瀏覽代碼

Merge branch 'fanghuisheng' of uskycloud/usky-web-mobile into master

gez 10 月之前
父節點
當前提交
97051cdc25
共有 100 個文件被更改,包括 3461 次插入931 次删除
  1. 247 0
      src/api/business/meeting.js
  2. 30 50
      src/components/oa-calendar/uni-calendar.vue
  3. 14 1
      src/components/oa-scroll/index.vue
  4. 149 158
      src/manifest.json
  5. 36 12
      src/pages.json
  6. 79 0
      src/pages/business/common/meeting/components/avatarList.vue
  7. 208 0
      src/pages/business/common/meeting/components/timeSlot.vue
  8. 383 0
      src/pages/business/common/meeting/index.vue
  9. 210 0
      src/pages/business/common/meeting/new/index.vue
  10. 13 11
      src/pages/business/common/projectMange/list/addEdit.vue
  11. 15 0
      src/pages/business/common/projectMange/mall/components/mall-list.vue
  12. 17 12
      src/pages/business/common/projectMange/mall/index.vue
  13. 4 7
      src/pages/business/common/projectMange/record/details.vue
  14. 36 50
      src/pages/business/common/projectMange/record/timingLog.vue
  15. 107 136
      src/pages/business/common/projectMange/write/components/template1.vue
  16. 1 1
      src/pages/business/common/projectMange/write/index.vue
  17. 7 10
      src/pages/business/common/projectMange/write/insert.vue
  18. 1 2
      src/pages/business/fireIot/facilitiesGather/mapGather.vue
  19. 1 1
      src/pages/business/fireIot/facilitiesManage/mapFacilitiesView.vue
  20. 13 2
      src/pages/business/zhaf/xunJian/plan/index.vue
  21. 1 1
      src/pages/business/zhaf/xunJian/xunJian.vue
  22. 61 55
      src/pages/common/face/index.vue
  23. 1 1
      src/pages/index.vue
  24. 205 191
      src/static/face/index.html
  25. 5 0
      src/static/face/js/vue.global.prod.js
  26. 1 1
      src/static/scss/colorui.css
  27. 32 0
      src/static/scss/index.scss
  28. 3 0
      src/store/modules/system.js
  29. 7 1
      src/store/modules/user.js
  30. 251 0
      src/uni_modules/uview-plus/changelog.md
  31. 3 3
      src/uni_modules/uview-plus/components/u--form/u--form.vue
  32. 3 3
      src/uni_modules/uview-plus/components/u--image/u--image.vue
  33. 3 3
      src/uni_modules/uview-plus/components/u--input/u--input.vue
  34. 3 3
      src/uni_modules/uview-plus/components/u--text/u--text.vue
  35. 3 3
      src/uni_modules/uview-plus/components/u--textarea/u--textarea.vue
  36. 26 0
      src/uni_modules/uview-plus/components/u-action-sheet/actionSheet.js
  37. 11 4
      src/uni_modules/uview-plus/components/u-action-sheet/props.js
  38. 14 13
      src/uni_modules/uview-plus/components/u-action-sheet/u-action-sheet.vue
  39. 27 0
      src/uni_modules/uview-plus/components/u-album/album.js
  40. 24 3
      src/uni_modules/uview-plus/components/u-album/props.js
  41. 43 29
      src/uni_modules/uview-plus/components/u-album/u-album.vue
  42. 22 0
      src/uni_modules/uview-plus/components/u-alert/alert.js
  43. 4 3
      src/uni_modules/uview-plus/components/u-alert/props.js
  44. 3 3
      src/uni_modules/uview-plus/components/u-alert/u-alert.vue
  45. 23 0
      src/uni_modules/uview-plus/components/u-avatar-group/avatarGroup.js
  46. 4 3
      src/uni_modules/uview-plus/components/u-avatar-group/props.js
  47. 3 3
      src/uni_modules/uview-plus/components/u-avatar-group/u-avatar-group.vue
  48. 28 0
      src/uni_modules/uview-plus/components/u-avatar/avatar.js
  49. 4 3
      src/uni_modules/uview-plus/components/u-avatar/props.js
  50. 3 3
      src/uni_modules/uview-plus/components/u-avatar/u-avatar.vue
  51. 27 0
      src/uni_modules/uview-plus/components/u-back-top/backtop.js
  52. 4 3
      src/uni_modules/uview-plus/components/u-back-top/props.js
  53. 3 3
      src/uni_modules/uview-plus/components/u-back-top/u-back-top.vue
  54. 27 0
      src/uni_modules/uview-plus/components/u-badge/badge.js
  55. 4 3
      src/uni_modules/uview-plus/components/u-badge/props.js
  56. 3 3
      src/uni_modules/uview-plus/components/u-badge/u-badge.vue
  57. 27 0
      src/uni_modules/uview-plus/components/u-box/props.js
  58. 92 0
      src/uni_modules/uview-plus/components/u-box/u-box.vue
  59. 42 0
      src/uni_modules/uview-plus/components/u-button/button.js
  60. 4 3
      src/uni_modules/uview-plus/components/u-button/props.js
  61. 6 6
      src/uni_modules/uview-plus/components/u-button/u-button.vue
  62. 42 0
      src/uni_modules/uview-plus/components/u-calendar/calendar.js
  63. 4 2
      src/uni_modules/uview-plus/components/u-calendar/header.vue
  64. 6 4
      src/uni_modules/uview-plus/components/u-calendar/month.vue
  65. 5 3
      src/uni_modules/uview-plus/components/u-calendar/props.js
  66. 3 3
      src/uni_modules/uview-plus/components/u-calendar/u-calendar.vue
  67. 15 0
      src/uni_modules/uview-plus/components/u-car-keyboard/carKeyboard.js
  68. 5 3
      src/uni_modules/uview-plus/components/u-car-keyboard/props.js
  69. 5 5
      src/uni_modules/uview-plus/components/u-car-keyboard/u-car-keyboard.vue
  70. 140 0
      src/uni_modules/uview-plus/components/u-card/props.js
  71. 186 0
      src/uni_modules/uview-plus/components/u-card/u-card.vue
  72. 17 0
      src/uni_modules/uview-plus/components/u-cell-group/cellGroup.js
  73. 4 3
      src/uni_modules/uview-plus/components/u-cell-group/props.js
  74. 3 3
      src/uni_modules/uview-plus/components/u-cell-group/u-cell-group.vue
  75. 35 0
      src/uni_modules/uview-plus/components/u-cell/cell.js
  76. 4 3
      src/uni_modules/uview-plus/components/u-cell/props.js
  77. 25 4
      src/uni_modules/uview-plus/components/u-cell/u-cell.vue
  78. 29 0
      src/uni_modules/uview-plus/components/u-checkbox-group/checkboxGroup.js
  79. 5 4
      src/uni_modules/uview-plus/components/u-checkbox-group/props.js
  80. 3 3
      src/uni_modules/uview-plus/components/u-checkbox-group/u-checkbox-group.vue
  81. 27 0
      src/uni_modules/uview-plus/components/u-checkbox/checkbox.js
  82. 4 3
      src/uni_modules/uview-plus/components/u-checkbox/props.js
  83. 42 30
      src/uni_modules/uview-plus/components/u-checkbox/u-checkbox.vue
  84. 15 0
      src/uni_modules/uview-plus/components/u-circle-progress/circleProgress.js
  85. 4 3
      src/uni_modules/uview-plus/components/u-circle-progress/props.js
  86. 3 3
      src/uni_modules/uview-plus/components/u-circle-progress/u-circle-progress.vue
  87. 29 0
      src/uni_modules/uview-plus/components/u-code-input/codeInput.js
  88. 4 3
      src/uni_modules/uview-plus/components/u-code-input/props.js
  89. 46 12
      src/uni_modules/uview-plus/components/u-code-input/u-code-input.vue
  90. 21 0
      src/uni_modules/uview-plus/components/u-code/code.js
  91. 4 3
      src/uni_modules/uview-plus/components/u-code/props.js
  92. 3 8
      src/uni_modules/uview-plus/components/u-code/u-code.vue
  93. 19 0
      src/uni_modules/uview-plus/components/u-col/col.js
  94. 4 3
      src/uni_modules/uview-plus/components/u-col/props.js
  95. 3 3
      src/uni_modules/uview-plus/components/u-col/u-col.vue
  96. 26 0
      src/uni_modules/uview-plus/components/u-collapse-item/collapseItem.js
  97. 10 4
      src/uni_modules/uview-plus/components/u-collapse-item/props.js
  98. 9 7
      src/uni_modules/uview-plus/components/u-collapse-item/u-collapse-item.vue
  99. 17 0
      src/uni_modules/uview-plus/components/u-collapse/collapse.js
  100. 4 3
      src/uni_modules/uview-plus/components/u-collapse/props.js

+ 247 - 0
src/api/business/meeting.js

@@ -0,0 +1,247 @@
+import { request } from "@/utils/request";
+
+// 首页统计
+export function FirstPageStatistic(data) {
+    return request({
+        url: '/service-meeting/meetingRoom/FirstPageStatistic',
+        method: 'GET',
+        params: data
+    })
+}
+
+// 会议室列表
+export function dmMeetingRoomList(data) {
+    return request({
+        url: '/service-meeting/meetingRoom/dmMeetingRoomList',
+        method: 'POST',
+        data: data
+    })
+}
+
+// 会议室下拉列表
+export function MeetingRoomList(data) {
+    return request({
+        url: '/service-meeting/meetingRoom/MeetingRoomList',
+        method: 'GET',
+        params: data
+    })
+}
+
+
+
+/**
+ * 楼层管理api接口集合
+ * @method Select 列表
+ * @method Insert 新增
+ * @method Update 修改
+ * @method Delete 删除
+ */
+export function floorApi() {
+    return {
+        Select: (data) => {
+            return request({
+                url: '/service-meeting/meetingFloor/meetingFloorList',
+                method: 'POST',
+                data,
+            });
+        },
+        Insert: (data) => {
+            return request({
+                url: '/service-meeting/meetingFloor',
+                method: 'POST',
+                data
+            });
+        },
+        Update: (data) => {
+            return request({
+                url: '/service-meeting/meetingFloor',
+                method: 'PUT',
+                data
+            });
+        },
+        Delete: (data) => {
+            return request({
+                url: '/service-meeting/meetingFloor?floorId=' + data,
+                method: 'DELETE',
+            });
+        },
+    };
+}
+
+/**
+ * 设备管理api接口集合
+ * @method Select 列表
+ * @method Insert 新增
+ * @method Update 修改
+ * @method Delete 删除
+ */
+export function deviceApi() {
+    return {
+        Select: (data) => {
+            return request({
+                url: '/service-meeting/meetingDevice/meetingDeviceList',
+                method: 'POST',
+                data,
+            });
+        },
+        Insert: (data) => {
+            return request({
+                url: '/service-meeting/meetingDevice',
+                method: 'POST',
+                data
+            });
+        },
+        Update: (data) => {
+            return request({
+                url: '/service-meeting/meetingDevice',
+                method: 'PUT',
+                data
+            });
+        },
+        Delete: (data) => {
+            return request({
+                url: '/service-meeting/meetingDevice?deviceId=' + data,
+                method: 'DELETE',
+            });
+        },
+    };
+}
+
+
+/**
+ * 会议室管理api接口集合
+ * @method Select 列表
+ * @method Insert 新增
+ * @method Update 修改
+ * @method Delete 删除
+ */
+export function roomApi() {
+    return {
+        Select: (data) => {
+            return request({
+                url: '/service-meeting/meetingRoom/dmMeetingRoomList',
+                method: 'POST',
+                data,
+            });
+        },
+        Insert: (data) => {
+            return request({
+                url: '/service-meeting/meetingRoom',
+                method: 'POST',
+                data
+            });
+        },
+        Update: (data) => {
+            return request({
+                url: '/service-meeting/meetingRoom',
+                method: 'PUT',
+                data
+            });
+        },
+        Delete: (data) => {
+            return request({
+                url: '/service-meeting/meetingRoom?roomId=' + data,
+                method: 'DELETE',
+            });
+        },
+    };
+}
+
+//会议室详情
+export function meetingRoomDetails(data) {
+    return request({
+        url: '/service-meeting/meetingRoom/meetingRoomDetails',
+        method: 'GET',
+        params: data
+    })
+}
+
+//会议室预约情况列表
+export function MeetingRoomReservationList(data) {
+    return request({
+        url: '/service-meeting/meetingRoom/getMeetingRoomReservationList',
+        method: 'POST',
+        data: data
+    })
+}
+
+//会议室预约-新增会议
+export function meetingInfoAdd(data) {
+    return request({
+        url: '/service-meeting/meetingInfo/add',
+        method: 'POST',
+        data
+    })
+}
+
+/**
+ * 会议室记录api接口集合
+ * @method Select 列表
+ * @method Cancel 取消
+ */
+export function recordApi() {
+    return {
+        Select: (data) => {
+            return request({
+                url: '/service-meeting/meetingInfo/meetingInfoList',
+                method: 'POST',
+                data,
+            });
+        },
+        Cancel: (data) => {
+            return request({
+                url: '/service-meeting/meetingInfo/cancel?meetingId=' + data,
+                method: 'POST',
+            });
+        },
+    };
+}
+
+/**
+ * 我的会议api接口集合
+ * @method Select 列表
+ * @method SignList 人员签到-列表
+ * @method InsertFile 会议文件-添加
+ * @method SelectFile 会议文件-列表
+ */
+export function myApi() {
+    return {
+        Select: (data) => {
+            return request({
+                url: '/service-meeting/meetingInfo/myMeetingList',
+                method: 'POST',
+                data,
+            });
+        },
+        SignList: (data) => {
+            return request({
+                url: '/service-meeting/meetingInfo/meetingSignList',
+                method: 'GET',
+                params: data
+            });
+        },
+        InsertFile: (data) => {
+            return request({
+                url: '/service-meeting/meetingFile/insertMeetingFile',
+                method: 'POST',
+                data,
+            });
+        },
+        SelectFile: (data) => {
+            return request({
+                url: '/service-meeting/meetingFile/meetingFileList',
+                method: 'POST',
+                data,
+            });
+        },
+    };
+}
+
+//人员签到-人员签退
+export function signOnOut(data) {
+    return request({
+        url: '/service-meeting/meetingInfo/signOnOut',
+        method: 'POST',
+        data
+    })
+}

+ 30 - 50
src/components/oa-calendar/uni-calendar.vue

@@ -11,28 +11,24 @@
         </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> -->
+        <view class="uni-calendar__header-btn-box" v-if="false" @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 style="margin: auto"></view>
+        <view style="margin: auto">
+          <text class="uni-calendar__backtoday" v-if="false" @click="backtoday">{{ todayText }}</text>
+        </view>
 
         <view class="uni-calendar__header-right">
-          <view class="item">
-            <span class="item_title">巡检</span>
-            <span class="item_cont" style="color: #00cdac">{{ JSON.stringify(currentDateList) === "{}" ? 0 : currentDateList.patrolledCount }}</span>
-          </view>
-          <view class="item">
-            <span class="item_title">漏检</span>
-            <span class="item_cont" style="color: #f07d28">{{ JSON.stringify(currentDateList) === "{}" ? 0 : currentDateList.undetectedCount }}</span>
-          </view>
+          <slot name="headerRight"> </slot>
+        </view>
+
+        <view class="uni-calendar__header-btn-box" v-if="false" @click.stop="next">
+          <view class="uni-calendar__header-btn uni-calendar--right"></view>
         </view>
       </view>
       <view class="uni-calendar__box">
@@ -88,8 +84,6 @@ const { t } = initVueI18n(messages);
  * @property {String} endDate 日期选择范围-结束日期
  * @property {Boolean} range 范围选择
  * @property {Boolean} insert = [true|false] 插入模式,默认为false
- * 	@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 是否选择月份为背景
@@ -145,10 +139,6 @@ export default {
       type: Boolean,
       default: true,
     },
