From 62a079a15b46925283581f6caaf631b5a4558927 Mon Sep 17 00:00:00 2001
From: wlzboy <66905212@qq.com>
Date: 星期三, 24 九月 2025 11:00:10 +0800
Subject: [PATCH] feat: 初始化app
---
app/uni_modules/uni-data-select/package.json | 85
app/pages.json | 102
app/uni_modules/uni-segmented-control/package.json | 87
app/uni_modules/uni-popup/components/uni-popup/uni-popup.vue | 473
app/README.md | 51
app/uni_modules/uni-file-picker/components/uni-file-picker/upload-file.vue | 325
app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar-item.vue | 177
app/uni_modules/uni-data-checkbox/components/uni-data-checkbox/uni-data-checkbox.vue | 821
app/uni_modules/uni-link/changelog.md | 17
app/uni_modules/uni-pagination/package.json | 83
app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/zh-Hant.json | 22
ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTask.java | 60
app/uni_modules/uni-easyinput/changelog.md | 97
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskVehicleService.java | 150
app/uni_modules/uni-popup/components/uni-popup/keypress.js | 45
app/components/uni-section/uni-section.vue | 167
app/uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue | 667
app/uni_modules/uni-table/components/uni-td/uni-td.vue | 90
app/uni_modules/uni-search-bar/components/uni-search-bar/i18n/en.json | 4
app/uni_modules/uni-table/components/uni-tbody/uni-tbody.vue | 29
app/uni_modules/uni-fav/components/uni-fav/uni-fav.vue | 161
app/uni_modules/uni-popup/package.json | 87
ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskCreateVO.java | 57
app/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-picker.js | 622
app/uni_modules/uni-popup/components/uni-popup-message/uni-popup-message.vue | 143
app/uni_modules/uni-swiper-dot/package.json | 87
app/uni_modules/uni-load-more/readme.md | 14
app/uni_modules/uni-breadcrumb/readme.md | 66
app/utils/errorCode.js | 6
app/uni_modules/uni-row/package.json | 87
ruoyi-system/src/main/resources/mapper/system/SysTaskVehicleMapper.xml | 12
app/uni_modules/uni-breadcrumb/package.json | 88
app/uni_modules/uni-data-picker/components/uni-data-picker/keypress.js | 45
ruoyi-ui/src/views/task/vehicle/index.vue | 525
app/pages/common/webview/index.vue | 34
app/pages/work/index.vue | 183
app/uni_modules/uni-drawer/components/uni-drawer/keypress.js | 45
app/uni_modules/uni-file-picker/components/uni-file-picker/choose-and-upload-file.js | 224
app/uni_modules/uni-number-box/package.json | 85
app/uni_modules/uni-tooltip/readme.md | 8
sql/时间字段更新说明.md | 117
app/uni_modules/uni-goods-nav/package.json | 88
app/uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list-item.vue | 144
app/uni_modules/uni-transition/readme.md | 11
app/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hans.json | 7
app/store/getters.js | 8
app/uni_modules/uni-countdown/package.json | 86
app/utils/storage.js | 32
app/uni_modules/uni-combox/components/uni-combox/uni-combox.vue | 294
app/uni_modules/uni-badge/changelog.md | 33
app/uni_modules/uni-scss/package.json | 82
app/uni_modules/uni-data-picker/changelog.md | 75
app/uni_modules/uni-table/components/uni-th/filter-dropdown.vue | 511
app/uni_modules/uni-list/package.json | 88
app/uni_modules/uni-breadcrumb/components/uni-breadcrumb-item/uni-breadcrumb-item.vue | 121
app/uni_modules/uni-swipe-action/package.json | 87
app/utils/upload.js | 70
app/uni_modules/uni-forms/components/uni-forms/uni-forms.vue | 397
app/uni_modules/uni-segmented-control/readme.md | 13
app/uni_modules/uni-calendar/changelog.md | 26
app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/isPC.js | 12
app/static/images/tabbar/mine_.png | 0
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/任务车辆关联插入问题修复说明.md | 190
app/api/system/user.js | 41
app/uni_modules/uni-row/readme.md | 10
app/uni_modules/uni-scss/index.scss | 1
app/uni_modules/uni-fab/package.json | 84
app/uni_modules/uni-swiper-dot/components/uni-swiper-dot/uni-swiper-dot.vue | 218
app/uni_modules/uni-load-more/components/uni-load-more/uni-load-more.vue | 399
app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpalipay.js | 195
app/uni_modules/uni-scss/styles/setting/_color.scss | 66
app/uni_modules/uni-popup/changelog.md | 68
app/uni_modules/uni-card/components/uni-card/uni-card.vue | 272
app/uni_modules/uni-link/package.json | 87
app/App.vue | 34
app/uni_modules/uni-table/components/uni-thead/uni-thead.vue | 129
app/static/images/tabbar/work_.png | 0
app/permission.js | 39
app/uni_modules/uni-list/changelog.md | 46
ruoyi-ui/public/map-config.js | 64
app/uni_modules/uni-calendar/components/uni-calendar/i18n/index.js | 8
app/static/images/tabbar/work.png | 0
app/uni_modules/uni-calendar/components/uni-calendar/i18n/en.json | 12
app/uni_modules/uni-goods-nav/components/uni-goods-nav/uni-goods-nav.vue | 229
app/uni_modules/uni-scss/styles/setting/_radius.scss | 55
app/uni_modules/uni-title/readme.md | 14
app/uni_modules/uni-icons/readme.md | 8
app/uni_modules/uni-countdown/components/uni-countdown/i18n/en.json | 6
app/uni_modules/uni-search-bar/components/uni-search-bar/uni-search-bar.vue | 298
app/uni_modules/uni-pagination/components/uni-pagination/i18n/fr.json | 5
app/uni_modules/uni-countdown/components/uni-countdown/uni-countdown.vue | 267
app/uni_modules/uni-calendar/components/uni-calendar/uni-calendar.vue | 566
app/uni_modules/uni-collapse/package.json | 89
app/uni_modules/uni-load-more/components/uni-load-more/i18n/index.js | 8
app/uni_modules/uni-badge/readme.md | 10
app/uni_modules/uni-search-bar/components/uni-search-bar/i18n/index.js | 8
app/uni_modules/uni-popup/components/uni-popup-dialog/keypress.js | 45
app/static/images/banner/banner01.jpg | 0
ruoyi-ui/src/views/task/vehicle/列表显示优化说明.md | 244
app/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hant.json | 7
app/utils/auth.js | 13
app/uni_modules/uni-grid/components/uni-grid-item/uni-grid-item.vue | 127
app/uni_modules/uni-pagination/components/uni-pagination/uni-pagination.vue | 465
app/uni_modules/uni-pagination/changelog.md | 27
app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/index.js | 8
app/uni_modules/uni-icons/components/uni-icons/icons.js | 1169 +
app/uni_modules/uni-popup/components/uni-popup/popup.js | 26
app/static/images/tabbar/mine.png | 0
app/uni_modules/uni-data-select/readme.md | 8
ruoyi-system/src/main/java/com/ruoyi/system/domain/VehicleInfo.java | 26
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskMapper.java | 8
sql/add_gps_coordinates.sql | 22
app/uni_modules/uni-fav/components/uni-fav/i18n/en.json | 4
app/uni_modules/uni-load-more/components/uni-load-more/i18n/en.json | 5
ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskVehicleController.java | 13
app/uni_modules/uni-easyinput/package.json | 87
app/uni_modules/uni-nav-bar/package.json | 86
app/uni_modules/uni-file-picker/readme.md | 11
app/uni_modules/uni-badge/package.json | 85
sql/fix_task_vehicle_insert.sql | 28
app/uni_modules/uni-scss/styles/index.scss | 7
app/static/scss/index.scss | 6
app/static/logo200.png | 0
app/uni_modules/uni-dateformat/components/uni-dateformat/uni-dateformat.vue | 88
app/uni_modules/uni-fab/changelog.md | 23
app/uni_modules/uni-card/changelog.md | 26
app/uni_modules/uni-card/readme.md | 12
sql/task_tables.sql | 11
app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/bindingx.js | 302
app/uni_modules/uni-row/components/uni-col/uni-col.vue | 317
app/uni_modules/uni-row/changelog.md | 10
app/static/images/profile.jpg | 0
app/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/en.json | 6
app/uni_modules/uni-list/readme.md | 346
app/uni_modules/uni-easyinput/components/uni-easyinput/common.js | 56
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/允许搜索所有车辆修改说明.md | 242
app/uni_modules/uni-dateformat/readme.md | 11
app/uni_modules/uni-forms/readme.md | 23
app/uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue | 657
app/uni_modules/uni-breadcrumb/changelog.md | 6
app/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hant.json | 5
app/uni_modules/uni-icons/package.json | 86
app/uni_modules/uni-list/components/uni-list/uni-list.vue | 123
app/uni_modules/uni-notice-bar/readme.md | 13
app/pages/common/textview/index.vue | 43
app/uni_modules/uni-countdown/components/uni-countdown/i18n/index.js | 8
app/uni_modules/uni-tooltip/package.json | 88
app/uni_modules/uni-data-picker/readme.md | 22
app/uni_modules/uni-dateformat/components/uni-dateformat/date-format.js | 200
app/uni_modules/uni-transition/components/uni-transition/createAnimation.js | 131
app/plugins/tab.js | 30
app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/time-picker.vue | 934 +
app/uni_modules/uni-icons/components/uni-icons/uniicons.ttf | 0
app/uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue | 275
ruoyi-ui/src/views/task/general/detail.vue | 26
app/uni_modules/uni-data-checkbox/readme.md | 18
app/uni_modules/uni-forms/changelog.md | 92
ruoyi-ui/vue.config.js | 8
app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpwxs.js | 84
app/uni_modules/uni-tooltip/components/uni-tooltip/uni-tooltip.vue | 68
app/uni_modules/uni-grid/changelog.md | 13
app/uni_modules/uni-scss/styles/setting/_space.scss | 56
app/static/scss/colorui.css | 5142 ++++++
app/uni_modules/uni-swipe-action/components/uni-swipe-action/uni-swipe-action.vue | 60
app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue | 1026 +
app/uni_modules/uni-notice-bar/changelog.md | 18
app/uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hant.json | 12
app/uni_modules/uni-dateformat/changelog.md | 10
ruoyi-ui/src/views/system/vehicle/部门功能优化说明.md | 170
app/uni_modules/uni-icons/components/uni-icons/uniicons.css | 663
app/uni_modules/uni-steps/changelog.md | 16
app/uni_modules/uni-pagination/components/uni-pagination/i18n/zh-Hans.json | 5
app/uni_modules/uni-combox/package.json | 90
app/uni_modules/uni-badge/components/uni-badge/uni-badge.vue | 268
app/store/index.js | 15
app/uni_modules/uni-datetime-picker/package.json | 87
app/uni_modules/uni-indexed-list/package.json | 89
sql/task_menu.sql | 70
app/uni_modules/uni-link/components/uni-link/uni-link.vue | 128
ruoyi-system/src/main/java/com/ruoyi/system/utils/TaskCodeGenerator.java | 36
app/uni_modules/uni-list/components/uni-list-ad/uni-list-ad.vue | 107
app/uni_modules/uni-drawer/changelog.md | 13
app/uni_modules/uni-table/i18n/es.json | 9
app/uni_modules/uni-title/changelog.md | 10
app/uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hans.json | 4
app/uni_modules/uni-fav/components/uni-fav/i18n/zh-Hant.json | 4
ruoyi-ui/src/views/task/general/分配车辆问题修复说明.md | 214
app/uni_modules/uni-table/components/uni-tr/uni-tr.vue | 171
app/utils/common.js | 54
app/LICENSE | 21
app/plugins/modal.js | 74
app/uni_modules/uni-group/package.json | 87
app/uni_modules/uni-indexed-list/readme.md | 11
app/uni_modules/uni-swipe-action/readme.md | 11
app/static/images/banner/banner03.jpg | 0
app/uni_modules/uni-list/components/uni-list-item/uni-list-item.vue | 534
sql/GPS坐标功能说明.md | 168
app/uni_modules/uni-search-bar/changelog.md | 33
app/pages/mine/avatar/index.vue | 631
app/uni_modules/uni-data-checkbox/package.json | 84
app/uni_modules/uni-calendar/components/uni-calendar/util.js | 360
app/plugins/index.js | 14
app/uni_modules/uni-table/components/uni-table/uni-table.vue | 455
app/uni_modules/uni-pagination/components/uni-pagination/i18n/index.js | 12
app/uni_modules/uni-fav/changelog.md | 19
app/uni_modules/uni-load-more/changelog.md | 19
app/uni_modules/uni-icons/components/uni-icons/uni-icons.vue | 96
app/pages/mine/help/index.vue | 112
app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/en.json | 22
app/pages/register.vue | 196
app/uni_modules/uni-pagination/readme.md | 11
app/uni_modules/uni-scss/styles/setting/_border.scss | 3
app/uni_modules/uni-rate/package.json | 88
ruoyi-system/src/main/resources/mapper/system/VehicleInfoMapper.xml | 29
app/uni_modules/uni-collapse/changelog.md | 36
app/uni_modules/uni-collapse/components/uni-collapse/uni-collapse.vue | 147
app/uni_modules/uni-steps/readme.md | 13
app/uni_modules/uni-title/components/uni-title/uni-title.vue | 171
app/uni_modules/uni-table/changelog.md | 27
app/uni_modules/uni-datetime-picker/readme.md | 21
app/uni_modules/uni-number-box/readme.md | 13
app/manifest.json | 69
app/uni_modules/uni-table/i18n/en.json | 9
app/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.scss | 58
app/uni_modules/uni-tag/components/uni-tag/uni-tag.vue | 252
app/utils/request.js | 73
ruoyi-ui/src/permission.js | 11
app/uni_modules/uni-fav/readme.md | 10
app/uni_modules/uni-search-bar/readme.md | 14
app/pages/mine/about/index.vue | 75
RuoYi-App-master.zip | 0
app/uni_modules/uni-transition/components/uni-transition/uni-transition.vue | 281
app/uni_modules/uni-card/package.json | 90
app/uni_modules/uni-pagination/components/uni-pagination/i18n/zh-Hant.json | 5
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskVehicleMapper.java | 5
app/uni_modules/uni-file-picker/components/uni-file-picker/utils.js | 109
app/uni_modules/uni-nav-bar/changelog.md | 51
app/uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list.vue | 367
app/uni_modules/uni-breadcrumb/components/uni-breadcrumb/uni-breadcrumb.vue | 41
app/static/images/tabbar/home_.png | 0
app/uni_modules/uni-drawer/readme.md | 10
app/uni_modules/uni-forms/components/uni-forms/validate.js | 486
app/uni_modules/uni-fab/components/uni-fab/uni-fab.vue | 491
app/uni_modules/uni-notice-bar/components/uni-notice-bar/uni-notice-bar.vue | 426
app/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.vue | 593
app/uni_modules/uni-table/readme.md | 13
app/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/index.js | 8
app/uni_modules/uni-link/readme.md | 11
ruoyi-ui/src/router/index.js | 10
app/uni_modules/uni-forms/components/uni-forms/utils.js | 293
app/uni_modules/uni-rate/changelog.md | 25
app/pages/mine/setting/index.vue | 78
app/uni_modules/uni-scss/styles/setting/_text.scss | 24
app/uni_modules/uni-scss/variables.scss | 62
app/uni_modules/uni-swipe-action/changelog.md | 43
ruoyi-ui/src/views/task/vehicle/改进说明.md | 126
app/uni_modules/uni-popup/components/uni-popup/i18n/en.json | 7
app/static/images/banner/banner02.jpg | 0
ruoyi-ui/src/views/task/general/index.vue | 150
app/uni_modules/uni-scss/styles/tools/functions.scss | 19
app/uni_modules/uni-countdown/components/uni-countdown/i18n/zh-Hans.json | 6
app/uni_modules/uni-table/i18n/zh-Hans.json | 9
app/plugins/auth.js | 60
app/uni_modules/uni-fav/package.json | 89
app/uni_modules/uni-fav/components/uni-fav/i18n/index.js | 8
app/static/logo.png | 0
app/uni_modules/uni-collapse/readme.md | 12
app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpother.js | 260
app/pages/mine/pwd/index.vue | 85
app/uni.scss | 64
app/uni_modules/uni-scss/theme.scss | 31
app/uni_modules/uni-file-picker/changelog.md | 67
app/uni_modules/uni-group/changelog.md | 16
app/uni_modules/uni-collapse/components/uni-collapse-item/uni-collapse-item.vue | 402
app/uni_modules/uni-table/i18n/zh-Hant.json | 9
ruoyi-ui/public/h5-test.html | 82
ruoyi-common/src/main/java/com/ruoyi/common/utils/GpsDistanceUtils.java | 132
app/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/zh-Hant.json | 6
app/uni_modules/uni-transition/changelog.md | 20
app/uni_modules/uni-tag/package.json | 87
app/uni_modules/uni-group/components/uni-group/uni-group.vue | 134
app/pages/mine/info/index.vue | 44
app/uni_modules/uni-table/components/uni-tr/table-checkbox.vue | 179
app/uni_modules/uni-scss/styles/setting/_variables.scss | 146
app/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.vue | 323
app/utils/permission.js | 51
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java | 110
ruoyi-ui/src/views/task/general/GPS坐标功能使用说明.md | 121
ruoyi-system/src/main/resources/mapper/system/SysTaskMapper.xml | 42
app/pages/login.vue | 202
ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskUpdateVO.java | 45
app/uni_modules/uni-steps/components/uni-steps/uni-steps.vue | 269
app/uni_modules/uni-calendar/package.json | 85
app/uni_modules/uni-file-picker/package.json | 83
app/uni_modules/uni-tag/changelog.md | 21
app/uni_modules/uni-file-picker/components/uni-file-picker/upload-image.vue | 292
app/uni_modules/uni-popup/readme.md | 17
app/uni_modules/uni-data-picker/package.json | 90
ruoyi-ui/src/views/task/vehicle/编辑界面优化说明.md | 169
app/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/zh-Hans.json | 6
sql/fix_update_time.sql | 12
app/uni_modules/uni-scss/readme.md | 4
app/static/font/iconfont.ttf | 0
app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/render.js | 270
app/uni_modules/uni-data-picker/components/uni-data-picker/uni-data-picker.vue | 551
ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskVehicleManagementController.java | 278
app/uni_modules/uni-load-more/package.json | 86
app/uni_modules/uni-pagination/components/uni-pagination/i18n/en.json | 5
app/uni_modules/uni-number-box/changelog.md | 25
app/uni_modules/uni-transition/package.json | 87
app/uni_modules/uni-swiper-dot/changelog.md | 12
app/main.js | 17
app/uni_modules/uni-rate/readme.md | 12
app/uni_modules/uni-indexed-list/changelog.md | 17
ruoyi-admin/src/main/resources/application.yml | 2
app/uni_modules/uni-calendar/readme.md | 103
app/uni_modules/uni-segmented-control/components/uni-segmented-control/uni-segmented-control.vue | 145
app/static/font/iconfont.css | 90
app/uni_modules/uni-grid/readme.md | 11
app/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-nav-bar.vue | 357
ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskVehicle.java | 13
app/uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hant.json | 4
app/uni_modules/uni-data-checkbox/changelog.md | 45
app/uni_modules/uni-tooltip/changelog.md | 10
app/uni_modules/uni-countdown/changelog.md | 24
app/static/index.html | 20
app/uni_modules/uni-calendar/components/uni-calendar/uni-calendar-item.vue | 187
app/uni_modules/uni-fav/components/uni-fav/i18n/zh-Hans.json | 4
app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/uni-swipe-action-item.vue | 347
app/uni_modules/uni-grid/components/uni-grid/uni-grid.vue | 142
app/uni_modules/uni-segmented-control/changelog.md | 9
app/pages/mine/index.vue | 198
ruoyi-ui/src/api/task.js | 88
app/uni_modules/uni-popup/components/uni-popup-share/uni-popup-share.vue | 187
app/static/images/tabbar/home.png | 0
app/uni_modules/uni-group/readme.md | 9
app/uni_modules/uni-data-select/components/uni-data-select/uni-data-select.vue | 517
app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/util.js | 403
ruoyi-ui/src/views/task/vehicle/README.md | 117
app/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-status-bar.vue | 24
app/uni_modules/uni-fab/readme.md | 9
app/uni_modules/uni-swiper-dot/readme.md | 11
app/uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hans.json | 12
app/uni_modules/uni-table/package.json | 83
sql/task_dict_data.sql | 79
app/pages/mine/info/edit.vue | 127
app/uni_modules/uni-number-box/components/uni-number-box/uni-number-box.vue | 221
app/uni_modules/uni-scss/changelog.md | 8
ruoyi-ui/src/views/system/vehicle/index.vue | 72
app/api/login.js | 59
app/uni_modules/uni-dateformat/package.json | 88
app/store/modules/user.js | 98
app/uni_modules/uni-steps/package.json | 89
app/uni_modules/uni-goods-nav/changelog.md | 18
app/uni_modules/uni-countdown/components/uni-countdown/i18n/zh-Hant.json | 6
app/uni_modules/uni-table/i18n/index.js | 12
app/uni_modules/uni-rate/components/uni-rate/uni-rate.vue | 365
app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar.vue | 928 +
app/pages/index.vue | 43
app/uni_modules/uni-list/components/uni-list/uni-refresh.wxs | 87
app/static/scss/global.scss | 90
app/uni_modules/uni-popup/components/uni-popup/i18n/index.js | 8
app/uni_modules/uni-forms/package.json | 88
app/uni_modules/uni-grid/package.json | 86
app/uni_modules/uni-pagination/components/uni-pagination/i18n/es.json | 5
app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/wx.wxs | 341
app/uni_modules/uni-table/components/uni-th/uni-th.vue | 285
app/uni_modules/uni-combox/changelog.md | 15
ruoyi-ui/src/views/task/h5/create.vue | 1513 +
app/uni_modules/uni-row/components/uni-row/uni-row.vue | 190
app/uni_modules/uni-title/package.json | 88
app/uni_modules/uni-nav-bar/readme.md | 15
app/uni_modules/uni-search-bar/package.json | 89
app/utils/constant.js | 8
app/uni_modules/uni-easyinput/readme.md | 11
app/uni_modules/uni-data-select/changelog.md | 35
app/uni_modules/uni-icons/changelog.md | 22
app/static/favicon.ico | 0
app/uni_modules/uni-table/i18n/fr.json | 9
app/uni_modules/uni-drawer/package.json | 87
app/uni_modules/uni-list/components/uni-list/uni-refresh.vue | 65
app/uni_modules/uni-calendar/components/uni-calendar/calendar.js | 546
app/uni_modules/uni-datetime-picker/changelog.md | 133
app/.gitignore | 16
app/uni_modules/uni-notice-bar/package.json | 87
app/uni_modules/uni-goods-nav/readme.md | 10
app/uni_modules/uni-tag/readme.md | 13
ruoyi-ui/src/App.vue | 7
app/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hans.json | 5
app/uni_modules/uni-scss/styles/setting/_styles.scss | 167
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskVehicleServiceImpl.java | 301
app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/zh-Hans.json | 22
app/uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue | 627
app/config.js | 26
app/uni_modules/uni-countdown/readme.md | 10
app/uni_modules/uni-drawer/components/uni-drawer/uni-drawer.vue | 183
app/uni_modules/uni-combox/readme.md | 11
397 files changed, 51,189 insertions(+), 95 deletions(-)
diff --git a/RuoYi-App-master.zip b/RuoYi-App-master.zip
new file mode 100644
index 0000000..1f63ca8
--- /dev/null
+++ b/RuoYi-App-master.zip
Binary files differ
diff --git a/app/.gitignore b/app/.gitignore
new file mode 100644
index 0000000..59c9154
--- /dev/null
+++ b/app/.gitignore
@@ -0,0 +1,16 @@
+######################################################################
+# Build Tools
+
+/unpackage/*
+/node_modules/*
+
+######################################################################
+# Development Tools
+
+/.idea/*
+/.vscode/*
+/.hbuilderx/*
+
+package-lock.json
+yarn.lock
+
diff --git a/app/App.vue b/app/App.vue
new file mode 100644
index 0000000..797f513
--- /dev/null
+++ b/app/App.vue
@@ -0,0 +1,34 @@
+<script>
+ import config from './config'
+ import store from '@/store'
+ import { getToken } from '@/utils/auth'
+
+ export default {
+ onLaunch: function() {
+ this.initApp()
+ },
+ methods: {
+ // 鍒濆鍖栧簲鐢�
+ initApp() {
+ // 鍒濆鍖栧簲鐢ㄩ厤缃�
+ this.initConfig()
+ // 妫�鏌ョ敤鎴风櫥褰曠姸鎬�
+ //#ifdef H5
+ this.checkLogin()
+ //#endif
+ },
+ initConfig() {
+ this.globalData.config = config
+ },
+ checkLogin() {
+ if (!getToken()) {
+ this.$tab.reLaunch('/pages/login')
+ }
+ }
+ }
+ }
+</script>
+
+<style lang="scss">
+ @import '@/static/scss/index.scss'
+</style>
diff --git a/app/LICENSE b/app/LICENSE
new file mode 100644
index 0000000..2c46dba
--- /dev/null
+++ b/app/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2022 鑻ヤ緷
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/app/README.md b/app/README.md
new file mode 100644
index 0000000..d396dc7
--- /dev/null
+++ b/app/README.md
@@ -0,0 +1,51 @@
+<p align="center">
+ <img alt="logo" src="https://oscimg.oschina.net/oscnet/up-43e3941654fa3054c9684bf53d1b1d356a1.png">
+</p>
+<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v1.1.0</h1>
+<h4 align="center">鍩轰簬UniApp寮�鍙戠殑杞婚噺绾хЩ鍔ㄧ妗嗘灦</h4>
+<p align="center">
+ <a href="https://gitee.com/y_project/RuoYi-App/stargazers"><img src="https://gitee.com/y_project/RuoYi-App/badge/star.svg?theme=dark"></a>
+ <a href="https://gitee.com/y_project/RuoYi-App"><img src="https://img.shields.io/badge/RuoYi-v1.1.0-brightgreen.svg"></a>
+ <a href="https://gitee.com/y_project/RuoYi-App/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a>
+</p>
+
+## 骞冲彴绠�浠�
+
+RuoYi App 绉诲姩瑙e喅鏂规锛岄噰鐢╱niapp妗嗘灦锛屼竴浠戒唬鐮佸缁堢閫傞厤锛屽悓鏃舵敮鎸丄PP銆佸皬绋嬪簭銆丠5锛佸疄鐜颁簡涓嶽RuoYi-Vue](https://gitee.com/y_project/RuoYi-Vue)銆乕RuoYi-Cloud](https://gitee.com/y_project/RuoYi-Cloud)瀹岀編瀵规帴鐨勭Щ鍔ㄨВ鍐虫柟妗堬紒鐩墠宸茬粡瀹炵幇鐧诲綍銆佹垜鐨勩�佸伐浣滃彴銆佺紪杈戣祫鏂欍�佸ご鍍忎慨鏀广�佸瘑鐮佷慨鏀广�佸父瑙侀棶棰樸�佸叧浜庢垜浠瓑鍩虹鍔熻兘銆�
+
+* 閰嶅鍚庣浠g爜浠撳簱鍦板潃[RuoYi-Vue](https://gitee.com/y_project/RuoYi-Vue) 鎴� [RuoYi-Cloud](https://github.com/yangzongzhuan/RuoYi-Cloud) 鐗堟湰銆�
+* 搴旂敤妗嗘灦鍩轰簬[uniapp](https://uniapp.dcloud.net.cn/)锛屾敮鎸佸皬绋嬪簭銆丠5銆丄ndroid鍜孖OS銆�
+* 鍓嶇缁勪欢閲囩敤[uni-ui](https://github.com/dcloudio/uni-ui)锛屽叏绔吋瀹圭殑楂樻�ц兘UI妗嗘灦銆�
+* 闃块噷浜戞姌鎵e満锛歔鐐规垜杩涘叆](http://aly.ruoyi.vip)锛岃吘璁簯绉掓潃鍦猴細[鐐规垜杩涘叆](http://txy.ruoyi.vip)
+
+
+## 鎶�鏈枃妗�
+
+- 瀹樼綉缃戠珯锛歔http://ruoyi.vip](http://ruoyi.vip)
+- 鏂囨。鍦板潃锛歔http://doc.ruoyi.vip](http://doc.ruoyi.vip)
+- H5椤典綋楠岋細[http://h5.ruoyi.vip](http://h5.ruoyi.vip)
+- QQ浜ゆ祦缇わ細 鈶�133713780(婊�)銆佲憽146013835(婊�)銆佲憿189091635
+- 灏忕▼搴忎綋楠�
+
+<img src="https://oscimg.oschina.net/oscnet/up-26c76dc90b92acdbd9ac8cd5252f07c8ad9.jpg" alt="灏忕▼搴忔紨绀�"/>
+
+
+## 婕旂ず鍥�
+
+<table>
+ <tr>
+ <td><img src="https://oscimg.oschina.net/oscnet/up-21f6f842fdc94540469b4eb43fdadbaf7f8.png"/></td>
+ <td><img src="https://oscimg.oschina.net/oscnet/up-a6f23cf9a371a30165e135eff6d9ae89a9d.png"/></td>
+ <td><img src="https://oscimg.oschina.net/oscnet/up-ff5f62016bf6624c1ff27eee57499dccd44.png"/></td>
+ </tr>
+ <tr>
+ <td><img src="https://oscimg.oschina.net/oscnet/up-b9a582fdb26ec69d407fabd044d2c8494df.png"/></td>
+ <td><img src="https://oscimg.oschina.net/oscnet/up-96427ee08fca29d77934cfc8d1b1a637cef.png"/></td>
+ <td><img src="https://oscimg.oschina.net/oscnet/up-5fdadc582d24cccd7727030d397b63185a3.png"/></td>
+ </tr>
+ <tr>
+ <td><img src="https://oscimg.oschina.net/oscnet/up-0a36797b6bcc50c36d40c3c782665b89efc.png"/></td>
+ <td><img src="https://oscimg.oschina.net/oscnet/up-d77995cc00687cedd00d5ac7d68a07ea276.png"/></td>
+ <td><img src="https://oscimg.oschina.net/oscnet/up-fa8f5ab20becf59b4b38c1b92a9989e7109.png"/></td>
+ </tr>
+</table>
diff --git a/app/api/login.js b/app/api/login.js
new file mode 100644
index 0000000..6ce7e7c
--- /dev/null
+++ b/app/api/login.js
@@ -0,0 +1,59 @@
+import request from '@/utils/request'
+
+// 鐧诲綍鏂规硶
+export function login(username, password, code, uuid) {
+ const data = {
+ username,
+ password,
+ code,
+ uuid
+ }
+ return request({
+ 'url': '/login',
+ headers: {
+ isToken: false
+ },
+ 'method': 'post',
+ 'data': data
+ })
+}
+
+// 娉ㄥ唽鏂规硶
+export function register(data) {
+ return request({
+ url: '/register',
+ headers: {
+ isToken: false
+ },
+ method: 'post',
+ data: data
+ })
+}
+
+// 鑾峰彇鐢ㄦ埛璇︾粏淇℃伅
+export function getInfo() {
+ return request({
+ 'url': '/getInfo',
+ 'method': 'get'
+ })
+}
+
+// 閫�鍑烘柟娉�
+export function logout() {
+ return request({
+ 'url': '/logout',
+ 'method': 'post'
+ })
+}
+
+// 鑾峰彇楠岃瘉鐮�
+export function getCodeImg() {
+ return request({
+ 'url': '/captchaImage',
+ headers: {
+ isToken: false
+ },
+ method: 'get',
+ timeout: 20000
+ })
+}
diff --git a/app/api/system/user.js b/app/api/system/user.js
new file mode 100644
index 0000000..0e307ea
--- /dev/null
+++ b/app/api/system/user.js
@@ -0,0 +1,41 @@
+import upload from '@/utils/upload'
+import request from '@/utils/request'
+
+// 鐢ㄦ埛瀵嗙爜閲嶇疆
+export function updateUserPwd(oldPassword, newPassword) {
+ const data = {
+ oldPassword,
+ newPassword
+ }
+ return request({
+ url: '/system/user/profile/updatePwd',
+ method: 'put',
+ data: data
+ })
+}
+
+// 鏌ヨ鐢ㄦ埛涓汉淇℃伅
+export function getUserProfile() {
+ return request({
+ url: '/system/user/profile',
+ method: 'get'
+ })
+}
+
+// 淇敼鐢ㄦ埛涓汉淇℃伅
+export function updateUserProfile(data) {
+ return request({
+ url: '/system/user/profile',
+ method: 'put',
+ data: data
+ })
+}
+
+// 鐢ㄦ埛澶村儚涓婁紶
+export function uploadAvatar(data) {
+ return upload({
+ url: '/system/user/profile/avatar',
+ name: data.name,
+ filePath: data.filePath
+ })
+}
diff --git a/app/components/uni-section/uni-section.vue b/app/components/uni-section/uni-section.vue
new file mode 100644
index 0000000..9a52e0b
--- /dev/null
+++ b/app/components/uni-section/uni-section.vue
@@ -0,0 +1,167 @@
+<template>
+ <view class="uni-section">
+ <view class="uni-section-header" @click="onClick">
+ <view class="uni-section-header__decoration" v-if="type" :class="type" />
+ <slot v-else name="decoration"></slot>
+
+ <view class="uni-section-header__content">
+ <text :style="{'font-size':titleFontSize,'color':titleColor}" class="uni-section__content-title" :class="{'distraction':!subTitle}">{{ title }}</text>
+ <text v-if="subTitle" :style="{'font-size':subTitleFontSize,'color':subTitleColor}" class="uni-section-header__content-sub">{{ subTitle }}</text>
+ </view>
+
+ <view class="uni-section-header__slot-right">
+ <slot name="right"></slot>
+ </view>
+ </view>
+
+ <view class="uni-section-content" :style="{padding: _padding}">
+ <slot />
+ </view>
+ </view>
+</template>
+
+<script>
+
+ /**
+ * Section 鏍囬鏍�
+ * @description 鏍囬鏍�
+ * @property {String} type = [line|circle|square] 鏍囬瑁呴グ绫诲瀷
+ * @value line 绔栫嚎
+ * @value circle 鍦嗗舰
+ * @value square 姝f柟褰�
+ * @property {String} title 涓绘爣棰�
+ * @property {String} titleFontSize 涓绘爣棰樺瓧浣撳ぇ灏�
+ * @property {String} titleColor 涓绘爣棰樺瓧浣撻鑹�
+ * @property {String} subTitle 鍓爣棰�
+ * @property {String} subTitleFontSize 鍓爣棰樺瓧浣撳ぇ灏�
+ * @property {String} subTitleColor 鍓爣棰樺瓧浣撻鑹�
+ * @property {String} padding 榛樿鎻掓Ы padding
+ */
+
+ export default {
+ name: 'UniSection',
+ emits:['click'],
+ props: {
+ type: {
+ type: String,
+ default: ''
+ },
+ title: {
+ type: String,
+ required: true,
+ default: ''
+ },
+ titleFontSize: {
+ type: String,
+ default: '14px'
+ },
+ titleColor:{
+ type: String,
+ default: '#333'
+ },
+ subTitle: {
+ type: String,
+ default: ''
+ },
+ subTitleFontSize: {
+ type: String,
+ default: '12px'
+ },
+ subTitleColor: {
+ type: String,
+ default: '#999'
+ },
+ padding: {
+ type: [Boolean, String],
+ default: false
+ }
+ },
+ computed:{
+ _padding(){
+ if(typeof this.padding === 'string'){
+ return this.padding
+ }
+
+ return this.padding?'10px':''
+ }
+ },
+ watch: {
+ title(newVal) {
+ if (uni.report && newVal !== '') {
+ uni.report('title', newVal)
+ }
+ }
+ },
+ methods: {
+ onClick() {
+ this.$emit('click')
+ }
+ }
+ }
+</script>
+<style lang="scss" >
+ $uni-primary: #2979ff !default;
+
+ .uni-section {
+ background-color: #fff;
+ .uni-section-header {
+ position: relative;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ align-items: center;
+ padding: 12px 10px;
+ font-weight: normal;
+
+ &__decoration{
+ margin-right: 6px;
+ background-color: $uni-primary;
+ &.line {
+ width: 4px;
+ height: 12px;
+ border-radius: 10px;
+ }
+
+ &.circle {
+ width: 8px;
+ height: 8px;
+ border-top-right-radius: 50px;
+ border-top-left-radius: 50px;
+ border-bottom-left-radius: 50px;
+ border-bottom-right-radius: 50px;
+ }
+
+ &.square {
+ width: 8px;
+ height: 8px;
+ }
+ }
+
+ &__content {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: column;
+ flex: 1;
+ color: #333;
+
+ .distraction {
+ flex-direction: row;
+ align-items: center;
+ }
+ &-sub {
+ margin-top: 2px;
+ }
+ }
+
+ &__slot-right{
+ font-size: 14px;
+ }
+ }
+
+ .uni-section-content{
+ font-size: 14px;
+ }
+ }
+</style>
diff --git a/app/config.js b/app/config.js
new file mode 100644
index 0000000..6f9236d
--- /dev/null
+++ b/app/config.js
@@ -0,0 +1,26 @@
+// 搴旂敤鍏ㄥ眬閰嶇疆
+module.exports = {
+ baseUrl: 'https://vue.ruoyi.vip/prod-api',
+ // baseUrl: 'http://localhost:8080',
+ // 搴旂敤淇℃伅
+ appInfo: {
+ // 搴旂敤鍚嶇О
+ name: "ruoyi-app",
+ // 搴旂敤鐗堟湰
+ version: "1.1.0",
+ // 搴旂敤logo
+ logo: "/static/logo.png",
+ // 瀹樻柟缃戠珯
+ site_url: "http://ruoyi.vip",
+ // 鏀跨瓥鍗忚
+ agreements: [{
+ title: "闅愮鏀跨瓥",
+ url: "https://ruoyi.vip/protocol.html"
+ },
+ {
+ title: "鐢ㄦ埛鏈嶅姟鍗忚",
+ url: "https://ruoyi.vip/protocol.html"
+ }
+ ]
+ }
+}
diff --git a/app/main.js b/app/main.js
new file mode 100644
index 0000000..3985b1b
--- /dev/null
+++ b/app/main.js
@@ -0,0 +1,17 @@
+import Vue from 'vue'
+import App from './App'
+import store from './store' // store
+import plugins from './plugins' // plugins
+import './permission' // permission
+Vue.use(plugins)
+
+Vue.config.productionTip = false
+Vue.prototype.$store = store
+
+App.mpType = 'app'
+
+const app = new Vue({
+ ...App
+})
+
+app.$mount()
diff --git a/app/manifest.json b/app/manifest.json
new file mode 100644
index 0000000..8a86db5
--- /dev/null
+++ b/app/manifest.json
@@ -0,0 +1,69 @@
+{
+ "name" : "鑻ヤ緷绉诲姩绔�",
+ "appid" : "__UNI__25A9D80",
+ "description" : "",
+ "versionName" : "1.1.0",
+ "versionCode" : "100",
+ "transformPx" : false,
+ "app-plus" : {
+ "usingComponents" : true,
+ "nvueCompiler" : "uni-app",
+ "splashscreen" : {
+ "alwaysShowBeforeRender" : true,
+ "waiting" : true,
+ "autoclose" : true,
+ "delay" : 0
+ },
+ "modules" : {},
+ "distribute" : {
+ "android" : {
+ "permissions" : [
+ "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
+ "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
+ "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
+ "<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
+ "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
+ "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
+ "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
+ "<uses-permission android:name=\"android.permission.CAMERA\"/>",
+ "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
+ "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
+ "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
+ "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
+ "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
+ "<uses-feature android:name=\"android.hardware.camera\"/>",
+ "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
+ ]
+ },
+ "ios" : {},
+ "sdkConfigs" : {}
+ }
+ },
+ "quickapp" : {},
+ "mp-weixin" : {
+ "appid" : "wxccd7e2a0911b3397",
+ "setting" : {
+ "urlCheck" : false,
+ "es6" : false,
+ "minified" : true,
+ "postcss" : true
+ },
+ "optimization" : {
+ "subPackages" : true
+ },
+ "usingComponents" : true
+ },
+ "vueVersion" : "2",
+ "h5" : {
+ "template" : "static/index.html",
+ "devServer" : {
+ "port" : 9090,
+ "https" : false
+ },
+ "title" : "RuoYi-App",
+ "router" : {
+ "mode" : "hash",
+ "base" : "./"
+ }
+ }
+}
diff --git a/app/pages.json b/app/pages.json
new file mode 100644
index 0000000..333251c
--- /dev/null
+++ b/app/pages.json
@@ -0,0 +1,102 @@
+{
+ "pages": [{
+ "path": "pages/login",
+ "style": {
+ "navigationBarTitleText": "鐧诲綍"
+ }
+ }, {
+ "path": "pages/register",
+ "style": {
+ "navigationBarTitleText": "娉ㄥ唽"
+ }
+ }, {
+ "path": "pages/index",
+ "style": {
+ "navigationBarTitleText": "鑻ヤ緷绉诲姩绔鏋�",
+ "navigationStyle": "custom"
+ }
+ }, {
+ "path": "pages/work/index",
+ "style": {
+ "navigationBarTitleText": "宸ヤ綔鍙�"
+ }
+ }, {
+ "path": "pages/mine/index",
+ "style": {
+ "navigationBarTitleText": "鎴戠殑"
+ }
+ }, {
+ "path": "pages/mine/avatar/index",
+ "style": {
+ "navigationBarTitleText": "淇敼澶村儚"
+ }
+ }, {
+ "path": "pages/mine/info/index",
+ "style": {
+ "navigationBarTitleText": "涓汉淇℃伅"
+ }
+ }, {
+ "path": "pages/mine/info/edit",
+ "style": {
+ "navigationBarTitleText": "缂栬緫璧勬枡"
+ }
+ }, {
+ "path": "pages/mine/pwd/index",
+ "style": {
+ "navigationBarTitleText": "淇敼瀵嗙爜"
+ }
+ }, {
+ "path": "pages/mine/setting/index",
+ "style": {
+ "navigationBarTitleText": "搴旂敤璁剧疆"
+ }
+ }, {
+ "path": "pages/mine/help/index",
+ "style": {
+ "navigationBarTitleText": "甯歌闂"
+ }
+ }, {
+ "path": "pages/mine/about/index",
+ "style": {
+ "navigationBarTitleText": "鍏充簬鎴戜滑"
+ }
+ }, {
+ "path": "pages/common/webview/index",
+ "style": {
+ "navigationBarTitleText": "娴忚缃戦〉"
+ }
+ }, {
+ "path": "pages/common/textview/index",
+ "style": {
+ "navigationBarTitleText": "娴忚鏂囨湰"
+ }
+ }],
+ "tabBar": {
+ "color": "#000000",
+ "selectedColor": "#000000",
+ "borderStyle": "white",
+ "backgroundColor": "#ffffff",
+ "list": [{
+ "pagePath": "pages/index",
+ "iconPath": "static/images/tabbar/home.png",
+ "selectedIconPath": "static/images/tabbar/home_.png",
+ "text": "棣栭〉"
+ }, {
+ "pagePath": "pages/work/index",
+ "iconPath": "static/images/tabbar/work.png",
+ "selectedIconPath": "static/images/tabbar/work_.png",
+ "text": "宸ヤ綔鍙�"
+ }, {
+ "pagePath": "pages/mine/index",
+ "iconPath": "static/images/tabbar/mine.png",
+ "selectedIconPath": "static/images/tabbar/mine_.png",
+ "text": "鎴戠殑"
+ }
+ ]
+ },
+ "globalStyle": {
+ "navigationBarTextStyle": "black",
+ "navigationBarTitleText": "RuoYi",
+ "navigationBarBackgroundColor": "#FFFFFF"
+ }
+}
diff --git a/app/pages/common/textview/index.vue b/app/pages/common/textview/index.vue
new file mode 100644
index 0000000..e9b05fb
--- /dev/null
+++ b/app/pages/common/textview/index.vue
@@ -0,0 +1,43 @@
+<template>
+ <view>
+ <uni-card class="view-title" :title="title">
+ <text class="uni-body view-content">{{ content }}</text>
+ </uni-card>
+ </view>
+</template>
+
+<script>
+ export default {
+ data() {
+ return {
+ title: '',
+ content: ''
+ }
+ },
+ onLoad(options) {
+ this.title = options.title
+ this.content = options.content
+ uni.setNavigationBarTitle({
+ title: options.title
+ })
+ }
+ }
+</script>
+
+<style scoped>
+ page {
+ background-color: #ffffff;
+ }
+
+ .view-title {
+ font-weight: bold;
+ }
+
+ .view-content {
+ font-size: 26rpx;
+ padding: 12px 5px 0;
+ color: #333;
+ line-height: 24px;
+ font-weight: normal;
+ }
+</style>
diff --git a/app/pages/common/webview/index.vue b/app/pages/common/webview/index.vue
new file mode 100644
index 0000000..8388c76
--- /dev/null
+++ b/app/pages/common/webview/index.vue
@@ -0,0 +1,34 @@
+<template>
+ <view v-if="params.url">
+ <web-view :webview-styles="webviewStyles" :src="`${params.url}`"></web-view>
+ </view>
+</template>
+
+<script>
+ export default {
+ data() {
+ return {
+ params: {},
+ webviewStyles: {
+ progress: {
+ color: "#FF3333"
+ }
+ }
+ }
+ },
+ props: {
+ src: {
+ type: [String],
+ default: null
+ }
+ },
+ onLoad(event) {
+ this.params = event
+ if (event.title) {
+ uni.setNavigationBarTitle({
+ title: event.title
+ })
+ }
+ }
+ }
+</script>
diff --git a/app/pages/index.vue b/app/pages/index.vue
new file mode 100644
index 0000000..4646807
--- /dev/null
+++ b/app/pages/index.vue
@@ -0,0 +1,43 @@
+<template>
+ <view class="content">
+ <image class="logo" src="@/static/logo.png"></image>
+ <view class="text-area">
+ <text class="title">Hello RuoYi</text>
+ </view>
+ </view>
+</template>
+
+<script>
+ export default {
+ onLoad: function() {
+ }
+ }
+</script>
+
+<style>
+ .content {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ }
+
+ .logo {
+ height: 200rpx;
+ width: 200rpx;
+ margin-top: 200rpx;
+ margin-left: auto;
+ margin-right: auto;
+ margin-bottom: 50rpx;
+ }
+
+ .text-area {
+ display: flex;
+ justify-content: center;
+ }
+
+ .title {
+ font-size: 36rpx;
+ color: #8f8f94;
+ }
+</style>
diff --git a/app/pages/login.vue b/app/pages/login.vue
new file mode 100644
index 0000000..7f0e8c8
--- /dev/null
+++ b/app/pages/login.vue
@@ -0,0 +1,202 @@
+<template>
+ <view class="normal-login-container">
+ <view class="logo-content align-center justify-center flex">
+ <image style="width: 100rpx;height: 100rpx;" :src="globalConfig.appInfo.logo" mode="widthFix">
+ </image>
+ <text class="title">鑻ヤ緷绉诲姩绔櫥褰�</text>
+ </view>
+ <view class="login-form-content">
+ <view class="input-item flex align-center">
+ <view class="iconfont icon-user icon"></view>
+ <input v-model="loginForm.username" class="input" type="text" placeholder="璇疯緭鍏ヨ处鍙�" maxlength="30" />
+ </view>
+ <view class="input-item flex align-center">
+ <view class="iconfont icon-password icon"></view>
+ <input v-model="loginForm.password" type="password" class="input" placeholder="璇疯緭鍏ュ瘑鐮�" maxlength="20" />
+ </view>
+ <view class="input-item flex align-center" style="width: 60%;margin: 0px;" v-if="captchaEnabled">
+ <view class="iconfont icon-code icon"></view>
+ <input v-model="loginForm.code" type="number" class="input" placeholder="璇疯緭鍏ラ獙璇佺爜" maxlength="4" />
+ <view class="login-code">
+ <image :src="codeUrl" @click="getCode" class="login-code-img"></image>
+ </view>
+ </view>
+ <view class="action-btn">
+ <button @click="handleLogin" class="login-btn cu-btn block bg-blue lg round">鐧诲綍</button>
+ </view>
+ <view class="reg text-center" v-if="register">
+ <text class="text-grey1">娌℃湁璐﹀彿锛�</text>
+ <text @click="handleUserRegister" class="text-blue">绔嬪嵆娉ㄥ唽</text>
+ </view>
+ <view class="xieyi text-center">
+ <text class="text-grey1">鐧诲綍鍗充唬琛ㄥ悓鎰�</text>
+ <text @click="handleUserAgrement" class="text-blue">銆婄敤鎴峰崗璁��</text>
+ <text @click="handlePrivacy" class="text-blue">銆婇殣绉佸崗璁��</text>
+ </view>
+ </view>
+
+ </view>
+</template>
+
+<script>
+ import { getCodeImg } from '@/api/login'
+
+ export default {
+ data() {
+ return {
+ codeUrl: "",
+ captchaEnabled: true,
+ // 鐢ㄦ埛娉ㄥ唽寮�鍏�
+ register: false,
+ globalConfig: getApp().globalData.config,
+ loginForm: {
+ username: "admin",
+ password: "admin123",
+ code: "",
+ uuid: ''
+ }
+ }
+ },
+ created() {
+ this.getCode()
+ },
+ methods: {
+ // 鐢ㄦ埛娉ㄥ唽
+ handleUserRegister() {
+ this.$tab.redirectTo(`/pages/register`)
+ },
+ // 闅愮鍗忚
+ handlePrivacy() {
+ let site = this.globalConfig.appInfo.agreements[0]
+ this.$tab.navigateTo(`/pages/common/webview/index?title=${site.title}&url=${site.url}`)
+ },
+ // 鐢ㄦ埛鍗忚
+ handleUserAgrement() {
+ let site = this.globalConfig.appInfo.agreements[1]
+ this.$tab.navigateTo(`/pages/common/webview/index?title=${site.title}&url=${site.url}`)
+ },
+ // 鑾峰彇鍥惧舰楠岃瘉鐮�
+ getCode() {
+ getCodeImg().then(res => {
+ this.captchaEnabled = res.captchaEnabled === undefined ? true : res.captchaEnabled
+ if (this.captchaEnabled) {
+ this.codeUrl = 'data:image/gif;base64,' + res.img
+ this.loginForm.uuid = res.uuid
+ }
+ })
+ },
+ // 鐧诲綍鏂规硶
+ async handleLogin() {
+ if (this.loginForm.username === "") {
+ this.$modal.msgError("璇疯緭鍏ユ偍鐨勮处鍙�")
+ } else if (this.loginForm.password === "") {
+ this.$modal.msgError("璇疯緭鍏ユ偍鐨勫瘑鐮�")
+ } else if (this.loginForm.code === "" && this.captchaEnabled) {
+ this.$modal.msgError("璇疯緭鍏ラ獙璇佺爜")
+ } else {
+ this.$modal.loading("鐧诲綍涓紝璇疯�愬績绛夊緟...")
+ this.pwdLogin()
+ }
+ },
+ // 瀵嗙爜鐧诲綍
+ async pwdLogin() {
+ this.$store.dispatch('Login', this.loginForm).then(() => {
+ this.$modal.closeLoading()
+ this.loginSuccess()
+ }).catch(() => {
+ if (this.captchaEnabled) {
+ this.getCode()
+ }
+ })
+ },
+ // 鐧诲綍鎴愬姛鍚庯紝澶勭悊鍑芥暟
+ loginSuccess(result) {
+ // 璁剧疆鐢ㄦ埛淇℃伅
+ this.$store.dispatch('GetInfo').then(res => {
+ this.$tab.reLaunch('/pages/index')
+ })
+ }
+ }
+ }
+</script>
+
+<style lang="scss">
+ page {
+ background-color: #ffffff;
+ }
+
+ .normal-login-container {
+ width: 100%;
+
+ .logo-content {
+ width: 100%;
+ font-size: 21px;
+ text-align: center;
+ padding-top: 15%;
+
+ image {
+ border-radius: 4px;
+ }
+
+ .title {
+ margin-left: 10px;
+ }
+ }
+
+ .login-form-content {
+ text-align: center;
+ margin: 20px auto;
+ margin-top: 15%;
+ width: 80%;
+
+ .input-item {
+ margin: 20px auto;
+ background-color: #f5f6f7;
+ height: 45px;
+ border-radius: 20px;
+
+ .icon {
+ font-size: 38rpx;
+ margin-left: 10px;
+ color: #999;
+ }
+
+ .input {
+ width: 100%;
+ font-size: 14px;
+ line-height: 20px;
+ text-align: left;
+ padding-left: 15px;
+ }
+
+ }
+
+ .login-btn {
+ margin-top: 40px;
+ height: 45px;
+ }
+
+ .reg {
+ margin-top: 15px;
+ }
+
+ .xieyi {
+ color: #333;
+ margin-top: 20px;
+ }
+
+ .login-code {
+ height: 38px;
+ float: right;
+
+ .login-code-img {
+ height: 38px;
+ position: absolute;
+ margin-left: 10px;
+ width: 200rpx;
+ }
+ }
+ }
+ }
+
+</style>
diff --git a/app/pages/mine/about/index.vue b/app/pages/mine/about/index.vue
new file mode 100644
index 0000000..d3f6255
--- /dev/null
+++ b/app/pages/mine/about/index.vue
@@ -0,0 +1,75 @@
+<template>
+ <view class="about-container">
+ <view class="header-section text-center">
+ <image style="width: 150rpx;height: 150rpx;" src="/static/logo200.png" mode="widthFix">
+ </image>
+ <uni-title type="h2" title="鑻ヤ緷绉诲姩绔�"></uni-title>
+ </view>
+
+ <view class="content-section">
+ <view class="menu-list">
+ <view class="list-cell list-cell-arrow">
+ <view class="menu-item-box">
+ <view>鐗堟湰淇℃伅</view>
+ <view class="text-right">v{{version}}</view>
+ </view>
+ </view>
+ <view class="list-cell list-cell-arrow">
+ <view class="menu-item-box">
+ <view>瀹樻柟閭</view>
+ <view class="text-right">ruoyi@xx.com</view>
+ </view>
+ </view>
+ <view class="list-cell list-cell-arrow">
+ <view class="menu-item-box">
+ <view>鏈嶅姟鐑嚎</view>
+ <view class="text-right">400-999-9999</view>
+ </view>
+ </view>
+ <view class="list-cell list-cell-arrow">
+ <view class="menu-item-box">
+ <view>鍏徃缃戠珯</view>
+ <view class="text-right">
+ <uni-link :href="url" :text="url" showUnderLine="false"></uni-link>
+ </view>
+ </view>
+ </view>
+ </view>
+ </view>
+
+ <view class="copyright">
+ <view>Copyright © 2022 ruoyi.vip All Rights Reserved.</view>
+ </view>
+ </view>
+</template>
+
+<script>
+ export default {
+ data() {
+ return {
+ url: getApp().globalData.config.appInfo.site_url,
+ version: getApp().globalData.config.appInfo.version
+ }
+ }
+ }
+</script>
+
+<style lang="scss">
+ page {
+ background-color: #f8f8f8;
+ }
+
+ .copyright {
+ margin-top: 50rpx;
+ text-align: center;
+ line-height: 60rpx;
+ color: #999;
+ }
+
+ .header-section {
+ display: flex;
+ padding: 30rpx 0 0;
+ flex-direction: column;
+ align-items: center;
+ }
+</style>
diff --git a/app/pages/mine/avatar/index.vue b/app/pages/mine/avatar/index.vue
new file mode 100644
index 0000000..7a874bd
--- /dev/null
+++ b/app/pages/mine/avatar/index.vue
@@ -0,0 +1,631 @@
+<template>
+ <view class="container">
+ <view class="page-body uni-content-info">
+ <view class='cropper-content'>
+ <view v-if="isShowImg" class="uni-corpper" :style="'width:'+cropperInitW+'px;height:'+cropperInitH+'px;background:#000'">
+ <view class="uni-corpper-content" :style="'width:'+cropperW+'px;height:'+cropperH+'px;left:'+cropperL+'px;top:'+cropperT+'px'">
+ <image :src="imageSrc" :style="'width:'+cropperW+'px;height:'+cropperH+'px'"></image>
+ <view class="uni-corpper-crop-box" @touchstart.stop="contentStartMove" @touchmove.stop="contentMoveing" @touchend.stop="contentTouchEnd"
+ :style="'left:'+cutL+'px;top:'+cutT+'px;right:'+cutR+'px;bottom:'+cutB+'px'">
+ <view class="uni-cropper-view-box">
+ <view class="uni-cropper-dashed-h"></view>
+ <view class="uni-cropper-dashed-v"></view>
+ <view class="uni-cropper-line-t" data-drag="top" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view>
+ <view class="uni-cropper-line-r" data-drag="right" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view>
+ <view class="uni-cropper-line-b" data-drag="bottom" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view>
+ <view class="uni-cropper-line-l" data-drag="left" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view>
+ <view class="uni-cropper-point point-t" data-drag="top" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view>
+ <view class="uni-cropper-point point-tr" data-drag="topTight"></view>
+ <view class="uni-cropper-point point-r" data-drag="right" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view>
+ <view class="uni-cropper-point point-rb" data-drag="rightBottom" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view>
+ <view class="uni-cropper-point point-b" data-drag="bottom" @touchstart.stop="dragStart" @touchmove.stop="dragMove" @touchend.stop="dragEnd"></view>
+ <view class="uni-cropper-point point-bl" data-drag="bottomLeft"></view>
+ <view class="uni-cropper-point point-l" data-drag="left" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view>
+ <view class="uni-cropper-point point-lt" data-drag="leftTop"></view>
+ </view>
+ </view>
+ </view>
+ </view>
+ </view>
+ <view class='cropper-config'>
+ <button type="primary reverse" @click="getImage" style='margin-top: 30rpx;'> 閫夋嫨澶村儚 </button>
+ <button type="warn" @click="getImageInfo" style='margin-top: 30rpx;'> 鎻愪氦 </button>
+ </view>
+ <canvas canvas-id="myCanvas" :style="'position:absolute;border: 1px solid red; width:'+imageW+'px;height:'+imageH+'px;top:-9999px;left:-9999px;'"></canvas>
+ </view>
+ </view>
+</template>
+
+<script>
+ import config from '@/config'
+ import store from "@/store"
+ import { uploadAvatar } from "@/api/system/user"
+
+ const baseUrl = config.baseUrl
+ let sysInfo = uni.getSystemInfoSync()
+ let SCREEN_WIDTH = sysInfo.screenWidth
+ let PAGE_X, // 鎵嬫寜涓嬬殑x浣嶇疆
+ PAGE_Y, // 鎵嬫寜涓媦鐨勪綅缃�
+ PR = sysInfo.pixelRatio, // dpi
+ T_PAGE_X, // 鎵嬬Щ鍔ㄧ殑鏃跺�檟鐨勪綅缃�
+ T_PAGE_Y, // 鎵嬬Щ鍔ㄧ殑鏃跺�橸鐨勪綅缃�
+ CUT_L, // 鍒濆鍖栨嫋鎷藉厓绱犵殑left鍊�
+ CUT_T, // 鍒濆鍖栨嫋鎷藉厓绱犵殑top鍊�
+ CUT_R, // 鍒濆鍖栨嫋鎷藉厓绱犵殑
+ CUT_B, // 鍒濆鍖栨嫋鎷藉厓绱犵殑
+ CUT_W, // 鍒濆鍖栨嫋鎷藉厓绱犵殑瀹藉害
+ CUT_H, // 鍒濆鍖栨嫋鎷藉厓绱犵殑楂樺害
+ IMG_RATIO, // 鍥剧墖姣斾緥
+ IMG_REAL_W, // 鍥剧墖瀹為檯鐨勫搴�
+ IMG_REAL_H, // 鍥剧墖瀹為檯鐨勯珮搴�
+ DRAFG_MOVE_RATIO = 1, //绉诲姩鏃跺�欑殑姣斾緥,
+ INIT_DRAG_POSITION = 100, // 鍒濆鍖栧睆骞曞搴﹀拰瑁佸壀鍖哄煙鐨勫搴︿箣宸紝鐢ㄤ簬璁剧疆鍒濆鍖栬鍓殑瀹藉害
+ DRAW_IMAGE_W = sysInfo.screenWidth // 璁剧疆鐢熸垚鐨勫浘鐗囧搴�
+
+ export default {
+ /**
+ * 椤甸潰鐨勫垵濮嬫暟鎹�
+ */
+ data() {
+ return {
+ imageSrc: store.getters.avatar,
+ isShowImg: false,
+ // 鍒濆鍖栫殑瀹介珮
+ cropperInitW: SCREEN_WIDTH,
+ cropperInitH: SCREEN_WIDTH,
+ // 鍔ㄦ�佺殑瀹介珮
+ cropperW: SCREEN_WIDTH,
+ cropperH: SCREEN_WIDTH,
+ // 鍔ㄦ�佺殑left top鍊�
+ cropperL: 0,
+ cropperT: 0,
+
+ transL: 0,
+ transT: 0,
+
+ // 鍥剧墖缂╂斁鍊�
+ scaleP: 0,
+ imageW: 0,
+ imageH: 0,
+
+ // 瑁佸壀妗� 瀹介珮
+ cutL: 0,
+ cutT: 0,
+ cutB: SCREEN_WIDTH,
+ cutR: '100%',
+ qualityWidth: DRAW_IMAGE_W,
+ innerAspectRadio: DRAFG_MOVE_RATIO
+ }
+ },
+ /**
+ * 鐢熷懡鍛ㄦ湡鍑芥暟--鐩戝惉椤甸潰鍒濇娓叉煋瀹屾垚
+ */
+ onReady: function () {
+ this.loadImage()
+ },
+ methods: {
+ setData: function (obj) {
+ let that = this
+ Object.keys(obj).forEach(function (key) {
+ that.$set(that.$data, key, obj[key])
+ })
+ },
+ getImage: function () {
+ var _this = this
+ uni.chooseImage({
+ success: function (res) {
+ _this.setData({
+ imageSrc: res.tempFilePaths[0],
+ })
+ _this.loadImage()
+ },
+ })
+ },
+ loadImage: function () {
+ var _this = this
+
+ uni.getImageInfo({
+ src: _this.imageSrc,
+ success: function success(res) {
+ IMG_RATIO = 1 / 1
+ if (IMG_RATIO >= 1) {
+ IMG_REAL_W = SCREEN_WIDTH
+ IMG_REAL_H = SCREEN_WIDTH / IMG_RATIO
+ } else {
+ IMG_REAL_W = SCREEN_WIDTH * IMG_RATIO
+ IMG_REAL_H = SCREEN_WIDTH
+ }
+ let minRange = IMG_REAL_W > IMG_REAL_H ? IMG_REAL_W : IMG_REAL_H
+ INIT_DRAG_POSITION = minRange > INIT_DRAG_POSITION ? INIT_DRAG_POSITION : minRange
+ // 鏍规嵁鍥剧墖鐨勫楂樻樉绀轰笉鍚岀殑鏁堟灉 淇濊瘉鍥剧墖鍙互姝e父鏄剧ず
+ if (IMG_RATIO >= 1) {
+ let cutT = Math.ceil((SCREEN_WIDTH / IMG_RATIO - (SCREEN_WIDTH / IMG_RATIO - INIT_DRAG_POSITION)) / 2)
+ let cutB = cutT
+ let cutL = Math.ceil((SCREEN_WIDTH - SCREEN_WIDTH + INIT_DRAG_POSITION) / 2)
+ let cutR = cutL
+ _this.setData({
+ cropperW: SCREEN_WIDTH,
+ cropperH: SCREEN_WIDTH / IMG_RATIO,
+ // 鍒濆鍖杔eft right
+ cropperL: Math.ceil((SCREEN_WIDTH - SCREEN_WIDTH) / 2),
+ cropperT: Math.ceil((SCREEN_WIDTH - SCREEN_WIDTH / IMG_RATIO) / 2),
+ cutL: cutL,
+ cutT: cutT,
+ cutR: cutR,
+ cutB: cutB,
+ // 鍥剧墖缂╂斁鍊�
+ imageW: IMG_REAL_W,
+ imageH: IMG_REAL_H,
+ scaleP: IMG_REAL_W / SCREEN_WIDTH,
+ qualityWidth: DRAW_IMAGE_W,
+ innerAspectRadio: IMG_RATIO
+ })
+ } else {
+ let cutL = Math.ceil((SCREEN_WIDTH * IMG_RATIO - (SCREEN_WIDTH * IMG_RATIO)) / 2)
+ let cutR = cutL
+ let cutT = Math.ceil((SCREEN_WIDTH - INIT_DRAG_POSITION) / 2)
+ let cutB = cutT
+ _this.setData({
+ cropperW: SCREEN_WIDTH * IMG_RATIO,
+ cropperH: SCREEN_WIDTH,
+ // 鍒濆鍖杔eft right
+ cropperL: Math.ceil((SCREEN_WIDTH - SCREEN_WIDTH * IMG_RATIO) / 2),
+ cropperT: Math.ceil((SCREEN_WIDTH - SCREEN_WIDTH) / 2),
+
+ cutL: cutL,
+ cutT: cutT,
+ cutR: cutR,
+ cutB: cutB,
+ // 鍥剧墖缂╂斁鍊�
+ imageW: IMG_REAL_W,
+ imageH: IMG_REAL_H,
+ scaleP: IMG_REAL_W / SCREEN_WIDTH,
+ qualityWidth: DRAW_IMAGE_W,
+ innerAspectRadio: IMG_RATIO
+ })
+ }
+ _this.setData({
+ isShowImg: true
+ })
+ uni.hideLoading()
+ }
+ })
+ },
+ // 鎷栧姩鏃跺�欒Е鍙戠殑touchStart浜嬩欢
+ contentStartMove(e) {
+ PAGE_X = e.touches[0].pageX
+ PAGE_Y = e.touches[0].pageY
+ },
+
+ // 鎷栧姩鏃跺�欒Е鍙戠殑touchMove浜嬩欢
+ contentMoveing(e) {
+ var _this = this
+ var dragLengthX = (PAGE_X - e.touches[0].pageX) * DRAFG_MOVE_RATIO
+ var dragLengthY = (PAGE_Y - e.touches[0].pageY) * DRAFG_MOVE_RATIO
+ // 宸︾Щ
+ if (dragLengthX > 0) {
+ if (this.cutL - dragLengthX < 0) dragLengthX = this.cutL
+ } else {
+ if (this.cutR + dragLengthX < 0) dragLengthX = -this.cutR
+ }
+
+ if (dragLengthY > 0) {
+ if (this.cutT - dragLengthY < 0) dragLengthY = this.cutT
+ } else {
+ if (this.cutB + dragLengthY < 0) dragLengthY = -this.cutB
+ }
+ this.setData({
+ cutL: this.cutL - dragLengthX,
+ cutT: this.cutT - dragLengthY,
+ cutR: this.cutR + dragLengthX,
+ cutB: this.cutB + dragLengthY
+ })
+
+ PAGE_X = e.touches[0].pageX
+ PAGE_Y = e.touches[0].pageY
+ },
+
+ contentTouchEnd() {
+
+ },
+
+ // 鑾峰彇鍥剧墖
+ getImageInfo() {
+ var _this = this
+ uni.showLoading({
+ title: '鍥剧墖鐢熸垚涓�...',
+ })
+ // 灏嗗浘鐗囧啓鍏ョ敾甯�
+ const ctx = uni.createCanvasContext('myCanvas')
+ ctx.drawImage(_this.imageSrc, 0, 0, IMG_REAL_W, IMG_REAL_H)
+ ctx.draw(true, () => {
+ // 鑾峰彇鐢诲竷瑕佽鍓殑浣嶇疆鍜屽搴� 鍧囦负鐧惧垎姣� * 鐢诲竷涓浘鐗囩殑瀹藉害 淇濊瘉浜嗗湪寰俊灏忕▼搴忎腑瑁佸壀鐨勫浘鐗囨ā绯� 浣嶇疆涓嶅鐨勯棶棰� canvasT = (_this.cutT / _this.cropperH) * (_this.imageH / pixelRatio)
+ var canvasW = ((_this.cropperW - _this.cutL - _this.cutR) / _this.cropperW) * IMG_REAL_W
+ var canvasH = ((_this.cropperH - _this.cutT - _this.cutB) / _this.cropperH) * IMG_REAL_H
+ var canvasL = (_this.cutL / _this.cropperW) * IMG_REAL_W
+ var canvasT = (_this.cutT / _this.cropperH) * IMG_REAL_H
+ uni.canvasToTempFilePath({
+ x: canvasL,
+ y: canvasT,
+ width: canvasW,
+ height: canvasH,
+ destWidth: canvasW,
+ destHeight: canvasH,
+ quality: 0.5,
+ canvasId: 'myCanvas',
+ success: function (res) {
+ uni.hideLoading()
+ let data = {name: 'avatarfile', filePath: res.tempFilePath}
+ uploadAvatar(data).then(response => {
+ store.commit('SET_AVATAR', baseUrl + response.imgUrl)
+ uni.showToast({ title: "淇敼鎴愬姛", icon: 'success' })
+ uni.navigateBack()
+ })
+ }
+ })
+ })
+ },
+ // 璁剧疆澶у皬鐨勬椂鍊欒Е鍙戠殑touchStart浜嬩欢
+ dragStart(e) {
+ T_PAGE_X = e.touches[0].pageX
+ T_PAGE_Y = e.touches[0].pageY
+ CUT_L = this.cutL
+ CUT_R = this.cutR
+ CUT_B = this.cutB
+ CUT_T = this.cutT
+ },
+
+ // 璁剧疆澶у皬鐨勬椂鍊欒Е鍙戠殑touchMove浜嬩欢
+ dragMove(e) {
+ var _this = this
+ var dragType = e.target.dataset.drag
+ switch (dragType) {
+ case 'right':
+ var dragLength = (T_PAGE_X - e.touches[0].pageX) * DRAFG_MOVE_RATIO
+ if (CUT_R + dragLength < 0) dragLength = -CUT_R
+ this.setData({
+ cutR: CUT_R + dragLength
+ })
+ break
+ case 'left':
+ var dragLength = (T_PAGE_X - e.touches[0].pageX) * DRAFG_MOVE_RATIO
+ if (CUT_L - dragLength < 0) dragLength = CUT_L
+ if ((CUT_L - dragLength) > (this.cropperW - this.cutR)) dragLength = CUT_L - (this.cropperW - this.cutR)
+ this.setData({
+ cutL: CUT_L - dragLength
+ })
+ break
+ case 'top':
+ var dragLength = (T_PAGE_Y - e.touches[0].pageY) * DRAFG_MOVE_RATIO
+ if (CUT_T - dragLength < 0) dragLength = CUT_T
+ if ((CUT_T - dragLength) > (this.cropperH - this.cutB)) dragLength = CUT_T - (this.cropperH - this.cutB)
+ this.setData({
+ cutT: CUT_T - dragLength
+ })
+ break
+ case 'bottom':
+ var dragLength = (T_PAGE_Y - e.touches[0].pageY) * DRAFG_MOVE_RATIO
+ if (CUT_B + dragLength < 0) dragLength = -CUT_B
+ this.setData({
+ cutB: CUT_B + dragLength
+ })
+ break
+ case 'rightBottom':
+ var dragLengthX = (T_PAGE_X - e.touches[0].pageX) * DRAFG_MOVE_RATIO
+ var dragLengthY = (T_PAGE_Y - e.touches[0].pageY) * DRAFG_MOVE_RATIO
+
+ if (CUT_B + dragLengthY < 0) dragLengthY = -CUT_B
+ if (CUT_R + dragLengthX < 0) dragLengthX = -CUT_R
+ let cutB = CUT_B + dragLengthY
+ let cutR = CUT_R + dragLengthX
+
+ this.setData({
+ cutB: cutB,
+ cutR: cutR
+ })
+ break
+ default:
+ break
+ }
+ }
+ }
+ }
+</script>
+
+<style>
+ /* pages/uni-cropper/index.wxss */
+
+ .uni-content-info {
+ /* position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ display: block;
+ align-items: center;
+ flex-direction: column; */
+ }
+
+ .cropper-config {
+ padding: 20rpx 40rpx;
+ }
+
+ .cropper-content {
+ min-height: 750rpx;
+ width: 100%;
+ }
+
+ .uni-corpper {
+ position: relative;
+ overflow: hidden;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ -webkit-tap-highlight-color: transparent;
+ -webkit-touch-callout: none;
+ box-sizing: border-box;
+ }
+
+ .uni-corpper-content {
+ position: relative;
+ }
+
+ .uni-corpper-content image {
+ display: block;
+ width: 100%;
+ min-width: 0 !important;
+ max-width: none !important;
+ height: 100%;
+ min-height: 0 !important;
+ max-height: none !important;
+ image-orientation: 0deg !important;
+ margin: 0 auto;
+ }
+ /* 绉诲姩鍥剧墖鏁堟灉 */
+
+ .uni-cropper-drag-box {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ cursor: move;
+ background: rgba(0, 0, 0, 0.6);
+ z-index: 1;
+ }
+ /* 鍐呴儴鐨勪俊鎭� */
+
+ .uni-corpper-crop-box {
+ position: absolute;
+ background: rgba(255, 255, 255, 0.3);
+ z-index: 2;
+ }
+
+ .uni-corpper-crop-box .uni-cropper-view-box {
+ position: relative;
+ display: block;
+ width: 100%;
+ height: 100%;
+ overflow: visible;
+ outline: 1rpx solid #69f;
+ outline-color: rgba(102, 153, 255, .75)
+ }
+ /* 妯悜铏氱嚎 */
+
+ .uni-cropper-dashed-h {
+ position: absolute;
+ top: 33.33333333%;
+ left: 0;
+ width: 100%;
+ height: 33.33333333%;
+ border-top: 1rpx dashed rgba(255, 255, 255, 0.5);
+ border-bottom: 1rpx dashed rgba(255, 255, 255, 0.5);
+ }
+ /* 绾靛悜铏氱嚎 */
+
+ .uni-cropper-dashed-v {
+ position: absolute;
+ left: 33.33333333%;
+ top: 0;
+ width: 33.33333333%;
+ height: 100%;
+ border-left: 1rpx dashed rgba(255, 255, 255, 0.5);
+ border-right: 1rpx dashed rgba(255, 255, 255, 0.5);
+ }
+ /* 鍥涗釜鏂瑰悜鐨勭嚎 涓轰簡涔嬪悗鐨勬嫋鍔ㄤ簨浠�*/
+
+ .uni-cropper-line-t {
+ position: absolute;
+ display: block;
+ width: 100%;
+ background-color: #69f;
+ top: 0;
+ left: 0;
+ height: 1rpx;
+ opacity: 0.1;
+ cursor: n-resize;
+ }
+
+ .uni-cropper-line-t::before {
+ content: '';
+ position: absolute;
+ top: 50%;
+ right: 0rpx;
+ width: 100%;
+ -webkit-transform: translate3d(0, -50%, 0);
+ transform: translate3d(0, -50%, 0);
+ bottom: 0;
+ height: 41rpx;
+ background: transparent;
+ z-index: 11;
+ }
+
+ .uni-cropper-line-r {
+ position: absolute;
+ display: block;
+ background-color: #69f;
+ top: 0;
+ right: 0rpx;
+ width: 1rpx;
+ opacity: 0.1;
+ height: 100%;
+ cursor: e-resize;
+ }
+
+ .uni-cropper-line-r::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 50%;
+ width: 41rpx;
+ -webkit-transform: translate3d(-50%, 0, 0);
+ transform: translate3d(-50%, 0, 0);
+ bottom: 0;
+ height: 100%;
+ background: transparent;
+ z-index: 11;
+ }
+
+ .uni-cropper-line-b {
+ position: absolute;
+ display: block;
+ width: 100%;
+ background-color: #69f;
+ bottom: 0;
+ left: 0;
+ height: 1rpx;
+ opacity: 0.1;
+ cursor: s-resize;
+ }
+
+ .uni-cropper-line-b::before {
+ content: '';
+ position: absolute;
+ top: 50%;
+ right: 0rpx;
+ width: 100%;
+ -webkit-transform: translate3d(0, -50%, 0);
+ transform: translate3d(0, -50%, 0);
+ bottom: 0;
+ height: 41rpx;
+ background: transparent;
+ z-index: 11;
+ }
+
+ .uni-cropper-line-l {
+ position: absolute;
+ display: block;
+ background-color: #69f;
+ top: 0;
+ left: 0;
+ width: 1rpx;
+ opacity: 0.1;
+ height: 100%;
+ cursor: w-resize;
+ }
+
+ .uni-cropper-line-l::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 50%;
+ width: 41rpx;
+ -webkit-transform: translate3d(-50%, 0, 0);
+ transform: translate3d(-50%, 0, 0);
+ bottom: 0;
+ height: 100%;
+ background: transparent;
+ z-index: 11;
+ }
+
+ .uni-cropper-point {
+ width: 5rpx;
+ height: 5rpx;
+ background-color: #69f;
+ opacity: .75;
+ position: absolute;
+ z-index: 3;
+ }
+
+ .point-t {
+ top: -3rpx;
+ left: 50%;
+ margin-left: -3rpx;
+ cursor: n-resize;
+ }
+
+ .point-tr {
+ top: -3rpx;
+ left: 100%;
+ margin-left: -3rpx;
+ cursor: n-resize;
+ }
+
+ .point-r {
+ top: 50%;
+ left: 100%;
+ margin-left: -3rpx;
+ margin-top: -3rpx;
+ cursor: n-resize;
+ }
+
+ .point-rb {
+ left: 100%;
+ top: 100%;
+ -webkit-transform: translate3d(-50%, -50%, 0);
+ transform: translate3d(-50%, -50%, 0);
+ cursor: n-resize;
+ width: 36rpx;
+ height: 36rpx;
+ background-color: #69f;
+ position: absolute;
+ z-index: 1112;
+ opacity: 1;
+ }
+
+ .point-b {
+ left: 50%;
+ top: 100%;
+ margin-left: -3rpx;
+ margin-top: -3rpx;
+ cursor: n-resize;
+ }
+
+ .point-bl {
+ left: 0%;
+ top: 100%;
+ margin-left: -3rpx;
+ margin-top: -3rpx;
+ cursor: n-resize;
+ }
+
+ .point-l {
+ left: 0%;
+ top: 50%;
+ margin-left: -3rpx;
+ margin-top: -3rpx;
+ cursor: n-resize;
+ }
+
+ .point-lt {
+ left: 0%;
+ top: 0%;
+ margin-left: -3rpx;
+ margin-top: -3rpx;
+ cursor: n-resize;
+ }
+ /* 瑁佸壀妗嗛瑙堝唴瀹� */
+
+ .uni-cropper-viewer {
+ position: relative;
+ width: 100%;
+ height: 100%;
+ overflow: hidden;
+ }
+
+ .uni-cropper-viewer image {
+ position: absolute;
+ z-index: 2;
+ }
+</style>
diff --git a/app/pages/mine/help/index.vue b/app/pages/mine/help/index.vue
new file mode 100644
index 0000000..d2e4374
--- /dev/null
+++ b/app/pages/mine/help/index.vue
@@ -0,0 +1,112 @@
+<template>
+ <view class="help-container">
+ <view v-for="(item, findex) in list" :key="findex" :title="item.title" class="list-title">
+ <view class="text-title">
+ <view :class="item.icon"></view>{{ item.title }}
+ </view>
+ <view class="childList">
+ <view v-for="(child, zindex) in item.childList" :key="zindex" class="question" hover-class="hover"
+ @click="handleText(child)">
+ <view class="text-item">{{ child.title }}</view>
+ <view class="line" v-if="zindex !== item.childList.length - 1"></view>
+ </view>
+ </view>
+ </view>
+ </view>
+</template>
+
+<script>
+ export default {
+ data() {
+ return {
+ list: [{
+ icon: 'iconfont icon-github',
+ title: '鑻ヤ緷闂',
+ childList: [{
+ title: '鑻ヤ緷寮�婧愬悧锛�',
+ content: '寮�婧�'
+ }, {
+ title: '鑻ヤ緷鍙互鍟嗙敤鍚楋紵',
+ content: '鍙互'
+ }, {
+ title: '鑻ヤ緷瀹樼綉鍦板潃澶氬皯锛�',
+ content: 'http://ruoyi.vip'
+ }, {
+ title: '鑻ヤ緷鏂囨。鍦板潃澶氬皯锛�',
+ content: 'http://doc.ruoyi.vip'
+ }]
+ },
+ {
+ icon: 'iconfont icon-help',
+ title: '鍏朵粬闂',
+ childList: [{
+ title: '濡備綍閫�鍑虹櫥褰曪紵',
+ content: '璇风偣鍑籟鎴戠殑] - [搴旂敤璁剧疆] - [閫�鍑虹櫥褰昡鍗冲彲閫�鍑虹櫥褰�',
+ }, {
+ title: '濡備綍淇敼鐢ㄦ埛澶村儚锛�',
+ content: '璇风偣鍑籟鎴戠殑] - [閫夋嫨澶村儚] - [鐐瑰嚮鎻愪氦]鍗冲彲鏇存崲鐢ㄦ埛澶村儚',
+ }, {
+ title: '濡備綍淇敼鐧诲綍瀵嗙爜锛�',
+ content: '璇风偣鍑籟鎴戠殑] - [搴旂敤璁剧疆] - [淇敼瀵嗙爜]鍗冲彲淇敼鐧诲綍瀵嗙爜',
+ }]
+ }
+ ]
+ }
+ },
+ methods: {
+ handleText(item) {
+ this.$tab.navigateTo(`/pages/common/textview/index?title=${item.title}&content=${item.content}`)
+ }
+ }
+ }
+</script>
+
+<style lang="scss" scoped>
+ page {
+ background-color: #f8f8f8;
+ }
+
+ .help-container {
+ margin-bottom: 100rpx;
+ padding: 30rpx;
+ }
+
+ .list-title {
+ margin-bottom: 30rpx;
+ }
+
+ .childList {
+ background: #ffffff;
+ box-shadow: 0px 0px 10rpx rgba(193, 193, 193, 0.2);
+ border-radius: 16rpx;
+ margin-top: 10rpx;
+ }
+
+ .line {
+ width: 100%;
+ height: 1rpx;
+ background-color: #F5F5F5;
+ }
+
+ .text-title {
+ color: #303133;
+ font-size: 32rpx;
+ font-weight: bold;
+ margin-left: 10rpx;
+
+ .iconfont {
+ font-size: 16px;
+ margin-right: 10rpx;
+ }
+ }
+
+ .text-item {
+ font-size: 28rpx;
+ padding: 24rpx;
+ }
+
+ .question {
+ color: #606266;
+ font-size: 28rpx;
+ }
+</style>
diff --git a/app/pages/mine/index.vue b/app/pages/mine/index.vue
new file mode 100644
index 0000000..33c3a6e
--- /dev/null
+++ b/app/pages/mine/index.vue
@@ -0,0 +1,198 @@
+<template>
+ <view class="mine-container" :style="{height: `${windowHeight}px`}">
+ <!--椤堕儴涓汉淇℃伅鏍�-->
+ <view class="header-section">
+ <view class="flex padding justify-between">
+ <view class="flex align-center">
+ <view v-if="!avatar" class="cu-avatar xl round bg-white">
+ <view class="iconfont icon-people text-gray icon"></view>
+ </view>
+ <image v-if="avatar" @click="handleToAvatar" :src="avatar" class="cu-avatar xl round" mode="widthFix">
+ </image>
+ <view v-if="!name" @click="handleToLogin" class="login-tip">
+ 鐐瑰嚮鐧诲綍
+ </view>
+ <view v-if="name" @click="handleToInfo" class="user-info">
+ <view class="u_title">
+ 鐢ㄦ埛鍚嶏細{{ name }}
+ </view>
+ </view>
+ </view>
+ <view @click="handleToInfo" class="flex align-center">
+ <text>涓汉淇℃伅</text>
+ <view class="iconfont icon-right"></view>
+ </view>
+ </view>
+ </view>
+
+ <view class="content-section">
+ <view class="mine-actions grid col-4 text-center">
+ <view class="action-item" @click="handleJiaoLiuQun">
+ <view class="iconfont icon-friendfill text-pink icon"></view>
+ <text class="text">浜ゆ祦缇�</text>
+ </view>
+ <view class="action-item" @click="handleBuilding">
+ <view class="iconfont icon-service text-blue icon"></view>
+ <text class="text">鍦ㄧ嚎瀹㈡湇</text>
+ </view>
+ <view class="action-item" @click="handleBuilding">
+ <view class="iconfont icon-community text-mauve icon"></view>
+ <text class="text">鍙嶉绀惧尯</text>
+ </view>
+ <view class="action-item" @click="handleBuilding">
+ <view class="iconfont icon-dianzan text-green icon"></view>
+ <text class="text">鐐硅禐鎴戜滑</text>
+ </view>
+ </view>
+
+ <view class="menu-list">
+ <view class="list-cell list-cell-arrow" @click="handleToEditInfo">
+ <view class="menu-item-box">
+ <view class="iconfont icon-user menu-icon"></view>
+ <view>缂栬緫璧勬枡</view>
+ </view>
+ </view>
+ <view class="list-cell list-cell-arrow" @click="handleHelp">
+ <view class="menu-item-box">
+ <view class="iconfont icon-help menu-icon"></view>
+ <view>甯歌闂</view>
+ </view>
+ </view>
+ <view class="list-cell list-cell-arrow" @click="handleAbout">
+ <view class="menu-item-box">
+ <view class="iconfont icon-aixin menu-icon"></view>
+ <view>鍏充簬鎴戜滑</view>
+ </view>
+ </view>
+ <view class="list-cell list-cell-arrow" @click="handleToSetting">
+ <view class="menu-item-box">
+ <view class="iconfont icon-setting menu-icon"></view>
+ <view>搴旂敤璁剧疆</view>
+ </view>
+ </view>
+ </view>
+
+ </view>
+ </view>
+</template>
+
+<script>
+ import storage from '@/utils/storage'
+
+ export default {
+ data() {
+ return {
+ name: this.$store.state.user.name,
+ version: getApp().globalData.config.appInfo.version
+ }
+ },
+ computed: {
+ avatar() {
+ return this.$store.state.user.avatar
+ },
+ windowHeight() {
+ return uni.getSystemInfoSync().windowHeight - 50
+ }
+ },
+ methods: {
+ handleToInfo() {
+ this.$tab.navigateTo('/pages/mine/info/index')
+ },
+ handleToEditInfo() {
+ this.$tab.navigateTo('/pages/mine/info/edit')
+ },
+ handleToSetting() {
+ this.$tab.navigateTo('/pages/mine/setting/index')
+ },
+ handleToLogin() {
+ this.$tab.reLaunch('/pages/login')
+ },
+ handleToAvatar() {
+ this.$tab.navigateTo('/pages/mine/avatar/index')
+ },
+ handleLogout() {
+ this.$modal.confirm('纭畾娉ㄩ攢骞堕��鍑虹郴缁熷悧锛�').then(() => {
+ this.$store.dispatch('LogOut').then(() => {
+ this.$tab.reLaunch('/pages/index')
+ })
+ })
+ },
+ handleHelp() {
+ this.$tab.navigateTo('/pages/mine/help/index')
+ },
+ handleAbout() {
+ this.$tab.navigateTo('/pages/mine/about/index')
+ },
+ handleJiaoLiuQun() {
+ this.$modal.showToast('QQ缇わ細鈶�133713780(婊�)銆佲憽146013835(婊�)銆佲憿189091635')
+ },
+ handleBuilding() {
+ this.$modal.showToast('妯″潡寤鸿涓瓇')
+ }
+ }
+ }
+</script>
+
+<style lang="scss">
+ page {
+ background-color: #f5f6f7;
+ }
+
+ .mine-container {
+ width: 100%;
+ height: 100%;
+
+
+ .header-section {
+ padding: 15px 15px 45px 15px;
+ background-color: #3c96f3;
+ color: white;
+
+ .login-tip {
+ font-size: 18px;
+ margin-left: 10px;
+ }
+
+ .cu-avatar {
+ border: 2px solid #eaeaea;
+
+ .icon {
+ font-size: 40px;
+ }
+ }
+
+ .user-info {
+ margin-left: 15px;
+
+ .u_title {
+ font-size: 18px;
+ line-height: 30px;
+ }
+ }
+ }
+
+ .content-section {
+ position: relative;
+ top: -50px;
+
+ .mine-actions {
+ margin: 15px 15px;
+ padding: 20px 0px;
+ border-radius: 8px;
+ background-color: white;
+
+ .action-item {
+ .icon {
+ font-size: 28px;
+ }
+
+ .text {
+ display: block;
+ font-size: 13px;
+ margin: 8px 0px;
+ }
+ }
+ }
+ }
+ }
+</style>
diff --git a/app/pages/mine/info/edit.vue b/app/pages/mine/info/edit.vue
new file mode 100644
index 0000000..519540a
--- /dev/null
+++ b/app/pages/mine/info/edit.vue
@@ -0,0 +1,127 @@
+<template>
+ <view class="container">
+ <view class="example">
+ <uni-forms ref="form" :model="user" labelWidth="80px">
+ <uni-forms-item label="鐢ㄦ埛鏄电О" name="nickName">
+ <uni-easyinput v-model="user.nickName" placeholder="璇疯緭鍏ユ樀绉�" />
+ </uni-forms-item>
+ <uni-forms-item label="鎵嬫満鍙风爜" name="phonenumber">
+ <uni-easyinput v-model="user.phonenumber" placeholder="璇疯緭鍏ユ墜鏈哄彿鐮�" />
+ </uni-forms-item>
+ <uni-forms-item label="閭" name="email">
+ <uni-easyinput v-model="user.email" placeholder="璇疯緭鍏ラ偖绠�" />
+ </uni-forms-item>
+ <uni-forms-item label="鎬у埆" name="sex" required>
+ <uni-data-checkbox v-model="user.sex" :localdata="sexs" />
+ </uni-forms-item>
+ </uni-forms>
+ <button type="primary" @click="submit">鎻愪氦</button>
+ </view>
+ </view>
+</template>
+
+<script>
+ import { getUserProfile } from "@/api/system/user"
+ import { updateUserProfile } from "@/api/system/user"
+
+ export default {
+ data() {
+ return {
+ user: {
+ nickName: "",
+ phonenumber: "",
+ email: "",
+ sex: ""
+ },
+ sexs: [{
+ text: '鐢�',
+ value: "0"
+ }, {
+ text: '濂�',
+ value: "1"
+ }],
+ rules: {
+ nickName: {
+ rules: [{
+ required: true,
+ errorMessage: '鐢ㄦ埛鏄电О涓嶈兘涓虹┖'
+ }]
+ },
+ phonenumber: {
+ rules: [{
+ required: true,
+ errorMessage: '鎵嬫満鍙风爜涓嶈兘涓虹┖'
+ }, {
+ pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
+ errorMessage: '璇疯緭鍏ユ纭殑鎵嬫満鍙风爜'
+ }]
+ },
+ email: {
+ rules: [{
+ required: true,
+ errorMessage: '閭鍦板潃涓嶈兘涓虹┖'
+ }, {
+ format: 'email',
+ errorMessage: '璇疯緭鍏ユ纭殑閭鍦板潃'
+ }]
+ }
+ }
+ }
+ },
+ onLoad() {
+ this.getUser()
+ },
+ onReady() {
+ this.$refs.form.setRules(this.rules)
+ },
+ methods: {
+ getUser() {
+ getUserProfile().then(response => {
+ this.user = response.data
+ })
+ },
+ submit(ref) {
+ this.$refs.form.validate().then(res => {
+ updateUserProfile(this.user).then(response => {
+ this.$modal.msgSuccess("淇敼鎴愬姛")
+ })
+ })
+ }
+ }
+ }
+</script>
+
+<style lang="scss">
+ page {
+ background-color: #ffffff;
+ }
+
+ .example {
+ padding: 15px;
+ background-color: #fff;
+ }
+
+ .segmented-control {
+ margin-bottom: 15px;
+ }
+
+ .button-group {
+ margin-top: 15px;
+ display: flex;
+ justify-content: space-around;
+ }
+
+ .form-item {
+ display: flex;
+ align-items: center;
+ flex: 1;
+ }
+
+ .button {
+ display: flex;
+ align-items: center;
+ height: 35px;
+ line-height: 35px;
+ margin-left: 10px;
+ }
+</style>
diff --git a/app/pages/mine/info/index.vue b/app/pages/mine/info/index.vue
new file mode 100644
index 0000000..65c861a
--- /dev/null
+++ b/app/pages/mine/info/index.vue
@@ -0,0 +1,44 @@
+<template>
+ <view class="container">
+ <uni-list>
+ <uni-list-item showExtraIcon="true" :extraIcon="{type: 'person-filled'}" title="鏄电О" :rightText="user.nickName" />
+ <uni-list-item showExtraIcon="true" :extraIcon="{type: 'phone-filled'}" title="鎵嬫満鍙风爜" :rightText="user.phonenumber" />
+ <uni-list-item showExtraIcon="true" :extraIcon="{type: 'email-filled'}" title="閭" :rightText="user.email" />
+ <uni-list-item showExtraIcon="true" :extraIcon="{type: 'auth-filled'}" title="宀椾綅" :rightText="postGroup" />
+ <uni-list-item showExtraIcon="true" :extraIcon="{type: 'staff-filled'}" title="瑙掕壊" :rightText="roleGroup" />
+ <uni-list-item showExtraIcon="true" :extraIcon="{type: 'calendar-filled'}" title="鍒涘缓鏃ユ湡" :rightText="user.createTime" />
+ </uni-list>
+ </view>
+</template>
+
+<script>
+ import { getUserProfile } from "@/api/system/user"
+
+ export default {
+ data() {
+ return {
+ user: {},
+ roleGroup: "",
+ postGroup: ""
+ }
+ },
+ onLoad() {
+ this.getUser()
+ },
+ methods: {
+ getUser() {
+ getUserProfile().then(response => {
+ this.user = response.data
+ this.roleGroup = response.roleGroup
+ this.postGroup = response.postGroup
+ })
+ }
+ }
+ }
+</script>
+
+<style lang="scss">
+ page {
+ background-color: #ffffff;
+ }
+</style>
diff --git a/app/pages/mine/pwd/index.vue b/app/pages/mine/pwd/index.vue
new file mode 100644
index 0000000..da9567f
--- /dev/null
+++ b/app/pages/mine/pwd/index.vue
@@ -0,0 +1,85 @@
+<template>
+ <view class="pwd-retrieve-container">
+ <uni-forms ref="form" :value="user" labelWidth="80px">
+ <uni-forms-item name="oldPassword" label="鏃у瘑鐮�">
+ <uni-easyinput type="password" v-model="user.oldPassword" placeholder="璇疯緭鍏ユ棫瀵嗙爜" />
+ </uni-forms-item>
+ <uni-forms-item name="newPassword" label="鏂板瘑鐮�">
+ <uni-easyinput type="password" v-model="user.newPassword" placeholder="璇疯緭鍏ユ柊瀵嗙爜" />
+ </uni-forms-item>
+ <uni-forms-item name="confirmPassword" label="纭瀵嗙爜">
+ <uni-easyinput type="password" v-model="user.confirmPassword" placeholder="璇风‘璁ゆ柊瀵嗙爜" />
+ </uni-forms-item>
+ <button type="primary" @click="submit">鎻愪氦</button>
+ </uni-forms>
+ </view>
+</template>
+
+<script>
+ import { updateUserPwd } from "@/api/system/user"
+
+ export default {
+ data() {
+ return {
+ user: {
+ oldPassword: undefined,
+ newPassword: undefined,
+ confirmPassword: undefined
+ },
+ rules: {
+ oldPassword: {
+ rules: [{
+ required: true,
+ errorMessage: '鏃у瘑鐮佷笉鑳戒负绌�'
+ }]
+ },
+ newPassword: {
+ rules: [{
+ required: true,
+ errorMessage: '鏂板瘑鐮佷笉鑳戒负绌�',
+ },
+ {
+ minLength: 6,
+ maxLength: 20,
+ errorMessage: '闀垮害鍦� 6 鍒� 20 涓瓧绗�'
+ }
+ ]
+ },
+ confirmPassword: {
+ rules: [{
+ required: true,
+ errorMessage: '纭瀵嗙爜涓嶈兘涓虹┖'
+ }, {
+ validateFunction: (rule, value, data) => data.newPassword === value,
+ errorMessage: '涓ゆ杈撳叆鐨勫瘑鐮佷笉涓�鑷�'
+ }
+ ]
+ }
+ }
+ }
+ },
+ onReady() {
+ this.$refs.form.setRules(this.rules)
+ },
+ methods: {
+ submit() {
+ this.$refs.form.validate().then(res => {
+ updateUserPwd(this.user.oldPassword, this.user.newPassword).then(response => {
+ this.$modal.msgSuccess("淇敼鎴愬姛")
+ })
+ })
+ }
+ }
+ }
+</script>
+
+<style lang="scss">
+ page {
+ background-color: #ffffff;
+ }
+
+ .pwd-retrieve-container {
+ padding-top: 36rpx;
+ padding: 15px;
+ }
+</style>
diff --git a/app/pages/mine/setting/index.vue b/app/pages/mine/setting/index.vue
new file mode 100644
index 0000000..0f9f058
--- /dev/null
+++ b/app/pages/mine/setting/index.vue
@@ -0,0 +1,78 @@
+<template>
+ <view class="setting-container" :style="{height: `${windowHeight}px`}">
+ <view class="menu-list">
+ <view class="list-cell list-cell-arrow" @click="handleToPwd">
+ <view class="menu-item-box">
+ <view class="iconfont icon-password menu-icon"></view>
+ <view>淇敼瀵嗙爜</view>
+ </view>
+ </view>
+ <view class="list-cell list-cell-arrow" @click="handleToUpgrade">
+ <view class="menu-item-box">
+ <view class="iconfont icon-refresh menu-icon"></view>
+ <view>妫�鏌ユ洿鏂�</view>
+ </view>
+ </view>
+ <view class="list-cell list-cell-arrow" @click="handleCleanTmp">
+ <view class="menu-item-box">
+ <view class="iconfont icon-clean menu-icon"></view>
+ <view>娓呯悊缂撳瓨</view>
+ </view>
+ </view>
+ </view>
+ <view class="cu-list menu">
+ <view class="cu-item item-box">
+ <view class="content text-center" @click="handleLogout">
+ <text class="text-black">閫�鍑虹櫥褰�</text>
+ </view>
+ </view>
+ </view>
+ </view>
+</template>
+
+<script>
+ export default {
+ data() {
+ return {
+ windowHeight: uni.getSystemInfoSync().windowHeight
+ }
+ },
+ methods: {
+ handleToPwd() {
+ this.$tab.navigateTo('/pages/mine/pwd/index')
+ },
+ handleToUpgrade() {
+ this.$modal.showToast('妯″潡寤鸿涓瓇')
+ },
+ handleCleanTmp() {
+ this.$modal.showToast('妯″潡寤鸿涓瓇')
+ },
+ handleLogout() {
+ this.$modal.confirm('纭畾娉ㄩ攢骞堕��鍑虹郴缁熷悧锛�').then(() => {
+ this.$store.dispatch('LogOut').then(() => {
+ this.$tab.reLaunch('/pages/index')
+ })
+ })
+ }
+ }
+ }
+</script>
+
+<style lang="scss" scoped>
+ .page {
+ background-color: #f8f8f8;
+ }
+
+ .item-box {
+ background-color: #FFFFFF;
+ margin: 30rpx;
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+ align-items: center;
+ padding: 10rpx;
+ border-radius: 8rpx;
+ color: #303133;
+ font-size: 32rpx;
+ }
+</style>
diff --git a/app/pages/register.vue b/app/pages/register.vue
new file mode 100644
index 0000000..61e6d5c
--- /dev/null
+++ b/app/pages/register.vue
@@ -0,0 +1,196 @@
+<template>
+ <view class="normal-login-container">
+ <view class="logo-content align-center justify-center flex">
+ <image style="width: 100rpx;height: 100rpx;" :src="globalConfig.appInfo.logo" mode="widthFix">
+ </image>
+ <text class="title">鑻ヤ緷绉诲姩绔敞鍐�</text>
+ </view>
+ <view class="login-form-content">
+ <view class="input-item flex align-center">
+ <view class="iconfont icon-user icon"></view>
+ <input v-model="registerForm.username" class="input" type="text" placeholder="璇疯緭鍏ヨ处鍙�" maxlength="30" />
+ </view>
+ <view class="input-item flex align-center">
+ <view class="iconfont icon-password icon"></view>
+ <input v-model="registerForm.password" type="password" class="input" placeholder="璇疯緭鍏ュ瘑鐮�" maxlength="20" />
+ </view>
+ <view class="input-item flex align-center">
+ <view class="iconfont icon-password icon"></view>
+ <input v-model="registerForm.confirmPassword" type="password" class="input" placeholder="璇疯緭鍏ラ噸澶嶅瘑鐮�" maxlength="20" />
+ </view>
+ <view class="input-item flex align-center" style="width: 60%;margin: 0px;" v-if="captchaEnabled">
+ <view class="iconfont icon-code icon"></view>
+ <input v-model="registerForm.code" type="number" class="input" placeholder="璇疯緭鍏ラ獙璇佺爜" maxlength="4" />
+ <view class="login-code">
+ <image :src="codeUrl" @click="getCode" class="login-code-img"></image>
+ </view>
+ </view>
+ <view class="action-btn">
+ <button @click="handleRegister()" class="register-btn cu-btn block bg-blue lg round">娉ㄥ唽</button>
+ </view>
+ </view>
+ <view class="xieyi text-center">
+ <text @click="handleUserLogin" class="text-blue">浣跨敤宸叉湁璐﹀彿鐧诲綍</text>
+ </view>
+ </view>
+</template>
+
+<script>
+ import { getCodeImg, register } from '@/api/login'
+
+ export default {
+ data() {
+ return {
+ codeUrl: "",
+ captchaEnabled: true,
+ globalConfig: getApp().globalData.config,
+ registerForm: {
+ username: "",
+ password: "",
+ confirmPassword: "",
+ code: "",
+ uuid: ''
+ }
+ }
+ },
+ created() {
+ this.getCode()
+ },
+ methods: {
+ // 鐢ㄦ埛鐧诲綍
+ handleUserLogin() {
+ this.$tab.navigateTo(`/pages/login`)
+ },
+ // 鑾峰彇鍥惧舰楠岃瘉鐮�
+ getCode() {
+ getCodeImg().then(res => {
+ this.captchaEnabled = res.captchaEnabled === undefined ? true : res.captchaEnabled
+ if (this.captchaEnabled) {
+ this.codeUrl = 'data:image/gif;base64,' + res.img
+ this.registerForm.uuid = res.uuid
+ }
+ })
+ },
+ // 娉ㄥ唽鏂规硶
+ async handleRegister() {
+ if (this.registerForm.username === "") {
+ this.$modal.msgError("璇疯緭鍏ユ偍鐨勮处鍙�")
+ } else if (this.registerForm.password === "") {
+ this.$modal.msgError("璇疯緭鍏ユ偍鐨勫瘑鐮�")
+ } else if (this.registerForm.confirmPassword === "") {
+ this.$modal.msgError("璇峰啀娆¤緭鍏ユ偍鐨勫瘑鐮�")
+ } else if (this.registerForm.password !== this.registerForm.confirmPassword) {
+ this.$modal.msgError("涓ゆ杈撳叆鐨勫瘑鐮佷笉涓�鑷�")
+ } else if (this.registerForm.code === "" && this.captchaEnabled) {
+ this.$modal.msgError("璇疯緭鍏ラ獙璇佺爜")
+ } else {
+ this.$modal.loading("娉ㄥ唽涓紝璇疯�愬績绛夊緟...")
+ this.register()
+ }
+ },
+ // 鐢ㄦ埛娉ㄥ唽
+ async register() {
+ register(this.registerForm).then(res => {
+ this.$modal.closeLoading()
+ uni.showModal({
+ title: "绯荤粺鎻愮ず",
+ content: "鎭枩浣狅紝鎮ㄧ殑璐﹀彿 " + this.registerForm.username + " 娉ㄥ唽鎴愬姛锛�",
+ success: function (res) {
+ if (res.confirm) {
+ uni.redirectTo({ url: `/pages/login` });
+ }
+ }
+ })
+ }).catch(() => {
+ if (this.captchaEnabled) {
+ this.getCode()
+ }
+ })
+ },
+ // 娉ㄥ唽鎴愬姛鍚庯紝澶勭悊鍑芥暟
+ registerSuccess(result) {
+ // 璁剧疆鐢ㄦ埛淇℃伅
+ this.$store.dispatch('GetInfo').then(res => {
+ this.$tab.reLaunch('/pages/index')
+ })
+ }
+ }
+ }
+</script>
+
+<style lang="scss">
+ page {
+ background-color: #ffffff;
+ }
+
+ .normal-login-container {
+ width: 100%;
+
+ .logo-content {
+ width: 100%;
+ font-size: 21px;
+ text-align: center;
+ padding-top: 15%;
+
+ image {
+ border-radius: 4px;
+ }
+
+ .title {
+ margin-left: 10px;
+ }
+ }
+
+ .login-form-content {
+ text-align: center;
+ margin: 20px auto;
+ margin-top: 15%;
+ width: 80%;
+
+ .input-item {
+ margin: 20px auto;
+ background-color: #f5f6f7;
+ height: 45px;
+ border-radius: 20px;
+
+ .icon {
+ font-size: 38rpx;
+ margin-left: 10px;
+ color: #999;
+ }
+
+ .input {
+ width: 100%;
+ font-size: 14px;
+ line-height: 20px;
+ text-align: left;
+ padding-left: 15px;
+ }
+
+ }
+
+ .register-btn {
+ margin-top: 40px;
+ height: 45px;
+ }
+
+ .xieyi {
+ color: #333;
+ margin-top: 20px;
+ }
+
+ .login-code {
+ height: 38px;
+ float: right;
+
+ .login-code-img {
+ height: 38px;
+ position: absolute;
+ margin-left: 10px;
+ width: 200rpx;
+ }
+ }
+ }
+ }
+
+</style>
diff --git a/app/pages/work/index.vue b/app/pages/work/index.vue
new file mode 100644
index 0000000..1afefc9
--- /dev/null
+++ b/app/pages/work/index.vue
@@ -0,0 +1,183 @@
+<template>
+ <view class="work-container">
+ <!-- 杞挱鍥� -->
+ <uni-swiper-dot class="uni-swiper-dot-box" :info="data" :current="current" field="content">
+ <swiper class="swiper-box" :current="swiperDotIndex" @change="changeSwiper">
+ <swiper-item v-for="(item, index) in data" :key="index">
+ <view class="swiper-item" @click="clickBannerItem(item)">
+ <image :src="item.image" mode="aspectFill" :draggable="false" />
+ </view>
+ </swiper-item>
+ </swiper>
+ </uni-swiper-dot>
+
+ <!-- 瀹牸缁勪欢 -->
+ <uni-section title="绯荤粺绠$悊" type="line"></uni-section>
+ <view class="grid-body">
+ <uni-grid :column="4" :showBorder="false" @change="changeGrid">
+ <uni-grid-item>
+ <view class="grid-item-box">
+ <uni-icons type="person-filled" size="30"></uni-icons>
+ <text class="text">鐢ㄦ埛绠$悊</text>
+ </view>
+ </uni-grid-item>
+ <uni-grid-item>
+ <view class="grid-item-box">
+ <uni-icons type="staff-filled" size="30"></uni-icons>
+ <text class="text">瑙掕壊绠$悊</text>
+ </view>
+ </uni-grid-item>
+ <uni-grid-item>
+ <view class="grid-item-box">
+ <uni-icons type="color" size="30"></uni-icons>
+ <text class="text">鑿滃崟绠$悊</text>
+ </view>
+ </uni-grid-item>
+ <uni-grid-item>
+ <view class="grid-item-box">
+ <uni-icons type="settings-filled" size="30"></uni-icons>
+ <text class="text">閮ㄩ棬绠$悊</text>
+ </view>
+ </uni-grid-item>
+ <uni-grid-item>
+ <view class="grid-item-box">
+ <uni-icons type="heart-filled" size="30"></uni-icons>
+ <text class="text">宀椾綅绠$悊</text>
+ </view>
+ </uni-grid-item>
+ <uni-grid-item>
+ <view class="grid-item-box">
+ <uni-icons type="bars" size="30"></uni-icons>
+ <text class="text">瀛楀吀绠$悊</text>
+ </view>
+ </uni-grid-item>
+ <uni-grid-item>
+ <view class="grid-item-box">
+ <uni-icons type="gear-filled" size="30"></uni-icons>
+ <text class="text">鍙傛暟璁剧疆</text>
+ </view>
+ </uni-grid-item>
+ <uni-grid-item>
+ <view class="grid-item-box">
+ <uni-icons type="chat-filled" size="30"></uni-icons>
+ <text class="text">閫氱煡鍏憡</text>
+ </view>
+ </uni-grid-item>
+ <uni-grid-item>
+ <view class="grid-item-box">
+ <uni-icons type="wallet-filled" size="30"></uni-icons>
+ <text class="text">鏃ュ織绠$悊</text>
+ </view>
+ </uni-grid-item>
+ </uni-grid>
+ </view>
+ </view>
+</template>
+
+<script>
+ export default {
+ data() {
+ return {
+ current: 0,
+ swiperDotIndex: 0,
+ data: [{
+ image: '/static/images/banner/banner01.jpg'
+ },
+ {
+ image: '/static/images/banner/banner02.jpg'
+ },
+ {
+ image: '/static/images/banner/banner03.jpg'
+ }
+ ]
+ }
+ },
+ methods: {
+ clickBannerItem(item) {
+ console.info(item)
+ },
+ changeSwiper(e) {
+ this.current = e.detail.current
+ },
+ changeGrid(e) {
+ this.$modal.showToast('妯″潡寤鸿涓瓇')
+ }
+ }
+ }
+</script>
+
+<style lang="scss">
+ /* #ifndef APP-NVUE */
+ page {
+ display: flex;
+ flex-direction: column;
+ box-sizing: border-box;
+ background-color: #fff;
+ min-height: 100%;
+ height: auto;
+ }
+
+ view {
+ font-size: 14px;
+ line-height: inherit;
+ }
+
+ /* #endif */
+
+ .text {
+ text-align: center;
+ font-size: 26rpx;
+ margin-top: 10rpx;
+ }
+
+ .grid-item-box {
+ flex: 1;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding: 15px 0;
+ }
+
+ .uni-margin-wrap {
+ width: 690rpx;
+ width: 100%;
+ ;
+ }
+
+ .swiper {
+ height: 300rpx;
+ }
+
+ .swiper-box {
+ height: 150px;
+ }
+
+ .swiper-item {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ color: #fff;
+ height: 300rpx;
+ line-height: 300rpx;
+ }
+
+ @media screen and (min-width: 500px) {
+ .uni-swiper-dot-box {
+ width: 400px;
+ /* #ifndef APP-NVUE */
+ margin: 0 auto;
+ /* #endif */
+ margin-top: 8px;
+ }
+
+ .image {
+ width: 100%;
+ }
+ }
+</style>
diff --git a/app/permission.js b/app/permission.js
new file mode 100644
index 0000000..cbaec53
--- /dev/null
+++ b/app/permission.js
@@ -0,0 +1,39 @@
+import { getToken } from '@/utils/auth'
+
+// 鐧诲綍椤甸潰
+const loginPage = "/pages/login"
+
+// 椤甸潰鐧藉悕鍗�
+const whiteList = [
+ '/pages/login', '/pages/register', '/pages/common/webview/index'
+]
+
+// 妫�鏌ュ湴鍧�鐧藉悕鍗�
+function checkWhite(url) {
+ const path = url.split('?')[0]
+ return whiteList.indexOf(path) !== -1
+}
+
+// 椤甸潰璺宠浆楠岃瘉鎷︽埅鍣�
+let list = ["navigateTo", "redirectTo", "reLaunch", "switchTab"]
+list.forEach(item => {
+ uni.addInterceptor(item, {
+ invoke(to) {
+ if (getToken()) {
+ if (to.url === loginPage) {
+ uni.reLaunch({ url: "/" })
+ }
+ return true
+ } else {
+ if (checkWhite(to.url)) {
+ return true
+ }
+ uni.reLaunch({ url: loginPage })
+ return false
+ }
+ },
+ fail(err) {
+ console.log(err)
+ }
+ })
+})
diff --git a/app/plugins/auth.js b/app/plugins/auth.js
new file mode 100644
index 0000000..3b91c14
--- /dev/null
+++ b/app/plugins/auth.js
@@ -0,0 +1,60 @@
+import store from '@/store'
+
+function authPermission(permission) {
+ const all_permission = "*:*:*"
+ const permissions = store.getters && store.getters.permissions
+ if (permission && permission.length > 0) {
+ return permissions.some(v => {
+ return all_permission === v || v === permission
+ })
+ } else {
+ return false
+ }
+}
+
+function authRole(role) {
+ const super_admin = "admin"
+ const roles = store.getters && store.getters.roles
+ if (role && role.length > 0) {
+ return roles.some(v => {
+ return super_admin === v || v === role
+ })
+ } else {
+ return false
+ }
+}
+
+export default {
+ // 楠岃瘉鐢ㄦ埛鏄惁鍏峰鏌愭潈闄�
+ hasPermi(permission) {
+ return authPermission(permission)
+ },
+ // 楠岃瘉鐢ㄦ埛鏄惁鍚湁鎸囧畾鏉冮檺锛屽彧闇�鍖呭惈鍏朵腑涓�涓�
+ hasPermiOr(permissions) {
+ return permissions.some(item => {
+ return authPermission(item)
+ })
+ },
+ // 楠岃瘉鐢ㄦ埛鏄惁鍚湁鎸囧畾鏉冮檺锛屽繀椤诲叏閮ㄦ嫢鏈�
+ hasPermiAnd(permissions) {
+ return permissions.every(item => {
+ return authPermission(item)
+ })
+ },
+ // 楠岃瘉鐢ㄦ埛鏄惁鍏峰鏌愯鑹�
+ hasRole(role) {
+ return authRole(role)
+ },
+ // 楠岃瘉鐢ㄦ埛鏄惁鍚湁鎸囧畾瑙掕壊锛屽彧闇�鍖呭惈鍏朵腑涓�涓�
+ hasRoleOr(roles) {
+ return roles.some(item => {
+ return authRole(item)
+ })
+ },
+ // 楠岃瘉鐢ㄦ埛鏄惁鍚湁鎸囧畾瑙掕壊锛屽繀椤诲叏閮ㄦ嫢鏈�
+ hasRoleAnd(roles) {
+ return roles.every(item => {
+ return authRole(item)
+ })
+ }
+}
diff --git a/app/plugins/index.js b/app/plugins/index.js
new file mode 100644
index 0000000..efbae15
--- /dev/null
+++ b/app/plugins/index.js
@@ -0,0 +1,14 @@
+import tab from './tab'
+import auth from './auth'
+import modal from './modal'
+
+export default {
+ install(Vue) {
+ // 椤电鎿嶄綔
+ Vue.prototype.$tab = tab
+ // 璁よ瘉瀵硅薄
+ Vue.prototype.$auth = auth
+ // 妯℃�佹瀵硅薄
+ Vue.prototype.$modal = modal
+ }
+}
diff --git a/app/plugins/modal.js b/app/plugins/modal.js
new file mode 100644
index 0000000..99b2215
--- /dev/null
+++ b/app/plugins/modal.js
@@ -0,0 +1,74 @@
+export default {
+ // 娑堟伅鎻愮ず
+ msg(content) {
+ uni.showToast({
+ title: content,
+ icon: 'none'
+ })
+ },
+ // 閿欒娑堟伅
+ msgError(content) {
+ uni.showToast({
+ title: content,
+ icon: 'error'
+ })
+ },
+ // 鎴愬姛娑堟伅
+ msgSuccess(content) {
+ uni.showToast({
+ title: content,
+ icon: 'success'
+ })
+ },
+ // 闅愯棌娑堟伅
+ hideMsg(content) {
+ uni.hideToast()
+ },
+ // 寮瑰嚭鎻愮ず
+ alert(content, title) {
+ uni.showModal({
+ title: title || '绯荤粺鎻愮ず',
+ content: content,
+ showCancel: false
+ })
+ },
+ // 纭绐椾綋
+ confirm(content, title) {
+ return new Promise((resolve, reject) => {
+ uni.showModal({
+ title: title || '绯荤粺鎻愮ず',
+ content: content,
+ cancelText: '鍙栨秷',
+ confirmText: '纭畾',
+ success: function(res) {
+ if (res.confirm) {
+ resolve(res.confirm)
+ }
+ }
+ })
+ })
+ },
+ // 鎻愮ず淇℃伅
+ showToast(option) {
+ if (typeof option === "object") {
+ uni.showToast(option)
+ } else {
+ uni.showToast({
+ title: option,
+ icon: "none",
+ duration: 2500
+ })
+ }
+ },
+ // 鎵撳紑閬僵灞�
+ loading(content) {
+ uni.showLoading({
+ title: content,
+ icon: 'none'
+ })
+ },
+ // 鍏抽棴閬僵灞�
+ closeLoading() {
+ uni.hideLoading()
+ }
+}
diff --git a/app/plugins/tab.js b/app/plugins/tab.js
new file mode 100644
index 0000000..5d1b305
--- /dev/null
+++ b/app/plugins/tab.js
@@ -0,0 +1,30 @@
+export default {
+ // 鍏抽棴鎵�鏈夐〉闈紝鎵撳紑鍒板簲鐢ㄥ唴鐨勬煇涓〉闈�
+ reLaunch(url) {
+ return uni.reLaunch({
+ url: url
+ })
+ },
+ // 璺宠浆鍒皌abBar椤甸潰锛屽苟鍏抽棴鍏朵粬鎵�鏈夐潪tabBar椤甸潰
+ switchTab(url) {
+ return uni.switchTab({
+ url: url
+ })
+ },
+ // 鍏抽棴褰撳墠椤甸潰锛岃烦杞埌搴旂敤鍐呯殑鏌愪釜椤甸潰
+ redirectTo(url) {
+ return uni.redirectTo({
+ url: url
+ })
+ },
+ // 淇濈暀褰撳墠椤甸潰锛岃烦杞埌搴旂敤鍐呯殑鏌愪釜椤甸潰
+ navigateTo(url) {
+ return uni.navigateTo({
+ url: url
+ })
+ },
+ // 鍏抽棴褰撳墠椤甸潰锛岃繑鍥炰笂涓�椤甸潰鎴栧绾ч〉闈�
+ navigateBack() {
+ return uni.navigateBack()
+ }
+}
diff --git a/app/static/favicon.ico b/app/static/favicon.ico
new file mode 100644
index 0000000..6f07782
--- /dev/null
+++ b/app/static/favicon.ico
Binary files differ
diff --git a/app/static/font/iconfont.css b/app/static/font/iconfont.css
new file mode 100644
index 0000000..afd7102
--- /dev/null
+++ b/app/static/font/iconfont.css
@@ -0,0 +1,90 @@
+@font-face {
+ font-family: "iconfont";
+ src: url('@/static/font/iconfont.ttf') format('truetype');
+}
+
+.iconfont {
+ font-family: "iconfont" !important;
+ font-size: 16px;
+ display: inline-block;
+ font-style: normal;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+.icon-user:before {
+ content: "\e7ae";
+}
+
+.icon-password:before {
+ content: "\e8b2";
+}
+
+.icon-code:before {
+ content: "\e699";
+}
+
+.icon-setting:before {
+ content: "\e6cc";
+}
+
+.icon-share:before {
+ content: "\e739";
+}
+
+.icon-edit:before {
+ content: "\e60c";
+}
+
+.icon-version:before {
+ content: "\e63f";
+}
+
+.icon-service:before {
+ content: "\e6ff";
+}
+
+.icon-friendfill:before {
+ content: "\e726";
+}
+
+.icon-community:before {
+ content: "\e741";
+}
+
+.icon-people:before {
+ content: "\e736";
+}
+
+.icon-dianzan:before {
+ content: "\ec7f";
+}
+
+.icon-right:before {
+ content: "\e7eb";
+}
+
+.icon-logout:before {
+ content: "\e61d";
+}
+
+.icon-help:before {
+ content: "\e616";
+}
+
+.icon-github:before {
+ content: "\e628";
+}
+
+.icon-aixin:before {
+ content: "\e601";
+}
+
+.icon-clean:before {
+ content: "\e607";
+}
+
+.icon-refresh:before {
+ content: "\e604";
+}
+
diff --git a/app/static/font/iconfont.ttf b/app/static/font/iconfont.ttf
new file mode 100644
index 0000000..53915ca
--- /dev/null
+++ b/app/static/font/iconfont.ttf
Binary files differ
diff --git a/app/static/images/banner/banner01.jpg b/app/static/images/banner/banner01.jpg
new file mode 100644
index 0000000..c44d84c
--- /dev/null
+++ b/app/static/images/banner/banner01.jpg
Binary files differ
diff --git a/app/static/images/banner/banner02.jpg b/app/static/images/banner/banner02.jpg
new file mode 100644
index 0000000..1086afd
--- /dev/null
+++ b/app/static/images/banner/banner02.jpg
Binary files differ
diff --git a/app/static/images/banner/banner03.jpg b/app/static/images/banner/banner03.jpg
new file mode 100644
index 0000000..092a5fc
--- /dev/null
+++ b/app/static/images/banner/banner03.jpg
Binary files differ
diff --git a/app/static/images/profile.jpg b/app/static/images/profile.jpg
new file mode 100644
index 0000000..b3a940b
--- /dev/null
+++ b/app/static/images/profile.jpg
Binary files differ
diff --git a/app/static/images/tabbar/home.png b/app/static/images/tabbar/home.png
new file mode 100644
index 0000000..50acdfd
--- /dev/null
+++ b/app/static/images/tabbar/home.png
Binary files differ
diff --git a/app/static/images/tabbar/home_.png b/app/static/images/tabbar/home_.png
new file mode 100644
index 0000000..a408f71
--- /dev/null
+++ b/app/static/images/tabbar/home_.png
Binary files differ
diff --git a/app/static/images/tabbar/mine.png b/app/static/images/tabbar/mine.png
new file mode 100644
index 0000000..f13fe44
--- /dev/null
+++ b/app/static/images/tabbar/mine.png
Binary files differ
diff --git a/app/static/images/tabbar/mine_.png b/app/static/images/tabbar/mine_.png
new file mode 100644
index 0000000..8a0a742
--- /dev/null
+++ b/app/static/images/tabbar/mine_.png
Binary files differ
diff --git a/app/static/images/tabbar/work.png b/app/static/images/tabbar/work.png
new file mode 100644
index 0000000..21e130d
--- /dev/null
+++ b/app/static/images/tabbar/work.png
Binary files differ
diff --git a/app/static/images/tabbar/work_.png b/app/static/images/tabbar/work_.png
new file mode 100644
index 0000000..80b979c
--- /dev/null
+++ b/app/static/images/tabbar/work_.png
Binary files differ
diff --git a/app/static/index.html b/app/static/index.html
new file mode 100644
index 0000000..a7af653
--- /dev/null
+++ b/app/static/index.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html lang="zh-CN">
+ <head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+ <meta name="renderer" content="webkit">
+ <title><%= htmlWebpackPlugin.options.title %></title>
+ <link rel="shortcut icon" type="image/x-icon" href="<%= BASE_URL %>static/favicon.ico">
+ <script>
+ var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') || CSS.supports('top: constant(a)'))
+ document.write('<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' + (coverSupport ? ', viewport-fit=cover' : '') + '" />')
+ </script>
+ <link rel="stylesheet" href="<%= BASE_URL %>static/index.<%= VUE_APP_INDEX_CSS_HASH %>.css" />
+ </head>
+ <body>
+ <noscript>
+ <strong>鏈珯鐐瑰繀椤昏寮�鍚疛avaScript鎵嶈兘杩愯.</strong>
+ </noscript>
+ <div id="app"></div>
+</html>
\ No newline at end of file
diff --git a/app/static/logo.png b/app/static/logo.png
new file mode 100644
index 0000000..d4ebbf0
--- /dev/null
+++ b/app/static/logo.png
Binary files differ
diff --git a/app/static/logo200.png b/app/static/logo200.png
new file mode 100644
index 0000000..ffa9988
--- /dev/null
+++ b/app/static/logo200.png
Binary files differ
diff --git a/app/static/scss/colorui.css b/app/static/scss/colorui.css
new file mode 100644
index 0000000..07380a5
--- /dev/null
+++ b/app/static/scss/colorui.css
@@ -0,0 +1,5142 @@
+/*
+ ColorUi for uniApp v2.1.6 | by 鏂囨檽娓� 2019-05-31 10:44:24
+ 浠呬緵瀛︿範浜ゆ祦锛屽浣滃畠鐢ㄦ墍鎵垮彈鐨勬硶寰嬭矗浠讳竴姒備笌浣滆�呮棤鍏�
+
+ *浣跨敤ColorUi寮�鍙戞墿灞曚笌鎻掍欢鏃讹紝璇锋敞鏄庡熀浜嶤olorUi寮�鍙�
+
+ 锛圦Q浜ゆ祦缇わ細240787041锛�
+*/
+
+/* ==================
+ main 鍒濆鍖�
+ ==================== */
+body {
+ background-color: #f1f1f1;
+ font-size: 28upx;
+ color: #333333;
+ font-family: Helvetica Neue, Helvetica, sans-serif;
+}
+
+view,
+scroll-view,
+swiper,
+button,
+input,
+textarea,
+label,
+navigator,
+image {
+ box-sizing: border-box;
+}
+
+.round {
+ border-radius: 5000upx;
+}
+
+.radius {
+ border-radius: 6upx;
+}
+
+/* ==================
+ 鍥剧墖
+ ==================== */
+
+image {
+ max-width: 100%;
+ display: inline-block;
+ position: relative;
+ z-index: 0;
+}
+
+image.loading::before {
+ content: "";
+ background-color: #f5f5f5;
+ display: block;
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ z-index: -2;
+}
+
+image.loading::after {
+ content: "\e7f1";
+ font-family: "cuIcon";
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 32upx;
+ height: 32upx;
+ line-height: 32upx;
+ right: 0;
+ bottom: 0;
+ z-index: -1;
+ font-size: 32upx;
+ margin: auto;
+ color: #ccc;
+ -webkit-animation: cuIcon-spin 2s infinite linear;
+ animation: cuIcon-spin 2s infinite linear;
+ display: block;
+}
+
+.response {
+ width: 100%;
+}
+
+/* ==================
+ 寮�鍏�
+ ==================== */
+
+switch,
+checkbox,
+radio {
+ position: relative;
+}
+
+switch::after,
+switch::before {
+ font-family: "cuIcon";
+ content: "\e645";
+ position: absolute;
+ color: #ffffff !important;
+ top: 0%;
+ left: 0upx;
+ font-size: 26upx;
+ line-height: 26px;
+ width: 50%;
+ text-align: center;
+ pointer-events: none;
+ transform: scale(0, 0);
+ transition: all 0.3s ease-in-out 0s;
+ z-index: 9;
+ bottom: 0;
+ height: 26px;
+ margin: auto;
+}
+
+switch::before {
+ content: "\e646";
+ right: 0;
+ transform: scale(1, 1);
+ left: auto;
+}
+
+switch[checked]::after,
+switch.checked::after {
+ transform: scale(1, 1);
+}
+
+switch[checked]::before,
+switch.checked::before {
+ transform: scale(0, 0);
+}
+
+/* #ifndef MP-ALIPAY */
+radio::before,
+checkbox::before {
+ font-family: "cuIcon";
+ content: "\e645";
+ position: absolute;
+ color: #ffffff !important;
+ top: 50%;
+ margin-top: -8px;
+ right: 5px;
+ font-size: 32upx;
+ line-height: 16px;
+ pointer-events: none;
+ transform: scale(1, 1);
+ transition: all 0.3s ease-in-out 0s;
+ z-index: 9;
+}
+
+radio .wx-radio-input,
+checkbox .wx-checkbox-input,
+radio .uni-radio-input,
+checkbox .uni-checkbox-input {
+ margin: 0;
+ width: 24px;
+ height: 24px;
+}
+
+checkbox.round .wx-checkbox-input,
+checkbox.round .uni-checkbox-input {
+ border-radius: 100upx;
+}
+
+/* #endif */
+
+switch[checked]::before {
+ transform: scale(0, 0);
+}
+
+switch .wx-switch-input,
+switch .uni-switch-input {
+ border: none;
+ padding: 0 24px;
+ width: 48px;
+ height: 26px;
+ margin: 0;
+ border-radius: 100upx;
+}
+
+switch .wx-switch-input:not([class*="bg-"]),
+switch .uni-switch-input:not([class*="bg-"]) {
+ background: #8799a3 !important;
+}
+
+switch .wx-switch-input::after,
+switch .uni-switch-input::after {
+ margin: auto;
+ width: 26px;
+ height: 26px;
+ border-radius: 100upx;
+ left: 0upx;
+ top: 0upx;
+ bottom: 0upx;
+ position: absolute;
+ transform: scale(0.9, 0.9);
+ transition: all 0.1s ease-in-out 0s;
+}
+
+switch .wx-switch-input.wx-switch-input-checked::after,
+switch .uni-switch-input.uni-switch-input-checked::after {
+ margin: auto;
+ left: 22px;
+ box-shadow: none;
+ transform: scale(0.9, 0.9);
+}
+
+radio-group {
+ display: inline-block;
+}
+
+
+
+switch.radius .wx-switch-input::after,
+switch.radius .wx-switch-input,
+switch.radius .wx-switch-input::before,
+switch.radius .uni-switch-input::after,
+switch.radius .uni-switch-input,
+switch.radius .uni-switch-input::before {
+ border-radius: 10upx;
+}
+
+switch .wx-switch-input::before,
+radio.radio::before,
+checkbox .wx-checkbox-input::before,
+radio .wx-radio-input::before,
+switch .uni-switch-input::before,
+radio.radio::before,
+checkbox .uni-checkbox-input::before,
+radio .uni-radio-input::before {
+ display: none;
+}
+
+radio.radio[checked]::after,
+radio.radio .uni-radio-input-checked::after {
+ content: "";
+ background-color: transparent;
+ display: block;
+ position: absolute;
+ width: 8px;
+ height: 8px;
+ z-index: 999;
+ top: 0upx;
+ left: 0upx;
+ right: 0;
+ bottom: 0;
+ margin: auto;
+ border-radius: 200upx;
+ /* #ifndef MP */
+ border: 7px solid #ffffff !important;
+ /* #endif */
+
+ /* #ifdef MP */
+ border: 8px solid #ffffff !important;
+ /* #endif */
+}
+
+.switch-sex::after {
+ content: "\e71c";
+}
+
+.switch-sex::before {
+ content: "\e71a";
+}
+
+.switch-sex .wx-switch-input,
+.switch-sex .uni-switch-input {
+ background: #e54d42 !important;
+ border-color: #e54d42 !important;
+}
+
+.switch-sex[checked] .wx-switch-input,
+.switch-sex.checked .uni-switch-input {
+ background: #0081ff !important;
+ border-color: #0081ff !important;
+}
+
+switch.red[checked] .wx-switch-input.wx-switch-input-checked,
+checkbox.red[checked] .wx-checkbox-input,
+radio.red[checked] .wx-radio-input,
+switch.red.checked .uni-switch-input.uni-switch-input-checked,
+checkbox.red.checked .uni-checkbox-input,
+radio.red.checked .uni-radio-input {
+ background-color: #e54d42 !important;
+ border-color: #e54d42 !important;
+ color: #ffffff !important;
+}
+
+switch.orange[checked] .wx-switch-input,
+checkbox.orange[checked] .wx-checkbox-input,
+radio.orange[checked] .wx-radio-input,
+switch.orange.checked .uni-switch-input,
+checkbox.orange.checked .uni-checkbox-input,
+radio.orange.checked .uni-radio-input {
+ background-color: #f37b1d !important;
+ border-color: #f37b1d !important;
+ color: #ffffff !important;
+}
+
+switch.yellow[checked] .wx-switch-input,
+checkbox.yellow[checked] .wx-checkbox-input,
+radio.yellow[checked] .wx-radio-input,
+switch.yellow.checked .uni-switch-input,
+checkbox.yellow.checked .uni-checkbox-input,
+radio.yellow.checked .uni-radio-input {
+ background-color: #fbbd08 !important;
+ border-color: #fbbd08 !important;
+ color: #333333 !important;
+}
+
+switch.olive[checked] .wx-switch-input,
+checkbox.olive[checked] .wx-checkbox-input,
+radio.olive[checked] .wx-radio-input,
+switch.olive.checked .uni-switch-input,
+checkbox.olive.checked .uni-checkbox-input,
+radio.olive.checked .uni-radio-input {
+ background-color: #8dc63f !important;
+ border-color: #8dc63f !important;
+ color: #ffffff !important;
+}
+
+switch.green[checked] .wx-switch-input,
+switch[checked] .wx-switch-input,
+checkbox.green[checked] .wx-checkbox-input,
+checkbox[checked] .wx-checkbox-input,
+radio.green[checked] .wx-radio-input,
+radio[checked] .wx-radio-input,
+switch.green.checked .uni-switch-input,
+switch.checked .uni-switch-input,
+checkbox.green.checked .uni-checkbox-input,
+checkbox.checked .uni-checkbox-input,
+radio.green.checked .uni-radio-input,
+radio.checked .uni-radio-input {
+ background-color: #39b54a !important;
+ border-color: #39b54a !important;
+ color: #ffffff !important;
+ border-color: #39B54A !important;
+}
+
+switch.cyan[checked] .wx-switch-input,
+checkbox.cyan[checked] .wx-checkbox-input,
+radio.cyan[checked] .wx-radio-input,
+switch.cyan.checked .uni-switch-input,
+checkbox.cyan.checked .uni-checkbox-input,
+radio.cyan.checked .uni-radio-input {
+ background-color: #1cbbb4 !important;
+ border-color: #1cbbb4 !important;
+ color: #ffffff !important;
+}
+
+switch.blue[checked] .wx-switch-input,
+checkbox.blue[checked] .wx-checkbox-input,
+radio.blue[checked] .wx-radio-input,
+switch.blue.checked .uni-switch-input,
+checkbox.blue.checked .uni-checkbox-input,
+radio.blue.checked .uni-radio-input {
+ background-color: #0081ff !important;
+ border-color: #0081ff !important;
+ color: #ffffff !important;
+}
+
+switch.purple[checked] .wx-switch-input,
+checkbox.purple[checked] .wx-checkbox-input,
+radio.purple[checked] .wx-radio-input,
+switch.purple.checked .uni-switch-input,
+checkbox.purple.checked .uni-checkbox-input,
+radio.purple.checked .uni-radio-input {
+ background-color: #6739b6 !important;
+ border-color: #6739b6 !important;
+ color: #ffffff !important;
+}
+
+switch.mauve[checked] .wx-switch-input,
+checkbox.mauve[checked] .wx-checkbox-input,
+radio.mauve[checked] .wx-radio-input,
+switch.mauve.checked .uni-switch-input,
+checkbox.mauve.checked .uni-checkbox-input,
+radio.mauve.checked .uni-radio-input {
+ background-color: #9c26b0 !important;
+ border-color: #9c26b0 !important;
+ color: #ffffff !important;
+}
+
+switch.pink[checked] .wx-switch-input,
+checkbox.pink[checked] .wx-checkbox-input,
+radio.pink[checked] .wx-radio-input,
+switch.pink.checked .uni-switch-input,
+checkbox.pink.checked .uni-checkbox-input,
+radio.pink.checked .uni-radio-input {
+ background-color: #e03997 !important;
+ border-color: #e03997 !important;
+ color: #ffffff !important;
+}
+
+switch.brown[checked] .wx-switch-input,
+checkbox.brown[checked] .wx-checkbox-input,
+radio.brown[checked] .wx-radio-input,
+switch.brown.checked .uni-switch-input,
+checkbox.brown.checked .uni-checkbox-input,
+radio.brown.checked .uni-radio-input {
+ background-color: #a5673f !important;
+ border-color: #a5673f !important;
+ color: #ffffff !important;
+}
+
+switch.grey[checked] .wx-switch-input,
+checkbox.grey[checked] .wx-checkbox-input,
+radio.grey[checked] .wx-radio-input,
+switch.grey.checked .uni-switch-input,
+checkbox.grey.checked .uni-checkbox-input,
+radio.grey.checked .uni-radio-input {
+ background-color: #8799a3 !important;
+ border-color: #8799a3 !important;
+ color: #ffffff !important;
+}
+
+switch.gray[checked] .wx-switch-input,
+checkbox.gray[checked] .wx-checkbox-input,
+radio.gray[checked] .wx-radio-input,
+switch.gray.checked .uni-switch-input,
+checkbox.gray.checked .uni-checkbox-input,
+radio.gray.checked .uni-radio-input {
+ background-color: #f0f0f0 !important;
+ border-color: #f0f0f0 !important;
+ color: #333333 !important;
+}
+
+switch.black[checked] .wx-switch-input,
+checkbox.black[checked] .wx-checkbox-input,
+radio.black[checked] .wx-radio-input,
+switch.black.checked .uni-switch-input,
+checkbox.black.checked .uni-checkbox-input,
+radio.black.checked .uni-radio-input {
+ background-color: #333333 !important;
+ border-color: #333333 !important;
+ color: #ffffff !important;
+}
+
+switch.white[checked] .wx-switch-input,
+checkbox.white[checked] .wx-checkbox-input,
+radio.white[checked] .wx-radio-input,
+switch.white.checked .uni-switch-input,
+checkbox.white.checked .uni-checkbox-input,
+radio.white.checked .uni-radio-input {
+ background-color: #ffffff !important;
+ border-color: #ffffff !important;
+ color: #333333 !important;
+}
+
+/* ==================
+ 杈规
+ ==================== */
+
+/* -- 瀹炵嚎 -- */
+
+.solid,
+.solid-top,
+.solid-right,
+.solid-bottom,
+.solid-left,
+.solids,
+.solids-top,
+.solids-right,
+.solids-bottom,
+.solids-left,
+.dashed,
+.dashed-top,
+.dashed-right,
+.dashed-bottom,
+.dashed-left {
+ position: relative;
+}
+
+.solid::after,
+.solid-top::after,
+.solid-right::after,
+.solid-bottom::after,
+.solid-left::after,
+.solids::after,
+.solids-top::after,
+.solids-right::after,
+.solids-bottom::after,
+.solids-left::after,
+.dashed::after,
+.dashed-top::after,
+.dashed-right::after,
+.dashed-bottom::after,
+.dashed-left::after {
+ content: " ";
+ width: 200%;
+ height: 200%;
+ position: absolute;
+ top: 0;
+ left: 0;
+ border-radius: inherit;
+ transform: scale(0.5);
+ transform-origin: 0 0;
+ pointer-events: none;
+ box-sizing: border-box;
+}
+
+.solid::after {
+ border: 1upx solid rgba(0, 0, 0, 0.1);
+}
+
+.solid-top::after {
+ border-top: 1upx solid rgba(0, 0, 0, 0.1);
+}
+
+.solid-right::after {
+ border-right: 1upx solid rgba(0, 0, 0, 0.1);
+}
+
+.solid-bottom::after {
+ border-bottom: 1upx solid rgba(0, 0, 0, 0.1);
+}
+
+.solid-left::after {
+ border-left: 1upx solid rgba(0, 0, 0, 0.1);
+}
+
+.solids::after {
+ border: 8upx solid #eee;
+}
+
+.solids-top::after {
+ border-top: 8upx solid #eee;
+}
+
+.solids-right::after {
+ border-right: 8upx solid #eee;
+}
+
+.solids-bottom::after {
+ border-bottom: 8upx solid #eee;
+}
+
+.solids-left::after {
+ border-left: 8upx solid #eee;
+}
+
+/* -- 铏氱嚎 -- */
+
+.dashed::after {
+ border: 1upx dashed #ddd;
+}
+
+.dashed-top::after {
+ border-top: 1upx dashed #ddd;
+}
+
+.dashed-right::after {
+ border-right: 1upx dashed #ddd;
+}
+
+.dashed-bottom::after {
+ border-bottom: 1upx dashed #ddd;
+}
+
+.dashed-left::after {
+ border-left: 1upx dashed #ddd;
+}
+
+/* -- 闃村奖 -- */
+
+.shadow[class*='white'] {
+ --ShadowSize: 0 1upx 6upx;
+}
+
+.shadow-lg {
+ --ShadowSize: 0upx 40upx 100upx 0upx;
+}
+
+.shadow-warp {
+ position: relative;
+ box-shadow: 0 0 10upx rgba(0, 0, 0, 0.1);
+}
+
+.shadow-warp:before,
+.shadow-warp:after {
+ position: absolute;
+ content: "";
+ top: 20upx;
+ bottom: 30upx;
+ left: 20upx;
+ width: 50%;
+ box-shadow: 0 30upx 20upx rgba(0, 0, 0, 0.2);
+ transform: rotate(-3deg);
+ z-index: -1;
+}
+
+.shadow-warp:after {
+ right: 20upx;
+ left: auto;
+ transform: rotate(3deg);
+}
+
+.shadow-blur {
+ position: relative;
+}
+
+.shadow-blur::before {
+ content: "";
+ display: block;
+ background: inherit;
+ filter: blur(10upx);
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ top: 10upx;
+ left: 10upx;
+ z-index: -1;
+ opacity: 0.4;
+ transform-origin: 0 0;
+ border-radius: inherit;
+ transform: scale(1, 1);
+}
+
+/* ==================
+ 鎸夐挳
+ ==================== */
+
+.cu-btn {
+ position: relative;
+ border: 0upx;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ box-sizing: border-box;
+ padding: 0 30upx;
+ font-size: 28upx;
+ height: 64upx;
+ line-height: 1;
+ text-align: center;
+ text-decoration: none;
+ overflow: visible;
+ margin-left: initial;
+ transform: translate(0upx, 0upx);
+ margin-right: initial;
+}
+
+.cu-btn::after {
+ display: none;
+}
+
+.cu-btn:not([class*="bg-"]) {
+ background-color: #f0f0f0;
+}
+
+.cu-btn[class*="line"] {
+ background-color: transparent;
+}
+
+.cu-btn[class*="line"]::after {
+ content: " ";
+ display: block;
+ width: 200%;
+ height: 200%;
+ position: absolute;
+ top: 0;
+ left: 0;
+ border: 1upx solid currentColor;
+ transform: scale(0.5);
+ transform-origin: 0 0;
+ box-sizing: border-box;
+ border-radius: 12upx;
+ z-index: 1;
+ pointer-events: none;
+}
+
+.cu-btn.round[class*="line"]::after {
+ border-radius: 1000upx;
+}
+
+.cu-btn[class*="lines"]::after {
+ border: 6upx solid currentColor;
+}
+
+.cu-btn[class*="bg-"]::after {
+ display: none;
+}
+
+.cu-btn.sm {
+ padding: 0 20upx;
+ font-size: 20upx;
+ height: 48upx;
+}
+
+.cu-btn.lg {
+ padding: 0 40upx;
+ font-size: 32upx;
+ height: 80upx;
+}
+
+.cu-btn.cuIcon.sm {
+ width: 48upx;
+ height: 48upx;
+}
+
+.cu-btn.cuIcon {
+ width: 64upx;
+ height: 64upx;
+ border-radius: 500upx;
+ padding: 0;
+}
+
+button.cuIcon.lg {
+ width: 80upx;
+ height: 80upx;
+}
+
+.cu-btn.shadow-blur::before {
+ top: 4upx;
+ left: 4upx;
+ filter: blur(6upx);
+ opacity: 0.6;
+}
+
+.cu-btn.button-hover {
+ transform: translate(1upx, 1upx);
+}
+
+.block {
+ display: block;
+}
+
+.cu-btn.block {
+ display: flex;
+}
+
+.cu-btn[disabled] {
+ opacity: 0.6;
+ color: #ffffff;
+}
+
+/* ==================
+ 寰界珷
+ ==================== */
+
+.cu-tag {
+ font-size: 24upx;
+ vertical-align: middle;
+ position: relative;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ box-sizing: border-box;
+ padding: 0upx 16upx;
+ height: 48upx;
+ font-family: Helvetica Neue, Helvetica, sans-serif;
+ white-space: nowrap;
+}
+
+.cu-tag:not([class*="bg"]):not([class*="line"]) {
+ background-color: #f1f1f1;
+}
+
+.cu-tag[class*="line-"]::after {
+ content: " ";
+ width: 200%;
+ height: 200%;
+ position: absolute;
+ top: 0;
+ left: 0;
+ border: 1upx solid currentColor;
+ transform: scale(0.5);
+ transform-origin: 0 0;
+ box-sizing: border-box;
+ border-radius: inherit;
+ z-index: 1;
+ pointer-events: none;
+}
+
+.cu-tag.radius[class*="line"]::after {
+ border-radius: 12upx;
+}
+
+.cu-tag.round[class*="line"]::after {
+ border-radius: 1000upx;
+}
+
+.cu-tag[class*="line-"]::after {
+ border-radius: 0;
+}
+
+.cu-tag+.cu-tag {
+ margin-left: 10upx;
+}
+
+.cu-tag.sm {
+ font-size: 20upx;
+ padding: 0upx 12upx;
+ height: 32upx;
+}
+
+.cu-capsule {
+ display: inline-flex;
+ vertical-align: middle;
+}
+
+.cu-capsule+.cu-capsule {
+ margin-left: 10upx;
+}
+
+.cu-capsule .cu-tag {
+ margin: 0;
+}
+
+.cu-capsule .cu-tag[class*="line-"]:last-child::after {
+ border-left: 0upx solid transparent;
+}
+
+.cu-capsule .cu-tag[class*="line-"]:first-child::after {
+ border-right: 0upx solid transparent;
+}
+
+.cu-capsule.radius .cu-tag:first-child {
+ border-top-left-radius: 6upx;
+ border-bottom-left-radius: 6upx;
+}
+
+.cu-capsule.radius .cu-tag:last-child::after,
+.cu-capsule.radius .cu-tag[class*="line-"] {
+ border-top-right-radius: 12upx;
+ border-bottom-right-radius: 12upx;
+}
+
+.cu-capsule.round .cu-tag:first-child {
+ border-top-left-radius: 200upx;
+ border-bottom-left-radius: 200upx;
+ text-indent: 4upx;
+}
+
+.cu-capsule.round .cu-tag:last-child::after,
+.cu-capsule.round .cu-tag:last-child {
+ border-top-right-radius: 200upx;
+ border-bottom-right-radius: 200upx;
+ text-indent: -4upx;
+}
+
+.cu-tag.badge {
+ border-radius: 200upx;
+ position: absolute;
+ top: -10upx;
+ right: -10upx;
+ font-size: 20upx;
+ padding: 0upx 10upx;
+ height: 28upx;
+ color: #ffffff;
+}
+
+.cu-tag.badge:not([class*="bg-"]) {
+ background-color: #dd514c;
+}
+
+.cu-tag:empty:not([class*="cuIcon-"]) {
+ padding: 0upx;
+ width: 16upx;
+ height: 16upx;
+ top: -4upx;
+ right: -4upx;
+}
+
+.cu-tag[class*="cuIcon-"] {
+ width: 32upx;
+ height: 32upx;
+ top: -4upx;
+ right: -4upx;
+}
+
+/* ==================
+ 澶村儚
+ ==================== */
+
+.cu-avatar {
+ font-variant: small-caps;
+ margin: 0;
+ padding: 0;
+ display: inline-flex;
+ text-align: center;
+ justify-content: center;
+ align-items: center;
+ background-color: #ccc;
+ color: #ffffff;
+ white-space: nowrap;
+ position: relative;
+ width: 64upx;
+ height: 64upx;
+ background-size: cover;
+ background-position: center;
+ vertical-align: middle;
+ font-size: 1.5em;
+}
+
+.cu-avatar.sm {
+ width: 48upx;
+ height: 48upx;
+ font-size: 1em;
+}
+
+.cu-avatar.lg {
+ width: 96upx;
+ height: 96upx;
+ font-size: 2em;
+}
+
+.cu-avatar.xl {
+ width: 128upx;
+ height: 128upx;
+ font-size: 2.5em;
+}
+
+.cu-avatar .avatar-text {
+ font-size: 0.4em;
+}
+
+.cu-avatar-group {
+ direction: rtl;
+ unicode-bidi: bidi-override;
+ padding: 0 10upx 0 40upx;
+ display: inline-block;
+}
+
+.cu-avatar-group .cu-avatar {
+ margin-left: -30upx;
+ border: 4upx solid #f1f1f1;
+ vertical-align: middle;
+}
+
+.cu-avatar-group .cu-avatar.sm {
+ margin-left: -20upx;
+ border: 1upx solid #f1f1f1;
+}
+
+/* ==================
+ 杩涘害鏉�
+ ==================== */
+
+.cu-progress {
+ overflow: hidden;
+ height: 28upx;
+ background-color: #ebeef5;
+ display: inline-flex;
+ align-items: center;
+ width: 100%;
+}
+
+.cu-progress+view,
+.cu-progress+text {
+ line-height: 1;
+}
+
+.cu-progress.xs {
+ height: 10upx;
+}
+
+.cu-progress.sm {
+ height: 20upx;
+}
+
+.cu-progress view {
+ width: 0;
+ height: 100%;
+ align-items: center;
+ display: flex;
+ justify-items: flex-end;
+ justify-content: space-around;
+ font-size: 20upx;
+ color: #ffffff;
+ transition: width 0.6s ease;
+}
+
+.cu-progress text {
+ align-items: center;
+ display: flex;
+ font-size: 20upx;
+ color: #333333;
+ text-indent: 10upx;
+}
+
+.cu-progress.text-progress {
+ padding-right: 60upx;
+}
+
+.cu-progress.striped view {
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-size: 72upx 72upx;
+}
+
+.cu-progress.active view {
+ animation: progress-stripes 2s linear infinite;
+}
+
+@keyframes progress-stripes {
+ from {
+ background-position: 72upx 0;
+ }
+
+ to {
+ background-position: 0 0;
+ }
+}
+
+/* ==================
+ 鍔犺浇
+ ==================== */
+
+.cu-load {
+ display: block;
+ line-height: 3em;
+ text-align: center;
+}
+
+.cu-load::before {
+ font-family: "cuIcon";
+ display: inline-block;
+ margin-right: 6upx;
+}
+
+.cu-load.loading::before {
+ content: "\e67a";
+ animation: cuIcon-spin 2s infinite linear;
+}
+
+.cu-load.loading::after {
+ content: "鍔犺浇涓�...";
+}
+
+.cu-load.over::before {
+ content: "\e64a";
+}
+
+.cu-load.over::after {
+ content: "娌℃湁鏇村浜�";
+}
+
+.cu-load.erro::before {
+ content: "\e658";
+}
+
+.cu-load.erro::after {
+ content: "鍔犺浇澶辫触";
+}
+
+.cu-load.load-cuIcon::before {
+ font-size: 32upx;
+}
+
+.cu-load.load-cuIcon::after {
+ display: none;
+}
+
+.cu-load.load-cuIcon.over {
+ display: none;
+}
+
+.cu-load.load-modal {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 140upx;
+ left: 0;
+ margin: auto;
+ width: 260upx;
+ height: 260upx;
+ background-color: #ffffff;
+ border-radius: 10upx;
+ box-shadow: 0 0 0upx 2000upx rgba(0, 0, 0, 0.5);
+ display: flex;
+ align-items: center;
+ flex-direction: column;
+ justify-content: center;
+ font-size: 28upx;
+ z-index: 9999;
+ line-height: 2.4em;
+}
+
+.cu-load.load-modal [class*="cuIcon-"] {
+ font-size: 60upx;
+}
+
+.cu-load.load-modal image {
+ width: 70upx;
+ height: 70upx;
+}
+
+.cu-load.load-modal::after {
+ content: "";
+ position: absolute;
+ background-color: #ffffff;
+ border-radius: 50%;
+ width: 200upx;
+ height: 200upx;
+ font-size: 10px;
+ border-top: 6upx solid rgba(0, 0, 0, 0.05);
+ border-right: 6upx solid rgba(0, 0, 0, 0.05);
+ border-bottom: 6upx solid rgba(0, 0, 0, 0.05);
+ border-left: 6upx solid #f37b1d;
+ animation: cuIcon-spin 1s infinite linear;
+ z-index: -1;
+}
+
+.load-progress {
+ pointer-events: none;
+ top: 0;
+ position: fixed;
+ width: 100%;
+ left: 0;
+ z-index: 2000;
+}
+
+.load-progress.hide {
+ display: none;
+}
+
+.load-progress .load-progress-bar {
+ position: relative;
+ width: 100%;
+ height: 4upx;
+ overflow: hidden;
+ transition: all 200ms ease 0s;
+}
+
+.load-progress .load-progress-spinner {
+ position: absolute;
+ top: 10upx;
+ right: 10upx;
+ z-index: 2000;
+ display: block;
+}
+
+.load-progress .load-progress-spinner::after {
+ content: "";
+ display: block;
+ width: 24upx;
+ height: 24upx;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ border: solid 4upx transparent;
+ border-top-color: inherit;
+ border-left-color: inherit;
+ border-radius: 50%;
+ -webkit-animation: load-progress-spinner 0.4s linear infinite;
+ animation: load-progress-spinner 0.4s linear infinite;
+}
+
+@-webkit-keyframes load-progress-spinner {
+ 0% {
+ -webkit-transform: rotate(0);
+ transform: rotate(0);
+ }
+
+ 100% {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+
+@keyframes load-progress-spinner {
+ 0% {
+ -webkit-transform: rotate(0);
+ transform: rotate(0);
+ }
+
+ 100% {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+
+/* ==================
+ 鍒楄〃
+ ==================== */
+.grayscale {
+ filter: grayscale(1);
+}
+
+.cu-list+.cu-list {
+ margin-top: 30upx
+}
+
+.cu-list>.cu-item {
+ transition: all .6s ease-in-out 0s;
+ transform: translateX(0upx)
+}
+
+.cu-list>.cu-item.move-cur {
+ transform: translateX(-260upx)
+}
+
+.cu-list>.cu-item .move {
+ position: absolute;
+ right: 0;
+ display: flex;
+ width: 260upx;
+ height: 100%;
+ transform: translateX(100%)
+}
+
+.cu-list>.cu-item .move view {
+ display: flex;
+ flex: 1;
+ justify-content: center;
+ align-items: center
+}
+
+.cu-list.menu-avatar {
+ overflow: hidden;
+}
+
+.cu-list.menu-avatar>.cu-item {
+ position: relative;
+ display: flex;
+ padding-right: 10upx;
+ height: 140upx;
+ background-color: #ffffff;
+ justify-content: flex-end;
+ align-items: center
+}
+
+.cu-list.menu-avatar>.cu-item>.cu-avatar {
+ position: absolute;
+ left: 30upx
+}
+
+.cu-list.menu-avatar>.cu-item .flex .text-cut {
+ max-width: 510upx
+}
+
+.cu-list.menu-avatar>.cu-item .content {
+ position: absolute;
+ left: 146upx;
+ width: calc(100% - 96upx - 60upx - 120upx - 20upx);
+ line-height: 1.6em;
+}
+
+.cu-list.menu-avatar>.cu-item .content.flex-sub {
+ width: calc(100% - 96upx - 60upx - 20upx);
+}
+
+.cu-list.menu-avatar>.cu-item .content>view:first-child {
+ font-size: 30upx;
+ display: flex;
+ align-items: center
+}
+
+.cu-list.menu-avatar>.cu-item .content .cu-tag.sm {
+ display: inline-block;
+ margin-left: 10upx;
+ height: 28upx;
+ font-size: 16upx;
+ line-height: 32upx
+}
+
+.cu-list.menu-avatar>.cu-item .action {
+ width: 100upx;
+ text-align: center
+}
+
+.cu-list.menu-avatar>.cu-item .action view+view {
+ margin-top: 10upx
+}
+
+.cu-list.menu-avatar.comment>.cu-item .content {
+ position: relative;
+ left: 0;
+ width: auto;
+ flex: 1;
+}
+
+.cu-list.menu-avatar.comment>.cu-item {
+ padding: 30upx 30upx 30upx 120upx;
+ height: auto
+}
+
+.cu-list.menu-avatar.comment .cu-avatar {
+ align-self: flex-start
+}
+
+.cu-list.menu>.cu-item {
+ position: relative;
+ display: flex;
+ padding: 0 30upx;
+ min-height: 100upx;
+ background-color: #ffffff;
+ justify-content: space-between;
+ align-items: center
+}
+
+.cu-list.menu>.cu-item:last-child:after {
+ border: none
+}
+
+.cu-list.menu-avatar>.cu-item:after,
+.cu-list.menu>.cu-item:after {
+ position: absolute;
+ top: 0;
+ left: 0;
+ box-sizing: border-box;
+ width: 200%;
+ height: 200%;
+ border-bottom: 1upx solid #ddd;
+ border-radius: inherit;
+ content: " ";
+ transform: scale(.5);
+ transform-origin: 0 0;
+ pointer-events: none
+}
+
+.cu-list.menu>.cu-item.grayscale {
+ background-color: #f5f5f5
+}
+
+.cu-list.menu>.cu-item.cur {
+ background-color: #fcf7e9
+}
+
+.cu-list.menu>.cu-item.arrow {
+ padding-right: 90upx
+}
+
+.cu-list.menu>.cu-item.arrow:before {
+ position: absolute;
+ top: 0;
+ right: 30upx;
+ bottom: 0;
+ display: block;
+ margin: auto;
+ width: 30upx;
+ height: 30upx;
+ color: #8799a3;
+ content: "\e6a3";
+ text-align: center;
+ font-size: 34upx;
+ font-family: cuIcon;
+ line-height: 30upx
+}
+
+.cu-list.menu>.cu-item button.content {
+ padding: 0;
+ background-color: transparent;
+ justify-content: flex-start
+}
+
+.cu-list.menu>.cu-item button.content:after {
+ display: none
+}
+
+.cu-list.menu>.cu-item .cu-avatar-group .cu-avatar {
+ border-color: #ffffff
+}
+
+.cu-list.menu>.cu-item .content>view:first-child {
+ display: flex;
+ align-items: center
+}
+
+.cu-list.menu>.cu-item .content>text[class*=cuIcon] {
+ display: inline-block;
+ margin-right: 10upx;
+ width: 1.6em;
+ text-align: center
+}
+
+.cu-list.menu>.cu-item .content>image {
+ display: inline-block;
+ margin-right: 10upx;
+ width: 1.6em;
+ height: 1.6em;
+ vertical-align: middle
+}
+
+.cu-list.menu>.cu-item .content {
+ font-size: 30upx;
+ line-height: 1.6em;
+ flex: 1
+}
+
+.cu-list.menu>.cu-item .content .cu-tag.sm {
+ display: inline-block;
+ margin-left: 10upx;
+ height: 28upx;
+ font-size: 16upx;
+ line-height: 32upx
+}
+
+.cu-list.menu>.cu-item .action .cu-tag:empty {
+ right: 10upx
+}
+
+.cu-list.menu {
+ display: block;
+ overflow: hidden
+}
+
+.cu-list.menu.sm-border>.cu-item:after {
+ left: 30upx;
+ width: calc(200% - 120upx)
+}
+
+.cu-list.grid>.cu-item {
+ position: relative;
+ display: flex;
+ padding: 20upx 0 30upx;
+ transition-duration: 0s;
+ flex-direction: column
+}
+
+.cu-list.grid>.cu-item:after {
+ position: absolute;
+ top: 0;
+ left: 0;
+ box-sizing: border-box;
+ width: 200%;
+ height: 200%;
+ border-right: 1px solid rgba(0, 0, 0, .1);
+ border-bottom: 1px solid rgba(0, 0, 0, .1);
+ border-radius: inherit;
+ content: " ";
+ transform: scale(.5);
+ transform-origin: 0 0;
+ pointer-events: none
+}
+
+.cu-list.grid>.cu-item text {
+ display: block;
+ margin-top: 10upx;
+ color: #888;
+ font-size: 26upx;
+ line-height: 40upx
+}
+
+.cu-list.grid>.cu-item [class*=cuIcon] {
+ position: relative;
+ display: block;
+ margin-top: 20upx;
+ width: 100%;
+ font-size: 48upx
+}
+
+.cu-list.grid>.cu-item .cu-tag {
+ right: auto;
+ left: 50%;
+ margin-left: 20upx
+}
+
+.cu-list.grid {
+ background-color: #ffffff;
+ text-align: center
+}
+
+.cu-list.grid.no-border>.cu-item {
+ padding-top: 10upx;
+ padding-bottom: 20upx
+}
+
+.cu-list.grid.no-border>.cu-item:after {
+ border: none
+}
+
+.cu-list.grid.no-border {
+ padding: 20upx 10upx
+}
+
+.cu-list.grid.col-3>.cu-item:nth-child(3n):after,
+.cu-list.grid.col-4>.cu-item:nth-child(4n):after,
+.cu-list.grid.col-5>.cu-item:nth-child(5n):after {
+ border-right-width: 0
+}
+
+.cu-list.card-menu {
+ overflow: hidden;
+ margin-right: 30upx;
+ margin-left: 30upx;
+ border-radius: 20upx
+}
+
+
+/* ==================
+ 鎿嶄綔鏉�
+ ==================== */
+
+.cu-bar {
+ display: flex;
+ position: relative;
+ align-items: center;
+ min-height: 100upx;
+ justify-content: space-between;
+}
+
+.cu-bar .action {
+ display: flex;
+ align-items: center;
+ height: 100%;
+ justify-content: center;
+ max-width: 100%;
+}
+
+.cu-bar .action.border-title {
+ position: relative;
+ top: -10upx;
+}
+
+.cu-bar .action.border-title text[class*="bg-"]:last-child {
+ position: absolute;
+ bottom: -0.5rem;
+ min-width: 2rem;
+ height: 6upx;
+ left: 0;
+}
+
+.cu-bar .action.sub-title {
+ position: relative;
+ top: -0.2rem;
+}
+
+.cu-bar .action.sub-title text {
+ position: relative;
+ z-index: 1;
+}
+
+.cu-bar .action.sub-title text[class*="bg-"]:last-child {
+ position: absolute;
+ display: inline-block;
+ bottom: -0.2rem;
+ border-radius: 6upx;
+ width: 100%;
+ height: 0.6rem;
+ left: 0.6rem;
+ opacity: 0.3;
+ z-index: 0;
+}
+
+.cu-bar .action.sub-title text[class*="text-"]:last-child {
+ position: absolute;
+ display: inline-block;
+ bottom: -0.7rem;
+ left: 0.5rem;
+ opacity: 0.2;
+ z-index: 0;
+ text-align: right;
+ font-weight: 900;
+ font-size: 36upx;
+}
+
+.cu-bar.justify-center .action.border-title text:last-child,
+.cu-bar.justify-center .action.sub-title text:last-child {
+ left: 0;
+ right: 0;
+ margin: auto;
+ text-align: center;
+}
+
+.cu-bar .action:first-child {
+ margin-left: 30upx;
+ font-size: 30upx;
+}
+
+.cu-bar .action text.text-cut {
+ text-align: left;
+ width: 100%;
+}
+
+.cu-bar .cu-avatar:first-child {
+ margin-left: 20upx;
+}
+
+.cu-bar .action:first-child>text[class*="cuIcon-"] {
+ margin-left: -0.3em;
+ margin-right: 0.3em;
+}
+
+.cu-bar .action:last-child {
+ margin-right: 30upx;
+}
+
+.cu-bar .action>text[class*="cuIcon-"],
+.cu-bar .action>view[class*="cuIcon-"] {
+ font-size: 36upx;
+}
+
+.cu-bar .action>text[class*="cuIcon-"]+text[class*="cuIcon-"] {
+ margin-left: 0.5em;
+}
+
+.cu-bar .content {
+ position: absolute;
+ text-align: center;
+ width: calc(100% - 340upx);
+ left: 0;
+ right: 0;
+ bottom: 0;
+ top: 0;
+ margin: auto;
+ height: 60upx;
+ font-size: 32upx;
+ line-height: 60upx;
+ cursor: none;
+ pointer-events: none;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+}
+
+.cu-bar.ios .content {
+ bottom: 7px;
+ height: 30px;
+ font-size: 32upx;
+ line-height: 30px;
+}
+
+.cu-bar.btn-group {
+ justify-content: space-around;
+}
+
+.cu-bar.btn-group button {
+ padding: 20upx 32upx;
+}
+
+.cu-bar.btn-group button {
+ flex: 1;
+ margin: 0 20upx;
+ max-width: 50%;
+}
+
+.cu-bar .search-form {
+ background-color: #f5f5f5;
+ line-height: 64upx;
+ height: 64upx;
+ font-size: 24upx;
+ color: #333333;
+ flex: 1;
+ display: flex;
+ align-items: center;
+ margin: 0 30upx;
+}
+
+.cu-bar .search-form+.action {
+ margin-right: 30upx;
+}
+
+.cu-bar .search-form input {
+ flex: 1;
+ padding-right: 30upx;
+ height: 64upx;
+ line-height: 64upx;
+ font-size: 26upx;
+ background-color: transparent;
+}
+
+.cu-bar .search-form [class*="cuIcon-"] {
+ margin: 0 0.5em 0 0.8em;
+}
+
+.cu-bar .search-form [class*="cuIcon-"]::before {
+ top: 0upx;
+}
+
+.cu-bar.fixed,
+.nav.fixed {
+ position: fixed;
+ width: 100%;
+ top: 0;
+ z-index: 1024;
+ box-shadow: 0 1upx 6upx rgba(0, 0, 0, 0.1);
+}
+
+.cu-bar.foot {
+ position: fixed;
+ width: 100%;
+ bottom: 0;
+ z-index: 1024;
+ box-shadow: 0 -1upx 6upx rgba(0, 0, 0, 0.1);
+}
+
+.cu-bar.tabbar {
+ padding: 0;
+ height: calc(100upx + env(safe-area-inset-bottom) / 2);
+ padding-bottom: calc(env(safe-area-inset-bottom) / 2);
+}
+
+.cu-tabbar-height {
+ min-height: 100upx;
+ height: calc(100upx + env(safe-area-inset-bottom) / 2);
+}
+
+.cu-bar.tabbar.shadow {
+ box-shadow: 0 -1upx 6upx rgba(0, 0, 0, 0.1);
+}
+
+.cu-bar.tabbar .action {
+ font-size: 22upx;
+ position: relative;
+ flex: 1;
+ text-align: center;
+ padding: 0;
+ display: block;
+ height: auto;
+ line-height: 1;
+ margin: 0;
+ background-color: inherit;
+ overflow: initial;
+}
+
+.cu-bar.tabbar.shop .action {
+ width: 140upx;
+ flex: initial;
+}
+
+.cu-bar.tabbar .action.add-action {
+ position: relative;
+ z-index: 2;
+ padding-top: 50upx;
+}
+
+.cu-bar.tabbar .action.add-action [class*="cuIcon-"] {
+ position: absolute;
+ width: 70upx;
+ z-index: 2;
+ height: 70upx;
+ border-radius: 50%;
+ line-height: 70upx;
+ font-size: 50upx;
+ top: -35upx;
+ left: 0;
+ right: 0;
+ margin: auto;
+ padding: 0;
+}
+
+.cu-bar.tabbar .action.add-action::after {
+ content: "";
+ position: absolute;
+ width: 100upx;
+ height: 100upx;
+ top: -50upx;
+ left: 0;
+ right: 0;
+ margin: auto;
+ box-shadow: 0 -3upx 8upx rgba(0, 0, 0, 0.08);
+ border-radius: 50upx;
+ background-color: inherit;
+ z-index: 0;
+}
+
+.cu-bar.tabbar .action.add-action::before {
+ content: "";
+ position: absolute;
+ width: 100upx;
+ height: 30upx;
+ bottom: 30upx;
+ left: 0;
+ right: 0;
+ margin: auto;
+ background-color: inherit;
+ z-index: 1;
+}
+
+.cu-bar.tabbar .btn-group {
+ flex: 1;
+ display: flex;
+ justify-content: space-around;
+ align-items: center;
+ padding: 0 10upx;
+}
+
+.cu-bar.tabbar button.action::after {
+ border: 0;
+}
+
+.cu-bar.tabbar .action [class*="cuIcon-"] {
+ width: 100upx;
+ position: relative;
+ display: block;
+ height: auto;
+ margin: 0 auto 10upx;
+ text-align: center;
+ font-size: 40upx;
+}
+
+.cu-bar.tabbar .action .cuIcon-cu-image {
+ margin: 0 auto;
+}
+
+.cu-bar.tabbar .action .cuIcon-cu-image image {
+ width: 50upx;
+ height: 50upx;
+ display: inline-block;
+}
+
+.cu-bar.tabbar .submit {
+ align-items: center;
+ display: flex;
+ justify-content: center;
+ text-align: center;
+ position: relative;
+ flex: 2;
+ align-self: stretch;
+}
+
+.cu-bar.tabbar .submit:last-child {
+ flex: 2.6;
+}
+
+.cu-bar.tabbar .submit+.submit {
+ flex: 2;
+}
+
+.cu-bar.tabbar.border .action::before {
+ content: " ";
+ width: 200%;
+ height: 200%;
+ position: absolute;
+ top: 0;
+ left: 0;
+ transform: scale(0.5);
+ transform-origin: 0 0;
+ border-right: 1upx solid rgba(0, 0, 0, 0.1);
+ z-index: 3;
+}
+
+.cu-bar.tabbar.border .action:last-child:before {
+ display: none;
+}
+
+.cu-bar.input {
+ padding-right: 20upx;
+ background-color: #ffffff;
+}
+
+.cu-bar.input input {
+ overflow: initial;
+ line-height: 64upx;
+ height: 64upx;
+ min-height: 64upx;
+ flex: 1;
+ font-size: 30upx;
+ margin: 0 20upx;
+}
+
+.cu-bar.input .action {
+ margin-left: 20upx;
+}
+
+.cu-bar.input .action [class*="cuIcon-"] {
+ font-size: 48upx;
+}
+
+.cu-bar.input input+.action {
+ margin-right: 20upx;
+ margin-left: 0upx;
+}
+
+.cu-bar.input .action:first-child [class*="cuIcon-"] {
+ margin-left: 0upx;
+}
+
+.cu-custom {
+ display: block;
+ position: relative;
+}
+
+.cu-custom .cu-bar .content {
+ width: calc(100% - 440upx);
+}
+
+/* #ifdef MP-ALIPAY */
+.cu-custom .cu-bar .action .cuIcon-back {
+ opacity: 0;
+}
+
+/* #endif */
+
+.cu-custom .cu-bar .content image {
+ height: 60upx;
+ width: 240upx;
+}
+
+.cu-custom .cu-bar {
+ min-height: 0px;
+ /* #ifdef MP-WEIXIN */
+ padding-right: 220upx;
+ /* #endif */
+ /* #ifdef MP-ALIPAY */
+ padding-right: 150upx;
+ /* #endif */
+ box-shadow: 0upx 0upx 0upx;
+ z-index: 9999;
+}
+
+.cu-custom .cu-bar .border-custom {
+ position: relative;
+ background: rgba(0, 0, 0, 0.15);
+ border-radius: 1000upx;
+ height: 30px;
+}
+
+.cu-custom .cu-bar .border-custom::after {
+ content: " ";
+ width: 200%;
+ height: 200%;
+ position: absolute;
+ top: 0;
+ left: 0;
+ border-radius: inherit;
+ transform: scale(0.5);
+ transform-origin: 0 0;
+ pointer-events: none;
+ box-sizing: border-box;
+ border: 1upx solid #ffffff;
+ opacity: 0.5;
+}
+
+.cu-custom .cu-bar .border-custom::before {
+ content: " ";
+ width: 1upx;
+ height: 110%;
+ position: absolute;
+ top: 22.5%;
+ left: 0;
+ right: 0;
+ margin: auto;
+ transform: scale(0.5);
+ transform-origin: 0 0;
+ pointer-events: none;
+ box-sizing: border-box;
+ opacity: 0.6;
+ background-color: #ffffff;
+}
+
+.cu-custom .cu-bar .border-custom text {
+ display: block;
+ flex: 1;
+ margin: auto !important;
+ text-align: center;
+ font-size: 34upx;
+}
+
+/* ==================
+ 瀵艰埅鏍�
+ ==================== */
+
+.nav {
+ white-space: nowrap;
+}
+
+::-webkit-scrollbar {
+ display: none;
+}
+
+.nav .cu-item {
+ height: 90upx;
+ display: inline-block;
+ line-height: 90upx;
+ margin: 0 10upx;
+ padding: 0 20upx;
+}
+
+.nav .cu-item.cur {
+ border-bottom: 4upx solid;
+}
+
+/* ==================
+ 鏃堕棿杞�
+ ==================== */
+
+.cu-timeline {
+ display: block;
+ background-color: #ffffff;
+}
+
+.cu-timeline .cu-time {
+ width: 120upx;
+ text-align: center;
+ padding: 20upx 0;
+ font-size: 26upx;
+ color: #888;
+ display: block;
+}
+
+.cu-timeline>.cu-item {
+ padding: 30upx 30upx 30upx 120upx;
+ position: relative;
+ display: block;
+ z-index: 0;
+}
+
+.cu-timeline>.cu-item:not([class*="text-"]) {
+ color: #ccc;
+}
+
+.cu-timeline>.cu-item::after {
+ content: "";
+ display: block;
+ position: absolute;
+ width: 1upx;
+ background-color: #ddd;
+ left: 60upx;
+ height: 100%;
+ top: 0;
+ z-index: 8;
+}
+
+.cu-timeline>.cu-item::before {
+ font-family: "cuIcon";
+ display: block;
+ position: absolute;
+ top: 36upx;
+ z-index: 9;
+ background-color: #ffffff;
+ width: 50upx;
+ height: 50upx;
+ text-align: center;
+ border: none;
+ line-height: 50upx;
+ left: 36upx;
+}
+
+.cu-timeline>.cu-item:not([class*="cuIcon-"])::before {
+ content: "\e763";
+}
+
+.cu-timeline>.cu-item[class*="cuIcon-"]::before {
+ background-color: #ffffff;
+ width: 50upx;
+ height: 50upx;
+ text-align: center;
+ border: none;
+ line-height: 50upx;
+ left: 36upx;
+}
+
+.cu-timeline>.cu-item>.content {
+ padding: 30upx;
+ border-radius: 6upx;
+ display: block;
+ line-height: 1.6;
+}
+
+.cu-timeline>.cu-item>.content:not([class*="bg-"]) {
+ background-color: #f1f1f1;
+ color: #333333;
+}
+
+.cu-timeline>.cu-item>.content+.content {
+ margin-top: 20upx;
+}
+
+/* ==================
+ 鑱婂ぉ
+ ==================== */
+
+.cu-chat {
+ display: flex;
+ flex-direction: column;
+}
+
+.cu-chat .cu-item {
+ display: flex;
+ padding: 30upx 30upx 70upx;
+ position: relative;
+}
+
+.cu-chat .cu-item>.cu-avatar {
+ width: 80upx;
+ height: 80upx;
+}
+
+.cu-chat .cu-item>.main {
+ max-width: calc(100% - 260upx);
+ margin: 0 40upx;
+ display: flex;
+ align-items: center;
+}
+
+.cu-chat .cu-item>image {
+ height: 320upx;
+}
+
+.cu-chat .cu-item>.main .content {
+ padding: 20upx;
+ border-radius: 6upx;
+ display: inline-flex;
+ max-width: 100%;
+ align-items: center;
+ font-size: 30upx;
+ position: relative;
+ min-height: 80upx;
+ line-height: 40upx;
+ text-align: left;
+}
+
+.cu-chat .cu-item>.main .content:not([class*="bg-"]) {
+ background-color: #ffffff;
+ color: #333333;
+}
+
+.cu-chat .cu-item .date {
+ position: absolute;
+ font-size: 24upx;
+ color: #8799a3;
+ width: calc(100% - 320upx);
+ bottom: 20upx;
+ left: 160upx;
+}
+
+.cu-chat .cu-item .action {
+ padding: 0 30upx;
+ display: flex;
+ align-items: center;
+}
+
+.cu-chat .cu-item>.main .content::after {
+ content: "";
+ top: 27upx;
+ transform: rotate(45deg);
+ position: absolute;
+ z-index: 100;
+ display: inline-block;
+ overflow: hidden;
+ width: 24upx;
+ height: 24upx;
+ left: -12upx;
+ right: initial;
+ background-color: inherit;
+}
+
+.cu-chat .cu-item.self>.main .content::after {
+ left: auto;
+ right: -12upx;
+}
+
+.cu-chat .cu-item>.main .content::before {
+ content: "";
+ top: 30upx;
+ transform: rotate(45deg);
+ position: absolute;
+ z-index: -1;
+ display: inline-block;
+ overflow: hidden;
+ width: 24upx;
+ height: 24upx;
+ left: -12upx;
+ right: initial;
+ background-color: inherit;
+ filter: blur(5upx);
+ opacity: 0.3;
+}
+
+.cu-chat .cu-item>.main .content:not([class*="bg-"])::before {
+ background-color: #333333;
+ opacity: 0.1;
+}
+
+.cu-chat .cu-item.self>.main .content::before {
+ left: auto;
+ right: -12upx;
+}
+
+.cu-chat .cu-item.self {
+ justify-content: flex-end;
+ text-align: right;
+}
+
+.cu-chat .cu-info {
+ display: inline-block;
+ margin: 20upx auto;
+ font-size: 24upx;
+ padding: 8upx 12upx;
+ background-color: rgba(0, 0, 0, 0.2);
+ border-radius: 6upx;
+ color: #ffffff;
+ max-width: 400upx;
+ line-height: 1.4;
+}
+
+/* ==================
+ 鍗$墖
+ ==================== */
+
+.cu-card {
+ display: block;
+ overflow: hidden;
+}
+
+.cu-card>.cu-item {
+ display: block;
+ background-color: #ffffff;
+ overflow: hidden;
+ border-radius: 10upx;
+ margin: 30upx;
+}
+
+.cu-card>.cu-item.shadow-blur {
+ overflow: initial;
+}
+
+.cu-card.no-card>.cu-item {
+ margin: 0upx;
+ border-radius: 0upx;
+}
+
+.cu-card .grid.grid-square {
+ margin-bottom: -20upx;
+}
+
+.cu-card.case .image {
+ position: relative;
+}
+
+.cu-card.case .image image {
+ width: 100%;
+}
+
+.cu-card.case .image .cu-tag {
+ position: absolute;
+ right: 0;
+ top: 0;
+}
+
+.cu-card.case .image .cu-bar {
+ position: absolute;
+ bottom: 0;
+ width: 100%;
+ background-color: transparent;
+ padding: 0upx 30upx;
+}
+
+.cu-card.case.no-card .image {
+ margin: 30upx 30upx 0;
+ overflow: hidden;
+ border-radius: 10upx;
+}
+
+.cu-card.dynamic {
+ display: block;
+}
+
+.cu-card.dynamic>.cu-item {
+ display: block;
+ background-color: #ffffff;
+ overflow: hidden;
+}
+
+.cu-card.dynamic>.cu-item>.text-content {
+ padding: 0 30upx 0;
+ max-height: 6.4em;
+ overflow: hidden;
+ font-size: 30upx;
+ margin-bottom: 20upx;
+}
+
+.cu-card.dynamic>.cu-item .square-img {
+ width: 100%;
+ height: 200upx;
+ border-radius: 6upx;
+}
+
+.cu-card.dynamic>.cu-item .only-img {
+ width: 100%;
+ height: 320upx;
+ border-radius: 6upx;
+}
+
+/* card.dynamic>.cu-item .comment {
+ padding: 20upx;
+ background-color: #f1f1f1;
+ margin: 0 30upx 30upx;
+ border-radius: 6upx;
+} */
+
+.cu-card.article {
+ display: block;
+}
+
+.cu-card.article>.cu-item {
+ padding-bottom: 30upx;
+}
+
+.cu-card.article>.cu-item .title {
+ font-size: 30upx;
+ font-weight: 900;
+ color: #333333;
+ line-height: 100upx;
+ padding: 0 30upx;
+}
+
+.cu-card.article>.cu-item .content {
+ display: flex;
+ padding: 0 30upx;
+}
+
+.cu-card.article>.cu-item .content>image {
+ width: 240upx;
+ height: 6.4em;
+ margin-right: 20upx;
+ border-radius: 6upx;
+}
+
+.cu-card.article>.cu-item .content .desc {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+}
+
+.cu-card.article>.cu-item .content .text-content {
+ font-size: 28upx;
+ color: #888;
+ height: 4.8em;
+ overflow: hidden;
+}
+
+/* ==================
+ 琛ㄥ崟
+ ==================== */
+
+.cu-form-group {
+ background-color: #ffffff;
+ padding: 1upx 30upx;
+ display: flex;
+ align-items: center;
+ min-height: 100upx;
+ justify-content: space-between;
+}
+
+.cu-form-group+.cu-form-group {
+ border-top: 1upx solid #eee;
+}
+
+.cu-form-group .title {
+ text-align: justify;
+ padding-right: 30upx;
+ font-size: 30upx;
+ position: relative;
+ height: 60upx;
+ line-height: 60upx;
+}
+
+.cu-form-group input {
+ flex: 1;
+ font-size: 30upx;
+ color: #555;
+ padding-right: 20upx;
+}
+
+.cu-form-group>text[class*="cuIcon-"] {
+ font-size: 36upx;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+.cu-form-group textarea {
+ margin: 32upx 0 30upx;
+ height: 4.6em;
+ width: 100%;
+ line-height: 1.2em;
+ flex: 1;
+ font-size: 28upx;
+ padding: 0;
+}
+
+.cu-form-group.align-start .title {
+ height: 1em;
+ margin-top: 32upx;
+ line-height: 1em;
+}
+
+.cu-form-group picker {
+ flex: 1;
+ padding-right: 40upx;
+ overflow: hidden;
+ position: relative;
+}
+
+.cu-form-group picker .picker {
+ line-height: 100upx;
+ font-size: 28upx;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+ width: 100%;
+ text-align: right;
+}
+
+.cu-form-group picker::after {
+ font-family: cuIcon;
+ display: block;
+ content: "\e6a3";
+ position: absolute;
+ font-size: 34upx;
+ color: #8799a3;
+ line-height: 100upx;
+ width: 60upx;
+ text-align: center;
+ top: 0;
+ bottom: 0;
+ right: -20upx;
+ margin: auto;
+}
+
+.cu-form-group textarea[disabled],
+.cu-form-group textarea[disabled] .placeholder {
+ color: transparent;
+}
+
+/* ==================
+ 妯℃�佺獥鍙�
+ ==================== */
+
+.cu-modal {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 1110;
+ opacity: 0;
+ outline: 0;
+ text-align: center;
+ -ms-transform: scale(1.185);
+ transform: scale(1.185);
+ backface-visibility: hidden;
+ perspective: 2000upx;
+ background: rgba(0, 0, 0, 0.6);
+ transition: all 0.3s ease-in-out 0s;
+ pointer-events: none;
+}
+
+.cu-modal::before {
+ content: "\200B";
+ display: inline-block;
+ height: 100%;
+ vertical-align: middle;
+}
+
+.cu-modal.show {
+ opacity: 1;
+ transition-duration: 0.3s;
+ -ms-transform: scale(1);
+ transform: scale(1);
+ overflow-x: hidden;
+ overflow-y: auto;
+ pointer-events: auto;
+}
+
+.cu-dialog {
+ position: relative;
+ display: inline-block;
+ vertical-align: middle;
+ margin-left: auto;
+ margin-right: auto;
+ width: 680upx;
+ max-width: 100%;
+ background-color: #f8f8f8;
+ border-radius: 10upx;
+ overflow: hidden;
+}
+
+.cu-modal.bottom-modal::before {
+ vertical-align: bottom;
+}
+
+.cu-modal.bottom-modal .cu-dialog {
+ width: 100%;
+ border-radius: 0;
+}
+
+.cu-modal.bottom-modal {
+ margin-bottom: -1000upx;
+}
+
+.cu-modal.bottom-modal.show {
+ margin-bottom: 0;
+}
+
+.cu-modal.drawer-modal {
+ transform: scale(1);
+ display: flex;
+}
+
+.cu-modal.drawer-modal .cu-dialog {
+ height: 100%;
+ min-width: 200upx;
+ border-radius: 0;
+ margin: initial;
+ transition-duration: 0.3s;
+}
+
+.cu-modal.drawer-modal.justify-start .cu-dialog {
+ transform: translateX(-100%);
+}
+
+.cu-modal.drawer-modal.justify-end .cu-dialog {
+ transform: translateX(100%);
+}
+
+.cu-modal.drawer-modal.show .cu-dialog {
+ transform: translateX(0%);
+}
+.cu-modal .cu-dialog>.cu-bar:first-child .action{
+ min-width: 100rpx;
+ margin-right: 0;
+ min-height: 100rpx;
+}
+/* ==================
+ 杞挱
+ ==================== */
+swiper .a-swiper-dot {
+ display: inline-block;
+ width: 16upx;
+ height: 16upx;
+ background: rgba(0, 0, 0, .3);
+ border-radius: 50%;
+ vertical-align: middle;
+}
+
+swiper[class*="-dot"] .wx-swiper-dots,
+swiper[class*="-dot"] .a-swiper-dots,
+swiper[class*="-dot"] .uni-swiper-dots {
+ display: flex;
+ align-items: center;
+ width: 100%;
+ justify-content: center;
+}
+
+swiper.square-dot .wx-swiper-dot,
+swiper.square-dot .a-swiper-dot,
+swiper.square-dot .uni-swiper-dot {
+ background-color: #ffffff;
+ opacity: 0.4;
+ width: 10upx;
+ height: 10upx;
+ border-radius: 20upx;
+ margin: 0 8upx !important;
+}
+
+swiper.square-dot .wx-swiper-dot.wx-swiper-dot-active,
+swiper.square-dot .a-swiper-dot.a-swiper-dot-active,
+swiper.square-dot .uni-swiper-dot.uni-swiper-dot-active {
+ opacity: 1;
+ width: 30upx;
+}
+
+swiper.round-dot .wx-swiper-dot,
+swiper.round-dot .a-swiper-dot,
+swiper.round-dot .uni-swiper-dot {
+ width: 10upx;
+ height: 10upx;
+ position: relative;
+ margin: 4upx 8upx !important;
+}
+
+swiper.round-dot .wx-swiper-dot.wx-swiper-dot-active::after,
+swiper.round-dot .a-swiper-dot.a-swiper-dot-active::after,
+swiper.round-dot .uni-swiper-dot.uni-swiper-dot-active::after {
+ content: "";
+ position: absolute;
+ width: 10upx;
+ height: 10upx;
+ top: 0upx;
+ left: 0upx;
+ right: 0;
+ bottom: 0;
+ margin: auto;
+ background-color: #ffffff;
+ border-radius: 20upx;
+}
+
+swiper.round-dot .wx-swiper-dot.wx-swiper-dot-active,
+swiper.round-dot .a-swiper-dot.a-swiper-dot-active,
+swiper.round-dot .uni-swiper-dot.uni-swiper-dot-active {
+ width: 18upx;
+ height: 18upx;
+}
+
+.screen-swiper {
+ min-height: 375upx;
+}
+
+.screen-swiper image,
+.screen-swiper video,
+.swiper-item image,
+.swiper-item video {
+ width: 100%;
+ display: block;
+ height: 100%;
+ margin: 0;
+ pointer-events: none;
+}
+
+.card-swiper {
+ height: 420upx !important;
+}
+
+.card-swiper swiper-item {
+ width: 610upx !important;
+ left: 70upx;
+ box-sizing: border-box;
+ padding: 40upx 0upx 70upx;
+ overflow: initial;
+}
+
+.card-swiper swiper-item .swiper-item {
+ width: 100%;
+ display: block;
+ height: 100%;
+ border-radius: 10upx;
+ transform: scale(0.9);
+ transition: all 0.2s ease-in 0s;
+ overflow: hidden;
+}
+
+.card-swiper swiper-item.cur .swiper-item {
+ transform: none;
+ transition: all 0.2s ease-in 0s;
+}
+
+
+.tower-swiper {
+ height: 420upx;
+ position: relative;
+ max-width: 750upx;
+ overflow: hidden;
+}
+
+.tower-swiper .tower-item {
+ position: absolute;
+ width: 300upx;
+ height: 380upx;
+ top: 0;
+ bottom: 0;
+ left: 50%;
+ margin: auto;
+ transition: all 0.2s ease-in 0s;
+ opacity: 1;
+}
+
+.tower-swiper .tower-item.none {
+ opacity: 0;
+}
+
+.tower-swiper .tower-item .swiper-item {
+ width: 100%;
+ height: 100%;
+ border-radius: 6upx;
+ overflow: hidden;
+}
+
+/* ==================
+ 姝ラ鏉�
+ ==================== */
+
+.cu-steps {
+ display: flex;
+}
+
+scroll-view.cu-steps {
+ display: block;
+ white-space: nowrap;
+}
+
+scroll-view.cu-steps .cu-item {
+ display: inline-block;
+}
+
+.cu-steps .cu-item {
+ flex: 1;
+ text-align: center;
+ position: relative;
+ min-width: 100upx;
+}
+
+.cu-steps .cu-item:not([class*="text-"]) {
+ color: #8799a3;
+}
+
+.cu-steps .cu-item [class*="cuIcon-"],
+.cu-steps .cu-item .num {
+ display: block;
+ font-size: 40upx;
+ line-height: 80upx;
+}
+
+.cu-steps .cu-item::before,
+.cu-steps .cu-item::after,
+.cu-steps.steps-arrow .cu-item::before,
+.cu-steps.steps-arrow .cu-item::after {
+ content: "";
+ display: block;
+ position: absolute;
+ height: 0px;
+ width: calc(100% - 80upx);
+ border-bottom: 1px solid #ccc;
+ left: calc(0px - (100% - 80upx) / 2);
+ top: 40upx;
+ z-index: 0;
+}
+
+.cu-steps.steps-arrow .cu-item::before,
+.cu-steps.steps-arrow .cu-item::after {
+ content: "\e6a3";
+ font-family: 'cuIcon';
+ height: 30upx;
+ border-bottom-width: 0px;
+ line-height: 30upx;
+ top: 0;
+ bottom: 0;
+ margin: auto;
+ color: #ccc;
+}
+
+.cu-steps.steps-bottom .cu-item::before,
+.cu-steps.steps-bottom .cu-item::after {
+ bottom: 40upx;
+ top: initial;
+}
+
+.cu-steps .cu-item::after {
+ border-bottom: 1px solid currentColor;
+ width: 0px;
+ transition: all 0.3s ease-in-out 0s;
+}
+
+.cu-steps .cu-item[class*="text-"]::after {
+ width: calc(100% - 80upx);
+ color: currentColor;
+}
+
+.cu-steps .cu-item:first-child::before,
+.cu-steps .cu-item:first-child::after {
+ display: none;
+}
+
+.cu-steps .cu-item .num {
+ width: 40upx;
+ height: 40upx;
+ border-radius: 50%;
+ line-height: 40upx;
+ margin: 20upx auto;
+ font-size: 24upx;
+ border: 1px solid currentColor;
+ position: relative;
+ overflow: hidden;
+}
+
+.cu-steps .cu-item[class*="text-"] .num {
+ background-color: currentColor;
+}
+
+.cu-steps .cu-item .num::before,
+.cu-steps .cu-item .num::after {
+ content: attr(data-index);
+ position: absolute;
+ left: 0;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ margin: auto;
+ transition: all 0.3s ease-in-out 0s;
+ transform: translateY(0upx);
+}
+
+.cu-steps .cu-item[class*="text-"] .num::before {
+ transform: translateY(-40upx);
+ color: #ffffff;
+}
+
+.cu-steps .cu-item .num::after {
+ transform: translateY(40upx);
+ color: #ffffff;
+ transition: all 0.3s ease-in-out 0s;
+}
+
+.cu-steps .cu-item[class*="text-"] .num::after {
+ content: "\e645";
+ font-family: 'cuIcon';
+ color: #ffffff;
+ transform: translateY(0upx);
+}
+
+.cu-steps .cu-item[class*="text-"] .num.err::after {
+ content: "\e646";
+}
+
+/* ==================
+ 甯冨眬
+ ==================== */
+
+/* -- flex寮规�у竷灞� -- */
+
+.flex {
+ display: flex;
+}
+
+.basis-xs {
+ flex-basis: 20%;
+}
+
+.basis-sm {
+ flex-basis: 40%;
+}
+
+.basis-df {
+ flex-basis: 50%;
+}
+
+.basis-lg {
+ flex-basis: 60%;
+}
+
+.basis-xl {
+ flex-basis: 80%;
+}
+
+.flex-sub {
+ flex: 1;
+}
+
+.flex-twice {
+ flex: 2;
+}
+
+.flex-treble {
+ flex: 3;
+}
+
+.flex-direction {
+ flex-direction: column;
+}
+
+.flex-wrap {
+ flex-wrap: wrap;
+}
+
+.align-start {
+ align-items: flex-start;
+}
+
+.align-end {
+ align-items: flex-end;
+}
+
+.align-center {
+ align-items: center;
+}
+
+.align-stretch {
+ align-items: stretch;
+}
+
+.self-start {
+ align-self: flex-start;
+}
+
+.self-center {
+ align-self: flex-center;
+}
+
+.self-end {
+ align-self: flex-end;
+}
+
+.self-stretch {
+ align-self: stretch;
+}
+
+.align-stretch {
+ align-items: stretch;
+}
+
+.justify-start {
+ justify-content: flex-start;
+}
+
+.justify-end {
+ justify-content: flex-end;
+}
+
+.justify-center {
+ justify-content: center;
+}
+
+.justify-between {
+ justify-content: space-between;
+}
+
+.justify-around {
+ justify-content: space-around;
+}
+
+/* grid甯冨眬 */
+
+.grid {
+ display: flex;
+ flex-wrap: wrap;
+}
+
+.grid.grid-square {
+ overflow: hidden;
+}
+
+.grid.grid-square .cu-tag {
+ position: absolute;
+ right: 0;
+ top: 0;
+ border-bottom-left-radius: 6upx;
+ padding: 6upx 12upx;
+ height: auto;
+ background-color: rgba(0, 0, 0, 0.5);
+}
+
+.grid.grid-square>view>text[class*="cuIcon-"] {
+ font-size: 52upx;
+ position: absolute;
+ color: #8799a3;
+ margin: auto;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ flex-direction: column;
+}
+
+.grid.grid-square>view {
+ margin-right: 20upx;
+ margin-bottom: 20upx;
+ border-radius: 6upx;
+ position: relative;
+ overflow: hidden;
+}
+.grid.grid-square>view.bg-img image {
+ width: 100%;
+ height: 100%;
+ position: absolute;
+}
+.grid.col-1.grid-square>view {
+ padding-bottom: 100%;
+ height: 0;
+ margin-right: 0;
+}
+
+.grid.col-2.grid-square>view {
+ padding-bottom: calc((100% - 20upx)/2);
+ height: 0;
+ width: calc((100% - 20upx)/2);
+}
+
+.grid.col-3.grid-square>view {
+ padding-bottom: calc((100% - 40upx)/3);
+ height: 0;
+ width: calc((100% - 40upx)/3);
+}
+
+.grid.col-4.grid-square>view {
+ padding-bottom: calc((100% - 60upx)/4);
+ height: 0;
+ width: calc((100% - 60upx)/4);
+}
+
+.grid.col-5.grid-square>view {
+ padding-bottom: calc((100% - 80upx)/5);
+ height: 0;
+ width: calc((100% - 80upx)/5);
+}
+
+.grid.col-2.grid-square>view:nth-child(2n),
+.grid.col-3.grid-square>view:nth-child(3n),
+.grid.col-4.grid-square>view:nth-child(4n),
+.grid.col-5.grid-square>view:nth-child(5n) {
+ margin-right: 0;
+}
+
+.grid.col-1>view {
+ width: 100%;
+}
+
+.grid.col-2>view {
+ width: 50%;
+}
+
+.grid.col-3>view {
+ width: 33.33%;
+}
+
+.grid.col-4>view {
+ width: 25%;
+}
+
+.grid.col-5>view {
+ width: 20%;
+}
+
+/* -- 鍐呭杈硅窛 -- */
+
+.margin-0 {
+ margin: 0;
+}
+
+.margin-xs {
+ margin: 10upx;
+}
+
+.margin-sm {
+ margin: 20upx;
+}
+
+.margin {
+ margin: 30upx;
+}
+
+.margin-lg {
+ margin: 40upx;
+}
+
+.margin-xl {
+ margin: 50upx;
+}
+
+.margin-top-xs {
+ margin-top: 10upx;
+}
+
+.margin-top-sm {
+ margin-top: 20upx;
+}
+
+.margin-top {
+ margin-top: 30upx;
+}
+
+.margin-top-lg {
+ margin-top: 40upx;
+}
+
+.margin-top-xl {
+ margin-top: 50upx;
+}
+
+.margin-right-xs {
+ margin-right: 10upx;
+}
+
+.margin-right-sm {
+ margin-right: 20upx;
+}
+
+.margin-right {
+ margin-right: 30upx;
+}
+
+.margin-right-lg {
+ margin-right: 40upx;
+}
+
+.margin-right-xl {
+ margin-right: 50upx;
+}
+
+.margin-bottom-xs {
+ margin-bottom: 10upx;
+}
+
+.margin-bottom-sm {
+ margin-bottom: 20upx;
+}
+
+.margin-bottom {
+ margin-bottom: 30upx;
+}
+
+.margin-bottom-lg {
+ margin-bottom: 40upx;
+}
+
+.margin-bottom-xl {
+ margin-bottom: 50upx;
+}
+
+.margin-left-xs {
+ margin-left: 10upx;
+}
+
+.margin-left-sm {
+ margin-left: 20upx;
+}
+
+.margin-left {
+ margin-left: 30upx;
+}
+
+.margin-left-lg {
+ margin-left: 40upx;
+}
+
+.margin-left-xl {
+ margin-left: 50upx;
+}
+
+.margin-lr-xs {
+ margin-left: 10upx;
+ margin-right: 10upx;
+}
+
+.margin-lr-sm {
+ margin-left: 20upx;
+ margin-right: 20upx;
+}
+
+.margin-lr {
+ margin-left: 30upx;
+ margin-right: 30upx;
+}
+
+.margin-lr-lg {
+ margin-left: 40upx;
+ margin-right: 40upx;
+}
+
+.margin-lr-xl {
+ margin-left: 50upx;
+ margin-right: 50upx;
+}
+
+.margin-tb-xs {
+ margin-top: 10upx;
+ margin-bottom: 10upx;
+}
+
+.margin-tb-sm {
+ margin-top: 20upx;
+ margin-bottom: 20upx;
+}
+
+.margin-tb {
+ margin-top: 30upx;
+ margin-bottom: 30upx;
+}
+
+.margin-tb-lg {
+ margin-top: 40upx;
+ margin-bottom: 40upx;
+}
+
+.margin-tb-xl {
+ margin-top: 50upx;
+ margin-bottom: 50upx;
+}
+
+.padding-0 {
+ padding: 0;
+}
+
+.padding-xs {
+ padding: 10upx;
+}
+
+.padding-sm {
+ padding: 20upx;
+}
+
+.padding {
+ padding: 30upx;
+}
+
+.padding-lg {
+ padding: 40upx;
+}
+
+.padding-xl {
+ padding: 50upx;
+}
+
+.padding-top-xs {
+ padding-top: 10upx;
+}
+
+.padding-top-sm {
+ padding-top: 20upx;
+}
+
+.padding-top {
+ padding-top: 30upx;
+}
+
+.padding-top-lg {
+ padding-top: 40upx;
+}
+
+.padding-top-xl {
+ padding-top: 50upx;
+}
+
+.padding-right-xs {
+ padding-right: 10upx;
+}
+
+.padding-right-sm {
+ padding-right: 20upx;
+}
+
+.padding-right {
+ padding-right: 30upx;
+}
+
+.padding-right-lg {
+ padding-right: 40upx;
+}
+
+.padding-right-xl {
+ padding-right: 50upx;
+}
+
+.padding-bottom-xs {
+ padding-bottom: 10upx;
+}
+
+.padding-bottom-sm {
+ padding-bottom: 20upx;
+}
+
+.padding-bottom {
+ padding-bottom: 30upx;
+}
+
+.padding-bottom-lg {
+ padding-bottom: 40upx;
+}
+
+.padding-bottom-xl {
+ padding-bottom: 50upx;
+}
+
+.padding-left-xs {
+ padding-left: 10upx;
+}
+
+.padding-left-sm {
+ padding-left: 20upx;
+}
+
+.padding-left {
+ padding-left: 30upx;
+}
+
+.padding-left-lg {
+ padding-left: 40upx;
+}
+
+.padding-left-xl {
+ padding-left: 50upx;
+}
+
+.padding-lr-xs {
+ padding-left: 10upx;
+ padding-right: 10upx;
+}
+
+.padding-lr-sm {
+ padding-left: 20upx;
+ padding-right: 20upx;
+}
+
+.padding-lr {
+ padding-left: 30upx;
+ padding-right: 30upx;
+}
+
+.padding-lr-lg {
+ padding-left: 40upx;
+ padding-right: 40upx;
+}
+
+.padding-lr-xl {
+ padding-left: 50upx;
+ padding-right: 50upx;
+}
+
+.padding-tb-xs {
+ padding-top: 10upx;
+ padding-bottom: 10upx;
+}
+
+.padding-tb-sm {
+ padding-top: 20upx;
+ padding-bottom: 20upx;
+}
+
+.padding-tb {
+ padding-top: 30upx;
+ padding-bottom: 30upx;
+}
+
+.padding-tb-lg {
+ padding-top: 40upx;
+ padding-bottom: 40upx;
+}
+
+.padding-tb-xl {
+ padding-top: 50upx;
+ padding-bottom: 50upx;
+}
+
+/* -- 娴姩 -- */
+
+.cf::after,
+.cf::before {
+ content: " ";
+ display: table;
+}
+
+.cf::after {
+ clear: both;
+}
+
+.fl {
+ float: left;
+}
+
+.fr {
+ float: right;
+}
+
+/* ==================
+ 鑳屾櫙
+ ==================== */
+
+.line-red::after,
+.lines-red::after {
+ border-color: #e54d42;
+}
+
+.line-orange::after,
+.lines-orange::after {
+ border-color: #f37b1d;
+}
+
+.line-yellow::after,
+.lines-yellow::after {
+ border-color: #fbbd08;
+}
+
+.line-olive::after,
+.lines-olive::after {
+ border-color: #8dc63f;
+}
+
+.line-green::after,
+.lines-green::after {
+ border-color: #39b54a;
+}
+
+.line-cyan::after,
+.lines-cyan::after {
+ border-color: #1cbbb4;
+}
+
+.line-blue::after,
+.lines-blue::after {
+ border-color: #0081ff;
+}
+
+.line-purple::after,
+.lines-purple::after {
+ border-color: #6739b6;
+}
+
+.line-mauve::after,
+.lines-mauve::after {
+ border-color: #9c26b0;
+}
+
+.line-pink::after,
+.lines-pink::after {
+ border-color: #e03997;
+}
+
+.line-brown::after,
+.lines-brown::after {
+ border-color: #a5673f;
+}
+
+.line-grey::after,
+.lines-grey::after {
+ border-color: #8799a3;
+}
+
+.line-gray::after,
+.lines-gray::after {
+ border-color: #aaaaaa;
+}
+
+.line-black::after,
+.lines-black::after {
+ border-color: #333333;
+}
+
+.line-white::after,
+.lines-white::after {
+ border-color: #ffffff;
+}
+
+.bg-red {
+ background-color: #e54d42;
+ color: #ffffff;
+}
+
+.bg-orange {
+ background-color: #f37b1d;
+ color: #ffffff;
+}
+
+.bg-yellow {
+ background-color: #fbbd08;
+ color: #333333;
+}
+
+.bg-olive {
+ background-color: #8dc63f;
+ color: #ffffff;
+}
+
+.bg-green {
+ background-color: #39b54a;
+ color: #ffffff;
+}
+
+.bg-cyan {
+ background-color: #1cbbb4;
+ color: #ffffff;
+}
+
+.bg-blue {
+ background-color: #0081ff;
+ color: #ffffff;
+}
+
+.bg-purple {
+ background-color: #6739b6;
+ color: #ffffff;
+}
+
+.bg-mauve {
+ background-color: #9c26b0;
+ color: #ffffff;
+}
+
+.bg-pink {
+ background-color: #e03997;
+ color: #ffffff;
+}
+
+.bg-brown {
+ background-color: #a5673f;
+ color: #ffffff;
+}
+
+.bg-grey {
+ background-color: #8799a3;
+ color: #ffffff;
+}
+
+.bg-gray {
+ background-color: #f0f0f0;
+ color: #333333;
+}
+
+.bg-black {
+ background-color: #333333;
+ color: #ffffff;
+}
+
+.bg-white {
+ background-color: #ffffff;
+ color: #666666;
+}
+
+.bg-shadeTop {
+ background-image: linear-gradient(rgba(0, 0, 0, 1), rgba(0, 0, 0, 0.01));
+ color: #ffffff;
+}
+
+.bg-shadeBottom {
+ background-image: linear-gradient(rgba(0, 0, 0, 0.01), rgba(0, 0, 0, 1));
+ color: #ffffff;
+}
+
+.bg-red.light {
+ color: #e54d42;
+ background-color: #fadbd9;
+}
+
+.bg-orange.light {
+ color: #f37b1d;
+ background-color: #fde6d2;
+}
+
+.bg-yellow.light {
+ color: #fbbd08;
+ background-color: #fef2ced2;
+}
+
+.bg-olive.light {
+ color: #8dc63f;
+ background-color: #e8f4d9;
+}
+
+.bg-green.light {
+ color: #39b54a;
+ background-color: #d7f0dbff;
+}
+
+.bg-cyan.light {
+ color: #1cbbb4;
+ background-color: #d2f1f0;
+}
+
+.bg-blue.light {
+ color: #0081ff;
+ background-color: #cce6ff;
+}
+
+.bg-purple.light {
+ color: #6739b6;
+ background-color: #e1d7f0;
+}
+
+.bg-mauve.light {
+ color: #9c26b0;
+ background-color: #ebd4ef;
+}
+
+.bg-pink.light {
+ color: #e03997;
+ background-color: #f9d7ea;
+}
+
+.bg-brown.light {
+ color: #a5673f;
+ background-color: #ede1d9;
+}
+
+.bg-grey.light {
+ color: #8799a3;
+ background-color: #e7ebed;
+}
+
+.bg-gradual-red {
+ background-image: linear-gradient(45deg, #f43f3b, #ec008c);
+ color: #ffffff;
+}
+
+.bg-gradual-orange {
+ background-image: linear-gradient(45deg, #ff9700, #ed1c24);
+ color: #ffffff;
+}
+
+.bg-gradual-green {
+ background-image: linear-gradient(45deg, #39b54a, #8dc63f);
+ color: #ffffff;
+}
+
+.bg-gradual-purple {
+ background-image: linear-gradient(45deg, #9000ff, #5e00ff);
+ color: #ffffff;
+}
+
+.bg-gradual-pink {
+ background-image: linear-gradient(45deg, #ec008c, #6739b6);
+ color: #ffffff;
+}
+
+.bg-gradual-blue {
+ background-image: linear-gradient(45deg, #0081ff, #1cbbb4);
+ color: #ffffff;
+}
+
+.shadow[class*="-red"] {
+ box-shadow: 6upx 6upx 8upx rgba(204, 69, 59, 0.2);
+}
+
+.shadow[class*="-orange"] {
+ box-shadow: 6upx 6upx 8upx rgba(217, 109, 26, 0.2);
+}
+
+.shadow[class*="-yellow"] {
+ box-shadow: 6upx 6upx 8upx rgba(224, 170, 7, 0.2);
+}
+
+.shadow[class*="-olive"] {
+ box-shadow: 6upx 6upx 8upx rgba(124, 173, 55, 0.2);
+}
+
+.shadow[class*="-green"] {
+ box-shadow: 6upx 6upx 8upx rgba(48, 156, 63, 0.2);
+}
+
+.shadow[class*="-cyan"] {
+ box-shadow: 6upx 6upx 8upx rgba(28, 187, 180, 0.2);
+}
+
+.shadow[class*="-blue"] {
+ box-shadow: 6upx 6upx 8upx rgba(0, 102, 204, 0.2);
+}
+
+.shadow[class*="-purple"] {
+ box-shadow: 6upx 6upx 8upx rgba(88, 48, 156, 0.2);
+}
+
+.shadow[class*="-mauve"] {
+ box-shadow: 6upx 6upx 8upx rgba(133, 33, 150, 0.2);
+}
+
+.shadow[class*="-pink"] {
+ box-shadow: 6upx 6upx 8upx rgba(199, 50, 134, 0.2);
+}
+
+.shadow[class*="-brown"] {
+ box-shadow: 6upx 6upx 8upx rgba(140, 88, 53, 0.2);
+}
+
+.shadow[class*="-grey"] {
+ box-shadow: 6upx 6upx 8upx rgba(114, 130, 138, 0.2);
+}
+
+.shadow[class*="-gray"] {
+ box-shadow: 6upx 6upx 8upx rgba(114, 130, 138, 0.2);
+}
+
+.shadow[class*="-black"] {
+ box-shadow: 6upx 6upx 8upx rgba(26, 26, 26, 0.2);
+}
+
+.shadow[class*="-white"] {
+ box-shadow: 6upx 6upx 8upx rgba(26, 26, 26, 0.2);
+}
+
+.text-shadow[class*="-red"] {
+ text-shadow: 6upx 6upx 8upx rgba(204, 69, 59, 0.2);
+}
+
+.text-shadow[class*="-orange"] {
+ text-shadow: 6upx 6upx 8upx rgba(217, 109, 26, 0.2);
+}
+
+.text-shadow[class*="-yellow"] {
+ text-shadow: 6upx 6upx 8upx rgba(224, 170, 7, 0.2);
+}
+
+.text-shadow[class*="-olive"] {
+ text-shadow: 6upx 6upx 8upx rgba(124, 173, 55, 0.2);
+}
+
+.text-shadow[class*="-green"] {
+ text-shadow: 6upx 6upx 8upx rgba(48, 156, 63, 0.2);
+}
+
+.text-shadow[class*="-cyan"] {
+ text-shadow: 6upx 6upx 8upx rgba(28, 187, 180, 0.2);
+}
+
+.text-shadow[class*="-blue"] {
+ text-shadow: 6upx 6upx 8upx rgba(0, 102, 204, 0.2);
+}
+
+.text-shadow[class*="-purple"] {
+ text-shadow: 6upx 6upx 8upx rgba(88, 48, 156, 0.2);
+}
+
+.text-shadow[class*="-mauve"] {
+ text-shadow: 6upx 6upx 8upx rgba(133, 33, 150, 0.2);
+}
+
+.text-shadow[class*="-pink"] {
+ text-shadow: 6upx 6upx 8upx rgba(199, 50, 134, 0.2);
+}
+
+.text-shadow[class*="-brown"] {
+ text-shadow: 6upx 6upx 8upx rgba(140, 88, 53, 0.2);
+}
+
+.text-shadow[class*="-grey"] {
+ text-shadow: 6upx 6upx 8upx rgba(114, 130, 138, 0.2);
+}
+
+.text-shadow[class*="-gray"] {
+ text-shadow: 6upx 6upx 8upx rgba(114, 130, 138, 0.2);
+}
+
+.text-shadow[class*="-black"] {
+ text-shadow: 6upx 6upx 8upx rgba(26, 26, 26, 0.2);
+}
+
+.bg-img {
+ background-size: cover;
+ background-position: center;
+ background-repeat: no-repeat;
+}
+
+.bg-mask {
+ background-color: #333333;
+ position: relative;
+}
+
+.bg-mask::after {
+ content: "";
+ border-radius: inherit;
+ width: 100%;
+ height: 100%;
+ display: block;
+ background-color: rgba(0, 0, 0, 0.4);
+ position: absolute;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ top: 0;
+}
+
+.bg-mask view,
+.bg-mask cover-view {
+ z-index: 5;
+ position: relative;
+}
+
+.bg-video {
+ position: relative;
+}
+
+.bg-video video {
+ display: block;
+ height: 100%;
+ width: 100%;
+ -o-object-fit: cover;
+ object-fit: cover;
+ position: absolute;
+ top: 0;
+ z-index: 0;
+ pointer-events: none;
+}
+
+/* ==================
+ 鏂囨湰
+ ==================== */
+
+.text-xs {
+ font-size: 20upx;
+}
+
+.text-sm {
+ font-size: 24upx;
+}
+
+.text-df {
+ font-size: 28upx;
+}
+
+.text-lg {
+ font-size: 32upx;
+}
+
+.text-xl {
+ font-size: 36upx;
+}
+
+.text-xxl {
+ font-size: 44upx;
+}
+
+.text-sl {
+ font-size: 80upx;
+}
+
+.text-xsl {
+ font-size: 120upx;
+}
+
+.text-Abc {
+ text-transform: Capitalize;
+}
+
+.text-ABC {
+ text-transform: Uppercase;
+}
+
+.text-abc {
+ text-transform: Lowercase;
+}
+
+.text-price::before {
+ content: "楼";
+ font-size: 80%;
+ margin-right: 4upx;
+}
+
+.text-cut {
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+}
+
+.text-bold {
+ font-weight: bold;
+}
+
+.text-center {
+ text-align: center;
+}
+
+.text-content {
+ line-height: 1.6;
+}
+
+.text-left {
+ text-align: left;
+}
+
+.text-right {
+ text-align: right;
+}
+
+.text-red,
+.line-red,
+.lines-red {
+ color: #e54d42;
+}
+
+.text-orange,
+.line-orange,
+.lines-orange {
+ color: #f37b1d;
+}
+
+.text-yellow,
+.line-yellow,
+.lines-yellow {
+ color: #fbbd08;
+}
+
+.text-olive,
+.line-olive,
+.lines-olive {
+ color: #8dc63f;
+}
+
+.text-green,
+.line-green,
+.lines-green {
+ color: #39b54a;
+}
+
+.text-cyan,
+.line-cyan,
+.lines-cyan {
+ color: #1cbbb4;
+}
+
+.text-blue,
+.line-blue,
+.lines-blue {
+ color: #0081ff;
+}
+
+.text-purple,
+.line-purple,
+.lines-purple {
+ color: #6739b6;
+}
+
+.text-mauve,
+.line-mauve,
+.lines-mauve {
+ color: #9c26b0;
+}
+
+.text-pink,
+.line-pink,
+.lines-pink {
+ color: #e03997;
+}
+
+.text-brown,
+.line-brown,
+.lines-brown {
+ color: #a5673f;
+}
+
+.text-grey,
+.line-grey,
+.lines-grey {
+ color: #8799a3;
+}
+
+.text-gray,
+.line-gray,
+.lines-gray {
+ color: #aaaaaa;
+}
+
+.text-black,
+.line-black,
+.lines-black {
+ color: #333333;
+}
+
+.text-white,
+.line-white,
+.lines-white {
+ color: #ffffff;
+}
+
+/* ==================
+ icon 鍒濆鍖�
+ ==================== */
+ @keyframes cuIcon-spin {
+ 0% {
+ -webkit-transform: rotate(0);
+ transform: rotate(0);
+ }
+
+ 100% {
+ -webkit-transform: rotate(359deg);
+ transform: rotate(359deg);
+ }
+ }
+
+ .cuIconfont-spin {
+ -webkit-animation: cuIcon-spin 2s infinite linear;
+ animation: cuIcon-spin 2s infinite linear;
+ display: inline-block;
+ }
+
+ .cuIconfont-pulse {
+ -webkit-animation: cuIcon-spin 1s infinite steps(8);
+ animation: cuIcon-spin 1s infinite steps(8);
+ display: inline-block;
+ }
+
+ [class*="cuIcon-"] {
+ font-family: "cuIcon";
+ font-size: inherit;
+ font-style: normal;
+ }
+
+ @font-face {
+ font-family: "cuIcon";
+ src: url('//at.alicdn.com/t/font_533566_yfq2d9wdij.eot?t=1545239985831');
+ /* IE9*/
+ src: url('//at.alicdn.com/t/font_533566_yfq2d9wdij.eot?t=1545239985831#iefix') format('embedded-opentype'),
+ /* IE6-IE8 */
+ url('data:application/x-font-woff;charset=utf-8;base64,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') format('woff'),
+ url('//at.alicdn.com/t/font_533566_yfq2d9wdij.ttf?t=1545239985831') format('truetype'),
+ /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
+ url('//at.alicdn.com/t/font_533566_yfq2d9wdij.svg?t=1545239985831#cuIconfont') format('svg');
+ /* iOS 4.1- */
+ }
+
+ .cuIcon-appreciate:before {
+ content: "\e644";
+ }
+
+ .cuIcon-check:before {
+ content: "\e645";
+ }
+
+ .cuIcon-close:before {
+ content: "\e646";
+ }
+
+ .cuIcon-edit:before {
+ content: "\e649";
+ }
+
+ .cuIcon-emoji:before {
+ content: "\e64a";
+ }
+
+ .cuIcon-favorfill:before {
+ content: "\e64b";
+ }
+
+ .cuIcon-favor:before {
+ content: "\e64c";
+ }
+
+ .cuIcon-loading:before {
+ content: "\e64f";
+ }
+
+ .cuIcon-locationfill:before {
+ content: "\e650";
+ }
+
+ .cuIcon-location:before {
+ content: "\e651";
+ }
+
+ .cuIcon-phone:before {
+ content: "\e652";
+ }
+
+ .cuIcon-roundcheckfill:before {
+ content: "\e656";
+ }
+
+ .cuIcon-roundcheck:before {
+ content: "\e657";
+ }
+
+ .cuIcon-roundclosefill:before {
+ content: "\e658";
+ }
+
+ .cuIcon-roundclose:before {
+ content: "\e659";
+ }
+
+ .cuIcon-roundrightfill:before {
+ content: "\e65a";
+ }
+
+ .cuIcon-roundright:before {
+ content: "\e65b";
+ }
+
+ .cuIcon-search:before {
+ content: "\e65c";
+ }
+
+ .cuIcon-taxi:before {
+ content: "\e65d";
+ }
+
+ .cuIcon-timefill:before {
+ content: "\e65e";
+ }
+
+ .cuIcon-time:before {
+ content: "\e65f";
+ }
+
+ .cuIcon-unfold:before {
+ content: "\e661";
+ }
+
+ .cuIcon-warnfill:before {
+ content: "\e662";
+ }
+
+ .cuIcon-warn:before {
+ content: "\e663";
+ }
+
+ .cuIcon-camerafill:before {
+ content: "\e664";
+ }
+
+ .cuIcon-camera:before {
+ content: "\e665";
+ }
+
+ .cuIcon-commentfill:before {
+ content: "\e666";
+ }
+
+ .cuIcon-comment:before {
+ content: "\e667";
+ }
+
+ .cuIcon-likefill:before {
+ content: "\e668";
+ }
+
+ .cuIcon-like:before {
+ content: "\e669";
+ }
+
+ .cuIcon-notificationfill:before {
+ content: "\e66a";
+ }
+
+ .cuIcon-notification:before {
+ content: "\e66b";
+ }
+
+ .cuIcon-order:before {
+ content: "\e66c";
+ }
+
+ .cuIcon-samefill:before {
+ content: "\e66d";
+ }
+
+ .cuIcon-same:before {
+ content: "\e66e";
+ }
+
+ .cuIcon-deliver:before {
+ content: "\e671";
+ }
+
+ .cuIcon-evaluate:before {
+ content: "\e672";
+ }
+
+ .cuIcon-pay:before {
+ content: "\e673";
+ }
+
+ .cuIcon-send:before {
+ content: "\e675";
+ }
+
+ .cuIcon-shop:before {
+ content: "\e676";
+ }
+
+ .cuIcon-ticket:before {
+ content: "\e677";
+ }
+
+ .cuIcon-back:before {
+ content: "\e679";
+ }
+
+ .cuIcon-cascades:before {
+ content: "\e67c";
+ }
+
+ .cuIcon-discover:before {
+ content: "\e67e";
+ }
+
+ .cuIcon-list:before {
+ content: "\e682";
+ }
+
+ .cuIcon-more:before {
+ content: "\e684";
+ }
+
+ .cuIcon-scan:before {
+ content: "\e689";
+ }
+
+ .cuIcon-settings:before {
+ content: "\e68a";
+ }
+
+ .cuIcon-questionfill:before {
+ content: "\e690";
+ }
+
+ .cuIcon-question:before {
+ content: "\e691";
+ }
+
+ .cuIcon-shopfill:before {
+ content: "\e697";
+ }
+
+ .cuIcon-form:before {
+ content: "\e699";
+ }
+
+ .cuIcon-pic:before {
+ content: "\e69b";
+ }
+
+ .cuIcon-filter:before {
+ content: "\e69c";
+ }
+
+ .cuIcon-footprint:before {
+ content: "\e69d";
+ }
+
+ .cuIcon-top:before {
+ content: "\e69e";
+ }
+
+ .cuIcon-pulldown:before {
+ content: "\e69f";
+ }
+
+ .cuIcon-pullup:before {
+ content: "\e6a0";
+ }
+
+ .cuIcon-right:before {
+ content: "\e6a3";
+ }
+
+ .cuIcon-refresh:before {
+ content: "\e6a4";
+ }
+
+ .cuIcon-moreandroid:before {
+ content: "\e6a5";
+ }
+
+ .cuIcon-deletefill:before {
+ content: "\e6a6";
+ }
+
+ .cuIcon-refund:before {
+ content: "\e6ac";
+ }
+
+ .cuIcon-cart:before {
+ content: "\e6af";
+ }
+
+ .cuIcon-qrcode:before {
+ content: "\e6b0";
+ }
+
+ .cuIcon-remind:before {
+ content: "\e6b2";
+ }
+
+ .cuIcon-delete:before {
+ content: "\e6b4";
+ }
+
+ .cuIcon-profile:before {
+ content: "\e6b7";
+ }
+
+ .cuIcon-home:before {
+ content: "\e6b8";
+ }
+
+ .cuIcon-cartfill:before {
+ content: "\e6b9";
+ }
+
+ .cuIcon-discoverfill:before {
+ content: "\e6ba";
+ }
+
+ .cuIcon-homefill:before {
+ content: "\e6bb";
+ }
+
+ .cuIcon-message:before {
+ content: "\e6bc";
+ }
+
+ .cuIcon-addressbook:before {
+ content: "\e6bd";
+ }
+
+ .cuIcon-link:before {
+ content: "\e6bf";
+ }
+
+ .cuIcon-lock:before {
+ content: "\e6c0";
+ }
+
+ .cuIcon-unlock:before {
+ content: "\e6c2";
+ }
+
+ .cuIcon-vip:before {
+ content: "\e6c3";
+ }
+
+ .cuIcon-weibo:before {
+ content: "\e6c4";
+ }
+
+ .cuIcon-activity:before {
+ content: "\e6c5";
+ }
+
+ .cuIcon-friendaddfill:before {
+ content: "\e6c9";
+ }
+
+ .cuIcon-friendadd:before {
+ content: "\e6ca";
+ }
+
+ .cuIcon-friendfamous:before {
+ content: "\e6cb";
+ }
+
+ .cuIcon-friend:before {
+ content: "\e6cc";
+ }
+
+ .cuIcon-goods:before {
+ content: "\e6cd";
+ }
+
+ .cuIcon-selection:before {
+ content: "\e6ce";
+ }
+
+ .cuIcon-explore:before {
+ content: "\e6d2";
+ }
+
+ .cuIcon-present:before {
+ content: "\e6d3";
+ }
+
+ .cuIcon-squarecheckfill:before {
+ content: "\e6d4";
+ }
+
+ .cuIcon-square:before {
+ content: "\e6d5";
+ }
+
+ .cuIcon-squarecheck:before {
+ content: "\e6d6";
+ }
+
+ .cuIcon-round:before {
+ content: "\e6d7";
+ }
+
+ .cuIcon-roundaddfill:before {
+ content: "\e6d8";
+ }
+
+ .cuIcon-roundadd:before {
+ content: "\e6d9";
+ }
+
+ .cuIcon-add:before {
+ content: "\e6da";
+ }
+
+ .cuIcon-notificationforbidfill:before {
+ content: "\e6db";
+ }
+
+ .cuIcon-explorefill:before {
+ content: "\e6dd";
+ }
+
+ .cuIcon-fold:before {
+ content: "\e6de";
+ }
+
+ .cuIcon-game:before {
+ content: "\e6df";
+ }
+
+ .cuIcon-redpacket:before {
+ content: "\e6e0";
+ }
+
+ .cuIcon-selectionfill:before {
+ content: "\e6e1";
+ }
+
+ .cuIcon-similar:before {
+ content: "\e6e2";
+ }
+
+ .cuIcon-appreciatefill:before {
+ content: "\e6e3";
+ }
+
+ .cuIcon-infofill:before {
+ content: "\e6e4";
+ }
+
+ .cuIcon-info:before {
+ content: "\e6e5";
+ }
+
+ .cuIcon-forwardfill:before {
+ content: "\e6ea";
+ }
+
+ .cuIcon-forward:before {
+ content: "\e6eb";
+ }
+
+ .cuIcon-rechargefill:before {
+ content: "\e6ec";
+ }
+
+ .cuIcon-recharge:before {
+ content: "\e6ed";
+ }
+
+ .cuIcon-vipcard:before {
+ content: "\e6ee";
+ }
+
+ .cuIcon-voice:before {
+ content: "\e6ef";
+ }
+
+ .cuIcon-voicefill:before {
+ content: "\e6f0";
+ }
+
+ .cuIcon-friendfavor:before {
+ content: "\e6f1";
+ }
+
+ .cuIcon-wifi:before {
+ content: "\e6f2";
+ }
+
+ .cuIcon-share:before {
+ content: "\e6f3";
+ }
+
+ .cuIcon-wefill:before {
+ content: "\e6f4";
+ }
+
+ .cuIcon-we:before {
+ content: "\e6f5";
+ }
+
+ .cuIcon-lightauto:before {
+ content: "\e6f6";
+ }
+
+ .cuIcon-lightforbid:before {
+ content: "\e6f7";
+ }
+
+ .cuIcon-lightfill:before {
+ content: "\e6f8";
+ }
+
+ .cuIcon-camerarotate:before {
+ content: "\e6f9";
+ }
+
+ .cuIcon-light:before {
+ content: "\e6fa";
+ }
+
+ .cuIcon-barcode:before {
+ content: "\e6fb";
+ }
+
+ .cuIcon-flashlightclose:before {
+ content: "\e6fc";
+ }
+
+ .cuIcon-flashlightopen:before {
+ content: "\e6fd";
+ }
+
+ .cuIcon-searchlist:before {
+ content: "\e6fe";
+ }
+
+ .cuIcon-service:before {
+ content: "\e6ff";
+ }
+
+ .cuIcon-sort:before {
+ content: "\e700";
+ }
+
+ .cuIcon-down:before {
+ content: "\e703";
+ }
+
+ .cuIcon-mobile:before {
+ content: "\e704";
+ }
+
+ .cuIcon-mobilefill:before {
+ content: "\e705";
+ }
+
+ .cuIcon-copy:before {
+ content: "\e706";
+ }
+
+ .cuIcon-countdownfill:before {
+ content: "\e707";
+ }
+
+ .cuIcon-countdown:before {
+ content: "\e708";
+ }
+
+ .cuIcon-noticefill:before {
+ content: "\e709";
+ }
+
+ .cuIcon-notice:before {
+ content: "\e70a";
+ }
+
+ .cuIcon-upstagefill:before {
+ content: "\e70e";
+ }
+
+ .cuIcon-upstage:before {
+ content: "\e70f";
+ }
+
+ .cuIcon-babyfill:before {
+ content: "\e710";
+ }
+
+ .cuIcon-baby:before {
+ content: "\e711";
+ }
+
+ .cuIcon-brandfill:before {
+ content: "\e712";
+ }
+
+ .cuIcon-brand:before {
+ content: "\e713";
+ }
+
+ .cuIcon-choicenessfill:before {
+ content: "\e714";
+ }
+
+ .cuIcon-choiceness:before {
+ content: "\e715";
+ }
+
+ .cuIcon-clothesfill:before {
+ content: "\e716";
+ }
+
+ .cuIcon-clothes:before {
+ content: "\e717";
+ }
+
+ .cuIcon-creativefill:before {
+ content: "\e718";
+ }
+
+ .cuIcon-creative:before {
+ content: "\e719";
+ }
+
+ .cuIcon-female:before {
+ content: "\e71a";
+ }
+
+ .cuIcon-keyboard:before {
+ content: "\e71b";
+ }
+
+ .cuIcon-male:before {
+ content: "\e71c";
+ }
+
+ .cuIcon-newfill:before {
+ content: "\e71d";
+ }
+
+ .cuIcon-new:before {
+ content: "\e71e";
+ }
+
+ .cuIcon-pullleft:before {
+ content: "\e71f";
+ }
+
+ .cuIcon-pullright:before {
+ content: "\e720";
+ }
+
+ .cuIcon-rankfill:before {
+ content: "\e721";
+ }
+
+ .cuIcon-rank:before {
+ content: "\e722";
+ }
+
+ .cuIcon-bad:before {
+ content: "\e723";
+ }
+
+ .cuIcon-cameraadd:before {
+ content: "\e724";
+ }
+
+ .cuIcon-focus:before {
+ content: "\e725";
+ }
+
+ .cuIcon-friendfill:before {
+ content: "\e726";
+ }
+
+ .cuIcon-cameraaddfill:before {
+ content: "\e727";
+ }
+
+ .cuIcon-apps:before {
+ content: "\e729";
+ }
+
+ .cuIcon-paintfill:before {
+ content: "\e72a";
+ }
+
+ .cuIcon-paint:before {
+ content: "\e72b";
+ }
+
+ .cuIcon-picfill:before {
+ content: "\e72c";
+ }
+
+ .cuIcon-refresharrow:before {
+ content: "\e72d";
+ }
+
+ .cuIcon-colorlens:before {
+ content: "\e6e6";
+ }
+
+ .cuIcon-markfill:before {
+ content: "\e730";
+ }
+
+ .cuIcon-mark:before {
+ content: "\e731";
+ }
+
+ .cuIcon-presentfill:before {
+ content: "\e732";
+ }
+
+ .cuIcon-repeal:before {
+ content: "\e733";
+ }
+
+ .cuIcon-album:before {
+ content: "\e734";
+ }
+
+ .cuIcon-peoplefill:before {
+ content: "\e735";
+ }
+
+ .cuIcon-people:before {
+ content: "\e736";
+ }
+
+ .cuIcon-servicefill:before {
+ content: "\e737";
+ }
+
+ .cuIcon-repair:before {
+ content: "\e738";
+ }
+
+ .cuIcon-file:before {
+ content: "\e739";
+ }
+
+ .cuIcon-repairfill:before {
+ content: "\e73a";
+ }
+
+ .cuIcon-taoxiaopu:before {
+ content: "\e73b";
+ }
+
+ .cuIcon-weixin:before {
+ content: "\e612";
+ }
+
+ .cuIcon-attentionfill:before {
+ content: "\e73c";
+ }
+
+ .cuIcon-attention:before {
+ content: "\e73d";
+ }
+
+ .cuIcon-commandfill:before {
+ content: "\e73e";
+ }
+
+ .cuIcon-command:before {
+ content: "\e73f";
+ }
+
+ .cuIcon-communityfill:before {
+ content: "\e740";
+ }
+
+ .cuIcon-community:before {
+ content: "\e741";
+ }
+
+ .cuIcon-read:before {
+ content: "\e742";
+ }
+
+ .cuIcon-calendar:before {
+ content: "\e74a";
+ }
+
+ .cuIcon-cut:before {
+ content: "\e74b";
+ }
+
+ .cuIcon-magic:before {
+ content: "\e74c";
+ }
+
+ .cuIcon-backwardfill:before {
+ content: "\e74d";
+ }
+
+ .cuIcon-playfill:before {
+ content: "\e74f";
+ }
+
+ .cuIcon-stop:before {
+ content: "\e750";
+ }
+
+ .cuIcon-tagfill:before {
+ content: "\e751";
+ }
+
+ .cuIcon-tag:before {
+ content: "\e752";
+ }
+
+ .cuIcon-group:before {
+ content: "\e753";
+ }
+
+ .cuIcon-all:before {
+ content: "\e755";
+ }
+
+ .cuIcon-backdelete:before {
+ content: "\e756";
+ }
+
+ .cuIcon-hotfill:before {
+ content: "\e757";
+ }
+
+ .cuIcon-hot:before {
+ content: "\e758";
+ }
+
+ .cuIcon-post:before {
+ content: "\e759";
+ }
+
+ .cuIcon-radiobox:before {
+ content: "\e75b";
+ }
+
+ .cuIcon-rounddown:before {
+ content: "\e75c";
+ }
+
+ .cuIcon-upload:before {
+ content: "\e75d";
+ }
+
+ .cuIcon-writefill:before {
+ content: "\e760";
+ }
+
+ .cuIcon-write:before {
+ content: "\e761";
+ }
+
+ .cuIcon-radioboxfill:before {
+ content: "\e763";
+ }
+
+ .cuIcon-punch:before {
+ content: "\e764";
+ }
+
+ .cuIcon-shake:before {
+ content: "\e765";
+ }
+
+ .cuIcon-move:before {
+ content: "\e768";
+ }
+
+ .cuIcon-safe:before {
+ content: "\e769";
+ }
+
+ .cuIcon-activityfill:before {
+ content: "\e775";
+ }
+
+ .cuIcon-crownfill:before {
+ content: "\e776";
+ }
+
+ .cuIcon-crown:before {
+ content: "\e777";
+ }
+
+ .cuIcon-goodsfill:before {
+ content: "\e778";
+ }
+
+ .cuIcon-messagefill:before {
+ content: "\e779";
+ }
+
+ .cuIcon-profilefill:before {
+ content: "\e77a";
+ }
+
+ .cuIcon-sound:before {
+ content: "\e77b";
+ }
+
+ .cuIcon-sponsorfill:before {
+ content: "\e77c";
+ }
+
+ .cuIcon-sponsor:before {
+ content: "\e77d";
+ }
+
+ .cuIcon-upblock:before {
+ content: "\e77e";
+ }
+
+ .cuIcon-weblock:before {
+ content: "\e77f";
+ }
+
+ .cuIcon-weunblock:before {
+ content: "\e780";
+ }
+
+ .cuIcon-my:before {
+ content: "\e78b";
+ }
+
+ .cuIcon-myfill:before {
+ content: "\e78c";
+ }
+
+ .cuIcon-emojifill:before {
+ content: "\e78d";
+ }
+
+ .cuIcon-emojiflashfill:before {
+ content: "\e78e";
+ }
+
+ .cuIcon-flashbuyfill:before {
+ content: "\e78f";
+ }
+
+ .cuIcon-text:before {
+ content: "\e791";
+ }
+
+ .cuIcon-goodsfavor:before {
+ content: "\e794";
+ }
+
+ .cuIcon-musicfill:before {
+ content: "\e795";
+ }
+
+ .cuIcon-musicforbidfill:before {
+ content: "\e796";
+ }
+
+ .cuIcon-card:before {
+ content: "\e624";
+ }
+
+ .cuIcon-triangledownfill:before {
+ content: "\e79b";
+ }
+
+ .cuIcon-triangleupfill:before {
+ content: "\e79c";
+ }
+
+ .cuIcon-roundleftfill-copy:before {
+ content: "\e79e";
+ }
+
+ .cuIcon-font:before {
+ content: "\e76a";
+ }
+
+ .cuIcon-title:before {
+ content: "\e82f";
+ }
+
+ .cuIcon-recordfill:before {
+ content: "\e7a4";
+ }
+
+ .cuIcon-record:before {
+ content: "\e7a6";
+ }
+
+ .cuIcon-cardboardfill:before {
+ content: "\e7a9";
+ }
+
+ .cuIcon-cardboard:before {
+ content: "\e7aa";
+ }
+
+ .cuIcon-formfill:before {
+ content: "\e7ab";
+ }
+
+ .cuIcon-coin:before {
+ content: "\e7ac";
+ }
+
+ .cuIcon-cardboardforbid:before {
+ content: "\e7af";
+ }
+
+ .cuIcon-circlefill:before {
+ content: "\e7b0";
+ }
+
+ .cuIcon-circle:before {
+ content: "\e7b1";
+ }
+
+ .cuIcon-attentionforbid:before {
+ content: "\e7b2";
+ }
+
+ .cuIcon-attentionforbidfill:before {
+ content: "\e7b3";
+ }
+
+ .cuIcon-attentionfavorfill:before {
+ content: "\e7b4";
+ }
+
+ .cuIcon-attentionfavor:before {
+ content: "\e7b5";
+ }
+
+ .cuIcon-titles:before {
+ content: "\e701";
+ }
+
+ .cuIcon-icloading:before {
+ content: "\e67a";
+ }
+
+ .cuIcon-full:before {
+ content: "\e7bc";
+ }
+
+ .cuIcon-mail:before {
+ content: "\e7bd";
+ }
+
+ .cuIcon-peoplelist:before {
+ content: "\e7be";
+ }
+
+ .cuIcon-goodsnewfill:before {
+ content: "\e7bf";
+ }
+
+ .cuIcon-goodsnew:before {
+ content: "\e7c0";
+ }
+
+ .cuIcon-medalfill:before {
+ content: "\e7c1";
+ }
+
+ .cuIcon-medal:before {
+ content: "\e7c2";
+ }
+
+ .cuIcon-newsfill:before {
+ content: "\e7c3";
+ }
+
+ .cuIcon-newshotfill:before {
+ content: "\e7c4";
+ }
+
+ .cuIcon-newshot:before {
+ content: "\e7c5";
+ }
+
+ .cuIcon-news:before {
+ content: "\e7c6";
+ }
+
+ .cuIcon-videofill:before {
+ content: "\e7c7";
+ }
+
+ .cuIcon-video:before {
+ content: "\e7c8";
+ }
+
+ .cuIcon-exit:before {
+ content: "\e7cb";
+ }
+
+ .cuIcon-skinfill:before {
+ content: "\e7cc";
+ }
+
+ .cuIcon-skin:before {
+ content: "\e7cd";
+ }
+
+ .cuIcon-moneybagfill:before {
+ content: "\e7ce";
+ }
+
+ .cuIcon-usefullfill:before {
+ content: "\e7cf";
+ }
+
+ .cuIcon-usefull:before {
+ content: "\e7d0";
+ }
+
+ .cuIcon-moneybag:before {
+ content: "\e7d1";
+ }
+
+ .cuIcon-redpacket_fill:before {
+ content: "\e7d3";
+ }
+
+ .cuIcon-subscription:before {
+ content: "\e7d4";
+ }
+
+ .cuIcon-loading1:before {
+ content: "\e633";
+ }
+
+ .cuIcon-github:before {
+ content: "\e692";
+ }
+
+ .cuIcon-global:before {
+ content: "\e7eb";
+ }
+
+ .cuIcon-settingsfill:before {
+ content: "\e6ab";
+ }
+
+ .cuIcon-back_android:before {
+ content: "\e7ed";
+ }
+
+ .cuIcon-expressman:before {
+ content: "\e7ef";
+ }
+
+ .cuIcon-evaluate_fill:before {
+ content: "\e7f0";
+ }
+
+ .cuIcon-group_fill:before {
+ content: "\e7f5";
+ }
+
+ .cuIcon-play_forward_fill:before {
+ content: "\e7f6";
+ }
+
+ .cuIcon-deliver_fill:before {
+ content: "\e7f7";
+ }
+
+ .cuIcon-notice_forbid_fill:before {
+ content: "\e7f8";
+ }
+
+ .cuIcon-fork:before {
+ content: "\e60c";
+ }
+
+ .cuIcon-pick:before {
+ content: "\e7fa";
+ }
+
+ .cuIcon-wenzi:before {
+ content: "\e6a7";
+ }
+
+ .cuIcon-ellipse:before {
+ content: "\e600";
+ }
+
+ .cuIcon-qr_code:before {
+ content: "\e61b";
+ }
+
+ .cuIcon-dianhua:before {
+ content: "\e64d";
+ }
+
+ .cuIcon-cuIcon:before {
+ content: "\e602";
+ }
+
+ .cuIcon-loading2:before {
+ content: "\e7f1";
+ }
+
+ .cuIcon-btn:before {
+ content: "\e601";
+ }
diff --git a/app/static/scss/global.scss b/app/static/scss/global.scss
new file mode 100644
index 0000000..ac636bd
--- /dev/null
+++ b/app/static/scss/global.scss
@@ -0,0 +1,90 @@
+.text-center {
+ text-align: center;
+}
+
+.font-13 {
+ font-size: 13px;
+}
+
+.font-12 {
+ font-size: 12px;
+}
+
+.font-11 {
+ font-size: 11px;
+}
+
+.text-grey1 {
+ color: #888;
+}
+.text-grey2 {
+ color: #aaa;
+}
+
+.list-cell-arrow::before {
+ content: ' ';
+ height: 10px;
+ width: 10px;
+ border-width: 2px 2px 0 0;
+ border-color: #c0c0c0;
+ border-style: solid;
+ -webkit-transform: matrix(0.5, 0.5, -0.5, 0.5, 0, 0);
+ transform: matrix(0.5, 0.5, -0.5, 0.5, 0, 0);
+ position: absolute;
+ top: 50%;
+ margin-top: -6px;
+ right: 30rpx;
+ }
+
+ .list-cell {
+ position: relative;
+ width: 100%;
+ box-sizing: border-box;
+ background-color: #fff;
+ color: #333;
+ padding: 26rpx 30rpx;
+ }
+
+ .list-cell:first-child {
+ border-radius: 8rpx 8rpx 0 0;
+ }
+
+ .list-cell:last-child {
+ border-radius: 0 0 8rpx 8rpx;
+ }
+
+ .list-cell::after {
+ content: '';
+ position: absolute;
+ border-bottom: 1px solid #eaeef1;
+ -webkit-transform: scaleY(0.5) translateZ(0);
+ transform: scaleY(0.5) translateZ(0);
+ transform-origin: 0 100%;
+ bottom: 0;
+ right: 0;
+ left: 0;
+ pointer-events: none;
+ }
+
+
+ .menu-list {
+ margin: 15px 15px;
+
+ .menu-item-box {
+ width: 100%;
+ display: flex;
+ align-items: center;
+
+ .menu-icon {
+ color: #007AFF;
+ font-size: 16px;
+ margin-right: 5px;
+ }
+
+ .text-right {
+ margin-left: auto;
+ margin-right: 34rpx;
+ color: #999;
+ }
+ }
+ }
diff --git a/app/static/scss/index.scss b/app/static/scss/index.scss
new file mode 100644
index 0000000..745cffa
--- /dev/null
+++ b/app/static/scss/index.scss
@@ -0,0 +1,6 @@
+// global
+@import "./global.scss";
+// color-ui
+@import "@/static/scss/colorui.css";
+// iconfont
+@import "@/static/font/iconfont.css";
\ No newline at end of file
diff --git a/app/store/getters.js b/app/store/getters.js
new file mode 100644
index 0000000..8854794
--- /dev/null
+++ b/app/store/getters.js
@@ -0,0 +1,8 @@
+const getters = {
+ token: state => state.user.token,
+ avatar: state => state.user.avatar,
+ name: state => state.user.name,
+ roles: state => state.user.roles,
+ permissions: state => state.user.permissions
+}
+export default getters
diff --git a/app/store/index.js b/app/store/index.js
new file mode 100644
index 0000000..83a9db5
--- /dev/null
+++ b/app/store/index.js
@@ -0,0 +1,15 @@
+import Vue from 'vue'
+import Vuex from 'vuex'
+import user from '@/store/modules/user'
+import getters from './getters'
+
+Vue.use(Vuex)
+
+const store = new Vuex.Store({
+ modules: {
+ user
+ },
+ getters
+})
+
+export default store
diff --git a/app/store/modules/user.js b/app/store/modules/user.js
new file mode 100644
index 0000000..c1ec441
--- /dev/null
+++ b/app/store/modules/user.js
@@ -0,0 +1,98 @@
+import config from '@/config'
+import storage from '@/utils/storage'
+import constant from '@/utils/constant'
+import { login, logout, getInfo } from '@/api/login'
+import { getToken, setToken, removeToken } from '@/utils/auth'
+
+const baseUrl = config.baseUrl
+
+const user = {
+ state: {
+ token: getToken(),
+ name: storage.get(constant.name),
+ avatar: storage.get(constant.avatar),
+ roles: storage.get(constant.roles),
+ permissions: storage.get(constant.permissions)
+ },
+
+ mutations: {
+ SET_TOKEN: (state, token) => {
+ state.token = token
+ },
+ SET_NAME: (state, name) => {
+ state.name = name
+ storage.set(constant.name, name)
+ },
+ SET_AVATAR: (state, avatar) => {
+ state.avatar = avatar
+ storage.set(constant.avatar, avatar)
+ },
+ SET_ROLES: (state, roles) => {
+ state.roles = roles
+ storage.set(constant.roles, roles)
+ },
+ SET_PERMISSIONS: (state, permissions) => {
+ state.permissions = permissions
+ storage.set(constant.permissions, permissions)
+ }
+ },
+
+ actions: {
+ // 鐧诲綍
+ Login({ commit }, userInfo) {
+ const username = userInfo.username.trim()
+ const password = userInfo.password
+ const code = userInfo.code
+ const uuid = userInfo.uuid
+ return new Promise((resolve, reject) => {
+ login(username, password, code, uuid).then(res => {
+ setToken(res.token)
+ commit('SET_TOKEN', res.token)
+ resolve()
+ }).catch(error => {
+ reject(error)
+ })
+ })
+ },
+
+ // 鑾峰彇鐢ㄦ埛淇℃伅
+ GetInfo({ commit, state }) {
+ return new Promise((resolve, reject) => {
+ getInfo().then(res => {
+ const user = res.user
+ const avatar = (user == null || user.avatar == "" || user.avatar == null) ? require("@/static/images/profile.jpg") : baseUrl + user.avatar
+ const username = (user == null || user.userName == "" || user.userName == null) ? "" : user.userName
+ if (res.roles && res.roles.length > 0) {
+ commit('SET_ROLES', res.roles)
+ commit('SET_PERMISSIONS', res.permissions)
+ } else {
+ commit('SET_ROLES', ['ROLE_DEFAULT'])
+ }
+ commit('SET_NAME', username)
+ commit('SET_AVATAR', avatar)
+ resolve(res)
+ }).catch(error => {
+ reject(error)
+ })
+ })
+ },
+
+ // 閫�鍑虹郴缁�
+ LogOut({ commit, state }) {
+ return new Promise((resolve, reject) => {
+ logout(state.token).then(() => {
+ commit('SET_TOKEN', '')
+ commit('SET_ROLES', [])
+ commit('SET_PERMISSIONS', [])
+ removeToken()
+ storage.clean()
+ resolve()
+ }).catch(error => {
+ reject(error)
+ })
+ })
+ }
+ }
+}
+
+export default user
diff --git a/app/uni.scss b/app/uni.scss
new file mode 100644
index 0000000..5b30ca3
--- /dev/null
+++ b/app/uni.scss
@@ -0,0 +1,64 @@
+/**
+ * uni-app鍐呯疆鐨勫父鐢ㄦ牱寮忓彉閲�
+ */
+
+/* 琛屼负鐩稿叧棰滆壊 */
+$uni-color-primary: #007aff;
+$uni-color-success: #4cd964;
+$uni-color-warning: #f0ad4e;
+$uni-color-error: #dd524d;
+
+/* 鏂囧瓧鍩烘湰棰滆壊 */
+$uni-text-color:#333;//鍩烘湰鑹�
+$uni-text-color-inverse:#fff;//鍙嶈壊
+$uni-text-color-grey:#999;//杈呭姪鐏拌壊锛屽鍔犺浇鏇村鐨勬彁绀轰俊鎭�
+$uni-text-color-placeholder: #808080;
+$uni-text-color-disable:#c0c0c0;
+
+/* 鑳屾櫙棰滆壊 */
+$uni-bg-color:#ffffff;
+$uni-bg-color-grey:#f8f8f8;
+$uni-bg-color-hover:#f1f1f1;//鐐瑰嚮鐘舵�侀鑹�
+$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//閬僵棰滆壊
+
+/* 杈规棰滆壊 */
+$uni-border-color:#e5e5e5;
+
+/* 灏哄鍙橀噺 */
+
+/* 鏂囧瓧灏哄 */
+$uni-font-size-sm:12px;
+$uni-font-size-base:14px;
+$uni-font-size-lg:16px;
+
+/* 鍥剧墖灏哄 */
+$uni-img-size-sm:20px;
+$uni-img-size-base:26px;
+$uni-img-size-lg:40px;
+
+/* Border Radius */
+$uni-border-radius-sm: 2px;
+$uni-border-radius-base: 3px;
+$uni-border-radius-lg: 6px;
+$uni-border-radius-circle: 50%;
+
+/* 姘村钩闂磋窛 */
+$uni-spacing-row-sm: 5px;
+$uni-spacing-row-base: 10px;
+$uni-spacing-row-lg: 15px;
+
+/* 鍨傜洿闂磋窛 */
+$uni-spacing-col-sm: 4px;
+$uni-spacing-col-base: 8px;
+$uni-spacing-col-lg: 12px;
+
+/* 閫忔槑搴� */
+$uni-opacity-disabled: 0.3; // 缁勪欢绂佺敤鎬佺殑閫忔槑搴�
+
+/* 鏂囩珷鍦烘櫙鐩稿叧 */
+$uni-color-title: #2C405A; // 鏂囩珷鏍囬棰滆壊
+$uni-font-size-title:20px;
+$uni-color-subtitle: #555555; // 浜岀骇鏍囬棰滆壊
+$uni-font-size-subtitle:26px;
+$uni-color-paragraph: #3F536E; // 鏂囩珷娈佃惤棰滆壊
+$uni-font-size-paragraph:15px;
\ No newline at end of file
diff --git a/app/uni_modules/uni-badge/changelog.md b/app/uni_modules/uni-badge/changelog.md
new file mode 100644
index 0000000..e352c60
--- /dev/null
+++ b/app/uni_modules/uni-badge/changelog.md
@@ -0,0 +1,33 @@
+## 1.2.2锛�2023-01-28锛�
+- 淇 杩愯/鎵撳寘 鎺у埗鍙拌鍛婇棶棰�
+## 1.2.1锛�2022-09-05锛�
+- 淇 褰� text 瓒呰繃 max-num 鏃讹紝badge 鐨勫搴﹁绠楁槸鏍规嵁 text 鐨勯暱搴﹁绠楋紝鏇存敼涓� css 璁$畻瀹為檯灞曠ず瀹藉害锛岃瑙�:[https://ask.dcloud.net.cn/question/150473](https://ask.dcloud.net.cn/question/150473)
+## 1.2.0锛�2021-11-19锛�
+- 浼樺寲 缁勪欢UI锛屽苟鎻愪緵璁捐璧勬簮锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 鏂囨。杩佺Щ锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/uni-badge](https://uniapp.dcloud.io/component/uniui/uni-badge)
+## 1.1.7锛�2021-11-08锛�
+- 浼樺寲 鍗囩骇ui
+- 淇敼 size 灞炴�ч粯璁ゅ�艰皟鏁翠负 small
+- 淇敼 type 灞炴�э紝榛樿鍊艰皟鏁翠负 error锛宨nfo 鏇挎崲 default
+## 1.1.6锛�2021-09-22锛�
+- 淇 鍦ㄥ瓧鑺傚皬绋嬪簭涓婃牱寮忎笉鐢熸晥鐨� bug
+## 1.1.5锛�2021-07-30锛�
+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤簐ue3椤圭洰锛岃瑙� [uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+## 1.1.4锛�2021-07-29锛�
+- 淇 鍘绘帀 nvue 涓嶆敮鎸乧ss 鐨� align-self 灞炴�э紝nvue 涓嬩笉鏆傛敮鎸� absolute 灞炴��
+## 1.1.3锛�2021-06-24锛�
+- 浼樺寲 绀轰緥椤圭洰
+## 1.1.1锛�2021-05-12锛�
+- 鏂板 缁勪欢绀轰緥鍦板潃
+## 1.1.0锛�2021-05-12锛�
+- 鏂板 uni-badge 鐨� absolute 灞炴�э紝鏀寔瀹氫綅
+- 鏂板 uni-badge 鐨� offset 灞炴�э紝鏀寔瀹氫綅鍋忕Щ
+- 鏂板 uni-badge 鐨� is-dot 灞炴�э紝鏀寔浠呮樉绀烘湁涓�涓皬鐐�
+- 鏂板 uni-badge 鐨� max-num 灞炴�э紝鏀寔鑷畾涔夊皝椤剁殑鏁板瓧鍊硷紝瓒呰繃 99 鏄剧ず99+
+- 浼樺寲 uni-badge 灞炴�� custom-style锛� 鏀寔浠ュ璞″舰寮忚嚜瀹氫箟鏍峰紡
+## 1.0.7锛�2021-05-07锛�
+- 淇 uni-badge 鍦� App 绔紝鏁板瓧灏忎簬10鏃朵笉鏄渾褰㈢殑bug
+- 淇 uni-badge 鍦ㄧ埗鍏冪礌涓嶆槸 flex 甯冨眬鏃讹紝瀹藉害缂╁皬鐨刡ug
+- 鏂板 uni-badge 灞炴�� custom-style锛� 鏀寔鑷畾涔夋牱寮�
+## 1.0.6锛�2021-02-04锛�
+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
diff --git a/app/uni_modules/uni-badge/components/uni-badge/uni-badge.vue b/app/uni_modules/uni-badge/components/uni-badge/uni-badge.vue
new file mode 100644
index 0000000..956354b
--- /dev/null
+++ b/app/uni_modules/uni-badge/components/uni-badge/uni-badge.vue
@@ -0,0 +1,268 @@
+<template>
+ <view class="uni-badge--x">
+ <slot />
+ <text v-if="text" :class="classNames" :style="[positionStyle, customStyle, dotStyle]"
+ class="uni-badge" @click="onClick()">{{displayValue}}</text>
+ </view>
+</template>
+
+<script>
+ /**
+ * Badge 鏁板瓧瑙掓爣
+ * @description 鏁板瓧瑙掓爣涓�鑸拰鍏跺畠鎺т欢锛堝垪琛ㄣ��9瀹牸绛夛級閰嶅悎浣跨敤锛岀敤浜庤繘琛屾暟閲忔彁绀猴紝榛樿涓哄疄蹇冪伆鑹茶儗鏅�
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=21
+ * @property {String} text 瑙掓爣鍐呭
+ * @property {String} size = [normal|small] 瑙掓爣鍐呭
+ * @property {String} type = [info|primary|success|warning|error] 棰滆壊绫诲瀷
+ * @value info 鐏拌壊
+ * @value primary 钃濊壊
+ * @value success 缁胯壊
+ * @value warning 榛勮壊
+ * @value error 绾㈣壊
+ * @property {String} inverted = [true|false] 鏄惁鏃犻渶鑳屾櫙棰滆壊
+ * @property {Number} maxNum 灞曠ず灏侀《鐨勬暟瀛楀�硷紝瓒呰繃 99 鏄剧ず 99+
+ * @property {String} absolute = [rightTop|rightBottom|leftBottom|leftTop] 寮�鍚粷瀵瑰畾浣�, 瑙掓爣灏嗗畾浣嶅埌鍏跺寘瑁圭殑鏍囩鐨勫洓瑙掍笂
+ * @value rightTop 鍙充笂
+ * @value rightBottom 鍙充笅
+ * @value leftTop 宸︿笂
+ * @value leftBottom 宸︿笅
+ * @property {Array[number]} offset 璺濆畾浣嶈涓績鐐圭殑鍋忕Щ閲忥紝鍙湁瀛樺湪 absolute 灞炴�ф椂鏈夋晥锛屼緥濡傦細[-10, -10] 琛ㄧず鍚戝鍋忕Щ 10px锛孾10, 10] 琛ㄧず鍚� absolute 鎸囧畾鐨勫唴鍋忕Щ 10px
+ * @property {String} isDot = [true|false] 鏄惁鏄剧ず涓轰竴涓皬鐐�
+ * @event {Function} click 鐐瑰嚮 Badge 瑙﹀彂浜嬩欢
+ * @example <uni-badge text="1"></uni-badge>
+ */
+
+ export default {
+ name: 'UniBadge',
+ emits: ['click'],
+ props: {
+ type: {
+ type: String,
+ default: 'error'
+ },
+ inverted: {
+ type: Boolean,
+ default: false
+ },
+ isDot: {
+ type: Boolean,
+ default: false
+ },
+ maxNum: {
+ type: Number,
+ default: 99
+ },
+ absolute: {
+ type: String,
+ default: ''
+ },
+ offset: {
+ type: Array,
+ default () {
+ return [0, 0]
+ }
+ },
+ text: {
+ type: [String, Number],
+ default: ''
+ },
+ size: {
+ type: String,
+ default: 'small'
+ },
+ customStyle: {
+ type: Object,
+ default () {
+ return {}
+ }
+ }
+ },
+ data() {
+ return {};
+ },
+ computed: {
+ width() {
+ return String(this.text).length * 8 + 12
+ },
+ classNames() {
+ const {
+ inverted,
+ type,
+ size,
+ absolute
+ } = this
+ return [
+ inverted ? 'uni-badge--' + type + '-inverted' : '',
+ 'uni-badge--' + type,
+ 'uni-badge--' + size,
+ absolute ? 'uni-badge--absolute' : ''
+ ].join(' ')
+ },
+ positionStyle() {
+ if (!this.absolute) return {}
+ let w = this.width / 2,
+ h = 10
+ if (this.isDot) {
+ w = 5
+ h = 5
+ }
+ const x = `${- w + this.offset[0]}px`
+ const y = `${- h + this.offset[1]}px`
+
+ const whiteList = {
+ rightTop: {
+ right: x,
+ top: y
+ },
+ rightBottom: {
+ right: x,
+ bottom: y
+ },
+ leftBottom: {
+ left: x,
+ bottom: y
+ },
+ leftTop: {
+ left: x,
+ top: y
+ }
+ }
+ const match = whiteList[this.absolute]
+ return match ? match : whiteList['rightTop']
+ },
+ dotStyle() {
+ if (!this.isDot) return {}
+ return {
+ width: '10px',
+ minWidth: '0',
+ height: '10px',
+ padding: '0',
+ borderRadius: '10px'
+ }
+ },
+ displayValue() {
+ const {
+ isDot,
+ text,
+ maxNum
+ } = this
+ return isDot ? '' : (Number(text) > maxNum ? `${maxNum}+` : text)
+ }
+ },
+ methods: {
+ onClick() {
+ this.$emit('click');
+ }
+ }
+ };
+</script>
+
+<style lang="scss" >
+ $uni-primary: #2979ff !default;
+ $uni-success: #4cd964 !default;
+ $uni-warning: #f0ad4e !default;
+ $uni-error: #dd524d !default;
+ $uni-info: #909399 !default;
+
+
+ $bage-size: 12px;
+ $bage-small: scale(0.8);
+
+ .uni-badge--x {
+ /* #ifdef APP-NVUE */
+ // align-self: flex-start;
+ /* #endif */
+ /* #ifndef APP-NVUE */
+ display: inline-block;
+ /* #endif */
+ position: relative;
+ }
+
+ .uni-badge--absolute {
+ position: absolute;
+ }
+
+ .uni-badge--small {
+ transform: $bage-small;
+ transform-origin: center center;
+ }
+
+ .uni-badge {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ overflow: hidden;
+ box-sizing: border-box;
+ font-feature-settings: "tnum";
+ min-width: 20px;
+ /* #endif */
+ justify-content: center;
+ flex-direction: row;
+ height: 20px;
+ padding: 0 4px;
+ line-height: 18px;
+ color: #fff;
+ border-radius: 100px;
+ background-color: $uni-info;
+ background-color: transparent;
+ border: 1px solid #fff;
+ text-align: center;
+ font-family: 'Helvetica Neue', Helvetica, sans-serif;
+ font-size: $bage-size;
+ /* #ifdef H5 */
+ z-index: 999;
+ cursor: pointer;
+ /* #endif */
+
+ &--info {
+ color: #fff;
+ background-color: $uni-info;
+ }
+
+ &--primary {
+ background-color: $uni-primary;
+ }
+
+ &--success {
+ background-color: $uni-success;
+ }
+
+ &--warning {
+ background-color: $uni-warning;
+ }
+
+ &--error {
+ background-color: $uni-error;
+ }
+
+ &--inverted {
+ padding: 0 5px 0 0;
+ color: $uni-info;
+ }
+
+ &--info-inverted {
+ color: $uni-info;
+ background-color: transparent;
+ }
+
+ &--primary-inverted {
+ color: $uni-primary;
+ background-color: transparent;
+ }
+
+ &--success-inverted {
+ color: $uni-success;
+ background-color: transparent;
+ }
+
+ &--warning-inverted {
+ color: $uni-warning;
+ background-color: transparent;
+ }
+
+ &--error-inverted {
+ color: $uni-error;
+ background-color: transparent;
+ }
+
+ }
+</style>
diff --git a/app/uni_modules/uni-badge/package.json b/app/uni_modules/uni-badge/package.json
new file mode 100644
index 0000000..b0bac93
--- /dev/null
+++ b/app/uni_modules/uni-badge/package.json
@@ -0,0 +1,85 @@
+{
+ "id": "uni-badge",
+ "displayName": "uni-badge 鏁板瓧瑙掓爣",
+ "version": "1.2.2",
+ "description": "鏁板瓧瑙掓爣锛堝窘绔狅級缁勪欢锛屽湪鍏冪礌鍛ㄥ洿灞曠ず娑堟伅鎻愰啋锛屼竴鑸敤浜庡垪琛ㄣ�佷節瀹牸銆佹寜閽瓑鍦版柟銆�",
+ "keywords": [
+ "",
+ "badge",
+ "uni-ui",
+ "uniui",
+ "鏁板瓧瑙掓爣",
+ "寰界珷"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+"dcloudext": {
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+ "type": "component-vue"
+ },
+ "uni_modules": {
+ "dependencies": ["uni-scss"],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "y",
+ "鑱旂洘": "y"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/uni_modules/uni-badge/readme.md b/app/uni_modules/uni-badge/readme.md
new file mode 100644
index 0000000..bdf175d
--- /dev/null
+++ b/app/uni_modules/uni-badge/readme.md
@@ -0,0 +1,10 @@
+## Badge 鏁板瓧瑙掓爣
+> **缁勪欢鍚嶏細uni-badge**
+> 浠g爜鍧楋細 `uBadge`
+
+鏁板瓧瑙掓爣涓�鑸拰鍏跺畠鎺т欢锛堝垪琛ㄣ��9瀹牸绛夛級閰嶅悎浣跨敤锛岀敤浜庤繘琛屾暟閲忔彁绀猴紝榛樿涓哄疄蹇冪伆鑹茶儗鏅紝
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-badge)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
+
+
diff --git a/app/uni_modules/uni-breadcrumb/changelog.md b/app/uni_modules/uni-breadcrumb/changelog.md
new file mode 100644
index 0000000..209e5c5
--- /dev/null
+++ b/app/uni_modules/uni-breadcrumb/changelog.md
@@ -0,0 +1,6 @@
+## 0.1.2锛�2022-06-08锛�
+- 淇 寰俊灏忕▼搴� separator 涓嶆樉绀虹殑Bug
+## 0.1.1锛�2022-06-02锛�
+- 鏂板 鏀寔 uni.scss 淇敼棰滆壊
+## 0.1.0锛�2022-04-21锛�
+- 鍒濆鍖�
diff --git a/app/uni_modules/uni-breadcrumb/components/uni-breadcrumb-item/uni-breadcrumb-item.vue b/app/uni_modules/uni-breadcrumb/components/uni-breadcrumb-item/uni-breadcrumb-item.vue
new file mode 100644
index 0000000..b9edbd6
--- /dev/null
+++ b/app/uni_modules/uni-breadcrumb/components/uni-breadcrumb-item/uni-breadcrumb-item.vue
@@ -0,0 +1,121 @@
+<template>
+ <view class="uni-breadcrumb-item">
+ <view :class="{
+ 'uni-breadcrumb-item--slot': true,
+ 'uni-breadcrumb-item--slot-link': to && currentPage !== to
+ }" @click="navTo">
+ <slot />
+ </view>
+ <i v-if="separatorClass" class="uni-breadcrumb-item--separator" :class="separatorClass" />
+ <text v-else class="uni-breadcrumb-item--separator">{{ separator }}</text>
+ </view>
+</template>
+<script>
+ /**
+ * BreadcrumbItem 闈㈠寘灞戝鑸瓙缁勪欢
+ * @property {String/Object} to 璺敱璺宠浆椤甸潰璺緞/瀵硅薄
+ * @property {Boolean} replace 鍦ㄤ娇鐢� to 杩涜璺敱璺宠浆鏃讹紝鍚敤 replace 灏嗕笉浼氬悜 history 娣诲姞鏂拌褰�(浠� h5 鏀寔锛�
+ */
+ export default {
+ data() {
+ return {
+ currentPage: ""
+ }
+ },
+ options: {
+ virtualHost: true
+ },
+ props: {
+ to: {
+ type: String,
+ default: ''
+ },
+ replace:{
+ type: Boolean,
+ default: false
+ }
+ },
+ inject: {
+ uniBreadcrumb: {
+ from: "uniBreadcrumb",
+ default: null
+ }
+ },
+ created(){
+ const pages = getCurrentPages()
+ const page = pages[pages.length-1]
+
+ if(page){
+ this.currentPage = `/${page.route}`
+ }
+ },
+ computed: {
+ separator() {
+ return this.uniBreadcrumb.separator
+ },
+ separatorClass() {
+ return this.uniBreadcrumb.separatorClass
+ }
+ },
+ methods: {
+ navTo() {
+ const { to } = this
+
+ if (!to || this.currentPage === to){
+ return
+ }
+
+ if(this.replace){
+ uni.redirectTo({
+ url:to
+ })
+ }else{
+ uni.navigateTo({
+ url:to
+ })
+ }
+ }
+ }
+ }
+</script>
+<style lang="scss">
+ $uni-primary: #2979ff !default;
+ $uni-base-color: #6a6a6a !default;
+ $uni-main-color: #3a3a3a !default;
+ .uni-breadcrumb-item {
+ display: flex;
+ align-items: center;
+ white-space: nowrap;
+ font-size: 14px;
+
+ &--slot {
+ color: $uni-base-color;
+ padding: 0 10px;
+
+ &-link {
+ color: $uni-main-color;
+ font-weight: bold;
+ /* #ifndef APP-NVUE */
+ cursor: pointer;
+ /* #endif */
+
+ &:hover {
+ color: $uni-primary;
+ }
+ }
+ }
+
+ &--separator {
+ font-size: 12px;
+ color: $uni-base-color;
+ }
+
+ &:first-child &--slot {
+ padding-left: 0;
+ }
+
+ &:last-child &--separator {
+ display: none;
+ }
+ }
+</style>
diff --git a/app/uni_modules/uni-breadcrumb/components/uni-breadcrumb/uni-breadcrumb.vue b/app/uni_modules/uni-breadcrumb/components/uni-breadcrumb/uni-breadcrumb.vue
new file mode 100644
index 0000000..94493a2
--- /dev/null
+++ b/app/uni_modules/uni-breadcrumb/components/uni-breadcrumb/uni-breadcrumb.vue
@@ -0,0 +1,41 @@
+<template>
+ <view class="uni-breadcrumb">
+ <slot />
+ </view>
+</template>
+<script>
+ /**
+ * Breadcrumb 闈㈠寘灞戝鑸埗缁勪欢
+ * @description 鏄剧ず褰撳墠椤甸潰鐨勮矾寰勶紝蹇�熻繑鍥炰箣鍓嶇殑浠绘剰椤甸潰
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=xxx
+ * @property {String} separator 鍒嗛殧绗︼紝榛樿涓烘枩鏉�'/'
+ * @property {String} separatorClass 鍥炬爣鍒嗛殧绗� class
+ */
+ export default {
+ options: {
+ virtualHost: true
+ },
+ props: {
+ separator: {
+ type: String,
+ default: '/'
+ },
+ separatorClass: {
+ type: String,
+ default: ''
+ }
+ },
+
+ provide() {
+ return {
+ uniBreadcrumb: this
+ }
+ }
+
+ }
+</script>
+<style lang="scss">
+ .uni-breadcrumb {
+ display: flex;
+ }
+</style>
diff --git a/app/uni_modules/uni-breadcrumb/package.json b/app/uni_modules/uni-breadcrumb/package.json
new file mode 100644
index 0000000..0a04e50
--- /dev/null
+++ b/app/uni_modules/uni-breadcrumb/package.json
@@ -0,0 +1,88 @@
+{
+ "id": "uni-breadcrumb",
+ "displayName": "uni-breadcrumb 闈㈠寘灞�",
+ "version": "0.1.2",
+ "description": "Breadcrumb 闈㈠寘灞�",
+ "keywords": [
+ "uni-breadcrumb",
+ "breadcrumb",
+ "uni-ui",
+ "闈㈠寘灞戝鑸�",
+ "闈㈠寘灞�"
+],
+ "repository": "",
+ "engines": {
+ "HBuilderX": "^3.1.0"
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "鍓嶇缁勪欢",
+ "閫氱敤缁勪欢"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": ""
+ },
+ "uni_modules": {
+ "dependencies": [],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ },
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "n"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "u",
+ "鐧惧害": "u",
+ "瀛楄妭璺冲姩": "u",
+ "QQ": "u",
+ "浜笢": "u"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "u",
+ "鑱旂洘": "u"
+ }
+ }
+ }
+ }
+}
diff --git a/app/uni_modules/uni-breadcrumb/readme.md b/app/uni_modules/uni-breadcrumb/readme.md
new file mode 100644
index 0000000..6976b8d
--- /dev/null
+++ b/app/uni_modules/uni-breadcrumb/readme.md
@@ -0,0 +1,66 @@
+
+## breadcrumb 闈㈠寘灞戝鑸�
+> **缁勪欢鍚嶏細uni-breadcrumb**
+> 浠g爜鍧楋細 `ubreadcrumb`
+
+鏄剧ず褰撳墠椤甸潰鐨勮矾寰勶紝蹇�熻繑鍥炰箣鍓嶇殑浠绘剰椤甸潰銆�
+
+### 瀹夎鏂瑰紡
+
+鏈粍浠剁鍚圼easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)瑙勮寖锛宍HBuilderX 2.5.5`璧凤紝鍙渶灏嗘湰缁勪欢瀵煎叆椤圭洰锛屽湪椤甸潰`template`涓嵆鍙洿鎺ヤ娇鐢紝鏃犻渶鍦ㄩ〉闈腑`import`鍜屾敞鍐宍components`銆�
+
+濡傞渶閫氳繃`npm`鏂瑰紡浣跨敤`uni-ui`缁勪欢锛屽彟瑙佹枃妗o細[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55)
+
+### 鍩烘湰鐢ㄦ硶
+
+鍦� ``template`` 涓娇鐢ㄧ粍浠�
+
+```html
+<uni-breadcrumb separator="/">
+ <uni-breadcrumb-item v-for="(route,index) in routes" :key="index" :to="route.to">{{route.name}}</uni-breadcrumb-item>
+</uni-breadcrumb>
+```
+
+```js
+export default {
+ name: "uni-stat-breadcrumb",
+ data() {
+ return {
+ routes: [{
+ to: '/A',
+ name: 'A椤甸潰'
+ }, {
+ to: '/B',
+ name: 'B椤甸潰'
+ }, {
+ to: '/C',
+ name: 'C椤甸潰'
+ }]
+ };
+ }
+ }
+```
+
+
+## API
+
+### Breadcrumb Props
+
+|灞炴�у悕 |绫诲瀷 |榛樿鍊� |璇存槑 |
+|:-: |:-: |:-: |:-: |
+|separator |String |鏂滄潬'/' |鍒嗛殧绗� |
+|separatorClass |String | |鍥炬爣鍒嗛殧绗� class |
+
+### Breadcrumb Item Props
+
+|灞炴�у悕 |绫诲瀷 |榛樿鍊� |璇存槑 |
+|:-: |:-: |:-: |:-: |
+|to |String | |璺敱璺宠浆椤甸潰璺緞 |
+|replace|Boolean | |鍦ㄤ娇鐢� to 杩涜璺敱璺宠浆鏃讹紝鍚敤 replace 灏嗕笉浼氬悜 history 娣诲姞鏂拌褰�(浠� h5 鏀寔锛� |
+
+
+
+
+## 缁勪欢绀轰緥
+
+鐐瑰嚮鏌ョ湅锛歔https://hellouniapp.dcloud.net.cn/pages/extUI/breadcrumb/breadcrumb](https://hellouniapp.dcloud.net.cn/pages/extUI/breadcrumb/breadcrumb)
\ No newline at end of file
diff --git a/app/uni_modules/uni-calendar/changelog.md b/app/uni_modules/uni-calendar/changelog.md
new file mode 100644
index 0000000..f291eec
--- /dev/null
+++ b/app/uni_modules/uni-calendar/changelog.md
@@ -0,0 +1,26 @@
+## 1.4.10锛�2023-04-10锛�
+- 淇 鏌愪簺鎯呭喌 monthSwitch 鏈Е鍙戠殑Bug
+## 1.4.9锛�2023-02-02锛�
+- 淇 鏌愪簺鎯呭喌鍒囨崲鏈堜唤閿欒鐨凚ug
+## 1.4.8锛�2023-01-30锛�
+- 淇 鏌愪簺鎯呭喌鍒囨崲鏈堜唤閿欒鐨凚ug [璇︽儏](https://ask.dcloud.net.cn/question/161964)
+## 1.4.7锛�2022-09-16锛�
+- 浼樺寲 鏀寔浣跨敤 uni-scss 鎺у埗涓婚鑹�
+## 1.4.6锛�2022-09-08锛�
+- 淇 琛ㄥご骞存湀鍒囨崲锛屽鑷存敼鍙樺綋鍓嶆棩鏈熶负閫夋嫨鏈�1鍙凤紝涓旀湭瑙﹀彂change浜嬩欢鐨凚ug
+## 1.4.5锛�2022-02-25锛�
+- 淇 鏉′欢缂栬瘧 nvue 涓嶆敮鎸佺殑 css 鏍峰紡鐨凚ug
+## 1.4.4锛�2022-02-25锛�
+- 淇 鏉′欢缂栬瘧 nvue 涓嶆敮鎸佺殑 css 鏍峰紡鐨凚ug
+## 1.4.3锛�2021-09-22锛�
+- 淇 startDate銆� endDate 灞炴�уけ鏁堢殑Bug
+## 1.4.2锛�2021-08-24锛�
+- 鏂板 鏀寔鍥介檯鍖�
+## 1.4.1锛�2021-08-05锛�
+- 淇 寮瑰嚭灞傝 tabbar 閬洊鐨凚ug
+## 1.4.0锛�2021-07-30锛�
+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤簐ue3椤圭洰锛岃瑙� [uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+## 1.3.16锛�2021-05-12锛�
+- 鏂板 缁勪欢绀轰緥鍦板潃
+## 1.3.15锛�2021-02-04锛�
+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
diff --git a/app/uni_modules/uni-calendar/components/uni-calendar/calendar.js b/app/uni_modules/uni-calendar/components/uni-calendar/calendar.js
new file mode 100644
index 0000000..b8d7d6f
--- /dev/null
+++ b/app/uni_modules/uni-calendar/components/uni-calendar/calendar.js
@@ -0,0 +1,546 @@
+/**
+* @1900-2100鍖洪棿鍐呯殑鍏巻銆佸啘鍘嗕簰杞�
+* @charset UTF-8
+* @github https://github.com/jjonline/calendar.js
+* @Author Jea鏉�(JJonline@JJonline.Cn)
+* @Time 2014-7-21
+* @Time 2016-8-13 Fixed 2033hex銆丄ttribution Annals
+* @Time 2016-9-25 Fixed lunar LeapMonth Param Bug
+* @Time 2017-7-24 Fixed use getTerm Func Param Error.use solar year,NOT lunar year
+* @Version 1.0.3
+* @鍏巻杞啘鍘嗭細calendar.solar2lunar(1987,11,01); //[you can ignore params of prefix 0]
+* @鍐滃巻杞叕鍘嗭細calendar.lunar2solar(1987,09,10); //[you can ignore params of prefix 0]
+*/
+/* eslint-disable */
+var calendar = {
+
+ /**
+ * 鍐滃巻1900-2100鐨勬鼎澶у皬淇℃伅琛�
+ * @Array Of Property
+ * @return Hex
+ */
+ lunarInfo: [0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, // 1900-1909
+ 0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977, // 1910-1919
+ 0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, // 1920-1929
+ 0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950, // 1930-1939
+ 0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, // 1940-1949
+ 0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5b0, 0x14573, 0x052b0, 0x0a9a8, 0x0e950, 0x06aa0, // 1950-1959
+ 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, // 1960-1969
+ 0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b6a0, 0x195a6, // 1970-1979
+ 0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570, // 1980-1989
+ 0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x05ac0, 0x0ab60, 0x096d5, 0x092e0, // 1990-1999
+ 0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5, // 2000-2009
+ 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, // 2010-2019
+ 0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530, // 2020-2029
+ 0x05aa0, 0x076a3, 0x096d0, 0x04afb, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, // 2030-2039
+ 0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0, // 2040-2049
+ /** Add By JJonline@JJonline.Cn**/
+ 0x14b63, 0x09370, 0x049f8, 0x04970, 0x064b0, 0x168a6, 0x0ea50, 0x06b20, 0x1a6c4, 0x0aae0, // 2050-2059
+ 0x0a2e0, 0x0d2e3, 0x0c960, 0x0d557, 0x0d4a0, 0x0da50, 0x05d55, 0x056a0, 0x0a6d0, 0x055d4, // 2060-2069
+ 0x052d0, 0x0a9b8, 0x0a950, 0x0b4a0, 0x0b6a6, 0x0ad50, 0x055a0, 0x0aba4, 0x0a5b0, 0x052b0, // 2070-2079
+ 0x0b273, 0x06930, 0x07337, 0x06aa0, 0x0ad50, 0x14b55, 0x04b60, 0x0a570, 0x054e4, 0x0d160, // 2080-2089
+ 0x0e968, 0x0d520, 0x0daa0, 0x16aa6, 0x056d0, 0x04ae0, 0x0a9d4, 0x0a2d0, 0x0d150, 0x0f252, // 2090-2099
+ 0x0d520], // 2100
+
+ /**
+ * 鍏巻姣忎釜鏈堜唤鐨勫ぉ鏁版櫘閫氳〃
+ * @Array Of Property
+ * @return Number
+ */
+ solarMonth: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
+
+ /**
+ * 澶╁共鍦版敮涔嬪ぉ骞查�熸煡琛�
+ * @Array Of Property trans["鐢�","涔�","涓�","涓�","鎴�","宸�","搴�","杈�","澹�","鐧�"]
+ * @return Cn string
+ */
+ Gan: ['\u7532', '\u4e59', '\u4e19', '\u4e01', '\u620a', '\u5df1', '\u5e9a', '\u8f9b', '\u58ec', '\u7678'],
+
+ /**
+ * 澶╁共鍦版敮涔嬪湴鏀�熸煡琛�
+ * @Array Of Property
+ * @trans["瀛�","涓�","瀵�","鍗�","杈�","宸�","鍗�","鏈�","鐢�","閰�","鎴�","浜�"]
+ * @return Cn string
+ */
+ Zhi: ['\u5b50', '\u4e11', '\u5bc5', '\u536f', '\u8fb0', '\u5df3', '\u5348', '\u672a', '\u7533', '\u9149', '\u620c', '\u4ea5'],
+
+ /**
+ * 澶╁共鍦版敮涔嬪湴鏀�熸煡琛�<=>鐢熻倴
+ * @Array Of Property
+ * @trans["榧�","鐗�","铏�","鍏�","榫�","铔�","椹�","缇�","鐚�","楦�","鐙�","鐚�"]
+ * @return Cn string
+ */
+ Animals: ['\u9f20', '\u725b', '\u864e', '\u5154', '\u9f99', '\u86c7', '\u9a6c', '\u7f8a', '\u7334', '\u9e21', '\u72d7', '\u732a'],
+
+ /**
+ * 24鑺傛皵閫熸煡琛�
+ * @Array Of Property
+ * @trans["灏忓瘨","澶у瘨","绔嬫槬","闆ㄦ按","鎯婅洶","鏄ュ垎","娓呮槑","璋烽洦","绔嬪","灏忔弧","鑺掔","澶忚嚦","灏忔殤","澶ф殤","绔嬬","澶勬殤","鐧介湶","绉嬪垎","瀵掗湶","闇滈檷","绔嬪啲","灏忛洩","澶ч洩","鍐嚦"]
+ * @return Cn string
+ */
+ solarTerm: ['\u5c0f\u5bd2', '\u5927\u5bd2', '\u7acb\u6625', '\u96e8\u6c34', '\u60ca\u86f0', '\u6625\u5206', '\u6e05\u660e', '\u8c37\u96e8', '\u7acb\u590f', '\u5c0f\u6ee1', '\u8292\u79cd', '\u590f\u81f3', '\u5c0f\u6691', '\u5927\u6691', '\u7acb\u79cb', '\u5904\u6691', '\u767d\u9732', '\u79cb\u5206', '\u5bd2\u9732', '\u971c\u964d', '\u7acb\u51ac', '\u5c0f\u96ea', '\u5927\u96ea', '\u51ac\u81f3'],
+
+ /**
+ * 1900-2100鍚勫勾鐨�24鑺傛皵鏃ユ湡閫熸煡琛�
+ * @Array Of Property
+ * @return 0x string For splice
+ */
+ sTermInfo: ['9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf97c3598082c95f8c965cc920f',
+ '97bd0b06bdb0722c965ce1cfcc920f', 'b027097bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
+ '97bcf97c359801ec95f8c965cc920f', '97bd0b06bdb0722c965ce1cfcc920f', 'b027097bd097c36b0b6fc9274c91aa',
+ '97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f', '97bd0b06bdb0722c965ce1cfcc920f',
+ 'b027097bd097c36b0b6fc9274c91aa', '9778397bd19801ec9210c965cc920e', '97b6b97bd19801ec95f8c965cc920f',
+ '97bd09801d98082c95f8e1cfcc920f', '97bd097bd097c36b0b6fc9210c8dc2', '9778397bd197c36c9210c9274c91aa',
+ '97b6b97bd19801ec95f8c965cc920e', '97bd09801d98082c95f8e1cfcc920f', '97bd097bd097c36b0b6fc9210c8dc2',
+ '9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec95f8c965cc920e', '97bcf97c3598082c95f8e1cfcc920f',
+ '97bd097bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec9210c965cc920e',
+ '97bcf97c3598082c95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
+ '97b6b97bd19801ec9210c965cc920e', '97bcf97c3598082c95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722',
+ '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f',
+ '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
+ '97bcf97c359801ec95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
+ '97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f', '97bd097bd07f595b0b6fc920fb0722',
+ '9778397bd097c36b0b6fc9210c8dc2', '9778397bd19801ec9210c9274c920e', '97b6b97bd19801ec95f8c965cc920f',
+ '97bd07f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c920e',
+ '97b6b97bd19801ec95f8c965cc920f', '97bd07f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2',
+ '9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bd07f1487f595b0b0bc920fb0722',
+ '7f0e397bd097c36b0b6fc9210c8dc2', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
+ '97bcf7f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
+ '97b6b97bd19801ec9210c965cc920e', '97bcf7f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722',
+ '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf7f1487f531b0b0bb0b6fb0722',
+ '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
+ '97bcf7f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
+ '97b6b97bd19801ec9210c9274c920e', '97bcf7f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722',
+ '9778397bd097c36b0b6fc9210c91aa', '97b6b97bd197c36c9210c9274c920e', '97bcf7f0e47f531b0b0bb0b6fb0722',
+ '7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c920e',
+ '97b6b7f0e47f531b0723b0b6fb0722', '7f0e37f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2',
+ '9778397bd097c36b0b70c9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', '7f0e37f1487f595b0b0bb0b6fb0722',
+ '7f0e397bd097c35b0b6fc9210c8dc2', '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721',
+ '7f0e27f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
+ '97b6b7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722',
+ '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722',
+ '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721',
+ '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
+ '97b6b7f0e47f531b0723b0787b0721', '7f0e27f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722',
+ '9778397bd097c36b0b6fc9210c91aa', '97b6b7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722',
+ '7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9210c8dc2', '977837f0e37f149b0723b0787b0721',
+ '7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f5307f595b0b0bc920fb0722', '7f0e397bd097c35b0b6fc9210c8dc2',
+ '977837f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e37f1487f595b0b0bb0b6fb0722',
+ '7f0e397bd097c35b0b6fc9210c8dc2', '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
+ '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '977837f0e37f14998082b0787b06bd',
+ '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722',
+ '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722',
+ '7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
+ '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14998082b0787b06bd',
+ '7f07e7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722',
+ '977837f0e37f14998082b0723b06bd', '7f07e7f0e37f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722',
+ '7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b0721',
+ '7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f1487f595b0b0bb0b6fb0722', '7f0e37f0e37f14898082b0723b02d5',
+ '7ec967f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f1487f531b0b0bb0b6fb0722',
+ '7f0e37f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
+ '7f0e37f1487f531b0b0bb0b6fb0722', '7f0e37f0e37f14898082b072297c35', '7ec967f0e37f14998082b0787b06bd',
+ '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e37f0e37f14898082b072297c35',
+ '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722',
+ '7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f149b0723b0787b0721',
+ '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14998082b0723b06bd',
+ '7f07e7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722', '7f0e37f0e366aa89801eb072297c35',
+ '7ec967f0e37f14998082b0723b06bd', '7f07e7f0e37f14998083b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722',
+ '7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14898082b0723b02d5', '7f07e7f0e37f14998082b0787b0721',
+ '7f07e7f0e47f531b0723b0b6fb0722', '7f0e36665b66aa89801e9808297c35', '665f67f0e37f14898082b0723b02d5',
+ '7ec967f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0722', '7f0e36665b66a449801e9808297c35',
+ '665f67f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
+ '7f0e36665b66a449801e9808297c35', '665f67f0e37f14898082b072297c35', '7ec967f0e37f14998082b0787b06bd',
+ '7f07e7f0e47f531b0723b0b6fb0721', '7f0e26665b66a449801e9808297c35', '665f67f0e37f1489801eb072297c35',
+ '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722'],
+
+ /**
+ * 鏁板瓧杞腑鏂囬�熸煡琛�
+ * @Array Of Property
+ * @trans ['鏃�','涓�','浜�','涓�','鍥�','浜�','鍏�','涓�','鍏�','涔�','鍗�']
+ * @return Cn string
+ */
+ nStr1: ['\u65e5', '\u4e00', '\u4e8c', '\u4e09', '\u56db', '\u4e94', '\u516d', '\u4e03', '\u516b', '\u4e5d', '\u5341'],
+
+ /**
+ * 鏃ユ湡杞啘鍘嗙О鍛奸�熸煡琛�
+ * @Array Of Property
+ * @trans ['鍒�','鍗�','寤�','鍗�']
+ * @return Cn string
+ */
+ nStr2: ['\u521d', '\u5341', '\u5eff', '\u5345'],
+
+ /**
+ * 鏈堜唤杞啘鍘嗙О鍛奸�熸煡琛�
+ * @Array Of Property
+ * @trans ['姝�','涓�','浜�','涓�','鍥�','浜�','鍏�','涓�','鍏�','涔�','鍗�','鍐�','鑵�']
+ * @return Cn string
+ */
+ nStr3: ['\u6b63', '\u4e8c', '\u4e09', '\u56db', '\u4e94', '\u516d', '\u4e03', '\u516b', '\u4e5d', '\u5341', '\u51ac', '\u814a'],
+
+ /**
+ * 杩斿洖鍐滃巻y骞翠竴鏁村勾鐨勬�诲ぉ鏁�
+ * @param lunar Year
+ * @return Number
+ * @eg:var count = calendar.lYearDays(1987) ;//count=387
+ */
+ lYearDays: function (y) {
+ var i; var sum = 348
+ for (i = 0x8000; i > 0x8; i >>= 1) { sum += (this.lunarInfo[y - 1900] & i) ? 1 : 0 }
+ return (sum + this.leapDays(y))
+ },
+
+ /**
+ * 杩斿洖鍐滃巻y骞撮棸鏈堟槸鍝釜鏈堬紱鑻骞存病鏈夐棸鏈� 鍒欒繑鍥�0
+ * @param lunar Year
+ * @return Number (0-12)
+ * @eg:var leapMonth = calendar.leapMonth(1987) ;//leapMonth=6
+ */
+ leapMonth: function (y) { // 闂板瓧缂栫爜 \u95f0
+ return (this.lunarInfo[y - 1900] & 0xf)
+ },
+
+ /**
+ * 杩斿洖鍐滃巻y骞撮棸鏈堢殑澶╂暟 鑻ヨ骞存病鏈夐棸鏈堝垯杩斿洖0
+ * @param lunar Year
+ * @return Number (0銆�29銆�30)
+ * @eg:var leapMonthDay = calendar.leapDays(1987) ;//leapMonthDay=29
+ */
+ leapDays: function (y) {
+ if (this.leapMonth(y)) {
+ return ((this.lunarInfo[y - 1900] & 0x10000) ? 30 : 29)
+ }
+ return (0)
+ },
+
+ /**
+ * 杩斿洖鍐滃巻y骞磎鏈堬紙闈為棸鏈堬級鐨勬�诲ぉ鏁帮紝璁$畻m涓洪棸鏈堟椂鐨勫ぉ鏁拌浣跨敤leapDays鏂规硶
+ * @param lunar Year
+ * @return Number (-1銆�29銆�30)
+ * @eg:var MonthDay = calendar.monthDays(1987,9) ;//MonthDay=29
+ */
+ monthDays: function (y, m) {
+ if (m > 12 || m < 1) { return -1 }// 鏈堜唤鍙傛暟浠�1鑷�12锛屽弬鏁伴敊璇繑鍥�-1
+ return ((this.lunarInfo[y - 1900] & (0x10000 >> m)) ? 30 : 29)
+ },
+
+ /**
+ * 杩斿洖鍏巻(!)y骞磎鏈堢殑澶╂暟
+ * @param solar Year
+ * @return Number (-1銆�28銆�29銆�30銆�31)
+ * @eg:var solarMonthDay = calendar.leapDays(1987) ;//solarMonthDay=30
+ */
+ solarDays: function (y, m) {
+ if (m > 12 || m < 1) { return -1 } // 鑻ュ弬鏁伴敊璇� 杩斿洖-1
+ var ms = m - 1
+ if (ms == 1) { // 2鏈堜唤鐨勯棸骞宠寰嬫祴绠楀悗纭杩斿洖28鎴�29
+ return (((y % 4 == 0) && (y % 100 != 0) || (y % 400 == 0)) ? 29 : 28)
+ } else {
+ return (this.solarMonth[ms])
+ }
+ },
+
+ /**
+ * 鍐滃巻骞翠唤杞崲涓哄共鏀邯骞�
+ * @param lYear 鍐滃巻骞寸殑骞翠唤鏁�
+ * @return Cn string
+ */
+ toGanZhiYear: function (lYear) {
+ var ganKey = (lYear - 3) % 10
+ var zhiKey = (lYear - 3) % 12
+ if (ganKey == 0) ganKey = 10// 濡傛灉浣欐暟涓�0鍒欎负鏈�鍚庝竴涓ぉ骞�
+ if (zhiKey == 0) zhiKey = 12// 濡傛灉浣欐暟涓�0鍒欎负鏈�鍚庝竴涓湴鏀�
+ return this.Gan[ganKey - 1] + this.Zhi[zhiKey - 1]
+ },
+
+ /**
+ * 鍏巻鏈堛�佹棩鍒ゆ柇鎵�灞炴槦搴�
+ * @param cMonth [description]
+ * @param cDay [description]
+ * @return Cn string
+ */
+ toAstro: function (cMonth, cDay) {
+ var s = '\u9b54\u7faf\u6c34\u74f6\u53cc\u9c7c\u767d\u7f8a\u91d1\u725b\u53cc\u5b50\u5de8\u87f9\u72ee\u5b50\u5904\u5973\u5929\u79e4\u5929\u874e\u5c04\u624b\u9b54\u7faf'
+ var arr = [20, 19, 21, 21, 21, 22, 23, 23, 23, 23, 22, 22]
+ return s.substr(cMonth * 2 - (cDay < arr[cMonth - 1] ? 2 : 0), 2) + '\u5ea7'// 搴�
+ },
+
+ /**
+ * 浼犲叆offset鍋忕Щ閲忚繑鍥炲共鏀�
+ * @param offset 鐩稿鐢插瓙鐨勫亸绉婚噺
+ * @return Cn string
+ */
+ toGanZhi: function (offset) {
+ return this.Gan[offset % 10] + this.Zhi[offset % 12]
+ },
+
+ /**
+ * 浼犲叆鍏巻(!)y骞磋幏寰楄骞寸n涓妭姘旂殑鍏巻鏃ユ湡
+ * @param y鍏巻骞�(1900-2100)锛沶浜屽崄鍥涜妭姘斾腑鐨勭鍑犱釜鑺傛皵(1~24)锛涗粠n=1(灏忓瘨)绠楄捣
+ * @return day Number
+ * @eg:var _24 = calendar.getTerm(1987,3) ;//_24=4;鎰忓嵆1987骞�2鏈�4鏃ョ珛鏄�
+ */
+ getTerm: function (y, n) {
+ if (y < 1900 || y > 2100) { return -1 }
+ if (n < 1 || n > 24) { return -1 }
+ var _table = this.sTermInfo[y - 1900]
+ var _info = [
+ parseInt('0x' + _table.substr(0, 5)).toString(),
+ parseInt('0x' + _table.substr(5, 5)).toString(),
+ parseInt('0x' + _table.substr(10, 5)).toString(),
+ parseInt('0x' + _table.substr(15, 5)).toString(),
+ parseInt('0x' + _table.substr(20, 5)).toString(),
+ parseInt('0x' + _table.substr(25, 5)).toString()
+ ]
+ var _calday = [
+ _info[0].substr(0, 1),
+ _info[0].substr(1, 2),
+ _info[0].substr(3, 1),
+ _info[0].substr(4, 2),
+
+ _info[1].substr(0, 1),
+ _info[1].substr(1, 2),
+ _info[1].substr(3, 1),
+ _info[1].substr(4, 2),
+
+ _info[2].substr(0, 1),
+ _info[2].substr(1, 2),
+ _info[2].substr(3, 1),
+ _info[2].substr(4, 2),
+
+ _info[3].substr(0, 1),
+ _info[3].substr(1, 2),
+ _info[3].substr(3, 1),
+ _info[3].substr(4, 2),
+
+ _info[4].substr(0, 1),
+ _info[4].substr(1, 2),
+ _info[4].substr(3, 1),
+ _info[4].substr(4, 2),
+
+ _info[5].substr(0, 1),
+ _info[5].substr(1, 2),
+ _info[5].substr(3, 1),
+ _info[5].substr(4, 2)
+ ]
+ return parseInt(_calday[n - 1])
+ },
+
+ /**
+ * 浼犲叆鍐滃巻鏁板瓧鏈堜唤杩斿洖姹夎閫氫織琛ㄧず娉�
+ * @param lunar month
+ * @return Cn string
+ * @eg:var cnMonth = calendar.toChinaMonth(12) ;//cnMonth='鑵婃湀'
+ */
+ toChinaMonth: function (m) { // 鏈� => \u6708
+ if (m > 12 || m < 1) { return -1 } // 鑻ュ弬鏁伴敊璇� 杩斿洖-1
+ var s = this.nStr3[m - 1]
+ s += '\u6708'// 鍔犱笂鏈堝瓧
+ return s
+ },
+
+ /**
+ * 浼犲叆鍐滃巻鏃ユ湡鏁板瓧杩斿洖姹夊瓧琛ㄧず娉�
+ * @param lunar day
+ * @return Cn string
+ * @eg:var cnDay = calendar.toChinaDay(21) ;//cnMonth='寤夸竴'
+ */
+ toChinaDay: function (d) { // 鏃� => \u65e5
+ var s
+ switch (d) {
+ case 10:
+ s = '\u521d\u5341'; break
+ case 20:
+ s = '\u4e8c\u5341'; break
+ break
+ case 30:
+ s = '\u4e09\u5341'; break
+ break
+ default :
+ s = this.nStr2[Math.floor(d / 10)]
+ s += this.nStr1[d % 10]
+ }
+ return (s)
+ },
+
+ /**
+ * 骞翠唤杞敓鑲朳!浠呰兘澶ц嚧杞崲] => 绮剧‘鍒掑垎鐢熻倴鍒嗙晫绾挎槸鈥滅珛鏄モ��
+ * @param y year
+ * @return Cn string
+ * @eg:var animal = calendar.getAnimal(1987) ;//animal='鍏�'
+ */
+ getAnimal: function (y) {
+ return this.Animals[(y - 4) % 12]
+ },
+
+ /**
+ * 浼犲叆闃冲巻骞存湀鏃ヨ幏寰楄缁嗙殑鍏巻銆佸啘鍘唎bject淇℃伅 <=>JSON
+ * @param y solar year
+ * @param m solar month
+ * @param d solar day
+ * @return JSON object
+ * @eg:console.log(calendar.solar2lunar(1987,11,01));
+ */
+ solar2lunar: function (y, m, d) { // 鍙傛暟鍖洪棿1900.1.31~2100.12.31
+ // 骞翠唤闄愬畾銆佷笂闄�
+ if (y < 1900 || y > 2100) {
+ return -1// undefined杞崲涓烘暟瀛楀彉涓篘aN
+ }
+ // 鍏巻浼犲弬鏈�涓嬮檺
+ if (y == 1900 && m == 1 && d < 31) {
+ return -1
+ }
+ // 鏈紶鍙� 鑾峰緱褰撳ぉ
+ if (!y) {
+ var objDate = new Date()
+ } else {
+ var objDate = new Date(y, parseInt(m) - 1, d)
+ }
+ var i; var leap = 0; var temp = 0
+ // 淇ymd鍙傛暟
+ var y = objDate.getFullYear()
+ var m = objDate.getMonth() + 1
+ var d = objDate.getDate()
+ var offset = (Date.UTC(objDate.getFullYear(), objDate.getMonth(), objDate.getDate()) - Date.UTC(1900, 0, 31)) / 86400000
+ for (i = 1900; i < 2101 && offset > 0; i++) {
+ temp = this.lYearDays(i)
+ offset -= temp
+ }
+ if (offset < 0) {
+ offset += temp; i--
+ }
+
+ // 鏄惁浠婂ぉ
+ var isTodayObj = new Date()
+ var isToday = false
+ if (isTodayObj.getFullYear() == y && isTodayObj.getMonth() + 1 == m && isTodayObj.getDate() == d) {
+ isToday = true
+ }
+ // 鏄熸湡鍑�
+ var nWeek = objDate.getDay()
+ var cWeek = this.nStr1[nWeek]
+ // 鏁板瓧琛ㄧず鍛ㄥ嚑椤哄簲澶╂湞鍛ㄤ竴寮�濮嬬殑鎯緥
+ if (nWeek == 0) {
+ nWeek = 7
+ }
+ // 鍐滃巻骞�
+ var year = i
+ var leap = this.leapMonth(i) // 闂板摢涓湀
+ var isLeap = false
+
+ // 鏁堥獙闂版湀
+ for (i = 1; i < 13 && offset > 0; i++) {
+ // 闂版湀
+ if (leap > 0 && i == (leap + 1) && isLeap == false) {
+ --i
+ isLeap = true; temp = this.leapDays(year) // 璁$畻鍐滃巻闂版湀澶╂暟
+ } else {
+ temp = this.monthDays(year, i)// 璁$畻鍐滃巻鏅�氭湀澶╂暟
+ }
+ // 瑙i櫎闂版湀
+ if (isLeap == true && i == (leap + 1)) { isLeap = false }
+ offset -= temp
+ }
+ // 闂版湀瀵艰嚧鏁扮粍涓嬫爣閲嶅彔鍙栧弽
+ if (offset == 0 && leap > 0 && i == leap + 1) {
+ if (isLeap) {
+ isLeap = false
+ } else {
+ isLeap = true; --i
+ }
+ }
+ if (offset < 0) {
+ offset += temp; --i
+ }
+ // 鍐滃巻鏈�
+ var month = i
+ // 鍐滃巻鏃�
+ var day = offset + 1
+ // 澶╁共鍦版敮澶勭悊
+ var sm = m - 1
+ var gzY = this.toGanZhiYear(year)
+
+ // 褰撴湀鐨勪袱涓妭姘�
+ // bugfix-2017-7-24 11:03:38 use lunar Year Param `y` Not `year`
+ var firstNode = this.getTerm(y, (m * 2 - 1))// 杩斿洖褰撴湀銆岃妭銆嶄负鍑犳棩寮�濮�
+ var secondNode = this.getTerm(y, (m * 2))// 杩斿洖褰撴湀銆岃妭銆嶄负鍑犳棩寮�濮�
+
+ // 渚濇嵁12鑺傛皵淇骞叉敮鏈�
+ var gzM = this.toGanZhi((y - 1900) * 12 + m + 11)
+ if (d >= firstNode) {
+ gzM = this.toGanZhi((y - 1900) * 12 + m + 12)
+ }
+
+ // 浼犲叆鐨勬棩鏈熺殑鑺傛皵涓庡惁
+ var isTerm = false
+ var Term = null
+ if (firstNode == d) {
+ isTerm = true
+ Term = this.solarTerm[m * 2 - 2]
+ }
+ if (secondNode == d) {
+ isTerm = true
+ Term = this.solarTerm[m * 2 - 1]
+ }
+ // 鏃ユ煴 褰撴湀涓�鏃ヤ笌 1900/1/1 鐩稿樊澶╂暟
+ var dayCyclical = Date.UTC(y, sm, 1, 0, 0, 0, 0) / 86400000 + 25567 + 10
+ var gzD = this.toGanZhi(dayCyclical + d - 1)
+ // 璇ユ棩鏈熸墍灞炵殑鏄熷骇
+ var astro = this.toAstro(m, d)
+
+ return { 'lYear': year, 'lMonth': month, 'lDay': day, 'Animal': this.getAnimal(year), 'IMonthCn': (isLeap ? '\u95f0' : '') + this.toChinaMonth(month), 'IDayCn': this.toChinaDay(day), 'cYear': y, 'cMonth': m, 'cDay': d, 'gzYear': gzY, 'gzMonth': gzM, 'gzDay': gzD, 'isToday': isToday, 'isLeap': isLeap, 'nWeek': nWeek, 'ncWeek': '\u661f\u671f' + cWeek, 'isTerm': isTerm, 'Term': Term, 'astro': astro }
+ },
+
+ /**
+ * 浼犲叆鍐滃巻骞存湀鏃ヤ互鍙婁紶鍏ョ殑鏈堜唤鏄惁闂版湀鑾峰緱璇︾粏鐨勫叕鍘嗐�佸啘鍘唎bject淇℃伅 <=>JSON
+ * @param y lunar year
+ * @param m lunar month
+ * @param d lunar day
+ * @param isLeapMonth lunar month is leap or not.[濡傛灉鏄啘鍘嗛棸鏈堢鍥涗釜鍙傛暟璧嬪�紅rue鍗冲彲]
+ * @return JSON object
+ * @eg:console.log(calendar.lunar2solar(1987,9,10));
+ */
+ lunar2solar: function (y, m, d, isLeapMonth) { // 鍙傛暟鍖洪棿1900.1.31~2100.12.1
+ var isLeapMonth = !!isLeapMonth
+ var leapOffset = 0
+ var leapMonth = this.leapMonth(y)
+ var leapDay = this.leapDays(y)
+ if (isLeapMonth && (leapMonth != m)) { return -1 }// 浼犲弬瑕佹眰璁$畻璇ラ棸鏈堝叕鍘� 浣嗚骞村緱鍑虹殑闂版湀涓庝紶鍙傜殑鏈堜唤骞朵笉鍚�
+ if (y == 2100 && m == 12 && d > 1 || y == 1900 && m == 1 && d < 31) { return -1 }// 瓒呭嚭浜嗘渶澶ф瀬闄愬��
+ var day = this.monthDays(y, m)
+ var _day = day
+ // bugFix 2016-9-25
+ // if month is leap, _day use leapDays method
+ if (isLeapMonth) {
+ _day = this.leapDays(y, m)
+ }
+ if (y < 1900 || y > 2100 || d > _day) { return -1 }// 鍙傛暟鍚堟硶鎬ф晥楠�
+
+ // 璁$畻鍐滃巻鐨勬椂闂村樊
+ var offset = 0
+ for (var i = 1900; i < y; i++) {
+ offset += this.lYearDays(i)
+ }
+ var leap = 0; var isAdd = false
+ for (var i = 1; i < m; i++) {
+ leap = this.leapMonth(y)
+ if (!isAdd) { // 澶勭悊闂版湀
+ if (leap <= i && leap > 0) {
+ offset += this.leapDays(y); isAdd = true
+ }
+ }
+ offset += this.monthDays(y, i)
+ }
+ // 杞崲闂版湀鍐滃巻 闇�琛ュ厖璇ュ勾闂版湀鐨勫墠涓�涓湀鐨勬椂宸�
+ if (isLeapMonth) { offset += day }
+ // 1900骞村啘鍘嗘鏈堜竴鏃ョ殑鍏巻鏃堕棿涓�1900骞�1鏈�30鏃�0鏃�0鍒�0绉�(璇ユ椂闂翠篃鏄湰鍐滃巻鐨勬渶寮�濮嬭捣濮嬬偣)
+ var stmap = Date.UTC(1900, 1, 30, 0, 0, 0)
+ var calObj = new Date((offset + d - 31) * 86400000 + stmap)
+ var cY = calObj.getUTCFullYear()
+ var cM = calObj.getUTCMonth() + 1
+ var cD = calObj.getUTCDate()
+
+ return this.solar2lunar(cY, cM, cD)
+ }
+}
+
+export default calendar
diff --git a/app/uni_modules/uni-calendar/components/uni-calendar/i18n/en.json b/app/uni_modules/uni-calendar/components/uni-calendar/i18n/en.json
new file mode 100644
index 0000000..fcbd13c
--- /dev/null
+++ b/app/uni_modules/uni-calendar/components/uni-calendar/i18n/en.json
@@ -0,0 +1,12 @@
+{
+ "uni-calender.ok": "ok",
+ "uni-calender.cancel": "cancel",
+ "uni-calender.today": "today",
+ "uni-calender.MON": "MON",
+ "uni-calender.TUE": "TUE",
+ "uni-calender.WED": "WED",
+ "uni-calender.THU": "THU",
+ "uni-calender.FRI": "FRI",
+ "uni-calender.SAT": "SAT",
+ "uni-calender.SUN": "SUN"
+}
diff --git a/app/uni_modules/uni-calendar/components/uni-calendar/i18n/index.js b/app/uni_modules/uni-calendar/components/uni-calendar/i18n/index.js
new file mode 100644
index 0000000..de7509c
--- /dev/null
+++ b/app/uni_modules/uni-calendar/components/uni-calendar/i18n/index.js
@@ -0,0 +1,8 @@
+import en from './en.json'
+import zhHans from './zh-Hans.json'
+import zhHant from './zh-Hant.json'
+export default {
+ en,
+ 'zh-Hans': zhHans,
+ 'zh-Hant': zhHant
+}
diff --git a/app/uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hans.json b/app/uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hans.json
new file mode 100644
index 0000000..1ca43de
--- /dev/null
+++ b/app/uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hans.json
@@ -0,0 +1,12 @@
+{
+ "uni-calender.ok": "纭畾",
+ "uni-calender.cancel": "鍙栨秷",
+ "uni-calender.today": "浠婃棩",
+ "uni-calender.SUN": "鏃�",
+ "uni-calender.MON": "涓�",
+ "uni-calender.TUE": "浜�",
+ "uni-calender.WED": "涓�",
+ "uni-calender.THU": "鍥�",
+ "uni-calender.FRI": "浜�",
+ "uni-calender.SAT": "鍏�"
+}
diff --git a/app/uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hant.json b/app/uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hant.json
new file mode 100644
index 0000000..e0fe33b
--- /dev/null
+++ b/app/uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hant.json
@@ -0,0 +1,12 @@
+{
+ "uni-calender.ok": "纰哄畾",
+ "uni-calender.cancel": "鍙栨秷",
+ "uni-calender.today": "浠婃棩",
+ "uni-calender.SUN": "鏃�",
+ "uni-calender.MON": "涓�",
+ "uni-calender.TUE": "浜�",
+ "uni-calender.WED": "涓�",
+ "uni-calender.THU": "鍥�",
+ "uni-calender.FRI": "浜�",
+ "uni-calender.SAT": "鍏�"
+}
diff --git a/app/uni_modules/uni-calendar/components/uni-calendar/uni-calendar-item.vue b/app/uni_modules/uni-calendar/components/uni-calendar/uni-calendar-item.vue
new file mode 100644
index 0000000..a54135e
--- /dev/null
+++ b/app/uni_modules/uni-calendar/components/uni-calendar/uni-calendar-item.vue
@@ -0,0 +1,187 @@
+<template>
+ <view class="uni-calendar-item__weeks-box" :class="{
+ 'uni-calendar-item--disable':weeks.disable,
+ 'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
+ 'uni-calendar-item--checked':(calendar.fullDate === weeks.fullDate && !weeks.isDay) ,
+ 'uni-calendar-item--before-checked':weeks.beforeMultiple,
+ 'uni-calendar-item--multiple': weeks.multiple,
+ 'uni-calendar-item--after-checked':weeks.afterMultiple,
+ }"
+ @click="choiceDate(weeks)">
+ <view class="uni-calendar-item__weeks-box-item">
+ <text v-if="selected&&weeks.extraInfo" class="uni-calendar-item__weeks-box-circle"></text>
+ <text class="uni-calendar-item__weeks-box-text" :class="{
+ 'uni-calendar-item--isDay-text': weeks.isDay,
+ 'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
+ 'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
+ 'uni-calendar-item--before-checked':weeks.beforeMultiple,
+ 'uni-calendar-item--multiple': weeks.multiple,
+ 'uni-calendar-item--after-checked':weeks.afterMultiple,
+ 'uni-calendar-item--disable':weeks.disable,
+ }">{{weeks.date}}</text>
+ <text v-if="!lunar&&!weeks.extraInfo && weeks.isDay" class="uni-calendar-item__weeks-lunar-text" :class="{
+ 'uni-calendar-item--isDay-text':weeks.isDay,
+ 'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
+ 'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
+ 'uni-calendar-item--before-checked':weeks.beforeMultiple,
+ 'uni-calendar-item--multiple': weeks.multiple,
+ 'uni-calendar-item--after-checked':weeks.afterMultiple,
+ }">{{todayText}}</text>
+ <text v-if="lunar&&!weeks.extraInfo" class="uni-calendar-item__weeks-lunar-text" :class="{
+ 'uni-calendar-item--isDay-text':weeks.isDay,
+ 'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
+ 'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
+ 'uni-calendar-item--before-checked':weeks.beforeMultiple,
+ 'uni-calendar-item--multiple': weeks.multiple,
+ 'uni-calendar-item--after-checked':weeks.afterMultiple,
+ 'uni-calendar-item--disable':weeks.disable,
+ }">{{weeks.isDay ? todayText : (weeks.lunar.IDayCn === '鍒濅竴'?weeks.lunar.IMonthCn:weeks.lunar.IDayCn)}}</text>
+ <text v-if="weeks.extraInfo&&weeks.extraInfo.info" class="uni-calendar-item__weeks-lunar-text" :class="{
+ 'uni-calendar-item--extra':weeks.extraInfo.info,
+ 'uni-calendar-item--isDay-text':weeks.isDay,
+ 'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
+ 'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
+ 'uni-calendar-item--before-checked':weeks.beforeMultiple,
+ 'uni-calendar-item--multiple': weeks.multiple,
+ 'uni-calendar-item--after-checked':weeks.afterMultiple,
+ 'uni-calendar-item--disable':weeks.disable,
+ }">{{weeks.extraInfo.info}}</text>
+ </view>
+ </view>
+</template>
+
+<script>
+ import { initVueI18n } from '@dcloudio/uni-i18n'
+ import i18nMessages from './i18n/index.js'
+ const { t } = initVueI18n(i18nMessages)
+
+ export default {
+ emits:['change'],
+ props: {
+ weeks: {
+ type: Object,
+ default () {
+ return {}
+ }
+ },
+ calendar: {
+ type: Object,
+ default: () => {
+ return {}
+ }
+ },
+ selected: {
+ type: Array,
+ default: () => {
+ return []
+ }
+ },
+ lunar: {
+ type: Boolean,
+ default: false
+ }
+ },
+ computed: {
+ todayText() {
+ return t("uni-calender.today")
+ },
+ },
+ methods: {
+ choiceDate(weeks) {
+ this.$emit('change', weeks)
+ }
+ }
+ }
+</script>
+
+<style lang="scss" scoped>
+ $uni-font-size-base:14px;
+ $uni-text-color:#333;
+ $uni-font-size-sm:12px;
+ $uni-color-error: #e43d33;
+ $uni-opacity-disabled: 0.3;
+ $uni-text-color-disable:#c0c0c0;
+ $uni-primary: #2979ff !default;
+ .uni-calendar-item__weeks-box {
+ flex: 1;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ }
+
+ .uni-calendar-item__weeks-box-text {
+ font-size: $uni-font-size-base;
+ color: $uni-text-color;
+ }
+
+ .uni-calendar-item__weeks-lunar-text {
+ font-size: $uni-font-size-sm;
+ color: $uni-text-color;
+ }
+
+ .uni-calendar-item__weeks-box-item {
+ position: relative;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ width: 100rpx;
+ height: 100rpx;
+ }
+
+ .uni-calendar-item__weeks-box-circle {
+ position: absolute;
+ top: 5px;
+ right: 5px;
+ width: 8px;
+ height: 8px;
+ border-radius: 8px;
+ background-color: $uni-color-error;
+
+ }
+
+ .uni-calendar-item--disable {
+ background-color: rgba(249, 249, 249, $uni-opacity-disabled);
+ color: $uni-text-color-disable;
+ }
+
+ .uni-calendar-item--isDay-text {
+ color: $uni-primary;
+ }
+
+ .uni-calendar-item--isDay {
+ background-color: $uni-primary;
+ opacity: 0.8;
+ color: #fff;
+ }
+
+ .uni-calendar-item--extra {
+ color: $uni-color-error;
+ opacity: 0.8;
+ }
+
+ .uni-calendar-item--checked {
+ background-color: $uni-primary;
+ color: #fff;
+ opacity: 0.8;
+ }
+
+ .uni-calendar-item--multiple {
+ background-color: $uni-primary;
+ color: #fff;
+ opacity: 0.8;
+ }
+ .uni-calendar-item--before-checked {
+ background-color: #ff5a5f;
+ color: #fff;
+ }
+ .uni-calendar-item--after-checked {
+ background-color: #ff5a5f;
+ color: #fff;
+ }
+</style>
diff --git a/app/uni_modules/uni-calendar/components/uni-calendar/uni-calendar.vue b/app/uni_modules/uni-calendar/components/uni-calendar/uni-calendar.vue
new file mode 100644
index 0000000..17c958d
--- /dev/null
+++ b/app/uni_modules/uni-calendar/components/uni-calendar/uni-calendar.vue
@@ -0,0 +1,566 @@
+<template>
+ <view class="uni-calendar">
+ <view v-if="!insert&&show" class="uni-calendar__mask" :class="{'uni-calendar--mask-show':aniMaskShow}" @click="clean"></view>
+ <view v-if="insert || show" class="uni-calendar__content" :class="{'uni-calendar--fixed':!insert,'uni-calendar--ani-show':aniMaskShow}">
+ <view v-if="!insert" class="uni-calendar__header uni-calendar--fixed-top">
+ <view class="uni-calendar__header-btn-box" @click="close">
+ <text class="uni-calendar__header-text uni-calendar--fixed-width">{{cancelText}}</text>
+ </view>
+ <view class="uni-calendar__header-btn-box" @click="confirm">
+ <text class="uni-calendar__header-text uni-calendar--fixed-width">{{okText}}</text>
+ </view>
+ </view>
+ <view class="uni-calendar__header">
+ <view class="uni-calendar__header-btn-box" @click.stop="pre">
+ <view class="uni-calendar__header-btn uni-calendar--left"></view>
+ </view>
+ <picker mode="date" :value="date" fields="month" @change="bindDateChange">
+ <text class="uni-calendar__header-text">{{ (nowDate.year||'') +' / '+( nowDate.month||'')}}</text>
+ </picker>
+ <view class="uni-calendar__header-btn-box" @click.stop="next">
+ <view class="uni-calendar__header-btn uni-calendar--right"></view>
+ </view>
+ <text class="uni-calendar__backtoday" @click="backToday">{{todayText}}</text>
+
+ </view>
+ <view class="uni-calendar__box">
+ <view v-if="showMonth" class="uni-calendar__box-bg">
+ <text class="uni-calendar__box-bg-text">{{nowDate.month}}</text>
+ </view>
+ <view class="uni-calendar__weeks">
+ <view class="uni-calendar__weeks-day">
+ <text class="uni-calendar__weeks-day-text">{{SUNText}}</text>
+ </view>
+ <view class="uni-calendar__weeks-day">
+ <text class="uni-calendar__weeks-day-text">{{monText}}</text>
+ </view>
+ <view class="uni-calendar__weeks-day">
+ <text class="uni-calendar__weeks-day-text">{{TUEText}}</text>
+ </view>
+ <view class="uni-calendar__weeks-day">
+ <text class="uni-calendar__weeks-day-text">{{WEDText}}</text>
+ </view>
+ <view class="uni-calendar__weeks-day">
+ <text class="uni-calendar__weeks-day-text">{{THUText}}</text>
+ </view>
+ <view class="uni-calendar__weeks-day">
+ <text class="uni-calendar__weeks-day-text">{{FRIText}}</text>
+ </view>
+ <view class="uni-calendar__weeks-day">
+ <text class="uni-calendar__weeks-day-text">{{SATText}}</text>
+ </view>
+ </view>
+ <view class="uni-calendar__weeks" v-for="(item,weekIndex) in weeks" :key="weekIndex">
+ <view class="uni-calendar__weeks-item" v-for="(weeks,weeksIndex) in item" :key="weeksIndex">
+ <calendar-item class="uni-calendar-item--hook" :weeks="weeks" :calendar="calendar" :selected="selected" :lunar="lunar" @change="choiceDate"></calendar-item>
+ </view>
+ </view>
+ </view>
+ </view>
+ </view>
+</template>
+
+<script>
+ import Calendar from './util.js';
+ import CalendarItem from './uni-calendar-item.vue'
+
+ import { initVueI18n } from '@dcloudio/uni-i18n'
+ import i18nMessages from './i18n/index.js'
+ const { t } = initVueI18n(i18nMessages)
+
+ /**
+ * Calendar 鏃ュ巻
+ * @description 鏃ュ巻缁勪欢鍙互鏌ョ湅鏃ユ湡锛岄�夋嫨浠绘剰鑼冨洿鍐呯殑鏃ユ湡锛屾墦鐐规搷浣溿�傚父鐢ㄥ満鏅锛氶厭搴楁棩鏈熼璁€�佺伀杞︽満绁ㄩ�夋嫨璐拱鏃ユ湡銆佷笂涓嬬彮鎵撳崱绛�
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=56
+ * @property {String} date 鑷畾涔夊綋鍓嶆椂闂达紝榛樿涓轰粖澶�
+ * @property {Boolean} lunar 鏄剧ず鍐滃巻
+ * @property {String} startDate 鏃ユ湡閫夋嫨鑼冨洿-寮�濮嬫棩鏈�
+ * @property {String} endDate 鏃ユ湡閫夋嫨鑼冨洿-缁撴潫鏃ユ湡
+ * @property {Boolean} range 鑼冨洿閫夋嫨
+ * @property {Boolean} insert = [true|false] 鎻掑叆妯″紡,榛樿涓篺alse
+ * @value true 寮圭獥妯″紡
+ * @value false 鎻掑叆妯″紡
+ * @property {Boolean} clearDate = [true|false] 寮圭獥妯″紡鏄惁娓呯┖涓婃閫夋嫨鍐呭
+ * @property {Array} selected 鎵撶偣锛屾湡寰呮牸寮廩{date: '2019-06-27', info: '绛惧埌', data: { custom: '鑷畾涔変俊鎭�', name: '鑷畾涔夋秷鎭ご',xxx:xxx... }}]
+ * @property {Boolean} showMonth 鏄惁閫夋嫨鏈堜唤涓鸿儗鏅�
+ * @event {Function} change 鏃ユ湡鏀瑰彉锛宍insert :ture` 鏃剁敓鏁�
+ * @event {Function} confirm 纭閫夋嫨`insert :false` 鏃剁敓鏁�
+ * @event {Function} monthSwitch 鍒囨崲鏈堜唤鏃惰Е鍙�
+ * @example <uni-calendar :insert="true":lunar="true" :start-date="'2019-3-2'":end-date="'2019-5-20'"@change="change" />
+ */
+ export default {
+ components: {
+ CalendarItem
+ },
+ emits:['close','confirm','change','monthSwitch'],
+ props: {
+ date: {
+ type: String,
+ default: ''
+ },
+ selected: {
+ type: Array,
+ default () {
+ return []
+ }
+ },
+ lunar: {
+ type: Boolean,
+ default: false
+ },
+ startDate: {
+ type: String,
+ default: ''
+ },
+ endDate: {
+ type: String,
+ default: ''
+ },
+ range: {
+ type: Boolean,
+ default: false
+ },
+ insert: {
+ type: Boolean,
+ default: true
+ },
+ showMonth: {
+ type: Boolean,
+ default: true
+ },
+ clearDate: {
+ type: Boolean,
+ default: true
+ }
+ },
+ data() {
+ return {
+ show: false,
+ weeks: [],
+ calendar: {},
+ nowDate: '',
+ aniMaskShow: false
+ }
+ },
+ computed:{
+ /**
+ * for i18n
+ */
+
+ okText() {
+ return t("uni-calender.ok")
+ },
+ cancelText() {
+ return t("uni-calender.cancel")
+ },
+ todayText() {
+ return t("uni-calender.today")
+ },
+ monText() {
+ return t("uni-calender.MON")
+ },
+ TUEText() {
+ return t("uni-calender.TUE")
+ },
+ WEDText() {
+ return t("uni-calender.WED")
+ },
+ THUText() {
+ return t("uni-calender.THU")
+ },
+ FRIText() {
+ return t("uni-calender.FRI")
+ },
+ SATText() {
+ return t("uni-calender.SAT")
+ },
+ SUNText() {
+ return t("uni-calender.SUN")
+ },
+ },
+ watch: {
+ date(newVal) {
+ // this.cale.setDate(newVal)
+ this.init(newVal)
+ },
+ startDate(val){
+ this.cale.resetSatrtDate(val)
+ this.cale.setDate(this.nowDate.fullDate)
+ this.weeks = this.cale.weeks
+ },
+ endDate(val){
+ this.cale.resetEndDate(val)
+ this.cale.setDate(this.nowDate.fullDate)
+ this.weeks = this.cale.weeks
+ },
+ selected(newVal) {
+ this.cale.setSelectInfo(this.nowDate.fullDate, newVal)
+ this.weeks = this.cale.weeks
+ }
+ },
+ created() {
+ this.cale = new Calendar({
+ selected: this.selected,
+ startDate: this.startDate,
+ endDate: this.endDate,
+ range: this.range,
+ })
+ this.init(this.date)
+ },
+ methods: {
+ // 鍙栨秷绌块��
+ clean() {},
+ bindDateChange(e) {
+ const value = e.detail.value + '-1'
+ this.setDate(value)
+
+ const { year,month } = this.cale.getDate(value)
+ this.$emit('monthSwitch', {
+ year,
+ month
+ })
+ },
+ /**
+ * 鍒濆鍖栨棩鏈熸樉绀�
+ * @param {Object} date
+ */
+ init(date) {
+ this.cale.setDate(date)
+ this.weeks = this.cale.weeks
+ this.nowDate = this.calendar = this.cale.getInfo(date)
+ },
+ /**
+ * 鎵撳紑鏃ュ巻寮圭獥
+ */
+ open() {
+ // 寮圭獥妯″紡骞朵笖娓呯悊鏁版嵁
+ if (this.clearDate && !this.insert) {
+ this.cale.cleanMultipleStatus()
+ // this.cale.setDate(this.date)
+ this.init(this.date)
+ }
+ this.show = true
+ this.$nextTick(() => {
+ setTimeout(() => {
+ this.aniMaskShow = true
+ }, 50)
+ })
+ },
+ /**
+ * 鍏抽棴鏃ュ巻寮圭獥
+ */
+ close() {
+ this.aniMaskShow = false
+ this.$nextTick(() => {
+ setTimeout(() => {
+ this.show = false
+ this.$emit('close')
+ }, 300)
+ })
+ },
+ /**
+ * 纭鎸夐挳
+ */
+ confirm() {
+ this.setEmit('confirm')
+ this.close()
+ },
+ /**
+ * 鍙樺寲瑙﹀彂
+ */
+ change() {
+ if (!this.insert) return
+ this.setEmit('change')
+ },
+ /**
+ * 閫夋嫨鏈堜唤瑙﹀彂
+ */
+ monthSwitch() {
+ let {
+ year,
+ month
+ } = this.nowDate
+ this.$emit('monthSwitch', {
+ year,
+ month: Number(month)
+ })
+ },
+ /**
+ * 娲惧彂浜嬩欢
+ * @param {Object} name
+ */
+ setEmit(name) {
+ let {
+ year,
+ month,
+ date,
+ fullDate,
+ lunar,
+ extraInfo
+ } = this.calendar
+ this.$emit(name, {
+ range: this.cale.multipleStatus,
+ year,
+ month,
+ date,
+ fulldate: fullDate,
+ lunar,
+ extraInfo: extraInfo || {}
+ })
+ },
+ /**
+ * 閫夋嫨澶╄Е鍙�
+ * @param {Object} weeks
+ */
+ choiceDate(weeks) {
+ if (weeks.disable) return
+ this.calendar = weeks
+ // 璁剧疆澶氶��
+ this.cale.setMultiple(this.calendar.fullDate)
+ this.weeks = this.cale.weeks
+ this.change()
+ },
+ /**
+ * 鍥炲埌浠婂ぉ
+ */
+ backToday() {
+ const nowYearMonth = `${this.nowDate.year}-${this.nowDate.month}`
+ const date = this.cale.getDate(new Date())
+ const todayYearMonth = `${date.year}-${date.month}`
+
+ if(nowYearMonth !== todayYearMonth) {
+ this.monthSwitch()
+ }
+
+ this.init(date.fullDate)
+ this.change()
+ },
+ /**
+ * 涓婁釜鏈�
+ */
+ pre() {
+ const preDate = this.cale.getDate(this.nowDate.fullDate, -1, 'month').fullDate
+ this.setDate(preDate)
+ this.monthSwitch()
+
+ },
+ /**
+ * 涓嬩釜鏈�
+ */
+ next() {
+ const nextDate = this.cale.getDate(this.nowDate.fullDate, +1, 'month').fullDate
+ this.setDate(nextDate)
+ this.monthSwitch()
+ },
+ /**
+ * 璁剧疆鏃ユ湡
+ * @param {Object} date
+ */
+ setDate(date) {
+ this.cale.setDate(date)
+ this.weeks = this.cale.weeks
+ this.nowDate = this.cale.getInfo(date)
+ }
+ }
+ }
+</script>
+
+<style lang="scss" scoped>
+ $uni-bg-color-mask: rgba($color: #000000, $alpha: 0.4);
+ $uni-border-color: #EDEDED;
+ $uni-text-color: #333;
+ $uni-bg-color-hover:#f1f1f1;
+ $uni-font-size-base:14px;
+ $uni-text-color-placeholder: #808080;
+ $uni-color-subtitle: #555555;
+ $uni-text-color-grey:#999;
+ .uni-calendar {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: column;
+ }
+
+ .uni-calendar__mask {
+ position: fixed;
+ bottom: 0;
+ top: 0;
+ left: 0;
+ right: 0;
+ background-color: $uni-bg-color-mask;
+ transition-property: opacity;
+ transition-duration: 0.3s;
+ opacity: 0;
+ /* #ifndef APP-NVUE */
+ z-index: 99;
+ /* #endif */
+ }
+
+ .uni-calendar--mask-show {
+ opacity: 1
+ }
+
+ .uni-calendar--fixed {
+ position: fixed;
+ /* #ifdef APP-NVUE */
+ bottom: 0;
+ /* #endif */
+ left: 0;
+ right: 0;
+ transition-property: transform;
+ transition-duration: 0.3s;
+ transform: translateY(460px);
+ /* #ifndef APP-NVUE */
+ bottom: calc(var(--window-bottom));
+ z-index: 99;
+ /* #endif */
+ }
+
+ .uni-calendar--ani-show {
+ transform: translateY(0);
+ }
+
+ .uni-calendar__content {
+ background-color: #fff;
+ }
+
+ .uni-calendar__header {
+ position: relative;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ justify-content: center;
+ align-items: center;
+ height: 50px;
+ border-bottom-color: $uni-border-color;
+ border-bottom-style: solid;
+ border-bottom-width: 1px;
+ }
+
+ .uni-calendar--fixed-top {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ justify-content: space-between;
+ border-top-color: $uni-border-color;
+ border-top-style: solid;
+ border-top-width: 1px;
+ }
+
+ .uni-calendar--fixed-width {
+ width: 50px;
+ }
+
+ .uni-calendar__backtoday {
+ position: absolute;
+ right: 0;
+ top: 25rpx;
+ padding: 0 5px;
+ padding-left: 10px;
+ height: 25px;
+ line-height: 25px;
+ font-size: 12px;
+ border-top-left-radius: 25px;
+ border-bottom-left-radius: 25px;
+ color: $uni-text-color;
+ background-color: $uni-bg-color-hover;
+ }
+
+ .uni-calendar__header-text {
+ text-align: center;
+ width: 100px;
+ font-size: $uni-font-size-base;
+ color: $uni-text-color;
+ }
+
+ .uni-calendar__header-btn-box {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ align-items: center;
+ justify-content: center;
+ width: 50px;
+ height: 50px;
+ }
+
+ .uni-calendar__header-btn {
+ width: 10px;
+ height: 10px;
+ border-left-color: $uni-text-color-placeholder;
+ border-left-style: solid;
+ border-left-width: 2px;
+ border-top-color: $uni-color-subtitle;
+ border-top-style: solid;
+ border-top-width: 2px;
+ }
+
+ .uni-calendar--left {
+ transform: rotate(-45deg);
+ }
+
+ .uni-calendar--right {
+ transform: rotate(135deg);
+ }
+
+
+ .uni-calendar__weeks {
+ position: relative;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ }
+
+ .uni-calendar__weeks-item {
+ flex: 1;
+ }
+
+ .uni-calendar__weeks-day {
+ flex: 1;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ height: 45px;
+ border-bottom-color: #F5F5F5;
+ border-bottom-style: solid;
+ border-bottom-width: 1px;
+ }
+
+ .uni-calendar__weeks-day-text {
+ font-size: 14px;
+ }
+
+ .uni-calendar__box {
+ position: relative;
+ }
+
+ .uni-calendar__box-bg {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ justify-content: center;
+ align-items: center;
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ }
+
+ .uni-calendar__box-bg-text {
+ font-size: 200px;
+ font-weight: bold;
+ color: $uni-text-color-grey;
+ opacity: 0.1;
+ text-align: center;
+ /* #ifndef APP-NVUE */
+ line-height: 1;
+ /* #endif */
+ }
+</style>
diff --git a/app/uni_modules/uni-calendar/components/uni-calendar/util.js b/app/uni_modules/uni-calendar/components/uni-calendar/util.js
new file mode 100644
index 0000000..5ec8a92
--- /dev/null
+++ b/app/uni_modules/uni-calendar/components/uni-calendar/util.js
@@ -0,0 +1,360 @@
+import CALENDAR from './calendar.js'
+
+class Calendar {
+ constructor({
+ date,
+ selected,
+ startDate,
+ endDate,
+ range
+ } = {}) {
+ // 褰撳墠鏃ユ湡
+ this.date = this.getDate(new Date()) // 褰撳墠鍒濆叆鏃ユ湡
+ // 鎵撶偣淇℃伅
+ this.selected = selected || [];
+ // 鑼冨洿寮�濮�
+ this.startDate = startDate
+ // 鑼冨洿缁撴潫
+ this.endDate = endDate
+ this.range = range
+ // 澶氶�夌姸鎬�
+ this.cleanMultipleStatus()
+ // 姣忓懆鏃ユ湡
+ this.weeks = {}
+ // this._getWeek(this.date.fullDate)
+ }
+ /**
+ * 璁剧疆鏃ユ湡
+ * @param {Object} date
+ */
+ setDate(date) {
+ this.selectDate = this.getDate(date)
+ this._getWeek(this.selectDate.fullDate)
+ }
+
+ /**
+ * 娓呯悊澶氶�夌姸鎬�
+ */
+ cleanMultipleStatus() {
+ this.multipleStatus = {
+ before: '',
+ after: '',
+ data: []
+ }
+ }
+
+ /**
+ * 閲嶇疆寮�濮嬫棩鏈�
+ */
+ resetSatrtDate(startDate) {
+ // 鑼冨洿寮�濮�
+ this.startDate = startDate
+
+ }
+
+ /**
+ * 閲嶇疆缁撴潫鏃ユ湡
+ */
+ resetEndDate(endDate) {
+ // 鑼冨洿缁撴潫
+ this.endDate = endDate
+ }
+
+ /**
+ * 鑾峰彇浠绘剰鏃堕棿
+ */
+ getDate(date, AddDayCount = 0, str = 'day') {
+ if (!date) {
+ date = new Date()
+ }
+ if (typeof date !== 'object') {
+ date = date.replace(/-/g, '/')
+ }
+ const dd = new Date(date)
+ switch (str) {
+ case 'day':
+ dd.setDate(dd.getDate() + AddDayCount) // 鑾峰彇AddDayCount澶╁悗鐨勬棩鏈�
+ break
+ case 'month':
+ if (dd.getDate() === 31 && AddDayCount>0) {
+ dd.setDate(dd.getDate() + AddDayCount)
+ } else {
+ const preMonth = dd.getMonth()
+ dd.setMonth(preMonth + AddDayCount) // 鑾峰彇AddDayCount澶╁悗鐨勬棩鏈�
+ const nextMonth = dd.getMonth()
+ // 澶勭悊 pre 鍒囨崲鏈堜唤鐩爣鏈堜唤涓�2鏈堟病鏈夊綋鍓嶆棩(30 31) 鍒囨崲閿欒闂
+ if(AddDayCount<0 && preMonth!==0 && nextMonth-preMonth>AddDayCount){
+ dd.setMonth(nextMonth+(nextMonth-preMonth+AddDayCount))
+ }
+ // 澶勭悊 next 鍒囨崲鏈堜唤鐩爣鏈堜唤涓�2鏈堟病鏈夊綋鍓嶆棩(30 31) 鍒囨崲閿欒闂
+ if(AddDayCount>0 && nextMonth-preMonth>AddDayCount){
+ dd.setMonth(nextMonth-(nextMonth-preMonth-AddDayCount))
+ }
+ }
+ break
+ case 'year':
+ dd.setFullYear(dd.getFullYear() + AddDayCount) // 鑾峰彇AddDayCount澶╁悗鐨勬棩鏈�
+ break
+ }
+ const y = dd.getFullYear()
+ const m = dd.getMonth() + 1 < 10 ? '0' + (dd.getMonth() + 1) : dd.getMonth() + 1 // 鑾峰彇褰撳墠鏈堜唤鐨勬棩鏈燂紝涓嶈冻10琛�0
+ const d = dd.getDate() < 10 ? '0' + dd.getDate() : dd.getDate() // 鑾峰彇褰撳墠鍑犲彿锛屼笉瓒�10琛�0
+ return {
+ fullDate: y + '-' + m + '-' + d,
+ year: y,
+ month: m,
+ date: d,
+ day: dd.getDay()
+ }
+ }
+
+
+ /**
+ * 鑾峰彇涓婃湀鍓╀綑澶╂暟
+ */
+ _getLastMonthDays(firstDay, full) {
+ let dateArr = []
+ for (let i = firstDay; i > 0; i--) {
+ const beforeDate = new Date(full.year, full.month - 1, -i + 1).getDate()
+ dateArr.push({
+ date: beforeDate,
+ month: full.month - 1,
+ lunar: this.getlunar(full.year, full.month - 1, beforeDate),
+ disable: true
+ })
+ }
+ return dateArr
+ }
+ /**
+ * 鑾峰彇鏈湀澶╂暟
+ */
+ _currentMonthDys(dateData, full) {
+ let dateArr = []
+ let fullDate = this.date.fullDate
+ for (let i = 1; i <= dateData; i++) {
+ let nowDate = full.year + '-' + (full.month < 10 ?
+ full.month : full.month) + '-' + (i < 10 ?
+ '0' + i : i)
+ // 鏄惁浠婂ぉ
+ let isDay = fullDate === nowDate
+ // 鑾峰彇鎵撶偣淇℃伅
+ let info = this.selected && this.selected.find((item) => {
+ if (this.dateEqual(nowDate, item.date)) {
+ return item
+ }
+ })
+
+ // 鏃ユ湡绂佺敤
+ let disableBefore = true
+ let disableAfter = true
+ if (this.startDate) {
+ // let dateCompBefore = this.dateCompare(this.startDate, fullDate)
+ // disableBefore = this.dateCompare(dateCompBefore ? this.startDate : fullDate, nowDate)
+ disableBefore = this.dateCompare(this.startDate, nowDate)
+ }
+
+ if (this.endDate) {
+ // let dateCompAfter = this.dateCompare(fullDate, this.endDate)
+ // disableAfter = this.dateCompare(nowDate, dateCompAfter ? this.endDate : fullDate)
+ disableAfter = this.dateCompare(nowDate, this.endDate)
+ }
+ let multiples = this.multipleStatus.data
+ let checked = false
+ let multiplesStatus = -1
+ if (this.range) {
+ if (multiples) {
+ multiplesStatus = multiples.findIndex((item) => {
+ return this.dateEqual(item, nowDate)
+ })
+ }
+ if (multiplesStatus !== -1) {
+ checked = true
+ }
+ }
+ let data = {
+ fullDate: nowDate,
+ year: full.year,
+ date: i,
+ multiple: this.range ? checked : false,
+ beforeMultiple: this.dateEqual(this.multipleStatus.before, nowDate),
+ afterMultiple: this.dateEqual(this.multipleStatus.after, nowDate),
+ month: full.month,
+ lunar: this.getlunar(full.year, full.month, i),
+ disable: !(disableBefore && disableAfter),
+ isDay
+ }
+ if (info) {
+ data.extraInfo = info
+ }
+
+ dateArr.push(data)
+ }
+ return dateArr
+ }
+ /**
+ * 鑾峰彇涓嬫湀澶╂暟
+ */
+ _getNextMonthDays(surplus, full) {
+ let dateArr = []
+ for (let i = 1; i < surplus + 1; i++) {
+ dateArr.push({
+ date: i,
+ month: Number(full.month) + 1,
+ lunar: this.getlunar(full.year, Number(full.month) + 1, i),
+ disable: true
+ })
+ }
+ return dateArr
+ }
+
+ /**
+ * 鑾峰彇褰撳墠鏃ユ湡璇︽儏
+ * @param {Object} date
+ */
+ getInfo(date) {
+ if (!date) {
+ date = new Date()
+ }
+ const dateInfo = this.canlender.find(item => item.fullDate === this.getDate(date).fullDate)
+ return dateInfo
+ }
+
+ /**
+ * 姣旇緝鏃堕棿澶у皬
+ */
+ dateCompare(startDate, endDate) {
+ // 璁$畻鎴鏃堕棿
+ startDate = new Date(startDate.replace('-', '/').replace('-', '/'))
+ // 璁$畻璇︾粏椤圭殑鎴鏃堕棿
+ endDate = new Date(endDate.replace('-', '/').replace('-', '/'))
+ if (startDate <= endDate) {
+ return true
+ } else {
+ return false
+ }
+ }
+
+ /**
+ * 姣旇緝鏃堕棿鏄惁鐩哥瓑
+ */
+ dateEqual(before, after) {
+ // 璁$畻鎴鏃堕棿
+ before = new Date(before.replace('-', '/').replace('-', '/'))
+ // 璁$畻璇︾粏椤圭殑鎴鏃堕棿
+ after = new Date(after.replace('-', '/').replace('-', '/'))
+ if (before.getTime() - after.getTime() === 0) {
+ return true
+ } else {
+ return false
+ }
+ }
+
+
+ /**
+ * 鑾峰彇鏃ユ湡鑼冨洿鍐呮墍鏈夋棩鏈�
+ * @param {Object} begin
+ * @param {Object} end
+ */
+ geDateAll(begin, end) {
+ var arr = []
+ var ab = begin.split('-')
+ var ae = end.split('-')
+ var db = new Date()
+ db.setFullYear(ab[0], ab[1] - 1, ab[2])
+ var de = new Date()
+ de.setFullYear(ae[0], ae[1] - 1, ae[2])
+ var unixDb = db.getTime() - 24 * 60 * 60 * 1000
+ var unixDe = de.getTime() - 24 * 60 * 60 * 1000
+ for (var k = unixDb; k <= unixDe;) {
+ k = k + 24 * 60 * 60 * 1000
+ arr.push(this.getDate(new Date(parseInt(k))).fullDate)
+ }
+ return arr
+ }
+ /**
+ * 璁$畻闃村巻鏃ユ湡鏄剧ず
+ */
+ getlunar(year, month, date) {
+ return CALENDAR.solar2lunar(year, month, date)
+ }
+ /**
+ * 璁剧疆鎵撶偣
+ */
+ setSelectInfo(data, value) {
+ this.selected = value
+ this._getWeek(data)
+ }
+
+ /**
+ * 鑾峰彇澶氶�夌姸鎬�
+ */
+ setMultiple(fullDate) {
+ let {
+ before,
+ after
+ } = this.multipleStatus
+
+ if (!this.range) return
+ if (before && after) {
+ this.multipleStatus.before = ''
+ this.multipleStatus.after = ''
+ this.multipleStatus.data = []
+ } else {
+ if (!before) {
+ this.multipleStatus.before = fullDate
+ } else {
+ this.multipleStatus.after = fullDate
+ if (this.dateCompare(this.multipleStatus.before, this.multipleStatus.after)) {
+ this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus.after);
+ } else {
+ this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus.before);
+ }
+ }
+ }
+ this._getWeek(fullDate)
+ }
+
+ /**
+ * 鑾峰彇姣忓懆鏁版嵁
+ * @param {Object} dateData
+ */
+ _getWeek(dateData) {
+ const {
+ year,
+ month
+ } = this.getDate(dateData)
+ let firstDay = new Date(year, month - 1, 1).getDay()
+ let currentDay = new Date(year, month, 0).getDate()
+ let dates = {
+ lastMonthDays: this._getLastMonthDays(firstDay, this.getDate(dateData)), // 涓婁釜鏈堟湯灏惧嚑澶�
+ currentMonthDys: this._currentMonthDys(currentDay, this.getDate(dateData)), // 鏈湀澶╂暟
+ nextMonthDays: [], // 涓嬩釜鏈堝紑濮嬪嚑澶�
+ weeks: []
+ }
+ let canlender = []
+ const surplus = 42 - (dates.lastMonthDays.length + dates.currentMonthDys.length)
+ dates.nextMonthDays = this._getNextMonthDays(surplus, this.getDate(dateData))
+ canlender = canlender.concat(dates.lastMonthDays, dates.currentMonthDys, dates.nextMonthDays)
+ let weeks = {}
+ // 鎷兼帴鏁扮粍 涓婁釜鏈堝紑濮嬪嚑澶� + 鏈湀澶╂暟+ 涓嬩釜鏈堝紑濮嬪嚑澶�
+ for (let i = 0; i < canlender.length; i++) {
+ if (i % 7 === 0) {
+ weeks[parseInt(i / 7)] = new Array(7)
+ }
+ weeks[parseInt(i / 7)][i % 7] = canlender[i]
+ }
+ this.canlender = canlender
+ this.weeks = weeks
+ }
+
+ //闈欐�佹柟娉�
+ // static init(date) {
+ // if (!this.instance) {
+ // this.instance = new Calendar(date);
+ // }
+ // return this.instance;
+ // }
+}
+
+
+export default Calendar
diff --git a/app/uni_modules/uni-calendar/package.json b/app/uni_modules/uni-calendar/package.json
new file mode 100644
index 0000000..fad841f
--- /dev/null
+++ b/app/uni_modules/uni-calendar/package.json
@@ -0,0 +1,85 @@
+{
+ "id": "uni-calendar",
+ "displayName": "uni-calendar 鏃ュ巻",
+ "version": "1.4.10",
+ "description": "鏃ュ巻缁勪欢",
+ "keywords": [
+ "uni-ui",
+ "uniui",
+ "鏃ュ巻",
+ "",
+ "鎵撳崱",
+ "鏃ュ巻閫夋嫨"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+"dcloudext": {
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+ "type": "component-vue"
+ },
+ "uni_modules": {
+ "dependencies": [],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "u",
+ "鑱旂洘": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/uni_modules/uni-calendar/readme.md b/app/uni_modules/uni-calendar/readme.md
new file mode 100644
index 0000000..4e1748c
--- /dev/null
+++ b/app/uni_modules/uni-calendar/readme.md
@@ -0,0 +1,103 @@
+
+
+## Calendar 鏃ュ巻
+> **缁勪欢鍚嶏細uni-calendar**
+> 浠g爜鍧楋細 `uCalendar`
+
+
+鏃ュ巻缁勪欢
+
+> **娉ㄦ剰浜嬮」**
+> 涓轰簡閬垮厤閿欒浣跨敤锛岀粰澶у甯︽潵涓嶅ソ鐨勫紑鍙戜綋楠岋紝璇峰湪浣跨敤缁勪欢鍓嶄粩缁嗛槄璇讳笅闈㈢殑娉ㄦ剰浜嬮」锛屽彲浠ュ府浣犻伩鍏嶄竴浜涢敊璇��
+> - 鏈粍浠跺啘鍘嗚浆鎹娇鐢ㄧ殑js鏄� [@1900-2100鍖洪棿鍐呯殑鍏巻銆佸啘鍘嗕簰杞琞(https://github.com/jjonline/calendar.js)
+> - 浠呮敮鎸佽嚜瀹氫箟缁勪欢妯″紡
+> - `date`灞炴�т紶鍏ョ殑搴旇鏄竴涓� String 锛屽锛� 2019-06-27 锛岃�屼笉鏄� new Date()
+> - 閫氳繃 `insert` 灞炴�ф潵纭畾褰撳墠鐨勪簨浠舵槸 @change 杩樻槸 @confirm 銆傜悊搴斿悎骞朵负涓�涓簨浠讹紝浣嗘槸涓轰簡鍖哄垎妯″紡锛岀幇浣跨敤涓や釜浜嬩欢锛岃繖閲岄渶瑕佹敞鎰�
+> - 寮圭獥妯″紡涓嬫棤娉曢樆姝㈠悗闈㈢殑鍏冪礌婊氬姩锛屽鏈夐渶瑕侀樆姝紝璇峰湪寮圭獥寮瑰嚭鍚庯紝鎵嬪姩璁剧疆婊氬姩鍏冪礌涓轰笉鍙粴鍔�
+
+
+### 瀹夎鏂瑰紡
+
+鏈粍浠剁鍚圼easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)瑙勮寖锛宍HBuilderX 2.5.5`璧凤紝鍙渶灏嗘湰缁勪欢瀵煎叆椤圭洰锛屽湪椤甸潰`template`涓嵆鍙洿鎺ヤ娇鐢紝鏃犻渶鍦ㄩ〉闈腑`import`鍜屾敞鍐宍components`銆�
+
+濡傞渶閫氳繃`npm`鏂瑰紡浣跨敤`uni-ui`缁勪欢锛屽彟瑙佹枃妗o細[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55)
+
+### 鍩烘湰鐢ㄦ硶
+
+鍦� ``template`` 涓娇鐢ㄧ粍浠�
+
+```html
+<view>
+ <uni-calendar
+ :insert="true"
+ :lunar="true"
+ :start-date="'2019-3-2'"
+ :end-date="'2019-5-20'"
+ @change="change"
+ />
+</view>
+```
+
+### 閫氳繃鏂规硶鎵撳紑鏃ュ巻
+
+闇�瑕佽缃� `insert` 涓� `false`
+
+```html
+<view>
+ <uni-calendar
+ ref="calendar"
+ :insert="false"
+ @confirm="confirm"
+ />
+ <button @click="open">鎵撳紑鏃ュ巻</button>
+</view>
+```
+
+```javascript
+
+export default {
+ data() {
+ return {};
+ },
+ methods: {
+ open(){
+ this.$refs.calendar.open();
+ },
+ confirm(e) {
+ console.log(e);
+ }
+ }
+};
+
+```
+
+
+## API
+
+### Calendar Props
+
+| 灞炴�у悕 | 绫诲瀷 | 榛樿鍊紎 璇存槑 |
+| - | - | - | - |
+| date | String |- | 鑷畾涔夊綋鍓嶆椂闂达紝榛樿涓轰粖澶� |
+| lunar | Boolean | false | 鏄剧ず鍐滃巻 |
+| startDate | String |- | 鏃ユ湡閫夋嫨鑼冨洿-寮�濮嬫棩鏈� |
+| endDate | String |- | 鏃ユ湡閫夋嫨鑼冨洿-缁撴潫鏃ユ湡 |
+| range | Boolean | false | 鑼冨洿閫夋嫨 |
+| insert | Boolean | false | 鎻掑叆妯″紡,鍙�夊�硷紝ture锛氭彃鍏ユā寮忥紱false锛氬脊绐楁ā寮忥紱榛樿涓烘彃鍏ユā寮� |
+|clearDate |Boolean |true |寮圭獥妯″紡鏄惁娓呯┖涓婃閫夋嫨鍐呭 |
+| selected | Array |- | 鎵撶偣锛屾湡寰呮牸寮廩{date: '2019-06-27', info: '绛惧埌', data: { custom: '鑷畾涔変俊鎭�', name: '鑷畾涔夋秷鎭ご',xxx:xxx... }}] |
+|showMonth | Boolean | true | 鏄惁鏄剧ず鏈堜唤涓鸿儗鏅� |
+
+### Calendar Events
+
+| 浜嬩欢鍚� | 璇存槑 |杩斿洖鍊紎
+| - | - | - |
+| open | 寮瑰嚭鏃ュ巻缁勪欢锛宍insert :false` 鏃剁敓鏁坾- |
+
+
+
+
+
+## 缁勪欢绀轰緥
+
+鐐瑰嚮鏌ョ湅锛歔https://hellouniapp.dcloud.net.cn/pages/extUI/calendar/calendar](https://hellouniapp.dcloud.net.cn/pages/extUI/calendar/calendar)
diff --git a/app/uni_modules/uni-card/changelog.md b/app/uni_modules/uni-card/changelog.md
new file mode 100644
index 0000000..c3cd8c4
--- /dev/null
+++ b/app/uni_modules/uni-card/changelog.md
@@ -0,0 +1,26 @@
+## 1.3.1锛�2021-12-20锛�
+- 淇 鍦╲ue椤甸潰涓嬬暐缂╁浘鏄剧ず涓嶆甯哥殑bug
+## 1.3.0锛�2021-11-19锛�
+- 閲嶆瀯鎻掓Ы鐨勭敤娉� 锛宧eader 鏇挎崲涓� title
+- 鏂板 actions 鎻掓Ы
+- 鏂板 cover 灏侀潰鍥惧睘鎬у拰鎻掓Ы
+- 鏂板 padding 鍐呭榛樿鍐呰竟璺濈
+- 鏂板 margin 鍗$墖榛樿澶栬竟璺濈
+- 鏂板 spacing 鍗$墖榛樿鍐呰竟璺�
+- 鏂板 shadow 鍗$墖闃村奖灞炴��
+- 鍙栨秷 mode 灞炴�э紝鍙娇鐢ㄧ粍鍚堟彃妲戒唬鏇�
+- 鍙栨秷 note 灞炴�� 锛屼娇鐢╝ctions鎻掓Ы浠f浛
+- 浼樺寲 缁勪欢UI锛屽苟鎻愪緵璁捐璧勬簮锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 鏂囨。杩佺Щ锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/uni-card](https://uniapp.dcloud.io/component/uniui/uni-card)
+## 1.2.1锛�2021-07-30锛�
+- 浼樺寲 vue3涓嬩簨浠惰鍛婄殑闂
+## 1.2.0锛�2021-07-13锛�
+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤簐ue3椤圭洰璇﹁ [uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+## 1.1.8锛�2021-07-01锛�
+- 浼樺寲 鍥炬枃鍗$墖鏃犲浘鐗囧姞杞芥椂锛屾彁渚涘崰浣嶅浘鏍�
+- 鏂板 header 鎻掓Ы锛岃嚜瀹氫箟鍗$墖澶撮儴锛� 鍥炬枃鍗$墖 mode="style" 鏃讹紝涓嶆敮鎸侊級
+- 淇 thumbnail 涓嶅瓨鍦ㄤ粛鐒跺崰浣嶇殑 bug
+## 1.1.7锛�2021-05-12锛�
+- 鏂板 缁勪欢绀轰緥鍦板潃
+## 1.1.6锛�2021-02-04锛�
+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
diff --git a/app/uni_modules/uni-card/components/uni-card/uni-card.vue b/app/uni_modules/uni-card/components/uni-card/uni-card.vue
new file mode 100644
index 0000000..88d8342
--- /dev/null
+++ b/app/uni_modules/uni-card/components/uni-card/uni-card.vue
@@ -0,0 +1,272 @@
+<template>
+ <view class="uni-card" :class="{ 'uni-card--full': isFull, 'uni-card--shadow': isShadow,'uni-card--border':border}"
+ :style="{'margin':isFull?0:margin,'padding':spacing,'box-shadow':isShadow?shadow:''}">
+ <!-- 灏侀潰 -->
+ <slot name="cover">
+ <view v-if="cover" class="uni-card__cover">
+ <image class="uni-card__cover-image" mode="widthFix" @click="onClick('cover')" :src="cover"></image>
+ </view>
+ </slot>
+ <slot name="title">
+ <view v-if="title || extra" class="uni-card__header">
+ <!-- 鍗$墖鏍囬 -->
+ <view class="uni-card__header-box" @click="onClick('title')">
+ <view v-if="thumbnail" class="uni-card__header-avatar">
+ <image class="uni-card__header-avatar-image" :src="thumbnail" mode="aspectFit" />
+ </view>
+ <view class="uni-card__header-content">
+ <text class="uni-card__header-content-title uni-ellipsis">{{ title }}</text>
+ <text v-if="title&&subTitle"
+ class="uni-card__header-content-subtitle uni-ellipsis">{{ subTitle }}</text>
+ </view>
+ </view>
+ <view class="uni-card__header-extra" @click="onClick('extra')">
+ <slot name="extra">
+ <text class="uni-card__header-extra-text">{{ extra }}</text>
+ </slot>
+ </view>
+ </view>
+ </slot>
+ <!-- 鍗$墖鍐呭 -->
+ <view class="uni-card__content" :style="{padding:padding}" @click="onClick('content')">
+ <slot></slot>
+ </view>
+ <view class="uni-card__actions" @click="onClick('actions')">
+ <slot name="actions"></slot>
+ </view>
+ </view>
+</template>
+
+<script>
+ /**
+ * Card 鍗$墖
+ * @description 鍗$墖瑙嗗浘缁勪欢
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=22
+ * @property {String} title 鏍囬鏂囧瓧
+ * @property {String} subTitle 鍓爣棰�
+ * @property {Number} padding 鍐呭鍐呰竟璺�
+ * @property {Number} margin 鍗$墖澶栬竟璺�
+ * @property {Number} spacing 鍗$墖鍐呰竟璺�
+ * @property {String} extra 鏍囬棰濆淇℃伅
+ * @property {String} cover 灏侀潰鍥撅紙鏈湴璺緞闇�瑕佸紩鍏ワ級
+ * @property {String} thumbnail 鏍囬宸︿晶缂╃暐鍥�
+ * @property {Boolean} is-full = [true | false] 鍗$墖鍐呭鏄惁閫氭爮锛屼负 true 鏃跺皢鍘婚櫎padding鍊�
+ * @property {Boolean} is-shadow = [true | false] 鍗$墖鍐呭鏄惁寮�鍚槾褰�
+ * @property {String} shadow 鍗$墖闃村奖
+ * @property {Boolean} border 鍗$墖杈规
+ * @event {Function} click 鐐瑰嚮 Card 瑙﹀彂浜嬩欢
+ */
+ export default {
+ name: 'UniCard',
+ emits: ['click'],
+ props: {
+ title: {
+ type: String,
+ default: ''
+ },
+ subTitle: {
+ type: String,
+ default: ''
+ },
+ padding: {
+ type: String,
+ default: '10px'
+ },
+ margin: {
+ type: String,
+ default: '15px'
+ },
+ spacing: {
+ type: String,
+ default: '0 10px'
+ },
+ extra: {
+ type: String,
+ default: ''
+ },
+ cover: {
+ type: String,
+ default: ''
+ },
+ thumbnail: {
+ type: String,
+ default: ''
+ },
+ isFull: {
+ // 鍐呭鍖哄煙鏄惁閫氭爮
+ type: Boolean,
+ default: false
+ },
+ isShadow: {
+ // 鏄惁寮�鍚槾褰�
+ type: Boolean,
+ default: true
+ },
+ shadow: {
+ type: String,
+ default: '0px 0px 3px 1px rgba(0, 0, 0, 0.08)'
+ },
+ border: {
+ type: Boolean,
+ default: true
+ }
+ },
+ methods: {
+ onClick(type) {
+ this.$emit('click', type)
+ }
+ }
+ }
+</script>
+
+<style lang="scss">
+ $uni-border-3: #EBEEF5 !default;
+ $uni-shadow-base:0 0px 6px 1px rgba($color: #a5a5a5, $alpha: 0.2) !default;
+ $uni-main-color: #3a3a3a !default;
+ $uni-base-color: #6a6a6a !default;
+ $uni-secondary-color: #909399 !default;
+ $uni-spacing-sm: 8px !default;
+ $uni-border-color:$uni-border-3;
+ $uni-shadow: $uni-shadow-base;
+ $uni-card-title: 15px;
+ $uni-cart-title-color:$uni-main-color;
+ $uni-card-subtitle: 12px;
+ $uni-cart-subtitle-color:$uni-secondary-color;
+ $uni-card-spacing: 10px;
+ $uni-card-content-color: $uni-base-color;
+
+ .uni-card {
+ margin: $uni-card-spacing;
+ padding: 0 $uni-spacing-sm;
+ border-radius: 4px;
+ overflow: hidden;
+ font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, SimSun, sans-serif;
+ background-color: #fff;
+ flex: 1;
+
+ .uni-card__cover {
+ position: relative;
+ margin-top: $uni-card-spacing;
+ flex-direction: row;
+ overflow: hidden;
+ border-radius: 4px;
+ .uni-card__cover-image {
+ flex: 1;
+ // width: 100%;
+ /* #ifndef APP-PLUS */
+ vertical-align: middle;
+ /* #endif */
+ }
+ }
+
+ .uni-card__header {
+ display: flex;
+ border-bottom: 1px $uni-border-color solid;
+ flex-direction: row;
+ align-items: center;
+ padding: $uni-card-spacing;
+ overflow: hidden;
+
+ .uni-card__header-box {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex: 1;
+ flex-direction: row;
+ align-items: center;
+ overflow: hidden;
+ }
+
+ .uni-card__header-avatar {
+ width: 40px;
+ height: 40px;
+ overflow: hidden;
+ border-radius: 5px;
+ margin-right: $uni-card-spacing;
+ .uni-card__header-avatar-image {
+ flex: 1;
+ width: 40px;
+ height: 40px;
+ }
+ }
+
+ .uni-card__header-content {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: column;
+ justify-content: center;
+ flex: 1;
+ // height: 40px;
+ overflow: hidden;
+
+ .uni-card__header-content-title {
+ font-size: $uni-card-title;
+ color: $uni-cart-title-color;
+ // line-height: 22px;
+ }
+
+ .uni-card__header-content-subtitle {
+ font-size: $uni-card-subtitle;
+ margin-top: 5px;
+ color: $uni-cart-subtitle-color;
+ }
+ }
+
+ .uni-card__header-extra {
+ line-height: 12px;
+
+ .uni-card__header-extra-text {
+ font-size: 12px;
+ color: $uni-cart-subtitle-color;
+ }
+ }
+ }
+
+ .uni-card__content {
+ padding: $uni-card-spacing;
+ font-size: 14px;
+ color: $uni-card-content-color;
+ line-height: 22px;
+ }
+
+ .uni-card__actions {
+ font-size: 12px;
+ }
+ }
+
+ .uni-card--border {
+ border: 1px solid $uni-border-color;
+ }
+
+ .uni-card--shadow {
+ position: relative;
+ /* #ifndef APP-NVUE */
+ box-shadow: $uni-shadow;
+ /* #endif */
+ }
+
+ .uni-card--full {
+ margin: 0;
+ border-left-width: 0;
+ border-left-width: 0;
+ border-radius: 0;
+ }
+
+ /* #ifndef APP-NVUE */
+ .uni-card--full:after {
+ border-radius: 0;
+ }
+
+ /* #endif */
+ .uni-ellipsis {
+ /* #ifndef APP-NVUE */
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ /* #endif */
+ /* #ifdef APP-NVUE */
+ lines: 1;
+ /* #endif */
+ }
+</style>
diff --git a/app/uni_modules/uni-card/package.json b/app/uni_modules/uni-card/package.json
new file mode 100644
index 0000000..f16224d
--- /dev/null
+++ b/app/uni_modules/uni-card/package.json
@@ -0,0 +1,90 @@
+{
+ "id": "uni-card",
+ "displayName": "uni-card 鍗$墖",
+ "version": "1.3.1",
+ "description": "Card 缁勪欢锛屾彁渚涘父瑙佺殑鍗$墖鏍峰紡銆�",
+ "keywords": [
+ "uni-ui",
+ "uniui",
+ "card",
+ "",
+ "鍗$墖"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "鍓嶇缁勪欢",
+ "閫氱敤缁勪欢"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": [
+ "uni-icons",
+ "uni-scss"
+ ],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "u",
+ "鑱旂洘": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
diff --git a/app/uni_modules/uni-card/readme.md b/app/uni_modules/uni-card/readme.md
new file mode 100644
index 0000000..7434e71
--- /dev/null
+++ b/app/uni_modules/uni-card/readme.md
@@ -0,0 +1,12 @@
+
+
+## Card 鍗$墖
+> **缁勪欢鍚嶏細uni-card**
+> 浠g爜鍧楋細 `uCard`
+
+鍗$墖瑙嗗浘缁勪欢銆�
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-card)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
+
+
diff --git a/app/uni_modules/uni-collapse/changelog.md b/app/uni_modules/uni-collapse/changelog.md
new file mode 100644
index 0000000..292e4c7
--- /dev/null
+++ b/app/uni_modules/uni-collapse/changelog.md
@@ -0,0 +1,36 @@
+## 1.4.3锛�2022-01-25锛�
+- 淇 鍒濆鍖栫殑鏃跺�� 锛宱pen 灞炴�уけ鏁堢殑bug
+## 1.4.2锛�2022-01-21锛�
+- 淇 寰俊灏忕▼搴弐esize鍚庣粍浠舵敹璧风殑bug
+## 1.4.1锛�2021-11-22锛�
+- 淇 vue3涓釜鍒玸css鍙橀噺鏃犳硶鎵惧埌鐨勯棶棰�
+## 1.4.0锛�2021-11-19锛�
+- 浼樺寲 缁勪欢UI锛屽苟鎻愪緵璁捐璧勬簮锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 鏂囨。杩佺Щ锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/uni-collapse](https://uniapp.dcloud.io/component/uniui/uni-collapse)
+## 1.3.3锛�2021-08-17锛�
+- 浼樺寲 show-arrow 灞炴�ч粯璁や负true
+## 1.3.2锛�2021-08-17锛�
+- 鏂板 show-arrow 灞炴�э紝鎺у埗鏄惁鏄剧ず鍙充晶绠ご
+## 1.3.1锛�2021-07-30锛�
+- 浼樺寲 vue3涓嬪皬绋嬪簭浜嬩欢璀﹀憡鐨勯棶棰�
+## 1.3.0锛�2021-07-30锛�
+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤簐ue3椤圭洰锛岃瑙� [uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+## 1.2.2锛�2021-07-21锛�
+- 淇 鐢�1.2.0鐗堟湰寮曡捣鐨� change 浜嬩欢杩斿洖 undefined 鐨凚ug
+## 1.2.1锛�2021-07-21锛�
+- 浼樺寲 缁勪欢绀轰緥
+## 1.2.0锛�2021-07-21锛�
+- 鏂板 缁勪欢鎶樺彔鍔ㄧ敾
+- 鏂板 value\v-model 灞炴�� 锛屽姩鎬佷慨鏀归潰鏉挎姌鍙犵姸鎬�
+- 鏂板 title 鎻掓Ы 锛屽彲瀹氫箟闈㈡澘鏍囬
+- 鏂板 border 灞炴�� 锛屾樉绀洪殣钘忛潰鏉垮唴瀹瑰垎闅旂嚎
+- 鏂板 title-border 灞炴�� 锛屾樉绀洪殣钘忛潰鏉挎爣棰樺垎闅旂嚎
+- 淇 resize 鏂规硶澶辨晥鐨凚ug
+- 淇 change 浜嬩欢杩斿洖鍙傛暟涓嶆纭殑Bug
+- 浼樺寲 H5銆丄pp 骞冲彴鑷姩鏇村叿鍐呭鏇存柊楂樺害锛屾棤闇�璋冪敤 reszie() 鏂规硶
+## 1.1.7锛�2021-05-12锛�
+- 鏂板 缁勪欢绀轰緥鍦板潃
+## 1.1.6锛�2021-02-05锛�
+- 浼樺寲 缁勪欢寮曠敤鍏崇郴锛岄�氳繃uni_modules寮曠敤缁勪欢
+## 1.1.5锛�2021-02-05锛�
+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
\ No newline at end of file
diff --git a/app/uni_modules/uni-collapse/components/uni-collapse-item/uni-collapse-item.vue b/app/uni_modules/uni-collapse/components/uni-collapse-item/uni-collapse-item.vue
new file mode 100644
index 0000000..d62a6a7
--- /dev/null
+++ b/app/uni_modules/uni-collapse/components/uni-collapse-item/uni-collapse-item.vue
@@ -0,0 +1,402 @@
+<template>
+ <view class="uni-collapse-item">
+ <!-- onClick(!isOpen) -->
+ <view @click="onClick(!isOpen)" class="uni-collapse-item__title"
+ :class="{'is-open':isOpen &&titleBorder === 'auto' ,'uni-collapse-item-border':titleBorder !== 'none'}">
+ <view class="uni-collapse-item__title-wrap">
+ <slot name="title">
+ <view class="uni-collapse-item__title-box" :class="{'is-disabled':disabled}">
+ <image v-if="thumb" :src="thumb" class="uni-collapse-item__title-img" />
+ <text class="uni-collapse-item__title-text">{{ title }}</text>
+ </view>
+ </slot>
+ </view>
+ <view v-if="showArrow"
+ :class="{ 'uni-collapse-item__title-arrow-active': isOpen, 'uni-collapse-item--animation': showAnimation === true }"
+ class="uni-collapse-item__title-arrow">
+ <uni-icons :color="disabled?'#ddd':'#bbb'" size="14" type="bottom" />
+ </view>
+ </view>
+ <view class="uni-collapse-item__wrap" :class="{'is--transition':showAnimation}"
+ :style="{height: (isOpen?height:0) +'px'}">
+ <view :id="elId" ref="collapse--hook" class="uni-collapse-item__wrap-content"
+ :class="{open:isheight,'uni-collapse-item--border':border&&isOpen}">
+ <slot></slot>
+ </view>
+ </view>
+
+ </view>
+</template>
+
+<script>
+ // #ifdef APP-NVUE
+ const dom = weex.requireModule('dom')
+ // #endif
+ /**
+ * CollapseItem 鎶樺彔闈㈡澘瀛愮粍浠�
+ * @description 鎶樺彔闈㈡澘瀛愮粍浠�
+ * @property {String} title 鏍囬鏂囧瓧
+ * @property {String} thumb 鏍囬宸︿晶缂╃暐鍥�
+ * @property {String} name 鍞竴鏍囧織绗�
+ * @property {Boolean} open = [true|false] 鏄惁灞曞紑缁勪欢
+ * @property {Boolean} titleBorder = [true|false] 鏄惁鏄剧ず鏍囬鍒嗛殧绾�
+ * @property {Boolean} border = [true|false] 鏄惁鏄剧ず鍒嗛殧绾�
+ * @property {Boolean} disabled = [true|false] 鏄惁灞曞紑闈㈡澘
+ * @property {Boolean} showAnimation = [true|false] 寮�鍚姩鐢�
+ * @property {Boolean} showArrow = [true|false] 鏄惁鏄剧ず鍙充晶绠ご
+ */
+ export default {
+ name: 'uniCollapseItem',
+ props: {
+ // 鍒楄〃鏍囬
+ title: {
+ type: String,
+ default: ''
+ },
+ name: {
+ type: [Number, String],
+ default: ''
+ },
+ // 鏄惁绂佺敤
+ disabled: {
+ type: Boolean,
+ default: false
+ },
+ // #ifdef APP-PLUS
+ // 鏄惁鏄剧ず鍔ㄧ敾,app 绔粯璁や笉寮�鍚姩鐢伙紝鍗¢】涓ラ噸
+ showAnimation: {
+ type: Boolean,
+ default: false
+ },
+ // #endif
+ // #ifndef APP-PLUS
+ // 鏄惁鏄剧ず鍔ㄧ敾
+ showAnimation: {
+ type: Boolean,
+ default: true
+ },
+ // #endif
+ // 鏄惁灞曞紑
+ open: {
+ type: Boolean,
+ default: false
+ },
+ // 缂╃暐鍥�
+ thumb: {
+ type: String,
+ default: ''
+ },
+ // 鏍囬鍒嗛殧绾挎樉绀虹被鍨�
+ titleBorder: {
+ type: String,
+ default: 'auto'
+ },
+ border: {
+ type: Boolean,
+ default: true
+ },
+ showArrow: {
+ type: Boolean,
+ default: true
+ }
+ },
+ data() {
+ // TODO 闅忔満鐢熺敓鍏冪礌ID锛岃В鍐崇櫨搴﹀皬绋嬪簭鑾峰彇鍚屼竴涓厓绱犱綅缃俊鎭殑bug
+ const elId = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`
+ return {
+ isOpen: false,
+ isheight: null,
+ height: 0,
+ elId,
+ nameSync: 0
+ }
+ },
+ watch: {
+ open(val) {
+ this.isOpen = val
+ this.onClick(val, 'init')
+ }
+ },
+ updated(e) {
+ this.$nextTick(() => {
+ this.init(true)
+ })
+ },
+ created() {
+ this.collapse = this.getCollapse()
+ this.oldHeight = 0
+ this.onClick(this.open, 'init')
+ },
+ // #ifndef VUE3
+ // TODO vue2
+ destroyed() {
+ if (this.__isUnmounted) return
+ this.uninstall()
+ },
+ // #endif
+ // #ifdef VUE3
+ // TODO vue3
+ unmounted() {
+ this.__isUnmounted = true
+ this.uninstall()
+ },
+ // #endif
+ mounted() {
+ if (!this.collapse) return
+ if (this.name !== '') {
+ this.nameSync = this.name
+ } else {
+ this.nameSync = this.collapse.childrens.length + ''
+ }
+ if (this.collapse.names.indexOf(this.nameSync) === -1) {
+ this.collapse.names.push(this.nameSync)
+ } else {
+ console.warn(`name 鍊� ${this.nameSync} 閲嶅`);
+ }
+ if (this.collapse.childrens.indexOf(this) === -1) {
+ this.collapse.childrens.push(this)
+ }
+ this.init()
+ },
+ methods: {
+ init(type) {
+ // #ifndef APP-NVUE
+ this.getCollapseHeight(type)
+ // #endif
+ // #ifdef APP-NVUE
+ this.getNvueHwight(type)
+ // #endif
+ },
+ uninstall() {
+ if (this.collapse) {
+ this.collapse.childrens.forEach((item, index) => {
+ if (item === this) {
+ this.collapse.childrens.splice(index, 1)
+ }
+ })
+ this.collapse.names.forEach((item, index) => {
+ if (item === this.nameSync) {
+ this.collapse.names.splice(index, 1)
+ }
+ })
+ }
+ },
+ onClick(isOpen, type) {
+ if (this.disabled) return
+ this.isOpen = isOpen
+ if (this.isOpen && this.collapse) {
+ this.collapse.setAccordion(this)
+ }
+ if (type !== 'init') {
+ this.collapse.onChange(isOpen, this)
+ }
+ },
+ getCollapseHeight(type, index = 0) {
+ const views = uni.createSelectorQuery().in(this)
+ views
+ .select(`#${this.elId}`)
+ .fields({
+ size: true
+ }, data => {
+ // TODO 鐧惧害涓彲鑳借幏鍙栦笉鍒拌妭鐐逛俊鎭� 锛岄渶瑕佸惊鐜幏鍙�
+ if (index >= 10) return
+ if (!data) {
+ index++
+ this.getCollapseHeight(false, index)
+ return
+ }
+ // #ifdef APP-NVUE
+ this.height = data.height + 1
+ // #endif
+ // #ifndef APP-NVUE
+ this.height = data.height
+ // #endif
+ this.isheight = true
+ if (type) return
+ this.onClick(this.isOpen, 'init')
+ })
+ .exec()
+ },
+ getNvueHwight(type) {
+ const result = dom.getComponentRect(this.$refs['collapse--hook'], option => {
+ if (option && option.result && option.size) {
+ // #ifdef APP-NVUE
+ this.height = option.size.height + 1
+ // #endif
+ // #ifndef APP-NVUE
+ this.height = option.size.height
+ // #endif
+ this.isheight = true
+ if (type) return
+ this.onClick(this.open, 'init')
+ }
+ })
+ },
+ /**
+ * 鑾峰彇鐖跺厓绱犲疄渚�
+ */
+ getCollapse(name = 'uniCollapse') {
+ let parent = this.$parent;
+ let parentName = parent.$options.name;
+ while (parentName !== name) {
+ parent = parent.$parent;
+ if (!parent) return false;
+ parentName = parent.$options.name;
+ }
+ return parent;
+ }
+ }
+ }
+</script>
+
+<style lang="scss">
+ .uni-collapse-item {
+ /* #ifndef APP-NVUE */
+ box-sizing: border-box;
+
+ /* #endif */
+ &__title {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ width: 100%;
+ box-sizing: border-box;
+ /* #endif */
+ flex-direction: row;
+ align-items: center;
+ transition: border-bottom-color .3s;
+
+ // transition-property: border-bottom-color;
+ // transition-duration: 5s;
+ &-wrap {
+ width: 100%;
+ flex: 1;
+
+ }
+
+ &-box {
+ padding: 0 15px;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ width: 100%;
+ box-sizing: border-box;
+ /* #endif */
+ flex-direction: row;
+ justify-content: space-between;
+ align-items: center;
+ height: 48px;
+ line-height: 48px;
+ background-color: #fff;
+ color: #303133;
+ font-size: 13px;
+ font-weight: 500;
+ /* #ifdef H5 */
+ cursor: pointer;
+ outline: none;
+
+ /* #endif */
+ &.is-disabled {
+ .uni-collapse-item__title-text {
+ color: #999;
+ }
+ }
+
+ }
+
+ &.uni-collapse-item-border {
+ border-bottom: 1px solid #ebeef5;
+ }
+
+ &.is-open {
+ border-bottom-color: transparent;
+ }
+
+ &-img {
+ height: 22px;
+ width: 22px;
+ margin-right: 10px;
+ }
+
+ &-text {
+ flex: 1;
+ font-size: 14px;
+ /* #ifndef APP-NVUE */
+ white-space: nowrap;
+ color: inherit;
+ /* #endif */
+ /* #ifdef APP-NVUE */
+ lines: 1;
+ /* #endif */
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+
+ &-arrow {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ box-sizing: border-box;
+ /* #endif */
+ align-items: center;
+ justify-content: center;
+ width: 20px;
+ height: 20px;
+ margin-right: 10px;
+ transform: rotate(0deg);
+
+ &-active {
+ transform: rotate(-180deg);
+ }
+ }
+
+
+ }
+
+ &__wrap {
+ /* #ifndef APP-NVUE */
+ will-change: height;
+ box-sizing: border-box;
+ /* #endif */
+ background-color: #fff;
+ overflow: hidden;
+ position: relative;
+ height: 0;
+
+ &.is--transition {
+ // transition: all 0.3s;
+ transition-property: height, border-bottom-width;
+ transition-duration: 0.3s;
+ /* #ifndef APP-NVUE */
+ will-change: height;
+ /* #endif */
+ }
+
+
+
+ &-content {
+ position: absolute;
+ font-size: 13px;
+ color: #303133;
+ // transition: height 0.3s;
+ border-bottom-color: transparent;
+ border-bottom-style: solid;
+ border-bottom-width: 0;
+
+ &.uni-collapse-item--border {
+ border-bottom-width: 1px;
+ border-bottom-color: red;
+ border-bottom-color: #ebeef5;
+ }
+
+ &.open {
+ position: relative;
+ }
+ }
+ }
+
+ &--animation {
+ transition-property: transform;
+ transition-duration: 0.3s;
+ transition-timing-function: ease;
+ }
+
+ }
+</style>
diff --git a/app/uni_modules/uni-collapse/components/uni-collapse/uni-collapse.vue b/app/uni_modules/uni-collapse/components/uni-collapse/uni-collapse.vue
new file mode 100644
index 0000000..384c39a
--- /dev/null
+++ b/app/uni_modules/uni-collapse/components/uni-collapse/uni-collapse.vue
@@ -0,0 +1,147 @@
+<template>
+ <view class="uni-collapse">
+ <slot />
+ </view>
+</template>
+<script>
+ /**
+ * Collapse 鎶樺彔闈㈡澘
+ * @description 灞曠ず鍙互鎶樺彔 / 灞曞紑鐨勫唴瀹瑰尯鍩�
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=23
+ * @property {String|Array} value 褰撳墠婵�娲婚潰鏉挎敼鍙樻椂瑙﹀彂(濡傛灉鏄墜椋庣惔妯″紡锛屽弬鏁扮被鍨嬩负string锛屽惁鍒欎负array)
+ * @property {Boolean} accordion = [true|false] 鏄惁寮�鍚墜椋庣惔鏁堟灉鏄惁寮�鍚墜椋庣惔鏁堟灉
+ * @event {Function} change 鍒囨崲闈㈡澘鏃惰Е鍙戯紝濡傛灉鏄墜椋庣惔妯″紡锛岃繑鍥炵被鍨嬩负string锛屽惁鍒欎负array
+ */
+ export default {
+ name: 'uniCollapse',
+ emits:['change','activeItem','input','update:modelValue'],
+ props: {
+ value: {
+ type: [String, Array],
+ default: ''
+ },
+ modelValue: {
+ type: [String, Array],
+ default: ''
+ },
+ accordion: {
+ // 鏄惁寮�鍚墜椋庣惔鏁堟灉
+ type: [Boolean, String],
+ default: false
+ },
+ },
+ data() {
+ return {}
+ },
+ computed: {
+ // TODO 鍏煎 vue2 鍜� vue3
+ dataValue() {
+ let value = (typeof this.value === 'string' && this.value === '') ||
+ (Array.isArray(this.value) && this.value.length === 0)
+ let modelValue = (typeof this.modelValue === 'string' && this.modelValue === '') ||
+ (Array.isArray(this.modelValue) && this.modelValue.length === 0)
+ if (value) {
+ return this.modelValue
+ }
+ if (modelValue) {
+ return this.value
+ }
+
+ return this.value
+ }
+ },
+ watch: {
+ dataValue(val) {
+ this.setOpen(val)
+ }
+ },
+ created() {
+ this.childrens = []
+ this.names = []
+ },
+ mounted() {
+ this.$nextTick(()=>{
+ this.setOpen(this.dataValue)
+ })
+ },
+ methods: {
+ setOpen(val) {
+ let str = typeof val === 'string'
+ let arr = Array.isArray(val)
+ this.childrens.forEach((vm, index) => {
+ if (str) {
+ if (val === vm.nameSync) {
+ if (!this.accordion) {
+ console.warn('accordion 灞炴�т负 false ,v-model 绫诲瀷搴旇涓� array')
+ return
+ }
+ vm.isOpen = true
+ }
+ }
+ if (arr) {
+ val.forEach(v => {
+ if (v === vm.nameSync) {
+ if (this.accordion) {
+ console.warn('accordion 灞炴�т负 true ,v-model 绫诲瀷搴旇涓� string')
+ return
+ }
+ vm.isOpen = true
+ }
+ })
+ }
+ })
+ this.emit(val)
+ },
+ setAccordion(self) {
+ if (!this.accordion) return
+ this.childrens.forEach((vm, index) => {
+ if (self !== vm) {
+ vm.isOpen = false
+ }
+ })
+ },
+ resize() {
+ this.childrens.forEach((vm, index) => {
+ // #ifndef APP-NVUE
+ vm.getCollapseHeight()
+ // #endif
+ // #ifdef APP-NVUE
+ vm.getNvueHwight()
+ // #endif
+ })
+ },
+ onChange(isOpen, self) {
+ let activeItem = []
+
+ if (this.accordion) {
+ activeItem = isOpen ? self.nameSync : ''
+ } else {
+ this.childrens.forEach((vm, index) => {
+ if (vm.isOpen) {
+ activeItem.push(vm.nameSync)
+ }
+ })
+ }
+ this.$emit('change', activeItem)
+ this.emit(activeItem)
+ },
+ emit(val){
+ this.$emit('input', val)
+ this.$emit('update:modelValue', val)
+ }
+ }
+ }
+</script>
+<style lang="scss" >
+ .uni-collapse {
+ /* #ifndef APP-NVUE */
+ width: 100%;
+ display: flex;
+ /* #endif */
+ /* #ifdef APP-NVUE */
+ flex: 1;
+ /* #endif */
+ flex-direction: column;
+ background-color: #fff;
+ }
+</style>
diff --git a/app/uni_modules/uni-collapse/package.json b/app/uni_modules/uni-collapse/package.json
new file mode 100644
index 0000000..65349cf
--- /dev/null
+++ b/app/uni_modules/uni-collapse/package.json
@@ -0,0 +1,89 @@
+{
+ "id": "uni-collapse",
+ "displayName": "uni-collapse 鎶樺彔闈㈡澘",
+ "version": "1.4.3",
+ "description": "Collapse 缁勪欢锛屽彲浠ユ姌鍙� / 灞曞紑鐨勫唴瀹瑰尯鍩熴��",
+ "keywords": [
+ "uni-ui",
+ "鎶樺彔",
+ "鎶樺彔闈㈡澘",
+ "鎵嬮鐞�"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "鍓嶇缁勪欢",
+ "閫氱敤缁勪欢"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": [
+ "uni-scss",
+ "uni-icons"
+ ],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "u",
+ "鑱旂洘": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
diff --git a/app/uni_modules/uni-collapse/readme.md b/app/uni_modules/uni-collapse/readme.md
new file mode 100644
index 0000000..bc758eb
--- /dev/null
+++ b/app/uni_modules/uni-collapse/readme.md
@@ -0,0 +1,12 @@
+
+
+## Collapse 鎶樺彔闈㈡澘
+> **缁勪欢鍚嶏細uni-collapse**
+> 浠g爜鍧楋細 `uCollapse`
+> 鍏宠仈缁勪欢锛歚uni-collapse-item`銆乣uni-icons`銆�
+
+
+鎶樺彔闈㈡澘鐢ㄦ潵鎶樺彔/鏄剧ず杩囬暱鐨勫唴瀹规垨鑰呮槸鍒楄〃銆傞�氬父鏄湪澶氬唴瀹瑰垎绫婚」浣跨敤锛屾姌鍙犱笉閲嶈鐨勫唴瀹癸紝鏄剧ず閲嶈鍐呭銆傜偣鍑诲彲浠ュ睍寮�鎶樺彔閮ㄥ垎銆�
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-collapse)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
\ No newline at end of file
diff --git a/app/uni_modules/uni-combox/changelog.md b/app/uni_modules/uni-combox/changelog.md
new file mode 100644
index 0000000..23c2748
--- /dev/null
+++ b/app/uni_modules/uni-combox/changelog.md
@@ -0,0 +1,15 @@
+## 1.0.1锛�2021-11-23锛�
+- 浼樺寲 label銆乴abel-width 灞炴��
+## 1.0.0锛�2021-11-19锛�
+- 浼樺寲 缁勪欢UI锛屽苟鎻愪緵璁捐璧勬簮锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 鏂囨。杩佺Щ锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/uni-combox](https://uniapp.dcloud.io/component/uniui/uni-combox)
+## 0.1.0锛�2021-07-30锛�
+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤簐ue3椤圭洰锛岃瑙� [uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+## 0.0.6锛�2021-05-12锛�
+- 鏂板 缁勪欢绀轰緥鍦板潃
+## 0.0.5锛�2021-04-21锛�
+- 浼樺寲 娣诲姞渚濊禆 uni-icons, 瀵煎叆鍚庤嚜鍔ㄤ笅杞戒緷璧�
+## 0.0.4锛�2021-02-05锛�
+- 浼樺寲 缁勪欢寮曠敤鍏崇郴锛岄�氳繃uni_modules寮曠敤缁勪欢
+## 0.0.3锛�2021-02-04锛�
+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
diff --git a/app/uni_modules/uni-combox/components/uni-combox/uni-combox.vue b/app/uni_modules/uni-combox/components/uni-combox/uni-combox.vue
new file mode 100644
index 0000000..83454e5
--- /dev/null
+++ b/app/uni_modules/uni-combox/components/uni-combox/uni-combox.vue
@@ -0,0 +1,294 @@
+<template>
+ <view class="uni-combox" :class="border ? '' : 'uni-combox__no-border'">
+ <view v-if="label" class="uni-combox__label" :style="labelStyle">
+ <text>{{label}}</text>
+ </view>
+ <view class="uni-combox__input-box">
+ <input class="uni-combox__input" type="text" :placeholder="placeholder"
+ placeholder-class="uni-combox__input-plac" v-model="inputVal" @input="onInput" @focus="onFocus" @blur="onBlur" />
+ <uni-icons :type="showSelector? 'top' : 'bottom'" size="14" color="#999" @click="toggleSelector">
+ </uni-icons>
+ </view>
+ <view class="uni-combox__selector" v-if="showSelector">
+ <view class="uni-popper__arrow"></view>
+ <scroll-view scroll-y="true" class="uni-combox__selector-scroll" @scroll="onScroll">
+ <view class="uni-combox__selector-empty" v-if="filterCandidatesLength === 0">
+ <text>{{emptyTips}}</text>
+ </view>
+ <view class="uni-combox__selector-item" v-for="(item,index) in filterCandidates" :key="index" @click="onSelectorClick(index)">
+ <text>{{item}}</text>
+ </view>
+ </scroll-view>
+ </view>
+ <!-- 鏂板钂欏眰锛岀偣鍑昏挋灞傛椂鍏抽棴閫夐」鏄剧ず -->
+ <view class="uni-combox__mask" v-show="showSelector" @click="showSelector = false"></view>
+ </view>
+</template>
+
+<script>
+ /**
+ * Combox 缁勫悎杈撳叆妗�
+ * @description 缁勫悎杈撳叆妗嗕竴鑸敤浜庢棦鍙互杈撳叆涔熷彲浠ラ�夋嫨鐨勫満鏅�
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=1261
+ * @property {String} label 宸︿晶鏂囧瓧
+ * @property {String} labelWidth 宸︿晶鍐呭瀹藉害
+ * @property {String} placeholder 杈撳叆妗嗗崰浣嶇
+ * @property {Array} candidates 鍊欓�夐」鍒楄〃
+ * @property {String} emptyTips 绛涢�夌粨鏋滀负绌烘椂鏄剧ず鐨勬枃瀛�
+ * @property {String} value 缁勫悎妗嗙殑鍊�
+ */
+ export default {
+ name: 'uniCombox',
+ emits: ['input', 'update:modelValue'],
+ props: {
+ border: {
+ type: Boolean,
+ default: true
+ },
+ label: {
+ type: String,
+ default: ''
+ },
+ labelWidth: {
+ type: String,
+ default: 'auto'
+ },
+ placeholder: {
+ type: String,
+ default: ''
+ },
+ candidates: {
+ type: Array,
+ default () {
+ return []
+ }
+ },
+ emptyTips: {
+ type: String,
+ default: '鏃犲尮閰嶉」'
+ },
+ // #ifndef VUE3
+ value: {
+ type: [String, Number],
+ default: ''
+ },
+ // #endif
+ // #ifdef VUE3
+ modelValue: {
+ type: [String, Number],
+ default: ''
+ },
+ // #endif
+ },
+ data() {
+ return {
+ showSelector: false,
+ inputVal: '',
+ blurTimer:null,
+ }
+ },
+ computed: {
+ labelStyle() {
+ if (this.labelWidth === 'auto') {
+ return ""
+ }
+ return `width: ${this.labelWidth}`
+ },
+ filterCandidates() {
+ if (this.inputVal !== 0 && !this.inputVal) {
+ return this.candidates
+ }
+ return this.candidates.filter((item) => {
+ return item.toString().indexOf(this.inputVal) > -1
+ })
+ },
+ filterCandidatesLength() {
+ return this.filterCandidates.length
+ }
+ },
+ watch: {
+ // #ifndef VUE3
+ value: {
+ handler(newVal) {
+ this.inputVal = newVal
+ },
+ immediate: true
+ },
+ // #endif
+ // #ifdef VUE3
+ modelValue: {
+ handler(newVal) {
+ this.inputVal = newVal
+ },
+ immediate: true
+ },
+ // #endif
+ },
+ methods: {
+ toggleSelector() {
+ this.showSelector = !this.showSelector
+ },
+ onFocus() {
+ this.showSelector = true
+ },
+ onBlur() {
+ this.blurTimer = setTimeout(() => {
+ this.showSelector = false
+ }, 153)
+ },
+ onScroll(){ // 婊氬姩鏃跺皢blur鐨勫畾鏃跺櫒鍏虫帀
+ if(this.blurTimer) {
+ clearTimeout(this.blurTimer)
+ this.blurTimer = null
+ }
+ },
+ onSelectorClick(index) {
+ this.inputVal = this.filterCandidates[index]
+ this.showSelector = false
+ this.$emit('input', this.inputVal)
+ this.$emit('update:modelValue', this.inputVal)
+ },
+ onInput() {
+ setTimeout(() => {
+ this.$emit('input', this.inputVal)
+ this.$emit('update:modelValue', this.inputVal)
+ })
+ }
+ }
+ }
+</script>
+
+<style lang="scss">
+ .uni-combox {
+ font-size: 14px;
+ border: 1px solid #DCDFE6;
+ border-radius: 4px;
+ padding: 6px 10px;
+ position: relative;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ // height: 40px;
+ flex-direction: row;
+ align-items: center;
+ // border-bottom: solid 1px #DDDDDD;
+ }
+
+ .uni-combox__label {
+ font-size: 16px;
+ line-height: 22px;
+ padding-right: 10px;
+ color: #999999;
+ }
+
+ .uni-combox__input-box {
+ position: relative;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex: 1;
+ flex-direction: row;
+ align-items: center;
+ }
+
+ .uni-combox__input {
+ flex: 1;
+ font-size: 14px;
+ height: 22px;
+ line-height: 22px;
+ }
+
+ .uni-combox__input-plac {
+ font-size: 14px;
+ color: #999;
+ }
+
+ .uni-combox__selector {
+ /* #ifndef APP-NVUE */
+ box-sizing: border-box;
+ /* #endif */
+ position: absolute;
+ top: calc(100% + 12px);
+ left: 0;
+ width: 100%;
+ background-color: #FFFFFF;
+ border: 1px solid #EBEEF5;
+ border-radius: 6px;
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+ z-index: 3;
+ padding: 4px 0;
+ }
+
+ .uni-combox__selector-scroll {
+ /* #ifndef APP-NVUE */
+ max-height: 200px;
+ box-sizing: border-box;
+ /* #endif */
+ }
+
+ .uni-combox__selector-empty,
+ .uni-combox__selector-item {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ cursor: pointer;
+ /* #endif */
+ line-height: 36px;
+ font-size: 14px;
+ text-align: center;
+ // border-bottom: solid 1px #DDDDDD;
+ padding: 0px 10px;
+ }
+
+ .uni-combox__selector-item:hover {
+ background-color: #f9f9f9;
+ }
+
+ .uni-combox__selector-empty:last-child,
+ .uni-combox__selector-item:last-child {
+ /* #ifndef APP-NVUE */
+ border-bottom: none;
+ /* #endif */
+ }
+
+ // picker 寮瑰嚭灞傞�氱敤鐨勬寚绀哄皬涓夎
+ .uni-popper__arrow,
+ .uni-popper__arrow::after {
+ position: absolute;
+ display: block;
+ width: 0;
+ height: 0;
+ border-color: transparent;
+ border-style: solid;
+ border-width: 6px;
+ }
+
+ .uni-popper__arrow {
+ filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03));
+ top: -6px;
+ left: 10%;
+ margin-right: 3px;
+ border-top-width: 0;
+ border-bottom-color: #EBEEF5;
+ }
+
+ .uni-popper__arrow::after {
+ content: " ";
+ top: 1px;
+ margin-left: -6px;
+ border-top-width: 0;
+ border-bottom-color: #fff;
+ }
+
+ .uni-combox__no-border {
+ border: none;
+ }
+
+ .uni-combox__mask {
+ width:100%;
+ height:100%;
+ position: fixed;
+ top: 0;
+ left: 0;
+ z-index: 1;
+ }
+</style>
diff --git a/app/uni_modules/uni-combox/package.json b/app/uni_modules/uni-combox/package.json
new file mode 100644
index 0000000..4a05c3f
--- /dev/null
+++ b/app/uni_modules/uni-combox/package.json
@@ -0,0 +1,90 @@
+{
+ "id": "uni-combox",
+ "displayName": "uni-combox 缁勫悎妗�",
+ "version": "1.0.1",
+ "description": "鍙互閫夋嫨涔熷彲浠ヨ緭鍏ョ殑琛ㄥ崟椤� ",
+ "keywords": [
+ "uni-ui",
+ "uniui",
+ "combox",
+ "缁勫悎妗�",
+ "select"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "鍓嶇缁勪欢",
+ "閫氱敤缁勪欢"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": [
+ "uni-scss",
+ "uni-icons"
+ ],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "n"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "u",
+ "鑱旂洘": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/uni_modules/uni-combox/readme.md b/app/uni_modules/uni-combox/readme.md
new file mode 100644
index 0000000..ffa2cc8
--- /dev/null
+++ b/app/uni_modules/uni-combox/readme.md
@@ -0,0 +1,11 @@
+
+
+## Combox 缁勫悎妗�
+> **缁勪欢鍚嶏細uni-combox**
+> 浠g爜鍧楋細 `uCombox`
+
+
+缁勫悎妗嗙粍浠躲��
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-combox)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
\ No newline at end of file
diff --git a/app/uni_modules/uni-countdown/changelog.md b/app/uni_modules/uni-countdown/changelog.md
new file mode 100644
index 0000000..f25beef
--- /dev/null
+++ b/app/uni_modules/uni-countdown/changelog.md
@@ -0,0 +1,24 @@
+## 1.2.2锛�2022-01-19锛�
+- 淇 鍦ㄥ井淇″皬绋嬪簭涓牱寮忎笉鐢熸晥鐨刡ug
+## 1.2.1锛�2022-01-18锛�
+- 鏂板 update 鏂规硶 锛屽湪鍔ㄦ�佹洿鏂版椂闂村悗锛屽埛鏂扮粍浠�
+## 1.2.0锛�2021-11-19锛�
+- 浼樺寲 缁勪欢UI锛屽苟鎻愪緵璁捐璧勬簮锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 鏂囨。杩佺Щ锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/uni-countdown](https://uniapp.dcloud.io/component/uniui/uni-countdown)
+## 1.1.3锛�2021-10-18锛�
+- 閲嶆瀯
+- 鏂板 font-size 鏀寔鑷畾涔夊瓧浣撳ぇ灏�
+## 1.1.2锛�2021-08-24锛�
+- 鏂板 鏀寔鍥介檯鍖�
+## 1.1.1锛�2021-07-30锛�
+- 浼樺寲 vue3涓嬪皬绋嬪簭浜嬩欢璀﹀憡鐨勯棶棰�
+## 1.1.0锛�2021-07-30锛�
+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤簐ue3椤圭洰锛岃瑙� [uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+## 1.0.5锛�2021-06-18锛�
+- 淇 uni-countdown 閲嶅璧嬪�艰烦涓ょ鐨� bug
+## 1.0.4锛�2021-05-12锛�
+- 鏂板 缁勪欢绀轰緥鍦板潃
+## 1.0.3锛�2021-05-08锛�
+- 淇 uni-countdown 涓嶈兘鎺у埗鍊掕鏃剁殑 bug
+## 1.0.2锛�2021-02-04锛�
+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
diff --git a/app/uni_modules/uni-countdown/components/uni-countdown/i18n/en.json b/app/uni_modules/uni-countdown/components/uni-countdown/i18n/en.json
new file mode 100644
index 0000000..06309cb
--- /dev/null
+++ b/app/uni_modules/uni-countdown/components/uni-countdown/i18n/en.json
@@ -0,0 +1,6 @@
+{
+ "uni-countdown.day": "day",
+ "uni-countdown.h": "h",
+ "uni-countdown.m": "m",
+ "uni-countdown.s": "s"
+}
diff --git a/app/uni_modules/uni-countdown/components/uni-countdown/i18n/index.js b/app/uni_modules/uni-countdown/components/uni-countdown/i18n/index.js
new file mode 100644
index 0000000..de7509c
--- /dev/null
+++ b/app/uni_modules/uni-countdown/components/uni-countdown/i18n/index.js
@@ -0,0 +1,8 @@
+import en from './en.json'
+import zhHans from './zh-Hans.json'
+import zhHant from './zh-Hant.json'
+export default {
+ en,
+ 'zh-Hans': zhHans,
+ 'zh-Hant': zhHant
+}
diff --git a/app/uni_modules/uni-countdown/components/uni-countdown/i18n/zh-Hans.json b/app/uni_modules/uni-countdown/components/uni-countdown/i18n/zh-Hans.json
new file mode 100644
index 0000000..358cdd1
--- /dev/null
+++ b/app/uni_modules/uni-countdown/components/uni-countdown/i18n/zh-Hans.json
@@ -0,0 +1,6 @@
+{
+ "uni-countdown.day": "澶�",
+ "uni-countdown.h": "鏃�",
+ "uni-countdown.m": "鍒�",
+ "uni-countdown.s": "绉�"
+}
diff --git a/app/uni_modules/uni-countdown/components/uni-countdown/i18n/zh-Hant.json b/app/uni_modules/uni-countdown/components/uni-countdown/i18n/zh-Hant.json
new file mode 100644
index 0000000..e5a63de
--- /dev/null
+++ b/app/uni_modules/uni-countdown/components/uni-countdown/i18n/zh-Hant.json
@@ -0,0 +1,6 @@
+{
+ "uni-countdown.day": "澶�",
+ "uni-countdown.h": "鏅�",
+ "uni-countdown.m": "鍒�",
+ "uni-countdown.s": "绉�"
+}
diff --git a/app/uni_modules/uni-countdown/components/uni-countdown/uni-countdown.vue b/app/uni_modules/uni-countdown/components/uni-countdown/uni-countdown.vue
new file mode 100644
index 0000000..65a1216
--- /dev/null
+++ b/app/uni_modules/uni-countdown/components/uni-countdown/uni-countdown.vue
@@ -0,0 +1,267 @@
+<template>
+ <view class="uni-countdown">
+ <text v-if="showDay" :style="[timeStyle]" class="uni-countdown__number">{{ d }}</text>
+ <text v-if="showDay" :style="[splitorStyle]" class="uni-countdown__splitor">{{dayText}}</text>
+ <text :style="[timeStyle]" class="uni-countdown__number">{{ h }}</text>
+ <text :style="[splitorStyle]" class="uni-countdown__splitor">{{ showColon ? ':' : hourText }}</text>
+ <text :style="[timeStyle]" class="uni-countdown__number">{{ i }}</text>
+ <text :style="[splitorStyle]" class="uni-countdown__splitor">{{ showColon ? ':' : minuteText }}</text>
+ <text :style="[timeStyle]" class="uni-countdown__number">{{ s }}</text>
+ <text v-if="!showColon" :style="[splitorStyle]" class="uni-countdown__splitor">{{secondText}}</text>
+ </view>
+</template>
+<script>
+ import {
+ initVueI18n
+ } from '@dcloudio/uni-i18n'
+ import messages from './i18n/index.js'
+ const {
+ t
+ } = initVueI18n(messages)
+ /**
+ * Countdown 鍊掕鏃�
+ * @description 鍊掕鏃剁粍浠�
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=25
+ * @property {String} backgroundColor 鑳屾櫙鑹�
+ * @property {String} color 鏂囧瓧棰滆壊
+ * @property {Number} day 澶╂暟
+ * @property {Number} hour 灏忔椂
+ * @property {Number} minute 鍒嗛挓
+ * @property {Number} second 绉�
+ * @property {Number} timestamp 鏃堕棿鎴�
+ * @property {Boolean} showDay = [true|false] 鏄惁鏄剧ず澶╂暟
+ * @property {Boolean} show-colon = [true|false] 鏄惁浠ュ啋鍙蜂负鍒嗛殧绗�
+ * @property {String} splitorColor 鍒嗗壊绗﹀彿棰滆壊
+ * @event {Function} timeup 鍊掕鏃舵椂闂村埌瑙﹀彂浜嬩欢
+ * @example <uni-countdown :day="1" :hour="1" :minute="12" :second="40"></uni-countdown>
+ */
+ export default {
+ name: 'UniCountdown',
+ emits: ['timeup'],
+ props: {
+ showDay: {
+ type: Boolean,
+ default: true
+ },
+ showColon: {
+ type: Boolean,
+ default: true
+ },
+ start: {
+ type: Boolean,
+ default: true
+ },
+ backgroundColor: {
+ type: String,
+ default: ''
+ },
+ color: {
+ type: String,
+ default: '#333'
+ },
+ fontSize: {
+ type: Number,
+ default: 14
+ },
+ splitorColor: {
+ type: String,
+ default: '#333'
+ },
+ day: {
+ type: Number,
+ default: 0
+ },
+ hour: {
+ type: Number,
+ default: 0
+ },
+ minute: {
+ type: Number,
+ default: 0
+ },
+ second: {
+ type: Number,
+ default: 0
+ },
+ timestamp: {
+ type: Number,
+ default: 0
+ },
+ zeroPad: {
+ type: Boolean,
+ default: true
+ }
+ },
+ data() {
+ return {
+ timer: null,
+ syncFlag: false,
+ d: '00',
+ h: '00',
+ i: '00',
+ s: '00',
+ leftTime: 0,
+ seconds: 0
+ }
+ },
+ computed: {
+ dayText() {
+ return t("uni-countdown.day")
+ },
+ hourText(val) {
+ return t("uni-countdown.h")
+ },
+ minuteText(val) {
+ return t("uni-countdown.m")
+ },
+ secondText(val) {
+ return t("uni-countdown.s")
+ },
+ timeStyle() {
+ const {
+ color,
+ backgroundColor,
+ fontSize
+ } = this
+ return {
+ color,
+ backgroundColor,
+ fontSize: `${fontSize}px`,
+ width: `${fontSize * 22 / 14}px`, // 鎸夊瓧浣撳ぇ灏忎负 14px 鏃剁殑姣斾緥缂╂斁
+ lineHeight: `${fontSize * 20 / 14}px`,
+ borderRadius: `${fontSize * 3 / 14}px`,
+ }
+ },
+ splitorStyle() {
+ const { splitorColor, fontSize, backgroundColor } = this
+ return {
+ color: splitorColor,
+ fontSize: `${fontSize * 12 / 14}px`,
+ margin: backgroundColor ? `${fontSize * 4 / 14}px` : ''
+ }
+ }
+ },
+ watch: {
+ day(val) {
+ this.changeFlag()
+ },
+ hour(val) {
+ this.changeFlag()
+ },
+ minute(val) {
+ this.changeFlag()
+ },
+ second(val) {
+ this.changeFlag()
+ },
+ start: {
+ immediate: true,
+ handler(newVal, oldVal) {
+ if (newVal) {
+ this.startData();
+ } else {
+ if (!oldVal) return
+ clearInterval(this.timer)
+ }
+ }
+
+ }
+ },
+ created: function(e) {
+ this.seconds = this.toSeconds(this.timestamp, this.day, this.hour, this.minute, this.second)
+ this.countDown()
+ },
+ // #ifndef VUE3
+ destroyed() {
+ clearInterval(this.timer)
+ },
+ // #endif
+ // #ifdef VUE3
+ unmounted() {
+ clearInterval(this.timer)
+ },
+ // #endif
+ methods: {
+ toSeconds(timestamp, day, hours, minutes, seconds) {
+ if (timestamp) {
+ return timestamp - parseInt(new Date().getTime() / 1000, 10)
+ }
+ return day * 60 * 60 * 24 + hours * 60 * 60 + minutes * 60 + seconds
+ },
+ timeUp() {
+ clearInterval(this.timer)
+ this.$emit('timeup')
+ },
+ countDown() {
+ let seconds = this.seconds
+ let [day, hour, minute, second] = [0, 0, 0, 0]
+ if (seconds > 0) {
+ day = Math.floor(seconds / (60 * 60 * 24))
+ hour = Math.floor(seconds / (60 * 60)) - (day * 24)
+ minute = Math.floor(seconds / 60) - (day * 24 * 60) - (hour * 60)
+ second = Math.floor(seconds) - (day * 24 * 60 * 60) - (hour * 60 * 60) - (minute * 60)
+ } else {
+ this.timeUp()
+ }
+ day = (day < 10 && this.zeroPad) ? `0${day}` : day
+ hour = (hour < 10 && this.zeroPad) ? `0${hour}` : hour
+ minute = (minute < 10 && this.zeroPad) ? `0${minute}` : minute
+ second = (second < 10 && this.zeroPad) ? `0${second}` : second
+ this.d = day
+ this.h = hour
+ this.i = minute
+ this.s = second
+ },
+ startData() {
+ this.seconds = this.toSeconds(this.timestamp, this.day, this.hour, this.minute, this.second)
+ if (this.seconds <= 0) {
+ this.seconds = this.toSeconds(0, 0, 0, 0, 0)
+ this.countDown()
+ return
+ }
+ clearInterval(this.timer)
+ this.countDown()
+ this.timer = setInterval(() => {
+ this.seconds--
+ if (this.seconds < 0) {
+ this.timeUp()
+ return
+ }
+ this.countDown()
+ }, 1000)
+ },
+ update(){
+ this.startData();
+ },
+ changeFlag() {
+ if (!this.syncFlag) {
+ this.seconds = this.toSeconds(this.timestamp, this.day, this.hour, this.minute, this.second)
+ this.startData();
+ this.syncFlag = true;
+ }
+ }
+ }
+ }
+</script>
+<style lang="scss" scoped>
+ $font-size: 14px;
+
+ .uni-countdown {
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-start;
+ align-items: center;
+
+ &__splitor {
+ margin: 0 2px;
+ font-size: $font-size;
+ color: #333;
+ }
+
+ &__number {
+ border-radius: 3px;
+ text-align: center;
+ font-size: $font-size;
+ }
+ }
+</style>
diff --git a/app/uni_modules/uni-countdown/package.json b/app/uni_modules/uni-countdown/package.json
new file mode 100644
index 0000000..70e99ee
--- /dev/null
+++ b/app/uni_modules/uni-countdown/package.json
@@ -0,0 +1,86 @@
+{
+ "id": "uni-countdown",
+ "displayName": "uni-countdown 鍊掕鏃�",
+ "version": "1.2.2",
+ "description": "CountDown 鍊掕鏃剁粍浠�",
+ "keywords": [
+ "uni-ui",
+ "uniui",
+ "countdown",
+ "鍊掕鏃�"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "鍓嶇缁勪欢",
+ "閫氱敤缁勪欢"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": ["uni-scss"],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "u",
+ "鑱旂洘": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/uni_modules/uni-countdown/readme.md b/app/uni_modules/uni-countdown/readme.md
new file mode 100644
index 0000000..4bcb1aa
--- /dev/null
+++ b/app/uni_modules/uni-countdown/readme.md
@@ -0,0 +1,10 @@
+
+
+## CountDown 鍊掕鏃�
+> **缁勪欢鍚嶏細uni-countdown**
+> 浠g爜鍧楋細 `uCountDown`
+
+鍊掕鏃剁粍浠躲��
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-countdown)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
\ No newline at end of file
diff --git a/app/uni_modules/uni-data-checkbox/changelog.md b/app/uni_modules/uni-data-checkbox/changelog.md
new file mode 100644
index 0000000..c7a468a
--- /dev/null
+++ b/app/uni_modules/uni-data-checkbox/changelog.md
@@ -0,0 +1,45 @@
+## 1.0.3锛�2022-09-16锛�
+- 鍙互浣跨敤 uni-scss 鎺у埗涓婚鑹�
+## 1.0.2锛�2022-06-30锛�
+- 浼樺寲 鍦� uni-forms 涓殑渚濊禆娉ㄥ叆鏂瑰紡
+## 1.0.1锛�2022-02-07锛�
+- 淇 multiple 涓� true 鏃讹紝v-model 鐨勫�间负 null 鎶ラ敊鐨� bug
+## 1.0.0锛�2021-11-19锛�
+- 浼樺寲 缁勪欢UI锛屽苟鎻愪緵璁捐璧勬簮锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 鏂囨。杩佺Щ锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/uni-data-checkbox](https://uniapp.dcloud.io/component/uniui/uni-data-checkbox)
+## 0.2.5锛�2021-08-23锛�
+- 淇 鍦╱ni-forms涓� modelValue 涓笉瀛樺湪褰撳墠瀛楁锛屽綋鍓嶅瓧娈靛繀濉啓涔熶笉鍙備笌鏍¢獙鐨勯棶棰�
+## 0.2.4锛�2021-08-17锛�
+- 淇 鍗曢�� list 妯″紡涓� 锛宨con 涓� left 鏃讹紝閫変腑鍥炬爣涓嶆樉绀虹殑闂
+## 0.2.3锛�2021-08-11锛�
+- 淇 鍦� uni-forms 涓噸缃〃鍗曪紝閿欒淇℃伅鏃犳硶娓呴櫎鐨勯棶棰�
+## 0.2.2锛�2021-07-30锛�
+- 浼樺寲 鍦╱ni-forms缁勪欢锛屼笌label涓嶅榻愮殑闂
+## 0.2.1锛�2021-07-27锛�
+- 淇 鍗曢�夐粯璁ゅ�间负0涓嶈兘閫変腑鐨凚ug
+## 0.2.0锛�2021-07-13锛�
+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤簐ue3椤圭洰锛岃瑙� [uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+## 0.1.11锛�2021-07-06锛�
+- 浼樺寲 鍒犻櫎鏃犵敤鏃ュ織
+## 0.1.10锛�2021-07-05锛�
+- 淇 鐢� 0.1.9 寮曡捣鐨勯潪 nvue 绔浘鏍囦笉鏄剧ず鐨勯棶棰�
+## 0.1.9锛�2021-07-05锛�
+- 淇 nvue 榛戞鏍峰紡闂
+## 0.1.8锛�2021-06-28锛�
+- 淇 selectedTextColor 灞炴�т笉鐢熸晥鐨凚ug
+## 0.1.7锛�2021-06-02锛�
+- 鏂板 map 灞炴�э紝鍙互鏂逛究鏄犲皠text/value灞炴��
+## 0.1.6锛�2021-05-26锛�
+- 淇 涓嶅叧鑱旀湇鍔$┖闂寸殑鎯呭喌涓嬬粍浠舵姤閿欑殑Bug
+## 0.1.5锛�2021-05-12锛�
+- 鏂板 缁勪欢绀轰緥鍦板潃
+## 0.1.4锛�2021-04-09锛�
+- 淇 nvue 涓嬫棤娉曢�変腑鐨勯棶棰�
+## 0.1.3锛�2021-03-22锛�
+- 鏂板 disabled灞炴��
+## 0.1.2锛�2021-02-24锛�
+- 浼樺寲 榛樿棰滆壊鏄剧ず
+## 0.1.1锛�2021-02-24锛�
+- 鏂板 鏀寔nvue
+## 0.1.0锛�2021-02-18锛�
+- 鈥滄殏鏃犳暟鎹�濇樉绀哄眳涓�
diff --git a/app/uni_modules/uni-data-checkbox/components/uni-data-checkbox/uni-data-checkbox.vue b/app/uni_modules/uni-data-checkbox/components/uni-data-checkbox/uni-data-checkbox.vue
new file mode 100644
index 0000000..3c75d9f
--- /dev/null
+++ b/app/uni_modules/uni-data-checkbox/components/uni-data-checkbox/uni-data-checkbox.vue
@@ -0,0 +1,821 @@
+<template>
+ <view class="uni-data-checklist" :style="{'margin-top':isTop+'px'}">
+ <template v-if="!isLocal">
+ <view class="uni-data-loading">
+ <uni-load-more v-if="!mixinDatacomErrorMessage" status="loading" iconType="snow" :iconSize="18" :content-text="contentText"></uni-load-more>
+ <text v-else>{{mixinDatacomErrorMessage}}</text>
+ </view>
+ </template>
+ <template v-else>
+ <checkbox-group v-if="multiple" class="checklist-group" :class="{'is-list':mode==='list' || wrap}" @change="chagne">
+ <label class="checklist-box" :class="['is--'+mode,item.selected?'is-checked':'',(disabled || !!item.disabled)?'is-disable':'',index!==0&&mode==='list'?'is-list-border':'']"
+ :style="item.styleBackgroud" v-for="(item,index) in dataList" :key="index">
+ <checkbox class="hidden" hidden :disabled="disabled || !!item.disabled" :value="item[map.value]+''" :checked="item.selected" />
+ <view v-if="(mode !=='tag' && mode !== 'list') || ( mode === 'list' && icon === 'left')" class="checkbox__inner" :style="item.styleIcon">
+ <view class="checkbox__inner-icon"></view>
+ </view>
+ <view class="checklist-content" :class="{'list-content':mode === 'list' && icon ==='left'}">
+ <text class="checklist-text" :style="item.styleIconText">{{item[map.text]}}</text>
+ <view v-if="mode === 'list' && icon === 'right'" class="checkobx__list" :style="item.styleBackgroud"></view>
+ </view>
+ </label>
+ </checkbox-group>
+ <radio-group v-else class="checklist-group" :class="{'is-list':mode==='list','is-wrap':wrap}" @change="chagne">
+ <!-- -->
+ <label class="checklist-box" :class="['is--'+mode,item.selected?'is-checked':'',(disabled || !!item.disabled)?'is-disable':'',index!==0&&mode==='list'?'is-list-border':'']"
+ :style="item.styleBackgroud" v-for="(item,index) in dataList" :key="index">
+ <radio class="hidden" hidden :disabled="disabled || item.disabled" :value="item[map.value]+''" :checked="item.selected" />
+ <view v-if="(mode !=='tag' && mode !== 'list') || ( mode === 'list' && icon === 'left')" class="radio__inner"
+ :style="item.styleBackgroud">
+ <view class="radio__inner-icon" :style="item.styleIcon"></view>
+ </view>
+ <view class="checklist-content" :class="{'list-content':mode === 'list' && icon ==='left'}">
+ <text class="checklist-text" :style="item.styleIconText">{{item[map.text]}}</text>
+ <view v-if="mode === 'list' && icon === 'right'" :style="item.styleRightIcon" class="checkobx__list"></view>
+ </view>
+ </label>
+ </radio-group>
+ </template>
+ </view>
+</template>
+
+<script>
+ /**
+ * DataChecklist 鏁版嵁閫夋嫨鍣�
+ * @description 閫氳繃鏁版嵁娓叉煋 checkbox 鍜� radio
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=xxx
+ * @property {String} mode = [default| list | button | tag] 鏄剧ず妯″紡
+ * @value default 榛樿妯帓妯″紡
+ * @value list 鍒楄〃妯″紡
+ * @value button 鎸夐挳妯″紡
+ * @value tag 鏍囩妯″紡
+ * @property {Boolean} multiple = [true|false] 鏄惁澶氶��
+ * @property {Array|String|Number} value 榛樿鍊�
+ * @property {Array} localdata 鏈湴鏁版嵁 锛屾牸寮� [{text:'',value:''}]
+ * @property {Number|String} min 鏈�灏忛�夋嫨涓暟 锛宮ultiple涓簍rue鏃剁敓鏁�
+ * @property {Number|String} max 鏈�澶ч�夋嫨涓暟 锛宮ultiple涓簍rue鏃剁敓鏁�
+ * @property {Boolean} wrap 鏄惁鎹㈣鏄剧ず
+ * @property {String} icon = [left|right] list 鍒楄〃妯″紡涓媔con鏄剧ず浣嶇疆
+ * @property {Boolean} selectedColor 閫変腑棰滆壊
+ * @property {Boolean} emptyText 娌℃湁鏁版嵁鏃舵樉绀虹殑鏂囧瓧 锛屾湰鍦版暟鎹棤鏁�
+ * @property {Boolean} selectedTextColor 閫変腑鏂囨湰棰滆壊锛屽涓嶅~鍐欏垯鑷姩鏄剧ず
+ * @property {Object} map 瀛楁鏄犲皠锛� 榛樿 map={text:'text',value:'value'}
+ * @value left 宸︿晶鏄剧ず
+ * @value right 鍙充晶鏄剧ず
+ * @event {Function} change 閫変腑鍙戠敓鍙樺寲瑙﹀彂
+ */
+
+ export default {
+ name: 'uniDataChecklist',
+ mixins: [uniCloud.mixinDatacom || {}],
+ emits:['input','update:modelValue','change'],
+ props: {
+ mode: {
+ type: String,
+ default: 'default'
+ },
+
+ multiple: {
+ type: Boolean,
+ default: false
+ },
+ value: {
+ type: [Array, String, Number],
+ default () {
+ return ''
+ }
+ },
+ // TODO vue3
+ modelValue: {
+ type: [Array, String, Number],
+ default() {
+ return '';
+ }
+ },
+ localdata: {
+ type: Array,
+ default () {
+ return []
+ }
+ },
+ min: {
+ type: [Number, String],
+ default: ''
+ },
+ max: {
+ type: [Number, String],
+ default: ''
+ },
+ wrap: {
+ type: Boolean,
+ default: false
+ },
+ icon: {
+ type: String,
+ default: 'left'
+ },
+ selectedColor: {
+ type: String,
+ default: ''
+ },
+ selectedTextColor: {
+ type: String,
+ default: ''
+ },
+ emptyText:{
+ type: String,
+ default: '鏆傛棤鏁版嵁'
+ },
+ disabled:{
+ type: Boolean,
+ default: false
+ },
+ map:{
+ type: Object,
+ default(){
+ return {
+ text:'text',
+ value:'value'
+ }
+ }
+ }
+ },
+ watch: {
+ localdata: {
+ handler(newVal) {
+ this.range = newVal
+ this.dataList = this.getDataList(this.getSelectedValue(newVal))
+ },
+ deep: true
+ },
+ mixinDatacomResData(newVal) {
+ this.range = newVal
+ this.dataList = this.getDataList(this.getSelectedValue(newVal))
+ },
+ value(newVal) {
+ this.dataList = this.getDataList(newVal)
+ // fix by mehaotian is_reset 鍦� uni-forms 涓畾涔�
+ // if(!this.is_reset){
+ // this.is_reset = false
+ // this.formItem && this.formItem.setValue(newVal)
+ // }
+ },
+ modelValue(newVal) {
+ this.dataList = this.getDataList(newVal);
+ // if(!this.is_reset){
+ // this.is_reset = false
+ // this.formItem && this.formItem.setValue(newVal)
+ // }
+ }
+ },
+ data() {
+ return {
+ dataList: [],
+ range: [],
+ contentText: {
+ contentdown: '鏌ョ湅鏇村',
+ contentrefresh: '鍔犺浇涓�',
+ contentnomore: '娌℃湁鏇村'
+ },
+ isLocal:true,
+ styles: {
+ selectedColor: '#2979ff',
+ selectedTextColor: '#666',
+ },
+ isTop:0
+ };
+ },
+ computed:{
+ dataValue(){
+ if(this.value === '')return this.modelValue
+ if(this.modelValue === '') return this.value
+ return this.value
+ }
+ },
+ created() {
+ // this.form = this.getForm('uniForms')
+ // this.formItem = this.getForm('uniFormsItem')
+ // this.formItem && this.formItem.setValue(this.value)
+
+ // if (this.formItem) {
+ // this.isTop = 6
+ // if (this.formItem.name) {
+ // // 濡傛灉瀛樺湪name娣诲姞榛樿鍊�,鍚﹀垯formData 涓笉瀛樺湪杩欎釜瀛楁涓嶆牎楠�
+ // if(!this.is_reset){
+ // this.is_reset = false
+ // this.formItem.setValue(this.dataValue)
+ // }
+ // this.rename = this.formItem.name
+ // this.form.inputChildrens.push(this)
+ // }
+ // }
+
+ if (this.localdata && this.localdata.length !== 0) {
+ this.isLocal = true
+ this.range = this.localdata
+ this.dataList = this.getDataList(this.getSelectedValue(this.range))
+ } else {
+ if (this.collection) {
+ this.isLocal = false
+ this.loadData()
+ }
+ }
+ },
+ methods: {
+ loadData() {
+ this.mixinDatacomGet().then(res=>{
+ this.mixinDatacomResData = res.result.data
+ if(this.mixinDatacomResData.length === 0){
+ this.isLocal = false
+ this.mixinDatacomErrorMessage = this.emptyText
+ }else{
+ this.isLocal = true
+ }
+ }).catch(err=>{
+ this.mixinDatacomErrorMessage = err.message
+ })
+ },
+ /**
+ * 鑾峰彇鐖跺厓绱犲疄渚�
+ */
+ getForm(name = 'uniForms') {
+ let parent = this.$parent;
+ let parentName = parent.$options.name;
+ while (parentName !== name) {
+ parent = parent.$parent;
+ if (!parent) return false
+ parentName = parent.$options.name;
+ }
+ return parent;
+ },
+ chagne(e) {
+ const values = e.detail.value
+
+ let detail = {
+ value: [],
+ data: []
+ }
+
+ if (this.multiple) {
+ this.range.forEach(item => {
+
+ if (values.includes(item[this.map.value] + '')) {
+ detail.value.push(item[this.map.value])
+ detail.data.push(item)
+ }
+ })
+ } else {
+ const range = this.range.find(item => (item[this.map.value] + '') === values)
+ if (range) {
+ detail = {
+ value: range[this.map.value],
+ data: range
+ }
+ }
+ }
+ // this.formItem && this.formItem.setValue(detail.value)
+ // TODO 鍏煎 vue2
+ this.$emit('input', detail.value);
+ // // TOTO 鍏煎 vue3
+ this.$emit('update:modelValue', detail.value);
+ this.$emit('change', {
+ detail
+ })
+ if (this.multiple) {
+ // 濡傛灉 v-model 娌℃湁缁戝畾 锛屽垯璧板唴閮ㄩ�昏緫
+ // if (this.value.length === 0) {
+ this.dataList = this.getDataList(detail.value, true)
+ // }
+ } else {
+ this.dataList = this.getDataList(detail.value)
+ }
+ },
+
+ /**
+ * 鑾峰彇娓叉煋鐨勬柊鏁扮粍
+ * @param {Object} value 閫変腑鍐呭
+ */
+ getDataList(value) {
+ // 瑙i櫎寮曠敤鍏崇郴锛岀牬鍧忓師寮曠敤鍏崇郴锛岄伩鍏嶆薄鏌撴簮鏁版嵁
+ let dataList = JSON.parse(JSON.stringify(this.range))
+ let list = []
+ if (this.multiple) {
+ if (!Array.isArray(value)) {
+ value = []
+ }
+ }
+ dataList.forEach((item, index) => {
+ item.disabled = item.disable || item.disabled || false
+ if (this.multiple) {
+ if (value.length > 0) {
+ let have = value.find(val => val === item[this.map.value])
+ item.selected = have !== undefined
+ } else {
+ item.selected = false
+ }
+ } else {
+ item.selected = value === item[this.map.value]
+ }
+
+ list.push(item)
+ })
+ return this.setRange(list)
+ },
+ /**
+ * 澶勭悊鏈�澶ф渶灏忓��
+ * @param {Object} list
+ */
+ setRange(list) {
+ let selectList = list.filter(item => item.selected)
+ let min = Number(this.min) || 0
+ let max = Number(this.max) || ''
+ list.forEach((item, index) => {
+ if (this.multiple) {
+ if (selectList.length <= min) {
+ let have = selectList.find(val => val[this.map.value] === item[this.map.value])
+ if (have !== undefined) {
+ item.disabled = true
+ }
+ }
+
+ if (selectList.length >= max && max !== '') {
+ let have = selectList.find(val => val[this.map.value] === item[this.map.value])
+ if (have === undefined) {
+ item.disabled = true
+ }
+ }
+ }
+ this.setStyles(item, index)
+ list[index] = item
+ })
+ return list
+ },
+ /**
+ * 璁剧疆 class
+ * @param {Object} item
+ * @param {Object} index
+ */
+ setStyles(item, index) {
+ // 璁剧疆鑷畾涔夋牱寮�
+ item.styleBackgroud = this.setStyleBackgroud(item)
+ item.styleIcon = this.setStyleIcon(item)
+ item.styleIconText = this.setStyleIconText(item)
+ item.styleRightIcon = this.setStyleRightIcon(item)
+ },
+
+ /**
+ * 鑾峰彇閫変腑鍊�
+ * @param {Object} range
+ */
+ getSelectedValue(range) {
+ if (!this.multiple) return this.dataValue
+ let selectedArr = []
+ range.forEach((item) => {
+ if (item.selected) {
+ selectedArr.push(item[this.map.value])
+ }
+ })
+ return this.dataValue.length > 0 ? this.dataValue : selectedArr
+ },
+
+ /**
+ * 璁剧疆鑳屾櫙鏍峰紡
+ */
+ setStyleBackgroud(item) {
+ let styles = {}
+ let selectedColor = this.selectedColor?this.selectedColor:'#2979ff'
+ if (this.selectedColor) {
+ if (this.mode !== 'list') {
+ styles['border-color'] = item.selected?selectedColor:'#DCDFE6'
+ }
+ if (this.mode === 'tag') {
+ styles['background-color'] = item.selected? selectedColor:'#f5f5f5'
+ }
+ }
+ let classles = ''
+ for (let i in styles) {
+ classles += `${i}:${styles[i]};`
+ }
+ return classles
+ },
+ setStyleIcon(item) {
+ let styles = {}
+ let classles = ''
+ if (this.selectedColor) {
+ let selectedColor = this.selectedColor?this.selectedColor:'#2979ff'
+ styles['background-color'] = item.selected?selectedColor:'#fff'
+ styles['border-color'] = item.selected?selectedColor:'#DCDFE6'
+
+ if(!item.selected && item.disabled){
+ styles['background-color'] = '#F2F6FC'
+ styles['border-color'] = item.selected?selectedColor:'#DCDFE6'
+ }
+ }
+ for (let i in styles) {
+ classles += `${i}:${styles[i]};`
+ }
+ return classles
+ },
+ setStyleIconText(item) {
+ let styles = {}
+ let classles = ''
+ if (this.selectedColor) {
+ let selectedColor = this.selectedColor?this.selectedColor:'#2979ff'
+ if (this.mode === 'tag') {
+ styles.color = item.selected?(this.selectedTextColor?this.selectedTextColor:'#fff'):'#666'
+ } else {
+ styles.color = item.selected?(this.selectedTextColor?this.selectedTextColor:selectedColor):'#666'
+ }
+ if(!item.selected && item.disabled){
+ styles.color = '#999'
+ }
+ }
+ for (let i in styles) {
+ classles += `${i}:${styles[i]};`
+ }
+ return classles
+ },
+ setStyleRightIcon(item) {
+ let styles = {}
+ let classles = ''
+ if (this.mode === 'list') {
+ styles['border-color'] = item.selected?this.styles.selectedColor:'#DCDFE6'
+ }
+ for (let i in styles) {
+ classles += `${i}:${styles[i]};`
+ }
+
+ return classles
+ }
+ }
+ }
+</script>
+
+<style lang="scss">
+ $uni-primary: #2979ff !default;
+ $border-color: #DCDFE6;
+ $disable:0.4;
+
+ @mixin flex {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ }
+
+ .uni-data-loading {
+ @include flex;
+ flex-direction: row;
+ justify-content: center;
+ align-items: center;
+ height: 36px;
+ padding-left: 10px;
+ color: #999;
+ }
+
+ .uni-data-checklist {
+ position: relative;
+ z-index: 0;
+ flex: 1;
+ // 澶氶�夋牱寮�
+ .checklist-group {
+ @include flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+
+ &.is-list {
+ flex-direction: column;
+ }
+
+ .checklist-box {
+ @include flex;
+ flex-direction: row;
+ align-items: center;
+ position: relative;
+ margin: 5px 0;
+ margin-right: 25px;
+
+ .hidden {
+ position: absolute;
+ opacity: 0;
+ }
+
+ // 鏂囧瓧鏍峰紡
+ .checklist-content {
+ @include flex;
+ flex: 1;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-between;
+ .checklist-text {
+ font-size: 14px;
+ color: #666;
+ margin-left: 5px;
+ line-height: 14px;
+ }
+
+ .checkobx__list {
+ border-right-width: 1px;
+ border-right-color: #007aff;
+ border-right-style: solid;
+ border-bottom-width:1px;
+ border-bottom-color: #007aff;
+ border-bottom-style: solid;
+ height: 12px;
+ width: 6px;
+ left: -5px;
+ transform-origin: center;
+ transform: rotate(45deg);
+ opacity: 0;
+ }
+ }
+
+ // 澶氶�夋牱寮�
+ .checkbox__inner {
+ /* #ifndef APP-NVUE */
+ flex-shrink: 0;
+ box-sizing: border-box;
+ /* #endif */
+ position: relative;
+ width: 16px;
+ height: 16px;
+ border: 1px solid $border-color;
+ border-radius: 4px;
+ background-color: #fff;
+ z-index: 1;
+ .checkbox__inner-icon {
+ position: absolute;
+ /* #ifdef APP-NVUE */
+ top: 2px;
+ /* #endif */
+ /* #ifndef APP-NVUE */
+ top: 1px;
+ /* #endif */
+ left: 5px;
+ height: 8px;
+ width: 4px;
+ border-right-width: 1px;
+ border-right-color: #fff;
+ border-right-style: solid;
+ border-bottom-width:1px ;
+ border-bottom-color: #fff;
+ border-bottom-style: solid;
+ opacity: 0;
+ transform-origin: center;
+ transform: rotate(40deg);
+ }
+ }
+
+ // 鍗曢�夋牱寮�
+ .radio__inner {
+ @include flex;
+ /* #ifndef APP-NVUE */
+ flex-shrink: 0;
+ box-sizing: border-box;
+ /* #endif */
+ justify-content: center;
+ align-items: center;
+ position: relative;
+ width: 16px;
+ height: 16px;
+ border: 1px solid $border-color;
+ border-radius: 16px;
+ background-color: #fff;
+ z-index: 1;
+
+ .radio__inner-icon {
+ width: 8px;
+ height: 8px;
+ border-radius: 10px;
+ opacity: 0;
+ }
+ }
+
+ // 榛樿鏍峰紡
+ &.is--default {
+
+ // 绂佺敤
+ &.is-disable {
+ /* #ifdef H5 */
+ cursor: not-allowed;
+ /* #endif */
+ .checkbox__inner {
+ background-color: #F2F6FC;
+ border-color: $border-color;
+ /* #ifdef H5 */
+ cursor: not-allowed;
+ /* #endif */
+ }
+
+ .radio__inner {
+ background-color: #F2F6FC;
+ border-color: $border-color;
+ }
+ .checklist-text {
+ color: #999;
+ }
+ }
+
+ // 閫変腑
+ &.is-checked {
+ .checkbox__inner {
+ border-color: $uni-primary;
+ background-color: $uni-primary;
+
+ .checkbox__inner-icon {
+ opacity: 1;
+ transform: rotate(45deg);
+ }
+ }
+ .radio__inner {
+ border-color: $uni-primary;
+ .radio__inner-icon {
+ opacity: 1;
+ background-color: $uni-primary;
+ }
+ }
+ .checklist-text {
+ color: $uni-primary;
+ }
+ // 閫変腑绂佺敤
+ &.is-disable {
+ .checkbox__inner {
+ opacity: $disable;
+ }
+
+ .checklist-text {
+ opacity: $disable;
+ }
+ .radio__inner {
+ opacity: $disable;
+ }
+ }
+ }
+ }
+
+ // 鎸夐挳鏍峰紡
+ &.is--button {
+ margin-right: 10px;
+ padding: 5px 10px;
+ border: 1px $border-color solid;
+ border-radius: 3px;
+ transition: border-color 0.2s;
+
+ // 绂佺敤
+ &.is-disable {
+ /* #ifdef H5 */
+ cursor: not-allowed;
+ /* #endif */
+ border: 1px #eee solid;
+ opacity: $disable;
+ .checkbox__inner {
+ background-color: #F2F6FC;
+ border-color: $border-color;
+ /* #ifdef H5 */
+ cursor: not-allowed;
+ /* #endif */
+ }
+ .radio__inner {
+ background-color: #F2F6FC;
+ border-color: $border-color;
+ /* #ifdef H5 */
+ cursor: not-allowed;
+ /* #endif */
+ }
+ .checklist-text {
+ color: #999;
+ }
+ }
+
+ &.is-checked {
+ border-color: $uni-primary;
+ .checkbox__inner {
+ border-color: $uni-primary;
+ background-color: $uni-primary;
+ .checkbox__inner-icon {
+ opacity: 1;
+ transform: rotate(45deg);
+ }
+ }
+
+ .radio__inner {
+ border-color: $uni-primary;
+
+ .radio__inner-icon {
+ opacity: 1;
+ background-color: $uni-primary;
+ }
+ }
+
+ .checklist-text {
+ color: $uni-primary;
+ }
+
+ // 閫変腑绂佺敤
+ &.is-disable {
+ opacity: $disable;
+ }
+ }
+ }
+
+ // 鏍囩鏍峰紡
+ &.is--tag {
+ margin-right: 10px;
+ padding: 5px 10px;
+ border: 1px $border-color solid;
+ border-radius: 3px;
+ background-color: #f5f5f5;
+
+ .checklist-text {
+ margin: 0;
+ color: #666;
+ }
+
+ // 绂佺敤
+ &.is-disable {
+ /* #ifdef H5 */
+ cursor: not-allowed;
+ /* #endif */
+ opacity: $disable;
+ }
+
+ &.is-checked {
+ background-color: $uni-primary;
+ border-color: $uni-primary;
+
+ .checklist-text {
+ color: #fff;
+ }
+ }
+ }
+ // 鍒楄〃鏍峰紡
+ &.is--list {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ padding: 10px 15px;
+ padding-left: 0;
+ margin: 0;
+
+ &.is-list-border {
+ border-top: 1px #eee solid;
+ }
+
+ // 绂佺敤
+ &.is-disable {
+ /* #ifdef H5 */
+ cursor: not-allowed;
+ /* #endif */
+ .checkbox__inner {
+ background-color: #F2F6FC;
+ border-color: $border-color;
+ /* #ifdef H5 */
+ cursor: not-allowed;
+ /* #endif */
+ }
+ .checklist-text {
+ color: #999;
+ }
+ }
+
+ &.is-checked {
+ .checkbox__inner {
+ border-color: $uni-primary;
+ background-color: $uni-primary;
+
+ .checkbox__inner-icon {
+ opacity: 1;
+ transform: rotate(45deg);
+ }
+ }
+ .radio__inner {
+ .radio__inner-icon {
+ opacity: 1;
+ }
+ }
+ .checklist-text {
+ color: $uni-primary;
+ }
+
+ .checklist-content {
+ .checkobx__list {
+ opacity: 1;
+ border-color: $uni-primary;
+ }
+ }
+
+ // 閫変腑绂佺敤
+ &.is-disable {
+ .checkbox__inner {
+ opacity: $disable;
+ }
+
+ .checklist-text {
+ opacity: $disable;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+</style>
diff --git a/app/uni_modules/uni-data-checkbox/package.json b/app/uni_modules/uni-data-checkbox/package.json
new file mode 100644
index 0000000..113c350
--- /dev/null
+++ b/app/uni_modules/uni-data-checkbox/package.json
@@ -0,0 +1,84 @@
+{
+ "id": "uni-data-checkbox",
+ "displayName": "uni-data-checkbox 鏁版嵁閫夋嫨鍣�",
+ "version": "1.0.3",
+ "description": "閫氳繃鏁版嵁椹卞姩鐨勫崟閫夋鍜屽閫夋",
+ "keywords": [
+ "uni-ui",
+ "checkbox",
+ "鍗曢��",
+ "澶氶��",
+ "鍗曢�夊閫�"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": "^3.1.1"
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+"dcloudext": {
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+ "type": "component-vue"
+ },
+ "uni_modules": {
+ "dependencies": ["uni-load-more","uni-scss"],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "u",
+ "鑱旂洘": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
diff --git a/app/uni_modules/uni-data-checkbox/readme.md b/app/uni_modules/uni-data-checkbox/readme.md
new file mode 100644
index 0000000..6eb253d
--- /dev/null
+++ b/app/uni_modules/uni-data-checkbox/readme.md
@@ -0,0 +1,18 @@
+
+
+## DataCheckbox 鏁版嵁椹卞姩鐨勫崟閫夊閫夋
+> **缁勪欢鍚嶏細uni-data-checkbox**
+> 浠g爜鍧楋細 `uDataCheckbox`
+
+
+鏈粍浠舵槸鍩轰簬uni-app鍩虹缁勪欢checkbox鐨勫皝瑁呫�傛湰缁勪欢瑕佽В鍐抽棶棰樺寘鎷細
+
+1. 鏁版嵁缁戝畾鍨嬬粍浠讹細缁欐湰缁勪欢缁戝畾涓�涓猟ata锛屼細鑷姩娓叉煋涓�缁勫�欓�夊唴瀹广�傚啀浠ュ線锛屽紑鍙戣�呴渶瑕佺紪鍐欎笉灏戜唬鐮佸疄鐜扮被浼煎姛鑳�
+2. 鑷姩鐨勮〃鍗曟牎楠岋細缁勪欢缁戝畾浜哾ata锛屼笖绗﹀悎[uni-forms](https://ext.dcloud.net.cn/plugin?id=2773)缁勪欢鐨勮〃鍗曟牎楠岃鑼冿紝鎼厤浣跨敤浼氳嚜鍔ㄥ疄鐜拌〃鍗曟牎楠�
+3. 鏈粍浠跺悎骞朵簡鍗曢�夊閫�
+4. 鏈粍浠舵湁鑻ュ共椋庢牸閫夋嫨锛屽鏅�氱殑鍗曢�夊閫夋銆佸苟鍒梑utton椋庢牸銆乼ag椋庢牸銆傚紑鍙戣�呭彲浠ュ揩閫熼�夋嫨闇�瑕佺殑椋庢牸銆備絾浣滀负涓�涓皝瑁呯粍浠讹紝鏍峰紡浠g爜铏界劧涓嶇敤鑷繁鍐欎簡锛屽嵈浼氱壓鐗蹭竴瀹氱殑鏍峰紡鑷畾涔夋��
+
+鍦╱niCloud寮�鍙戜腑锛宍DB Schema`涓厤缃簡enum鏋氫妇绛夌被鍨嬪悗锛屽湪web鎺у埗鍙扮殑[鑷姩鐢熸垚琛ㄥ崟](https://uniapp.dcloud.io/uniCloud/schema?id=autocode)鍔熻兘涓紝浼氳嚜鍔ㄧ敓鎴恅`uni-data-checkbox``缁勪欢骞剁粦瀹氬ソdata
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-data-checkbox)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
\ No newline at end of file
diff --git a/app/uni_modules/uni-data-picker/changelog.md b/app/uni_modules/uni-data-picker/changelog.md
new file mode 100644
index 0000000..1dd79f7
--- /dev/null
+++ b/app/uni_modules/uni-data-picker/changelog.md
@@ -0,0 +1,75 @@
+## 1.1.2锛�2023-04-11锛�
+- 淇 鏇存敼 modelValue 鎶ラ敊鐨� bug
+- 淇 v-for 鏈娇鐢� key 鍊兼帶鍒跺彴 warning
+## 1.1.1锛�2023-02-21锛�
+- 淇浠g爜鍚堝苟鏃跺紩鍙� value 灞炴�т负绌烘椂涓嶆覆鏌撴暟鎹殑闂
+## 1.1.0锛�2023-02-15锛�
+- 淇 localdata 涓嶆敮鎸佸姩鎬佹洿鏂扮殑bug
+## 1.0.9锛�2023-02-15锛�
+- 淇 localdata 涓嶆敮鎸佸姩鎬佹洿鏂扮殑bug
+## 1.0.8锛�2022-09-16锛�
+- 鍙互浣跨敤 uni-scss 鎺у埗涓婚鑹�
+## 1.0.7锛�2022-07-06锛�
+- 浼樺寲 pc绔浘鏍囦綅缃笉姝g‘鐨勯棶棰�
+## 1.0.6锛�2022-07-05锛�
+- 浼樺寲 鏄剧ず鏍峰紡
+## 1.0.5锛�2022-07-04锛�
+- 淇 uni-data-picker 鍦� uni-forms-item 涓搴︿笉姝g‘鐨刡ug
+## 1.0.4锛�2022-04-19锛�
+- 淇 瀛楄妭灏忕▼搴� 鏈湴鏁版嵁鏃犳硶閫夋嫨涓嬩竴绾х殑Bug
+## 1.0.3锛�2022-02-25锛�
+- 淇 nvue 涓嶆敮鎸佺殑 v-show 鐨� bug
+## 1.0.2锛�2022-02-25锛�
+- 淇 鏉′欢缂栬瘧 nvue 涓嶆敮鎸佺殑 css 鏍峰紡
+## 1.0.1锛�2021-11-23锛�
+- 淇 鐢变笂涓増鏈紩鍙戠殑map銆乿-model绛夊睘鎬т笉鐢熸晥鐨刡ug
+## 1.0.0锛�2021-11-19锛�
+- 浼樺寲 缁勪欢 UI锛屽苟鎻愪緵璁捐璧勬簮锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 鏂囨。杩佺Щ锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/uni-data-picker](https://uniapp.dcloud.io/component/uniui/uni-data-picker)
+## 0.4.9锛�2021-10-28锛�
+- 淇 VUE2 v-model 姒傜巼鏃犳晥鐨� bug
+## 0.4.8锛�2021-10-27锛�
+- 淇 v-model 姒傜巼鏃犳晥鐨� bug
+## 0.4.7锛�2021-10-25锛�
+- 鏂板 灞炴�� spaceInfo 鏈嶅姟绌洪棿閰嶇疆 HBuilderX 3.2.11+
+- 淇 鏍戝瀷 uniCloud 鏁版嵁绫诲瀷涓� int 鏃舵姤閿欑殑 bug
+## 0.4.6锛�2021-10-19锛�
+- 淇 闈� VUE3 v-model 涓� 0 鏃舵棤娉曢�変腑鐨� bug
+## 0.4.5锛�2021-09-26锛�
+- 鏂板 娓呴櫎宸查�夐」鐨勫姛鑳斤紙閫氳繃 clearIcon 灞炴�ч厤缃槸鍚︽樉绀烘寜閽級锛屽悓鏃舵彁渚� clear 鏂规硶浠ヤ緵璋冪敤锛屼簩鑰呯瓑鏁�
+- 淇 readonly 涓� true 鏃舵姤閿欑殑 bug
+## 0.4.4锛�2021-09-26锛�
+- 淇 涓婁竴鐗堟湰閫犳垚鐨� map 灞炴�уけ鏁堢殑 bug
+- 鏂板 ellipsis 灞炴�э紝鏀寔閰嶇疆 tab 閫夐」闀垮害杩囬暱鏃舵槸鍚﹁嚜鍔ㄧ渷鐣�
+## 0.4.3锛�2021-09-24锛�
+- 淇 鏌愪簺鎯呭喌涓嬬骇鑱旀湭瑙﹀彂鐨� bug
+## 0.4.2锛�2021-09-23锛�
+- 鏂板 鎻愪緵 show 鍜� hide 鏂规硶锛屽紑鍙戣�呭彲浠ラ�氳繃 ref 璋冪敤
+- 鏂板 閫夐」鍐呭杩囬暱鑷姩娣诲姞鐪佺暐鍙�
+## 0.4.1锛�2021-09-15锛�
+- 鏂板 map 灞炴�� 瀛楁鏄犲皠锛屽皢 text/value 鏄犲皠鍒版暟鎹腑鐨勫叾浠栧瓧娈�
+## 0.4.0锛�2021-07-13锛�
+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤� vue3 椤圭洰锛岃瑙� [uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+## 0.3.5锛�2021-06-04锛�
+- 淇 鏃犳硶鍔犺浇浜戠鏁版嵁鐨勯棶棰�
+## 0.3.4锛�2021-05-28锛�
+- 淇 v-model 鏃犳晥闂
+- 淇 loaddata 涓虹┖鏁版嵁缁勬椂鍔犺浇鏃堕棿杩囬暱闂
+- 淇 涓婁釜鐗堟湰寮曞嚭鐨勬湰鍦版暟鎹棤娉曢�夋嫨甯︽湁 children 鐨� 2 绾ц妭鐐�
+## 0.3.3锛�2021-05-12锛�
+- 鏂板 缁勪欢绀轰緥鍦板潃
+## 0.3.2锛�2021-04-22锛�
+- 淇 闈炴爲褰㈡暟鎹湁 where 灞炴�ф煡璇㈡姤閿欑殑闂
+## 0.3.1锛�2021-04-15锛�
+- 淇 鏈湴鏁版嵁姒傜巼鏃犳硶鍥炴樉鏃堕棶棰�
+## 0.3.0锛�2021-04-07锛�
+- 鏂板 鏀寔浜戠闈炴爲褰㈣〃缁撴瀯鏁版嵁
+- 淇 鏍硅妭鐐� parent_field 瀛楁绛変簬 null 鏃堕�夋嫨鐣岄潰閿欎贡闂
+## 0.2.0锛�2021-03-15锛�
+- 淇 nodeclick銆乸opupopened銆乸opupclosed 浜嬩欢鏃犳硶瑙﹀彂鐨勯棶棰�
+## 0.1.9锛�2021-03-09锛�
+- 淇 寰俊灏忕▼搴忔煇浜涙儏鍐典笅鏃犳硶閫夋嫨鐨勯棶棰�
+## 0.1.8锛�2021-02-05锛�
+- 浼樺寲 閮ㄥ垎鏍峰紡鍦� nvue 涓婄殑鍏煎琛ㄧ幇
+## 0.1.7锛�2021-02-05锛�
+- 璋冩暣涓� uni_modules 鐩綍瑙勮寖
diff --git a/app/uni_modules/uni-data-picker/components/uni-data-picker/keypress.js b/app/uni_modules/uni-data-picker/components/uni-data-picker/keypress.js
new file mode 100644
index 0000000..6ef26a2
--- /dev/null
+++ b/app/uni_modules/uni-data-picker/components/uni-data-picker/keypress.js
@@ -0,0 +1,45 @@
+// #ifdef H5
+export default {
+ name: 'Keypress',
+ props: {
+ disable: {
+ type: Boolean,
+ default: false
+ }
+ },
+ mounted () {
+ const keyNames = {
+ esc: ['Esc', 'Escape'],
+ tab: 'Tab',
+ enter: 'Enter',
+ space: [' ', 'Spacebar'],
+ up: ['Up', 'ArrowUp'],
+ left: ['Left', 'ArrowLeft'],
+ right: ['Right', 'ArrowRight'],
+ down: ['Down', 'ArrowDown'],
+ delete: ['Backspace', 'Delete', 'Del']
+ }
+ const listener = ($event) => {
+ if (this.disable) {
+ return
+ }
+ const keyName = Object.keys(keyNames).find(key => {
+ const keyName = $event.key
+ const value = keyNames[key]
+ return value === keyName || (Array.isArray(value) && value.includes(keyName))
+ })
+ if (keyName) {
+ // 閬垮厤鍜屽叾浠栨寜閿簨浠跺啿绐�
+ setTimeout(() => {
+ this.$emit(keyName, {})
+ }, 0)
+ }
+ }
+ document.addEventListener('keyup', listener)
+ this.$once('hook:beforeDestroy', () => {
+ document.removeEventListener('keyup', listener)
+ })
+ },
+ render: () => {}
+}
+// #endif
diff --git a/app/uni_modules/uni-data-picker/components/uni-data-picker/uni-data-picker.vue b/app/uni_modules/uni-data-picker/components/uni-data-picker/uni-data-picker.vue
new file mode 100644
index 0000000..179a4e0
--- /dev/null
+++ b/app/uni_modules/uni-data-picker/components/uni-data-picker/uni-data-picker.vue
@@ -0,0 +1,551 @@
+<template>
+ <view class="uni-data-tree">
+ <view class="uni-data-tree-input" @click="handleInput">
+ <slot :options="options" :data="inputSelected" :error="errorMessage">
+ <view class="input-value" :class="{'input-value-border': border}">
+ <text v-if="errorMessage" class="selected-area error-text">{{errorMessage}}</text>
+ <view v-else-if="loading && !isOpened" class="selected-area">
+ <uni-load-more class="load-more" :contentText="loadMore" status="loading"></uni-load-more>
+ </view>
+ <scroll-view v-else-if="inputSelected.length" class="selected-area" scroll-x="true">
+ <view class="selected-list">
+ <view class="selected-item" v-for="(item,index) in inputSelected" :key="index">
+ <text class="text-color">{{item.text}}</text><text v-if="index<inputSelected.length-1"
+ class="input-split-line">{{split}}</text>
+ </view>
+ </view>
+ </scroll-view>
+ <text v-else class="selected-area placeholder">{{placeholder}}</text>
+ <view v-if="clearIcon && !readonly && inputSelected.length" class="icon-clear" @click.stop="clear">
+ <uni-icons type="clear" color="#c0c4cc" size="24"></uni-icons>
+ </view>
+ <view class="arrow-area" v-if="(!clearIcon || !inputSelected.length) && !readonly ">
+ <view class="input-arrow"></view>
+ </view>
+ </view>
+ </slot>
+ </view>
+ <view class="uni-data-tree-cover" v-if="isOpened" @click="handleClose"></view>
+ <view class="uni-data-tree-dialog" v-if="isOpened">
+ <view class="uni-popper__arrow"></view>
+ <view class="dialog-caption">
+ <view class="title-area">
+ <text class="dialog-title">{{popupTitle}}</text>
+ </view>
+ <view class="dialog-close" @click="handleClose">
+ <view class="dialog-close-plus" data-id="close"></view>
+ <view class="dialog-close-plus dialog-close-rotate" data-id="close"></view>
+ </view>
+ </view>
+ <data-picker-view class="picker-view" ref="pickerView" v-model="dataValue" :localdata="localdata"
+ :preload="preload" :collection="collection" :field="field" :orderby="orderby" :where="where"
+ :step-searh="stepSearh" :self-field="selfField" :parent-field="parentField" :managed-mode="true" :map="map"
+ :ellipsis="ellipsis" @change="onchange" @datachange="ondatachange" @nodeclick="onnodeclick">
+ </data-picker-view>
+ </view>
+ </view>
+</template>
+
+<script>
+ import dataPicker from "../uni-data-pickerview/uni-data-picker.js"
+ import DataPickerView from "../uni-data-pickerview/uni-data-pickerview.vue"
+
+ /**
+ * DataPicker 绾ц仈閫夋嫨
+ * @description 鏀寔鍗曞垪銆佸拰澶氬垪绾ц仈閫夋嫨銆傚垪鏁版病鏈夐檺鍒讹紝濡傛灉灞忓箷鏄剧ず涓嶅叏锛岄《閮╰ab鍖哄煙浼氬乏鍙虫粴鍔ㄣ��
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=3796
+ * @property {String} popup-title 寮瑰嚭绐楀彛鏍囬
+ * @property {Array} localdata 鏈湴鏁版嵁锛屽弬鑰�
+ * @property {Boolean} border = [true|false] 鏄惁鏈夎竟妗�
+ * @property {Boolean} readonly = [true|false] 鏄惁浠呰
+ * @property {Boolean} preload = [true|false] 鏄惁棰勫姞杞芥暟鎹�
+ * @value true 寮�鍚鍔犺浇鏁版嵁锛岀偣鍑诲脊鍑虹獥鍙e悗鏄剧ず宸插姞杞芥暟鎹�
+ * @value false 鍏抽棴棰勫姞杞芥暟鎹紝鐐瑰嚮寮瑰嚭绐楀彛鍚庡紑濮嬪姞杞芥暟鎹�
+ * @property {Boolean} step-searh = [true|false] 鏄惁鍒嗗竷鏌ヨ
+ * @value true 鍚敤鍒嗗竷鏌ヨ锛屼粎鏌ヨ褰撳墠閫変腑鑺傜偣
+ * @value false 鍏抽棴鍒嗗竷鏌ヨ锛屼竴娆℃煡璇㈠嚭鎵�鏈夋暟鎹�
+ * @property {String|DBFieldString} self-field 鍒嗗竷鏌ヨ褰撳墠瀛楁鍚嶇О
+ * @property {String|DBFieldString} parent-field 鍒嗗竷鏌ヨ鐖跺瓧娈靛悕绉�
+ * @property {String|DBCollectionString} collection 琛ㄥ悕
+ * @property {String|DBFieldString} field 鏌ヨ瀛楁锛屽涓瓧娈电敤 `,` 鍒嗗壊
+ * @property {String} orderby 鎺掑簭瀛楁鍙婃搴忓�掑彊璁剧疆
+ * @property {String|JQLString} where 鏌ヨ鏉′欢
+ * @event {Function} popupshow 寮瑰嚭鐨勯�夋嫨绐楀彛鎵撳紑鏃惰Е鍙戞浜嬩欢
+ * @event {Function} popuphide 寮瑰嚭鐨勯�夋嫨绐楀彛鍏抽棴鏃惰Е鍙戞浜嬩欢
+ */
+ export default {
+ name: 'UniDataPicker',
+ emits: ['popupopened', 'popupclosed', 'nodeclick', 'input', 'change', 'update:modelValue','inputclick'],
+ mixins: [dataPicker],
+ components: {
+ DataPickerView
+ },
+ props: {
+ options: {
+ type: [Object, Array],
+ default () {
+ return {}
+ }
+ },
+ popupTitle: {
+ type: String,
+ default: '璇烽�夋嫨'
+ },
+ placeholder: {
+ type: String,
+ default: '璇烽�夋嫨'
+ },
+ heightMobile: {
+ type: String,
+ default: ''
+ },
+ readonly: {
+ type: Boolean,
+ default: false
+ },
+ clearIcon: {
+ type: Boolean,
+ default: true
+ },
+ border: {
+ type: Boolean,
+ default: true
+ },
+ split: {
+ type: String,
+ default: '/'
+ },
+ ellipsis: {
+ type: Boolean,
+ default: true
+ }
+ },
+ data() {
+ return {
+ isOpened: false,
+ inputSelected: []
+ }
+ },
+ created() {
+ this.$nextTick(() => {
+ this.load();
+ })
+ },
+ watch: {
+ localdata: {
+ handler() {
+ this.load()
+ },
+ deep: true
+ },
+ },
+ methods: {
+ clear() {
+ this._dispatchEvent([]);
+ },
+ onPropsChange() {
+ this._treeData = [];
+ this.selectedIndex = 0;
+
+ this.load();
+ },
+ load() {
+ if (this.readonly) {
+ this._processReadonly(this.localdata, this.dataValue);
+ return;
+ }
+
+ // 鍥炴樉鏈湴鏁版嵁
+ if (this.isLocalData) {
+ this.loadData();
+ this.inputSelected = this.selected.slice(0);
+ } else if (this.isCloudDataList || this.isCloudDataTree) { // 鍥炴樉 Cloud 鏁版嵁
+ this.loading = true;
+ this.getCloudDataValue().then((res) => {
+ this.loading = false;
+ this.inputSelected = res;
+ }).catch((err) => {
+ this.loading = false;
+ this.errorMessage = err;
+ })
+ }
+ },
+ show() {
+ this.isOpened = true
+ setTimeout(() => {
+ this.$refs.pickerView.updateData({
+ treeData: this._treeData,
+ selected: this.selected,
+ selectedIndex: this.selectedIndex
+ })
+ }, 200)
+ this.$emit('popupopened')
+ },
+ hide() {
+ this.isOpened = false
+ this.$emit('popupclosed')
+ },
+ handleInput() {
+ if (this.readonly) {
+ this.$emit('inputclick')
+ return
+ }
+ this.show()
+ },
+ handleClose(e) {
+ this.hide()
+ },
+ onnodeclick(e) {
+ this.$emit('nodeclick', e)
+ },
+ ondatachange(e) {
+ this._treeData = this.$refs.pickerView._treeData
+ },
+ onchange(e) {
+ this.hide()
+ this.$nextTick(() => {
+ this.inputSelected = e;
+ })
+ this._dispatchEvent(e)
+ },
+ _processReadonly(dataList, value) {
+ var isTree = dataList.findIndex((item) => {
+ return item.children
+ })
+ if (isTree > -1) {
+ let inputValue
+ if (Array.isArray(value)) {
+ inputValue = value[value.length - 1]
+ if (typeof inputValue === 'object' && inputValue.value) {
+ inputValue = inputValue.value
+ }
+ } else {
+ inputValue = value
+ }
+ this.inputSelected = this._findNodePath(inputValue, this.localdata)
+ return
+ }
+
+ if (!this.hasValue) {
+ this.inputSelected = []
+ return
+ }
+
+ let result = []
+ for (let i = 0; i < value.length; i++) {
+ var val = value[i]
+ var item = dataList.find((v) => {
+ return v.value == val
+ })
+ if (item) {
+ result.push(item)
+ }
+ }
+ if (result.length) {
+ this.inputSelected = result
+ }
+ },
+ _filterForArray(data, valueArray) {
+ var result = []
+ for (let i = 0; i < valueArray.length; i++) {
+ var value = valueArray[i]
+ var found = data.find((item) => {
+ return item.value == value
+ })
+ if (found) {
+ result.push(found)
+ }
+ }
+ return result
+ },
+ _dispatchEvent(selected) {
+ let item = {}
+ if (selected.length) {
+ var value = new Array(selected.length)
+ for (var i = 0; i < selected.length; i++) {
+ value[i] = selected[i].value
+ }
+ item = selected[selected.length - 1]
+ } else {
+ item.value = ''
+ }
+ if (this.formItem) {
+ this.formItem.setValue(item.value)
+ }
+
+ this.$emit('input', item.value)
+ this.$emit('update:modelValue', item.value)
+ this.$emit('change', {
+ detail: {
+ value: selected
+ }
+ })
+ }
+ }
+ }
+</script>
+
+<style>
+ .uni-data-tree {
+ flex: 1;
+ position: relative;
+ font-size: 14px;
+ }
+
+ .error-text {
+ color: #DD524D;
+ }
+
+ .input-value {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ align-items: center;
+ flex-wrap: nowrap;
+ font-size: 14px;
+ /* line-height: 35px; */
+ padding: 0 10px;
+ padding-right: 5px;
+ overflow: hidden;
+ height: 35px;
+ /* #ifndef APP-NVUE */
+ box-sizing: border-box;
+ /* #endif */
+ }
+
+ .input-value-border {
+ border: 1px solid #e5e5e5;
+ border-radius: 5px;
+ }
+
+ .selected-area {
+ flex: 1;
+ overflow: hidden;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ }
+
+ .load-more {
+ /* #ifndef APP-NVUE */
+ margin-right: auto;
+ /* #endif */
+ /* #ifdef APP-NVUE */
+ width: 40px;
+ /* #endif */
+ }
+
+ .selected-list {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ flex-wrap: nowrap;
+ /* padding: 0 5px; */
+ }
+
+ .selected-item {
+ flex-direction: row;
+ /* padding: 0 1px; */
+ /* #ifndef APP-NVUE */
+ white-space: nowrap;
+ /* #endif */
+ }
+
+ .text-color {
+ color: #333;
+ }
+
+ .placeholder {
+ color: grey;
+ font-size: 12px;
+ }
+
+ .input-split-line {
+ opacity: .5;
+ }
+
+ .arrow-area {
+ position: relative;
+ width: 20px;
+ /* #ifndef APP-NVUE */
+ margin-bottom: 5px;
+ margin-left: auto;
+ display: flex;
+ /* #endif */
+ justify-content: center;
+ transform: rotate(-45deg);
+ transform-origin: center;
+ }
+
+ .input-arrow {
+ width: 7px;
+ height: 7px;
+ border-left: 1px solid #999;
+ border-bottom: 1px solid #999;
+ }
+
+ .uni-data-tree-cover {
+ position: fixed;
+ left: 0;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ background-color: rgba(0, 0, 0, .4);
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: column;
+ z-index: 100;
+ }
+
+ .uni-data-tree-dialog {
+ position: fixed;
+ left: 0;
+ /* #ifndef APP-NVUE */
+ top: 20%;
+ /* #endif */
+ /* #ifdef APP-NVUE */
+ top: 200px;
+ /* #endif */
+ right: 0;
+ bottom: 0;
+ background-color: #FFFFFF;
+ border-top-left-radius: 10px;
+ border-top-right-radius: 10px;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: column;
+ z-index: 102;
+ overflow: hidden;
+ /* #ifdef APP-NVUE */
+ width: 750rpx;
+ /* #endif */
+ }
+
+ .dialog-caption {
+ position: relative;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ /* border-bottom: 1px solid #f0f0f0; */
+ }
+
+ .title-area {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ align-items: center;
+ /* #ifndef APP-NVUE */
+ margin: auto;
+ /* #endif */
+ padding: 0 10px;
+ }
+
+ .dialog-title {
+ /* font-weight: bold; */
+ line-height: 44px;
+ }
+
+ .dialog-close {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ align-items: center;
+ padding: 0 15px;
+ }
+
+ .dialog-close-plus {
+ width: 16px;
+ height: 2px;
+ background-color: #666;
+ border-radius: 2px;
+ transform: rotate(45deg);
+ }
+
+ .dialog-close-rotate {
+ position: absolute;
+ transform: rotate(-45deg);
+ }
+
+ .picker-view {
+ flex: 1;
+ overflow: hidden;
+ }
+
+ .icon-clear {
+ display: flex;
+ align-items: center;
+ }
+
+ /* #ifdef H5 */
+ @media all and (min-width: 768px) {
+ .uni-data-tree-cover {
+ background-color: transparent;
+ }
+
+ .uni-data-tree-dialog {
+ position: absolute;
+ top: 55px;
+ height: auto;
+ min-height: 400px;
+ max-height: 50vh;
+ background-color: #fff;
+ border: 1px solid #EBEEF5;
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+ border-radius: 4px;
+ overflow: unset;
+ }
+
+ .dialog-caption {
+ display: none;
+ }
+
+ .icon-clear {
+ /* margin-right: 5px; */
+ }
+ }
+
+ /* #endif */
+
+ /* picker 寮瑰嚭灞傞�氱敤鐨勬寚绀哄皬涓夎, todo锛氭墿灞曡嚦涓婁笅宸﹀彸鏂瑰悜瀹氫綅 */
+ /* #ifndef APP-NVUE */
+ .uni-popper__arrow,
+ .uni-popper__arrow::after {
+ position: absolute;
+ display: block;
+ width: 0;
+ height: 0;
+ border-color: transparent;
+ border-style: solid;
+ border-width: 6px;
+ }
+
+ .uni-popper__arrow {
+ filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03));
+ top: -6px;
+ left: 10%;
+ margin-right: 3px;
+ border-top-width: 0;
+ border-bottom-color: #EBEEF5;
+ }
+
+ .uni-popper__arrow::after {
+ content: " ";
+ top: 1px;
+ margin-left: -6px;
+ border-top-width: 0;
+ border-bottom-color: #fff;
+ }
+
+ /* #endif */
+</style>
diff --git a/app/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-picker.js b/app/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-picker.js
new file mode 100644
index 0000000..cfae22a
--- /dev/null
+++ b/app/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-picker.js
@@ -0,0 +1,622 @@
+export default {
+ props: {
+ localdata: {
+ type: [Array, Object],
+ default () {
+ return []
+ }
+ },
+ spaceInfo: {
+ type: Object,
+ default () {
+ return {}
+ }
+ },
+ collection: {
+ type: String,
+ default: ''
+ },
+ action: {
+ type: String,
+ default: ''
+ },
+ field: {
+ type: String,
+ default: ''
+ },
+ orderby: {
+ type: String,
+ default: ''
+ },
+ where: {
+ type: [String, Object],
+ default: ''
+ },
+ pageData: {
+ type: String,
+ default: 'add'
+ },
+ pageCurrent: {
+ type: Number,
+ default: 1
+ },
+ pageSize: {
+ type: Number,
+ default: 500
+ },
+ getcount: {
+ type: [Boolean, String],
+ default: false
+ },
+ getone: {
+ type: [Boolean, String],
+ default: false
+ },
+ gettree: {
+ type: [Boolean, String],
+ default: false
+ },
+ manual: {
+ type: Boolean,
+ default: false
+ },
+ value: {
+ type: [Array, String, Number],
+ default () {
+ return []
+ }
+ },
+ modelValue: {
+ type: [Array, String, Number],
+ default () {
+ return []
+ }
+ },
+ preload: {
+ type: Boolean,
+ default: false
+ },
+ stepSearh: {
+ type: Boolean,
+ default: true
+ },
+ selfField: {
+ type: String,
+ default: ''
+ },
+ parentField: {
+ type: String,
+ default: ''
+ },
+ multiple: {
+ type: Boolean,
+ default: false
+ },
+ map: {
+ type: Object,
+ default () {
+ return {
+ text: "text",
+ value: "value"
+ }
+ }
+ }
+ },
+ data() {
+ return {
+ loading: false,
+ errorMessage: '',
+ loadMore: {
+ contentdown: '',
+ contentrefresh: '',
+ contentnomore: ''
+ },
+ dataList: [],
+ selected: [],
+ selectedIndex: 0,
+ page: {
+ current: this.pageCurrent,
+ size: this.pageSize,
+ count: 0
+ }
+ }
+ },
+ computed: {
+ isLocalData() {
+ return !this.collection.length;
+ },
+ isCloudData() {
+ return this.collection.length > 0;
+ },
+ isCloudDataList() {
+ return (this.isCloudData && (!this.parentField && !this.selfField));
+ },
+ isCloudDataTree() {
+ return (this.isCloudData && this.parentField && this.selfField);
+ },
+ dataValue() {
+ let isModelValue = Array.isArray(this.modelValue) ? (this.modelValue.length > 0) : (this.modelValue !== null ||
+ this.modelValue !== undefined);
+ return isModelValue ? this.modelValue : this.value;
+ },
+ hasValue() {
+ if (typeof this.dataValue === 'number') {
+ return true
+ }
+ return (this.dataValue != null) && (this.dataValue.length > 0)
+ }
+ },
+ created() {
+ this.$watch(() => {
+ var al = [];
+ ['pageCurrent',
+ 'pageSize',
+ 'spaceInfo',
+ 'value',
+ 'modelValue',
+ 'localdata',
+ 'collection',
+ 'action',
+ 'field',
+ 'orderby',
+ 'where',
+ 'getont',
+ 'getcount',
+ 'gettree'
+ ].forEach(key => {
+ al.push(this[key])
+ });
+ return al
+ }, (newValue, oldValue) => {
+ let needReset = false
+ for (let i = 2; i < newValue.length; i++) {
+ if (newValue[i] != oldValue[i]) {
+ needReset = true
+ break
+ }
+ }
+ if (newValue[0] != oldValue[0]) {
+ this.page.current = this.pageCurrent
+ }
+ this.page.size = this.pageSize
+
+ this.onPropsChange()
+ })
+ this._treeData = []
+ },
+ methods: {
+ onPropsChange() {
+ this._treeData = [];
+ },
+
+ // 濉厖 pickview 鏁版嵁
+ async loadData() {
+ if (this.isLocalData) {
+ this.loadLocalData();
+ } else if (this.isCloudDataList) {
+ this.loadCloudDataList();
+ } else if (this.isCloudDataTree) {
+ this.loadCloudDataTree();
+ }
+ },
+
+ // 鍔犺浇鏈湴鏁版嵁
+ async loadLocalData() {
+ this._treeData = [];
+ this._extractTree(this.localdata, this._treeData);
+
+ let inputValue = this.dataValue;
+ if (inputValue === undefined) {
+ return;
+ }
+
+ if (Array.isArray(inputValue)) {
+ inputValue = inputValue[inputValue.length - 1];
+ if (typeof inputValue === 'object' && inputValue[this.map.value]) {
+ inputValue = inputValue[this.map.value];
+ }
+ }
+
+ this.selected = this._findNodePath(inputValue, this.localdata);
+ },
+
+ // 鍔犺浇 Cloud 鏁版嵁 (鍗曞垪)
+ async loadCloudDataList() {
+ if (this.loading) {
+ return;
+ }
+ this.loading = true;
+
+ try {
+ let response = await this.getCommand();
+ let responseData = response.result.data;
+
+ this._treeData = responseData;
+
+ this._updateBindData();
+ this._updateSelected();
+
+ this.onDataChange();
+ } catch (e) {
+ this.errorMessage = e;
+ } finally {
+ this.loading = false;
+ }
+ },
+
+ // 鍔犺浇 Cloud 鏁版嵁 (鏍戝舰)
+ async loadCloudDataTree() {
+ if (this.loading) {
+ return;
+ }
+ this.loading = true;
+
+ try {
+ let commandOptions = {
+ field: this._cloudDataPostField(),
+ where: this._cloudDataTreeWhere()
+ };
+ if (this.gettree) {
+ commandOptions.startwith = `${this.selfField}=='${this.dataValue}'`;
+ }
+
+ let response = await this.getCommand(commandOptions);
+ let responseData = response.result.data;
+
+ this._treeData = responseData;
+ this._updateBindData();
+ this._updateSelected();
+
+ this.onDataChange();
+ } catch (e) {
+ this.errorMessage = e;
+ } finally {
+ this.loading = false;
+ }
+ },
+
+ // 鍔犺浇 Cloud 鏁版嵁 (鑺傜偣)
+ async loadCloudDataNode(callback) {
+ if (this.loading) {
+ return;
+ }
+ this.loading = true;
+
+ try {
+ let commandOptions = {
+ field: this._cloudDataPostField(),
+ where: this._cloudDataNodeWhere()
+ };
+
+ let response = await this.getCommand(commandOptions);
+ let responseData = response.result.data;
+
+ callback(responseData);
+ } catch (e) {
+ this.errorMessage = e;
+ } finally {
+ this.loading = false;
+ }
+ },
+
+ // 鍥炴樉 Cloud 鏁版嵁
+ getCloudDataValue() {
+ if (this.isCloudDataList) {
+ return this.getCloudDataListValue();
+ }
+
+ if (this.isCloudDataTree) {
+ return this.getCloudDataTreeValue();
+ }
+ },
+
+ // 鍥炴樉 Cloud 鏁版嵁 (鍗曞垪)
+ getCloudDataListValue() {
+ // 鏍规嵁 field's as value鏍囪瘑鍖归厤 where 鏉′欢
+ let where = [];
+ let whereField = this._getForeignKeyByField();
+ if (whereField) {
+ where.push(`${whereField} == '${this.dataValue}'`)
+ }
+
+ where = where.join(' || ');
+
+ if (this.where) {
+ where = `(${this.where}) && (${where})`
+ }
+
+ return this.getCommand({
+ field: this._cloudDataPostField(),
+ where
+ }).then((res) => {
+ this.selected = res.result.data;
+ return res.result.data;
+ });
+ },
+
+ // 鍥炴樉 Cloud 鏁版嵁 (鏍戝舰)
+ getCloudDataTreeValue() {
+ return this.getCommand({
+ field: this._cloudDataPostField(),
+ getTreePath: {
+ startWith: `${this.selfField}=='${this.dataValue}'`
+ }
+ }).then((res) => {
+ let treePath = [];
+ this._extractTreePath(res.result.data, treePath);
+ this.selected = treePath;
+ return treePath;
+ });
+ },
+
+ getCommand(options = {}) {
+ /* eslint-disable no-undef */
+ let db = uniCloud.database(this.spaceInfo)
+
+ const action = options.action || this.action
+ if (action) {
+ db = db.action(action)
+ }
+
+ const collection = options.collection || this.collection
+ db = db.collection(collection)
+
+ const where = options.where || this.where
+ if (!(!where || !Object.keys(where).length)) {
+ db = db.where(where)
+ }
+
+ const field = options.field || this.field
+ if (field) {
+ db = db.field(field)
+ }
+
+ const orderby = options.orderby || this.orderby
+ if (orderby) {
+ db = db.orderBy(orderby)
+ }
+
+ const current = options.pageCurrent !== undefined ? options.pageCurrent : this.page.current
+ const size = options.pageSize !== undefined ? options.pageSize : this.page.size
+ const getCount = options.getcount !== undefined ? options.getcount : this.getcount
+ const getTree = options.gettree !== undefined ? options.gettree : this.gettree
+
+ const getOptions = {
+ getCount,
+ getTree
+ }
+ if (options.getTreePath) {
+ getOptions.getTreePath = options.getTreePath
+ }
+
+ db = db.skip(size * (current - 1)).limit(size).get(getOptions)
+
+ return db
+ },
+
+ _cloudDataPostField() {
+ let fields = [this.field];
+ if (this.parentField) {
+ fields.push(`${this.parentField} as parent_value`);
+ }
+ return fields.join(',');
+ },
+
+ _cloudDataTreeWhere() {
+ let result = []
+ let selected = this.selected
+ let parentField = this.parentField
+ if (parentField) {
+ result.push(`${parentField} == null || ${parentField} == ""`)
+ }
+ if (selected.length) {
+ for (var i = 0; i < selected.length - 1; i++) {
+ result.push(`${parentField} == '${selected[i].value}'`)
+ }
+ }
+
+ let where = []
+ if (this.where) {
+ where.push(`(${this.where})`)
+ }
+
+ if (result.length) {
+ where.push(`(${result.join(' || ')})`)
+ }
+
+ return where.join(' && ')
+ },
+
+ _cloudDataNodeWhere() {
+ let where = []
+ let selected = this.selected;
+ if (selected.length) {
+ where.push(`${this.parentField} == '${selected[selected.length - 1].value}'`);
+ }
+
+ where = where.join(' || ');
+
+ if (this.where) {
+ return `(${this.where}) && (${where})`
+ }
+
+ return where
+ },
+
+ _getWhereByForeignKey() {
+ let result = []
+ let whereField = this._getForeignKeyByField();
+ if (whereField) {
+ result.push(`${whereField} == '${this.dataValue}'`)
+ }
+
+ if (this.where) {
+ return `(${this.where}) && (${result.join(' || ')})`
+ }
+
+ return result.join(' || ')
+ },
+
+ _getForeignKeyByField() {
+ let fields = this.field.split(',');
+ let whereField = null;
+ for (let i = 0; i < fields.length; i++) {
+ const items = fields[i].split('as');
+ if (items.length < 2) {
+ continue;
+ }
+ if (items[1].trim() === 'value') {
+ whereField = items[0].trim();
+ break;
+ }
+ }
+ return whereField;
+ },
+
+ _updateBindData(node) {
+ const {
+ dataList,
+ hasNodes
+ } = this._filterData(this._treeData, this.selected)
+
+ let isleaf = this._stepSearh === false && !hasNodes
+
+ if (node) {
+ node.isleaf = isleaf
+ }
+
+ this.dataList = dataList
+ this.selectedIndex = dataList.length - 1
+
+ if (!isleaf && this.selected.length < dataList.length) {
+ this.selected.push({
+ value: null,
+ text: "璇烽�夋嫨"
+ })
+ }
+
+ return {
+ isleaf,
+ hasNodes
+ }
+ },
+
+ _updateSelected() {
+ let dl = this.dataList
+ let sl = this.selected
+ let textField = this.map.text
+ let valueField = this.map.value
+ for (let i = 0; i < sl.length; i++) {
+ let value = sl[i].value
+ let dl2 = dl[i]
+ for (let j = 0; j < dl2.length; j++) {
+ let item2 = dl2[j]
+ if (item2[valueField] === value) {
+ sl[i].text = item2[textField]
+ break
+ }
+ }
+ }
+ },
+
+ _filterData(data, paths) {
+ let dataList = []
+ let hasNodes = true
+
+ dataList.push(data.filter((item) => {
+ return (item.parent_value === null || item.parent_value === undefined || item.parent_value === '')
+ }))
+ for (let i = 0; i < paths.length; i++) {
+ let value = paths[i].value
+ let nodes = data.filter((item) => {
+ return item.parent_value === value
+ })
+
+ if (nodes.length) {
+ dataList.push(nodes)
+ } else {
+ hasNodes = false
+ }
+ }
+
+ return {
+ dataList,
+ hasNodes
+ }
+ },
+
+ _extractTree(nodes, result, parent_value) {
+ let list = result || []
+ let valueField = this.map.value
+ for (let i = 0; i < nodes.length; i++) {
+ let node = nodes[i]
+
+ let child = {}
+ for (let key in node) {
+ if (key !== 'children') {
+ child[key] = node[key]
+ }
+ }
+ if (parent_value !== null && parent_value !== undefined && parent_value !== '') {
+ child.parent_value = parent_value
+ }
+ result.push(child)
+
+ let children = node.children
+ if (children) {
+ this._extractTree(children, result, node[valueField])
+ }
+ }
+ },
+
+ _extractTreePath(nodes, result) {
+ let list = result || []
+ for (let i = 0; i < nodes.length; i++) {
+ let node = nodes[i]
+
+ let child = {}
+ for (let key in node) {
+ if (key !== 'children') {
+ child[key] = node[key]
+ }
+ }
+ result.push(child)
+
+ let children = node.children
+ if (children) {
+ this._extractTreePath(children, result)
+ }
+ }
+ },
+
+ _findNodePath(key, nodes, path = []) {
+ let textField = this.map.text
+ let valueField = this.map.value
+ for (let i = 0; i < nodes.length; i++) {
+ let node = nodes[i]
+ let children = node.children
+ let text = node[textField]
+ let value = node[valueField]
+
+ path.push({
+ value,
+ text
+ })
+
+ if (value === key) {
+ return path
+ }
+
+ if (children) {
+ const p = this._findNodePath(key, children, path)
+ if (p.length) {
+ return p
+ }
+ }
+
+ path.pop()
+ }
+ return []
+ }
+ }
+}
diff --git a/app/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.vue b/app/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.vue
new file mode 100644
index 0000000..6ebced9
--- /dev/null
+++ b/app/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.vue
@@ -0,0 +1,323 @@
+<template>
+ <view class="uni-data-pickerview">
+ <scroll-view v-if="!isCloudDataList" class="selected-area" scroll-x="true">
+ <view class="selected-list">
+ <view
+ class="selected-item"
+ v-for="(item,index) in selected"
+ :key="index"
+ :class="{
+ 'selected-item-active':index == selectedIndex
+ }"
+ @click="handleSelect(index)"
+ >
+ <text>{{item.text || ''}}</text>
+ </view>
+ </view>
+ </scroll-view>
+ <view class="tab-c">
+ <scroll-view class="list" :scroll-y="true">
+ <view class="item" :class="{'is-disabled': !!item.disable}" v-for="(item, j) in dataList[selectedIndex]" :key="j"
+ @click="handleNodeClick(item, selectedIndex, j)">
+ <text class="item-text">{{item[map.text]}}</text>
+ <view class="check" v-if="selected.length > selectedIndex && item[map.value] == selected[selectedIndex].value"></view>
+ </view>
+ </scroll-view>
+
+ <view class="loading-cover" v-if="loading">
+ <uni-load-more class="load-more" :contentText="loadMore" status="loading"></uni-load-more>
+ </view>
+ <view class="error-message" v-if="errorMessage">
+ <text class="error-text">{{errorMessage}}</text>
+ </view>
+ </view>
+ </view>
+</template>
+
+<script>
+ import dataPicker from "./uni-data-picker.js"
+
+ /**
+ * DataPickerview
+ * @description uni-data-pickerview
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=3796
+ * @property {Array} localdata 鏈湴鏁版嵁锛屽弬鑰�
+ * @property {Boolean} step-searh = [true|false] 鏄惁鍒嗗竷鏌ヨ
+ * @value true 鍚敤鍒嗗竷鏌ヨ锛屼粎鏌ヨ褰撳墠閫変腑鑺傜偣
+ * @value false 鍏抽棴鍒嗗竷鏌ヨ锛屼竴娆℃煡璇㈠嚭鎵�鏈夋暟鎹�
+ * @property {String|DBFieldString} self-field 鍒嗗竷鏌ヨ褰撳墠瀛楁鍚嶇О
+ * @property {String|DBFieldString} parent-field 鍒嗗竷鏌ヨ鐖跺瓧娈靛悕绉�
+ * @property {String|DBCollectionString} collection 琛ㄥ悕
+ * @property {String|DBFieldString} field 鏌ヨ瀛楁锛屽涓瓧娈电敤 `,` 鍒嗗壊
+ * @property {String} orderby 鎺掑簭瀛楁鍙婃搴忓�掑彊璁剧疆
+ * @property {String|JQLString} where 鏌ヨ鏉′欢
+ */
+ export default {
+ name: 'UniDataPickerView',
+ emits: ['nodeclick', 'change', 'datachange', 'update:modelValue'],
+ mixins: [dataPicker],
+ props: {
+ managedMode: {
+ type: Boolean,
+ default: false
+ },
+ ellipsis: {
+ type: Boolean,
+ default: true
+ }
+ },
+ created() {
+ if (!this.managedMode) {
+ this.$nextTick(() => {
+ this.loadData();
+ })
+ }
+ },
+ methods: {
+ onPropsChange() {
+ this._treeData = [];
+ this.selectedIndex = 0;
+ this.$nextTick(() => {
+ this.loadData();
+ })
+ },
+ handleSelect(index) {
+ this.selectedIndex = index;
+ },
+ handleNodeClick(item, i, j) {
+ if (item.disable) {
+ return;
+ }
+
+ const node = this.dataList[i][j];
+ const text = node[this.map.text];
+ const value = node[this.map.value];
+
+ if (i < this.selected.length - 1) {
+ this.selected.splice(i, this.selected.length - i)
+ this.selected.push({
+ text,
+ value
+ })
+ } else if (i === this.selected.length - 1) {
+ this.selected.splice(i, 1, {
+ text,
+ value
+ })
+ }
+
+ if (node.isleaf) {
+ this.onSelectedChange(node, node.isleaf)
+ return
+ }
+
+ const {
+ isleaf,
+ hasNodes
+ } = this._updateBindData()
+
+ // 鏈湴鏁版嵁
+ if (this.isLocalData) {
+ this.onSelectedChange(node, (!hasNodes || isleaf))
+ } else if (this.isCloudDataList) { // Cloud 鏁版嵁 (鍗曞垪)
+ this.onSelectedChange(node, true)
+ } else if (this.isCloudDataTree) { // Cloud 鏁版嵁 (鏍戝舰)
+ if (isleaf) {
+ this.onSelectedChange(node, node.isleaf)
+ } else if (!hasNodes) { // 璇锋眰涓�娆℃湇鍔″櫒浠ョ‘瀹氭槸鍚︿负鍙跺瓙鑺傜偣
+ this.loadCloudDataNode((data) => {
+ if (!data.length) {
+ node.isleaf = true
+ } else {
+ this._treeData.push(...data)
+ this._updateBindData(node)
+ }
+ this.onSelectedChange(node, node.isleaf)
+ })
+ }
+ }
+ },
+ updateData(data) {
+ this._treeData = data.treeData
+ this.selected = data.selected
+ if (!this._treeData.length) {
+ this.loadData()
+ } else {
+ //this.selected = data.selected
+ this._updateBindData()
+ }
+ },
+ onDataChange() {
+ this.$emit('datachange');
+ },
+ onSelectedChange(node, isleaf) {
+ if (isleaf) {
+ this._dispatchEvent()
+ }
+
+ if (node) {
+ this.$emit('nodeclick', node)
+ }
+ },
+ _dispatchEvent() {
+ this.$emit('change', this.selected.slice(0))
+ }
+ }
+ }
+</script>
+
+<style lang="scss">
+ $uni-primary: #007aff !default;
+
+ .uni-data-pickerview {
+ flex: 1;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: column;
+ overflow: hidden;
+ height: 100%;
+ }
+
+ .error-text {
+ color: #DD524D;
+ }
+
+ .loading-cover {
+ position: absolute;
+ left: 0;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ background-color: rgba(255, 255, 255, .5);
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: column;
+ align-items: center;
+ z-index: 1001;
+ }
+
+ .load-more {
+ /* #ifndef APP-NVUE */
+ margin: auto;
+ /* #endif */
+ }
+
+ .error-message {
+ background-color: #fff;
+ position: absolute;
+ left: 0;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ padding: 15px;
+ opacity: .9;
+ z-index: 102;
+ }
+
+ /* #ifdef APP-NVUE */
+ .selected-area {
+ width: 750rpx;
+ }
+ /* #endif */
+
+ .selected-list {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ flex-wrap: nowrap;
+ /* #endif */
+ flex-direction: row;
+ padding: 0 5px;
+ border-bottom: 1px solid #f8f8f8;
+ }
+
+ .selected-item {
+ margin-left: 10px;
+ margin-right: 10px;
+ padding: 12px 0;
+ text-align: center;
+ /* #ifndef APP-NVUE */
+ white-space: nowrap;
+ /* #endif */
+ }
+
+ .selected-item-text-overflow {
+ width: 168px;
+ /* fix nvue */
+ overflow: hidden;
+ /* #ifndef APP-NVUE */
+ width: 6em;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ -o-text-overflow: ellipsis;
+ /* #endif */
+ }
+
+ .selected-item-active {
+ border-bottom: 2px solid $uni-primary;
+ }
+
+ .selected-item-text {
+ color: $uni-primary;
+ }
+
+ .tab-c {
+ position: relative;
+ flex: 1;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ overflow: hidden;
+ }
+
+ .list {
+ flex: 1;
+ }
+
+ .item {
+ padding: 12px 15px;
+ /* border-bottom: 1px solid #f0f0f0; */
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ justify-content: space-between;
+ }
+
+ .is-disabled {
+ opacity: .5;
+ }
+
+ .item-text {
+ /* flex: 1; */
+ color: #333333;
+ }
+
+ .item-text-overflow {
+ width: 280px;
+ /* fix nvue */
+ overflow: hidden;
+ /* #ifndef APP-NVUE */
+ width: 20em;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ -o-text-overflow: ellipsis;
+ /* #endif */
+ }
+
+ .check {
+ margin-right: 5px;
+ border: 2px solid $uni-primary;
+ border-left: 0;
+ border-top: 0;
+ height: 12px;
+ width: 6px;
+ transform-origin: center;
+ /* #ifndef APP-NVUE */
+ transition: all 0.3s;
+ /* #endif */
+ transform: rotate(45deg);
+ }
+</style>
diff --git a/app/uni_modules/uni-data-picker/package.json b/app/uni_modules/uni-data-picker/package.json
new file mode 100644
index 0000000..038f9ce
--- /dev/null
+++ b/app/uni_modules/uni-data-picker/package.json
@@ -0,0 +1,90 @@
+{
+ "id": "uni-data-picker",
+ "displayName": "uni-data-picker 鏁版嵁椹卞姩鐨刾icker閫夋嫨鍣�",
+ "version": "1.1.2",
+ "description": "鍗曞垪銆佸鍒楃骇鑱旈�夋嫨鍣紝甯哥敤浜庣渷甯傚尯鍩庡競閫夋嫨銆佸叕鍙搁儴闂ㄩ�夋嫨銆佸绾у垎绫荤瓑鍦烘櫙",
+ "keywords": [
+ "uni-ui",
+ "uniui",
+ "picker",
+ "绾ц仈",
+ "鐪佸競鍖�",
+ ""
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+"dcloudext": {
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+ "type": "component-vue"
+ },
+ "uni_modules": {
+ "dependencies": [
+ "uni-load-more",
+ "uni-icons",
+ "uni-scss"
+ ],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "u"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y",
+ "浜笢": "u"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "u",
+ "鑱旂洘": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/uni_modules/uni-data-picker/readme.md b/app/uni_modules/uni-data-picker/readme.md
new file mode 100644
index 0000000..6cda224
--- /dev/null
+++ b/app/uni_modules/uni-data-picker/readme.md
@@ -0,0 +1,22 @@
+## DataPicker 绾ц仈閫夋嫨
+> **缁勪欢鍚嶏細uni-data-picker**
+> 浠g爜鍧楋細 `uDataPicker`
+> 鍏宠仈缁勪欢锛歚uni-data-pickerview`銆乣uni-load-more`銆�
+
+
+`<uni-data-picker>` 鏄竴涓�夋嫨绫籟datacom缁勪欢](https://uniapp.dcloud.net.cn/component/datacom)銆�
+
+鏀寔鍗曞垪銆佸拰澶氬垪绾ц仈閫夋嫨銆傚垪鏁版病鏈夐檺鍒讹紝濡傛灉灞忓箷鏄剧ず涓嶅叏锛岄《閮╰ab鍖哄煙浼氬乏鍙虫粴鍔ㄣ��
+
+鍊欓�夋暟鎹敮鎸佷竴娆℃�у姞杞藉畬姣曪紝涔熸敮鎸佹噿鍔犺浇锛屾瘮濡傜ず渚嬪浘涓紝閫夋嫨浜嗏�滃寳浜�濆悗锛屽姩鎬佸姞杞藉寳浜殑鍖哄幙鏁版嵁銆�
+
+`<uni-data-picker>` 缁勪欢灏ゅ叾閫傜敤浜庡湴鍧�閫夋嫨銆佸垎绫婚�夋嫨绛夐�夋嫨绫汇��
+
+`<uni-data-picker>` 鏀寔鏈湴鏁版嵁銆佷簯绔潤鎬佹暟鎹�(json)锛寀niCloud浜戞暟鎹簱鏁版嵁銆�
+
+`<uni-data-picker>` 鍙互閫氳繃JQL鐩磋繛uniCloud浜戞暟鎹簱锛岄厤濂梉DB Schema](https://uniapp.dcloud.net.cn/uniCloud/schema)锛屽彲鍦╯chema2code涓嚜鍔ㄧ敓鎴愬墠绔〉闈紝杩樻敮鎸佹湇鍔″櫒绔牎楠屻��
+
+鍦╱niCloud鏁版嵁琛ㄤ腑鏂板缓琛ㄢ�渦ni-id-address鈥濆拰鈥渙pendb-city-china鈥濓紝杩�2涓〃鐨剆chema鑷甫foreignKey鍏宠仈銆傚湪鈥渦ni-id-address鈥濊〃鐨勮〃缁撴瀯椤甸潰浣跨敤schema2code鐢熸垚鍓嶇椤甸潰锛屼細鑷姩鐢熸垚鍦板潃绠$悊鐨勭淮鎶ら〉闈紝鑷姩浠庘�渙pendb-city-china鈥濊〃鍖呭惈鐨勪腑鍥芥墍鏈夌渷甯傚尯淇℃伅閲岄�夋嫨鍦板潃銆�
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-data-picker)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
\ No newline at end of file
diff --git a/app/uni_modules/uni-data-select/changelog.md b/app/uni_modules/uni-data-select/changelog.md
new file mode 100644
index 0000000..eb3d1ce
--- /dev/null
+++ b/app/uni_modules/uni-data-select/changelog.md
@@ -0,0 +1,35 @@
+## 1.0.6锛�2023-04-12锛�
+- 淇 寰俊灏忕▼搴忕偣鍑绘椂浼氭敼鍙樿儗鏅鑹茬殑 bug
+## 1.0.5锛�2023-02-03锛�
+- 淇 绂佺敤鏃朵細鏄剧ず娓呯┖鎸夐挳
+## 1.0.4锛�2023-02-02锛�
+- 浼樺寲 鏌ヨ鏉′欢鐭湡鍐呭娆″彉鏇村彧鏌ヨ鏈�鍚庝竴娆″彉鏇村悗鐨勭粨鏋�
+- 璋冩暣 鍐呴儴缂撳瓨閿悕璋冩暣涓� uni-data-select-lastSelectedValue
+## 1.0.3锛�2023-01-16锛�
+- 淇 涓嶅叧鑱旀湇鍔$┖闂存姤閿欑殑闂
+## 1.0.2锛�2023-01-14锛�
+- 鏂板 灞炴�� `format` 鍙敤浜庢牸寮忓寲鏄剧ず閫夐」鍐呭
+## 1.0.1锛�2022-12-06锛�
+- 淇 褰搘here鍙樺寲鏃讹紝鏁版嵁涓嶄細鑷姩鏇存柊鐨勯棶棰�
+## 0.1.9锛�2022-09-05锛�
+- 淇 寰俊灏忕▼搴忎笅鎷夋鍑虹幇鍚庨�夋嫨浼氱偣鍑诲埌钂欐澘鍚庨潰鐨勮緭鍏ユ
+## 0.1.8锛�2022-08-29锛�
+- 淇 鐐瑰嚮鐨勪綅缃笉鍑嗙‘
+## 0.1.7锛�2022-08-12锛�
+- 鏂板 鏀寔 disabled 灞炴��
+## 0.1.6锛�2022-07-06锛�
+- 淇 pc绔搴﹀紓甯哥殑bug
+## 0.1.5
+- 淇 pc绔搴﹀紓甯哥殑bug
+## 0.1.4锛�2022-07-05锛�
+- 浼樺寲 鏄剧ず鏍峰紡
+## 0.1.3锛�2022-06-02锛�
+- 淇 localdata 璧嬪�间笉鐢熸晥鐨� bug
+- 鏂板 鏀寔 uni.scss 淇敼棰滆壊
+- 鏂板 鏀寔閫夐」绂佺敤锛堟暟鎹�夐」璁剧疆 disabled: true 鍗崇鐢級
+## 0.1.2锛�2022-05-08锛�
+- 淇 褰� value 涓� 0 鏃堕�夋嫨涓嶇敓鏁堢殑 bug
+## 0.1.1锛�2022-05-07锛�
+- 鏂板 璁颁綇涓婃鐨勯�夐」锛堜粎 collection 瀛樺湪鏃舵湁鏁堬級
+## 0.1.0锛�2022-04-22锛�
+- 鍒濆鍖�
diff --git a/app/uni_modules/uni-data-select/components/uni-data-select/uni-data-select.vue b/app/uni_modules/uni-data-select/components/uni-data-select/uni-data-select.vue
new file mode 100644
index 0000000..9b32348
--- /dev/null
+++ b/app/uni_modules/uni-data-select/components/uni-data-select/uni-data-select.vue
@@ -0,0 +1,517 @@
+<template>
+ <view class="uni-stat__select">
+ <span v-if="label" class="uni-label-text hide-on-phone">{{label + '锛�'}}</span>
+ <view class="uni-stat-box" :class="{'uni-stat__actived': current}">
+ <view class="uni-select" :class="{'uni-select--disabled':disabled}">
+ <view class="uni-select__input-box" @click="toggleSelector">
+ <view v-if="current" class="uni-select__input-text">{{current}}</view>
+ <view v-else class="uni-select__input-text uni-select__input-placeholder">{{typePlaceholder}}</view>
+ <view v-if="current && clear && !disabled" @click.stop="clearVal" >
+ <uni-icons type="clear" color="#c0c4cc" size="24"/>
+ </view>
+ <view v-else>
+ <uni-icons :type="showSelector? 'top' : 'bottom'" size="14" color="#999" />
+ </view>
+ </view>
+ <view class="uni-select--mask" v-if="showSelector" @click="toggleSelector" />
+ <view class="uni-select__selector" v-if="showSelector">
+ <view class="uni-popper__arrow"></view>
+ <scroll-view scroll-y="true" class="uni-select__selector-scroll">
+ <view class="uni-select__selector-empty" v-if="mixinDatacomResData.length === 0">
+ <text>{{emptyTips}}</text>
+ </view>
+ <view v-else class="uni-select__selector-item" v-for="(item,index) in mixinDatacomResData" :key="index"
+ @click="change(item)">
+ <text :class="{'uni-select__selector__disabled': item.disable}">{{formatItemName(item)}}</text>
+ </view>
+ </scroll-view>
+ </view>
+ </view>
+ </view>
+ </view>
+</template>
+
+<script>
+ /**
+ * DataChecklist 鏁版嵁閫夋嫨鍣�
+ * @description 閫氳繃鏁版嵁娓叉煋鐨勪笅鎷夋缁勪欢
+ * @tutorial https://uniapp.dcloud.io/component/uniui/uni-data-select
+ * @property {String} value 榛樿鍊�
+ * @property {Array} localdata 鏈湴鏁版嵁 锛屾牸寮� [{text:'',value:''}]
+ * @property {Boolean} clear 鏄惁鍙互娓呯┖宸查�夐」
+ * @property {Boolean} emptyText 娌℃湁鏁版嵁鏃舵樉绀虹殑鏂囧瓧 锛屾湰鍦版暟鎹棤鏁�
+ * @property {String} label 宸︿晶鏍囬
+ * @property {String} placeholder 杈撳叆妗嗙殑鎻愮ず鏂囧瓧
+ * @property {Boolean} disabled 鏄惁绂佺敤
+ * @event {Function} change 閫変腑鍙戠敓鍙樺寲瑙﹀彂
+ */
+
+ export default {
+ name: "uni-data-select",
+ mixins: [uniCloud.mixinDatacom || {}],
+ props: {
+ localdata: {
+ type: Array,
+ default () {
+ return []
+ }
+ },
+ value: {
+ type: [String, Number],
+ default: ''
+ },
+ modelValue: {
+ type: [String, Number],
+ default: ''
+ },
+ label: {
+ type: String,
+ default: ''
+ },
+ placeholder: {
+ type: String,
+ default: '璇烽�夋嫨'
+ },
+ emptyTips: {
+ type: String,
+ default: '鏃犻�夐」'
+ },
+ clear: {
+ type: Boolean,
+ default: true
+ },
+ defItem: {
+ type: Number,
+ default: 0
+ },
+ disabled: {
+ type: Boolean,
+ default: false
+ },
+ // 鏍煎紡鍖栬緭鍑� 鐢ㄦ硶 field="_id as value, version as text, uni_platform as label" format="{label} - {text}"
+ format: {
+ type: String,
+ default: ''
+ },
+ },
+ data() {
+ return {
+ showSelector: false,
+ current: '',
+ mixinDatacomResData: [],
+ apps: [],
+ channels: [],
+ cacheKey: "uni-data-select-lastSelectedValue",
+ };
+ },
+ created() {
+ this.debounceGet = this.debounce(() => {
+ this.query();
+ }, 300);
+ if (this.collection && !this.localdata.length) {
+ this.debounceGet();
+ }
+ },
+ computed: {
+ typePlaceholder() {
+ const text = {
+ 'opendb-stat-app-versions': '鐗堟湰',
+ 'opendb-app-channels': '娓犻亾',
+ 'opendb-app-list': '搴旂敤'
+ }
+ const common = this.placeholder
+ const placeholder = text[this.collection]
+ return placeholder ?
+ common + placeholder :
+ common
+ },
+ valueCom(){
+ // #ifdef VUE3
+ return this.modelValue;
+ // #endif
+ // #ifndef VUE3
+ return this.value;
+ // #endif
+ }
+ },
+ watch: {
+ localdata: {
+ immediate: true,
+ handler(val, old) {
+ if (Array.isArray(val) && old !== val) {
+ this.mixinDatacomResData = val
+ }
+ }
+ },
+ valueCom(val, old) {
+ this.initDefVal()
+ },
+ mixinDatacomResData: {
+ immediate: true,
+ handler(val) {
+ if (val.length) {
+ this.initDefVal()
+ }
+ }
+ }
+ },
+ methods: {
+ debounce(fn, time = 100){
+ let timer = null
+ return function(...args) {
+ if (timer) clearTimeout(timer)
+ timer = setTimeout(() => {
+ fn.apply(this, args)
+ }, time)
+ }
+ },
+ // 鎵ц鏁版嵁搴撴煡璇�
+ query(){
+ this.mixinDatacomEasyGet();
+ },
+ // 鐩戝惉鏌ヨ鏉′欢鍙樻洿浜嬩欢
+ onMixinDatacomPropsChange(){
+ if (this.collection) {
+ this.debounceGet();
+ }
+ },
+ initDefVal() {
+ let defValue = ''
+ if ((this.valueCom || this.valueCom === 0) && !this.isDisabled(this.valueCom)) {
+ defValue = this.valueCom
+ } else {
+ let strogeValue
+ if (this.collection) {
+ strogeValue = this.getCache()
+ }
+ if (strogeValue || strogeValue === 0) {
+ defValue = strogeValue
+ } else {
+ let defItem = ''
+ if (this.defItem > 0 && this.defItem <= this.mixinDatacomResData.length) {
+ defItem = this.mixinDatacomResData[this.defItem - 1].value
+ }
+ defValue = defItem
+ }
+ if (defValue || defValue === 0) {
+ this.emit(defValue)
+ }
+ }
+ const def = this.mixinDatacomResData.find(item => item.value === defValue)
+ this.current = def ? this.formatItemName(def) : ''
+ },
+
+ /**
+ * @param {[String, Number]} value
+ * 鍒ゆ柇鐢ㄦ埛缁欑殑 value 鏄惁鍚屾椂涓虹鐢ㄧ姸鎬�
+ */
+ isDisabled(value) {
+ let isDisabled = false;
+
+ this.mixinDatacomResData.forEach(item => {
+ if (item.value === value) {
+ isDisabled = item.disable
+ }
+ })
+
+ return isDisabled;
+ },
+
+ clearVal() {
+ this.emit('')
+ if (this.collection) {
+ this.removeCache()
+ }
+ },
+ change(item) {
+ if (!item.disable) {
+ this.showSelector = false
+ this.current = this.formatItemName(item)
+ this.emit(item.value)
+ }
+ },
+ emit(val) {
+ this.$emit('input', val)
+ this.$emit('update:modelValue', val)
+ this.$emit('change', val)
+ if (this.collection) {
+ this.setCache(val);
+ }
+ },
+ toggleSelector() {
+ if (this.disabled) {
+ return
+ }
+
+ this.showSelector = !this.showSelector
+ },
+ formatItemName(item) {
+ let {
+ text,
+ value,
+ channel_code
+ } = item
+ channel_code = channel_code ? `(${channel_code})` : ''
+
+ if (this.format) {
+ // 鏍煎紡鍖栬緭鍑�
+ let str = "";
+ str = this.format;
+ for (let key in item) {
+ str = str.replace(new RegExp(`{${key}}`,"g"),item[key]);
+ }
+ return str;
+ } else {
+ return this.collection.indexOf('app-list') > 0 ?
+ `${text}(${value})` :
+ (
+ text ?
+ text :
+ `鏈懡鍚�${channel_code}`
+ )
+ }
+ },
+ // 鑾峰彇褰撳墠鍔犺浇鐨勬暟鎹�
+ getLoadData(){
+ return this.mixinDatacomResData;
+ },
+ // 鑾峰彇褰撳墠缂撳瓨key
+ getCurrentCacheKey(){
+ return this.collection;
+ },
+ // 鑾峰彇缂撳瓨
+ getCache(name=this.getCurrentCacheKey()){
+ let cacheData = uni.getStorageSync(this.cacheKey) || {};
+ return cacheData[name];
+ },
+ // 璁剧疆缂撳瓨
+ setCache(value, name=this.getCurrentCacheKey()){
+ let cacheData = uni.getStorageSync(this.cacheKey) || {};
+ cacheData[name] = value;
+ uni.setStorageSync(this.cacheKey, cacheData);
+ },
+ // 鍒犻櫎缂撳瓨
+ removeCache(name=this.getCurrentCacheKey()){
+ let cacheData = uni.getStorageSync(this.cacheKey) || {};
+ delete cacheData[name];
+ uni.setStorageSync(this.cacheKey, cacheData);
+ },
+ }
+ }
+</script>
+
+<style lang="scss">
+ $uni-base-color: #6a6a6a !default;
+ $uni-main-color: #333 !default;
+ $uni-secondary-color: #909399 !default;
+ $uni-border-3: #e5e5e5;
+
+
+ /* #ifndef APP-NVUE */
+ @media screen and (max-width: 500px) {
+ .hide-on-phone {
+ display: none;
+ }
+ }
+
+ /* #endif */
+ .uni-stat__select {
+ display: flex;
+ align-items: center;
+ // padding: 15px;
+ /* #ifdef H5 */
+ cursor: pointer;
+ /* #endif */
+ width: 100%;
+ flex: 1;
+ box-sizing: border-box;
+ }
+
+ .uni-stat-box {
+ width: 100%;
+ flex: 1;
+ }
+
+ .uni-stat__actived {
+ width: 100%;
+ flex: 1;
+ // outline: 1px solid #2979ff;
+ }
+
+ .uni-label-text {
+ font-size: 14px;
+ font-weight: bold;
+ color: $uni-base-color;
+ margin: auto 0;
+ margin-right: 5px;
+ }
+
+ .uni-select {
+ font-size: 14px;
+ border: 1px solid $uni-border-3;
+ box-sizing: border-box;
+ border-radius: 4px;
+ padding: 0 5px;
+ padding-left: 10px;
+ position: relative;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ user-select: none;
+ /* #endif */
+ flex-direction: row;
+ align-items: center;
+ border-bottom: solid 1px $uni-border-3;
+ width: 100%;
+ flex: 1;
+ height: 35px;
+
+ &--disabled {
+ background-color: #f5f7fa;
+ cursor: not-allowed;
+ }
+ }
+
+ .uni-select__label {
+ font-size: 16px;
+ // line-height: 22px;
+ height: 35px;
+ padding-right: 10px;
+ color: $uni-secondary-color;
+ }
+
+ .uni-select__input-box {
+ height: 35px;
+ position: relative;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex: 1;
+ flex-direction: row;
+ align-items: center;
+ }
+
+ .uni-select__input {
+ flex: 1;
+ font-size: 14px;
+ height: 22px;
+ line-height: 22px;
+ }
+
+ .uni-select__input-plac {
+ font-size: 14px;
+ color: $uni-secondary-color;
+ }
+
+ .uni-select__selector {
+ /* #ifndef APP-NVUE */
+ box-sizing: border-box;
+ /* #endif */
+ position: absolute;
+ top: calc(100% + 12px);
+ left: 0;
+ width: 100%;
+ background-color: #FFFFFF;
+ border: 1px solid #EBEEF5;
+ border-radius: 6px;
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+ z-index: 3;
+ padding: 4px 0;
+ }
+
+ .uni-select__selector-scroll {
+ /* #ifndef APP-NVUE */
+ max-height: 200px;
+ box-sizing: border-box;
+ /* #endif */
+ }
+
+ /* #ifdef H5 */
+ @media (min-width: 768px) {
+ .uni-select__selector-scroll {
+ max-height: 600px;
+ }
+ }
+ /* #endif */
+
+ .uni-select__selector-empty,
+ .uni-select__selector-item {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ cursor: pointer;
+ /* #endif */
+ line-height: 35px;
+ font-size: 14px;
+ text-align: center;
+ /* border-bottom: solid 1px $uni-border-3; */
+ padding: 0px 10px;
+ }
+
+ .uni-select__selector-item:hover {
+ background-color: #f9f9f9;
+ }
+
+ .uni-select__selector-empty:last-child,
+ .uni-select__selector-item:last-child {
+ /* #ifndef APP-NVUE */
+ border-bottom: none;
+ /* #endif */
+ }
+
+ .uni-select__selector__disabled {
+ opacity: 0.4;
+ cursor: default;
+ }
+
+ /* picker 寮瑰嚭灞傞�氱敤鐨勬寚绀哄皬涓夎 */
+ .uni-popper__arrow,
+ .uni-popper__arrow::after {
+ position: absolute;
+ display: block;
+ width: 0;
+ height: 0;
+ border-color: transparent;
+ border-style: solid;
+ border-width: 6px;
+ }
+
+ .uni-popper__arrow {
+ filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03));
+ top: -6px;
+ left: 10%;
+ margin-right: 3px;
+ border-top-width: 0;
+ border-bottom-color: #EBEEF5;
+ }
+
+ .uni-popper__arrow::after {
+ content: " ";
+ top: 1px;
+ margin-left: -6px;
+ border-top-width: 0;
+ border-bottom-color: #fff;
+ }
+
+ .uni-select__input-text {
+ // width: 280px;
+ width: 100%;
+ color: $uni-main-color;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ -o-text-overflow: ellipsis;
+ overflow: hidden;
+ }
+
+ .uni-select__input-placeholder {
+ color: $uni-base-color;
+ font-size: 12px;
+ }
+
+ .uni-select--mask {
+ position: fixed;
+ top: 0;
+ bottom: 0;
+ right: 0;
+ left: 0;
+ z-index: 2;
+ }
+</style>
diff --git a/app/uni_modules/uni-data-select/package.json b/app/uni_modules/uni-data-select/package.json
new file mode 100644
index 0000000..0187429
--- /dev/null
+++ b/app/uni_modules/uni-data-select/package.json
@@ -0,0 +1,85 @@
+{
+ "id": "uni-data-select",
+ "displayName": "uni-data-select 涓嬫媺妗嗛�夋嫨鍣�",
+ "version": "1.0.6",
+ "description": "閫氳繃鏁版嵁椹卞姩鐨勪笅鎷夋閫夋嫨鍣�",
+ "keywords": [
+ "uni-ui",
+ "select",
+ "uni-data-select",
+ "涓嬫媺妗�",
+ "涓嬫媺閫�"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": "^3.1.1"
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+"dcloudext": {
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+ "type": "component-vue"
+ },
+ "uni_modules": {
+ "dependencies": ["uni-load-more"],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "u",
+ "app-nvue": "n"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "u",
+ "鐧惧害": "u",
+ "瀛楄妭璺冲姩": "u",
+ "QQ": "u",
+ "浜笢": "u"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "u",
+ "鑱旂洘": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
diff --git a/app/uni_modules/uni-data-select/readme.md b/app/uni_modules/uni-data-select/readme.md
new file mode 100644
index 0000000..eb58de3
--- /dev/null
+++ b/app/uni_modules/uni-data-select/readme.md
@@ -0,0 +1,8 @@
+## DataSelect 涓嬫媺妗嗛�夋嫨鍣�
+> **缁勪欢鍚嶏細uni-data-select**
+> 浠g爜鍧楋細 `uDataSelect`
+
+褰撻�夐」杩囧鏃讹紝浣跨敤涓嬫媺鑿滃崟灞曠ず骞堕�夋嫨鍐呭
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-data-select)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
diff --git a/app/uni_modules/uni-dateformat/changelog.md b/app/uni_modules/uni-dateformat/changelog.md
new file mode 100644
index 0000000..d551d7b
--- /dev/null
+++ b/app/uni_modules/uni-dateformat/changelog.md
@@ -0,0 +1,10 @@
+## 1.0.0锛�2021-11-19锛�
+- 浼樺寲 缁勪欢UI锛屽苟鎻愪緵璁捐璧勬簮锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 鏂囨。杩佺Щ锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/uni-dateformat](https://uniapp.dcloud.io/component/uniui/uni-dateformat)
+## 0.0.5锛�2021-07-08锛�
+- 璋冩暣 榛樿鏃堕棿涓嶅啀鏄綋鍓嶆椂闂达紝鑰屾槸鏄剧ず'-'瀛楃
+## 0.0.4锛�2021-05-12锛�
+- 鏂板 缁勪欢绀轰緥鍦板潃
+## 0.0.3锛�2021-02-04锛�
+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
+- 淇 iOS 骞冲彴鏃ユ湡鏍煎紡鍖栧嚭閿欑殑闂
diff --git a/app/uni_modules/uni-dateformat/components/uni-dateformat/date-format.js b/app/uni_modules/uni-dateformat/components/uni-dateformat/date-format.js
new file mode 100644
index 0000000..e00d559
--- /dev/null
+++ b/app/uni_modules/uni-dateformat/components/uni-dateformat/date-format.js
@@ -0,0 +1,200 @@
+// yyyy-MM-dd hh:mm:ss.SSS 鎵�鏈夋敮鎸佺殑绫诲瀷
+function pad(str, length = 2) {
+ str += ''
+ while (str.length < length) {
+ str = '0' + str
+ }
+ return str.slice(-length)
+}
+
+const parser = {
+ yyyy: (dateObj) => {
+ return pad(dateObj.year, 4)
+ },
+ yy: (dateObj) => {
+ return pad(dateObj.year)
+ },
+ MM: (dateObj) => {
+ return pad(dateObj.month)
+ },
+ M: (dateObj) => {
+ return dateObj.month
+ },
+ dd: (dateObj) => {
+ return pad(dateObj.day)
+ },
+ d: (dateObj) => {
+ return dateObj.day
+ },
+ hh: (dateObj) => {
+ return pad(dateObj.hour)
+ },
+ h: (dateObj) => {
+ return dateObj.hour
+ },
+ mm: (dateObj) => {
+ return pad(dateObj.minute)
+ },
+ m: (dateObj) => {
+ return dateObj.minute
+ },
+ ss: (dateObj) => {
+ return pad(dateObj.second)
+ },
+ s: (dateObj) => {
+ return dateObj.second
+ },
+ SSS: (dateObj) => {
+ return pad(dateObj.millisecond, 3)
+ },
+ S: (dateObj) => {
+ return dateObj.millisecond
+ },
+}
+
+// 杩欓兘n骞翠簡iOS渚濈劧涓嶈璇�2020-12-12锛岄渶瑕佽浆鎹负2020/12/12
+function getDate(time) {
+ if (time instanceof Date) {
+ return time
+ }
+ switch (typeof time) {
+ case 'string':
+ {
+ // 2020-12-12T12:12:12.000Z銆�2020-12-12T12:12:12.000
+ if (time.indexOf('T') > -1) {
+ return new Date(time)
+ }
+ return new Date(time.replace(/-/g, '/'))
+ }
+ default:
+ return new Date(time)
+ }
+}
+
+export function formatDate(date, format = 'yyyy/MM/dd hh:mm:ss') {
+ if (!date && date !== 0) {
+ return ''
+ }
+ date = getDate(date)
+ const dateObj = {
+ year: date.getFullYear(),
+ month: date.getMonth() + 1,
+ day: date.getDate(),
+ hour: date.getHours(),
+ minute: date.getMinutes(),
+ second: date.getSeconds(),
+ millisecond: date.getMilliseconds()
+ }
+ const tokenRegExp = /yyyy|yy|MM|M|dd|d|hh|h|mm|m|ss|s|SSS|SS|S/
+ let flag = true
+ let result = format
+ while (flag) {
+ flag = false
+ result = result.replace(tokenRegExp, function(matched) {
+ flag = true
+ return parser[matched](dateObj)
+ })
+ }
+ return result
+}
+
+export function friendlyDate(time, {
+ locale = 'zh',
+ threshold = [60000, 3600000],
+ format = 'yyyy/MM/dd hh:mm:ss'
+}) {
+ if (time === '-') {
+ return time
+ }
+ if (!time && time !== 0) {
+ return ''
+ }
+ const localeText = {
+ zh: {
+ year: '骞�',
+ month: '鏈�',
+ day: '澶�',
+ hour: '灏忔椂',
+ minute: '鍒嗛挓',
+ second: '绉�',
+ ago: '鍓�',
+ later: '鍚�',
+ justNow: '鍒氬垰',
+ soon: '椹笂',
+ template: '{num}{unit}{suffix}'
+ },
+ en: {
+ year: 'year',
+ month: 'month',
+ day: 'day',
+ hour: 'hour',
+ minute: 'minute',
+ second: 'second',
+ ago: 'ago',
+ later: 'later',
+ justNow: 'just now',
+ soon: 'soon',
+ template: '{num} {unit} {suffix}'
+ }
+ }
+ const text = localeText[locale] || localeText.zh
+ let date = getDate(time)
+ let ms = date.getTime() - Date.now()
+ let absMs = Math.abs(ms)
+ if (absMs < threshold[0]) {
+ return ms < 0 ? text.justNow : text.soon
+ }
+ if (absMs >= threshold[1]) {
+ return formatDate(date, format)
+ }
+ let num
+ let unit
+ let suffix = text.later
+ if (ms < 0) {
+ suffix = text.ago
+ ms = -ms
+ }
+ const seconds = Math.floor((ms) / 1000)
+ const minutes = Math.floor(seconds / 60)
+ const hours = Math.floor(minutes / 60)
+ const days = Math.floor(hours / 24)
+ const months = Math.floor(days / 30)
+ const years = Math.floor(months / 12)
+ switch (true) {
+ case years > 0:
+ num = years
+ unit = text.year
+ break
+ case months > 0:
+ num = months
+ unit = text.month
+ break
+ case days > 0:
+ num = days
+ unit = text.day
+ break
+ case hours > 0:
+ num = hours
+ unit = text.hour
+ break
+ case minutes > 0:
+ num = minutes
+ unit = text.minute
+ break
+ default:
+ num = seconds
+ unit = text.second
+ break
+ }
+
+ if (locale === 'en') {
+ if (num === 1) {
+ num = 'a'
+ } else {
+ unit += 's'
+ }
+ }
+
+ return text.template.replace(/{\s*num\s*}/g, num + '').replace(/{\s*unit\s*}/g, unit).replace(/{\s*suffix\s*}/g,
+ suffix)
+}
diff --git a/app/uni_modules/uni-dateformat/components/uni-dateformat/uni-dateformat.vue b/app/uni_modules/uni-dateformat/components/uni-dateformat/uni-dateformat.vue
new file mode 100644
index 0000000..c5ed030
--- /dev/null
+++ b/app/uni_modules/uni-dateformat/components/uni-dateformat/uni-dateformat.vue
@@ -0,0 +1,88 @@
+<template>
+ <text>{{dateShow}}</text>
+</template>
+
+<script>
+ import {friendlyDate} from './date-format.js'
+ /**
+ * Dateformat 鏃ユ湡鏍煎紡鍖�
+ * @description 鏃ユ湡鏍煎紡鍖栫粍浠�
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=3279
+ * @property {Object|String|Number} date 鏃ユ湡瀵硅薄/鏃ユ湡瀛楃涓�/鏃堕棿鎴�
+ * @property {String} locale 鏍煎紡鍖栦娇鐢ㄧ殑璇█
+ * @value zh 涓枃
+ * @value en 鑻辨枃
+ * @property {Array} threshold 搴旂敤涓嶅悓绫诲瀷鏍煎紡鍖栫殑闃堝��
+ * @property {String} format 杈撳嚭鏃ユ湡瀛楃涓叉椂鐨勬牸寮�
+ */
+ export default {
+ name: 'uniDateformat',
+ props: {
+ date: {
+ type: [Object, String, Number],
+ default () {
+ return '-'
+ }
+ },
+ locale: {
+ type: String,
+ default: 'zh',
+ },
+ threshold: {
+ type: Array,
+ default () {
+ return [0, 0]
+ }
+ },
+ format: {
+ type: String,
+ default: 'yyyy/MM/dd hh:mm:ss'
+ },
+ // refreshRate浣跨敤涓嶅綋鍙兘瀵艰嚧鎬ц兘闂锛岃皑鎱庝娇鐢�
+ refreshRate: {
+ type: [Number, String],
+ default: 0
+ }
+ },
+ data() {
+ return {
+ refreshMark: 0
+ }
+ },
+ computed: {
+ dateShow() {
+ this.refreshMark
+ return friendlyDate(this.date, {
+ locale: this.locale,
+ threshold: this.threshold,
+ format: this.format
+ })
+ }
+ },
+ watch: {
+ refreshRate: {
+ handler() {
+ this.setAutoRefresh()
+ },
+ immediate: true
+ }
+ },
+ methods: {
+ refresh() {
+ this.refreshMark++
+ },
+ setAutoRefresh() {
+ clearInterval(this.refreshInterval)
+ if (this.refreshRate) {
+ this.refreshInterval = setInterval(() => {
+ this.refresh()
+ }, parseInt(this.refreshRate))
+ }
+ }
+ }
+ }
+</script>
+
+<style>
+
+</style>
diff --git a/app/uni_modules/uni-dateformat/package.json b/app/uni_modules/uni-dateformat/package.json
new file mode 100644
index 0000000..786a670
--- /dev/null
+++ b/app/uni_modules/uni-dateformat/package.json
@@ -0,0 +1,88 @@
+{
+ "id": "uni-dateformat",
+ "displayName": "uni-dateformat 鏃ユ湡鏍煎紡鍖�",
+ "version": "1.0.0",
+ "description": "鏃ユ湡鏍煎紡鍖栫粍浠讹紝鍙互灏嗘棩鏈熸牸寮忓寲涓�1鍒嗛挓鍓嶃�佸垰鍒氱瓑褰㈠紡",
+ "keywords": [
+ "uni-ui",
+ "uniui",
+ "鏃ユ湡鏍煎紡鍖�",
+ "鏃堕棿鏍煎紡鍖�",
+ "鏍煎紡鍖栨椂闂�",
+ ""
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "鍓嶇缁勪欢",
+ "閫氱敤缁勪欢"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": ["uni-scss"],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "y",
+ "鑱旂洘": "y"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/uni_modules/uni-dateformat/readme.md b/app/uni_modules/uni-dateformat/readme.md
new file mode 100644
index 0000000..37ddb6e
--- /dev/null
+++ b/app/uni_modules/uni-dateformat/readme.md
@@ -0,0 +1,11 @@
+
+
+### DateFormat 鏃ユ湡鏍煎紡鍖�
+> **缁勪欢鍚嶏細uni-dateformat**
+> 浠g爜鍧楋細 `uDateformat`
+
+
+鏃ユ湡鏍煎紡鍖栫粍浠躲��
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-dateformat)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
\ No newline at end of file
diff --git a/app/uni_modules/uni-datetime-picker/changelog.md b/app/uni_modules/uni-datetime-picker/changelog.md
new file mode 100644
index 0000000..1f1a554
--- /dev/null
+++ b/app/uni_modules/uni-datetime-picker/changelog.md
@@ -0,0 +1,133 @@
+## 2.2.22锛�2023-03-30锛�
+- 淇 鏃ュ巻 picker 淇敼骞存湀鍚庯紝鑷姩閫変腑褰撴湀1鏃� [璇︽儏](https://ask.dcloud.net.cn/question/165937)
+- 淇 灏忕▼搴忕 浣庣増鏈� ios NaN [璇︽儏](https://ask.dcloud.net.cn/question/162979)
+## 2.2.21锛�2023-02-20锛�
+- 淇 firefox 娴忚鍣ㄦ樉绀哄尯鍩熺偣鍑绘棤娉曟媺璧锋棩鍘嗗脊妗嗙殑Bug [璇︽儏](https://ask.dcloud.net.cn/question/163362)
+## 2.2.20锛�2023-02-17锛�
+- 浼樺寲 鍊间负绌轰緷鐒堕�変腑褰撳ぉ闂
+- 浼樺寲 鎻愪緵 default-value 灞炴�ф敮鎸侀厤缃�夋嫨鍣ㄦ墦寮�鏃堕粯璁ゆ樉绀虹殑鏃堕棿
+- 浼樺寲 闈炶寖鍥撮�夋嫨鏈�夋嫨鏃ユ湡鏃堕棿锛岀偣鍑荤‘璁ゆ寜閽�変腑褰撳墠鏃ユ湡鏃堕棿
+- 浼樺寲 瀛楄妭灏忕▼搴忔棩鏈熸椂闂磋寖鍥撮�夋嫨锛屽簳閮ㄦ棩鏈熸崲琛岄棶棰�
+## 2.2.19锛�2023-02-09锛�
+- 淇 2.2.18 寮曡捣鑼冨洿閫夋嫨閰嶇疆 end 閫夋嫨鏃犳晥鐨凚ug [璇︽儏](https://github.com/dcloudio/uni-ui/issues/686)
+## 2.2.18锛�2023-02-08锛�
+- 淇 绉诲姩绔寖鍥撮�夋嫨change浜嬩欢瑙﹀彂寮傚父鐨凚ug [璇︽儏](https://github.com/dcloudio/uni-ui/issues/684)
+- 浼樺寲 PC绔緭鍏ユ棩鏈熸牸寮忛敊璇椂杩斿洖褰撳墠鏃ユ湡鏃堕棿
+- 浼樺寲 PC绔緭鍏ユ棩鏈熸椂闂磋秴鍑� start銆乪nd 闄愬埗鐨凚ug
+- 浼樺寲 绉诲姩绔棩鏈熸椂闂磋寖鍥寸敤娉曟椂闂村睍绀轰笉瀹屾暣闂
+## 2.2.17锛�2023-02-04锛�
+- 淇 灏忕▼搴忕缁戝畾 Date 绫诲瀷鎶ラ敊鐨凚ug [璇︽儏](https://github.com/dcloudio/uni-ui/issues/679)
+- 淇 vue3 time-picker 鏃犳硶鏄剧ず缁戝畾鏃跺垎绉掔殑Bug
+## 2.2.16锛�2023-02-02锛�
+- 淇 瀛楄妭灏忕▼搴忔姤閿欑殑Bug
+## 2.2.15锛�2023-02-02锛�
+- 淇 鏌愪簺鎯呭喌鍒囨崲鏈堜唤閿欒鐨凚ug
+## 2.2.14锛�2023-01-30锛�
+- 淇 鏌愪簺鎯呭喌鍒囨崲鏈堜唤閿欒鐨凚ug [璇︽儏](https://ask.dcloud.net.cn/question/162033)
+## 2.2.13锛�2023-01-10锛�
+- 淇 澶氭鍔犺浇缁勪欢閫犳垚鍐呭瓨鍗犵敤鐨凚ug
+## 2.2.12锛�2022-12-01锛�
+- 淇 vue3 涓� i18n 鍥介檯鍖栧垵濮嬪�间笉姝g‘鐨凚ug
+## 2.2.11锛�2022-09-19锛�
+- 淇 鏀粯瀹濆皬绋嬪簭鏍峰紡閿欎贡鐨凚ug [璇︽儏](https://github.com/dcloudio/uni-app/issues/3861)
+## 2.2.10锛�2022-09-19锛�
+- 淇 鍙嶅悜閫夋嫨鏃ユ湡鑼冨洿锛屾棩鏈熸樉绀哄紓甯哥殑Bug [璇︽儏](https://ask.dcloud.net.cn/question/153401?item_id=212892&rf=false)
+## 2.2.9锛�2022-09-16锛�
+- 鍙互浣跨敤 uni-scss 鎺у埗涓婚鑹�
+## 2.2.8锛�2022-09-08锛�
+- 淇 close浜嬩欢鏃犳晥鐨凚ug
+## 2.2.7锛�2022-09-05锛�
+- 淇 绉诲姩绔� maskClick 鏃犳晥鐨凚ug [璇︽儏](https://ask.dcloud.net.cn/question/140824)
+## 2.2.6锛�2022-06-30锛�
+- 浼樺寲 缁勪欢鏍峰紡锛岃皟鏁翠簡缁勪欢鍥炬爣澶у皬銆侀珮搴︺�侀鑹茬瓑锛屼笌uni-ui椋庢牸淇濇寔涓�鑷�
+## 2.2.5锛�2022-06-24锛�
+- 淇 鏃ュ巻椤堕儴骞存湀鍙婂簳閮ㄧ‘璁ゆ湭鍥介檯鍖栫殑Bug
+## 2.2.4锛�2022-03-31锛�
+- 淇 Vue3 涓嬪姩鎬佽祴鍊�,鍗曢�夌被鍨嬫湭鍝嶅簲鐨凚ug
+## 2.2.3锛�2022-03-28锛�
+- 淇 Vue3 涓嬪姩鎬佽祴鍊兼湭鍝嶅簲鐨凚ug
+## 2.2.2锛�2021-12-10锛�
+- 淇 clear-icon 灞炴�у湪灏忕▼搴忓钩鍙颁笉鐢熸晥鐨凚ug
+## 2.2.1锛�2021-12-10锛�
+- 淇 鏃ユ湡鑼冨洿閫夊湪灏忕▼搴忓钩鍙帮紝蹇呴』澶氱偣鍑讳竴娆℃墠鑳藉彇娑堥�変腑鐘舵�佺殑Bug
+## 2.2.0锛�2021-11-19锛�
+- 浼樺寲 缁勪欢UI锛屽苟鎻愪緵璁捐璧勬簮 [璇︽儏](https://uniapp.dcloud.io/component/uniui/resource)
+- 鏂囨。杩佺Щ [https://uniapp.dcloud.io/component/uniui/uni-datetime-picker](https://uniapp.dcloud.io/component/uniui/uni-datetime-picker)
+## 2.1.5锛�2021-11-09锛�
+- 鏂板 鎻愪緵缁勪欢璁捐璧勬簮锛岀粍浠舵牱寮忚皟鏁�
+## 2.1.4锛�2021-09-10锛�
+- 淇 hide-second 鍦ㄧЩ鍔ㄧ鐨凚ug
+- 淇 鍗曢�夎祴榛樿鍊兼椂锛岃祴鍊兼棩鏈熸湭楂樹寒鐨凚ug
+- 淇 璧嬮粯璁ゅ�兼椂锛岀Щ鍔ㄧ鏈纭樉绀烘椂闂寸殑Bug
+## 2.1.3锛�2021-09-09锛�
+- 鏂板 hide-second 灞炴�э紝鏀寔鍙娇鐢ㄦ椂鍒嗭紝闅愯棌绉�
+## 2.1.2锛�2021-09-03锛�
+- 浼樺寲 鍙栨秷閫変腑鏃讹紙鑼冨洿閫夛級鐩存帴寮�濮嬩笅涓�娆¢�夋嫨, 閬垮厤澶氱偣涓�娆�
+- 浼樺寲 绉诲姩绔敮鎸佹竻闄ゆ寜閽紝鍚屾椂鏀寔閫氳繃 ref 璋冪敤缁勪欢鐨� clear 鏂规硶
+- 浼樺寲 璋冩暣瀛楀彿澶у皬锛岀編鍖栨棩鍘嗙晫闈�
+- 淇 鍥犲浗闄呭寲瀵艰嚧鐨� placeholder 澶辨晥鐨凚ug
+## 2.1.1锛�2021-08-24锛�
+- 鏂板 鏀寔鍥介檯鍖�
+- 浼樺寲 鑼冨洿閫夋嫨鍣ㄥ湪 pc 绔繃瀹界殑闂
+## 2.1.0锛�2021-08-09锛�
+- 鏂板 閫傞厤 vue3
+## 2.0.19锛�2021-08-09锛�
+- 鏂板 鏀寔浣滀负 uni-forms 瀛愮粍浠剁浉鍏冲姛鑳�
+- 淇 鍦� uni-forms 涓娇鐢ㄦ椂锛岄�夋嫨鏃堕棿鎶� NAN 閿欒鐨凚ug
+## 2.0.18锛�2021-08-05锛�
+- 淇 type 灞炴�у姩鎬佽祴鍊兼棤鏁堢殑Bug
+- 淇 鈥樼‘璁も�欐寜閽 tabbar 閬洊 bug
+- 淇 缁勪欢鏈祴鍊兼椂鑼冨洿閫夊乏銆佸彸鏃ュ巻鐩稿悓鐨凚ug
+## 2.0.17锛�2021-08-04锛�
+- 淇 鑼冨洿閫夋湭姝g‘鏄剧ず褰撳墠鍊肩殑Bug
+- 淇 h5 骞冲彴锛堢Щ鍔ㄧ锛夋姤閿� 'cale' of undefined 鐨凚ug
+## 2.0.16锛�2021-07-21锛�
+- 鏂板 return-type 灞炴�ф敮鎸佽繑鍥� date 鏃ユ湡瀵硅薄
+## 2.0.15锛�2021-07-14锛�
+- 淇 鍗曢�夋棩鏈熺被鍨嬶紝鍒濆璧嬪�煎悗涓嶅湪褰撳墠鏃ュ巻鐨凚ug
+- 鏂板 clearIcon 灞炴�э紝鏄剧ず妗嗙殑娓呯┖鎸夐挳鍙厤缃樉绀洪殣钘忥紙浠� pc 鏈夋晥锛�
+- 浼樺寲 绉诲姩绔Щ闄ゆ樉绀烘鐨勬竻绌烘寜閽紝鏃犲疄闄呯敤閫�
+## 2.0.14锛�2021-07-14锛�
+- 淇 缁勪欢璧嬪�间负绌猴紝鐣岄潰鏈洿鏂扮殑Bug
+- 淇 start 鍜� end 涓嶈兘鍔ㄦ�佽祴鍊肩殑Bug
+- 淇 鑼冨洿閫夌被鍨嬶紝鐢ㄦ埛閫夋嫨鍚庡啀娆¢�夋嫨鍙充晶鏃ュ巻锛堢粨鏉熸棩鏈燂級鏄剧ず涓嶆纭殑Bug
+## 2.0.13锛�2021-07-08锛�
+- 淇 鑼冨洿閫夋嫨涓嶈兘鍔ㄦ�佽祴鍊肩殑Bug
+## 2.0.12锛�2021-07-08锛�
+- 淇 鑼冨洿閫夋嫨鐨勫垵濮嬫椂闂村湪涓�涓湀鍐呮椂锛岄�犳垚鏃犳硶閫夋嫨鐨刡ug
+## 2.0.11锛�2021-07-08锛�
+- 浼樺寲 寮瑰嚭灞傚湪瓒呭嚭瑙嗙獥杈圭紭瀹氫綅涓嶅噯纭殑闂
+## 2.0.10锛�2021-07-08锛�
+- 淇 鑼冨洿璧峰鐐规牱寮忕殑鑳屾櫙鑹蹭笌浠婃棩鏍峰紡鐨勫瓧浣撳墠鏅壊铻嶅悎锛屽鑷存棩鏈熷瓧浣撶湅涓嶆竻鐨凚ug
+- 浼樺寲 寮瑰嚭灞傚湪瓒呭嚭瑙嗙獥杈圭紭琚伄鐩栫殑闂
+## 2.0.9锛�2021-07-07锛�
+- 鏂板 maskClick 浜嬩欢
+- 淇 鐗规畩鎯呭喌鏃ュ巻 rpx 甯冨眬閿欒鐨凚ug锛宺px -> px
+- 淇 鑼冨洿閫夋嫨鏃舵竻绌鸿繑鍥炲�间笉鍚堢悊鐨刡ug锛孾'', ''] -> []
+## 2.0.8锛�2021-07-07锛�
+- 鏂板 鏃ユ湡鏃堕棿鏄剧ず妗嗘敮鎸佹彃妲�
+## 2.0.7锛�2021-07-01锛�
+- 浼樺寲 娣诲姞 uni-icons 渚濊禆
+## 2.0.6锛�2021-05-22锛�
+- 淇 鍥炬爣鍦ㄥ皬绋嬪簭涓婁笉鏄剧ず鐨凚ug
+- 浼樺寲 閲嶅懡鍚嶅紩鐢ㄧ粍浠讹紝閬垮厤娼滃湪缁勪欢鍛藉悕鍐茬獊
+## 2.0.5锛�2021-05-20锛�
+- 浼樺寲 浠g爜鐩綍鎵佸钩鍖�
+## 2.0.4锛�2021-05-12锛�
+- 鏂板 缁勪欢绀轰緥鍦板潃
+## 2.0.3锛�2021-05-10锛�
+- 淇 ios 涓嬩笉璇嗗埆 '-' 鏃ユ湡鏍煎紡鐨凚ug
+- 浼樺寲 pc 涓嬪脊鍑哄眰娣诲姞杈规鍜岄槾褰�
+## 2.0.2锛�2021-05-08锛�
+- 淇 鍦� admin 涓幏鍙栧脊鍑哄眰瀹氫綅閿欒鐨刡ug
+## 2.0.1锛�2021-05-08锛�
+- 淇 type 灞炴�у悜涓嬪吋瀹癸紝榛樿鍊间粠 date 鍙樻洿涓� datetime
+## 2.0.0锛�2021-04-30锛�
+- 鏀寔鏃ュ巻褰㈠紡鐨勬棩鏈�+鏃堕棿鐨勮寖鍥撮�夋嫨
+ > 娉ㄦ剰锛氭鐗堟湰涓嶅悜鍚庡吋瀹癸紝涓嶅啀鏀寔鍗曠嫭鏃堕棿閫夋嫨锛坱ype=time锛夊強鐩稿叧鐨� hide-second 灞炴�э紙鏃堕棿閫夊彲浣跨敤鍐呯疆缁勪欢 picker锛�
+## 1.0.6锛�2021-03-18锛�
+- 鏂板 hide-second 灞炴�э紝鏃堕棿鏀寔浠呴�夋嫨鏃躲�佸垎
+- 淇 閫夋嫨璺熸樉绀虹殑鏃ユ湡涓嶄竴鏍风殑Bug
+- 淇 chang浜嬩欢瑙﹀彂2娆$殑Bug
+- 淇 鍒嗐�佺 end 鑼冨洿閿欒鐨凚ug
+- 浼樺寲 鏇村ソ鐨� nvue 閫傞厤
diff --git a/app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar-item.vue b/app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar-item.vue
new file mode 100644
index 0000000..dba9887
--- /dev/null
+++ b/app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar-item.vue
@@ -0,0 +1,177 @@
+<template>
+ <view class="uni-calendar-item__weeks-box" :class="{
+ 'uni-calendar-item--disable':weeks.disable,
+ 'uni-calendar-item--before-checked-x':weeks.beforeMultiple,
+ 'uni-calendar-item--multiple': weeks.multiple,
+ 'uni-calendar-item--after-checked-x':weeks.afterMultiple,
+ }" @click="choiceDate(weeks)" @mouseenter="handleMousemove(weeks)">
+ <view class="uni-calendar-item__weeks-box-item" :class="{
+ 'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && (calendar.userChecked || !checkHover),
+ 'uni-calendar-item--checked-range-text': checkHover,
+ 'uni-calendar-item--before-checked':weeks.beforeMultiple,
+ 'uni-calendar-item--multiple': weeks.multiple,
+ 'uni-calendar-item--after-checked':weeks.afterMultiple,
+ 'uni-calendar-item--disable':weeks.disable,
+ }">
+ <text v-if="selected && weeks.extraInfo" class="uni-calendar-item__weeks-box-circle"></text>
+ <text class="uni-calendar-item__weeks-box-text uni-calendar-item__weeks-box-text-disable uni-calendar-item--checked-text">{{weeks.date}}</text>
+ </view>
+ <view :class="{'uni-calendar-item--today': weeks.isToday}"></view>
+ </view>
+</template>
+
+<script>
+ export default {
+ props: {
+ weeks: {
+ type: Object,
+ default () {
+ return {}
+ }
+ },
+ calendar: {
+ type: Object,
+ default: () => {
+ return {}
+ }
+ },
+ selected: {
+ type: Array,
+ default: () => {
+ return []
+ }
+ },
+ checkHover: {
+ type: Boolean,
+ default: false
+ }
+ },
+ methods: {
+ choiceDate(weeks) {
+ this.$emit('change', weeks)
+ },
+ handleMousemove(weeks) {
+ this.$emit('handleMouse', weeks)
+ }
+ }
+ }
+</script>
+
+<style lang="scss" >
+ $uni-primary: #007aff !default;
+
+ .uni-calendar-item__weeks-box {
+ flex: 1;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ margin: 1px 0;
+ position: relative;
+ }
+
+ .uni-calendar-item__weeks-box-text {
+ font-size: 14px;
+ // font-family: Lato-Bold, Lato;
+ font-weight: bold;
+ color: darken($color: $uni-primary, $amount: 40%);
+ }
+
+ .uni-calendar-item__weeks-box-item {
+ position: relative;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ width: 40px;
+ height: 40px;
+ /* #ifdef H5 */
+ cursor: pointer;
+ /* #endif */
+ }
+
+
+ .uni-calendar-item__weeks-box-circle {
+ position: absolute;
+ top: 5px;
+ right: 5px;
+ width: 8px;
+ height: 8px;
+ border-radius: 8px;
+ background-color: #dd524d;
+
+ }
+
+ .uni-calendar-item__weeks-box .uni-calendar-item--disable {
+ cursor: default;
+ }
+
+ .uni-calendar-item--disable .uni-calendar-item__weeks-box-text-disable {
+ color: #D1D1D1;
+ }
+
+ .uni-calendar-item--today {
+ position: absolute;
+ top: 10px;
+ right: 17%;
+ background-color: #dd524d;
+ width:6px;
+ height: 6px;
+ border-radius: 50%;
+ }
+
+ .uni-calendar-item--extra {
+ color: #dd524d;
+ opacity: 0.8;
+ }
+
+ .uni-calendar-item__weeks-box .uni-calendar-item--checked {
+ background-color: $uni-primary;
+ border-radius: 50%;
+ box-sizing: border-box;
+ border: 3px solid #fff;
+ }
+
+ .uni-calendar-item--checked .uni-calendar-item--checked-text {
+ color: #fff;
+ }
+
+ .uni-calendar-item--multiple .uni-calendar-item--checked-range-text {
+ color: #333;
+ }
+
+ .uni-calendar-item--multiple {
+ background-color: #F6F7FC;
+ // color: #fff;
+ }
+
+ .uni-calendar-item--multiple .uni-calendar-item--before-checked,
+ .uni-calendar-item--multiple .uni-calendar-item--after-checked {
+ background-color: $uni-primary;
+ border-radius: 50%;
+ box-sizing: border-box;
+ border: 3px solid #F6F7FC;
+ }
+
+ .uni-calendar-item--before-checked .uni-calendar-item--checked-text,
+ .uni-calendar-item--after-checked .uni-calendar-item--checked-text {
+ color: #fff;
+ }
+
+ .uni-calendar-item--before-checked-x {
+ border-top-left-radius: 50px;
+ border-bottom-left-radius: 50px;
+ box-sizing: border-box;
+ background-color: #F6F7FC;
+ }
+
+ .uni-calendar-item--after-checked-x {
+ border-top-right-radius: 50px;
+ border-bottom-right-radius: 50px;
+ background-color: #F6F7FC;
+ }
+</style>
diff --git a/app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar.vue b/app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar.vue
new file mode 100644
index 0000000..3418f49
--- /dev/null
+++ b/app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar.vue
@@ -0,0 +1,928 @@
+<template>
+ <view class="uni-calendar" @mouseleave="leaveCale">
+
+ <view v-if="!insert && show" class="uni-calendar__mask" :class="{'uni-calendar--mask-show':aniMaskShow}"
+ @click="maskClick"></view>
+
+ <view v-if="insert || show" class="uni-calendar__content"
+ :class="{'uni-calendar--fixed':!insert,'uni-calendar--ani-show':aniMaskShow, 'uni-calendar__content-mobile': aniMaskShow}">
+ <view class="uni-calendar__header" :class="{'uni-calendar__header-mobile' :!insert}">
+
+ <view class="uni-calendar__header-btn-box" @click.stop="changeMonth('pre')">
+ <view class="uni-calendar__header-btn uni-calendar--left"></view>
+ </view>
+
+ <picker mode="date" :value="date" fields="month" @change="bindDateChange">
+ <text
+ class="uni-calendar__header-text">{{ (nowDate.year||'') + yearText + ( nowDate.month||'') + monthText}}</text>
+ </picker>
+
+ <view class="uni-calendar__header-btn-box" @click.stop="changeMonth('next')">
+ <view class="uni-calendar__header-btn uni-calendar--right"></view>
+ </view>
+
+ <view v-if="!insert" class="dialog-close" @click="close">
+ <view class="dialog-close-plus" data-id="close"></view>
+ <view class="dialog-close-plus dialog-close-rotate" data-id="close"></view>
+ </view>
+ </view>
+ <view class="uni-calendar__box">
+
+ <view v-if="showMonth" class="uni-calendar__box-bg">
+ <text class="uni-calendar__box-bg-text">{{nowDate.month}}</text>
+ </view>
+
+ <view class="uni-calendar__weeks" style="padding-bottom: 7px;">
+ <view class="uni-calendar__weeks-day">
+ <text class="uni-calendar__weeks-day-text">{{SUNText}}</text>
+ </view>
+ <view class="uni-calendar__weeks-day">
+ <text class="uni-calendar__weeks-day-text">{{MONText}}</text>
+ </view>
+ <view class="uni-calendar__weeks-day">
+ <text class="uni-calendar__weeks-day-text">{{TUEText}}</text>
+ </view>
+ <view class="uni-calendar__weeks-day">
+ <text class="uni-calendar__weeks-day-text">{{WEDText}}</text>
+ </view>
+ <view class="uni-calendar__weeks-day">
+ <text class="uni-calendar__weeks-day-text">{{THUText}}</text>
+ </view>
+ <view class="uni-calendar__weeks-day">
+ <text class="uni-calendar__weeks-day-text">{{FRIText}}</text>
+ </view>
+ <view class="uni-calendar__weeks-day">
+ <text class="uni-calendar__weeks-day-text">{{SATText}}</text>
+ </view>
+ </view>
+
+ <view class="uni-calendar__weeks" v-for="(item,weekIndex) in weeks" :key="weekIndex">
+ <view class="uni-calendar__weeks-item" v-for="(weeks,weeksIndex) in item" :key="weeksIndex">
+ <calendar-item class="uni-calendar-item--hook" :weeks="weeks" :calendar="calendar"
+ :selected="selected" :checkHover="range" @change="choiceDate"
+ @handleMouse="handleMouse">
+ </calendar-item>
+ </view>
+ </view>
+ </view>
+
+ <view v-if="!insert && !range && hasTime" class="uni-date-changed uni-calendar--fixed-top"
+ style="padding: 0 80px;">
+ <view class="uni-date-changed--time-date">{{tempSingleDate ? tempSingleDate : selectDateText}}</view>
+ <time-picker type="time" :start="timepickerStartTime" :end="timepickerEndTime" v-model="time"
+ :disabled="!tempSingleDate" :border="false" :hide-second="hideSecond" class="time-picker-style">
+ </time-picker>
+ </view>
+
+ <view v-if="!insert && range && hasTime" class="uni-date-changed uni-calendar--fixed-top">
+ <view class="uni-date-changed--time-start">
+ <view class="uni-date-changed--time-date">{{tempRange.before ? tempRange.before : startDateText}}
+ </view>
+ <time-picker type="time" :start="timepickerStartTime" v-model="timeRange.startTime" :border="false"
+ :hide-second="hideSecond" :disabled="!tempRange.before" class="time-picker-style">
+ </time-picker>
+ </view>
+ <view style="line-height: 50px;">
+ <uni-icons type="arrowthinright" color="#999"></uni-icons>
+ </view>
+ <view class="uni-date-changed--time-end">
+ <view class="uni-date-changed--time-date">{{tempRange.after ? tempRange.after : endDateText}}</view>
+ <time-picker type="time" :end="timepickerEndTime" v-model="timeRange.endTime" :border="false"
+ :hide-second="hideSecond" :disabled="!tempRange.after" class="time-picker-style">
+ </time-picker>
+ </view>
+ </view>
+
+ <view v-if="!insert" class="uni-date-changed uni-date-btn--ok">
+ <view class="uni-datetime-picker--btn" @click="confirm">{{confirmText}}</view>
+ </view>
+ </view>
+ </view>
+</template>
+
+<script>
+ import { Calendar, getDate, getTime } from './util.js';
+ import calendarItem from './calendar-item.vue'
+ import timePicker from './time-picker.vue'
+
+ import { initVueI18n } from '@dcloudio/uni-i18n'
+ import i18nMessages from './i18n/index.js'
+ const { t } = initVueI18n(i18nMessages)
+
+ /**
+ * Calendar 鏃ュ巻
+ * @description 鏃ュ巻缁勪欢鍙互鏌ョ湅鏃ユ湡锛岄�夋嫨浠绘剰鑼冨洿鍐呯殑鏃ユ湡锛屾墦鐐规搷浣溿�傚父鐢ㄥ満鏅锛氶厭搴楁棩鏈熼璁€�佺伀杞︽満绁ㄩ�夋嫨璐拱鏃ユ湡銆佷笂涓嬬彮鎵撳崱绛�
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=56
+ * @property {String} date 鑷畾涔夊綋鍓嶆椂闂达紝榛樿涓轰粖澶�
+ * @property {String} startDate 鏃ユ湡閫夋嫨鑼冨洿-寮�濮嬫棩鏈�
+ * @property {String} endDate 鏃ユ湡閫夋嫨鑼冨洿-缁撴潫鏃ユ湡
+ * @property {Boolean} range 鑼冨洿閫夋嫨
+ * @property {Boolean} insert = [true|false] 鎻掑叆妯″紡,榛樿涓篺alse
+ * @value true 寮圭獥妯″紡
+ * @value false 鎻掑叆妯″紡
+ * @property {Boolean} clearDate = [true|false] 寮圭獥妯″紡鏄惁娓呯┖涓婃閫夋嫨鍐呭
+ * @property {Array} selected 鎵撶偣锛屾湡寰呮牸寮廩{date: '2019-06-27', info: '绛惧埌', data: { custom: '鑷畾涔変俊鎭�', name: '鑷畾涔夋秷鎭ご',xxx:xxx... }}]
+ * @property {Boolean} showMonth 鏄惁閫夋嫨鏈堜唤涓鸿儗鏅�
+ * @property {[String} defaultValue 閫夋嫨鍣ㄦ墦寮�鏃堕粯璁ゆ樉绀虹殑鏃堕棿
+ * @event {Function} change 鏃ユ湡鏀瑰彉锛宍insert :ture` 鏃剁敓鏁�
+ * @event {Function} confirm 纭閫夋嫨`insert :false` 鏃剁敓鏁�
+ * @event {Function} monthSwitch 鍒囨崲鏈堜唤鏃惰Е鍙�
+ * @example <uni-calendar :insert="true" :start-date="'2019-3-2'":end-date="'2019-5-20'"@change="change" />
+ */
+ export default {
+ components: {
+ calendarItem,
+ timePicker
+ },
+ props: {
+ date: {
+ type: String,
+ default: ''
+ },
+ defTime: {
+ type: [String, Object],
+ default: ''
+ },
+ selectableTimes: {
+ type: [Object],
+ default () {
+ return {}
+ }
+ },
+ selected: {
+ type: Array,
+ default () {
+ return []
+ }
+ },
+ startDate: {
+ type: String,
+ default: ''
+ },
+ endDate: {
+ type: String,
+ default: ''
+ },
+ startPlaceholder: {
+ type: String,
+ default: ''
+ },
+ endPlaceholder: {
+ type: String,
+ default: ''
+ },
+ range: {
+ type: Boolean,
+ default: false
+ },
+ hasTime: {
+ type: Boolean,
+ default: false
+ },
+ insert: {
+ type: Boolean,
+ default: true
+ },
+ showMonth: {
+ type: Boolean,
+ default: true
+ },
+ clearDate: {
+ type: Boolean,
+ default: true
+ },
+ checkHover: {
+ type: Boolean,
+ default: true
+ },
+ hideSecond: {
+ type: [Boolean],
+ default: false
+ },
+ pleStatus: {
+ type: Object,
+ default () {
+ return {
+ before: '',
+ after: '',
+ data: [],
+ fulldate: ''
+ }
+ }
+ },
+ defaultValue: {
+ type: [String, Object, Array],
+ default: ''
+ }
+ },
+ data() {
+ return {
+ show: false,
+ weeks: [],
+ calendar: {},
+ nowDate: {},
+ aniMaskShow: false,
+ firstEnter: true,
+ time: '',
+ timeRange: {
+ startTime: '',
+ endTime: ''
+ },
+ tempSingleDate: '',
+ tempRange: {
+ before: '',
+ after: ''
+ }
+ }
+ },
+ watch: {
+ date: {
+ immediate: true,
+ handler(newVal) {
+ if (!this.range) {
+ this.tempSingleDate = newVal
+ setTimeout(() => {
+ this.init(newVal)
+ }, 100)
+ }
+ }
+ },
+ defTime: {
+ immediate: true,
+ handler(newVal) {
+ if (!this.range) {
+ this.time = newVal
+ } else {
+ this.timeRange.startTime = newVal.start
+ this.timeRange.endTime = newVal.end
+ }
+ }
+ },
+ startDate(val) {
+ // 瀛楄妭灏忕▼搴� watch 鏃╀簬 created
+ if(!this.cale){
+ return
+ }
+ this.cale.setStartDate(val)
+ this.cale.setDate(this.nowDate.fullDate)
+ this.weeks = this.cale.weeks
+ },
+ endDate(val) {
+ // 瀛楄妭灏忕▼搴� watch 鏃╀簬 created
+ if(!this.cale){
+ return
+ }
+ this.cale.setEndDate(val)
+ this.cale.setDate(this.nowDate.fullDate)
+ this.weeks = this.cale.weeks
+ },
+ selected(newVal) {
+ // 瀛楄妭灏忕▼搴� watch 鏃╀簬 created
+ if(!this.cale){
+ return
+ }
+ this.cale.setSelectInfo(this.nowDate.fullDate, newVal)
+ this.weeks = this.cale.weeks
+ },
+ pleStatus: {
+ immediate: true,
+ handler(newVal) {
+ const {
+ before,
+ after,
+ fulldate,
+ which
+ } = newVal
+ this.tempRange.before = before
+ this.tempRange.after = after
+ setTimeout(() => {
+ if (fulldate) {
+ this.cale.setHoverMultiple(fulldate)
+ if (before && after) {
+ this.cale.lastHover = true
+ if (this.rangeWithinMonth(after, before)) return
+ this.setDate(before)
+ } else {
+ this.cale.setMultiple(fulldate)
+ this.setDate(this.nowDate.fullDate)
+ this.calendar.fullDate = ''
+ this.cale.lastHover = false
+ }
+ } else {
+ // 瀛楄妭灏忕▼搴� watch 鏃╀簬 created
+ if(!this.cale){
+ return
+ }
+
+ this.cale.setDefaultMultiple(before, after)
+ if (which === 'left' && before) {
+ this.setDate(before)
+ this.weeks = this.cale.weeks
+ } else if(after) {
+ this.setDate(after)
+ this.weeks = this.cale.weeks
+ }
+ this.cale.lastHover = true
+ }
+ }, 16)
+ }
+ }
+ },
+ computed: {
+ timepickerStartTime() {
+ const activeDate = this.range ? this.tempRange.before : this.calendar.fullDate
+ return activeDate === this.startDate ? this.selectableTimes.start : ''
+ },
+ timepickerEndTime() {
+ const activeDate = this.range ? this.tempRange.after : this.calendar.fullDate
+ return activeDate === this.endDate ? this.selectableTimes.end : ''
+ },
+ /**
+ * for i18n
+ */
+ selectDateText() {
+ return t("uni-datetime-picker.selectDate")
+ },
+ startDateText() {
+ return this.startPlaceholder || t("uni-datetime-picker.startDate")
+ },
+ endDateText() {
+ return this.endPlaceholder || t("uni-datetime-picker.endDate")
+ },
+ okText() {
+ return t("uni-datetime-picker.ok")
+ },
+ yearText() {
+ return t("uni-datetime-picker.year")
+ },
+ monthText() {
+ return t("uni-datetime-picker.month")
+ },
+ MONText() {
+ return t("uni-calender.MON")
+ },
+ TUEText() {
+ return t("uni-calender.TUE")
+ },
+ WEDText() {
+ return t("uni-calender.WED")
+ },
+ THUText() {
+ return t("uni-calender.THU")
+ },
+ FRIText() {
+ return t("uni-calender.FRI")
+ },
+ SATText() {
+ return t("uni-calender.SAT")
+ },
+ SUNText() {
+ return t("uni-calender.SUN")
+ },
+ confirmText() {
+ return t("uni-calender.confirm")
+ },
+ },
+ created() {
+ // 鑾峰彇鏃ュ巻鏂规硶瀹炰緥
+ this.cale = new Calendar({
+ selected: this.selected,
+ startDate: this.startDate,
+ endDate: this.endDate,
+ range: this.range,
+ })
+ // 閫変腑鏌愪竴澶�
+ this.init(this.date)
+ },
+ methods: {
+ leaveCale() {
+ this.firstEnter = true
+ },
+ handleMouse(weeks) {
+ if (weeks.disable) return
+ if (this.cale.lastHover) return
+ let {
+ before,
+ after
+ } = this.cale.multipleStatus
+ if (!before) return
+ this.calendar = weeks
+ // 璁剧疆鑼冨洿閫�
+ this.cale.setHoverMultiple(this.calendar.fullDate)
+ this.weeks = this.cale.weeks
+ // hover鏃讹紝杩涘叆涓�涓棩鍘嗭紝鏇存柊鍙︿竴涓�
+ if (this.firstEnter) {
+ this.$emit('firstEnterCale', this.cale.multipleStatus)
+ this.firstEnter = false
+ }
+ },
+ rangeWithinMonth(A, B) {
+ const [yearA, monthA] = A.split('-')
+ const [yearB, monthB] = B.split('-')
+ return yearA === yearB && monthA === monthB
+ },
+ // 钂欑増鐐瑰嚮浜嬩欢
+ maskClick() {
+ this.close()
+ this.$emit('maskClose')
+ },
+
+ clearCalender() {
+ if (this.range) {
+ this.timeRange.startTime = ''
+ this.timeRange.endTime = ''
+ this.tempRange.before = ''
+ this.tempRange.after = ''
+ this.cale.multipleStatus.before = ''
+ this.cale.multipleStatus.after = ''
+ this.cale.multipleStatus.data = []
+ this.cale.lastHover = false
+ } else {
+ this.time = ''
+ this.tempSingleDate = ''
+ }
+ this.calendar.fullDate = ''
+ this.setDate(new Date())
+ },
+
+ bindDateChange(e) {
+ const value = e.detail.value + '-1'
+ this.setDate(value)
+ },
+ /**
+ * 鍒濆鍖栨棩鏈熸樉绀�
+ * @param {Object} date
+ */
+ init(date) {
+ // 瀛楄妭灏忕▼搴� watch 鏃╀簬 created
+ if(!this.cale){
+ return
+ }
+ this.cale.setDate(date || new Date())
+ this.weeks = this.cale.weeks
+ this.nowDate = this.cale.getInfo(date)
+ this.calendar = {...this.nowDate}
+ if(!date){
+ // 浼樺寲date涓虹┖榛樿涓嶉�変腑浠婂ぉ
+ this.calendar.fullDate = ''
+ if(this.defaultValue && !this.range){
+ // 鏆傛椂鍙敮鎸佺Щ鍔ㄧ闈炶寖鍥撮�夋嫨
+ const defaultDate = new Date(this.defaultValue)
+ const fullDate = getDate(defaultDate)
+ const year = defaultDate.getFullYear()
+ const month = defaultDate.getMonth()+1
+ const date = defaultDate.getDate()
+ const day = defaultDate.getDay()
+ this.calendar = {
+ fullDate,
+ year,
+ month,
+ date,
+ day
+ },
+ this.tempSingleDate = fullDate
+ this.time = getTime(defaultDate, this.hideSecond)
+ }
+ }
+ },
+ /**
+ * 鎵撳紑鏃ュ巻寮圭獥
+ */
+ open() {
+ // 寮圭獥妯″紡骞朵笖娓呯悊鏁版嵁
+ if (this.clearDate && !this.insert) {
+ this.cale.cleanMultipleStatus()
+ this.init(this.date)
+ }
+ this.show = true
+ this.$nextTick(() => {
+ setTimeout(() => {
+ this.aniMaskShow = true
+ }, 50)
+ })
+ },
+ /**
+ * 鍏抽棴鏃ュ巻寮圭獥
+ */
+ close() {
+ this.aniMaskShow = false
+ this.$nextTick(() => {
+ setTimeout(() => {
+ this.show = false
+ this.$emit('close')
+ }, 300)
+ })
+ },
+ /**
+ * 纭鎸夐挳
+ */
+ confirm() {
+ this.setEmit('confirm')
+ this.close()
+ },
+ /**
+ * 鍙樺寲瑙﹀彂
+ */
+ change() {
+ if (!this.insert) return
+ this.setEmit('change')
+ },
+ /**
+ * 閫夋嫨鏈堜唤瑙﹀彂
+ */
+ monthSwitch() {
+ let {
+ year,
+ month
+ } = this.nowDate
+ this.$emit('monthSwitch', {
+ year,
+ month: Number(month)
+ })
+ },
+ /**
+ * 娲惧彂浜嬩欢
+ * @param {Object} name
+ */
+ setEmit(name) {
+ if(!this.range){
+ if(!this.calendar.fullDate){
+ this.calendar = this.cale.getInfo(new Date())
+ this.tempSingleDate = this.calendar.fullDate
+ }
+ if(this.hasTime && !this.time) {
+ this.time = getTime(new Date(), this.hideSecond)
+ }
+ }
+ let {
+ year,
+ month,
+ date,
+ fullDate,
+ extraInfo
+ } = this.calendar
+ this.$emit(name, {
+ range: this.cale.multipleStatus,
+ year,
+ month,
+ date,
+ time: this.time,
+ timeRange: this.timeRange,
+ fulldate: fullDate,
+ extraInfo: extraInfo || {}
+ })
+ },
+ /**
+ * 閫夋嫨澶╄Е鍙�
+ * @param {Object} weeks
+ */
+ choiceDate(weeks) {
+ if (weeks.disable) return
+ this.calendar = weeks
+ this.calendar.userChecked = true
+ // 璁剧疆澶氶��
+ this.cale.setMultiple(this.calendar.fullDate, true)
+ this.weeks = this.cale.weeks
+ this.tempSingleDate = this.calendar.fullDate
+ const beforeDate = new Date(this.cale.multipleStatus.before).getTime()
+ const afterDate = new Date(this.cale.multipleStatus.after).getTime()
+ if (beforeDate > afterDate && afterDate) {
+ this.tempRange.before = this.cale.multipleStatus.after
+ this.tempRange.after = this.cale.multipleStatus.before
+ } else {
+ this.tempRange.before = this.cale.multipleStatus.before
+ this.tempRange.after = this.cale.multipleStatus.after
+ }
+ this.change()
+ },
+ changeMonth(type) {
+ let newDate
+ if(type === 'pre') {
+ newDate = this.cale.getPreMonthObj(this.nowDate.fullDate).fullDate
+ } else if(type === 'next') {
+ newDate = this.cale.getNextMonthObj(this.nowDate.fullDate).fullDate
+ }
+
+ this.setDate(newDate)
+ this.monthSwitch()
+ },
+ /**
+ * 璁剧疆鏃ユ湡
+ * @param {Object} date
+ */
+ setDate(date) {
+ this.cale.setDate(date)
+ this.weeks = this.cale.weeks
+ this.nowDate = this.cale.getInfo(date)
+ }
+ }
+ }
+</script>
+
+<style lang="scss" >
+ $uni-primary: #007aff !default;
+
+ .uni-calendar {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: column;
+ }
+
+ .uni-calendar__mask {
+ position: fixed;
+ bottom: 0;
+ top: 0;
+ left: 0;
+ right: 0;
+ background-color: rgba(0, 0, 0, 0.4);
+ transition-property: opacity;
+ transition-duration: 0.3s;
+ opacity: 0;
+ /* #ifndef APP-NVUE */
+ z-index: 99;
+ /* #endif */
+ }
+
+ .uni-calendar--mask-show {
+ opacity: 1
+ }
+
+ .uni-calendar--fixed {
+ position: fixed;
+ bottom: calc(var(--window-bottom));
+ left: 0;
+ right: 0;
+ transition-property: transform;
+ transition-duration: 0.3s;
+ transform: translateY(460px);
+ /* #ifndef APP-NVUE */
+ z-index: 99;
+ /* #endif */
+ }
+
+ .uni-calendar--ani-show {
+ transform: translateY(0);
+ }
+
+ .uni-calendar__content {
+ background-color: #fff;
+ }
+
+ .uni-calendar__content-mobile {
+ border-top-left-radius: 10px;
+ border-top-right-radius: 10px;
+ box-shadow: 0px 0px 5px 3px rgba(0, 0, 0, 0.1);
+ }
+
+ .uni-calendar__header {
+ position: relative;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ justify-content: center;
+ align-items: center;
+ height: 50px;
+ }
+
+ .uni-calendar__header-mobile {
+ padding: 10px;
+ padding-bottom: 0;
+ }
+
+ .uni-calendar--fixed-top {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ justify-content: space-between;
+ border-top-color: rgba(0, 0, 0, 0.4);
+ border-top-style: solid;
+ border-top-width: 1px;
+ }
+
+ .uni-calendar--fixed-width {
+ width: 50px;
+ }
+
+ .uni-calendar__backtoday {
+ position: absolute;
+ right: 0;
+ top: 25rpx;
+ padding: 0 5px;
+ padding-left: 10px;
+ height: 25px;
+ line-height: 25px;
+ font-size: 12px;
+ border-top-left-radius: 25px;
+ border-bottom-left-radius: 25px;
+ color: #fff;
+ background-color: #f1f1f1;
+ }
+
+ .uni-calendar__header-text {
+ text-align: center;
+ width: 100px;
+ font-size: 15px;
+ color: #666;
+ }
+
+ .uni-calendar__button-text {
+ text-align: center;
+ width: 100px;
+ font-size: 14px;
+ color: $uni-primary;
+ /* #ifndef APP-NVUE */
+ letter-spacing: 3px;
+ /* #endif */
+ }
+
+ .uni-calendar__header-btn-box {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ align-items: center;
+ justify-content: center;
+ width: 50px;
+ height: 50px;
+ }
+
+ .uni-calendar__header-btn {
+ width: 9px;
+ height: 9px;
+ border-left-color: #808080;
+ border-left-style: solid;
+ border-left-width: 1px;
+ border-top-color: #555555;
+ border-top-style: solid;
+ border-top-width: 1px;
+ }
+
+ .uni-calendar--left {
+ transform: rotate(-45deg);
+ }
+
+ .uni-calendar--right {
+ transform: rotate(135deg);
+ }
+
+
+ .uni-calendar__weeks {
+ position: relative;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ }
+
+ .uni-calendar__weeks-item {
+ flex: 1;
+ }
+
+ .uni-calendar__weeks-day {
+ flex: 1;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ height: 40px;
+ border-bottom-color: #F5F5F5;
+ border-bottom-style: solid;
+ border-bottom-width: 1px;
+ }
+
+ .uni-calendar__weeks-day-text {
+ font-size: 12px;
+ color: #B2B2B2;
+ }
+
+ .uni-calendar__box {
+ position: relative;
+ // padding: 0 10px;
+ padding-bottom: 7px;
+ }
+
+ .uni-calendar__box-bg {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ justify-content: center;
+ align-items: center;
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ }
+
+ .uni-calendar__box-bg-text {
+ font-size: 200px;
+ font-weight: bold;
+ color: #999;
+ opacity: 0.1;
+ text-align: center;
+ /* #ifndef APP-NVUE */
+ line-height: 1;
+ /* #endif */
+ }
+
+ .uni-date-changed {
+ padding: 0 10px;
+ // line-height: 50px;
+ text-align: center;
+ color: #333;
+ border-top-color: #DCDCDC;
+ ;
+ border-top-style: solid;
+ border-top-width: 1px;
+ flex: 1;
+ }
+
+ .uni-date-btn--ok {
+ padding: 20px 15px;
+ }
+
+ .uni-date-changed--time-start {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ align-items: center;
+ }
+
+ .uni-date-changed--time-end {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ align-items: center;
+ }
+
+ .uni-date-changed--time-date {
+ color: #999;
+ line-height: 50px;
+ /* #ifdef MP-TOUTIAO */
+ font-size: 16px;
+ /* #endif */
+ margin-right: 5px;
+ // opacity: 0.6;
+ }
+
+ .time-picker-style {
+ // width: 62px;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ justify-content: center;
+ align-items: center
+ }
+
+ .mr-10 {
+ margin-right: 10px;
+ }
+
+ .dialog-close {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ align-items: center;
+ padding: 0 25px;
+ margin-top: 10px;
+ }
+
+ .dialog-close-plus {
+ width: 16px;
+ height: 2px;
+ background-color: #737987;
+ border-radius: 2px;
+ transform: rotate(45deg);
+ }
+
+ .dialog-close-rotate {
+ position: absolute;
+ transform: rotate(-45deg);
+ }
+
+ .uni-datetime-picker--btn {
+ border-radius: 100px;
+ height: 40px;
+ line-height: 40px;
+ background-color: $uni-primary;
+ color: #fff;
+ font-size: 16px;
+ letter-spacing: 2px;
+ }
+
+ /* #ifndef APP-NVUE */
+ .uni-datetime-picker--btn:active {
+ opacity: 0.7;
+ }
+ /* #endif */
+</style>
diff --git a/app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/en.json b/app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/en.json
new file mode 100644
index 0000000..024f22f
--- /dev/null
+++ b/app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/en.json
@@ -0,0 +1,22 @@
+{
+ "uni-datetime-picker.selectDate": "select date",
+ "uni-datetime-picker.selectTime": "select time",
+ "uni-datetime-picker.selectDateTime": "select date and time",
+ "uni-datetime-picker.startDate": "start date",
+ "uni-datetime-picker.endDate": "end date",
+ "uni-datetime-picker.startTime": "start time",
+ "uni-datetime-picker.endTime": "end time",
+ "uni-datetime-picker.ok": "ok",
+ "uni-datetime-picker.clear": "clear",
+ "uni-datetime-picker.cancel": "cancel",
+ "uni-datetime-picker.year": "-",
+ "uni-datetime-picker.month": "",
+ "uni-calender.MON": "MON",
+ "uni-calender.TUE": "TUE",
+ "uni-calender.WED": "WED",
+ "uni-calender.THU": "THU",
+ "uni-calender.FRI": "FRI",
+ "uni-calender.SAT": "SAT",
+ "uni-calender.SUN": "SUN",
+ "uni-calender.confirm": "confirm"
+}
diff --git a/app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/index.js b/app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/index.js
new file mode 100644
index 0000000..de7509c
--- /dev/null
+++ b/app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/index.js
@@ -0,0 +1,8 @@
+import en from './en.json'
+import zhHans from './zh-Hans.json'
+import zhHant from './zh-Hant.json'
+export default {
+ en,
+ 'zh-Hans': zhHans,
+ 'zh-Hant': zhHant
+}
diff --git a/app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/zh-Hans.json b/app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/zh-Hans.json
new file mode 100644
index 0000000..d2df5e7
--- /dev/null
+++ b/app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/zh-Hans.json
@@ -0,0 +1,22 @@
+{
+ "uni-datetime-picker.selectDate": "閫夋嫨鏃ユ湡",
+ "uni-datetime-picker.selectTime": "閫夋嫨鏃堕棿",
+ "uni-datetime-picker.selectDateTime": "閫夋嫨鏃ユ湡鏃堕棿",
+ "uni-datetime-picker.startDate": "寮�濮嬫棩鏈�",
+ "uni-datetime-picker.endDate": "缁撴潫鏃ユ湡",
+ "uni-datetime-picker.startTime": "寮�濮嬫椂闂�",
+ "uni-datetime-picker.endTime": "缁撴潫鏃堕棿",
+ "uni-datetime-picker.ok": "纭畾",
+ "uni-datetime-picker.clear": "娓呴櫎",
+ "uni-datetime-picker.cancel": "鍙栨秷",
+ "uni-datetime-picker.year": "骞�",
+ "uni-datetime-picker.month": "鏈�",
+ "uni-calender.SUN": "鏃�",
+ "uni-calender.MON": "涓�",
+ "uni-calender.TUE": "浜�",
+ "uni-calender.WED": "涓�",
+ "uni-calender.THU": "鍥�",
+ "uni-calender.FRI": "浜�",
+ "uni-calender.SAT": "鍏�",
+ "uni-calender.confirm": "纭"
+}
\ No newline at end of file
diff --git a/app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/zh-Hant.json b/app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/zh-Hant.json
new file mode 100644
index 0000000..d23fa3c
--- /dev/null
+++ b/app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/zh-Hant.json
@@ -0,0 +1,22 @@
+{
+ "uni-datetime-picker.selectDate": "閬告搰鏃ユ湡",
+ "uni-datetime-picker.selectTime": "閬告搰鏅傞枔",
+ "uni-datetime-picker.selectDateTime": "閬告搰鏃ユ湡鏅傞枔",
+ "uni-datetime-picker.startDate": "闁嬪鏃ユ湡",
+ "uni-datetime-picker.endDate": "绲愭潫鏃ユ湡",
+ "uni-datetime-picker.startTime": "闁嬪鏃堕棿",
+ "uni-datetime-picker.endTime": "绲愭潫鏃堕棿",
+ "uni-datetime-picker.ok": "纰哄畾",
+ "uni-datetime-picker.clear": "娓呴櫎",
+ "uni-datetime-picker.cancel": "鍙栨秷",
+ "uni-datetime-picker.year": "骞�",
+ "uni-datetime-picker.month": "鏈�",
+ "uni-calender.SUN": "鏃�",
+ "uni-calender.MON": "涓�",
+ "uni-calender.TUE": "浜�",
+ "uni-calender.WED": "涓�",
+ "uni-calender.THU": "鍥�",
+ "uni-calender.FRI": "浜�",
+ "uni-calender.SAT": "鍏�",
+ "uni-calender.confirm": "纰鸿獚"
+}
\ No newline at end of file
diff --git a/app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/time-picker.vue b/app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/time-picker.vue
new file mode 100644
index 0000000..81a042a
--- /dev/null
+++ b/app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/time-picker.vue
@@ -0,0 +1,934 @@
+<template>
+ <view class="uni-datetime-picker">
+ <view @click="initTimePicker">
+ <slot>
+ <view class="uni-datetime-picker-timebox-pointer"
+ :class="{'uni-datetime-picker-disabled': disabled, 'uni-datetime-picker-timebox': border}">
+ <text class="uni-datetime-picker-text">{{time}}</text>
+ <view v-if="!time" class="uni-datetime-picker-time">
+ <text class="uni-datetime-picker-text">{{selectTimeText}}</text>
+ </view>
+ </view>
+ </slot>
+ </view>
+ <view v-if="visible" id="mask" class="uni-datetime-picker-mask" @click="tiggerTimePicker"></view>
+ <view v-if="visible" class="uni-datetime-picker-popup" :class="[dateShow && timeShow ? '' : 'fix-nvue-height']"
+ :style="fixNvueBug">
+ <view class="uni-title">
+ <text class="uni-datetime-picker-text">{{selectTimeText}}</text>
+ </view>
+ <view v-if="dateShow" class="uni-datetime-picker__container-box">
+ <picker-view class="uni-datetime-picker-view" :indicator-style="indicatorStyle" :value="ymd"
+ @change="bindDateChange">
+ <picker-view-column>
+ <view class="uni-datetime-picker-item" v-for="(item,index) in years" :key="index">
+ <text class="uni-datetime-picker-item">{{lessThanTen(item)}}</text>
+ </view>
+ </picker-view-column>
+ <picker-view-column>
+ <view class="uni-datetime-picker-item" v-for="(item,index) in months" :key="index">
+ <text class="uni-datetime-picker-item">{{lessThanTen(item)}}</text>
+ </view>
+ </picker-view-column>
+ <picker-view-column>
+ <view class="uni-datetime-picker-item" v-for="(item,index) in days" :key="index">
+ <text class="uni-datetime-picker-item">{{lessThanTen(item)}}</text>
+ </view>
+ </picker-view-column>
+ </picker-view>
+ <!-- 鍏煎 nvue 涓嶆敮鎸佷吉绫� -->
+ <text class="uni-datetime-picker-sign sign-left">-</text>
+ <text class="uni-datetime-picker-sign sign-right">-</text>
+ </view>
+ <view v-if="timeShow" class="uni-datetime-picker__container-box">
+ <picker-view class="uni-datetime-picker-view" :class="[hideSecond ? 'time-hide-second' : '']"
+ :indicator-style="indicatorStyle" :value="hms" @change="bindTimeChange">
+ <picker-view-column>
+ <view class="uni-datetime-picker-item" v-for="(item,index) in hours" :key="index">
+ <text class="uni-datetime-picker-item">{{lessThanTen(item)}}</text>
+ </view>
+ </picker-view-column>
+ <picker-view-column>
+ <view class="uni-datetime-picker-item" v-for="(item,index) in minutes" :key="index">
+ <text class="uni-datetime-picker-item">{{lessThanTen(item)}}</text>
+ </view>
+ </picker-view-column>
+ <picker-view-column v-if="!hideSecond">
+ <view class="uni-datetime-picker-item" v-for="(item,index) in seconds" :key="index">
+ <text class="uni-datetime-picker-item">{{lessThanTen(item)}}</text>
+ </view>
+ </picker-view-column>
+ </picker-view>
+ <!-- 鍏煎 nvue 涓嶆敮鎸佷吉绫� -->
+ <text class="uni-datetime-picker-sign" :class="[hideSecond ? 'sign-center' : 'sign-left']">:</text>
+ <text v-if="!hideSecond" class="uni-datetime-picker-sign sign-right">:</text>
+ </view>
+ <view class="uni-datetime-picker-btn">
+ <view @click="clearTime">
+ <text class="uni-datetime-picker-btn-text">{{clearText}}</text>
+ </view>
+ <view class="uni-datetime-picker-btn-group">
+ <view class="uni-datetime-picker-cancel" @click="tiggerTimePicker">
+ <text class="uni-datetime-picker-btn-text">{{cancelText}}</text>
+ </view>
+ <view @click="setTime">
+ <text class="uni-datetime-picker-btn-text">{{okText}}</text>
+ </view>
+ </view>
+ </view>
+ </view>
+ </view>
+</template>
+
+<script>
+ import { initVueI18n } from '@dcloudio/uni-i18n'
+ import i18nMessages from './i18n/index.js'
+ const { t } = initVueI18n(i18nMessages)
+ import { fixIosDateFormat } from './util'
+
+ /**
+ * DatetimePicker 鏃堕棿閫夋嫨鍣�
+ * @description 鍙互鍚屾椂閫夋嫨鏃ユ湡鍜屾椂闂寸殑閫夋嫨鍣�
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=xxx
+ * @property {String} type = [datetime | date | time] 鏄剧ず妯″紡
+ * @property {Boolean} multiple = [true|false] 鏄惁澶氶��
+ * @property {String|Number} value 榛樿鍊�
+ * @property {String|Number} start 璧峰鏃ユ湡鎴栨椂闂�
+ * @property {String|Number} end 璧峰鏃ユ湡鎴栨椂闂�
+ * @property {String} return-type = [timestamp | string]
+ * @event {Function} change 閫変腑鍙戠敓鍙樺寲瑙﹀彂
+ */
+
+ export default {
+ name: 'UniDatetimePicker',
+ data() {
+ return {
+ indicatorStyle: `height: 50px;`,
+ visible: false,
+ fixNvueBug: {},
+ dateShow: true,
+ timeShow: true,
+ title: '鏃ユ湡鍜屾椂闂�',
+ // 杈撳叆妗嗗綋鍓嶆椂闂�
+ time: '',
+ // 褰撳墠鐨勫勾鏈堟棩鏃跺垎绉�
+ year: 1920,
+ month: 0,
+ day: 0,
+ hour: 0,
+ minute: 0,
+ second: 0,
+ // 璧峰鏃堕棿
+ startYear: 1920,
+ startMonth: 1,
+ startDay: 1,
+ startHour: 0,
+ startMinute: 0,
+ startSecond: 0,
+ // 缁撴潫鏃堕棿
+ endYear: 2120,
+ endMonth: 12,
+ endDay: 31,
+ endHour: 23,
+ endMinute: 59,
+ endSecond: 59,
+ }
+ },
+ props: {
+ type: {
+ type: String,
+ default: 'datetime'
+ },
+ value: {
+ type: [String, Number],
+ default: ''
+ },
+ modelValue: {
+ type: [String, Number],
+ default: ''
+ },
+ start: {
+ type: [Number, String],
+ default: ''
+ },
+ end: {
+ type: [Number, String],
+ default: ''
+ },
+ returnType: {
+ type: String,
+ default: 'string'
+ },
+ disabled: {
+ type: [Boolean, String],
+ default: false
+ },
+ border: {
+ type: [Boolean, String],
+ default: true
+ },
+ hideSecond: {
+ type: [Boolean, String],
+ default: false
+ }
+ },
+ watch: {
+ // #ifndef VUE3
+ value: {
+ handler(newVal) {
+ if (newVal) {
+ this.parseValue(fixIosDateFormat(newVal))
+ this.initTime(false)
+ } else {
+ this.time = ''
+ this.parseValue(Date.now())
+ }
+ },
+ immediate: true
+ },
+ // #endif
+ // #ifdef VUE3
+ modelValue: {
+ handler(newVal) {
+ if (newVal) {
+ this.parseValue(fixIosDateFormat(newVal))
+ this.initTime(false)
+ } else {
+ this.time = ''
+ this.parseValue(Date.now())
+ }
+ },
+ immediate: true
+ },
+ // #endif
+ type: {
+ handler(newValue) {
+ if (newValue === 'date') {
+ this.dateShow = true
+ this.timeShow = false
+ this.title = '鏃ユ湡'
+ } else if (newValue === 'time') {
+ this.dateShow = false
+ this.timeShow = true
+ this.title = '鏃堕棿'
+ } else {
+ this.dateShow = true
+ this.timeShow = true
+ this.title = '鏃ユ湡鍜屾椂闂�'
+ }
+ },
+ immediate: true
+ },
+ start: {
+ handler(newVal) {
+ this.parseDatetimeRange(fixIosDateFormat(newVal), 'start')
+ },
+ immediate: true
+ },
+ end: {
+ handler(newVal) {
+ this.parseDatetimeRange(fixIosDateFormat(newVal), 'end')
+ },
+ immediate: true
+ },
+
+ // 鏈堛�佹棩銆佹椂銆佸垎銆佺鍙�夎寖鍥村彉鍖栧悗锛屾鏌ュ綋鍓嶅�兼槸鍚﹀湪鑼冨洿鍐咃紝涓嶅湪鍒欏綋鍓嶅�奸噸缃负鍙�夎寖鍥寸涓�椤�
+ months(newVal) {
+ this.checkValue('month', this.month, newVal)
+ },
+ days(newVal) {
+ this.checkValue('day', this.day, newVal)
+ },
+ hours(newVal) {
+ this.checkValue('hour', this.hour, newVal)
+ },
+ minutes(newVal) {
+ this.checkValue('minute', this.minute, newVal)
+ },
+ seconds(newVal) {
+ this.checkValue('second', this.second, newVal)
+ }
+ },
+ computed: {
+ // 褰撳墠骞淬�佹湀銆佹棩銆佹椂銆佸垎銆佺閫夋嫨鑼冨洿
+ years() {
+ return this.getCurrentRange('year')
+ },
+
+ months() {
+ return this.getCurrentRange('month')
+ },
+
+ days() {
+ return this.getCurrentRange('day')
+ },
+
+ hours() {
+ return this.getCurrentRange('hour')
+ },
+
+ minutes() {
+ return this.getCurrentRange('minute')
+ },
+
+ seconds() {
+ return this.getCurrentRange('second')
+ },
+
+ // picker 褰撳墠鍊兼暟缁�
+ ymd() {
+ return [this.year - this.minYear, this.month - this.minMonth, this.day - this.minDay]
+ },
+ hms() {
+ return [this.hour - this.minHour, this.minute - this.minMinute, this.second - this.minSecond]
+ },
+
+ // 褰撳墠 date 鏄� start
+ currentDateIsStart() {
+ return this.year === this.startYear && this.month === this.startMonth && this.day === this.startDay
+ },
+
+ // 褰撳墠 date 鏄� end
+ currentDateIsEnd() {
+ return this.year === this.endYear && this.month === this.endMonth && this.day === this.endDay
+ },
+
+ // 褰撳墠骞淬�佹湀銆佹棩銆佹椂銆佸垎銆佺鐨勬渶灏忓�煎拰鏈�澶у��
+ minYear() {
+ return this.startYear
+ },
+ maxYear() {
+ return this.endYear
+ },
+ minMonth() {
+ if (this.year === this.startYear) {
+ return this.startMonth
+ } else {
+ return 1
+ }
+ },
+ maxMonth() {
+ if (this.year === this.endYear) {
+ return this.endMonth
+ } else {
+ return 12
+ }
+ },
+ minDay() {
+ if (this.year === this.startYear && this.month === this.startMonth) {
+ return this.startDay
+ } else {
+ return 1
+ }
+ },
+ maxDay() {
+ if (this.year === this.endYear && this.month === this.endMonth) {
+ return this.endDay
+ } else {
+ return this.daysInMonth(this.year, this.month)
+ }
+ },
+ minHour() {
+ if (this.type === 'datetime') {
+ if (this.currentDateIsStart) {
+ return this.startHour
+ } else {
+ return 0
+ }
+ }
+ if (this.type === 'time') {
+ return this.startHour
+ }
+ },
+ maxHour() {
+ if (this.type === 'datetime') {
+ if (this.currentDateIsEnd) {
+ return this.endHour
+ } else {
+ return 23
+ }
+ }
+ if (this.type === 'time') {
+ return this.endHour
+ }
+ },
+ minMinute() {
+ if (this.type === 'datetime') {
+ if (this.currentDateIsStart && this.hour === this.startHour) {
+ return this.startMinute
+ } else {
+ return 0
+ }
+ }
+ if (this.type === 'time') {
+ if (this.hour === this.startHour) {
+ return this.startMinute
+ } else {
+ return 0
+ }
+ }
+ },
+ maxMinute() {
+ if (this.type === 'datetime') {
+ if (this.currentDateIsEnd && this.hour === this.endHour) {
+ return this.endMinute
+ } else {
+ return 59
+ }
+ }
+ if (this.type === 'time') {
+ if (this.hour === this.endHour) {
+ return this.endMinute
+ } else {
+ return 59
+ }
+ }
+ },
+ minSecond() {
+ if (this.type === 'datetime') {
+ if (this.currentDateIsStart && this.hour === this.startHour && this.minute === this.startMinute) {
+ return this.startSecond
+ } else {
+ return 0
+ }
+ }
+ if (this.type === 'time') {
+ if (this.hour === this.startHour && this.minute === this.startMinute) {
+ return this.startSecond
+ } else {
+ return 0
+ }
+ }
+ },
+ maxSecond() {
+ if (this.type === 'datetime') {
+ if (this.currentDateIsEnd && this.hour === this.endHour && this.minute === this.endMinute) {
+ return this.endSecond
+ } else {
+ return 59
+ }
+ }
+ if (this.type === 'time') {
+ if (this.hour === this.endHour && this.minute === this.endMinute) {
+ return this.endSecond
+ } else {
+ return 59
+ }
+ }
+ },
+
+ /**
+ * for i18n
+ */
+ selectTimeText() {
+ return t("uni-datetime-picker.selectTime")
+ },
+ okText() {
+ return t("uni-datetime-picker.ok")
+ },
+ clearText() {
+ return t("uni-datetime-picker.clear")
+ },
+ cancelText() {
+ return t("uni-datetime-picker.cancel")
+ }
+ },
+
+ mounted() {
+ // #ifdef APP-NVUE
+ const res = uni.getSystemInfoSync();
+ this.fixNvueBug = {
+ top: res.windowHeight / 2,
+ left: res.windowWidth / 2
+ }
+ // #endif
+ },
+
+ methods: {
+ /**
+ * @param {Object} item
+ * 灏忎簬 10 鍦ㄥ墠闈㈠姞涓� 0
+ */
+
+ lessThanTen(item) {
+ return item < 10 ? '0' + item : item
+ },
+
+ /**
+ * 瑙f瀽鏃跺垎绉掑瓧绗︿覆锛屼緥濡傦細00:00:00
+ * @param {String} timeString
+ */
+ parseTimeType(timeString) {
+ if (timeString) {
+ let timeArr = timeString.split(':')
+ this.hour = Number(timeArr[0])
+ this.minute = Number(timeArr[1])
+ this.second = Number(timeArr[2])
+ }
+ },
+
+ /**
+ * 瑙f瀽閫夋嫨鍣ㄥ垵濮嬪�硷紝绫诲瀷鍙互鏄瓧绗︿覆銆佹椂闂存埑锛屼緥濡傦細2000-10-02銆�'08:30:00'銆� 1610695109000
+ * @param {String | Number} datetime
+ */
+ initPickerValue(datetime) {
+ let defaultValue = null
+ if (datetime) {
+ defaultValue = this.compareValueWithStartAndEnd(datetime, this.start, this.end)
+ } else {
+ defaultValue = Date.now()
+ defaultValue = this.compareValueWithStartAndEnd(defaultValue, this.start, this.end)
+ }
+ this.parseValue(defaultValue)
+ },
+
+ /**
+ * 鍒濆鍊艰鍒欙細
+ * - 鐢ㄦ埛璁剧疆鍒濆鍊� value
+ * - 璁剧疆浜嗚捣濮嬫椂闂� start銆佺粓姝㈡椂闂� end锛屽苟 start < value < end锛屽垵濮嬪�间负 value锛� 鍚﹀垯鍒濆鍊间负 start
+ * - 鍙缃簡璧峰鏃堕棿 start锛屽苟 start < value锛屽垵濮嬪�间负 value锛屽惁鍒欏垵濮嬪�间负 start
+ * - 鍙缃簡缁堟鏃堕棿 end锛屽苟 value < end锛屽垵濮嬪�间负 value锛屽惁鍒欏垵濮嬪�间负 end
+ * - 鏃犺捣濮嬬粓姝㈡椂闂达紝鍒欏垵濮嬪�间负 value
+ * - 鏃犲垵濮嬪�� value锛屽垯鍒濆鍊间负褰撳墠鏈湴鏃堕棿 Date.now()
+ * @param {Object} value
+ * @param {Object} dateBase
+ */
+ compareValueWithStartAndEnd(value, start, end) {
+ let winner = null
+ value = this.superTimeStamp(value)
+ start = this.superTimeStamp(start)
+ end = this.superTimeStamp(end)
+
+ if (start && end) {
+ if (value < start) {
+ winner = new Date(start)
+ } else if (value > end) {
+ winner = new Date(end)
+ } else {
+ winner = new Date(value)
+ }
+ } else if (start && !end) {
+ winner = start <= value ? new Date(value) : new Date(start)
+ } else if (!start && end) {
+ winner = value <= end ? new Date(value) : new Date(end)
+ } else {
+ winner = new Date(value)
+ }
+
+ return winner
+ },
+
+ /**
+ * 杞崲涓哄彲姣旇緝鐨勬椂闂存埑锛屾帴鍙楁棩鏈熴�佹椂鍒嗙銆佹椂闂存埑
+ * @param {Object} value
+ */
+ superTimeStamp(value) {
+ let dateBase = ''
+ if (this.type === 'time' && value && typeof value === 'string') {
+ const now = new Date()
+ const year = now.getFullYear()
+ const month = now.getMonth() + 1
+ const day = now.getDate()
+ dateBase = year + '/' + month + '/' + day + ' '
+ }
+ if (Number(value)) {
+ value = parseInt(value)
+ dateBase = 0
+ }
+ return this.createTimeStamp(dateBase + value)
+ },
+
+ /**
+ * 瑙f瀽榛樿鍊� value锛屽瓧绗︿覆銆佹椂闂存埑
+ * @param {Object} defaultTime
+ */
+ parseValue(value) {
+ if (!value) {
+ return
+ }
+ if (this.type === 'time' && typeof value === "string") {
+ this.parseTimeType(value)
+ } else {
+ let defaultDate = null
+ defaultDate = new Date(value)
+ if (this.type !== 'time') {
+ this.year = defaultDate.getFullYear()
+ this.month = defaultDate.getMonth() + 1
+ this.day = defaultDate.getDate()
+ }
+ if (this.type !== 'date') {
+ this.hour = defaultDate.getHours()
+ this.minute = defaultDate.getMinutes()
+ this.second = defaultDate.getSeconds()
+ }
+ }
+ if (this.hideSecond) {
+ this.second = 0
+ }
+ },
+
+ /**
+ * 瑙f瀽鍙�夋嫨鏃堕棿鑼冨洿 start銆乪nd锛屽勾鏈堟棩瀛楃涓层�佹椂闂存埑
+ * @param {Object} defaultTime
+ */
+ parseDatetimeRange(point, pointType) {
+ // 鏃堕棿涓虹┖锛屽垯閲嶇疆涓哄垵濮嬪��
+ if (!point) {
+ if (pointType === 'start') {
+ this.startYear = 1920
+ this.startMonth = 1
+ this.startDay = 1
+ this.startHour = 0
+ this.startMinute = 0
+ this.startSecond = 0
+ }
+ if (pointType === 'end') {
+ this.endYear = 2120
+ this.endMonth = 12
+ this.endDay = 31
+ this.endHour = 23
+ this.endMinute = 59
+ this.endSecond = 59
+ }
+ return
+ }
+ if (this.type === 'time') {
+ const pointArr = point.split(':')
+ this[pointType + 'Hour'] = Number(pointArr[0])
+ this[pointType + 'Minute'] = Number(pointArr[1])
+ this[pointType + 'Second'] = Number(pointArr[2])
+ } else {
+ if (!point) {
+ pointType === 'start' ? this.startYear = this.year - 60 : this.endYear = this.year + 60
+ return
+ }
+ if (Number(point)) {
+ point = parseInt(point)
+ }
+ // datetime 鐨� end 娌℃湁鏃跺垎绉�, 鍒欎笉闄愬埗
+ const hasTime = /[0-9]:[0-9]/
+ if (this.type === 'datetime' && pointType === 'end' && typeof point === 'string' && !hasTime.test(
+ point)) {
+ point = point + ' 23:59:59'
+ }
+ const pointDate = new Date(point)
+ this[pointType + 'Year'] = pointDate.getFullYear()
+ this[pointType + 'Month'] = pointDate.getMonth() + 1
+ this[pointType + 'Day'] = pointDate.getDate()
+ if (this.type === 'datetime') {
+ this[pointType + 'Hour'] = pointDate.getHours()
+ this[pointType + 'Minute'] = pointDate.getMinutes()
+ this[pointType + 'Second'] = pointDate.getSeconds()
+ }
+ }
+ },
+
+ // 鑾峰彇 骞淬�佹湀銆佹棩銆佹椂銆佸垎銆佺 褰撳墠鍙�夎寖鍥�
+ getCurrentRange(value) {
+ const range = []
+ for (let i = this['min' + this.capitalize(value)]; i <= this['max' + this.capitalize(value)]; i++) {
+ range.push(i)
+ }
+ return range
+ },
+
+ // 瀛楃涓查瀛楁瘝澶у啓
+ capitalize(str) {
+ return str.charAt(0).toUpperCase() + str.slice(1)
+ },
+
+ // 妫�鏌ュ綋鍓嶅�兼槸鍚﹀湪鑼冨洿鍐咃紝涓嶅湪鍒欏綋鍓嶅�奸噸缃负鍙�夎寖鍥寸涓�椤�
+ checkValue(name, value, values) {
+ if (values.indexOf(value) === -1) {
+ this[name] = values[0]
+ }
+ },
+
+ // 姣忎釜鏈堢殑瀹為檯澶╂暟
+ daysInMonth(year, month) { // Use 1 for January, 2 for February, etc.
+ return new Date(year, month, 0).getDate();
+ },
+
+ //鍏煎 iOS銆乻afari 鏃ユ湡鏍煎紡
+ fixIosDateFormat(value) {
+ if (typeof value === 'string') {
+ value = value.replace(/-/g, '/')
+ }
+ return value
+ },
+
+ /**
+ * 鐢熸垚鏃堕棿鎴�
+ * @param {Object} time
+ */
+ createTimeStamp(time) {
+ if (!time) return
+ if (typeof time === "number") {
+ return time
+ } else {
+ time = time.replace(/-/g, '/')
+ if (this.type === 'date') {
+ time = time + ' ' + '00:00:00'
+ }
+ return Date.parse(time)
+ }
+ },
+
+ /**
+ * 鐢熸垚鏃ユ湡鎴栨椂闂寸殑瀛楃涓�
+ */
+ createDomSting() {
+ const yymmdd = this.year +
+ '-' +
+ this.lessThanTen(this.month) +
+ '-' +
+ this.lessThanTen(this.day)
+
+ let hhmmss = this.lessThanTen(this.hour) +
+ ':' +
+ this.lessThanTen(this.minute)
+
+ if (!this.hideSecond) {
+ hhmmss = hhmmss + ':' + this.lessThanTen(this.second)
+ }
+
+ if (this.type === 'date') {
+ return yymmdd
+ } else if (this.type === 'time') {
+ return hhmmss
+ } else {
+ return yymmdd + ' ' + hhmmss
+ }
+ },
+
+ /**
+ * 鍒濆鍖栬繑鍥炲�硷紝骞舵姏鍑� change 浜嬩欢
+ */
+ initTime(emit = true) {
+ this.time = this.createDomSting()
+ if (!emit) return
+ if (this.returnType === 'timestamp' && this.type !== 'time') {
+ this.$emit('change', this.createTimeStamp(this.time))
+ this.$emit('input', this.createTimeStamp(this.time))
+ this.$emit('update:modelValue', this.createTimeStamp(this.time))
+ } else {
+ this.$emit('change', this.time)
+ this.$emit('input', this.time)
+ this.$emit('update:modelValue', this.time)
+ }
+ },
+
+ /**
+ * 鐢ㄦ埛閫夋嫨鏃ユ湡鎴栨椂闂存洿鏂� data
+ * @param {Object} e
+ */
+ bindDateChange(e) {
+ const val = e.detail.value
+ this.year = this.years[val[0]]
+ this.month = this.months[val[1]]
+ this.day = this.days[val[2]]
+ },
+ bindTimeChange(e) {
+ const val = e.detail.value
+ this.hour = this.hours[val[0]]
+ this.minute = this.minutes[val[1]]
+ this.second = this.seconds[val[2]]
+ },
+
+ /**
+ * 鍒濆鍖栧脊鍑哄眰
+ */
+ initTimePicker() {
+ if (this.disabled) return
+ const value = fixIosDateFormat(this.time)
+ this.initPickerValue(value)
+ this.visible = !this.visible
+ },
+
+ /**
+ * 瑙﹀彂鎴栧叧闂脊妗�
+ */
+ tiggerTimePicker(e) {
+ this.visible = !this.visible
+ },
+
+ /**
+ * 鐢ㄦ埛鐐瑰嚮鈥滄竻绌衡�濇寜閽紝娓呯┖褰撳墠鍊�
+ */
+ clearTime() {
+ this.time = ''
+ this.$emit('change', this.time)
+ this.$emit('input', this.time)
+ this.$emit('update:modelValue', this.time)
+ this.tiggerTimePicker()
+ },
+
+ /**
+ * 鐢ㄦ埛鐐瑰嚮鈥滅‘瀹氣�濇寜閽�
+ */
+ setTime() {
+ this.initTime()
+ this.tiggerTimePicker()
+ }
+ }
+ }
+</script>
+
+<style lang="scss">
+ $uni-primary: #007aff !default;
+
+ .uni-datetime-picker {
+ /* #ifndef APP-NVUE */
+ /* width: 100%; */
+ /* #endif */
+ }
+
+ .uni-datetime-picker-view {
+ height: 130px;
+ width: 270px;
+ /* #ifndef APP-NVUE */
+ cursor: pointer;
+ /* #endif */
+ }
+
+ .uni-datetime-picker-item {
+ height: 50px;
+ line-height: 50px;
+ text-align: center;
+ font-size: 14px;
+ }
+
+ .uni-datetime-picker-btn {
+ margin-top: 60px;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ cursor: pointer;
+ /* #endif */
+ flex-direction: row;
+ justify-content: space-between;
+ }
+
+ .uni-datetime-picker-btn-text {
+ font-size: 14px;
+ color: $uni-primary;
+ }
+
+ .uni-datetime-picker-btn-group {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ }
+
+ .uni-datetime-picker-cancel {
+ margin-right: 30px;
+ }
+
+ .uni-datetime-picker-mask {
+ position: fixed;
+ bottom: 0px;
+ top: 0px;
+ left: 0px;
+ right: 0px;
+ background-color: rgba(0, 0, 0, 0.4);
+ transition-duration: 0.3s;
+ z-index: 998;
+ }
+
+ .uni-datetime-picker-popup {
+ border-radius: 8px;
+ padding: 30px;
+ width: 270px;
+ /* #ifdef APP-NVUE */
+ height: 500px;
+ /* #endif */
+ /* #ifdef APP-NVUE */
+ width: 330px;
+ /* #endif */
+ background-color: #fff;
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ transition-duration: 0.3s;
+ z-index: 999;
+ }
+
+ .fix-nvue-height {
+ /* #ifdef APP-NVUE */
+ height: 330px;
+ /* #endif */
+ }
+
+ .uni-datetime-picker-time {
+ color: grey;
+ }
+
+ .uni-datetime-picker-column {
+ height: 50px;
+ }
+
+ .uni-datetime-picker-timebox {
+
+ border: 1px solid #E5E5E5;
+ border-radius: 5px;
+ padding: 7px 10px;
+ /* #ifndef APP-NVUE */
+ box-sizing: border-box;
+ cursor: pointer;
+ /* #endif */
+ }
+
+ .uni-datetime-picker-timebox-pointer {
+ /* #ifndef APP-NVUE */
+ cursor: pointer;
+ /* #endif */
+ }
+
+
+ .uni-datetime-picker-disabled {
+ opacity: 0.4;
+ /* #ifdef H5 */
+ cursor: not-allowed !important;
+ /* #endif */
+ }
+
+ .uni-datetime-picker-text {
+ font-size: 14px;
+ line-height: 50px
+ }
+
+ .uni-datetime-picker-sign {
+ position: absolute;
+ top: 53px;
+ /* 鍑忔帀 10px 鐨勫厓绱犻珮搴︼紝鍏煎nvue */
+ color: #999;
+ /* #ifdef APP-NVUE */
+ font-size: 16px;
+ /* #endif */
+ }
+
+ .sign-left {
+ left: 86px;
+ }
+
+ .sign-right {
+ right: 86px;
+ }
+
+ .sign-center {
+ left: 135px;
+ }
+
+ .uni-datetime-picker__container-box {
+ position: relative;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-top: 40px;
+ }
+
+ .time-hide-second {
+ width: 180px;
+ }
+</style>
diff --git a/app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue b/app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue
new file mode 100644
index 0000000..bd96488
--- /dev/null
+++ b/app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue
@@ -0,0 +1,1026 @@
+<template>
+ <view class="uni-date">
+ <view class="uni-date-editor" @click="show">
+ <slot>
+ <view
+ class="uni-date-editor--x"
+ :class="{'uni-date-editor--x__disabled': disabled,'uni-date-x--border': border}"
+ >
+ <view v-if="!isRange" class="uni-date-x uni-date-single">
+ <uni-icons class="icon-calendar" type="calendar" color="#c0c4cc" size="22"></uni-icons>
+ <view class="uni-date__x-input">{{ displayValue || singlePlaceholderText }}</view>
+ </view>
+
+ <view v-else class="uni-date-x uni-date-range">
+ <uni-icons class="icon-calendar" type="calendar" color="#c0c4cc" size="22"></uni-icons>
+ <view class="uni-date__x-input text-center">{{ displayRangeValue.startDate || startPlaceholderText }}</view>
+
+ <view class="range-separator">{{rangeSeparator}}</view>
+
+ <view class="uni-date__x-input text-center">{{ displayRangeValue.endDate || endPlaceholderText }}</view>
+ </view>
+
+ <view v-if="showClearIcon" class="uni-date__icon-clear" @click.stop="clear">
+ <uni-icons type="clear" color="#c0c4cc" size="22"></uni-icons>
+ </view>
+ </view>
+ </slot>
+ </view>
+
+ <view v-show="pickerVisible" class="uni-date-mask--pc" @click="close"></view>
+
+ <view v-if="!isPhone" v-show="pickerVisible" ref="datePicker" class="uni-date-picker__container">
+ <view v-if="!isRange" class="uni-date-single--x" :style="pickerPositionStyle">
+ <view class="uni-popper__arrow"></view>
+
+ <view v-if="hasTime" class="uni-date-changed popup-x-header">
+ <input class="uni-date__input text-center" type="text" v-model="inputDate"
+ :placeholder="selectDateText" />
+
+ <time-picker type="time" v-model="pickerTime" :border="false" :disabled="!inputDate"
+ :start="timepickerStartTime" :end="timepickerEndTime" :hideSecond="hideSecond" style="width: 100%;">
+ <input class="uni-date__input text-center" type="text" v-model="pickerTime" :placeholder="selectTimeText"
+ :disabled="!inputDate" />
+ </time-picker>
+ </view>
+
+ <Calendar ref="pcSingle" :showMonth="false" :start-date="calendarRange.startDate"
+ :end-date="calendarRange.endDate" :date="calendarDate" @change="singleChange"
+ :default-value="defaultValue"
+ style="padding: 0 8px;" />
+
+ <view v-if="hasTime" class="popup-x-footer">
+ <text class="confirm-text" @click="confirmSingleChange">{{okText}}</text>
+ </view>
+ </view>
+
+ <view v-else class="uni-date-range--x" :style="pickerPositionStyle">
+ <view class="uni-popper__arrow"></view>
+ <view v-if="hasTime" class="popup-x-header uni-date-changed">
+ <view class="popup-x-header--datetime">
+ <input class="uni-date__input uni-date-range__input" type="text" v-model="tempRange.startDate"
+ :placeholder="startDateText" />
+
+ <time-picker type="time" v-model="tempRange.startTime" :start="timepickerStartTime" :border="false"
+ :disabled="!tempRange.startDate" :hideSecond="hideSecond">
+ <input class="uni-date__input uni-date-range__input" type="text"
+ v-model="tempRange.startTime" :placeholder="startTimeText"
+ :disabled="!tempRange.startDate" />
+ </time-picker>
+ </view>
+
+ <uni-icons type="arrowthinright" color="#999" style="line-height: 40px;"></uni-icons>
+
+ <view class="popup-x-header--datetime">
+ <input class="uni-date__input uni-date-range__input" type="text" v-model="tempRange.endDate"
+ :placeholder="endDateText" />
+
+ <time-picker type="time" v-model="tempRange.endTime" :end="timepickerEndTime" :border="false"
+ :disabled="!tempRange.endDate" :hideSecond="hideSecond">
+ <input class="uni-date__input uni-date-range__input" type="text" v-model="tempRange.endTime"
+ :placeholder="endTimeText" :disabled="!tempRange.endDate" />
+ </time-picker>
+ </view>
+ </view>
+
+ <view class="popup-x-body">
+ <Calendar ref="left" :showMonth="false" :start-date="calendarRange.startDate"
+ :end-date="calendarRange.endDate" :range="true" :pleStatus="endMultipleStatus"
+ @change="leftChange" @firstEnterCale="updateRightCale" style="padding: 0 8px;" />
+ <Calendar ref="right" :showMonth="false" :start-date="calendarRange.startDate"
+ :end-date="calendarRange.endDate" :range="true" @change="rightChange"
+ :pleStatus="startMultipleStatus" @firstEnterCale="updateLeftCale"
+ style="padding: 0 8px;border-left: 1px solid #F1F1F1;" />
+ </view>
+
+ <view v-if="hasTime" class="popup-x-footer">
+ <text @click="clear">{{clearText}}</text>
+ <text class="confirm-text" @click="confirmRangeChange">{{okText}}</text>
+ </view>
+ </view>
+ </view>
+
+ <Calendar v-if="isPhone" ref="mobile" :clearDate="false" :date="calendarDate" :defTime="mobileCalendarTime"
+ :start-date="calendarRange.startDate" :end-date="calendarRange.endDate" :selectableTimes="mobSelectableTime"
+ :startPlaceholder="startPlaceholder" :endPlaceholder="endPlaceholder"
+ :default-value="defaultValue"
+ :pleStatus="endMultipleStatus" :showMonth="false" :range="isRange" :hasTime="hasTime" :insert="false"
+ :hideSecond="hideSecond" @confirm="mobileChange" @maskClose="close" />
+ </view>
+</template>
+<script>
+ /**
+ * DatetimePicker 鏃堕棿閫夋嫨鍣�
+ * @description 鍚屾椂鏀寔 PC 鍜岀Щ鍔ㄧ浣跨敤鏃ュ巻閫夋嫨鏃ユ湡鍜屾棩鏈熻寖鍥�
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=3962
+ * @property {String} type 閫夋嫨鍣ㄧ被鍨�
+ * @property {String|Number|Array|Date} value 缁戝畾鍊�
+ * @property {String} placeholder 鍗曢�夋嫨鏃剁殑鍗犱綅鍐呭
+ * @property {String} start 璧峰鏃堕棿
+ * @property {String} end 缁堟鏃堕棿
+ * @property {String} start-placeholder 鑼冨洿閫夋嫨鏃跺紑濮嬫棩鏈熺殑鍗犱綅鍐呭
+ * @property {String} end-placeholder 鑼冨洿閫夋嫨鏃剁粨鏉熸棩鏈熺殑鍗犱綅鍐呭
+ * @property {String} range-separator 閫夋嫨鑼冨洿鏃剁殑鍒嗛殧绗�
+ * @property {Boolean} border = [true|false] 鏄惁鏈夎竟妗�
+ * @property {Boolean} disabled = [true|false] 鏄惁绂佺敤
+ * @property {Boolean} clearIcon = [true|false] 鏄惁鏄剧ず娓呴櫎鎸夐挳锛堜粎PC绔�傜敤锛�
+ * @property {[String} defaultValue 閫夋嫨鍣ㄦ墦寮�鏃堕粯璁ゆ樉绀虹殑鏃堕棿
+ * @event {Function} change 纭畾鏃ユ湡鏃惰Е鍙戠殑浜嬩欢
+ * @event {Function} maskClick 鐐瑰嚮閬僵灞傝Е鍙戠殑浜嬩欢
+ * @event {Function} show 鎵撳紑寮瑰嚭灞�
+ * @event {Function} close 鍏抽棴寮瑰嚭灞�
+ * @event {Function} clear 娓呴櫎涓婃閫変腑鐨勭姸鎬佸拰鍊�
+ **/
+ import Calendar from './calendar.vue'
+ import TimePicker from './time-picker.vue'
+ import { initVueI18n } from '@dcloudio/uni-i18n'
+ import i18nMessages from './i18n/index.js'
+ import { getDateTime, getDate, getTime, getDefaultSecond, dateCompare, checkDate, fixIosDateFormat } from './util'
+
+ export default {
+ name: 'UniDatetimePicker',
+ options: {
+ virtualHost: true
+ },
+ components: {
+ Calendar,
+ TimePicker
+ },
+ data() {
+ return {
+ isRange: false,
+ hasTime: false,
+ displayValue: '',
+ inputDate: '',
+ calendarDate: '',
+ pickerTime: '',
+ calendarRange: {
+ startDate: '',
+ startTime: '',
+ endDate: '',
+ endTime: ''
+ },
+ displayRangeValue: {
+ startDate: '',
+ endDate: '',
+ },
+ tempRange: {
+ startDate: '',
+ startTime: '',
+ endDate: '',
+ endTime: ''
+ },
+ // 宸﹀彸鏃ュ巻鍚屾鏁版嵁
+ startMultipleStatus: {
+ before: '',
+ after: '',
+ data: [],
+ fulldate: ''
+ },
+ endMultipleStatus: {
+ before: '',
+ after: '',
+ data: [],
+ fulldate: ''
+ },
+ pickerVisible: false,
+ pickerPositionStyle: null,
+ isEmitValue: false,
+ isPhone: false,
+ isFirstShow: true,
+ i18nT: () => {}
+ }
+ },
+ props: {
+ type: {
+ type: String,
+ default: 'datetime'
+ },
+ value: {
+ type: [String, Number, Array, Date],
+ default: ''
+ },
+ modelValue: {
+ type: [String, Number, Array, Date],
+ default: ''
+ },
+ start: {
+ type: [Number, String],
+ default: ''
+ },
+ end: {
+ type: [Number, String],
+ default: ''
+ },
+ returnType: {
+ type: String,
+ default: 'string'
+ },
+ placeholder: {
+ type: String,
+ default: ''
+ },
+ startPlaceholder: {
+ type: String,
+ default: ''
+ },
+ endPlaceholder: {
+ type: String,
+ default: ''
+ },
+ rangeSeparator: {
+ type: String,
+ default: '-'
+ },
+ border: {
+ type: [Boolean],
+ default: true
+ },
+ disabled: {
+ type: [Boolean],
+ default: false
+ },
+ clearIcon: {
+ type: [Boolean],
+ default: true
+ },
+ hideSecond: {
+ type: [Boolean],
+ default: false
+ },
+ defaultValue: {
+ type: [String, Object, Array],
+ default: ''
+ }
+ },
+ watch: {
+ type: {
+ immediate: true,
+ handler(newVal) {
+ this.hasTime = newVal.indexOf('time') !== -1
+ this.isRange = newVal.indexOf('range') !== -1
+ }
+ },
+ // #ifndef VUE3
+ value: {
+ immediate: true,
+ handler(newVal) {
+ if (this.isEmitValue) {
+ this.isEmitValue = false
+ return
+ }
+ this.initPicker(newVal)
+ }
+ },
+ // #endif
+ // #ifdef VUE3
+ modelValue: {
+ immediate: true,
+ handler(newVal) {
+ if (this.isEmitValue) {
+ this.isEmitValue = false
+ return
+ }
+ this.initPicker(newVal)
+ }
+ },
+ // #endif
+ start: {
+ immediate: true,
+ handler(newVal) {
+ if (!newVal) return
+ this.calendarRange.startDate = getDate(newVal)
+ if (this.hasTime) {
+ this.calendarRange.startTime = getTime(newVal)
+ }
+ }
+ },
+ end: {
+ immediate: true,
+ handler(newVal) {
+ if (!newVal) return
+ this.calendarRange.endDate = getDate(newVal)
+ if (this.hasTime) {
+ this.calendarRange.endTime = getTime(newVal, this.hideSecond)
+ }
+ }
+ },
+ },
+ computed: {
+ timepickerStartTime() {
+ const activeDate = this.isRange ? this.tempRange.startDate : this.inputDate
+ return activeDate === this.calendarRange.startDate ? this.calendarRange.startTime : ''
+ },
+ timepickerEndTime() {
+ const activeDate = this.isRange ? this.tempRange.endDate : this.inputDate
+ return activeDate === this.calendarRange.endDate ? this.calendarRange.endTime : ''
+ },
+ mobileCalendarTime() {
+ const timeRange = {
+ start: this.tempRange.startTime,
+ end: this.tempRange.endTime
+ }
+ return this.isRange ? timeRange : this.pickerTime
+ },
+ mobSelectableTime() {
+ return {
+ start: this.calendarRange.startTime,
+ end: this.calendarRange.endTime
+ }
+ },
+ datePopupWidth() {
+ // todo
+ return this.isRange ? 653 : 301
+ },
+
+ /**
+ * for i18n
+ */
+ singlePlaceholderText() {
+ return this.placeholder || (this.type === 'date' ? this.selectDateText : this.selectDateTimeText)
+ },
+ startPlaceholderText() {
+ return this.startPlaceholder || this.startDateText
+ },
+ endPlaceholderText() {
+ return this.endPlaceholder || this.endDateText
+ },
+ selectDateText() {
+ return this.i18nT("uni-datetime-picker.selectDate")
+ },
+ selectDateTimeText() {
+ return this.i18nT("uni-datetime-picker.selectDateTime")
+ },
+ selectTimeText() {
+ return this.i18nT("uni-datetime-picker.selectTime")
+ },
+ startDateText() {
+ return this.startPlaceholder || this.i18nT("uni-datetime-picker.startDate")
+ },
+ startTimeText() {
+ return this.i18nT("uni-datetime-picker.startTime")
+ },
+ endDateText() {
+ return this.endPlaceholder || this.i18nT("uni-datetime-picker.endDate")
+ },
+ endTimeText() {
+ return this.i18nT("uni-datetime-picker.endTime")
+ },
+ okText() {
+ return this.i18nT("uni-datetime-picker.ok")
+ },
+ clearText() {
+ return this.i18nT("uni-datetime-picker.clear")
+ },
+ showClearIcon() {
+ return this.clearIcon && !this.disabled && (this.displayValue || (this.displayRangeValue.startDate && this.displayRangeValue.endDate))
+ }
+ },
+ created() {
+ this.initI18nT()
+ this.platform()
+ },
+ methods: {
+ initI18nT() {
+ const vueI18n = initVueI18n(i18nMessages)
+ this.i18nT = vueI18n.t
+ },
+ initPicker(newVal) {
+ if ((!newVal && !this.defaultValue) || Array.isArray(newVal) && !newVal.length) {
+ this.$nextTick(() => {
+ this.clear(false)
+ })
+ return
+ }
+
+ if (!Array.isArray(newVal) && !this.isRange) {
+ if(newVal){
+ this.displayValue = this.inputDate = this.calendarDate = getDate(newVal)
+ if (this.hasTime) {
+ this.pickerTime = getTime(newVal, this.hideSecond)
+ this.displayValue = `${this.displayValue} ${this.pickerTime}`
+ }
+ }else if(this.defaultValue){
+ this.inputDate = this.calendarDate = getDate(this.defaultValue)
+ if(this.hasTime){
+ this.pickerTime = getTime(this.defaultValue, this.hideSecond)
+ }
+ }
+ } else {
+ const [before, after] = newVal
+ if (!before && !after) return
+ const beforeDate = getDate(before)
+ const beforeTime = getTime(before, this.hideSecond)
+
+ const afterDate = getDate(after)
+ const afterTime = getTime(after, this.hideSecond)
+ const startDate = beforeDate
+ const endDate = afterDate
+ this.displayRangeValue.startDate = this.tempRange.startDate = startDate
+ this.displayRangeValue.endDate = this.tempRange.endDate = endDate
+
+ if (this.hasTime) {
+ this.displayRangeValue.startDate = `${beforeDate} ${beforeTime}`
+ this.displayRangeValue.endDate = `${afterDate} ${afterTime}`
+ this.tempRange.startTime = beforeTime
+ this.tempRange.endTime = afterTime
+ }
+ const defaultRange = {
+ before: beforeDate,
+ after: afterDate
+ }
+ this.startMultipleStatus = Object.assign({}, this.startMultipleStatus, defaultRange, {
+ which: 'right'
+ })
+ this.endMultipleStatus = Object.assign({}, this.endMultipleStatus, defaultRange, {
+ which: 'left'
+ })
+ }
+ },
+ updateLeftCale(e) {
+ const left = this.$refs.left
+ // 璁剧疆鑼冨洿閫�
+ left.cale.setHoverMultiple(e.after)
+ left.setDate(this.$refs.left.nowDate.fullDate)
+ },
+ updateRightCale(e) {
+ const right = this.$refs.right
+ // 璁剧疆鑼冨洿閫�
+ right.cale.setHoverMultiple(e.after)
+ right.setDate(this.$refs.right.nowDate.fullDate)
+ },
+ platform() {
+ const { windowWidth } = uni.getSystemInfoSync()
+ this.isPhone = windowWidth <= 500
+ this.windowWidth = windowWidth
+ },
+ show() {
+ if (this.disabled) {
+ return
+ }
+ this.platform()
+ if (this.isPhone) {
+ this.$refs.mobile.open()
+ return
+ }
+ this.pickerPositionStyle = {
+ top: '10px'
+ }
+ const dateEditor = uni.createSelectorQuery().in(this).select(".uni-date-editor")
+ dateEditor.boundingClientRect(rect => {
+ if (this.windowWidth - rect.left < this.datePopupWidth) {
+ this.pickerPositionStyle.right = 0
+ }
+ }).exec()
+ setTimeout(() => {
+ this.pickerVisible = !this.pickerVisible
+ if (!this.isPhone && this.isRange && this.isFirstShow) {
+ this.isFirstShow = false
+ const {
+ startDate,
+ endDate
+ } = this.calendarRange
+ if (startDate && endDate) {
+ if (this.diffDate(startDate, endDate) < 30) {
+ this.$refs.right.changeMonth('pre')
+ }
+ } else {
+ this.$refs.right.changeMonth('next')
+ this.$refs.right.cale.lastHover = false
+ }
+ }
+
+ }, 50)
+ },
+ close() {
+ setTimeout(() => {
+ this.pickerVisible = false
+ this.$emit('maskClick', this.value)
+ this.$refs.mobile && this.$refs.mobile.close()
+ }, 20)
+ },
+ setEmit(value) {
+ if (this.returnType === "timestamp" || this.returnType === "date") {
+ if (!Array.isArray(value)) {
+ if (!this.hasTime) {
+ value = value + ' ' + '00:00:00'
+ }
+ value = this.createTimestamp(value)
+ if (this.returnType === "date") {
+ value = new Date(value)
+ }
+ } else {
+ if (!this.hasTime) {
+ value[0] = value[0] + ' ' + '00:00:00'
+ value[1] = value[1] + ' ' + '00:00:00'
+ }
+ value[0] = this.createTimestamp(value[0])
+ value[1] = this.createTimestamp(value[1])
+ if (this.returnType === "date") {
+ value[0] = new Date(value[0])
+ value[1] = new Date(value[1])
+ }
+ }
+ }
+
+ this.$emit('update:modelValue', value)
+ this.$emit('input', value)
+ this.$emit('change', value)
+ this.isEmitValue = true
+ },
+ createTimestamp(date) {
+ date = fixIosDateFormat(date)
+ return Date.parse(new Date(date))
+ },
+ singleChange(e) {
+ this.calendarDate = this.inputDate = e.fulldate
+ if (this.hasTime) return
+ this.confirmSingleChange()
+ },
+ confirmSingleChange() {
+ if(!checkDate(this.inputDate)){
+ const now = new Date()
+ this.calendarDate = this.inputDate = getDate(now)
+ this.pickerTime = getTime(now, this.hideSecond)
+ }
+
+ let startLaterInputDate = false
+ let startDate, startTime
+ if(this.start) {
+ let startString = this.start
+ if(typeof this.start === 'number'){
+ startString = getDateTime(this.start, this.hideSecond)
+ }
+ [startDate, startTime] = startString.split(' ')
+ if(this.start && !dateCompare(startDate, this.inputDate)) {
+ startLaterInputDate = true
+ this.inputDate = startDate
+ }
+ }
+
+ let endEarlierInputDate = false
+ let endDate, endTime
+ if(this.end) {
+ let endString = this.end
+ if(typeof this.end === 'number'){
+ endString = getDateTime(this.end, this.hideSecond)
+ }
+ [endDate, endTime] = endString.split(' ')
+ if(this.end && !dateCompare(this.inputDate, endDate)) {
+ endEarlierInputDate = true
+ this.inputDate = endDate
+ }
+ }
+ if (this.hasTime) {
+ if(startLaterInputDate){
+ this.pickerTime = startTime || getDefaultSecond(this.hideSecond)
+ }
+ if(endEarlierInputDate){
+ this.pickerTime = endTime || getDefaultSecond(this.hideSecond)
+ }
+ if(!this.pickerTime){
+ this.pickerTime = getTime(Date.now(), this.hideSecond)
+ }
+ this.displayValue = `${this.inputDate} ${this.pickerTime}`
+ } else {
+ this.displayValue = this.inputDate
+ }
+ this.setEmit(this.displayValue)
+ this.pickerVisible = false
+ },
+ leftChange(e) {
+ const {
+ before,
+ after
+ } = e.range
+ this.rangeChange(before, after)
+ const obj = {
+ before: e.range.before,
+ after: e.range.after,
+ data: e.range.data,
+ fulldate: e.fulldate
+ }
+ this.startMultipleStatus = Object.assign({}, this.startMultipleStatus, obj)
+ },
+ rightChange(e) {
+ const {
+ before,
+ after
+ } = e.range
+ this.rangeChange(before, after)
+ const obj = {
+ before: e.range.before,
+ after: e.range.after,
+ data: e.range.data,
+ fulldate: e.fulldate
+ }
+ this.endMultipleStatus = Object.assign({}, this.endMultipleStatus, obj)
+ },
+ mobileChange(e) {
+ if (this.isRange) {
+ const {before, after} = e.range
+
+ if(!before || !after){
+ return
+ }
+
+ this.handleStartAndEnd(before, after, true)
+ if (this.hasTime) {
+ const {
+ startTime,
+ endTime
+ } = e.timeRange
+ this.tempRange.startTime = startTime
+ this.tempRange.endTime = endTime
+ }
+ this.confirmRangeChange()
+ } else {
+ if (this.hasTime) {
+ this.displayValue = e.fulldate + ' ' + e.time
+ } else {
+ this.displayValue = e.fulldate
+ }
+ this.setEmit(this.displayValue)
+ }
+ this.$refs.mobile.close()
+ },
+ rangeChange(before, after) {
+ if (!(before && after)) return
+ this.handleStartAndEnd(before, after, true)
+ if (this.hasTime) return
+ this.confirmRangeChange()
+ },
+ confirmRangeChange() {
+ if (!this.tempRange.startDate || !this.tempRange.endDate) {
+ this.pickerVisible = false
+ return
+ }
+ if(!checkDate(this.tempRange.startDate)){
+ this.tempRange.startDate = getDate(Date.now())
+ }
+ if(!checkDate(this.tempRange.endDate)){
+ this.tempRange.endDate = getDate(Date.now())
+ }
+
+ let start, end
+
+ let startDateLaterRangeStartDate = false
+ let startDateLaterRangeEndDate = false
+ let startDate, startTime
+ if(this.start) {
+ let startString = this.start
+ if(typeof this.start === 'number'){
+ startString = getDateTime(this.start, this.hideSecond)
+ }
+ [startDate,startTime] = startString.split(' ')
+ if(this.start && !dateCompare(this.start, this.tempRange.startDate)) {
+ startDateLaterRangeStartDate = true
+ this.tempRange.startDate = startDate
+ }
+ if(this.start && !dateCompare(this.start, this.tempRange.endDate)) {
+ startDateLaterRangeEndDate = true
+ this.tempRange.endDate = startDate
+ }
+ }
+ let endDateEarlierRangeStartDate = false
+ let endDateEarlierRangeEndDate = false
+ let endDate, endTime
+ if(this.end) {
+ let endString = this.end
+ if(typeof this.end === 'number'){
+ endString = getDateTime(this.end, this.hideSecond)
+ }
+ [endDate,endTime] = endString.split(' ')
+
+ if(this.end && !dateCompare(this.tempRange.startDate, this.end)) {
+ endDateEarlierRangeStartDate = true
+ this.tempRange.startDate = endDate
+ }
+ if(this.end && !dateCompare(this.tempRange.endDate, this.end)) {
+ endDateEarlierRangeEndDate = true
+ this.tempRange.endDate = endDate
+ }
+ }
+ if (!this.hasTime) {
+ start = this.displayRangeValue.startDate = this.tempRange.startDate
+ end = this.displayRangeValue.endDate = this.tempRange.endDate
+ } else {
+ if(startDateLaterRangeStartDate){
+ this.tempRange.startTime = startTime || getDefaultSecond(this.hideSecond)
+ }else if(endDateEarlierRangeStartDate){
+ this.tempRange.startTime = endTime || getDefaultSecond(this.hideSecond)
+ }
+ if(!this.tempRange.startTime){
+ this.tempRange.startTime = getTime(Date.now(), this.hideSecond)
+ }
+
+ if(startDateLaterRangeEndDate){
+ this.tempRange.endTime = startTime || getDefaultSecond(this.hideSecond)
+ }else if(endDateEarlierRangeEndDate){
+ this.tempRange.endTime = endTime || getDefaultSecond(this.hideSecond)
+ }
+ if(!this.tempRange.endTime){
+ this.tempRange.endTime = getTime(Date.now(), this.hideSecond)
+ }
+ start = this.displayRangeValue.startDate = `${this.tempRange.startDate} ${this.tempRange.startTime}`
+ end = this.displayRangeValue.endDate = `${this.tempRange.endDate} ${this.tempRange.endTime}`
+ }
+ if(!dateCompare(start,end)){
+ [start, end] = [end, start]
+ }
+ this.displayRangeValue.startDate = start
+ this.displayRangeValue.endDate = end
+ const displayRange = [start, end]
+ this.setEmit(displayRange)
+ this.pickerVisible = false
+ },
+ handleStartAndEnd(before, after, temp = false) {
+ if (!(before && after)) return
+
+ const type = temp ? 'tempRange' : 'range'
+ const isStartEarlierEnd = dateCompare(before, after)
+ this[type].startDate = isStartEarlierEnd ? before : after
+ this[type].endDate = isStartEarlierEnd ? after : before
+ },
+ /**
+ * 姣旇緝鏃堕棿澶у皬
+ */
+ dateCompare(startDate, endDate) {
+ // 璁$畻鎴鏃堕棿
+ startDate = new Date(startDate.replace('-', '/').replace('-', '/'))
+ // 璁$畻璇︾粏椤圭殑鎴鏃堕棿
+ endDate = new Date(endDate.replace('-', '/').replace('-', '/'))
+ return startDate <= endDate
+ },
+
+ /**
+ * 姣旇緝鏃堕棿宸�
+ */
+ diffDate(startDate, endDate) {
+ // 璁$畻鎴鏃堕棿
+ startDate = new Date(startDate.replace('-', '/').replace('-', '/'))
+ // 璁$畻璇︾粏椤圭殑鎴鏃堕棿
+ endDate = new Date(endDate.replace('-', '/').replace('-', '/'))
+ const diff = (endDate - startDate) / (24 * 60 * 60 * 1000)
+ return Math.abs(diff)
+ },
+
+ clear(needEmit = true) {
+ if (!this.isRange) {
+ this.displayValue = ''
+ this.inputDate = ''
+ this.pickerTime = ''
+ if (this.isPhone) {
+ this.$refs.mobile && this.$refs.mobile.clearCalender()
+ } else {
+ this.$refs.pcSingle && this.$refs.pcSingle.clearCalender()
+ }
+ if (needEmit) {
+ this.$emit('change', '')
+ this.$emit('input', '')
+ this.$emit('update:modelValue', '')
+ }
+ } else {
+ this.displayRangeValue.startDate = ''
+ this.displayRangeValue.endDate = ''
+ this.tempRange.startDate = ''
+ this.tempRange.startTime = ''
+ this.tempRange.endDate = ''
+ this.tempRange.endTime = ''
+ if (this.isPhone) {
+ this.$refs.mobile && this.$refs.mobile.clearCalender()
+ } else {
+ this.$refs.left && this.$refs.left.clearCalender()
+ this.$refs.right && this.$refs.right.clearCalender()
+ this.$refs.right && this.$refs.right.changeMonth('next')
+ }
+ if (needEmit) {
+ this.$emit('change', [])
+ this.$emit('input', [])
+ this.$emit('update:modelValue', [])
+ }
+ }
+ }
+ }
+ }
+</script>
+
+<style lang="scss">
+ $uni-primary: #007aff !default;
+
+ .uni-date {
+ width: 100%;
+ flex: 1;
+ }
+ .uni-date-x {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: center;
+ border-radius: 4px;
+ background-color: #fff;
+ color: #666;
+ font-size: 14px;
+ flex: 1;
+
+ .icon-calendar{
+ padding-left: 3px;
+ }
+ .range-separator{
+ height: 35px;
+ /* #ifndef MP */
+ padding: 0 2px;
+ /* #endif */
+ line-height: 35px;
+ }
+ }
+
+ .uni-date-x--border {
+ box-sizing: border-box;
+ border-radius: 4px;
+ border: 1px solid #e5e5e5;
+ }
+
+ .uni-date-editor--x {
+ display: flex;
+ align-items: center;
+ position: relative;
+ }
+
+ .uni-date-editor--x .uni-date__icon-clear {
+ padding-right: 3px;
+ display: flex;
+ align-items: center;
+ /* #ifdef H5 */
+ cursor: pointer;
+ /* #endif */
+ }
+
+ .uni-date__x-input {
+ width: auto;
+ height: 35px;
+ /* #ifndef MP */
+ padding-left: 5px;
+ /* #endif */
+ position: relative;
+ flex: 1;
+ line-height: 35px;
+ font-size: 14px;
+ overflow: hidden;
+ }
+
+ .text-center {
+ text-align: center;
+ }
+
+ .uni-date__input {
+ height: 40px;
+ width: 100%;
+ line-height: 40px;
+ font-size: 14px;
+ }
+
+ .uni-date-range__input {
+ text-align: center;
+ max-width: 142px;
+ }
+
+ .uni-date-picker__container {
+ position: relative;
+ }
+
+ .uni-date-mask--pc {
+ position: fixed;
+ bottom: 0px;
+ top: 0px;
+ left: 0px;
+ right: 0px;
+ background-color: rgba(0, 0, 0, 0);
+ transition-duration: 0.3s;
+ z-index: 996;
+ }
+
+ .uni-date-single--x {
+ background-color: #fff;
+ position: absolute;
+ top: 0;
+ z-index: 999;
+ border: 1px solid #EBEEF5;
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+ border-radius: 4px;
+ }
+
+ .uni-date-range--x {
+ background-color: #fff;
+ position: absolute;
+ top: 0;
+ z-index: 999;
+ border: 1px solid #EBEEF5;
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+ border-radius: 4px;
+ }
+
+ .uni-date-editor--x__disabled {
+ opacity: 0.4;
+ cursor: default;
+ }
+
+ .uni-date-editor--logo {
+ width: 16px;
+ height: 16px;
+ vertical-align: middle;
+ }
+
+ /* 娣诲姞鏃堕棿 */
+ .popup-x-header {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ }
+
+ .popup-x-header--datetime {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ flex: 1;
+ }
+
+ .popup-x-body {
+ display: flex;
+ }
+
+ .popup-x-footer {
+ padding: 0 15px;
+ border-top-color: #F1F1F1;
+ border-top-style: solid;
+ border-top-width: 1px;
+ line-height: 40px;
+ text-align: right;
+ color: #666;
+ }
+
+ .popup-x-footer text:hover {
+ color: $uni-primary;
+ cursor: pointer;
+ opacity: 0.8;
+ }
+
+ .popup-x-footer .confirm-text {
+ margin-left: 20px;
+ color: $uni-primary;
+ }
+
+ .uni-date-changed {
+ text-align: center;
+ color: #333;
+ border-bottom-color: #F1F1F1;
+ border-bottom-style: solid;
+ border-bottom-width: 1px;
+ }
+
+ .uni-date-changed--time text {
+ height: 50px;
+ line-height: 50px;
+ }
+
+ .uni-date-changed .uni-date-changed--time {
+ flex: 1;
+ }
+
+ .uni-date-changed--time-date {
+ color: #333;
+ opacity: 0.6;
+ }
+
+ .mr-50 {
+ margin-right: 50px;
+ }
+
+ /* picker 寮瑰嚭灞傞�氱敤鐨勬寚绀哄皬涓夎, todo锛氭墿灞曡嚦涓婁笅宸﹀彸鏂瑰悜瀹氫綅 */
+ .uni-popper__arrow,
+ .uni-popper__arrow::after {
+ position: absolute;
+ display: block;
+ width: 0;
+ height: 0;
+ border: 6px solid transparent;
+ border-top-width: 0;
+ }
+
+ .uni-popper__arrow {
+ filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03));
+ top: -6px;
+ left: 10%;
+ margin-right: 3px;
+ border-bottom-color: #EBEEF5;
+ }
+
+ .uni-popper__arrow::after {
+ content: " ";
+ top: 1px;
+ margin-left: -6px;
+ border-bottom-color: #fff;
+ }
+</style>
diff --git a/app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/util.js b/app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/util.js
new file mode 100644
index 0000000..7dc34c4
--- /dev/null
+++ b/app/uni_modules/uni-datetime-picker/components/uni-datetime-picker/util.js
@@ -0,0 +1,403 @@
+class Calendar {
+ constructor({
+ selected,
+ startDate,
+ endDate,
+ range,
+ } = {}) {
+ // 褰撳墠鏃ユ湡
+ this.date = this.getDateObj(new Date()) // 褰撳墠鍒濆叆鏃ユ湡
+ // 鎵撶偣淇℃伅
+ this.selected = selected || [];
+ // 璧峰鏃堕棿
+ this.startDate = startDate
+ // 缁堟鏃堕棿
+ this.endDate = endDate
+ // 鏄惁鑼冨洿閫夋嫨
+ this.range = range
+ // 澶氶�夌姸鎬�
+ this.cleanMultipleStatus()
+ // 姣忓懆鏃ユ湡
+ this.weeks = {}
+ this.lastHover = false
+ }
+ /**
+ * 璁剧疆鏃ユ湡
+ * @param {Object} date
+ */
+ setDate(date) {
+ const selectDate = this.getDateObj(date)
+ this.getWeeks(selectDate.fullDate)
+ }
+
+ /**
+ * 娓呯悊澶氶�夌姸鎬�
+ */
+ cleanMultipleStatus() {
+ this.multipleStatus = {
+ before: '',
+ after: '',
+ data: []
+ }
+ }
+
+ setStartDate(startDate) {
+ this.startDate = startDate
+ }
+
+ setEndDate(endDate) {
+ this.endDate = endDate
+ }
+
+ getPreMonthObj(date){
+ date = fixIosDateFormat(date)
+ date = new Date(date)
+
+ const oldMonth = date.getMonth()
+ date.setMonth(oldMonth - 1)
+ const newMonth = date.getMonth()
+ if(oldMonth !== 0 && newMonth - oldMonth === 0){
+ date.setMonth(newMonth - 1)
+ }
+ return this.getDateObj(date)
+ }
+ getNextMonthObj(date){
+ date = fixIosDateFormat(date)
+ date = new Date(date)
+
+ const oldMonth = date.getMonth()
+ date.setMonth(oldMonth + 1)
+ const newMonth = date.getMonth()
+ if(newMonth - oldMonth > 1){
+ date.setMonth(newMonth - 1)
+ }
+ return this.getDateObj(date)
+ }
+
+ /**
+ * 鑾峰彇鎸囧畾鏍煎紡Date瀵硅薄
+ */
+ getDateObj(date) {
+ date = fixIosDateFormat(date)
+ date = new Date(date)
+
+ return {
+ fullDate: getDate(date),
+ year: date.getFullYear(),
+ month: addZero(date.getMonth() + 1),
+ date: addZero(date.getDate()),
+ day: date.getDay()
+ }
+ }
+
+ /**
+ * 鑾峰彇涓婁竴涓湀鏃ユ湡闆嗗悎
+ */
+ getPreMonthDays(amount, dateObj) {
+ const result = []
+ for (let i = amount - 1; i >= 0; i--) {
+ const month = dateObj.month - 1
+ result.push({
+ date: new Date(dateObj.year, month, -i).getDate(),
+ month,
+ disable: true
+ })
+ }
+ return result
+ }
+ /**
+ * 鑾峰彇鏈湀鏃ユ湡闆嗗悎
+ */
+ getCurrentMonthDays(amount, dateObj) {
+ const result = []
+ const fullDate = this.date.fullDate
+ for (let i = 1; i <= amount; i++) {
+ const currentDate = `${dateObj.year}-${dateObj.month}-${addZero(i)}`
+ const isToday = fullDate === currentDate
+ // 鑾峰彇鎵撶偣淇℃伅
+ const info = this.selected && this.selected.find((item) => {
+ if (this.dateEqual(currentDate, item.date)) {
+ return item
+ }
+ })
+
+ // 鏃ユ湡绂佺敤
+ let disableBefore = true
+ let disableAfter = true
+ if (this.startDate) {
+ disableBefore = dateCompare(this.startDate, currentDate)
+ }
+
+ if (this.endDate) {
+ disableAfter = dateCompare(currentDate, this.endDate)
+ }
+
+ let multiples = this.multipleStatus.data
+ let multiplesStatus = -1
+ if (this.range && multiples) {
+ multiplesStatus = multiples.findIndex((item) => {
+ return this.dateEqual(item, currentDate)
+ })
+ }
+ const checked = multiplesStatus !== -1
+
+ result.push({
+ fullDate: currentDate,
+ year: dateObj.year,
+ date: i,
+ multiple: this.range ? checked : false,
+ beforeMultiple: this.isLogicBefore(currentDate, this.multipleStatus.before, this.multipleStatus.after),
+ afterMultiple: this.isLogicAfter(currentDate, this.multipleStatus.before, this.multipleStatus.after),
+ month: dateObj.month,
+ disable: (this.startDate && !dateCompare(this.startDate, currentDate)) || (this.endDate && !dateCompare(currentDate,this.endDate)),
+ isToday,
+ userChecked: false,
+ extraInfo: info
+ })
+ }
+ return result
+ }
+ /**
+ * 鑾峰彇涓嬩竴涓湀鏃ユ湡闆嗗悎
+ */
+ _getNextMonthDays(amount, dateObj) {
+ const result = []
+ const month = dateObj.month + 1
+ for (let i = 1; i <= amount; i++) {
+ result.push({
+ date: i,
+ month,
+ disable: true
+ })
+ }
+ return result
+ }
+
+ /**
+ * 鑾峰彇褰撳墠鏃ユ湡璇︽儏
+ * @param {Object} date
+ */
+ getInfo(date) {
+ if (!date) {
+ date = new Date()
+ }
+
+ return this.calendar.find(item => item.fullDate === this.getDateObj(date).fullDate)
+ }
+
+ /**
+ * 姣旇緝鏃堕棿鏄惁鐩哥瓑
+ */
+ dateEqual(before, after) {
+ before = new Date(fixIosDateFormat(before))
+ after = new Date(fixIosDateFormat(after))
+ return before.valueOf() === after.valueOf()
+ }
+
+ /**
+ * 姣旇緝鐪熷疄璧峰鏃ユ湡
+ */
+
+ isLogicBefore(currentDate, before, after) {
+ let logicBefore = before
+ if (before && after) {
+ logicBefore = dateCompare(before, after) ? before : after
+ }
+ return this.dateEqual(logicBefore, currentDate)
+ }
+
+ isLogicAfter(currentDate, before, after) {
+ let logicAfter = after
+ if (before && after) {
+ logicAfter = dateCompare(before, after) ? after : before
+ }
+ return this.dateEqual(logicAfter, currentDate)
+ }
+
+ /**
+ * 鑾峰彇鏃ユ湡鑼冨洿鍐呮墍鏈夋棩鏈�
+ * @param {Object} begin
+ * @param {Object} end
+ */
+ geDateAll(begin, end) {
+ var arr = []
+ var ab = begin.split('-')
+ var ae = end.split('-')
+ var db = new Date()
+ db.setFullYear(ab[0], ab[1] - 1, ab[2])
+ var de = new Date()
+ de.setFullYear(ae[0], ae[1] - 1, ae[2])
+ var unixDb = db.getTime() - 24 * 60 * 60 * 1000
+ var unixDe = de.getTime() - 24 * 60 * 60 * 1000
+ for (var k = unixDb; k <= unixDe;) {
+ k = k + 24 * 60 * 60 * 1000
+ arr.push(this.getDateObj(new Date(parseInt(k))).fullDate)
+ }
+ return arr
+ }
+
+ /**
+ * 鑾峰彇澶氶�夌姸鎬�
+ */
+ setMultiple(fullDate) {
+ if (!this.range) return
+
+ let {
+ before,
+ after
+ } = this.multipleStatus
+ if (before && after) {
+ if (!this.lastHover) {
+ this.lastHover = true
+ return
+ }
+ this.multipleStatus.before = fullDate
+ this.multipleStatus.after = ''
+ this.multipleStatus.data = []
+ this.multipleStatus.fulldate = ''
+ this.lastHover = false
+ } else {
+ if (!before) {
+ this.multipleStatus.before = fullDate
+ this.lastHover = false
+ } else {
+ this.multipleStatus.after = fullDate
+ if (dateCompare(this.multipleStatus.before, this.multipleStatus.after)) {
+ this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus
+ .after);
+ } else {
+ this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus
+ .before);
+ }
+ this.lastHover = true
+ }
+ }
+ this.getWeeks(fullDate)
+ }
+
+ /**
+ * 榧犳爣 hover 鏇存柊澶氶�夌姸鎬�
+ */
+ setHoverMultiple(fullDate) {
+ if (!this.range || this.lastHover) return
+
+ const { before } = this.multipleStatus
+
+ if (!before) {
+ this.multipleStatus.before = fullDate
+ } else {
+ this.multipleStatus.after = fullDate
+ if (dateCompare(this.multipleStatus.before, this.multipleStatus.after)) {
+ this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus.after);
+ } else {
+ this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus.before);
+ }
+ }
+ this.getWeeks(fullDate)
+ }
+
+ /**
+ * 鏇存柊榛樿鍊煎閫夌姸鎬�
+ */
+ setDefaultMultiple(before, after) {
+ this.multipleStatus.before = before
+ this.multipleStatus.after = after
+ if (before && after) {
+ if (dateCompare(before, after)) {
+ this.multipleStatus.data = this.geDateAll(before, after);
+ this.getWeeks(after)
+ } else {
+ this.multipleStatus.data = this.geDateAll(after, before);
+ this.getWeeks(before)
+ }
+ }
+ }
+
+ /**
+ * 鑾峰彇姣忓懆鏁版嵁
+ * @param {Object} dateData
+ */
+ getWeeks(dateData) {
+ const {
+ year,
+ month,
+ } = this.getDateObj(dateData)
+
+ const preMonthDayAmount = new Date(year, month - 1, 1).getDay()
+ const preMonthDays = this.getPreMonthDays(preMonthDayAmount, this.getDateObj(dateData))
+
+ const currentMonthDayAmount = new Date(year, month, 0).getDate()
+ const currentMonthDays = this.getCurrentMonthDays(currentMonthDayAmount, this.getDateObj(dateData))
+
+ const nextMonthDayAmount = 42 - preMonthDayAmount - currentMonthDayAmount
+ const nextMonthDays = this._getNextMonthDays(nextMonthDayAmount, this.getDateObj(dateData))
+
+ const calendarDays = [...preMonthDays, ...currentMonthDays, ...nextMonthDays]
+
+ const weeks = new Array(6)
+ for (let i = 0; i < calendarDays.length; i++) {
+ const index = Math.floor(i / 7)
+ if(!weeks[index]){
+ weeks[index] = new Array(7)
+ }
+ weeks[index][i % 7] = calendarDays[i]
+ }
+
+ this.calendar = calendarDays
+ this.weeks = weeks
+ }
+}
+
+function getDateTime(date, hideSecond){
+ return `${getDate(date)} ${getTime(date, hideSecond)}`
+}
+
+function getDate(date) {
+ date = fixIosDateFormat(date)
+ date = new Date(date)
+ const year = date.getFullYear()
+ const month = date.getMonth()+1
+ const day = date.getDate()
+ return `${year}-${addZero(month)}-${addZero(day)}`
+}
+
+function getTime(date, hideSecond){
+ date = fixIosDateFormat(date)
+ date = new Date(date)
+ const hour = date.getHours()
+ const minute = date.getMinutes()
+ const second = date.getSeconds()
+ return hideSecond ? `${addZero(hour)}:${addZero(minute)}` : `${addZero(hour)}:${addZero(minute)}:${addZero(second)}`
+}
+
+function addZero(num) {
+ if(num < 10){
+ num = `0${num}`
+ }
+ return num
+}
+
+function getDefaultSecond(hideSecond) {
+ return hideSecond ? '00:00' : '00:00:00'
+}
+
+function dateCompare(startDate, endDate) {
+ startDate = new Date(fixIosDateFormat(startDate))
+ endDate = new Date(fixIosDateFormat(endDate))
+ return startDate <= endDate
+}
+
+function checkDate(date){
+ const dateReg = /((19|20)\d{2})(-|\/)\d{1,2}(-|\/)\d{1,2}/g
+ return date.match(dateReg)
+}
+
+const dateTimeReg = /^\d{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])( [0-5][0-9]:[0-5][0-9]:[0-5][0-9])?$/
+function fixIosDateFormat(value) {
+ if (typeof value === 'string' && dateTimeReg.test(value)) {
+ value = value.replace(/-/g, '/')
+ }
+ return value
+}
+
+export {Calendar, getDateTime, getDate, getTime, addZero, getDefaultSecond, dateCompare, checkDate, fixIosDateFormat}
\ No newline at end of file
diff --git a/app/uni_modules/uni-datetime-picker/package.json b/app/uni_modules/uni-datetime-picker/package.json
new file mode 100644
index 0000000..8abed63
--- /dev/null
+++ b/app/uni_modules/uni-datetime-picker/package.json
@@ -0,0 +1,87 @@
+{
+ "id": "uni-datetime-picker",
+ "displayName": "uni-datetime-picker 鏃ユ湡閫夋嫨鍣�",
+ "version": "2.2.22",
+ "description": "uni-datetime-picker 鏃ユ湡鏃堕棿閫夋嫨鍣紝鏀寔鏃ュ巻锛屾敮鎸佽寖鍥撮�夋嫨",
+ "keywords": [
+ "uni-datetime-picker",
+ "uni-ui",
+ "uniui",
+ "鏃ユ湡鏃堕棿閫夋嫨鍣�",
+ "鏃ユ湡鏃堕棿"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+"dcloudext": {
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+ "type": "component-vue"
+ },
+ "uni_modules": {
+ "dependencies": [
+ "uni-scss",
+ "uni-icons"
+ ],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "n"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "u",
+ "鑱旂洘": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
diff --git a/app/uni_modules/uni-datetime-picker/readme.md b/app/uni_modules/uni-datetime-picker/readme.md
new file mode 100644
index 0000000..162fbef
--- /dev/null
+++ b/app/uni_modules/uni-datetime-picker/readme.md
@@ -0,0 +1,21 @@
+
+
+> `閲嶈閫氱煡锛氱粍浠跺崌绾ф洿鏂� 2.0.0 鍚庯紝鏀寔鏃ユ湡+鏃堕棿鑼冨洿閫夋嫨锛岀粍浠� ui 灏嗕娇鐢ㄦ棩鍘嗛�夋嫨鏃ユ湡锛寀i 鍙樺寲杈冨ぇ锛屽悓鏃舵敮鎸� PC 鍜� 绉诲姩绔�傛鐗堟湰涓嶅悜鍚庡吋瀹癸紝涓嶅啀鏀寔鍗曠嫭鐨勬椂闂撮�夋嫨锛坱ype=time锛夊強鐩稿叧鐨� hide-second 灞炴�э紙鏃堕棿閫夊彲浣跨敤鍐呯疆缁勪欢 picker锛夈�傝嫢浠嶉渶浣跨敤鏃х増鏈紝鍙湪鎻掍欢甯傚満涓嬭浇*闈瀠ni_modules鐗堟湰*锛屾棫鐗堟湰灏嗕笉鍐嶇淮鎶
+
+## DatetimePicker 鏃堕棿閫夋嫨鍣�
+
+> **缁勪欢鍚嶏細uni-datetime-picker**
+> 浠g爜鍧楋細 `uDatetimePicker`
+
+
+璇ョ粍浠剁殑浼樺娍鏄紝鏀寔**鏃堕棿鎴�**杈撳叆鍜岃緭鍑猴紙璧峰鏃堕棿銆佺粓姝㈡椂闂翠篃鏀寔鏃堕棿鎴筹級锛屽彲**鍚屾椂閫夋嫨**鏃ユ湡鍜屾椂闂淬��
+
+鑻ュ彧鏄渶瑕佸崟鐙�夋嫨鏃ユ湡鍜屾椂闂达紝涓嶉渶瑕佹椂闂存埑杈撳叆鍜岃緭鍑猴紝鍙娇鐢ㄥ師鐢熺殑 picker 缁勪欢銆�
+
+**_鐐瑰嚮 picker 榛樿鍊艰鍒欙細_**
+
+- 鑻ヨ缃垵濮嬪�� value, 浼氭樉绀哄湪 picker 鏄剧ず妗嗕腑
+- 鑻ユ棤鍒濆鍊� value锛屽垯鍒濆鍊� value 涓哄綋鍓嶆湰鍦版椂闂� Date.now()锛� 浣嗕笉浼氭樉绀哄湪 picker 鏄剧ず妗嗕腑
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-datetime-picker)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
\ No newline at end of file
diff --git a/app/uni_modules/uni-drawer/changelog.md b/app/uni_modules/uni-drawer/changelog.md
new file mode 100644
index 0000000..6d2488c
--- /dev/null
+++ b/app/uni_modules/uni-drawer/changelog.md
@@ -0,0 +1,13 @@
+## 1.2.1锛�2021-11-22锛�
+- 淇 vue3涓釜鍒玸css鍙橀噺鏃犳硶鎵惧埌鐨勯棶棰�
+## 1.2.0锛�2021-11-19锛�
+- 浼樺寲 缁勪欢UI锛屽苟鎻愪緵璁捐璧勬簮锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 鏂囨。杩佺Щ锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/uni-drawer](https://uniapp.dcloud.io/component/uniui/uni-drawer)
+## 1.1.1锛�2021-07-30锛�
+- 浼樺寲 vue3涓嬩簨浠惰鍛婄殑闂
+## 1.1.0锛�2021-07-13锛�
+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤簐ue3椤圭洰锛岃瑙� [uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+## 1.0.7锛�2021-05-12锛�
+- 鏂板 缁勪欢绀轰緥鍦板潃
+## 1.0.6锛�2021-02-04锛�
+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
diff --git a/app/uni_modules/uni-drawer/components/uni-drawer/keypress.js b/app/uni_modules/uni-drawer/components/uni-drawer/keypress.js
new file mode 100644
index 0000000..62dda46
--- /dev/null
+++ b/app/uni_modules/uni-drawer/components/uni-drawer/keypress.js
@@ -0,0 +1,45 @@
+// #ifdef H5
+export default {
+ name: 'Keypress',
+ props: {
+ disable: {
+ type: Boolean,
+ default: false
+ }
+ },
+ mounted () {
+ const keyNames = {
+ esc: ['Esc', 'Escape'],
+ tab: 'Tab',
+ enter: 'Enter',
+ space: [' ', 'Spacebar'],
+ up: ['Up', 'ArrowUp'],
+ left: ['Left', 'ArrowLeft'],
+ right: ['Right', 'ArrowRight'],
+ down: ['Down', 'ArrowDown'],
+ delete: ['Backspace', 'Delete', 'Del']
+ }
+ const listener = ($event) => {
+ if (this.disable) {
+ return
+ }
+ const keyName = Object.keys(keyNames).find(key => {
+ const keyName = $event.key
+ const value = keyNames[key]
+ return value === keyName || (Array.isArray(value) && value.includes(keyName))
+ })
+ if (keyName) {
+ // 閬垮厤鍜屽叾浠栨寜閿簨浠跺啿绐�
+ setTimeout(() => {
+ this.$emit(keyName, {})
+ }, 0)
+ }
+ }
+ document.addEventListener('keyup', listener)
+ // this.$once('hook:beforeDestroy', () => {
+ // document.removeEventListener('keyup', listener)
+ // })
+ },
+ render: () => {}
+}
+// #endif
diff --git a/app/uni_modules/uni-drawer/components/uni-drawer/uni-drawer.vue b/app/uni_modules/uni-drawer/components/uni-drawer/uni-drawer.vue
new file mode 100644
index 0000000..82331a8
--- /dev/null
+++ b/app/uni_modules/uni-drawer/components/uni-drawer/uni-drawer.vue
@@ -0,0 +1,183 @@
+<template>
+ <view v-if="visibleSync" :class="{ 'uni-drawer--visible': showDrawer }" class="uni-drawer" @touchmove.stop.prevent="clear">
+ <view class="uni-drawer__mask" :class="{ 'uni-drawer__mask--visible': showDrawer && mask }" @tap="close('mask')" />
+ <view class="uni-drawer__content" :class="{'uni-drawer--right': rightMode,'uni-drawer--left': !rightMode, 'uni-drawer__content--visible': showDrawer}" :style="{width:drawerWidth+'px'}">
+ <slot />
+ </view>
+ <!-- #ifdef H5 -->
+ <keypress @esc="close('mask')" />
+ <!-- #endif -->
+ </view>
+</template>
+
+<script>
+ // #ifdef H5
+ import keypress from './keypress.js'
+ // #endif
+ /**
+ * Drawer 鎶藉眽
+ * @description 鎶藉眽渚ф粦鑿滃崟
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=26
+ * @property {Boolean} mask = [true | false] 鏄惁鏄剧ず閬僵
+ * @property {Boolean} maskClick = [true | false] 鐐瑰嚮閬僵鏄惁鍏抽棴
+ * @property {Boolean} mode = [left | right] Drawer 婊戝嚭浣嶇疆
+ * @value left 浠庡乏渚ф粦鍑�
+ * @value right 浠庡彸渚т晶婊戝嚭
+ * @property {Number} width 鎶藉眽鐨勫搴� 锛屼粎 vue 椤甸潰鐢熸晥
+ * @event {Function} close 缁勪欢鍏抽棴鏃惰Е鍙戜簨浠�
+ */
+ export default {
+ name: 'UniDrawer',
+ components: {
+ // #ifdef H5
+ keypress
+ // #endif
+ },
+ emits:['change'],
+ props: {
+ /**
+ * 鏄剧ず妯″紡锛堝乏銆佸彸锛夛紝鍙湪鍒濆鍖栫敓鏁�
+ */
+ mode: {
+ type: String,
+ default: ''
+ },
+ /**
+ * 钂欏眰鏄剧ず鐘舵��
+ */
+ mask: {
+ type: Boolean,
+ default: true
+ },
+ /**
+ * 閬僵鏄惁鍙偣鍑诲叧闂�
+ */
+ maskClick:{
+ type: Boolean,
+ default: true
+ },
+ /**
+ * 鎶藉眽瀹藉害
+ */
+ width: {
+ type: Number,
+ default: 220
+ }
+ },
+ data() {
+ return {
+ visibleSync: false,
+ showDrawer: false,
+ rightMode: false,
+ watchTimer: null,
+ drawerWidth: 220
+ }
+ },
+ created() {
+ // #ifndef APP-NVUE
+ this.drawerWidth = this.width
+ // #endif
+ this.rightMode = this.mode === 'right'
+ },
+ methods: {
+ clear(){},
+ close(type) {
+ // fixed by mehaotian 鎶藉眽灏氭湭瀹屽叏鍏抽棴鎴栭伄缃╃姝㈢偣鍑绘椂涓嶈Е鍙戜互涓嬮�昏緫
+ if((type === 'mask' && !this.maskClick) || !this.visibleSync) return
+ this._change('showDrawer', 'visibleSync', false)
+ },
+ open() {
+ // fixed by mehaotian 澶勭悊閲嶅鐐瑰嚮鎵撳紑鐨勪簨浠�
+ if(this.visibleSync) return
+ this._change('visibleSync', 'showDrawer', true)
+ },
+ _change(param1, param2, status) {
+ this[param1] = status
+ if (this.watchTimer) {
+ clearTimeout(this.watchTimer)
+ }
+ this.watchTimer = setTimeout(() => {
+ this[param2] = status
+ this.$emit('change',status)
+ }, status ? 50 : 300)
+ }
+ }
+ }
+</script>
+
+<style lang="scss" >
+ $uni-mask: rgba($color: #000000, $alpha: 0.4) ;
+ // 鎶藉眽瀹藉害
+ $drawer-width: 220px;
+
+ .uni-drawer {
+ /* #ifndef APP-NVUE */
+ display: block;
+ /* #endif */
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ overflow: hidden;
+ z-index: 999;
+ }
+
+ .uni-drawer__content {
+ /* #ifndef APP-NVUE */
+ display: block;
+ /* #endif */
+ position: absolute;
+ top: 0;
+ width: $drawer-width;
+ bottom: 0;
+ background-color: $uni-bg-color;
+ transition: transform 0.3s ease;
+ }
+
+ .uni-drawer--left {
+ left: 0;
+ /* #ifdef APP-NVUE */
+ transform: translateX(-$drawer-width);
+ /* #endif */
+ /* #ifndef APP-NVUE */
+ transform: translateX(-100%);
+ /* #endif */
+ }
+
+ .uni-drawer--right {
+ right: 0;
+ /* #ifdef APP-NVUE */
+ transform: translateX($drawer-width);
+ /* #endif */
+ /* #ifndef APP-NVUE */
+ transform: translateX(100%);
+ /* #endif */
+ }
+
+ .uni-drawer__content--visible {
+ transform: translateX(0px);
+ }
+
+
+ .uni-drawer__mask {
+ /* #ifndef APP-NVUE */
+ display: block;
+ /* #endif */
+ opacity: 0;
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+ background-color: $uni-mask;
+ transition: opacity 0.3s;
+ }
+
+ .uni-drawer__mask--visible {
+ /* #ifndef APP-NVUE */
+ display: block;
+ /* #endif */
+ opacity: 1;
+ }
+</style>
diff --git a/app/uni_modules/uni-drawer/package.json b/app/uni_modules/uni-drawer/package.json
new file mode 100644
index 0000000..dd056e4
--- /dev/null
+++ b/app/uni_modules/uni-drawer/package.json
@@ -0,0 +1,87 @@
+{
+ "id": "uni-drawer",
+ "displayName": "uni-drawer 鎶藉眽",
+ "version": "1.2.1",
+ "description": "鎶藉眽寮忓鑸紝鐢ㄤ簬灞曠ず渚ф粦鑿滃崟锛屼晶婊戝鑸��",
+ "keywords": [
+ "uni-ui",
+ "uniui",
+ "drawer",
+ "鎶藉眽",
+ "渚ф粦瀵艰埅"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "鍓嶇缁勪欢",
+ "閫氱敤缁勪欢"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": ["uni-scss"],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "u",
+ "鑱旂洘": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/uni_modules/uni-drawer/readme.md b/app/uni_modules/uni-drawer/readme.md
new file mode 100644
index 0000000..dcf6e6b
--- /dev/null
+++ b/app/uni_modules/uni-drawer/readme.md
@@ -0,0 +1,10 @@
+
+
+## Drawer 鎶藉眽
+> **缁勪欢鍚嶏細uni-drawer**
+> 浠g爜鍧楋細 `uDrawer`
+
+鎶藉眽渚ф粦鑿滃崟銆�
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-drawer)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
\ No newline at end of file
diff --git a/app/uni_modules/uni-easyinput/changelog.md b/app/uni_modules/uni-easyinput/changelog.md
new file mode 100644
index 0000000..765401a
--- /dev/null
+++ b/app/uni_modules/uni-easyinput/changelog.md
@@ -0,0 +1,97 @@
+## 1.1.9锛�2023-04-11锛�
+- 淇 vue3 涓� keyboardheightchange 浜嬩欢鎶ラ敊鐨刡ug
+## 1.1.8锛�2023-03-29锛�
+- 浼樺寲 trim 灞炴�ч粯璁ゅ��
+## 1.1.7锛�2023-03-29锛�
+- 鏂板 cursor-spacing 灞炴��
+## 1.1.6锛�2023-01-28锛�
+- 鏂板 keyboardheightchange 浜嬩欢锛屽彲鐩戝惉閿洏楂樺害鍙樺寲
+## 1.1.5锛�2022-11-29锛�
+- 浼樺寲 涓婚鏍峰紡
+## 1.1.4锛�2022-10-27锛�
+- 淇 props 涓儗鏅鑹叉棤榛樿鍊肩殑bug
+## 1.1.0锛�2022-06-30锛�
+
+- 鏂板 鍦� uni-forms 1.4.0 涓娇鐢ㄥ彲浠ュ湪 blur 鏃舵牎楠屽唴瀹�
+- 鏂板 clear 浜嬩欢锛岀偣鍑诲彸渚у弶鍙峰浘鏍囪Е鍙�
+- 鏂板 change 浜嬩欢 锛屼粎鍦ㄨ緭鍏ユ澶卞幓鐒︾偣鎴栫敤鎴锋寜涓嬪洖杞︽椂瑙﹀彂
+- 浼樺寲 缁勪欢鏍峰紡锛岀粍浠惰幏鍙栫劍鐐规椂楂樹寒鏄剧ず锛屽浘鏍囬鑹茶皟鏁寸瓑
+
+## 1.0.5锛�2022-06-07锛�
+
+- 浼樺寲 clearable 鏄剧ず绛栫暐
+
+## 1.0.4锛�2022-06-07锛�
+
+- 浼樺寲 clearable 鏄剧ず绛栫暐
+
+## 1.0.3锛�2022-05-20锛�
+
+- 淇 鍏抽棴鍥炬爣鏌愪簺鎯呭喌涓嬫棤娉曞彇娑堢殑 bug
+
+## 1.0.2锛�2022-04-12锛�
+
+- 淇 榛樿鍊间笉鐢熸晥鐨� bug
+
+## 1.0.1锛�2022-04-02锛�
+
+- 淇 value 涓嶈兘涓� 0 鐨� bug
+
+## 1.0.0锛�2021-11-19锛�
+
+- 浼樺寲 缁勪欢 UI锛屽苟鎻愪緵璁捐璧勬簮锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 鏂囨。杩佺Щ锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/uni-easyinput](https://uniapp.dcloud.io/component/uniui/uni-easyinput)
+
+## 0.1.4锛�2021-08-20锛�
+
+- 淇 鍦� uni-forms 鐨勫姩鎬佽〃鍗曚腑榛樿鍊兼牎楠屼笉閫氳繃鐨� bug
+
+## 0.1.3锛�2021-08-11锛�
+
+- 淇 鍦� uni-forms 涓噸缃〃鍗曪紝閿欒淇℃伅鏃犳硶娓呴櫎鐨勯棶棰�
+
+## 0.1.2锛�2021-07-30锛�
+
+- 浼樺寲 vue3 涓嬩簨浠惰鍛婄殑闂
+
+## 0.1.1
+
+- 浼樺寲 errorMessage 灞炴�ф敮鎸� Boolean 绫诲瀷
+
+## 0.1.0锛�2021-07-13锛�
+
+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤� vue3 椤圭洰锛岃瑙� [uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+
+## 0.0.16锛�2021-06-29锛�
+
+- 淇 confirmType 灞炴�э紙浠� type="text" 鐢熸晥锛夊鑷村琛屾枃鏈鏃犳硶鎹㈣鐨� bug
+
+## 0.0.15锛�2021-06-21锛�
+
+- 淇 passwordIcon 灞炴�ф嫾鍐欓敊璇殑 bug
+
+## 0.0.14锛�2021-06-18锛�
+
+- 鏂板 passwordIcon 灞炴�э紝褰� type=password 鏃舵槸鍚︽樉绀哄皬鐪肩潧鍥炬爣
+- 淇 confirmType 灞炴�т笉鐢熸晥鐨勯棶棰�
+
+## 0.0.13锛�2021-06-04锛�
+
+- 淇 disabled 鐘舵�佸彲娓呭嚭鍐呭鐨� bug
+
+## 0.0.12锛�2021-05-12锛�
+
+- 鏂板 缁勪欢绀轰緥鍦板潃
+
+## 0.0.11锛�2021-05-07锛�
+
+- 淇 input-border 灞炴�т笉鐢熸晥鐨勯棶棰�
+
+## 0.0.10锛�2021-04-30锛�
+
+- 淇 ios 閬尅鏂囧瓧銆佹樉绀轰竴鍗婄殑闂
+
+## 0.0.9锛�2021-02-05锛�
+
+- 璋冩暣涓� uni_modules 鐩綍瑙勮寖
+- 浼樺寲 鍏煎 nvue 椤甸潰
diff --git a/app/uni_modules/uni-easyinput/components/uni-easyinput/common.js b/app/uni_modules/uni-easyinput/components/uni-easyinput/common.js
new file mode 100644
index 0000000..df9abe1
--- /dev/null
+++ b/app/uni_modules/uni-easyinput/components/uni-easyinput/common.js
@@ -0,0 +1,56 @@
+/**
+ * @desc 鍑芥暟闃叉姈
+ * @param func 鐩爣鍑芥暟
+ * @param wait 寤惰繜鎵ц姣鏁�
+ * @param immediate true - 绔嬪嵆鎵ц锛� false - 寤惰繜鎵ц
+ */
+export const debounce = function(func, wait = 1000, immediate = true) {
+ let timer;
+ console.log(1);
+ return function() {
+ console.log(123);
+ let context = this,
+ args = arguments;
+ if (timer) clearTimeout(timer);
+ if (immediate) {
+ let callNow = !timer;
+ timer = setTimeout(() => {
+ timer = null;
+ }, wait);
+ if (callNow) func.apply(context, args);
+ } else {
+ timer = setTimeout(() => {
+ func.apply(context, args);
+ }, wait)
+ }
+ }
+}
+/**
+ * @desc 鍑芥暟鑺傛祦
+ * @param func 鍑芥暟
+ * @param wait 寤惰繜鎵ц姣鏁�
+ * @param type 1 浣跨敤琛ㄦ椂闂存埑锛屽湪鏃堕棿娈靛紑濮嬬殑鏃跺�欒Е鍙� 2 浣跨敤琛ㄥ畾鏃跺櫒锛屽湪鏃堕棿娈电粨鏉熺殑鏃跺�欒Е鍙�
+ */
+export const throttle = (func, wait = 1000, type = 1) => {
+ let previous = 0;
+ let timeout;
+ return function() {
+ let context = this;
+ let args = arguments;
+ if (type === 1) {
+ let now = Date.now();
+
+ if (now - previous > wait) {
+ func.apply(context, args);
+ previous = now;
+ }
+ } else if (type === 2) {
+ if (!timeout) {
+ timeout = setTimeout(() => {
+ timeout = null;
+ func.apply(context, args)
+ }, wait)
+ }
+ }
+ }
+}
diff --git a/app/uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue b/app/uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue
new file mode 100644
index 0000000..2c7993a
--- /dev/null
+++ b/app/uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue
@@ -0,0 +1,657 @@
+<template>
+ <view class="uni-easyinput" :class="{ 'uni-easyinput-error': msg }" :style="boxStyle">
+ <view class="uni-easyinput__content" :class="inputContentClass" :style="inputContentStyle">
+ <uni-icons v-if="prefixIcon" class="content-clear-icon" :type="prefixIcon" color="#c0c4cc" @click="onClickIcon('prefix')" size="22"></uni-icons>
+ <textarea
+ v-if="type === 'textarea'"
+ class="uni-easyinput__content-textarea"
+ :class="{ 'input-padding': inputBorder }"
+ :name="name"
+ :value="val"
+ :placeholder="placeholder"
+ :placeholderStyle="placeholderStyle"
+ :disabled="disabled"
+ placeholder-class="uni-easyinput__placeholder-class"
+ :maxlength="inputMaxlength"
+ :focus="focused"
+ :autoHeight="autoHeight"
+ :cursor-spacing="cursorSpacing"
+ @input="onInput"
+ @blur="_Blur"
+ @focus="_Focus"
+ @confirm="onConfirm"
+ @keyboardheightchange="onkeyboardheightchange"
+ ></textarea>
+ <input
+ v-else
+ :type="type === 'password' ? 'text' : type"
+ class="uni-easyinput__content-input"
+ :style="inputStyle"
+ :name="name"
+ :value="val"
+ :password="!showPassword && type === 'password'"
+ :placeholder="placeholder"
+ :placeholderStyle="placeholderStyle"
+ placeholder-class="uni-easyinput__placeholder-class"
+ :disabled="disabled"
+ :maxlength="inputMaxlength"
+ :focus="focused"
+ :confirmType="confirmType"
+ :cursor-spacing="cursorSpacing"
+ @focus="_Focus"
+ @blur="_Blur"
+ @input="onInput"
+ @confirm="onConfirm"
+ @keyboardheightchange="onkeyboardheightchange"
+ />
+ <template v-if="type === 'password' && passwordIcon">
+ <!-- 寮�鍚瘑鐮佹椂鏄剧ず灏忕溂鐫� -->
+ <uni-icons
+ v-if="isVal"
+ class="content-clear-icon"
+ :class="{ 'is-textarea-icon': type === 'textarea' }"
+ :type="showPassword ? 'eye-slash-filled' : 'eye-filled'"
+ :size="22"
+ :color="focusShow ? primaryColor : '#c0c4cc'"
+ @click="onEyes"
+ ></uni-icons>
+ </template>
+ <template v-else-if="suffixIcon">
+ <uni-icons v-if="suffixIcon" class="content-clear-icon" :type="suffixIcon" color="#c0c4cc" @click="onClickIcon('suffix')" size="22"></uni-icons>
+ </template>
+ <template v-else>
+ <uni-icons
+ v-if="clearable && isVal && !disabled && type !== 'textarea'"
+ class="content-clear-icon"
+ :class="{ 'is-textarea-icon': type === 'textarea' }"
+ type="clear"
+ :size="clearSize"
+ :color="msg ? '#dd524d' : focusShow ? primaryColor : '#c0c4cc'"
+ @click="onClear"
+ ></uni-icons>
+ </template>
+ <slot name="right"></slot>
+ </view>
+ </view>
+</template>
+
+<script>
+/**
+ * Easyinput 杈撳叆妗�
+ * @description 姝ょ粍浠跺彲浠ュ疄鐜拌〃鍗曠殑杈撳叆涓庢牎楠岋紝鍖呮嫭 "text" 鍜� "textarea" 绫诲瀷銆�
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=3455
+ * @property {String} value 杈撳叆鍐呭
+ * @property {String } type 杈撳叆妗嗙殑绫诲瀷锛堥粯璁ext锛� password/text/textarea/..
+ * @value text 鏂囨湰杈撳叆閿洏
+ * @value textarea 澶氳鏂囨湰杈撳叆閿洏
+ * @value password 瀵嗙爜杈撳叆閿洏
+ * @value number 鏁板瓧杈撳叆閿洏锛屾敞鎰廼OS涓奱pp-vue寮瑰嚭鐨勬暟瀛楅敭鐩樺苟闈�9瀹牸鏂瑰紡
+ * @value idcard 韬唤璇佽緭鍏ラ敭鐩橈紝淇°�佹敮浠樺疂銆佺櫨搴︺�丵Q灏忕▼搴�
+ * @value digit 甯﹀皬鏁扮偣鐨勬暟瀛楅敭鐩� 锛孉pp鐨刵vue椤甸潰銆佸井淇°�佹敮浠樺疂銆佺櫨搴︺�佸ご鏉°�丵Q灏忕▼搴忔敮鎸�
+ * @property {Boolean} clearable 鏄惁鏄剧ず鍙充晶娓呯┖鍐呭鐨勫浘鏍囨帶浠讹紝鐐瑰嚮鍙竻绌鸿緭鍏ユ鍐呭锛堥粯璁rue锛�
+ * @property {Boolean} autoHeight 鏄惁鑷姩澧為珮杈撳叆鍖哄煙锛宼ype涓簍extarea鏃舵湁鏁堬紙榛樿true锛�
+ * @property {String } placeholder 杈撳叆妗嗙殑鎻愮ず鏂囧瓧
+ * @property {String } placeholderStyle placeholder鐨勬牱寮�(鍐呰仈鏍峰紡锛屽瓧绗︿覆)锛屽"color: #ddd"
+ * @property {Boolean} focus 鏄惁鑷姩鑾峰緱鐒︾偣锛堥粯璁alse锛�
+ * @property {Boolean} disabled 鏄惁绂佺敤锛堥粯璁alse锛�
+ * @property {Number } maxlength 鏈�澶ц緭鍏ラ暱搴︼紝璁剧疆涓� -1 鐨勬椂鍊欎笉闄愬埗鏈�澶ч暱搴︼紙榛樿140锛�
+ * @property {String } confirmType 璁剧疆閿洏鍙充笅瑙掓寜閽殑鏂囧瓧锛屼粎鍦╰ype="text"鏃剁敓鏁堬紙榛樿done锛�
+ * @property {Number } clearSize 娓呴櫎鍥炬爣鐨勫ぇ灏忥紝鍗曚綅px锛堥粯璁�15锛�
+ * @property {String} prefixIcon 杈撳叆妗嗗ご閮ㄥ浘鏍�
+ * @property {String} suffixIcon 杈撳叆妗嗗熬閮ㄥ浘鏍�
+ * @property {String} primaryColor 璁剧疆涓婚鑹诧紙榛樿#2979ff锛�
+ * @property {Boolean} trim 鏄惁鑷姩鍘婚櫎涓ょ鐨勭┖鏍�
+ * @property {Boolean} cursorSpacing 鎸囧畾鍏夋爣涓庨敭鐩樼殑璺濈锛屽崟浣� px
+ * @value both 鍘婚櫎涓ょ绌烘牸
+ * @value left 鍘婚櫎宸︿晶绌烘牸
+ * @value right 鍘婚櫎鍙充晶绌烘牸
+ * @value start 鍘婚櫎宸︿晶绌烘牸
+ * @value end 鍘婚櫎鍙充晶绌烘牸
+ * @value all 鍘婚櫎鍏ㄩ儴绌烘牸
+ * @value none 涓嶅幓闄ょ┖鏍�
+ * @property {Boolean} inputBorder 鏄惁鏄剧ずinput杈撳叆妗嗙殑杈规锛堥粯璁rue锛�
+ * @property {Boolean} passwordIcon type=password鏃舵槸鍚︽樉绀哄皬鐪肩潧鍥炬爣
+ * @property {Object} styles 鑷畾涔夐鑹�
+ * @event {Function} input 杈撳叆妗嗗唴瀹瑰彂鐢熷彉鍖栨椂瑙﹀彂
+ * @event {Function} focus 杈撳叆妗嗚幏寰楃劍鐐规椂瑙﹀彂
+ * @event {Function} blur 杈撳叆妗嗗け鍘荤劍鐐规椂瑙﹀彂
+ * @event {Function} confirm 鐐瑰嚮瀹屾垚鎸夐挳鏃惰Е鍙�
+ * @event {Function} iconClick 鐐瑰嚮鍥炬爣鏃惰Е鍙�
+ * @example <uni-easyinput v-model="mobile"></uni-easyinput>
+ */
+function obj2strClass(obj) {
+ let classess = '';
+ for (let key in obj) {
+ const val = obj[key];
+ if (val) {
+ classess += `${key} `;
+ }
+ }
+ return classess;
+}
+
+function obj2strStyle(obj) {
+ let style = '';
+ for (let key in obj) {
+ const val = obj[key];
+ style += `${key}:${val};`;
+ }
+ return style;
+}
+export default {
+ name: 'uni-easyinput',
+ emits: ['click', 'iconClick', 'update:modelValue', 'input', 'focus', 'blur', 'confirm', 'clear', 'eyes', 'change', 'keyboardheightchange'],
+ model: {
+ prop: 'modelValue',
+ event: 'update:modelValue'
+ },
+ options: {
+ virtualHost: true
+ },
+ inject: {
+ form: {
+ from: 'uniForm',
+ default: null
+ },
+ formItem: {
+ from: 'uniFormItem',
+ default: null
+ }
+ },
+ props: {
+ name: String,
+ value: [Number, String],
+ modelValue: [Number, String],
+ type: {
+ type: String,
+ default: 'text'
+ },
+ clearable: {
+ type: Boolean,
+ default: true
+ },
+ autoHeight: {
+ type: Boolean,
+ default: false
+ },
+ placeholder: {
+ type: String,
+ default: ' '
+ },
+ placeholderStyle: String,
+ focus: {
+ type: Boolean,
+ default: false
+ },
+ disabled: {
+ type: Boolean,
+ default: false
+ },
+ maxlength: {
+ type: [Number, String],
+ default: 140
+ },
+ confirmType: {
+ type: String,
+ default: 'done'
+ },
+ clearSize: {
+ type: [Number, String],
+ default: 24
+ },
+ inputBorder: {
+ type: Boolean,
+ default: true
+ },
+ prefixIcon: {
+ type: String,
+ default: ''
+ },
+ suffixIcon: {
+ type: String,
+ default: ''
+ },
+ trim: {
+ type: [Boolean, String],
+ default: false
+ },
+ cursorSpacing: {
+ type: Number,
+ default: 0
+ },
+ passwordIcon: {
+ type: Boolean,
+ default: true
+ },
+ primaryColor: {
+ type: String,
+ default: '#2979ff'
+ },
+ styles: {
+ type: Object,
+ default() {
+ return {
+ color: '#333',
+ backgroundColor: '#fff',
+ disableColor: '#F7F6F6',
+ borderColor: '#e5e5e5'
+ };
+ }
+ },
+ errorMessage: {
+ type: [String, Boolean],
+ default: ''
+ }
+ },
+ data() {
+ return {
+ focused: false,
+ val: '',
+ showMsg: '',
+ border: false,
+ isFirstBorder: false,
+ showClearIcon: false,
+ showPassword: false,
+ focusShow: false,
+ localMsg: '',
+ isEnter: false // 鐢ㄤ簬鍒ゆ柇褰撳墠鏄惁鏄娇鐢ㄥ洖杞︽搷浣�
+ };
+ },
+ computed: {
+ // 杈撳叆妗嗗唴鏄惁鏈夊��
+ isVal() {
+ const val = this.val;
+ // fixed by mehaotian 澶勭悊鍊间负0鐨勬儏鍐碉紝瀛楃涓�0涓嶅湪澶勭悊鑼冨洿
+ if (val || val === 0) {
+ return true;
+ }
+ return false;
+ },
+
+ msg() {
+ // console.log('computed', this.form, this.formItem);
+ // if (this.form) {
+ // return this.errorMessage || this.formItem.errMsg;
+ // }
+ // TODO 澶勭悊澶存潯 formItem 涓� errMsg 涓嶆洿鏂扮殑闂
+ return this.localMsg || this.errorMessage;
+ },
+ // 鍥犱负uniapp鐨刬nput缁勪欢鐨刴axlength缁勪欢蹇呴』瑕佹暟鍊硷紝杩欓噷杞负鏁板�硷紝鐢ㄦ埛鍙互浼犲叆瀛楃涓叉暟鍊�
+ inputMaxlength() {
+ return Number(this.maxlength);
+ },
+
+ // 澶勭悊澶栧眰鏍峰紡鐨剆tyle
+ boxStyle() {
+ return `color:${this.inputBorder && this.msg ? '#e43d33' : this.styles.color};`;
+ },
+ // input 鍐呭鐨勭被鍜屾牱寮忓鐞�
+ inputContentClass() {
+ return obj2strClass({
+ 'is-input-border': this.inputBorder,
+ 'is-input-error-border': this.inputBorder && this.msg,
+ 'is-textarea': this.type === 'textarea',
+ 'is-disabled': this.disabled,
+ 'is-focused': this.focusShow
+ });
+ },
+ inputContentStyle() {
+ const focusColor = this.focusShow ? this.primaryColor : this.styles.borderColor;
+ const borderColor = this.inputBorder && this.msg ? '#dd524d' : focusColor;
+ return obj2strStyle({
+ 'border-color': borderColor || '#e5e5e5',
+ 'background-color': this.disabled ? this.styles.disableColor : this.styles.backgroundColor
+ });
+ },
+ // input鍙充晶鏍峰紡
+ inputStyle() {
+ const paddingRight = this.type === 'password' || this.clearable || this.prefixIcon ? '' : '10px';
+ return obj2strStyle({
+ 'padding-right': paddingRight,
+ 'padding-left': this.prefixIcon ? '' : '10px'
+ });
+ }
+ },
+ watch: {
+ value(newVal) {
+ this.val = newVal;
+ },
+ modelValue(newVal) {
+ this.val = newVal;
+ },
+ focus(newVal) {
+ this.$nextTick(() => {
+ this.focused = this.focus;
+ this.focusShow = this.focus;
+ });
+ }
+ },
+ created() {
+ this.init();
+ // TODO 澶勭悊澶存潯vue3 computed 涓嶇洃鍚� inject 鏇存敼鐨勯棶棰橈紙formItem.errMsg锛�
+ if (this.form && this.formItem) {
+ this.$watch('formItem.errMsg', newVal => {
+ this.localMsg = newVal;
+ });
+ }
+ },
+ mounted() {
+ this.$nextTick(() => {
+ this.focused = this.focus;
+ this.focusShow = this.focus;
+ });
+ },
+ methods: {
+ /**
+ * 鍒濆鍖栧彉閲忓��
+ */
+ init() {
+ if (this.value || this.value === 0) {
+ this.val = this.value;
+ } else if (this.modelValue || this.modelValue === 0 || this.modelValue === '') {
+ this.val = this.modelValue;
+ } else {
+ this.val = null;
+ }
+ },
+
+ /**
+ * 鐐瑰嚮鍥炬爣鏃惰Е鍙�
+ * @param {Object} type
+ */
+ onClickIcon(type) {
+ this.$emit('iconClick', type);
+ },
+
+ /**
+ * 鏄剧ず闅愯棌鍐呭锛屽瘑鐮佹鏃剁敓鏁�
+ */
+ onEyes() {
+ this.showPassword = !this.showPassword;
+ this.$emit('eyes', this.showPassword);
+ },
+
+ /**
+ * 杈撳叆鏃惰Е鍙�
+ * @param {Object} event
+ */
+ onInput(event) {
+ let value = event.detail.value;
+ // 鍒ゆ柇鏄惁鍘婚櫎绌烘牸
+ if (this.trim) {
+ if (typeof this.trim === 'boolean' && this.trim) {
+ value = this.trimStr(value);
+ }
+ if (typeof this.trim === 'string') {
+ value = this.trimStr(value, this.trim);
+ }
+ }
+ if (this.errMsg) this.errMsg = '';
+ this.val = value;
+ // TODO 鍏煎 vue2
+ this.$emit('input', value);
+ // TODO銆�鍏煎銆�vue3
+ this.$emit('update:modelValue', value);
+ },
+
+ /**
+ * 澶栭儴璋冪敤鏂规硶
+ * 鑾峰彇鐒︾偣鏃惰Е鍙�
+ * @param {Object} event
+ */
+ onFocus() {
+ this.$nextTick(() => {
+ this.focused = true;
+ });
+ this.$emit('focus', null);
+ },
+
+ _Focus(event) {
+ this.focusShow = true;
+ this.$emit('focus', event);
+ },
+
+ /**
+ * 澶栭儴璋冪敤鏂规硶
+ * 澶卞幓鐒︾偣鏃惰Е鍙�
+ * @param {Object} event
+ */
+ onBlur() {
+ this.focused = false;
+ this.$emit('focus', null);
+ },
+ _Blur(event) {
+ let value = event.detail.value;
+ this.focusShow = false;
+ this.$emit('blur', event);
+ // 鏍规嵁绫诲瀷杩斿洖鍊硷紝鍦╡vent涓幏鍙栫殑鍊肩悊璁轰笂璁查兘鏄痵tring
+ if (this.isEnter === false) {
+ this.$emit('change', this.val);
+ }
+ // 澶卞幓鐒︾偣鏃跺弬涓庤〃鍗曟牎楠�
+ if (this.form && this.formItem) {
+ const { validateTrigger } = this.form;
+ if (validateTrigger === 'blur') {
+ this.formItem.onFieldChange();
+ }
+ }
+ },
+
+ /**
+ * 鎸変笅閿洏鐨勫彂閫侀敭
+ * @param {Object} e
+ */
+ onConfirm(e) {
+ this.$emit('confirm', this.val);
+ this.isEnter = true;
+ this.$emit('change', this.val);
+ this.$nextTick(() => {
+ this.isEnter = false;
+ });
+ },
+
+ /**
+ * 娓呯悊鍐呭
+ * @param {Object} event
+ */
+ onClear(event) {
+ this.val = '';
+ // TODO 鍏煎 vue2
+ this.$emit('input', '');
+ // TODO 鍏煎 vue2
+ // TODO銆�鍏煎銆�vue3
+ this.$emit('update:modelValue', '');
+ // 鐐瑰嚮鍙夊彿瑙﹀彂
+ this.$emit('clear');
+ },
+
+ /**
+ * 閿洏楂樺害鍙戠敓鍙樺寲鐨勬椂鍊欒Е鍙戞浜嬩欢
+ * 鍏煎鎬э細寰俊灏忕▼搴�2.7.0+銆丄pp 3.1.0+
+ * @param {Object} event
+ */
+ onkeyboardheightchange(event) {
+ this.$emit("keyboardheightchange",event);
+ },
+
+ /**
+ * 鍘婚櫎绌烘牸
+ */
+ trimStr(str, pos = 'both') {
+ if (pos === 'both') {
+ return str.trim();
+ } else if (pos === 'left') {
+ return str.trimLeft();
+ } else if (pos === 'right') {
+ return str.trimRight();
+ } else if (pos === 'start') {
+ return str.trimStart();
+ } else if (pos === 'end') {
+ return str.trimEnd();
+ } else if (pos === 'all') {
+ return str.replace(/\s+/g, '');
+ } else if (pos === 'none') {
+ return str;
+ }
+ return str;
+ }
+ }
+};
+</script>
+
+<style lang="scss">
+$uni-error: #e43d33;
+$uni-border-1: #dcdfe6 !default;
+
+.uni-easyinput {
+ /* #ifndef APP-NVUE */
+ width: 100%;
+ /* #endif */
+ flex: 1;
+ position: relative;
+ text-align: left;
+ color: #333;
+ font-size: 14px;
+}
+
+.uni-easyinput__content {
+ flex: 1;
+ /* #ifndef APP-NVUE */
+ width: 100%;
+ display: flex;
+ box-sizing: border-box;
+ // min-height: 36px;
+ /* #endif */
+ flex-direction: row;
+ align-items: center;
+ // 澶勭悊border鍔ㄧ敾鍒氬紑濮嬫樉绀洪粦鑹茬殑闂
+ border-color: #fff;
+ transition-property: border-color;
+ transition-duration: 0.3s;
+}
+
+.uni-easyinput__content-input {
+ /* #ifndef APP-NVUE */
+ width: auto;
+ /* #endif */
+ position: relative;
+ overflow: hidden;
+ flex: 1;
+ line-height: 1;
+ font-size: 14px;
+ height: 35px;
+ // min-height: 36px;
+}
+
+.uni-easyinput__placeholder-class {
+ color: #999;
+ font-size: 12px;
+ // font-weight: 200;
+}
+
+.is-textarea {
+ align-items: flex-start;
+}
+
+.is-textarea-icon {
+ margin-top: 5px;
+}
+
+.uni-easyinput__content-textarea {
+ position: relative;
+ overflow: hidden;
+ flex: 1;
+ line-height: 1.5;
+ font-size: 14px;
+ margin: 6px;
+ margin-left: 0;
+ height: 80px;
+ min-height: 80px;
+ /* #ifndef APP-NVUE */
+ min-height: 80px;
+ width: auto;
+ /* #endif */
+}
+
+.input-padding {
+ padding-left: 10px;
+}
+
+.content-clear-icon {
+ padding: 0 5px;
+}
+
+.label-icon {
+ margin-right: 5px;
+ margin-top: -1px;
+}
+
+// 鏄剧ず杈规
+.is-input-border {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ box-sizing: border-box;
+ /* #endif */
+ flex-direction: row;
+ align-items: center;
+ border: 1px solid $uni-border-1;
+ border-radius: 4px;
+ /* #ifdef MP-ALIPAY */
+ overflow: hidden;
+ /* #endif */
+}
+
+.uni-error-message {
+ position: absolute;
+ bottom: -17px;
+ left: 0;
+ line-height: 12px;
+ color: $uni-error;
+ font-size: 12px;
+ text-align: left;
+}
+
+.uni-error-msg--boeder {
+ position: relative;
+ bottom: 0;
+ line-height: 22px;
+}
+
+.is-input-error-border {
+ border-color: $uni-error;
+
+ .uni-easyinput__placeholder-class {
+ color: mix(#fff, $uni-error, 50%);
+ }
+}
+
+.uni-easyinput--border {
+ margin-bottom: 0;
+ padding: 10px 15px;
+ // padding-bottom: 0;
+ border-top: 1px #eee solid;
+}
+
+.uni-easyinput-error {
+ padding-bottom: 0;
+}
+
+.is-first-border {
+ /* #ifndef APP-NVUE */
+ border: none;
+ /* #endif */
+ /* #ifdef APP-NVUE */
+ border-width: 0;
+ /* #endif */
+}
+
+.is-disabled {
+ background-color: #f7f6f6;
+ color: #d5d5d5;
+
+ .uni-easyinput__placeholder-class {
+ color: #d5d5d5;
+ font-size: 12px;
+ }
+}
+</style>
diff --git a/app/uni_modules/uni-easyinput/package.json b/app/uni_modules/uni-easyinput/package.json
new file mode 100644
index 0000000..bd128e1
--- /dev/null
+++ b/app/uni_modules/uni-easyinput/package.json
@@ -0,0 +1,87 @@
+{
+ "id": "uni-easyinput",
+ "displayName": "uni-easyinput 澧炲己杈撳叆妗�",
+ "version": "1.1.9",
+ "description": "Easyinput 缁勪欢鏄鍘熺敓input缁勪欢鐨勫寮�",
+ "keywords": [
+ "uni-ui",
+ "uniui",
+ "input",
+ "uni-easyinput",
+ "杈撳叆妗�"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+"dcloudext": {
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+ "type": "component-vue"
+ },
+ "uni_modules": {
+ "dependencies": [
+ "uni-scss",
+ "uni-icons"
+ ],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "u",
+ "鑱旂洘": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/uni_modules/uni-easyinput/readme.md b/app/uni_modules/uni-easyinput/readme.md
new file mode 100644
index 0000000..f1faf8f
--- /dev/null
+++ b/app/uni_modules/uni-easyinput/readme.md
@@ -0,0 +1,11 @@
+
+
+### Easyinput 澧炲己杈撳叆妗�
+> **缁勪欢鍚嶏細uni-easyinput**
+> 浠g爜鍧楋細 `uEasyinput`
+
+
+easyinput 缁勪欢鏄鍘熺敓input缁勪欢鐨勫寮� 锛屾槸涓撻棬涓洪厤鍚堣〃鍗曠粍浠禰uni-forms](https://ext.dcloud.net.cn/plugin?id=2773)鑰岃璁$殑锛宔asyinput 鍐呯疆浜嗚竟妗嗭紝鍥炬爣绛夛紝鍚屾椂鍖呭惈 input 鎵�鏈夊姛鑳�
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-easyinput)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
\ No newline at end of file
diff --git a/app/uni_modules/uni-fab/changelog.md b/app/uni_modules/uni-fab/changelog.md
new file mode 100644
index 0000000..9bd4729
--- /dev/null
+++ b/app/uni_modules/uni-fab/changelog.md
@@ -0,0 +1,23 @@
+## 1.2.5锛�2023-03-29锛�
+- 鏂板 pattern.icon 灞炴�э紝鍙嚜瀹氫箟鍥炬爣
+## 1.2.4锛�2022-09-07锛�
+灏忕▼搴忕鐢变簬 style 浣跨敤浜嗗璞″鑷存姤閿欙紝[璇︽儏](https://ask.dcloud.net.cn/question/152790?item_id=211778&rf=false)
+## 1.2.3锛�2022-09-05锛�
+- 淇 nvue 鐜涓嬶紝鍏锋湁 tabBar 鏃讹紝fab 缁勪欢涓嬮儴浣嶇疆鏃犳硶姝e父鑾峰彇 --window-bottom 鐨刡ug锛岃瑙侊細[https://ask.dcloud.net.cn/question/110638?notification_id=826310](https://ask.dcloud.net.cn/question/110638?notification_id=826310)
+## 1.2.2锛�2021-12-29锛�
+- 鏇存柊 缁勪欢渚濊禆
+## 1.2.1锛�2021-11-19锛�
+- 淇 闃村奖棰滆壊涓嶆纭殑bug
+## 1.2.0锛�2021-11-19锛�
+- 浼樺寲 缁勪欢UI锛屽苟鎻愪緵璁捐璧勬簮锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 鏂囨。杩佺Щ锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/uni-fab](https://uniapp.dcloud.io/component/uniui/uni-fab)
+## 1.1.1锛�2021-11-09锛�
+- 鏂板 鎻愪緵缁勪欢璁捐璧勬簮锛岀粍浠舵牱寮忚皟鏁�
+## 1.1.0锛�2021-07-30锛�
+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤簐ue3椤圭洰锛岃瑙� [uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+## 1.0.7锛�2021-05-12锛�
+- 鏂板 缁勪欢绀轰緥鍦板潃
+## 1.0.6锛�2021-02-05锛�
+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
+- 浼樺寲 鎸夐挳鑳屾櫙鑹茶皟鏁�
+- 浼樺寲 鍏煎pc绔�
diff --git a/app/uni_modules/uni-fab/components/uni-fab/uni-fab.vue b/app/uni_modules/uni-fab/components/uni-fab/uni-fab.vue
new file mode 100644
index 0000000..dfa65c1
--- /dev/null
+++ b/app/uni_modules/uni-fab/components/uni-fab/uni-fab.vue
@@ -0,0 +1,491 @@
+<template>
+ <view class="uni-cursor-point">
+ <view v-if="popMenu && (leftBottom||rightBottom||leftTop||rightTop) && content.length > 0" :class="{
+ 'uni-fab--leftBottom': leftBottom,
+ 'uni-fab--rightBottom': rightBottom,
+ 'uni-fab--leftTop': leftTop,
+ 'uni-fab--rightTop': rightTop
+ }" class="uni-fab"
+ :style="nvueBottom"
+ >
+ <view :class="{
+ 'uni-fab__content--left': horizontal === 'left',
+ 'uni-fab__content--right': horizontal === 'right',
+ 'uni-fab__content--flexDirection': direction === 'vertical',
+ 'uni-fab__content--flexDirectionStart': flexDirectionStart,
+ 'uni-fab__content--flexDirectionEnd': flexDirectionEnd,
+ 'uni-fab__content--other-platform': !isAndroidNvue
+ }" :style="{ width: boxWidth, height: boxHeight, backgroundColor: styles.backgroundColor }"
+ class="uni-fab__content" elevation="5">
+ <view v-if="flexDirectionStart || horizontalLeft" class="uni-fab__item uni-fab__item--first" />
+ <view v-for="(item, index) in content" :key="index" :class="{ 'uni-fab__item--active': isShow }"
+ class="uni-fab__item" @click="_onItemClick(index, item)">
+ <image :src="item.active ? item.selectedIconPath : item.iconPath" class="uni-fab__item-image"
+ mode="aspectFit" />
+ <text class="uni-fab__item-text"
+ :style="{ color: item.active ? styles.selectedColor : styles.color }">{{ item.text }}</text>
+ </view>
+ <view v-if="flexDirectionEnd || horizontalRight" class="uni-fab__item uni-fab__item--first" />
+ </view>
+ </view>
+ <view :class="{
+ 'uni-fab__circle--leftBottom': leftBottom,
+ 'uni-fab__circle--rightBottom': rightBottom,
+ 'uni-fab__circle--leftTop': leftTop,
+ 'uni-fab__circle--rightTop': rightTop,
+ 'uni-fab__content--other-platform': !isAndroidNvue
+ }" class="uni-fab__circle uni-fab__plus" :style="{ 'background-color': styles.buttonColor, 'bottom': nvueBottom }" @click="_onClick">
+ <uni-icons class="fab-circle-icon" :type="styles.icon" :color="styles.iconColor" size="32"
+ :class="{'uni-fab__plus--active': isShow && content.length > 0}"></uni-icons>
+ <!-- <view class="fab-circle-v" :class="{'uni-fab__plus--active': isShow && content.length > 0}"></view>
+ <view class="fab-circle-h" :class="{'uni-fab__plus--active': isShow && content.length > 0}"></view> -->
+ </view>
+ </view>
+</template>
+
+<script>
+ let platform = 'other'
+ // #ifdef APP-NVUE
+ platform = uni.getSystemInfoSync().platform
+ // #endif
+
+ /**
+ * Fab 鎮诞鎸夐挳
+ * @description 鐐瑰嚮鍙睍寮�涓�涓浘褰㈡寜閽彍鍗�
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=144
+ * @property {Object} pattern 鍙�夋牱寮忛厤缃」
+ * @property {Object} horizontal = [left | right] 姘村钩瀵归綈鏂瑰紡
+ * @value left 宸﹀榻�
+ * @value right 鍙冲榻�
+ * @property {Object} vertical = [bottom | top] 鍨傜洿瀵归綈鏂瑰紡
+ * @value bottom 涓嬪榻�
+ * @value top 涓婂榻�
+ * @property {Object} direction = [horizontal | vertical] 灞曞紑鑿滃崟鏄剧ず鏂瑰紡
+ * @value horizontal 姘村钩鏄剧ず
+ * @value vertical 鍨傜洿鏄剧ず
+ * @property {Array} content 灞曞紑鑿滃崟鍐呭閰嶇疆椤�
+ * @property {Boolean} popMenu 鏄惁浣跨敤寮瑰嚭鑿滃崟
+ * @event {Function} trigger 灞曞紑鑿滃崟鐐瑰嚮浜嬩欢锛岃繑鍥炵偣鍑讳俊鎭�
+ * @event {Function} fabClick 鎮诞鎸夐挳鐐瑰嚮浜嬩欢
+ */
+ export default {
+ name: 'UniFab',
+ emits: ['fabClick', 'trigger'],
+ props: {
+ pattern: {
+ type: Object,
+ default () {
+ return {}
+ }
+ },
+ horizontal: {
+ type: String,
+ default: 'left'
+ },
+ vertical: {
+ type: String,
+ default: 'bottom'
+ },
+ direction: {
+ type: String,
+ default: 'horizontal'
+ },
+ content: {
+ type: Array,
+ default () {
+ return []
+ }
+ },
+ show: {
+ type: Boolean,
+ default: false
+ },
+ popMenu: {
+ type: Boolean,
+ default: true
+ }
+ },
+ data() {
+ return {
+ fabShow: false,
+ isShow: false,
+ isAndroidNvue: platform === 'android',
+ styles: {
+ color: '#3c3e49',
+ selectedColor: '#007AFF',
+ backgroundColor: '#fff',
+ buttonColor: '#007AFF',
+ iconColor: '#fff',
+ icon: 'plusempty'
+ }
+ }
+ },
+ computed: {
+ contentWidth(e) {
+ return (this.content.length + 1) * 55 + 15 + 'px'
+ },
+ contentWidthMin() {
+ return '55px'
+ },
+ // 鍔ㄦ�佽绠楀搴�
+ boxWidth() {
+ return this.getPosition(3, 'horizontal')
+ },
+ // 鍔ㄦ�佽绠楅珮搴�
+ boxHeight() {
+ return this.getPosition(3, 'vertical')
+ },
+ // 璁$畻宸︿笅浣嶇疆
+ leftBottom() {
+ return this.getPosition(0, 'left', 'bottom')
+ },
+ // 璁$畻鍙充笅浣嶇疆
+ rightBottom() {
+ return this.getPosition(0, 'right', 'bottom')
+ },
+ // 璁$畻宸︿笂浣嶇疆
+ leftTop() {
+ return this.getPosition(0, 'left', 'top')
+ },
+ rightTop() {
+ return this.getPosition(0, 'right', 'top')
+ },
+ flexDirectionStart() {
+ return this.getPosition(1, 'vertical', 'top')
+ },
+ flexDirectionEnd() {
+ return this.getPosition(1, 'vertical', 'bottom')
+ },
+ horizontalLeft() {
+ return this.getPosition(2, 'horizontal', 'left')
+ },
+ horizontalRight() {
+ return this.getPosition(2, 'horizontal', 'right')
+ },
+ // 璁$畻 nvue bottom
+ nvueBottom() {
+ const safeBottom = uni.getSystemInfoSync().windowBottom;
+ // #ifdef APP-NVUE
+ return 30 + safeBottom
+ // #endif
+ // #ifndef APP-NVUE
+ return 30
+ // #endif
+ }
+ },
+ watch: {
+ pattern: {
+ handler(val, oldVal) {
+ this.styles = Object.assign({}, this.styles, val)
+ },
+ deep: true
+ }
+ },
+ created() {
+ this.isShow = this.show
+ if (this.top === 0) {
+ this.fabShow = true
+ }
+ // 鍒濆鍖栨牱寮�
+ this.styles = Object.assign({}, this.styles, this.pattern)
+ },
+ methods: {
+ _onClick() {
+ this.$emit('fabClick')
+ if (!this.popMenu) {
+ return
+ }
+ this.isShow = !this.isShow
+ },
+ open() {
+ this.isShow = true
+ },
+ close() {
+ this.isShow = false
+ },
+ /**
+ * 鎸夐挳鐐瑰嚮浜嬩欢
+ */
+ _onItemClick(index, item) {
+ if (!this.isShow) {
+ return
+ }
+ this.$emit('trigger', {
+ index,
+ item
+ })
+ },
+ /**
+ * 鑾峰彇 浣嶇疆淇℃伅
+ */
+ getPosition(types, paramA, paramB) {
+ if (types === 0) {
+ return this.horizontal === paramA && this.vertical === paramB
+ } else if (types === 1) {
+ return this.direction === paramA && this.vertical === paramB
+ } else if (types === 2) {
+ return this.direction === paramA && this.horizontal === paramB
+ } else {
+ return this.isShow && this.direction === paramA ? this.contentWidth : this.contentWidthMin
+ }
+ }
+ }
+ }
+</script>
+
+<style lang="scss" >
+ $uni-shadow-base:0 1px 5px 2px rgba($color: #000000, $alpha: 0.3) !default;
+
+ .uni-fab {
+ position: fixed;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ justify-content: center;
+ align-items: center;
+ z-index: 10;
+ border-radius: 45px;
+ box-shadow: $uni-shadow-base;
+ }
+
+ .uni-cursor-point {
+ /* #ifdef H5 */
+ cursor: pointer;
+ /* #endif */
+ }
+
+ .uni-fab--active {
+ opacity: 1;
+ }
+
+ .uni-fab--leftBottom {
+ left: 15px;
+ bottom: 30px;
+ /* #ifdef H5 */
+ left: calc(15px + var(--window-left));
+ bottom: calc(30px + var(--window-bottom));
+ /* #endif */
+ // padding: 10px;
+ }
+
+ .uni-fab--leftTop {
+ left: 15px;
+ top: 30px;
+ /* #ifdef H5 */
+ left: calc(15px + var(--window-left));
+ top: calc(30px + var(--window-top));
+ /* #endif */
+ // padding: 10px;
+ }
+
+ .uni-fab--rightBottom {
+ right: 15px;
+ bottom: 30px;
+ /* #ifdef H5 */
+ right: calc(15px + var(--window-right));
+ bottom: calc(30px + var(--window-bottom));
+ /* #endif */
+ // padding: 10px;
+ }
+
+ .uni-fab--rightTop {
+ right: 15px;
+ top: 30px;
+ /* #ifdef H5 */
+ right: calc(15px + var(--window-right));
+ top: calc(30px + var(--window-top));
+ /* #endif */
+ // padding: 10px;
+ }
+
+ .uni-fab__circle {
+ position: fixed;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ justify-content: center;
+ align-items: center;
+ width: 55px;
+ height: 55px;
+ background-color: #3c3e49;
+ border-radius: 45px;
+ z-index: 11;
+ // box-shadow: $uni-shadow-base;
+ }
+
+ .uni-fab__circle--leftBottom {
+ left: 15px;
+ bottom: 30px;
+ /* #ifdef H5 */
+ left: calc(15px + var(--window-left));
+ bottom: calc(30px + var(--window-bottom));
+ /* #endif */
+ }
+
+ .uni-fab__circle--leftTop {
+ left: 15px;
+ top: 30px;
+ /* #ifdef H5 */
+ left: calc(15px + var(--window-left));
+ top: calc(30px + var(--window-top));
+ /* #endif */
+ }
+
+ .uni-fab__circle--rightBottom {
+ right: 15px;
+ bottom: 30px;
+ /* #ifdef H5 */
+ right: calc(15px + var(--window-right));
+ bottom: calc(30px + var(--window-bottom));
+ /* #endif */
+ }
+
+ .uni-fab__circle--rightTop {
+ right: 15px;
+ top: 30px;
+ /* #ifdef H5 */
+ right: calc(15px + var(--window-right));
+ top: calc(30px + var(--window-top));
+ /* #endif */
+ }
+
+ .uni-fab__circle--left {
+ left: 0;
+ }
+
+ .uni-fab__circle--right {
+ right: 0;
+ }
+
+ .uni-fab__circle--top {
+ top: 0;
+ }
+
+ .uni-fab__circle--bottom {
+ bottom: 0;
+ }
+
+ .uni-fab__plus {
+ font-weight: bold;
+ }
+
+ // .fab-circle-v {
+ // position: absolute;
+ // width: 2px;
+ // height: 24px;
+ // left: 0;
+ // top: 0;
+ // right: 0;
+ // bottom: 0;
+ // /* #ifndef APP-NVUE */
+ // margin: auto;
+ // /* #endif */
+ // background-color: white;
+ // transform: rotate(0deg);
+ // transition: transform 0.3s;
+ // }
+
+ // .fab-circle-h {
+ // position: absolute;
+ // width: 24px;
+ // height: 2px;
+ // left: 0;
+ // top: 0;
+ // right: 0;
+ // bottom: 0;
+ // /* #ifndef APP-NVUE */
+ // margin: auto;
+ // /* #endif */
+ // background-color: white;
+ // transform: rotate(0deg);
+ // transition: transform 0.3s;
+ // }
+
+ .fab-circle-icon {
+ transform: rotate(0deg);
+ transition: transform 0.3s;
+ font-weight: 200;
+ }
+
+ .uni-fab__plus--active {
+ transform: rotate(135deg);
+ }
+
+ .uni-fab__content {
+ /* #ifndef APP-NVUE */
+ box-sizing: border-box;
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ border-radius: 55px;
+ overflow: hidden;
+ transition-property: width, height;
+ transition-duration: 0.2s;
+ width: 55px;
+ border-color: #DDDDDD;
+ border-width: 1rpx;
+ border-style: solid;
+ }
+
+ .uni-fab__content--other-platform {
+ border-width: 0px;
+ box-shadow: $uni-shadow-base;
+ }
+
+ .uni-fab__content--left {
+ justify-content: flex-start;
+ }
+
+ .uni-fab__content--right {
+ justify-content: flex-end;
+ }
+
+ .uni-fab__content--flexDirection {
+ flex-direction: column;
+ justify-content: flex-end;
+ }
+
+ .uni-fab__content--flexDirectionStart {
+ flex-direction: column;
+ justify-content: flex-start;
+ }
+
+ .uni-fab__content--flexDirectionEnd {
+ flex-direction: column;
+ justify-content: flex-end;
+ }
+
+ .uni-fab__item {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ width: 55px;
+ height: 55px;
+ opacity: 0;
+ transition: opacity 0.2s;
+ }
+
+ .uni-fab__item--active {
+ opacity: 1;
+ }
+
+ .uni-fab__item-image {
+ width: 20px;
+ height: 20px;
+ margin-bottom: 4px;
+ }
+
+ .uni-fab__item-text {
+ color: #FFFFFF;
+ font-size: 12px;
+ line-height: 12px;
+ margin-top: 2px;
+ }
+
+ .uni-fab__item--first {
+ width: 55px;
+ }
+</style>
diff --git a/app/uni_modules/uni-fab/package.json b/app/uni_modules/uni-fab/package.json
new file mode 100644
index 0000000..18c0810
--- /dev/null
+++ b/app/uni_modules/uni-fab/package.json
@@ -0,0 +1,84 @@
+{
+ "id": "uni-fab",
+ "displayName": "uni-fab 鎮诞鎸夐挳",
+ "version": "1.2.5",
+ "description": "鎮诞鎸夐挳 fab button 锛岀偣鍑诲彲灞曞紑涓�涓浘鏍囨寜閽彍鍗曘��",
+ "keywords": [
+ "uni-ui",
+ "uniui",
+ "鎸夐挳",
+ "鎮诞鎸夐挳",
+ "fab"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+"dcloudext": {
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+ "type": "component-vue"
+ },
+ "uni_modules": {
+ "dependencies": ["uni-scss","uni-icons"],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "u",
+ "鑱旂洘": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
diff --git a/app/uni_modules/uni-fab/readme.md b/app/uni_modules/uni-fab/readme.md
new file mode 100644
index 0000000..9a444e8
--- /dev/null
+++ b/app/uni_modules/uni-fab/readme.md
@@ -0,0 +1,9 @@
+## Fab 鎮诞鎸夐挳
+> **缁勪欢鍚嶏細uni-fab**
+> 浠g爜鍧楋細 `uFab`
+
+
+鐐瑰嚮鍙睍寮�涓�涓浘褰㈡寜閽彍鍗�
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-fab)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
\ No newline at end of file
diff --git a/app/uni_modules/uni-fav/changelog.md b/app/uni_modules/uni-fav/changelog.md
new file mode 100644
index 0000000..d8a08d4
--- /dev/null
+++ b/app/uni_modules/uni-fav/changelog.md
@@ -0,0 +1,19 @@
+## 1.2.1锛�2022-05-30锛�
+- 鏂板 stat 灞炴�� 锛屾槸鍚﹀紑鍚痷ni缁熻鍔熻兘
+## 1.2.0锛�2021-11-19锛�
+- 浼樺寲 缁勪欢UI锛屽苟鎻愪緵璁捐璧勬簮锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 鏂囨。杩佺Щ锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/uni-fav](https://uniapp.dcloud.io/component/uniui/uni-fav)
+## 1.1.1锛�2021-08-24锛�
+- 鏂板 鏀寔鍥介檯鍖�
+## 1.1.0锛�2021-07-13锛�
+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤簐ue3椤圭洰锛岃瑙� [uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+## 1.0.6锛�2021-05-12锛�
+- 鏂板 缁勪欢绀轰緥鍦板潃
+## 1.0.5锛�2021-04-21锛�
+- 浼樺寲 娣诲姞渚濊禆 uni-icons, 瀵煎叆鍚庤嚜鍔ㄤ笅杞戒緷璧�
+## 1.0.4锛�2021-02-05锛�
+- 浼樺寲 缁勪欢寮曠敤鍏崇郴锛岄�氳繃uni_modules寮曠敤缁勪欢
+## 1.0.3锛�2021-02-05锛�
+- 浼樺寲 缁勪欢寮曠敤鍏崇郴锛岄�氳繃uni_modules寮曠敤缁勪欢
+## 1.0.2锛�2021-02-05锛�
+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
diff --git a/app/uni_modules/uni-fav/components/uni-fav/i18n/en.json b/app/uni_modules/uni-fav/components/uni-fav/i18n/en.json
new file mode 100644
index 0000000..9a0759e
--- /dev/null
+++ b/app/uni_modules/uni-fav/components/uni-fav/i18n/en.json
@@ -0,0 +1,4 @@
+{
+ "uni-fav.collect": "collect",
+ "uni-fav.collected": "collected"
+}
diff --git a/app/uni_modules/uni-fav/components/uni-fav/i18n/index.js b/app/uni_modules/uni-fav/components/uni-fav/i18n/index.js
new file mode 100644
index 0000000..de7509c
--- /dev/null
+++ b/app/uni_modules/uni-fav/components/uni-fav/i18n/index.js
@@ -0,0 +1,8 @@
+import en from './en.json'
+import zhHans from './zh-Hans.json'
+import zhHant from './zh-Hant.json'
+export default {
+ en,
+ 'zh-Hans': zhHans,
+ 'zh-Hant': zhHant
+}
diff --git a/app/uni_modules/uni-fav/components/uni-fav/i18n/zh-Hans.json b/app/uni_modules/uni-fav/components/uni-fav/i18n/zh-Hans.json
new file mode 100644
index 0000000..67c89bf
--- /dev/null
+++ b/app/uni_modules/uni-fav/components/uni-fav/i18n/zh-Hans.json
@@ -0,0 +1,4 @@
+{
+ "uni-fav.collect": "鏀惰棌",
+ "uni-fav.collected": "宸叉敹钘�"
+}
diff --git a/app/uni_modules/uni-fav/components/uni-fav/i18n/zh-Hant.json b/app/uni_modules/uni-fav/components/uni-fav/i18n/zh-Hant.json
new file mode 100644
index 0000000..67c89bf
--- /dev/null
+++ b/app/uni_modules/uni-fav/components/uni-fav/i18n/zh-Hant.json
@@ -0,0 +1,4 @@
+{
+ "uni-fav.collect": "鏀惰棌",
+ "uni-fav.collected": "宸叉敹钘�"
+}
diff --git a/app/uni_modules/uni-fav/components/uni-fav/uni-fav.vue b/app/uni_modules/uni-fav/components/uni-fav/uni-fav.vue
new file mode 100644
index 0000000..d2c58df
--- /dev/null
+++ b/app/uni_modules/uni-fav/components/uni-fav/uni-fav.vue
@@ -0,0 +1,161 @@
+<template>
+ <view :class="[circle === true || circle === 'true' ? 'uni-fav--circle' : '']" :style="[{ backgroundColor: checked ? bgColorChecked : bgColor }]"
+ @click="onClick" class="uni-fav">
+ <!-- #ifdef MP-ALIPAY -->
+ <view class="uni-fav-star" v-if="!checked && (star === true || star === 'true')">
+ <uni-icons :color="fgColor" :style="{color: checked ? fgColorChecked : fgColor}" size="14" type="star-filled" />
+ </view>
+ <!-- #endif -->
+ <!-- #ifndef MP-ALIPAY -->
+ <uni-icons :color="fgColor" :style="{color: checked ? fgColorChecked : fgColor}" class="uni-fav-star" size="14" type="star-filled"
+ v-if="!checked && (star === true || star === 'true')" />
+ <!-- #endif -->
+ <text :style="{color: checked ? fgColorChecked : fgColor}" class="uni-fav-text">{{ checked ? contentFav : contentDefault }}</text>
+ </view>
+</template>
+
+<script>
+
+ /**
+ * Fav 鏀惰棌鎸夐挳
+ * @description 鐢ㄤ簬鏀惰棌鍔熻兘锛屽彲鐐瑰嚮鍒囨崲閫変腑銆佷笉閫変腑鐨勭姸鎬�
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=864
+ * @property {Boolean} star = [true|false] 鎸夐挳鏄惁甯︽槦鏄�
+ * @property {String} bgColor 鏈敹钘忔椂鐨勮儗鏅壊
+ * @property {String} bgColorChecked 宸叉敹钘忔椂鐨勮儗鏅壊
+ * @property {String} fgColor 鏈敹钘忔椂鐨勬枃瀛楅鑹�
+ * @property {String} fgColorChecked 宸叉敹钘忔椂鐨勬枃瀛楅鑹�
+ * @property {Boolean} circle = [true|false] 鏄惁涓哄渾瑙�
+ * @property {Boolean} checked = [true|false] 鏄惁涓哄凡鏀惰棌
+ * @property {Object} contentText = [true|false] 鏀惰棌鎸夐挳鏂囧瓧
+ * @property {Boolean} stat 鏄惁寮�鍚粺璁″姛鑳�
+ * @event {Function} click 鐐瑰嚮 fav鎸夐挳瑙﹀彂浜嬩欢
+ * @example <uni-fav :checked="true"/>
+ */
+
+ import {
+ initVueI18n
+ } from '@dcloudio/uni-i18n'
+ import messages from './i18n/index.js'
+ const { t } = initVueI18n(messages)
+
+ export default {
+ name: "UniFav",
+ // TODO 鍏煎 vue3锛岄渶瑕佹敞鍐屼簨浠�
+ emits: ['click'],
+ props: {
+ star: {
+ type: [Boolean, String],
+ default: true
+ },
+ bgColor: {
+ type: String,
+ default: "#eeeeee"
+ },
+ fgColor: {
+ type: String,
+ default: "#666666"
+ },
+ bgColorChecked: {
+ type: String,
+ default: "#007aff"
+ },
+ fgColorChecked: {
+ type: String,
+ default: "#FFFFFF"
+ },
+ circle: {
+ type: [Boolean, String],
+ default: false
+ },
+ checked: {
+ type: Boolean,
+ default: false
+ },
+ contentText: {
+ type: Object,
+ default () {
+ return {
+ contentDefault: "",
+ contentFav: ""
+ };
+ }
+ },
+ stat:{
+ type: Boolean,
+ default: false
+ }
+ },
+ computed: {
+ contentDefault() {
+ return this.contentText.contentDefault || t("uni-fav.collect")
+ },
+ contentFav() {
+ return this.contentText.contentFav || t("uni-fav.collected")
+ },
+ },
+ watch: {
+ checked() {
+ if (uni.report && this.stat) {
+ if (this.checked) {
+ uni.report("鏀惰棌", "鏀惰棌");
+ } else {
+ uni.report("鍙栨秷鏀惰棌", "鍙栨秷鏀惰棌");
+ }
+ }
+ }
+ },
+ methods: {
+ onClick() {
+ this.$emit("click");
+ }
+ }
+ };
+</script>
+
+<style lang="scss" >
+ $fav-height: 25px;
+
+ .uni-fav {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ align-items: center;
+ justify-content: center;
+ width: 60px;
+ height: $fav-height;
+ line-height: $fav-height;
+ text-align: center;
+ border-radius: 3px;
+ /* #ifdef H5 */
+ cursor: pointer;
+ /* #endif */
+ }
+
+ .uni-fav--circle {
+ border-radius: 30px;
+ }
+
+ .uni-fav-star {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ height: $fav-height;
+ line-height: 24px;
+ margin-right: 3px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ .uni-fav-text {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ height: $fav-height;
+ line-height: $fav-height;
+ align-items: center;
+ justify-content: center;
+ font-size: 12px;
+ }
+</style>
diff --git a/app/uni_modules/uni-fav/package.json b/app/uni_modules/uni-fav/package.json
new file mode 100644
index 0000000..cc14697
--- /dev/null
+++ b/app/uni_modules/uni-fav/package.json
@@ -0,0 +1,89 @@
+{
+ "id": "uni-fav",
+ "displayName": "uni-fav 鏀惰棌鎸夐挳",
+ "version": "1.2.1",
+ "description": " Fav 鏀惰棌缁勪欢锛屽彲鑷畾涔夐鑹层�佸ぇ灏忋��",
+ "keywords": [
+ "fav",
+ "uni-ui",
+ "uniui",
+ "鏀惰棌"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "鍓嶇缁勪欢",
+ "閫氱敤缁勪欢"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": [
+ "uni-scss",
+ "uni-icons"
+ ],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "u",
+ "鑱旂洘": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
diff --git a/app/uni_modules/uni-fav/readme.md b/app/uni_modules/uni-fav/readme.md
new file mode 100644
index 0000000..4de125d
--- /dev/null
+++ b/app/uni_modules/uni-fav/readme.md
@@ -0,0 +1,10 @@
+
+
+## Fav 鏀惰棌鎸夐挳
+> **缁勪欢鍚嶏細uni-fav**
+> 浠g爜鍧楋細 `uFav`
+
+鐢ㄤ簬鏀惰棌鍔熻兘锛屽彲鐐瑰嚮鍒囨崲閫変腑銆佷笉閫変腑鐨勭姸鎬併��
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-fav)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
\ No newline at end of file
diff --git a/app/uni_modules/uni-file-picker/changelog.md b/app/uni_modules/uni-file-picker/changelog.md
new file mode 100644
index 0000000..b8230e9
--- /dev/null
+++ b/app/uni_modules/uni-file-picker/changelog.md
@@ -0,0 +1,67 @@
+## 1.0.4锛�2023-03-29锛�
+- 淇 鎵嬪姩涓婁紶鍒犻櫎涓�涓枃浠跺悗涓嶈兘鍐嶄笂浼犵殑bug
+## 1.0.3锛�2022-12-19锛�
+- 鏂板 sourceType 灞炴��, 鍙互鑷畾涔夊浘鐗囧拰瑙嗛閫夋嫨鐨勬潵婧�
+## 1.0.2锛�2022-07-04锛�
+- 淇 鍦╱ni-forms涓嬫牱寮忎笉鐢熸晥鐨刡ug
+## 1.0.1锛�2021-11-23锛�
+- 淇 鍙傛暟涓哄璞$殑鎯呭喌涓嬶紝url鍦ㄦ煇浜涙儏鍐垫樉绀洪敊璇殑bug
+## 1.0.0锛�2021-11-19锛�
+- 浼樺寲 缁勪欢UI锛屽苟鎻愪緵璁捐璧勬簮锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 鏂囨。杩佺Щ锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/uni-file-picker](https://uniapp.dcloud.io/component/uniui/uni-file-picker)
+## 0.2.16锛�2021-11-08锛�
+- 淇 浼犲叆绌哄璞� 锛屾樉绀洪敊璇殑Bug
+## 0.2.15锛�2021-08-30锛�
+- 淇 return-type="object" 鏃朵笖瀛樺湪v-model鏃讹紝鏃犳硶鍒犻櫎鏂囦欢鐨凚ug
+## 0.2.14锛�2021-08-23锛�
+- 鏂板 鍙傛暟涓繑鍥� fileID 瀛楁
+## 0.2.13锛�2021-08-23锛�
+- 淇 鑵捐浜戜紶鍏ileID 涓嶈兘鍥炴樉鐨刡ug
+- 淇 閫夋嫨鍥剧墖鍚庯紝涓嶈兘鏀惧ぇ鐨勯棶棰�
+## 0.2.12锛�2021-08-17锛�
+- 淇 鐢变簬 0.2.11 鐗堟湰寮曡捣鐨勪笉鑳藉洖鏄惧浘鐗囩殑Bug
+## 0.2.11锛�2021-08-16锛�
+- 鏂板 clearFiles(index) 鏂规硶锛屽彲浠ユ墜鍔ㄥ垹闄ゆ寚瀹氭枃浠�
+- 淇 v-model 鍊艰涓� null 鎶ラ敊鐨凚ug
+## 0.2.10锛�2021-08-13锛�
+- 淇 return-type="object" 鏃讹紝鏃犳硶鍒犻櫎鏂囦欢鐨凚ug
+## 0.2.9锛�2021-08-03锛�
+- 淇 auto-upload 灞炴�уけ鏁堢殑Bug
+## 0.2.8锛�2021-07-31锛�
+- 淇 fileExtname灞炴�т笉鎸囧畾鍊兼姤閿欑殑Bug
+## 0.2.7锛�2021-07-31锛�
+- 淇 鍦ㄦ煇绉嶅満鏅笅鍥剧墖涓嶅洖鏄剧殑Bug
+## 0.2.6锛�2021-07-30锛�
+- 淇 return-type涓簅bject涓嬶紝杩斿洖鍊间笉姝g‘鐨凚ug
+## 0.2.5锛�2021-07-30锛�
+- 淇锛堥噸瑕侊級 H5 骞冲彴涓嬪鏋滃拰uni-forms缁勪欢涓�鍚屼娇鐢ㄥ鑷撮〉闈㈠崱姝荤殑闂
+## 0.2.3锛�2021-07-28锛�
+- 浼樺寲 璋冩暣绀轰緥浠g爜
+## 0.2.2锛�2021-07-27锛�
+- 淇 vue3 涓嬭祴鍊奸敊璇殑Bug
+- 浼樺寲 h5骞冲彴涓嬩笂浼犳枃浠跺鑷撮〉闈㈠崱姝荤殑闂
+## 0.2.0锛�2021-07-13锛�
+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤簐ue3椤圭洰锛岃瑙� [uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+## 0.1.1锛�2021-07-02锛�
+- 淇 sourceType 缂哄皯榛樿鍊煎鑷� ios 鏃犳硶閫夋嫨鏂囦欢
+## 0.1.0锛�2021-06-30锛�
+- 浼樺寲 瑙h�︿笌uniCloud鐨勫己缁戝畾鍏崇郴 锛屽涓嶇粦瀹氭湇鍔$┖闂达紝榛樿autoUpload涓篺alse涓斾笉鍙洿鏀�
+## 0.0.11锛�2021-06-30锛�
+- 淇 鐢� 0.0.10 鐗堟湰寮曞彂鐨� returnType 灞炴�уけ鏁堢殑闂
+## 0.0.10锛�2021-06-29锛�
+- 浼樺寲 鏂囦欢涓婁紶鍚庤繘搴︽潯娑堝け鏃舵満
+## 0.0.9锛�2021-06-29锛�
+- 淇 鍦╱ni-forms 涓紝鍒犻櫎鏂囦欢 锛岃幏鍙栫殑鍊间笉瀵圭殑Bug
+## 0.0.8锛�2021-06-15锛�
+- 淇 鍒犻櫎鏂囦欢鏃舵棤娉曡Е鍙� v-model 鐨凚ug
+## 0.0.7锛�2021-05-12锛�
+- 鏂板 缁勪欢绀轰緥鍦板潃
+## 0.0.6锛�2021-04-09锛�
+- 淇 閫夋嫨鐨勬枃浠堕潪 file-extname 瀛楁鎸囧畾鐨勬墿灞曞悕鎶ラ敊鐨凚ug
+## 0.0.5锛�2021-04-09锛�
+- 浼樺寲 鏇存柊缁勪欢绀轰緥
+## 0.0.4锛�2021-04-09锛�
+- 浼樺寲 file-extname 瀛楁鏀寔瀛楃涓插啓娉曪紝澶氫釜鎵╁睍鍚嶉渶瑕佺敤閫楀彿鍒嗛殧
+## 0.0.3锛�2021-02-05锛�
+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
+- 淇 寰俊灏忕▼搴忎笉鎸囧畾 fileExtname 灞炴�ч�夋嫨澶辫触鐨凚ug
diff --git a/app/uni_modules/uni-file-picker/components/uni-file-picker/choose-and-upload-file.js b/app/uni_modules/uni-file-picker/components/uni-file-picker/choose-and-upload-file.js
new file mode 100644
index 0000000..aff0864
--- /dev/null
+++ b/app/uni_modules/uni-file-picker/components/uni-file-picker/choose-and-upload-file.js
@@ -0,0 +1,224 @@
+'use strict';
+
+const ERR_MSG_OK = 'chooseAndUploadFile:ok';
+const ERR_MSG_FAIL = 'chooseAndUploadFile:fail';
+
+function chooseImage(opts) {
+ const {
+ count,
+ sizeType = ['original', 'compressed'],
+ sourceType,
+ extension
+ } = opts
+ return new Promise((resolve, reject) => {
+ uni.chooseImage({
+ count,
+ sizeType,
+ sourceType,
+ extension,
+ success(res) {
+ resolve(normalizeChooseAndUploadFileRes(res, 'image'));
+ },
+ fail(res) {
+ reject({
+ errMsg: res.errMsg.replace('chooseImage:fail', ERR_MSG_FAIL),
+ });
+ },
+ });
+ });
+}
+
+function chooseVideo(opts) {
+ const {
+ camera,
+ compressed,
+ maxDuration,
+ sourceType,
+ extension
+ } = opts;
+ return new Promise((resolve, reject) => {
+ uni.chooseVideo({
+ camera,
+ compressed,
+ maxDuration,
+ sourceType,
+ extension,
+ success(res) {
+ const {
+ tempFilePath,
+ duration,
+ size,
+ height,
+ width
+ } = res;
+ resolve(normalizeChooseAndUploadFileRes({
+ errMsg: 'chooseVideo:ok',
+ tempFilePaths: [tempFilePath],
+ tempFiles: [
+ {
+ name: (res.tempFile && res.tempFile.name) || '',
+ path: tempFilePath,
+ size,
+ type: (res.tempFile && res.tempFile.type) || '',
+ width,
+ height,
+ duration,
+ fileType: 'video',
+ cloudPath: '',
+ }, ],
+ }, 'video'));
+ },
+ fail(res) {
+ reject({
+ errMsg: res.errMsg.replace('chooseVideo:fail', ERR_MSG_FAIL),
+ });
+ },
+ });
+ });
+}
+
+function chooseAll(opts) {
+ const {
+ count,
+ extension
+ } = opts;
+ return new Promise((resolve, reject) => {
+ let chooseFile = uni.chooseFile;
+ if (typeof wx !== 'undefined' &&
+ typeof wx.chooseMessageFile === 'function') {
+ chooseFile = wx.chooseMessageFile;
+ }
+ if (typeof chooseFile !== 'function') {
+ return reject({
+ errMsg: ERR_MSG_FAIL + ' 璇锋寚瀹� type 绫诲瀷锛岃骞冲彴浠呮敮鎸侀�夋嫨 image 鎴� video銆�',
+ });
+ }
+ chooseFile({
+ type: 'all',
+ count,
+ extension,
+ success(res) {
+ resolve(normalizeChooseAndUploadFileRes(res));
+ },
+ fail(res) {
+ reject({
+ errMsg: res.errMsg.replace('chooseFile:fail', ERR_MSG_FAIL),
+ });
+ },
+ });
+ });
+}
+
+function normalizeChooseAndUploadFileRes(res, fileType) {
+ res.tempFiles.forEach((item, index) => {
+ if (!item.name) {
+ item.name = item.path.substring(item.path.lastIndexOf('/') + 1);
+ }
+ if (fileType) {
+ item.fileType = fileType;
+ }
+ item.cloudPath =
+ Date.now() + '_' + index + item.name.substring(item.name.lastIndexOf('.'));
+ });
+ if (!res.tempFilePaths) {
+ res.tempFilePaths = res.tempFiles.map((file) => file.path);
+ }
+ return res;
+}
+
+function uploadCloudFiles(files, max = 5, onUploadProgress) {
+ files = JSON.parse(JSON.stringify(files))
+ const len = files.length
+ let count = 0
+ let self = this
+ return new Promise(resolve => {
+ while (count < max) {
+ next()
+ }
+
+ function next() {
+ let cur = count++
+ if (cur >= len) {
+ !files.find(item => !item.url && !item.errMsg) && resolve(files)
+ return
+ }
+ const fileItem = files[cur]
+ const index = self.files.findIndex(v => v.uuid === fileItem.uuid)
+ fileItem.url = ''
+ delete fileItem.errMsg
+
+ uniCloud
+ .uploadFile({
+ filePath: fileItem.path,
+ cloudPath: fileItem.cloudPath,
+ fileType: fileItem.fileType,
+ onUploadProgress: res => {
+ res.index = index
+ onUploadProgress && onUploadProgress(res)
+ }
+ })
+ .then(res => {
+ fileItem.url = res.fileID
+ fileItem.index = index
+ if (cur < len) {
+ next()
+ }
+ })
+ .catch(res => {
+ fileItem.errMsg = res.errMsg || res.message
+ fileItem.index = index
+ if (cur < len) {
+ next()
+ }
+ })
+ }
+ })
+}
+
+
+
+
+
+function uploadFiles(choosePromise, {
+ onChooseFile,
+ onUploadProgress
+}) {
+ return choosePromise
+ .then((res) => {
+ if (onChooseFile) {
+ const customChooseRes = onChooseFile(res);
+ if (typeof customChooseRes !== 'undefined') {
+ return Promise.resolve(customChooseRes).then((chooseRes) => typeof chooseRes === 'undefined' ?
+ res : chooseRes);
+ }
+ }
+ return res;
+ })
+ .then((res) => {
+ if (res === false) {
+ return {
+ errMsg: ERR_MSG_OK,
+ tempFilePaths: [],
+ tempFiles: [],
+ };
+ }
+ return res
+ })
+}
+
+function chooseAndUploadFile(opts = {
+ type: 'all'
+}) {
+ if (opts.type === 'image') {
+ return uploadFiles(chooseImage(opts), opts);
+ }
+ else if (opts.type === 'video') {
+ return uploadFiles(chooseVideo(opts), opts);
+ }
+ return uploadFiles(chooseAll(opts), opts);
+}
+
+export {
+ chooseAndUploadFile,
+ uploadCloudFiles
+};
diff --git a/app/uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue b/app/uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue
new file mode 100644
index 0000000..370441d
--- /dev/null
+++ b/app/uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue
@@ -0,0 +1,667 @@
+<template>
+ <view class="uni-file-picker">
+ <view v-if="title" class="uni-file-picker__header">
+ <text class="file-title">{{ title }}</text>
+ <text class="file-count">{{ filesList.length }}/{{ limitLength }}</text>
+ </view>
+ <upload-image v-if="fileMediatype === 'image' && showType === 'grid'" :readonly="readonly"
+ :image-styles="imageStyles" :files-list="filesList" :limit="limitLength" :disablePreview="disablePreview"
+ :delIcon="delIcon" @uploadFiles="uploadFiles" @choose="choose" @delFile="delFile">
+ <slot>
+ <view class="is-add">
+ <view class="icon-add"></view>
+ <view class="icon-add rotate"></view>
+ </view>
+ </slot>
+ </upload-image>
+ <upload-file v-if="fileMediatype !== 'image' || showType !== 'grid'" :readonly="readonly"
+ :list-styles="listStyles" :files-list="filesList" :showType="showType" :delIcon="delIcon"
+ @uploadFiles="uploadFiles" @choose="choose" @delFile="delFile">
+ <slot><button type="primary" size="mini">閫夋嫨鏂囦欢</button></slot>
+ </upload-file>
+ </view>
+</template>
+
+<script>
+ import {
+ chooseAndUploadFile,
+ uploadCloudFiles
+ } from './choose-and-upload-file.js'
+ import {
+ get_file_ext,
+ get_extname,
+ get_files_and_is_max,
+ get_file_info,
+ get_file_data
+ } from './utils.js'
+ import uploadImage from './upload-image.vue'
+ import uploadFile from './upload-file.vue'
+ let fileInput = null
+ /**
+ * FilePicker 鏂囦欢閫夋嫨涓婁紶
+ * @description 鏂囦欢閫夋嫨涓婁紶缁勪欢锛屽彲浠ラ�夋嫨鍥剧墖銆佽棰戠瓑浠绘剰鏂囦欢骞朵笂浼犲埌褰撳墠缁戝畾鐨勬湇鍔$┖闂�
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=4079
+ * @property {Object|Array} value 缁勪欢鏁版嵁锛岄�氬父鐢ㄦ潵鍥炴樉 ,绫诲瀷鐢眗eturn-type灞炴�у喅瀹�
+ * @property {Boolean} disabled = [true|false] 缁勪欢绂佺敤
+ * @value true 绂佺敤
+ * @value false 鍙栨秷绂佺敤
+ * @property {Boolean} readonly = [true|false] 缁勪欢鍙锛屼笉鍙�夋嫨锛屼笉鏄剧ず杩涘害锛屼笉鏄剧ず鍒犻櫎鎸夐挳
+ * @value true 鍙
+ * @value false 鍙栨秷鍙
+ * @property {String} return-type = [array|object] 闄愬埗 value 鏍煎紡锛屽綋涓� object 鏃� 锛岀粍浠跺彧鑳藉崟閫夛紝涓斾細瑕嗙洊
+ * @value array 瑙勫畾 value 灞炴�х殑绫诲瀷涓烘暟缁�
+ * @value object 瑙勫畾 value 灞炴�х殑绫诲瀷涓哄璞�
+ * @property {Boolean} disable-preview = [true|false] 绂佺敤鍥剧墖棰勮锛屼粎 mode:grid 鏃剁敓鏁�
+ * @value true 绂佺敤鍥剧墖棰勮
+ * @value false 鍙栨秷绂佺敤鍥剧墖棰勮
+ * @property {Boolean} del-icon = [true|false] 鏄惁鏄剧ず鍒犻櫎鎸夐挳
+ * @value true 鏄剧ず鍒犻櫎鎸夐挳
+ * @value false 涓嶆樉绀哄垹闄ゆ寜閽�
+ * @property {Boolean} auto-upload = [true|false] 鏄惁鑷姩涓婁紶锛屽�间负true鍒欏彧瑙﹀彂@select,鍙嚜琛屼笂浼�
+ * @value true 鑷姩涓婁紶
+ * @value false 鍙栨秷鑷姩涓婁紶
+ * @property {Number|String} limit 鏈�澶ч�夋嫨涓暟 锛宧5 浼氳嚜鍔ㄥ拷鐣ュ閫夌殑閮ㄥ垎
+ * @property {String} title 缁勪欢鏍囬锛屽彸渚ф樉绀轰笂浼犺鏁�
+ * @property {String} mode = [list|grid] 閫夋嫨鏂囦欢鍚庣殑鏂囦欢鍒楄〃鏍峰紡
+ * @value list 鍒楄〃鏄剧ず
+ * @value grid 瀹牸鏄剧ず
+ * @property {String} file-mediatype = [image|video|all] 閫夋嫨鏂囦欢绫诲瀷
+ * @value image 鍙�夋嫨鍥剧墖
+ * @value video 鍙�夋嫨瑙嗛
+ * @value all 閫夋嫨鎵�鏈夋枃浠�
+ * @property {Array} file-extname 閫夋嫨鏂囦欢鍚庣紑锛屾牴鎹� file-mediatype 灞炴�ц�屼笉鍚�
+ * @property {Object} list-style mode:list 鏃剁殑鏍峰紡
+ * @property {Object} image-styles 閫夋嫨鏂囦欢鍚庣紑锛屾牴鎹� file-mediatype 灞炴�ц�屼笉鍚�
+ * @event {Function} select 閫夋嫨鏂囦欢鍚庤Е鍙�
+ * @event {Function} progress 鏂囦欢涓婁紶鏃惰Е鍙�
+ * @event {Function} success 涓婁紶鎴愬姛瑙﹀彂
+ * @event {Function} fail 涓婁紶澶辫触瑙﹀彂
+ * @event {Function} delete 鏂囦欢浠庡垪琛ㄧЩ闄ゆ椂瑙﹀彂
+ */
+ export default {
+ name: 'uniFilePicker',
+ components: {
+ uploadImage,
+ uploadFile
+ },
+ options: {
+ virtualHost: true
+ },
+ emits: ['select', 'success', 'fail', 'progress', 'delete', 'update:modelValue', 'input'],
+ props: {
+ // #ifdef VUE3
+ modelValue: {
+ type: [Array, Object],
+ default () {
+ return []
+ }
+ },
+ // #endif
+
+ // #ifndef VUE3
+ value: {
+ type: [Array, Object],
+ default () {
+ return []
+ }
+ },
+ // #endif
+
+ disabled: {
+ type: Boolean,
+ default: false
+ },
+ disablePreview: {
+ type: Boolean,
+ default: false
+ },
+ delIcon: {
+ type: Boolean,
+ default: true
+ },
+ // 鑷姩涓婁紶
+ autoUpload: {
+ type: Boolean,
+ default: true
+ },
+ // 鏈�澶ч�夋嫨涓暟 锛宧5鍙兘闄愬埗鍗曢�夋垨鏄閫�
+ limit: {
+ type: [Number, String],
+ default: 9
+ },
+ // 鍒楄〃鏍峰紡 grid | list | list-card
+ mode: {
+ type: String,
+ default: 'grid'
+ },
+ // 閫夋嫨鏂囦欢绫诲瀷 image/video/all
+ fileMediatype: {
+ type: String,
+ default: 'image'
+ },
+ // 鏂囦欢绫诲瀷绛涢��
+ fileExtname: {
+ type: [Array, String],
+ default () {
+ return []
+ }
+ },
+ title: {
+ type: String,
+ default: ''
+ },
+ listStyles: {
+ type: Object,
+ default () {
+ return {
+ // 鏄惁鏄剧ず杈规
+ border: true,
+ // 鏄惁鏄剧ず鍒嗛殧绾�
+ dividline: true,
+ // 绾挎潯鏍峰紡
+ borderStyle: {}
+ }
+ }
+ },
+ imageStyles: {
+ type: Object,
+ default () {
+ return {
+ width: 'auto',
+ height: 'auto'
+ }
+ }
+ },
+ readonly: {
+ type: Boolean,
+ default: false
+ },
+ returnType: {
+ type: String,
+ default: 'array'
+ },
+ sizeType: {
+ type: Array,
+ default () {
+ return ['original', 'compressed']
+ }
+ },
+ sourceType: {
+ type: Array,
+ default () {
+ return ['album', 'camera']
+ }
+ }
+ },
+ data() {
+ return {
+ files: [],
+ localValue: []
+ }
+ },
+ watch: {
+ // #ifndef VUE3
+ value: {
+ handler(newVal, oldVal) {
+ this.setValue(newVal, oldVal)
+ },
+ immediate: true
+ },
+ // #endif
+ // #ifdef VUE3
+ modelValue: {
+ handler(newVal, oldVal) {
+ this.setValue(newVal, oldVal)
+ },
+ immediate: true
+ },
+ // #endif
+ },
+ computed: {
+ filesList() {
+ let files = []
+ this.files.forEach(v => {
+ files.push(v)
+ })
+ return files
+ },
+ showType() {
+ if (this.fileMediatype === 'image') {
+ return this.mode
+ }
+ return 'list'
+ },
+ limitLength() {
+ if (this.returnType === 'object') {
+ return 1
+ }
+ if (!this.limit) {
+ return 1
+ }
+ if (this.limit >= 9) {
+ return 9
+ }
+ return this.limit
+ }
+ },
+ created() {
+ // TODO 鍏煎涓嶅紑閫氭湇鍔$┖闂寸殑鎯呭喌
+ if (!(uniCloud.config && uniCloud.config.provider)) {
+ this.noSpace = true
+ uniCloud.chooseAndUploadFile = chooseAndUploadFile
+ }
+ this.form = this.getForm('uniForms')
+ this.formItem = this.getForm('uniFormsItem')
+ if (this.form && this.formItem) {
+ if (this.formItem.name) {
+ this.rename = this.formItem.name
+ this.form.inputChildrens.push(this)
+ }
+ }
+ },
+ methods: {
+ /**
+ * 鍏紑鐢ㄦ埛浣跨敤锛屾竻绌烘枃浠�
+ * @param {Object} index
+ */
+ clearFiles(index) {
+ if (index !== 0 && !index) {
+ this.files = []
+ this.$nextTick(() => {
+ this.setEmit()
+ })
+ } else {
+ this.files.splice(index, 1)
+ }
+ this.$nextTick(() => {
+ this.setEmit()
+ })
+ },
+ /**
+ * 鍏紑鐢ㄦ埛浣跨敤锛岀户缁笂浼�
+ */
+ upload() {
+ let files = []
+ this.files.forEach((v, index) => {
+ if (v.status === 'ready' || v.status === 'error') {
+ files.push(Object.assign({}, v))
+ }
+ })
+ return this.uploadFiles(files)
+ },
+ async setValue(newVal, oldVal) {
+ const newData = async (v) => {
+ const reg = /cloud:\/\/([\w.]+\/?)\S*/
+ let url = ''
+ if(v.fileID){
+ url = v.fileID
+ }else{
+ url = v.url
+ }
+ if (reg.test(url)) {
+ v.fileID = url
+ v.url = await this.getTempFileURL(url)
+ }
+ if(v.url) v.path = v.url
+ return v
+ }
+ if (this.returnType === 'object') {
+ if (newVal) {
+ await newData(newVal)
+ } else {
+ newVal = {}
+ }
+ } else {
+ if (!newVal) newVal = []
+ for(let i =0 ;i < newVal.length ;i++){
+ let v = newVal[i]
+ await newData(v)
+ }
+ }
+ this.localValue = newVal
+ if (this.form && this.formItem &&!this.is_reset) {
+ this.is_reset = false
+ this.formItem.setValue(this.localValue)
+ }
+ let filesData = Object.keys(newVal).length > 0 ? newVal : [];
+ this.files = [].concat(filesData)
+ },
+
+ /**
+ * 閫夋嫨鏂囦欢
+ */
+ choose() {
+
+ if (this.disabled) return
+ if (this.files.length >= Number(this.limitLength) && this.showType !== 'grid' && this.returnType ===
+ 'array') {
+ uni.showToast({
+ title: `鎮ㄦ渶澶氶�夋嫨 ${this.limitLength} 涓枃浠禶,
+ icon: 'none'
+ })
+ return
+ }
+ this.chooseFiles()
+ },
+
+ /**
+ * 閫夋嫨鏂囦欢骞朵笂浼�
+ */
+ chooseFiles() {
+ const _extname = get_extname(this.fileExtname)
+ // 鑾峰彇鍚庣紑
+ uniCloud
+ .chooseAndUploadFile({
+ type: this.fileMediatype,
+ compressed: false,
+ sizeType: this.sizeType,
+ sourceType: this.sourceType,
+ // TODO 濡傛灉涓虹┖锛寁ideo 鏈夐棶棰�
+ extension: _extname.length > 0 ? _extname : undefined,
+ count: this.limitLength - this.files.length, //榛樿9
+ onChooseFile: this.chooseFileCallback,
+ onUploadProgress: progressEvent => {
+ this.setProgress(progressEvent, progressEvent.index)
+ }
+ })
+ .then(result => {
+ this.setSuccessAndError(result.tempFiles)
+ })
+ .catch(err => {
+ console.log('閫夋嫨澶辫触', err)
+ })
+ },
+
+ /**
+ * 閫夋嫨鏂囦欢鍥炶皟
+ * @param {Object} res
+ */
+ async chooseFileCallback(res) {
+ const _extname = get_extname(this.fileExtname)
+ const is_one = (Number(this.limitLength) === 1 &&
+ this.disablePreview &&
+ !this.disabled) ||
+ this.returnType === 'object'
+ // 濡傛灉杩欐湁涓�涓枃浠� 锛岄渶瑕佹竻绌烘湰鍦扮紦瀛樻暟鎹�
+ if (is_one) {
+ this.files = []
+ }
+
+ let {
+ filePaths,
+ files
+ } = get_files_and_is_max(res, _extname)
+ if (!(_extname && _extname.length > 0)) {
+ filePaths = res.tempFilePaths
+ files = res.tempFiles
+ }
+
+ let currentData = []
+ for (let i = 0; i < files.length; i++) {
+ if (this.limitLength - this.files.length <= 0) break
+ files[i].uuid = Date.now()
+ let filedata = await get_file_data(files[i], this.fileMediatype)
+ filedata.progress = 0
+ filedata.status = 'ready'
+ this.files.push(filedata)
+ currentData.push({
+ ...filedata,
+ file: files[i]
+ })
+ }
+ this.$emit('select', {
+ tempFiles: currentData,
+ tempFilePaths: filePaths
+ })
+ res.tempFiles = files
+ // 鍋滄鑷姩涓婁紶
+ if (!this.autoUpload || this.noSpace) {
+ res.tempFiles = []
+ }
+ },
+
+ /**
+ * 鎵逛紶
+ * @param {Object} e
+ */
+ uploadFiles(files) {
+ files = [].concat(files)
+ return uploadCloudFiles.call(this, files, 5, res => {
+ this.setProgress(res, res.index, true)
+ })
+ .then(result => {
+ this.setSuccessAndError(result)
+ return result;
+ })
+ .catch(err => {
+ console.log(err)
+ })
+ },
+
+ /**
+ * 鎴愬姛鎴栧け璐�
+ */
+ async setSuccessAndError(res, fn) {
+ let successData = []
+ let errorData = []
+ let tempFilePath = []
+ let errorTempFilePath = []
+ for (let i = 0; i < res.length; i++) {
+ const item = res[i]
+ const index = item.uuid ? this.files.findIndex(p => p.uuid === item.uuid) : item.index
+
+ if (index === -1 || !this.files) break
+ if (item.errMsg === 'request:fail') {
+ this.files[index].url = item.path
+ this.files[index].status = 'error'
+ this.files[index].errMsg = item.errMsg
+ // this.files[index].progress = -1
+ errorData.push(this.files[index])
+ errorTempFilePath.push(this.files[index].url)
+ } else {
+ this.files[index].errMsg = ''
+ this.files[index].fileID = item.url
+ const reg = /cloud:\/\/([\w.]+\/?)\S*/
+ if (reg.test(item.url)) {
+ this.files[index].url = await this.getTempFileURL(item.url)
+ }else{
+ this.files[index].url = item.url
+ }
+
+ this.files[index].status = 'success'
+ this.files[index].progress += 1
+ successData.push(this.files[index])
+ tempFilePath.push(this.files[index].fileID)
+ }
+ }
+
+ if (successData.length > 0) {
+ this.setEmit()
+ // 鐘舵�佹敼鍙樿繑鍥�
+ this.$emit('success', {
+ tempFiles: this.backObject(successData),
+ tempFilePaths: tempFilePath
+ })
+ }
+
+ if (errorData.length > 0) {
+ this.$emit('fail', {
+ tempFiles: this.backObject(errorData),
+ tempFilePaths: errorTempFilePath
+ })
+ }
+ },
+
+ /**
+ * 鑾峰彇杩涘害
+ * @param {Object} progressEvent
+ * @param {Object} index
+ * @param {Object} type
+ */
+ setProgress(progressEvent, index, type) {
+ const fileLenth = this.files.length
+ const percentNum = (index / fileLenth) * 100
+ const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total)
+ let idx = index
+ if (!type) {
+ idx = this.files.findIndex(p => p.uuid === progressEvent.tempFile.uuid)
+ }
+ if (idx === -1 || !this.files[idx]) return
+ // fix by mehaotian 100 灏变細娑堝け锛�-1 鏄负浜嗚杩涘害鏉℃秷澶�
+ this.files[idx].progress = percentCompleted - 1
+ // 涓婁紶涓�
+ this.$emit('progress', {
+ index: idx,
+ progress: parseInt(percentCompleted),
+ tempFile: this.files[idx]
+ })
+ },
+
+ /**
+ * 鍒犻櫎鏂囦欢
+ * @param {Object} index
+ */
+ delFile(index) {
+ this.$emit('delete', {
+ tempFile: this.files[index],
+ tempFilePath: this.files[index].url
+ })
+ this.files.splice(index, 1)
+ this.$nextTick(() => {
+ this.setEmit()
+ })
+ },
+
+ /**
+ * 鑾峰彇鏂囦欢鍚嶅拰鍚庣紑
+ * @param {Object} name
+ */
+ getFileExt(name) {
+ const last_len = name.lastIndexOf('.')
+ const len = name.length
+ return {
+ name: name.substring(0, last_len),
+ ext: name.substring(last_len + 1, len)
+ }
+ },
+
+ /**
+ * 澶勭悊杩斿洖浜嬩欢
+ */
+ setEmit() {
+ let data = []
+ if (this.returnType === 'object') {
+ data = this.backObject(this.files)[0]
+ this.localValue = data?data:null
+ } else {
+ data = this.backObject(this.files)
+ if (!this.localValue) {
+ this.localValue = []
+ }
+ this.localValue = [...data]
+ }
+ // #ifdef VUE3
+ this.$emit('update:modelValue', this.localValue)
+ // #endif
+ // #ifndef VUE3
+ this.$emit('input', this.localValue)
+ // #endif
+ },
+
+ /**
+ * 澶勭悊杩斿洖鍙傛暟
+ * @param {Object} files
+ */
+ backObject(files) {
+ let newFilesData = []
+ files.forEach(v => {
+ newFilesData.push({
+ extname: v.extname,
+ fileType: v.fileType,
+ image: v.image,
+ name: v.name,
+ path: v.path,
+ size: v.size,
+ fileID:v.fileID,
+ url: v.url,
+ // 淇敼鍒犻櫎涓�涓枃浠跺悗涓嶈兘鍐嶄笂浼犵殑bug, #694
+ uuid: v.uuid,
+ status: v.status,
+ cloudPath: v.cloudPath
+ })
+ })
+ return newFilesData
+ },
+ async getTempFileURL(fileList) {
+ fileList = {
+ fileList: [].concat(fileList)
+ }
+ const urls = await uniCloud.getTempFileURL(fileList)
+ return urls.fileList[0].tempFileURL || ''
+ },
+ /**
+ * 鑾峰彇鐖跺厓绱犲疄渚�
+ */
+ getForm(name = 'uniForms') {
+ let parent = this.$parent;
+ let parentName = parent.$options.name;
+ while (parentName !== name) {
+ parent = parent.$parent;
+ if (!parent) return false;
+ parentName = parent.$options.name;
+ }
+ return parent;
+ }
+ }
+ }
+</script>
+
+<style>
+ .uni-file-picker {
+ /* #ifndef APP-NVUE */
+ box-sizing: border-box;
+ overflow: hidden;
+ width: 100%;
+ /* #endif */
+ flex: 1;
+ }
+
+ .uni-file-picker__header {
+ padding-top: 5px;
+ padding-bottom: 10px;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ justify-content: space-between;
+ }
+
+ .file-title {
+ font-size: 14px;
+ color: #333;
+ }
+
+ .file-count {
+ font-size: 14px;
+ color: #999;
+ }
+
+ .is-add {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ align-items: center;
+ justify-content: center;
+ }
+
+ .icon-add {
+ width: 50px;
+ height: 5px;
+ background-color: #f1f1f1;
+ border-radius: 2px;
+ }
+
+ .rotate {
+ position: absolute;
+ transform: rotate(90deg);
+ }
+</style>
diff --git a/app/uni_modules/uni-file-picker/components/uni-file-picker/upload-file.vue b/app/uni_modules/uni-file-picker/components/uni-file-picker/upload-file.vue
new file mode 100644
index 0000000..625d92e
--- /dev/null
+++ b/app/uni_modules/uni-file-picker/components/uni-file-picker/upload-file.vue
@@ -0,0 +1,325 @@
+<template>
+ <view class="uni-file-picker__files">
+ <view v-if="!readonly" class="files-button" @click="choose">
+ <slot></slot>
+ </view>
+ <!-- :class="{'is-text-box':showType === 'list'}" -->
+ <view v-if="list.length > 0" class="uni-file-picker__lists is-text-box" :style="borderStyle">
+ <!-- ,'is-list-card':showType === 'list-card' -->
+
+ <view class="uni-file-picker__lists-box" v-for="(item ,index) in list" :key="index" :class="{
+ 'files-border':index !== 0 && styles.dividline}"
+ :style="index !== 0 && styles.dividline &&borderLineStyle">
+ <view class="uni-file-picker__item">
+ <!-- :class="{'is-text-image':showType === 'list'}" -->
+ <!-- <view class="files__image is-text-image">
+ <image class="header-image" :src="item.logo" mode="aspectFit"></image>
+ </view> -->
+ <view class="files__name">{{item.name}}</view>
+ <view v-if="delIcon&&!readonly" class="icon-del-box icon-files" @click="delFile(index)">
+ <view class="icon-del icon-files"></view>
+ <view class="icon-del rotate"></view>
+ </view>
+ </view>
+ <view v-if="(item.progress && item.progress !== 100) ||item.progress===0 " class="file-picker__progress">
+ <progress class="file-picker__progress-item" :percent="item.progress === -1?0:item.progress" stroke-width="4"
+ :backgroundColor="item.errMsg?'#ff5a5f':'#EBEBEB'" />
+ </view>
+ <view v-if="item.status === 'error'" class="file-picker__mask" @click.stop="uploadFiles(item,index)">
+ 鐐瑰嚮閲嶈瘯
+ </view>
+ </view>
+
+ </view>
+ </view>
+</template>
+
+<script>
+ export default {
+ name: "uploadFile",
+ emits:['uploadFiles','choose','delFile'],
+ props: {
+ filesList: {
+ type: Array,
+ default () {
+ return []
+ }
+ },
+ delIcon: {
+ type: Boolean,
+ default: true
+ },
+ limit: {
+ type: [Number, String],
+ default: 9
+ },
+ showType: {
+ type: String,
+ default: ''
+ },
+ listStyles: {
+ type: Object,
+ default () {
+ return {
+ // 鏄惁鏄剧ず杈规
+ border: true,
+ // 鏄惁鏄剧ず鍒嗛殧绾�
+ dividline: true,
+ // 绾挎潯鏍峰紡
+ borderStyle: {}
+ }
+ }
+ },
+ readonly:{
+ type:Boolean,
+ default:false
+ }
+ },
+ computed: {
+ list() {
+ let files = []
+ this.filesList.forEach(v => {
+ files.push(v)
+ })
+ return files
+ },
+ styles() {
+ let styles = {
+ border: true,
+ dividline: true,
+ 'border-style': {}
+ }
+ return Object.assign(styles, this.listStyles)
+ },
+ borderStyle() {
+ let {
+ borderStyle,
+ border
+ } = this.styles
+ let obj = {}
+ if (!border) {
+ obj.border = 'none'
+ } else {
+ let width = (borderStyle && borderStyle.width) || 1
+ width = this.value2px(width)
+ let radius = (borderStyle && borderStyle.radius) || 5
+ radius = this.value2px(radius)
+ obj = {
+ 'border-width': width,
+ 'border-style': (borderStyle && borderStyle.style) || 'solid',
+ 'border-color': (borderStyle && borderStyle.color) || '#eee',
+ 'border-radius': radius
+ }
+ }
+ let classles = ''
+ for (let i in obj) {
+ classles += `${i}:${obj[i]};`
+ }
+ return classles
+ },
+ borderLineStyle() {
+ let obj = {}
+ let {
+ borderStyle
+ } = this.styles
+ if (borderStyle && borderStyle.color) {
+ obj['border-color'] = borderStyle.color
+ }
+ if (borderStyle && borderStyle.width) {
+ let width = borderStyle && borderStyle.width || 1
+ let style = borderStyle && borderStyle.style || 0
+ if (typeof width === 'number') {
+ width += 'px'
+ } else {
+ width = width.indexOf('px') ? width : width + 'px'
+ }
+ obj['border-width'] = width
+
+ if (typeof style === 'number') {
+ style += 'px'
+ } else {
+ style = style.indexOf('px') ? style : style + 'px'
+ }
+ obj['border-top-style'] = style
+ }
+ let classles = ''
+ for (let i in obj) {
+ classles += `${i}:${obj[i]};`
+ }
+ return classles
+ }
+ },
+
+ methods: {
+ uploadFiles(item, index) {
+ this.$emit("uploadFiles", {
+ item,
+ index
+ })
+ },
+ choose() {
+ this.$emit("choose")
+ },
+ delFile(index) {
+ this.$emit('delFile', index)
+ },
+ value2px(value) {
+ if (typeof value === 'number') {
+ value += 'px'
+ } else {
+ value = value.indexOf('px') !== -1 ? value : value + 'px'
+ }
+ return value
+ }
+ }
+ }
+</script>
+
+<style lang="scss">
+ .uni-file-picker__files {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: column;
+ justify-content: flex-start;
+ }
+
+ .files-button {
+ // border: 1px red solid;
+ }
+
+ .uni-file-picker__lists {
+ position: relative;
+ margin-top: 5px;
+ overflow: hidden;
+ }
+
+ .file-picker__mask {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ justify-content: center;
+ align-items: center;
+ position: absolute;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ color: #fff;
+ font-size: 14px;
+ background-color: rgba(0, 0, 0, 0.4);
+ }
+
+ .uni-file-picker__lists-box {
+ position: relative;
+ }
+
+ .uni-file-picker__item {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ align-items: center;
+ padding: 8px 10px;
+ padding-right: 5px;
+ padding-left: 10px;
+ }
+
+ .files-border {
+ border-top: 1px #eee solid;
+ }
+
+ .files__name {
+ flex: 1;
+ font-size: 14px;
+ color: #666;
+ margin-right: 25px;
+ /* #ifndef APP-NVUE */
+ word-break: break-all;
+ word-wrap: break-word;
+ /* #endif */
+ }
+
+ .icon-files {
+ /* #ifndef APP-NVUE */
+ position: static;
+ background-color: initial;
+ /* #endif */
+ }
+
+ // .icon-files .icon-del {
+ // background-color: #333;
+ // width: 12px;
+ // height: 1px;
+ // }
+
+
+ .is-list-card {
+ border: 1px #eee solid;
+ margin-bottom: 5px;
+ border-radius: 5px;
+ box-shadow: 0 0 2px 0px rgba(0, 0, 0, 0.1);
+ padding: 5px;
+ }
+
+ .files__image {
+ width: 40px;
+ height: 40px;
+ margin-right: 10px;
+ }
+
+ .header-image {
+ width: 100%;
+ height: 100%;
+ }
+
+ .is-text-box {
+ border: 1px #eee solid;
+ border-radius: 5px;
+ }
+
+ .is-text-image {
+ width: 25px;
+ height: 25px;
+ margin-left: 5px;
+ }
+
+ .rotate {
+ position: absolute;
+ transform: rotate(90deg);
+ }
+
+ .icon-del-box {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ margin: auto 0;
+ /* #endif */
+ align-items: center;
+ justify-content: center;
+ position: absolute;
+ top: 0px;
+ bottom: 0;
+ right: 5px;
+ height: 26px;
+ width: 26px;
+ // border-radius: 50%;
+ // background-color: rgba(0, 0, 0, 0.5);
+ z-index: 2;
+ transform: rotate(-45deg);
+ }
+
+ .icon-del {
+ width: 15px;
+ height: 1px;
+ background-color: #333;
+ // border-radius: 1px;
+ }
+
+ /* #ifdef H5 */
+ @media all and (min-width: 768px) {
+ .uni-file-picker__files {
+ max-width: 375px;
+ }
+ }
+
+ /* #endif */
+</style>
diff --git a/app/uni_modules/uni-file-picker/components/uni-file-picker/upload-image.vue b/app/uni_modules/uni-file-picker/components/uni-file-picker/upload-image.vue
new file mode 100644
index 0000000..2a29bc2
--- /dev/null
+++ b/app/uni_modules/uni-file-picker/components/uni-file-picker/upload-image.vue
@@ -0,0 +1,292 @@
+<template>
+ <view class="uni-file-picker__container">
+ <view class="file-picker__box" v-for="(item,index) in filesList" :key="index" :style="boxStyle">
+ <view class="file-picker__box-content" :style="borderStyle">
+ <image class="file-image" :src="item.url" mode="aspectFill" @click.stop="prviewImage(item,index)"></image>
+ <view v-if="delIcon && !readonly" class="icon-del-box" @click.stop="delFile(index)">
+ <view class="icon-del"></view>
+ <view class="icon-del rotate"></view>
+ </view>
+ <view v-if="(item.progress && item.progress !== 100) ||item.progress===0 " class="file-picker__progress">
+ <progress class="file-picker__progress-item" :percent="item.progress === -1?0:item.progress" stroke-width="4"
+ :backgroundColor="item.errMsg?'#ff5a5f':'#EBEBEB'" />
+ </view>
+ <view v-if="item.errMsg" class="file-picker__mask" @click.stop="uploadFiles(item,index)">
+ 鐐瑰嚮閲嶈瘯
+ </view>
+ </view>
+ </view>
+ <view v-if="filesList.length < limit && !readonly" class="file-picker__box" :style="boxStyle">
+ <view class="file-picker__box-content is-add" :style="borderStyle" @click="choose">
+ <slot>
+ <view class="icon-add"></view>
+ <view class="icon-add rotate"></view>
+ </slot>
+ </view>
+ </view>
+ </view>
+</template>
+
+<script>
+ export default {
+ name: "uploadImage",
+ emits:['uploadFiles','choose','delFile'],
+ props: {
+ filesList: {
+ type: Array,
+ default () {
+ return []
+ }
+ },
+ disabled:{
+ type: Boolean,
+ default: false
+ },
+ disablePreview: {
+ type: Boolean,
+ default: false
+ },
+ limit: {
+ type: [Number, String],
+ default: 9
+ },
+ imageStyles: {
+ type: Object,
+ default () {
+ return {
+ width: 'auto',
+ height: 'auto',
+ border: {}
+ }
+ }
+ },
+ delIcon: {
+ type: Boolean,
+ default: true
+ },
+ readonly:{
+ type:Boolean,
+ default:false
+ }
+ },
+ computed: {
+ styles() {
+ let styles = {
+ width: 'auto',
+ height: 'auto',
+ border: {}
+ }
+ return Object.assign(styles, this.imageStyles)
+ },
+ boxStyle() {
+ const {
+ width = 'auto',
+ height = 'auto'
+ } = this.styles
+ let obj = {}
+ if (height === 'auto') {
+ if (width !== 'auto') {
+ obj.height = this.value2px(width)
+ obj['padding-top'] = 0
+ } else {
+ obj.height = 0
+ }
+ } else {
+ obj.height = this.value2px(height)
+ obj['padding-top'] = 0
+ }
+
+ if (width === 'auto') {
+ if (height !== 'auto') {
+ obj.width = this.value2px(height)
+ } else {
+ obj.width = '33.3%'
+ }
+ } else {
+ obj.width = this.value2px(width)
+ }
+
+ let classles = ''
+ for(let i in obj){
+ classles+= `${i}:${obj[i]};`
+ }
+ return classles
+ },
+ borderStyle() {
+ let {
+ border
+ } = this.styles
+ let obj = {}
+ const widthDefaultValue = 1
+ const radiusDefaultValue = 3
+ if (typeof border === 'boolean') {
+ obj.border = border ? '1px #eee solid' : 'none'
+ } else {
+ let width = (border && border.width) || widthDefaultValue
+ width = this.value2px(width)
+ let radius = (border && border.radius) || radiusDefaultValue
+ radius = this.value2px(radius)
+ obj = {
+ 'border-width': width,
+ 'border-style': (border && border.style) || 'solid',
+ 'border-color': (border && border.color) || '#eee',
+ 'border-radius': radius
+ }
+ }
+ let classles = ''
+ for(let i in obj){
+ classles+= `${i}:${obj[i]};`
+ }
+ return classles
+ }
+ },
+ methods: {
+ uploadFiles(item, index) {
+ this.$emit("uploadFiles", item)
+ },
+ choose() {
+ this.$emit("choose")
+ },
+ delFile(index) {
+ this.$emit('delFile', index)
+ },
+ prviewImage(img, index) {
+ let urls = []
+ if(Number(this.limit) === 1&&this.disablePreview&&!this.disabled){
+ this.$emit("choose")
+ }
+ if(this.disablePreview) return
+ this.filesList.forEach(i => {
+ urls.push(i.url)
+ })
+
+ uni.previewImage({
+ urls: urls,
+ current: index
+ });
+ },
+ value2px(value) {
+ if (typeof value === 'number') {
+ value += 'px'
+ } else {
+ if (value.indexOf('%') === -1) {
+ value = value.indexOf('px') !== -1 ? value : value + 'px'
+ }
+ }
+ return value
+ }
+ }
+ }
+</script>
+
+<style lang="scss">
+ .uni-file-picker__container {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ box-sizing: border-box;
+ /* #endif */
+ flex-wrap: wrap;
+ margin: -5px;
+ }
+
+ .file-picker__box {
+ position: relative;
+ // flex: 0 0 33.3%;
+ width: 33.3%;
+ height: 0;
+ padding-top: 33.33%;
+ /* #ifndef APP-NVUE */
+ box-sizing: border-box;
+ /* #endif */
+ }
+
+ .file-picker__box-content {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ margin: 5px;
+ border: 1px #eee solid;
+ border-radius: 5px;
+ overflow: hidden;
+ }
+
+ .file-picker__progress {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ /* border: 1px red solid; */
+ z-index: 2;
+ }
+
+ .file-picker__progress-item {
+ width: 100%;
+ }
+
+ .file-picker__mask {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ justify-content: center;
+ align-items: center;
+ position: absolute;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ color: #fff;
+ font-size: 12px;
+ background-color: rgba(0, 0, 0, 0.4);
+ }
+
+ .file-image {
+ width: 100%;
+ height: 100%;
+ }
+
+ .is-add {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ align-items: center;
+ justify-content: center;
+ }
+
+ .icon-add {
+ width: 50px;
+ height: 5px;
+ background-color: #f1f1f1;
+ border-radius: 2px;
+ }
+
+ .rotate {
+ position: absolute;
+ transform: rotate(90deg);
+ }
+
+ .icon-del-box {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ align-items: center;
+ justify-content: center;
+ position: absolute;
+ top: 3px;
+ right: 3px;
+ height: 26px;
+ width: 26px;
+ border-radius: 50%;
+ background-color: rgba(0, 0, 0, 0.5);
+ z-index: 2;
+ transform: rotate(-45deg);
+ }
+
+ .icon-del {
+ width: 15px;
+ height: 2px;
+ background-color: #fff;
+ border-radius: 2px;
+ }
+</style>
diff --git a/app/uni_modules/uni-file-picker/components/uni-file-picker/utils.js b/app/uni_modules/uni-file-picker/components/uni-file-picker/utils.js
new file mode 100644
index 0000000..60aaa3e
--- /dev/null
+++ b/app/uni_modules/uni-file-picker/components/uni-file-picker/utils.js
@@ -0,0 +1,109 @@
+/**
+ * 鑾峰彇鏂囦欢鍚嶅拰鍚庣紑
+ * @param {String} name
+ */
+export const get_file_ext = (name) => {
+ const last_len = name.lastIndexOf('.')
+ const len = name.length
+ return {
+ name: name.substring(0, last_len),
+ ext: name.substring(last_len + 1, len)
+ }
+}
+
+/**
+ * 鑾峰彇鎵╁睍鍚�
+ * @param {Array} fileExtname
+ */
+export const get_extname = (fileExtname) => {
+ if (!Array.isArray(fileExtname)) {
+ let extname = fileExtname.replace(/(\[|\])/g, '')
+ return extname.split(',')
+ } else {
+ return fileExtname
+ }
+ return []
+}
+
+/**
+ * 鑾峰彇鏂囦欢鍜屾娴嬫槸鍚﹀彲閫�
+ */
+export const get_files_and_is_max = (res, _extname) => {
+ let filePaths = []
+ let files = []
+ if(!_extname || _extname.length === 0){
+ return {
+ filePaths,
+ files
+ }
+ }
+ res.tempFiles.forEach(v => {
+ let fileFullName = get_file_ext(v.name)
+ const extname = fileFullName.ext.toLowerCase()
+ if (_extname.indexOf(extname) !== -1) {
+ files.push(v)
+ filePaths.push(v.path)
+ }
+ })
+ if (files.length !== res.tempFiles.length) {
+ uni.showToast({
+ title: `褰撳墠閫夋嫨浜�${res.tempFiles.length}涓枃浠� 锛�${res.tempFiles.length - files.length} 涓枃浠舵牸寮忎笉姝g‘`,
+ icon: 'none',
+ duration: 5000
+ })
+ }
+
+ return {
+ filePaths,
+ files
+ }
+}
+
+
+/**
+ * 鑾峰彇鍥剧墖淇℃伅
+ * @param {Object} filepath
+ */
+export const get_file_info = (filepath) => {
+ return new Promise((resolve, reject) => {
+ uni.getImageInfo({
+ src: filepath,
+ success(res) {
+ resolve(res)
+ },
+ fail(err) {
+ reject(err)
+ }
+ })
+ })
+}
+/**
+ * 鑾峰彇灏佽鏁版嵁
+ */
+export const get_file_data = async (files, type = 'image') => {
+ // 鏈�缁堥渶瑕佷笂浼犳暟鎹簱鐨勬暟鎹�
+ let fileFullName = get_file_ext(files.name)
+ const extname = fileFullName.ext.toLowerCase()
+ let filedata = {
+ name: files.name,
+ uuid: files.uuid,
+ extname: extname || '',
+ cloudPath: files.cloudPath,
+ fileType: files.fileType,
+ url: files.path || files.path,
+ size: files.size, //鍗曚綅鏄瓧鑺�
+ image: {},
+ path: files.path,
+ video: {}
+ }
+ if (type === 'image') {
+ const imageinfo = await get_file_info(files.path)
+ delete filedata.video
+ filedata.image.width = imageinfo.width
+ filedata.image.height = imageinfo.height
+ filedata.image.location = imageinfo.path
+ } else {
+ delete filedata.image
+ }
+ return filedata
+}
diff --git a/app/uni_modules/uni-file-picker/package.json b/app/uni_modules/uni-file-picker/package.json
new file mode 100644
index 0000000..35c926c
--- /dev/null
+++ b/app/uni_modules/uni-file-picker/package.json
@@ -0,0 +1,83 @@
+{
+ "id": "uni-file-picker",
+ "displayName": "uni-file-picker 鏂囦欢閫夋嫨涓婁紶",
+ "version": "1.0.4",
+ "description": "鏂囦欢閫夋嫨涓婁紶缁勪欢锛屽彲浠ラ�夋嫨鍥剧墖銆佽棰戠瓑浠绘剰鏂囦欢骞朵笂浼犲埌褰撳墠缁戝畾鐨勬湇鍔$┖闂�",
+ "keywords": [
+ "uni-ui",
+ "uniui",
+ "鍥剧墖涓婁紶",
+ "鏂囦欢涓婁紶"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+"dcloudext": {
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+ "type": "component-vue"
+ },
+ "uni_modules": {
+ "dependencies": ["uni-scss"],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "n"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "u",
+ "鑱旂洘": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
diff --git a/app/uni_modules/uni-file-picker/readme.md b/app/uni_modules/uni-file-picker/readme.md
new file mode 100644
index 0000000..c8399a5
--- /dev/null
+++ b/app/uni_modules/uni-file-picker/readme.md
@@ -0,0 +1,11 @@
+
+## FilePicker 鏂囦欢閫夋嫨涓婁紶
+
+> **缁勪欢鍚嶏細uni-file-picker**
+> 浠g爜鍧楋細 `uFilePicker`
+
+
+鏂囦欢閫夋嫨涓婁紶缁勪欢锛屽彲浠ラ�夋嫨鍥剧墖銆佽棰戠瓑浠绘剰鏂囦欢骞朵笂浼犲埌褰撳墠缁戝畾鐨勬湇鍔$┖闂�
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-file-picker)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
\ No newline at end of file
diff --git a/app/uni_modules/uni-forms/changelog.md b/app/uni_modules/uni-forms/changelog.md
new file mode 100644
index 0000000..8218df5
--- /dev/null
+++ b/app/uni_modules/uni-forms/changelog.md
@@ -0,0 +1,92 @@
+## 1.4.9锛�2023-02-10锛�
+- 淇 required 鍙傛暟鏃犳硶鍔ㄦ�佺粦瀹�
+## 1.4.8锛�2022-08-23锛�
+- 浼樺寲 鏍规嵁 rules 鑷姩娣诲姞 required 鐨勯棶棰�
+## 1.4.7锛�2022-08-22锛�
+- 淇 item 鏈缃� require 灞炴�э紝rules 璁剧疆 require 鍚庯紝鏄熷彿涔熸樉绀虹殑 bug锛岃瑙侊細[https://ask.dcloud.net.cn/question/151540](https://ask.dcloud.net.cn/question/151540)
+## 1.4.6锛�2022-07-13锛�
+- 淇 model 闇�瑕佹牎楠岀殑鍊兼病鏈夊0鏄庡搴斿瓧娈垫椂锛屽鑷寸涓�娆′笉瑙﹀彂鏍¢獙鐨刡ug
+## 1.4.5锛�2022-07-05锛�
+- 鏂板 鏇村琛ㄥ崟绀轰緥
+- 浼樺寲 瀛愯〃鍗曠粍浠惰繃鏈熸彁绀虹殑闂
+- 浼樺寲 瀛愯〃鍗曠粍浠秛ni-datetime-picker銆乽ni-data-select銆乽ni-data-picker鐨勬樉绀烘牱寮�
+## 1.4.4锛�2022-07-04锛�
+- 鏇存柊 鍒犻櫎缁勪欢鏃ュ織
+## 1.4.3锛�2022-07-04锛�
+- 淇 鐢� 1.4.0 寮曞彂鐨� label 鎻掓Ы涓嶇敓鏁堢殑bug
+## 1.4.2锛�2022-07-04锛�
+- 淇 瀛愮粍浠舵壘涓嶅埌 setValue 鎶ラ敊鐨刡ug
+## 1.4.1锛�2022-07-04锛�
+- 淇 uni-data-picker 鍦� uni-forms-item 涓姤閿欑殑bug
+- 淇 uni-data-picker 鍦� uni-forms-item 涓搴︿笉姝g‘鐨刡ug
+## 1.4.0锛�2022-06-30锛�
+- 銆愰噸瑕併�戠粍浠堕�昏緫閲嶆瀯锛岄儴鍒嗙敤娉曠敤鏃х増鏈笉鍏煎锛岃娉ㄦ剰鍏煎闂
+- 銆愰噸瑕併�戠粍浠朵娇鐢� Provide/Inject 鏂瑰紡娉ㄥ叆渚濊禆锛屾彁渚涗簡鑷畾涔夎〃鍗曠粍浠惰皟鐢� uni-forms 鏍¢獙琛ㄥ崟鐨勮兘鍔�
+- 鏂板 model 灞炴�э紝绛夊悓浜庡師 value/modelValue 灞炴�э紝鏃у睘鎬у嵆灏嗗簾寮�
+- 鏂板 validateTrigger 灞炴�х殑 blur 鍊硷紝浠� uni-easyinput 鐢熸晥
+- 鏂板 onFieldChange 鏂规硶锛屽彲浠ュ瀛愯〃鍗曡繘琛屾牎楠岋紝鍙浛浠inddata鏂规硶
+- 鏂板 瀛愯〃鍗曠殑 setRules 鏂规硶锛岄厤鍚堣嚜瀹氫箟鏍¢獙鍑芥暟浣跨敤
+- 鏂板 uni-forms-item 鐨� setRules 鏂规硶锛岄厤缃姩鎬佽〃鍗曚娇鐢ㄥ彲鍔ㄦ�佹洿鏂版牎楠岃鍒�
+- 浼樺寲 鍔ㄦ�佽〃鍗曟牎楠屾柟寮忥紝搴熷純鎷兼帴name鐨勬柟寮�
+## 1.3.3锛�2022-06-22锛�
+- 淇 琛ㄥ崟鏍¢獙椤哄簭鏃犲簭闂
+## 1.3.2锛�2021-12-09锛�
+-
+## 1.3.1锛�2021-11-19锛�
+- 淇 label 鎻掓Ы涓嶇敓鏁堢殑bug
+## 1.3.0锛�2021-11-19锛�
+- 浼樺寲 缁勪欢UI锛屽苟鎻愪緵璁捐璧勬簮锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 鏂囨。杩佺Щ锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/uni-forms](https://uniapp.dcloud.io/component/uniui/uni-forms)
+## 1.2.7锛�2021-08-13锛�
+- 淇 娌℃湁娣诲姞鏍¢獙瑙勫垯鐨勫瓧娈典緷鐒舵姤閿欑殑Bug
+## 1.2.6锛�2021-08-11锛�
+- 淇 閲嶇疆琛ㄥ崟閿欒淇℃伅鏃犳硶娓呴櫎鐨勯棶棰�
+## 1.2.5锛�2021-08-11锛�
+- 浼樺寲 缁勪欢鏂囨。
+## 1.2.4锛�2021-08-11锛�
+- 淇 琛ㄥ崟楠岃瘉鍙敓鏁堜竴娆$殑闂
+## 1.2.3锛�2021-07-30锛�
+- 浼樺寲 vue3涓嬩簨浠惰鍛婄殑闂
+## 1.2.2锛�2021-07-26锛�
+- 淇 vue2 涓嬫潯浠剁紪璇戝鑷磀estroyed鐢熷懡鍛ㄦ湡澶辨晥鐨凚ug
+- 淇 1.2.1 寮曡捣鐨勭ず渚嬪湪灏忕▼搴忓钩鍙版姤閿欑殑Bug
+## 1.2.1锛�2021-07-22锛�
+- 淇 鍔ㄦ�佹牎楠岃〃鍗曪紝榛樿鍊间负绌虹殑鎯呭喌涓嬫牎楠屽け鏁堢殑Bug
+- 淇 涓嶆寚瀹歯ame灞炴�ф椂锛岃繍琛屾姤閿欑殑Bug
+- 浼樺寲 label榛樿瀹藉害浠�65璋冩暣鑷�70锛屼娇required涓簍rue涓斿洓瀛楁椂涓嶆崲琛�
+- 浼樺寲 缁勪欢绀轰緥锛屾柊澧炲姩鎬佹牎楠岀ず渚嬩唬鐮�
+- 浼樺寲 缁勪欢鏂囨。锛屼娇鐢ㄦ柟寮忔洿娓呮櫚
+## 1.2.0锛�2021-07-13锛�
+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤簐ue3椤圭洰锛岃瑙� [uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+## 1.1.2锛�2021-06-25锛�
+- 淇 pattern 灞炴�у湪寰俊灏忕▼搴忓钩鍙版棤鏁堢殑闂
+## 1.1.1锛�2021-06-22锛�
+- 淇 validate-trigger灞炴�т负submit涓攅rr-show-type灞炴�т负toast鏃朵笉鑳藉脊鍑虹殑Bug
+## 1.1.0锛�2021-06-22锛�
+- 淇 鍙啓setRules鏂规硶鑰屽鑷存牎楠屼笉鐢熸晥鐨凚ug
+- 淇 鐢变笂涓姙娉曞紩鍙戠殑閿欒鎻愮ず鏂囧瓧閿欎綅鐨凚ug
+## 1.0.48锛�2021-06-21锛�
+- 淇 涓嶈缃� label 灞炴�� 锛屾棤娉曡缃甽abel鎻掓Ы鐨勯棶棰�
+## 1.0.47锛�2021-06-21锛�
+- 淇 涓嶈缃甽abel灞炴�э紝label-width灞炴�т笉鐢熸晥鐨刡ug
+- 淇 setRules 鏂规硶涓巖ules灞炴�у啿绐佺殑闂
+## 1.0.46锛�2021-06-04锛�
+- 淇 鍔ㄦ�佸垹鍑忔暟鎹鑷存姤閿欑殑闂
+## 1.0.45锛�2021-06-04锛�
+- 鏂板 modelValue 灞炴�� 锛寁alue 鍗冲皢搴熷純
+## 1.0.44锛�2021-06-02锛�
+- 鏂板 uni-forms-item 鍙互璁剧疆鍗曠嫭鐨� rules
+- 鏂板 validate 浜嬩欢澧炲姞 keepitem 鍙傛暟锛屽彲浠ラ�夋嫨閭d簺瀛楁涓嶈繃婊�
+- 浼樺寲 submit 浜嬩欢閲嶅懡鍚嶄负 validate
+## 1.0.43锛�2021-05-12锛�
+- 鏂板 缁勪欢绀轰緥鍦板潃
+## 1.0.42锛�2021-04-30锛�
+- 淇 鑷畾涔夋楠屽櫒澶辨晥鐨勯棶棰�
+## 1.0.41锛�2021-03-05锛�
+- 鏇存柊 鏍¢獙鍣�
+- 淇 琛ㄥ崟瑙勫垯璁剧疆绫诲瀷涓� number 鐨勬儏鍐典笅锛屽�间负0鏍¢獙澶辫触鐨凚ug
+## 1.0.40锛�2021-03-04锛�
+- 淇 鍔ㄦ�佹樉绀簎ni-forms-item鐨勬儏鍐典笅锛宻ubmit 鏂规硶鑾峰彇鍊奸敊璇殑Bug
+## 1.0.39锛�2021-02-05锛�
+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
+- 淇 鏍¢獙鍣ㄤ紶鍏� int 绛夌被鍨� 锛岃繑鍥濻tring绫诲瀷鐨凚ug
diff --git a/app/uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue b/app/uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue
new file mode 100644
index 0000000..91fe351
--- /dev/null
+++ b/app/uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue
@@ -0,0 +1,627 @@
+<template>
+ <view class="uni-forms-item"
+ :class="['is-direction-' + localLabelPos ,border?'uni-forms-item--border':'' ,border && isFirstBorder?'is-first-border':'']">
+ <slot name="label">
+ <view class="uni-forms-item__label" :class="{'no-label':!label && !required}"
+ :style="{width:localLabelWidth,justifyContent: localLabelAlign}">
+ <text v-if="required" class="is-required">*</text>
+ <text>{{label}}</text>
+ </view>
+ </slot>
+ <!-- #ifndef APP-NVUE -->
+ <view class="uni-forms-item__content">
+ <slot></slot>
+ <view class="uni-forms-item__error" :class="{'msg--active':msg}">
+ <text>{{msg}}</text>
+ </view>
+ </view>
+ <!-- #endif -->
+ <!-- #ifdef APP-NVUE -->
+ <view class="uni-forms-item__nuve-content">
+ <view class="uni-forms-item__content">
+ <slot></slot>
+ </view>
+ <view class="uni-forms-item__error" :class="{'msg--active':msg}">
+ <text class="error-text">{{msg}}</text>
+ </view>
+ </view>
+ <!-- #endif -->
+ </view>
+</template>
+
+<script>
+ /**
+ * uni-fomrs-item 琛ㄥ崟瀛愮粍浠�
+ * @description uni-fomrs-item 琛ㄥ崟瀛愮粍浠讹紝鎻愪緵浜嗗熀纭�甯冨眬宸茬粡鏍¢獙鑳藉姏
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=2773
+ * @property {Boolean} required 鏄惁蹇呭~锛屽乏杈规樉绀虹孩鑹�"*"鍙�
+ * @property {String } label 杈撳叆妗嗗乏杈圭殑鏂囧瓧鎻愮ず
+ * @property {Number } labelWidth label鐨勫搴︼紝鍗曚綅px锛堥粯璁�65锛�
+ * @property {String } labelAlign = [left|center|right] label鐨勬枃瀛楀榻愭柟寮忥紙榛樿left锛�
+ * @value left label 宸︿晶鏄剧ず
+ * @value center label 灞呬腑
+ * @value right label 鍙充晶瀵归綈
+ * @property {String } errorMessage 鏄剧ず鐨勯敊璇彁绀哄唴瀹癸紝濡傛灉涓虹┖瀛楃涓叉垨鑰協alse锛屽垯涓嶆樉绀洪敊璇俊鎭�
+ * @property {String } name 琛ㄥ崟鍩熺殑灞炴�у悕锛屽湪浣跨敤鏍¢獙瑙勫垯鏃跺繀濉�
+ * @property {String } leftIcon 銆�1.4.0搴熷純銆憀abel宸﹁竟鐨勫浘鏍囷紝闄� uni-ui 鐨勫浘鏍囧悕绉�
+ * @property {String } iconColor 銆�1.4.0搴熷純銆戝乏杈归�氳繃icon閰嶇疆鐨勫浘鏍囩殑棰滆壊锛堥粯璁�#606266锛�
+ * @property {String} validateTrigger = [bind|submit|blur] 銆�1.4.0搴熷純銆戞牎楠岃Е鍙戝櫒鏂瑰紡 榛樿 submit
+ * @value bind 鍙戠敓鍙樺寲鏃惰Е鍙�
+ * @value submit 鎻愪氦鏃惰Е鍙�
+ * @value blur 澶卞幓鐒︾偣瑙﹀彂
+ * @property {String } labelPosition = [top|left] 銆�1.4.0搴熷純銆憀abel鐨勬枃瀛楃殑浣嶇疆锛堥粯璁eft锛�
+ * @value top 椤堕儴鏄剧ず label
+ * @value left 宸︿晶鏄剧ず label
+ */
+
+ export default {
+ name: 'uniFormsItem',
+ options: {
+ virtualHost: true
+ },
+ provide() {
+ return {
+ uniFormItem: this
+ }
+ },
+ inject: {
+ form: {
+ from: 'uniForm',
+ default: null
+ },
+ },
+ props: {
+ // 琛ㄥ崟鏍¢獙瑙勫垯
+ rules: {
+ type: Array,
+ default () {
+ return null;
+ }
+ },
+ // 琛ㄥ崟鍩熺殑灞炴�у悕锛屽湪浣跨敤鏍¢獙瑙勫垯鏃跺繀濉�
+ name: {
+ type: [String, Array],
+ default: ''
+ },
+ required: {
+ type: Boolean,
+ default: false
+ },
+ label: {
+ type: String,
+ default: ''
+ },
+ // label鐨勫搴� 锛岄粯璁� 80
+ labelWidth: {
+ type: [String, Number],
+ default: ''
+ },
+ // label 灞呬腑鏂瑰紡锛岄粯璁� left 鍙栧�� left/center/right
+ labelAlign: {
+ type: String,
+ default: ''
+ },
+ // 寮哄埗鏄剧ず閿欒淇℃伅
+ errorMessage: {
+ type: [String, Boolean],
+ default: ''
+ },
+ // 1.4.0 寮冪敤锛岀粺涓�浣跨敤 form 鐨勬牎楠屾椂鏈�
+ // validateTrigger: {
+ // type: String,
+ // default: ''
+ // },
+ // 1.4.0 寮冪敤锛岀粺涓�浣跨敤 form 鐨刲abel 浣嶇疆
+ // labelPosition: {
+ // type: String,
+ // default: ''
+ // },
+ // 1.4.0 浠ヤ笅灞炴�у凡缁忓簾寮冿紝璇蜂娇鐢� #label 鎻掓Ы浠f浛
+ leftIcon: String,
+ iconColor: {
+ type: String,
+ default: '#606266'
+ },
+ },
+ data() {
+ return {
+ errMsg: '',
+ userRules: null,
+ localLabelAlign: 'left',
+ localLabelWidth: '65px',
+ localLabelPos: 'left',
+ border: false,
+ isFirstBorder: false,
+ };
+ },
+ computed: {
+ // 澶勭悊閿欒淇℃伅
+ msg() {
+ return this.errorMessage || this.errMsg;
+ }
+ },
+ watch: {
+ // 瑙勫垯鍙戠敓鍙樺寲閫氱煡瀛愮粍浠舵洿鏂�
+ 'form.formRules'(val) {
+ // TODO 澶勭悊澶存潯vue3 watch涓嶇敓鏁堢殑闂
+ // #ifndef MP-TOUTIAO
+ this.init()
+ // #endif
+ },
+ 'form.labelWidth'(val) {
+ // 瀹藉害
+ this.localLabelWidth = this._labelWidthUnit(val)
+
+ },
+ 'form.labelPosition'(val) {
+ // 鏍囩浣嶇疆
+ this.localLabelPos = this._labelPosition()
+ },
+ 'form.labelAlign'(val) {
+
+ }
+ },
+ created() {
+ this.init(true)
+ if (this.name && this.form) {
+ // TODO 澶勭悊澶存潯vue3 watch涓嶇敓鏁堢殑闂
+ // #ifdef MP-TOUTIAO
+ this.$watch('form.formRules', () => {
+ this.init()
+ })
+ // #endif
+
+ // 鐩戝惉鍙樺寲
+ this.$watch(
+ () => {
+ const val = this.form._getDataValue(this.name, this.form.localData)
+ return val
+ },
+ (value, oldVal) => {
+ const isEqual = this.form._isEqual(value, oldVal)
+ // 绠�鍗曞垽鏂墠鍚庡�肩殑鍙樺寲锛屽彧鏈夊彂鐢熷彉鍖栨墠浼氬彂鐢熸牎楠�
+ // TODO 濡傛灉 oldVal = undefined 锛岄偅涔堝ぇ姒傜巼鏄簮鏁版嵁閲屾病鏈夊�煎鑷� 锛岃繖涓儏鍐典笉鍝︽牎楠� ,鍙兘涓嶄弗璋� 锛岄渶瑕佸湪鍋氳瀵�
+ // fix by mehaotian 鏆傛椂鍙栨秷 && oldVal !== undefined 锛屽鏋渇ormData 涓笉瀛樺湪锛屽彲鑳戒細涓嶆牎楠�
+ if (!isEqual) {
+ const val = this.itemSetValue(value)
+ this.onFieldChange(val, false)
+ }
+ }, {
+ immediate: false
+ }
+ );
+ }
+
+ },
+ // #ifndef VUE3
+ destroyed() {
+ if (this.__isUnmounted) return
+ this.unInit()
+ },
+ // #endif
+ // #ifdef VUE3
+ unmounted() {
+ this.__isUnmounted = true
+ this.unInit()
+ },
+ // #endif
+ methods: {
+ /**
+ * 澶栭儴璋冪敤鏂规硶
+ * 璁剧疆瑙勫垯 锛屼富瑕佺敤浜庡皬绋嬪簭鑷畾涔夋楠岃鍒�
+ * @param {Array} rules 瑙勫垯婧愭暟鎹�
+ */
+ setRules(rules = null) {
+ this.userRules = rules
+ this.init(false)
+ },
+ // 鍏煎鑰佺増鏈〃鍗曠粍浠�
+ setValue() {
+ // console.log('setValue 鏂规硶宸茬粡寮冪敤锛岃浣跨敤鏈�鏂扮増鏈殑 uni-forms 琛ㄥ崟缁勪欢浠ュ強鍏朵粬鍏宠仈缁勪欢銆�');
+ },
+ /**
+ * 澶栭儴璋冪敤鏂规硶
+ * 鏍¢獙鏁版嵁
+ * @param {any} value 闇�瑕佹牎楠岀殑鏁版嵁
+ * @param {boolean} 鏄惁绔嬪嵆鏍¢獙
+ * @return {Array|null} 鏍¢獙鍐呭
+ */
+ async onFieldChange(value, formtrigger = true) {
+ const {
+ formData,
+ localData,
+ errShowType,
+ validateCheck,
+ validateTrigger,
+ _isRequiredField,
+ _realName
+ } = this.form
+ const name = _realName(this.name)
+ if (!value) {
+ value = this.form.formData[name]
+ }
+ // fixd by mehaotian 涓嶅湪鏍¢獙鍓嶆竻绌轰俊鎭紝瑙e喅闂睆鐨勯棶棰�
+ // this.errMsg = '';
+
+ // fix by mehaotian 瑙e喅娌℃湁妫�楠岃鍒欑殑鎯呭喌涓嬶紝鎶涘嚭閿欒鐨勯棶棰�
+ const ruleLen = this.itemRules.rules && this.itemRules.rules.length
+ if (!this.validator || !ruleLen || ruleLen === 0) return;
+
+ // 妫�楠屾椂鏈�
+ // let trigger = this.isTrigger(this.itemRules.validateTrigger, this.validateTrigger, validateTrigger);
+ const isRequiredField = _isRequiredField(this.itemRules.rules || []);
+ let result = null;
+ // 鍙湁绛変簬 bind 鏃� 锛屾墠鑳藉紑鍚椂瀹炴牎楠�
+ if (validateTrigger === 'bind' || formtrigger) {
+ // 鏍¢獙褰撳墠琛ㄥ崟椤�
+ result = await this.validator.validateUpdate({
+ [name]: value
+ },
+ formData
+ );
+
+ // 鍒ゆ柇鏄惁蹇呭~,闈炲繀濉紝涓嶅~涓嶆牎楠岋紝濉啓鎵嶆牎楠� ,鏆傛椂鍙鐞� undefined 鍜岀┖鐨勬儏鍐�
+ if (!isRequiredField && (value === undefined || value === '')) {
+ result = null;
+ }
+
+ // 鍒ゆ柇閿欒淇℃伅鏄剧ず绫诲瀷
+ if (result && result.errorMessage) {
+ if (errShowType === 'undertext') {
+ // 鑾峰彇閿欒淇℃伅
+ this.errMsg = !result ? '' : result.errorMessage;
+ }
+ if (errShowType === 'toast') {
+ uni.showToast({
+ title: result.errorMessage || '鏍¢獙閿欒',
+ icon: 'none'
+ });
+ }
+ if (errShowType === 'modal') {
+ uni.showModal({
+ title: '鎻愮ず',
+ content: result.errorMessage || '鏍¢獙閿欒'
+ });
+ }
+ } else {
+ this.errMsg = ''
+ }
+ // 閫氱煡 form 缁勪欢鏇存柊浜嬩欢
+ validateCheck(result ? result : null)
+ } else {
+ this.errMsg = ''
+ }
+ return result ? result : null;
+ },
+ /**
+ * 鍒濆缁勪欢鏁版嵁
+ */
+ init(type = false) {
+ const {
+ validator,
+ formRules,
+ childrens,
+ formData,
+ localData,
+ _realName,
+ labelWidth,
+ _getDataValue,
+ _setDataValue
+ } = this.form || {}
+ // 瀵归綈鏂瑰紡
+ this.localLabelAlign = this._justifyContent()
+ // 瀹藉害
+ this.localLabelWidth = this._labelWidthUnit(labelWidth)
+ // 鏍囩浣嶇疆
+ this.localLabelPos = this._labelPosition()
+ // 灏嗛渶瑕佹牎楠岀殑瀛愮粍浠跺姞鍏orm 闃熷垪
+ this.form && type && childrens.push(this)
+
+ if (!validator || !formRules) return
+ // 鍒ゆ柇绗竴涓� item
+ if (!this.form.isFirstBorder) {
+ this.form.isFirstBorder = true;
+ this.isFirstBorder = true;
+ }
+
+ // 鍒ゆ柇 group 閲岀殑绗竴涓� item
+ if (this.group) {
+ if (!this.group.isFirstBorder) {
+ this.group.isFirstBorder = true;
+ this.isFirstBorder = true;
+ }
+ }
+ this.border = this.form.border;
+ // 鑾峰彇瀛愬煙鐨勭湡瀹炲悕绉�
+ const name = _realName(this.name)
+ const itemRule = this.userRules || this.rules
+ if (typeof formRules === 'object' && itemRule) {
+ // 瀛愯鍒欐浛鎹㈢埗瑙勫垯
+ formRules[name] = {
+ rules: itemRule
+ }
+ validator.updateSchema(formRules);
+ }
+ // 娉ㄥ唽鏍¢獙瑙勫垯
+ const itemRules = formRules[name] || {}
+ this.itemRules = itemRules
+ // 娉ㄥ唽鏍¢獙鍑芥暟
+ this.validator = validator
+ // 榛樿鍊艰祴浜�
+ this.itemSetValue(_getDataValue(this.name, localData))
+ },
+ unInit() {
+ if (this.form) {
+ const {
+ childrens,
+ formData,
+ _realName
+ } = this.form
+ childrens.forEach((item, index) => {
+ if (item === this) {
+ this.form.childrens.splice(index, 1)
+ delete formData[_realName(item.name)]
+ }
+ })
+ }
+ },
+ // 璁剧疆item 鐨勫��
+ itemSetValue(value) {
+ const name = this.form._realName(this.name)
+ const rules = this.itemRules.rules || []
+ const val = this.form._getValue(name, value, rules)
+ this.form._setDataValue(name, this.form.formData, val)
+ return val
+ },
+
+ /**
+ * 绉婚櫎璇ヨ〃鍗曢」鐨勬牎楠岀粨鏋�
+ */
+ clearValidate() {
+ this.errMsg = '';
+ },
+
+ // 鏄惁鏄剧ず鏄熷彿
+ _isRequired() {
+ // TODO 涓嶆牴鎹鍒欐樉绀� 鏄熷彿锛岃�冭檻鍚庣画鍏煎
+ // if (this.form) {
+ // if (this.form._isRequiredField(this.itemRules.rules || []) && this.required) {
+ // return true
+ // }
+ // return false
+ // }
+ return this.required
+ },
+
+ // 澶勭悊瀵归綈鏂瑰紡
+ _justifyContent() {
+ if (this.form) {
+ const {
+ labelAlign
+ } = this.form
+ let labelAli = this.labelAlign ? this.labelAlign : labelAlign;
+ if (labelAli === 'left') return 'flex-start';
+ if (labelAli === 'center') return 'center';
+ if (labelAli === 'right') return 'flex-end';
+ }
+ return 'flex-start';
+ },
+ // 澶勭悊 label瀹藉害鍗曚綅 ,缁ф壙鐖跺厓绱犵殑鍊�
+ _labelWidthUnit(labelWidth) {
+
+ // if (this.form) {
+ // const {
+ // labelWidth
+ // } = this.form
+ return this.num2px(this.labelWidth ? this.labelWidth : (labelWidth || (this.label ? 65 : 'auto')))
+ // }
+ // return '65px'
+ },
+ // 澶勭悊 label 浣嶇疆
+ _labelPosition() {
+ if (this.form) return this.form.labelPosition || 'left'
+ return 'left'
+
+ },
+
+ /**
+ * 瑙﹀彂鏃舵満
+ * @param {Object} rule 褰撳墠瑙勫垯鍐呮椂鏈�
+ * @param {Object} itemRlue 褰撳墠缁勪欢鏃舵満
+ * @param {Object} parentRule 鐖剁粍浠舵椂鏈�
+ */
+ isTrigger(rule, itemRlue, parentRule) {
+ // bind submit
+ if (rule === 'submit' || !rule) {
+ if (rule === undefined) {
+ if (itemRlue !== 'bind') {
+ if (!itemRlue) {
+ return parentRule === '' ? 'bind' : 'submit';
+ }
+ return 'submit';
+ }
+ return 'bind';
+ }
+ return 'submit';
+ }
+ return 'bind';
+ },
+ num2px(num) {
+ if (typeof num === 'number') {
+ return `${num}px`
+ }
+ return num
+ }
+ }
+ };
+</script>
+
+<style lang="scss">
+ .uni-forms-item {
+ position: relative;
+ display: flex;
+ /* #ifdef APP-NVUE */
+ // 鍦� nvue 涓紝浣跨敤 margin-bottom error 淇℃伅浼氳闅愯棌
+ padding-bottom: 22px;
+ /* #endif */
+ /* #ifndef APP-NVUE */
+ margin-bottom: 22px;
+ /* #endif */
+ flex-direction: row;
+
+ &__label {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ text-align: left;
+ font-size: 14px;
+ color: #606266;
+ height: 36px;
+ padding: 0 12px 0 0;
+ /* #ifndef APP-NVUE */
+ vertical-align: middle;
+ flex-shrink: 0;
+ /* #endif */
+
+ /* #ifndef APP-NVUE */
+ box-sizing: border-box;
+
+ /* #endif */
+ &.no-label {
+ padding: 0;
+ }
+ }
+
+ &__content {
+ /* #ifndef MP-TOUTIAO */
+ // display: flex;
+ // align-items: center;
+ /* #endif */
+ position: relative;
+ font-size: 14px;
+ flex: 1;
+ /* #ifndef APP-NVUE */
+ box-sizing: border-box;
+ /* #endif */
+ flex-direction: row;
+
+ /* #ifndef APP || H5 || MP-WEIXIN || APP-NVUE */
+ // TODO 鍥犱负灏忕▼搴忓钩鍙颁細澶氫竴灞傛爣绛捐妭鐐� 锛屾墍浠ラ渶瑕佸湪澶氫綑鑺傜偣缁ф壙褰撳墠鏍峰紡
+ &>uni-easyinput,
+ &>uni-data-picker {
+ width: 100%;
+ }
+
+ /* #endif */
+
+ }
+
+ & .uni-forms-item__nuve-content {
+ display: flex;
+ flex-direction: column;
+ flex: 1;
+ }
+
+ &__error {
+ color: #f56c6c;
+ font-size: 12px;
+ line-height: 1;
+ padding-top: 4px;
+ position: absolute;
+ /* #ifndef APP-NVUE */
+ top: 100%;
+ left: 0;
+ transition: transform 0.3s;
+ transform: translateY(-100%);
+ /* #endif */
+ /* #ifdef APP-NVUE */
+ bottom: 5px;
+ /* #endif */
+
+ opacity: 0;
+
+ .error-text {
+ // 鍙湁 nvue 涓嬭繖涓牱寮忔墠鐢熸晥
+ color: #f56c6c;
+ font-size: 12px;
+ }
+
+ &.msg--active {
+ opacity: 1;
+ transform: translateY(0%);
+ }
+ }
+
+ // 浣嶇疆淇グ鏍峰紡
+ &.is-direction-left {
+ flex-direction: row;
+ }
+
+ &.is-direction-top {
+ flex-direction: column;
+
+ .uni-forms-item__label {
+ padding: 0 0 8px;
+ line-height: 1.5715;
+ text-align: left;
+ /* #ifndef APP-NVUE */
+ white-space: initial;
+ /* #endif */
+ }
+ }
+
+ .is-required {
+ // color: $uni-color-error;
+ color: #dd524d;
+ font-weight: bold;
+ }
+ }
+
+
+ .uni-forms-item--border {
+ margin-bottom: 0;
+ padding: 10px 0;
+ // padding-bottom: 0;
+ border-top: 1px #eee solid;
+
+ /* #ifndef APP-NVUE */
+ .uni-forms-item__content {
+ flex-direction: column;
+ justify-content: flex-start;
+ align-items: flex-start;
+
+ .uni-forms-item__error {
+ position: relative;
+ top: 5px;
+ left: 0;
+ padding-top: 0;
+ }
+ }
+
+ /* #endif */
+
+ /* #ifdef APP-NVUE */
+ display: flex;
+ flex-direction: column;
+
+ .uni-forms-item__error {
+ position: relative;
+ top: 0px;
+ left: 0;
+ padding-top: 0;
+ margin-top: 5px;
+ }
+
+ /* #endif */
+
+ }
+
+ .is-first-border {
+ /* #ifndef APP-NVUE */
+ border: none;
+ /* #endif */
+ /* #ifdef APP-NVUE */
+ border-width: 0;
+ /* #endif */
+ }
+</style>
diff --git a/app/uni_modules/uni-forms/components/uni-forms/uni-forms.vue b/app/uni_modules/uni-forms/components/uni-forms/uni-forms.vue
new file mode 100644
index 0000000..ed2f6d9
--- /dev/null
+++ b/app/uni_modules/uni-forms/components/uni-forms/uni-forms.vue
@@ -0,0 +1,397 @@
+<template>
+ <view class="uni-forms">
+ <form>
+ <slot></slot>
+ </form>
+ </view>
+</template>
+
+<script>
+ import Validator from './validate.js';
+ import {
+ deepCopy,
+ getValue,
+ isRequiredField,
+ setDataValue,
+ getDataValue,
+ realName,
+ isRealName,
+ rawData,
+ isEqual
+ } from './utils.js'
+
+ // #ifndef VUE3
+ // 鍚庣画浼氭參鎱㈠簾寮冭繖涓柟娉�
+ import Vue from 'vue';
+ Vue.prototype.binddata = function(name, value, formName) {
+ if (formName) {
+ this.$refs[formName].setValue(name, value);
+ } else {
+ let formVm;
+ for (let i in this.$refs) {
+ const vm = this.$refs[i];
+ if (vm && vm.$options && vm.$options.name === 'uniForms') {
+ formVm = vm;
+ break;
+ }
+ }
+ if (!formVm) return console.error('褰撳墠 uni-froms 缁勪欢缂哄皯 ref 灞炴��');
+ formVm.setValue(name, value);
+ }
+ };
+ // #endif
+ /**
+ * Forms 琛ㄥ崟
+ * @description 鐢辫緭鍏ユ銆侀�夋嫨鍣ㄣ�佸崟閫夋銆佸閫夋绛夋帶浠剁粍鎴愶紝鐢ㄤ互鏀堕泦銆佹牎楠屻�佹彁浜ゆ暟鎹�
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=2773
+ * @property {Object} rules 琛ㄥ崟鏍¢獙瑙勫垯
+ * @property {String} validateTrigger = [bind|submit|blur] 鏍¢獙瑙﹀彂鍣ㄦ柟寮� 榛樿 submit
+ * @value bind 鍙戠敓鍙樺寲鏃惰Е鍙�
+ * @value submit 鎻愪氦鏃惰Е鍙�
+ * @value blur 澶卞幓鐒︾偣鏃惰Е鍙�
+ * @property {String} labelPosition = [top|left] label 浣嶇疆 榛樿 left
+ * @value top 椤堕儴鏄剧ず label
+ * @value left 宸︿晶鏄剧ず label
+ * @property {String} labelWidth label 瀹藉害锛岄粯璁� 65px
+ * @property {String} labelAlign = [left|center|right] label 灞呬腑鏂瑰紡 榛樿 left
+ * @value left label 宸︿晶鏄剧ず
+ * @value center label 灞呬腑
+ * @value right label 鍙充晶瀵归綈
+ * @property {String} errShowType = [undertext|toast|modal] 鏍¢獙閿欒淇℃伅鎻愮ず鏂瑰紡
+ * @value undertext 閿欒淇℃伅鍦ㄥ簳閮ㄦ樉绀�
+ * @value toast 閿欒淇℃伅toast鏄剧ず
+ * @value modal 閿欒淇℃伅modal鏄剧ず
+ * @event {Function} submit 鎻愪氦鏃惰Е鍙�
+ * @event {Function} validate 鏍¢獙缁撴灉鍙戠敓鍙樺寲瑙﹀彂
+ */
+ export default {
+ name: 'uniForms',
+ emits: ['validate', 'submit'],
+ options: {
+ virtualHost: true
+ },
+ props: {
+ // 鍗冲皢寮冪敤
+ value: {
+ type: Object,
+ default () {
+ return null;
+ }
+ },
+ // vue3 鏇挎崲 value 灞炴��
+ modelValue: {
+ type: Object,
+ default () {
+ return null;
+ }
+ },
+ // 1.4.0 寮�濮嬪皢涓嶆敮鎸� v-model 锛屼笖搴熷純 value 鍜� modelValue
+ model: {
+ type: Object,
+ default () {
+ return null;
+ }
+ },
+ // 琛ㄥ崟鏍¢獙瑙勫垯
+ rules: {
+ type: Object,
+ default () {
+ return {};
+ }
+ },
+ //鏍¢獙閿欒淇℃伅鎻愮ず鏂瑰紡 榛樿 undertext 鍙栧�� [undertext|toast|modal]
+ errShowType: {
+ type: String,
+ default: 'undertext'
+ },
+ // 鏍¢獙瑙﹀彂鍣ㄦ柟寮� 榛樿 bind 鍙栧�� [bind|submit]
+ validateTrigger: {
+ type: String,
+ default: 'submit'
+ },
+ // label 浣嶇疆锛岄粯璁� left 鍙栧�� top/left
+ labelPosition: {
+ type: String,
+ default: 'left'
+ },
+ // label 瀹藉害
+ labelWidth: {
+ type: [String, Number],
+ default: ''
+ },
+ // label 灞呬腑鏂瑰紡锛岄粯璁� left 鍙栧�� left/center/right
+ labelAlign: {
+ type: String,
+ default: 'left'
+ },
+ border: {
+ type: Boolean,
+ default: false
+ }
+ },
+ provide() {
+ return {
+ uniForm: this
+ }
+ },
+ data() {
+ return {
+ // 琛ㄥ崟鏈湴鍊肩殑璁板綍锛屼笉搴旇涓庝紶濡傜殑鍊艰繘琛屽叧鑱�
+ formData: {},
+ formRules: {}
+ };
+ },
+ computed: {
+ // 璁$畻鏁版嵁婧愬彉鍖栫殑
+ localData() {
+ const localVal = this.model || this.modelValue || this.value
+ if (localVal) {
+ return deepCopy(localVal)
+ }
+ return {}
+ }
+ },
+ watch: {
+ // 鐩戝惉鏁版嵁鍙樺寲 ,鏆傛椂涓嶄娇鐢紝闇�瑕佸崟鐙祴鍊�
+ // localData: {},
+ // 鐩戝惉瑙勫垯鍙樺寲
+ rules: {
+ handler: function(val, oldVal) {
+ this.setRules(val)
+ },
+ deep: true,
+ immediate: true
+ }
+ },
+ created() {
+ // #ifdef VUE3
+ let getbinddata = getApp().$vm.$.appContext.config.globalProperties.binddata
+ if (!getbinddata) {
+ getApp().$vm.$.appContext.config.globalProperties.binddata = function(name, value, formName) {
+ if (formName) {
+ this.$refs[formName].setValue(name, value);
+ } else {
+ let formVm;
+ for (let i in this.$refs) {
+ const vm = this.$refs[i];
+ if (vm && vm.$options && vm.$options.name === 'uniForms') {
+ formVm = vm;
+ break;
+ }
+ }
+ if (!formVm) return console.error('褰撳墠 uni-froms 缁勪欢缂哄皯 ref 灞炴��');
+ formVm.setValue(name, value);
+ }
+ }
+ }
+ // #endif
+
+ // 瀛愮粍浠跺疄渚嬫暟缁�
+ this.childrens = []
+ // TODO 鍏煎鏃х増 uni-data-picker ,鏂扮増鏈腑鏃犳晥锛屽彧鏄伩鍏嶆姤閿�
+ this.inputChildrens = []
+ this.setRules(this.rules)
+ },
+ methods: {
+ /**
+ * 澶栭儴璋冪敤鏂规硶
+ * 璁剧疆瑙勫垯 锛屼富瑕佺敤浜庡皬绋嬪簭鑷畾涔夋楠岃鍒�
+ * @param {Array} rules 瑙勫垯婧愭暟鎹�
+ */
+ setRules(rules) {
+ // TODO 鏈夊彲鑳藉瓙缁勪欢鍚堝苟瑙勫垯鐨勬椂鏈烘瘮杩欎釜瑕佹棭锛屾墍浠ラ渶瑕佸悎骞跺璞� 锛岃�屼笉鏄洿鎺ヨ祴鍊硷紝鍙兘浼氳瑕嗙洊
+ this.formRules = Object.assign({}, this.formRules, rules)
+ // 鍒濆鍖栨牎楠屽嚱鏁�
+ this.validator = new Validator(rules);
+ },
+
+ /**
+ * 澶栭儴璋冪敤鏂规硶
+ * 璁剧疆鏁版嵁锛岀敤浜庤缃〃鍗曟暟鎹紝鍏紑缁欑敤鎴蜂娇鐢� 锛� 涓嶆敮鎸佸湪鍔ㄦ�佽〃鍗曚腑浣跨敤
+ * @param {Object} key
+ * @param {Object} value
+ */
+ setValue(key, value) {
+ let example = this.childrens.find(child => child.name === key);
+ if (!example) return null;
+ this.formData[key] = getValue(key, value, (this.formRules[key] && this.formRules[key].rules) || [])
+ return example.onFieldChange(this.formData[key]);
+ },
+
+ /**
+ * 澶栭儴璋冪敤鏂规硶
+ * 鎵嬪姩鎻愪氦鏍¢獙琛ㄥ崟
+ * 瀵规暣涓〃鍗曡繘琛屾牎楠岀殑鏂规硶锛屽弬鏁颁负涓�涓洖璋冨嚱鏁般��
+ * @param {Array} keepitem 淇濈暀涓嶅弬涓庢牎楠岀殑瀛楁
+ * @param {type} callback 鏂规硶鍥炶皟
+ */
+ validate(keepitem, callback) {
+ return this.checkAll(this.formData, keepitem, callback);
+ },
+
+ /**
+ * 澶栭儴璋冪敤鏂规硶
+ * 閮ㄥ垎琛ㄥ崟鏍¢獙
+ * @param {Array|String} props 闇�瑕佹牎楠岀殑瀛楁
+ * @param {Function} 鍥炶皟鍑芥暟
+ */
+ validateField(props = [], callback) {
+ props = [].concat(props);
+ let invalidFields = {};
+ this.childrens.forEach(item => {
+ const name = realName(item.name)
+ if (props.indexOf(name) !== -1) {
+ invalidFields = Object.assign({}, invalidFields, {
+ [name]: this.formData[name]
+ });
+ }
+ });
+ return this.checkAll(invalidFields, [], callback);
+ },
+
+ /**
+ * 澶栭儴璋冪敤鏂规硶
+ * 绉婚櫎琛ㄥ崟椤圭殑鏍¢獙缁撴灉銆備紶鍏ュ緟绉婚櫎鐨勮〃鍗曢」鐨� prop 灞炴�ф垨鑰� prop 缁勬垚鐨勬暟缁勶紝濡備笉浼犲垯绉婚櫎鏁翠釜琛ㄥ崟鐨勬牎楠岀粨鏋�
+ * @param {Array|String} props 闇�瑕佺Щ闄ゆ牎楠岀殑瀛楁 锛屼笉濉负鎵�鏈�
+ */
+ clearValidate(props = []) {
+ props = [].concat(props);
+ this.childrens.forEach(item => {
+ if (props.length === 0) {
+ item.errMsg = '';
+ } else {
+ const name = realName(item.name)
+ if (props.indexOf(name) !== -1) {
+ item.errMsg = '';
+ }
+ }
+ });
+ },
+
+ /**
+ * 澶栭儴璋冪敤鏂规硶 锛屽嵆灏嗗簾寮�
+ * 鎵嬪姩鎻愪氦鏍¢獙琛ㄥ崟
+ * 瀵规暣涓〃鍗曡繘琛屾牎楠岀殑鏂规硶锛屽弬鏁颁负涓�涓洖璋冨嚱鏁般��
+ * @param {Array} keepitem 淇濈暀涓嶅弬涓庢牎楠岀殑瀛楁
+ * @param {type} callback 鏂规硶鍥炶皟
+ */
+ submit(keepitem, callback, type) {
+ for (let i in this.dataValue) {
+ const itemData = this.childrens.find(v => v.name === i);
+ if (itemData) {
+ if (this.formData[i] === undefined) {
+ this.formData[i] = this._getValue(i, this.dataValue[i]);
+ }
+ }
+ }
+
+ if (!type) {
+ console.warn('submit 鏂规硶鍗冲皢搴熷純锛岃浣跨敤validate鏂规硶浠f浛锛�');
+ }
+
+ return this.checkAll(this.formData, keepitem, callback, 'submit');
+ },
+
+ // 鏍¢獙鎵�鏈�
+ async checkAll(invalidFields, keepitem, callback, type) {
+ // 涓嶅瓨鍦ㄦ牎楠岃鍒� 锛屽垯鍋滄鏍¢獙娴佺▼
+ if (!this.validator) return
+ let childrens = []
+ // 澶勭悊鍙備笌鏍¢獙鐨刬tem瀹炰緥
+ for (let i in invalidFields) {
+ const item = this.childrens.find(v => realName(v.name) === i)
+ if (item) {
+ childrens.push(item)
+ }
+ }
+
+ // 濡傛灉validate绗竴涓弬鏁版槸funciont ,閭e氨璧板洖璋�
+ if (!callback && typeof keepitem === 'function') {
+ callback = keepitem;
+ }
+
+ let promise;
+ // 濡傛灉涓嶅瓨鍦ㄥ洖璋冿紝閭d箞浣跨敤 Promise 鏂瑰紡杩斿洖
+ if (!callback && typeof callback !== 'function' && Promise) {
+ promise = new Promise((resolve, reject) => {
+ callback = function(valid, invalidFields) {
+ !valid ? resolve(invalidFields) : reject(valid);
+ };
+ });
+ }
+
+ let results = [];
+ // 閬垮厤寮曠敤閿欎贡 锛屽缓璁嫹璐濆璞″鐞�
+ let tempFormData = JSON.parse(JSON.stringify(invalidFields))
+ // 鎵�鏈夊瓙缁勪欢鍙備笌鏍¢獙,浣跨敤 for 鍙互浣跨敤 awiat
+ for (let i in childrens) {
+ const child = childrens[i]
+ let name = realName(child.name);
+ const result = await child.onFieldChange(tempFormData[name]);
+ if (result) {
+ results.push(result);
+ // toast ,modal 鍙渶瑕佹墽琛岀涓�娆″氨鍙互
+ if (this.errShowType === 'toast' || this.errShowType === 'modal') break;
+ }
+ }
+
+
+ if (Array.isArray(results)) {
+ if (results.length === 0) results = null;
+ }
+ if (Array.isArray(keepitem)) {
+ keepitem.forEach(v => {
+ let vName = realName(v);
+ let value = getDataValue(v, this.localData)
+ if (value !== undefined) {
+ tempFormData[vName] = value
+ }
+ });
+ }
+
+ // TODO submit 鍗冲皢搴熷純
+ if (type === 'submit') {
+ this.$emit('submit', {
+ detail: {
+ value: tempFormData,
+ errors: results
+ }
+ });
+ } else {
+ this.$emit('validate', results);
+ }
+
+ // const resetFormData = rawData(tempFormData, this.localData, this.name)
+ let resetFormData = {}
+ resetFormData = rawData(tempFormData, this.name)
+ callback && typeof callback === 'function' && callback(results, resetFormData);
+
+ if (promise && callback) {
+ return promise;
+ } else {
+ return null;
+ }
+
+ },
+
+ /**
+ * 杩斿洖validate浜嬩欢
+ * @param {Object} result
+ */
+ validateCheck(result) {
+ this.$emit('validate', result);
+ },
+ _getValue: getValue,
+ _isRequiredField: isRequiredField,
+ _setDataValue: setDataValue,
+ _getDataValue: getDataValue,
+ _realName: realName,
+ _isRealName: isRealName,
+ _isEqual: isEqual
+ }
+ };
+</script>
+
+<style lang="scss">
+ .uni-forms {}
+</style>
diff --git a/app/uni_modules/uni-forms/components/uni-forms/utils.js b/app/uni_modules/uni-forms/components/uni-forms/utils.js
new file mode 100644
index 0000000..6da2421
--- /dev/null
+++ b/app/uni_modules/uni-forms/components/uni-forms/utils.js
@@ -0,0 +1,293 @@
+/**
+ * 绠�鍗曞鐞嗗璞℃嫹璐�
+ * @param {Obejct} 琚嫹璐濆璞�
+ * @@return {Object} 鎷疯礉瀵硅薄
+ */
+export const deepCopy = (val) => {
+ return JSON.parse(JSON.stringify(val))
+}
+/**
+ * 杩囨护鏁板瓧绫诲瀷
+ * @param {String} format 鏁板瓧绫诲瀷
+ * @@return {Boolean} 杩斿洖鏄惁涓烘暟瀛楃被鍨�
+ */
+export const typeFilter = (format) => {
+ return format === 'int' || format === 'double' || format === 'number' || format === 'timestamp';
+}
+
+/**
+ * 鎶� value 杞崲鎴愭寚瀹氱殑绫诲瀷锛岀敤浜庡鐞嗗垵濮嬪�硷紝鍘熷洜鏄垵濮嬪�奸渶瑕佸叆搴撲笉鑳戒负 undefined
+ * @param {String} key 瀛楁鍚�
+ * @param {any} value 瀛楁鍊�
+ * @param {Object} rules 琛ㄥ崟鏍¢獙瑙勫垯
+ */
+export const getValue = (key, value, rules) => {
+ const isRuleNumType = rules.find(val => val.format && typeFilter(val.format));
+ const isRuleBoolType = rules.find(val => (val.format && val.format === 'boolean') || val.format === 'bool');
+ // 杈撳叆绫诲瀷涓� number
+ if (!!isRuleNumType) {
+ if (!value && value !== 0) {
+ value = null
+ } else {
+ value = isNumber(Number(value)) ? Number(value) : value
+ }
+ }
+
+ // 杈撳叆绫诲瀷涓� boolean
+ if (!!isRuleBoolType) {
+ value = isBoolean(value) ? value : false
+ }
+
+ return value;
+}
+
+/**
+ * 鑾峰彇琛ㄥ崟鏁版嵁
+ * @param {String|Array} name 鐪熷疄鍚嶇О锛岄渶瑕佷娇鐢� realName 鑾峰彇
+ * @param {Object} data 鍘熷鏁版嵁
+ * @param {any} value 闇�瑕佽缃殑鍊�
+ */
+export const setDataValue = (field, formdata, value) => {
+ formdata[field] = value
+ return value || ''
+}
+
+/**
+ * 鑾峰彇琛ㄥ崟鏁版嵁
+ * @param {String|Array} field 鐪熷疄鍚嶇О锛岄渶瑕佷娇鐢� realName 鑾峰彇
+ * @param {Object} data 鍘熷鏁版嵁
+ */
+export const getDataValue = (field, data) => {
+ return objGet(data, field)
+}
+
+/**
+ * 鑾峰彇琛ㄥ崟绫诲瀷
+ * @param {String|Array} field 鐪熷疄鍚嶇О锛岄渶瑕佷娇鐢� realName 鑾峰彇
+ */
+export const getDataValueType = (field, data) => {
+ const value = getDataValue(field, data)
+ return {
+ type: type(value),
+ value
+ }
+}
+
+/**
+ * 鑾峰彇琛ㄥ崟鍙敤鐨勭湡瀹瀗ame
+ * @param {String|Array} name 琛ㄥ崟name
+ * @@return {String} 琛ㄥ崟鍙敤鐨勭湡瀹瀗ame
+ */
+export const realName = (name, data = {}) => {
+ const base_name = _basePath(name)
+ if (typeof base_name === 'object' && Array.isArray(base_name) && base_name.length > 1) {
+ const realname = base_name.reduce((a, b) => a += `#${b}`, '_formdata_')
+ return realname
+ }
+ return base_name[0] || name
+}
+
+/**
+ * 鍒ゆ柇鏄惁琛ㄥ崟鍙敤鐨勭湡瀹瀗ame
+ * @param {String|Array} name 琛ㄥ崟name
+ * @@return {String} 琛ㄥ崟鍙敤鐨勭湡瀹瀗ame
+ */
+export const isRealName = (name) => {
+ const reg = /^_formdata_#*/
+ return reg.test(name)
+}
+
+/**
+ * 鑾峰彇琛ㄥ崟鏁版嵁鐨勫師濮嬫牸寮�
+ * @@return {Object|Array} object 闇�瑕佽В鏋愮殑鏁版嵁
+ */
+export const rawData = (object = {}, name) => {
+ let newData = JSON.parse(JSON.stringify(object))
+ let formData = {}
+ for(let i in newData){
+ let path = name2arr(i)
+ objSet(formData,path,newData[i])
+ }
+ return formData
+}
+
+/**
+ * 鐪熷疄name杩樺師涓� array
+ * @param {*} name
+ */
+export const name2arr = (name) => {
+ let field = name.replace('_formdata_#', '')
+ field = field.split('#').map(v => (isNumber(v) ? Number(v) : v))
+ return field
+}
+
+/**
+ * 瀵硅薄涓缃��
+ * @param {Object|Array} object 婧愭暟鎹�
+ * @param {String| Array} path 'a.b.c' 鎴� ['a',0,'b','c']
+ * @param {String} value 闇�瑕佽缃殑鍊�
+ */
+export const objSet = (object, path, value) => {
+ if (typeof object !== 'object') return object;
+ _basePath(path).reduce((o, k, i, _) => {
+ if (i === _.length - 1) {
+ // 鑻ラ亶鍘嗙粨鏉熺洿鎺ヨ祴鍊�
+ o[k] = value
+ return null
+ } else if (k in o) {
+ // 鑻ュ瓨鍦ㄥ搴旇矾寰勶紝鍒欒繑鍥炴壘鍒扮殑瀵硅薄锛岃繘琛屼笅涓�娆¢亶鍘�
+ return o[k]
+ } else {
+ // 鑻ヤ笉瀛樺湪瀵瑰簲璺緞锛屽垯鍒涘缓瀵瑰簲瀵硅薄锛岃嫢涓嬩竴璺緞鏄暟瀛楋紝鏂板璞¤祴鍊间负绌烘暟缁勶紝鍚﹀垯璧嬪�间负绌哄璞�
+ o[k] = /^[0-9]{1,}$/.test(_[i + 1]) ? [] : {}
+ return o[k]
+ }
+ }, object)
+ // 杩斿洖object
+ return object;
+}
+
+// 澶勭悊 path锛� path鏈変笁绉嶅舰寮忥細'a[0].b.c'銆�'a.0.b.c' 鍜� ['a','0','b','c']锛岄渶瑕佺粺涓�澶勭悊鎴愭暟缁勶紝渚夸簬鍚庣画浣跨敤
+function _basePath(path) {
+ // 鑻ユ槸鏁扮粍锛屽垯鐩存帴杩斿洖
+ if (Array.isArray(path)) return path
+ // 鑻ユ湁 '[',']'锛屽垯鏇挎崲鎴愬皢 '[' 鏇挎崲鎴� '.',鍘绘帀 ']'
+ return path.replace(/\[/g, '.').replace(/\]/g, '').split('.')
+}
+
+/**
+ * 浠庡璞′腑鑾峰彇鍊�
+ * @param {Object|Array} object 婧愭暟鎹�
+ * @param {String| Array} path 'a.b.c' 鎴� ['a',0,'b','c']
+ * @param {String} defaultVal 濡傛灉鏃犳硶浠庤皟鐢ㄩ摼涓幏鍙栧�肩殑榛樿鍊�
+ */
+export const objGet = (object, path, defaultVal = 'undefined') => {
+ // 鍏堝皢path澶勭悊鎴愮粺涓�鏍煎紡
+ let newPath = _basePath(path)
+ // 閫掑綊澶勭悊锛岃繑鍥炴渶鍚庣粨鏋�
+ let val = newPath.reduce((o, k) => {
+ return (o || {})[k]
+ }, object);
+ return !val || val !== undefined ? val : defaultVal
+}
+
+
+/**
+ * 鏄惁涓� number 绫诲瀷
+ * @param {any} num 闇�瑕佸垽鏂殑鍊�
+ * @return {Boolean} 鏄惁涓� number
+ */
+export const isNumber = (num) => {
+ return !isNaN(Number(num))
+}
+
+/**
+ * 鏄惁涓� boolean 绫诲瀷
+ * @param {any} bool 闇�瑕佸垽鏂殑鍊�
+ * @return {Boolean} 鏄惁涓� boolean
+ */
+export const isBoolean = (bool) => {
+ return (typeof bool === 'boolean')
+}
+/**
+ * 鏄惁鏈夊繀濉瓧娈�
+ * @param {Object} rules 瑙勫垯
+ * @return {Boolean} 鏄惁鏈夊繀濉瓧娈�
+ */
+export const isRequiredField = (rules) => {
+ let isNoField = false;
+ for (let i = 0; i < rules.length; i++) {
+ const ruleData = rules[i];
+ if (ruleData.required) {
+ isNoField = true;
+ break;
+ }
+ }
+ return isNoField;
+}
+
+
+/**
+ * 鑾峰彇鏁版嵁绫诲瀷
+ * @param {Any} obj 闇�瑕佽幏鍙栨暟鎹被鍨嬬殑鍊�
+ */
+export const type = (obj) => {
+ var class2type = {};
+
+ // 鐢熸垚class2type鏄犲皠
+ "Boolean Number String Function Array Date RegExp Object Error".split(" ").map(function(item, index) {
+ class2type["[object " + item + "]"] = item.toLowerCase();
+ })
+ if (obj == null) {
+ return obj + "";
+ }
+ return typeof obj === "object" || typeof obj === "function" ?
+ class2type[Object.prototype.toString.call(obj)] || "object" :
+ typeof obj;
+}
+
+/**
+ * 鍒ゆ柇涓や釜鍊兼槸鍚︾浉绛�
+ * @param {any} a 鍊�
+ * @param {any} b 鍊�
+ * @return {Boolean} 鏄惁鐩哥瓑
+ */
+export const isEqual = (a, b) => {
+ //濡傛灉a鍜宐鏈潵灏卞叏绛�
+ if (a === b) {
+ //鍒ゆ柇鏄惁涓�0鍜�-0
+ return a !== 0 || 1 / a === 1 / b;
+ }
+ //鍒ゆ柇鏄惁涓簄ull鍜寀ndefined
+ if (a == null || b == null) {
+ return a === b;
+ }
+ //鎺ヤ笅鏉ュ垽鏂璦鍜宐鐨勬暟鎹被鍨�
+ var classNameA = toString.call(a),
+ classNameB = toString.call(b);
+ //濡傛灉鏁版嵁绫诲瀷涓嶇浉绛夛紝鍒欒繑鍥瀎alse
+ if (classNameA !== classNameB) {
+ return false;
+ }
+ //濡傛灉鏁版嵁绫诲瀷鐩哥瓑锛屽啀鏍规嵁涓嶅悓鏁版嵁绫诲瀷鍒嗗埆鍒ゆ柇
+ switch (classNameA) {
+ case '[object RegExp]':
+ case '[object String]':
+ //杩涜瀛楃涓茶浆鎹㈡瘮杈�
+ return '' + a === '' + b;
+ case '[object Number]':
+ //杩涜鏁板瓧杞崲姣旇緝,鍒ゆ柇鏄惁涓篘aN
+ if (+a !== +a) {
+ return +b !== +b;
+ }
+ //鍒ゆ柇鏄惁涓�0鎴�-0
+ return +a === 0 ? 1 / +a === 1 / b : +a === +b;
+ case '[object Date]':
+ case '[object Boolean]':
+ return +a === +b;
+ }
+ //濡傛灉鏄璞$被鍨�
+ if (classNameA == '[object Object]') {
+ //鑾峰彇a鍜宐鐨勫睘鎬ч暱搴�
+ var propsA = Object.getOwnPropertyNames(a),
+ propsB = Object.getOwnPropertyNames(b);
+ if (propsA.length != propsB.length) {
+ return false;
+ }
+ for (var i = 0; i < propsA.length; i++) {
+ var propName = propsA[i];
+ //濡傛灉瀵瑰簲灞炴�у搴斿�间笉鐩哥瓑锛屽垯杩斿洖false
+ if (a[propName] !== b[propName]) {
+ return false;
+ }
+ }
+ return true;
+ }
+ //濡傛灉鏄暟缁勭被鍨�
+ if (classNameA == '[object Array]') {
+ if (a.toString() == b.toString()) {
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/app/uni_modules/uni-forms/components/uni-forms/validate.js b/app/uni_modules/uni-forms/components/uni-forms/validate.js
new file mode 100644
index 0000000..1834c6c
--- /dev/null
+++ b/app/uni_modules/uni-forms/components/uni-forms/validate.js
@@ -0,0 +1,486 @@
+var pattern = {
+ email: /^\S+?@\S+?\.\S+?$/,
+ idcard: /^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/,
+ url: new RegExp(
+ "^(?!mailto:)(?:(?:http|https|ftp)://|//)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-*)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-*)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?$",
+ 'i')
+};
+
+const FORMAT_MAPPING = {
+ "int": 'integer',
+ "bool": 'boolean',
+ "double": 'number',
+ "long": 'number',
+ "password": 'string'
+ // "fileurls": 'array'
+}
+
+function formatMessage(args, resources = '') {
+ var defaultMessage = ['label']
+ defaultMessage.forEach((item) => {
+ if (args[item] === undefined) {
+ args[item] = ''
+ }
+ })
+
+ let str = resources
+ for (let key in args) {
+ let reg = new RegExp('{' + key + '}')
+ str = str.replace(reg, args[key])
+ }
+ return str
+}
+
+function isEmptyValue(value, type) {
+ if (value === undefined || value === null) {
+ return true;
+ }
+
+ if (typeof value === 'string' && !value) {
+ return true;
+ }
+
+ if (Array.isArray(value) && !value.length) {
+ return true;
+ }
+
+ if (type === 'object' && !Object.keys(value).length) {
+ return true;
+ }
+
+ return false;
+}
+
+const types = {
+ integer(value) {
+ return types.number(value) && parseInt(value, 10) === value;
+ },
+ string(value) {
+ return typeof value === 'string';
+ },
+ number(value) {
+ if (isNaN(value)) {
+ return false;
+ }
+ return typeof value === 'number';
+ },
+ "boolean": function(value) {
+ return typeof value === 'boolean';
+ },
+ "float": function(value) {
+ return types.number(value) && !types.integer(value);
+ },
+ array(value) {
+ return Array.isArray(value);
+ },
+ object(value) {
+ return typeof value === 'object' && !types.array(value);
+ },
+ date(value) {
+ return value instanceof Date;
+ },
+ timestamp(value) {
+ if (!this.integer(value) || Math.abs(value).toString().length > 16) {
+ return false
+ }
+ return true;
+ },
+ file(value) {
+ return typeof value.url === 'string';
+ },
+ email(value) {
+ return typeof value === 'string' && !!value.match(pattern.email) && value.length < 255;
+ },
+ url(value) {
+ return typeof value === 'string' && !!value.match(pattern.url);
+ },
+ pattern(reg, value) {
+ try {
+ return new RegExp(reg).test(value);
+ } catch (e) {
+ return false;
+ }
+ },
+ method(value) {
+ return typeof value === 'function';
+ },
+ idcard(value) {
+ return typeof value === 'string' && !!value.match(pattern.idcard);
+ },
+ 'url-https'(value) {
+ return this.url(value) && value.startsWith('https://');
+ },
+ 'url-scheme'(value) {
+ return value.startsWith('://');
+ },
+ 'url-web'(value) {
+ return false;
+ }
+}
+
+class RuleValidator {
+
+ constructor(message) {
+ this._message = message
+ }
+
+ async validateRule(fieldKey, fieldValue, value, data, allData) {
+ var result = null
+
+ let rules = fieldValue.rules
+
+ let hasRequired = rules.findIndex((item) => {
+ return item.required
+ })
+ if (hasRequired < 0) {
+ if (value === null || value === undefined) {
+ return result
+ }
+ if (typeof value === 'string' && !value.length) {
+ return result
+ }
+ }
+
+ var message = this._message
+
+ if (rules === undefined) {
+ return message['default']
+ }
+
+ for (var i = 0; i < rules.length; i++) {
+ let rule = rules[i]
+ let vt = this._getValidateType(rule)
+
+ Object.assign(rule, {
+ label: fieldValue.label || `["${fieldKey}"]`
+ })
+
+ if (RuleValidatorHelper[vt]) {
+ result = RuleValidatorHelper[vt](rule, value, message)
+ if (result != null) {
+ break
+ }
+ }
+
+ if (rule.validateExpr) {
+ let now = Date.now()
+ let resultExpr = rule.validateExpr(value, allData, now)
+ if (resultExpr === false) {
+ result = this._getMessage(rule, rule.errorMessage || this._message['default'])
+ break
+ }
+ }
+
+ if (rule.validateFunction) {
+ result = await this.validateFunction(rule, value, data, allData, vt)
+ if (result !== null) {
+ break
+ }
+ }
+ }
+
+ if (result !== null) {
+ result = message.TAG + result
+ }
+
+ return result
+ }
+
+ async validateFunction(rule, value, data, allData, vt) {
+ let result = null
+ try {
+ let callbackMessage = null
+ const res = await rule.validateFunction(rule, value, allData || data, (message) => {
+ callbackMessage = message
+ })
+ if (callbackMessage || (typeof res === 'string' && res) || res === false) {
+ result = this._getMessage(rule, callbackMessage || res, vt)
+ }
+ } catch (e) {
+ result = this._getMessage(rule, e.message, vt)
+ }
+ return result
+ }
+
+ _getMessage(rule, message, vt) {
+ return formatMessage(rule, message || rule.errorMessage || this._message[vt] || message['default'])
+ }
+
+ _getValidateType(rule) {
+ var result = ''
+ if (rule.required) {
+ result = 'required'
+ } else if (rule.format) {
+ result = 'format'
+ } else if (rule.arrayType) {
+ result = 'arrayTypeFormat'
+ } else if (rule.range) {
+ result = 'range'
+ } else if (rule.maximum !== undefined || rule.minimum !== undefined) {
+ result = 'rangeNumber'
+ } else if (rule.maxLength !== undefined || rule.minLength !== undefined) {
+ result = 'rangeLength'
+ } else if (rule.pattern) {
+ result = 'pattern'
+ } else if (rule.validateFunction) {
+ result = 'validateFunction'
+ }
+ return result
+ }
+}
+
+const RuleValidatorHelper = {
+ required(rule, value, message) {
+ if (rule.required && isEmptyValue(value, rule.format || typeof value)) {
+ return formatMessage(rule, rule.errorMessage || message.required);
+ }
+
+ return null
+ },
+
+ range(rule, value, message) {
+ const {
+ range,
+ errorMessage
+ } = rule;
+
+ let list = new Array(range.length);
+ for (let i = 0; i < range.length; i++) {
+ const item = range[i];
+ if (types.object(item) && item.value !== undefined) {
+ list[i] = item.value;
+ } else {
+ list[i] = item;
+ }
+ }
+
+ let result = false
+ if (Array.isArray(value)) {
+ result = (new Set(value.concat(list)).size === list.length);
+ } else {
+ if (list.indexOf(value) > -1) {
+ result = true;
+ }
+ }
+
+ if (!result) {
+ return formatMessage(rule, errorMessage || message['enum']);
+ }
+
+ return null
+ },
+
+ rangeNumber(rule, value, message) {
+ if (!types.number(value)) {
+ return formatMessage(rule, rule.errorMessage || message.pattern.mismatch);
+ }
+
+ let {
+ minimum,
+ maximum,
+ exclusiveMinimum,
+ exclusiveMaximum
+ } = rule;
+ let min = exclusiveMinimum ? value <= minimum : value < minimum;
+ let max = exclusiveMaximum ? value >= maximum : value > maximum;
+
+ if (minimum !== undefined && min) {
+ return formatMessage(rule, rule.errorMessage || message['number'][exclusiveMinimum ?
+ 'exclusiveMinimum' : 'minimum'
+ ])
+ } else if (maximum !== undefined && max) {
+ return formatMessage(rule, rule.errorMessage || message['number'][exclusiveMaximum ?
+ 'exclusiveMaximum' : 'maximum'
+ ])
+ } else if (minimum !== undefined && maximum !== undefined && (min || max)) {
+ return formatMessage(rule, rule.errorMessage || message['number'].range)
+ }
+
+ return null
+ },
+
+ rangeLength(rule, value, message) {
+ if (!types.string(value) && !types.array(value)) {
+ return formatMessage(rule, rule.errorMessage || message.pattern.mismatch);
+ }
+
+ let min = rule.minLength;
+ let max = rule.maxLength;
+ let val = value.length;
+
+ if (min !== undefined && val < min) {
+ return formatMessage(rule, rule.errorMessage || message['length'].minLength)
+ } else if (max !== undefined && val > max) {
+ return formatMessage(rule, rule.errorMessage || message['length'].maxLength)
+ } else if (min !== undefined && max !== undefined && (val < min || val > max)) {
+ return formatMessage(rule, rule.errorMessage || message['length'].range)
+ }
+
+ return null
+ },
+
+ pattern(rule, value, message) {
+ if (!types['pattern'](rule.pattern, value)) {
+ return formatMessage(rule, rule.errorMessage || message.pattern.mismatch);
+ }
+
+ return null
+ },
+
+ format(rule, value, message) {
+ var customTypes = Object.keys(types);
+ var format = FORMAT_MAPPING[rule.format] ? FORMAT_MAPPING[rule.format] : (rule.format || rule.arrayType);
+
+ if (customTypes.indexOf(format) > -1) {
+ if (!types[format](value)) {
+ return formatMessage(rule, rule.errorMessage || message.typeError);
+ }
+ }
+
+ return null
+ },
+
+ arrayTypeFormat(rule, value, message) {
+ if (!Array.isArray(value)) {
+ return formatMessage(rule, rule.errorMessage || message.typeError);
+ }
+
+ for (let i = 0; i < value.length; i++) {
+ const element = value[i];
+ let formatResult = this.format(rule, element, message)
+ if (formatResult !== null) {
+ return formatResult
+ }
+ }
+
+ return null
+ }
+}
+
+class SchemaValidator extends RuleValidator {
+
+ constructor(schema, options) {
+ super(SchemaValidator.message);
+
+ this._schema = schema
+ this._options = options || null
+ }
+
+ updateSchema(schema) {
+ this._schema = schema
+ }
+
+ async validate(data, allData) {
+ let result = this._checkFieldInSchema(data)
+ if (!result) {
+ result = await this.invokeValidate(data, false, allData)
+ }
+ return result.length ? result[0] : null
+ }
+
+ async validateAll(data, allData) {
+ let result = this._checkFieldInSchema(data)
+ if (!result) {
+ result = await this.invokeValidate(data, true, allData)
+ }
+ return result
+ }
+
+ async validateUpdate(data, allData) {
+ let result = this._checkFieldInSchema(data)
+ if (!result) {
+ result = await this.invokeValidateUpdate(data, false, allData)
+ }
+ return result.length ? result[0] : null
+ }
+
+ async invokeValidate(data, all, allData) {
+ let result = []
+ let schema = this._schema
+ for (let key in schema) {
+ let value = schema[key]
+ let errorMessage = await this.validateRule(key, value, data[key], data, allData)
+ if (errorMessage != null) {
+ result.push({
+ key,
+ errorMessage
+ })
+ if (!all) break
+ }
+ }
+ return result
+ }
+
+ async invokeValidateUpdate(data, all, allData) {
+ let result = []
+ for (let key in data) {
+ let errorMessage = await this.validateRule(key, this._schema[key], data[key], data, allData)
+ if (errorMessage != null) {
+ result.push({
+ key,
+ errorMessage
+ })
+ if (!all) break
+ }
+ }
+ return result
+ }
+
+ _checkFieldInSchema(data) {
+ var keys = Object.keys(data)
+ var keys2 = Object.keys(this._schema)
+ if (new Set(keys.concat(keys2)).size === keys2.length) {
+ return ''
+ }
+
+ var noExistFields = keys.filter((key) => {
+ return keys2.indexOf(key) < 0;
+ })
+ var errorMessage = formatMessage({
+ field: JSON.stringify(noExistFields)
+ }, SchemaValidator.message.TAG + SchemaValidator.message['defaultInvalid'])
+ return [{
+ key: 'invalid',
+ errorMessage
+ }]
+ }
+}
+
+function Message() {
+ return {
+ TAG: "",
+ default: '楠岃瘉閿欒',
+ defaultInvalid: '鎻愪氦鐨勫瓧娈祘field}鍦ㄦ暟鎹簱涓苟涓嶅瓨鍦�',
+ validateFunction: '楠岃瘉鏃犳晥',
+ required: '{label}蹇呭~',
+ 'enum': '{label}瓒呭嚭鑼冨洿',
+ timestamp: '{label}鏍煎紡鏃犳晥',
+ whitespace: '{label}涓嶈兘涓虹┖',
+ typeError: '{label}绫诲瀷鏃犳晥',
+ date: {
+ format: '{label}鏃ユ湡{value}鏍煎紡鏃犳晥',
+ parse: '{label}鏃ユ湡鏃犳硶瑙f瀽,{value}鏃犳晥',
+ invalid: '{label}鏃ユ湡{value}鏃犳晥'
+ },
+ length: {
+ minLength: '{label}闀垮害涓嶈兘灏戜簬{minLength}',
+ maxLength: '{label}闀垮害涓嶈兘瓒呰繃{maxLength}',
+ range: '{label}蹇呴』浠嬩簬{minLength}鍜寋maxLength}涔嬮棿'
+ },
+ number: {
+ minimum: '{label}涓嶈兘灏忎簬{minimum}',
+ maximum: '{label}涓嶈兘澶т簬{maximum}',
+ exclusiveMinimum: '{label}涓嶈兘灏忎簬绛変簬{minimum}',
+ exclusiveMaximum: '{label}涓嶈兘澶т簬绛変簬{maximum}',
+ range: '{label}蹇呴』浠嬩簬{minimum}and{maximum}涔嬮棿'
+ },
+ pattern: {
+ mismatch: '{label}鏍煎紡涓嶅尮閰�'
+ }
+ };
+}
+
+
+SchemaValidator.message = new Message();
+
+export default SchemaValidator
diff --git a/app/uni_modules/uni-forms/package.json b/app/uni_modules/uni-forms/package.json
new file mode 100644
index 0000000..1925611
--- /dev/null
+++ b/app/uni_modules/uni-forms/package.json
@@ -0,0 +1,88 @@
+{
+ "id": "uni-forms",
+ "displayName": "uni-forms 琛ㄥ崟",
+ "version": "1.4.9",
+ "description": "鐢辫緭鍏ユ銆侀�夋嫨鍣ㄣ�佸崟閫夋銆佸閫夋绛夋帶浠剁粍鎴愶紝鐢ㄤ互鏀堕泦銆佹牎楠屻�佹彁浜ゆ暟鎹�",
+ "keywords": [
+ "uni-ui",
+ "琛ㄥ崟",
+ "鏍¢獙",
+ "琛ㄥ崟鏍¢獙",
+ "琛ㄥ崟楠岃瘉"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+"dcloudext": {
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+ "type": "component-vue"
+ },
+ "uni_modules": {
+ "dependencies": [
+ "uni-scss",
+ "uni-icons"
+ ],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y",
+ "浜笢": "u"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "u",
+ "鑱旂洘": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
diff --git a/app/uni_modules/uni-forms/readme.md b/app/uni_modules/uni-forms/readme.md
new file mode 100644
index 0000000..63d5a04
--- /dev/null
+++ b/app/uni_modules/uni-forms/readme.md
@@ -0,0 +1,23 @@
+
+
+## Forms 琛ㄥ崟
+
+> **缁勪欢鍚嶏細uni-forms**
+> 浠g爜鍧楋細 `uForms`銆乣uni-forms-item`
+> 鍏宠仈缁勪欢锛歚uni-forms-item`銆乣uni-easyinput`銆乣uni-data-checkbox`銆乣uni-group`銆�
+
+
+uni-app鐨勫唴缃粍浠跺凡缁忔湁浜� `<form>`缁勪欢锛岀敤浜庢彁浜よ〃鍗曞唴瀹广��
+
+鐒惰�屽嚑涔庢瘡涓〃鍗曢兘闇�瑕佸仛琛ㄥ崟楠岃瘉锛屼负浜嗘柟渚垮仛琛ㄥ崟楠岃瘉锛屽噺灏戦噸澶嶅紑鍙戯紝`uni ui` 鍙堝熀浜� `<form>`缁勪欢灏佽浜� `<uni-forms>`缁勪欢锛屽唴缃簡琛ㄥ崟楠岃瘉鍔熻兘銆�
+
+`<uni-forms>` 鎻愪緵浜� `rules`灞炴�ф潵鎻忚堪鏍¢獙瑙勫垯銆乣<uni-forms-item>`瀛愮粍浠舵潵鍖呰9鍏蜂綋鐨勮〃鍗曢」锛屼互鍙婄粰鍘熺敓鎴栦笁鏂圭粍浠舵彁渚涗簡 `binddata()` 鏉ヨ缃〃鍗曞�笺��
+
+姣忎釜瑕佹牎楠岀殑琛ㄥ崟椤癸紝涓嶇input杩樻槸checkbox锛岄兘蹇呴』鏀惧湪`<uni-forms-item>`缁勪欢涓紝涓斾竴涓猔<uni-forms-item>`缁勪欢鍙兘鏀剧疆涓�涓〃鍗曢」銆�
+
+`<uni-forms-item>`缁勪欢鍐呴儴棰勭暀浜嗘樉绀篹rror message鐨勫尯鍩燂紝榛樿鏄湪琛ㄥ崟椤圭殑搴曢儴銆�
+
+鍙﹀锛宍<uni-forms>`缁勪欢涓嬮潰鐨勫悇涓〃鍗曢」锛屽彲浠ラ�氳繃`<uni-group>`鍖呰9涓轰笉鍚岀殑鍒嗙粍銆傚悓涓�`<uni-group>`涓嬬殑涓嶅悓琛ㄥ崟椤圭洰灏嗚仛鎷㈠湪涓�璧凤紝鍚屽叾浠杇roup淇濇寔鍨傜洿闂磋窛銆俙<uni-group>`浠呭奖鍝嶈瑙夋晥鏋溿��
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-forms)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
\ No newline at end of file
diff --git a/app/uni_modules/uni-goods-nav/changelog.md b/app/uni_modules/uni-goods-nav/changelog.md
new file mode 100644
index 0000000..c6264c6
--- /dev/null
+++ b/app/uni_modules/uni-goods-nav/changelog.md
@@ -0,0 +1,18 @@
+## 1.2.1锛�2022-05-30锛�
+- 鏂板 stat灞炴�э紝鏄惁寮�鍚痷ni缁熻鍔熻兘
+## 1.2.0锛�2021-11-19锛�
+- 浼樺寲 缁勪欢UI锛屽苟鎻愪緵璁捐璧勬簮锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 鏂囨。杩佺Щ锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/uni-goods-nav](https://uniapp.dcloud.io/component/uniui/uni-goods-nav)
+## 1.1.1锛�2021-08-24锛�
+- 鏂板 鏀寔鍥介檯鍖�
+## 1.1.0锛�2021-07-13锛�
+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤簐ue3椤圭洰锛岃瑙� [uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+## 1.0.7锛�2021-05-12锛�
+- 鏂板 缁勪欢绀轰緥鍦板潃
+## 1.0.6锛�2021-04-21锛�
+- 浼樺寲 娣诲姞渚濊禆 uni-icons, 瀵煎叆鍚庤嚜鍔ㄤ笅杞戒緷璧�
+## 1.0.5锛�2021-02-05锛�
+- 浼樺寲 缁勪欢寮曠敤鍏崇郴锛岄�氳繃uni_modules寮曠敤缁勪欢
+
+## 1.0.4锛�2021-02-05锛�
+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
diff --git a/app/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/en.json b/app/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/en.json
new file mode 100644
index 0000000..dcdba41
--- /dev/null
+++ b/app/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/en.json
@@ -0,0 +1,6 @@
+{
+ "uni-goods-nav.options.shop": "shop",
+ "uni-goods-nav.options.cart": "cart",
+ "uni-goods-nav.buttonGroup.addToCart": "add to cart",
+ "uni-goods-nav.buttonGroup.buyNow": "buy now"
+}
diff --git a/app/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/index.js b/app/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/index.js
new file mode 100644
index 0000000..de7509c
--- /dev/null
+++ b/app/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/index.js
@@ -0,0 +1,8 @@
+import en from './en.json'
+import zhHans from './zh-Hans.json'
+import zhHant from './zh-Hant.json'
+export default {
+ en,
+ 'zh-Hans': zhHans,
+ 'zh-Hant': zhHant
+}
diff --git a/app/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/zh-Hans.json b/app/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/zh-Hans.json
new file mode 100644
index 0000000..48ee344
--- /dev/null
+++ b/app/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/zh-Hans.json
@@ -0,0 +1,6 @@
+{
+ "uni-goods-nav.options.shop": "搴楅摵",
+ "uni-goods-nav.options.cart": "璐墿杞�",
+ "uni-goods-nav.buttonGroup.addToCart": "鍔犲叆璐墿杞�",
+ "uni-goods-nav.buttonGroup.buyNow": "绔嬪嵆璐拱"
+}
diff --git a/app/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/zh-Hant.json b/app/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/zh-Hant.json
new file mode 100644
index 0000000..d0a0255
--- /dev/null
+++ b/app/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/zh-Hant.json
@@ -0,0 +1,6 @@
+{
+ "uni-goods-nav.options.shop": "搴楅嫪",
+ "uni-goods-nav.options.cart": "璩肩墿杌�",
+ "uni-goods-nav.buttonGroup.addToCart": "鍔犲叆璩肩墿杌�",
+ "uni-goods-nav.buttonGroup.buyNow": "绔嬪嵆璩艰卜"
+}
diff --git a/app/uni_modules/uni-goods-nav/components/uni-goods-nav/uni-goods-nav.vue b/app/uni_modules/uni-goods-nav/components/uni-goods-nav/uni-goods-nav.vue
new file mode 100644
index 0000000..8a16b17
--- /dev/null
+++ b/app/uni_modules/uni-goods-nav/components/uni-goods-nav/uni-goods-nav.vue
@@ -0,0 +1,229 @@
+<template>
+ <view class="uni-goods-nav">
+ <!-- 搴曢儴鍗犱綅 -->
+ <view class="uni-tab__seat" />
+ <view class="uni-tab__cart-box flex">
+ <view class="flex uni-tab__cart-sub-left">
+ <view v-for="(item,index) in options" :key="index" class="flex uni-tab__cart-button-left uni-tab__shop-cart" @click="onClick(index,item)">
+ <view class="uni-tab__icon">
+ <uni-icons :type="item.icon" size="20" color="#646566"></uni-icons>
+ <!-- <image class="image" :src="item.icon" mode="widthFix" /> -->
+ </view>
+ <text class="uni-tab__text">{{ item.text }}</text>
+ <view class="flex uni-tab__dot-box">
+ <text v-if="item.info" :class="{ 'uni-tab__dots': item.info > 9 }" class="uni-tab__dot " :style="{'backgroundColor':item.infoBackgroundColor?item.infoBackgroundColor:'#ff0000',
+ color:item.infoColor?item.infoColor:'#fff'
+ }">{{ item.info }}</text>
+ </view>
+ </view>
+ </view>
+ <view :class="{'uni-tab__right':fill}" class="flex uni-tab__cart-sub-right ">
+ <view v-for="(item,index) in buttonGroup" :key="index" :style="{background:item.backgroundColor,color:item.color}"
+ class="flex uni-tab__cart-button-right" @click="buttonClick(index,item)"><text :style="{color:item.color}" class="uni-tab__cart-button-right-text">{{ item.text }}</text></view>
+ </view>
+ </view>
+ </view>
+</template>
+
+<script>
+ import {
+ initVueI18n
+ } from '@dcloudio/uni-i18n'
+ import messages from './i18n/index.js'
+ const { t } = initVueI18n(messages)
+ /**
+ * GoodsNav 鍟嗗搧瀵艰埅
+ * @description 鍟嗗搧鍔犲叆璐墿杞︺�佺珛鍗宠喘涔扮瓑
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=865
+ * @property {Array} options 缁勪欢鍙傛暟
+ * @property {Array} buttonGroup 缁勪欢鎸夐挳缁勫弬鏁�
+ * @property {Boolean} fill = [true | false] 缁勪欢鎸夐挳缁勫弬鏁�
+ * @property {Boolean} stat 鏄惁寮�鍚粺璁″姛鑳�
+ * @event {Function} click 宸︿晶鐐瑰嚮浜嬩欢
+ * @event {Function} buttonClick 鍙充晶鎸夐挳缁勭偣鍑讳簨浠�
+ * @example <uni-goods-nav :fill="true" options="" buttonGroup="buttonGroup" @click="" @buttonClick="" />
+ */
+ export default {
+ name: 'UniGoodsNav',
+ emits:['click','buttonClick'],
+ props: {
+ options: {
+ type: Array,
+ default () {
+ return [{
+ icon: 'shop',
+ text: t("uni-goods-nav.options.shop"),
+ }, {
+ icon: 'cart',
+ text: t("uni-goods-nav.options.cart")
+ }]
+ }
+ },
+ buttonGroup: {
+ type: Array,
+ default () {
+ return [{
+ text: t("uni-goods-nav.buttonGroup.addToCart"),
+ backgroundColor: 'linear-gradient(90deg, #FFCD1E, #FF8A18)',
+ color: '#fff'
+ },
+ {
+ text: t("uni-goods-nav.buttonGroup.buyNow"),
+ backgroundColor: 'linear-gradient(90deg, #FE6035, #EF1224)',
+ color: '#fff'
+ }
+ ]
+ }
+ },
+ fill: {
+ type: Boolean,
+ default: false
+ },
+ stat:{
+ type: Boolean,
+ default: false
+ }
+ },
+ methods: {
+ onClick(index, item) {
+ this.$emit('click', {
+ index,
+ content: item,
+ })
+ },
+ buttonClick(index, item) {
+ if (uni.report && this.stat) {
+ uni.report(item.text, item.text)
+ }
+ this.$emit('buttonClick', {
+ index,
+ content: item
+ })
+ }
+ }
+ }
+</script>
+
+<style lang="scss" >
+ .flex {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ }
+
+ .uni-goods-nav {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex: 1;
+ flex-direction: row;
+ }
+
+ .uni-tab__cart-box {
+ flex: 1;
+ height: 50px;
+ background-color: #fff;
+ z-index: 900;
+ }
+
+ .uni-tab__cart-sub-left {
+ padding: 0 5px;
+ }
+
+ .uni-tab__cart-sub-right {
+ flex: 1;
+ }
+
+ .uni-tab__right {
+ margin: 5px 0;
+ margin-right: 10px;
+ border-radius: 100px;
+ overflow: hidden;
+ }
+
+ .uni-tab__cart-button-left {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ // flex: 1;
+ position: relative;
+ justify-content: center;
+ align-items: center;
+ flex-direction: column;
+ margin: 0 10px;
+ /* #ifdef H5 */
+ cursor: pointer;
+ /* #endif */
+ }
+
+ .uni-tab__icon {
+ width: 18px;
+ height: 18px;
+ }
+
+ .image {
+ width: 18px;
+ height: 18px;
+ }
+
+ .uni-tab__text {
+ margin-top: 3px;
+ font-size: 12px;
+ color: #646566;
+ }
+
+ .uni-tab__cart-button-right {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ flex-direction: column;
+ /* #endif */
+ flex: 1;
+ justify-content: center;
+ align-items: center;
+ /* #ifdef H5 */
+ cursor: pointer;
+ /* #endif */
+ }
+
+ .uni-tab__cart-button-right-text {
+ font-size: 14px;
+ color: #fff;
+ }
+
+ .uni-tab__cart-button-right:active {
+ opacity: 0.7;
+ }
+
+ .uni-tab__dot-box {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ flex-direction: column;
+ /* #endif */
+ position: absolute;
+ right: -2px;
+ top: 2px;
+ justify-content: center;
+ align-items: center;
+ // width: 0;
+ // height: 0;
+ }
+
+ .uni-tab__dot {
+ // width: 30rpx;
+ // height: 30rpx;
+ padding: 0 4px;
+ line-height: 15px;
+ color: #ffffff;
+ text-align: center;
+ font-size: 12px;
+ background-color: #ff0000;
+ border-radius: 15px;
+ }
+
+ .uni-tab__dots {
+ padding: 0 4px;
+ // width: auto;
+ border-radius: 15px;
+ }
+</style>
diff --git a/app/uni_modules/uni-goods-nav/package.json b/app/uni_modules/uni-goods-nav/package.json
new file mode 100644
index 0000000..636e45e
--- /dev/null
+++ b/app/uni_modules/uni-goods-nav/package.json
@@ -0,0 +1,88 @@
+{
+ "id": "uni-goods-nav",
+ "displayName": "uni-goods-nav 鍟嗗搧瀵艰埅",
+ "version": "1.2.1",
+ "description": "鍟嗗搧瀵艰埅缁勪欢涓昏鐢ㄤ簬鐢靛晢绫诲簲鐢ㄥ簳閮ㄥ鑸紝鍙嚜瀹氫箟鍔犲叆璐墿杞︼紝璐拱绛夋搷浣�",
+ "keywords": [
+ "uni-ui",
+ "uniui",
+ "鍟嗗搧瀵艰埅"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "鍓嶇缁勪欢",
+ "閫氱敤缁勪欢"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": [
+ "uni-scss",
+ "uni-icons"
+ ],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "u",
+ "鑱旂洘": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
diff --git a/app/uni_modules/uni-goods-nav/readme.md b/app/uni_modules/uni-goods-nav/readme.md
new file mode 100644
index 0000000..07df93f
--- /dev/null
+++ b/app/uni_modules/uni-goods-nav/readme.md
@@ -0,0 +1,10 @@
+
+
+## GoodsNav 鍟嗗搧瀵艰埅
+> **缁勪欢鍚嶏細uni-goods-nav**
+> 浠g爜鍧楋細 `uGoodsNav`
+
+鍟嗗搧鍔犲叆璐墿杞︼紝绔嬪嵆璐拱绛夈��
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-goods-nav)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
\ No newline at end of file
diff --git a/app/uni_modules/uni-grid/changelog.md b/app/uni_modules/uni-grid/changelog.md
new file mode 100644
index 0000000..d301166
--- /dev/null
+++ b/app/uni_modules/uni-grid/changelog.md
@@ -0,0 +1,13 @@
+## 1.4.0锛�2021-11-19锛�
+- 浼樺寲 缁勪欢UI锛屽苟鎻愪緵璁捐璧勬簮锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 鏂囨。杩佺Щ锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/uni-grid](https://uniapp.dcloud.io/component/uniui/uni-grid)
+## 1.3.2锛�2021-11-09锛�
+- 鏂板 鎻愪緵缁勪欢璁捐璧勬簮锛岀粍浠舵牱寮忚皟鏁�
+## 1.3.1锛�2021-07-30锛�
+- 浼樺寲 vue3涓嬩簨浠惰鍛婄殑闂
+## 1.3.0锛�2021-07-13锛�
+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤簐ue3椤圭洰锛岃瑙� [uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+## 1.2.4锛�2021-05-12锛�
+- 鏂板 缁勪欢绀轰緥鍦板潃
+## 1.2.3锛�2021-02-05锛�
+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
diff --git a/app/uni_modules/uni-grid/components/uni-grid-item/uni-grid-item.vue b/app/uni_modules/uni-grid/components/uni-grid-item/uni-grid-item.vue
new file mode 100644
index 0000000..20fd54e
--- /dev/null
+++ b/app/uni_modules/uni-grid/components/uni-grid-item/uni-grid-item.vue
@@ -0,0 +1,127 @@
+<template>
+ <view v-if="width" :style="'width:'+width+';'+(square?'height:'+width:'')" class="uni-grid-item">
+ <view :class="{ 'uni-grid-item--border': showBorder, 'uni-grid-item--border-top': showBorder && index < column, 'uni-highlight': highlight }"
+ :style="{'border-right-color': borderColor ,'border-bottom-color': borderColor ,'border-top-color': borderColor }"
+ class="uni-grid-item__box" @click="_onClick">
+ <slot />
+ </view>
+ </view>
+</template>
+
+<script>
+ /**
+ * GridItem 瀹牸
+ * @description 瀹牸缁勪欢
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=27
+ * @property {Number} index 瀛愮粍浠剁殑鍞竴鏍囪瘑 锛岀偣鍑籫ird浼氳繑鍥炲綋鍓嶇殑鏍囪瘑
+ */
+ export default {
+ name: 'UniGridItem',
+ inject: ['grid'],
+ props: {
+ index: {
+ type: Number,
+ default: 0
+ }
+ },
+ data() {
+ return {
+ column: 0,
+ showBorder: true,
+ square: true,
+ highlight: true,
+ left: 0,
+ top: 0,
+ openNum: 2,
+ width: 0,
+ borderColor: '#e5e5e5'
+ }
+ },
+ created() {
+ this.column = this.grid.column
+ this.showBorder = this.grid.showBorder
+ this.square = this.grid.square
+ this.highlight = this.grid.highlight
+ this.top = this.hor === 0 ? this.grid.hor : this.hor
+ this.left = this.ver === 0 ? this.grid.ver : this.ver
+ this.borderColor = this.grid.borderColor
+ this.grid.children.push(this)
+ // this.grid.init()
+ this.width = this.grid.width
+ },
+ beforeDestroy() {
+ this.grid.children.forEach((item, index) => {
+ if (item === this) {
+ this.grid.children.splice(index, 1)
+ }
+ })
+ },
+ methods: {
+ _onClick() {
+ this.grid.change({
+ detail: {
+ index: this.index
+ }
+ })
+ }
+ }
+ }
+</script>
+
+<style lang="scss" >
+ .uni-grid-item {
+ /* #ifndef APP-NVUE */
+ height: 100%;
+ display: flex;
+ /* #endif */
+ /* #ifdef H5 */
+ cursor: pointer;
+ /* #endif */
+ }
+
+ .uni-grid-item__box {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ width: 100%;
+ /* #endif */
+ position: relative;
+ flex: 1;
+ flex-direction: column;
+ // justify-content: center;
+ // align-items: center;
+ }
+
+ .uni-grid-item--border {
+ position: relative;
+ /* #ifdef APP-NVUE */
+ border-bottom-color: #D2D2D2;
+ border-bottom-style: solid;
+ border-bottom-width: 0.5px;
+ border-right-color: #D2D2D2;
+ border-right-style: solid;
+ border-right-width: 0.5px;
+ /* #endif */
+ /* #ifndef APP-NVUE */
+ z-index: 0;
+ border-bottom: 1px #D2D2D2 solid;
+ border-right: 1px #D2D2D2 solid;
+ /* #endif */
+ }
+ .uni-grid-item--border-top {
+ position: relative;
+ /* #ifdef APP-NVUE */
+ border-top-color: #D2D2D2;
+ border-top-style: solid;
+ border-top-width: 0.5px;
+ /* #endif */
+ /* #ifndef APP-NVUE */
+ border-top: 1px #D2D2D2 solid;
+ z-index: 0;
+ /* #endif */
+ }
+
+
+ .uni-highlight:active {
+ background-color: #f1f1f1;
+ }
+</style>
diff --git a/app/uni_modules/uni-grid/components/uni-grid/uni-grid.vue b/app/uni_modules/uni-grid/components/uni-grid/uni-grid.vue
new file mode 100644
index 0000000..96a412f
--- /dev/null
+++ b/app/uni_modules/uni-grid/components/uni-grid/uni-grid.vue
@@ -0,0 +1,142 @@
+<template>
+ <view class="uni-grid-wrap">
+ <view :id="elId" ref="uni-grid" class="uni-grid" :class="{ 'uni-grid--border': showBorder }" :style="{ 'border-left-color':borderColor}">
+ <slot />
+ </view>
+ </view>
+</template>
+
+<script>
+ // #ifdef APP-NVUE
+ const dom = uni.requireNativePlugin('dom');
+ // #endif
+
+ /**
+ * Grid 瀹牸
+ * @description 瀹牸缁勪欢
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=27
+ * @property {Number} column 姣忓垪鏄剧ず涓暟
+ * @property {String} borderColor 杈规棰滆壊
+ * @property {Boolean} showBorder 鏄惁鏄剧ず杈规
+ * @property {Boolean} square 鏄惁鏂瑰舰鏄剧ず
+ * @property {Boolean} Boolean 鐐瑰嚮鑳屾櫙鏄惁楂樹寒
+ * @event {Function} change 鐐瑰嚮 grid 瑙﹀彂锛宔={detail:{index:0}}锛宨ndex 涓哄綋鍓嶇偣鍑� gird 涓嬫爣
+ */
+ export default {
+ name: 'UniGrid',
+ emits:['change'],
+ props: {
+ // 姣忓垪鏄剧ず涓暟
+ column: {
+ type: Number,
+ default: 3
+ },
+ // 鏄惁鏄剧ず杈规
+ showBorder: {
+ type: Boolean,
+ default: true
+ },
+ // 杈规棰滆壊
+ borderColor: {
+ type: String,
+ default: '#D2D2D2'
+ },
+ // 鏄惁姝f柟褰㈡樉绀�,榛樿涓� true
+ square: {
+ type: Boolean,
+ default: true
+ },
+ highlight: {
+ type: Boolean,
+ default: true
+ }
+ },
+ provide() {
+ return {
+ grid: this
+ }
+ },
+ data() {
+ const elId = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`
+ return {
+ elId,
+ width: 0
+ }
+ },
+ created() {
+ this.children = []
+ },
+ mounted() {
+ this.$nextTick(()=>{
+ this.init()
+ })
+ },
+ methods: {
+ init() {
+ setTimeout(() => {
+ this._getSize((width) => {
+ this.children.forEach((item, index) => {
+ item.width = width
+ })
+ })
+ }, 50)
+ },
+ change(e) {
+ this.$emit('change', e)
+ },
+ _getSize(fn) {
+ // #ifndef APP-NVUE
+ uni.createSelectorQuery()
+ .in(this)
+ .select(`#${this.elId}`)
+ .boundingClientRect()
+ .exec(ret => {
+ this.width = parseInt((ret[0].width - 1) / this.column) + 'px'
+ fn(this.width)
+ })
+ // #endif
+ // #ifdef APP-NVUE
+ dom.getComponentRect(this.$refs['uni-grid'], (ret) => {
+ this.width = parseInt((ret.size.width - 1) / this.column) + 'px'
+ fn(this.width)
+ })
+ // #endif
+ }
+ }
+ }
+</script>
+
+<style lang="scss" >
+ .uni-grid-wrap {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex: 1;
+ flex-direction: column;
+ /* #ifdef H5 */
+ width: 100%;
+ /* #endif */
+ }
+
+ .uni-grid {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ // flex: 1;
+ flex-direction: row;
+ flex-wrap: wrap;
+ }
+
+ .uni-grid--border {
+ position: relative;
+ /* #ifdef APP-NVUE */
+ border-left-color: #D2D2D2;
+ border-left-style: solid;
+ border-left-width: 0.5px;
+ /* #endif */
+ /* #ifndef APP-NVUE */
+ z-index: 1;
+ border-left: 1px #D2D2D2 solid;
+ /* #endif */
+ }
+</style>
diff --git a/app/uni_modules/uni-grid/package.json b/app/uni_modules/uni-grid/package.json
new file mode 100644
index 0000000..ccb2c91
--- /dev/null
+++ b/app/uni_modules/uni-grid/package.json
@@ -0,0 +1,86 @@
+{
+ "id": "uni-grid",
+ "displayName": "uni-grid 瀹牸",
+ "version": "1.4.0",
+ "description": "Grid 瀹牸缁勪欢锛屾彁渚涚Щ鍔ㄧ甯歌鐨勫鏍煎竷灞�锛屽涔濆鏍笺��",
+ "keywords": [
+ "uni-ui",
+ "uniui",
+ "涔濆鏍�",
+ "琛ㄦ牸"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "鍓嶇缁勪欢",
+ "閫氱敤缁勪欢"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": ["uni-scss","uni-icons"],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "u",
+ "鑱旂洘": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
diff --git a/app/uni_modules/uni-grid/readme.md b/app/uni_modules/uni-grid/readme.md
new file mode 100644
index 0000000..0aa44cc
--- /dev/null
+++ b/app/uni_modules/uni-grid/readme.md
@@ -0,0 +1,11 @@
+
+
+## Grid 瀹牸
+> **缁勪欢鍚嶏細uni-grid**
+> 浠g爜鍧楋細 `uGrid`
+
+
+瀹牸缁勪欢銆�
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-grid)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
\ No newline at end of file
diff --git a/app/uni_modules/uni-group/changelog.md b/app/uni_modules/uni-group/changelog.md
new file mode 100644
index 0000000..a7024fd
--- /dev/null
+++ b/app/uni_modules/uni-group/changelog.md
@@ -0,0 +1,16 @@
+## 1.2.2锛�2022-05-30锛�
+- 鏂板 stat灞炴�э紝鏄惁寮�鍚痷ni缁熻鍔熻兘
+## 1.2.1锛�2021-11-22锛�
+- 淇 vue3涓煇浜泂css鍙橀噺鏃犳硶鎵惧埌鐨勯棶棰�
+## 1.2.0锛�2021-11-19锛�
+- 浼樺寲 缁勪欢UI锛屽苟鎻愪緵璁捐璧勬簮锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 鏂囨。杩佺Щ锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/uni-group](https://uniapp.dcloud.io/component/uniui/uni-group)
+## 1.1.7锛�2021-11-08锛�
+## 1.1.0锛�2021-07-30锛�
+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤簐ue3椤圭洰锛岃瑙� [uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+- 浼樺寲 缁勪欢鏂囨。
+## 1.0.3锛�2021-05-12锛�
+- 鏂板 缁勪欢绀轰緥鍦板潃
+## 1.0.2锛�2021-02-05锛�
+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
+- 浼樺寲 鍏煎 nvue 椤甸潰
diff --git a/app/uni_modules/uni-group/components/uni-group/uni-group.vue b/app/uni_modules/uni-group/components/uni-group/uni-group.vue
new file mode 100644
index 0000000..3425ecd
--- /dev/null
+++ b/app/uni_modules/uni-group/components/uni-group/uni-group.vue
@@ -0,0 +1,134 @@
+<template>
+ <view class="uni-group" :class="['uni-group--'+mode ,margin?'group-margin':'']" :style="{marginTop: `${top}px` }">
+ <slot name="title">
+ <view v-if="title" class="uni-group__title" :style="{'padding-left':border?'30px':'15px'}">
+ <text class="uni-group__title-text">{{ title }}</text>
+ </view>
+ </slot>
+ <view class="uni-group__content" :class="{'group-conent-padding':border}">
+ <slot />
+ </view>
+ </view>
+</template>
+
+<script>
+ /**
+ * Group 鍒嗙粍
+ * @description 琛ㄥ崟瀛楁鍒嗙粍
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=3281
+ * @property {String} title 涓绘爣棰�
+ * @property {Number} top 鍒嗙粍闂撮殧
+ * @property {Number} mode 妯″紡
+ */
+ export default {
+ name: 'uniGroup',
+ emits:['click'],
+ props: {
+ title: {
+ type: String,
+ default: ''
+ },
+ top: {
+ type: [Number, String],
+ default: 10
+ },
+ mode: {
+ type: String,
+ default: 'default'
+ },
+ stat:{
+ type: Boolean,
+ default: false
+ }
+ },
+ data() {
+ return {
+ margin: false,
+ border: false
+ }
+ },
+ watch: {
+ title(newVal) {
+ if (uni.report && this.stat && newVal !== '') {
+ uni.report('title', newVal)
+ }
+ }
+ },
+ created() {
+ this.form = this.getForm()
+ if (this.form) {
+ this.margin = true
+ this.border = this.form.border
+ }
+ },
+ methods: {
+ /**
+ * 鑾峰彇鐖跺厓绱犲疄渚�
+ */
+ getForm() {
+ let parent = this.$parent;
+ let parentName = parent.$options.name;
+ while (parentName !== 'uniForms') {
+ parent = parent.$parent;
+ if (!parent) return false
+ parentName = parent.$options.name;
+ }
+ return parent;
+ },
+ onClick() {
+ this.$emit('click')
+ }
+ }
+ }
+</script>
+<style lang="scss" >
+ .uni-group {
+ background: #fff;
+ margin-top: 10px;
+ // border: 1px red solid;
+ }
+
+ .group-margin {
+ // margin: 0 -15px;
+ }
+
+ .uni-group__title {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ align-items: center;
+ padding-left: 15px;
+ height: 40px;
+ background-color: #eee;
+ font-weight: normal;
+ color: #666;
+ }
+
+ .uni-group__content {
+ padding: 15px;
+ // padding-bottom: 5px;
+ // background-color: #FFF;
+ }
+
+ .group-conent-padding {
+ padding: 0 15px;
+ }
+
+ .uni-group__title-text {
+ font-size: 14px;
+ color: #666;
+ }
+
+ .distraction {
+ flex-direction: row;
+ align-items: center;
+ }
+
+ .uni-group--card {
+ margin: 10px;
+ border-radius: 5px;
+ overflow: hidden;
+ box-shadow: 0 0 5px 1px rgba($color: #000000, $alpha: 0.08);
+ }
+</style>
diff --git a/app/uni_modules/uni-group/package.json b/app/uni_modules/uni-group/package.json
new file mode 100644
index 0000000..ea00a08
--- /dev/null
+++ b/app/uni_modules/uni-group/package.json
@@ -0,0 +1,87 @@
+{
+ "id": "uni-group",
+ "displayName": "uni-group 鍒嗙粍",
+ "version": "1.2.2",
+ "description": "鍒嗙粍缁勪欢鍙敤浜庡皢缁勪欢鐢ㄤ簬鍒嗙粍锛屾坊鍔犻棿闅旓紝浠ヤ骇鐢熸槑鏄剧殑鍖哄潡",
+ "keywords": [
+ "uni-ui",
+ "uniui",
+ "group",
+ "鍒嗙粍",
+ ""
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "鍓嶇缁勪欢",
+ "閫氱敤缁勪欢"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": ["uni-scss"],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "u",
+ "鑱旂洘": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/uni_modules/uni-group/readme.md b/app/uni_modules/uni-group/readme.md
new file mode 100644
index 0000000..bae67f4
--- /dev/null
+++ b/app/uni_modules/uni-group/readme.md
@@ -0,0 +1,9 @@
+
+## Group 鍒嗙粍
+> **缁勪欢鍚嶏細uni-group**
+> 浠g爜鍧楋細 `uGroup`
+
+鍒嗙粍缁勪欢鍙敤浜庡皢缁勪欢鍒嗙粍锛屾坊鍔犻棿闅旓紝浠ヤ骇鐢熸槑鏄剧殑鍖哄潡銆�
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-group)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
\ No newline at end of file
diff --git a/app/uni_modules/uni-icons/changelog.md b/app/uni_modules/uni-icons/changelog.md
new file mode 100644
index 0000000..6449885
--- /dev/null
+++ b/app/uni_modules/uni-icons/changelog.md
@@ -0,0 +1,22 @@
+## 1.3.5锛�2022-01-24锛�
+- 浼樺寲 size 灞炴�у彲浠ヤ紶鍏ヤ笉甯﹀崟浣嶇殑瀛楃涓叉暟鍊�
+## 1.3.4锛�2022-01-24锛�
+- 浼樺寲 size 鏀寔鍏朵粬鍗曚綅
+## 1.3.3锛�2022-01-17锛�
+- 淇 nvue 鏈変簺鍥炬爣涓嶆樉绀虹殑bug锛屽吋瀹硅�佺増鏈浘鏍�
+## 1.3.2锛�2021-12-01锛�
+- 浼樺寲 绀轰緥鍙鍒跺浘鏍囧悕绉�
+## 1.3.1锛�2021-11-23锛�
+- 浼樺寲 鍏煎鏃х粍浠� type 鍊�
+## 1.3.0锛�2021-11-19锛�
+- 鏂板 鏇村鍥炬爣
+- 浼樺寲 鑷畾涔夊浘鏍囦娇鐢ㄦ柟寮�
+- 浼樺寲 缁勪欢UI锛屽苟鎻愪緵璁捐璧勬簮锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 鏂囨。杩佺Щ锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/uni-icons](https://uniapp.dcloud.io/component/uniui/uni-icons)
+## 1.1.7锛�2021-11-08锛�
+## 1.2.0锛�2021-07-30锛�
+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤簐ue3椤圭洰锛岃瑙� [uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+## 1.1.5锛�2021-05-12锛�
+- 鏂板 缁勪欢绀轰緥鍦板潃
+## 1.1.4锛�2021-02-05锛�
+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
diff --git a/app/uni_modules/uni-icons/components/uni-icons/icons.js b/app/uni_modules/uni-icons/components/uni-icons/icons.js
new file mode 100644
index 0000000..7889936
--- /dev/null
+++ b/app/uni_modules/uni-icons/components/uni-icons/icons.js
@@ -0,0 +1,1169 @@
+export default {
+ "id": "2852637",
+ "name": "uniui鍥炬爣搴�",
+ "font_family": "uniicons",
+ "css_prefix_text": "uniui-",
+ "description": "",
+ "glyphs": [
+ {
+ "icon_id": "25027049",
+ "name": "yanse",
+ "font_class": "color",
+ "unicode": "e6cf",
+ "unicode_decimal": 59087
+ },
+ {
+ "icon_id": "25027048",
+ "name": "wallet",
+ "font_class": "wallet",
+ "unicode": "e6b1",
+ "unicode_decimal": 59057
+ },
+ {
+ "icon_id": "25015720",
+ "name": "settings-filled",
+ "font_class": "settings-filled",
+ "unicode": "e6ce",
+ "unicode_decimal": 59086
+ },
+ {
+ "icon_id": "25015434",
+ "name": "shimingrenzheng-filled",
+ "font_class": "auth-filled",
+ "unicode": "e6cc",
+ "unicode_decimal": 59084
+ },
+ {
+ "icon_id": "24934246",
+ "name": "shop-filled",
+ "font_class": "shop-filled",
+ "unicode": "e6cd",
+ "unicode_decimal": 59085
+ },
+ {
+ "icon_id": "24934159",
+ "name": "staff-filled-01",
+ "font_class": "staff-filled",
+ "unicode": "e6cb",
+ "unicode_decimal": 59083
+ },
+ {
+ "icon_id": "24932461",
+ "name": "VIP-filled",
+ "font_class": "vip-filled",
+ "unicode": "e6c6",
+ "unicode_decimal": 59078
+ },
+ {
+ "icon_id": "24932462",
+ "name": "plus_circle_fill",
+ "font_class": "plus-filled",
+ "unicode": "e6c7",
+ "unicode_decimal": 59079
+ },
+ {
+ "icon_id": "24932463",
+ "name": "folder_add-filled",
+ "font_class": "folder-add-filled",
+ "unicode": "e6c8",
+ "unicode_decimal": 59080
+ },
+ {
+ "icon_id": "24932464",
+ "name": "yanse-filled",
+ "font_class": "color-filled",
+ "unicode": "e6c9",
+ "unicode_decimal": 59081
+ },
+ {
+ "icon_id": "24932465",
+ "name": "tune-filled",
+ "font_class": "tune-filled",
+ "unicode": "e6ca",
+ "unicode_decimal": 59082
+ },
+ {
+ "icon_id": "24932455",
+ "name": "a-rilidaka-filled",
+ "font_class": "calendar-filled",
+ "unicode": "e6c0",
+ "unicode_decimal": 59072
+ },
+ {
+ "icon_id": "24932456",
+ "name": "notification-filled",
+ "font_class": "notification-filled",
+ "unicode": "e6c1",
+ "unicode_decimal": 59073
+ },
+ {
+ "icon_id": "24932457",
+ "name": "wallet-filled",
+ "font_class": "wallet-filled",
+ "unicode": "e6c2",
+ "unicode_decimal": 59074
+ },
+ {
+ "icon_id": "24932458",
+ "name": "paihangbang-filled",
+ "font_class": "medal-filled",
+ "unicode": "e6c3",
+ "unicode_decimal": 59075
+ },
+ {
+ "icon_id": "24932459",
+ "name": "gift-filled",
+ "font_class": "gift-filled",
+ "unicode": "e6c4",
+ "unicode_decimal": 59076
+ },
+ {
+ "icon_id": "24932460",
+ "name": "fire-filled",
+ "font_class": "fire-filled",
+ "unicode": "e6c5",
+ "unicode_decimal": 59077
+ },
+ {
+ "icon_id": "24928001",
+ "name": "refreshempty",
+ "font_class": "refreshempty",
+ "unicode": "e6bf",
+ "unicode_decimal": 59071
+ },
+ {
+ "icon_id": "24926853",
+ "name": "location-ellipse",
+ "font_class": "location-filled",
+ "unicode": "e6af",
+ "unicode_decimal": 59055
+ },
+ {
+ "icon_id": "24926735",
+ "name": "person-filled",
+ "font_class": "person-filled",
+ "unicode": "e69d",
+ "unicode_decimal": 59037
+ },
+ {
+ "icon_id": "24926703",
+ "name": "personadd-filled",
+ "font_class": "personadd-filled",
+ "unicode": "e698",
+ "unicode_decimal": 59032
+ },
+ {
+ "icon_id": "24923351",
+ "name": "back",
+ "font_class": "back",
+ "unicode": "e6b9",
+ "unicode_decimal": 59065
+ },
+ {
+ "icon_id": "24923352",
+ "name": "forward",
+ "font_class": "forward",
+ "unicode": "e6ba",
+ "unicode_decimal": 59066
+ },
+ {
+ "icon_id": "24923353",
+ "name": "arrowthinright",
+ "font_class": "arrow-right",
+ "unicode": "e6bb",
+ "unicode_decimal": 59067
+ },
+ {
+ "icon_id": "24923353",
+ "name": "arrowthinright",
+ "font_class": "arrowthinright",
+ "unicode": "e6bb",
+ "unicode_decimal": 59067
+ },
+ {
+ "icon_id": "24923354",
+ "name": "arrowthinleft",
+ "font_class": "arrow-left",
+ "unicode": "e6bc",
+ "unicode_decimal": 59068
+ },
+ {
+ "icon_id": "24923354",
+ "name": "arrowthinleft",
+ "font_class": "arrowthinleft",
+ "unicode": "e6bc",
+ "unicode_decimal": 59068
+ },
+ {
+ "icon_id": "24923355",
+ "name": "arrowthinup",
+ "font_class": "arrow-up",
+ "unicode": "e6bd",
+ "unicode_decimal": 59069
+ },
+ {
+ "icon_id": "24923355",
+ "name": "arrowthinup",
+ "font_class": "arrowthinup",
+ "unicode": "e6bd",
+ "unicode_decimal": 59069
+ },
+ {
+ "icon_id": "24923356",
+ "name": "arrowthindown",
+ "font_class": "arrow-down",
+ "unicode": "e6be",
+ "unicode_decimal": 59070
+ },{
+ "icon_id": "24923356",
+ "name": "arrowthindown",
+ "font_class": "arrowthindown",
+ "unicode": "e6be",
+ "unicode_decimal": 59070
+ },
+ {
+ "icon_id": "24923349",
+ "name": "arrowdown",
+ "font_class": "bottom",
+ "unicode": "e6b8",
+ "unicode_decimal": 59064
+ },{
+ "icon_id": "24923349",
+ "name": "arrowdown",
+ "font_class": "arrowdown",
+ "unicode": "e6b8",
+ "unicode_decimal": 59064
+ },
+ {
+ "icon_id": "24923346",
+ "name": "arrowright",
+ "font_class": "right",
+ "unicode": "e6b5",
+ "unicode_decimal": 59061
+ },
+ {
+ "icon_id": "24923346",
+ "name": "arrowright",
+ "font_class": "arrowright",
+ "unicode": "e6b5",
+ "unicode_decimal": 59061
+ },
+ {
+ "icon_id": "24923347",
+ "name": "arrowup",
+ "font_class": "top",
+ "unicode": "e6b6",
+ "unicode_decimal": 59062
+ },
+ {
+ "icon_id": "24923347",
+ "name": "arrowup",
+ "font_class": "arrowup",
+ "unicode": "e6b6",
+ "unicode_decimal": 59062
+ },
+ {
+ "icon_id": "24923348",
+ "name": "arrowleft",
+ "font_class": "left",
+ "unicode": "e6b7",
+ "unicode_decimal": 59063
+ },
+ {
+ "icon_id": "24923348",
+ "name": "arrowleft",
+ "font_class": "arrowleft",
+ "unicode": "e6b7",
+ "unicode_decimal": 59063
+ },
+ {
+ "icon_id": "24923334",
+ "name": "eye",
+ "font_class": "eye",
+ "unicode": "e651",
+ "unicode_decimal": 58961
+ },
+ {
+ "icon_id": "24923335",
+ "name": "eye-filled",
+ "font_class": "eye-filled",
+ "unicode": "e66a",
+ "unicode_decimal": 58986
+ },
+ {
+ "icon_id": "24923336",
+ "name": "eye-slash",
+ "font_class": "eye-slash",
+ "unicode": "e6b3",
+ "unicode_decimal": 59059
+ },
+ {
+ "icon_id": "24923337",
+ "name": "eye-slash-filled",
+ "font_class": "eye-slash-filled",
+ "unicode": "e6b4",
+ "unicode_decimal": 59060
+ },
+ {
+ "icon_id": "24923305",
+ "name": "info-filled",
+ "font_class": "info-filled",
+ "unicode": "e649",
+ "unicode_decimal": 58953
+ },
+ {
+ "icon_id": "24923299",
+ "name": "reload-01",
+ "font_class": "reload",
+ "unicode": "e6b2",
+ "unicode_decimal": 59058
+ },
+ {
+ "icon_id": "24923195",
+ "name": "mic_slash_fill",
+ "font_class": "micoff-filled",
+ "unicode": "e6b0",
+ "unicode_decimal": 59056
+ },
+ {
+ "icon_id": "24923165",
+ "name": "map-pin-ellipse",
+ "font_class": "map-pin-ellipse",
+ "unicode": "e6ac",
+ "unicode_decimal": 59052
+ },
+ {
+ "icon_id": "24923166",
+ "name": "map-pin",
+ "font_class": "map-pin",
+ "unicode": "e6ad",
+ "unicode_decimal": 59053
+ },
+ {
+ "icon_id": "24923167",
+ "name": "location",
+ "font_class": "location",
+ "unicode": "e6ae",
+ "unicode_decimal": 59054
+ },
+ {
+ "icon_id": "24923064",
+ "name": "starhalf",
+ "font_class": "starhalf",
+ "unicode": "e683",
+ "unicode_decimal": 59011
+ },
+ {
+ "icon_id": "24923065",
+ "name": "star",
+ "font_class": "star",
+ "unicode": "e688",
+ "unicode_decimal": 59016
+ },
+ {
+ "icon_id": "24923066",
+ "name": "star-filled",
+ "font_class": "star-filled",
+ "unicode": "e68f",
+ "unicode_decimal": 59023
+ },
+ {
+ "icon_id": "24899646",
+ "name": "a-rilidaka",
+ "font_class": "calendar",
+ "unicode": "e6a0",
+ "unicode_decimal": 59040
+ },
+ {
+ "icon_id": "24899647",
+ "name": "fire",
+ "font_class": "fire",
+ "unicode": "e6a1",
+ "unicode_decimal": 59041
+ },
+ {
+ "icon_id": "24899648",
+ "name": "paihangbang",
+ "font_class": "medal",
+ "unicode": "e6a2",
+ "unicode_decimal": 59042
+ },
+ {
+ "icon_id": "24899649",
+ "name": "font",
+ "font_class": "font",
+ "unicode": "e6a3",
+ "unicode_decimal": 59043
+ },
+ {
+ "icon_id": "24899650",
+ "name": "gift",
+ "font_class": "gift",
+ "unicode": "e6a4",
+ "unicode_decimal": 59044
+ },
+ {
+ "icon_id": "24899651",
+ "name": "link",
+ "font_class": "link",
+ "unicode": "e6a5",
+ "unicode_decimal": 59045
+ },
+ {
+ "icon_id": "24899652",
+ "name": "notification",
+ "font_class": "notification",
+ "unicode": "e6a6",
+ "unicode_decimal": 59046
+ },
+ {
+ "icon_id": "24899653",
+ "name": "staff",
+ "font_class": "staff",
+ "unicode": "e6a7",
+ "unicode_decimal": 59047
+ },
+ {
+ "icon_id": "24899654",
+ "name": "VIP",
+ "font_class": "vip",
+ "unicode": "e6a8",
+ "unicode_decimal": 59048
+ },
+ {
+ "icon_id": "24899655",
+ "name": "folder_add",
+ "font_class": "folder-add",
+ "unicode": "e6a9",
+ "unicode_decimal": 59049
+ },
+ {
+ "icon_id": "24899656",
+ "name": "tune",
+ "font_class": "tune",
+ "unicode": "e6aa",
+ "unicode_decimal": 59050
+ },
+ {
+ "icon_id": "24899657",
+ "name": "shimingrenzheng",
+ "font_class": "auth",
+ "unicode": "e6ab",
+ "unicode_decimal": 59051
+ },
+ {
+ "icon_id": "24899565",
+ "name": "person",
+ "font_class": "person",
+ "unicode": "e699",
+ "unicode_decimal": 59033
+ },
+ {
+ "icon_id": "24899566",
+ "name": "email-filled",
+ "font_class": "email-filled",
+ "unicode": "e69a",
+ "unicode_decimal": 59034
+ },
+ {
+ "icon_id": "24899567",
+ "name": "phone-filled",
+ "font_class": "phone-filled",
+ "unicode": "e69b",
+ "unicode_decimal": 59035
+ },
+ {
+ "icon_id": "24899568",
+ "name": "phone",
+ "font_class": "phone",
+ "unicode": "e69c",
+ "unicode_decimal": 59036
+ },
+ {
+ "icon_id": "24899570",
+ "name": "email",
+ "font_class": "email",
+ "unicode": "e69e",
+ "unicode_decimal": 59038
+ },
+ {
+ "icon_id": "24899571",
+ "name": "personadd",
+ "font_class": "personadd",
+ "unicode": "e69f",
+ "unicode_decimal": 59039
+ },
+ {
+ "icon_id": "24899558",
+ "name": "chatboxes-filled",
+ "font_class": "chatboxes-filled",
+ "unicode": "e692",
+ "unicode_decimal": 59026
+ },
+ {
+ "icon_id": "24899559",
+ "name": "contact",
+ "font_class": "contact",
+ "unicode": "e693",
+ "unicode_decimal": 59027
+ },
+ {
+ "icon_id": "24899560",
+ "name": "chatbubble-filled",
+ "font_class": "chatbubble-filled",
+ "unicode": "e694",
+ "unicode_decimal": 59028
+ },
+ {
+ "icon_id": "24899561",
+ "name": "contact-filled",
+ "font_class": "contact-filled",
+ "unicode": "e695",
+ "unicode_decimal": 59029
+ },
+ {
+ "icon_id": "24899562",
+ "name": "chatboxes",
+ "font_class": "chatboxes",
+ "unicode": "e696",
+ "unicode_decimal": 59030
+ },
+ {
+ "icon_id": "24899563",
+ "name": "chatbubble",
+ "font_class": "chatbubble",
+ "unicode": "e697",
+ "unicode_decimal": 59031
+ },
+ {
+ "icon_id": "24881290",
+ "name": "upload-filled",
+ "font_class": "upload-filled",
+ "unicode": "e68e",
+ "unicode_decimal": 59022
+ },
+ {
+ "icon_id": "24881292",
+ "name": "upload",
+ "font_class": "upload",
+ "unicode": "e690",
+ "unicode_decimal": 59024
+ },
+ {
+ "icon_id": "24881293",
+ "name": "weixin",
+ "font_class": "weixin",
+ "unicode": "e691",
+ "unicode_decimal": 59025
+ },
+ {
+ "icon_id": "24881274",
+ "name": "compose",
+ "font_class": "compose",
+ "unicode": "e67f",
+ "unicode_decimal": 59007
+ },
+ {
+ "icon_id": "24881275",
+ "name": "qq",
+ "font_class": "qq",
+ "unicode": "e680",
+ "unicode_decimal": 59008
+ },
+ {
+ "icon_id": "24881276",
+ "name": "download-filled",
+ "font_class": "download-filled",
+ "unicode": "e681",
+ "unicode_decimal": 59009
+ },
+ {
+ "icon_id": "24881277",
+ "name": "pengyouquan",
+ "font_class": "pyq",
+ "unicode": "e682",
+ "unicode_decimal": 59010
+ },
+ {
+ "icon_id": "24881279",
+ "name": "sound",
+ "font_class": "sound",
+ "unicode": "e684",
+ "unicode_decimal": 59012
+ },
+ {
+ "icon_id": "24881280",
+ "name": "trash-filled",
+ "font_class": "trash-filled",
+ "unicode": "e685",
+ "unicode_decimal": 59013
+ },
+ {
+ "icon_id": "24881281",
+ "name": "sound-filled",
+ "font_class": "sound-filled",
+ "unicode": "e686",
+ "unicode_decimal": 59014
+ },
+ {
+ "icon_id": "24881282",
+ "name": "trash",
+ "font_class": "trash",
+ "unicode": "e687",
+ "unicode_decimal": 59015
+ },
+ {
+ "icon_id": "24881284",
+ "name": "videocam-filled",
+ "font_class": "videocam-filled",
+ "unicode": "e689",
+ "unicode_decimal": 59017
+ },
+ {
+ "icon_id": "24881285",
+ "name": "spinner-cycle",
+ "font_class": "spinner-cycle",
+ "unicode": "e68a",
+ "unicode_decimal": 59018
+ },
+ {
+ "icon_id": "24881286",
+ "name": "weibo",
+ "font_class": "weibo",
+ "unicode": "e68b",
+ "unicode_decimal": 59019
+ },
+ {
+ "icon_id": "24881288",
+ "name": "videocam",
+ "font_class": "videocam",
+ "unicode": "e68c",
+ "unicode_decimal": 59020
+ },
+ {
+ "icon_id": "24881289",
+ "name": "download",
+ "font_class": "download",
+ "unicode": "e68d",
+ "unicode_decimal": 59021
+ },
+ {
+ "icon_id": "24879601",
+ "name": "help",
+ "font_class": "help",
+ "unicode": "e679",
+ "unicode_decimal": 59001
+ },
+ {
+ "icon_id": "24879602",
+ "name": "navigate-filled",
+ "font_class": "navigate-filled",
+ "unicode": "e67a",
+ "unicode_decimal": 59002
+ },
+ {
+ "icon_id": "24879603",
+ "name": "plusempty",
+ "font_class": "plusempty",
+ "unicode": "e67b",
+ "unicode_decimal": 59003
+ },
+ {
+ "icon_id": "24879604",
+ "name": "smallcircle",
+ "font_class": "smallcircle",
+ "unicode": "e67c",
+ "unicode_decimal": 59004
+ },
+ {
+ "icon_id": "24879605",
+ "name": "minus-filled",
+ "font_class": "minus-filled",
+ "unicode": "e67d",
+ "unicode_decimal": 59005
+ },
+ {
+ "icon_id": "24879606",
+ "name": "micoff",
+ "font_class": "micoff",
+ "unicode": "e67e",
+ "unicode_decimal": 59006
+ },
+ {
+ "icon_id": "24879588",
+ "name": "closeempty",
+ "font_class": "closeempty",
+ "unicode": "e66c",
+ "unicode_decimal": 58988
+ },
+ {
+ "icon_id": "24879589",
+ "name": "clear",
+ "font_class": "clear",
+ "unicode": "e66d",
+ "unicode_decimal": 58989
+ },
+ {
+ "icon_id": "24879590",
+ "name": "navigate",
+ "font_class": "navigate",
+ "unicode": "e66e",
+ "unicode_decimal": 58990
+ },
+ {
+ "icon_id": "24879591",
+ "name": "minus",
+ "font_class": "minus",
+ "unicode": "e66f",
+ "unicode_decimal": 58991
+ },
+ {
+ "icon_id": "24879592",
+ "name": "image",
+ "font_class": "image",
+ "unicode": "e670",
+ "unicode_decimal": 58992
+ },
+ {
+ "icon_id": "24879593",
+ "name": "mic",
+ "font_class": "mic",
+ "unicode": "e671",
+ "unicode_decimal": 58993
+ },
+ {
+ "icon_id": "24879594",
+ "name": "paperplane",
+ "font_class": "paperplane",
+ "unicode": "e672",
+ "unicode_decimal": 58994
+ },
+ {
+ "icon_id": "24879595",
+ "name": "close",
+ "font_class": "close",
+ "unicode": "e673",
+ "unicode_decimal": 58995
+ },
+ {
+ "icon_id": "24879596",
+ "name": "help-filled",
+ "font_class": "help-filled",
+ "unicode": "e674",
+ "unicode_decimal": 58996
+ },
+ {
+ "icon_id": "24879597",
+ "name": "plus-filled",
+ "font_class": "paperplane-filled",
+ "unicode": "e675",
+ "unicode_decimal": 58997
+ },
+ {
+ "icon_id": "24879598",
+ "name": "plus",
+ "font_class": "plus",
+ "unicode": "e676",
+ "unicode_decimal": 58998
+ },
+ {
+ "icon_id": "24879599",
+ "name": "mic-filled",
+ "font_class": "mic-filled",
+ "unicode": "e677",
+ "unicode_decimal": 58999
+ },
+ {
+ "icon_id": "24879600",
+ "name": "image-filled",
+ "font_class": "image-filled",
+ "unicode": "e678",
+ "unicode_decimal": 59000
+ },
+ {
+ "icon_id": "24855900",
+ "name": "locked-filled",
+ "font_class": "locked-filled",
+ "unicode": "e668",
+ "unicode_decimal": 58984
+ },
+ {
+ "icon_id": "24855901",
+ "name": "info",
+ "font_class": "info",
+ "unicode": "e669",
+ "unicode_decimal": 58985
+ },
+ {
+ "icon_id": "24855903",
+ "name": "locked",
+ "font_class": "locked",
+ "unicode": "e66b",
+ "unicode_decimal": 58987
+ },
+ {
+ "icon_id": "24855884",
+ "name": "camera-filled",
+ "font_class": "camera-filled",
+ "unicode": "e658",
+ "unicode_decimal": 58968
+ },
+ {
+ "icon_id": "24855885",
+ "name": "chat-filled",
+ "font_class": "chat-filled",
+ "unicode": "e659",
+ "unicode_decimal": 58969
+ },
+ {
+ "icon_id": "24855886",
+ "name": "camera",
+ "font_class": "camera",
+ "unicode": "e65a",
+ "unicode_decimal": 58970
+ },
+ {
+ "icon_id": "24855887",
+ "name": "circle",
+ "font_class": "circle",
+ "unicode": "e65b",
+ "unicode_decimal": 58971
+ },
+ {
+ "icon_id": "24855888",
+ "name": "checkmarkempty",
+ "font_class": "checkmarkempty",
+ "unicode": "e65c",
+ "unicode_decimal": 58972
+ },
+ {
+ "icon_id": "24855889",
+ "name": "chat",
+ "font_class": "chat",
+ "unicode": "e65d",
+ "unicode_decimal": 58973
+ },
+ {
+ "icon_id": "24855890",
+ "name": "circle-filled",
+ "font_class": "circle-filled",
+ "unicode": "e65e",
+ "unicode_decimal": 58974
+ },
+ {
+ "icon_id": "24855891",
+ "name": "flag",
+ "font_class": "flag",
+ "unicode": "e65f",
+ "unicode_decimal": 58975
+ },
+ {
+ "icon_id": "24855892",
+ "name": "flag-filled",
+ "font_class": "flag-filled",
+ "unicode": "e660",
+ "unicode_decimal": 58976
+ },
+ {
+ "icon_id": "24855893",
+ "name": "gear-filled",
+ "font_class": "gear-filled",
+ "unicode": "e661",
+ "unicode_decimal": 58977
+ },
+ {
+ "icon_id": "24855894",
+ "name": "home",
+ "font_class": "home",
+ "unicode": "e662",
+ "unicode_decimal": 58978
+ },
+ {
+ "icon_id": "24855895",
+ "name": "home-filled",
+ "font_class": "home-filled",
+ "unicode": "e663",
+ "unicode_decimal": 58979
+ },
+ {
+ "icon_id": "24855896",
+ "name": "gear",
+ "font_class": "gear",
+ "unicode": "e664",
+ "unicode_decimal": 58980
+ },
+ {
+ "icon_id": "24855897",
+ "name": "smallcircle-filled",
+ "font_class": "smallcircle-filled",
+ "unicode": "e665",
+ "unicode_decimal": 58981
+ },
+ {
+ "icon_id": "24855898",
+ "name": "map-filled",
+ "font_class": "map-filled",
+ "unicode": "e666",
+ "unicode_decimal": 58982
+ },
+ {
+ "icon_id": "24855899",
+ "name": "map",
+ "font_class": "map",
+ "unicode": "e667",
+ "unicode_decimal": 58983
+ },
+ {
+ "icon_id": "24855825",
+ "name": "refresh-filled",
+ "font_class": "refresh-filled",
+ "unicode": "e656",
+ "unicode_decimal": 58966
+ },
+ {
+ "icon_id": "24855826",
+ "name": "refresh",
+ "font_class": "refresh",
+ "unicode": "e657",
+ "unicode_decimal": 58967
+ },
+ {
+ "icon_id": "24855808",
+ "name": "cloud-upload",
+ "font_class": "cloud-upload",
+ "unicode": "e645",
+ "unicode_decimal": 58949
+ },
+ {
+ "icon_id": "24855809",
+ "name": "cloud-download-filled",
+ "font_class": "cloud-download-filled",
+ "unicode": "e646",
+ "unicode_decimal": 58950
+ },
+ {
+ "icon_id": "24855810",
+ "name": "cloud-download",
+ "font_class": "cloud-download",
+ "unicode": "e647",
+ "unicode_decimal": 58951
+ },
+ {
+ "icon_id": "24855811",
+ "name": "cloud-upload-filled",
+ "font_class": "cloud-upload-filled",
+ "unicode": "e648",
+ "unicode_decimal": 58952
+ },
+ {
+ "icon_id": "24855813",
+ "name": "redo",
+ "font_class": "redo",
+ "unicode": "e64a",
+ "unicode_decimal": 58954
+ },
+ {
+ "icon_id": "24855814",
+ "name": "images-filled",
+ "font_class": "images-filled",
+ "unicode": "e64b",
+ "unicode_decimal": 58955
+ },
+ {
+ "icon_id": "24855815",
+ "name": "undo-filled",
+ "font_class": "undo-filled",
+ "unicode": "e64c",
+ "unicode_decimal": 58956
+ },
+ {
+ "icon_id": "24855816",
+ "name": "more",
+ "font_class": "more",
+ "unicode": "e64d",
+ "unicode_decimal": 58957
+ },
+ {
+ "icon_id": "24855817",
+ "name": "more-filled",
+ "font_class": "more-filled",
+ "unicode": "e64e",
+ "unicode_decimal": 58958
+ },
+ {
+ "icon_id": "24855818",
+ "name": "undo",
+ "font_class": "undo",
+ "unicode": "e64f",
+ "unicode_decimal": 58959
+ },
+ {
+ "icon_id": "24855819",
+ "name": "images",
+ "font_class": "images",
+ "unicode": "e650",
+ "unicode_decimal": 58960
+ },
+ {
+ "icon_id": "24855821",
+ "name": "paperclip",
+ "font_class": "paperclip",
+ "unicode": "e652",
+ "unicode_decimal": 58962
+ },
+ {
+ "icon_id": "24855822",
+ "name": "settings",
+ "font_class": "settings",
+ "unicode": "e653",
+ "unicode_decimal": 58963
+ },
+ {
+ "icon_id": "24855823",
+ "name": "search",
+ "font_class": "search",
+ "unicode": "e654",
+ "unicode_decimal": 58964
+ },
+ {
+ "icon_id": "24855824",
+ "name": "redo-filled",
+ "font_class": "redo-filled",
+ "unicode": "e655",
+ "unicode_decimal": 58965
+ },
+ {
+ "icon_id": "24841702",
+ "name": "list",
+ "font_class": "list",
+ "unicode": "e644",
+ "unicode_decimal": 58948
+ },
+ {
+ "icon_id": "24841489",
+ "name": "mail-open-filled",
+ "font_class": "mail-open-filled",
+ "unicode": "e63a",
+ "unicode_decimal": 58938
+ },
+ {
+ "icon_id": "24841491",
+ "name": "hand-thumbsdown-filled",
+ "font_class": "hand-down-filled",
+ "unicode": "e63c",
+ "unicode_decimal": 58940
+ },
+ {
+ "icon_id": "24841492",
+ "name": "hand-thumbsdown",
+ "font_class": "hand-down",
+ "unicode": "e63d",
+ "unicode_decimal": 58941
+ },
+ {
+ "icon_id": "24841493",
+ "name": "hand-thumbsup-filled",
+ "font_class": "hand-up-filled",
+ "unicode": "e63e",
+ "unicode_decimal": 58942
+ },
+ {
+ "icon_id": "24841494",
+ "name": "hand-thumbsup",
+ "font_class": "hand-up",
+ "unicode": "e63f",
+ "unicode_decimal": 58943
+ },
+ {
+ "icon_id": "24841496",
+ "name": "heart-filled",
+ "font_class": "heart-filled",
+ "unicode": "e641",
+ "unicode_decimal": 58945
+ },
+ {
+ "icon_id": "24841498",
+ "name": "mail-open",
+ "font_class": "mail-open",
+ "unicode": "e643",
+ "unicode_decimal": 58947
+ },
+ {
+ "icon_id": "24841488",
+ "name": "heart",
+ "font_class": "heart",
+ "unicode": "e639",
+ "unicode_decimal": 58937
+ },
+ {
+ "icon_id": "24839963",
+ "name": "loop",
+ "font_class": "loop",
+ "unicode": "e633",
+ "unicode_decimal": 58931
+ },
+ {
+ "icon_id": "24839866",
+ "name": "pulldown",
+ "font_class": "pulldown",
+ "unicode": "e632",
+ "unicode_decimal": 58930
+ },
+ {
+ "icon_id": "24813798",
+ "name": "scan",
+ "font_class": "scan",
+ "unicode": "e62a",
+ "unicode_decimal": 58922
+ },
+ {
+ "icon_id": "24813786",
+ "name": "bars",
+ "font_class": "bars",
+ "unicode": "e627",
+ "unicode_decimal": 58919
+ },
+ {
+ "icon_id": "24813788",
+ "name": "cart-filled",
+ "font_class": "cart-filled",
+ "unicode": "e629",
+ "unicode_decimal": 58921
+ },
+ {
+ "icon_id": "24813790",
+ "name": "checkbox",
+ "font_class": "checkbox",
+ "unicode": "e62b",
+ "unicode_decimal": 58923
+ },
+ {
+ "icon_id": "24813791",
+ "name": "checkbox-filled",
+ "font_class": "checkbox-filled",
+ "unicode": "e62c",
+ "unicode_decimal": 58924
+ },
+ {
+ "icon_id": "24813794",
+ "name": "shop",
+ "font_class": "shop",
+ "unicode": "e62f",
+ "unicode_decimal": 58927
+ },
+ {
+ "icon_id": "24813795",
+ "name": "headphones",
+ "font_class": "headphones",
+ "unicode": "e630",
+ "unicode_decimal": 58928
+ },
+ {
+ "icon_id": "24813796",
+ "name": "cart",
+ "font_class": "cart",
+ "unicode": "e631",
+ "unicode_decimal": 58929
+ }
+ ]
+}
diff --git a/app/uni_modules/uni-icons/components/uni-icons/uni-icons.vue b/app/uni_modules/uni-icons/components/uni-icons/uni-icons.vue
new file mode 100644
index 0000000..86e7444
--- /dev/null
+++ b/app/uni_modules/uni-icons/components/uni-icons/uni-icons.vue
@@ -0,0 +1,96 @@
+<template>
+ <!-- #ifdef APP-NVUE -->
+ <text :style="{ color: color, 'font-size': iconSize }" class="uni-icons" @click="_onClick">{{unicode}}</text>
+ <!-- #endif -->
+ <!-- #ifndef APP-NVUE -->
+ <text :style="{ color: color, 'font-size': iconSize }" class="uni-icons" :class="['uniui-'+type,customPrefix,customPrefix?type:'']" @click="_onClick"></text>
+ <!-- #endif -->
+</template>
+
+<script>
+ import icons from './icons.js';
+ const getVal = (val) => {
+ const reg = /^[0-9]*$/g
+ return (typeof val === 'number' ||銆�reg.test(val) )? val + 'px' : val;
+ }
+ // #ifdef APP-NVUE
+ var domModule = weex.requireModule('dom');
+ import iconUrl from './uniicons.ttf'
+ domModule.addRule('fontFace', {
+ 'fontFamily': "uniicons",
+ 'src': "url('"+iconUrl+"')"
+ });
+ // #endif
+
+ /**
+ * Icons 鍥炬爣
+ * @description 鐢ㄤ簬灞曠ず icons 鍥炬爣
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=28
+ * @property {Number} size 鍥炬爣澶у皬
+ * @property {String} type 鍥炬爣鍥炬锛屽弬鑰冪ず渚�
+ * @property {String} color 鍥炬爣棰滆壊
+ * @property {String} customPrefix 鑷畾涔夊浘鏍�
+ * @event {Function} click 鐐瑰嚮 Icon 瑙﹀彂浜嬩欢
+ */
+ export default {
+ name: 'UniIcons',
+ emits:['click'],
+ props: {
+ type: {
+ type: String,
+ default: ''
+ },
+ color: {
+ type: String,
+ default: '#333333'
+ },
+ size: {
+ type: [Number, String],
+ default: 16
+ },
+ customPrefix:{
+ type: String,
+ default: ''
+ }
+ },
+ data() {
+ return {
+ icons: icons.glyphs
+ }
+ },
+ computed:{
+ unicode(){
+ let code = this.icons.find(v=>v.font_class === this.type)
+ if(code){
+ return unescape(`%u${code.unicode}`)
+ }
+ return ''
+ },
+ iconSize(){
+ return getVal(this.size)
+ }
+ },
+ methods: {
+ _onClick() {
+ this.$emit('click')
+ }
+ }
+ }
+</script>
+
+<style lang="scss">
+ /* #ifndef APP-NVUE */
+ @import './uniicons.css';
+ @font-face {
+ font-family: uniicons;
+ src: url('./uniicons.ttf') format('truetype');
+ }
+
+ /* #endif */
+ .uni-icons {
+ font-family: uniicons;
+ text-decoration: none;
+ text-align: center;
+ }
+
+</style>
diff --git a/app/uni_modules/uni-icons/components/uni-icons/uniicons.css b/app/uni_modules/uni-icons/components/uni-icons/uniicons.css
new file mode 100644
index 0000000..2f56eab
--- /dev/null
+++ b/app/uni_modules/uni-icons/components/uni-icons/uniicons.css
@@ -0,0 +1,663 @@
+.uniui-color:before {
+ content: "\e6cf";
+}
+
+.uniui-wallet:before {
+ content: "\e6b1";
+}
+
+.uniui-settings-filled:before {
+ content: "\e6ce";
+}
+
+.uniui-auth-filled:before {
+ content: "\e6cc";
+}
+
+.uniui-shop-filled:before {
+ content: "\e6cd";
+}
+
+.uniui-staff-filled:before {
+ content: "\e6cb";
+}
+
+.uniui-vip-filled:before {
+ content: "\e6c6";
+}
+
+.uniui-plus-filled:before {
+ content: "\e6c7";
+}
+
+.uniui-folder-add-filled:before {
+ content: "\e6c8";
+}
+
+.uniui-color-filled:before {
+ content: "\e6c9";
+}
+
+.uniui-tune-filled:before {
+ content: "\e6ca";
+}
+
+.uniui-calendar-filled:before {
+ content: "\e6c0";
+}
+
+.uniui-notification-filled:before {
+ content: "\e6c1";
+}
+
+.uniui-wallet-filled:before {
+ content: "\e6c2";
+}
+
+.uniui-medal-filled:before {
+ content: "\e6c3";
+}
+
+.uniui-gift-filled:before {
+ content: "\e6c4";
+}
+
+.uniui-fire-filled:before {
+ content: "\e6c5";
+}
+
+.uniui-refreshempty:before {
+ content: "\e6bf";
+}
+
+.uniui-location-filled:before {
+ content: "\e6af";
+}
+
+.uniui-person-filled:before {
+ content: "\e69d";
+}
+
+.uniui-personadd-filled:before {
+ content: "\e698";
+}
+
+.uniui-back:before {
+ content: "\e6b9";
+}
+
+.uniui-forward:before {
+ content: "\e6ba";
+}
+
+.uniui-arrow-right:before {
+ content: "\e6bb";
+}
+
+.uniui-arrowthinright:before {
+ content: "\e6bb";
+}
+
+.uniui-arrow-left:before {
+ content: "\e6bc";
+}
+
+.uniui-arrowthinleft:before {
+ content: "\e6bc";
+}
+
+.uniui-arrow-up:before {
+ content: "\e6bd";
+}
+
+.uniui-arrowthinup:before {
+ content: "\e6bd";
+}
+
+.uniui-arrow-down:before {
+ content: "\e6be";
+}
+
+.uniui-arrowthindown:before {
+ content: "\e6be";
+}
+
+.uniui-bottom:before {
+ content: "\e6b8";
+}
+
+.uniui-arrowdown:before {
+ content: "\e6b8";
+}
+
+.uniui-right:before {
+ content: "\e6b5";
+}
+
+.uniui-arrowright:before {
+ content: "\e6b5";
+}
+
+.uniui-top:before {
+ content: "\e6b6";
+}
+
+.uniui-arrowup:before {
+ content: "\e6b6";
+}
+
+.uniui-left:before {
+ content: "\e6b7";
+}
+
+.uniui-arrowleft:before {
+ content: "\e6b7";
+}
+
+.uniui-eye:before {
+ content: "\e651";
+}
+
+.uniui-eye-filled:before {
+ content: "\e66a";
+}
+
+.uniui-eye-slash:before {
+ content: "\e6b3";
+}
+
+.uniui-eye-slash-filled:before {
+ content: "\e6b4";
+}
+
+.uniui-info-filled:before {
+ content: "\e649";
+}
+
+.uniui-reload:before {
+ content: "\e6b2";
+}
+
+.uniui-micoff-filled:before {
+ content: "\e6b0";
+}
+
+.uniui-map-pin-ellipse:before {
+ content: "\e6ac";
+}
+
+.uniui-map-pin:before {
+ content: "\e6ad";
+}
+
+.uniui-location:before {
+ content: "\e6ae";
+}
+
+.uniui-starhalf:before {
+ content: "\e683";
+}
+
+.uniui-star:before {
+ content: "\e688";
+}
+
+.uniui-star-filled:before {
+ content: "\e68f";
+}
+
+.uniui-calendar:before {
+ content: "\e6a0";
+}
+
+.uniui-fire:before {
+ content: "\e6a1";
+}
+
+.uniui-medal:before {
+ content: "\e6a2";
+}
+
+.uniui-font:before {
+ content: "\e6a3";
+}
+
+.uniui-gift:before {
+ content: "\e6a4";
+}
+
+.uniui-link:before {
+ content: "\e6a5";
+}
+
+.uniui-notification:before {
+ content: "\e6a6";
+}
+
+.uniui-staff:before {
+ content: "\e6a7";
+}
+
+.uniui-vip:before {
+ content: "\e6a8";
+}
+
+.uniui-folder-add:before {
+ content: "\e6a9";
+}
+
+.uniui-tune:before {
+ content: "\e6aa";
+}
+
+.uniui-auth:before {
+ content: "\e6ab";
+}
+
+.uniui-person:before {
+ content: "\e699";
+}
+
+.uniui-email-filled:before {
+ content: "\e69a";
+}
+
+.uniui-phone-filled:before {
+ content: "\e69b";
+}
+
+.uniui-phone:before {
+ content: "\e69c";
+}
+
+.uniui-email:before {
+ content: "\e69e";
+}
+
+.uniui-personadd:before {
+ content: "\e69f";
+}
+
+.uniui-chatboxes-filled:before {
+ content: "\e692";
+}
+
+.uniui-contact:before {
+ content: "\e693";
+}
+
+.uniui-chatbubble-filled:before {
+ content: "\e694";
+}
+
+.uniui-contact-filled:before {
+ content: "\e695";
+}
+
+.uniui-chatboxes:before {
+ content: "\e696";
+}
+
+.uniui-chatbubble:before {
+ content: "\e697";
+}
+
+.uniui-upload-filled:before {
+ content: "\e68e";
+}
+
+.uniui-upload:before {
+ content: "\e690";
+}
+
+.uniui-weixin:before {
+ content: "\e691";
+}
+
+.uniui-compose:before {
+ content: "\e67f";
+}
+
+.uniui-qq:before {
+ content: "\e680";
+}
+
+.uniui-download-filled:before {
+ content: "\e681";
+}
+
+.uniui-pyq:before {
+ content: "\e682";
+}
+
+.uniui-sound:before {
+ content: "\e684";
+}
+
+.uniui-trash-filled:before {
+ content: "\e685";
+}
+
+.uniui-sound-filled:before {
+ content: "\e686";
+}
+
+.uniui-trash:before {
+ content: "\e687";
+}
+
+.uniui-videocam-filled:before {
+ content: "\e689";
+}
+
+.uniui-spinner-cycle:before {
+ content: "\e68a";
+}
+
+.uniui-weibo:before {
+ content: "\e68b";
+}
+
+.uniui-videocam:before {
+ content: "\e68c";
+}
+
+.uniui-download:before {
+ content: "\e68d";
+}
+
+.uniui-help:before {
+ content: "\e679";
+}
+
+.uniui-navigate-filled:before {
+ content: "\e67a";
+}
+
+.uniui-plusempty:before {
+ content: "\e67b";
+}
+
+.uniui-smallcircle:before {
+ content: "\e67c";
+}
+
+.uniui-minus-filled:before {
+ content: "\e67d";
+}
+
+.uniui-micoff:before {
+ content: "\e67e";
+}
+
+.uniui-closeempty:before {
+ content: "\e66c";
+}
+
+.uniui-clear:before {
+ content: "\e66d";
+}
+
+.uniui-navigate:before {
+ content: "\e66e";
+}
+
+.uniui-minus:before {
+ content: "\e66f";
+}
+
+.uniui-image:before {
+ content: "\e670";
+}
+
+.uniui-mic:before {
+ content: "\e671";
+}
+
+.uniui-paperplane:before {
+ content: "\e672";
+}
+
+.uniui-close:before {
+ content: "\e673";
+}
+
+.uniui-help-filled:before {
+ content: "\e674";
+}
+
+.uniui-paperplane-filled:before {
+ content: "\e675";
+}
+
+.uniui-plus:before {
+ content: "\e676";
+}
+
+.uniui-mic-filled:before {
+ content: "\e677";
+}
+
+.uniui-image-filled:before {
+ content: "\e678";
+}
+
+.uniui-locked-filled:before {
+ content: "\e668";
+}
+
+.uniui-info:before {
+ content: "\e669";
+}
+
+.uniui-locked:before {
+ content: "\e66b";
+}
+
+.uniui-camera-filled:before {
+ content: "\e658";
+}
+
+.uniui-chat-filled:before {
+ content: "\e659";
+}
+
+.uniui-camera:before {
+ content: "\e65a";
+}
+
+.uniui-circle:before {
+ content: "\e65b";
+}
+
+.uniui-checkmarkempty:before {
+ content: "\e65c";
+}
+
+.uniui-chat:before {
+ content: "\e65d";
+}
+
+.uniui-circle-filled:before {
+ content: "\e65e";
+}
+
+.uniui-flag:before {
+ content: "\e65f";
+}
+
+.uniui-flag-filled:before {
+ content: "\e660";
+}
+
+.uniui-gear-filled:before {
+ content: "\e661";
+}
+
+.uniui-home:before {
+ content: "\e662";
+}
+
+.uniui-home-filled:before {
+ content: "\e663";
+}
+
+.uniui-gear:before {
+ content: "\e664";
+}
+
+.uniui-smallcircle-filled:before {
+ content: "\e665";
+}
+
+.uniui-map-filled:before {
+ content: "\e666";
+}
+
+.uniui-map:before {
+ content: "\e667";
+}
+
+.uniui-refresh-filled:before {
+ content: "\e656";
+}
+
+.uniui-refresh:before {
+ content: "\e657";
+}
+
+.uniui-cloud-upload:before {
+ content: "\e645";
+}
+
+.uniui-cloud-download-filled:before {
+ content: "\e646";
+}
+
+.uniui-cloud-download:before {
+ content: "\e647";
+}
+
+.uniui-cloud-upload-filled:before {
+ content: "\e648";
+}
+
+.uniui-redo:before {
+ content: "\e64a";
+}
+
+.uniui-images-filled:before {
+ content: "\e64b";
+}
+
+.uniui-undo-filled:before {
+ content: "\e64c";
+}
+
+.uniui-more:before {
+ content: "\e64d";
+}
+
+.uniui-more-filled:before {
+ content: "\e64e";
+}
+
+.uniui-undo:before {
+ content: "\e64f";
+}
+
+.uniui-images:before {
+ content: "\e650";
+}
+
+.uniui-paperclip:before {
+ content: "\e652";
+}
+
+.uniui-settings:before {
+ content: "\e653";
+}
+
+.uniui-search:before {
+ content: "\e654";
+}
+
+.uniui-redo-filled:before {
+ content: "\e655";
+}
+
+.uniui-list:before {
+ content: "\e644";
+}
+
+.uniui-mail-open-filled:before {
+ content: "\e63a";
+}
+
+.uniui-hand-down-filled:before {
+ content: "\e63c";
+}
+
+.uniui-hand-down:before {
+ content: "\e63d";
+}
+
+.uniui-hand-up-filled:before {
+ content: "\e63e";
+}
+
+.uniui-hand-up:before {
+ content: "\e63f";
+}
+
+.uniui-heart-filled:before {
+ content: "\e641";
+}
+
+.uniui-mail-open:before {
+ content: "\e643";
+}
+
+.uniui-heart:before {
+ content: "\e639";
+}
+
+.uniui-loop:before {
+ content: "\e633";
+}
+
+.uniui-pulldown:before {
+ content: "\e632";
+}
+
+.uniui-scan:before {
+ content: "\e62a";
+}
+
+.uniui-bars:before {
+ content: "\e627";
+}
+
+.uniui-cart-filled:before {
+ content: "\e629";
+}
+
+.uniui-checkbox:before {
+ content: "\e62b";
+}
+
+.uniui-checkbox-filled:before {
+ content: "\e62c";
+}
+
+.uniui-shop:before {
+ content: "\e62f";
+}
+
+.uniui-headphones:before {
+ content: "\e630";
+}
+
+.uniui-cart:before {
+ content: "\e631";
+}
diff --git a/app/uni_modules/uni-icons/components/uni-icons/uniicons.ttf b/app/uni_modules/uni-icons/components/uni-icons/uniicons.ttf
new file mode 100644
index 0000000..835f33b
--- /dev/null
+++ b/app/uni_modules/uni-icons/components/uni-icons/uniicons.ttf
Binary files differ
diff --git a/app/uni_modules/uni-icons/package.json b/app/uni_modules/uni-icons/package.json
new file mode 100644
index 0000000..d1c4e77
--- /dev/null
+++ b/app/uni_modules/uni-icons/package.json
@@ -0,0 +1,86 @@
+{
+ "id": "uni-icons",
+ "displayName": "uni-icons 鍥炬爣",
+ "version": "1.3.5",
+ "description": "鍥炬爣缁勪欢锛岀敤浜庡睍绀虹Щ鍔ㄧ甯歌鐨勫浘鏍囷紝鍙嚜瀹氫箟棰滆壊銆佸ぇ灏忋��",
+ "keywords": [
+ "uni-ui",
+ "uniui",
+ "icon",
+ "鍥炬爣"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": "^3.2.14"
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "鍓嶇缁勪欢",
+ "閫氱敤缁勪欢"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": ["uni-scss"],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "u",
+ "鑱旂洘": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/uni_modules/uni-icons/readme.md b/app/uni_modules/uni-icons/readme.md
new file mode 100644
index 0000000..86234ba
--- /dev/null
+++ b/app/uni_modules/uni-icons/readme.md
@@ -0,0 +1,8 @@
+## Icons 鍥炬爣
+> **缁勪欢鍚嶏細uni-icons**
+> 浠g爜鍧楋細 `uIcons`
+
+鐢ㄤ簬灞曠ず icons 鍥炬爣 銆�
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-icons)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
diff --git a/app/uni_modules/uni-indexed-list/changelog.md b/app/uni_modules/uni-indexed-list/changelog.md
new file mode 100644
index 0000000..08fa71c
--- /dev/null
+++ b/app/uni_modules/uni-indexed-list/changelog.md
@@ -0,0 +1,17 @@
+## 1.2.1锛�2021-11-22锛�
+- 淇 vue3涓煇浜泂css鍙橀噺鏃犳硶鎵惧埌鐨勯棶棰�
+## 1.2.0锛�2021-11-19锛�
+- 浼樺寲 缁勪欢UI锛屽苟鎻愪緵璁捐璧勬簮锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 鏂囨。杩佺Щ锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/uni-indexed-list](https://uniapp.dcloud.io/component/uniui/uni-indexed-list)
+## 1.1.0锛�2021-07-30锛�
+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤簐ue3椤圭洰锛岃瑙� [uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+## 1.0.11锛�2021-05-12锛�
+- 鏂板 缁勪欢绀轰緥鍦板潃
+## 1.0.10锛�2021-04-21锛�
+- 浼樺寲 娣诲姞渚濊禆 uni-icons, 瀵煎叆鍚庤嚜鍔ㄤ笅杞戒緷璧�
+## 1.0.9锛�2021-02-05锛�
+- 浼樺寲 缁勪欢寮曠敤鍏崇郴锛岄�氳繃uni_modules寮曠敤缁勪欢
+
+## 1.0.8锛�2021-02-05锛�
+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
+- 鏂板 鏀寔 PC 绔�
diff --git a/app/uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list-item.vue b/app/uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list-item.vue
new file mode 100644
index 0000000..2f13bae
--- /dev/null
+++ b/app/uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list-item.vue
@@ -0,0 +1,144 @@
+<template>
+ <view>
+ <view v-if="loaded || list.itemIndex < 15" class="uni-indexed-list__title-wrapper">
+ <text v-if="list.items && list.items.length > 0" class="uni-indexed-list__title">{{ list.key }}</text>
+ </view>
+ <view v-if="(loaded || list.itemIndex < 15) && list.items && list.items.length > 0" class="uni-indexed-list__list">
+ <view v-for="(item, index) in list.items" :key="index" class="uni-indexed-list__item" hover-class="uni-indexed-list__item--hover">
+ <view class="uni-indexed-list__item-container" @click="onClick(idx, index)">
+ <view class="uni-indexed-list__item-border" :class="{'uni-indexed-list__item-border--last':index===list.items.length-1}">
+ <view v-if="showSelect" style="margin-right: 20rpx;">
+ <uni-icons :type="item.checked ? 'checkbox-filled' : 'circle'" :color="item.checked ? '#007aff' : '#C0C0C0'" size="24" />
+ </view>
+ <text class="uni-indexed-list__item-content">{{ item.name }}</text>
+ </view>
+ </view>
+ </view>
+ </view>
+ </view>
+</template>
+
+<script>
+ export default {
+ name: 'UniIndexedList',
+ emits:['itemClick'],
+ props: {
+ loaded: {
+ type: Boolean,
+ default: false
+ },
+ idx: {
+ type: Number,
+ default: 0
+ },
+ list: {
+ type: Object,
+ default () {
+ return {}
+ }
+ },
+ showSelect: {
+ type: Boolean,
+ default: false
+ }
+ },
+ methods: {
+ onClick(idx, index) {
+ this.$emit("itemClick", {
+ idx,
+ index
+ })
+ }
+ }
+ }
+</script>
+
+<style lang="scss" >
+ .uni-indexed-list__list {
+ background-color: $uni-bg-color;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: column;
+ border-top-style: solid;
+ border-top-width: 1px;
+ border-top-color: #DEDEDE;
+ }
+
+ .uni-indexed-list__item {
+ font-size: 14px;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex: 1;
+ flex-direction: row;
+ justify-content: space-between;
+ align-items: center;
+ }
+
+ .uni-indexed-list__item-container {
+ padding-left: 15px;
+ flex: 1;
+ position: relative;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ box-sizing: border-box;
+ /* #endif */
+ flex-direction: row;
+ justify-content: space-between;
+ align-items: center;
+ /* #ifdef H5 */
+ cursor: pointer;
+ /* #endif */
+ }
+
+ .uni-indexed-list__item-border {
+ flex: 1;
+ position: relative;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ box-sizing: border-box;
+ /* #endif */
+ flex-direction: row;
+ justify-content: space-between;
+ align-items: center;
+ height: 50px;
+ padding: 25px;
+ padding-left: 0;
+ border-bottom-style: solid;
+ border-bottom-width: 1px;
+ border-bottom-color: #DEDEDE;
+ }
+
+ .uni-indexed-list__item-border--last {
+ border-bottom-width: 0px;
+ }
+
+ .uni-indexed-list__item-content {
+ flex: 1;
+ font-size: 14px;
+ color: #191919;
+ }
+
+ .uni-indexed-list {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ }
+
+ .uni-indexed-list__title-wrapper {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ width: 100%;
+ /* #endif */
+ background-color: #f7f7f7;
+ }
+
+ .uni-indexed-list__title {
+ padding: 6px 12px;
+ line-height: 24px;
+ font-size: 16px;
+ font-weight: 500;
+ }
+</style>
diff --git a/app/uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list.vue b/app/uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list.vue
new file mode 100644
index 0000000..35e168c
--- /dev/null
+++ b/app/uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list.vue
@@ -0,0 +1,367 @@
+<template>
+ <view class="uni-indexed-list" ref="list" id="list">
+ <!-- #ifdef APP-NVUE -->
+ <list class="uni-indexed-list__scroll" scrollable="true" show-scrollbar="false">
+ <cell v-for="(list, idx) in lists" :key="idx" :ref="'uni-indexed-list-' + idx">
+ <!-- #endif -->
+ <!-- #ifndef APP-NVUE -->
+ <scroll-view :scroll-into-view="scrollViewId" class="uni-indexed-list__scroll" scroll-y>
+ <view v-for="(list, idx) in lists" :key="idx" :id="'uni-indexed-list-' + idx">
+ <!-- #endif -->
+ <indexed-list-item :list="list" :loaded="loaded" :idx="idx" :showSelect="showSelect"
+ @itemClick="onClick"></indexed-list-item>
+ <!-- #ifndef APP-NVUE -->
+ </view>
+ </scroll-view>
+ <!-- #endif -->
+ <!-- #ifdef APP-NVUE -->
+ </cell>
+ </list>
+ <!-- #endif -->
+ <view class="uni-indexed-list__menu" @touchstart="touchStart" @touchmove.stop.prevent="touchMove"
+ @touchend="touchEnd" @mousedown.stop="mousedown" @mousemove.stop.prevent="mousemove"
+ @mouseleave.stop="mouseleave">
+ <view v-for="(list, key) in lists" :key="key" class="uni-indexed-list__menu-item"
+ :class="touchmoveIndex == key ? 'uni-indexed-list__menu--active' : ''">
+ <text class="uni-indexed-list__menu-text"
+ :class="touchmoveIndex == key ? 'uni-indexed-list__menu-text--active' : ''">{{ list.key }}</text>
+ </view>
+ </view>
+ <view v-if="touchmove" class="uni-indexed-list__alert-wrapper">
+ <text class="uni-indexed-list__alert">{{ lists[touchmoveIndex].key }}</text>
+ </view>
+ </view>
+</template>
+<script>
+ import indexedListItem from './uni-indexed-list-item.vue'
+ // #ifdef APP-NVUE
+ const dom = weex.requireModule('dom');
+ // #endif
+ // #ifdef APP-PLUS
+ function throttle(func, delay) {
+ var prev = Date.now();
+ return function() {
+ var context = this;
+ var args = arguments;
+ var now = Date.now();
+ if (now - prev >= delay) {
+ func.apply(context, args);
+ prev = Date.now();
+ }
+ }
+ }
+
+ function touchMove(e) {
+ let pageY = e.touches[0].pageY
+ let index = Math.floor((pageY - this.winOffsetY) / this.itemHeight)
+ if (this.touchmoveIndex === index) {
+ return false
+ }
+ let item = this.lists[index]
+ if (item) {
+ // #ifndef APP-NVUE
+ this.scrollViewId = 'uni-indexed-list-' + index
+ this.touchmoveIndex = index
+ // #endif
+ // #ifdef APP-NVUE
+ dom.scrollToElement(this.$refs['uni-indexed-list-' + index][0], {
+ animated: false
+ })
+ this.touchmoveIndex = index
+ // #endif
+ }
+ }
+ const throttleTouchMove = throttle(touchMove, 40)
+ // #endif
+
+ /**
+ * IndexedList 绱㈠紩鍒楄〃
+ * @description 鐢ㄤ簬灞曠ず绱㈠紩鍒楄〃
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=375
+ * @property {Boolean} showSelect = [true|false] 灞曠ず妯″紡
+ * @value true 灞曠ず妯″紡
+ * @value false 閫夋嫨妯″紡
+ * @property {Object} options 绱㈠紩鍒楄〃闇�瑕佺殑鏁版嵁瀵硅薄
+ * @event {Function} click 鐐瑰嚮鍒楄〃浜嬩欢 锛岃繑鍥炲綋鍓嶉�夋嫨椤圭殑浜嬩欢瀵硅薄
+ * @example <uni-indexed-list options="" showSelect="false" @click=""></uni-indexed-list>
+ */
+ export default {
+ name: 'UniIndexedList',
+ components: {
+ indexedListItem
+ },
+ emits: ['click'],
+ props: {
+ options: {
+ type: Array,
+ default () {
+ return []
+ }
+ },
+ showSelect: {
+ type: Boolean,
+ default: false
+ }
+ },
+ data() {
+ return {
+ lists: [],
+ winHeight: 0,
+ itemHeight: 0,
+ winOffsetY: 0,
+ touchmove: false,
+ touchmoveIndex: -1,
+ scrollViewId: '',
+ touchmovable: true,
+ loaded: false,
+ isPC: false
+ }
+ },
+ watch: {
+ options: {
+ handler: function() {
+ this.setList()
+ },
+ deep: true
+ }
+ },
+ mounted() {
+ // #ifdef H5
+ this.isPC = this.IsPC()
+ // #endif
+ setTimeout(() => {
+ this.setList()
+ }, 50)
+ setTimeout(() => {
+ this.loaded = true
+ }, 300);
+ },
+ methods: {
+ setList() {
+ let index = 0;
+ this.lists = []
+ this.options.forEach((value) => {
+ if (value.data.length === 0) {
+ return
+ }
+ let indexBefore = index
+ let items = value.data.map(item => {
+ let obj = {}
+ obj['key'] = value.letter
+ obj['name'] = item
+ obj['itemIndex'] = index
+ index++
+ obj.checked = item.checked ? item.checked : false
+ return obj
+ })
+ this.lists.push({
+ title: value.letter,
+ key: value.letter,
+ items: items,
+ itemIndex: indexBefore
+ })
+ })
+ // #ifndef APP-NVUE
+ uni.createSelectorQuery()
+ .in(this)
+ .select('#list')
+ .boundingClientRect()
+ .exec(ret => {
+ this.winOffsetY = ret[0].top
+ this.winHeight = ret[0].height
+ this.itemHeight = this.winHeight / this.lists.length
+ })
+ // #endif
+ // #ifdef APP-NVUE
+ dom.getComponentRect(this.$refs['list'], (res) => {
+ this.winOffsetY = res.size.top
+ this.winHeight = res.size.height
+ this.itemHeight = this.winHeight / this.lists.length
+ })
+ // #endif
+ },
+ touchStart(e) {
+ this.touchmove = true
+ let pageY = this.isPC ? e.pageY : e.touches[0].pageY
+ let index = Math.floor((pageY - this.winOffsetY) / this.itemHeight)
+ let item = this.lists[index]
+ if (item) {
+ this.scrollViewId = 'uni-indexed-list-' + index
+ this.touchmoveIndex = index
+ // #ifdef APP-NVUE
+ dom.scrollToElement(this.$refs['uni-indexed-list-' + index][0], {
+ animated: false
+ })
+ // #endif
+ }
+ },
+ touchMove(e) {
+ // #ifndef APP-PLUS
+ let pageY = this.isPC ? e.pageY : e.touches[0].pageY
+ let index = Math.floor((pageY - this.winOffsetY) / this.itemHeight)
+ if (this.touchmoveIndex === index) {
+ return false
+ }
+ let item = this.lists[index]
+ if (item) {
+ this.scrollViewId = 'uni-indexed-list-' + index
+ this.touchmoveIndex = index
+ }
+ // #endif
+ // #ifdef APP-PLUS
+ throttleTouchMove.call(this, e)
+ // #endif
+ },
+ touchEnd() {
+ this.touchmove = false
+ // this.touchmoveIndex = -1
+ },
+
+ /**
+ * 鍏煎 PC @tian
+ */
+
+ mousedown(e) {
+ if (!this.isPC) return
+ this.touchStart(e)
+ },
+ mousemove(e) {
+ if (!this.isPC) return
+ this.touchMove(e)
+ },
+ mouseleave(e) {
+ if (!this.isPC) return
+ this.touchEnd(e)
+ },
+
+ // #ifdef H5
+ IsPC() {
+ var userAgentInfo = navigator.userAgent;
+ var Agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"];
+ var flag = true;
+ for (let v = 0; v < Agents.length - 1; v++) {
+ if (userAgentInfo.indexOf(Agents[v]) > 0) {
+ flag = false;
+ break;
+ }
+ }
+ return flag;
+ },
+ // #endif
+
+
+ onClick(e) {
+ let {
+ idx,
+ index
+ } = e
+ let obj = {}
+ for (let key in this.lists[idx].items[index]) {
+ obj[key] = this.lists[idx].items[index][key]
+ }
+ let select = []
+ if (this.showSelect) {
+ this.lists[idx].items[index].checked = !this.lists[idx].items[index].checked
+ this.lists.forEach((value, idx) => {
+ value.items.forEach((item, index) => {
+ if (item.checked) {
+ let obj = {}
+ for (let key in this.lists[idx].items[index]) {
+ obj[key] = this.lists[idx].items[index][key]
+ }
+ select.push(obj)
+ }
+ })
+ })
+ }
+ this.$emit('click', {
+ item: obj,
+ select: select
+ })
+ }
+ }
+ }
+</script>
+<style lang="scss" >
+ .uni-indexed-list {
+ position: absolute;
+ left: 0;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ }
+
+ .uni-indexed-list__scroll {
+ flex: 1;
+ }
+
+ .uni-indexed-list__menu {
+ width: 24px;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: column;
+ }
+
+ .uni-indexed-list__menu-item {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex: 1;
+ align-items: center;
+ justify-content: center;
+ /* #ifdef H5 */
+ cursor: pointer;
+ /* #endif */
+ }
+
+ .uni-indexed-list__menu-text {
+ font-size: 12px;
+ text-align: center;
+ color: #aaa;
+ }
+
+ .uni-indexed-list__menu--active {
+ // background-color: rgb(200, 200, 200);
+ }
+
+ .uni-indexed-list__menu--active {}
+
+ .uni-indexed-list__menu-text--active {
+ border-radius: 16px;
+ width: 16px;
+ height: 16px;
+ line-height: 16px;
+ background-color: #007aff;
+ color: #fff;
+ }
+
+ .uni-indexed-list__alert-wrapper {
+ position: absolute;
+ left: 0;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ align-items: center;
+ justify-content: center;
+ }
+
+ .uni-indexed-list__alert {
+ width: 80px;
+ height: 80px;
+ border-radius: 80px;
+ text-align: center;
+ line-height: 80px;
+ font-size: 35px;
+ color: #fff;
+ background-color: rgba(0, 0, 0, 0.5);
+ }
+</style>
diff --git a/app/uni_modules/uni-indexed-list/package.json b/app/uni_modules/uni-indexed-list/package.json
new file mode 100644
index 0000000..125c0e7
--- /dev/null
+++ b/app/uni_modules/uni-indexed-list/package.json
@@ -0,0 +1,89 @@
+{
+ "id": "uni-indexed-list",
+ "displayName": "uni-indexed-list 绱㈠紩鍒楄〃",
+ "version": "1.2.1",
+ "description": "绱㈠紩鍒楄〃缁勪欢锛屽彸渚у甫绱㈠紩鐨勫垪琛紝鏂逛究蹇�熷畾浣嶅埌鍏蜂綋鍐呭锛岄�氬父鐢ㄤ簬鍩庡競/鏈哄満閫夋嫨绛夊満鏅�",
+ "keywords": [
+ "uni-ui",
+ "绱㈠紩鍒楄〃",
+ "绱㈠紩",
+ "鍒楄〃"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "鍓嶇缁勪欢",
+ "閫氱敤缁勪欢"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": [
+ "uni-scss",
+ "uni-icons"
+ ],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "u",
+ "鑱旂洘": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
diff --git a/app/uni_modules/uni-indexed-list/readme.md b/app/uni_modules/uni-indexed-list/readme.md
new file mode 100644
index 0000000..44ad84b
--- /dev/null
+++ b/app/uni_modules/uni-indexed-list/readme.md
@@ -0,0 +1,11 @@
+
+
+## IndexedList 绱㈠紩鍒楄〃
+> **缁勪欢鍚嶏細uni-indexed-list**
+> 浠g爜鍧楋細 `uIndexedList`
+
+
+鐢ㄤ簬灞曠ず绱㈠紩鍒楄〃銆�
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-indexed-list)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
diff --git a/app/uni_modules/uni-link/changelog.md b/app/uni_modules/uni-link/changelog.md
new file mode 100644
index 0000000..2cfbf59
--- /dev/null
+++ b/app/uni_modules/uni-link/changelog.md
@@ -0,0 +1,17 @@
+## 1.0.0锛�2021-11-19锛�
+- 浼樺寲 缁勪欢UI锛屽苟鎻愪緵璁捐璧勬簮锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 鏂囨。杩佺Щ锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/uni-link](https://uniapp.dcloud.io/component/uniui/uni-link)
+## 1.1.7锛�2021-11-08锛�
+## 0.0.7锛�2021-09-03锛�
+- 淇 鍦� nvue 涓嬩笉鏄剧ず鐨� bug
+## 0.0.6锛�2021-07-30锛�
+- 鏂板 鏀寔鑷畾涔夋彃妲�
+## 0.0.5锛�2021-06-21锛�
+- 鏂板 download 灞炴�э紝H5骞冲彴涓嬭浇鏂囦欢鍚�
+## 0.0.4锛�2021-05-12锛�
+- 鏂板 缁勪欢绀轰緥鍦板潃
+## 0.0.3锛�2021-03-09锛�
+- 鏂板 href 灞炴�ф敮鎸� tel:|mailto:
+
+## 0.0.2锛�2021-02-05锛�
+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
diff --git a/app/uni_modules/uni-link/components/uni-link/uni-link.vue b/app/uni_modules/uni-link/components/uni-link/uni-link.vue
new file mode 100644
index 0000000..27c5468
--- /dev/null
+++ b/app/uni_modules/uni-link/components/uni-link/uni-link.vue
@@ -0,0 +1,128 @@
+<template>
+ <a v-if="isShowA" class="uni-link" :href="href"
+ :class="{'uni-link--withline':showUnderLine===true||showUnderLine==='true'}"
+ :style="{color,fontSize:fontSize+'px'}" :download="download">
+ <slot>{{text}}</slot>
+ </a>
+ <!-- #ifndef APP-NVUE -->
+ <text v-else class="uni-link" :class="{'uni-link--withline':showUnderLine===true||showUnderLine==='true'}"
+ :style="{color,fontSize:fontSize+'px'}" @click="openURL">
+ <slot>{{text}}</slot>
+ </text>
+ <!-- #endif -->
+ <!-- #ifdef APP-NVUE -->
+ <text v-else class="uni-link" :class="{'uni-link--withline':showUnderLine===true||showUnderLine==='true'}"
+ :style="{color,fontSize:fontSize+'px'}" @click="openURL">
+ {{text}}
+ </text>
+ <!-- #endif -->
+</template>
+
+<script>
+ /**
+ * Link 澶栭儴缃戦〉瓒呴摼鎺ョ粍浠�
+ * @description uni-link鏄竴涓閮ㄧ綉椤佃秴閾炬帴缁勪欢锛屽湪灏忕▼搴忓唴澶嶅埗url锛屽湪app鍐呮墦寮�澶栭儴娴忚鍣紝鍦╤5绔墦寮�鏂扮綉椤�
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=1182
+ * @property {String} href 鐐瑰嚮鍚庢墦寮�鐨勫閮ㄧ綉椤祏rl
+ * @property {String} text 鏄剧ず鐨勬枃瀛�
+ * @property {String} downlaod H5骞冲彴涓嬭浇鏂囦欢鍚�
+ * @property {Boolean} showUnderLine 鏄惁鏄剧ず涓嬪垝绾�
+ * @property {String} copyTips 鍦ㄥ皬绋嬪簭绔鍒堕摼鎺ユ椂鏄剧ず鐨勬彁绀鸿
+ * @property {String} color 閾炬帴鏂囧瓧棰滆壊
+ * @property {String} fontSize 閾炬帴鏂囧瓧澶у皬
+ * @example * <uni-link href="https://ext.dcloud.net.cn" text="https://ext.dcloud.net.cn"></uni-link>
+ */
+ export default {
+ name: 'uniLink',
+ props: {
+ href: {
+ type: String,
+ default: ''
+ },
+ text: {
+ type: String,
+ default: ''
+ },
+ download: {
+ type: String,
+ default: ''
+ },
+ showUnderLine: {
+ type: [Boolean, String],
+ default: true
+ },
+ copyTips: {
+ type: String,
+ default: '宸茶嚜鍔ㄥ鍒剁綉鍧�锛岃鍦ㄦ墜鏈烘祻瑙堝櫒閲岀矘璐磋缃戝潃'
+ },
+ color: {
+ type: String,
+ default: '#999999'
+ },
+ fontSize: {
+ type: [Number, String],
+ default: 14
+ }
+ },
+ computed: {
+ isShowA() {
+ // #ifdef H5
+ this._isH5 = true;
+ // #endif
+ if ((this.isMail() || this.isTel()) && this._isH5 === true) {
+ return true;
+ }
+ return false;
+ }
+ },
+ created() {
+ this._isH5 = null;
+ },
+ methods: {
+ isMail() {
+ return this.href.startsWith('mailto:');
+ },
+ isTel() {
+ return this.href.startsWith('tel:');
+ },
+ openURL() {
+ // #ifdef APP-PLUS
+ if (this.isTel()) {
+ this.makePhoneCall(this.href.replace('tel:', ''));
+ } else {
+ plus.runtime.openURL(this.href);
+ }
+ // #endif
+ // #ifdef H5
+ window.open(this.href)
+ // #endif
+ // #ifdef MP
+ uni.setClipboardData({
+ data: this.href
+ });
+ uni.showModal({
+ content: this.copyTips,
+ showCancel: false
+ });
+ // #endif
+ },
+ makePhoneCall(phoneNumber) {
+ uni.makePhoneCall({
+ phoneNumber
+ })
+ }
+ }
+ }
+</script>
+
+<style>
+ /* #ifndef APP-NVUE */
+ .uni-link {
+ cursor: pointer;
+ }
+
+ /* #endif */
+ .uni-link--withline {
+ text-decoration: underline;
+ }
+</style>
diff --git a/app/uni_modules/uni-link/package.json b/app/uni_modules/uni-link/package.json
new file mode 100644
index 0000000..77b1986
--- /dev/null
+++ b/app/uni_modules/uni-link/package.json
@@ -0,0 +1,87 @@
+{
+ "id": "uni-link",
+ "displayName": "uni-link 瓒呴摼鎺�",
+ "version": "1.0.0",
+ "description": "uni-link鏄竴涓閮ㄧ綉椤佃秴閾炬帴缁勪欢锛屽湪灏忕▼搴忓唴澶嶅埗url锛屽湪app鍐呮墦寮�澶栭儴娴忚鍣紝鍦╤5绔墦",
+ "keywords": [
+ "uni-ui",
+ "uniui",
+ "link",
+ "瓒呴摼鎺�",
+ ""
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "鍓嶇缁勪欢",
+ "閫氱敤缁勪欢"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": ["uni-scss"],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "y",
+ "鑱旂洘": "y"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/uni_modules/uni-link/readme.md b/app/uni_modules/uni-link/readme.md
new file mode 100644
index 0000000..7f09e94
--- /dev/null
+++ b/app/uni_modules/uni-link/readme.md
@@ -0,0 +1,11 @@
+
+
+## Link 閾炬帴
+> **缁勪欢鍚嶏細uni-link**
+> 浠g爜鍧楋細 `uLink`
+
+
+uni-link鏄竴涓閮ㄧ綉椤佃秴閾炬帴缁勪欢锛屽湪灏忕▼搴忓唴澶嶅埗url锛屽湪app鍐呮墦寮�澶栭儴娴忚鍣紝鍦╤5绔墦寮�鏂扮綉椤点��
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-link)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
\ No newline at end of file
diff --git a/app/uni_modules/uni-list/changelog.md b/app/uni_modules/uni-list/changelog.md
new file mode 100644
index 0000000..8254a18
--- /dev/null
+++ b/app/uni_modules/uni-list/changelog.md
@@ -0,0 +1,46 @@
+## 1.2.14锛�2023-04-14锛�
+- 浼樺寲 uni-list-chat 鍏峰悕鎻掓Ы`header` 闈瀉pp绔涓�灞傚厓绱狅紝鏂逛究浣跨敤鏃堕�氳繃澶栧眰鍏冪礌瀹氫綅瀹炵幇鏍峰紡淇敼
+## 1.2.13锛�2023-03-03锛�
+- uni-list-chat 鏂板 鏀寔鍏峰悕鎻掓Ы`header`
+## 1.2.12锛�2023-02-01锛�
+- 鏂板 鍒楄〃鍥炬爣鏂板 customPrefix 灞炴�� 锛岀敤娉� [璇﹁](https://uniapp.dcloud.net.cn/component/uniui/uni-icons.html#icons-props)
+## 1.2.11锛�2023-01-31锛�
+- 淇 鏃犲弽棣堟晥鏋滃憟鐜扮殑bug
+## 1.2.9锛�2022-11-22锛�
+- 淇 uni-list-chat 鍦╲ue3涓嬭烦杞姤閿欑殑bug
+## 1.2.8锛�2022-11-21锛�
+- 淇 uni-list-chat avatar灞炴�� 鍊间负鏈湴璺緞鏃堕敊璇殑闂
+## 1.2.7锛�2022-11-21锛�
+- 淇 uni-list-chat avatar灞炴�� 鍦ㄨ吘璁簯鐗坲niCloud涓嬮敊璇殑闂
+## 1.2.6锛�2022-11-18锛�
+- 淇 uni-list-chat note灞炴�� 鏀寔锛氣�滆崏绋库�濆瓧鏍峰姛鑳� 鏂囨湰灏�1浣嶇殑闂
+## 1.2.5锛�2022-11-15锛�
+- 淇 uni-list-item 鐨� customStyle 灞炴�� padding鍊煎湪 H5绔� 鏃犳晥鐨刡ug
+## 1.2.4锛�2022-11-15锛�
+- 淇 uni-list-item 鐨� customStyle 灞炴�� padding鍊煎湪nvue锛坴ue2锛変笅鏃犳晥鐨刡ug
+## 1.2.3锛�2022-11-14锛�
+- uni-list-chat 鏂板 avatar 鏀寔 fileId
+## 1.2.2锛�2022-11-11锛�
+- uni-list 鏂板灞炴�� render-reverse 璇︽儏鍙傝�冿細[https://uniapp.dcloud.net.cn/component/list.html](https://uniapp.dcloud.net.cn/component/list.html)
+- uni-list-chat note灞炴�� 鏀寔锛氣�滆崏绋库�濆瓧鏍� 鍔犵孩鏄剧ず 璇︽儏鍙傝�僽ni-im锛歔https://ext.dcloud.net.cn/plugin?name=uni-im](https://ext.dcloud.net.cn/plugin?name=uni-im)
+- uni-list-item 鏂板灞炴�� customStyle 鏀寔璁剧疆padding銆乥ackgroundColor
+## 1.2.1锛�2022-03-30锛�
+- 鍒犻櫎鏃犵敤鏂囦欢
+## 1.2.0锛�2021-11-23锛�
+- 浼樺寲 缁勪欢UI锛屽苟鎻愪緵璁捐璧勬簮锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 鏂囨。杩佺Щ锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/uni-list](https://uniapp.dcloud.io/component/uniui/uni-list)
+## 1.1.3锛�2021-08-30锛�
+- 淇 鍦╲ue3涓璽o灞炴�у湪鍙戣搴旂敤鐨勬椂鍊欐姤閿欑殑bug
+## 1.1.2锛�2021-07-30锛�
+- 浼樺寲 vue3涓嬩簨浠惰鍛婄殑闂
+## 1.1.1锛�2021-07-21锛�
+- 淇 涓庡叾浠栫粍浠跺祵濂椾娇鐢ㄦ椂锛岀偣鍑诲け鏁堢殑Bug
+## 1.1.0锛�2021-07-13锛�
+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤簐ue3椤圭洰锛岃瑙� [uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+## 1.0.17锛�2021-05-12锛�
+- 鏂板 缁勪欢绀轰緥鍦板潃
+## 1.0.16锛�2021-02-05锛�
+- 浼樺寲 缁勪欢寮曠敤鍏崇郴锛岄�氳繃uni_modules寮曠敤缁勪欢
+## 1.0.15锛�2021-02-05锛�
+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
+- 淇 uni-list-chat 瑙掓爣鏄剧ず涓嶆甯哥殑闂
diff --git a/app/uni_modules/uni-list/components/uni-list-ad/uni-list-ad.vue b/app/uni_modules/uni-list/components/uni-list-ad/uni-list-ad.vue
new file mode 100644
index 0000000..b9349c2
--- /dev/null
+++ b/app/uni_modules/uni-list/components/uni-list-ad/uni-list-ad.vue
@@ -0,0 +1,107 @@
+<template>
+ <!-- #ifdef APP-NVUE -->
+ <cell>
+ <!-- #endif -->
+ <view class="uni-list-ad">
+ <view v-if="borderShow" :class="{'uni-list--border':border,'uni-list-item--first':isFirstChild}"></view>
+ <ad style="width: 200px;height: 300px;border-width: 1px;border-color: red;border-style: solid;" adpid="1111111111"
+ unit-id="" appid="" apid="" type="feed" @error="aderror" @close="closeAd"></ad>
+ </view>
+ <!-- #ifdef APP-NVUE -->
+ </cell>
+ <!-- #endif -->
+
+</template>
+
+<script>
+ // #ifdef APP-NVUE
+ const dom = uni.requireNativePlugin('dom');
+ // #endif
+ export default {
+ name: 'UniListAd',
+ props: {
+ title: {
+ type: String,
+ default: '',
+
+ }
+ },
+ // inject: ['list'],
+ data() {
+ return {
+ isFirstChild: false,
+ border: false,
+ borderShow: true,
+ }
+ },
+
+ mounted() {
+ this.list = this.getForm()
+ if (this.list) {
+ if (!this.list.firstChildAppend) {
+ this.list.firstChildAppend = true
+ this.isFirstChild = true
+ }
+ this.border = this.list.border
+ }
+ },
+ methods: {
+ /**
+ * 鑾峰彇鐖跺厓绱犲疄渚�
+ */
+ getForm(name = 'uniList') {
+ let parent = this.$parent;
+ let parentName = parent.$options.name;
+ while (parentName !== name) {
+ parent = parent.$parent;
+ if (!parent) return false
+ parentName = parent.$options.name;
+ }
+ return parent;
+ },
+ aderror(e) {
+ console.log("aderror: " + JSON.stringify(e.detail));
+ },
+ closeAd(e) {
+ this.borderShow = false
+ }
+ }
+ }
+</script>
+
+<style lang="scss" >
+ .uni-list-ad {
+ position: relative;
+ border: 1px red solid;
+ }
+
+ .uni-list--border {
+ position: relative;
+ padding-bottom: 1px;
+ /* #ifdef APP-PLUS */
+ border-top-color: $uni-border-color;
+ border-top-style: solid;
+ border-top-width: 0.5px;
+ /* #endif */
+ margin-left: $uni-spacing-row-lg;
+ }
+
+ /* #ifndef APP-NVUE */
+ .uni-list--border:after {
+ position: absolute;
+ top: 0;
+ right: 0;
+ left: 0;
+ height: 1px;
+ content: '';
+ -webkit-transform: scaleY(.5);
+ transform: scaleY(.5);
+ background-color: $uni-border-color;
+ }
+
+ .uni-list-item--first:after {
+ height: 0px;
+ }
+
+ /* #endif */
+</style>
diff --git a/app/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.scss b/app/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.scss
new file mode 100644
index 0000000..311f8d9
--- /dev/null
+++ b/app/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.scss
@@ -0,0 +1,58 @@
+/**
+ * 杩欓噷鏄� uni-list 缁勪欢鍐呯疆鐨勫父鐢ㄦ牱寮忓彉閲�
+ * 濡傛灉闇�瑕佽鐩栨牱寮忥紝杩欓噷鎻愪緵浜嗗熀鏈殑缁勪欢鏍峰紡鍙橀噺锛屾偍鍙互灏濊瘯淇敼杩欓噷鐨勫彉閲忥紝鍘诲畬鎴愭牱寮忔浛鎹紝鑰屼笉鐢ㄥ幓淇敼婧愮爜
+ *
+ */
+
+// 鑳屾櫙鑹�
+$background-color : #fff;
+// 鍒嗗壊绾块鑹�
+$divide-line-color : #e5e5e5;
+
+// 榛樿澶村儚澶у皬锛屽闇�瑕佷慨鏀规鍊硷紝娉ㄦ剰鍚屾淇敼 js 涓殑鍊� const avatarWidth = xx 锛岀洰鍓嶅彧鏀寔鏂瑰舰澶村儚
+// nvue 椤甸潰涓嶆敮鎸佷慨鏀瑰ご鍍忓ぇ灏�
+$avatar-width : 45px ;
+
+// 澶村儚杈规
+$avatar-border-radius: 5px;
+$avatar-border-color: #eee;
+$avatar-border-width: 1px;
+
+// 鏍囬鏂囧瓧鏍峰紡
+$title-size : 16px;
+$title-color : #3b4144;
+$title-weight : normal;
+
+// 鎻忚堪鏂囧瓧鏍峰紡
+$note-size : 12px;
+$note-color : #999;
+$note-weight : normal;
+
+// 鍙充晶棰濆鍐呭榛樿鏍峰紡
+$right-text-size : 12px;
+$right-text-color : #999;
+$right-text-weight : normal;
+
+// 瑙掓爣鏍峰紡
+// nvue 椤甸潰涓嶆敮鎸佷慨鏀瑰渾鐐逛綅缃互鍙婂ぇ灏�
+// 瑙掓爣鍦ㄥ乏渚ф椂锛岃鏍囩殑浣嶇疆锛岄粯璁や负 0 锛岃礋鏁板乏/涓嬬Щ鍔紝姝f暟鍙�/涓婄Щ鍔�
+$badge-left: 0px;
+$badge-top: 0px;
+
+// 鏄剧ず鍦嗙偣鏃讹紝鍦嗙偣澶у皬
+$dot-width: 10px;
+$dot-height: 10px;
+
+// 鏄剧ず瑙掓爣鏃讹紝瑙掓爣澶у皬鍜屽瓧浣撳ぇ灏�
+$badge-size : 18px;
+$badge-font : 12px;
+// 鏄剧ず瑙掓爣鏃讹紝瑙掓爣鍓嶆櫙鑹�
+$badge-color : #fff;
+// 鏄剧ず瑙掓爣鏃讹紝瑙掓爣鑳屾櫙鑹�
+$badge-background-color : #ff5a5f;
+// 鏄剧ず瑙掓爣鏃讹紝瑙掓爣宸﹀彸闂磋窛
+$badge-space : 6px;
+
+// 鐘舵�佹牱寮�
+// 閫変腑棰滆壊
+$hover : #f5f5f5;
diff --git a/app/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.vue b/app/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.vue
new file mode 100644
index 0000000..d49fd7c
--- /dev/null
+++ b/app/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.vue
@@ -0,0 +1,593 @@
+<template>
+ <!-- #ifdef APP-NVUE -->
+ <cell>
+ <!-- #endif -->
+ <view :hover-class="!clickable && !link ? '' : 'uni-list-chat--hover'" class="uni-list-chat" @click.stop="onClick">
+ <view :class="{ 'uni-list--border': border, 'uni-list-chat--first': isFirstChild }"></view>
+ <view class="uni-list-chat__container">
+ <view class="uni-list-chat__header-warp">
+ <view v-if="avatarCircle || avatarList.length === 0" class="uni-list-chat__header" :class="{ 'header--circle': avatarCircle }">
+ <image class="uni-list-chat__header-image" :class="{ 'header--circle': avatarCircle }" :src="avatarUrl" mode="aspectFill"></image>
+ </view>
+ <!-- 澶村儚缁� -->
+ <view v-else class="uni-list-chat__header">
+ <view v-for="(item, index) in avatarList" :key="index" class="uni-list-chat__header-box" :class="computedAvatar"
+ :style="{ width: imageWidth + 'px', height: imageWidth + 'px' }">
+ <image class="uni-list-chat__header-image" :style="{ width: imageWidth + 'px', height: imageWidth + 'px' }" :src="item.url"
+ mode="aspectFill"></image>
+ </view>
+ </view>
+ </view>
+ <!-- #ifndef APP -->
+ <view class="slot-header">
+ <!-- #endif -->
+ <slot name="header"></slot>
+ <!-- #ifndef APP -->
+ </view>
+ <!-- #endif -->
+ <view v-if="badgeText && badgePositon === 'left'" class="uni-list-chat__badge uni-list-chat__badge-pos" :class="[isSingle]">
+ <text class="uni-list-chat__badge-text">{{ badgeText === 'dot' ? '' : badgeText }}</text>
+ </view>
+ <view class="uni-list-chat__content">
+ <view class="uni-list-chat__content-main">
+ <text class="uni-list-chat__content-title uni-ellipsis">{{ title }}</text>
+ <view style="flex-direction: row;">
+ <text class="draft" v-if="isDraft">[鑽夌]</text>
+ <text class="uni-list-chat__content-note uni-ellipsis">{{isDraft?note.slice(14):note}}</text>
+ </view>
+ </view>
+ <view class="uni-list-chat__content-extra">
+ <slot>
+ <text class="uni-list-chat__content-extra-text">{{ time }}</text>
+ <view v-if="badgeText && badgePositon === 'right'" class="uni-list-chat__badge" :class="[isSingle, badgePositon === 'right' ? 'uni-list-chat--right' : '']">
+ <text class="uni-list-chat__badge-text">{{ badgeText === 'dot' ? '' : badgeText }}</text>
+ </view>
+ </slot>
+ </view>
+ </view>
+ </view>
+ </view>
+ <!-- #ifdef APP-NVUE -->
+ </cell>
+ <!-- #endif -->
+</template>
+
+<script>
+ // 澶村儚澶у皬
+ const avatarWidth = 45;
+
+ /**
+ * ListChat 鑱婂ぉ鍒楄〃
+ * @description 鑱婂ぉ鍒楄〃,鐢ㄤ簬鍒涘缓鑱婂ぉ绫诲垪琛�
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=24
+ * @property {String} title 鏍囬
+ * @property {String} note 鎻忚堪
+ * @property {Boolean} clickable = [true|false] 鏄惁寮�鍚偣鍑诲弽棣堬紝榛樿涓篺alse
+ * @property {String} badgeText 鏁板瓧瑙掓爣鍐呭
+ * @property {String} badgePositon = [left|right] 瑙掓爣浣嶇疆锛岄粯璁や负 right
+ * @property {String} link = [false锝渘avigateTo|redirectTo|reLaunch|switchTab] 鏄惁灞曠ず鍙充晶绠ご骞跺紑鍚偣鍑诲弽棣堬紝榛樿涓篺alse
+ * @value false 涓嶅紑鍚�
+ * @value navigateTo 鍚� uni.navigateTo()
+ * @value redirectTo 鍚� uni.redirectTo()
+ * @value reLaunch 鍚� uni.reLaunch()
+ * @value switchTab 鍚� uni.switchTab()
+ * @property {String | PageURIString} to 璺宠浆鐩爣椤甸潰
+ * @property {String} time 鍙充晶鏃堕棿鏄剧ず
+ * @property {Boolean} avatarCircle = [true|false] 鏄惁鏄剧ず鍦嗗舰澶村儚锛岄粯璁や负false
+ * @property {String} avatar 澶村儚鍦板潃锛宎vatarCircle 涓嶅~鏃剁敓鏁�
+ * @property {Array} avatarList 澶村儚缁勶紝鏍煎紡涓� [{url:''}]
+ * @event {Function} click 鐐瑰嚮 uniListChat 瑙﹀彂浜嬩欢
+ */
+ export default {
+ name: 'UniListChat',
+ emits:['click'],
+ props: {
+ title: {
+ type: String,
+ default: ''
+ },
+ note: {
+ type: String,
+ default: ''
+ },
+ clickable: {
+ type: Boolean,
+ default: false
+ },
+ link: {
+ type: [Boolean, String],
+ default: false
+ },
+ to: {
+ type: String,
+ default: ''
+ },
+ badgeText: {
+ type: [String, Number],
+ default: ''
+ },
+ badgePositon: {
+ type: String,
+ default: 'right'
+ },
+ time: {
+ type: String,
+ default: ''
+ },
+ avatarCircle: {
+ type: Boolean,
+ default: false
+ },
+ avatar: {
+ type: String,
+ default: ''
+ },
+ avatarList: {
+ type: Array,
+ default () {
+ return [];
+ }
+ }
+ },
+ // inject: ['list'],
+ computed: {
+ isDraft(){
+ return this.note.slice(0,14) == '[uni-im-draft]'
+ },
+ isSingle() {
+ if (this.badgeText === 'dot') {
+ return 'uni-badge--dot';
+ } else {
+ const badgeText = this.badgeText.toString();
+ if (badgeText.length > 1) {
+ return 'uni-badge--complex';
+ } else {
+ return 'uni-badge--single';
+ }
+ }
+ },
+ computedAvatar() {
+ if (this.avatarList.length > 4) {
+ this.imageWidth = avatarWidth * 0.31;
+ return 'avatarItem--3';
+ } else if (this.avatarList.length > 1) {
+ this.imageWidth = avatarWidth * 0.47;
+ return 'avatarItem--2';
+ } else {
+ this.imageWidth = avatarWidth;
+ return 'avatarItem--1';
+ }
+ }
+ },
+ watch: {
+ avatar:{
+ handler(avatar) {
+ if(avatar.substr(0,8) == 'cloud://'){
+ uniCloud.getTempFileURL({
+ fileList: [avatar]
+ }).then(res=>{
+ // console.log(res);
+ // 鍏煎uniCloud绉佹湁鍖栭儴缃�
+ let fileList = res.fileList || res.result.fileList
+ this.avatarUrl = fileList[0].tempFileURL
+ })
+ }else{
+ this.avatarUrl = avatar
+ }
+ },
+ immediate: true
+ }
+ },
+ data() {
+ return {
+ isFirstChild: false,
+ border: true,
+ // avatarList: 3,
+ imageWidth: 50,
+ avatarUrl:''
+ };
+ },
+ mounted() {
+ this.list = this.getForm()
+ if (this.list) {
+ if (!this.list.firstChildAppend) {
+ this.list.firstChildAppend = true;
+ this.isFirstChild = true;
+ }
+ this.border = this.list.border;
+ }
+ },
+ methods: {
+ /**
+ * 鑾峰彇鐖跺厓绱犲疄渚�
+ */
+ getForm(name = 'uniList') {
+ let parent = this.$parent;
+ let parentName = parent.$options.name;
+ while (parentName !== name) {
+ parent = parent.$parent;
+ if (!parent) return false
+ parentName = parent.$options.name;
+ }
+ return parent;
+ },
+ onClick() {
+ if (this.to !== '') {
+ this.openPage();
+ return;
+ }
+
+ if (this.clickable || this.link) {
+ this.$emit('click', {
+ data: {}
+ });
+ }
+ },
+ openPage() {
+ if (['navigateTo', 'redirectTo', 'reLaunch', 'switchTab'].indexOf(this.link) !== -1) {
+ this.pageApi(this.link);
+ } else {
+ this.pageApi('navigateTo');
+ }
+ },
+ pageApi(api) {
+ let callback = {
+ url: this.to,
+ success: res => {
+ this.$emit('click', {
+ data: res
+ });
+ },
+ fail: err => {
+ this.$emit('click', {
+ data: err
+ });
+ }
+ }
+ switch (api) {
+ case 'navigateTo':
+ uni.navigateTo(callback)
+ break
+ case 'redirectTo':
+ uni.redirectTo(callback)
+ break
+ case 'reLaunch':
+ uni.reLaunch(callback)
+ break
+ case 'switchTab':
+ uni.switchTab(callback)
+ break
+ default:
+ uni.navigateTo(callback)
+ }
+ }
+ }
+ };
+</script>
+
+<style lang="scss" >
+ $uni-font-size-lg:16px;
+ $uni-spacing-row-sm: 5px;
+ $uni-spacing-row-base: 10px;
+ $uni-spacing-row-lg: 15px;
+ $background-color: #fff;
+ $divide-line-color: #e5e5e5;
+ $avatar-width: 45px;
+ $avatar-border-radius: 5px;
+ $avatar-border-color: #eee;
+ $avatar-border-width: 1px;
+ $title-size: 16px;
+ $title-color: #3b4144;
+ $title-weight: normal;
+ $note-size: 12px;
+ $note-color: #999;
+ $note-weight: normal;
+ $right-text-size: 12px;
+ $right-text-color: #999;
+ $right-text-weight: normal;
+ $badge-left: 0px;
+ $badge-top: 0px;
+ $dot-width: 10px;
+ $dot-height: 10px;
+ $badge-size: 18px;
+ $badge-font: 12px;
+ $badge-color: #fff;
+ $badge-background-color: #ff5a5f;
+ $badge-space: 6px;
+ $hover: #f5f5f5;
+
+ .uni-list-chat {
+ font-size: $uni-font-size-lg;
+ position: relative;
+ flex-direction: column;
+ justify-content: space-between;
+ background-color: $background-color;
+ }
+
+ // .uni-list-chat--disabled {
+ // opacity: 0.3;
+ // }
+
+ .uni-list-chat--hover {
+ background-color: $hover;
+ }
+
+ .uni-list--border {
+ position: relative;
+ margin-left: $uni-spacing-row-lg;
+ /* #ifdef APP-PLUS */
+ border-top-color: $divide-line-color;
+ border-top-style: solid;
+ border-top-width: 0.5px;
+ /* #endif */
+ }
+
+ /* #ifndef APP-NVUE */
+ .uni-list--border:after {
+ position: absolute;
+ top: 0;
+ right: 0;
+ left: 0;
+ height: 1px;
+ content: '';
+ -webkit-transform: scaleY(0.5);
+ transform: scaleY(0.5);
+ background-color: $divide-line-color;
+ }
+
+ .uni-list-item--first:after {
+ height: 0px;
+ }
+
+ /* #endif */
+
+ .uni-list-chat--first {
+ border-top-width: 0px;
+ }
+
+ .uni-ellipsis {
+ /* #ifndef APP-NVUE */
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ /* #endif */
+ /* #ifdef APP-NVUE */
+ lines: 1;
+ /* #endif */
+ }
+
+ .uni-ellipsis-2 {
+ /* #ifndef APP-NVUE */
+ overflow: hidden;
+ text-overflow: ellipsis;
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ /* #endif */
+
+ /* #ifdef APP-NVUE */
+ lines: 2;
+ /* #endif */
+ }
+
+ .uni-list-chat__container {
+ position: relative;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ flex: 1;
+ padding: $uni-spacing-row-base $uni-spacing-row-lg;
+ position: relative;
+ overflow: hidden;
+ }
+
+ .uni-list-chat__header-warp {
+ position: relative;
+ }
+
+ .uni-list-chat__header {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ align-content: center;
+ /* #endif */
+ flex-direction: row;
+ justify-content: center;
+ align-items: center;
+ flex-wrap: wrap-reverse;
+ /* #ifdef APP-NVUE */
+ width: 50px;
+ height: 50px;
+ /* #endif */
+ /* #ifndef APP-NVUE */
+ width: $avatar-width;
+ height: $avatar-width;
+ /* #endif */
+
+ border-radius: $avatar-border-radius;
+ border-color: $avatar-border-color;
+ border-width: $avatar-border-width;
+ border-style: solid;
+ overflow: hidden;
+ }
+
+ .uni-list-chat__header-box {
+ /* #ifndef APP-PLUS */
+ box-sizing: border-box;
+ display: flex;
+ width: $avatar-width;
+ height: $avatar-width;
+ /* #endif */
+ /* #ifdef APP-NVUE */
+ width: 50px;
+ height: 50px;
+ /* #endif */
+ overflow: hidden;
+ border-radius: 2px;
+ }
+
+ .uni-list-chat__header-image {
+ margin: 1px;
+ /* #ifdef APP-NVUE */
+ width: 50px;
+ height: 50px;
+ /* #endif */
+ /* #ifndef APP-NVUE */
+ width: $avatar-width;
+ height: $avatar-width;
+ /* #endif */
+ }
+
+ /* #ifndef APP-NVUE */
+ .uni-list-chat__header-image {
+ display: block;
+ width: 100%;
+ height: 100%;
+ }
+
+ .avatarItem--1 {
+ width: 100%;
+ height: 100%;
+ }
+
+ .avatarItem--2 {
+ width: 47%;
+ height: 47%;
+ }
+
+ .avatarItem--3 {
+ width: 32%;
+ height: 32%;
+ }
+
+ /* #endif */
+ .header--circle {
+ border-radius: 50%;
+ }
+
+ .uni-list-chat__content {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ flex: 1;
+ overflow: hidden;
+ padding: 2px 0;
+ }
+
+ .uni-list-chat__content-main {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: column;
+ justify-content: space-between;
+ padding-left: $uni-spacing-row-base;
+ flex: 1;
+ overflow: hidden;
+ }
+
+ .uni-list-chat__content-title {
+ font-size: $title-size;
+ color: $title-color;
+ font-weight: $title-weight;
+ overflow: hidden;
+ }
+
+ .draft ,.uni-list-chat__content-note {
+ margin-top: 3px;
+ color: $note-color;
+ font-size: $note-size;
+ font-weight: $title-weight;
+ overflow: hidden;
+ }
+ .draft{
+ color: #eb3a41;
+ /* #ifndef APP-NVUE */
+ flex-shrink: 0;
+ /* #endif */
+ padding-right: 3px;
+ }
+
+ .uni-list-chat__content-extra {
+ /* #ifndef APP-NVUE */
+ flex-shrink: 0;
+ display: flex;
+ /* #endif */
+ flex-direction: column;
+ justify-content: space-between;
+ align-items: flex-end;
+ margin-left: 5px;
+ }
+
+ .uni-list-chat__content-extra-text {
+ color: $right-text-color;
+ font-size: $right-text-size;
+ font-weight: $right-text-weight;
+ overflow: hidden;
+ }
+
+ .uni-list-chat__badge-pos {
+ position: absolute;
+ /* #ifdef APP-NVUE */
+ left: 55px;
+ top: 3px;
+ /* #endif */
+ /* #ifndef APP-NVUE */
+ left: calc(#{$avatar-width} + 10px - #{$badge-space} + #{$badge-left});
+ top: calc(#{$uni-spacing-row-base}/ 2 + 1px + #{$badge-top});
+ /* #endif */
+ }
+
+ .uni-list-chat__badge {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ justify-content: center;
+ align-items: center;
+ border-radius: 100px;
+ background-color: $badge-background-color;
+ }
+
+ .uni-list-chat__badge-text {
+ color: $badge-color;
+ font-size: $badge-font;
+ }
+
+ .uni-badge--single {
+ /* #ifndef APP-NVUE */
+ // left: calc(#{$avatar-width} + 7px + #{$badge-left});
+ /* #endif */
+ width: $badge-size;
+ height: $badge-size;
+ }
+
+ .uni-badge--complex {
+ /* #ifdef APP-NVUE */
+ left: 50px;
+ /* #endif */
+ /* #ifndef APP-NVUE */
+ width: auto;
+ /* #endif */
+ height: $badge-size;
+ padding: 0 $badge-space;
+ }
+
+ .uni-badge--dot {
+ /* #ifdef APP-NVUE */
+ left: 60px;
+ top: 6px;
+ /* #endif */
+ /* #ifndef APP-NVUE */
+ left: calc(#{$avatar-width} + 15px - #{$dot-width}/ 2 + 1px + #{$badge-left});
+ /* #endif */
+ width: $dot-width;
+ height: $dot-height;
+ padding: 0;
+ }
+
+ .uni-list-chat--right {
+ /* #ifdef APP-NVUE */
+ left: 0;
+ /* #endif */
+ }
+</style>
diff --git a/app/uni_modules/uni-list/components/uni-list-item/uni-list-item.vue b/app/uni_modules/uni-list/components/uni-list-item/uni-list-item.vue
new file mode 100644
index 0000000..a274ac8
--- /dev/null
+++ b/app/uni_modules/uni-list/components/uni-list-item/uni-list-item.vue
@@ -0,0 +1,534 @@
+<template>
+ <!-- #ifdef APP-NVUE -->
+ <cell :keep-scroll-position="keepScrollPosition">
+ <!-- #endif -->
+ <view :class="{ 'uni-list-item--disabled': disabled }" :style="{'background-color':customStyle.backgroundColor}"
+ :hover-class="(!clickable && !link) || disabled || showSwitch ? '' : 'uni-list-item--hover'"
+ class="uni-list-item" @click="onClick">
+ <view v-if="!isFirstChild" class="border--left" :class="{ 'uni-list--border': border }"></view>
+ <view class="uni-list-item__container"
+ :class="{ 'container--right': showArrow || link, 'flex--direction': direction === 'column'}"
+ :style="{paddingTop:padding.top,paddingLeft:padding.left,paddingRight:padding.right,paddingBottom:padding.bottom}">
+ <slot name="header">
+ <view class="uni-list-item__header">
+ <view v-if="thumb" class="uni-list-item__icon">
+ <image :src="thumb" class="uni-list-item__icon-img" :class="['uni-list--' + thumbSize]" />
+ </view>
+ <view v-else-if="showExtraIcon" class="uni-list-item__icon">
+ <uni-icons :customPrefix="extraIcon.customPrefix" :color="extraIcon.color" :size="extraIcon.size" :type="extraIcon.type" />
+ </view>
+ </view>
+ </slot>
+ <slot name="body">
+ <view class="uni-list-item__content"
+ :class="{ 'uni-list-item__content--center': thumb || showExtraIcon || showBadge || showSwitch }">
+ <text v-if="title" class="uni-list-item__content-title"
+ :class="[ellipsis !== 0 && ellipsis <= 2 ? 'uni-ellipsis-' + ellipsis : '']">{{ title }}</text>
+ <text v-if="note" class="uni-list-item__content-note">{{ note }}</text>
+ </view>
+ </slot>
+ <slot name="footer">
+ <view v-if="rightText || showBadge || showSwitch" class="uni-list-item__extra"
+ :class="{ 'flex--justify': direction === 'column' }">
+ <text v-if="rightText" class="uni-list-item__extra-text">{{ rightText }}</text>
+ <uni-badge v-if="showBadge" :type="badgeType" :text="badgeText" :custom-style="badgeStyle" />
+ <switch v-if="showSwitch" :disabled="disabled" :checked="switchChecked"
+ @change="onSwitchChange" />
+ </view>
+ </slot>
+ </view>
+ <uni-icons v-if="showArrow || link" :size="16" class="uni-icon-wrapper" color="#bbb" type="arrowright" />
+ </view>
+ <!-- #ifdef APP-NVUE -->
+ </cell>
+ <!-- #endif -->
+</template>
+
+<script>
+ /**
+ * ListItem 鍒楄〃瀛愮粍浠�
+ * @description 鍒楄〃瀛愮粍浠�
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=24
+ * @property {String} title 鏍囬
+ * @property {String} note 鎻忚堪
+ * @property {String} thumb 宸︿晶缂╃暐鍥撅紝鑻humb鏈夊�硷紝鍒欎笉浼氭樉绀烘墿灞曞浘鏍�
+ * @property {String} thumbSize = [lg|base|sm] 鐣ョ缉鍥惧ぇ灏�
+ * @value lg 澶у浘
+ * @value base 涓�鑸�
+ * @value sm 灏忓浘
+ * @property {String} badgeText 鏁板瓧瑙掓爣鍐呭
+ * @property {String} badgeType 鏁板瓧瑙掓爣绫诲瀷锛屽弬鑰僛uni-icons](https://ext.dcloud.net.cn/plugin?id=21)
+ * @property {Object} badgeStyle 鏁板瓧瑙掓爣鏍峰紡
+ * @property {String} rightText 鍙充晶鏂囧瓧鍐呭
+ * @property {Boolean} disabled = [true|false] 鏄惁绂佺敤
+ * @property {Boolean} clickable = [true|false] 鏄惁寮�鍚偣鍑诲弽棣�
+ * @property {String} link = [navigateTo|redirectTo|reLaunch|switchTab] 鏄惁灞曠ず鍙充晶绠ご骞跺紑鍚偣鍑诲弽棣�
+ * @value navigateTo 鍚� uni.navigateTo()
+ * @value redirectTo 鍚� uni.redirectTo()
+ * @value reLaunch 鍚� uni.reLaunch()
+ * @value switchTab 鍚� uni.switchTab()
+ * @property {String | PageURIString} to 璺宠浆鐩爣椤甸潰
+ * @property {Boolean} showBadge = [true|false] 鏄惁鏄剧ず鏁板瓧瑙掓爣
+ * @property {Boolean} showSwitch = [true|false] 鏄惁鏄剧ずSwitch
+ * @property {Boolean} switchChecked = [true|false] Switch鏄惁琚�変腑
+ * @property {Boolean} showExtraIcon = [true|false] 宸︿晶鏄惁鏄剧ず鎵╁睍鍥炬爣
+ * @property {Object} extraIcon 鎵╁睍鍥炬爣鍙傛暟锛屾牸寮忎负 {color: '#4cd964',size: '22',type: 'spinner'}
+ * @property {String} direction = [row|column] 鎺掔増鏂瑰悜
+ * @value row 姘村钩鎺掑垪
+ * @value column 鍨傜洿鎺掑垪
+ * @event {Function} click 鐐瑰嚮 uniListItem 瑙﹀彂浜嬩欢
+ * @event {Function} switchChange 鐐瑰嚮鍒囨崲 Switch 鏃惰Е鍙�
+ */
+ export default {
+ name: 'UniListItem',
+ emits: ['click', 'switchChange'],
+ props: {
+ direction: {
+ type: String,
+ default: 'row'
+ },
+ title: {
+ type: String,
+ default: ''
+ },
+ note: {
+ type: String,
+ default: ''
+ },
+ ellipsis: {
+ type: [Number, String],
+ default: 0
+ },
+ disabled: {
+ type: [Boolean, String],
+ default: false
+ },
+ clickable: {
+ type: Boolean,
+ default: false
+ },
+ showArrow: {
+ type: [Boolean, String],
+ default: false
+ },
+ link: {
+ type: [Boolean, String],
+ default: false
+ },
+ to: {
+ type: String,
+ default: ''
+ },
+ showBadge: {
+ type: [Boolean, String],
+ default: false
+ },
+ showSwitch: {
+ type: [Boolean, String],
+ default: false
+ },
+ switchChecked: {
+ type: [Boolean, String],
+ default: false
+ },
+ badgeText: {
+ type: String,
+ default: ''
+ },
+ badgeType: {
+ type: String,
+ default: 'success'
+ },
+ badgeStyle: {
+ type: Object,
+ default () {
+ return {}
+ }
+ },
+ rightText: {
+ type: String,
+ default: ''
+ },
+ thumb: {
+ type: String,
+ default: ''
+ },
+ thumbSize: {
+ type: String,
+ default: 'base'
+ },
+ showExtraIcon: {
+ type: [Boolean, String],
+ default: false
+ },
+ extraIcon: {
+ type: Object,
+ default () {
+ return {
+ type: '',
+ color: '#000000',
+ size: 20,
+ customPrefix: ''
+ };
+ }
+ },
+ border: {
+ type: Boolean,
+ default: true
+ },
+ customStyle: {
+ type: Object,
+ default () {
+ return {
+ padding: '',
+ backgroundColor: '#FFFFFF'
+ }
+ }
+ },
+ keepScrollPosition: {
+ type: Boolean,
+ default: false
+ }
+ },
+ watch: {
+ 'customStyle.padding': {
+ handler(padding) {
+ if(typeof padding == 'number'){
+ padding += ''
+ }
+ let paddingArr = padding.split(' ')
+ if (paddingArr.length === 1) {
+ const allPadding = paddingArr[0]
+ this.padding = {
+ "top": allPadding,
+ "right": allPadding,
+ "bottom": allPadding,
+ "left": allPadding
+ }
+ } else if (paddingArr.length === 2) {
+ const [verticalPadding, horizontalPadding] = paddingArr;
+ this.padding = {
+ "top": verticalPadding,
+ "right": horizontalPadding,
+ "bottom": verticalPadding,
+ "left": horizontalPadding
+ }
+ } else if (paddingArr.length === 4) {
+ const [topPadding, rightPadding, bottomPadding, leftPadding] = paddingArr;
+ this.padding = {
+ "top": topPadding,
+ "right": rightPadding,
+ "bottom": bottomPadding,
+ "left": leftPadding
+ }
+ }
+ },
+ immediate: true
+ }
+ },
+ // inject: ['list'],
+ data() {
+ return {
+ isFirstChild: false,
+ padding: {
+ top: "",
+ right: "",
+ bottom: "",
+ left: ""
+ }
+ };
+ },
+ mounted() {
+ this.list = this.getForm()
+ // 鍒ゆ柇鏄惁瀛樺湪 uni-list 缁勪欢
+ if (this.list) {
+ if (!this.list.firstChildAppend) {
+ this.list.firstChildAppend = true;
+ this.isFirstChild = true;
+ }
+ }
+ },
+ methods: {
+ /**
+ * 鑾峰彇鐖跺厓绱犲疄渚�
+ */
+ getForm(name = 'uniList') {
+ let parent = this.$parent;
+ let parentName = parent.$options.name;
+ while (parentName !== name) {
+ parent = parent.$parent;
+ if (!parent) return false
+ parentName = parent.$options.name;
+ }
+ return parent;
+ },
+ onClick() {
+ if (this.to !== '') {
+ this.openPage();
+ return;
+ }
+ if (this.clickable || this.link) {
+ this.$emit('click', {
+ data: {}
+ });
+ }
+ },
+ onSwitchChange(e) {
+ this.$emit('switchChange', e.detail);
+ },
+ openPage() {
+ if (['navigateTo', 'redirectTo', 'reLaunch', 'switchTab'].indexOf(this.link) !== -1) {
+ this.pageApi(this.link);
+ } else {
+ this.pageApi('navigateTo');
+ }
+ },
+ pageApi(api) {
+ let callback = {
+ url: this.to,
+ success: res => {
+ this.$emit('click', {
+ data: res
+ });
+ },
+ fail: err => {
+ this.$emit('click', {
+ data: err
+ });
+ }
+ }
+ switch (api) {
+ case 'navigateTo':
+ uni.navigateTo(callback)
+ break
+ case 'redirectTo':
+ uni.redirectTo(callback)
+ break
+ case 'reLaunch':
+ uni.reLaunch(callback)
+ break
+ case 'switchTab':
+ uni.switchTab(callback)
+ break
+ default:
+ uni.navigateTo(callback)
+ }
+ }
+ }
+ };
+</script>
+
+<style lang="scss">
+ $uni-font-size-sm:12px;
+ $uni-font-size-base:14px;
+ $uni-font-size-lg:16px;
+ $uni-spacing-col-lg: 12px;
+ $uni-spacing-row-lg: 15px;
+ $uni-img-size-sm:20px;
+ $uni-img-size-base:26px;
+ $uni-img-size-lg:40px;
+ $uni-border-color:#e5e5e5;
+ $uni-bg-color-hover:#f1f1f1;
+ $uni-text-color-grey:#999;
+ $list-item-pd: $uni-spacing-col-lg $uni-spacing-row-lg;
+
+ .uni-list-item {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ font-size: $uni-font-size-lg;
+ position: relative;
+ justify-content: space-between;
+ align-items: center;
+ background-color: #fff;
+ flex-direction: row;
+ /* #ifdef H5 */
+ cursor: pointer;
+ /* #endif */
+ }
+
+ .uni-list-item--disabled {
+ opacity: 0.3;
+ }
+
+ .uni-list-item--hover {
+ background-color: $uni-bg-color-hover !important;
+ }
+
+ .uni-list-item__container {
+ position: relative;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ padding: $list-item-pd;
+ padding-left: $uni-spacing-row-lg;
+ flex: 1;
+ overflow: hidden;
+ // align-items: center;
+ }
+
+ .container--right {
+ padding-right: 0;
+ }
+
+ // .border--left {
+ // margin-left: $uni-spacing-row-lg;
+ // }
+ .uni-list--border {
+ position: absolute;
+ top: 0;
+ right: 0;
+ left: 0;
+ /* #ifdef APP-NVUE */
+ border-top-color: $uni-border-color;
+ border-top-style: solid;
+ border-top-width: 0.5px;
+ /* #endif */
+ }
+
+ /* #ifndef APP-NVUE */
+ .uni-list--border:after {
+ position: absolute;
+ top: 0;
+ right: 0;
+ left: 0;
+ height: 1px;
+ content: '';
+ -webkit-transform: scaleY(0.5);
+ transform: scaleY(0.5);
+ background-color: $uni-border-color;
+ }
+
+ /* #endif */
+ .uni-list-item__content {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ padding-right: 8px;
+ flex: 1;
+ color: #3b4144;
+ // overflow: hidden;
+ flex-direction: column;
+ justify-content: space-between;
+ overflow: hidden;
+ }
+
+ .uni-list-item__content--center {
+ justify-content: center;
+ }
+
+ .uni-list-item__content-title {
+ font-size: $uni-font-size-base;
+ color: #3b4144;
+ overflow: hidden;
+ }
+
+ .uni-list-item__content-note {
+ margin-top: 6rpx;
+ color: $uni-text-color-grey;
+ font-size: $uni-font-size-sm;
+ overflow: hidden;
+ }
+
+ .uni-list-item__extra {
+ // width: 25%;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ justify-content: flex-end;
+ align-items: center;
+ }
+
+ .uni-list-item__header {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ align-items: center;
+ }
+
+ .uni-list-item__icon {
+ margin-right: 18rpx;
+ flex-direction: row;
+ justify-content: center;
+ align-items: center;
+ }
+
+ .uni-list-item__icon-img {
+ /* #ifndef APP-NVUE */
+ display: block;
+ /* #endif */
+ height: $uni-img-size-base;
+ width: $uni-img-size-base;
+ margin-right: 10px;
+ }
+
+ .uni-icon-wrapper {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ align-items: center;
+ padding: 0 10px;
+ }
+
+ .flex--direction {
+ flex-direction: column;
+ /* #ifndef APP-NVUE */
+ align-items: initial;
+ /* #endif */
+ }
+
+ .flex--justify {
+ /* #ifndef APP-NVUE */
+ justify-content: initial;
+ /* #endif */
+ }
+
+ .uni-list--lg {
+ height: $uni-img-size-lg;
+ width: $uni-img-size-lg;
+ }
+
+ .uni-list--base {
+ height: $uni-img-size-base;
+ width: $uni-img-size-base;
+ }
+
+ .uni-list--sm {
+ height: $uni-img-size-sm;
+ width: $uni-img-size-sm;
+ }
+
+ .uni-list-item__extra-text {
+ color: $uni-text-color-grey;
+ font-size: $uni-font-size-sm;
+ }
+
+ .uni-ellipsis-1 {
+ /* #ifndef APP-NVUE */
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ /* #endif */
+ /* #ifdef APP-NVUE */
+ lines: 1;
+ text-overflow: ellipsis;
+ /* #endif */
+ }
+
+ .uni-ellipsis-2 {
+ /* #ifndef APP-NVUE */
+ overflow: hidden;
+ text-overflow: ellipsis;
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ /* #endif */
+ /* #ifdef APP-NVUE */
+ lines: 2;
+ text-overflow: ellipsis;
+ /* #endif */
+ }
+</style>
\ No newline at end of file
diff --git a/app/uni_modules/uni-list/components/uni-list/uni-list.vue b/app/uni_modules/uni-list/components/uni-list/uni-list.vue
new file mode 100644
index 0000000..6ef5972
--- /dev/null
+++ b/app/uni_modules/uni-list/components/uni-list/uni-list.vue
@@ -0,0 +1,123 @@
+<template>
+ <!-- #ifndef APP-NVUE -->
+ <view class="uni-list uni-border-top-bottom">
+ <view v-if="border" class="uni-list--border-top"></view>
+ <slot />
+ <view v-if="border" class="uni-list--border-bottom"></view>
+ </view>
+ <!-- #endif -->
+ <!-- #ifdef APP-NVUE -->
+ <list :bounce="false" :scrollable="true" show-scrollbar :render-reverse="renderReverse" @scroll="scroll" class="uni-list" :class="{ 'uni-list--border': border }" :enableBackToTop="enableBackToTop"
+ loadmoreoffset="15">
+ <slot />
+ </list>
+ <!-- #endif -->
+</template>
+
+<script>
+ /**
+ * List 鍒楄〃
+ * @description 鍒楄〃缁勪欢
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=24
+ * @property {String} border = [true|false] 鏍囬
+ */
+ export default {
+ name: 'uniList',
+ 'mp-weixin': {
+ options: {
+ multipleSlots: false
+ }
+ },
+ props: {
+ stackFromEnd:{
+ type: Boolean,
+ default:false
+ },
+ enableBackToTop: {
+ type: [Boolean, String],
+ default: false
+ },
+ scrollY: {
+ type: [Boolean, String],
+ default: false
+ },
+ border: {
+ type: Boolean,
+ default: true
+ },
+ renderReverse:{
+ type: Boolean,
+ default: false
+ }
+ },
+ // provide() {
+ // return {
+ // list: this
+ // };
+ // },
+ created() {
+ this.firstChildAppend = false;
+ },
+ methods: {
+ loadMore(e) {
+ this.$emit('scrolltolower');
+ },
+ scroll(e) {
+ this.$emit('scroll', e);
+ }
+ }
+ };
+</script>
+<style lang="scss">
+ $uni-bg-color:#ffffff;
+ $uni-border-color:#e5e5e5;
+
+ .uni-list {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ background-color: $uni-bg-color;
+ position: relative;
+ flex-direction: column;
+ }
+
+ .uni-list--border {
+ position: relative;
+ /* #ifdef APP-NVUE */
+ border-top-color: $uni-border-color;
+ border-top-style: solid;
+ border-top-width: 0.5px;
+ border-bottom-color: $uni-border-color;
+ border-bottom-style: solid;
+ border-bottom-width: 0.5px;
+ /* #endif */
+ z-index: -1;
+ }
+
+ /* #ifndef APP-NVUE */
+
+ .uni-list--border-top {
+ position: absolute;
+ top: 0;
+ right: 0;
+ left: 0;
+ height: 1px;
+ -webkit-transform: scaleY(0.5);
+ transform: scaleY(0.5);
+ background-color: $uni-border-color;
+ z-index: 1;
+ }
+
+ .uni-list--border-bottom {
+ position: absolute;
+ bottom: 0;
+ right: 0;
+ left: 0;
+ height: 1px;
+ -webkit-transform: scaleY(0.5);
+ transform: scaleY(0.5);
+ background-color: $uni-border-color;
+ }
+
+ /* #endif */
+</style>
diff --git a/app/uni_modules/uni-list/components/uni-list/uni-refresh.vue b/app/uni_modules/uni-list/components/uni-list/uni-refresh.vue
new file mode 100644
index 0000000..3b4c5a2
--- /dev/null
+++ b/app/uni_modules/uni-list/components/uni-list/uni-refresh.vue
@@ -0,0 +1,65 @@
+<template>
+ <!-- #ifdef APP-NVUE -->
+ <refresh :display="display" @refresh="onrefresh" @pullingdown="onpullingdown">
+ <slot />
+ </refresh>
+ <!-- #endif -->
+ <!-- #ifndef APP-NVUE -->
+ <view ref="uni-refresh" class="uni-refresh" v-show="isShow">
+ <slot />
+ </view>
+ <!-- #endif -->
+</template>
+
+<script>
+ export default {
+ name: 'UniRefresh',
+ props: {
+ display: {
+ type: [String],
+ default: "hide"
+ }
+ },
+ data() {
+ return {
+ pulling: false
+ }
+ },
+ computed: {
+ isShow() {
+ if (this.display === "show" || this.pulling === true) {
+ return true;
+ }
+ return false;
+ }
+ },
+ created() {},
+ methods: {
+ onchange(value) {
+ this.pulling = value;
+ },
+ onrefresh(e) {
+ this.$emit("refresh", e);
+ },
+ onpullingdown(e) {
+ // #ifdef APP-NVUE
+ this.$emit("pullingdown", e);
+ // #endif
+ // #ifndef APP-NVUE
+ var detail = {
+ viewHeight: 90,
+ pullingDistance: e.height
+ }
+ this.$emit("pullingdown", detail);
+ // #endif
+ }
+ }
+ }
+</script>
+
+<style>
+ .uni-refresh {
+ height: 0;
+ overflow: hidden;
+ }
+</style>
diff --git a/app/uni_modules/uni-list/components/uni-list/uni-refresh.wxs b/app/uni_modules/uni-list/components/uni-list/uni-refresh.wxs
new file mode 100644
index 0000000..818a6b7
--- /dev/null
+++ b/app/uni_modules/uni-list/components/uni-list/uni-refresh.wxs
@@ -0,0 +1,87 @@
+var pullDown = {
+ threshold: 95,
+ maxHeight: 200,
+ callRefresh: 'onrefresh',
+ callPullingDown: 'onpullingdown',
+ refreshSelector: '.uni-refresh'
+};
+
+function ready(newValue, oldValue, ownerInstance, instance) {
+ var state = instance.getState()
+ state.canPullDown = newValue;
+ // console.log(newValue);
+}
+
+function touchStart(e, instance) {
+ var state = instance.getState();
+ state.refreshInstance = instance.selectComponent(pullDown.refreshSelector);
+ state.canPullDown = (state.refreshInstance != null && state.refreshInstance != undefined);
+ if (!state.canPullDown) {
+ return
+ }
+
+ // console.log("touchStart");
+
+ state.height = 0;
+ state.touchStartY = e.touches[0].pageY || e.changedTouches[0].pageY;
+ state.refreshInstance.setStyle({
+ 'height': 0
+ });
+ state.refreshInstance.callMethod("onchange", true);
+}
+
+function touchMove(e, ownerInstance) {
+ var instance = e.instance;
+ var state = instance.getState();
+ if (!state.canPullDown) {
+ return
+ }
+
+ var oldHeight = state.height;
+ var endY = e.touches[0].pageY || e.changedTouches[0].pageY;
+ var height = endY - state.touchStartY;
+ if (height > pullDown.maxHeight) {
+ return;
+ }
+
+ var refreshInstance = state.refreshInstance;
+ refreshInstance.setStyle({
+ 'height': height + 'px'
+ });
+
+ height = height < pullDown.maxHeight ? height : pullDown.maxHeight;
+ state.height = height;
+ refreshInstance.callMethod(pullDown.callPullingDown, {
+ height: height
+ });
+}
+
+function touchEnd(e, ownerInstance) {
+ var state = e.instance.getState();
+ if (!state.canPullDown) {
+ return
+ }
+
+ state.refreshInstance.callMethod("onchange", false);
+
+ var refreshInstance = state.refreshInstance;
+ if (state.height > pullDown.threshold) {
+ refreshInstance.callMethod(pullDown.callRefresh);
+ return;
+ }
+
+ refreshInstance.setStyle({
+ 'height': 0
+ });
+}
+
+function propObserver(newValue, oldValue, instance) {
+ pullDown = newValue;
+}
+
+module.exports = {
+ touchmove: touchMove,
+ touchstart: touchStart,
+ touchend: touchEnd,
+ propObserver: propObserver
+}
diff --git a/app/uni_modules/uni-list/package.json b/app/uni_modules/uni-list/package.json
new file mode 100644
index 0000000..8350efc
--- /dev/null
+++ b/app/uni_modules/uni-list/package.json
@@ -0,0 +1,88 @@
+{
+ "id": "uni-list",
+ "displayName": "uni-list 鍒楄〃",
+ "version": "1.2.14",
+ "description": "List 缁勪欢 锛屽府鍔╀娇鐢ㄨ�呭揩閫熸瀯寤哄垪琛ㄣ��",
+ "keywords": [
+ "",
+ "uni-ui",
+ "uniui",
+ "鍒楄〃",
+ "",
+ "list"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+"dcloudext": {
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+ "type": "component-vue"
+ },
+ "uni_modules": {
+ "dependencies": [
+ "uni-badge",
+ "uni-icons"
+ ],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "u",
+ "鑱旂洘": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/uni_modules/uni-list/readme.md b/app/uni_modules/uni-list/readme.md
new file mode 100644
index 0000000..32c2865
--- /dev/null
+++ b/app/uni_modules/uni-list/readme.md
@@ -0,0 +1,346 @@
+## List 鍒楄〃
+> **缁勪欢鍚嶏細uni-list**
+> 浠g爜鍧楋細 `uList`銆乣uListItem`
+> 鍏宠仈缁勪欢锛歚uni-list-item`銆乣uni-badge`銆乣uni-icons`銆乣uni-list-chat`銆乣uni-list-ad`
+
+
+List 鍒楄〃缁勪欢锛屽寘鍚熀鏈垪琛ㄦ牱寮忋�佸彲鎵╁睍鎻掓Ы鏈哄埗銆侀暱鍒楄〃鎬ц兘浼樺寲銆佸绔吋瀹广��
+
+鍦╲ue椤甸潰閲岋紝瀹冮粯璁や娇鐢ㄩ〉闈㈢骇婊氬姩銆傚湪app-nvue椤甸潰閲岋紝瀹冮粯璁や娇鐢ㄥ師鐢焞ist缁勪欢婊氬姩銆傝繖鏍风殑闀垮垪琛紝鍦ㄦ粴鍔ㄥ嚭灞忓箷澶栧悗锛岀郴缁熶細鍥炴敹涓嶅彲瑙佸尯鍩熺殑娓叉煋鍐呭瓨璧勬簮锛屼笉浼氶�犳垚婊氬姩瓒婇暱鎵嬫満瓒婂崱鐨勯棶棰樸��
+
+uni-list缁勪欢鏄埗瀹瑰櫒锛岄噷闈㈢殑鏍稿績鏄痷ni-list-item瀛愮粍浠讹紝瀹冧唬琛ㄥ垪琛ㄤ腑鐨勪竴涓彲閲嶅琛岋紝瀛愮粍浠跺彲浠ユ棤闄愬惊鐜��
+
+uni-list-item鏈夊緢澶氶鏍硷紝uni-list-item缁勪欢閫氳繃鍐呯疆鐨勫睘鎬э紝婊¤冻涓�浜涘父鐢ㄧ殑鍦烘櫙銆傚綋鍐呯疆灞炴�т笉婊¤冻闇�姹傛椂锛屽彲浠ラ�氳繃鎵╁睍鎻掓Ы鏉ヨ嚜瀹氫箟鍒楄〃鍐呭銆�
+
+鍐呯疆灞炴�у彲浠ヨ鐩栫殑鍦烘櫙鍖呮嫭锛氬鑸垪琛ㄣ�佽缃垪琛ㄣ�佸皬鍥炬爣鍒楄〃銆侀�氫俊褰曞垪琛ㄣ�佽亰澶╄褰曞垪琛ㄣ��
+
+娑夊強寰堝澶у浘鎴栦赴瀵屽唴瀹圭殑鍒楄〃锛屾瘮濡傜被浠婃棩澶存潯鐨勬柊闂诲垪琛ㄣ�佺被娣樺疂鐨勭數鍟嗗垪琛紝闇�瑕侀�氳繃鎵╁睍鎻掓Ы瀹炵幇銆�
+
+涓嬫枃鍧囨湁鏍蜂緥缁欏嚭銆�
+
+uni-list涓嶅寘鍚笅鎷夊埛鏂板拰涓婃媺缈婚〉銆備笂鎷夌炕椤靛彟瑙佺粍浠讹細[uni-load-more](https://ext.dcloud.net.cn/plugin?id=29)
+
+
+### 瀹夎鏂瑰紡
+
+鏈粍浠剁鍚圼easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)瑙勮寖锛宍HBuilderX 2.5.5`璧凤紝鍙渶灏嗘湰缁勪欢瀵煎叆椤圭洰锛屽湪椤甸潰`template`涓嵆鍙洿鎺ヤ娇鐢紝鏃犻渶鍦ㄩ〉闈腑`import`鍜屾敞鍐宍components`銆�
+
+濡傞渶閫氳繃`npm`鏂瑰紡浣跨敤`uni-ui`缁勪欢锛屽彟瑙佹枃妗o細[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55)
+
+> **娉ㄦ剰浜嬮」**
+> 涓轰簡閬垮厤閿欒浣跨敤锛岀粰澶у甯︽潵涓嶅ソ鐨勫紑鍙戜綋楠岋紝璇峰湪浣跨敤缁勪欢鍓嶄粩缁嗛槄璇讳笅闈㈢殑娉ㄦ剰浜嬮」锛屽彲浠ュ府浣犻伩鍏嶄竴浜涢敊璇��
+> - 缁勪欢闇�瑕佷緷璧� `sass` 鎻掍欢 锛岃鑷鎵嬪姩瀹夎
+> - 缁勪欢鍐呴儴渚濊禆 `'uni-icons'` 銆乣uni-badge` 缁勪欢
+> - `uni-list` 鍜� `uni-list-item` 闇�瑕侀厤濂椾娇鐢紝鏆備笉鏀寔鍗曠嫭浣跨敤 `uni-list-item`
+> - 鍙湁寮�鍚偣鍑诲弽棣堝悗锛屼細鏈夌偣鍑婚�変腑鏁堟灉
+> - 浣跨敤鎻掓Ы鏃讹紝鍙互瀹屽叏鑷畾涔夊唴瀹�
+> - note 銆乺ightText 灞炴�ф殏鏃舵病鍋氶檺鍒讹紝涓嶆敮鎸佹枃瀛楁孩鍑洪殣钘忥紝浣跨敤鏃跺簲璇ユ帶鍒堕暱搴︽樉绀烘垨閫氳繃榛樿鎻掓Ы鑷鎵╁睍
+> - 鏀粯瀹濆皬绋嬪簭骞冲彴闇�瑕佸湪鏀粯瀹濆皬绋嬪簭寮�鍙戣�呭伐鍏烽噷寮�鍚� component2 缂栬瘧妯″紡锛屽紑鍚柟寮忥細 璇︽儏 --> 椤圭洰閰嶇疆 --> 鍚敤 component2 缂栬瘧
+> - 濡傛灉闇�瑕佷慨鏀� `switch`銆乣badge` 鏍峰紡锛岃浣跨敤鎻掓Ы鑷畾涔�
+> - 鍦� `HBuilderX` 浣庣増鏈腑锛屽彲鑳戒細鍑虹幇缁勪欢鏄剧ず `undefined` 鐨勯棶棰橈紝璇峰崌绾ф渶鏂扮殑 `HBuilderX` 鎴栬�� `cli`
+> - 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
+
+
+### 鍩烘湰鐢ㄦ硶
+
+- 璁剧疆 `title` 灞炴�э紝鍙互鏄剧ず鍒楄〃鏍囬
+- 璁剧疆 `disabled` 灞炴�э紝鍙互绂佺敤褰撳墠椤�
+
+```html
+<uni-list>
+ <uni-list-item title="鍒楄〃鏂囧瓧" ></uni-list-item>
+ <uni-list-item :disabled="true" title="鍒楄〃绂佺敤鐘舵��" ></uni-list-item>
+</uni-list>
+
+```
+
+### 澶氳鍐呭鏄剧ず
+
+- 璁剧疆 `note` 灞炴�� 锛屽彲浠ュ湪绗簩琛屾樉绀烘弿杩版枃鏈俊鎭�
+
+```html
+<uni-list>
+ <uni-list-item title="鍒楄〃鏂囧瓧" note="鍒楄〃鎻忚堪淇℃伅"></uni-list-item>
+ <uni-list-item :disabled="true" title="鍒楄〃鏂囧瓧" note="鍒楄〃绂佺敤鐘舵��"></uni-list-item>
+</uni-list>
+
+```
+
+### 鍙充晶鏄剧ず瑙掓爣銆乻witch
+
+- 璁剧疆 `show-badge` 灞炴�� 锛屽彲浠ユ樉绀鸿鏍囧唴瀹�
+- 璁剧疆 `show-switch` 灞炴�э紝鍙互鏄剧ず switch 寮�鍏�
+
+```html
+<uni-list>
+ <uni-list-item title="鍒楄〃鍙充晶鏄剧ず瑙掓爣" :show-badge="true" badge-text="12" ></uni-list-item>
+ <uni-list-item title="鍒楄〃鍙充晶鏄剧ず switch" :show-switch="true" @switchChange="switchChange" ></uni-list-item>
+</uni-list>
+
+```
+
+### 宸︿晶鏄剧ず鐣ョ缉鍥俱�佸浘鏍�
+
+- 璁剧疆 `thumb` 灞炴�� 锛屽彲浠ュ湪鍒楄〃宸︿晶鏄剧ず鐣ョ缉鍥�
+- 璁剧疆 `show-extra-icon` 灞炴�э紝骞舵寚瀹� `extra-icon` 鍙互鍦ㄥ乏渚ф樉绀哄浘鏍�
+
+```html
+ <uni-list>
+ <uni-list-item title="鍒楄〃宸︿晶甯︾暐缂╁浘" note="鍒楄〃鎻忚堪淇℃伅" thumb="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png"
+ thumb-size="lg" rightText="鍙充晶鏂囧瓧"></uni-list-item>
+ <uni-list-item :show-extra-icon="true" :extra-icon="extraIcon1" title="鍒楄〃宸︿晶甯︽墿灞曞浘鏍�" ></uni-list-item>
+</uni-list>
+```
+
+### 寮�鍚偣鍑诲弽棣堝拰鍙充晶绠ご
+- 璁剧疆 `clickable` 涓� `true` 锛屽垯琛ㄧず杩欐槸涓�涓彲鐐瑰嚮鐨勫垪琛紝浼氶粯璁ょ粰涓�涓偣鍑绘晥鏋滐紝骞跺彲浠ョ洃鍚� `click` 浜嬩欢
+- 璁剧疆 `link` 灞炴�э紝浼氳嚜鍔ㄥ紑鍚偣鍑诲弽棣堬紝骞剁粰鍒楄〃鍙充晶娣诲姞涓�涓澶�
+- 璁剧疆 `to` 灞炴�э紝鍙互璺宠浆椤甸潰锛宍link` 鐨勫�艰〃绀鸿烦杞柟寮忥紝濡傛灉涓嶆寚瀹氾紝榛樿涓� `navigateTo`
+
+```html
+
+<uni-list>
+ <uni-list-item title="寮�鍚偣鍑诲弽棣�" clickable @click="onClick" ></uni-list-item>
+ <uni-list-item title="榛樿 navigateTo 鏂瑰紡璺宠浆椤甸潰" link to="/pages/vue/index/index" @click="onClick($event,1)" ></uni-list-item>
+ <uni-list-item title="reLaunch 鏂瑰紡璺宠浆椤甸潰" link="reLaunch" to="/pages/vue/index/index" @click="onClick($event,1)" ></uni-list-item>
+</uni-list>
+
+```
+
+
+### 鑱婂ぉ鍒楄〃绀轰緥
+- 璁剧疆 `clickable` 涓� `true` 锛屽垯琛ㄧず杩欐槸涓�涓彲鐐瑰嚮鐨勫垪琛紝浼氶粯璁ょ粰涓�涓偣鍑绘晥鏋滐紝骞跺彲浠ョ洃鍚� `click` 浜嬩欢
+- 璁剧疆 `link` 灞炴�э紝浼氳嚜鍔ㄥ紑鍚偣鍑诲弽棣堬紝`link` 鐨勫�艰〃绀鸿烦杞柟寮忥紝濡傛灉涓嶆寚瀹氾紝榛樿涓� `navigateTo`
+- 璁剧疆 `to` 灞炴�э紝鍙互璺宠浆椤甸潰
+- `time` 灞炴�э紝閫氬父浼氳缃垚鏃堕棿鏄剧ず锛屼絾鏄繖涓睘鎬т笉浠呬粎鍙互璁剧疆鏃堕棿锛屼綘鍙互浼犲叆浠讳綍鏂囨湰锛屾敞鎰忔枃鏈暱搴﹀彲鑳戒細褰卞搷鏄剧ず
+- `avatar` 鍜� `avatarList` 灞炴�у悓鏃跺彧浼氭湁涓�涓敓鏁堬紝鍚屾椂璁剧疆鐨勮瘽锛宍avatarList` 灞炴�х殑闀垮害澶т簬1 锛宍avatar` 灞炴�у皢澶辨晥
+- 鍙互閫氳繃榛樿鎻掓Ы鑷畾涔夊垪琛ㄥ彸渚у唴瀹�
+
+```html
+
+<uni-list>
+ <uni-list :border="true">
+ <!-- 鏄剧ず鍦嗗舰澶村儚 -->
+ <uni-list-chat :avatar-circle="true" title="uni-app" avatar="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png" note="鎮ㄦ敹鍒颁竴鏉℃柊鐨勬秷鎭�" time="2020-02-02 20:20" ></uni-list-chat>
+ <!-- 鍙充晶甯﹁鏍� -->
+ <uni-list-chat title="uni-app" avatar="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png" note="鎮ㄦ敹鍒颁竴鏉℃柊鐨勬秷鎭�" time="2020-02-02 20:20" badge-text="12" :badge-style="{backgroundColor:'#FF80AB'}"></uni-list-chat>
+ <!-- 澶村儚鏄剧ず鍦嗙偣 -->
+ <uni-list-chat title="uni-app" avatar="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png" note="鎮ㄦ敹鍒颁竴鏉℃柊鐨勬秷鎭�" time="2020-02-02 20:20" badge-positon="left" badge-text="dot"></uni-list-chat>
+ <!-- 澶村儚鏄剧ず瑙掓爣 -->
+ <uni-list-chat title="uni-app" avatar="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png" note="鎮ㄦ敹鍒颁竴鏉℃柊鐨勬秷鎭�" time="2020-02-02 20:20" badge-positon="left" badge-text="99"></uni-list-chat>
+ <!-- 鏄剧ず澶氬ご鍍� -->
+ <uni-list-chat title="uni-app" :avatar-list="avatarList" note="鎮ㄦ敹鍒颁竴鏉℃柊鐨勬秷鎭�" time="2020-02-02 20:20" badge-positon="left" badge-text="dot"></uni-list-chat>
+ <!-- 鑷畾涔夊彸渚у唴瀹� -->
+ <uni-list-chat title="uni-app" :avatar-list="avatarList" note="鎮ㄦ敹鍒颁竴鏉℃柊鐨勬秷鎭�" time="2020-02-02 20:20" badge-positon="left" badge-text="dot">
+ <view class="chat-custom-right">
+ <text class="chat-custom-text">鍒氬垰</text>
+ <!-- 闇�瑕佷娇鐢� uni-icons 璇疯嚜琛屽紩鍏� -->
+ <uni-icons type="star-filled" color="#999" size="18"></uni-icons>
+ </view>
+ </uni-list-chat>
+ </uni-list>
+</uni-list>
+
+```
+
+```javascript
+
+export default {
+ components: {},
+ data() {
+ return {
+ avatarList: [{
+ url: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png'
+ }, {
+ url: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png'
+ }, {
+ url: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png'
+ }]
+ }
+ }
+}
+
+```
+
+
+```css
+
+.chat-custom-right {
+ flex: 1;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: column;
+ justify-content: space-between;
+ align-items: flex-end;
+}
+
+.chat-custom-text {
+ font-size: 12px;
+ color: #999;
+}
+
+```
+
+## API
+
+### List Props
+
+灞炴�у悕 |绫诲瀷 |榛樿鍊� | 璇存槑
+:-: |:-: |:-: | :-:
+border |Boolean |true | 鏄惁鏄剧ず杈规
+
+
+### ListItem Props
+
+灞炴�у悕 |绫诲瀷 |榛樿鍊� | 璇存槑
+:-: |:-: |:-: | :-:
+title |String |- | 鏍囬
+note |String |- | 鎻忚堪
+ellipsis |Number |0 | title 鏄惁婧㈠嚭闅愯棌锛屽彲閫夊�硷紝0:榛樿; 1:鏄剧ず涓�琛�; 2:鏄剧ず涓よ;銆恘vue 鏆備笉鏀寔銆�
+thumb |String |- | 宸︿晶缂╃暐鍥撅紝鑻humb鏈夊�硷紝鍒欎笉浼氭樉绀烘墿灞曞浘鏍�
+thumbSize |String |medium | 鐣ョ缉鍥惧昂瀵革紝鍙�夊�硷紝lg:澶у浘; medium:涓�鑸�; sm:灏忓浘;
+showBadge |Boolean |false | 鏄惁鏄剧ず鏁板瓧瑙掓爣
+badgeText |String |- | 鏁板瓧瑙掓爣鍐呭
+badgeType |String |- | 鏁板瓧瑙掓爣绫诲瀷锛屽弬鑰僛uni-icons](https://ext.dcloud.net.cn/plugin?id=21)
+badgeStyle |Object |- | 鏁板瓧瑙掓爣鏍峰紡锛屼娇鐢╱ni-badge鐨刢ustom-style鍙傛暟
+rightText |String |- | 鍙充晶鏂囧瓧鍐呭
+disabled |Boolean |false | 鏄惁绂佺敤
+showArrow |Boolean |true | 鏄惁鏄剧ず绠ご鍥炬爣
+link |String |navigateTo | 鏂伴〉闈㈣烦杞柟寮忥紝鍙�夊�艰涓嬭〃
+to |String |- | 鏂伴〉闈㈣烦杞湴鍧�锛屽濉啓姝ゅ睘鎬э紝click 浼氳繑鍥為〉闈㈡槸鍚﹁烦杞垚鍔�
+clickable |Boolean |false | 鏄惁寮�鍚偣鍑诲弽棣�
+showSwitch |Boolean |false | 鏄惁鏄剧ずSwitch
+switchChecked |Boolean |false | Switch鏄惁琚�変腑
+showExtraIcon |Boolean |false | 宸︿晶鏄惁鏄剧ず鎵╁睍鍥炬爣
+extraIcon |Object |- | 鎵╁睍鍥炬爣鍙傛暟锛屾牸寮忎负 ``{color: '#4cd964',size: '22',type: 'spinner'}``锛屽弬鑰� [uni-icons](https://ext.dcloud.net.cn/plugin?id=28)
+direction | String |row | 鎺掔増鏂瑰悜锛屽彲閫夊�硷紝row:姘村钩鎺掑垪; column:鍨傜洿鎺掑垪; 3涓彃妲芥槸姘村钩鎺掕繕鏄瀭鐩存帓锛屼篃鍙楁灞炴�ф帶鍒�
+
+
+#### Link Options
+
+灞炴�у悕 | 璇存槑
+:-: | :-:
+navigateTo | 鍚� uni.navigateTo()
+redirectTo | 鍚� uni.reLaunch()
+reLaunch | 鍚� uni.reLaunch()
+switchTab | 鍚� uni.switchTab()
+
+### ListItem Events
+
+浜嬩欢绉板悕 |璇存槑 |杩斿洖鍙傛暟
+:-: |:-: |:-:
+click |鐐瑰嚮 uniListItem 瑙﹀彂浜嬩欢锛岄渶寮�鍚偣鍑诲弽棣� |-
+switchChange |鐐瑰嚮鍒囨崲 Switch 鏃惰Е鍙戯紝闇�鏄剧ず switch |e={value:checked}
+
+
+
+### ListItem Slots
+
+鍚嶇О | 璇存槑
+:-: | :-:
+header | 宸�/涓婂唴瀹规彃妲斤紝鍙畬鍏ㄨ嚜瀹氫箟榛樿鏄剧ず
+body | 涓棿鍐呭鎻掓Ы锛屽彲瀹屽叏鑷畾涔変腑闂村唴瀹�
+footer | 鍙�/涓嬪唴瀹规彃妲斤紝鍙畬鍏ㄨ嚜瀹氫箟鍙充晶鍐呭
+
+
+> **閫氳繃鎻掓Ы鎵╁睍**
+> 闇�瑕佹敞鎰忕殑鏄綋浣跨敤鎻掓Ы鏃讹紝鍐呯疆鏍峰紡灏嗕細澶辨晥锛屽彧淇濈暀鎺掔増鏍峰紡锛屾鏃剁殑鏍峰紡闇�瑕佸紑鍙戣�呰嚜宸卞疄鐜�
+> 濡傛灉 `uni-list-item` 缁勪欢鍐呯疆灞炴�ф牱寮忔棤娉曟弧瓒抽渶姹傦紝鍙互浣跨敤鎻掓Ы鏉ヨ嚜瀹氫箟uni-list-item閲岀殑鍐呭銆�
+> uni-list-item鎻愪緵浜�3涓彲鎵╁睍鐨勬彃妲斤細`header`銆乣body`銆乣footer`
+> - 褰� `direction` 灞炴�т负 `row` 鏃惰〃绀烘按骞虫帓鍒楋紝姝ゆ椂 `header` 琛ㄧず鍒楄〃鐨勫乏杈归儴鍒嗭紝`body` 琛ㄧず鍒楄〃鐨勪腑闂撮儴鍒嗭紝`footer` 琛ㄧず鍒楄〃鐨勫彸杈归儴鍒�
+> - 褰� `direction` 灞炴�т负 `column` 鏃惰〃绀哄瀭鐩存帓鍒楋紝姝ゆ椂 `header` 琛ㄧず鍒楄〃鐨勪笂杈归儴鍒嗭紝`body` 琛ㄧず鍒楄〃鐨勪腑闂撮儴鍒嗭紝`footer` 琛ㄧず鍒楄〃鐨勪笅杈归儴鍒�
+> 寮�鍙戣�呭彲浠ュ彧鐢�1涓彃妲斤紝涔熷彲浠�3涓竴璧蜂娇鐢ㄣ�傚湪鎻掓Ы涓彲鑷富缂栧啓view鏍囩锛屽疄鐜拌嚜宸辨墍闇�鐨勬晥鏋溿��
+
+
+**绀轰緥**
+
+```html
+<uni-list>
+ <uni-list-item title="鑷畾涔夊彸渚ф彃妲�" note="鍒楄〃鎻忚堪淇℃伅" link>
+ <template slot="header">
+ <image class="slot-image" src="/static/logo.png" mode="widthFix"></image>
+ </template>
+ </uni-list-item>
+ <uni-list-item>
+ <!-- 鑷畾涔� header -->
+ <view slot="header" class="slot-box"><image class="slot-image" src="/static/logo.png" mode="widthFix"></image></view>
+ <!-- 鑷畾涔� body -->
+ <text slot="body" class="slot-box slot-text">鑷畾涔夋彃妲�</text>
+ <!-- 鑷畾涔� footer-->
+ <template slot="footer">
+ <image class="slot-image" src="/static/logo.png" mode="widthFix"></image>
+ </template>
+ </uni-list-item>
+</uni-list>
+```
+
+
+
+
+
+### ListItemChat Props
+
+灞炴�у悕 |绫诲瀷 |榛樿鍊� | 璇存槑
+:-: |:-: |:-: | :-:
+title |String |- | 鏍囬
+note |String |- | 鎻忚堪
+clickable |Boolean |false | 鏄惁寮�鍚偣鍑诲弽棣�
+badgeText |String |- | 鏁板瓧瑙掓爣鍐呭锛岃缃负 `dot` 灏嗘樉绀哄渾鐐�
+badgePositon |String |right | 瑙掓爣浣嶇疆
+link |String |navigateTo | 鏄惁灞曠ず鍙充晶绠ご骞跺紑鍚偣鍑诲弽棣堬紝鍙�夊�艰涓嬭〃
+clickable |Boolean |false | 鏄惁寮�鍚偣鍑诲弽棣�
+to |String |- | 璺宠浆椤甸潰鍦板潃锛屽濉啓姝ゅ睘鎬э紝click 浼氳繑鍥為〉闈㈡槸鍚﹁烦杞垚鍔�
+time |String |- | 鍙充晶鏃堕棿鏄剧ず
+avatarCircle |Boolean |false | 鏄惁鏄剧ず鍦嗗舰澶村儚
+avatar |String |- | 澶村儚鍦板潃锛宎vatarCircle 涓嶅~鏃剁敓鏁�
+avatarList |Array |- | 澶村儚缁勶紝鏍煎紡涓� [{url:''}]
+
+#### Link Options
+
+灞炴�у悕 | 璇存槑
+:-: | :-:
+navigateTo | 鍚� uni.navigateTo()
+redirectTo | 鍚� uni.reLaunch()
+reLaunch | 鍚� uni.reLaunch()
+switchTab | 鍚� uni.switchTab()
+
+### ListItemChat Slots
+
+鍚嶇О | 璇存槑
+:- | :-
+default | 鑷畾涔夊垪琛ㄥ彸渚у唴瀹癸紙鍖呮嫭鏃堕棿鍜岃鏍囨樉绀猴級
+
+### ListItemChat Events
+浜嬩欢绉板悕 | 璇存槑 | 杩斿洖鍙傛暟
+:-: | :-: | :-:
+@click | 鐐瑰嚮 uniListChat 瑙﹀彂浜嬩欢 | {data:{}} 锛屽鏈� to 灞炴�э紝浼氳繑鍥為〉闈㈣烦杞俊鎭�
+
+
+
+
+
+
+## 鍩轰簬uni-list鎵╁睍鐨勯〉闈㈡ā鏉�
+
+閫氳繃鎵╁睍鎻掓Ы锛屽彲瀹炵幇澶氱甯歌鏍峰紡鐨勫垪琛�
+
+**鏂伴椈鍒楄〃绫�**
+
+1. 浜戠涓�浣撴贩鍚堝竷灞�锛歔https://ext.dcloud.net.cn/plugin?id=2546](https://ext.dcloud.net.cn/plugin?id=2546)
+2. 浜戠涓�浣撳瀭鐩村竷灞�锛屽ぇ鍥炬ā寮忥細[https://ext.dcloud.net.cn/plugin?id=2583](https://ext.dcloud.net.cn/plugin?id=2583)
+3. 浜戠涓�浣撳瀭鐩村竷灞�锛屽琛屽浘鏂囨贩鎺掞細[https://ext.dcloud.net.cn/plugin?id=2584](https://ext.dcloud.net.cn/plugin?id=2584)
+4. 浜戠涓�浣撳瀭鐩村竷灞�锛屽鍥炬ā寮忥細[https://ext.dcloud.net.cn/plugin?id=2585](https://ext.dcloud.net.cn/plugin?id=2585)
+5. 浜戠涓�浣撴按骞冲竷灞�锛屽乏鍥惧彸鏂囷細[https://ext.dcloud.net.cn/plugin?id=2586](https://ext.dcloud.net.cn/plugin?id=2586)
+6. 浜戠涓�浣撴按骞冲竷灞�锛屽乏鏂囧彸鍥撅細[https://ext.dcloud.net.cn/plugin?id=2587](https://ext.dcloud.net.cn/plugin?id=2587)
+7. 浜戠涓�浣撳瀭鐩村竷灞�锛屾棤鍥炬ā寮忥紝涓绘爣棰�+鍓爣棰橈細[https://ext.dcloud.net.cn/plugin?id=2588](https://ext.dcloud.net.cn/plugin?id=2588)
+
+**鍟嗗搧鍒楄〃绫�**
+
+1. 浜戠涓�浣撳垪琛�/瀹牸瑙嗗浘浜掑垏锛歔https://ext.dcloud.net.cn/plugin?id=2651](https://ext.dcloud.net.cn/plugin?id=2651)
+2. 浜戠涓�浣撳垪琛紙瀹牸妯″紡锛夛細[https://ext.dcloud.net.cn/plugin?id=2671](https://ext.dcloud.net.cn/plugin?id=2671)
+3. 浜戠涓�浣撳垪琛紙鍒楄〃妯″紡锛夛細[https://ext.dcloud.net.cn/plugin?id=2672](https://ext.dcloud.net.cn/plugin?id=2672)
+
+## 缁勪欢绀轰緥
+
+鐐瑰嚮鏌ョ湅锛歔https://hellouniapp.dcloud.net.cn/pages/extUI/list/list](https://hellouniapp.dcloud.net.cn/pages/extUI/list/list)
\ No newline at end of file
diff --git a/app/uni_modules/uni-load-more/changelog.md b/app/uni_modules/uni-load-more/changelog.md
new file mode 100644
index 0000000..8f03f1d
--- /dev/null
+++ b/app/uni_modules/uni-load-more/changelog.md
@@ -0,0 +1,19 @@
+## 1.3.3锛�2022-01-20锛�
+- 鏂板 showText灞炴�� 锛屾槸鍚︽樉绀烘枃鏈�
+## 1.3.2锛�2022-01-19锛�
+- 淇 nvue 骞冲彴涓嬩笉鏄剧ず鏂囨湰鐨刡ug
+## 1.3.1锛�2022-01-19锛�
+- 淇 寰俊灏忕▼搴忓钩鍙版牱寮忛�夋嫨鍣ㄦ姤璀﹀憡鐨勯棶棰�
+## 1.3.0锛�2021-11-19锛�
+- 浼樺寲 缁勪欢UI锛屽苟鎻愪緵璁捐璧勬簮锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 鏂囨。杩佺Щ锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/uni-load-more](https://uniapp.dcloud.io/component/uniui/uni-load-more)
+## 1.2.1锛�2021-08-24锛�
+- 鏂板 鏀寔鍥介檯鍖�
+## 1.2.0锛�2021-07-30锛�
+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤簐ue3椤圭洰锛岃瑙� [uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+## 1.1.8锛�2021-05-12锛�
+- 鏂板 缁勪欢绀轰緥鍦板潃
+## 1.1.7锛�2021-03-30锛�
+- 淇 uni-load-more 鍦ㄩ椤典娇鐢ㄦ椂锛宧5 骞冲彴鎶� 'uni is not defined' 鐨� bug
+## 1.1.6锛�2021-02-05锛�
+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
diff --git a/app/uni_modules/uni-load-more/components/uni-load-more/i18n/en.json b/app/uni_modules/uni-load-more/components/uni-load-more/i18n/en.json
new file mode 100644
index 0000000..a4f14a5
--- /dev/null
+++ b/app/uni_modules/uni-load-more/components/uni-load-more/i18n/en.json
@@ -0,0 +1,5 @@
+{
+ "uni-load-more.contentdown": "Pull up to show more",
+ "uni-load-more.contentrefresh": "loading...",
+ "uni-load-more.contentnomore": "No more data"
+}
diff --git a/app/uni_modules/uni-load-more/components/uni-load-more/i18n/index.js b/app/uni_modules/uni-load-more/components/uni-load-more/i18n/index.js
new file mode 100644
index 0000000..de7509c
--- /dev/null
+++ b/app/uni_modules/uni-load-more/components/uni-load-more/i18n/index.js
@@ -0,0 +1,8 @@
+import en from './en.json'
+import zhHans from './zh-Hans.json'
+import zhHant from './zh-Hant.json'
+export default {
+ en,
+ 'zh-Hans': zhHans,
+ 'zh-Hant': zhHant
+}
diff --git a/app/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hans.json b/app/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hans.json
new file mode 100644
index 0000000..f15d510
--- /dev/null
+++ b/app/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hans.json
@@ -0,0 +1,5 @@
+{
+ "uni-load-more.contentdown": "涓婃媺鏄剧ず鏇村",
+ "uni-load-more.contentrefresh": "姝e湪鍔犺浇...",
+ "uni-load-more.contentnomore": "娌℃湁鏇村鏁版嵁浜�"
+}
diff --git a/app/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hant.json b/app/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hant.json
new file mode 100644
index 0000000..a255c6d
--- /dev/null
+++ b/app/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hant.json
@@ -0,0 +1,5 @@
+{
+ "uni-load-more.contentdown": "涓婃媺椤ず鏇村",
+ "uni-load-more.contentrefresh": "姝e湪鍔犺級...",
+ "uni-load-more.contentnomore": "娌掓湁鏇村鏁告摎浜�"
+}
diff --git a/app/uni_modules/uni-load-more/components/uni-load-more/uni-load-more.vue b/app/uni_modules/uni-load-more/components/uni-load-more/uni-load-more.vue
new file mode 100644
index 0000000..e5eff4d
--- /dev/null
+++ b/app/uni_modules/uni-load-more/components/uni-load-more/uni-load-more.vue
@@ -0,0 +1,399 @@
+<template>
+ <view class="uni-load-more" @click="onClick">
+ <!-- #ifdef APP-NVUE -->
+ <loading-indicator v-if="!webviewHide && status === 'loading' && showIcon"
+ :style="{color: color,width:iconSize+'px',height:iconSize+'px'}" :animating="true"
+ class="uni-load-more__img uni-load-more__img--nvue"></loading-indicator>
+ <!-- #endif -->
+ <!-- #ifdef H5 -->
+ <svg width="24" height="24" viewBox="25 25 50 50"
+ v-if="!webviewHide && (iconType==='circle' || iconType==='auto' && platform === 'android') && status === 'loading' && showIcon"
+ :style="{width:iconSize+'px',height:iconSize+'px'}"
+ class="uni-load-more__img uni-load-more__img--android-H5">
+ <circle cx="50" cy="50" r="20" fill="none" :style="{color:color}" :stroke-width="3"></circle>
+ </svg>
+ <!-- #endif -->
+ <!-- #ifndef APP-NVUE || H5 -->
+ <view
+ v-if="!webviewHide && (iconType==='circle' || iconType==='auto' && platform === 'android') && status === 'loading' && showIcon"
+ :style="{width:iconSize+'px',height:iconSize+'px'}"
+ class="uni-load-more__img uni-load-more__img--android-MP">
+ <view class="uni-load-more__img-icon" :style="{borderTopColor:color,borderTopWidth:iconSize/12}"></view>
+ <view class="uni-load-more__img-icon" :style="{borderTopColor:color,borderTopWidth:iconSize/12}"></view>
+ <view class="uni-load-more__img-icon" :style="{borderTopColor:color,borderTopWidth:iconSize/12}"></view>
+ </view>
+ <!-- #endif -->
+ <!-- #ifndef APP-NVUE -->
+ <view v-else-if="!webviewHide && status === 'loading' && showIcon"
+ :style="{width:iconSize+'px',height:iconSize+'px'}" class="uni-load-more__img uni-load-more__img--ios-H5">
+ <image :src="imgBase64" mode="widthFix"></image>
+ </view>
+ <!-- #endif -->
+ <text v-if="showText" class="uni-load-more__text"
+ :style="{color: color}">{{ status === 'more' ? contentdownText : status === 'loading' ? contentrefreshText : contentnomoreText }}</text>
+ </view>
+</template>
+
+<script>
+ let platform
+ setTimeout(() => {
+ platform = uni.getSystemInfoSync().platform
+ }, 16)
+
+ import {
+ initVueI18n
+ } from '@dcloudio/uni-i18n'
+ import messages from './i18n/index.js'
+ const {
+ t
+ } = initVueI18n(messages)
+
+ /**
+ * LoadMore 鍔犺浇鏇村
+ * @description 鐢ㄤ簬鍒楄〃涓紝鍋氭粴鍔ㄥ姞杞戒娇鐢紝灞曠ず loading 鐨勫悇绉嶇姸鎬�
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=29
+ * @property {String} status = [more|loading|noMore] loading 鐨勭姸鎬�
+ * @value more loading鍓�
+ * @value loading loading涓�
+ * @value noMore 娌℃湁鏇村浜�
+ * @property {Number} iconSize 鎸囧畾鍥炬爣澶у皬
+ * @property {Boolean} iconSize = [true|false] 鏄惁鏄剧ず loading 鍥炬爣
+ * @property {String} iconType = [snow|circle|auto] 鎸囧畾鍥炬爣鏍峰紡
+ * @value snow ios闆姳鍔犺浇鏍峰紡
+ * @value circle 瀹夊崜鍞ら啋鍔犺浇鏍峰紡
+ * @value auto 鏍规嵁骞冲彴鑷姩閫夋嫨鍔犺浇鏍峰紡
+ * @property {String} color 鍥炬爣鍜屾枃瀛楅鑹�
+ * @property {Object} contentText 鍚勭姸鎬佹枃瀛楄鏄庯紝鍊间负锛歿contentdown: "涓婃媺鏄剧ず鏇村",contentrefresh: "姝e湪鍔犺浇...",contentnomore: "娌℃湁鏇村鏁版嵁浜�"}
+ * @event {Function} clickLoadMore 鐐瑰嚮鍔犺浇鏇村鏃惰Е鍙�
+ */
+ export default {
+ name: 'UniLoadMore',
+ emits: ['clickLoadMore'],
+ props: {
+ status: {
+ // 涓婃媺鐨勭姸鎬侊細more-loading鍓嶏紱loading-loading涓紱noMore-娌℃湁鏇村浜�
+ type: String,
+ default: 'more'
+ },
+ showIcon: {
+ type: Boolean,
+ default: true
+ },
+ iconType: {
+ type: String,
+ default: 'auto'
+ },
+ iconSize: {
+ type: Number,
+ default: 24
+ },
+ color: {
+ type: String,
+ default: '#777777'
+ },
+ contentText: {
+ type: Object,
+ default () {
+ return {
+ contentdown: '',
+ contentrefresh: '',
+ contentnomore: ''
+ }
+ }
+ },
+ showText: {
+ type: Boolean,
+ default: true
+ }
+ },
+ data() {
+ return {
+ webviewHide: false,
+ platform: platform,
+ imgBase64: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QzlBMzU3OTlEOUM0MTFFOUI0NTZDNERBQURBQzI4RkUiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QzlBMzU3OUFEOUM0MTFFOUI0NTZDNERBQURBQzI4RkUiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpDOUEzNTc5N0Q5QzQxMUU5QjQ1NkM0REFBREFDMjhGRSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpDOUEzNTc5OEQ5QzQxMUU5QjQ1NkM0REFBREFDMjhGRSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pt+ALSwAAA6CSURBVHja1FsLkFZV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'
+ }
+ },
+ computed: {
+ iconSnowWidth() {
+ return (Math.floor(this.iconSize / 24) || 1) * 2
+ },
+ contentdownText() {
+ return this.contentText.contentdown || t("uni-load-more.contentdown")
+ },
+ contentrefreshText() {
+ return this.contentText.contentrefresh || t("uni-load-more.contentrefresh")
+ },
+ contentnomoreText() {
+ return this.contentText.contentnomore || t("uni-load-more.contentnomore")
+ }
+ },
+ mounted() {
+ // #ifdef APP-PLUS
+ var pages = getCurrentPages();
+ var page = pages[pages.length - 1];
+ var currentWebview = page.$getAppWebview();
+ currentWebview.addEventListener('hide', () => {
+ this.webviewHide = true
+ })
+ currentWebview.addEventListener('show', () => {
+ this.webviewHide = false
+ })
+ // #endif
+ },
+ methods: {
+ onClick() {
+ this.$emit('clickLoadMore', {
+ detail: {
+ status: this.status,
+ }
+ })
+ }
+ }
+ }
+</script>
+
+<style lang="scss" >
+ .uni-load-more {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ height: 40px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ .uni-load-more__text {
+ font-size: 14px;
+ margin-left: 8px;
+ }
+
+ .uni-load-more__img {
+ width: 24px;
+ height: 24px;
+ // margin-right: 8px;
+ }
+
+ .uni-load-more__img--nvue {
+ color: #666666;
+ }
+
+ .uni-load-more__img--android,
+ .uni-load-more__img--ios {
+ width: 24px;
+ height: 24px;
+ transform: rotate(0deg);
+ }
+
+ /* #ifndef APP-NVUE */
+ .uni-load-more__img--android {
+ animation: loading-ios 1s 0s linear infinite;
+ }
+
+ @keyframes loading-android {
+ 0% {
+ transform: rotate(0deg);
+ }
+
+ 100% {
+ transform: rotate(360deg);
+ }
+ }
+
+ .uni-load-more__img--ios-H5 {
+ position: relative;
+ animation: loading-ios-H5 1s 0s step-end infinite;
+ }
+
+ .uni-load-more__img--ios-H5 image {
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ left: 0;
+ top: 0;
+ }
+
+ @keyframes loading-ios-H5 {
+ 0% {
+ transform: rotate(0deg);
+ }
+
+ 8% {
+ transform: rotate(30deg);
+ }
+
+ 16% {
+ transform: rotate(60deg);
+ }
+
+ 24% {
+ transform: rotate(90deg);
+ }
+
+ 32% {
+ transform: rotate(120deg);
+ }
+
+ 40% {
+ transform: rotate(150deg);
+ }
+
+ 48% {
+ transform: rotate(180deg);
+ }
+
+ 56% {
+ transform: rotate(210deg);
+ }
+
+ 64% {
+ transform: rotate(240deg);
+ }
+
+ 73% {
+ transform: rotate(270deg);
+ }
+
+ 82% {
+ transform: rotate(300deg);
+ }
+
+ 91% {
+ transform: rotate(330deg);
+ }
+
+ 100% {
+ transform: rotate(360deg);
+ }
+ }
+
+ /* #endif */
+
+ /* #ifdef H5 */
+ .uni-load-more__img--android-H5 {
+ animation: loading-android-H5-rotate 2s linear infinite;
+ transform-origin: center center;
+ }
+
+ .uni-load-more__img--android-H5 circle {
+ display: inline-block;
+ animation: loading-android-H5-dash 1.5s ease-in-out infinite;
+ stroke: currentColor;
+ stroke-linecap: round;
+ }
+
+ @keyframes loading-android-H5-rotate {
+ 0% {
+ transform: rotate(0deg);
+ }
+
+ 100% {
+ transform: rotate(360deg);
+ }
+ }
+
+ @keyframes loading-android-H5-dash {
+ 0% {
+ stroke-dasharray: 1, 200;
+ stroke-dashoffset: 0;
+ }
+
+ 50% {
+ stroke-dasharray: 90, 150;
+ stroke-dashoffset: -40;
+ }
+
+ 100% {
+ stroke-dasharray: 90, 150;
+ stroke-dashoffset: -120;
+ }
+ }
+
+ /* #endif */
+
+ /* #ifndef APP-NVUE || H5 */
+ .uni-load-more__img--android-MP {
+ position: relative;
+ width: 24px;
+ height: 24px;
+ transform: rotate(0deg);
+ animation: loading-ios 1s 0s ease infinite;
+ }
+
+ .uni-load-more__img--android-MP .uni-load-more__img-icon {
+ position: absolute;
+ box-sizing: border-box;
+ width: 100%;
+ height: 100%;
+ border-radius: 50%;
+ border: solid 2px transparent;
+ border-top: solid 2px #777777;
+ transform-origin: center;
+ }
+
+ .uni-load-more__img--android-MP .uni-load-more__img-icon:nth-child(1) {
+ animation: loading-android-MP-1 1s 0s linear infinite;
+ }
+
+ .uni-load-more__img--android-MP .uni-load-more__img-icon:nth-child(2) {
+ animation: loading-android-MP-2 1s 0s linear infinite;
+ }
+
+ .uni-load-more__img--android-MP .uni-load-more__img-icon:nth-child(3) {
+ animation: loading-android-MP-3 1s 0s linear infinite;
+ }
+
+ @keyframes loading-android {
+ 0% {
+ transform: rotate(0deg);
+ }
+
+ 100% {
+ transform: rotate(360deg);
+ }
+ }
+
+ @keyframes loading-android-MP-1 {
+ 0% {
+ transform: rotate(0deg);
+ }
+
+ 50% {
+ transform: rotate(90deg);
+ }
+
+ 100% {
+ transform: rotate(360deg);
+ }
+ }
+
+ @keyframes loading-android-MP-2 {
+ 0% {
+ transform: rotate(0deg);
+ }
+
+ 50% {
+ transform: rotate(180deg);
+ }
+
+ 100% {
+ transform: rotate(360deg);
+ }
+ }
+
+ @keyframes loading-android-MP-3 {
+ 0% {
+ transform: rotate(0deg);
+ }
+
+ 50% {
+ transform: rotate(270deg);
+ }
+
+ 100% {
+ transform: rotate(360deg);
+ }
+ }
+
+ /* #endif */
+</style>
diff --git a/app/uni_modules/uni-load-more/package.json b/app/uni_modules/uni-load-more/package.json
new file mode 100644
index 0000000..2fa6f04
--- /dev/null
+++ b/app/uni_modules/uni-load-more/package.json
@@ -0,0 +1,86 @@
+{
+ "id": "uni-load-more",
+ "displayName": "uni-load-more 鍔犺浇鏇村",
+ "version": "1.3.3",
+ "description": "LoadMore 缁勪欢锛屽父鐢ㄥ湪鍒楄〃閲岄潰锛屽仛婊氬姩鍔犺浇浣跨敤銆�",
+ "keywords": [
+ "uni-ui",
+ "uniui",
+ "鍔犺浇鏇村",
+ "load-more"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "鍓嶇缁勪欢",
+ "閫氱敤缁勪欢"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": ["uni-scss"],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "u",
+ "鑱旂洘": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/uni_modules/uni-load-more/readme.md b/app/uni_modules/uni-load-more/readme.md
new file mode 100644
index 0000000..54dc1fa
--- /dev/null
+++ b/app/uni_modules/uni-load-more/readme.md
@@ -0,0 +1,14 @@
+
+
+### LoadMore 鍔犺浇鏇村
+> **缁勪欢鍚嶏細uni-load-more**
+> 浠g爜鍧楋細 `uLoadMore`
+
+
+鐢ㄤ簬鍒楄〃涓紝鍋氭粴鍔ㄥ姞杞戒娇鐢紝灞曠ず loading 鐨勫悇绉嶇姸鎬併��
+
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-load-more)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
+
+
diff --git a/app/uni_modules/uni-nav-bar/changelog.md b/app/uni_modules/uni-nav-bar/changelog.md
new file mode 100644
index 0000000..0f9a2f1
--- /dev/null
+++ b/app/uni_modules/uni-nav-bar/changelog.md
@@ -0,0 +1,51 @@
+## 1.3.11锛�2023-03-29锛�
+- 淇 鑷畾涔夌姸鎬佹爮楂樺害闂姩BUG
+## 1.3.10锛�2023-03-29锛�
+- 淇 鏆楅粦妯″紡涓嬭竟绾块鑹查敊璇殑bug
+## 1.3.9锛�2022-10-13锛�
+- 淇 鏉′欢缂栬瘧閿欒鐨刡ug
+## 1.3.8锛�2022-10-12锛�
+- 淇 nvue 鐜 fixed 涓� true 鐨勬儏鍐典笅锛屾棤娉曠疆椤剁殑 bug
+## 1.3.7锛�2022-08-11锛�
+- 淇 nvue 鐜涓� fixed 涓� true 鐨勬儏鍐典笅锛屾棤娉曠疆椤剁殑 bug
+## 1.3.6锛�2022-06-30锛�
+- 淇 缁勪欢绀轰緥涓彃妲界敤娉曟棤娉曟樉绀哄唴瀹圭殑bug
+## 1.3.5锛�2022-05-24锛�
+- 鏂板 stat 灞炴�� 锛屽彲寮�鍚粺璁itle 涓婃姤 锛屼粎浣跨敤浜唗itle 灞炴�т笖椤圭洰寮�鍚簡uni缁熻鐢熸晥
+## 1.3.4锛�2022-01-24锛�
+- 鏇存柊 缁勪欢绀轰緥
+## 1.3.3锛�2022-01-24锛�
+- 鏂板 left-width/right-width灞炴�� 锛屽彲淇敼宸﹀彸涓や晶鐨勫搴�
+## 1.3.2锛�2022-01-18锛�
+- 淇 鍦╲ue涓嬶紝鏍囬涓嶅瀭鐩村眳涓殑bug
+## 1.3.1锛�2022-01-18锛�
+- 淇 height 灞炴�х被鍨嬮敊璇�
+## 1.3.0锛�2022-01-18锛�
+- 鏂板 height 灞炴��,鍙慨鏀圭粍浠堕珮搴�
+- 鏂板 dark 灞炴�у彲鍙紑鍚殫榛戞ā寮�
+- 浼樺寲 鏍囬瀛楁暟杩囧鏄剧ず鐪佺暐鍙�
+- 浼樺寲 鎻掓Ы锛屾彃鍏ュ唴瀹瑰彲瀹屽叏瑕嗙洊
+## 1.2.1锛�2022-01-10锛�
+- 淇 color 灞炴�т笉鐢熸晥鐨刡ug
+## 1.2.0锛�2021-11-19锛�
+- 浼樺寲 缁勪欢UI锛屽苟鎻愪緵璁捐璧勬簮锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 鏂囨。杩佺Щ锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/uni-nav-bar](https://uniapp.dcloud.io/component/uniui/uni-nav-bar)
+## 1.1.0锛�2021-07-30锛�
+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤簐ue3椤圭洰锛岃瑙� [uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+## 1.0.11锛�2021-05-12锛�
+- 鏂板 缁勪欢绀轰緥鍦板潃
+## 1.0.10锛�2021-04-30锛�
+- 淇 鍦╪vue涓媐ixed涓簍rue锛屽搴︿笉鑳芥拺婊$殑Bug
+## 1.0.9锛�2021-04-21锛�
+- 浼樺寲 娣诲姞渚濊禆 uni-icons, 瀵煎叆鍚庤嚜鍔ㄤ笅杞戒緷璧�
+## 1.0.8锛�2021-04-14锛�
+- uni-ui 淇 uni-nav-bar 褰� fixed 灞炴�т负 true 鏃堕摵涓嶆弧灞忓箷鐨� bug
+
+## 1.0.7锛�2021-02-25锛�
+- 淇 easycom 涓嬶紝鎵句笉鍒� uni-status-bar 鐨刡ug
+
+## 1.0.6锛�2021-02-05锛�
+- 浼樺寲 缁勪欢寮曠敤鍏崇郴锛岄�氳繃uni_modules寮曠敤缁勪欢
+
+## 1.0.5锛�2021-02-05锛�
+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
diff --git a/app/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-nav-bar.vue b/app/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-nav-bar.vue
new file mode 100644
index 0000000..c890860
--- /dev/null
+++ b/app/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-nav-bar.vue
@@ -0,0 +1,357 @@
+<template>
+ <view class="uni-navbar" :class="{'uni-dark':dark, 'uni-nvue-fixed': fixed}">
+ <view class="uni-navbar__content" :class="{ 'uni-navbar--fixed': fixed, 'uni-navbar--shadow': shadow, 'uni-navbar--border': border }"
+ :style="{ 'background-color': themeBgColor, 'border-bottom-color':themeColor }" >
+ <status-bar v-if="statusBar" />
+ <view :style="{ color: themeColor,backgroundColor: themeBgColor ,height:navbarHeight}"
+ class="uni-navbar__header">
+ <view @tap="onClickLeft" class="uni-navbar__header-btns uni-navbar__header-btns-left"
+ :style="{width:leftIconWidth}">
+ <slot name="left">
+ <view class="uni-navbar__content_view" v-if="leftIcon.length > 0">
+ <uni-icons :color="themeColor" :type="leftIcon" size="20" />
+ </view>
+ <view :class="{ 'uni-navbar-btn-icon-left': !leftIcon.length > 0 }" class="uni-navbar-btn-text"
+ v-if="leftText.length">
+ <text :style="{ color: themeColor, fontSize: '12px' }">{{ leftText }}</text>
+ </view>
+ </slot>
+ </view>
+ <view class="uni-navbar__header-container " @tap="onClickTitle">
+ <slot>
+ <view class="uni-navbar__header-container-inner" v-if="title.length>0">
+ <text class="uni-nav-bar-text uni-ellipsis-1"
+ :style="{color: themeColor }">{{ title }}</text>
+ </view>
+ </slot>
+ </view>
+ <view @click="onClickRight" class="uni-navbar__header-btns uni-navbar__header-btns-right"
+ :style="{width:rightIconWidth}">
+ <slot name="right">
+ <view v-if="rightIcon.length">
+ <uni-icons :color="themeColor" :type="rightIcon" size="22" />
+ </view>
+ <view class="uni-navbar-btn-text" v-if="rightText.length && !rightIcon.length">
+ <text class="uni-nav-bar-right-text" :style="{ color: themeColor}">{{ rightText }}</text>
+ </view>
+ </slot>
+ </view>
+ </view>
+ </view>
+ <!-- #ifndef APP-NVUE -->
+ <view class="uni-navbar__placeholder" v-if="fixed">
+ <status-bar v-if="statusBar" />
+ <view class="uni-navbar__placeholder-view" :style="{ height:navbarHeight}" />
+ </view>
+ <!-- #endif -->
+ </view>
+</template>
+
+<script>
+ import statusBar from "./uni-status-bar.vue";
+ const getVal = (val) => typeof val === 'number' ? val + 'px' : val;
+
+ /**
+ *
+ *
+ * NavBar 鑷畾涔夊鑸爮
+ * @description 瀵艰埅鏍忕粍浠讹紝涓昏鐢ㄤ簬澶撮儴瀵艰埅
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=52
+ * @property {Boolean} dark 寮�鍚粦鏆楁ā寮�
+ * @property {String} title 鏍囬鏂囧瓧
+ * @property {String} leftText 宸︿晶鎸夐挳鏂囨湰
+ * @property {String} rightText 鍙充晶鎸夐挳鏂囨湰
+ * @property {String} leftIcon 宸︿晶鎸夐挳鍥炬爣锛堝浘鏍囩被鍨嬪弬鑰� [Icon 鍥炬爣](http://ext.dcloud.net.cn/plugin?id=28) type 灞炴�э級
+ * @property {String} rightIcon 鍙充晶鎸夐挳鍥炬爣锛堝浘鏍囩被鍨嬪弬鑰� [Icon 鍥炬爣](http://ext.dcloud.net.cn/plugin?id=28) type 灞炴�э級
+ * @property {String} color 鍥炬爣鍜屾枃瀛楅鑹�
+ * @property {String} backgroundColor 瀵艰埅鏍忚儗鏅鑹�
+ * @property {Boolean} fixed = [true|false] 鏄惁鍥哄畾椤堕儴
+ * @property {Boolean} statusBar = [true|false] 鏄惁鍖呭惈鐘舵�佹爮
+ * @property {Boolean} shadow = [true|false] 瀵艰埅鏍忎笅鏄惁鏈夐槾褰�
+ * @property {Boolean} stat 鏄惁寮�鍚粺璁℃爣棰樹笂鎶�
+ * @event {Function} clickLeft 宸︿晶鎸夐挳鐐瑰嚮鏃惰Е鍙�
+ * @event {Function} clickRight 鍙充晶鎸夐挳鐐瑰嚮鏃惰Е鍙�
+ * @event {Function} clickTitle 涓棿鏍囬鐐瑰嚮鏃惰Е鍙�
+ */
+ export default {
+ name: "UniNavBar",
+ components: {
+ statusBar
+ },
+ emits: ['clickLeft', 'clickRight', 'clickTitle'],
+ props: {
+ dark: {
+ type: Boolean,
+ default: false
+ },
+ title: {
+ type: String,
+ default: ""
+ },
+ leftText: {
+ type: String,
+ default: ""
+ },
+ rightText: {
+ type: String,
+ default: ""
+ },
+ leftIcon: {
+ type: String,
+ default: ""
+ },
+ rightIcon: {
+ type: String,
+ default: ""
+ },
+ fixed: {
+ type: [Boolean, String],
+ default: false
+ },
+ color: {
+ type: String,
+ default: ""
+ },
+ backgroundColor: {
+ type: String,
+ default: ""
+ },
+ statusBar: {
+ type: [Boolean, String],
+ default: false
+ },
+ shadow: {
+ type: [Boolean, String],
+ default: false
+ },
+ border: {
+ type: [Boolean, String],
+ default: true
+ },
+ height: {
+ type: [Number, String],
+ default: 44
+ },
+ leftWidth: {
+ type: [Number, String],
+ default: 60
+ },
+ rightWidth: {
+ type: [Number, String],
+ default: 60
+ },
+ stat: {
+ type: [Boolean, String],
+ default: ''
+ }
+ },
+ computed: {
+ themeBgColor() {
+ if (this.dark) {
+ // 榛樿鍊�
+ if (this.backgroundColor) {
+ return this.backgroundColor
+ } else {
+ return this.dark ? '#333' : '#FFF'
+ }
+ }
+ return this.backgroundColor || '#FFF'
+ },
+ themeColor() {
+ if (this.dark) {
+ // 榛樿鍊�
+ if (this.color) {
+ return this.color
+ } else {
+ return this.dark ? '#fff' : '#333'
+ }
+ }
+ return this.color || '#333'
+ },
+ navbarHeight() {
+ return getVal(this.height)
+ },
+ leftIconWidth() {
+ return getVal(this.leftWidth)
+ },
+ rightIconWidth() {
+ return getVal(this.rightWidth)
+ }
+ },
+ mounted() {
+ if (uni.report && this.stat && this.title !== '') {
+ uni.report('title', this.title)
+ }
+ },
+ methods: {
+ onClickLeft() {
+ this.$emit("clickLeft");
+ },
+ onClickRight() {
+ this.$emit("clickRight");
+ },
+ onClickTitle() {
+ this.$emit("clickTitle");
+ }
+ }
+ };
+</script>
+
+<style lang="scss" scoped>
+ $nav-height: 44px;
+
+ .uni-nvue-fixed {
+ /* #ifdef APP-NVUE */
+ position: sticky;
+ /* #endif */
+ }
+ .uni-navbar {
+ // box-sizing: border-box;
+ }
+
+ .uni-nav-bar-text {
+ /* #ifdef APP-PLUS */
+ font-size: 34rpx;
+ /* #endif */
+ /* #ifndef APP-PLUS */
+ font-size: 14px;
+ /* #endif */
+ }
+
+ .uni-nav-bar-right-text {
+ font-size: 12px;
+ }
+
+ .uni-navbar__content {
+ position: relative;
+ // background-color: #fff;
+ // box-sizing: border-box;
+ background-color: transparent;
+ }
+
+ .uni-navbar__content_view {
+ // box-sizing: border-box;
+ }
+
+ .uni-navbar-btn-text {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: column;
+ justify-content: flex-start;
+ align-items: center;
+ line-height: 12px;
+ }
+
+ .uni-navbar__header {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ padding: 0 10px;
+ flex-direction: row;
+ height: $nav-height;
+ font-size: 12px;
+ }
+
+ .uni-navbar__header-btns {
+ /* #ifndef APP-NVUE */
+ overflow: hidden;
+ display: flex;
+ /* #endif */
+ flex-wrap: nowrap;
+ flex-direction: row;
+ width: 120rpx;
+ // padding: 0 6px;
+ justify-content: center;
+ align-items: center;
+ /* #ifdef H5 */
+ cursor: pointer;
+ /* #endif */
+ }
+
+ .uni-navbar__header-btns-left {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ width: 120rpx;
+ justify-content: flex-start;
+ align-items: center;
+ }
+
+ .uni-navbar__header-btns-right {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ // width: 150rpx;
+ // padding-right: 30rpx;
+ justify-content: flex-end;
+ align-items: center;
+ }
+
+ .uni-navbar__header-container {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex: 1;
+ padding: 0 10px;
+ overflow: hidden;
+ }
+
+ .uni-navbar__header-container-inner {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex: 1;
+ flex-direction: row;
+ align-items: center;
+ justify-content: center;
+ font-size: 12px;
+ overflow: hidden;
+ // box-sizing: border-box;
+ }
+
+
+ .uni-navbar__placeholder-view {
+ height: $nav-height;
+ }
+
+ .uni-navbar--fixed {
+ position: fixed;
+ z-index: 998;
+ /* #ifdef H5 */
+ left: var(--window-left);
+ right: var(--window-right);
+ /* #endif */
+ /* #ifndef H5 */
+ left: 0;
+ right: 0;
+ /* #endif */
+
+ }
+
+ .uni-navbar--shadow {
+ box-shadow: 0 1px 6px #ccc;
+ }
+
+ .uni-navbar--border {
+ border-bottom-width: 1rpx;
+ border-bottom-style: solid;
+ border-bottom-color: #eee;
+ }
+
+ .uni-ellipsis-1 {
+ overflow: hidden;
+ /* #ifndef APP-NVUE */
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ /* #endif */
+ /* #ifdef APP-NVUE */
+ lines: 1;
+ text-overflow: ellipsis;
+ /* #endif */
+ }
+
+ // 鏆椾富棰橀厤缃�
+ .uni-dark {}
+</style>
diff --git a/app/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-status-bar.vue b/app/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-status-bar.vue
new file mode 100644
index 0000000..4ac73ae
--- /dev/null
+++ b/app/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-status-bar.vue
@@ -0,0 +1,24 @@
+<template>
+ <view :style="{ height: statusBarHeight }" class="uni-status-bar">
+ <slot />
+ </view>
+</template>
+
+<script>
+ export default {
+ name: 'UniStatusBar',
+ data() {
+ return {
+ statusBarHeight: uni.getSystemInfoSync().statusBarHeight + 'px'
+ }
+ }
+ }
+</script>
+
+<style lang="scss" >
+ .uni-status-bar {
+ // width: 750rpx;
+ height: 20px;
+ // height: var(--status-bar-height);
+ }
+</style>
diff --git a/app/uni_modules/uni-nav-bar/package.json b/app/uni_modules/uni-nav-bar/package.json
new file mode 100644
index 0000000..240ae95
--- /dev/null
+++ b/app/uni_modules/uni-nav-bar/package.json
@@ -0,0 +1,86 @@
+{
+ "id": "uni-nav-bar",
+ "displayName": "uni-nav-bar 鑷畾涔夊鑸爮",
+ "version": "1.3.11",
+ "description": "鑷畾涔夊鑸爮缁勪欢锛屼富瑕佺敤浜庡ご閮ㄥ鑸��",
+ "keywords": [
+ "uni-ui",
+ "瀵艰埅",
+ "瀵艰埅鏍�",
+ "鑷畾涔夊鑸爮"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+"dcloudext": {
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+ "type": "component-vue"
+ },
+ "uni_modules": {
+ "dependencies": [
+ "uni-scss",
+ "uni-icons"
+ ],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "u",
+ "鑱旂洘": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/uni_modules/uni-nav-bar/readme.md b/app/uni_modules/uni-nav-bar/readme.md
new file mode 100644
index 0000000..3934b32
--- /dev/null
+++ b/app/uni_modules/uni-nav-bar/readme.md
@@ -0,0 +1,15 @@
+
+
+## NavBar 瀵艰埅鏍�
+> **缁勪欢鍚嶏細uni-nav-bar**
+> 浠g爜鍧楋細 `uNavBar`
+
+瀵艰埅鏍忕粍浠讹紝涓昏鐢ㄤ簬澶撮儴瀵艰埅銆�
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-nav-bar)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
+
+
+
+
+
diff --git a/app/uni_modules/uni-notice-bar/changelog.md b/app/uni_modules/uni-notice-bar/changelog.md
new file mode 100644
index 0000000..d526811
--- /dev/null
+++ b/app/uni_modules/uni-notice-bar/changelog.md
@@ -0,0 +1,18 @@
+## 1.2.1锛�2022-09-05锛�
+- 鏂板 灞炴�� fontSize锛屽彲淇敼鏂囧瓧澶у皬銆�
+## 1.2.0锛�2021-11-19锛�
+- 浼樺寲 缁勪欢UI锛屽苟鎻愪緵璁捐璧勬簮锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 鏂囨。杩佺Щ锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/uni-notice-bar](https://uniapp.dcloud.io/component/uniui/uni-notice-bar)
+## 1.1.1锛�2021-11-09锛�
+- 鏂板 鎻愪緵缁勪欢璁捐璧勬簮锛岀粍浠舵牱寮忚皟鏁�
+## 1.1.0锛�2021-07-30锛�
+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤簐ue3椤圭洰锛岃瑙� [uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+## 1.0.9锛�2021-05-12锛�
+- 鏂板 缁勪欢绀轰緥鍦板潃
+## 1.0.8锛�2021-04-21锛�
+- 浼樺寲 娣诲姞渚濊禆 uni-icons, 瀵煎叆鍚庤嚜鍔ㄤ笅杞戒緷璧�
+## 1.0.7锛�2021-02-05锛�
+- 浼樺寲 缁勪欢寮曠敤鍏崇郴锛岄�氳繃uni_modules寮曠敤缁勪欢
+
+## 1.0.6锛�2021-02-05锛�
+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
diff --git a/app/uni_modules/uni-notice-bar/components/uni-notice-bar/uni-notice-bar.vue b/app/uni_modules/uni-notice-bar/components/uni-notice-bar/uni-notice-bar.vue
new file mode 100644
index 0000000..98d4720
--- /dev/null
+++ b/app/uni_modules/uni-notice-bar/components/uni-notice-bar/uni-notice-bar.vue
@@ -0,0 +1,426 @@
+<template>
+ <view v-if="show" class="uni-noticebar" :style="{ backgroundColor }" @click="onClick">
+ <uni-icons v-if="showIcon === true || showIcon === 'true'" class="uni-noticebar-icon" type="sound"
+ :color="color" :size="fontSize * 1.5" />
+ <view ref="textBox" class="uni-noticebar__content-wrapper"
+ :class="{
+ 'uni-noticebar__content-wrapper--scrollable': scrollable,
+ 'uni-noticebar__content-wrapper--single': !scrollable && (single || moreText)
+ }"
+ :style="{ height: scrollable ? fontSize * 1.5 + 'px' : 'auto' }"
+ >
+ <view :id="elIdBox" class="uni-noticebar__content"
+ :class="{
+ 'uni-noticebar__content--scrollable': scrollable,
+ 'uni-noticebar__content--single': !scrollable && (single || moreText)
+ }"
+ >
+ <text :id="elId" ref="animationEle" class="uni-noticebar__content-text"
+ :class="{
+ 'uni-noticebar__content-text--scrollable': scrollable,
+ 'uni-noticebar__content-text--single': !scrollable && (single || showGetMore)
+ }"
+ :style="{
+ color: color,
+ fontSize: fontSize + 'px',
+ lineHeight: fontSize * 1.5 + 'px',
+ width: wrapWidth + 'px',
+ 'animationDuration': animationDuration,
+ '-webkit-animationDuration': animationDuration,
+ animationPlayState: webviewHide ? 'paused' : animationPlayState,
+ '-webkit-animationPlayState': webviewHide ? 'paused' : animationPlayState,
+ animationDelay: animationDelay,
+ '-webkit-animationDelay': animationDelay
+ }"
+ >{{text}}</text>
+ </view>
+ </view>
+ <view v-if="isShowGetMore" class="uni-noticebar__more uni-cursor-point"
+ @click="clickMore">
+ <text v-if="moreText.length > 0" :style="{ color: moreColor, fontSize: fontSize + 'px' }">{{ moreText }}</text>
+ <uni-icons v-else type="right" :color="moreColor" :size="fontSize * 1.1" />
+ </view>
+ <view class="uni-noticebar-close uni-cursor-point" v-if="isShowClose">
+ <uni-icons type="closeempty" :color="color" :size="fontSize * 1.1" @click="close" />
+ </view>
+ </view>
+</template>
+
+<script>
+ // #ifdef APP-NVUE
+ const dom = weex.requireModule('dom');
+ const animation = weex.requireModule('animation');
+ // #endif
+
+ /**
+ * NoticeBar 鑷畾涔夊鑸爮
+ * @description 閫氬憡鏍忕粍浠�
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=30
+ * @property {Number} speed 鏂囧瓧婊氬姩鐨勯�熷害锛岄粯璁�100px/绉�
+ * @property {String} text 鏄剧ず鏂囧瓧
+ * @property {String} backgroundColor 鑳屾櫙棰滆壊
+ * @property {String} color 鏂囧瓧棰滆壊
+ * @property {String} moreColor 鏌ョ湅鏇村鏂囧瓧鐨勯鑹�
+ * @property {String} moreText 璁剧疆鈥滄煡鐪嬫洿澶氣�濈殑鏂囨湰
+ * @property {Boolean} single = [true|false] 鏄惁鍗曡
+ * @property {Boolean} scrollable = [true|false] 鏄惁婊氬姩锛屼负true鏃讹紝NoticeBar涓哄崟琛�
+ * @property {Boolean} showIcon = [true|false] 鏄惁鏄剧ず宸︿晶鍠囧彮鍥炬爣
+ * @property {Boolean} showClose = [true|false] 鏄惁鏄剧ず宸︿晶鍏抽棴鎸夐挳
+ * @property {Boolean} showGetMore = [true|false] 鏄惁鏄剧ず鍙充晶鏌ョ湅鏇村鍥炬爣锛屼负true鏃讹紝NoticeBar涓哄崟琛�
+ * @event {Function} click 鐐瑰嚮 NoticeBar 瑙﹀彂浜嬩欢
+ * @event {Function} close 鍏抽棴 NoticeBar 瑙﹀彂浜嬩欢
+ * @event {Function} getmore 鐐瑰嚮鈥濇煡鐪嬫洿澶氣�滄椂瑙﹀彂浜嬩欢
+ */
+
+ export default {
+ name: 'UniNoticeBar',
+ emits: ['click', 'getmore', 'close'],
+ props: {
+ text: {
+ type: String,
+ default: ''
+ },
+ moreText: {
+ type: String,
+ default: ''
+ },
+ backgroundColor: {
+ type: String,
+ default: '#FFF9EA'
+ },
+ speed: {
+ // 榛樿1s婊氬姩100px
+ type: Number,
+ default: 100
+ },
+ color: {
+ type: String,
+ default: '#FF9A43'
+ },
+ fontSize: {
+ type: Number,
+ default: 14
+ },
+ moreColor: {
+ type: String,
+ default: '#FF9A43'
+ },
+ single: {
+ // 鏄惁鍗曡
+ type: [Boolean, String],
+ default: false
+ },
+ scrollable: {
+ // 鏄惁婊氬姩锛屾坊鍔犲悗鎺у埗鍗曡鏁堟灉鍙栨秷
+ type: [Boolean, String],
+ default: false
+ },
+ showIcon: {
+ // 鏄惁鏄剧ず宸︿晶icon
+ type: [Boolean, String],
+ default: false
+ },
+ showGetMore: {
+ // 鏄惁鏄剧ず鍙充晶鏌ョ湅鏇村
+ type: [Boolean, String],
+ default: false
+ },
+ showClose: {
+ // 鏄惁鏄剧ず宸︿晶鍏抽棴鎸夐挳
+ type: [Boolean, String],
+ default: false
+ }
+ },
+ data() {
+ const elId = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`
+ const elIdBox = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`
+ return {
+ textWidth: 0,
+ boxWidth: 0,
+ wrapWidth: '',
+ webviewHide: false,
+ // #ifdef APP-NVUE
+ stopAnimation: false,
+ // #endif
+ elId: elId,
+ elIdBox: elIdBox,
+ show: true,
+ animationDuration: 'none',
+ animationPlayState: 'paused',
+ animationDelay: '0s'
+ }
+ },
+ computed: {
+ isShowGetMore() {
+ return this.showGetMore === true || this.showGetMore === 'true'
+ },
+ isShowClose() {
+ return (this.showClose === true || this.showClose === 'true')
+ && (this.showGetMore === false || this.showGetMore === 'false')
+ }
+ },
+ mounted() {
+ // #ifdef APP-PLUS
+ var pages = getCurrentPages();
+ var page = pages[pages.length - 1];
+ var currentWebview = page.$getAppWebview();
+ currentWebview.addEventListener('hide', () => {
+ this.webviewHide = true
+ })
+ currentWebview.addEventListener('show', () => {
+ this.webviewHide = false
+ })
+ // #endif
+ this.$nextTick(() => {
+ this.initSize()
+ })
+ },
+ // #ifdef APP-NVUE
+ beforeDestroy() {
+ this.stopAnimation = true
+ },
+ // #endif
+ methods: {
+ initSize() {
+ if (this.scrollable) {
+ // #ifndef APP-NVUE
+ let query = [],
+ boxWidth = 0,
+ textWidth = 0;
+ let textQuery = new Promise((resolve, reject) => {
+ uni.createSelectorQuery()
+ // #ifndef MP-ALIPAY
+ .in(this)
+ // #endif
+ .select(`#${this.elId}`)
+ .boundingClientRect()
+ .exec(ret => {
+ this.textWidth = ret[0].width
+ resolve()
+ })
+ })
+ let boxQuery = new Promise((resolve, reject) => {
+ uni.createSelectorQuery()
+ // #ifndef MP-ALIPAY
+ .in(this)
+ // #endif
+ .select(`#${this.elIdBox}`)
+ .boundingClientRect()
+ .exec(ret => {
+ this.boxWidth = ret[0].width
+ resolve()
+ })
+ })
+ query.push(textQuery)
+ query.push(boxQuery)
+ Promise.all(query).then(() => {
+ this.animationDuration = `${this.textWidth / this.speed}s`
+ this.animationDelay = `-${this.boxWidth / this.speed}s`
+ setTimeout(() => {
+ this.animationPlayState = 'running'
+ }, 1000)
+ })
+ // #endif
+ // #ifdef APP-NVUE
+ dom.getComponentRect(this.$refs['animationEle'], (res) => {
+ let winWidth = uni.getSystemInfoSync().windowWidth
+ this.textWidth = res.size.width
+ animation.transition(this.$refs['animationEle'], {
+ styles: {
+ transform: `translateX(-${winWidth}px)`
+ },
+ duration: 0,
+ timingFunction: 'linear',
+ delay: 0
+ }, () => {
+ if (!this.stopAnimation) {
+ animation.transition(this.$refs['animationEle'], {
+ styles: {
+ transform: `translateX(-${this.textWidth}px)`
+ },
+ timingFunction: 'linear',
+ duration: (this.textWidth - winWidth) / this.speed * 1000,
+ delay: 1000
+ }, () => {
+ if (!this.stopAnimation) {
+ this.loopAnimation()
+ }
+ });
+ }
+ });
+ })
+ // #endif
+ }
+ // #ifdef APP-NVUE
+ if (!this.scrollable && (this.single || this.moreText)) {
+ dom.getComponentRect(this.$refs['textBox'], (res) => {
+ this.wrapWidth = res.size.width
+ })
+ }
+ // #endif
+ },
+ loopAnimation() {
+ // #ifdef APP-NVUE
+ animation.transition(this.$refs['animationEle'], {
+ styles: {
+ transform: `translateX(0px)`
+ },
+ duration: 0
+ }, () => {
+ if (!this.stopAnimation) {
+ animation.transition(this.$refs['animationEle'], {
+ styles: {
+ transform: `translateX(-${this.textWidth}px)`
+ },
+ duration: this.textWidth / this.speed * 1000,
+ timingFunction: 'linear',
+ delay: 0
+ }, () => {
+ if (!this.stopAnimation) {
+ this.loopAnimation()
+ }
+ });
+ }
+ });
+ // #endif
+ },
+ clickMore() {
+ this.$emit('getmore')
+ },
+ close() {
+ this.show = false;
+ this.$emit('close')
+ },
+ onClick() {
+ this.$emit('click')
+ }
+ }
+ }
+</script>
+
+<style lang="scss" scoped>
+ .uni-noticebar {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ width: 100%;
+ box-sizing: border-box;
+ /* #endif */
+ flex-direction: row;
+ align-items: center;
+ padding: 10px 12px;
+ margin-bottom: 10px;
+ }
+
+ .uni-cursor-point {
+ /* #ifdef H5 */
+ cursor: pointer;
+ /* #endif */
+ }
+
+ .uni-noticebar-close {
+ margin-left: 8px;
+ margin-right: 5px;
+ }
+
+ .uni-noticebar-icon {
+ margin-right: 5px;
+ }
+
+ .uni-noticebar__content-wrapper {
+ flex: 1;
+ flex-direction: column;
+ overflow: hidden;
+ }
+
+ .uni-noticebar__content-wrapper--single {
+ /* #ifndef APP-NVUE */
+ line-height: 18px;
+ /* #endif */
+ }
+
+ .uni-noticebar__content-wrapper--single,
+ .uni-noticebar__content-wrapper--scrollable {
+ flex-direction: row;
+ }
+
+ /* #ifndef APP-NVUE */
+ .uni-noticebar__content-wrapper--scrollable {
+ position: relative;
+ }
+
+ /* #endif */
+
+ .uni-noticebar__content--scrollable {
+ /* #ifdef APP-NVUE */
+ flex: 0;
+ /* #endif */
+ /* #ifndef APP-NVUE */
+ flex: 1;
+ display: block;
+ overflow: hidden;
+ /* #endif */
+ }
+
+ .uni-noticebar__content--single {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ flex: none;
+ width: 100%;
+ justify-content: center;
+ /* #endif */
+ }
+
+ .uni-noticebar__content-text {
+ font-size: 14px;
+ line-height: 18px;
+ /* #ifndef APP-NVUE */
+ word-break: break-all;
+ /* #endif */
+ }
+
+ .uni-noticebar__content-text--single {
+ /* #ifdef APP-NVUE */
+ lines: 1;
+ /* #endif */
+ /* #ifndef APP-NVUE */
+ display: block;
+ width: 100%;
+ white-space: nowrap;
+ /* #endif */
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+
+ .uni-noticebar__content-text--scrollable {
+ /* #ifdef APP-NVUE */
+ lines: 1;
+ padding-left: 750rpx;
+ /* #endif */
+ /* #ifndef APP-NVUE */
+ position: absolute;
+ display: block;
+ height: 18px;
+ line-height: 18px;
+ white-space: nowrap;
+ padding-left: 100%;
+ animation: notice 10s 0s linear infinite both;
+ animation-play-state: paused;
+ /* #endif */
+ }
+
+ .uni-noticebar__more {
+ /* #ifndef APP-NVUE */
+ display: inline-flex;
+ /* #endif */
+ flex-direction: row;
+ flex-wrap: nowrap;
+ align-items: center;
+ padding-left: 5px;
+ }
+
+ @keyframes notice {
+ 100% {
+ transform: translate3d(-100%, 0, 0);
+ }
+ }
+</style>
diff --git a/app/uni_modules/uni-notice-bar/package.json b/app/uni_modules/uni-notice-bar/package.json
new file mode 100644
index 0000000..8d9b13c
--- /dev/null
+++ b/app/uni_modules/uni-notice-bar/package.json
@@ -0,0 +1,87 @@
+{
+ "id": "uni-notice-bar",
+ "displayName": "uni-notice-bar 閫氬憡鏍�",
+ "version": "1.2.1",
+ "description": "NoticeBar 閫氬憡鏍忕粍浠讹紝甯哥敤浜庡睍绀哄叕鍛婁俊鎭紝鍙涓烘粴鍔ㄥ叕鍛�",
+ "keywords": [
+ "uni-ui",
+ "uniui",
+ "閫氬憡鏍�",
+ "鍏憡",
+ "璺戦┈鐏�"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+"dcloudext": {
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+ "type": "component-vue"
+ },
+ "uni_modules": {
+ "dependencies": [
+ "uni-scss",
+ "uni-icons"
+ ],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "u",
+ "鑱旂洘": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
diff --git a/app/uni_modules/uni-notice-bar/readme.md b/app/uni_modules/uni-notice-bar/readme.md
new file mode 100644
index 0000000..fb2ede2
--- /dev/null
+++ b/app/uni_modules/uni-notice-bar/readme.md
@@ -0,0 +1,13 @@
+
+
+## NoticeBar 閫氬憡鏍�
+> **缁勪欢鍚嶏細uni-notice-bar**
+> 浠g爜鍧楋細 `uNoticeBar`
+
+
+閫氬憡鏍忕粍浠� 銆�
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-notice-bar)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
+
+
diff --git a/app/uni_modules/uni-number-box/changelog.md b/app/uni_modules/uni-number-box/changelog.md
new file mode 100644
index 0000000..5925c32
--- /dev/null
+++ b/app/uni_modules/uni-number-box/changelog.md
@@ -0,0 +1,25 @@
+## 1.2.1锛�2021-11-22锛�
+- 淇 vue3涓煇浜泂css鍙橀噺鏃犳硶鎵惧埌鐨勯棶棰�
+## 1.2.0锛�2021-11-19锛�
+- 浼樺寲 缁勪欢UI锛屽苟鎻愪緵璁捐璧勬簮锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 鏂囨。杩佺Щ锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/uni-number-box](https://uniapp.dcloud.io/component/uniui/uni-number-box)
+## 1.1.2锛�2021-11-09锛�
+- 鏂板 鎻愪緵缁勪欢璁捐璧勬簮锛岀粍浠舵牱寮忚皟鏁�
+## 1.1.1锛�2021-07-30锛�
+- 浼樺寲 vue3涓嬩簨浠惰鍛婄殑闂
+## 1.1.0锛�2021-07-13锛�
+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤簐ue3椤圭洰锛岃瑙� [uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+## 1.0.7锛�2021-05-12锛�
+- 鏂板 缁勪欢绀轰緥鍦板潃
+## 1.0.6锛�2021-04-20锛�
+- 淇 uni-number-box 娴偣鏁拌繍绠椾笉绮剧‘鐨� bug
+- 淇 uni-number-box change 浜嬩欢瑙﹀彂涓嶆纭殑 bug
+- 鏂板 uni-number-box v-model 鍙屽悜缁戝畾
+## 1.0.5锛�2021-02-05锛�
+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
+
+## 1.0.7锛�2021-02-05锛�
+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
+- 鏂板 鏀寔 v-model
+- 鏂板 鏀寔 focus銆乥lur 浜嬩欢
+- 鏂板 鏀寔 PC 绔�
diff --git a/app/uni_modules/uni-number-box/components/uni-number-box/uni-number-box.vue b/app/uni_modules/uni-number-box/components/uni-number-box/uni-number-box.vue
new file mode 100644
index 0000000..e91c032
--- /dev/null
+++ b/app/uni_modules/uni-number-box/components/uni-number-box/uni-number-box.vue
@@ -0,0 +1,221 @@
+<template>
+ <view class="uni-numbox">
+ <view @click="_calcValue('minus')" class="uni-numbox__minus uni-numbox-btns" :style="{background}">
+ <text class="uni-numbox--text" :class="{ 'uni-numbox--disabled': inputValue <= min || disabled }" :style="{color}">-</text>
+ </view>
+ <input :disabled="disabled" @focus="_onFocus" @blur="_onBlur" class="uni-numbox__value" type="number"
+ v-model="inputValue" :style="{background, color}" />
+ <view @click="_calcValue('plus')" class="uni-numbox__plus uni-numbox-btns" :style="{background}">
+ <text class="uni-numbox--text" :class="{ 'uni-numbox--disabled': inputValue >= max || disabled }" :style="{color}">+</text>
+ </view>
+ </view>
+</template>
+<script>
+ /**
+ * NumberBox 鏁板瓧杈撳叆妗�
+ * @description 甯﹀姞鍑忔寜閽殑鏁板瓧杈撳叆妗�
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=31
+ * @property {Number} value 杈撳叆妗嗗綋鍓嶅��
+ * @property {Number} min 鏈�灏忓��
+ * @property {Number} max 鏈�澶у��
+ * @property {Number} step 姣忔鐐瑰嚮鏀瑰彉鐨勯棿闅斿ぇ灏�
+ * @property {String} background 鑳屾櫙鑹�
+ * @property {String} color 瀛椾綋棰滆壊锛堝墠鏅壊锛�
+ * @property {Boolean} disabled = [true|false] 鏄惁涓虹鐢ㄧ姸鎬�
+ * @event {Function} change 杈撳叆妗嗗�兼敼鍙樻椂瑙﹀彂鐨勪簨浠讹紝鍙傛暟涓鸿緭鍏ユ褰撳墠鐨� value
+ * @event {Function} focus 杈撳叆妗嗚仛鐒︽椂瑙﹀彂鐨勪簨浠讹紝鍙傛暟涓� event 瀵硅薄
+ * @event {Function} blur 杈撳叆妗嗗け鐒︽椂瑙﹀彂鐨勪簨浠讹紝鍙傛暟涓� event 瀵硅薄
+ */
+
+ export default {
+ name: "UniNumberBox",
+ emits: ['change', 'input', 'update:modelValue', 'blur', 'focus'],
+ props: {
+ value: {
+ type: [Number, String],
+ default: 1
+ },
+ modelValue: {
+ type: [Number, String],
+ default: 1
+ },
+ min: {
+ type: Number,
+ default: 0
+ },
+ max: {
+ type: Number,
+ default: 100
+ },
+ step: {
+ type: Number,
+ default: 1
+ },
+ background: {
+ type: String,
+ default: '#f5f5f5'
+ },
+ color: {
+ type: String,
+ default: '#333'
+ },
+ disabled: {
+ type: Boolean,
+ default: false
+ }
+ },
+ data() {
+ return {
+ inputValue: 0
+ };
+ },
+ watch: {
+ value(val) {
+ this.inputValue = +val;
+ },
+ modelValue(val) {
+ this.inputValue = +val;
+ }
+ },
+ created() {
+ if (this.value === 1) {
+ this.inputValue = +this.modelValue;
+ }
+ if (this.modelValue === 1) {
+ this.inputValue = +this.value;
+ }
+ },
+ methods: {
+ _calcValue(type) {
+ if (this.disabled) {
+ return;
+ }
+ const scale = this._getDecimalScale();
+ let value = this.inputValue * scale;
+ let step = this.step * scale;
+ if (type === "minus") {
+ value -= step;
+ if (value < (this.min * scale)) {
+ return;
+ }
+ if (value > (this.max * scale)) {
+ value = this.max * scale
+ }
+ }
+
+ if (type === "plus") {
+ value += step;
+ if (value > (this.max * scale)) {
+ return;
+ }
+ if (value < (this.min * scale)) {
+ value = this.min * scale
+ }
+ }
+
+ this.inputValue = (value / scale).toFixed(String(scale).length - 1);
+ this.$emit("change", +this.inputValue);
+ // TODO vue2 鍏煎
+ this.$emit("input", +this.inputValue);
+ // TODO vue3 鍏煎
+ this.$emit("update:modelValue", +this.inputValue);
+ },
+ _getDecimalScale() {
+
+ let scale = 1;
+ // 娴偣鍨�
+ if (~~this.step !== this.step) {
+ scale = Math.pow(10, String(this.step).split(".")[1].length);
+ }
+ return scale;
+ },
+ _onBlur(event) {
+ this.$emit('blur', event)
+ let value = event.detail.value;
+ if (isNaN(value)) {
+ this.inputValue = this.min;
+ return;
+ }
+ value = +value;
+ if (value > this.max) {
+ value = this.max;
+ } else if (value < this.min) {
+ value = this.min;
+ }
+ const scale = this._getDecimalScale();
+ this.inputValue = value.toFixed(String(scale).length - 1);
+ this.$emit("change", +this.inputValue);
+ this.$emit("input", +this.inputValue);
+ this.$emit("update:modelValue", +this.inputValue);
+ },
+ _onFocus(event) {
+ this.$emit('focus', event)
+ }
+ }
+ };
+</script>
+<style lang="scss" >
+ $box-height: 26px;
+ $bg: #f5f5f5;
+ $br: 2px;
+ $color: #333;
+
+ .uni-numbox {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ }
+
+ .uni-numbox-btns {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ align-items: center;
+ justify-content: center;
+ padding: 0 8px;
+ background-color: $bg;
+ /* #ifdef H5 */
+ cursor: pointer;
+ /* #endif */
+ }
+
+ .uni-numbox__value {
+ margin: 0 2px;
+ background-color: $bg;
+ width: 40px;
+ height: $box-height;
+ text-align: center;
+ font-size: 14px;
+ border-left-width: 0;
+ border-right-width: 0;
+ color: $color;
+ }
+
+ .uni-numbox__minus {
+ border-top-left-radius: $br;
+ border-bottom-left-radius: $br;
+ }
+
+ .uni-numbox__plus {
+ border-top-right-radius: $br;
+ border-bottom-right-radius: $br;
+ }
+
+ .uni-numbox--text {
+ // fix nvue
+ line-height: 20px;
+
+ font-size: 20px;
+ font-weight: 300;
+ color: $color;
+ }
+
+ .uni-numbox .uni-numbox--disabled {
+ color: #c0c0c0 !important;
+ /* #ifdef H5 */
+ cursor: not-allowed;
+ /* #endif */
+ }
+</style>
diff --git a/app/uni_modules/uni-number-box/package.json b/app/uni_modules/uni-number-box/package.json
new file mode 100644
index 0000000..ad82336
--- /dev/null
+++ b/app/uni_modules/uni-number-box/package.json
@@ -0,0 +1,85 @@
+{
+ "id": "uni-number-box",
+ "displayName": "uni-number-box 鏁板瓧杈撳叆妗�",
+ "version": "1.2.1",
+ "description": "NumberBox 甯﹀姞鍑忔寜閽殑鏁板瓧杈撳叆妗嗙粍浠讹紝鐢ㄦ埛鍙互鎺у埗姣忔鐐瑰嚮澧炲姞鐨勬暟鍊硷紝鏀寔灏忔暟銆�",
+ "keywords": [
+ "uni-ui",
+ "uniui",
+ "鏁板瓧杈撳叆妗�"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "鍓嶇缁勪欢",
+ "閫氱敤缁勪欢"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": ["uni-scss"],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "u",
+ "鑱旂洘": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/uni_modules/uni-number-box/readme.md b/app/uni_modules/uni-number-box/readme.md
new file mode 100644
index 0000000..affc56f
--- /dev/null
+++ b/app/uni_modules/uni-number-box/readme.md
@@ -0,0 +1,13 @@
+
+
+## NumberBox 鏁板瓧杈撳叆妗�
+> **缁勪欢鍚嶏細uni-number-box**
+> 浠g爜鍧楋細 `uNumberBox`
+
+
+甯﹀姞鍑忔寜閽殑鏁板瓧杈撳叆妗嗐��
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-number-box)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
+
+
diff --git a/app/uni_modules/uni-pagination/changelog.md b/app/uni_modules/uni-pagination/changelog.md
new file mode 100644
index 0000000..2e94adc
--- /dev/null
+++ b/app/uni_modules/uni-pagination/changelog.md
@@ -0,0 +1,27 @@
+## 1.2.4锛�2022-09-19锛�
+- 淇锛屾湭瀵逛富棰樿壊璁剧疆榛樿鑹诧紝瀵艰嚧鏈紩鍏� uni-scss 鍙橀噺鏂囦欢鎶ラ敊銆�
+- 淇锛屾湭瀵圭Щ鍔ㄧ褰撳墠椤垫枃瀛楀仛涓婚鑹查�傞厤銆�
+## 1.2.3锛�2022-09-15锛�
+- 淇鏈娇鐢� uni-scss 涓婚鑹茬殑 bug銆�
+## 1.2.2锛�2022-07-06锛�
+- 淇 es 璇█ i18n 閿欒
+## 1.2.1锛�2021-11-22锛�
+- 淇 vue3涓煇浜泂css鍙橀噺鏃犳硶鎵惧埌鐨勯棶棰�
+## 1.2.0锛�2021-11-19锛�
+- 浼樺寲 缁勪欢UI锛屽苟鎻愪緵璁捐璧勬簮锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 鏂囨。杩佺Щ锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/uni-pagination](https://uniapp.dcloud.io/component/uniui/uni-pagination)
+## 1.1.2锛�2021-10-08锛�
+- 淇 current 銆乿alue 灞炴�ф湭鐩戝惉锛屽鑷撮珮浜牱寮忓け鏁堢殑 bug
+## 1.1.1锛�2021-08-20锛�
+- 鏂板 鏀寔鍥介檯鍖�
+## 1.1.0锛�2021-07-30锛�
+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤簐ue3椤圭洰锛岃瑙� [uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+## 1.0.7锛�2021-05-12锛�
+- 鏂板 缁勪欢绀轰緥鍦板潃
+## 1.0.6锛�2021-04-12锛�
+- 鏂板 PC 鍜� 绉诲姩绔�傞厤涓嶅悓鐨� ui
+## 1.0.5锛�2021-02-05锛�
+- 浼樺寲 缁勪欢寮曠敤鍏崇郴锛岄�氳繃uni_modules寮曠敤缁勪欢
+
+## 1.0.4锛�2021-02-05锛�
+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
diff --git a/app/uni_modules/uni-pagination/components/uni-pagination/i18n/en.json b/app/uni_modules/uni-pagination/components/uni-pagination/i18n/en.json
new file mode 100644
index 0000000..d6e2897
--- /dev/null
+++ b/app/uni_modules/uni-pagination/components/uni-pagination/i18n/en.json
@@ -0,0 +1,5 @@
+{
+ "uni-pagination.prevText": "prev",
+ "uni-pagination.nextText": "next",
+ "uni-pagination.piecePerPage": "piece/page"
+}
diff --git a/app/uni_modules/uni-pagination/components/uni-pagination/i18n/es.json b/app/uni_modules/uni-pagination/components/uni-pagination/i18n/es.json
new file mode 100644
index 0000000..604a113
--- /dev/null
+++ b/app/uni_modules/uni-pagination/components/uni-pagination/i18n/es.json
@@ -0,0 +1,5 @@
+{
+ "uni-pagination.prevText": "anterior",
+ "uni-pagination.nextText": "prxima",
+ "uni-pagination.piecePerPage": "Artículo/Página"
+}
diff --git a/app/uni_modules/uni-pagination/components/uni-pagination/i18n/fr.json b/app/uni_modules/uni-pagination/components/uni-pagination/i18n/fr.json
new file mode 100644
index 0000000..a7a0c77
--- /dev/null
+++ b/app/uni_modules/uni-pagination/components/uni-pagination/i18n/fr.json
@@ -0,0 +1,5 @@
+{
+ "uni-pagination.prevText": "pr茅c茅dente",
+ "uni-pagination.nextText": "suivante",
+ "uni-pagination.piecePerPage": "Articles/Pages"
+}
diff --git a/app/uni_modules/uni-pagination/components/uni-pagination/i18n/index.js b/app/uni_modules/uni-pagination/components/uni-pagination/i18n/index.js
new file mode 100644
index 0000000..2469dd0
--- /dev/null
+++ b/app/uni_modules/uni-pagination/components/uni-pagination/i18n/index.js
@@ -0,0 +1,12 @@
+import en from './en.json'
+import es from './es.json'
+import fr from './fr.json'
+import zhHans from './zh-Hans.json'
+import zhHant from './zh-Hant.json'
+export default {
+ en,
+ es,
+ fr,
+ 'zh-Hans': zhHans,
+ 'zh-Hant': zhHant
+}
diff --git a/app/uni_modules/uni-pagination/components/uni-pagination/i18n/zh-Hans.json b/app/uni_modules/uni-pagination/components/uni-pagination/i18n/zh-Hans.json
new file mode 100644
index 0000000..782bbe4
--- /dev/null
+++ b/app/uni_modules/uni-pagination/components/uni-pagination/i18n/zh-Hans.json
@@ -0,0 +1,5 @@
+{
+ "uni-pagination.prevText": "涓婁竴椤�",
+ "uni-pagination.nextText": "涓嬩竴椤�",
+ "uni-pagination.piecePerPage": "鏉�/椤�"
+}
diff --git a/app/uni_modules/uni-pagination/components/uni-pagination/i18n/zh-Hant.json b/app/uni_modules/uni-pagination/components/uni-pagination/i18n/zh-Hant.json
new file mode 100644
index 0000000..180fddb
--- /dev/null
+++ b/app/uni_modules/uni-pagination/components/uni-pagination/i18n/zh-Hant.json
@@ -0,0 +1,5 @@
+{
+ "uni-pagination.prevText": "涓婁竴闋�",
+ "uni-pagination.nextText": "涓嬩竴闋�",
+ "uni-pagination.piecePerPage": "姊�/闋�"
+}
diff --git a/app/uni_modules/uni-pagination/components/uni-pagination/uni-pagination.vue b/app/uni_modules/uni-pagination/components/uni-pagination/uni-pagination.vue
new file mode 100644
index 0000000..5305b5f
--- /dev/null
+++ b/app/uni_modules/uni-pagination/components/uni-pagination/uni-pagination.vue
@@ -0,0 +1,465 @@
+<template>
+ <view class="uni-pagination">
+ <!-- #ifndef MP -->
+ <picker v-if="showPageSize === true || showPageSize === 'true'" class="select-picker" mode="selector"
+ :value="pageSizeIndex" :range="pageSizeRange" @change="pickerChange" @cancel="pickerClick"
+ @click.native="pickerClick">
+ <button type="default" size="mini" :plain="true">
+ <text>{{pageSizeRange[pageSizeIndex]}} {{piecePerPage}}</text>
+ <uni-icons class="select-picker-icon" type="arrowdown" size="12" color="#999"></uni-icons>
+ </button>
+ </picker>
+ <!-- #endif -->
+ <!-- #ifndef APP-NVUE -->
+ <view class="uni-pagination__total is-phone-hide">鍏� {{ total }} 鏉�</view>
+ <!-- #endif -->
+ <view class="uni-pagination__btn"
+ :class="currentIndex === 1 ? 'uni-pagination--disabled' : 'uni-pagination--enabled'"
+ :hover-class="currentIndex === 1 ? '' : 'uni-pagination--hover'" :hover-start-time="20"
+ :hover-stay-time="70" @click="clickLeft">
+ <template v-if="showIcon === true || showIcon === 'true'">
+ <uni-icons color="#666" size="16" type="left" />
+ </template>
+ <template v-else>
+ <text class="uni-pagination__child-btn">{{ prevPageText }}</text>
+ </template>
+ </view>
+ <view class="uni-pagination__num uni-pagination__num-flex-none">
+ <view class="uni-pagination__num-current">
+ <text class="uni-pagination__num-current-text is-pc-hide current-index-text">{{ currentIndex }}</text>
+ <text class="uni-pagination__num-current-text is-pc-hide">/{{ maxPage || 0 }}</text>
+ <!-- #ifndef APP-NVUE -->
+ <view v-for="(item, index) in paper" :key="index" :class="{ 'page--active': item === currentIndex }"
+ class="uni-pagination__num-tag tag--active is-phone-hide" @click.top="selectPage(item, index)">
+ <text>{{ item }}</text>
+ </view>
+ <!-- #endif -->
+
+ </view>
+ </view>
+ <view class="uni-pagination__btn"
+ :class="currentIndex >= maxPage ? 'uni-pagination--disabled' : 'uni-pagination--enabled'"
+ :hover-class="currentIndex === maxPage ? '' : 'uni-pagination--hover'" :hover-start-time="20"
+ :hover-stay-time="70" @click="clickRight">
+ <template v-if="showIcon === true || showIcon === 'true'">
+ <uni-icons color="#666" size="16" type="right" />
+ </template>
+ <template v-else>
+ <text class="uni-pagination__child-btn">{{ nextPageText }}</text>
+ </template>
+ </view>
+ </view>
+</template>
+
+<script>
+ /**
+ * Pagination 鍒嗛〉鍣�
+ * @description 鍒嗛〉鍣ㄧ粍浠讹紝鐢ㄤ簬灞曠ず椤电爜銆佽姹傛暟鎹瓑
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=32
+ * @property {String} prevText 宸︿晶鎸夐挳鏂囧瓧
+ * @property {String} nextText 鍙充晶鎸夐挳鏂囧瓧
+ * @property {String} piecePerPageText 鏉�/椤垫枃瀛�
+ * @property {Number} current 褰撳墠椤�
+ * @property {Number} total 鏁版嵁鎬婚噺
+ * @property {Number} pageSize 姣忛〉鏁版嵁閲�
+ * @property {Boolean} showIcon = [true|false] 鏄惁浠� icon 褰㈠紡灞曠ず鎸夐挳
+ * @property {Boolean} showPageSize = [true|false] 鏄惁灞曠ず姣忛〉鏉℃暟
+ * @property {Array} pageSizeRange = [20, 50, 100, 500] 姣忛〉鏉℃暟閫夋
+ * @event {Function} change 鐐瑰嚮椤电爜鎸夐挳鏃惰Е鍙� ,e={type,current} current涓哄綋鍓嶉〉锛宼ype鍊间负锛歯ext/prev锛岃〃绀虹偣鍑荤殑鏄笂涓�椤佃繕鏄笅涓�涓�
+ * * @event {Function} pageSizeChange 褰撳墠姣忛〉鏉℃暟鏀瑰彉鏃惰Е鍙� ,e={pageSize} pageSize 涓哄綋鍓嶆墍閫夌殑姣忛〉鏉℃暟
+ */
+
+ import {
+ initVueI18n
+ } from '@dcloudio/uni-i18n'
+ import messages from './i18n/index.js'
+ const {
+ t
+ } = initVueI18n(messages)
+ export default {
+ name: 'UniPagination',
+ emits: ['update:modelValue', 'input', 'change', 'pageSizeChange'],
+ props: {
+ value: {
+ type: [Number, String],
+ default: 1
+ },
+ modelValue: {
+ type: [Number, String],
+ default: 1
+ },
+ prevText: {
+ type: String,
+ },
+ nextText: {
+ type: String,
+ },
+ piecePerPageText: {
+ type: String
+ },
+ current: {
+ type: [Number, String],
+ default: 1
+ },
+ total: {
+ // 鏁版嵁鎬婚噺
+ type: [Number, String],
+ default: 0
+ },
+ pageSize: {
+ // 姣忛〉鏁版嵁閲�
+ type: [Number, String],
+ default: 10
+ },
+ showIcon: {
+ // 鏄惁浠� icon 褰㈠紡灞曠ず鎸夐挳
+ type: [Boolean, String],
+ default: false
+ },
+ showPageSize: {
+ // 鏄惁浠� icon 褰㈠紡灞曠ず鎸夐挳
+ type: [Boolean, String],
+ default: false
+ },
+ pagerCount: {
+ type: Number,
+ default: 7
+ },
+ pageSizeRange: {
+ type: Array,
+ default: () => [20, 50, 100, 500]
+ }
+ },
+ data() {
+ return {
+ pageSizeIndex: 0,
+ currentIndex: 1,
+ paperData: [],
+ pickerShow: false
+ }
+ },
+ computed: {
+ piecePerPage() {
+ return this.piecePerPageText || t('uni-pagination.piecePerPage')
+ },
+ prevPageText() {
+ return this.prevText || t('uni-pagination.prevText')
+ },
+ nextPageText() {
+ return this.nextText || t('uni-pagination.nextText')
+ },
+ maxPage() {
+ let maxPage = 1
+ let total = Number(this.total)
+ let pageSize = Number(this.pageSize)
+ if (total && pageSize) {
+ maxPage = Math.ceil(total / pageSize)
+ }
+ return maxPage
+ },
+ paper() {
+ const num = this.currentIndex
+ // TODO 鏈�澶ч〉鏁�
+ const pagerCount = this.pagerCount
+ // const total = 181
+ const total = this.total
+ const pageSize = this.pageSize
+ let totalArr = []
+ let showPagerArr = []
+ let pagerNum = Math.ceil(total / pageSize)
+ for (let i = 0; i < pagerNum; i++) {
+ totalArr.push(i + 1)
+ }
+ showPagerArr.push(1)
+ const totalNum = totalArr[totalArr.length - (pagerCount + 1) / 2]
+ totalArr.forEach((item, index) => {
+ if ((pagerCount + 1) / 2 >= num) {
+ if (item < pagerCount + 1 && item > 1) {
+ showPagerArr.push(item)
+ }
+ } else if (num + 2 <= totalNum) {
+ if (item > num - (pagerCount + 1) / 2 && item < num + (pagerCount + 1) / 2) {
+ showPagerArr.push(item)
+ }
+ } else {
+ if ((item > num - (pagerCount + 1) / 2 || pagerNum - pagerCount < item) && item < totalArr[
+ totalArr.length - 1]) {
+ showPagerArr.push(item)
+ }
+ }
+ })
+ if (pagerNum > pagerCount) {
+ if ((pagerCount + 1) / 2 >= num) {
+ showPagerArr[showPagerArr.length - 1] = '...'
+ } else if (num + 2 <= totalNum) {
+ showPagerArr[1] = '...'
+ showPagerArr[showPagerArr.length - 1] = '...'
+ } else {
+ showPagerArr[1] = '...'
+ }
+ showPagerArr.push(totalArr[totalArr.length - 1])
+ } else {
+ if ((pagerCount + 1) / 2 >= num) {} else if (num + 2 <= totalNum) {} else {
+ showPagerArr.shift()
+ showPagerArr.push(totalArr[totalArr.length - 1])
+ }
+ }
+
+ return showPagerArr
+ }
+ },
+ watch: {
+ current: {
+ immediate: true,
+ handler(val, old) {
+ if (val < 1) {
+ this.currentIndex = 1
+ } else {
+ this.currentIndex = val
+ }
+ }
+ },
+ value: {
+ immediate: true,
+ handler(val) {
+ if (Number(this.current) !== 1) return
+ if (val < 1) {
+ this.currentIndex = 1
+ } else {
+ this.currentIndex = val
+ }
+ }
+ },
+ pageSizeIndex(val) {
+ this.$emit('pageSizeChange', this.pageSizeRange[val])
+ }
+ },
+ methods: {
+ pickerChange(e) {
+ this.pageSizeIndex = e.detail.value
+ this.pickerClick()
+ },
+ pickerClick() {
+ // #ifdef H5
+ const body = document.querySelector('body')
+ if (!body) return
+
+ const className = 'uni-pagination-picker-show'
+ this.pickerShow = !this.pickerShow
+
+ if (this.pickerShow) {
+ body.classList.add(className)
+ } else {
+ setTimeout(() => body.classList.remove(className), 300)
+ }
+ // #endif
+ },
+ // 閫夋嫨鏍囩
+ selectPage(e, index) {
+ if (parseInt(e)) {
+ this.currentIndex = e
+ this.change('current')
+ } else {
+ let pagerNum = Math.ceil(this.total / this.pageSize)
+ // let pagerNum = Math.ceil(181 / this.pageSize)
+ // 涓婁竴椤�
+ if (index <= 1) {
+ if (this.currentIndex - 5 > 1) {
+ this.currentIndex -= 5
+ } else {
+ this.currentIndex = 1
+ }
+ return
+ }
+ // 涓嬩竴椤�
+ if (index >= 6) {
+ if (this.currentIndex + 5 > pagerNum) {
+ this.currentIndex = pagerNum
+ } else {
+ this.currentIndex += 5
+ }
+ return
+ }
+ }
+ },
+ clickLeft() {
+ if (Number(this.currentIndex) === 1) {
+ return
+ }
+ this.currentIndex -= 1
+ this.change('prev')
+ },
+ clickRight() {
+ if (Number(this.currentIndex) >= this.maxPage) {
+ return
+ }
+ this.currentIndex += 1
+ this.change('next')
+ },
+ change(e) {
+ this.$emit('input', this.currentIndex)
+ this.$emit('update:modelValue', this.currentIndex)
+ this.$emit('change', {
+ type: e,
+ current: this.currentIndex
+ })
+ }
+ }
+ }
+</script>
+
+<style lang="scss" scoped>
+ $uni-primary: #2979ff !default;
+ .uni-pagination {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ position: relative;
+ overflow: hidden;
+ flex-direction: row;
+ justify-content: center;
+ align-items: center;
+ }
+
+ .uni-pagination__total {
+ font-size: 14px;
+ color: #999;
+ margin-right: 15px;
+ }
+
+ .uni-pagination__btn {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ cursor: pointer;
+ /* #endif */
+ padding: 0 8px;
+ line-height: 30px;
+ font-size: 12px;
+ position: relative;
+ background-color: #F0F0F0;
+ flex-direction: row;
+ justify-content: center;
+ align-items: center;
+ text-align: center;
+ border-radius: 5px;
+ // border-width: 1px;
+ // border-style: solid;
+ // border-color: $uni-border-color;
+ }
+
+ .uni-pagination__child-btn {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ font-size: 12px;
+ position: relative;
+ flex-direction: row;
+ justify-content: center;
+ align-items: center;
+ text-align: center;
+ color: #666;
+ font-size: 12px;
+ }
+
+ .uni-pagination__num {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex: 1;
+ flex-direction: row;
+ justify-content: center;
+ align-items: center;
+ height: 30px;
+ line-height: 30px;
+ font-size: 12px;
+ color: #666;
+ margin: 0 5px;
+ }
+
+ .uni-pagination__num-tag {
+ /* #ifdef H5 */
+ cursor: pointer;
+ min-width: 30px;
+ /* #endif */
+ margin: 0 5px;
+ height: 30px;
+ text-align: center;
+ line-height: 30px;
+ // border: 1px red solid;
+ color: #999;
+ border-radius: 4px;
+ // border-width: 1px;
+ // border-style: solid;
+ // border-color: $uni-border-color;
+ }
+
+ .uni-pagination__num-current {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ }
+
+ .uni-pagination__num-current-text {
+ font-size: 15px;
+ }
+
+ .current-index-text{
+ color: $uni-primary;
+ }
+
+ .uni-pagination--enabled {
+ color: #333333;
+ opacity: 1;
+ }
+
+ .uni-pagination--disabled {
+ opacity: 0.5;
+ /* #ifdef H5 */
+ cursor: default;
+ /* #endif */
+ }
+
+ .uni-pagination--hover {
+ color: rgba(0, 0, 0, 0.6);
+ background-color: #eee;
+ }
+
+ .tag--active:hover {
+ color: $uni-primary;
+ }
+
+ .page--active {
+ color: #fff;
+ background-color: $uni-primary;
+ }
+
+ .page--active:hover {
+ color: #fff;
+ }
+
+ /* #ifndef APP-NVUE */
+ .is-pc-hide {
+ display: block;
+ }
+
+ .is-phone-hide {
+ display: none;
+ }
+
+ @media screen and (min-width: 450px) {
+ .is-pc-hide {
+ display: none;
+ }
+
+ .is-phone-hide {
+ display: block;
+ }
+
+ .uni-pagination__num-flex-none {
+ flex: none;
+ }
+ }
+
+ /* #endif */
+</style>
diff --git a/app/uni_modules/uni-pagination/package.json b/app/uni_modules/uni-pagination/package.json
new file mode 100644
index 0000000..862d5ab
--- /dev/null
+++ b/app/uni_modules/uni-pagination/package.json
@@ -0,0 +1,83 @@
+{
+ "id": "uni-pagination",
+ "displayName": "uni-pagination 鍒嗛〉鍣�",
+ "version": "1.2.4",
+ "description": "Pagination 鍒嗛〉鍣ㄧ粍浠讹紝鐢ㄤ簬灞曠ず椤电爜銆佽姹傛暟鎹瓑銆�",
+ "keywords": [
+ "uni-ui",
+ "uniui",
+ "鍒嗛〉鍣�",
+ "椤电爜"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+"dcloudext": {
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+ "type": "component-vue"
+ },
+ "uni_modules": {
+ "dependencies": ["uni-scss","uni-icons"],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "u",
+ "鑱旂洘": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/uni_modules/uni-pagination/readme.md b/app/uni_modules/uni-pagination/readme.md
new file mode 100644
index 0000000..97ea1d6
--- /dev/null
+++ b/app/uni_modules/uni-pagination/readme.md
@@ -0,0 +1,11 @@
+
+
+## Pagination 鍒嗛〉鍣�
+> **缁勪欢鍚嶏細uni-pagination**
+> 浠g爜鍧楋細 `uPagination`
+
+
+鍒嗛〉鍣ㄧ粍浠讹紝鐢ㄤ簬灞曠ず椤电爜銆佽姹傛暟鎹瓑銆�
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-pagination)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
diff --git a/app/uni_modules/uni-popup/changelog.md b/app/uni_modules/uni-popup/changelog.md
new file mode 100644
index 0000000..bc59f07
--- /dev/null
+++ b/app/uni_modules/uni-popup/changelog.md
@@ -0,0 +1,68 @@
+## 1.8.3锛�2023-04-17锛�
+- 淇 uni-popup 閲嶅鎵撳紑鏃剁殑 bug
+## 1.8.2锛�2023-02-02锛�
+- uni-popup-dialog 缁勪欢鏂板 inputType 灞炴��
+## 1.8.1锛�2022-12-01锛�
+- 淇 nvue 涓� v-show 鎶ラ敊
+## 1.8.0锛�2022-11-29锛�
+- 浼樺寲 涓婚鏍峰紡
+## 1.7.9锛�2022-04-02锛�
+- 淇 寮瑰嚭灞傚唴閮ㄦ棤娉曟粴鍔ㄧ殑bug
+## 1.7.8锛�2022-03-28锛�
+- 淇 灏忕▼搴忎腑楂樺害閿欒鐨刡ug
+## 1.7.7锛�2022-03-17锛�
+- 淇 蹇�熻皟鐢╫pen鍑虹幇闂鐨凚ug
+## 1.7.6锛�2022-02-14锛�
+- 淇 safeArea 灞炴�т笉鑳借缃负false鐨刡ug
+## 1.7.5锛�2022-01-19锛�
+- 淇 isMaskClick 澶辨晥鐨刡ug
+## 1.7.4锛�2022-01-19锛�
+- 鏂板 cancelText \ confirmText 灞炴�� 锛屽彲鑷畾涔夋枃鏈�
+- 鏂板 maskBackgroundColor 灞炴�� 锛屽彲浠ヤ慨鏀硅挋鐗堥鑹�
+- 浼樺寲 maskClick灞炴�� 鏇存柊涓� isMaskClick 锛岃В鍐冲井淇″皬绋嬪簭璀﹀憡鐨勯棶棰�
+## 1.7.3锛�2022-01-13锛�
+- 淇 璁剧疆 safeArea 灞炴�т笉鐢熸晥鐨刡ug
+## 1.7.2锛�2021-11-26锛�
+- 浼樺寲 缁勪欢绀轰緥
+## 1.7.1锛�2021-11-26锛�
+- 淇 vuedoc 鏂囧瓧閿欒
+## 1.7.0锛�2021-11-19锛�
+- 浼樺寲 缁勪欢UI锛屽苟鎻愪緵璁捐璧勬簮锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 鏂囨。杩佺Щ锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/uni-popup](https://uniapp.dcloud.io/component/uniui/uni-popup)
+## 1.6.2锛�2021-08-24锛�
+- 鏂板 鏀寔鍥介檯鍖�
+## 1.6.1锛�2021-07-30锛�
+- 浼樺寲 vue3涓嬩簨浠惰鍛婄殑闂
+## 1.6.0锛�2021-07-13锛�
+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤簐ue3椤圭洰锛岃瑙� [uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+## 1.5.0锛�2021-06-23锛�
+- 鏂板 mask-click 閬僵灞傜偣鍑讳簨浠�
+## 1.4.5锛�2021-06-22锛�
+- 淇 nvue 骞冲彴涓棿寮瑰嚭鍚庯紝鐐瑰嚮鍐呭锛屽啀鐐瑰嚮閬僵鏃犳硶鍏抽棴鐨凚ug
+## 1.4.4锛�2021-06-18锛�
+- 淇 H5骞冲彴涓棿寮瑰嚭鍚庯紝鐐瑰嚮鍐呭锛屽啀鐐瑰嚮閬僵鏃犳硶鍏抽棴鐨凚ug
+## 1.4.3锛�2021-06-08锛�
+- 淇 閿欒鐨� watch 瀛楁
+- 淇 safeArea 灞炴�т笉鐢熸晥鐨勯棶棰�
+- 淇 鐐瑰嚮鍐呭锛屽啀鐐瑰嚮閬僵鏃犳硶鍏抽棴鐨凚ug
+## 1.4.2锛�2021-05-12锛�
+- 鏂板 缁勪欢绀轰緥鍦板潃
+## 1.4.1锛�2021-04-29锛�
+- 淇 缁勪欢鍐呮斁缃� input 銆乼extarea 缁勪欢锛屾棤娉曡仛鐒︾殑闂
+## 1.4.0 锛�2021-04-29锛�
+- 鏂板 type 灞炴�х殑 left\right 鍊硷紝鏀寔宸﹀彸寮瑰嚭
+- 鏂板 open(String:type) 鏂规硶鍙傛暟 锛屽彲浠ョ渷鐣� type 灞炴�� 锛岀洿鎺ヤ紶鍏ョ被鍨嬫墦寮�鎸囧畾寮圭獥
+- 鏂板 backgroundColor 灞炴�э紝鍙畾涔変富绐楀彛鑳屾櫙鑹�,榛樿涓嶆樉绀鸿儗鏅壊
+- 鏂板 safeArea 灞炴�э紝鏄惁閫傞厤搴曢儴瀹夊叏鍖�
+- 淇 App\h5\寰俊灏忕▼搴忓簳閮ㄥ畨鍏ㄥ尯鍗犱綅涓嶅鐨凚ug
+- 淇 App 绔脊鍑虹瓑寰呯殑Bug
+- 浼樺寲 鎻愬崌浣庨厤璁惧鎬ц兘锛屼紭鍖栧姩鐢诲崱椤块棶棰�
+- 浼樺寲 鏇寸畝鍗曠殑缁勪欢鑷畾涔夋柟寮�
+## 1.2.9锛�2021-02-05锛�
+- 浼樺寲 缁勪欢寮曠敤鍏崇郴锛岄�氳繃uni_modules寮曠敤缁勪欢
+## 1.2.8锛�2021-02-05锛�
+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
+## 1.2.7锛�2021-02-05锛�
+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
+- 鏂板 鏀寔 PC 绔�
+- 鏂板 uni-popup-message 銆乽ni-popup-dialog鎵╁睍缁勪欢鏀寔 PC 绔�
diff --git a/app/uni_modules/uni-popup/components/uni-popup-dialog/keypress.js b/app/uni_modules/uni-popup/components/uni-popup-dialog/keypress.js
new file mode 100644
index 0000000..6ef26a2
--- /dev/null
+++ b/app/uni_modules/uni-popup/components/uni-popup-dialog/keypress.js
@@ -0,0 +1,45 @@
+// #ifdef H5
+export default {
+ name: 'Keypress',
+ props: {
+ disable: {
+ type: Boolean,
+ default: false
+ }
+ },
+ mounted () {
+ const keyNames = {
+ esc: ['Esc', 'Escape'],
+ tab: 'Tab',
+ enter: 'Enter',
+ space: [' ', 'Spacebar'],
+ up: ['Up', 'ArrowUp'],
+ left: ['Left', 'ArrowLeft'],
+ right: ['Right', 'ArrowRight'],
+ down: ['Down', 'ArrowDown'],
+ delete: ['Backspace', 'Delete', 'Del']
+ }
+ const listener = ($event) => {
+ if (this.disable) {
+ return
+ }
+ const keyName = Object.keys(keyNames).find(key => {
+ const keyName = $event.key
+ const value = keyNames[key]
+ return value === keyName || (Array.isArray(value) && value.includes(keyName))
+ })
+ if (keyName) {
+ // 閬垮厤鍜屽叾浠栨寜閿簨浠跺啿绐�
+ setTimeout(() => {
+ this.$emit(keyName, {})
+ }, 0)
+ }
+ }
+ document.addEventListener('keyup', listener)
+ this.$once('hook:beforeDestroy', () => {
+ document.removeEventListener('keyup', listener)
+ })
+ },
+ render: () => {}
+}
+// #endif
diff --git a/app/uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue b/app/uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue
new file mode 100644
index 0000000..b5eee79
--- /dev/null
+++ b/app/uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue
@@ -0,0 +1,275 @@
+<template>
+ <view class="uni-popup-dialog">
+ <view class="uni-dialog-title">
+ <text class="uni-dialog-title-text" :class="['uni-popup__'+dialogType]">{{titleText}}</text>
+ </view>
+ <view v-if="mode === 'base'" class="uni-dialog-content">
+ <slot>
+ <text class="uni-dialog-content-text">{{content}}</text>
+ </slot>
+ </view>
+ <view v-else class="uni-dialog-content">
+ <slot>
+ <input class="uni-dialog-input" v-model="val" :type="inputType" :placeholder="placeholderText" :focus="focus" >
+ </slot>
+ </view>
+ <view class="uni-dialog-button-group">
+ <view class="uni-dialog-button" @click="closeDialog">
+ <text class="uni-dialog-button-text">{{closeText}}</text>
+ </view>
+ <view class="uni-dialog-button uni-border-left" @click="onOk">
+ <text class="uni-dialog-button-text uni-button-color">{{okText}}</text>
+ </view>
+ </view>
+
+ </view>
+</template>
+
+<script>
+ import popup from '../uni-popup/popup.js'
+ import {
+ initVueI18n
+ } from '@dcloudio/uni-i18n'
+ import messages from '../uni-popup/i18n/index.js'
+ const { t } = initVueI18n(messages)
+ /**
+ * PopUp 寮瑰嚭灞�-瀵硅瘽妗嗘牱寮�
+ * @description 寮瑰嚭灞�-瀵硅瘽妗嗘牱寮�
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=329
+ * @property {String} value input 妯″紡涓嬬殑榛樿鍊�
+ * @property {String} placeholder input 妯″紡涓嬭緭鍏ユ彁绀�
+ * @property {String} type = [success|warning|info|error] 涓婚鏍峰紡
+ * @value success 鎴愬姛
+ * @value warning 鎻愮ず
+ * @value info 娑堟伅
+ * @value error 閿欒
+ * @property {String} mode = [base|input] 妯″紡銆�
+ * @value base 鍩虹瀵硅瘽妗�
+ * @value input 鍙緭鍏ュ璇濇
+ * @property {String} content 瀵硅瘽妗嗗唴瀹�
+ * @property {Boolean} beforeClose 鏄惁鎷︽埅鍙栨秷浜嬩欢
+ * @event {Function} confirm 鐐瑰嚮纭鎸夐挳瑙﹀彂
+ * @event {Function} close 鐐瑰嚮鍙栨秷鎸夐挳瑙﹀彂
+ */
+
+ export default {
+ name: "uniPopupDialog",
+ mixins: [popup],
+ emits:['confirm','close'],
+ props: {
+ inputType:{
+ type: String,
+ default: 'text'
+ },
+ value: {
+ type: [String, Number],
+ default: ''
+ },
+ placeholder: {
+ type: [String, Number],
+ default: ''
+ },
+ type: {
+ type: String,
+ default: 'error'
+ },
+ mode: {
+ type: String,
+ default: 'base'
+ },
+ title: {
+ type: String,
+ default: ''
+ },
+ content: {
+ type: String,
+ default: ''
+ },
+ beforeClose: {
+ type: Boolean,
+ default: false
+ },
+ cancelText:{
+ type: String,
+ default: ''
+ },
+ confirmText:{
+ type: String,
+ default: ''
+ }
+ },
+ data() {
+ return {
+ dialogType: 'error',
+ focus: false,
+ val: ""
+ }
+ },
+ computed: {
+ okText() {
+ return this.confirmText || t("uni-popup.ok")
+ },
+ closeText() {
+ return this.cancelText || t("uni-popup.cancel")
+ },
+ placeholderText() {
+ return this.placeholder || t("uni-popup.placeholder")
+ },
+ titleText() {
+ return this.title || t("uni-popup.title")
+ }
+ },
+ watch: {
+ type(val) {
+ this.dialogType = val
+ },
+ mode(val) {
+ if (val === 'input') {
+ this.dialogType = 'info'
+ }
+ },
+ value(val) {
+ this.val = val
+ }
+ },
+ created() {
+ // 瀵硅瘽妗嗛伄缃╀笉鍙偣鍑�
+ this.popup.disableMask()
+ // this.popup.closeMask()
+ if (this.mode === 'input') {
+ this.dialogType = 'info'
+ this.val = this.value
+ } else {
+ this.dialogType = this.type
+ }
+ },
+ mounted() {
+ this.focus = true
+ },
+ methods: {
+ /**
+ * 鐐瑰嚮纭鎸夐挳
+ */
+ onOk() {
+ if (this.mode === 'input'){
+ this.$emit('confirm', this.val)
+ }else{
+ this.$emit('confirm')
+ }
+ if(this.beforeClose) return
+ this.popup.close()
+ },
+ /**
+ * 鐐瑰嚮鍙栨秷鎸夐挳
+ */
+ closeDialog() {
+ this.$emit('close')
+ if(this.beforeClose) return
+ this.popup.close()
+ },
+ close(){
+ this.popup.close()
+ }
+ }
+ }
+</script>
+
+<style lang="scss" >
+ .uni-popup-dialog {
+ width: 300px;
+ border-radius: 11px;
+ background-color: #fff;
+ }
+
+ .uni-dialog-title {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ justify-content: center;
+ padding-top: 25px;
+ }
+
+ .uni-dialog-title-text {
+ font-size: 16px;
+ font-weight: 500;
+ }
+
+ .uni-dialog-content {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ justify-content: center;
+ align-items: center;
+ padding: 20px;
+ }
+
+ .uni-dialog-content-text {
+ font-size: 14px;
+ color: #6C6C6C;
+ }
+
+ .uni-dialog-button-group {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ border-top-color: #f5f5f5;
+ border-top-style: solid;
+ border-top-width: 1px;
+ }
+
+ .uni-dialog-button {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+
+ flex: 1;
+ flex-direction: row;
+ justify-content: center;
+ align-items: center;
+ height: 45px;
+ }
+
+ .uni-border-left {
+ border-left-color: #f0f0f0;
+ border-left-style: solid;
+ border-left-width: 1px;
+ }
+
+ .uni-dialog-button-text {
+ font-size: 16px;
+ color: #333;
+ }
+
+ .uni-button-color {
+ color: #007aff;
+ }
+
+ .uni-dialog-input {
+ flex: 1;
+ font-size: 14px;
+ border: 1px #eee solid;
+ height: 40px;
+ padding: 0 10px;
+ border-radius: 5px;
+ color: #555;
+ }
+
+ .uni-popup__success {
+ color: #4cd964;
+ }
+
+ .uni-popup__warn {
+ color: #f0ad4e;
+ }
+
+ .uni-popup__error {
+ color: #dd524d;
+ }
+
+ .uni-popup__info {
+ color: #909399;
+ }
+</style>
diff --git a/app/uni_modules/uni-popup/components/uni-popup-message/uni-popup-message.vue b/app/uni_modules/uni-popup/components/uni-popup-message/uni-popup-message.vue
new file mode 100644
index 0000000..91370a8
--- /dev/null
+++ b/app/uni_modules/uni-popup/components/uni-popup-message/uni-popup-message.vue
@@ -0,0 +1,143 @@
+<template>
+ <view class="uni-popup-message">
+ <view class="uni-popup-message__box fixforpc-width" :class="'uni-popup__'+type">
+ <slot>
+ <text class="uni-popup-message-text" :class="'uni-popup__'+type+'-text'">{{message}}</text>
+ </slot>
+ </view>
+ </view>
+</template>
+
+<script>
+ import popup from '../uni-popup/popup.js'
+ /**
+ * PopUp 寮瑰嚭灞�-娑堟伅鎻愮ず
+ * @description 寮瑰嚭灞�-娑堟伅鎻愮ず
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=329
+ * @property {String} type = [success|warning|info|error] 涓婚鏍峰紡
+ * @value success 鎴愬姛
+ * @value warning 鎻愮ず
+ * @value info 娑堟伅
+ * @value error 閿欒
+ * @property {String} message 娑堟伅鎻愮ず鏂囧瓧
+ * @property {String} duration 鏄剧ず鏃堕棿锛岃缃负 0 鍒欎笉浼氳嚜鍔ㄥ叧闂�
+ */
+
+ export default {
+ name: 'uniPopupMessage',
+ mixins:[popup],
+ props: {
+ /**
+ * 涓婚 success/warning/info/error 榛樿 success
+ */
+ type: {
+ type: String,
+ default: 'success'
+ },
+ /**
+ * 娑堟伅鏂囧瓧
+ */
+ message: {
+ type: String,
+ default: ''
+ },
+ /**
+ * 鏄剧ず鏃堕棿锛岃缃负 0 鍒欎笉浼氳嚜鍔ㄥ叧闂�
+ */
+ duration: {
+ type: Number,
+ default: 3000
+ },
+ maskShow:{
+ type:Boolean,
+ default:false
+ }
+ },
+ data() {
+ return {}
+ },
+ created() {
+ this.popup.maskShow = this.maskShow
+ this.popup.messageChild = this
+ },
+ methods: {
+ timerClose(){
+ if(this.duration === 0) return
+ clearTimeout(this.timer)
+ this.timer = setTimeout(()=>{
+ this.popup.close()
+ },this.duration)
+ }
+ }
+ }
+</script>
+<style lang="scss" >
+ .uni-popup-message {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ justify-content: center;
+ }
+
+ .uni-popup-message__box {
+ background-color: #e1f3d8;
+ padding: 10px 15px;
+ border-color: #eee;
+ border-style: solid;
+ border-width: 1px;
+ flex: 1;
+ }
+
+ @media screen and (min-width: 500px) {
+ .fixforpc-width {
+ margin-top: 20px;
+ border-radius: 4px;
+ flex: none;
+ min-width: 380px;
+ /* #ifndef APP-NVUE */
+ max-width: 50%;
+ /* #endif */
+ /* #ifdef APP-NVUE */
+ max-width: 500px;
+ /* #endif */
+ }
+ }
+
+ .uni-popup-message-text {
+ font-size: 14px;
+ padding: 0;
+ }
+
+ .uni-popup__success {
+ background-color: #e1f3d8;
+ }
+
+ .uni-popup__success-text {
+ color: #67C23A;
+ }
+
+ .uni-popup__warn {
+ background-color: #faecd8;
+ }
+
+ .uni-popup__warn-text {
+ color: #E6A23C;
+ }
+
+ .uni-popup__error {
+ background-color: #fde2e2;
+ }
+
+ .uni-popup__error-text {
+ color: #F56C6C;
+ }
+
+ .uni-popup__info {
+ background-color: #F2F6FC;
+ }
+
+ .uni-popup__info-text {
+ color: #909399;
+ }
+</style>
diff --git a/app/uni_modules/uni-popup/components/uni-popup-share/uni-popup-share.vue b/app/uni_modules/uni-popup/components/uni-popup-share/uni-popup-share.vue
new file mode 100644
index 0000000..5be7624
--- /dev/null
+++ b/app/uni_modules/uni-popup/components/uni-popup-share/uni-popup-share.vue
@@ -0,0 +1,187 @@
+<template>
+ <view class="uni-popup-share">
+ <view class="uni-share-title"><text class="uni-share-title-text">{{shareTitleText}}</text></view>
+ <view class="uni-share-content">
+ <view class="uni-share-content-box">
+ <view class="uni-share-content-item" v-for="(item,index) in bottomData" :key="index" @click.stop="select(item,index)">
+ <image class="uni-share-image" :src="item.icon" mode="aspectFill"></image>
+ <text class="uni-share-text">{{item.text}}</text>
+ </view>
+
+ </view>
+ </view>
+ <view class="uni-share-button-box">
+ <button class="uni-share-button" @click="close">{{cancelText}}</button>
+ </view>
+ </view>
+</template>
+
+<script>
+ import popup from '../uni-popup/popup.js'
+ import {
+ initVueI18n
+ } from '@dcloudio/uni-i18n'
+ import messages from '../uni-popup/i18n/index.js'
+ const { t } = initVueI18n(messages)
+ export default {
+ name: 'UniPopupShare',
+ mixins:[popup],
+ emits:['select'],
+ props: {
+ title: {
+ type: String,
+ default: ''
+ },
+ beforeClose: {
+ type: Boolean,
+ default: false
+ }
+ },
+ data() {
+ return {
+ bottomData: [{
+ text: '寰俊',
+ icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/c2b17470-50be-11eb-b680-7980c8a877b8.png',
+ name: 'wx'
+ },
+ {
+ text: '鏀粯瀹�',
+ icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/d684ae40-50be-11eb-8ff1-d5dcf8779628.png',
+ name: 'wx'
+ },
+ {
+ text: 'QQ',
+ icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/e7a79520-50be-11eb-b997-9918a5dda011.png',
+ name: 'qq'
+ },
+ {
+ text: '鏂版氮',
+ icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/0dacdbe0-50bf-11eb-8ff1-d5dcf8779628.png',
+ name: 'sina'
+ },
+ // {
+ // text: '鐧惧害',
+ // icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/1ec6e920-50bf-11eb-8a36-ebb87efcf8c0.png',
+ // name: 'copy'
+ // },
+ // {
+ // text: '鍏朵粬',
+ // icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/2e0fdfe0-50bf-11eb-b997-9918a5dda011.png',
+ // name: 'more'
+ // }
+ ]
+ }
+ },
+ created() {},
+ computed: {
+ cancelText() {
+ return t("uni-popup.cancel")
+ },
+ shareTitleText() {
+ return this.title || t("uni-popup.shareTitle")
+ }
+ },
+ methods: {
+ /**
+ * 閫夋嫨鍐呭
+ */
+ select(item, index) {
+ this.$emit('select', {
+ item,
+ index
+ })
+ this.close()
+
+ },
+ /**
+ * 鍏抽棴绐楀彛
+ */
+ close() {
+ if(this.beforeClose) return
+ this.popup.close()
+ }
+ }
+ }
+</script>
+<style lang="scss" >
+ .uni-popup-share {
+ background-color: #fff;
+ border-top-left-radius: 11px;
+ border-top-right-radius: 11px;
+ }
+ .uni-share-title {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ align-items: center;
+ justify-content: center;
+ height: 40px;
+ }
+ .uni-share-title-text {
+ font-size: 14px;
+ color: #666;
+ }
+ .uni-share-content {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ justify-content: center;
+ padding-top: 10px;
+ }
+
+ .uni-share-content-box {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ flex-wrap: wrap;
+ width: 360px;
+ }
+
+ .uni-share-content-item {
+ width: 90px;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: column;
+ justify-content: center;
+ padding: 10px 0;
+ align-items: center;
+ }
+
+ .uni-share-content-item:active {
+ background-color: #f5f5f5;
+ }
+
+ .uni-share-image {
+ width: 30px;
+ height: 30px;
+ }
+
+ .uni-share-text {
+ margin-top: 10px;
+ font-size: 14px;
+ color: #3B4144;
+ }
+
+ .uni-share-button-box {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ padding: 10px 15px;
+ }
+
+ .uni-share-button {
+ flex: 1;
+ border-radius: 50px;
+ color: #666;
+ font-size: 16px;
+ }
+
+ .uni-share-button::after {
+ border-radius: 50px;
+ }
+</style>
diff --git a/app/uni_modules/uni-popup/components/uni-popup/i18n/en.json b/app/uni_modules/uni-popup/components/uni-popup/i18n/en.json
new file mode 100644
index 0000000..7f1bd06
--- /dev/null
+++ b/app/uni_modules/uni-popup/components/uni-popup/i18n/en.json
@@ -0,0 +1,7 @@
+{
+ "uni-popup.cancel": "cancel",
+ "uni-popup.ok": "ok",
+ "uni-popup.placeholder": "pleace enter",
+ "uni-popup.title": "Hint",
+ "uni-popup.shareTitle": "Share to"
+}
diff --git a/app/uni_modules/uni-popup/components/uni-popup/i18n/index.js b/app/uni_modules/uni-popup/components/uni-popup/i18n/index.js
new file mode 100644
index 0000000..de7509c
--- /dev/null
+++ b/app/uni_modules/uni-popup/components/uni-popup/i18n/index.js
@@ -0,0 +1,8 @@
+import en from './en.json'
+import zhHans from './zh-Hans.json'
+import zhHant from './zh-Hant.json'
+export default {
+ en,
+ 'zh-Hans': zhHans,
+ 'zh-Hant': zhHant
+}
diff --git a/app/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hans.json b/app/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hans.json
new file mode 100644
index 0000000..5e3003c
--- /dev/null
+++ b/app/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hans.json
@@ -0,0 +1,7 @@
+{
+ "uni-popup.cancel": "鍙栨秷",
+ "uni-popup.ok": "纭畾",
+ "uni-popup.placeholder": "璇疯緭鍏�",
+ "uni-popup.title": "鎻愮ず",
+ "uni-popup.shareTitle": "鍒嗕韩鍒�"
+}
diff --git a/app/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hant.json b/app/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hant.json
new file mode 100644
index 0000000..13e39eb
--- /dev/null
+++ b/app/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hant.json
@@ -0,0 +1,7 @@
+{
+ "uni-popup.cancel": "鍙栨秷",
+ "uni-popup.ok": "纰哄畾",
+ "uni-popup.placeholder": "璜嬭几鍏�",
+ "uni-popup.title": "鎻愮ず",
+ "uni-popup.shareTitle": "鍒嗕韩鍒�"
+}
diff --git a/app/uni_modules/uni-popup/components/uni-popup/keypress.js b/app/uni_modules/uni-popup/components/uni-popup/keypress.js
new file mode 100644
index 0000000..62dda46
--- /dev/null
+++ b/app/uni_modules/uni-popup/components/uni-popup/keypress.js
@@ -0,0 +1,45 @@
+// #ifdef H5
+export default {
+ name: 'Keypress',
+ props: {
+ disable: {
+ type: Boolean,
+ default: false
+ }
+ },
+ mounted () {
+ const keyNames = {
+ esc: ['Esc', 'Escape'],
+ tab: 'Tab',
+ enter: 'Enter',
+ space: [' ', 'Spacebar'],
+ up: ['Up', 'ArrowUp'],
+ left: ['Left', 'ArrowLeft'],
+ right: ['Right', 'ArrowRight'],
+ down: ['Down', 'ArrowDown'],
+ delete: ['Backspace', 'Delete', 'Del']
+ }
+ const listener = ($event) => {
+ if (this.disable) {
+ return
+ }
+ const keyName = Object.keys(keyNames).find(key => {
+ const keyName = $event.key
+ const value = keyNames[key]
+ return value === keyName || (Array.isArray(value) && value.includes(keyName))
+ })
+ if (keyName) {
+ // 閬垮厤鍜屽叾浠栨寜閿簨浠跺啿绐�
+ setTimeout(() => {
+ this.$emit(keyName, {})
+ }, 0)
+ }
+ }
+ document.addEventListener('keyup', listener)
+ // this.$once('hook:beforeDestroy', () => {
+ // document.removeEventListener('keyup', listener)
+ // })
+ },
+ render: () => {}
+}
+// #endif
diff --git a/app/uni_modules/uni-popup/components/uni-popup/popup.js b/app/uni_modules/uni-popup/components/uni-popup/popup.js
new file mode 100644
index 0000000..c4e5781
--- /dev/null
+++ b/app/uni_modules/uni-popup/components/uni-popup/popup.js
@@ -0,0 +1,26 @@
+
+export default {
+ data() {
+ return {
+
+ }
+ },
+ created(){
+ this.popup = this.getParent()
+ },
+ methods:{
+ /**
+ * 鑾峰彇鐖跺厓绱犲疄渚�
+ */
+ getParent(name = 'uniPopup') {
+ let parent = this.$parent;
+ let parentName = parent.$options.name;
+ while (parentName !== name) {
+ parent = parent.$parent;
+ if (!parent) return false
+ parentName = parent.$options.name;
+ }
+ return parent;
+ },
+ }
+}
diff --git a/app/uni_modules/uni-popup/components/uni-popup/uni-popup.vue b/app/uni_modules/uni-popup/components/uni-popup/uni-popup.vue
new file mode 100644
index 0000000..54afee2
--- /dev/null
+++ b/app/uni_modules/uni-popup/components/uni-popup/uni-popup.vue
@@ -0,0 +1,473 @@
+<template>
+ <view v-if="showPopup" class="uni-popup" :class="[popupstyle, isDesktop ? 'fixforpc-z-index' : '']">
+ <view @touchstart="touchstart">
+ <uni-transition key="1" v-if="maskShow" name="mask" mode-class="fade" :styles="maskClass"
+ :duration="duration" :show="showTrans" @click="onTap" />
+ <uni-transition key="2" :mode-class="ani" name="content" :styles="transClass" :duration="duration"
+ :show="showTrans" @click="onTap">
+ <view class="uni-popup__wrapper" :style="{ backgroundColor: bg }" :class="[popupstyle]" @click="clear">
+ <slot />
+ </view>
+ </uni-transition>
+ </view>
+ <!-- #ifdef H5 -->
+ <keypress v-if="maskShow" @esc="onTap" />
+ <!-- #endif -->
+ </view>
+</template>
+
+<script>
+ // #ifdef H5
+ import keypress from './keypress.js'
+ // #endif
+
+ /**
+ * PopUp 寮瑰嚭灞�
+ * @description 寮瑰嚭灞傜粍浠讹紝涓轰簡瑙e喅閬僵寮瑰眰鐨勯棶棰�
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=329
+ * @property {String} type = [top|center|bottom|left|right|message|dialog|share] 寮瑰嚭鏂瑰紡
+ * @value top 椤堕儴寮瑰嚭
+ * @value center 涓棿寮瑰嚭
+ * @value bottom 搴曢儴寮瑰嚭
+ * @value left 宸︿晶寮瑰嚭
+ * @value right 鍙充晶寮瑰嚭
+ * @value message 娑堟伅鎻愮ず
+ * @value dialog 瀵硅瘽妗�
+ * @value share 搴曢儴鍒嗕韩绀轰緥
+ * @property {Boolean} animation = [true|false] 鏄惁寮�鍚姩鐢�
+ * @property {Boolean} maskClick = [true|false] 钂欑増鐐瑰嚮鏄惁鍏抽棴寮圭獥(搴熷純)
+ * @property {Boolean} isMaskClick = [true|false] 钂欑増鐐瑰嚮鏄惁鍏抽棴寮圭獥
+ * @property {String} backgroundColor 涓荤獥鍙h儗鏅壊
+ * @property {String} maskBackgroundColor 钂欑増棰滆壊
+ * @property {Boolean} safeArea 鏄惁閫傞厤搴曢儴瀹夊叏鍖�
+ * @event {Function} change 鎵撳紑鍏抽棴寮圭獥瑙﹀彂锛宔={show: false}
+ * @event {Function} maskClick 鐐瑰嚮閬僵瑙﹀彂
+ */
+
+ export default {
+ name: 'uniPopup',
+ components: {
+ // #ifdef H5
+ keypress
+ // #endif
+ },
+ emits: ['change', 'maskClick'],
+ props: {
+ // 寮�鍚姩鐢�
+ animation: {
+ type: Boolean,
+ default: true
+ },
+ // 寮瑰嚭灞傜被鍨嬶紝鍙�夊�硷紝top: 椤堕儴寮瑰嚭灞傦紱bottom锛氬簳閮ㄥ脊鍑哄眰锛沜enter锛氬叏灞忓脊鍑哄眰
+ // message: 娑堟伅鎻愮ず ; dialog : 瀵硅瘽妗�
+ type: {
+ type: String,
+ default: 'center'
+ },
+ // maskClick
+ isMaskClick: {
+ type: Boolean,
+ default: null
+ },
+ // TODO 2 涓増鏈悗搴熷純灞炴�� 锛屼娇鐢� isMaskClick
+ maskClick: {
+ type: Boolean,
+ default: null
+ },
+ backgroundColor: {
+ type: String,
+ default: 'none'
+ },
+ safeArea: {
+ type: Boolean,
+ default: true
+ },
+ maskBackgroundColor: {
+ type: String,
+ default: 'rgba(0, 0, 0, 0.4)'
+ },
+ },
+
+ watch: {
+ /**
+ * 鐩戝惉type绫诲瀷
+ */
+ type: {
+ handler: function(type) {
+ if (!this.config[type]) return
+ this[this.config[type]](true)
+ },
+ immediate: true
+ },
+ isDesktop: {
+ handler: function(newVal) {
+ if (!this.config[newVal]) return
+ this[this.config[this.type]](true)
+ },
+ immediate: true
+ },
+ /**
+ * 鐩戝惉閬僵鏄惁鍙偣鍑�
+ * @param {Object} val
+ */
+ maskClick: {
+ handler: function(val) {
+ this.mkclick = val
+ },
+ immediate: true
+ },
+ isMaskClick: {
+ handler: function(val) {
+ this.mkclick = val
+ },
+ immediate: true
+ },
+ // H5 涓嬬姝㈠簳閮ㄦ粴鍔�
+ showPopup(show) {
+ // #ifdef H5
+ // fix by mehaotian 澶勭悊 h5 婊氬姩绌块�忕殑闂
+ document.getElementsByTagName('body')[0].style.overflow = show ? 'hidden' : 'visible'
+ // #endif
+ }
+ },
+ data() {
+ return {
+ duration: 300,
+ ani: [],
+ showPopup: false,
+ showTrans: false,
+ popupWidth: 0,
+ popupHeight: 0,
+ config: {
+ top: 'top',
+ bottom: 'bottom',
+ center: 'center',
+ left: 'left',
+ right: 'right',
+ message: 'top',
+ dialog: 'center',
+ share: 'bottom'
+ },
+ maskClass: {
+ position: 'fixed',
+ bottom: 0,
+ top: 0,
+ left: 0,
+ right: 0,
+ backgroundColor: 'rgba(0, 0, 0, 0.4)'
+ },
+ transClass: {
+ position: 'fixed',
+ left: 0,
+ right: 0
+ },
+ maskShow: true,
+ mkclick: true,
+ popupstyle: this.isDesktop ? 'fixforpc-top' : 'top'
+ }
+ },
+ computed: {
+ isDesktop() {
+ return this.popupWidth >= 500 && this.popupHeight >= 500
+ },
+ bg() {
+ if (this.backgroundColor === '' || this.backgroundColor === 'none') {
+ return 'transparent'
+ }
+ return this.backgroundColor
+ }
+ },
+ mounted() {
+ const fixSize = () => {
+ const {
+ windowWidth,
+ windowHeight,
+ windowTop,
+ safeArea,
+ screenHeight,
+ safeAreaInsets
+ } = uni.getSystemInfoSync()
+ this.popupWidth = windowWidth
+ this.popupHeight = windowHeight + (windowTop || 0)
+ // TODO fix by mehaotian 鏄惁閫傞厤搴曢儴瀹夊叏鍖� ,鐩墠寰俊ios 銆佸拰 app ios 璁$畻鏈夊樊寮傦紝闇�瑕佹鏋朵慨澶�
+ if (safeArea && this.safeArea) {
+ // #ifdef MP-WEIXIN
+ this.safeAreaInsets = screenHeight - safeArea.bottom
+ // #endif
+ // #ifndef MP-WEIXIN
+ this.safeAreaInsets = safeAreaInsets.bottom
+ // #endif
+ } else {
+ this.safeAreaInsets = 0
+ }
+ }
+ fixSize()
+ // #ifdef H5
+ // window.addEventListener('resize', fixSize)
+ // this.$once('hook:beforeDestroy', () => {
+ // window.removeEventListener('resize', fixSize)
+ // })
+ // #endif
+ },
+ // #ifndef VUE3
+ // TODO vue2
+ destroyed() {
+ this.setH5Visible()
+ },
+ // #endif
+ // #ifdef VUE3
+ // TODO vue3
+ unmounted() {
+ this.setH5Visible()
+ },
+ // #endif
+ created() {
+ // this.mkclick = this.isMaskClick || this.maskClick
+ if (this.isMaskClick === null && this.maskClick === null) {
+ this.mkclick = true
+ } else {
+ this.mkclick = this.isMaskClick !== null ? this.isMaskClick : this.maskClick
+ }
+ if (this.animation) {
+ this.duration = 300
+ } else {
+ this.duration = 0
+ }
+ // TODO 澶勭悊 message 缁勪欢鐢熷懡鍛ㄦ湡寮傚父鐨勯棶棰�
+ this.messageChild = null
+ // TODO 瑙e喅澶存潯鍐掓场鐨勯棶棰�
+ this.clearPropagation = false
+ this.maskClass.backgroundColor = this.maskBackgroundColor
+ },
+ methods: {
+ setH5Visible() {
+ // #ifdef H5
+ // fix by mehaotian 澶勭悊 h5 婊氬姩绌块�忕殑闂
+ document.getElementsByTagName('body')[0].style.overflow = 'visible'
+ // #endif
+ },
+ /**
+ * 鍏敤鏂规硶锛屼笉鏄剧ず閬僵灞�
+ */
+ closeMask() {
+ this.maskShow = false
+ },
+ /**
+ * 鍏敤鏂规硶锛岄伄缃╁眰绂佹鐐瑰嚮
+ */
+ disableMask() {
+ this.mkclick = false
+ },
+ // TODO nvue 鍙栨秷鍐掓场
+ clear(e) {
+ // #ifndef APP-NVUE
+ e.stopPropagation()
+ // #endif
+ this.clearPropagation = true
+ },
+
+ open(direction) {
+ // fix by mehaotian 澶勭悊蹇�熸墦寮�鍏抽棴鐨勬儏鍐�
+ if (this.showPopup) {
+ return
+ }
+ let innerType = ['top', 'center', 'bottom', 'left', 'right', 'message', 'dialog', 'share']
+ if (!(direction && innerType.indexOf(direction) !== -1)) {
+ direction = this.type
+ }
+ if (!this.config[direction]) {
+ console.error('缂哄皯绫诲瀷锛�', direction)
+ return
+ }
+ this[this.config[direction]]()
+ this.$emit('change', {
+ show: true,
+ type: direction
+ })
+ },
+ close(type) {
+ this.showTrans = false
+ this.$emit('change', {
+ show: false,
+ type: this.type
+ })
+ clearTimeout(this.timer)
+ // // 鑷畾涔夊叧闂簨浠�
+ // this.customOpen && this.customClose()
+ this.timer = setTimeout(() => {
+ this.showPopup = false
+ }, 300)
+ },
+ // TODO 澶勭悊鍐掓场浜嬩欢锛屽ご鏉$殑鍐掓场浜嬩欢鏈夐棶棰� 锛屽厛杩欐牱鍏煎
+ touchstart() {
+ this.clearPropagation = false
+ },
+
+ onTap() {
+ if (this.clearPropagation) {
+ // fix by mehaotian 鍏煎 nvue
+ this.clearPropagation = false
+ return
+ }
+ this.$emit('maskClick')
+ if (!this.mkclick) return
+ this.close()
+ },
+ /**
+ * 椤堕儴寮瑰嚭鏍峰紡澶勭悊
+ */
+ top(type) {
+ this.popupstyle = this.isDesktop ? 'fixforpc-top' : 'top'
+ this.ani = ['slide-top']
+ this.transClass = {
+ position: 'fixed',
+ left: 0,
+ right: 0,
+ backgroundColor: this.bg
+ }
+ // TODO 鍏煎 type 灞炴�� 锛屽悗缁細搴熷純
+ if (type) return
+ this.showPopup = true
+ this.showTrans = true
+ this.$nextTick(() => {
+ if (this.messageChild && this.type === 'message') {
+ this.messageChild.timerClose()
+ }
+ })
+ },
+ /**
+ * 搴曢儴寮瑰嚭鏍峰紡澶勭悊
+ */
+ bottom(type) {
+ this.popupstyle = 'bottom'
+ this.ani = ['slide-bottom']
+ this.transClass = {
+ position: 'fixed',
+ left: 0,
+ right: 0,
+ bottom: 0,
+ paddingBottom: this.safeAreaInsets + 'px',
+ backgroundColor: this.bg
+ }
+ // TODO 鍏煎 type 灞炴�� 锛屽悗缁細搴熷純
+ if (type) return
+ this.showPopup = true
+ this.showTrans = true
+ },
+ /**
+ * 涓棿寮瑰嚭鏍峰紡澶勭悊
+ */
+ center(type) {
+ this.popupstyle = 'center'
+ this.ani = ['zoom-out', 'fade']
+ this.transClass = {
+ position: 'fixed',
+ /* #ifndef APP-NVUE */
+ display: 'flex',
+ flexDirection: 'column',
+ /* #endif */
+ bottom: 0,
+ left: 0,
+ right: 0,
+ top: 0,
+ justifyContent: 'center',
+ alignItems: 'center'
+ }
+ // TODO 鍏煎 type 灞炴�� 锛屽悗缁細搴熷純
+ if (type) return
+ this.showPopup = true
+ this.showTrans = true
+ },
+ left(type) {
+ this.popupstyle = 'left'
+ this.ani = ['slide-left']
+ this.transClass = {
+ position: 'fixed',
+ left: 0,
+ bottom: 0,
+ top: 0,
+ backgroundColor: this.bg,
+ /* #ifndef APP-NVUE */
+ display: 'flex',
+ flexDirection: 'column'
+ /* #endif */
+ }
+ // TODO 鍏煎 type 灞炴�� 锛屽悗缁細搴熷純
+ if (type) return
+ this.showPopup = true
+ this.showTrans = true
+ },
+ right(type) {
+ this.popupstyle = 'right'
+ this.ani = ['slide-right']
+ this.transClass = {
+ position: 'fixed',
+ bottom: 0,
+ right: 0,
+ top: 0,
+ backgroundColor: this.bg,
+ /* #ifndef APP-NVUE */
+ display: 'flex',
+ flexDirection: 'column'
+ /* #endif */
+ }
+ // TODO 鍏煎 type 灞炴�� 锛屽悗缁細搴熷純
+ if (type) return
+ this.showPopup = true
+ this.showTrans = true
+ }
+ }
+ }
+</script>
+<style lang="scss">
+ .uni-popup {
+ position: fixed;
+ /* #ifndef APP-NVUE */
+ z-index: 99;
+
+ /* #endif */
+ &.top,
+ &.left,
+ &.right {
+ /* #ifdef H5 */
+ top: var(--window-top);
+ /* #endif */
+ /* #ifndef H5 */
+ top: 0;
+ /* #endif */
+ }
+
+ .uni-popup__wrapper {
+ /* #ifndef APP-NVUE */
+ display: block;
+ /* #endif */
+ position: relative;
+
+ /* iphonex 绛夊畨鍏ㄥ尯璁剧疆锛屽簳閮ㄥ畨鍏ㄥ尯閫傞厤 */
+ /* #ifndef APP-NVUE */
+ // padding-bottom: constant(safe-area-inset-bottom);
+ // padding-bottom: env(safe-area-inset-bottom);
+ /* #endif */
+ &.left,
+ &.right {
+ /* #ifdef H5 */
+ padding-top: var(--window-top);
+ /* #endif */
+ /* #ifndef H5 */
+ padding-top: 0;
+ /* #endif */
+ flex: 1;
+ }
+ }
+ }
+
+ .fixforpc-z-index {
+ /* #ifndef APP-NVUE */
+ z-index: 999;
+ /* #endif */
+ }
+
+ .fixforpc-top {
+ top: 0;
+ }
+</style>
diff --git a/app/uni_modules/uni-popup/package.json b/app/uni_modules/uni-popup/package.json
new file mode 100644
index 0000000..f40556b
--- /dev/null
+++ b/app/uni_modules/uni-popup/package.json
@@ -0,0 +1,87 @@
+{
+ "id": "uni-popup",
+ "displayName": "uni-popup 寮瑰嚭灞�",
+ "version": "1.8.3",
+ "description": " Popup 缁勪欢锛屾彁渚涘父鐢ㄧ殑寮瑰眰",
+ "keywords": [
+ "uni-ui",
+ "寮瑰嚭灞�",
+ "寮圭獥",
+ "popup",
+ "寮规"
+ ],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+ "type": "component-vue"
+ },
+ "uni_modules": {
+ "dependencies": [
+ "uni-scss",
+ "uni-transition"
+ ],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "u",
+ "鑱旂洘": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
diff --git a/app/uni_modules/uni-popup/readme.md b/app/uni_modules/uni-popup/readme.md
new file mode 100644
index 0000000..fdad4b3
--- /dev/null
+++ b/app/uni_modules/uni-popup/readme.md
@@ -0,0 +1,17 @@
+
+
+## Popup 寮瑰嚭灞�
+> **缁勪欢鍚嶏細uni-popup**
+> 浠g爜鍧楋細 `uPopup`
+> 鍏宠仈缁勪欢锛歚uni-transition`
+
+
+寮瑰嚭灞傜粍浠讹紝鍦ㄥ簲鐢ㄤ腑寮瑰嚭涓�涓秷鎭彁绀虹獥鍙c�佹彁绀烘绛�
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-popup)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
+
+
+
+
+
diff --git a/app/uni_modules/uni-rate/changelog.md b/app/uni_modules/uni-rate/changelog.md
new file mode 100644
index 0000000..8a98a61
--- /dev/null
+++ b/app/uni_modules/uni-rate/changelog.md
@@ -0,0 +1,25 @@
+## 1.3.1锛�2022-02-25锛�
+- 淇 鏉′欢鍒ゆ柇 `NaN` 閿欒鐨� bug
+## 1.3.0锛�2021-11-19锛�
+- 浼樺寲 缁勪欢UI锛屽苟鎻愪緵璁捐璧勬簮锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 鏂囨。杩佺Щ锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/uni-rate](https://uniapp.dcloud.io/component/uniui/uni-rate)
+## 1.2.2锛�2021-09-10锛�
+- 浼樺寲 榛樿鍊间慨鏀逛负 0 棰楁槦
+## 1.2.1锛�2021-07-30锛�
+- 浼樺寲 vue3涓嬩簨浠惰鍛婄殑闂
+## 1.2.0锛�2021-07-13锛�
+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤簐ue3椤圭洰锛岃瑙� [uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+## 1.1.2锛�2021-05-12锛�
+- 鏂板 缁勪欢绀轰緥鍦板潃
+## 1.1.1锛�2021-04-21锛�
+- 淇 甯冨眬鍙樺寲鍚� uni-rate 鏄熸槦璁$畻涓嶅噯纭殑 bug
+- 浼樺寲 娣诲姞渚濊禆 uni-icons, 瀵煎叆 uni-rate 鑷姩涓嬭浇渚濊禆
+## 1.1.0锛�2021-04-16锛�
+- 淇 uni-rate 灞炴�� margin 鍊间负 string 缁勪欢澶辨晥鐨� bug
+
+## 1.0.9锛�2021-02-05锛�
+- 浼樺寲 缁勪欢寮曠敤鍏崇郴锛岄�氳繃uni_modules寮曠敤缁勪欢
+
+## 1.0.8锛�2021-02-05锛�
+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
+- 鏀寔 pc 绔�
diff --git a/app/uni_modules/uni-rate/components/uni-rate/uni-rate.vue b/app/uni_modules/uni-rate/components/uni-rate/uni-rate.vue
new file mode 100644
index 0000000..9802dfc
--- /dev/null
+++ b/app/uni_modules/uni-rate/components/uni-rate/uni-rate.vue
@@ -0,0 +1,365 @@
+<template>
+ <view>
+ <view ref="uni-rate" class="uni-rate">
+ <view class="uni-rate__icon" :class="{'uni-cursor-not-allowed': disabled}"
+ :style="{ 'margin-right': marginNumber + 'px' }" v-for="(star, index) in stars" :key="index"
+ @touchstart.stop="touchstart" @touchmove.stop="touchmove" @mousedown.stop="mousedown"
+ @mousemove.stop="mousemove" @mouseleave="mouseleave">
+ <uni-icons :color="color" :size="size" :type="isFill ? 'star-filled' : 'star'" />
+ <!-- #ifdef APP-NVUE -->
+ <view :style="{ width: star.activeWitch.replace('%','')*size/100+'px'}" class="uni-rate__icon-on">
+ <uni-icons style="text-align: left;" :color="disabled?'#ccc':activeColor" :size="size"
+ type="star-filled" />
+ </view>
+ <!-- #endif -->
+ <!-- #ifndef APP-NVUE -->
+ <view :style="{ width: star.activeWitch}" class="uni-rate__icon-on">
+ <uni-icons :color="disabled?disabledColor:activeColor" :size="size" type="star-filled" />
+ </view>
+ <!-- #endif -->
+ </view>
+ </view>
+ </view>
+</template>
+
+<script>
+ // #ifdef APP-NVUE
+ const dom = uni.requireNativePlugin('dom');
+ // #endif
+ /**
+ * Rate 璇勫垎
+ * @description 璇勫垎缁勪欢
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=33
+ * @property {Boolean} isFill = [true|false] 鏄熸槦鐨勭被鍨嬶紝鏄惁涓哄疄蹇冪被鍨�, 榛樿涓哄疄蹇�
+ * @property {String} color 鏈�変腑鐘舵�佺殑鏄熸槦棰滆壊锛岄粯璁や负 "#ececec"
+ * @property {String} activeColor 閫変腑鐘舵�佺殑鏄熸槦棰滆壊锛岄粯璁や负 "#ffca3e"
+ * @property {String} disabledColor 绂佺敤鐘舵�佺殑鏄熸槦棰滆壊锛岄粯璁や负 "#c0c0c0"
+ * @property {Number} size 鏄熸槦鐨勫ぇ灏�
+ * @property {Number} value/v-model 褰撳墠璇勫垎
+ * @property {Number} max 鏈�澶ц瘎鍒嗚瘎鍒嗘暟閲忥紝鐩墠涓�鍒嗕竴棰楁槦
+ * @property {Number} margin 鏄熸槦鐨勯棿璺濓紝鍗曚綅 px
+ * @property {Boolean} disabled = [true|false] 鏄惁涓虹鐢ㄧ姸鎬侊紝榛樿涓� false
+ * @property {Boolean} readonly = [true|false] 鏄惁涓哄彧璇荤姸鎬侊紝榛樿涓� false
+ * @property {Boolean} allowHalf = [true|false] 鏄惁瀹炵幇鍗婃槦锛岄粯璁や负 false
+ * @property {Boolean} touchable = [true|false] 鏄惁鏀寔婊戝姩鎵嬪娍锛岄粯璁や负 true
+ * @event {Function} change uniRate 鐨� value 鏀瑰彉鏃惰Е鍙戜簨浠讹紝e={value:Number}
+ */
+
+ export default {
+ name: "UniRate",
+ props: {
+ isFill: {
+ // 鏄熸槦鐨勭被鍨嬶紝鏄惁闀傜┖
+ type: [Boolean, String],
+ default: true
+ },
+ color: {
+ // 鏄熸槦鏈�変腑鐨勯鑹�
+ type: String,
+ default: "#ececec"
+ },
+ activeColor: {
+ // 鏄熸槦閫変腑鐘舵�侀鑹�
+ type: String,
+ default: "#ffca3e"
+ },
+ disabledColor: {
+ // 鏄熸槦绂佺敤鐘舵�侀鑹�
+ type: String,
+ default: "#c0c0c0"
+ },
+ size: {
+ // 鏄熸槦鐨勫ぇ灏�
+ type: [Number, String],
+ default: 24
+ },
+ value: {
+ // 褰撳墠璇勫垎
+ type: [Number, String],
+ default: 0
+ },
+ modelValue: {
+ // 褰撳墠璇勫垎
+ type: [Number, String],
+ default: 0
+ },
+ max: {
+ // 鏈�澶ц瘎鍒�
+ type: [Number, String],
+ default: 5
+ },
+ margin: {
+ // 鏄熸槦鐨勯棿璺�
+ type: [Number, String],
+ default: 0
+ },
+ disabled: {
+ // 鏄惁鍙偣鍑�
+ type: [Boolean, String],
+ default: false
+ },
+ readonly: {
+ // 鏄惁鍙
+ type: [Boolean, String],
+ default: false
+ },
+ allowHalf: {
+ // 鏄惁鏄剧ず鍗婃槦
+ type: [Boolean, String],
+ default: false
+ },
+ touchable: {
+ // 鏄惁鏀寔婊戝姩鎵嬪娍
+ type: [Boolean, String],
+ default: true
+ }
+ },
+ data() {
+ return {
+ valueSync: "",
+ userMouseFristMove: true,
+ userRated: false,
+ userLastRate: 1
+ };
+ },
+ watch: {
+ value(newVal) {
+ this.valueSync = Number(newVal);
+ },
+ modelValue(newVal) {
+ this.valueSync = Number(newVal);
+ },
+ },
+ computed: {
+ stars() {
+ const value = this.valueSync ? this.valueSync : 0;
+ const starList = [];
+ const floorValue = Math.floor(value);
+ const ceilValue = Math.ceil(value);
+ for (let i = 0; i < this.max; i++) {
+ if (floorValue > i) {
+ starList.push({
+ activeWitch: "100%"
+ });
+ } else if (ceilValue - 1 === i) {
+ starList.push({
+ activeWitch: (value - floorValue) * 100 + "%"
+ });
+ } else {
+ starList.push({
+ activeWitch: "0"
+ });
+ }
+ }
+ return starList;
+ },
+
+ marginNumber() {
+ return Number(this.margin)
+ }
+ },
+ created() {
+ this.valueSync = Number(this.value || this.modelValue);
+ this._rateBoxLeft = 0
+ this._oldValue = null
+ },
+ mounted() {
+ setTimeout(() => {
+ this._getSize()
+ }, 100)
+ // #ifdef H5
+ this.PC = this.IsPC()
+ // #endif
+ },
+ methods: {
+ touchstart(e) {
+ // #ifdef H5
+ if (this.IsPC()) return
+ // #endif
+ if (this.readonly || this.disabled) return
+ const {
+ clientX,
+ screenX
+ } = e.changedTouches[0]
+ // TODO 鍋氫竴涓嬪吋瀹癸紝鍙湁 Nvue 涓嬫墠鏈� screenX锛屽叾浠栧钩鍙板紡 clientX
+ this._getRateCount(clientX || screenX)
+ },
+ touchmove(e) {
+ // #ifdef H5
+ if (this.IsPC()) return
+ // #endif
+ if (this.readonly || this.disabled || !this.touchable) return
+ const {
+ clientX,
+ screenX
+ } = e.changedTouches[0]
+ this._getRateCount(clientX || screenX)
+ },
+
+ /**
+ * 鍏煎 PC @tian
+ */
+
+ mousedown(e) {
+ // #ifdef H5
+ if (!this.IsPC()) return
+ if (this.readonly || this.disabled) return
+ const {
+ clientX,
+ } = e
+ this.userLastRate = this.valueSync
+ this._getRateCount(clientX)
+ this.userRated = true
+ // #endif
+ },
+ mousemove(e) {
+ // #ifdef H5
+ if (!this.IsPC()) return
+ if (this.userRated) return
+ if (this.userMouseFristMove) {
+ console.log('---mousemove----', this.valueSync);
+ this.userLastRate = this.valueSync
+ this.userMouseFristMove = false
+ }
+ if (this.readonly || this.disabled || !this.touchable) return
+ const {
+ clientX,
+ } = e
+ this._getRateCount(clientX)
+ // #endif
+ },
+ mouseleave(e) {
+ // #ifdef H5
+ if (!this.IsPC()) return
+ if (this.readonly || this.disabled || !this.touchable) return
+ if (this.userRated) {
+ this.userRated = false
+ return
+ }
+ this.valueSync = this.userLastRate
+ // #endif
+ },
+ // #ifdef H5
+ IsPC() {
+ var userAgentInfo = navigator.userAgent;
+ var Agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"];
+ var flag = true;
+ for (let v = 0; v < Agents.length - 1; v++) {
+ if (userAgentInfo.indexOf(Agents[v]) > 0) {
+ flag = false;
+ break;
+ }
+ }
+ return flag;
+ },
+ // #endif
+
+ /**
+ * 鑾峰彇鏄熸槦涓暟
+ */
+ _getRateCount(clientX) {
+ const _this = this;
+ this._getSize(function() {
+ const size = Number(_this.size)
+ if (isNaN(size)) {
+ return new Error('size 灞炴�у彧鑳借缃负鏁板瓧')
+ }
+ const rateMoveRange = clientX - _this._rateBoxLeft
+ let index = parseInt(rateMoveRange / (size + _this.marginNumber))
+ index = index < 0 ? 0 : index;
+ index = index > _this.max ? _this.max : index;
+ const range = parseInt(rateMoveRange - (size + _this.marginNumber) * index);
+ let value = 0;
+ if (_this._oldValue === index && !_this.PC) return;
+ _this._oldValue = index;
+ if (_this.allowHalf) {
+ if (range > (size / 2)) {
+ value = index + 1
+ } else {
+ value = index + 0.5
+ }
+ } else {
+ value = index + 1
+ }
+
+ value = Math.max(0.5, Math.min(value, _this.max))
+ _this.valueSync = value
+ _this._onChange()
+ })
+ },
+
+ /**
+ * 瑙﹀彂鍔ㄦ�佷慨鏀�
+ */
+ _onChange() {
+
+ this.$emit("input", this.valueSync);
+ this.$emit("update:modelValue", this.valueSync);
+ this.$emit("change", {
+ value: this.valueSync
+ });
+ },
+ /**
+ * 鑾峰彇鏄熸槦璺濈灞忓箷宸︿晶璺濈
+ */
+ _getSize(fn) {
+ // #ifndef APP-NVUE
+ uni.createSelectorQuery()
+ .in(this)
+ .select('.uni-rate')
+ .boundingClientRect()
+ .exec(ret => {
+ if (ret) {
+ this._rateBoxLeft = ret[0].left
+ fn && fn()
+ }
+ })
+ // #endif
+ // #ifdef APP-NVUE
+ dom.getComponentRect(this.$refs['uni-rate'], (ret) => {
+ const size = ret.size
+ if (size) {
+ this._rateBoxLeft = size.left
+ fn && fn()
+ }
+ })
+ // #endif
+ }
+ }
+ };
+</script>
+
+<style lang="scss">
+ .uni-rate {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ line-height: 1;
+ font-size: 0;
+ flex-direction: row;
+ /* #ifdef H5 */
+ cursor: pointer;
+ /* #endif */
+ }
+
+ .uni-rate__icon {
+ position: relative;
+ line-height: 1;
+ font-size: 0;
+ }
+
+ .uni-rate__icon-on {
+ overflow: hidden;
+ position: absolute;
+ top: 0;
+ left: 0;
+ line-height: 1;
+ text-align: left;
+ }
+
+ .uni-cursor-not-allowed {
+ /* #ifdef H5 */
+ cursor: not-allowed !important;
+ /* #endif */
+ }
+</style>
diff --git a/app/uni_modules/uni-rate/package.json b/app/uni_modules/uni-rate/package.json
new file mode 100644
index 0000000..64e8e33
--- /dev/null
+++ b/app/uni_modules/uni-rate/package.json
@@ -0,0 +1,88 @@
+{
+ "id": "uni-rate",
+ "displayName": "uni-rate 璇勫垎",
+ "version": "1.3.1",
+ "description": "Rate 璇勫垎缁勪欢锛屽彲鑷畾涔夎瘎鍒嗘槦鏄熷浘鏍囩殑澶у皬銆侀棿闅斻�佽瘎鍒嗘暟銆�",
+ "keywords": [
+ "uni-ui",
+ "uniui",
+ "璇勫垎"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "鍓嶇缁勪欢",
+ "閫氱敤缁勪欢"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": [
+ "uni-scss",
+ "uni-icons"
+ ],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "u",
+ "鑱旂洘": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
diff --git a/app/uni_modules/uni-rate/readme.md b/app/uni_modules/uni-rate/readme.md
new file mode 100644
index 0000000..eae7b5c
--- /dev/null
+++ b/app/uni_modules/uni-rate/readme.md
@@ -0,0 +1,12 @@
+
+
+## Rate 璇勫垎
+> **缁勪欢鍚嶏細uni-rate**
+> 浠g爜鍧楋細 `uRate`
+> 鍏宠仈缁勪欢锛歚uni-icons`
+
+
+璇勫垎缁勪欢锛屽鐢ㄤ簬璐拱鍟嗗搧鍚庯紝瀵瑰晢鍝佽繘琛岃瘎浠风瓑鍦烘櫙
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-rate)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
\ No newline at end of file
diff --git a/app/uni_modules/uni-row/changelog.md b/app/uni_modules/uni-row/changelog.md
new file mode 100644
index 0000000..5b465bc
--- /dev/null
+++ b/app/uni_modules/uni-row/changelog.md
@@ -0,0 +1,10 @@
+## 1.0.0锛�2021-11-19锛�
+- 浼樺寲 缁勪欢UI锛屽苟鎻愪緵璁捐璧勬簮锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 鏂囨。杩佺Щ锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/uni-row](https://uniapp.dcloud.io/component/uniui/uni-row)
+## 0.1.0锛�2021-07-13锛�
+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤簐ue3椤圭洰锛岃瑙� [uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+## 0.0.4锛�2021-05-12锛�
+- 鏂板 缁勪欢绀轰緥鍦板潃
+## 0.0.3锛�2021-02-05锛�
+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
+- 鏂板uni-row缁勪欢
diff --git a/app/uni_modules/uni-row/components/uni-col/uni-col.vue b/app/uni_modules/uni-row/components/uni-col/uni-col.vue
new file mode 100644
index 0000000..d5f3728
--- /dev/null
+++ b/app/uni_modules/uni-row/components/uni-col/uni-col.vue
@@ -0,0 +1,317 @@
+<template>
+ <!-- #ifndef APP-NVUE -->
+ <view :class="['uni-col', sizeClass, pointClassList]" :style="{
+ paddingLeft:`${Number(gutter)}rpx`,
+ paddingRight:`${Number(gutter)}rpx`,
+ }">
+ <slot></slot>
+ </view>
+ <!-- #endif -->
+ <!-- #ifdef APP-NVUE -->
+ <!-- 鍦╪vue涓婏紝绫诲悕鏍峰紡涓嶇敓鏁堬紝鎹负style -->
+ <!-- 璁剧疆right姝e�煎け鏁堬紝璁剧疆 left 璐熷�� -->
+ <view :class="['uni-col']" :style="{
+ paddingLeft:`${Number(gutter)}rpx`,
+ paddingRight:`${Number(gutter)}rpx`,
+ width:`${nvueWidth}rpx`,
+ position:'relative',
+ marginLeft:`${marginLeft}rpx`,
+ left:`${right === 0 ? left : -right}rpx`
+ }">
+ <slot></slot>
+ </view>
+ <!-- #endif -->
+</template>
+
+<script>
+ /**
+ * Col 甯冨眬-鍒�
+ * @description 鎼厤uni-row浣跨敤锛屾瀯寤哄竷灞�銆�
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=3958
+ *
+ * @property {span} type = Number 鏍呮牸鍗犳嵁鐨勫垪鏁�
+ * 榛樿 24
+ * @property {offset} type = Number 鏍呮牸宸︿晶鐨勯棿闅旀牸鏁�
+ * @property {push} type = Number 鏍呮牸鍚戝彸绉诲姩鏍兼暟
+ * @property {pull} type = Number 鏍呮牸鍚戝乏绉诲姩鏍兼暟
+ * @property {xs} type = [Number, Object] <768px 鍝嶅簲寮忔爡鏍兼暟鎴栬�呮爡鏍煎睘鎬у璞�
+ * @description Number鏃惰〃绀哄湪姝ゅ睆骞曞搴︿笅锛屾爡鏍煎崰鎹殑鍒楁暟銆侽bject鏃跺彲閰嶇疆澶氫釜鎻忚堪{span: 4, offset: 4}
+ * @property {sm} type = [Number, Object] 鈮�768px 鍝嶅簲寮忔爡鏍兼暟鎴栬�呮爡鏍煎睘鎬у璞�
+ * @description Number鏃惰〃绀哄湪姝ゅ睆骞曞搴︿笅锛屾爡鏍煎崰鎹殑鍒楁暟銆侽bject鏃跺彲閰嶇疆澶氫釜鎻忚堪{span: 4, offset: 4}
+ * @property {md} type = [Number, Object] 鈮�992px 鍝嶅簲寮忔爡鏍兼暟鎴栬�呮爡鏍煎睘鎬у璞�
+ * @description Number鏃惰〃绀哄湪姝ゅ睆骞曞搴︿笅锛屾爡鏍煎崰鎹殑鍒楁暟銆侽bject鏃跺彲閰嶇疆澶氫釜鎻忚堪{span: 4, offset: 4}
+ * @property {lg} type = [Number, Object] 鈮�1200px 鍝嶅簲寮忔爡鏍兼暟鎴栬�呮爡鏍煎睘鎬у璞�
+ * @description Number鏃惰〃绀哄湪姝ゅ睆骞曞搴︿笅锛屾爡鏍煎崰鎹殑鍒楁暟銆侽bject鏃跺彲閰嶇疆澶氫釜鎻忚堪{span: 4, offset: 4}
+ * @property {xl} type = [Number, Object] 鈮�1920px 鍝嶅簲寮忔爡鏍兼暟鎴栬�呮爡鏍煎睘鎬у璞�
+ * @description Number鏃惰〃绀哄湪姝ゅ睆骞曞搴︿笅锛屾爡鏍煎崰鎹殑鍒楁暟銆侽bject鏃跺彲閰嶇疆澶氫釜鎻忚堪{span: 4, offset: 4}
+ */
+ const ComponentClass = 'uni-col';
+
+ // -1 榛樿鍊硷紝鍥犱负鍦ㄥ井淇″皬绋嬪簭绔彧缁橬umber浼氭湁榛樿鍊�0
+ export default {
+ name: 'uniCol',
+ // #ifdef MP-WEIXIN
+ options: {
+ virtualHost: true // 鍦ㄥ井淇″皬绋嬪簭涓皢缁勪欢鑺傜偣娓叉煋涓鸿櫄鎷熻妭鐐癸紝鏇村姞鎺ヨ繎Vue缁勪欢鐨勮〃鐜�
+ },
+ // #endif
+ props: {
+ span: {
+ type: Number,
+ default: 24
+ },
+ offset: {
+ type: Number,
+ default: -1
+ },
+ pull: {
+ type: Number,
+ default: -1
+ },
+ push: {
+ type: Number,
+ default: -1
+ },
+ xs: [Number, Object],
+ sm: [Number, Object],
+ md: [Number, Object],
+ lg: [Number, Object],
+ xl: [Number, Object]
+ },
+ data() {
+ return {
+ gutter: 0,
+ sizeClass: '',
+ parentWidth: 0,
+ nvueWidth: 0,
+ marginLeft: 0,
+ right: 0,
+ left: 0
+ }
+ },
+ created() {
+ // 瀛楄妭灏忕▼搴忎腑锛屽湪computed涓鍙�$parent涓簎ndefined
+ let parent = this.$parent;
+
+ while (parent && parent.$options.componentName !== 'uniRow') {
+ parent = parent.$parent;
+ }
+
+ this.updateGutter(parent.gutter)
+ parent.$watch('gutter', (gutter) => {
+ this.updateGutter(gutter)
+ })
+
+ // #ifdef APP-NVUE
+ this.updateNvueWidth(parent.width)
+ parent.$watch('width', (width) => {
+ this.updateNvueWidth(width)
+ })
+ // #endif
+ },
+ computed: {
+ sizeList() {
+ let {
+ span,
+ offset,
+ pull,
+ push
+ } = this;
+
+ return {
+ span,
+ offset,
+ pull,
+ push
+ }
+ },
+ // #ifndef APP-NVUE
+ pointClassList() {
+ let classList = [];
+
+ ['xs', 'sm', 'md', 'lg', 'xl'].forEach(point => {
+ const props = this[point];
+ if (typeof props === 'number') {
+ classList.push(`${ComponentClass}-${point}-${props}`)
+ } else if (typeof props === 'object' && props) {
+ Object.keys(props).forEach(pointProp => {
+ classList.push(
+ pointProp === 'span' ?
+ `${ComponentClass}-${point}-${props[pointProp]}` :
+ `${ComponentClass}-${point}-${pointProp}-${props[pointProp]}`
+ )
+ })
+ }
+ });
+
+ // 鏀粯瀹濆皬绋嬪簭浣跨敤 :class=[ ['a','b'] ]锛屾覆鏌撻敊璇�
+ return classList.join(' ');
+ }
+ // #endif
+ },
+ methods: {
+ updateGutter(parentGutter) {
+ parentGutter = Number(parentGutter);
+ if (!isNaN(parentGutter)) {
+ this.gutter = parentGutter / 2
+ }
+ },
+ // #ifdef APP-NVUE
+ updateNvueWidth(width) {
+ // 鐢ㄤ簬鍦╪vue绔紝span锛宱ffset锛宲ull锛宲ush鐨勮绠�
+ this.parentWidth = width;
+ ['span', 'offset', 'pull', 'push'].forEach(size => {
+ const curSize = this[size];
+ if ((curSize || curSize === 0) && curSize !== -1) {
+ let RPX = 1 / 24 * curSize * width
+ RPX = Number(RPX);
+ switch (size) {
+ case 'span':
+ this.nvueWidth = RPX
+ break;
+ case 'offset':
+ this.marginLeft = RPX
+ break;
+ case 'pull':
+ this.right = RPX
+ break;
+ case 'push':
+ this.left = RPX
+ break;
+ }
+ }
+ });
+ }
+ // #endif
+ },
+ watch: {
+ sizeList: {
+ immediate: true,
+ handler(newVal) {
+ // #ifndef APP-NVUE
+ let classList = [];
+ for (let size in newVal) {
+ const curSize = newVal[size];
+ if ((curSize || curSize === 0) && curSize !== -1) {
+ classList.push(
+ size === 'span' ?
+ `${ComponentClass}-${curSize}` :
+ `${ComponentClass}-${size}-${curSize}`
+ )
+ }
+ }
+ // 鏀粯瀹濆皬绋嬪簭浣跨敤 :class=[ ['a','b'] ]锛屾覆鏌撻敊璇�
+ this.sizeClass = classList.join(' ');
+ // #endif
+ // #ifdef APP-NVUE
+ this.updateNvueWidth(this.parentWidth);
+ // #endif
+ }
+ }
+ }
+ }
+</script>
+
+<style lang='scss' >
+ /* breakpoints */
+ $--sm: 768px !default;
+ $--md: 992px !default;
+ $--lg: 1200px !default;
+ $--xl: 1920px !default;
+
+ $breakpoints: ('xs' : (max-width: $--sm - 1),
+ 'sm' : (min-width: $--sm),
+ 'md' : (min-width: $--md),
+ 'lg' : (min-width: $--lg),
+ 'xl' : (min-width: $--xl));
+
+ $layout-namespace: ".uni-";
+ $col: $layout-namespace+"col";
+
+ @function getSize($size) {
+ /* TODO 1/24 * $size * 100 * 1%; 浣跨敤璁$畻鍚庣殑鍊硷紝涓轰簡瑙e喅 vue3 鎺у埗鍙版姤閿� */
+ @return 0.04166666666 * $size * 100 * 1%;
+ }
+
+ @mixin res($key, $map:$breakpoints) {
+ @if map-has-key($map, $key) {
+ @media screen and #{inspect(map-get($map,$key))} {
+ @content;
+ }
+ }
+
+ @else {
+ @warn "Undeinfed point: `#{$key}`";
+ }
+ }
+
+ /* #ifndef APP-NVUE */
+ #{$col} {
+ float: left;
+ box-sizing: border-box;
+ }
+
+ #{$col}-0 {
+ /* #ifdef APP-NVUE */
+ width: 0;
+ height: 0;
+ margin-top: 0;
+ margin-right: 0;
+ margin-bottom: 0;
+ margin-left: 0;
+ /* #endif */
+ /* #ifndef APP-NVUE */
+ display: none;
+ /* #endif */
+ }
+
+ @for $i from 0 through 24 {
+ #{$col}-#{$i} {
+ width: getSize($i);
+ }
+
+ #{$col}-offset-#{$i} {
+ margin-left: getSize($i);
+ }
+
+ #{$col}-pull-#{$i} {
+ position: relative;
+ right: getSize($i);
+ }
+
+ #{$col}-push-#{$i} {
+ position: relative;
+ left: getSize($i);
+ }
+ }
+
+ @each $point in map-keys($breakpoints) {
+ @include res($point) {
+ #{$col}-#{$point}-0 {
+ display: none;
+ }
+
+ @for $i from 0 through 24 {
+ #{$col}-#{$point}-#{$i} {
+ width: getSize($i);
+ }
+
+ #{$col}-#{$point}-offset-#{$i} {
+ margin-left: getSize($i);
+ }
+
+ #{$col}-#{$point}-pull-#{$i} {
+ position: relative;
+ right: getSize($i);
+ }
+
+ #{$col}-#{$point}-push-#{$i} {
+ position: relative;
+ left: getSize($i);
+ }
+ }
+ }
+ }
+
+ /* #endif */
+</style>
diff --git a/app/uni_modules/uni-row/components/uni-row/uni-row.vue b/app/uni_modules/uni-row/components/uni-row/uni-row.vue
new file mode 100644
index 0000000..c7d9370
--- /dev/null
+++ b/app/uni_modules/uni-row/components/uni-row/uni-row.vue
@@ -0,0 +1,190 @@
+<template>
+ <view :class="[ 'uni-row', typeClass , justifyClass, alignClass, ]" :style="{
+ marginLeft:`${Number(marginValue)}rpx`,
+ marginRight:`${Number(marginValue)}rpx`,
+ }">
+ <slot></slot>
+ </view>
+</template>
+
+<script>
+ const ComponentClass = 'uni-row';
+ const modifierSeparator = '--';
+ /**
+ * Row 甯冨眬-琛�
+ * @description 娴佸紡鏍呮牸绯荤粺锛岄殢鐫�灞忓箷鎴栬鍙e垎涓� 24 浠斤紝鍙互杩呴�熺畝渚垮湴鍒涘缓甯冨眬銆�
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=3958
+ *
+ * @property {gutter} type = Number 鏍呮牸闂撮殧
+ * @property {justify} type = String flex 甯冨眬涓嬬殑姘村钩鎺掑垪鏂瑰紡
+ * 鍙�� start/end/center/space-around/space-between start
+ * 榛樿鍊� start
+ * @property {align} type = String flex 甯冨眬涓嬬殑鍨傜洿鎺掑垪鏂瑰紡
+ * 鍙�� top/middle/bottom
+ * 榛樿鍊� top
+ * @property {width} type = String|Number nvue涓嬮渶瑕佽嚜琛岄厤缃搴︾敤浜庤绠�
+ * 榛樿鍊� 750
+ */
+
+
+ export default {
+ name: 'uniRow',
+ componentName: 'uniRow',
+ // #ifdef MP-WEIXIN
+ options: {
+ virtualHost: true // 鍦ㄥ井淇″皬绋嬪簭涓皢缁勪欢鑺傜偣娓叉煋涓鸿櫄鎷熻妭鐐癸紝鏇村姞鎺ヨ繎Vue缁勪欢鐨勮〃鐜帮紝鍙娇鐢╢lex甯冨眬
+ },
+ // #endif
+ props: {
+ type: String,
+ gutter: Number,
+ justify: {
+ type: String,
+ default: 'start'
+ },
+ align: {
+ type: String,
+ default: 'top'
+ },
+ // nvue濡傛灉浣跨敤span绛夊睘鎬э紝闇�瑕侀厤缃搴�
+ width: {
+ type: [String, Number],
+ default: 750
+ }
+ },
+ created() {
+ // #ifdef APP-NVUE
+ this.type = 'flex';
+ // #endif
+ },
+ computed: {
+ marginValue() {
+ // #ifndef APP-NVUE
+ if (this.gutter) {
+ return -(this.gutter / 2);
+ }
+ // #endif
+ return 0;
+ },
+ typeClass() {
+ return this.type === 'flex' ? `${ComponentClass + modifierSeparator}flex` : '';
+ },
+ justifyClass() {
+ return this.justify !== 'start' ? `${ComponentClass + modifierSeparator}flex-justify-${this.justify}` : ''
+ },
+ alignClass() {
+ return this.align !== 'top' ? `${ComponentClass + modifierSeparator}flex-align-${this.align}` : ''
+ }
+ }
+ };
+</script>
+
+<style lang="scss">
+ $layout-namespace: ".uni-";
+ $row:$layout-namespace+"row";
+ $modifier-separator: "--";
+
+ @mixin utils-clearfix {
+ $selector: &;
+
+ @at-root {
+
+ /* #ifndef APP-NVUE */
+ #{$selector}::before,
+ #{$selector}::after {
+ display: table;
+ content: "";
+ }
+
+ #{$selector}::after {
+ clear: both;
+ }
+
+ /* #endif */
+ }
+
+ }
+
+ @mixin utils-flex ($direction: row) {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: $direction;
+ }
+
+ @mixin set-flex($state) {
+ @at-root &-#{$state} {
+ @content
+ }
+ }
+
+ #{$row} {
+ position: relative;
+ flex-direction: row;
+
+ /* #ifdef APP-NVUE */
+ flex: 1;
+ /* #endif */
+
+ /* #ifndef APP-NVUE */
+ box-sizing: border-box;
+ /* #endif */
+
+ // 闈瀗vue浣跨敤float甯冨眬
+ @include utils-clearfix;
+
+ // 鍦≦Q銆佸瓧鑺傘�佺櫨搴﹀皬绋嬪簭骞冲彴锛岀紪璇戝悗浣跨敤shadow dom锛屼笉鍙娇鐢╢lex甯冨眬锛屼娇鐢╢loat
+ @at-root {
+
+ /* #ifndef MP-QQ || MP-TOUTIAO || MP-BAIDU */
+ &#{$modifier-separator}flex {
+ @include utils-flex;
+ flex-wrap: wrap;
+ flex: 1;
+
+ &:before,
+ &:after {
+ /* #ifndef APP-NVUE */
+ display: none;
+ /* #endif */
+ }
+
+ @include set-flex(justify-center) {
+ justify-content: center;
+ }
+
+ @include set-flex(justify-end) {
+ justify-content: flex-end;
+ }
+
+ @include set-flex(justify-space-between) {
+ justify-content: space-between;
+ }
+
+ @include set-flex(justify-space-around) {
+ justify-content: space-around;
+ }
+
+ @include set-flex(align-middle) {
+ align-items: center;
+ }
+
+ @include set-flex(align-bottom) {
+ align-items: flex-end;
+ }
+ }
+
+ /* #endif */
+ }
+
+ }
+
+ // 瀛楄妭銆丵Q閰嶇疆鍚庝笉鐢熸晥
+ // 姝ゅ鐢ㄦ硶鏃犳硶浣跨敤
+ /* #ifdef MP-WEIXIN || MP-TOUTIAO || MP-QQ */
+ :host {
+ display: block;
+ }
+
+ /* #endif */
+</style>
diff --git a/app/uni_modules/uni-row/package.json b/app/uni_modules/uni-row/package.json
new file mode 100644
index 0000000..3f52fa6
--- /dev/null
+++ b/app/uni_modules/uni-row/package.json
@@ -0,0 +1,87 @@
+{
+ "id": "uni-row",
+ "displayName": "uni-row 甯冨眬-琛�",
+ "version": "1.0.0",
+ "description": "娴佸紡鏍呮牸绯荤粺锛岄殢鐫�灞忓箷鎴栬鍙e垎涓� 24 浠斤紝鍙互杩呴�熺畝渚垮湴鍒涘缓甯冨眬銆�",
+ "keywords": [
+ "uni-ui",
+ "uniui",
+ "鏍呮牸",
+ "甯冨眬",
+ "layout"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "鍓嶇缁勪欢",
+ "閫氱敤缁勪欢"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": ["uni-scss"],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "u",
+ "鑱旂洘": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "u"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/uni_modules/uni-row/readme.md b/app/uni_modules/uni-row/readme.md
new file mode 100644
index 0000000..3c9c8b9
--- /dev/null
+++ b/app/uni_modules/uni-row/readme.md
@@ -0,0 +1,10 @@
+## Layout 甯冨眬
+
+> **缁勪欢鍚� uni-row銆乽ni-col**
+> 浠g爜鍧楋細 `uRow`銆乣uCol`
+
+
+娴佸紡鏍呮牸绯荤粺锛岄殢鐫�灞忓箷鎴栬鍙e垎涓� 24 浠斤紝鍙互杩呴�熺畝渚垮湴鍒涘缓甯冨眬銆�
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-row)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
\ No newline at end of file
diff --git a/app/uni_modules/uni-scss/changelog.md b/app/uni_modules/uni-scss/changelog.md
new file mode 100644
index 0000000..b863bb0
--- /dev/null
+++ b/app/uni_modules/uni-scss/changelog.md
@@ -0,0 +1,8 @@
+## 1.0.3锛�2022-01-21锛�
+- 浼樺寲 缁勪欢绀轰緥
+## 1.0.2锛�2021-11-22锛�
+- 淇 / 绗﹀彿鍦� vue 涓嶅悓鐗堟湰鍏煎闂寮曡捣鐨勬姤閿欓棶棰�
+## 1.0.1锛�2021-11-22锛�
+- 淇 vue3涓璼css璇硶鍏煎闂
+## 1.0.0锛�2021-11-18锛�
+- init
diff --git a/app/uni_modules/uni-scss/index.scss b/app/uni_modules/uni-scss/index.scss
new file mode 100644
index 0000000..1744a5f
--- /dev/null
+++ b/app/uni_modules/uni-scss/index.scss
@@ -0,0 +1 @@
+@import './styles/index.scss';
diff --git a/app/uni_modules/uni-scss/package.json b/app/uni_modules/uni-scss/package.json
new file mode 100644
index 0000000..7cc0ccb
--- /dev/null
+++ b/app/uni_modules/uni-scss/package.json
@@ -0,0 +1,82 @@
+{
+ "id": "uni-scss",
+ "displayName": "uni-scss 杈呭姪鏍峰紡",
+ "version": "1.0.3",
+ "description": "uni-sass鏄痷ni-ui鎻愪緵鐨勪竴濂楀叏灞�鏍峰紡 锛岄�氳繃涓�浜涚畝鍗曠殑绫诲悕鍜宻ass鍙橀噺锛屽疄鐜扮畝鍗曠殑椤甸潰甯冨眬鎿嶄綔锛屾瘮濡傞鑹层�佽竟璺濄�佸渾瑙掔瓑銆�",
+ "keywords": [
+ "uni-scss",
+ "uni-ui",
+ "杈呭姪鏍峰紡"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": "^3.1.0"
+ },
+ "dcloudext": {
+ "category": [
+ "JS SDK",
+ "閫氱敤 SDK"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": [],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "u"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "n",
+ "鑱旂洘": "n"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
diff --git a/app/uni_modules/uni-scss/readme.md b/app/uni_modules/uni-scss/readme.md
new file mode 100644
index 0000000..b7d1c25
--- /dev/null
+++ b/app/uni_modules/uni-scss/readme.md
@@ -0,0 +1,4 @@
+`uni-sass` 鏄� `uni-ui`鎻愪緵鐨勪竴濂楀叏灞�鏍峰紡 锛岄�氳繃涓�浜涚畝鍗曠殑绫诲悕鍜宍sass`鍙橀噺锛屽疄鐜扮畝鍗曠殑椤甸潰甯冨眬鎿嶄綔锛屾瘮濡傞鑹层�佽竟璺濄�佸渾瑙掔瓑銆�
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-sass)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
\ No newline at end of file
diff --git a/app/uni_modules/uni-scss/styles/index.scss b/app/uni_modules/uni-scss/styles/index.scss
new file mode 100644
index 0000000..ffac4fe
--- /dev/null
+++ b/app/uni_modules/uni-scss/styles/index.scss
@@ -0,0 +1,7 @@
+@import './setting/_variables.scss';
+@import './setting/_border.scss';
+@import './setting/_color.scss';
+@import './setting/_space.scss';
+@import './setting/_radius.scss';
+@import './setting/_text.scss';
+@import './setting/_styles.scss';
diff --git a/app/uni_modules/uni-scss/styles/setting/_border.scss b/app/uni_modules/uni-scss/styles/setting/_border.scss
new file mode 100644
index 0000000..12a11c3
--- /dev/null
+++ b/app/uni_modules/uni-scss/styles/setting/_border.scss
@@ -0,0 +1,3 @@
+.uni-border {
+ border: 1px $uni-border-1 solid;
+}
\ No newline at end of file
diff --git a/app/uni_modules/uni-scss/styles/setting/_color.scss b/app/uni_modules/uni-scss/styles/setting/_color.scss
new file mode 100644
index 0000000..1ededd9
--- /dev/null
+++ b/app/uni_modules/uni-scss/styles/setting/_color.scss
@@ -0,0 +1,66 @@
+
+// TODO 鏆傛椂涓嶉渶瑕� class 锛岄渶瑕佺敤鎴蜂娇鐢ㄥ彉閲忓疄鐜� 锛屽鏋滀娇鐢ㄧ被鍚嶅叾瀹炲苟涓嶆帹鑽�
+// @mixin get-styles($k,$c) {
+// @if $k == size or $k == weight{
+// font-#{$k}:#{$c}
+// }@else{
+// #{$k}:#{$c}
+// }
+// }
+$uni-ui-color:(
+ // 涓昏壊
+ primary: $uni-primary,
+ primary-disable: $uni-primary-disable,
+ primary-light: $uni-primary-light,
+ // 杈呭姪鑹�
+ success: $uni-success,
+ success-disable: $uni-success-disable,
+ success-light: $uni-success-light,
+ warning: $uni-warning,
+ warning-disable: $uni-warning-disable,
+ warning-light: $uni-warning-light,
+ error: $uni-error,
+ error-disable: $uni-error-disable,
+ error-light: $uni-error-light,
+ info: $uni-info,
+ info-disable: $uni-info-disable,
+ info-light: $uni-info-light,
+ // 涓�ц壊
+ main-color: $uni-main-color,
+ base-color: $uni-base-color,
+ secondary-color: $uni-secondary-color,
+ extra-color: $uni-extra-color,
+ // 鑳屾櫙鑹�
+ bg-color: $uni-bg-color,
+ // 杈规棰滆壊
+ border-1: $uni-border-1,
+ border-2: $uni-border-2,
+ border-3: $uni-border-3,
+ border-4: $uni-border-4,
+ // 榛戣壊
+ black:$uni-black,
+ // 鐧借壊
+ white:$uni-white,
+ // 閫忔槑
+ transparent:$uni-transparent
+) !default;
+@each $key, $child in $uni-ui-color {
+ .uni-#{"" + $key} {
+ color: $child;
+ }
+ .uni-#{"" + $key}-bg {
+ background-color: $child;
+ }
+}
+.uni-shadow-sm {
+ box-shadow: $uni-shadow-sm;
+}
+.uni-shadow-base {
+ box-shadow: $uni-shadow-base;
+}
+.uni-shadow-lg {
+ box-shadow: $uni-shadow-lg;
+}
+.uni-mask {
+ background-color:$uni-mask;
+}
diff --git a/app/uni_modules/uni-scss/styles/setting/_radius.scss b/app/uni_modules/uni-scss/styles/setting/_radius.scss
new file mode 100644
index 0000000..9a0428b
--- /dev/null
+++ b/app/uni_modules/uni-scss/styles/setting/_radius.scss
@@ -0,0 +1,55 @@
+@mixin radius($r,$d:null ,$important: false){
+ $radius-value:map-get($uni-radius, $r) if($important, !important, null);
+ // Key exists within the $uni-radius variable
+ @if (map-has-key($uni-radius, $r) and $d){
+ @if $d == t {
+ border-top-left-radius:$radius-value;
+ border-top-right-radius:$radius-value;
+ }@else if $d == r {
+ border-top-right-radius:$radius-value;
+ border-bottom-right-radius:$radius-value;
+ }@else if $d == b {
+ border-bottom-left-radius:$radius-value;
+ border-bottom-right-radius:$radius-value;
+ }@else if $d == l {
+ border-top-left-radius:$radius-value;
+ border-bottom-left-radius:$radius-value;
+ }@else if $d == tl {
+ border-top-left-radius:$radius-value;
+ }@else if $d == tr {
+ border-top-right-radius:$radius-value;
+ }@else if $d == br {
+ border-bottom-right-radius:$radius-value;
+ }@else if $d == bl {
+ border-bottom-left-radius:$radius-value;
+ }
+ }@else{
+ border-radius:$radius-value;
+ }
+}
+
+@each $key, $child in $uni-radius {
+ @if($key){
+ .uni-radius-#{"" + $key} {
+ @include radius($key)
+ }
+ }@else{
+ .uni-radius {
+ @include radius($key)
+ }
+ }
+}
+
+@each $direction in t, r, b, l,tl, tr, br, bl {
+ @each $key, $child in $uni-radius {
+ @if($key){
+ .uni-radius-#{"" + $direction}-#{"" + $key} {
+ @include radius($key,$direction,false)
+ }
+ }@else{
+ .uni-radius-#{$direction} {
+ @include radius($key,$direction,false)
+ }
+ }
+ }
+}
diff --git a/app/uni_modules/uni-scss/styles/setting/_space.scss b/app/uni_modules/uni-scss/styles/setting/_space.scss
new file mode 100644
index 0000000..3c89528
--- /dev/null
+++ b/app/uni_modules/uni-scss/styles/setting/_space.scss
@@ -0,0 +1,56 @@
+
+@mixin fn($space,$direction,$size,$n) {
+ @if $n {
+ #{$space}-#{$direction}: #{$size*$uni-space-root}px
+ } @else {
+ #{$space}-#{$direction}: #{-$size*$uni-space-root}px
+ }
+}
+@mixin get-styles($direction,$i,$space,$n){
+ @if $direction == t {
+ @include fn($space, top,$i,$n);
+ }
+ @if $direction == r {
+ @include fn($space, right,$i,$n);
+ }
+ @if $direction == b {
+ @include fn($space, bottom,$i,$n);
+ }
+ @if $direction == l {
+ @include fn($space, left,$i,$n);
+ }
+ @if $direction == x {
+ @include fn($space, left,$i,$n);
+ @include fn($space, right,$i,$n);
+ }
+ @if $direction == y {
+ @include fn($space, top,$i,$n);
+ @include fn($space, bottom,$i,$n);
+ }
+ @if $direction == a {
+ @if $n {
+ #{$space}:#{$i*$uni-space-root}px;
+ } @else {
+ #{$space}:#{-$i*$uni-space-root}px;
+ }
+ }
+}
+
+@each $orientation in m,p {
+ $space: margin;
+ @if $orientation == m {
+ $space: margin;
+ } @else {
+ $space: padding;
+ }
+ @for $i from 0 through 16 {
+ @each $direction in t, r, b, l, x, y, a {
+ .uni-#{$orientation}#{$direction}-#{$i} {
+ @include get-styles($direction,$i,$space,true);
+ }
+ .uni-#{$orientation}#{$direction}-n#{$i} {
+ @include get-styles($direction,$i,$space,false);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/uni_modules/uni-scss/styles/setting/_styles.scss b/app/uni_modules/uni-scss/styles/setting/_styles.scss
new file mode 100644
index 0000000..689afec
--- /dev/null
+++ b/app/uni_modules/uni-scss/styles/setting/_styles.scss
@@ -0,0 +1,167 @@
+/* #ifndef APP-NVUE */
+
+$-color-white:#fff;
+$-color-black:#000;
+@mixin base-style($color) {
+ color: #fff;
+ background-color: $color;
+ border-color: mix($-color-black, $color, 8%);
+ &:not([hover-class]):active {
+ background: mix($-color-black, $color, 10%);
+ border-color: mix($-color-black, $color, 20%);
+ color: $-color-white;
+ outline: none;
+ }
+}
+@mixin is-color($color) {
+ @include base-style($color);
+ &[loading] {
+ @include base-style($color);
+ &::before {
+ margin-right:5px;
+ }
+ }
+ &[disabled] {
+ &,
+ &[loading],
+ &:not([hover-class]):active {
+ color: $-color-white;
+ border-color: mix(darken($color,10%), $-color-white);
+ background-color: mix($color, $-color-white);
+ }
+ }
+
+}
+@mixin base-plain-style($color) {
+ color:$color;
+ background-color: mix($-color-white, $color, 90%);
+ border-color: mix($-color-white, $color, 70%);
+ &:not([hover-class]):active {
+ background: mix($-color-white, $color, 80%);
+ color: $color;
+ outline: none;
+ border-color: mix($-color-white, $color, 50%);
+ }
+}
+@mixin is-plain($color){
+ &[plain] {
+ @include base-plain-style($color);
+ &[loading] {
+ @include base-plain-style($color);
+ &::before {
+ margin-right:5px;
+ }
+ }
+ &[disabled] {
+ &,
+ &:active {
+ color: mix($-color-white, $color, 40%);
+ background-color: mix($-color-white, $color, 90%);
+ border-color: mix($-color-white, $color, 80%);
+ }
+ }
+ }
+}
+
+
+.uni-btn {
+ margin: 5px;
+ color: #393939;
+ border:1px solid #ccc;
+ font-size: 16px;
+ font-weight: 200;
+ background-color: #F9F9F9;
+ // TODO 鏆傛椂澶勭悊杈规闅愯棌涓�杈圭殑闂
+ overflow: visible;
+ &::after{
+ border: none;
+ }
+
+ &:not([type]),&[type=default] {
+ color: #999;
+ &[loading] {
+ background: none;
+ &::before {
+ margin-right:5px;
+ }
+ }
+
+
+
+ &[disabled]{
+ color: mix($-color-white, #999, 60%);
+ &,
+ &[loading],
+ &:active {
+ color: mix($-color-white, #999, 60%);
+ background-color: mix($-color-white,$-color-black , 98%);
+ border-color: mix($-color-white, #999, 85%);
+ }
+ }
+
+ &[plain] {
+ color: #999;
+ background: none;
+ border-color: $uni-border-1;
+ &:not([hover-class]):active {
+ background: none;
+ color: mix($-color-white, $-color-black, 80%);
+ border-color: mix($-color-white, $-color-black, 90%);
+ outline: none;
+ }
+ &[disabled]{
+ &,
+ &[loading],
+ &:active {
+ background: none;
+ color: mix($-color-white, #999, 60%);
+ border-color: mix($-color-white, #999, 85%);
+ }
+ }
+ }
+ }
+
+ &:not([hover-class]):active {
+ color: mix($-color-white, $-color-black, 50%);
+ }
+
+ &[size=mini] {
+ font-size: 16px;
+ font-weight: 200;
+ border-radius: 8px;
+ }
+
+
+
+ &.uni-btn-small {
+ font-size: 14px;
+ }
+ &.uni-btn-mini {
+ font-size: 12px;
+ }
+
+ &.uni-btn-radius {
+ border-radius: 999px;
+ }
+ &[type=primary] {
+ @include is-color($uni-primary);
+ @include is-plain($uni-primary)
+ }
+ &[type=success] {
+ @include is-color($uni-success);
+ @include is-plain($uni-success)
+ }
+ &[type=error] {
+ @include is-color($uni-error);
+ @include is-plain($uni-error)
+ }
+ &[type=warning] {
+ @include is-color($uni-warning);
+ @include is-plain($uni-warning)
+ }
+ &[type=info] {
+ @include is-color($uni-info);
+ @include is-plain($uni-info)
+ }
+}
+/* #endif */
diff --git a/app/uni_modules/uni-scss/styles/setting/_text.scss b/app/uni_modules/uni-scss/styles/setting/_text.scss
new file mode 100644
index 0000000..a34d08f
--- /dev/null
+++ b/app/uni_modules/uni-scss/styles/setting/_text.scss
@@ -0,0 +1,24 @@
+@mixin get-styles($k,$c) {
+ @if $k == size or $k == weight{
+ font-#{$k}:#{$c}
+ }@else{
+ #{$k}:#{$c}
+ }
+}
+
+@each $key, $child in $uni-headings {
+ /* #ifndef APP-NVUE */
+ .uni-#{$key} {
+ @each $k, $c in $child {
+ @include get-styles($k,$c)
+ }
+ }
+ /* #endif */
+ /* #ifdef APP-NVUE */
+ .container .uni-#{$key} {
+ @each $k, $c in $child {
+ @include get-styles($k,$c)
+ }
+ }
+ /* #endif */
+}
diff --git a/app/uni_modules/uni-scss/styles/setting/_variables.scss b/app/uni_modules/uni-scss/styles/setting/_variables.scss
new file mode 100644
index 0000000..557d3d7
--- /dev/null
+++ b/app/uni_modules/uni-scss/styles/setting/_variables.scss
@@ -0,0 +1,146 @@
+// @use "sass:math";
+@import '../tools/functions.scss';
+// 闂磋窛鍩虹鍊嶆暟
+$uni-space-root: 2 !default;
+// 杈规鍗婂緞榛樿鍊�
+$uni-radius-root:5px !default;
+$uni-radius: () !default;
+// 杈规鍗婂緞鏂偣
+$uni-radius: map-deep-merge(
+ (
+ 0: 0,
+ // TODO 褰撳墠鐗堟湰鏆傛椂涓嶆敮鎸� sm 灞炴��
+ // 'sm': math.div($uni-radius-root, 2),
+ null: $uni-radius-root,
+ 'lg': $uni-radius-root * 2,
+ 'xl': $uni-radius-root * 6,
+ 'pill': 9999px,
+ 'circle': 50%
+ ),
+ $uni-radius
+);
+// 瀛椾綋瀹舵棌
+$body-font-family: 'Roboto', sans-serif !default;
+// 鏂囨湰
+$heading-font-family: $body-font-family !default;
+$uni-headings: () !default;
+$letterSpacing: -0.01562em;
+$uni-headings: map-deep-merge(
+ (
+ 'h1': (
+ size: 32px,
+ weight: 300,
+ line-height: 50px,
+ // letter-spacing:-0.01562em
+ ),
+ 'h2': (
+ size: 28px,
+ weight: 300,
+ line-height: 40px,
+ // letter-spacing: -0.00833em
+ ),
+ 'h3': (
+ size: 24px,
+ weight: 400,
+ line-height: 32px,
+ // letter-spacing: normal
+ ),
+ 'h4': (
+ size: 20px,
+ weight: 400,
+ line-height: 30px,
+ // letter-spacing: 0.00735em
+ ),
+ 'h5': (
+ size: 16px,
+ weight: 400,
+ line-height: 24px,
+ // letter-spacing: normal
+ ),
+ 'h6': (
+ size: 14px,
+ weight: 500,
+ line-height: 18px,
+ // letter-spacing: 0.0125em
+ ),
+ 'subtitle': (
+ size: 12px,
+ weight: 400,
+ line-height: 20px,
+ // letter-spacing: 0.00937em
+ ),
+ 'body': (
+ font-size: 14px,
+ font-weight: 400,
+ line-height: 22px,
+ // letter-spacing: 0.03125em
+ ),
+ 'caption': (
+ 'size': 12px,
+ 'weight': 400,
+ 'line-height': 20px,
+ // 'letter-spacing': 0.03333em,
+ // 'text-transform': false
+ )
+ ),
+ $uni-headings
+);
+
+
+
+// 涓昏壊
+$uni-primary: #2979ff !default;
+$uni-primary-disable:lighten($uni-primary,20%) !default;
+$uni-primary-light: lighten($uni-primary,25%) !default;
+
+// 杈呭姪鑹�
+// 闄や簡涓昏壊澶栫殑鍦烘櫙鑹诧紝闇�瑕佸湪涓嶅悓鐨勫満鏅腑浣跨敤锛堜緥濡傚嵄闄╄壊琛ㄧず鍗遍櫓鐨勬搷浣滐級銆�
+$uni-success: #18bc37 !default;
+$uni-success-disable:lighten($uni-success,20%) !default;
+$uni-success-light: lighten($uni-success,25%) !default;
+
+$uni-warning: #f3a73f !default;
+$uni-warning-disable:lighten($uni-warning,20%) !default;
+$uni-warning-light: lighten($uni-warning,25%) !default;
+
+$uni-error: #e43d33 !default;
+$uni-error-disable:lighten($uni-error,20%) !default;
+$uni-error-light: lighten($uni-error,25%) !default;
+
+$uni-info: #8f939c !default;
+$uni-info-disable:lighten($uni-info,20%) !default;
+$uni-info-light: lighten($uni-info,25%) !default;
+
+// 涓�ц壊
+// 涓�ц壊鐢ㄤ簬鏂囨湰銆佽儗鏅拰杈规棰滆壊銆傞�氳繃杩愮敤涓嶅悓鐨勪腑鎬ц壊锛屾潵琛ㄧ幇灞傛缁撴瀯銆�
+$uni-main-color: #3a3a3a !default; // 涓昏鏂囧瓧
+$uni-base-color: #6a6a6a !default; // 甯歌鏂囧瓧
+$uni-secondary-color: #909399 !default; // 娆¤鏂囧瓧
+$uni-extra-color: #c7c7c7 !default; // 杈呭姪璇存槑
+
+// 杈规棰滆壊
+$uni-border-1: #F0F0F0 !default;
+$uni-border-2: #EDEDED !default;
+$uni-border-3: #DCDCDC !default;
+$uni-border-4: #B9B9B9 !default;
+
+// 甯歌鑹�
+$uni-black: #000000 !default;
+$uni-white: #ffffff !default;
+$uni-transparent: rgba($color: #000000, $alpha: 0) !default;
+
+// 鑳屾櫙鑹�
+$uni-bg-color: #f7f7f7 !default;
+
+/* 姘村钩闂磋窛 */
+$uni-spacing-sm: 8px !default;
+$uni-spacing-base: 15px !default;
+$uni-spacing-lg: 30px !default;
+
+// 闃村奖
+$uni-shadow-sm:0 0 5px rgba($color: #d8d8d8, $alpha: 0.5) !default;
+$uni-shadow-base:0 1px 8px 1px rgba($color: #a5a5a5, $alpha: 0.2) !default;
+$uni-shadow-lg:0px 1px 10px 2px rgba($color: #a5a4a4, $alpha: 0.5) !default;
+
+// 钂欑増
+$uni-mask: rgba($color: #000000, $alpha: 0.4) !default;
diff --git a/app/uni_modules/uni-scss/styles/tools/functions.scss b/app/uni_modules/uni-scss/styles/tools/functions.scss
new file mode 100644
index 0000000..ac6f63e
--- /dev/null
+++ b/app/uni_modules/uni-scss/styles/tools/functions.scss
@@ -0,0 +1,19 @@
+// 鍚堝苟 map
+@function map-deep-merge($parent-map, $child-map){
+ $result: $parent-map;
+ @each $key, $child in $child-map {
+ $parent-has-key: map-has-key($result, $key);
+ $parent-value: map-get($result, $key);
+ $parent-type: type-of($parent-value);
+ $child-type: type-of($child);
+ $parent-is-map: $parent-type == map;
+ $child-is-map: $child-type == map;
+
+ @if (not $parent-has-key) or ($parent-type != $child-type) or (not ($parent-is-map and $child-is-map)){
+ $result: map-merge($result, ( $key: $child ));
+ }@else {
+ $result: map-merge($result, ( $key: map-deep-merge($parent-value, $child) ));
+ }
+ }
+ @return $result;
+};
diff --git a/app/uni_modules/uni-scss/theme.scss b/app/uni_modules/uni-scss/theme.scss
new file mode 100644
index 0000000..80ee62f
--- /dev/null
+++ b/app/uni_modules/uni-scss/theme.scss
@@ -0,0 +1,31 @@
+// 闂磋窛鍩虹鍊嶆暟
+$uni-space-root: 2;
+// 杈规鍗婂緞榛樿鍊�
+$uni-radius-root:5px;
+// 涓昏壊
+$uni-primary: #2979ff;
+// 杈呭姪鑹�
+$uni-success: #4cd964;
+// 璀﹀憡鑹�
+$uni-warning: #f0ad4e;
+// 閿欒鑹�
+$uni-error: #dd524d;
+// 鎻忚堪鑹�
+$uni-info: #909399;
+// 涓�ц壊
+$uni-main-color: #303133;
+$uni-base-color: #606266;
+$uni-secondary-color: #909399;
+$uni-extra-color: #C0C4CC;
+// 鑳屾櫙鑹�
+$uni-bg-color: #f5f5f5;
+// 杈规棰滆壊
+$uni-border-1: #DCDFE6;
+$uni-border-2: #E4E7ED;
+$uni-border-3: #EBEEF5;
+$uni-border-4: #F2F6FC;
+
+// 甯歌鑹�
+$uni-black: #000000;
+$uni-white: #ffffff;
+$uni-transparent: rgba($color: #000000, $alpha: 0);
diff --git a/app/uni_modules/uni-scss/variables.scss b/app/uni_modules/uni-scss/variables.scss
new file mode 100644
index 0000000..1c062d4
--- /dev/null
+++ b/app/uni_modules/uni-scss/variables.scss
@@ -0,0 +1,62 @@
+@import './styles/setting/_variables.scss';
+// 闂磋窛鍩虹鍊嶆暟
+$uni-space-root: 2;
+// 杈规鍗婂緞榛樿鍊�
+$uni-radius-root:5px;
+
+// 涓昏壊
+$uni-primary: #2979ff;
+$uni-primary-disable:mix(#fff,$uni-primary,50%);
+$uni-primary-light: mix(#fff,$uni-primary,80%);
+
+// 杈呭姪鑹�
+// 闄や簡涓昏壊澶栫殑鍦烘櫙鑹诧紝闇�瑕佸湪涓嶅悓鐨勫満鏅腑浣跨敤锛堜緥濡傚嵄闄╄壊琛ㄧず鍗遍櫓鐨勬搷浣滐級銆�
+$uni-success: #18bc37;
+$uni-success-disable:mix(#fff,$uni-success,50%);
+$uni-success-light: mix(#fff,$uni-success,80%);
+
+$uni-warning: #f3a73f;
+$uni-warning-disable:mix(#fff,$uni-warning,50%);
+$uni-warning-light: mix(#fff,$uni-warning,80%);
+
+$uni-error: #e43d33;
+$uni-error-disable:mix(#fff,$uni-error,50%);
+$uni-error-light: mix(#fff,$uni-error,80%);
+
+$uni-info: #8f939c;
+$uni-info-disable:mix(#fff,$uni-info,50%);
+$uni-info-light: mix(#fff,$uni-info,80%);
+
+// 涓�ц壊
+// 涓�ц壊鐢ㄤ簬鏂囨湰銆佽儗鏅拰杈规棰滆壊銆傞�氳繃杩愮敤涓嶅悓鐨勪腑鎬ц壊锛屾潵琛ㄧ幇灞傛缁撴瀯銆�
+$uni-main-color: #3a3a3a; // 涓昏鏂囧瓧
+$uni-base-color: #6a6a6a; // 甯歌鏂囧瓧
+$uni-secondary-color: #909399; // 娆¤鏂囧瓧
+$uni-extra-color: #c7c7c7; // 杈呭姪璇存槑
+
+// 杈规棰滆壊
+$uni-border-1: #F0F0F0;
+$uni-border-2: #EDEDED;
+$uni-border-3: #DCDCDC;
+$uni-border-4: #B9B9B9;
+
+// 甯歌鑹�
+$uni-black: #000000;
+$uni-white: #ffffff;
+$uni-transparent: rgba($color: #000000, $alpha: 0);
+
+// 鑳屾櫙鑹�
+$uni-bg-color: #f7f7f7;
+
+/* 姘村钩闂磋窛 */
+$uni-spacing-sm: 8px;
+$uni-spacing-base: 15px;
+$uni-spacing-lg: 30px;
+
+// 闃村奖
+$uni-shadow-sm:0 0 5px rgba($color: #d8d8d8, $alpha: 0.5);
+$uni-shadow-base:0 1px 8px 1px rgba($color: #a5a5a5, $alpha: 0.2);
+$uni-shadow-lg:0px 1px 10px 2px rgba($color: #a5a4a4, $alpha: 0.5);
+
+// 钂欑増
+$uni-mask: rgba($color: #000000, $alpha: 0.4);
diff --git a/app/uni_modules/uni-search-bar/changelog.md b/app/uni_modules/uni-search-bar/changelog.md
new file mode 100644
index 0000000..b41fdd3
--- /dev/null
+++ b/app/uni_modules/uni-search-bar/changelog.md
@@ -0,0 +1,33 @@
+## 1.2.3锛�2022-05-24锛�
+- 鏂板 readonly 灞炴�э紝缁勪欢鍙
+## 1.2.2锛�2022-05-06锛�
+- 淇 vue3 input 浜嬩欢涓嶇敓鏁堢殑bug
+## 1.2.1锛�2022-05-06锛�
+- 淇 澶氫綑浠g爜瀵艰嚧鐨刡ug
+## 1.2.0锛�2021-11-19锛�
+- 浼樺寲 缁勪欢UI锛屽苟鎻愪緵璁捐璧勬簮锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 鏂囨。杩佺Щ锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/uni-search-bar](https://uniapp.dcloud.io/component/uniui/uni-search-bar)
+## 1.1.2锛�2021-08-30锛�
+- 淇 value 灞炴�т笌 modelValue 灞炴�т笉鍏煎鐨凚ug
+## 1.1.1锛�2021-08-24锛�
+- 鏂板 鏀寔鍥介檯鍖�
+## 1.1.0锛�2021-07-30锛�
+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤簐ue3椤圭洰锛岃瑙� [uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+## 1.0.9锛�2021-05-12锛�
+- 鏂板 椤圭洰绀轰緥鍦板潃
+## 1.0.8锛�2021-04-21锛�
+- 浼樺寲 娣诲姞渚濊禆 uni-icons, 瀵煎叆鍚庤嚜鍔ㄤ笅杞戒緷璧�
+## 1.0.7锛�2021-04-15锛�
+- uni-ui 鏂板 uni-search-bar 鐨� focus 浜嬩欢
+
+## 1.0.6锛�2021-02-05锛�
+- 浼樺寲 缁勪欢寮曠敤鍏崇郴锛岄�氳繃uni_modules寮曠敤缁勪欢
+
+## 1.0.5锛�2021-02-05锛�
+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
+- 鏂板 鏀寔鍙屽悜缁戝畾
+- 鏇存敼 input 浜嬩欢鐨勮繑鍥炲�硷紝e={value:Number} --> e=value
+- 鏂板 鏀寔鍥炬爣鎻掓Ы
+- 鏂板 鏀寔 clear銆乥lur 浜嬩欢
+- 鏂板 鏀寔 focus 灞炴��
+- 鍘绘帀缁勪欢鑳屾櫙鑹�
diff --git a/app/uni_modules/uni-search-bar/components/uni-search-bar/i18n/en.json b/app/uni_modules/uni-search-bar/components/uni-search-bar/i18n/en.json
new file mode 100644
index 0000000..dd083a5
--- /dev/null
+++ b/app/uni_modules/uni-search-bar/components/uni-search-bar/i18n/en.json
@@ -0,0 +1,4 @@
+{
+ "uni-search-bar.cancel": "cancel",
+ "uni-search-bar.placeholder": "Search enter content"
+}
\ No newline at end of file
diff --git a/app/uni_modules/uni-search-bar/components/uni-search-bar/i18n/index.js b/app/uni_modules/uni-search-bar/components/uni-search-bar/i18n/index.js
new file mode 100644
index 0000000..de7509c
--- /dev/null
+++ b/app/uni_modules/uni-search-bar/components/uni-search-bar/i18n/index.js
@@ -0,0 +1,8 @@
+import en from './en.json'
+import zhHans from './zh-Hans.json'
+import zhHant from './zh-Hant.json'
+export default {
+ en,
+ 'zh-Hans': zhHans,
+ 'zh-Hant': zhHant
+}
diff --git a/app/uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hans.json b/app/uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hans.json
new file mode 100644
index 0000000..d4e5c12
--- /dev/null
+++ b/app/uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hans.json
@@ -0,0 +1,4 @@
+{
+ "uni-search-bar.cancel": "cancel",
+ "uni-search-bar.placeholder": "璇疯緭鍏ユ悳绱㈠唴瀹�"
+}
diff --git a/app/uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hant.json b/app/uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hant.json
new file mode 100644
index 0000000..318b6ef
--- /dev/null
+++ b/app/uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hant.json
@@ -0,0 +1,4 @@
+{
+ "uni-search-bar.cancel": "cancel",
+ "uni-search-bar.placeholder": "璜嬭几鍏ユ悳绱㈠収瀹�"
+}
diff --git a/app/uni_modules/uni-search-bar/components/uni-search-bar/uni-search-bar.vue b/app/uni_modules/uni-search-bar/components/uni-search-bar/uni-search-bar.vue
new file mode 100644
index 0000000..5a518a8
--- /dev/null
+++ b/app/uni_modules/uni-search-bar/components/uni-search-bar/uni-search-bar.vue
@@ -0,0 +1,298 @@
+<template>
+ <view class="uni-searchbar">
+ <view :style="{borderRadius:radius+'px',backgroundColor: bgColor}" class="uni-searchbar__box"
+ @click="searchClick">
+ <view class="uni-searchbar__box-icon-search">
+ <slot name="searchIcon">
+ <uni-icons color="#c0c4cc" size="18" type="search" />
+ </slot>
+ </view>
+ <input v-if="show || searchVal" :focus="showSync" :disabled="readonly" :placeholder="placeholderText" :maxlength="maxlength"
+ class="uni-searchbar__box-search-input" confirm-type="search" type="text" v-model="searchVal"
+ @confirm="confirm" @blur="blur" @focus="emitFocus" />
+ <text v-else class="uni-searchbar__text-placeholder">{{ placeholder }}</text>
+ <view v-if="show && (clearButton==='always'||clearButton==='auto'&&searchVal!=='') &&!readonly"
+ class="uni-searchbar__box-icon-clear" @click="clear">
+ <slot name="clearIcon">
+ <uni-icons color="#c0c4cc" size="20" type="clear" />
+ </slot>
+ </view>
+ </view>
+ <text @click="cancel" class="uni-searchbar__cancel"
+ v-if="cancelButton ==='always' || show && cancelButton ==='auto'">{{cancelTextI18n}}</text>
+ </view>
+</template>
+
+<script>
+ import {
+ initVueI18n
+ } from '@dcloudio/uni-i18n'
+ import messages from './i18n/index.js'
+ const {
+ t
+ } = initVueI18n(messages)
+
+ /**
+ * SearchBar 鎼滅储鏍�
+ * @description 鎼滅储鏍忕粍浠讹紝閫氬父鐢ㄤ簬鎼滅储鍟嗗搧銆佹枃绔犵瓑
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=866
+ * @property {Number} radius 鎼滅储鏍忓渾瑙�
+ * @property {Number} maxlength 杈撳叆鏈�澶ч暱搴�
+ * @property {String} placeholder 鎼滅储鏍廝laceholder
+ * @property {String} clearButton = [always|auto|none] 鏄惁鏄剧ず娓呴櫎鎸夐挳
+ * @value always 涓�鐩存樉绀�
+ * @value auto 杈撳叆妗嗕笉涓虹┖鏃舵樉绀�
+ * @value none 涓�鐩翠笉鏄剧ず
+ * @property {String} cancelButton = [always|auto|none] 鏄惁鏄剧ず鍙栨秷鎸夐挳
+ * @value always 涓�鐩存樉绀�
+ * @value auto 杈撳叆妗嗕笉涓虹┖鏃舵樉绀�
+ * @value none 涓�鐩翠笉鏄剧ず
+ * @property {String} cancelText 鍙栨秷鎸夐挳鐨勬枃瀛�
+ * @property {String} bgColor 杈撳叆妗嗚儗鏅鑹�
+ * @property {Boolean} focus 鏄惁鑷姩鑱氱劍
+ * @property {Boolean} readonly 缁勪欢鍙锛屼笉鑳芥湁浠讳綍鎿嶄綔锛屽彧鍋氬睍绀�
+ * @event {Function} confirm uniSearchBar 鐨勮緭鍏ユ confirm 浜嬩欢锛岃繑鍥炲弬鏁颁负uniSearchBar鐨剉alue锛宔={value:Number}
+ * @event {Function} input uniSearchBar 鐨� value 鏀瑰彉鏃惰Е鍙戜簨浠讹紝杩斿洖鍙傛暟涓簎niSearchBar鐨剉alue锛宔=value
+ * @event {Function} cancel 鐐瑰嚮鍙栨秷鎸夐挳鏃惰Е鍙戜簨浠讹紝杩斿洖鍙傛暟涓簎niSearchBar鐨剉alue锛宔={value:Number}
+ * @event {Function} clear 鐐瑰嚮娓呴櫎鎸夐挳鏃惰Е鍙戜簨浠讹紝杩斿洖鍙傛暟涓簎niSearchBar鐨剉alue锛宔={value:Number}
+ * @event {Function} blur input澶卞幓鐒︾偣鏃惰Е鍙戜簨浠讹紝杩斿洖鍙傛暟涓簎niSearchBar鐨剉alue锛宔={value:Number}
+ */
+
+ export default {
+ name: "UniSearchBar",
+ emits: ['input', 'update:modelValue', 'clear', 'cancel', 'confirm', 'blur', 'focus'],
+ props: {
+ placeholder: {
+ type: String,
+ default: ""
+ },
+ radius: {
+ type: [Number, String],
+ default: 5
+ },
+ clearButton: {
+ type: String,
+ default: "auto"
+ },
+ cancelButton: {
+ type: String,
+ default: "auto"
+ },
+ cancelText: {
+ type: String,
+ default: '鍙栨秷'
+ },
+ bgColor: {
+ type: String,
+ default: "#F8F8F8"
+ },
+ maxlength: {
+ type: [Number, String],
+ default: 100
+ },
+ value: {
+ type: [Number, String],
+ default: ""
+ },
+ modelValue: {
+ type: [Number, String],
+ default: ""
+ },
+ focus: {
+ type: Boolean,
+ default: false
+ },
+ readonly: {
+ type: Boolean,
+ default: false
+ }
+ },
+ data() {
+ return {
+ show: false,
+ showSync: false,
+ searchVal: ''
+ }
+ },
+ computed: {
+ cancelTextI18n() {
+ return this.cancelText || t("uni-search-bar.cancel")
+ },
+ placeholderText() {
+ return this.placeholder || t("uni-search-bar.placeholder")
+ }
+ },
+ watch: {
+ // #ifndef VUE3
+ value: {
+ immediate: true,
+ handler(newVal) {
+ this.searchVal = newVal
+ if (newVal) {
+ this.show = true
+ }
+ }
+ },
+ // #endif
+ // #ifdef VUE3
+ modelValue: {
+ immediate: true,
+ handler(newVal) {
+ this.searchVal = newVal
+ if (newVal) {
+ this.show = true
+ }
+ }
+ },
+ // #endif
+ focus: {
+ immediate: true,
+ handler(newVal) {
+ if (newVal) {
+ if(this.readonly) return
+ this.show = true;
+ this.$nextTick(() => {
+ this.showSync = true
+ })
+ }
+ }
+ },
+ searchVal(newVal, oldVal) {
+ this.$emit("input", newVal)
+ // #ifdef VUE3
+ this.$emit("update:modelValue", newVal)
+ // #endif
+ }
+ },
+ methods: {
+ searchClick() {
+ if(this.readonly) return
+ if (this.show) {
+ return
+ }
+ this.show = true;
+ this.$nextTick(() => {
+ this.showSync = true
+ })
+ },
+ clear() {
+ this.$emit("clear", {
+ value: this.searchVal
+ })
+ this.searchVal = ""
+ },
+ cancel() {
+ if(this.readonly) return
+ this.$emit("cancel", {
+ value: this.searchVal
+ });
+ this.searchVal = ""
+ this.show = false
+ this.showSync = false
+ // #ifndef APP-PLUS
+ uni.hideKeyboard()
+ // #endif
+ // #ifdef APP-PLUS
+ plus.key.hideSoftKeybord()
+ // #endif
+ },
+ confirm() {
+ // #ifndef APP-PLUS
+ uni.hideKeyboard();
+ // #endif
+ // #ifdef APP-PLUS
+ plus.key.hideSoftKeybord()
+ // #endif
+ this.$emit("confirm", {
+ value: this.searchVal
+ })
+ },
+ blur() {
+ // #ifndef APP-PLUS
+ uni.hideKeyboard();
+ // #endif
+ // #ifdef APP-PLUS
+ plus.key.hideSoftKeybord()
+ // #endif
+ this.$emit("blur", {
+ value: this.searchVal
+ })
+ },
+ emitFocus(e) {
+ this.$emit("focus", e.detail)
+ }
+ }
+ };
+</script>
+
+<style lang="scss">
+ $uni-searchbar-height: 36px;
+
+ .uni-searchbar {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ position: relative;
+ padding: 10px;
+ // background-color: #fff;
+ }
+
+ .uni-searchbar__box {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ box-sizing: border-box;
+ /* #endif */
+ overflow: hidden;
+ position: relative;
+ flex: 1;
+ justify-content: center;
+ flex-direction: row;
+ align-items: center;
+ height: $uni-searchbar-height;
+ padding: 5px 8px 5px 0px;
+ }
+
+ .uni-searchbar__box-icon-search {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ // width: 32px;
+ padding: 0 8px;
+ justify-content: center;
+ align-items: center;
+ color: #B3B3B3;
+ }
+
+ .uni-searchbar__box-search-input {
+ flex: 1;
+ font-size: 14px;
+ color: #333;
+ }
+
+ .uni-searchbar__box-icon-clear {
+ align-items: center;
+ line-height: 24px;
+ padding-left: 8px;
+ /* #ifdef H5 */
+ cursor: pointer;
+ /* #endif */
+ }
+
+ .uni-searchbar__text-placeholder {
+ font-size: 14px;
+ color: #B3B3B3;
+ margin-left: 5px;
+ }
+
+ .uni-searchbar__cancel {
+ padding-left: 10px;
+ line-height: $uni-searchbar-height;
+ font-size: 14px;
+ color: #333333;
+ /* #ifdef H5 */
+ cursor: pointer;
+ /* #endif */
+ }
+</style>
diff --git a/app/uni_modules/uni-search-bar/package.json b/app/uni_modules/uni-search-bar/package.json
new file mode 100644
index 0000000..9352c57
--- /dev/null
+++ b/app/uni_modules/uni-search-bar/package.json
@@ -0,0 +1,89 @@
+{
+ "id": "uni-search-bar",
+ "displayName": "uni-search-bar 鎼滅储鏍�",
+ "version": "1.2.3",
+ "description": "鎼滅储鏍忕粍浠讹紝閫氬父鐢ㄤ簬鎼滅储鍟嗗搧銆佹枃绔犵瓑",
+ "keywords": [
+ "uni-ui",
+ "uniui",
+ "鎼滅储妗�",
+ "鎼滅储鏍�"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "鍓嶇缁勪欢",
+ "閫氱敤缁勪欢"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": [
+ "uni-scss",
+ "uni-icons"
+ ],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "u",
+ "鑱旂洘": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/uni_modules/uni-search-bar/readme.md b/app/uni_modules/uni-search-bar/readme.md
new file mode 100644
index 0000000..253092f
--- /dev/null
+++ b/app/uni_modules/uni-search-bar/readme.md
@@ -0,0 +1,14 @@
+
+
+## SearchBar 鎼滅储鏍�
+
+> **缁勪欢鍚嶏細uni-search-bar**
+> 浠g爜鍧楋細 `uSearchBar`
+
+
+鎼滅储鏍忕粍浠�
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-search-bar)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
+
+
diff --git a/app/uni_modules/uni-segmented-control/changelog.md b/app/uni_modules/uni-segmented-control/changelog.md
new file mode 100644
index 0000000..a44385d
--- /dev/null
+++ b/app/uni_modules/uni-segmented-control/changelog.md
@@ -0,0 +1,9 @@
+## 1.2.0锛�2021-11-19锛�
+- 浼樺寲 缁勪欢UI锛屽苟鎻愪緵璁捐璧勬簮锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 鏂囨。杩佺Щ锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/uni-segmented-control](https://uniapp.dcloud.io/component/uniui/uni-segmented-control)
+## 1.1.0锛�2021-07-30锛�
+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤簐ue3椤圭洰锛岃瑙� [uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+## 1.0.5锛�2021-05-12锛�
+- 鏂板 椤圭洰绀轰緥鍦板潃
+## 1.0.4锛�2021-02-05锛�
+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
diff --git a/app/uni_modules/uni-segmented-control/components/uni-segmented-control/uni-segmented-control.vue b/app/uni_modules/uni-segmented-control/components/uni-segmented-control/uni-segmented-control.vue
new file mode 100644
index 0000000..e8bb3e5
--- /dev/null
+++ b/app/uni_modules/uni-segmented-control/components/uni-segmented-control/uni-segmented-control.vue
@@ -0,0 +1,145 @@
+<template>
+ <view :class="[styleType === 'text'?'segmented-control--text' : 'segmented-control--button' ]"
+ :style="{ borderColor: styleType === 'text' ? '' : activeColor }" class="segmented-control">
+ <view v-for="(item, index) in values" :class="[ styleType === 'text' ? '': 'segmented-control__item--button',
+ index === currentIndex&&styleType === 'button' ? 'segmented-control__item--button--active': '',
+ index === 0&&styleType === 'button' ? 'segmented-control__item--button--first': '',
+ index === values.length - 1&&styleType === 'button' ? 'segmented-control__item--button--last': '' ]" :key="index"
+ :style="{ backgroundColor: index === currentIndex && styleType === 'button' ? activeColor : '',borderColor: index === currentIndex&&(styleType === 'text'||styleType === 'button')?activeColor:'#d9d9d9' }"
+ class="segmented-control__item" @click="_onClick(index)">
+ <view>
+ <text :style="{color:
+ index === currentIndex
+ ? styleType === 'text'
+ ? activeColor
+ : '#fff'
+ : styleType === 'text'
+ ? '#000'
+ : activeColor}" class="segmented-control__text" :class="styleType === 'text' && index === currentIndex ? 'segmented-control__item--text': ''">{{ item }}</text>
+ </view>
+
+ </view>
+ </view>
+</template>
+
+<script>
+ /**
+ * SegmentedControl 鍒嗘鍣�
+ * @description 鐢ㄤ綔涓嶅悓瑙嗗浘鐨勬樉绀�
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=54
+ * @property {Number} current 褰撳墠閫変腑鐨則ab绱㈠紩鍊硷紝浠�0璁℃暟
+ * @property {String} styleType = [button|text] 鍒嗘鍣ㄦ牱寮忕被鍨�
+ * @value button 鎸夐挳绫诲瀷
+ * @value text 鏂囧瓧绫诲瀷
+ * @property {String} activeColor 閫変腑鐨勬爣绛捐儗鏅壊涓庤竟妗嗛鑹�
+ * @property {Array} values 閫夐」鏁扮粍
+ * @event {Function} clickItem 缁勪欢瑙﹀彂鐐瑰嚮浜嬩欢鏃惰Е鍙戯紝e={currentIndex}
+ */
+
+ export default {
+ name: 'UniSegmentedControl',
+ emits: ['clickItem'],
+ props: {
+ current: {
+ type: Number,
+ default: 0
+ },
+ values: {
+ type: Array,
+ default () {
+ return []
+ }
+ },
+ activeColor: {
+ type: String,
+ default: '#2979FF'
+ },
+ styleType: {
+ type: String,
+ default: 'button'
+ }
+ },
+ data() {
+ return {
+ currentIndex: 0
+ }
+ },
+ watch: {
+ current(val) {
+ if (val !== this.currentIndex) {
+ this.currentIndex = val
+ }
+ }
+ },
+ created() {
+ this.currentIndex = this.current
+ },
+ methods: {
+ _onClick(index) {
+ if (this.currentIndex !== index) {
+ this.currentIndex = index
+ this.$emit('clickItem', {
+ currentIndex: index
+ })
+ }
+ }
+ }
+ }
+</script>
+
+<style lang="scss" >
+ .segmented-control {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ box-sizing: border-box;
+ /* #endif */
+ flex-direction: row;
+ height: 36px;
+ overflow: hidden;
+ /* #ifdef H5 */
+ cursor: pointer;
+ /* #endif */
+ }
+
+ .segmented-control__item {
+ /* #ifndef APP-NVUE */
+ display: inline-flex;
+ box-sizing: border-box;
+ /* #endif */
+ position: relative;
+ flex: 1;
+ justify-content: center;
+ align-items: center;
+ }
+
+ .segmented-control__item--button {
+ border-style: solid;
+ border-top-width: 1px;
+ border-bottom-width: 1px;
+ border-right-width: 1px;
+ border-left-width: 0;
+ }
+
+ .segmented-control__item--button--first {
+ border-left-width: 1px;
+ border-top-left-radius: 5px;
+ border-bottom-left-radius: 5px;
+ }
+
+ .segmented-control__item--button--last {
+ border-top-right-radius: 5px;
+ border-bottom-right-radius: 5px;
+ }
+
+ .segmented-control__item--text {
+ border-bottom-style: solid;
+ border-bottom-width: 2px;
+ padding: 6px 0;
+ }
+
+ .segmented-control__text {
+ font-size: 14px;
+ line-height: 20px;
+ text-align: center;
+ }
+</style>
diff --git a/app/uni_modules/uni-segmented-control/package.json b/app/uni_modules/uni-segmented-control/package.json
new file mode 100644
index 0000000..6cae41d
--- /dev/null
+++ b/app/uni_modules/uni-segmented-control/package.json
@@ -0,0 +1,87 @@
+{
+ "id": "uni-segmented-control",
+ "displayName": "uni-segmented-control 鍒嗘鍣�",
+ "version": "1.2.0",
+ "description": "鍒嗘鍣ㄧ敱鑷冲皯 2 涓垎娈垫帶浠剁粍鎴愶紝鐢ㄤ綔涓嶅悓瑙嗗浘鐨勬樉绀�",
+ "keywords": [
+ "uni-ui",
+ "uniui",
+ "鍒嗘鍣�",
+ "segement",
+ "椤堕儴閫夋嫨"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "鍓嶇缁勪欢",
+ "閫氱敤缁勪欢"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": ["uni-scss"],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "u",
+ "鑱旂洘": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/uni_modules/uni-segmented-control/readme.md b/app/uni_modules/uni-segmented-control/readme.md
new file mode 100644
index 0000000..3527b03
--- /dev/null
+++ b/app/uni_modules/uni-segmented-control/readme.md
@@ -0,0 +1,13 @@
+
+
+## SegmentedControl 鍒嗘鍣�
+> **缁勪欢鍚嶏細uni-segmented-control**
+> 浠g爜鍧楋細 `uSegmentedControl`
+
+
+鐢ㄤ綔涓嶅悓瑙嗗浘鐨勬樉绀�
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-segmented-control)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
+
+
diff --git a/app/uni_modules/uni-steps/changelog.md b/app/uni_modules/uni-steps/changelog.md
new file mode 100644
index 0000000..cb9d367
--- /dev/null
+++ b/app/uni_modules/uni-steps/changelog.md
@@ -0,0 +1,16 @@
+## 1.1.1锛�2021-11-22锛�
+- 淇 vue3涓煇浜泂css鍙橀噺鏃犳硶鎵惧埌鐨勯棶棰�
+## 1.1.0锛�2021-11-19锛�
+- 浼樺寲 缁勪欢UI锛屽苟鎻愪緵璁捐璧勬簮锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 鏂囨。杩佺Щ锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/uni-steps](https://uniapp.dcloud.io/component/uniui/uni-steps)
+## 1.0.8锛�2021-05-12锛�
+- 鏂板 椤圭洰绀轰緥鍦板潃
+## 1.0.7锛�2021-05-06锛�
+- 淇 uni-steps 妯悜甯冨眬鏃讹紝澶氳鏂囧瓧楂樺害涓嶅悎鐞嗙殑 bug
+## 1.0.6锛�2021-04-21锛�
+- 浼樺寲 娣诲姞渚濊禆 uni-icons, 瀵煎叆鍚庤嚜鍔ㄤ笅杞戒緷璧�
+## 1.0.5锛�2021-02-05锛�
+- 浼樺寲 缁勪欢寮曠敤鍏崇郴锛岄�氳繃uni_modules寮曠敤缁勪欢
+
+## 1.0.4锛�2021-02-05锛�
+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
diff --git a/app/uni_modules/uni-steps/components/uni-steps/uni-steps.vue b/app/uni_modules/uni-steps/components/uni-steps/uni-steps.vue
new file mode 100644
index 0000000..a6c8f28
--- /dev/null
+++ b/app/uni_modules/uni-steps/components/uni-steps/uni-steps.vue
@@ -0,0 +1,269 @@
+<template>
+ <view class="uni-steps">
+ <view :class="[direction==='column'?'uni-steps__column':'uni-steps__row']">
+ <view :class="[direction==='column'?'uni-steps__column-text-container':'uni-steps__row-text-container']">
+ <view v-for="(item,index) in options" :key="index"
+ :class="[direction==='column'?'uni-steps__column-text':'uni-steps__row-text']">
+ <text :style="{color:index === active?activeColor:deactiveColor}"
+ :class="[direction==='column'?'uni-steps__column-title':'uni-steps__row-title']">{{item.title}}</text>
+ <text :style="{color: deactiveColor}"
+ :class="[direction==='column'?'uni-steps__column-desc':'uni-steps__row-desc']">{{item.desc}}</text>
+ </view>
+ </view>
+ <view :class="[direction==='column'?'uni-steps__column-container':'uni-steps__row-container']">
+ <view :class="[direction==='column'?'uni-steps__column-line-item':'uni-steps__row-line-item']"
+ v-for="(item,index) in options" :key="index">
+ <view
+ :class="[direction==='column'?'uni-steps__column-line':'uni-steps__row-line',direction==='column'?'uni-steps__column-line--before':'uni-steps__row-line--before']"
+ :style="{backgroundColor:index<=active&&index!==0?activeColor:index===0?'transparent':deactiveColor}">
+ </view>
+ <view :class="[direction==='column'?'uni-steps__column-check':'uni-steps__row-check']"
+ v-if="index === active">
+ <uni-icons :color="activeColor" :type="activeIcon" size="14"></uni-icons>
+ </view>
+ <view v-else :class="[direction==='column'?'uni-steps__column-circle':'uni-steps__row-circle']"
+ :style="{backgroundColor:index<active?activeColor:deactiveColor}"></view>
+ <view
+ :class="[direction==='column'?'uni-steps__column-line':'uni-steps__row-line',direction==='column'?'uni-steps__column-line--after':'uni-steps__row-line--after']"
+ :style="{backgroundColor:index<active&&index!==options.length-1?activeColor:index===options.length-1?'transparent':deactiveColor}">
+ </view>
+ </view>
+ </view>
+ </view>
+ </view>
+</template>
+
+<script>
+ /**
+ * Steps 姝ラ鏉�
+ * @description 璇勫垎缁勪欢
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=34
+ * @property {Number} active 褰撳墠姝ラ
+ * @property {String} direction = [row|column] 褰撳墠姝ラ
+ * @value row 妯悜
+ * @value column 绾靛悜
+ * @property {String} activeColor 閫変腑鐘舵�佺殑棰滆壊
+ * @property {Array} options 鏁版嵁婧愶紝鏍煎紡涓猴細[{title:'xxx',desc:'xxx'},{title:'xxx',desc:'xxx'}]
+ */
+
+ export default {
+ name: 'UniSteps',
+ props: {
+ direction: {
+ // 鎺掑垪鏂瑰悜 row column
+ type: String,
+ default: 'row'
+ },
+ activeColor: {
+ // 婵�娲荤姸鎬侀鑹�
+ type: String,
+ default: '#2979FF'
+ },
+ deactiveColor: {
+ // 鏈縺娲荤姸鎬侀鑹�
+ type: String,
+ default: '#B7BDC6'
+ },
+ active: {
+ // 褰撳墠姝ラ
+ type: Number,
+ default: 0
+ },
+ activeIcon: {
+ // 褰撳墠姝ラ
+ type: String,
+ default: 'checkbox-filled'
+ },
+ options: {
+ type: Array,
+ default () {
+ return []
+ }
+ } // 鏁版嵁
+ },
+ data() {
+ return {}
+ }
+ }
+</script>
+
+<style lang="scss">
+ $uni-primary: #2979ff !default;
+ $uni-border-color:#EDEDED;
+ .uni-steps {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ width: 100%;
+ /* #endif */
+ /* #ifdef APP-NVUE */
+ flex: 1;
+ /* #endif */
+ flex-direction: column;
+ }
+
+ .uni-steps__row {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: column;
+ }
+
+ .uni-steps__column {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row-reverse;
+ }
+
+ .uni-steps__row-text-container {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ align-items: flex-end;
+ margin-bottom: 8px;
+ }
+
+ .uni-steps__column-text-container {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: column;
+ flex: 1;
+ }
+
+ .uni-steps__row-text {
+ /* #ifndef APP-NVUE */
+ display: inline-flex;
+ /* #endif */
+ flex: 1;
+ flex-direction: column;
+ }
+
+ .uni-steps__column-text {
+ padding: 6px 0px;
+ border-bottom-style: solid;
+ border-bottom-width: 1px;
+ border-bottom-color: $uni-border-color;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: column;
+ }
+
+ .uni-steps__row-title {
+ font-size: 14px;
+ line-height: 16px;
+ text-align: center;
+ }
+
+ .uni-steps__column-title {
+ font-size: 14px;
+ text-align: left;
+ line-height: 18px;
+ }
+
+ .uni-steps__row-desc {
+ font-size: 12px;
+ line-height: 14px;
+ text-align: center;
+ }
+
+ .uni-steps__column-desc {
+ font-size: 12px;
+ text-align: left;
+ line-height: 18px;
+ }
+
+ .uni-steps__row-container {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ }
+
+ .uni-steps__column-container {
+ /* #ifndef APP-NVUE */
+ display: inline-flex;
+ /* #endif */
+ width: 30px;
+ flex-direction: column;
+ }
+
+ .uni-steps__row-line-item {
+ /* #ifndef APP-NVUE */
+ display: inline-flex;
+ /* #endif */
+ flex-direction: row;
+ flex: 1;
+ height: 14px;
+ line-height: 14px;
+ align-items: center;
+ justify-content: center;
+ }
+
+ .uni-steps__column-line-item {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: column;
+ flex: 1;
+ align-items: center;
+ justify-content: center;
+ }
+
+ .uni-steps__row-line {
+ flex: 1;
+ height: 1px;
+ background-color: #B7BDC6;
+ }
+
+ .uni-steps__column-line {
+ width: 1px;
+ background-color: #B7BDC6;
+ }
+
+ .uni-steps__row-line--after {
+ transform: translateX(1px);
+ }
+
+ .uni-steps__column-line--after {
+ flex: 1;
+ transform: translate(0px, 1px);
+ }
+
+ .uni-steps__row-line--before {
+ transform: translateX(-1px);
+ }
+
+ .uni-steps__column-line--before {
+ height: 6px;
+ transform: translate(0px, -13px);
+ }
+
+ .uni-steps__row-circle {
+ width: 5px;
+ height: 5px;
+ border-radius: 50%;
+ background-color: #B7BDC6;
+ margin: 0px 3px;
+ }
+
+ .uni-steps__column-circle {
+ width: 5px;
+ height: 5px;
+ border-radius: 50%;
+ background-color: #B7BDC6;
+ margin: 4px 0px 5px 0px;
+ }
+
+ .uni-steps__row-check {
+ margin: 0px 6px;
+ }
+
+ .uni-steps__column-check {
+ height: 14px;
+ line-height: 14px;
+ margin: 2px 0px;
+ }
+</style>
diff --git a/app/uni_modules/uni-steps/package.json b/app/uni_modules/uni-steps/package.json
new file mode 100644
index 0000000..c687b40
--- /dev/null
+++ b/app/uni_modules/uni-steps/package.json
@@ -0,0 +1,89 @@
+{
+ "id": "uni-steps",
+ "displayName": "uni-steps 姝ラ鏉�",
+ "version": "1.1.1",
+ "description": "姝ラ鏉$粍浠讹紝鎻愪緵妯悜鍜岀旱鍚戜袱绉嶅竷灞�鏍煎紡銆�",
+ "keywords": [
+ "uni-ui",
+ "uniui",
+ "姝ラ鏉�",
+ "鏃堕棿杞�"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "鍓嶇缁勪欢",
+ "閫氱敤缁勪欢"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": [
+ "uni-scss",
+ "uni-icons"
+ ],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "u",
+ "鑱旂洘": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/uni_modules/uni-steps/readme.md b/app/uni_modules/uni-steps/readme.md
new file mode 100644
index 0000000..da7a4bf
--- /dev/null
+++ b/app/uni_modules/uni-steps/readme.md
@@ -0,0 +1,13 @@
+
+
+## Steps 姝ラ鏉�
+> **缁勪欢鍚嶏細uni-steps**
+> 浠g爜鍧楋細 `uSteps`
+
+
+姝ラ鏉★紝甯哥敤浜庢樉绀鸿繘搴�
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-steps)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
+
+
diff --git a/app/uni_modules/uni-swipe-action/changelog.md b/app/uni_modules/uni-swipe-action/changelog.md
new file mode 100644
index 0000000..c916427
--- /dev/null
+++ b/app/uni_modules/uni-swipe-action/changelog.md
@@ -0,0 +1,43 @@
+## 1.3.8锛�2023-04-13锛�
+- 淇`uni-swipe-action`鍜宍uni-swipe-action-item`涓嶅悓鏃朵娇鐢ㄥ鑷� closeOther 鏂规硶鎶ラ敊鐨� bug
+## 1.3.7锛�2022-06-06锛�
+- 淇 vue3 涓嬩娇鐢ㄧ粍浠朵笉鑳芥甯歌繍琛岀殑Bug
+## 1.3.6锛�2022-05-31锛�
+- 淇 h5绔偣鍑籧lick瑙﹀彂涓ゆ鐨凚ug
+## 1.3.5锛�2022-05-23锛�
+- 淇 isPC 鎵句笉鍒扮殑Bug
+## 1.3.4锛�2022-05-19锛�
+- 淇 鍦� nvue 涓� disabled 澶辨晥鐨刡ug
+## 1.3.3锛�2022-03-31锛�
+- 淇 鎸夐挳瀛椾綋澶у皬涓嶈兘璁剧疆鐨刡ug
+## 1.3.2锛�2022-03-16锛�
+- 淇 h5鍜宎pp绔笅鎶l閿欒鐨刡ug
+## 1.3.1锛�2022-03-07锛�
+- 淇 HBuilderX 1.4.X 鐗堟湰涓紝h5鍜宎pp绔笅鎶ラ敊鐨刡ug
+## 1.3.0锛�2021-11-19锛�
+- 浼樺寲 缁勪欢UI锛屽苟鎻愪緵璁捐璧勬簮锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 鏂囨。杩佺Щ锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/uni-swipe-action](https://uniapp.dcloud.io/component/uniui/uni-swipe-action)
+## 1.2.4锛�2021-08-20锛�
+- 浼樺寲 close-all 鏂规硶
+## 1.2.3锛�2021-08-20锛�
+- 鏂板 close-all 鏂规硶锛屽叧闂墍鏈夊凡鎵撳紑鐨勭粍浠�
+## 1.2.2锛�2021-08-17锛�
+- 鏂板 resize() 鏂规硶锛屽湪闈炲井淇″皬绋嬪簭銆乭5銆乤pp-vue绔嚭鐜颁笉鑳芥粦鍔ㄧ殑闂鐨勬椂鍊欙紝閲嶇疆缁勪欢
+- 淇 app 绔伓灏斿嚭鐜扮被浼� Page[x][-x,xx;-x,xx,x,x-x] 鐨勯棶棰�
+- 浼樺寲 寰俊灏忕▼搴忋�乭5銆乤pp-vue 婊戝姩閫昏緫锛岄伩鍏嶅嚭鐜板姩鎬佹柊澧炵粍浠跺悗涓嶈兘婊戝姩鐨勯棶棰�
+## 1.2.1锛�2021-07-30锛�
+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤簐ue3椤圭洰锛岃瑙� [uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+- 淇 璺ㄩ〉闈慨鏀圭粍浠舵暟鎹� 锛屽鑷翠笉鑳芥粦鍔ㄧ殑闂
+## 1.1.10锛�2021-06-17锛�
+- 淇 鎸夐挳鐐瑰嚮鎵ц涓ゆ鐨刡ug
+## 1.1.9锛�2021-05-12锛�
+- 鏂板 椤圭洰绀轰緥鍦板潃
+## 1.1.8锛�2021-03-26锛�
+- 淇 寰俊灏忕▼搴� nv_navigator is not defined 鎶ラ敊鐨刡ug
+## 1.1.7锛�2021-02-05锛�
+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
+- 鏂板 宸︿晶婊戝姩
+- 鏂板 鎻掓Ы浣跨敤鏂瑰紡
+- 鏂板 threshold 灞炴�э紝鍙互鎺у埗婊戝姩缂虹渷鍊�
+- 浼樺寲 闀垮垪琛ㄦ粴鍔ㄦ�ц兘
+- 淇 婊氬姩椤甸潰鏃惰Е鍙戠粍浠舵粦鍔ㄧ殑Bug
diff --git a/app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/bindingx.js b/app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/bindingx.js
new file mode 100644
index 0000000..707e432
--- /dev/null
+++ b/app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/bindingx.js
@@ -0,0 +1,302 @@
+let bindIngXMixins = {}
+
+// #ifdef APP-NVUE
+const BindingX = uni.requireNativePlugin('bindingx');
+const dom = uni.requireNativePlugin('dom');
+const animation = uni.requireNativePlugin('animation');
+
+bindIngXMixins = {
+ data() {
+ return {}
+ },
+
+ watch: {
+ show(newVal) {
+ if (this.autoClose) return
+ if (this.stop) return
+ this.stop = true
+ if (newVal) {
+ this.open(newVal)
+ } else {
+ this.close()
+ }
+ },
+ leftOptions() {
+ this.getSelectorQuery()
+ this.init()
+ },
+ rightOptions(newVal) {
+ this.init()
+ }
+ },
+ created() {
+ this.swipeaction = this.getSwipeAction()
+ if (this.swipeaction && Array.isArray(this.swipeaction.children)) {
+ this.swipeaction.children.push(this)
+ }
+ },
+ mounted() {
+ this.box = this.getEl(this.$refs['selector-box--hock'])
+ this.selector = this.getEl(this.$refs['selector-content--hock']);
+ this.leftButton = this.getEl(this.$refs['selector-left-button--hock']);
+ this.rightButton = this.getEl(this.$refs['selector-right-button--hock']);
+ this.init()
+ },
+ // beforeDestroy() {
+ // this.swipeaction.children.forEach((item, index) => {
+ // if (item === this) {
+ // this.swipeaction.children.splice(index, 1)
+ // }
+ // })
+ // },
+ methods: {
+ init() {
+ this.$nextTick(() => {
+ this.x = 0
+ this.button = {
+ show: false
+ }
+ setTimeout(() => {
+ this.getSelectorQuery()
+ }, 200)
+ })
+ },
+ onClick(index, item, position) {
+ this.$emit('click', {
+ content: item,
+ index,
+ position
+ })
+ },
+ touchstart(e) {
+ // fix by mehaotian 绂佹婊戝姩
+ if (this.disabled) return
+ // 姣忔鍙Е鍙戜竴娆★紝閬垮厤澶氭鐩戝惉閫犳垚闂儊
+ if (this.stop) return
+ this.stop = true
+ if (this.autoClose && this.swipeaction) {
+ this.swipeaction.closeOther(this)
+ }
+
+ const leftWidth = this.button.left.width
+ const rightWidth = this.button.right.width
+ let expression = this.range(this.x, -rightWidth, leftWidth)
+ let leftExpression = this.range(this.x - leftWidth, -leftWidth, 0)
+ let rightExpression = this.range(this.x + rightWidth, 0, rightWidth)
+
+ this.eventpan = BindingX.bind({
+ anchor: this.box,
+ eventType: 'pan',
+ props: [{
+ element: this.selector,
+ property: 'transform.translateX',
+ expression
+ }, {
+ element: this.leftButton,
+ property: 'transform.translateX',
+ expression: leftExpression
+ }, {
+ element: this.rightButton,
+ property: 'transform.translateX',
+ expression: rightExpression
+ }, ]
+ }, (e) => {
+ // nope
+ if (e.state === 'end') {
+ this.x = e.deltaX + this.x;
+ this.isclick = true
+ this.bindTiming(e.deltaX)
+ }
+ });
+ },
+ touchend(e) {
+ if (this.isopen !== 'none' && !this.isclick) {
+ this.open('none')
+ }
+ },
+ bindTiming(x) {
+ const left = this.x
+ const leftWidth = this.button.left.width
+ const rightWidth = this.button.right.width
+ const threshold = this.threshold
+ if (!this.isopen || this.isopen === 'none') {
+ if (left > threshold) {
+ this.open('left')
+ } else if (left < -threshold) {
+ this.open('right')
+ } else {
+ this.open('none')
+ }
+ } else {
+ if ((x > -leftWidth && x < 0) || x > rightWidth) {
+ if ((x > -threshold && x < 0) || (x - rightWidth > threshold)) {
+ this.open('left')
+ } else {
+ this.open('none')
+ }
+ } else {
+ if ((x < threshold && x > 0) || (x + leftWidth < -threshold)) {
+ this.open('right')
+ } else {
+ this.open('none')
+ }
+ }
+ }
+ },
+
+ /**
+ * 绉诲姩鑼冨洿
+ * @param {Object} num
+ * @param {Object} mix
+ * @param {Object} max
+ */
+ range(num, mix, max) {
+ return `min(max(x+${num}, ${mix}), ${max})`
+ },
+
+ /**
+ * 寮�鍚痵wipe
+ */
+ open(type) {
+ this.animation(type)
+ },
+
+ /**
+ * 鍏抽棴swipe
+ */
+ close() {
+ this.animation('none')
+ },
+
+ /**
+ * 寮�鍚叧闂姩鐢�
+ * @param {Object} type
+ */
+ animation(type) {
+ const time = 300
+ const leftWidth = this.button.left.width
+ const rightWidth = this.button.right.width
+ if (this.eventpan && this.eventpan.token) {
+ BindingX.unbind({
+ token: this.eventpan.token,
+ eventType: 'pan'
+ })
+ }
+
+ switch (type) {
+ case 'left':
+ Promise.all([
+ this.move(this.selector, leftWidth),
+ this.move(this.leftButton, 0),
+ this.move(this.rightButton, rightWidth * 2)
+ ]).then(() => {
+ this.setEmit(leftWidth, type)
+ })
+ break
+ case 'right':
+ Promise.all([
+ this.move(this.selector, -rightWidth),
+ this.move(this.leftButton, -leftWidth * 2),
+ this.move(this.rightButton, 0)
+ ]).then(() => {
+ this.setEmit(-rightWidth, type)
+ })
+ break
+ default:
+ Promise.all([
+ this.move(this.selector, 0),
+ this.move(this.leftButton, -leftWidth),
+ this.move(this.rightButton, rightWidth)
+ ]).then(() => {
+ this.setEmit(0, type)
+ })
+
+ }
+ },
+ setEmit(x, type) {
+ const leftWidth = this.button.left.width
+ const rightWidth = this.button.right.width
+ this.isopen = this.isopen || 'none'
+ this.stop = false
+ this.isclick = false
+ // 鍙湁鐘舵�佷笉涓�鑷存墠浼氳繑鍥炵粨鏋�
+ if (this.isopen !== type && this.x !== x) {
+ if (type === 'left' && leftWidth > 0) {
+ this.$emit('change', 'left')
+ }
+ if (type === 'right' && rightWidth > 0) {
+ this.$emit('change', 'right')
+ }
+ if (type === 'none') {
+ this.$emit('change', 'none')
+ }
+ }
+ this.x = x
+ this.isopen = type
+ },
+ move(ref, value) {
+ return new Promise((resolve, reject) => {
+ animation.transition(ref, {
+ styles: {
+ transform: `translateX(${value})`,
+ },
+ duration: 150, //ms
+ timingFunction: 'linear',
+ needLayout: false,
+ delay: 0 //ms
+ }, function(res) {
+ resolve(res)
+ })
+ })
+
+ },
+
+ /**
+ * 鑾峰彇ref
+ * @param {Object} el
+ */
+ getEl(el) {
+ return el.ref
+ },
+ /**
+ * 鑾峰彇鑺傜偣淇℃伅
+ */
+ getSelectorQuery() {
+ Promise.all([
+ this.getDom('left'),
+ this.getDom('right'),
+ ]).then((data) => {
+ let show = 'none'
+ if (this.autoClose) {
+ show = 'none'
+ } else {
+ show = this.show
+ }
+
+ if (show === 'none') {
+ // this.close()
+ } else {
+ this.open(show)
+ }
+
+ })
+
+ },
+ getDom(str) {
+ return new Promise((resolve, reject) => {
+ dom.getComponentRect(this.$refs[`selector-${str}-button--hock`], (data) => {
+ if (data) {
+ this.button[str] = data.size
+ resolve(data)
+ } else {
+ reject()
+ }
+ })
+ })
+ }
+ }
+}
+
+// #endif
+
+export default bindIngXMixins
diff --git a/app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/isPC.js b/app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/isPC.js
new file mode 100644
index 0000000..917cb48
--- /dev/null
+++ b/app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/isPC.js
@@ -0,0 +1,12 @@
+export function isPC() {
+ var userAgentInfo = navigator.userAgent;
+ var Agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"];
+ var flag = true;
+ for (let v = 0; v < Agents.length - 1; v++) {
+ if (userAgentInfo.indexOf(Agents[v]) > 0) {
+ flag = false;
+ break;
+ }
+ }
+ return flag;
+}
diff --git a/app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpalipay.js b/app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpalipay.js
new file mode 100644
index 0000000..35c796b
--- /dev/null
+++ b/app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpalipay.js
@@ -0,0 +1,195 @@
+export default {
+ data() {
+ return {
+ x: 0,
+ transition: false,
+ width: 0,
+ viewWidth: 0,
+ swipeShow: 0
+ }
+ },
+ watch: {
+ show(newVal) {
+ if (this.autoClose) return
+ if (newVal && newVal !== 'none') {
+ this.transition = true
+ this.open(newVal)
+ } else {
+ this.close()
+ }
+ }
+ },
+ created() {
+ this.swipeaction = this.getSwipeAction()
+ if (this.swipeaction && Array.isArray(this.swipeaction.children)) {
+ this.swipeaction.children.push(this)
+ }
+ },
+ mounted() {
+ this.isopen = false
+ setTimeout(() => {
+ this.getQuerySelect()
+ }, 50)
+ },
+ methods: {
+ appTouchStart(e) {
+ const {
+ clientX
+ } = e.changedTouches[0]
+ this.clientX = clientX
+ this.timestamp = new Date().getTime()
+ },
+ appTouchEnd(e, index, item, position) {
+ const {
+ clientX
+ } = e.changedTouches[0]
+ // fixed by xxxx 妯℃嫙鐐瑰嚮浜嬩欢锛岃В鍐� ios 13 鐐瑰嚮鍖哄煙閿欎綅鐨勯棶棰�
+ let diff = Math.abs(this.clientX - clientX)
+ let time = (new Date().getTime()) - this.timestamp
+ if (diff < 40 && time < 300) {
+ this.$emit('click', {
+ content: item,
+ index,
+ position
+ })
+ }
+ },
+ /**
+ * 绉诲姩瑙﹀彂
+ * @param {Object} e
+ */
+ onChange(e) {
+ this.moveX = e.detail.x
+ this.isclose = false
+ },
+ touchstart(e) {
+ this.transition = false
+ this.isclose = true
+ if (this.autoClose && this.swipeaction) {
+ this.swipeaction.closeOther(this)
+ }
+ },
+ touchmove(e) {},
+ touchend(e) {
+ // 0鐨勪綅缃粈涔堥兘涓嶆墽琛�
+ if (this.isclose && this.isopen === 'none') return
+ if (this.isclose && this.isopen !== 'none') {
+ this.transition = true
+ this.close()
+ } else {
+ this.move(this.moveX + this.leftWidth)
+ }
+ },
+
+ /**
+ * 绉诲姩
+ * @param {Object} moveX
+ */
+ move(moveX) {
+ // 鎵撳紑鍏抽棴鐨勫鐞嗛�昏緫涓嶅お涓�鏍�
+ this.transition = true
+ // 鏈墦寮�鐘舵��
+ if (!this.isopen || this.isopen === 'none') {
+ if (moveX > this.threshold) {
+ this.open('left')
+ } else if (moveX < -this.threshold) {
+ this.open('right')
+ } else {
+ this.close()
+ }
+ } else {
+ if (moveX < 0 && moveX < this.rightWidth) {
+ const rightX = this.rightWidth + moveX
+ if (rightX < this.threshold) {
+ this.open('right')
+ } else {
+ this.close()
+ }
+ } else if (moveX > 0 && moveX < this.leftWidth) {
+ const leftX = this.leftWidth - moveX
+ if (leftX < this.threshold) {
+ this.open('left')
+ } else {
+ this.close()
+ }
+ }
+
+ }
+
+ },
+
+ /**
+ * 鎵撳紑
+ */
+ open(type) {
+ this.x = this.moveX
+ this.animation(type)
+ },
+
+ /**
+ * 鍏抽棴
+ */
+ close() {
+ this.x = this.moveX
+ // TODO 瑙e喅 x 鍊间笉鏇存柊鐨勯棶棰橈紝鎵�浠ヤ細澶氳Е鍙戜竴娆� nextTick 锛屽緟浼樺寲
+ this.$nextTick(() => {
+ this.x = -this.leftWidth
+ if (this.isopen !== 'none') {
+ this.$emit('change', 'none')
+ }
+ this.isopen = 'none'
+ })
+ },
+
+ /**
+ * 鎵ц缁撴潫鍔ㄧ敾
+ * @param {Object} type
+ */
+ animation(type) {
+ this.$nextTick(() => {
+ if (type === 'left') {
+ this.x = 0
+ } else {
+ this.x = -this.rightWidth - this.leftWidth
+ }
+
+ if (this.isopen !== type) {
+ this.$emit('change', type)
+ }
+ this.isopen = type
+ })
+
+ },
+ getSlide(x) {},
+ getQuerySelect() {
+ const query = uni.createSelectorQuery().in(this);
+ query.selectAll('.movable-view--hock').boundingClientRect(data => {
+ this.leftWidth = data[1].width
+ this.rightWidth = data[2].width
+ this.width = data[0].width
+ this.viewWidth = this.width + this.rightWidth + this.leftWidth
+ if (this.leftWidth === 0) {
+ // TODO 鐤戜技bug ,鍒濆鍖栫殑鏃跺�欏鏋渪 鏄�0锛屼細瀵艰嚧绉诲姩浣嶇疆閿欒锛屾墍浠ヨ鍏冪礌瓒呭嚭涓�鐐�
+ this.x = -0.1
+ } else {
+ this.x = -this.leftWidth
+ }
+ this.moveX = this.x
+ this.$nextTick(() => {
+ this.swipeShow = 1
+ })
+
+ if (!this.buttonWidth) {
+ this.disabledView = true
+ }
+
+ if (this.autoClose) return
+ if (this.show !== 'none') {
+ this.transition = true
+ this.open(this.shows)
+ }
+ }).exec();
+
+ }
+ }
+}
diff --git a/app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpother.js b/app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpother.js
new file mode 100644
index 0000000..d389bce
--- /dev/null
+++ b/app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpother.js
@@ -0,0 +1,260 @@
+let otherMixins = {}
+
+// #ifndef APP-PLUS|| MP-WEIXIN || H5
+const MIN_DISTANCE = 10;
+otherMixins = {
+ data() {
+ // TODO 闅忔満鐢熺敓鍏冪礌ID锛岃В鍐崇櫨搴﹀皬绋嬪簭鑾峰彇鍚屼竴涓厓绱犱綅缃俊鎭殑bug
+ const elClass = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`
+ return {
+ uniShow: false,
+ left: 0,
+ buttonShow: 'none',
+ ani: false,
+ moveLeft: '',
+ elClass
+ }
+ },
+ watch: {
+ show(newVal) {
+ if (this.autoClose) return
+ this.openState(newVal)
+ },
+ left() {
+ this.moveLeft = `translateX(${this.left}px)`
+ },
+ buttonShow(newVal) {
+ if (this.autoClose) return
+ this.openState(newVal)
+ },
+ leftOptions() {
+ this.init()
+ },
+ rightOptions() {
+ this.init()
+ }
+ },
+ mounted() {
+ this.swipeaction = this.getSwipeAction()
+ if (this.swipeaction && Array.isArray(this.swipeaction.children)) {
+ this.swipeaction.children.push(this)
+ }
+ this.init()
+ },
+ methods: {
+ init() {
+ clearTimeout(this.timer)
+ this.timer = setTimeout(() => {
+ this.getSelectorQuery()
+ }, 100)
+ // 绉诲姩璺濈
+ this.left = 0
+ this.x = 0
+ },
+
+ closeSwipe(e) {
+ if (this.autoClose && this.swipeaction) {
+ this.swipeaction.closeOther(this)
+ }
+ },
+ appTouchStart(e) {
+ const {
+ clientX
+ } = e.changedTouches[0]
+ this.clientX = clientX
+ this.timestamp = new Date().getTime()
+ },
+ appTouchEnd(e, index, item, position) {
+ const {
+ clientX
+ } = e.changedTouches[0]
+ // fixed by xxxx 妯℃嫙鐐瑰嚮浜嬩欢锛岃В鍐� ios 13 鐐瑰嚮鍖哄煙閿欎綅鐨勯棶棰�
+ let diff = Math.abs(this.clientX - clientX)
+ let time = (new Date().getTime()) - this.timestamp
+ if (diff < 40 && time < 300) {
+ this.$emit('click', {
+ content: item,
+ index,
+ position
+ })
+ }
+ },
+ touchstart(e) {
+ if (this.disabled) return
+ this.ani = false
+ this.x = this.left || 0
+ this.stopTouchStart(e)
+ this.autoClose && this.closeSwipe()
+ },
+ touchmove(e) {
+ if (this.disabled) return
+ // 鏄惁鍙互婊戝姩椤甸潰
+ this.stopTouchMove(e);
+ if (this.direction !== 'horizontal') {
+ return;
+ }
+ this.move(this.x + this.deltaX)
+ return false
+ },
+ touchend() {
+ if (this.disabled) return
+ this.moveDirection(this.left)
+ },
+ /**
+ * 璁剧疆绉诲姩璺濈
+ * @param {Object} value
+ */
+ move(value) {
+ value = value || 0
+ const leftWidth = this.leftWidth
+ const rightWidth = this.rightWidth
+ // 鑾峰彇鍙粦鍔ㄨ寖鍥�
+ this.left = this.range(value, -rightWidth, leftWidth);
+ },
+
+ /**
+ * 鑾峰彇鑼冨洿
+ * @param {Object} num
+ * @param {Object} min
+ * @param {Object} max
+ */
+ range(num, min, max) {
+ return Math.min(Math.max(num, min), max);
+ },
+ /**
+ * 绉诲姩鏂瑰悜鍒ゆ柇
+ * @param {Object} left
+ * @param {Object} value
+ */
+ moveDirection(left) {
+ const threshold = this.threshold
+ const isopen = this.isopen || 'none'
+ const leftWidth = this.leftWidth
+ const rightWidth = this.rightWidth
+ if (this.deltaX === 0) {
+ this.openState('none')
+ return
+ }
+ if ((isopen === 'none' && rightWidth > 0 && -left > threshold) || (isopen !== 'none' && rightWidth >
+ 0 && rightWidth +
+ left < threshold)) {
+ // right
+ this.openState('right')
+ } else if ((isopen === 'none' && leftWidth > 0 && left > threshold) || (isopen !== 'none' && leftWidth >
+ 0 &&
+ leftWidth - left < threshold)) {
+ // left
+ this.openState('left')
+ } else {
+ // default
+ this.openState('none')
+ }
+ },
+
+ /**
+ * 寮�鍚姸鎬�
+ * @param {Boolean} type
+ */
+ openState(type) {
+ const leftWidth = this.leftWidth
+ const rightWidth = this.rightWidth
+ let left = ''
+ this.isopen = this.isopen ? this.isopen : 'none'
+ switch (type) {
+ case "left":
+ left = leftWidth
+ break
+ case "right":
+ left = -rightWidth
+ break
+ default:
+ left = 0
+ }
+
+
+ if (this.isopen !== type) {
+ this.throttle = true
+ this.$emit('change', type)
+ }
+
+ this.isopen = type
+ // 娣诲姞鍔ㄧ敾绫�
+ this.ani = true
+ this.$nextTick(() => {
+ this.move(left)
+ })
+ // 璁剧疆鏈�缁堢Щ鍔ㄤ綅缃�,鐞嗚涓婂彧瑕佽繘鍏ュ埌杩欎釜鍑芥暟锛岃偗瀹氭槸瑕佹墦寮�鐨�
+ },
+ close() {
+ this.openState('none')
+ },
+ getDirection(x, y) {
+ if (x > y && x > MIN_DISTANCE) {
+ return 'horizontal';
+ }
+ if (y > x && y > MIN_DISTANCE) {
+ return 'vertical';
+ }
+ return '';
+ },
+
+ /**
+ * 閲嶇疆婊戝姩鐘舵��
+ * @param {Object} event
+ */
+ resetTouchStatus() {
+ this.direction = '';
+ this.deltaX = 0;
+ this.deltaY = 0;
+ this.offsetX = 0;
+ this.offsetY = 0;
+ },
+
+ /**
+ * 璁剧疆婊戝姩寮�濮嬩綅缃�
+ * @param {Object} event
+ */
+ stopTouchStart(event) {
+ this.resetTouchStatus();
+ const touch = event.touches[0];
+ this.startX = touch.clientX;
+ this.startY = touch.clientY;
+ },
+
+ /**
+ * 婊戝姩涓紝鏄惁绂佹鎵撳紑
+ * @param {Object} event
+ */
+ stopTouchMove(event) {
+ const touch = event.touches[0];
+ this.deltaX = touch.clientX - this.startX;
+ this.deltaY = touch.clientY - this.startY;
+ this.offsetX = Math.abs(this.deltaX);
+ this.offsetY = Math.abs(this.deltaY);
+ this.direction = this.direction || this.getDirection(this.offsetX, this.offsetY);
+ },
+
+ getSelectorQuery() {
+ const views = uni.createSelectorQuery().in(this)
+ views
+ .selectAll('.' + this.elClass)
+ .boundingClientRect(data => {
+ if (data.length === 0) return
+ let show = 'none'
+ if (this.autoClose) {
+ show = 'none'
+ } else {
+ show = this.show
+ }
+ this.leftWidth = data[0].width || 0
+ this.rightWidth = data[1].width || 0
+ this.buttonShow = show
+ })
+ .exec()
+ }
+ }
+}
+
+// #endif
+
+export default otherMixins
diff --git a/app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpwxs.js b/app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpwxs.js
new file mode 100644
index 0000000..08de1c9
--- /dev/null
+++ b/app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpwxs.js
@@ -0,0 +1,84 @@
+let mpMixins = {}
+let is_pc = null
+// #ifdef H5
+import {
+ isPC
+} from "./isPC"
+is_pc = isPC()
+// #endif
+// #ifdef APP-VUE|| MP-WEIXIN || H5
+
+mpMixins = {
+ data() {
+ return {
+ is_show: 'none'
+ }
+ },
+ watch: {
+ show(newVal) {
+ this.is_show = this.show
+ }
+ },
+ created() {
+ this.swipeaction = this.getSwipeAction()
+ if (this.swipeaction && Array.isArray(this.swipeaction.children)) {
+ this.swipeaction.children.push(this)
+ }
+ },
+ mounted() {
+ this.is_show = this.show
+ },
+ methods: {
+ // wxs 涓皟鐢�
+ closeSwipe(e) {
+ if (this.autoClose && this.swipeaction) {
+ this.swipeaction.closeOther(this)
+ }
+ },
+
+ change(e) {
+ this.$emit('change', e.open)
+ if (this.is_show !== e.open) {
+ this.is_show = e.open
+ }
+ },
+
+ appTouchStart(e) {
+ if (is_pc) return
+ const {
+ clientX
+ } = e.changedTouches[0]
+ this.clientX = clientX
+ this.timestamp = new Date().getTime()
+ },
+ appTouchEnd(e, index, item, position) {
+ if (is_pc) return
+ const {
+ clientX
+ } = e.changedTouches[0]
+ // fixed by xxxx 妯℃嫙鐐瑰嚮浜嬩欢锛岃В鍐� ios 13 鐐瑰嚮鍖哄煙閿欎綅鐨勯棶棰�
+ let diff = Math.abs(this.clientX - clientX)
+ let time = (new Date().getTime()) - this.timestamp
+ if (diff < 40 && time < 300) {
+ this.$emit('click', {
+ content: item,
+ index,
+ position
+ })
+ }
+ },
+ onClickForPC(index, item, position) {
+ if (!is_pc) return
+ // #ifdef H5
+ this.$emit('click', {
+ content: item,
+ index,
+ position
+ })
+ // #endif
+ }
+ }
+}
+
+// #endif
+export default mpMixins
diff --git a/app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/render.js b/app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/render.js
new file mode 100644
index 0000000..78f0ec6
--- /dev/null
+++ b/app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/render.js
@@ -0,0 +1,270 @@
+const MIN_DISTANCE = 10;
+export default {
+ showWatch(newVal, oldVal, ownerInstance, instance, self) {
+ var state = self.state
+ var $el = ownerInstance.$el || ownerInstance.$vm && ownerInstance.$vm.$el
+ if (!$el) return
+ this.getDom(instance, ownerInstance, self)
+ if (newVal && newVal !== 'none') {
+ this.openState(newVal, instance, ownerInstance, self)
+ return
+ }
+
+ if (state.left) {
+ this.openState('none', instance, ownerInstance, self)
+ }
+ this.resetTouchStatus(instance, self)
+ },
+
+ /**
+ * 寮�濮嬭Е鎽告搷浣�
+ * @param {Object} e
+ * @param {Object} ins
+ */
+ touchstart(e, ownerInstance, self) {
+ let instance = e.instance;
+ let disabled = instance.getDataset().disabled
+ let state = self.state;
+ this.getDom(instance, ownerInstance, self)
+ // fix by mehaotian, TODO 鍏煎 app-vue 鑾峰彇dataset涓哄瓧绗︿覆 , h5 鑾峰彇 涓� undefined 鐨勯棶棰�,寰呮鏋朵慨澶�
+ disabled = this.getDisabledType(disabled)
+ if (disabled) return
+ // 寮�濮嬭Е鎽告椂绉婚櫎鍔ㄧ敾绫�
+ instance.requestAnimationFrame(function() {
+ instance.removeClass('ani');
+ ownerInstance.callMethod('closeSwipe');
+ })
+
+ // 璁板綍涓婃鐨勪綅缃�
+ state.x = state.left || 0
+ // 璁$畻婊戝姩寮�濮嬩綅缃�
+ this.stopTouchStart(e, ownerInstance, self)
+ },
+
+ /**
+ * 寮�濮嬫粦鍔ㄦ搷浣�
+ * @param {Object} e
+ * @param {Object} ownerInstance
+ */
+ touchmove(e, ownerInstance, self) {
+ let instance = e.instance;
+ // 鍒犻櫎涔嬪悗宸茬粡閭d笉鍒板疄渚嬩簡
+ if (!instance) return;
+ let disabled = instance.getDataset().disabled
+ let state = self.state
+ // fix by mehaotian, TODO 鍏煎 app-vue 鑾峰彇dataset涓哄瓧绗︿覆 , h5 鑾峰彇 涓� undefined 鐨勯棶棰�,寰呮鏋朵慨澶�
+ disabled = this.getDisabledType(disabled)
+ if (disabled) return
+ // 鏄惁鍙互婊戝姩椤甸潰
+ this.stopTouchMove(e, self);
+ if (state.direction !== 'horizontal') {
+ return;
+ }
+ if (e.preventDefault) {
+ // 闃绘椤甸潰婊氬姩
+ e.preventDefault()
+ }
+ let x = state.x + state.deltaX
+ this.move(x, instance, ownerInstance, self)
+ },
+
+ /**
+ * 缁撴潫瑙︽懜鎿嶄綔
+ * @param {Object} e
+ * @param {Object} ownerInstance
+ */
+ touchend(e, ownerInstance, self) {
+ let instance = e.instance;
+ let disabled = instance.getDataset().disabled
+ let state = self.state
+ // fix by mehaotian, TODO 鍏煎 app-vue 鑾峰彇dataset涓哄瓧绗︿覆 , h5 鑾峰彇 涓� undefined 鐨勯棶棰�,寰呮鏋朵慨澶�
+ disabled = this.getDisabledType(disabled)
+
+ if (disabled) return
+ // 婊戝姩杩囩▼涓Е鎽哥粨鏉�,閫氳繃闃欏�煎垽鏂槸寮�鍚繕鏄叧闂�
+ // fixed by mehaotian 瀹氭椂鍣ㄨВ鍐崇偣鍑绘寜閽紝touchend 瑙﹀彂姣� click 浜嬩欢鏃舵満鏃╃殑闂 锛屼富瑕佹槸 ios13
+ this.moveDirection(state.left, instance, ownerInstance, self)
+
+ },
+
+ /**
+ * 璁剧疆绉诲姩璺濈
+ * @param {Object} value
+ * @param {Object} instance
+ * @param {Object} ownerInstance
+ */
+ move(value, instance, ownerInstance, self) {
+ value = value || 0
+ let state = self.state
+ let leftWidth = state.leftWidth
+ let rightWidth = state.rightWidth
+ // 鑾峰彇鍙粦鍔ㄨ寖鍥�
+ state.left = this.range(value, -rightWidth, leftWidth);
+ instance.requestAnimationFrame(function() {
+ instance.setStyle({
+ transform: 'translateX(' + state.left + 'px)',
+ '-webkit-transform': 'translateX(' + state.left + 'px)'
+ })
+ })
+
+ },
+
+ /**
+ * 鑾峰彇鍏冪礌淇℃伅
+ * @param {Object} instance
+ * @param {Object} ownerInstance
+ */
+ getDom(instance, ownerInstance, self) {
+ var state = self.state
+ var $el = ownerInstance.$el || ownerInstance.$vm && ownerInstance.$vm.$el
+ var leftDom = $el.querySelector('.button-group--left')
+ var rightDom = $el.querySelector('.button-group--right')
+
+ state.leftWidth = leftDom.offsetWidth || 0
+ state.rightWidth = rightDom.offsetWidth || 0
+ state.threshold = instance.getDataset().threshold
+ },
+
+ getDisabledType(value) {
+ return (typeof(value) === 'string' ? JSON.parse(value) : value) || false;
+ },
+
+ /**
+ * 鑾峰彇鑼冨洿
+ * @param {Object} num
+ * @param {Object} min
+ * @param {Object} max
+ */
+ range(num, min, max) {
+ return Math.min(Math.max(num, min), max);
+ },
+
+
+ /**
+ * 绉诲姩鏂瑰悜鍒ゆ柇
+ * @param {Object} left
+ * @param {Object} value
+ * @param {Object} ownerInstance
+ * @param {Object} ins
+ */
+ moveDirection(left, ins, ownerInstance, self) {
+ var state = self.state
+ var threshold = state.threshold
+ var position = state.position
+ var isopen = state.isopen || 'none'
+ var leftWidth = state.leftWidth
+ var rightWidth = state.rightWidth
+ if (state.deltaX === 0) {
+ this.openState('none', ins, ownerInstance, self)
+ return
+ }
+ if ((isopen === 'none' && rightWidth > 0 && -left > threshold) || (isopen !== 'none' && rightWidth > 0 &&
+ rightWidth +
+ left < threshold)) {
+ // right
+ this.openState('right', ins, ownerInstance, self)
+ } else if ((isopen === 'none' && leftWidth > 0 && left > threshold) || (isopen !== 'none' && leftWidth > 0 &&
+ leftWidth - left < threshold)) {
+ // left
+ this.openState('left', ins, ownerInstance, self)
+ } else {
+ // default
+ this.openState('none', ins, ownerInstance, self)
+ }
+ },
+
+
+ /**
+ * 寮�鍚姸鎬�
+ * @param {Boolean} type
+ * @param {Object} ins
+ * @param {Object} ownerInstance
+ */
+ openState(type, ins, ownerInstance, self) {
+ let state = self.state
+ let leftWidth = state.leftWidth
+ let rightWidth = state.rightWidth
+ let left = ''
+ state.isopen = state.isopen ? state.isopen : 'none'
+ switch (type) {
+ case "left":
+ left = leftWidth
+ break
+ case "right":
+ left = -rightWidth
+ break
+ default:
+ left = 0
+ }
+
+ // && !state.throttle
+
+ if (state.isopen !== type) {
+ state.throttle = true
+ ownerInstance.callMethod('change', {
+ open: type
+ })
+
+ }
+
+ state.isopen = type
+ // 娣诲姞鍔ㄧ敾绫�
+ ins.requestAnimationFrame(() => {
+ ins.addClass('ani');
+ this.move(left, ins, ownerInstance, self)
+ })
+ },
+
+
+ getDirection(x, y) {
+ if (x > y && x > MIN_DISTANCE) {
+ return 'horizontal';
+ }
+ if (y > x && y > MIN_DISTANCE) {
+ return 'vertical';
+ }
+ return '';
+ },
+
+ /**
+ * 閲嶇疆婊戝姩鐘舵��
+ * @param {Object} event
+ */
+ resetTouchStatus(instance, self) {
+ let state = self.state;
+ state.direction = '';
+ state.deltaX = 0;
+ state.deltaY = 0;
+ state.offsetX = 0;
+ state.offsetY = 0;
+ },
+
+ /**
+ * 璁剧疆婊戝姩寮�濮嬩綅缃�
+ * @param {Object} event
+ */
+ stopTouchStart(event, ownerInstance, self) {
+ let instance = event.instance;
+ let state = self.state
+ this.resetTouchStatus(instance, self);
+ var touch = event.touches[0];
+ state.startX = touch.clientX;
+ state.startY = touch.clientY;
+ },
+
+ /**
+ * 婊戝姩涓紝鏄惁绂佹鎵撳紑
+ * @param {Object} event
+ */
+ stopTouchMove(event, self) {
+ let instance = event.instance;
+ let state = self.state;
+ let touch = event.touches[0];
+
+ state.deltaX = touch.clientX - state.startX;
+ state.deltaY = touch.clientY - state.startY;
+ state.offsetY = Math.abs(state.deltaY);
+ state.offsetX = Math.abs(state.deltaX);
+ state.direction = state.direction || this.getDirection(state.offsetX, state.offsetY);
+ }
+}
diff --git a/app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/uni-swipe-action-item.vue b/app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/uni-swipe-action-item.vue
new file mode 100644
index 0000000..d79c297
--- /dev/null
+++ b/app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/uni-swipe-action-item.vue
@@ -0,0 +1,347 @@
+<template>
+ <!-- 鍦ㄥ井淇″皬绋嬪簭 app vue绔� h5 浣跨敤wxs 瀹炵幇-->
+ <!-- #ifdef APP-VUE || MP-WEIXIN || H5 -->
+ <view class="uni-swipe">
+ <!-- #ifdef MP-WEIXIN || VUE3 -->
+ <view class="uni-swipe_box" :change:prop="wxsswipe.showWatch" :prop="is_show" :data-threshold="threshold"
+ :data-disabled="disabled" @touchstart="wxsswipe.touchstart" @touchmove="wxsswipe.touchmove"
+ @touchend="wxsswipe.touchend">
+ <!-- #endif -->
+ <!-- #ifndef MP-WEIXIN || VUE3 -->
+ <view class="uni-swipe_box" :change:prop="renderswipe.showWatch" :prop="is_show" :data-threshold="threshold"
+ :data-disabled="disabled+''" @touchstart="renderswipe.touchstart" @touchmove="renderswipe.touchmove"
+ @touchend="renderswipe.touchend">
+ <!-- #endif -->
+ <!-- 鍦ㄥ井淇″皬绋嬪簭 app vue绔� h5 浣跨敤wxs 瀹炵幇-->
+ <view class="uni-swipe_button-group button-group--left">
+ <slot name="left">
+ <view v-for="(item,index) in leftOptions" :key="index" :style="{
+ backgroundColor: item.style && item.style.backgroundColor ? item.style.backgroundColor : '#C7C6CD'
+ }" class="uni-swipe_button button-hock" @touchstart="appTouchStart"
+ @touchend="appTouchEnd($event,index,item,'left')"
+ @click.stop="onClickForPC(index,item,'left')">
+ <text class="uni-swipe_button-text"
+ :style="{color: item.style && item.style.color ? item.style.color : '#FFFFFF',fontSize: item.style && item.style.fontSize ? item.style.fontSize : '16px'}">{{ item.text }}</text>
+ </view>
+ </slot>
+ </view>
+ <view class="uni-swipe_text--center">
+ <slot></slot>
+ </view>
+ <view class="uni-swipe_button-group button-group--right">
+ <slot name="right">
+ <view v-for="(item,index) in rightOptions" :key="index" :style="{
+ backgroundColor: item.style && item.style.backgroundColor ? item.style.backgroundColor : '#C7C6CD'
+ }" class="uni-swipe_button button-hock" @touchstart="appTouchStart"
+ @touchend="appTouchEnd($event,index,item,'right')"
+ @click.stop="onClickForPC(index,item,'right')"><text class="uni-swipe_button-text"
+ :style="{color: item.style && item.style.color ? item.style.color : '#FFFFFF',fontSize: item.style && item.style.fontSize ? item.style.fontSize : '16px'}">{{ item.text }}</text>
+ </view>
+ </slot>
+ </view>
+ </view>
+ </view>
+ <!-- #endif -->
+ <!-- app nvue绔� 浣跨敤 bindingx -->
+ <!-- #ifdef APP-NVUE -->
+ <view ref="selector-box--hock" class="uni-swipe" @horizontalpan="touchstart" @touchend="touchend">
+ <view ref='selector-left-button--hock' class="uni-swipe_button-group button-group--left">
+ <slot name="left">
+ <view v-for="(item,index) in leftOptions" :key="index" :style="{
+ backgroundColor: item.style && item.style.backgroundColor ? item.style.backgroundColor : '#C7C6CD'
+ }" class="uni-swipe_button button-hock" @click.stop="onClick(index,item,'left')"><text
+ class="uni-swipe_button-text"
+ :style="{color: item.style && item.style.color ? item.style.color : '#FFFFFF', fontSize: item.style && item.style.fontSize ? item.style.fontSize : '16px'}">{{ item.text }}</text>
+ </view>
+ </slot>
+ </view>
+ <view ref='selector-right-button--hock' class="uni-swipe_button-group button-group--right">
+ <slot name="right">
+ <view v-for="(item,index) in rightOptions" :key="index" :style="{
+ backgroundColor: item.style && item.style.backgroundColor ? item.style.backgroundColor : '#C7C6CD'
+ }" class="uni-swipe_button button-hock" @click.stop="onClick(index,item,'right')"><text
+ class="uni-swipe_button-text"
+ :style="{color: item.style && item.style.color ? item.style.color : '#FFFFFF',fontSize: item.style && item.style.fontSize ? item.style.fontSize : '16px'}">{{ item.text }}</text>
+ </view>
+ </slot>
+ </view>
+ <view ref='selector-content--hock' class="uni-swipe_box">
+ <slot></slot>
+ </view>
+ </view>
+ <!-- #endif -->
+ <!-- 鍏朵粬骞冲彴浣跨敤 js 锛岄暱鍒楄〃鎬ц兘鍙兘浼氭湁褰卞搷-->
+ <!-- #ifdef MP-ALIPAY || MP-BAIDU || MP-TOUTIAO || MP-QQ -->
+ <view class="uni-swipe">
+ <view class="uni-swipe_box" @touchstart="touchstart" @touchmove="touchmove" @touchend="touchend"
+ :style="{transform:moveLeft}" :class="{ani:ani}">
+ <view class="uni-swipe_button-group button-group--left" :class="[elClass]">
+ <slot name="left">
+ <view v-for="(item,index) in leftOptions" :key="index" :style="{
+ backgroundColor: item.style && item.style.backgroundColor ? item.style.backgroundColor : '#C7C6CD',
+ fontSize: item.style && item.style.fontSize ? item.style.fontSize : '16px'
+ }" class="uni-swipe_button button-hock" @touchstart="appTouchStart"
+ @touchend="appTouchEnd($event,index,item,'left')"><text class="uni-swipe_button-text"
+ :style="{color: item.style && item.style.color ? item.style.color : '#FFFFFF',}">{{ item.text }}</text>
+ </view>
+ </slot>
+ </view>
+ <slot></slot>
+ <view class="uni-swipe_button-group button-group--right" :class="[elClass]">
+ <slot name="right">
+ <view v-for="(item,index) in rightOptions" :key="index" :style="{
+ backgroundColor: item.style && item.style.backgroundColor ? item.style.backgroundColor : '#C7C6CD',
+ fontSize: item.style && item.style.fontSize ? item.style.fontSize : '16px'
+ }" @touchstart="appTouchStart" @touchend="appTouchEnd($event,index,item,'right')"
+ class="uni-swipe_button button-hock"><text class="uni-swipe_button-text"
+ :style="{color: item.style && item.style.color ? item.style.color : '#FFFFFF',}">{{ item.text }}</text>
+ </view>
+ </slot>
+ </view>
+ </view>
+ </view>
+ <!-- #endif -->
+
+</template>
+<script src="./wx.wxs" module="wxsswipe" lang="wxs"></script>
+
+<script module="renderswipe" lang="renderjs">
+ import render from './render.js'
+ export default {
+ mounted(e, ins, owner) {
+ this.state = {}
+ },
+ methods: {
+ showWatch(newVal, oldVal, ownerInstance, instance) {
+ render.showWatch(newVal, oldVal, ownerInstance, instance, this)
+ },
+ touchstart(e, ownerInstance) {
+ render.touchstart(e, ownerInstance, this)
+ },
+ touchmove(e, ownerInstance) {
+ render.touchmove(e, ownerInstance, this)
+ },
+ touchend(e, ownerInstance) {
+ render.touchend(e, ownerInstance, this)
+ }
+ }
+ }
+</script>
+<script>
+ import mpwxs from './mpwxs'
+ import bindingx from './bindingx.js'
+ import mpother from './mpother'
+
+ /**
+ * SwipeActionItem 婊戝姩鎿嶄綔瀛愮粍浠�
+ * @description 閫氳繃婊戝姩瑙﹀彂閫夐」鐨勫鍣�
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=181
+ * @property {Boolean} show = [left|right锝渘one] 寮�鍚叧闂粍浠讹紝auto-close = false 鏃剁敓鏁�
+ * @property {Boolean} disabled = [true|false] 鏄惁绂佹婊戝姩
+ * @property {Boolean} autoClose = [true|false] 婊戝姩鎵撳紑褰撳墠缁勪欢锛屾槸鍚﹀叧闂叾浠栫粍浠�
+ * @property {Number} threshold 婊戝姩缂虹渷鍊�
+ * @property {Array} leftOptions 宸︿晶閫夐」鍐呭鍙婃牱寮�
+ * @property {Array} rgihtOptions 鍙充晶閫夐」鍐呭鍙婃牱寮�
+ * @event {Function} click 鐐瑰嚮閫夐」鎸夐挳鏃惰Е鍙戜簨浠讹紝e = {content,index} 锛宑ontent锛堢偣鍑诲唴瀹癸級銆乮ndex锛堜笅鏍�)
+ * @event {Function} change 缁勪欢鎵撳紑鎴栧叧闂椂瑙﹀彂锛宭eft\right\none
+ */
+
+ export default {
+ mixins: [mpwxs, bindingx, mpother],
+ emits: ['click', 'change'],
+ props: {
+ // 鎺у埗寮�鍏�
+ show: {
+ type: String,
+ default: 'none'
+ },
+
+ // 绂佺敤
+ disabled: {
+ type: Boolean,
+ default: false
+ },
+
+ // 鏄惁鑷姩鍏抽棴
+ autoClose: {
+ type: Boolean,
+ default: true
+ },
+
+ // 婊戝姩缂虹渷璺濈
+ threshold: {
+ type: Number,
+ default: 20
+ },
+
+ // 宸︿晶鎸夐挳鍐呭
+ leftOptions: {
+ type: Array,
+ default () {
+ return []
+ }
+ },
+
+ // 鍙充晶鎸夐挳鍐呭
+ rightOptions: {
+ type: Array,
+ default () {
+ return []
+ }
+ }
+
+ },
+ // #ifndef VUE3
+ // TODO vue2
+ destroyed() {
+ if (this.__isUnmounted) return
+ this.uninstall()
+ },
+ // #endif
+ // #ifdef VUE3
+ // TODO vue3
+ unmounted() {
+ this.__isUnmounted = true
+ this.uninstall()
+ },
+ // #endif
+
+ methods: {
+ uninstall() {
+ if (this.swipeaction) {
+ this.swipeaction.children.forEach((item, index) => {
+ if (item === this) {
+ this.swipeaction.children.splice(index, 1)
+ }
+ })
+ }
+ },
+ /**
+ * 鑾峰彇鐖跺厓绱犲疄渚�
+ */
+ getSwipeAction(name = 'uniSwipeAction') {
+ let parent = this.$parent;
+ let parentName = parent.$options.name;
+ while (parentName !== name) {
+ parent = parent.$parent;
+ if (!parent) return false;
+ parentName = parent.$options.name;
+ }
+ return parent;
+ }
+ }
+ }
+</script>
+<style lang="scss">
+ .uni-swipe {
+ position: relative;
+ /* #ifndef APP-NVUE */
+ overflow: hidden;
+ /* #endif */
+ }
+
+ .uni-swipe_box {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ flex-shrink: 0;
+ // touch-action: none;
+ /* #endif */
+ position: relative;
+ }
+
+ .uni-swipe_content {
+ // border: 1px red solid;
+ }
+
+ .uni-swipe_text--center {
+ width: 100%;
+ /* #ifndef APP-NVUE */
+ cursor: grab;
+ /* #endif */
+ }
+
+ .uni-swipe_button-group {
+ /* #ifndef APP-NVUE */
+ box-sizing: border-box;
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ /* #ifdef H5 */
+ cursor: pointer;
+ /* #endif */
+ }
+
+ .button-group--left {
+ left: 0;
+ transform: translateX(-100%)
+ }
+
+ .button-group--right {
+ right: 0;
+ transform: translateX(100%)
+ }
+
+ .uni-swipe_button {
+ /* #ifdef APP-NVUE */
+ flex: 1;
+ /* #endif */
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+ justify-content: center;
+ align-items: center;
+ padding: 0 20px;
+ }
+
+ .uni-swipe_button-text {
+ /* #ifndef APP-NVUE */
+ flex-shrink: 0;
+ /* #endif */
+ font-size: 14px;
+ }
+
+ .ani {
+ transition-property: transform;
+ transition-duration: 0.3s;
+ transition-timing-function: cubic-bezier(0.165, 0.84, 0.44, 1);
+ }
+
+ /* #ifdef MP-ALIPAY */
+ .movable-area {
+ /* width: 100%; */
+ height: 45px;
+ }
+
+ .movable-view {
+ display: flex;
+ /* justify-content: center; */
+ position: relative;
+ flex: 1;
+ height: 45px;
+ z-index: 2;
+ }
+
+ .movable-view-button {
+ display: flex;
+ flex-shrink: 0;
+ flex-direction: row;
+ height: 100%;
+ background: #C0C0C0;
+ }
+
+ /* .transition {
+ transition: all 0.3s;
+ } */
+
+ .movable-view-box {
+ flex-shrink: 0;
+ height: 100%;
+ background-color: #fff;
+ }
+
+ /* #endif */
+</style>
diff --git a/app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/wx.wxs b/app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/wx.wxs
new file mode 100644
index 0000000..b394244
--- /dev/null
+++ b/app/uni_modules/uni-swipe-action/components/uni-swipe-action-item/wx.wxs
@@ -0,0 +1,341 @@
+var MIN_DISTANCE = 10;
+
+/**
+ * 鍒ゆ柇褰撳墠鏄惁涓篐5銆乤pp-vue
+ */
+var IS_HTML5 = false
+if (typeof window === 'object') IS_HTML5 = true
+
+/**
+ * 鐩戝惉椤甸潰鍐呭�肩殑鍙樺寲,涓昏鐢ㄤ簬鍔ㄦ�佸紑鍏硈wipe-action
+ * @param {Object} newValue
+ * @param {Object} oldValue
+ * @param {Object} ownerInstance
+ * @param {Object} instance
+ */
+function showWatch(newVal, oldVal, ownerInstance, instance) {
+ var state = instance.getState()
+ getDom(instance, ownerInstance)
+ if (newVal && newVal !== 'none') {
+ openState(newVal, instance, ownerInstance)
+ return
+ }
+
+ if (state.left) {
+ openState('none', instance, ownerInstance)
+ }
+ resetTouchStatus(instance)
+}
+
+/**
+ * 寮�濮嬭Е鎽告搷浣�
+ * @param {Object} e
+ * @param {Object} ins
+ */
+function touchstart(e, ownerInstance) {
+ var instance = e.instance;
+ var disabled = instance.getDataset().disabled
+ var state = instance.getState();
+ getDom(instance, ownerInstance)
+ // fix by mehaotian, TODO 鍏煎 app-vue 鑾峰彇dataset涓哄瓧绗︿覆 , h5 鑾峰彇 涓� undefined 鐨勯棶棰�,寰呮鏋朵慨澶�
+ disabled = (typeof(disabled) === 'string' ? JSON.parse(disabled) : disabled) || false;
+ if (disabled) return
+ // 寮�濮嬭Е鎽告椂绉婚櫎鍔ㄧ敾绫�
+ instance.requestAnimationFrame(function() {
+ instance.removeClass('ani');
+ ownerInstance.callMethod('closeSwipe');
+ })
+
+ // 璁板綍涓婃鐨勪綅缃�
+ state.x = state.left || 0
+ // 璁$畻婊戝姩寮�濮嬩綅缃�
+ stopTouchStart(e, ownerInstance)
+}
+
+/**
+ * 寮�濮嬫粦鍔ㄦ搷浣�
+ * @param {Object} e
+ * @param {Object} ownerInstance
+ */
+function touchmove(e, ownerInstance) {
+ var instance = e.instance;
+ var disabled = instance.getDataset().disabled
+ var state = instance.getState()
+ // fix by mehaotian, TODO 鍏煎 app-vue 鑾峰彇dataset涓哄瓧绗︿覆 , h5 鑾峰彇 涓� undefined 鐨勯棶棰�,寰呮鏋朵慨澶�
+ disabled = (typeof(disabled) === 'string' ? JSON.parse(disabled) : disabled) || false;
+ if (disabled) return
+ // 鏄惁鍙互婊戝姩椤甸潰
+ stopTouchMove(e);
+ if (state.direction !== 'horizontal') {
+ return;
+ }
+
+ if (e.preventDefault) {
+ // 闃绘椤甸潰婊氬姩
+ e.preventDefault()
+ }
+
+ move(state.x + state.deltaX, instance, ownerInstance)
+}
+
+/**
+ * 缁撴潫瑙︽懜鎿嶄綔
+ * @param {Object} e
+ * @param {Object} ownerInstance
+ */
+function touchend(e, ownerInstance) {
+ var instance = e.instance;
+ var disabled = instance.getDataset().disabled
+ var state = instance.getState()
+ // fix by mehaotian, TODO 鍏煎 app-vue 鑾峰彇dataset涓哄瓧绗︿覆 , h5 鑾峰彇 涓� undefined 鐨勯棶棰�,寰呮鏋朵慨澶�
+ disabled = (typeof(disabled) === 'string' ? JSON.parse(disabled) : disabled) || false;
+
+ if (disabled) return
+ // 婊戝姩杩囩▼涓Е鎽哥粨鏉�,閫氳繃闃欏�煎垽鏂槸寮�鍚繕鏄叧闂�
+ // fixed by mehaotian 瀹氭椂鍣ㄨВ鍐崇偣鍑绘寜閽紝touchend 瑙﹀彂姣� click 浜嬩欢鏃舵満鏃╃殑闂 锛屼富瑕佹槸 ios13
+ moveDirection(state.left, instance, ownerInstance)
+
+}
+
+/**
+ * 璁剧疆绉诲姩璺濈
+ * @param {Object} value
+ * @param {Object} instance
+ * @param {Object} ownerInstance
+ */
+function move(value, instance, ownerInstance) {
+ value = value || 0
+ var state = instance.getState()
+ var leftWidth = state.leftWidth
+ var rightWidth = state.rightWidth
+ // 鑾峰彇鍙粦鍔ㄨ寖鍥�
+ state.left = range(value, -rightWidth, leftWidth);
+ instance.requestAnimationFrame(function() {
+ instance.setStyle({
+ transform: 'translateX(' + state.left + 'px)',
+ '-webkit-transform': 'translateX(' + state.left + 'px)'
+ })
+ })
+
+}
+
+/**
+ * 鑾峰彇鍏冪礌淇℃伅
+ * @param {Object} instance
+ * @param {Object} ownerInstance
+ */
+function getDom(instance, ownerInstance) {
+ var state = instance.getState()
+ var leftDom = ownerInstance.selectComponent('.button-group--left')
+ var rightDom = ownerInstance.selectComponent('.button-group--right')
+ var leftStyles = {
+ width: 0
+ }
+ var rightStyles = {
+ width: 0
+ }
+ leftStyles = leftDom.getBoundingClientRect()
+ rightStyles = rightDom.getBoundingClientRect()
+
+ state.leftWidth = leftStyles.width || 0
+ state.rightWidth = rightStyles.width || 0
+ state.threshold = instance.getDataset().threshold
+}
+
+/**
+ * 鑾峰彇鑼冨洿
+ * @param {Object} num
+ * @param {Object} min
+ * @param {Object} max
+ */
+function range(num, min, max) {
+ return Math.min(Math.max(num, min), max);
+}
+
+
+/**
+ * 绉诲姩鏂瑰悜鍒ゆ柇
+ * @param {Object} left
+ * @param {Object} value
+ * @param {Object} ownerInstance
+ * @param {Object} ins
+ */
+function moveDirection(left, ins, ownerInstance) {
+ var state = ins.getState()
+ var threshold = state.threshold
+ var position = state.position
+ var isopen = state.isopen || 'none'
+ var leftWidth = state.leftWidth
+ var rightWidth = state.rightWidth
+ if (state.deltaX === 0) {
+ openState('none', ins, ownerInstance)
+ return
+ }
+ if ((isopen === 'none' && rightWidth > 0 && -left > threshold) || (isopen !== 'none' && rightWidth > 0 &&
+ rightWidth +
+ left < threshold)) {
+ // right
+ openState('right', ins, ownerInstance)
+ } else if ((isopen === 'none' && leftWidth > 0 && left > threshold) || (isopen !== 'none' && leftWidth > 0 &&
+ leftWidth - left < threshold)) {
+ // left
+ openState('left', ins, ownerInstance)
+ } else {
+ // default
+ openState('none', ins, ownerInstance)
+ }
+}
+
+
+/**
+ * 寮�鍚姸鎬�
+ * @param {Boolean} type
+ * @param {Object} ins
+ * @param {Object} ownerInstance
+ */
+function openState(type, ins, ownerInstance) {
+ var state = ins.getState()
+ var leftWidth = state.leftWidth
+ var rightWidth = state.rightWidth
+ var left = ''
+ state.isopen = state.isopen ? state.isopen : 'none'
+ switch (type) {
+ case "left":
+ left = leftWidth
+ break
+ case "right":
+ left = -rightWidth
+ break
+ default:
+ left = 0
+ }
+
+ // && !state.throttle
+
+ if (state.isopen !== type) {
+ state.throttle = true
+ ownerInstance.callMethod('change', {
+ open: type
+ })
+
+ }
+
+ state.isopen = type
+ // 娣诲姞鍔ㄧ敾绫�
+ ins.requestAnimationFrame(function() {
+ ins.addClass('ani');
+ move(left, ins, ownerInstance)
+ })
+ // 璁剧疆鏈�缁堢Щ鍔ㄤ綅缃�,鐞嗚涓婂彧瑕佽繘鍏ュ埌杩欎釜鍑芥暟锛岃偗瀹氭槸瑕佹墦寮�鐨�
+}
+
+
+function getDirection(x, y) {
+ if (x > y && x > MIN_DISTANCE) {
+ return 'horizontal';
+ }
+ if (y > x && y > MIN_DISTANCE) {
+ return 'vertical';
+ }
+ return '';
+}
+
+/**
+ * 閲嶇疆婊戝姩鐘舵��
+ * @param {Object} event
+ */
+function resetTouchStatus(instance) {
+ var state = instance.getState();
+ state.direction = '';
+ state.deltaX = 0;
+ state.deltaY = 0;
+ state.offsetX = 0;
+ state.offsetY = 0;
+}
+
+/**
+ * 璁剧疆婊戝姩寮�濮嬩綅缃�
+ * @param {Object} event
+ */
+function stopTouchStart(event) {
+ var instance = event.instance;
+ var state = instance.getState();
+ resetTouchStatus(instance);
+ var touch = event.touches[0];
+ if (IS_HTML5 && isPC()) {
+ touch = event;
+ }
+ state.startX = touch.clientX;
+ state.startY = touch.clientY;
+}
+
+/**
+ * 婊戝姩涓紝鏄惁绂佹鎵撳紑
+ * @param {Object} event
+ */
+function stopTouchMove(event) {
+ var instance = event.instance;
+ var state = instance.getState();
+ var touch = event.touches[0];
+ if (IS_HTML5 && isPC()) {
+ touch = event;
+ }
+ state.deltaX = touch.clientX - state.startX;
+ state.deltaY = touch.clientY - state.startY;
+ state.offsetY = Math.abs(state.deltaY);
+ state.offsetX = Math.abs(state.deltaX);
+ state.direction = state.direction || getDirection(state.offsetX, state.offsetY);
+}
+
+function isPC() {
+ var userAgentInfo = navigator.userAgent;
+ var Agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"];
+ var flag = true;
+ for (var v = 0; v < Agents.length - 1; v++) {
+ if (userAgentInfo.indexOf(Agents[v]) > 0) {
+ flag = false;
+ break;
+ }
+ }
+ return flag;
+}
+
+var movable = false
+
+function mousedown(e, ins) {
+ if (!IS_HTML5) return
+ if (!isPC()) return
+ touchstart(e, ins)
+ movable = true
+}
+
+function mousemove(e, ins) {
+ if (!IS_HTML5) return
+ if (!isPC()) return
+ if (!movable) return
+ touchmove(e, ins)
+}
+
+function mouseup(e, ins) {
+ if (!IS_HTML5) return
+ if (!isPC()) return
+ touchend(e, ins)
+ movable = false
+}
+
+function mouseleave(e, ins) {
+ if (!IS_HTML5) return
+ if (!isPC()) return
+ movable = false
+}
+
+module.exports = {
+ showWatch: showWatch,
+ touchstart: touchstart,
+ touchmove: touchmove,
+ touchend: touchend,
+ mousedown: mousedown,
+ mousemove: mousemove,
+ mouseup: mouseup,
+ mouseleave: mouseleave
+}
diff --git a/app/uni_modules/uni-swipe-action/components/uni-swipe-action/uni-swipe-action.vue b/app/uni_modules/uni-swipe-action/components/uni-swipe-action/uni-swipe-action.vue
new file mode 100644
index 0000000..4971782
--- /dev/null
+++ b/app/uni_modules/uni-swipe-action/components/uni-swipe-action/uni-swipe-action.vue
@@ -0,0 +1,60 @@
+<template>
+ <view>
+ <slot></slot>
+ </view>
+</template>
+
+<script>
+ /**
+ * SwipeAction 婊戝姩鎿嶄綔
+ * @description 閫氳繃婊戝姩瑙﹀彂閫夐」鐨勫鍣�
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=181
+ */
+ export default {
+ name:"uniSwipeAction",
+ data() {
+ return {};
+ },
+ created() {
+ this.children = [];
+ },
+ methods: {
+ // 鍏紑缁欑敤鎴蜂娇鐢紝閲嶅埗缁勪欢鏍峰紡
+ resize(){
+ // wxs 浼氳嚜宸辫绠楃粍浠跺ぇ灏忥紝鎵�浠ユ棤闇�鎵ц涓嬮潰浠g爜
+ // #ifndef APP-VUE || H5 || MP-WEIXIN
+ this.children.forEach(vm=>{
+ vm.init()
+ })
+ // #endif
+ },
+ // 鍏紑缁欑敤鎴蜂娇鐢紝鍏抽棴鍏ㄩ儴 宸茬粡鎵撳紑鐨勭粍浠�
+ closeAll(){
+ this.children.forEach(vm=>{
+ // #ifdef APP-VUE || H5 || MP-WEIXIN
+ vm.is_show = 'none'
+ // #endif
+
+ // #ifndef APP-VUE || H5 || MP-WEIXIN
+ vm.close()
+ // #endif
+ })
+ },
+ closeOther(vm) {
+ if (this.openItem && this.openItem !== vm) {
+ // #ifdef APP-VUE || H5 || MP-WEIXIN
+ this.openItem.is_show = 'none'
+ // #endif
+
+ // #ifndef APP-VUE || H5 || MP-WEIXIN
+ this.openItem.close()
+ // #endif
+ }
+ // 璁板綍涓婁竴涓墦寮�鐨� swipe-action-item ,鐢ㄤ簬 auto-close
+ this.openItem = vm
+ }
+ }
+ };
+</script>
+
+<style></style>
diff --git a/app/uni_modules/uni-swipe-action/package.json b/app/uni_modules/uni-swipe-action/package.json
new file mode 100644
index 0000000..47651a6
--- /dev/null
+++ b/app/uni_modules/uni-swipe-action/package.json
@@ -0,0 +1,87 @@
+{
+ "id": "uni-swipe-action",
+ "displayName": "uni-swipe-action 婊戝姩鎿嶄綔",
+ "version": "1.3.8",
+ "description": "SwipeAction 婊戝姩鎿嶄綔鎿嶄綔缁勪欢",
+ "keywords": [
+ "",
+ "uni-ui",
+ "uniui",
+ "婊戝姩鍒犻櫎",
+ "渚ф粦鍒犻櫎"
+ ],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "鍓嶇缁勪欢",
+ "閫氱敤缁勪欢"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": ["uni-scss"],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "y",
+ "鑱旂洘": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
diff --git a/app/uni_modules/uni-swipe-action/readme.md b/app/uni_modules/uni-swipe-action/readme.md
new file mode 100644
index 0000000..93a5cac
--- /dev/null
+++ b/app/uni_modules/uni-swipe-action/readme.md
@@ -0,0 +1,11 @@
+
+
+## SwipeAction 婊戝姩鎿嶄綔
+> **缁勪欢鍚嶏細uni-swipe-action**
+> 浠g爜鍧楋細 `uSwipeAction`銆乣uSwipeActionItem`
+
+
+閫氳繃婊戝姩瑙﹀彂閫夐」鐨勫鍣�
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-swipe-action)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
\ No newline at end of file
diff --git a/app/uni_modules/uni-swiper-dot/changelog.md b/app/uni_modules/uni-swiper-dot/changelog.md
new file mode 100644
index 0000000..85cf54d
--- /dev/null
+++ b/app/uni_modules/uni-swiper-dot/changelog.md
@@ -0,0 +1,12 @@
+## 1.2.0锛�2021-11-19锛�
+- 浼樺寲 缁勪欢UI锛屽苟鎻愪緵璁捐璧勬簮锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 鏂囨。杩佺Щ锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/uni-swiper-dot](https://uniapp.dcloud.io/component/uniui/uni-swiper-dot)
+## 1.1.0锛�2021-07-30锛�
+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤簐ue3椤圭洰锛岃瑙� [uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+## 1.0.6锛�2021-05-12锛�
+- 鏂板 绀轰緥鍦板潃
+- 淇 绀轰緥椤圭洰缂哄皯缁勪欢鐨凚ug
+## 1.0.5锛�2021-02-05锛�
+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
+- 鏂板 clickItem 浜嬩欢锛屾敮鎸佹寚绀虹偣鎺у埗杞挱
+- 鏂板 鏀寔 pc 鍙敤
diff --git a/app/uni_modules/uni-swiper-dot/components/uni-swiper-dot/uni-swiper-dot.vue b/app/uni_modules/uni-swiper-dot/components/uni-swiper-dot/uni-swiper-dot.vue
new file mode 100644
index 0000000..46eb8c1
--- /dev/null
+++ b/app/uni_modules/uni-swiper-dot/components/uni-swiper-dot/uni-swiper-dot.vue
@@ -0,0 +1,218 @@
+<template>
+ <view class="uni-swiper__warp">
+ <slot />
+ <view v-if="mode === 'default'" :style="{'bottom':dots.bottom + 'px'}" class="uni-swiper__dots-box" key='default'>
+ <view v-for="(item,index) in info" @click="clickItem(index)" :style="{
+ 'width': (index === current? dots.width*2:dots.width ) + 'px','height':dots.width/2 +'px' ,'background-color':index !== current?dots.backgroundColor:dots.selectedBackgroundColor,'border-radius':'0px'}"
+ :key="index" class="uni-swiper__dots-item uni-swiper__dots-bar" />
+ </view>
+ <view v-if="mode === 'dot'" :style="{'bottom':dots.bottom + 'px'}" class="uni-swiper__dots-box" key='dot'>
+ <view v-for="(item,index) in info" @click="clickItem(index)" :style="{
+ 'width': dots.width + 'px','height':dots.height +'px' ,'background-color':index !== current?dots.backgroundColor:dots.selectedBackgroundColor,'border':index !==current ? dots.border:dots.selectedBorder}"
+ :key="index" class="uni-swiper__dots-item" />
+ </view>
+ <view v-if="mode === 'round'" :style="{'bottom':dots.bottom + 'px'}" class="uni-swiper__dots-box" key='round'>
+ <view v-for="(item,index) in info" @click="clickItem(index)" :class="[index === current&&'uni-swiper__dots-long']" :style="{
+ 'width':(index === current? dots.width*3:dots.width ) + 'px','height':dots.height +'px' ,'background-color':index !== current?dots.backgroundColor:dots.selectedBackgroundColor,'border':index !==current ? dots.border:dots.selectedBorder}"
+ :key="index" class="uni-swiper__dots-item " />
+ </view>
+ <view v-if="mode === 'nav'" key='nav' :style="{'background-color':dotsStyles.backgroundColor,'bottom':'0'}" class="uni-swiper__dots-box uni-swiper__dots-nav">
+ <text :style="{'color':dotsStyles.color}" class="uni-swiper__dots-nav-item">{{ (current+1)+"/"+info.length +' ' +info[current][field] }}</text>
+ </view>
+ <view v-if="mode === 'indexes'" key='indexes' :style="{'bottom':dots.bottom + 'px'}" class="uni-swiper__dots-box">
+ <view v-for="(item,index) in info" @click="clickItem(index)" :style="{
+ 'width':dots.width + 'px','height':dots.height +'px' ,'color':index === current?dots.selectedColor:dots.color,'background-color':index !== current?dots.backgroundColor:dots.selectedBackgroundColor,'border':index !==current ? dots.border:dots.selectedBorder}"
+ :key="index" class="uni-swiper__dots-item uni-swiper__dots-indexes"><text class="uni-swiper__dots-indexes-text">{{ index+1 }}</text></view>
+ </view>
+ </view>
+</template>
+
+<script>
+
+ /**
+ * SwiperDod 杞挱鍥炬寚绀虹偣
+ * @description 鑷畾涔夎疆鎾浘鎸囩ず鐐�
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=284
+ * @property {Number} current 褰撳墠鎸囩ず鐐圭储寮曪紝蹇呴』鏄�氳繃 `swiper` 鐨� `change` 浜嬩欢鑾峰彇鍒扮殑 `e.detail.current`
+ * @property {String} mode = [default|round|nav|indexes] 鎸囩ず鐐圭殑绫诲瀷
+ * @value defualt 榛樿鎸囩ず鐐�
+ * @value round 鍦嗗舰鎸囩ず鐐�
+ * @value nav 鏉″舰鎸囩ず鐐�
+ * @value indexes 绱㈠紩鎸囩ず鐐�
+ * @property {String} field mode 涓� nav 鏃讹紝鏄剧ず鐨勫唴瀹瑰瓧娈碉紙mode = nav 鏃跺繀濉級
+ * @property {String} info 杞挱鍥剧殑鏁版嵁锛岄�氳繃鏁扮粍闀垮害鍐冲畾鎸囩ず鐐逛釜鏁�
+ * @property {Object} dotsStyles 鎸囩ず鐐规牱寮�
+ * @event {Function} clickItem 缁勪欢瑙﹀彂鐐瑰嚮浜嬩欢鏃惰Е鍙戯紝e={currentIndex}
+ */
+
+ export default {
+ name: 'UniSwiperDot',
+ emits:['clickItem'],
+ props: {
+ info: {
+ type: Array,
+ default () {
+ return []
+ }
+ },
+ current: {
+ type: Number,
+ default: 0
+ },
+ dotsStyles: {
+ type: Object,
+ default () {
+ return {}
+ }
+ },
+ // 绫诲瀷 锛歞efault(榛樿) indexes long nav
+ mode: {
+ type: String,
+ default: 'default'
+ },
+ // 鍙湪 nav 妯″紡涓嬬敓鏁堬紝鍙橀噺鍚嶇О
+ field: {
+ type: String,
+ default: ''
+ }
+ },
+ data() {
+ return {
+ dots: {
+ width: 6,
+ height: 6,
+ bottom: 10,
+ color: '#fff',
+ backgroundColor: 'rgba(0, 0, 0, .3)',
+ border: '1px rgba(0, 0, 0, .3) solid',
+ selectedBackgroundColor: '#333',
+ selectedBorder: '1px rgba(0, 0, 0, .9) solid'
+ }
+ }
+ },
+ watch: {
+ dotsStyles(newVal) {
+ this.dots = Object.assign(this.dots, this.dotsStyles)
+ },
+ mode(newVal) {
+ if (newVal === 'indexes') {
+ this.dots.width = 14
+ this.dots.height = 14
+ } else {
+ this.dots.width = 6
+ this.dots.height = 6
+ }
+ }
+
+ },
+ created() {
+ if (this.mode === 'indexes') {
+ this.dots.width = 12
+ this.dots.height = 12
+ }
+ this.dots = Object.assign(this.dots, this.dotsStyles)
+ },
+ methods: {
+ clickItem(index) {
+ this.$emit('clickItem', index)
+ }
+ }
+ }
+</script>
+
+<style lang="scss">
+ .uni-swiper__warp {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex: 1;
+ flex-direction: column;
+ position: relative;
+ overflow: hidden;
+ }
+
+ .uni-swiper__dots-box {
+ position: absolute;
+ bottom: 10px;
+ left: 0;
+ right: 0;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex: 1;
+ flex-direction: row;
+ justify-content: center;
+ align-items: center;
+ }
+
+ .uni-swiper__dots-item {
+ width: 8px;
+ border-radius: 100px;
+ margin-left: 6px;
+ background-color: rgba(0, 0, 0, 0.4);
+ /* #ifndef APP-NVUE */
+ cursor: pointer;
+ /* #endif */
+ /* #ifdef H5 */
+ // border-width: 5px 0;
+ // border-style: solid;
+ // border-color: transparent;
+ // background-clip: padding-box;
+ /* #endif */
+ // transition: width 0.2s linear; 涓嶈鍙栨秷娉ㄩ噴锛屼笉鐒朵細涓嶈兘鍙樿壊
+ }
+
+ .uni-swiper__dots-item:first-child {
+ margin: 0;
+ }
+
+ .uni-swiper__dots-default {
+ border-radius: 100px;
+ }
+
+ .uni-swiper__dots-long {
+ border-radius: 50px;
+ }
+
+ .uni-swiper__dots-bar {
+ border-radius: 50px;
+ }
+
+ .uni-swiper__dots-nav {
+ bottom: 0px;
+ // height: 26px;
+ padding: 8px 0;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex: 1;
+ flex-direction: row;
+ justify-content: flex-start;
+ align-items: center;
+ background-color: rgba(0, 0, 0, 0.2);
+ }
+
+ .uni-swiper__dots-nav-item {
+ /* overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap; */
+ font-size: 14px;
+ color: #fff;
+ margin: 0 15px;
+ }
+
+ .uni-swiper__dots-indexes {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ // flex: 1;
+ justify-content: center;
+ align-items: center;
+ }
+
+ .uni-swiper__dots-indexes-text {
+ color: #fff;
+ font-size: 12px;
+ line-height: 14px;
+ }
+</style>
diff --git a/app/uni_modules/uni-swiper-dot/package.json b/app/uni_modules/uni-swiper-dot/package.json
new file mode 100644
index 0000000..f2dd8d2
--- /dev/null
+++ b/app/uni_modules/uni-swiper-dot/package.json
@@ -0,0 +1,87 @@
+{
+ "id": "uni-swiper-dot",
+ "displayName": "uni-swiper-dot 杞挱鍥炬寚绀虹偣",
+ "version": "1.2.0",
+ "description": "鑷畾涔夎疆鎾浘鎸囩ず鐐圭粍浠�",
+ "keywords": [
+ "uni-ui",
+ "uniui",
+ "杞挱鍥炬寚绀虹偣",
+ "dot",
+ "swiper"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "鍓嶇缁勪欢",
+ "閫氱敤缁勪欢"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": ["uni-scss"],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "u",
+ "鑱旂洘": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/uni_modules/uni-swiper-dot/readme.md b/app/uni_modules/uni-swiper-dot/readme.md
new file mode 100644
index 0000000..7d397e2
--- /dev/null
+++ b/app/uni_modules/uni-swiper-dot/readme.md
@@ -0,0 +1,11 @@
+
+
+## SwiperDot 杞挱鍥炬寚绀虹偣
+> **缁勪欢鍚嶏細uni-swiper-dot**
+> 浠g爜鍧楋細 `uSwiperDot`
+
+
+鑷畾涔夎疆鎾浘鎸囩ず鐐�
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-swiper-dot)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
\ No newline at end of file
diff --git a/app/uni_modules/uni-table/changelog.md b/app/uni_modules/uni-table/changelog.md
new file mode 100644
index 0000000..9f87c67
--- /dev/null
+++ b/app/uni_modules/uni-table/changelog.md
@@ -0,0 +1,27 @@
+## 1.2.3锛�2023-03-28锛�
+- 淇 鍦╲ue3妯″紡涓嬪彲鑳戒細鍑虹幇閿欒鐨勯棶棰�
+## 1.2.2锛�2022-11-29锛�
+- 浼樺寲 涓婚鏍峰紡
+## 1.2.1锛�2022-06-06锛�
+- 淇 寰俊灏忕▼搴忓瓨鍦ㄦ棤浣跨敤缁勪欢鐨勯棶棰�
+## 1.2.0锛�2021-11-19锛�
+- 浼樺寲 缁勪欢UI锛屽苟鎻愪緵璁捐璧勬簮锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 鏂囨。杩佺Щ锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/uni-table](https://uniapp.dcloud.io/component/uniui/uni-table)
+## 1.1.0锛�2021-07-30锛�
+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤簐ue3椤圭洰锛岃瑙� [uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+## 1.0.7锛�2021-07-08锛�
+- 鏂板 uni-th 鏀寔 date 鏃ユ湡绛涢�夎寖鍥�
+## 1.0.6锛�2021-07-05锛�
+- 鏂板 uni-th 鏀寔 range 绛涢�夎寖鍥�
+## 1.0.5锛�2021-06-28锛�
+- 鏂板 uni-th 绛涢�夊姛鑳�
+## 1.0.4锛�2021-05-12锛�
+- 鏂板 绀轰緥鍦板潃
+- 淇 绀轰緥椤圭洰缂哄皯缁勪欢鐨凚ug
+## 1.0.3锛�2021-04-16锛�
+- 鏂板 sortable 灞炴�э紝鏄惁寮�鍚崟鍒楁帓搴�
+- 浼樺寲 琛ㄦ牸澶氶�夐�昏緫
+## 1.0.2锛�2021-03-22锛�
+- uni-tr 娣诲姞 disabled 灞炴�э紝鐢ㄤ簬 type=selection 鏃讹紝璁剧疆鏌愯鏄惁鍙敱鍏ㄩ�夋寜閽帶鍒�
+## 1.0.1锛�2021-02-05锛�
+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
diff --git a/app/uni_modules/uni-table/components/uni-table/uni-table.vue b/app/uni_modules/uni-table/components/uni-table/uni-table.vue
new file mode 100644
index 0000000..21d9527
--- /dev/null
+++ b/app/uni_modules/uni-table/components/uni-table/uni-table.vue
@@ -0,0 +1,455 @@
+<template>
+ <view class="uni-table-scroll" :class="{ 'table--border': border, 'border-none': !noData }">
+ <!-- #ifdef H5 -->
+ <table class="uni-table" border="0" cellpadding="0" cellspacing="0" :class="{ 'table--stripe': stripe }" :style="{ 'min-width': minWidth + 'px' }">
+ <slot></slot>
+ <tr v-if="noData" class="uni-table-loading">
+ <td class="uni-table-text" :class="{ 'empty-border': border }">{{ emptyText }}</td>
+ </tr>
+ <view v-if="loading" class="uni-table-mask" :class="{ 'empty-border': border }"><div class="uni-table--loader"></div></view>
+ </table>
+ <!-- #endif -->
+ <!-- #ifndef H5 -->
+ <view class="uni-table" :style="{ 'min-width': minWidth + 'px' }" :class="{ 'table--stripe': stripe }">
+ <slot></slot>
+ <view v-if="noData" class="uni-table-loading">
+ <view class="uni-table-text" :class="{ 'empty-border': border }">{{ emptyText }}</view>
+ </view>
+ <view v-if="loading" class="uni-table-mask" :class="{ 'empty-border': border }"><div class="uni-table--loader"></div></view>
+ </view>
+ <!-- #endif -->
+ </view>
+</template>
+
+<script>
+/**
+ * Table 琛ㄦ牸
+ * @description 鐢ㄤ簬灞曠ず澶氭潯缁撴瀯绫讳技鐨勬暟鎹�
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=3270
+ * @property {Boolean} border 鏄惁甯︽湁绾靛悜杈规
+ * @property {Boolean} stripe 鏄惁鏄剧ず鏂戦┈绾�
+ * @property {Boolean} type 鏄惁寮�鍚閫�
+ * @property {String} emptyText 绌烘暟鎹椂鏄剧ず鐨勬枃鏈唴瀹�
+ * @property {Boolean} loading 鏄剧ず鍔犺浇涓�
+ * @event {Function} selection-change 寮�鍚閫夋椂锛屽綋閫夋嫨椤瑰彂鐢熷彉鍖栨椂浼氳Е鍙戣浜嬩欢
+ */
+export default {
+ name: 'uniTable',
+ options: {
+ virtualHost: true
+ },
+ emits:['selection-change'],
+ props: {
+ data: {
+ type: Array,
+ default() {
+ return []
+ }
+ },
+ // 鏄惁鏈夌珫绾�
+ border: {
+ type: Boolean,
+ default: false
+ },
+ // 鏄惁鏄剧ず鏂戦┈绾�
+ stripe: {
+ type: Boolean,
+ default: false
+ },
+ // 澶氶��
+ type: {
+ type: String,
+ default: ''
+ },
+ // 娌℃湁鏇村鏁版嵁
+ emptyText: {
+ type: String,
+ default: '娌℃湁鏇村鏁版嵁'
+ },
+ loading: {
+ type: Boolean,
+ default: false
+ },
+ rowKey: {
+ type: String,
+ default: ''
+ }
+ },
+ data() {
+ return {
+ noData: true,
+ minWidth: 0,
+ multiTableHeads: []
+ }
+ },
+ watch: {
+ loading(val) {},
+ data(newVal) {
+ let theadChildren = this.theadChildren
+ let rowspan = 1
+ if (this.theadChildren) {
+ rowspan = this.theadChildren.rowspan
+ }
+
+ // this.trChildren.length - rowspan
+ this.noData = false
+ // this.noData = newVal.length === 0
+ }
+ },
+ created() {
+ // 瀹氫箟tr鐨勫疄渚嬫暟缁�
+ this.trChildren = []
+ this.thChildren = []
+ this.theadChildren = null
+ this.backData = []
+ this.backIndexData = []
+ },
+
+ methods: {
+ isNodata() {
+ let theadChildren = this.theadChildren
+ let rowspan = 1
+ if (this.theadChildren) {
+ rowspan = this.theadChildren.rowspan
+ }
+ this.noData = this.trChildren.length - rowspan <= 0
+ },
+ /**
+ * 閫変腑鎵�鏈�
+ */
+ selectionAll() {
+ let startIndex = 1
+ let theadChildren = this.theadChildren
+ if (!this.theadChildren) {
+ theadChildren = this.trChildren[0]
+ } else {
+ startIndex = theadChildren.rowspan - 1
+ }
+ let isHaveData = this.data && this.data.length > 0
+ theadChildren.checked = true
+ theadChildren.indeterminate = false
+ this.trChildren.forEach((item, index) => {
+ if (!item.disabled) {
+ item.checked = true
+ if (isHaveData && item.keyValue) {
+ const row = this.data.find(v => v[this.rowKey] === item.keyValue)
+ if (!this.backData.find(v => v[this.rowKey] === row[this.rowKey])) {
+ this.backData.push(row)
+ }
+ }
+ if (index > (startIndex - 1) && this.backIndexData.indexOf(index - startIndex) === -1) {
+ this.backIndexData.push(index - startIndex)
+ }
+ }
+ })
+ // this.backData = JSON.parse(JSON.stringify(this.data))
+ this.$emit('selection-change', {
+ detail: {
+ value: this.backData,
+ index: this.backIndexData
+ }
+ })
+ },
+ /**
+ * 鐢ㄤ簬澶氶�夎〃鏍硷紝鍒囨崲鏌愪竴琛岀殑閫変腑鐘舵�侊紝濡傛灉浣跨敤浜嗙浜屼釜鍙傛暟锛屽垯鏄缃繖涓�琛岄�変腑涓庡惁锛坰elected 涓� true 鍒欓�変腑锛�
+ */
+ toggleRowSelection(row, selected) {
+ // if (!this.theadChildren) return
+ row = [].concat(row)
+
+ this.trChildren.forEach((item, index) => {
+ // if (item.keyValue) {
+
+ const select = row.findIndex(v => {
+ //
+ if (typeof v === 'number') {
+ return v === index - 1
+ } else {
+ return v[this.rowKey] === item.keyValue
+ }
+ })
+ let ischeck = item.checked
+ if (select !== -1) {
+ if (typeof selected === 'boolean') {
+ item.checked = selected
+ } else {
+ item.checked = !item.checked
+ }
+ if (ischeck !== item.checked) {
+ this.check(item.rowData||item, item.checked, item.rowData?item.keyValue:null, true)
+ }
+ }
+ // }
+ })
+ this.$emit('selection-change', {
+ detail: {
+ value: this.backData,
+ index:this.backIndexData
+ }
+ })
+ },
+
+ /**
+ * 鐢ㄤ簬澶氶�夎〃鏍硷紝娓呯┖鐢ㄦ埛鐨勯�夋嫨
+ */
+ clearSelection() {
+ let theadChildren = this.theadChildren
+ if (!this.theadChildren) {
+ theadChildren = this.trChildren[0]
+ }
+ // if (!this.theadChildren) return
+ theadChildren.checked = false
+ theadChildren.indeterminate = false
+ this.trChildren.forEach(item => {
+ // if (item.keyValue) {
+ item.checked = false
+ // }
+ })
+ this.backData = []
+ this.backIndexData = []
+ this.$emit('selection-change', {
+ detail: {
+ value: [],
+ index: []
+ }
+ })
+ },
+ /**
+ * 鐢ㄤ簬澶氶�夎〃鏍硷紝鍒囨崲鎵�鏈夎鐨勯�変腑鐘舵��
+ */
+ toggleAllSelection() {
+ let list = []
+ let startIndex = 1
+ let theadChildren = this.theadChildren
+ if (!this.theadChildren) {
+ theadChildren = this.trChildren[0]
+ } else {
+ startIndex = theadChildren.rowspan - 1
+ }
+ this.trChildren.forEach((item, index) => {
+ if (!item.disabled) {
+ if (index > (startIndex - 1) ) {
+ list.push(index-startIndex)
+ }
+ }
+ })
+ this.toggleRowSelection(list)
+ },
+
+ /**
+ * 閫変腑\鍙栨秷閫変腑
+ * @param {Object} child
+ * @param {Object} check
+ * @param {Object} rowValue
+ */
+ check(child, check, keyValue, emit) {
+ let theadChildren = this.theadChildren
+ if (!this.theadChildren) {
+ theadChildren = this.trChildren[0]
+ }
+
+
+
+ let childDomIndex = this.trChildren.findIndex((item, index) => child === item)
+ if(childDomIndex < 0){
+ childDomIndex = this.data.findIndex(v=>v[this.rowKey] === keyValue) + 1
+ }
+ const dataLen = this.trChildren.filter(v => !v.disabled && v.keyValue).length
+ if (childDomIndex === 0) {
+ check ? this.selectionAll() : this.clearSelection()
+ return
+ }
+
+ if (check) {
+ if (keyValue) {
+ this.backData.push(child)
+ }
+ this.backIndexData.push(childDomIndex - 1)
+ } else {
+ const index = this.backData.findIndex(v => v[this.rowKey] === keyValue)
+ const idx = this.backIndexData.findIndex(item => item === childDomIndex - 1)
+ if (keyValue) {
+ this.backData.splice(index, 1)
+ }
+ this.backIndexData.splice(idx, 1)
+ }
+
+ const domCheckAll = this.trChildren.find((item, index) => index > 0 && !item.checked && !item.disabled)
+ if (!domCheckAll) {
+ theadChildren.indeterminate = false
+ theadChildren.checked = true
+ } else {
+ theadChildren.indeterminate = true
+ theadChildren.checked = false
+ }
+
+ if (this.backIndexData.length === 0) {
+ theadChildren.indeterminate = false
+ }
+
+ if (!emit) {
+ this.$emit('selection-change', {
+ detail: {
+ value: this.backData,
+ index: this.backIndexData
+ }
+ })
+ }
+ }
+ }
+}
+</script>
+
+<style lang="scss">
+$border-color: #ebeef5;
+
+.uni-table-scroll {
+ width: 100%;
+ /* #ifndef APP-NVUE */
+ overflow-x: auto;
+ /* #endif */
+}
+
+.uni-table {
+ position: relative;
+ width: 100%;
+ border-radius: 5px;
+ // box-shadow: 0px 0px 3px 1px rgba(0, 0, 0, 0.1);
+ background-color: #fff;
+ /* #ifndef APP-NVUE */
+ box-sizing: border-box;
+ display: table;
+ overflow-x: auto;
+ ::v-deep .uni-table-tr:nth-child(n + 2) {
+ &:hover {
+ background-color: #f5f7fa;
+ }
+ }
+ ::v-deep .uni-table-thead {
+ .uni-table-tr {
+ // background-color: #f5f7fa;
+ &:hover {
+ background-color:#fafafa;
+ }
+ }
+ }
+ /* #endif */
+}
+
+.table--border {
+ border: 1px $border-color solid;
+ border-right: none;
+}
+
+.border-none {
+ /* #ifndef APP-NVUE */
+ border-bottom: none;
+ /* #endif */
+}
+
+.table--stripe {
+ /* #ifndef APP-NVUE */
+ ::v-deep .uni-table-tr:nth-child(2n + 3) {
+ background-color: #fafafa;
+ }
+ /* #endif */
+}
+
+/* 琛ㄦ牸鍔犺浇銆佹棤鏁版嵁鏍峰紡 */
+.uni-table-loading {
+ position: relative;
+ /* #ifndef APP-NVUE */
+ display: table-row;
+ /* #endif */
+ height: 50px;
+ line-height: 50px;
+ overflow: hidden;
+ box-sizing: border-box;
+}
+.empty-border {
+ border-right: 1px $border-color solid;
+}
+.uni-table-text {
+ position: absolute;
+ right: 0;
+ left: 0;
+ text-align: center;
+ font-size: 14px;
+ color: #999;
+}
+
+.uni-table-mask {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ background-color: rgba(255, 255, 255, 0.8);
+ z-index: 99;
+ /* #ifndef APP-NVUE */
+ display: flex;
+ margin: auto;
+ transition: all 0.5s;
+ /* #endif */
+ justify-content: center;
+ align-items: center;
+}
+
+.uni-table--loader {
+ width: 30px;
+ height: 30px;
+ border: 2px solid #aaa;
+ // border-bottom-color: transparent;
+ border-radius: 50%;
+ /* #ifndef APP-NVUE */
+ animation: 2s uni-table--loader linear infinite;
+ /* #endif */
+ position: relative;
+}
+
+@keyframes uni-table--loader {
+ 0% {
+ transform: rotate(360deg);
+ }
+
+ 10% {
+ border-left-color: transparent;
+ }
+
+ 20% {
+ border-bottom-color: transparent;
+ }
+
+ 30% {
+ border-right-color: transparent;
+ }
+
+ 40% {
+ border-top-color: transparent;
+ }
+
+ 50% {
+ transform: rotate(0deg);
+ }
+
+ 60% {
+ border-top-color: transparent;
+ }
+
+ 70% {
+ border-left-color: transparent;
+ }
+
+ 80% {
+ border-bottom-color: transparent;
+ }
+
+ 90% {
+ border-right-color: transparent;
+ }
+
+ 100% {
+ transform: rotate(-360deg);
+ }
+}
+</style>
diff --git a/app/uni_modules/uni-table/components/uni-tbody/uni-tbody.vue b/app/uni_modules/uni-table/components/uni-tbody/uni-tbody.vue
new file mode 100644
index 0000000..fbe1bdc
--- /dev/null
+++ b/app/uni_modules/uni-table/components/uni-tbody/uni-tbody.vue
@@ -0,0 +1,29 @@
+<template>
+ <!-- #ifdef H5 -->
+ <tbody>
+ <slot></slot>
+ </tbody>
+ <!-- #endif -->
+ <!-- #ifndef H5 -->
+ <view><slot></slot></view>
+ <!-- #endif -->
+</template>
+
+<script>
+export default {
+ name: 'uniBody',
+ options: {
+ virtualHost: true
+ },
+ data() {
+ return {
+
+ }
+ },
+ created() {},
+ methods: {}
+}
+</script>
+
+<style>
+</style>
diff --git a/app/uni_modules/uni-table/components/uni-td/uni-td.vue b/app/uni_modules/uni-table/components/uni-td/uni-td.vue
new file mode 100644
index 0000000..9ce93e9
--- /dev/null
+++ b/app/uni_modules/uni-table/components/uni-td/uni-td.vue
@@ -0,0 +1,90 @@
+<template>
+ <!-- #ifdef H5 -->
+ <td class="uni-table-td" :rowspan="rowspan" :colspan="colspan" :class="{'table--border':border}" :style="{width:width + 'px','text-align':align}">
+ <slot></slot>
+ </td>
+ <!-- #endif -->
+ <!-- #ifndef H5 -->
+ <!-- :class="{'table--border':border}" -->
+ <view class="uni-table-td" :class="{'table--border':border}" :style="{width:width + 'px','text-align':align}">
+ <slot></slot>
+ </view>
+ <!-- #endif -->
+
+</template>
+
+<script>
+ /**
+ * Td 鍗曞厓鏍�
+ * @description 琛ㄦ牸涓殑鏍囧噯鍗曞厓鏍肩粍浠�
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=3270
+ * @property {Number} align = [left|center|right] 鍗曞厓鏍煎榻愭柟寮�
+ */
+ export default {
+ name: 'uniTd',
+ options: {
+ virtualHost: true
+ },
+ props: {
+ width: {
+ type: [String, Number],
+ default: ''
+ },
+ align: {
+ type: String,
+ default: 'left'
+ },
+ rowspan: {
+ type: [Number,String],
+ default: 1
+ },
+ colspan: {
+ type: [Number,String],
+ default: 1
+ }
+ },
+ data() {
+ return {
+ border: false
+ };
+ },
+ created() {
+ this.root = this.getTable()
+ this.border = this.root.border
+ },
+ methods: {
+ /**
+ * 鑾峰彇鐖跺厓绱犲疄渚�
+ */
+ getTable() {
+ let parent = this.$parent;
+ let parentName = parent.$options.name;
+ while (parentName !== 'uniTable') {
+ parent = parent.$parent;
+ if (!parent) return false;
+ parentName = parent.$options.name;
+ }
+ return parent;
+ },
+ }
+ }
+</script>
+
+<style lang="scss">
+ $border-color:#EBEEF5;
+
+ .uni-table-td {
+ display: table-cell;
+ padding: 8px 10px;
+ font-size: 14px;
+ border-bottom: 1px $border-color solid;
+ font-weight: 400;
+ color: #606266;
+ line-height: 23px;
+ box-sizing: border-box;
+ }
+
+ .table--border {
+ border-right: 1px $border-color solid;
+ }
+</style>
diff --git a/app/uni_modules/uni-table/components/uni-th/filter-dropdown.vue b/app/uni_modules/uni-table/components/uni-th/filter-dropdown.vue
new file mode 100644
index 0000000..df22a71
--- /dev/null
+++ b/app/uni_modules/uni-table/components/uni-th/filter-dropdown.vue
@@ -0,0 +1,511 @@
+<template>
+ <view class="uni-filter-dropdown">
+ <view class="dropdown-btn" @click="onDropdown">
+ <view class="icon-select" :class="{active: canReset}" v-if="isSelect || isRange"></view>
+ <view class="icon-search" :class="{active: canReset}" v-if="isSearch">
+ <view class="icon-search-0"></view>
+ <view class="icon-search-1"></view>
+ </view>
+ <view class="icon-calendar" :class="{active: canReset}" v-if="isDate">
+ <view class="icon-calendar-0"></view>
+ <view class="icon-calendar-1"></view>
+ </view>
+ </view>
+ <view class="uni-dropdown-cover" v-if="isOpened" @click="handleClose"></view>
+ <view class="dropdown-popup dropdown-popup-right" v-if="isOpened" @click.stop>
+ <!-- select-->
+ <view v-if="isSelect" class="list">
+ <label class="flex-r a-i-c list-item" v-for="(item,index) in dataList" :key="index"
+ @click="onItemClick($event, index)">
+ <check-box class="check" :checked="item.checked" />
+ <view class="checklist-content">
+ <text class="checklist-text" :style="item.styleIconText">{{item[map.text]}}</text>
+ </view>
+ </label>
+ </view>
+ <view v-if="isSelect" class="flex-r opera-area">
+ <view class="flex-f btn btn-default" :class="{disable: !canReset}" @click="handleSelectReset">
+ {{resource.reset}}</view>
+ <view class="flex-f btn btn-submit" @click="handleSelectSubmit">{{resource.submit}}</view>
+ </view>
+ <!-- search -->
+ <view v-if="isSearch" class="search-area">
+ <input class="search-input" v-model="filterValue" />
+ </view>
+ <view v-if="isSearch" class="flex-r opera-area">
+ <view class="flex-f btn btn-submit" @click="handleSearchSubmit">{{resource.search}}</view>
+ <view class="flex-f btn btn-default" :class="{disable: !canReset}" @click="handleSearchReset">
+ {{resource.reset}}</view>
+ </view>
+ <!-- range -->
+ <view v-if="isRange">
+ <view class="input-label">{{resource.gt}}</view>
+ <input class="input" v-model="gtValue" />
+ <view class="input-label">{{resource.lt}}</view>
+ <input class="input" v-model="ltValue" />
+ </view>
+ <view v-if="isRange" class="flex-r opera-area">
+ <view class="flex-f btn btn-default" :class="{disable: !canReset}" @click="handleRangeReset">
+ {{resource.reset}}</view>
+ <view class="flex-f btn btn-submit" @click="handleRangeSubmit">{{resource.submit}}</view>
+ </view>
+ <!-- date -->
+ <view v-if="isDate">
+ <uni-datetime-picker ref="datetimepicker" :value="dateRange" type="datetimerange" return-type="timestamp" @change="datetimechange" @maskClick="timepickerclose">
+ <view></view>
+ </uni-datetime-picker>
+ </view>
+ </view>
+ </view>
+</template>
+
+<script>
+ import checkBox from '../uni-tr/table-checkbox.vue'
+
+ const resource = {
+ "reset": "閲嶇疆",
+ "search": "鎼滅储",
+ "submit": "纭畾",
+ "filter": "绛涢��",
+ "gt": "澶т簬绛変簬",
+ "lt": "灏忎簬绛変簬",
+ "date": "鏃ユ湡鑼冨洿"
+ }
+
+ const DropdownType = {
+ Select: "select",
+ Search: "search",
+ Range: "range",
+ Date: "date",
+ Timestamp: "timestamp"
+ }
+
+ export default {
+ name: 'FilterDropdown',
+ emits:['change'],
+ components: {
+ checkBox
+ },
+ options: {
+ virtualHost: true
+ },
+ props: {
+ filterType: {
+ type: String,
+ default: DropdownType.Select
+ },
+ filterData: {
+ type: Array,
+ default () {
+ return []
+ }
+ },
+ mode: {
+ type: String,
+ default: 'default'
+ },
+ map: {
+ type: Object,
+ default () {
+ return {
+ text: 'text',
+ value: 'value'
+ }
+ }
+ },
+ filterDefaultValue: {
+ type: [Array,String],
+ default () {
+ return ""
+ }
+ }
+ },
+ computed: {
+ canReset() {
+ if (this.isSearch) {
+ return this.filterValue.length > 0
+ }
+ if (this.isSelect) {
+ return this.checkedValues.length > 0
+ }
+ if (this.isRange) {
+ return (this.gtValue.length > 0 && this.ltValue.length > 0)
+ }
+ if (this.isDate) {
+ return this.dateSelect.length > 0
+ }
+ return false
+ },
+ isSelect() {
+ return this.filterType === DropdownType.Select
+ },
+ isSearch() {
+ return this.filterType === DropdownType.Search
+ },
+ isRange() {
+ return this.filterType === DropdownType.Range
+ },
+ isDate() {
+ return (this.filterType === DropdownType.Date || this.filterType === DropdownType.Timestamp)
+ }
+ },
+ watch: {
+ filterData(newVal) {
+ this._copyFilters()
+ },
+ indeterminate(newVal) {
+ this.isIndeterminate = newVal
+ }
+ },
+ data() {
+ return {
+ resource,
+ enabled: true,
+ isOpened: false,
+ dataList: [],
+ filterValue: this.filterDefaultValue,
+ checkedValues: [],
+ gtValue: '',
+ ltValue: '',
+ dateRange: [],
+ dateSelect: []
+ };
+ },
+ created() {
+ this._copyFilters()
+ },
+ methods: {
+ _copyFilters() {
+ let dl = JSON.parse(JSON.stringify(this.filterData))
+ for (let i = 0; i < dl.length; i++) {
+ if (dl[i].checked === undefined) {
+ dl[i].checked = false
+ }
+ }
+ this.dataList = dl
+ },
+ openPopup() {
+ this.isOpened = true
+ if (this.isDate) {
+ this.$nextTick(() => {
+ if (!this.dateRange.length) {
+ this.resetDate()
+ }
+ this.$refs.datetimepicker.show()
+ })
+ }
+ },
+ closePopup() {
+ this.isOpened = false
+ },
+ handleClose(e) {
+ this.closePopup()
+ },
+ resetDate() {
+ let date = new Date()
+ let dateText = date.toISOString().split('T')[0]
+ this.dateRange = [dateText + ' 0:00:00', dateText + ' 23:59:59']
+ },
+ onDropdown(e) {
+ this.openPopup()
+ },
+ onItemClick(e, index) {
+ let items = this.dataList
+ let listItem = items[index]
+ if (listItem.checked === undefined) {
+ items[index].checked = true
+ } else {
+ items[index].checked = !listItem.checked
+ }
+
+ let checkvalues = []
+ for (let i = 0; i < items.length; i++) {
+ const item = items[i]
+ if (item.checked) {
+ checkvalues.push(item.value)
+ }
+ }
+ this.checkedValues = checkvalues
+ },
+ datetimechange(e) {
+ this.closePopup()
+ this.dateRange = e
+ this.dateSelect = e
+ this.$emit('change', {
+ filterType: this.filterType,
+ filter: e
+ })
+ },
+ timepickerclose(e) {
+ this.closePopup()
+ },
+ handleSelectSubmit() {
+ this.closePopup()
+ this.$emit('change', {
+ filterType: this.filterType,
+ filter: this.checkedValues
+ })
+ },
+ handleSelectReset() {
+ if (!this.canReset) {
+ return;
+ }
+ var items = this.dataList
+ for (let i = 0; i < items.length; i++) {
+ let item = items[i]
+ this.$set(item, 'checked', false)
+ }
+ this.checkedValues = []
+ this.handleSelectSubmit()
+ },
+ handleSearchSubmit() {
+ this.closePopup()
+ this.$emit('change', {
+ filterType: this.filterType,
+ filter: this.filterValue
+ })
+ },
+ handleSearchReset() {
+ if (!this.canReset) {
+ return;
+ }
+ this.filterValue = ''
+ this.handleSearchSubmit()
+ },
+ handleRangeSubmit(isReset) {
+ this.closePopup()
+ this.$emit('change', {
+ filterType: this.filterType,
+ filter: isReset === true ? [] : [parseInt(this.gtValue), parseInt(this.ltValue)]
+ })
+ },
+ handleRangeReset() {
+ if (!this.canReset) {
+ return;
+ }
+ this.gtValue = ''
+ this.ltValue = ''
+ this.handleRangeSubmit(true)
+ }
+ }
+ }
+</script>
+
+<style lang="scss">
+ $uni-primary: #1890ff !default;
+
+ .flex-r {
+ display: flex;
+ flex-direction: row;
+ }
+
+ .flex-f {
+ flex: 1;
+ }
+
+ .a-i-c {
+ align-items: center;
+ }
+
+ .j-c-c {
+ justify-content: center;
+ }
+
+ .icon-select {
+ width: 14px;
+ height: 16px;
+ border: solid 6px transparent;
+ border-top: solid 6px #ddd;
+ border-bottom: none;
+ background-color: #ddd;
+ background-clip: content-box;
+ box-sizing: border-box;
+ }
+
+ .icon-select.active {
+ background-color: $uni-primary;
+ border-top-color: $uni-primary;
+ }
+
+ .icon-search {
+ width: 12px;
+ height: 16px;
+ position: relative;
+ }
+
+ .icon-search-0 {
+ border: 2px solid #ddd;
+ border-radius: 8px;
+ width: 7px;
+ height: 7px;
+ }
+
+ .icon-search-1 {
+ position: absolute;
+ top: 8px;
+ right: 0;
+ width: 1px;
+ height: 7px;
+ background-color: #ddd;
+ transform: rotate(-45deg);
+ }
+
+ .icon-search.active .icon-search-0 {
+ border-color: $uni-primary;
+ }
+
+ .icon-search.active .icon-search-1 {
+ background-color: $uni-primary;
+ }
+
+ .icon-calendar {
+ color: #ddd;
+ width: 14px;
+ height: 16px;
+ }
+
+ .icon-calendar-0 {
+ height: 4px;
+ margin-top: 3px;
+ margin-bottom: 1px;
+ background-color: #ddd;
+ border-radius: 2px 2px 1px 1px;
+ position: relative;
+ }
+ .icon-calendar-0:before, .icon-calendar-0:after {
+ content: '';
+ position: absolute;
+ top: -3px;
+ width: 4px;
+ height: 3px;
+ border-radius: 1px;
+ background-color: #ddd;
+ }
+ .icon-calendar-0:before {
+ left: 2px;
+ }
+ .icon-calendar-0:after {
+ right: 2px;
+ }
+
+ .icon-calendar-1 {
+ height: 9px;
+ background-color: #ddd;
+ border-radius: 1px 1px 2px 2px;
+ }
+
+ .icon-calendar.active {
+ color: $uni-primary;
+ }
+
+ .icon-calendar.active .icon-calendar-0,
+ .icon-calendar.active .icon-calendar-1,
+ .icon-calendar.active .icon-calendar-0:before,
+ .icon-calendar.active .icon-calendar-0:after {
+ background-color: $uni-primary;
+ }
+
+ .uni-filter-dropdown {
+ position: relative;
+ font-weight: normal;
+ }
+
+ .dropdown-popup {
+ position: absolute;
+ top: 100%;
+ background-color: #fff;
+ box-shadow: 0 3px 6px -4px #0000001f, 0 6px 16px #00000014, 0 9px 28px 8px #0000000d;
+ min-width: 150px;
+ z-index: 1000;
+ }
+
+ .dropdown-popup-left {
+ left: 0;
+ }
+
+ .dropdown-popup-right {
+ right: 0;
+ }
+
+ .uni-dropdown-cover {
+ position: fixed;
+ left: 0;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ background-color: transparent;
+ z-index: 100;
+ }
+
+ .list {
+ margin-top: 5px;
+ margin-bottom: 5px;
+ }
+
+ .list-item {
+ padding: 5px 10px;
+ text-align: left;
+ }
+
+ .list-item:hover {
+ background-color: #f0f0f0;
+ }
+
+ .check {
+ margin-right: 5px;
+ }
+
+ .search-area {
+ padding: 10px;
+ }
+
+ .search-input {
+ font-size: 12px;
+ border: 1px solid #f0f0f0;
+ border-radius: 3px;
+ padding: 2px 5px;
+ min-width: 150px;
+ text-align: left;
+ }
+
+ .input-label {
+ margin: 10px 10px 5px 10px;
+ text-align: left;
+ }
+
+ .input {
+ font-size: 12px;
+ border: 1px solid #f0f0f0;
+ border-radius: 3px;
+ margin: 10px;
+ padding: 2px 5px;
+ min-width: 150px;
+ text-align: left;
+ }
+
+ .opera-area {
+ cursor: default;
+ border-top: 1px solid #ddd;
+ padding: 5px;
+ }
+
+ .opera-area .btn {
+ font-size: 12px;
+ border-radius: 3px;
+ margin: 5px;
+ padding: 4px 4px;
+ }
+
+ .btn-default {
+ border: 1px solid #ddd;
+ }
+
+ .btn-default.disable {
+ border-color: transparent;
+ }
+
+ .btn-submit {
+ background-color: $uni-primary;
+ color: #ffffff;
+ }
+</style>
diff --git a/app/uni_modules/uni-table/components/uni-th/uni-th.vue b/app/uni_modules/uni-table/components/uni-th/uni-th.vue
new file mode 100644
index 0000000..14889dd
--- /dev/null
+++ b/app/uni_modules/uni-table/components/uni-th/uni-th.vue
@@ -0,0 +1,285 @@
+<template>
+ <!-- #ifdef H5 -->
+ <th :rowspan="rowspan" :colspan="colspan" class="uni-table-th" :class="{ 'table--border': border }" :style="{ width: customWidth + 'px', 'text-align': align }">
+ <view class="uni-table-th-row">
+ <view class="uni-table-th-content" :style="{ 'justify-content': contentAlign }" @click="sort">
+ <slot></slot>
+ <view v-if="sortable" class="arrow-box">
+ <text class="arrow up" :class="{ active: ascending }" @click.stop="ascendingFn"></text>
+ <text class="arrow down" :class="{ active: descending }" @click.stop="descendingFn"></text>
+ </view>
+ </view>
+ <dropdown v-if="filterType || filterData.length" :filterDefaultValue="filterDefaultValue" :filterData="filterData" :filterType="filterType" @change="ondropdown"></dropdown>
+ </view>
+ </th>
+ <!-- #endif -->
+ <!-- #ifndef H5 -->
+ <view class="uni-table-th" :class="{ 'table--border': border }" :style="{ width: customWidth + 'px', 'text-align': align }"><slot></slot></view>
+ <!-- #endif -->
+</template>
+
+<script>
+ // #ifdef H5
+ import dropdown from './filter-dropdown.vue'
+ // #endif
+/**
+ * Th 琛ㄥご
+ * @description 琛ㄦ牸鍐呯殑琛ㄥご鍗曞厓鏍肩粍浠�
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=3270
+ * @property {Number | String} width 鍗曞厓鏍煎搴︼紙鏀寔绾暟瀛椼�佹惡甯﹀崟浣峱x鎴杛px锛�
+ * @property {Boolean} sortable 鏄惁鍚敤鎺掑簭
+ * @property {Number} align = [left|center|right] 鍗曞厓鏍煎榻愭柟寮�
+ * @value left 鍗曞厓鏍兼枃瀛楀乏渚у榻�
+ * @value center 鍗曞厓鏍兼枃瀛楀眳涓�
+ * @value right 鍗曞厓鏍兼枃瀛楀彸渚у榻�
+ * @property {Array} filterData 绛涢�夋暟鎹�
+ * @property {String} filterType [search|select] 绛涢�夌被鍨�
+ * @value search 鍏抽敭瀛楁悳绱�
+ * @value select 鏉′欢閫夋嫨
+ * @event {Function} sort-change 鎺掑簭瑙﹀彂浜嬩欢
+ */
+export default {
+ name: 'uniTh',
+ options: {
+ virtualHost: true
+ },
+ components: {
+ // #ifdef H5
+ dropdown
+ // #endif
+ },
+ emits:['sort-change','filter-change'],
+ props: {
+ width: {
+ type: [String, Number],
+ default: ''
+ },
+ align: {
+ type: String,
+ default: 'left'
+ },
+ rowspan: {
+ type: [Number, String],
+ default: 1
+ },
+ colspan: {
+ type: [Number, String],
+ default: 1
+ },
+ sortable: {
+ type: Boolean,
+ default: false
+ },
+ filterType: {
+ type: String,
+ default: ""
+ },
+ filterData: {
+ type: Array,
+ default () {
+ return []
+ }
+ },
+ filterDefaultValue: {
+ type: [Array,String],
+ default () {
+ return ""
+ }
+ }
+ },
+ data() {
+ return {
+ border: false,
+ ascending: false,
+ descending: false
+ }
+ },
+ computed: {
+ // 鏍规嵁props涓殑width灞炴�� 鑷姩鍖归厤褰撳墠th鐨勫搴�(px)
+ customWidth(){
+ if(typeof this.width === 'number'){
+ return this.width
+ } else if(typeof this.width === 'string') {
+ let regexHaveUnitPx = new RegExp(/^[1-9][0-9]*px$/g)
+ let regexHaveUnitRpx = new RegExp(/^[1-9][0-9]*rpx$/g)
+ let regexHaveNotUnit = new RegExp(/^[1-9][0-9]*$/g)
+ if (this.width.match(regexHaveUnitPx) !== null) { // 鎼哄甫浜� px
+ return this.width.replace('px', '')
+ } else if (this.width.match(regexHaveUnitRpx) !== null) { // 鎼哄甫浜� rpx
+ let numberRpx = Number(this.width.replace('rpx', ''))
+ let widthCoe = uni.getSystemInfoSync().screenWidth / 750
+ return Math.round(numberRpx * widthCoe)
+ } else if (this.width.match(regexHaveNotUnit) !== null) { // 鏈惡甯� rpx鎴杙x 鐨勭函鏁板瓧 String
+ return this.width
+ } else { // 涓嶇鍚堟牸寮�
+ return ''
+ }
+ } else {
+ return ''
+ }
+ },
+ contentAlign() {
+ let align = 'left'
+ switch (this.align) {
+ case 'left':
+ align = 'flex-start'
+ break
+ case 'center':
+ align = 'center'
+ break
+ case 'right':
+ align = 'flex-end'
+ break
+ }
+ return align
+ }
+ },
+ created() {
+ this.root = this.getTable('uniTable')
+ this.rootTr = this.getTable('uniTr')
+ this.rootTr.minWidthUpdate(this.customWidth ? this.customWidth : 140)
+ this.border = this.root.border
+ this.root.thChildren.push(this)
+ },
+ methods: {
+ sort() {
+ if (!this.sortable) return
+ this.clearOther()
+ if (!this.ascending && !this.descending) {
+ this.ascending = true
+ this.$emit('sort-change', { order: 'ascending' })
+ return
+ }
+ if (this.ascending && !this.descending) {
+ this.ascending = false
+ this.descending = true
+ this.$emit('sort-change', { order: 'descending' })
+ return
+ }
+
+ if (!this.ascending && this.descending) {
+ this.ascending = false
+ this.descending = false
+ this.$emit('sort-change', { order: null })
+ }
+ },
+ ascendingFn() {
+ this.clearOther()
+ this.ascending = !this.ascending
+ this.descending = false
+ this.$emit('sort-change', { order: this.ascending ? 'ascending' : null })
+ },
+ descendingFn() {
+ this.clearOther()
+ this.descending = !this.descending
+ this.ascending = false
+ this.$emit('sort-change', { order: this.descending ? 'descending' : null })
+ },
+ clearOther() {
+ this.root.thChildren.map(item => {
+ if (item !== this) {
+ item.ascending = false
+ item.descending = false
+ }
+ return item
+ })
+ },
+ ondropdown(e) {
+ this.$emit("filter-change", e)
+ },
+ /**
+ * 鑾峰彇鐖跺厓绱犲疄渚�
+ */
+ getTable(name) {
+ let parent = this.$parent
+ let parentName = parent.$options.name
+ while (parentName !== name) {
+ parent = parent.$parent
+ if (!parent) return false
+ parentName = parent.$options.name
+ }
+ return parent
+ }
+ }
+}
+</script>
+
+<style lang="scss">
+$border-color: #ebeef5;
+$uni-primary: #007aff !default;
+
+.uni-table-th {
+ padding: 12px 10px;
+ /* #ifndef APP-NVUE */
+ display: table-cell;
+ box-sizing: border-box;
+ /* #endif */
+ font-size: 14px;
+ font-weight: bold;
+ color: #909399;
+ border-bottom: 1px $border-color solid;
+}
+
+.uni-table-th-row {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: row;
+}
+
+.table--border {
+ border-right: 1px $border-color solid;
+}
+.uni-table-th-content {
+ display: flex;
+ align-items: center;
+ flex: 1;
+}
+.arrow-box {
+}
+.arrow {
+ display: block;
+ position: relative;
+ width: 10px;
+ height: 8px;
+ // border: 1px red solid;
+ left: 5px;
+ overflow: hidden;
+ cursor: pointer;
+}
+.down {
+ top: 3px;
+ ::after {
+ content: '';
+ width: 8px;
+ height: 8px;
+ position: absolute;
+ left: 2px;
+ top: -5px;
+ transform: rotate(45deg);
+ background-color: #ccc;
+ }
+ &.active {
+ ::after {
+ background-color: $uni-primary;
+ }
+ }
+}
+.up {
+ ::after {
+ content: '';
+ width: 8px;
+ height: 8px;
+ position: absolute;
+ left: 2px;
+ top: 5px;
+ transform: rotate(45deg);
+ background-color: #ccc;
+ }
+ &.active {
+ ::after {
+ background-color: $uni-primary;
+ }
+ }
+}
+</style>
diff --git a/app/uni_modules/uni-table/components/uni-thead/uni-thead.vue b/app/uni_modules/uni-table/components/uni-thead/uni-thead.vue
new file mode 100644
index 0000000..0dd18cd
--- /dev/null
+++ b/app/uni_modules/uni-table/components/uni-thead/uni-thead.vue
@@ -0,0 +1,129 @@
+<template>
+ <!-- #ifdef H5 -->
+ <thead class="uni-table-thead">
+ <tr class="uni-table-tr">
+ <th :rowspan="rowspan" colspan="1" class="checkbox" :class="{ 'tr-table--border': border }">
+ <table-checkbox :indeterminate="indeterminate" :checked="checked" @checkboxSelected="checkboxSelected"></table-checkbox>
+ </th>
+ </tr>
+ <slot></slot>
+ </thead>
+ <!-- #endif -->
+ <!-- #ifndef H5 -->
+ <view class="uni-table-thead"><slot></slot></view>
+ <!-- #endif -->
+</template>
+
+<script>
+import tableCheckbox from '../uni-tr/table-checkbox.vue'
+export default {
+ name: 'uniThead',
+ components: {
+ tableCheckbox
+ },
+ options: {
+ virtualHost: true
+ },
+ data() {
+ return {
+ border: false,
+ selection: false,
+ rowspan: 1,
+ indeterminate: false,
+ checked: false
+ }
+ },
+ created() {
+ this.root = this.getTable()
+ // #ifdef H5
+ this.root.theadChildren = this
+ // #endif
+ this.border = this.root.border
+ this.selection = this.root.type
+ },
+ methods: {
+ init(self) {
+ this.rowspan++
+ },
+ checkboxSelected(e) {
+ this.indeterminate = false
+ const backIndexData = this.root.backIndexData
+ const data = this.root.trChildren.filter(v => !v.disabled && v.keyValue)
+ if (backIndexData.length === data.length) {
+ this.checked = false
+ this.root.clearSelection()
+ } else {
+ this.checked = true
+ this.root.selectionAll()
+ }
+ },
+ /**
+ * 鑾峰彇鐖跺厓绱犲疄渚�
+ */
+ getTable(name = 'uniTable') {
+ let parent = this.$parent
+ let parentName = parent.$options.name
+ while (parentName !== name) {
+ parent = parent.$parent
+ if (!parent) return false
+ parentName = parent.$options.name
+ }
+ return parent
+ }
+ }
+}
+</script>
+
+<style lang="scss">
+$border-color: #ebeef5;
+
+.uni-table-thead {
+ display: table-header-group;
+}
+
+.uni-table-tr {
+ /* #ifndef APP-NVUE */
+ display: table-row;
+ transition: all 0.3s;
+ box-sizing: border-box;
+ /* #endif */
+ border: 1px red solid;
+ background-color: #fafafa;
+}
+
+.checkbox {
+ padding: 0 8px;
+ width: 26px;
+ padding-left: 12px;
+ /* #ifndef APP-NVUE */
+ display: table-cell;
+ vertical-align: middle;
+ /* #endif */
+ color: #333;
+ font-weight: 500;
+ border-bottom: 1px $border-color solid;
+ font-size: 14px;
+ // text-align: center;
+}
+
+.tr-table--border {
+ border-right: 1px $border-color solid;
+}
+
+/* #ifndef APP-NVUE */
+.uni-table-tr {
+ ::v-deep .uni-table-th {
+ &.table--border:last-child {
+ // border-right: none;
+ }
+ }
+
+ ::v-deep .uni-table-td {
+ &.table--border:last-child {
+ // border-right: none;
+ }
+ }
+}
+
+/* #endif */
+</style>
diff --git a/app/uni_modules/uni-table/components/uni-tr/table-checkbox.vue b/app/uni_modules/uni-table/components/uni-tr/table-checkbox.vue
new file mode 100644
index 0000000..1089187
--- /dev/null
+++ b/app/uni_modules/uni-table/components/uni-tr/table-checkbox.vue
@@ -0,0 +1,179 @@
+<template>
+ <view class="uni-table-checkbox" @click="selected">
+ <view v-if="!indeterminate" class="checkbox__inner" :class="{'is-checked':isChecked,'is-disable':isDisabled}">
+ <view class="checkbox__inner-icon"></view>
+ </view>
+ <view v-else class="checkbox__inner checkbox--indeterminate">
+ <view class="checkbox__inner-icon"></view>
+ </view>
+ </view>
+</template>
+
+<script>
+ export default {
+ name: 'TableCheckbox',
+ emits:['checkboxSelected'],
+ props: {
+ indeterminate: {
+ type: Boolean,
+ default: false
+ },
+ checked: {
+ type: [Boolean,String],
+ default: false
+ },
+ disabled: {
+ type: Boolean,
+ default: false
+ },
+ index: {
+ type: Number,
+ default: -1
+ },
+ cellData: {
+ type: Object,
+ default () {
+ return {}
+ }
+ }
+ },
+ watch:{
+ checked(newVal){
+ if(typeof this.checked === 'boolean'){
+ this.isChecked = newVal
+ }else{
+ this.isChecked = true
+ }
+ },
+ indeterminate(newVal){
+ this.isIndeterminate = newVal
+ }
+ },
+ data() {
+ return {
+ isChecked: false,
+ isDisabled: false,
+ isIndeterminate:false
+ }
+ },
+ created() {
+ if(typeof this.checked === 'boolean'){
+ this.isChecked = this.checked
+ }
+ this.isDisabled = this.disabled
+ },
+ methods: {
+ selected() {
+ if (this.isDisabled) return
+ this.isIndeterminate = false
+ this.isChecked = !this.isChecked
+ this.$emit('checkboxSelected', {
+ checked: this.isChecked,
+ data: this.cellData
+ })
+ }
+ }
+ }
+</script>
+
+<style lang="scss">
+ $uni-primary: #007aff !default;
+ $border-color: #DCDFE6;
+ $disable:0.4;
+
+ .uni-table-checkbox {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: center;
+ position: relative;
+ margin: 5px 0;
+ cursor: pointer;
+
+ // 澶氶�夋牱寮�
+ .checkbox__inner {
+ /* #ifndef APP-NVUE */
+ flex-shrink: 0;
+ box-sizing: border-box;
+ /* #endif */
+ position: relative;
+ width: 16px;
+ height: 16px;
+ border: 1px solid $border-color;
+ border-radius: 2px;
+ background-color: #fff;
+ z-index: 1;
+
+ .checkbox__inner-icon {
+ position: absolute;
+ /* #ifdef APP-NVUE */
+ top: 2px;
+ /* #endif */
+ /* #ifndef APP-NVUE */
+ top: 2px;
+ /* #endif */
+ left: 5px;
+ height: 7px;
+ width: 3px;
+ border: 1px solid #fff;
+ border-left: 0;
+ border-top: 0;
+ opacity: 0;
+ transform-origin: center;
+ transform: rotate(45deg);
+ box-sizing: content-box;
+ }
+
+ &.checkbox--indeterminate {
+ border-color: $uni-primary;
+ background-color: $uni-primary;
+
+ .checkbox__inner-icon {
+ position: absolute;
+ opacity: 1;
+ transform: rotate(0deg);
+ height: 2px;
+ top: 0;
+ bottom: 0;
+ margin: auto;
+ left: 0px;
+ right: 0px;
+ bottom: 0;
+ width: auto;
+ border: none;
+ border-radius: 2px;
+ transform: scale(0.5);
+ background-color: #fff;
+ }
+ }
+ &:hover{
+ border-color: $uni-primary;
+ }
+ // 绂佺敤
+ &.is-disable {
+ /* #ifdef H5 */
+ cursor: not-allowed;
+ /* #endif */
+ background-color: #F2F6FC;
+ border-color: $border-color;
+ }
+
+ // 閫変腑
+ &.is-checked {
+ border-color: $uni-primary;
+ background-color: $uni-primary;
+
+ .checkbox__inner-icon {
+ opacity: 1;
+ transform: rotate(45deg);
+ }
+
+ // 閫変腑绂佺敤
+ &.is-disable {
+ opacity: $disable;
+ }
+ }
+
+ }
+ }
+</style>
diff --git a/app/uni_modules/uni-table/components/uni-tr/uni-tr.vue b/app/uni_modules/uni-table/components/uni-tr/uni-tr.vue
new file mode 100644
index 0000000..f9b9671
--- /dev/null
+++ b/app/uni_modules/uni-table/components/uni-tr/uni-tr.vue
@@ -0,0 +1,171 @@
+<template>
+ <!-- #ifdef H5 -->
+ <tr class="uni-table-tr">
+ <th v-if="selection === 'selection' && ishead" class="checkbox" :class="{ 'tr-table--border': border }">
+ <table-checkbox :checked="checked" :indeterminate="indeterminate" :disabled="disabled" @checkboxSelected="checkboxSelected"></table-checkbox>
+ </th>
+ <slot></slot>
+ <!-- <uni-th class="th-fixed">123</uni-th> -->
+ </tr>
+ <!-- #endif -->
+ <!-- #ifndef H5 -->
+ <view class="uni-table-tr">
+ <view v-if="selection === 'selection' " class="checkbox" :class="{ 'tr-table--border': border }">
+ <table-checkbox :checked="checked" :indeterminate="indeterminate" :disabled="disabled" @checkboxSelected="checkboxSelected"></table-checkbox>
+ </view>
+ <slot></slot>
+ </view>
+ <!-- #endif -->
+</template>
+
+<script>
+ import tableCheckbox from './table-checkbox.vue'
+/**
+ * Tr 琛ㄦ牸琛岀粍浠�
+ * @description 琛ㄦ牸琛岀粍浠� 浠呭寘鍚� th,td 缁勪欢
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=
+ */
+export default {
+ name: 'uniTr',
+ components: { tableCheckbox },
+ props: {
+ disabled: {
+ type: Boolean,
+ default: false
+ },
+ keyValue: {
+ type: [String, Number],
+ default: ''
+ }
+ },
+ options: {
+ virtualHost: true
+ },
+ data() {
+ return {
+ value: false,
+ border: false,
+ selection: false,
+ widthThArr: [],
+ ishead: true,
+ checked: false,
+ indeterminate:false
+ }
+ },
+ created() {
+ this.root = this.getTable()
+ this.head = this.getTable('uniThead')
+ if (this.head) {
+ this.ishead = false
+ this.head.init(this)
+ }
+ this.border = this.root.border
+ this.selection = this.root.type
+ this.root.trChildren.push(this)
+ const rowData = this.root.data.find(v => v[this.root.rowKey] === this.keyValue)
+ if(rowData){
+ this.rowData = rowData
+ }
+ this.root.isNodata()
+ },
+ mounted() {
+ if (this.widthThArr.length > 0) {
+ const selectionWidth = this.selection === 'selection' ? 50 : 0
+ this.root.minWidth = this.widthThArr.reduce((a, b) => Number(a) + Number(b)) + selectionWidth
+ }
+ },
+ // #ifndef VUE3
+ destroyed() {
+ const index = this.root.trChildren.findIndex(i => i === this)
+ this.root.trChildren.splice(index, 1)
+ this.root.isNodata()
+ },
+ // #endif
+ // #ifdef VUE3
+ unmounted() {
+ const index = this.root.trChildren.findIndex(i => i === this)
+ this.root.trChildren.splice(index, 1)
+ this.root.isNodata()
+ },
+ // #endif
+ methods: {
+ minWidthUpdate(width) {
+ this.widthThArr.push(width)
+ },
+ // 閫変腑
+ checkboxSelected(e) {
+ let rootData = this.root.data.find(v => v[this.root.rowKey] === this.keyValue)
+ this.checked = e.checked
+ this.root.check(rootData||this, e.checked,rootData? this.keyValue:null)
+ },
+ change(e) {
+ this.root.trChildren.forEach(item => {
+ if (item === this) {
+ this.root.check(this, e.detail.value.length > 0 ? true : false)
+ }
+ })
+ },
+ /**
+ * 鑾峰彇鐖跺厓绱犲疄渚�
+ */
+ getTable(name = 'uniTable') {
+ let parent = this.$parent
+ let parentName = parent.$options.name
+ while (parentName !== name) {
+ parent = parent.$parent
+ if (!parent) return false
+ parentName = parent.$options.name
+ }
+ return parent
+ }
+ }
+}
+</script>
+
+<style lang="scss">
+$border-color: #ebeef5;
+
+.uni-table-tr {
+ /* #ifndef APP-NVUE */
+ display: table-row;
+ transition: all 0.3s;
+ box-sizing: border-box;
+ /* #endif */
+}
+
+.checkbox {
+ padding: 0 8px;
+ width: 26px;
+ padding-left: 12px;
+ /* #ifndef APP-NVUE */
+ display: table-cell;
+ vertical-align: middle;
+ /* #endif */
+ color: #333;
+ font-weight: 500;
+ border-bottom: 1px $border-color solid;
+ font-size: 14px;
+ // text-align: center;
+}
+
+.tr-table--border {
+ border-right: 1px $border-color solid;
+}
+
+/* #ifndef APP-NVUE */
+.uni-table-tr {
+ ::v-deep .uni-table-th {
+ &.table--border:last-child {
+ // border-right: none;
+ }
+ }
+
+ ::v-deep .uni-table-td {
+ &.table--border:last-child {
+ // border-right: none;
+ }
+ }
+}
+
+/* #endif */
+</style>
diff --git a/app/uni_modules/uni-table/i18n/en.json b/app/uni_modules/uni-table/i18n/en.json
new file mode 100644
index 0000000..e32023c
--- /dev/null
+++ b/app/uni_modules/uni-table/i18n/en.json
@@ -0,0 +1,9 @@
+{
+ "filter-dropdown.reset": "Reset",
+ "filter-dropdown.search": "Search",
+ "filter-dropdown.submit": "Submit",
+ "filter-dropdown.filter": "Filter",
+ "filter-dropdown.gt": "Greater or equal to",
+ "filter-dropdown.lt": "Less than or equal to",
+ "filter-dropdown.date": "Date"
+}
diff --git a/app/uni_modules/uni-table/i18n/es.json b/app/uni_modules/uni-table/i18n/es.json
new file mode 100644
index 0000000..9afd04b
--- /dev/null
+++ b/app/uni_modules/uni-table/i18n/es.json
@@ -0,0 +1,9 @@
+{
+ "filter-dropdown.reset": "Reiniciar",
+ "filter-dropdown.search": "B煤squeda",
+ "filter-dropdown.submit": "Entregar",
+ "filter-dropdown.filter": "Filtrar",
+ "filter-dropdown.gt": "Mayor o igual a",
+ "filter-dropdown.lt": "Menos que o igual a",
+ "filter-dropdown.date": "Fecha"
+}
diff --git a/app/uni_modules/uni-table/i18n/fr.json b/app/uni_modules/uni-table/i18n/fr.json
new file mode 100644
index 0000000..b006237
--- /dev/null
+++ b/app/uni_modules/uni-table/i18n/fr.json
@@ -0,0 +1,9 @@
+{
+ "filter-dropdown.reset": "R茅initialiser",
+ "filter-dropdown.search": "Chercher",
+ "filter-dropdown.submit": "Soumettre",
+ "filter-dropdown.filter": "Filtre",
+ "filter-dropdown.gt": "Sup茅rieur ou 茅gal 脿",
+ "filter-dropdown.lt": "Inf茅rieur ou 茅gal 脿",
+ "filter-dropdown.date": "Date"
+}
diff --git a/app/uni_modules/uni-table/i18n/index.js b/app/uni_modules/uni-table/i18n/index.js
new file mode 100644
index 0000000..2469dd0
--- /dev/null
+++ b/app/uni_modules/uni-table/i18n/index.js
@@ -0,0 +1,12 @@
+import en from './en.json'
+import es from './es.json'
+import fr from './fr.json'
+import zhHans from './zh-Hans.json'
+import zhHant from './zh-Hant.json'
+export default {
+ en,
+ es,
+ fr,
+ 'zh-Hans': zhHans,
+ 'zh-Hant': zhHant
+}
diff --git a/app/uni_modules/uni-table/i18n/zh-Hans.json b/app/uni_modules/uni-table/i18n/zh-Hans.json
new file mode 100644
index 0000000..862af17
--- /dev/null
+++ b/app/uni_modules/uni-table/i18n/zh-Hans.json
@@ -0,0 +1,9 @@
+{
+ "filter-dropdown.reset": "閲嶇疆",
+ "filter-dropdown.search": "鎼滅储",
+ "filter-dropdown.submit": "纭畾",
+ "filter-dropdown.filter": "绛涢��",
+ "filter-dropdown.gt": "澶т簬绛変簬",
+ "filter-dropdown.lt": "灏忎簬绛変簬",
+ "filter-dropdown.date": "鏃ユ湡鑼冨洿"
+}
diff --git a/app/uni_modules/uni-table/i18n/zh-Hant.json b/app/uni_modules/uni-table/i18n/zh-Hant.json
new file mode 100644
index 0000000..64f8061
--- /dev/null
+++ b/app/uni_modules/uni-table/i18n/zh-Hant.json
@@ -0,0 +1,9 @@
+{
+ "filter-dropdown.reset": "閲嶇疆",
+ "filter-dropdown.search": "鎼滅储",
+ "filter-dropdown.submit": "纰哄畾",
+ "filter-dropdown.filter": "绡╅伕",
+ "filter-dropdown.gt": "澶ф柤绛夋柤",
+ "filter-dropdown.lt": "灏忔柤绛夋柤",
+ "filter-dropdown.date": "鏃ユ湡绡勫湇"
+}
diff --git a/app/uni_modules/uni-table/package.json b/app/uni_modules/uni-table/package.json
new file mode 100644
index 0000000..7c2f91c
--- /dev/null
+++ b/app/uni_modules/uni-table/package.json
@@ -0,0 +1,83 @@
+{
+ "id": "uni-table",
+ "displayName": "uni-table 琛ㄦ牸",
+ "version": "1.2.3",
+ "description": "琛ㄦ牸缁勪欢锛屽鐢ㄤ簬灞曠ず澶氭潯缁撴瀯绫讳技鐨勬暟鎹紝濡�",
+ "keywords": [
+ "uni-ui",
+ "uniui",
+ "table",
+ "琛ㄦ牸"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+"dcloudext": {
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+ "type": "component-vue"
+ },
+ "uni_modules": {
+ "dependencies": ["uni-scss","uni-datetime-picker"],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "n"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "n",
+ "QQ": "y"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "n",
+ "鑱旂洘": "n"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/uni_modules/uni-table/readme.md b/app/uni_modules/uni-table/readme.md
new file mode 100644
index 0000000..bb08c79
--- /dev/null
+++ b/app/uni_modules/uni-table/readme.md
@@ -0,0 +1,13 @@
+
+
+## Table 琛ㄥ崟
+> 缁勪欢鍚嶏細``uni-table``锛屼唬鐮佸潡锛� `uTable`銆�
+
+鐢ㄤ簬灞曠ず澶氭潯缁撴瀯绫讳技鐨勬暟鎹�
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-table)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
+
+
+
+
diff --git a/app/uni_modules/uni-tag/changelog.md b/app/uni_modules/uni-tag/changelog.md
new file mode 100644
index 0000000..c0c5839
--- /dev/null
+++ b/app/uni_modules/uni-tag/changelog.md
@@ -0,0 +1,21 @@
+## 2.1.0锛�2021-11-19锛�
+- 浼樺寲 缁勪欢UI锛屽苟鎻愪緵璁捐璧勬簮锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 鏂囨。杩佺Щ锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/uni-tag](https://uniapp.dcloud.io/component/uniui/uni-tag)
+## 2.0.0锛�2021-11-09锛�
+- 鏂板 鎻愪緵缁勪欢璁捐璧勬簮锛岀粍浠舵牱寮忚皟鏁�
+- 绉婚櫎 鎻掓Ы
+- 绉婚櫎 type 灞炴�х殑 royal 閫夐」
+## 1.1.1锛�2021-08-11锛�
+- type 涓嶆槸 default 鏃讹紝size 涓� small 瀛椾綋澶у皬鏄剧ず涓嶆纭�
+## 1.1.0锛�2021-07-30锛�
+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤簐ue3椤圭洰锛岃瑙� [uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+## 1.0.7锛�2021-06-18锛�
+- 淇 uni-tag 鍦ㄥ瓧鑺傝烦鍔ㄥ皬绋嬪簭涓� css 绫诲悕缂栬瘧閿欒鐨� bug
+## 1.0.6锛�2021-06-04锛�
+- 淇 鏈畾涔� sass 鍙橀噺 "$uni-color-royal" 鐨刡ug
+## 1.0.5锛�2021-05-10锛�
+- 淇 royal 绫诲瀷鏃犳晥鐨刡ug
+- 淇 uni-tag 瀹藉害涓嶈嚜閫傚簲鐨刡ug
+- 鏂板 uni-tag 鏀寔灞炴�� custom-style 鑷畾涔夋牱寮�
+## 1.0.4锛�2021-02-05锛�
+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
diff --git a/app/uni_modules/uni-tag/components/uni-tag/uni-tag.vue b/app/uni_modules/uni-tag/components/uni-tag/uni-tag.vue
new file mode 100644
index 0000000..6378a0b
--- /dev/null
+++ b/app/uni_modules/uni-tag/components/uni-tag/uni-tag.vue
@@ -0,0 +1,252 @@
+<template>
+ <text class="uni-tag" v-if="text" :class="classes" :style="customStyle" @click="onClick">{{text}}</text>
+</template>
+
+<script>
+ /**
+ * Tag 鏍囩
+ * @description 鐢ㄤ簬灞曠ず1涓垨澶氫釜鏂囧瓧鏍囩锛屽彲鐐瑰嚮鍒囨崲閫変腑銆佷笉閫変腑鐨勭姸鎬�
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=35
+ * @property {String} text 鏍囩鍐呭
+ * @property {String} size = [default|small|mini] 澶у皬灏哄
+ * @value default 姝e父
+ * @value small 灏忓昂瀵�
+ * @value mini 杩蜂綘灏哄
+ * @property {String} type = [default|primary|success锝渨arning锝渆rror] 棰滆壊绫诲瀷
+ * @value default 鐏拌壊
+ * @value primary 钃濊壊
+ * @value success 缁胯壊
+ * @value warning 榛勮壊
+ * @value error 绾㈣壊
+ * @property {Boolean} disabled = [true|false] 鏄惁涓虹鐢ㄧ姸鎬�
+ * @property {Boolean} inverted = [true|false] 鏄惁鏃犻渶鑳屾櫙棰滆壊锛堢┖蹇冩爣绛撅級
+ * @property {Boolean} circle = [true|false] 鏄惁涓哄渾瑙�
+ * @event {Function} click 鐐瑰嚮 Tag 瑙﹀彂浜嬩欢
+ */
+
+ export default {
+ name: "UniTag",
+ emits: ['click'],
+ props: {
+ type: {
+ // 鏍囩绫诲瀷default銆乸rimary銆乻uccess銆亀arning銆乪rror銆乺oyal
+ type: String,
+ default: "default"
+ },
+ size: {
+ // 鏍囩澶у皬 normal, small
+ type: String,
+ default: "normal"
+ },
+ // 鏍囩鍐呭
+ text: {
+ type: String,
+ default: ""
+ },
+ disabled: {
+ // 鏄惁涓虹鐢ㄧ姸鎬�
+ type: [Boolean, String],
+ default: false
+ },
+ inverted: {
+ // 鏄惁涓虹┖蹇�
+ type: [Boolean, String],
+ default: false
+ },
+ circle: {
+ // 鏄惁涓哄渾瑙掓牱寮�
+ type: [Boolean, String],
+ default: false
+ },
+ mark: {
+ // 鏄惁涓烘爣璁版牱寮�
+ type: [Boolean, String],
+ default: false
+ },
+ customStyle: {
+ type: String,
+ default: ''
+ }
+ },
+ computed: {
+ classes() {
+ const {
+ type,
+ disabled,
+ inverted,
+ circle,
+ mark,
+ size,
+ isTrue
+ } = this
+ const classArr = [
+ 'uni-tag--' + type,
+ 'uni-tag--' + size,
+ isTrue(disabled) ? 'uni-tag--disabled' : '',
+ isTrue(inverted) ? 'uni-tag--' + type + '--inverted' : '',
+ isTrue(circle) ? 'uni-tag--circle' : '',
+ isTrue(mark) ? 'uni-tag--mark' : '',
+ // type === 'default' ? 'uni-tag--default' : 'uni-tag-text',
+ isTrue(inverted) ? 'uni-tag--inverted uni-tag-text--' + type : '',
+ size === 'small' ? 'uni-tag-text--small' : ''
+ ]
+ // 杩斿洖绫荤殑瀛楃涓诧紝鍏煎瀛楄妭灏忕▼搴�
+ return classArr.join(' ')
+ }
+ },
+ methods: {
+ isTrue(value) {
+ return value === true || value === 'true'
+ },
+ onClick() {
+ if (this.isTrue(this.disabled)) return
+ this.$emit("click");
+ }
+ }
+ };
+</script>
+
+<style lang="scss">
+ $uni-primary: #2979ff !default;
+ $uni-success: #18bc37 !default;
+ $uni-warning: #f3a73f !default;
+ $uni-error: #e43d33 !default;
+ $uni-info: #8f939c !default;
+
+
+ $tag-default-pd: 4px 7px;
+ $tag-small-pd: 2px 5px;
+ $tag-mini-pd: 1px 3px;
+
+ .uni-tag {
+ line-height: 14px;
+ font-size: 12px;
+ font-weight: 200;
+ padding: $tag-default-pd;
+ color: #fff;
+ border-radius: 3px;
+ background-color: $uni-info;
+ border-width: 1rpx;
+ border-style: solid;
+ border-color: $uni-info;
+ /* #ifdef H5 */
+ cursor: pointer;
+ /* #endif */
+
+ // size attr
+ &--default {
+ font-size: 12px;
+ }
+
+ &--default--inverted {
+ color: $uni-info;
+ border-color: $uni-info;
+ }
+
+ &--small {
+ padding: $tag-small-pd;
+ font-size: 12px;
+ border-radius: 2px;
+ }
+
+ &--mini {
+ padding: $tag-mini-pd;
+ font-size: 12px;
+ border-radius: 2px;
+ }
+
+ // type attr
+ &--primary {
+ background-color: $uni-primary;
+ border-color: $uni-primary;
+ color: #fff;
+ }
+
+ &--success {
+ color: #fff;
+ background-color: $uni-success;
+ border-color: $uni-success;
+ }
+
+ &--warning {
+ color: #fff;
+ background-color: $uni-warning;
+ border-color: $uni-warning;
+ }
+
+ &--error {
+ color: #fff;
+ background-color: $uni-error;
+ border-color: $uni-error;
+ }
+
+ &--primary--inverted {
+ color: $uni-primary;
+ border-color: $uni-primary;
+ }
+
+ &--success--inverted {
+ color: $uni-success;
+ border-color: $uni-success;
+ }
+
+ &--warning--inverted {
+ color: $uni-warning;
+ border-color: $uni-warning;
+ }
+
+ &--error--inverted {
+ color: $uni-error;
+ border-color: $uni-error;
+ }
+
+ &--inverted {
+ background-color: #fff;
+ }
+
+ // other attr
+ &--circle {
+ border-radius: 15px !important;
+ }
+
+ &--mark {
+ border-top-left-radius: 0 !important;
+ border-bottom-left-radius: 0 !important;
+ border-top-right-radius: 15px !important;
+ border-bottom-right-radius: 15px !important;
+ }
+
+ &--disabled {
+ opacity: 0.5;
+ /* #ifdef H5 */
+ cursor: not-allowed;
+ /* #endif */
+ }
+ }
+
+
+ .uni-tag-text {
+ color: #fff;
+ font-size: 14px;
+
+ &--primary {
+ color: $uni-primary;
+ }
+
+ &--success {
+ color: $uni-success;
+ }
+
+ &--warning {
+ color: $uni-warning;
+ }
+
+ &--error {
+ color: $uni-error;
+ }
+
+ &--small {
+ font-size: 12px;
+ }
+ }
+</style>
diff --git a/app/uni_modules/uni-tag/package.json b/app/uni_modules/uni-tag/package.json
new file mode 100644
index 0000000..1878088
--- /dev/null
+++ b/app/uni_modules/uni-tag/package.json
@@ -0,0 +1,87 @@
+{
+ "id": "uni-tag",
+ "displayName": "uni-tag 鏍囩",
+ "version": "2.1.0",
+ "description": "Tag 缁勪欢锛岀敤浜庡睍绀�1涓垨澶氫釜鏂囧瓧鏍囩锛屽彲鐐瑰嚮鍒囨崲閫変腑銆佷笉閫変腑鐨勭姸鎬併��",
+ "keywords": [
+ "uni-ui",
+ "uniui",
+ "",
+ "tag",
+ "鏍囩"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "鍓嶇缁勪欢",
+ "閫氱敤缁勪欢"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": ["uni-scss"],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "u",
+ "鑱旂洘": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/uni_modules/uni-tag/readme.md b/app/uni_modules/uni-tag/readme.md
new file mode 100644
index 0000000..6e78ff5
--- /dev/null
+++ b/app/uni_modules/uni-tag/readme.md
@@ -0,0 +1,13 @@
+
+
+## Tag 鏍囩
+> **缁勪欢鍚嶏細uni-tag**
+> 浠g爜鍧楋細 `uTag`
+
+
+鐢ㄤ簬灞曠ず1涓垨澶氫釜鏂囧瓧鏍囩锛屽彲鐐瑰嚮鍒囨崲閫変腑銆佷笉閫変腑鐨勭姸鎬� 銆�
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-tag)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
+
+
diff --git a/app/uni_modules/uni-title/changelog.md b/app/uni_modules/uni-title/changelog.md
new file mode 100644
index 0000000..7626216
--- /dev/null
+++ b/app/uni_modules/uni-title/changelog.md
@@ -0,0 +1,10 @@
+## 1.1.1锛�2022-05-19锛�
+- 淇敼缁勪欢鎻忚堪
+## 1.1.0锛�2021-11-19锛�
+- 浼樺寲 缁勪欢UI锛屽苟鎻愪緵璁捐璧勬簮锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 鏂囨。杩佺Щ锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/uni-title](https://uniapp.dcloud.io/component/uniui/uni-title)
+## 1.0.2锛�2021-05-12锛�
+- 鏂板 绀轰緥鍦板潃
+- 淇 绀轰緥椤圭洰缂哄皯缁勪欢鐨凚ug
+## 1.0.1锛�2021-02-05锛�
+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
diff --git a/app/uni_modules/uni-title/components/uni-title/uni-title.vue b/app/uni_modules/uni-title/components/uni-title/uni-title.vue
new file mode 100644
index 0000000..bf4f926
--- /dev/null
+++ b/app/uni_modules/uni-title/components/uni-title/uni-title.vue
@@ -0,0 +1,171 @@
+<template>
+ <view class="uni-title__box" :style="{'align-items':textAlign}">
+ <text class="uni-title__base" :class="['uni-'+type]" :style="{'color':color}">{{title}}</text>
+ </view>
+</template>
+
+<script>
+ /**
+ * Title 鏍囬
+ * @description 鏍囬锛岄�氬父鐢ㄤ簬璁板綍椤甸潰鏍囬锛屼娇鐢ㄥ綋鍓嶇粍浠讹紝uni-app 濡傛灉寮�鍚粺璁★紝灏嗕細鑷姩缁熻椤甸潰鏍囬
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=1066
+ * @property {String} type = [h1|h2|h3|h4|h5] 鏍囬绫诲瀷
+ * @value h1 涓�绾ф爣棰�
+ * @value h2 浜岀骇鏍囬
+ * @value h3 涓夌骇鏍囬
+ * @value h4 鍥涚骇鏍囬
+ * @value h5 浜旂骇鏍囬
+ * @property {String} title 鏍囬鍐呭
+ * @property {String} align = [left|center|right] 瀵归綈鏂瑰紡
+ * @value left 鍋氬榻�
+ * @value center 灞呬腑瀵归綈
+ * @value right 鍙冲榻�
+ * @property {String} color 瀛椾綋棰滆壊
+ * @property {Boolean} stat = [true|false] 鏄惁寮�鍚粺璁″姛鑳藉憿锛屽涓嶅~鍐檛ype鍊硷紝榛樿涓哄紑鍚紝濉啓 type 灞炴�э紝榛樿涓哄叧闂�
+ */
+ export default {
+ name:"UniTitle",
+ props: {
+ type: {
+ type: String,
+ default: ''
+ },
+ title: {
+ type: String,
+ default: ''
+ },
+ align: {
+ type: String,
+ default: 'left'
+ },
+ color: {
+ type: String,
+ default: '#333333'
+ },
+ stat: {
+ type: [Boolean, String],
+ default: ''
+ }
+ },
+ data() {
+ return {
+
+ };
+ },
+ computed: {
+ textAlign() {
+ let align = 'center';
+ switch (this.align) {
+ case 'left':
+ align = 'flex-start'
+ break;
+ case 'center':
+ align = 'center'
+ break;
+ case 'right':
+ align = 'flex-end'
+ break;
+ }
+ return align
+ }
+ },
+ watch: {
+ title(newVal) {
+ if (this.isOpenStat()) {
+ // 涓婃姤鏁版嵁
+ if (uni.report) {
+ uni.report('title', this.title)
+ }
+ }
+ }
+ },
+ mounted() {
+ if (this.isOpenStat()) {
+ // 涓婃姤鏁版嵁
+ if (uni.report) {
+ uni.report('title', this.title)
+ }
+ }
+ },
+ methods: {
+ isOpenStat() {
+ if (this.stat === '') {
+ this.isStat = false
+ }
+ let stat_type = (typeof(this.stat) === 'boolean' && this.stat) || (typeof(this.stat) === 'string' && this.stat !==
+ '')
+ if (this.type === "") {
+ this.isStat = true
+ if (this.stat.toString() === 'false') {
+ this.isStat = false
+ }
+ }
+
+ if (this.type !== '') {
+ this.isStat = true
+ if (stat_type) {
+ this.isStat = true
+ } else {
+ this.isStat = false
+ }
+ }
+ return this.isStat
+ }
+ }
+ }
+</script>
+
+<style>
+ /* .uni-title {
+
+ } */
+ .uni-title__box {
+ /* #ifndef APP-NVUE */
+ display: flex;
+ /* #endif */
+ flex-direction: column;
+ align-items: flex-start;
+ justify-content: center;
+ padding: 8px 0;
+ flex: 1;
+ }
+
+ .uni-title__base {
+ font-size: 15px;
+ color: #333;
+ font-weight: 500;
+ }
+
+ .uni-h1 {
+ font-size: 20px;
+ color: #333;
+ font-weight: bold;
+ }
+
+ .uni-h2 {
+ font-size: 18px;
+ color: #333;
+ font-weight: bold;
+ }
+
+ .uni-h3 {
+ font-size: 16px;
+ color: #333;
+ font-weight: bold;
+ /* font-weight: 400; */
+ }
+
+ .uni-h4 {
+ font-size: 14px;
+ color: #333;
+ font-weight: bold;
+ /* font-weight: 300; */
+ }
+
+ .uni-h5 {
+ font-size: 12px;
+ color: #333;
+ font-weight: bold;
+ /* font-weight: 200; */
+ }
+</style>
diff --git a/app/uni_modules/uni-title/package.json b/app/uni_modules/uni-title/package.json
new file mode 100644
index 0000000..2249f5a
--- /dev/null
+++ b/app/uni_modules/uni-title/package.json
@@ -0,0 +1,88 @@
+{
+ "id": "uni-title",
+ "displayName": "uni-title 绔犺妭鏍囬",
+ "version": "1.1.1",
+ "description": "绔犺妭鏍囬锛岄�氬父鐢ㄤ簬璁板綍椤甸潰鏍囬锛屼娇鐢ㄥ綋鍓嶇粍浠讹紝uni-app 濡傛灉寮�鍚粺璁★紝灏嗕細鑷姩缁熻椤甸潰鏍囬",
+ "keywords": [
+ "uni-ui",
+ "uniui",
+ "鏍囬",
+ "绔犺妭",
+ "绔犺妭鏍囬",
+ ""
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "鍓嶇缁勪欢",
+ "閫氱敤缁勪欢"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": ["uni-scss"],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "u",
+ "鑱旂洘": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/uni_modules/uni-title/readme.md b/app/uni_modules/uni-title/readme.md
new file mode 100644
index 0000000..0e60b1b
--- /dev/null
+++ b/app/uni_modules/uni-title/readme.md
@@ -0,0 +1,14 @@
+
+
+## Title 鏍囬
+> **缁勪欢鍚嶏細uni-title**
+> 浠g爜鍧楋細 `uTitle`
+
+
+绔犺妭鏍囬锛岄�氬父鐢ㄤ簬璁板綍椤甸潰鏍囬锛屼娇鐢ㄥ綋鍓嶇粍浠讹紝uni-app 濡傛灉寮�鍚粺璁★紝灏嗕細鑷姩缁熻椤甸潰鏍囬 銆�
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-title)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
+
+
+
diff --git a/app/uni_modules/uni-tooltip/changelog.md b/app/uni_modules/uni-tooltip/changelog.md
new file mode 100644
index 0000000..00f1572
--- /dev/null
+++ b/app/uni_modules/uni-tooltip/changelog.md
@@ -0,0 +1,10 @@
+## 0.2.1锛�2022-05-09锛�
+- 淇 content 涓虹┖鏃朵粛鐒跺脊鍑虹殑bug
+## 0.2.0锛�2022-05-07锛�
+**娉ㄦ剰锛氱牬鍧忔�ф洿鏂�**
+- 鏇存柊 text 灞炴�у彉鏇翠负 content
+- 鏇存柊 绉婚櫎 width 灞炴��
+## 0.1.1锛�2022-04-27锛�
+- 淇 缁勪欢鏍� text 宓屽缁勪欢 warning
+## 0.1.0锛�2022-04-21锛�
+- 鍒濆鍖�
diff --git a/app/uni_modules/uni-tooltip/components/uni-tooltip/uni-tooltip.vue b/app/uni_modules/uni-tooltip/components/uni-tooltip/uni-tooltip.vue
new file mode 100644
index 0000000..ffbb6fa
--- /dev/null
+++ b/app/uni_modules/uni-tooltip/components/uni-tooltip/uni-tooltip.vue
@@ -0,0 +1,68 @@
+<template>
+ <view class="uni-tooltip">
+ <slot></slot>
+ <view v-if="content || $slots.content" class="uni-tooltip-popup">
+ <slot name="content">
+ {{content}}
+ </slot>
+ </view>
+ </view>
+</template>
+
+
+<script>
+ /**
+ * Tooltip 鎻愮ず鏂囧瓧
+ * @description 甯哥敤浜庡睍绀洪紶鏍� hover 鏃剁殑鎻愮ず淇℃伅銆�
+ * @tutorial https://uniapp.dcloud.io/component/uniui/uni-tooltip
+ * @property {String} content 寮瑰嚭灞傛樉绀虹殑鍐呭
+ * @property {String} placement鍑虹幇浣嶇疆, 鐩墠鍙敮鎸� left
+ */
+
+
+ export default {
+ name: "uni-tooltip",
+ data() {
+ return {
+
+ };
+ },
+ props: {
+ content: {
+ type: String,
+ default: ''
+ },
+
+ placement: {
+ type: String,
+ default: 'bottom'
+ },
+ }
+ }
+</script>
+
+<style>
+ .uni-tooltip {
+ position: relative;
+ cursor: pointer;
+ }
+
+ .uni-tooltip-popup {
+ z-index: 1;
+ display: none;
+ position: absolute;
+ left: 0;
+ background-color: #333;
+ border-radius: 8px;
+ color: #fff;
+ font-size: 12px;
+ text-align: left;
+ line-height: 16px;
+ padding: 12px;
+ }
+
+
+ .uni-tooltip:hover .uni-tooltip-popup {
+ display: block;
+ }
+</style>
diff --git a/app/uni_modules/uni-tooltip/package.json b/app/uni_modules/uni-tooltip/package.json
new file mode 100644
index 0000000..e88ecf8
--- /dev/null
+++ b/app/uni_modules/uni-tooltip/package.json
@@ -0,0 +1,88 @@
+{
+ "id": "uni-tooltip",
+ "displayName": "uni-tooltip 鎻愮ず鏂囧瓧",
+ "version": "0.2.1",
+ "description": "Tooltip 鎻愮ず鏂囧瓧",
+ "keywords": [
+ "uni-tooltip",
+ "uni-ui",
+ "tooltip",
+ "tip",
+ "鏂囧瓧鎻愮ず"
+ ],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "鍓嶇缁勪欢",
+ "閫氱敤缁勪欢"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃� ",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": ""
+ },
+ "uni_modules": {
+ "dependencies": [],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ },
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "u"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "u",
+ "鐧惧害": "u",
+ "瀛楄妭璺冲姩": "u",
+ "QQ": "u",
+ "浜笢": "u"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "u",
+ "鑱旂洘": "u"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/uni_modules/uni-tooltip/readme.md b/app/uni_modules/uni-tooltip/readme.md
new file mode 100644
index 0000000..faafa2e
--- /dev/null
+++ b/app/uni_modules/uni-tooltip/readme.md
@@ -0,0 +1,8 @@
+## Badge 鏁板瓧瑙掓爣
+> **缁勪欢鍚嶏細uni-tooltip**
+> 浠g爜鍧楋細 `uTooltip`
+
+鏁板瓧瑙掓爣涓�鑸拰鍏跺畠鎺т欢锛堝垪琛ㄣ��9瀹牸绛夛級閰嶅悎浣跨敤锛岀敤浜庤繘琛屾暟閲忔彁绀猴紝榛樿涓哄疄蹇冪伆鑹茶儗鏅紝
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-tooltip)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
diff --git a/app/uni_modules/uni-transition/changelog.md b/app/uni_modules/uni-transition/changelog.md
new file mode 100644
index 0000000..b1a824b
--- /dev/null
+++ b/app/uni_modules/uni-transition/changelog.md
@@ -0,0 +1,20 @@
+## 1.3.1锛�2021-11-23锛�
+- 淇 init 鏂规硶鍒濆鍖栭棶棰�
+## 1.3.0锛�2021-11-19锛�
+- 浼樺寲 缁勪欢UI锛屽苟鎻愪緵璁捐璧勬簮锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 鏂囨。杩佺Щ锛岃瑙�:[https://uniapp.dcloud.io/component/uniui/uni-transition](https://uniapp.dcloud.io/component/uniui/uni-transition)
+## 1.2.1锛�2021-09-27锛�
+- 淇 init 鏂规硶涓嶇敓鏁堢殑 Bug
+## 1.2.0锛�2021-07-30锛�
+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤� vue3 椤圭洰锛岃瑙� [uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+## 1.1.1锛�2021-05-12锛�
+- 鏂板 绀轰緥鍦板潃
+- 淇 绀轰緥椤圭洰缂哄皯缁勪欢鐨� Bug
+## 1.1.0锛�2021-04-22锛�
+- 鏂板 閫氳繃鏂规硶鑷畾涔夊姩鐢�
+- 鏂板 custom-class 闈� NVUE 骞冲彴鏀寔鑷畾涔� class 瀹氬埗鏍峰紡
+- 浼樺寲 鍔ㄧ敾瑙﹀彂閫昏緫锛屼娇鍔ㄧ敾鏇存祦鐣�
+- 浼樺寲 鏀寔鍗曠嫭鐨勫姩鐢荤被鍨�
+- 浼樺寲 鏂囨。绀轰緥
+## 1.0.2锛�2021-02-05锛�
+- 璋冩暣涓� uni_modules 鐩綍瑙勮寖
diff --git a/app/uni_modules/uni-transition/components/uni-transition/createAnimation.js b/app/uni_modules/uni-transition/components/uni-transition/createAnimation.js
new file mode 100644
index 0000000..8f89b18
--- /dev/null
+++ b/app/uni_modules/uni-transition/components/uni-transition/createAnimation.js
@@ -0,0 +1,131 @@
+// const defaultOption = {
+// duration: 300,
+// timingFunction: 'linear',
+// delay: 0,
+// transformOrigin: '50% 50% 0'
+// }
+// #ifdef APP-NVUE
+const nvueAnimation = uni.requireNativePlugin('animation')
+// #endif
+class MPAnimation {
+ constructor(options, _this) {
+ this.options = options
+ // 鍦╥OS10+QQ灏忕▼搴忓钩鍙颁笅锛屼紶缁欏師鐢熺殑瀵硅薄涓�瀹氭槸涓櫘閫氬璞¤�屼笉鏄疨roxy瀵硅薄锛屽惁鍒欎細鎶arameter should be Object instead of ProxyObject鐨勯敊璇�
+ this.animation = uni.createAnimation({
+ ...options
+ })
+ this.currentStepAnimates = {}
+ this.next = 0
+ this.$ = _this
+
+ }
+
+ _nvuePushAnimates(type, args) {
+ let aniObj = this.currentStepAnimates[this.next]
+ let styles = {}
+ if (!aniObj) {
+ styles = {
+ styles: {},
+ config: {}
+ }
+ } else {
+ styles = aniObj
+ }
+ if (animateTypes1.includes(type)) {
+ if (!styles.styles.transform) {
+ styles.styles.transform = ''
+ }
+ let unit = ''
+ if(type === 'rotate'){
+ unit = 'deg'
+ }
+ styles.styles.transform += `${type}(${args+unit}) `
+ } else {
+ styles.styles[type] = `${args}`
+ }
+ this.currentStepAnimates[this.next] = styles
+ }
+ _animateRun(styles = {}, config = {}) {
+ let ref = this.$.$refs['ani'].ref
+ if (!ref) return
+ return new Promise((resolve, reject) => {
+ nvueAnimation.transition(ref, {
+ styles,
+ ...config
+ }, res => {
+ resolve()
+ })
+ })
+ }
+
+ _nvueNextAnimate(animates, step = 0, fn) {
+ let obj = animates[step]
+ if (obj) {
+ let {
+ styles,
+ config
+ } = obj
+ this._animateRun(styles, config).then(() => {
+ step += 1
+ this._nvueNextAnimate(animates, step, fn)
+ })
+ } else {
+ this.currentStepAnimates = {}
+ typeof fn === 'function' && fn()
+ this.isEnd = true
+ }
+ }
+
+ step(config = {}) {
+ // #ifndef APP-NVUE
+ this.animation.step(config)
+ // #endif
+ // #ifdef APP-NVUE
+ this.currentStepAnimates[this.next].config = Object.assign({}, this.options, config)
+ this.currentStepAnimates[this.next].styles.transformOrigin = this.currentStepAnimates[this.next].config.transformOrigin
+ this.next++
+ // #endif
+ return this
+ }
+
+ run(fn) {
+ // #ifndef APP-NVUE
+ this.$.animationData = this.animation.export()
+ this.$.timer = setTimeout(() => {
+ typeof fn === 'function' && fn()
+ }, this.$.durationTime)
+ // #endif
+ // #ifdef APP-NVUE
+ this.isEnd = false
+ let ref = this.$.$refs['ani'] && this.$.$refs['ani'].ref
+ if(!ref) return
+ this._nvueNextAnimate(this.currentStepAnimates, 0, fn)
+ this.next = 0
+ // #endif
+ }
+}
+
+
+const animateTypes1 = ['matrix', 'matrix3d', 'rotate', 'rotate3d', 'rotateX', 'rotateY', 'rotateZ', 'scale', 'scale3d',
+ 'scaleX', 'scaleY', 'scaleZ', 'skew', 'skewX', 'skewY', 'translate', 'translate3d', 'translateX', 'translateY',
+ 'translateZ'
+]
+const animateTypes2 = ['opacity', 'backgroundColor']
+const animateTypes3 = ['width', 'height', 'left', 'right', 'top', 'bottom']
+animateTypes1.concat(animateTypes2, animateTypes3).forEach(type => {
+ MPAnimation.prototype[type] = function(...args) {
+ // #ifndef APP-NVUE
+ this.animation[type](...args)
+ // #endif
+ // #ifdef APP-NVUE
+ this._nvuePushAnimates(type, args)
+ // #endif
+ return this
+ }
+})
+
+export function createAnimation(option, _this) {
+ if(!_this) return
+ clearTimeout(_this.timer)
+ return new MPAnimation(option, _this)
+}
diff --git a/app/uni_modules/uni-transition/components/uni-transition/uni-transition.vue b/app/uni_modules/uni-transition/components/uni-transition/uni-transition.vue
new file mode 100644
index 0000000..a2bf104
--- /dev/null
+++ b/app/uni_modules/uni-transition/components/uni-transition/uni-transition.vue
@@ -0,0 +1,281 @@
+<template>
+ <view v-if="isShow||onceRender" v-show="isShow" ref="ani" :animation="animationData" :class="customClass" :style="transformStyles" @click="onClick"><slot></slot></view>
+</template>
+
+<script>
+import { createAnimation } from './createAnimation'
+
+/**
+ * Transition 杩囨浮鍔ㄧ敾
+ * @description 绠�鍗曡繃娓″姩鐢荤粍浠�
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=985
+ * @property {Boolean} show = [false|true] 鎺у埗缁勪欢鏄剧ず鎴栭殣钘�
+ * @property {Array|String} modeClass = [fade|slide-top|slide-right|slide-bottom|slide-left|zoom-in|zoom-out] 杩囨浮鍔ㄧ敾绫诲瀷
+ * @value fade 娓愰殣娓愬嚭杩囨浮
+ * @value slide-top 鐢变笂鑷充笅杩囨浮
+ * @value slide-right 鐢卞彸鑷冲乏杩囨浮
+ * @value slide-bottom 鐢变笅鑷充笂杩囨浮
+ * @value slide-left 鐢卞乏鑷冲彸杩囨浮
+ * @value zoom-in 鐢卞皬鍒板ぇ杩囨浮
+ * @value zoom-out 鐢卞ぇ鍒板皬杩囨浮
+ * @property {Number} duration 杩囨浮鍔ㄧ敾鎸佺画鏃堕棿
+ * @property {Object} styles 缁勪欢鏍峰紡锛屽悓 css 鏍峰紡锛屾敞鎰忓甫鈥�-鈥樿繛鎺ョ鐨勫睘鎬ч渶瑕佷娇鐢ㄥ皬椹煎嘲鍐欐硶濡傦細`backgroundColor:red`
+ */
+export default {
+ name: 'uniTransition',
+ emits:['click','change'],
+ props: {
+ show: {
+ type: Boolean,
+ default: false
+ },
+ modeClass: {
+ type: [Array, String],
+ default() {
+ return 'fade'
+ }
+ },
+ duration: {
+ type: Number,
+ default: 300
+ },
+ styles: {
+ type: Object,
+ default() {
+ return {}
+ }
+ },
+ customClass:{
+ type: String,
+ default: ''
+ },
+ onceRender:{
+ type:Boolean,
+ default:false
+ },
+ },
+ data() {
+ return {
+ isShow: false,
+ transform: '',
+ opacity: 1,
+ animationData: {},
+ durationTime: 300,
+ config: {}
+ }
+ },
+ watch: {
+ show: {
+ handler(newVal) {
+ if (newVal) {
+ this.open()
+ } else {
+ // 閬垮厤涓婃潵灏辨墽琛� close,瀵艰嚧鍔ㄧ敾閿欎贡
+ if (this.isShow) {
+ this.close()
+ }
+ }
+ },
+ immediate: true
+ }
+ },
+ computed: {
+ // 鐢熸垚鏍峰紡鏁版嵁
+ stylesObject() {
+ let styles = {
+ ...this.styles,
+ 'transition-duration': this.duration / 1000 + 's'
+ }
+ let transform = ''
+ for (let i in styles) {
+ let line = this.toLine(i)
+ transform += line + ':' + styles[i] + ';'
+ }
+ return transform
+ },
+ // 鍒濆鍖栧姩鐢绘潯浠�
+ transformStyles() {
+ return 'transform:' + this.transform + ';' + 'opacity:' + this.opacity + ';' + this.stylesObject
+ }
+ },
+ created() {
+ // 鍔ㄧ敾榛樿閰嶇疆
+ this.config = {
+ duration: this.duration,
+ timingFunction: 'ease',
+ transformOrigin: '50% 50%',
+ delay: 0
+ }
+ this.durationTime = this.duration
+ },
+ methods: {
+ /**
+ * ref 瑙﹀彂 鍒濆鍖栧姩鐢�
+ */
+ init(obj = {}) {
+ if (obj.duration) {
+ this.durationTime = obj.duration
+ }
+ this.animation = createAnimation(Object.assign(this.config, obj),this)
+ },
+ /**
+ * 鐐瑰嚮缁勪欢瑙﹀彂鍥炶皟
+ */
+ onClick() {
+ this.$emit('click', {
+ detail: this.isShow
+ })
+ },
+ /**
+ * ref 瑙﹀彂 鍔ㄧ敾鍒嗙粍
+ * @param {Object} obj
+ */
+ step(obj, config = {}) {
+ if (!this.animation) return
+ for (let i in obj) {
+ try {
+ if(typeof obj[i] === 'object'){
+ this.animation[i](...obj[i])
+ }else{
+ this.animation[i](obj[i])
+ }
+ } catch (e) {
+ console.error(`鏂规硶 ${i} 涓嶅瓨鍦╜)
+ }
+ }
+ this.animation.step(config)
+ return this
+ },
+ /**
+ * ref 瑙﹀彂 鎵ц鍔ㄧ敾
+ */
+ run(fn) {
+ if (!this.animation) return
+ this.animation.run(fn)
+ },
+ // 寮�濮嬭繃搴﹀姩鐢�
+ open() {
+ clearTimeout(this.timer)
+ this.transform = ''
+ this.isShow = true
+ let { opacity, transform } = this.styleInit(false)
+ if (typeof opacity !== 'undefined') {
+ this.opacity = opacity
+ }
+ this.transform = transform
+ // 纭繚鍔ㄦ�佹牱寮忓凡缁忕敓鏁堝悗锛屾墽琛屽姩鐢伙紝濡傛灉涓嶅姞 nextTick 锛屼細瀵艰嚧 wx 鍔ㄧ敾鎵ц寮傚父
+ this.$nextTick(() => {
+ // TODO 瀹氭椂鍣ㄤ繚璇佸姩鐢诲畬鍏ㄦ墽琛岋紝鐩墠鏈変簺闂锛屽悗闈細鍙栨秷瀹氭椂鍣�
+ this.timer = setTimeout(() => {
+ this.animation = createAnimation(this.config, this)
+ this.tranfromInit(false).step()
+ this.animation.run()
+ this.$emit('change', {
+ detail: this.isShow
+ })
+ }, 20)
+ })
+ },
+ // 鍏抽棴杩囧害鍔ㄧ敾
+ close(type) {
+ if (!this.animation) return
+ this.tranfromInit(true)
+ .step()
+ .run(() => {
+ this.isShow = false
+ this.animationData = null
+ this.animation = null
+ let { opacity, transform } = this.styleInit(false)
+ this.opacity = opacity || 1
+ this.transform = transform
+ this.$emit('change', {
+ detail: this.isShow
+ })
+ })
+ },
+ // 澶勭悊鍔ㄧ敾寮�濮嬪墠鐨勯粯璁ゆ牱寮�
+ styleInit(type) {
+ let styles = {
+ transform: ''
+ }
+ let buildStyle = (type, mode) => {
+ if (mode === 'fade') {
+ styles.opacity = this.animationType(type)[mode]
+ } else {
+ styles.transform += this.animationType(type)[mode] + ' '
+ }
+ }
+ if (typeof this.modeClass === 'string') {
+ buildStyle(type, this.modeClass)
+ } else {
+ this.modeClass.forEach(mode => {
+ buildStyle(type, mode)
+ })
+ }
+ return styles
+ },
+ // 澶勭悊鍐呯疆缁勫悎鍔ㄧ敾
+ tranfromInit(type) {
+ let buildTranfrom = (type, mode) => {
+ let aniNum = null
+ if (mode === 'fade') {
+ aniNum = type ? 0 : 1
+ } else {
+ aniNum = type ? '-100%' : '0'
+ if (mode === 'zoom-in') {
+ aniNum = type ? 0.8 : 1
+ }
+ if (mode === 'zoom-out') {
+ aniNum = type ? 1.2 : 1
+ }
+ if (mode === 'slide-right') {
+ aniNum = type ? '100%' : '0'
+ }
+ if (mode === 'slide-bottom') {
+ aniNum = type ? '100%' : '0'
+ }
+ }
+ this.animation[this.animationMode()[mode]](aniNum)
+ }
+ if (typeof this.modeClass === 'string') {
+ buildTranfrom(type, this.modeClass)
+ } else {
+ this.modeClass.forEach(mode => {
+ buildTranfrom(type, mode)
+ })
+ }
+
+ return this.animation
+ },
+ animationType(type) {
+ return {
+ fade: type ? 1 : 0,
+ 'slide-top': `translateY(${type ? '0' : '-100%'})`,
+ 'slide-right': `translateX(${type ? '0' : '100%'})`,
+ 'slide-bottom': `translateY(${type ? '0' : '100%'})`,
+ 'slide-left': `translateX(${type ? '0' : '-100%'})`,
+ 'zoom-in': `scaleX(${type ? 1 : 0.8}) scaleY(${type ? 1 : 0.8})`,
+ 'zoom-out': `scaleX(${type ? 1 : 1.2}) scaleY(${type ? 1 : 1.2})`
+ }
+ },
+ // 鍐呯疆鍔ㄧ敾绫诲瀷涓庡疄闄呭姩鐢诲搴斿瓧鍏�
+ animationMode() {
+ return {
+ fade: 'opacity',
+ 'slide-top': 'translateY',
+ 'slide-right': 'translateX',
+ 'slide-bottom': 'translateY',
+ 'slide-left': 'translateX',
+ 'zoom-in': 'scale',
+ 'zoom-out': 'scale'
+ }
+ },
+ // 椹煎嘲杞腑妯嚎
+ toLine(name) {
+ return name.replace(/([A-Z])/g, '-$1').toLowerCase()
+ }
+ }
+}
+</script>
+
+<style></style>
diff --git a/app/uni_modules/uni-transition/package.json b/app/uni_modules/uni-transition/package.json
new file mode 100644
index 0000000..d15fdf0
--- /dev/null
+++ b/app/uni_modules/uni-transition/package.json
@@ -0,0 +1,87 @@
+{
+ "id": "uni-transition",
+ "displayName": "uni-transition 杩囨浮鍔ㄧ敾",
+ "version": "1.3.1",
+ "description": "鍏冪礌鐨勭畝鍗曡繃娓″姩鐢�",
+ "keywords": [
+ "uni-ui",
+ "uniui",
+ "鍔ㄧ敾",
+ "杩囨浮",
+ "杩囨浮鍔ㄧ敾"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "鍓嶇缁勪欢",
+ "閫氱敤缁勪欢"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "鏃�",
+ "data": "鏃�",
+ "permissions": "鏃�"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": ["uni-scss"],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "寰俊娴忚鍣�(Android)": "y",
+ "QQ娴忚鍣�(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "灏忕▼搴�": {
+ "寰俊": "y",
+ "闃块噷": "y",
+ "鐧惧害": "y",
+ "瀛楄妭璺冲姩": "y",
+ "QQ": "y"
+ },
+ "蹇簲鐢�": {
+ "鍗庝负": "u",
+ "鑱旂洘": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/uni_modules/uni-transition/readme.md b/app/uni_modules/uni-transition/readme.md
new file mode 100644
index 0000000..2f8a77e
--- /dev/null
+++ b/app/uni_modules/uni-transition/readme.md
@@ -0,0 +1,11 @@
+
+
+## Transition 杩囨浮鍔ㄧ敾
+> **缁勪欢鍚嶏細uni-transition**
+> 浠g爜鍧楋細 `uTransition`
+
+
+鍏冪礌杩囨浮鍔ㄧ敾
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-transition)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�呮偍瀵箄ni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839
\ No newline at end of file
diff --git a/app/utils/auth.js b/app/utils/auth.js
new file mode 100644
index 0000000..9a7cc04
--- /dev/null
+++ b/app/utils/auth.js
@@ -0,0 +1,13 @@
+const TokenKey = 'App-Token'
+
+export function getToken() {
+ return uni.getStorageSync(TokenKey)
+}
+
+export function setToken(token) {
+ return uni.setStorageSync(TokenKey, token)
+}
+
+export function removeToken() {
+ return uni.removeStorageSync(TokenKey)
+}
diff --git a/app/utils/common.js b/app/utils/common.js
new file mode 100644
index 0000000..00d4137
--- /dev/null
+++ b/app/utils/common.js
@@ -0,0 +1,54 @@
+/**
+* 鏄剧ず娑堟伅鎻愮ず妗�
+* @param content 鎻愮ず鐨勬爣棰�
+*/
+export function toast(content) {
+ uni.showToast({
+ icon: 'none',
+ title: content
+ })
+}
+
+/**
+* 鏄剧ず妯℃�佸脊绐�
+* @param content 鎻愮ず鐨勬爣棰�
+*/
+export function showConfirm(content) {
+ return new Promise((resolve, reject) => {
+ uni.showModal({
+ title: '鎻愮ず',
+ content: content,
+ cancelText: '鍙栨秷',
+ confirmText: '纭畾',
+ success: function(res) {
+ resolve(res)
+ }
+ })
+ })
+}
+
+/**
+* 鍙傛暟澶勭悊
+* @param params 鍙傛暟
+*/
+export function tansParams(params) {
+ let result = ''
+ for (const propName of Object.keys(params)) {
+ const value = params[propName]
+ var part = encodeURIComponent(propName) + "="
+ if (value !== null && value !== "" && typeof (value) !== "undefined") {
+ if (typeof value === 'object') {
+ for (const key of Object.keys(value)) {
+ if (value[key] !== null && value[key] !== "" && typeof (value[key]) !== 'undefined') {
+ let params = propName + '[' + key + ']'
+ var subPart = encodeURIComponent(params) + "="
+ result += subPart + encodeURIComponent(value[key]) + "&"
+ }
+ }
+ } else {
+ result += part + encodeURIComponent(value) + "&"
+ }
+ }
+ }
+ return result
+}
\ No newline at end of file
diff --git a/app/utils/constant.js b/app/utils/constant.js
new file mode 100644
index 0000000..8becd84
--- /dev/null
+++ b/app/utils/constant.js
@@ -0,0 +1,8 @@
+const constant = {
+ avatar: 'vuex_avatar',
+ name: 'vuex_name',
+ roles: 'vuex_roles',
+ permissions: 'vuex_permissions'
+ }
+
+ export default constant
diff --git a/app/utils/errorCode.js b/app/utils/errorCode.js
new file mode 100644
index 0000000..d2111ee
--- /dev/null
+++ b/app/utils/errorCode.js
@@ -0,0 +1,6 @@
+export default {
+ '401': '璁よ瘉澶辫触锛屾棤娉曡闂郴缁熻祫婧�',
+ '403': '褰撳墠鎿嶄綔娌℃湁鏉冮檺',
+ '404': '璁块棶璧勬簮涓嶅瓨鍦�',
+ 'default': '绯荤粺鏈煡閿欒锛岃鍙嶉缁欑鐞嗗憳'
+}
diff --git a/app/utils/permission.js b/app/utils/permission.js
new file mode 100644
index 0000000..17969f2
--- /dev/null
+++ b/app/utils/permission.js
@@ -0,0 +1,51 @@
+import store from '@/store'
+
+/**
+ * 瀛楃鏉冮檺鏍¢獙
+ * @param {Array} value 鏍¢獙鍊�
+ * @returns {Boolean}
+ */
+export function checkPermi(value) {
+ if (value && value instanceof Array && value.length > 0) {
+ const permissions = store.getters && store.getters.permissions
+ const permissionDatas = value
+ const all_permission = "*:*:*"
+
+ const hasPermission = permissions.some(permission => {
+ return all_permission === permission || permissionDatas.includes(permission)
+ })
+
+ if (!hasPermission) {
+ return false
+ }
+ return true
+ } else {
+ console.error(`need roles! Like checkPermi="['system:user:add','system:user:edit']"`)
+ return false
+ }
+}
+
+/**
+ * 瑙掕壊鏉冮檺鏍¢獙
+ * @param {Array} value 鏍¢獙鍊�
+ * @returns {Boolean}
+ */
+export function checkRole(value) {
+ if (value && value instanceof Array && value.length > 0) {
+ const roles = store.getters && store.getters.roles
+ const permissionRoles = value
+ const super_admin = "admin"
+
+ const hasRole = roles.some(role => {
+ return super_admin === role || permissionRoles.includes(role)
+ })
+
+ if (!hasRole) {
+ return false
+ }
+ return true
+ } else {
+ console.error(`need roles! Like checkRole="['admin','editor']"`)
+ return false
+ }
+}
\ No newline at end of file
diff --git a/app/utils/request.js b/app/utils/request.js
new file mode 100644
index 0000000..860f0ef
--- /dev/null
+++ b/app/utils/request.js
@@ -0,0 +1,73 @@
+import store from '@/store'
+import config from '@/config'
+import { getToken } from '@/utils/auth'
+import errorCode from '@/utils/errorCode'
+import { toast, showConfirm, tansParams } from '@/utils/common'
+
+let timeout = 10000
+const baseUrl = config.baseUrl
+
+const request = config => {
+ // 鏄惁闇�瑕佽缃� token
+ const isToken = (config.headers || {}).isToken === false
+ config.header = config.header || {}
+ if (getToken() && !isToken) {
+ config.header['Authorization'] = 'Bearer ' + getToken()
+ }
+ // get璇锋眰鏄犲皠params鍙傛暟
+ if (config.params) {
+ let url = config.url + '?' + tansParams(config.params)
+ url = url.slice(0, -1)
+ config.url = url
+ }
+ return new Promise((resolve, reject) => {
+ uni.request({
+ method: config.method || 'get',
+ timeout: config.timeout || timeout,
+ url: config.baseUrl || baseUrl + config.url,
+ data: config.data,
+ header: config.header,
+ dataType: 'json'
+ }).then(response => {
+ let [error, res] = response
+ if (error) {
+ toast('鍚庣鎺ュ彛杩炴帴寮傚父')
+ reject('鍚庣鎺ュ彛杩炴帴寮傚父')
+ return
+ }
+ const code = res.data.code || 200
+ const msg = errorCode[code] || res.data.msg || errorCode['default']
+ if (code === 401) {
+ showConfirm('鐧诲綍鐘舵�佸凡杩囨湡锛屾偍鍙互缁х画鐣欏湪璇ラ〉闈紝鎴栬�呴噸鏂扮櫥褰�?').then(res => {
+ if (res.confirm) {
+ store.dispatch('LogOut').then(res => {
+ uni.reLaunch({ url: '/pages/login' })
+ })
+ }
+ })
+ reject('鏃犳晥鐨勪細璇濓紝鎴栬�呬細璇濆凡杩囨湡锛岃閲嶆柊鐧诲綍銆�')
+ } else if (code === 500) {
+ toast(msg)
+ reject('500')
+ } else if (code !== 200) {
+ toast(msg)
+ reject(code)
+ }
+ resolve(res.data)
+ })
+ .catch(error => {
+ let { message } = error
+ if (message === 'Network Error') {
+ message = '鍚庣鎺ュ彛杩炴帴寮傚父'
+ } else if (message.includes('timeout')) {
+ message = '绯荤粺鎺ュ彛璇锋眰瓒呮椂'
+ } else if (message.includes('Request failed with status code')) {
+ message = '绯荤粺鎺ュ彛' + message.substr(message.length - 3) + '寮傚父'
+ }
+ toast(message)
+ reject(error)
+ })
+ })
+}
+
+export default request
diff --git a/app/utils/storage.js b/app/utils/storage.js
new file mode 100644
index 0000000..4c5fdec
--- /dev/null
+++ b/app/utils/storage.js
@@ -0,0 +1,32 @@
+import constant from './constant'
+
+// 瀛樺偍鍙橀噺鍚�
+let storageKey = 'storage_data'
+
+// 瀛樺偍鑺傜偣鍙橀噺鍚�
+let storageNodeKeys = [constant.avatar, constant.name, constant.roles, constant.permissions]
+
+const storage = {
+ set: function(key, value) {
+ if (storageNodeKeys.indexOf(key) != -1) {
+ let tmp = uni.getStorageSync(storageKey)
+ tmp = tmp ? tmp : {}
+ tmp[key] = value
+ uni.setStorageSync(storageKey, tmp)
+ }
+ },
+ get: function(key) {
+ let storageData = uni.getStorageSync(storageKey) || {}
+ return storageData[key] || ""
+ },
+ remove: function(key) {
+ let storageData = uni.getStorageSync(storageKey) || {}
+ delete storageData[key]
+ uni.setStorageSync(storageKey, storageData)
+ },
+ clean: function() {
+ uni.removeStorageSync(storageKey)
+ }
+}
+
+export default storage
diff --git a/app/utils/upload.js b/app/utils/upload.js
new file mode 100644
index 0000000..740387e
--- /dev/null
+++ b/app/utils/upload.js
@@ -0,0 +1,70 @@
+import store from '@/store'
+import config from '@/config'
+import { getToken } from '@/utils/auth'
+import errorCode from '@/utils/errorCode'
+import { toast, showConfirm, tansParams } from '@/utils/common'
+
+let timeout = 10000
+const baseUrl = config.baseUrl
+
+const upload = config => {
+ // 鏄惁闇�瑕佽缃� token
+ const isToken = (config.headers || {}).isToken === false
+ config.header = config.header || {}
+ if (getToken() && !isToken) {
+ config.header['Authorization'] = 'Bearer ' + getToken()
+ }
+ // get璇锋眰鏄犲皠params鍙傛暟
+ if (config.params) {
+ let url = config.url + '?' + tansParams(config.params)
+ url = url.slice(0, -1)
+ config.url = url
+ }
+ return new Promise((resolve, reject) => {
+ uni.uploadFile({
+ timeout: config.timeout || timeout,
+ url: baseUrl + config.url,
+ filePath: config.filePath,
+ name: config.name || 'file',
+ header: config.header,
+ formData: config.formData,
+ success: (res) => {
+ let result = JSON.parse(res.data)
+ const code = result.code || 200
+ const msg = errorCode[code] || result.msg || errorCode['default']
+ if (code === 200) {
+ resolve(result)
+ } else if (code == 401) {
+ showConfirm("鐧诲綍鐘舵�佸凡杩囨湡锛屾偍鍙互缁х画鐣欏湪璇ラ〉闈紝鎴栬�呴噸鏂扮櫥褰�?").then(res => {
+ if (res.confirm) {
+ store.dispatch('LogOut').then(res => {
+ uni.reLaunch({ url: '/pages/login/login' })
+ })
+ }
+ })
+ reject('鏃犳晥鐨勪細璇濓紝鎴栬�呬細璇濆凡杩囨湡锛岃閲嶆柊鐧诲綍銆�')
+ } else if (code === 500) {
+ toast(msg)
+ reject('500')
+ } else if (code !== 200) {
+ toast(msg)
+ reject(code)
+ }
+ },
+ fail: (error) => {
+ let { message } = error
+ if (message == 'Network Error') {
+ message = '鍚庣鎺ュ彛杩炴帴寮傚父'
+ } else if (message.includes('timeout')) {
+ message = '绯荤粺鎺ュ彛璇锋眰瓒呮椂'
+ } else if (message.includes('Request failed with status code')) {
+ message = '绯荤粺鎺ュ彛' + message.substr(message.length - 3) + '寮傚父'
+ }
+ toast(message)
+ reject(error)
+ }
+ })
+ })
+}
+
+export default upload
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskVehicleController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskVehicleController.java
index 6d70f75..c5dd2a1 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskVehicleController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskVehicleController.java
@@ -78,7 +78,9 @@
@PostMapping("/assign-batch/{taskId}")
public AjaxResult assignVehicles(@PathVariable("taskId") Long taskId, @RequestBody BatchAssignVehicleRequest request) {
try {
- int result = sysTaskService.assignMultipleVehiclesToTask(taskId, request.getVehicleIds(), request.getRemark());
+ // 璁剧疆璇锋眰瀵硅薄涓殑taskId锛岀‘淇濆弬鏁颁竴鑷存��
+ request.setTaskId(taskId);
+ int result = sysTaskService.assignMultipleVehiclesToTask(request.getTaskId(), request.getVehicleIds(), request.getRemark());
if (result > 0) {
return success("鎵归噺鍒嗛厤鎴愬姛锛屽叡鍒嗛厤 " + result + " 杈嗚溅");
} else {
@@ -136,9 +138,18 @@
* 鎵归噺鍒嗛厤杞﹁締璇锋眰瀵硅薄
*/
public static class BatchAssignVehicleRequest {
+ private Long taskId;
private List<Long> vehicleIds;
private String remark;
+ public Long getTaskId() {
+ return taskId;
+ }
+
+ public void setTaskId(Long taskId) {
+ this.taskId = taskId;
+ }
+
public List<Long> getVehicleIds() {
return vehicleIds;
}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskVehicleManagementController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskVehicleManagementController.java
new file mode 100644
index 0000000..9d47562
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskVehicleManagementController.java
@@ -0,0 +1,278 @@
+package com.ruoyi.web.controller.task;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.system.domain.SysTaskVehicle;
+import com.ruoyi.system.service.ISysTaskVehicleService;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * 浠诲姟杞﹁締鍏宠仈绠$悊Controller
+ *
+ * @author ruoyi
+ * @date 2024-01-15
+ */
+@RestController
+@RequestMapping("/task/vehicle/management")
+public class SysTaskVehicleManagementController extends BaseController {
+
+ @Autowired
+ private ISysTaskVehicleService sysTaskVehicleService;
+
+ /**
+ * 鏌ヨ浠诲姟杞﹁締鍏宠仈鍒楄〃
+ */
+ @PreAuthorize("@ss.hasPermi('task:vehicle:list')")
+ @GetMapping("/list")
+ public TableDataInfo list(SysTaskVehicle sysTaskVehicle) {
+ startPage();
+ List<SysTaskVehicle> list = sysTaskVehicleService.selectSysTaskVehicleList(sysTaskVehicle);
+ return getDataTable(list);
+ }
+
+ /**
+ * 瀵煎嚭浠诲姟杞﹁締鍏宠仈鍒楄〃
+ */
+ @PreAuthorize("@ss.hasPermi('task:vehicle:export')")
+ @Log(title = "浠诲姟杞﹁締鍏宠仈", businessType = BusinessType.EXPORT)
+ @PostMapping("/export")
+ public void export(HttpServletResponse response, SysTaskVehicle sysTaskVehicle) {
+ List<SysTaskVehicle> list = sysTaskVehicleService.selectSysTaskVehicleList(sysTaskVehicle);
+ ExcelUtil<SysTaskVehicle> util = new ExcelUtil<SysTaskVehicle>(SysTaskVehicle.class);
+ util.exportExcel(response, list, "浠诲姟杞﹁締鍏宠仈鏁版嵁");
+ }
+
+ /**
+ * 鑾峰彇浠诲姟杞﹁締鍏宠仈璇︾粏淇℃伅
+ */
+ @PreAuthorize("@ss.hasPermi('task:vehicle:query')")
+ @GetMapping(value = "/{id}")
+ public AjaxResult getInfo(@PathVariable("id") Long id) {
+ return success(sysTaskVehicleService.selectSysTaskVehicleById(id));
+ }
+
+ /**
+ * 鏂板浠诲姟杞﹁締鍏宠仈
+ */
+ @PreAuthorize("@ss.hasPermi('task:vehicle:add')")
+ @Log(title = "浠诲姟杞﹁締鍏宠仈", businessType = BusinessType.INSERT)
+ @PostMapping
+ public AjaxResult add(@RequestBody SysTaskVehicle sysTaskVehicle) {
+ try {
+ int result = sysTaskVehicleService.insertSysTaskVehicle(sysTaskVehicle);
+ if (result > 0) {
+ return success("鏂板鎴愬姛");
+ } else {
+ return error("鏂板澶辫触");
+ }
+ } catch (Exception e) {
+ return error("鏂板澶辫触锛�" + e.getMessage());
+ }
+ }
+
+ /**
+ * 淇敼浠诲姟杞﹁締鍏宠仈
+ */
+ @PreAuthorize("@ss.hasPermi('task:vehicle:edit')")
+ @Log(title = "浠诲姟杞﹁締鍏宠仈", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public AjaxResult edit(@RequestBody SysTaskVehicle sysTaskVehicle) {
+ try {
+ int result = sysTaskVehicleService.updateSysTaskVehicle(sysTaskVehicle);
+ if (result > 0) {
+ return success("淇敼鎴愬姛");
+ } else {
+ return error("淇敼澶辫触");
+ }
+ } catch (Exception e) {
+ return error("淇敼澶辫触锛�" + e.getMessage());
+ }
+ }
+
+ /**
+ * 鍒犻櫎浠诲姟杞﹁締鍏宠仈
+ */
+ @PreAuthorize("@ss.hasPermi('task:vehicle:remove')")
+ @Log(title = "浠诲姟杞﹁締鍏宠仈", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{ids}")
+ public AjaxResult remove(@PathVariable Long[] ids) {
+ try {
+ int result = sysTaskVehicleService.deleteSysTaskVehicleByIds(ids);
+ if (result > 0) {
+ return success("鍒犻櫎鎴愬姛");
+ } else {
+ return error("鍒犻櫎澶辫触");
+ }
+ } catch (Exception e) {
+ return error("鍒犻櫎澶辫触锛�" + e.getMessage());
+ }
+ }
+
+ /**
+ * 鏍规嵁浠诲姟ID鏌ヨ鍏宠仈杞﹁締鍒楄〃
+ */
+ @PreAuthorize("@ss.hasPermi('task:vehicle:query')")
+ @GetMapping("/task/{taskId}")
+ public AjaxResult getVehiclesByTaskId(@PathVariable("taskId") Long taskId) {
+ List<SysTaskVehicle> list = sysTaskVehicleService.selectSysTaskVehicleByTaskId(taskId);
+ return success(list);
+ }
+
+ /**
+ * 鍒嗛厤杞﹁締缁欎换鍔�
+ */
+ @PreAuthorize("@ss.hasPermi('task:vehicle:assign')")
+ @Log(title = "浠诲姟杞﹁締鍒嗛厤", businessType = BusinessType.INSERT)
+ @PostMapping("/assign")
+ public AjaxResult assignVehicle(@RequestBody AssignVehicleRequest request) {
+ try {
+ int result = sysTaskVehicleService.assignVehicleToTask(request.getTaskId(), request.getVehicleId(), request.getRemark());
+ if (result > 0) {
+ return success("鍒嗛厤鎴愬姛");
+ } else {
+ return error("鍒嗛厤澶辫触");
+ }
+ } catch (Exception e) {
+ return error("鍒嗛厤澶辫触锛�" + e.getMessage());
+ }
+ }
+
+ /**
+ * 鎵归噺鍒嗛厤杞﹁締缁欎换鍔�
+ */
+ @PreAuthorize("@ss.hasPermi('task:vehicle:assign')")
+ @Log(title = "浠诲姟杞﹁締鎵归噺鍒嗛厤", businessType = BusinessType.INSERT)
+ @PostMapping("/assign-batch")
+ public AjaxResult assignVehicles(@RequestBody BatchAssignVehicleRequest request) {
+ try {
+ int result = sysTaskVehicleService.assignMultipleVehiclesToTask(request.getTaskId(), request.getVehicleIds(), request.getRemark());
+ if (result > 0) {
+ return success("鎵归噺鍒嗛厤鎴愬姛锛屽叡鍒嗛厤 " + result + " 杈嗚溅");
+ } else {
+ return error("鎵归噺鍒嗛厤澶辫触");
+ }
+ } catch (Exception e) {
+ return error("鎵归噺鍒嗛厤澶辫触锛�" + e.getMessage());
+ }
+ }
+
+ /**
+ * 鍙栨秷浠诲姟杞﹁締鍒嗛厤
+ */
+ @PreAuthorize("@ss.hasPermi('task:vehicle:assign')")
+ @Log(title = "鍙栨秷浠诲姟杞﹁締鍒嗛厤", businessType = BusinessType.DELETE)
+ @DeleteMapping("/unassign/{taskId}/{vehicleId}")
+ public AjaxResult unassignVehicle(@PathVariable("taskId") Long taskId, @PathVariable("vehicleId") Long vehicleId) {
+ try {
+ int result = sysTaskVehicleService.unassignVehicleFromTask(taskId, vehicleId);
+ if (result > 0) {
+ return success("鍙栨秷鍒嗛厤鎴愬姛");
+ } else {
+ return error("鍙栨秷鍒嗛厤澶辫触");
+ }
+ } catch (Exception e) {
+ return error("鍙栨秷鍒嗛厤澶辫触锛�" + e.getMessage());
+ }
+ }
+
+ /**
+ * 鏇存柊浠诲姟杞﹁締鍏宠仈鐘舵��
+ */
+ @PreAuthorize("@ss.hasPermi('task:vehicle:edit')")
+ @Log(title = "鏇存柊浠诲姟杞﹁締鐘舵��", businessType = BusinessType.UPDATE)
+ @PutMapping("/status/{id}")
+ public AjaxResult updateStatus(@PathVariable("id") Long id, @RequestParam String status) {
+ try {
+ int result = sysTaskVehicleService.updateTaskVehicleStatus(id, status);
+ if (result > 0) {
+ return success("鐘舵�佹洿鏂版垚鍔�");
+ } else {
+ return error("鐘舵�佹洿鏂板け璐�");
+ }
+ } catch (Exception e) {
+ return error("鐘舵�佹洿鏂板け璐ワ細" + e.getMessage());
+ }
+ }
+
+ /**
+ * 鍒嗛厤杞﹁締璇锋眰瀵硅薄
+ */
+ public static class AssignVehicleRequest {
+ private Long taskId;
+ private Long vehicleId;
+ private String remark;
+
+ public Long getTaskId() {
+ return taskId;
+ }
+
+ public void setTaskId(Long taskId) {
+ this.taskId = taskId;
+ }
+
+ public Long getVehicleId() {
+ return vehicleId;
+ }
+
+ public void setVehicleId(Long vehicleId) {
+ this.vehicleId = vehicleId;
+ }
+
+ public String getRemark() {
+ return remark;
+ }
+
+ public void setRemark(String remark) {
+ this.remark = remark;
+ }
+ }
+
+ /**
+ * 鎵归噺鍒嗛厤杞﹁締璇锋眰瀵硅薄
+ */
+ public static class BatchAssignVehicleRequest {
+ private Long taskId;
+ private List<Long> vehicleIds;
+ private String remark;
+
+ public Long getTaskId() {
+ return taskId;
+ }
+
+ public void setTaskId(Long taskId) {
+ this.taskId = taskId;
+ }
+
+ public List<Long> getVehicleIds() {
+ return vehicleIds;
+ }
+
+ public void setVehicleIds(List<Long> vehicleIds) {
+ this.vehicleIds = vehicleIds;
+ }
+
+ public String getRemark() {
+ return remark;
+ }
+
+ public void setRemark(String remark) {
+ this.remark = remark;
+ }
+ }
+}
diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml
index 0128223..ae08b40 100644
--- a/ruoyi-admin/src/main/resources/application.yml
+++ b/ruoyi-admin/src/main/resources/application.yml
@@ -56,7 +56,7 @@
basename: i18n/messages
profiles:
# 鐜 dev|test|prod
- active: prod
+ active: dev
# 鏂囦欢涓婁紶
servlet:
multipart:
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/GpsDistanceUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/GpsDistanceUtils.java
new file mode 100644
index 0000000..cc96961
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/GpsDistanceUtils.java
@@ -0,0 +1,132 @@
+package com.ruoyi.common.utils;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+
+/**
+ * GPS鍧愭爣璺濈璁$畻宸ュ叿绫�
+ * 浣跨敤Haversine鍏紡璁$畻涓ょ偣闂寸殑鐞冮潰璺濈
+ *
+ * @author ruoyi
+ * @date 2024-01-15
+ */
+public class GpsDistanceUtils {
+
+ /** 鍦扮悆鍗婂緞锛堝叕閲岋級 */
+ private static final double EARTH_RADIUS = 6371.0;
+
+ /**
+ * 璁$畻涓や釜GPS鍧愭爣鐐逛箣闂寸殑璺濈锛堝叕閲岋級
+ *
+ * @param lat1 璧风偣绾害
+ * @param lon1 璧风偣缁忓害
+ * @param lat2 缁堢偣绾害
+ * @param lon2 缁堢偣缁忓害
+ * @return 璺濈锛堝叕閲岋級锛屼繚鐣�2浣嶅皬鏁�
+ */
+ public static BigDecimal calculateDistance(double lat1, double lon1, double lat2, double lon2) {
+ // 灏嗚搴﹁浆鎹负寮у害
+ double lat1Rad = Math.toRadians(lat1);
+ double lon1Rad = Math.toRadians(lon1);
+ double lat2Rad = Math.toRadians(lat2);
+ double lon2Rad = Math.toRadians(lon2);
+
+ // 璁$畻绾害宸拰缁忓害宸�
+ double deltaLat = lat2Rad - lat1Rad;
+ double deltaLon = lon2Rad - lon1Rad;
+
+ // Haversine鍏紡
+ double a = Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2) +
+ Math.cos(lat1Rad) * Math.cos(lat2Rad) *
+ Math.sin(deltaLon / 2) * Math.sin(deltaLon / 2);
+
+ double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
+
+ // 璁$畻璺濈
+ double distance = EARTH_RADIUS * c;
+
+ // 杩斿洖BigDecimal锛屼繚鐣�2浣嶅皬鏁�
+ return new BigDecimal(distance).setScale(2, RoundingMode.HALF_UP);
+ }
+
+ /**
+ * 璁$畻涓や釜GPS鍧愭爣鐐逛箣闂寸殑璺濈锛堝叕閲岋級
+ *
+ * @param lat1 璧风偣绾害
+ * @param lon1 璧风偣缁忓害
+ * @param lat2 缁堢偣绾害
+ * @param lon2 缁堢偣缁忓害
+ * @return 璺濈锛堝叕閲岋級锛屼繚鐣�2浣嶅皬鏁�
+ */
+ public static BigDecimal calculateDistance(BigDecimal lat1, BigDecimal lon1, BigDecimal lat2, BigDecimal lon2) {
+ if (lat1 == null || lon1 == null || lat2 == null || lon2 == null) {
+ return BigDecimal.ZERO;
+ }
+
+ return calculateDistance(lat1.doubleValue(), lon1.doubleValue(),
+ lat2.doubleValue(), lon2.doubleValue());
+ }
+
+ /**
+ * 楠岃瘉GPS鍧愭爣鏄惁鏈夋晥
+ *
+ * @param latitude 绾害
+ * @param longitude 缁忓害
+ * @return 鏄惁鏈夋晥
+ */
+ public static boolean isValidCoordinate(double latitude, double longitude) {
+ return latitude >= -90 && latitude <= 90 && longitude >= -180 && longitude <= 180;
+ }
+
+ /**
+ * 楠岃瘉GPS鍧愭爣鏄惁鏈夋晥
+ *
+ * @param latitude 绾害
+ * @param longitude 缁忓害
+ * @return 鏄惁鏈夋晥
+ */
+ public static boolean isValidCoordinate(BigDecimal latitude, BigDecimal longitude) {
+ if (latitude == null || longitude == null) {
+ return false;
+ }
+
+ return isValidCoordinate(latitude.doubleValue(), longitude.doubleValue());
+ }
+
+ /**
+ * 鏍煎紡鍖朑PS鍧愭爣鏄剧ず
+ *
+ * @param coordinate 鍧愭爣鍊�
+ * @return 鏍煎紡鍖栧悗鐨勫潗鏍囧瓧绗︿覆
+ */
+ public static String formatCoordinate(BigDecimal coordinate) {
+ if (coordinate == null) {
+ return "";
+ }
+ return coordinate.setScale(6, RoundingMode.HALF_UP).toString();
+ }
+
+ /**
+ * 鑾峰彇鍧愭爣鐨勫害鍒嗙鏍煎紡
+ *
+ * @param coordinate 鍧愭爣鍊硷紙搴︼級
+ * @return 搴﹀垎绉掓牸寮忓瓧绗︿覆
+ */
+ public static String toDegreesMinutesSeconds(BigDecimal coordinate) {
+ if (coordinate == null) {
+ return "";
+ }
+
+ double coord = coordinate.doubleValue();
+ boolean isNegative = coord < 0;
+ coord = Math.abs(coord);
+
+ int degrees = (int) coord;
+ double minutesFloat = (coord - degrees) * 60;
+ int minutes = (int) minutesFloat;
+ double seconds = (minutesFloat - minutes) * 60;
+
+ String result = String.format("%d掳%d'%.2f\"", degrees, minutes, seconds);
+ return isNegative ? "-" + result : result;
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTask.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTask.java
index 0286efe..99c8bad 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTask.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTask.java
@@ -44,6 +44,26 @@
@Excel(name = "鐩殑鍦板潃")
private String destinationAddress;
+ /** 鍑哄彂鍦扮粡搴� */
+ @Excel(name = "鍑哄彂鍦扮粡搴�")
+ private java.math.BigDecimal departureLongitude;
+
+ /** 鍑哄彂鍦扮含搴� */
+ @Excel(name = "鍑哄彂鍦扮含搴�")
+ private java.math.BigDecimal departureLatitude;
+
+ /** 鐩殑鍦扮粡搴� */
+ @Excel(name = "鐩殑鍦扮粡搴�")
+ private java.math.BigDecimal destinationLongitude;
+
+ /** 鐩殑鍦扮含搴� */
+ @Excel(name = "鐩殑鍦扮含搴�")
+ private java.math.BigDecimal destinationLatitude;
+
+ /** 棰勮鍏噷鏁� */
+ @Excel(name = "棰勮鍏噷鏁�")
+ private java.math.BigDecimal estimatedDistance;
+
/** 璁″垝寮�濮嬫椂闂� */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "璁″垝寮�濮嬫椂闂�", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
@@ -156,6 +176,46 @@
return destinationAddress;
}
+ public void setDepartureLongitude(java.math.BigDecimal departureLongitude) {
+ this.departureLongitude = departureLongitude;
+ }
+
+ public java.math.BigDecimal getDepartureLongitude() {
+ return departureLongitude;
+ }
+
+ public void setDepartureLatitude(java.math.BigDecimal departureLatitude) {
+ this.departureLatitude = departureLatitude;
+ }
+
+ public java.math.BigDecimal getDepartureLatitude() {
+ return departureLatitude;
+ }
+
+ public void setDestinationLongitude(java.math.BigDecimal destinationLongitude) {
+ this.destinationLongitude = destinationLongitude;
+ }
+
+ public java.math.BigDecimal getDestinationLongitude() {
+ return destinationLongitude;
+ }
+
+ public void setDestinationLatitude(java.math.BigDecimal destinationLatitude) {
+ this.destinationLatitude = destinationLatitude;
+ }
+
+ public java.math.BigDecimal getDestinationLatitude() {
+ return destinationLatitude;
+ }
+
+ public void setEstimatedDistance(java.math.BigDecimal estimatedDistance) {
+ this.estimatedDistance = estimatedDistance;
+ }
+
+ public java.math.BigDecimal getEstimatedDistance() {
+ return estimatedDistance;
+ }
+
public void setPlannedStartTime(Date plannedStartTime) {
this.plannedStartTime = plannedStartTime;
}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskVehicle.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskVehicle.java
index 6630b8f..9344047 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskVehicle.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskVehicle.java
@@ -54,6 +54,10 @@
@Excel(name = "杞﹁締鍨嬪彿")
private String vehicleModel;
+ /** 褰掑睘閮ㄩ棬鍚嶇О */
+ @Excel(name = "褰掑睘閮ㄩ棬")
+ private String deptName;
+
public void setId(Long id) {
this.id = id;
}
@@ -134,6 +138,14 @@
return vehicleModel;
}
+ public void setDeptName(String deptName) {
+ this.deptName = deptName;
+ }
+
+ public String getDeptName() {
+ return deptName;
+ }
+
@Override
public String toString() {
return "SysTaskVehicle{" +
@@ -147,6 +159,7 @@
", vehicleType='" + vehicleType + '\'' +
", vehicleBrand='" + vehicleBrand + '\'' +
", vehicleModel='" + vehicleModel + '\'' +
+ ", deptName='" + deptName + '\'' +
'}';
}
}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/VehicleInfo.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/VehicleInfo.java
index b8aa771..f3017e6 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/VehicleInfo.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/VehicleInfo.java
@@ -42,6 +42,14 @@
@Excel(name = "骞冲彴鏍囪瘑")
private String platformCode;
+ /** 褰掑睘閮ㄩ棬ID */
+ @Excel(name = "褰掑睘閮ㄩ棬ID")
+ private Long deptId;
+
+ /** 褰掑睘閮ㄩ棬鍚嶇О */
+ @Excel(name = "褰掑睘閮ㄩ棬")
+ private String deptName;
+
public void setVehicleId(Long vehicleId) {
this.vehicleId = vehicleId;
}
@@ -106,6 +114,22 @@
this.platformCode = platformCode;
}
+ public Long getDeptId() {
+ return deptId;
+ }
+
+ public void setDeptId(Long deptId) {
+ this.deptId = deptId;
+ }
+
+ public String getDeptName() {
+ return deptName;
+ }
+
+ public void setDeptName(String deptName) {
+ this.deptName = deptName;
+ }
+
@Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
@@ -117,6 +141,8 @@
.append("vehicleModel", getVehicleModel())
.append("status", getStatus())
.append("platformCode", getPlatformCode())
+ .append("deptId", getDeptId())
+ .append("deptName", getDeptName())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskCreateVO.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskCreateVO.java
index c1f60e4..809b5b7 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskCreateVO.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskCreateVO.java
@@ -1,6 +1,8 @@
package com.ruoyi.system.domain.vo;
+import java.math.BigDecimal;
import java.util.Date;
+import java.util.List;
import com.fasterxml.jackson.annotation.JsonFormat;
/**
@@ -36,6 +38,21 @@
/** 澶囨敞 */
private String remark;
+
+ /** 鍑哄彂鍦扮粡搴� */
+ private BigDecimal departureLongitude;
+
+ /** 鍑哄彂鍦扮含搴� */
+ private BigDecimal departureLatitude;
+
+ /** 鐩殑鍦扮粡搴� */
+ private BigDecimal destinationLongitude;
+
+ /** 鐩殑鍦扮含搴� */
+ private BigDecimal destinationLatitude;
+
+ /** 杞﹁締ID鍒楄〃 */
+ private List<Long> vehicleIds;
public String getTaskType() {
return taskType;
@@ -100,4 +117,44 @@
public void setRemark(String remark) {
this.remark = remark;
}
+
+ public BigDecimal getDepartureLongitude() {
+ return departureLongitude;
+ }
+
+ public void setDepartureLongitude(BigDecimal departureLongitude) {
+ this.departureLongitude = departureLongitude;
+ }
+
+ public BigDecimal getDepartureLatitude() {
+ return departureLatitude;
+ }
+
+ public void setDepartureLatitude(BigDecimal departureLatitude) {
+ this.departureLatitude = departureLatitude;
+ }
+
+ public BigDecimal getDestinationLongitude() {
+ return destinationLongitude;
+ }
+
+ public void setDestinationLongitude(BigDecimal destinationLongitude) {
+ this.destinationLongitude = destinationLongitude;
+ }
+
+ public BigDecimal getDestinationLatitude() {
+ return destinationLatitude;
+ }
+
+ public void setDestinationLatitude(BigDecimal destinationLatitude) {
+ this.destinationLatitude = destinationLatitude;
+ }
+
+ public List<Long> getVehicleIds() {
+ return vehicleIds;
+ }
+
+ public void setVehicleIds(List<Long> vehicleIds) {
+ this.vehicleIds = vehicleIds;
+ }
}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskUpdateVO.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskUpdateVO.java
index 155b5ed..b8e502b 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskUpdateVO.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskUpdateVO.java
@@ -1,5 +1,6 @@
package com.ruoyi.system.domain.vo;
+import java.math.BigDecimal;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
@@ -36,6 +37,18 @@
/** 澶囨敞 */
private String remark;
+
+ /** 鍑哄彂鍦扮粡搴� */
+ private BigDecimal departureLongitude;
+
+ /** 鍑哄彂鍦扮含搴� */
+ private BigDecimal departureLatitude;
+
+ /** 鐩殑鍦扮粡搴� */
+ private BigDecimal destinationLongitude;
+
+ /** 鐩殑鍦扮含搴� */
+ private BigDecimal destinationLatitude;
public Long getTaskId() {
return taskId;
@@ -100,4 +113,36 @@
public void setRemark(String remark) {
this.remark = remark;
}
+
+ public BigDecimal getDepartureLongitude() {
+ return departureLongitude;
+ }
+
+ public void setDepartureLongitude(BigDecimal departureLongitude) {
+ this.departureLongitude = departureLongitude;
+ }
+
+ public BigDecimal getDepartureLatitude() {
+ return departureLatitude;
+ }
+
+ public void setDepartureLatitude(BigDecimal departureLatitude) {
+ this.departureLatitude = departureLatitude;
+ }
+
+ public BigDecimal getDestinationLongitude() {
+ return destinationLongitude;
+ }
+
+ public void setDestinationLongitude(BigDecimal destinationLongitude) {
+ this.destinationLongitude = destinationLongitude;
+ }
+
+ public BigDecimal getDestinationLatitude() {
+ return destinationLatitude;
+ }
+
+ public void setDestinationLatitude(BigDecimal destinationLatitude) {
+ this.destinationLatitude = destinationLatitude;
+ }
}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskMapper.java
index 6a914c5..4c703c0 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskMapper.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskMapper.java
@@ -92,6 +92,14 @@
public SysTask selectSysTaskByTaskCode(String taskCode);
/**
+ * 鏌ヨ鎸囧畾鏃ユ湡鍓嶇紑鐨勬渶澶т换鍔$紪鍙�
+ *
+ * @param datePrefix 鏃ユ湡鍓嶇紑锛堝锛歍ASK20250923锛�
+ * @return 鏈�澶т换鍔$紪鍙�
+ */
+ public String selectMaxTaskCodeByDatePrefix(String datePrefix);
+
+ /**
* 鏇存柊浠诲姟鐘舵��
*
* @param sysTask 浠诲姟淇℃伅
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskVehicleMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskVehicleMapper.java
index 1969629..8a1d6a4 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskVehicleMapper.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTaskVehicleMapper.java
@@ -1,6 +1,7 @@
package com.ruoyi.system.mapper;
import java.util.List;
+import org.apache.ibatis.annotations.Param;
import com.ruoyi.system.domain.SysTaskVehicle;
/**
@@ -82,7 +83,7 @@
* @param vehicleId 杞﹁締ID
* @return 缁撴灉
*/
- public int deleteSysTaskVehicleByTaskIdAndVehicleId(Long taskId, Long vehicleId);
+ public int deleteSysTaskVehicleByTaskIdAndVehicleId(@Param("taskId") Long taskId, @Param("vehicleId") Long vehicleId);
/**
* 妫�鏌ヤ换鍔¤溅杈嗗叧鑱旀槸鍚﹀瓨鍦�
@@ -91,7 +92,7 @@
* @param vehicleId 杞﹁締ID
* @return 缁撴灉
*/
- public int checkTaskVehicleExists(Long taskId, Long vehicleId);
+ public int checkTaskVehicleExists(@Param("taskId") Long taskId, @Param("vehicleId") Long vehicleId);
/**
* 鎵归噺鏂板浠诲姟杞﹁締鍏宠仈
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskVehicleService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskVehicleService.java
new file mode 100644
index 0000000..75ab50f
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskVehicleService.java
@@ -0,0 +1,150 @@
+package com.ruoyi.system.service;
+
+import java.util.List;
+import com.ruoyi.system.domain.SysTaskVehicle;
+
+/**
+ * 浠诲姟杞﹁締鍏宠仈Service鎺ュ彛
+ *
+ * @author ruoyi
+ * @date 2024-01-15
+ */
+public interface ISysTaskVehicleService {
+
+ /**
+ * 鏌ヨ浠诲姟杞﹁締鍏宠仈
+ *
+ * @param id 浠诲姟杞﹁締鍏宠仈涓婚敭
+ * @return 浠诲姟杞﹁締鍏宠仈
+ */
+ public SysTaskVehicle selectSysTaskVehicleById(Long id);
+
+ /**
+ * 鏌ヨ浠诲姟杞﹁締鍏宠仈鍒楄〃
+ *
+ * @param sysTaskVehicle 浠诲姟杞﹁締鍏宠仈
+ * @return 浠诲姟杞﹁締鍏宠仈闆嗗悎
+ */
+ public List<SysTaskVehicle> selectSysTaskVehicleList(SysTaskVehicle sysTaskVehicle);
+
+ /**
+ * 鏍规嵁浠诲姟ID鏌ヨ鍏宠仈杞﹁締鍒楄〃
+ *
+ * @param taskId 浠诲姟ID
+ * @return 浠诲姟杞﹁締鍏宠仈闆嗗悎
+ */
+ public List<SysTaskVehicle> selectSysTaskVehicleByTaskId(Long taskId);
+
+ /**
+ * 鏂板浠诲姟杞﹁締鍏宠仈
+ *
+ * @param sysTaskVehicle 浠诲姟杞﹁締鍏宠仈
+ * @return 缁撴灉
+ */
+ public int insertSysTaskVehicle(SysTaskVehicle sysTaskVehicle);
+
+ /**
+ * 淇敼浠诲姟杞﹁締鍏宠仈
+ *
+ * @param sysTaskVehicle 浠诲姟杞﹁締鍏宠仈
+ * @return 缁撴灉
+ */
+ public int updateSysTaskVehicle(SysTaskVehicle sysTaskVehicle);
+
+ /**
+ * 鎵归噺鍒犻櫎浠诲姟杞﹁締鍏宠仈
+ *
+ * @param ids 闇�瑕佸垹闄ょ殑浠诲姟杞﹁締鍏宠仈涓婚敭闆嗗悎
+ * @return 缁撴灉
+ */
+ public int deleteSysTaskVehicleByIds(Long[] ids);
+
+ /**
+ * 鍒犻櫎浠诲姟杞﹁締鍏宠仈淇℃伅
+ *
+ * @param id 浠诲姟杞﹁締鍏宠仈涓婚敭
+ * @return 缁撴灉
+ */
+ public int deleteSysTaskVehicleById(Long id);
+
+ /**
+ * 鏍规嵁浠诲姟ID鍒犻櫎杞﹁締鍏宠仈
+ *
+ * @param taskId 浠诲姟ID
+ * @return 缁撴灉
+ */
+ public int deleteSysTaskVehicleByTaskId(Long taskId);
+
+ /**
+ * 鏍规嵁浠诲姟ID鍜岃溅杈咺D鍒犻櫎鍏宠仈
+ *
+ * @param taskId 浠诲姟ID
+ * @param vehicleId 杞﹁締ID
+ * @return 缁撴灉
+ */
+ public int deleteSysTaskVehicleByTaskIdAndVehicleId(Long taskId, Long vehicleId);
+
+ /**
+ * 妫�鏌ヤ换鍔¤溅杈嗗叧鑱旀槸鍚﹀瓨鍦�
+ *
+ * @param taskId 浠诲姟ID
+ * @param vehicleId 杞﹁締ID
+ * @return 缁撴灉
+ */
+ public int checkTaskVehicleExists(Long taskId, Long vehicleId);
+
+ /**
+ * 鎵归噺鏂板浠诲姟杞﹁締鍏宠仈
+ *
+ * @param sysTaskVehicleList 浠诲姟杞﹁締鍏宠仈鍒楄〃
+ * @return 缁撴灉
+ */
+ public int batchInsertSysTaskVehicle(List<SysTaskVehicle> sysTaskVehicleList);
+
+ /**
+ * 鍒嗛厤杞﹁締缁欎换鍔�
+ *
+ * @param taskId 浠诲姟ID
+ * @param vehicleId 杞﹁締ID
+ * @param remark 澶囨敞
+ * @return 缁撴灉
+ */
+ public int assignVehicleToTask(Long taskId, Long vehicleId, String remark);
+
+ /**
+ * 鍙栨秷浠诲姟杞﹁締鍒嗛厤
+ *
+ * @param taskId 浠诲姟ID
+ * @param vehicleId 杞﹁締ID
+ * @return 缁撴灉
+ */
+ public int unassignVehicleFromTask(Long taskId, Long vehicleId);
+
+ /**
+ * 鎵归噺鍒嗛厤杞﹁締缁欎换鍔�
+ *
+ * @param taskId 浠诲姟ID
+ * @param vehicleIds 杞﹁締ID鍒楄〃
+ * @param remark 澶囨敞
+ * @return 缁撴灉
+ */
+ public int assignMultipleVehiclesToTask(Long taskId, List<Long> vehicleIds, String remark);
+
+ /**
+ * 鏌ヨ鍙敤杞﹁締
+ *
+ * @param deptId 閮ㄩ棬ID
+ * @param taskType 浠诲姟绫诲瀷
+ * @return 鍙敤杞﹁締鍒楄〃
+ */
+ public List<SysTaskVehicle> getAvailableVehicles(Long deptId, String taskType);
+
+ /**
+ * 鏇存柊浠诲姟杞﹁締鍏宠仈鐘舵��
+ *
+ * @param id 鍏宠仈ID
+ * @param status 鏂扮姸鎬�
+ * @return 缁撴灉
+ */
+ public int updateTaskVehicleStatus(Long id, String status);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java
index 093a6a4..386cf99 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java
@@ -5,6 +5,8 @@
import java.util.ArrayList;
import java.io.File;
import java.io.IOException;
+
+import com.ruoyi.system.utils.TaskCodeGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -12,6 +14,7 @@
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.GpsDistanceUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.system.domain.SysTask;
@@ -27,6 +30,8 @@
import com.ruoyi.system.mapper.SysTaskVehicleMapper;
import com.ruoyi.system.mapper.SysTaskAttachmentMapper;
import com.ruoyi.system.mapper.SysTaskLogMapper;
+import com.ruoyi.system.mapper.VehicleInfoMapper;
+import com.ruoyi.system.domain.VehicleInfo;
import com.ruoyi.system.service.ISysTaskService;
/**
@@ -49,6 +54,9 @@
@Autowired
private SysTaskLogMapper sysTaskLogMapper;
+
+ @Autowired
+ private VehicleInfoMapper vehicleInfoMapper;
/**
* 鏌ヨ浠诲姟绠$悊
@@ -88,6 +96,10 @@
task.setTaskDescription(createVO.getTaskDescription());
task.setDepartureAddress(createVO.getDepartureAddress());
task.setDestinationAddress(createVO.getDestinationAddress());
+ task.setDepartureLongitude(createVO.getDepartureLongitude());
+ task.setDepartureLatitude(createVO.getDepartureLatitude());
+ task.setDestinationLongitude(createVO.getDestinationLongitude());
+ task.setDestinationLatitude(createVO.getDestinationLatitude());
task.setPlannedStartTime(createVO.getPlannedStartTime());
task.setPlannedEndTime(createVO.getPlannedEndTime());
task.setAssigneeId(createVO.getAssigneeId());
@@ -95,10 +107,33 @@
task.setDeptId(SecurityUtils.getDeptId());
task.setCreateBy(SecurityUtils.getUsername());
task.setCreateTime(DateUtils.getNowDate());
+ task.setUpdateBy(SecurityUtils.getUsername());
+ task.setUpdateTime(DateUtils.getNowDate());
task.setRemark(createVO.getRemark());
task.setDelFlag("0");
+ // 璁$畻棰勮鍏噷鏁�
+ calculateEstimatedDistance(task);
+
int result = sysTaskMapper.insertSysTask(task);
+
+ // 淇濆瓨杞﹁締鍏宠仈淇℃伅
+ if (result > 0 && createVO.getVehicleIds() != null && !createVO.getVehicleIds().isEmpty()) {
+ for (Long vehicleId : createVO.getVehicleIds()) {
+ SysTaskVehicle taskVehicle = new SysTaskVehicle();
+ taskVehicle.setTaskId(task.getTaskId());
+ taskVehicle.setVehicleId(vehicleId);
+ taskVehicle.setAssignTime(DateUtils.getNowDate());
+ taskVehicle.setAssignBy(SecurityUtils.getUsername());
+ taskVehicle.setStatus("ASSIGNED");
+ taskVehicle.setCreateBy(SecurityUtils.getUsername());
+ taskVehicle.setCreateTime(DateUtils.getNowDate());
+ taskVehicle.setUpdateBy(SecurityUtils.getUsername());
+ taskVehicle.setUpdateTime(DateUtils.getNowDate());
+
+ sysTaskVehicleMapper.insertSysTaskVehicle(taskVehicle);
+ }
+ }
// 璁板綍鎿嶄綔鏃ュ織
if (result > 0) {
@@ -128,12 +163,19 @@
task.setTaskDescription(updateVO.getTaskDescription());
task.setDepartureAddress(updateVO.getDepartureAddress());
task.setDestinationAddress(updateVO.getDestinationAddress());
+ task.setDepartureLongitude(updateVO.getDepartureLongitude());
+ task.setDepartureLatitude(updateVO.getDepartureLatitude());
+ task.setDestinationLongitude(updateVO.getDestinationLongitude());
+ task.setDestinationLatitude(updateVO.getDestinationLatitude());
task.setPlannedStartTime(updateVO.getPlannedStartTime());
task.setPlannedEndTime(updateVO.getPlannedEndTime());
task.setAssigneeId(updateVO.getAssigneeId());
task.setUpdateBy(SecurityUtils.getUsername());
task.setUpdateTime(DateUtils.getNowDate());
task.setRemark(updateVO.getRemark());
+
+ // 閲嶆柊璁$畻棰勮鍏噷鏁�
+ calculateEstimatedDistance(task);
int result = sysTaskMapper.updateSysTask(task);
@@ -181,6 +223,7 @@
task.setTaskId(taskId);
task.setAssigneeId(assigneeId);
task.setUpdateBy(SecurityUtils.getUsername());
+ task.setUpdateTime(DateUtils.getNowDate());
int result = sysTaskMapper.assignTask(task);
@@ -220,6 +263,7 @@
task.setTaskId(taskId);
task.setTaskStatus(newStatus.getCode());
task.setUpdateBy(SecurityUtils.getUsername());
+ task.setUpdateTime(DateUtils.getNowDate());
// 鏍规嵁鐘舵�佽缃浉搴旂殑鏃堕棿
if (newStatus == TaskStatus.IN_PROGRESS && oldTask.getActualStartTime() == null) {
@@ -437,9 +481,33 @@
*/
@Override
public List<SysTaskVehicle> getAvailableVehicles(Long deptId, String taskType) {
- // 杩欓噷闇�瑕佹牴鎹笟鍔¢�昏緫鏌ヨ鍙敤杞﹁締
- // 鏆傛椂杩斿洖绌哄垪琛紝瀹為檯瀹炵幇闇�瑕佹煡璇㈣溅杈嗚〃
- return new ArrayList<>();
+ List<SysTaskVehicle> availableVehicles = new ArrayList<>();
+
+ try {
+ // 鏌ヨ鎵�鏈夌姸鎬佷负姝e父鐨勮溅杈嗭紙涓嶉檺鍒堕儴闂級
+ VehicleInfo queryParam = new VehicleInfo();
+ queryParam.setStatus("0"); // 0琛ㄧず姝e父鐘舵��
+ // 涓嶈缃甦eptId锛屾煡璇㈡墍鏈夐儴闂ㄧ殑杞﹁締
+
+ List<VehicleInfo> vehicles = vehicleInfoMapper.selectVehicleInfoList(queryParam);
+
+ // 杞崲涓篠ysTaskVehicle瀵硅薄
+ for (VehicleInfo vehicle : vehicles) {
+ SysTaskVehicle taskVehicle = new SysTaskVehicle();
+ taskVehicle.setVehicleId(vehicle.getVehicleId());
+ taskVehicle.setVehicleNo(vehicle.getVehicleNo());
+ taskVehicle.setVehicleType(vehicle.getVehicleType());
+ taskVehicle.setVehicleBrand(vehicle.getVehicleBrand());
+ taskVehicle.setVehicleModel(vehicle.getVehicleModel());
+ taskVehicle.setDeptName(vehicle.getDeptName()); // 娣诲姞閮ㄩ棬鍚嶇О
+ availableVehicles.add(taskVehicle);
+ }
+ } catch (Exception e) {
+ // 濡傛灉鏌ヨ澶辫触锛岃褰曟棩蹇楀苟杩斿洖绌哄垪琛�
+ System.err.println("鏌ヨ鍙敤杞﹁締澶辫触: " + e.getMessage());
+ }
+
+ return availableVehicles;
}
/**
@@ -493,14 +561,16 @@
return task;
}
+ @Autowired
+ private TaskCodeGenerator taskCodeGenerator;
+
/**
* 鐢熸垚浠诲姟缂栧彿
*
* @return 浠诲姟缂栧彿
*/
private String generateTaskCode() {
- String dateStr = DateUtils.dateTimeNow("yyyyMMdd");
- return "TASK" + dateStr + "0001";
+ return taskCodeGenerator.generateTaskCode();
}
/**
@@ -564,4 +634,34 @@
}
return "";
}
+
+ /**
+ * 璁$畻棰勮鍏噷鏁�
+ *
+ * @param task 浠诲姟瀵硅薄
+ */
+ private void calculateEstimatedDistance(SysTask task) {
+ if (task.getDepartureLongitude() != null && task.getDepartureLatitude() != null &&
+ task.getDestinationLongitude() != null && task.getDestinationLatitude() != null) {
+
+ // 楠岃瘉GPS鍧愭爣鏄惁鏈夋晥
+ if (GpsDistanceUtils.isValidCoordinate(task.getDepartureLatitude(), task.getDepartureLongitude()) &&
+ GpsDistanceUtils.isValidCoordinate(task.getDestinationLatitude(), task.getDestinationLongitude())) {
+
+ // 璁$畻璺濈
+ java.math.BigDecimal distance = GpsDistanceUtils.calculateDistance(
+ task.getDepartureLatitude(), task.getDepartureLongitude(),
+ task.getDestinationLatitude(), task.getDestinationLongitude()
+ );
+
+ task.setEstimatedDistance(distance);
+ } else {
+ // 鍧愭爣鏃犳晥锛岃缃负0
+ task.setEstimatedDistance(java.math.BigDecimal.ZERO);
+ }
+ } else {
+ // 鍧愭爣涓嶅畬鏁达紝璁剧疆涓�0
+ task.setEstimatedDistance(java.math.BigDecimal.ZERO);
+ }
+ }
}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskVehicleServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskVehicleServiceImpl.java
new file mode 100644
index 0000000..b8e1c76
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskVehicleServiceImpl.java
@@ -0,0 +1,301 @@
+package com.ruoyi.system.service.impl;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.system.mapper.SysTaskVehicleMapper;
+import com.ruoyi.system.domain.SysTaskVehicle;
+import com.ruoyi.system.service.ISysTaskVehicleService;
+
+/**
+ * 浠诲姟杞﹁締鍏宠仈Service涓氬姟灞傚鐞�
+ *
+ * @author ruoyi
+ * @date 2024-01-15
+ */
+@Service
+public class SysTaskVehicleServiceImpl implements ISysTaskVehicleService {
+
+ @Autowired
+ private SysTaskVehicleMapper sysTaskVehicleMapper;
+
+ /**
+ * 鏌ヨ浠诲姟杞﹁締鍏宠仈
+ *
+ * @param id 浠诲姟杞﹁締鍏宠仈涓婚敭
+ * @return 浠诲姟杞﹁締鍏宠仈
+ */
+ @Override
+ public SysTaskVehicle selectSysTaskVehicleById(Long id) {
+ return sysTaskVehicleMapper.selectSysTaskVehicleById(id);
+ }
+
+ /**
+ * 鏌ヨ浠诲姟杞﹁締鍏宠仈鍒楄〃
+ *
+ * @param sysTaskVehicle 浠诲姟杞﹁締鍏宠仈
+ * @return 浠诲姟杞﹁締鍏宠仈
+ */
+ @Override
+ public List<SysTaskVehicle> selectSysTaskVehicleList(SysTaskVehicle sysTaskVehicle) {
+ return sysTaskVehicleMapper.selectSysTaskVehicleList(sysTaskVehicle);
+ }
+
+ /**
+ * 鏍规嵁浠诲姟ID鏌ヨ鍏宠仈杞﹁締鍒楄〃
+ *
+ * @param taskId 浠诲姟ID
+ * @return 浠诲姟杞﹁締鍏宠仈闆嗗悎
+ */
+ @Override
+ public List<SysTaskVehicle> selectSysTaskVehicleByTaskId(Long taskId) {
+ return sysTaskVehicleMapper.selectSysTaskVehicleByTaskId(taskId);
+ }
+
+ /**
+ * 鏂板浠诲姟杞﹁締鍏宠仈
+ *
+ * @param sysTaskVehicle 浠诲姟杞﹁締鍏宠仈
+ * @return 缁撴灉
+ */
+ @Override
+ @Transactional
+ public int insertSysTaskVehicle(SysTaskVehicle sysTaskVehicle) {
+ // 璁剧疆鍒嗛厤鏃堕棿鍜屽垎閰嶄汉
+ if (sysTaskVehicle.getAssignTime() == null) {
+ sysTaskVehicle.setAssignTime(DateUtils.getNowDate());
+ }
+ if (sysTaskVehicle.getAssignBy() == null || sysTaskVehicle.getAssignBy().isEmpty()) {
+ sysTaskVehicle.setAssignBy(SecurityUtils.getUsername());
+ }
+ // 璁剧疆榛樿鐘舵��
+ if (sysTaskVehicle.getStatus() == null || sysTaskVehicle.getStatus().isEmpty()) {
+ sysTaskVehicle.setStatus("ASSIGNED");
+ }
+ sysTaskVehicle.setCreateTime(DateUtils.getNowDate());
+ return sysTaskVehicleMapper.insertSysTaskVehicle(sysTaskVehicle);
+ }
+
+ /**
+ * 淇敼浠诲姟杞﹁締鍏宠仈
+ *
+ * @param sysTaskVehicle 浠诲姟杞﹁締鍏宠仈
+ * @return 缁撴灉
+ */
+ @Override
+ @Transactional
+ public int updateSysTaskVehicle(SysTaskVehicle sysTaskVehicle) {
+ sysTaskVehicle.setUpdateTime(DateUtils.getNowDate());
+ return sysTaskVehicleMapper.updateSysTaskVehicle(sysTaskVehicle);
+ }
+
+ /**
+ * 鎵归噺鍒犻櫎浠诲姟杞﹁締鍏宠仈
+ *
+ * @param ids 闇�瑕佸垹闄ょ殑浠诲姟杞﹁締鍏宠仈涓婚敭
+ * @return 缁撴灉
+ */
+ @Override
+ @Transactional
+ public int deleteSysTaskVehicleByIds(Long[] ids) {
+ return sysTaskVehicleMapper.deleteSysTaskVehicleByIds(ids);
+ }
+
+ /**
+ * 鍒犻櫎浠诲姟杞﹁締鍏宠仈淇℃伅
+ *
+ * @param id 浠诲姟杞﹁締鍏宠仈涓婚敭
+ * @return 缁撴灉
+ */
+ @Override
+ @Transactional
+ public int deleteSysTaskVehicleById(Long id) {
+ return sysTaskVehicleMapper.deleteSysTaskVehicleById(id);
+ }
+
+ /**
+ * 鏍规嵁浠诲姟ID鍒犻櫎杞﹁締鍏宠仈
+ *
+ * @param taskId 浠诲姟ID
+ * @return 缁撴灉
+ */
+ @Override
+ @Transactional
+ public int deleteSysTaskVehicleByTaskId(Long taskId) {
+ return sysTaskVehicleMapper.deleteSysTaskVehicleByTaskId(taskId);
+ }
+
+ /**
+ * 鏍规嵁浠诲姟ID鍜岃溅杈咺D鍒犻櫎鍏宠仈
+ *
+ * @param taskId 浠诲姟ID
+ * @param vehicleId 杞﹁締ID
+ * @return 缁撴灉
+ */
+ @Override
+ @Transactional
+ public int deleteSysTaskVehicleByTaskIdAndVehicleId(Long taskId, Long vehicleId) {
+ return sysTaskVehicleMapper.deleteSysTaskVehicleByTaskIdAndVehicleId(taskId, vehicleId);
+ }
+
+ /**
+ * 妫�鏌ヤ换鍔¤溅杈嗗叧鑱旀槸鍚﹀瓨鍦�
+ *
+ * @param taskId 浠诲姟ID
+ * @param vehicleId 杞﹁締ID
+ * @return 缁撴灉
+ */
+ @Override
+ public int checkTaskVehicleExists(Long taskId, Long vehicleId) {
+ return sysTaskVehicleMapper.checkTaskVehicleExists(taskId, vehicleId);
+ }
+
+ /**
+ * 鎵归噺鏂板浠诲姟杞﹁締鍏宠仈
+ *
+ * @param sysTaskVehicleList 浠诲姟杞﹁締鍏宠仈鍒楄〃
+ * @return 缁撴灉
+ */
+ @Override
+ @Transactional
+ public int batchInsertSysTaskVehicle(List<SysTaskVehicle> sysTaskVehicleList) {
+ return sysTaskVehicleMapper.batchInsertSysTaskVehicle(sysTaskVehicleList);
+ }
+
+ /**
+ * 鍒嗛厤杞﹁締缁欎换鍔�
+ *
+ * @param taskId 浠诲姟ID
+ * @param vehicleId 杞﹁締ID
+ * @param remark 澶囨敞
+ * @return 缁撴灉
+ */
+ @Override
+ @Transactional
+ public int assignVehicleToTask(Long taskId, Long vehicleId, String remark) {
+ // 妫�鏌ユ槸鍚﹀凡缁忓垎閰�
+ int exists = sysTaskVehicleMapper.checkTaskVehicleExists(taskId, vehicleId);
+ if (exists > 0) {
+ throw new RuntimeException("杞﹁締宸茬粡鍒嗛厤缁欒浠诲姟");
+ }
+
+ SysTaskVehicle taskVehicle = new SysTaskVehicle();
+ taskVehicle.setTaskId(taskId);
+ taskVehicle.setVehicleId(vehicleId);
+ taskVehicle.setAssignTime(DateUtils.getNowDate());
+ taskVehicle.setAssignBy(SecurityUtils.getUsername());
+ taskVehicle.setStatus("ASSIGNED");
+ taskVehicle.setRemark(remark);
+
+ return sysTaskVehicleMapper.insertSysTaskVehicle(taskVehicle);
+ }
+
+ /**
+ * 鍙栨秷浠诲姟杞﹁締鍒嗛厤
+ *
+ * @param taskId 浠诲姟ID
+ * @param vehicleId 杞﹁締ID
+ * @return 缁撴灉
+ */
+ @Override
+ @Transactional
+ public int unassignVehicleFromTask(Long taskId, Long vehicleId) {
+ return sysTaskVehicleMapper.deleteSysTaskVehicleByTaskIdAndVehicleId(taskId, vehicleId);
+ }
+
+ /**
+ * 鎵归噺鍒嗛厤杞﹁締缁欎换鍔�
+ *
+ * @param taskId 浠诲姟ID
+ * @param vehicleIds 杞﹁締ID鍒楄〃
+ * @param remark 澶囨敞
+ * @return 缁撴灉
+ */
+ @Override
+ @Transactional
+ public int assignMultipleVehiclesToTask(Long taskId, List<Long> vehicleIds, String remark) {
+ List<SysTaskVehicle> taskVehicles = new ArrayList<>();
+ Date now = DateUtils.getNowDate();
+ String assignBy = SecurityUtils.getUsername();
+
+ for (Long vehicleId : vehicleIds) {
+ // 妫�鏌ユ槸鍚﹀凡缁忓垎閰�
+ int exists = sysTaskVehicleMapper.checkTaskVehicleExists(taskId, vehicleId);
+ if (exists == 0) {
+ SysTaskVehicle taskVehicle = new SysTaskVehicle();
+ taskVehicle.setTaskId(taskId);
+ taskVehicle.setVehicleId(vehicleId);
+ taskVehicle.setAssignTime(now);
+ taskVehicle.setAssignBy(assignBy);
+ taskVehicle.setStatus("ASSIGNED");
+ taskVehicle.setRemark(remark);
+ taskVehicles.add(taskVehicle);
+ }
+ }
+
+ if (!taskVehicles.isEmpty()) {
+ return sysTaskVehicleMapper.batchInsertSysTaskVehicle(taskVehicles);
+ }
+
+ return 0;
+ }
+
+ /**
+ * 鏌ヨ鍙敤杞﹁締
+ *
+ * @param deptId 閮ㄩ棬ID
+ * @param taskType 浠诲姟绫诲瀷
+ * @return 鍙敤杞﹁締鍒楄〃
+ */
+ @Override
+ public List<SysTaskVehicle> getAvailableVehicles(Long deptId, String taskType) {
+ // 鏌ヨ鎸囧畾閮ㄩ棬涓嬬姸鎬佷负姝e父鐨勮溅杈�
+ // 杩欓噷闇�瑕佹牴鎹疄闄呯殑杞﹁締淇℃伅琛ㄧ粨鏋勬潵瀹炵幇
+ // 鏆傛椂杩斿洖绌哄垪琛紝瀹為檯瀹炵幇闇�瑕侊細
+ // 1. 鏌ヨ tb_vehicle_info 琛ㄤ腑 dept_id = deptId 涓� vehicle_status = '0' 鐨勮溅杈�
+ // 2. 鎺掗櫎宸茬粡鍒嗛厤缁欏叾浠栨湭瀹屾垚浠诲姟涓旂姸鎬佷负 ACTIVE 鐨勮溅杈�
+ // 3. 鏍规嵁浠诲姟绫诲瀷绛涢�夊悎閫傜殑杞﹁締绫诲瀷
+
+ List<SysTaskVehicle> availableVehicles = new ArrayList<>();
+
+ // TODO: 瀹炵幇鍏蜂綋鐨勬煡璇㈤�昏緫
+ // 绀轰緥浠g爜锛�
+ // 1. 鏌ヨ杞﹁締淇℃伅
+ // List<TbVehicleInfo> vehicles = vehicleInfoMapper.selectAvailableVehiclesByDept(deptId, taskType);
+ //
+ // 2. 杞崲涓� SysTaskVehicle 瀵硅薄
+ // for (TbVehicleInfo vehicle : vehicles) {
+ // SysTaskVehicle taskVehicle = new SysTaskVehicle();
+ // taskVehicle.setVehicleId(vehicle.getVehicleId());
+ // taskVehicle.setVehicleNo(vehicle.getVehicleNo());
+ // taskVehicle.setVehicleType(vehicle.getVehicleType());
+ // taskVehicle.setVehicleBrand(vehicle.getVehicleBrand());
+ // taskVehicle.setVehicleModel(vehicle.getVehicleModel());
+ // availableVehicles.add(taskVehicle);
+ // }
+
+ return availableVehicles;
+ }
+
+ /**
+ * 鏇存柊浠诲姟杞﹁締鍏宠仈鐘舵��
+ *
+ * @param id 鍏宠仈ID
+ * @param status 鏂扮姸鎬�
+ * @return 缁撴灉
+ */
+ @Override
+ @Transactional
+ public int updateTaskVehicleStatus(Long id, String status) {
+ SysTaskVehicle taskVehicle = new SysTaskVehicle();
+ taskVehicle.setId(id);
+ taskVehicle.setStatus(status);
+ taskVehicle.setUpdateTime(DateUtils.getNowDate());
+ return sysTaskVehicleMapper.updateSysTaskVehicle(taskVehicle);
+ }
+}
diff --git "a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/\344\273\273\345\212\241\350\275\246\350\276\206\345\205\263\350\201\224\346\217\222\345\205\245\351\227\256\351\242\230\344\277\256\345\244\215\350\257\264\346\230\216.md" "b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/\344\273\273\345\212\241\350\275\246\350\276\206\345\205\263\350\201\224\346\217\222\345\205\245\351\227\256\351\242\230\344\277\256\345\244\215\350\257\264\346\230\216.md"
new file mode 100644
index 0000000..81bcaed
--- /dev/null
+++ "b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/\344\273\273\345\212\241\350\275\246\350\276\206\345\205\263\350\201\224\346\217\222\345\205\245\351\227\256\351\242\230\344\277\256\345\244\215\350\257\264\346\230\216.md"
@@ -0,0 +1,190 @@
+# 浠诲姟杞﹁締鍏宠仈鎻掑叆闂淇璇存槑
+
+## 闂鎻忚堪
+
+鍦ㄦ柊澧炰换鍔¤溅杈嗗叧鑱旀椂鍑虹幇浠ヤ笅閿欒锛�
+```
+### Error updating database. Cause: java.sql.SQLException: Field 'assign_time' doesn't have a default value ###
+### The error may exist in file [SysTaskVehicleMapper.xml] ###
+### The error may involve com.ruoyi.system.mapper.SysTaskVehicleMapper.insertSysTaskVehicle-Inline ###
+### The error occurred while setting parameters ###
+### SQL: insert into sys_task_vehicle ( task_id, vehicle_id, status ) values ( ?, ?, ? ) ###
+```
+
+## 闂鍘熷洜
+
+1. **鏁版嵁搴撹〃缁撴瀯绾︽潫**锛歚sys_task_vehicle` 琛ㄤ腑鐨� `assign_time` 鍜� `assign_by` 瀛楁瀹氫箟涓� `NOT NULL`
+2. **Service灞傜己澶�**锛歚insertSysTaskVehicle` 鏂规硶娌℃湁璁剧疆杩欎簺蹇呴渶瀛楁鐨勫��
+3. **Mapper灞傛潯浠跺垽鏂�**锛歑ML涓殑鎻掑叆璇彞鍙湁鍦ㄥ瓧娈典笉涓簄ull鏃舵墠鍖呭惈杩欎簺瀛楁
+
+## 淇鏂规
+
+### 1. Service灞備慨澶�
+
+**鏂囦欢**锛歚SysTaskVehicleServiceImpl.java`
+
+**淇鍐呭**锛�
+```java
+@Override
+@Transactional
+public int insertSysTaskVehicle(SysTaskVehicle sysTaskVehicle) {
+ // 璁剧疆鍒嗛厤鏃堕棿鍜屽垎閰嶄汉
+ if (sysTaskVehicle.getAssignTime() == null) {
+ sysTaskVehicle.setAssignTime(DateUtils.getNowDate());
+ }
+ if (sysTaskVehicle.getAssignBy() == null || sysTaskVehicle.getAssignBy().isEmpty()) {
+ sysTaskVehicle.setAssignBy(SecurityUtils.getUsername());
+ }
+ // 璁剧疆榛樿鐘舵��
+ if (sysTaskVehicle.getStatus() == null || sysTaskVehicle.getStatus().isEmpty()) {
+ sysTaskVehicle.setStatus("ASSIGNED");
+ }
+ sysTaskVehicle.setCreateTime(DateUtils.getNowDate());
+ return sysTaskVehicleMapper.insertSysTaskVehicle(sysTaskVehicle);
+}
+```
+
+**淇璇存槑**锛�
+- 鑷姩璁剧疆 `assignTime` 涓哄綋鍓嶆椂闂�
+- 鑷姩璁剧疆 `assignBy` 涓哄綋鍓嶇櫥褰曠敤鎴�
+- 鑷姩璁剧疆 `status` 涓� 'ASSIGNED'锛堝鏋滄湭璁剧疆锛�
+- 纭繚鎵�鏈夊繀闇�瀛楁閮芥湁鍊�
+
+### 2. Mapper灞備慨澶�
+
+**鏂囦欢**锛歚SysTaskVehicleMapper.xml`
+
+**淇鍓�**锛�
+```xml
+<insert id="insertSysTaskVehicle" parameterType="SysTaskVehicle" useGeneratedKeys="true" keyProperty="id">
+ insert into sys_task_vehicle
+ <trim prefix="(" suffix=")" suffixOverrides=",">
+ <if test="taskId != null">task_id,</if>
+ <if test="vehicleId != null">vehicle_id,</if>
+ <if test="assignTime != null">assign_time,</if>
+ <if test="assignBy != null and assignBy != ''">assign_by,</if>
+ <if test="status != null and status != ''">status,</if>
+ <if test="remark != null">remark,</if>
+ </trim>
+ <trim prefix="values (" suffix=")" suffixOverrides=",">
+ <if test="taskId != null">#{taskId},</if>
+ <if test="vehicleId != null">#{vehicleId},</if>
+ <if test="assignTime != null">#{assignTime},</if>
+ <if test="assignBy != null and assignBy != ''">#{assignBy},</if>
+ <if test="status != null and status != ''">#{status},</if>
+ <if test="remark != null">#{remark},</if>
+ </trim>
+</insert>
+```
+
+**淇鍚�**锛�
+```xml
+<insert id="insertSysTaskVehicle" parameterType="SysTaskVehicle" useGeneratedKeys="true" keyProperty="id">
+ insert into sys_task_vehicle
+ <trim prefix="(" suffix=")" suffixOverrides=",">
+ <if test="taskId != null">task_id,</if>
+ <if test="vehicleId != null">vehicle_id,</if>
+ assign_time,
+ assign_by,
+ <if test="status != null and status != ''">status,</if>
+ <if test="remark != null">remark,</if>
+ </trim>
+ <trim prefix="values (" suffix=")" suffixOverrides=",">
+ <if test="taskId != null">#{taskId},</if>
+ <if test="vehicleId != null">#{vehicleId},</if>
+ #{assignTime},
+ #{assignBy},
+ <if test="status != null and status != ''">#{status},</if>
+ <if test="remark != null">#{remark},</if>
+ </trim>
+</insert>
+```
+
+**淇璇存槑**锛�
+- `assign_time` 鍜� `assign_by` 瀛楁鎬绘槸琚寘鍚湪鎻掑叆璇彞涓�
+- 涓嶅啀浣跨敤鏉′欢鍒ゆ柇锛屽洜涓鸿繖浜涘瓧娈垫槸蹇呴渶鐨�
+- 纭繚鏁版嵁搴撶害鏉熷緱鍒版弧瓒�
+
+## 鏁版嵁搴撹〃缁撴瀯
+
+```sql
+CREATE TABLE sys_task_vehicle (
+ id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '鍏宠仈ID',
+ task_id BIGINT NOT NULL COMMENT '浠诲姟ID',
+ vehicle_id BIGINT NOT NULL COMMENT '杞﹁締ID',
+ assign_time DATETIME NOT NULL COMMENT '鍒嗛厤鏃堕棿', -- NOT NULL 绾︽潫
+ assign_by VARCHAR(64) NOT NULL COMMENT '鍒嗛厤浜�', -- NOT NULL 绾︽潫
+ status VARCHAR(20) DEFAULT 'ASSIGNED' COMMENT '鍏宠仈鐘舵��',
+ remark VARCHAR(500) COMMENT '澶囨敞',
+
+ UNIQUE KEY uk_task_vehicle (task_id, vehicle_id),
+ FOREIGN KEY (task_id) REFERENCES sys_task(task_id) ON DELETE CASCADE,
+ FOREIGN KEY (vehicle_id) REFERENCES tb_vehicle_info(vehicle_id) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='浠诲姟杞﹁締鍏宠仈琛�';
+```
+
+## 淇鏁堟灉
+
+### 淇鍓�
+- 鉂� 鎻掑叆鏃剁己灏戝繀闇�瀛楁鍊�
+- 鉂� 鏁版嵁搴撶害鏉熻繚鍙�
+- 鉂� 鍑虹幇 "Field doesn't have a default value" 閿欒
+
+### 淇鍚�
+- 鉁� 鑷姩璁剧疆鎵�鏈夊繀闇�瀛楁
+- 鉁� 婊¤冻鏁版嵁搴撶害鏉�
+- 鉁� 鎻掑叆鎿嶄綔鎴愬姛
+- 鉁� 鏁版嵁瀹屾暣鎬у緱鍒颁繚璇�
+
+## 娴嬭瘯楠岃瘉
+
+### 1. 鍗曞厓娴嬭瘯
+```java
+@Test
+public void testInsertSysTaskVehicle() {
+ SysTaskVehicle taskVehicle = new SysTaskVehicle();
+ taskVehicle.setTaskId(1L);
+ taskVehicle.setVehicleId(1L);
+ // 涓嶈缃� assignTime, assignBy, status
+
+ int result = sysTaskVehicleService.insertSysTaskVehicle(taskVehicle);
+
+ assertThat(result).isEqualTo(1);
+ // 楠岃瘉鑷姩璁剧疆鐨勫瓧娈�
+ assertThat(taskVehicle.getAssignTime()).isNotNull();
+ assertThat(taskVehicle.getAssignBy()).isEqualTo("admin");
+ assertThat(taskVehicle.getStatus()).isEqualTo("ASSIGNED");
+}
+```
+
+### 2. 闆嗘垚娴嬭瘯
+```sql
+-- 娴嬭瘯鎻掑叆
+INSERT INTO sys_task_vehicle (task_id, vehicle_id, assign_time, assign_by, status)
+VALUES (1, 1, NOW(), 'admin', 'ASSIGNED');
+
+-- 楠岃瘉缁撴灉
+SELECT * FROM sys_task_vehicle WHERE task_id = 1 AND vehicle_id = 1;
+```
+
+## 娉ㄦ剰浜嬮」
+
+1. **鏁版嵁涓�鑷存��**锛氱‘淇� `assign_time` 鍜� `assign_by` 瀛楁濮嬬粓鏈夊��
+2. **鐢ㄦ埛涓婁笅鏂�**锛歚assign_by` 瀛楁渚濊禆褰撳墠鐧诲綍鐢ㄦ埛锛岄渶瑕佺‘淇濈敤鎴峰凡鐧诲綍
+3. **鏃堕棿鍚屾**锛歚assign_time` 浣跨敤鏈嶅姟鍣ㄦ椂闂达紝纭繚鏃堕棿鍚屾
+4. **鐘舵�佺鐞�**锛氶粯璁ょ姸鎬佷负 'ASSIGNED'锛屽彲鏍规嵁涓氬姟闇�姹傝皟鏁�
+
+## 鐩稿叧鏂囦欢
+
+- `SysTaskVehicleServiceImpl.java` - Service灞傚疄鐜�
+- `SysTaskVehicleMapper.xml` - MyBatis鏄犲皠鏂囦欢
+- `sys_task_vehicle` - 鏁版嵁搴撹〃
+- `SysTaskVehicle.java` - 瀹炰綋绫�
+
+## 鍚庣画浼樺寲寤鸿
+
+1. **瀛楁楠岃瘉**锛氬湪瀹炰綋绫讳腑娣诲姞瀛楁楠岃瘉娉ㄨВ
+2. **寮傚父澶勭悊**锛氭坊鍔犳洿璇︾粏鐨勫紓甯稿鐞嗘満鍒�
+3. **鏃ュ織璁板綍**锛氳褰曞垎閰嶆搷浣滅殑璇︾粏鏃ュ織
+4. **鏉冮檺鎺у埗**锛氱‘淇濆彧鏈夋湁鏉冮檺鐨勭敤鎴锋墠鑳藉垎閰嶈溅杈�
+5. **鏁版嵁瀹¤**锛氳褰曟墍鏈夊垎閰嶆搷浣滅殑瀹¤淇℃伅
diff --git "a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/\345\205\201\350\256\270\346\220\234\347\264\242\346\211\200\346\234\211\350\275\246\350\276\206\344\277\256\346\224\271\350\257\264\346\230\216.md" "b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/\345\205\201\350\256\270\346\220\234\347\264\242\346\211\200\346\234\211\350\275\246\350\276\206\344\277\256\346\224\271\350\257\264\346\230\216.md"
new file mode 100644
index 0000000..0a6c221
--- /dev/null
+++ "b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/\345\205\201\350\256\270\346\220\234\347\264\242\346\211\200\346\234\211\350\275\246\350\276\206\344\277\256\346\224\271\350\257\264\346\230\216.md"
@@ -0,0 +1,242 @@
+# 鍏佽鎼滅储鎵�鏈夎溅杈嗕慨鏀硅鏄�
+
+## 淇敼鍐呭
+
+鏍规嵁鐢ㄦ埛闇�姹傦紝灏嗕换鍔¤溅杈嗗垎閰嶅姛鑳戒粠"鍙悳绱㈡寚瀹氶儴闂ㄧ殑杞﹁締"淇敼涓�"鍏佽鎼滅储鎵�鏈夎溅杈�"锛屼互鎻愪緵鏇村ぇ鐨勯�夋嫨鑼冨洿銆�
+
+## 淇敼璇︽儏
+
+### 1. 鍚庣Service灞備慨鏀�
+
+#### 鏂囦欢锛歚SysTaskServiceImpl.java`
+
+**淇敼鍓�**锛�
+```java
+@Override
+public List<SysTaskVehicle> getAvailableVehicles(Long deptId, String taskType) {
+ List<SysTaskVehicle> availableVehicles = new ArrayList<>();
+
+ try {
+ // 鏌ヨ鎸囧畾閮ㄩ棬涓嬬姸鎬佷负姝e父鐨勮溅杈�
+ VehicleInfo queryParam = new VehicleInfo();
+ queryParam.setDeptId(deptId); // 闄愬埗閮ㄩ棬
+ queryParam.setStatus("0"); // 0琛ㄧず姝e父鐘舵��
+
+ List<VehicleInfo> vehicles = vehicleInfoMapper.selectVehicleInfoList(queryParam);
+
+ // 杞崲涓篠ysTaskVehicle瀵硅薄
+ for (VehicleInfo vehicle : vehicles) {
+ SysTaskVehicle taskVehicle = new SysTaskVehicle();
+ taskVehicle.setVehicleId(vehicle.getVehicleId());
+ taskVehicle.setVehicleNo(vehicle.getVehicleNo());
+ taskVehicle.setVehicleType(vehicle.getVehicleType());
+ taskVehicle.setVehicleBrand(vehicle.getVehicleBrand());
+ taskVehicle.setVehicleModel(vehicle.getVehicleModel());
+ availableVehicles.add(taskVehicle);
+ }
+ } catch (Exception e) {
+ System.err.println("鏌ヨ鍙敤杞﹁締澶辫触: " + e.getMessage());
+ }
+
+ return availableVehicles;
+}
+```
+
+**淇敼鍚�**锛�
+```java
+@Override
+public List<SysTaskVehicle> getAvailableVehicles(Long deptId, String taskType) {
+ List<SysTaskVehicle> availableVehicles = new ArrayList<>();
+
+ try {
+ // 鏌ヨ鎵�鏈夌姸鎬佷负姝e父鐨勮溅杈嗭紙涓嶉檺鍒堕儴闂級
+ VehicleInfo queryParam = new VehicleInfo();
+ queryParam.setStatus("0"); // 0琛ㄧず姝e父鐘舵��
+ // 涓嶈缃甦eptId锛屾煡璇㈡墍鏈夐儴闂ㄧ殑杞﹁締
+
+ List<VehicleInfo> vehicles = vehicleInfoMapper.selectVehicleInfoList(queryParam);
+
+ // 杞崲涓篠ysTaskVehicle瀵硅薄
+ for (VehicleInfo vehicle : vehicles) {
+ SysTaskVehicle taskVehicle = new SysTaskVehicle();
+ taskVehicle.setVehicleId(vehicle.getVehicleId());
+ taskVehicle.setVehicleNo(vehicle.getVehicleNo());
+ taskVehicle.setVehicleType(vehicle.getVehicleType());
+ taskVehicle.setVehicleBrand(vehicle.getVehicleBrand());
+ taskVehicle.setVehicleModel(vehicle.getVehicleModel());
+ taskVehicle.setDeptName(vehicle.getDeptName()); // 娣诲姞閮ㄩ棬鍚嶇О
+ availableVehicles.add(taskVehicle);
+ }
+ } catch (Exception e) {
+ System.err.println("鏌ヨ鍙敤杞﹁締澶辫触: " + e.getMessage());
+ }
+
+ return availableVehicles;
+}
+```
+
+**鍏抽敭鍙樺寲**锛�
+- 鉁� 绉婚櫎浜� `queryParam.setDeptId(deptId);` 闄愬埗
+- 鉁� 娣诲姞浜� `taskVehicle.setDeptName(vehicle.getDeptName());` 璁剧疆閮ㄩ棬鍚嶇О
+- 鉁� 娉ㄩ噴璇存槑鏌ヨ鎵�鏈夐儴闂ㄧ殑杞﹁締
+
+### 2. 瀹炰綋绫讳慨鏀�
+
+#### 鏂囦欢锛歚SysTaskVehicle.java`
+
+**娣诲姞瀛楁**锛�
+```java
+/** 褰掑睘閮ㄩ棬鍚嶇О */
+@Excel(name = "褰掑睘閮ㄩ棬")
+private String deptName;
+```
+
+**娣诲姞getter鍜宻etter鏂规硶**锛�
+```java
+public void setDeptName(String deptName) {
+ this.deptName = deptName;
+}
+
+public String getDeptName() {
+ return deptName;
+}
+```
+
+**鏇存柊toString鏂规硶**锛�
+```java
+@Override
+public String toString() {
+ return "SysTaskVehicle{" +
+ "id=" + id +
+ ", taskId=" + taskId +
+ ", vehicleId=" + vehicleId +
+ ", assignTime=" + assignTime +
+ ", assignBy='" + assignBy + '\'' +
+ ", status='" + status + '\'' +
+ ", vehicleNo='" + vehicleNo + '\'' +
+ ", vehicleType='" + vehicleType + '\'' +
+ ", vehicleBrand='" + vehicleBrand + '\'' +
+ ", vehicleModel='" + vehicleModel + '\'' +
+ ", deptName='" + deptName + '\'' + // 鏂板
+ '}';
+}
+```
+
+### 3. Mapper XML淇敼
+
+#### 鏂囦欢锛歚SysTaskVehicleMapper.xml`
+
+**鏇存柊resultMap**锛�
+```xml
+<resultMap type="SysTaskVehicle" id="SysTaskVehicleResult">
+ <result property="id" column="id" />
+ <result property="taskId" column="task_id" />
+ <result property="vehicleId" column="vehicle_id" />
+ <result property="assignTime" column="assign_time" />
+ <result property="assignBy" column="assign_by" />
+ <result property="status" column="status" />
+ <result property="remark" column="remark" />
+ <result property="vehicleNo" column="vehicle_no" />
+ <result property="vehicleType" column="vehicle_type" />
+ <result property="vehicleBrand" column="vehicle_brand" />
+ <result property="vehicleModel" column="vehicle_model" />
+ <result property="deptName" column="dept_name" /> <!-- 鏂板 -->
+</resultMap>
+```
+
+**鏇存柊鏌ヨSQL**锛�
+```xml
+<sql id="selectSysTaskVehicleVo">
+ select tv.id, tv.task_id, tv.vehicle_id, tv.assign_time, tv.assign_by, tv.status, tv.remark,
+ v.vehicle_no, v.vehicle_type, v.vehicle_brand, v.vehicle_model, d.dept_name <!-- 鏂板d.dept_name -->
+ from sys_task_vehicle tv
+ left join tb_vehicle_info v on tv.vehicle_id = v.vehicle_id
+ left join sys_dept d on v.dept_id = d.dept_id <!-- 鏂板閮ㄩ棬鍏宠仈 -->
+</sql>
+```
+
+## 鍔熻兘鍙樺寲
+
+### 淇敼鍓�
+- 鉂� 鍙兘閫夋嫨褰撳墠浠诲姟鎵�灞為儴闂ㄧ殑杞﹁締
+- 鉂� 閫夋嫨鑼冨洿鍙楅檺
+- 鉂� 璺ㄩ儴闂ㄨ溅杈嗘棤娉曞垎閰�
+
+### 淇敼鍚�
+- 鉁� 鍙互閫夋嫨鎵�鏈夐儴闂ㄧ殑杞﹁締
+- 鉁� 閫夋嫨鑼冨洿鎵╁ぇ
+- 鉁� 鏀寔璺ㄩ儴闂ㄨ溅杈嗗垎閰�
+- 鉁� 鏄剧ず杞﹁締鎵�灞為儴闂ㄤ俊鎭�
+
+## 鐣岄潰鏁堟灉
+
+### 鍓嶇鏄剧ず
+```
+杞﹁締: [绮12345 - 鎬ユ晳涓績 鈻糫
+鈹屸攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�
+鈹� 绮12345 - 鎬ユ晳涓績 鈹�
+鈹� 鈹屸攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹� 鈹屸攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹� 鈹�
+鈹� 鈹� 绮12345 鈹� 鈹� 鏁戞姢杞� 鈹� 鈹�
+鈹� 鈹� ID: 1 鈹� 鈹� 濂旈┌ S350 鈹� 鈹�
+鈹� 鈹斺攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹� 鈹斺攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹� 鈹�
+鈹� 绮67890 - 杞繍涓績 鈹�
+鈹� 鈹屸攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹� 鈹屸攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹� 鈹�
+鈹� 鈹� 绮67890 鈹� 鈹� 杞繍杞� 鈹� 鈹�
+鈹� 鈹� ID: 2 鈹� 鈹� 涓扮敯 娴风嫯 鈹� 鈹�
+鈹� 鈹斺攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹� 鈹斺攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹� 鈹�
+鈹� 绮99999 - 缁翠慨涓績 鈹�
+鈹� 鈹屸攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹� 鈹屸攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹� 鈹�
+鈹� 鈹� 绮99999 鈹� 鈹� 缁翠慨杞� 鈹� 鈹�
+鈹� 鈹� ID: 3 鈹� 鈹� 澶т紬 閫斿畨 鈹� 鈹�
+鈹� 鈹斺攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹� 鈹斺攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹� 鈹�
+鈹斺攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�
+```
+
+## 鏁版嵁娴佺▼
+
+```
+鍓嶇璋冪敤 getAvailableVehicles(deptId, taskType)
+ 鈫�
+鍚庣Controller: /task/vehicle/available
+ 鈫�
+Service灞�: SysTaskServiceImpl.getAvailableVehicles()
+ 鈫� (涓嶅啀闄愬埗閮ㄩ棬ID)
+Mapper灞�: VehicleInfoMapper.selectVehicleInfoList()
+ 鈫�
+鏁版嵁搴撴煡璇�: tb_vehicle_info琛� (鎵�鏈夐儴闂�)
+ 鈫�
+鏁版嵁杞崲: VehicleInfo 鈫� SysTaskVehicle (鍖呭惈閮ㄩ棬鍚嶇О)
+ 鈫�
+杩斿洖缁欏墠绔� (鏄剧ず鎵�鏈夐儴闂ㄧ殑杞﹁締)
+```
+
+## 娉ㄦ剰浜嬮」
+
+1. **鏉冮檺鎺у埗**锛氳櫧鐒跺彲浠ユ悳绱㈡墍鏈夎溅杈嗭紝浣嗗疄闄呭垎閰嶆椂浠嶉渶瑕佺浉搴旂殑鏉冮檺
+2. **閮ㄩ棬淇℃伅**锛氱幇鍦ㄤ細鏄剧ず杞﹁締鎵�灞炵殑閮ㄩ棬锛屼究浜庣敤鎴疯瘑鍒�
+3. **鎬ц兘鑰冭檻**锛氬鏋滆溅杈嗘暟鎹緢澶氾紝鍙�冭檻娣诲姞鎼滅储鎴栧垎椤靛姛鑳�
+4. **涓氬姟閫昏緫**锛氳法閮ㄩ棬杞﹁締鍒嗛厤鍙兘闇�瑕侀澶栫殑瀹℃壒娴佺▼
+
+## 鍚庣画浼樺寲寤鸿
+
+1. **鎼滅储鍔熻兘**锛氭坊鍔犺溅杈嗘悳绱㈠姛鑳斤紝鏀寔鎸夎溅鐗屽彿銆侀儴闂ㄣ�佺被鍨嬫悳绱�
+2. **鍒嗛〉鍔犺浇**锛氬鏋滆溅杈嗗緢澶氾紝鍙�冭檻鍒嗛〉鍔犺浇
+3. **鏉冮檺缁嗗寲**锛氭牴鎹敤鎴锋潈闄愭帶鍒跺彲閫夋嫨鐨勮溅杈嗚寖鍥�
+4. **閮ㄩ棬绛涢��**锛氭坊鍔犻儴闂ㄧ瓫閫夐�夐」锛岃鐢ㄦ埛鍙互閫夋嫨鏄惁鍙樉绀虹壒瀹氶儴闂ㄧ殑杞﹁締
+5. **鐘舵�佺鐞�**锛氭敮鎸佹寜杞﹁締鐘舵�佺瓫閫夛紙濡傦細绌洪棽銆佷娇鐢ㄤ腑銆佺淮淇腑锛�
+
+## 鐩稿叧鏂囦欢
+
+- 鉁� `SysTaskServiceImpl.java` - Service灞傚疄鐜帮紙宸蹭慨鏀癸級
+- 鉁� `SysTaskVehicle.java` - 瀹炰綋绫伙紙宸叉坊鍔燿eptName瀛楁锛�
+- 鉁� `SysTaskVehicleMapper.xml` - Mapper閰嶇疆锛堝凡鏇存柊鏌ヨ鍜屾槧灏勶級
+- 鉁� `detail.vue` - 鍓嶇椤甸潰锛堝凡鏀寔鏄剧ず閮ㄩ棬淇℃伅锛�
+
+## 娴嬭瘯寤鸿
+
+1. **鍔熻兘娴嬭瘯**锛氶獙璇佸彲浠ユ悳绱㈠埌鎵�鏈夐儴闂ㄧ殑杞﹁締
+2. **鏄剧ず娴嬭瘯**锛氶獙璇佽溅杈嗗垪琛ㄦ纭樉绀洪儴闂ㄤ俊鎭�
+3. **鍒嗛厤娴嬭瘯**锛氶獙璇佸彲浠ユ垚鍔熷垎閰嶈法閮ㄩ棬杞﹁締
+4. **鏉冮檺娴嬭瘯**锛氶獙璇佹潈闄愭帶鍒舵槸鍚︽甯稿伐浣�
+5. **鎬ц兘娴嬭瘯**锛氶獙璇佸ぇ閲忚溅杈嗘暟鎹笅鐨勬煡璇㈡�ц兘
+
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/utils/TaskCodeGenerator.java b/ruoyi-system/src/main/java/com/ruoyi/system/utils/TaskCodeGenerator.java
index 6f73f74..22c5c72 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/utils/TaskCodeGenerator.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/utils/TaskCodeGenerator.java
@@ -2,8 +2,10 @@
import java.text.SimpleDateFormat;
import java.util.Date;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.system.mapper.SysTaskMapper;
/**
* 浠诲姟缂栧彿鐢熸垚鍣�
@@ -13,6 +15,9 @@
@Component
public class TaskCodeGenerator {
+ @Autowired
+ private SysTaskMapper sysTaskMapper;
+
/**
* 鐢熸垚浠诲姟缂栧彿
* 鏍煎紡锛歍ASK + YYYYMMDD + 4浣嶅簭鍙�
@@ -21,7 +26,7 @@
*/
public String generateTaskCode() {
String dateStr = DateUtils.dateTimeNow("yyyyMMdd");
- return "TASK" + dateStr + "0001";
+ return generateTaskCode(dateStr);
}
/**
@@ -33,6 +38,33 @@
public String generateTaskCode(Date date) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
String dateStr = sdf.format(date);
- return "TASK" + dateStr + "0001";
+ return generateTaskCode(dateStr);
+ }
+
+ /**
+ * 鏍规嵁鏃ユ湡瀛楃涓茬敓鎴愪换鍔$紪鍙�
+ *
+ * @param dateStr 鏃ユ湡瀛楃涓诧紙鏍煎紡锛歽yyyMMdd锛�
+ * @return 浠诲姟缂栧彿
+ */
+ private String generateTaskCode(String dateStr) {
+ String datePrefix = "TASK" + dateStr;
+
+ // 鏌ヨ褰撴棩鏈�澶х紪鍙�
+ String maxTaskCode = sysTaskMapper.selectMaxTaskCodeByDatePrefix(datePrefix);
+
+ int sequence = 1;
+ if (maxTaskCode != null && maxTaskCode.startsWith(datePrefix)) {
+ // 鎻愬彇搴忓彿閮ㄥ垎
+ String sequenceStr = maxTaskCode.substring(datePrefix.length());
+ try {
+ sequence = Integer.parseInt(sequenceStr) + 1;
+ } catch (NumberFormatException e) {
+ sequence = 1;
+ }
+ }
+
+ // 鏍煎紡鍖栦负4浣嶅簭鍙�
+ return datePrefix + String.format("%04d", sequence);
}
}
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysTaskMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysTaskMapper.xml
index 359443d..599cd7e 100644
--- a/ruoyi-system/src/main/resources/mapper/system/SysTaskMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/SysTaskMapper.xml
@@ -12,6 +12,11 @@
<result property="taskDescription" column="task_description" />
<result property="departureAddress" column="departure_address" />
<result property="destinationAddress" column="destination_address" />
+ <result property="departureLongitude" column="departure_longitude" />
+ <result property="departureLatitude" column="departure_latitude" />
+ <result property="destinationLongitude" column="destination_longitude" />
+ <result property="destinationLatitude" column="destination_latitude" />
+ <result property="estimatedDistance" column="estimated_distance" />
<result property="plannedStartTime" column="planned_start_time" />
<result property="plannedEndTime" column="planned_end_time" />
<result property="actualStartTime" column="actual_start_time" />
@@ -32,7 +37,9 @@
<sql id="selectSysTaskVo">
select t.task_id, t.task_code, t.task_type, t.task_status, t.task_description,
- t.departure_address, t.destination_address, t.planned_start_time, t.planned_end_time,
+ t.departure_address, t.destination_address, t.departure_longitude, t.departure_latitude,
+ t.destination_longitude, t.destination_latitude, t.estimated_distance,
+ t.planned_start_time, t.planned_end_time,
t.actual_start_time, t.actual_end_time, t.creator_id, t.assignee_id, t.dept_id,
t.create_time, t.update_time, t.create_by, t.update_by, t.remark, t.del_flag,
u1.nick_name as creator_name, u2.nick_name as assignee_name, d.dept_name
@@ -71,6 +78,12 @@
where t.task_code = #{taskCode} and t.del_flag = '0'
</select>
+ <select id="selectMaxTaskCodeByDatePrefix" parameterType="String" resultType="String">
+ select max(task_code)
+ from sys_task
+ where task_code like concat(#{datePrefix}, '%') and del_flag = '0'
+ </select>
+
<select id="selectOverdueTasks" resultMap="SysTaskResult">
<include refid="selectSysTaskVo"/>
where t.del_flag = '0' and t.planned_end_time < now() and t.task_status != 'COMPLETED'
@@ -106,6 +119,11 @@
<if test="taskDescription != null">task_description,</if>
<if test="departureAddress != null">departure_address,</if>
<if test="destinationAddress != null">destination_address,</if>
+ <if test="departureLongitude != null">departure_longitude,</if>
+ <if test="departureLatitude != null">departure_latitude,</if>
+ <if test="destinationLongitude != null">destination_longitude,</if>
+ <if test="destinationLatitude != null">destination_latitude,</if>
+ <if test="estimatedDistance != null">estimated_distance,</if>
<if test="plannedStartTime != null">planned_start_time,</if>
<if test="plannedEndTime != null">planned_end_time,</if>
<if test="actualStartTime != null">actual_start_time,</if>
@@ -114,7 +132,7 @@
<if test="assigneeId != null">assignee_id,</if>
<if test="deptId != null">dept_id,</if>
<if test="createTime != null">create_time,</if>
- <if test="updateTime != null">update_time,</if>
+ update_time,
<if test="createBy != null">create_by,</if>
<if test="updateBy != null">update_by,</if>
<if test="remark != null">remark,</if>
@@ -127,6 +145,11 @@
<if test="taskDescription != null">#{taskDescription},</if>
<if test="departureAddress != null">#{departureAddress},</if>
<if test="destinationAddress != null">#{destinationAddress},</if>
+ <if test="departureLongitude != null">#{departureLongitude},</if>
+ <if test="departureLatitude != null">#{departureLatitude},</if>
+ <if test="destinationLongitude != null">#{destinationLongitude},</if>
+ <if test="destinationLatitude != null">#{destinationLatitude},</if>
+ <if test="estimatedDistance != null">#{estimatedDistance},</if>
<if test="plannedStartTime != null">#{plannedStartTime},</if>
<if test="plannedEndTime != null">#{plannedEndTime},</if>
<if test="actualStartTime != null">#{actualStartTime},</if>
@@ -135,7 +158,7 @@
<if test="assigneeId != null">#{assigneeId},</if>
<if test="deptId != null">#{deptId},</if>
<if test="createTime != null">#{createTime},</if>
- <if test="updateTime != null">#{updateTime},</if>
+ now(),
<if test="createBy != null">#{createBy},</if>
<if test="updateBy != null">#{updateBy},</if>
<if test="remark != null">#{remark},</if>
@@ -152,6 +175,11 @@
<if test="taskDescription != null">task_description = #{taskDescription},</if>
<if test="departureAddress != null">departure_address = #{departureAddress},</if>
<if test="destinationAddress != null">destination_address = #{destinationAddress},</if>
+ <if test="departureLongitude != null">departure_longitude = #{departureLongitude},</if>
+ <if test="departureLatitude != null">departure_latitude = #{departureLatitude},</if>
+ <if test="destinationLongitude != null">destination_longitude = #{destinationLongitude},</if>
+ <if test="destinationLatitude != null">destination_latitude = #{destinationLatitude},</if>
+ <if test="estimatedDistance != null">estimated_distance = #{estimatedDistance},</if>
<if test="plannedStartTime != null">planned_start_time = #{plannedStartTime},</if>
<if test="plannedEndTime != null">planned_end_time = #{plannedEndTime},</if>
<if test="actualStartTime != null">actual_start_time = #{actualStartTime},</if>
@@ -172,7 +200,7 @@
task_status = #{taskStatus},
<if test="actualStartTime != null">actual_start_time = #{actualStartTime},</if>
<if test="actualEndTime != null">actual_end_time = #{actualEndTime},</if>
- update_time = now(),
+ update_time = #{updateTime},
update_by = #{updateBy}
where task_id = #{taskId}
</update>
@@ -180,17 +208,17 @@
<update id="assignTask" parameterType="SysTask">
update sys_task set
assignee_id = #{assigneeId},
- update_time = now(),
+ update_time = #{updateTime},
update_by = #{updateBy}
where task_id = #{taskId}
</update>
<delete id="deleteSysTaskByTaskId" parameterType="Long">
- update sys_task set del_flag = '2' where task_id = #{taskId}
+ update sys_task set del_flag = '2', update_time = now() where task_id = #{taskId}
</delete>
<delete id="deleteSysTaskByTaskIds" parameterType="String">
- update sys_task set del_flag = '2' where task_id in
+ update sys_task set del_flag = '2', update_time = now() where task_id in
<foreach item="taskId" collection="array" open="(" separator="," close=")">
#{taskId}
</foreach>
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysTaskVehicleMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysTaskVehicleMapper.xml
index e8a3a0f..44f44e3 100644
--- a/ruoyi-system/src/main/resources/mapper/system/SysTaskVehicleMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/SysTaskVehicleMapper.xml
@@ -16,13 +16,15 @@
<result property="vehicleType" column="vehicle_type" />
<result property="vehicleBrand" column="vehicle_brand" />
<result property="vehicleModel" column="vehicle_model" />
+ <result property="deptName" column="dept_name" />
</resultMap>
<sql id="selectSysTaskVehicleVo">
select tv.id, tv.task_id, tv.vehicle_id, tv.assign_time, tv.assign_by, tv.status, tv.remark,
- v.vehicle_no, v.vehicle_type, v.vehicle_brand, v.vehicle_model
+ v.vehicle_no, v.vehicle_type, v.vehicle_brand, v.vehicle_model, d.dept_name
from sys_task_vehicle tv
left join tb_vehicle_info v on tv.vehicle_id = v.vehicle_id
+ left join sys_dept d on v.dept_id = d.dept_id
</sql>
<select id="selectSysTaskVehicleList" parameterType="SysTaskVehicle" resultMap="SysTaskVehicleResult">
@@ -57,16 +59,16 @@
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="taskId != null">task_id,</if>
<if test="vehicleId != null">vehicle_id,</if>
- <if test="assignTime != null">assign_time,</if>
- <if test="assignBy != null and assignBy != ''">assign_by,</if>
+ assign_time,
+ assign_by,
<if test="status != null and status != ''">status,</if>
<if test="remark != null">remark,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="taskId != null">#{taskId},</if>
<if test="vehicleId != null">#{vehicleId},</if>
- <if test="assignTime != null">#{assignTime},</if>
- <if test="assignBy != null and assignBy != ''">#{assignBy},</if>
+ #{assignTime},
+ #{assignBy},
<if test="status != null and status != ''">#{status},</if>
<if test="remark != null">#{remark},</if>
</trim>
diff --git a/ruoyi-system/src/main/resources/mapper/system/VehicleInfoMapper.xml b/ruoyi-system/src/main/resources/mapper/system/VehicleInfoMapper.xml
index aa34be7..885e016 100644
--- a/ruoyi-system/src/main/resources/mapper/system/VehicleInfoMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/VehicleInfoMapper.xml
@@ -13,6 +13,8 @@
<result property="vehicleModel" column="vehicle_model" />
<result property="status" column="status" />
<result property="platformCode" column="platform_code" />
+ <result property="deptId" column="dept_id" />
+ <result property="deptName" column="dept_name" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
@@ -21,31 +23,33 @@
</resultMap>
<sql id="selectVehicleInfoVo">
- select vehicle_id, device_id, vehicle_no, vehicle_type, vehicle_brand, vehicle_model, status, platform_code, create_by, create_time, update_by, update_time, remark
- from tb_vehicle_info
+ select v.vehicle_id, v.device_id, v.vehicle_no, v.vehicle_type, v.vehicle_brand, v.vehicle_model, v.status, v.platform_code, v.dept_id, d.dept_name, v.create_by, v.create_time, v.update_by, v.update_time, v.remark
+ from tb_vehicle_info v
+ left join sys_dept d on v.dept_id = d.dept_id
</sql>
<select id="selectVehicleInfoList" parameterType="VehicleInfo" resultMap="VehicleInfoResult">
<include refid="selectVehicleInfoVo"/>
<where>
- <if test="vehicleNo != null and vehicleNo != ''"> and vehicle_no = #{vehicleNo}</if>
- <if test="deviceId != null and deviceId != ''"> and device_id = #{deviceId}</if>
- <if test="vehicleType != null and vehicleType != ''"> and vehicle_type = #{vehicleType}</if>
- <if test="vehicleBrand != null and vehicleBrand != ''"> and vehicle_brand = #{vehicleBrand}</if>
- <if test="vehicleModel != null and vehicleModel != ''"> and vehicle_model = #{vehicleModel}</if>
- <if test="status != null and status != ''"> and status = #{status}</if>
- <if test="platformCode != null and platformCode != ''"> and platform_code = #{platformCode}</if>
+ <if test="vehicleNo != null and vehicleNo != ''"> and v.vehicle_no = #{vehicleNo}</if>
+ <if test="deviceId != null and deviceId != ''"> and v.device_id = #{deviceId}</if>
+ <if test="vehicleType != null and vehicleType != ''"> and v.vehicle_type = #{vehicleType}</if>
+ <if test="vehicleBrand != null and vehicleBrand != ''"> and v.vehicle_brand = #{vehicleBrand}</if>
+ <if test="vehicleModel != null and vehicleModel != ''"> and v.vehicle_model = #{vehicleModel}</if>
+ <if test="status != null and status != ''"> and v.status = #{status}</if>
+ <if test="platformCode != null and platformCode != ''"> and v.platform_code = #{platformCode}</if>
+ <if test="deptId != null"> and v.dept_id = #{deptId}</if>
</where>
</select>
<select id="selectVehicleInfoById" parameterType="Long" resultMap="VehicleInfoResult">
<include refid="selectVehicleInfoVo"/>
- where vehicle_id = #{vehicleId}
+ where v.vehicle_id = #{vehicleId}
</select>
<select id="selectVehicleInfoByPlateNumber" parameterType="String" resultMap="VehicleInfoResult">
<include refid="selectVehicleInfoVo"/>
- where vehicle_no = #{plateNumber}
+ where v.vehicle_no = #{plateNumber}
</select>
<insert id="insertVehicleInfo" parameterType="VehicleInfo" useGeneratedKeys="true" keyProperty="vehicleId">
@@ -58,6 +62,7 @@
<if test="vehicleModel != null">vehicle_model,</if>
<if test="status != null">status,</if>
<if test="platformCode != null">platform_code,</if>
+ <if test="deptId != null">dept_id,</if>
<if test="createBy != null">create_by,</if>
<if test="createTime != null">create_time,</if>
<if test="updateBy != null">update_by,</if>
@@ -72,6 +77,7 @@
<if test="vehicleModel != null">#{vehicleModel},</if>
<if test="status != null">#{status},</if>
<if test="platformCode != null">#{platformCode},</if>
+ <if test="deptId != null">#{deptId},</if>
<if test="createBy != null">#{createBy},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateBy != null">#{updateBy},</if>
@@ -90,6 +96,7 @@
<if test="vehicleModel != null">vehicle_model = #{vehicleModel},</if>
<if test="status != null">status = #{status},</if>
<if test="platformCode != null">platform_code = #{platformCode},</if>
+ <if test="deptId != null">dept_id = #{deptId},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
<if test="remark != null">remark = #{remark},</if>
diff --git a/ruoyi-ui/public/h5-test.html b/ruoyi-ui/public/h5-test.html
new file mode 100644
index 0000000..6ed5d43
--- /dev/null
+++ b/ruoyi-ui/public/h5-test.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<html lang="zh-CN">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>H5娴嬭瘯椤甸潰</title>
+ <style>
+ body {
+ font-family: Arial, sans-serif;
+ margin: 0;
+ padding: 20px;
+ background-color: #f5f5f5;
+ }
+ .container {
+ max-width: 600px;
+ margin: 0 auto;
+ background: white;
+ padding: 20px;
+ border-radius: 8px;
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
+ }
+ h1 {
+ color: #409eff;
+ text-align: center;
+ }
+ .info {
+ background: #f0f9ff;
+ padding: 15px;
+ border-radius: 4px;
+ margin: 20px 0;
+ }
+ .success {
+ color: #67c23a;
+ font-weight: bold;
+ }
+ </style>
+</head>
+<body>
+ <div class="container">
+ <h1>H5椤甸潰娴嬭瘯</h1>
+ <div class="info">
+ <p class="success">鉁� 濡傛灉鎮ㄨ兘鐪嬪埌杩欎釜椤甸潰锛岃鏄庢湇鍔″櫒杩愯姝e父锛�</p>
+ <p>褰撳墠鏃堕棿: <span id="currentTime"></span></p>
+ <p>椤甸潰璺緞: <span id="currentPath"></span></p>
+ </div>
+
+ <h2>娴嬭瘯閾炬帴</h2>
+ <ul>
+ <li><a href="/#/h5/simple">绠�鍗曟祴璇曢〉闈�</a></li>
+ <li><a href="/#/h5/test">瀹屾暣娴嬭瘯椤甸潰</a></li>
+ <li><a href="/#/h5/task/create">鍒涘缓浠诲姟椤甸潰</a></li>
+ </ul>
+
+ <h2>璋冭瘯淇℃伅</h2>
+ <div id="debugInfo">
+ <p>鐢ㄦ埛浠g悊: <span id="userAgent"></span></p>
+ <p>灞忓箷鍒嗚鲸鐜�: <span id="screenSize"></span></p>
+ <p>瑙嗗彛澶у皬: <span id="viewportSize"></span></p>
+ </div>
+ </div>
+
+ <script>
+ // 鏄剧ず褰撳墠鏃堕棿
+ document.getElementById('currentTime').textContent = new Date().toLocaleString();
+
+ // 鏄剧ず褰撳墠璺緞
+ document.getElementById('currentPath').textContent = window.location.href;
+
+ // 鏄剧ず鐢ㄦ埛浠g悊
+ document.getElementById('userAgent').textContent = navigator.userAgent;
+
+ // 鏄剧ず灞忓箷鍒嗚鲸鐜�
+ document.getElementById('screenSize').textContent = screen.width + 'x' + screen.height;
+
+ // 鏄剧ず瑙嗗彛澶у皬
+ document.getElementById('viewportSize').textContent = window.innerWidth + 'x' + window.innerHeight;
+
+ console.log('H5娴嬭瘯椤甸潰宸插姞杞�');
+ console.log('褰撳墠URL:', window.location.href);
+ </script>
+</body>
+</html>
diff --git a/ruoyi-ui/public/map-config.js b/ruoyi-ui/public/map-config.js
new file mode 100644
index 0000000..196f19f
--- /dev/null
+++ b/ruoyi-ui/public/map-config.js
@@ -0,0 +1,64 @@
+// 鐧惧害鍦板浘閰嶇疆
+window.BMapConfig = {
+ // 鐧惧害鍦板浘API Key锛堜娇鐢ㄩ」鐩腑宸叉湁鐨凙PI Key锛�
+ key: 'n5z5pKfAnaP3fYMR4RJOAQsR1wQ2avAn',
+ // 鍦板浘鐗堟湰
+ version: '3.0',
+ // 榛樿涓績鐐癸紙鍖椾含锛�
+ center: [116.404, 39.915],
+ // 榛樿缂╂斁绾у埆
+ zoom: 15
+};
+
+// 鍔ㄦ�佸姞杞界櫨搴﹀湴鍥続PI
+(function() {
+ // 妫�鏌ユ槸鍚﹀凡缁忓姞杞借繃鐧惧害鍦板浘API
+ if (window.BMap) {
+ console.log('鐧惧害鍦板浘API宸插瓨鍦�');
+ return;
+ }
+
+ // 纭繚DOM宸插姞杞藉畬鎴�
+ function loadBMapScript() {
+ // 妫�鏌ocument.head鏄惁瀛樺湪
+ if (!document.head) {
+ console.error('document.head涓嶅瓨鍦紝寤惰繜鍔犺浇鐧惧害鍦板浘API');
+ setTimeout(loadBMapScript, 100);
+ return;
+ }
+
+ // 璁剧疆鍥炶皟鍑芥暟
+ window.initBMap = function() {
+ console.log('鐧惧害鍦板浘API鍔犺浇鎴愬姛');
+ // 瑙﹀彂鑷畾涔変簨浠讹紝閫氱煡鍏朵粬缁勪欢鍦板浘宸插姞杞�
+ window.dispatchEvent(new CustomEvent('bmapLoaded'));
+ };
+
+ const script = document.createElement('script');
+ script.type = 'text/javascript';
+ script.src = `https://api.map.baidu.com/api?v=${window.BMapConfig.version}&ak=${window.BMapConfig.key}&callback=initBMap`;
+ script.async = true;
+ script.onload = function() {
+ console.log('鐧惧害鍦板浘鑴氭湰鍔犺浇瀹屾垚');
+ };
+ script.onerror = function(error) {
+ console.error('鐧惧害鍦板浘API鍔犺浇澶辫触:', error);
+ // 瑙﹀彂閿欒浜嬩欢
+ window.dispatchEvent(new CustomEvent('bmapError', { detail: error }));
+ };
+
+ try {
+ document.head.appendChild(script);
+ console.log('鐧惧害鍦板浘鑴氭湰宸叉坊鍔犲埌椤甸潰');
+ } catch (error) {
+ console.error('娣诲姞鐧惧害鍦板浘鑴氭湰澶辫触:', error);
+ }
+ }
+
+ // 绛夊緟DOM鍔犺浇瀹屾垚
+ if (document.readyState === 'loading') {
+ document.addEventListener('DOMContentLoaded', loadBMapScript);
+ } else {
+ loadBMapScript();
+ }
+})();
diff --git a/ruoyi-ui/src/App.vue b/ruoyi-ui/src/App.vue
index b92ea37..199b075 100644
--- a/ruoyi-ui/src/App.vue
+++ b/ruoyi-ui/src/App.vue
@@ -1,7 +1,7 @@
<template>
<div id="app">
<router-view />
- <theme-picker />
+ <theme-picker v-if="!isH5Page" />
</div>
</template>
@@ -11,6 +11,11 @@
export default {
name: "App",
components: { ThemePicker },
+ computed: {
+ isH5Page() {
+ return this.$route.path.startsWith('/h5/');
+ }
+ },
metaInfo() {
return {
title: this.$store.state.settings.dynamicTitle && this.$store.state.settings.title,
diff --git a/ruoyi-ui/src/api/task.js b/ruoyi-ui/src/api/task.js
index abeb5fb..de044c9 100644
--- a/ruoyi-ui/src/api/task.js
+++ b/ruoyi-ui/src/api/task.js
@@ -157,3 +157,91 @@
method: 'delete'
})
}
+
+// ========== 浠诲姟杞﹁締鍏宠仈绠$悊鐩稿叧API ==========
+
+// 鏌ヨ浠诲姟杞﹁締鍏宠仈鍒楄〃
+export function listTaskVehicle(query) {
+ return request({
+ url: '/task/vehicle/management/list',
+ method: 'get',
+ params: query
+ })
+}
+
+// 鏌ヨ浠诲姟杞﹁締鍏宠仈璇︾粏
+export function getTaskVehicle(id) {
+ return request({
+ url: '/task/vehicle/management/' + id,
+ method: 'get'
+ })
+}
+
+// 鏂板浠诲姟杞﹁締鍏宠仈
+export function addTaskVehicle(data) {
+ return request({
+ url: '/task/vehicle/management',
+ method: 'post',
+ data: data
+ })
+}
+
+// 淇敼浠诲姟杞﹁締鍏宠仈
+export function updateTaskVehicle(data) {
+ return request({
+ url: '/task/vehicle/management',
+ method: 'put',
+ data: data
+ })
+}
+
+// 鍒犻櫎浠诲姟杞﹁締鍏宠仈
+export function delTaskVehicle(ids) {
+ return request({
+ url: '/task/vehicle/management/' + ids,
+ method: 'delete'
+ })
+}
+
+// 鏍规嵁浠诲姟ID鏌ヨ鍏宠仈杞﹁締鍒楄〃
+export function getVehiclesByTaskId(taskId) {
+ return request({
+ url: '/task/vehicle/management/task/' + taskId,
+ method: 'get'
+ })
+}
+
+// 鍒嗛厤杞﹁締缁欎换鍔★紙绠$悊鎺ュ彛锛�
+export function assignVehicleToTaskManagement(data) {
+ return request({
+ url: '/task/vehicle/management/assign',
+ method: 'post',
+ data: data
+ })
+}
+
+// 鎵归噺鍒嗛厤杞﹁締缁欎换鍔★紙绠$悊鎺ュ彛锛�
+export function assignVehiclesToTaskManagement(data) {
+ return request({
+ url: '/task/vehicle/management/assign-batch',
+ method: 'post',
+ data: data
+ })
+}
+
+// 鍙栨秷浠诲姟杞﹁締鍒嗛厤锛堢鐞嗘帴鍙o級
+export function unassignVehicleFromTaskManagement(taskId, vehicleId) {
+ return request({
+ url: '/task/vehicle/management/unassign/' + taskId + '/' + vehicleId,
+ method: 'delete'
+ })
+}
+
+// 鏇存柊浠诲姟杞﹁締鍏宠仈鐘舵��
+export function updateTaskVehicleStatus(id, status) {
+ return request({
+ url: '/task/vehicle/management/status/' + id,
+ method: 'put',
+ params: { status }
+ })
+}
\ No newline at end of file
diff --git a/ruoyi-ui/src/permission.js b/ruoyi-ui/src/permission.js
index 7ab950d..ca6c9cf 100644
--- a/ruoyi-ui/src/permission.js
+++ b/ruoyi-ui/src/permission.js
@@ -9,7 +9,7 @@
NProgress.configure({ showSpinner: false })
-const whiteList = ['/login', '/register','/anonymous/*']
+const whiteList = ['/login', '/register','/anonymous/*', '/h5/*']
const isWhiteList = (path) => {
return whiteList.some(pattern => isPathMatch(pattern, path))
@@ -17,6 +17,14 @@
router.beforeEach((to, from, next) => {
NProgress.start()
+
+ // 璋冭瘯鏃ュ織
+ console.log('=== 璺敱瀹堝崼璋冭瘯 ===')
+ console.log('鐩爣璺緞:', to.path)
+ console.log('瀹屾暣璺緞:', to.fullPath)
+ console.log('Token鐘舵��:', !!getToken())
+ console.log('鐧藉悕鍗曟鏌�:', isWhiteList(to.path))
+
if (getToken()) {
to.meta.title && store.dispatch('settings/setTitle', to.meta.title)
/* has token*/
@@ -24,6 +32,7 @@
next({ path: '/' })
NProgress.done()
} else if (isWhiteList(to.path)) {
+ console.log('鉁� 鏈塗oken涓斿湪鐧藉悕鍗曪紝鐩存帴閫氳繃')
next()
} else {
if (store.getters.roles.length === 0) {
diff --git a/ruoyi-ui/src/router/index.js b/ruoyi-ui/src/router/index.js
index 41e0f28..0a18af8 100644
--- a/ruoyi-ui/src/router/index.js
+++ b/ruoyi-ui/src/router/index.js
@@ -123,6 +123,14 @@
component: () => import('@/views/system/gps/mapNeed'),
name: 'GpsMapNeed',
meta: { title: '杞﹁締杞ㄨ抗', icon: 'map' }
+ },
+
+ {
+ path: '/h5/task_create',
+ component: () => import('@/views/task/h5/create'),
+ hidden: false,
+ name: 'H5TaskCreate',
+ meta: { title: '鍒涘缓浠诲姟' }
}
]
@@ -227,7 +235,7 @@
}
export default new Router({
- mode: 'history', // 鍘绘帀url涓殑#
+ mode: 'hash', // 浣跨敤hash妯″紡锛屽吋瀹规�ф洿濂�
scrollBehavior: () => ({ y: 0 }),
routes: constantRoutes
})
diff --git a/ruoyi-ui/src/views/system/vehicle/index.vue b/ruoyi-ui/src/views/system/vehicle/index.vue
index 4ec9201..4049d3d 100644
--- a/ruoyi-ui/src/views/system/vehicle/index.vue
+++ b/ruoyi-ui/src/views/system/vehicle/index.vue
@@ -11,13 +11,14 @@
/>
</el-form-item>
<el-form-item label="杞﹁締绫诲瀷" prop="vehicleType">
- <el-input
- v-model="queryParams.vehicleType"
- placeholder="璇疯緭鍏ヨ溅杈嗙被鍨�"
- clearable
- size="small"
- @keyup.enter.native="handleQuery"
- />
+ <el-select v-model="queryParams.vehicleType" placeholder="璇烽�夋嫨杞﹁締绫诲瀷" clearable size="small">
+ <el-option
+ v-for="dict in dict.type.sys_vehicle_type"
+ :key="dict.value"
+ :label="dict.label"
+ :value="dict.value"
+ />
+ </el-select>
</el-form-item>
<el-form-item label="鐘舵��" prop="status">
<el-select v-model="queryParams.status" placeholder="璇烽�夋嫨鐘舵��" clearable size="small">
@@ -36,6 +37,16 @@
:key="dict.value"
:label="dict.label"
:value="dict.value"
+ />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="褰掑睘閮ㄩ棬" prop="deptId">
+ <el-select v-model="queryParams.deptId" placeholder="璇烽�夋嫨閮ㄩ棬" clearable size="small">
+ <el-option
+ v-for="dept in deptList"
+ :key="dept.deptId"
+ :label="dept.deptName"
+ :value="dept.deptId"
/>
</el-select>
</el-form-item>
@@ -95,7 +106,11 @@
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="杞﹁締ID" align="center" prop="vehicleId" />
<el-table-column label="杞︾墝鍙�" align="center" prop="vehicleNo" />
- <el-table-column label="杞﹁締绫诲瀷" align="center" prop="vehicleType" />
+ <el-table-column label="杞﹁締绫诲瀷" align="center" prop="vehicleType">
+ <template slot-scope="scope">
+ <dict-tag :options="dict.type.sys_vehicle_type" :value="scope.row.vehicleType"/>
+ </template>
+ </el-table-column>
<el-table-column label="杞﹁締鍝佺墝" align="center" prop="vehicleBrand" />
<el-table-column label="杞﹁締鍨嬪彿" align="center" prop="vehicleModel" />
<el-table-column label="骞冲彴鏍囪瘑" align="center" prop="platformCode">
@@ -108,6 +123,7 @@
<dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
</template>
</el-table-column>
+ <el-table-column label="褰掑睘閮ㄩ棬" align="center" prop="deptName" />
<el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
@@ -148,7 +164,14 @@
<el-input v-model="form.vehicleNo" placeholder="璇疯緭鍏ヨ溅鐗屽彿" />
</el-form-item>
<el-form-item label="杞﹁締绫诲瀷" prop="vehicleType">
- <el-input v-model="form.vehicleType" placeholder="璇疯緭鍏ヨ溅杈嗙被鍨�" />
+ <el-select v-model="form.vehicleType" placeholder="璇烽�夋嫨杞﹁締绫诲瀷" clearable style="width: 100%">
+ <el-option
+ v-for="dict in dict.type.sys_vehicle_type"
+ :key="dict.value"
+ :label="dict.label"
+ :value="dict.value"
+ />
+ </el-select>
</el-form-item>
<el-form-item label="杞﹁締鍝佺墝" prop="vehicleBrand">
<el-input v-model="form.vehicleBrand" placeholder="璇疯緭鍏ヨ溅杈嗗搧鐗�" />
@@ -175,6 +198,16 @@
>{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
+ <el-form-item label="褰掑睘閮ㄩ棬" prop="deptId">
+ <el-select v-model="form.deptId" placeholder="璇烽�夋嫨褰掑睘閮ㄩ棬" clearable style="width: 100%">
+ <el-option
+ v-for="dept in deptList"
+ :key="dept.deptId"
+ :label="dept.deptName"
+ :value="dept.deptId"
+ />
+ </el-select>
+ </el-form-item>
<el-form-item label="澶囨敞" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" />
</el-form-item>
@@ -189,10 +222,11 @@
<script>
import { listVehicle, getVehicle, delVehicle, addVehicle, updateVehicle } from "@/api/system/vehicle";
+import { listDept } from "@/api/system/dept";
export default {
name: "Vehicle",
- dicts: ['sys_normal_disable', 'sys_platform'],
+ dicts: ['sys_normal_disable', 'sys_platform', 'sys_vehicle_type'],
data() {
return {
// 閬僵灞�
@@ -209,6 +243,8 @@
total: 0,
// 杞﹁締淇℃伅琛ㄦ牸鏁版嵁
vehicleList: [],
+ // 閮ㄩ棬鍒楄〃鏁版嵁
+ deptList: [],
// 寮瑰嚭灞傛爣棰�
title: "",
// 鏄惁鏄剧ず寮瑰嚭灞�
@@ -222,7 +258,8 @@
vehicleBrand: null,
vehicleModel: null,
status: null,
- platformCode: null
+ platformCode: null,
+ deptId: null
},
// 琛ㄥ崟鍙傛暟
form: {
@@ -233,7 +270,8 @@
vehicleModel: null,
status: "0",
remark: null,
- platformCode: null
+ platformCode: null,
+ deptId: null
},
// 琛ㄥ崟鏍¢獙
rules: {
@@ -251,6 +289,7 @@
},
created() {
this.getList();
+ this.getDeptList();
},
methods: {
/** 鏌ヨ杞﹁締淇℃伅鍒楄〃 */
@@ -260,6 +299,12 @@
this.vehicleList = response.rows;
this.total = response.total;
this.loading = false;
+ });
+ },
+ /** 鑾峰彇閮ㄩ棬鍒楄〃 */
+ getDeptList() {
+ listDept().then(response => {
+ this.deptList = response.data;
});
},
// 鍙栨秷鎸夐挳
@@ -277,7 +322,8 @@
vehicleModel: null,
status: "0",
remark: null,
- platformCode: null
+ platformCode: null,
+ deptId: null
};
this.resetForm("form");
},
diff --git "a/ruoyi-ui/src/views/system/vehicle/\351\203\250\351\227\250\345\212\237\350\203\275\344\274\230\345\214\226\350\257\264\346\230\216.md" "b/ruoyi-ui/src/views/system/vehicle/\351\203\250\351\227\250\345\212\237\350\203\275\344\274\230\345\214\226\350\257\264\346\230\216.md"
new file mode 100644
index 0000000..ccfbb84
--- /dev/null
+++ "b/ruoyi-ui/src/views/system/vehicle/\351\203\250\351\227\250\345\212\237\350\203\275\344\274\230\345\214\226\350\257\264\346\230\216.md"
@@ -0,0 +1,170 @@
+# 杞﹁締绠$悊鐣岄潰閮ㄩ棬鍔熻兘浼樺寲璇存槑
+
+## 浼樺寲鍐呭
+
+### 1. 鏌ヨ鏉′欢浼樺寲
+- 鉁� **鏂板閮ㄩ棬鏌ヨ**锛氭坊鍔犱簡"褰掑睘閮ㄩ棬"鏌ヨ鏉′欢
+- 鉁� **杞﹁締绫诲瀷浼樺寲**锛氬皢杞﹁締绫诲瀷浠庤緭鍏ユ鏀逛负涓嬫媺閫夋嫨
+- 鉁� **瀛楀吀鏀寔**锛氳溅杈嗙被鍨嬩娇鐢ㄥ瓧鍏告爣绛炬樉绀�
+
+### 2. 琛ㄦ牸鏄剧ず浼樺寲
+- 鉁� **鏂板閮ㄩ棬鍒�**锛氬湪琛ㄦ牸涓坊鍔�"褰掑睘閮ㄩ棬"鍒楁樉绀�
+- 鉁� **杞﹁締绫诲瀷鏄剧ず**锛氫娇鐢ㄥ瓧鍏告爣绛炬樉绀鸿溅杈嗙被鍨�
+- 鉁� **淇℃伅瀹屾暣**锛氭樉绀鸿溅杈嗙殑瀹屾暣淇℃伅鍖呮嫭褰掑睘閮ㄩ棬
+
+### 3. 缂栬緫鍔熻兘浼樺寲
+- 鉁� **閮ㄩ棬閫夋嫨**锛氬湪鏂板/缂栬緫瀵硅瘽妗嗕腑娣诲姞閮ㄩ棬閫夋嫨
+- 鉁� **杞﹁締绫诲瀷閫夋嫨**锛氬皢杞﹁締绫诲瀷鏀逛负涓嬫媺閫夋嫨
+- 鉁� **琛ㄥ崟楠岃瘉**锛氫繚鎸佸師鏈夌殑琛ㄥ崟楠岃瘉瑙勫垯
+
+## 鎶�鏈疄鐜�
+
+### 1. 鍓嶇鐣岄潰浼樺寲
+```vue
+<!-- 鏌ヨ鏉′欢 -->
+<el-form-item label="褰掑睘閮ㄩ棬" prop="deptId">
+ <el-select v-model="queryParams.deptId" placeholder="璇烽�夋嫨閮ㄩ棬" clearable size="small">
+ <el-option
+ v-for="dept in deptList"
+ :key="dept.deptId"
+ :label="dept.deptName"
+ :value="dept.deptId"
+ />
+ </el-select>
+</el-form-item>
+
+<!-- 琛ㄦ牸鏄剧ず -->
+<el-table-column label="褰掑睘閮ㄩ棬" align="center" prop="deptName" />
+
+<!-- 缂栬緫琛ㄥ崟 -->
+<el-form-item label="褰掑睘閮ㄩ棬" prop="deptId">
+ <el-select v-model="form.deptId" placeholder="璇烽�夋嫨褰掑睘閮ㄩ棬" clearable style="width: 100%">
+ <el-option
+ v-for="dept in deptList"
+ :key="dept.deptId"
+ :label="dept.deptName"
+ :value="dept.deptId"
+ />
+ </el-select>
+</el-form-item>
+```
+
+### 2. 鏁版嵁绠$悊
+```javascript
+// 瀵煎叆閮ㄩ棬API
+import { listDept } from "@/api/system/dept";
+
+// 鏁版嵁瀹氫箟
+data() {
+ return {
+ // 閮ㄩ棬鍒楄〃鏁版嵁
+ deptList: [],
+ // 鏌ヨ鍙傛暟
+ queryParams: {
+ // ... 鍏朵粬鍙傛暟
+ deptId: null
+ },
+ // 琛ㄥ崟鍙傛暟
+ form: {
+ // ... 鍏朵粬瀛楁
+ deptId: null
+ }
+ };
+}
+
+// 鑾峰彇閮ㄩ棬鍒楄〃
+getDeptList() {
+ listDept().then(response => {
+ this.deptList = response.data;
+ });
+}
+```
+
+### 3. 瀛楀吀閰嶇疆
+```javascript
+// 娣诲姞杞﹁締绫诲瀷瀛楀吀
+dicts: ['sys_normal_disable', 'sys_platform', 'sys_vehicle_type']
+
+// 杞﹁締绫诲瀷鏄剧ず
+<el-table-column label="杞﹁締绫诲瀷" align="center" prop="vehicleType">
+ <template slot-scope="scope">
+ <dict-tag :options="dict.type.sys_vehicle_type" :value="scope.row.vehicleType"/>
+ </template>
+</el-table-column>
+```
+
+## 鍔熻兘鐗规��
+
+### 1. 鏌ヨ鍔熻兘
+- **澶氭潯浠舵煡璇�**锛氭敮鎸佹寜杞︾墝鍙枫�佽溅杈嗙被鍨嬨�佺姸鎬併�佸钩鍙版爣璇嗐�佸綊灞為儴闂ㄦ煡璇�
+- **閮ㄩ棬绛涢��**锛氬彲浠ユ寜閮ㄩ棬绛涢�夎溅杈�
+- **绫诲瀷绛涢��**锛氬彲浠ユ寜杞﹁締绫诲瀷绛涢��
+
+### 2. 鏄剧ず鍔熻兘
+- **閮ㄩ棬淇℃伅**锛氳〃鏍间腑鏄剧ず杞﹁締褰掑睘閮ㄩ棬
+- **绫诲瀷鏍囩**锛氳溅杈嗙被鍨嬩娇鐢ㄥ僵鑹叉爣绛炬樉绀�
+- **鐘舵�佹爣绛�**锛氳溅杈嗙姸鎬佷娇鐢ㄥ僵鑹叉爣绛炬樉绀�
+
+### 3. 缂栬緫鍔熻兘
+- **閮ㄩ棬鍒嗛厤**锛氬彲浠ヤ负杞﹁締鍒嗛厤褰掑睘閮ㄩ棬
+- **绫诲瀷閫夋嫨**锛氳溅杈嗙被鍨嬮�氳繃涓嬫媺閫夋嫨
+- **鏁版嵁瀹屾暣鎬�**锛氫繚鎸佹墍鏈夊瓧娈电殑鏁版嵁瀹屾暣鎬�
+
+## 鐣岄潰鏁堟灉
+
+### 鏌ヨ鏉′欢鍖哄煙
+```
+鈹屸攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�
+鈹� 杞︾墝鍙�: [杈撳叆妗哴 杞﹁締绫诲瀷: [涓嬫媺閫夋嫨] 鐘舵��: [涓嬫媺閫夋嫨] 鈹�
+鈹� 骞冲彴鏍囪瘑: [涓嬫媺閫夋嫨] 褰掑睘閮ㄩ棬: [涓嬫媺閫夋嫨] 鈹�
+鈹� [鎼滅储] [閲嶇疆] 鈹�
+鈹斺攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�
+```
+
+### 琛ㄦ牸鏄剧ず
+```
+鈹屸攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�
+鈹� 杞﹁締ID 鈹� 杞︾墝鍙� 鈹� 杞﹁締绫诲瀷 鈹� 鍝佺墝 鈹� 鍨嬪彿 鈹� 骞冲彴 鈹� 鐘舵�� 鈹� 褰掑睘閮ㄩ棬 鈹� 鍒涘缓鏃堕棿 鈹� 鎿嶄綔 鈹�
+鈹溾攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�
+鈹� 1 鈹� 绮12345 鈹� 鏁戞姢杞� 鈹� 濂旈┌ 鈹� S350 鈹� A骞冲彴 鈹� 姝e父 鈹� 鎬ユ晳涓績 鈹� 2024-01-01 鈹� 淇敼鍒犻櫎 鈹�
+鈹� 2 鈹� 绮67890 鈹� 杞繍杞� 鈹� 涓扮敯 鈹� 娴风嫯 鈹� B骞冲彴 鈹� 姝e父 鈹� 杞繍涓績 鈹� 2024-01-02 鈹� 淇敼鍒犻櫎 鈹�
+鈹斺攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�
+```
+
+### 缂栬緫瀵硅瘽妗�
+```
+鈹屸攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�
+鈹� 杞︾墝鍙�: [杈撳叆妗哴 鈹�
+鈹� 杞﹁締绫诲瀷: [涓嬫媺閫夋嫨] 鈹�
+鈹� 杞﹁締鍝佺墝: [杈撳叆妗哴 鈹�
+鈹� 杞﹁締鍨嬪彿: [杈撳叆妗哴 鈹�
+鈹� 骞冲彴鏍囪瘑: [涓嬫媺閫夋嫨] 鈹�
+鈹� 鐘舵��: [鍗曢�夋寜閽甝 鈹�
+鈹� 褰掑睘閮ㄩ棬: [涓嬫媺閫夋嫨] 鈹�
+鈹� 澶囨敞: [鏂囨湰鍩焆 鈹�
+鈹� [纭畾] [鍙栨秷] 鈹�
+鈹斺攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�
+```
+
+## 鐢ㄦ埛浣撻獙鎻愬崌
+
+1. **鏌ヨ渚挎嵎**锛氭敮鎸佹寜閮ㄩ棬鏌ヨ杞﹁締锛屼究浜庣鐞�
+2. **淇℃伅瀹屾暣**锛氭樉绀鸿溅杈嗗綊灞為儴闂紝淇℃伅鏇村畬鏁�
+3. **鎿嶄綔鍙嬪ソ**锛氳溅杈嗙被鍨嬪拰閮ㄩ棬閮戒娇鐢ㄤ笅鎷夐�夋嫨锛岄伩鍏嶈緭鍏ラ敊璇�
+4. **瑙嗚娓呮櫚**锛氫娇鐢ㄥ瓧鍏告爣绛炬樉绀虹被鍨嬪拰鐘舵�侊紝瑙嗚鏁堟灉鏇村ソ
+5. **鏁版嵁涓�鑷�**锛氫笌浠诲姟杞﹁締鍏宠仈鍔熻兘淇濇寔涓�鑷寸殑鏁版嵁缁撴瀯
+
+## 娉ㄦ剰浜嬮」
+
+1. **鏁版嵁渚濊禆**锛氶渶瑕佺‘淇濋儴闂ㄦ暟鎹瓨鍦�
+2. **鏉冮檺鎺у埗**锛氶渶瑕佺浉搴旂殑鏉冮檺鎵嶈兘杩涜澧炲垹鏀规煡鎿嶄綔
+3. **鏁版嵁瀹屾暣鎬�**锛氶儴闂ㄥ瓧娈靛彲浠ヤ负绌猴紝浣嗗缓璁负杞﹁締鍒嗛厤閮ㄩ棬
+4. **鎬ц兘鑰冭檻**锛氶儴闂ㄥ垪琛ㄥ湪椤甸潰鍔犺浇鏃惰幏鍙栵紝濡傛灉閮ㄩ棬寰堝鍙�冭檻鍒嗛〉
+
+## 鍚庣画浼樺寲寤鸿
+
+1. **閮ㄩ棬鏍戝舰缁撴瀯**锛氬鏋滈儴闂ㄦ湁灞傜骇鍏崇郴锛屽彲浠ユ樉绀轰负鏍戝舰缁撴瀯
+2. **鎵归噺鎿嶄綔**锛氭敮鎸佹壒閲忎慨鏀硅溅杈嗛儴闂�
+3. **閮ㄩ棬缁熻**锛氭樉绀哄悇閮ㄩ棬鐨勮溅杈嗘暟閲忕粺璁�
+4. **鏉冮檺缁嗗寲**锛氭寜閮ㄩ棬鎺у埗杞﹁締绠$悊鏉冮檺
+5. **瀵煎叆瀵煎嚭**锛氭敮鎸佸寘鍚儴闂ㄤ俊鎭殑鎵归噺瀵煎叆瀵煎嚭
diff --git "a/ruoyi-ui/src/views/task/general/GPS\345\235\220\346\240\207\345\212\237\350\203\275\344\275\277\347\224\250\350\257\264\346\230\216.md" "b/ruoyi-ui/src/views/task/general/GPS\345\235\220\346\240\207\345\212\237\350\203\275\344\275\277\347\224\250\350\257\264\346\230\216.md"
new file mode 100644
index 0000000..65e7fcc
--- /dev/null
+++ "b/ruoyi-ui/src/views/task/general/GPS\345\235\220\346\240\207\345\212\237\350\203\275\344\275\277\347\224\250\350\257\264\346\230\216.md"
@@ -0,0 +1,121 @@
+# 閫氱敤浠诲姟绠$悊GPS鍧愭爣鍔熻兘浣跨敤璇存槑
+
+## 鍔熻兘姒傝堪
+
+閫氱敤浠诲姟绠$悊鐣岄潰宸插鍔燝PS鍧愭爣杈撳叆鍜岃窛绂昏绠楀姛鑳斤紝鏀寔璁板綍杞﹁締鐨勮矾绋嬩俊鎭��
+
+## 鏂板鍔熻兘
+
+### 1. GPS鍧愭爣杈撳叆
+- **鍑哄彂鍦扮粡搴�**锛氳緭鍏ヨ寖鍥� -180掳 鍒� 180掳
+- **鍑哄彂鍦扮含搴�**锛氳緭鍏ヨ寖鍥� -90掳 鍒� 90掳
+- **鐩殑鍦扮粡搴�**锛氳緭鍏ヨ寖鍥� -180掳 鍒� 180掳
+- **鐩殑鍦扮含搴�**锛氳緭鍏ヨ寖鍥� -90掳 鍒� 90掳
+
+### 2. 鑷姩璺濈璁$畻
+- 褰撹緭鍏ュ畬鏁寸殑GPS鍧愭爣鏃讹紝绯荤粺鑷姩璁$畻涓ょ偣闂磋窛绂�
+- 浣跨敤Haversine鍏紡璁$畻鐞冮潰璺濈
+- 璺濈鏄剧ず鍗曚綅涓哄叕閲岋紝淇濈暀2浣嶅皬鏁�
+
+### 3. 琛ㄦ牸鏄剧ず
+- 鍦ㄤ换鍔″垪琛ㄤ腑娣诲姞"棰勮鍏噷鏁�"鍒�
+- 鏄剧ず鏍煎紡锛歚XX.XX km`
+- 鏃犳暟鎹椂鏄剧ず `--`
+
+## 浣跨敤鏂规硶
+
+### 鍒涘缓浠诲姟鏃�
+1. 濉啓鍩烘湰淇℃伅锛堜换鍔$被鍨嬨�佹弿杩般�佸湴鍧�绛夛級
+2. 鍦�"GPS鍧愭爣淇℃伅"閮ㄥ垎杈撳叆鍧愭爣锛�
+ - 鍑哄彂鍦扮粡搴︺�佺含搴�
+ - 鐩殑鍦扮粡搴︺�佺含搴�
+3. 绯荤粺鑷姩璁$畻骞舵樉绀洪璁″叕閲屾暟
+4. 鐐瑰嚮"纭畾"淇濆瓨浠诲姟
+
+### 淇敼浠诲姟鏃�
+1. 鐐瑰嚮"淇敼"鎸夐挳鎵撳紑缂栬緫瀵硅瘽妗�
+2. 淇敼GPS鍧愭爣淇℃伅
+3. 绯荤粺鑷姩閲嶆柊璁$畻璺濈
+4. 淇濆瓨淇敼
+
+### 鏌ョ湅浠诲姟鏃�
+1. 鍦ㄤ换鍔″垪琛ㄤ腑鏌ョ湅"棰勮鍏噷鏁�"鍒�
+2. 鐐瑰嚮"鏌ョ湅"鎸夐挳鏌ョ湅璇︾粏淇℃伅
+
+## 鍧愭爣杈撳叆璇存槑
+
+### 鍧愭爣鏍煎紡
+- 浣跨敤鍗佽繘鍒舵牸寮忥紙濡傦細116.397128锛�
+- 绮惧害锛�7浣嶅皬鏁帮紙绾�1.1鍘樼背绮惧害锛�
+- 鏀寔姝h礋鍊�
+
+### 鍧愭爣鑼冨洿
+- **缁忓害**锛�-180掳 鍒� 180掳
+- **绾害**锛�-90掳 鍒� 90掳
+
+### 甯歌鍩庡競鍧愭爣绀轰緥
+- **鍖椾含澶╁畨闂�**锛氱粡搴� 116.397128锛岀含搴� 39.916527
+- **涓婃捣澶栨哗**锛氱粡搴� 121.499763锛岀含搴� 31.239663
+- **骞垮窞濉�**锛氱粡搴� 113.324520锛岀含搴� 23.109720
+
+## 璺濈璁$畻璇存槑
+
+### 璁$畻绠楁硶
+浣跨敤Haversine鍏紡璁$畻鍦扮悆琛ㄩ潰涓ょ偣闂寸殑鐞冮潰璺濈锛�
+- 鑰冭檻鍦扮悆鏇茬巼
+- 閫傜敤浜庝腑鐭窛绂昏绠楋紙< 1000鍏噷锛�
+- 绮惧害锛氱背绾�
+
+### 璁$畻鏉′欢
+- 鍥涗釜鍧愭爣鍊奸兘蹇呴』杈撳叆
+- 鍧愭爣鍊煎繀椤诲湪鏈夋晥鑼冨洿鍐�
+- 鍧愭爣鏃犳晥鏃惰窛绂绘樉绀轰负0
+
+## 鐣岄潰璇存槑
+
+### 琛ㄥ崟甯冨眬
+- GPS鍧愭爣淇℃伅浣跨敤鍒嗗壊绾垮垎闅�
+- 缁忓害绾害浣跨敤涓ゅ垪甯冨眬
+- 棰勮鍏噷鏁板瓧娈典负鍙鐘舵��
+
+### 杈撳叆鎺т欢
+- 浣跨敤鏁板瓧杈撳叆妗嗭紙el-input-number锛�
+- 鏀寔姝ヨ繘璋冩暣
+- 鑷姩楠岃瘉杈撳叆鑼冨洿
+
+### 鎻愮ず淇℃伅
+- 棰勮鍏噷鏁板瓧娈典笅鏂规湁鎻愮ず鏂囧瓧
+- 璇存槑璇ュ瓧娈典负鑷姩璁$畻
+
+## 娉ㄦ剰浜嬮」
+
+1. **鍧愭爣绮惧害**锛氬缓璁娇鐢ㄩ珮绮惧害GPS璁惧鑾峰彇鍧愭爣
+2. **璺濈鑼冨洿**锛氶�傜敤浜庝腑鐭窛绂伙紝闀胯窛绂诲彲鑳芥湁璇樊
+3. **鍧愭爣绯荤粺**锛氫娇鐢╓GS84鍧愭爣绯伙紙GPS鏍囧噯锛�
+4. **鏁版嵁瀹屾暣鎬�**锛氬缓璁悓鏃跺~鍐欏湴鍧�鍜屽潗鏍囦俊鎭�
+5. **缃戠粶渚濊禆**锛氬墠绔绠楋紝鏃犻渶缃戠粶杩炴帴
+
+## 鏁呴殰鎺掗櫎
+
+### 璺濈鏄剧ず涓�0
+- 妫�鏌ュ潗鏍囨槸鍚﹀畬鏁磋緭鍏�
+- 楠岃瘉鍧愭爣鏄惁鍦ㄦ湁鏁堣寖鍥村唴
+- 纭鍧愭爣鏍煎紡姝g‘
+
+### 璺濈璁$畻涓嶅噯纭�
+- 妫�鏌ュ潗鏍囩簿搴︽槸鍚﹁冻澶�
+- 纭浣跨敤WGS84鍧愭爣绯�
+- 娉ㄦ剰闀胯窛绂昏绠楃殑璇樊
+
+### 鐣岄潰鏄剧ず寮傚父
+- 鍒锋柊椤甸潰閲嶈瘯
+- 妫�鏌ユ祻瑙堝櫒鍏煎鎬�
+- 娓呴櫎娴忚鍣ㄧ紦瀛�
+
+## 鎵╁睍鍔熻兘寤鸿
+
+1. **鍦板浘闆嗘垚**锛氶泦鎴愬湴鍥続PI杩涜鍧愭爣閫夋嫨
+2. **鍧愭爣杞崲**锛氭敮鎸佷笉鍚屽潗鏍囩郴缁熻浆鎹�
+3. **璺緞瑙勫垝**锛氶泦鎴愯矾寰勮鍒扐PI
+4. **鍘嗗彶杞ㄨ抗**锛氳褰曞疄闄呰椹惰建杩�
+5. **鍦扮悊鍥存爮**锛氳缃换鍔℃墽琛岃寖鍥�
diff --git a/ruoyi-ui/src/views/task/general/detail.vue b/ruoyi-ui/src/views/task/general/detail.vue
index 99fd176..379fff6 100644
--- a/ruoyi-ui/src/views/task/general/detail.vue
+++ b/ruoyi-ui/src/views/task/general/detail.vue
@@ -242,13 +242,24 @@
<el-dialog title="鍒嗛厤杞﹁締" :visible.sync="vehicleAssignOpen" width="600px" append-to-body>
<el-form ref="vehicleAssignForm" :model="vehicleAssignForm" :rules="vehicleAssignRules" label-width="80px">
<el-form-item label="杞﹁締" prop="vehicleIds">
- <el-select v-model="vehicleAssignForm.vehicleIds" placeholder="璇烽�夋嫨杞﹁締" multiple clearable>
+ <el-select v-model="vehicleAssignForm.vehicleIds" placeholder="璇烽�夋嫨杞﹁締" multiple clearable style="width: 100%">
<el-option
v-for="vehicle in availableVehicles"
:key="vehicle.vehicleId"
- :label="vehicle.vehicleNo + ' (' + vehicle.vehicleType + ')'"
+ :label="vehicle.vehicleNo + ' - ' + vehicle.deptName"
:value="vehicle.vehicleId"
- />
+ >
+ <div style="display: flex; justify-content: space-between; align-items: center;">
+ <div>
+ <div style="font-weight: bold; color: #303133;">{{ vehicle.vehicleNo }}</div>
+ <div style="font-size: 12px; color: #909399;">ID: {{ vehicle.vehicleId }}</div>
+ </div>
+ <div style="text-align: right;">
+ <div style="color: #67C23A; font-size: 13px;">{{ getVehicleTypeName(vehicle.vehicleType) }}</div>
+ <div style="color: #8492a6; font-size: 12px;">{{ vehicle.vehicleBrand }} {{ vehicle.vehicleModel }}</div>
+ </div>
+ </div>
+ </el-option>
</el-select>
</el-form-item>
<el-form-item label="澶囨敞" prop="remark">
@@ -552,6 +563,15 @@
} else {
return (size / 1024 / 1024).toFixed(2) + ' MB';
}
+ },
+ /** 鑾峰彇杞﹁締绫诲瀷鍚嶇О */
+ getVehicleTypeName(vehicleType) {
+ const typeDict = this.dict.type.sys_vehicle_type;
+ if (typeDict && typeDict.length > 0) {
+ const typeItem = typeDict.find(item => item.value === vehicleType);
+ return typeItem ? typeItem.label : vehicleType;
+ }
+ return vehicleType;
}
}
};
diff --git a/ruoyi-ui/src/views/task/general/index.vue b/ruoyi-ui/src/views/task/general/index.vue
index 9feb3cb..5c8c97c 100644
--- a/ruoyi-ui/src/views/task/general/index.vue
+++ b/ruoyi-ui/src/views/task/general/index.vue
@@ -94,7 +94,15 @@
<el-table v-loading="loading" :data="taskList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
- <el-table-column label="浠诲姟缂栧彿" align="center" prop="taskCode" />
+ <el-table-column label="浠诲姟缂栧彿" align="center" prop="taskCode">
+ <template slot-scope="scope">
+ <el-button
+ type="text"
+ @click="handleView(scope.row)"
+ v-hasPermi="['task:general:query']"
+ >{{ scope.row.taskCode }}</el-button>
+ </template>
+ </el-table-column>
<el-table-column label="浠诲姟绫诲瀷" align="center" prop="taskType">
<template slot-scope="scope">
<dict-tag :options="dict.type.sys_task_type" :value="scope.row.taskType"/>
@@ -105,9 +113,14 @@
<dict-tag :options="dict.type.sys_task_status" :value="scope.row.taskStatus"/>
</template>
</el-table-column>
- <el-table-column label="浠诲姟鎻忚堪" align="center" prop="taskDescription" show-overflow-tooltip />
<el-table-column label="鍑哄彂鍦板潃" align="center" prop="departureAddress" show-overflow-tooltip />
<el-table-column label="鐩殑鍦板潃" align="center" prop="destinationAddress" show-overflow-tooltip />
+ <el-table-column label="棰勮鍏噷鏁�" align="center" prop="estimatedDistance" width="120">
+ <template slot-scope="scope">
+ <span v-if="scope.row.estimatedDistance">{{ scope.row.estimatedDistance }} km</span>
+ <span v-else style="color: #C0C4CC;">--</span>
+ </template>
+ </el-table-column>
<el-table-column label="璁″垝寮�濮嬫椂闂�" align="center" prop="plannedStartTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.plannedStartTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
@@ -175,7 +188,7 @@
/>
<!-- 娣诲姞鎴栦慨鏀逛换鍔$鐞嗗璇濇 -->
- <el-dialog :title="title" :visible.sync="open" width="600px" append-to-body>
+ <el-dialog :title="title" :visible.sync="open" width="800px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="浠诲姟绫诲瀷" prop="taskType">
<el-select v-model="form.taskType" placeholder="璇烽�夋嫨浠诲姟绫诲瀷">
@@ -195,6 +208,86 @@
</el-form-item>
<el-form-item label="鐩殑鍦板潃" prop="destinationAddress">
<el-input v-model="form.destinationAddress" placeholder="璇疯緭鍏ョ洰鐨勫湴鍧�" />
+ </el-form-item>
+
+ <!-- GPS鍧愭爣淇℃伅 -->
+ <el-divider content-position="left">GPS鍧愭爣淇℃伅</el-divider>
+
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="鍑哄彂鍦扮粡搴�" prop="departureLongitude">
+ <el-input-number
+ v-model="form.departureLongitude"
+ :precision="7"
+ :step="0.0000001"
+ :min="-180"
+ :max="180"
+ placeholder="璇疯緭鍏ョ粡搴�"
+ style="width: 100%"
+ @change="calculateDistance"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鍑哄彂鍦扮含搴�" prop="departureLatitude">
+ <el-input-number
+ v-model="form.departureLatitude"
+ :precision="7"
+ :step="0.0000001"
+ :min="-90"
+ :max="90"
+ placeholder="璇疯緭鍏ョ含搴�"
+ style="width: 100%"
+ @change="calculateDistance"
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="鐩殑鍦扮粡搴�" prop="destinationLongitude">
+ <el-input-number
+ v-model="form.destinationLongitude"
+ :precision="7"
+ :step="0.0000001"
+ :min="-180"
+ :max="180"
+ placeholder="璇疯緭鍏ョ粡搴�"
+ style="width: 100%"
+ @change="calculateDistance"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鐩殑鍦扮含搴�" prop="destinationLatitude">
+ <el-input-number
+ v-model="form.destinationLatitude"
+ :precision="7"
+ :step="0.0000001"
+ :min="-90"
+ :max="90"
+ placeholder="璇疯緭鍏ョ含搴�"
+ style="width: 100%"
+ @change="calculateDistance"
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+
+ <el-form-item label="棰勮鍏噷鏁�" prop="estimatedDistance">
+ <el-input-number
+ v-model="form.estimatedDistance"
+ :precision="2"
+ :step="0.01"
+ :min="0"
+ placeholder="鑷姩璁$畻"
+ style="width: 200px"
+ :disabled="true"
+ />
+ <span style="margin-left: 10px; color: #909399; font-size: 12px;">
+ <i class="el-icon-info"></i> 鏍规嵁GPS鍧愭爣鑷姩璁$畻
+ </span>
</el-form-item>
<el-form-item label="璁″垝寮�濮嬫椂闂�" prop="plannedStartTime">
<el-date-picker clearable
@@ -398,6 +491,11 @@
taskDescription: null,
departureAddress: null,
destinationAddress: null,
+ departureLongitude: null,
+ departureLatitude: null,
+ destinationLongitude: null,
+ destinationLatitude: null,
+ estimatedDistance: null,
plannedStartTime: null,
plannedEndTime: null,
assigneeId: null,
@@ -529,6 +627,52 @@
cancelStatusChange() {
this.statusOpen = false;
this.statusForm = {};
+ },
+
+ /** 璁$畻GPS鍧愭爣璺濈 */
+ calculateDistance() {
+ if (this.form.departureLongitude && this.form.departureLatitude &&
+ this.form.destinationLongitude && this.form.destinationLatitude) {
+
+ // 楠岃瘉鍧愭爣鏈夋晥鎬�
+ if (this.isValidCoordinate(this.form.departureLatitude, this.form.departureLongitude) &&
+ this.isValidCoordinate(this.form.destinationLatitude, this.form.destinationLongitude)) {
+
+ // 浣跨敤Haversine鍏紡璁$畻璺濈
+ const distance = this.calculateHaversineDistance(
+ this.form.departureLatitude, this.form.departureLongitude,
+ this.form.destinationLatitude, this.form.destinationLongitude
+ );
+
+ this.form.estimatedDistance = Math.round(distance * 100) / 100; // 淇濈暀2浣嶅皬鏁�
+ } else {
+ this.form.estimatedDistance = 0;
+ }
+ } else {
+ this.form.estimatedDistance = 0;
+ }
+ },
+
+ /** 楠岃瘉GPS鍧愭爣鏄惁鏈夋晥 */
+ isValidCoordinate(latitude, longitude) {
+ return latitude >= -90 && latitude <= 90 && longitude >= -180 && longitude <= 180;
+ },
+
+ /** 浣跨敤Haversine鍏紡璁$畻涓ょ偣闂磋窛绂� */
+ calculateHaversineDistance(lat1, lon1, lat2, lon2) {
+ const R = 6371; // 鍦扮悆鍗婂緞锛堝叕閲岋級
+ const dLat = this.toRadians(lat2 - lat1);
+ const dLon = this.toRadians(lon2 - lon1);
+ const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
+ Math.cos(this.toRadians(lat1)) * Math.cos(this.toRadians(lat2)) *
+ Math.sin(dLon / 2) * Math.sin(dLon / 2);
+ const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
+ return R * c;
+ },
+
+ /** 瑙掑害杞姬搴� */
+ toRadians(degrees) {
+ return degrees * (Math.PI / 180);
}
}
};
diff --git "a/ruoyi-ui/src/views/task/general/\345\210\206\351\205\215\350\275\246\350\276\206\351\227\256\351\242\230\344\277\256\345\244\215\350\257\264\346\230\216.md" "b/ruoyi-ui/src/views/task/general/\345\210\206\351\205\215\350\275\246\350\276\206\351\227\256\351\242\230\344\277\256\345\244\215\350\257\264\346\230\216.md"
new file mode 100644
index 0000000..5b9448c
--- /dev/null
+++ "b/ruoyi-ui/src/views/task/general/\345\210\206\351\205\215\350\275\246\350\276\206\351\227\256\351\242\230\344\277\256\345\244\215\350\257\264\346\230\216.md"
@@ -0,0 +1,214 @@
+# 浠诲姟璇︽儏椤甸潰鍒嗛厤杞﹁締闂淇璇存槑
+
+## 闂鎻忚堪
+
+鍦ㄤ换鍔¤鎯呴〉闈㈢殑鍒嗛厤杞﹁締瀵硅瘽妗嗕腑锛屼笅鎷夊垪琛ㄤ腑娌℃湁鏄剧ず杞﹁締閫夐」锛屽鑷存棤娉曢�夋嫨杞﹁締杩涜鍒嗛厤銆�
+
+## 闂鍘熷洜
+
+1. **鍚庣Service灞傛湭瀹炵幇**锛歚SysTaskServiceImpl.getAvailableVehicles()` 鏂规硶鍙槸杩斿洖绌哄垪琛紝娌℃湁瀹為檯鏌ヨ杞﹁締鏁版嵁
+2. **缂哄皯渚濊禆娉ㄥ叆**锛氭病鏈夋敞鍏� `VehicleInfoMapper` 鏉ユ煡璇㈣溅杈嗕俊鎭�
+3. **鍓嶇鏄剧ず浼樺寲**锛氳溅杈嗛�夋嫨涓嬫媺妗嗙殑鏄剧ず鏍煎紡鍙互杩涗竴姝ヤ紭鍖�
+
+## 淇鏂规
+
+### 1. 鍚庣Service灞備慨澶�
+
+#### 娣诲姞渚濊禆娉ㄥ叆
+**鏂囦欢**锛歚SysTaskServiceImpl.java`
+
+```java
+// 娣诲姞瀵煎叆
+import com.ruoyi.system.mapper.VehicleInfoMapper;
+import com.ruoyi.system.domain.VehicleInfo;
+
+// 娣诲姞渚濊禆娉ㄥ叆
+@Autowired
+private VehicleInfoMapper vehicleInfoMapper;
+```
+
+#### 瀹炵幇getAvailableVehicles鏂规硶
+```java
+@Override
+public List<SysTaskVehicle> getAvailableVehicles(Long deptId, String taskType) {
+ List<SysTaskVehicle> availableVehicles = new ArrayList<>();
+
+ try {
+ // 鏌ヨ鎸囧畾閮ㄩ棬涓嬬姸鎬佷负姝e父鐨勮溅杈�
+ VehicleInfo queryParam = new VehicleInfo();
+ queryParam.setDeptId(deptId);
+ queryParam.setStatus("0"); // 0琛ㄧず姝e父鐘舵��
+
+ List<VehicleInfo> vehicles = vehicleInfoMapper.selectVehicleInfoList(queryParam);
+
+ // 杞崲涓篠ysTaskVehicle瀵硅薄
+ for (VehicleInfo vehicle : vehicles) {
+ SysTaskVehicle taskVehicle = new SysTaskVehicle();
+ taskVehicle.setVehicleId(vehicle.getVehicleId());
+ taskVehicle.setVehicleNo(vehicle.getVehicleNo());
+ taskVehicle.setVehicleType(vehicle.getVehicleType());
+ taskVehicle.setVehicleBrand(vehicle.getVehicleBrand());
+ taskVehicle.setVehicleModel(vehicle.getVehicleModel());
+ availableVehicles.add(taskVehicle);
+ }
+ } catch (Exception e) {
+ // 濡傛灉鏌ヨ澶辫触锛岃褰曟棩蹇楀苟杩斿洖绌哄垪琛�
+ System.err.println("鏌ヨ鍙敤杞﹁締澶辫触: " + e.getMessage());
+ }
+
+ return availableVehicles;
+}
+```
+
+### 2. 鍓嶇鐣岄潰浼樺寲
+
+#### 浼樺寲杞﹁締閫夋嫨涓嬫媺妗�
+**鏂囦欢**锛歚detail.vue`
+
+```vue
+<el-form-item label="杞﹁締" prop="vehicleIds">
+ <el-select v-model="vehicleAssignForm.vehicleIds" placeholder="璇烽�夋嫨杞﹁締" multiple clearable style="width: 100%">
+ <el-option
+ v-for="vehicle in availableVehicles"
+ :key="vehicle.vehicleId"
+ :label="vehicle.vehicleNo + ' - ' + getVehicleTypeName(vehicle.vehicleType)"
+ :value="vehicle.vehicleId"
+ >
+ <div style="display: flex; justify-content: space-between; align-items: center;">
+ <div>
+ <div style="font-weight: bold; color: #303133;">{{ vehicle.vehicleNo }}</div>
+ <div style="font-size: 12px; color: #909399;">ID: {{ vehicle.vehicleId }}</div>
+ </div>
+ <div style="text-align: right;">
+ <div style="color: #67C23A; font-size: 13px;">{{ getVehicleTypeName(vehicle.vehicleType) }}</div>
+ <div style="color: #8492a6; font-size: 12px;">{{ vehicle.vehicleBrand }} {{ vehicle.vehicleModel }}</div>
+ </div>
+ </div>
+ </el-option>
+ </el-select>
+</el-form-item>
+```
+
+#### 娣诲姞杞﹁締绫诲瀷鍚嶇О鏂规硶
+```javascript
+/** 鑾峰彇杞﹁締绫诲瀷鍚嶇О */
+getVehicleTypeName(vehicleType) {
+ const typeDict = this.dict.type.sys_vehicle_type;
+ if (typeDict && typeDict.length > 0) {
+ const typeItem = typeDict.find(item => item.value === vehicleType);
+ return typeItem ? typeItem.label : vehicleType;
+ }
+ return vehicleType;
+}
+```
+
+## 鎶�鏈疄鐜扮粏鑺�
+
+### 1. 鏁版嵁娴佺▼
+
+```
+鍓嶇璋冪敤 getAvailableVehicles(deptId, taskType)
+ 鈫�
+鍚庣Controller: /task/vehicle/available
+ 鈫�
+Service灞�: SysTaskServiceImpl.getAvailableVehicles()
+ 鈫�
+Mapper灞�: VehicleInfoMapper.selectVehicleInfoList()
+ 鈫�
+鏁版嵁搴撴煡璇�: tb_vehicle_info琛�
+ 鈫�
+鏁版嵁杞崲: VehicleInfo 鈫� SysTaskVehicle
+ 鈫�
+杩斿洖缁欏墠绔�
+```
+
+### 2. 鏌ヨ鏉′欢
+
+- **閮ㄩ棬ID**锛氬彧鏌ヨ鎸囧畾閮ㄩ棬鐨勮溅杈�
+- **杞﹁締鐘舵��**锛氬彧鏌ヨ鐘舵�佷负"0"锛堟甯革級鐨勮溅杈�
+- **浠诲姟绫诲瀷**锛氶鐣欏弬鏁帮紝鍙牴鎹换鍔$被鍨嬬瓫閫夊悎閫傜殑杞﹁締
+
+### 3. 鏁版嵁杞崲
+
+```java
+// VehicleInfo 鈫� SysTaskVehicle
+SysTaskVehicle taskVehicle = new SysTaskVehicle();
+taskVehicle.setVehicleId(vehicle.getVehicleId());
+taskVehicle.setVehicleNo(vehicle.getVehicleNo());
+taskVehicle.setVehicleType(vehicle.getVehicleType());
+taskVehicle.setVehicleBrand(vehicle.getVehicleBrand());
+taskVehicle.setVehicleModel(vehicle.getVehicleModel());
+```
+
+## 鐣岄潰鏁堟灉
+
+### 淇鍓�
+```
+鈹屸攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�
+鈹� 杞﹁締: [璇烽�夋嫨杞﹁締 鈻糫 鈹�
+鈹� 鈹屸攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹� 鈹�
+鈹� 鈹� (鏃犻�夐」) 鈹� 鈹�
+鈹� 鈹斺攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹� 鈹�
+鈹斺攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�
+```
+
+### 淇鍚�
+```
+鈹屸攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�
+鈹� 杞﹁締: [绮12345 - 鏁戞姢杞� 鈻糫 鈹�
+鈹� 鈹屸攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹� 鈹�
+鈹� 鈹� 绮12345 - 鏁戞姢杞� 鈹� 鈹�
+鈹� 鈹� 鈹屸攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹� 鈹屸攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹� 鈹� 鈹�
+鈹� 鈹� 鈹� 绮12345 鈹� 鈹� 鏁戞姢杞� 鈹� 鈹� 鈹�
+鈹� 鈹� 鈹� ID: 1 鈹� 鈹� 濂旈┌ S350 鈹� 鈹� 鈹�
+鈹� 鈹� 鈹斺攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹� 鈹斺攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹� 鈹� 鈹�
+鈹� 鈹� 绮67890 - 杞繍杞� 鈹� 鈹�
+鈹� 鈹� 鈹屸攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹� 鈹屸攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹� 鈹� 鈹�
+鈹� 鈹� 鈹� 绮67890 鈹� 鈹� 杞繍杞� 鈹� 鈹� 鈹�
+鈹� 鈹� 鈹� ID: 2 鈹� 鈹� 涓扮敯 娴风嫯 鈹� 鈹� 鈹�
+鈹� 鈹� 鈹斺攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹� 鈹斺攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹� 鈹� 鈹�
+鈹� 鈹斺攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹� 鈹�
+鈹斺攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�
+```
+
+## 鍔熻兘鐗规��
+
+### 1. 鏌ヨ鍔熻兘
+- **閮ㄩ棬绛涢��**锛氬彧鏄剧ず鎸囧畾閮ㄩ棬鐨勮溅杈�
+- **鐘舵�佺瓫閫�**锛氬彧鏄剧ず姝e父鐘舵�佺殑杞﹁締
+- **澶氶�夋敮鎸�**锛氭敮鎸侀�夋嫨澶氳締杞﹁繘琛屽垎閰�
+
+### 2. 鏄剧ず鍔熻兘
+- **璇︾粏淇℃伅**锛氭樉绀鸿溅鐗屽彿銆佽溅杈嗙被鍨嬨�佸搧鐗屽瀷鍙�
+- **绫诲瀷鏍囩**锛氳溅杈嗙被鍨嬩娇鐢ㄥ瓧鍏告爣绛炬樉绀�
+- **ID鏄剧ず**锛氭樉绀鸿溅杈咺D渚夸簬璇嗗埆
+- **缇庤甯冨眬**锛氫娇鐢ㄥ崱鐗囧紡甯冨眬灞曠ず杞﹁締淇℃伅
+
+### 3. 鐢ㄦ埛浣撻獙
+- **鎼滅储鍙嬪ソ**锛氭敮鎸佽緭鍏ユ悳绱㈠揩閫熷畾浣嶈溅杈�
+- **淇℃伅瀹屾暣**锛氭樉绀鸿溅杈嗙殑瀹屾暣淇℃伅
+- **鎿嶄綔渚挎嵎**锛氭敮鎸佸閫夊拰娓呯┖鎿嶄綔
+
+## 娉ㄦ剰浜嬮」
+
+1. **鏁版嵁渚濊禆**锛氶渶瑕佺‘淇濊溅杈嗘暟鎹瓨鍦ㄤ笖鐘舵�佹甯�
+2. **閮ㄩ棬鏉冮檺**锛氬彧鏄剧ず褰撳墠浠诲姟鎵�灞為儴闂ㄧ殑杞﹁締
+3. **寮傚父澶勭悊**锛氭煡璇㈠け璐ユ椂杩斿洖绌哄垪琛紝涓嶅奖鍝嶉〉闈㈡甯镐娇鐢�
+4. **鎬ц兘鑰冭檻**锛氬鏋滆溅杈嗘暟鎹緢澶氾紝鍙�冭檻鍒嗛〉鎴栨悳绱紭鍖�
+
+## 鍚庣画浼樺寲寤鸿
+
+1. **鎼滅储鍔熻兘**锛氭坊鍔犺溅杈嗘悳绱㈠姛鑳斤紝鏀寔鎸夎溅鐗屽彿銆佺被鍨嬫悳绱�
+2. **鍒嗛〉鍔犺浇**锛氬鏋滆溅杈嗗緢澶氾紝鍙�冭檻鍒嗛〉鍔犺浇
+3. **缂撳瓨浼樺寲**锛氬杞﹁締鍒楄〃杩涜缂撳瓨锛屽噺灏戦噸澶嶆煡璇�
+4. **鐘舵�佺鐞�**锛氭敮鎸佹寜杞﹁締鐘舵�佺瓫閫夛紙濡傦細绌洪棽銆佷娇鐢ㄤ腑锛�
+5. **璺濈璁$畻**锛氭牴鎹换鍔″湴鍧�璁$畻杞﹁締璺濈锛屼紭鍏堟帹鑽愬氨杩戣溅杈�
+
+## 鐩稿叧鏂囦欢
+
+- 鉁� `SysTaskServiceImpl.java` - Service灞傚疄鐜帮紙宸蹭慨澶嶏級
+- 鉁� `detail.vue` - 鍓嶇椤甸潰锛堝凡浼樺寲锛�
+- 鉁� `VehicleInfoMapper.java` - 杞﹁締淇℃伅Mapper
+- 鉁� `VehicleInfo.java` - 杞﹁締淇℃伅瀹炰綋绫�
+- 鉁� `SysTaskVehicle.java` - 浠诲姟杞﹁締鍏宠仈瀹炰綋绫�
+
diff --git a/ruoyi-ui/src/views/task/h5/create.vue b/ruoyi-ui/src/views/task/h5/create.vue
new file mode 100644
index 0000000..4da5f7b
--- /dev/null
+++ b/ruoyi-ui/src/views/task/h5/create.vue
@@ -0,0 +1,1513 @@
+<template>
+ <div class="h5-task-create">
+ <!-- 澶撮儴 -->
+ <div class="header">
+ <div class="header-left" @click="goBack">
+ <i class="el-icon-arrow-left"></i>
+ <span>杩斿洖</span>
+ </div>
+ <div class="header-title">鍒涘缓浠诲姟</div>
+ <div class="header-right"></div>
+ </div>
+
+ <!-- 琛ㄥ崟鍐呭 -->
+ <div class="form-container">
+ <el-form ref="taskForm" :model="taskForm" :rules="taskRules" label-width="100px">
+ <!-- 浠诲姟绫诲瀷 -->
+ <div class="form-section">
+ <div class="section-title">浠诲姟绫诲瀷</div>
+ <el-form-item prop="taskType">
+ <el-select v-model="taskForm.taskType" placeholder="璇烽�夋嫨浠诲姟绫诲瀷" style="width: 100%">
+ <el-option
+ v-for="dict in dict.type.sys_task_type"
+ :key="dict.value"
+ :label="dict.label"
+ :value="dict.value"
+ />
+ </el-select>
+ </el-form-item>
+ </div>
+
+ <!-- 浠诲姟鎻忚堪 -->
+ <div class="form-section">
+ <div class="section-title">浠诲姟鎻忚堪</div>
+ <el-form-item prop="taskDescription">
+ <el-input
+ v-model="taskForm.taskDescription"
+ type="textarea"
+ :rows="3"
+ placeholder="璇疯緭鍏ヤ换鍔℃弿杩�"
+ maxlength="200"
+ show-word-limit
+ />
+ </el-form-item>
+ </div>
+
+ <!-- 杞﹁締閫夋嫨 -->
+ <div class="form-section">
+ <div class="section-title">閫夋嫨杞﹁締</div>
+ <el-form-item prop="vehicleIds">
+ <div class="vehicle-selector" @click="showVehicleSelector = true">
+ <div v-if="selectedVehicles.length === 0" class="placeholder">
+ 璇烽�夋嫨杞﹁締
+ </div>
+ <div v-else class="selected-vehicles">
+ <div v-for="vehicle in selectedVehicles" :key="vehicle.vehicleId" class="vehicle-item">
+ <span class="vehicle-no">{{ vehicle.vehicleNo }}</span>
+ <span class="vehicle-type">{{ getVehicleTypeName(vehicle.vehicleType) }}</span>
+ <i class="el-icon-close" @click.stop="removeVehicle(vehicle.vehicleId)"></i>
+ </div>
+ </div>
+ <i class="el-icon-arrow-right"></i>
+ </div>
+ </el-form-item>
+ </div>
+
+ <!-- 鍦板潃閫夋嫨 -->
+ <div class="form-section">
+ <div class="section-title">鍑哄彂鍦板潃</div>
+ <el-form-item prop="departureAddress">
+ <div class="address-selector" @click="selectAddress('departure')">
+ <div v-if="!taskForm.departureAddress" class="placeholder">
+ 鐐瑰嚮閫夋嫨鍑哄彂鍦板潃
+ </div>
+ <div v-else class="address-content">
+ <i class="el-icon-location"></i>
+ <span>{{ taskForm.departureAddress }}</span>
+ </div>
+ <i class="el-icon-arrow-right"></i>
+ </div>
+ </el-form-item>
+ </div>
+
+ <div class="form-section">
+ <div class="section-title">鐩爣鍦板潃</div>
+ <el-form-item prop="destinationAddress">
+ <div class="address-selector" @click="selectAddress('destination')">
+ <div v-if="!taskForm.destinationAddress" class="placeholder">
+ 鐐瑰嚮閫夋嫨鐩爣鍦板潃
+ </div>
+ <div v-else class="address-content">
+ <i class="el-icon-location"></i>
+ <span>{{ taskForm.destinationAddress }}</span>
+ </div>
+ <i class="el-icon-arrow-right"></i>
+ </div>
+ </el-form-item>
+ </div>
+
+ <!-- 鏃堕棿閫夋嫨 -->
+ <div class="form-section">
+ <div class="section-title">璁″垝鏃堕棿</div>
+ <el-form-item prop="plannedStartTime">
+ <div class="time-label">寮�濮嬫椂闂�</div>
+ <el-date-picker
+ v-model="taskForm.plannedStartTime"
+ type="datetime"
+ placeholder="閫夋嫨寮�濮嬫椂闂�"
+ value-format="yyyy-MM-dd HH:mm:ss"
+ style="width: 100%"
+ />
+ </el-form-item>
+ <el-form-item prop="plannedEndTime">
+ <div class="time-label">缁撴潫鏃堕棿</div>
+ <el-date-picker
+ v-model="taskForm.plannedEndTime"
+ type="datetime"
+ placeholder="閫夋嫨缁撴潫鏃堕棿"
+ value-format="yyyy-MM-dd HH:mm:ss"
+ style="width: 100%"
+ />
+ </el-form-item>
+ </div>
+
+ <!-- 鎵ц浜洪�夋嫨 -->
+ <div class="form-section">
+ <div class="section-title">鎵ц浜�</div>
+ <el-form-item prop="assigneeId">
+ <el-select v-model="taskForm.assigneeId" placeholder="璇烽�夋嫨鎵ц浜�" style="width: 100%">
+ <el-option
+ v-for="user in userList"
+ :key="user.userId"
+ :label="user.nickName"
+ :value="user.userId"
+ />
+ </el-select>
+ </el-form-item>
+ </div>
+
+ <!-- 澶囨敞 -->
+ <div class="form-section">
+ <div class="section-title">澶囨敞</div>
+ <el-form-item prop="remark">
+ <el-input
+ v-model="taskForm.remark"
+ type="textarea"
+ :rows="2"
+ placeholder="璇疯緭鍏ュ娉ㄤ俊鎭�"
+ maxlength="100"
+ show-word-limit
+ />
+ </el-form-item>
+ </div>
+ </el-form>
+ </div>
+
+ <!-- 鎻愪氦鎸夐挳 -->
+ <div class="submit-container">
+ <el-button type="primary" size="large" @click="submitTask" :loading="submitting" style="width: 100%">
+ 鍒涘缓浠诲姟
+ </el-button>
+ </div>
+
+ <!-- 杞﹁締閫夋嫨寮圭獥 -->
+ <el-dialog
+ title="閫夋嫨杞﹁締"
+ :visible.sync="showVehicleSelector"
+ width="90%"
+ :close-on-click-modal="false"
+ class="vehicle-dialog"
+ :modal="false"
+ :append-to-body="true"
+ :top="'10vh'"
+ >
+ <div class="vehicle-list">
+ <div
+ v-for="vehicle in availableVehicles"
+ :key="vehicle.vehicleId"
+ class="vehicle-item"
+ :class="{ selected: isVehicleSelected(vehicle.vehicleId) }"
+ @click="toggleVehicle(vehicle)"
+ >
+ <div class="vehicle-info">
+ <div class="vehicle-no">{{ vehicle.vehicleNo }}</div>
+ <div class="vehicle-details">
+ <span class="vehicle-type">{{ getVehicleTypeName(vehicle.vehicleType) }}</span>
+ <span class="vehicle-brand">{{ vehicle.vehicleBrand }} {{ vehicle.vehicleModel }}</span>
+ </div>
+ <div class="vehicle-dept">{{ vehicle.deptName }}</div>
+ </div>
+ <div class="vehicle-status">
+ <i v-if="isVehicleSelected(vehicle.vehicleId)" class="el-icon-check selected-icon"></i>
+ <i v-else class="el-icon-circle-check-outline unselected-icon"></i>
+ </div>
+ </div>
+ </div>
+ <div slot="footer" class="dialog-footer">
+ <el-button @click="showVehicleSelector = false">鍙栨秷</el-button>
+ <el-button type="primary" @click="confirmVehicleSelection">纭畾</el-button>
+ </div>
+ </el-dialog>
+
+ <!-- 鍦板浘閫夋嫨寮圭獥 -->
+ <el-dialog
+ :title="addressDialogTitle"
+ :visible.sync="showMapSelector"
+ width="95%"
+ :close-on-click-modal="false"
+ class="map-dialog"
+ :modal="false"
+ :append-to-body="true"
+ :top="'5vh'"
+ @close="closeMapSelector"
+ >
+ <div class="address-selector-container">
+ <!-- 鍦板潃鎼滅储妗� -->
+ <div class="address-search">
+ <el-input
+ v-model="searchKeyword"
+ placeholder="璇疯緭鍏ュ湴鍧�杩涜鎼滅储"
+ @input="searchAddress"
+ clearable
+ class="search-input"
+ >
+ <i slot="prefix" class="el-icon-search"></i>
+ </el-input>
+ </div>
+
+ <!-- 鎼滅储缁撴灉鍒楄〃 -->
+ <div v-if="searchResults.length > 0" class="search-results">
+ <div class="results-title">鎼滅储缁撴灉</div>
+ <div class="result-list">
+ <div
+ v-for="(result, index) in searchResults"
+ :key="index"
+ class="result-item"
+ @click="selectSearchResult(result)"
+ >
+ <div class="result-address">{{ result.address }}</div>
+ <div class="result-detail">{{ result.detail }}</div>
+ </div>
+ </div>
+ </div>
+
+ <!-- 鍦板浘瀹瑰櫒 -->
+ <div class="map-container">
+ <div id="mapContainer" class="map"></div>
+ <div class="map-controls">
+ <el-button type="primary" size="small" @click="getCurrentLocation">
+ <i class="el-icon-location"></i> 褰撳墠浣嶇疆
+ </el-button>
+ </div>
+ </div>
+
+ <!-- 閫変腑鍦板潃淇℃伅 -->
+ <div v-if="selectedLocation && selectedAddress" class="selected-address-info">
+ <div class="info-title">閫変腑鍦板潃</div>
+ <div class="address-info">
+ <div class="address-text">{{ selectedAddress }}</div>
+ <div class="coordinates">鍧愭爣锛歿{ selectedLocation.lng.toFixed(6) }}, {{ selectedLocation.lat.toFixed(6) }}</div>
+ </div>
+ </div>
+ </div>
+ <div slot="footer" class="dialog-footer">
+ <el-button @click="closeMapSelector">鍙栨秷</el-button>
+ <el-button type="primary" @click="confirmAddressSelection" :disabled="!selectedLocation">
+ 纭閫夋嫨
+ </el-button>
+ </div>
+ </el-dialog>
+ </div>
+</template>
+
+<script>
+import { addTask, getAvailableVehicles } from "@/api/task";
+import { listUser } from "@/api/system/user";
+
+export default {
+ name: "H5TaskCreate",
+ dicts: ['sys_task_type', 'sys_vehicle_type'],
+ data() {
+ return {
+ // 琛ㄥ崟鏁版嵁
+ taskForm: {
+ taskType: '',
+ taskDescription: '',
+ vehicleIds: [],
+ departureAddress: '',
+ destinationAddress: '',
+ plannedStartTime: '',
+ plannedEndTime: '',
+ assigneeId: '',
+ remark: ''
+ },
+ // 琛ㄥ崟楠岃瘉瑙勫垯
+ taskRules: {
+ taskType: [
+ { required: true, message: "璇烽�夋嫨浠诲姟绫诲瀷", trigger: "change" }
+ ],
+ taskDescription: [
+ { required: true, message: "璇疯緭鍏ヤ换鍔℃弿杩�", trigger: "blur" }
+ ],
+ vehicleIds: [
+ { required: true, message: "璇烽�夋嫨杞﹁締", trigger: "change" }
+ ],
+ departureAddress: [
+ { required: true, message: "璇烽�夋嫨鍑哄彂鍦板潃", trigger: "change" }
+ ],
+ destinationAddress: [
+ { required: true, message: "璇烽�夋嫨鐩爣鍦板潃", trigger: "change" }
+ ],
+ plannedStartTime: [
+ { required: true, message: "璇烽�夋嫨寮�濮嬫椂闂�", trigger: "change" }
+ ],
+ plannedEndTime: [
+ { required: true, message: "璇烽�夋嫨缁撴潫鏃堕棿", trigger: "change" }
+ ],
+ assigneeId: [
+ { required: true, message: "璇烽�夋嫨鎵ц浜�", trigger: "change" }
+ ]
+ },
+ // 鐢ㄦ埛鍒楄〃
+ userList: [],
+ // 鍙敤杞﹁締鍒楄〃
+ availableVehicles: [],
+ // 閫変腑鐨勮溅杈�
+ selectedVehicles: [],
+ // 寮圭獥鎺у埗
+ showVehicleSelector: false,
+ showMapSelector: false,
+ currentAddressType: '', // 'departure' 鎴� 'destination'
+ // 鍦板浘鐩稿叧
+ map: null,
+ marker: null,
+ selectedLocation: null,
+ selectedAddress: '',
+ // 鍦板潃鎼滅储鐩稿叧
+ searchKeyword: '',
+ searchResults: [],
+ searchTimer: null,
+ // 鎻愪氦鐘舵��
+ submitting: false
+ };
+ },
+ computed: {
+ addressDialogTitle() {
+ return this.currentAddressType === 'departure' ? '閫夋嫨鍑哄彂鍦板潃' : '閫夋嫨鐩爣鍦板潃';
+ }
+ },
+ created() {
+ this.getUserList();
+ this.getAvailableVehicleList();
+ },
+ mounted() {
+ // 绛夊緟鍦板浘API鍔犺浇瀹屾垚鍚庡啀鍒濆鍖栧湴鍥�
+ this.waitForMapAPI();
+ },
+ methods: {
+ /** 绛夊緟鍦板浘API鍔犺浇瀹屾垚 */
+ waitForMapAPI() {
+ if (window.BMap) {
+ console.log('鐧惧害鍦板浘API宸插瓨鍦紝鐩存帴鍒濆鍖�');
+ this.$nextTick(() => {
+ this.initMap();
+ });
+ return;
+ }
+
+ console.log('寮�濮嬪姞杞界櫨搴﹀湴鍥続PI...');
+ this.loadMapConfig();
+ },
+
+ /** 鍔ㄦ�佸姞杞藉湴鍥鹃厤缃� */
+ loadMapConfig() {
+ // 妫�鏌ユ槸鍚﹀凡缁忓姞杞借繃鍦板浘閰嶇疆
+ if (window.BMapConfig) {
+ console.log('鍦板浘閰嶇疆宸插瓨鍦紝鐩存帴鍔犺浇API');
+ this.loadBMapAPI();
+ return;
+ }
+
+ // 鍔ㄦ�佸姞杞藉湴鍥鹃厤缃枃浠�
+ const script = document.createElement('script');
+ script.type = 'text/javascript';
+ script.src = '/map-config.js';
+ script.onload = () => {
+ console.log('鍦板浘閰嶇疆鏂囦欢鍔犺浇瀹屾垚');
+ this.loadBMapAPI();
+ };
+ script.onerror = (error) => {
+ console.error('鍦板浘閰嶇疆鏂囦欢鍔犺浇澶辫触:', error);
+ this.$message.error('鍦板浘閰嶇疆鍔犺浇澶辫触锛岃鍒锋柊椤甸潰閲嶈瘯');
+ };
+ document.head.appendChild(script);
+ },
+
+ /** 鍔犺浇鐧惧害鍦板浘API */
+ loadBMapAPI() {
+ if (window.BMap) {
+ console.log('鐧惧害鍦板浘API宸插瓨鍦�');
+ // 绛夊緟API瀹屽叏鍒濆鍖�
+ this.waitForBMapReady();
+ return;
+ }
+
+ console.log('寮�濮嬪姞杞界櫨搴﹀湴鍥続PI...');
+
+ // 鐩戝惉鍦板浘鍔犺浇瀹屾垚浜嬩欢
+ const handleMapLoaded = () => {
+ console.log('鏀跺埌鍦板浘鍔犺浇瀹屾垚浜嬩欢');
+ this.waitForBMapReady();
+ window.removeEventListener('bmapLoaded', handleMapLoaded);
+ window.removeEventListener('bmapError', handleMapError);
+ };
+
+ // 鐩戝惉鍦板浘鍔犺浇閿欒浜嬩欢
+ const handleMapError = (event) => {
+ console.error('鍦板浘API鍔犺浇澶辫触:', event.detail);
+ this.$message.error('鍦板浘鏈嶅姟鍔犺浇澶辫触锛岃鍒锋柊椤甸潰閲嶈瘯');
+ window.removeEventListener('bmapLoaded', handleMapLoaded);
+ window.removeEventListener('bmapError', handleMapError);
+ };
+
+ window.addEventListener('bmapLoaded', handleMapLoaded);
+ window.addEventListener('bmapError', handleMapError);
+
+ // 璁剧疆瓒呮椂锛屽鏋�10绉掑唴娌℃湁鍔犺浇瀹屾垚锛屾樉绀洪敊璇俊鎭�
+ setTimeout(() => {
+ if (!window.BMap) {
+ console.error('鍦板浘API鍔犺浇瓒呮椂');
+ this.$message.error('鍦板浘鏈嶅姟鍔犺浇瓒呮椂锛岃妫�鏌ョ綉缁滆繛鎺�');
+ window.removeEventListener('bmapLoaded', handleMapLoaded);
+ window.removeEventListener('bmapError', handleMapError);
+ }
+ }, 10000);
+ },
+
+ /** 绛夊緟鐧惧害鍦板浘API瀹屽叏鍑嗗灏辩华 */
+ waitForBMapReady() {
+ const checkReady = () => {
+ if (window.BMap && window.BMap.Map && window.BMap.Point && window.BMap.Marker) {
+ console.log('鐧惧害鍦板浘API瀹屽叏鍑嗗灏辩华');
+ this.$nextTick(() => {
+ this.initMap();
+ });
+ } else {
+ console.log('绛夊緟鐧惧害鍦板浘API瀹屽叏鍔犺浇...');
+ setTimeout(checkReady, 100);
+ }
+ };
+ checkReady();
+ },
+
+ /** 杩斿洖涓婁竴椤� */
+ goBack() {
+ this.$router.go(-1);
+ },
+
+ /** 鑾峰彇鐢ㄦ埛鍒楄〃 */
+ getUserList() {
+ listUser().then(response => {
+ this.userList = response.rows;
+ });
+ },
+
+ /** 鑾峰彇鍙敤杞﹁締鍒楄〃 */
+ getAvailableVehicleList() {
+ // 杩欓噷闇�瑕佷紶鍏ュ綋鍓嶇敤鎴风殑閮ㄩ棬ID锛屾殏鏃朵娇鐢ㄩ粯璁ゅ��
+ const deptId = this.$store.getters.deptId || 1;
+ getAvailableVehicles(deptId, null).then(response => {
+ this.availableVehicles = response.data || [];
+ });
+ },
+
+ /** 鑾峰彇杞﹁締绫诲瀷鍚嶇О */
+ getVehicleTypeName(vehicleType) {
+ const typeDict = this.dict.type.sys_vehicle_type;
+ if (typeDict && typeDict.length > 0) {
+ const typeItem = typeDict.find(item => item.value === vehicleType);
+ return typeItem ? typeItem.label : vehicleType;
+ }
+ return vehicleType;
+ },
+
+ /** 妫�鏌ヨ溅杈嗘槸鍚﹀凡閫変腑 */
+ isVehicleSelected(vehicleId) {
+ return this.selectedVehicles.some(v => v.vehicleId === vehicleId);
+ },
+
+ /** 鍒囨崲杞﹁締閫夋嫨鐘舵�� */
+ toggleVehicle(vehicle) {
+ const index = this.selectedVehicles.findIndex(v => v.vehicleId === vehicle.vehicleId);
+ if (index > -1) {
+ this.selectedVehicles.splice(index, 1);
+ } else {
+ this.selectedVehicles.push(vehicle);
+ }
+ },
+
+ /** 绉婚櫎杞﹁締 */
+ removeVehicle(vehicleId) {
+ const index = this.selectedVehicles.findIndex(v => v.vehicleId === vehicleId);
+ if (index > -1) {
+ this.selectedVehicles.splice(index, 1);
+ this.updateVehicleIds();
+ }
+ },
+
+ /** 纭杞﹁締閫夋嫨 */
+ confirmVehicleSelection() {
+ this.updateVehicleIds();
+ this.showVehicleSelector = false;
+ },
+
+ /** 鏇存柊杞﹁締ID鍒楄〃 */
+ updateVehicleIds() {
+ this.taskForm.vehicleIds = this.selectedVehicles.map(v => v.vehicleId);
+ },
+
+ /** 閫夋嫨鍦板潃 */
+ selectAddress(type) {
+ this.currentAddressType = type;
+ this.showMapSelector = true;
+ // 閲嶇疆鎼滅储鐘舵��
+ this.searchKeyword = '';
+ this.searchResults = [];
+ this.selectedLocation = null;
+ this.selectedAddress = '';
+ // 绛夊緟寮圭獥瀹屽叏鎵撳紑鍚庡啀鍒濆鍖栧湴鍥�
+ this.$nextTick(() => {
+ // 浣跨敤setTimeout纭繚寮圭獥鍔ㄧ敾瀹屾垚
+ setTimeout(() => {
+ this.initMap();
+ }, 300);
+ });
+ },
+
+ /** 鍒濆鍖栧湴鍥� */
+ initMap() {
+ if (!window.BMap) {
+ console.error('鐧惧害鍦板浘API鏈姞杞�');
+ this.$message.error('鍦板浘鏈嶅姟鍔犺浇澶辫触锛岃妫�鏌ョ綉缁滆繛鎺�');
+ return;
+ }
+
+ // 妫�鏌ュ湴鍥惧鍣ㄦ槸鍚﹀瓨鍦紝濡傛灉涓嶅瓨鍦ㄥ垯閲嶈瘯
+ const mapContainer = document.getElementById('mapContainer');
+ if (!mapContainer) {
+ console.log('鍦板浘瀹瑰櫒涓嶅瓨鍦紝500ms鍚庨噸璇�...');
+ setTimeout(() => {
+ this.initMap();
+ }, 500);
+ return;
+ }
+
+ // 妫�鏌ュ鍣ㄦ槸鍚︽湁灏哄
+ if (mapContainer.offsetWidth === 0 || mapContainer.offsetHeight === 0) {
+ console.log('鍦板浘瀹瑰櫒灏哄涓�0锛�500ms鍚庨噸璇�...');
+ setTimeout(() => {
+ this.initMap();
+ }, 500);
+ return;
+ }
+
+ try {
+ if (this.map) {
+ this.map.clearOverlays();
+ }
+
+ // 鍒涘缓鍦板浘瀹炰緥
+ this.map = new BMap.Map('mapContainer');
+ this.map.centerAndZoom(new BMap.Point(116.404, 39.915), 15);
+
+ // 娣诲姞鍦板浘鎺т欢
+ this.map.addControl(new BMap.NavigationControl());
+ this.map.addControl(new BMap.ScaleControl());
+ this.map.addControl(new BMap.OverviewMapControl());
+ this.map.addControl(new BMap.MapTypeControl());
+
+ // 鍚敤婊氳疆鏀惧ぇ缂╁皬
+ this.map.enableScrollWheelZoom(true);
+
+ // 娣诲姞鐐瑰嚮浜嬩欢
+ this.map.addEventListener('click', (e) => {
+ this.handleMapClick(e);
+ });
+
+ // 娣诲姞鏍囪
+ const center = this.map.getCenter();
+ this.marker = new BMap.Marker(center, {
+ enableDragging: true
+ });
+ this.map.addOverlay(this.marker);
+
+ // 鏍囪鎷栨嫿浜嬩欢
+ this.marker.addEventListener('dragend', (e) => {
+ this.handleMarkerDrag(e);
+ });
+
+ console.log('鍦板浘鍒濆鍖栨垚鍔�');
+ } catch (error) {
+ console.error('鍦板浘鍒濆鍖栧け璐�:', error);
+ this.$message.error('鍦板浘鍒濆鍖栧け璐ワ紝璇烽噸璇�');
+ }
+ },
+
+ /** 鍦板浘鐐瑰嚮浜嬩欢 */
+ handleMapClick(e) {
+ const point = e.latlng;
+ this.selectedLocation = { lng: point.lng, lat: point.lat };
+ this.marker.setPosition(point);
+ this.reverseGeocode(point.lng, point.lat);
+ },
+
+ /** 鏍囪鎷栨嫿浜嬩欢 */
+ handleMarkerDrag(e) {
+ const point = e.target.getPosition();
+ this.selectedLocation = { lng: point.lng, lat: point.lat };
+ this.reverseGeocode(point.lng, point.lat);
+ },
+
+ /** 閫嗗湴鐞嗙紪鐮� */
+ reverseGeocode(lng, lat) {
+ if (!window.BMap) {
+ console.error('鐧惧害鍦板浘API鏈姞杞�');
+ return;
+ }
+
+ try {
+ const geocoder = new BMap.Geocoder();
+ const point = new BMap.Point(lng, lat);
+ geocoder.getLocation(point, (result) => {
+ if (result) {
+ this.selectedAddress = result.address;
+ }
+ });
+ } catch (error) {
+ console.error('閫嗗湴鐞嗙紪鐮佸け璐�:', error);
+ }
+ },
+
+ /** 鑾峰彇褰撳墠浣嶇疆 */
+ getCurrentLocation() {
+ if (!window.BMap) {
+ this.$message.error('鍦板浘鏈嶅姟鏈姞杞�');
+ return;
+ }
+
+ if (!this.map) {
+ this.$message.error('鍦板浘鏈垵濮嬪寲');
+ return;
+ }
+
+ try {
+ const geolocation = new BMap.Geolocation();
+ geolocation.getCurrentPosition((result) => {
+ if (geolocation.getStatus() === BMAP_STATUS_SUCCESS) {
+ const point = result.point;
+ this.selectedLocation = { lng: point.lng, lat: point.lat };
+ if (this.marker) {
+ this.marker.setPosition(point);
+ }
+ this.map.setCenter(point);
+ this.map.setZoom(16);
+ this.reverseGeocode(point.lng, point.lat);
+ } else {
+ this.$message.error('瀹氫綅澶辫触锛岃鎵嬪姩閫夋嫨浣嶇疆');
+ }
+ });
+ } catch (error) {
+ console.error('鑾峰彇褰撳墠浣嶇疆澶辫触:', error);
+ this.$message.error('瀹氫綅澶辫触锛岃鎵嬪姩閫夋嫨浣嶇疆');
+ }
+ },
+
+ /** 鍦板潃鎼滅储 */
+ searchAddress() {
+ if (this.searchTimer) {
+ clearTimeout(this.searchTimer);
+ }
+
+ if (!this.searchKeyword.trim()) {
+ this.searchResults = [];
+ return;
+ }
+
+ this.searchTimer = setTimeout(() => {
+ this.performAddressSearch(this.searchKeyword);
+ }, 500);
+ },
+
+ /** 鎵ц鍦板潃鎼滅储 */
+ performAddressSearch(keyword) {
+ if (!window.BMap) {
+ this.$message.error('鍦板浘鏈嶅姟鏈姞杞�');
+ return;
+ }
+
+ if (!this.map) {
+ this.$message.error('鍦板浘鏈垵濮嬪寲');
+ return;
+ }
+
+ try {
+ const localSearch = new BMap.LocalSearch(this.map, {
+ onSearchComplete: (results) => {
+ this.searchResults = [];
+ if (localSearch.getStatus() === BMAP_STATUS_SUCCESS) {
+ for (let i = 0; i < results.getCurrentNumPois(); i++) {
+ const poi = results.getPoi(i);
+ this.searchResults.push({
+ address: poi.title,
+ detail: poi.address,
+ point: poi.point,
+ lng: poi.point.lng,
+ lat: poi.point.lat
+ });
+ }
+ }
+ }
+ });
+
+ localSearch.search(keyword);
+ } catch (error) {
+ console.error('鍦板潃鎼滅储澶辫触:', error);
+ this.$message.error('鍦板潃鎼滅储澶辫触锛岃閲嶈瘯');
+ }
+ },
+
+ /** 閫夋嫨鎼滅储缁撴灉 */
+ selectSearchResult(result) {
+ if (!window.BMap) {
+ this.$message.error('鍦板浘鏈嶅姟鏈姞杞�');
+ return;
+ }
+
+ try {
+ this.selectedLocation = {
+ lng: result.lng,
+ lat: result.lat
+ };
+ this.selectedAddress = result.address;
+
+ // 绉诲姩鍦板浘鍒伴�変腑浣嶇疆
+ if (this.map) {
+ const point = new BMap.Point(result.lng, result.lat);
+ this.map.setCenter(point);
+ this.map.setZoom(16);
+
+ // 鏇存柊鏍囪浣嶇疆
+ if (this.marker) {
+ this.marker.setPosition(point);
+ }
+ }
+
+ // 娓呯┖鎼滅储缁撴灉
+ this.searchResults = [];
+ this.searchKeyword = '';
+ } catch (error) {
+ console.error('閫夋嫨鎼滅储缁撴灉澶辫触:', error);
+ this.$message.error('閫夋嫨鍦板潃澶辫触锛岃閲嶈瘯');
+ }
+ },
+
+ /** 纭鍦板潃閫夋嫨 */
+ confirmAddressSelection() {
+ if (!this.selectedLocation || !this.selectedAddress) {
+ this.$message.warning('璇峰厛閫夋嫨浣嶇疆');
+ return;
+ }
+
+ // 璁剧疆閫変腑鐨勫湴鍧�鍒拌〃鍗�
+ if (this.currentAddressType === 'departure') {
+ this.taskForm.departureAddress = this.selectedAddress;
+ } else {
+ this.taskForm.destinationAddress = this.selectedAddress;
+ }
+
+ this.closeMapSelector();
+ },
+
+ /** 鍏抽棴鍦板浘閫夋嫨鍣� */
+ closeMapSelector() {
+ this.showMapSelector = false;
+ // 娓呯悊鍦板浘瀹炰緥
+ if (this.map) {
+ this.map.clearOverlays();
+ this.map = null;
+ }
+ this.marker = null;
+ this.selectedLocation = null;
+ this.selectedAddress = '';
+ this.searchResults = [];
+ this.searchKeyword = '';
+ },
+
+ /** 鎻愪氦浠诲姟 */
+ submitTask() {
+ this.$refs.taskForm.validate(valid => {
+ if (valid) {
+ this.submitting = true;
+
+ // 鍑嗗鎻愪氦鏁版嵁
+ const submitData = {
+ ...this.taskForm,
+ vehicleIds: this.taskForm.vehicleIds // 鐩存帴浼犻�掓暟缁勶紝涓嶉渶瑕佽浆鎹负瀛楃涓�
+ };
+
+ addTask(submitData).then(response => {
+ this.$message.success('浠诲姟鍒涘缓鎴愬姛');
+ this.submitting = false;
+ // 璺宠浆鍒颁换鍔″垪琛ㄦ垨璇︽儏椤�
+ this.$router.push('/task/general');
+ }).catch(error => {
+ this.$message.error('浠诲姟鍒涘缓澶辫触锛�' + (error.message || '鏈煡閿欒'));
+ this.submitting = false;
+ });
+ }
+ });
+ }
+ }
+};
+</script>
+
+<style scoped>
+.h5-task-create {
+ min-height: 100vh;
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ padding-bottom: 100px;
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
+}
+
+/* 澶撮儴鏍峰紡 */
+.header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ height: 60px;
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ color: white;
+ padding: 0 20px;
+ position: sticky;
+ top: 0;
+ z-index: 100;
+ box-shadow: 0 2px 20px rgba(0,0,0,0.1);
+}
+
+.header-left {
+ display: flex;
+ align-items: center;
+ cursor: pointer;
+ padding: 8px 12px;
+ border-radius: 20px;
+ background: rgba(255,255,255,0.2);
+ backdrop-filter: blur(10px);
+ transition: all 0.3s ease;
+}
+
+.header-left:hover {
+ background: rgba(255,255,255,0.3);
+ transform: translateX(-2px);
+}
+
+.header-left i {
+ margin-right: 6px;
+ font-size: 18px;
+}
+
+.header-title {
+ font-size: 20px;
+ font-weight: 600;
+ letter-spacing: 0.5px;
+}
+
+/* 琛ㄥ崟瀹瑰櫒 */
+.form-container {
+ padding: 20px;
+}
+
+.form-section {
+ background: rgba(255,255,255,0.95);
+ backdrop-filter: blur(20px);
+ border-radius: 16px;
+ margin-bottom: 20px;
+ padding: 20px;
+ box-shadow: 0 8px 32px rgba(0,0,0,0.1);
+ border: 1px solid rgba(255,255,255,0.2);
+ transition: all 0.3s ease;
+}
+
+.form-section:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 12px 40px rgba(0,0,0,0.15);
+}
+
+.section-title {
+ font-size: 18px;
+ font-weight: 600;
+ color: #2c3e50;
+ margin-bottom: 20px;
+ padding-bottom: 12px;
+ border-bottom: 2px solid #e8f4fd;
+ position: relative;
+}
+
+.section-title::after {
+ content: '';
+ position: absolute;
+ bottom: -2px;
+ left: 0;
+ width: 40px;
+ height: 2px;
+ background: linear-gradient(90deg, #667eea, #764ba2);
+ border-radius: 1px;
+}
+
+.time-label {
+ font-size: 15px;
+ color: #5a6c7d;
+ margin-bottom: 10px;
+ font-weight: 500;
+}
+
+/* 杞﹁締閫夋嫨鍣� */
+.vehicle-selector {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 16px;
+ border: 2px solid #e8f4fd;
+ border-radius: 12px;
+ background: linear-gradient(135deg, #f8fbff 0%, #f0f9ff 100%);
+ cursor: pointer;
+ min-height: 24px;
+ transition: all 0.3s ease;
+}
+
+.vehicle-selector:hover {
+ border-color: #667eea;
+ background: linear-gradient(135deg, #f0f9ff 0%, #e8f4fd 100%);
+ transform: translateY(-1px);
+}
+
+.placeholder {
+ color: #a0aec0;
+ font-size: 15px;
+}
+
+.selected-vehicles {
+ flex: 1;
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+}
+
+.vehicle-item {
+ display: inline-flex;
+ align-items: center;
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ color: white;
+ border-radius: 20px;
+ padding: 6px 12px;
+ font-size: 13px;
+ font-weight: 500;
+ box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3);
+ transition: all 0.3s ease;
+}
+
+.vehicle-item:hover {
+ transform: scale(1.05);
+ box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
+}
+
+.vehicle-no {
+ font-weight: 600;
+ margin-right: 6px;
+}
+
+.vehicle-type {
+ opacity: 0.9;
+ margin-right: 6px;
+}
+
+.vehicle-item .el-icon-close {
+ cursor: pointer;
+ margin-left: 6px;
+ padding: 2px;
+ border-radius: 50%;
+ background: rgba(255,255,255,0.2);
+ transition: all 0.3s ease;
+}
+
+.vehicle-item .el-icon-close:hover {
+ background: rgba(255,255,255,0.3);
+ transform: scale(1.1);
+}
+
+/* 鍦板潃閫夋嫨鍣� */
+.address-selector {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 16px;
+ border: 2px solid #e8f4fd;
+ border-radius: 12px;
+ background: linear-gradient(135deg, #f8fbff 0%, #f0f9ff 100%);
+ cursor: pointer;
+ min-height: 24px;
+ transition: all 0.3s ease;
+}
+
+.address-selector:hover {
+ border-color: #667eea;
+ background: linear-gradient(135deg, #f0f9ff 0%, #e8f4fd 100%);
+ transform: translateY(-1px);
+}
+
+.address-content {
+ display: flex;
+ align-items: center;
+ flex: 1;
+}
+
+.address-content i {
+ margin-right: 10px;
+ color: #667eea;
+ font-size: 16px;
+}
+
+/* 鎻愪氦鎸夐挳瀹瑰櫒 */
+.submit-container {
+ position: fixed;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ padding: 20px;
+ background: rgba(255,255,255,0.95);
+ backdrop-filter: blur(20px);
+ border-top: 1px solid rgba(255,255,255,0.2);
+ box-shadow: 0 -8px 32px rgba(0,0,0,0.1);
+}
+
+/* 杞﹁締閫夋嫨寮圭獥 */
+.vehicle-dialog .el-dialog {
+ border-radius: 16px;
+ overflow: hidden;
+ max-height: 80vh;
+ display: flex;
+ flex-direction: column;
+}
+
+.vehicle-dialog .el-dialog__body {
+ padding: 0;
+ flex: 1;
+ overflow: hidden;
+ display: flex;
+ flex-direction: column;
+}
+
+.vehicle-dialog .el-dialog__footer {
+ padding: 15px 20px;
+ background: white;
+ border-top: 1px solid #e8f4fd;
+ flex-shrink: 0;
+}
+
+.vehicle-list {
+ flex: 1;
+ overflow-y: auto;
+ background: #f8fbff;
+ max-height: 60vh;
+}
+
+.vehicle-item {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 20px;
+ border-bottom: 1px solid #e8f4fd;
+ cursor: pointer;
+ transition: all 0.3s ease;
+ background: white;
+ margin: 0;
+}
+
+.vehicle-item:hover {
+ background: linear-gradient(135deg, #f0f9ff 0%, #e8f4fd 100%);
+ transform: translateX(4px);
+}
+
+.vehicle-item.selected {
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ color: white;
+ border-left: 4px solid #4facfe;
+}
+
+.vehicle-info {
+ flex: 1;
+}
+
+.vehicle-no {
+ font-size: 17px;
+ font-weight: 600;
+ color: #2c3e50;
+ margin-bottom: 6px;
+ background: #f0f9ff;
+ padding: 4px 8px;
+ border-radius: 4px;
+ display: inline-block;
+ border: 1px solid #e8f4fd;
+}
+
+.vehicle-item.selected .vehicle-no {
+ color: white;
+ background: rgba(255,255,255,0.2);
+ border-color: rgba(255,255,255,0.3);
+}
+
+.vehicle-details {
+ font-size: 14px;
+ color: #5a6c7d;
+ margin-bottom: 4px;
+}
+
+.vehicle-item.selected .vehicle-details {
+ color: rgba(255,255,255,0.9);
+}
+
+.vehicle-dept {
+ font-size: 12px;
+ color: #999;
+}
+
+.vehicle-item.selected .vehicle-dept {
+ color: rgba(255,255,255,0.7);
+}
+
+.vehicle-status {
+ margin-left: 15px;
+}
+
+.selected-icon {
+ color: #4facfe;
+ font-size: 24px;
+}
+
+.unselected-icon {
+ color: #c0c4cc;
+ font-size: 24px;
+}
+
+/* 鍦板浘寮圭獥 */
+.map-dialog .el-dialog {
+ border-radius: 16px;
+ overflow: hidden;
+ max-height: 90vh;
+ display: flex;
+ flex-direction: column;
+}
+
+.map-dialog .el-dialog__body {
+ padding: 0;
+ flex: 1;
+ overflow: hidden;
+ display: flex;
+ flex-direction: column;
+}
+
+.map-dialog .el-dialog__footer {
+ padding: 15px 20px;
+ background: white;
+ border-top: 1px solid #e8f4fd;
+ flex-shrink: 0;
+}
+
+.address-selector-container {
+ background: #f8fbff;
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+}
+
+/* 鍦板潃鎼滅储 */
+.address-search {
+ padding: 20px;
+ background: white;
+ border-bottom: 1px solid #e8f4fd;
+}
+
+.search-input {
+ width: 100%;
+}
+
+.search-input .el-input__inner {
+ border-radius: 25px;
+ border: 2px solid #e8f4fd;
+ padding-left: 40px;
+ font-size: 15px;
+ transition: all 0.3s ease;
+}
+
+.search-input .el-input__inner:focus {
+ border-color: #667eea;
+ box-shadow: 0 0 0 2px rgba(102, 126, 234, 0.1);
+}
+
+.search-input .el-input__prefix {
+ left: 12px;
+ color: #667eea;
+}
+
+/* 鎼滅储缁撴灉 */
+.search-results {
+ background: white;
+ border-bottom: 1px solid #e8f4fd;
+ max-height: 30vh;
+ min-height: 100px;
+ overflow-y: auto;
+ flex-shrink: 0;
+}
+
+.results-title {
+ padding: 15px 20px 10px;
+ font-size: 14px;
+ font-weight: 600;
+ color: #2c3e50;
+ background: #f8fbff;
+ border-bottom: 1px solid #e8f4fd;
+}
+
+.result-list {
+ padding: 0;
+}
+
+.result-item {
+ padding: 15px 20px;
+ border-bottom: 1px solid #f0f9ff;
+ cursor: pointer;
+ transition: all 0.3s ease;
+}
+
+.result-item:hover {
+ background: linear-gradient(135deg, #f0f9ff 0%, #e8f4fd 100%);
+ transform: translateX(4px);
+}
+
+.result-item:last-child {
+ border-bottom: none;
+}
+
+.result-address {
+ font-size: 15px;
+ font-weight: 600;
+ color: #2c3e50;
+ margin-bottom: 4px;
+}
+
+.result-detail {
+ font-size: 13px;
+ color: #5a6c7d;
+ opacity: 0.8;
+}
+
+.map-container {
+ position: relative;
+ height: 40vh;
+ min-height: 300px;
+ max-height: 500px;
+ background: #f0f9ff;
+ flex-shrink: 0;
+}
+
+.map {
+ width: 100%;
+ height: 100%;
+}
+
+.map-controls {
+ position: absolute;
+ top: 15px;
+ right: 15px;
+ display: flex;
+ gap: 12px;
+ z-index: 1000;
+}
+
+.map-controls .el-button {
+ border-radius: 20px;
+ padding: 8px 16px;
+ font-weight: 500;
+ box-shadow: 0 4px 12px rgba(0,0,0,0.15);
+ backdrop-filter: blur(10px);
+}
+
+/* 閫変腑鍦板潃淇℃伅 */
+.selected-address-info {
+ padding: 15px 20px;
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ color: white;
+ flex-shrink: 0;
+ max-height: 20vh;
+ overflow-y: auto;
+}
+
+.info-title {
+ font-size: 14px;
+ font-weight: 600;
+ margin-bottom: 10px;
+ opacity: 0.9;
+}
+
+.address-info {
+ background: rgba(255,255,255,0.1);
+ border-radius: 8px;
+ padding: 12px;
+ backdrop-filter: blur(10px);
+}
+
+.address-text {
+ font-size: 15px;
+ font-weight: 600;
+ margin-bottom: 6px;
+ line-height: 1.4;
+}
+
+.coordinates {
+ font-size: 12px;
+ opacity: 0.8;
+ font-family: 'Courier New', monospace;
+}
+
+/* 鍝嶅簲寮忚璁� */
+@media (max-width: 768px) {
+ .form-container {
+ padding: 15px;
+ }
+
+ .form-section {
+ padding: 16px;
+ margin-bottom: 16px;
+ border-radius: 12px;
+ }
+
+ .section-title {
+ font-size: 16px;
+ }
+
+ .header {
+ height: 56px;
+ padding: 0 16px;
+ }
+
+ .header-title {
+ font-size: 18px;
+ }
+
+ .submit-container {
+ padding: 16px;
+ }
+
+ /* 寮圭獥鍝嶅簲寮� */
+ .vehicle-dialog .el-dialog,
+ .map-dialog .el-dialog {
+ width: 95% !important;
+ margin: 0 auto;
+ }
+
+ .vehicle-list {
+ max-height: 50vh;
+ }
+
+ .map-container {
+ height: 35vh;
+ min-height: 250px;
+ }
+
+ .search-results {
+ max-height: 25vh;
+ }
+}
+
+@media (max-width: 480px) {
+ .form-container {
+ padding: 12px;
+ }
+
+ .form-section {
+ padding: 14px;
+ margin-bottom: 14px;
+ }
+
+ .vehicle-selector,
+ .address-selector {
+ padding: 14px;
+ }
+}
+
+/* Element UI 鏍峰紡瑕嗙洊 */
+.el-form-item {
+ margin-bottom: 20px;
+}
+
+.el-form-item__label {
+ font-weight: 600;
+ color: #2c3e50;
+ font-size: 15px;
+}
+
+.el-textarea__inner {
+ border-radius: 8px;
+ border: 2px solid #e8f4fd;
+ transition: all 0.3s ease;
+}
+
+.el-textarea__inner:focus {
+ border-color: #667eea;
+ box-shadow: 0 0 0 2px rgba(102, 126, 234, 0.1);
+}
+
+.el-select {
+ width: 100%;
+}
+
+.el-select .el-input__inner {
+ border-radius: 8px;
+ border: 2px solid #e8f4fd;
+ transition: all 0.3s ease;
+}
+
+.el-select .el-input__inner:focus {
+ border-color: #667eea;
+ box-shadow: 0 0 0 2px rgba(102, 126, 234, 0.1);
+}
+
+.el-date-editor {
+ width: 100%;
+}
+
+.el-date-editor .el-input__inner {
+ border-radius: 8px;
+ border: 2px solid #e8f4fd;
+ transition: all 0.3s ease;
+}
+
+.el-date-editor .el-input__inner:focus {
+ border-color: #667eea;
+ box-shadow: 0 0 0 2px rgba(102, 126, 234, 0.1);
+}
+
+.el-button--primary {
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ border: none;
+ border-radius: 25px;
+ padding: 14px 30px;
+ font-size: 16px;
+ font-weight: 600;
+ letter-spacing: 0.5px;
+ box-shadow: 0 8px 25px rgba(102, 126, 234, 0.3);
+ transition: all 0.3s ease;
+}
+
+.el-button--primary:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 12px 35px rgba(102, 126, 234, 0.4);
+}
+
+.el-button--primary:active {
+ transform: translateY(0);
+}
+
+/* 寮圭獥鏍峰紡浼樺寲 */
+.el-dialog__header {
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ color: white;
+ padding: 20px;
+ border-radius: 16px 16px 0 0;
+}
+
+.el-dialog__title {
+ font-weight: 600;
+ font-size: 18px;
+}
+
+.el-dialog__headerbtn .el-dialog__close {
+ color: white;
+ font-size: 20px;
+}
+
+.el-dialog__footer {
+ padding: 20px;
+ background: #f8fbff;
+ border-radius: 0 0 16px 16px;
+}
+
+/* 婊氬姩鏉℃牱寮� */
+.vehicle-list::-webkit-scrollbar {
+ width: 6px;
+}
+
+.vehicle-list::-webkit-scrollbar-track {
+ background: #f1f1f1;
+ border-radius: 3px;
+}
+
+.vehicle-list::-webkit-scrollbar-thumb {
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ border-radius: 3px;
+}
+
+.vehicle-list::-webkit-scrollbar-thumb:hover {
+ background: linear-gradient(135deg, #5a6fd8 0%, #6a4190 100%);
+}
+</style>
diff --git a/ruoyi-ui/src/views/task/vehicle/README.md b/ruoyi-ui/src/views/task/vehicle/README.md
new file mode 100644
index 0000000..9f0b242
--- /dev/null
+++ b/ruoyi-ui/src/views/task/vehicle/README.md
@@ -0,0 +1,117 @@
+# 浠诲姟杞﹁締鍏宠仈绠$悊鍔熻兘璇存槑
+
+## 鍔熻兘姒傝堪
+
+浠诲姟杞﹁締鍏宠仈绠$悊妯″潡鎻愪緵浜嗗畬鏁寸殑杞﹁締涓庝换鍔″叧鑱斿叧绯荤殑绠$悊鍔熻兘锛屽寘鎷細
+
+- 杞﹁締浠诲姟鍏宠仈鐨勫鍒犳敼鏌�
+- 杞﹁締鍒嗛厤鍜屽彇娑堝垎閰�
+- 鎵归噺杞﹁締鍒嗛厤
+- 鍏宠仈鐘舵�佺鐞�
+- 鏁版嵁瀵煎嚭鍔熻兘
+
+## 涓昏鍔熻兘
+
+### 1. 鍏宠仈绠$悊
+- **鏂板鍏宠仈**锛氭墜鍔ㄥ垱寤轰换鍔′笌杞﹁締鐨勫叧鑱斿叧绯�
+- **淇敼鍏宠仈**锛氭洿鏂板叧鑱斾俊鎭紝濡傜姸鎬併�佸娉ㄧ瓑
+- **鍒犻櫎鍏宠仈**锛氱Щ闄や换鍔′笌杞﹁締鐨勫叧鑱斿叧绯�
+- **鎵归噺鍒犻櫎**锛氭敮鎸佹壒閲忓垹闄ゅ涓叧鑱斿叧绯�
+
+### 2. 杞﹁締鍒嗛厤
+- **鍗曚釜鍒嗛厤**锛氫负浠诲姟鍒嗛厤鍗曚釜杞﹁締
+- **鎵归噺鍒嗛厤**锛氫负浠诲姟鍚屾椂鍒嗛厤澶氫釜杞﹁締
+- **鍙栨秷鍒嗛厤**锛氬彇娑堝凡鍒嗛厤鐨勮溅杈�
+
+### 3. 鐘舵�佺鐞�
+- **鐘舵�佸彉鏇�**锛氭洿鏂拌溅杈嗗湪浠诲姟涓殑鎵ц鐘舵��
+- **鐘舵�佺被鍨�**锛�
+ - 宸插垎閰� (ASSIGNED)
+ - 鎵ц涓� (ACTIVE)
+ - 宸插畬鎴� (COMPLETED)
+ - 宸插彇娑� (CANCELLED)
+
+### 4. 鏌ヨ鍔熻兘
+- **澶氭潯浠舵煡璇�**锛氭敮鎸佹寜浠诲姟ID銆佽溅杈咺D銆佽溅鐗屽彿銆佺姸鎬併�佸垎閰嶄汉绛夋潯浠舵煡璇�
+- **鍒嗛〉鏄剧ず**锛氭敮鎸佸垎椤垫祻瑙堝叧鑱旀暟鎹�
+- **鎺掑簭鍔熻兘**锛氭敮鎸佹寜鍒嗛厤鏃堕棿绛夊瓧娈垫帓搴�
+
+### 5. 鏁版嵁瀵煎嚭
+- **Excel瀵煎嚭**锛氭敮鎸佸皢鏌ヨ缁撴灉瀵煎嚭涓篍xcel鏂囦欢
+- **鑷畾涔夊鍑�**锛氭敮鎸佹寜鏌ヨ鏉′欢瀵煎嚭鐗瑰畾鏁版嵁
+
+## 鏉冮檺閰嶇疆
+
+绯荤粺鎻愪緵浜嗙粏绮掑害鐨勬潈闄愭帶鍒讹細
+
+- `task:vehicle:view` - 鏌ョ湅杞﹁締鍏宠仈椤甸潰
+- `task:vehicle:list` - 鏌ヨ杞﹁締鍏宠仈鍒楄〃
+- `task:vehicle:query` - 鏌ヨ杞﹁締鍏宠仈璇︽儏
+- `task:vehicle:add` - 鏂板杞﹁締鍏宠仈
+- `task:vehicle:edit` - 淇敼杞﹁締鍏宠仈
+- `task:vehicle:remove` - 鍒犻櫎杞﹁締鍏宠仈
+- `task:vehicle:assign` - 鍒嗛厤杞﹁締
+- `task:vehicle:export` - 瀵煎嚭杞﹁締鍏宠仈鏁版嵁
+
+## 浣跨敤娴佺▼
+
+### 1. 鏌ョ湅鍏宠仈鍒楄〃
+1. 杩涘叆"浠诲姟绠$悊" -> "杞﹁締绠$悊"椤甸潰
+2. 绯荤粺鑷姩鍔犺浇鎵�鏈夎溅杈嗕换鍔″叧鑱旀暟鎹�
+3. 鍙娇鐢ㄦ悳绱㈡潯浠剁瓫閫夋暟鎹�
+
+### 2. 鏂板鍏宠仈
+1. 鐐瑰嚮"鏂板"鎸夐挳
+2. 濉啓浠诲姟ID銆佽溅杈咺D銆佺姸鎬佺瓑淇℃伅
+3. 鐐瑰嚮"纭畾"淇濆瓨
+
+### 3. 鍒嗛厤杞﹁締
+1. 鍦ㄤ换鍔¤鎯呴〉闈㈢偣鍑�"鍒嗛厤杞﹁締"
+2. 閫夋嫨瑕佸垎閰嶇殑杞﹁締锛堟敮鎸佸閫夛級
+3. 濉啓鍒嗛厤澶囨敞
+4. 纭鍒嗛厤
+
+### 4. 鐘舵�佸彉鏇�
+1. 鍦ㄥ叧鑱斿垪琛ㄤ腑鐐瑰嚮"鐘舵�佸彉鏇�"
+2. 閫夋嫨鏂扮殑鐘舵��
+3. 纭鍙樻洿
+
+### 5. 鏁版嵁瀵煎嚭
+1. 璁剧疆鏌ヨ鏉′欢锛堝彲閫夛級
+2. 鐐瑰嚮"瀵煎嚭"鎸夐挳
+3. 绯荤粺鐢熸垚Excel鏂囦欢渚涗笅杞�
+
+## 娉ㄦ剰浜嬮」
+
+1. **鍞竴鎬х害鏉�**锛氬悓涓�浠诲姟鍜岃溅杈嗗彧鑳芥湁涓�涓叧鑱斿叧绯�
+2. **鐘舵�佹祦杞�**锛氱姸鎬佸彉鏇村簲閬靛惊涓氬姟閫昏緫
+3. **鏉冮檺鎺у埗**锛氱‘淇濈敤鎴锋湁鐩稿簲鏉冮檺鎵嶈兘鎵ц鎿嶄綔
+4. **鏁版嵁瀹屾暣鎬�**锛氬垹闄ゅ叧鑱斿墠璇风‘璁や笉浼氬奖鍝嶄笟鍔�
+
+## 鎶�鏈疄鐜�
+
+### 鍚庣鏋舵瀯
+- **Controller灞�**锛歚SysTaskVehicleManagementController`
+- **Service灞�**锛歚ISysTaskVehicleService` 鍜� `SysTaskVehicleServiceImpl`
+- **Mapper灞�**锛歚SysTaskVehicleMapper`
+- **瀹炰綋绫�**锛歚SysTaskVehicle`
+
+### 鍓嶇鏋舵瀯
+- **椤甸潰缁勪欢**锛歚/views/task/vehicle/index.vue`
+- **API鎺ュ彛**锛歚/api/task.js`
+- **璺敱閰嶇疆**锛氶渶瑕佸湪璺敱涓坊鍔犺溅杈嗙鐞嗛〉闈�
+
+### 鏁版嵁搴撹璁�
+- **涓昏〃**锛歚sys_task_vehicle`
+- **鍏宠仈琛�**锛歚sys_task`銆乣tb_vehicle_info`
+- **瀛楀吀琛�**锛歚sys_dict_type`銆乣sys_dict_data`
+
+## 鎵╁睍鍔熻兘
+
+绯荤粺鏀寔浠ヤ笅鎵╁睍锛�
+
+1. **杞﹁締鍙敤鎬ф鏌�**锛氬湪鍒嗛厤鍓嶆鏌ヨ溅杈嗘槸鍚﹀彲鐢�
+2. **鑷姩鍒嗛厤绠楁硶**锛氭牴鎹换鍔$被鍨嬪拰杞﹁締绫诲瀷鑷姩鎺ㄨ崘杞﹁締
+3. **鍒嗛厤鍘嗗彶璁板綍**锛氳褰曡溅杈嗗垎閰嶇殑鍘嗗彶鍙樻洿
+4. **閫氱煡鍔熻兘**锛氬垎閰嶅彉鏇存椂鍙戦�侀�氱煡缁欑浉鍏充汉鍛�
+5. **缁熻鎶ヨ〃**锛氳溅杈嗕娇鐢ㄧ巼銆佷换鍔″畬鎴愮巼绛夌粺璁″姛鑳�
diff --git a/ruoyi-ui/src/views/task/vehicle/index.vue b/ruoyi-ui/src/views/task/vehicle/index.vue
new file mode 100644
index 0000000..314fda7
--- /dev/null
+++ b/ruoyi-ui/src/views/task/vehicle/index.vue
@@ -0,0 +1,525 @@
+<template>
+ <div class="app-container">
+ <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+ <el-form-item label="浠诲姟" prop="taskId">
+ <el-select v-model="queryParams.taskId" placeholder="璇烽�夋嫨浠诲姟" clearable filterable style="width: 200px">
+ <el-option
+ v-for="task in taskList"
+ :key="task.taskId"
+ :label="task.taskCode + ' - ' + getTaskTypeName(task.taskType)"
+ :value="task.taskId"
+ />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="杞﹁締" prop="vehicleId">
+ <el-select v-model="queryParams.vehicleId" placeholder="璇烽�夋嫨杞﹁締" clearable filterable style="width: 200px">
+ <el-option
+ v-for="vehicle in vehicleList"
+ :key="vehicle.vehicleId"
+ :label="vehicle.vehicleNo + ' - ' + vehicle.deptName"
+ :value="vehicle.vehicleId"
+ />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="杞︾墝鍙�" prop="vehicleNo">
+ <el-input
+ v-model="queryParams.vehicleNo"
+ placeholder="璇疯緭鍏ヨ溅鐗屽彿"
+ clearable
+ @keyup.enter.native="handleQuery"
+ />
+ </el-form-item>
+ <el-form-item label="鍏宠仈鐘舵��" prop="status">
+ <el-select v-model="queryParams.status" placeholder="璇烽�夋嫨鍏宠仈鐘舵��" clearable>
+ <el-option
+ v-for="dict in dict.type.sys_task_vehicle_status"
+ :key="dict.value"
+ :label="dict.label"
+ :value="dict.value"
+ />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="鍒嗛厤浜�" prop="assignBy">
+ <el-input
+ v-model="queryParams.assignBy"
+ placeholder="璇疯緭鍏ュ垎閰嶄汉"
+ clearable
+ @keyup.enter.native="handleQuery"
+ />
+ </el-form-item>
+ <el-form-item>
+ <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+ <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+ </el-form-item>
+ </el-form>
+
+ <el-row :gutter="10" class="mb8">
+ <el-col :span="1.5">
+ <el-button
+ type="primary"
+ plain
+ icon="el-icon-plus"
+ size="mini"
+ @click="handleAdd"
+ v-hasPermi="['task:vehicle:add']"
+ >鏂板</el-button>
+ </el-col>
+ <el-col :span="1.5">
+ <el-button
+ type="success"
+ plain
+ icon="el-icon-edit"
+ size="mini"
+ :disabled="single"
+ @click="handleUpdate"
+ v-hasPermi="['task:vehicle:edit']"
+ >淇敼</el-button>
+ </el-col>
+ <el-col :span="1.5">
+ <el-button
+ type="danger"
+ plain
+ icon="el-icon-delete"
+ size="mini"
+ :disabled="multiple"
+ @click="handleDelete"
+ v-hasPermi="['task:vehicle:remove']"
+ >鍒犻櫎</el-button>
+ </el-col>
+ <el-col :span="1.5">
+ <el-button
+ type="warning"
+ plain
+ icon="el-icon-download"
+ size="mini"
+ @click="handleExport"
+ v-hasPermi="['task:vehicle:export']"
+ >瀵煎嚭</el-button>
+ </el-col>
+ <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+ </el-row>
+
+ <el-table v-loading="loading" :data="taskVehicleList" @selection-change="handleSelectionChange">
+ <el-table-column type="selection" width="55" align="center" />
+ <el-table-column label="浠诲姟缂栧彿" align="center" prop="taskCode" />
+ <el-table-column label="浠诲姟绫诲瀷" align="center" prop="taskType">
+ <template slot-scope="scope">
+ <dict-tag :options="dict.type.sys_task_type" :value="scope.row.taskType"/>
+ </template>
+ </el-table-column>
+ <el-table-column label="杞︾墝鍙�" align="center" prop="vehicleNo" />
+ <el-table-column label="杞﹁締绫诲瀷" align="center" prop="vehicleType">
+ <template slot-scope="scope">
+ <dict-tag :options="dict.type.sys_vehicle_type" :value="scope.row.vehicleType"/>
+ </template>
+ </el-table-column>
+
+ <el-table-column label="鍒嗛厤鏃堕棿" align="center" prop="assignTime" width="180">
+ <template slot-scope="scope">
+ <span>{{ parseTime(scope.row.assignTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
+ </template>
+ </el-table-column>
+ <el-table-column label="鍒嗛厤浜�" align="center" prop="assignBy" />
+ <el-table-column label="鍏宠仈鐘舵��" align="center" prop="status">
+ <template slot-scope="scope">
+ <dict-tag :options="dict.type.sys_task_vehicle_status" :value="scope.row.status"/>
+ </template>
+ </el-table-column>
+ <el-table-column label="澶囨敞" align="center" prop="remark" />
+ <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+ <template slot-scope="scope">
+ <el-button
+ size="mini"
+ type="text"
+ icon="el-icon-edit"
+ @click="handleUpdate(scope.row)"
+ v-hasPermi="['task:vehicle:edit']"
+ >淇敼</el-button>
+ <el-button
+ size="mini"
+ type="text"
+ icon="el-icon-delete"
+ @click="handleDelete(scope.row)"
+ v-hasPermi="['task:vehicle:remove']"
+ >鍒犻櫎</el-button>
+ <el-button
+ size="mini"
+ type="text"
+ icon="el-icon-refresh"
+ @click="handleStatusChange(scope.row)"
+ v-hasPermi="['task:vehicle:edit']"
+ >鐘舵�佸彉鏇�</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+
+ <pagination
+ v-show="total>0"
+ :total="total"
+ :page.sync="queryParams.pageNum"
+ :limit.sync="queryParams.pageSize"
+ @pagination="getList"
+ />
+
+ <!-- 娣诲姞鎴栦慨鏀逛换鍔¤溅杈嗗叧鑱斿璇濇 -->
+ <el-dialog :title="title" :visible.sync="open" width="600px" append-to-body>
+ <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+ <el-form-item label="浠诲姟" prop="taskId">
+ <el-select v-model="form.taskId" placeholder="璇烽�夋嫨浠诲姟" filterable clearable style="width: 100%" @change="handleTaskChange" :loading="taskListLoading">
+ <el-option
+ v-for="task in taskList"
+ :key="task.taskId"
+ :label="task.taskCode + ' - ' + getTaskTypeName(task.taskType) + ' - ' + (task.taskDescription || '鏃犳弿杩�')"
+ :value="task.taskId"
+ >
+ <div style="display: flex; justify-content: space-between; align-items: center;">
+ <div>
+ <div style="font-weight: bold; color: #303133;">{{ task.taskCode }}</div>
+ <div style="font-size: 12px; color: #909399;">ID: {{ task.taskId }}</div>
+ </div>
+ <div style="text-align: right;">
+ <div style="color: #409EFF; font-size: 13px;">{{ getTaskTypeName(task.taskType) }}</div>
+ <div style="color: #8492a6; font-size: 12px;">{{ task.taskDescription || '鏃犳弿杩�' }}</div>
+ </div>
+ </div>
+ </el-option>
+ </el-select>
+ </el-form-item>
+ <el-form-item label="杞﹁締" prop="vehicleId">
+ <el-select v-model="form.vehicleId" placeholder="璇烽�夋嫨杞﹁締" filterable clearable style="width: 100%" @change="handleVehicleChange" :loading="vehicleListLoading">
+ <el-option
+ v-for="vehicle in vehicleList"
+ :key="vehicle.vehicleId"
+ :label="vehicle.vehicleNo + ' - ' + (vehicle.deptName || '鏈垎閰嶉儴闂�')"
+ :value="vehicle.vehicleId"
+ >
+ <div style="display: flex; justify-content: space-between; align-items: center;">
+ <div>
+ <div style="font-weight: bold; color: #303133;">{{ vehicle.vehicleNo }}</div>
+ <div style="font-size: 12px; color: #909399;">ID: {{ vehicle.vehicleId }}</div>
+ </div>
+ <div style="text-align: right;">
+ <div style="color: #67C23A; font-size: 13px;">{{ getVehicleTypeName(vehicle.vehicleType) }}</div>
+ <div style="color: #E6A23C; font-size: 12px;">{{ vehicle.deptName || '鏈垎閰嶉儴闂�' }}</div>
+ </div>
+ </div>
+ </el-option>
+ </el-select>
+ </el-form-item>
+ <el-form-item label="鍏宠仈鐘舵��" prop="status">
+ <el-select v-model="form.status" placeholder="璇烽�夋嫨鍏宠仈鐘舵��" style="width: 100%">
+ <el-option
+ v-for="dict in dict.type.sys_task_vehicle_status"
+ :key="dict.value"
+ :label="dict.label"
+ :value="dict.value"
+ ></el-option>
+ </el-select>
+ </el-form-item>
+ <el-form-item label="澶囨敞" prop="remark">
+ <el-input v-model="form.remark" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" />
+ </el-form-item>
+ </el-form>
+ <div slot="footer" class="dialog-footer">
+ <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+ <el-button @click="cancel">鍙� 娑�</el-button>
+ </div>
+ </el-dialog>
+
+ <!-- 鐘舵�佸彉鏇村璇濇 -->
+ <el-dialog title="鐘舵�佸彉鏇�" :visible.sync="statusOpen" width="400px" append-to-body>
+ <el-form ref="statusForm" :model="statusForm" :rules="statusRules" label-width="80px">
+ <el-form-item label="褰撳墠鐘舵��">
+ <dict-tag :options="dict.type.sys_task_vehicle_status" :value="statusForm.oldStatus"/>
+ </el-form-item>
+ <el-form-item label="鏂扮姸鎬�" prop="newStatus">
+ <el-select v-model="statusForm.newStatus" placeholder="璇烽�夋嫨鏂扮姸鎬�">
+ <el-option
+ v-for="dict in dict.type.sys_task_vehicle_status"
+ :key="dict.value"
+ :label="dict.label"
+ :value="dict.value"
+ ></el-option>
+ </el-select>
+ </el-form-item>
+ </el-form>
+ <div slot="footer" class="dialog-footer">
+ <el-button type="primary" @click="submitStatusChange">纭� 瀹�</el-button>
+ <el-button @click="cancelStatusChange">鍙� 娑�</el-button>
+ </div>
+ </el-dialog>
+ </div>
+</template>
+
+<script>
+import { listTaskVehicle, getTaskVehicle, delTaskVehicle, addTaskVehicle, updateTaskVehicle, updateTaskVehicleStatus, listTask } from "@/api/task";
+import { listVehicle } from "@/api/system/vehicle";
+
+export default {
+ name: "TaskVehicle",
+ dicts: ['sys_task_vehicle_status', 'sys_vehicle_type', 'sys_task_type'],
+ data() {
+ return {
+ // 閬僵灞�
+ loading: true,
+ // 閫変腑鏁扮粍
+ ids: [],
+ // 闈炲崟涓鐢�
+ single: true,
+ // 闈炲涓鐢�
+ multiple: true,
+ // 鏄剧ず鎼滅储鏉′欢
+ showSearch: true,
+ // 鎬绘潯鏁�
+ total: 0,
+ // 浠诲姟杞﹁締鍏宠仈琛ㄦ牸鏁版嵁
+ taskVehicleList: [],
+ // 浠诲姟鍒楄〃
+ taskList: [],
+ // 杞﹁締鍒楄〃
+ vehicleList: [],
+ // 浠诲姟鍒楄〃鍔犺浇鐘舵��
+ taskListLoading: false,
+ // 杞﹁締鍒楄〃鍔犺浇鐘舵��
+ vehicleListLoading: false,
+ // 寮瑰嚭灞傛爣棰�
+ title: "",
+ // 鏄惁鏄剧ず寮瑰嚭灞�
+ open: false,
+ // 鏄惁鏄剧ず鐘舵�佸彉鏇村脊鍑哄眰
+ statusOpen: false,
+ // 鏌ヨ鍙傛暟
+ queryParams: {
+ pageNum: 1,
+ pageSize: 10,
+ taskId: null,
+ vehicleId: null,
+ vehicleNo: null,
+ status: null,
+ assignBy: null,
+ },
+ // 琛ㄥ崟鍙傛暟
+ form: {},
+ // 鐘舵�佸彉鏇磋〃鍗曞弬鏁�
+ statusForm: {},
+ // 琛ㄥ崟鏍¢獙
+ rules: {
+ taskId: [
+ { required: true, message: "浠诲姟ID涓嶈兘涓虹┖", trigger: "blur" }
+ ],
+ vehicleId: [
+ { required: true, message: "杞﹁締ID涓嶈兘涓虹┖", trigger: "blur" }
+ ],
+ status: [
+ { required: true, message: "鍏宠仈鐘舵�佷笉鑳戒负绌�", trigger: "change" }
+ ]
+ },
+ // 鐘舵�佸彉鏇磋〃鍗曟牎楠�
+ statusRules: {
+ newStatus: [
+ { required: true, message: "鏂扮姸鎬佷笉鑳戒负绌�", trigger: "change" }
+ ]
+ }
+ };
+ },
+ created() {
+ this.getList();
+ this.getTaskList();
+ this.getVehicleList();
+ },
+ methods: {
+ /** 鏌ヨ浠诲姟杞﹁締鍏宠仈鍒楄〃 */
+ getList() {
+ this.loading = true;
+ listTaskVehicle(this.queryParams).then(response => {
+ this.taskVehicleList = response.rows;
+ this.total = response.total;
+ this.loading = false;
+ });
+ },
+ /** 鑾峰彇浠诲姟鍒楄〃 */
+ getTaskList() {
+ this.taskListLoading = true;
+ // 鑾峰彇鎵�鏈変换鍔″垪琛ㄧ敤浜庝笅鎷夐�夋嫨
+ listTask({ pageNum: 1, pageSize: 1000 }).then(response => {
+ this.taskList = response.rows || [];
+ this.taskListLoading = false;
+ }).catch(() => {
+ this.taskListLoading = false;
+ });
+ },
+ /** 鑾峰彇杞﹁締鍒楄〃 */
+ getVehicleList() {
+ this.vehicleListLoading = true;
+ // 鑾峰彇鎵�鏈夎溅杈嗗垪琛ㄧ敤浜庝笅鎷夐�夋嫨
+ listVehicle({ pageNum: 1, pageSize: 1000 }).then(response => {
+ this.vehicleList = response.rows || [];
+ this.vehicleListLoading = false;
+ }).catch(() => {
+ this.vehicleListLoading = false;
+ });
+ },
+ // 鍙栨秷鎸夐挳
+ cancel() {
+ this.open = false;
+ this.reset();
+ },
+ // 琛ㄥ崟閲嶇疆
+ reset() {
+ this.form = {
+ id: null,
+ taskId: null,
+ vehicleId: null,
+ assignTime: null,
+ assignBy: null,
+ status: null,
+ remark: null
+ };
+ this.resetForm("form");
+ },
+ /** 鎼滅储鎸夐挳鎿嶄綔 */
+ handleQuery() {
+ this.queryParams.pageNum = 1;
+ this.getList();
+ },
+ /** 閲嶇疆鎸夐挳鎿嶄綔 */
+ resetQuery() {
+ this.resetForm("queryForm");
+ this.handleQuery();
+ },
+ // 澶氶�夋閫変腑鏁版嵁
+ handleSelectionChange(selection) {
+ this.ids = selection.map(item => item.id)
+ this.single = selection.length!==1
+ this.multiple = !selection.length
+ },
+ /** 鏂板鎸夐挳鎿嶄綔 */
+ handleAdd() {
+ this.reset();
+ // 璁剧疆榛樿鐘舵�佷负宸插垎閰�
+ this.form.status = 'ASSIGNED';
+ this.open = true;
+ this.title = "娣诲姞浠诲姟杞﹁締鍏宠仈";
+ },
+ /** 淇敼鎸夐挳鎿嶄綔 */
+ handleUpdate(row) {
+ this.reset();
+ const id = row.id || this.ids
+ getTaskVehicle(id).then(response => {
+ this.form = response.data;
+ this.open = true;
+ this.title = "淇敼浠诲姟杞﹁締鍏宠仈";
+ });
+ },
+ /** 鎻愪氦鎸夐挳 */
+ submitForm() {
+ this.$refs["form"].validate(valid => {
+ if (valid) {
+ // 妫�鏌ユ槸鍚﹀凡瀛樺湪鐩稿悓鐨勪换鍔¤溅杈嗗叧鑱�
+ if (this.form.id == null) {
+ const exists = this.taskVehicleList.find(item =>
+ item.taskId === this.form.taskId && item.vehicleId === this.form.vehicleId
+ );
+ if (exists) {
+ this.$modal.msgError("璇ヤ换鍔″拰杞﹁締鐨勫叧鑱斿叧绯诲凡瀛樺湪锛岃鍕块噸澶嶆坊鍔�");
+ return;
+ }
+ }
+
+ if (this.form.id != null) {
+ updateTaskVehicle(this.form).then(response => {
+ this.$modal.msgSuccess("淇敼鎴愬姛");
+ this.open = false;
+ this.getList();
+ });
+ } else {
+ addTaskVehicle(this.form).then(response => {
+ this.$modal.msgSuccess("鏂板鎴愬姛");
+ this.open = false;
+ this.getList();
+ });
+ }
+ }
+ });
+ },
+ /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+ handleDelete(row) {
+ const ids = row.id || this.ids;
+ this.$modal.confirm('鏄惁纭鍒犻櫎浠诲姟杞﹁締鍏宠仈缂栧彿涓�"' + ids + '"鐨勬暟鎹」锛�').then(function() {
+ return delTaskVehicle(ids);
+ }).then(() => {
+ this.getList();
+ this.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ }).catch(() => {});
+ },
+ /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+ handleExport() {
+ this.download('task/vehicle/management/export', {
+ ...this.queryParams
+ }, `task_vehicle_${new Date().getTime()}.xlsx`)
+ },
+ /** 鐘舵�佸彉鏇存寜閽搷浣� */
+ handleStatusChange(row) {
+ this.statusForm = {
+ id: row.id,
+ oldStatus: row.status,
+ newStatus: null
+ };
+ this.statusOpen = true;
+ },
+ /** 鎻愪氦鐘舵�佸彉鏇� */
+ submitStatusChange() {
+ this.$refs["statusForm"].validate(valid => {
+ if (valid) {
+ updateTaskVehicleStatus(this.statusForm.id, this.statusForm.newStatus).then(response => {
+ this.$modal.msgSuccess("鐘舵�佸彉鏇存垚鍔�");
+ this.statusOpen = false;
+ this.getList();
+ });
+ }
+ });
+ },
+ /** 鍙栨秷鐘舵�佸彉鏇� */
+ cancelStatusChange() {
+ this.statusOpen = false;
+ this.statusForm = {};
+ },
+ /** 浠诲姟閫夋嫨鍙樺寲 */
+ handleTaskChange(taskId) {
+ if (taskId) {
+ const selectedTask = this.taskList.find(task => task.taskId === taskId);
+ if (selectedTask) {
+ console.log('閫夋嫨鐨勪换鍔�:', selectedTask);
+ }
+ }
+ },
+ /** 杞﹁締閫夋嫨鍙樺寲 */
+ handleVehicleChange(vehicleId) {
+ if (vehicleId) {
+ const selectedVehicle = this.vehicleList.find(vehicle => vehicle.vehicleId === vehicleId);
+ if (selectedVehicle) {
+ console.log('閫夋嫨鐨勮溅杈�:', selectedVehicle);
+ }
+ }
+ },
+ /** 鑾峰彇杞﹁締绫诲瀷鍚嶇О */
+ getVehicleTypeName(vehicleType) {
+ const typeDict = this.dict.type.sys_vehicle_type;
+ if (typeDict && typeDict.length > 0) {
+ const typeItem = typeDict.find(item => item.value === vehicleType);
+ return typeItem ? typeItem.label : vehicleType;
+ }
+ return vehicleType;
+ },
+ /** 鑾峰彇浠诲姟绫诲瀷鍚嶇О */
+ getTaskTypeName(taskType) {
+ const typeDict = this.dict.type.sys_task_type;
+ if (typeDict && typeDict.length > 0) {
+ const typeItem = typeDict.find(item => item.value === taskType);
+ return typeItem ? typeItem.label : taskType;
+ }
+ return taskType;
+ }
+ }
+};
+</script>
diff --git "a/ruoyi-ui/src/views/task/vehicle/\345\210\227\350\241\250\346\230\276\347\244\272\344\274\230\345\214\226\350\257\264\346\230\216.md" "b/ruoyi-ui/src/views/task/vehicle/\345\210\227\350\241\250\346\230\276\347\244\272\344\274\230\345\214\226\350\257\264\346\230\216.md"
new file mode 100644
index 0000000..04e5b92
--- /dev/null
+++ "b/ruoyi-ui/src/views/task/vehicle/\345\210\227\350\241\250\346\230\276\347\244\272\344\274\230\345\214\226\350\257\264\346\230\216.md"
@@ -0,0 +1,244 @@
+# 浠诲姟杞﹁締鍏宠仈鍒楄〃鏄剧ず浼樺寲璇存槑
+
+## 浼樺寲鍐呭
+
+### 1. 鏌ヨ鏉′欢浼樺寲
+- 鉁� **浠诲姟閫夋嫨**锛氬皢"浠诲姟ID"鏀逛负"浠诲姟"涓嬫媺閫夋嫨锛屾樉绀轰换鍔$紪鍙峰拰绫诲瀷
+- 鉁� **杞﹁締閫夋嫨**锛氬皢"杞﹁締ID"鏀逛负"杞﹁締"涓嬫媺閫夋嫨锛屾樉绀鸿溅鐗屽彿鍜岀被鍨�
+- 鉁� **鐢ㄦ埛浣撻獙**锛氭敮鎸佹悳绱㈣繃婊わ紝鎿嶄綔鏇翠究鎹�
+
+### 2. 琛ㄦ牸鏄剧ず浼樺寲
+- 鉁� **绉婚櫎鍏宠仈ID**锛氫笉鍐嶆樉绀哄唴閮ㄥ叧鑱擨D锛岀晫闈㈡洿绠�娲�
+- 鉁� **绉婚櫎浠诲姟ID**锛氫笉鍐嶆樉绀轰换鍔D锛屾敼涓烘樉绀轰换鍔$紪鍙�
+- 鉁� **鏂板浠诲姟缂栧彿**锛氭樉绀轰换鍔$紪鍙凤紝渚夸簬璇嗗埆
+- 鉁� **鏂板浠诲姟绫诲瀷**锛氭樉绀轰换鍔$被鍨嬶紝浣跨敤瀛楀吀鏍囩
+- 鉁� **鏂板杞﹁締绫诲瀷**锛氭樉绀鸿溅杈嗙被鍨嬶紝浣跨敤瀛楀吀鏍囩
+
+## 鎶�鏈疄鐜�
+
+### 1. 鏌ヨ鏉′欢浼樺寲
+
+#### 浠诲姟閫夋嫨涓嬫媺
+```vue
+<el-form-item label="浠诲姟" prop="taskId">
+ <el-select v-model="queryParams.taskId" placeholder="璇烽�夋嫨浠诲姟" clearable filterable style="width: 200px">
+ <el-option
+ v-for="task in taskList"
+ :key="task.taskId"
+ :label="task.taskCode + ' - ' + getTaskTypeName(task.taskType)"
+ :value="task.taskId"
+ />
+ </el-select>
+</el-form-item>
+```
+
+#### 杞﹁締閫夋嫨涓嬫媺
+```vue
+<el-form-item label="杞﹁締" prop="vehicleId">
+ <el-select v-model="queryParams.vehicleId" placeholder="璇烽�夋嫨杞﹁締" clearable filterable style="width: 200px">
+ <el-option
+ v-for="vehicle in vehicleList"
+ :key="vehicle.vehicleId"
+ :label="vehicle.vehicleNo + ' - ' + getVehicleTypeName(vehicle.vehicleType)"
+ :value="vehicle.vehicleId"
+ />
+ </el-select>
+</el-form-item>
+```
+
+### 2. 琛ㄦ牸鏄剧ず浼樺寲
+
+#### 琛ㄦ牸鍒楀畾涔�
+```vue
+<el-table v-loading="loading" :data="taskVehicleList" @selection-change="handleSelectionChange">
+ <el-table-column type="selection" width="55" align="center" />
+ <!-- 绉婚櫎锛氬叧鑱擨D銆佷换鍔D -->
+ <!-- 鏂板锛氫换鍔$紪鍙枫�佷换鍔$被鍨嬨�佽溅杈嗙被鍨� -->
+ <el-table-column label="浠诲姟缂栧彿" align="center" prop="taskCode" />
+ <el-table-column label="浠诲姟绫诲瀷" align="center" prop="taskType">
+ <template slot-scope="scope">
+ <dict-tag :options="dict.type.sys_task_type" :value="scope.row.taskType"/>
+ </template>
+ </el-table-column>
+ <el-table-column label="杞︾墝鍙�" align="center" prop="vehicleNo" />
+ <el-table-column label="杞﹁締绫诲瀷" align="center" prop="vehicleType">
+ <template slot-scope="scope">
+ <dict-tag :options="dict.type.sys_vehicle_type" :value="scope.row.vehicleType"/>
+ </template>
+ </el-table-column>
+ <!-- 鍏朵粬鍒椾繚鎸佷笉鍙� -->
+</el-table>
+```
+
+### 3. 鏁版嵁绠$悊
+
+#### 鏁版嵁瀹氫箟
+```javascript
+data() {
+ return {
+ // 浠诲姟鍒楄〃
+ taskList: [],
+ // 杞﹁締鍒楄〃
+ vehicleList: [],
+ // 浠诲姟鍒楄〃鍔犺浇鐘舵��
+ taskListLoading: false,
+ // 杞﹁締鍒楄〃鍔犺浇鐘舵��
+ vehicleListLoading: false,
+ // ... 鍏朵粬鏁版嵁
+ };
+}
+```
+
+#### 鏁版嵁鍔犺浇
+```javascript
+created() {
+ this.getList();
+ this.getTaskList(); // 鍔犺浇浠诲姟鍒楄〃
+ this.getVehicleList(); // 鍔犺浇杞﹁締鍒楄〃
+}
+
+/** 鑾峰彇浠诲姟鍒楄〃 */
+getTaskList() {
+ this.taskListLoading = true;
+ listTask({ pageNum: 1, pageSize: 1000 }).then(response => {
+ this.taskList = response.rows || [];
+ this.taskListLoading = false;
+ }).catch(() => {
+ this.taskListLoading = false;
+ });
+}
+
+/** 鑾峰彇杞﹁締鍒楄〃 */
+getVehicleList() {
+ this.vehicleListLoading = true;
+ listVehicle({ pageNum: 1, pageSize: 1000 }).then(response => {
+ this.vehicleList = response.rows || [];
+ this.vehicleListLoading = false;
+ }).catch(() => {
+ this.vehicleListLoading = false;
+ });
+}
+```
+
+#### 瀛楀吀鏂规硶
+```javascript
+/** 鑾峰彇浠诲姟绫诲瀷鍚嶇О */
+getTaskTypeName(taskType) {
+ const typeDict = this.dict.type.sys_task_type;
+ if (typeDict && typeDict.length > 0) {
+ const typeItem = typeDict.find(item => item.value === taskType);
+ return typeItem ? typeItem.label : taskType;
+ }
+ return taskType;
+}
+
+/** 鑾峰彇杞﹁締绫诲瀷鍚嶇О */
+getVehicleTypeName(vehicleType) {
+ const typeDict = this.dict.type.sys_vehicle_type;
+ if (typeDict && typeDict.length > 0) {
+ const typeItem = typeDict.find(item => item.value === vehicleType);
+ return typeItem ? typeItem.label : vehicleType;
+ }
+ return vehicleType;
+}
+```
+
+## 鐣岄潰鏁堟灉
+
+### 鏌ヨ鏉′欢鍖哄煙
+```
+鈹屸攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�
+鈹� 浠诲姟: [涓嬫媺閫夋嫨-浠诲姟缂栧彿-浠诲姟绫诲瀷] 杞﹁締: [涓嬫媺閫夋嫨-杞︾墝鍙�-杞﹁締绫诲瀷] 鈹�
+鈹� 杞︾墝鍙�: [杈撳叆妗哴 鍏宠仈鐘舵��: [涓嬫媺閫夋嫨] 鍒嗛厤浜�: [杈撳叆妗哴 鈹�
+鈹� [鎼滅储] [閲嶇疆] 鈹�
+鈹斺攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�
+```
+
+### 琛ㄦ牸鏄剧ず
+```
+鈹屸攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�
+鈹� 閫夋嫨 鈹� 浠诲姟缂栧彿 鈹� 浠诲姟绫诲瀷 鈹� 杞︾墝鍙� 鈹� 杞﹁締绫诲瀷 鈹� 鍒嗛厤鏃堕棿 鈹� 鍒嗛厤浜� 鈹� 鍏宠仈鐘舵�� 鈹� 澶囨敞 鈹� 鎿嶄綔 鈹�
+鈹溾攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�
+鈹� 鈽� 鈹� TASK001 鈹� 缁翠慨淇濆吇 鈹� 绮12345 鈹� 鏁戞姢杞� 鈹� 2024-01-01 鈹� admin 鈹� 宸插垎閰� 鈹� 娴嬭瘯 鈹� 淇敼鍒犻櫎鐘舵�佸彉鏇� 鈹�
+鈹� 鈽� 鈹� TASK002 鈹� 鍔犳补浠诲姟 鈹� 绮67890 鈹� 杞繍杞� 鈹� 2024-01-02 鈹� admin 鈹� 鎵ц涓� 鈹� 娴嬭瘯 鈹� 淇敼鍒犻櫎鐘舵�佸彉鏇� 鈹�
+鈹斺攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�
+```
+
+### 涓嬫媺閫夋嫨鏁堟灉
+
+#### 浠诲姟閫夋嫨涓嬫媺
+```
+鈹屸攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�
+鈹� 浠诲姟: [TASK001 - 缁翠慨淇濆吇 鈻糫 鈹�
+鈹� 鈹屸攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹� 鈹�
+鈹� 鈹� TASK001 - 缁翠慨淇濆吇 鈹� 鈹�
+鈹� 鈹� TASK002 - 鍔犳补浠诲姟 鈹� 鈹�
+鈹� 鈹� TASK003 - 鍏朵粬浠诲姟 鈹� 鈹�
+鈹� 鈹斺攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹� 鈹�
+鈹斺攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�
+```
+
+#### 杞﹁締閫夋嫨涓嬫媺
+```
+鈹屸攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�
+鈹� 杞﹁締: [绮12345 - 鏁戞姢杞� 鈻糫 鈹�
+鈹� 鈹屸攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹� 鈹�
+鈹� 鈹� 绮12345 - 鏁戞姢杞� 鈹� 鈹�
+鈹� 鈹� 绮67890 - 杞繍杞� 鈹� 鈹�
+鈹� 鈹� 绮99999 - 鏁戞姢杞� 鈹� 鈹�
+鈹� 鈹斺攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹� 鈹�
+鈹斺攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�
+```
+
+## 鍔熻兘鐗规��
+
+### 1. 鏌ヨ鍔熻兘
+- **浠诲姟绛涢��**锛氭敮鎸佹寜浠诲姟缂栧彿鍜岀被鍨嬬瓫閫�
+- **杞﹁締绛涢��**锛氭敮鎸佹寜杞︾墝鍙峰拰绫诲瀷绛涢��
+- **鎼滅储杩囨护**锛氫笅鎷夐�夋嫨鏀寔杈撳叆鎼滅储
+- **澶氭潯浠舵煡璇�**锛氭敮鎸佺粍鍚堟潯浠舵煡璇�
+
+### 2. 鏄剧ず鍔熻兘
+- **淇℃伅瀹屾暣**锛氭樉绀轰换鍔$紪鍙枫�佺被鍨嬨�佽溅鐗屽彿銆佽溅杈嗙被鍨�
+- **绫诲瀷鏍囩**锛氫换鍔$被鍨嬪拰杞﹁締绫诲瀷浣跨敤褰╄壊鏍囩鏄剧ず
+- **鐘舵�佹爣绛�**锛氬叧鑱旂姸鎬佷娇鐢ㄥ僵鑹叉爣绛炬樉绀�
+- **鐣岄潰绠�娲�**锛氱Щ闄や笉蹇呰鐨処D瀛楁
+
+### 3. 鐢ㄦ埛浣撻獙
+- **鎿嶄綔渚挎嵎**锛氫笅鎷夐�夋嫨姣旀墜鍔ㄨ緭鍏ユ洿渚挎嵎
+- **淇℃伅娓呮櫚**锛氭樉绀烘湁鎰忎箟鐨勪笟鍔′俊鎭�岄潪鎶�鏈疘D
+- **鎼滅储鍙嬪ソ**锛氭敮鎸佽緭鍏ユ悳绱㈠揩閫熷畾浣�
+- **瑙嗚缇庤**锛氫娇鐢ㄥ瓧鍏告爣绛炬彁鍗囪瑙夋晥鏋�
+
+## 鏁版嵁瀛楀吀閰嶇疆
+
+### 1. 浠诲姟绫诲瀷瀛楀吀 (sys_task_type)
+```javascript
+dicts: ['sys_task_vehicle_status', 'sys_vehicle_type', 'sys_task_type']
+```
+
+### 2. 杞﹁締绫诲瀷瀛楀吀 (sys_vehicle_type)
+- 鏁戞姢杞�
+- 杞繍杞�
+- 鍏朵粬
+
+### 3. 浠诲姟杞﹁締鍏宠仈鐘舵�佸瓧鍏� (sys_task_vehicle_status)
+- ASSIGNED - 宸插垎閰�
+- ACTIVE - 鎵ц涓�
+- COMPLETED - 宸插畬鎴�
+- CANCELLED - 宸插彇娑�
+
+## 娉ㄦ剰浜嬮」
+
+1. **鏁版嵁鍔犺浇**锛氫换鍔″拰杞﹁締鍒楄〃鍦ㄩ〉闈㈠姞杞芥椂鑾峰彇锛屽鏋滄暟鎹緢澶氬彲鑰冭檻鍒嗛〉
+2. **鎬ц兘鑰冭檻**锛氫笅鎷夐�夋嫨鏀寔鎼滅储杩囨护锛屾彁鍗囧ぇ鏁版嵁閲忎笅鐨勭敤鎴蜂綋楠�
+3. **鏁版嵁涓�鑷存��**锛氱‘淇濅换鍔″拰杞﹁締鏁版嵁涓庡叧鑱旀暟鎹繚鎸佷竴鑷�
+4. **鏉冮檺鎺у埗**锛氶渶瑕佺浉搴旂殑鏉冮檺鎵嶈兘杩涜鏌ヨ鍜屾搷浣�
+
+## 鍚庣画浼樺寲寤鸿
+
+1. **鍒嗛〉鍔犺浇**锛氬鏋滀换鍔℃垨杞﹁締鏁版嵁寰堝锛屽彲鑰冭檻鍒嗛〉鍔犺浇
+2. **缂撳瓨浼樺寲**锛氬浠诲姟鍜岃溅杈嗗垪琛ㄨ繘琛岀紦瀛橈紝鍑忓皯閲嶅璇锋眰
+3. **鎼滅储浼樺寲**锛氭敮鎸佹洿澶嶆潅鐨勬悳绱㈡潯浠讹紝濡傛寜閮ㄩ棬绛涢��
+4. **瀵煎嚭鍔熻兘**锛氭敮鎸佸鍑哄寘鍚换鍔$紪鍙峰拰绫诲瀷鐨勬暟鎹�
+5. **鎵归噺鎿嶄綔**锛氭敮鎸佹壒閲忎慨鏀逛换鍔¤溅杈嗗叧鑱旂姸鎬�
diff --git "a/ruoyi-ui/src/views/task/vehicle/\346\224\271\350\277\233\350\257\264\346\230\216.md" "b/ruoyi-ui/src/views/task/vehicle/\346\224\271\350\277\233\350\257\264\346\230\216.md"
new file mode 100644
index 0000000..2c067d3
--- /dev/null
+++ "b/ruoyi-ui/src/views/task/vehicle/\346\224\271\350\277\233\350\257\264\346\230\216.md"
@@ -0,0 +1,126 @@
+# 杞﹁締浠诲姟鍏宠仈绠$悊椤甸潰鏀硅繘璇存槑
+
+## 鏀硅繘鍐呭
+
+### 1. 涓嬫媺閫夋嫨浼樺寲
+- **浠诲姟閫夋嫨**锛氬皢鍘熸潵鐨勬墜鍔ㄨ緭鍏ヤ换鍔D鏀逛负涓嬫媺閫夋嫨
+- **杞﹁締閫夋嫨**锛氬皢鍘熸潵鐨勬墜鍔ㄨ緭鍏ヨ溅杈咺D鏀逛负涓嬫媺閫夋嫨
+- **鏀寔鎼滅储**锛氫袱涓笅鎷夋閮芥敮鎸佽緭鍏ユ悳绱㈠姛鑳�
+- **鏀寔娓呯┖**锛氬彲浠ユ竻绌哄凡閫夋嫨鐨勫唴瀹�
+
+### 2. 鐢ㄦ埛浣撻獙鎻愬崌
+- **鍔犺浇鐘舵��**锛氫笅鎷夐�夋嫨鏃舵樉绀哄姞杞界姸鎬�
+- **鍙嬪ソ鏄剧ず**锛氫换鍔℃樉绀轰负"浠诲姟缂栧彿 - 浠诲姟鎻忚堪"鏍煎紡
+- **杞﹁締鏄剧ず**锛氳溅杈嗘樉绀轰负"杞︾墝鍙� - 杞﹁締绫诲瀷"鏍煎紡
+- **瀛楀吀杞崲**锛氳溅杈嗙被鍨嬭嚜鍔ㄨ浆鎹负涓枃鏄剧ず
+
+### 3. 鏁版嵁楠岃瘉澧炲己
+- **閲嶅妫�鏌�**锛氭柊澧炴椂妫�鏌ユ槸鍚﹀凡瀛樺湪鐩稿悓鐨勪换鍔¤溅杈嗗叧鑱�
+- **榛樿鐘舵��**锛氭柊澧炴椂鑷姩璁剧疆鐘舵�佷负"宸插垎閰�"
+- **閫夋嫨鐩戝惉**锛氭坊鍔犱换鍔″拰杞﹁締閫夋嫨鍙樺寲鐨勭洃鍚簨浠�
+
+### 4. 鐣岄潰浼樺寲
+- **瀵硅瘽妗嗗搴�**锛氬皢瀵硅瘽妗嗗搴︿粠500px澧炲姞鍒�600px
+- **鏍峰紡缇庡寲**锛氫紭鍖栦笅鎷夐�夐」鐨勬樉绀烘牱寮�
+- **閿欒鎻愮ず**锛氭坊鍔犲弸濂界殑閿欒鎻愮ず淇℃伅
+
+## 鎶�鏈疄鐜�
+
+### 1. API闆嗘垚
+```javascript
+// 瀵煎叆浠诲姟鍜岃溅杈咥PI
+import { listTask } from "@/api/task";
+import { listVehicle } from "@/api/system/vehicle";
+```
+
+### 2. 鏁版嵁鑾峰彇
+```javascript
+// 鑾峰彇浠诲姟鍒楄〃
+getTaskList() {
+ this.taskListLoading = true;
+ listTask({ pageNum: 1, pageSize: 1000 }).then(response => {
+ this.taskList = response.rows || [];
+ this.taskListLoading = false;
+ });
+}
+
+// 鑾峰彇杞﹁締鍒楄〃
+getVehicleList() {
+ this.vehicleListLoading = true;
+ listVehicle({ pageNum: 1, pageSize: 1000 }).then(response => {
+ this.vehicleList = response.rows || [];
+ this.vehicleListLoading = false;
+ });
+}
+```
+
+### 3. 涓嬫媺閫夋嫨缁勪欢
+```vue
+<el-select
+ v-model="form.taskId"
+ placeholder="璇烽�夋嫨浠诲姟"
+ filterable
+ clearable
+ style="width: 100%"
+ @change="handleTaskChange"
+ :loading="taskListLoading"
+>
+ <el-option
+ v-for="task in taskList"
+ :key="task.taskId"
+ :label="task.taskCode + ' - ' + (task.taskDescription || '鏃犳弿杩�')"
+ :value="task.taskId"
+ >
+ <span style="float: left; font-weight: bold">{{ task.taskCode }}</span>
+ <span style="float: right; color: #8492a6; font-size: 13px">{{ task.taskDescription || '鏃犳弿杩�' }}</span>
+ </el-option>
+</el-select>
+```
+
+### 4. 閲嶅妫�鏌ラ�昏緫
+```javascript
+// 妫�鏌ユ槸鍚﹀凡瀛樺湪鐩稿悓鐨勪换鍔¤溅杈嗗叧鑱�
+if (this.form.id == null) {
+ const exists = this.taskVehicleList.find(item =>
+ item.taskId === this.form.taskId && item.vehicleId === this.form.vehicleId
+ );
+ if (exists) {
+ this.$modal.msgError("璇ヤ换鍔″拰杞﹁締鐨勫叧鑱斿叧绯诲凡瀛樺湪锛岃鍕块噸澶嶆坊鍔�");
+ return;
+ }
+}
+```
+
+## 浣跨敤璇存槑
+
+### 1. 鏂板鍏宠仈
+1. 鐐瑰嚮"鏂板"鎸夐挳
+2. 浠庝笅鎷夊垪琛ㄤ腑閫夋嫨浠诲姟锛堟敮鎸佹悳绱級
+3. 浠庝笅鎷夊垪琛ㄤ腑閫夋嫨杞﹁締锛堟敮鎸佹悳绱級
+4. 閫夋嫨鍏宠仈鐘舵�侊紙榛樿涓�"宸插垎閰�"锛�
+5. 濉啓澶囨敞锛堝彲閫夛級
+6. 鐐瑰嚮"纭畾"淇濆瓨
+
+### 2. 淇敼鍏宠仈
+1. 鐐瑰嚮琛ㄦ牸涓殑"淇敼"鎸夐挳
+2. 鍦ㄥ脊鍑虹殑瀵硅瘽妗嗕腑淇敼鐩稿叧淇℃伅
+3. 鐐瑰嚮"纭畾"淇濆瓨淇敼
+
+### 3. 鎼滅储鍔熻兘
+- **浠诲姟鎼滅储**锛氬湪浠诲姟涓嬫媺妗嗕腑杈撳叆浠诲姟缂栧彿鎴栨弿杩拌繘琛屾悳绱�
+- **杞﹁締鎼滅储**锛氬湪杞﹁締涓嬫媺妗嗕腑杈撳叆杞︾墝鍙疯繘琛屾悳绱�
+
+## 娉ㄦ剰浜嬮」
+
+1. **鏁版嵁鍔犺浇**锛氶〉闈㈠垵濮嬪寲鏃朵細鑷姩鍔犺浇浠诲姟鍜岃溅杈嗗垪琛�
+2. **鏉冮檺鎺у埗**锛氶渶瑕佺浉搴旂殑鏉冮檺鎵嶈兘杩涜澧炲垹鏀规煡鎿嶄綔
+3. **鏁版嵁瀹屾暣鎬�**锛氱郴缁熶細鑷姩妫�鏌ラ噸澶嶅叧鑱旓紝闃叉鏁版嵁閲嶅
+4. **鐘舵�佺鐞�**锛氬叧鑱旂姸鎬佸彉鏇撮渶瑕佺浉搴旂殑鏉冮檺
+
+## 鍚庣画浼樺寲寤鸿
+
+1. **鍒嗛〉鍔犺浇**锛氬鏋滀换鍔″拰杞﹁締鏁版嵁閲忓緢澶э紝鍙互鑰冭檻鍒嗛〉鍔犺浇
+2. **缂撳瓨鏈哄埗**锛氬彲浠ユ坊鍔犳湰鍦扮紦瀛樺噺灏戦噸澶嶈姹�
+3. **瀹炴椂鏇存柊**锛氬彲浠ユ坊鍔燱ebSocket瀹炵幇鏁版嵁瀹炴椂鏇存柊
+4. **鎵归噺鎿嶄綔**锛氬彲浠ユ坊鍔犳壒閲忓垎閰嶈溅杈嗙殑鍔熻兘
+5. **鍘嗗彶璁板綍**锛氬彲浠ユ坊鍔犳搷浣滃巻鍙茶褰曞姛鑳�
diff --git "a/ruoyi-ui/src/views/task/vehicle/\347\274\226\350\276\221\347\225\214\351\235\242\344\274\230\345\214\226\350\257\264\346\230\216.md" "b/ruoyi-ui/src/views/task/vehicle/\347\274\226\350\276\221\347\225\214\351\235\242\344\274\230\345\214\226\350\257\264\346\230\216.md"
new file mode 100644
index 0000000..b4d129a
--- /dev/null
+++ "b/ruoyi-ui/src/views/task/vehicle/\347\274\226\350\276\221\347\225\214\351\235\242\344\274\230\345\214\226\350\257\264\346\230\216.md"
@@ -0,0 +1,169 @@
+# 缂栬緫鐣岄潰浼樺寲璇存槑
+
+## 浼樺寲鍐呭
+
+### 1. 浠诲姟閫夋嫨浼樺寲
+- **鏄剧ず淇℃伅**锛氫换鍔$紪鍙� + 浠诲姟绫诲瀷 + 浠诲姟鎻忚堪
+- **璇︾粏淇℃伅**锛�
+ - 宸︿晶锛氫换鍔$紪鍙凤紙绮椾綋锛�+ 浠诲姟ID
+ - 鍙充晶锛氫换鍔$被鍨嬶紙钃濊壊锛�+ 浠诲姟鎻忚堪锛堢伆鑹诧級
+- **鎼滅储鏀寔**锛氭敮鎸佹寜浠诲姟缂栧彿銆佷换鍔$被鍨嬨�佷换鍔℃弿杩版悳绱�
+
+### 2. 杞﹁締閫夋嫨浼樺寲
+- **鏄剧ず淇℃伅**锛氳溅鐗屽彿 + 杞﹁締绫诲瀷 + 褰掑睘閮ㄩ棬
+- **璇︾粏淇℃伅**锛�
+ - 宸︿晶锛氳溅鐗屽彿锛堢矖浣擄級+ 杞﹁締ID
+ - 鍙充晶锛氳溅杈嗙被鍨嬶紙缁胯壊锛�+ 褰掑睘閮ㄩ棬锛堟鑹诧級
+- **鎼滅储鏀寔**锛氭敮鎸佹寜杞︾墝鍙枫�佽溅杈嗙被鍨嬨�侀儴闂ㄥ悕绉版悳绱�
+
+### 3. 鍚庣鏁版嵁鏀寔
+- **杞﹁締瀹炰綋绫�**锛氭坊鍔犱簡 `deptId` 鍜� `deptName` 瀛楁
+- **鏁版嵁搴撴煡璇�**锛氳溅杈嗘煡璇㈣仈琛ㄦ煡璇㈤儴闂ㄤ俊鎭�
+- **瀛楀吀鏀寔**锛氭坊鍔犱簡浠诲姟绫诲瀷瀛楀吀鏀寔
+
+## 鎶�鏈疄鐜�
+
+### 1. 鍓嶇鐣岄潰浼樺寲
+```vue
+<!-- 浠诲姟閫夋嫨 -->
+<el-select v-model="form.taskId" placeholder="璇烽�夋嫨浠诲姟" filterable clearable>
+ <el-option
+ v-for="task in taskList"
+ :key="task.taskId"
+ :label="task.taskCode + ' - ' + getTaskTypeName(task.taskType) + ' - ' + (task.taskDescription || '鏃犳弿杩�')"
+ :value="task.taskId"
+ >
+ <div style="display: flex; justify-content: space-between; align-items: center;">
+ <div>
+ <div style="font-weight: bold; color: #303133;">{{ task.taskCode }}</div>
+ <div style="font-size: 12px; color: #909399;">ID: {{ task.taskId }}</div>
+ </div>
+ <div style="text-align: right;">
+ <div style="color: #409EFF; font-size: 13px;">{{ getTaskTypeName(task.taskType) }}</div>
+ <div style="color: #8492a6; font-size: 12px;">{{ task.taskDescription || '鏃犳弿杩�' }}</div>
+ </div>
+ </div>
+ </el-option>
+</el-select>
+
+<!-- 杞﹁締閫夋嫨 -->
+<el-select v-model="form.vehicleId" placeholder="璇烽�夋嫨杞﹁締" filterable clearable>
+ <el-option
+ v-for="vehicle in vehicleList"
+ :key="vehicle.vehicleId"
+ :label="vehicle.vehicleNo + ' - ' + getVehicleTypeName(vehicle.vehicleType) + ' - ' + (vehicle.deptName || '鏈垎閰嶉儴闂�')"
+ :value="vehicle.vehicleId"
+ >
+ <div style="display: flex; justify-content: space-between; align-items: center;">
+ <div>
+ <div style="font-weight: bold; color: #303133;">{{ vehicle.vehicleNo }}</div>
+ <div style="font-size: 12px; color: #909399;">ID: {{ vehicle.vehicleId }}</div>
+ </div>
+ <div style="text-align: right;">
+ <div style="color: #67C23A; font-size: 13px;">{{ getVehicleTypeName(vehicle.vehicleType) }}</div>
+ <div style="color: #E6A23C; font-size: 12px;">{{ vehicle.deptName || '鏈垎閰嶉儴闂�' }}</div>
+ </div>
+ </div>
+ </el-option>
+</el-select>
+```
+
+### 2. 鍚庣鏁版嵁鏀寔
+```java
+// 杞﹁締瀹炰綋绫绘坊鍔犲瓧娈�
+public class VehicleInfo extends BaseEntity {
+ // ... 鍏朵粬瀛楁
+
+ /** 褰掑睘閮ㄩ棬ID */
+ @Excel(name = "褰掑睘閮ㄩ棬ID")
+ private Long deptId;
+
+ /** 褰掑睘閮ㄩ棬鍚嶇О */
+ @Excel(name = "褰掑睘閮ㄩ棬")
+ private String deptName;
+
+ // getter鍜宻etter鏂规硶
+}
+```
+
+```xml
+<!-- 杞﹁締Mapper XML浼樺寲 -->
+<resultMap type="com.ruoyi.system.domain.VehicleInfo" id="VehicleInfoResult">
+ <!-- ... 鍏朵粬瀛楁鏄犲皠 -->
+ <result property="deptId" column="dept_id" />
+ <result property="deptName" column="dept_name" />
+</resultMap>
+
+<sql id="selectVehicleInfoVo">
+ select v.vehicle_id, v.device_id, v.vehicle_no, v.vehicle_type, v.vehicle_brand, v.vehicle_model, v.status, v.platform_code, v.dept_id, d.dept_name, v.create_by, v.create_time, v.update_by, v.update_time, v.remark
+ from tb_vehicle_info v
+ left join sys_dept d on v.dept_id = d.dept_id
+</sql>
+```
+
+### 3. 瀛楀吀鏀寔
+```javascript
+// 娣诲姞浠诲姟绫诲瀷瀛楀吀
+dicts: ['sys_task_vehicle_status', 'sys_vehicle_type', 'sys_task_type']
+
+// 鑾峰彇浠诲姟绫诲瀷鍚嶇О
+getTaskTypeName(taskType) {
+ const typeDict = this.dict.type.sys_task_type;
+ if (typeDict && typeDict.length > 0) {
+ const typeItem = typeDict.find(item => item.value === taskType);
+ return typeItem ? typeItem.label : taskType;
+ }
+ return taskType;
+}
+```
+
+## 鏄剧ず鏁堟灉
+
+### 浠诲姟閫夋嫨涓嬫媺妗�
+```
+鈹屸攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�
+鈹� 浠诲姟缂栧彿 - 浠诲姟绫诲瀷 - 浠诲姟鎻忚堪 鈹�
+鈹溾攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�
+鈹� TASK001 鈹� 缁翠慨淇濆吇 鈹�
+鈹� ID: 1 鈹� 杞﹁締瀹氭湡淇濆吇缁存姢 鈹�
+鈹溾攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�
+鈹� TASK002 鈹� 鍔犳补浠诲姟 鈹�
+鈹� ID: 2 鈹� 杞﹁締鍔犳补浠诲姟 鈹�
+鈹斺攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�
+```
+
+### 杞﹁締閫夋嫨涓嬫媺妗�
+```
+鈹屸攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�
+鈹� 杞︾墝鍙� - 杞﹁締绫诲瀷 - 褰掑睘閮ㄩ棬 鈹�
+鈹溾攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�
+鈹� 绮12345 鈹� 鏁戞姢杞� 鈹�
+鈹� ID: 1 鈹� 鎬ユ晳涓績 鈹�
+鈹溾攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�
+鈹� 绮67890 鈹� 杞繍杞� 鈹�
+鈹� ID: 2 鈹� 杞繍涓績 鈹�
+鈹斺攢鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�鈹�
+```
+
+## 鐢ㄦ埛浣撻獙鎻愬崌
+
+1. **淇℃伅涓板瘜**锛氭樉绀烘洿澶氭湁鐢ㄤ俊鎭紝渚夸簬鐢ㄦ埛閫夋嫨
+2. **瑙嗚灞傛**锛氫娇鐢ㄤ笉鍚岄鑹插拰瀛椾綋澶у皬鍖哄垎淇℃伅閲嶈鎬�
+3. **鎼滅储鍙嬪ソ**锛氭敮鎸佸瀛楁鎼滅储锛屾彁楂樻煡鎵炬晥鐜�
+4. **鏁版嵁瀹屾暣**锛氭樉绀篒D淇℃伅锛屼究浜庢妧鏈敤鎴疯瘑鍒�
+5. **鐘舵�佹竻鏅�**锛氭槑纭樉绀轰换鍔$被鍨嬪拰杞﹁締褰掑睘閮ㄩ棬
+
+## 娉ㄦ剰浜嬮」
+
+1. **鏁版嵁渚濊禆**锛氶渶瑕佺‘淇濊溅杈嗘暟鎹寘鍚儴闂ㄤ俊鎭�
+2. **瀛楀吀閰嶇疆**锛氶渶瑕侀厤缃换鍔$被鍨嬪瓧鍏告暟鎹�
+3. **鎬ц兘鑰冭檻**锛氳仈琛ㄦ煡璇㈠彲鑳藉奖鍝嶆�ц兘锛屽缓璁坊鍔犵储寮�
+4. **鍏煎鎬�**锛氫繚鎸佷笌鐜版湁鍔熻兘鐨勫吋瀹规��
+
+## 鍚庣画浼樺寲寤鸿
+
+1. **缂撳瓨鏈哄埗**锛氬瀛楀吀鏁版嵁杩涜缂撳瓨
+2. **鍒嗛〉鍔犺浇**锛氬鏋滄暟鎹噺澶э紝鑰冭檻鍒嗛〉鍔犺浇
+3. **瀹炴椂鏇存柊**锛氭敮鎸佹暟鎹疄鏃舵洿鏂�
+4. **鑷畾涔夋樉绀�**锛氬厑璁哥敤鎴疯嚜瀹氫箟鏄剧ず瀛楁
+5. **鎵归噺鎿嶄綔**锛氭敮鎸佹壒閲忛�夋嫨浠诲姟鍜岃溅杈�
diff --git a/ruoyi-ui/vue.config.js b/ruoyi-ui/vue.config.js
index a74ca00..6a06c2b 100644
--- a/ruoyi-ui/vue.config.js
+++ b/ruoyi-ui/vue.config.js
@@ -82,6 +82,14 @@
config.plugins.delete('preload') // TODO: need test
config.plugins.delete('prefetch') // TODO: need test
+ // 鎺掗櫎.md鏂囦欢鐨勭紪璇�
+ config.module
+ .rule('md')
+ .test(/\.md$/)
+ .use('ignore-loader')
+ .loader('ignore-loader')
+ .end()
+
// set svg-sprite-loader
config.module
.rule('svg')
diff --git "a/sql/GPS\345\235\220\346\240\207\345\212\237\350\203\275\350\257\264\346\230\216.md" "b/sql/GPS\345\235\220\346\240\207\345\212\237\350\203\275\350\257\264\346\230\216.md"
new file mode 100644
index 0000000..688b719
--- /dev/null
+++ "b/sql/GPS\345\235\220\346\240\207\345\212\237\350\203\275\350\257\264\346\230\216.md"
@@ -0,0 +1,168 @@
+# 浠诲姟绠$悊GPS鍧愭爣鍔熻兘璇存槑
+
+## 鍔熻兘姒傝堪
+
+涓洪�氱敤浠诲姟绠$悊绯荤粺澧炲姞浜咷PS鍧愭爣璁板綍鍜岃窛绂昏绠楀姛鑳斤紝鐢ㄤ簬璁板綍杞﹁締鐨勮矾绋嬩俊鎭��
+
+## 鏂板瀛楁
+
+### 鏁版嵁搴撹〃瀛楁
+鍦� `sys_task` 琛ㄤ腑鏂板浠ヤ笅瀛楁锛�
+
+| 瀛楁鍚� | 绫诲瀷 | 璇存槑 |
+|--------|------|------|
+| `departure_longitude` | DECIMAL(10,7) | 鍑哄彂鍦扮粡搴� |
+| `departure_latitude` | DECIMAL(10,7) | 鍑哄彂鍦扮含搴� |
+| `destination_longitude` | DECIMAL(10,7) | 鐩殑鍦扮粡搴� |
+| `destination_latitude` | DECIMAL(10,7) | 鐩殑鍦扮含搴� |
+| `estimated_distance` | DECIMAL(8,2) | 棰勮鍏噷鏁� |
+
+## 鎶�鏈疄鐜�
+
+### 1. 鏁版嵁搴撳眰
+- **琛ㄧ粨鏋勬洿鏂�**锛歚sql/task_tables.sql` - 鏂拌〃鍒涘缓鑴氭湰
+- **鐜版湁琛ㄦ洿鏂�**锛歚sql/add_gps_coordinates.sql` - 鐜版湁琛ㄥ瓧娈垫坊鍔犺剼鏈�
+
+### 2. 瀹炰綋灞�
+- **SysTask瀹炰綋绫�**锛氭坊鍔燝PS鍧愭爣鐩稿叧瀛楁鍜実etter/setter鏂规硶
+- **TaskCreateVO**锛氫换鍔″垱寤哄璞★紝鏀寔GPS鍧愭爣杈撳叆
+- **TaskUpdateVO**锛氫换鍔℃洿鏂板璞★紝鏀寔GPS鍧愭爣淇敼
+
+### 3. 鏁版嵁璁块棶灞�
+- **SysTaskMapper.xml**锛氭洿鏂癕yBatis鏄犲皠鏂囦欢锛屾敮鎸丟PS鍧愭爣瀛楁鐨勫鍒犳敼鏌�
+
+### 4. 涓氬姟閫昏緫灞�
+- **SysTaskServiceImpl**锛氬湪鍒涘缓鍜屾洿鏂颁换鍔℃椂鑷姩璁$畻棰勮鍏噷鏁�
+- **GpsDistanceUtils**锛欸PS鍧愭爣璺濈璁$畻宸ュ叿绫�
+
+### 5. 宸ュ叿绫�
+- **GpsDistanceUtils**锛氭彁渚涗互涓嬪姛鑳�
+ - 浣跨敤Haversine鍏紡璁$畻涓ょ偣闂寸悆闈㈣窛绂�
+ - GPS鍧愭爣鏈夋晥鎬ч獙璇�
+ - 鍧愭爣鏍煎紡鍖栨樉绀�
+ - 搴﹀垎绉掓牸寮忚浆鎹�
+
+## 璺濈璁$畻绠楁硶
+
+### Haversine鍏紡
+浣跨敤Haversine鍏紡璁$畻鍦扮悆琛ㄩ潰涓ょ偣闂寸殑鐞冮潰璺濈锛�
+
+```
+a = sin虏(螖蠁/2) + cos 蠁1 鈰� cos 蠁2 鈰� sin虏(螖位/2)
+c = 2 鈰� atan2( 鈭歛, 鈭�(1鈭抋) )
+d = R 鈰� c
+```
+
+鍏朵腑锛�
+- 蠁1, 蠁2锛氫袱鐐圭殑绾害
+- 螖蠁锛氱含搴﹀樊
+- 螖位锛氱粡搴﹀樊
+- R锛氬湴鐞冨崐寰勶紙6371鍏噷锛�
+
+### 绮惧害璇存槑
+- 缁忓害绾害锛氫繚鐣�7浣嶅皬鏁帮紝绮惧害绾�1.1鍘樼背
+- 璺濈锛氫繚鐣�2浣嶅皬鏁帮紝绮惧害鍒扮背
+- 閫傜敤浜庝腑鐭窛绂昏绠楋紙< 1000鍏噷锛�
+
+## 鍔熻兘鐗规��
+
+### 1. 鑷姩璺濈璁$畻
+- 鍒涘缓浠诲姟鏃讹細濡傛灉鎻愪緵浜嗗畬鏁寸殑GPS鍧愭爣锛岃嚜鍔ㄨ绠楅璁″叕閲屾暟
+- 鏇存柊浠诲姟鏃讹細濡傛灉淇敼浜咷PS鍧愭爣锛岄噸鏂拌绠楅璁″叕閲屾暟
+- 鍧愭爣楠岃瘉锛氳嚜鍔ㄩ獙璇丟PS鍧愭爣鐨勬湁鏁堟��
+
+### 2. 鏁版嵁楠岃瘉
+- 绾害鑼冨洿锛�-90掳 鍒� 90掳
+- 缁忓害鑼冨洿锛�-180掳 鍒� 180掳
+- 鏃犳晥鍧愭爣锛氳窛绂昏缃负0
+
+### 3. 瀹归敊澶勭悊
+- 鍧愭爣涓嶅畬鏁达細璺濈璁剧疆涓�0
+- 鍧愭爣鏃犳晥锛氳窛绂昏缃负0
+- 璁$畻寮傚父锛氳窛绂昏缃负0
+
+## 浣跨敤绀轰緥
+
+### 鍒涘缓浠诲姟鏃惰缃瓽PS鍧愭爣
+```json
+{
+ "taskType": "MAINTENANCE",
+ "taskDescription": "杞﹁締缁翠慨浠诲姟",
+ "departureAddress": "鍖椾含甯傛湞闃冲尯",
+ "destinationAddress": "鍖椾含甯傛捣娣�鍖�",
+ "departureLongitude": 116.397128,
+ "departureLatitude": 39.916527,
+ "destinationLongitude": 116.298056,
+ "destinationLatitude": 39.959444,
+ "plannedStartTime": "2024-01-15 09:00:00",
+ "plannedEndTime": "2024-01-15 17:00:00"
+}
+```
+
+### 绯荤粺鑷姩璁$畻
+绯荤粺浼氳嚜鍔ㄨ绠椾袱鐐归棿璺濈骞惰缃埌 `estimatedDistance` 瀛楁銆�
+
+## 鎵ц姝ラ
+
+### 鏂伴儴缃�
+1. 浣跨敤 `sql/task_tables.sql` 鍒涘缓鏂拌〃
+
+### 鐜版湁绯荤粺鍗囩骇
+1. 鎵ц `sql/add_gps_coordinates.sql` 娣诲姞瀛楁
+2. 閲嶆柊閮ㄧ讲搴旂敤绋嬪簭
+
+## 楠岃瘉鏂规硶
+
+### 鏁版嵁搴撻獙璇�
+```sql
+-- 鏌ョ湅琛ㄧ粨鏋�
+SHOW CREATE TABLE sys_task;
+
+-- 鏌ョ湅鏂板瀛楁
+DESCRIBE sys_task;
+
+-- 娴嬭瘯鏁版嵁鎻掑叆
+INSERT INTO sys_task (
+ task_code, task_type, task_status, creator_id, dept_id, create_by,
+ departure_longitude, departure_latitude, destination_longitude, destination_latitude
+) VALUES (
+ 'TEST001', 'MAINTENANCE', 'PENDING', 1, 1, 'admin',
+ 116.397128, 39.916527, 116.298056, 39.959444
+);
+```
+
+### 鍔熻兘楠岃瘉
+1. 鍒涘缓浠诲姟鏃惰緭鍏PS鍧愭爣锛屾鏌ユ槸鍚﹁嚜鍔ㄨ绠楄窛绂�
+2. 鏇存柊浠诲姟鐨凣PS鍧愭爣锛屾鏌ユ槸鍚﹂噸鏂拌绠楄窛绂�
+3. 杈撳叆鏃犳晥鍧愭爣锛屾鏌ヨ窛绂绘槸鍚︿负0
+4. 涓嶈緭鍏ュ潗鏍囷紝妫�鏌ヨ窛绂绘槸鍚︿负0
+
+## 鐩稿叧鏂囦欢娓呭崟
+
+### 鏁版嵁搴撴枃浠�
+- `sql/task_tables.sql` - 鏂拌〃鍒涘缓鑴氭湰
+- `sql/add_gps_coordinates.sql` - 鐜版湁琛ㄦ洿鏂拌剼鏈�
+
+### Java鏂囦欢
+- `ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTask.java` - 瀹炰綋绫�
+- `ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskCreateVO.java` - 鍒涘缓VO
+- `ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/TaskUpdateVO.java` - 鏇存柊VO
+- `ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java` - 鏈嶅姟瀹炵幇
+- `ruoyi-system/src/main/resources/mapper/system/SysTaskMapper.xml` - MyBatis鏄犲皠
+- `ruoyi-common/src/main/java/com/ruoyi/common/utils/GpsDistanceUtils.java` - 宸ュ叿绫�
+
+## 娉ㄦ剰浜嬮」
+
+1. **鍧愭爣绯荤粺**锛氫娇鐢╓GS84鍧愭爣绯伙紙GPS鏍囧噯鍧愭爣绯伙級
+2. **绮惧害瑕佹眰**锛氱粡搴︾含搴﹀缓璁繚鐣�6-7浣嶅皬鏁�
+3. **璺濈鑼冨洿**锛氶�傜敤浜庝腑鐭窛绂昏绠楋紝闀胯窛绂诲彲鑳芥湁璇樊
+4. **鎬ц兘鑰冭檻**锛氬ぇ閲忔暟鎹椂鍙�冭檻娣诲姞绌洪棿绱㈠紩
+5. **鏁版嵁瀹屾暣鎬�**锛氬缓璁悓鏃舵彁渚涘湴鍧�鍜屽潗鏍囦俊鎭�
+
+## 鎵╁睍鍔熻兘寤鸿
+
+1. **鍦板浘闆嗘垚**锛氶泦鎴愬湴鍥続PI杩涜鍧愭爣閫夋嫨
+2. **璺緞瑙勫垝**锛氶泦鎴愯矾寰勮鍒扐PI璁$畻瀹為檯琛岄┒璺濈
+3. **鍘嗗彶杞ㄨ抗**锛氳褰曡溅杈嗗疄闄呰椹惰建杩�
+4. **璺濈缁熻**锛氭寜鏃堕棿娈电粺璁℃�昏椹惰窛绂�
+5. **鍦扮悊鍥存爮**锛氳缃换鍔℃墽琛岀殑鍦扮悊鑼冨洿
diff --git a/sql/add_gps_coordinates.sql b/sql/add_gps_coordinates.sql
new file mode 100644
index 0000000..8149539
--- /dev/null
+++ b/sql/add_gps_coordinates.sql
@@ -0,0 +1,22 @@
+-- 涓轰换鍔¤〃娣诲姞GPS鍧愭爣鍜岄璁″叕閲屾暟瀛楁
+-- 鎵ц姝よ剼鏈墠璇峰厛澶囦唤鏁版嵁搴�
+
+-- 娉ㄦ剰锛氬鏋滆〃宸插瓨鍦ㄤ絾缂哄皯鏃堕棿瀛楁锛岃鍏堟墽琛屼互涓嬭鍙ワ細
+-- ALTER TABLE sys_task MODIFY COLUMN create_time DATETIME NOT NULL COMMENT '鍒涘缓鏃堕棿';
+-- ALTER TABLE sys_task MODIFY COLUMN update_time DATETIME NOT NULL COMMENT '鏇存柊鏃堕棿';
+
+-- 1. 娣诲姞GPS鍧愭爣瀛楁
+ALTER TABLE sys_task ADD COLUMN departure_longitude DECIMAL(10,7) COMMENT '鍑哄彂鍦扮粡搴�';
+ALTER TABLE sys_task ADD COLUMN departure_latitude DECIMAL(10,7) COMMENT '鍑哄彂鍦扮含搴�';
+ALTER TABLE sys_task ADD COLUMN destination_longitude DECIMAL(10,7) COMMENT '鐩殑鍦扮粡搴�';
+ALTER TABLE sys_task ADD COLUMN destination_latitude DECIMAL(10,7) COMMENT '鐩殑鍦扮含搴�';
+ALTER TABLE sys_task ADD COLUMN estimated_distance DECIMAL(8,2) COMMENT '棰勮鍏噷鏁�';
+
+-- 2. 涓篏PS鍧愭爣瀛楁娣诲姞绱㈠紩锛堝彲閫夛紝鐢ㄤ簬鍦扮悊浣嶇疆鏌ヨ锛�
+-- ALTER TABLE sys_task ADD INDEX idx_departure_coords (departure_longitude, departure_latitude);
+-- ALTER TABLE sys_task ADD INDEX idx_destination_coords (destination_longitude, destination_latitude);
+
+-- 3. 楠岃瘉淇敼缁撴灉
+-- 鍙互鎵ц浠ヤ笅鏌ヨ鏉ラ獙璇佸瓧娈靛畾涔夛細
+-- SHOW CREATE TABLE sys_task;
+-- DESCRIBE sys_task;
diff --git a/sql/fix_task_vehicle_insert.sql b/sql/fix_task_vehicle_insert.sql
new file mode 100644
index 0000000..0fb9465
--- /dev/null
+++ b/sql/fix_task_vehicle_insert.sql
@@ -0,0 +1,28 @@
+-- 淇浠诲姟杞﹁締鍏宠仈琛ㄦ彃鍏ラ棶棰�
+-- 闂锛歛ssign_time 鍜� assign_by 瀛楁涓� NOT NULL锛屼絾鎻掑叆鏃跺彲鑳芥病鏈夊��
+
+-- 1. 妫�鏌ヨ〃缁撴瀯
+DESCRIBE sys_task_vehicle;
+
+-- 2. 娴嬭瘯鎻掑叆鏁版嵁锛堟ā鎷熶慨澶嶅悗鐨勬儏鍐碉級
+-- 娉ㄦ剰锛氳繖浜涘瓧娈电幇鍦ㄥ湪 Service 灞備細鑷姩璁剧疆
+INSERT INTO sys_task_vehicle (task_id, vehicle_id, assign_time, assign_by, status, remark)
+VALUES (1, 1, NOW(), 'admin', 'ASSIGNED', '娴嬭瘯鏁版嵁');
+
+-- 3. 楠岃瘉鎻掑叆缁撴灉
+SELECT * FROM sys_task_vehicle WHERE task_id = 1 AND vehicle_id = 1;
+
+-- 4. 娓呯悊娴嬭瘯鏁版嵁
+DELETE FROM sys_task_vehicle WHERE task_id = 1 AND vehicle_id = 1;
+
+-- 淇璇存槑锛�
+-- 1. 鍦� SysTaskVehicleServiceImpl.insertSysTaskVehicle() 鏂规硶涓�
+-- 鑷姩璁剧疆 assign_time 涓哄綋鍓嶆椂闂�
+-- 鑷姩璁剧疆 assign_by 涓哄綋鍓嶇敤鎴�
+-- 鑷姩璁剧疆 status 涓� 'ASSIGNED'锛堝鏋滄湭璁剧疆锛�
+--
+-- 2. 鍦� SysTaskVehicleMapper.xml 涓�
+-- assign_time 鍜� assign_by 瀛楁鎬绘槸琚寘鍚湪鎻掑叆璇彞涓�
+-- 涓嶅啀浣跨敤鏉′欢鍒ゆ柇锛屽洜涓鸿繖浜涘瓧娈垫槸蹇呴渶鐨�
+--
+-- 3. 杩欐牱纭繚浜嗘暟鎹簱绾︽潫寰楀埌婊¤冻锛岄伩鍏� "Field doesn't have a default value" 閿欒
diff --git a/sql/fix_update_time.sql b/sql/fix_update_time.sql
new file mode 100644
index 0000000..0e72df2
--- /dev/null
+++ b/sql/fix_update_time.sql
@@ -0,0 +1,12 @@
+-- 淇 sys_task 琛� update_time 瀛楁娌℃湁榛樿鍊肩殑闂
+-- 鎵ц姝よ剼鏈墠璇峰厛澶囦唤鏁版嵁搴�
+
+-- 1. 淇敼 create_time 瀛楁
+ALTER TABLE sys_task MODIFY COLUMN create_time DATETIME NOT NULL COMMENT '鍒涘缓鏃堕棿';
+
+-- 2. 淇敼 update_time 瀛楁
+ALTER TABLE sys_task MODIFY COLUMN update_time DATETIME NOT NULL COMMENT '鏇存柊鏃堕棿';
+
+-- 3. 楠岃瘉淇敼缁撴灉
+-- 鍙互鎵ц浠ヤ笅鏌ヨ鏉ラ獙璇佸瓧娈靛畾涔夛細
+-- SHOW CREATE TABLE sys_task;
diff --git a/sql/task_dict_data.sql b/sql/task_dict_data.sql
index cad5c34..020257c 100644
--- a/sql/task_dict_data.sql
+++ b/sql/task_dict_data.sql
@@ -4,36 +4,73 @@
-- 1. 浠诲姟绫诲瀷瀛楀吀
-- ----------------------------
-INSERT INTO sys_dict_type VALUES ('sys_task_type', '浠诲姟绫诲瀷', '0', 'admin', sysdate(), '', null, '浠诲姟绫诲瀷鍒楄〃');
-INSERT INTO sys_dict_data VALUES (1, 1, '缁翠慨淇濆吇', 'MAINTENANCE', 'sys_task_type', '', 'primary', 'N', '0', 'admin', sysdate(), '', null, '缁翠慨淇濆吇浠诲姟');
-INSERT INTO sys_dict_data VALUES (2, 2, '鍔犳补浠诲姟', 'FUEL', 'sys_task_type', '', 'success', 'N', '0', 'admin', sysdate(), '', null, '鍔犳补浠诲姟');
-INSERT INTO sys_dict_data VALUES (3, 3, '鍏朵粬', 'OTHER', 'sys_task_type', '', 'info', 'N', '0', 'admin', sysdate(), '', null, '鍏朵粬绫诲瀷浠诲姟');
+INSERT INTO sys_dict_type(dict_name, dict_type, status, create_by, create_time, update_by, update_time, remark)
+VALUES('浠诲姟绫诲瀷', 'sys_task_type', '0', 'admin', SYSDATE(), '', NULL, '浠诲姟绫诲瀷鍒楄〃');
+
+INSERT INTO sys_dict_data(dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, update_by, update_time, remark)
+VALUES(1, '缁翠慨淇濆吇', 'MAINTENANCE', 'sys_task_type', '', 'primary', 'N', '0', 'admin', SYSDATE(), '', NULL, '缁翠慨淇濆吇浠诲姟');
+
+INSERT INTO sys_dict_data(dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, update_by, update_time, remark)
+VALUES(2, '鍔犳补浠诲姟', 'FUEL', 'sys_task_type', '', 'success', 'N', '0', 'admin', SYSDATE(), '', NULL, '鍔犳补浠诲姟');
+
+INSERT INTO sys_dict_data(dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, update_by, update_time, remark)
+VALUES(3, '鍏朵粬', 'OTHER', 'sys_task_type', '', 'info', 'N', '0', 'admin', SYSDATE(), '', NULL, '鍏朵粬绫诲瀷浠诲姟');
-- 2. 浠诲姟鐘舵�佸瓧鍏�
-- ----------------------------
-INSERT INTO sys_dict_type VALUES ('sys_task_status', '浠诲姟鐘舵��', '0', 'admin', sysdate(), '', null, '浠诲姟鐘舵�佸垪琛�');
-INSERT INTO sys_dict_data VALUES (4, 1, '寰呭紑濮�', 'PENDING', 'sys_task_status', '', 'warning', 'N', '0', 'admin', sysdate(), '', null, '浠诲姟宸插垱寤猴紝绛夊緟寮�濮�');
-INSERT INTO sys_dict_data VALUES (5, 2, '浠诲姟涓�', 'IN_PROGRESS', 'sys_task_status', '', 'primary', 'N', '0', 'admin', sysdate(), '', null, '浠诲姟宸茬粡寮�濮�');
-INSERT INTO sys_dict_data VALUES (6, 3, '宸插畬鎴�', 'COMPLETED', 'sys_task_status', '', 'success', 'N', '0', 'admin', sysdate(), '', null, '浠诲姟宸插畬鎴�');
-INSERT INTO sys_dict_data VALUES (7, 4, '宸插彇娑�', 'CANCELLED', 'sys_task_status', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '浠诲姟宸插彇娑�');
+INSERT INTO sys_dict_type(dict_name, dict_type, status, create_by, create_time, update_by, update_time, remark)
+VALUES('浠诲姟鐘舵��', 'sys_task_status', '0', 'admin', SYSDATE(), '', NULL, '浠诲姟鐘舵�佸垪琛�');
+
+INSERT INTO sys_dict_data(dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, update_by, update_time, remark)
+VALUES(1, '寰呭紑濮�', 'PENDING', 'sys_task_status', '', 'warning', 'N', '0', 'admin', SYSDATE(), '', NULL, '浠诲姟宸插垱寤猴紝绛夊緟寮�濮�');
+
+INSERT INTO sys_dict_data(dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, update_by, update_time, remark)
+VALUES(2, '浠诲姟涓�', 'IN_PROGRESS', 'sys_task_status', '', 'primary', 'N', '0', 'admin', SYSDATE(), '', NULL, '浠诲姟宸茬粡寮�濮�');
+
+INSERT INTO sys_dict_data(dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, update_by, update_time, remark)
+VALUES(3, '宸插畬鎴�', 'COMPLETED', 'sys_task_status', '', 'success', 'N', '0', 'admin', SYSDATE(), '', NULL, '浠诲姟宸插畬鎴�');
+
+INSERT INTO sys_dict_data(dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, update_by, update_time, remark)
+VALUES(4, '宸插彇娑�', 'CANCELLED', 'sys_task_status', '', 'danger', 'N', '0', 'admin', SYSDATE(), '', NULL, '浠诲姟宸插彇娑�');
-- 3. 杞﹁締绫诲瀷瀛楀吀
-- ----------------------------
-INSERT INTO sys_dict_type VALUES ('sys_vehicle_type', '杞﹁締绫诲瀷', '0', 'admin', sysdate(), '', null, '杞﹁締绫诲瀷鍒楄〃');
-INSERT INTO sys_dict_data VALUES (8, 1, '鏁戞姢杞�', 'AMBULANCE', 'sys_vehicle_type', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '鏁戞姢杞�');
-INSERT INTO sys_dict_data VALUES (9, 2, '杞繍杞�', 'TRANSFER', 'sys_vehicle_type', '', 'primary', 'N', '0', 'admin', sysdate(), '', null, '杞繍杞�');
-INSERT INTO sys_dict_data VALUES (10, 3, '缁翠慨杞�', 'MAINTENANCE', 'sys_vehicle_type', '', 'warning', 'N', '0', 'admin', sysdate(), '', null, '缁翠慨杞�');
+INSERT INTO sys_dict_type(dict_name, dict_type, status, create_by, create_time, update_by, update_time, remark)
+VALUES('杞﹁締绫诲瀷', 'sys_vehicle_type', '0', 'admin', SYSDATE(), '', NULL, '杞﹁締绫诲瀷鍒楄〃');
+
+INSERT INTO sys_dict_data(dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, update_by, update_time, remark)
+VALUES(1, '鏁戞姢杞�', 'AMBULANCE', 'sys_vehicle_type', '', 'danger', 'N', '0', 'admin', SYSDATE(), '', NULL, '鏁戞姢杞�');
+
+INSERT INTO sys_dict_data(dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, update_by, update_time, remark)
+VALUES(2, '杞繍杞�', 'TRANSFER', 'sys_vehicle_type', '', 'primary', 'N', '0', 'admin', SYSDATE(), '', NULL, '杞繍杞�');
+
+INSERT INTO sys_dict_data(dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, update_by, update_time, remark)
+VALUES(3, '缁翠慨杞�', 'MAINTENANCE', 'sys_vehicle_type', '', 'warning', 'N', '0', 'admin', SYSDATE(), '', NULL, '缁翠慨杞�');
-- 4. 杞﹁締鐘舵�佸瓧鍏�
-- ----------------------------
-INSERT INTO sys_dict_type VALUES ('sys_vehicle_status', '杞﹁締鐘舵��', '0', 'admin', sysdate(), '', null, '杞﹁締鐘舵�佸垪琛�');
-INSERT INTO sys_dict_data VALUES (11, 1, '姝e父', '0', 'sys_vehicle_status', '', 'success', 'N', '0', 'admin', sysdate(), '', null, '杞﹁締姝e父浣跨敤');
-INSERT INTO sys_dict_data VALUES (12, 2, '鍋滅敤', '1', 'sys_vehicle_status', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '杞﹁締鍋滅敤');
+INSERT INTO sys_dict_type(dict_name, dict_type, status, create_by, create_time, update_by, update_time, remark)
+VALUES('杞﹁締鐘舵��', 'sys_vehicle_status', '0', 'admin', SYSDATE(), '', NULL, '杞﹁締鐘舵�佸垪琛�');
+
+INSERT INTO sys_dict_data(dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, update_by, update_time, remark)
+VALUES(1, '姝e父', '0', 'sys_vehicle_status', '', 'success', 'N', '0', 'admin', SYSDATE(), '', NULL, '杞﹁締姝e父浣跨敤');
+
+INSERT INTO sys_dict_data(dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, update_by, update_time, remark)
+VALUES(2, '鍋滅敤', '1', 'sys_vehicle_status', '', 'danger', 'N', '0', 'admin', SYSDATE(), '', NULL, '杞﹁締鍋滅敤');
-- 5. 浠诲姟杞﹁締鍏宠仈鐘舵�佸瓧鍏�
-- ----------------------------
-INSERT INTO sys_dict_type VALUES ('sys_task_vehicle_status', '浠诲姟杞﹁締鍏宠仈鐘舵��', '0', 'admin', sysdate(), '', null, '浠诲姟杞﹁締鍏宠仈鐘舵�佸垪琛�');
-INSERT INTO sys_dict_data VALUES (15, 1, '宸插垎閰�', 'ASSIGNED', 'sys_task_vehicle_status', '', 'primary', 'N', '0', 'admin', sysdate(), '', null, '杞﹁締宸插垎閰嶇粰浠诲姟');
-INSERT INTO sys_dict_data VALUES (16, 2, '鎵ц涓�', 'ACTIVE', 'sys_task_vehicle_status', '', 'success', 'N', '0', 'admin', sysdate(), '', null, '杞﹁締姝e湪鎵ц浠诲姟');
-INSERT INTO sys_dict_data VALUES (17, 3, '宸插畬鎴�', 'COMPLETED', 'sys_task_vehicle_status', '', 'info', 'N', '0', 'admin', sysdate(), '', null, '杞﹁締浠诲姟宸插畬鎴�');
-INSERT INTO sys_dict_data VALUES (18, 4, '宸插彇娑�', 'CANCELLED', 'sys_task_vehicle_status', '', 'danger', 'N', '0', 'admin', sysdate(), '', null, '杞﹁締浠诲姟宸插彇娑�');
+INSERT INTO sys_dict_type(dict_name, dict_type, status, create_by, create_time, update_by, update_time, remark)
+VALUES('浠诲姟杞﹁締鍏宠仈鐘舵��', 'sys_task_vehicle_status', '0', 'admin', SYSDATE(), '', NULL, '浠诲姟杞﹁締鍏宠仈鐘舵�佸垪琛�');
+
+INSERT INTO sys_dict_data(dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, update_by, update_time, remark)
+VALUES(1, '宸插垎閰�', 'ASSIGNED', 'sys_task_vehicle_status', '', 'primary', 'N', '0', 'admin', SYSDATE(), '', NULL, '杞﹁締宸插垎閰嶇粰浠诲姟');
+
+INSERT INTO sys_dict_data(dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, update_by, update_time, remark)
+VALUES(2, '鎵ц涓�', 'ACTIVE', 'sys_task_vehicle_status', '', 'success', 'N', '0', 'admin', SYSDATE(), '', NULL, '杞﹁締姝e湪鎵ц浠诲姟');
+
+INSERT INTO sys_dict_data(dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, update_by, update_time, remark)
+VALUES(3, '宸插畬鎴�', 'COMPLETED', 'sys_task_vehicle_status', '', 'info', 'N', '0', 'admin', SYSDATE(), '', NULL, '杞﹁締浠诲姟宸插畬鎴�');
+
+INSERT INTO sys_dict_data(dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, update_by, update_time, remark)
+VALUES(4, '宸插彇娑�', 'CANCELLED', 'sys_task_vehicle_status', '', 'danger', 'N', '0', 'admin', SYSDATE(), '', NULL, '杞﹁締浠诲姟宸插彇娑�');
diff --git a/sql/task_menu.sql b/sql/task_menu.sql
index 2c254b9..cdfb9df 100644
--- a/sql/task_menu.sql
+++ b/sql/task_menu.sql
@@ -3,25 +3,63 @@
-- ----------------------------
-- 浠诲姟绠$悊鑿滃崟
-INSERT INTO sys_menu VALUES (2000, '浠诲姟绠$悊', 0, 5, 'task', null, '', 1, 0, 'M', '0', '0', '', 'task', 'admin', sysdate(), '', null, '浠诲姟绠$悊鐩綍');
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('浠诲姟绠$悊', '0', '5', 'task', null, 1, 0, 'M', '0', '0', '', 'task', 'admin', sysdate(), '', null, '浠诲姟绠$悊鐩綍');
+
+-- 浠诲姟绠$悊鐖惰彍鍗旾D
+SELECT @taskParentId := LAST_INSERT_ID();
-- 閫氱敤浠诲姟鑿滃崟
-INSERT INTO sys_menu VALUES (2001, '閫氱敤浠诲姟', 2000, 1, 'general', 'task/general/index', '', 1, 0, 'C', '0', '0', 'task:general:view', 'list', 'admin', sysdate(), '', null, '閫氱敤浠诲姟鑿滃崟');
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('閫氱敤浠诲姟', @taskParentId, '1', 'general', 'task/general/index', 1, 0, 'C', '0', '0', 'task:general:view', 'list', 'admin', sysdate(), '', null, '閫氱敤浠诲姟鑿滃崟');
--- 浠诲姟绠$悊鎸夐挳鏉冮檺
-INSERT INTO sys_menu VALUES (2002, '浠诲姟鏌ヨ', 2001, 1, '', '', '', 1, 0, 'F', '0', '0', 'task:general:query', '#', 'admin', sysdate(), '', null, '');
-INSERT INTO sys_menu VALUES (2003, '浠诲姟鏂板', 2001, 2, '', '', '', 1, 0, 'F', '0', '0', 'task:general:add', '#', 'admin', sysdate(), '', null, '');
-INSERT INTO sys_menu VALUES (2004, '浠诲姟淇敼', 2001, 3, '', '', '', 1, 0, 'F', '0', '0', 'task:general:edit', '#', 'admin', sysdate(), '', null, '');
-INSERT INTO sys_menu VALUES (2005, '浠诲姟鍒犻櫎', 2001, 4, '', '', '', 1, 0, 'F', '0', '0', 'task:general:remove', '#', 'admin', sysdate(), '', null, '');
-INSERT INTO sys_menu VALUES (2006, '浠诲姟鍒嗛厤', 2001, 5, '', '', '', 1, 0, 'F', '0', '0', 'task:general:assign', '#', 'admin', sysdate(), '', null, '');
-INSERT INTO sys_menu VALUES (2007, '鐘舵�佸彉鏇�', 2001, 6, '', '', '', 1, 0, 'F', '0', '0', 'task:general:status', '#', 'admin', sysdate(), '', null, '');
+-- 閫氱敤浠诲姟鎸夐挳鐖惰彍鍗旾D
+SELECT @generalParentId := LAST_INSERT_ID();
+
+-- 閫氱敤浠诲姟鎸夐挳 SQL
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('浠诲姟鏌ヨ', @generalParentId, '1', '#', '', 1, 0, 'F', '0', '0', 'task:general:query', '#', 'admin', sysdate(), '', null, '');
+
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('浠诲姟鏂板', @generalParentId, '2', '#', '', 1, 0, 'F', '0', '0', 'task:general:add', '#', 'admin', sysdate(), '', null, '');
+
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('浠诲姟淇敼', @generalParentId, '3', '#', '', 1, 0, 'F', '0', '0', 'task:general:edit', '#', 'admin', sysdate(), '', null, '');
+
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('浠诲姟鍒犻櫎', @generalParentId, '4', '#', '', 1, 0, 'F', '0', '0', 'task:general:remove', '#', 'admin', sysdate(), '', null, '');
+
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('浠诲姟鍒嗛厤', @generalParentId, '5', '#', '', 1, 0, 'F', '0', '0', 'task:general:assign', '#', 'admin', sysdate(), '', null, '');
+
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('鐘舵�佸彉鏇�', @generalParentId, '6', '#', '', 1, 0, 'F', '0', '0', 'task:general:status', '#', 'admin', sysdate(), '', null, '');
-- 杞﹁締绠$悊鑿滃崟
-INSERT INTO sys_menu VALUES (2008, '杞﹁締绠$悊', 2000, 2, 'vehicle', 'task/vehicle/index', '', 1, 0, 'C', '0', '0', 'task:vehicle:view', 'car', 'admin', sysdate(), '', null, '杞﹁締绠$悊鑿滃崟');
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('杞﹁締绠$悊', @taskParentId, '2', 'vehicle', 'task/vehicle/index', 1, 0, 'C', '0', '0', 'task:vehicle:view', 'car', 'admin', sysdate(), '', null, '杞﹁締绠$悊鑿滃崟');
--- 杞﹁締绠$悊鎸夐挳鏉冮檺
-INSERT INTO sys_menu VALUES (2009, '杞﹁締鏌ヨ', 2008, 1, '', '', '', 1, 0, 'F', '0', '0', 'task:vehicle:query', '#', 'admin', sysdate(), '', null, '');
-INSERT INTO sys_menu VALUES (2010, '杞﹁締鏂板', 2008, 2, '', '', '', 1, 0, 'F', '0', '0', 'task:vehicle:add', '#', 'admin', sysdate(), '', null, '');
-INSERT INTO sys_menu VALUES (2011, '杞﹁締淇敼', 2008, 3, '', '', '', 1, 0, 'F', '0', '0', 'task:vehicle:edit', '#', 'admin', sysdate(), '', null, '');
-INSERT INTO sys_menu VALUES (2012, '杞﹁締鍒犻櫎', 2008, 4, '', '', '', 1, 0, 'F', '0', '0', 'task:vehicle:remove', '#', 'admin', sysdate(), '', null, '');
-INSERT INTO sys_menu VALUES (2013, '杞﹁締鍒嗛厤', 2008, 5, '', '', '', 1, 0, 'F', '0', '0', 'task:vehicle:assign', '#', 'admin', sysdate(), '', null, '');
+-- 杞﹁締绠$悊鎸夐挳鐖惰彍鍗旾D
+SELECT @vehicleParentId := LAST_INSERT_ID();
+
+-- 杞﹁締绠$悊鎸夐挳 SQL
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('杞﹁締鏌ヨ', @vehicleParentId, '1', '#', '', 1, 0, 'F', '0', '0', 'task:vehicle:query', '#', 'admin', sysdate(), '', null, '');
+
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('杞﹁締鏂板', @vehicleParentId, '2', '#', '', 1, 0, 'F', '0', '0', 'task:vehicle:add', '#', 'admin', sysdate(), '', null, '');
+
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('杞﹁締淇敼', @vehicleParentId, '3', '#', '', 1, 0, 'F', '0', '0', 'task:vehicle:edit', '#', 'admin', sysdate(), '', null, '');
+
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('杞﹁締鍒犻櫎', @vehicleParentId, '4', '#', '', 1, 0, 'F', '0', '0', 'task:vehicle:remove', '#', 'admin', sysdate(), '', null, '');
+
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('杞﹁締鍒嗛厤', @vehicleParentId, '5', '#', '', 1, 0, 'F', '0', '0', 'task:vehicle:assign', '#', 'admin', sysdate(), '', null, '');
+
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('杞﹁締瀵煎嚭', @vehicleParentId, '6', '#', '', 1, 0, 'F', '0', '0', 'task:vehicle:export', '#', 'admin', sysdate(), '', null, '');
+
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('杞﹁締鍒楄〃', @vehicleParentId, '7', '#', '', 1, 0, 'F', '0', '0', 'task:vehicle:list', '#', 'admin', sysdate(), '', null, '');
\ No newline at end of file
diff --git a/sql/task_tables.sql b/sql/task_tables.sql
index 4983473..ab8e4d3 100644
--- a/sql/task_tables.sql
+++ b/sql/task_tables.sql
@@ -16,6 +16,13 @@
departure_address VARCHAR(500) COMMENT '鍑哄彂鍦板潃',
destination_address VARCHAR(500) COMMENT '鐩殑鍦板潃',
+ -- GPS鍧愭爣淇℃伅
+ departure_longitude DECIMAL(10,7) COMMENT '鍑哄彂鍦扮粡搴�',
+ departure_latitude DECIMAL(10,7) COMMENT '鍑哄彂鍦扮含搴�',
+ destination_longitude DECIMAL(10,7) COMMENT '鐩殑鍦扮粡搴�',
+ destination_latitude DECIMAL(10,7) COMMENT '鐩殑鍦扮含搴�',
+ estimated_distance DECIMAL(8,2) COMMENT '棰勮鍏噷鏁�',
+
-- 鏃堕棿淇℃伅
planned_start_time DATETIME COMMENT '璁″垝寮�濮嬫椂闂�',
planned_end_time DATETIME COMMENT '璁″垝缁撴潫鏃堕棿',
@@ -28,8 +35,8 @@
dept_id BIGINT NOT NULL COMMENT '褰掑睘閮ㄩ棬ID',
-- 绯荤粺瀛楁
- create_time DATETIME NOT NULL COMMENT '鍒涘缓鏃堕棿',
- update_time DATETIME NOT NULL COMMENT '鏇存柊鏃堕棿',
+ create_time DATETIME NOT NULL COMMENT '鍒涘缓鏃堕棿',
+ update_time DATETIME NOT NULL COMMENT '鏇存柊鏃堕棿',
create_by VARCHAR(64) NOT NULL COMMENT '鍒涘缓鑰�',
update_by VARCHAR(64) COMMENT '鏇存柊鑰�',
remark VARCHAR(500) COMMENT '澶囨敞',
diff --git "a/sql/\346\227\266\351\227\264\345\255\227\346\256\265\346\233\264\346\226\260\350\257\264\346\230\216.md" "b/sql/\346\227\266\351\227\264\345\255\227\346\256\265\346\233\264\346\226\260\350\257\264\346\230\216.md"
new file mode 100644
index 0000000..670722d
--- /dev/null
+++ "b/sql/\346\227\266\351\227\264\345\255\227\346\256\265\346\233\264\346\226\260\350\257\264\346\230\216.md"
@@ -0,0 +1,117 @@
+# 浠诲姟绠$悊鏃堕棿瀛楁鏇存柊璇存槑
+
+## 淇敼姒傝堪
+
+涓轰簡纭繚鍦ㄤ换鍔$鐞嗙殑澧炲垹鏀规煡鎿嶄綔涓紝`create_time` 鍜� `update_time` 瀛楁鑳藉姝g‘鏇存柊锛屾垜浠浠ヤ笅鏂囦欢杩涜浜嗕慨鏀癸細
+
+## 1. 鏁版嵁搴撹〃缁撴瀯淇敼
+
+### 鏂囦欢锛歚sql/task_tables.sql`
+- 涓� `create_time` 瀛楁娣诲姞榛樿鍊硷細`DEFAULT CURRENT_TIMESTAMP`
+- 涓� `update_time` 瀛楁娣诲姞榛樿鍊煎拰鑷姩鏇存柊锛歚DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP`
+
+### 鏂囦欢锛歚sql/fix_update_time.sql`
+- 鍒涘缓浜嗘暟鎹簱淇鑴氭湰锛岀敤浜庢洿鏂扮幇鏈夋暟鎹簱琛ㄧ粨鏋�
+
+## 2. MyBatis 鏄犲皠鏂囦欢淇敼
+
+### 鏂囦欢锛歚ruoyi-system/src/main/resources/mapper/system/SysTaskMapper.xml`
+
+#### 鎻掑叆鎿嶄綔 (`insertSysTask`)
+- 淇敼鍓嶏細鍙湁褰� `updateTime` 涓嶄负 null 鏃舵墠鍖呭惈璇ュ瓧娈�
+- 淇敼鍚庯細鎬绘槸鍖呭惈 `update_time` 瀛楁锛屼娇鐢� `now()` 鍑芥暟璁剧疆褰撳墠鏃堕棿
+
+#### 鏇存柊鎿嶄綔 (`updateSysTask`)
+- 淇濇寔鍘熸湁閫昏緫锛岄�氳繃 Service 灞傝缃� `updateTime`
+
+#### 鍒嗛厤浠诲姟鎿嶄綔 (`assignTask`)
+- 淇敼鍓嶏細浣跨敤 `now()` 鍑芥暟
+- 淇敼鍚庯細浣跨敤 `#{updateTime}` 鍙傛暟锛岀敱 Service 灞傛帶鍒�
+
+#### 鐘舵�佸彉鏇存搷浣� (`updateTaskStatus`)
+- 淇敼鍓嶏細浣跨敤 `now()` 鍑芥暟
+- 淇敼鍚庯細浣跨敤 `#{updateTime}` 鍙傛暟锛岀敱 Service 灞傛帶鍒�
+
+#### 鍒犻櫎鎿嶄綔 (`deleteSysTaskByTaskId` 鍜� `deleteSysTaskByTaskIds`)
+- 娣诲姞 `update_time = now()` 纭繚鍒犻櫎鏃朵篃鏇存柊鏃堕棿
+
+## 3. Service 灞備慨鏀�
+
+### 鏂囦欢锛歚ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java`
+
+#### 鏂板浠诲姟 (`insertSysTask`)
+- 娣诲姞 `task.setUpdateTime(DateUtils.getNowDate())` 纭繚鍒涘缓鏃朵篃璁剧疆鏇存柊鏃堕棿
+
+#### 淇敼浠诲姟 (`updateSysTask`)
+- 淇濇寔鍘熸湁閫昏緫锛屾纭缃� `updateTime`
+
+#### 鍒嗛厤浠诲姟 (`assignTask`)
+- 娣诲姞 `task.setUpdateTime(DateUtils.getNowDate())` 纭繚鍒嗛厤鏃舵洿鏂版椂闂�
+
+#### 鐘舵�佸彉鏇� (`changeTaskStatus`)
+- 娣诲姞 `task.setUpdateTime(DateUtils.getNowDate())` 纭繚鐘舵�佸彉鏇存椂鏇存柊鏃堕棿
+
+## 4. 鏃堕棿瀛楁鏇存柊瑙勫垯
+
+### 鍒涘缓鎿嶄綔
+- `create_time`锛氳缃负褰撳墠鏃堕棿
+- `update_time`锛氳缃负褰撳墠鏃堕棿
+- `create_by`锛氳缃负褰撳墠鐢ㄦ埛
+- `update_by`锛氳缃负褰撳墠鐢ㄦ埛
+
+### 鏇存柊鎿嶄綔
+- `update_time`锛氳缃负褰撳墠鏃堕棿
+- `update_by`锛氳缃负褰撳墠鐢ㄦ埛
+
+### 鍒犻櫎鎿嶄綔
+- `update_time`锛氳缃负褰撳墠鏃堕棿锛堥�氳繃 SQL 鐨� `now()` 鍑芥暟锛�
+
+### 鍒嗛厤鎿嶄綔
+- `update_time`锛氳缃负褰撳墠鏃堕棿
+- `update_by`锛氳缃负褰撳墠鐢ㄦ埛
+
+### 鐘舵�佸彉鏇存搷浣�
+- `update_time`锛氳缃负褰撳墠鏃堕棿
+- `update_by`锛氳缃负褰撳墠鐢ㄦ埛
+- 鏍规嵁鐘舵�佸彲鑳借缃� `actual_start_time` 鎴� `actual_end_time`
+
+## 5. 鎵ц姝ラ
+
+### 瀵逛簬鏂伴儴缃�
+1. 鐩存帴浣跨敤淇敼鍚庣殑 `sql/task_tables.sql` 鍒涘缓琛�
+
+### 瀵逛簬鐜版湁鏁版嵁搴�
+1. 鎵ц `sql/fix_update_time.sql` 鑴氭湰淇鐜版湁琛ㄧ粨鏋�
+2. 閲嶆柊閮ㄧ讲搴旂敤绋嬪簭
+
+## 6. 楠岃瘉鏂规硶
+
+### 鏁版嵁搴撻獙璇�
+```sql
+-- 鏌ョ湅琛ㄧ粨鏋�
+SHOW CREATE TABLE sys_task;
+
+-- 楠岃瘉瀛楁瀹氫箟
+DESCRIBE sys_task;
+```
+
+### 鍔熻兘楠岃瘉
+1. 鍒涘缓鏂颁换鍔★紝妫�鏌� `create_time` 鍜� `update_time` 鏄惁姝g‘璁剧疆
+2. 淇敼浠诲姟锛屾鏌� `update_time` 鏄惁姝g‘鏇存柊
+3. 鍒犻櫎浠诲姟锛屾鏌� `update_time` 鏄惁姝g‘鏇存柊
+4. 鍒嗛厤浠诲姟锛屾鏌� `update_time` 鏄惁姝g‘鏇存柊
+5. 鍙樻洿浠诲姟鐘舵�侊紝妫�鏌� `update_time` 鏄惁姝g‘鏇存柊
+
+## 7. 娉ㄦ剰浜嬮」
+
+1. **鏁版嵁搴撳吋瀹规��**锛氫慨鏀瑰悗鐨� SQL 璇彞鍏煎 MySQL 5.7+ 鐗堟湰
+2. **鏃跺尯璁剧疆**锛氱‘淇濇暟鎹簱鍜屽簲鐢ㄦ湇鍔″櫒鐨勬椂鍖鸿缃竴鑷�
+3. **鎬ц兘褰卞搷**锛氫娇鐢� `now()` 鍑芥暟瀵规�ц兘褰卞搷寰堝皬
+4. **鏁版嵁涓�鑷存��**锛氭墍鏈夋椂闂村瓧娈甸兘浣跨敤缁熶竴鐨勬椂闂存簮锛岀‘淇濇暟鎹竴鑷存��
+
+## 8. 鐩稿叧鏂囦欢娓呭崟
+
+- `sql/task_tables.sql` - 鏁版嵁搴撹〃缁撴瀯瀹氫箟
+- `sql/fix_update_time.sql` - 鏁版嵁搴撲慨澶嶈剼鏈�
+- `ruoyi-system/src/main/resources/mapper/system/SysTaskMapper.xml` - MyBatis 鏄犲皠鏂囦欢
+- `ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java` - Service 瀹炵幇绫�
--
Gitblit v1.9.1