-    currentDate: {
-      type: Object,
-      default: {},
-    },
   },
   data() {
     return {
@@ -157,7 +147,6 @@ export default {
       calendar: {},
       nowDate: "",
       aniMaskShow: false,
-      currentDateList: {},
     };
   },
   computed: {
@@ -215,9 +204,6 @@ export default {
       this.cale.setSelectInfo(this.nowDate.fullDate, newVal);
       this.weeks = this.cale.weeks;
     },
-    currentDate(obj) {
-      this.currentDateList = obj;
-    },
   },
   created() {
     // 获取日历方法实例
@@ -413,7 +399,7 @@ $uni-bg-color-mask: rgba(
 $uni-border-color: #ededed;
 $uni-text-color: #333;
 $uni-bg-color-hover: #f1f1f1;
-$uni-font-size-sm:12px;
+$uni-font-size-sm: 12px;
 $uni-font-size-base: 14px;
 $uni-text-color-placeholder: #808080;
 $uni-color-subtitle: #555555;
@@ -497,20 +483,14 @@ $uni-text-color-grey: #999;
 
 .uni-calendar--fixed-width {
   width: 50px;
-  // padding: 0 15px;
 }
 
 .uni-calendar__backtoday {
-  position: absolute;
-  right: 0;
-  top: 25rpx;
-  padding: 0 5px;
-  padding-left: 10px;
+  padding: 0 10px;
   height: 25px;
   line-height: 25px;
   font-size: $uni-font-size-sm;
-  border-top-left-radius: 25px;
-  border-bottom-left-radius: 25px;
+  border-radius: 25px;
   color: $uni-text-color;
   background-color: $uni-bg-color-hover;
 }
@@ -522,19 +502,19 @@ $uni-text-color-grey: #999;
   color: $uni-text-color;
 }
 
-.uni-calendar__header-right {
-  display: flex;
-
-  .item {
-    font-size: $uni-font-size-base;
-    .item_title {
-      margin-right: 5px;
+:deep() {
+  .uni-calendar__header-right {
+    display: flex;
+    .item {
+      font-size: $uni-font-size-base;
+      + .item {
+        margin-left: 10px;
+      }
+      .item_title {
+        margin-right: 5px;
+      }
     }
   }
-
-  .item + .item {
-    margin-left: 10px;
-  }
 }
 
 .uni-calendar__header-btn-box {
@@ -544,8 +524,8 @@ $uni-text-color-grey: #999;
   flex-direction: row;
   align-items: center;
   justify-content: center;
-  width: 50px;
-  height: 50px;
+  width: 20px;
+  height: 10px;
 }
 
 .uni-calendar__header-btn {
@@ -553,10 +533,10 @@ $uni-text-color-grey: #999;
   height: 10px;
   border-left-color: $uni-text-color-placeholder;
   border-left-style: solid;
-  border-left-width: 2px;
+  border-left-width: 1.5px;
   border-top-color: $uni-color-subtitle;
   border-top-style: solid;
-  border-top-width: 2px;
+  border-top-width: 1.5px;
 }
 
 .uni-calendar--left {

+ 14 - 1
src/components/oa-scroll/index.vue

@@ -142,7 +142,20 @@ const props = defineProps({
   },
 });
 
-const { pageSize, total, scrollTop, customClass, customStyle, refresherLoad, refresherEnabled, refresherEnabledTitle, refresherThreshold, refresherDefaultStyle, refresherBackground } = toRefs(props);
+const {
+  pageSize,
+  total,
+  scrollTop,
+  customClass,
+  customStyle,
+  refresherLoad,
+  refresherLoadTitle,
+  refresherEnabled,
+  refresherEnabledTitle,
+  refresherThreshold,
+  refresherDefaultStyle,
+  refresherBackground,
+} = toRefs(props);
 
 const state = reactive({
   StatusBarHeight: computed(() => {

+ 149 - 158
src/manifest.json

@@ -1,46 +1,46 @@
 {
-    "name": "综合智慧云",
-    "appid": "__UNI__36DE3A0",
-    "description": "综合智慧云APP,是一款助力于企业数字化的应用平台,帮助企业提升办公效率,实现组织数字化和业务数字化。",
-    "versionName": "2.1.9",
-    "versionCode": 19,
-    "transformPx": false,
-    "app-plus": {
-        "compatible": {
-            "ignoreVersion": true
+    "name" : "综合智慧云",
+    "appid" : "__UNI__36DE3A0",
+    "description" : "综合智慧云APP,是一款助力于企业数字化的应用平台,帮助企业提升办公效率,实现组织数字化和业务数字化。",
+    "versionName" : "2.2.4",
+    "versionCode" : 24,
+    "transformPx" : false,
+    "app-plus" : {
+        "compatible" : {
+            "ignoreVersion" : true
         },
-        "kernel": {
-            "ios": "WKWebview"
+        "kernel" : {
+            "ios" : "WKWebview"
         },
-        "usingComponents": true,
-        "nvueStyleCompiler": "uni-app",
-        "compilerVersion": 3,
-        "splashscreen": {
-            "alwaysShowBeforeRender": true,
-            "waiting": true,
-            "autoclose": true,
-            "delay": 0
+        "usingComponents" : true,
+        "nvueStyleCompiler" : "uni-app",
+        "compilerVersion" : 3,
+        "splashscreen" : {
+            "alwaysShowBeforeRender" : true,
+            "waiting" : true,
+            "autoclose" : true,
+            "delay" : 0
         },
-        "screenOrientation": [
+        "screenOrientation" : [
             "portrait-primary",
             "portrait-secondary",
             "landscape-primary",
             "landscape-secondary"
         ],
-        "modules": {
-            "VideoPlayer": {},
-            "iBeacon": {},
-            "Geolocation": {},
-            "Maps": {},
-            "Barcode": {},
-            "Fingerprint": {},
-            "Push": {},
-            "Camera": {},
-            "LivePusher": {}
+        "modules" : {
+            "VideoPlayer" : {},
+            "iBeacon" : {},
+            "Geolocation" : {},
+            "Maps" : {},
+            "Barcode" : {},
+            "Fingerprint" : {},
+            "Push" : {},
+            "Camera" : {},
+            "LivePusher" : {}
         },
-        "distribute": {
-            "android": {
-                "permissions": [
+        "distribute" : {
+            "android" : {
+                "permissions" : [
                     "<uses-feature android:name=\"android.hardware.camera\"/>",
                     "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
                     "<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>",
@@ -80,165 +80,156 @@
                     "<uses-permission android:name=\"android.permission.RECEIVE_BOOT_COMPLETED\"/>",
                     "<uses-permission android:name=\"android.permission.SYSTEM_ALERT_WINDOW\"/>"
                 ],
-                "minSdkVersion": "",
-                "abiFilters": [
-                    "armeabi-v7a",
-                    "arm64-v8a"
-                ],
-                "targetSdkVersion": 30
+                "minSdkVersion" : "",
+                "abiFilters" : [ "armeabi-v7a", "arm64-v8a" ],
+                "targetSdkVersion" : 30
             },
-            "ios": {
-                "dSYMs": false,
-                "privacyDescription": {
-                    "NSPhotoLibraryUsageDescription": "该应用需要读取你的相册,用于上传头像",
-                    "NSPhotoLibraryAddUsageDescription": "该应用需要读取你的相册,用于拍照保存图片",
-                    "NSCameraUsageDescription": "该应用需要你的相机,用于你拍摄上传头像信息",
-                    "NSMicrophoneUsageDescription": "该应用需要使用你的麦克风,用于语音播放",
-                    "NSLocationWhenInUseUsageDescription": "该应用需要你的地理位置,用于天气、签到等功能",
-                    "NSLocationAlwaysUsageDescription": "该应用需要持续获取用户地理位置,用于天气、签到等功能",
-                    "NSLocationAlwaysAndWhenInUseUsageDescription": "该应用需要你的地理位置,用于天气、签到等功能",
-                    "NSCalendarsUsageDescription": "该应用需要获取你的日历,以便更好的体验",
-                    "NSContactsUsageDescription": "该应用需要读取你的通讯录,以便联系同事",
-                    "NSBluetoothPeripheralUsageDescription": "该应用需要你的蓝牙,以便读取相关蓝牙设备",
-                    "NFCReaderUsageDescription": "",
-                    "NSBluetoothAlwaysUsageDescription": "该应用需要你的蓝牙,以便读取相关蓝牙设备"
+            "ios" : {
+                "dSYMs" : false,
+                "privacyDescription" : {
+                    "NSPhotoLibraryUsageDescription" : "该应用需要读取你的相册,用于上传头像",
+                    "NSPhotoLibraryAddUsageDescription" : "该应用需要读取你的相册,用于拍照保存图片",
+                    "NSCameraUsageDescription" : "该应用需要你的相机,用于你拍摄上传头像信息",
+                    "NSMicrophoneUsageDescription" : "该应用需要使用你的麦克风,用于语音播放",
+                    "NSLocationWhenInUseUsageDescription" : "该应用需要你的地理位置,用于天气、签到等功能",
+                    "NSLocationAlwaysUsageDescription" : "该应用需要持续获取用户地理位置,用于天气、签到等功能",
+                    "NSLocationAlwaysAndWhenInUseUsageDescription" : "该应用需要你的地理位置,用于天气、签到等功能",
+                    "NSCalendarsUsageDescription" : "该应用需要获取你的日历,以便更好的体验",
+                    "NSContactsUsageDescription" : "该应用需要读取你的通讯录,以便联系同事",
+                    "NSBluetoothPeripheralUsageDescription" : "该应用需要你的蓝牙,以便读取相关蓝牙设备",
+                    "NFCReaderUsageDescription" : "",
+                    "NSBluetoothAlwaysUsageDescription" : "该应用需要你的蓝牙,以便读取相关蓝牙设备"
                 },
-                "UIBackgroundModes": ""
+                "UIBackgroundModes" : ""
             },
-            "sdkConfigs": {
-                "ad": {},
-                "maps": {
-                    "amap": {
-                        "appkey_ios": "fb35d03fbb17cbf7a8743a522da3c7fc",
-                        "appkey_android": "ffc71dfd4e576596027f8f45a1b8fb2f",
-                        "name": "amapBOujshtbA"
+            "sdkConfigs" : {
+                "ad" : {},
+                "maps" : {
+                    "amap" : {
+                        "appkey_ios" : "fb35d03fbb17cbf7a8743a522da3c7fc",
+                        "appkey_android" : "ffc71dfd4e576596027f8f45a1b8fb2f",
+                        "name" : "amapBOujshtbA"
                     }
                 },
-                "geolocation": {
-                    "system": {
-                        "__platform__": [
-                            "ios",
-                            "android"
-                        ]
+                "geolocation" : {
+                    "system" : {
+                        "__platform__" : [ "ios", "android" ]
                     },
-                    "amap": {
-                        "__platform__": [
-                            "ios",
-                            "android"
-                        ],
-                        "appkey_ios": "fb35d03fbb17cbf7a8743a522da3c7fc",
-                        "appkey_android": "ffc71dfd4e576596027f8f45a1b8fb2f",
-                        "name": "amapBOujshtbA"
+                    "amap" : {
+                        "__platform__" : [ "ios", "android" ],
+                        "appkey_ios" : "fb35d03fbb17cbf7a8743a522da3c7fc",
+                        "appkey_android" : "ffc71dfd4e576596027f8f45a1b8fb2f",
+                        "name" : "amapBOujshtbA"
                     }
                 },
-                "push": {
-                    "unipush": {
-                        "version": "2",
-                        "offline": true,
-                        "icons": {
-                            "small": {
-                                "hdpi": "unpackage/res/push/36x36.png",
-                                "ldpi": "unpackage/res/push/18x18.png",
-                                "mdpi": "unpackage/res/push/24x24.png",
-                                "xhdpi": "unpackage/res/push/48x48.png",
-                                "xxhdpi": "unpackage/res/push/72x72.png"
+                "push" : {
+                    "unipush" : {
+                        "version" : "2",
+                        "offline" : true,
+                        "icons" : {
+                            "small" : {
+                                "hdpi" : "unpackage/res/push/36x36.png",
+                                "ldpi" : "unpackage/res/push/18x18.png",
+                                "mdpi" : "unpackage/res/push/24x24.png",
+                                "xhdpi" : "unpackage/res/push/48x48.png",
+                                "xxhdpi" : "unpackage/res/push/72x72.png"
                             }
                         }
                     }
                 }
             },
-            "icons": {
-                "android": {
-                    "hdpi": "unpackage/res/icons/72x72.png",
-                    "xhdpi": "unpackage/res/icons/96x96.png",
-                    "xxhdpi": "unpackage/res/icons/144x144.png",
-                    "xxxhdpi": "unpackage/res/icons/192x192.png"
+            "icons" : {
+                "android" : {
+                    "hdpi" : "unpackage/res/icons/72x72.png",
+                    "xhdpi" : "unpackage/res/icons/96x96.png",
+                    "xxhdpi" : "unpackage/res/icons/144x144.png",
+                    "xxxhdpi" : "unpackage/res/icons/192x192.png"
                 },
-                "ios": {
-                    "appstore": "unpackage/res/icons/1024x1024.png",
-                    "ipad": {
-                        "app": "unpackage/res/icons/76x76.png",
-                        "app@2x": "unpackage/res/icons/152x152.png",
-                        "notification": "unpackage/res/icons/20x20.png",
-                        "notification@2x": "unpackage/res/icons/40x40.png",
-                        "proapp@2x": "unpackage/res/icons/167x167.png",
-                        "settings": "unpackage/res/icons/29x29.png",
-                        "settings@2x": "unpackage/res/icons/58x58.png",
-                        "spotlight": "unpackage/res/icons/40x40.png",
-                        "spotlight@2x": "unpackage/res/icons/80x80.png"
+                "ios" : {
+                    "appstore" : "unpackage/res/icons/1024x1024.png",
+                    "ipad" : {
+                        "app" : "unpackage/res/icons/76x76.png",
+                        "app@2x" : "unpackage/res/icons/152x152.png",
+                        "notification" : "unpackage/res/icons/20x20.png",
+                        "notification@2x" : "unpackage/res/icons/40x40.png",
+                        "proapp@2x" : "unpackage/res/icons/167x167.png",
+                        "settings" : "unpackage/res/icons/29x29.png",
+                        "settings@2x" : "unpackage/res/icons/58x58.png",
+                        "spotlight" : "unpackage/res/icons/40x40.png",
+                        "spotlight@2x" : "unpackage/res/icons/80x80.png"
                     },
-                    "iphone": {
-                        "app@2x": "unpackage/res/icons/120x120.png",
-                        "app@3x": "unpackage/res/icons/180x180.png",
-                        "notification@2x": "unpackage/res/icons/40x40.png",
-                        "notification@3x": "unpackage/res/icons/60x60.png",
-                        "settings@2x": "unpackage/res/icons/58x58.png",
-                        "settings@3x": "unpackage/res/icons/87x87.png",
-                        "spotlight@2x": "unpackage/res/icons/80x80.png",
-                        "spotlight@3x": "unpackage/res/icons/120x120.png"
+                    "iphone" : {
+                        "app@2x" : "unpackage/res/icons/120x120.png",
+                        "app@3x" : "unpackage/res/icons/180x180.png",
+                        "notification@2x" : "unpackage/res/icons/40x40.png",
+                        "notification@3x" : "unpackage/res/icons/60x60.png",
+                        "settings@2x" : "unpackage/res/icons/58x58.png",
+                        "settings@3x" : "unpackage/res/icons/87x87.png",
+                        "spotlight@2x" : "unpackage/res/icons/80x80.png",
+                        "spotlight@3x" : "unpackage/res/icons/120x120.png"
                     }
                 }
             },
-            "splashscreen": {
-                "androidStyle": "default",
-                "android": {
-                    "hdpi": "src/static/images/wt/bg.png"
+            "splashscreen" : {
+                "androidStyle" : "default",
+                "android" : {
+                    "hdpi" : "src/static/images/wt/bg.png"
                 },
-                "iosStyle": "common"
+                "iosStyle" : "common"
             }
         },
-        "nativePlugins": {},
-        "safearea": {
-            "offset": "none"
+        "nativePlugins" : {},
+        "safearea" : {
+            "offset" : "none"
         }
     },
-    "quickapp": {},
-    "mp-weixin": {
-        "appid": "",
-        "setting": {
-            "urlCheck": false,
-            "checkSiteMap": false
+    "quickapp" : {},
+    "mp-weixin" : {
+        "appid" : "",
+        "setting" : {
+            "urlCheck" : false,
+            "checkSiteMap" : false
         },
-        "usingComponents": true
+        "usingComponents" : true
     },
-    "mp-alipay": {
-        "usingComponents": true
+    "mp-alipay" : {
+        "usingComponents" : true
     },
-    "mp-baidu": {
-        "usingComponents": true
+    "mp-baidu" : {
+        "usingComponents" : true
     },
-    "mp-toutiao": {
-        "usingComponents": true
+    "mp-toutiao" : {
+        "usingComponents" : true
     },
-    "uniStatistics": {
-        "enable": false
+    "uniStatistics" : {
+        "enable" : false
     },
-    "h5": {
-        "publicPath": "./",
-        "title": "综合智慧云",
-        "router": {
-            "mode": "hash"
+    "h5" : {
+        "publicPath" : "./",
+        "title" : "综合智慧云",
+        "router" : {
+            "mode" : "hash"
         },
-        "devServer": {
-            "https": false,
-            "proxy": {}
+        "devServer" : {
+            "https" : false,
+            "proxy" : {}
         },
-        "sdkConfigs": {
-            "maps": {
-                "amap": {
-                    "key": "d4d73a7d572b6ff6028d5f67de62029a",
-                    "securityJsCode": "be916fcd16d0b33d228c49f0ff096b17",
-                    "serviceHost": ""
+        "sdkConfigs" : {
+            "maps" : {
+                "amap" : {
+                    "key" : "d4d73a7d572b6ff6028d5f67de62029a",
+                    "securityJsCode" : "be916fcd16d0b33d228c49f0ff096b17",
+                    "serviceHost" : ""
                 }
             }
         },
-        "optimization": {
-            "treeShaking": {
-                "enable": true
+        "optimization" : {
+            "treeShaking" : {
+                "enable" : true
             }
         },
-        "template": "index.html"
+        "template" : "index.html"
     },
-    "vueVersion": "3",
-    "locale": "zh-Hans"
-}
+    "vueVersion" : "3",
+    "locale" : "zh-Hans"
+}

+ 36 - 12
src/pages.json

@@ -65,6 +65,18 @@
                     "titleNView": false
                 }
             }
+        },
+        {
+            "path": "pages/common/face/index",
+            "style": {
+                "navigationBarTitleText": "人脸识别",
+                "enablePullDownRefresh": false,
+                "navigationStyle": "custom",
+                "app-plus": {
+                    "bounce": "none",
+                    "titleNView": false
+                }
+            }
         }
     ],
     "subPackages": [
@@ -160,18 +172,6 @@
                             "titleNView": false
                         }
                     }
-                },
-                {
-                    "path": "face/index",
-                    "style": {
-                        "navigationBarTitleText": "人脸识别",
-                        "enablePullDownRefresh": false,
-                        "navigationStyle": "custom",
-                        "app-plus": {
-                            "bounce": "none",
-                            "titleNView": false
-                        }
-                    }
                 }
             ]
         },
@@ -745,6 +745,30 @@
                             "titleNView": false
                         }
                     }
+                },
+                {
+                    "path": "meeting/index",
+                    "style": {
+                        "navigationBarTitleText": "会议预约",
+                        "enablePullDownRefresh": false,
+                        "navigationStyle": "custom",
+                        "app-plus": {
+                            "bounce": "none",
+                            "titleNView": false
+                        }
+                    }
+                },
+                {
+                    "path": "meeting/new/index",
+                    "style": {
+                        "navigationBarTitleText": "新建日程",
+                        "enablePullDownRefresh": false,
+                        "navigationStyle": "custom",
+                        "app-plus": {
+                            "bounce": "none",
+                            "titleNView": false
+                        }
+                    }
                 }
             ]
         }

+ 79 - 0
src/pages/business/common/meeting/components/avatarList.vue

@@ -0,0 +1,79 @@
+<template>
+  <view class="flex flex-wrap">
+    <view class="mr10 mb10" v-for="(user, index) in userList" :key="index" @click="deleteUsers(index)">
+      <u-avatar
+        class="avatar"
+        :src="user.avatar ? user.avatar : '/static/images/404.png'"
+        shape="square"
+        size="40"
+        fontSize="12"
+        color="#ffffff"
+        :bgColor="$settingStore.themeColor.color"
+        v-if="user.avatar"
+      ></u-avatar>
+      <u-avatar
+        class="avatar"
+        :text="user.label.length > 2 ? user.label.slice(1, 3) : user.label"
+        shape="square"
+        size="40"
+        fontSize="12"
+        color="#ffffff"
+        :bgColor="$settingStore.themeColor.color"
+        v-else
+      ></u-avatar>
+      <view class="font12 text-center mt5">{{ user.label }}</view>
+    </view>
+  </view>
+</template>
+<script setup>
+/*----------------------------------依赖引入-----------------------------------*/
+import { onLoad, onShow, onReady, onHide, onLaunch, onNavigationBarButtonTap, onPageScroll } from "@dcloudio/uni-app";
+import { ref, reactive, computed, getCurrentInstance, toRefs, inject } from "vue";
+/*----------------------------------接口引入-----------------------------------*/
+/*----------------------------------组件引入-----------------------------------*/
+/*----------------------------------store引入-----------------------------------*/
+import { useStores, commonStores } from "@/store/modules/index";
+/*----------------------------------公共方法引入-----------------------------------*/
+/*----------------------------------公共变量-----------------------------------*/
+const { proxy } = getCurrentInstance();
+const commonStore = commonStores();
+/*----------------------------------变量声明-----------------------------------*/
+const emit = defineEmits(["deleteUsers"]);
+const props = defineProps({
+  userList: {
+    type: Object,
+    default: [],
+  },
+});
+
+const { userList } = toRefs(props);
+
+/** 删除回调事件 */
+function deleteUsers(index) {
+  emit("deleteUsers", index);
+}
+</script>
+<style lang="scss" scoped>
+.avatar {
+  position: relative;
+
+  &::after {
+    position: absolute;
+    content: "✖";
+    display: inline-block;
+    padding: 2px 4px;
+    border-radius: 100%;
+    cursor: pointer;
+    font-size: 8px;
+    text-align: center;
+    background-color: #ccc;
+    color: #fff;
+    top: -5px;
+    right: -5px;
+  }
+
+  &::after:hover {
+    background-color: #ccc;
+  }
+}
+</style>

+ 208 - 0
src/pages/business/common/meeting/components/timeSlot.vue

@@ -0,0 +1,208 @@
+<template>
+  <view>
+    <view class="axis" :style="{ backgroundColor: this.defaultColor }">
+      <view class="leftLine" :style="leftTimeStyle"></view>
+      <view class="line" v-for="item in disArr" :key="item" :style="item"></view>
+      <view class="kedu">
+        <view class="kedu-line" v-for="num in 24" :key="num"></view>
+      </view>
+    </view>
+    <view class="nums">
+      <view class="num" v-for="num in nums" :key="num">
+        {{ num }}
+      </view>
+    </view>
+    <view class="tip">
+      <view class="tip-block">
+        <view class="tip-color" :style="{ backgroundColor: this.activeColor }"> </view>
+        <view class="tip-text"> 已预约 </view>
+      </view>
+      <view class="tip-block">
+        <view class="tip-color" :style="{ backgroundColor: this.defaultColor, border: `1px ${this.leftColor} solid` }"> </view>
+        <view class="tip-text"> 可预约 </view>
+      </view>
+      <view class="tip-block">
+        <view class="tip-color" :style="{ backgroundColor: this.leftColor }"> </view>
+        <view class="tip-text"> 不可预约 </view>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  name: "time-slot",
+  props: {
+    leftColor: {
+      type: String,
+      default: "#CAD1CE",
+    }, //不可预约颜色
+    activeColor: {
+      type: String,
+      default: "#149eff",
+    }, //已预约颜色
+    defaultColor: {
+      type: String,
+      default: "#FFFFFF",
+    }, //可预约颜色
+    currentDay: {
+      type: String,
+      default: "",
+    }, //当前时间
+    startDateKey: {
+      type: String,
+      default: "startDate",
+    }, //开始时间key
+    endDateKey: {
+      type: String,
+      default: "endDate",
+    }, //结束时间key
+    aboutTimeData: {
+      type: Array,
+      default: () => {
+        return [];
+      },
+    }, //预约时间集合
+  },
+  data() {
+    return {
+      nums: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24],
+    };
+  },
+  computed: {
+    curDay() {
+      return this.currentDay ? this.currentDay : this.getCurrentDay();
+    },
+    disArr() {
+      const zeroTime = this.get_unix_time(this.curDay + " 00:00:00");
+      return this.aboutTimeData.map((e) => {
+        const leftWidth = this.get_unix_time(e[this.startDateKey].indexOf("T") != -1 ? e[this.startDateKey].replace("T", " ") : e[this.startDateKey]) - zeroTime;
+        const owerWidth = this.get_unix_time(e[this.endDateKey].indexOf("T") != -1 ? e[this.endDateKey].replace("T", " ") : e[this.endDateKey]) - zeroTime - leftWidth;
+        return {
+          left: leftWidth / 864 + "%",
+          width: owerWidth / 864 + "%",
+          backgroundColor: this.activeColor,
+        };
+      });
+    },
+    leftTimeStyle() {
+      var owerWidth = (new Date().getTime().toString().substr(0, 10) - this.get_unix_time(this.curDay + " 00:00:00")) / 864;
+      var newWidth = 0;
+
+      if (owerWidth >= 100) {
+        newWidth = 100;
+      } else if (owerWidth <= 0) {
+        newWidth = 0;
+      } else {
+        newWidth = owerWidth;
+      }
+
+      return {
+        left: 0,
+        width: newWidth + "%",
+        backgroundColor: this.leftColor,
+      };
+    },
+  },
+  methods: {
+    get_unix_time(dateStr) {
+      var newstr = dateStr.replace(/-/g, "/");
+      var date = new Date(newstr);
+      var time_str = date.getTime().toString();
+      return time_str.substr(0, 10);
+    },
+    getCurrentDay() {
+      const strFormat = (str) => {
+        return str < 10 ? `0${str}` : str;
+      };
+      const myDate = new Date();
+      const y = myDate.getFullYear();
+      const m = myDate.getMonth() + 1;
+      const d = myDate.getDate();
+      return y + "-" + strFormat(m) + "-" + strFormat(d);
+    },
+  },
+};
+</script>
+
+<style lang="scss">
+.axis {
+  position: relative;
+  width: 100%;
+  height: 20rpx;
+  background-color: #fff;
+  border: 1px #cad1ce solid;
+  margin-bottom: 5px;
+  .line {
+    position: absolute;
+    height: 20rpx;
+    width: 200rpx;
+    top: 0;
+    left: 50%;
+    background-color: #31b179;
+    z-index: 3;
+  }
+  .leftLine {
+    position: absolute;
+    height: 20rpx;
+    width: 200rpx;
+    max-width: 100%;
+    top: 0;
+    left: 50%;
+    background-color: #cad1ce;
+    z-index: 2;
+  }
+}
+
+.kedu {
+  display: flex;
+  position: absolute;
+  align-items: flex-end;
+  width: 100%;
+  bottom: 0;
+  left: 0;
+  z-index: 4;
+  .kedu-line {
+    width: 4.16666%;
+    height: 6rpx;
+    border-right: 1px solid #333333;
+  }
+  .kedu-line:nth-child(2n) {
+    height: 12rpx;
+  }
+  .kedu-line:last-child {
+    border-right: 0;
+  }
+}
+.nums {
+  width: 108.2%;
+  display: flex;
+  margin-left: -4.16666%;
+  .num {
+    width: 8.2%;
+    font-size: 14rpx;
+    text-align: center;
+  }
+}
+.tip {
+  display: flex;
+  .tip-block {
+    display: flex;
+    align-items: center;
+    padding: 10rpx;
+    justify-content: center;
+
+    .tip-color {
+      width: 20rpx;
+      height: 20rpx;
+    }
+    .tip-text {
+      margin-left: 10rpx;
+      font-size: 22rpx;
+      font-family: Adobe Heiti Std;
+      font-weight: normal;
+      color: #999999;
+    }
+  }
+}
+</style>

+ 383 - 0
src/pages/business/common/meeting/index.vue

@@ -0,0 +1,383 @@
+<template>
+  <u-sticky class="shadow-default" bgColor="#fff" style="top: 0">
+    <u-navbar :titleStyle="{ color: '#000' }" :autoBack="true" title="会议预约" :placeholder="true" :safeAreaInsetTop="true" bgColor="#fff">
+      <template #left>
+        <view class="u-navbar__content__left__item">
+          <u-icon name="arrow-left" size="20" color="#000"></u-icon>
+        </view>
+      </template>
+      <template #right>
+        <view class="u-navbar__content__right__item">
+          <u-icon name="more-dot-fill" size="19" color="#000"></u-icon>
+        </view>
+      </template>
+    </u-navbar>
+
+    <view class="flex plr10">
+      <u--input
+        style="width: 100%"
+        v-model="form.meetingRoomName"
+        placeholder="搜索会议室"
+        prefixIcon="search"
+        prefixIconStyle="font-size: 22px;color: #909399"
+        customStyle="height:35px;background-color:#f5f6fa; "
+        @confirm="init()"
+        clearable
+      ></u--input>
+    </view>
+
+    <view class="flex plr10" style="line-height: 20px">
+      <view class="flex mtb-auto ptb10 nav" style="overflow-x: auto" @click="handlePopup(true, 'switchTime', {})">
+        <view
+          class="radius p5 mr10"
+          :style="{
+            color: proxy.$settingStore.themeColor.color,
+            backgroundColor: `${proxy.$settingStore.themeColor.color}30`,
+          }"
+        >
+          {{ proxy.$dayjs(form.date).format("MM月DD日") }}
+          {{ weekData[proxy.$dayjs(form.date).format("d")] }}
+        </view>
+      </view>
+      <view class="ml-auto mtb-auto pl10 nav" :style="{ color: proxy.$settingStore.themeColor.color }">重置</view>
+    </view>
+  </u-sticky>
+
+  <oa-scroll
+    customClass="record-container scroll-height"
+    :isSticky="true"
+    :customStyle="{
+      //#ifdef APP-PLUS || MP-WEIXIN
+      height: `calc(100vh - (44px + 35px + 50px + ${proxy.$settingStore.StatusBarHeight}))`,
+      //#endif
+      //#ifdef H5
+      height: 'calc(100vh - (44px + 35px + 50px))',
+      //#endif
+    }"
+    :pageSize="pageSize"
+    :total="total"
+    :refresherLoad="false"
+    :refresherEnabled="true"
+    :refresherDefaultStyle="'none'"
+    :refresherThreshold="44"
+    :refresherBackground="'#f5f6f7'"
+    @refresh="refresh"
+    :data-theme="'theme-' + proxy.$settingStore.themeColor.name"
+  >
+    <template #default>
+      <u-loading-page :loading="state.loading" fontSize="16" style="z-index: 99"></u-loading-page>
+      <view class="content-area bg-white radius flex flex-wrap m10 p10" v-for="room in dataList" :key="room" @click="handlePopup(true, 'aboutMeeting', room)">
+        <view class="mr10 mtb-auto">
+          <u-image v-if="room.imgPath" :show-loading="true" :src="room.imgPath" width="50px" height="50px" radius="5px"></u-image>
+          <u-image v-else :show-loading="true" src="@/static/images/defaultImg.jpg" width="50px" height="50px" radius="5px"></u-image>
+        </view>
+        <view class="mtb-auto">
+          <view class="font16 text-black mb5">{{ room.roomName }}</view>
+          <view class="font12 text-gray">可容纳{{ room.capacity || 0 }}人</view>
+        </view>
+        <view class="mt10" style="width: 100%">
+          <timeSlot :currentDay="form.date" :aboutTimeData="room.dmMeetingList" :activeColor="proxy.$settingStore.themeColor.color" />
+        </view>
+      </view>
+    </template>
+  </oa-scroll>
+
+  <u-popup :show="popup.show" mode="bottom" bgColor="#fff" :round="10" @close="popup.show = false">
+    <view
+      :style="{
+        borderTopLeftRadius: '10px',
+        borderTopRightRadius: '10px',
+        overflow: 'hidden',
+      }"
+    >
+      <oa-calendar v-if="popup.type === 'switchTime'" :date="form.date" :showMonth="true" @change="calendarChange" @monthSwitch="calendarMonthSwitch">
+        <template #headerRight> </template>
+      </oa-calendar>
+
+      <view v-if="popup.type === 'aboutMeeting'">
+        <view class="flex p15 font16">
+          <view class="mtb-auto"> {{ popup.list.roomName }}</view>
+          <view class="mtb-auto ml-auto" @click="sheet.show = true">
+            <u-icon name="info-circle" size="16" label="更多" labelSize="14" labelColor="#333" color="#333"></u-icon>
+          </view>
+        </view>
+
+        <u-gap height="10" bgColor="#f5f6f7"></u-gap>
+        <u-checkbox-group v-model="checkboxValue" placement="column" shape="circle" :borderBottom="true" @change="checkboxChange" style="height: 42vh; overflow: auto">
+          <view v-for="(item, index) in checkboxList" :key="index">
+            <u-checkbox
+              :customStyle="{ padding: '15px', margin: '0', backgroundColor: `${item.isDisabledColor}30` }"
+              :label="item.timeSlot"
+              :name="item.startTime"
+              :disabled="item.isDisabled || item.isAbout === '已预约'"
+              :activeColor="proxy.$settingStore.themeColor.color"
+            >
+              <template #label>
+                <view class="font15 mtb-auto" :style="{ color: item.isDisabled || item.isAbout === '已预约' ? '#c8c9cc' : '#333333' }"> {{ item.timeSlot }}</view>
+                <view class="font15 mtb-auto ml-auto" :style="{ color: item.isDisabled || item.isAbout === '已预约' ? '#c8c9cc' : '#333333' }"> {{ item.isAbout }}</view>
+              </template>
+            </u-checkbox>
+          </view>
+        </u-checkbox-group>
+
+        <u-gap height="10" bgColor="#f5f6f7"></u-gap>
+
+        <view class="p10" style="overflow: hidden">
+          <u-button type="primary" @click="handleSubmit('下一步')" text="下一步" style="width: 100px; float: right"></u-button>
+        </view>
+      </view>
+    </view>
+  </u-popup>
+
+  <u-action-sheet
+    :actions="sheet.actions"
+    :show="sheet.show"
+    cancelText="取消"
+    :round="10"
+    :wrapMaxHeight="'50vh'"
+    :closeOnClickOverlay="true"
+    :safeAreaInsetBottom="true"
+    @close="sheet.show = false"
+    @select="handleSheet"
+  ></u-action-sheet>
+</template>
+
+<script setup>
+/*----------------------------------依赖引入-----------------------------------*/
+import { onLoad, onShow, onReady, onHide, onLaunch, onUnload, onNavigationBarButtonTap, onPageScroll } from "@dcloudio/uni-app";
+import { ref, reactive, computed, getCurrentInstance, toRefs, inject } from "vue";
+/*----------------------------------接口引入-----------------------------------*/
+import { MeetingRoomList, MeetingRoomReservationList } from "@/api/business/meeting.js";
+/*----------------------------------组件引入-----------------------------------*/
+import timeSlot from "./components/timeSlot.vue";
+/*----------------------------------store引入-----------------------------------*/
+import { useStores, systemStores } from "@/store/modules/index";
+/*----------------------------------公共方法引入-----------------------------------*/
+import { storageSystem } from "@/utils/storage"; // 公共方法引用
+/*----------------------------------公共变量-----------------------------------*/
+const { proxy } = getCurrentInstance();
+const useStore = useStores();
+const systemStore = systemStores();
+/*----------------------------------变量声明-----------------------------------*/
+const state = reactive({
+  loading: false,
+  dataList: [],
+  pageSize: 20,
+  total: 0,
+  form: {
+    date: proxy.$dayjs().format("YYYY-MM-DD"),
+    meetingRoomName: "",
+  },
+  popup: {
+    show: false,
+    type: "",
+    list: {},
+  },
+  sheet: {
+    show: false,
+    title: "",
+    actions: [
+      {
+        name: "更多",
+        fontSize: "16",
+        disabled: true,
+      },
+      {
+        name: "会议室详情",
+        fontSize: "16",
+        type: "meeting-details",
+      },
+    ],
+  },
+  weekData: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"],
+  checkboxValue: [],
+  checkboxList: [],
+});
+
+const { loading, dataList, pageSize, total, form, popup, sheet, weekData, checkboxValue, checkboxList } = toRefs(state);
+
+/** 初始化 */
+function init() {
+  state.checkboxValue = [];
+  state.checkboxList = [];
+
+  state.loading = true;
+  MeetingRoomReservationList({
+    date: state.form.date + " 00:00:00",
+    meetingRoomName: state.form.meetingRoomName,
+  })
+    .then((requset) => {
+      if (requset.status === "SUCCESS") {
+        state.dataList = requset.data;
+        state.total = requset.data.length;
+        state.loading = false;
+      }
+    })
+    .catch((err) => {
+      state.loading = false;
+    });
+
+  state.checkboxList = getAllTimesDay(state.form.date, 30);
+}
+
+/** 获取当天时间 */
+function getAllTimesDay(day, min) {
+  let defaultList = [];
+  // 获取当天开始的时间
+  const startOfDay = proxy.$dayjs(day).startOf("day");
+  const endOfDay = proxy.$dayjs(day).endOf("day");
+
+  // 循环半小时直到当天结束
+  for (let currentTime = startOfDay; currentTime.isBefore(endOfDay); currentTime = currentTime.add(min, "minute")) {
+    let isAfter = currentTime.add(min, "minute").isAfter(endOfDay); //当前时间是否在结束时间之后(true|false)
+    let startTime = currentTime.add(0, "minute").format("YYYY-MM-DD HH:mm:ss"); //获取开始时间
+    let endTime = isAfter ? endOfDay.format("YYYY-MM-DD HH:mm:ss") : currentTime.add(min, "minute").format("YYYY-MM-DD HH:mm:ss"); //获取结束时间
+    let timeSlot = proxy.$dayjs(startTime).format("HH:mm") + " - " + proxy.$dayjs(endTime).format("HH:mm"); //获取开始时间和结束时间“时、分”
+
+    const array = {
+      startTime: startTime,
+      endTime: endTime,
+      timeSlot: timeSlot,
+      isDisabled: false,
+      isAbout: "",
+      isDisabledColor: "#FFFFFF",
+      isDisabledFontColor: "#333333",
+    }; //此返回值(不可删除)可叠加
+
+    //判断当前时间是否相同或在其之后
+    if (proxy.$dayjs().isSameOrAfter(startTime)) {
+      array.isAbout = "不可预约";
+      array.isDisabled = true;
+    }
+
+    defaultList.push(array);
+  }
+  return defaultList;
+}
+
+/** 复选框改变事件 */
+function checkboxChange(e, index) {
+  if (e.length > 1) {
+    const startOfDay = proxy.$dayjs(e[0]);
+    const endOfDay = proxy.$dayjs(e[e.length - 1]);
+
+    for (let currentTime = startOfDay; currentTime.isBefore(endOfDay); currentTime = currentTime.add(30, "minute")) {
+      if (!e.includes(currentTime.format("YYYY-MM-DD HH:mm:ss"))) {
+        e.push(currentTime.format("YYYY-MM-DD HH:mm:ss"));
+      }
+    }
+  }
+
+  state.checkboxValue = e.sort((a, b) => new Date(`${proxy.$dayjs(a).format("YYYY-MM-DD HH:mm:ss")}`) - new Date(`${proxy.$dayjs(b).format("YYYY-MM-DD HH:mm:ss")}`));
+}
+
+/** 点击预约 */
+function handleSubmit() {
+  if (!state.checkboxValue.length) {
+    proxy.$modal.msg("请先选择时间");
+    return false;
+  }
+
+  systemStore.meetingList.form = {
+    roomId: state.popup.list.roomId, //房间Id
+    roomName: state.popup.list.roomName, //会议室名称
+    startDate: state.checkboxValue[0], //会议开始时间
+    endDate: state.checkboxValue[state.checkboxValue.length - 1], //会议结束时间
+    meetingName: useStore.nickName + "预约的会议", //会议名称
+    initiatorUser: {
+      contacts: useStore.phonenumber, //联系方式
+      deptId: useStore.deptId,
+      email: useStore.email,
+      id: useStore.userId,
+      isApprover: false,
+      name: useStore.nickName, //验证人名称
+      sex: useStore.sex,
+    }, //发起人信息
+    meetingDescribe: "", //会议介绍
+    users: [], //参会人信息
+    meetingMode: 0, //会议模式
+    sendType: ["站内信"], //通知类型(短信)
+    remark: "", //备注
+    room: state.popup.list, //会议室信息
+    meetingFileList: [], //会议文件信息
+  };
+
+  proxy.$tab.navigateTo(`/pages/business/common/meeting/new/index`);
+  state.popup.show = false;
+}
+
+/** 实时保存填写数据 */
+function realTimeSaving() {
+  if (!state.form.id) {
+    state.saveTime = proxy.$time.formatterDate(new Date(), "hh:mm");
+    storageSystem.set("project", state);
+  }
+}
+
+/** 日历日期改变事件 */
+function calendarChange(e) {
+  state.form.date = e.fulldate;
+  init();
+}
+
+/** 日历月份选择事件 */
+function calendarMonthSwitch(e) {
+  console.log(e);
+}
+
+/** 操作菜单 */
+function handleSheet(e) {
+  console.log(e);
+  if (e.type == "meeting-details") {
+  }
+}
+
+/** 操作弹窗 */
+function handlePopup(show, type, list) {
+  state.popup.show = show;
+  state.popup.type = type;
+  state.popup.list = list;
+
+  if (type === "aboutMeeting") {
+    list.dmMeetingList.forEach((e) => {
+      let startTime = proxy.$dayjs(e.startDate).add(0, "minute").format("YYYY-MM-DD HH:mm:ss");
+      let endTimeNum = e.endDate.indexOf("59") != -1 ? -29.59 : -30;
+      let endTime = proxy.$dayjs(e.endDate).add(endTimeNum, "minute").format("YYYY-MM-DD HH:mm:ss");
+
+      state.checkboxList.forEach((f) => {
+        if (proxy.$dayjs(f.startTime).isBetween(startTime, endTime, null, "[]")) {
+          f.isDisabledColor = proxy.$settingStore.themeColor.color;
+          f.isDisabledFontColor = "#FFFFFF";
+          f.isAbout = "已预约";
+        }
+      });
+    });
+  }
+}
+
+/**
+ * @scrollView刷新数据
+ */
+function refresh() {
+  init();
+}
+
+onReady(() => {});
+
+onShow(() => {
+  //调用系统主题颜色
+  proxy.$settingStore.systemThemeColor([1]);
+
+  init();
+});
+
+onLoad((options) => {});
+
+onUnload(() => {});
+</script>
+
+<style lang="scss" scoped>
+.content-area {
+  color: #000000;
+}
+</style>

+ 210 - 0
src/pages/business/common/meeting/new/index.vue

@@ -0,0 +1,210 @@
+<template>
+  <u-sticky class="shadow-default" bgColor="#fff" style="top: 0">
+    <u-navbar :titleStyle="{ color: '#000' }" :autoBack="true" title="新建日程" :placeholder="true" :safeAreaInsetTop="true" bgColor="#fff" @rightClick="submitForm()">
+      <template #left>
+        <view class="u-navbar__content__left__item">
+          <u-icon name="arrow-left" size="20" color="#000"></u-icon>
+        </view>
+      </template>
+      <template #right>
+        <view class="u-navbar__content__right__item">
+          <view style="color: #333">完成</view>
+        </view>
+      </template>
+    </u-navbar>
+  </u-sticky>
+
+  <oa-scroll
+    customClass="record-container scroll-height"
+    :isSticky="false"
+    :customStyle="{
+      //#ifdef APP-PLUS || MP-WEIXIN
+      height: `calc(100vh - (44px + ${proxy.$settingStore.StatusBarHeight}))`,
+      //#endif
+    }"
+    :refresherLoad="false"
+    :refresherEnabled="false"
+    :refresherDefaultStyle="'none'"
+    :refresherThreshold="44"
+    :refresherBackground="'#f5f6f7'"
+    :data-theme="'theme-' + proxy.$settingStore.themeColor.name"
+  >
+    <template #default>
+      <view class="content-area">
+        <view class="content-area-item mt10 p10 bg-white">
+          <view class="font15 weight mb10 required">会议议题</view>
+          <u-textarea
+            v-model="form.meetingName"
+            placeholder="请输入"
+            placeholderStyle="color:#909399;font-size:13px"
+            confirmType="return"
+            :autoHeight="true"
+            :maxlength="-1"
+            :height="'100%'"
+            border="none"
+            style="padding: 0px"
+          ></u-textarea>
+        </view>
+        <view class="content-area-item mt10 p10 bg-white">
+          <view class="font15 weight mb10">预约人</view>
+          <u-textarea
+            v-model="form.initiatorUser.name"
+            placeholder="请输入"
+            placeholderStyle="color:#909399;font-size:13px"
+            confirmType="return"
+            :autoHeight="true"
+            :maxlength="-1"
+            :height="'100%'"
+            border="none"
+            style="padding: 0px"
+            :disabled="true"
+          ></u-textarea>
+        </view>
+        <view class="content-area-item mt10 p10 bg-white">
+          <view class="font15 weight mb10 required">会议介绍</view>
+          <u-textarea
+            v-model="form.meetingDescribe"
+            placeholder="请输入"
+            placeholderStyle="color:#909399;font-size:13px"
+            confirmType="return"
+            :autoHeight="true"
+            :maxlength="-1"
+            :height="'100%'"
+            border="none"
+            style="padding: 0px"
+          ></u-textarea>
+        </view>
+        <view class="content-area-item mt10 p10 bg-white">
+          <view class="font14 weight mb10 required">参会人员</view>
+          <avatarList :userList="form.users" @deleteUsers="deleteUsers" />
+          <u-button class="mt20" type="primary" style="width: 100px; height: 25px" @click="insertUsers()" shape="circle" icon="plus" size="mini" :disabled="form.reportStatus == 1">
+            选择人员
+          </u-button>
+        </view>
+        <view class="content-area-item mt10 p10 bg-white">
+          <view class="font15 weight mb10">通知类型</view>
+          <u-checkbox-group v-model="form.sendType" placement="row" size="14px" @change="checkboxChange">
+            <u-checkbox :customStyle="{ marginRight: '10px' }" v-for="(item, index) in checkboxList" :key="index" :label="item.name" :name="item.name"> </u-checkbox>
+          </u-checkbox-group>
+        </view>
+      </view>
+    </template>
+  </oa-scroll>
+</template>
+
+<script setup>
+/*----------------------------------依赖引入-----------------------------------*/
+import { onLoad, onShow, onReady, onHide, onLaunch, onUnload, onNavigationBarButtonTap, onPageScroll } from "@dcloudio/uni-app";
+import { ref, reactive, computed, getCurrentInstance, toRefs, inject } from "vue";
+/*----------------------------------接口引入-----------------------------------*/
+import { meetingInfoAdd } from "@/api/business/meeting.js";
+/*----------------------------------组件引入-----------------------------------*/
+import avatarList from "../components/avatarList.vue";
+/*----------------------------------store引入-----------------------------------*/
+import { systemStores } from "@/store/modules/index";
+/*----------------------------------公共方法引入-----------------------------------*/
+/*----------------------------------公共变量-----------------------------------*/
+const { proxy } = getCurrentInstance();
+const systemStore = systemStores();
+/*----------------------------------变量声明-----------------------------------*/
+const state = reactive({
+  form: computed(() => {
+    return systemStore.meetingList.form;
+  }),
+  checkboxList: [{ name: "站内信" }, { name: "短信" }],
+});
+
+const { form, checkboxList } = toRefs(state);
+
+/** 初始化 */
+function init() {}
+
+/** 提交按钮 */
+function submitForm() {
+  var newForm = JSON.parse(JSON.stringify(state.form));
+
+  if (!newForm.meetingName) {
+    proxy.$modal.msg("请输入会议议题");
+    return false;
+  }
+
+  if (!newForm.meetingDescribe) {
+    proxy.$modal.msg("请输入会议介绍");
+    return false;
+  }
+
+  if (newForm.users.length <= 0) {
+    proxy.$modal.msg("请选择参会人员");
+    return false;
+  }
+
+  const minute = proxy.$dayjs(newForm.endDate).add(30, "minute");
+  const endOfDay = proxy.$dayjs(proxy.$dayjs(newForm.endDate).format("YYYY-MM-DD")).endOf("day");
+  const isAfter = minute.isAfter(endOfDay); //当前时间是否在结束时间之后(true|false)
+  const endTime = isAfter ? endOfDay.format("YYYY-MM-DD HH:mm:ss") : minute.format("YYYY-MM-DD HH:mm:ss");
+
+  newForm.endDate = endTime;
+  newForm.meetingFileList.forEach((e) => {
+    e.fileUrl = e.url;
+    e.fileName = e.name;
+    e.fileType = 1;
+  });
+  newForm.sendType = Array.isArray(newForm.sendType) ? newForm.sendType.join(",") : newForm.sendType;
+
+  meetingInfoAdd(newForm).then((res) => {
+    proxy.$modal.msg("会议室预约成功");
+    proxy.$tab.navigateBack(1); //返回到需要执行方法的页面
+    state.form = [];
+  });
+}
+
+/** 添加人员按钮事件 */
+function insertUsers() {
+  proxy.$tab.navigateTo(`/pages/business/common/projectMange/mall/index?number=200&type=3&title=选择参会人`).then(() => {
+    setTimeout(() => {
+      uni.$emit("FathertuSon__UserMall", state.form.users); //将值存储监听器
+    }, 500);
+  });
+}
+
+/** 删除人员按钮事件 */
+function deleteUsers(index) {
+  state.form.users.splice(index, 1);
+  realTimeSaving();
+}
+
+/** 点击预约 */
+function handleSubmit() {}
+
+onReady(() => {});
+
+onShow(() => {
+  //调用系统主题颜色
+  proxy.$settingStore.systemThemeColor([1]);
+
+  // 监听组件返回数据
+  uni.$on("SontoFather__UserMall", function (value) {
+    state.form.users = value;
+  });
+});
+
+onLoad((options) => {
+  init();
+});
+
+onUnload(() => {
+  uni.$off("SontoFather__UserMall"); //将值删除监听器
+});
+</script>
+
+<style lang="scss" scoped>
+.content-area {
+  color: #000000;
+}
+
+:deep() {
+  .u-textarea--disabled {
+    background-color: #ffffff;
+  }
+}
+</style>

+ 13 - 11
src/pages/business/common/projectMange/list/addEdit.vue

@@ -14,7 +14,7 @@
     :isSticky="false"
     :customStyle="{
       //#ifdef APP-PLUS || MP-WEIXIN
-      height: 'calc(100vh - 44px)',
+      height: `calc(100vh - (44px + ${proxy.$settingStore.StatusBarHeight}))`,
       //#endif
     }"
     :refresherLoad="false"
@@ -68,7 +68,9 @@
             disabledColor="transparent"
             disabled
           />
-          <u-button class="mt20" type="primary" style="width: 100px; height: 25px" @click="handleAction('公开状态', project_displayType)" shape="circle" icon="plus" size="mini"> 选择公开状态 </u-button>
+          <u-button class="mt20" type="primary" style="width: 100px; height: 25px" @click="handleAction('公开状态', project_displayType)" shape="circle" icon="plus" size="mini">
+            选择公开状态
+          </u-button>
         </view>
         <view class="content-area-item mt10 p10 bg-white">
           <view class="font14 weight mb10 required">项目负责人</view>
@@ -140,7 +142,7 @@ import { storageSystem } from "@/utils/storage"; // 公共方法引用
 /*----------------------------------公共变量-----------------------------------*/
 const systemStore = systemStores();
 const { proxy } = getCurrentInstance();
-const { project_status, project_type, project_ascription,project_displayType } = proxy.useDict("project_status", "project_type", "project_ascription","project_displayType");
+const { project_status, project_type, project_ascription, project_displayType } = proxy.useDict("project_status", "project_type", "project_ascription", "project_displayType");
 const props = defineProps({
   id: {
     type: String,
@@ -179,13 +181,14 @@ const { pageTitle, projectHeadList, projectMemberList, form, rules, actionShow,
 /** 添加人员按钮事件 */
 function insertUsers(key) {
   state.projectKey = key;
-  //将人员选中数据传入store中
-  systemStore.mallList.activeUserList = state[key];
   if (key === "projectHeadList") {
-    proxy.$tab.navigateTo(`/pages/business/common/projectMange/mall/index?number=1&type=1`);
+    proxy.$tab.navigateTo(`/pages/business/common/projectMange/mall/index?number=1&title=选择项目负责人`);
   } else if (key === "projectMemberList") {
-    proxy.$tab.navigateTo(`/pages/business/common/projectMange/mall/index?number=50&type=2`);
+    proxy.$tab.navigateTo(`/pages/business/common/projectMange/mall/index?number=50&title=选择项目成员`);
   }
+  setTimeout(() => {
+    uni.$emit("FathertuSon__UserMall", state[key]); //将值存储监听器
+  }, 500);
 }
 
 /** 删除人员按钮事件 */
@@ -211,7 +214,7 @@ function selectAction(e) {
   if (state.actionTitle == "项目类型") {
     state.form.projectType = e.value[0].value;
   } else if (state.actionTitle == "项目状态") {
-    state.form.projectStatus = e.value[0].value; 
+    state.form.projectStatus = e.value[0].value;
   } else if (state.actionTitle == "公开状态") {
     state.form.visibleRange = e.value[0].value;
   }
@@ -369,14 +372,13 @@ onShow(() => {
   proxy.$settingStore.systemThemeColor([1]);
 
   //监听组件返回数据
-  uni.$on("UserMall", function (value) {
-    console.log(value);
+  uni.$on("SontoFather__UserMall", function (value) {
     state[state.projectKey] = value;
   });
 });
 
 onUnload(() => {
-  uni.$off("UserMall"); //将值删除监听器
+  uni.$off("SontoFather__UserMall"); //将值删除监听器
 });
 </script>
 

+ 15 - 0
src/pages/business/common/projectMange/mall/components/mall-list.vue

@@ -179,6 +179,21 @@ export default {
       });
     },
   },
+  watch: {
+    activeUserList: {
+      handler(val, oldVal) {
+        if (val) {
+          val.forEach((e) => {
+            this.checkboxList.push(e.id);
+            this.checkboxUserData.push(e);
+            this.checkboxUserList.push(e.label);
+          });
+        }
+      },
+      immediate: false, //刷新加载 立马触发一次handler
+      deep: true, // 可以深度检测,里面每个值改变都会通知数据更新。
+    },
+  },
 };
 </script>
 

+ 17 - 12
src/pages/business/common/projectMange/mall/index.vue

@@ -19,7 +19,10 @@
     :isSticky="false"
     :customStyle="{
       //#ifdef APP-PLUS || MP-WEIXIN
-      height: 'calc(100vh - 44px)',
+      height: `calc(100vh - (44px + 48px + 60px + ${proxy.$settingStore.StatusBarHeight}))`,
+      //#endif
+      //#ifdef H5
+      height: 'calc(100vh - (0px + 48px + 60px))',
       //#endif
     }"
     :refresherLoad="false"
@@ -66,18 +69,17 @@ const state = reactive({
   activeUserNumber: undefined,
   pageTitle: "",
 });
-const { defaultHeadList, userList, activeUserList, activeUserNumber,pageTitle } = toRefs(state);
+const { defaultHeadList, userList, activeUserList, activeUserNumber, pageTitle } = toRefs(state);
 
 function init() {
   deptUserTreeSelect({ pageNum: "1", pageSize: "10000" }).then((res) => {
     state.userList = JSON.parse(JSON.stringify(res.data).replace(/value/g, "id"))[0].children;
   });
-  state.activeUserList = systemStore.mallList.activeUserList;
 }
 
 function handleSubmit(event) {
   proxy.$tab.navigateBack(1); //返回到需要执行方法的页面
-  uni.$emit("UserMall", event); //将值存储监听器
+  uni.$emit("SontoFather__UserMall", event); //将值存储监听器
 }
 
 function handleChange() {}
@@ -87,22 +89,25 @@ onReady(() => {});
 onShow(() => {});
 
 onLoad((options) => {
+  // 监听组件返回数据
+  uni.$on("FathertuSon__UserMall", function (value) {
+    state.activeUserList = value;
+  });
+
   if ("number" in options) {
     state.activeUserNumber = parseInt(options.number);
   }
-  init();
 
-  if (options.type==1) {
-    state.pageTitle = "选择项目负责人";
-  } else if (options.type==2) {
-    state.pageTitle = "选择项目成员";
-  }else{
-    state.pageTitle = "选择抄送人"
+  if ("title" in options) {
+    state.pageTitle = options.title;
   }
 
+  init();
 });
 
-onUnload(() => {});
+onUnload(() => {
+  uni.$off("FathertuSon__UserMall"); //将值删除监听器
+});
 </script>
 
 <style></style>

+ 4 - 7
src/pages/business/common/projectMange/record/details.vue

@@ -13,9 +13,6 @@
       //#ifdef APP-PLUS || MP-WEIXIN
       height: `calc(100vh - (44px + ${proxy.$settingStore.StatusBarHeight}))`,
       //#endif
-      //#ifdef H5
-      height: 'calc(100vh - (44px))',
-      //#endif
     }"
     :refresherLoad="false"
     :refresherEnabled="false"
@@ -62,7 +59,7 @@
         </view>
         <view class="content-area-center mb10">
           <view class="content-area-center-top">图片</view>
-          <view class="imageBox" v-if="JSON.parse(item.reportImage)&&JSON.parse(item.reportImage).length>0">
+          <view class="imageBox" v-if="JSON.parse(item.reportImage) && JSON.parse(item.reportImage).length > 0">
             <image class="image m5" style="width: 50px" mode="widthFix" v-for="(a, index) in JSON.parse(item.reportImage)" :key="index" :src="a.url" @click="previewImage(index)" />
           </view>
           <view class="imageBox" v-else>无</view>
@@ -70,7 +67,7 @@
 
         <view class="content-area-center mb10">
           <view class="content-area-center-top">附件 </view>
-          <view v-if="JSON.parse(item.reportFile)&&JSON.parse(item.reportFile).length>0">
+          <view v-if="JSON.parse(item.reportFile) && JSON.parse(item.reportFile).length > 0">
             <uni-link v-for="(file, index) in JSON.parse(item.reportFile)" :key="index" :href="file.url" text="file.url" style="color: rgba(0, 0, 0, 0.7)">{{ file.name }}</uni-link>
           </view>
           <view v-else>无</view>
@@ -179,8 +176,8 @@ function init() {
         dataList.value = requset.data.records;
         state.loading = false;
         pmReportReaders.value = requset.data.records[0].pmReportReaders;
-        state.tabsList[0].name=state.tabsList[0].name+'('+pmReportReaders.value.read+')';
-        state.tabsList[1].name=state.tabsList[1].name+'('+pmReportReaders.value.unRead+')';
+        state.tabsList[0].name = state.tabsList[0].name + "(" + pmReportReaders.value.read + ")";
+        state.tabsList[1].name = state.tabsList[1].name + "(" + pmReportReaders.value.unRead + ")";
         reportDetailData.value.treeSelectNodes = proxy.$common.findTreeNodes(tree.value, tabsCurrent.value == 0 ? pmReportReaders.value.readAlready : pmReportReaders.value.readNotAlready);
         var imgs = JSON.parse(dataList.value[0].reportImage);
         var files = JSON.parse(dataList.value[0].reportFile);

+ 36 - 50
src/pages/business/common/projectMange/record/timingLog.vue

@@ -1,22 +1,19 @@
 <template>
   <u-sticky class="shadow-default" bgColor="#fff" style="top: 0">
-    <u-navbar :titleStyle="{ color: '#000' }" :autoBack="true" title="定时日志" :placeholder="true" :safeAreaInsetTop="true" bgColor="#fff">
-     
-    </u-navbar>
-   
+    <u-navbar :titleStyle="{ color: '#000' }" :autoBack="true" title="定时日志" :placeholder="true" :safeAreaInsetTop="true" bgColor="#fff"> </u-navbar>
   </u-sticky>
 
   <oa-scroll
     customClass="record-container scroll-height"
     :pageSize="pageSize"
     :total="total"
-    :isSticky="true"
+    :isSticky="false"
     :customStyle="{
       //#ifdef APP-PLUS || MP-WEIXIN
-      height: 'calc(100vh - 40px)',
+      height: `calc(100vh - (44px + ${proxy.$settingStore.StatusBarHeight}))`,
       //#endif
       //#ifdef H5
-      height: 'calc(100vh - 40px)',
+      height: 'calc(100vh - (44px))',
       //#endif
     }"
     :refresherLoad="true"
@@ -30,14 +27,13 @@
     :data-theme="'theme-' + proxy.$settingStore.themeColor.name"
   >
     <template #default>
-
       <u-loading-page :loading="state.loading" fontSize="16" style="z-index: 99"></u-loading-page>
       <view class="content-area" v-for="(group, date) in proxy.$common.groupedItems(state.timedList, 'submitDate')" :key="date">
         <view class="content-area-time font14">{{ proxy.$time.jktTimes(date, "否") }}</view>
         <view class="content-area-center bg-white" v-for="(el, ind) in group" :key="ind">
-          <view class="content-area-top menu-item" style="float:right;padding:10px 0px">
+          <view class="content-area-top menu-item" style="float: right; padding: 10px 0px">
             <view class="content-area-top-time"> </view>
-            <u-icon  class="content-area-top-icon" name="more-dot-fill" size="20" color="#000" @click="moreClick(el)"></u-icon>
+            <u-icon class="content-area-top-icon" name="more-dot-fill" size="20" color="#000" @click="moreClick(el)"></u-icon>
           </view>
           <view class="flex mb10" @click="goContentDetails(el)">
             <u-avatar
@@ -57,17 +53,15 @@
           <view class="mb5" @click="goContentDetails(el)">
             <u-text :text="el.contentText.length >= 100 ? el.contentText.slice(0, 100) + '···' : el.contentText" color="#666666" size="14"></u-text>
           </view>
-          <view style="font-size:12px;color:#a7a4a4">
-            <u-button size="mini" style="width:50px;float:left;margin-right:5px;line-height:18px;height:18px">定时日志</u-button>
+          <view style="font-size: 12px; color: #a7a4a4">
+            <u-button size="mini" style="width: 50px; float: left; margin-right: 5px; line-height: 18px; height: 18px">定时日志</u-button>
             将于 {{ el.timingTime.replace("T", " ").slice(0, 16) }} 发布
           </view>
-        
         </view>
       </view>
     </template>
   </oa-scroll>
 
-
   <u-popup :show="popup.show" mode="bottom" bgColor="#fff" :round="10" @close="popup.show = false">
     <view
       :style="{
@@ -76,7 +70,6 @@
         overflow: 'hidden',
       }"
     >
-     
       <u-button
         class="custom-style"
         type="info"
@@ -121,13 +114,8 @@
     </view>
   </u-popup>
 
-  
-
-
-
   <uni-popup ref="alertDialog" type="dialog">
-    <uni-popup-dialog :type="state.tip.type" cancelText="取消" confirmText="确定" title="操作提醒" :content="state.tip.content" @confirm="dialogConfirm"
-      @close="dialogClose"></uni-popup-dialog>
+    <uni-popup-dialog :type="state.tip.type" cancelText="取消" confirmText="确定" title="操作提醒" :content="state.tip.content" @confirm="dialogConfirm" @close="dialogClose"></uni-popup-dialog>
   </uni-popup>
 
   <u-modal
@@ -140,7 +128,6 @@
     @cancel="modal.show = false"
     @close="modal.show = false"
   ></u-modal>
-
 </template>
 
 <script setup>
@@ -174,17 +161,16 @@ const state = reactive({
   },
   eventList: {}, //数据存储
 
-
-  tip:{
-    type:undefined,//弹框类型
-    content:"",//提示信息
-    data:{},//带入数据
-    operation:undefined,//操作类型
+  tip: {
+    type: undefined, //弹框类型
+    content: "", //提示信息
+    data: {}, //带入数据
+    operation: undefined, //操作类型
   },
-  timedList:[]
+  timedList: [],
 });
 
-const {pageSize, current, total,popup,eventList,modal,timedList} = toRefs(state);
+const { pageSize, current, total, popup, eventList, modal, timedList } = toRefs(state);
 /**
  * 操作弹框提醒
  * @param type  弹框类型
@@ -192,20 +178,20 @@ const {pageSize, current, total,popup,eventList,modal,timedList} = toRefs(state)
  * @param item 带入数据
  * @param operation 操作类型
  */
- function tips(type,content,item,operation){
-  state.tip.type=type
-  state.tip.content=content
-  state.tip.data=item
-  state.tip.operation=operation
-  proxy.$refs.alertDialog.open()
+function tips(type, content, item, operation) {
+  state.tip.type = type;
+  state.tip.content = content;
+  state.tip.data = item;
+  state.tip.operation = operation;
+  proxy.$refs.alertDialog.open();
 }
 /**弹框确定操作 */
-function dialogConfirm(){
-  if(state.tip.operation =='delete'){
-    handleSubmit('delete',state.tip.data)
+function dialogConfirm() {
+  if (state.tip.operation == "delete") {
+    handleSubmit("delete", state.tip.data);
   }
-  if(state.tip.operation=='exit'){
-    handleSubmit('exit',state.tip.data)
+  if (state.tip.operation == "exit") {
+    handleSubmit("exit", state.tip.data);
   }
 }
 /**
@@ -213,8 +199,8 @@ function dialogConfirm(){
  */
 function init() {
   projectApi()
-    .TimedReports({
-     }).then((requset) => {
+    .TimedReports({})
+    .then((requset) => {
       state.timedList = requset.data;
       requset.data.forEach((el) => {
         el.contentText = "";
@@ -224,10 +210,10 @@ function init() {
       });
       state.total = requset.data.length;
       state.loading = false;
-     })
+    })
     .catch((err) => {
       state.loading = false;
-    })
+    });
 }
 
 /**
@@ -265,7 +251,7 @@ function handleModal(type, content) {
 }
 
 /** 编辑、删除日报*/
-function handleSubmit(type,item) {
+function handleSubmit(type, item) {
   if (type === "update") {
     proxy.$tab.navigateTo(`/pages/business/common/projectMange/write/insert?templateId=1&id=${item.id}`);
     state.modal.show = false;
@@ -281,7 +267,7 @@ function handleSubmit(type,item) {
       .catch((errors) => {
         proxy.$modal.msg(errors);
       });
-  } 
+  }
 }
 
 onReady(() => {});
@@ -335,12 +321,12 @@ onUnload(() => {
   }
 }
 
-.pp{
+.pp {
   text-align: left;
 }
 </style>
 <style>
-.pp .u-modal__content{
-  justify-content: left !important
+.pp .u-modal__content {
+  justify-content: left !important;
 }
 </style>

+ 107 - 136
src/pages/business/common/projectMange/write/components/template1.vue

@@ -1,6 +1,6 @@
 <template>
   <view class="content-area">
-    <view class="content-area-title font12 mtb5 plr10" v-if="!state.form.id">{{state.form.id}}实时保存,保存时间 {{ saveTime }}</view>
+    <view class="content-area-title font12 mtb5 plr10" v-if="!state.form.id">{{ state.form.id }}实时保存,保存时间 {{ saveTime }}</view>
 
     <view class="content-area-item p10 bg-white">
       <view class="font14 weight mb10 required">工作内容</view>
@@ -67,30 +67,29 @@
     </view>
     <view class="content-area-item mt10 p10 bg-white">
       <view class="font14 weight mb10">图片上传</view>
-      <view style="color:#f56c6c;font-size:11px;margin-bottom:10px">( 注:不可同步钉钉,最多上传5张 )</view>
+      <view style="color: #f56c6c; font-size: 11px; margin-bottom: 10px">( 注:不可同步钉钉,最多上传5张 )</view>
       <oa-upload :uploadCount="5" :uploadList="reportImage1" :uploadListSrc="'url'" @uploadSuccessChange="uploadSuccessChange" @uploadDeleteChange="uploadDeleteChange"></oa-upload>
     </view>
     <view class="content-area-item mt10 p10 bg-white">
       <view class="font14 weight mb10">附件上传</view>
-      <view style="color:#f56c6c;font-size:11px;margin-bottom:10px">( 注:不可同步钉钉,最多上传5个 )</view>
-      <uni-file-picker limit="5" 
-        @select='selectUpload' 
-          v-model="reportFile1"
-					:auto-upload='false' 
-					file-extname='git,pdf,docx,doc,xls,xlsx,ppt,pptx,txt,zip,rar,7z,gz,bz2,tar,tgz,tbz,txz,apk,ipa,mp3,mp4,avi,flv,rmvb,wmv,mkv,mov,wma,aac,m4a,amr,ogg,flac,wav,amr,ape,m4r,aac,ac3,dts,m4b,m4p,m4v,mp2,mpe,mpeg,mpg,mpv,ogv,rm,swf,vob,wmv,3gp,3g2,asf,asx,avi,flv,m2ts,m4v,mkv,mov,mp4,mpg,mpeg,rm,swf,vob,wmv,3gp,3g2,asf,asx,avi,' 
-					file-mediatype="all" 
-		  >
+      <view style="color: #f56c6c; font-size: 11px; margin-bottom: 10px">( 注:不可同步钉钉,最多上传5个 )</view>
+      <uni-file-picker
+        limit="5"
+        @select="selectUpload"
+        v-model="reportFile1"
+        :auto-upload="false"
+        file-extname="git,pdf,docx,doc,xls,xlsx,ppt,pptx,txt,zip,rar,7z,gz,bz2,tar,tgz,tbz,txz,apk,ipa,mp3,mp4,avi,flv,rmvb,wmv,mkv,mov,wma,aac,m4a,amr,ogg,flac,wav,amr,ape,m4r,aac,ac3,dts,m4b,m4p,m4v,mp2,mpe,mpeg,mpg,mpv,ogv,rm,swf,vob,wmv,3gp,3g2,asf,asx,avi,flv,m2ts,m4v,mkv,mov,mp4,mpg,mpeg,rm,swf,vob,wmv,3gp,3g2,asf,asx,avi,"
+        file-mediatype="all"
+      >
       </uni-file-picker>
-       <!-- 文件列表回显 -->
-       <br>
-      <view v-for="(file, index) in reportFile1" :key="index" style="border-bottom:1px solid #eee;margin:6px;padding:6px;font-size:12px">
-       <uni-link :href="file.url" text="file.url">{{file.name}}</uni-link>
-        <uni-icons type="closeempty" size="12" style="float:right" @click="delectFile(file)"></uni-icons>
+      <!-- 文件列表回显 -->
+      <br />
+      <view v-for="(file, index) in reportFile1" :key="index" style="border-bottom: 1px solid #eee; margin: 6px; padding: 6px; font-size: 12px">
+        <uni-link :href="file.url" text="file.url">{{ file.name }}</uni-link>
+        <uni-icons type="closeempty" size="12" style="float: right" @click="delectFile(file)"></uni-icons>
       </view>
     </view>
 
-    
-
     <view class="content-area-item mt10 p10 bg-white">
       <view class="font14 weight mb10">抄送到人</view>
       <avatarList :userList="userList" @deleteUsers="deleteUsers" />
@@ -144,51 +143,38 @@
     <view class="app-button-padding"></view>
     <view class="app-button-fixed">
       <!-- {{ form }} -->
-      <u-button class="app-buttom" type="primary" @click="handleSubmit('提交')" shape="circle"> {{ form.isRegularlySend == 1 &&form.reportStatus!=1 ?  "保 存" : "确 定" }} </u-button>
+      <u-button class="app-buttom" type="primary" @click="handleSubmit('提交')" shape="circle"> {{ form.isRegularlySend == 1 && form.reportStatus != 1 ? "保 存" : "确 定" }} </u-button>
     </view>
   </view>
 
   <u-datetime-picker :show="timeShow" v-model="timeValue" mode="datetime" :closeOnClickOverlay="true" @cancel="timeShow = false" @confirm="timeConfirm"></u-datetime-picker>
 
   <u-modal :show="modalShow" title="" :confirmText="'确定'" :cancelText="'取消'" :zoom="false" :showCancelButton="true" @confirm="modalConfirm" @cancel="modalShow = false">
-    <view class="slot-content" style="max-height: 45vh;overflow:auto">
-     
-    <view v-if="projectsList.length > 0">
-    
-      <u-checkbox-group v-model="projectsCheck" placement="row" :size="14" style="max-height: 100%; overflow: auto">
-        <view class="checkbox-group-title">最近使用</view>
-        <block  v-for="(item, index) in projectsList">
-          <u-checkbox v-if="item.submissions>0"
-            :customStyle="{ marginBottom: '8px', width: '50%' }"
-            :label="item.projectName+' ('+item.submissions+'次)'"
-            :name="item.id"
-            :activeColor="proxy.$settingStore.themeColor.color"
-          >
-          </u-checkbox>
-        </block>
-				<u-line class="u-line"  color="info" style="margin:10px 0"></u-line>
-
-
-        <view  class="checkbox-group-title">其他</view>
-  
-        <block  v-for="(item, index) in projectsList">
-          <u-checkbox v-if="!item.submissions"
-            :customStyle="{ marginBottom: '8px', width: '50%' }"
-            :label="item.projectName"
-            :name="item.id"
-            :activeColor="proxy.$settingStore.themeColor.color"
-          >
-        </u-checkbox>
-       
-  
-           
-       
-        </block>
-
-       
-      </u-checkbox-group>
- 
-      <!-- <u-checkbox-group v-else v-model="projectsCheck" placement="row" :size="14"  style="max-height: 100%; overflow: auto">
+    <view class="slot-content" style="max-height: 45vh; overflow: auto">
+      <view v-if="projectsList.length > 0">
+        <u-checkbox-group v-model="projectsCheck" placement="row" :size="14" style="max-height: 100%; overflow: auto">
+          <view class="checkbox-group-title">最近使用</view>
+          <block v-for="(item, index) in projectsList">
+            <u-checkbox
+              v-if="item.submissions > 0"
+              :customStyle="{ marginBottom: '8px', width: '50%' }"
+              :label="item.projectName + ' (' + item.submissions + '次)'"
+              :name="item.id"
+              :activeColor="proxy.$settingStore.themeColor.color"
+            >
+            </u-checkbox>
+          </block>
+          <u-line class="u-line" color="info" style="margin: 10px 0"></u-line>
+
+          <view class="checkbox-group-title">其他</view>
+
+          <block v-for="(item, index) in projectsList">
+            <u-checkbox v-if="!item.submissions" :customStyle="{ marginBottom: '8px', width: '50%' }" :label="item.projectName" :name="item.id" :activeColor="proxy.$settingStore.themeColor.color">
+            </u-checkbox>
+          </block>
+        </u-checkbox-group>
+
+        <!-- <u-checkbox-group v-else v-model="projectsCheck" placement="row" :size="14"  style="max-height: 100%; overflow: auto">
         <u-checkbox
           :customStyle="{ marginBottom: '8px', width: '50%' }"
           v-for="(item, index) in projectsList"
@@ -199,8 +185,8 @@
         >
         </u-checkbox>
       </u-checkbox-group> -->
-    </view>
-      
+      </view>
+
       <view v-else>请联系项目管理人员给您分配项目后重试!</view>
     </view>
   </u-modal>
@@ -255,8 +241,8 @@ const state = reactive({
   userDate: [],
   saveTime: "",
 });
-const reportImage1=ref([])//图片
-const reportFile1=ref([])//附件
+const reportImage1 = ref([]); //图片
+const reportFile1 = ref([]); //附件
 const { timeShow, timeValue, modalShow } = toRefs(modal);
 const { form, projectsCheck, projectsList, userList, userDate, saveTime } = toRefs(state);
 
@@ -267,8 +253,6 @@ function init() {
   // dUserList().then((res) => {
   //   state.userDate = res.data;
   // });
-
-
 }
 
 /** 时间选择器确定按钮点击事件 */
@@ -288,10 +272,11 @@ function switchChage(e, key) {
 
 /** 添加人员按钮事件 */
 function insertUsers() {
-  //将人员选中数据传入store中
-  systemStore.mallList.activeUserList = state.userList;
- 
-  proxy.$tab.navigateTo(`/pages/business/common/projectMange/mall/index?number=200&type=3`);
+  proxy.$tab.navigateTo(`/pages/business/common/projectMange/mall/index?number=200&title=选择抄送人`).then(() => {
+    setTimeout(() => {
+      uni.$emit("FathertuSon__UserMall", state.userList); //将值存储监听器
+    }, 500);
+  });
 }
 
 /** 删除人员按钮事件 */
@@ -316,7 +301,7 @@ function insertProjects() {
 
 /** 实时保存填写数据 */
 function realTimeSaving() {
-  if(!state.form.id){
+  if (!state.form.id) {
     state.saveTime = proxy.$time.formatterDate(new Date(), "hh:mm");
     storageSystem.set("project", state);
   }
@@ -352,57 +337,52 @@ function modalConfirm() {
 /**
  * @图片上传成功回调
  */
- function uploadSuccessChange(e) {
+function uploadSuccessChange(e) {
   reportImage1.value.push({
     name: e.name,
     url: e.url,
-  })
-  reportImage1.value=reportImage1.value.slice(0,5)
-  realTimeSaving()
+  });
+  reportImage1.value = reportImage1.value.slice(0, 5);
+  realTimeSaving();
 }
 /**
  * @图片删除回调
  */
- function uploadDeleteChange(e) {
+function uploadDeleteChange(e) {
   reportImage1.value = e;
-  realTimeSaving()
+  realTimeSaving();
 }
 
-
-
-
-
 /**
  * @文件删除
  */
-function delectFile(param){
+function delectFile(param) {
   reportFile1.value = reportFile1.value.filter(function (item) {
-    return item.name!=param.name;
+    return item.name != param.name;
   });
-  realTimeSaving()
+  realTimeSaving();
 }
 
-
 /**
  * @文件上传
  */
 function selectUpload(e) {
   // console.log('上传:', e)
 
-    e.tempFilePaths.forEach((item,index) => {
-      uni.uploadFile({
-        url: config.baseUrl+'/service-file/upload', 
-        filePath: item,
-        name: 'file',
-        success: (uploadFileRes) => {
-          reportFile1.value.push(JSON.parse(uploadFileRes.data).data)
-          realTimeSaving()
-        },
-        fail: (err) => {
-          console.log(err);
-        }
-      })
-   })
+  e.tempFilePaths.forEach((item, index) => {
+    uni.uploadFile({
+      url: config.baseUrl + "/service-file/upload",
+      filePath: item,
+      name: "file",
+      success: (uploadFileRes) => {
+        reportFile1.value.push(JSON.parse(uploadFileRes.data).data);
+        realTimeSaving();
+      },
+      fail: (err) => {
+        console.log(err);
+      },
+    });
+  });
 }
 // function delectUpload(e){
 //   console.log(e)
@@ -414,8 +394,6 @@ function selectUpload(e) {
 // 	console.log('上传失败:', e)
 // }
 
-
-
 /** 提交 */
 function handleSubmit() {
   state.form.sendDingTalk == true ? 1 : 0;
@@ -425,27 +403,26 @@ function handleSubmit() {
   state.form.workContents.forEach((e) => {
     e.workTime = Number(e.workTime);
   });
-  state.form.reportImage=JSON.stringify(reportImage1.value);
-  state.form.reportFile=JSON.stringify(reportFile1.value);
+  state.form.reportImage = JSON.stringify(reportImage1.value);
+  state.form.reportFile = JSON.stringify(reportFile1.value);
   projectApi()
     .ReportInsert(state.form)
     .then((requset) => {
       proxy.$tab.redirectTo("/pages/business/common/projectMange/record/index"); //返回到需要执行方法的页面
 
       // storageSystem.set("project", state);
-    }).catch((err) => {
-     
-    });;
+    })
+    .catch((err) => {});
 }
 watch(
   () => reportFile1.value.length,
   (val) => {
-    var element = document.querySelector('.files-button');
-   if(reportFile1.value.length>=5){
-    element.style.display = 'none';
-   }else{
-    element.style.display = 'block';
-   }
+    var element = document.querySelector(".files-button");
+    if (reportFile1.value.length >= 5) {
+      element.style.display = "none";
+    } else {
+      element.style.display = "block";
+    }
   }
 );
 
@@ -457,13 +434,13 @@ watch(
     state.projectsList = [];
     state.form.reportImage = [];
     state.form.reportFile = [];
-   
+
     Object.keys(props.projectList).forEach((key) => {
       state.form[key] = props.projectList[key];
     });
- 
-    reportImage1.value=state.form.reportImage?JSON.parse(state.form.reportImage):[];
-    reportFile1.value=state.form.reportFile?JSON.parse(state.form.reportFile):[];
+
+    reportImage1.value = state.form.reportImage ? JSON.parse(state.form.reportImage) : [];
+    reportFile1.value = state.form.reportFile ? JSON.parse(state.form.reportFile) : [];
     state.form.workContents.forEach((e) => {
       state.projectsCheck.push(e.projectId);
     });
@@ -490,42 +467,36 @@ watch(
       });
     });
 
-    if(!state.form.id){
-        storageSystem.set("project", state);
-      }
+    if (!state.form.id) {
+      storageSystem.set("project", state);
+    }
   }
 );
 
 onReady(() => {});
 
 onShow(() => {
-
   init();
 
-
   //循环将缓存数据遍历
 
-  if(!state.form.id){
+  if (!state.form.id) {
     var storages = storageSystem.get("project");
     Object.keys(storages).forEach((key) => {
       state[key] = storages[key];
     });
   }
-  
-  
 
   // 监听组件返回数据
-  uni.$on("UserMall", function (value) {
+  uni.$on("SontoFather__UserMall", function (value) {
     state.userList = value;
-    if(!state.form.id){
+    if (!state.form.id) {
       realTimeSaving();
     }
-   
   });
 });
 
 onLoad((options) => {
-
   if (options.id) {
     state.form.id = options.id;
   } else {
@@ -534,24 +505,24 @@ onLoad((options) => {
 });
 
 onUnload(() => {
-  uni.$off("UserMall"); //将值删除监听器
+  uni.$off("SontoFather__UserMall"); //将值删除监听器
 });
 </script>
-<style lang="scss" >
- :deep(.uni-file-picker__lists, .is-text-box){
-  display:none!important;
-  opacity:0!important;
-  height:0!important;
+<style lang="scss">
+:deep(.uni-file-picker__lists, .is-text-box) {
+  display: none !important;
+  opacity: 0 !important;
+  height: 0 !important;
 }
 </style>
 <style lang="scss" scoped>
-
-.checkbox-group-title{
-  display:block;width:100%;
-  font-size:16px;
-  font-weight:bold;
+.checkbox-group-title {
+  display: block;
+  width: 100%;
+  font-size: 16px;
+  font-weight: bold;
   note-color: #909399;
-  margin-bottom:10px;
+  margin-bottom: 10px;
 }
 :deep() {
   .u-cell__body {

+ 1 - 1
src/pages/business/common/projectMange/write/index.vue

@@ -19,7 +19,7 @@
     :isSticky="true"
     :customStyle="{
       //#ifdef APP-PLUS || MP-WEIXIN
-      height: 'calc(100vh - 88px)',
+      height: `calc(100vh - (88px + ${proxy.$settingStore.StatusBarHeight}))`,
       //#endif
     }"
     :refresherLoad="false"

+ 7 - 10
src/pages/business/common/projectMange/write/insert.vue

@@ -6,7 +6,7 @@
           <u-icon name="arrow-left" size="20" color="#000"></u-icon>
         </view>
       </template>
-      <template #right v-if="state.pageTitle=='报告填写'">
+      <template #right v-if="state.pageTitle == '报告填写'">
         <view class="u-navbar__content__right__item">
           <u-icon name="more-dot-fill" size="20" color="#000" @click="moreClick()"></u-icon>
         </view>
@@ -19,7 +19,7 @@
     :isSticky="false"
     :customStyle="{
       //#ifdef APP-PLUS || MP-WEIXIN
-      height: 'calc(100vh - 44px)',
+      height: `calc(100vh - (44px + ${proxy.$settingStore.StatusBarHeight}))`,
       //#endif
     }"
     :refresherLoad="false"
@@ -67,18 +67,17 @@ const state = reactive({
   newProjectList: {},
   pageTitle: "",
 });
-const { modalShow, newProjectList,pageTitle } = toRefs(state);
+const { modalShow, newProjectList, pageTitle } = toRefs(state);
 
 function moreClick() {
   state.modalShow = true;
 }
 
-
 /**
  * @列表查询
  * @api接口查询
  */
- function selectListApi() {
+function selectListApi() {
   projectApi()
     .ProjectsWeekList({
       id: parseInt(props.id),
@@ -86,8 +85,8 @@ function moreClick() {
     .then((requset) => {
       if (requset.data.length > 0) {
         const data = requset.data[1].weekData[0];
-        state.newProjectList =data
-        console.log(state.newProjectList)
+        state.newProjectList = data;
+        console.log(state.newProjectList);
       }
     })
     .catch((err) => {});
@@ -119,7 +118,6 @@ function handleSubmit(type, id) {
       });
   }
   if (type === "update") {
-
   }
 }
 
@@ -141,9 +139,8 @@ onLoad((options) => {
     selectListApi();
   } else {
     state.pageTitle = "报告填写";
-    state.newProjectList={}
+    state.newProjectList = {};
   }
-
 });
 
 onUnload(() => {});

+ 1 - 2
src/pages/business/fireIot/facilitiesGather/mapGather.vue

@@ -20,13 +20,12 @@ const commonStore = commonStores(); //全局公共Store
 
 const { proxy } = getCurrentInstance();
 
-const pages = getCurrentPages();
-
 const dataArray = commonStore.facilitiesGatherArray;
 const dataType = commonStore.facilitiesGatherType;
 
 // #ifdef APP-PLUS
 setTimeout(() => {
+  var pages = getCurrentPages();
   var currentWebview = pages[pages.length - 1].$getAppWebview();
   var wv = currentWebview.children()[0];
   wv.evalJS(`receiveData(${JSON.stringify({ dataArray: dataArray, dataType: dataType })})`);

+ 1 - 1
src/pages/business/fireIot/facilitiesManage/mapFacilitiesView.vue

@@ -21,7 +21,6 @@ import { baseFacilityType, baseGgpFacilityList } from "@/api/business/fireIot/fa
 const commonStore = commonStores(); //全局公共Store
 
 const { proxy } = getCurrentInstance();
-const pages = getCurrentPages();
 
 const dataArray = ref();
 const typeCode = ref("");
@@ -92,6 +91,7 @@ function analysisData(data) {
  */
 function handleChildren(data) {
   // #ifdef APP-PLUS
+  var pages = getCurrentPages();
   var currentWebview = pages[pages.length - 1].$getAppWebview();
   var wv = currentWebview.children()[0];
   wv.evalJS(`receiveData(${JSON.stringify(data)})`);

+ 13 - 2
src/pages/business/zhaf/xunJian/plan/index.vue

@@ -11,7 +11,18 @@
   >
     <template #default>
       <!-- 日历组件 -->
-      <oa-calendar class="uni-calendar--hook" :selected="info.selected" :showMonth="false" @change="change" @monthSwitch="monthSwitch" :currentDate="currentDateList" />
+      <oa-calendar class="uni-calendar--hook" :selected="info.selected" :showMonth="false" @change="change" @monthSwitch="monthSwitch">
+        <template #headerRight>
+          <view class="item">
+            <span class="item_title">巡检</span>
+            <span class="item_cont" style="color: #00cdac">{{ JSON.stringify(currentDateList) === "{}" ? 0 : currentDateList.patrolledCount }}</span>
+          </view>
+          <view class="item">
+            <span class="item_title">漏检</span>
+            <span class="item_cont" style="color: #f07d28">{{ JSON.stringify(currentDateList) === "{}" ? 0 : currentDateList.undetectedCount }}</span>
+          </view>
+        </template>
+      </oa-calendar>
 
       <!-- 分段器组件 -->
       <view class="app-subsection">
@@ -321,7 +332,7 @@ function activitiesApi() {
  * @统计
  * @api接口请求
  */
-const currentDate = ref(proxy.$time.getDate().year + "-" + proxy.$time.getDate().month + "-" + proxy.$time.getDate().dates); //统计时间数据存储
+const currentDate = ref(proxy.$dayjs().format("YYYY-MM-DD")); //统计时间数据存储
 const currentDatevalue = ref(new Date());
 const currentDateList = ref({}); //统计list数据存储
 function currentApi() {

+ 1 - 1
src/pages/business/zhaf/xunJian/xunJian.vue

@@ -53,7 +53,7 @@ const xunJianStore = xunJianStores(); //全局变量值Store
 /*----------------------------------变量声明-----------------------------------*/
 const inspectList = proxy.$constData.xunJianList; //九宫格json数据
 
-const currentDate = proxy.$time.getDate().year + "-" + proxy.$time.getDate().month + "-" + proxy.$time.getDate().dates;
+const currentDate = proxy.$dayjs().format("YYYY-MM-DD");
 const currentDateList = ref([]);
 
 function navItemClick(url, id) {

+ 61 - 55
src/pages/common/face/index.vue

@@ -1,5 +1,7 @@
 <template>
-  <web-view ref="faceView" id="faceView" class="faceView" src="/static/face/index.html" bindmessage="receiveMessage" :webview-styles="webviewStyles" @message="onMessage"></web-view>
+  <web-view v-show="!modal.show" ref="faceView" id="faceView" class="faceView" src="/static/face/index.html" bindmessage="receiveMessage" :webview-styles="webviewStyles" @message="onMessage">
+  </web-view>
+
   <u-modal
     :show="modal.show"
     title="配置服务器"
@@ -97,28 +99,34 @@ const state = reactive({
     meetingId: undefined,
     meetingName: undefined,
   },
+  inter: {
+    interMeeting: null,
+  },
 });
-const { webviewStyles, meetingRoomList, modal, picker, form } = toRefs(state);
+const { webviewStyles, meetingRoomList, modal, picker, form, inter } = toRefs(state);
 
 // 初始化
 function init() {
+  uni.chooseImage({
+    sourceType: ["camera"],
+    success(res) {
+      console.log(res);
+    },
+  });
+
   var storage = uni.getStorageSync("storage_face");
   if (storage) {
     state.form.linkUrl = storage.linkUrl.indexOf(":") != -1 ? storage.linkUrl.split(":")[0] : storage.linkUrl;
     state.form.port = storage.port ? storage.port : "";
     state.form.meetingId = storage.meetingId || undefined;
     state.form.meetingName = storage.meetingName || undefined;
-    meetingInit();
   }
-}
 
-/**
- * @会议信息初始化
- * @method domain 服务器地址
- */
-function meetingInit() {
   getMeetingRoomList();
   getMeetingRoomReservationList();
+  inter.interMeeting = setInterval(() => {
+    getMeetingRoomReservationList();
+  }, 1000 * 5);
 }
 
 /**
@@ -151,6 +159,31 @@ function getMeetingRoomList() {
  * @会议室详情列表
  */
 function getMeetingRoomReservationList() {
+  for (let i = 0; i <= 23.5; i += 0.5) {
+    var time = "";
+    if (i % 1 === 0.5) {
+      if (i < 10) {
+        time = "0" + (i - 0.5) + ":30";
+      } else {
+        time = i - 0.5 + ":30";
+      }
+    } else {
+      if (i < 10) {
+        time = "0" + i + ":00";
+      } else {
+        time = i + ":00";
+      }
+    }
+
+    state.meetingTimeList.push({
+      startTime: time,
+      endTime: time,
+      isEnd: 0,
+      isHave: 0,
+      isReservation: 0,
+    });
+  }
+
   var domain = "";
   if (state.form.linkUrl) {
     domain = state.form.linkUrl;
@@ -159,10 +192,6 @@ function getMeetingRoomReservationList() {
     }
   }
 
-  if (!state.form.meetingId) {
-    return;
-  }
-
   meetingApi()
     .GetMeetingRoomReservationList({
       domain: domain,
@@ -170,31 +199,6 @@ function getMeetingRoomReservationList() {
       date: proxy.$dayjs().format("YYYY-MM-DD") + " 00:00:00",
     })
     .then((requset) => {
-      for (let i = 0; i <= 23.5; i += 0.5) {
-        var time = "";
-        if (i % 1 === 0.5) {
-          if (i < 10) {
-            time = "0" + (i - 0.5) + ":30";
-          } else {
-            time = i - 0.5 + ":30";
-          }
-        } else {
-          if (i < 10) {
-            time = "0" + i + ":00";
-          } else {
-            time = i + ":00";
-          }
-        }
-
-        state.meetingTimeList.push({
-          startTime: time,
-          endTime: time,
-          isEnd: 0,
-          isHave: 0,
-          isReservation: 0,
-        });
-      }
-
       if (requset.data.length > 0) {
         state.meetingReservaList.dataAll = requset.data[0];
         state.meetingReservaList.dataAll.dmMeetingList.forEach((e, index) => {
@@ -211,20 +215,16 @@ function getMeetingRoomReservationList() {
         });
 
         state.meetingReservaList.timeList = showTimeSegments(state.meetingTimeList);
-
-        setTimeout(() => {
-          handleChildren({
-            funcName: "初始化",
-            data: JSON.stringify(state.meetingReservaList),
-          });
-        }, 0);
+        handleChildren({
+          funcName: "初始化数据",
+          data: JSON.stringify(state.meetingReservaList),
+        });
       } else {
-        setTimeout(() => {
-          handleChildren({
-            funcName: "初始化",
-            data: JSON.stringify(state.meetingReservaList),
-          });
-        }, 0);
+        state.meetingReservaList.timeList = state.meetingTimeList;
+        handleChildren({
+          funcName: "初始化数据",
+          data: JSON.stringify(state.meetingReservaList),
+        });
       }
     });
 }
@@ -234,8 +234,9 @@ function showTimeSegments(times) {
   const timesXleList = JSON.parse(JSON.stringify(times));
 
   for (var i = 0; i < timesXleList.length; i++) {
+    const timeValue = new Date(`${proxy.$dayjs().format("YYYY-MM-DD")}T${timesXleList[i].startTime}`);
+
     state.meetingReservaList.dataAll.meetingRoomUsage.forEach((item) => {
-      const timeValue = new Date(`${proxy.$dayjs().format("YYYY-MM-DD")}T${timesXleList[i].startTime}`);
       const timeList = proxy.$time.timeRestructuring(item);
       const startValue = new Date(`${proxy.$dayjs().format("YYYY-MM-DD")}T${timeList.startTime}`);
       const endValue = new Date(`${proxy.$dayjs().format("YYYY-MM-DD")}T${timeList.endTime}`);
@@ -358,7 +359,6 @@ function handlePicker(value, index, ind) {
     state.picker.list = [state.meetingRoomList];
     state.picker.defaultIndex = 0;
   }
-
   state.picker.show = true;
 }
 
@@ -370,7 +370,6 @@ function pickerConfirm(e) {
     state.form.meetingId = e.value[0].value;
     state.form.meetingName = e.value[0].name;
   }
-
   state.picker.show = false;
 }
 
@@ -379,6 +378,9 @@ function pickerConfirm(e) {
  */
 function modalCancel() {
   state.modal.show = false;
+  //#ifdef APP-PLUS
+  proxy.$keyListen.quitApp();
+  //#endif
 }
 
 /**
@@ -400,6 +402,7 @@ function analysisData(event) {
  */
 function handleChildren(data) {
   // #ifdef APP-PLUS
+  var pages = getCurrentPages();
   var currentWebview = pages[pages.length - 1].$getAppWebview();
   var wv = currentWebview.children()[0];
   wv.evalJS(`receiveData(${JSON.stringify(data)})`);
@@ -427,6 +430,10 @@ onLoad((options) => {
   init();
 });
 
+onUnload(() => {
+  clearInterval(inter.interMeeting); //销毁之前定时器
+});
+
 watch(
   () => [state.form.linkUrl, state.form.port],
   (val) => {
@@ -439,7 +446,6 @@ watch(
     if (!/^[a-zA-Z0-9][a-zA-Z0-9-]{1,61}(?:\.[a-zA-Z0-9]{2,})+$/.test(state.form.linkUrl)) {
       return;
     }
-
     getMeetingRoomList();
   }
 );

+ 1 - 1
src/pages/index.vue

@@ -33,7 +33,7 @@
         <!-- 右侧弹窗 -->
         <u-transition :show="dialogFlag" :duration="200" mode="fade">
           <view class="transition" @click="rightButtonClick()">
-            <view class="transition-section" :style="{ top: '44px' + proxy.$settingStore.StatusBarHeight }">
+            <view class="transition-section" :style="{ top: `calc(44px + ${proxy.$settingStore.StatusBarHeight})` }">
               <view class="transition-section-content" @click="scanCode()">
                 <text class="transition-section-content-icon iconfont oaIcon-saoyisao"></text>
                 <view class="transition-section-content-text"> 扫一扫 </view>

+ 205 - 191
src/static/face/index.html

@@ -7,8 +7,9 @@
     <script type="text/javascript" src="./js/tracking-min.js"></script>
     <script type="text/javascript" src="./js/face-min.js"></script>
     <script type="text/javascript" src="./js/jquery-2.2.1.min.js"></script>
+    <!-- VUE3 的 SDK -->
+    <script type="text/javascript" src="./js/vue.global.prod.js"></script>
     <!-- uni 的 SDK -->
-    <!-- 需要把 uni.webview.1.5.4.js 下载到自己的服务器 -->
     <script type="text/javascript" src="./js/uni.webview.1.5.4.js"></script>
     <style>
         html,
@@ -173,210 +174,223 @@
 
 <body>
     <div id="face-container" class="face-container home-card-two">
-        <div id="home-card-left" class="home-card-left"></div>
-        <div id="home-card-right" class="home-card-right"></div>
-        <div id="home-card-bottom" class="home-card-bottom"></div>
-    </div>
-
-    <script type="text/javascript">
-        var state = {
-            dataAll: {},
-            thisVenueData: [],
-            thisVenueTime: {},
-            nextSceneData: [],
-            nextSceneTime: {},
-            timeList: []
-        }
-        var timeOutEvent = 0;
-
-
-        // 初始化
-        function initData() {
-            $(`#home-card-left`).append(`
-                <image id="home-card-left-image" class="home-card-left-image" src="./img/logo.png" width="125px" height="60px" mode="aspectFill"></image>
-                <div class="home-card-left-header">${state.dataAll?.roomName || "请配置会议室"}</div>
-                <div class="home-card-left-content" style="margin-bottom: 20px;">
-                    <div>本场会议</div>
-                    <div>${state.thisVenueData[0]?.meetingName || "空闲中"}</div>
-                    <div>${state.thisVenueTime.startTime || "00:00"} — ${state.thisVenueTime.endTime || "00:00"}</div>
+        <div id="home-card-left" class="home-card-left">
+            <image id="home-card-left-image" class="home-card-left-image" src="./img/logo.png" width="125px"
+                height="60px" mode="aspectFill"></image>
+            <div class="home-card-left-header">{{state.dataAll?.roomName || "请配置会议室"}}</div>
+            <div class="home-card-left-content" style="margin-bottom: 20px;">
+                <div>本场会议</div>
+                <div>{{state.thisVenueData[0]?.meetingName || "空闲中"}}</div>
+                <div>{{state.thisVenueTime.startTime || "00:00"}} — {{state.thisVenueTime.endTime || "00:00"}}
                 </div>
+            </div>
 
-                <div class="home-card-left-content">
-                    <div>下场会议</div>
-                    <div>${state.nextSceneData[0]?.meetingName || "空闲中"}</div>
-                    <div>${state.nextSceneTime.startTime || "00:00"} — ${state.nextSceneTime.endTime || "00:00"}</div>
+            <div class="home-card-left-content">
+                <div>下场会议</div>
+                <div>{{state.nextSceneData[0]?.meetingName || "空闲中"}}</div>
+                <div>{{state.nextSceneTime.startTime || "00:00"}} — {{state.nextSceneTime.endTime || "00:00"}}
                 </div>
-            `)
-
-            $(`#home-card-right`).append(`
-                <div class="home-card-right-header">
-                    <div class="home-card-right-header-center">
-                        <span style="padding: 0 5px 0 0; border-right: 1px #fff solid">温度:80℃</span>
-                        <span style="padding: 0px 5px; border-right: 1px #fff solid">湿度:80%</span>
-                        <span style="padding: 0px 5px; border-right: 1px #fff solid">PM2.5:10μg/m3</span>
-                        <span style="padding: 0 0 0 5px">甲醛:0ppm</span>
-                    </div>
-                    <div class="home-card-right-header-title">${state.thisVenueData[0] ? "&nbsp;&nbsp;会议进行中" : "&nbsp;"}</div>
+            </div>
+        </div>
+        <div id="home-card-right" class="home-card-right">
+            <div class="home-card-right-header">
+                <div class="home-card-right-header-center">
+                    <span style="padding: 0 5px 0 0; border-right: 1px #fff solid">温度:80℃</span>
+                    <span style="padding: 0px 5px; border-right: 1px #fff solid">湿度:80%</span>
+                    <span style="padding: 0px 5px; border-right: 1px #fff solid">PM2.5:10μg/m3</span>
+                    <span style="padding: 0 0 0 5px">甲醛:0ppm</span>
                 </div>
-                <div class="home-card-right-content">
-                    <div style="font-size: 20px; margin-bottom: 15px;">${state.thisVenueData[0]?.meetingName || "空闲中"}</div>
-                    <div style="font-size: 18px; margin-bottom: 15px;">
-                        ${state.thisVenueTime.startTime || "00:00"} — ${state.thisVenueTime.endTime || "00:00"}
-                    </div>
-                    <div style="font-size: 14px; margin-bottom: 15px;">${state.msg || "&nbsp;"}</div>
+                <div class="home-card-right-header-title">{{state.thisVenueData[0] ? "&nbsp;&nbsp;会议进行中" :
+                    "&nbsp;"}}</div>
+            </div>
+            <div class="home-card-right-content">
+                <div style="font-size: 20px; margin-bottom: 15px;">{{state.thisVenueData[0]?.meetingName || "空闲中"}}
                 </div>
-                <div class="home-card-right-footer" id="home-card-right-footer">
-                    <video id="video" width="320" height="240" preload autoplay loop muted></video>
-                    <canvas id="canvas" width="320" height="240"></canvas>
+                <div style="font-size: 18px; margin-bottom: 15px;">
+                    {{state.thisVenueTime.startTime || "00:00"}} — {{state.thisVenueTime.endTime || "00:00"}}
                 </div>
-            `)
-
-            var html = ``
-            state.timeList.forEach((item, timeIndex) => {
-                html += `
-                    <div id="timeScorll${timeIndex}" style="background-color: ${item.isEnd === 1 ? "#909399" : item.isHave === 1 ? "#fa3534" : item.isReservation === 1 ? "#ff9900" : "#409eff"}">
-                      ${item.isEnd != 0 || item.isHave != 0 || item.isReservation != 0 ? item.startTime + " —— " + item.endTime : item.startTime}  
-                    </div >
-                `
-            });
-            $(`#home-card-bottom`).append(html)
-
-            var video = document.getElementById("video");//视频dom
-            video.style.transform = 'scaleX(-1)';//视频翻转(1.水平翻转-scaleX(-1) 2.垂直翻转-scaleY(-1))
-            var canvas = document.getElementById('canvas');//画布dom
-            canvas.style.transform = 'scaleX(-1)';//画布翻转(1.水平翻转-scaleX(-1) 2.垂直翻转-scaleY(-1))
-            var context = canvas.getContext('2d');
-            var time = 5000;
-            var tracker = new tracking.ObjectTracker('face');
-            tracker.setInitialScale(4); //设置识别的放大比例
-            tracker.setStepSize(2);//设置步长
-            tracker.setEdgesDensity(0.1);//边缘密度
-            //启动摄像头,并且识别视频内容
-            var trackerTask = tracking.track('#video', tracker, {
-                camera: true
-            });
-
-            var flag = true;
-            tracker.on('track', function (event) {
-                if (event.data.length === 0) {
-                    // console.log('未检测到人脸')
-                    context.clearRect(0, 0, canvas.width, canvas.height);
-                } else if (event.data.length > 1) {
-                    // console.log('检测到多张人脸')
-                } else {
-                    context.clearRect(0, 0, canvas.width, canvas.height);
-                    event.data.forEach(function (rect) {
-                        context.strokeStyle = '#409eff';
-                        context.strokeRect(rect.x, rect.y, rect.width, rect.height);
-                        context.fillStyle = "#409eff";
-                        context.lineWidth = 1.5;
+                <div style="font-size: 14px; margin-bottom: 15px;">{{state.msg || "&nbsp;"}}</div>
+            </div>
+            <div class="home-card-right-footer" id="home-card-right-footer">
+                <video id="video" width="320" height="240" preload autoplay loop muted></video>
+                <canvas id="canvas" width="320" height="240"></canvas>
+            </div>
+
+        </div>
+        <div id="home-card-bottom" class="home-card-bottom"></div>
+    </div>
+    <script>
+        // 创建Vue实例
+        Vue.createApp({
+            components: {},
+            emits: [],
+            props: {},
+            data() {
+                return {
+                    state: {
+                        dataAll: {},
+                        thisVenueData: [],
+                        thisVenueTime: {},
+                        nextSceneData: [],
+                        nextSceneTime: {},
+                        timeList: []
+                    },
+                    timeOutEvent: 0
+                };
+            },
+            computed: {},
+            methods: {
+                // 初始化数据
+                initData() {
+                    var that = this
+
+                    var html = ``
+                    this.state.timeList.forEach((item, timeIndex) => {
+                        html += `
+                            <div id="timeScorll${timeIndex}" style="background-color: ${item.isEnd === 1 ? "#909399" : item.isHave === 1 ? "#fa3534" : item.isReservation === 1 ? "#ff9900" : "#409eff"}">
+                            ${item.isEnd != 0 || item.isHave != 0 || item.isReservation != 0 ? item.startTime + " —— " + item.endTime : item.startTime}  
+                            </div>
+                        `
                     });
-                    if (flag) {
-                        console.log("拍照");
-                        context.drawImage(video, 0, 0, video.width, video.height);
-                        saveAsLocalImage();
-                        context.clearRect(0, 0, canvas.width, canvas.height);
-                        flag = false;
-                        setTimeout(function () {
-                            flag = true;
-                        }, time);
-                    } else {
-                        //console.log("冷却中");
-                    }
-                }
-            });
+                    $(`#home-card-bottom`).append(html)
 
-            $("#home-card-left-image").on({
-                touchstart: function (e) {
-                    timeOutEvent = setTimeout("longPress()", 500);
-                    e.preventDefault();
-                },
-                touchmove: function () {
-                    clearTimeout(timeOutEvent);
-                    timeOutEvent = 0;
                 },
-                touchend: function () {
-                    clearTimeout(timeOutEvent);
-                    if (timeOutEvent != 0) {
-                        console.log("你这是点击,不是长按");
-                    }
-                    return false;
-                }
-            })
-        }
+                // 初始化摄像头
+                initVido() {
+                    var that = this;
+
+                    var video = document.getElementById("video");//视频dom
+                    video.style.transform = 'scaleX(-1)';//视频翻转(1.水平翻转-scaleX(-1) 2.垂直翻转-scaleY(-1))
+                    var canvas = document.getElementById('canvas');//画布dom
+                    canvas.style.transform = 'scaleX(-1)';//画布翻转(1.水平翻转-scaleX(-1) 2.垂直翻转-scaleY(-1))
+                    var context = canvas.getContext('2d');
+                    var time = 5000;
+                    var tracker = new tracking.ObjectTracker('face');
+                    tracker.setInitialScale(4); //设置识别的放大比例
+                    tracker.setStepSize(2);//设置步长
+                    tracker.setEdgesDensity(0.1);//边缘密度
+                    //启动摄像头,并且识别视频内容
+                    var trackerTask = tracking.track('#video', tracker, {
+                        camera: true
+                    });
 
-        // 长按事件
-        function longPress() {
-            timeOutEvent = 0
-            parentMessage('打开配置')
-        }
+                    var flag = true;
+                    tracker.on('track', function (event) {
+                        if (event.data.length === 0) {
+                            // console.log('未检测到人脸')
+                            context.clearRect(0, 0, canvas.width, canvas.height);
+                        } else if (event.data.length > 1) {
+                            // console.log('检测到多张人脸')
+                        } else {
+                            context.clearRect(0, 0, canvas.width, canvas.height);
+                            event.data.forEach(function (rect) {
+                                context.strokeStyle = '#409eff';
+                                context.strokeRect(rect.x, rect.y, rect.width, rect.height);
+                                context.fillStyle = "#409eff";
+                                context.lineWidth = 1.5;
+                            });
+                            if (flag) {
+                                console.log("拍照");
+                                context.drawImage(video, 0, 0, video.width, video.height);
+                                that.saveAsLocalImage();//调用获取图片bold
+                                context.clearRect(0, 0, canvas.width, canvas.height);
+                                flag = false;
+                                setTimeout(function () {
+                                    flag = true;
+                                }, time);
+                            } else {
+                                //console.log("冷却中");
+                            }
+                        }
+                    });
 
-        /**
-         * 解析数据
-         */
-        function analysisData(event) {
-            console.log(event.funcName)
-            if ("funcName" in event) {
-                if (event.funcName == "初始化") {
-                    $(`#home-card-left`).empty();//删除dom下的所有子元素
-                    $("#home-card-right").empty();//删除dom下的所有子元素
-                    $(`#home-card-bottom`).empty();//删除dom下的所有子元素
-
-                    state.dataAll = JSON.parse(event.data).dataAll
-                    state.thisVenueData = JSON.parse(event.data).thisVenueData
-                    state.thisVenueTime = JSON.parse(event.data).thisVenueTime
-                    state.nextSceneData = JSON.parse(event.data).nextSceneData
-                    state.nextSceneTime = JSON.parse(event.data).nextSceneTime
-                    state.timeList = JSON.parse(event.data).timeList
-
-                    initData();
-                } else if (event.funcName == "撒点") {
+                    $("#home-card-left-image").on({
+                        touchstart: function (e) {
+                            that.timeOutEvent = setTimeout(() => {
+                                that.longPress()
+                            }, 2000);
+                            e.preventDefault();
+                        },
+                        touchmove: function () {
+                            clearTimeout(that.timeOutEvent);
+                            that.timeOutEvent = 0;
+                        },
+                        touchend: function () {
+                            clearTimeout(that.timeOutEvent);
+                            if (that.timeOutEvent != 0) {
+                                console.log("你这是点击,不是长按");
+                            }
+                            return false;
+                        }
+                    })
+                },
+                // 向父页面推送数据
+                parentMessage(type, data) {
+                    var message = {
+                        funcName: type,
+                        data: data,
+                    };
+
+                    //APP-PLUS
+                    uni.postMessage({
+                        data: message
+                    });
 
+                    //H5
+                    if (window.parent) {
+                        window.parent.postMessage(message, '*');
+                    }
+                },
+                // 获取图片bold
+                saveAsLocalImage() {
+                    var myCanvas = document.getElementById("canvas");
+                    var image = myCanvas.toDataURL("image/png").replace("image/png", "image/octet-stream");
+                    this.parentMessage('人脸识别', { imageBase: image })
+                },
+                // 解析数据
+                analysisData(event) {
+                    console.log(event.funcName)
+                    if ("funcName" in event) {
+                        if (event.funcName == "初始化数据") {
+                            $(`#home-card-bottom`).empty();//删除dom下的所有子元素
+                            this.state.dataAll = JSON.parse(event.data).dataAll
+                            this.state.thisVenueData = JSON.parse(event.data).thisVenueData
+                            this.state.thisVenueTime = JSON.parse(event.data).thisVenueTime
+                            this.state.nextSceneData = JSON.parse(event.data).nextSceneData
+                            this.state.nextSceneTime = JSON.parse(event.data).nextSceneTime
+                            this.state.timeList = JSON.parse(event.data).timeList
+                            this.initData();
+                        } else if (event.funcName == "撒点") {
+
+                        }
+                    }
+                },
+                // 长按事件
+                longPress() {
+                    this.parentMessage('打开配置')
+                    this.timeOutEvent = 0
                 }
-            }
-        }
-
-        // 获取图片bold
-        function saveAsLocalImage() {
-            var myCanvas = document.getElementById("canvas");
-            var image = myCanvas.toDataURL("image/png").replace("image/png", "image/octet-stream");
-            parentMessage('人脸识别', { imageBase: image })
-        }
-
-        // 向父页面发送数据
-        function parentMessage(type, data) {
-            var message = {
-                funcName: type,
-                data: data,
-            };
-
-            //APP-PLUS
-            uni.postMessage({
-                data: message
-            });
-
-            //H5
-            if (window.parent) {
-                window.parent.postMessage(message, '*');
-            }
-        }
-
-        /**
-         * APP-PLUS || H5
-         * 接收父页面传过来的值
-         */
-        window.receiveData = function (msg) {
-            analysisData(msg)
-        }
-        window.addEventListener("message", function (event) {
-            analysisData(event.data)
-        });
-
-        window.onload = function () {
-            initData();
-        };
+            },
+            created() {
+                var that = this
+                // APP-PLUS || H5(接收父页面传过来的值)
+                window.receiveData = (msg) => {
+                    that.analysisData(msg)
+                }
+                window.addEventListener("message", function (event) {
+                    that.analysisData(event.data)
+                });
+            },
+            mounted() {
+                this.initVido();//调用初始化摄像头
+            },
+            beforeDestroy() {
+                // 移除window方法
+                window.receiveData = null;
+            },
+            watch: {},
+        }).mount('#face-container');
     </script>
-
 </body>
 
 </html>

文件差異過大導致無法顯示
+ 5 - 0
src/static/face/js/vue.global.prod.js


+ 1 - 1
src/static/scss/colorui.css

@@ -35,7 +35,7 @@ image {
 }
 
 .radius {
-  border-radius: 6upx;
+  border-radius: 10upx;
 }
 
 /* ==================

+ 32 - 0
src/static/scss/index.scss

@@ -46,6 +46,38 @@
 
 /* 外边距、内边距全局样式
 ------------------------------- */
+@each $val in auto {
+    .m-#{$val} {
+        margin: $val;
+    }
+
+    .mt-#{$val} {
+        margin-top: $val;
+    }
+
+    .mr-#{$val} {
+        margin-right: $val;
+    }
+
+    .mb-#{$val} {
+        margin-bottom: $val;
+    }
+
+    .ml-#{$val} {
+        margin-left: $val;
+    }
+
+    .mlr-#{$val} {
+        margin-left: $val;
+        margin-right: $val;
+    }
+
+    .mtb-#{$val} {
+        margin-top: $val;
+        margin-bottom: $val;
+    }
+}
+
 @for $i from 0 through 100 {
 
     // margin

+ 3 - 0
src/store/modules/system.js

@@ -9,6 +9,9 @@ const systemStores = defineStore(`storage-system`, {
         homeList: storageSystem.get("homeList"),
         mallList: {
             activeUserList: []
+        },
+        meetingList: {
+            form: {}
         }
     }),
     unistorage: true,

+ 7 - 1
src/store/modules/user.js

@@ -20,6 +20,9 @@ const useStores = defineStore("useStores", {
     name: storage.get("name"),//用户名称
     nickName: storage.get("nickName"),//用户昵称
     phonenumber: storage.get("phonenumber"),//用户手机号
+    deptId: storage.get("deptId"),//部门ID
+    email: storage.get("email"),//邮箱
+    sex: storage.get("sex"),//性别
     avatar: storage.get("avatar"),//用户头像
     roles: storage.get("roles"),//用户权限
     permissions: storage.get("permissions"),
@@ -99,8 +102,11 @@ const useStores = defineStore("useStores", {
               userId: data.user.userId,//用户ID
               name: data.user.userName,//用户名称
               nickName: data.user.nickName,//用户昵称
-              phonenumber: data.user.phonenumber ? data.user.phonenumber.substr(0, 3) + "******" + data.user.phonenumber.substr(9) : "",//手机号码
+              phonenumber: data.user.phonenumber,//手机号码
               avatar: data.user.avatar,//头像
+              deptId: data.user.deptId,//部门ID
+              email: data.user.email,//邮箱
+              sex: data.user.sex,//性别
             })
 
             resolve(res);

+ 251 - 0
src/uni_modules/uview-plus/changelog.md

@@ -1,3 +1,254 @@
+## 3.3.34(2024-09-23)
+feat: 支持toast设置duration值为-1时不自动关闭
+
+## 3.3.33(2024-09-18)
+fix: 修复test.date('008')等验证结果不准确
+
+## 3.3.32(2024-09-09)
+fix: u-keyboard名称冲突warning
+
+## 3.3.31(2024-08-31)
+feat: qrcode初步支持nvue
+
+## 3.3.30(2024-08-30)
+fix: slider兼容step为字符串类型
+
+## 3.3.29(2024-08-30)
+fix: 修复tabs组件current参数为字符串处理逻辑
+
+## 3.3.28(2024-08-26)
+fix: list组件滑动偏移量不一样取绝对值导致iOS下拉偏移量计算错误
+
+## 3.3.27(2024-08-22)
+fix: 修复up-datetime-picker组件toolbarRightSlot定义缺失
+
+fix: 修复FormItem的rules更新错误的问题
+
+## 3.3.26(2024-08-22)
+fix: 批量注册全局组件优化
+
+## 3.3.25(2024-08-21)
+fix: 修复slider在app-vue下样式问题
+
+## 3.3.24(2024-08-19)
+fix: 修复时间选择器hasInput模式小程序不生效
+
+feat: 支持H5导入所有组件
+
+## 3.3.23(2024-08-17)
+feat: swipe-action增加closeAll方法
+
+fix: 兼容tabs在某些场景下index小于0时自动设置为0
+
+add: 通用mixin新增navTo页面跳转方法
+
+## 3.3.21(2024-08-15)
+improvement: 优化二维码组件loading及支持预览与长按事件 #351
+
+fix: 修复swipe-action自动关闭其它功能及组件卸载自动关闭
+
+## 3.3.20(2024-08-15)
+refactor: props默认值文件移至组件文件夹内便于查找
+## 3.3.19(2024-08-14)
+fix: 修复2被rpx兼容处理只在数字值生效
+
+add: 增加swiper自定义插槽示例
+
+## 3.3.18(2024-08-13)
+feat: 新增支持datetime-picker工具栏插槽及picker插槽支持修复
+## 3.3.17(2024-08-12)
+feat: swiper组件增加默认slot便于自定义
+
+feat: grid新增间隔参数
+
+feat: picker新增toolbar-right和toolbar-bottom插槽
+
+## 3.3.16(2024-08-12)
+fix: 解决swiper中title换行后多余的内容未被遮挡问题
+
+fix: 修复迷你导航适配异形屏
+
+## 3.3.15(2024-08-09)
+fix: 修复默认单位设置为rpx时一些组件高度间距异常
+
+fix: 修复日历在rpx单位下布局异常
+
+feat: code-input支持App端展示输入光标
+
+## 3.3.14(2024-08-09)
+add: 增加box组件
+
+add: 增加card卡片组件
+
+
+## 3.3.13(2024-08-08)
+feat: input支持调用原生组件的focus和blur方法
+
+improvement: grid-item条件编译优化
+
+add: 新增迷你导航组件
+
+## 3.3.12(2024-08-06)
+improvement: $u挂载时机调整便于打包分离chunk
+
+fix: steps新增itemStyle属性名称冲突
+
+## 3.3.11(2024-08-05)
+feat: 新增支持upload组件的deletable/maxCount/accept变更监听 #333
+
+feat: 新增支持tabs在swiper中使用
+
+feat: 新增FormItem支持独立设置验证规则rules
+
+fix: 修复index-list未设置$slots.header时索引高亮失效
+
+## 3.3.10(2024-08-02)
+fix: 修复index-list偶发的滑动最后一个索引报错top不存在
+
+fix: 修复gird在QQ、抖音小程序下布局
+
+feat: 优化step支持自定义样式prop
+
+feat: action-sheet组件支持v-model:show双向绑定
+
+fix: 小程序下steps和grid都统一采用grid布局
+
+fix: 修复支付宝小程序下input类型为数字时双向绑定失效
+
+feat : form 表单 validate 校验不通过后 error增加字段prop信息  #304
+
+fix: form组件异步校异常验问题 #393
+
+## 3.3.9(2024-08-01)
+fix: 优化获取nvue元素
+
+feat: modal新增contentTextAlign设置文案对齐方式
+
+fix: 修复NVUE下tabbar文字不显示  #458
+
+feat: loading-page增加zIndex属性
+
+fix: 相册在宽度较小时换行问题
+
+feat: album相册增加自适应自动换行模式
+
+feat: album相册增加图片尺寸单位prop
+
+fix: 修复calendar日历月份居中
+
+## 3.3.8(2024-07-31)
+feat: slider支持进度条任意位置触发按钮拖动
+
+fix: 修复app-vue下modal标题不居中
+
+fix: #459 TS setConfig 声明异常
+
+feat: tabs组件增加longPress长按事件
+
+feat: 新增showRight属性控制collapse右侧图标显隐
+
+fix: 优化nvue下css警告
+
+## 3.3.7(2024-07-29)
+feat: 支持IndexList组件支持在弹窗等场景下使用及联动优化
+
+feat: popup组件支持v-model:show双向绑定
+
+feat: 优化tabs的current双向绑定
+
+fix: checkbox独立使用时checked赋初始值可以,但是手动切换时值没有做双向绑定! #455
+
+feat: slider组件支持区间双滑块
+
+fix: toast 支持自定义图标?可传入了决对路径的 icon也没有用 #409
+
+feat: form-item校验失败时 增加class方便自定义显示错误的展示方式 #394
+
+fix: up-cell的required配置不生效 #395
+
+fix: 横向滚动组件,微信小程序编译后会有警告 #415
+
+fix: u-picker内部对默认值defaultIndex的监听 #425
+
+feat: toast 组件支持遮掩层穿透  #417
+
+fix: 兼容vue的slot编译bug #423
+
+fix: upload 微信小程序 点击预览视频报错 #424
+
+fix: u-number-box 组件修改【integer, decimalLength, min, max 】props时没有触发绑定值更新 #429
+
+feat: Tabs组件能否支持自定义插槽 #439
+
+feat: ActionSheet 可以配置最大高度吗, 我当做select使用了。 #445
+
+fix: cursor-pointer优化
+
+feat: 新版slider组件兼容NVUE改造
+
+feat: 新增slider组件手动实现以支持样式自定义
+
+perf:补充TS声明提示信息
+
+修复:ActionSheet 操作菜单cancelText属性为空DOM节点还存在并且可以点击问题
+
+fix: 去除预留的beforeDestroy兼容容易在某些sdk下不识别条件编译
+
+## 3.3.6(2024-07-23)
+feat: u-album组件添加radius,shape参数,定义参考当前u-image参数
+
+fix: 修复了calendar组件title和日期title未垂直居中的问题
+
+fix: update:modelValue缺失emit定义
+
+## 3.3.5(2024-07-10)
+picker组件支持hasInput模式
+
+## 3.3.4(2024-07-07)
+fix: input组件双向绑定问题 #419
+
+lazy-load完善emit
+
+优化通用小程序分享
+
+## 3.3.2(2024-06-27)
+fix: 在Nvue环境中编译,出现大量警告 #406
+## 3.3.1(2024-06-27)
+u-button组件报错,找不到button mixins #407
+## 3.3.0(2024-06-27)
+feat: checkbox支持label设置slot
+
+feat: modal增加customClass
+
+feat: navbar、popup、tabs、text支持customClass
+
+fix: cell组建缺少flex布局
+
+fix: 修复微信小程序真机调试时快速输入出现文本回退问题
+
+feat: tag增加默认slot
+
+公共mixin改造为按需导入语法
+
+refactor: 组件props混入mixin改造为按需导入语法
+
+fix: u-tabbar 安卓手机点击按钮变蓝问题 #396
+
+feat: upload组建增加extension属性
+
+fix: upload组件参数mode添加left
+
+fix: 修复阴影在非nvue时白色背景色不显示
+
+## 3.2.24(2024-06-11)
+fix: 修复时间选择器confirm事件触发时机导致2次才会触发v-model更新
+## 3.2.23(2024-05-30)
+fix: #378 H5 u-input 在表单中初始值为空也会触发一次 formValidate(this,"change")事件导致进入页面直接校验了一次
+
+fix: #373 搜索组件up-search的@clear事件无效
+
+fix: #372 ActionSheet 组件的取消按钮触发区域太小
+
 ## 3.2.22(2024-05-13)
 上传组件支持微信小程序预览视频
 

+ 3 - 3
src/uni_modules/uview-plus/components/u--form/u--form.vue

@@ -21,9 +21,9 @@
 	 * 所以在nvue下,取名为u--form,内部其实还是u-form.vue,只不过做一层中转
 	 */
 	import uvForm from '../u-form/u-form.vue';
-	import props from '../u-form/props.js';
-	import mpMixin from '../../libs/mixin/mpMixin';
-	import mixin from '../../libs/mixin/mixin';
+	import { props } from '../u-form/props.js';
+	import { mpMixin } from '../../libs/mixin/mpMixin';
+	import { mixin } from '../../libs/mixin/mixin';
 	export default {
 		// #ifdef MP-WEIXIN
 		name: 'u-form',

+ 3 - 3
src/uni_modules/uview-plus/components/u--image/u--image.vue

@@ -36,9 +36,9 @@
 	 * 所以在nvue下,取名为u--image,内部其实还是u-iamge.vue,只不过做一层中转
 	 */
 	import uvImage from '../u-image/u-image.vue';
-	import props from '../u-image/props.js';
-	import mpMixin from '../../libs/mixin/mpMixin';
-	import mixin from '../../libs/mixin/mixin';
+	import { props } from '../u-image/props.js';
+	import { mpMixin } from '../../libs/mixin/mpMixin';
+	import { mixin } from '../../libs/mixin/mixin';
 	export default {
 		name: 'u--image',
 		mixins: [mpMixin, props, mixin],

+ 3 - 3
src/uni_modules/uview-plus/components/u--input/u--input.vue

@@ -61,9 +61,9 @@
 	 * 所以在nvue下,取名为u--input,内部其实还是u-input.vue,只不过做一层中转
 	 */
 	import uvInput from '../u-input/u-input.vue';
-	import props from '../u-input/props.js';
-	import mpMixin from '../../libs/mixin/mpMixin';
-	import mixin from '../../libs/mixin/mixin';
+	import { props } from '../u-input/props.js';
+	import { mpMixin } from '../../libs/mixin/mpMixin';
+	import { mixin } from '../../libs/mixin/mixin';
 	export default {
 		name: 'u--input',
 		mixins: [mpMixin, props, mixin],

+ 3 - 3
src/uni_modules/uview-plus/components/u--text/u--text.vue

@@ -32,9 +32,9 @@
  * 不使用v-bind="$attrs",而是分开独立写传参,是因为微信小程序不支持此写法
  */
 import uvText from "../u-text/u-text.vue";
-import props from "../u-text/props.js";
-import mpMixin from '../../libs/mixin/mpMixin.js'
-import mixin from '../../libs/mixin/mixin.js'
+import { props } from "../u-text/props.js";
+import { mpMixin } from '../../libs/mixin/mpMixin.js'
+import { mixin } from '../../libs/mixin/mixin.js'
 export default {
     name: "u--text",
     mixins: [mpMixin, mixin, props,],

+ 3 - 3
src/uni_modules/uview-plus/components/u--textarea/u--textarea.vue

@@ -34,9 +34,9 @@
 	 * 所以在nvue下,取名为u--textarea,内部其实还是u-textarea.vue,只不过做一层中转
 	 */
 	import uvTextarea from '../u-textarea/u-textarea.vue';
-	import props from '../u-textarea/props.js';
-	import mpMixin from '../../libs/mixin/mpMixin';
-	import mixin from '../../libs/mixin/mixin';
+	import { props } from '../u-textarea/props.js';
+	import { mpMixin } from '../../libs/mixin/mpMixin';
+	import { mixin } from '../../libs/mixin/mixin';
 	export default {
 		name: 'u--textarea',
 		mixins: [mpMixin, props, mixin],

+ 26 - 0
src/uni_modules/uview-plus/components/u-action-sheet/actionSheet.js

@@ -0,0 +1,26 @@
+/*
+ * @Author       : LQ
+ * @Description  :
+ * @version      : 1.0
+ * @Date         : 2021-08-20 16:44:21
+ * @LastAuthor   : LQ
+ * @lastTime     : 2021-08-20 16:44:35
+ * @FilePath     : /u-view2.0/uview-ui/libs/config/props/actionSheet.js
+ */
+export default {
+    // action-sheet组件
+    actionSheet: {
+        show: false,
+        title: '',
+        description: '',
+        actions: [],
+        index: '',
+        cancelText: '',
+        closeOnClickAction: true,
+        safeAreaInsetBottom: true,
+        openType: '',
+        closeOnClickOverlay: true,
+        round: 0,
+        wrapMaxHeight: '600px'
+    }
+}

+ 11 - 4
src/uni_modules/uview-plus/components/u-action-sheet/props.js

@@ -1,5 +1,7 @@
-import defProps from '../../libs/config/props.js';
-export default {
+import { defineMixin } from '../../libs/vue'
+import defProps from '../../libs/config/props.js'
+
+export const props = defineMixin({
     props: {
         // 操作菜单是否展示 (默认false)
         show: {
@@ -50,6 +52,11 @@ export default {
         round: {
             type: [Boolean, String, Number],
             default: () => defProps.actionSheet.round
-        }
+        },
+        // 选项区域最大高度
+        wrapMaxHeight: {
+            type: [String],
+            default: () => defProps.actionSheet.wrapMaxHeight
+        },
     }
-}
+})

+ 14 - 13
src/uni_modules/uview-plus/components/u-action-sheet/u-action-sheet.vue

@@ -34,7 +34,7 @@
 			>{{description}}</text>
 			<slot>
 				<u-line v-if="description"></u-line>
-				<view class="u-action-sheet__item-wrap">
+				<scroll-view scroll-y class="u-action-sheet__item-wrap" :style="{maxHeight: wrapMaxHeight}">
 					<view :key="index" v-for="(item, index) in actions">
 						<!-- #ifdef MP -->
 						<button
@@ -85,7 +85,7 @@
 						<!-- #endif -->
 						<u-line v-if="index !== actions.length - 1"></u-line>
 					</view>
-				</view>
+				</scroll-view>
 			</slot>
 			<u-gap
 			    bgColor="#eaeaec"
@@ -93,13 +93,11 @@
 			    v-if="cancelText"
 			></u-gap>
 			<view class="u-action-sheet__item-wrap__item u-action-sheet__cancel"
-				hover-class="u-action-sheet--hover">
+				hover-class="u-action-sheet--hover" @tap="cancel" v-if="cancelText">
 				<text
 				    @touchmove.stop.prevent
 				    :hover-stay-time="150"
-				    v-if="cancelText"
 				    class="u-action-sheet__cancel-text"
-				    @tap="cancel"
 				>{{cancelText}}</text>
 			</view>
 		</view>
@@ -107,11 +105,11 @@
 </template>
 
 <script>
-	import openType from '../../libs/mixin/openType'
-	import button from '../../libs/mixin/button'
-	import props from './props';
-	import mpMixin from '../../libs/mixin/mpMixin';
-	import mixin from '../../libs/mixin/mixin';
+	import { openType } from '../../libs/mixin/openType'
+	import { buttonMixin } from '../../libs/mixin/button'
+	import { props } from './props';
+	import { mpMixin } from '../../libs/mixin/mpMixin';
+	import { mixin } from '../../libs/mixin/mixin';
 	import { addUnit } from '../../libs/function/index';
 	/**
 	 * ActionSheet 操作菜单
@@ -149,7 +147,7 @@
 	export default {
 		name: "u-action-sheet",
 		// 一些props参数和methods方法,通过mixin混入,因为其他文件也会用到
-		mixins: [openType, button, mixin, props],
+		mixins: [openType, buttonMixin, mixin, props],
 		data() {
 			return {
 
@@ -168,16 +166,18 @@
 				}
 			},
 		},
-		emits: ["close", "select"],
+		emits: ["close", "select", "update:show"],
 		methods: {
 			closeHandler() {
 				// 允许点击遮罩关闭时,才发出close事件
 				if(this.closeOnClickOverlay) {
+					this.$emit('update:show')
 					this.$emit('close')
 				}
 			},
 			// 点击取消按钮
 			cancel() {
+				this.$emit('update:show')
 				this.$emit('close')
 			},
 			selectHandler(index) {
@@ -185,6 +185,7 @@
 				if (item && !item.disabled && !item.loading) {
 					this.$emit('select', item)
 					if (this.closeOnClickAction) {
+						this.$emit('update:show')
 						this.$emit('close')
 					}
 				}
@@ -272,7 +273,7 @@
 			font-size: $u-action-sheet-cancel-text-font-size;
 			color: $u-action-sheet-cancel-text-color;
 			text-align: center;
-			padding: $u-action-sheet-cancel-text-font-size;
+			// padding: $u-action-sheet-cancel-text-font-size;
 		}
 
 		&--hover {

+ 27 - 0
src/uni_modules/uview-plus/components/u-album/album.js

@@ -0,0 +1,27 @@
+/*
+ * @Author       : LQ
+ * @Description  :
+ * @version      : 1.0
+ * @Date         : 2021-08-20 16:44:21
+ * @LastAuthor   : LQ
+ * @lastTime     : 2021-08-20 16:47:24
+ * @FilePath     : /u-view2.0/uview-ui/libs/config/props/album.js
+ */
+export default {
+    // album 组件
+    album: {
+        urls: [],
+        keyName: '',
+        singleSize: 180,
+        multipleSize: 70,
+        space: 6,
+        singleMode: 'scaleToFill',
+        multipleMode: 'aspectFill',
+        maxCount: 9,
+        previewFullImage: true,
+        rowCount: 3,
+        showMore: true,
+        autoWrap: false,
+        unit: 'px'
+    }
+}

+ 24 - 3
src/uni_modules/uview-plus/components/u-album/props.js

@@ -1,5 +1,6 @@
-import defProps from '../../libs/config/props.js';
-export default {
+import { defineMixin } from '../../libs/vue'
+import defProps from '../../libs/config/props.js'
+export const props = defineMixin({
     props: {
         // 图片地址,Array<String>|Array<Object>形式
         urls: {
@@ -55,6 +56,26 @@ export default {
         showMore: {
             type: Boolean,
             default: () => defProps.album.showMore
+        },
+        // 图片形状,circle-圆形,square-方形
+        shape: {
+            type: String,
+            default: () => defProps.image.shape
+        },
+        // 圆角,单位任意
+        radius: {
+            type: [String, Number],
+            default: () => defProps.image.radius
+        },
+        // 自适应换行
+        autoWrap: {
+            type: Boolean,
+            default: () => defProps.album.autoWrap
+        },
+        // 单位
+        unit: {
+            type: [String],
+            default: () => defProps.album.unit
         }
     }
-}
+})

+ 43 - 29
src/uni_modules/uview-plus/components/u-album/u-album.vue

@@ -6,6 +6,7 @@
             v-for="(arr, index) in showUrls"
             :forComputedUse="albumWidth"
             :key="index"
+            :style="{flexWrap: autoWrap ? 'wrap' : 'nowrap'}"
         >
             <view
                 class="u-album__row__wrapper"
@@ -26,7 +27,8 @@
                     :style="[
                         {
                             width: imageWidth,
-                            height: imageHeight
+                            height: imageHeight,
+                            borderRadius: shape == 'circle' ? '10000px' : addUnit(radius)
                         }
                     ]"
                 ></image>
@@ -38,6 +40,9 @@
                         index1 === showUrls[showUrls.length - 1].length - 1
                     "
                     class="u-album__row__wrapper__text"
+                    :style="{
+					    borderRadius: shape == 'circle' ? '50%' : addUnit(radius),
+				    }"
                 >
                     <up-text
                         :text="`+${urls.length - maxCount}`"
@@ -53,9 +58,9 @@
 </template>
 
 <script>
-import props from './props';
-import mpMixin from '../../libs/mixin/mpMixin';
-import mixin from '../../libs/mixin/mixin';
+import { props } from './props';
+import { mpMixin } from '../../libs/mixin/mpMixin';
+import { mixin } from '../../libs/mixin/mixin';
 import { addUnit, sleep } from '../../libs/function/index';
 import test from '../../libs/function/test';
 // #ifdef APP-NVUE
@@ -79,7 +84,10 @@ const dom = uni.requireNativePlugin('dom')
  * @property {Boolean}         previewFullImage 是否可以预览图片 (默认 true )
  * @property {String | Number} rowCount         每行展示图片数量,如设置,singleSize和multipleSize将会无效	(默认 3 )
  * @property {Boolean}         showMore         超出maxCount时是否显示查看更多的提示 (默认 true )
- *
+ * @property {String}          shape            图片形状,circle-圆形,square-方形 (默认 'square' )
+ * @property {String | Number} radius           圆角值,单位任意,如果为数值,则为px单位 (默认 0 )
+ * @property {Boolean}         autoWrap         自适应换行模式,不受rowCount限制,图片会自动换行 (默认 false )
+ * @property {String}          unit             图片单位 (默认 px )
  * @event    {Function}        albumWidth       某些特殊的情况下,需要让文字与相册的宽度相等,这里事件的形式对外发送  (回调参数 width )
  * @example <u-album :urls="urls2" @albumWidth="width => albumWidth = width" multipleSize="68" ></u-album>
  */
@@ -119,42 +127,48 @@ export default {
                     marginBottom: addUnit(space)
                 }
                 // 如果为最后一行,则每个图片都无需下边框
-                if (index1 === rowLen) style.marginBottom = 0
+                if (index1 === rowLen && !this.autoWrap) style.marginBottom = 0
                 // 每行的最右边一张和总长度的最后一张无需右边框
-                if (
-                    index2 === rowCount ||
-                    (index1 === rowLen &&
-                        index2 === this.showUrls[index1 - 1].length)
-                )
-                    style.marginRight = 0
+                if (!this.autoWrap) {
+                    if (
+                        index2 === rowCount ||
+                        (index1 === rowLen &&
+                            index2 === this.showUrls[index1 - 1].length)
+                    )
+                        style.marginRight = 0
+                }
                 return style
             }
         },
         // 将数组划分为二维数组
         showUrls() {
-            const arr = []
-            this.urls.map((item, index) => {
-                // 限制最大展示数量
-                if (index + 1 <= this.maxCount) {
-                    // 计算该元素为第几个素组内
-                    const itemIndex = Math.floor(index / this.rowCount)
-                    // 判断对应的索引是否存在
-                    if (!arr[itemIndex]) {
-                        arr[itemIndex] = []
+            if (this.autoWrap) {
+                return [ this.urls.slice(0, this.maxCount) ];
+            } else {
+                const arr = []
+                this.urls.map((item, index) => {
+                    // 限制最大展示数量
+                    if (index + 1 <= this.maxCount) {
+                        // 计算该元素为第几个素组内
+                        const itemIndex = Math.floor(index / this.rowCount)
+                        // 判断对应的索引是否存在
+                        if (!arr[itemIndex]) {
+                            arr[itemIndex] = []
+                        }
+                        arr[itemIndex].push(item)
                     }
-                    arr[itemIndex].push(item)
-                }
-            })
-            return arr
+                })
+                return arr
+            }
         },
         imageWidth() {
             return addUnit(
-                this.urls.length === 1 ? this.singleWidth : this.multipleSize
+                this.urls.length === 1 ? this.singleWidth : this.multipleSize, this.unit
             )
         },
         imageHeight() {
             return addUnit(
-                this.urls.length === 1 ? this.singleHeight : this.multipleSize
+                this.urls.length === 1 ? this.singleHeight : this.multipleSize, this.unit
             )
         },
         // 此变量无实际用途,仅仅是为了利用computed特性,让其在urls长度等变化时,重新计算图片的宽度
@@ -173,6 +187,7 @@ export default {
         }
     },
     methods: {
+        addUnit,
         // 预览图片
         onPreviewTap(url) {
             const urls = this.urls.map((item) => {
@@ -242,7 +257,6 @@ export default {
 
     &__row {
         @include flex(row);
-        flex-wrap: wrap;
 
         &__wrapper {
             position: relative;
@@ -261,4 +275,4 @@ export default {
         }
     }
 }
-</style>
+</style>

+ 22 - 0
src/uni_modules/uview-plus/components/u-alert/alert.js

@@ -0,0 +1,22 @@
+/*
+ * @Author       : LQ
+ * @Description  :
+ * @version      : 1.0
+ * @Date         : 2021-08-20 16:44:21
+ * @LastAuthor   : LQ
+ * @lastTime     : 2021-08-20 16:48:53
+ * @FilePath     : /u-view2.0/uview-ui/libs/config/props/alert.js
+ */
+export default {
+    // alert警告组件
+    alert: {
+        title: '',
+        type: 'warning',
+        description: '',
+        closable: false,
+        showIcon: false,
+        effect: 'light',
+        center: false,
+        fontSize: 14
+    }
+}

+ 4 - 3
src/uni_modules/uview-plus/components/u-alert/props.js

@@ -1,5 +1,6 @@
-import defProps from '../../libs/config/props.js';
-export default {
+import { defineMixin } from '../../libs/vue'
+import defProps from '../../libs/config/props.js'
+export const props = defineMixin({
     props: {
         // 显示文字
         title: {
@@ -42,4 +43,4 @@ export default {
             default: () => defProps.alert.fontSize
         }
     }
-}
+})

+ 3 - 3
src/uni_modules/uview-plus/components/u-alert/u-alert.vue

@@ -60,9 +60,9 @@
 </template>
 
 <script>
-	import props from './props';
-	import mpMixin from '../../libs/mixin/mpMixin';
-	import mixin from '../../libs/mixin/mixin';
+	import { props } from './props';
+	import { mpMixin } from '../../libs/mixin/mpMixin';
+	import { mixin } from '../../libs/mixin/mixin';
 	import { addUnit, addStyle } from '../../libs/function/index';
 	/**
 	 * Alert  警告提示

+ 23 - 0
src/uni_modules/uview-plus/components/u-avatar-group/avatarGroup.js

@@ -0,0 +1,23 @@
+/*
+ * @Author       : LQ
+ * @Description  :
+ * @version      : 1.0
+ * @Date         : 2021-08-20 16:44:21
+ * @LastAuthor   : LQ
+ * @lastTime     : 2021-08-20 16:49:55
+ * @FilePath     : /u-view2.0/uview-ui/libs/config/props/avatarGroup.js
+ */
+export default {
+    // avatarGroup 组件
+    avatarGroup: {
+        urls: [],
+        maxCount: 5,
+        shape: 'circle',
+        mode: 'scaleToFill',
+        showMore: true,
+        size: 40,
+        keyName: '',
+        gap: 0.5,
+		extraValue: 0
+    }
+}

+ 4 - 3
src/uni_modules/uview-plus/components/u-avatar-group/props.js

@@ -1,5 +1,6 @@
-import defProps from '../../libs/config/props.js';
-export default {
+import { defineMixin } from '../../libs/vue'
+import defProps from '../../libs/config/props.js'
+export const props = defineMixin({
     props: {
         // 头像图片组
         urls: {
@@ -50,4 +51,4 @@ export default {
 			default: () => defProps.avatarGroup.extraValue
 		}
     }
-}
+})

+ 3 - 3
src/uni_modules/uview-plus/components/u-avatar-group/u-avatar-group.vue

@@ -32,9 +32,9 @@
 </template>
 
 <script>
-	import props from './props';
-	import mpMixin from '../../libs/mixin/mpMixin';
-	import mixin from '../../libs/mixin/mixin';
+	import { props } from './props';
+	import { mpMixin } from '../../libs/mixin/mpMixin';
+	import { mixin } from '../../libs/mixin/mixin';
 	import { addUnit } from '../../libs/function/index';
 	import test from '../../libs/function/test';
 	/**

+ 28 - 0
src/uni_modules/uview-plus/components/u-avatar/avatar.js

@@ -0,0 +1,28 @@
+/*
+ * @Author       : LQ
+ * @Description  :
+ * @version      : 1.0
+ * @Date         : 2021-08-20 16:44:21
+ * @LastAuthor   : LQ
+ * @lastTime     : 2021-08-20 16:49:22
+ * @FilePath     : /u-view2.0/uview-ui/libs/config/props/avatar.js
+ */
+export default {
+    // avatar 组件
+    avatar: {
+        src: '',
+        shape: 'circle',
+        size: 40,
+        mode: 'scaleToFill',
+        text: '',
+        bgColor: '#c0c4cc',
+        color: '#ffffff',
+        fontSize: 18,
+        icon: '',
+        mpAvatar: false,
+        randomBgColor: false,
+        defaultUrl: '',
+        colorIndex: '',
+        name: ''
+    }
+}

+ 4 - 3
src/uni_modules/uview-plus/components/u-avatar/props.js

@@ -1,6 +1,7 @@
-import defProps from '../../libs/config/props.js';
+import { defineMixin } from '../../libs/vue'
+import defProps from '../../libs/config/props.js'
 import test from '../../libs/function/test';
-export default {
+export const props = defineMixin({
     props: {
         // 头像图片路径(不能为相对路径)
         src: {
@@ -77,4 +78,4 @@ export default {
             default: () => defProps.avatar.name
         }
     }
-}
+})

文件差異過大導致無法顯示
+ 3 - 3
src/uni_modules/uview-plus/components/u-avatar/u-avatar.vue


+ 27 - 0
src/uni_modules/uview-plus/components/u-back-top/backtop.js

@@ -0,0 +1,27 @@
+/*
+ * @Author       : LQ
+ * @Description  :
+ * @version      : 1.0
+ * @Date         : 2021-08-20 16:44:21
+ * @LastAuthor   : LQ
+ * @lastTime     : 2021-08-20 16:50:18
+ * @FilePath     : /u-view2.0/uview-ui/libs/config/props/backtop.js
+ */
+export default {
+    // backtop组件
+    backtop: {
+        mode: 'circle',
+        icon: 'arrow-upward',
+        text: '',
+        duration: 100,
+        scrollTop: 0,
+        top: 400,
+        bottom: 100,
+        right: 20,
+        zIndex: 9,
+        iconStyle: {
+            color: '#909399',
+            fontSize: '19px'
+        }
+    }
+}

+ 4 - 3
src/uni_modules/uview-plus/components/u-back-top/props.js

@@ -1,5 +1,6 @@
-import defProps from '../../libs/config/props.js';
-export default {
+import { defineMixin } from '../../libs/vue'
+import defProps from '../../libs/config/props.js'
+export const props = defineMixin({
     props: {
         // 返回顶部的形状,circle-圆形,square-方形
         mode: {
@@ -52,4 +53,4 @@ export default {
             default: () => defProps.backtop.iconStyle
         }
     }
-}
+})

+ 3 - 3
src/uni_modules/uview-plus/components/u-back-top/u-back-top.vue

@@ -24,9 +24,9 @@
 </template>
 
 <script>
-	import props from './props';
-	import mpMixin from '../../libs/mixin/mpMixin';
-	import mixin from '../../libs/mixin/mixin';
+	import { props } from './props';
+	import { mpMixin } from '../../libs/mixin/mpMixin';
+	import { mixin } from '../../libs/mixin/mixin';
 	import { addUnit, addStyle, getPx, deepMerge, error } from '../../libs/function/index';
 	// #ifdef APP-NVUE
 	const dom = weex.requireModule('dom')

+ 27 - 0
src/uni_modules/uview-plus/components/u-badge/badge.js

@@ -0,0 +1,27 @@
+/*
+ * @Author       : LQ
+ * @Description  :
+ * @version      : 1.0
+ * @Date         : 2021-08-20 16:44:21
+ * @LastAuthor   : LQ
+ * @lastTime     : 2021-08-23 19:51:50
+ * @FilePath     : /u-view2.0/uview-ui/libs/config/props/badge.js
+ */
+export default {
+    // 徽标数组件
+    badge: {
+        isDot: false,
+        value: '',
+        show: true,
+        max: 999,
+        type: 'error',
+        showZero: false,
+        bgColor: null,
+        color: null,
+        shape: 'circle',
+        numberType: 'overflow',
+        offset: [],
+        inverted: false,
+        absolute: false
+    }
+}

+ 4 - 3
src/uni_modules/uview-plus/components/u-badge/props.js

@@ -1,5 +1,6 @@
-import defProps from '../../libs/config/props.js';
-export default {
+import { defineMixin } from '../../libs/vue'
+import defProps from '../../libs/config/props.js'
+export const props = defineMixin({
     props: {
         // 是否显示圆点
         isDot: {
@@ -75,4 +76,4 @@ export default {
             default: () => defProps.badge.absolute
         }
     }
-}
+})

+ 3 - 3
src/uni_modules/uview-plus/components/u-badge/u-badge.vue

@@ -8,9 +8,9 @@
 </template>
 
 <script>
-	import props from './props';
-	import mpMixin from '../../libs/mixin/mpMixin';
-	import mixin from '../../libs/mixin/mixin';
+	import { props } from './props';
+	import { mpMixin } from '../../libs/mixin/mpMixin';
+	import { mixin } from '../../libs/mixin/mixin';
 	import { addStyle, addUnit } from '../../libs/function/index';
 	/**
 	 * badge 徽标数

+ 27 - 0
src/uni_modules/uview-plus/components/u-box/props.js

@@ -0,0 +1,27 @@
+import { defineMixin } from '../../libs/vue'
+import defProps from '../../libs/config/props.js'
+
+export const propsBox = defineMixin({
+    props: {
+        // 背景色
+        bgColors: {
+            type: [Array],
+            default: ['#EEFCFF', '#FCF8FF', '#FDF8F2']
+        },
+        // 高度
+        height: {
+            type: [String],
+            default: "160px"
+        },
+        // 圆角
+        borderRadius: {
+            type: [String],
+            default: "6px"
+        },
+        // 间隔
+        gap: {
+            type: [String],
+            default: "15px"
+        },
+    }
+})

+ 92 - 0
src/uni_modules/uview-plus/components/u-box/u-box.vue

@@ -0,0 +1,92 @@
+<template>
+	<view class="u-box" :style="[{height: height}, addStyle(customStyle)]">
+        <view class="u-box__left" :style="{borderRadius: borderRadius, backgroundColor: bgColors[0]}">
+            <slot name="left">左</slot>
+        </view>
+        <view class="u-box__gap" :style="{width: gap, height: height}"></view>
+        <view class="u-box__right">
+            <view class="u-box__right-top" :style="{borderRadius: borderRadius, backgroundColor: bgColors[1]}">
+                <slot name="rightTop">右上</slot>
+            </view>
+            <view class="u-box__right-gap" :style="{height: gap}"></view>
+            <view class="u-box__right-bottom" :style="{borderRadius: borderRadius, backgroundColor: bgColors[2]}">
+                <slot name="rightBottom">右下</slot>
+            </view>
+        </view>
+	</view>
+</template>
+
+<script>
+	import { propsBox } from './props';
+	import { mpMixin } from '../../libs/mixin/mpMixin';
+	import { mixin } from '../../libs/mixin/mixin';
+	import { addStyle } from '../../libs/function/index';
+	import test from '../../libs/function/test';
+	/**
+	 * box 盒子
+	 * @description box盒子一般为左边一个盒子,右侧两个等高的半盒组成,常用于App首页座位重点突出。
+	 * @tutorial https://uview-plus.jiangruyi.com/components/box.html
+	 * @property {Array}	bgColors			背景色
+	 * @property {String}	height			    高度
+     * @property {String}	borderRadius		圆角
+	 * @property {Object}   customStyle		    定义需要用到的外部样式
+	 * 
+	 * @event {Function}			click			点击cell列表时触发
+	 * @example <up-box colors=['blue', 'red', 'yellow'] height="200px"></up-box>
+	 */
+	export default {
+		name: 'up-box',
+		data() {
+			return {
+			}
+		},
+		mixins: [mpMixin, mixin, propsBox],
+		computed: {
+		},
+		emits: [],
+		methods: {
+			addStyle,
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	@import "../../libs/css/components.scss";
+
+	.u-box {
+        /* #ifndef APP-NVUE */
+        /* #endif */
+        @include flex();
+        flex: 1;
+
+		&__left {
+            @include flex();
+            justify-content: center;
+            align-items: center;
+            flex: 1;
+        }
+        &__gap {
+            @include flex();
+            flex-direction: column;
+        }
+        &__right {
+            @include flex();
+            flex-direction: column;
+            flex: 1;
+        }
+
+        &__right-top {
+            @include flex();
+            flex: 1;
+            justify-content: center;
+            align-items: center;
+        }
+
+        &__right-bottom {
+            @include flex();
+            flex: 1;
+            justify-content: center;
+            align-items: center;
+        }
+	}
+</style>

+ 42 - 0
src/uni_modules/uview-plus/components/u-button/button.js

@@ -0,0 +1,42 @@
+/*
+ * @Author       : LQ
+ * @Description  :
+ * @version      : 1.0
+ * @Date         : 2021-08-20 16:44:21
+ * @LastAuthor   : LQ
+ * @lastTime     : 2021-08-20 16:51:27
+ * @FilePath     : /u-view2.0/uview-ui/libs/config/props/button.js
+ */
+export default {
+    // button组件
+    button: {
+        hairline: false,
+        type: 'info',
+        size: 'normal',
+        shape: 'square',
+        plain: false,
+        disabled: false,
+        loading: false,
+        loadingText: '',
+        loadingMode: 'spinner',
+        loadingSize: 15,
+        openType: '',
+        formType: '',
+        appParameter: '',
+        hoverStopPropagation: true,
+        lang: 'en',
+        sessionFrom: '',
+        sendMessageTitle: '',
+        sendMessagePath: '',
+        sendMessageImg: '',
+        showMessageCard: false,
+        dataName: '',
+        throttleTime: 0,
+        hoverStartTime: 0,
+        hoverStayTime: 200,
+        text: '',
+        icon: '',
+        iconColor: '',
+        color: ''
+    }
+}

+ 4 - 3
src/uni_modules/uview-plus/components/u-button/props.js

@@ -1,5 +1,6 @@
-import defProps from '../../libs/config/props.js';
-export default {
+import { defineMixin } from '../../libs/vue'
+import defProps from '../../libs/config/props.js'
+export const props = defineMixin({
     props: {
         // 是否细边框
         hairline: {
@@ -150,4 +151,4 @@ export default {
             default: () => defProps.button.color
         }
     }
-}
+})

+ 6 - 6
src/uni_modules/uview-plus/components/u-button/u-button.vue

@@ -110,11 +110,11 @@
 </template>
 
 <script lang="ts">
-import button from "../../libs/mixin/button";
-import openType from "../../libs/mixin/openType";
-import mpMixin from '../../libs/mixin/mpMixin';
-import mixin from '../../libs/mixin/mixin';
-import props from "./props";
+import { buttonMixin } from "../../libs/mixin/button";
+import { openType } from "../../libs/mixin/openType";
+import { mpMixin } from '../../libs/mixin/mpMixin';
+import { mixin } from '../../libs/mixin/mixin';
+import { props } from "./props";
 import { addStyle } from '../../libs/function/index';
 import { throttle } from '../../libs/function/throttle';
 import color from '../../libs/config/color';
@@ -165,7 +165,7 @@ import color from '../../libs/config/color';
 export default {
     name: "u-button",
     // #ifdef MP
-    mixins: [mpMixin, mixin, button, openType, props],
+    mixins: [mpMixin, mixin, buttonMixin, openType, props],
     // #endif
     // #ifndef MP
     mixins: [mpMixin, mixin, props],

+ 42 - 0
src/uni_modules/uview-plus/components/u-calendar/calendar.js

@@ -0,0 +1,42 @@
+/*
+ * @Author       : LQ
+ * @Description  :
+ * @version      : 1.0
+ * @Date         : 2021-08-20 16:44:21
+ * @LastAuthor   : LQ
+ * @lastTime     : 2021-08-20 16:52:43
+ * @FilePath     : /u-view2.0/uview-ui/libs/config/props/calendar.js
+ */
+export default {
+    // calendar 组件
+    calendar: {
+        title: '日期选择',
+        showTitle: true,
+        showSubtitle: true,
+        mode: 'single',
+        startText: '开始',
+        endText: '结束',
+        customList: [],
+        color: '#3c9cff',
+        minDate: 0,
+        maxDate: 0,
+        defaultDate: null,
+        maxCount: Number.MAX_SAFE_INTEGER, // Infinity
+        rowHeight: 56,
+        formatter: null,
+        showLunar: false,
+        showMark: true,
+        confirmText: '确定',
+        confirmDisabledText: '确定',
+        show: false,
+        closeOnClickOverlay: false,
+        readonly: false,
+        showConfirm: true,
+        maxRange: Number.MAX_SAFE_INTEGER, // Infinity
+        rangePrompt: '',
+        showRangePrompt: true,
+        allowSameDay: false,
+		round: 0,
+		monthNum: 3
+    }
+}

+ 4 - 2
src/uni_modules/uview-plus/components/u-calendar/header.vue

@@ -21,8 +21,8 @@
 </template>
 
 <script>
-	import mpMixin from '../../libs/mixin/mpMixin';
-	import mixin from '../../libs/mixin/mixin';
+	import { mpMixin } from '../../libs/mixin/mpMixin';
+	import { mixin } from '../../libs/mixin/mixin';
 	export default {
 		name: 'u-calendar-header',
 		mixins: [mpMixin, mixin],
@@ -65,6 +65,8 @@
 	@import "../../libs/css/components.scss";
 
 	.u-calendar-header {
+		display: flex;
+		flex-direction: column;
 		padding-bottom: 4px;
 
 		&__title {

+ 6 - 4
src/uni_modules/uview-plus/components/u-calendar/month.vue

@@ -31,8 +31,8 @@
 	// 由于nvue不支持百分比单位,需要查询宽度来计算每个日期的宽度
 	const dom = uni.requireNativePlugin('dom')
 	// #endif
-	import mpMixin from '../../libs/mixin/mpMixin';
-	import mixin from '../../libs/mixin/mixin';
+	import { mpMixin } from '../../libs/mixin/mpMixin';
+	import { mixin } from '../../libs/mixin/mixin';
 	import { addUnit, deepClone, toast, sleep } from '../../libs/function/index';
 	import { colorGradient } from '../../libs/function/colorGradient';
 	import test from '../../libs/function/test';
@@ -158,13 +158,13 @@
 					const dayWidth = Number(parseFloat(this.width / 7).toFixed(3).slice(0, -1))
 					// 得出每个日期的宽度
 					// #ifdef APP-NVUE
-					style.width = addUnit(dayWidth)
+					style.width = addUnit(dayWidth, 'px')
 					// #endif
 					style.height = addUnit(this.rowHeight)
 					if (index2 === 0) {
 						// 获取当前为星期几,如果为0,则为星期天,减一为每月第一天时,需要向左偏移的item个数
 						week = (week === 0 ? 7 : week) - 1
-						style.marginLeft = addUnit(week * dayWidth)
+						style.marginLeft = addUnit(week * dayWidth, 'px')
 					}
 					if (this.mode === 'range') {
 						// 之所以需要这么写,是因为DCloud公司的iOS客户端的开发者能力有限导致的bug
@@ -468,6 +468,8 @@
 	.u-calendar-month {
 
 		&__title {
+			display: flex;
+			flex-direction: column;
 			font-size: 14px;
 			line-height: 42px;
 			height: 42px;

+ 5 - 3
src/uni_modules/uview-plus/components/u-calendar/props.js

@@ -1,5 +1,7 @@
-import defProps from '../../libs/config/props.js';
-export default {
+import { defineMixin } from '../../libs/vue'
+import defProps from '../../libs/config/props.js'
+
+export const props = defineMixin({
     props: {
         // 日历顶部标题
         title: {
@@ -142,4 +144,4 @@ export default {
 			default: 3
 		}	
     }
-}
+})

+ 3 - 3
src/uni_modules/uview-plus/components/u-calendar/u-calendar.vue

@@ -66,12 +66,12 @@
 <script>
 import uHeader from './header.vue'
 import uMonth from './month.vue'
-import props from './props.js'
+import { props } from './props.js'
 import util from './util.js'
 import dayjs from 'dayjs/esm/index'
 import Calendar from '../../libs/util/calendar.js'
-import mpMixin from '../../libs/mixin/mpMixin.js'
-import mixin from '../../libs/mixin/mixin.js'
+import { mpMixin } from '../../libs/mixin/mpMixin.js'
+import { mixin } from '../../libs/mixin/mixin.js'
 import { addUnit, range, error, padZero } from '../../libs/function/index';
 import test from '../../libs/function/test';
 /**

+ 15 - 0
src/uni_modules/uview-plus/components/u-car-keyboard/carKeyboard.js

@@ -0,0 +1,15 @@
+/*
+ * @Author       : LQ
+ * @Description  :
+ * @version      : 1.0
+ * @Date         : 2021-08-20 16:44:21
+ * @LastAuthor   : LQ
+ * @lastTime     : 2021-08-20 16:53:20
+ * @FilePath     : /u-view2.0/uview-ui/libs/config/props/carKeyboard.js
+ */
+export default {
+    // 车牌号键盘
+    carKeyboard: {
+        random: false
+    }
+}

+ 5 - 3
src/uni_modules/uview-plus/components/u-car-keyboard/props.js

@@ -1,5 +1,7 @@
-// import defProps from '../../libs/config/props.js';
-export default {
+import { defineMixin } from '../../libs/vue'
+import defProps from '../../libs/config/props.js'
+
+export const props = defineMixin({
     props: {
         // 是否打乱键盘按键的顺序
         random: {
@@ -12,4 +14,4 @@ export default {
             default: false
         }
     }
-}
+})

+ 5 - 5
src/uni_modules/uview-plus/components/u-car-keyboard/u-car-keyboard.vue

@@ -68,13 +68,13 @@
 </template>
 
 <script>
-	import props from './props';
-	import mpMixin from '../../libs/mixin/mpMixin';
-	import mixin from '../../libs/mixin/mixin';
+	import { props } from './props';
+	import { mpMixin } from '../../libs/mixin/mpMixin';
+	import { mixin } from '../../libs/mixin/mixin';
 	import { randomArray, sleep } from '../../libs/function/index';
 	/**
 	 * keyboard 键盘组件
-	 * @description 此为uView自定义的键盘面板,内含了数字键盘,车牌号键,身份证号键盘3种模式,都有可以打乱按键顺序的选项。
+	 * @description 此为uview-plus自定义的键盘面板,内含了数字键盘,车牌号键,身份证号键盘3种模式,都有可以打乱按键顺序的选项。
 	 * @tutorial https://uview-plus.jiangruyi.com/components/keyboard.html
 	 * @property {Boolean} random 是否打乱键盘的顺序
 	 * @event {Function} change 点击键盘触发
@@ -82,7 +82,7 @@
 	 * @example <u-keyboard ref="uKeyboard" mode="car" v-model="show"></u-keyboard>
 	 */
 	export default {
-		name: "u-keyboard",
+		name: "u-car-keyboard",
 		mixins: [mpMixin, mixin, props],
 		data() {
 			return {

+ 140 - 0
src/uni_modules/uview-plus/components/u-card/props.js

@@ -0,0 +1,140 @@
+import { defineMixin } from '../../libs/vue'
+import defProps from '../../libs/config/props.js'
+
+export const propsCard = defineMixin({
+    props: {
+        // 与屏幕两侧是否留空隙
+		full: {
+			type: Boolean,
+			default: false
+		},
+		// 标题
+		title: {
+			type: String,
+			default: ''
+		},
+		// 标题颜色
+		titleColor: {
+			type: String,
+			default: '#303133'
+		},
+		// 标题字体大小
+		titleSize: {
+			type: [Number, String],
+			default: '15px'
+		},
+		// 副标题
+		subTitle: {
+			type: String,
+			default: ''
+		},
+		// 副标题颜色
+		subTitleColor: {
+			type: String,
+			default: '#909399'
+		},
+		// 副标题字体大小
+		subTitleSize: {
+			type: [Number, String],
+			default: '13'
+		},
+		// 是否显示外部边框,只对full=false时有效(卡片与边框有空隙时)
+		border: {
+			type: Boolean,
+			default: true
+		},
+		// 用于标识点击了第几个
+		index: {
+			type: [Number, String, Object],
+			default: ''
+		},
+		// 用于隔开上下左右的边距,带单位的写法,如:"30px 30px","20px 20px 30px 30px"
+		margin: {
+			type: String,
+			default: '15px'
+		},
+		// card卡片的圆角
+		borderRadius: {
+			type: [Number, String],
+			default: '8px'
+		},
+		// 头部自定义样式,对象形式
+		headStyle: {
+			type: Object,
+			default() {
+				return {};
+			}
+		},
+		// 主体自定义样式,对象形式
+		bodyStyle: {
+			type: Object,
+			default() {
+				return {};
+			}
+		},
+		// 底部自定义样式,对象形式
+		footStyle: {
+			type: Object,
+			default() {
+				return {};
+			}
+		},
+		// 头部是否下边框
+		headBorderBottom: {
+			type: Boolean,
+			default: true
+		},
+		// 底部是否有上边框
+		footBorderTop: {
+			type: Boolean,
+			default: true
+		},
+		// 标题左边的缩略图
+		thumb: {
+			type: String,
+			default: ''
+		},
+		// 缩略图宽高
+		thumbWidth: {
+			type: [String, Number],
+			default: '30px'
+		},
+		// 缩略图是否为圆形
+		thumbCircle: {
+			type: Boolean,
+			default: false
+		},
+		// 给head,body,foot的内边距
+		padding: {
+			type: [String, Number],
+			default: '15px'
+		},
+		paddingHead: {
+			type: [String, Number],
+			default: ''
+		},
+		paddingBody: {
+			type: [String, Number],
+			default: ''
+		},
+		paddingFoot: {
+			type: [String, Number],
+			default: ''
+		},
+		// 是否显示头部
+		showHead: {
+			type: Boolean,
+			default: true
+		},
+		// 是否显示尾部
+		showFoot: {
+			type: Boolean,
+			default: true
+		},
+		// 卡片外围阴影,字符串形式
+		boxShadow: {
+			type: String,
+			default: 'none'
+		}
+    }
+})

+ 186 - 0
src/uni_modules/uview-plus/components/u-card/u-card.vue

@@ -0,0 +1,186 @@
+<template>
+	<view
+		class="u-card"
+		@tap.stop="click"
+		:class="{ 'u-border': border, 'u-card-full': full, 'u-card--border': getPx(borderRadius) > 0 }"
+		:style="{
+			borderRadius: addUnit(borderRadius),
+			margin: margin,
+			boxShadow: boxShadow
+		}"
+	>
+		<view
+			v-if="showHead"
+			class="u-card__head"
+			:style="[{padding: addUnit(paddingHead || padding)}, headStyle]"
+			:class="{
+				'u-border-bottom': headBorderBottom
+			}"
+			@tap="headClick"
+		>
+			<view v-if="!$slots.head" class="u-flex u-row-between">
+				<view class="u-card__head--left u-flex u-line-1" v-if="title">
+					<image
+						:src="thumb"
+						class="u-card__head--left__thumb"
+						mode="aspectFill"
+						v-if="thumb"
+						:style="{ 
+							height: addUnit(thumbWidth), 
+							width: addUnit(thumbWidth), 
+							borderRadius: thumbCircle ? '50px' : '4px' 
+						}"
+					></image>
+					<text
+						class="u-card__head--left__title u-line-1"
+						:style="{
+							fontSize: addUnit(titleSize),
+							color: titleColor
+						}"
+					>
+						{{ title }}
+					</text>
+				</view>
+				<view class="u-card__head--right u-line-1" v-if="subTitle">
+					<text
+						class="u-card__head__title__text"
+						:style="{
+							fontSize: addUnit(subTitleSize),
+							color: subTitleColor
+						}"
+					>
+						{{ subTitle }}
+					</text>
+				</view>
+			</view>
+			<slot name="head" v-else />
+		</view>
+		<view @tap="bodyClick" class="u-card__body"
+			:style="[{padding: addUnit(paddingBody || padding)}, bodyStyle]"><slot name="body" /></view>
+		<view
+			v-if="showFoot"
+			class="u-card__foot"
+			 @tap="footClick"
+			:style="[{padding: $slots.foot ? addUnit(paddingFoot || padding) : 0}, footStyle]"
+			:class="{
+				'u-border-top': footBorderTop
+			}"
+		>
+			<slot name="foot" />
+		</view>
+	</view>
+</template>
+
+<script>
+    import { propsCard } from './props';
+    import { mpMixin } from '../../libs/mixin/mpMixin';
+    import { mixin } from '../../libs/mixin/mixin';
+    import { addStyle, addUnit, getPx } from '../../libs/function/index';
+    /**
+     * card 卡片
+     * @description 卡片组件一般用于多个列表条目,且风格统一的场景
+     * @tutorial https://uview-plus.jiangruyi.com/components/card.html
+     * @property {Boolean} full 卡片与屏幕两侧是否留空隙(默认false)
+     * @property {String} title 头部左边的标题
+     * @property {String} title-color 标题颜色(默认#303133)
+     * @property {String | Number} title-size 标题字体大小,单位rpx(默认15px)
+     * @property {String} sub-title 头部右边的副标题
+     * @property {String} sub-title-color 副标题颜色(默认#909399)
+     * @property {String | Number} sub-title-size 副标题字体大小(默认13px
+     * @property {Boolean} border 是否显示边框(默认true)
+     * @property {String | Number} index 用于标识点击了第几个卡片
+     * @property {String} box-shadow 卡片外围阴影,字符串形式(默认none)
+     * @property {String} margin 卡片与屏幕两边和上下元素的间距,需带单位,如"30px 20px"(默认15px)
+     * @property {String | Number} border-radius 卡片整体的圆角值,单位rpx(默认8px)
+     * @property {Object} head-style 头部自定义样式,对象形式
+     * @property {Object} body-style 中部自定义样式,对象形式
+     * @property {Object} foot-style 底部自定义样式,对象形式
+     * @property {Boolean} head-border-bottom 是否显示头部的下边框(默认true)
+     * @property {Boolean} foot-border-top 是否显示底部的上边框(默认true)
+     * @property {Boolean} show-head 是否显示头部(默认true)
+     * @property {Boolean} show-foot 是否显示尾部(默认true)
+     * @property {String} thumb 缩略图路径,如设置将显示在标题的左边,不建议使用相对路径
+     * @property {String | Number} thumb-width 缩略图的宽度,高等于宽,单位px(默认30px)
+     * @property {Boolean} thumb-circle 缩略图是否为圆形(默认false)
+     * @event {Function} click 整个卡片任意位置被点击时触发
+     * @event {Function} head-click 卡片头部被点击时触发
+     * @event {Function} body-click 卡片主体部分被点击时触发
+     * @event {Function} foot-click 卡片底部部分被点击时触发
+     * @example <u-card paddingFoot="2px 15px" title="card"></u-card>
+     */
+    export default {
+        name: 'up-card',
+        data() {
+            return {};
+        },
+        mixins: [mpMixin, mixin, propsCard],
+        emits: ['click', 'head-click', 'body-click', 'foot-click'],
+        methods: {
+			addStyle,
+			addUnit,
+			getPx,
+            click() {
+                this.$emit('click', this.index);
+            },
+            headClick() {
+                this.$emit('head-click', this.index);
+            },
+            bodyClick() {
+                this.$emit('body-click', this.index);
+            },
+            footClick() {
+                this.$emit('foot-click', this.index);
+            }
+        }
+    };
+</script>
+
+<style lang="scss" scoped>
+@import "../../libs/css/components.scss";
+	
+.u-card {
+	position: relative;
+	overflow: hidden;
+	font-size: 28rpx;
+	background-color: #ffffff;
+	box-sizing: border-box;
+	
+	&-full {
+		// 如果是与屏幕之间不留空隙,应该设置左右边距为0
+		margin-left: 0 !important;
+		margin-right: 0 !important;
+		width: 100%;
+	}
+	
+	&--border:after {
+		border-radius: 16rpx;
+	}
+
+	&__head {
+		&--left {
+			color: $u-main-color;
+			
+			&__thumb {
+				margin-right: 16rpx;
+			}
+			
+			&__title {
+				max-width: 400rpx;
+			}
+		}
+
+		&--right {
+			color: $u-tips-color;
+			margin-left: 6rpx;
+		}
+	}
+
+	&__body {
+		color: $u-content-color;
+	}
+
+	&__foot {
+		color: $u-tips-color;
+	}
+}
+</style>

+ 17 - 0
src/uni_modules/uview-plus/components/u-cell-group/cellGroup.js

@@ -0,0 +1,17 @@
+/*
+ * @Author       : LQ
+ * @Description  :
+ * @version      : 1.0
+ * @Date         : 2021-08-20 16:44:21
+ * @LastAuthor   : LQ
+ * @lastTime     : 2021-08-20 16:54:16
+ * @FilePath     : /u-view2.0/uview-ui/libs/config/props/cellGroup.js
+ */
+export default {
+    // cell-group组件的props
+    cellGroup: {
+        title: '',
+        border: true,
+        customStyle: {}
+    }
+}

+ 4 - 3
src/uni_modules/uview-plus/components/u-cell-group/props.js

@@ -1,5 +1,6 @@
-import defProps from '../../libs/config/props.js';
-export default {
+import { defineMixin } from '../../libs/vue'
+import defProps from '../../libs/config/props.js'
+export const props = defineMixin({
     props: {
         // 分组标题
         title: {
@@ -12,4 +13,4 @@ export default {
             default: () => defProps.cellGroup.border
         }
     }
-}
+})

+ 3 - 3
src/uni_modules/uview-plus/components/u-cell-group/u-cell-group.vue

@@ -13,9 +13,9 @@
 </template>
 
 <script>
-	import props from './props';
-	import mpMixin from '../../libs/mixin/mpMixin';
-	import mixin from '../../libs/mixin/mixin';
+	import { props } from './props';
+	import { mpMixin } from '../../libs/mixin/mpMixin';
+	import { mixin } from '../../libs/mixin/mixin';
 	import { addStyle } from '../../libs/function/index';
 	/**
 	 * cellGroup  单元格

+ 35 - 0
src/uni_modules/uview-plus/components/u-cell/cell.js

@@ -0,0 +1,35 @@
+/*
+ * @Author       : LQ
+ * @Description  :
+ * @version      : 1.0
+ * @Date         : 2021-08-20 16:44:21
+ * @LastAuthor   : LQ
+ * @lastTime     : 2021-08-23 20:53:09
+ * @FilePath     : /u-view2.0/uview-ui/libs/config/props/cell.js
+ */
+export default {
+	// cell组件的props
+	cell: {
+		customClass: '',
+		title: '',
+		label: '',
+		value: '',
+		icon: '',
+		disabled: false,
+		border: true,
+		center: false,
+		url: '',
+		linkType: 'navigateTo',
+		clickable: false,
+		isLink: false,
+		required: false,
+		arrowDirection: '',
+		iconStyle: {},
+		rightIconStyle: {},
+		rightIcon: 'arrow-right',
+		titleStyle: {},
+		size: '',
+		stop: true,
+		name: ''
+	}
+}

+ 4 - 3
src/uni_modules/uview-plus/components/u-cell/props.js

@@ -1,5 +1,6 @@
-import defProps from '../../libs/config/props.js';
-export default {
+import { defineMixin } from '../../libs/vue'
+import defProps from '../../libs/config/props.js'
+export const props = defineMixin({
     props: {
         // 标题
         title: {
@@ -108,4 +109,4 @@ export default {
             default: () => defProps.cell.name
         }
     }
-}
+})

+ 25 - 4
src/uni_modules/uview-plus/components/u-cell/u-cell.vue

@@ -16,7 +16,7 @@
 					<slot name="title" v-if="$slots.title || !title">
 					</slot>
                     <text v-else class="u-cell__title-text" :style="[titleTextStyle]"
-                        :class="[disabled && 'u-cell--disabled', size === 'large' && 'u-cell__title-text--large']">{{ title }}</text>
+                        :class="[required && 'u-cell--required', disabled && 'u-cell--disabled', size === 'large' && 'u-cell__title-text--large']">{{ title }}</text>
 					<slot name="label">
 						<text class="u-cell__label" v-if="label"
 							:class="[disabled && 'u-cell--disabled', size === 'large' && 'u-cell__label--large']">{{ label }}</text>
@@ -47,9 +47,9 @@
 </template>
 
 <script>
-	import props from './props';
-	import mpMixin from '../../libs/mixin/mpMixin';
-	import mixin from '../../libs/mixin/mixin';
+	import { props } from './props';
+	import { mpMixin } from '../../libs/mixin/mpMixin';
+	import { mixin } from '../../libs/mixin/mixin';
 	import { addStyle } from '../../libs/function/index';
 	import test from '../../libs/function/test';
 	/**
@@ -192,6 +192,8 @@
 
 		&__title {
 			flex: $u-cell-title-flex;
+			display: flex;
+			flex-direction: column;
 
 			&-text {
 				font-size: $u-cell-title-font-size;
@@ -229,6 +231,25 @@
 			}
 		}
 
+		&--required {
+			/* #ifndef APP-NVUE */
+			overflow: visible;
+			/* #endif */
+			@include flex;
+			align-items: center;
+		}
+
+		&--required:before {
+			position: absolute;
+			/* #ifndef APP-NVUE */
+			content: '*';
+			/* #endif */
+			left: -8px;
+			margin-top: 4rpx;
+			font-size: 14px;
+			color: $u-error;
+		}
+
 		&--clickable {
 			background-color: $u-cell-clickable-color;
 		}

+ 29 - 0
src/uni_modules/uview-plus/components/u-checkbox-group/checkboxGroup.js

@@ -0,0 +1,29 @@
+/*
+ * @Author       : LQ
+ * @Description  :
+ * @version      : 1.0
+ * @Date         : 2021-08-20 16:44:21
+ * @LastAuthor   : LQ
+ * @lastTime     : 2021-08-20 16:54:47
+ * @FilePath     : /u-view2.0/uview-ui/libs/config/props/checkboxGroup.js
+ */
+export default {
+    // checkbox-group组件
+    checkboxGroup: {
+        name: '',
+        value: [],
+        shape: 'square',
+        disabled: false,
+        activeColor: '#2979ff',
+        inactiveColor: '#c8c9cc',
+        size: 18,
+        placement: 'row',
+        labelSize: 14,
+        labelColor: '#303133',
+        labelDisabled: false,
+        iconColor: '#ffffff',
+        iconSize: 12,
+        iconPlacement: 'left',
+        borderBottom: false
+    }
+}

+ 5 - 4
src/uni_modules/uview-plus/components/u-checkbox-group/props.js

@@ -1,5 +1,7 @@
-import defProps from '../../libs/config/props.js';
-export default {
+import { defineMixin } from '../../libs/vue'
+import defProps from '../../libs/config/props.js'
+
+export const props = defineMixin({
     props: {
         // 标识符
         name: {
@@ -87,6 +89,5 @@ export default {
             type: Boolean,
             default: () => defProps.checkboxGroup.borderBottom
         }
-
     }
-}
+})

+ 3 - 3
src/uni_modules/uview-plus/components/u-checkbox-group/u-checkbox-group.vue

@@ -8,9 +8,9 @@
 </template>
 
 <script>
-	import props from './props';
-	import mpMixin from '../../libs/mixin/mpMixin';
-	import mixin from '../../libs/mixin/mixin';
+	import { props } from './props';
+	import { mpMixin } from '../../libs/mixin/mpMixin';
+	import { mixin } from '../../libs/mixin/mixin';
 	/**
 	 * checkboxGroup 复选框组
 	 * @description 复选框组件一般用于需要多个选择的场景,该组件功能完整,使用方便

+ 27 - 0
src/uni_modules/uview-plus/components/u-checkbox/checkbox.js

@@ -0,0 +1,27 @@
+/*
+ * @Author       : LQ
+ * @Description  :
+ * @version      : 1.0
+ * @Date         : 2021-08-20 16:44:21
+ * @LastAuthor   : LQ
+ * @lastTime     : 2021-08-23 21:06:59
+ * @FilePath     : /u-view2.0/uview-ui/libs/config/props/checkbox.js
+ */
+export default {
+    // checkbox组件
+    checkbox: {
+        name: '',
+        shape: '',
+        size: '',
+        checkbox: false,
+        disabled: '',
+        activeColor: '',
+        inactiveColor: '',
+        iconSize: '',
+        iconColor: '',
+        label: '',
+        labelSize: '',
+        labelColor: '',
+        labelDisabled: ''
+    }
+}

+ 4 - 3
src/uni_modules/uview-plus/components/u-checkbox/props.js

@@ -1,5 +1,6 @@
-import defProps from '../../libs/config/props.js';
-export default {
+import { defineMixin } from '../../libs/vue'
+import defProps from '../../libs/config/props.js'
+export const props = defineMixin({
     props: {
         // checkbox的名称
         name: {
@@ -72,4 +73,4 @@ export default {
             default: () => false
         }
     }
-}
+})

+ 42 - 30
src/uni_modules/uview-plus/components/u-checkbox/u-checkbox.vue

@@ -20,21 +20,23 @@
 				/>
 			</slot>
 		</view>
-		<text
-		    @tap.stop="labelClickHandler"
-		    :style="{
-				color: elDisabled ? elInactiveColor : elLabelColor,
-				fontSize: elLabelSize,
-				lineHeight: elLabelSize
-			}"
-		>{{label}}</text>
+		<slot name="label" :label="label" :elDisabled="elDisabled">
+			<text
+				@tap.stop="labelClickHandler"
+				:style="{
+					color: elDisabled ? elInactiveColor : elLabelColor,
+					fontSize: elLabelSize,
+					lineHeight: elLabelSize
+				}"
+			>{{label}}</text>
+		</slot>
 	</view>
 </template>
 
 <script>
-	import props from './props';
-	import mpMixin from '../../libs/mixin/mpMixin';
-	import mixin from '../../libs/mixin/mixin';
+	import { props } from './props';
+	import { mpMixin } from '../../libs/mixin/mpMixin';
+	import { mixin } from '../../libs/mixin/mixin';
 	import { addStyle, addUnit, deepMerge, formValidate, error } from '../../libs/function/index';
 	import test from '../../libs/function/test';
 	/**
@@ -89,7 +91,7 @@
 			}
 		},
 		computed: {
-			// 是否禁用,如果父组件u-raios-group禁用的话,将会忽略子组件的配置
+			// 是否禁用,如果父组件u-radios-group禁用的话,将会忽略子组件的配置
 			elDisabled() {
 				return this.disabled !== '' ? this.disabled : this.parentData.disabled !== null ? this.parentData.disabled : false;
 			},
@@ -187,7 +189,7 @@
 		mounted() {
 			this.init()
 		},
-		emits: ["change"],
+		emits: ["change", "update:checked"],
 		methods: {
 			init() {
 				if (!this.usedAlone) {
@@ -196,21 +198,25 @@
 					if (!this.parent) {
 						error('u-checkbox必须搭配u-checkbox-group组件使用')
 					}
-				}
-				// #ifdef VUE2
-				const value = this.parentData.value
-				// #endif
-				// #ifdef VUE3
-				const value = this.parentData.modelValue
-				// #endif
-				// 设置初始化时,是否默认选中的状态,父组件u-checkbox-group的value可能是array,所以额外判断
-				if (this.checked) {
-					this.isChecked = true
-				} else if (!this.usedAlone && test.array(value)) {
-					// 查找数组是是否存在this.name元素值
-					this.isChecked = value.some(item => {
-						return item === this.name
-					})
+					// #ifdef VUE2
+					const value = this.parentData.value
+					// #endif
+					// #ifdef VUE3
+					const value = this.parentData.modelValue
+					// #endif
+					// 设置初始化时,是否默认选中的状态,父组件u-checkbox-group的value可能是array,所以额外判断
+					if (this.checked) {
+						this.isChecked = true
+					} else if (!this.usedAlone && test.array(value)) {
+						// 查找数组是是否存在this.name元素值
+						this.isChecked = value.some(item => {
+							return item === this.name
+						})
+					}
+				} else {
+					if (this.checked) {
+						this.isChecked = true
+					}
 				}
 			},
 			updateParentData() {
@@ -242,6 +248,10 @@
 			},
 			emitEvent() {
 				this.$emit('change', this.isChecked)
+				// 双向绑定
+				if (this.usedAlone) {
+					this.$emit('update:checked', this.isChecked)
+				}
 				// 尝试调用u-form的验证方法,进行一定延迟,否则微信小程序更新可能会不及时
 				this.$nextTick(() => {
 					formValidate(this, 'change')
@@ -260,8 +270,10 @@
 			}
 		},
 		watch:{
-			checked(){
-				this.isChecked = this.checked
+			checked(newValue, oldValue){
+				if (newValue !== this.isChecked) {
+					this.isChecked = newValue
+				}
 			}
 		}
 	}

+ 15 - 0
src/uni_modules/uview-plus/components/u-circle-progress/circleProgress.js

@@ -0,0 +1,15 @@
+/*
+ * @Author       : LQ
+ * @Description  :
+ * @version      : 1.0
+ * @Date         : 2021-08-20 16:44:21
+ * @LastAuthor   : LQ
+ * @lastTime     : 2021-08-20 16:55:02
+ * @FilePath     : /u-view2.0/uview-ui/libs/config/props/circleProgress.js
+ */
+export default {
+    // circleProgress 组件
+    circleProgress: {
+        percentage: 30
+    }
+}

+ 4 - 3
src/uni_modules/uview-plus/components/u-circle-progress/props.js

@@ -1,9 +1,10 @@
-import defProps from '../../libs/config/props.js';
-export default {
+import { defineMixin } from '../../libs/vue'
+import defProps from '../../libs/config/props.js'
+export const props = defineMixin({
     props: {
         percentage: {
             type: [String, Number],
             default: () => defProps.circleProgress.percentage
         }
     }
-}
+})

+ 3 - 3
src/uni_modules/uview-plus/components/u-circle-progress/u-circle-progress.vue

@@ -27,9 +27,9 @@
 </template>
 
 <script>
-	import props from './props';
-	import mpMixin from '../../libs/mixin/mpMixin';
-	import mixin from '../../libs/mixin/mixin';
+	import { props } from './props';
+	import { mpMixin } from '../../libs/mixin/mpMixin';
+	import { mixin } from '../../libs/mixin/mixin';
 	import {sleep } from '../../libs/function/index';
 	// #ifdef APP-NVUE
 	const animation = uni.requireNativePlugin('animation')

+ 29 - 0
src/uni_modules/uview-plus/components/u-code-input/codeInput.js

@@ -0,0 +1,29 @@
+/*
+ * @Author       : LQ
+ * @Description  :
+ * @version      : 1.0
+ * @Date         : 2021-08-20 16:44:21
+ * @LastAuthor   : LQ
+ * @lastTime     : 2021-08-20 16:55:58
+ * @FilePath     : /u-view2.0/uview-ui/libs/config/props/codeInput.js
+ */
+export default {
+    // codeInput 组件
+    codeInput: {
+		adjustPosition: true,
+        maxlength: 6,
+        dot: false,
+        mode: 'box',
+        hairline: false,
+        space: 10,
+        value: '',
+        focus: false,
+        bold: false,
+        color: '#606266',
+        fontSize: 18,
+        size: 35,
+        disabledKeyboard: false,
+        borderColor: '#c9cacc',
+		disabledDot: true
+    }
+}

+ 4 - 3
src/uni_modules/uview-plus/components/u-code-input/props.js

@@ -1,5 +1,6 @@
-import defProps from '../../libs/config/props.js';
-export default {
+import { defineMixin } from '../../libs/vue'
+import defProps from '../../libs/config/props.js'
+export const props = defineMixin({
     props: {
 		// 键盘弹起时,是否自动上推页面
 		adjustPosition: {
@@ -86,4 +87,4 @@ export default {
 			default: () => defProps.codeInput.disabledDot
 		}
     }
-}
+})

+ 46 - 12
src/uni_modules/uview-plus/components/u-code-input/u-code-input.vue

@@ -23,8 +23,13 @@
 				v-if="mode === 'line'"
 				:style="[lineStyle]"
 			></view>
-			<!-- #ifndef APP-PLUS -->
-			<view v-if="isFocus && codeArray.length === index" :style="{backgroundColor: color}" class="u-code-input__item__cursor"></view>
+			<!-- #ifndef APP-NVUE -->
+			<view v-if="isFocus && codeArray.length === index"
+				:style="{backgroundColor: color}" class="u-code-input__item__cursor"></view>
+			<!-- #endif -->
+			<!-- #ifdef APP-NVUE -->
+			 <view v-if="isFocus && codeArray.length === index"
+			 :style="{backgroundColor: color, opacity: opacity}" class="u-code-input__item__cursor"></view>
 			<!-- #endif -->
 		</view>
 		<input
@@ -46,9 +51,9 @@
 </template>
 
 <script>
-	import props from './props';
-	import mpMixin from '../../libs/mixin/mpMixin';
-	import mixin from '../../libs/mixin/mixin';
+	import { props } from './props';
+	import { mpMixin } from '../../libs/mixin/mpMixin';
+	import { mixin } from '../../libs/mixin/mixin';
 	import { addUnit, getPx } from '../../libs/function/index';
 	/**
 	 * CodeInput 验证码输入
@@ -79,22 +84,51 @@
 		data() {
 			return {
 				inputValue: '',
-				isFocus: this.focus
+				isFocus: this.focus,
+				timer: null,
+				opacity: 1
 			}
 		},
 		watch: {
 			// #ifdef VUE2
 			value: {
+				immediate: true,
+				handler(val) {
+					// 转为字符串,超出部分截掉
+					this.inputValue = String(val).substring(0, this.maxlength)
+				}
+			},
 			// #endif
 			// #ifdef VUE3
 			modelValue: {
-			// #endif
 				immediate: true,
 				handler(val) {
 					// 转为字符串,超出部分截掉
 					this.inputValue = String(val).substring(0, this.maxlength)
 				}
 			},
+			// #endif
+			isFocus: {
+				handler(val) {
+					// #ifdef APP-NVUE
+					if (val) {
+						this.timer = setInterval(() => {
+							this.opacity = Math.abs(this.opacity - 1)
+						}, 600)
+					} else {
+						clearInterval(this.timer)
+					}
+					// #endif
+				}
+			}
+		},
+		created() {
+			
+		},
+		beforeUnmount() {
+			// #ifdef APP-NVUE
+			clearInterval(this.timer)
+			// #endif
 		},
 		computed: {
 			// 根据长度,循环输入框的个数,因为头条小程序数值不能用于v-for
@@ -188,7 +222,7 @@
 <style lang="scss" scoped>
 	@import "../../libs/css/components.scss";
 	$u-code-input-cursor-width: 1px;
-	$u-code-input-cursor-height: 40%;
+	$u-code-input-cursor-height: 20px;
 	$u-code-input-cursor-animation-duration: 1s;
 	$u-code-input-cursor-animation-name: u-cursor-flicker;
 
@@ -223,18 +257,18 @@
 				width: 40px;
 				background-color: $u-content-color;
 			}
-			/* #ifndef APP-PLUS */
 			&__cursor {
 				position: absolute;
+				/* #ifndef APP-NVUE */
 				top: 50%;
 				left: 50%;
+				opacity: 1;
 				transform: translate(-50%,-50%);
+				/* #endif */
 				width: $u-code-input-cursor-width;
 				height: $u-code-input-cursor-height;
 				animation: $u-code-input-cursor-animation-duration u-cursor-flicker infinite;
 			}
-			/* #endif */
-			
 		}
 
 		&__input {
@@ -249,7 +283,7 @@
 		}
 	}
 	
-	/* #ifndef APP-PLUS */
+	/* #ifndef APP-NVUE */
 	@keyframes u-cursor-flicker {
 		0% {
 		    opacity: 0;

+ 21 - 0
src/uni_modules/uview-plus/components/u-code/code.js

@@ -0,0 +1,21 @@
+/*
+ * @Author       : LQ
+ * @Description  :
+ * @version      : 1.0
+ * @Date         : 2021-08-20 16:44:21
+ * @LastAuthor   : LQ
+ * @lastTime     : 2021-08-20 16:55:27
+ * @FilePath     : /u-view2.0/uview-ui/libs/config/props/code.js
+ */
+
+export default {
+    // code 组件
+    code: {
+        seconds: 60,
+        startText: '获取验证码',
+        changeText: 'X秒重新获取',
+        endText: '重新获取',
+        keepRunning: false,
+        uniqueKey: ''
+    }
+}

+ 4 - 3
src/uni_modules/uview-plus/components/u-code/props.js

@@ -1,5 +1,6 @@
-import defProps from '../../libs/config/props.js';
-export default {
+import { defineMixin } from '../../libs/vue'
+import defProps from '../../libs/config/props.js'
+export const props = defineMixin({
     props: {
         // 倒计时总秒数
         seconds: {
@@ -32,4 +33,4 @@ export default {
             default: () => defProps.code.uniqueKey
         }
     }
-}
+})

+ 3 - 8
src/uni_modules/uview-plus/components/u-code/u-code.vue

@@ -5,9 +5,9 @@
 </template>
 
 <script>
-	import props from './props';
-	import mpMixin from '../../libs/mixin/mpMixin';
-	import mixin from '../../libs/mixin/mixin';
+	import { props } from './props';
+	import { mpMixin } from '../../libs/mixin/mpMixin';
+	import { mixin } from '../../libs/mixin/mixin';
 	/**
 	 * Code 验证码输入框
 	 * @description 考虑到用户实际发送验证码的场景,可能是一个按钮,也可能是一段文字,提示语各有不同,所以本组件 不提供界面显示,只提供提示语,由用户将提示语嵌入到具体的场景
@@ -119,12 +119,7 @@
 			}
 		},
 		// 组件销毁的时候,清除定时器,否则定时器会继续存在,系统不会自动清除
-		// #ifdef VUE2
-		beforeDestroy() {
-		// #endif
-		// #ifdef VUE3
 		beforeUnmount() {
-		// #endif
 			this.setTimeToStorage()
 			clearTimeout(this.timer)
 			this.timer = null

+ 19 - 0
src/uni_modules/uview-plus/components/u-col/col.js

@@ -0,0 +1,19 @@
+/*
+ * @Author       : LQ
+ * @Description  :
+ * @version      : 1.0
+ * @Date         : 2021-08-20 16:44:21
+ * @LastAuthor   : LQ
+ * @lastTime     : 2021-08-20 16:56:12
+ * @FilePath     : /u-view2.0/uview-ui/libs/config/props/col.js
+ */
+export default {
+    // col 组件
+    col: {
+        span: 12,
+        offset: 0,
+        justify: 'start',
+        align: 'stretch',
+        textAlign: 'left'
+    }
+}

+ 4 - 3
src/uni_modules/uview-plus/components/u-col/props.js

@@ -1,5 +1,6 @@
-import defProps from '../../libs/config/props.js';
-export default {
+import { defineMixin } from '../../libs/vue'
+import defProps from '../../libs/config/props.js'
+export const props = defineMixin({
     props: {
         // 占父容器宽度的多少等分,总分为12份
         span: {
@@ -27,4 +28,4 @@ export default {
             default: () => defProps.col.textAlign
         }
     }
-}
+})

+ 3 - 3
src/uni_modules/uview-plus/components/u-col/u-col.vue

@@ -13,9 +13,9 @@
 </template>
 
 <script>
-	import props from './props';
-	import mpMixin from '../../libs/mixin/mpMixin';
-	import mixin from '../../libs/mixin/mixin';
+	import { props } from './props';
+	import { mpMixin } from '../../libs/mixin/mpMixin';
+	import { mixin } from '../../libs/mixin/mixin';
 	import { addStyle, addUnit, deepMerge, getPx } from '../../libs/function/index';
 	/**
 	 * CodeInput 栅格系统的列 

+ 26 - 0
src/uni_modules/uview-plus/components/u-collapse-item/collapseItem.js

@@ -0,0 +1,26 @@
+/*
+ * @Author       : LQ
+ * @Description  :
+ * @version      : 1.0
+ * @Date         : 2021-08-20 16:44:21
+ * @LastAuthor   : LQ
+ * @lastTime     : 2021-08-20 16:56:42
+ * @FilePath     : /u-view2.0/uview-ui/libs/config/props/collapseItem.js
+ */
+export default {
+    // collapseItem 组件
+    collapseItem: {
+        title: '',
+        value: '',
+        label: '',
+        disabled: false,
+        isLink: true,
+        clickable: true,
+        border: true,
+        align: 'left',
+        name: '',
+        icon: '',
+        duration: 300,
+        showRight: true
+    }
+}

+ 10 - 4
src/uni_modules/uview-plus/components/u-collapse-item/props.js

@@ -1,5 +1,6 @@
-import defProps from '../../libs/config/props.js';
-export default {
+import { defineMixin } from '../../libs/vue'
+import defProps from '../../libs/config/props.js'
+export const props = defineMixin({
     props: {
         // 标题
         title: {
@@ -55,6 +56,11 @@ export default {
         duration: {
             type: Number,
             default: () => defProps.collapseItem.duration
-        }
+        },
+        // 显示右侧图标
+        showRight: {
+            type: Boolean,
+            default: () => defProps.collapseItem.showRight
+        },
     }
-}
+})

+ 9 - 7
src/uni_modules/uview-plus/components/u-collapse-item/u-collapse-item.vue

@@ -33,9 +33,11 @@
 				</slot>
 			</template>
 			<template #right-icon>
-				<u-icon v-if="!$slots['right-icon']" :size="16" name="arrow-right"></u-icon>
-				<slot name="right-icon">
-				</slot>
+				<template v-if="showRight">
+					<u-icon v-if="!$slots['right-icon']" :size="16" name="arrow-right"></u-icon>
+					<slot name="right-icon">
+					</slot>
+				</template>
 			</template>
 		</u-cell>
 		<view
@@ -54,9 +56,9 @@
 </template>
 
 <script>
-	import props from './props.js';
-	import mpMixin from '../../libs/mixin/mpMixin';
-	import mixin from '../../libs/mixin/mixin';
+	import { props } from './props.js';
+	import { mpMixin } from '../../libs/mixin/mpMixin';
+	import { mixin } from '../../libs/mixin/mixin';
 	import { nextTick } from 'vue';
 	import { guid, sleep, error } from '../../libs/function/index';
 	import test from '../../libs/function/test';
@@ -153,7 +155,7 @@
 				// 每次面板打开或者收起时,都查询元素尺寸
 				// 好处是,父组件从服务端获取内容后,变更折叠面板后可以获得最新的高度
 				const rect = await this.queryRect()
-				const height = this.expanded ? 'auto' : 0
+				const height = this.expanded ? rect.height : 0
 				this.animating = true
 				// #ifdef APP-NVUE
 				const ref = this.$refs['animation'].ref

+ 17 - 0
src/uni_modules/uview-plus/components/u-collapse/collapse.js

@@ -0,0 +1,17 @@
+/*
+ * @Author       : LQ
+ * @Description  :
+ * @version      : 1.0
+ * @Date         : 2021-08-20 16:44:21
+ * @LastAuthor   : LQ
+ * @lastTime     : 2021-08-20 16:56:30
+ * @FilePath     : /u-view2.0/uview-ui/libs/config/props/collapse.js
+ */
+export default {
+    // collapse 组件
+    collapse: {
+        value: null,
+        accordion: false,
+        border: true
+    }
+}

+ 4 - 3
src/uni_modules/uview-plus/components/u-collapse/props.js

@@ -1,5 +1,6 @@
-import defProps from '../../libs/config/props.js';
-export default {
+import { defineMixin } from '../../libs/vue'
+import defProps from '../../libs/config/props.js'
+export const props = defineMixin({
     props: {
         // 当前展开面板的name,非手风琴模式:[<string | number>],手风琴模式:string | number
         value: {
@@ -17,4 +18,4 @@ export default {
             default: () => defProps.collapse.border
         }
     }
-}
+})

部分文件因文件數量過多而無法顯示