diff --git a/README.md b/README.md
index c98e2ed87..0c8ccac05 100644
--- a/README.md
+++ b/README.md
@@ -23,8 +23,8 @@
 >
 > 😜 给项目点点 Star 吧,这对我们真的很重要!
 
-* 前端 Vue2 版本采用 [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin)
-* 前端 Vue3 版本采用 [vue-element-plus-admin](https://gitee.com/kailong110120130/vue-element-plus-admin)
+* 管理后台的 Vue3 版本采用 [vue-element-plus-admin](https://gitee.com/kailong110120130/vue-element-plus-admin) ,Vue2 版本采用 [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin) 
+* 管理后台的移动端采用 [uni-app](https://github.com/dcloudio/uni-app) 方案,一份代码多终端适配,同时支持 APP、小程序、H5!
 * 后端采用 Spring Boot、MySQL + MyBatis Plus、Redis + Redisson
 * 数据库可使用 MySQL、Oracle、PostgreSQL、SQL Server、MariaDB、国产达梦 DM、TiDB 等
 * 权限认证使用 Spring Security & Token & Redis,支持多终端、多种用户的认证系统,支持 SSO 单点登录
@@ -156,8 +156,9 @@ ps:核心功能已经实现,正在对接微信小程序中...
 | `yudao-dependencies`  | Maven 依赖版本管理       |
 | `yudao-framework`     | Java 框架拓展          |
 | `yudao-server`        | 管理后台 + 用户 APP 的服务端 |
-| `yudao-ui-admin`      | Vue2 管理后台的 UI 界面        |
-| `yudao-ui-admin-vue3`      | Vue3 管理后台的 UI 界面        |
+| `yudao-ui-admin`      | 管理后台的 Vue2 前端项目        |
+| `yudao-ui-admin-vue3`      | 管理后台的 Vue3 前端项目        |
+| `yudao-ui-admin-uniapp`      | 管理后台的 uni-app 多端项目        |
 | `yudao-ui-app`       | 用户 APP 的 UI 界面     |
 | `yudao-module-system` | 系统功能的 Module 模块    |
 | `yudao-module-member` | 会员中心的 Module 模块    |
@@ -192,14 +193,14 @@ ps:核心功能已经实现,正在对接微信小程序中...
 | [JUnit](https://junit.org/junit5/)                                                          | Java 单元测试框架        | 5.8.2    | -                                                              |
 | [Mockito](https://github.com/mockito/mockito)                                               | Java Mock 框架         | 4.0.0    | -                                                              |
 
-### [Vue2 前端](./yudao-ui-admin)
+### [管理后台 Vue2 前端](./yudao-ui-admin)
 
 | 框架                                                                           | 说明            | 版本     |
 |------------------------------------------------------------------------------|---------------|--------|
 | [Vue](https://cn.vuejs.org/index.html)                                       | JavaScript 框架 | 2.6.12 |
 | [Vue Element Admin](https://panjiachen.github.io/vue-element-admin-site/zh/) | 后台前端解决方案      | -      |
 
-### [Vue3 前端](./yudao-ui-admin-vue3)
+### [管理后台 Vue3 前端](./yudao-ui-admin-vue3)
 
 | 框架                                                                  | 说明               | 版本     |
 |----------------------------------------------------------------------|------------------|--------|
@@ -212,6 +213,13 @@ ps:核心功能已经实现,正在对接微信小程序中...
 | [windicss](https://cn.windicss.org/)                                 | 下一代工具优先的 CSS 框架  | 3.5.6  |
 | [iconify](https://icon-sets.iconify.design/)                         | 在线图标库            | 2.2.1  |
 
+### [管理后台 uni-app 跨端](./yudao-ui-admin-uniapp)
+
+| 框架                                                                  | 说明               | 版本     |
+|----------------------------------------------------------------------|------------------|--------|
+| [uni-app](hhttps://github.com/dcloudio/uni-app)                                 | 跨平台框架           | 2.0.0 |
+| [uni-ui](https://github.com/dcloudio/uni-ui)                                      | 基于 uni-app 的 UI 框架          | 1.4.20  |
+
 ## 🐷 演示图
 
 ### 系统功能
@@ -262,3 +270,13 @@ ps:核心功能已经实现,正在对接微信小程序中...
 | 模块      | biu                                                              | biu                                                                    | biu                                                                    |
 |---------|------------------------------------------------------------------|------------------------------------------------------------------------|------------------------------------------------------------------------|
 | 报表设计器 | ![数据报表](https://static.iocoder.cn/images/ruoyi-vue-pro/报表设计器-数据报表.jpg?imageView2/2/format/webp/w/1280) | ![图形报表](https://static.iocoder.cn/images/ruoyi-vue-pro/报表设计器-图形报表.jpg?imageView2/2/format/webp/w/1280) | ![报表设计器-打印设计](https://static.iocoder.cn/images/ruoyi-vue-pro/报表设计器-打印设计.jpg?imageView2/2/format/webp/w/1280) |
+
+### 移动端(管理后台)
+
+| biu                                                              | biu                                                                    | biu                                                                    |
+|------------------------------------------------------------------|------------------------------------------------------------------------|------------------------------------------------------------------------|
+| ![](https://static.iocoder.cn/images/ruoyi-vue-pro/admin-uniapp/01.png?imageView2/2/format/webp) | ![](https://static.iocoder.cn/images/ruoyi-vue-pro/admin-uniapp/02.png?imageView2/2/format/webp) | ![](https://static.iocoder.cn/images/ruoyi-vue-pro/admin-uniapp/03.png?imageView2/2/format/webp) |
+| ![](https://static.iocoder.cn/images/ruoyi-vue-pro/admin-uniapp/04.png?imageView2/2/format/webp) | ![](https://static.iocoder.cn/images/ruoyi-vue-pro/admin-uniapp/05.png?imageView2/2/format/webp) | ![](https://static.iocoder.cn/images/ruoyi-vue-pro/admin-uniapp/06.png?imageView2/2/format/webp) |
+| ![](https://static.iocoder.cn/images/ruoyi-vue-pro/admin-uniapp/07.png?imageView2/2/format/webp) | ![](https://static.iocoder.cn/images/ruoyi-vue-pro/admin-uniapp/08.png?imageView2/2/format/webp) | ![](https://static.iocoder.cn/images/ruoyi-vue-pro/admin-uniapp/09.png?imageView2/2/format/webp) |
+
+目前已经实现登录、我的、工作台、编辑资料、头像修改、密码修改、常见问题、关于我们等基础功能。
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/UserProfileController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/UserProfileController.java
index 3cc3a44dd..d65994379 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/UserProfileController.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/UserProfileController.java
@@ -95,7 +95,7 @@ public class UserProfileController {
         return success(true);
     }
 
-    @PutMapping("/update-avatar")
+    @RequestMapping(value = "/update-avatar", method = {RequestMethod.POST, RequestMethod.PUT}) // 解决 uni-app 不支持 Put 上传文件的问题
     @ApiOperation("上传用户个人头像")
     public CommonResult<String> updateUserAvatar(@RequestParam("avatarFile") MultipartFile file) throws Exception {
         if (file.isEmpty()) {
diff --git a/yudao-ui-admin-uniapp/.gitignore b/yudao-ui-admin-uniapp/.gitignore
new file mode 100644
index 000000000..59c91545c
--- /dev/null
+++ b/yudao-ui-admin-uniapp/.gitignore
@@ -0,0 +1,16 @@
+######################################################################
+# Build Tools
+
+/unpackage/*
+/node_modules/*
+
+######################################################################
+# Development Tools
+
+/.idea/*
+/.vscode/*
+/.hbuilderx/*
+
+package-lock.json
+yarn.lock
+
diff --git a/yudao-ui-admin-uniapp/App.vue b/yudao-ui-admin-uniapp/App.vue
new file mode 100644
index 000000000..93318b588
--- /dev/null
+++ b/yudao-ui-admin-uniapp/App.vue
@@ -0,0 +1,34 @@
+<script>
+  import config from './config'
+  import store from '@/store'
+  import { getAccessToken } from '@/utils/auth'
+
+  export default {
+    onLaunch: function() {
+      this.initApp()
+    },
+    methods: {
+      // 初始化应用
+      initApp() {
+        // 初始化应用配置
+        this.initConfig()
+        // 检查用户登录状态
+        //#ifdef H5
+        this.checkLogin()
+        //#endif
+      },
+      initConfig() {
+        this.globalData.config = config
+      },
+      checkLogin() {
+        if (!getAccessToken()) {
+          this.$tab.reLaunch('/pages/login')
+        }
+      }
+    }
+  }
+</script>
+
+<style lang="scss">
+  @import '@/static/scss/index.scss'
+</style>
diff --git a/yudao-ui-admin-uniapp/LICENSE b/yudao-ui-admin-uniapp/LICENSE
new file mode 100644
index 000000000..84f43b5ab
--- /dev/null
+++ b/yudao-ui-admin-uniapp/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2022 芋道
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/yudao-ui-admin-uniapp/api/login.js b/yudao-ui-admin-uniapp/api/login.js
new file mode 100644
index 000000000..628e2a741
--- /dev/null
+++ b/yudao-ui-admin-uniapp/api/login.js
@@ -0,0 +1,47 @@
+import request from '@/utils/request'
+
+// 登录方法
+export function login(username, password, code, uuid) {
+  const data = {
+    username,
+    password,
+    code,
+    uuid
+  }
+  return request({
+    url: '/system/auth/login',
+    headers: {
+      isToken: false
+    },
+    'method': 'post',
+    'data': data
+  })
+}
+
+// 获取用户详细信息
+export function getInfo() {
+  return request({
+    url: '/system/auth/get-permission-info',
+    'method': 'get'
+  })
+}
+
+// 退出方法
+export function logout() {
+  return request({
+    url: '/system/auth/logout',
+    'method': 'post'
+  })
+}
+
+// 获取验证码
+export function getCodeImg() {
+  return request({
+    url: '/system/captcha/get-image',
+    headers: {
+      isToken: false
+    },
+    method: 'get',
+    timeout: 20000
+  })
+}
diff --git a/yudao-ui-admin-uniapp/api/system/user.js b/yudao-ui-admin-uniapp/api/system/user.js
new file mode 100644
index 000000000..9e9e7bf5e
--- /dev/null
+++ b/yudao-ui-admin-uniapp/api/system/user.js
@@ -0,0 +1,42 @@
+import upload from '@/utils/upload'
+import request from '@/utils/request'
+
+// 用户密码重置
+export function updateUserPwd(oldPassword, newPassword) {
+  const data = {
+    oldPassword,
+    newPassword
+  }
+  return request({
+    url: '/system/user/profile/update-password',
+    method: 'put',
+    params: data
+  })
+}
+
+// 查询用户个人信息
+export function getUserProfile() {
+  return request({
+    url: '/system/user/profile/get',
+    method: 'get'
+  })
+}
+
+// 修改用户个人信息
+export function updateUserProfile(data) {
+  return request({
+    url: '/system/user/profile/update',
+    method: 'put',
+    data: data
+  })
+}
+
+// 用户头像上传
+export function uploadAvatar(data) {
+  return upload({
+    url: '/system/user/profile/update-avatar',
+    method: 'put',
+    name: data.name,
+    filePath: data.filePath
+  })
+}
diff --git a/yudao-ui-admin-uniapp/components/uni-section/uni-section.vue b/yudao-ui-admin-uniapp/components/uni-section/uni-section.vue
new file mode 100644
index 000000000..9a52e0b8d
--- /dev/null
+++ b/yudao-ui-admin-uniapp/components/uni-section/uni-section.vue
@@ -0,0 +1,167 @@
+<template>
+	<view class="uni-section">
+		<view class="uni-section-header" @click="onClick">
+				<view class="uni-section-header__decoration" v-if="type" :class="type" />
+        <slot v-else name="decoration"></slot>
+
+        <view class="uni-section-header__content">
+          <text :style="{'font-size':titleFontSize,'color':titleColor}" class="uni-section__content-title" :class="{'distraction':!subTitle}">{{ title }}</text>
+          <text v-if="subTitle" :style="{'font-size':subTitleFontSize,'color':subTitleColor}" class="uni-section-header__content-sub">{{ subTitle }}</text>
+        </view>
+
+        <view class="uni-section-header__slot-right">
+          <slot name="right"></slot>
+        </view>
+		</view>
+
+		<view class="uni-section-content" :style="{padding: _padding}">
+			<slot />
+		</view>
+	</view>
+</template>
+
+<script>
+
+	/**
+	 * Section 标题栏
+	 * @description 标题栏
+	 * @property {String} type = [line|circle|square] 标题装饰类型
+	 * 	@value line 竖线
+	 * 	@value circle 圆形
+	 * 	@value square 正方形
+	 * @property {String} title 主标题
+	 * @property {String} titleFontSize 主标题字体大小
+	 * @property {String} titleColor 主标题字体颜色
+	 * @property {String} subTitle 副标题
+	 * @property {String} subTitleFontSize 副标题字体大小
+	 * @property {String} subTitleColor 副标题字体颜色
+	 * @property {String} padding 默认插槽 padding
+	 */
+
+	export default {
+		name: 'UniSection',
+    emits:['click'],
+		props: {
+			type: {
+				type: String,
+				default: ''
+			},
+			title: {
+				type: String,
+				required: true,
+				default: ''
+			},
+      titleFontSize: {
+        type: String,
+        default: '14px'
+      },
+			titleColor:{
+				type: String,
+				default: '#333'
+			},
+			subTitle: {
+				type: String,
+				default: ''
+			},
+      subTitleFontSize: {
+        type: String,
+        default: '12px'
+      },
+      subTitleColor: {
+        type: String,
+        default: '#999'
+      },
+			padding: {
+				type: [Boolean, String],
+				default: false
+			}
+		},
+    computed:{
+      _padding(){
+        if(typeof this.padding === 'string'){
+          return this.padding
+        }
+
+        return this.padding?'10px':''
+      }
+    },
+		watch: {
+			title(newVal) {
+				if (uni.report && newVal !== '') {
+					uni.report('title', newVal)
+				}
+			}
+		},
+    methods: {
+			onClick() {
+				this.$emit('click')
+			}
+		}
+	}
+</script>
+<style lang="scss" >
+	$uni-primary: #2979ff !default;
+
+	.uni-section {
+		background-color: #fff;
+    .uni-section-header {
+      position: relative;
+      /* #ifndef APP-NVUE */
+      display: flex;
+      /* #endif */
+      flex-direction: row;
+      align-items: center;
+      padding: 12px 10px;
+      font-weight: normal;
+
+      &__decoration{
+        margin-right: 6px;
+        background-color: $uni-primary;
+        &.line {
+          width: 4px;
+          height: 12px;
+          border-radius: 10px;
+        }
+
+        &.circle {
+          width: 8px;
+          height: 8px;
+          border-top-right-radius: 50px;
+          border-top-left-radius: 50px;
+          border-bottom-left-radius: 50px;
+          border-bottom-right-radius: 50px;
+        }
+
+        &.square {
+          width: 8px;
+          height: 8px;
+        }
+      }
+
+      &__content {
+        /* #ifndef APP-NVUE */
+        display: flex;
+        /* #endif */
+        flex-direction: column;
+        flex: 1;
+        color: #333;
+
+        .distraction {
+          flex-direction: row;
+          align-items: center;
+        }
+        &-sub {
+          margin-top: 2px;
+        }
+      }
+
+      &__slot-right{
+        font-size: 14px;
+      }
+    }
+
+    .uni-section-content{
+      font-size: 14px;
+    }
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/config.js b/yudao-ui-admin-uniapp/config.js
new file mode 100644
index 000000000..cd0a162b3
--- /dev/null
+++ b/yudao-ui-admin-uniapp/config.js
@@ -0,0 +1,26 @@
+// 应用全局配置
+module.exports = {
+  // baseUrl: 'http://localhost:8080',
+  baseUrl: 'http://localhost:48080/admin-api',
+  // 应用信息
+  appInfo: {
+    // 应用名称
+    name: "yudao-app",
+    // 应用版本
+    version: "1.0.0",
+    // 应用logo
+    logo: "/static/logo.png",
+    // 官方网站
+    site_url: "https://iocoder.cn",
+    // 政策协议
+    agreements: [{
+        title: "隐私政策",
+        url: "https://iocoder.cn"
+      },
+      {
+        title: "用户服务协议",
+        url: "https://iocoder.cn"
+      }
+    ]
+  }
+}
diff --git a/yudao-ui-admin-uniapp/main.js b/yudao-ui-admin-uniapp/main.js
new file mode 100644
index 000000000..3985b1b17
--- /dev/null
+++ b/yudao-ui-admin-uniapp/main.js
@@ -0,0 +1,17 @@
+import Vue from 'vue'
+import App from './App'
+import store from './store' // store
+import plugins from './plugins' // plugins
+import './permission' // permission
+Vue.use(plugins)
+
+Vue.config.productionTip = false
+Vue.prototype.$store = store
+
+App.mpType = 'app'
+
+const app = new Vue({
+  ...App
+})
+
+app.$mount()
diff --git a/yudao-ui-admin-uniapp/manifest.json b/yudao-ui-admin-uniapp/manifest.json
new file mode 100644
index 000000000..8c138fa16
--- /dev/null
+++ b/yudao-ui-admin-uniapp/manifest.json
@@ -0,0 +1,69 @@
+{
+    "name" : "芋道移动端",
+    "appid" : "__UNI__25A9D80",
+    "description" : "",
+    "versionName" : "1.0.0",
+    "versionCode" : "100",
+    "transformPx" : false,
+    "app-plus" : {
+        "usingComponents" : true,
+        "nvueCompiler" : "uni-app",
+        "splashscreen" : {
+            "alwaysShowBeforeRender" : true,
+            "waiting" : true,
+            "autoclose" : true,
+            "delay" : 0
+        },
+        "modules" : {},
+        "distribute" : {
+            "android" : {
+                "permissions" : [
+                    "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
+                    "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
+                    "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CAMERA\"/>",
+                    "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
+                    "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
+                    "<uses-feature android:name=\"android.hardware.camera\"/>",
+                    "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
+                ]
+            },
+            "ios" : {},
+            "sdkConfigs" : {}
+        }
+    },
+    "quickapp" : {},
+    "mp-weixin" : {
+        "appid" : "wxccd7e2a0911b3397",
+        "setting" : {
+            "urlCheck" : false,
+            "es6" : false,
+            "minified" : true,
+            "postcss" : true
+        },
+        "optimization" : {
+            "subPackages" : true
+        },
+        "usingComponents" : true
+    },
+    "vueVersion" : "2",
+    "h5" : {
+        "template" : "static/index.html",
+        "devServer" : {
+            "port" : 9090,
+            "https" : false
+        },
+        "title" : "Yudao-App",
+        "router" : {
+            "mode" : "hash",
+            "base" : "./"
+        }
+    }
+}
diff --git a/yudao-ui-admin-uniapp/pages.json b/yudao-ui-admin-uniapp/pages.json
new file mode 100644
index 000000000..73c631aa8
--- /dev/null
+++ b/yudao-ui-admin-uniapp/pages.json
@@ -0,0 +1,97 @@
+{
+  "pages": [{
+    "path": "pages/login",
+    "style": {
+      "navigationBarTitleText": "登录"
+    }
+  }, {
+    "path": "pages/index",
+    "style": {
+      "navigationBarTitleText": "芋道移动端框架",
+      "navigationStyle": "custom"
+    }
+  }, {
+    "path": "pages/work/index",
+    "style": {
+      "navigationBarTitleText": "工作台"
+    }
+  }, {
+    "path": "pages/mine/index",
+    "style": {
+      "navigationBarTitleText": "我的"
+    }
+  }, {
+    "path": "pages/mine/avatar/index",
+    "style": {
+      "navigationBarTitleText": "修改头像"
+    }
+  }, {
+    "path": "pages/mine/info/index",
+    "style": {
+      "navigationBarTitleText": "个人信息"
+    }
+  }, {
+    "path": "pages/mine/info/edit",
+    "style": {
+      "navigationBarTitleText": "编辑资料"
+    }
+  }, {
+    "path": "pages/mine/pwd/index",
+    "style": {
+      "navigationBarTitleText": "修改密码"
+    }
+  }, {
+    "path": "pages/mine/setting/index",
+    "style": {
+      "navigationBarTitleText": "应用设置"
+    }
+  }, {
+    "path": "pages/mine/help/index",
+    "style": {
+      "navigationBarTitleText": "常见问题"
+    }
+  }, {
+    "path": "pages/mine/about/index",
+    "style": {
+      "navigationBarTitleText": "关于我们"
+    }
+  }, {
+    "path": "pages/common/webview/index",
+    "style": {
+      "navigationBarTitleText": "浏览网页"
+    }
+  }, {
+    "path": "pages/common/textview/index",
+    "style": {
+      "navigationBarTitleText": "浏览文本"
+    }
+  }],
+  "tabBar": {
+    "color": "#000000",
+    "selectedColor": "#000000",
+    "borderStyle": "white",
+    "backgroundColor": "#ffffff",
+    "list": [{
+        "pagePath": "pages/index",
+        "iconPath": "static/images/tabbar/home.png",
+        "selectedIconPath": "static/images/tabbar/home_.png",
+        "text": "首页"
+      }, {
+        "pagePath": "pages/work/index",
+        "iconPath": "static/images/tabbar/work.png",
+        "selectedIconPath": "static/images/tabbar/work_.png",
+        "text": "工作台"
+      }, {
+        "pagePath": "pages/mine/index",
+        "iconPath": "static/images/tabbar/mine.png",
+        "selectedIconPath": "static/images/tabbar/mine_.png",
+        "text": "我的"
+      }
+    ]
+  },
+  "globalStyle": {
+    "navigationBarTextStyle": "black",
+    "navigationBarTitleText": "RuoYi",
+    "navigationBarBackgroundColor": "#FFFFFF"
+  }
+}
diff --git a/yudao-ui-admin-uniapp/pages/common/textview/index.vue b/yudao-ui-admin-uniapp/pages/common/textview/index.vue
new file mode 100644
index 000000000..e9b05fbb9
--- /dev/null
+++ b/yudao-ui-admin-uniapp/pages/common/textview/index.vue
@@ -0,0 +1,43 @@
+<template>
+  <view>
+    <uni-card class="view-title" :title="title">
+      <text class="uni-body view-content">{{ content }}</text>
+    </uni-card>
+  </view>
+</template>
+
+<script>
+  export default {
+    data() {
+      return {
+        title: '',
+        content: ''
+      }
+    },
+    onLoad(options) {
+      this.title = options.title
+      this.content = options.content
+      uni.setNavigationBarTitle({
+        title: options.title
+      })
+    }
+  }
+</script>
+
+<style scoped>
+  page {
+    background-color: #ffffff;
+  }
+
+  .view-title {
+    font-weight: bold;
+  }
+
+  .view-content {
+    font-size: 26rpx;
+    padding: 12px 5px 0;
+    color: #333;
+    line-height: 24px;
+    font-weight: normal;
+  }
+</style>
diff --git a/yudao-ui-admin-uniapp/pages/common/webview/index.vue b/yudao-ui-admin-uniapp/pages/common/webview/index.vue
new file mode 100644
index 000000000..8388c76f2
--- /dev/null
+++ b/yudao-ui-admin-uniapp/pages/common/webview/index.vue
@@ -0,0 +1,34 @@
+<template>
+  <view v-if="params.url">
+    <web-view :webview-styles="webviewStyles" :src="`${params.url}`"></web-view>
+  </view>
+</template>
+
+<script>
+  export default {
+    data() {
+      return {
+        params: {},
+        webviewStyles: {
+          progress: {
+            color: "#FF3333"
+          }
+        }
+      }
+    },
+    props: {
+      src: {
+        type: [String],
+        default: null
+      }
+    },
+    onLoad(event) {
+      this.params = event
+      if (event.title) {
+        uni.setNavigationBarTitle({
+          title: event.title
+        })
+      }
+    }
+  }
+</script>
diff --git a/yudao-ui-admin-uniapp/pages/index.vue b/yudao-ui-admin-uniapp/pages/index.vue
new file mode 100644
index 000000000..17613f04f
--- /dev/null
+++ b/yudao-ui-admin-uniapp/pages/index.vue
@@ -0,0 +1,43 @@
+<template>
+  <view class="content">
+    <image class="logo" src="/static/logo.png"></image>
+    <view class="text-area">
+      <text class="title">Hello 芋道</text>
+    </view>
+  </view>
+</template>
+
+<script>
+  export default {
+    onLoad: function() {
+    }
+  }
+</script>
+
+<style>
+  .content {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+  }
+
+  .logo {
+    height: 200rpx;
+    width: 200rpx;
+    margin-top: 200rpx;
+    margin-left: auto;
+    margin-right: auto;
+    margin-bottom: 50rpx;
+  }
+
+  .text-area {
+    display: flex;
+    justify-content: center;
+  }
+
+  .title {
+    font-size: 36rpx;
+    color: #8f8f94;
+  }
+</style>
diff --git a/yudao-ui-admin-uniapp/pages/login.vue b/yudao-ui-admin-uniapp/pages/login.vue
new file mode 100644
index 000000000..021e0530b
--- /dev/null
+++ b/yudao-ui-admin-uniapp/pages/login.vue
@@ -0,0 +1,182 @@
+<template>
+  <view class="normal-login-container">
+    <view class="logo-content align-center justify-center flex">
+      <image style="width: 100rpx;height: 100rpx;" :src="globalConfig.appInfo.logo" mode="widthFix">
+      </image>
+      <text class="title">芋道移动端登录</text>
+    </view>
+    <view class="login-form-content">
+      <view class="input-item flex align-center">
+        <view class="iconfont icon-user icon"></view>
+        <input v-model="loginForm.username" class="input" type="text" placeholder="请输入账号" maxlength="30" />
+      </view>
+      <view class="input-item flex align-center">
+        <view class="iconfont icon-password icon"></view>
+        <input v-model="loginForm.password" type="password" class="input" placeholder="请输入密码" maxlength="20" />
+      </view>
+      <view class="input-item flex align-center" v-if="captchaEnabled">
+        <view class="iconfont icon-code icon"></view>
+        <input v-model="loginForm.code" class="input" placeholder="请输入验证码" maxlength="5" />
+        <image :src="codeUrl" @click="getCode" class="login-code-img"></image>
+      </view>
+      <view class="action-btn">
+        <button @click="handleLogin" class="login-btn cu-btn block bg-blue lg round">登录</button>
+      </view>
+    </view>
+
+    <view class="xieyi text-center">
+      <text class="text-grey1">登录即代表同意</text>
+      <text @click="handleUserAgrement" class="text-blue">《用户协议》</text>
+      <text @click="handlePrivacy" class="text-blue">《隐私协议》</text>
+    </view>
+  </view>
+</template>
+
+<script>
+  import { getCodeImg } from '@/api/login'
+
+  export default {
+    data() {
+      return {
+        codeUrl: "",
+        captchaEnabled: true,
+        globalConfig: getApp().globalData.config,
+        loginForm: {
+          username: "admin",
+          password: "admin123",
+          code: "",
+          uuid: ''
+        }
+      }
+    },
+    created() {
+      this.getCode()
+    },
+    methods: {
+      // 隐私协议
+      handlePrivacy() {
+        let site = this.globalConfig.appInfo.agreements[0]
+        this.$tab.navigateTo(`/pages/common/webview/index?title=${site.title}&url=${site.url}`)
+      },
+      // 用户协议
+      handleUserAgrement() {
+        let site = this.globalConfig.appInfo.agreements[1]
+        this.$tab.navigateTo(`/pages/common/webview/index?title=${site.title}&url=${site.url}`)
+      },
+      // 获取图形验证码
+      getCode() {
+        getCodeImg().then(res => {
+          res = res.data;
+          this.captchaEnable = res.enable;
+          if (this.captchaEnable) {
+            this.codeUrl = "data:image/gif;base64," + res.img;
+            this.loginForm.uuid = res.uuid;
+          }
+        })
+      },
+      // 登录方法
+      async handleLogin() {
+        if (this.loginForm.username === "") {
+          this.$modal.msgError("请输入您的账号")
+        } else if (this.loginForm.password === "") {
+          this.$modal.msgError("请输入您的密码")
+        } else if (this.loginForm.code === "" && this.captchaEnabled) {
+          this.$modal.msgError("请输入验证码")
+        } else {
+          this.$modal.loading("登录中,请耐心等待...")
+          this.pwdLogin()
+        }
+      },
+      // 密码登录
+      async pwdLogin() {
+        this.$store.dispatch('Login', this.loginForm).then(() => {
+          this.$modal.closeLoading()
+          this.loginSuccess()
+        }).catch(() => {
+          if (this.captchaEnabled) {
+            this.getCode()
+          }
+        })
+      },
+      // 登录成功后,处理函数
+      loginSuccess(result) {
+        // 设置用户信息
+        this.$store.dispatch('GetInfo').then(res => {
+          this.$tab.reLaunch('/pages/index')
+        })
+      }
+    }
+  }
+</script>
+
+<style lang="scss">
+  page {
+    background-color: #ffffff;
+  }
+
+  .normal-login-container {
+    width: 100%;
+
+    .logo-content {
+      width: 100%;
+      font-size: 21px;
+      text-align: center;
+      padding-top: 15%;
+
+      image {
+        border-radius: 4px;
+      }
+
+      .title {
+        margin-left: 10px;
+      }
+    }
+
+    .login-form-content {
+      text-align: center;
+      margin: 20px auto;
+      margin-top: 15%;
+      width: 80%;
+
+      .input-item {
+        margin: 20px auto;
+        background-color: #f5f6f7;
+        height: 45px;
+        border-radius: 20px;
+
+        .icon {
+          font-size: 38rpx;
+          margin-left: 10px;
+          color: #999;
+        }
+
+        .input {
+          width: 100%;
+          font-size: 14px;
+          line-height: 20px;
+          text-align: left;
+          padding-left: 15px;
+        }
+
+      }
+
+      .login-btn {
+        margin-top: 40px;
+        height: 45px;
+      }
+
+      .xieyi {
+        color: #333;
+        margin-top: 20px;
+      }
+    }
+
+    .easyinput {
+      width: 100%;
+    }
+  }
+
+  .login-code-img {
+    height: 45px;
+  }
+</style>
diff --git a/yudao-ui-admin-uniapp/pages/mine/about/index.vue b/yudao-ui-admin-uniapp/pages/mine/about/index.vue
new file mode 100644
index 000000000..c5dd58aec
--- /dev/null
+++ b/yudao-ui-admin-uniapp/pages/mine/about/index.vue
@@ -0,0 +1,75 @@
+<template>
+  <view class="about-container">
+    <view class="header-section text-center">
+      <image style="width: 150rpx;height: 150rpx;" src="/static/logo200.png" mode="widthFix">
+      </image>
+      <uni-title type="h2" title="芋道移动端"></uni-title>
+    </view>
+
+    <view class="content-section">
+      <view class="menu-list">
+        <view class="list-cell list-cell-arrow">
+          <view class="menu-item-box">
+            <view>版本信息</view>
+            <view class="text-right">v{{version}}</view>
+          </view>
+        </view>
+        <view class="list-cell list-cell-arrow">
+          <view class="menu-item-box">
+            <view>官方邮箱</view>
+            <view class="text-right">7685413@qq.com</view>
+          </view>
+        </view>
+        <view class="list-cell list-cell-arrow">
+          <view class="menu-item-box">
+            <view>服务热线</view>
+            <view class="text-right">400-999-9999</view>
+          </view>
+        </view>
+        <view class="list-cell list-cell-arrow">
+          <view class="menu-item-box">
+            <view>公司网站</view>
+            <view class="text-right">
+              <uni-link :href="url" :text="url" showUnderLine="false"></uni-link>
+            </view>
+          </view>
+        </view>
+      </view>
+    </view>
+
+    <view class="copyright">
+      <view>Copyright &copy; 2022 iocoder.cn All Rights Reserved.</view>
+    </view>
+  </view>
+</template>
+
+<script>
+  export default {
+    data() {
+      return {
+        url: getApp().globalData.config.appInfo.site_url,
+        version: getApp().globalData.config.appInfo.version
+      }
+    }
+  }
+</script>
+
+<style lang="scss">
+  page {
+    background-color: #f8f8f8;
+  }
+
+  .copyright {
+    margin-top: 50rpx;
+    text-align: center;
+    line-height: 60rpx;
+    color: #999;
+  }
+
+  .header-section {
+    display: flex;
+    padding: 30rpx 0 0;
+    flex-direction: column;
+    align-items: center;
+  }
+</style>
diff --git a/yudao-ui-admin-uniapp/pages/mine/avatar/index.vue b/yudao-ui-admin-uniapp/pages/mine/avatar/index.vue
new file mode 100644
index 000000000..773148668
--- /dev/null
+++ b/yudao-ui-admin-uniapp/pages/mine/avatar/index.vue
@@ -0,0 +1,631 @@
+<template>
+	<view class="container">
+		<view class="page-body uni-content-info">
+			<view class='cropper-content'>
+				<view v-if="isShowImg" class="uni-corpper" :style="'width:'+cropperInitW+'px;height:'+cropperInitH+'px;background:#000'">
+					<view class="uni-corpper-content" :style="'width:'+cropperW+'px;height:'+cropperH+'px;left:'+cropperL+'px;top:'+cropperT+'px'">
+						<image :src="imageSrc" :style="'width:'+cropperW+'px;height:'+cropperH+'px'"></image>
+						<view class="uni-corpper-crop-box" @touchstart.stop="contentStartMove" @touchmove.stop="contentMoveing" @touchend.stop="contentTouchEnd"
+						    :style="'left:'+cutL+'px;top:'+cutT+'px;right:'+cutR+'px;bottom:'+cutB+'px'">
+							<view class="uni-cropper-view-box">
+								<view class="uni-cropper-dashed-h"></view>
+								<view class="uni-cropper-dashed-v"></view>
+								<view class="uni-cropper-line-t" data-drag="top" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view>
+								<view class="uni-cropper-line-r" data-drag="right" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view>
+								<view class="uni-cropper-line-b" data-drag="bottom" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view>
+								<view class="uni-cropper-line-l" data-drag="left" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view>
+								<view class="uni-cropper-point point-t" data-drag="top" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view>
+								<view class="uni-cropper-point point-tr" data-drag="topTight"></view>
+								<view class="uni-cropper-point point-r" data-drag="right" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view>
+								<view class="uni-cropper-point point-rb" data-drag="rightBottom" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view>
+								<view class="uni-cropper-point point-b" data-drag="bottom" @touchstart.stop="dragStart" @touchmove.stop="dragMove" @touchend.stop="dragEnd"></view>
+								<view class="uni-cropper-point point-bl" data-drag="bottomLeft"></view>
+								<view class="uni-cropper-point point-l" data-drag="left" @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view>
+								<view class="uni-cropper-point point-lt" data-drag="leftTop"></view>
+							</view>
+						</view>
+					</view>
+				</view>
+			</view>
+			<view class='cropper-config'>
+				<button type="primary reverse" @click="getImage" style='margin-top: 30rpx;'> 选择头像 </button>
+				<button type="warn" @click="getImageInfo" style='margin-top: 30rpx;'> 提交 </button>
+			</view>
+			<canvas canvas-id="myCanvas" :style="'position:absolute;border: 1px solid red; width:'+imageW+'px;height:'+imageH+'px;top:-9999px;left:-9999px;'"></canvas>
+		</view>
+	</view>
+</template>
+
+<script>
+  import config from '@/config'
+  import store from "@/store"
+  import { uploadAvatar } from "@/api/system/user"
+
+  const baseUrl = config.baseUrl
+	let sysInfo = uni.getSystemInfoSync()
+	let SCREEN_WIDTH = sysInfo.screenWidth
+	let PAGE_X, // 手按下的x位置
+		PAGE_Y, // 手按下y的位置
+		PR = sysInfo.pixelRatio, // dpi
+		T_PAGE_X, // 手移动的时候x的位置
+		T_PAGE_Y, // 手移动的时候Y的位置
+		CUT_L, // 初始化拖拽元素的left值
+		CUT_T, // 初始化拖拽元素的top值
+		CUT_R, // 初始化拖拽元素的
+		CUT_B, // 初始化拖拽元素的
+		CUT_W, // 初始化拖拽元素的宽度
+		CUT_H, //  初始化拖拽元素的高度
+		IMG_RATIO, // 图片比例
+		IMG_REAL_W, // 图片实际的宽度
+		IMG_REAL_H, // 图片实际的高度
+		DRAFG_MOVE_RATIO = 1, //移动时候的比例,
+		INIT_DRAG_POSITION = 100, // 初始化屏幕宽度和裁剪区域的宽度之差,用于设置初始化裁剪的宽度
+		DRAW_IMAGE_W = sysInfo.screenWidth // 设置生成的图片宽度
+
+	export default {
+		/**
+		 * 页面的初始数据
+		 */
+		data() {
+			return {
+				imageSrc: store.getters.avatar,
+				isShowImg: false,
+				// 初始化的宽高
+				cropperInitW: SCREEN_WIDTH,
+				cropperInitH: SCREEN_WIDTH,
+				// 动态的宽高
+				cropperW: SCREEN_WIDTH,
+				cropperH: SCREEN_WIDTH,
+				// 动态的left top值
+				cropperL: 0,
+				cropperT: 0,
+
+				transL: 0,
+				transT: 0,
+
+				// 图片缩放值
+				scaleP: 0,
+				imageW: 0,
+				imageH: 0,
+
+				// 裁剪框 宽高
+				cutL: 0,
+				cutT: 0,
+				cutB: SCREEN_WIDTH,
+				cutR: '100%',
+				qualityWidth: DRAW_IMAGE_W,
+				innerAspectRadio: DRAFG_MOVE_RATIO
+			}
+		},
+		/**
+		 * 生命周期函数--监听页面初次渲染完成
+		 */
+		onReady: function () {
+			this.loadImage()
+		},
+		methods: {
+			setData: function (obj) {
+				let that = this
+				Object.keys(obj).forEach(function (key) {
+					that.$set(that.$data, key, obj[key])
+				})
+			},
+			getImage: function () {
+				var _this = this
+				uni.chooseImage({
+					success: function (res) {
+						_this.setData({
+							imageSrc: res.tempFilePaths[0],
+						})
+						_this.loadImage()
+					},
+				})
+			},
+			loadImage: function () {
+				var _this = this
+
+				uni.getImageInfo({
+					src: _this.imageSrc,
+					success: function success(res) {
+						IMG_RATIO = 1 / 1
+						if (IMG_RATIO >= 1) {
+							IMG_REAL_W = SCREEN_WIDTH
+							IMG_REAL_H = SCREEN_WIDTH / IMG_RATIO
+						} else {
+							IMG_REAL_W = SCREEN_WIDTH * IMG_RATIO
+							IMG_REAL_H = SCREEN_WIDTH
+						}
+						let minRange = IMG_REAL_W > IMG_REAL_H ? IMG_REAL_W : IMG_REAL_H
+						INIT_DRAG_POSITION = minRange > INIT_DRAG_POSITION ? INIT_DRAG_POSITION : minRange
+						// 根据图片的宽高显示不同的效果   保证图片可以正常显示
+						if (IMG_RATIO >= 1) {
+							let cutT = Math.ceil((SCREEN_WIDTH / IMG_RATIO - (SCREEN_WIDTH / IMG_RATIO - INIT_DRAG_POSITION)) / 2)
+							let cutB = cutT
+							let cutL = Math.ceil((SCREEN_WIDTH - SCREEN_WIDTH + INIT_DRAG_POSITION) / 2)
+							let cutR = cutL
+							_this.setData({
+								cropperW: SCREEN_WIDTH,
+								cropperH: SCREEN_WIDTH / IMG_RATIO,
+								// 初始化left right
+								cropperL: Math.ceil((SCREEN_WIDTH - SCREEN_WIDTH) / 2),
+								cropperT: Math.ceil((SCREEN_WIDTH - SCREEN_WIDTH / IMG_RATIO) / 2),
+								cutL: cutL,
+								cutT: cutT,
+								cutR: cutR,
+								cutB: cutB,
+								// 图片缩放值
+								imageW: IMG_REAL_W,
+								imageH: IMG_REAL_H,
+								scaleP: IMG_REAL_W / SCREEN_WIDTH,
+								qualityWidth: DRAW_IMAGE_W,
+								innerAspectRadio: IMG_RATIO
+							})
+						} else {
+							let cutL = Math.ceil((SCREEN_WIDTH * IMG_RATIO - (SCREEN_WIDTH * IMG_RATIO)) / 2)
+							let cutR = cutL
+							let cutT = Math.ceil((SCREEN_WIDTH - INIT_DRAG_POSITION) / 2)
+							let cutB = cutT
+							_this.setData({
+								cropperW: SCREEN_WIDTH * IMG_RATIO,
+								cropperH: SCREEN_WIDTH,
+								// 初始化left right
+								cropperL: Math.ceil((SCREEN_WIDTH - SCREEN_WIDTH * IMG_RATIO) / 2),
+								cropperT: Math.ceil((SCREEN_WIDTH - SCREEN_WIDTH) / 2),
+
+								cutL: cutL,
+								cutT: cutT,
+								cutR: cutR,
+								cutB: cutB,
+								// 图片缩放值
+								imageW: IMG_REAL_W,
+								imageH: IMG_REAL_H,
+								scaleP: IMG_REAL_W / SCREEN_WIDTH,
+								qualityWidth: DRAW_IMAGE_W,
+								innerAspectRadio: IMG_RATIO
+							})
+						}
+						_this.setData({
+							isShowImg: true
+						})
+						uni.hideLoading()
+					}
+				})
+			},
+			// 拖动时候触发的touchStart事件
+			contentStartMove(e) {
+				PAGE_X = e.touches[0].pageX
+				PAGE_Y = e.touches[0].pageY
+			},
+
+			// 拖动时候触发的touchMove事件
+			contentMoveing(e) {
+				var _this = this
+				var dragLengthX = (PAGE_X - e.touches[0].pageX) * DRAFG_MOVE_RATIO
+				var dragLengthY = (PAGE_Y - e.touches[0].pageY) * DRAFG_MOVE_RATIO
+				// 左移
+				if (dragLengthX > 0) {
+					if (this.cutL - dragLengthX < 0) dragLengthX = this.cutL
+				} else {
+					if (this.cutR + dragLengthX < 0) dragLengthX = -this.cutR
+				}
+
+				if (dragLengthY > 0) {
+					if (this.cutT - dragLengthY < 0) dragLengthY = this.cutT
+				} else {
+					if (this.cutB + dragLengthY < 0) dragLengthY = -this.cutB
+				}
+				this.setData({
+					cutL: this.cutL - dragLengthX,
+					cutT: this.cutT - dragLengthY,
+					cutR: this.cutR + dragLengthX,
+					cutB: this.cutB + dragLengthY
+				})
+
+				PAGE_X = e.touches[0].pageX
+				PAGE_Y = e.touches[0].pageY
+			},
+
+			contentTouchEnd() {
+
+			},
+
+			// 获取图片
+			getImageInfo() {
+				var _this = this
+				uni.showLoading({
+					title: '图片生成中...',
+				})
+				// 将图片写入画布
+				const ctx = uni.createCanvasContext('myCanvas')
+				ctx.drawImage(_this.imageSrc, 0, 0, IMG_REAL_W, IMG_REAL_H)
+				ctx.draw(true, () => {
+					// 获取画布要裁剪的位置和宽度   均为百分比 * 画布中图片的宽度    保证了在微信小程序中裁剪的图片模糊  位置不对的问题 canvasT = (_this.cutT / _this.cropperH) * (_this.imageH / pixelRatio)
+					var canvasW = ((_this.cropperW - _this.cutL - _this.cutR) / _this.cropperW) * IMG_REAL_W
+					var canvasH = ((_this.cropperH - _this.cutT - _this.cutB) / _this.cropperH) * IMG_REAL_H
+					var canvasL = (_this.cutL / _this.cropperW) * IMG_REAL_W
+					var canvasT = (_this.cutT / _this.cropperH) * IMG_REAL_H
+					uni.canvasToTempFilePath({
+						x: canvasL,
+						y: canvasT,
+						width: canvasW,
+						height: canvasH,
+						destWidth: canvasW,
+						destHeight: canvasH,
+						quality: 0.5,
+						canvasId: 'myCanvas',
+						success: function (res) {
+							uni.hideLoading()
+							let data = {name: 'avatarFile', filePath: res.tempFilePath}
+							uploadAvatar(data).then(response => {
+								store.commit('SET_AVATAR', response.data)
+								uni.showToast({ title: "修改成功", icon: 'success' })
+								uni.navigateBack()
+							})
+						}
+					})
+				})
+			},
+			// 设置大小的时候触发的touchStart事件
+			dragStart(e) {
+				T_PAGE_X = e.touches[0].pageX
+				T_PAGE_Y = e.touches[0].pageY
+				CUT_L = this.cutL
+				CUT_R = this.cutR
+				CUT_B = this.cutB
+				CUT_T = this.cutT
+			},
+
+			// 设置大小的时候触发的touchMove事件
+			dragMove(e) {
+				var _this = this
+				var dragType = e.target.dataset.drag
+				switch (dragType) {
+					case 'right':
+						var dragLength = (T_PAGE_X - e.touches[0].pageX) * DRAFG_MOVE_RATIO
+						if (CUT_R + dragLength < 0) dragLength = -CUT_R
+						this.setData({
+							cutR: CUT_R + dragLength
+						})
+						break
+					case 'left':
+						var dragLength = (T_PAGE_X - e.touches[0].pageX) * DRAFG_MOVE_RATIO
+						if (CUT_L - dragLength < 0) dragLength = CUT_L
+						if ((CUT_L - dragLength) > (this.cropperW - this.cutR)) dragLength = CUT_L - (this.cropperW - this.cutR)
+						this.setData({
+							cutL: CUT_L - dragLength
+						})
+						break
+					case 'top':
+						var dragLength = (T_PAGE_Y - e.touches[0].pageY) * DRAFG_MOVE_RATIO
+						if (CUT_T - dragLength < 0) dragLength = CUT_T
+						if ((CUT_T - dragLength) > (this.cropperH - this.cutB)) dragLength = CUT_T - (this.cropperH - this.cutB)
+						this.setData({
+							cutT: CUT_T - dragLength
+						})
+						break
+					case 'bottom':
+						var dragLength = (T_PAGE_Y - e.touches[0].pageY) * DRAFG_MOVE_RATIO
+						if (CUT_B + dragLength < 0) dragLength = -CUT_B
+						this.setData({
+							cutB: CUT_B + dragLength
+						})
+						break
+					case 'rightBottom':
+						var dragLengthX = (T_PAGE_X - e.touches[0].pageX) * DRAFG_MOVE_RATIO
+						var dragLengthY = (T_PAGE_Y - e.touches[0].pageY) * DRAFG_MOVE_RATIO
+
+						if (CUT_B + dragLengthY < 0) dragLengthY = -CUT_B
+						if (CUT_R + dragLengthX < 0) dragLengthX = -CUT_R
+						let cutB = CUT_B + dragLengthY
+						let cutR = CUT_R + dragLengthX
+
+						this.setData({
+							cutB: cutB,
+							cutR: cutR
+						})
+						break
+					default:
+						break
+				}
+			}
+		}
+	}
+</script>
+
+<style>
+	/* pages/uni-cropper/index.wxss */
+
+	.uni-content-info {
+		/* position: fixed;
+		top: 0;
+		left: 0;
+		right: 0;
+		bottom: 0;
+		display: block;
+		align-items: center;
+		flex-direction: column; */
+	}
+
+	.cropper-config {
+		padding: 20rpx 40rpx;
+	}
+
+	.cropper-content {
+		min-height: 750rpx;
+		width: 100%;
+	}
+
+	.uni-corpper {
+		position: relative;
+		overflow: hidden;
+		-webkit-user-select: none;
+		-moz-user-select: none;
+		-ms-user-select: none;
+		user-select: none;
+		-webkit-tap-highlight-color: transparent;
+		-webkit-touch-callout: none;
+		box-sizing: border-box;
+	}
+
+	.uni-corpper-content {
+		position: relative;
+	}
+
+	.uni-corpper-content image {
+		display: block;
+		width: 100%;
+		min-width: 0 !important;
+		max-width: none !important;
+		height: 100%;
+		min-height: 0 !important;
+		max-height: none !important;
+		image-orientation: 0deg !important;
+		margin: 0 auto;
+	}
+	/* 移动图片效果 */
+
+	.uni-cropper-drag-box {
+		position: absolute;
+		top: 0;
+		right: 0;
+		bottom: 0;
+		left: 0;
+		cursor: move;
+		background: rgba(0, 0, 0, 0.6);
+		z-index: 1;
+	}
+	/* 内部的信息 */
+
+	.uni-corpper-crop-box {
+		position: absolute;
+		background: rgba(255, 255, 255, 0.3);
+		z-index: 2;
+	}
+
+	.uni-corpper-crop-box .uni-cropper-view-box {
+		position: relative;
+		display: block;
+		width: 100%;
+		height: 100%;
+		overflow: visible;
+		outline: 1rpx solid #69f;
+		outline-color: rgba(102, 153, 255, .75)
+	}
+	/* 横向虚线 */
+
+	.uni-cropper-dashed-h {
+		position: absolute;
+		top: 33.33333333%;
+		left: 0;
+		width: 100%;
+		height: 33.33333333%;
+		border-top: 1rpx dashed rgba(255, 255, 255, 0.5);
+		border-bottom: 1rpx dashed rgba(255, 255, 255, 0.5);
+	}
+	/* 纵向虚线 */
+
+	.uni-cropper-dashed-v {
+		position: absolute;
+		left: 33.33333333%;
+		top: 0;
+		width: 33.33333333%;
+		height: 100%;
+		border-left: 1rpx dashed rgba(255, 255, 255, 0.5);
+		border-right: 1rpx dashed rgba(255, 255, 255, 0.5);
+	}
+	/* 四个方向的线  为了之后的拖动事件*/
+
+	.uni-cropper-line-t {
+		position: absolute;
+		display: block;
+		width: 100%;
+		background-color: #69f;
+		top: 0;
+		left: 0;
+		height: 1rpx;
+		opacity: 0.1;
+		cursor: n-resize;
+	}
+
+	.uni-cropper-line-t::before {
+		content: '';
+		position: absolute;
+		top: 50%;
+		right: 0rpx;
+		width: 100%;
+		-webkit-transform: translate3d(0, -50%, 0);
+		transform: translate3d(0, -50%, 0);
+		bottom: 0;
+		height: 41rpx;
+		background: transparent;
+		z-index: 11;
+	}
+
+	.uni-cropper-line-r {
+		position: absolute;
+		display: block;
+		background-color: #69f;
+		top: 0;
+		right: 0rpx;
+		width: 1rpx;
+		opacity: 0.1;
+		height: 100%;
+		cursor: e-resize;
+	}
+
+	.uni-cropper-line-r::before {
+		content: '';
+		position: absolute;
+		top: 0;
+		left: 50%;
+		width: 41rpx;
+		-webkit-transform: translate3d(-50%, 0, 0);
+		transform: translate3d(-50%, 0, 0);
+		bottom: 0;
+		height: 100%;
+		background: transparent;
+		z-index: 11;
+	}
+
+	.uni-cropper-line-b {
+		position: absolute;
+		display: block;
+		width: 100%;
+		background-color: #69f;
+		bottom: 0;
+		left: 0;
+		height: 1rpx;
+		opacity: 0.1;
+		cursor: s-resize;
+	}
+
+	.uni-cropper-line-b::before {
+		content: '';
+		position: absolute;
+		top: 50%;
+		right: 0rpx;
+		width: 100%;
+		-webkit-transform: translate3d(0, -50%, 0);
+		transform: translate3d(0, -50%, 0);
+		bottom: 0;
+		height: 41rpx;
+		background: transparent;
+		z-index: 11;
+	}
+
+	.uni-cropper-line-l {
+		position: absolute;
+		display: block;
+		background-color: #69f;
+		top: 0;
+		left: 0;
+		width: 1rpx;
+		opacity: 0.1;
+		height: 100%;
+		cursor: w-resize;
+	}
+
+	.uni-cropper-line-l::before {
+		content: '';
+		position: absolute;
+		top: 0;
+		left: 50%;
+		width: 41rpx;
+		-webkit-transform: translate3d(-50%, 0, 0);
+		transform: translate3d(-50%, 0, 0);
+		bottom: 0;
+		height: 100%;
+		background: transparent;
+		z-index: 11;
+	}
+
+	.uni-cropper-point {
+		width: 5rpx;
+		height: 5rpx;
+		background-color: #69f;
+		opacity: .75;
+		position: absolute;
+		z-index: 3;
+	}
+
+	.point-t {
+		top: -3rpx;
+		left: 50%;
+		margin-left: -3rpx;
+		cursor: n-resize;
+	}
+
+	.point-tr {
+		top: -3rpx;
+		left: 100%;
+		margin-left: -3rpx;
+		cursor: n-resize;
+	}
+
+	.point-r {
+		top: 50%;
+		left: 100%;
+		margin-left: -3rpx;
+		margin-top: -3rpx;
+		cursor: n-resize;
+	}
+
+	.point-rb {
+		left: 100%;
+		top: 100%;
+		-webkit-transform: translate3d(-50%, -50%, 0);
+		transform: translate3d(-50%, -50%, 0);
+		cursor: n-resize;
+		width: 36rpx;
+		height: 36rpx;
+		background-color: #69f;
+		position: absolute;
+		z-index: 1112;
+		opacity: 1;
+	}
+
+	.point-b {
+		left: 50%;
+		top: 100%;
+		margin-left: -3rpx;
+		margin-top: -3rpx;
+		cursor: n-resize;
+	}
+
+	.point-bl {
+		left: 0%;
+		top: 100%;
+		margin-left: -3rpx;
+		margin-top: -3rpx;
+		cursor: n-resize;
+	}
+
+	.point-l {
+		left: 0%;
+		top: 50%;
+		margin-left: -3rpx;
+		margin-top: -3rpx;
+		cursor: n-resize;
+	}
+
+	.point-lt {
+		left: 0%;
+		top: 0%;
+		margin-left: -3rpx;
+		margin-top: -3rpx;
+		cursor: n-resize;
+	}
+	/* 裁剪框预览内容 */
+
+	.uni-cropper-viewer {
+		position: relative;
+		width: 100%;
+		height: 100%;
+		overflow: hidden;
+	}
+
+	.uni-cropper-viewer image {
+		position: absolute;
+		z-index: 2;
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/pages/mine/help/index.vue b/yudao-ui-admin-uniapp/pages/mine/help/index.vue
new file mode 100644
index 000000000..4cffe5550
--- /dev/null
+++ b/yudao-ui-admin-uniapp/pages/mine/help/index.vue
@@ -0,0 +1,112 @@
+<template>
+  <view class="help-container">
+    <view v-for="(item, findex) in list" :key="findex" :title="item.title" class="list-title">
+      <view class="text-title">
+        <view :class="item.icon"></view>{{ item.title }}
+      </view>
+      <view class="childList">
+        <view v-for="(child, zindex) in item.childList" :key="zindex" class="question" hover-class="hover"
+          @click="handleText(child)">
+          <view class="text-item">{{ child.title }}</view>
+          <view class="line" v-if="zindex !== item.childList.length - 1"></view>
+        </view>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+  export default {
+    data() {
+      return {
+        list: [{
+            icon: 'iconfont icon-github',
+            title: '芋道问题',
+            childList: [{
+              title: '芋道开源吗?',
+              content: '开源'
+            }, {
+              title: '芋道可以商用吗?',
+              content: '可以'
+            }, {
+              title: '芋道官网地址多少?',
+              content: 'https://www.iocoder.cn'
+            }, {
+              title: '芋道文档地址多少?',
+              content: 'https://doc.iocoder.cn'
+            }]
+          },
+          {
+            icon: 'iconfont icon-help',
+            title: '其他问题',
+            childList: [{
+              title: '如何退出登录?',
+              content: '请点击[我的] - [应用设置] - [退出登录]即可退出登录',
+            }, {
+              title: '如何修改用户头像?',
+              content: '请点击[我的] - [选择头像] - [点击提交]即可更换用户头像',
+            }, {
+              title: '如何修改登录密码?',
+              content: '请点击[我的] - [应用设置] - [修改密码]即可修改登录密码',
+            }]
+          }
+        ]
+      }
+    },
+    methods: {
+      handleText(item) {
+        this.$tab.navigateTo(`/pages/common/textview/index?title=${item.title}&content=${item.content}`)
+      }
+    }
+  }
+</script>
+
+<style lang="scss" scoped>
+  page {
+    background-color: #f8f8f8;
+  }
+
+  .help-container {
+    margin-bottom: 100rpx;
+    padding: 30rpx;
+  }
+
+  .list-title {
+    margin-bottom: 30rpx;
+  }
+
+  .childList {
+    background: #ffffff;
+    box-shadow: 0px 0px 10rpx rgba(193, 193, 193, 0.2);
+    border-radius: 16rpx;
+    margin-top: 10rpx;
+  }
+
+  .line {
+    width: 100%;
+    height: 1rpx;
+    background-color: #F5F5F5;
+  }
+
+  .text-title {
+    color: #303133;
+    font-size: 32rpx;
+    font-weight: bold;
+    margin-left: 10rpx;
+
+    .iconfont {
+      font-size: 16px;
+      margin-right: 10rpx;
+    }
+  }
+
+  .text-item {
+    font-size: 28rpx;
+    padding: 24rpx;
+  }
+
+  .question {
+    color: #606266;
+    font-size: 28rpx;
+  }
+</style>
diff --git a/yudao-ui-admin-uniapp/pages/mine/index.vue b/yudao-ui-admin-uniapp/pages/mine/index.vue
new file mode 100644
index 000000000..42e2120df
--- /dev/null
+++ b/yudao-ui-admin-uniapp/pages/mine/index.vue
@@ -0,0 +1,198 @@
+<template>
+  <view class="mine-container" :style="{height: `${windowHeight}px`}">
+    <!--顶部个人信息栏-->
+    <view class="header-section">
+      <view class="flex padding justify-between">
+        <view class="flex align-center">
+          <view v-if="!avatar" class="cu-avatar xl round bg-white">
+            <view class="iconfont icon-people text-gray icon"></view>
+          </view>
+          <image v-if="avatar" @click="handleToAvatar" :src="avatar" class="cu-avatar xl round" mode="widthFix">
+          </image>
+          <view v-if="!name" @click="handleToLogin" class="login-tip">
+            点击登录
+          </view>
+          <view v-if="name" @click="handleToInfo" class="user-info">
+            <view class="u_title">
+              用户名:{{ name }}
+            </view>
+          </view>
+        </view>
+        <view @click="handleToInfo" class="flex align-center">
+          <text>个人信息</text>
+          <view class="iconfont icon-right"></view>
+        </view>
+      </view>
+    </view>
+
+    <view class="content-section">
+      <view class="mine-actions grid col-4 text-center">
+        <view class="action-item" @click="handleJiaoLiuQun">
+          <view class="iconfont icon-friendfill text-pink icon"></view>
+          <text class="text">交流群</text>
+        </view>
+        <view class="action-item" @click="handleBuilding">
+          <view class="iconfont icon-service text-blue icon"></view>
+          <text class="text">在线客服</text>
+        </view>
+        <view class="action-item" @click="handleBuilding">
+          <view class="iconfont icon-community text-mauve icon"></view>
+          <text class="text">反馈社区</text>
+        </view>
+        <view class="action-item" @click="handleBuilding">
+          <view class="iconfont icon-dianzan text-green icon"></view>
+          <text class="text">点赞我们</text>
+        </view>
+      </view>
+
+      <view class="menu-list">
+        <view class="list-cell list-cell-arrow" @click="handleToEditInfo">
+          <view class="menu-item-box">
+            <view class="iconfont icon-user menu-icon"></view>
+            <view>编辑资料</view>
+          </view>
+        </view>
+        <view class="list-cell list-cell-arrow" @click="handleHelp">
+          <view class="menu-item-box">
+            <view class="iconfont icon-help menu-icon"></view>
+            <view>常见问题</view>
+          </view>
+        </view>
+        <view class="list-cell list-cell-arrow" @click="handleAbout">
+          <view class="menu-item-box">
+            <view class="iconfont icon-aixin menu-icon"></view>
+            <view>关于我们</view>
+          </view>
+        </view>
+        <view class="list-cell list-cell-arrow" @click="handleToSetting">
+          <view class="menu-item-box">
+            <view class="iconfont icon-setting menu-icon"></view>
+            <view>应用设置</view>
+          </view>
+        </view>
+      </view>
+
+    </view>
+  </view>
+</template>
+
+<script>
+  import storage from '@/utils/storage'
+
+  export default {
+    data() {
+      return {
+        name: this.$store.state.user.name,
+        version: getApp().globalData.config.appInfo.version
+      }
+    },
+    computed: {
+      avatar() {
+        return this.$store.state.user.avatar
+      },
+      windowHeight() {
+        return uni.getSystemInfoSync().windowHeight - 50
+      }
+    },
+    methods: {
+      handleToInfo() {
+        this.$tab.navigateTo('/pages/mine/info/index')
+      },
+      handleToEditInfo() {
+        this.$tab.navigateTo('/pages/mine/info/edit')
+      },
+      handleToSetting() {
+        this.$tab.navigateTo('/pages/mine/setting/index')
+      },
+      handleToLogin() {
+        this.$tab.reLaunch('/pages/login')
+      },
+      handleToAvatar() {
+        this.$tab.navigateTo('/pages/mine/avatar/index')
+      },
+      handleLogout() {
+        this.$modal.confirm('确定注销并退出系统吗?').then(() => {
+          this.$store.dispatch('LogOut').then(() => {
+            this.$tab.reLaunch('/pages/index')
+          })
+        })
+      },
+      handleHelp() {
+        this.$tab.navigateTo('/pages/mine/help/index')
+      },
+      handleAbout() {
+        this.$tab.navigateTo('/pages/mine/about/index')
+      },
+      handleJiaoLiuQun() {
+        this.$modal.showToast('微信搜索 naidaguo 后,添加好友后拉你进技术交流群')
+      },
+      handleBuilding() {
+        this.$modal.showToast('模块建设中~')
+      }
+    }
+  }
+</script>
+
+<style lang="scss">
+  page {
+    background-color: #f5f6f7;
+  }
+
+  .mine-container {
+    width: 100%;
+    height: 100%;
+
+
+    .header-section {
+      padding: 15px 15px 45px 15px;
+      background-color: #3c96f3;
+      color: white;
+
+      .login-tip {
+        font-size: 18px;
+        margin-left: 10px;
+      }
+
+      .cu-avatar {
+        border: 2px solid #eaeaea;
+
+        .icon {
+          font-size: 40px;
+        }
+      }
+
+      .user-info {
+        margin-left: 15px;
+
+        .u_title {
+          font-size: 18px;
+          line-height: 30px;
+        }
+      }
+    }
+
+    .content-section {
+      position: relative;
+      top: -50px;
+
+      .mine-actions {
+        margin: 15px 15px;
+        padding: 20px 0px;
+        border-radius: 8px;
+        background-color: white;
+
+        .action-item {
+          .icon {
+            font-size: 28px;
+          }
+
+          .text {
+            display: block;
+            font-size: 13px;
+            margin: 8px 0px;
+          }
+        }
+      }
+    }
+  }
+</style>
diff --git a/yudao-ui-admin-uniapp/pages/mine/info/edit.vue b/yudao-ui-admin-uniapp/pages/mine/info/edit.vue
new file mode 100644
index 000000000..44d8ce4c0
--- /dev/null
+++ b/yudao-ui-admin-uniapp/pages/mine/info/edit.vue
@@ -0,0 +1,128 @@
+<template>
+  <view class="container">
+    <view class="example">
+      <uni-forms ref="form" :model="user" labelWidth="80px">
+        <uni-forms-item label="用户昵称" name="nickname">
+          <uni-easyinput v-model="user.nickname" placeholder="请输入昵称" />
+        </uni-forms-item>
+        <uni-forms-item label="手机号码" name="mobile">
+          <uni-easyinput v-model="user.mobile" placeholder="请输入手机号码" />
+        </uni-forms-item>
+        <uni-forms-item label="邮箱" name="email">
+          <uni-easyinput v-model="user.email" placeholder="请输入邮箱" />
+        </uni-forms-item>
+        <!-- TODO 芋艿:uni-data-checkbox 存在问题 -->
+        <uni-forms-item label="性别" name="sex" required>
+<!--          <uni-data-checkbox v-model="user.sex" :localdata="sexs" />-->
+        </uni-forms-item>
+      </uni-forms>
+      <button type="primary" @click="submit">提交</button>
+    </view>
+  </view>
+</template>
+
+<script>
+  import { getUserProfile } from "@/api/system/user"
+  import { updateUserProfile } from "@/api/system/user"
+
+  export default {
+    data() {
+      return {
+        user: {
+          nickname: "",
+          mobile: "",
+          email: "",
+          sex: ""
+        },
+        sexs: [{
+          text: '男',
+          value: "1"
+        }, {
+          text: '女',
+          value: "2"
+        }],
+        rules: {
+          nickname: {
+            rules: [{
+              required: true,
+              errorMessage: '用户昵称不能为空'
+            }]
+          },
+          mobile: {
+            rules: [{
+              required: true,
+              errorMessage: '手机号码不能为空'
+            }, {
+              pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
+              errorMessage: '请输入正确的手机号码'
+            }]
+          },
+          email: {
+            rules: [{
+              required: true,
+              errorMessage: '邮箱地址不能为空'
+            }, {
+              format: 'email',
+              errorMessage: '请输入正确的邮箱地址'
+            }]
+          }
+        }
+      }
+    },
+    onLoad() {
+      this.getUser()
+    },
+    onReady() {
+      this.$refs.form.setRules(this.rules)
+    },
+    methods: {
+      getUser() {
+        getUserProfile().then(response => {
+          this.user = response.data
+        })
+      },
+      submit(ref) {
+        this.$refs.form.validate().then(res => {
+          updateUserProfile(this.user).then(response => {
+            this.$modal.msgSuccess("修改成功")
+          })
+        })
+      }
+    }
+  }
+</script>
+
+<style lang="scss">
+  page {
+    background-color: #ffffff;
+  }
+
+  .example {
+    padding: 15px;
+    background-color: #fff;
+  }
+
+  .segmented-control {
+    margin-bottom: 15px;
+  }
+
+  .button-group {
+    margin-top: 15px;
+    display: flex;
+    justify-content: space-around;
+  }
+
+  .form-item {
+    display: flex;
+    align-items: center;
+    flex: 1;
+  }
+
+  .button {
+    display: flex;
+    align-items: center;
+    height: 35px;
+    line-height: 35px;
+    margin-left: 10px;
+  }
+</style>
diff --git a/yudao-ui-admin-uniapp/pages/mine/info/index.vue b/yudao-ui-admin-uniapp/pages/mine/info/index.vue
new file mode 100644
index 000000000..2e519e8f5
--- /dev/null
+++ b/yudao-ui-admin-uniapp/pages/mine/info/index.vue
@@ -0,0 +1,44 @@
+<template>
+  <view class="container">
+    <uni-list>
+      <uni-list-item showExtraIcon="true" :extraIcon="{type: 'person-filled'}" title="昵称" :rightText="user.nickname" />
+      <uni-list-item showExtraIcon="true" :extraIcon="{type: 'phone-filled'}" title="手机号码" :rightText="user.mobile" />
+      <uni-list-item showExtraIcon="true" :extraIcon="{type: 'email-filled'}" title="邮箱" :rightText="user.email" />
+      <uni-list-item showExtraIcon="true" :extraIcon="{type: 'auth-filled'}" title="岗位" :rightText="(user.posts || []).map(post => post.name).join(',')" />
+      <uni-list-item showExtraIcon="true" :extraIcon="{type: 'staff-filled'}" title="角色" :rightText="(user.roles || []).map(role => role.name).join(',')" />
+      <uni-list-item showExtraIcon="true" :extraIcon="{type: 'calendar-filled'}" title="创建日期" :rightText="this.parseTime(user.createTime)" />
+    </uni-list>
+  </view>
+</template>
+
+<script>
+  import { getUserProfile } from "@/api/system/user"
+  import { parseTime } from "@/utils/ruoyi"
+
+  export default {
+    data() {
+      return {
+        user: {}
+      }
+    },
+    onLoad() {
+      this.getUser()
+    },
+    methods: {
+      getUser() {
+        getUserProfile().then(response => {
+          this.user = response.data
+        })
+      },
+      parseTime(time) {
+        return parseTime(time)
+      }
+    }
+  }
+</script>
+
+<style lang="scss">
+  page {
+    background-color: #ffffff;
+  }
+</style>
diff --git a/yudao-ui-admin-uniapp/pages/mine/pwd/index.vue b/yudao-ui-admin-uniapp/pages/mine/pwd/index.vue
new file mode 100644
index 000000000..da9567f5f
--- /dev/null
+++ b/yudao-ui-admin-uniapp/pages/mine/pwd/index.vue
@@ -0,0 +1,85 @@
+<template>
+  <view class="pwd-retrieve-container">
+    <uni-forms ref="form" :value="user" labelWidth="80px">
+      <uni-forms-item name="oldPassword" label="旧密码">
+        <uni-easyinput type="password" v-model="user.oldPassword" placeholder="请输入旧密码" />
+      </uni-forms-item>
+      <uni-forms-item name="newPassword" label="新密码">
+        <uni-easyinput type="password" v-model="user.newPassword" placeholder="请输入新密码" />
+      </uni-forms-item>
+      <uni-forms-item name="confirmPassword" label="确认密码">
+        <uni-easyinput type="password" v-model="user.confirmPassword" placeholder="请确认新密码" />
+      </uni-forms-item>
+      <button type="primary" @click="submit">提交</button>
+    </uni-forms>
+  </view>
+</template>
+
+<script>
+  import { updateUserPwd } from "@/api/system/user"
+
+  export default {
+    data() {
+      return {
+        user: {
+          oldPassword: undefined,
+          newPassword: undefined,
+          confirmPassword: undefined
+        },
+        rules: {
+          oldPassword: {
+            rules: [{
+              required: true,
+              errorMessage: '旧密码不能为空'
+            }]
+          },
+          newPassword: {
+            rules: [{
+                required: true,
+                errorMessage: '新密码不能为空',
+              },
+              {
+                minLength: 6,
+                maxLength: 20,
+                errorMessage: '长度在 6 到 20 个字符'
+              }
+            ]
+          },
+          confirmPassword: {
+            rules: [{
+                required: true,
+                errorMessage: '确认密码不能为空'
+              }, {
+                validateFunction: (rule, value, data) => data.newPassword === value,
+                errorMessage: '两次输入的密码不一致'
+              }
+            ]
+          }
+        }
+      }
+    },
+    onReady() {
+      this.$refs.form.setRules(this.rules)
+    },
+    methods: {
+      submit() {
+        this.$refs.form.validate().then(res => {
+          updateUserPwd(this.user.oldPassword, this.user.newPassword).then(response => {
+            this.$modal.msgSuccess("修改成功")
+          })
+        })
+      }
+    }
+  }
+</script>
+
+<style lang="scss">
+  page {
+    background-color: #ffffff;
+  }
+
+  .pwd-retrieve-container {
+    padding-top: 36rpx;
+    padding: 15px;
+  }
+</style>
diff --git a/yudao-ui-admin-uniapp/pages/mine/setting/index.vue b/yudao-ui-admin-uniapp/pages/mine/setting/index.vue
new file mode 100644
index 000000000..0f9f058ea
--- /dev/null
+++ b/yudao-ui-admin-uniapp/pages/mine/setting/index.vue
@@ -0,0 +1,78 @@
+<template>
+  <view class="setting-container" :style="{height: `${windowHeight}px`}">
+    <view class="menu-list">
+      <view class="list-cell list-cell-arrow" @click="handleToPwd">
+        <view class="menu-item-box">
+          <view class="iconfont icon-password menu-icon"></view>
+          <view>修改密码</view>
+        </view>
+      </view>
+      <view class="list-cell list-cell-arrow" @click="handleToUpgrade">
+        <view class="menu-item-box">
+          <view class="iconfont icon-refresh menu-icon"></view>
+          <view>检查更新</view>
+        </view>
+      </view>
+      <view class="list-cell list-cell-arrow" @click="handleCleanTmp">
+        <view class="menu-item-box">
+          <view class="iconfont icon-clean menu-icon"></view>
+          <view>清理缓存</view>
+        </view>
+      </view>
+    </view>
+    <view class="cu-list menu">
+      <view class="cu-item item-box">
+        <view class="content text-center" @click="handleLogout">
+          <text class="text-black">退出登录</text>
+        </view>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script>
+  export default {
+    data() {
+      return {
+        windowHeight: uni.getSystemInfoSync().windowHeight
+      }
+    },
+    methods: {
+      handleToPwd() {
+        this.$tab.navigateTo('/pages/mine/pwd/index')
+      },
+      handleToUpgrade() {
+        this.$modal.showToast('模块建设中~')
+      },
+      handleCleanTmp() {
+        this.$modal.showToast('模块建设中~')
+      },
+      handleLogout() {
+        this.$modal.confirm('确定注销并退出系统吗?').then(() => {
+          this.$store.dispatch('LogOut').then(() => {
+            this.$tab.reLaunch('/pages/index')
+          })
+        })
+      }
+    }
+  }
+</script>
+
+<style lang="scss" scoped>
+  .page {
+    background-color: #f8f8f8;
+  }
+
+  .item-box {
+    background-color: #FFFFFF;
+    margin: 30rpx;
+    display: flex;
+    flex-direction: row;
+    justify-content: center;
+    align-items: center;
+    padding: 10rpx;
+    border-radius: 8rpx;
+    color: #303133;
+    font-size: 32rpx;
+  }
+</style>
diff --git a/yudao-ui-admin-uniapp/pages/work/index.vue b/yudao-ui-admin-uniapp/pages/work/index.vue
new file mode 100644
index 000000000..1afefc915
--- /dev/null
+++ b/yudao-ui-admin-uniapp/pages/work/index.vue
@@ -0,0 +1,183 @@
+<template>
+  <view class="work-container">
+    <!-- 轮播图 -->
+    <uni-swiper-dot class="uni-swiper-dot-box" :info="data" :current="current" field="content">
+      <swiper class="swiper-box" :current="swiperDotIndex" @change="changeSwiper">
+        <swiper-item v-for="(item, index) in data" :key="index">
+          <view class="swiper-item" @click="clickBannerItem(item)">
+            <image :src="item.image" mode="aspectFill" :draggable="false" />
+          </view>
+        </swiper-item>
+      </swiper>
+    </uni-swiper-dot>
+
+    <!-- 宫格组件 -->
+    <uni-section title="系统管理" type="line"></uni-section>
+    <view class="grid-body">
+      <uni-grid :column="4" :showBorder="false" @change="changeGrid">
+        <uni-grid-item>
+          <view class="grid-item-box">
+            <uni-icons type="person-filled" size="30"></uni-icons>
+            <text class="text">用户管理</text>
+          </view>
+        </uni-grid-item>
+        <uni-grid-item>
+          <view class="grid-item-box">
+            <uni-icons type="staff-filled" size="30"></uni-icons>
+            <text class="text">角色管理</text>
+          </view>
+        </uni-grid-item>
+        <uni-grid-item>
+          <view class="grid-item-box">
+            <uni-icons type="color" size="30"></uni-icons>
+            <text class="text">菜单管理</text>
+          </view>
+        </uni-grid-item>
+        <uni-grid-item>
+          <view class="grid-item-box">
+            <uni-icons type="settings-filled" size="30"></uni-icons>
+            <text class="text">部门管理</text>
+          </view>
+        </uni-grid-item>
+        <uni-grid-item>
+          <view class="grid-item-box">
+            <uni-icons type="heart-filled" size="30"></uni-icons>
+            <text class="text">岗位管理</text>
+          </view>
+        </uni-grid-item>
+        <uni-grid-item>
+          <view class="grid-item-box">
+            <uni-icons type="bars" size="30"></uni-icons>
+            <text class="text">字典管理</text>
+          </view>
+        </uni-grid-item>
+        <uni-grid-item>
+          <view class="grid-item-box">
+            <uni-icons type="gear-filled" size="30"></uni-icons>
+            <text class="text">参数设置</text>
+          </view>
+        </uni-grid-item>
+        <uni-grid-item>
+          <view class="grid-item-box">
+            <uni-icons type="chat-filled" size="30"></uni-icons>
+            <text class="text">通知公告</text>
+          </view>
+        </uni-grid-item>
+        <uni-grid-item>
+          <view class="grid-item-box">
+            <uni-icons type="wallet-filled" size="30"></uni-icons>
+            <text class="text">日志管理</text>
+          </view>
+        </uni-grid-item>
+      </uni-grid>
+    </view>
+  </view>
+</template>
+
+<script>
+  export default {
+    data() {
+      return {
+        current: 0,
+        swiperDotIndex: 0,
+        data: [{
+            image: '/static/images/banner/banner01.jpg'
+          },
+          {
+            image: '/static/images/banner/banner02.jpg'
+          },
+          {
+            image: '/static/images/banner/banner03.jpg'
+          }
+        ]
+      }
+    },
+    methods: {
+      clickBannerItem(item) {
+        console.info(item)
+      },
+      changeSwiper(e) {
+        this.current = e.detail.current
+      },
+      changeGrid(e) {
+        this.$modal.showToast('模块建设中~')
+      }
+    }
+  }
+</script>
+
+<style lang="scss">
+  /* #ifndef APP-NVUE */
+  page {
+    display: flex;
+    flex-direction: column;
+    box-sizing: border-box;
+    background-color: #fff;
+    min-height: 100%;
+    height: auto;
+  }
+
+  view {
+    font-size: 14px;
+    line-height: inherit;
+  }
+
+  /* #endif */
+
+  .text {
+    text-align: center;
+    font-size: 26rpx;
+    margin-top: 10rpx;
+  }
+
+  .grid-item-box {
+    flex: 1;
+    /* #ifndef APP-NVUE */
+    display: flex;
+    /* #endif */
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    padding: 15px 0;
+  }
+
+  .uni-margin-wrap {
+    width: 690rpx;
+    width: 100%;
+    ;
+  }
+
+  .swiper {
+    height: 300rpx;
+  }
+
+  .swiper-box {
+    height: 150px;
+  }
+
+  .swiper-item {
+    /* #ifndef APP-NVUE */
+    display: flex;
+    /* #endif */
+    flex-direction: column;
+    justify-content: center;
+    align-items: center;
+    color: #fff;
+    height: 300rpx;
+    line-height: 300rpx;
+  }
+
+  @media screen and (min-width: 500px) {
+    .uni-swiper-dot-box {
+      width: 400px;
+      /* #ifndef APP-NVUE */
+      margin: 0 auto;
+      /* #endif */
+      margin-top: 8px;
+    }
+
+    .image {
+      width: 100%;
+    }
+  }
+</style>
diff --git a/yudao-ui-admin-uniapp/permission.js b/yudao-ui-admin-uniapp/permission.js
new file mode 100644
index 000000000..a47d94738
--- /dev/null
+++ b/yudao-ui-admin-uniapp/permission.js
@@ -0,0 +1,39 @@
+import { getAccessToken } from '@/utils/auth'
+
+// 登录页面
+const loginPage = "/pages/login"
+
+// 页面白名单
+const whiteList = [
+  '/pages/login', '/pages/common/webview/index'
+]
+
+// 检查地址白名单
+function checkWhite(url) {
+  const path = url.split('?')[0]
+  return whiteList.indexOf(path) !== -1
+}
+
+// 页面跳转验证拦截器
+let list = ["navigateTo", "redirectTo", "reLaunch", "switchTab"]
+list.forEach(item => {
+  uni.addInterceptor(item, {
+    invoke(to) {
+      if (getAccessToken()) {
+        if (to.path === loginPage) {
+          uni.reLaunch({ url: "/" })
+        }
+        return true
+      } else {
+        if (checkWhite(to.url)) {
+          return true
+        }
+        uni.reLaunch({ url: loginPage })
+        return false
+      }
+    },
+    fail(err) {
+      console.log(err)
+    }
+  })
+})
diff --git a/yudao-ui-admin-uniapp/plugins/auth.js b/yudao-ui-admin-uniapp/plugins/auth.js
new file mode 100644
index 000000000..3b91c14ef
--- /dev/null
+++ b/yudao-ui-admin-uniapp/plugins/auth.js
@@ -0,0 +1,60 @@
+import store from '@/store'
+
+function authPermission(permission) {
+  const all_permission = "*:*:*"
+  const permissions = store.getters && store.getters.permissions
+  if (permission && permission.length > 0) {
+    return permissions.some(v => {
+      return all_permission === v || v === permission
+    })
+  } else {
+    return false
+  }
+}
+
+function authRole(role) {
+  const super_admin = "admin"
+  const roles = store.getters && store.getters.roles
+  if (role && role.length > 0) {
+    return roles.some(v => {
+      return super_admin === v || v === role
+    })
+  } else {
+    return false
+  }
+}
+
+export default {
+  // 验证用户是否具备某权限
+  hasPermi(permission) {
+    return authPermission(permission)
+  },
+  // 验证用户是否含有指定权限,只需包含其中一个
+  hasPermiOr(permissions) {
+    return permissions.some(item => {
+      return authPermission(item)
+    })
+  },
+  // 验证用户是否含有指定权限,必须全部拥有
+  hasPermiAnd(permissions) {
+    return permissions.every(item => {
+      return authPermission(item)
+    })
+  },
+  // 验证用户是否具备某角色
+  hasRole(role) {
+    return authRole(role)
+  },
+  // 验证用户是否含有指定角色,只需包含其中一个
+  hasRoleOr(roles) {
+    return roles.some(item => {
+      return authRole(item)
+    })
+  },
+  // 验证用户是否含有指定角色,必须全部拥有
+  hasRoleAnd(roles) {
+    return roles.every(item => {
+      return authRole(item)
+    })
+  }
+}
diff --git a/yudao-ui-admin-uniapp/plugins/index.js b/yudao-ui-admin-uniapp/plugins/index.js
new file mode 100644
index 000000000..efbae151d
--- /dev/null
+++ b/yudao-ui-admin-uniapp/plugins/index.js
@@ -0,0 +1,14 @@
+import tab from './tab'
+import auth from './auth'
+import modal from './modal'
+
+export default {
+  install(Vue) {
+    // 页签操作
+    Vue.prototype.$tab = tab
+    // 认证对象
+    Vue.prototype.$auth = auth
+    // 模态框对象
+    Vue.prototype.$modal = modal
+  }
+}
diff --git a/yudao-ui-admin-uniapp/plugins/modal.js b/yudao-ui-admin-uniapp/plugins/modal.js
new file mode 100644
index 000000000..87960fd40
--- /dev/null
+++ b/yudao-ui-admin-uniapp/plugins/modal.js
@@ -0,0 +1,74 @@
+export default {
+  // 消息提示
+  msg(content) {
+    uni.showToast({
+      title: content,
+      icon: 'none'
+    })
+  },
+  // 错误消息
+  msgError(content) {
+    uni.showToast({
+      title: content,
+      icon: 'error'
+    })
+  },
+  // 成功消息
+  msgSuccess(content) {
+    uni.showToast({
+      title: content,
+      icon: 'success'
+    })
+  },
+  // 隐藏消息
+  hideMsg(content) {
+    uni.hideToast()
+  },
+  // 弹出提示
+  alert(content) {
+    uni.showModal({
+      title: '提示',
+      content: content,
+      showCancel: false
+    })
+  },
+  // 确认窗体
+  confirm(content) {
+    return new Promise((resolve, reject) => {
+      uni.showModal({
+        title: '系统提示',
+        content: content,
+        cancelText: '取消',
+        confirmText: '确定',
+        success: function(res) {
+          if (res.confirm) {
+            resolve(res.confirm)
+          }
+        }
+      })
+    })
+  },
+  // 提示信息
+  showToast(option) {
+    if (typeof option === "object") {
+      uni.showToast(option)
+    } else {
+      uni.showToast({
+        title: option,
+        icon: "none",
+        duration: 2500
+      })
+    }
+  },
+  // 打开遮罩层
+  loading(content) {
+    uni.showLoading({
+      title: content,
+      icon: 'none'
+    })
+  },
+  // 关闭遮罩层
+  closeLoading() {
+    uni.hideLoading()
+  }
+}
diff --git a/yudao-ui-admin-uniapp/plugins/tab.js b/yudao-ui-admin-uniapp/plugins/tab.js
new file mode 100644
index 000000000..5d1b30580
--- /dev/null
+++ b/yudao-ui-admin-uniapp/plugins/tab.js
@@ -0,0 +1,30 @@
+export default {
+  // 关闭所有页面,打开到应用内的某个页面
+  reLaunch(url) {
+    return uni.reLaunch({
+      url: url
+    })
+  },
+  // 跳转到tabBar页面,并关闭其他所有非tabBar页面
+  switchTab(url) {
+    return uni.switchTab({
+      url: url
+    })
+  },
+  // 关闭当前页面,跳转到应用内的某个页面
+  redirectTo(url) {
+    return uni.redirectTo({
+      url: url
+    })
+  },
+  // 保留当前页面,跳转到应用内的某个页面
+  navigateTo(url) {
+    return uni.navigateTo({
+      url: url
+    })
+  },
+  // 关闭当前页面,返回上一页面或多级页面
+  navigateBack() {
+    return uni.navigateBack()
+  }
+}
diff --git a/yudao-ui-admin-uniapp/static/favicon.ico b/yudao-ui-admin-uniapp/static/favicon.ico
new file mode 100644
index 000000000..6f07782ab
Binary files /dev/null and b/yudao-ui-admin-uniapp/static/favicon.ico differ
diff --git a/yudao-ui-admin-uniapp/static/font/iconfont.css b/yudao-ui-admin-uniapp/static/font/iconfont.css
new file mode 100644
index 000000000..39aed3da7
--- /dev/null
+++ b/yudao-ui-admin-uniapp/static/font/iconfont.css
@@ -0,0 +1,90 @@
+@font-face {
+  font-family: "iconfont";
+  src: url('/static/font/iconfont.ttf') format('truetype');
+}
+
+.iconfont {
+  font-family: "iconfont" !important;
+  font-size: 16px;
+  display: inline-block;
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+.icon-user:before {
+  content: "\e7ae";
+}
+
+.icon-password:before {
+  content: "\e8b2";
+}
+
+.icon-code:before {
+  content: "\e699";
+}
+
+.icon-setting:before {
+  content: "\e6cc";
+}
+
+.icon-share:before {
+  content: "\e739";
+}
+
+.icon-edit:before {
+  content: "\e60c";
+}
+
+.icon-version:before {
+  content: "\e63f";
+}
+
+.icon-service:before {
+  content: "\e6ff";
+}
+
+.icon-friendfill:before {
+  content: "\e726";
+}
+
+.icon-community:before {
+  content: "\e741";
+}
+
+.icon-people:before {
+  content: "\e736";
+}
+
+.icon-dianzan:before {
+  content: "\ec7f";
+}
+
+.icon-right:before {
+  content: "\e7eb";
+}
+
+.icon-logout:before {
+  content: "\e61d";
+}
+
+.icon-help:before {
+  content: "\e616";
+}
+
+.icon-github:before {
+  content: "\e628";
+}
+
+.icon-aixin:before {
+  content: "\e601";
+}
+
+.icon-clean:before {
+  content: "\e607";
+}
+
+.icon-refresh:before {
+  content: "\e604";
+}
+
diff --git a/yudao-ui-admin-uniapp/static/font/iconfont.ttf b/yudao-ui-admin-uniapp/static/font/iconfont.ttf
new file mode 100644
index 000000000..53915cafc
Binary files /dev/null and b/yudao-ui-admin-uniapp/static/font/iconfont.ttf differ
diff --git a/yudao-ui-admin-uniapp/static/images/banner/banner01.jpg b/yudao-ui-admin-uniapp/static/images/banner/banner01.jpg
new file mode 100755
index 000000000..fdb1e167e
Binary files /dev/null and b/yudao-ui-admin-uniapp/static/images/banner/banner01.jpg differ
diff --git a/yudao-ui-admin-uniapp/static/images/banner/banner02.jpg b/yudao-ui-admin-uniapp/static/images/banner/banner02.jpg
new file mode 100644
index 000000000..1086afd3c
Binary files /dev/null and b/yudao-ui-admin-uniapp/static/images/banner/banner02.jpg differ
diff --git a/yudao-ui-admin-uniapp/static/images/banner/banner03.jpg b/yudao-ui-admin-uniapp/static/images/banner/banner03.jpg
new file mode 100644
index 000000000..092a5fc23
Binary files /dev/null and b/yudao-ui-admin-uniapp/static/images/banner/banner03.jpg differ
diff --git a/yudao-ui-admin-uniapp/static/images/profile.jpg b/yudao-ui-admin-uniapp/static/images/profile.jpg
new file mode 100644
index 000000000..b3a940b21
Binary files /dev/null and b/yudao-ui-admin-uniapp/static/images/profile.jpg differ
diff --git a/yudao-ui-admin-uniapp/static/images/tabbar/home.png b/yudao-ui-admin-uniapp/static/images/tabbar/home.png
new file mode 100644
index 000000000..50acdfdde
Binary files /dev/null and b/yudao-ui-admin-uniapp/static/images/tabbar/home.png differ
diff --git a/yudao-ui-admin-uniapp/static/images/tabbar/home_.png b/yudao-ui-admin-uniapp/static/images/tabbar/home_.png
new file mode 100644
index 000000000..a408f71b2
Binary files /dev/null and b/yudao-ui-admin-uniapp/static/images/tabbar/home_.png differ
diff --git a/yudao-ui-admin-uniapp/static/images/tabbar/mine.png b/yudao-ui-admin-uniapp/static/images/tabbar/mine.png
new file mode 100644
index 000000000..f13fe44d2
Binary files /dev/null and b/yudao-ui-admin-uniapp/static/images/tabbar/mine.png differ
diff --git a/yudao-ui-admin-uniapp/static/images/tabbar/mine_.png b/yudao-ui-admin-uniapp/static/images/tabbar/mine_.png
new file mode 100644
index 000000000..8a0a742ff
Binary files /dev/null and b/yudao-ui-admin-uniapp/static/images/tabbar/mine_.png differ
diff --git a/yudao-ui-admin-uniapp/static/images/tabbar/work.png b/yudao-ui-admin-uniapp/static/images/tabbar/work.png
new file mode 100644
index 000000000..21e130d8e
Binary files /dev/null and b/yudao-ui-admin-uniapp/static/images/tabbar/work.png differ
diff --git a/yudao-ui-admin-uniapp/static/images/tabbar/work_.png b/yudao-ui-admin-uniapp/static/images/tabbar/work_.png
new file mode 100644
index 000000000..80b979c5a
Binary files /dev/null and b/yudao-ui-admin-uniapp/static/images/tabbar/work_.png differ
diff --git a/yudao-ui-admin-uniapp/static/index.html b/yudao-ui-admin-uniapp/static/index.html
new file mode 100644
index 000000000..a7af653b0
--- /dev/null
+++ b/yudao-ui-admin-uniapp/static/index.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html lang="zh-CN">
+	<head>
+		<meta charset="utf-8">
+		<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+		  <meta name="renderer" content="webkit">
+		<title><%= htmlWebpackPlugin.options.title %></title>
+    <link rel="shortcut icon" type="image/x-icon" href="<%= BASE_URL %>static/favicon.ico">
+		<script>
+			var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') || CSS.supports('top: constant(a)'))
+			document.write('<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' + (coverSupport ? ', viewport-fit=cover' : '') + '" />')
+		</script>
+		<link rel="stylesheet" href="<%= BASE_URL %>static/index.<%= VUE_APP_INDEX_CSS_HASH %>.css" />
+	</head>
+	<body>
+		<noscript>
+			<strong>本站点必须要开启JavaScript才能运行.</strong>
+		</noscript>
+		<div id="app"></div>
+</html>
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/static/logo.png b/yudao-ui-admin-uniapp/static/logo.png
new file mode 100644
index 000000000..b4270c067
Binary files /dev/null and b/yudao-ui-admin-uniapp/static/logo.png differ
diff --git a/yudao-ui-admin-uniapp/static/logo200.png b/yudao-ui-admin-uniapp/static/logo200.png
new file mode 100644
index 000000000..ffa998826
Binary files /dev/null and b/yudao-ui-admin-uniapp/static/logo200.png differ
diff --git a/yudao-ui-admin-uniapp/static/scss/colorui.css b/yudao-ui-admin-uniapp/static/scss/colorui.css
new file mode 100644
index 000000000..fade3b29e
--- /dev/null
+++ b/yudao-ui-admin-uniapp/static/scss/colorui.css
@@ -0,0 +1,3912 @@
+/*
+  ColorUi for uniApp  v2.1.6 | by 文晓港 2019-05-31 10:44:24
+  仅供学习交流,如作它用所承受的法律责任一概与作者无关  
+  
+  *使用ColorUi开发扩展与插件时,请注明基于ColorUi开发 
+  
+  (QQ交流群:240787041)
+*/
+
+/* ==================
+        初始化
+ ==================== */
+body {
+	background-color: #f1f1f1;
+	font-size: 28upx;
+	color: #333333;
+	font-family: Helvetica Neue, Helvetica, sans-serif;
+}
+
+view,
+scroll-view,
+swiper,
+button,
+input,
+textarea,
+label,
+navigator,
+image {
+	box-sizing: border-box;
+}
+
+.round {
+	border-radius: 5000upx;
+}
+
+.radius {
+	border-radius: 6upx;
+}
+
+/* ==================
+          图片
+ ==================== */
+
+image {
+	max-width: 100%;
+	display: inline-block;
+	position: relative;
+	z-index: 0;
+}
+
+image.loading::before {
+	content: "";
+	background-color: #f5f5f5;
+	display: block;
+	position: absolute;
+	width: 100%;
+	height: 100%;
+	z-index: -2;
+}
+
+image.loading::after {
+	content: "\e7f1";
+	font-family: "cuIcon";
+	position: absolute;
+	top: 0;
+	left: 0;
+	width: 32upx;
+	height: 32upx;
+	line-height: 32upx;
+	right: 0;
+	bottom: 0;
+	z-index: -1;
+	font-size: 32upx;
+	margin: auto;
+	color: #ccc;
+	-webkit-animation: cuIcon-spin 2s infinite linear;
+	animation: cuIcon-spin 2s infinite linear;
+	display: block;
+}
+
+.response {
+	width: 100%;
+}
+
+/* ==================
+         开关
+ ==================== */
+
+switch,
+checkbox,
+radio {
+	position: relative;
+}
+
+switch::after,
+switch::before {
+	font-family: "cuIcon";
+	content: "\e645";
+	position: absolute;
+	color: #ffffff !important;
+	top: 0%;
+	left: 0upx;
+	font-size: 26upx;
+	line-height: 26px;
+	width: 50%;
+	text-align: center;
+	pointer-events: none;
+	transform: scale(0, 0);
+	transition: all 0.3s ease-in-out 0s;
+	z-index: 9;
+	bottom: 0;
+	height: 26px;
+	margin: auto;
+}
+
+switch::before {
+	content: "\e646";
+	right: 0;
+	transform: scale(1, 1);
+	left: auto;
+}
+
+switch[checked]::after,
+switch.checked::after {
+	transform: scale(1, 1);
+}
+
+switch[checked]::before,
+switch.checked::before {
+	transform: scale(0, 0);
+}
+
+/* #ifndef MP-ALIPAY */
+radio::before,
+checkbox::before {
+	font-family: "cuIcon";
+	content: "\e645";
+	position: absolute;
+	color: #ffffff !important;
+	top: 50%;
+	margin-top: -8px;
+	right: 5px;
+	font-size: 32upx;
+	line-height: 16px;
+	pointer-events: none;
+	transform: scale(1, 1);
+	transition: all 0.3s ease-in-out 0s;
+	z-index: 9;
+}
+
+radio .wx-radio-input,
+checkbox .wx-checkbox-input,
+radio .uni-radio-input,
+checkbox .uni-checkbox-input {
+	margin: 0;
+	width: 24px;
+	height: 24px;
+}
+
+checkbox.round .wx-checkbox-input,
+checkbox.round .uni-checkbox-input {
+	border-radius: 100upx;
+}
+
+/* #endif */
+
+switch[checked]::before {
+	transform: scale(0, 0);
+}
+
+switch .wx-switch-input,
+switch .uni-switch-input {
+	border: none;
+	padding: 0 24px;
+	width: 48px;
+	height: 26px;
+	margin: 0;
+	border-radius: 100upx;
+}
+
+switch .wx-switch-input:not([class*="bg-"]),
+switch .uni-switch-input:not([class*="bg-"]) {
+	background: #8799a3 !important;
+}
+
+switch .wx-switch-input::after,
+switch .uni-switch-input::after {
+	margin: auto;
+	width: 26px;
+	height: 26px;
+	border-radius: 100upx;
+	left: 0upx;
+	top: 0upx;
+	bottom: 0upx;
+	position: absolute;
+	transform: scale(0.9, 0.9);
+	transition: all 0.1s ease-in-out 0s;
+}
+
+switch .wx-switch-input.wx-switch-input-checked::after,
+switch .uni-switch-input.uni-switch-input-checked::after {
+	margin: auto;
+	left: 22px;
+	box-shadow: none;
+	transform: scale(0.9, 0.9);
+}
+
+radio-group {
+	display: inline-block;
+}
+
+
+
+switch.radius .wx-switch-input::after,
+switch.radius .wx-switch-input,
+switch.radius .wx-switch-input::before,
+switch.radius .uni-switch-input::after,
+switch.radius .uni-switch-input,
+switch.radius .uni-switch-input::before {
+	border-radius: 10upx;
+}
+
+switch .wx-switch-input::before,
+radio.radio::before,
+checkbox .wx-checkbox-input::before,
+radio .wx-radio-input::before,
+switch .uni-switch-input::before,
+radio.radio::before,
+checkbox .uni-checkbox-input::before,
+radio .uni-radio-input::before {
+	display: none;
+}
+
+radio.radio[checked]::after,
+radio.radio .uni-radio-input-checked::after {
+	content: "";
+	background-color: transparent;
+	display: block;
+	position: absolute;
+	width: 8px;
+	height: 8px;
+	z-index: 999;
+	top: 0upx;
+	left: 0upx;
+	right: 0;
+	bottom: 0;
+	margin: auto;
+	border-radius: 200upx;
+	/* #ifndef MP */
+	border: 7px solid #ffffff !important;
+	/* #endif */
+
+	/* #ifdef MP */
+	border: 8px solid #ffffff !important;
+	/* #endif */
+}
+
+.switch-sex::after {
+	content: "\e71c";
+}
+
+.switch-sex::before {
+	content: "\e71a";
+}
+
+.switch-sex .wx-switch-input,
+.switch-sex .uni-switch-input {
+	background: #e54d42 !important;
+	border-color: #e54d42 !important;
+}
+
+.switch-sex[checked] .wx-switch-input,
+.switch-sex.checked .uni-switch-input {
+	background: #0081ff !important;
+	border-color: #0081ff !important;
+}
+
+switch.red[checked] .wx-switch-input.wx-switch-input-checked,
+checkbox.red[checked] .wx-checkbox-input,
+radio.red[checked] .wx-radio-input,
+switch.red.checked .uni-switch-input.uni-switch-input-checked,
+checkbox.red.checked .uni-checkbox-input,
+radio.red.checked .uni-radio-input {
+	background-color: #e54d42 !important;
+	border-color: #e54d42 !important;
+	color: #ffffff !important;
+}
+
+switch.orange[checked] .wx-switch-input,
+checkbox.orange[checked] .wx-checkbox-input,
+radio.orange[checked] .wx-radio-input,
+switch.orange.checked .uni-switch-input,
+checkbox.orange.checked .uni-checkbox-input,
+radio.orange.checked .uni-radio-input {
+	background-color: #f37b1d !important;
+	border-color: #f37b1d !important;
+	color: #ffffff !important;
+}
+
+switch.yellow[checked] .wx-switch-input,
+checkbox.yellow[checked] .wx-checkbox-input,
+radio.yellow[checked] .wx-radio-input,
+switch.yellow.checked .uni-switch-input,
+checkbox.yellow.checked .uni-checkbox-input,
+radio.yellow.checked .uni-radio-input {
+	background-color: #fbbd08 !important;
+	border-color: #fbbd08 !important;
+	color: #333333 !important;
+}
+
+switch.olive[checked] .wx-switch-input,
+checkbox.olive[checked] .wx-checkbox-input,
+radio.olive[checked] .wx-radio-input,
+switch.olive.checked .uni-switch-input,
+checkbox.olive.checked .uni-checkbox-input,
+radio.olive.checked .uni-radio-input {
+	background-color: #8dc63f !important;
+	border-color: #8dc63f !important;
+	color: #ffffff !important;
+}
+
+switch.green[checked] .wx-switch-input,
+switch[checked] .wx-switch-input,
+checkbox.green[checked] .wx-checkbox-input,
+checkbox[checked] .wx-checkbox-input,
+radio.green[checked] .wx-radio-input,
+radio[checked] .wx-radio-input,
+switch.green.checked .uni-switch-input,
+switch.checked .uni-switch-input,
+checkbox.green.checked .uni-checkbox-input,
+checkbox.checked .uni-checkbox-input,
+radio.green.checked .uni-radio-input,
+radio.checked .uni-radio-input {
+	background-color: #39b54a !important;
+	border-color: #39b54a !important;
+	color: #ffffff !important;
+	border-color: #39B54A !important;
+}
+
+switch.cyan[checked] .wx-switch-input,
+checkbox.cyan[checked] .wx-checkbox-input,
+radio.cyan[checked] .wx-radio-input,
+switch.cyan.checked .uni-switch-input,
+checkbox.cyan.checked .uni-checkbox-input,
+radio.cyan.checked .uni-radio-input {
+	background-color: #1cbbb4 !important;
+	border-color: #1cbbb4 !important;
+	color: #ffffff !important;
+}
+
+switch.blue[checked] .wx-switch-input,
+checkbox.blue[checked] .wx-checkbox-input,
+radio.blue[checked] .wx-radio-input,
+switch.blue.checked .uni-switch-input,
+checkbox.blue.checked .uni-checkbox-input,
+radio.blue.checked .uni-radio-input {
+	background-color: #0081ff !important;
+	border-color: #0081ff !important;
+	color: #ffffff !important;
+}
+
+switch.purple[checked] .wx-switch-input,
+checkbox.purple[checked] .wx-checkbox-input,
+radio.purple[checked] .wx-radio-input,
+switch.purple.checked .uni-switch-input,
+checkbox.purple.checked .uni-checkbox-input,
+radio.purple.checked .uni-radio-input {
+	background-color: #6739b6 !important;
+	border-color: #6739b6 !important;
+	color: #ffffff !important;
+}
+
+switch.mauve[checked] .wx-switch-input,
+checkbox.mauve[checked] .wx-checkbox-input,
+radio.mauve[checked] .wx-radio-input,
+switch.mauve.checked .uni-switch-input,
+checkbox.mauve.checked .uni-checkbox-input,
+radio.mauve.checked .uni-radio-input {
+	background-color: #9c26b0 !important;
+	border-color: #9c26b0 !important;
+	color: #ffffff !important;
+}
+
+switch.pink[checked] .wx-switch-input,
+checkbox.pink[checked] .wx-checkbox-input,
+radio.pink[checked] .wx-radio-input,
+switch.pink.checked .uni-switch-input,
+checkbox.pink.checked .uni-checkbox-input,
+radio.pink.checked .uni-radio-input {
+	background-color: #e03997 !important;
+	border-color: #e03997 !important;
+	color: #ffffff !important;
+}
+
+switch.brown[checked] .wx-switch-input,
+checkbox.brown[checked] .wx-checkbox-input,
+radio.brown[checked] .wx-radio-input,
+switch.brown.checked .uni-switch-input,
+checkbox.brown.checked .uni-checkbox-input,
+radio.brown.checked .uni-radio-input {
+	background-color: #a5673f !important;
+	border-color: #a5673f !important;
+	color: #ffffff !important;
+}
+
+switch.grey[checked] .wx-switch-input,
+checkbox.grey[checked] .wx-checkbox-input,
+radio.grey[checked] .wx-radio-input,
+switch.grey.checked .uni-switch-input,
+checkbox.grey.checked .uni-checkbox-input,
+radio.grey.checked .uni-radio-input {
+	background-color: #8799a3 !important;
+	border-color: #8799a3 !important;
+	color: #ffffff !important;
+}
+
+switch.gray[checked] .wx-switch-input,
+checkbox.gray[checked] .wx-checkbox-input,
+radio.gray[checked] .wx-radio-input,
+switch.gray.checked .uni-switch-input,
+checkbox.gray.checked .uni-checkbox-input,
+radio.gray.checked .uni-radio-input {
+	background-color: #f0f0f0 !important;
+	border-color: #f0f0f0 !important;
+	color: #333333 !important;
+}
+
+switch.black[checked] .wx-switch-input,
+checkbox.black[checked] .wx-checkbox-input,
+radio.black[checked] .wx-radio-input,
+switch.black.checked .uni-switch-input,
+checkbox.black.checked .uni-checkbox-input,
+radio.black.checked .uni-radio-input {
+	background-color: #333333 !important;
+	border-color: #333333 !important;
+	color: #ffffff !important;
+}
+
+switch.white[checked] .wx-switch-input,
+checkbox.white[checked] .wx-checkbox-input,
+radio.white[checked] .wx-radio-input,
+switch.white.checked .uni-switch-input,
+checkbox.white.checked .uni-checkbox-input,
+radio.white.checked .uni-radio-input {
+	background-color: #ffffff !important;
+	border-color: #ffffff !important;
+	color: #333333 !important;
+}
+
+/* ==================
+          边框
+ ==================== */
+
+/* -- 实线 -- */
+
+.solid,
+.solid-top,
+.solid-right,
+.solid-bottom,
+.solid-left,
+.solids,
+.solids-top,
+.solids-right,
+.solids-bottom,
+.solids-left,
+.dashed,
+.dashed-top,
+.dashed-right,
+.dashed-bottom,
+.dashed-left {
+	position: relative;
+}
+
+.solid::after,
+.solid-top::after,
+.solid-right::after,
+.solid-bottom::after,
+.solid-left::after,
+.solids::after,
+.solids-top::after,
+.solids-right::after,
+.solids-bottom::after,
+.solids-left::after,
+.dashed::after,
+.dashed-top::after,
+.dashed-right::after,
+.dashed-bottom::after,
+.dashed-left::after {
+	content: " ";
+	width: 200%;
+	height: 200%;
+	position: absolute;
+	top: 0;
+	left: 0;
+	border-radius: inherit;
+	transform: scale(0.5);
+	transform-origin: 0 0;
+	pointer-events: none;
+	box-sizing: border-box;
+}
+
+.solid::after {
+	border: 1upx solid rgba(0, 0, 0, 0.1);
+}
+
+.solid-top::after {
+	border-top: 1upx solid rgba(0, 0, 0, 0.1);
+}
+
+.solid-right::after {
+	border-right: 1upx solid rgba(0, 0, 0, 0.1);
+}
+
+.solid-bottom::after {
+	border-bottom: 1upx solid rgba(0, 0, 0, 0.1);
+}
+
+.solid-left::after {
+	border-left: 1upx solid rgba(0, 0, 0, 0.1);
+}
+
+.solids::after {
+	border: 8upx solid #eee;
+}
+
+.solids-top::after {
+	border-top: 8upx solid #eee;
+}
+
+.solids-right::after {
+	border-right: 8upx solid #eee;
+}
+
+.solids-bottom::after {
+	border-bottom: 8upx solid #eee;
+}
+
+.solids-left::after {
+	border-left: 8upx solid #eee;
+}
+
+/* -- 虚线 -- */
+
+.dashed::after {
+	border: 1upx dashed #ddd;
+}
+
+.dashed-top::after {
+	border-top: 1upx dashed #ddd;
+}
+
+.dashed-right::after {
+	border-right: 1upx dashed #ddd;
+}
+
+.dashed-bottom::after {
+	border-bottom: 1upx dashed #ddd;
+}
+
+.dashed-left::after {
+	border-left: 1upx dashed #ddd;
+}
+
+/* -- 阴影 -- */
+
+.shadow[class*='white'] {
+	--ShadowSize: 0 1upx 6upx;
+}
+
+.shadow-lg {
+	--ShadowSize: 0upx 40upx 100upx 0upx;
+}
+
+.shadow-warp {
+	position: relative;
+	box-shadow: 0 0 10upx rgba(0, 0, 0, 0.1);
+}
+
+.shadow-warp:before,
+.shadow-warp:after {
+	position: absolute;
+	content: "";
+	top: 20upx;
+	bottom: 30upx;
+	left: 20upx;
+	width: 50%;
+	box-shadow: 0 30upx 20upx rgba(0, 0, 0, 0.2);
+	transform: rotate(-3deg);
+	z-index: -1;
+}
+
+.shadow-warp:after {
+	right: 20upx;
+	left: auto;
+	transform: rotate(3deg);
+}
+
+.shadow-blur {
+	position: relative;
+}
+
+.shadow-blur::before {
+	content: "";
+	display: block;
+	background: inherit;
+	filter: blur(10upx);
+	position: absolute;
+	width: 100%;
+	height: 100%;
+	top: 10upx;
+	left: 10upx;
+	z-index: -1;
+	opacity: 0.4;
+	transform-origin: 0 0;
+	border-radius: inherit;
+	transform: scale(1, 1);
+}
+
+/* ==================
+          按钮
+ ==================== */
+
+.cu-btn {
+	position: relative;
+	border: 0upx;
+	display: inline-flex;
+	align-items: center;
+	justify-content: center;
+	box-sizing: border-box;
+	padding: 0 30upx;
+	font-size: 28upx;
+	height: 64upx;
+	line-height: 1;
+	text-align: center;
+	text-decoration: none;
+	overflow: visible;
+	margin-left: initial;
+	transform: translate(0upx, 0upx);
+	margin-right: initial;
+}
+
+.cu-btn::after {
+	display: none;
+}
+
+.cu-btn:not([class*="bg-"]) {
+	background-color: #f0f0f0;
+}
+
+.cu-btn[class*="line"] {
+	background-color: transparent;
+}
+
+.cu-btn[class*="line"]::after {
+	content: " ";
+	display: block;
+	width: 200%;
+	height: 200%;
+	position: absolute;
+	top: 0;
+	left: 0;
+	border: 1upx solid currentColor;
+	transform: scale(0.5);
+	transform-origin: 0 0;
+	box-sizing: border-box;
+	border-radius: 12upx;
+	z-index: 1;
+	pointer-events: none;
+}
+
+.cu-btn.round[class*="line"]::after {
+	border-radius: 1000upx;
+}
+
+.cu-btn[class*="lines"]::after {
+	border: 6upx solid currentColor;
+}
+
+.cu-btn[class*="bg-"]::after {
+	display: none;
+}
+
+.cu-btn.sm {
+	padding: 0 20upx;
+	font-size: 20upx;
+	height: 48upx;
+}
+
+.cu-btn.lg {
+	padding: 0 40upx;
+	font-size: 32upx;
+	height: 80upx;
+}
+
+.cu-btn.cuIcon.sm {
+	width: 48upx;
+	height: 48upx;
+}
+
+.cu-btn.cuIcon {
+	width: 64upx;
+	height: 64upx;
+	border-radius: 500upx;
+	padding: 0;
+}
+
+button.cuIcon.lg {
+	width: 80upx;
+	height: 80upx;
+}
+
+.cu-btn.shadow-blur::before {
+	top: 4upx;
+	left: 4upx;
+	filter: blur(6upx);
+	opacity: 0.6;
+}
+
+.cu-btn.button-hover {
+	transform: translate(1upx, 1upx);
+}
+
+.block {
+	display: block;
+}
+
+.cu-btn.block {
+	display: flex;
+}
+
+.cu-btn[disabled] {
+	opacity: 0.6;
+	color: #ffffff;
+}
+
+/* ==================
+          徽章
+ ==================== */
+
+.cu-tag {
+	font-size: 24upx;
+	vertical-align: middle;
+	position: relative;
+	display: inline-flex;
+	align-items: center;
+	justify-content: center;
+	box-sizing: border-box;
+	padding: 0upx 16upx;
+	height: 48upx;
+	font-family: Helvetica Neue, Helvetica, sans-serif;
+	white-space: nowrap;
+}
+
+.cu-tag:not([class*="bg"]):not([class*="line"]) {
+	background-color: #f1f1f1;
+}
+
+.cu-tag[class*="line-"]::after {
+	content: " ";
+	width: 200%;
+	height: 200%;
+	position: absolute;
+	top: 0;
+	left: 0;
+	border: 1upx solid currentColor;
+	transform: scale(0.5);
+	transform-origin: 0 0;
+	box-sizing: border-box;
+	border-radius: inherit;
+	z-index: 1;
+	pointer-events: none;
+}
+
+.cu-tag.radius[class*="line"]::after {
+	border-radius: 12upx;
+}
+
+.cu-tag.round[class*="line"]::after {
+	border-radius: 1000upx;
+}
+
+.cu-tag[class*="line-"]::after {
+	border-radius: 0;
+}
+
+.cu-tag+.cu-tag {
+	margin-left: 10upx;
+}
+
+.cu-tag.sm {
+	font-size: 20upx;
+	padding: 0upx 12upx;
+	height: 32upx;
+}
+
+.cu-capsule {
+	display: inline-flex;
+	vertical-align: middle;
+}
+
+.cu-capsule+.cu-capsule {
+	margin-left: 10upx;
+}
+
+.cu-capsule .cu-tag {
+	margin: 0;
+}
+
+.cu-capsule .cu-tag[class*="line-"]:last-child::after {
+	border-left: 0upx solid transparent;
+}
+
+.cu-capsule .cu-tag[class*="line-"]:first-child::after {
+	border-right: 0upx solid transparent;
+}
+
+.cu-capsule.radius .cu-tag:first-child {
+	border-top-left-radius: 6upx;
+	border-bottom-left-radius: 6upx;
+}
+
+.cu-capsule.radius .cu-tag:last-child::after,
+.cu-capsule.radius .cu-tag[class*="line-"] {
+	border-top-right-radius: 12upx;
+	border-bottom-right-radius: 12upx;
+}
+
+.cu-capsule.round .cu-tag:first-child {
+	border-top-left-radius: 200upx;
+	border-bottom-left-radius: 200upx;
+	text-indent: 4upx;
+}
+
+.cu-capsule.round .cu-tag:last-child::after,
+.cu-capsule.round .cu-tag:last-child {
+	border-top-right-radius: 200upx;
+	border-bottom-right-radius: 200upx;
+	text-indent: -4upx;
+}
+
+.cu-tag.badge {
+	border-radius: 200upx;
+	position: absolute;
+	top: -10upx;
+	right: -10upx;
+	font-size: 20upx;
+	padding: 0upx 10upx;
+	height: 28upx;
+	color: #ffffff;
+}
+
+.cu-tag.badge:not([class*="bg-"]) {
+	background-color: #dd514c;
+}
+
+.cu-tag:empty:not([class*="cuIcon-"]) {
+	padding: 0upx;
+	width: 16upx;
+	height: 16upx;
+	top: -4upx;
+	right: -4upx;
+}
+
+.cu-tag[class*="cuIcon-"] {
+	width: 32upx;
+	height: 32upx;
+	top: -4upx;
+	right: -4upx;
+}
+
+/* ==================
+          头像
+ ==================== */
+
+.cu-avatar {
+	font-variant: small-caps;
+	margin: 0;
+	padding: 0;
+	display: inline-flex;
+	text-align: center;
+	justify-content: center;
+	align-items: center;
+	background-color: #ccc;
+	color: #ffffff;
+	white-space: nowrap;
+	position: relative;
+	width: 64upx;
+	height: 64upx;
+	background-size: cover;
+	background-position: center;
+	vertical-align: middle;
+	font-size: 1.5em;
+}
+
+.cu-avatar.sm {
+	width: 48upx;
+	height: 48upx;
+	font-size: 1em;
+}
+
+.cu-avatar.lg {
+	width: 96upx;
+	height: 96upx;
+	font-size: 2em;
+}
+
+.cu-avatar.xl {
+	width: 128upx;
+	height: 128upx;
+	font-size: 2.5em;
+}
+
+.cu-avatar .avatar-text {
+	font-size: 0.4em;
+}
+
+.cu-avatar-group {
+	direction: rtl;
+	unicode-bidi: bidi-override;
+	padding: 0 10upx 0 40upx;
+	display: inline-block;
+}
+
+.cu-avatar-group .cu-avatar {
+	margin-left: -30upx;
+	border: 4upx solid #f1f1f1;
+	vertical-align: middle;
+}
+
+.cu-avatar-group .cu-avatar.sm {
+	margin-left: -20upx;
+	border: 1upx solid #f1f1f1;
+}
+
+/* ==================
+         进度条
+ ==================== */
+
+.cu-progress {
+	overflow: hidden;
+	height: 28upx;
+	background-color: #ebeef5;
+	display: inline-flex;
+	align-items: center;
+	width: 100%;
+}
+
+.cu-progress+view,
+.cu-progress+text {
+	line-height: 1;
+}
+
+.cu-progress.xs {
+	height: 10upx;
+}
+
+.cu-progress.sm {
+	height: 20upx;
+}
+
+.cu-progress view {
+	width: 0;
+	height: 100%;
+	align-items: center;
+	display: flex;
+	justify-items: flex-end;
+	justify-content: space-around;
+	font-size: 20upx;
+	color: #ffffff;
+	transition: width 0.6s ease;
+}
+
+.cu-progress text {
+	align-items: center;
+	display: flex;
+	font-size: 20upx;
+	color: #333333;
+	text-indent: 10upx;
+}
+
+.cu-progress.text-progress {
+	padding-right: 60upx;
+}
+
+.cu-progress.striped view {
+	background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+	background-size: 72upx 72upx;
+}
+
+.cu-progress.active view {
+	animation: progress-stripes 2s linear infinite;
+}
+
+@keyframes progress-stripes {
+	from {
+		background-position: 72upx 0;
+	}
+
+	to {
+		background-position: 0 0;
+	}
+}
+
+/* ==================
+          加载
+ ==================== */
+
+.cu-load {
+	display: block;
+	line-height: 3em;
+	text-align: center;
+}
+
+.cu-load::before {
+	font-family: "cuIcon";
+	display: inline-block;
+	margin-right: 6upx;
+}
+
+.cu-load.loading::before {
+	content: "\e67a";
+	animation: cuIcon-spin 2s infinite linear;
+}
+
+.cu-load.loading::after {
+	content: "加载中...";
+}
+
+.cu-load.over::before {
+	content: "\e64a";
+}
+
+.cu-load.over::after {
+	content: "没有更多了";
+}
+
+.cu-load.erro::before {
+	content: "\e658";
+}
+
+.cu-load.erro::after {
+	content: "加载失败";
+}
+
+.cu-load.load-cuIcon::before {
+	font-size: 32upx;
+}
+
+.cu-load.load-cuIcon::after {
+	display: none;
+}
+
+.cu-load.load-cuIcon.over {
+	display: none;
+}
+
+.cu-load.load-modal {
+	position: fixed;
+	top: 0;
+	right: 0;
+	bottom: 140upx;
+	left: 0;
+	margin: auto;
+	width: 260upx;
+	height: 260upx;
+	background-color: #ffffff;
+	border-radius: 10upx;
+	box-shadow: 0 0 0upx 2000upx rgba(0, 0, 0, 0.5);
+	display: flex;
+	align-items: center;
+	flex-direction: column;
+	justify-content: center;
+	font-size: 28upx;
+	z-index: 9999;
+	line-height: 2.4em;
+}
+
+.cu-load.load-modal [class*="cuIcon-"] {
+	font-size: 60upx;
+}
+
+.cu-load.load-modal image {
+	width: 70upx;
+	height: 70upx;
+}
+
+.cu-load.load-modal::after {
+	content: "";
+	position: absolute;
+	background-color: #ffffff;
+	border-radius: 50%;
+	width: 200upx;
+	height: 200upx;
+	font-size: 10px;
+	border-top: 6upx solid rgba(0, 0, 0, 0.05);
+	border-right: 6upx solid rgba(0, 0, 0, 0.05);
+	border-bottom: 6upx solid rgba(0, 0, 0, 0.05);
+	border-left: 6upx solid #f37b1d;
+	animation: cuIcon-spin 1s infinite linear;
+	z-index: -1;
+}
+
+.load-progress {
+	pointer-events: none;
+	top: 0;
+	position: fixed;
+	width: 100%;
+	left: 0;
+	z-index: 2000;
+}
+
+.load-progress.hide {
+	display: none;
+}
+
+.load-progress .load-progress-bar {
+	position: relative;
+	width: 100%;
+	height: 4upx;
+	overflow: hidden;
+	transition: all 200ms ease 0s;
+}
+
+.load-progress .load-progress-spinner {
+	position: absolute;
+	top: 10upx;
+	right: 10upx;
+	z-index: 2000;
+	display: block;
+}
+
+.load-progress .load-progress-spinner::after {
+	content: "";
+	display: block;
+	width: 24upx;
+	height: 24upx;
+	-webkit-box-sizing: border-box;
+	box-sizing: border-box;
+	border: solid 4upx transparent;
+	border-top-color: inherit;
+	border-left-color: inherit;
+	border-radius: 50%;
+	-webkit-animation: load-progress-spinner 0.4s linear infinite;
+	animation: load-progress-spinner 0.4s linear infinite;
+}
+
+@-webkit-keyframes load-progress-spinner {
+	0% {
+		-webkit-transform: rotate(0);
+		transform: rotate(0);
+	}
+
+	100% {
+		-webkit-transform: rotate(360deg);
+		transform: rotate(360deg);
+	}
+}
+
+@keyframes load-progress-spinner {
+	0% {
+		-webkit-transform: rotate(0);
+		transform: rotate(0);
+	}
+
+	100% {
+		-webkit-transform: rotate(360deg);
+		transform: rotate(360deg);
+	}
+}
+
+/* ==================
+          列表
+ ==================== */
+.grayscale {
+	filter: grayscale(1);
+}
+
+.cu-list+.cu-list {
+	margin-top: 30upx
+}
+
+.cu-list>.cu-item {
+	transition: all .6s ease-in-out 0s;
+	transform: translateX(0upx)
+}
+
+.cu-list>.cu-item.move-cur {
+	transform: translateX(-260upx)
+}
+
+.cu-list>.cu-item .move {
+	position: absolute;
+	right: 0;
+	display: flex;
+	width: 260upx;
+	height: 100%;
+	transform: translateX(100%)
+}
+
+.cu-list>.cu-item .move view {
+	display: flex;
+	flex: 1;
+	justify-content: center;
+	align-items: center
+}
+
+.cu-list.menu-avatar {
+	overflow: hidden;
+}
+
+.cu-list.menu-avatar>.cu-item {
+	position: relative;
+	display: flex;
+	padding-right: 10upx;
+	height: 140upx;
+	background-color: #ffffff;
+	justify-content: flex-end;
+	align-items: center
+}
+
+.cu-list.menu-avatar>.cu-item>.cu-avatar {
+	position: absolute;
+	left: 30upx
+}
+
+.cu-list.menu-avatar>.cu-item .flex .text-cut {
+	max-width: 510upx
+}
+
+.cu-list.menu-avatar>.cu-item .content {
+	position: absolute;
+	left: 146upx;
+	width: calc(100% - 96upx - 60upx - 120upx - 20upx);
+	line-height: 1.6em;
+}
+
+.cu-list.menu-avatar>.cu-item .content.flex-sub {
+	width: calc(100% - 96upx - 60upx - 20upx);
+}
+
+.cu-list.menu-avatar>.cu-item .content>view:first-child {
+	font-size: 30upx;
+	display: flex;
+	align-items: center
+}
+
+.cu-list.menu-avatar>.cu-item .content .cu-tag.sm {
+	display: inline-block;
+	margin-left: 10upx;
+	height: 28upx;
+	font-size: 16upx;
+	line-height: 32upx
+}
+
+.cu-list.menu-avatar>.cu-item .action {
+	width: 100upx;
+	text-align: center
+}
+
+.cu-list.menu-avatar>.cu-item .action view+view {
+	margin-top: 10upx
+}
+
+.cu-list.menu-avatar.comment>.cu-item .content {
+	position: relative;
+	left: 0;
+	width: auto;
+	flex: 1;
+}
+
+.cu-list.menu-avatar.comment>.cu-item {
+	padding: 30upx 30upx 30upx 120upx;
+	height: auto
+}
+
+.cu-list.menu-avatar.comment .cu-avatar {
+	align-self: flex-start
+}
+
+.cu-list.menu>.cu-item {
+	position: relative;
+	display: flex;
+	padding: 0 30upx;
+	min-height: 100upx;
+	background-color: #ffffff;
+	justify-content: space-between;
+	align-items: center
+}
+
+.cu-list.menu>.cu-item:last-child:after {
+	border: none
+}
+
+.cu-list.menu-avatar>.cu-item:after,
+.cu-list.menu>.cu-item:after {
+	position: absolute;
+	top: 0;
+	left: 0;
+	box-sizing: border-box;
+	width: 200%;
+	height: 200%;
+	border-bottom: 1upx solid #ddd;
+	border-radius: inherit;
+	content: " ";
+	transform: scale(.5);
+	transform-origin: 0 0;
+	pointer-events: none
+}
+
+.cu-list.menu>.cu-item.grayscale {
+	background-color: #f5f5f5
+}
+
+.cu-list.menu>.cu-item.cur {
+	background-color: #fcf7e9
+}
+
+.cu-list.menu>.cu-item.arrow {
+	padding-right: 90upx
+}
+
+.cu-list.menu>.cu-item.arrow:before {
+	position: absolute;
+	top: 0;
+	right: 30upx;
+	bottom: 0;
+	display: block;
+	margin: auto;
+	width: 30upx;
+	height: 30upx;
+	color: #8799a3;
+	content: "\e6a3";
+	text-align: center;
+	font-size: 34upx;
+	font-family: cuIcon;
+	line-height: 30upx
+}
+
+.cu-list.menu>.cu-item button.content {
+	padding: 0;
+	background-color: transparent;
+	justify-content: flex-start
+}
+
+.cu-list.menu>.cu-item button.content:after {
+	display: none
+}
+
+.cu-list.menu>.cu-item .cu-avatar-group .cu-avatar {
+	border-color: #ffffff
+}
+
+.cu-list.menu>.cu-item .content>view:first-child {
+	display: flex;
+	align-items: center
+}
+
+.cu-list.menu>.cu-item .content>text[class*=cuIcon] {
+	display: inline-block;
+	margin-right: 10upx;
+	width: 1.6em;
+	text-align: center
+}
+
+.cu-list.menu>.cu-item .content>image {
+	display: inline-block;
+	margin-right: 10upx;
+	width: 1.6em;
+	height: 1.6em;
+	vertical-align: middle
+}
+
+.cu-list.menu>.cu-item .content {
+	font-size: 30upx;
+	line-height: 1.6em;
+	flex: 1
+}
+
+.cu-list.menu>.cu-item .content .cu-tag.sm {
+	display: inline-block;
+	margin-left: 10upx;
+	height: 28upx;
+	font-size: 16upx;
+	line-height: 32upx
+}
+
+.cu-list.menu>.cu-item .action .cu-tag:empty {
+	right: 10upx
+}
+
+.cu-list.menu {
+	display: block;
+	overflow: hidden
+}
+
+.cu-list.menu.sm-border>.cu-item:after {
+	left: 30upx;
+	width: calc(200% - 120upx)
+}
+
+.cu-list.grid>.cu-item {
+	position: relative;
+	display: flex;
+	padding: 20upx 0 30upx;
+	transition-duration: 0s;
+	flex-direction: column
+}
+
+.cu-list.grid>.cu-item:after {
+	position: absolute;
+	top: 0;
+	left: 0;
+	box-sizing: border-box;
+	width: 200%;
+	height: 200%;
+	border-right: 1px solid rgba(0, 0, 0, .1);
+	border-bottom: 1px solid rgba(0, 0, 0, .1);
+	border-radius: inherit;
+	content: " ";
+	transform: scale(.5);
+	transform-origin: 0 0;
+	pointer-events: none
+}
+
+.cu-list.grid>.cu-item text {
+	display: block;
+	margin-top: 10upx;
+	color: #888;
+	font-size: 26upx;
+	line-height: 40upx
+}
+
+.cu-list.grid>.cu-item [class*=cuIcon] {
+	position: relative;
+	display: block;
+	margin-top: 20upx;
+	width: 100%;
+	font-size: 48upx
+}
+
+.cu-list.grid>.cu-item .cu-tag {
+	right: auto;
+	left: 50%;
+	margin-left: 20upx
+}
+
+.cu-list.grid {
+	background-color: #ffffff;
+	text-align: center
+}
+
+.cu-list.grid.no-border>.cu-item {
+	padding-top: 10upx;
+	padding-bottom: 20upx
+}
+
+.cu-list.grid.no-border>.cu-item:after {
+	border: none
+}
+
+.cu-list.grid.no-border {
+	padding: 20upx 10upx
+}
+
+.cu-list.grid.col-3>.cu-item:nth-child(3n):after,
+.cu-list.grid.col-4>.cu-item:nth-child(4n):after,
+.cu-list.grid.col-5>.cu-item:nth-child(5n):after {
+	border-right-width: 0
+}
+
+.cu-list.card-menu {
+	overflow: hidden;
+	margin-right: 30upx;
+	margin-left: 30upx;
+	border-radius: 20upx
+}
+
+
+/* ==================
+          操作条
+ ==================== */
+
+.cu-bar {
+	display: flex;
+	position: relative;
+	align-items: center;
+	min-height: 100upx;
+	justify-content: space-between;
+}
+
+.cu-bar .action {
+	display: flex;
+	align-items: center;
+	height: 100%;
+	justify-content: center;
+	max-width: 100%;
+}
+
+.cu-bar .action.border-title {
+	position: relative;
+	top: -10upx;
+}
+
+.cu-bar .action.border-title text[class*="bg-"]:last-child {
+	position: absolute;
+	bottom: -0.5rem;
+	min-width: 2rem;
+	height: 6upx;
+	left: 0;
+}
+
+.cu-bar .action.sub-title {
+	position: relative;
+	top: -0.2rem;
+}
+
+.cu-bar .action.sub-title text {
+	position: relative;
+	z-index: 1;
+}
+
+.cu-bar .action.sub-title text[class*="bg-"]:last-child {
+	position: absolute;
+	display: inline-block;
+	bottom: -0.2rem;
+	border-radius: 6upx;
+	width: 100%;
+	height: 0.6rem;
+	left: 0.6rem;
+	opacity: 0.3;
+	z-index: 0;
+}
+
+.cu-bar .action.sub-title text[class*="text-"]:last-child {
+	position: absolute;
+	display: inline-block;
+	bottom: -0.7rem;
+	left: 0.5rem;
+	opacity: 0.2;
+	z-index: 0;
+	text-align: right;
+	font-weight: 900;
+	font-size: 36upx;
+}
+
+.cu-bar.justify-center .action.border-title text:last-child,
+.cu-bar.justify-center .action.sub-title text:last-child {
+	left: 0;
+	right: 0;
+	margin: auto;
+	text-align: center;
+}
+
+.cu-bar .action:first-child {
+	margin-left: 30upx;
+	font-size: 30upx;
+}
+
+.cu-bar .action text.text-cut {
+	text-align: left;
+	width: 100%;
+}
+
+.cu-bar .cu-avatar:first-child {
+	margin-left: 20upx;
+}
+
+.cu-bar .action:first-child>text[class*="cuIcon-"] {
+	margin-left: -0.3em;
+	margin-right: 0.3em;
+}
+
+.cu-bar .action:last-child {
+	margin-right: 30upx;
+}
+
+.cu-bar .action>text[class*="cuIcon-"],
+.cu-bar .action>view[class*="cuIcon-"] {
+	font-size: 36upx;
+}
+
+.cu-bar .action>text[class*="cuIcon-"]+text[class*="cuIcon-"] {
+	margin-left: 0.5em;
+}
+
+.cu-bar .content {
+	position: absolute;
+	text-align: center;
+	width: calc(100% - 340upx);
+	left: 0;
+	right: 0;
+	bottom: 0;
+	top: 0;
+	margin: auto;
+	height: 60upx;
+	font-size: 32upx;
+	line-height: 60upx;
+	cursor: none;
+	pointer-events: none;
+	text-overflow: ellipsis;
+	white-space: nowrap;
+	overflow: hidden;
+}
+
+.cu-bar.ios .content {
+	bottom: 7px;
+	height: 30px;
+	font-size: 32upx;
+	line-height: 30px;
+}
+
+.cu-bar.btn-group {
+	justify-content: space-around;
+}
+
+.cu-bar.btn-group button {
+	padding: 20upx 32upx;
+}
+
+.cu-bar.btn-group button {
+	flex: 1;
+	margin: 0 20upx;
+	max-width: 50%;
+}
+
+.cu-bar .search-form {
+	background-color: #f5f5f5;
+	line-height: 64upx;
+	height: 64upx;
+	font-size: 24upx;
+	color: #333333;
+	flex: 1;
+	display: flex;
+	align-items: center;
+	margin: 0 30upx;
+}
+
+.cu-bar .search-form+.action {
+	margin-right: 30upx;
+}
+
+.cu-bar .search-form input {
+	flex: 1;
+	padding-right: 30upx;
+	height: 64upx;
+	line-height: 64upx;
+	font-size: 26upx;
+	background-color: transparent;
+}
+
+.cu-bar .search-form [class*="cuIcon-"] {
+	margin: 0 0.5em 0 0.8em;
+}
+
+.cu-bar .search-form [class*="cuIcon-"]::before {
+	top: 0upx;
+}
+
+.cu-bar.fixed,
+.nav.fixed {
+	position: fixed;
+	width: 100%;
+	top: 0;
+	z-index: 1024;
+	box-shadow: 0 1upx 6upx rgba(0, 0, 0, 0.1);
+}
+
+.cu-bar.foot {
+	position: fixed;
+	width: 100%;
+	bottom: 0;
+	z-index: 1024;
+	box-shadow: 0 -1upx 6upx rgba(0, 0, 0, 0.1);
+}
+
+.cu-bar.tabbar {
+	padding: 0;
+	height: calc(100upx + env(safe-area-inset-bottom) / 2);
+	padding-bottom: calc(env(safe-area-inset-bottom) / 2);
+}
+
+.cu-tabbar-height {
+	min-height: 100upx;
+	height: calc(100upx + env(safe-area-inset-bottom) / 2);
+}
+
+.cu-bar.tabbar.shadow {
+	box-shadow: 0 -1upx 6upx rgba(0, 0, 0, 0.1);
+}
+
+.cu-bar.tabbar .action {
+	font-size: 22upx;
+	position: relative;
+	flex: 1;
+	text-align: center;
+	padding: 0;
+	display: block;
+	height: auto;
+	line-height: 1;
+	margin: 0;
+	background-color: inherit;
+	overflow: initial;
+}
+
+.cu-bar.tabbar.shop .action {
+	width: 140upx;
+	flex: initial;
+}
+
+.cu-bar.tabbar .action.add-action {
+	position: relative;
+	z-index: 2;
+	padding-top: 50upx;
+}
+
+.cu-bar.tabbar .action.add-action [class*="cuIcon-"] {
+	position: absolute;
+	width: 70upx;
+	z-index: 2;
+	height: 70upx;
+	border-radius: 50%;
+	line-height: 70upx;
+	font-size: 50upx;
+	top: -35upx;
+	left: 0;
+	right: 0;
+	margin: auto;
+	padding: 0;
+}
+
+.cu-bar.tabbar .action.add-action::after {
+	content: "";
+	position: absolute;
+	width: 100upx;
+	height: 100upx;
+	top: -50upx;
+	left: 0;
+	right: 0;
+	margin: auto;
+	box-shadow: 0 -3upx 8upx rgba(0, 0, 0, 0.08);
+	border-radius: 50upx;
+	background-color: inherit;
+	z-index: 0;
+}
+
+.cu-bar.tabbar .action.add-action::before {
+	content: "";
+	position: absolute;
+	width: 100upx;
+	height: 30upx;
+	bottom: 30upx;
+	left: 0;
+	right: 0;
+	margin: auto;
+	background-color: inherit;
+	z-index: 1;
+}
+
+.cu-bar.tabbar .btn-group {
+	flex: 1;
+	display: flex;
+	justify-content: space-around;
+	align-items: center;
+	padding: 0 10upx;
+}
+
+.cu-bar.tabbar button.action::after {
+	border: 0;
+}
+
+.cu-bar.tabbar .action [class*="cuIcon-"] {
+	width: 100upx;
+	position: relative;
+	display: block;
+	height: auto;
+	margin: 0 auto 10upx;
+	text-align: center;
+	font-size: 40upx;
+}
+
+.cu-bar.tabbar .action .cuIcon-cu-image {
+	margin: 0 auto;
+}
+
+.cu-bar.tabbar .action .cuIcon-cu-image image {
+	width: 50upx;
+	height: 50upx;
+	display: inline-block;
+}
+
+.cu-bar.tabbar .submit {
+	align-items: center;
+	display: flex;
+	justify-content: center;
+	text-align: center;
+	position: relative;
+	flex: 2;
+	align-self: stretch;
+}
+
+.cu-bar.tabbar .submit:last-child {
+	flex: 2.6;
+}
+
+.cu-bar.tabbar .submit+.submit {
+	flex: 2;
+}
+
+.cu-bar.tabbar.border .action::before {
+	content: " ";
+	width: 200%;
+	height: 200%;
+	position: absolute;
+	top: 0;
+	left: 0;
+	transform: scale(0.5);
+	transform-origin: 0 0;
+	border-right: 1upx solid rgba(0, 0, 0, 0.1);
+	z-index: 3;
+}
+
+.cu-bar.tabbar.border .action:last-child:before {
+	display: none;
+}
+
+.cu-bar.input {
+	padding-right: 20upx;
+	background-color: #ffffff;
+}
+
+.cu-bar.input input {
+	overflow: initial;
+	line-height: 64upx;
+	height: 64upx;
+	min-height: 64upx;
+	flex: 1;
+	font-size: 30upx;
+	margin: 0 20upx;
+}
+
+.cu-bar.input .action {
+	margin-left: 20upx;
+}
+
+.cu-bar.input .action [class*="cuIcon-"] {
+	font-size: 48upx;
+}
+
+.cu-bar.input input+.action {
+	margin-right: 20upx;
+	margin-left: 0upx;
+}
+
+.cu-bar.input .action:first-child [class*="cuIcon-"] {
+	margin-left: 0upx;
+}
+
+.cu-custom {
+	display: block;
+	position: relative;
+}
+
+.cu-custom .cu-bar .content {
+	width: calc(100% - 440upx);
+}
+
+/* #ifdef MP-ALIPAY */
+.cu-custom .cu-bar .action .cuIcon-back {
+	opacity: 0;
+}
+
+/* #endif */
+
+.cu-custom .cu-bar .content image {
+	height: 60upx;
+	width: 240upx;
+}
+
+.cu-custom .cu-bar {
+	min-height: 0px;
+	/* #ifdef MP-WEIXIN */
+	padding-right: 220upx;
+	/* #endif */
+	/* #ifdef MP-ALIPAY */
+	padding-right: 150upx;
+	/* #endif */
+	box-shadow: 0upx 0upx 0upx;
+	z-index: 9999;
+}
+
+.cu-custom .cu-bar .border-custom {
+	position: relative;
+	background: rgba(0, 0, 0, 0.15);
+	border-radius: 1000upx;
+	height: 30px;
+}
+
+.cu-custom .cu-bar .border-custom::after {
+	content: " ";
+	width: 200%;
+	height: 200%;
+	position: absolute;
+	top: 0;
+	left: 0;
+	border-radius: inherit;
+	transform: scale(0.5);
+	transform-origin: 0 0;
+	pointer-events: none;
+	box-sizing: border-box;
+	border: 1upx solid #ffffff;
+	opacity: 0.5;
+}
+
+.cu-custom .cu-bar .border-custom::before {
+	content: " ";
+	width: 1upx;
+	height: 110%;
+	position: absolute;
+	top: 22.5%;
+	left: 0;
+	right: 0;
+	margin: auto;
+	transform: scale(0.5);
+	transform-origin: 0 0;
+	pointer-events: none;
+	box-sizing: border-box;
+	opacity: 0.6;
+	background-color: #ffffff;
+}
+
+.cu-custom .cu-bar .border-custom text {
+	display: block;
+	flex: 1;
+	margin: auto !important;
+	text-align: center;
+	font-size: 34upx;
+}
+
+/* ==================
+         导航栏
+ ==================== */
+
+.nav {
+	white-space: nowrap;
+}
+
+::-webkit-scrollbar {
+	display: none;
+}
+
+.nav .cu-item {
+	height: 90upx;
+	display: inline-block;
+	line-height: 90upx;
+	margin: 0 10upx;
+	padding: 0 20upx;
+}
+
+.nav .cu-item.cur {
+	border-bottom: 4upx solid;
+}
+
+/* ==================
+         时间轴
+ ==================== */
+
+.cu-timeline {
+	display: block;
+	background-color: #ffffff;
+}
+
+.cu-timeline .cu-time {
+	width: 120upx;
+	text-align: center;
+	padding: 20upx 0;
+	font-size: 26upx;
+	color: #888;
+	display: block;
+}
+
+.cu-timeline>.cu-item {
+	padding: 30upx 30upx 30upx 120upx;
+	position: relative;
+	display: block;
+	z-index: 0;
+}
+
+.cu-timeline>.cu-item:not([class*="text-"]) {
+	color: #ccc;
+}
+
+.cu-timeline>.cu-item::after {
+	content: "";
+	display: block;
+	position: absolute;
+	width: 1upx;
+	background-color: #ddd;
+	left: 60upx;
+	height: 100%;
+	top: 0;
+	z-index: 8;
+}
+
+.cu-timeline>.cu-item::before {
+	font-family: "cuIcon";
+	display: block;
+	position: absolute;
+	top: 36upx;
+	z-index: 9;
+	background-color: #ffffff;
+	width: 50upx;
+	height: 50upx;
+	text-align: center;
+	border: none;
+	line-height: 50upx;
+	left: 36upx;
+}
+
+.cu-timeline>.cu-item:not([class*="cuIcon-"])::before {
+	content: "\e763";
+}
+
+.cu-timeline>.cu-item[class*="cuIcon-"]::before {
+	background-color: #ffffff;
+	width: 50upx;
+	height: 50upx;
+	text-align: center;
+	border: none;
+	line-height: 50upx;
+	left: 36upx;
+}
+
+.cu-timeline>.cu-item>.content {
+	padding: 30upx;
+	border-radius: 6upx;
+	display: block;
+	line-height: 1.6;
+}
+
+.cu-timeline>.cu-item>.content:not([class*="bg-"]) {
+	background-color: #f1f1f1;
+	color: #333333;
+}
+
+.cu-timeline>.cu-item>.content+.content {
+	margin-top: 20upx;
+}
+
+/* ==================
+         聊天
+ ==================== */
+
+.cu-chat {
+	display: flex;
+	flex-direction: column;
+}
+
+.cu-chat .cu-item {
+	display: flex;
+	padding: 30upx 30upx 70upx;
+	position: relative;
+}
+
+.cu-chat .cu-item>.cu-avatar {
+	width: 80upx;
+	height: 80upx;
+}
+
+.cu-chat .cu-item>.main {
+	max-width: calc(100% - 260upx);
+	margin: 0 40upx;
+	display: flex;
+	align-items: center;
+}
+
+.cu-chat .cu-item>image {
+	height: 320upx;
+}
+
+.cu-chat .cu-item>.main .content {
+	padding: 20upx;
+	border-radius: 6upx;
+	display: inline-flex;
+	max-width: 100%;
+	align-items: center;
+	font-size: 30upx;
+	position: relative;
+	min-height: 80upx;
+	line-height: 40upx;
+	text-align: left;
+}
+
+.cu-chat .cu-item>.main .content:not([class*="bg-"]) {
+	background-color: #ffffff;
+	color: #333333;
+}
+
+.cu-chat .cu-item .date {
+	position: absolute;
+	font-size: 24upx;
+	color: #8799a3;
+	width: calc(100% - 320upx);
+	bottom: 20upx;
+	left: 160upx;
+}
+
+.cu-chat .cu-item .action {
+	padding: 0 30upx;
+	display: flex;
+	align-items: center;
+}
+
+.cu-chat .cu-item>.main .content::after {
+	content: "";
+	top: 27upx;
+	transform: rotate(45deg);
+	position: absolute;
+	z-index: 100;
+	display: inline-block;
+	overflow: hidden;
+	width: 24upx;
+	height: 24upx;
+	left: -12upx;
+	right: initial;
+	background-color: inherit;
+}
+
+.cu-chat .cu-item.self>.main .content::after {
+	left: auto;
+	right: -12upx;
+}
+
+.cu-chat .cu-item>.main .content::before {
+	content: "";
+	top: 30upx;
+	transform: rotate(45deg);
+	position: absolute;
+	z-index: -1;
+	display: inline-block;
+	overflow: hidden;
+	width: 24upx;
+	height: 24upx;
+	left: -12upx;
+	right: initial;
+	background-color: inherit;
+	filter: blur(5upx);
+	opacity: 0.3;
+}
+
+.cu-chat .cu-item>.main .content:not([class*="bg-"])::before {
+	background-color: #333333;
+	opacity: 0.1;
+}
+
+.cu-chat .cu-item.self>.main .content::before {
+	left: auto;
+	right: -12upx;
+}
+
+.cu-chat .cu-item.self {
+	justify-content: flex-end;
+	text-align: right;
+}
+
+.cu-chat .cu-info {
+	display: inline-block;
+	margin: 20upx auto;
+	font-size: 24upx;
+	padding: 8upx 12upx;
+	background-color: rgba(0, 0, 0, 0.2);
+	border-radius: 6upx;
+	color: #ffffff;
+	max-width: 400upx;
+	line-height: 1.4;
+}
+
+/* ==================
+         卡片
+ ==================== */
+
+.cu-card {
+	display: block;
+	overflow: hidden;
+}
+
+.cu-card>.cu-item {
+	display: block;
+	background-color: #ffffff;
+	overflow: hidden;
+	border-radius: 10upx;
+	margin: 30upx;
+}
+
+.cu-card>.cu-item.shadow-blur {
+	overflow: initial;
+}
+
+.cu-card.no-card>.cu-item {
+	margin: 0upx;
+	border-radius: 0upx;
+}
+
+.cu-card .grid.grid-square {
+	margin-bottom: -20upx;
+}
+
+.cu-card.case .image {
+	position: relative;
+}
+
+.cu-card.case .image image {
+	width: 100%;
+}
+
+.cu-card.case .image .cu-tag {
+	position: absolute;
+	right: 0;
+	top: 0;
+}
+
+.cu-card.case .image .cu-bar {
+	position: absolute;
+	bottom: 0;
+	width: 100%;
+	background-color: transparent;
+	padding: 0upx 30upx;
+}
+
+.cu-card.case.no-card .image {
+	margin: 30upx 30upx 0;
+	overflow: hidden;
+	border-radius: 10upx;
+}
+
+.cu-card.dynamic {
+	display: block;
+}
+
+.cu-card.dynamic>.cu-item {
+	display: block;
+	background-color: #ffffff;
+	overflow: hidden;
+}
+
+.cu-card.dynamic>.cu-item>.text-content {
+	padding: 0 30upx 0;
+	max-height: 6.4em;
+	overflow: hidden;
+	font-size: 30upx;
+	margin-bottom: 20upx;
+}
+
+.cu-card.dynamic>.cu-item .square-img {
+	width: 100%;
+	height: 200upx;
+	border-radius: 6upx;
+}
+
+.cu-card.dynamic>.cu-item .only-img {
+	width: 100%;
+	height: 320upx;
+	border-radius: 6upx;
+}
+
+/* card.dynamic>.cu-item .comment {
+  padding: 20upx;
+  background-color: #f1f1f1;
+  margin: 0 30upx 30upx;
+  border-radius: 6upx;
+} */
+
+.cu-card.article {
+	display: block;
+}
+
+.cu-card.article>.cu-item {
+	padding-bottom: 30upx;
+}
+
+.cu-card.article>.cu-item .title {
+	font-size: 30upx;
+	font-weight: 900;
+	color: #333333;
+	line-height: 100upx;
+	padding: 0 30upx;
+}
+
+.cu-card.article>.cu-item .content {
+	display: flex;
+	padding: 0 30upx;
+}
+
+.cu-card.article>.cu-item .content>image {
+	width: 240upx;
+	height: 6.4em;
+	margin-right: 20upx;
+	border-radius: 6upx;
+}
+
+.cu-card.article>.cu-item .content .desc {
+	flex: 1;
+	display: flex;
+	flex-direction: column;
+	justify-content: space-between;
+}
+
+.cu-card.article>.cu-item .content .text-content {
+	font-size: 28upx;
+	color: #888;
+	height: 4.8em;
+	overflow: hidden;
+}
+
+/* ==================
+         表单
+ ==================== */
+
+.cu-form-group {
+	background-color: #ffffff;
+	padding: 1upx 30upx;
+	display: flex;
+	align-items: center;
+	min-height: 100upx;
+	justify-content: space-between;
+}
+
+.cu-form-group+.cu-form-group {
+	border-top: 1upx solid #eee;
+}
+
+.cu-form-group .title {
+	text-align: justify;
+	padding-right: 30upx;
+	font-size: 30upx;
+	position: relative;
+	height: 60upx;
+	line-height: 60upx;
+}
+
+.cu-form-group input {
+	flex: 1;
+	font-size: 30upx;
+	color: #555;
+	padding-right: 20upx;
+}
+
+.cu-form-group>text[class*="cuIcon-"] {
+	font-size: 36upx;
+	padding: 0;
+	box-sizing: border-box;
+}
+
+.cu-form-group textarea {
+	margin: 32upx 0 30upx;
+	height: 4.6em;
+	width: 100%;
+	line-height: 1.2em;
+	flex: 1;
+	font-size: 28upx;
+	padding: 0;
+}
+
+.cu-form-group.align-start .title {
+	height: 1em;
+	margin-top: 32upx;
+	line-height: 1em;
+}
+
+.cu-form-group picker {
+	flex: 1;
+	padding-right: 40upx;
+	overflow: hidden;
+	position: relative;
+}
+
+.cu-form-group picker .picker {
+	line-height: 100upx;
+	font-size: 28upx;
+	text-overflow: ellipsis;
+	white-space: nowrap;
+	overflow: hidden;
+	width: 100%;
+	text-align: right;
+}
+
+.cu-form-group picker::after {
+	font-family: cuIcon;
+	display: block;
+	content: "\e6a3";
+	position: absolute;
+	font-size: 34upx;
+	color: #8799a3;
+	line-height: 100upx;
+	width: 60upx;
+	text-align: center;
+	top: 0;
+	bottom: 0;
+	right: -20upx;
+	margin: auto;
+}
+
+.cu-form-group textarea[disabled],
+.cu-form-group textarea[disabled] .placeholder {
+	color: transparent;
+}
+
+/* ==================
+         模态窗口
+ ==================== */
+
+.cu-modal {
+	position: fixed;
+	top: 0;
+	right: 0;
+	bottom: 0;
+	left: 0;
+	z-index: 1110;
+	opacity: 0;
+	outline: 0;
+	text-align: center;
+	-ms-transform: scale(1.185);
+	transform: scale(1.185);
+	backface-visibility: hidden;
+	perspective: 2000upx;
+	background: rgba(0, 0, 0, 0.6);
+	transition: all 0.3s ease-in-out 0s;
+	pointer-events: none;
+}
+
+.cu-modal::before {
+	content: "\200B";
+	display: inline-block;
+	height: 100%;
+	vertical-align: middle;
+}
+
+.cu-modal.show {
+	opacity: 1;
+	transition-duration: 0.3s;
+	-ms-transform: scale(1);
+	transform: scale(1);
+	overflow-x: hidden;
+	overflow-y: auto;
+	pointer-events: auto;
+}
+
+.cu-dialog {
+	position: relative;
+	display: inline-block;
+	vertical-align: middle;
+	margin-left: auto;
+	margin-right: auto;
+	width: 680upx;
+	max-width: 100%;
+	background-color: #f8f8f8;
+	border-radius: 10upx;
+	overflow: hidden;
+}
+
+.cu-modal.bottom-modal::before {
+	vertical-align: bottom;
+}
+
+.cu-modal.bottom-modal .cu-dialog {
+	width: 100%;
+	border-radius: 0;
+}
+
+.cu-modal.bottom-modal {
+	margin-bottom: -1000upx;
+}
+
+.cu-modal.bottom-modal.show {
+	margin-bottom: 0;
+}
+
+.cu-modal.drawer-modal {
+	transform: scale(1);
+	display: flex;
+}
+
+.cu-modal.drawer-modal .cu-dialog {
+	height: 100%;
+	min-width: 200upx;
+	border-radius: 0;
+	margin: initial;
+	transition-duration: 0.3s;
+}
+
+.cu-modal.drawer-modal.justify-start .cu-dialog {
+	transform: translateX(-100%);
+}
+
+.cu-modal.drawer-modal.justify-end .cu-dialog {
+	transform: translateX(100%);
+}
+
+.cu-modal.drawer-modal.show .cu-dialog {
+	transform: translateX(0%);
+}
+.cu-modal .cu-dialog>.cu-bar:first-child .action{
+  min-width: 100rpx;
+  margin-right: 0;
+  min-height: 100rpx;
+}
+/* ==================
+         轮播
+ ==================== */
+swiper .a-swiper-dot {
+	display: inline-block;
+	width: 16upx;
+	height: 16upx;
+	background: rgba(0, 0, 0, .3);
+	border-radius: 50%;
+	vertical-align: middle;
+}
+
+swiper[class*="-dot"] .wx-swiper-dots,
+swiper[class*="-dot"] .a-swiper-dots,
+swiper[class*="-dot"] .uni-swiper-dots {
+	display: flex;
+	align-items: center;
+	width: 100%;
+	justify-content: center;
+}
+
+swiper.square-dot .wx-swiper-dot,
+swiper.square-dot .a-swiper-dot,
+swiper.square-dot .uni-swiper-dot {
+	background-color: #ffffff;
+	opacity: 0.4;
+	width: 10upx;
+	height: 10upx;
+	border-radius: 20upx;
+	margin: 0 8upx !important;
+}
+
+swiper.square-dot .wx-swiper-dot.wx-swiper-dot-active,
+swiper.square-dot .a-swiper-dot.a-swiper-dot-active,
+swiper.square-dot .uni-swiper-dot.uni-swiper-dot-active {
+	opacity: 1;
+	width: 30upx;
+}
+
+swiper.round-dot .wx-swiper-dot,
+swiper.round-dot .a-swiper-dot,
+swiper.round-dot .uni-swiper-dot {
+	width: 10upx;
+	height: 10upx;
+	position: relative;
+	margin: 4upx 8upx !important;
+}
+
+swiper.round-dot .wx-swiper-dot.wx-swiper-dot-active::after,
+swiper.round-dot .a-swiper-dot.a-swiper-dot-active::after,
+swiper.round-dot .uni-swiper-dot.uni-swiper-dot-active::after {
+	content: "";
+	position: absolute;
+	width: 10upx;
+	height: 10upx;
+	top: 0upx;
+	left: 0upx;
+	right: 0;
+	bottom: 0;
+	margin: auto;
+	background-color: #ffffff;
+	border-radius: 20upx;
+}
+
+swiper.round-dot .wx-swiper-dot.wx-swiper-dot-active,
+swiper.round-dot .a-swiper-dot.a-swiper-dot-active,
+swiper.round-dot .uni-swiper-dot.uni-swiper-dot-active {
+	width: 18upx;
+	height: 18upx;
+}
+
+.screen-swiper {
+	min-height: 375upx;
+}
+
+.screen-swiper image,
+.screen-swiper video,
+.swiper-item image,
+.swiper-item video {
+	width: 100%;
+	display: block;
+	height: 100%;
+	margin: 0;
+	pointer-events: none;
+}
+
+.card-swiper {
+	height: 420upx !important;
+}
+
+.card-swiper swiper-item {
+	width: 610upx !important;
+	left: 70upx;
+	box-sizing: border-box;
+	padding: 40upx 0upx 70upx;
+	overflow: initial;
+}
+
+.card-swiper swiper-item .swiper-item {
+	width: 100%;
+	display: block;
+	height: 100%;
+	border-radius: 10upx;
+	transform: scale(0.9);
+	transition: all 0.2s ease-in 0s;
+	overflow: hidden;
+}
+
+.card-swiper swiper-item.cur .swiper-item {
+	transform: none;
+	transition: all 0.2s ease-in 0s;
+}
+
+
+.tower-swiper {
+	height: 420upx;
+	position: relative;
+	max-width: 750upx;
+	overflow: hidden;
+}
+
+.tower-swiper .tower-item {
+	position: absolute;
+	width: 300upx;
+	height: 380upx;
+	top: 0;
+	bottom: 0;
+	left: 50%;
+	margin: auto;
+	transition: all 0.2s ease-in 0s;
+	opacity: 1;
+}
+
+.tower-swiper .tower-item.none {
+	opacity: 0;
+}
+
+.tower-swiper .tower-item .swiper-item {
+	width: 100%;
+	height: 100%;
+	border-radius: 6upx;
+	overflow: hidden;
+}
+
+/* ==================
+          步骤条
+ ==================== */
+
+.cu-steps {
+	display: flex;
+}
+
+scroll-view.cu-steps {
+	display: block;
+	white-space: nowrap;
+}
+
+scroll-view.cu-steps .cu-item {
+	display: inline-block;
+}
+
+.cu-steps .cu-item {
+	flex: 1;
+	text-align: center;
+	position: relative;
+	min-width: 100upx;
+}
+
+.cu-steps .cu-item:not([class*="text-"]) {
+	color: #8799a3;
+}
+
+.cu-steps .cu-item [class*="cuIcon-"],
+.cu-steps .cu-item .num {
+	display: block;
+	font-size: 40upx;
+	line-height: 80upx;
+}
+
+.cu-steps .cu-item::before,
+.cu-steps .cu-item::after,
+.cu-steps.steps-arrow .cu-item::before,
+.cu-steps.steps-arrow .cu-item::after {
+	content: "";
+	display: block;
+	position: absolute;
+	height: 0px;
+	width: calc(100% - 80upx);
+	border-bottom: 1px solid #ccc;
+	left: calc(0px - (100% - 80upx) / 2);
+	top: 40upx;
+	z-index: 0;
+}
+
+.cu-steps.steps-arrow .cu-item::before,
+.cu-steps.steps-arrow .cu-item::after {
+	content: "\e6a3";
+	font-family: 'cuIcon';
+	height: 30upx;
+	border-bottom-width: 0px;
+	line-height: 30upx;
+	top: 0;
+	bottom: 0;
+	margin: auto;
+	color: #ccc;
+}
+
+.cu-steps.steps-bottom .cu-item::before,
+.cu-steps.steps-bottom .cu-item::after {
+	bottom: 40upx;
+	top: initial;
+}
+
+.cu-steps .cu-item::after {
+	border-bottom: 1px solid currentColor;
+	width: 0px;
+	transition: all 0.3s ease-in-out 0s;
+}
+
+.cu-steps .cu-item[class*="text-"]::after {
+	width: calc(100% - 80upx);
+	color: currentColor;
+}
+
+.cu-steps .cu-item:first-child::before,
+.cu-steps .cu-item:first-child::after {
+	display: none;
+}
+
+.cu-steps .cu-item .num {
+	width: 40upx;
+	height: 40upx;
+	border-radius: 50%;
+	line-height: 40upx;
+	margin: 20upx auto;
+	font-size: 24upx;
+	border: 1px solid currentColor;
+	position: relative;
+	overflow: hidden;
+}
+
+.cu-steps .cu-item[class*="text-"] .num {
+	background-color: currentColor;
+}
+
+.cu-steps .cu-item .num::before,
+.cu-steps .cu-item .num::after {
+	content: attr(data-index);
+	position: absolute;
+	left: 0;
+	right: 0;
+	top: 0;
+	bottom: 0;
+	margin: auto;
+	transition: all 0.3s ease-in-out 0s;
+	transform: translateY(0upx);
+}
+
+.cu-steps .cu-item[class*="text-"] .num::before {
+	transform: translateY(-40upx);
+	color: #ffffff;
+}
+
+.cu-steps .cu-item .num::after {
+	transform: translateY(40upx);
+	color: #ffffff;
+	transition: all 0.3s ease-in-out 0s;
+}
+
+.cu-steps .cu-item[class*="text-"] .num::after {
+	content: "\e645";
+	font-family: 'cuIcon';
+	color: #ffffff;
+	transform: translateY(0upx);
+}
+
+.cu-steps .cu-item[class*="text-"] .num.err::after {
+	content: "\e646";
+}
+
+/* ==================
+          布局
+ ==================== */
+
+/*  -- flex弹性布局 -- */
+
+.flex {
+	display: flex;
+}
+
+.basis-xs {
+	flex-basis: 20%;
+}
+
+.basis-sm {
+	flex-basis: 40%;
+}
+
+.basis-df {
+	flex-basis: 50%;
+}
+
+.basis-lg {
+	flex-basis: 60%;
+}
+
+.basis-xl {
+	flex-basis: 80%;
+}
+
+.flex-sub {
+	flex: 1;
+}
+
+.flex-twice {
+	flex: 2;
+}
+
+.flex-treble {
+	flex: 3;
+}
+
+.flex-direction {
+	flex-direction: column;
+}
+
+.flex-wrap {
+	flex-wrap: wrap;
+}
+
+.align-start {
+	align-items: flex-start;
+}
+
+.align-end {
+	align-items: flex-end;
+}
+
+.align-center {
+	align-items: center;
+}
+
+.align-stretch {
+	align-items: stretch;
+}
+
+.self-start {
+	align-self: flex-start;
+}
+
+.self-center {
+	align-self: flex-center;
+}
+
+.self-end {
+	align-self: flex-end;
+}
+
+.self-stretch {
+	align-self: stretch;
+}
+
+.align-stretch {
+	align-items: stretch;
+}
+
+.justify-start {
+	justify-content: flex-start;
+}
+
+.justify-end {
+	justify-content: flex-end;
+}
+
+.justify-center {
+	justify-content: center;
+}
+
+.justify-between {
+	justify-content: space-between;
+}
+
+.justify-around {
+	justify-content: space-around;
+}
+
+/* grid布局 */
+
+.grid {
+	display: flex;
+	flex-wrap: wrap;
+}
+
+.grid.grid-square {
+	overflow: hidden;
+}
+
+.grid.grid-square .cu-tag {
+	position: absolute;
+	right: 0;
+	top: 0;
+	border-bottom-left-radius: 6upx;
+	padding: 6upx 12upx;
+	height: auto;
+	background-color: rgba(0, 0, 0, 0.5);
+}
+
+.grid.grid-square>view>text[class*="cuIcon-"] {
+	font-size: 52upx;
+	position: absolute;
+	color: #8799a3;
+	margin: auto;
+	top: 0;
+	bottom: 0;
+	left: 0;
+	right: 0;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	flex-direction: column;
+}
+
+.grid.grid-square>view {
+	margin-right: 20upx;
+	margin-bottom: 20upx;
+	border-radius: 6upx;
+	position: relative;
+	overflow: hidden;
+}
+.grid.grid-square>view.bg-img image {
+	width: 100%;
+	height: 100%;
+	position: absolute;
+}
+.grid.col-1.grid-square>view {
+	padding-bottom: 100%;
+	height: 0;
+	margin-right: 0;
+}
+
+.grid.col-2.grid-square>view {
+	padding-bottom: calc((100% - 20upx)/2);
+	height: 0;
+	width: calc((100% - 20upx)/2);
+}
+
+.grid.col-3.grid-square>view {
+	padding-bottom: calc((100% - 40upx)/3);
+	height: 0;
+	width: calc((100% - 40upx)/3);
+}
+
+.grid.col-4.grid-square>view {
+	padding-bottom: calc((100% - 60upx)/4);
+	height: 0;
+	width: calc((100% - 60upx)/4);
+}
+
+.grid.col-5.grid-square>view {
+	padding-bottom: calc((100% - 80upx)/5);
+	height: 0;
+	width: calc((100% - 80upx)/5);
+}
+
+.grid.col-2.grid-square>view:nth-child(2n),
+.grid.col-3.grid-square>view:nth-child(3n),
+.grid.col-4.grid-square>view:nth-child(4n),
+.grid.col-5.grid-square>view:nth-child(5n) {
+	margin-right: 0;
+}
+
+.grid.col-1>view {
+	width: 100%;
+}
+
+.grid.col-2>view {
+	width: 50%;
+}
+
+.grid.col-3>view {
+	width: 33.33%;
+}
+
+.grid.col-4>view {
+	width: 25%;
+}
+
+.grid.col-5>view {
+	width: 20%;
+}
+
+/*  -- 内外边距 -- */
+
+.margin-0 {
+	margin: 0;
+}
+
+.margin-xs {
+	margin: 10upx;
+}
+
+.margin-sm {
+	margin: 20upx;
+}
+
+.margin {
+	margin: 30upx;
+}
+
+.margin-lg {
+	margin: 40upx;
+}
+
+.margin-xl {
+	margin: 50upx;
+}
+
+.margin-top-xs {
+	margin-top: 10upx;
+}
+
+.margin-top-sm {
+	margin-top: 20upx;
+}
+
+.margin-top {
+	margin-top: 30upx;
+}
+
+.margin-top-lg {
+	margin-top: 40upx;
+}
+
+.margin-top-xl {
+	margin-top: 50upx;
+}
+
+.margin-right-xs {
+	margin-right: 10upx;
+}
+
+.margin-right-sm {
+	margin-right: 20upx;
+}
+
+.margin-right {
+	margin-right: 30upx;
+}
+
+.margin-right-lg {
+	margin-right: 40upx;
+}
+
+.margin-right-xl {
+	margin-right: 50upx;
+}
+
+.margin-bottom-xs {
+	margin-bottom: 10upx;
+}
+
+.margin-bottom-sm {
+	margin-bottom: 20upx;
+}
+
+.margin-bottom {
+	margin-bottom: 30upx;
+}
+
+.margin-bottom-lg {
+	margin-bottom: 40upx;
+}
+
+.margin-bottom-xl {
+	margin-bottom: 50upx;
+}
+
+.margin-left-xs {
+	margin-left: 10upx;
+}
+
+.margin-left-sm {
+	margin-left: 20upx;
+}
+
+.margin-left {
+	margin-left: 30upx;
+}
+
+.margin-left-lg {
+	margin-left: 40upx;
+}
+
+.margin-left-xl {
+	margin-left: 50upx;
+}
+
+.margin-lr-xs {
+	margin-left: 10upx;
+	margin-right: 10upx;
+}
+
+.margin-lr-sm {
+	margin-left: 20upx;
+	margin-right: 20upx;
+}
+
+.margin-lr {
+	margin-left: 30upx;
+	margin-right: 30upx;
+}
+
+.margin-lr-lg {
+	margin-left: 40upx;
+	margin-right: 40upx;
+}
+
+.margin-lr-xl {
+	margin-left: 50upx;
+	margin-right: 50upx;
+}
+
+.margin-tb-xs {
+	margin-top: 10upx;
+	margin-bottom: 10upx;
+}
+
+.margin-tb-sm {
+	margin-top: 20upx;
+	margin-bottom: 20upx;
+}
+
+.margin-tb {
+	margin-top: 30upx;
+	margin-bottom: 30upx;
+}
+
+.margin-tb-lg {
+	margin-top: 40upx;
+	margin-bottom: 40upx;
+}
+
+.margin-tb-xl {
+	margin-top: 50upx;
+	margin-bottom: 50upx;
+}
+
+.padding-0 {
+	padding: 0;
+}
+
+.padding-xs {
+	padding: 10upx;
+}
+
+.padding-sm {
+	padding: 20upx;
+}
+
+.padding {
+	padding: 30upx;
+}
+
+.padding-lg {
+	padding: 40upx;
+}
+
+.padding-xl {
+	padding: 50upx;
+}
+
+.padding-top-xs {
+	padding-top: 10upx;
+}
+
+.padding-top-sm {
+	padding-top: 20upx;
+}
+
+.padding-top {
+	padding-top: 30upx;
+}
+
+.padding-top-lg {
+	padding-top: 40upx;
+}
+
+.padding-top-xl {
+	padding-top: 50upx;
+}
+
+.padding-right-xs {
+	padding-right: 10upx;
+}
+
+.padding-right-sm {
+	padding-right: 20upx;
+}
+
+.padding-right {
+	padding-right: 30upx;
+}
+
+.padding-right-lg {
+	padding-right: 40upx;
+}
+
+.padding-right-xl {
+	padding-right: 50upx;
+}
+
+.padding-bottom-xs {
+	padding-bottom: 10upx;
+}
+
+.padding-bottom-sm {
+	padding-bottom: 20upx;
+}
+
+.padding-bottom {
+	padding-bottom: 30upx;
+}
+
+.padding-bottom-lg {
+	padding-bottom: 40upx;
+}
+
+.padding-bottom-xl {
+	padding-bottom: 50upx;
+}
+
+.padding-left-xs {
+	padding-left: 10upx;
+}
+
+.padding-left-sm {
+	padding-left: 20upx;
+}
+
+.padding-left {
+	padding-left: 30upx;
+}
+
+.padding-left-lg {
+	padding-left: 40upx;
+}
+
+.padding-left-xl {
+	padding-left: 50upx;
+}
+
+.padding-lr-xs {
+	padding-left: 10upx;
+	padding-right: 10upx;
+}
+
+.padding-lr-sm {
+	padding-left: 20upx;
+	padding-right: 20upx;
+}
+
+.padding-lr {
+	padding-left: 30upx;
+	padding-right: 30upx;
+}
+
+.padding-lr-lg {
+	padding-left: 40upx;
+	padding-right: 40upx;
+}
+
+.padding-lr-xl {
+	padding-left: 50upx;
+	padding-right: 50upx;
+}
+
+.padding-tb-xs {
+	padding-top: 10upx;
+	padding-bottom: 10upx;
+}
+
+.padding-tb-sm {
+	padding-top: 20upx;
+	padding-bottom: 20upx;
+}
+
+.padding-tb {
+	padding-top: 30upx;
+	padding-bottom: 30upx;
+}
+
+.padding-tb-lg {
+	padding-top: 40upx;
+	padding-bottom: 40upx;
+}
+
+.padding-tb-xl {
+	padding-top: 50upx;
+	padding-bottom: 50upx;
+}
+
+/* -- 浮动 --  */
+
+.cf::after,
+.cf::before {
+	content: " ";
+	display: table;
+}
+
+.cf::after {
+	clear: both;
+}
+
+.fl {
+	float: left;
+}
+
+.fr {
+	float: right;
+}
+
+/* ==================
+          背景
+ ==================== */
+
+.line-red::after,
+.lines-red::after {
+	border-color: #e54d42;
+}
+
+.line-orange::after,
+.lines-orange::after {
+	border-color: #f37b1d;
+}
+
+.line-yellow::after,
+.lines-yellow::after {
+	border-color: #fbbd08;
+}
+
+.line-olive::after,
+.lines-olive::after {
+	border-color: #8dc63f;
+}
+
+.line-green::after,
+.lines-green::after {
+	border-color: #39b54a;
+}
+
+.line-cyan::after,
+.lines-cyan::after {
+	border-color: #1cbbb4;
+}
+
+.line-blue::after,
+.lines-blue::after {
+	border-color: #0081ff;
+}
+
+.line-purple::after,
+.lines-purple::after {
+	border-color: #6739b6;
+}
+
+.line-mauve::after,
+.lines-mauve::after {
+	border-color: #9c26b0;
+}
+
+.line-pink::after,
+.lines-pink::after {
+	border-color: #e03997;
+}
+
+.line-brown::after,
+.lines-brown::after {
+	border-color: #a5673f;
+}
+
+.line-grey::after,
+.lines-grey::after {
+	border-color: #8799a3;
+}
+
+.line-gray::after,
+.lines-gray::after {
+	border-color: #aaaaaa;
+}
+
+.line-black::after,
+.lines-black::after {
+	border-color: #333333;
+}
+
+.line-white::after,
+.lines-white::after {
+	border-color: #ffffff;
+}
+
+.bg-red {
+	background-color: #e54d42;
+	color: #ffffff;
+}
+
+.bg-orange {
+	background-color: #f37b1d;
+	color: #ffffff;
+}
+
+.bg-yellow {
+	background-color: #fbbd08;
+	color: #333333;
+}
+
+.bg-olive {
+	background-color: #8dc63f;
+	color: #ffffff;
+}
+
+.bg-green {
+	background-color: #39b54a;
+	color: #ffffff;
+}
+
+.bg-cyan {
+	background-color: #1cbbb4;
+	color: #ffffff;
+}
+
+.bg-blue {
+	background-color: #0081ff;
+	color: #ffffff;
+}
+
+.bg-purple {
+	background-color: #6739b6;
+	color: #ffffff;
+}
+
+.bg-mauve {
+	background-color: #9c26b0;
+	color: #ffffff;
+}
+
+.bg-pink {
+	background-color: #e03997;
+	color: #ffffff;
+}
+
+.bg-brown {
+	background-color: #a5673f;
+	color: #ffffff;
+}
+
+.bg-grey {
+	background-color: #8799a3;
+	color: #ffffff;
+}
+
+.bg-gray {
+	background-color: #f0f0f0;
+	color: #333333;
+}
+
+.bg-black {
+	background-color: #333333;
+	color: #ffffff;
+}
+
+.bg-white {
+	background-color: #ffffff;
+	color: #666666;
+}
+
+.bg-shadeTop {
+	background-image: linear-gradient(rgba(0, 0, 0, 1), rgba(0, 0, 0, 0.01));
+	color: #ffffff;
+}
+
+.bg-shadeBottom {
+	background-image: linear-gradient(rgba(0, 0, 0, 0.01), rgba(0, 0, 0, 1));
+	color: #ffffff;
+}
+
+.bg-red.light {
+	color: #e54d42;
+	background-color: #fadbd9;
+}
+
+.bg-orange.light {
+	color: #f37b1d;
+	background-color: #fde6d2;
+}
+
+.bg-yellow.light {
+	color: #fbbd08;
+	background-color: #fef2ced2;
+}
+
+.bg-olive.light {
+	color: #8dc63f;
+	background-color: #e8f4d9;
+}
+
+.bg-green.light {
+	color: #39b54a;
+	background-color: #d7f0dbff;
+}
+
+.bg-cyan.light {
+	color: #1cbbb4;
+	background-color: #d2f1f0;
+}
+
+.bg-blue.light {
+	color: #0081ff;
+	background-color: #cce6ff;
+}
+
+.bg-purple.light {
+	color: #6739b6;
+	background-color: #e1d7f0;
+}
+
+.bg-mauve.light {
+	color: #9c26b0;
+	background-color: #ebd4ef;
+}
+
+.bg-pink.light {
+	color: #e03997;
+	background-color: #f9d7ea;
+}
+
+.bg-brown.light {
+	color: #a5673f;
+	background-color: #ede1d9;
+}
+
+.bg-grey.light {
+	color: #8799a3;
+	background-color: #e7ebed;
+}
+
+.bg-gradual-red {
+	background-image: linear-gradient(45deg, #f43f3b, #ec008c);
+	color: #ffffff;
+}
+
+.bg-gradual-orange {
+	background-image: linear-gradient(45deg, #ff9700, #ed1c24);
+	color: #ffffff;
+}
+
+.bg-gradual-green {
+	background-image: linear-gradient(45deg, #39b54a, #8dc63f);
+	color: #ffffff;
+}
+
+.bg-gradual-purple {
+	background-image: linear-gradient(45deg, #9000ff, #5e00ff);
+	color: #ffffff;
+}
+
+.bg-gradual-pink {
+	background-image: linear-gradient(45deg, #ec008c, #6739b6);
+	color: #ffffff;
+}
+
+.bg-gradual-blue {
+	background-image: linear-gradient(45deg, #0081ff, #1cbbb4);
+	color: #ffffff;
+}
+
+.shadow[class*="-red"] {
+	box-shadow: 6upx 6upx 8upx rgba(204, 69, 59, 0.2);
+}
+
+.shadow[class*="-orange"] {
+	box-shadow: 6upx 6upx 8upx rgba(217, 109, 26, 0.2);
+}
+
+.shadow[class*="-yellow"] {
+	box-shadow: 6upx 6upx 8upx rgba(224, 170, 7, 0.2);
+}
+
+.shadow[class*="-olive"] {
+	box-shadow: 6upx 6upx 8upx rgba(124, 173, 55, 0.2);
+}
+
+.shadow[class*="-green"] {
+	box-shadow: 6upx 6upx 8upx rgba(48, 156, 63, 0.2);
+}
+
+.shadow[class*="-cyan"] {
+	box-shadow: 6upx 6upx 8upx rgba(28, 187, 180, 0.2);
+}
+
+.shadow[class*="-blue"] {
+	box-shadow: 6upx 6upx 8upx rgba(0, 102, 204, 0.2);
+}
+
+.shadow[class*="-purple"] {
+	box-shadow: 6upx 6upx 8upx rgba(88, 48, 156, 0.2);
+}
+
+.shadow[class*="-mauve"] {
+	box-shadow: 6upx 6upx 8upx rgba(133, 33, 150, 0.2);
+}
+
+.shadow[class*="-pink"] {
+	box-shadow: 6upx 6upx 8upx rgba(199, 50, 134, 0.2);
+}
+
+.shadow[class*="-brown"] {
+	box-shadow: 6upx 6upx 8upx rgba(140, 88, 53, 0.2);
+}
+
+.shadow[class*="-grey"] {
+	box-shadow: 6upx 6upx 8upx rgba(114, 130, 138, 0.2);
+}
+
+.shadow[class*="-gray"] {
+	box-shadow: 6upx 6upx 8upx rgba(114, 130, 138, 0.2);
+}
+
+.shadow[class*="-black"] {
+	box-shadow: 6upx 6upx 8upx rgba(26, 26, 26, 0.2);
+}
+
+.shadow[class*="-white"] {
+	box-shadow: 6upx 6upx 8upx rgba(26, 26, 26, 0.2);
+}
+
+.text-shadow[class*="-red"] {
+	text-shadow: 6upx 6upx 8upx rgba(204, 69, 59, 0.2);
+}
+
+.text-shadow[class*="-orange"] {
+	text-shadow: 6upx 6upx 8upx rgba(217, 109, 26, 0.2);
+}
+
+.text-shadow[class*="-yellow"] {
+	text-shadow: 6upx 6upx 8upx rgba(224, 170, 7, 0.2);
+}
+
+.text-shadow[class*="-olive"] {
+	text-shadow: 6upx 6upx 8upx rgba(124, 173, 55, 0.2);
+}
+
+.text-shadow[class*="-green"] {
+	text-shadow: 6upx 6upx 8upx rgba(48, 156, 63, 0.2);
+}
+
+.text-shadow[class*="-cyan"] {
+	text-shadow: 6upx 6upx 8upx rgba(28, 187, 180, 0.2);
+}
+
+.text-shadow[class*="-blue"] {
+	text-shadow: 6upx 6upx 8upx rgba(0, 102, 204, 0.2);
+}
+
+.text-shadow[class*="-purple"] {
+	text-shadow: 6upx 6upx 8upx rgba(88, 48, 156, 0.2);
+}
+
+.text-shadow[class*="-mauve"] {
+	text-shadow: 6upx 6upx 8upx rgba(133, 33, 150, 0.2);
+}
+
+.text-shadow[class*="-pink"] {
+	text-shadow: 6upx 6upx 8upx rgba(199, 50, 134, 0.2);
+}
+
+.text-shadow[class*="-brown"] {
+	text-shadow: 6upx 6upx 8upx rgba(140, 88, 53, 0.2);
+}
+
+.text-shadow[class*="-grey"] {
+	text-shadow: 6upx 6upx 8upx rgba(114, 130, 138, 0.2);
+}
+
+.text-shadow[class*="-gray"] {
+	text-shadow: 6upx 6upx 8upx rgba(114, 130, 138, 0.2);
+}
+
+.text-shadow[class*="-black"] {
+	text-shadow: 6upx 6upx 8upx rgba(26, 26, 26, 0.2);
+}
+
+.bg-img {
+	background-size: cover;
+	background-position: center;
+	background-repeat: no-repeat;
+}
+
+.bg-mask {
+	background-color: #333333;
+	position: relative;
+}
+
+.bg-mask::after {
+	content: "";
+	border-radius: inherit;
+	width: 100%;
+	height: 100%;
+	display: block;
+	background-color: rgba(0, 0, 0, 0.4);
+	position: absolute;
+	left: 0;
+	right: 0;
+	bottom: 0;
+	top: 0;
+}
+
+.bg-mask view,
+.bg-mask cover-view {
+	z-index: 5;
+	position: relative;
+}
+
+.bg-video {
+	position: relative;
+}
+
+.bg-video video {
+	display: block;
+	height: 100%;
+	width: 100%;
+	-o-object-fit: cover;
+	object-fit: cover;
+	position: absolute;
+	top: 0;
+	z-index: 0;
+	pointer-events: none;
+}
+
+/* ==================
+          文本
+ ==================== */
+
+.text-xs {
+	font-size: 20upx;
+}
+
+.text-sm {
+	font-size: 24upx;
+}
+
+.text-df {
+	font-size: 28upx;
+}
+
+.text-lg {
+	font-size: 32upx;
+}
+
+.text-xl {
+	font-size: 36upx;
+}
+
+.text-xxl {
+	font-size: 44upx;
+}
+
+.text-sl {
+	font-size: 80upx;
+}
+
+.text-xsl {
+	font-size: 120upx;
+}
+
+.text-Abc {
+	text-transform: Capitalize;
+}
+
+.text-ABC {
+	text-transform: Uppercase;
+}
+
+.text-abc {
+	text-transform: Lowercase;
+}
+
+.text-price::before {
+	content: "¥";
+	font-size: 80%;
+	margin-right: 4upx;
+}
+
+.text-cut {
+	text-overflow: ellipsis;
+	white-space: nowrap;
+	overflow: hidden;
+}
+
+.text-bold {
+	font-weight: bold;
+}
+
+.text-center {
+	text-align: center;
+}
+
+.text-content {
+	line-height: 1.6;
+}
+
+.text-left {
+	text-align: left;
+}
+
+.text-right {
+	text-align: right;
+}
+
+.text-red,
+.line-red,
+.lines-red {
+	color: #e54d42;
+}
+
+.text-orange,
+.line-orange,
+.lines-orange {
+	color: #f37b1d;
+}
+
+.text-yellow,
+.line-yellow,
+.lines-yellow {
+	color: #fbbd08;
+}
+
+.text-olive,
+.line-olive,
+.lines-olive {
+	color: #8dc63f;
+}
+
+.text-green,
+.line-green,
+.lines-green {
+	color: #39b54a;
+}
+
+.text-cyan,
+.line-cyan,
+.lines-cyan {
+	color: #1cbbb4;
+}
+
+.text-blue,
+.line-blue,
+.lines-blue {
+	color: #0081ff;
+}
+
+.text-purple,
+.line-purple,
+.lines-purple {
+	color: #6739b6;
+}
+
+.text-mauve,
+.line-mauve,
+.lines-mauve {
+	color: #9c26b0;
+}
+
+.text-pink,
+.line-pink,
+.lines-pink {
+	color: #e03997;
+}
+
+.text-brown,
+.line-brown,
+.lines-brown {
+	color: #a5673f;
+}
+
+.text-grey,
+.line-grey,
+.lines-grey {
+	color: #8799a3;
+}
+
+.text-gray,
+.line-gray,
+.lines-gray {
+	color: #aaaaaa;
+}
+
+.text-black,
+.line-black,
+.lines-black {
+	color: #333333;
+}
+
+.text-white,
+.line-white,
+.lines-white {
+	color: #ffffff;
+}
diff --git a/yudao-ui-admin-uniapp/static/scss/global.scss b/yudao-ui-admin-uniapp/static/scss/global.scss
new file mode 100644
index 000000000..ac636bdf9
--- /dev/null
+++ b/yudao-ui-admin-uniapp/static/scss/global.scss
@@ -0,0 +1,90 @@
+.text-center {
+	text-align: center;
+}
+
+.font-13 {
+	font-size: 13px;
+}
+
+.font-12 {
+	font-size: 12px;
+}
+
+.font-11 {
+	font-size: 11px;
+}
+
+.text-grey1 {
+	color: #888;
+}
+.text-grey2 {
+	color: #aaa;
+}
+
+.list-cell-arrow::before {
+    content: ' ';
+    height: 10px;
+    width: 10px;
+    border-width: 2px 2px 0 0;
+    border-color: #c0c0c0;
+    border-style: solid;
+    -webkit-transform: matrix(0.5, 0.5, -0.5, 0.5, 0, 0);
+    transform: matrix(0.5, 0.5, -0.5, 0.5, 0, 0);
+    position: absolute;
+    top: 50%;
+    margin-top: -6px;
+    right: 30rpx;
+  }
+  
+  .list-cell {
+    position: relative;
+    width: 100%;
+    box-sizing: border-box;
+    background-color: #fff;
+    color: #333;
+    padding: 26rpx 30rpx;
+  }
+  
+  .list-cell:first-child {
+    border-radius: 8rpx 8rpx 0 0;
+  }
+  
+  .list-cell:last-child {
+    border-radius: 0 0 8rpx 8rpx;
+  }
+  
+  .list-cell::after {
+    content: '';
+    position: absolute;
+    border-bottom: 1px solid #eaeef1;
+    -webkit-transform: scaleY(0.5) translateZ(0);
+    transform: scaleY(0.5) translateZ(0);
+    transform-origin: 0 100%;
+    bottom: 0;
+    right: 0;
+    left: 0;
+    pointer-events: none;
+  }
+  
+  
+  .menu-list {
+    margin: 15px 15px;
+  
+    .menu-item-box {
+      width: 100%;
+      display: flex;
+      align-items: center;
+  
+      .menu-icon {
+        color: #007AFF;
+        font-size: 16px;
+        margin-right: 5px;
+      }
+      
+      .text-right {
+        margin-left: auto;
+        margin-right: 34rpx;
+        color: #999;
+      }
+    }
+  }
diff --git a/yudao-ui-admin-uniapp/static/scss/index.scss b/yudao-ui-admin-uniapp/static/scss/index.scss
new file mode 100644
index 000000000..745cffa25
--- /dev/null
+++ b/yudao-ui-admin-uniapp/static/scss/index.scss
@@ -0,0 +1,6 @@
+// global
+@import "./global.scss";
+// color-ui
+@import "@/static/scss/colorui.css";
+// iconfont
+@import "@/static/font/iconfont.css";
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/store/getters.js b/yudao-ui-admin-uniapp/store/getters.js
new file mode 100644
index 000000000..885479411
--- /dev/null
+++ b/yudao-ui-admin-uniapp/store/getters.js
@@ -0,0 +1,8 @@
+const getters = {
+  token: state => state.user.token,
+  avatar: state => state.user.avatar,
+  name: state => state.user.name,
+  roles: state => state.user.roles,
+  permissions: state => state.user.permissions
+}
+export default getters
diff --git a/yudao-ui-admin-uniapp/store/index.js b/yudao-ui-admin-uniapp/store/index.js
new file mode 100644
index 000000000..83a9db562
--- /dev/null
+++ b/yudao-ui-admin-uniapp/store/index.js
@@ -0,0 +1,15 @@
+import Vue from 'vue'
+import Vuex from 'vuex'
+import user from '@/store/modules/user'
+import getters from './getters'
+
+Vue.use(Vuex)
+
+const store = new Vuex.Store({
+  modules: {
+    user
+  },
+  getters
+})
+
+export default store
diff --git a/yudao-ui-admin-uniapp/store/modules/user.js b/yudao-ui-admin-uniapp/store/modules/user.js
new file mode 100644
index 000000000..d49cb9a9d
--- /dev/null
+++ b/yudao-ui-admin-uniapp/store/modules/user.js
@@ -0,0 +1,100 @@
+import config from '@/config'
+import storage from '@/utils/storage'
+import constant from '@/utils/constant'
+import { login, logout, getInfo } from '@/api/login'
+import { setToken, removeToken } from '@/utils/auth'
+
+const baseUrl = config.baseUrl
+
+const user = {
+  state: {
+    id: 0, // 用户编号
+    name: storage.get(constant.name),
+    avatar: storage.get(constant.avatar),
+    roles: storage.get(constant.roles),
+    permissions: storage.get(constant.permissions)
+  },
+
+  mutations: {
+    SET_ID: (state, id) => {
+      state.id = id
+    },
+    SET_NAME: (state, name) => {
+      state.name = name
+      storage.set(constant.name, name)
+    },
+    SET_AVATAR: (state, avatar) => {
+      state.avatar = avatar
+      storage.set(constant.avatar, avatar)
+    },
+    SET_ROLES: (state, roles) => {
+      state.roles = roles
+      storage.set(constant.roles, roles)
+    },
+    SET_PERMISSIONS: (state, permissions) => {
+      state.permissions = permissions
+      storage.set(constant.permissions, permissions)
+    }
+  },
+
+  actions: {
+    // 登录
+    Login({ commit }, userInfo) {
+      const username = userInfo.username.trim()
+      const password = userInfo.password
+      const code = userInfo.code
+      const uuid = userInfo.uuid
+      return new Promise((resolve, reject) => {
+        login(username, password, code, uuid).then(res => {
+          res = res.data;
+          // 设置 token
+          setToken(res)
+          resolve()
+        }).catch(error => {
+          reject(error)
+        })
+      })
+    },
+
+    // 获取用户信息
+    GetInfo({ commit, state }) {
+      return new Promise((resolve, reject) => {
+        getInfo().then(res => {
+          res = res.data; // 读取 data 数据
+          const user = res.user
+          const avatar = (user == null || user.avatar === "" || user.avatar == null) ? require("@/static/images/profile.jpg") : user.avatar
+          const nickname = (user == null || user.nickname === "" || user.nickname == null) ? "" : user.nickname
+          if (res.roles && res.roles.length > 0) {
+            commit('SET_ROLES', res.roles)
+            commit('SET_PERMISSIONS', res.permissions)
+          } else {
+            commit('SET_ROLES', ['ROLE_DEFAULT'])
+          }
+          commit('SET_NAME', nickname)
+          commit('SET_AVATAR', avatar)
+          resolve(res)
+        }).catch(error => {
+          reject(error)
+        })
+      })
+    },
+
+    // 退出系统
+    LogOut({ commit, state }) {
+      return new Promise((resolve, reject) => {
+        logout(state.token).then(() => {
+          commit('SET_TOKEN', '')
+          commit('SET_ROLES', [])
+          commit('SET_PERMISSIONS', [])
+          removeToken()
+          storage.clean()
+          resolve()
+        }).catch(error => {
+          reject(error)
+        })
+      })
+    }
+  }
+}
+
+export default user
diff --git a/yudao-ui-admin-uniapp/uni.scss b/yudao-ui-admin-uniapp/uni.scss
new file mode 100644
index 000000000..5b30ca317
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni.scss
@@ -0,0 +1,64 @@
+/**
+ * uni-app内置的常用样式变量
+ */
+
+/* 行为相关颜色 */
+$uni-color-primary: #007aff;
+$uni-color-success: #4cd964;
+$uni-color-warning: #f0ad4e;
+$uni-color-error: #dd524d;
+
+/* 文字基本颜色 */
+$uni-text-color:#333;//基本色
+$uni-text-color-inverse:#fff;//反色
+$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息
+$uni-text-color-placeholder: #808080;
+$uni-text-color-disable:#c0c0c0;
+
+/* 背景颜色 */
+$uni-bg-color:#ffffff;
+$uni-bg-color-grey:#f8f8f8;
+$uni-bg-color-hover:#f1f1f1;//点击状态颜色
+$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色
+
+/* 边框颜色 */
+$uni-border-color:#e5e5e5;
+
+/* 尺寸变量 */
+
+/* 文字尺寸 */
+$uni-font-size-sm:12px;
+$uni-font-size-base:14px;
+$uni-font-size-lg:16px;
+
+/* 图片尺寸 */
+$uni-img-size-sm:20px;
+$uni-img-size-base:26px;
+$uni-img-size-lg:40px;
+
+/* Border Radius */
+$uni-border-radius-sm: 2px;
+$uni-border-radius-base: 3px;
+$uni-border-radius-lg: 6px;
+$uni-border-radius-circle: 50%;
+
+/* 水平间距 */
+$uni-spacing-row-sm: 5px;
+$uni-spacing-row-base: 10px;
+$uni-spacing-row-lg: 15px;
+
+/* 垂直间距 */
+$uni-spacing-col-sm: 4px;
+$uni-spacing-col-base: 8px;
+$uni-spacing-col-lg: 12px;
+
+/* 透明度 */
+$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
+
+/* 文章场景相关 */
+$uni-color-title: #2C405A; // 文章标题颜色
+$uni-font-size-title:20px;
+$uni-color-subtitle: #555555; // 二级标题颜色
+$uni-font-size-subtitle:26px;
+$uni-color-paragraph: #3F536E; // 文章段落颜色
+$uni-font-size-paragraph:15px;
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-badge/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-badge/changelog.md
new file mode 100644
index 000000000..544ecc135
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-badge/changelog.md
@@ -0,0 +1,29 @@
+## 1.2.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-badge](https://uniapp.dcloud.io/component/uniui/uni-badge)
+## 1.1.7(2021-11-08)
+- 优化 升级ui
+- 修改 size 属性默认值调整为 small
+- 修改 type 属性,默认值调整为 error,info 替换 default
+## 1.1.6(2021-09-22)
+- 修复 在字节小程序上样式不生效的 bug
+## 1.1.5(2021-07-30)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.1.4(2021-07-29)
+- 修复 去掉 nvue 不支持css 的 align-self 属性,nvue 下不暂支持 absolute 属性
+## 1.1.3(2021-06-24)
+- 优化 示例项目
+## 1.1.1(2021-05-12)
+- 新增 组件示例地址
+## 1.1.0(2021-05-12)
+- 新增 uni-badge 的 absolute 属性,支持定位
+- 新增 uni-badge 的 offset 属性,支持定位偏移
+- 新增 uni-badge 的 is-dot 属性,支持仅显示有一个小点
+- 新增 uni-badge 的 max-num 属性,支持自定义封顶的数字值,超过 99 显示99+
+- 优化 uni-badge 属性 custom-style, 支持以对象形式自定义样式
+## 1.0.7(2021-05-07)
+- 修复 uni-badge 在 App 端,数字小于10时不是圆形的bug
+- 修复 uni-badge 在父元素不是 flex 布局时,宽度缩小的bug
+- 新增 uni-badge 属性 custom-style, 支持自定义样式
+## 1.0.6(2021-02-04)
+- 调整为uni_modules目录规范
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-badge/components/uni-badge/uni-badge.vue b/yudao-ui-admin-uniapp/uni_modules/uni-badge/components/uni-badge/uni-badge.vue
new file mode 100644
index 000000000..fcbfe9382
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-badge/components/uni-badge/uni-badge.vue
@@ -0,0 +1,268 @@
+<template>
+	<view class="uni-badge--x">
+		<slot />
+		<text v-if="text" :class="classNames" :style="[badgeWidth, positionStyle, customStyle, dotStyle]"
+			class="uni-badge" @click="onClick()">{{displayValue}}</text>
+	</view>
+</template>
+
+<script>
+	/**
+	 * Badge 数字角标
+	 * @description 数字角标一般和其它控件(列表、9宫格等)配合使用,用于进行数量提示,默认为实心灰色背景
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=21
+	 * @property {String} text 角标内容
+	 * @property {String} size = [normal|small] 角标内容
+	 * @property {String} type = [info|primary|success|warning|error] 颜色类型
+	 * 	@value info 灰色
+	 * 	@value primary 蓝色
+	 * 	@value success 绿色
+	 * 	@value warning 黄色
+	 * 	@value error 红色
+	 * @property {String} inverted = [true|false] 是否无需背景颜色
+	 * @property {Number} maxNum 展示封顶的数字值,超过 99 显示 99+
+	 * @property {String} absolute = [rightTop|rightBottom|leftBottom|leftTop] 开启绝对定位, 角标将定位到其包裹的标签的四角上		
+	 * 	@value rightTop 右上
+	 * 	@value rightBottom 右下
+	 * 	@value leftTop 左上
+	 * 	@value leftBottom 左下
+	 * @property {Array[number]} offset	距定位角中心点的偏移量,只有存在 absolute 属性时有效,例如:[-10, -10] 表示向外偏移 10px,[10, 10] 表示向 absolute 指定的内偏移 10px
+	 * @property {String} isDot = [true|false] 是否显示为一个小点
+	 * @event {Function} click 点击 Badge 触发事件
+	 * @example <uni-badge text="1"></uni-badge>
+	 */
+
+	export default {
+		name: 'UniBadge',
+		emits: ['click'],
+		props: {
+			type: {
+				type: String,
+				default: 'error'
+			},
+			inverted: {
+				type: Boolean,
+				default: false
+			},
+			isDot: {
+				type: Boolean,
+				default: false
+			},
+			maxNum: {
+				type: Number,
+				default: 99
+			},
+			absolute: {
+				type: String,
+				default: ''
+			},
+			offset: {
+				type: Array,
+				default () {
+					return [0, 0]
+				}
+			},
+			text: {
+				type: [String, Number],
+				default: ''
+			},
+			size: {
+				type: String,
+				default: 'small'
+			},
+			customStyle: {
+				type: Object,
+				default () {
+					return {}
+				}
+			}
+		},
+		data() {
+			return {};
+		},
+		computed: {
+			width() {
+				return String(this.text).length * 8 + 12
+			},
+			classNames() {
+				const {
+					inverted,
+					type,
+					size,
+					absolute
+				} = this
+				return [
+					inverted ? 'uni-badge--' + type + '-inverted' : '',
+					'uni-badge--' + type,
+					'uni-badge--' + size,
+					absolute ? 'uni-badge--absolute' : ''
+				].join(' ')
+			},
+			positionStyle() {
+				if (!this.absolute) return {}
+				let w = this.width / 2,
+					h = 10
+				if (this.isDot) {
+					w = 5
+					h = 5
+				}
+				const x = `${- w  + this.offset[0]}px`
+				const y = `${- h + this.offset[1]}px`
+
+				const whiteList = {
+					rightTop: {
+						right: x,
+						top: y
+					},
+					rightBottom: {
+						right: x,
+						bottom: y
+					},
+					leftBottom: {
+						left: x,
+						bottom: y
+					},
+					leftTop: {
+						left: x,
+						top: y
+					}
+				}
+				const match = whiteList[this.absolute]
+				return match ? match : whiteList['rightTop']
+			},
+			badgeWidth() {
+				return {
+					width: `${this.width}px`
+				}
+			},
+			dotStyle() {
+				if (!this.isDot) return {}
+				return {
+					width: '10px',
+					height: '10px',
+					borderRadius: '10px'
+				}
+			},
+			displayValue() {
+				const {
+					isDot,
+					text,
+					maxNum
+				} = this
+				return isDot ? '' : (Number(text) > maxNum ? `${maxNum}+` : text)
+			}
+		},
+		methods: {
+			onClick() {
+				this.$emit('click');
+			}
+		}
+	};
+</script>
+
+<style lang="scss" >
+	$uni-primary: #2979ff !default;
+	$uni-success: #4cd964 !default;
+	$uni-warning: #f0ad4e !default;
+	$uni-error: #dd524d !default;
+	$uni-info: #909399 !default;
+
+
+	$bage-size: 12px;
+	$bage-small: scale(0.8);
+
+	.uni-badge--x {
+		/* #ifdef APP-NVUE */
+		// align-self: flex-start;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		display: inline-block;
+		/* #endif */
+		position: relative;
+	}
+
+	.uni-badge--absolute {
+		position: absolute;
+	}
+
+	.uni-badge--small {
+		transform: $bage-small;
+		transform-origin: center center;
+	}
+
+	.uni-badge {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		overflow: hidden;
+		box-sizing: border-box;
+		/* #endif */
+		justify-content: center;
+		flex-direction: row;
+		height: 20px;
+		line-height: 18px;
+		color: #fff;
+		border-radius: 100px;
+		background-color: $uni-info;
+		background-color: transparent;
+		border: 1px solid #fff;
+		text-align: center;
+		font-family: 'Helvetica Neue', Helvetica, sans-serif;
+		font-size: $bage-size;
+		/* #ifdef H5 */
+		z-index: 999;
+		cursor: pointer;
+		/* #endif */
+
+		&--info {
+			color: #fff;
+			background-color: $uni-info;
+		}
+
+		&--primary {
+			background-color: $uni-primary;
+		}
+
+		&--success {
+			background-color: $uni-success;
+		}
+
+		&--warning {
+			background-color: $uni-warning;
+		}
+
+		&--error {
+			background-color: $uni-error;
+		}
+
+		&--inverted {
+			padding: 0 5px 0 0;
+			color: $uni-info;
+		}
+
+		&--info-inverted {
+			color: $uni-info;
+			background-color: transparent;
+		}
+
+		&--primary-inverted {
+			color: $uni-primary;
+			background-color: transparent;
+		}
+
+		&--success-inverted {
+			color: $uni-success;
+			background-color: transparent;
+		}
+
+		&--warning-inverted {
+			color: $uni-warning;
+			background-color: transparent;
+		}
+
+		&--error-inverted {
+			color: $uni-error;
+			background-color: transparent;
+		}
+
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-badge/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-badge/package.json
new file mode 100644
index 000000000..4e9e631ab
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-badge/package.json
@@ -0,0 +1,88 @@
+{
+  "id": "uni-badge",
+  "displayName": "uni-badge 数字角标",
+  "version": "1.2.0",
+  "description": "数字角标(徽章)组件,在元素周围展示消息提醒,一般用于列表、九宫格、按钮等地方。",
+  "keywords": [
+    "",
+    "badge",
+    "uni-ui",
+    "uniui",
+    "数字角标",
+    "徽章"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": ["uni-scss"],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "y",
+          "联盟": "y"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-badge/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-badge/readme.md
new file mode 100644
index 000000000..bdf175da9
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-badge/readme.md
@@ -0,0 +1,10 @@
+## Badge 数字角标
+> **组件名:uni-badge**
+> 代码块: `uBadge`
+
+数字角标一般和其它控件(列表、9宫格等)配合使用,用于进行数量提示,默认为实心灰色背景,
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-badge)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
+
+
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-breadcrumb/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-breadcrumb/changelog.md
new file mode 100644
index 000000000..016e6cee3
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-breadcrumb/changelog.md
@@ -0,0 +1,6 @@
+## 0.1.2(2022-06-08)
+- 修复 微信小程序 separator 不显示问题
+## 0.1.1(2022-06-02)
+- 新增 支持 uni.scss 修改颜色
+## 0.1.0(2022-04-21)
+- 初始化
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-breadcrumb/components/uni-breadcrumb-item/uni-breadcrumb-item.vue b/yudao-ui-admin-uniapp/uni_modules/uni-breadcrumb/components/uni-breadcrumb-item/uni-breadcrumb-item.vue
new file mode 100644
index 000000000..b9edbd622
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-breadcrumb/components/uni-breadcrumb-item/uni-breadcrumb-item.vue
@@ -0,0 +1,121 @@
+<template>
+	<view class="uni-breadcrumb-item">
+		<view :class="{
+			'uni-breadcrumb-item--slot': true,
+			'uni-breadcrumb-item--slot-link': to && currentPage !== to
+			}" @click="navTo">
+			<slot />
+		</view>
+		<i v-if="separatorClass" class="uni-breadcrumb-item--separator" :class="separatorClass" />
+		<text v-else class="uni-breadcrumb-item--separator">{{ separator }}</text>
+	</view>
+</template>
+<script>
+	/**
+	 * BreadcrumbItem 面包屑导航子组件
+	 * @property {String/Object} to 路由跳转页面路径/对象
+	 * @property {Boolean} replace 在使用 to 进行路由跳转时,启用 replace 将不会向 history 添加新记录(仅 h5 支持)
+	 */
+	export default {
+		data() {
+			return {
+				currentPage: ""
+			}
+		},
+		options: {
+			virtualHost: true
+		},
+		props: {
+			to: {
+				type: String,
+				default: ''
+			},
+			replace:{
+				type: Boolean,
+				default: false
+			}
+		},
+		inject: {
+			uniBreadcrumb: {
+				from: "uniBreadcrumb",
+				default: null
+			}
+		},
+		created(){
+			const pages = getCurrentPages()
+			const page = pages[pages.length-1]
+
+			if(page){
+				this.currentPage = `/${page.route}`
+			}
+		},
+		computed: {
+			separator() {
+				return this.uniBreadcrumb.separator
+			},
+			separatorClass() {
+				return this.uniBreadcrumb.separatorClass
+			}
+		},
+		methods: {
+			navTo() {
+				const { to } = this
+
+				if (!to || this.currentPage === to){
+					return
+				}
+
+				if(this.replace){
+					uni.redirectTo({
+						url:to
+					})
+				}else{
+					uni.navigateTo({
+						url:to
+					})
+				}
+			}
+		}
+	}
+</script>
+<style lang="scss">
+	$uni-primary: #2979ff !default;
+	$uni-base-color: #6a6a6a !default;
+	$uni-main-color: #3a3a3a !default;
+	.uni-breadcrumb-item {
+		display: flex;
+		align-items: center;
+		white-space: nowrap;
+		font-size: 14px;
+
+		&--slot {
+			color: $uni-base-color;
+			padding: 0 10px;
+
+			&-link {
+				color: $uni-main-color;
+				font-weight: bold;
+				/* #ifndef APP-NVUE */
+				cursor: pointer;
+				/* #endif */
+
+				&:hover {
+					color: $uni-primary;
+				}
+			}
+		}
+
+		&--separator {
+			font-size: 12px;
+			color: $uni-base-color;
+		}
+
+		&:first-child &--slot {
+			padding-left: 0;
+		}
+		
+		&:last-child &--separator {
+			display: none;
+		}
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-breadcrumb/components/uni-breadcrumb/uni-breadcrumb.vue b/yudao-ui-admin-uniapp/uni_modules/uni-breadcrumb/components/uni-breadcrumb/uni-breadcrumb.vue
new file mode 100644
index 000000000..94493a21f
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-breadcrumb/components/uni-breadcrumb/uni-breadcrumb.vue
@@ -0,0 +1,41 @@
+<template>
+	<view class="uni-breadcrumb">
+		<slot />
+	</view>
+</template>
+<script>
+	/**
+	 * Breadcrumb 面包屑导航父组件
+	 * @description 显示当前页面的路径,快速返回之前的任意页面
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=xxx
+	 * @property {String} separator 分隔符,默认为斜杠'/'
+	 * @property {String} separatorClass 图标分隔符 class
+	 */
+	export default {
+		options: {
+			virtualHost: true
+		},
+		props: {
+			separator: {
+				type: String,
+				default: '/'
+			},
+			separatorClass: {
+				type: String,
+				default: ''
+			}
+		},
+
+		provide() {
+			return {
+				uniBreadcrumb: this
+			}
+		}
+
+	}
+</script>
+<style lang="scss">
+	.uni-breadcrumb {
+		display: flex;
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-breadcrumb/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-breadcrumb/package.json
new file mode 100644
index 000000000..0a04e5032
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-breadcrumb/package.json
@@ -0,0 +1,88 @@
+{
+  "id": "uni-breadcrumb",
+  "displayName": "uni-breadcrumb 面包屑",
+  "version": "0.1.2",
+  "description": "Breadcrumb  面包屑",
+  "keywords": [
+    "uni-breadcrumb",
+    "breadcrumb",
+    "uni-ui",
+    "面包屑导航",
+    "面包屑"
+],
+  "repository": "",
+  "engines": {
+    "HBuilderX": "^3.1.0"
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+        "前端组件",
+        "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": ""
+  },
+  "uni_modules": {
+    "dependencies": [],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "Vue": {
+          "vue2": "y",
+          "vue3": "y"
+        },
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "n"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "u",
+          "百度": "u",
+          "字节跳动": "u",
+        "QQ": "u",
+        "京东": "u"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        }
+      }
+    }
+  }
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-breadcrumb/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-breadcrumb/readme.md
new file mode 100644
index 000000000..6976b8d7d
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-breadcrumb/readme.md
@@ -0,0 +1,66 @@
+
+## breadcrumb 面包屑导航
+> **组件名:uni-breadcrumb**
+> 代码块: `ubreadcrumb`
+
+显示当前页面的路径,快速返回之前的任意页面。
+
+### 安装方式
+
+本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。
+
+如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55)
+
+### 基本用法
+
+在 ``template`` 中使用组件
+
+```html
+<uni-breadcrumb separator="/">
+	<uni-breadcrumb-item v-for="(route,index) in routes" :key="index" :to="route.to">{{route.name}}</uni-breadcrumb-item>
+</uni-breadcrumb>
+```
+
+```js
+export default {
+		name: "uni-stat-breadcrumb",
+		data() {
+			return {
+				routes: [{
+					to: '/A',
+					name: 'A页面'
+				}, {
+					to: '/B',
+					name: 'B页面'
+				}, {
+					to: '/C',
+					name: 'C页面'
+				}]
+			};
+		}
+	}
+```
+
+
+## API
+
+### Breadcrumb Props
+
+|属性名			|类型	|默认值	|说明				|
+|:-:			|:-:	|:-:	|:-:				|
+|separator		|String	|斜杠'/' |分隔符				|
+|separatorClass	|String	|		|图标分隔符 class	    |
+
+### Breadcrumb Item Props
+
+|属性名	|类型			|默认值	|说明																			|
+|:-:	|:-:			|:-:	|:-:																			|
+|to		|String     	|		|路由跳转页面路径           														|
+|replace|Boolean		|		|在使用 to 进行路由跳转时,启用 replace 将不会向 history 添加新记录(仅 h5 支持)         |
+
+
+
+
+## 组件示例
+
+点击查看:[https://hellouniapp.dcloud.net.cn/pages/extUI/breadcrumb/breadcrumb](https://hellouniapp.dcloud.net.cn/pages/extUI/breadcrumb/breadcrumb)
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-calendar/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-calendar/changelog.md
new file mode 100644
index 000000000..6df4493eb
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-calendar/changelog.md
@@ -0,0 +1,16 @@
+## 1.4.5(2022-02-25)
+- 修复 条件编译 nvue 不支持的 css 样式
+## 1.4.4(2022-02-25)
+- 修复 条件编译 nvue 不支持的 css 样式
+## 1.4.3(2021-09-22)
+- 修复 startDate、 endDate 属性失效的 bug
+## 1.4.2(2021-08-24)
+- 新增 支持国际化
+## 1.4.1(2021-08-05)
+- 修复 弹出层被 tabbar 遮盖 bug
+## 1.4.0(2021-07-30)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.3.16(2021-05-12)
+- 新增 组件示例地址
+## 1.3.15(2021-02-04)
+- 调整为uni_modules目录规范 
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-calendar/components/uni-calendar/calendar.js b/yudao-ui-admin-uniapp/uni_modules/uni-calendar/components/uni-calendar/calendar.js
new file mode 100644
index 000000000..b8d7d6fc4
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-calendar/components/uni-calendar/calendar.js
@@ -0,0 +1,546 @@
+/**
+* @1900-2100区间内的公历、农历互转
+* @charset UTF-8
+* @github  https://github.com/jjonline/calendar.js
+* @Author  Jea杨(JJonline@JJonline.Cn)
+* @Time    2014-7-21
+* @Time    2016-8-13 Fixed 2033hex、Attribution Annals
+* @Time    2016-9-25 Fixed lunar LeapMonth Param Bug
+* @Time    2017-7-24 Fixed use getTerm Func Param Error.use solar year,NOT lunar year
+* @Version 1.0.3
+* @公历转农历:calendar.solar2lunar(1987,11,01); //[you can ignore params of prefix 0]
+* @农历转公历:calendar.lunar2solar(1987,09,10); //[you can ignore params of prefix 0]
+*/
+/* eslint-disable */
+var calendar = {
+
+  /**
+      * 农历1900-2100的润大小信息表
+      * @Array Of Property
+      * @return Hex
+      */
+  lunarInfo: [0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, // 1900-1909
+    0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977, // 1910-1919
+    0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, // 1920-1929
+    0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950, // 1930-1939
+    0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, // 1940-1949
+    0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5b0, 0x14573, 0x052b0, 0x0a9a8, 0x0e950, 0x06aa0, // 1950-1959
+    0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, // 1960-1969
+    0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b6a0, 0x195a6, // 1970-1979
+    0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570, // 1980-1989
+    0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x05ac0, 0x0ab60, 0x096d5, 0x092e0, // 1990-1999
+    0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5, // 2000-2009
+    0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, // 2010-2019
+    0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530, // 2020-2029
+    0x05aa0, 0x076a3, 0x096d0, 0x04afb, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, // 2030-2039
+    0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0, // 2040-2049
+    /** Add By JJonline@JJonline.Cn**/
+    0x14b63, 0x09370, 0x049f8, 0x04970, 0x064b0, 0x168a6, 0x0ea50, 0x06b20, 0x1a6c4, 0x0aae0, // 2050-2059
+    0x0a2e0, 0x0d2e3, 0x0c960, 0x0d557, 0x0d4a0, 0x0da50, 0x05d55, 0x056a0, 0x0a6d0, 0x055d4, // 2060-2069
+    0x052d0, 0x0a9b8, 0x0a950, 0x0b4a0, 0x0b6a6, 0x0ad50, 0x055a0, 0x0aba4, 0x0a5b0, 0x052b0, // 2070-2079
+    0x0b273, 0x06930, 0x07337, 0x06aa0, 0x0ad50, 0x14b55, 0x04b60, 0x0a570, 0x054e4, 0x0d160, // 2080-2089
+    0x0e968, 0x0d520, 0x0daa0, 0x16aa6, 0x056d0, 0x04ae0, 0x0a9d4, 0x0a2d0, 0x0d150, 0x0f252, // 2090-2099
+    0x0d520], // 2100
+
+  /**
+      * 公历每个月份的天数普通表
+      * @Array Of Property
+      * @return Number
+      */
+  solarMonth: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
+
+  /**
+      * 天干地支之天干速查表
+      * @Array Of Property trans["甲","乙","丙","丁","戊","己","庚","辛","壬","癸"]
+      * @return Cn string
+      */
+  Gan: ['\u7532', '\u4e59', '\u4e19', '\u4e01', '\u620a', '\u5df1', '\u5e9a', '\u8f9b', '\u58ec', '\u7678'],
+
+  /**
+      * 天干地支之地支速查表
+      * @Array Of Property
+      * @trans["子","丑","寅","卯","辰","巳","午","未","申","酉","戌","亥"]
+      * @return Cn string
+      */
+  Zhi: ['\u5b50', '\u4e11', '\u5bc5', '\u536f', '\u8fb0', '\u5df3', '\u5348', '\u672a', '\u7533', '\u9149', '\u620c', '\u4ea5'],
+
+  /**
+      * 天干地支之地支速查表<=>生肖
+      * @Array Of Property
+      * @trans["鼠","牛","虎","兔","龙","蛇","马","羊","猴","鸡","狗","猪"]
+      * @return Cn string
+      */
+  Animals: ['\u9f20', '\u725b', '\u864e', '\u5154', '\u9f99', '\u86c7', '\u9a6c', '\u7f8a', '\u7334', '\u9e21', '\u72d7', '\u732a'],
+
+  /**
+      * 24节气速查表
+      * @Array Of Property
+      * @trans["小寒","大寒","立春","雨水","惊蛰","春分","清明","谷雨","立夏","小满","芒种","夏至","小暑","大暑","立秋","处暑","白露","秋分","寒露","霜降","立冬","小雪","大雪","冬至"]
+      * @return Cn string
+      */
+  solarTerm: ['\u5c0f\u5bd2', '\u5927\u5bd2', '\u7acb\u6625', '\u96e8\u6c34', '\u60ca\u86f0', '\u6625\u5206', '\u6e05\u660e', '\u8c37\u96e8', '\u7acb\u590f', '\u5c0f\u6ee1', '\u8292\u79cd', '\u590f\u81f3', '\u5c0f\u6691', '\u5927\u6691', '\u7acb\u79cb', '\u5904\u6691', '\u767d\u9732', '\u79cb\u5206', '\u5bd2\u9732', '\u971c\u964d', '\u7acb\u51ac', '\u5c0f\u96ea', '\u5927\u96ea', '\u51ac\u81f3'],
+
+  /**
+      * 1900-2100各年的24节气日期速查表
+      * @Array Of Property
+      * @return 0x string For splice
+      */
+  sTermInfo: ['9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf97c3598082c95f8c965cc920f',
+    '97bd0b06bdb0722c965ce1cfcc920f', 'b027097bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
+    '97bcf97c359801ec95f8c965cc920f', '97bd0b06bdb0722c965ce1cfcc920f', 'b027097bd097c36b0b6fc9274c91aa',
+    '97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f', '97bd0b06bdb0722c965ce1cfcc920f',
+    'b027097bd097c36b0b6fc9274c91aa', '9778397bd19801ec9210c965cc920e', '97b6b97bd19801ec95f8c965cc920f',
+    '97bd09801d98082c95f8e1cfcc920f', '97bd097bd097c36b0b6fc9210c8dc2', '9778397bd197c36c9210c9274c91aa',
+    '97b6b97bd19801ec95f8c965cc920e', '97bd09801d98082c95f8e1cfcc920f', '97bd097bd097c36b0b6fc9210c8dc2',
+    '9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec95f8c965cc920e', '97bcf97c3598082c95f8e1cfcc920f',
+    '97bd097bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec9210c965cc920e',
+    '97bcf97c3598082c95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
+    '97b6b97bd19801ec9210c965cc920e', '97bcf97c3598082c95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722',
+    '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f',
+    '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
+    '97bcf97c359801ec95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
+    '97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f', '97bd097bd07f595b0b6fc920fb0722',
+    '9778397bd097c36b0b6fc9210c8dc2', '9778397bd19801ec9210c9274c920e', '97b6b97bd19801ec95f8c965cc920f',
+    '97bd07f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c920e',
+    '97b6b97bd19801ec95f8c965cc920f', '97bd07f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2',
+    '9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bd07f1487f595b0b0bc920fb0722',
+    '7f0e397bd097c36b0b6fc9210c8dc2', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
+    '97bcf7f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
+    '97b6b97bd19801ec9210c965cc920e', '97bcf7f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722',
+    '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf7f1487f531b0b0bb0b6fb0722',
+    '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
+    '97bcf7f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
+    '97b6b97bd19801ec9210c9274c920e', '97bcf7f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722',
+    '9778397bd097c36b0b6fc9210c91aa', '97b6b97bd197c36c9210c9274c920e', '97bcf7f0e47f531b0b0bb0b6fb0722',
+    '7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c920e',
+    '97b6b7f0e47f531b0723b0b6fb0722', '7f0e37f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2',
+    '9778397bd097c36b0b70c9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', '7f0e37f1487f595b0b0bb0b6fb0722',
+    '7f0e397bd097c35b0b6fc9210c8dc2', '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721',
+    '7f0e27f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
+    '97b6b7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722',
+    '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722',
+    '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721',
+    '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
+    '97b6b7f0e47f531b0723b0787b0721', '7f0e27f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722',
+    '9778397bd097c36b0b6fc9210c91aa', '97b6b7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722',
+    '7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9210c8dc2', '977837f0e37f149b0723b0787b0721',
+    '7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f5307f595b0b0bc920fb0722', '7f0e397bd097c35b0b6fc9210c8dc2',
+    '977837f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e37f1487f595b0b0bb0b6fb0722',
+    '7f0e397bd097c35b0b6fc9210c8dc2', '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
+    '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '977837f0e37f14998082b0787b06bd',
+    '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722',
+    '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722',
+    '7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
+    '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14998082b0787b06bd',
+    '7f07e7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722',
+    '977837f0e37f14998082b0723b06bd', '7f07e7f0e37f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722',
+    '7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b0721',
+    '7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f1487f595b0b0bb0b6fb0722', '7f0e37f0e37f14898082b0723b02d5',
+    '7ec967f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f1487f531b0b0bb0b6fb0722',
+    '7f0e37f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
+    '7f0e37f1487f531b0b0bb0b6fb0722', '7f0e37f0e37f14898082b072297c35', '7ec967f0e37f14998082b0787b06bd',
+    '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e37f0e37f14898082b072297c35',
+    '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722',
+    '7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f149b0723b0787b0721',
+    '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14998082b0723b06bd',
+    '7f07e7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722', '7f0e37f0e366aa89801eb072297c35',
+    '7ec967f0e37f14998082b0723b06bd', '7f07e7f0e37f14998083b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722',
+    '7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14898082b0723b02d5', '7f07e7f0e37f14998082b0787b0721',
+    '7f07e7f0e47f531b0723b0b6fb0722', '7f0e36665b66aa89801e9808297c35', '665f67f0e37f14898082b0723b02d5',
+    '7ec967f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0722', '7f0e36665b66a449801e9808297c35',
+    '665f67f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
+    '7f0e36665b66a449801e9808297c35', '665f67f0e37f14898082b072297c35', '7ec967f0e37f14998082b0787b06bd',
+    '7f07e7f0e47f531b0723b0b6fb0721', '7f0e26665b66a449801e9808297c35', '665f67f0e37f1489801eb072297c35',
+    '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722'],
+
+  /**
+      * 数字转中文速查表
+      * @Array Of Property
+      * @trans ['日','一','二','三','四','五','六','七','八','九','十']
+      * @return Cn string
+      */
+  nStr1: ['\u65e5', '\u4e00', '\u4e8c', '\u4e09', '\u56db', '\u4e94', '\u516d', '\u4e03', '\u516b', '\u4e5d', '\u5341'],
+
+  /**
+      * 日期转农历称呼速查表
+      * @Array Of Property
+      * @trans ['初','十','廿','卅']
+      * @return Cn string
+      */
+  nStr2: ['\u521d', '\u5341', '\u5eff', '\u5345'],
+
+  /**
+      * 月份转农历称呼速查表
+      * @Array Of Property
+      * @trans ['正','一','二','三','四','五','六','七','八','九','十','冬','腊']
+      * @return Cn string
+      */
+  nStr3: ['\u6b63', '\u4e8c', '\u4e09', '\u56db', '\u4e94', '\u516d', '\u4e03', '\u516b', '\u4e5d', '\u5341', '\u51ac', '\u814a'],
+
+  /**
+      * 返回农历y年一整年的总天数
+      * @param lunar Year
+      * @return Number
+      * @eg:var count = calendar.lYearDays(1987) ;//count=387
+      */
+  lYearDays: function (y) {
+    var i; var sum = 348
+    for (i = 0x8000; i > 0x8; i >>= 1) { sum += (this.lunarInfo[y - 1900] & i) ? 1 : 0 }
+    return (sum + this.leapDays(y))
+  },
+
+  /**
+      * 返回农历y年闰月是哪个月;若y年没有闰月 则返回0
+      * @param lunar Year
+      * @return Number (0-12)
+      * @eg:var leapMonth = calendar.leapMonth(1987) ;//leapMonth=6
+      */
+  leapMonth: function (y) { // 闰字编码 \u95f0
+    return (this.lunarInfo[y - 1900] & 0xf)
+  },
+
+  /**
+      * 返回农历y年闰月的天数 若该年没有闰月则返回0
+      * @param lunar Year
+      * @return Number (0、29、30)
+      * @eg:var leapMonthDay = calendar.leapDays(1987) ;//leapMonthDay=29
+      */
+  leapDays: function (y) {
+    if (this.leapMonth(y)) {
+      return ((this.lunarInfo[y - 1900] & 0x10000) ? 30 : 29)
+    }
+    return (0)
+  },
+
+  /**
+      * 返回农历y年m月(非闰月)的总天数,计算m为闰月时的天数请使用leapDays方法
+      * @param lunar Year
+      * @return Number (-1、29、30)
+      * @eg:var MonthDay = calendar.monthDays(1987,9) ;//MonthDay=29
+      */
+  monthDays: function (y, m) {
+    if (m > 12 || m < 1) { return -1 }// 月份参数从1至12,参数错误返回-1
+    return ((this.lunarInfo[y - 1900] & (0x10000 >> m)) ? 30 : 29)
+  },
+
+  /**
+      * 返回公历(!)y年m月的天数
+      * @param solar Year
+      * @return Number (-1、28、29、30、31)
+      * @eg:var solarMonthDay = calendar.leapDays(1987) ;//solarMonthDay=30
+      */
+  solarDays: function (y, m) {
+    if (m > 12 || m < 1) { return -1 } // 若参数错误 返回-1
+    var ms = m - 1
+    if (ms == 1) { // 2月份的闰平规律测算后确认返回28或29
+      return (((y % 4 == 0) && (y % 100 != 0) || (y % 400 == 0)) ? 29 : 28)
+    } else {
+      return (this.solarMonth[ms])
+    }
+  },
+
+  /**
+     * 农历年份转换为干支纪年
+     * @param  lYear 农历年的年份数
+     * @return Cn string
+     */
+  toGanZhiYear: function (lYear) {
+    var ganKey = (lYear - 3) % 10
+    var zhiKey = (lYear - 3) % 12
+    if (ganKey == 0) ganKey = 10// 如果余数为0则为最后一个天干
+    if (zhiKey == 0) zhiKey = 12// 如果余数为0则为最后一个地支
+    return this.Gan[ganKey - 1] + this.Zhi[zhiKey - 1]
+  },
+
+  /**
+     * 公历月、日判断所属星座
+     * @param  cMonth [description]
+     * @param  cDay [description]
+     * @return Cn string
+     */
+  toAstro: function (cMonth, cDay) {
+    var s = '\u9b54\u7faf\u6c34\u74f6\u53cc\u9c7c\u767d\u7f8a\u91d1\u725b\u53cc\u5b50\u5de8\u87f9\u72ee\u5b50\u5904\u5973\u5929\u79e4\u5929\u874e\u5c04\u624b\u9b54\u7faf'
+    var arr = [20, 19, 21, 21, 21, 22, 23, 23, 23, 23, 22, 22]
+    return s.substr(cMonth * 2 - (cDay < arr[cMonth - 1] ? 2 : 0), 2) + '\u5ea7'// 座
+  },
+
+  /**
+      * 传入offset偏移量返回干支
+      * @param offset 相对甲子的偏移量
+      * @return Cn string
+      */
+  toGanZhi: function (offset) {
+    return this.Gan[offset % 10] + this.Zhi[offset % 12]
+  },
+
+  /**
+      * 传入公历(!)y年获得该年第n个节气的公历日期
+      * @param y公历年(1900-2100);n二十四节气中的第几个节气(1~24);从n=1(小寒)算起
+      * @return day Number
+      * @eg:var _24 = calendar.getTerm(1987,3) ;//_24=4;意即1987年2月4日立春
+      */
+  getTerm: function (y, n) {
+    if (y < 1900 || y > 2100) { return -1 }
+    if (n < 1 || n > 24) { return -1 }
+    var _table = this.sTermInfo[y - 1900]
+    var _info = [
+      parseInt('0x' + _table.substr(0, 5)).toString(),
+      parseInt('0x' + _table.substr(5, 5)).toString(),
+      parseInt('0x' + _table.substr(10, 5)).toString(),
+      parseInt('0x' + _table.substr(15, 5)).toString(),
+      parseInt('0x' + _table.substr(20, 5)).toString(),
+      parseInt('0x' + _table.substr(25, 5)).toString()
+    ]
+    var _calday = [
+      _info[0].substr(0, 1),
+      _info[0].substr(1, 2),
+      _info[0].substr(3, 1),
+      _info[0].substr(4, 2),
+
+      _info[1].substr(0, 1),
+      _info[1].substr(1, 2),
+      _info[1].substr(3, 1),
+      _info[1].substr(4, 2),
+
+      _info[2].substr(0, 1),
+      _info[2].substr(1, 2),
+      _info[2].substr(3, 1),
+      _info[2].substr(4, 2),
+
+      _info[3].substr(0, 1),
+      _info[3].substr(1, 2),
+      _info[3].substr(3, 1),
+      _info[3].substr(4, 2),
+
+      _info[4].substr(0, 1),
+      _info[4].substr(1, 2),
+      _info[4].substr(3, 1),
+      _info[4].substr(4, 2),
+
+      _info[5].substr(0, 1),
+      _info[5].substr(1, 2),
+      _info[5].substr(3, 1),
+      _info[5].substr(4, 2)
+    ]
+    return parseInt(_calday[n - 1])
+  },
+
+  /**
+      * 传入农历数字月份返回汉语通俗表示法
+      * @param lunar month
+      * @return Cn string
+      * @eg:var cnMonth = calendar.toChinaMonth(12) ;//cnMonth='腊月'
+      */
+  toChinaMonth: function (m) { // 月 => \u6708
+    if (m > 12 || m < 1) { return -1 } // 若参数错误 返回-1
+    var s = this.nStr3[m - 1]
+    s += '\u6708'// 加上月字
+    return s
+  },
+
+  /**
+      * 传入农历日期数字返回汉字表示法
+      * @param lunar day
+      * @return Cn string
+      * @eg:var cnDay = calendar.toChinaDay(21) ;//cnMonth='廿一'
+      */
+  toChinaDay: function (d) { // 日 => \u65e5
+    var s
+    switch (d) {
+      case 10:
+        s = '\u521d\u5341'; break
+      case 20:
+        s = '\u4e8c\u5341'; break
+        break
+      case 30:
+        s = '\u4e09\u5341'; break
+        break
+      default :
+        s = this.nStr2[Math.floor(d / 10)]
+        s += this.nStr1[d % 10]
+    }
+    return (s)
+  },
+
+  /**
+      * 年份转生肖[!仅能大致转换] => 精确划分生肖分界线是“立春”
+      * @param y year
+      * @return Cn string
+      * @eg:var animal = calendar.getAnimal(1987) ;//animal='兔'
+      */
+  getAnimal: function (y) {
+    return this.Animals[(y - 4) % 12]
+  },
+
+  /**
+      * 传入阳历年月日获得详细的公历、农历object信息 <=>JSON
+      * @param y  solar year
+      * @param m  solar month
+      * @param d  solar day
+      * @return JSON object
+      * @eg:console.log(calendar.solar2lunar(1987,11,01));
+      */
+  solar2lunar: function (y, m, d) { // 参数区间1900.1.31~2100.12.31
+    // 年份限定、上限
+    if (y < 1900 || y > 2100) {
+      return -1// undefined转换为数字变为NaN
+    }
+    // 公历传参最下限
+    if (y == 1900 && m == 1 && d < 31) {
+      return -1
+    }
+    // 未传参  获得当天
+    if (!y) {
+      var objDate = new Date()
+    } else {
+      var objDate = new Date(y, parseInt(m) - 1, d)
+    }
+    var i; var leap = 0; var temp = 0
+    // 修正ymd参数
+    var y = objDate.getFullYear()
+    var m = objDate.getMonth() + 1
+    var d = objDate.getDate()
+    var offset = (Date.UTC(objDate.getFullYear(), objDate.getMonth(), objDate.getDate()) - Date.UTC(1900, 0, 31)) / 86400000
+    for (i = 1900; i < 2101 && offset > 0; i++) {
+      temp = this.lYearDays(i)
+      offset -= temp
+    }
+    if (offset < 0) {
+      offset += temp; i--
+    }
+
+    // 是否今天
+    var isTodayObj = new Date()
+    var isToday = false
+    if (isTodayObj.getFullYear() == y && isTodayObj.getMonth() + 1 == m && isTodayObj.getDate() == d) {
+      isToday = true
+    }
+    // 星期几
+    var nWeek = objDate.getDay()
+    var cWeek = this.nStr1[nWeek]
+    // 数字表示周几顺应天朝周一开始的惯例
+    if (nWeek == 0) {
+      nWeek = 7
+    }
+    // 农历年
+    var year = i
+    var leap = this.leapMonth(i) // 闰哪个月
+    var isLeap = false
+
+    // 效验闰月
+    for (i = 1; i < 13 && offset > 0; i++) {
+      // 闰月
+      if (leap > 0 && i == (leap + 1) && isLeap == false) {
+        --i
+        isLeap = true; temp = this.leapDays(year) // 计算农历闰月天数
+      } else {
+        temp = this.monthDays(year, i)// 计算农历普通月天数
+      }
+      // 解除闰月
+      if (isLeap == true && i == (leap + 1)) { isLeap = false }
+      offset -= temp
+    }
+    // 闰月导致数组下标重叠取反
+    if (offset == 0 && leap > 0 && i == leap + 1) {
+      if (isLeap) {
+        isLeap = false
+      } else {
+        isLeap = true; --i
+      }
+    }
+    if (offset < 0) {
+      offset += temp; --i
+    }
+    // 农历月
+    var month = i
+    // 农历日
+    var day = offset + 1
+    // 天干地支处理
+    var sm = m - 1
+    var gzY = this.toGanZhiYear(year)
+
+    // 当月的两个节气
+    // bugfix-2017-7-24 11:03:38 use lunar Year Param `y` Not `year`
+    var firstNode = this.getTerm(y, (m * 2 - 1))// 返回当月「节」为几日开始
+    var secondNode = this.getTerm(y, (m * 2))// 返回当月「节」为几日开始
+
+    // 依据12节气修正干支月
+    var gzM = this.toGanZhi((y - 1900) * 12 + m + 11)
+    if (d >= firstNode) {
+      gzM = this.toGanZhi((y - 1900) * 12 + m + 12)
+    }
+
+    // 传入的日期的节气与否
+    var isTerm = false
+    var Term = null
+    if (firstNode == d) {
+      isTerm = true
+      Term = this.solarTerm[m * 2 - 2]
+    }
+    if (secondNode == d) {
+      isTerm = true
+      Term = this.solarTerm[m * 2 - 1]
+    }
+    // 日柱 当月一日与 1900/1/1 相差天数
+    var dayCyclical = Date.UTC(y, sm, 1, 0, 0, 0, 0) / 86400000 + 25567 + 10
+    var gzD = this.toGanZhi(dayCyclical + d - 1)
+    // 该日期所属的星座
+    var astro = this.toAstro(m, d)
+
+    return { 'lYear': year, 'lMonth': month, 'lDay': day, 'Animal': this.getAnimal(year), 'IMonthCn': (isLeap ? '\u95f0' : '') + this.toChinaMonth(month), 'IDayCn': this.toChinaDay(day), 'cYear': y, 'cMonth': m, 'cDay': d, 'gzYear': gzY, 'gzMonth': gzM, 'gzDay': gzD, 'isToday': isToday, 'isLeap': isLeap, 'nWeek': nWeek, 'ncWeek': '\u661f\u671f' + cWeek, 'isTerm': isTerm, 'Term': Term, 'astro': astro }
+  },
+
+  /**
+      * 传入农历年月日以及传入的月份是否闰月获得详细的公历、农历object信息 <=>JSON
+      * @param y  lunar year
+      * @param m  lunar month
+      * @param d  lunar day
+      * @param isLeapMonth  lunar month is leap or not.[如果是农历闰月第四个参数赋值true即可]
+      * @return JSON object
+      * @eg:console.log(calendar.lunar2solar(1987,9,10));
+      */
+  lunar2solar: function (y, m, d, isLeapMonth) { // 参数区间1900.1.31~2100.12.1
+    var isLeapMonth = !!isLeapMonth
+    var leapOffset = 0
+    var leapMonth = this.leapMonth(y)
+    var leapDay = this.leapDays(y)
+    if (isLeapMonth && (leapMonth != m)) { return -1 }// 传参要求计算该闰月公历 但该年得出的闰月与传参的月份并不同
+    if (y == 2100 && m == 12 && d > 1 || y == 1900 && m == 1 && d < 31) { return -1 }// 超出了最大极限值
+    var day = this.monthDays(y, m)
+    var _day = day
+    // bugFix 2016-9-25
+    // if month is leap, _day use leapDays method
+    if (isLeapMonth) {
+      _day = this.leapDays(y, m)
+    }
+    if (y < 1900 || y > 2100 || d > _day) { return -1 }// 参数合法性效验
+
+    // 计算农历的时间差
+    var offset = 0
+    for (var i = 1900; i < y; i++) {
+      offset += this.lYearDays(i)
+    }
+    var leap = 0; var isAdd = false
+    for (var i = 1; i < m; i++) {
+      leap = this.leapMonth(y)
+      if (!isAdd) { // 处理闰月
+        if (leap <= i && leap > 0) {
+          offset += this.leapDays(y); isAdd = true
+        }
+      }
+      offset += this.monthDays(y, i)
+    }
+    // 转换闰月农历 需补充该年闰月的前一个月的时差
+    if (isLeapMonth) { offset += day }
+    // 1900年农历正月一日的公历时间为1900年1月30日0时0分0秒(该时间也是本农历的最开始起始点)
+    var stmap = Date.UTC(1900, 1, 30, 0, 0, 0)
+    var calObj = new Date((offset + d - 31) * 86400000 + stmap)
+    var cY = calObj.getUTCFullYear()
+    var cM = calObj.getUTCMonth() + 1
+    var cD = calObj.getUTCDate()
+
+    return this.solar2lunar(cY, cM, cD)
+  }
+}
+
+export default calendar
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-calendar/components/uni-calendar/i18n/en.json b/yudao-ui-admin-uniapp/uni_modules/uni-calendar/components/uni-calendar/i18n/en.json
new file mode 100644
index 000000000..fcbd13cfc
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-calendar/components/uni-calendar/i18n/en.json
@@ -0,0 +1,12 @@
+{
+	"uni-calender.ok": "ok",
+	"uni-calender.cancel": "cancel",
+	"uni-calender.today": "today",
+	"uni-calender.MON": "MON",
+	"uni-calender.TUE": "TUE",
+	"uni-calender.WED": "WED",
+	"uni-calender.THU": "THU",
+	"uni-calender.FRI": "FRI",
+	"uni-calender.SAT": "SAT",
+	"uni-calender.SUN": "SUN"
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-calendar/components/uni-calendar/i18n/index.js b/yudao-ui-admin-uniapp/uni_modules/uni-calendar/components/uni-calendar/i18n/index.js
new file mode 100644
index 000000000..de7509c87
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-calendar/components/uni-calendar/i18n/index.js
@@ -0,0 +1,8 @@
+import en from './en.json'
+import zhHans from './zh-Hans.json'
+import zhHant from './zh-Hant.json'
+export default {
+	en,
+	'zh-Hans': zhHans,
+	'zh-Hant': zhHant
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hans.json b/yudao-ui-admin-uniapp/uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hans.json
new file mode 100644
index 000000000..1ca43de01
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hans.json
@@ -0,0 +1,12 @@
+{
+	"uni-calender.ok": "确定",
+	"uni-calender.cancel": "取消",
+	"uni-calender.today": "今日",
+	"uni-calender.SUN": "日",
+	"uni-calender.MON": "一",
+	"uni-calender.TUE": "二",
+	"uni-calender.WED": "三",
+	"uni-calender.THU": "四",
+	"uni-calender.FRI": "五",
+	"uni-calender.SAT": "六"
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hant.json b/yudao-ui-admin-uniapp/uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hant.json
new file mode 100644
index 000000000..e0fe33b95
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-calendar/components/uni-calendar/i18n/zh-Hant.json
@@ -0,0 +1,12 @@
+{
+	"uni-calender.ok": "確定",
+	"uni-calender.cancel": "取消",
+	"uni-calender.today": "今日",
+	"uni-calender.SUN": "日",
+	"uni-calender.MON": "一",
+	"uni-calender.TUE": "二",
+	"uni-calender.WED": "三",
+	"uni-calender.THU": "四",
+	"uni-calender.FRI": "五",
+	"uni-calender.SAT": "六"
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-calendar/components/uni-calendar/uni-calendar-item.vue b/yudao-ui-admin-uniapp/uni_modules/uni-calendar/components/uni-calendar/uni-calendar-item.vue
new file mode 100644
index 000000000..30bd6c849
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-calendar/components/uni-calendar/uni-calendar-item.vue
@@ -0,0 +1,188 @@
+<template>
+	<view class="uni-calendar-item__weeks-box" :class="{
+		'uni-calendar-item--disable':weeks.disable,
+		'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
+		'uni-calendar-item--checked':(calendar.fullDate === weeks.fullDate && !weeks.isDay) ,
+		'uni-calendar-item--before-checked':weeks.beforeMultiple,
+		'uni-calendar-item--multiple': weeks.multiple,
+		'uni-calendar-item--after-checked':weeks.afterMultiple,
+		}"
+	 @click="choiceDate(weeks)">
+		<view class="uni-calendar-item__weeks-box-item">
+			<text v-if="selected&&weeks.extraInfo" class="uni-calendar-item__weeks-box-circle"></text>
+			<text class="uni-calendar-item__weeks-box-text" :class="{
+				'uni-calendar-item--isDay-text': weeks.isDay,
+				'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
+				'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
+				'uni-calendar-item--before-checked':weeks.beforeMultiple,
+				'uni-calendar-item--multiple': weeks.multiple,
+				'uni-calendar-item--after-checked':weeks.afterMultiple,
+				'uni-calendar-item--disable':weeks.disable,
+				}">{{weeks.date}}</text>
+			<text v-if="!lunar&&!weeks.extraInfo && weeks.isDay" class="uni-calendar-item__weeks-lunar-text" :class="{
+				'uni-calendar-item--isDay-text':weeks.isDay,
+				'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
+				'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
+				'uni-calendar-item--before-checked':weeks.beforeMultiple,
+				'uni-calendar-item--multiple': weeks.multiple,
+				'uni-calendar-item--after-checked':weeks.afterMultiple,
+				}">{{todayText}}</text>
+			<text v-if="lunar&&!weeks.extraInfo" class="uni-calendar-item__weeks-lunar-text" :class="{
+				'uni-calendar-item--isDay-text':weeks.isDay,
+				'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
+				'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
+				'uni-calendar-item--before-checked':weeks.beforeMultiple,
+				'uni-calendar-item--multiple': weeks.multiple,
+				'uni-calendar-item--after-checked':weeks.afterMultiple,
+				'uni-calendar-item--disable':weeks.disable,
+				}">{{weeks.isDay ? todayText : (weeks.lunar.IDayCn === '初一'?weeks.lunar.IMonthCn:weeks.lunar.IDayCn)}}</text>
+			<text v-if="weeks.extraInfo&&weeks.extraInfo.info" class="uni-calendar-item__weeks-lunar-text" :class="{
+				'uni-calendar-item--extra':weeks.extraInfo.info,
+				'uni-calendar-item--isDay-text':weeks.isDay,
+				'uni-calendar-item--isDay':calendar.fullDate === weeks.fullDate && weeks.isDay,
+				'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && !weeks.isDay,
+				'uni-calendar-item--before-checked':weeks.beforeMultiple,
+				'uni-calendar-item--multiple': weeks.multiple,
+				'uni-calendar-item--after-checked':weeks.afterMultiple,
+				'uni-calendar-item--disable':weeks.disable,
+				}">{{weeks.extraInfo.info}}</text>
+		</view>
+	</view>
+</template>
+
+<script>
+	import {
+	initVueI18n
+	} from '@dcloudio/uni-i18n'
+	import messages from './i18n/index.js'
+	const {	t	} = initVueI18n(messages)
+	export default {
+		emits:['change'],
+		props: {
+			weeks: {
+				type: Object,
+				default () {
+					return {}
+				}
+			},
+			calendar: {
+				type: Object,
+				default: () => {
+					return {}
+				}
+			},
+			selected: {
+				type: Array,
+				default: () => {
+					return []
+				}
+			},
+			lunar: {
+				type: Boolean,
+				default: false
+			}
+		},
+		computed: {
+			todayText() {
+				return t("uni-calender.today")
+			},
+		},
+		methods: {
+			choiceDate(weeks) {
+				this.$emit('change', weeks)
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	$uni-font-size-base:14px;
+	$uni-text-color:#333;
+	$uni-font-size-sm:12px;
+	$uni-color-error: #e43d33;
+	$uni-opacity-disabled: 0.3;
+	$uni-text-color-disable:#c0c0c0;
+	$uni-color-primary: #2979ff;
+	.uni-calendar-item__weeks-box {
+		flex: 1;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		justify-content: center;
+		align-items: center;
+	}
+
+	.uni-calendar-item__weeks-box-text {
+		font-size: $uni-font-size-base;
+		color: $uni-text-color;
+	}
+
+	.uni-calendar-item__weeks-lunar-text {
+		font-size: $uni-font-size-sm;
+		color: $uni-text-color;
+	}
+
+	.uni-calendar-item__weeks-box-item {
+		position: relative;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		justify-content: center;
+		align-items: center;
+		width: 100rpx;
+		height: 100rpx;
+	}
+
+	.uni-calendar-item__weeks-box-circle {
+		position: absolute;
+		top: 5px;
+		right: 5px;
+		width: 8px;
+		height: 8px;
+		border-radius: 8px;
+		background-color: $uni-color-error;
+
+	}
+
+	.uni-calendar-item--disable {
+		background-color: rgba(249, 249, 249, $uni-opacity-disabled);
+		color: $uni-text-color-disable;
+	}
+
+	.uni-calendar-item--isDay-text {
+		color: $uni-color-primary;
+	}
+
+	.uni-calendar-item--isDay {
+		background-color: $uni-color-primary;
+		opacity: 0.8;
+		color: #fff;
+	}
+
+	.uni-calendar-item--extra {
+		color: $uni-color-error;
+		opacity: 0.8;
+	}
+
+	.uni-calendar-item--checked {
+		background-color: $uni-color-primary;
+		color: #fff;
+		opacity: 0.8;
+	}
+
+	.uni-calendar-item--multiple {
+		background-color: $uni-color-primary;
+		color: #fff;
+		opacity: 0.8;
+	}
+	.uni-calendar-item--before-checked {
+		background-color: #ff5a5f;
+		color: #fff;
+	}
+	.uni-calendar-item--after-checked {
+		background-color: #ff5a5f;
+		color: #fff;
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-calendar/components/uni-calendar/uni-calendar.vue b/yudao-ui-admin-uniapp/uni_modules/uni-calendar/components/uni-calendar/uni-calendar.vue
new file mode 100644
index 000000000..88381db73
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-calendar/components/uni-calendar/uni-calendar.vue
@@ -0,0 +1,562 @@
+<template>
+	<view class="uni-calendar">
+		<view v-if="!insert&&show" class="uni-calendar__mask" :class="{'uni-calendar--mask-show':aniMaskShow}" @click="clean"></view>
+		<view v-if="insert || show" class="uni-calendar__content" :class="{'uni-calendar--fixed':!insert,'uni-calendar--ani-show':aniMaskShow}">
+			<view v-if="!insert" class="uni-calendar__header uni-calendar--fixed-top">
+				<view class="uni-calendar__header-btn-box" @click="close">
+					<text class="uni-calendar__header-text uni-calendar--fixed-width">{{cancelText}}</text>
+				</view>
+				<view class="uni-calendar__header-btn-box" @click="confirm">
+					<text class="uni-calendar__header-text uni-calendar--fixed-width">{{okText}}</text>
+				</view>
+			</view>
+			<view class="uni-calendar__header">
+				<view class="uni-calendar__header-btn-box" @click.stop="pre">
+					<view class="uni-calendar__header-btn uni-calendar--left"></view>
+				</view>
+				<picker mode="date" :value="date" fields="month" @change="bindDateChange">
+					<text class="uni-calendar__header-text">{{ (nowDate.year||'') +' / '+( nowDate.month||'')}}</text>
+				</picker>
+				<view class="uni-calendar__header-btn-box" @click.stop="next">
+					<view class="uni-calendar__header-btn uni-calendar--right"></view>
+				</view>
+				<text class="uni-calendar__backtoday" @click="backtoday">{{todayText}}</text>
+
+			</view>
+			<view class="uni-calendar__box">
+				<view v-if="showMonth" class="uni-calendar__box-bg">
+					<text class="uni-calendar__box-bg-text">{{nowDate.month}}</text>
+				</view>
+				<view class="uni-calendar__weeks">
+					<view class="uni-calendar__weeks-day">
+						<text class="uni-calendar__weeks-day-text">{{SUNText}}</text>
+					</view>
+					<view class="uni-calendar__weeks-day">
+						<text class="uni-calendar__weeks-day-text">{{monText}}</text>
+					</view>
+					<view class="uni-calendar__weeks-day">
+						<text class="uni-calendar__weeks-day-text">{{TUEText}}</text>
+					</view>
+					<view class="uni-calendar__weeks-day">
+						<text class="uni-calendar__weeks-day-text">{{WEDText}}</text>
+					</view>
+					<view class="uni-calendar__weeks-day">
+						<text class="uni-calendar__weeks-day-text">{{THUText}}</text>
+					</view>
+					<view class="uni-calendar__weeks-day">
+						<text class="uni-calendar__weeks-day-text">{{FRIText}}</text>
+					</view>
+					<view class="uni-calendar__weeks-day">
+						<text class="uni-calendar__weeks-day-text">{{SATText}}</text>
+					</view>
+				</view>
+				<view class="uni-calendar__weeks" v-for="(item,weekIndex) in weeks" :key="weekIndex">
+					<view class="uni-calendar__weeks-item" v-for="(weeks,weeksIndex) in item" :key="weeksIndex">
+						<calendar-item class="uni-calendar-item--hook" :weeks="weeks" :calendar="calendar" :selected="selected" :lunar="lunar" @change="choiceDate"></calendar-item>
+					</view>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import Calendar from './util.js';
+	import calendarItem from './uni-calendar-item.vue'
+	import {
+	initVueI18n
+	} from '@dcloudio/uni-i18n'
+	import messages from './i18n/index.js'
+	const {	t	} = initVueI18n(messages)
+	/**
+	 * Calendar 日历
+	 * @description 日历组件可以查看日期,选择任意范围内的日期,打点操作。常用场景如:酒店日期预订、火车机票选择购买日期、上下班打卡等
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=56
+	 * @property {String} date 自定义当前时间,默认为今天
+	 * @property {Boolean} lunar 显示农历
+	 * @property {String} startDate 日期选择范围-开始日期
+	 * @property {String} endDate 日期选择范围-结束日期
+	 * @property {Boolean} range 范围选择
+	 * @property {Boolean} insert = [true|false] 插入模式,默认为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 是否选择月份为背景
+	 * @event {Function} change 日期改变,`insert :ture` 时生效
+	 * @event {Function} confirm 确认选择`insert :false` 时生效
+	 * @event {Function} monthSwitch 切换月份时触发
+	 * @example <uni-calendar :insert="true":lunar="true" :start-date="'2019-3-2'":end-date="'2019-5-20'"@change="change" />
+	 */
+	export default {
+		components: {
+			calendarItem
+		},
+		emits:['close','confirm','change','monthSwitch'],
+		props: {
+			date: {
+				type: String,
+				default: ''
+			},
+			selected: {
+				type: Array,
+				default () {
+					return []
+				}
+			},
+			lunar: {
+				type: Boolean,
+				default: false
+			},
+			startDate: {
+				type: String,
+				default: ''
+			},
+			endDate: {
+				type: String,
+				default: ''
+			},
+			range: {
+				type: Boolean,
+				default: false
+			},
+			insert: {
+				type: Boolean,
+				default: true
+			},
+			showMonth: {
+				type: Boolean,
+				default: true
+			},
+			clearDate: {
+				type: Boolean,
+				default: true
+			}
+		},
+		data() {
+			return {
+				show: false,
+				weeks: [],
+				calendar: {},
+				nowDate: '',
+				aniMaskShow: false
+			}
+		},
+		computed:{
+			/**
+			 * for i18n
+			 */
+
+			okText() {
+				return t("uni-calender.ok")
+			},
+			cancelText() {
+				return t("uni-calender.cancel")
+			},
+			todayText() {
+				return t("uni-calender.today")
+			},
+			monText() {
+				return t("uni-calender.MON")
+			},
+			TUEText() {
+				return t("uni-calender.TUE")
+			},
+			WEDText() {
+				return t("uni-calender.WED")
+			},
+			THUText() {
+				return t("uni-calender.THU")
+			},
+			FRIText() {
+				return t("uni-calender.FRI")
+			},
+			SATText() {
+				return t("uni-calender.SAT")
+			},
+			SUNText() {
+				return t("uni-calender.SUN")
+			},
+		},
+		watch: {
+			date(newVal) {
+				// this.cale.setDate(newVal)
+				this.init(newVal)
+			},
+			startDate(val){
+				this.cale.resetSatrtDate(val)
+				this.cale.setDate(this.nowDate.fullDate)
+				this.weeks = this.cale.weeks
+			},
+			endDate(val){
+				this.cale.resetEndDate(val)
+				this.cale.setDate(this.nowDate.fullDate)
+				this.weeks = this.cale.weeks
+			},
+			selected(newVal) {
+				this.cale.setSelectInfo(this.nowDate.fullDate, newVal)
+				this.weeks = this.cale.weeks
+			}
+		},
+		created() {
+			// 获取日历方法实例
+			this.cale = new Calendar({
+				// date: new Date(),
+				selected: this.selected,
+				startDate: this.startDate,
+				endDate: this.endDate,
+				range: this.range,
+			})
+			// 选中某一天
+			// this.cale.setDate(this.date)
+			this.init(this.date)
+			// this.setDay
+		},
+		methods: {
+			// 取消穿透
+			clean() {},
+			bindDateChange(e) {
+				const value = e.detail.value + '-1'
+				console.log(this.cale.getDate(value));
+				this.init(value)
+			},
+			/**
+			 * 初始化日期显示
+			 * @param {Object} date
+			 */
+			init(date) {
+				this.cale.setDate(date)
+				this.weeks = this.cale.weeks
+				this.nowDate = this.calendar = this.cale.getInfo(date)
+			},
+			/**
+			 * 打开日历弹窗
+			 */
+			open() {
+				// 弹窗模式并且清理数据
+				if (this.clearDate && !this.insert) {
+					this.cale.cleanMultipleStatus()
+					// this.cale.setDate(this.date)
+					this.init(this.date)
+				}
+				this.show = true
+				this.$nextTick(() => {
+					setTimeout(() => {
+						this.aniMaskShow = true
+					}, 50)
+				})
+			},
+			/**
+			 * 关闭日历弹窗
+			 */
+			close() {
+				this.aniMaskShow = false
+				this.$nextTick(() => {
+					setTimeout(() => {
+						this.show = false
+						this.$emit('close')
+					}, 300)
+				})
+			},
+			/**
+			 * 确认按钮
+			 */
+			confirm() {
+				this.setEmit('confirm')
+				this.close()
+			},
+			/**
+			 * 变化触发
+			 */
+			change() {
+				if (!this.insert) return
+				this.setEmit('change')
+			},
+			/**
+			 * 选择月份触发
+			 */
+			monthSwitch() {
+				let {
+					year,
+					month
+				} = this.nowDate
+				this.$emit('monthSwitch', {
+					year,
+					month: Number(month)
+				})
+			},
+			/**
+			 * 派发事件
+			 * @param {Object} name
+			 */
+			setEmit(name) {
+				let {
+					year,
+					month,
+					date,
+					fullDate,
+					lunar,
+					extraInfo
+				} = this.calendar
+				this.$emit(name, {
+					range: this.cale.multipleStatus,
+					year,
+					month,
+					date,
+					fulldate: fullDate,
+					lunar,
+					extraInfo: extraInfo || {}
+				})
+			},
+			/**
+			 * 选择天触发
+			 * @param {Object} weeks
+			 */
+			choiceDate(weeks) {
+				if (weeks.disable) return
+				this.calendar = weeks
+				// 设置多选
+				this.cale.setMultiple(this.calendar.fullDate)
+				this.weeks = this.cale.weeks
+				this.change()
+			},
+			/**
+			 * 回到今天
+			 */
+			backtoday() {
+				console.log(this.cale.getDate(new Date()).fullDate);
+				let date = this.cale.getDate(new Date()).fullDate
+				// this.cale.setDate(date)
+				this.init(date)
+				this.change()
+			},
+			/**
+			 * 上个月
+			 */
+			pre() {
+				const preDate = this.cale.getDate(this.nowDate.fullDate, -1, 'month').fullDate
+				this.setDate(preDate)
+				this.monthSwitch()
+
+			},
+			/**
+			 * 下个月
+			 */
+			next() {
+				const nextDate = this.cale.getDate(this.nowDate.fullDate, +1, 'month').fullDate
+				this.setDate(nextDate)
+				this.monthSwitch()
+			},
+			/**
+			 * 设置日期
+			 * @param {Object} date
+			 */
+			setDate(date) {
+				this.cale.setDate(date)
+				this.weeks = this.cale.weeks
+				this.nowDate = this.cale.getInfo(date)
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	$uni-bg-color-mask: rgba($color: #000000, $alpha: 0.4);
+	$uni-border-color: #EDEDED;
+	$uni-text-color: #333;
+	$uni-bg-color-hover:#f1f1f1;
+	$uni-font-size-base:14px;
+	$uni-text-color-placeholder: #808080;
+	$uni-color-subtitle: #555555;
+	$uni-text-color-grey:#999;
+	.uni-calendar {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+	}
+
+	.uni-calendar__mask {
+		position: fixed;
+		bottom: 0;
+		top: 0;
+		left: 0;
+		right: 0;
+		background-color: $uni-bg-color-mask;
+		transition-property: opacity;
+		transition-duration: 0.3s;
+		opacity: 0;
+		/* #ifndef APP-NVUE */
+		z-index: 99;
+		/* #endif */
+	}
+
+	.uni-calendar--mask-show {
+		opacity: 1
+	}
+
+	.uni-calendar--fixed {
+		position: fixed;
+		/* #ifdef APP-NVUE */
+		bottom: 0;
+		/* #endif */
+		left: 0;
+		right: 0;
+		transition-property: transform;
+		transition-duration: 0.3s;
+		transform: translateY(460px);
+		/* #ifndef APP-NVUE */
+		bottom: calc(var(--window-bottom));
+		z-index: 99;
+		/* #endif */
+	}
+
+	.uni-calendar--ani-show {
+		transform: translateY(0);
+	}
+
+	.uni-calendar__content {
+		background-color: #fff;
+	}
+
+	.uni-calendar__header {
+		position: relative;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		justify-content: center;
+		align-items: center;
+		height: 50px;
+		border-bottom-color: $uni-border-color;
+		border-bottom-style: solid;
+		border-bottom-width: 1px;
+	}
+
+	.uni-calendar--fixed-top {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		justify-content: space-between;
+		border-top-color: $uni-border-color;
+		border-top-style: solid;
+		border-top-width: 1px;
+	}
+
+	.uni-calendar--fixed-width {
+		width: 50px;
+		// padding: 0 15px;
+	}
+
+	.uni-calendar__backtoday {
+		position: absolute;
+		right: 0;
+		top: 25rpx;
+		padding: 0 5px;
+		padding-left: 10px;
+		height: 25px;
+		line-height: 25px;
+		font-size: 12px;
+		border-top-left-radius: 25px;
+		border-bottom-left-radius: 25px;
+		color: $uni-text-color;
+		background-color: $uni-bg-color-hover;
+	}
+
+	.uni-calendar__header-text {
+		text-align: center;
+		width: 100px;
+		font-size: $uni-font-size-base;
+		color: $uni-text-color;
+	}
+
+	.uni-calendar__header-btn-box {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		align-items: center;
+		justify-content: center;
+		width: 50px;
+		height: 50px;
+	}
+
+	.uni-calendar__header-btn {
+		width: 10px;
+		height: 10px;
+		border-left-color: $uni-text-color-placeholder;
+		border-left-style: solid;
+		border-left-width: 2px;
+		border-top-color: $uni-color-subtitle;
+		border-top-style: solid;
+		border-top-width: 2px;
+	}
+
+	.uni-calendar--left {
+		transform: rotate(-45deg);
+	}
+
+	.uni-calendar--right {
+		transform: rotate(135deg);
+	}
+
+
+	.uni-calendar__weeks {
+		position: relative;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+	}
+
+	.uni-calendar__weeks-item {
+		flex: 1;
+	}
+
+	.uni-calendar__weeks-day {
+		flex: 1;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		justify-content: center;
+		align-items: center;
+		height: 45px;
+		border-bottom-color: #F5F5F5;
+		border-bottom-style: solid;
+		border-bottom-width: 1px;
+	}
+
+	.uni-calendar__weeks-day-text {
+		font-size: 14px;
+	}
+
+	.uni-calendar__box {
+		position: relative;
+	}
+
+	.uni-calendar__box-bg {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		justify-content: center;
+		align-items: center;
+		position: absolute;
+		top: 0;
+		left: 0;
+		right: 0;
+		bottom: 0;
+	}
+
+	.uni-calendar__box-bg-text {
+		font-size: 200px;
+		font-weight: bold;
+		color: $uni-text-color-grey;
+		opacity: 0.1;
+		text-align: center;
+		/* #ifndef APP-NVUE */
+		line-height: 1;
+		/* #endif */
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-calendar/components/uni-calendar/util.js b/yudao-ui-admin-uniapp/uni_modules/uni-calendar/components/uni-calendar/util.js
new file mode 100644
index 000000000..2d6100bff
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-calendar/components/uni-calendar/util.js
@@ -0,0 +1,350 @@
+import CALENDAR from './calendar.js'
+
+class Calendar {
+	constructor({
+		date,
+		selected,
+		startDate,
+		endDate,
+		range
+	} = {}) {
+		// 当前日期
+		this.date = this.getDate(new Date()) // 当前初入日期
+		// 打点信息
+		this.selected = selected || [];
+		// 范围开始
+		this.startDate = startDate
+		// 范围结束
+		this.endDate = endDate
+		this.range = range
+		// 多选状态
+		this.cleanMultipleStatus()
+		// 每周日期
+		this.weeks = {}
+		// this._getWeek(this.date.fullDate)
+	}
+	/**
+	 * 设置日期
+	 * @param {Object} date
+	 */
+	setDate(date) {
+		this.selectDate = this.getDate(date)
+		this._getWeek(this.selectDate.fullDate)
+	}
+
+	/**
+	 * 清理多选状态
+	 */
+	cleanMultipleStatus() {
+		this.multipleStatus = {
+			before: '',
+			after: '',
+			data: []
+		}
+	}
+
+	/**
+	 * 重置开始日期
+	 */
+	resetSatrtDate(startDate) {
+		// 范围开始
+		this.startDate = startDate
+
+	}
+
+	/**
+	 * 重置结束日期
+	 */
+	resetEndDate(endDate) {
+		// 范围结束
+		this.endDate = endDate
+	}
+
+	/**
+	 * 获取任意时间
+	 */
+	getDate(date, AddDayCount = 0, str = 'day') {
+		if (!date) {
+			date = new Date()
+		}
+		if (typeof date !== 'object') {
+			date = date.replace(/-/g, '/')
+		}
+		const dd = new Date(date)
+		switch (str) {
+			case 'day':
+				dd.setDate(dd.getDate() + AddDayCount) // 获取AddDayCount天后的日期
+				break
+			case 'month':
+				if (dd.getDate() === 31) {
+					dd.setDate(dd.getDate() + AddDayCount)
+				} else {
+					dd.setMonth(dd.getMonth() + AddDayCount) // 获取AddDayCount天后的日期
+				}
+				break
+			case 'year':
+				dd.setFullYear(dd.getFullYear() + AddDayCount) // 获取AddDayCount天后的日期
+				break
+		}
+		const y = dd.getFullYear()
+		const m = dd.getMonth() + 1 < 10 ? '0' + (dd.getMonth() + 1) : dd.getMonth() + 1 // 获取当前月份的日期,不足10补0
+		const d = dd.getDate() < 10 ? '0' + dd.getDate() : dd.getDate() // 获取当前几号,不足10补0
+		return {
+			fullDate: y + '-' + m + '-' + d,
+			year: y,
+			month: m,
+			date: d,
+			day: dd.getDay()
+		}
+	}
+
+
+	/**
+	 * 获取上月剩余天数
+	 */
+	_getLastMonthDays(firstDay, full) {
+		let dateArr = []
+		for (let i = firstDay; i > 0; i--) {
+			const beforeDate = new Date(full.year, full.month - 1, -i + 1).getDate()
+			dateArr.push({
+				date: beforeDate,
+				month: full.month - 1,
+				lunar: this.getlunar(full.year, full.month - 1, beforeDate),
+				disable: true
+			})
+		}
+		return dateArr
+	}
+	/**
+	 * 获取本月天数
+	 */
+	_currentMonthDys(dateData, full) {
+		let dateArr = []
+		let fullDate = this.date.fullDate
+		for (let i = 1; i <= dateData; i++) {
+			let nowDate = full.year + '-' + (full.month < 10 ?
+				full.month : full.month) + '-' + (i < 10 ?
+				'0' + i : i)
+			// 是否今天
+			let isDay = fullDate === nowDate
+			// 获取打点信息
+			let info = this.selected && this.selected.find((item) => {
+				if (this.dateEqual(nowDate, item.date)) {
+					return item
+				}
+			})
+
+			// 日期禁用
+			let disableBefore = true
+			let disableAfter = true
+			if (this.startDate) {
+				// let dateCompBefore = this.dateCompare(this.startDate, fullDate)
+				// disableBefore = this.dateCompare(dateCompBefore ? this.startDate : fullDate, nowDate)
+				disableBefore = this.dateCompare(this.startDate, nowDate)
+			}
+
+			if (this.endDate) {
+				// let dateCompAfter = this.dateCompare(fullDate, this.endDate)
+				// disableAfter = this.dateCompare(nowDate, dateCompAfter ? this.endDate : fullDate)
+				disableAfter = this.dateCompare(nowDate, this.endDate)
+			}
+			let multiples = this.multipleStatus.data
+			let checked = false
+			let multiplesStatus = -1
+			if (this.range) {
+				if (multiples) {
+					multiplesStatus = multiples.findIndex((item) => {
+						return this.dateEqual(item, nowDate)
+					})
+				}
+				if (multiplesStatus !== -1) {
+					checked = true
+				}
+			}
+			let data = {
+				fullDate: nowDate,
+				year: full.year,
+				date: i,
+				multiple: this.range ? checked : false,
+				beforeMultiple: this.dateEqual(this.multipleStatus.before, nowDate),
+				afterMultiple: this.dateEqual(this.multipleStatus.after, nowDate),
+				month: full.month,
+				lunar: this.getlunar(full.year, full.month, i),
+				disable: !(disableBefore && disableAfter),
+				isDay
+			}
+			if (info) {
+				data.extraInfo = info
+			}
+
+			dateArr.push(data)
+		}
+		return dateArr
+	}
+	/**
+	 * 获取下月天数
+	 */
+	_getNextMonthDays(surplus, full) {
+		let dateArr = []
+		for (let i = 1; i < surplus + 1; i++) {
+			dateArr.push({
+				date: i,
+				month: Number(full.month) + 1,
+				lunar: this.getlunar(full.year, Number(full.month) + 1, i),
+				disable: true
+			})
+		}
+		return dateArr
+	}
+
+	/**
+	 * 获取当前日期详情
+	 * @param {Object} date
+	 */
+	getInfo(date) {
+		if (!date) {
+			date = new Date()
+		}
+		const dateInfo = this.canlender.find(item => item.fullDate === this.getDate(date).fullDate)
+		return dateInfo
+	}
+
+	/**
+	 * 比较时间大小
+	 */
+	dateCompare(startDate, endDate) {
+		// 计算截止时间
+		startDate = new Date(startDate.replace('-', '/').replace('-', '/'))
+		// 计算详细项的截止时间
+		endDate = new Date(endDate.replace('-', '/').replace('-', '/'))
+		if (startDate <= endDate) {
+			return true
+		} else {
+			return false
+		}
+	}
+
+	/**
+	 * 比较时间是否相等
+	 */
+	dateEqual(before, after) {
+		// 计算截止时间
+		before = new Date(before.replace('-', '/').replace('-', '/'))
+		// 计算详细项的截止时间
+		after = new Date(after.replace('-', '/').replace('-', '/'))
+		if (before.getTime() - after.getTime() === 0) {
+			return true
+		} else {
+			return false
+		}
+	}
+
+
+	/**
+	 * 获取日期范围内所有日期
+	 * @param {Object} begin
+	 * @param {Object} end
+	 */
+	geDateAll(begin, end) {
+		var arr = []
+		var ab = begin.split('-')
+		var ae = end.split('-')
+		var db = new Date()
+		db.setFullYear(ab[0], ab[1] - 1, ab[2])
+		var de = new Date()
+		de.setFullYear(ae[0], ae[1] - 1, ae[2])
+		var unixDb = db.getTime() - 24 * 60 * 60 * 1000
+		var unixDe = de.getTime() - 24 * 60 * 60 * 1000
+		for (var k = unixDb; k <= unixDe;) {
+			k = k + 24 * 60 * 60 * 1000
+			arr.push(this.getDate(new Date(parseInt(k))).fullDate)
+		}
+		return arr
+	}
+	/**
+	 * 计算阴历日期显示
+	 */
+	getlunar(year, month, date) {
+		return CALENDAR.solar2lunar(year, month, date)
+	}
+	/**
+	 * 设置打点
+	 */
+	setSelectInfo(data, value) {
+		this.selected = value
+		this._getWeek(data)
+	}
+
+	/**
+	 *  获取多选状态
+	 */
+	setMultiple(fullDate) {
+		let {
+			before,
+			after
+		} = this.multipleStatus
+
+		if (!this.range) return
+		if (before && after) {
+			this.multipleStatus.before = ''
+			this.multipleStatus.after = ''
+			this.multipleStatus.data = []
+		} else {
+			if (!before) {
+				this.multipleStatus.before = fullDate
+			} else {
+				this.multipleStatus.after = fullDate
+				if (this.dateCompare(this.multipleStatus.before, this.multipleStatus.after)) {
+					this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus.after);
+				} else {
+					this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus.before);
+				}
+			}
+		}
+		this._getWeek(fullDate)
+	}
+
+	/**
+	 * 获取每周数据
+	 * @param {Object} dateData
+	 */
+	_getWeek(dateData) {
+		const {
+			year,
+			month
+		} = this.getDate(dateData)
+		let firstDay = new Date(year, month - 1, 1).getDay()
+		let currentDay = new Date(year, month, 0).getDate()
+		let dates = {
+			lastMonthDays: this._getLastMonthDays(firstDay, this.getDate(dateData)), // 上个月末尾几天
+			currentMonthDys: this._currentMonthDys(currentDay, this.getDate(dateData)), // 本月天数
+			nextMonthDays: [], // 下个月开始几天
+			weeks: []
+		}
+		let canlender = []
+		const surplus = 42 - (dates.lastMonthDays.length + dates.currentMonthDys.length)
+		dates.nextMonthDays = this._getNextMonthDays(surplus, this.getDate(dateData))
+		canlender = canlender.concat(dates.lastMonthDays, dates.currentMonthDys, dates.nextMonthDays)
+		let weeks = {}
+		// 拼接数组  上个月开始几天 + 本月天数+ 下个月开始几天
+		for (let i = 0; i < canlender.length; i++) {
+			if (i % 7 === 0) {
+				weeks[parseInt(i / 7)] = new Array(7)
+			}
+			weeks[parseInt(i / 7)][i % 7] = canlender[i]
+		}
+		this.canlender = canlender
+		this.weeks = weeks
+	}
+
+	//静态方法
+	// static init(date) {
+	// 	if (!this.instance) {
+	// 		this.instance = new Calendar(date);
+	// 	}
+	// 	return this.instance;
+	// }
+}
+
+
+export default Calendar
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-calendar/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-calendar/package.json
new file mode 100644
index 000000000..40455c870
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-calendar/package.json
@@ -0,0 +1,88 @@
+{
+  "id": "uni-calendar",
+  "displayName": "uni-calendar 日历",
+  "version": "1.4.5",
+  "description": "日历组件",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "日历",
+    "",
+    "打卡",
+    "日历选择"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": [],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-calendar/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-calendar/readme.md
new file mode 100644
index 000000000..4f3ca0e84
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-calendar/readme.md
@@ -0,0 +1,103 @@
+
+
+## Calendar 日历
+> **组件名:uni-calendar**
+> 代码块: `uCalendar`
+
+
+日历组件
+
+> **注意事项**
+> 为了避免错误使用,给大家带来不好的开发体验,请在使用组件前仔细阅读下面的注意事项,可以帮你避免一些错误。
+> - 本组件农历转换使用的js是 [@1900-2100区间内的公历、农历互转](https://github.com/jjonline/calendar.js)  
+> - 仅支持自定义组件模式
+> - `date`属性传入的应该是一个 String ,如: 2019-06-27 ,而不是 new Date()
+> - 通过 `insert` 属性来确定当前的事件是 @change 还是 @confirm 。理应合并为一个事件,但是为了区分模式,现使用两个事件,这里需要注意
+> - 弹窗模式下无法阻止后面的元素滚动,如有需要阻止,请在弹窗弹出后,手动设置滚动元素为不可滚动
+
+
+### 安装方式
+
+本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。
+
+如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55)
+
+### 基本用法
+
+在 ``template`` 中使用组件
+
+```html
+<view>
+	<uni-calendar 
+	:insert="true"
+	:lunar="true" 
+	:start-date="'2019-3-2'"
+	:end-date="'2019-5-20'"
+	@change="change"
+	 />
+</view>
+```
+
+### 通过方法打开日历
+
+需要设置 `insert` 为 `false`
+
+```html
+<view>
+	<uni-calendar 
+	ref="calendar"
+	:insert="false"
+	@confirm="confirm"
+	 />
+	 <button @click="open">打开日历</button>
+</view>
+```
+
+```javascript
+
+export default {
+	data() {
+		return {};
+	},
+	methods: {
+		open(){
+			this.$refs.calendar.open();
+		},
+		confirm(e) {
+			console.log(e);
+		}
+	}
+};
+
+```
+
+
+## API
+
+### Calendar Props
+
+|  属性名	|    类型	| 默认值| 说明																													|
+| 		| 																													|
+| date		| String	|-		| 自定义当前时间,默认为今天																							|
+| lunar		| Boolean	| false	| 显示农历																												|
+| startDate	| String	|-		| 日期选择范围-开始日期																									|
+| endDate	| String	|-		| 日期选择范围-结束日期																									|
+| range		| Boolean	| false	| 范围选择																												|
+| insert	| Boolean	| false	| 插入模式,可选值,ture:插入模式;false:弹窗模式;默认为插入模式														|
+|clearDate	|Boolean	|true	|弹窗模式是否清空上次选择内容	|
+| selected	| Array		|-		| 打点,期待格式[{date: '2019-06-27', info: '签到', data: { custom: '自定义信息', name: '自定义消息头',xxx:xxx... }}]	|
+|showMonth	| Boolean	| true	| 是否显示月份为背景																									|
+
+### Calendar Events
+
+|  事件名		| 说明								|返回值|
+| 								|		| 									|
+| open	| 弹出日历组件,`insert :false` 时生效|- 	|
+
+
+
+
+
+## 组件示例
+
+点击查看:[https://hellouniapp.dcloud.net.cn/pages/extUI/calendar/calendar](https://hellouniapp.dcloud.net.cn/pages/extUI/calendar/calendar)
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-card/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-card/changelog.md
new file mode 100644
index 000000000..c3cd8c45a
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-card/changelog.md
@@ -0,0 +1,26 @@
+## 1.3.1(2021-12-20)
+- 修复 在vue页面下略缩图显示不正常的bug
+## 1.3.0(2021-11-19)
+- 重构插槽的用法 ,header 替换为 title 
+- 新增 actions 插槽
+- 新增 cover 封面图属性和插槽
+- 新增 padding 内容默认内边距离
+- 新增 margin 卡片默认外边距离
+- 新增 spacing 卡片默认内边距
+- 新增 shadow 卡片阴影属性
+- 取消 mode 属性,可使用组合插槽代替
+- 取消 note 属性 ,使用actions插槽代替
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-card](https://uniapp.dcloud.io/component/uniui/uni-card)
+## 1.2.1(2021-07-30)
+- 优化 vue3下事件警告的问题
+## 1.2.0(2021-07-13)
+- 组件兼容 vue3,如何创建vue3项目详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.1.8(2021-07-01)
+- 优化 图文卡片无图片加载时,提供占位图标
+- 新增 header 插槽,自定义卡片头部( 图文卡片 mode="style" 时,不支持)
+- 修复 thumbnail 不存在仍然占位的 bug
+## 1.1.7(2021-05-12)
+- 新增 组件示例地址
+## 1.1.6(2021-02-04)
+- 调整为uni_modules目录规范
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-card/components/uni-card/uni-card.vue b/yudao-ui-admin-uniapp/uni_modules/uni-card/components/uni-card/uni-card.vue
new file mode 100644
index 000000000..38cf594cf
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-card/components/uni-card/uni-card.vue
@@ -0,0 +1,270 @@
+<template>
+	<view class="uni-card" :class="{ 'uni-card--full': isFull, 'uni-card--shadow': isShadow,'uni-card--border':border}"
+		:style="{'margin':isFull?0:margin,'padding':spacing,'box-shadow':isShadow?shadow:''}">
+		<!-- 封面 -->
+		<slot name="cover">
+			<view v-if="cover" class="uni-card__cover">
+				<image class="uni-card__cover-image" mode="widthFix" @click="onClick('cover')" :src="cover"></image>
+			</view>
+		</slot>
+		<slot name="title">
+			<view v-if="title || extra" class="uni-card__header">
+				<!-- 卡片标题 -->
+				<view class="uni-card__header-box" @click="onClick('title')">
+					<view v-if="thumbnail" class="uni-card__header-avatar">
+						<image class="uni-card__header-avatar-image" :src="thumbnail" mode="aspectFit" />
+					</view>
+					<view class="uni-card__header-content">
+						<text class="uni-card__header-content-title uni-ellipsis">{{ title }}</text>
+						<text v-if="title&&subTitle"
+							class="uni-card__header-content-subtitle uni-ellipsis">{{ subTitle }}</text>
+					</view>
+				</view>
+				<view class="uni-card__header-extra" @click="onClick('extra')">
+					<text class="uni-card__header-extra-text">{{ extra }}</text>
+				</view>
+			</view>
+		</slot>
+		<!-- 卡片内容 -->
+		<view class="uni-card__content" :style="{padding:padding}" @click="onClick('content')">
+			<slot></slot>
+		</view>
+		<view class="uni-card__actions" @click="onClick('actions')">
+			<slot name="actions"></slot>
+		</view>
+	</view>
+</template>
+
+<script>
+	/**
+	 * Card 卡片
+	 * @description 卡片视图组件
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=22
+	 * @property {String} title 标题文字
+	 * @property {String} subTitle 副标题
+	 * @property {Number} padding 内容内边距
+	 * @property {Number} margin 卡片外边距
+	 * @property {Number} spacing 卡片内边距
+	 * @property {String} extra 标题额外信息
+	 * @property {String} cover 封面图(本地路径需要引入)
+	 * @property {String} thumbnail 标题左侧缩略图
+	 * @property {Boolean} is-full = [true | false] 卡片内容是否通栏,为 true 时将去除padding值
+	 * @property {Boolean} is-shadow = [true | false] 卡片内容是否开启阴影
+	 * @property {String} shadow 卡片阴影
+	 * @property {Boolean} border 卡片边框
+	 * @event {Function} click 点击 Card 触发事件
+	 */
+	export default {
+		name: 'UniCard',
+		emits: ['click'],
+		props: {
+			title: {
+				type: String,
+				default: ''
+			},
+			subTitle: {
+				type: String,
+				default: ''
+			},
+			padding: {
+				type: String,
+				default: '10px'
+			},
+			margin: {
+				type: String,
+				default: '15px'
+			},
+			spacing: {
+				type: String,
+				default: '0 10px'
+			},
+			extra: {
+				type: String,
+				default: ''
+			},
+			cover: {
+				type: String,
+				default: ''
+			},
+			thumbnail: {
+				type: String,
+				default: ''
+			},
+			isFull: {
+				// 内容区域是否通栏
+				type: Boolean,
+				default: false
+			},
+			isShadow: {
+				// 是否开启阴影
+				type: Boolean,
+				default: true
+			},
+			shadow: {
+				type: String,
+				default: '0px 0px 3px 1px rgba(0, 0, 0, 0.08)'
+			},
+			border: {
+				type: Boolean,
+				default: true
+			}
+		},
+		methods: {
+			onClick(type) {
+				this.$emit('click', type)
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	$uni-border-3: #EBEEF5 !default;
+	$uni-shadow-base:0 0px 6px 1px rgba($color: #a5a5a5, $alpha: 0.2) !default;
+	$uni-main-color: #3a3a3a !default;
+	$uni-base-color: #6a6a6a !default;
+	$uni-secondary-color: #909399 !default;
+	$uni-spacing-sm: 8px !default;
+	$uni-border-color:$uni-border-3;
+	$uni-shadow: $uni-shadow-base;
+	$uni-card-title: 15px;
+	$uni-cart-title-color:$uni-main-color;
+	$uni-card-subtitle: 12px;
+	$uni-cart-subtitle-color:$uni-secondary-color;
+	$uni-card-spacing: 10px;
+	$uni-card-content-color: $uni-base-color;
+
+	.uni-card {
+		margin: $uni-card-spacing;
+		padding: 0 $uni-spacing-sm;
+		border-radius: 4px;
+		overflow: hidden;
+		font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, SimSun, sans-serif;
+		background-color: #fff;
+		flex: 1;
+
+		.uni-card__cover {
+			position: relative;
+			margin-top: $uni-card-spacing;
+			flex-direction: row;
+			overflow: hidden;
+			border-radius: 4px;
+			.uni-card__cover-image {
+				flex: 1;
+				// width: 100%;
+				/* #ifndef APP-PLUS */
+				vertical-align: middle;
+				/* #endif */
+			}
+		}
+
+		.uni-card__header {
+			display: flex;
+			border-bottom: 1px $uni-border-color solid;
+			flex-direction: row;
+			align-items: center;
+			padding: $uni-card-spacing;
+			overflow: hidden;
+
+			.uni-card__header-box {
+				/* #ifndef APP-NVUE */
+				display: flex;
+				/* #endif */
+				flex: 1;
+				flex-direction: row;
+				align-items: center;
+				overflow: hidden;
+			}
+
+			.uni-card__header-avatar {
+				width: 40px;
+				height: 40px;
+				overflow: hidden;
+				border-radius: 5px;
+				margin-right: $uni-card-spacing;
+				.uni-card__header-avatar-image {
+					flex: 1;
+					width: 40px;
+					height: 40px;
+				}
+			}
+
+			.uni-card__header-content {
+				/* #ifndef APP-NVUE */
+				display: flex;
+				/* #endif */
+				flex-direction: column;
+				justify-content: center;
+				flex: 1;
+				// height: 40px;
+				overflow: hidden;
+
+				.uni-card__header-content-title {
+					font-size: $uni-card-title;
+					color: $uni-cart-title-color;
+					// line-height: 22px;
+				}
+
+				.uni-card__header-content-subtitle {
+					font-size: $uni-card-subtitle;
+					margin-top: 5px;
+					color: $uni-cart-subtitle-color;
+				}
+			}
+
+			.uni-card__header-extra {
+				line-height: 12px;
+
+				.uni-card__header-extra-text {
+					font-size: 12px;
+					color: $uni-cart-subtitle-color;
+				}
+			}
+		}
+
+		.uni-card__content {
+			padding: $uni-card-spacing;
+			font-size: 14px;
+			color: $uni-card-content-color;
+			line-height: 22px;
+		}
+
+		.uni-card__actions {
+			font-size: 12px;
+		}
+	}
+
+	.uni-card--border {
+		border: 1px solid $uni-border-color;
+	}
+
+	.uni-card--shadow {
+		position: relative;
+		/* #ifndef APP-NVUE */
+		box-shadow: $uni-shadow;
+		/* #endif */
+	}
+
+	.uni-card--full {
+		margin: 0;
+		border-left-width: 0;
+		border-left-width: 0;
+		border-radius: 0;
+	}
+
+	/* #ifndef APP-NVUE */
+	.uni-card--full:after {
+		border-radius: 0;
+	}
+
+	/* #endif */
+	.uni-ellipsis {
+		/* #ifndef APP-NVUE */
+		overflow: hidden;
+		white-space: nowrap;
+		text-overflow: ellipsis;
+		/* #endif */
+		/* #ifdef APP-NVUE */
+		lines: 1;
+		/* #endif */
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-card/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-card/package.json
new file mode 100644
index 000000000..f16224de2
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-card/package.json
@@ -0,0 +1,90 @@
+{
+  "id": "uni-card",
+  "displayName": "uni-card 卡片",
+  "version": "1.3.1",
+  "description": "Card 组件,提供常见的卡片样式。",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "card",
+    "",
+    "卡片"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": [
+			"uni-icons",
+			"uni-scss"
+		],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-card/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-card/readme.md
new file mode 100644
index 000000000..7434e71d2
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-card/readme.md
@@ -0,0 +1,12 @@
+
+
+## Card 卡片
+> **组件名:uni-card**
+> 代码块: `uCard`
+
+卡片视图组件。
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-card)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
+
+
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-collapse/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-collapse/changelog.md
new file mode 100644
index 000000000..292e4c79f
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-collapse/changelog.md
@@ -0,0 +1,36 @@
+## 1.4.3(2022-01-25)
+- 修复 初始化的时候 ,open 属性失效的bug
+## 1.4.2(2022-01-21)
+- 修复 微信小程序resize后组件收起的bug
+## 1.4.1(2021-11-22)
+- 修复 vue3中个别scss变量无法找到的问题
+## 1.4.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-collapse](https://uniapp.dcloud.io/component/uniui/uni-collapse)
+## 1.3.3(2021-08-17)
+- 优化 show-arrow 属性默认为true
+## 1.3.2(2021-08-17)
+- 新增 show-arrow 属性,控制是否显示右侧箭头
+## 1.3.1(2021-07-30)
+- 优化 vue3下小程序事件警告的问题
+## 1.3.0(2021-07-30)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.2.2(2021-07-21)
+- 修复 由1.2.0版本引起的 change 事件返回 undefined 的Bug
+## 1.2.1(2021-07-21)
+- 优化 组件示例
+## 1.2.0(2021-07-21)
+- 新增 组件折叠动画
+- 新增 value\v-model 属性 ,动态修改面板折叠状态
+- 新增 title 插槽 ,可定义面板标题
+- 新增 border 属性 ,显示隐藏面板内容分隔线
+- 新增 title-border 属性 ,显示隐藏面板标题分隔线
+- 修复 resize 方法失效的Bug
+- 修复 change 事件返回参数不正确的Bug
+- 优化 H5、App 平台自动更具内容更新高度,无需调用 reszie() 方法
+## 1.1.7(2021-05-12)
+- 新增 组件示例地址
+## 1.1.6(2021-02-05)
+- 优化 组件引用关系,通过uni_modules引用组件
+## 1.1.5(2021-02-05)
+- 调整为uni_modules目录规范
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-collapse/components/uni-collapse-item/uni-collapse-item.vue b/yudao-ui-admin-uniapp/uni_modules/uni-collapse/components/uni-collapse-item/uni-collapse-item.vue
new file mode 100644
index 000000000..d62a6a713
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-collapse/components/uni-collapse-item/uni-collapse-item.vue
@@ -0,0 +1,402 @@
+<template>
+	<view class="uni-collapse-item">
+		<!-- onClick(!isOpen) -->
+		<view @click="onClick(!isOpen)" class="uni-collapse-item__title"
+			:class="{'is-open':isOpen &&titleBorder === 'auto' ,'uni-collapse-item-border':titleBorder !== 'none'}">
+			<view class="uni-collapse-item__title-wrap">
+				<slot name="title">
+					<view class="uni-collapse-item__title-box" :class="{'is-disabled':disabled}">
+						<image v-if="thumb" :src="thumb" class="uni-collapse-item__title-img" />
+						<text class="uni-collapse-item__title-text">{{ title }}</text>
+					</view>
+				</slot>
+			</view>
+			<view v-if="showArrow"
+				:class="{ 'uni-collapse-item__title-arrow-active': isOpen, 'uni-collapse-item--animation': showAnimation === true }"
+				class="uni-collapse-item__title-arrow">
+				<uni-icons :color="disabled?'#ddd':'#bbb'" size="14" type="bottom" />
+			</view>
+		</view>
+		<view class="uni-collapse-item__wrap" :class="{'is--transition':showAnimation}"
+			:style="{height: (isOpen?height:0) +'px'}">
+			<view :id="elId" ref="collapse--hook" class="uni-collapse-item__wrap-content"
+				:class="{open:isheight,'uni-collapse-item--border':border&&isOpen}">
+				<slot></slot>
+			</view>
+		</view>
+
+	</view>
+</template>
+
+<script>
+	// #ifdef APP-NVUE
+	const dom = weex.requireModule('dom')
+	// #endif
+	/**
+	 * CollapseItem 折叠面板子组件
+	 * @description 折叠面板子组件
+	 * @property {String} title 标题文字
+	 * @property {String} thumb 标题左侧缩略图
+	 * @property {String} name 唯一标志符
+	 * @property {Boolean} open = [true|false] 是否展开组件
+	 * @property {Boolean} titleBorder = [true|false] 是否显示标题分隔线
+	 * @property {Boolean} border = [true|false] 是否显示分隔线
+	 * @property {Boolean} disabled = [true|false] 是否展开面板
+	 * @property {Boolean} showAnimation = [true|false] 开启动画
+	 * @property {Boolean} showArrow = [true|false] 是否显示右侧箭头
+	 */
+	export default {
+		name: 'uniCollapseItem',
+		props: {
+			// 列表标题
+			title: {
+				type: String,
+				default: ''
+			},
+			name: {
+				type: [Number, String],
+				default: ''
+			},
+			// 是否禁用
+			disabled: {
+				type: Boolean,
+				default: false
+			},
+			// #ifdef APP-PLUS
+			// 是否显示动画,app 端默认不开启动画,卡顿严重
+			showAnimation: {
+				type: Boolean,
+				default: false
+			},
+			// #endif
+			// #ifndef APP-PLUS
+			// 是否显示动画
+			showAnimation: {
+				type: Boolean,
+				default: true
+			},
+			// #endif
+			// 是否展开
+			open: {
+				type: Boolean,
+				default: false
+			},
+			// 缩略图
+			thumb: {
+				type: String,
+				default: ''
+			},
+			// 标题分隔线显示类型
+			titleBorder: {
+				type: String,
+				default: 'auto'
+			},
+			border: {
+				type: Boolean,
+				default: true
+			},
+			showArrow: {
+				type: Boolean,
+				default: true
+			}
+		},
+		data() {
+			// TODO 随机生生元素ID,解决百度小程序获取同一个元素位置信息的bug
+			const elId = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`
+			return {
+				isOpen: false,
+				isheight: null,
+				height: 0,
+				elId,
+				nameSync: 0
+			}
+		},
+		watch: {
+			open(val) {
+				this.isOpen = val
+				this.onClick(val, 'init')
+			}
+		},
+		updated(e) {
+			this.$nextTick(() => {
+				this.init(true)
+			})
+		},
+		created() {
+			this.collapse = this.getCollapse()
+			this.oldHeight = 0
+			this.onClick(this.open, 'init')
+		},
+		// #ifndef VUE3
+		// TODO vue2
+		destroyed() {
+			if (this.__isUnmounted) return
+			this.uninstall()
+		},
+		// #endif
+		// #ifdef VUE3
+		// TODO vue3
+		unmounted() {
+			this.__isUnmounted = true
+			this.uninstall()
+		},
+		// #endif
+		mounted() {
+			if (!this.collapse) return
+			if (this.name !== '') {
+				this.nameSync = this.name
+			} else {
+				this.nameSync = this.collapse.childrens.length + ''
+			}
+			if (this.collapse.names.indexOf(this.nameSync) === -1) {
+				this.collapse.names.push(this.nameSync)
+			} else {
+				console.warn(`name 值 ${this.nameSync} 重复`);
+			}
+			if (this.collapse.childrens.indexOf(this) === -1) {
+				this.collapse.childrens.push(this)
+			}
+			this.init()
+		},
+		methods: {
+			init(type) {
+				// #ifndef APP-NVUE
+				this.getCollapseHeight(type)
+				// #endif
+				// #ifdef APP-NVUE
+				this.getNvueHwight(type)
+				// #endif
+			},
+			uninstall() {
+				if (this.collapse) {
+					this.collapse.childrens.forEach((item, index) => {
+						if (item === this) {
+							this.collapse.childrens.splice(index, 1)
+						}
+					})
+					this.collapse.names.forEach((item, index) => {
+						if (item === this.nameSync) {
+							this.collapse.names.splice(index, 1)
+						}
+					})
+				}
+			},
+			onClick(isOpen, type) {
+				if (this.disabled) return
+				this.isOpen = isOpen
+				if (this.isOpen && this.collapse) {
+					this.collapse.setAccordion(this)
+				}
+				if (type !== 'init') {
+					this.collapse.onChange(isOpen, this)
+				}
+			},
+			getCollapseHeight(type, index = 0) {
+				const views = uni.createSelectorQuery().in(this)
+				views
+					.select(`#${this.elId}`)
+					.fields({
+						size: true
+					}, data => {
+						// TODO 百度中可能获取不到节点信息 ,需要循环获取
+						if (index >= 10) return
+						if (!data) {
+							index++
+							this.getCollapseHeight(false, index)
+							return
+						}
+						// #ifdef APP-NVUE
+						this.height = data.height + 1
+						// #endif
+						// #ifndef APP-NVUE
+						this.height = data.height
+						// #endif
+						this.isheight = true
+						if (type) return
+						this.onClick(this.isOpen, 'init')
+					})
+					.exec()
+			},
+			getNvueHwight(type) {
+				const result = dom.getComponentRect(this.$refs['collapse--hook'], option => {
+					if (option && option.result && option.size) {
+						// #ifdef APP-NVUE
+						this.height = option.size.height + 1
+						// #endif
+						// #ifndef APP-NVUE
+						this.height = option.size.height
+						// #endif
+						this.isheight = true
+						if (type) return
+						this.onClick(this.open, 'init')
+					}
+				})
+			},
+			/**
+			 * 获取父元素实例
+			 */
+			getCollapse(name = 'uniCollapse') {
+				let parent = this.$parent;
+				let parentName = parent.$options.name;
+				while (parentName !== name) {
+					parent = parent.$parent;
+					if (!parent) return false;
+					parentName = parent.$options.name;
+				}
+				return parent;
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.uni-collapse-item {
+		/* #ifndef APP-NVUE */
+		box-sizing: border-box;
+
+		/* #endif */
+		&__title {
+			/* #ifndef APP-NVUE */
+			display: flex;
+			width: 100%;
+			box-sizing: border-box;
+			/* #endif */
+			flex-direction: row;
+			align-items: center;
+			transition: border-bottom-color .3s;
+
+			// transition-property: border-bottom-color;
+			// transition-duration: 5s;
+			&-wrap {
+				width: 100%;
+				flex: 1;
+
+			}
+
+			&-box {
+				padding: 0 15px;
+				/* #ifndef APP-NVUE */
+				display: flex;
+				width: 100%;
+				box-sizing: border-box;
+				/* #endif */
+				flex-direction: row;
+				justify-content: space-between;
+				align-items: center;
+				height: 48px;
+				line-height: 48px;
+				background-color: #fff;
+				color: #303133;
+				font-size: 13px;
+				font-weight: 500;
+				/* #ifdef H5 */
+				cursor: pointer;
+				outline: none;
+
+				/* #endif */
+				&.is-disabled {
+					.uni-collapse-item__title-text {
+						color: #999;
+					}
+				}
+
+			}
+
+			&.uni-collapse-item-border {
+				border-bottom: 1px solid #ebeef5;
+			}
+
+			&.is-open {
+				border-bottom-color: transparent;
+			}
+
+			&-img {
+				height: 22px;
+				width: 22px;
+				margin-right: 10px;
+			}
+
+			&-text {
+				flex: 1;
+				font-size: 14px;
+				/* #ifndef APP-NVUE */
+				white-space: nowrap;
+				color: inherit;
+				/* #endif */
+				/* #ifdef APP-NVUE */
+				lines: 1;
+				/* #endif */
+				overflow: hidden;
+				text-overflow: ellipsis;
+			}
+
+			&-arrow {
+				/* #ifndef APP-NVUE */
+				display: flex;
+				box-sizing: border-box;
+				/* #endif */
+				align-items: center;
+				justify-content: center;
+				width: 20px;
+				height: 20px;
+				margin-right: 10px;
+				transform: rotate(0deg);
+
+				&-active {
+					transform: rotate(-180deg);
+				}
+			}
+
+
+		}
+
+		&__wrap {
+			/* #ifndef APP-NVUE */
+			will-change: height;
+			box-sizing: border-box;
+			/* #endif */
+			background-color: #fff;
+			overflow: hidden;
+			position: relative;
+			height: 0;
+
+			&.is--transition {
+				// transition: all 0.3s;
+				transition-property: height, border-bottom-width;
+				transition-duration: 0.3s;
+				/* #ifndef APP-NVUE */
+				will-change: height;
+				/* #endif */
+			}
+
+
+
+			&-content {
+				position: absolute;
+				font-size: 13px;
+				color: #303133;
+				// transition: height 0.3s;
+				border-bottom-color: transparent;
+				border-bottom-style: solid;
+				border-bottom-width: 0;
+
+				&.uni-collapse-item--border {
+					border-bottom-width: 1px;
+					border-bottom-color: red;
+					border-bottom-color: #ebeef5;
+				}
+
+				&.open {
+					position: relative;
+				}
+			}
+		}
+
+		&--animation {
+			transition-property: transform;
+			transition-duration: 0.3s;
+			transition-timing-function: ease;
+		}
+
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-collapse/components/uni-collapse/uni-collapse.vue b/yudao-ui-admin-uniapp/uni_modules/uni-collapse/components/uni-collapse/uni-collapse.vue
new file mode 100644
index 000000000..384c39a9c
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-collapse/components/uni-collapse/uni-collapse.vue
@@ -0,0 +1,147 @@
+<template>
+	<view class="uni-collapse">
+		<slot />
+	</view>
+</template>
+<script>
+	/**
+	 * Collapse 折叠面板
+	 * @description 展示可以折叠 / 展开的内容区域
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=23
+	 * @property {String|Array} value 当前激活面板改变时触发(如果是手风琴模式,参数类型为string,否则为array)
+	 * @property {Boolean} accordion = [true|false] 是否开启手风琴效果是否开启手风琴效果
+	 * @event {Function} change 切换面板时触发,如果是手风琴模式,返回类型为string,否则为array
+	 */
+	export default {
+		name: 'uniCollapse',
+		emits:['change','activeItem','input','update:modelValue'],
+		props: {
+			value: {
+				type: [String, Array],
+				default: ''
+			},
+			modelValue: {
+				type: [String, Array],
+				default: ''
+			},
+			accordion: {
+				// 是否开启手风琴效果
+				type: [Boolean, String],
+				default: false
+			},
+		},
+		data() {
+			return {}
+		},
+		computed: {
+			// TODO 兼容 vue2 和 vue3
+			dataValue() {
+				let value = (typeof this.value === 'string' && this.value === '') ||
+					(Array.isArray(this.value) && this.value.length === 0)
+				let modelValue = (typeof this.modelValue === 'string' && this.modelValue === '') ||
+					(Array.isArray(this.modelValue) && this.modelValue.length === 0)
+				if (value) {
+					return this.modelValue
+				}
+				if (modelValue) {
+					return this.value
+				}
+
+				return this.value
+			}
+		},
+		watch: {
+			dataValue(val) {
+				this.setOpen(val)
+			}
+		},
+		created() {
+			this.childrens = []
+			this.names = []
+		},
+		mounted() {
+			this.$nextTick(()=>{
+				this.setOpen(this.dataValue)
+			})
+		},
+		methods: {
+			setOpen(val) {
+				let str = typeof val === 'string'
+				let arr = Array.isArray(val)
+				this.childrens.forEach((vm, index) => {
+					if (str) {
+						if (val === vm.nameSync) {
+							if (!this.accordion) {
+								console.warn('accordion 属性为 false ,v-model 类型应该为 array')
+								return
+							}
+							vm.isOpen = true
+						}
+					}
+					if (arr) {
+						val.forEach(v => {
+							if (v === vm.nameSync) {
+								if (this.accordion) {
+									console.warn('accordion 属性为 true ,v-model 类型应该为 string')
+									return
+								}
+								vm.isOpen = true
+							}
+						})
+					}
+				})
+				this.emit(val)
+			},
+			setAccordion(self) {
+				if (!this.accordion) return
+				this.childrens.forEach((vm, index) => {
+					if (self !== vm) {
+						vm.isOpen = false
+					}
+				})
+			},
+			resize() {
+				this.childrens.forEach((vm, index) => {
+					// #ifndef APP-NVUE
+					vm.getCollapseHeight()
+					// #endif
+					// #ifdef APP-NVUE
+					vm.getNvueHwight()
+					// #endif
+				})
+			},
+			onChange(isOpen, self) {
+				let activeItem = []
+
+				if (this.accordion) {
+					activeItem = isOpen ? self.nameSync : ''
+				} else {
+					this.childrens.forEach((vm, index) => {
+						if (vm.isOpen) {
+							activeItem.push(vm.nameSync)
+						}
+					})
+				}
+				this.$emit('change', activeItem)
+				this.emit(activeItem)
+			},
+			emit(val){
+				this.$emit('input', val)
+				this.$emit('update:modelValue', val)
+			}
+		}
+	}
+</script>
+<style lang="scss" >
+	.uni-collapse {
+		/* #ifndef APP-NVUE */
+		width: 100%;
+		display: flex;
+		/* #endif */
+		/* #ifdef APP-NVUE */
+		flex: 1;
+		/* #endif */
+		flex-direction: column;
+		background-color: #fff;
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-collapse/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-collapse/package.json
new file mode 100644
index 000000000..65349cf9f
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-collapse/package.json
@@ -0,0 +1,89 @@
+{
+  "id": "uni-collapse",
+  "displayName": "uni-collapse 折叠面板",
+  "version": "1.4.3",
+  "description": "Collapse 组件,可以折叠 / 展开的内容区域。",
+  "keywords": [
+    "uni-ui",
+    "折叠",
+    "折叠面板",
+    "手风琴"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": [
+			"uni-scss",
+      "uni-icons"
+    ],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-collapse/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-collapse/readme.md
new file mode 100644
index 000000000..bc758ebc4
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-collapse/readme.md
@@ -0,0 +1,12 @@
+
+
+## Collapse 折叠面板
+> **组件名:uni-collapse**
+> 代码块: `uCollapse`
+> 关联组件:`uni-collapse-item`、`uni-icons`。
+
+
+折叠面板用来折叠/显示过长的内容或者是列表。通常是在多内容分类项使用,折叠不重要的内容,显示重要内容。点击可以展开折叠部分。
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-collapse)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-combox/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-combox/changelog.md
new file mode 100644
index 000000000..23c27485c
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-combox/changelog.md
@@ -0,0 +1,15 @@
+## 1.0.1(2021-11-23)
+- 优化 label、label-width 属性
+## 1.0.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-combox](https://uniapp.dcloud.io/component/uniui/uni-combox)
+## 0.1.0(2021-07-30)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 0.0.6(2021-05-12)
+- 新增 组件示例地址
+## 0.0.5(2021-04-21)
+- 优化 添加依赖 uni-icons, 导入后自动下载依赖
+## 0.0.4(2021-02-05)
+- 优化 组件引用关系,通过uni_modules引用组件
+## 0.0.3(2021-02-04)
+- 调整为uni_modules目录规范
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-combox/components/uni-combox/uni-combox.vue b/yudao-ui-admin-uniapp/uni_modules/uni-combox/components/uni-combox/uni-combox.vue
new file mode 100644
index 000000000..500b6f881
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-combox/components/uni-combox/uni-combox.vue
@@ -0,0 +1,275 @@
+<template>
+	<view class="uni-combox" :class="border ? '' : 'uni-combox__no-border'">
+		<view v-if="label" class="uni-combox__label" :style="labelStyle">
+			<text>{{label}}</text>
+		</view>
+		<view class="uni-combox__input-box">
+			<input class="uni-combox__input" type="text" :placeholder="placeholder" 
+			placeholder-class="uni-combox__input-plac" v-model="inputVal" @input="onInput" @focus="onFocus" 
+@blur="onBlur" />
+			<uni-icons :type="showSelector? 'top' : 'bottom'" size="14" color="#999" @click="toggleSelector">
+			</uni-icons>
+		</view>
+		<view class="uni-combox__selector" v-if="showSelector">
+			<view class="uni-popper__arrow"></view>
+			<scroll-view scroll-y="true" class="uni-combox__selector-scroll">
+				<view class="uni-combox__selector-empty" v-if="filterCandidatesLength === 0">
+					<text>{{emptyTips}}</text>
+				</view>
+				<view class="uni-combox__selector-item" v-for="(item,index) in filterCandidates" :key="index" 
+				@click="onSelectorClick(index)">
+					<text>{{item}}</text>
+				</view>
+			</scroll-view>
+		</view>
+	</view>
+</template>
+
+<script>
+	/**
+	 * Combox 组合输入框
+	 * @description 组合输入框一般用于既可以输入也可以选择的场景
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=1261
+	 * @property {String} label 左侧文字
+	 * @property {String} labelWidth 左侧内容宽度
+	 * @property {String} placeholder 输入框占位符
+	 * @property {Array} candidates 候选项列表
+	 * @property {String} emptyTips 筛选结果为空时显示的文字
+	 * @property {String} value 组合框的值
+	 */
+	export default {
+		name: 'uniCombox',
+		emits: ['input', 'update:modelValue'],
+		props: {
+			border: {
+				type: Boolean,
+				default: true
+			},
+			label: {
+				type: String,
+				default: ''
+			},
+			labelWidth: {
+				type: String,
+				default: 'auto'
+			},
+			placeholder: {
+				type: String,
+				default: ''
+			},
+			candidates: {
+				type: Array,
+				default () {
+					return []
+				}
+			},
+			emptyTips: {
+				type: String,
+				default: '无匹配项'
+			},
+			// #ifndef VUE3
+			value: {
+				type: [String, Number],
+				default: ''
+			},
+			// #endif
+			// #ifdef VUE3
+			modelValue: {
+				type: [String, Number],
+				default: ''
+			},
+			// #endif
+		},
+		data() {
+			return {
+				showSelector: false,
+				inputVal: ''
+			}
+		},
+		computed: {
+			labelStyle() {
+				if (this.labelWidth === 'auto') {
+					return ""
+				}
+				return `width: ${this.labelWidth}`
+			},
+			filterCandidates() {
+				return this.candidates.filter((item) => {
+					return item.toString().indexOf(this.inputVal) > -1
+				})
+			},
+			filterCandidatesLength() {
+				return this.filterCandidates.length
+			}
+		},
+		watch: {
+			// #ifndef VUE3
+			value: {
+				handler(newVal) {
+					this.inputVal = newVal
+				},
+				immediate: true
+			},
+			// #endif
+			// #ifdef VUE3
+			modelValue: {
+				handler(newVal) {
+					this.inputVal = newVal
+				},
+				immediate: true
+			},
+			// #endif
+		},
+		methods: {
+			toggleSelector() {
+				this.showSelector = !this.showSelector
+			},
+			onFocus() {
+				this.showSelector = true
+			},
+			onBlur() {
+				setTimeout(() => {
+					this.showSelector = false
+				}, 153)
+			},
+			onSelectorClick(index) {
+				this.inputVal = this.filterCandidates[index]
+				this.showSelector = false
+				this.$emit('input', this.inputVal)
+				this.$emit('update:modelValue', this.inputVal)
+			},
+			onInput() {
+				setTimeout(() => {
+					this.$emit('input', this.inputVal)
+					this.$emit('update:modelValue', this.inputVal)
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss" >
+	.uni-combox {
+		font-size: 14px;
+		border: 1px solid #DCDFE6;
+		border-radius: 4px;
+		padding: 6px 10px;
+		position: relative;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		// height: 40px;
+		flex-direction: row;
+		align-items: center;
+		// border-bottom: solid 1px #DDDDDD;
+	}
+
+	.uni-combox__label {
+		font-size: 16px;
+		line-height: 22px;
+		padding-right: 10px;
+		color: #999999;
+	}
+
+	.uni-combox__input-box {
+		position: relative;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex: 1;
+		flex-direction: row;
+		align-items: center;
+	}
+
+	.uni-combox__input {
+		flex: 1;
+		font-size: 14px;
+		height: 22px;
+		line-height: 22px;
+	}
+
+	.uni-combox__input-plac {
+		font-size: 14px;
+		color: #999;
+	}
+
+	.uni-combox__selector {
+		/* #ifndef APP-NVUE */
+		box-sizing: border-box;
+		/* #endif */
+		position: absolute;
+		top: calc(100% + 12px);
+		left: 0;
+		width: 100%;
+		background-color: #FFFFFF;
+		border: 1px solid #EBEEF5;
+		border-radius: 6px;
+		box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+		z-index: 2;
+		padding: 4px 0;
+	}
+
+	.uni-combox__selector-scroll {
+		/* #ifndef APP-NVUE */
+		max-height: 200px;
+		box-sizing: border-box;
+		/* #endif */
+	}
+
+	.uni-combox__selector-empty,
+	.uni-combox__selector-item {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		cursor: pointer;
+		/* #endif */
+		line-height: 36px;
+		font-size: 14px;
+		text-align: center;
+		// border-bottom: solid 1px #DDDDDD;
+		padding: 0px 10px;
+	}
+
+	.uni-combox__selector-item:hover {
+		background-color: #f9f9f9;
+	}
+
+	.uni-combox__selector-empty:last-child,
+	.uni-combox__selector-item:last-child {
+		/* #ifndef APP-NVUE */
+		border-bottom: none;
+		/* #endif */
+	}
+
+	// picker 弹出层通用的指示小三角
+	.uni-popper__arrow,
+	.uni-popper__arrow::after {
+		position: absolute;
+		display: block;
+		width: 0;
+		height: 0;
+		border-color: transparent;
+		border-style: solid;
+		border-width: 6px;
+	}
+
+	.uni-popper__arrow {
+		filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03));
+		top: -6px;
+		left: 10%;
+		margin-right: 3px;
+		border-top-width: 0;
+		border-bottom-color: #EBEEF5;
+	}
+
+	.uni-popper__arrow::after {
+		content: " ";
+		top: 1px;
+		margin-left: -6px;
+		border-top-width: 0;
+		border-bottom-color: #fff;
+	}
+
+	.uni-combox__no-border {
+		border: none;
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-combox/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-combox/package.json
new file mode 100644
index 000000000..4a05c3ff5
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-combox/package.json
@@ -0,0 +1,90 @@
+{
+  "id": "uni-combox",
+  "displayName": "uni-combox 组合框",
+  "version": "1.0.1",
+  "description": "可以选择也可以输入的表单项 ",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "combox",
+    "组合框",
+    "select"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": [
+			"uni-scss",
+			"uni-icons"
+		],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "n"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-combox/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-combox/readme.md
new file mode 100644
index 000000000..ffa2cc864
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-combox/readme.md
@@ -0,0 +1,11 @@
+
+
+## Combox 组合框
+> **组件名:uni-combox**
+> 代码块: `uCombox`
+
+
+组合框组件。
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-combox)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-countdown/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-countdown/changelog.md
new file mode 100644
index 000000000..f25beefca
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-countdown/changelog.md
@@ -0,0 +1,24 @@
+## 1.2.2(2022-01-19)
+- 修复 在微信小程序中样式不生效的bug
+## 1.2.1(2022-01-18)
+- 新增 update 方法 ,在动态更新时间后,刷新组件
+## 1.2.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-countdown](https://uniapp.dcloud.io/component/uniui/uni-countdown)
+## 1.1.3(2021-10-18)
+- 重构
+- 新增 font-size 支持自定义字体大小
+## 1.1.2(2021-08-24)
+- 新增 支持国际化
+## 1.1.1(2021-07-30)
+- 优化 vue3下小程序事件警告的问题
+## 1.1.0(2021-07-30)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.0.5(2021-06-18)
+- 修复 uni-countdown 重复赋值跳两秒的 bug
+## 1.0.4(2021-05-12)
+- 新增 组件示例地址
+## 1.0.3(2021-05-08)
+- 修复 uni-countdown 不能控制倒计时的 bug
+## 1.0.2(2021-02-04)
+- 调整为uni_modules目录规范
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-countdown/components/uni-countdown/i18n/en.json b/yudao-ui-admin-uniapp/uni_modules/uni-countdown/components/uni-countdown/i18n/en.json
new file mode 100644
index 000000000..06309cb0f
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-countdown/components/uni-countdown/i18n/en.json
@@ -0,0 +1,6 @@
+{
+	"uni-countdown.day": "day",
+	"uni-countdown.h": "h",
+	"uni-countdown.m": "m",
+	"uni-countdown.s": "s"
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-countdown/components/uni-countdown/i18n/index.js b/yudao-ui-admin-uniapp/uni_modules/uni-countdown/components/uni-countdown/i18n/index.js
new file mode 100644
index 000000000..de7509c87
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-countdown/components/uni-countdown/i18n/index.js
@@ -0,0 +1,8 @@
+import en from './en.json'
+import zhHans from './zh-Hans.json'
+import zhHant from './zh-Hant.json'
+export default {
+	en,
+	'zh-Hans': zhHans,
+	'zh-Hant': zhHant
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-countdown/components/uni-countdown/i18n/zh-Hans.json b/yudao-ui-admin-uniapp/uni_modules/uni-countdown/components/uni-countdown/i18n/zh-Hans.json
new file mode 100644
index 000000000..358cdd166
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-countdown/components/uni-countdown/i18n/zh-Hans.json
@@ -0,0 +1,6 @@
+{
+	"uni-countdown.day": "天",
+	"uni-countdown.h": "时",
+	"uni-countdown.m": "分",
+	"uni-countdown.s": "秒"
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-countdown/components/uni-countdown/i18n/zh-Hant.json b/yudao-ui-admin-uniapp/uni_modules/uni-countdown/components/uni-countdown/i18n/zh-Hant.json
new file mode 100644
index 000000000..e5a63deab
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-countdown/components/uni-countdown/i18n/zh-Hant.json
@@ -0,0 +1,6 @@
+{
+	"uni-countdown.day": "天",
+	"uni-countdown.h": "時",
+	"uni-countdown.m": "分",
+	"uni-countdown.s": "秒"
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-countdown/components/uni-countdown/uni-countdown.vue b/yudao-ui-admin-uniapp/uni_modules/uni-countdown/components/uni-countdown/uni-countdown.vue
new file mode 100644
index 000000000..1f8ef4eb9
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-countdown/components/uni-countdown/uni-countdown.vue
@@ -0,0 +1,271 @@
+<template>
+	<view class="uni-countdown">
+		<text v-if="showDay" :style="[timeStyle]" class="uni-countdown__number">{{ d }}</text>
+		<text v-if="showDay" :style="[splitorStyle]" class="uni-countdown__splitor">{{dayText}}</text>
+		<text :style="[timeStyle]" class="uni-countdown__number">{{ h }}</text>
+		<text :style="[splitorStyle]" class="uni-countdown__splitor">{{ showColon ? ':' : hourText }}</text>
+		<text :style="[timeStyle]" class="uni-countdown__number">{{ i }}</text>
+		<text :style="[splitorStyle]" class="uni-countdown__splitor">{{ showColon ? ':' : minuteText }}</text>
+		<text :style="[timeStyle]" class="uni-countdown__number">{{ s }}</text>
+		<text v-if="!showColon" :style="[splitorStyle]" class="uni-countdown__splitor">{{secondText}}</text>
+	</view>
+</template>
+<script>
+	import {
+		initVueI18n
+	} from '@dcloudio/uni-i18n'
+	import messages from './i18n/index.js'
+	const {
+		t
+	} = initVueI18n(messages)
+	/**
+	 * Countdown 倒计时
+	 * @description 倒计时组件
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=25
+	 * @property {String} backgroundColor 背景色
+	 * @property {String} color 文字颜色
+	 * @property {Number} day 天数
+	 * @property {Number} hour 小时
+	 * @property {Number} minute 分钟
+	 * @property {Number} second 秒
+	 * @property {Number} timestamp 时间戳
+	 * @property {Boolean} showDay = [true|false] 是否显示天数
+	 * @property {Boolean} show-colon = [true|false] 是否以冒号为分隔符
+	 * @property {String} splitorColor 分割符号颜色
+	 * @event {Function} timeup 倒计时时间到触发事件
+	 * @example <uni-countdown :day="1" :hour="1" :minute="12" :second="40"></uni-countdown>
+	 */
+	export default {
+		name: 'UniCountdown',
+		emits: ['timeup'],
+		props: {
+			showDay: {
+				type: Boolean,
+				default: true
+			},
+			showColon: {
+				type: Boolean,
+				default: true
+			},
+			start: {
+				type: Boolean,
+				default: true
+			},
+			backgroundColor: {
+				type: String,
+				default: ''
+			},
+			color: {
+				type: String,
+				default: '#333'
+			},
+			fontSize: {
+				type: Number,
+				default: 14
+			},
+			splitorColor: {
+				type: String,
+				default: '#333'
+			},
+			day: {
+				type: Number,
+				default: 0
+			},
+			hour: {
+				type: Number,
+				default: 0
+			},
+			minute: {
+				type: Number,
+				default: 0
+			},
+			second: {
+				type: Number,
+				default: 0
+			},
+			timestamp: {
+				type: Number,
+				default: 0
+			}
+		},
+		data() {
+			return {
+				timer: null,
+				syncFlag: false,
+				d: '00',
+				h: '00',
+				i: '00',
+				s: '00',
+				leftTime: 0,
+				seconds: 0
+			}
+		},
+		computed: {
+			dayText() {
+				return t("uni-countdown.day")
+			},
+			hourText(val) {
+				return t("uni-countdown.h")
+			},
+			minuteText(val) {
+				return t("uni-countdown.m")
+			},
+			secondText(val) {
+				return t("uni-countdown.s")
+			},
+			timeStyle() {
+				const {
+					color,
+					backgroundColor,
+					fontSize
+				} = this
+				return {
+					color,
+					backgroundColor,
+					fontSize: `${fontSize}px`,
+					width: `${fontSize * 22 / 14}px`, // 按字体大小为 14px 时的比例缩放
+ 					lineHeight: `${fontSize * 20 / 14}px`,
+					borderRadius: `${fontSize * 3 / 14}px`,
+				}
+			},
+			splitorStyle() {
+				const { splitorColor, fontSize, backgroundColor } = this
+				return {
+					color: splitorColor,
+					fontSize: `${fontSize * 12 / 14}px`,
+					margin: backgroundColor ? `${fontSize * 4 / 14}px` : ''
+				}
+			}
+		},
+		watch: {
+			day(val) {
+				this.changeFlag()
+			},
+			hour(val) {
+				this.changeFlag()
+			},
+			minute(val) {
+				this.changeFlag()
+			},
+			second(val) {
+				this.changeFlag()
+			},
+			start: {
+				immediate: true,
+				handler(newVal, oldVal) {
+					if (newVal) {
+						this.startData();
+					} else {
+						if (!oldVal) return
+						clearInterval(this.timer)
+					}
+				}
+
+			}
+		},
+		created: function(e) {
+			this.seconds = this.toSeconds(this.timestamp, this.day, this.hour, this.minute, this.second)
+			this.countDown()
+		},
+		// #ifndef VUE3
+		destroyed() {
+			clearInterval(this.timer)
+		},
+		// #endif
+		// #ifdef VUE3
+		unmounted() {
+			clearInterval(this.timer)
+		},
+		// #endif
+		methods: {
+			toSeconds(timestamp, day, hours, minutes, seconds) {
+				if (timestamp) {
+					return timestamp - parseInt(new Date().getTime() / 1000, 10)
+				}
+				return day * 60 * 60 * 24 + hours * 60 * 60 + minutes * 60 + seconds
+			},
+			timeUp() {
+				clearInterval(this.timer)
+				this.$emit('timeup')
+			},
+			countDown() {
+				let seconds = this.seconds
+				let [day, hour, minute, second] = [0, 0, 0, 0]
+				if (seconds > 0) {
+					day = Math.floor(seconds / (60 * 60 * 24))
+					hour = Math.floor(seconds / (60 * 60)) - (day * 24)
+					minute = Math.floor(seconds / 60) - (day * 24 * 60) - (hour * 60)
+					second = Math.floor(seconds) - (day * 24 * 60 * 60) - (hour * 60 * 60) - (minute * 60)
+				} else {
+					this.timeUp()
+				}
+				if (day < 10) {
+					day = '0' + day
+				}
+				if (hour < 10) {
+					hour = '0' + hour
+				}
+				if (minute < 10) {
+					minute = '0' + minute
+				}
+				if (second < 10) {
+					second = '0' + second
+				}
+				this.d = day
+				this.h = hour
+				this.i = minute
+				this.s = second
+			},
+			startData() {
+				this.seconds = this.toSeconds(this.timestamp, this.day, this.hour, this.minute, this.second)
+				if (this.seconds <= 0) {
+					this.seconds = this.toSeconds(0, 0, 0, 0, 0)
+					this.countDown()
+					return
+				}
+				clearInterval(this.timer)
+				this.countDown()
+				this.timer = setInterval(() => {
+					this.seconds--
+					if (this.seconds < 0) {
+						this.timeUp()
+						return
+					}
+					this.countDown()
+				}, 1000)
+			},
+			update(){
+				this.startData();
+			},
+			changeFlag() {
+				if (!this.syncFlag) {
+					this.seconds = this.toSeconds(this.timestamp, this.day, this.hour, this.minute, this.second)
+					this.startData();
+					this.syncFlag = true;
+				}
+			}
+		}
+	}
+</script>
+<style lang="scss" scoped>
+	$font-size: 14px;
+
+	.uni-countdown {
+		display: flex;
+		flex-direction: row;
+		justify-content: flex-start;
+		align-items: center;
+
+		&__splitor {
+			margin: 0 2px;
+			font-size: $font-size;
+			color: #333;
+		}
+
+		&__number {
+			border-radius: 3px;
+			text-align: center;
+			font-size: $font-size;
+		}
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-countdown/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-countdown/package.json
new file mode 100644
index 000000000..70e99ee7c
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-countdown/package.json
@@ -0,0 +1,86 @@
+{
+  "id": "uni-countdown",
+  "displayName": "uni-countdown 倒计时",
+  "version": "1.2.2",
+  "description": "CountDown 倒计时组件",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "countdown",
+    "倒计时"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": ["uni-scss"],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-countdown/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-countdown/readme.md
new file mode 100644
index 000000000..4bcb1aa71
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-countdown/readme.md
@@ -0,0 +1,10 @@
+
+
+## CountDown 倒计时
+> **组件名:uni-countdown**
+> 代码块: `uCountDown`
+
+倒计时组件。
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-countdown)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-data-checkbox/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-data-checkbox/changelog.md
new file mode 100644
index 000000000..dbc517a30
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-data-checkbox/changelog.md
@@ -0,0 +1,43 @@
+## 1.0.2(2022-06-30)
+- 优化 在 uni-forms 中的依赖注入方式
+## 1.0.1(2022-02-07)
+- 修复 multiple 为 true 时,v-model 的值为 null 报错的 bug
+## 1.0.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-data-checkbox](https://uniapp.dcloud.io/component/uniui/uni-data-checkbox)
+## 0.2.5(2021-08-23)
+- 修复 在uni-forms中 modelValue 中不存在当前字段,当前字段必填写也不参与校验的问题
+## 0.2.4(2021-08-17)
+- 修复 单选 list 模式下 ,icon 为 left 时,选中图标不显示的问题
+## 0.2.3(2021-08-11)
+- 修复 在 uni-forms 中重置表单,错误信息无法清除的问题
+## 0.2.2(2021-07-30)
+- 优化 在uni-forms组件,与label不对齐的问题
+## 0.2.1(2021-07-27)
+- 修复 单选默认值为0不能选中的Bug
+## 0.2.0(2021-07-13)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 0.1.11(2021-07-06)
+- 优化 删除无用日志
+## 0.1.10(2021-07-05)
+- 修复 由 0.1.9 引起的非 nvue 端图标不显示的问题
+## 0.1.9(2021-07-05)
+- 修复 nvue 黑框样式问题
+## 0.1.8(2021-06-28)
+- 修复 selectedTextColor 属性不生效的Bug
+## 0.1.7(2021-06-02)
+- 新增 map 属性,可以方便映射text/value属性
+## 0.1.6(2021-05-26)
+- 修复 不关联服务空间的情况下组件报错的Bug
+## 0.1.5(2021-05-12)
+- 新增 组件示例地址
+## 0.1.4(2021-04-09)
+- 修复 nvue 下无法选中的问题
+## 0.1.3(2021-03-22)
+- 新增 disabled属性
+## 0.1.2(2021-02-24)
+- 优化 默认颜色显示
+## 0.1.1(2021-02-24)
+- 新增 支持nvue
+## 0.1.0(2021-02-18)
+- “暂无数据”显示居中
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-data-checkbox/components/uni-data-checkbox/uni-data-checkbox.vue b/yudao-ui-admin-uniapp/uni_modules/uni-data-checkbox/components/uni-data-checkbox/uni-data-checkbox.vue
new file mode 100644
index 000000000..2e5171237
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-data-checkbox/components/uni-data-checkbox/uni-data-checkbox.vue
@@ -0,0 +1,817 @@
+<template>
+	<view class="uni-data-checklist" :style="{'margin-top':isTop+'px'}">
+		<template v-if="!isLocal">
+			<view class="uni-data-loading">
+				<uni-load-more v-if="!mixinDatacomErrorMessage" status="loading" iconType="snow" :iconSize="18" :content-text="contentText"></uni-load-more>
+				<text v-else>{{mixinDatacomErrorMessage}}</text>
+			</view>
+		</template>
+		<template v-else>
+			<checkbox-group v-if="multiple" class="checklist-group" :class="{'is-list':mode==='list' || wrap}" @change="chagne">
+				<label class="checklist-box" :class="['is--'+mode,item.selected?'is-checked':'',(disabled || !!item.disabled)?'is-disable':'',index!==0&&mode==='list'?'is-list-border':'']"
+				 :style="item.styleBackgroud" v-for="(item,index) in dataList" :key="index">
+					<checkbox class="hidden" hidden :disabled="disabled || !!item.disabled" :value="item[map.value]+''" :checked="item.selected" />
+					<view v-if="(mode !=='tag' && mode !== 'list') || ( mode === 'list' && icon === 'left')" class="checkbox__inner"  :style="item.styleIcon">
+						<view class="checkbox__inner-icon"></view>
+					</view>
+					<view class="checklist-content" :class="{'list-content':mode === 'list' && icon ==='left'}">
+						<text class="checklist-text" :style="item.styleIconText">{{item[map.text]}}</text>
+						<view v-if="mode === 'list' && icon === 'right'" class="checkobx__list" :style="item.styleBackgroud"></view>
+					</view>
+				</label>
+			</checkbox-group>
+			<radio-group v-else class="checklist-group" :class="{'is-list':mode==='list','is-wrap':wrap}" @change="chagne">
+				<!-- -->
+				<label class="checklist-box" :class="['is--'+mode,item.selected?'is-checked':'',(disabled || !!item.disabled)?'is-disable':'',index!==0&&mode==='list'?'is-list-border':'']"
+				 :style="item.styleBackgroud" v-for="(item,index) in dataList" :key="index">
+					<radio class="hidden" hidden :disabled="disabled || item.disabled" :value="item[map.value]+''" :checked="item.selected" />
+					<view v-if="(mode !=='tag' && mode !== 'list') || ( mode === 'list' && icon === 'left')" class="radio__inner"
+					 :style="item.styleBackgroud">
+						<view class="radio__inner-icon" :style="item.styleIcon"></view>
+					</view>
+					<view class="checklist-content" :class="{'list-content':mode === 'list' && icon ==='left'}">
+						<text class="checklist-text" :style="item.styleIconText">{{item[map.text]}}</text>
+						<view v-if="mode === 'list' && icon === 'right'" :style="item.styleRightIcon" class="checkobx__list"></view>
+					</view>
+				</label>
+			</radio-group>
+		</template>
+	</view>
+</template>
+
+<script>
+	/**
+	 * DataChecklist 数据选择器
+	 * @description 通过数据渲染 checkbox 和 radio
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=xxx
+	 * @property {String} mode = [default| list | button | tag] 显示模式
+	 * @value default  	默认横排模式
+	 * @value list		列表模式
+	 * @value button	按钮模式
+	 * @value tag 		标签模式
+	 * @property {Boolean} multiple = [true|false] 是否多选
+	 * @property {Array|String|Number} value 默认值
+	 * @property {Array} localdata 本地数据 ,格式 [{text:'',value:''}]
+	 * @property {Number|String} min 最小选择个数 ,multiple为true时生效
+	 * @property {Number|String} max 最大选择个数 ,multiple为true时生效
+	 * @property {Boolean} wrap 是否换行显示
+	 * @property {String} icon = [left|right]  list 列表模式下icon显示位置
+	 * @property {Boolean} selectedColor 选中颜色
+	 * @property {Boolean} emptyText 没有数据时显示的文字 ,本地数据无效
+	 * @property {Boolean} selectedTextColor 选中文本颜色,如不填写则自动显示
+	 * @property {Object} map 字段映射, 默认 map={text:'text',value:'value'}
+	 * @value left 左侧显示
+	 * @value right 右侧显示
+	 * @event {Function} change  选中发生变化触发
+	 */
+
+	export default {
+		name: 'uniDataChecklist',
+		mixins: [uniCloud.mixinDatacom || {}],
+		emits:['input','update:modelValue','change'],
+		props: {
+			mode: {
+				type: String,
+				default: 'default'
+			},
+
+			multiple: {
+				type: Boolean,
+				default: false
+			},
+			value: {
+				type: [Array, String, Number],
+				default () {
+					return ''
+				}
+			},
+			// TODO vue3
+			modelValue: {
+				type: [Array, String, Number],
+				default() {
+					return '';
+				}
+			},
+			localdata: {
+				type: Array,
+				default () {
+					return []
+				}
+			},
+			min: {
+				type: [Number, String],
+				default: ''
+			},
+			max: {
+				type: [Number, String],
+				default: ''
+			},
+			wrap: {
+				type: Boolean,
+				default: false
+			},
+			icon: {
+				type: String,
+				default: 'left'
+			},
+			selectedColor: {
+				type: String,
+				default: ''
+			},
+			selectedTextColor: {
+				type: String,
+				default: ''
+			},
+			emptyText:{
+				type: String,
+				default: '暂无数据'
+			},
+			disabled:{
+				type: Boolean,
+				default: false
+			},
+			map:{
+				type: Object,
+				default(){
+					return {
+						text:'text',
+						value:'value'
+					}
+				}
+			}
+		},
+		watch: {
+			localdata: {
+				handler(newVal) {
+					this.range = newVal
+					this.dataList = this.getDataList(this.getSelectedValue(newVal))
+				},
+				deep: true
+			},
+			mixinDatacomResData(newVal) {
+				this.range = newVal
+				this.dataList = this.getDataList(this.getSelectedValue(newVal))
+			},
+			value(newVal) {
+				this.dataList = this.getDataList(newVal)
+				// fix by mehaotian is_reset 在 uni-forms 中定义
+				// if(!this.is_reset){
+				// 	this.is_reset = false
+				// 	this.formItem && this.formItem.setValue(newVal)
+				// }
+			},
+			modelValue(newVal) {
+				this.dataList = this.getDataList(newVal);
+				// if(!this.is_reset){
+				// 	this.is_reset = false
+				// 	this.formItem && this.formItem.setValue(newVal)
+				// }
+			}
+		},
+		data() {
+			return {
+				dataList: [],
+				range: [],
+				contentText: {
+					contentdown: '查看更多',
+					contentrefresh: '加载中',
+					contentnomore: '没有更多'
+				},
+				isLocal:true,
+				styles: {
+					selectedColor: '#2979ff',
+					selectedTextColor: '#666',
+				},
+				isTop:0
+			};
+		},
+		computed:{
+			dataValue(){
+				if(this.value === '')return this.modelValue
+				if(this.modelValue === '') return this.value
+				return this.value
+			}
+		},
+		created() {
+			// this.form = this.getForm('uniForms')
+			// this.formItem = this.getForm('uniFormsItem')
+			// this.formItem && this.formItem.setValue(this.value)
+
+			// if (this.formItem) {
+			// 	this.isTop = 6
+			// 	if (this.formItem.name) {
+			// 		// 如果存在name添加默认值,否则formData 中不存在这个字段不校验
+			// 		if(!this.is_reset){
+			// 			this.is_reset = false
+			// 			this.formItem.setValue(this.dataValue)
+			// 		}
+			// 		this.rename = this.formItem.name
+			// 		this.form.inputChildrens.push(this)
+			// 	}
+			// }
+
+			if (this.localdata && this.localdata.length !== 0) {
+				this.isLocal = true
+				this.range = this.localdata
+				this.dataList = this.getDataList(this.getSelectedValue(this.range))
+			} else {
+				if (this.collection) {
+					this.isLocal = false
+					this.loadData()
+				}
+			}
+		},
+		methods: {
+			loadData() {
+				this.mixinDatacomGet().then(res=>{
+					this.mixinDatacomResData = res.result.data
+					if(this.mixinDatacomResData.length === 0){
+						this.isLocal = false
+						this.mixinDatacomErrorMessage = this.emptyText
+					}else{
+						this.isLocal = true
+					}
+				}).catch(err=>{
+					this.mixinDatacomErrorMessage = err.message
+				})
+			},
+			/**
+			 * 获取父元素实例
+			 */
+			getForm(name = 'uniForms') {
+				let parent = this.$parent;
+				let parentName = parent.$options.name;
+				while (parentName !== name) {
+					parent = parent.$parent;
+					if (!parent) return false
+					parentName = parent.$options.name;
+				}
+				return parent;
+			},
+			chagne(e) {
+				const values = e.detail.value
+
+				let detail = {
+					value: [],
+					data: []
+				}
+
+				if (this.multiple) {
+					this.range.forEach(item => {
+
+						if (values.includes(item[this.map.value] + '')) {
+							detail.value.push(item[this.map.value])
+							detail.data.push(item)
+						}
+					})
+				} else {
+					const range = this.range.find(item => (item[this.map.value] + '') === values)
+					if (range) {
+						detail = {
+							value: range[this.map.value],
+							data: range
+						}
+					}
+				}
+				// this.formItem && this.formItem.setValue(detail.value)
+				// TODO 兼容 vue2
+				this.$emit('input', detail.value);
+				// // TOTO 兼容 vue3
+				this.$emit('update:modelValue', detail.value);
+				this.$emit('change', {
+					detail
+				})
+				if (this.multiple) {
+					// 如果 v-model 没有绑定 ,则走内部逻辑
+					// if (this.value.length === 0) {
+					this.dataList = this.getDataList(detail.value, true)
+					// }
+				} else {
+					this.dataList = this.getDataList(detail.value)
+				}
+			},
+
+			/**
+			 * 获取渲染的新数组
+			 * @param {Object} value 选中内容
+			 */
+			getDataList(value) {
+				// 解除引用关系,破坏原引用关系,避免污染源数据
+				let dataList = JSON.parse(JSON.stringify(this.range))
+				let list = []
+				if (this.multiple) {
+					if (!Array.isArray(value)) {
+						value = []
+					}
+				}
+				dataList.forEach((item, index) => {
+					item.disabled = item.disable || item.disabled || false
+					if (this.multiple) {
+						if (value.length > 0) {
+							let have = value.find(val => val === item[this.map.value])
+							item.selected = have !== undefined
+						} else {
+							item.selected = false
+						}
+					} else {
+						item.selected = value === item[this.map.value]
+					}
+
+					list.push(item)
+				})
+				return this.setRange(list)
+			},
+			/**
+			 * 处理最大最小值
+			 * @param {Object} list
+			 */
+			setRange(list) {
+				let selectList = list.filter(item => item.selected)
+				let min = Number(this.min) || 0
+				let max = Number(this.max) || ''
+				list.forEach((item, index) => {
+					if (this.multiple) {
+						if (selectList.length <= min) {
+							let have = selectList.find(val => val[this.map.value] === item[this.map.value])
+							if (have !== undefined) {
+								item.disabled = true
+							}
+						}
+
+						if (selectList.length >= max && max !== '') {
+							let have = selectList.find(val => val[this.map.value] === item[this.map.value])
+							if (have === undefined) {
+								item.disabled = true
+							}
+						}
+					}
+					this.setStyles(item, index)
+					list[index] = item
+				})
+				return list
+			},
+			/**
+			 * 设置 class
+			 * @param {Object} item
+			 * @param {Object} index
+			 */
+			setStyles(item, index) {
+				//  设置自定义样式
+				item.styleBackgroud = this.setStyleBackgroud(item)
+				item.styleIcon = this.setStyleIcon(item)
+				item.styleIconText = this.setStyleIconText(item)
+				item.styleRightIcon = this.setStyleRightIcon(item)
+			},
+
+			/**
+			 * 获取选中值
+			 * @param {Object} range
+			 */
+			getSelectedValue(range) {
+				if (!this.multiple) return this.dataValue
+				let selectedArr = []
+				range.forEach((item) => {
+					if (item.selected) {
+						selectedArr.push(item[this.map.value])
+					}
+				})
+				return this.dataValue.length > 0 ? this.dataValue : selectedArr
+			},
+
+			/**
+			 * 设置背景样式
+			 */
+			setStyleBackgroud(item) {
+				let styles = {}
+				let selectedColor = this.selectedColor?this.selectedColor:'#2979ff'
+				if (this.mode !== 'list') {
+					styles['border-color'] = item.selected?selectedColor:'#DCDFE6'
+				}
+				if (this.mode === 'tag') {
+					styles['background-color'] = item.selected? selectedColor:'#f5f5f5'
+				}
+				let classles = ''
+				for (let i in styles) {
+					classles += `${i}:${styles[i]};`
+				}
+				return classles
+			},
+			setStyleIcon(item) {
+				let styles = {}
+				let classles = ''
+				let selectedColor = this.selectedColor?this.selectedColor:'#2979ff'
+				styles['background-color'] = item.selected?selectedColor:'#fff'
+				styles['border-color'] = item.selected?selectedColor:'#DCDFE6'
+
+				if(!item.selected && item.disabled){
+					styles['background-color'] = '#F2F6FC'
+					styles['border-color'] = item.selected?selectedColor:'#DCDFE6'
+				}
+
+				for (let i in styles) {
+					classles += `${i}:${styles[i]};`
+				}
+				return classles
+			},
+			setStyleIconText(item) {
+				let styles = {}
+				let classles = ''
+				let selectedColor = this.selectedColor?this.selectedColor:'#2979ff'
+				if (this.mode === 'tag') {
+					styles.color = item.selected?(this.selectedTextColor?this.selectedTextColor:'#fff'):'#666'
+				} else {
+					styles.color = item.selected?(this.selectedTextColor?this.selectedTextColor:selectedColor):'#666'
+				}
+				if(!item.selected && item.disabled){
+					styles.color = '#999'
+				}
+
+				for (let i in styles) {
+					classles += `${i}:${styles[i]};`
+				}
+				return classles
+			},
+			setStyleRightIcon(item) {
+				let styles = {}
+				let classles = ''
+				if (this.mode === 'list') {
+					styles['border-color'] = item.selected?this.styles.selectedColor:'#DCDFE6'
+				}
+				for (let i in styles) {
+					classles += `${i}:${styles[i]};`
+				}
+
+				return classles
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	$checked-color: #2979ff;
+	$border-color: #DCDFE6;
+	$disable:0.4;
+
+	@mixin flex {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+	}
+
+	.uni-data-loading {
+		@include flex;
+		flex-direction: row;
+		justify-content: center;
+		align-items: center;
+		height: 36px;
+		padding-left: 10px;
+		color: #999;
+	}
+
+	.uni-data-checklist {
+		position: relative;
+		z-index: 0;
+		flex: 1;
+		// 多选样式
+		.checklist-group {
+			@include flex;
+			flex-direction: row;
+			flex-wrap: wrap;
+
+			&.is-list {
+				flex-direction: column;
+			}
+
+			.checklist-box {
+				@include flex;
+				flex-direction: row;
+				align-items: center;
+				position: relative;
+				margin: 5px 0;
+				margin-right: 25px;
+
+				.hidden {
+					position: absolute;
+					opacity: 0;
+				}
+
+				// 文字样式
+				.checklist-content {
+					@include flex;
+					flex: 1;
+					flex-direction: row;
+					align-items: center;
+					justify-content: space-between;
+					.checklist-text {
+						font-size: 14px;
+						color: #666;
+						margin-left: 5px;
+						line-height: 14px;
+					}
+
+					.checkobx__list {
+						border-right-width: 1px;
+						border-right-color: #007aff;
+						border-right-style: solid;
+						border-bottom-width:1px;
+						border-bottom-color: #007aff;
+						border-bottom-style: solid;
+						height: 12px;
+						width: 6px;
+						left: -5px;
+						transform-origin: center;
+						transform: rotate(45deg);
+						opacity: 0;
+					}
+				}
+
+				// 多选样式
+				.checkbox__inner {
+					/* #ifndef APP-NVUE */
+					flex-shrink: 0;
+					box-sizing: border-box;
+					/* #endif */
+					position: relative;
+					width: 16px;
+					height: 16px;
+					border: 1px solid $border-color;
+					border-radius: 4px;
+					background-color: #fff;
+					z-index: 1;
+					.checkbox__inner-icon {
+						position: absolute;
+						/* #ifdef APP-NVUE */
+						top: 2px;
+						/* #endif */
+						/* #ifndef APP-NVUE */
+						top: 1px;
+						/* #endif */
+						left: 5px;
+						height: 8px;
+						width: 4px;
+						border-right-width: 1px;
+						border-right-color: #fff;
+						border-right-style: solid;
+						border-bottom-width:1px ;
+						border-bottom-color: #fff;
+						border-bottom-style: solid;
+						opacity: 0;
+						transform-origin: center;
+						transform: rotate(40deg);
+					}
+				}
+
+				// 单选样式
+				.radio__inner {
+					@include flex;
+					/* #ifndef APP-NVUE */
+					flex-shrink: 0;
+					box-sizing: border-box;
+					/* #endif */
+					justify-content: center;
+					align-items: center;
+					position: relative;
+					width: 16px;
+					height: 16px;
+					border: 1px solid $border-color;
+					border-radius: 16px;
+					background-color: #fff;
+					z-index: 1;
+
+					.radio__inner-icon {
+						width: 8px;
+						height: 8px;
+						border-radius: 10px;
+						opacity: 0;
+					}
+				}
+
+				// 默认样式
+				&.is--default {
+
+					// 禁用
+					&.is-disable {
+						/* #ifdef H5 */
+						cursor: not-allowed;
+						/* #endif */
+						.checkbox__inner {
+							background-color: #F2F6FC;
+							border-color: $border-color;
+							/* #ifdef H5 */
+							cursor: not-allowed;
+							/* #endif */
+						}
+
+						.radio__inner {
+							background-color: #F2F6FC;
+							border-color: $border-color;
+						}
+						.checklist-text {
+							color: #999;
+						}
+					}
+
+					// 选中
+					&.is-checked {
+						.checkbox__inner {
+							border-color: $checked-color;
+							background-color: $checked-color;
+
+							.checkbox__inner-icon {
+								opacity: 1;
+								transform: rotate(45deg);
+							}
+						}
+						.radio__inner {
+							border-color: $checked-color;
+							.radio__inner-icon {
+								opacity: 1;
+								background-color: $checked-color;
+							}
+						}
+						.checklist-text {
+							color: $checked-color;
+						}
+						// 选中禁用
+						&.is-disable {
+							.checkbox__inner {
+								opacity: $disable;
+							}
+
+							.checklist-text {
+								opacity: $disable;
+							}
+							.radio__inner {
+								opacity: $disable;
+							}
+						}
+					}
+				}
+
+				// 按钮样式
+				&.is--button {
+					margin-right: 10px;
+					padding: 5px 10px;
+					border: 1px $border-color solid;
+					border-radius: 3px;
+					transition: border-color 0.2s;
+
+					// 禁用
+					&.is-disable {
+						/* #ifdef H5 */
+						cursor: not-allowed;
+						/* #endif */
+						border: 1px #eee solid;
+						opacity: $disable;
+						.checkbox__inner {
+							background-color: #F2F6FC;
+							border-color: $border-color;
+							/* #ifdef H5 */
+							cursor: not-allowed;
+							/* #endif */
+						}
+						.radio__inner {
+							background-color: #F2F6FC;
+							border-color: $border-color;
+							/* #ifdef H5 */
+							cursor: not-allowed;
+							/* #endif */
+						}
+						.checklist-text {
+							color: #999;
+						}
+					}
+
+					&.is-checked {
+						border-color: $checked-color;
+						.checkbox__inner {
+							border-color: $checked-color;
+							background-color: $checked-color;
+							.checkbox__inner-icon {
+								opacity: 1;
+								transform: rotate(45deg);
+							}
+						}
+
+						.radio__inner {
+							border-color: $checked-color;
+
+							.radio__inner-icon {
+								opacity: 1;
+								background-color: $checked-color;
+							}
+						}
+
+						.checklist-text {
+							color: $checked-color;
+						}
+
+						// 选中禁用
+						&.is-disable {
+							opacity: $disable;
+						}
+					}
+				}
+
+				// 标签样式
+				&.is--tag {
+					margin-right: 10px;
+					padding: 5px 10px;
+					border: 1px $border-color solid;
+					border-radius: 3px;
+					background-color: #f5f5f5;
+
+					.checklist-text {
+						margin: 0;
+						color: #666;
+					}
+
+					// 禁用
+					&.is-disable {
+						/* #ifdef H5 */
+						cursor: not-allowed;
+						/* #endif */
+						opacity: $disable;
+					}
+
+					&.is-checked {
+						background-color: $checked-color;
+						border-color: $checked-color;
+
+						.checklist-text {
+							color: #fff;
+						}
+					}
+				}
+				// 列表样式
+				&.is--list {
+					/* #ifndef APP-NVUE */
+					display: flex;
+					/* #endif */
+					padding: 10px 15px;
+					padding-left: 0;
+					margin: 0;
+
+					&.is-list-border {
+						border-top: 1px #eee solid;
+					}
+
+					// 禁用
+					&.is-disable {
+						/* #ifdef H5 */
+						cursor: not-allowed;
+						/* #endif */
+						.checkbox__inner {
+							background-color: #F2F6FC;
+							border-color: $border-color;
+							/* #ifdef H5 */
+							cursor: not-allowed;
+							/* #endif */
+						}
+						.checklist-text {
+							color: #999;
+						}
+					}
+
+					&.is-checked {
+						.checkbox__inner {
+							border-color: $checked-color;
+							background-color: $checked-color;
+
+							.checkbox__inner-icon {
+								opacity: 1;
+								transform: rotate(45deg);
+							}
+						}
+						.radio__inner {
+							.radio__inner-icon {
+								opacity: 1;
+							}
+						}
+						.checklist-text {
+							color: $checked-color;
+						}
+
+						.checklist-content {
+							.checkobx__list {
+								opacity: 1;
+								border-color: $checked-color;
+							}
+						}
+
+						// 选中禁用
+						&.is-disable {
+							.checkbox__inner {
+								opacity: $disable;
+							}
+
+							.checklist-text {
+								opacity: $disable;
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-data-checkbox/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-data-checkbox/package.json
new file mode 100644
index 000000000..51470a956
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-data-checkbox/package.json
@@ -0,0 +1,87 @@
+{
+  "id": "uni-data-checkbox",
+  "displayName": "uni-data-checkbox 数据选择器",
+  "version": "1.0.2",
+  "description": "通过数据驱动的单选框和复选框",
+  "keywords": [
+    "uni-ui",
+    "checkbox",
+    "单选",
+    "多选",
+    "单选多选"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": "^3.1.1"
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": ["uni-load-more","uni-scss"],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-data-checkbox/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-data-checkbox/readme.md
new file mode 100644
index 000000000..6eb253d42
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-data-checkbox/readme.md
@@ -0,0 +1,18 @@
+
+
+## DataCheckbox 数据驱动的单选复选框
+> **组件名:uni-data-checkbox**
+> 代码块: `uDataCheckbox`
+
+
+本组件是基于uni-app基础组件checkbox的封装。本组件要解决问题包括:
+
+1. 数据绑定型组件:给本组件绑定一个data,会自动渲染一组候选内容。再以往,开发者需要编写不少代码实现类似功能
+2. 自动的表单校验:组件绑定了data,且符合[uni-forms](https://ext.dcloud.net.cn/plugin?id=2773)组件的表单校验规范,搭配使用会自动实现表单校验
+3. 本组件合并了单选多选
+4. 本组件有若干风格选择,如普通的单选多选框、并列button风格、tag风格。开发者可以快速选择需要的风格。但作为一个封装组件,样式代码虽然不用自己写了,却会牺牲一定的样式自定义性
+
+在uniCloud开发中,`DB Schema`中配置了enum枚举等类型后,在web控制台的[自动生成表单](https://uniapp.dcloud.io/uniCloud/schema?id=autocode)功能中,会自动生成``uni-data-checkbox``组件并绑定好data
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-data-checkbox)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-data-picker/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-data-picker/changelog.md
new file mode 100644
index 000000000..083e521fe
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-data-picker/changelog.md
@@ -0,0 +1,64 @@
+## 1.0.7(2022-07-06)
+- 优化 pc端图标位置不正确的问题
+## 1.0.6(2022-07-05)
+- 优化 显示样式
+## 1.0.5(2022-07-04)
+- 修复 uni-data-picker 在 uni-forms-item 中宽度不正确的bug
+## 1.0.4(2022-04-19)
+- 修复 字节小程序 本地数据无法选择下一级的Bug
+## 1.0.3(2022-02-25)
+- 修复 nvue 不支持的 v-show 的 bug
+## 1.0.2(2022-02-25)
+- 修复 条件编译 nvue 不支持的 css 样式
+## 1.0.1(2021-11-23)
+- 修复 由上个版本引发的map、v-model等属性不生效的bug
+## 1.0.0(2021-11-19)
+- 优化 组件 UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-data-picker](https://uniapp.dcloud.io/component/uniui/uni-data-picker)
+## 0.4.9(2021-10-28)
+- 修复 VUE2 v-model 概率无效的 bug
+## 0.4.8(2021-10-27)
+- 修复 v-model 概率无效的 bug
+## 0.4.7(2021-10-25)
+- 新增 属性 spaceInfo 服务空间配置 HBuilderX 3.2.11+
+- 修复 树型 uniCloud 数据类型为 int 时报错的 bug
+## 0.4.6(2021-10-19)
+- 修复 非 VUE3 v-model 为 0 时无法选中的 bug
+## 0.4.5(2021-09-26)
+- 新增 清除已选项的功能(通过 clearIcon 属性配置是否显示按钮),同时提供 clear 方法以供调用,二者等效
+- 修复 readonly 为 true 时报错的 bug
+## 0.4.4(2021-09-26)
+- 修复 上一版本造成的 map 属性失效的 bug
+- 新增 ellipsis 属性,支持配置 tab 选项长度过长时是否自动省略
+## 0.4.3(2021-09-24)
+- 修复 某些情况下级联未触发的 bug
+## 0.4.2(2021-09-23)
+- 新增 提供 show 和 hide 方法,开发者可以通过 ref 调用
+- 新增 选项内容过长自动添加省略号
+## 0.4.1(2021-09-15)
+- 新增 map 属性 字段映射,将 text/value 映射到数据中的其他字段
+## 0.4.0(2021-07-13)
+- 组件兼容 vue3,如何创建 vue3 项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 0.3.5(2021-06-04)
+- 修复 无法加载云端数据的问题
+## 0.3.4(2021-05-28)
+- 修复 v-model 无效问题
+- 修复 loaddata 为空数据组时加载时间过长问题
+- 修复 上个版本引出的本地数据无法选择带有 children 的 2 级节点
+## 0.3.3(2021-05-12)
+- 新增 组件示例地址
+## 0.3.2(2021-04-22)
+- 修复 非树形数据有 where 属性查询报错的问题
+## 0.3.1(2021-04-15)
+- 修复 本地数据概率无法回显时问题
+## 0.3.0(2021-04-07)
+- 新增 支持云端非树形表结构数据
+- 修复 根节点 parent_field 字段等于 null 时选择界面错乱问题
+## 0.2.0(2021-03-15)
+- 修复 nodeclick、popupopened、popupclosed 事件无法触发的问题
+## 0.1.9(2021-03-09)
+- 修复 微信小程序某些情况下无法选择的问题
+## 0.1.8(2021-02-05)
+- 优化 部分样式在 nvue 上的兼容表现
+## 0.1.7(2021-02-05)
+- 调整为 uni_modules 目录规范
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-data-picker/components/uni-data-picker/keypress.js b/yudao-ui-admin-uniapp/uni_modules/uni-data-picker/components/uni-data-picker/keypress.js
new file mode 100644
index 000000000..6ef26a262
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-data-picker/components/uni-data-picker/keypress.js
@@ -0,0 +1,45 @@
+// #ifdef H5
+export default {
+  name: 'Keypress',
+  props: {
+    disable: {
+      type: Boolean,
+      default: false
+    }
+  },
+  mounted () {
+    const keyNames = {
+      esc: ['Esc', 'Escape'],
+      tab: 'Tab',
+      enter: 'Enter',
+      space: [' ', 'Spacebar'],
+      up: ['Up', 'ArrowUp'],
+      left: ['Left', 'ArrowLeft'],
+      right: ['Right', 'ArrowRight'],
+      down: ['Down', 'ArrowDown'],
+      delete: ['Backspace', 'Delete', 'Del']
+    }
+    const listener = ($event) => {
+      if (this.disable) {
+        return
+      }
+      const keyName = Object.keys(keyNames).find(key => {
+        const keyName = $event.key
+        const value = keyNames[key]
+        return value === keyName || (Array.isArray(value) && value.includes(keyName))
+      })
+      if (keyName) {
+        // 避免和其他按键事件冲突
+        setTimeout(() => {
+          this.$emit(keyName, {})
+        }, 0)
+      }
+    }
+    document.addEventListener('keyup', listener)
+    this.$once('hook:beforeDestroy', () => {
+      document.removeEventListener('keyup', listener)
+    })
+  },
+	render: () => {}
+}
+// #endif
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-data-picker/components/uni-data-picker/uni-data-picker.vue b/yudao-ui-admin-uniapp/uni_modules/uni-data-picker/components/uni-data-picker/uni-data-picker.vue
new file mode 100644
index 000000000..455362755
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-data-picker/components/uni-data-picker/uni-data-picker.vue
@@ -0,0 +1,554 @@
+<template>
+	<view class="uni-data-tree">
+		<view class="uni-data-tree-input" @click="handleInput">
+			<slot :options="options" :data="inputSelected" :error="errorMessage">
+				<view class="input-value" :class="{'input-value-border': border}">
+					<text v-if="errorMessage" class="selected-area error-text">{{errorMessage}}</text>
+					<view v-else-if="loading && !isOpened" class="selected-area">
+						<uni-load-more class="load-more" :contentText="loadMore" status="loading"></uni-load-more>
+					</view>
+					<scroll-view v-else-if="inputSelected.length" class="selected-area" scroll-x="true">
+						<view class="selected-list">
+							<view class="selected-item" v-for="(item,index) in inputSelected" :key="index">
+								<text class="text-color">{{item.text}}</text><text v-if="index<inputSelected.length-1"
+									class="input-split-line">{{split}}</text>
+							</view>
+						</view>
+					</scroll-view>
+					<text v-else class="selected-area placeholder">{{placeholder}}</text>
+					<view v-if="clearIcon && !readonly && inputSelected.length" class="icon-clear"
+						@click.stop="clear">
+						<uni-icons type="clear" color="#c0c4cc" size="24"></uni-icons>
+					</view>
+					<view class="arrow-area" v-if="(!clearIcon || !inputSelected.length) && !readonly ">
+						<view class="input-arrow"></view>
+					</view>
+				</view>
+			</slot>
+		</view>
+		<view class="uni-data-tree-cover" v-if="isOpened" @click="handleClose"></view>
+		<view class="uni-data-tree-dialog" v-if="isOpened">
+			<view class="uni-popper__arrow"></view>
+			<view class="dialog-caption">
+				<view class="title-area">
+					<text class="dialog-title">{{popupTitle}}</text>
+				</view>
+				<view class="dialog-close" @click="handleClose">
+					<view class="dialog-close-plus" data-id="close"></view>
+					<view class="dialog-close-plus dialog-close-rotate" data-id="close"></view>
+				</view>
+			</view>
+			<data-picker-view class="picker-view" ref="pickerView" v-model="dataValue" :localdata="localdata"
+				:preload="preload" :collection="collection" :field="field" :orderby="orderby" :where="where"
+				:step-searh="stepSearh" :self-field="selfField" :parent-field="parentField" :managed-mode="true"
+				:map="map" :ellipsis="ellipsis" @change="onchange" @datachange="ondatachange" @nodeclick="onnodeclick">
+			</data-picker-view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import dataPicker from "../uni-data-pickerview/uni-data-picker.js"
+	import DataPickerView from "../uni-data-pickerview/uni-data-pickerview.vue"
+
+	/**
+	 * DataPicker 级联选择
+	 * @description 支持单列、和多列级联选择。列数没有限制,如果屏幕显示不全,顶部tab区域会左右滚动。
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=3796
+	 * @property {String} popup-title 弹出窗口标题
+	 * @property {Array} localdata 本地数据,参考
+	 * @property {Boolean} border = [true|false] 是否有边框
+	 * @property {Boolean} readonly = [true|false] 是否仅读
+	 * @property {Boolean} preload = [true|false] 是否预加载数据
+	 * @value true 开启预加载数据,点击弹出窗口后显示已加载数据
+	 * @value false 关闭预加载数据,点击弹出窗口后开始加载数据
+	 * @property {Boolean} step-searh = [true|false] 是否分布查询
+	 * @value true 启用分布查询,仅查询当前选中节点
+	 * @value false 关闭分布查询,一次查询出所有数据
+	 * @property {String|DBFieldString} self-field 分布查询当前字段名称
+	 * @property {String|DBFieldString} parent-field 分布查询父字段名称
+	 * @property {String|DBCollectionString} collection 表名
+	 * @property {String|DBFieldString} field 查询字段,多个字段用 `,` 分割
+	 * @property {String} orderby 排序字段及正序倒叙设置
+	 * @property {String|JQLString} where 查询条件
+	 * @event {Function} popupshow 弹出的选择窗口打开时触发此事件
+	 * @event {Function} popuphide 弹出的选择窗口关闭时触发此事件
+	 */
+	export default {
+		name: 'UniDataPicker',
+		emits: ['popupopened', 'popupclosed', 'nodeclick', 'input', 'change', 'update:modelValue'],
+		mixins: [dataPicker],
+		components: {
+			DataPickerView
+		},
+		props: {
+			options: {
+				type: [Object, Array],
+				default () {
+					return {}
+				}
+			},
+			popupTitle: {
+				type: String,
+				default: '请选择'
+			},
+			placeholder: {
+				type: String,
+				default: '请选择'
+			},
+			heightMobile: {
+				type: String,
+				default: ''
+			},
+			readonly: {
+				type: Boolean,
+				default: false
+			},
+			clearIcon: {
+				type: Boolean,
+				default: true
+			},
+			border: {
+				type: Boolean,
+				default: true
+			},
+			split: {
+				type: String,
+				default: '/'
+			},
+			ellipsis: {
+				type: Boolean,
+				default: true
+			}
+		},
+		data() {
+			return {
+				isOpened: false,
+				inputSelected: []
+			}
+		},
+		created() {
+			this.form = this.getForm('uniForms')
+			this.formItem = this.getForm('uniFormsItem')
+			if (this.formItem) {
+				if (this.formItem.name) {
+					this.rename = this.formItem.name
+					this.form.inputChildrens.push(this)
+				}
+			}
+
+			this.$nextTick(() => {
+				this.load()
+			})
+		},
+		methods: {
+			clear() {
+				this.inputSelected.splice(0)
+				this._dispatchEvent([])
+			},
+			onPropsChange() {
+				this._treeData = []
+				this.selectedIndex = 0
+				this.load()
+			},
+			load() {
+				if (this.readonly) {
+					this._processReadonly(this.localdata, this.dataValue)
+					return
+				}
+
+				if (this.isLocaldata) {
+					this.loadData()
+					this.inputSelected = this.selected.slice(0)
+				} else if (!this.parentField && !this.selfField && this.hasValue) {
+					this.getNodeData(() => {
+						this.inputSelected = this.selected.slice(0)
+					})
+				} else if (this.hasValue) {
+					this.getTreePath(() => {
+						this.inputSelected = this.selected.slice(0)
+					})
+				}
+			},
+			getForm(name = 'uniForms') {
+				let parent = this.$parent;
+				let parentName = parent.$options.name;
+				while (parentName !== name) {
+					parent = parent.$parent;
+					if (!parent) return false;
+					parentName = parent.$options.name;
+				}
+				return parent;
+			},
+			show() {
+				this.isOpened = true
+				setTimeout(() => {
+					this.$refs.pickerView.updateData({
+						treeData: this._treeData,
+						selected: this.selected,
+						selectedIndex: this.selectedIndex
+					})
+				}, 200)
+				this.$emit('popupopened')
+			},
+			hide() {
+				this.isOpened = false
+				this.$emit('popupclosed')
+			},
+			handleInput() {
+				if (this.readonly) {
+					return
+				}
+				this.show()
+			},
+			handleClose(e) {
+				this.hide()
+			},
+			onnodeclick(e) {
+				this.$emit('nodeclick', e)
+			},
+			ondatachange(e) {
+				this._treeData = this.$refs.pickerView._treeData
+			},
+			onchange(e) {
+				this.hide()
+				this.$nextTick(() => {
+					this.inputSelected = e;
+				})
+				this._dispatchEvent(e)
+			},
+			_processReadonly(dataList, value) {
+				var isTree = dataList.findIndex((item) => {
+					return item.children
+				})
+				if (isTree > -1) {
+					let inputValue
+					if (Array.isArray(value)) {
+						inputValue = value[value.length - 1]
+						if (typeof inputValue === 'object' && inputValue.value) {
+							inputValue = inputValue.value
+						}
+					} else {
+						inputValue = value
+					}
+					this.inputSelected = this._findNodePath(inputValue, this.localdata)
+					return
+				}
+
+				if (!this.hasValue) {
+					this.inputSelected = []
+					return
+				}
+
+				let result = []
+				for (let i = 0; i < value.length; i++) {
+					var val = value[i]
+					var item = dataList.find((v) => {
+						return v.value == val
+					})
+					if (item) {
+						result.push(item)
+					}
+				}
+				if (result.length) {
+					this.inputSelected = result
+				}
+			},
+			_filterForArray(data, valueArray) {
+				var result = []
+				for (let i = 0; i < valueArray.length; i++) {
+					var value = valueArray[i]
+					var found = data.find((item) => {
+						return item.value == value
+					})
+					if (found) {
+						result.push(found)
+					}
+				}
+				return result
+			},
+			_dispatchEvent(selected) {
+				let item = {}
+				if (selected.length) {
+					var value = new Array(selected.length)
+					for (var i = 0; i < selected.length; i++) {
+						value[i] = selected[i].value
+					}
+					item = selected[selected.length - 1]
+				} else {
+					item.value = ''
+				}
+				if (this.formItem) {
+					this.formItem.setValue(item.value)
+				}
+
+				this.$emit('input', item.value)
+				this.$emit('update:modelValue', item.value)
+				this.$emit('change', {
+					detail: {
+						value: selected
+					}
+				})
+			}
+		}
+	}
+</script>
+
+<style >
+	.uni-data-tree {
+		flex: 1;
+		position: relative;
+		font-size: 14px;
+	}
+
+	.error-text {
+		color: #DD524D;
+	}
+
+	.input-value {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		align-items: center;
+		flex-wrap: nowrap;
+		font-size: 14px;
+		/* line-height: 35px; */
+		padding: 0 10px;
+		padding-right: 5px;
+		overflow: hidden;
+		height: 35px;
+		/* #ifndef APP-NVUE */
+		box-sizing: border-box;
+		/* #endif */
+	}
+
+	.input-value-border {
+		border: 1px solid #e5e5e5;
+		border-radius: 5px;
+	}
+
+	.selected-area {
+		flex: 1;
+		overflow: hidden;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+	}
+
+	.load-more {
+		/* #ifndef APP-NVUE */
+		margin-right: auto;
+		/* #endif */
+		/* #ifdef APP-NVUE */
+		width: 40px;
+		/* #endif */
+	}
+
+	.selected-list {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		flex-wrap: nowrap;
+		/* padding: 0 5px; */
+	}
+
+	.selected-item {
+		flex-direction: row;
+		/* padding: 0 1px; */
+		/* #ifndef APP-NVUE */
+		white-space: nowrap;
+		/* #endif */
+	}
+	
+	.text-color {
+		color: #333;
+	}
+
+	.placeholder {
+		color: grey;
+		font-size: 12px;
+	}
+
+	.input-split-line {
+		opacity: .5;
+	}
+
+	.arrow-area {
+		position: relative;
+		width: 20px;
+		/* #ifndef APP-NVUE */
+		margin-bottom: 5px;
+		margin-left: auto;
+		display: flex;
+		/* #endif */
+		justify-content: center;
+		transform: rotate(-45deg);
+		transform-origin: center;
+	}
+
+	.input-arrow {
+		width: 7px;
+		height: 7px;
+		border-left: 1px solid #999;
+		border-bottom: 1px solid #999;
+	}
+
+	.uni-data-tree-cover {
+		position: fixed;
+		left: 0;
+		top: 0;
+		right: 0;
+		bottom: 0;
+		background-color: rgba(0, 0, 0, .4);
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		z-index: 100;
+	}
+
+	.uni-data-tree-dialog {
+		position: fixed;
+		left: 0;
+		top: 20%;
+		right: 0;
+		bottom: 0;
+		background-color: #FFFFFF;
+		border-top-left-radius: 10px;
+		border-top-right-radius: 10px;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		z-index: 102;
+		overflow: hidden;
+		/* #ifdef APP-NVUE */
+		width: 750rpx;
+		/* #endif */
+	}
+
+	.dialog-caption {
+		position: relative;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		/* border-bottom: 1px solid #f0f0f0; */
+	}
+
+	.title-area {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		align-items: center;
+		/* #ifndef APP-NVUE */
+		margin: auto;
+		/* #endif */
+		padding: 0 10px;
+	}
+
+	.dialog-title {
+		/* font-weight: bold; */
+		line-height: 44px;
+	}
+
+	.dialog-close {
+		position: absolute;
+		top: 0;
+		right: 0;
+		bottom: 0;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		align-items: center;
+		padding: 0 15px;
+	}
+
+	.dialog-close-plus {
+		width: 16px;
+		height: 2px;
+		background-color: #666;
+		border-radius: 2px;
+		transform: rotate(45deg);
+	}
+
+	.dialog-close-rotate {
+		position: absolute;
+		transform: rotate(-45deg);
+	}
+
+	.picker-view {
+		flex: 1;
+		overflow: hidden;
+	}
+	
+	.icon-clear {
+		display: flex;
+		align-items: center;
+	}
+
+	/* #ifdef H5 */
+	@media all and (min-width: 768px) {
+		.uni-data-tree-cover {
+			background-color: transparent;
+		}
+
+		.uni-data-tree-dialog {
+			position: absolute;
+			top: 55px;
+			height: auto;
+			min-height: 400px;
+			max-height: 50vh;
+			background-color: #fff;
+			border: 1px solid #EBEEF5;
+			box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+			border-radius: 4px;
+			overflow: unset;
+		}
+
+		.dialog-caption {
+			display: none;
+		}
+
+		.icon-clear {
+			/* margin-right: 5px; */
+		}
+	}
+
+	/* #endif */
+
+	/* picker 弹出层通用的指示小三角, todo:扩展至上下左右方向定位 */
+	/* #ifndef APP-NVUE */
+	.uni-popper__arrow,
+	.uni-popper__arrow::after {
+		position: absolute;
+		display: block;
+		width: 0;
+		height: 0;
+		border-color: transparent;
+		border-style: solid;
+		border-width: 6px;
+	}
+
+	.uni-popper__arrow {
+		filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03));
+		top: -6px;
+		left: 10%;
+		margin-right: 3px;
+		border-top-width: 0;
+		border-bottom-color: #EBEEF5;
+	}
+
+	.uni-popper__arrow::after {
+		content: " ";
+		top: 1px;
+		margin-left: -6px;
+		border-top-width: 0;
+		border-bottom-color: #fff;
+	}
+	/* #endif */
+	</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-picker.js b/yudao-ui-admin-uniapp/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-picker.js
new file mode 100644
index 000000000..c12fd54b3
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-picker.js
@@ -0,0 +1,563 @@
+export default {
+  props: {
+    localdata: {
+      type: [Array, Object],
+      default () {
+        return []
+      }
+    },
+    spaceInfo: {
+      type: Object,
+      default () {
+        return {}
+      }
+    },
+    collection: {
+      type: String,
+      default: ''
+    },
+    action: {
+      type: String,
+      default: ''
+    },
+    field: {
+      type: String,
+      default: ''
+    },
+    orderby: {
+      type: String,
+      default: ''
+    },
+    where: {
+      type: [String, Object],
+      default: ''
+    },
+    pageData: {
+      type: String,
+      default: 'add'
+    },
+    pageCurrent: {
+      type: Number,
+      default: 1
+    },
+    pageSize: {
+      type: Number,
+      default: 20
+    },
+    getcount: {
+      type: [Boolean, String],
+      default: false
+    },
+    getone: {
+      type: [Boolean, String],
+      default: false
+    },
+    gettree: {
+      type: [Boolean, String],
+      default: false
+    },
+    manual: {
+      type: Boolean,
+      default: false
+    },
+    value: {
+      type: [Array, String, Number],
+      default () {
+        return []
+      }
+    },
+    modelValue: {
+      type: [Array, String, Number],
+      default () {
+        return []
+      }
+    },
+    preload: {
+      type: Boolean,
+      default: false
+    },
+    stepSearh: {
+      type: Boolean,
+      default: true
+    },
+    selfField: {
+      type: String,
+      default: ''
+    },
+    parentField: {
+      type: String,
+      default: ''
+    },
+    multiple: {
+      type: Boolean,
+      default: false
+    },
+    map: {
+      type: Object,
+      default() {
+        return {
+          text: "text",
+          value: "value"
+        }
+      }
+    }
+  },
+  data() {
+    return {
+      loading: false,
+      errorMessage: '',
+      loadMore: {
+        contentdown: '',
+        contentrefresh: '',
+        contentnomore: ''
+      },
+      dataList: [],
+      selected: [],
+      selectedIndex: 0,
+      page: {
+        current: this.pageCurrent,
+        size: this.pageSize,
+        count: 0
+      }
+    }
+  },
+  computed: {
+    isLocaldata() {
+      return !this.collection.length
+    },
+    postField() {
+      let fields = [this.field];
+      if (this.parentField) {
+        fields.push(`${this.parentField} as parent_value`);
+      }
+      return fields.join(',');
+    },
+    dataValue() {
+      let isModelValue = Array.isArray(this.modelValue) ? (this.modelValue.length > 0) : (this.modelValue !== null || this.modelValue !== undefined)
+      return isModelValue ? this.modelValue : this.value
+    },
+    hasValue() {
+      if (typeof this.dataValue === 'number') {
+        return true
+      }
+      return (this.dataValue != null) && (this.dataValue.length > 0)
+    }
+  },
+  created() {
+    this.$watch(() => {
+      var al = [];
+      ['pageCurrent',
+        'pageSize',
+        'spaceInfo',
+        'value',
+        'modelValue',
+        'localdata',
+        'collection',
+        'action',
+        'field',
+        'orderby',
+        'where',
+        'getont',
+        'getcount',
+        'gettree'
+      ].forEach(key => {
+        al.push(this[key])
+      });
+      return al
+    }, (newValue, oldValue) => {
+      let needReset = false
+      for (let i = 2; i < newValue.length; i++) {
+        if (newValue[i] != oldValue[i]) {
+          needReset = true
+          break
+        }
+      }
+      if (newValue[0] != oldValue[0]) {
+        this.page.current = this.pageCurrent
+      }
+      this.page.size = this.pageSize
+
+      this.onPropsChange()
+    })
+    this._treeData = []
+  },
+  methods: {
+    onPropsChange() {
+      this._treeData = []
+    },
+    getCommand(options = {}) {
+      /* eslint-disable no-undef */
+      let db = uniCloud.database(this.spaceInfo)
+
+      const action = options.action || this.action
+      if (action) {
+        db = db.action(action)
+      }
+
+      const collection = options.collection || this.collection
+      db = db.collection(collection)
+
+      const where = options.where || this.where
+      if (!(!where || !Object.keys(where).length)) {
+        db = db.where(where)
+      }
+
+      const field = options.field || this.field
+      if (field) {
+        db = db.field(field)
+      }
+
+      const orderby = options.orderby || this.orderby
+      if (orderby) {
+        db = db.orderBy(orderby)
+      }
+
+      const current = options.pageCurrent !== undefined ? options.pageCurrent : this.page.current
+      const size = options.pageSize !== undefined ? options.pageSize : this.page.size
+      const getCount = options.getcount !== undefined ? options.getcount : this.getcount
+      const getTree = options.gettree !== undefined ? options.gettree : this.gettree
+
+      const getOptions = {
+        getCount,
+        getTree
+      }
+      if (options.getTreePath) {
+        getOptions.getTreePath = options.getTreePath
+      }
+
+      db = db.skip(size * (current - 1)).limit(size).get(getOptions)
+
+      return db
+    },
+		getNodeData(callback) {
+		  if (this.loading) {
+		    return
+		  }
+		  this.loading = true
+		  this.getCommand({
+		    field: this.postField,
+				where: this._pathWhere()
+		  }).then((res) => {
+		    this.loading = false
+		    this.selected = res.result.data
+		    callback && callback()
+		  }).catch((err) => {
+		    this.loading = false
+		    this.errorMessage = err
+		  })
+		},
+    getTreePath(callback) {
+      if (this.loading) {
+        return
+      }
+      this.loading = true
+
+      this.getCommand({
+        field: this.postField,
+        getTreePath: {
+          startWith: `${this.selfField}=='${this.dataValue}'`
+        }
+      }).then((res) => {
+        this.loading = false
+        let treePath = []
+        this._extractTreePath(res.result.data, treePath)
+        this.selected = treePath
+        callback && callback()
+      }).catch((err) => {
+        this.loading = false
+        this.errorMessage = err
+      })
+    },
+    loadData() {
+      if (this.isLocaldata) {
+        this._processLocalData()
+        return
+      }
+
+      if (this.dataValue != null) {
+        this._loadNodeData((data) => {
+          this._treeData = data
+          this._updateBindData()
+          this._updateSelected()
+        })
+        return
+      }
+
+      if (this.stepSearh) {
+        this._loadNodeData((data) => {
+          this._treeData = data
+          this._updateBindData()
+        })
+      } else {
+        this._loadAllData((data) => {
+          this._treeData = []
+          this._extractTree(data, this._treeData, null)
+          this._updateBindData()
+        })
+      }
+    },
+    _loadAllData(callback) {
+      if (this.loading) {
+        return
+      }
+      this.loading = true
+
+      this.getCommand({
+        field: this.postField,
+        gettree: true,
+        startwith: `${this.selfField}=='${this.dataValue}'`
+      }).then((res) => {
+        this.loading = false
+        callback(res.result.data)
+        this.onDataChange()
+      }).catch((err) => {
+        this.loading = false
+        this.errorMessage = err
+      })
+    },
+    _loadNodeData(callback, pw) {
+      if (this.loading) {
+        return
+      }
+      this.loading = true
+
+      this.getCommand({
+        field: this.postField,
+        where: pw || this._postWhere(),
+        pageSize: 500
+      }).then((res) => {
+        this.loading = false
+        callback(res.result.data)
+        this.onDataChange()
+      }).catch((err) => {
+        this.loading = false
+        this.errorMessage = err
+      })
+    },
+    _pathWhere() {
+      let result = []
+      let where_field = this._getParentNameByField();
+      if (where_field) {
+        result.push(`${where_field} == '${this.dataValue}'`)
+      }
+
+      if (this.where) {
+        return `(${this.where}) && (${result.join(' || ')})`
+      }
+
+      return result.join(' || ')
+    },
+    _postWhere() {
+      let result = []
+      let selected = this.selected
+      let parentField = this.parentField
+      if (parentField) {
+        result.push(`${parentField} == null || ${parentField} == ""`)
+      }
+      if (selected.length) {
+        for (var i = 0; i < selected.length - 1; i++) {
+          result.push(`${parentField} == '${selected[i].value}'`)
+        }
+      }
+
+      let where = []
+      if (this.where) {
+        where.push(`(${this.where})`)
+      }
+      if (result.length) {
+        where.push(`(${result.join(' || ')})`)
+      }
+
+      return where.join(' && ')
+    },
+    _nodeWhere() {
+      let result = []
+      let selected = this.selected
+      if (selected.length) {
+        result.push(`${this.parentField} == '${selected[selected.length - 1].value}'`)
+      }
+
+      if (this.where) {
+        return `(${this.where}) && (${result.join(' || ')})`
+      }
+
+      return result.join(' || ')
+    },
+    _getParentNameByField() {
+      const fields = this.field.split(',');
+      let where_field = null;
+      for (let i = 0; i < fields.length; i++) {
+        const items = fields[i].split('as');
+        if (items.length < 2) {
+          continue;
+        }
+        if (items[1].trim() === 'value') {
+          where_field = items[0].trim();
+          break;
+        }
+      }
+      return where_field
+    },
+    _isTreeView() {
+      return (this.parentField && this.selfField)
+    },
+    _updateSelected() {
+      var dl = this.dataList
+      var sl = this.selected
+      let textField = this.map.text
+      let valueField = this.map.value
+      for (var i = 0; i < sl.length; i++) {
+        var value = sl[i].value
+        var dl2 = dl[i]
+        for (var j = 0; j < dl2.length; j++) {
+          var item2 = dl2[j]
+          if (item2[valueField] === value) {
+            sl[i].text = item2[textField]
+            break
+          }
+        }
+      }
+    },
+    _updateBindData(node) {
+      const {
+        dataList,
+        hasNodes
+      } = this._filterData(this._treeData, this.selected)
+
+      let isleaf = this._stepSearh === false && !hasNodes
+
+      if (node) {
+        node.isleaf = isleaf
+      }
+
+      this.dataList = dataList
+      this.selectedIndex = dataList.length - 1
+
+      if (!isleaf && this.selected.length < dataList.length) {
+        this.selected.push({
+          value: null,
+          text: "请选择"
+        })
+      }
+
+      return {
+        isleaf,
+        hasNodes
+      }
+    },
+    _filterData(data, paths) {
+      let dataList = []
+      let hasNodes = true
+
+      dataList.push(data.filter((item) => {
+        return (item.parent_value === null || item.parent_value === undefined || item.parent_value === '')
+      }))
+      for (let i = 0; i < paths.length; i++) {
+        var value = paths[i].value
+        var nodes = data.filter((item) => {
+          return item.parent_value === value
+        })
+
+        if (nodes.length) {
+          dataList.push(nodes)
+        } else {
+          hasNodes = false
+        }
+      }
+
+      return {
+        dataList,
+        hasNodes
+      }
+    },
+    _extractTree(nodes, result, parent_value) {
+      let list = result || []
+      let valueField = this.map.value
+      for (let i = 0; i < nodes.length; i++) {
+        let node = nodes[i]
+
+        let child = {}
+        for (let key in node) {
+          if (key !== 'children') {
+            child[key] = node[key]
+          }
+        }
+        if (parent_value !== null && parent_value !== undefined && parent_value !== '') {
+          child.parent_value = parent_value
+        }
+        result.push(child)
+
+        let children = node.children
+        if (children) {
+          this._extractTree(children, result, node[valueField])
+        }
+      }
+    },
+    _extractTreePath(nodes, result) {
+      let list = result || []
+      for (let i = 0; i < nodes.length; i++) {
+        let node = nodes[i]
+
+        let child = {}
+        for (let key in node) {
+          if (key !== 'children') {
+            child[key] = node[key]
+          }
+        }
+        result.push(child)
+
+        let children = node.children
+        if (children) {
+          this._extractTreePath(children, result)
+        }
+      }
+    },
+    _findNodePath(key, nodes, path = []) {
+      let textField = this.map.text
+      let valueField = this.map.value
+      for (let i = 0; i < nodes.length; i++) {
+        let node = nodes[i]
+        let children = node.children
+        let text = node[textField]
+        let value = node[valueField]
+
+        path.push({
+          value,
+          text
+        })
+
+        if (value === key) {
+          return path
+        }
+
+        if (children) {
+          const p = this._findNodePath(key, children, path)
+          if (p.length) {
+            return p
+          }
+        }
+
+        path.pop()
+      }
+      return []
+    },
+    _processLocalData() {
+      this._treeData = []
+      this._extractTree(this.localdata, this._treeData)
+
+      var inputValue = this.dataValue
+      if (inputValue === undefined) {
+        return
+      }
+
+      if (Array.isArray(inputValue)) {
+        inputValue = inputValue[inputValue.length - 1]
+        if (typeof inputValue === 'object' && inputValue[this.map.value]) {
+          inputValue = inputValue[this.map.value]
+        }
+      }
+
+      this.selected = this._findNodePath(inputValue, this.localdata)
+    }
+  }
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.vue b/yudao-ui-admin-uniapp/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.vue
new file mode 100644
index 000000000..065aac2b6
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.vue
@@ -0,0 +1,333 @@
+<template>
+	<view class="uni-data-pickerview">
+		<scroll-view class="selected-area" scroll-x="true" scroll-y="false" :show-scrollbar="false">
+			<view class="selected-list">
+				<template v-for="(item,index) in selected">
+					<view class="selected-item"
+						:class="{'selected-item-active':index==selectedIndex, 'selected-item-text-overflow': ellipsis}"
+						 v-if="item.text" @click="handleSelect(index)">
+						<text class="">{{item.text}}</text>
+					</view>
+				</template>
+			</view>
+		</scroll-view>
+		<view class="tab-c">
+			<template v-for="(child, i) in dataList" >
+				<scroll-view class="list" :key="i" v-if="i==selectedIndex" :scroll-y="true">
+					<view class="item" :class="{'is-disabled': !!item.disable}" v-for="(item, j) in child"
+						@click="handleNodeClick(item, i, j)">
+						<text class="item-text item-text-overflow">{{item[map.text]}}</text>
+						<view class="check" v-if="selected.length > i && item[map.value] == selected[i].value"></view>
+					</view>
+				</scroll-view>
+			</template>
+
+			<view class="loading-cover" v-if="loading">
+				<uni-load-more class="load-more" :contentText="loadMore" status="loading"></uni-load-more>
+			</view>
+			<view class="error-message" v-if="errorMessage">
+				<text class="error-text">{{errorMessage}}</text>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import dataPicker from "./uni-data-picker.js"
+
+	/**
+	 * DataPickerview
+	 * @description uni-data-pickerview
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=3796
+	 * @property {Array} localdata 本地数据,参考
+	 * @property {Boolean} step-searh = [true|false] 是否分布查询
+	 * @value true 启用分布查询,仅查询当前选中节点
+	 * @value false 关闭分布查询,一次查询出所有数据
+	 * @property {String|DBFieldString} self-field 分布查询当前字段名称
+	 * @property {String|DBFieldString} parent-field 分布查询父字段名称
+	 * @property {String|DBCollectionString} collection 表名
+	 * @property {String|DBFieldString} field 查询字段,多个字段用 `,` 分割
+	 * @property {String} orderby 排序字段及正序倒叙设置
+	 * @property {String|JQLString} where 查询条件
+	 */
+	export default {
+		name: 'UniDataPickerView',
+		emits: ['nodeclick', 'change', 'datachange', 'update:modelValue'],
+		mixins: [dataPicker],
+		props: {
+			managedMode: {
+				type: Boolean,
+				default: false
+			},
+			ellipsis: {
+				type: Boolean,
+				default: true
+			}
+		},
+		data() {
+			return {}
+		},
+		created() {
+			if (this.managedMode) {
+				return
+			}
+
+			this.$nextTick(() => {
+				this.load()
+			})
+		},
+		methods: {
+			onPropsChange() {
+				this._treeData = []
+				this.selectedIndex = 0
+				this.load()
+			},
+			load() {
+				if (this.isLocaldata) {
+					this.loadData()
+				} else if (this.dataValue.length) {
+					this.getTreePath((res) => {
+						this.loadData()
+					})
+				}
+			},
+			handleSelect(index) {
+				this.selectedIndex = index
+			},
+			handleNodeClick(item, i, j) {
+				if (item.disable) {
+					return
+				}
+				const node = this.dataList[i][j]
+				const text = node[this.map.text]
+				const value = node[this.map.value]
+				if (i < this.selected.length - 1) {
+					this.selected.splice(i, this.selected.length - i)
+					this.selected.push({
+						text,
+						value
+					})
+				} else if (i === this.selected.length - 1) {
+					this.selected.splice(i, 1, {
+						text,
+						value
+					})
+				}
+
+				if (node.isleaf) {
+					this.onSelectedChange(node, node.isleaf)
+					return
+				}
+
+				const {
+					isleaf,
+					hasNodes
+				} = this._updateBindData()
+
+				if (!this._isTreeView() && !hasNodes) {
+					this.onSelectedChange(node, true)
+					return
+				}
+
+				if (this.isLocaldata && (!hasNodes || isleaf)) {
+					this.onSelectedChange(node, true)
+					return
+				}
+
+				if (!isleaf && !hasNodes) {
+					this._loadNodeData((data) => {
+						if (!data.length) {
+							node.isleaf = true
+						} else {
+							this._treeData.push(...data)
+							this._updateBindData(node)
+						}
+						this.onSelectedChange(node, node.isleaf)
+					}, this._nodeWhere())
+					return
+				}
+
+				this.onSelectedChange(node, false)
+			},
+			updateData(data) {
+				this._treeData = data.treeData
+				this.selected = data.selected
+				if (!this._treeData.length) {
+					this.loadData()
+				} else {
+					//this.selected = data.selected
+					this._updateBindData()
+				}
+			},
+			onDataChange() {
+				this.$emit('datachange')
+			},
+			onSelectedChange(node, isleaf) {
+				if (isleaf) {
+					this._dispatchEvent()
+				}
+
+				if (node) {
+					this.$emit('nodeclick', node)
+				}
+			},
+			_dispatchEvent() {
+				this.$emit('change', this.selected.slice(0))
+			}
+		}
+	}
+</script>
+<style >
+	.uni-data-pickerview {
+		flex: 1;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		overflow: hidden;
+		height: 100%;
+	}
+
+	.error-text {
+		color: #DD524D;
+	}
+
+	.loading-cover {
+		position: absolute;
+		left: 0;
+		top: 0;
+		right: 0;
+		bottom: 0;
+		background-color: rgba(255, 255, 255, .5);
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		align-items: center;
+		z-index: 1001;
+	}
+
+	.load-more {
+		/* #ifndef APP-NVUE */
+		margin: auto;
+		/* #endif */
+	}
+
+	.error-message {
+		background-color: #fff;
+		position: absolute;
+		left: 0;
+		top: 0;
+		right: 0;
+		bottom: 0;
+		padding: 15px;
+		opacity: .9;
+		z-index: 102;
+	}
+
+	/* #ifdef APP-NVUE */
+	.selected-area {
+		width: 750rpx;
+	}
+
+	/* #endif */
+
+	.selected-list {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		flex-wrap: nowrap;
+		padding: 0 5px;
+		border-bottom: 1px solid #f8f8f8;
+	}
+
+	.selected-item {
+		margin-left: 10px;
+		margin-right: 10px;
+		padding: 12px 0;
+		text-align: center;
+		/* #ifndef APP-NVUE */
+		white-space: nowrap;
+		/* #endif */
+	}
+
+	.selected-item-text-overflow {
+		width: 168px;
+		/* fix nvue */
+		overflow: hidden;
+		/* #ifndef APP-NVUE */
+		width: 6em;
+		white-space: nowrap;
+		text-overflow: ellipsis;
+		-o-text-overflow: ellipsis;
+		/* #endif */
+	}
+
+	.selected-item-active {
+		border-bottom: 2px solid #007aff;
+	}
+
+	.selected-item-text {
+		color: #007aff;
+	}
+
+	.tab-c {
+		position: relative;
+		flex: 1;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		overflow: hidden;
+	}
+
+	.list {
+		flex: 1;
+	}
+
+	.item {
+		padding: 12px 15px;
+		/* border-bottom: 1px solid #f0f0f0; */
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		justify-content: space-between;
+	}
+
+	.is-disabled {
+		opacity: .5;
+	}
+
+	.item-text {
+		/* flex: 1; */
+		color: #333333;
+	}
+
+	.item-text-overflow {
+		width: 280px;
+		/* fix nvue */
+		overflow: hidden;
+		/* #ifndef APP-NVUE */
+		width: 20em;
+		white-space: nowrap;
+		text-overflow: ellipsis;
+		-o-text-overflow: ellipsis;
+		/* #endif */
+	}
+
+	.check {
+		margin-right: 5px;
+		border: 2px solid #007aff;
+		border-left: 0;
+		border-top: 0;
+		height: 12px;
+		width: 6px;
+		transform-origin: center;
+		/* #ifndef APP-NVUE */
+		transition: all 0.3s;
+		/* #endif */
+		transform: rotate(45deg);
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-data-picker/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-data-picker/package.json
new file mode 100644
index 000000000..990038024
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-data-picker/package.json
@@ -0,0 +1,93 @@
+{
+  "id": "uni-data-picker",
+  "displayName": "uni-data-picker 数据驱动的picker选择器",
+  "version": "1.0.7",
+  "description": "单列、多列级联选择器,常用于省市区城市选择、公司部门选择、多级分类等场景",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "picker",
+    "级联",
+    "省市区",
+    ""
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": [
+      "uni-load-more",
+			"uni-icons",
+			"uni-scss"
+    ],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+        "QQ": "y",
+        "京东": "u"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-data-picker/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-data-picker/readme.md
new file mode 100644
index 000000000..6cda22406
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-data-picker/readme.md
@@ -0,0 +1,22 @@
+## DataPicker 级联选择
+> **组件名:uni-data-picker**
+> 代码块: `uDataPicker`
+> 关联组件:`uni-data-pickerview`、`uni-load-more`。
+
+
+`<uni-data-picker>` 是一个选择类[datacom组件](https://uniapp.dcloud.net.cn/component/datacom)。
+
+支持单列、和多列级联选择。列数没有限制,如果屏幕显示不全,顶部tab区域会左右滚动。
+
+候选数据支持一次性加载完毕,也支持懒加载,比如示例图中,选择了“北京”后,动态加载北京的区县数据。
+
+`<uni-data-picker>` 组件尤其适用于地址选择、分类选择等选择类。
+
+`<uni-data-picker>` 支持本地数据、云端静态数据(json),uniCloud云数据库数据。
+
+`<uni-data-picker>` 可以通过JQL直连uniCloud云数据库,配套[DB Schema](https://uniapp.dcloud.net.cn/uniCloud/schema),可在schema2code中自动生成前端页面,还支持服务器端校验。
+
+在uniCloud数据表中新建表“uni-id-address”和“opendb-city-china”,这2个表的schema自带foreignKey关联。在“uni-id-address”表的表结构页面使用schema2code生成前端页面,会自动生成地址管理的维护页面,自动从“opendb-city-china”表包含的中国所有省市区信息里选择地址。
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-data-picker)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-data-select/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-data-select/changelog.md
new file mode 100644
index 000000000..d5beaa357
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-data-select/changelog.md
@@ -0,0 +1,16 @@
+## 0.1.6(2022-07-06)
+- 修复 pc端宽度异常的bug
+## 0.1.5
+- 修复 pc端宽度异常的bug
+## 0.1.4(2022-07-05)
+- 优化 显示样式
+## 0.1.3(2022-06-02)
+- 修复 localdata 赋值不生效的 bug
+- 新增 支持  uni.scss 修改颜色
+- 新增 支持选项禁用(数据选项设置 disabled: true 即禁用)
+## 0.1.2(2022-05-08)
+- 修复 当 value 为 0 时选择不生效的 bug
+## 0.1.1(2022-05-07)
+- 新增 记住上次的选项(仅 collection 存在时有效)
+## 0.1.0(2022-04-22)
+- 初始化
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-data-select/components/uni-data-select/uni-data-select.vue b/yudao-ui-admin-uniapp/uni_modules/uni-data-select/components/uni-data-select/uni-data-select.vue
new file mode 100644
index 000000000..16995bd69
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-data-select/components/uni-data-select/uni-data-select.vue
@@ -0,0 +1,426 @@
+<template>
+	<view class="uni-stat__select">
+		<span v-if="label" class="uni-label-text hide-on-phone">{{label + ':'}}</span>
+		<view class="uni-stat-box" :class="{'uni-stat__actived': current}">
+			<view class="uni-select">
+				<view class="uni-select__input-box" @click="toggleSelector">
+					<view v-if="current" class="uni-select__input-text">{{current}}</view>
+					<view v-else class="uni-select__input-text uni-select__input-placeholder">{{typePlaceholder}}</view>
+					<uni-icons v-if="current && clear" type="clear" color="#c0c4cc" size="24" @click="clearVal" />
+					<uni-icons v-else :type="showSelector? 'top' : 'bottom'" size="14" color="#999" />
+				</view>
+				<view class="uni-select--mask" v-if="showSelector" @click="toggleSelector" />
+				<view class="uni-select__selector" v-if="showSelector">
+					<view class="uni-popper__arrow"></view>
+					<scroll-view scroll-y="true" class="uni-select__selector-scroll">
+						<view class="uni-select__selector-empty" v-if="mixinDatacomResData.length === 0">
+							<text>{{emptyTips}}</text>
+						</view>
+						<view v-else class="uni-select__selector-item" v-for="(item,index) in mixinDatacomResData"
+							:key="index" @click="change(item)">
+							<text
+								:class="{'uni-select__selector__disabled': item.disable}">{{formatItemName(item)}}</text>
+						</view>
+					</scroll-view>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	/**
+	 * DataChecklist 数据选择器
+	 * @description 通过数据渲染的下拉框组件
+	 * @tutorial https://uniapp.dcloud.io/component/uniui/uni-data-select
+	 * @property {String} value 默认值
+	 * @property {Array} localdata 本地数据 ,格式 [{text:'',value:''}]
+	 * @property {Boolean} clear 是否可以清空已选项
+	 * @property {Boolean} emptyText 没有数据时显示的文字 ,本地数据无效
+	 * @property {String} label 左侧标题
+	 * @property {String} placeholder 输入框的提示文字
+	 * @event {Function} change  选中发生变化触发
+	 */
+
+	export default {
+		name: "uni-stat-select",
+		mixins: [uniCloud.mixinDatacom || {}],
+		data() {
+			return {
+				showSelector: false,
+				current: '',
+				mixinDatacomResData: [],
+				apps: [],
+				channels: []
+			};
+		},
+		props: {
+			localdata: {
+				type: Array,
+				default () {
+					return []
+				}
+			},
+			value: {
+				type: [String, Number],
+				default: ''
+			},
+			modelValue: {
+				type: [String, Number],
+				default: ''
+			},
+			label: {
+				type: String,
+				default: ''
+			},
+			placeholder: {
+				type: String,
+				default: '请选择'
+			},
+			emptyTips: {
+				type: String,
+				default: '无选项'
+			},
+			clear: {
+				type: Boolean,
+				default: true
+			},
+			defItem: {
+				type: Number,
+				default: 0
+			}
+		},
+		created() {
+			this.last = `${this.collection}_last_selected_option_value`
+			if (this.collection && !this.localdata.length) {
+				this.mixinDatacomEasyGet()
+			}
+		},
+		computed: {
+			typePlaceholder() {
+				const text = {
+					'opendb-stat-app-versions': '版本',
+					'opendb-app-channels': '渠道',
+					'opendb-app-list': '应用'
+				}
+				const common = this.placeholder
+				const placeholder = text[this.collection]
+				return placeholder ?
+					common + placeholder :
+					common
+			}
+		},
+		watch: {
+			localdata: {
+				immediate: true,
+				handler(val, old) {
+					if (Array.isArray(val) && old !== val) {
+						this.mixinDatacomResData = val
+					}
+				}
+			},
+			// #ifndef VUE3
+			value() {
+				this.initDefVal()
+			},
+			// #endif
+			// #ifdef VUE3
+			modelValue() {
+				this.initDefVal()
+			},
+			// #endif
+			mixinDatacomResData: {
+				immediate: true,
+				handler(val) {
+					if (val.length) {
+						this.initDefVal()
+					}
+				}
+			}
+		},
+		methods: {
+			initDefVal() {
+				let defValue = ''
+				if ((this.value || this.value === 0) && !this.isDisabled(this.value)) {
+					defValue = this.value
+				} else if ((this.modelValue || this.modelValue === 0) && !this.isDisabled(this.modelValue)) {
+					defValue = this.modelValue
+				} else {
+					let strogeValue
+					if (this.collection) {
+						strogeValue = uni.getStorageSync(this.last)
+					}
+					if (strogeValue || strogeValue === 0) {
+						defValue = strogeValue
+					} else {
+						let defItem = ''
+						if (this.defItem > 0 && this.defItem < this.mixinDatacomResData.length) {
+							defItem = this.mixinDatacomResData[this.defItem - 1].value
+						}
+						defValue = defItem
+					}
+					this.emit(defValue)
+				}
+				const def = this.mixinDatacomResData.find(item => item.value === defValue)
+				this.current = def ? this.formatItemName(def) : ''
+			},
+
+			/**
+			 * @param {[String, Number]} value
+			 * 判断用户给的 value 是否同时为禁用状态
+			 */
+			isDisabled(value) {
+				let isDisabled = false;
+
+				this.mixinDatacomResData.forEach(item => {
+					if (item.value === value) {
+						isDisabled = item.disable
+					}
+				})
+
+				return isDisabled;
+			},
+
+			clearVal() {
+				this.emit('')
+				if (this.collection) {
+					uni.removeStorageSync(this.last)
+				}
+			},
+			change(item) {
+				if (!item.disable) {
+					this.showSelector = false
+					this.current = this.formatItemName(item)
+					this.emit(item.value)
+				}
+			},
+			emit(val) {
+				this.$emit('change', val)
+				this.$emit('input', val)
+				this.$emit('update:modelValue', val)
+				if (this.collection) {
+					uni.setStorageSync(this.last, val)
+				}
+			},
+
+			toggleSelector() {
+				this.showSelector = !this.showSelector
+			},
+			formatItemName(item) {
+				let {
+					text,
+					value,
+					channel_code
+				} = item
+				channel_code = channel_code ? `(${channel_code})` : ''
+				return this.collection.indexOf('app-list') > 0 ?
+					`${text}(${value})` :
+					(
+						text ?
+						text :
+						`未命名${channel_code}`
+					)
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	$uni-base-color: #6a6a6a !default;
+	$uni-main-color: #333 !default;
+	$uni-secondary-color: #909399 !default;
+	$uni-border-3: #e5e5e5;
+
+
+	/* #ifndef APP-NVUE */
+	@media screen and (max-width: 500px) {
+		.hide-on-phone {
+			display: none;
+		}
+	}
+
+	/* #endif */
+	.uni-stat__select {
+		display: flex;
+		align-items: center;
+		// padding: 15px;
+		cursor: pointer;
+		width: 100%;
+		flex: 1;
+		box-sizing: border-box;
+	}
+	
+	.uni-stat-box {
+		width: 100%;
+		flex: 1;
+	}
+	
+	.uni-stat__actived {
+		width: 100%;
+		flex: 1;
+		// outline: 1px solid #2979ff;
+	}
+
+	.uni-label-text {
+		font-size: 14px;
+		font-weight: bold;
+		color: $uni-base-color;
+		margin: auto 0;
+		margin-right: 5px;
+	}
+
+	.uni-select {
+		font-size: 14px;
+		border: 1px solid $uni-border-3;
+		box-sizing: border-box;
+		border-radius: 4px;
+		padding: 0 5px;
+		padding-left: 10px;
+		position: relative;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		user-select: none;
+		/* #endif */
+		flex-direction: row;
+		align-items: center;
+		border-bottom: solid 1px $uni-border-3;
+		width: 100%;
+		flex: 1;
+		height: 35px;
+	}
+
+	.uni-select__label {
+		font-size: 16px;
+		// line-height: 22px;
+		height: 35px;
+		padding-right: 10px;
+		color: $uni-secondary-color;
+	}
+
+	.uni-select__input-box {
+		// height: 35px;
+		position: relative;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex: 1;
+		flex-direction: row;
+		align-items: center;
+	}
+
+	.uni-select__input {
+		flex: 1;
+		font-size: 14px;
+		height: 22px;
+		line-height: 22px;
+	}
+
+	.uni-select__input-plac {
+		font-size: 14px;
+		color: $uni-secondary-color;
+	}
+
+	.uni-select__selector {
+		/* #ifndef APP-NVUE */
+		box-sizing: border-box;
+		/* #endif */
+		position: absolute;
+		top: calc(100% + 12px);
+		left: 0;
+		width: 100%;
+		background-color: #FFFFFF;
+		border: 1px solid #EBEEF5;
+		border-radius: 6px;
+		box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+		z-index: 2;
+		padding: 4px 0;
+	}
+
+	.uni-select__selector-scroll {
+		/* #ifndef APP-NVUE */
+		max-height: 200px;
+		box-sizing: border-box;
+		/* #endif */
+	}
+
+	.uni-select__selector-empty,
+	.uni-select__selector-item {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		cursor: pointer;
+		/* #endif */
+		line-height: 35px;
+		font-size: 14px;
+		text-align: center;
+		/* border-bottom: solid 1px $uni-border-3; */
+		padding: 0px 10px;
+	}
+
+	.uni-select__selector-item:hover {
+		background-color: #f9f9f9;
+	}
+
+	.uni-select__selector-empty:last-child,
+	.uni-select__selector-item:last-child {
+		/* #ifndef APP-NVUE */
+		border-bottom: none;
+		/* #endif */
+	}
+
+	.uni-select__selector__disabled {
+		opacity: 0.4;
+		cursor: default;
+	}
+
+	/* picker 弹出层通用的指示小三角 */
+	.uni-popper__arrow,
+	.uni-popper__arrow::after {
+		position: absolute;
+		display: block;
+		width: 0;
+		height: 0;
+		border-color: transparent;
+		border-style: solid;
+		border-width: 6px;
+	}
+
+	.uni-popper__arrow {
+		filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03));
+		top: -6px;
+		left: 10%;
+		margin-right: 3px;
+		border-top-width: 0;
+		border-bottom-color: #EBEEF5;
+	}
+
+	.uni-popper__arrow::after {
+		content: " ";
+		top: 1px;
+		margin-left: -6px;
+		border-top-width: 0;
+		border-bottom-color: #fff;
+	}
+
+	.uni-select__input-text {
+		// width: 280px;
+		width: 100%;
+		color: $uni-main-color;
+		white-space: nowrap;
+		text-overflow: ellipsis;
+		-o-text-overflow: ellipsis;
+		overflow: hidden;
+	}
+
+	.uni-select__input-placeholder {
+		color: $uni-base-color;
+		font-size: 12px;
+	}
+
+	.uni-select--mask {
+		position: fixed;
+		top: 0;
+		bottom: 0;
+		right: 0;
+		left: 0;
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-data-select/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-data-select/package.json
new file mode 100644
index 000000000..1ebd8dd40
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-data-select/package.json
@@ -0,0 +1,88 @@
+{
+  "id": "uni-data-select",
+  "displayName": "uni-data-select 下拉框选择器",
+  "version": "0.1.6",
+  "description": "通过数据驱动的下拉框选择器",
+  "keywords": [
+    "uni-ui",
+    "select",
+    "uni-data-select",
+    "下拉框",
+    "下拉选"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": "^3.1.1"
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": ["uni-load-more"],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "u",
+          "app-nvue": "n"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "u",
+          "百度": "u",
+          "字节跳动": "u",
+        "QQ": "u",
+        "京东": "u"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-data-select/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-data-select/readme.md
new file mode 100644
index 000000000..eb58de300
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-data-select/readme.md
@@ -0,0 +1,8 @@
+## DataSelect 下拉框选择器
+> **组件名:uni-data-select**
+> 代码块: `uDataSelect`
+
+当选项过多时,使用下拉菜单展示并选择内容
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-data-select)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-dateformat/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-dateformat/changelog.md
new file mode 100644
index 000000000..d551d7b88
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-dateformat/changelog.md
@@ -0,0 +1,10 @@
+## 1.0.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-dateformat](https://uniapp.dcloud.io/component/uniui/uni-dateformat)
+## 0.0.5(2021-07-08)
+- 调整 默认时间不再是当前时间,而是显示'-'字符
+## 0.0.4(2021-05-12)
+- 新增 组件示例地址
+## 0.0.3(2021-02-04)
+- 调整为uni_modules目录规范
+- 修复 iOS 平台日期格式化出错的问题
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-dateformat/components/uni-dateformat/date-format.js b/yudao-ui-admin-uniapp/uni_modules/uni-dateformat/components/uni-dateformat/date-format.js
new file mode 100644
index 000000000..e00d5597e
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-dateformat/components/uni-dateformat/date-format.js
@@ -0,0 +1,200 @@
+// yyyy-MM-dd hh:mm:ss.SSS 所有支持的类型
+function pad(str, length = 2) {
+	str += ''
+	while (str.length < length) {
+		str = '0' + str
+	}
+	return str.slice(-length)
+}
+
+const parser = {
+	yyyy: (dateObj) => {
+		return pad(dateObj.year, 4)
+	},
+	yy: (dateObj) => {
+		return pad(dateObj.year)
+	},
+	MM: (dateObj) => {
+		return pad(dateObj.month)
+	},
+	M: (dateObj) => {
+		return dateObj.month
+	},
+	dd: (dateObj) => {
+		return pad(dateObj.day)
+	},
+	d: (dateObj) => {
+		return dateObj.day
+	},
+	hh: (dateObj) => {
+		return pad(dateObj.hour)
+	},
+	h: (dateObj) => {
+		return dateObj.hour
+	},
+	mm: (dateObj) => {
+		return pad(dateObj.minute)
+	},
+	m: (dateObj) => {
+		return dateObj.minute
+	},
+	ss: (dateObj) => {
+		return pad(dateObj.second)
+	},
+	s: (dateObj) => {
+		return dateObj.second
+	},
+	SSS: (dateObj) => {
+		return pad(dateObj.millisecond, 3)
+	},
+	S: (dateObj) => {
+		return dateObj.millisecond
+	},
+}
+
+// 这都n年了iOS依然不认识2020-12-12,需要转换为2020/12/12
+function getDate(time) {
+	if (time instanceof Date) {
+		return time
+	}
+	switch (typeof time) {
+		case 'string':
+			{
+				// 2020-12-12T12:12:12.000Z、2020-12-12T12:12:12.000
+				if (time.indexOf('T') > -1) {
+					return new Date(time)
+				}
+				return new Date(time.replace(/-/g, '/'))
+			}
+		default:
+			return new Date(time)
+	}
+}
+
+export function formatDate(date, format = 'yyyy/MM/dd hh:mm:ss') {
+	if (!date && date !== 0) {
+		return ''
+	}
+	date = getDate(date)
+	const dateObj = {
+		year: date.getFullYear(),
+		month: date.getMonth() + 1,
+		day: date.getDate(),
+		hour: date.getHours(),
+		minute: date.getMinutes(),
+		second: date.getSeconds(),
+		millisecond: date.getMilliseconds()
+	}
+	const tokenRegExp = /yyyy|yy|MM|M|dd|d|hh|h|mm|m|ss|s|SSS|SS|S/
+	let flag = true
+	let result = format
+	while (flag) {
+		flag = false
+		result = result.replace(tokenRegExp, function(matched) {
+			flag = true
+			return parser[matched](dateObj)
+		})
+	}
+	return result
+}
+
+export function friendlyDate(time, {
+	locale = 'zh',
+	threshold = [60000, 3600000],
+	format = 'yyyy/MM/dd hh:mm:ss'
+}) {
+	if (time === '-') {
+		return time
+	}
+	if (!time && time !== 0) {
+		return ''
+	}
+	const localeText = {
+		zh: {
+			year: '年',
+			month: '月',
+			day: '天',
+			hour: '小时',
+			minute: '分钟',
+			second: '秒',
+			ago: '前',
+			later: '后',
+			justNow: '刚刚',
+			soon: '马上',
+			template: '{num}{unit}{suffix}'
+		},
+		en: {
+			year: 'year',
+			month: 'month',
+			day: 'day',
+			hour: 'hour',
+			minute: 'minute',
+			second: 'second',
+			ago: 'ago',
+			later: 'later',
+			justNow: 'just now',
+			soon: 'soon',
+			template: '{num} {unit} {suffix}'
+		}
+	}
+	const text = localeText[locale] || localeText.zh
+	let date = getDate(time)
+	let ms = date.getTime() - Date.now()
+	let absMs = Math.abs(ms)
+	if (absMs < threshold[0]) {
+		return ms < 0 ? text.justNow : text.soon
+	}
+	if (absMs >= threshold[1]) {
+		return formatDate(date, format)
+	}
+	let num
+	let unit
+	let suffix = text.later
+	if (ms < 0) {
+		suffix = text.ago
+		ms = -ms
+	}
+	const seconds = Math.floor((ms) / 1000)
+	const minutes = Math.floor(seconds / 60)
+	const hours = Math.floor(minutes / 60)
+	const days = Math.floor(hours / 24)
+	const months = Math.floor(days / 30)
+	const years = Math.floor(months / 12)
+	switch (true) {
+		case years > 0:
+			num = years
+			unit = text.year
+			break
+		case months > 0:
+			num = months
+			unit = text.month
+			break
+		case days > 0:
+			num = days
+			unit = text.day
+			break
+		case hours > 0:
+			num = hours
+			unit = text.hour
+			break
+		case minutes > 0:
+			num = minutes
+			unit = text.minute
+			break
+		default:
+			num = seconds
+			unit = text.second
+			break
+	}
+
+	if (locale === 'en') {
+		if (num === 1) {
+			num = 'a'
+		} else {
+			unit += 's'
+		}
+	}
+
+	return text.template.replace(/{\s*num\s*}/g, num + '').replace(/{\s*unit\s*}/g, unit).replace(/{\s*suffix\s*}/g,
+		suffix)
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-dateformat/components/uni-dateformat/uni-dateformat.vue b/yudao-ui-admin-uniapp/uni_modules/uni-dateformat/components/uni-dateformat/uni-dateformat.vue
new file mode 100644
index 000000000..c5ed03078
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-dateformat/components/uni-dateformat/uni-dateformat.vue
@@ -0,0 +1,88 @@
+<template>
+	<text>{{dateShow}}</text>
+</template>
+
+<script>
+	import {friendlyDate} from './date-format.js'
+	/**
+	 * Dateformat 日期格式化
+	 * @description 日期格式化组件
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=3279
+	 * @property {Object|String|Number} date 日期对象/日期字符串/时间戳
+	 * @property {String} locale 格式化使用的语言
+	 * 	@value zh 中文
+	 * 	@value en 英文
+	 * @property {Array} threshold 应用不同类型格式化的阈值
+	 * @property {String} format 输出日期字符串时的格式
+	 */
+	export default {
+		name: 'uniDateformat',
+		props: {
+			date: {
+				type: [Object, String, Number],
+				default () {
+					return '-'
+				}
+			},
+			locale: {
+				type: String,
+				default: 'zh',
+			},
+			threshold: {
+				type: Array,
+				default () {
+					return [0, 0]
+				}
+			},
+			format: {
+				type: String,
+				default: 'yyyy/MM/dd hh:mm:ss'
+			},
+			// refreshRate使用不当可能导致性能问题,谨慎使用
+			refreshRate: {
+				type: [Number, String],
+				default: 0
+			}
+		},
+		data() {
+			return {
+				refreshMark: 0
+			}
+		},
+		computed: {
+			dateShow() {
+				this.refreshMark
+				return friendlyDate(this.date, {
+					locale: this.locale,
+					threshold: this.threshold,
+					format: this.format
+				})
+			}
+		},
+		watch: {
+			refreshRate: {
+				handler() {
+					this.setAutoRefresh()
+				},
+				immediate: true
+			}
+		},
+		methods: {
+			refresh() {
+				this.refreshMark++
+			},
+			setAutoRefresh() {
+				clearInterval(this.refreshInterval)
+				if (this.refreshRate) {
+					this.refreshInterval = setInterval(() => {
+						this.refresh()
+					}, parseInt(this.refreshRate))
+				}
+			}
+		}
+	}
+</script>
+
+<style>
+
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-dateformat/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-dateformat/package.json
new file mode 100644
index 000000000..786a670b0
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-dateformat/package.json
@@ -0,0 +1,88 @@
+{
+  "id": "uni-dateformat",
+  "displayName": "uni-dateformat 日期格式化",
+  "version": "1.0.0",
+  "description": "日期格式化组件,可以将日期格式化为1分钟前、刚刚等形式",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "日期格式化",
+    "时间格式化",
+    "格式化时间",
+    ""
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": ["uni-scss"],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "y",
+          "联盟": "y"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-dateformat/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-dateformat/readme.md
new file mode 100644
index 000000000..37ddb6ece
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-dateformat/readme.md
@@ -0,0 +1,11 @@
+
+
+### DateFormat 日期格式化
+> **组件名:uni-dateformat**
+> 代码块: `uDateformat`
+
+
+日期格式化组件。
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-dateformat)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-datetime-picker/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-datetime-picker/changelog.md
new file mode 100644
index 000000000..5c9735a1b
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-datetime-picker/changelog.md
@@ -0,0 +1,93 @@
+## 2.2.6(2022-06-30)
+- 优化 组件样式,调整了组件图标大小、高度、颜色等,与uni-ui风格保持一致
+## 2.2.5(2022-06-24)
+- 修复 日历顶部年月及底部确认未国际化 bug
+## 2.2.4(2022-03-31)
+- 修复 Vue3 下动态赋值,单选类型未响应的 bug
+## 2.2.3(2022-03-28)
+- 修复 Vue3 下动态赋值未响应的 bug
+## 2.2.2(2021-12-10)
+- 修复 clear-icon 属性在小程序平台不生效的 bug
+## 2.2.1(2021-12-10)
+- 修复 日期范围选在小程序平台,必须多点击一次才能取消选中状态的 bug
+## 2.2.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-datetime-picker](https://uniapp.dcloud.io/component/uniui/uni-datetime-picker)
+## 2.1.5(2021-11-09) 
+- 新增 提供组件设计资源,组件样式调整
+## 2.1.4(2021-09-10)
+- 修复 hide-second 在移动端的 bug
+- 修复 单选赋默认值时,赋值日期未高亮的 bug
+- 修复 赋默认值时,移动端未正确显示时间的 bug
+## 2.1.3(2021-09-09)
+- 新增 hide-second 属性,支持只使用时分,隐藏秒
+## 2.1.2(2021-09-03)
+- 优化 取消选中时(范围选)直接开始下一次选择, 避免多点一次
+- 优化 移动端支持清除按钮,同时支持通过 ref 调用组件的 clear 方法
+- 优化 调整字号大小,美化日历界面
+- 修复 因国际化导致的 placeholder 失效的 bug
+## 2.1.1(2021-08-24)
+- 新增 支持国际化
+- 优化 范围选择器在 pc 端过宽的问题
+## 2.1.0(2021-08-09)
+- 新增 适配 vue3
+## 2.0.19(2021-08-09)
+- 新增 支持作为 uni-forms 子组件相关功能
+- 修复 在 uni-forms 中使用时,选择时间报 NAN 错误的 bug
+## 2.0.18(2021-08-05)
+- 修复 type 属性动态赋值无效的 bug
+- 修复 ‘确认’按钮被 tabbar 遮盖 bug
+- 修复 组件未赋值时范围选左、右日历相同的 bug
+## 2.0.17(2021-08-04)
+- 修复 范围选未正确显示当前值的 bug
+- 修复 h5 平台(移动端)报错 'cale' of undefined 的 bug
+## 2.0.16(2021-07-21)
+- 新增 return-type 属性支持返回 date 日期对象
+## 2.0.15(2021-07-14)
+- 修复 单选日期类型,初始赋值后不在当前日历的 bug
+- 新增 clearIcon 属性,显示框的清空按钮可配置显示隐藏(仅 pc 有效)
+- 优化 移动端移除显示框的清空按钮,无实际用途
+## 2.0.14(2021-07-14)
+- 修复 组件赋值为空,界面未更新的 bug
+- 修复 start 和 end 不能动态赋值的 bug
+- 修复 范围选类型,用户选择后再次选择右侧日历(结束日期)显示不正确的 bug
+## 2.0.13(2021-07-08)
+- 修复 范围选择不能动态赋值的 bug
+## 2.0.12(2021-07-08)
+- 修复 范围选择的初始时间在一个月内时,造成无法选择的bug
+## 2.0.11(2021-07-08)
+- 优化 弹出层在超出视窗边缘定位不准确的问题
+## 2.0.10(2021-07-08)
+- 修复 范围起始点样式的背景色与今日样式的字体前景色融合,导致日期字体看不清的 bug
+- 优化 弹出层在超出视窗边缘被遮盖的问题
+## 2.0.9(2021-07-07)
+- 新增 maskClick 事件
+- 修复 特殊情况日历 rpx 布局错误的 bug,rpx -> px
+- 修复 范围选择时清空返回值不合理的bug,['', ''] -> []
+## 2.0.8(2021-07-07)
+- 新增 日期时间显示框支持插槽
+## 2.0.7(2021-07-01)
+- 优化 添加 uni-icons 依赖
+## 2.0.6(2021-05-22)
+- 修复 图标在小程序上不显示的 bug
+- 优化 重命名引用组件,避免潜在组件命名冲突
+## 2.0.5(2021-05-20)
+- 优化 代码目录扁平化
+## 2.0.4(2021-05-12)
+- 新增 组件示例地址
+## 2.0.3(2021-05-10)
+- 修复 ios 下不识别 '-' 日期格式的 bug
+- 优化 pc 下弹出层添加边框和阴影
+## 2.0.2(2021-05-08)
+- 修复 在 admin 中获取弹出层定位错误的bug
+## 2.0.1(2021-05-08)
+- 修复 type 属性向下兼容,默认值从 date 变更为 datetime
+## 2.0.0(2021-04-30)
+- 支持日历形式的日期+时间的范围选择
+ > 注意:此版本不向后兼容,不再支持单独时间选择(type=time)及相关的 hide-second 属性(时间选可使用内置组件 picker)
+## 1.0.6(2021-03-18)
+- 新增 hide-second 属性,时间支持仅选择时、分
+- 修复 选择跟显示的日期不一样的 bug
+- 修复 chang事件触发2次的 bug
+- 修复 分、秒 end 范围错误的 bug
+- 优化 更好的 nvue 适配
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar-item.vue b/yudao-ui-admin-uniapp/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar-item.vue
new file mode 100644
index 000000000..3d2dbeac1
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar-item.vue
@@ -0,0 +1,185 @@
+<template>
+	<view class="uni-calendar-item__weeks-box" :class="{
+		'uni-calendar-item--disable':weeks.disable,
+		'uni-calendar-item--before-checked-x':weeks.beforeMultiple,
+		'uni-calendar-item--multiple': weeks.multiple,
+		'uni-calendar-item--after-checked-x':weeks.afterMultiple,
+		}" @click="choiceDate(weeks)" @mouseenter="handleMousemove(weeks)">
+		<view class="uni-calendar-item__weeks-box-item" :class="{
+				'uni-calendar-item--checked':calendar.fullDate === weeks.fullDate && (calendar.userChecked || !checkHover),
+				'uni-calendar-item--checked-range-text': checkHover,
+				'uni-calendar-item--before-checked':weeks.beforeMultiple,
+				'uni-calendar-item--multiple': weeks.multiple,
+				'uni-calendar-item--after-checked':weeks.afterMultiple,
+				'uni-calendar-item--disable':weeks.disable,
+				}">
+			<text v-if="selected&&weeks.extraInfo" class="uni-calendar-item__weeks-box-circle"></text>
+			<text class="uni-calendar-item__weeks-box-text uni-calendar-item__weeks-box-text-disable uni-calendar-item--checked-text">{{weeks.date}}</text>
+		</view>
+		<view :class="{'uni-calendar-item--isDay': weeks.isDay}"></view>
+	</view>
+</template>
+
+<script>
+	export default {
+		props: {
+			weeks: {
+				type: Object,
+				default () {
+					return {}
+				}
+			},
+			calendar: {
+				type: Object,
+				default: () => {
+					return {}
+				}
+			},
+			selected: {
+				type: Array,
+				default: () => {
+					return []
+				}
+			},
+			lunar: {
+				type: Boolean,
+				default: false
+			},
+			checkHover: {
+				type: Boolean,
+				default: false
+			}
+		},
+		methods: {
+			choiceDate(weeks) {
+				this.$emit('change', weeks)
+			},
+			handleMousemove(weeks) {
+				this.$emit('handleMouse', weeks)
+			}
+		}
+	}
+</script>
+
+<style lang="scss" >
+	.uni-calendar-item__weeks-box {
+		flex: 1;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		justify-content: center;
+		align-items: center;
+		margin: 1px 0;
+		position: relative;
+	}
+
+	.uni-calendar-item__weeks-box-text {
+		font-size: 14px;
+		// font-family: Lato-Bold, Lato;
+		font-weight: bold;
+		color: #455997;
+	}
+
+	.uni-calendar-item__weeks-lunar-text {
+		font-size: 12px;
+		color: #333;
+	}
+
+	.uni-calendar-item__weeks-box-item {
+		position: relative;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		justify-content: center;
+		align-items: center;
+		width: 40px;
+		height: 40px;
+		/* #ifdef H5 */
+		cursor: pointer;
+		/* #endif */
+	}
+
+
+	.uni-calendar-item__weeks-box-circle {
+		position: absolute;
+		top: 5px;
+		right: 5px;
+		width: 8px;
+		height: 8px;
+		border-radius: 8px;
+		background-color: #dd524d;
+
+	}
+
+	.uni-calendar-item__weeks-box .uni-calendar-item--disable {
+		// background-color: rgba(249, 249, 249, $uni-opacity-disabled);
+		cursor: default;
+	}
+
+	.uni-calendar-item--disable .uni-calendar-item__weeks-box-text-disable {
+		color: #D1D1D1;
+	}
+
+	.uni-calendar-item--isDay {
+		position: absolute;
+		top: 10px;
+		right: 17%;
+		background-color: #dd524d;
+		width:6px;
+		height: 6px;
+		border-radius: 50%;
+	}
+
+	.uni-calendar-item--extra {
+		color: #dd524d;
+		opacity: 0.8;
+	}
+
+	.uni-calendar-item__weeks-box .uni-calendar-item--checked {
+		background-color: #007aff;
+		border-radius: 50%;
+		box-sizing: border-box;
+		border: 3px solid #fff;
+	}
+
+	.uni-calendar-item--checked .uni-calendar-item--checked-text {
+		color: #fff;
+	}
+
+	.uni-calendar-item--multiple .uni-calendar-item--checked-range-text {
+		color: #333;
+	}
+
+	.uni-calendar-item--multiple {
+		background-color:  #F6F7FC;
+		// color: #fff;
+	}
+
+	.uni-calendar-item--multiple .uni-calendar-item--before-checked,
+	.uni-calendar-item--multiple .uni-calendar-item--after-checked {
+		background-color: #409eff;
+		border-radius: 50%;
+		box-sizing: border-box;
+		border: 3px solid #F6F7FC;
+	}
+
+	.uni-calendar-item--before-checked .uni-calendar-item--checked-text,
+	.uni-calendar-item--after-checked .uni-calendar-item--checked-text {
+		color: #fff;
+	}
+
+	.uni-calendar-item--before-checked-x {
+		border-top-left-radius: 50px;
+		border-bottom-left-radius: 50px;
+		box-sizing: border-box;
+		background-color: #F6F7FC;
+	}
+
+	.uni-calendar-item--after-checked-x {
+		border-top-right-radius: 50px;
+		border-bottom-right-radius: 50px;
+		background-color: #F6F7FC;
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar.vue b/yudao-ui-admin-uniapp/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar.vue
new file mode 100644
index 000000000..8f7f18158
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-datetime-picker/components/uni-datetime-picker/calendar.vue
@@ -0,0 +1,907 @@
+<template>
+	<view class="uni-calendar" @mouseleave="leaveCale">
+		<view v-if="!insert&&show" class="uni-calendar__mask" :class="{'uni-calendar--mask-show':aniMaskShow}"
+			@click="clean"></view>
+		<view v-if="insert || show" class="uni-calendar__content"
+			:class="{'uni-calendar--fixed':!insert,'uni-calendar--ani-show':aniMaskShow, 'uni-calendar__content-mobile': aniMaskShow}">
+			<view class="uni-calendar__header" :class="{'uni-calendar__header-mobile' :!insert}">
+				<view v-if="left" class="uni-calendar__header-btn-box" @click.stop="pre">
+					<view class="uni-calendar__header-btn uni-calendar--left"></view>
+				</view>
+				<picker mode="date" :value="date" fields="month" @change="bindDateChange">
+					<text
+						class="uni-calendar__header-text">{{ (nowDate.year||'') + yearText + ( nowDate.month||'') + monthText}}</text>
+				</picker>
+				<view v-if="right" class="uni-calendar__header-btn-box" @click.stop="next">
+					<view class="uni-calendar__header-btn uni-calendar--right"></view>
+				</view>
+				<view v-if="!insert" class="dialog-close" @click="clean">
+					<view class="dialog-close-plus" data-id="close"></view>
+					<view class="dialog-close-plus dialog-close-rotate" data-id="close"></view>
+				</view>
+
+				<!-- <text class="uni-calendar__backtoday" @click="backtoday">回到今天</text> -->
+			</view>
+			<view class="uni-calendar__box">
+				<view v-if="showMonth" class="uni-calendar__box-bg">
+					<text class="uni-calendar__box-bg-text">{{nowDate.month}}</text>
+				</view>
+				<view class="uni-calendar__weeks" style="padding-bottom: 7px;">
+					<view class="uni-calendar__weeks-day">
+						<text class="uni-calendar__weeks-day-text">{{SUNText}}</text>
+					</view>
+					<view class="uni-calendar__weeks-day">
+						<text class="uni-calendar__weeks-day-text">{{MONText}}</text>
+					</view>
+					<view class="uni-calendar__weeks-day">
+						<text class="uni-calendar__weeks-day-text">{{TUEText}}</text>
+					</view>
+					<view class="uni-calendar__weeks-day">
+						<text class="uni-calendar__weeks-day-text">{{WEDText}}</text>
+					</view>
+					<view class="uni-calendar__weeks-day">
+						<text class="uni-calendar__weeks-day-text">{{THUText}}</text>
+					</view>
+					<view class="uni-calendar__weeks-day">
+						<text class="uni-calendar__weeks-day-text">{{FRIText}}</text>
+					</view>
+					<view class="uni-calendar__weeks-day">
+						<text class="uni-calendar__weeks-day-text">{{SATText}}</text>
+					</view>
+				</view>
+				<view class="uni-calendar__weeks" v-for="(item,weekIndex) in weeks" :key="weekIndex">
+					<view class="uni-calendar__weeks-item" v-for="(weeks,weeksIndex) in item" :key="weeksIndex">
+						<calendar-item class="uni-calendar-item--hook" :weeks="weeks" :calendar="calendar"
+							:selected="selected" :lunar="lunar" :checkHover="range" @change="choiceDate"
+							@handleMouse="handleMouse">
+						</calendar-item>
+					</view>
+				</view>
+			</view>
+			<view v-if="!insert && !range && typeHasTime" class="uni-date-changed uni-calendar--fixed-top"
+				style="padding: 0 80px;">
+				<view class="uni-date-changed--time-date">{{tempSingleDate ? tempSingleDate : selectDateText}}</view>
+				<time-picker type="time" :start="reactStartTime" :end="reactEndTime" v-model="time"
+					:disabled="!tempSingleDate" :border="false" :hide-second="hideSecond" class="time-picker-style">
+				</time-picker>
+			</view>
+
+			<view v-if="!insert && range && typeHasTime" class="uni-date-changed uni-calendar--fixed-top">
+				<view class="uni-date-changed--time-start">
+					<view class="uni-date-changed--time-date">{{tempRange.before ? tempRange.before : startDateText}}
+					</view>
+					<time-picker type="time" :start="reactStartTime" v-model="timeRange.startTime" :border="false"
+						:hide-second="hideSecond" :disabled="!tempRange.before" class="time-picker-style">
+					</time-picker>
+				</view>
+				<uni-icons type="arrowthinright" color="#999" style="line-height: 50px;"></uni-icons>
+				<view class="uni-date-changed--time-end">
+					<view class="uni-date-changed--time-date">{{tempRange.after ? tempRange.after : endDateText}}</view>
+					<time-picker type="time" :end="reactEndTime" v-model="timeRange.endTime" :border="false"
+						:hide-second="hideSecond" :disabled="!tempRange.after" class="time-picker-style">
+					</time-picker>
+				</view>
+			</view>
+			<view v-if="!insert" class="uni-date-changed uni-date-btn--ok">
+				<!-- <view class="uni-calendar__header-btn-box">
+					<text class="uni-calendar__button-text uni-calendar--fixed-width">{{okText}}</text>
+				</view> -->
+				<view class="uni-datetime-picker--btn" @click="confirm">{{confirmText}}</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import Calendar from './util.js';
+	import calendarItem from './calendar-item.vue'
+	import timePicker from './time-picker.vue'
+	import {
+		initVueI18n
+	} from '@dcloudio/uni-i18n'
+	import messages from './i18n/index.js'
+	const {
+		t
+	} = initVueI18n(messages)
+	/**
+	 * Calendar 日历
+	 * @description 日历组件可以查看日期,选择任意范围内的日期,打点操作。常用场景如:酒店日期预订、火车机票选择购买日期、上下班打卡等
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=56
+	 * @property {String} date 自定义当前时间,默认为今天
+	 * @property {Boolean} lunar 显示农历
+	 * @property {String} startDate 日期选择范围-开始日期
+	 * @property {String} endDate 日期选择范围-结束日期
+	 * @property {Boolean} range 范围选择
+	 * @property {Boolean} insert = [true|false] 插入模式,默认为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 是否选择月份为背景
+	 * @event {Function} change 日期改变,`insert :ture` 时生效
+	 * @event {Function} confirm 确认选择`insert :false` 时生效
+	 * @event {Function} monthSwitch 切换月份时触发
+	 * @example <uni-calendar :insert="true":lunar="true" :start-date="'2019-3-2'":end-date="'2019-5-20'"@change="change" />
+	 */
+	export default {
+		components: {
+			calendarItem,
+			timePicker
+		},
+		props: {
+			date: {
+				type: String,
+				default: ''
+			},
+			defTime: {
+				type: [String, Object],
+				default: ''
+			},
+			selectableTimes: {
+				type: [Object],
+				default () {
+					return {}
+				}
+			},
+			selected: {
+				type: Array,
+				default () {
+					return []
+				}
+			},
+			lunar: {
+				type: Boolean,
+				default: false
+			},
+			startDate: {
+				type: String,
+				default: ''
+			},
+			endDate: {
+				type: String,
+				default: ''
+			},
+			range: {
+				type: Boolean,
+				default: false
+			},
+			typeHasTime: {
+				type: Boolean,
+				default: false
+			},
+			insert: {
+				type: Boolean,
+				default: true
+			},
+			showMonth: {
+				type: Boolean,
+				default: true
+			},
+			clearDate: {
+				type: Boolean,
+				default: true
+			},
+			left: {
+				type: Boolean,
+				default: true
+			},
+			right: {
+				type: Boolean,
+				default: true
+			},
+			checkHover: {
+				type: Boolean,
+				default: true
+			},
+			hideSecond: {
+				type: [Boolean],
+				default: false
+			},
+			pleStatus: {
+				type: Object,
+				default () {
+					return {
+						before: '',
+						after: '',
+						data: [],
+						fulldate: ''
+					}
+				}
+			}
+		},
+		data() {
+			return {
+				show: false,
+				weeks: [],
+				calendar: {},
+				nowDate: '',
+				aniMaskShow: false,
+				firstEnter: true,
+				time: '',
+				timeRange: {
+					startTime: '',
+					endTime: ''
+				},
+				tempSingleDate: '',
+				tempRange: {
+					before: '',
+					after: ''
+				}
+			}
+		},
+		watch: {
+			date: {
+				immediate: true,
+				handler(newVal, oldVal) {
+					if (!this.range) {
+						this.tempSingleDate = newVal
+						setTimeout(() => {
+							this.init(newVal)
+						}, 100)
+					}
+				}
+			},
+			defTime: {
+				immediate: true,
+				handler(newVal, oldVal) {
+					if (!this.range) {
+						this.time = newVal
+					} else {
+						// console.log('-----', newVal);
+						this.timeRange.startTime = newVal.start
+						this.timeRange.endTime = newVal.end
+					}
+				}
+			},
+			startDate(val) {
+				this.cale.resetSatrtDate(val)
+				this.cale.setDate(this.nowDate.fullDate)
+				this.weeks = this.cale.weeks
+			},
+			endDate(val) {
+				this.cale.resetEndDate(val)
+				this.cale.setDate(this.nowDate.fullDate)
+				this.weeks = this.cale.weeks
+			},
+			selected(newVal) {
+				this.cale.setSelectInfo(this.nowDate.fullDate, newVal)
+				this.weeks = this.cale.weeks
+			},
+			pleStatus: {
+				immediate: true,
+				handler(newVal, oldVal) {
+					const {
+						before,
+						after,
+						fulldate,
+						which
+					} = newVal
+					this.tempRange.before = before
+					this.tempRange.after = after
+					setTimeout(() => {
+						if (fulldate) {
+							this.cale.setHoverMultiple(fulldate)
+							if (before && after) {
+								this.cale.lastHover = true
+								if (this.rangeWithinMonth(after, before)) return
+								this.setDate(before)
+							} else {
+								this.cale.setMultiple(fulldate)
+								this.setDate(this.nowDate.fullDate)
+								this.calendar.fullDate = ''
+								this.cale.lastHover = false
+							}
+						} else {
+							this.cale.setDefaultMultiple(before, after)
+							if (which === 'left') {
+								this.setDate(before)
+								this.weeks = this.cale.weeks
+							} else {
+								this.setDate(after)
+								this.weeks = this.cale.weeks
+							}
+							this.cale.lastHover = true
+						}
+					}, 16)
+				}
+			}
+		},
+		computed: {
+			reactStartTime() {
+				const activeDate = this.range ? this.tempRange.before : this.calendar.fullDate
+				const res = activeDate === this.startDate ? this.selectableTimes.start : ''
+				return res
+			},
+			reactEndTime() {
+				const activeDate = this.range ? this.tempRange.after : this.calendar.fullDate
+				const res = activeDate === this.endDate ? this.selectableTimes.end : ''
+				return res
+			},
+			/**
+			 * for i18n
+			 */
+			selectDateText() {
+				return t("uni-datetime-picker.selectDate")
+			},
+			startDateText() {
+				return this.startPlaceholder || t("uni-datetime-picker.startDate")
+			},
+			endDateText() {
+				return this.endPlaceholder || t("uni-datetime-picker.endDate")
+			},
+			okText() {
+				return t("uni-datetime-picker.ok")
+			},
+			yearText() {
+				return t("uni-datetime-picker.year")
+			},
+			monthText() {
+				return t("uni-datetime-picker.month")
+			},
+			MONText() {
+				return t("uni-calender.MON")
+			},
+			TUEText() {
+				return t("uni-calender.TUE")
+			},
+			WEDText() {
+				return t("uni-calender.WED")
+			},
+			THUText() {
+				return t("uni-calender.THU")
+			},
+			FRIText() {
+				return t("uni-calender.FRI")
+			},
+			SATText() {
+				return t("uni-calender.SAT")
+			},
+			SUNText() {
+				return t("uni-calender.SUN")
+			},
+			confirmText() {
+				return t("uni-calender.confirm")
+			},
+		},
+		created() {
+			// 获取日历方法实例
+			this.cale = new Calendar({
+				// date: new Date(),
+				selected: this.selected,
+				startDate: this.startDate,
+				endDate: this.endDate,
+				range: this.range,
+				// multipleStatus: this.pleStatus
+			})
+			// 选中某一天
+			// this.cale.setDate(this.date)
+			this.init(this.date)
+			// this.setDay
+		},
+		methods: {
+			leaveCale() {
+				this.firstEnter = true
+			},
+			handleMouse(weeks) {
+				if (weeks.disable) return
+				if (this.cale.lastHover) return
+				let {
+					before,
+					after
+				} = this.cale.multipleStatus
+				if (!before) return
+				this.calendar = weeks
+				// 设置范围选
+				this.cale.setHoverMultiple(this.calendar.fullDate)
+				this.weeks = this.cale.weeks
+				// hover时,进入一个日历,更新另一个
+				if (this.firstEnter) {
+					this.$emit('firstEnterCale', this.cale.multipleStatus)
+					this.firstEnter = false
+				}
+			},
+			rangeWithinMonth(A, B) {
+				const [yearA, monthA] = A.split('-')
+				const [yearB, monthB] = B.split('-')
+				return yearA === yearB && monthA === monthB
+			},
+
+			// 取消穿透
+			clean() {
+				this.close()
+			},
+
+			clearCalender() {
+				if (this.range) {
+					this.timeRange.startTime = ''
+					this.timeRange.endTime = ''
+					this.tempRange.before = ''
+					this.tempRange.after = ''
+					this.cale.multipleStatus.before = ''
+					this.cale.multipleStatus.after = ''
+					this.cale.multipleStatus.data = []
+					this.cale.lastHover = false
+				} else {
+					this.time = ''
+					this.tempSingleDate = ''
+				}
+				this.calendar.fullDate = ''
+				this.setDate()
+			},
+
+			bindDateChange(e) {
+				const value = e.detail.value + '-1'
+				this.init(value)
+			},
+			/**
+			 * 初始化日期显示
+			 * @param {Object} date
+			 */
+			init(date) {
+				this.cale.setDate(date)
+				this.weeks = this.cale.weeks
+				this.nowDate = this.calendar = this.cale.getInfo(date)
+			},
+			// choiceDate(weeks) {
+			// 	if (weeks.disable) return
+			// 	this.calendar = weeks
+			// 	// 设置多选
+			// 	this.cale.setMultiple(this.calendar.fullDate, true)
+			// 	this.weeks = this.cale.weeks
+			// 	this.tempSingleDate = this.calendar.fullDate
+			// 	this.tempRange.before = this.cale.multipleStatus.before
+			// 	this.tempRange.after = this.cale.multipleStatus.after
+			// 	this.change()
+			// },
+			/**
+			 * 打开日历弹窗
+			 */
+			open() {
+				// 弹窗模式并且清理数据
+				if (this.clearDate && !this.insert) {
+					this.cale.cleanMultipleStatus()
+					// this.cale.setDate(this.date)
+					this.init(this.date)
+				}
+				this.show = true
+				this.$nextTick(() => {
+					setTimeout(() => {
+						this.aniMaskShow = true
+					}, 50)
+				})
+			},
+			/**
+			 * 关闭日历弹窗
+			 */
+			close() {
+				this.aniMaskShow = false
+				this.$nextTick(() => {
+					setTimeout(() => {
+						this.show = false
+						this.$emit('close')
+					}, 300)
+				})
+			},
+			/**
+			 * 确认按钮
+			 */
+			confirm() {
+				this.setEmit('confirm')
+				this.close()
+			},
+			/**
+			 * 变化触发
+			 */
+			change() {
+				if (!this.insert) return
+				this.setEmit('change')
+			},
+			/**
+			 * 选择月份触发
+			 */
+			monthSwitch() {
+				let {
+					year,
+					month
+				} = this.nowDate
+				this.$emit('monthSwitch', {
+					year,
+					month: Number(month)
+				})
+			},
+			/**
+			 * 派发事件
+			 * @param {Object} name
+			 */
+			setEmit(name) {
+				let {
+					year,
+					month,
+					date,
+					fullDate,
+					lunar,
+					extraInfo
+				} = this.calendar
+				this.$emit(name, {
+					range: this.cale.multipleStatus,
+					year,
+					month,
+					date,
+					time: this.time,
+					timeRange: this.timeRange,
+					fulldate: fullDate,
+					lunar,
+					extraInfo: extraInfo || {}
+				})
+			},
+			/**
+			 * 选择天触发
+			 * @param {Object} weeks
+			 */
+			choiceDate(weeks) {
+				if (weeks.disable) return
+				this.calendar = weeks
+				this.calendar.userChecked = true
+				// 设置多选
+				this.cale.setMultiple(this.calendar.fullDate, true)
+				this.weeks = this.cale.weeks
+				this.tempSingleDate = this.calendar.fullDate
+				this.tempRange.before = this.cale.multipleStatus.before
+				this.tempRange.after = this.cale.multipleStatus.after
+				this.change()
+			},
+			/**
+			 * 回到今天
+			 */
+			backtoday() {
+				let date = this.cale.getDate(new Date()).fullDate
+				// this.cale.setDate(date)
+				this.init(date)
+				this.change()
+			},
+			/**
+			 * 比较时间大小
+			 */
+			dateCompare(startDate, endDate) {
+				// 计算截止时间
+				startDate = new Date(startDate.replace('-', '/').replace('-', '/'))
+				// 计算详细项的截止时间
+				endDate = new Date(endDate.replace('-', '/').replace('-', '/'))
+				if (startDate <= endDate) {
+					return true
+				} else {
+					return false
+				}
+			},
+			/**
+			 * 上个月
+			 */
+			pre() {
+				const preDate = this.cale.getDate(this.nowDate.fullDate, -1, 'month').fullDate
+				this.setDate(preDate)
+				this.monthSwitch()
+
+			},
+			/**
+			 * 下个月
+			 */
+			next() {
+				const nextDate = this.cale.getDate(this.nowDate.fullDate, +1, 'month').fullDate
+				this.setDate(nextDate)
+				this.monthSwitch()
+			},
+			/**
+			 * 设置日期
+			 * @param {Object} date
+			 */
+			setDate(date) {
+				this.cale.setDate(date)
+				this.weeks = this.cale.weeks
+				this.nowDate = this.cale.getInfo(date)
+			}
+		}
+	}
+</script>
+
+<style lang="scss" >
+	.uni-calendar {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+	}
+
+	.uni-calendar__mask {
+		position: fixed;
+		bottom: 0;
+		top: 0;
+		left: 0;
+		right: 0;
+		background-color: rgba(0, 0, 0, 0.4);
+		transition-property: opacity;
+		transition-duration: 0.3s;
+		opacity: 0;
+		/* #ifndef APP-NVUE */
+		z-index: 99;
+		/* #endif */
+	}
+
+	.uni-calendar--mask-show {
+		opacity: 1
+	}
+
+	.uni-calendar--fixed {
+		position: fixed;
+		bottom: calc(var(--window-bottom));
+		left: 0;
+		right: 0;
+		transition-property: transform;
+		transition-duration: 0.3s;
+		transform: translateY(460px);
+		/* #ifndef APP-NVUE */
+		z-index: 99;
+		/* #endif */
+	}
+
+	.uni-calendar--ani-show {
+		transform: translateY(0);
+	}
+
+	.uni-calendar__content {
+		background-color: #fff;
+	}
+
+	.uni-calendar__content-mobile {
+		border-top-left-radius: 10px;
+		border-top-right-radius: 10px;
+		box-shadow: 0px 0px 5px 3px rgba(0, 0, 0, 0.1);
+	}
+
+	.uni-calendar__header {
+		position: relative;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		justify-content: center;
+		align-items: center;
+		height: 50px;
+	}
+
+	.uni-calendar__header-mobile {
+		padding: 10px;
+		padding-bottom: 0;
+	}
+
+	.uni-calendar--fixed-top {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		justify-content: space-between;
+		border-top-color: rgba(0, 0, 0, 0.4);
+		border-top-style: solid;
+		border-top-width: 1px;
+	}
+
+	.uni-calendar--fixed-width {
+		width: 50px;
+	}
+
+	.uni-calendar__backtoday {
+		position: absolute;
+		right: 0;
+		top: 25rpx;
+		padding: 0 5px;
+		padding-left: 10px;
+		height: 25px;
+		line-height: 25px;
+		font-size: 12px;
+		border-top-left-radius: 25px;
+		border-bottom-left-radius: 25px;
+		color: #fff;
+		background-color: #f1f1f1;
+	}
+
+	.uni-calendar__header-text {
+		text-align: center;
+		width: 100px;
+		font-size: 15px;
+		color: #666;
+	}
+
+	.uni-calendar__button-text {
+		text-align: center;
+		width: 100px;
+		font-size: 14px;
+		color: #007aff;
+		/* #ifndef APP-NVUE */
+		letter-spacing: 3px;
+		/* #endif */
+	}
+
+	.uni-calendar__header-btn-box {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		align-items: center;
+		justify-content: center;
+		width: 50px;
+		height: 50px;
+	}
+
+	.uni-calendar__header-btn {
+		width: 9px;
+		height: 9px;
+		border-left-color: #808080;
+		border-left-style: solid;
+		border-left-width: 1px;
+		border-top-color: #555555;
+		border-top-style: solid;
+		border-top-width: 1px;
+	}
+
+	.uni-calendar--left {
+		transform: rotate(-45deg);
+	}
+
+	.uni-calendar--right {
+		transform: rotate(135deg);
+	}
+
+
+	.uni-calendar__weeks {
+		position: relative;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+	}
+
+	.uni-calendar__weeks-item {
+		flex: 1;
+	}
+
+	.uni-calendar__weeks-day {
+		flex: 1;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		justify-content: center;
+		align-items: center;
+		height: 40px;
+		border-bottom-color: #F5F5F5;
+		border-bottom-style: solid;
+		border-bottom-width: 1px;
+	}
+
+	.uni-calendar__weeks-day-text {
+		font-size: 12px;
+		color: #B2B2B2;
+	}
+
+	.uni-calendar__box {
+		position: relative;
+		// padding: 0 10px;
+		padding-bottom: 7px;
+	}
+
+	.uni-calendar__box-bg {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		justify-content: center;
+		align-items: center;
+		position: absolute;
+		top: 0;
+		left: 0;
+		right: 0;
+		bottom: 0;
+	}
+
+	.uni-calendar__box-bg-text {
+		font-size: 200px;
+		font-weight: bold;
+		color: #999;
+		opacity: 0.1;
+		text-align: center;
+		/* #ifndef APP-NVUE */
+		line-height: 1;
+		/* #endif */
+	}
+
+	.uni-date-changed {
+		padding: 0 10px;
+		// line-height: 50px;
+		text-align: center;
+		color: #333;
+		border-top-color: #DCDCDC;
+		;
+		border-top-style: solid;
+		border-top-width: 1px;
+		flex: 1;
+	}
+
+	.uni-date-btn--ok {
+		padding: 20px 15px;
+	}
+
+	.uni-date-changed--time-start {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		align-items: center;
+	}
+
+	.uni-date-changed--time-end {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		align-items: center;
+	}
+
+	.uni-date-changed--time-date {
+		color: #999;
+		line-height: 50px;
+		margin-right: 5px;
+		// opacity: 0.6;
+	}
+
+	.time-picker-style {
+		// width: 62px;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		justify-content: center;
+		align-items: center
+	}
+
+	.mr-10 {
+		margin-right: 10px;
+	}
+
+	.dialog-close {
+		position: absolute;
+		top: 0;
+		right: 0;
+		bottom: 0;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		align-items: center;
+		padding: 0 25px;
+		margin-top: 10px;
+	}
+
+	.dialog-close-plus {
+		width: 16px;
+		height: 2px;
+		background-color: #737987;
+		border-radius: 2px;
+		transform: rotate(45deg);
+	}
+
+	.dialog-close-rotate {
+		position: absolute;
+		transform: rotate(-45deg);
+	}
+
+	.uni-datetime-picker--btn {
+		border-radius: 100px;
+		height: 40px;
+		line-height: 40px;
+		background-color: #007aff;
+		color: #fff;
+		font-size: 16px;
+		letter-spacing: 2px;
+	}
+
+	/* #ifndef APP-NVUE */
+	.uni-datetime-picker--btn:active {
+		opacity: 0.7;
+	}
+	/* #endif */
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/en.json b/yudao-ui-admin-uniapp/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/en.json
new file mode 100644
index 000000000..9acf1ab0e
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/en.json
@@ -0,0 +1,22 @@
+{
+	"uni-datetime-picker.selectDate": "select date",
+	"uni-datetime-picker.selectTime": "select time",
+	"uni-datetime-picker.selectDateTime": "select datetime",
+	"uni-datetime-picker.startDate": "start date",
+	"uni-datetime-picker.endDate": "end date",
+	"uni-datetime-picker.startTime": "start time",
+	"uni-datetime-picker.endTime": "end time",
+	"uni-datetime-picker.ok": "ok",
+	"uni-datetime-picker.clear": "clear",
+	"uni-datetime-picker.cancel": "cancel",
+	"uni-datetime-picker.year": "-",
+	"uni-datetime-picker.month": "",
+	"uni-calender.MON": "MON",
+	"uni-calender.TUE": "TUE",
+	"uni-calender.WED": "WED",
+	"uni-calender.THU": "THU",
+	"uni-calender.FRI": "FRI",
+	"uni-calender.SAT": "SAT",
+	"uni-calender.SUN": "SUN",
+	"uni-calender.confirm": "confirm"
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/index.js b/yudao-ui-admin-uniapp/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/index.js
new file mode 100644
index 000000000..de7509c87
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/index.js
@@ -0,0 +1,8 @@
+import en from './en.json'
+import zhHans from './zh-Hans.json'
+import zhHant from './zh-Hant.json'
+export default {
+	en,
+	'zh-Hans': zhHans,
+	'zh-Hant': zhHant
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/zh-Hans.json b/yudao-ui-admin-uniapp/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/zh-Hans.json
new file mode 100644
index 000000000..d2df5e722
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/zh-Hans.json
@@ -0,0 +1,22 @@
+{
+	"uni-datetime-picker.selectDate": "选择日期",
+	"uni-datetime-picker.selectTime": "选择时间",
+	"uni-datetime-picker.selectDateTime": "选择日期时间",
+	"uni-datetime-picker.startDate": "开始日期",
+	"uni-datetime-picker.endDate": "结束日期",
+	"uni-datetime-picker.startTime": "开始时间",
+	"uni-datetime-picker.endTime": "结束时间",
+	"uni-datetime-picker.ok": "确定",
+	"uni-datetime-picker.clear": "清除",
+	"uni-datetime-picker.cancel": "取消",
+	"uni-datetime-picker.year": "年",
+	"uni-datetime-picker.month": "月",
+	"uni-calender.SUN": "日",
+	"uni-calender.MON": "一",
+	"uni-calender.TUE": "二",
+	"uni-calender.WED": "三",
+	"uni-calender.THU": "四",
+	"uni-calender.FRI": "五",
+	"uni-calender.SAT": "六",
+	"uni-calender.confirm": "确认"
+}
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/zh-Hant.json b/yudao-ui-admin-uniapp/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/zh-Hant.json
new file mode 100644
index 000000000..d23fa3c39
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-datetime-picker/components/uni-datetime-picker/i18n/zh-Hant.json
@@ -0,0 +1,22 @@
+{
+  "uni-datetime-picker.selectDate": "選擇日期",
+  "uni-datetime-picker.selectTime": "選擇時間",
+  "uni-datetime-picker.selectDateTime": "選擇日期時間",
+  "uni-datetime-picker.startDate": "開始日期",
+  "uni-datetime-picker.endDate": "結束日期",
+  "uni-datetime-picker.startTime": "開始时间",
+  "uni-datetime-picker.endTime": "結束时间",
+  "uni-datetime-picker.ok": "確定",
+  "uni-datetime-picker.clear": "清除",
+  "uni-datetime-picker.cancel": "取消",
+  "uni-datetime-picker.year": "年",
+  "uni-datetime-picker.month": "月",
+  "uni-calender.SUN": "日",
+  "uni-calender.MON": "一",
+  "uni-calender.TUE": "二",
+  "uni-calender.WED": "三",
+  "uni-calender.THU": "四",
+  "uni-calender.FRI": "五",
+  "uni-calender.SAT": "六",
+  "uni-calender.confirm": "確認"
+}
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-datetime-picker/components/uni-datetime-picker/keypress.js b/yudao-ui-admin-uniapp/uni_modules/uni-datetime-picker/components/uni-datetime-picker/keypress.js
new file mode 100644
index 000000000..9601abae3
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-datetime-picker/components/uni-datetime-picker/keypress.js
@@ -0,0 +1,45 @@
+// #ifdef H5
+export default {
+  name: 'Keypress',
+  props: {
+    disable: {
+      type: Boolean,
+      default: false
+    }
+  },
+  mounted () {
+    const keyNames = {
+      esc: ['Esc', 'Escape'],
+      tab: 'Tab',
+      enter: 'Enter',
+      space: [' ', 'Spacebar'],
+      up: ['Up', 'ArrowUp'],
+      left: ['Left', 'ArrowLeft'],
+      right: ['Right', 'ArrowRight'],
+      down: ['Down', 'ArrowDown'],
+      delete: ['Backspace', 'Delete', 'Del']
+    }
+    const listener = ($event) => {
+      if (this.disable) {
+        return
+      }
+      const keyName = Object.keys(keyNames).find(key => {
+        const keyName = $event.key
+        const value = keyNames[key]
+        return value === keyName || (Array.isArray(value) && value.includes(keyName))
+      })
+      if (keyName) {
+        // 避免和其他按键事件冲突
+        setTimeout(() => {
+          this.$emit(keyName, {})
+        }, 0)
+      }
+    }
+    document.addEventListener('keyup', listener)
+    this.$once('hook:beforeDestroy', () => {
+      document.removeEventListener('keyup', listener)
+    })
+  },
+	render: () => {}
+}
+// #endif
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-datetime-picker/components/uni-datetime-picker/time-picker.vue b/yudao-ui-admin-uniapp/uni_modules/uni-datetime-picker/components/uni-datetime-picker/time-picker.vue
new file mode 100644
index 000000000..699aa639f
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-datetime-picker/components/uni-datetime-picker/time-picker.vue
@@ -0,0 +1,927 @@
+<template>
+	<view class="uni-datetime-picker">
+		<view @click="initTimePicker">
+			<slot>
+				<view class="uni-datetime-picker-timebox-pointer"
+					:class="{'uni-datetime-picker-disabled': disabled, 'uni-datetime-picker-timebox': border}">
+					<text class="uni-datetime-picker-text">{{time}}</text>
+					<view v-if="!time" class="uni-datetime-picker-time">
+						<text class="uni-datetime-picker-text">{{selectTimeText}}</text>
+					</view>
+				</view>
+			</slot>
+		</view>
+		<view v-if="visible" id="mask" class="uni-datetime-picker-mask" @click="tiggerTimePicker"></view>
+		<view v-if="visible" class="uni-datetime-picker-popup" :class="[dateShow && timeShow ? '' : 'fix-nvue-height']"
+			:style="fixNvueBug">
+			<view class="uni-title">
+				<text class="uni-datetime-picker-text">{{selectTimeText}}</text>
+			</view>
+			<view v-if="dateShow" class="uni-datetime-picker__container-box">
+				<picker-view class="uni-datetime-picker-view" :indicator-style="indicatorStyle" :value="ymd"
+					@change="bindDateChange">
+					<picker-view-column>
+						<view class="uni-datetime-picker-item" v-for="(item,index) in years" :key="index">
+							<text class="uni-datetime-picker-item">{{lessThanTen(item)}}</text>
+						</view>
+					</picker-view-column>
+					<picker-view-column>
+						<view class="uni-datetime-picker-item" v-for="(item,index) in months" :key="index">
+							<text class="uni-datetime-picker-item">{{lessThanTen(item)}}</text>
+						</view>
+					</picker-view-column>
+					<picker-view-column>
+						<view class="uni-datetime-picker-item" v-for="(item,index) in days" :key="index">
+							<text class="uni-datetime-picker-item">{{lessThanTen(item)}}</text>
+						</view>
+					</picker-view-column>
+				</picker-view>
+				<!-- 兼容 nvue 不支持伪类 -->
+				<text class="uni-datetime-picker-sign sign-left">-</text>
+				<text class="uni-datetime-picker-sign sign-right">-</text>
+			</view>
+			<view v-if="timeShow" class="uni-datetime-picker__container-box">
+				<picker-view class="uni-datetime-picker-view" :class="[hideSecond ? 'time-hide-second' : '']"
+					:indicator-style="indicatorStyle" :value="hms" @change="bindTimeChange">
+					<picker-view-column>
+						<view class="uni-datetime-picker-item" v-for="(item,index) in hours" :key="index">
+							<text class="uni-datetime-picker-item">{{lessThanTen(item)}}</text>
+						</view>
+					</picker-view-column>
+					<picker-view-column>
+						<view class="uni-datetime-picker-item" v-for="(item,index) in minutes" :key="index">
+							<text class="uni-datetime-picker-item">{{lessThanTen(item)}}</text>
+						</view>
+					</picker-view-column>
+					<picker-view-column v-if="!hideSecond">
+						<view class="uni-datetime-picker-item" v-for="(item,index) in seconds" :key="index">
+							<text class="uni-datetime-picker-item">{{lessThanTen(item)}}</text>
+						</view>
+					</picker-view-column>
+				</picker-view>
+				<!-- 兼容 nvue 不支持伪类 -->
+				<text class="uni-datetime-picker-sign" :class="[hideSecond ? 'sign-center' : 'sign-left']">:</text>
+				<text v-if="!hideSecond" class="uni-datetime-picker-sign sign-right">:</text>
+			</view>
+			<view class="uni-datetime-picker-btn">
+				<view @click="clearTime">
+					<text class="uni-datetime-picker-btn-text">{{clearText}}</text>
+				</view>
+				<view class="uni-datetime-picker-btn-group">
+					<view class="uni-datetime-picker-cancel" @click="tiggerTimePicker">
+						<text class="uni-datetime-picker-btn-text">{{cancelText}}</text>
+					</view>
+					<view @click="setTime">
+						<text class="uni-datetime-picker-btn-text">{{okText}}</text>
+					</view>
+				</view>
+			</view>
+		</view>
+		<!-- #ifdef H5 -->
+		<!-- <keypress v-if="visible" @esc="tiggerTimePicker" @enter="setTime" /> -->
+		<!-- #endif -->
+	</view>
+</template>
+
+<script>
+	// #ifdef H5
+	import keypress from './keypress'
+	// #endif
+	import {
+		initVueI18n
+	} from '@dcloudio/uni-i18n'
+	import messages from './i18n/index.js'
+	const {	t	} = initVueI18n(messages)
+
+	/**
+	 * DatetimePicker 时间选择器
+	 * @description 可以同时选择日期和时间的选择器
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=xxx
+	 * @property {String} type = [datetime | date | time] 显示模式
+	 * @property {Boolean} multiple = [true|false] 是否多选
+	 * @property {String|Number} value 默认值
+	 * @property {String|Number} start 起始日期或时间
+	 * @property {String|Number} end 起始日期或时间
+	 * @property {String} return-type = [timestamp | string]
+	 * @event {Function} change  选中发生变化触发
+	 */
+
+	export default {
+		name: 'UniDatetimePicker',
+		components: {
+			// #ifdef H5
+			keypress
+			// #endif
+		},
+		data() {
+			return {
+				indicatorStyle: `height: 50px;`,
+				visible: false,
+				fixNvueBug: {},
+				dateShow: true,
+				timeShow: true,
+				title: '日期和时间',
+				// 输入框当前时间
+				time: '',
+				// 当前的年月日时分秒
+				year: 1920,
+				month: 0,
+				day: 0,
+				hour: 0,
+				minute: 0,
+				second: 0,
+				// 起始时间
+				startYear: 1920,
+				startMonth: 1,
+				startDay: 1,
+				startHour: 0,
+				startMinute: 0,
+				startSecond: 0,
+				// 结束时间
+				endYear: 2120,
+				endMonth: 12,
+				endDay: 31,
+				endHour: 23,
+				endMinute: 59,
+				endSecond: 59,
+			}
+		},
+		props: {
+			type: {
+				type: String,
+				default: 'datetime'
+			},
+			value: {
+				type: [String, Number],
+				default: ''
+			},
+			modelValue: {
+				type: [String, Number],
+				default: ''
+			},
+			start: {
+				type: [Number, String],
+				default: ''
+			},
+			end: {
+				type: [Number, String],
+				default: ''
+			},
+			returnType: {
+				type: String,
+				default: 'string'
+			},
+			disabled: {
+				type: [Boolean, String],
+				default: false
+			},
+			border: {
+				type: [Boolean, String],
+				default: true
+			},
+			hideSecond: {
+				type: [Boolean, String],
+				default: false
+			}
+		},
+		watch: {
+			value: {
+				handler(newVal, oldVal) {
+					if (newVal) {
+						this.parseValue(this.fixIosDateFormat(newVal)) //兼容 iOS、safari 日期格式
+						this.initTime(false)
+					} else {
+						this.time = ''
+						this.parseValue(Date.now())
+					}
+				},
+				immediate: true
+			},
+			type: {
+				handler(newValue) {
+					if (newValue === 'date') {
+						this.dateShow = true
+						this.timeShow = false
+						this.title = '日期'
+					} else if (newValue === 'time') {
+						this.dateShow = false
+						this.timeShow = true
+						this.title = '时间'
+					} else {
+						this.dateShow = true
+						this.timeShow = true
+						this.title = '日期和时间'
+					}
+				},
+				immediate: true
+			},
+			start: {
+				handler(newVal) {
+					this.parseDatetimeRange(this.fixIosDateFormat(newVal), 'start') //兼容 iOS、safari 日期格式
+				},
+				immediate: true
+			},
+			end: {
+				handler(newVal) {
+					this.parseDatetimeRange(this.fixIosDateFormat(newVal), 'end') //兼容 iOS、safari 日期格式
+				},
+				immediate: true
+			},
+
+			// 月、日、时、分、秒可选范围变化后,检查当前值是否在范围内,不在则当前值重置为可选范围第一项
+			months(newVal) {
+				this.checkValue('month', this.month, newVal)
+			},
+			days(newVal) {
+				this.checkValue('day', this.day, newVal)
+			},
+			hours(newVal) {
+				this.checkValue('hour', this.hour, newVal)
+			},
+			minutes(newVal) {
+				this.checkValue('minute', this.minute, newVal)
+			},
+			seconds(newVal) {
+				this.checkValue('second', this.second, newVal)
+			}
+		},
+		computed: {
+			// 当前年、月、日、时、分、秒选择范围
+			years() {
+				return this.getCurrentRange('year')
+			},
+
+			months() {
+				return this.getCurrentRange('month')
+			},
+
+			days() {
+				return this.getCurrentRange('day')
+			},
+
+			hours() {
+				return this.getCurrentRange('hour')
+			},
+
+			minutes() {
+				return this.getCurrentRange('minute')
+			},
+
+			seconds() {
+				return this.getCurrentRange('second')
+			},
+
+			// picker 当前值数组
+			ymd() {
+				return [this.year - this.minYear, this.month - this.minMonth, this.day - this.minDay]
+			},
+			hms() {
+				return [this.hour - this.minHour, this.minute - this.minMinute, this.second - this.minSecond]
+			},
+
+			// 当前 date 是 start
+			currentDateIsStart() {
+				return this.year === this.startYear && this.month === this.startMonth && this.day === this.startDay
+			},
+
+			// 当前 date 是 end
+			currentDateIsEnd() {
+				return this.year === this.endYear && this.month === this.endMonth && this.day === this.endDay
+			},
+
+			// 当前年、月、日、时、分、秒的最小值和最大值
+			minYear() {
+				return this.startYear
+			},
+			maxYear() {
+				return this.endYear
+			},
+			minMonth() {
+				if (this.year === this.startYear) {
+					return this.startMonth
+				} else {
+					return 1
+				}
+			},
+			maxMonth() {
+				if (this.year === this.endYear) {
+					return this.endMonth
+				} else {
+					return 12
+				}
+			},
+			minDay() {
+				if (this.year === this.startYear && this.month === this.startMonth) {
+					return this.startDay
+				} else {
+					return 1
+				}
+			},
+			maxDay() {
+				if (this.year === this.endYear && this.month === this.endMonth) {
+					return this.endDay
+				} else {
+					return this.daysInMonth(this.year, this.month)
+				}
+			},
+			minHour() {
+				if (this.type === 'datetime') {
+					if (this.currentDateIsStart) {
+						return this.startHour
+					} else {
+						return 0
+					}
+				}
+				if (this.type === 'time') {
+					return this.startHour
+				}
+			},
+			maxHour() {
+				if (this.type === 'datetime') {
+					if (this.currentDateIsEnd) {
+						return this.endHour
+					} else {
+						return 23
+					}
+				}
+				if (this.type === 'time') {
+					return this.endHour
+				}
+			},
+			minMinute() {
+				if (this.type === 'datetime') {
+					if (this.currentDateIsStart && this.hour === this.startHour) {
+						return this.startMinute
+					} else {
+						return 0
+					}
+				}
+				if (this.type === 'time') {
+					if (this.hour === this.startHour) {
+						return this.startMinute
+					} else {
+						return 0
+					}
+				}
+			},
+			maxMinute() {
+				if (this.type === 'datetime') {
+					if (this.currentDateIsEnd && this.hour === this.endHour) {
+						return this.endMinute
+					} else {
+						return 59
+					}
+				}
+				if (this.type === 'time') {
+					if (this.hour === this.endHour) {
+						return this.endMinute
+					} else {
+						return 59
+					}
+				}
+			},
+			minSecond() {
+				if (this.type === 'datetime') {
+					if (this.currentDateIsStart && this.hour === this.startHour && this.minute === this.startMinute) {
+						return this.startSecond
+					} else {
+						return 0
+					}
+				}
+				if (this.type === 'time') {
+					if (this.hour === this.startHour && this.minute === this.startMinute) {
+						return this.startSecond
+					} else {
+						return 0
+					}
+				}
+			},
+			maxSecond() {
+				if (this.type === 'datetime') {
+					if (this.currentDateIsEnd && this.hour === this.endHour && this.minute === this.endMinute) {
+						return this.endSecond
+					} else {
+						return 59
+					}
+				}
+				if (this.type === 'time') {
+					if (this.hour === this.endHour && this.minute === this.endMinute) {
+						return this.endSecond
+					} else {
+						return 59
+					}
+				}
+			},
+
+			/**
+			 * for i18n
+			 */
+			selectTimeText() {
+				return t("uni-datetime-picker.selectTime")
+			},
+			okText() {
+				return t("uni-datetime-picker.ok")
+			},
+			clearText() {
+				return t("uni-datetime-picker.clear")
+			},
+			cancelText() {
+				return t("uni-datetime-picker.cancel")
+			}
+		},
+
+		mounted() {
+			// #ifdef APP-NVUE
+			const res = uni.getSystemInfoSync();
+			this.fixNvueBug = {
+				top: res.windowHeight / 2,
+				left: res.windowWidth / 2
+			}
+			// #endif
+		},
+
+		methods: {
+			/**
+			 * @param {Object} item
+			 * 小于 10 在前面加个 0
+			 */
+
+			lessThanTen(item) {
+				return item < 10 ? '0' + item : item
+			},
+
+			/**
+			 * 解析时分秒字符串,例如:00:00:00
+			 * @param {String} timeString
+			 */
+			parseTimeType(timeString) {
+				if (timeString) {
+					let timeArr = timeString.split(':')
+					this.hour = Number(timeArr[0])
+					this.minute = Number(timeArr[1])
+					this.second = Number(timeArr[2])
+				}
+			},
+
+			/**
+			 * 解析选择器初始值,类型可以是字符串、时间戳,例如:2000-10-02、'08:30:00'、 1610695109000
+			 * @param {String | Number} datetime
+			 */
+			initPickerValue(datetime) {
+				let defaultValue = null
+				if (datetime) {
+					defaultValue = this.compareValueWithStartAndEnd(datetime, this.start, this.end)
+				} else {
+					defaultValue = Date.now()
+					defaultValue = this.compareValueWithStartAndEnd(defaultValue, this.start, this.end)
+				}
+				this.parseValue(defaultValue)
+			},
+
+			/**
+			 * 初始值规则:
+			 * - 用户设置初始值 value
+			 * 	- 设置了起始时间 start、终止时间 end,并 start < value < end,初始值为 value, 否则初始值为 start
+			 * 	- 只设置了起始时间 start,并 start < value,初始值为 value,否则初始值为 start
+			 * 	- 只设置了终止时间 end,并 value < end,初始值为 value,否则初始值为 end
+			 * 	- 无起始终止时间,则初始值为 value
+			 * - 无初始值 value,则初始值为当前本地时间 Date.now()
+			 * @param {Object} value
+			 * @param {Object} dateBase
+			 */
+			compareValueWithStartAndEnd(value, start, end) {
+				let winner = null
+				value = this.superTimeStamp(value)
+				start = this.superTimeStamp(start)
+				end = this.superTimeStamp(end)
+
+				if (start && end) {
+					if (value < start) {
+						winner = new Date(start)
+					} else if (value > end) {
+						winner = new Date(end)
+					} else {
+						winner = new Date(value)
+					}
+				} else if (start && !end) {
+					winner = start <= value ? new Date(value) : new Date(start)
+				} else if (!start && end) {
+					winner = value <= end ? new Date(value) : new Date(end)
+				} else {
+					winner = new Date(value)
+				}
+
+				return winner
+			},
+
+			/**
+			 * 转换为可比较的时间戳,接受日期、时分秒、时间戳
+			 * @param {Object} value
+			 */
+			superTimeStamp(value) {
+				let dateBase = ''
+				if (this.type === 'time' && value && typeof value === 'string') {
+					const now = new Date()
+					const year = now.getFullYear()
+					const month = now.getMonth() + 1
+					const day = now.getDate()
+					dateBase = year + '/' + month + '/' + day + ' '
+				}
+				if (Number(value) && typeof value !== NaN) {
+					value = parseInt(value)
+					dateBase = 0
+				}
+				return this.createTimeStamp(dateBase + value)
+			},
+
+			/**
+			 * 解析默认值 value,字符串、时间戳
+			 * @param {Object} defaultTime
+			 */
+			parseValue(value) {
+				if (!value) {
+					return
+				}
+				if (this.type === 'time' && typeof value === "string") {
+					this.parseTimeType(value)
+				} else {
+					let defaultDate = null
+					defaultDate = new Date(value)
+					if (this.type !== 'time') {
+						this.year = defaultDate.getFullYear()
+						this.month = defaultDate.getMonth() + 1
+						this.day = defaultDate.getDate()
+					}
+					if (this.type !== 'date') {
+						this.hour = defaultDate.getHours()
+						this.minute = defaultDate.getMinutes()
+						this.second = defaultDate.getSeconds()
+					}
+				}
+				if (this.hideSecond) {
+					this.second = 0
+				}
+			},
+
+			/**
+			 * 解析可选择时间范围 start、end,年月日字符串、时间戳
+			 * @param {Object} defaultTime
+			 */
+			parseDatetimeRange(point, pointType) {
+				// 时间为空,则重置为初始值
+				if (!point) {
+					if (pointType === 'start') {
+						this.startYear = 1920
+						this.startMonth = 1
+						this.startDay = 1
+						this.startHour = 0
+						this.startMinute = 0
+						this.startSecond = 0
+					}
+					if (pointType === 'end') {
+						this.endYear = 2120
+						this.endMonth = 12
+						this.endDay = 31
+						this.endHour = 23
+						this.endMinute = 59
+						this.endSecond = 59
+					}
+					return
+				}
+				if (this.type === 'time') {
+					const pointArr = point.split(':')
+					this[pointType + 'Hour'] = Number(pointArr[0])
+					this[pointType + 'Minute'] = Number(pointArr[1])
+					this[pointType + 'Second'] = Number(pointArr[2])
+				} else {
+					if (!point) {
+						pointType === 'start' ? this.startYear = this.year - 60 : this.endYear = this.year + 60
+						return
+					}
+					if (Number(point) && Number(point) !== NaN) {
+						point = parseInt(point)
+					}
+					// datetime 的 end 没有时分秒, 则不限制
+					const hasTime = /[0-9]:[0-9]/
+					if (this.type === 'datetime' && pointType === 'end' && typeof point === 'string' && !hasTime.test(
+							point)) {
+						point = point + ' 23:59:59'
+					}
+					const pointDate = new Date(point)
+					this[pointType + 'Year'] = pointDate.getFullYear()
+					this[pointType + 'Month'] = pointDate.getMonth() + 1
+					this[pointType + 'Day'] = pointDate.getDate()
+					if (this.type === 'datetime') {
+						this[pointType + 'Hour'] = pointDate.getHours()
+						this[pointType + 'Minute'] = pointDate.getMinutes()
+						this[pointType + 'Second'] = pointDate.getSeconds()
+					}
+				}
+			},
+
+			// 获取 年、月、日、时、分、秒 当前可选范围
+			getCurrentRange(value) {
+				const range = []
+				for (let i = this['min' + this.capitalize(value)]; i <= this['max' + this.capitalize(value)]; i++) {
+					range.push(i)
+				}
+				return range
+			},
+
+			// 字符串首字母大写
+			capitalize(str) {
+				return str.charAt(0).toUpperCase() + str.slice(1)
+			},
+
+			// 检查当前值是否在范围内,不在则当前值重置为可选范围第一项
+			checkValue(name, value, values) {
+				if (values.indexOf(value) === -1) {
+					this[name] = values[0]
+				}
+			},
+
+			// 每个月的实际天数
+			daysInMonth(year, month) { // Use 1 for January, 2 for February, etc.
+				return new Date(year, month, 0).getDate();
+			},
+
+			//兼容 iOS、safari 日期格式
+			fixIosDateFormat(value) {
+				if (typeof value === 'string') {
+					value = value.replace(/-/g, '/')
+				}
+				return value
+			},
+
+			/**
+			 * 生成时间戳
+			 * @param {Object} time
+			 */
+			createTimeStamp(time) {
+				if (!time) return
+				if (typeof time === "number") {
+					return time
+				} else {
+					time = time.replace(/-/g, '/')
+					if (this.type === 'date') {
+						time = time + ' ' + '00:00:00'
+					}
+					return Date.parse(time)
+				}
+			},
+
+			/**
+			 * 生成日期或时间的字符串
+			 */
+			createDomSting() {
+				const yymmdd = this.year +
+					'-' +
+					this.lessThanTen(this.month) +
+					'-' +
+					this.lessThanTen(this.day)
+
+				let hhmmss = this.lessThanTen(this.hour) +
+					':' +
+					this.lessThanTen(this.minute)
+
+				if (!this.hideSecond) {
+					hhmmss = hhmmss + ':' + this.lessThanTen(this.second)
+				}
+
+				if (this.type === 'date') {
+					return yymmdd
+				} else if (this.type === 'time') {
+					return hhmmss
+				} else {
+					return yymmdd + ' ' + hhmmss
+				}
+			},
+
+			/**
+			 * 初始化返回值,并抛出 change 事件
+			 */
+			initTime(emit = true) {
+				this.time = this.createDomSting()
+				if (!emit) return
+				if (this.returnType === 'timestamp' && this.type !== 'time') {
+					this.$emit('change', this.createTimeStamp(this.time))
+					this.$emit('input', this.createTimeStamp(this.time))
+					this.$emit('update:modelValue', this.createTimeStamp(this.time))
+				} else {
+					this.$emit('change', this.time)
+					this.$emit('input', this.time)
+					this.$emit('update:modelValue', this.time)
+				}
+			},
+
+			/**
+			 * 用户选择日期或时间更新 data
+			 * @param {Object} e
+			 */
+			bindDateChange(e) {
+				const val = e.detail.value
+				this.year = this.years[val[0]]
+				this.month = this.months[val[1]]
+				this.day = this.days[val[2]]
+			},
+			bindTimeChange(e) {
+				const val = e.detail.value
+				this.hour = this.hours[val[0]]
+				this.minute = this.minutes[val[1]]
+				this.second = this.seconds[val[2]]
+			},
+
+			/**
+			 * 初始化弹出层
+			 */
+			initTimePicker() {
+				if (this.disabled) return
+				const value = this.fixIosDateFormat(this.value)
+				this.initPickerValue(value)
+				this.visible = !this.visible
+			},
+
+			/**
+			 * 触发或关闭弹框
+			 */
+			tiggerTimePicker(e) {
+				this.visible = !this.visible
+			},
+
+			/**
+			 * 用户点击“清空”按钮,清空当前值
+			 */
+			clearTime() {
+				this.time = ''
+				this.$emit('change', this.time)
+				this.$emit('input', this.time)
+				this.$emit('update:modelValue', this.time)
+				this.tiggerTimePicker()
+			},
+
+			/**
+			 * 用户点击“确定”按钮
+			 */
+			setTime() {
+				this.initTime()
+				this.tiggerTimePicker()
+			}
+		}
+	}
+</script>
+
+<style>
+	.uni-datetime-picker {
+		/* #ifndef APP-NVUE */
+		/* width: 100%; */
+		/* #endif */
+	}
+
+	.uni-datetime-picker-view {
+		height: 130px;
+		width: 270px;
+		/* #ifndef APP-NVUE */
+		cursor: pointer;
+		/* #endif */
+	}
+
+	.uni-datetime-picker-item {
+		height: 50px;
+		line-height: 50px;
+		text-align: center;
+		font-size: 14px;
+	}
+
+	.uni-datetime-picker-btn {
+		margin-top: 60px;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		cursor: pointer;
+		/* #endif */
+		flex-direction: row;
+		justify-content: space-between;
+	}
+
+	.uni-datetime-picker-btn-text {
+		font-size: 14px;
+		color: #007AFF;
+	}
+
+	.uni-datetime-picker-btn-group {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+	}
+
+	.uni-datetime-picker-cancel {
+		margin-right: 30px;
+	}
+
+	.uni-datetime-picker-mask {
+		position: fixed;
+		bottom: 0px;
+		top: 0px;
+		left: 0px;
+		right: 0px;
+		background-color: rgba(0, 0, 0, 0.4);
+		transition-duration: 0.3s;
+		z-index: 998;
+	}
+
+	.uni-datetime-picker-popup {
+		border-radius: 8px;
+		padding: 30px;
+		width: 270px;
+		/* #ifdef APP-NVUE */
+		height: 500px;
+		/* #endif */
+		/* #ifdef APP-NVUE */
+		width: 330px;
+		/* #endif */
+		background-color: #fff;
+		position: fixed;
+		top: 50%;
+		left: 50%;
+		transform: translate(-50%, -50%);
+		transition-duration: 0.3s;
+		z-index: 999;
+	}
+
+	.fix-nvue-height {
+		/* #ifdef APP-NVUE */
+		height: 330px;
+		/* #endif */
+	}
+
+	.uni-datetime-picker-time {
+		color: grey;
+	}
+
+	.uni-datetime-picker-column {
+		height: 50px;
+	}
+
+	.uni-datetime-picker-timebox {
+
+		border: 1px solid #E5E5E5;
+		border-radius: 5px;
+		padding: 7px 10px;
+		/* #ifndef APP-NVUE */
+		box-sizing: border-box;
+		cursor: pointer;
+		/* #endif */
+	}
+
+	.uni-datetime-picker-timebox-pointer {
+		/* #ifndef APP-NVUE */
+		cursor: pointer;
+		/* #endif */
+	}
+
+
+	.uni-datetime-picker-disabled {
+		opacity: 0.4;
+		/* #ifdef H5 */
+		cursor: not-allowed !important;
+		/* #endif */
+	}
+
+	.uni-datetime-picker-text {
+		font-size: 14px;
+	}
+
+	.uni-datetime-picker-sign {
+		position: absolute;
+		top: 53px;
+		/* 减掉 10px 的元素高度,兼容nvue */
+		color: #999;
+		/* #ifdef APP-NVUE */
+		font-size: 16px;
+		/* #endif */
+	}
+
+	.sign-left {
+		left: 86px;
+	}
+
+	.sign-right {
+		right: 86px;
+	}
+
+	.sign-center {
+		left: 135px;
+	}
+
+	.uni-datetime-picker__container-box {
+		position: relative;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		margin-top: 40px;
+	}
+
+	.time-hide-second {
+		width: 180px;
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue b/yudao-ui-admin-uniapp/uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue
new file mode 100644
index 000000000..9bdf8bca8
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue
@@ -0,0 +1,1012 @@
+<template>
+	<view class="uni-date">
+		<view class="uni-date-editor" @click="show">
+			<slot>
+				<view class="uni-date-editor--x" :class="{'uni-date-editor--x__disabled': disabled,
+		'uni-date-x--border': border}">
+					<view v-if="!isRange" class="uni-date-x uni-date-single">
+						<uni-icons type="calendar" color="#c0c4cc" size="22"></uni-icons>
+						<input class="uni-date__x-input" type="text" v-model="singleVal"
+							:placeholder="singlePlaceholderText" :disabled="true" />
+					</view>
+					<view v-else class="uni-date-x uni-date-range">
+						<uni-icons type="calendar" color="#c0c4cc" size="22"></uni-icons>
+						<input class="uni-date__x-input t-c" type="text" v-model="range.startDate"
+							:placeholder="startPlaceholderText" :disabled="true" />
+						<slot>
+							<view class="">{{rangeSeparator}}</view>
+						</slot>
+						<input class="uni-date__x-input t-c" type="text" v-model="range.endDate"
+							:placeholder="endPlaceholderText" :disabled="true" />
+					</view>
+					<view v-if="showClearIcon" class="uni-date__icon-clear" @click.stop="clear">
+						<uni-icons type="clear" color="#c0c4cc" size="24"></uni-icons>
+					</view>
+				</view>
+			</slot>
+		</view>
+
+		<view v-show="popup" class="uni-date-mask" @click="close"></view>
+		<view v-if="!isPhone" ref="datePicker" v-show="popup" class="uni-date-picker__container">
+			<view v-if="!isRange" class="uni-date-single--x" :style="popover">
+				<view class="uni-popper__arrow"></view>
+				<view v-if="hasTime" class="uni-date-changed popup-x-header">
+					<input class="uni-date__input t-c" type="text" v-model="tempSingleDate"
+						:placeholder="selectDateText" />
+					<time-picker type="time" v-model="time" :border="false" :disabled="!tempSingleDate"
+						:start="reactStartTime" :end="reactEndTime" :hideSecond="hideSecond" style="width: 100%;">
+						<input class="uni-date__input t-c" type="text" v-model="time" :placeholder="selectTimeText"
+							:disabled="!tempSingleDate" />
+					</time-picker>
+				</view>
+				<calendar ref="pcSingle" :showMonth="false" :start-date="caleRange.startDate"
+					:end-date="caleRange.endDate" :date="defSingleDate" @change="singleChange"
+					style="padding: 0 8px;" />
+				<view v-if="hasTime" class="popup-x-footer">
+					<!-- <text class="">此刻</text> -->
+					<text class="confirm" @click="confirmSingleChange">{{okText}}</text>
+				</view>
+				<view class="uni-date-popper__arrow"></view>
+			</view>
+
+			<view v-else class="uni-date-range--x" :style="popover">
+				<view class="uni-popper__arrow"></view>
+				<view v-if="hasTime" class="popup-x-header uni-date-changed">
+					<view class="popup-x-header--datetime">
+						<input class="uni-date__input uni-date-range__input" type="text" v-model="tempRange.startDate"
+							:placeholder="startDateText" />
+						<time-picker type="time" v-model="tempRange.startTime" :start="reactStartTime" :border="false"
+							:disabled="!tempRange.startDate" :hideSecond="hideSecond">
+							<input class="uni-date__input uni-date-range__input" type="text"
+								v-model="tempRange.startTime" :placeholder="startTimeText"
+								:disabled="!tempRange.startDate" />
+						</time-picker>
+					</view>
+					<uni-icons type="arrowthinright" color="#999" style="line-height: 40px;"></uni-icons>
+					<view class="popup-x-header--datetime">
+						<input class="uni-date__input uni-date-range__input" type="text" v-model="tempRange.endDate"
+							:placeholder="endDateText" />
+						<time-picker type="time" v-model="tempRange.endTime" :end="reactEndTime" :border="false"
+							:disabled="!tempRange.endDate" :hideSecond="hideSecond">
+							<input class="uni-date__input uni-date-range__input" type="text" v-model="tempRange.endTime"
+								:placeholder="endTimeText" :disabled="!tempRange.endDate" />
+						</time-picker>
+					</view>
+				</view>
+				<view class="popup-x-body">
+					<calendar ref="left" :showMonth="false" :start-date="caleRange.startDate"
+						:end-date="caleRange.endDate" :range="true" @change="leftChange" :pleStatus="endMultipleStatus"
+						@firstEnterCale="updateRightCale" @monthSwitch="leftMonthSwitch" style="padding: 0 8px;" />
+					<calendar ref="right" :showMonth="false" :start-date="caleRange.startDate"
+						:end-date="caleRange.endDate" :range="true" @change="rightChange"
+						:pleStatus="startMultipleStatus" @firstEnterCale="updateLeftCale"
+						@monthSwitch="rightMonthSwitch" style="padding: 0 8px;border-left: 1px solid #F1F1F1;" />
+				</view>
+				<view v-if="hasTime" class="popup-x-footer">
+					<text class="" @click="clear">{{clearText}}</text>
+					<text class="confirm" @click="confirmRangeChange">{{okText}}</text>
+				</view>
+			</view>
+		</view>
+		<calendar v-show="isPhone" ref="mobile" :clearDate="false" :date="defSingleDate" :defTime="reactMobDefTime"
+			:start-date="caleRange.startDate" :end-date="caleRange.endDate" :selectableTimes="mobSelectableTime"
+			:pleStatus="endMultipleStatus" :showMonth="false" :range="isRange" :typeHasTime="hasTime" :insert="false"
+			:hideSecond="hideSecond" @confirm="mobileChange" />
+	</view>
+</template>
+<script>
+	/**
+	 * DatetimePicker 时间选择器
+	 * @description 同时支持 PC 和移动端使用日历选择日期和日期范围
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=3962
+	 * @property {String} type 选择器类型
+	 * @property {String|Number|Array|Date} value 绑定值
+	 * @property {String} placeholder 单选择时的占位内容
+	 * @property {String} start 起始时间
+	 * @property {String} end 终止时间
+	 * @property {String} start-placeholder 范围选择时开始日期的占位内容
+	 * @property {String} end-placeholder 范围选择时结束日期的占位内容
+	 * @property {String} range-separator 选择范围时的分隔符
+	 * @property {Boolean} border = [true|false] 是否有边框
+	 * @property {Boolean} disabled = [true|false] 是否禁用
+	 * @property {Boolean} clearIcon = [true|false] 是否显示清除按钮(仅PC端适用)
+	 * @event {Function} change 确定日期时触发的事件
+	 * @event {Function} show 打开弹出层
+	 * @event {Function} close 关闭弹出层
+	 * @event {Function} clear 清除上次选中的状态和值
+	 **/
+	import calendar from './calendar.vue'
+	import timePicker from './time-picker.vue'
+	import {
+		initVueI18n
+	} from '@dcloudio/uni-i18n'
+	import messages from './i18n/index.js'
+	const {
+		t
+	} = initVueI18n(messages)
+
+	export default {
+		name: 'UniDatetimePicker',
+		options: {
+			virtualHost: true
+		},
+		components: {
+			calendar,
+			timePicker
+		},
+		inject: {
+			form: {
+				from: 'uniForm',
+				default: null
+			},
+			formItem: {
+				from: 'uniFormItem',
+				default: null
+			},
+		},
+		data() {
+			return {
+				isRange: false,
+				hasTime: false,
+				mobileRange: false,
+				// 单选
+				singleVal: '',
+				tempSingleDate: '',
+				defSingleDate: '',
+				time: '',
+				// 范围选
+				caleRange: {
+					startDate: '',
+					startTime: '',
+					endDate: '',
+					endTime: ''
+				},
+				range: {
+					startDate: '',
+					// startTime: '',
+					endDate: '',
+					// endTime: ''
+				},
+				tempRange: {
+					startDate: '',
+					startTime: '',
+					endDate: '',
+					endTime: ''
+				},
+				// 左右日历同步数据
+				startMultipleStatus: {
+					before: '',
+					after: '',
+					data: [],
+					fulldate: ''
+				},
+				endMultipleStatus: {
+					before: '',
+					after: '',
+					data: [],
+					fulldate: ''
+				},
+				visible: false,
+				popup: false,
+				popover: null,
+				isEmitValue: false,
+				isPhone: false,
+				isFirstShow: true,
+			}
+		},
+		props: {
+			type: {
+				type: String,
+				default: 'datetime'
+			},
+			value: {
+				type: [String, Number, Array, Date],
+				default: ''
+			},
+			modelValue: {
+				type: [String, Number, Array, Date],
+				default: ''
+			},
+			start: {
+				type: [Number, String],
+				default: ''
+			},
+			end: {
+				type: [Number, String],
+				default: ''
+			},
+			returnType: {
+				type: String,
+				default: 'string'
+			},
+			placeholder: {
+				type: String,
+				default: ''
+			},
+			startPlaceholder: {
+				type: String,
+				default: ''
+			},
+			endPlaceholder: {
+				type: String,
+				default: ''
+			},
+			rangeSeparator: {
+				type: String,
+				default: '-'
+			},
+			border: {
+				type: [Boolean],
+				default: true
+			},
+			disabled: {
+				type: [Boolean],
+				default: false
+			},
+			clearIcon: {
+				type: [Boolean],
+				default: true
+			},
+			hideSecond: {
+				type: [Boolean],
+				default: false
+			}
+		},
+		watch: {
+			type: {
+				immediate: true,
+				handler(newVal, oldVal) {
+					if (newVal.indexOf('time') !== -1) {
+						this.hasTime = true
+					} else {
+						this.hasTime = false
+					}
+					if (newVal.indexOf('range') !== -1) {
+						this.isRange = true
+					} else {
+						this.isRange = false
+					}
+				}
+			},
+			// #ifndef VUE3
+			value: {
+				immediate: true,
+				handler(newVal, oldVal) {
+					if (this.isEmitValue) {
+						this.isEmitValue = false
+						return
+					}
+					this.initPicker(newVal)
+				}
+			},
+			// #endif
+			// #ifdef VUE3
+			modelValue: {
+				immediate: true,
+				handler(newVal, oldVal) {
+					if (this.isEmitValue) {
+						this.isEmitValue = false
+						return
+					}
+					this.initPicker(newVal)
+				}
+			},
+			// #endif
+			start: {
+				immediate: true,
+				handler(newVal, oldVal) {
+					if (!newVal) return
+					const {
+						defDate,
+						defTime
+					} = this.parseDate(newVal)
+					this.caleRange.startDate = defDate
+					if (this.hasTime) {
+						this.caleRange.startTime = defTime
+					}
+				}
+			},
+			end: {
+				immediate: true,
+				handler(newVal, oldVal) {
+					if (!newVal) return
+					const {
+						defDate,
+						defTime
+					} = this.parseDate(newVal)
+					this.caleRange.endDate = defDate
+					if (this.hasTime) {
+						this.caleRange.endTime = defTime
+					}
+				}
+			},
+		},
+		computed: {
+			reactStartTime() {
+				const activeDate = this.isRange ? this.tempRange.startDate : this.tempSingleDate
+				const res = activeDate === this.caleRange.startDate ? this.caleRange.startTime : ''
+				return res
+			},
+			reactEndTime() {
+				const activeDate = this.isRange ? this.tempRange.endDate : this.tempSingleDate
+				const res = activeDate === this.caleRange.endDate ? this.caleRange.endTime : ''
+				return res
+			},
+			reactMobDefTime() {
+				const times = {
+					start: this.tempRange.startTime,
+					end: this.tempRange.endTime
+				}
+				return this.isRange ? times : this.time
+			},
+			mobSelectableTime() {
+				return {
+					start: this.caleRange.startTime,
+					end: this.caleRange.endTime
+				}
+			},
+			datePopupWidth() {
+				// todo
+				return this.isRange ? 653 : 301
+			},
+
+			/**
+			 * for i18n
+			 */
+			singlePlaceholderText() {
+				return this.placeholder || (this.type === 'date' ? this.selectDateText : t(
+					"uni-datetime-picker.selectDateTime"))
+			},
+			startPlaceholderText() {
+				return this.startPlaceholder || this.startDateText
+			},
+			endPlaceholderText() {
+				return this.endPlaceholder || this.endDateText
+			},
+			selectDateText() {
+				return t("uni-datetime-picker.selectDate")
+			},
+			selectTimeText() {
+				return t("uni-datetime-picker.selectTime")
+			},
+			startDateText() {
+				return this.startPlaceholder || t("uni-datetime-picker.startDate")
+			},
+			startTimeText() {
+				return t("uni-datetime-picker.startTime")
+			},
+			endDateText() {
+				return this.endPlaceholder || t("uni-datetime-picker.endDate")
+			},
+			endTimeText() {
+				return t("uni-datetime-picker.endTime")
+			},
+			okText() {
+				return t("uni-datetime-picker.ok")
+			},
+			clearText() {
+				return t("uni-datetime-picker.clear")
+			},
+			showClearIcon() {
+				const {
+					clearIcon,
+					disabled,
+					singleVal,
+					range
+				} = this
+				const bool = clearIcon && !disabled && (singleVal || (range.startDate && range.endDate))
+				return bool
+			}
+		},
+		created() {
+			// if (this.form && this.formItem) {
+			// 	this.$watch('formItem.errMsg', (newVal) => {
+			// 		this.localMsg = newVal
+			// 	})
+			// }
+		},
+		mounted() {
+			this.platform()
+		},
+		methods: {
+			initPicker(newVal) {
+				if (!newVal || Array.isArray(newVal) && !newVal.length) {
+					this.$nextTick(() => {
+						this.clear(false)
+					})
+					return
+				}
+				if (!Array.isArray(newVal) && !this.isRange) {
+					const {
+						defDate,
+						defTime
+					} = this.parseDate(newVal)
+					this.singleVal = defDate
+					this.tempSingleDate = defDate
+					this.defSingleDate = defDate
+					if (this.hasTime) {
+						this.singleVal = defDate + ' ' + defTime
+						this.time = defTime
+					}
+				} else {
+					const [before, after] = newVal
+					if (!before && !after) return
+					const defBefore = this.parseDate(before)
+					const defAfter = this.parseDate(after)
+					const startDate = defBefore.defDate
+					const endDate = defAfter.defDate
+					this.range.startDate = this.tempRange.startDate = startDate
+					this.range.endDate = this.tempRange.endDate = endDate
+
+					if (this.hasTime) {
+						this.range.startDate = defBefore.defDate + ' ' + defBefore.defTime
+						this.range.endDate = defAfter.defDate + ' ' + defAfter.defTime
+						this.tempRange.startTime = defBefore.defTime
+						this.tempRange.endTime = defAfter.defTime
+					}
+					const defaultRange = {
+						before: defBefore.defDate,
+						after: defAfter.defDate
+					}
+					this.startMultipleStatus = Object.assign({}, this.startMultipleStatus, defaultRange, {
+						which: 'right'
+					})
+					this.endMultipleStatus = Object.assign({}, this.endMultipleStatus, defaultRange, {
+						which: 'left'
+					})
+				}
+			},
+			updateLeftCale(e) {
+				const left = this.$refs.left
+				// 设置范围选
+				left.cale.setHoverMultiple(e.after)
+				left.setDate(this.$refs.left.nowDate.fullDate)
+			},
+			updateRightCale(e) {
+				const right = this.$refs.right
+				// 设置范围选
+				right.cale.setHoverMultiple(e.after)
+				right.setDate(this.$refs.right.nowDate.fullDate)
+			},
+			platform() {
+				const systemInfo = uni.getSystemInfoSync()
+				this.isPhone = systemInfo.windowWidth <= 500
+				this.windowWidth = systemInfo.windowWidth
+			},
+			show(event) {
+				if (this.disabled) {
+					return
+				}
+				this.platform()
+				if (this.isPhone) {
+					this.$refs.mobile.open()
+					return
+				}
+				this.popover = {
+					top: '10px'
+				}
+				const dateEditor = uni.createSelectorQuery().in(this).select(".uni-date-editor")
+				dateEditor.boundingClientRect(rect => {
+					if (this.windowWidth - rect.left < this.datePopupWidth) {
+						this.popover.right = 0
+					}
+				}).exec()
+				setTimeout(() => {
+					this.popup = !this.popup
+					if (!this.isPhone && this.isRange && this.isFirstShow) {
+						this.isFirstShow = false
+						const {
+							startDate,
+							endDate
+						} = this.range
+						if (startDate && endDate) {
+							if (this.diffDate(startDate, endDate) < 30) {
+								this.$refs.right.next()
+							}
+						} else {
+							this.$refs.right.next()
+							this.$refs.right.cale.lastHover = false
+						}
+					}
+
+				}, 50)
+			},
+
+			close() {
+				setTimeout(() => {
+					this.popup = false
+					this.$emit('maskClick', this.value)
+				}, 20)
+			},
+			setEmit(value) {
+				if (this.returnType === "timestamp" || this.returnType === "date") {
+					if (!Array.isArray(value)) {
+						if (!this.hasTime) {
+							value = value + ' ' + '00:00:00'
+						}
+						value = this.createTimestamp(value)
+						if (this.returnType === "date") {
+							value = new Date(value)
+						}
+					} else {
+						if (!this.hasTime) {
+							value[0] = value[0] + ' ' + '00:00:00'
+							value[1] = value[1] + ' ' + '00:00:00'
+						}
+						value[0] = this.createTimestamp(value[0])
+						value[1] = this.createTimestamp(value[1])
+						if (this.returnType === "date") {
+							value[0] = new Date(value[0])
+							value[1] = new Date(value[1])
+						}
+					}
+				}
+				
+				
+				this.$emit('change', value)
+				this.$emit('input', value)
+				this.$emit('update:modelValue', value)
+				this.isEmitValue = true
+			},
+			createTimestamp(date) {
+				date = this.fixIosDateFormat(date)
+				return Date.parse(new Date(date))
+			},
+			singleChange(e) {
+				this.tempSingleDate = e.fulldate
+				if (this.hasTime) return
+				this.confirmSingleChange()
+			},
+
+			confirmSingleChange() {
+				if (!this.tempSingleDate) {
+					this.popup = false
+					return
+				}
+				if (this.hasTime) {
+					this.singleVal = this.tempSingleDate + ' ' + (this.time ? this.time : '00:00:00')
+				} else {
+					this.singleVal = this.tempSingleDate
+				}
+				this.setEmit(this.singleVal)
+				this.popup = false
+			},
+
+			leftChange(e) {
+				const {
+					before,
+					after
+				} = e.range
+				this.rangeChange(before, after)
+				const obj = {
+					before: e.range.before,
+					after: e.range.after,
+					data: e.range.data,
+					fulldate: e.fulldate
+				}
+				this.startMultipleStatus = Object.assign({}, this.startMultipleStatus, obj)
+			},
+
+			rightChange(e) {
+				const {
+					before,
+					after
+				} = e.range
+				this.rangeChange(before, after)
+				const obj = {
+					before: e.range.before,
+					after: e.range.after,
+					data: e.range.data,
+					fulldate: e.fulldate
+				}
+				this.endMultipleStatus = Object.assign({}, this.endMultipleStatus, obj)
+			},
+
+			mobileChange(e) {
+				if (this.isRange) {
+					const {
+						before,
+						after
+					} = e.range
+					this.handleStartAndEnd(before, after, true)
+					if (this.hasTime) {
+						const {
+							startTime,
+							endTime
+						} = e.timeRange
+						this.tempRange.startTime = startTime
+						this.tempRange.endTime = endTime
+					}
+					this.confirmRangeChange()
+
+				} else {
+					if (this.hasTime) {
+						this.singleVal = e.fulldate + ' ' + e.time
+					} else {
+						this.singleVal = e.fulldate
+					}
+					this.setEmit(this.singleVal)
+				}
+				this.$refs.mobile.close()
+			},
+
+			rangeChange(before, after) {
+				if (!(before && after)) return
+				this.handleStartAndEnd(before, after, true)
+				if (this.hasTime) return
+				this.confirmRangeChange()
+			},
+
+			confirmRangeChange() {
+				if (!this.tempRange.startDate && !this.tempRange.endDate) {
+					this.popup = false
+					return
+				}
+				let start, end
+				if (!this.hasTime) {
+					start = this.range.startDate = this.tempRange.startDate
+					end = this.range.endDate = this.tempRange.endDate
+				} else {
+					start = this.range.startDate = this.tempRange.startDate + ' ' +
+						(this.tempRange.startTime ? this.tempRange.startTime : '00:00:00')
+					end = this.range.endDate = this.tempRange.endDate + ' ' +
+						(this.tempRange.endTime ? this.tempRange.endTime : '00:00:00')
+				}
+				const displayRange = [start, end]
+				this.setEmit(displayRange)
+				this.popup = false
+			},
+
+			handleStartAndEnd(before, after, temp = false) {
+				if (!(before && after)) return
+				const type = temp ? 'tempRange' : 'range'
+				if (this.dateCompare(before, after)) {
+					this[type].startDate = before
+					this[type].endDate = after
+				} else {
+					this[type].startDate = after
+					this[type].endDate = before
+				}
+			},
+
+			/**
+			 * 比较时间大小
+			 */
+			dateCompare(startDate, endDate) {
+				// 计算截止时间
+				startDate = new Date(startDate.replace('-', '/').replace('-', '/'))
+				// 计算详细项的截止时间
+				endDate = new Date(endDate.replace('-', '/').replace('-', '/'))
+				if (startDate <= endDate) {
+					return true
+				} else {
+					return false
+				}
+			},
+
+			/**
+			 * 比较时间差
+			 */
+			diffDate(startDate, endDate) {
+				// 计算截止时间
+				startDate = new Date(startDate.replace('-', '/').replace('-', '/'))
+				// 计算详细项的截止时间
+				endDate = new Date(endDate.replace('-', '/').replace('-', '/'))
+				const diff = (endDate - startDate) / (24 * 60 * 60 * 1000)
+				return Math.abs(diff)
+			},
+
+			clear(needEmit = true) {
+				if (!this.isRange) {
+					this.singleVal = ''
+					this.tempSingleDate = ''
+					this.time = ''
+					if (this.isPhone) {
+						this.$refs.mobile && this.$refs.mobile.clearCalender()
+					} else {
+						this.$refs.pcSingle && this.$refs.pcSingle.clearCalender()
+					}
+					if (needEmit) {
+						// 校验规则
+						// if(this.form  && this.formItem){
+						// 	const {
+						// 		validateTrigger
+						// 	} = this.form
+						// 	if (validateTrigger === 'blur') {
+						// 		this.formItem.onFieldChange()
+						// 	}
+						// }
+						this.$emit('change', '')
+						this.$emit('input', '')
+						this.$emit('update:modelValue', '')
+					}
+				} else {
+					this.range.startDate = ''
+					this.range.endDate = ''
+					this.tempRange.startDate = ''
+					this.tempRange.startTime = ''
+					this.tempRange.endDate = ''
+					this.tempRange.endTime = ''
+					if (this.isPhone) {
+						this.$refs.mobile && this.$refs.mobile.clearCalender()
+					} else {
+						this.$refs.left && this.$refs.left.clearCalender()
+						this.$refs.right && this.$refs.right.clearCalender()
+						this.$refs.right && this.$refs.right.next()
+					}
+					if (needEmit) {
+						this.$emit('change', [])
+						this.$emit('input', [])
+						this.$emit('update:modelValue', [])
+					}
+				}
+			},
+
+			parseDate(date) {
+				date = this.fixIosDateFormat(date)
+				const defVal = new Date(date)
+				const year = defVal.getFullYear()
+				const month = defVal.getMonth() + 1
+				const day = defVal.getDate()
+				const hour = defVal.getHours()
+				const minute = defVal.getMinutes()
+				const second = defVal.getSeconds()
+				const defDate = year + '-' + this.lessTen(month) + '-' + this.lessTen(day)
+				const defTime = this.lessTen(hour) + ':' + this.lessTen(minute) + (this.hideSecond ? '' : (':' + this
+					.lessTen(second)))
+				return {
+					defDate,
+					defTime
+				}
+			},
+
+			lessTen(item) {
+				return item < 10 ? '0' + item : item
+			},
+
+			//兼容 iOS、safari 日期格式
+			fixIosDateFormat(value) {
+				if (typeof value === 'string') {
+					value = value.replace(/-/g, '/')
+				}
+				return value
+			},
+
+			leftMonthSwitch(e) {
+				// console.log('leftMonthSwitch 返回:', e)
+			},
+			rightMonthSwitch(e) {
+				// console.log('rightMonthSwitch 返回:', e)
+			}
+		}
+	}
+</script>
+
+<style>
+	.uni-date {
+		/* #ifndef APP-NVUE */
+		width: 100%;
+		/* #endif */
+		flex: 1;
+	}
+	.uni-date-x {
+		display: flex;
+		flex-direction: row;
+		align-items: center;
+		justify-content: center;
+		padding: 0 10px;
+		border-radius: 4px;
+		background-color: #fff;
+		color: #666;
+		font-size: 14px;
+		flex: 1;
+	}
+
+	.uni-date-x--border {
+		box-sizing: border-box;
+		border-radius: 4px;
+		border: 1px solid #e5e5e5;
+	}
+
+	.uni-date-editor--x {
+		display: flex;
+		align-items: center;
+		position: relative;
+	}
+
+	.uni-date-editor--x .uni-date__icon-clear {
+		padding: 0 5px;
+		display: flex;
+		align-items: center;
+		/* #ifdef H5 */
+		cursor: pointer;
+		/* #endif */
+	}
+
+	.uni-date__x-input {
+		padding: 0 8px;
+		/* #ifndef APP-NVUE */
+		width: auto;
+		/* #endif */
+		position: relative;
+		overflow: hidden;
+		flex: 1;
+		line-height: 1;
+		font-size: 14px;
+		height: 35px;
+	}
+
+	.t-c {
+		text-align: center;
+	}
+
+	.uni-date__input {
+		height: 40px;
+		width: 100%;
+		line-height: 40px;
+		font-size: 14px;
+	}
+
+	.uni-date-range__input {
+		text-align: center;
+		max-width: 142px;
+	}
+
+	.uni-date-picker__container {
+		position: relative;
+		/* 		position: fixed;
+		left: 0;
+		right: 0;
+		top: 0;
+		bottom: 0;
+		box-sizing: border-box;
+		z-index: 996;
+		font-size: 14px; */
+	}
+
+	.uni-date-mask {
+		position: fixed;
+		bottom: 0px;
+		top: 0px;
+		left: 0px;
+		right: 0px;
+		background-color: rgba(0, 0, 0, 0);
+		transition-duration: 0.3s;
+		z-index: 996;
+	}
+
+	.uni-date-single--x {
+		/* padding: 0 8px; */
+		background-color: #fff;
+		position: absolute;
+		top: 0;
+		z-index: 999;
+		border: 1px solid #EBEEF5;
+		box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+		border-radius: 4px;
+	}
+
+	.uni-date-range--x {
+		/* padding: 0 8px; */
+		background-color: #fff;
+		position: absolute;
+		top: 0;
+		z-index: 999;
+		border: 1px solid #EBEEF5;
+		box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+		border-radius: 4px;
+	}
+
+	.uni-date-editor--x__disabled {
+		opacity: 0.4;
+		cursor: default;
+	}
+
+	.uni-date-editor--logo {
+		width: 16px;
+		height: 16px;
+		vertical-align: middle;
+	}
+
+	/* 添加时间 */
+	.popup-x-header {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		/* justify-content: space-between; */
+	}
+
+	.popup-x-header--datetime {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		flex: 1;
+	}
+
+	.popup-x-body {
+		display: flex;
+	}
+
+	.popup-x-footer {
+		padding: 0 15px;
+		border-top-color: #F1F1F1;
+		border-top-style: solid;
+		border-top-width: 1px;
+		/* background-color: #fff; */
+		line-height: 40px;
+		text-align: right;
+		color: #666;
+	}
+
+	.popup-x-footer text:hover {
+		color: #007aff;
+		cursor: pointer;
+		opacity: 0.8;
+	}
+
+	.popup-x-footer .confirm {
+		margin-left: 20px;
+		color: #007aff;
+	}
+
+	.uni-date-changed {
+		/* background-color: #fff; */
+		text-align: center;
+		color: #333;
+		border-bottom-color: #F1F1F1;
+		border-bottom-style: solid;
+		border-bottom-width: 1px;
+		/* padding: 0 50px; */
+	}
+
+	.uni-date-changed--time text {
+		/* padding: 0 20px; */
+		height: 50px;
+		line-height: 50px;
+	}
+
+	.uni-date-changed .uni-date-changed--time {
+		/* display: flex; */
+		flex: 1;
+	}
+
+	.uni-date-changed--time-date {
+		color: #333;
+		opacity: 0.6;
+	}
+
+	.mr-50 {
+		margin-right: 50px;
+	}
+
+	/* picker 弹出层通用的指示小三角, todo:扩展至上下左右方向定位 */
+	.uni-popper__arrow,
+	.uni-popper__arrow::after {
+		position: absolute;
+		display: block;
+		width: 0;
+		height: 0;
+		border-color: transparent;
+		border-style: solid;
+		border-width: 6px;
+	}
+
+	.uni-popper__arrow {
+		filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03));
+		top: -6px;
+		left: 10%;
+		margin-right: 3px;
+		border-top-width: 0;
+		border-bottom-color: #EBEEF5;
+	}
+
+	.uni-popper__arrow::after {
+		content: " ";
+		top: 1px;
+		margin-left: -6px;
+		border-top-width: 0;
+		border-bottom-color: #fff;
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-datetime-picker/components/uni-datetime-picker/util.js b/yudao-ui-admin-uniapp/uni_modules/uni-datetime-picker/components/uni-datetime-picker/util.js
new file mode 100644
index 000000000..efa5773ae
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-datetime-picker/components/uni-datetime-picker/util.js
@@ -0,0 +1,410 @@
+class Calendar {
+	constructor({
+		date,
+		selected,
+		startDate,
+		endDate,
+		range,
+		// multipleStatus
+	} = {}) {
+		// 当前日期
+		this.date = this.getDate(new Date()) // 当前初入日期
+		// 打点信息
+		this.selected = selected || [];
+		// 范围开始
+		this.startDate = startDate
+		// 范围结束
+		this.endDate = endDate
+		this.range = range
+		// 多选状态
+		this.cleanMultipleStatus()
+		// 每周日期
+		this.weeks = {}
+		// this._getWeek(this.date.fullDate)
+		// this.multipleStatus = multipleStatus
+		this.lastHover = false
+	}
+	/**
+	 * 设置日期
+	 * @param {Object} date
+	 */
+	setDate(date) {
+		this.selectDate = this.getDate(date)
+		this._getWeek(this.selectDate.fullDate)
+	}
+
+	/**
+	 * 清理多选状态
+	 */
+	cleanMultipleStatus() {
+		this.multipleStatus = {
+			before: '',
+			after: '',
+			data: []
+		}
+	}
+
+	/**
+	 * 重置开始日期
+	 */
+	resetSatrtDate(startDate) {
+		// 范围开始
+		this.startDate = startDate
+
+	}
+
+	/**
+	 * 重置结束日期
+	 */
+	resetEndDate(endDate) {
+		// 范围结束
+		this.endDate = endDate
+	}
+
+	/**
+	 * 获取任意时间
+	 */
+	getDate(date, AddDayCount = 0, str = 'day') {
+		if (!date) {
+			date = new Date()
+		}
+		if (typeof date !== 'object') {
+			date = date.replace(/-/g, '/')
+		}
+		const dd = new Date(date)
+		switch (str) {
+			case 'day':
+				dd.setDate(dd.getDate() + AddDayCount) // 获取AddDayCount天后的日期
+				break
+			case 'month':
+				if (dd.getDate() === 31) {
+					dd.setDate(dd.getDate() + AddDayCount)
+				} else {
+					dd.setMonth(dd.getMonth() + AddDayCount) // 获取AddDayCount天后的日期
+				}
+				break
+			case 'year':
+				dd.setFullYear(dd.getFullYear() + AddDayCount) // 获取AddDayCount天后的日期
+				break
+		}
+		const y = dd.getFullYear()
+		const m = dd.getMonth() + 1 < 10 ? '0' + (dd.getMonth() + 1) : dd.getMonth() + 1 // 获取当前月份的日期,不足10补0
+		const d = dd.getDate() < 10 ? '0' + dd.getDate() : dd.getDate() // 获取当前几号,不足10补0
+		return {
+			fullDate: y + '-' + m + '-' + d,
+			year: y,
+			month: m,
+			date: d,
+			day: dd.getDay()
+		}
+	}
+
+
+	/**
+	 * 获取上月剩余天数
+	 */
+	_getLastMonthDays(firstDay, full) {
+		let dateArr = []
+		for (let i = firstDay; i > 0; i--) {
+			const beforeDate = new Date(full.year, full.month - 1, -i + 1).getDate()
+			dateArr.push({
+				date: beforeDate,
+				month: full.month - 1,
+				disable: true
+			})
+		}
+		return dateArr
+	}
+	/**
+	 * 获取本月天数
+	 */
+	_currentMonthDys(dateData, full) {
+		let dateArr = []
+		let fullDate = this.date.fullDate
+		for (let i = 1; i <= dateData; i++) {
+			let isinfo = false
+			let nowDate = full.year + '-' + (full.month < 10 ?
+				full.month : full.month) + '-' + (i < 10 ?
+				'0' + i : i)
+			// 是否今天
+			let isDay = fullDate === nowDate
+			// 获取打点信息
+			let info = this.selected && this.selected.find((item) => {
+				if (this.dateEqual(nowDate, item.date)) {
+					return item
+				}
+			})
+
+			// 日期禁用
+			let disableBefore = true
+			let disableAfter = true
+			if (this.startDate) {
+				// let dateCompBefore = this.dateCompare(this.startDate, fullDate)
+				// disableBefore = this.dateCompare(dateCompBefore ? this.startDate : fullDate, nowDate)
+				disableBefore = this.dateCompare(this.startDate, nowDate)
+			}
+
+			if (this.endDate) {
+				// let dateCompAfter = this.dateCompare(fullDate, this.endDate)
+				// disableAfter = this.dateCompare(nowDate, dateCompAfter ? this.endDate : fullDate)
+				disableAfter = this.dateCompare(nowDate, this.endDate)
+			}
+			let multiples = this.multipleStatus.data
+			let checked = false
+			let multiplesStatus = -1
+			if (this.range) {
+				if (multiples) {
+					multiplesStatus = multiples.findIndex((item) => {
+						return this.dateEqual(item, nowDate)
+					})
+				}
+				if (multiplesStatus !== -1) {
+					checked = true
+				}
+			}
+			let data = {
+				fullDate: nowDate,
+				year: full.year,
+				date: i,
+				multiple: this.range ? checked : false,
+				beforeMultiple: this.isLogicBefore(nowDate, this.multipleStatus.before, this.multipleStatus.after),
+				afterMultiple: this.isLogicAfter(nowDate, this.multipleStatus.before, this.multipleStatus.after),
+				month: full.month,
+				disable: !(disableBefore && disableAfter),
+				isDay,
+				userChecked: false
+			}
+			if (info) {
+				data.extraInfo = info
+			}
+
+			dateArr.push(data)
+		}
+		return dateArr
+	}
+	/**
+	 * 获取下月天数
+	 */
+	_getNextMonthDays(surplus, full) {
+		let dateArr = []
+		for (let i = 1; i < surplus + 1; i++) {
+			dateArr.push({
+				date: i,
+				month: Number(full.month) + 1,
+				disable: true
+			})
+		}
+		return dateArr
+	}
+
+	/**
+	 * 获取当前日期详情
+	 * @param {Object} date
+	 */
+	getInfo(date) {
+		if (!date) {
+			date = new Date()
+		}
+		const dateInfo = this.canlender.find(item => item.fullDate === this.getDate(date).fullDate)
+		return dateInfo
+	}
+
+	/**
+	 * 比较时间大小
+	 */
+	dateCompare(startDate, endDate) {
+		// 计算截止时间
+		startDate = new Date(startDate.replace('-', '/').replace('-', '/'))
+		// 计算详细项的截止时间
+		endDate = new Date(endDate.replace('-', '/').replace('-', '/'))
+		if (startDate <= endDate) {
+			return true
+		} else {
+			return false
+		}
+	}
+
+	/**
+	 * 比较时间是否相等
+	 */
+	dateEqual(before, after) {
+		// 计算截止时间
+		before = new Date(before.replace('-', '/').replace('-', '/'))
+		// 计算详细项的截止时间
+		after = new Date(after.replace('-', '/').replace('-', '/'))
+		if (before.getTime() - after.getTime() === 0) {
+			return true
+		} else {
+			return false
+		}
+	}
+
+	/**
+	 *  比较真实起始日期
+	 */
+
+	isLogicBefore(currentDay, before, after) {
+		let logicBefore = before
+		if (before && after) {
+			logicBefore = this.dateCompare(before, after) ? before : after
+		}
+		return this.dateEqual(logicBefore, currentDay)
+	}
+
+	isLogicAfter(currentDay, before, after) {
+		let logicAfter = after
+		if (before && after) {
+			logicAfter = this.dateCompare(before, after) ? after : before
+		}
+		return this.dateEqual(logicAfter, currentDay)
+	}
+
+	/**
+	 * 获取日期范围内所有日期
+	 * @param {Object} begin
+	 * @param {Object} end
+	 */
+	geDateAll(begin, end) {
+		var arr = []
+		var ab = begin.split('-')
+		var ae = end.split('-')
+		var db = new Date()
+		db.setFullYear(ab[0], ab[1] - 1, ab[2])
+		var de = new Date()
+		de.setFullYear(ae[0], ae[1] - 1, ae[2])
+		var unixDb = db.getTime() - 24 * 60 * 60 * 1000
+		var unixDe = de.getTime() - 24 * 60 * 60 * 1000
+		for (var k = unixDb; k <= unixDe;) {
+			k = k + 24 * 60 * 60 * 1000
+			arr.push(this.getDate(new Date(parseInt(k))).fullDate)
+		}
+		return arr
+	}
+
+	/**
+	 *  获取多选状态
+	 */
+	setMultiple(fullDate) {
+		let {
+			before,
+			after
+		} = this.multipleStatus
+		if (!this.range) return
+		if (before && after) {
+			if (!this.lastHover) {
+				this.lastHover = true
+				return
+			}
+			this.multipleStatus.before = fullDate
+			this.multipleStatus.after = ''
+			this.multipleStatus.data = []
+			this.multipleStatus.fulldate = ''
+			this.lastHover = false
+		} else {
+			if (!before) {
+				this.multipleStatus.before = fullDate
+				this.lastHover = false
+			} else {
+				this.multipleStatus.after = fullDate
+				if (this.dateCompare(this.multipleStatus.before, this.multipleStatus.after)) {
+					this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus
+						.after);
+				} else {
+					this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus
+						.before);
+				}
+				this.lastHover = true
+			}
+		}
+		this._getWeek(fullDate)
+	}
+
+	/**
+	 *  鼠标 hover 更新多选状态
+	 */
+	setHoverMultiple(fullDate) {
+		let {
+			before,
+			after
+		} = this.multipleStatus
+
+		if (!this.range) return
+		if (this.lastHover) return
+
+		if (!before) {
+			this.multipleStatus.before = fullDate
+		} else {
+			this.multipleStatus.after = fullDate
+			if (this.dateCompare(this.multipleStatus.before, this.multipleStatus.after)) {
+				this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus.after);
+			} else {
+				this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus.before);
+			}
+		}
+		this._getWeek(fullDate)
+	}
+
+	/**
+	 * 更新默认值多选状态
+	 */
+	setDefaultMultiple(before, after) {
+		this.multipleStatus.before = before
+		this.multipleStatus.after = after
+		if (before && after) {
+			if (this.dateCompare(before, after)) {
+				this.multipleStatus.data = this.geDateAll(before, after);
+				this._getWeek(after)
+			} else {
+				this.multipleStatus.data = this.geDateAll(after, before);
+				this._getWeek(before)
+			}
+		}
+	}
+
+	/**
+	 * 获取每周数据
+	 * @param {Object} dateData
+	 */
+	_getWeek(dateData) {
+		const {
+			fullDate,
+			year,
+			month,
+			date,
+			day
+		} = this.getDate(dateData)
+		let firstDay = new Date(year, month - 1, 1).getDay()
+		let currentDay = new Date(year, month, 0).getDate()
+		let dates = {
+			lastMonthDays: this._getLastMonthDays(firstDay, this.getDate(dateData)), // 上个月末尾几天
+			currentMonthDys: this._currentMonthDys(currentDay, this.getDate(dateData)), // 本月天数
+			nextMonthDays: [], // 下个月开始几天
+			weeks: []
+		}
+		let canlender = []
+		const surplus = 42 - (dates.lastMonthDays.length + dates.currentMonthDys.length)
+		dates.nextMonthDays = this._getNextMonthDays(surplus, this.getDate(dateData))
+		canlender = canlender.concat(dates.lastMonthDays, dates.currentMonthDys, dates.nextMonthDays)
+		let weeks = {}
+		// 拼接数组  上个月开始几天 + 本月天数+ 下个月开始几天
+		for (let i = 0; i < canlender.length; i++) {
+			if (i % 7 === 0) {
+				weeks[parseInt(i / 7)] = new Array(7)
+			}
+			weeks[parseInt(i / 7)][i % 7] = canlender[i]
+		}
+		this.canlender = canlender
+		this.weeks = weeks
+	}
+
+	//静态方法
+	// static init(date) {
+	// 	if (!this.instance) {
+	// 		this.instance = new Calendar(date);
+	// 	}
+	// 	return this.instance;
+	// }
+}
+
+
+export default Calendar
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-datetime-picker/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-datetime-picker/package.json
new file mode 100644
index 000000000..60fa1d028
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-datetime-picker/package.json
@@ -0,0 +1,90 @@
+{
+  "id": "uni-datetime-picker",
+  "displayName": "uni-datetime-picker 日期选择器",
+  "version": "2.2.6",
+  "description": "uni-datetime-picker 日期时间选择器,支持日历,支持范围选择",
+  "keywords": [
+    "uni-datetime-picker",
+    "uni-ui",
+    "uniui",
+    "日期时间选择器",
+    "日期时间"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": [
+			"uni-scss",
+			"uni-icons"
+		],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "n"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-datetime-picker/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-datetime-picker/readme.md
new file mode 100644
index 000000000..162fbefaa
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-datetime-picker/readme.md
@@ -0,0 +1,21 @@
+
+
+> `重要通知:组件升级更新 2.0.0 后,支持日期+时间范围选择,组件 ui 将使用日历选择日期,ui 变化较大,同时支持 PC 和 移动端。此版本不向后兼容,不再支持单独的时间选择(type=time)及相关的 hide-second 属性(时间选可使用内置组件 picker)。若仍需使用旧版本,可在插件市场下载*非uni_modules版本*,旧版本将不再维护`
+
+## DatetimePicker 时间选择器
+
+> **组件名:uni-datetime-picker**
+> 代码块: `uDatetimePicker`
+
+
+该组件的优势是,支持**时间戳**输入和输出(起始时间、终止时间也支持时间戳),可**同时选择**日期和时间。
+
+若只是需要单独选择日期和时间,不需要时间戳输入和输出,可使用原生的 picker 组件。
+
+**_点击 picker 默认值规则:_**
+
+- 若设置初始值 value, 会显示在 picker 显示框中
+- 若无初始值 value,则初始值 value 为当前本地时间 Date.now(), 但不会显示在 picker 显示框中
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-datetime-picker)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-drawer/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-drawer/changelog.md
new file mode 100644
index 000000000..6d2488c32
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-drawer/changelog.md
@@ -0,0 +1,13 @@
+## 1.2.1(2021-11-22)
+- 修复 vue3中个别scss变量无法找到的问题
+## 1.2.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-drawer](https://uniapp.dcloud.io/component/uniui/uni-drawer)
+## 1.1.1(2021-07-30)
+- 优化 vue3下事件警告的问题
+## 1.1.0(2021-07-13)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.0.7(2021-05-12)
+- 新增 组件示例地址
+## 1.0.6(2021-02-04)
+- 调整为uni_modules目录规范
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-drawer/components/uni-drawer/keypress.js b/yudao-ui-admin-uniapp/uni_modules/uni-drawer/components/uni-drawer/keypress.js
new file mode 100644
index 000000000..62dda461b
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-drawer/components/uni-drawer/keypress.js
@@ -0,0 +1,45 @@
+// #ifdef H5
+export default {
+  name: 'Keypress',
+  props: {
+    disable: {
+      type: Boolean,
+      default: false
+    }
+  },
+  mounted () {
+    const keyNames = {
+      esc: ['Esc', 'Escape'],
+      tab: 'Tab',
+      enter: 'Enter',
+      space: [' ', 'Spacebar'],
+      up: ['Up', 'ArrowUp'],
+      left: ['Left', 'ArrowLeft'],
+      right: ['Right', 'ArrowRight'],
+      down: ['Down', 'ArrowDown'],
+      delete: ['Backspace', 'Delete', 'Del']
+    }
+    const listener = ($event) => {
+      if (this.disable) {
+        return
+      }
+      const keyName = Object.keys(keyNames).find(key => {
+        const keyName = $event.key
+        const value = keyNames[key]
+        return value === keyName || (Array.isArray(value) && value.includes(keyName))
+      })
+      if (keyName) {
+        // 避免和其他按键事件冲突
+        setTimeout(() => {
+          this.$emit(keyName, {})
+        }, 0)
+      }
+    }
+    document.addEventListener('keyup', listener)
+    // this.$once('hook:beforeDestroy', () => {
+    //   document.removeEventListener('keyup', listener)
+    // })
+  },
+	render: () => {}
+}
+// #endif
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-drawer/components/uni-drawer/uni-drawer.vue b/yudao-ui-admin-uniapp/uni_modules/uni-drawer/components/uni-drawer/uni-drawer.vue
new file mode 100644
index 000000000..82331a81b
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-drawer/components/uni-drawer/uni-drawer.vue
@@ -0,0 +1,183 @@
+<template>
+	<view v-if="visibleSync" :class="{ 'uni-drawer--visible': showDrawer }" class="uni-drawer" @touchmove.stop.prevent="clear">
+		<view class="uni-drawer__mask" :class="{ 'uni-drawer__mask--visible': showDrawer && mask }" @tap="close('mask')" />
+		<view class="uni-drawer__content" :class="{'uni-drawer--right': rightMode,'uni-drawer--left': !rightMode, 'uni-drawer__content--visible': showDrawer}" :style="{width:drawerWidth+'px'}">
+			<slot />
+		</view>
+		<!-- #ifdef H5 -->
+		<keypress @esc="close('mask')" />
+		<!-- #endif -->
+	</view>
+</template>
+
+<script>
+	// #ifdef H5
+	import keypress from './keypress.js'
+	// #endif
+	/**
+	 * Drawer 抽屉
+	 * @description 抽屉侧滑菜单
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=26
+	 * @property {Boolean} mask = [true | false] 是否显示遮罩
+	 * @property {Boolean} maskClick = [true | false] 点击遮罩是否关闭
+	 * @property {Boolean} mode = [left | right] Drawer 滑出位置
+	 * 	@value left 从左侧滑出
+	 * 	@value right 从右侧侧滑出
+	 * @property {Number} width 抽屉的宽度 ,仅 vue 页面生效
+	 * @event {Function} close 组件关闭时触发事件
+	 */
+	export default {
+		name: 'UniDrawer',
+		components: {
+			// #ifdef H5
+			keypress
+			// #endif
+		},
+		emits:['change'],
+		props: {
+			/**
+			 * 显示模式(左、右),只在初始化生效
+			 */
+			mode: {
+				type: String,
+				default: ''
+			},
+			/**
+			 * 蒙层显示状态
+			 */
+			mask: {
+				type: Boolean,
+				default: true
+			},
+			/**
+			 * 遮罩是否可点击关闭
+			 */
+			maskClick:{
+				type: Boolean,
+				default: true
+			},
+			/**
+			 * 抽屉宽度
+			 */
+			width: {
+				type: Number,
+				default: 220
+			}
+		},
+		data() {
+			return {
+				visibleSync: false,
+				showDrawer: false,
+				rightMode: false,
+				watchTimer: null,
+				drawerWidth: 220
+			}
+		},
+		created() {
+			// #ifndef APP-NVUE
+			this.drawerWidth = this.width
+			// #endif
+			this.rightMode = this.mode === 'right'
+		},
+		methods: {
+			clear(){},
+			close(type) {
+				// fixed by mehaotian 抽屉尚未完全关闭或遮罩禁止点击时不触发以下逻辑
+				if((type === 'mask' && !this.maskClick) || !this.visibleSync) return
+				this._change('showDrawer', 'visibleSync', false)
+			},
+			open() {
+				// fixed by mehaotian 处理重复点击打开的事件
+				if(this.visibleSync) return
+				this._change('visibleSync', 'showDrawer', true)
+			},
+			_change(param1, param2, status) {
+				this[param1] = status
+				if (this.watchTimer) {
+					clearTimeout(this.watchTimer)
+				}
+				this.watchTimer = setTimeout(() => {
+					this[param2] = status
+					this.$emit('change',status)
+				}, status ? 50 : 300)
+			}
+		}
+	}
+</script>
+
+<style lang="scss" >
+	$uni-mask: rgba($color: #000000, $alpha: 0.4) ;
+	// 抽屉宽度
+	$drawer-width: 220px;
+
+	.uni-drawer {
+		/* #ifndef APP-NVUE */
+		display: block;
+		/* #endif */
+		position: fixed;
+		top: 0;
+		left: 0;
+		right: 0;
+		bottom: 0;
+		overflow: hidden;
+		z-index: 999;
+	}
+
+	.uni-drawer__content {
+		/* #ifndef APP-NVUE */
+		display: block;
+		/* #endif */
+		position: absolute;
+		top: 0;
+		width: $drawer-width;
+		bottom: 0;
+		background-color: $uni-bg-color;
+		transition: transform 0.3s ease;
+	}
+
+	.uni-drawer--left {
+		left: 0;
+		/* #ifdef APP-NVUE */
+		transform: translateX(-$drawer-width);
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		transform: translateX(-100%);
+		/* #endif */
+	}
+
+	.uni-drawer--right {
+		right: 0;
+		/* #ifdef APP-NVUE */
+		transform: translateX($drawer-width);
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		transform: translateX(100%);
+		/* #endif */
+	}
+
+	.uni-drawer__content--visible {
+		transform: translateX(0px);
+	}
+
+
+	.uni-drawer__mask {
+		/* #ifndef APP-NVUE */
+		display: block;
+		/* #endif */
+		opacity: 0;
+		position: absolute;
+		top: 0;
+		left: 0;
+		bottom: 0;
+		right: 0;
+		background-color: $uni-mask;
+		transition: opacity 0.3s;
+	}
+
+	.uni-drawer__mask--visible {
+		/* #ifndef APP-NVUE */
+		display: block;
+		/* #endif */
+		opacity: 1;
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-drawer/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-drawer/package.json
new file mode 100644
index 000000000..dd056e4c6
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-drawer/package.json
@@ -0,0 +1,87 @@
+{
+  "id": "uni-drawer",
+  "displayName": "uni-drawer 抽屉",
+  "version": "1.2.1",
+  "description": "抽屉式导航,用于展示侧滑菜单,侧滑导航。",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "drawer",
+    "抽屉",
+    "侧滑导航"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": ["uni-scss"],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-drawer/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-drawer/readme.md
new file mode 100644
index 000000000..dcf6e6b2e
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-drawer/readme.md
@@ -0,0 +1,10 @@
+
+
+## Drawer 抽屉
+> **组件名:uni-drawer**
+> 代码块: `uDrawer`
+
+抽屉侧滑菜单。
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-drawer)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-easyinput/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-easyinput/changelog.md
new file mode 100644
index 000000000..1e8c6f91b
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-easyinput/changelog.md
@@ -0,0 +1,47 @@
+## 1.1.0(2022-06-30)
+- 新增 在 uni-forms 1.4.0 中使用可以在 blur 时校验内容
+- 新增 clear 事件,点击右侧叉号图标触发
+- 新增 change 事件 ,仅在输入框失去焦点或用户按下回车时触发
+- 优化 组件样式,组件获取焦点时高亮显示,图标颜色调整等
+-
+## 1.0.5(2022-06-07)
+- 优化 clearable 显示策略
+## 1.0.4(2022-06-07)
+- 优化 clearable 显示策略
+## 1.0.3(2022-05-20)
+- 修复 关闭图标某些情况下无法取消的bug
+## 1.0.2(2022-04-12)
+- 修复 默认值不生效的bug
+## 1.0.1(2022-04-02)
+- 修复 value不能为0的bug
+## 1.0.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-easyinput](https://uniapp.dcloud.io/component/uniui/uni-easyinput)
+## 0.1.4(2021-08-20)
+- 修复 在 uni-forms 的动态表单中默认值校验不通过的 bug
+## 0.1.3(2021-08-11)
+- 修复 在 uni-forms 中重置表单,错误信息无法清除的问题
+## 0.1.2(2021-07-30)
+- 优化 vue3下事件警告的问题
+## 0.1.1
+- 优化 errorMessage 属性支持 Boolean 类型
+## 0.1.0(2021-07-13)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 0.0.16(2021-06-29)
+- 修复 confirmType 属性(仅 type="text" 生效)导致多行文本框无法换行的 bug
+## 0.0.15(2021-06-21)
+- 修复 passwordIcon 属性拼写错误的 bug
+## 0.0.14(2021-06-18)
+- 新增 passwordIcon 属性,当type=password时是否显示小眼睛图标
+- 修复 confirmType 属性不生效的问题
+## 0.0.13(2021-06-04)
+- 修复 disabled 状态可清出内容的 bug
+## 0.0.12(2021-05-12)
+- 新增 组件示例地址
+## 0.0.11(2021-05-07)
+- 修复 input-border 属性不生效的问题
+## 0.0.10(2021-04-30)
+- 修复 ios 遮挡文字、显示一半的问题
+## 0.0.9(2021-02-05)
+- 调整为uni_modules目录规范
+- 优化 兼容 nvue 页面
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-easyinput/components/uni-easyinput/common.js b/yudao-ui-admin-uniapp/uni_modules/uni-easyinput/components/uni-easyinput/common.js
new file mode 100644
index 000000000..df9abe1da
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-easyinput/components/uni-easyinput/common.js
@@ -0,0 +1,56 @@
+/**
+ * @desc 函数防抖
+ * @param func 目标函数
+ * @param wait 延迟执行毫秒数
+ * @param immediate true - 立即执行, false - 延迟执行
+ */
+export const debounce = function(func, wait = 1000, immediate = true) {
+	let timer;
+	console.log(1);
+	return function() {
+		console.log(123);
+		let context = this,
+			args = arguments;
+		if (timer) clearTimeout(timer);
+		if (immediate) {
+			let callNow = !timer;
+			timer = setTimeout(() => {
+				timer = null;
+			}, wait);
+			if (callNow) func.apply(context, args);
+		} else {
+			timer = setTimeout(() => {
+				func.apply(context, args);
+			}, wait)
+		}
+	}
+}
+/**
+ * @desc 函数节流
+ * @param func 函数
+ * @param wait 延迟执行毫秒数
+ * @param type 1 使用表时间戳,在时间段开始的时候触发 2 使用表定时器,在时间段结束的时候触发
+ */
+export const throttle = (func, wait = 1000, type = 1) => {
+	let previous = 0;
+	let timeout;
+	return function() {
+		let context = this;
+		let args = arguments;
+		if (type === 1) {
+			let now = Date.now();
+
+			if (now - previous > wait) {
+				func.apply(context, args);
+				previous = now;
+			}
+		} else if (type === 2) {
+			if (!timeout) {
+				timeout = setTimeout(() => {
+					timeout = null;
+					func.apply(context, args)
+				}, wait)
+			}
+		}
+	}
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue b/yudao-ui-admin-uniapp/uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue
new file mode 100644
index 000000000..5818d7fa4
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue
@@ -0,0 +1,593 @@
+<template>
+	<view class="uni-easyinput" :class="{'uni-easyinput-error':msg}" :style="boxStyle">
+		<view class="uni-easyinput__content" :class="inputContentClass" :style="inputContentStyle">
+			<uni-icons v-if="prefixIcon" class="content-clear-icon" :type="prefixIcon" color="#c0c4cc"
+				@click="onClickIcon('prefix')" size="22"></uni-icons>
+			<textarea v-if="type === 'textarea'" class="uni-easyinput__content-textarea"
+				:class="{'input-padding':inputBorder}" :name="name" :value="val" :placeholder="placeholder"
+				:placeholderStyle="placeholderStyle" :disabled="disabled"
+				placeholder-class="uni-easyinput__placeholder-class" :maxlength="inputMaxlength" :focus="focused"
+				:autoHeight="autoHeight" @input="onInput" @blur="_Blur" @focus="_Focus" @confirm="onConfirm"></textarea>
+			<input v-else :type="type === 'password'?'text':type" class="uni-easyinput__content-input"
+				:style="inputStyle" :name="name" :value="val" :password="!showPassword && type === 'password'"
+				:placeholder="placeholder" :placeholderStyle="placeholderStyle"
+				placeholder-class="uni-easyinput__placeholder-class" :disabled="disabled" :maxlength="inputMaxlength"
+				:focus="focused" :confirmType="confirmType" @focus="_Focus" @blur="_Blur" @input="onInput"
+				@confirm="onConfirm" />
+			<template v-if="type === 'password' && passwordIcon">
+				<!-- 开启密码时显示小眼睛 -->
+				<uni-icons v-if="isVal" class="content-clear-icon" :class="{'is-textarea-icon':type==='textarea'}"
+					:type="showPassword?'eye-slash-filled':'eye-filled'" :size="22"
+					:color="focusShow?'#2979ff':'#c0c4cc'" @click="onEyes">
+				</uni-icons>
+			</template>
+			<template v-else-if="suffixIcon">
+				<uni-icons v-if="suffixIcon" class="content-clear-icon" :type="suffixIcon" color="#c0c4cc"
+					@click="onClickIcon('suffix')" size="22"></uni-icons>
+			</template>
+			<template v-else>
+				<uni-icons v-if="clearable && isVal && !disabled  && type !== 'textarea'" class="content-clear-icon"
+					:class="{'is-textarea-icon':type==='textarea'}" type="clear" :size="clearSize"
+					:color="msg?'#dd524d':(focusShow?'#2979ff':'#c0c4cc')" @click="onClear"></uni-icons>
+			</template>
+			<slot name="right"></slot>
+		</view>
+	</view>
+</template>
+
+<script>
+	/**
+	 * Easyinput 输入框
+	 * @description 此组件可以实现表单的输入与校验,包括 "text" 和 "textarea" 类型。
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=3455
+	 * @property {String}	value	输入内容
+	 * @property {String }	type	输入框的类型(默认text) password/text/textarea/..
+	 * 	@value text			文本输入键盘
+	 * 	@value textarea	多行文本输入键盘
+	 * 	@value password	密码输入键盘
+	 * 	@value number		数字输入键盘,注意iOS上app-vue弹出的数字键盘并非9宫格方式
+	 * 	@value idcard		身份证输入键盘,信、支付宝、百度、QQ小程序
+	 * 	@value digit		带小数点的数字键盘	,App的nvue页面、微信、支付宝、百度、头条、QQ小程序支持
+	 * @property {Boolean}	clearable	是否显示右侧清空内容的图标控件,点击可清空输入框内容(默认true)
+	 * @property {Boolean}	autoHeight	是否自动增高输入区域,type为textarea时有效(默认true)
+	 * @property {String }	placeholder	输入框的提示文字
+	 * @property {String }	placeholderStyle	placeholder的样式(内联样式,字符串),如"color: #ddd"
+	 * @property {Boolean}	focus	是否自动获得焦点(默认false)
+	 * @property {Boolean}	disabled	是否禁用(默认false)
+	 * @property {Number }	maxlength	最大输入长度,设置为 -1 的时候不限制最大长度(默认140)
+	 * @property {String }	confirmType	设置键盘右下角按钮的文字,仅在type="text"时生效(默认done)
+	 * @property {Number }	clearSize	清除图标的大小,单位px(默认15)
+	 * @property {String}	prefixIcon	输入框头部图标
+	 * @property {String}	suffixIcon	输入框尾部图标
+	 * @property {Boolean}	trim	是否自动去除两端的空格
+	 * @value both	去除两端空格
+	 * @value left	去除左侧空格
+	 * @value right	去除右侧空格
+	 * @value start	去除左侧空格
+	 * @value end		去除右侧空格
+	 * @value all		去除全部空格
+	 * @value none	不去除空格
+	 * @property {Boolean}	inputBorder	是否显示input输入框的边框(默认true)
+	 * @property {Boolean}	passwordIcon	type=password时是否显示小眼睛图标
+	 * @property {Object}	styles	自定义颜色
+	 * @event {Function}	input	输入框内容发生变化时触发
+	 * @event {Function}	focus	输入框获得焦点时触发
+	 * @event {Function}	blur	输入框失去焦点时触发
+	 * @event {Function}	confirm	点击完成按钮时触发
+	 * @event {Function}	iconClick	点击图标时触发
+	 * @example <uni-easyinput v-model="mobile"></uni-easyinput>
+	 */
+	function obj2strClass(obj) {
+		let classess = ''
+		for (let key in obj) {
+			const val = obj[key]
+			if (val) {
+				classess += `${key} `
+			}
+		}
+		return classess
+	}
+
+	function obj2strStyle(obj) {
+		let style = ''
+		for (let key in obj) {
+			const val = obj[key]
+			style += `${key}:${val};`
+		}
+		return style
+	}
+	export default {
+		name: 'uni-easyinput',
+		emits: ['click', 'iconClick', 'update:modelValue', 'input', 'focus', 'blur', 'confirm', 'clear', 'eyes', 'change'],
+		model: {
+			prop: 'modelValue',
+			event: 'update:modelValue'
+		},
+		options: {
+			virtualHost: true
+		},
+		inject: {
+			form: {
+				from: 'uniForm',
+				default: null
+			},
+			formItem: {
+				from: 'uniFormItem',
+				default: null
+			},
+		},
+		props: {
+			name: String,
+			value: [Number, String],
+			modelValue: [Number, String],
+			type: {
+				type: String,
+				default: 'text'
+			},
+			clearable: {
+				type: Boolean,
+				default: true
+			},
+			autoHeight: {
+				type: Boolean,
+				default: false
+			},
+			placeholder: {
+				type: String,
+				default: ' '
+			},
+			placeholderStyle: String,
+			focus: {
+				type: Boolean,
+				default: false
+			},
+			disabled: {
+				type: Boolean,
+				default: false
+			},
+			maxlength: {
+				type: [Number, String],
+				default: 140
+			},
+			confirmType: {
+				type: String,
+				default: 'done'
+			},
+			clearSize: {
+				type: [Number, String],
+				default: 24
+			},
+			inputBorder: {
+				type: Boolean,
+				default: true
+			},
+			prefixIcon: {
+				type: String,
+				default: ''
+			},
+			suffixIcon: {
+				type: String,
+				default: ''
+			},
+			trim: {
+				type: [Boolean, String],
+				default: true
+			},
+			passwordIcon: {
+				type: Boolean,
+				default: true
+			},
+			styles: {
+				type: Object,
+				default () {
+					return {
+						color: '#333',
+						disableColor: '#F7F6F6',
+						borderColor: '#e5e5e5'
+					}
+				}
+			},
+			errorMessage: {
+				type: [String, Boolean],
+				default: ''
+			}
+		},
+		data() {
+			return {
+				focused: false,
+				val: '',
+				showMsg: '',
+				border: false,
+				isFirstBorder: false,
+				showClearIcon: false,
+				showPassword: false,
+				focusShow: false,
+				localMsg: ''
+			};
+		},
+		computed: {
+			// 输入框内是否有值
+			isVal() {
+				const val = this.val
+				// fixed by mehaotian 处理值为0的情况,字符串0不在处理范围
+				if (val || val === 0) {
+					return true
+				}
+				return false
+			},
+
+			msg() {
+				// console.log('computed', this.form, this.formItem);
+				// if (this.form) {
+				// 	return this.errorMessage || this.formItem.errMsg;
+				// }
+				// TODO 处理头条 formItem 中 errMsg 不更新的问题
+				return this.localMsg || this.errorMessage
+			},
+			// 因为uniapp的input组件的maxlength组件必须要数值,这里转为数值,用户可以传入字符串数值
+			inputMaxlength() {
+				return Number(this.maxlength);
+			},
+
+			// 处理外层样式的style
+			boxStyle() {
+				return `color:${this.inputBorder && this.msg?'#e43d33':this.styles.color};`
+			},
+			// input 内容的类和样式处理
+			inputContentClass() {
+				return obj2strClass({
+					'is-input-border': this.inputBorder,
+					'is-input-error-border': this.inputBorder && this.msg,
+					'is-textarea': this.type === 'textarea',
+					'is-disabled': this.disabled
+				})
+			},
+			inputContentStyle() {
+				const focusColor = this.focusShow ? '#2979ff' : this.styles.borderColor
+				const borderColor = this.inputBorder && this.msg ? '#dd524d' : focusColor
+				return obj2strStyle({
+					'border-color': borderColor || '#e5e5e5',
+					'background-color': this.disabled ? this.styles.disableColor : '#fff'
+				})
+			},
+			// input右侧样式
+			inputStyle() {
+				const paddingRight = this.type === 'password' || this.clearable || this.prefixIcon ? '' : '10px'
+				return obj2strStyle({
+					'padding-right': paddingRight,
+					'padding-left': this.prefixIcon ? '' : '10px'
+				})
+			}
+		},
+		watch: {
+			value(newVal) {
+				this.val = newVal
+			},
+			modelValue(newVal) {
+				this.val = newVal
+			},
+			focus(newVal) {
+				this.$nextTick(() => {
+					this.focused = this.focus
+					this.focusShow = this.focus
+				})
+			}
+		},
+		created() {
+			this.init()
+			// TODO 处理头条vue3 computed 不监听 inject 更改的问题(formItem.errMsg)
+			if (this.form && this.formItem) {
+				this.$watch('formItem.errMsg', (newVal) => {
+					this.localMsg = newVal
+				})
+			}
+		},
+		mounted() {
+			this.$nextTick(() => {
+				this.focused = this.focus
+				this.focusShow = this.focus
+			})
+		},
+		methods: {
+			/**
+			 * 初始化变量值
+			 */
+			init() {
+				if (this.value || this.value === 0) {
+					this.val = this.value
+				} else if (this.modelValue || this.modelValue === 0) {
+					this.val = this.modelValue
+				} else {
+					this.val = null
+				}
+			},
+
+			/**
+			 * 点击图标时触发
+			 * @param {Object} type
+			 */
+			onClickIcon(type) {
+				this.$emit('iconClick', type)
+			},
+
+			/**
+			 * 显示隐藏内容,密码框时生效
+			 */
+			onEyes() {
+				this.showPassword = !this.showPassword
+				this.$emit('eyes', this.showPassword)
+			},
+
+			/**
+			 * 输入时触发
+			 * @param {Object} event
+			 */
+			onInput(event) {
+				let value = event.detail.value;
+				// 判断是否去除空格
+				if (this.trim) {
+					if (typeof(this.trim) === 'boolean' && this.trim) {
+						value = this.trimStr(value)
+					}
+					if (typeof(this.trim) === 'string') {
+						value = this.trimStr(value, this.trim)
+					}
+				};
+				if (this.errMsg) this.errMsg = ''
+				this.val = value
+				// TODO 兼容 vue2
+				this.$emit('input', value);
+				// TODO 兼容 vue3
+				this.$emit('update:modelValue', value)
+			},
+
+			/**
+			 * 外部调用方法
+			 * 获取焦点时触发
+			 * @param {Object} event
+			 */
+			onFocus() {
+				this.$nextTick(() => {
+					this.focused = true
+				})
+				this.$emit('focus', null);
+			},
+
+			_Focus(event) {
+				this.focusShow = true
+				this.$emit('focus', event);
+			},
+
+			/**
+			 * 外部调用方法
+			 * 失去焦点时触发
+			 * @param {Object} event
+			 */
+			onBlur() {
+				this.focused = false
+				this.$emit('focus', null);
+			},
+			_Blur(event) {
+				let value = event.detail.value;
+				this.focusShow = false
+				this.$emit('blur', event);
+				// 根据类型返回值,在event中获取的值理论上讲都是string
+				this.$emit('change', this.val)
+				// 失去焦点时参与表单校验
+				if (this.form && this.formItem) {
+					const {
+						validateTrigger
+					} = this.form
+					if (validateTrigger === 'blur') {
+						this.formItem.onFieldChange()
+					}
+				}
+			},
+
+			/**
+			 * 按下键盘的发送键
+			 * @param {Object} e
+			 */
+			onConfirm(e) {
+				this.$emit('confirm', this.val);
+				this.$emit('change', this.val)
+			},
+
+			/**
+			 * 清理内容
+			 * @param {Object} event
+			 */
+			onClear(event) {
+				this.val = '';
+				// TODO 兼容 vue2
+				this.$emit('input', '');
+				// TODO 兼容 vue2
+				// TODO 兼容 vue3
+				this.$emit('update:modelValue', '')
+				// 点击叉号触发
+				this.$emit('clear')
+			},
+
+			/**
+			 * 去除空格
+			 */
+			trimStr(str, pos = 'both') {
+				if (pos === 'both') {
+					return str.trim();
+				} else if (pos === 'left') {
+					return str.trimLeft();
+				} else if (pos === 'right') {
+					return str.trimRight();
+				} else if (pos === 'start') {
+					return str.trimStart()
+				} else if (pos === 'end') {
+					return str.trimEnd()
+				} else if (pos === 'all') {
+					return str.replace(/\s+/g, '');
+				} else if (pos === 'none') {
+					return str;
+				}
+				return str;
+			}
+		}
+	};
+</script>
+
+<style lang="scss">
+	$uni-error: #e43d33;
+	$uni-border-1: #DCDFE6 !default;
+
+	.uni-easyinput {
+		/* #ifndef APP-NVUE */
+		width: 100%;
+		/* #endif */
+		flex: 1;
+		position: relative;
+		text-align: left;
+		color: #333;
+		font-size: 14px;
+	}
+
+	.uni-easyinput__content {
+		flex: 1;
+		/* #ifndef APP-NVUE */
+		width: 100%;
+		display: flex;
+		box-sizing: border-box;
+		// min-height: 36px;
+		/* #endif */
+		flex-direction: row;
+		align-items: center;
+		// 处理border动画刚开始显示黑色的问题
+		border-color: #fff;
+		transition-property: border-color;
+		transition-duration: 0.3s;
+	}
+
+	.uni-easyinput__content-input {
+		/* #ifndef APP-NVUE */
+		width: auto;
+		/* #endif */
+		position: relative;
+		overflow: hidden;
+		flex: 1;
+		line-height: 1;
+		font-size: 14px;
+		height: 35px;
+		// min-height: 36px;
+	}
+
+	.uni-easyinput__placeholder-class {
+		color: #999;
+		font-size: 12px;
+		// font-weight: 200;
+	}
+
+	.is-textarea {
+		align-items: flex-start;
+	}
+
+	.is-textarea-icon {
+		margin-top: 5px;
+	}
+
+	.uni-easyinput__content-textarea {
+		position: relative;
+		overflow: hidden;
+		flex: 1;
+		line-height: 1.5;
+		font-size: 14px;
+		margin: 6px;
+		margin-left: 0;
+		height: 80px;
+		min-height: 80px;
+		/* #ifndef APP-NVUE */
+		min-height: 80px;
+		width: auto;
+		/* #endif */
+	}
+
+	.input-padding {
+		padding-left: 10px;
+	}
+
+	.content-clear-icon {
+		padding: 0 5px;
+	}
+
+	.label-icon {
+		margin-right: 5px;
+		margin-top: -1px;
+	}
+
+	// 显示边框
+	.is-input-border {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		box-sizing: border-box;
+		/* #endif */
+		flex-direction: row;
+		align-items: center;
+		border: 1px solid $uni-border-1;
+		border-radius: 4px;
+		/* #ifdef MP-ALIPAY */
+		overflow: hidden;
+		/* #endif */
+	}
+
+	.uni-error-message {
+		position: absolute;
+		bottom: -17px;
+		left: 0;
+		line-height: 12px;
+		color: $uni-error;
+		font-size: 12px;
+		text-align: left;
+	}
+
+	.uni-error-msg--boeder {
+		position: relative;
+		bottom: 0;
+		line-height: 22px;
+	}
+
+	.is-input-error-border {
+		border-color: $uni-error;
+
+		.uni-easyinput__placeholder-class {
+			color: mix(#fff, $uni-error, 50%);
+			;
+		}
+	}
+
+
+	.uni-easyinput--border {
+		margin-bottom: 0;
+		padding: 10px 15px;
+		// padding-bottom: 0;
+		border-top: 1px #eee solid;
+	}
+
+	.uni-easyinput-error {
+		padding-bottom: 0;
+	}
+
+	.is-first-border {
+		/* #ifndef APP-NVUE */
+		border: none;
+		/* #endif */
+		/* #ifdef APP-NVUE */
+		border-width: 0;
+		/* #endif */
+	}
+
+	.is-disabled {
+		background-color: #F7F6F6;
+		color: #D5D5D5;
+
+		.uni-easyinput__placeholder-class {
+			color: #D5D5D5;
+			font-size: 12px;
+		}
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-easyinput/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-easyinput/package.json
new file mode 100644
index 000000000..3cc793e61
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-easyinput/package.json
@@ -0,0 +1,90 @@
+{
+  "id": "uni-easyinput",
+  "displayName": "uni-easyinput 增强输入框",
+  "version": "1.1.0",
+  "description": "Easyinput 组件是对原生input组件的增强",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "input",
+    "uni-easyinput",
+    "输入框"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": [
+			"uni-scss",
+      "uni-icons"
+    ],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-easyinput/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-easyinput/readme.md
new file mode 100644
index 000000000..f1faf8fbb
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-easyinput/readme.md
@@ -0,0 +1,11 @@
+
+
+### Easyinput 增强输入框
+> **组件名:uni-easyinput**
+> 代码块: `uEasyinput`
+
+
+easyinput 组件是对原生input组件的增强 ,是专门为配合表单组件[uni-forms](https://ext.dcloud.net.cn/plugin?id=2773)而设计的,easyinput 内置了边框,图标等,同时包含 input 所有功能
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-easyinput)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-fab/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-fab/changelog.md
new file mode 100644
index 000000000..24e26b167
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-fab/changelog.md
@@ -0,0 +1,17 @@
+## 1.2.2(2021-12-29)
+- 更新 组件依赖
+## 1.2.1(2021-11-19)
+- 修复 阴影颜色不正确的bug
+## 1.2.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-fab](https://uniapp.dcloud.io/component/uniui/uni-fab)
+## 1.1.1(2021-11-09) 
+- 新增 提供组件设计资源,组件样式调整
+## 1.1.0(2021-07-30)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.0.7(2021-05-12)
+- 新增 组件示例地址
+## 1.0.6(2021-02-05)
+- 调整为uni_modules目录规范
+- 优化 按钮背景色调整
+- 优化 兼容pc端
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-fab/components/uni-fab/uni-fab.vue b/yudao-ui-admin-uniapp/uni_modules/uni-fab/components/uni-fab/uni-fab.vue
new file mode 100644
index 000000000..bef97f117
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-fab/components/uni-fab/uni-fab.vue
@@ -0,0 +1,475 @@
+<template>
+	<view class="uni-cursor-point">
+		<view v-if="popMenu && (leftBottom||rightBottom||leftTop||rightTop) && content.length > 0" :class="{
+        'uni-fab--leftBottom': leftBottom,
+        'uni-fab--rightBottom': rightBottom,
+        'uni-fab--leftTop': leftTop,
+        'uni-fab--rightTop': rightTop
+      }" class="uni-fab">
+			<view :class="{
+          'uni-fab__content--left': horizontal === 'left',
+          'uni-fab__content--right': horizontal === 'right',
+          'uni-fab__content--flexDirection': direction === 'vertical',
+          'uni-fab__content--flexDirectionStart': flexDirectionStart,
+          'uni-fab__content--flexDirectionEnd': flexDirectionEnd,
+		  'uni-fab__content--other-platform': !isAndroidNvue
+        }" :style="{ width: boxWidth, height: boxHeight, backgroundColor: styles.backgroundColor }"
+				class="uni-fab__content" elevation="5">
+				<view v-if="flexDirectionStart || horizontalLeft" class="uni-fab__item uni-fab__item--first" />
+				<view v-for="(item, index) in content" :key="index" :class="{ 'uni-fab__item--active': isShow }"
+					class="uni-fab__item" @click="_onItemClick(index, item)">
+					<image :src="item.active ? item.selectedIconPath : item.iconPath" class="uni-fab__item-image"
+						mode="aspectFit" />
+					<text class="uni-fab__item-text"
+						:style="{ color: item.active ? styles.selectedColor : styles.color }">{{ item.text }}</text>
+				</view>
+				<view v-if="flexDirectionEnd || horizontalRight" class="uni-fab__item uni-fab__item--first" />
+			</view>
+		</view>
+		<view :class="{
+		  'uni-fab__circle--leftBottom': leftBottom,
+		  'uni-fab__circle--rightBottom': rightBottom,
+		  'uni-fab__circle--leftTop': leftTop,
+		  'uni-fab__circle--rightTop': rightTop,
+		  'uni-fab__content--other-platform': !isAndroidNvue
+		}" class="uni-fab__circle uni-fab__plus" :style="{ 'background-color': styles.buttonColor }" @click="_onClick">
+			<uni-icons class="fab-circle-icon" type="plusempty" :color="styles.iconColor" size="32"
+				:class="{'uni-fab__plus--active': isShow && content.length > 0}"></uni-icons>
+			<!-- <view class="fab-circle-v"  :class="{'uni-fab__plus--active': isShow && content.length > 0}"></view>
+			<view class="fab-circle-h" :class="{'uni-fab__plus--active': isShow  && content.length > 0}"></view> -->
+		</view>
+	</view>
+</template>
+
+<script>
+	let platform = 'other'
+	// #ifdef APP-NVUE
+	platform = uni.getSystemInfoSync().platform
+	// #endif
+
+	/**
+	 * Fab 悬浮按钮
+	 * @description 点击可展开一个图形按钮菜单
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=144
+	 * @property {Object} pattern 可选样式配置项
+	 * @property {Object} horizontal = [left | right] 水平对齐方式
+	 * 	@value left 左对齐
+	 * 	@value right 右对齐
+	 * @property {Object} vertical = [bottom | top] 垂直对齐方式
+	 * 	@value bottom 下对齐
+	 * 	@value top 上对齐
+	 * @property {Object} direction = [horizontal | vertical] 展开菜单显示方式
+	 * 	@value horizontal 水平显示
+	 * 	@value vertical 垂直显示
+	 * @property {Array} content 展开菜单内容配置项
+	 * @property {Boolean} popMenu 是否使用弹出菜单
+	 * @event {Function} trigger 展开菜单点击事件,返回点击信息
+	 * @event {Function} fabClick 悬浮按钮点击事件
+	 */
+	export default {
+		name: 'UniFab',
+		emits: ['fabClick', 'trigger'],
+		props: {
+			pattern: {
+				type: Object,
+				default () {
+					return {}
+				}
+			},
+			horizontal: {
+				type: String,
+				default: 'left'
+			},
+			vertical: {
+				type: String,
+				default: 'bottom'
+			},
+			direction: {
+				type: String,
+				default: 'horizontal'
+			},
+			content: {
+				type: Array,
+				default () {
+					return []
+				}
+			},
+			show: {
+				type: Boolean,
+				default: false
+			},
+			popMenu: {
+				type: Boolean,
+				default: true
+			}
+		},
+		data() {
+			return {
+				fabShow: false,
+				isShow: false,
+				isAndroidNvue: platform === 'android',
+				styles: {
+					color: '#3c3e49',
+					selectedColor: '#007AFF',
+					backgroundColor: '#fff',
+					buttonColor: '#007AFF',
+					iconColor: '#fff'
+				}
+			}
+		},
+		computed: {
+			contentWidth(e) {
+				return (this.content.length + 1) * 55 + 15 + 'px'
+			},
+			contentWidthMin() {
+				return '55px'
+			},
+			// 动态计算宽度
+			boxWidth() {
+				return this.getPosition(3, 'horizontal')
+			},
+			// 动态计算高度
+			boxHeight() {
+				return this.getPosition(3, 'vertical')
+			},
+			// 计算左下位置
+			leftBottom() {
+				return this.getPosition(0, 'left', 'bottom')
+			},
+			// 计算右下位置
+			rightBottom() {
+				return this.getPosition(0, 'right', 'bottom')
+			},
+			// 计算左上位置
+			leftTop() {
+				return this.getPosition(0, 'left', 'top')
+			},
+			rightTop() {
+				return this.getPosition(0, 'right', 'top')
+			},
+			flexDirectionStart() {
+				return this.getPosition(1, 'vertical', 'top')
+			},
+			flexDirectionEnd() {
+				return this.getPosition(1, 'vertical', 'bottom')
+			},
+			horizontalLeft() {
+				return this.getPosition(2, 'horizontal', 'left')
+			},
+			horizontalRight() {
+				return this.getPosition(2, 'horizontal', 'right')
+			}
+		},
+		watch: {
+			pattern: {
+				handler(val, oldVal) {
+					this.styles = Object.assign({}, this.styles, val)
+				},
+				deep: true
+			}
+		},
+		created() {
+			this.isShow = this.show
+			if (this.top === 0) {
+				this.fabShow = true
+			}
+			// 初始化样式
+			this.styles = Object.assign({}, this.styles, this.pattern)
+		},
+		methods: {
+			_onClick() {
+				this.$emit('fabClick')
+				if (!this.popMenu) {
+					return
+				}
+				this.isShow = !this.isShow
+			},
+			open() {
+				this.isShow = true
+			},
+			close() {
+				this.isShow = false
+			},
+			/**
+			 * 按钮点击事件
+			 */
+			_onItemClick(index, item) {
+				this.$emit('trigger', {
+					index,
+					item
+				})
+			},
+			/**
+			 * 获取 位置信息
+			 */
+			getPosition(types, paramA, paramB) {
+				if (types === 0) {
+					return this.horizontal === paramA && this.vertical === paramB
+				} else if (types === 1) {
+					return this.direction === paramA && this.vertical === paramB
+				} else if (types === 2) {
+					return this.direction === paramA && this.horizontal === paramB
+				} else {
+					return this.isShow && this.direction === paramA ? this.contentWidth : this.contentWidthMin
+				}
+			}
+		}
+	}
+</script>
+
+<style lang="scss" >
+	$uni-shadow-base:0 1px 5px 2px rgba($color: #000000, $alpha: 0.3) !default;
+
+	.uni-fab {
+		position: fixed;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		justify-content: center;
+		align-items: center;
+		z-index: 10;
+		border-radius: 45px;
+		box-shadow: $uni-shadow-base;
+	}
+
+	.uni-cursor-point {
+		/* #ifdef H5 */
+		cursor: pointer;
+		/* #endif */
+	}
+
+	.uni-fab--active {
+		opacity: 1;
+	}
+
+	.uni-fab--leftBottom {
+		left: 15px;
+		bottom: 30px;
+		/* #ifdef H5 */
+		left: calc(15px + var(--window-left));
+		bottom: calc(30px + var(--window-bottom));
+		/* #endif */
+		// padding: 10px;
+	}
+
+	.uni-fab--leftTop {
+		left: 15px;
+		top: 30px;
+		/* #ifdef H5 */
+		left: calc(15px + var(--window-left));
+		top: calc(30px + var(--window-top));
+		/* #endif */
+		// padding: 10px;
+	}
+
+	.uni-fab--rightBottom {
+		right: 15px;
+		bottom: 30px;
+		/* #ifdef H5 */
+		right: calc(15px + var(--window-right));
+		bottom: calc(30px + var(--window-bottom));
+		/* #endif */
+		// padding: 10px;
+	}
+
+	.uni-fab--rightTop {
+		right: 15px;
+		top: 30px;
+		/* #ifdef H5 */
+		right: calc(15px + var(--window-right));
+		top: calc(30px + var(--window-top));
+		/* #endif */
+		// padding: 10px;
+	}
+
+	.uni-fab__circle {
+		position: fixed;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		justify-content: center;
+		align-items: center;
+		width: 55px;
+		height: 55px;
+		background-color: #3c3e49;
+		border-radius: 45px;
+		z-index: 11;
+		// box-shadow: $uni-shadow-base;
+	}
+
+	.uni-fab__circle--leftBottom {
+		left: 15px;
+		bottom: 30px;
+		/* #ifdef H5 */
+		left: calc(15px + var(--window-left));
+		bottom: calc(30px + var(--window-bottom));
+		/* #endif */
+	}
+
+	.uni-fab__circle--leftTop {
+		left: 15px;
+		top: 30px;
+		/* #ifdef H5 */
+		left: calc(15px + var(--window-left));
+		top: calc(30px + var(--window-top));
+		/* #endif */
+	}
+
+	.uni-fab__circle--rightBottom {
+		right: 15px;
+		bottom: 30px;
+		/* #ifdef H5 */
+		right: calc(15px + var(--window-right));
+		bottom: calc(30px + var(--window-bottom));
+		/* #endif */
+	}
+
+	.uni-fab__circle--rightTop {
+		right: 15px;
+		top: 30px;
+		/* #ifdef H5 */
+		right: calc(15px + var(--window-right));
+		top: calc(30px + var(--window-top));
+		/* #endif */
+	}
+
+	.uni-fab__circle--left {
+		left: 0;
+	}
+
+	.uni-fab__circle--right {
+		right: 0;
+	}
+
+	.uni-fab__circle--top {
+		top: 0;
+	}
+
+	.uni-fab__circle--bottom {
+		bottom: 0;
+	}
+
+	.uni-fab__plus {
+		font-weight: bold;
+	}
+
+	// .fab-circle-v {
+	// 	position: absolute;
+	// 	width: 2px;
+	// 	height: 24px;
+	// 	left: 0;
+	// 	top: 0;
+	// 	right: 0;
+	// 	bottom: 0;
+	// 	/* #ifndef APP-NVUE */
+	// 	margin: auto;
+	// 	/* #endif */
+	// 	background-color: white;
+	// 	transform: rotate(0deg);
+	// 	transition: transform 0.3s;
+	// }
+
+	// .fab-circle-h {
+	// 	position: absolute;
+	// 	width: 24px;
+	// 	height: 2px;
+	// 	left: 0;
+	// 	top: 0;
+	// 	right: 0;
+	// 	bottom: 0;
+	// 	/* #ifndef APP-NVUE */
+	// 	margin: auto;
+	// 	/* #endif */
+	// 	background-color: white;
+	// 	transform: rotate(0deg);
+	// 	transition: transform 0.3s;
+	// }
+
+	.fab-circle-icon {
+		transform: rotate(0deg);
+		transition: transform 0.3s;
+		font-weight: 200;
+	}
+
+	.uni-fab__plus--active {
+		transform: rotate(135deg);
+	}
+
+	.uni-fab__content {
+		/* #ifndef APP-NVUE */
+		box-sizing: border-box;
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		border-radius: 55px;
+		overflow: hidden;
+		transition-property: width, height;
+		transition-duration: 0.2s;
+		width: 55px;
+		border-color: #DDDDDD;
+		border-width: 1rpx;
+		border-style: solid;
+	}
+
+	.uni-fab__content--other-platform {
+		border-width: 0px;
+		box-shadow: $uni-shadow-base;
+	}
+
+	.uni-fab__content--left {
+		justify-content: flex-start;
+	}
+
+	.uni-fab__content--right {
+		justify-content: flex-end;
+	}
+
+	.uni-fab__content--flexDirection {
+		flex-direction: column;
+		justify-content: flex-end;
+	}
+
+	.uni-fab__content--flexDirectionStart {
+		flex-direction: column;
+		justify-content: flex-start;
+	}
+
+	.uni-fab__content--flexDirectionEnd {
+		flex-direction: column;
+		justify-content: flex-end;
+	}
+
+	.uni-fab__item {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		justify-content: center;
+		align-items: center;
+		width: 55px;
+		height: 55px;
+		opacity: 0;
+		transition: opacity 0.2s;
+	}
+
+	.uni-fab__item--active {
+		opacity: 1;
+	}
+
+	.uni-fab__item-image {
+		width: 20px;
+		height: 20px;
+		margin-bottom: 4px;
+	}
+
+	.uni-fab__item-text {
+		color: #FFFFFF;
+		font-size: 12px;
+		line-height: 12px;
+		margin-top: 2px;
+	}
+
+	.uni-fab__item--first {
+		width: 55px;
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-fab/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-fab/package.json
new file mode 100644
index 000000000..0f27daa58
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-fab/package.json
@@ -0,0 +1,87 @@
+{
+  "id": "uni-fab",
+  "displayName": "uni-fab 悬浮按钮",
+  "version": "1.2.2",
+  "description": "悬浮按钮 fab button ,点击可展开一个图标按钮菜单。",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "按钮",
+    "悬浮按钮",
+    "fab"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": ["uni-scss","uni-icons"],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-fab/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-fab/readme.md
new file mode 100644
index 000000000..9a444e880
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-fab/readme.md
@@ -0,0 +1,9 @@
+## Fab 悬浮按钮
+> **组件名:uni-fab**
+> 代码块: `uFab`
+
+
+点击可展开一个图形按钮菜单
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-fab)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-fav/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-fav/changelog.md
new file mode 100644
index 000000000..d8a08d436
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-fav/changelog.md
@@ -0,0 +1,19 @@
+## 1.2.1(2022-05-30)
+- 新增 stat 属性 ,是否开启uni统计功能
+## 1.2.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-fav](https://uniapp.dcloud.io/component/uniui/uni-fav)
+## 1.1.1(2021-08-24)
+- 新增 支持国际化
+## 1.1.0(2021-07-13)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.0.6(2021-05-12)
+- 新增 组件示例地址
+## 1.0.5(2021-04-21)
+- 优化 添加依赖 uni-icons, 导入后自动下载依赖
+## 1.0.4(2021-02-05)
+- 优化 组件引用关系,通过uni_modules引用组件
+## 1.0.3(2021-02-05)
+- 优化 组件引用关系,通过uni_modules引用组件
+## 1.0.2(2021-02-05)
+- 调整为uni_modules目录规范
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-fav/components/uni-fav/i18n/en.json b/yudao-ui-admin-uniapp/uni_modules/uni-fav/components/uni-fav/i18n/en.json
new file mode 100644
index 000000000..9a0759e02
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-fav/components/uni-fav/i18n/en.json
@@ -0,0 +1,4 @@
+{
+	"uni-fav.collect": "collect",
+	"uni-fav.collected": "collected"
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-fav/components/uni-fav/i18n/index.js b/yudao-ui-admin-uniapp/uni_modules/uni-fav/components/uni-fav/i18n/index.js
new file mode 100644
index 000000000..de7509c87
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-fav/components/uni-fav/i18n/index.js
@@ -0,0 +1,8 @@
+import en from './en.json'
+import zhHans from './zh-Hans.json'
+import zhHant from './zh-Hant.json'
+export default {
+	en,
+	'zh-Hans': zhHans,
+	'zh-Hant': zhHant
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-fav/components/uni-fav/i18n/zh-Hans.json b/yudao-ui-admin-uniapp/uni_modules/uni-fav/components/uni-fav/i18n/zh-Hans.json
new file mode 100644
index 000000000..67c89bfc7
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-fav/components/uni-fav/i18n/zh-Hans.json
@@ -0,0 +1,4 @@
+{
+	"uni-fav.collect": "收藏",
+	"uni-fav.collected": "已收藏"
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-fav/components/uni-fav/i18n/zh-Hant.json b/yudao-ui-admin-uniapp/uni_modules/uni-fav/components/uni-fav/i18n/zh-Hant.json
new file mode 100644
index 000000000..67c89bfc7
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-fav/components/uni-fav/i18n/zh-Hant.json
@@ -0,0 +1,4 @@
+{
+	"uni-fav.collect": "收藏",
+	"uni-fav.collected": "已收藏"
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-fav/components/uni-fav/uni-fav.vue b/yudao-ui-admin-uniapp/uni_modules/uni-fav/components/uni-fav/uni-fav.vue
new file mode 100644
index 000000000..d2c58df9e
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-fav/components/uni-fav/uni-fav.vue
@@ -0,0 +1,161 @@
+<template>
+	<view :class="[circle === true || circle === 'true' ? 'uni-fav--circle' : '']" :style="[{ backgroundColor: checked ? bgColorChecked : bgColor }]"
+	 @click="onClick" class="uni-fav">
+		<!-- #ifdef MP-ALIPAY -->
+		<view class="uni-fav-star" v-if="!checked && (star === true || star === 'true')">
+			<uni-icons :color="fgColor" :style="{color: checked ? fgColorChecked : fgColor}" size="14" type="star-filled" />
+		</view>
+		<!-- #endif -->
+		<!-- #ifndef MP-ALIPAY -->
+		<uni-icons :color="fgColor" :style="{color: checked ? fgColorChecked : fgColor}" class="uni-fav-star" size="14" type="star-filled"
+		 v-if="!checked && (star === true || star === 'true')" />
+		<!-- #endif -->
+		<text :style="{color: checked ? fgColorChecked : fgColor}" class="uni-fav-text">{{ checked ? contentFav : contentDefault }}</text>
+	</view>
+</template>
+
+<script>
+
+	/**
+	 * Fav 收藏按钮
+	 * @description 用于收藏功能,可点击切换选中、不选中的状态
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=864
+	 * @property {Boolean} star = [true|false] 按钮是否带星星
+	 * @property {String} bgColor 未收藏时的背景色
+	 * @property {String} bgColorChecked 已收藏时的背景色
+	 * @property {String} fgColor 未收藏时的文字颜色
+	 * @property {String} fgColorChecked 已收藏时的文字颜色
+	 * @property {Boolean} circle = [true|false] 是否为圆角
+	 * @property {Boolean} checked = [true|false] 是否为已收藏
+	 * @property {Object} contentText = [true|false] 收藏按钮文字
+	 * @property {Boolean} stat 是否开启统计功能
+	 * @event {Function} click 点击 fav按钮触发事件
+	 * @example <uni-fav :checked="true"/>
+	 */
+
+	import {
+		initVueI18n
+	} from '@dcloudio/uni-i18n'
+	import messages from './i18n/index.js'
+	const {	t	} = initVueI18n(messages)
+
+	export default {
+		name: "UniFav",
+		// TODO 兼容 vue3,需要注册事件
+		emits: ['click'],
+		props: {
+			star: {
+				type: [Boolean, String],
+				default: true
+			},
+			bgColor: {
+				type: String,
+				default: "#eeeeee"
+			},
+			fgColor: {
+				type: String,
+				default: "#666666"
+			},
+			bgColorChecked: {
+				type: String,
+				default: "#007aff"
+			},
+			fgColorChecked: {
+				type: String,
+				default: "#FFFFFF"
+			},
+			circle: {
+				type: [Boolean, String],
+				default: false
+			},
+			checked: {
+				type: Boolean,
+				default: false
+			},
+			contentText: {
+				type: Object,
+				default () {
+					return {
+						contentDefault: "",
+						contentFav: ""
+					};
+				}
+			},
+			stat:{
+				type: Boolean,
+				default: false
+			}
+		},
+		computed: {
+			contentDefault() {
+				return this.contentText.contentDefault || t("uni-fav.collect")
+			},
+			contentFav() {
+				return this.contentText.contentFav || t("uni-fav.collected")
+			},
+		},
+		watch: {
+			checked() {
+				if (uni.report && this.stat) {
+					if (this.checked) {
+						uni.report("收藏", "收藏");
+					} else {
+						uni.report("取消收藏", "取消收藏");
+					}
+				}
+			}
+		},
+		methods: {
+			onClick() {
+				this.$emit("click");
+			}
+		}
+	};
+</script>
+
+<style lang="scss" >
+	$fav-height: 25px;
+
+	.uni-fav {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		align-items: center;
+		justify-content: center;
+		width: 60px;
+		height: $fav-height;
+		line-height: $fav-height;
+		text-align: center;
+		border-radius: 3px;
+		/* #ifdef H5 */
+		cursor: pointer;
+		/* #endif */
+	}
+
+	.uni-fav--circle {
+		border-radius: 30px;
+	}
+
+	.uni-fav-star {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		height: $fav-height;
+		line-height: 24px;
+		margin-right: 3px;
+		align-items: center;
+		justify-content: center;
+	}
+
+	.uni-fav-text {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		height: $fav-height;
+		line-height: $fav-height;
+		align-items: center;
+		justify-content: center;
+		font-size: 12px;
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-fav/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-fav/package.json
new file mode 100644
index 000000000..cc1469716
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-fav/package.json
@@ -0,0 +1,89 @@
+{
+  "id": "uni-fav",
+  "displayName": "uni-fav 收藏按钮",
+  "version": "1.2.1",
+  "description": " Fav 收藏组件,可自定义颜色、大小。",
+  "keywords": [
+    "fav",
+    "uni-ui",
+    "uniui",
+    "收藏"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": [
+			"uni-scss",
+			"uni-icons"
+		],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-fav/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-fav/readme.md
new file mode 100644
index 000000000..4de125d28
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-fav/readme.md
@@ -0,0 +1,10 @@
+
+
+## Fav 收藏按钮
+> **组件名:uni-fav**
+> 代码块: `uFav`
+
+用于收藏功能,可点击切换选中、不选中的状态。
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-fav)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-file-picker/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-file-picker/changelog.md
new file mode 100644
index 000000000..5c8102682
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-file-picker/changelog.md
@@ -0,0 +1,63 @@
+## 1.0.2(2022-07-04)
+- 修复 在uni-forms下样式不生效的bug
+## 1.0.1(2021-11-23)
+- 修复 参数为对象的情况下,url在某些情况显示错误的bug
+## 1.0.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-file-picker](https://uniapp.dcloud.io/component/uniui/uni-file-picker)
+## 0.2.16(2021-11-08)
+- 修复 传入空对象 ,显示错误的Bug
+## 0.2.15(2021-08-30)
+- 修复 return-type="object" 时且存在v-model时,无法删除文件的Bug
+## 0.2.14(2021-08-23)
+- 新增 参数中返回 fileID 字段
+## 0.2.13(2021-08-23)
+- 修复 腾讯云传入fileID 不能回显的bug
+- 修复 选择图片后,不能放大的问题
+## 0.2.12(2021-08-17)
+- 修复 由于 0.2.11 版本引起的不能回显图片的Bug
+## 0.2.11(2021-08-16)
+- 新增 clearFiles(index) 方法,可以手动删除指定文件
+- 修复 v-model 值设为 null 报错的Bug
+## 0.2.10(2021-08-13)
+- 修复 return-type="object" 时,无法删除文件的Bug
+## 0.2.9(2021-08-03)
+- 修复 auto-upload 属性失效的Bug
+## 0.2.8(2021-07-31)
+- 修复 fileExtname属性不指定值报错的Bug
+## 0.2.7(2021-07-31)
+- 修复 在某种场景下图片不回显的Bug
+## 0.2.6(2021-07-30)
+- 修复 return-type为object下,返回值不正确的Bug
+## 0.2.5(2021-07-30)
+- 修复(重要) H5 平台下如果和uni-forms组件一同使用导致页面卡死的问题
+## 0.2.3(2021-07-28)
+- 优化 调整示例代码
+## 0.2.2(2021-07-27)
+- 修复 vue3 下赋值错误的Bug
+- 优化 h5平台下上传文件导致页面卡死的问题
+## 0.2.0(2021-07-13)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 0.1.1(2021-07-02)
+- 修复 sourceType 缺少默认值导致 ios 无法选择文件
+## 0.1.0(2021-06-30)
+- 优化 解耦与uniCloud的强绑定关系 ,如不绑定服务空间,默认autoUpload为false且不可更改
+## 0.0.11(2021-06-30)
+- 修复 由 0.0.10 版本引发的 returnType 属性失效的问题
+## 0.0.10(2021-06-29)
+- 优化 文件上传后进度条消失时机
+## 0.0.9(2021-06-29)
+- 修复 在uni-forms 中,删除文件 ,获取的值不对的Bug
+## 0.0.8(2021-06-15)
+- 修复 删除文件时无法触发 v-model 的Bug
+## 0.0.7(2021-05-12)
+- 新增 组件示例地址
+## 0.0.6(2021-04-09)
+- 修复 选择的文件非 file-extname 字段指定的扩展名报错的Bug
+## 0.0.5(2021-04-09)
+- 优化 更新组件示例
+## 0.0.4(2021-04-09)
+- 优化 file-extname 字段支持字符串写法,多个扩展名需要用逗号分隔
+## 0.0.3(2021-02-05)
+- 调整为uni_modules目录规范
+- 修复 微信小程序不指定 fileExtname 属性选择失败的Bug
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-file-picker/components/uni-file-picker/choose-and-upload-file.js b/yudao-ui-admin-uniapp/uni_modules/uni-file-picker/components/uni-file-picker/choose-and-upload-file.js
new file mode 100644
index 000000000..24a07f578
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-file-picker/components/uni-file-picker/choose-and-upload-file.js
@@ -0,0 +1,224 @@
+'use strict';
+
+const ERR_MSG_OK = 'chooseAndUploadFile:ok';
+const ERR_MSG_FAIL = 'chooseAndUploadFile:fail';
+
+function chooseImage(opts) {
+	const {
+		count,
+		sizeType = ['original', 'compressed'],
+		sourceType = ['album', 'camera'],
+		extension
+	} = opts
+	return new Promise((resolve, reject) => {
+		uni.chooseImage({
+			count,
+			sizeType,
+			sourceType,
+			extension,
+			success(res) {
+				resolve(normalizeChooseAndUploadFileRes(res, 'image'));
+			},
+			fail(res) {
+				reject({
+					errMsg: res.errMsg.replace('chooseImage:fail', ERR_MSG_FAIL),
+				});
+			},
+		});
+	});
+}
+
+function chooseVideo(opts) {
+	const {
+		camera,
+		compressed,
+		maxDuration,
+		sourceType = ['album', 'camera'],
+		extension
+	} = opts;
+	return new Promise((resolve, reject) => {
+		uni.chooseVideo({
+			camera,
+			compressed,
+			maxDuration,
+			sourceType,
+			extension,
+			success(res) {
+				const {
+					tempFilePath,
+					duration,
+					size,
+					height,
+					width
+				} = res;
+				resolve(normalizeChooseAndUploadFileRes({
+					errMsg: 'chooseVideo:ok',
+					tempFilePaths: [tempFilePath],
+					tempFiles: [
+					{
+						name: (res.tempFile && res.tempFile.name) || '',
+						path: tempFilePath,
+						size,
+						type: (res.tempFile && res.tempFile.type) || '',
+						width,
+						height,
+						duration,
+						fileType: 'video',
+						cloudPath: '',
+					}, ],
+				}, 'video'));
+			},
+			fail(res) {
+				reject({
+					errMsg: res.errMsg.replace('chooseVideo:fail', ERR_MSG_FAIL),
+				});
+			},
+		});
+	});
+}
+
+function chooseAll(opts) {
+	const {
+		count,
+		extension
+	} = opts;
+	return new Promise((resolve, reject) => {
+		let chooseFile = uni.chooseFile;
+		if (typeof wx !== 'undefined' &&
+			typeof wx.chooseMessageFile === 'function') {
+			chooseFile = wx.chooseMessageFile;
+		}
+		if (typeof chooseFile !== 'function') {
+			return reject({
+				errMsg: ERR_MSG_FAIL + ' 请指定 type 类型,该平台仅支持选择 image 或 video。',
+			});
+		}
+		chooseFile({
+			type: 'all',
+			count,
+			extension,
+			success(res) {
+				resolve(normalizeChooseAndUploadFileRes(res));
+			},
+			fail(res) {
+				reject({
+					errMsg: res.errMsg.replace('chooseFile:fail', ERR_MSG_FAIL),
+				});
+			},
+		});
+	});
+}
+
+function normalizeChooseAndUploadFileRes(res, fileType) {
+	res.tempFiles.forEach((item, index) => {
+		if (!item.name) {
+			item.name = item.path.substring(item.path.lastIndexOf('/') + 1);
+		}
+		if (fileType) {
+			item.fileType = fileType;
+		}
+		item.cloudPath =
+			Date.now() + '_' + index + item.name.substring(item.name.lastIndexOf('.'));
+	});
+	if (!res.tempFilePaths) {
+		res.tempFilePaths = res.tempFiles.map((file) => file.path);
+	}
+	return res;
+}
+
+function uploadCloudFiles(files, max = 5, onUploadProgress) {
+	files = JSON.parse(JSON.stringify(files))
+	const len = files.length
+	let count = 0
+	let self = this
+	return new Promise(resolve => {
+		while (count < max) {
+			next()
+		}
+
+		function next() {
+			let cur = count++
+			if (cur >= len) {
+				!files.find(item => !item.url && !item.errMsg) && resolve(files)
+				return
+			}
+			const fileItem = files[cur]
+			const index = self.files.findIndex(v => v.uuid === fileItem.uuid)
+			fileItem.url = ''
+			delete fileItem.errMsg
+
+			uniCloud
+				.uploadFile({
+					filePath: fileItem.path,
+					cloudPath: fileItem.cloudPath,
+					fileType: fileItem.fileType,
+					onUploadProgress: res => {
+						res.index = index
+						onUploadProgress && onUploadProgress(res)
+					}
+				})
+				.then(res => {
+					fileItem.url = res.fileID
+					fileItem.index = index
+					if (cur < len) {
+						next()
+					}
+				})
+				.catch(res => {
+					fileItem.errMsg = res.errMsg || res.message
+					fileItem.index = index
+					if (cur < len) {
+						next()
+					}
+				})
+		}
+	})
+}
+
+
+
+
+
+function uploadFiles(choosePromise, {
+	onChooseFile,
+	onUploadProgress
+}) {
+	return choosePromise
+		.then((res) => {
+			if (onChooseFile) {
+				const customChooseRes = onChooseFile(res);
+				if (typeof customChooseRes !== 'undefined') {
+					return Promise.resolve(customChooseRes).then((chooseRes) => typeof chooseRes === 'undefined' ?
+						res : chooseRes);
+				}
+			}
+			return res;
+		})
+		.then((res) => {
+			if (res === false) {
+				return {
+					errMsg: ERR_MSG_OK,
+					tempFilePaths: [],
+					tempFiles: [],
+				};
+			}
+			return res
+		})
+}
+
+function chooseAndUploadFile(opts = {
+	type: 'all'
+}) {
+	if (opts.type === 'image') {
+		return uploadFiles(chooseImage(opts), opts);
+	}
+	else if (opts.type === 'video') {
+		return uploadFiles(chooseVideo(opts), opts);
+	}
+	return uploadFiles(chooseAll(opts), opts);
+}
+
+export {
+	chooseAndUploadFile,
+	uploadCloudFiles
+};
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue b/yudao-ui-admin-uniapp/uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue
new file mode 100644
index 000000000..0928a41af
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue
@@ -0,0 +1,656 @@
+<template>
+	<view class="uni-file-picker">
+		<view v-if="title" class="uni-file-picker__header">
+			<text class="file-title">{{ title }}</text>
+			<text class="file-count">{{ filesList.length }}/{{ limitLength }}</text>
+		</view>
+		<upload-image v-if="fileMediatype === 'image' && showType === 'grid'" :readonly="readonly"
+			:image-styles="imageStyles" :files-list="filesList" :limit="limitLength" :disablePreview="disablePreview"
+			:delIcon="delIcon" @uploadFiles="uploadFiles" @choose="choose" @delFile="delFile">
+			<slot>
+				<view class="is-add">
+					<view class="icon-add"></view>
+					<view class="icon-add rotate"></view>
+				</view>
+			</slot>
+		</upload-image>
+		<upload-file v-if="fileMediatype !== 'image' || showType !== 'grid'" :readonly="readonly"
+			:list-styles="listStyles" :files-list="filesList" :showType="showType" :delIcon="delIcon"
+			@uploadFiles="uploadFiles" @choose="choose" @delFile="delFile">
+			<slot><button type="primary" size="mini">选择文件</button></slot>
+		</upload-file>
+	</view>
+</template>
+
+<script>
+	import {
+		chooseAndUploadFile,
+		uploadCloudFiles
+	} from './choose-and-upload-file.js'
+	import {
+		get_file_ext,
+		get_extname,
+		get_files_and_is_max,
+		get_file_info,
+		get_file_data
+	} from './utils.js'
+	import uploadImage from './upload-image.vue'
+	import uploadFile from './upload-file.vue'
+	let fileInput = null
+	/**
+	 * FilePicker 文件选择上传
+	 * @description 文件选择上传组件,可以选择图片、视频等任意文件并上传到当前绑定的服务空间
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=4079
+	 * @property {Object|Array}	value	组件数据,通常用来回显 ,类型由return-type属性决定
+	 * @property {Boolean}	disabled = [true|false]	组件禁用
+	 * 	@value true 	禁用
+	 * 	@value false 	取消禁用
+	 * @property {Boolean}	readonly = [true|false]	组件只读,不可选择,不显示进度,不显示删除按钮
+	 * 	@value true 	只读
+	 * 	@value false 	取消只读
+	 * @property {String}	return-type = [array|object]	限制 value 格式,当为 object 时 ,组件只能单选,且会覆盖
+	 * 	@value array	规定 value 属性的类型为数组
+	 * 	@value object	规定 value 属性的类型为对象
+	 * @property {Boolean}	disable-preview = [true|false]	禁用图片预览,仅 mode:grid 时生效
+	 * 	@value true 	禁用图片预览
+	 * 	@value false 	取消禁用图片预览
+	 * @property {Boolean}	del-icon = [true|false]	是否显示删除按钮
+	 * 	@value true 	显示删除按钮
+	 * 	@value false 	不显示删除按钮
+	 * @property {Boolean}	auto-upload = [true|false]	是否自动上传,值为true则只触发@select,可自行上传
+	 * 	@value true 	自动上传
+	 * 	@value false 	取消自动上传
+	 * @property {Number|String}	limit	最大选择个数 ,h5 会自动忽略多选的部分
+	 * @property {String}	title	组件标题,右侧显示上传计数
+	 * @property {String}	mode = [list|grid]	选择文件后的文件列表样式
+	 * 	@value list 	列表显示
+	 * 	@value grid 	宫格显示
+	 * @property {String}	file-mediatype = [image|video|all]	选择文件类型
+	 * 	@value image	只选择图片
+	 * 	@value video	只选择视频
+	 * 	@value all		选择所有文件
+	 * @property {Array}	file-extname	选择文件后缀,根据 file-mediatype 属性而不同
+	 * @property {Object}	list-style	mode:list 时的样式
+	 * @property {Object}	image-styles	选择文件后缀,根据 file-mediatype 属性而不同
+	 * @event {Function} select 	选择文件后触发
+	 * @event {Function} progress 文件上传时触发
+	 * @event {Function} success 	上传成功触发
+	 * @event {Function} fail 		上传失败触发
+	 * @event {Function} delete 	文件从列表移除时触发
+	 */
+	export default {
+		name: 'uniFilePicker',
+		components: {
+			uploadImage,
+			uploadFile
+		},
+		options: {
+			virtualHost: true
+		},
+		emits: ['select', 'success', 'fail', 'progress', 'delete', 'update:modelValue', 'input'],
+		props: {
+			// #ifdef VUE3
+			modelValue: {
+				type: [Array, Object],
+				default () {
+					return []
+				}
+			},
+			// #endif
+
+			// #ifndef VUE3
+			value: {
+				type: [Array, Object],
+				default () {
+					return []
+				}
+			},
+			// #endif
+
+			disabled: {
+				type: Boolean,
+				default: false
+			},
+			disablePreview: {
+				type: Boolean,
+				default: false
+			},
+			delIcon: {
+				type: Boolean,
+				default: true
+			},
+			// 自动上传
+			autoUpload: {
+				type: Boolean,
+				default: true
+			},
+			// 最大选择个数 ,h5只能限制单选或是多选
+			limit: {
+				type: [Number, String],
+				default: 9
+			},
+			// 列表样式 grid | list | list-card
+			mode: {
+				type: String,
+				default: 'grid'
+			},
+			// 选择文件类型  image/video/all
+			fileMediatype: {
+				type: String,
+				default: 'image'
+			},
+			// 文件类型筛选
+			fileExtname: {
+				type: [Array, String],
+				default () {
+					return []
+				}
+			},
+			title: {
+				type: String,
+				default: ''
+			},
+			listStyles: {
+				type: Object,
+				default () {
+					return {
+						// 是否显示边框
+						border: true,
+						// 是否显示分隔线
+						dividline: true,
+						// 线条样式
+						borderStyle: {}
+					}
+				}
+			},
+			imageStyles: {
+				type: Object,
+				default () {
+					return {
+						width: 'auto',
+						height: 'auto'
+					}
+				}
+			},
+			readonly: {
+				type: Boolean,
+				default: false
+			},
+			returnType: {
+				type: String,
+				default: 'array'
+			},
+			sizeType: {
+				type: Array,
+				default () {
+					return ['original', 'compressed']
+				}
+			}
+		},
+		data() {
+			return {
+				files: [],
+				localValue: []
+			}
+		},
+		watch: {
+			// #ifndef VUE3
+			value: {
+				handler(newVal, oldVal) {
+					this.setValue(newVal, oldVal)
+				},
+				immediate: true
+			},
+			// #endif
+			// #ifdef VUE3
+			modelValue: {
+				handler(newVal, oldVal) {
+					this.setValue(newVal, oldVal)
+				},
+				immediate: true
+			},
+			// #endif
+		},
+		computed: {
+			filesList() {
+				let files = []
+				this.files.forEach(v => {
+					files.push(v)
+				})
+				return files
+			},
+			showType() {
+				if (this.fileMediatype === 'image') {
+					return this.mode
+				}
+				return 'list'
+			},
+			limitLength() {
+				if (this.returnType === 'object') {
+					return 1
+				}
+				if (!this.limit) {
+					return 1
+				}
+				if (this.limit >= 9) {
+					return 9
+				}
+				return this.limit
+			}
+		},
+		created() {
+			// TODO 兼容不开通服务空间的情况
+			if (!(uniCloud.config && uniCloud.config.provider)) {
+				this.noSpace = true
+				uniCloud.chooseAndUploadFile = chooseAndUploadFile
+			}
+			this.form = this.getForm('uniForms')
+			this.formItem = this.getForm('uniFormsItem')
+			if (this.form && this.formItem) {
+				if (this.formItem.name) {
+					this.rename = this.formItem.name
+					this.form.inputChildrens.push(this)
+				}
+			}
+		},
+		methods: {
+			/**
+			 * 公开用户使用,清空文件
+			 * @param {Object} index
+			 */
+			clearFiles(index) {
+				if (index !== 0 && !index) {
+					this.files = []
+					this.$nextTick(() => {
+						this.setEmit()
+					})
+				} else {
+					this.files.splice(index, 1)
+				}
+				this.$nextTick(() => {
+					this.setEmit()
+				})
+			},
+			/**
+			 * 公开用户使用,继续上传
+			 */
+			upload() {
+				let files = []
+				this.files.forEach((v, index) => {
+					if (v.status === 'ready' || v.status === 'error') {
+						files.push(Object.assign({}, v))
+					}
+				})
+				return this.uploadFiles(files)
+			},
+			async setValue(newVal, oldVal) {
+				const newData =  async (v) => {
+					const reg = /cloud:\/\/([\w.]+\/?)\S*/
+					let url = ''
+					if(v.fileID){
+						url = v.fileID
+					}else{
+						url = v.url
+					}
+					if (reg.test(url)) {
+						v.fileID = url
+						v.url = await this.getTempFileURL(url)
+					}
+					if(v.url) v.path = v.url
+					return v
+				}
+				if (this.returnType === 'object') {
+					if (newVal) {
+						await newData(newVal)
+					} else {
+						newVal = {}
+					}
+				} else {
+					if (!newVal) newVal = []
+					for(let i =0 ;i < newVal.length ;i++){
+						let v = newVal[i]
+						await newData(v)
+					}
+				}
+				this.localValue = newVal
+				if (this.form && this.formItem &&!this.is_reset) {
+					this.is_reset = false
+					this.formItem.setValue(this.localValue)
+				}
+				let filesData = Object.keys(newVal).length > 0 ? newVal : [];
+				this.files = [].concat(filesData)
+			},
+
+			/**
+			 * 选择文件
+			 */
+			choose() {
+
+				if (this.disabled) return
+				if (this.files.length >= Number(this.limitLength) && this.showType !== 'grid' && this.returnType ===
+					'array') {
+					uni.showToast({
+						title: `您最多选择 ${this.limitLength} 个文件`,
+						icon: 'none'
+					})
+					return
+				}
+				this.chooseFiles()
+			},
+
+			/**
+			 * 选择文件并上传
+			 */
+			chooseFiles() {
+				const _extname = get_extname(this.fileExtname)
+				// 获取后缀
+				uniCloud
+					.chooseAndUploadFile({
+						type: this.fileMediatype,
+						compressed: false,
+						sizeType: this.sizeType,
+						// TODO 如果为空,video 有问题
+						extension: _extname.length > 0 ? _extname : undefined,
+						count: this.limitLength - this.files.length, //默认9
+						onChooseFile: this.chooseFileCallback,
+						onUploadProgress: progressEvent => {
+							this.setProgress(progressEvent, progressEvent.index)
+						}
+					})
+					.then(result => {
+						this.setSuccessAndError(result.tempFiles)
+					})
+					.catch(err => {
+						console.log('选择失败', err)
+					})
+			},
+
+			/**
+			 * 选择文件回调
+			 * @param {Object} res
+			 */
+			async chooseFileCallback(res) {
+				const _extname = get_extname(this.fileExtname)
+				const is_one = (Number(this.limitLength) === 1 &&
+						this.disablePreview &&
+						!this.disabled) ||
+					this.returnType === 'object'
+				// 如果这有一个文件 ,需要清空本地缓存数据
+				if (is_one) {
+					this.files = []
+				}
+
+				let {
+					filePaths,
+					files
+				} = get_files_and_is_max(res, _extname)
+				if (!(_extname && _extname.length > 0)) {
+					filePaths = res.tempFilePaths
+					files = res.tempFiles
+				}
+
+				let currentData = []
+				for (let i = 0; i < files.length; i++) {
+					if (this.limitLength - this.files.length <= 0) break
+					files[i].uuid = Date.now()
+					let filedata = await get_file_data(files[i], this.fileMediatype)
+					filedata.progress = 0
+					filedata.status = 'ready'
+					this.files.push(filedata)
+					currentData.push({
+						...filedata,
+						file: files[i]
+					})
+				}
+				this.$emit('select', {
+					tempFiles: currentData,
+					tempFilePaths: filePaths
+				})
+				res.tempFiles = files
+				// 停止自动上传
+				if (!this.autoUpload || this.noSpace) {
+					res.tempFiles = []
+				}
+			},
+
+			/**
+			 * 批传
+			 * @param {Object} e
+			 */
+			uploadFiles(files) {
+				files = [].concat(files)
+				return uploadCloudFiles.call(this, files, 5, res => {
+						this.setProgress(res, res.index, true)
+					})
+					.then(result => {
+						this.setSuccessAndError(result)
+						return result;
+					})
+					.catch(err => {
+						console.log(err)
+					})
+			},
+
+			/**
+			 * 成功或失败
+			 */
+			async setSuccessAndError(res, fn) {
+				let successData = []
+				let errorData = []
+				let tempFilePath = []
+				let errorTempFilePath = []
+				for (let i = 0; i < res.length; i++) {
+					const item = res[i]
+					const index = item.uuid ? this.files.findIndex(p => p.uuid === item.uuid) : item.index
+
+					if (index === -1 || !this.files) break
+					if (item.errMsg === 'request:fail') {
+						this.files[index].url = item.path
+						this.files[index].status = 'error'
+						this.files[index].errMsg = item.errMsg
+						// this.files[index].progress = -1
+						errorData.push(this.files[index])
+						errorTempFilePath.push(this.files[index].url)
+					} else {
+						this.files[index].errMsg = ''
+						this.files[index].fileID = item.url
+						const reg = /cloud:\/\/([\w.]+\/?)\S*/
+						if (reg.test(item.url)) {
+							this.files[index].url = await this.getTempFileURL(item.url)
+						}else{
+							this.files[index].url = item.url
+						}
+
+						this.files[index].status = 'success'
+						this.files[index].progress += 1
+						successData.push(this.files[index])
+						tempFilePath.push(this.files[index].fileID)
+					}
+				}
+
+				if (successData.length > 0) {
+					this.setEmit()
+					// 状态改变返回
+					this.$emit('success', {
+						tempFiles: this.backObject(successData),
+						tempFilePaths: tempFilePath
+					})
+				}
+
+				if (errorData.length > 0) {
+					this.$emit('fail', {
+						tempFiles: this.backObject(errorData),
+						tempFilePaths: errorTempFilePath
+					})
+				}
+			},
+
+			/**
+			 * 获取进度
+			 * @param {Object} progressEvent
+			 * @param {Object} index
+			 * @param {Object} type
+			 */
+			setProgress(progressEvent, index, type) {
+				const fileLenth = this.files.length
+				const percentNum = (index / fileLenth) * 100
+				const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total)
+				let idx = index
+				if (!type) {
+					idx = this.files.findIndex(p => p.uuid === progressEvent.tempFile.uuid)
+				}
+				if (idx === -1 || !this.files[idx]) return
+				// fix by mehaotian 100 就会消失,-1 是为了让进度条消失
+				this.files[idx].progress = percentCompleted - 1
+				// 上传中
+				this.$emit('progress', {
+					index: idx,
+					progress: parseInt(percentCompleted),
+					tempFile: this.files[idx]
+				})
+			},
+
+			/**
+			 * 删除文件
+			 * @param {Object} index
+			 */
+			delFile(index) {
+				this.$emit('delete', {
+					tempFile: this.files[index],
+					tempFilePath: this.files[index].url
+				})
+				this.files.splice(index, 1)
+				this.$nextTick(() => {
+					this.setEmit()
+				})
+			},
+
+			/**
+			 * 获取文件名和后缀
+			 * @param {Object} name
+			 */
+			getFileExt(name) {
+				const last_len = name.lastIndexOf('.')
+				const len = name.length
+				return {
+					name: name.substring(0, last_len),
+					ext: name.substring(last_len + 1, len)
+				}
+			},
+
+			/**
+			 * 处理返回事件
+			 */
+			setEmit() {
+				let data = []
+				if (this.returnType === 'object') {
+					data = this.backObject(this.files)[0]
+					this.localValue = data?data:null
+				} else {
+					data = this.backObject(this.files)
+					if (!this.localValue) {
+						this.localValue = []
+					}
+					this.localValue = [...data]
+				}
+				// #ifdef VUE3
+				this.$emit('update:modelValue', this.localValue)
+				// #endif
+				// #ifndef VUE3
+				this.$emit('input', this.localValue)
+				// #endif
+			},
+
+			/**
+			 * 处理返回参数
+			 * @param {Object} files
+			 */
+			backObject(files) {
+				let newFilesData = []
+				files.forEach(v => {
+					newFilesData.push({
+						extname: v.extname,
+						fileType: v.fileType,
+						image: v.image,
+						name: v.name,
+						path: v.path,
+						size: v.size,
+						fileID:v.fileID,
+						url: v.url
+					})
+				})
+				return newFilesData
+			},
+			async getTempFileURL(fileList) {
+				fileList = {
+					fileList: [].concat(fileList)
+				}
+				const urls = await uniCloud.getTempFileURL(fileList)
+				return urls.fileList[0].tempFileURL || ''
+			},
+			/**
+			 * 获取父元素实例
+			 */
+			getForm(name = 'uniForms') {
+				let parent = this.$parent;
+				let parentName = parent.$options.name;
+				while (parentName !== name) {
+					parent = parent.$parent;
+					if (!parent) return false;
+					parentName = parent.$options.name;
+				}
+				return parent;
+			}
+		}
+	}
+</script>
+
+<style>
+	.uni-file-picker {
+		/* #ifndef APP-NVUE */
+		box-sizing: border-box;
+		overflow: hidden;
+		width: 100%;
+		/* #endif */
+		flex: 1;
+	}
+
+	.uni-file-picker__header {
+		padding-top: 5px;
+		padding-bottom: 10px;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		justify-content: space-between;
+	}
+
+	.file-title {
+		font-size: 14px;
+		color: #333;
+	}
+
+	.file-count {
+		font-size: 14px;
+		color: #999;
+	}
+
+	.is-add {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		align-items: center;
+		justify-content: center;
+	}
+
+	.icon-add {
+		width: 50px;
+		height: 5px;
+		background-color: #f1f1f1;
+		border-radius: 2px;
+	}
+
+	.rotate {
+		position: absolute;
+		transform: rotate(90deg);
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-file-picker/components/uni-file-picker/upload-file.vue b/yudao-ui-admin-uniapp/uni_modules/uni-file-picker/components/uni-file-picker/upload-file.vue
new file mode 100644
index 000000000..625d92ec7
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-file-picker/components/uni-file-picker/upload-file.vue
@@ -0,0 +1,325 @@
+<template>
+	<view class="uni-file-picker__files">
+		<view v-if="!readonly" class="files-button" @click="choose">
+			<slot></slot>
+		</view>
+		<!-- :class="{'is-text-box':showType === 'list'}" -->
+		<view v-if="list.length > 0" class="uni-file-picker__lists is-text-box" :style="borderStyle">
+			<!-- ,'is-list-card':showType === 'list-card' -->
+
+			<view class="uni-file-picker__lists-box" v-for="(item ,index) in list" :key="index" :class="{
+				'files-border':index !== 0 && styles.dividline}"
+			 :style="index !== 0 && styles.dividline &&borderLineStyle">
+				<view class="uni-file-picker__item">
+					<!-- :class="{'is-text-image':showType === 'list'}" -->
+					<!-- 	<view class="files__image is-text-image">
+						<image class="header-image" :src="item.logo" mode="aspectFit"></image>
+					</view> -->
+					<view class="files__name">{{item.name}}</view>
+					<view v-if="delIcon&&!readonly" class="icon-del-box icon-files" @click="delFile(index)">
+						<view class="icon-del icon-files"></view>
+						<view class="icon-del rotate"></view>
+					</view>
+				</view>
+				<view v-if="(item.progress && item.progress !== 100) ||item.progress===0 " class="file-picker__progress">
+					<progress class="file-picker__progress-item" :percent="item.progress === -1?0:item.progress" stroke-width="4"
+					 :backgroundColor="item.errMsg?'#ff5a5f':'#EBEBEB'" />
+				</view>
+				<view v-if="item.status === 'error'" class="file-picker__mask" @click.stop="uploadFiles(item,index)">
+					点击重试
+				</view>
+			</view>
+
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: "uploadFile",
+		emits:['uploadFiles','choose','delFile'],
+		props: {
+			filesList: {
+				type: Array,
+				default () {
+					return []
+				}
+			},
+			delIcon: {
+				type: Boolean,
+				default: true
+			},
+			limit: {
+				type: [Number, String],
+				default: 9
+			},
+			showType: {
+				type: String,
+				default: ''
+			},
+			listStyles: {
+				type: Object,
+				default () {
+					return {
+						// 是否显示边框
+						border: true,
+						// 是否显示分隔线
+						dividline: true,
+						// 线条样式
+						borderStyle: {}
+					}
+				}
+			},
+			readonly:{
+				type:Boolean,
+				default:false
+			}
+		},
+		computed: {
+			list() {
+				let files = []
+				this.filesList.forEach(v => {
+					files.push(v)
+				})
+				return files
+			},
+			styles() {
+				let styles = {
+					border: true,
+					dividline: true,
+					'border-style': {}
+				}
+				return Object.assign(styles, this.listStyles)
+			},
+			borderStyle() {
+				let {
+					borderStyle,
+					border
+				} = this.styles
+				let obj = {}
+				if (!border) {
+					obj.border = 'none'
+				} else {
+					let width = (borderStyle && borderStyle.width) || 1
+					width = this.value2px(width)
+					let radius = (borderStyle && borderStyle.radius) || 5
+					radius = this.value2px(radius)
+					obj = {
+						'border-width': width,
+						'border-style': (borderStyle && borderStyle.style) || 'solid',
+						'border-color': (borderStyle && borderStyle.color) || '#eee',
+						'border-radius': radius
+					}
+				}
+				let classles = ''
+				for (let i in obj) {
+					classles += `${i}:${obj[i]};`
+				}
+				return classles
+			},
+			borderLineStyle() {
+				let obj = {}
+				let {
+					borderStyle
+				} = this.styles
+				if (borderStyle && borderStyle.color) {
+					obj['border-color'] = borderStyle.color
+				}
+				if (borderStyle && borderStyle.width) {
+					let width = borderStyle && borderStyle.width || 1
+					let style = borderStyle && borderStyle.style || 0
+					if (typeof width === 'number') {
+						width += 'px'
+					} else {
+						width = width.indexOf('px') ? width : width + 'px'
+					}
+					obj['border-width'] = width
+
+					if (typeof style === 'number') {
+						style += 'px'
+					} else {
+						style = style.indexOf('px') ? style : style + 'px'
+					}
+					obj['border-top-style'] = style
+				}
+				let classles = ''
+				for (let i in obj) {
+					classles += `${i}:${obj[i]};`
+				}
+				return classles
+			}
+		},
+
+		methods: {
+			uploadFiles(item, index) {
+				this.$emit("uploadFiles", {
+					item,
+					index
+				})
+			},
+			choose() {
+				this.$emit("choose")
+			},
+			delFile(index) {
+				this.$emit('delFile', index)
+			},
+			value2px(value) {
+				if (typeof value === 'number') {
+					value += 'px'
+				} else {
+					value = value.indexOf('px') !== -1 ? value : value + 'px'
+				}
+				return value
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.uni-file-picker__files {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		justify-content: flex-start;
+	}
+
+	.files-button {
+		// border: 1px red solid;
+	}
+
+	.uni-file-picker__lists {
+		position: relative;
+		margin-top: 5px;
+		overflow: hidden;
+	}
+
+	.file-picker__mask {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		justify-content: center;
+		align-items: center;
+		position: absolute;
+		right: 0;
+		top: 0;
+		bottom: 0;
+		left: 0;
+		color: #fff;
+		font-size: 14px;
+		background-color: rgba(0, 0, 0, 0.4);
+	}
+
+	.uni-file-picker__lists-box {
+		position: relative;
+	}
+
+	.uni-file-picker__item {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		align-items: center;
+		padding: 8px 10px;
+		padding-right: 5px;
+		padding-left: 10px;
+	}
+
+	.files-border {
+		border-top: 1px #eee solid;
+	}
+
+	.files__name {
+		flex: 1;
+		font-size: 14px;
+		color: #666;
+		margin-right: 25px;
+		/* #ifndef APP-NVUE */
+		word-break: break-all;
+		word-wrap: break-word;
+		/* #endif */
+	}
+
+	.icon-files {
+		/* #ifndef APP-NVUE */
+		position: static;
+		background-color: initial;
+		/* #endif */
+	}
+
+	// .icon-files .icon-del {
+	// 	background-color: #333;
+	// 	width: 12px;
+	// 	height: 1px;
+	// }
+
+
+	.is-list-card {
+		border: 1px #eee solid;
+		margin-bottom: 5px;
+		border-radius: 5px;
+		box-shadow: 0 0 2px 0px rgba(0, 0, 0, 0.1);
+		padding: 5px;
+	}
+
+	.files__image {
+		width: 40px;
+		height: 40px;
+		margin-right: 10px;
+	}
+
+	.header-image {
+		width: 100%;
+		height: 100%;
+	}
+
+	.is-text-box {
+		border: 1px #eee solid;
+		border-radius: 5px;
+	}
+
+	.is-text-image {
+		width: 25px;
+		height: 25px;
+		margin-left: 5px;
+	}
+
+	.rotate {
+		position: absolute;
+		transform: rotate(90deg);
+	}
+
+	.icon-del-box {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		margin: auto 0;
+		/* #endif */
+		align-items: center;
+		justify-content: center;
+		position: absolute;
+		top: 0px;
+		bottom: 0;
+		right: 5px;
+		height: 26px;
+		width: 26px;
+		// border-radius: 50%;
+		// background-color: rgba(0, 0, 0, 0.5);
+		z-index: 2;
+		transform: rotate(-45deg);
+	}
+
+	.icon-del {
+		width: 15px;
+		height: 1px;
+		background-color: #333;
+		// border-radius: 1px;
+	}
+
+	/* #ifdef H5 */
+	@media all and (min-width: 768px) {
+		.uni-file-picker__files {
+			max-width: 375px;
+		}
+	}
+
+	/* #endif */
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-file-picker/components/uni-file-picker/upload-image.vue b/yudao-ui-admin-uniapp/uni_modules/uni-file-picker/components/uni-file-picker/upload-image.vue
new file mode 100644
index 000000000..2a29bc231
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-file-picker/components/uni-file-picker/upload-image.vue
@@ -0,0 +1,292 @@
+<template>
+	<view class="uni-file-picker__container">
+		<view class="file-picker__box" v-for="(item,index) in filesList" :key="index" :style="boxStyle">
+			<view class="file-picker__box-content" :style="borderStyle">
+				<image class="file-image" :src="item.url" mode="aspectFill" @click.stop="prviewImage(item,index)"></image>
+				<view v-if="delIcon && !readonly" class="icon-del-box" @click.stop="delFile(index)">
+					<view class="icon-del"></view>
+					<view class="icon-del rotate"></view>
+				</view>
+				<view v-if="(item.progress && item.progress !== 100) ||item.progress===0 " class="file-picker__progress">
+					<progress class="file-picker__progress-item" :percent="item.progress === -1?0:item.progress" stroke-width="4"
+					 :backgroundColor="item.errMsg?'#ff5a5f':'#EBEBEB'" />
+				</view>
+				<view v-if="item.errMsg" class="file-picker__mask" @click.stop="uploadFiles(item,index)">
+					点击重试
+				</view>
+			</view>
+		</view>
+		<view v-if="filesList.length < limit && !readonly" class="file-picker__box" :style="boxStyle">
+			<view class="file-picker__box-content is-add" :style="borderStyle" @click="choose">
+				<slot>
+					<view class="icon-add"></view>
+					<view class="icon-add rotate"></view>
+				</slot>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: "uploadImage",
+		emits:['uploadFiles','choose','delFile'],
+		props: {
+			filesList: {
+				type: Array,
+				default () {
+					return []
+				}
+			},
+			disabled:{
+				type: Boolean,
+				default: false
+			},
+			disablePreview: {
+				type: Boolean,
+				default: false
+			},
+			limit: {
+				type: [Number, String],
+				default: 9
+			},
+			imageStyles: {
+				type: Object,
+				default () {
+					return {
+						width: 'auto',
+						height: 'auto',
+						border: {}
+					}
+				}
+			},
+			delIcon: {
+				type: Boolean,
+				default: true
+			},
+			readonly:{
+				type:Boolean,
+				default:false
+			}
+		},
+		computed: {
+			styles() {
+				let styles = {
+					width: 'auto',
+					height: 'auto',
+					border: {}
+				}
+				return Object.assign(styles, this.imageStyles)
+			},
+			boxStyle() {
+				const {
+					width = 'auto',
+						height = 'auto'
+				} = this.styles
+				let obj = {}
+				if (height === 'auto') {
+					if (width !== 'auto') {
+						obj.height = this.value2px(width)
+						obj['padding-top'] = 0
+					} else {
+						obj.height = 0
+					}
+				} else {
+					obj.height = this.value2px(height)
+					obj['padding-top'] = 0
+				}
+
+				if (width === 'auto') {
+					if (height !== 'auto') {
+						obj.width = this.value2px(height)
+					} else {
+						obj.width = '33.3%'
+					}
+				} else {
+					obj.width = this.value2px(width)
+				}
+
+				let classles = ''
+				for(let i in obj){
+					classles+= `${i}:${obj[i]};`
+				}
+				return classles
+			},
+			borderStyle() {
+				let {
+					border
+				} = this.styles
+				let obj = {}
+				const widthDefaultValue = 1
+				const radiusDefaultValue = 3
+				if (typeof border === 'boolean') {
+					obj.border = border ? '1px #eee solid' : 'none'
+				} else {
+					let width = (border && border.width) || widthDefaultValue
+					width = this.value2px(width)
+					let radius = (border && border.radius) || radiusDefaultValue
+					radius = this.value2px(radius)
+					obj = {
+						'border-width': width,
+						'border-style': (border && border.style) || 'solid',
+						'border-color': (border && border.color) || '#eee',
+						'border-radius': radius
+					}
+				}
+				let classles = ''
+				for(let i in obj){
+					classles+= `${i}:${obj[i]};`
+				}
+				return classles
+			}
+		},
+		methods: {
+			uploadFiles(item, index) {
+				this.$emit("uploadFiles", item)
+			},
+			choose() {
+				this.$emit("choose")
+			},
+			delFile(index) {
+				this.$emit('delFile', index)
+			},
+			prviewImage(img, index) {
+				let urls = []
+				if(Number(this.limit) === 1&&this.disablePreview&&!this.disabled){
+					this.$emit("choose")
+				}
+				if(this.disablePreview) return
+				this.filesList.forEach(i => {
+					urls.push(i.url)
+				})
+
+				uni.previewImage({
+					urls: urls,
+					current: index
+				});
+			},
+			value2px(value) {
+				if (typeof value === 'number') {
+					value += 'px'
+				} else {
+					if (value.indexOf('%') === -1) {
+						value = value.indexOf('px') !== -1 ? value : value + 'px'
+					}
+				}
+				return value
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.uni-file-picker__container {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		box-sizing: border-box;
+		/* #endif */
+		flex-wrap: wrap;
+		margin: -5px;
+	}
+
+	.file-picker__box {
+		position: relative;
+		// flex: 0 0 33.3%;
+		width: 33.3%;
+		height: 0;
+		padding-top: 33.33%;
+		/* #ifndef APP-NVUE */
+		box-sizing: border-box;
+		/* #endif */
+	}
+
+	.file-picker__box-content {
+		position: absolute;
+		top: 0;
+		right: 0;
+		bottom: 0;
+		left: 0;
+		margin: 5px;
+		border: 1px #eee solid;
+		border-radius: 5px;
+		overflow: hidden;
+	}
+
+	.file-picker__progress {
+		position: absolute;
+		bottom: 0;
+		left: 0;
+		right: 0;
+		/* border: 1px red solid; */
+		z-index: 2;
+	}
+
+	.file-picker__progress-item {
+		width: 100%;
+	}
+
+	.file-picker__mask {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		justify-content: center;
+		align-items: center;
+		position: absolute;
+		right: 0;
+		top: 0;
+		bottom: 0;
+		left: 0;
+		color: #fff;
+		font-size: 12px;
+		background-color: rgba(0, 0, 0, 0.4);
+	}
+
+	.file-image {
+		width: 100%;
+		height: 100%;
+	}
+
+	.is-add {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		align-items: center;
+		justify-content: center;
+	}
+
+	.icon-add {
+		width: 50px;
+		height: 5px;
+		background-color: #f1f1f1;
+		border-radius: 2px;
+	}
+
+	.rotate {
+		position: absolute;
+		transform: rotate(90deg);
+	}
+
+	.icon-del-box {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		align-items: center;
+		justify-content: center;
+		position: absolute;
+		top: 3px;
+		right: 3px;
+		height: 26px;
+		width: 26px;
+		border-radius: 50%;
+		background-color: rgba(0, 0, 0, 0.5);
+		z-index: 2;
+		transform: rotate(-45deg);
+	}
+
+	.icon-del {
+		width: 15px;
+		height: 2px;
+		background-color: #fff;
+		border-radius: 2px;
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-file-picker/components/uni-file-picker/utils.js b/yudao-ui-admin-uniapp/uni_modules/uni-file-picker/components/uni-file-picker/utils.js
new file mode 100644
index 000000000..60aaa3e4e
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-file-picker/components/uni-file-picker/utils.js
@@ -0,0 +1,109 @@
+/**
+ * 获取文件名和后缀
+ * @param {String} name
+ */
+export const get_file_ext = (name) => {
+	const last_len = name.lastIndexOf('.')
+	const len = name.length
+	return {
+		name: name.substring(0, last_len),
+		ext: name.substring(last_len + 1, len)
+	}
+}
+
+/**
+ * 获取扩展名
+ * @param {Array} fileExtname
+ */
+export const get_extname = (fileExtname) => {
+	if (!Array.isArray(fileExtname)) {
+		let extname = fileExtname.replace(/(\[|\])/g, '')
+		return extname.split(',')
+	} else {
+		return fileExtname
+	}
+	return []
+}
+
+/**
+ * 获取文件和检测是否可选
+ */
+export const get_files_and_is_max = (res, _extname) => {
+	let filePaths = []
+	let files = []
+	if(!_extname || _extname.length === 0){
+		return {
+			filePaths,
+			files
+		}
+	}
+	res.tempFiles.forEach(v => {
+		let fileFullName = get_file_ext(v.name)
+		const extname = fileFullName.ext.toLowerCase()
+		if (_extname.indexOf(extname) !== -1) {
+			files.push(v)
+			filePaths.push(v.path)
+		}
+	})
+	if (files.length !== res.tempFiles.length) {
+		uni.showToast({
+			title: `当前选择了${res.tempFiles.length}个文件 ,${res.tempFiles.length - files.length} 个文件格式不正确`,
+			icon: 'none',
+			duration: 5000
+		})
+	}
+
+	return {
+		filePaths,
+		files
+	}
+}
+
+
+/**
+ * 获取图片信息
+ * @param {Object} filepath
+ */
+export const get_file_info = (filepath) => {
+	return new Promise((resolve, reject) => {
+		uni.getImageInfo({
+			src: filepath,
+			success(res) {
+				resolve(res)
+			},
+			fail(err) {
+				reject(err)
+			}
+		})
+	})
+}
+/**
+ * 获取封装数据
+ */
+export const get_file_data = async (files, type = 'image') => {
+	// 最终需要上传数据库的数据
+	let fileFullName = get_file_ext(files.name)
+	const extname = fileFullName.ext.toLowerCase()
+	let filedata = {
+		name: files.name,
+		uuid: files.uuid,
+		extname: extname || '',
+		cloudPath: files.cloudPath,
+		fileType: files.fileType,
+		url: files.path || files.path,
+		size: files.size, //单位是字节
+		image: {},
+		path: files.path,
+		video: {}
+	}
+	if (type === 'image') {
+		const imageinfo = await get_file_info(files.path)
+		delete filedata.video
+		filedata.image.width = imageinfo.width
+		filedata.image.height = imageinfo.height
+		filedata.image.location = imageinfo.path
+	} else {
+		delete filedata.image
+	}
+	return filedata
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-file-picker/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-file-picker/package.json
new file mode 100644
index 000000000..08bd66ec3
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-file-picker/package.json
@@ -0,0 +1,86 @@
+{
+  "id": "uni-file-picker",
+  "displayName": "uni-file-picker 文件选择上传",
+  "version": "1.0.2",
+  "description": "文件选择上传组件,可以选择图片、视频等任意文件并上传到当前绑定的服务空间",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "图片上传",
+    "文件上传"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": ["uni-scss"],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "n"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-file-picker/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-file-picker/readme.md
new file mode 100644
index 000000000..c8399a5e7
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-file-picker/readme.md
@@ -0,0 +1,11 @@
+
+## FilePicker 文件选择上传
+
+> **组件名:uni-file-picker**
+>  代码块: `uFilePicker`
+
+
+文件选择上传组件,可以选择图片、视频等任意文件并上传到当前绑定的服务空间
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-file-picker)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-forms/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-forms/changelog.md
new file mode 100644
index 000000000..5a4bb79af
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-forms/changelog.md
@@ -0,0 +1,86 @@
+## 1.4.6(2022-07-13)
+- 修复 model 需要校验的值没有声明对应字段时,导致第一次不触发校验的bug
+## 1.4.5(2022-07-05)
+- 新增 更多表单示例
+- 优化 子表单组件过期提示的问题
+- 优化 子表单组件uni-datetime-picker、uni-data-select、uni-data-picker的显示样式
+## 1.4.4(2022-07-04)
+- 更新 删除组件日志
+## 1.4.3(2022-07-04)
+- 修复 由 1.4.0 引发的 label 插槽不生效的bug
+## 1.4.2(2022-07-04)
+- 修复 子组件找不到 setValue 报错的bug
+## 1.4.1(2022-07-04)
+- 修复 uni-data-picker 在 uni-forms-item 中报错的bug
+- 修复 uni-data-picker 在 uni-forms-item 中宽度不正确的bug
+## 1.4.0(2022-06-30)
+- 【重要】组件逻辑重构,部分用法用旧版本不兼容,请注意兼容问题
+- 【重要】组件使用 Provide/Inject 方式注入依赖,提供了自定义表单组件调用 uni-forms 校验表单的能力
+- 新增 model 属性,等同于原 value/modelValue 属性,旧属性即将废弃
+- 新增 validateTrigger 属性的 blur 值,仅 uni-easyinput 生效
+- 新增 onFieldChange 方法,可以对子表单进行校验,可替代binddata方法
+- 新增 子表单的 setRules 方法,配合自定义校验函数使用
+- 新增 uni-forms-item 的 setRules 方法,配置动态表单使用可动态更新校验规则
+- 优化 动态表单校验方式,废弃拼接name的方式
+## 1.3.3(2022-06-22)
+- 修复 表单校验顺序无序问题
+## 1.3.2(2021-12-09)
+-
+## 1.3.1(2021-11-19)
+- 修复 label 插槽不生效的bug
+## 1.3.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-forms](https://uniapp.dcloud.io/component/uniui/uni-forms)
+## 1.2.7(2021-08-13)
+- 修复 没有添加校验规则的字段依然报错的Bug
+## 1.2.6(2021-08-11)
+- 修复 重置表单错误信息无法清除的问题
+## 1.2.5(2021-08-11)
+- 优化 组件文档
+## 1.2.4(2021-08-11)
+- 修复 表单验证只生效一次的问题
+## 1.2.3(2021-07-30)
+- 优化 vue3下事件警告的问题
+## 1.2.2(2021-07-26)
+- 修复 vue2 下条件编译导致destroyed生命周期失效的Bug
+- 修复 1.2.1 引起的示例在小程序平台报错的Bug
+## 1.2.1(2021-07-22)
+- 修复 动态校验表单,默认值为空的情况下校验失效的Bug
+- 修复 不指定name属性时,运行报错的Bug
+- 优化 label默认宽度从65调整至70,使required为true且四字时不换行
+- 优化 组件示例,新增动态校验示例代码
+- 优化 组件文档,使用方式更清晰
+## 1.2.0(2021-07-13)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.1.2(2021-06-25)
+- 修复 pattern 属性在微信小程序平台无效的问题
+## 1.1.1(2021-06-22)
+- 修复 validate-trigger属性为submit且err-show-type属性为toast时不能弹出的Bug
+## 1.1.0(2021-06-22)
+- 修复 只写setRules方法而导致校验不生效的Bug
+- 修复 由上个办法引发的错误提示文字错位的Bug
+## 1.0.48(2021-06-21)
+- 修复 不设置 label 属性 ,无法设置label插槽的问题
+## 1.0.47(2021-06-21)
+- 修复 不设置label属性,label-width属性不生效的bug
+- 修复 setRules 方法与rules属性冲突的问题
+## 1.0.46(2021-06-04)
+- 修复 动态删减数据导致报错的问题
+## 1.0.45(2021-06-04)
+- 新增 modelValue 属性 ,value 即将废弃
+## 1.0.44(2021-06-02)
+- 新增 uni-forms-item 可以设置单独的 rules
+- 新增 validate 事件增加 keepitem 参数,可以选择那些字段不过滤
+- 优化 submit 事件重命名为 validate
+## 1.0.43(2021-05-12)
+- 新增 组件示例地址
+## 1.0.42(2021-04-30)
+- 修复 自定义检验器失效的问题
+## 1.0.41(2021-03-05)
+- 更新 校验器
+- 修复 表单规则设置类型为 number 的情况下,值为0校验失败的Bug
+## 1.0.40(2021-03-04)
+- 修复 动态显示uni-forms-item的情况下,submit 方法获取值错误的Bug
+## 1.0.39(2021-02-05)
+- 调整为uni_modules目录规范
+- 修复 校验器传入 int 等类型 ,返回String类型的Bug
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue b/yudao-ui-admin-uniapp/uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue
new file mode 100644
index 000000000..250ed875c
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue
@@ -0,0 +1,627 @@
+<template>
+	<view class="uni-forms-item"
+		:class="['is-direction-' + localLabelPos ,border?'uni-forms-item--border':'' ,border && isFirstBorder?'is-first-border':'']">
+		<slot name="label">
+			<view class="uni-forms-item__label" :class="{'no-label':!label && !isRequired}"
+				:style="{width:localLabelWidth,justifyContent: localLabelAlign}">
+				<text v-if="isRequired" class="is-required">*</text>
+				<text>{{label}}</text>
+			</view>
+		</slot>
+		<!-- #ifndef APP-NVUE -->
+		<view class="uni-forms-item__content">
+			<slot></slot>
+			<view class="uni-forms-item__error" :class="{'msg--active':msg}">
+				<text>{{msg}}</text>
+			</view>
+		</view>
+		<!-- #endif -->
+		<!-- #ifdef APP-NVUE -->
+		<view class="uni-forms-item__nuve-content">
+			<view class="uni-forms-item__content">
+				<slot></slot>
+			</view>
+			<view class="uni-forms-item__error" :class="{'msg--active':msg}">
+				<text class="error-text">{{msg}}</text>
+			</view>
+		</view>
+		<!-- #endif -->
+	</view>
+</template>
+
+<script>
+	/**
+	 * uni-fomrs-item 表单子组件
+	 * @description uni-fomrs-item 表单子组件,提供了基础布局已经校验能力
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=2773
+	 * @property {Boolean} required 是否必填,左边显示红色"*"号
+	 * @property {String } 	label 				输入框左边的文字提示
+	 * @property {Number } 	labelWidth 			label的宽度,单位px(默认65)
+	 * @property {String } 	labelAlign = [left|center|right] label的文字对齐方式(默认left)
+	 * 	@value left		label 左侧显示
+	 * 	@value center	label 居中
+	 * 	@value right	label 右侧对齐
+	 * @property {String } 	errorMessage 		显示的错误提示内容,如果为空字符串或者false,则不显示错误信息
+	 * @property {String } 	name 				表单域的属性名,在使用校验规则时必填
+	 * @property {String } 	leftIcon 			【1.4.0废弃】label左边的图标,限 uni-ui 的图标名称
+	 * @property {String } 	iconColor 		【1.4.0废弃】左边通过icon配置的图标的颜色(默认#606266)
+	 * @property {String} validateTrigger = [bind|submit|blur]	【1.4.0废弃】校验触发器方式 默认 submit
+	 * 	@value bind 	发生变化时触发
+	 * 	@value submit 提交时触发
+	 * 	@value blur 	失去焦点触发
+	 * @property {String } 	labelPosition = [top|left] 【1.4.0废弃】label的文字的位置(默认left)
+	 * 	@value top	顶部显示 label
+	 * 	@value left	左侧显示 label
+	 */
+
+	export default {
+		name: 'uniFormsItem',
+		options: {
+			virtualHost: true
+		},
+		provide() {
+			return {
+				uniFormItem: this
+			}
+		},
+		inject: {
+			form: {
+				from: 'uniForm',
+				default: null
+			},
+		},
+		props: {
+			// 表单校验规则
+			rules: {
+				type: Array,
+				default () {
+					return null;
+				}
+			},
+			// 表单域的属性名,在使用校验规则时必填
+			name: {
+				type: [String, Array],
+				default: ''
+			},
+			required: {
+				type: Boolean,
+				default: false
+			},
+			label: {
+				type: String,
+				default: ''
+			},
+			// label的宽度 ,默认 80
+			labelWidth: {
+				type: [String, Number],
+				default: ''
+			},
+			// label 居中方式,默认 left 取值 left/center/right
+			labelAlign: {
+				type: String,
+				default: ''
+			},
+			// 强制显示错误信息
+			errorMessage: {
+				type: [String, Boolean],
+				default: ''
+			},
+			// 1.4.0 弃用,统一使用 form 的校验时机
+			// validateTrigger: {
+			// 	type: String,
+			// 	default: ''
+			// },
+			// 1.4.0 弃用,统一使用 form 的label 位置
+			// labelPosition: {
+			// 	type: String,
+			// 	default: ''
+			// },
+			// 1.4.0 以下属性已经废弃,请使用  #label 插槽代替
+			leftIcon: String,
+			iconColor: {
+				type: String,
+				default: '#606266'
+			},
+		},
+		data() {
+			return {
+				errMsg: '',
+				isRequired: false,
+				userRules: null,
+				localLabelAlign: 'left',
+				localLabelWidth: '65px',
+				localLabelPos: 'left',
+				border: false,
+				isFirstBorder: false,
+			};
+		},
+		computed: {
+			// 处理错误信息
+			msg() {
+				return this.errorMessage || this.errMsg;
+			}
+		},
+		watch: {
+			// 规则发生变化通知子组件更新
+			'form.formRules'(val) {
+				// TODO 处理头条vue3 watch不生效的问题
+				// #ifndef MP-TOUTIAO
+				this.init()
+				// #endif
+			},
+			'form.labelWidth'(val) {
+				// 宽度
+				this.localLabelWidth = this._labelWidthUnit(val)
+
+			},
+			'form.labelPosition'(val) {
+				// 标签位置
+				this.localLabelPos = this._labelPosition()
+			},
+			'form.labelAlign'(val) {
+
+			}
+		},
+		created() {
+			this.init(true)
+			if (this.name && this.form) {
+				// TODO 处理头条vue3 watch不生效的问题
+				// #ifdef MP-TOUTIAO
+				this.$watch('form.formRules', () => {
+					this.init()
+				})
+				// #endif
+
+				// 监听变化
+				this.$watch(
+					() => {
+						const val = this.form._getDataValue(this.name, this.form.localData)
+						return val
+					},
+					(value, oldVal) => {
+						const isEqual = this.form._isEqual(value, oldVal)
+						// 简单判断前后值的变化,只有发生变化才会发生校验
+						// TODO  如果 oldVal = undefined ,那么大概率是源数据里没有值导致 ,这个情况不哦校验 ,可能不严谨 ,需要在做观察
+						// fix by mehaotian 暂时取消 && oldVal !== undefined ,如果formData 中不存在,可能会不校验
+						if (!isEqual) {
+							const val = this.itemSetValue(value)
+							this.onFieldChange(val, false)
+						}
+					}, {
+						immediate: false
+					}
+				);
+			}
+
+		},
+		// #ifndef VUE3
+		destroyed() {
+			if (this.__isUnmounted) return
+			this.unInit()
+		},
+		// #endif
+		// #ifdef VUE3
+		unmounted() {
+			this.__isUnmounted = true
+			this.unInit()
+		},
+		// #endif
+		methods: {
+			/**
+			 * 外部调用方法
+			 * 设置规则 ,主要用于小程序自定义检验规则
+			 * @param {Array} rules 规则源数据
+			 */
+			setRules(rules = null) {
+				this.userRules = rules
+				this.init(false)
+			},
+			// 兼容老版本表单组件
+			setValue() {
+				// console.log('setValue 方法已经弃用,请使用最新版本的 uni-forms 表单组件以及其他关联组件。');
+			},
+			/**
+			 * 外部调用方法
+			 * 校验数据
+			 * @param {any} value 需要校验的数据
+			 * @param {boolean} 是否立即校验
+			 * @return {Array|null} 校验内容
+			 */
+			async onFieldChange(value, formtrigger = true) {
+				const {
+					formData,
+					localData,
+					errShowType,
+					validateCheck,
+					validateTrigger,
+					_isRequiredField,
+					_realName
+				} = this.form
+				const name = _realName(this.name)
+				if (!value) {
+					value = this.form.formData[name]
+				}
+				// fixd by mehaotian 不在校验前清空信息,解决闪屏的问题
+				// this.errMsg = '';
+
+				// fix by mehaotian 解决没有检验规则的情况下,抛出错误的问题
+				const ruleLen = this.itemRules.rules && this.itemRules.rules.length
+				if (!this.validator || !ruleLen || ruleLen === 0) return;
+
+				// 检验时机
+				// let trigger = this.isTrigger(this.itemRules.validateTrigger, this.validateTrigger, validateTrigger);
+				const isRequiredField = _isRequiredField(this.itemRules.rules || []);
+				let result = null;
+				// 只有等于 bind 时 ,才能开启时实校验
+				if (validateTrigger === 'bind' || formtrigger) {
+					// 校验当前表单项
+					result = await this.validator.validateUpdate({
+							[name]: value
+						},
+						formData
+					);
+
+					// 判断是否必填,非必填,不填不校验,填写才校验 ,暂时只处理 undefined  和空的情况
+					if (!isRequiredField && (value === undefined || value === '')) {
+						result = null;
+					}
+
+					// 判断错误信息显示类型
+					if (result && result.errorMessage) {
+						if (errShowType === 'undertext') {
+							// 获取错误信息
+							this.errMsg = !result ? '' : result.errorMessage;
+						}
+						if (errShowType === 'toast') {
+							uni.showToast({
+								title: result.errorMessage || '校验错误',
+								icon: 'none'
+							});
+						}
+						if (errShowType === 'modal') {
+							uni.showModal({
+								title: '提示',
+								content: result.errorMessage || '校验错误'
+							});
+						}
+					} else {
+						this.errMsg = ''
+					}
+					// 通知 form 组件更新事件
+					validateCheck(result ? result : null)
+				} else {
+					this.errMsg = ''
+				}
+				return result ? result : null;
+			},
+			/**
+			 * 初始组件数据
+			 */
+			init(type = false) {
+				const {
+					validator,
+					formRules,
+					childrens,
+					formData,
+					localData,
+					_realName,
+					labelWidth,
+					_getDataValue,
+					_setDataValue
+				} = this.form || {}
+				// 对齐方式
+				this.localLabelAlign = this._justifyContent()
+				// 宽度
+				this.localLabelWidth = this._labelWidthUnit(labelWidth)
+				// 标签位置
+				this.localLabelPos = this._labelPosition()
+				this.isRequired = this.required
+				// 将需要校验的子组件加入form 队列
+				this.form && type && childrens.push(this)
+
+				if (!validator || !formRules) return
+				// 判断第一个 item
+				if (!this.form.isFirstBorder) {
+					this.form.isFirstBorder = true;
+					this.isFirstBorder = true;
+				}
+
+				// 判断 group 里的第一个 item
+				if (this.group) {
+					if (!this.group.isFirstBorder) {
+						this.group.isFirstBorder = true;
+						this.isFirstBorder = true;
+					}
+				}
+				this.border = this.form.border;
+				// 获取子域的真实名称
+				const name = _realName(this.name)
+				const itemRule = this.userRules || this.rules
+				if (typeof formRules === 'object' && itemRule) {
+					// 子规则替换父规则
+					formRules[name] = {
+						rules: itemRule
+					}
+					validator.updateSchema(formRules);
+				}
+				// 注册校验规则
+				const itemRules = formRules[name] || {}
+				this.itemRules = itemRules
+				// 注册校验函数
+				this.validator = validator
+				// 默认值赋予
+				this.itemSetValue(_getDataValue(this.name, localData))
+				this.isRequired = this._isRequired()
+
+			},
+			unInit() {
+				if (this.form) {
+					const {
+						childrens,
+						formData,
+						_realName
+					} = this.form
+					childrens.forEach((item, index) => {
+						if (item === this) {
+							this.form.childrens.splice(index, 1)
+							delete formData[_realName(item.name)]
+						}
+					})
+				}
+			},
+			// 设置item 的值
+			itemSetValue(value) {
+				const name = this.form._realName(this.name)
+				const rules = this.itemRules.rules || []
+				const val = this.form._getValue(name, value, rules)
+				this.form._setDataValue(name, this.form.formData, val)
+				return val
+			},
+
+			/**
+			 * 移除该表单项的校验结果
+			 */
+			clearValidate() {
+				this.errMsg = '';
+			},
+
+			// 是否显示星号
+			_isRequired() {
+				if (this.form) {
+					return this.required || this.form._isRequiredField(this.itemRules.rules || [])
+				}
+				return this.required
+			},
+
+			// 处理对齐方式
+			_justifyContent() {
+				if (this.form) {
+					const {
+						labelAlign
+					} = this.form
+					let labelAli = this.labelAlign ? this.labelAlign : labelAlign;
+					if (labelAli === 'left') return 'flex-start';
+					if (labelAli === 'center') return 'center';
+					if (labelAli === 'right') return 'flex-end';
+				}
+				return 'flex-start';
+			},
+			// 处理 label宽度单位 ,继承父元素的值
+			_labelWidthUnit(labelWidth) {
+
+				// if (this.form) {
+				// 	const {
+				// 		labelWidth
+				// 	} = this.form
+				return this.num2px(this.labelWidth ? this.labelWidth : (labelWidth || (this.label ? 65 : 'auto')))
+				// }
+				// return '65px'
+			},
+			// 处理 label 位置
+			_labelPosition() {
+				if (this.form) return this.form.labelPosition || 'left'
+				return 'left'
+
+			},
+
+			/**
+			 * 触发时机
+			 * @param {Object} rule 当前规则内时机
+			 * @param {Object} itemRlue 当前组件时机
+			 * @param {Object} parentRule 父组件时机
+			 */
+			isTrigger(rule, itemRlue, parentRule) {
+				//  bind  submit
+				if (rule === 'submit' || !rule) {
+					if (rule === undefined) {
+						if (itemRlue !== 'bind') {
+							if (!itemRlue) {
+								return parentRule === '' ? 'bind' : 'submit';
+							}
+							return 'submit';
+						}
+						return 'bind';
+					}
+					return 'submit';
+				}
+				return 'bind';
+			},
+			num2px(num) {
+				if (typeof num === 'number') {
+					return `${num}px`
+				}
+				return num
+			}
+		}
+	};
+</script>
+
+<style lang="scss">
+	.uni-forms-item {
+		position: relative;
+		display: flex;
+		/* #ifdef APP-NVUE */
+		// 在 nvue 中,使用 margin-bottom error 信息会被隐藏
+		padding-bottom: 22px;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		margin-bottom: 22px;
+		/* #endif */
+		flex-direction: row;
+
+		&__label {
+			display: flex;
+			flex-direction: row;
+			align-items: center;
+			text-align: left;
+			font-size: 14px;
+			color: #606266;
+			height: 36px;
+			padding: 0 12px 0 0;
+			/* #ifndef APP-NVUE */
+			vertical-align: middle;
+			flex-shrink: 0;
+			/* #endif */
+
+			/* #ifndef APP-NVUE */
+			box-sizing: border-box;
+
+			/* #endif */
+			&.no-label {
+				padding: 0;
+			}
+		}
+
+		&__content {
+			/* #ifndef MP-TOUTIAO */
+			// display: flex;
+			// align-items: center;
+			/* #endif */
+			position: relative;
+			font-size: 14px;
+			flex: 1;
+			/* #ifndef APP-NVUE */
+			box-sizing: border-box;
+			/* #endif */
+			flex-direction: row;
+
+			/* #ifndef APP || H5 || MP-WEIXIN || APP-NVUE */
+			// TODO 因为小程序平台会多一层标签节点 ,所以需要在多余节点继承当前样式
+			&>uni-easyinput,
+			&>uni-data-picker {
+				width: 100%;
+			}
+
+			/* #endif */
+
+		}
+
+		& .uni-forms-item__nuve-content {
+			display: flex;
+			flex-direction: column;
+			flex: 1;
+		}
+
+		&__error {
+			color: #f56c6c;
+			font-size: 12px;
+			line-height: 1;
+			padding-top: 4px;
+			position: absolute;
+			/* #ifndef APP-NVUE */
+			top: 100%;
+			left: 0;
+			transition: transform 0.3s;
+			transform: translateY(-100%);
+			/* #endif */
+			/* #ifdef APP-NVUE */
+			bottom: 5px;
+			/* #endif */
+
+			opacity: 0;
+
+			.error-text {
+				// 只有 nvue 下这个样式才生效
+				color: #f56c6c;
+				font-size: 12px;
+			}
+
+			&.msg--active {
+				opacity: 1;
+				transform: translateY(0%);
+			}
+		}
+
+		// 位置修饰样式
+		&.is-direction-left {
+			flex-direction: row;
+		}
+
+		&.is-direction-top {
+			flex-direction: column;
+
+			.uni-forms-item__label {
+				padding: 0 0 8px;
+				line-height: 1.5715;
+				text-align: left;
+				/* #ifndef APP-NVUE */
+				white-space: initial;
+				/* #endif */
+			}
+		}
+
+		.is-required {
+			// color: $uni-color-error;
+			color: #dd524d;
+			font-weight: bold;
+		}
+	}
+
+
+	.uni-forms-item--border {
+		margin-bottom: 0;
+		padding: 10px 0;
+		// padding-bottom: 0;
+		border-top: 1px #eee solid;
+
+		/* #ifndef APP-NVUE */
+		.uni-forms-item__content {
+			flex-direction: column;
+			justify-content: flex-start;
+			align-items: flex-start;
+
+			.uni-forms-item__error {
+				position: relative;
+				top: 5px;
+				left: 0;
+				padding-top: 0;
+			}
+		}
+
+		/* #endif */
+
+		/* #ifdef APP-NVUE */
+		display: flex;
+		flex-direction: column;
+
+		.uni-forms-item__error {
+			position: relative;
+			top: 0px;
+			left: 0;
+			padding-top: 0;
+			margin-top: 5px;
+		}
+
+		/* #endif */
+
+	}
+
+	.is-first-border {
+		/* #ifndef APP-NVUE */
+		border: none;
+		/* #endif */
+		/* #ifdef APP-NVUE */
+		border-width: 0;
+		/* #endif */
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-forms/components/uni-forms/uni-forms.vue b/yudao-ui-admin-uniapp/uni_modules/uni-forms/components/uni-forms/uni-forms.vue
new file mode 100644
index 000000000..ed2f6d971
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-forms/components/uni-forms/uni-forms.vue
@@ -0,0 +1,397 @@
+<template>
+	<view class="uni-forms">
+		<form>
+			<slot></slot>
+		</form>
+	</view>
+</template>
+
+<script>
+	import Validator from './validate.js';
+	import {
+		deepCopy,
+		getValue,
+		isRequiredField,
+		setDataValue,
+		getDataValue,
+		realName,
+		isRealName,
+		rawData,
+		isEqual
+	} from './utils.js'
+
+	// #ifndef VUE3
+	// 后续会慢慢废弃这个方法
+	import Vue from 'vue';
+	Vue.prototype.binddata = function(name, value, formName) {
+		if (formName) {
+			this.$refs[formName].setValue(name, value);
+		} else {
+			let formVm;
+			for (let i in this.$refs) {
+				const vm = this.$refs[i];
+				if (vm && vm.$options && vm.$options.name === 'uniForms') {
+					formVm = vm;
+					break;
+				}
+			}
+			if (!formVm) return console.error('当前 uni-froms 组件缺少 ref 属性');
+			formVm.setValue(name, value);
+		}
+	};
+	// #endif
+	/**
+	 * Forms 表单
+	 * @description 由输入框、选择器、单选框、多选框等控件组成,用以收集、校验、提交数据
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=2773
+	 * @property {Object} rules	表单校验规则
+	 * @property {String} validateTrigger = [bind|submit|blur]	校验触发器方式 默认 submit
+	 * @value bind		发生变化时触发
+	 * @value submit	提交时触发
+	 * @value blur	  失去焦点时触发
+	 * @property {String} labelPosition = [top|left]	label 位置 默认 left
+	 * @value top		顶部显示 label
+	 * @value left	左侧显示 label
+	 * @property {String} labelWidth	label 宽度,默认 65px
+	 * @property {String} labelAlign = [left|center|right]	label 居中方式  默认 left
+	 * @value left		label 左侧显示
+	 * @value center	label 居中
+	 * @value right		label 右侧对齐
+	 * @property {String} errShowType = [undertext|toast|modal]	校验错误信息提示方式
+	 * @value undertext	错误信息在底部显示
+	 * @value toast			错误信息toast显示
+	 * @value modal			错误信息modal显示
+	 * @event {Function} submit	提交时触发
+	 * @event {Function} validate	校验结果发生变化触发
+	 */
+	export default {
+		name: 'uniForms',
+		emits: ['validate', 'submit'],
+		options: {
+			virtualHost: true
+		},
+		props: {
+			// 即将弃用
+			value: {
+				type: Object,
+				default () {
+					return null;
+				}
+			},
+			// vue3 替换 value 属性
+			modelValue: {
+				type: Object,
+				default () {
+					return null;
+				}
+			},
+			// 1.4.0 开始将不支持 v-model ,且废弃 value 和 modelValue
+			model: {
+				type: Object,
+				default () {
+					return null;
+				}
+			},
+			// 表单校验规则
+			rules: {
+				type: Object,
+				default () {
+					return {};
+				}
+			},
+			//校验错误信息提示方式 默认 undertext 取值 [undertext|toast|modal]
+			errShowType: {
+				type: String,
+				default: 'undertext'
+			},
+			// 校验触发器方式 默认 bind 取值 [bind|submit]
+			validateTrigger: {
+				type: String,
+				default: 'submit'
+			},
+			// label 位置,默认 left 取值  top/left
+			labelPosition: {
+				type: String,
+				default: 'left'
+			},
+			// label 宽度
+			labelWidth: {
+				type: [String, Number],
+				default: ''
+			},
+			// label 居中方式,默认 left 取值 left/center/right
+			labelAlign: {
+				type: String,
+				default: 'left'
+			},
+			border: {
+				type: Boolean,
+				default: false
+			}
+		},
+		provide() {
+			return {
+				uniForm: this
+			}
+		},
+		data() {
+			return {
+				// 表单本地值的记录,不应该与传如的值进行关联
+				formData: {},
+				formRules: {}
+			};
+		},
+		computed: {
+			// 计算数据源变化的
+			localData() {
+				const localVal = this.model || this.modelValue || this.value
+				if (localVal) {
+					return deepCopy(localVal)
+				}
+				return {}
+			}
+		},
+		watch: {
+			// 监听数据变化 ,暂时不使用,需要单独赋值
+			// localData: {},
+			// 监听规则变化
+			rules: {
+				handler: function(val, oldVal) {
+					this.setRules(val)
+				},
+				deep: true,
+				immediate: true
+			}
+		},
+		created() {
+			// #ifdef VUE3
+			let getbinddata = getApp().$vm.$.appContext.config.globalProperties.binddata
+			if (!getbinddata) {
+				getApp().$vm.$.appContext.config.globalProperties.binddata = function(name, value, formName) {
+					if (formName) {
+						this.$refs[formName].setValue(name, value);
+					} else {
+						let formVm;
+						for (let i in this.$refs) {
+							const vm = this.$refs[i];
+							if (vm && vm.$options && vm.$options.name === 'uniForms') {
+								formVm = vm;
+								break;
+							}
+						}
+						if (!formVm) return console.error('当前 uni-froms 组件缺少 ref 属性');
+						formVm.setValue(name, value);
+					}
+				}
+			}
+			// #endif
+
+			// 子组件实例数组
+			this.childrens = []
+			// TODO 兼容旧版 uni-data-picker ,新版本中无效,只是避免报错
+			this.inputChildrens = []
+			this.setRules(this.rules)
+		},
+		methods: {
+			/**
+			 * 外部调用方法
+			 * 设置规则 ,主要用于小程序自定义检验规则
+			 * @param {Array} rules 规则源数据
+			 */
+			setRules(rules) {
+				// TODO 有可能子组件合并规则的时机比这个要早,所以需要合并对象 ,而不是直接赋值,可能会被覆盖
+				this.formRules = Object.assign({}, this.formRules, rules)
+				// 初始化校验函数
+				this.validator = new Validator(rules);
+			},
+
+			/**
+			 * 外部调用方法
+			 * 设置数据,用于设置表单数据,公开给用户使用 , 不支持在动态表单中使用
+			 * @param {Object} key
+			 * @param {Object} value
+			 */
+			setValue(key, value) {
+				let example = this.childrens.find(child => child.name === key);
+				if (!example) return null;
+				this.formData[key] = getValue(key, value, (this.formRules[key] && this.formRules[key].rules) || [])
+				return example.onFieldChange(this.formData[key]);
+			},
+
+			/**
+			 * 外部调用方法
+			 * 手动提交校验表单
+			 * 对整个表单进行校验的方法,参数为一个回调函数。
+			 * @param {Array} keepitem 保留不参与校验的字段
+			 * @param {type} callback 方法回调
+			 */
+			validate(keepitem, callback) {
+				return this.checkAll(this.formData, keepitem, callback);
+			},
+
+			/**
+			 * 外部调用方法
+			 * 部分表单校验
+			 * @param {Array|String} props 需要校验的字段
+			 * @param {Function} 回调函数
+			 */
+			validateField(props = [], callback) {
+				props = [].concat(props);
+				let invalidFields = {};
+				this.childrens.forEach(item => {
+					const name = realName(item.name)
+					if (props.indexOf(name) !== -1) {
+						invalidFields = Object.assign({}, invalidFields, {
+							[name]: this.formData[name]
+						});
+					}
+				});
+				return this.checkAll(invalidFields, [], callback);
+			},
+
+			/**
+			 * 外部调用方法
+			 * 移除表单项的校验结果。传入待移除的表单项的 prop 属性或者 prop 组成的数组,如不传则移除整个表单的校验结果
+			 * @param {Array|String} props 需要移除校验的字段 ,不填为所有
+			 */
+			clearValidate(props = []) {
+				props = [].concat(props);
+				this.childrens.forEach(item => {
+					if (props.length === 0) {
+						item.errMsg = '';
+					} else {
+						const name = realName(item.name)
+						if (props.indexOf(name) !== -1) {
+							item.errMsg = '';
+						}
+					}
+				});
+			},
+
+			/**
+			 * 外部调用方法 ,即将废弃
+			 * 手动提交校验表单
+			 * 对整个表单进行校验的方法,参数为一个回调函数。
+			 * @param {Array} keepitem 保留不参与校验的字段
+			 * @param {type} callback 方法回调
+			 */
+			submit(keepitem, callback, type) {
+				for (let i in this.dataValue) {
+					const itemData = this.childrens.find(v => v.name === i);
+					if (itemData) {
+						if (this.formData[i] === undefined) {
+							this.formData[i] = this._getValue(i, this.dataValue[i]);
+						}
+					}
+				}
+
+				if (!type) {
+					console.warn('submit 方法即将废弃,请使用validate方法代替!');
+				}
+
+				return this.checkAll(this.formData, keepitem, callback, 'submit');
+			},
+
+			// 校验所有
+			async checkAll(invalidFields, keepitem, callback, type) {
+				// 不存在校验规则 ,则停止校验流程
+				if (!this.validator) return
+				let childrens = []
+				// 处理参与校验的item实例
+				for (let i in invalidFields) {
+					const item = this.childrens.find(v => realName(v.name) === i)
+					if (item) {
+						childrens.push(item)
+					}
+				}
+
+				// 如果validate第一个参数是funciont ,那就走回调
+				if (!callback && typeof keepitem === 'function') {
+					callback = keepitem;
+				}
+
+				let promise;
+				// 如果不存在回调,那么使用 Promise 方式返回
+				if (!callback && typeof callback !== 'function' && Promise) {
+					promise = new Promise((resolve, reject) => {
+						callback = function(valid, invalidFields) {
+							!valid ? resolve(invalidFields) : reject(valid);
+						};
+					});
+				}
+
+				let results = [];
+				// 避免引用错乱 ,建议拷贝对象处理
+				let tempFormData = JSON.parse(JSON.stringify(invalidFields))
+				// 所有子组件参与校验,使用 for 可以使用  awiat
+				for (let i in childrens) {
+					const child = childrens[i]
+					let name = realName(child.name);
+					const result = await child.onFieldChange(tempFormData[name]);
+					if (result) {
+						results.push(result);
+						// toast ,modal 只需要执行第一次就可以
+						if (this.errShowType === 'toast' || this.errShowType === 'modal') break;
+					}
+				}
+
+
+				if (Array.isArray(results)) {
+					if (results.length === 0) results = null;
+				}
+				if (Array.isArray(keepitem)) {
+					keepitem.forEach(v => {
+						let vName = realName(v);
+						let value = getDataValue(v, this.localData)
+						if (value !== undefined) {
+							tempFormData[vName] = value
+						}
+					});
+				}
+
+				// TODO submit 即将废弃
+				if (type === 'submit') {
+					this.$emit('submit', {
+						detail: {
+							value: tempFormData,
+							errors: results
+						}
+					});
+				} else {
+					this.$emit('validate', results);
+				}
+
+				// const resetFormData = rawData(tempFormData, this.localData, this.name)
+				let resetFormData = {}
+				resetFormData = rawData(tempFormData, this.name)
+				callback && typeof callback === 'function' && callback(results, resetFormData);
+
+				if (promise && callback) {
+					return promise;
+				} else {
+					return null;
+				}
+
+			},
+
+			/**
+			 * 返回validate事件
+			 * @param {Object} result
+			 */
+			validateCheck(result) {
+				this.$emit('validate', result);
+			},
+			_getValue: getValue,
+			_isRequiredField: isRequiredField,
+			_setDataValue: setDataValue,
+			_getDataValue: getDataValue,
+			_realName: realName,
+			_isRealName: isRealName,
+			_isEqual: isEqual
+		}
+	};
+</script>
+
+<style lang="scss">
+	.uni-forms {}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-forms/components/uni-forms/utils.js b/yudao-ui-admin-uniapp/uni_modules/uni-forms/components/uni-forms/utils.js
new file mode 100644
index 000000000..6da242165
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-forms/components/uni-forms/utils.js
@@ -0,0 +1,293 @@
+/**
+ * 简单处理对象拷贝
+ * @param {Obejct} 被拷贝对象
+ * @@return {Object} 拷贝对象
+ */
+export const deepCopy = (val) => {
+	return JSON.parse(JSON.stringify(val))
+}
+/**
+ * 过滤数字类型
+ * @param {String} format 数字类型
+ * @@return {Boolean} 返回是否为数字类型
+ */
+export const typeFilter = (format) => {
+	return format === 'int' || format === 'double' || format === 'number' || format === 'timestamp';
+}
+
+/**
+ * 把 value 转换成指定的类型,用于处理初始值,原因是初始值需要入库不能为 undefined
+ * @param {String} key 字段名
+ * @param {any} value 字段值
+ * @param {Object} rules 表单校验规则
+ */
+export const getValue = (key, value, rules) => {
+	const isRuleNumType = rules.find(val => val.format && typeFilter(val.format));
+	const isRuleBoolType = rules.find(val => (val.format && val.format === 'boolean') || val.format === 'bool');
+	// 输入类型为 number
+	if (!!isRuleNumType) {
+		if (!value && value !== 0) {
+			value = null
+		} else {
+			value = isNumber(Number(value)) ? Number(value) : value
+		}
+	}
+
+	// 输入类型为 boolean
+	if (!!isRuleBoolType) {
+		value = isBoolean(value) ? value : false
+	}
+
+	return value;
+}
+
+/**
+ * 获取表单数据
+ * @param {String|Array} name 真实名称,需要使用 realName 获取
+ * @param {Object} data 原始数据
+ * @param {any} value  需要设置的值
+ */
+export const setDataValue = (field, formdata, value) => {
+	formdata[field] = value
+	return value || ''
+}
+
+/**
+ * 获取表单数据
+ * @param {String|Array} field 真实名称,需要使用 realName 获取
+ * @param {Object} data 原始数据
+ */
+export const getDataValue = (field, data) => {
+	return objGet(data, field)
+}
+
+/**
+ * 获取表单类型
+ * @param {String|Array} field 真实名称,需要使用 realName 获取
+ */
+export const getDataValueType = (field, data) => {
+	const value = getDataValue(field, data)
+	return {
+		type: type(value),
+		value
+	}
+}
+
+/**
+ * 获取表单可用的真实name
+ * @param {String|Array} name 表单name
+ * @@return {String} 表单可用的真实name
+ */
+export const realName = (name, data = {}) => {
+	const base_name = _basePath(name)
+	if (typeof base_name === 'object' && Array.isArray(base_name) && base_name.length > 1) {
+		const realname = base_name.reduce((a, b) => a += `#${b}`, '_formdata_')
+		return realname
+	}
+	return base_name[0] || name
+}
+
+/**
+ * 判断是否表单可用的真实name
+ * @param {String|Array} name 表单name
+ * @@return {String} 表单可用的真实name
+ */
+export const isRealName = (name) => {
+	const reg = /^_formdata_#*/
+	return reg.test(name)
+}
+
+/**
+ * 获取表单数据的原始格式
+ * @@return {Object|Array} object 需要解析的数据
+ */
+export const rawData = (object = {}, name) => {
+	let newData = JSON.parse(JSON.stringify(object))
+	let formData = {}
+	for(let i in newData){
+		let path = name2arr(i)
+		objSet(formData,path,newData[i])
+	}
+	return formData
+}
+
+/**
+ * 真实name还原为 array
+ * @param {*} name 
+ */
+export const name2arr = (name) => {
+	let field = name.replace('_formdata_#', '')
+	field = field.split('#').map(v => (isNumber(v) ? Number(v) : v))
+	return field
+}
+
+/**
+ * 对象中设置值
+ * @param {Object|Array} object 源数据
+ * @param {String| Array} path 'a.b.c' 或 ['a',0,'b','c']
+ * @param {String} value 需要设置的值
+ */
+export const objSet = (object, path, value) => {
+	if (typeof object !== 'object') return object;
+	_basePath(path).reduce((o, k, i, _) => {
+		if (i === _.length - 1) { 
+			// 若遍历结束直接赋值
+			o[k] = value
+			return null
+		} else if (k in o) { 
+			// 若存在对应路径,则返回找到的对象,进行下一次遍历
+			return o[k]
+		} else { 
+			// 若不存在对应路径,则创建对应对象,若下一路径是数字,新对象赋值为空数组,否则赋值为空对象
+			o[k] = /^[0-9]{1,}$/.test(_[i + 1]) ? [] : {}
+			return o[k]
+		}
+	}, object)
+	// 返回object
+	return object;
+}
+
+// 处理 path, path有三种形式:'a[0].b.c'、'a.0.b.c' 和 ['a','0','b','c'],需要统一处理成数组,便于后续使用
+function _basePath(path) {
+	// 若是数组,则直接返回
+	if (Array.isArray(path)) return path
+	// 若有 '[',']',则替换成将 '[' 替换成 '.',去掉 ']'
+	return path.replace(/\[/g, '.').replace(/\]/g, '').split('.')
+}
+
+/**
+ * 从对象中获取值
+ * @param {Object|Array} object 源数据
+ * @param {String| Array} path 'a.b.c' 或 ['a',0,'b','c']
+ * @param {String} defaultVal 如果无法从调用链中获取值的默认值
+ */
+export const objGet = (object, path, defaultVal = 'undefined') => {
+	// 先将path处理成统一格式
+	let newPath = _basePath(path)
+	// 递归处理,返回最后结果
+	let val = newPath.reduce((o, k) => {
+		return (o || {})[k]
+	}, object);
+	return !val || val !== undefined ? val : defaultVal
+}
+
+
+/**
+ * 是否为 number 类型 
+ * @param {any} num 需要判断的值
+ * @return {Boolean} 是否为 number
+ */
+export const isNumber = (num) => {
+	return !isNaN(Number(num))
+}
+
+/**
+ * 是否为 boolean 类型 
+ * @param {any} bool 需要判断的值
+ * @return {Boolean} 是否为 boolean
+ */
+export const isBoolean = (bool) => {
+	return (typeof bool === 'boolean')
+}
+/**
+ * 是否有必填字段
+ * @param {Object} rules 规则
+ * @return {Boolean} 是否有必填字段
+ */
+export const isRequiredField = (rules) => {
+	let isNoField = false;
+	for (let i = 0; i < rules.length; i++) {
+		const ruleData = rules[i];
+		if (ruleData.required) {
+			isNoField = true;
+			break;
+		}
+	}
+	return isNoField;
+}
+
+
+/**
+ * 获取数据类型
+ * @param {Any} obj 需要获取数据类型的值
+ */
+export const type = (obj) => {
+	var class2type = {};
+
+	// 生成class2type映射
+	"Boolean Number String Function Array Date RegExp Object Error".split(" ").map(function(item, index) {
+		class2type["[object " + item + "]"] = item.toLowerCase();
+	})
+	if (obj == null) {
+		return obj + "";
+	}
+	return typeof obj === "object" || typeof obj === "function" ?
+		class2type[Object.prototype.toString.call(obj)] || "object" :
+		typeof obj;
+}
+
+/**
+ * 判断两个值是否相等
+ * @param {any} a 值  
+ * @param {any} b 值  
+ * @return {Boolean} 是否相等
+ */
+export const isEqual = (a, b) => {
+	//如果a和b本来就全等
+	if (a === b) {
+		//判断是否为0和-0
+		return a !== 0 || 1 / a === 1 / b;
+	}
+	//判断是否为null和undefined
+	if (a == null || b == null) {
+		return a === b;
+	}
+	//接下来判断a和b的数据类型
+	var classNameA = toString.call(a),
+		classNameB = toString.call(b);
+	//如果数据类型不相等,则返回false
+	if (classNameA !== classNameB) {
+		return false;
+	}
+	//如果数据类型相等,再根据不同数据类型分别判断
+	switch (classNameA) {
+		case '[object RegExp]':
+		case '[object String]':
+			//进行字符串转换比较
+			return '' + a === '' + b;
+		case '[object Number]':
+			//进行数字转换比较,判断是否为NaN
+			if (+a !== +a) {
+				return +b !== +b;
+			}
+			//判断是否为0或-0
+			return +a === 0 ? 1 / +a === 1 / b : +a === +b;
+		case '[object Date]':
+		case '[object Boolean]':
+			return +a === +b;
+	}
+	//如果是对象类型
+	if (classNameA == '[object Object]') {
+		//获取a和b的属性长度
+		var propsA = Object.getOwnPropertyNames(a),
+			propsB = Object.getOwnPropertyNames(b);
+		if (propsA.length != propsB.length) {
+			return false;
+		}
+		for (var i = 0; i < propsA.length; i++) {
+			var propName = propsA[i];
+			//如果对应属性对应值不相等,则返回false
+			if (a[propName] !== b[propName]) {
+				return false;
+			}
+		}
+		return true;
+	}
+	//如果是数组类型
+	if (classNameA == '[object Array]') {
+		if (a.toString() == b.toString()) {
+			return true;
+		}
+		return false;
+	}
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-forms/components/uni-forms/validate.js b/yudao-ui-admin-uniapp/uni_modules/uni-forms/components/uni-forms/validate.js
new file mode 100644
index 000000000..1834c6cf6
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-forms/components/uni-forms/validate.js
@@ -0,0 +1,486 @@
+var pattern = {
+	email: /^\S+?@\S+?\.\S+?$/,
+	idcard: /^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/,
+	url: new RegExp(
+		"^(?!mailto:)(?:(?:http|https|ftp)://|//)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-*)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-*)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?$",
+		'i')
+};
+
+const FORMAT_MAPPING = {
+	"int": 'integer',
+	"bool": 'boolean',
+	"double": 'number',
+	"long": 'number',
+	"password": 'string'
+	// "fileurls": 'array'
+}
+
+function formatMessage(args, resources = '') {
+	var defaultMessage = ['label']
+	defaultMessage.forEach((item) => {
+		if (args[item] === undefined) {
+			args[item] = ''
+		}
+	})
+
+	let str = resources
+	for (let key in args) {
+		let reg = new RegExp('{' + key + '}')
+		str = str.replace(reg, args[key])
+	}
+	return str
+}
+
+function isEmptyValue(value, type) {
+	if (value === undefined || value === null) {
+		return true;
+	}
+
+	if (typeof value === 'string' && !value) {
+		return true;
+	}
+
+	if (Array.isArray(value) && !value.length) {
+		return true;
+	}
+
+	if (type === 'object' && !Object.keys(value).length) {
+		return true;
+	}
+
+	return false;
+}
+
+const types = {
+	integer(value) {
+		return types.number(value) && parseInt(value, 10) === value;
+	},
+	string(value) {
+		return typeof value === 'string';
+	},
+	number(value) {
+		if (isNaN(value)) {
+			return false;
+		}
+		return typeof value === 'number';
+	},
+	"boolean": function(value) {
+		return typeof value === 'boolean';
+	},
+	"float": function(value) {
+		return types.number(value) && !types.integer(value);
+	},
+	array(value) {
+		return Array.isArray(value);
+	},
+	object(value) {
+		return typeof value === 'object' && !types.array(value);
+	},
+	date(value) {
+		return value instanceof Date;
+	},
+	timestamp(value) {
+		if (!this.integer(value) || Math.abs(value).toString().length > 16) {
+			return false
+		}
+		return true;
+	},
+	file(value) {
+		return typeof value.url === 'string';
+	},
+	email(value) {
+		return typeof value === 'string' && !!value.match(pattern.email) && value.length < 255;
+	},
+	url(value) {
+		return typeof value === 'string' && !!value.match(pattern.url);
+	},
+	pattern(reg, value) {
+		try {
+			return new RegExp(reg).test(value);
+		} catch (e) {
+			return false;
+		}
+	},
+	method(value) {
+		return typeof value === 'function';
+	},
+	idcard(value) {
+		return typeof value === 'string' && !!value.match(pattern.idcard);
+	},
+	'url-https'(value) {
+		return this.url(value) && value.startsWith('https://');
+	},
+	'url-scheme'(value) {
+		return value.startsWith('://');
+	},
+	'url-web'(value) {
+		return false;
+	}
+}
+
+class RuleValidator {
+
+	constructor(message) {
+		this._message = message
+	}
+
+	async validateRule(fieldKey, fieldValue, value, data, allData) {
+		var result = null
+
+		let rules = fieldValue.rules
+
+		let hasRequired = rules.findIndex((item) => {
+			return item.required
+		})
+		if (hasRequired < 0) {
+			if (value === null || value === undefined) {
+				return result
+			}
+			if (typeof value === 'string' && !value.length) {
+				return result
+			}
+		}
+
+		var message = this._message
+
+		if (rules === undefined) {
+			return message['default']
+		}
+
+		for (var i = 0; i < rules.length; i++) {
+			let rule = rules[i]
+			let vt = this._getValidateType(rule)
+
+			Object.assign(rule, {
+				label: fieldValue.label || `["${fieldKey}"]`
+			})
+
+			if (RuleValidatorHelper[vt]) {
+				result = RuleValidatorHelper[vt](rule, value, message)
+				if (result != null) {
+					break
+				}
+			}
+
+			if (rule.validateExpr) {
+				let now = Date.now()
+				let resultExpr = rule.validateExpr(value, allData, now)
+				if (resultExpr === false) {
+					result = this._getMessage(rule, rule.errorMessage || this._message['default'])
+					break
+				}
+			}
+
+			if (rule.validateFunction) {
+				result = await this.validateFunction(rule, value, data, allData, vt)
+				if (result !== null) {
+					break
+				}
+			}
+		}
+
+		if (result !== null) {
+			result = message.TAG + result
+		}
+
+		return result
+	}
+
+	async validateFunction(rule, value, data, allData, vt) {
+		let result = null
+		try {
+			let callbackMessage = null
+			const res = await rule.validateFunction(rule, value, allData || data, (message) => {
+				callbackMessage = message
+			})
+			if (callbackMessage || (typeof res === 'string' && res) || res === false) {
+				result = this._getMessage(rule, callbackMessage || res, vt)
+			}
+		} catch (e) {
+			result = this._getMessage(rule, e.message, vt)
+		}
+		return result
+	}
+
+	_getMessage(rule, message, vt) {
+		return formatMessage(rule, message || rule.errorMessage || this._message[vt] || message['default'])
+	}
+
+	_getValidateType(rule) {
+		var result = ''
+		if (rule.required) {
+			result = 'required'
+		} else if (rule.format) {
+			result = 'format'
+		} else if (rule.arrayType) {
+			result = 'arrayTypeFormat'
+		} else if (rule.range) {
+			result = 'range'
+		} else if (rule.maximum !== undefined || rule.minimum !== undefined) {
+			result = 'rangeNumber'
+		} else if (rule.maxLength !== undefined || rule.minLength !== undefined) {
+			result = 'rangeLength'
+		} else if (rule.pattern) {
+			result = 'pattern'
+		} else if (rule.validateFunction) {
+			result = 'validateFunction'
+		}
+		return result
+	}
+}
+
+const RuleValidatorHelper = {
+	required(rule, value, message) {
+		if (rule.required && isEmptyValue(value, rule.format || typeof value)) {
+			return formatMessage(rule, rule.errorMessage || message.required);
+		}
+
+		return null
+	},
+
+	range(rule, value, message) {
+		const {
+			range,
+			errorMessage
+		} = rule;
+
+		let list = new Array(range.length);
+		for (let i = 0; i < range.length; i++) {
+			const item = range[i];
+			if (types.object(item) && item.value !== undefined) {
+				list[i] = item.value;
+			} else {
+				list[i] = item;
+			}
+		}
+
+		let result = false
+		if (Array.isArray(value)) {
+			result = (new Set(value.concat(list)).size === list.length);
+		} else {
+			if (list.indexOf(value) > -1) {
+				result = true;
+			}
+		}
+
+		if (!result) {
+			return formatMessage(rule, errorMessage || message['enum']);
+		}
+
+		return null
+	},
+
+	rangeNumber(rule, value, message) {
+		if (!types.number(value)) {
+			return formatMessage(rule, rule.errorMessage || message.pattern.mismatch);
+		}
+
+		let {
+			minimum,
+			maximum,
+			exclusiveMinimum,
+			exclusiveMaximum
+		} = rule;
+		let min = exclusiveMinimum ? value <= minimum : value < minimum;
+		let max = exclusiveMaximum ? value >= maximum : value > maximum;
+
+		if (minimum !== undefined && min) {
+			return formatMessage(rule, rule.errorMessage || message['number'][exclusiveMinimum ?
+				'exclusiveMinimum' : 'minimum'
+			])
+		} else if (maximum !== undefined && max) {
+			return formatMessage(rule, rule.errorMessage || message['number'][exclusiveMaximum ?
+				'exclusiveMaximum' : 'maximum'
+			])
+		} else if (minimum !== undefined && maximum !== undefined && (min || max)) {
+			return formatMessage(rule, rule.errorMessage || message['number'].range)
+		}
+
+		return null
+	},
+
+	rangeLength(rule, value, message) {
+		if (!types.string(value) && !types.array(value)) {
+			return formatMessage(rule, rule.errorMessage || message.pattern.mismatch);
+		}
+
+		let min = rule.minLength;
+		let max = rule.maxLength;
+		let val = value.length;
+
+		if (min !== undefined && val < min) {
+			return formatMessage(rule, rule.errorMessage || message['length'].minLength)
+		} else if (max !== undefined && val > max) {
+			return formatMessage(rule, rule.errorMessage || message['length'].maxLength)
+		} else if (min !== undefined && max !== undefined && (val < min || val > max)) {
+			return formatMessage(rule, rule.errorMessage || message['length'].range)
+		}
+
+		return null
+	},
+
+	pattern(rule, value, message) {
+		if (!types['pattern'](rule.pattern, value)) {
+			return formatMessage(rule, rule.errorMessage || message.pattern.mismatch);
+		}
+
+		return null
+	},
+
+	format(rule, value, message) {
+		var customTypes = Object.keys(types);
+		var format = FORMAT_MAPPING[rule.format] ? FORMAT_MAPPING[rule.format] : (rule.format || rule.arrayType);
+
+		if (customTypes.indexOf(format) > -1) {
+			if (!types[format](value)) {
+				return formatMessage(rule, rule.errorMessage || message.typeError);
+			}
+		}
+
+		return null
+	},
+
+	arrayTypeFormat(rule, value, message) {
+		if (!Array.isArray(value)) {
+			return formatMessage(rule, rule.errorMessage || message.typeError);
+		}
+
+		for (let i = 0; i < value.length; i++) {
+			const element = value[i];
+			let formatResult = this.format(rule, element, message)
+			if (formatResult !== null) {
+				return formatResult
+			}
+		}
+
+		return null
+	}
+}
+
+class SchemaValidator extends RuleValidator {
+
+	constructor(schema, options) {
+		super(SchemaValidator.message);
+
+		this._schema = schema
+		this._options = options || null
+	}
+
+	updateSchema(schema) {
+		this._schema = schema
+	}
+
+	async validate(data, allData) {
+		let result = this._checkFieldInSchema(data)
+		if (!result) {
+			result = await this.invokeValidate(data, false, allData)
+		}
+		return result.length ? result[0] : null
+	}
+
+	async validateAll(data, allData) {
+		let result = this._checkFieldInSchema(data)
+		if (!result) {
+			result = await this.invokeValidate(data, true, allData)
+		}
+		return result
+	}
+
+	async validateUpdate(data, allData) {
+		let result = this._checkFieldInSchema(data)
+		if (!result) {
+			result = await this.invokeValidateUpdate(data, false, allData)
+		}
+		return result.length ? result[0] : null
+	}
+
+	async invokeValidate(data, all, allData) {
+		let result = []
+		let schema = this._schema
+		for (let key in schema) {
+			let value = schema[key]
+			let errorMessage = await this.validateRule(key, value, data[key], data, allData)
+			if (errorMessage != null) {
+				result.push({
+					key,
+					errorMessage
+				})
+				if (!all) break
+			}
+		}
+		return result
+	}
+
+	async invokeValidateUpdate(data, all, allData) {
+		let result = []
+		for (let key in data) {
+			let errorMessage = await this.validateRule(key, this._schema[key], data[key], data, allData)
+			if (errorMessage != null) {
+				result.push({
+					key,
+					errorMessage
+				})
+				if (!all) break
+			}
+		}
+		return result
+	}
+
+	_checkFieldInSchema(data) {
+		var keys = Object.keys(data)
+		var keys2 = Object.keys(this._schema)
+		if (new Set(keys.concat(keys2)).size === keys2.length) {
+			return ''
+		}
+
+		var noExistFields = keys.filter((key) => {
+			return keys2.indexOf(key) < 0;
+		})
+		var errorMessage = formatMessage({
+			field: JSON.stringify(noExistFields)
+		}, SchemaValidator.message.TAG + SchemaValidator.message['defaultInvalid'])
+		return [{
+			key: 'invalid',
+			errorMessage
+		}]
+	}
+}
+
+function Message() {
+	return {
+		TAG: "",
+		default: '验证错误',
+		defaultInvalid: '提交的字段{field}在数据库中并不存在',
+		validateFunction: '验证无效',
+		required: '{label}必填',
+		'enum': '{label}超出范围',
+		timestamp: '{label}格式无效',
+		whitespace: '{label}不能为空',
+		typeError: '{label}类型无效',
+		date: {
+			format: '{label}日期{value}格式无效',
+			parse: '{label}日期无法解析,{value}无效',
+			invalid: '{label}日期{value}无效'
+		},
+		length: {
+			minLength: '{label}长度不能少于{minLength}',
+			maxLength: '{label}长度不能超过{maxLength}',
+			range: '{label}必须介于{minLength}和{maxLength}之间'
+		},
+		number: {
+			minimum: '{label}不能小于{minimum}',
+			maximum: '{label}不能大于{maximum}',
+			exclusiveMinimum: '{label}不能小于等于{minimum}',
+			exclusiveMaximum: '{label}不能大于等于{maximum}',
+			range: '{label}必须介于{minimum}and{maximum}之间'
+		},
+		pattern: {
+			mismatch: '{label}格式不匹配'
+		}
+	};
+}
+
+
+SchemaValidator.message = new Message();
+
+export default SchemaValidator
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-forms/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-forms/package.json
new file mode 100644
index 000000000..e69d39b51
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-forms/package.json
@@ -0,0 +1,91 @@
+{
+  "id": "uni-forms",
+  "displayName": "uni-forms 表单",
+  "version": "1.4.6",
+  "description": "由输入框、选择器、单选框、多选框等控件组成,用以收集、校验、提交数据",
+  "keywords": [
+    "uni-ui",
+    "表单",
+    "校验",
+    "表单校验",
+    "表单验证"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": [
+			"uni-scss",
+      "uni-icons"
+    ],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+        "QQ": "y",
+        "京东": "u"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-forms/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-forms/readme.md
new file mode 100644
index 000000000..63d5a043e
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-forms/readme.md
@@ -0,0 +1,23 @@
+
+
+## Forms 表单
+
+> **组件名:uni-forms**
+> 代码块: `uForms`、`uni-forms-item`
+> 关联组件:`uni-forms-item`、`uni-easyinput`、`uni-data-checkbox`、`uni-group`。
+
+
+uni-app的内置组件已经有了 `<form>`组件,用于提交表单内容。
+
+然而几乎每个表单都需要做表单验证,为了方便做表单验证,减少重复开发,`uni ui` 又基于 `<form>`组件封装了 `<uni-forms>`组件,内置了表单验证功能。
+
+`<uni-forms>` 提供了 `rules`属性来描述校验规则、`<uni-forms-item>`子组件来包裹具体的表单项,以及给原生或三方组件提供了 `binddata()` 来设置表单值。
+
+每个要校验的表单项,不管input还是checkbox,都必须放在`<uni-forms-item>`组件中,且一个`<uni-forms-item>`组件只能放置一个表单项。
+
+`<uni-forms-item>`组件内部预留了显示error message的区域,默认是在表单项的底部。
+
+另外,`<uni-forms>`组件下面的各个表单项,可以通过`<uni-group>`包裹为不同的分组。同一`<uni-group>`下的不同表单项目将聚拢在一起,同其他group保持垂直间距。`<uni-group>`仅影响视觉效果。
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-forms)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-goods-nav/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-goods-nav/changelog.md
new file mode 100644
index 000000000..c6264c67e
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-goods-nav/changelog.md
@@ -0,0 +1,18 @@
+## 1.2.1(2022-05-30)
+- 新增 stat属性,是否开启uni统计功能
+## 1.2.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-goods-nav](https://uniapp.dcloud.io/component/uniui/uni-goods-nav)
+## 1.1.1(2021-08-24)
+- 新增 支持国际化
+## 1.1.0(2021-07-13)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.0.7(2021-05-12)
+- 新增 组件示例地址
+## 1.0.6(2021-04-21)
+- 优化 添加依赖 uni-icons, 导入后自动下载依赖
+## 1.0.5(2021-02-05)
+- 优化 组件引用关系,通过uni_modules引用组件
+
+## 1.0.4(2021-02-05)
+- 调整为uni_modules目录规范
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/en.json b/yudao-ui-admin-uniapp/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/en.json
new file mode 100644
index 000000000..dcdba41ce
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/en.json
@@ -0,0 +1,6 @@
+{
+	"uni-goods-nav.options.shop": "shop",
+	"uni-goods-nav.options.cart": "cart",
+	"uni-goods-nav.buttonGroup.addToCart": "add to cart",
+	"uni-goods-nav.buttonGroup.buyNow": "buy now"
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/index.js b/yudao-ui-admin-uniapp/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/index.js
new file mode 100644
index 000000000..de7509c87
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/index.js
@@ -0,0 +1,8 @@
+import en from './en.json'
+import zhHans from './zh-Hans.json'
+import zhHant from './zh-Hant.json'
+export default {
+	en,
+	'zh-Hans': zhHans,
+	'zh-Hant': zhHant
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/zh-Hans.json b/yudao-ui-admin-uniapp/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/zh-Hans.json
new file mode 100644
index 000000000..48ee344c3
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/zh-Hans.json
@@ -0,0 +1,6 @@
+{
+	"uni-goods-nav.options.shop": "店铺",
+	"uni-goods-nav.options.cart": "购物车",
+	"uni-goods-nav.buttonGroup.addToCart": "加入购物车",
+	"uni-goods-nav.buttonGroup.buyNow": "立即购买"
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/zh-Hant.json b/yudao-ui-admin-uniapp/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/zh-Hant.json
new file mode 100644
index 000000000..d0a0255c7
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-goods-nav/components/uni-goods-nav/i18n/zh-Hant.json
@@ -0,0 +1,6 @@
+{
+	"uni-goods-nav.options.shop": "店鋪",
+	"uni-goods-nav.options.cart": "購物車",
+	"uni-goods-nav.buttonGroup.addToCart": "加入購物車",
+	"uni-goods-nav.buttonGroup.buyNow": "立即購買"
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-goods-nav/components/uni-goods-nav/uni-goods-nav.vue b/yudao-ui-admin-uniapp/uni_modules/uni-goods-nav/components/uni-goods-nav/uni-goods-nav.vue
new file mode 100644
index 000000000..8a16b1755
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-goods-nav/components/uni-goods-nav/uni-goods-nav.vue
@@ -0,0 +1,229 @@
+<template>
+	<view class="uni-goods-nav">
+		<!-- 底部占位 -->
+		<view class="uni-tab__seat" />
+		<view class="uni-tab__cart-box flex">
+			<view class="flex uni-tab__cart-sub-left">
+				<view v-for="(item,index) in options" :key="index" class="flex uni-tab__cart-button-left uni-tab__shop-cart" @click="onClick(index,item)">
+					<view class="uni-tab__icon">
+						<uni-icons :type="item.icon" size="20" color="#646566"></uni-icons>
+						<!-- <image class="image" :src="item.icon" mode="widthFix" /> -->
+					</view>
+					<text class="uni-tab__text">{{ item.text }}</text>
+					<view class="flex uni-tab__dot-box">
+						<text v-if="item.info" :class="{ 'uni-tab__dots': item.info > 9 }" class="uni-tab__dot " :style="{'backgroundColor':item.infoBackgroundColor?item.infoBackgroundColor:'#ff0000',
+						color:item.infoColor?item.infoColor:'#fff'
+						}">{{ item.info }}</text>
+					</view>
+				</view>
+			</view>
+			<view :class="{'uni-tab__right':fill}" class="flex uni-tab__cart-sub-right ">
+				<view v-for="(item,index) in buttonGroup" :key="index" :style="{background:item.backgroundColor,color:item.color}"
+				 class="flex uni-tab__cart-button-right" @click="buttonClick(index,item)"><text :style="{color:item.color}" class="uni-tab__cart-button-right-text">{{ item.text }}</text></view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import {
+	initVueI18n
+	} from '@dcloudio/uni-i18n'
+	import messages from './i18n/index.js'
+	const {	t	} = initVueI18n(messages)
+	/**
+	 * GoodsNav 商品导航
+	 * @description 商品加入购物车、立即购买等
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=865
+	 * @property {Array} options 组件参数
+	 * @property {Array} buttonGroup 组件按钮组参数
+	 * @property {Boolean} fill = [true | false] 组件按钮组参数
+	 * @property {Boolean} stat 是否开启统计功能
+	 * @event {Function} click 左侧点击事件
+	 * @event {Function} buttonClick 右侧按钮组点击事件
+	 * @example <uni-goods-nav :fill="true"  options="" buttonGroup="buttonGroup"  @click="" @buttonClick="" />
+	 */
+	export default {
+		name: 'UniGoodsNav',
+		emits:['click','buttonClick'],
+		props: {
+			options: {
+				type: Array,
+				default () {
+					return [{
+						icon: 'shop',
+						text: t("uni-goods-nav.options.shop"),
+					}, {
+						icon: 'cart',
+						text: t("uni-goods-nav.options.cart")
+					}]
+				}
+			},
+			buttonGroup: {
+				type: Array,
+				default () {
+					return [{
+							text: t("uni-goods-nav.buttonGroup.addToCart"),
+							backgroundColor: 'linear-gradient(90deg, #FFCD1E, #FF8A18)',
+							color: '#fff'
+						},
+						{
+							text: t("uni-goods-nav.buttonGroup.buyNow"),
+							backgroundColor: 'linear-gradient(90deg, #FE6035, #EF1224)',
+							color: '#fff'
+						}
+					]
+				}
+			},
+			fill: {
+				type: Boolean,
+				default: false
+			},
+			stat:{
+				type: Boolean,
+				default: false
+			}
+		},
+		methods: {
+			onClick(index, item) {
+				this.$emit('click', {
+					index,
+					content: item,
+				})
+			},
+			buttonClick(index, item) {
+				if (uni.report && this.stat) {
+					uni.report(item.text, item.text)
+				}
+				this.$emit('buttonClick', {
+					index,
+					content: item
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss" >
+	.flex {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+	}
+
+	.uni-goods-nav {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex: 1;
+		flex-direction: row;
+	}
+
+	.uni-tab__cart-box {
+		flex: 1;
+		height: 50px;
+		background-color: #fff;
+		z-index: 900;
+	}
+
+	.uni-tab__cart-sub-left {
+		padding: 0 5px;
+	}
+
+	.uni-tab__cart-sub-right {
+		flex: 1;
+	}
+
+	.uni-tab__right {
+		margin: 5px 0;
+		margin-right: 10px;
+		border-radius: 100px;
+		overflow: hidden;
+	}
+
+	.uni-tab__cart-button-left {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		// flex: 1;
+		position: relative;
+		justify-content: center;
+		align-items: center;
+		flex-direction: column;
+		margin: 0 10px;
+		/* #ifdef H5 */
+		cursor: pointer;
+		/* #endif */
+	}
+
+	.uni-tab__icon {
+		width: 18px;
+		height: 18px;
+	}
+
+	.image {
+		width: 18px;
+		height: 18px;
+	}
+
+	.uni-tab__text {
+		margin-top: 3px;
+		font-size: 12px;
+		color: #646566;
+	}
+
+	.uni-tab__cart-button-right {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		flex-direction: column;
+		/* #endif */
+		flex: 1;
+		justify-content: center;
+		align-items: center;
+		/* #ifdef H5 */
+		cursor: pointer;
+		/* #endif */
+	}
+
+	.uni-tab__cart-button-right-text {
+		font-size: 14px;
+		color: #fff;
+	}
+
+	.uni-tab__cart-button-right:active {
+		opacity: 0.7;
+	}
+
+	.uni-tab__dot-box {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		flex-direction: column;
+		/* #endif */
+		position: absolute;
+		right: -2px;
+		top: 2px;
+		justify-content: center;
+		align-items: center;
+		// width: 0;
+		// height: 0;
+	}
+
+	.uni-tab__dot {
+		// width: 30rpx;
+		// height: 30rpx;
+		padding: 0 4px;
+		line-height: 15px;
+		color: #ffffff;
+		text-align: center;
+		font-size: 12px;
+		background-color: #ff0000;
+		border-radius: 15px;
+	}
+
+	.uni-tab__dots {
+		padding: 0 4px;
+		// width: auto;
+		border-radius: 15px;
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-goods-nav/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-goods-nav/package.json
new file mode 100644
index 000000000..636e45e7e
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-goods-nav/package.json
@@ -0,0 +1,88 @@
+{
+  "id": "uni-goods-nav",
+  "displayName": "uni-goods-nav 商品导航",
+  "version": "1.2.1",
+  "description": "商品导航组件主要用于电商类应用底部导航,可自定义加入购物车,购买等操作",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "商品导航"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": [
+			"uni-scss",
+			"uni-icons"
+		],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-goods-nav/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-goods-nav/readme.md
new file mode 100644
index 000000000..07df93f55
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-goods-nav/readme.md
@@ -0,0 +1,10 @@
+
+
+## GoodsNav 商品导航
+> **组件名:uni-goods-nav**
+> 代码块: `uGoodsNav`
+
+商品加入购物车,立即购买等。
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-goods-nav)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-grid/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-grid/changelog.md
new file mode 100644
index 000000000..d301166cf
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-grid/changelog.md
@@ -0,0 +1,13 @@
+## 1.4.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-grid](https://uniapp.dcloud.io/component/uniui/uni-grid)
+## 1.3.2(2021-11-09) 
+- 新增 提供组件设计资源,组件样式调整
+## 1.3.1(2021-07-30)
+- 优化 vue3下事件警告的问题
+## 1.3.0(2021-07-13)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.2.4(2021-05-12)
+- 新增 组件示例地址
+## 1.2.3(2021-02-05)
+- 调整为uni_modules目录规范
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-grid/components/uni-grid-item/uni-grid-item.vue b/yudao-ui-admin-uniapp/uni_modules/uni-grid/components/uni-grid-item/uni-grid-item.vue
new file mode 100644
index 000000000..20fd54e59
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-grid/components/uni-grid-item/uni-grid-item.vue
@@ -0,0 +1,127 @@
+<template>
+	<view v-if="width" :style="'width:'+width+';'+(square?'height:'+width:'')" class="uni-grid-item">
+		<view :class="{ 'uni-grid-item--border': showBorder,  'uni-grid-item--border-top': showBorder && index < column, 'uni-highlight': highlight }"
+		 :style="{'border-right-color': borderColor ,'border-bottom-color': borderColor ,'border-top-color': borderColor }"
+		 class="uni-grid-item__box" @click="_onClick">
+			<slot />
+		</view>
+	</view>
+</template>
+
+<script>
+	/**
+	 * GridItem 宫格
+	 * @description 宫格组件
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=27
+	 * @property {Number} index 子组件的唯一标识 ,点击gird会返回当前的标识
+	 */
+	export default {
+		name: 'UniGridItem',
+		inject: ['grid'],
+		props: {
+			index: {
+				type: Number,
+				default: 0
+			}
+		},
+		data() {
+			return {
+				column: 0,
+				showBorder: true,
+				square: true,
+				highlight: true,
+				left: 0,
+				top: 0,
+				openNum: 2,
+				width: 0,
+				borderColor: '#e5e5e5'
+			}
+		},
+		created() {
+			this.column = this.grid.column
+			this.showBorder = this.grid.showBorder
+			this.square = this.grid.square
+			this.highlight = this.grid.highlight
+			this.top = this.hor === 0 ? this.grid.hor : this.hor
+			this.left = this.ver === 0 ? this.grid.ver : this.ver
+			this.borderColor = this.grid.borderColor
+			this.grid.children.push(this)
+			// this.grid.init()
+			this.width = this.grid.width
+		},
+		beforeDestroy() {
+			this.grid.children.forEach((item, index) => {
+				if (item === this) {
+					this.grid.children.splice(index, 1)
+				}
+			})
+		},
+		methods: {
+			_onClick() {
+				this.grid.change({
+					detail: {
+						index: this.index
+					}
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss" >
+	.uni-grid-item {
+		/* #ifndef APP-NVUE */
+		height: 100%;
+		display: flex;
+		/* #endif */
+		/* #ifdef H5 */
+		cursor: pointer;
+		/* #endif */
+	}
+
+	.uni-grid-item__box {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		width: 100%;
+		/* #endif */
+		position: relative;
+		flex: 1;
+		flex-direction: column;
+		// justify-content: center;
+		// align-items: center;
+	}
+
+	.uni-grid-item--border {
+		position: relative;
+		/* #ifdef APP-NVUE */
+		border-bottom-color: #D2D2D2;
+		border-bottom-style: solid;
+		border-bottom-width: 0.5px;
+		border-right-color: #D2D2D2;
+		border-right-style: solid;
+		border-right-width: 0.5px;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		z-index: 0;
+		border-bottom: 1px #D2D2D2 solid;
+		border-right: 1px #D2D2D2 solid;
+		/* #endif */
+	}
+	.uni-grid-item--border-top {
+		position: relative;
+		/* #ifdef APP-NVUE */
+		border-top-color: #D2D2D2;
+		border-top-style: solid;
+		border-top-width: 0.5px;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		border-top: 1px #D2D2D2 solid;
+		z-index: 0;
+		/* #endif */
+	}
+
+
+	.uni-highlight:active {
+		background-color: #f1f1f1;
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-grid/components/uni-grid/uni-grid.vue b/yudao-ui-admin-uniapp/uni_modules/uni-grid/components/uni-grid/uni-grid.vue
new file mode 100644
index 000000000..96a412f6d
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-grid/components/uni-grid/uni-grid.vue
@@ -0,0 +1,142 @@
+<template>
+	<view class="uni-grid-wrap">
+		<view :id="elId" ref="uni-grid" class="uni-grid" :class="{ 'uni-grid--border': showBorder }" :style="{ 'border-left-color':borderColor}">
+			<slot />
+		</view>
+	</view>
+</template>
+
+<script>
+	// #ifdef APP-NVUE
+	const dom = uni.requireNativePlugin('dom');
+	// #endif
+
+	/**
+	 * Grid 宫格
+	 * @description 宫格组件
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=27
+	 * @property {Number} column 每列显示个数
+	 * @property {String} borderColor 边框颜色
+	 * @property {Boolean} showBorder 是否显示边框
+	 * @property {Boolean} square 是否方形显示
+	 * @property {Boolean} Boolean 点击背景是否高亮
+	 * @event {Function} change 点击 grid 触发,e={detail:{index:0}},index 为当前点击 gird 下标
+	 */
+	export default {
+		name: 'UniGrid',
+		emits:['change'],
+		props: {
+			// 每列显示个数
+			column: {
+				type: Number,
+				default: 3
+			},
+			// 是否显示边框
+			showBorder: {
+				type: Boolean,
+				default: true
+			},
+			// 边框颜色
+			borderColor: {
+				type: String,
+				default: '#D2D2D2'
+			},
+			// 是否正方形显示,默认为 true
+			square: {
+				type: Boolean,
+				default: true
+			},
+			highlight: {
+				type: Boolean,
+				default: true
+			}
+		},
+		provide() {
+			return {
+				grid: this
+			}
+		},
+		data() {
+			const elId = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`
+			return {
+				elId,
+				width: 0
+			}
+		},
+		created() {
+			this.children = []
+		},
+		mounted() {
+			this.$nextTick(()=>{
+				this.init()
+			})
+		},
+		methods: {
+			init() {
+				setTimeout(() => {
+					this._getSize((width) => {
+						this.children.forEach((item, index) => {
+							item.width = width
+						})
+					})
+				}, 50)
+			},
+			change(e) {
+				this.$emit('change', e)
+			},
+			_getSize(fn) {
+				// #ifndef APP-NVUE
+				uni.createSelectorQuery()
+					.in(this)
+					.select(`#${this.elId}`)
+					.boundingClientRect()
+					.exec(ret => {
+						this.width = parseInt((ret[0].width - 1) / this.column) + 'px'
+						fn(this.width)
+					})
+				// #endif
+				// #ifdef APP-NVUE
+				dom.getComponentRect(this.$refs['uni-grid'], (ret) => {
+					this.width = parseInt((ret.size.width - 1) / this.column) + 'px'
+					fn(this.width)
+				})
+				// #endif
+			}
+		}
+	}
+</script>
+
+<style lang="scss" >
+	.uni-grid-wrap {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex: 1;
+		flex-direction: column;
+		/* #ifdef H5 */
+		width: 100%;
+		/* #endif */
+	}
+
+	.uni-grid {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		// flex: 1;
+		flex-direction: row;
+		flex-wrap: wrap;
+	}
+
+	.uni-grid--border {
+		position: relative;
+		/* #ifdef APP-NVUE */
+		border-left-color: #D2D2D2;
+		border-left-style: solid;
+		border-left-width: 0.5px;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		z-index: 1;
+		border-left: 1px #D2D2D2 solid;
+		/* #endif */
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-grid/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-grid/package.json
new file mode 100644
index 000000000..ccb2c9171
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-grid/package.json
@@ -0,0 +1,86 @@
+{
+  "id": "uni-grid",
+  "displayName": "uni-grid 宫格",
+  "version": "1.4.0",
+  "description": "Grid 宫格组件,提供移动端常见的宫格布局,如九宫格。",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "九宫格",
+    "表格"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": ["uni-scss","uni-icons"],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-grid/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-grid/readme.md
new file mode 100644
index 000000000..0aa44cc13
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-grid/readme.md
@@ -0,0 +1,11 @@
+
+
+## Grid 宫格
+> **组件名:uni-grid**
+> 代码块: `uGrid`
+
+
+宫格组件。
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-grid)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-group/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-group/changelog.md
new file mode 100644
index 000000000..a7024fdf8
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-group/changelog.md
@@ -0,0 +1,16 @@
+## 1.2.2(2022-05-30)
+- 新增 stat属性,是否开启uni统计功能
+## 1.2.1(2021-11-22)
+- 修复 vue3中某些scss变量无法找到的问题
+## 1.2.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-group](https://uniapp.dcloud.io/component/uniui/uni-group)
+## 1.1.7(2021-11-08)
+## 1.1.0(2021-07-30)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+- 优化 组件文档
+## 1.0.3(2021-05-12)
+- 新增 组件示例地址
+## 1.0.2(2021-02-05)
+- 调整为uni_modules目录规范
+- 优化 兼容 nvue 页面
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-group/components/uni-group/uni-group.vue b/yudao-ui-admin-uniapp/uni_modules/uni-group/components/uni-group/uni-group.vue
new file mode 100644
index 000000000..3425ecd3a
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-group/components/uni-group/uni-group.vue
@@ -0,0 +1,134 @@
+<template>
+	<view class="uni-group" :class="['uni-group--'+mode ,margin?'group-margin':'']" :style="{marginTop: `${top}px` }">
+		<slot name="title">
+			<view v-if="title" class="uni-group__title" :style="{'padding-left':border?'30px':'15px'}">
+				<text class="uni-group__title-text">{{ title }}</text>
+			</view>
+		</slot>
+		<view class="uni-group__content" :class="{'group-conent-padding':border}">
+			<slot />
+		</view>
+	</view>
+</template>
+
+<script>
+	/**
+	 * Group 分组
+	 * @description 表单字段分组
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=3281
+	 * @property {String} title 主标题
+	 * @property {Number} top 分组间隔
+	 * @property {Number} mode 模式
+	 */
+	export default {
+		name: 'uniGroup',
+		emits:['click'],
+		props: {
+			title: {
+				type: String,
+				default: ''
+			},
+			top: {
+				type: [Number, String],
+				default: 10
+			},
+			mode: {
+				type: String,
+				default: 'default'
+			},
+			stat:{
+				type: Boolean,
+				default: false
+			}
+		},
+		data() {
+			return {
+				margin: false,
+				border: false
+			}
+		},
+		watch: {
+			title(newVal) {
+				if (uni.report && this.stat && newVal !== '') {
+					uni.report('title', newVal)
+				}
+			}
+		},
+		created() {
+			this.form = this.getForm()
+			if (this.form) {
+				this.margin = true
+				this.border = this.form.border
+			}
+		},
+		methods: {
+			/**
+			 * 获取父元素实例
+			 */
+			getForm() {
+				let parent = this.$parent;
+				let parentName = parent.$options.name;
+				while (parentName !== 'uniForms') {
+					parent = parent.$parent;
+					if (!parent) return false
+					parentName = parent.$options.name;
+				}
+				return parent;
+			},
+			onClick() {
+				this.$emit('click')
+			}
+		}
+	}
+</script>
+<style lang="scss" >
+	.uni-group {
+		background: #fff;
+		margin-top: 10px;
+		// border: 1px red solid;
+	}
+
+	.group-margin {
+		// margin: 0 -15px;
+	}
+
+	.uni-group__title {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		align-items: center;
+		padding-left: 15px;
+		height: 40px;
+		background-color: #eee;
+		font-weight: normal;
+		color: #666;
+	}
+
+	.uni-group__content {
+		padding: 15px;
+		// padding-bottom: 5px;
+		// background-color: #FFF;
+	}
+
+	.group-conent-padding {
+		padding: 0 15px;
+	}
+
+	.uni-group__title-text {
+		font-size: 14px;
+		color: #666;
+	}
+
+	.distraction {
+		flex-direction: row;
+		align-items: center;
+	}
+
+	.uni-group--card {
+		margin: 10px;
+		border-radius: 5px;
+		overflow: hidden;
+		box-shadow: 0 0 5px 1px rgba($color: #000000, $alpha: 0.08);
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-group/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-group/package.json
new file mode 100644
index 000000000..ea00a08c2
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-group/package.json
@@ -0,0 +1,87 @@
+{
+  "id": "uni-group",
+  "displayName": "uni-group 分组",
+  "version": "1.2.2",
+  "description": "分组组件可用于将组件用于分组,添加间隔,以产生明显的区块",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "group",
+    "分组",
+    ""
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": ["uni-scss"],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-group/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-group/readme.md
new file mode 100644
index 000000000..bae67f468
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-group/readme.md
@@ -0,0 +1,9 @@
+
+## Group 分组
+> **组件名:uni-group**
+> 代码块: `uGroup`
+
+分组组件可用于将组件分组,添加间隔,以产生明显的区块。
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-group)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-icons/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-icons/changelog.md
new file mode 100644
index 000000000..64498853c
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-icons/changelog.md
@@ -0,0 +1,22 @@
+## 1.3.5(2022-01-24)
+- 优化 size 属性可以传入不带单位的字符串数值
+## 1.3.4(2022-01-24)
+- 优化 size 支持其他单位
+## 1.3.3(2022-01-17)
+- 修复 nvue 有些图标不显示的bug,兼容老版本图标
+## 1.3.2(2021-12-01)
+- 优化 示例可复制图标名称
+## 1.3.1(2021-11-23)
+- 优化 兼容旧组件 type 值
+## 1.3.0(2021-11-19)
+- 新增 更多图标
+- 优化 自定义图标使用方式
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-icons](https://uniapp.dcloud.io/component/uniui/uni-icons)
+## 1.1.7(2021-11-08)
+## 1.2.0(2021-07-30)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.1.5(2021-05-12)
+- 新增 组件示例地址
+## 1.1.4(2021-02-05)
+- 调整为uni_modules目录规范
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-icons/components/uni-icons/icons.js b/yudao-ui-admin-uniapp/uni_modules/uni-icons/components/uni-icons/icons.js
new file mode 100644
index 000000000..78899364e
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-icons/components/uni-icons/icons.js
@@ -0,0 +1,1169 @@
+export default {
+  "id": "2852637",
+  "name": "uniui图标库",
+  "font_family": "uniicons",
+  "css_prefix_text": "uniui-",
+  "description": "",
+  "glyphs": [
+    {
+      "icon_id": "25027049",
+      "name": "yanse",
+      "font_class": "color",
+      "unicode": "e6cf",
+      "unicode_decimal": 59087
+    },
+    {
+      "icon_id": "25027048",
+      "name": "wallet",
+      "font_class": "wallet",
+      "unicode": "e6b1",
+      "unicode_decimal": 59057
+    },
+    {
+      "icon_id": "25015720",
+      "name": "settings-filled",
+      "font_class": "settings-filled",
+      "unicode": "e6ce",
+      "unicode_decimal": 59086
+    },
+    {
+      "icon_id": "25015434",
+      "name": "shimingrenzheng-filled",
+      "font_class": "auth-filled",
+      "unicode": "e6cc",
+      "unicode_decimal": 59084
+    },
+    {
+      "icon_id": "24934246",
+      "name": "shop-filled",
+      "font_class": "shop-filled",
+      "unicode": "e6cd",
+      "unicode_decimal": 59085
+    },
+    {
+      "icon_id": "24934159",
+      "name": "staff-filled-01",
+      "font_class": "staff-filled",
+      "unicode": "e6cb",
+      "unicode_decimal": 59083
+    },
+    {
+      "icon_id": "24932461",
+      "name": "VIP-filled",
+      "font_class": "vip-filled",
+      "unicode": "e6c6",
+      "unicode_decimal": 59078
+    },
+    {
+      "icon_id": "24932462",
+      "name": "plus_circle_fill",
+      "font_class": "plus-filled",
+      "unicode": "e6c7",
+      "unicode_decimal": 59079
+    },
+    {
+      "icon_id": "24932463",
+      "name": "folder_add-filled",
+      "font_class": "folder-add-filled",
+      "unicode": "e6c8",
+      "unicode_decimal": 59080
+    },
+    {
+      "icon_id": "24932464",
+      "name": "yanse-filled",
+      "font_class": "color-filled",
+      "unicode": "e6c9",
+      "unicode_decimal": 59081
+    },
+    {
+      "icon_id": "24932465",
+      "name": "tune-filled",
+      "font_class": "tune-filled",
+      "unicode": "e6ca",
+      "unicode_decimal": 59082
+    },
+    {
+      "icon_id": "24932455",
+      "name": "a-rilidaka-filled",
+      "font_class": "calendar-filled",
+      "unicode": "e6c0",
+      "unicode_decimal": 59072
+    },
+    {
+      "icon_id": "24932456",
+      "name": "notification-filled",
+      "font_class": "notification-filled",
+      "unicode": "e6c1",
+      "unicode_decimal": 59073
+    },
+    {
+      "icon_id": "24932457",
+      "name": "wallet-filled",
+      "font_class": "wallet-filled",
+      "unicode": "e6c2",
+      "unicode_decimal": 59074
+    },
+    {
+      "icon_id": "24932458",
+      "name": "paihangbang-filled",
+      "font_class": "medal-filled",
+      "unicode": "e6c3",
+      "unicode_decimal": 59075
+    },
+    {
+      "icon_id": "24932459",
+      "name": "gift-filled",
+      "font_class": "gift-filled",
+      "unicode": "e6c4",
+      "unicode_decimal": 59076
+    },
+    {
+      "icon_id": "24932460",
+      "name": "fire-filled",
+      "font_class": "fire-filled",
+      "unicode": "e6c5",
+      "unicode_decimal": 59077
+    },
+    {
+      "icon_id": "24928001",
+      "name": "refreshempty",
+      "font_class": "refreshempty",
+      "unicode": "e6bf",
+      "unicode_decimal": 59071
+    },
+    {
+      "icon_id": "24926853",
+      "name": "location-ellipse",
+      "font_class": "location-filled",
+      "unicode": "e6af",
+      "unicode_decimal": 59055
+    },
+    {
+      "icon_id": "24926735",
+      "name": "person-filled",
+      "font_class": "person-filled",
+      "unicode": "e69d",
+      "unicode_decimal": 59037
+    },
+    {
+      "icon_id": "24926703",
+      "name": "personadd-filled",
+      "font_class": "personadd-filled",
+      "unicode": "e698",
+      "unicode_decimal": 59032
+    },
+    {
+      "icon_id": "24923351",
+      "name": "back",
+      "font_class": "back",
+      "unicode": "e6b9",
+      "unicode_decimal": 59065
+    },
+    {
+      "icon_id": "24923352",
+      "name": "forward",
+      "font_class": "forward",
+      "unicode": "e6ba",
+      "unicode_decimal": 59066
+    },
+    {
+      "icon_id": "24923353",
+      "name": "arrowthinright",
+      "font_class": "arrow-right",
+      "unicode": "e6bb",
+      "unicode_decimal": 59067
+    },
+		{
+		  "icon_id": "24923353",
+		  "name": "arrowthinright",
+		  "font_class": "arrowthinright",
+		  "unicode": "e6bb",
+		  "unicode_decimal": 59067
+		},
+    {
+      "icon_id": "24923354",
+      "name": "arrowthinleft",
+      "font_class": "arrow-left",
+      "unicode": "e6bc",
+      "unicode_decimal": 59068
+    },
+		{
+		  "icon_id": "24923354",
+		  "name": "arrowthinleft",
+		  "font_class": "arrowthinleft",
+		  "unicode": "e6bc",
+		  "unicode_decimal": 59068
+		},
+    {
+      "icon_id": "24923355",
+      "name": "arrowthinup",
+      "font_class": "arrow-up",
+      "unicode": "e6bd",
+      "unicode_decimal": 59069
+    },
+		{
+		  "icon_id": "24923355",
+		  "name": "arrowthinup",
+		  "font_class": "arrowthinup",
+		  "unicode": "e6bd",
+		  "unicode_decimal": 59069
+		},
+    {
+      "icon_id": "24923356",
+      "name": "arrowthindown",
+      "font_class": "arrow-down",
+      "unicode": "e6be",
+      "unicode_decimal": 59070
+    },{
+      "icon_id": "24923356",
+      "name": "arrowthindown",
+      "font_class": "arrowthindown",
+      "unicode": "e6be",
+      "unicode_decimal": 59070
+    },
+    {
+      "icon_id": "24923349",
+      "name": "arrowdown",
+      "font_class": "bottom",
+      "unicode": "e6b8",
+      "unicode_decimal": 59064
+    },{
+      "icon_id": "24923349",
+      "name": "arrowdown",
+      "font_class": "arrowdown",
+      "unicode": "e6b8",
+      "unicode_decimal": 59064
+    },
+    {
+      "icon_id": "24923346",
+      "name": "arrowright",
+      "font_class": "right",
+      "unicode": "e6b5",
+      "unicode_decimal": 59061
+    },
+		{
+		  "icon_id": "24923346",
+		  "name": "arrowright",
+		  "font_class": "arrowright",
+		  "unicode": "e6b5",
+		  "unicode_decimal": 59061
+		},
+    {
+      "icon_id": "24923347",
+      "name": "arrowup",
+      "font_class": "top",
+      "unicode": "e6b6",
+      "unicode_decimal": 59062
+    },
+		{
+		  "icon_id": "24923347",
+		  "name": "arrowup",
+		  "font_class": "arrowup",
+		  "unicode": "e6b6",
+		  "unicode_decimal": 59062
+		},
+    {
+      "icon_id": "24923348",
+      "name": "arrowleft",
+      "font_class": "left",
+      "unicode": "e6b7",
+      "unicode_decimal": 59063
+    },
+		{
+		  "icon_id": "24923348",
+		  "name": "arrowleft",
+		  "font_class": "arrowleft",
+		  "unicode": "e6b7",
+		  "unicode_decimal": 59063
+		},
+    {
+      "icon_id": "24923334",
+      "name": "eye",
+      "font_class": "eye",
+      "unicode": "e651",
+      "unicode_decimal": 58961
+    },
+    {
+      "icon_id": "24923335",
+      "name": "eye-filled",
+      "font_class": "eye-filled",
+      "unicode": "e66a",
+      "unicode_decimal": 58986
+    },
+    {
+      "icon_id": "24923336",
+      "name": "eye-slash",
+      "font_class": "eye-slash",
+      "unicode": "e6b3",
+      "unicode_decimal": 59059
+    },
+    {
+      "icon_id": "24923337",
+      "name": "eye-slash-filled",
+      "font_class": "eye-slash-filled",
+      "unicode": "e6b4",
+      "unicode_decimal": 59060
+    },
+    {
+      "icon_id": "24923305",
+      "name": "info-filled",
+      "font_class": "info-filled",
+      "unicode": "e649",
+      "unicode_decimal": 58953
+    },
+    {
+      "icon_id": "24923299",
+      "name": "reload-01",
+      "font_class": "reload",
+      "unicode": "e6b2",
+      "unicode_decimal": 59058
+    },
+    {
+      "icon_id": "24923195",
+      "name": "mic_slash_fill",
+      "font_class": "micoff-filled",
+      "unicode": "e6b0",
+      "unicode_decimal": 59056
+    },
+    {
+      "icon_id": "24923165",
+      "name": "map-pin-ellipse",
+      "font_class": "map-pin-ellipse",
+      "unicode": "e6ac",
+      "unicode_decimal": 59052
+    },
+    {
+      "icon_id": "24923166",
+      "name": "map-pin",
+      "font_class": "map-pin",
+      "unicode": "e6ad",
+      "unicode_decimal": 59053
+    },
+    {
+      "icon_id": "24923167",
+      "name": "location",
+      "font_class": "location",
+      "unicode": "e6ae",
+      "unicode_decimal": 59054
+    },
+    {
+      "icon_id": "24923064",
+      "name": "starhalf",
+      "font_class": "starhalf",
+      "unicode": "e683",
+      "unicode_decimal": 59011
+    },
+    {
+      "icon_id": "24923065",
+      "name": "star",
+      "font_class": "star",
+      "unicode": "e688",
+      "unicode_decimal": 59016
+    },
+    {
+      "icon_id": "24923066",
+      "name": "star-filled",
+      "font_class": "star-filled",
+      "unicode": "e68f",
+      "unicode_decimal": 59023
+    },
+    {
+      "icon_id": "24899646",
+      "name": "a-rilidaka",
+      "font_class": "calendar",
+      "unicode": "e6a0",
+      "unicode_decimal": 59040
+    },
+    {
+      "icon_id": "24899647",
+      "name": "fire",
+      "font_class": "fire",
+      "unicode": "e6a1",
+      "unicode_decimal": 59041
+    },
+    {
+      "icon_id": "24899648",
+      "name": "paihangbang",
+      "font_class": "medal",
+      "unicode": "e6a2",
+      "unicode_decimal": 59042
+    },
+    {
+      "icon_id": "24899649",
+      "name": "font",
+      "font_class": "font",
+      "unicode": "e6a3",
+      "unicode_decimal": 59043
+    },
+    {
+      "icon_id": "24899650",
+      "name": "gift",
+      "font_class": "gift",
+      "unicode": "e6a4",
+      "unicode_decimal": 59044
+    },
+    {
+      "icon_id": "24899651",
+      "name": "link",
+      "font_class": "link",
+      "unicode": "e6a5",
+      "unicode_decimal": 59045
+    },
+    {
+      "icon_id": "24899652",
+      "name": "notification",
+      "font_class": "notification",
+      "unicode": "e6a6",
+      "unicode_decimal": 59046
+    },
+    {
+      "icon_id": "24899653",
+      "name": "staff",
+      "font_class": "staff",
+      "unicode": "e6a7",
+      "unicode_decimal": 59047
+    },
+    {
+      "icon_id": "24899654",
+      "name": "VIP",
+      "font_class": "vip",
+      "unicode": "e6a8",
+      "unicode_decimal": 59048
+    },
+    {
+      "icon_id": "24899655",
+      "name": "folder_add",
+      "font_class": "folder-add",
+      "unicode": "e6a9",
+      "unicode_decimal": 59049
+    },
+    {
+      "icon_id": "24899656",
+      "name": "tune",
+      "font_class": "tune",
+      "unicode": "e6aa",
+      "unicode_decimal": 59050
+    },
+    {
+      "icon_id": "24899657",
+      "name": "shimingrenzheng",
+      "font_class": "auth",
+      "unicode": "e6ab",
+      "unicode_decimal": 59051
+    },
+    {
+      "icon_id": "24899565",
+      "name": "person",
+      "font_class": "person",
+      "unicode": "e699",
+      "unicode_decimal": 59033
+    },
+    {
+      "icon_id": "24899566",
+      "name": "email-filled",
+      "font_class": "email-filled",
+      "unicode": "e69a",
+      "unicode_decimal": 59034
+    },
+    {
+      "icon_id": "24899567",
+      "name": "phone-filled",
+      "font_class": "phone-filled",
+      "unicode": "e69b",
+      "unicode_decimal": 59035
+    },
+    {
+      "icon_id": "24899568",
+      "name": "phone",
+      "font_class": "phone",
+      "unicode": "e69c",
+      "unicode_decimal": 59036
+    },
+    {
+      "icon_id": "24899570",
+      "name": "email",
+      "font_class": "email",
+      "unicode": "e69e",
+      "unicode_decimal": 59038
+    },
+    {
+      "icon_id": "24899571",
+      "name": "personadd",
+      "font_class": "personadd",
+      "unicode": "e69f",
+      "unicode_decimal": 59039
+    },
+    {
+      "icon_id": "24899558",
+      "name": "chatboxes-filled",
+      "font_class": "chatboxes-filled",
+      "unicode": "e692",
+      "unicode_decimal": 59026
+    },
+    {
+      "icon_id": "24899559",
+      "name": "contact",
+      "font_class": "contact",
+      "unicode": "e693",
+      "unicode_decimal": 59027
+    },
+    {
+      "icon_id": "24899560",
+      "name": "chatbubble-filled",
+      "font_class": "chatbubble-filled",
+      "unicode": "e694",
+      "unicode_decimal": 59028
+    },
+    {
+      "icon_id": "24899561",
+      "name": "contact-filled",
+      "font_class": "contact-filled",
+      "unicode": "e695",
+      "unicode_decimal": 59029
+    },
+    {
+      "icon_id": "24899562",
+      "name": "chatboxes",
+      "font_class": "chatboxes",
+      "unicode": "e696",
+      "unicode_decimal": 59030
+    },
+    {
+      "icon_id": "24899563",
+      "name": "chatbubble",
+      "font_class": "chatbubble",
+      "unicode": "e697",
+      "unicode_decimal": 59031
+    },
+    {
+      "icon_id": "24881290",
+      "name": "upload-filled",
+      "font_class": "upload-filled",
+      "unicode": "e68e",
+      "unicode_decimal": 59022
+    },
+    {
+      "icon_id": "24881292",
+      "name": "upload",
+      "font_class": "upload",
+      "unicode": "e690",
+      "unicode_decimal": 59024
+    },
+    {
+      "icon_id": "24881293",
+      "name": "weixin",
+      "font_class": "weixin",
+      "unicode": "e691",
+      "unicode_decimal": 59025
+    },
+    {
+      "icon_id": "24881274",
+      "name": "compose",
+      "font_class": "compose",
+      "unicode": "e67f",
+      "unicode_decimal": 59007
+    },
+    {
+      "icon_id": "24881275",
+      "name": "qq",
+      "font_class": "qq",
+      "unicode": "e680",
+      "unicode_decimal": 59008
+    },
+    {
+      "icon_id": "24881276",
+      "name": "download-filled",
+      "font_class": "download-filled",
+      "unicode": "e681",
+      "unicode_decimal": 59009
+    },
+    {
+      "icon_id": "24881277",
+      "name": "pengyouquan",
+      "font_class": "pyq",
+      "unicode": "e682",
+      "unicode_decimal": 59010
+    },
+    {
+      "icon_id": "24881279",
+      "name": "sound",
+      "font_class": "sound",
+      "unicode": "e684",
+      "unicode_decimal": 59012
+    },
+    {
+      "icon_id": "24881280",
+      "name": "trash-filled",
+      "font_class": "trash-filled",
+      "unicode": "e685",
+      "unicode_decimal": 59013
+    },
+    {
+      "icon_id": "24881281",
+      "name": "sound-filled",
+      "font_class": "sound-filled",
+      "unicode": "e686",
+      "unicode_decimal": 59014
+    },
+    {
+      "icon_id": "24881282",
+      "name": "trash",
+      "font_class": "trash",
+      "unicode": "e687",
+      "unicode_decimal": 59015
+    },
+    {
+      "icon_id": "24881284",
+      "name": "videocam-filled",
+      "font_class": "videocam-filled",
+      "unicode": "e689",
+      "unicode_decimal": 59017
+    },
+    {
+      "icon_id": "24881285",
+      "name": "spinner-cycle",
+      "font_class": "spinner-cycle",
+      "unicode": "e68a",
+      "unicode_decimal": 59018
+    },
+    {
+      "icon_id": "24881286",
+      "name": "weibo",
+      "font_class": "weibo",
+      "unicode": "e68b",
+      "unicode_decimal": 59019
+    },
+    {
+      "icon_id": "24881288",
+      "name": "videocam",
+      "font_class": "videocam",
+      "unicode": "e68c",
+      "unicode_decimal": 59020
+    },
+    {
+      "icon_id": "24881289",
+      "name": "download",
+      "font_class": "download",
+      "unicode": "e68d",
+      "unicode_decimal": 59021
+    },
+    {
+      "icon_id": "24879601",
+      "name": "help",
+      "font_class": "help",
+      "unicode": "e679",
+      "unicode_decimal": 59001
+    },
+    {
+      "icon_id": "24879602",
+      "name": "navigate-filled",
+      "font_class": "navigate-filled",
+      "unicode": "e67a",
+      "unicode_decimal": 59002
+    },
+    {
+      "icon_id": "24879603",
+      "name": "plusempty",
+      "font_class": "plusempty",
+      "unicode": "e67b",
+      "unicode_decimal": 59003
+    },
+    {
+      "icon_id": "24879604",
+      "name": "smallcircle",
+      "font_class": "smallcircle",
+      "unicode": "e67c",
+      "unicode_decimal": 59004
+    },
+    {
+      "icon_id": "24879605",
+      "name": "minus-filled",
+      "font_class": "minus-filled",
+      "unicode": "e67d",
+      "unicode_decimal": 59005
+    },
+    {
+      "icon_id": "24879606",
+      "name": "micoff",
+      "font_class": "micoff",
+      "unicode": "e67e",
+      "unicode_decimal": 59006
+    },
+    {
+      "icon_id": "24879588",
+      "name": "closeempty",
+      "font_class": "closeempty",
+      "unicode": "e66c",
+      "unicode_decimal": 58988
+    },
+    {
+      "icon_id": "24879589",
+      "name": "clear",
+      "font_class": "clear",
+      "unicode": "e66d",
+      "unicode_decimal": 58989
+    },
+    {
+      "icon_id": "24879590",
+      "name": "navigate",
+      "font_class": "navigate",
+      "unicode": "e66e",
+      "unicode_decimal": 58990
+    },
+    {
+      "icon_id": "24879591",
+      "name": "minus",
+      "font_class": "minus",
+      "unicode": "e66f",
+      "unicode_decimal": 58991
+    },
+    {
+      "icon_id": "24879592",
+      "name": "image",
+      "font_class": "image",
+      "unicode": "e670",
+      "unicode_decimal": 58992
+    },
+    {
+      "icon_id": "24879593",
+      "name": "mic",
+      "font_class": "mic",
+      "unicode": "e671",
+      "unicode_decimal": 58993
+    },
+    {
+      "icon_id": "24879594",
+      "name": "paperplane",
+      "font_class": "paperplane",
+      "unicode": "e672",
+      "unicode_decimal": 58994
+    },
+    {
+      "icon_id": "24879595",
+      "name": "close",
+      "font_class": "close",
+      "unicode": "e673",
+      "unicode_decimal": 58995
+    },
+    {
+      "icon_id": "24879596",
+      "name": "help-filled",
+      "font_class": "help-filled",
+      "unicode": "e674",
+      "unicode_decimal": 58996
+    },
+    {
+      "icon_id": "24879597",
+      "name": "plus-filled",
+      "font_class": "paperplane-filled",
+      "unicode": "e675",
+      "unicode_decimal": 58997
+    },
+    {
+      "icon_id": "24879598",
+      "name": "plus",
+      "font_class": "plus",
+      "unicode": "e676",
+      "unicode_decimal": 58998
+    },
+    {
+      "icon_id": "24879599",
+      "name": "mic-filled",
+      "font_class": "mic-filled",
+      "unicode": "e677",
+      "unicode_decimal": 58999
+    },
+    {
+      "icon_id": "24879600",
+      "name": "image-filled",
+      "font_class": "image-filled",
+      "unicode": "e678",
+      "unicode_decimal": 59000
+    },
+    {
+      "icon_id": "24855900",
+      "name": "locked-filled",
+      "font_class": "locked-filled",
+      "unicode": "e668",
+      "unicode_decimal": 58984
+    },
+    {
+      "icon_id": "24855901",
+      "name": "info",
+      "font_class": "info",
+      "unicode": "e669",
+      "unicode_decimal": 58985
+    },
+    {
+      "icon_id": "24855903",
+      "name": "locked",
+      "font_class": "locked",
+      "unicode": "e66b",
+      "unicode_decimal": 58987
+    },
+    {
+      "icon_id": "24855884",
+      "name": "camera-filled",
+      "font_class": "camera-filled",
+      "unicode": "e658",
+      "unicode_decimal": 58968
+    },
+    {
+      "icon_id": "24855885",
+      "name": "chat-filled",
+      "font_class": "chat-filled",
+      "unicode": "e659",
+      "unicode_decimal": 58969
+    },
+    {
+      "icon_id": "24855886",
+      "name": "camera",
+      "font_class": "camera",
+      "unicode": "e65a",
+      "unicode_decimal": 58970
+    },
+    {
+      "icon_id": "24855887",
+      "name": "circle",
+      "font_class": "circle",
+      "unicode": "e65b",
+      "unicode_decimal": 58971
+    },
+    {
+      "icon_id": "24855888",
+      "name": "checkmarkempty",
+      "font_class": "checkmarkempty",
+      "unicode": "e65c",
+      "unicode_decimal": 58972
+    },
+    {
+      "icon_id": "24855889",
+      "name": "chat",
+      "font_class": "chat",
+      "unicode": "e65d",
+      "unicode_decimal": 58973
+    },
+    {
+      "icon_id": "24855890",
+      "name": "circle-filled",
+      "font_class": "circle-filled",
+      "unicode": "e65e",
+      "unicode_decimal": 58974
+    },
+    {
+      "icon_id": "24855891",
+      "name": "flag",
+      "font_class": "flag",
+      "unicode": "e65f",
+      "unicode_decimal": 58975
+    },
+    {
+      "icon_id": "24855892",
+      "name": "flag-filled",
+      "font_class": "flag-filled",
+      "unicode": "e660",
+      "unicode_decimal": 58976
+    },
+    {
+      "icon_id": "24855893",
+      "name": "gear-filled",
+      "font_class": "gear-filled",
+      "unicode": "e661",
+      "unicode_decimal": 58977
+    },
+    {
+      "icon_id": "24855894",
+      "name": "home",
+      "font_class": "home",
+      "unicode": "e662",
+      "unicode_decimal": 58978
+    },
+    {
+      "icon_id": "24855895",
+      "name": "home-filled",
+      "font_class": "home-filled",
+      "unicode": "e663",
+      "unicode_decimal": 58979
+    },
+    {
+      "icon_id": "24855896",
+      "name": "gear",
+      "font_class": "gear",
+      "unicode": "e664",
+      "unicode_decimal": 58980
+    },
+    {
+      "icon_id": "24855897",
+      "name": "smallcircle-filled",
+      "font_class": "smallcircle-filled",
+      "unicode": "e665",
+      "unicode_decimal": 58981
+    },
+    {
+      "icon_id": "24855898",
+      "name": "map-filled",
+      "font_class": "map-filled",
+      "unicode": "e666",
+      "unicode_decimal": 58982
+    },
+    {
+      "icon_id": "24855899",
+      "name": "map",
+      "font_class": "map",
+      "unicode": "e667",
+      "unicode_decimal": 58983
+    },
+    {
+      "icon_id": "24855825",
+      "name": "refresh-filled",
+      "font_class": "refresh-filled",
+      "unicode": "e656",
+      "unicode_decimal": 58966
+    },
+    {
+      "icon_id": "24855826",
+      "name": "refresh",
+      "font_class": "refresh",
+      "unicode": "e657",
+      "unicode_decimal": 58967
+    },
+    {
+      "icon_id": "24855808",
+      "name": "cloud-upload",
+      "font_class": "cloud-upload",
+      "unicode": "e645",
+      "unicode_decimal": 58949
+    },
+    {
+      "icon_id": "24855809",
+      "name": "cloud-download-filled",
+      "font_class": "cloud-download-filled",
+      "unicode": "e646",
+      "unicode_decimal": 58950
+    },
+    {
+      "icon_id": "24855810",
+      "name": "cloud-download",
+      "font_class": "cloud-download",
+      "unicode": "e647",
+      "unicode_decimal": 58951
+    },
+    {
+      "icon_id": "24855811",
+      "name": "cloud-upload-filled",
+      "font_class": "cloud-upload-filled",
+      "unicode": "e648",
+      "unicode_decimal": 58952
+    },
+    {
+      "icon_id": "24855813",
+      "name": "redo",
+      "font_class": "redo",
+      "unicode": "e64a",
+      "unicode_decimal": 58954
+    },
+    {
+      "icon_id": "24855814",
+      "name": "images-filled",
+      "font_class": "images-filled",
+      "unicode": "e64b",
+      "unicode_decimal": 58955
+    },
+    {
+      "icon_id": "24855815",
+      "name": "undo-filled",
+      "font_class": "undo-filled",
+      "unicode": "e64c",
+      "unicode_decimal": 58956
+    },
+    {
+      "icon_id": "24855816",
+      "name": "more",
+      "font_class": "more",
+      "unicode": "e64d",
+      "unicode_decimal": 58957
+    },
+    {
+      "icon_id": "24855817",
+      "name": "more-filled",
+      "font_class": "more-filled",
+      "unicode": "e64e",
+      "unicode_decimal": 58958
+    },
+    {
+      "icon_id": "24855818",
+      "name": "undo",
+      "font_class": "undo",
+      "unicode": "e64f",
+      "unicode_decimal": 58959
+    },
+    {
+      "icon_id": "24855819",
+      "name": "images",
+      "font_class": "images",
+      "unicode": "e650",
+      "unicode_decimal": 58960
+    },
+    {
+      "icon_id": "24855821",
+      "name": "paperclip",
+      "font_class": "paperclip",
+      "unicode": "e652",
+      "unicode_decimal": 58962
+    },
+    {
+      "icon_id": "24855822",
+      "name": "settings",
+      "font_class": "settings",
+      "unicode": "e653",
+      "unicode_decimal": 58963
+    },
+    {
+      "icon_id": "24855823",
+      "name": "search",
+      "font_class": "search",
+      "unicode": "e654",
+      "unicode_decimal": 58964
+    },
+    {
+      "icon_id": "24855824",
+      "name": "redo-filled",
+      "font_class": "redo-filled",
+      "unicode": "e655",
+      "unicode_decimal": 58965
+    },
+    {
+      "icon_id": "24841702",
+      "name": "list",
+      "font_class": "list",
+      "unicode": "e644",
+      "unicode_decimal": 58948
+    },
+    {
+      "icon_id": "24841489",
+      "name": "mail-open-filled",
+      "font_class": "mail-open-filled",
+      "unicode": "e63a",
+      "unicode_decimal": 58938
+    },
+    {
+      "icon_id": "24841491",
+      "name": "hand-thumbsdown-filled",
+      "font_class": "hand-down-filled",
+      "unicode": "e63c",
+      "unicode_decimal": 58940
+    },
+    {
+      "icon_id": "24841492",
+      "name": "hand-thumbsdown",
+      "font_class": "hand-down",
+      "unicode": "e63d",
+      "unicode_decimal": 58941
+    },
+    {
+      "icon_id": "24841493",
+      "name": "hand-thumbsup-filled",
+      "font_class": "hand-up-filled",
+      "unicode": "e63e",
+      "unicode_decimal": 58942
+    },
+    {
+      "icon_id": "24841494",
+      "name": "hand-thumbsup",
+      "font_class": "hand-up",
+      "unicode": "e63f",
+      "unicode_decimal": 58943
+    },
+    {
+      "icon_id": "24841496",
+      "name": "heart-filled",
+      "font_class": "heart-filled",
+      "unicode": "e641",
+      "unicode_decimal": 58945
+    },
+    {
+      "icon_id": "24841498",
+      "name": "mail-open",
+      "font_class": "mail-open",
+      "unicode": "e643",
+      "unicode_decimal": 58947
+    },
+    {
+      "icon_id": "24841488",
+      "name": "heart",
+      "font_class": "heart",
+      "unicode": "e639",
+      "unicode_decimal": 58937
+    },
+    {
+      "icon_id": "24839963",
+      "name": "loop",
+      "font_class": "loop",
+      "unicode": "e633",
+      "unicode_decimal": 58931
+    },
+    {
+      "icon_id": "24839866",
+      "name": "pulldown",
+      "font_class": "pulldown",
+      "unicode": "e632",
+      "unicode_decimal": 58930
+    },
+    {
+      "icon_id": "24813798",
+      "name": "scan",
+      "font_class": "scan",
+      "unicode": "e62a",
+      "unicode_decimal": 58922
+    },
+    {
+      "icon_id": "24813786",
+      "name": "bars",
+      "font_class": "bars",
+      "unicode": "e627",
+      "unicode_decimal": 58919
+    },
+    {
+      "icon_id": "24813788",
+      "name": "cart-filled",
+      "font_class": "cart-filled",
+      "unicode": "e629",
+      "unicode_decimal": 58921
+    },
+    {
+      "icon_id": "24813790",
+      "name": "checkbox",
+      "font_class": "checkbox",
+      "unicode": "e62b",
+      "unicode_decimal": 58923
+    },
+    {
+      "icon_id": "24813791",
+      "name": "checkbox-filled",
+      "font_class": "checkbox-filled",
+      "unicode": "e62c",
+      "unicode_decimal": 58924
+    },
+    {
+      "icon_id": "24813794",
+      "name": "shop",
+      "font_class": "shop",
+      "unicode": "e62f",
+      "unicode_decimal": 58927
+    },
+    {
+      "icon_id": "24813795",
+      "name": "headphones",
+      "font_class": "headphones",
+      "unicode": "e630",
+      "unicode_decimal": 58928
+    },
+    {
+      "icon_id": "24813796",
+      "name": "cart",
+      "font_class": "cart",
+      "unicode": "e631",
+      "unicode_decimal": 58929
+    }
+  ]
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-icons/components/uni-icons/uni-icons.vue b/yudao-ui-admin-uniapp/uni_modules/uni-icons/components/uni-icons/uni-icons.vue
new file mode 100644
index 000000000..86e744452
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-icons/components/uni-icons/uni-icons.vue
@@ -0,0 +1,96 @@
+<template>
+	<!-- #ifdef APP-NVUE -->
+	<text :style="{ color: color, 'font-size': iconSize }" class="uni-icons" @click="_onClick">{{unicode}}</text>
+	<!-- #endif -->
+	<!-- #ifndef APP-NVUE -->
+	<text :style="{ color: color, 'font-size': iconSize }" class="uni-icons" :class="['uniui-'+type,customPrefix,customPrefix?type:'']" @click="_onClick"></text>
+	<!-- #endif -->
+</template>
+
+<script>
+	import icons from './icons.js';
+	const getVal = (val) => {
+		const reg = /^[0-9]*$/g
+		return (typeof val === 'number' || reg.test(val) )? val + 'px' : val;
+	} 
+	// #ifdef APP-NVUE
+	var domModule = weex.requireModule('dom');
+	import iconUrl from './uniicons.ttf'
+	domModule.addRule('fontFace', {
+		'fontFamily': "uniicons",
+		'src': "url('"+iconUrl+"')"
+	});
+	// #endif
+
+	/**
+	 * Icons 图标
+	 * @description 用于展示 icons 图标
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=28
+	 * @property {Number} size 图标大小
+	 * @property {String} type 图标图案,参考示例
+	 * @property {String} color 图标颜色
+	 * @property {String} customPrefix 自定义图标
+	 * @event {Function} click 点击 Icon 触发事件
+	 */
+	export default {
+		name: 'UniIcons',
+		emits:['click'],
+		props: {
+			type: {
+				type: String,
+				default: ''
+			},
+			color: {
+				type: String,
+				default: '#333333'
+			},
+			size: {
+				type: [Number, String],
+				default: 16
+			},
+			customPrefix:{
+				type: String,
+				default: ''
+			}
+		},
+		data() {
+			return {
+				icons: icons.glyphs
+			}
+		},
+		computed:{
+			unicode(){
+				let code = this.icons.find(v=>v.font_class === this.type)
+				if(code){
+					return unescape(`%u${code.unicode}`)
+				}
+				return ''
+			},
+			iconSize(){
+				return getVal(this.size)
+			}
+		},
+		methods: {
+			_onClick() {
+				this.$emit('click')
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	/* #ifndef APP-NVUE */
+	@import './uniicons.css';
+	@font-face {
+		font-family: uniicons;
+		src: url('./uniicons.ttf') format('truetype');
+	}
+
+	/* #endif */
+	.uni-icons {
+		font-family: uniicons;
+		text-decoration: none;
+		text-align: center;
+	}
+
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-icons/components/uni-icons/uniicons.css b/yudao-ui-admin-uniapp/uni_modules/uni-icons/components/uni-icons/uniicons.css
new file mode 100644
index 000000000..2f56eabde
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-icons/components/uni-icons/uniicons.css
@@ -0,0 +1,663 @@
+.uniui-color:before {
+  content: "\e6cf";
+}
+
+.uniui-wallet:before {
+  content: "\e6b1";
+}
+
+.uniui-settings-filled:before {
+  content: "\e6ce";
+}
+
+.uniui-auth-filled:before {
+  content: "\e6cc";
+}
+
+.uniui-shop-filled:before {
+  content: "\e6cd";
+}
+
+.uniui-staff-filled:before {
+  content: "\e6cb";
+}
+
+.uniui-vip-filled:before {
+  content: "\e6c6";
+}
+
+.uniui-plus-filled:before {
+  content: "\e6c7";
+}
+
+.uniui-folder-add-filled:before {
+  content: "\e6c8";
+}
+
+.uniui-color-filled:before {
+  content: "\e6c9";
+}
+
+.uniui-tune-filled:before {
+  content: "\e6ca";
+}
+
+.uniui-calendar-filled:before {
+  content: "\e6c0";
+}
+
+.uniui-notification-filled:before {
+  content: "\e6c1";
+}
+
+.uniui-wallet-filled:before {
+  content: "\e6c2";
+}
+
+.uniui-medal-filled:before {
+  content: "\e6c3";
+}
+
+.uniui-gift-filled:before {
+  content: "\e6c4";
+}
+
+.uniui-fire-filled:before {
+  content: "\e6c5";
+}
+
+.uniui-refreshempty:before {
+  content: "\e6bf";
+}
+
+.uniui-location-filled:before {
+  content: "\e6af";
+}
+
+.uniui-person-filled:before {
+  content: "\e69d";
+}
+
+.uniui-personadd-filled:before {
+  content: "\e698";
+}
+
+.uniui-back:before {
+  content: "\e6b9";
+}
+
+.uniui-forward:before {
+  content: "\e6ba";
+}
+
+.uniui-arrow-right:before {
+  content: "\e6bb";
+}
+
+.uniui-arrowthinright:before {
+  content: "\e6bb";
+}
+
+.uniui-arrow-left:before {
+  content: "\e6bc";
+}
+
+.uniui-arrowthinleft:before {
+  content: "\e6bc";
+}
+
+.uniui-arrow-up:before {
+  content: "\e6bd";
+}
+
+.uniui-arrowthinup:before {
+  content: "\e6bd";
+}
+
+.uniui-arrow-down:before {
+  content: "\e6be";
+}
+
+.uniui-arrowthindown:before {
+  content: "\e6be";
+}
+
+.uniui-bottom:before {
+  content: "\e6b8";
+}
+
+.uniui-arrowdown:before {
+  content: "\e6b8";
+}
+
+.uniui-right:before {
+  content: "\e6b5";
+}
+
+.uniui-arrowright:before {
+  content: "\e6b5";
+}
+
+.uniui-top:before {
+  content: "\e6b6";
+}
+
+.uniui-arrowup:before {
+  content: "\e6b6";
+}
+
+.uniui-left:before {
+  content: "\e6b7";
+}
+
+.uniui-arrowleft:before {
+  content: "\e6b7";
+}
+
+.uniui-eye:before {
+  content: "\e651";
+}
+
+.uniui-eye-filled:before {
+  content: "\e66a";
+}
+
+.uniui-eye-slash:before {
+  content: "\e6b3";
+}
+
+.uniui-eye-slash-filled:before {
+  content: "\e6b4";
+}
+
+.uniui-info-filled:before {
+  content: "\e649";
+}
+
+.uniui-reload:before {
+  content: "\e6b2";
+}
+
+.uniui-micoff-filled:before {
+  content: "\e6b0";
+}
+
+.uniui-map-pin-ellipse:before {
+  content: "\e6ac";
+}
+
+.uniui-map-pin:before {
+  content: "\e6ad";
+}
+
+.uniui-location:before {
+  content: "\e6ae";
+}
+
+.uniui-starhalf:before {
+  content: "\e683";
+}
+
+.uniui-star:before {
+  content: "\e688";
+}
+
+.uniui-star-filled:before {
+  content: "\e68f";
+}
+
+.uniui-calendar:before {
+  content: "\e6a0";
+}
+
+.uniui-fire:before {
+  content: "\e6a1";
+}
+
+.uniui-medal:before {
+  content: "\e6a2";
+}
+
+.uniui-font:before {
+  content: "\e6a3";
+}
+
+.uniui-gift:before {
+  content: "\e6a4";
+}
+
+.uniui-link:before {
+  content: "\e6a5";
+}
+
+.uniui-notification:before {
+  content: "\e6a6";
+}
+
+.uniui-staff:before {
+  content: "\e6a7";
+}
+
+.uniui-vip:before {
+  content: "\e6a8";
+}
+
+.uniui-folder-add:before {
+  content: "\e6a9";
+}
+
+.uniui-tune:before {
+  content: "\e6aa";
+}
+
+.uniui-auth:before {
+  content: "\e6ab";
+}
+
+.uniui-person:before {
+  content: "\e699";
+}
+
+.uniui-email-filled:before {
+  content: "\e69a";
+}
+
+.uniui-phone-filled:before {
+  content: "\e69b";
+}
+
+.uniui-phone:before {
+  content: "\e69c";
+}
+
+.uniui-email:before {
+  content: "\e69e";
+}
+
+.uniui-personadd:before {
+  content: "\e69f";
+}
+
+.uniui-chatboxes-filled:before {
+  content: "\e692";
+}
+
+.uniui-contact:before {
+  content: "\e693";
+}
+
+.uniui-chatbubble-filled:before {
+  content: "\e694";
+}
+
+.uniui-contact-filled:before {
+  content: "\e695";
+}
+
+.uniui-chatboxes:before {
+  content: "\e696";
+}
+
+.uniui-chatbubble:before {
+  content: "\e697";
+}
+
+.uniui-upload-filled:before {
+  content: "\e68e";
+}
+
+.uniui-upload:before {
+  content: "\e690";
+}
+
+.uniui-weixin:before {
+  content: "\e691";
+}
+
+.uniui-compose:before {
+  content: "\e67f";
+}
+
+.uniui-qq:before {
+  content: "\e680";
+}
+
+.uniui-download-filled:before {
+  content: "\e681";
+}
+
+.uniui-pyq:before {
+  content: "\e682";
+}
+
+.uniui-sound:before {
+  content: "\e684";
+}
+
+.uniui-trash-filled:before {
+  content: "\e685";
+}
+
+.uniui-sound-filled:before {
+  content: "\e686";
+}
+
+.uniui-trash:before {
+  content: "\e687";
+}
+
+.uniui-videocam-filled:before {
+  content: "\e689";
+}
+
+.uniui-spinner-cycle:before {
+  content: "\e68a";
+}
+
+.uniui-weibo:before {
+  content: "\e68b";
+}
+
+.uniui-videocam:before {
+  content: "\e68c";
+}
+
+.uniui-download:before {
+  content: "\e68d";
+}
+
+.uniui-help:before {
+  content: "\e679";
+}
+
+.uniui-navigate-filled:before {
+  content: "\e67a";
+}
+
+.uniui-plusempty:before {
+  content: "\e67b";
+}
+
+.uniui-smallcircle:before {
+  content: "\e67c";
+}
+
+.uniui-minus-filled:before {
+  content: "\e67d";
+}
+
+.uniui-micoff:before {
+  content: "\e67e";
+}
+
+.uniui-closeempty:before {
+  content: "\e66c";
+}
+
+.uniui-clear:before {
+  content: "\e66d";
+}
+
+.uniui-navigate:before {
+  content: "\e66e";
+}
+
+.uniui-minus:before {
+  content: "\e66f";
+}
+
+.uniui-image:before {
+  content: "\e670";
+}
+
+.uniui-mic:before {
+  content: "\e671";
+}
+
+.uniui-paperplane:before {
+  content: "\e672";
+}
+
+.uniui-close:before {
+  content: "\e673";
+}
+
+.uniui-help-filled:before {
+  content: "\e674";
+}
+
+.uniui-paperplane-filled:before {
+  content: "\e675";
+}
+
+.uniui-plus:before {
+  content: "\e676";
+}
+
+.uniui-mic-filled:before {
+  content: "\e677";
+}
+
+.uniui-image-filled:before {
+  content: "\e678";
+}
+
+.uniui-locked-filled:before {
+  content: "\e668";
+}
+
+.uniui-info:before {
+  content: "\e669";
+}
+
+.uniui-locked:before {
+  content: "\e66b";
+}
+
+.uniui-camera-filled:before {
+  content: "\e658";
+}
+
+.uniui-chat-filled:before {
+  content: "\e659";
+}
+
+.uniui-camera:before {
+  content: "\e65a";
+}
+
+.uniui-circle:before {
+  content: "\e65b";
+}
+
+.uniui-checkmarkempty:before {
+  content: "\e65c";
+}
+
+.uniui-chat:before {
+  content: "\e65d";
+}
+
+.uniui-circle-filled:before {
+  content: "\e65e";
+}
+
+.uniui-flag:before {
+  content: "\e65f";
+}
+
+.uniui-flag-filled:before {
+  content: "\e660";
+}
+
+.uniui-gear-filled:before {
+  content: "\e661";
+}
+
+.uniui-home:before {
+  content: "\e662";
+}
+
+.uniui-home-filled:before {
+  content: "\e663";
+}
+
+.uniui-gear:before {
+  content: "\e664";
+}
+
+.uniui-smallcircle-filled:before {
+  content: "\e665";
+}
+
+.uniui-map-filled:before {
+  content: "\e666";
+}
+
+.uniui-map:before {
+  content: "\e667";
+}
+
+.uniui-refresh-filled:before {
+  content: "\e656";
+}
+
+.uniui-refresh:before {
+  content: "\e657";
+}
+
+.uniui-cloud-upload:before {
+  content: "\e645";
+}
+
+.uniui-cloud-download-filled:before {
+  content: "\e646";
+}
+
+.uniui-cloud-download:before {
+  content: "\e647";
+}
+
+.uniui-cloud-upload-filled:before {
+  content: "\e648";
+}
+
+.uniui-redo:before {
+  content: "\e64a";
+}
+
+.uniui-images-filled:before {
+  content: "\e64b";
+}
+
+.uniui-undo-filled:before {
+  content: "\e64c";
+}
+
+.uniui-more:before {
+  content: "\e64d";
+}
+
+.uniui-more-filled:before {
+  content: "\e64e";
+}
+
+.uniui-undo:before {
+  content: "\e64f";
+}
+
+.uniui-images:before {
+  content: "\e650";
+}
+
+.uniui-paperclip:before {
+  content: "\e652";
+}
+
+.uniui-settings:before {
+  content: "\e653";
+}
+
+.uniui-search:before {
+  content: "\e654";
+}
+
+.uniui-redo-filled:before {
+  content: "\e655";
+}
+
+.uniui-list:before {
+  content: "\e644";
+}
+
+.uniui-mail-open-filled:before {
+  content: "\e63a";
+}
+
+.uniui-hand-down-filled:before {
+  content: "\e63c";
+}
+
+.uniui-hand-down:before {
+  content: "\e63d";
+}
+
+.uniui-hand-up-filled:before {
+  content: "\e63e";
+}
+
+.uniui-hand-up:before {
+  content: "\e63f";
+}
+
+.uniui-heart-filled:before {
+  content: "\e641";
+}
+
+.uniui-mail-open:before {
+  content: "\e643";
+}
+
+.uniui-heart:before {
+  content: "\e639";
+}
+
+.uniui-loop:before {
+  content: "\e633";
+}
+
+.uniui-pulldown:before {
+  content: "\e632";
+}
+
+.uniui-scan:before {
+  content: "\e62a";
+}
+
+.uniui-bars:before {
+  content: "\e627";
+}
+
+.uniui-cart-filled:before {
+  content: "\e629";
+}
+
+.uniui-checkbox:before {
+  content: "\e62b";
+}
+
+.uniui-checkbox-filled:before {
+  content: "\e62c";
+}
+
+.uniui-shop:before {
+  content: "\e62f";
+}
+
+.uniui-headphones:before {
+  content: "\e630";
+}
+
+.uniui-cart:before {
+  content: "\e631";
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-icons/components/uni-icons/uniicons.ttf b/yudao-ui-admin-uniapp/uni_modules/uni-icons/components/uni-icons/uniicons.ttf
new file mode 100644
index 000000000..835f33bc9
Binary files /dev/null and b/yudao-ui-admin-uniapp/uni_modules/uni-icons/components/uni-icons/uniicons.ttf differ
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-icons/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-icons/package.json
new file mode 100644
index 000000000..d1c4e77d4
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-icons/package.json
@@ -0,0 +1,86 @@
+{
+  "id": "uni-icons",
+  "displayName": "uni-icons 图标",
+  "version": "1.3.5",
+  "description": "图标组件,用于展示移动端常见的图标,可自定义颜色、大小。",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "icon",
+    "图标"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": "^3.2.14"
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": ["uni-scss"],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-icons/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-icons/readme.md
new file mode 100644
index 000000000..86234ba1c
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-icons/readme.md
@@ -0,0 +1,8 @@
+## Icons 图标
+> **组件名:uni-icons**
+> 代码块: `uIcons`
+
+用于展示 icons 图标 。
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-icons)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-indexed-list/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-indexed-list/changelog.md
new file mode 100644
index 000000000..08fa71cb4
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-indexed-list/changelog.md
@@ -0,0 +1,17 @@
+## 1.2.1(2021-11-22)
+- 修复 vue3中某些scss变量无法找到的问题
+## 1.2.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-indexed-list](https://uniapp.dcloud.io/component/uniui/uni-indexed-list)
+## 1.1.0(2021-07-30)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.0.11(2021-05-12)
+- 新增 组件示例地址
+## 1.0.10(2021-04-21)
+- 优化 添加依赖 uni-icons, 导入后自动下载依赖
+## 1.0.9(2021-02-05)
+- 优化 组件引用关系,通过uni_modules引用组件
+
+## 1.0.8(2021-02-05)
+- 调整为uni_modules目录规范
+- 新增 支持 PC 端
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list-item.vue b/yudao-ui-admin-uniapp/uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list-item.vue
new file mode 100644
index 000000000..2f13baec9
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list-item.vue
@@ -0,0 +1,144 @@
+<template>
+	<view>
+		<view v-if="loaded || list.itemIndex < 15" class="uni-indexed-list__title-wrapper">
+			<text v-if="list.items && list.items.length > 0" class="uni-indexed-list__title">{{ list.key }}</text>
+		</view>
+		<view v-if="(loaded || list.itemIndex < 15) && list.items && list.items.length > 0" class="uni-indexed-list__list">
+			<view v-for="(item, index) in list.items" :key="index" class="uni-indexed-list__item" hover-class="uni-indexed-list__item--hover">
+				<view class="uni-indexed-list__item-container" @click="onClick(idx, index)">
+					<view class="uni-indexed-list__item-border" :class="{'uni-indexed-list__item-border--last':index===list.items.length-1}">
+						<view v-if="showSelect" style="margin-right: 20rpx;">
+							<uni-icons :type="item.checked ? 'checkbox-filled' : 'circle'" :color="item.checked ? '#007aff' : '#C0C0C0'" size="24" />
+						</view>
+						<text class="uni-indexed-list__item-content">{{ item.name }}</text>
+					</view>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: 'UniIndexedList',
+		emits:['itemClick'],
+		props: {
+			loaded: {
+				type: Boolean,
+				default: false
+			},
+			idx: {
+				type: Number,
+				default: 0
+			},
+			list: {
+				type: Object,
+				default () {
+					return {}
+				}
+			},
+			showSelect: {
+				type: Boolean,
+				default: false
+			}
+		},
+		methods: {
+			onClick(idx, index) {
+				this.$emit("itemClick", {
+					idx,
+					index
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss" >
+	.uni-indexed-list__list {
+		background-color: $uni-bg-color;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		border-top-style: solid;
+		border-top-width: 1px;
+		border-top-color: #DEDEDE;
+	}
+
+	.uni-indexed-list__item {
+		font-size: 14px;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex: 1;
+		flex-direction: row;
+		justify-content: space-between;
+		align-items: center;
+	}
+
+	.uni-indexed-list__item-container {
+		padding-left: 15px;
+		flex: 1;
+		position: relative;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		box-sizing: border-box;
+		/* #endif */
+		flex-direction: row;
+		justify-content: space-between;
+		align-items: center;
+		/* #ifdef H5 */
+		cursor: pointer;
+		/* #endif */
+	}
+
+	.uni-indexed-list__item-border {
+		flex: 1;
+		position: relative;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		box-sizing: border-box;
+		/* #endif */
+		flex-direction: row;
+		justify-content: space-between;
+		align-items: center;
+		height: 50px;
+		padding: 25px;
+		padding-left: 0;
+		border-bottom-style: solid;
+		border-bottom-width: 1px;
+		border-bottom-color:  #DEDEDE;
+	}
+
+	.uni-indexed-list__item-border--last {
+		border-bottom-width: 0px;
+	}
+
+	.uni-indexed-list__item-content {
+		flex: 1;
+		font-size: 14px;
+		color: #191919;
+	}
+
+	.uni-indexed-list {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+	}
+
+	.uni-indexed-list__title-wrapper {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		width: 100%;
+		/* #endif */
+		background-color: #f7f7f7;
+	}
+
+	.uni-indexed-list__title {
+		padding: 6px 12px;
+		line-height: 24px;
+		font-size: 16px;
+		font-weight: 500;
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list.vue b/yudao-ui-admin-uniapp/uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list.vue
new file mode 100644
index 000000000..35e168c26
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-indexed-list/components/uni-indexed-list/uni-indexed-list.vue
@@ -0,0 +1,367 @@
+<template>
+	<view class="uni-indexed-list" ref="list" id="list">
+		<!-- #ifdef APP-NVUE -->
+		<list class="uni-indexed-list__scroll" scrollable="true" show-scrollbar="false">
+			<cell v-for="(list, idx) in lists" :key="idx" :ref="'uni-indexed-list-' + idx">
+				<!-- #endif -->
+				<!-- #ifndef APP-NVUE -->
+				<scroll-view :scroll-into-view="scrollViewId" class="uni-indexed-list__scroll" scroll-y>
+					<view v-for="(list, idx) in lists" :key="idx" :id="'uni-indexed-list-' + idx">
+						<!-- #endif -->
+						<indexed-list-item :list="list" :loaded="loaded" :idx="idx" :showSelect="showSelect"
+							@itemClick="onClick"></indexed-list-item>
+						<!-- #ifndef APP-NVUE -->
+					</view>
+				</scroll-view>
+				<!-- #endif -->
+				<!-- #ifdef APP-NVUE -->
+			</cell>
+		</list>
+		<!-- #endif -->
+		<view class="uni-indexed-list__menu" @touchstart="touchStart" @touchmove.stop.prevent="touchMove"
+			@touchend="touchEnd" @mousedown.stop="mousedown" @mousemove.stop.prevent="mousemove"
+			@mouseleave.stop="mouseleave">
+			<view v-for="(list, key) in lists" :key="key" class="uni-indexed-list__menu-item"
+				:class="touchmoveIndex == key ? 'uni-indexed-list__menu--active' : ''">
+				<text class="uni-indexed-list__menu-text"
+					:class="touchmoveIndex == key ? 'uni-indexed-list__menu-text--active' : ''">{{ list.key }}</text>
+			</view>
+		</view>
+		<view v-if="touchmove" class="uni-indexed-list__alert-wrapper">
+			<text class="uni-indexed-list__alert">{{ lists[touchmoveIndex].key }}</text>
+		</view>
+	</view>
+</template>
+<script>
+	import indexedListItem from './uni-indexed-list-item.vue'
+	// #ifdef APP-NVUE
+	const dom = weex.requireModule('dom');
+	// #endif
+	// #ifdef APP-PLUS
+	function throttle(func, delay) {
+		var prev = Date.now();
+		return function() {
+			var context = this;
+			var args = arguments;
+			var now = Date.now();
+			if (now - prev >= delay) {
+				func.apply(context, args);
+				prev = Date.now();
+			}
+		}
+	}
+
+	function touchMove(e) {
+		let pageY = e.touches[0].pageY
+		let index = Math.floor((pageY - this.winOffsetY) / this.itemHeight)
+		if (this.touchmoveIndex === index) {
+			return false
+		}
+		let item = this.lists[index]
+		if (item) {
+			// #ifndef APP-NVUE
+			this.scrollViewId = 'uni-indexed-list-' + index
+			this.touchmoveIndex = index
+			// #endif
+			// #ifdef APP-NVUE
+			dom.scrollToElement(this.$refs['uni-indexed-list-' + index][0], {
+				animated: false
+			})
+			this.touchmoveIndex = index
+			// #endif
+		}
+	}
+	const throttleTouchMove = throttle(touchMove, 40)
+	// #endif
+
+	/**
+	 * IndexedList 索引列表
+	 * @description 用于展示索引列表
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=375
+	 * @property {Boolean} showSelect = [true|false] 展示模式
+	 * 	@value true 展示模式
+	 * 	@value false 选择模式
+	 * @property {Object} options 索引列表需要的数据对象
+	 * @event {Function} click 点击列表事件 ,返回当前选择项的事件对象
+	 * @example <uni-indexed-list options="" showSelect="false" @click=""></uni-indexed-list>
+	 */
+	export default {
+		name: 'UniIndexedList',
+		components: {
+			indexedListItem
+		},
+		emits: ['click'],
+		props: {
+			options: {
+				type: Array,
+				default () {
+					return []
+				}
+			},
+			showSelect: {
+				type: Boolean,
+				default: false
+			}
+		},
+		data() {
+			return {
+				lists: [],
+				winHeight: 0,
+				itemHeight: 0,
+				winOffsetY: 0,
+				touchmove: false,
+				touchmoveIndex: -1,
+				scrollViewId: '',
+				touchmovable: true,
+				loaded: false,
+				isPC: false
+			}
+		},
+		watch: {
+			options: {
+				handler: function() {
+					this.setList()
+				},
+				deep: true
+			}
+		},
+		mounted() {
+			// #ifdef H5
+			this.isPC = this.IsPC()
+			// #endif
+			setTimeout(() => {
+				this.setList()
+			}, 50)
+			setTimeout(() => {
+				this.loaded = true
+			}, 300);
+		},
+		methods: {
+			setList() {
+				let index = 0;
+				this.lists = []
+				this.options.forEach((value) => {
+					if (value.data.length === 0) {
+						return
+					}
+					let indexBefore = index
+					let items = value.data.map(item => {
+						let obj = {}
+						obj['key'] = value.letter
+						obj['name'] = item
+						obj['itemIndex'] = index
+						index++
+						obj.checked = item.checked ? item.checked : false
+						return obj
+					})
+					this.lists.push({
+						title: value.letter,
+						key: value.letter,
+						items: items,
+						itemIndex: indexBefore
+					})
+				})
+				// #ifndef APP-NVUE
+				uni.createSelectorQuery()
+					.in(this)
+					.select('#list')
+					.boundingClientRect()
+					.exec(ret => {
+						this.winOffsetY = ret[0].top
+						this.winHeight = ret[0].height
+						this.itemHeight = this.winHeight / this.lists.length
+					})
+				// #endif
+				// #ifdef APP-NVUE
+				dom.getComponentRect(this.$refs['list'], (res) => {
+					this.winOffsetY = res.size.top
+					this.winHeight = res.size.height
+					this.itemHeight = this.winHeight / this.lists.length
+				})
+				// #endif
+			},
+			touchStart(e) {
+				this.touchmove = true
+				let pageY = this.isPC ? e.pageY : e.touches[0].pageY
+				let index = Math.floor((pageY - this.winOffsetY) / this.itemHeight)
+				let item = this.lists[index]
+				if (item) {
+					this.scrollViewId = 'uni-indexed-list-' + index
+					this.touchmoveIndex = index
+					// #ifdef APP-NVUE
+					dom.scrollToElement(this.$refs['uni-indexed-list-' + index][0], {
+						animated: false
+					})
+					// #endif
+				}
+			},
+			touchMove(e) {
+				// #ifndef APP-PLUS
+				let pageY = this.isPC ? e.pageY : e.touches[0].pageY
+				let index = Math.floor((pageY - this.winOffsetY) / this.itemHeight)
+				if (this.touchmoveIndex === index) {
+					return false
+				}
+				let item = this.lists[index]
+				if (item) {
+					this.scrollViewId = 'uni-indexed-list-' + index
+					this.touchmoveIndex = index
+				}
+				// #endif
+				// #ifdef APP-PLUS
+				throttleTouchMove.call(this, e)
+				// #endif
+			},
+			touchEnd() {
+				this.touchmove = false
+				// this.touchmoveIndex = -1
+			},
+
+			/**
+			 * 兼容 PC @tian
+			 */
+
+			mousedown(e) {
+				if (!this.isPC) return
+				this.touchStart(e)
+			},
+			mousemove(e) {
+				if (!this.isPC) return
+				this.touchMove(e)
+			},
+			mouseleave(e) {
+				if (!this.isPC) return
+				this.touchEnd(e)
+			},
+
+			// #ifdef H5
+			IsPC() {
+				var userAgentInfo = navigator.userAgent;
+				var Agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"];
+				var flag = true;
+				for (let v = 0; v < Agents.length - 1; v++) {
+					if (userAgentInfo.indexOf(Agents[v]) > 0) {
+						flag = false;
+						break;
+					}
+				}
+				return flag;
+			},
+			// #endif
+
+
+			onClick(e) {
+				let {
+					idx,
+					index
+				} = e
+				let obj = {}
+				for (let key in this.lists[idx].items[index]) {
+					obj[key] = this.lists[idx].items[index][key]
+				}
+				let select = []
+				if (this.showSelect) {
+					this.lists[idx].items[index].checked = !this.lists[idx].items[index].checked
+					this.lists.forEach((value, idx) => {
+						value.items.forEach((item, index) => {
+							if (item.checked) {
+								let obj = {}
+								for (let key in this.lists[idx].items[index]) {
+									obj[key] = this.lists[idx].items[index][key]
+								}
+								select.push(obj)
+							}
+						})
+					})
+				}
+				this.$emit('click', {
+					item: obj,
+					select: select
+				})
+			}
+		}
+	}
+</script>
+<style lang="scss" >
+	.uni-indexed-list {
+		position: absolute;
+		left: 0;
+		top: 0;
+		right: 0;
+		bottom: 0;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+	}
+
+	.uni-indexed-list__scroll {
+		flex: 1;
+	}
+
+	.uni-indexed-list__menu {
+		width: 24px;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+	}
+
+	.uni-indexed-list__menu-item {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex: 1;
+		align-items: center;
+		justify-content: center;
+		/* #ifdef H5 */
+		cursor: pointer;
+		/* #endif */
+	}
+
+	.uni-indexed-list__menu-text {
+		font-size: 12px;
+		text-align: center;
+		color: #aaa;
+	}
+
+	.uni-indexed-list__menu--active {
+		// background-color: rgb(200, 200, 200);
+	}
+
+	.uni-indexed-list__menu--active {}
+
+	.uni-indexed-list__menu-text--active {
+		border-radius: 16px;
+		width: 16px;
+		height: 16px;
+		line-height: 16px;
+		background-color: #007aff;
+		color: #fff;
+	}
+
+	.uni-indexed-list__alert-wrapper {
+		position: absolute;
+		left: 0;
+		top: 0;
+		right: 0;
+		bottom: 0;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		align-items: center;
+		justify-content: center;
+	}
+
+	.uni-indexed-list__alert {
+		width: 80px;
+		height: 80px;
+		border-radius: 80px;
+		text-align: center;
+		line-height: 80px;
+		font-size: 35px;
+		color: #fff;
+		background-color: rgba(0, 0, 0, 0.5);
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-indexed-list/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-indexed-list/package.json
new file mode 100644
index 000000000..125c0e7f6
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-indexed-list/package.json
@@ -0,0 +1,89 @@
+{
+  "id": "uni-indexed-list",
+  "displayName": "uni-indexed-list 索引列表",
+  "version": "1.2.1",
+  "description": "索引列表组件,右侧带索引的列表,方便快速定位到具体内容,通常用于城市/机场选择等场景",
+  "keywords": [
+    "uni-ui",
+    "索引列表",
+    "索引",
+    "列表"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": [
+			"uni-scss",
+			"uni-icons"
+		],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-indexed-list/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-indexed-list/readme.md
new file mode 100644
index 000000000..44ad84b28
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-indexed-list/readme.md
@@ -0,0 +1,11 @@
+
+
+## IndexedList 索引列表
+> **组件名:uni-indexed-list**
+> 代码块: `uIndexedList`
+
+
+用于展示索引列表。
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-indexed-list)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-link/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-link/changelog.md
new file mode 100644
index 000000000..2cfbf5912
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-link/changelog.md
@@ -0,0 +1,17 @@
+## 1.0.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-link](https://uniapp.dcloud.io/component/uniui/uni-link)
+## 1.1.7(2021-11-08)
+## 0.0.7(2021-09-03)
+- 修复 在 nvue 下不显示的 bug
+## 0.0.6(2021-07-30)
+- 新增 支持自定义插槽
+## 0.0.5(2021-06-21)
+- 新增 download 属性,H5平台下载文件名
+## 0.0.4(2021-05-12)
+- 新增 组件示例地址
+## 0.0.3(2021-03-09)
+- 新增 href 属性支持 tel:|mailto:
+
+## 0.0.2(2021-02-05)
+- 调整为uni_modules目录规范
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-link/components/uni-link/uni-link.vue b/yudao-ui-admin-uniapp/uni_modules/uni-link/components/uni-link/uni-link.vue
new file mode 100644
index 000000000..27c5468e1
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-link/components/uni-link/uni-link.vue
@@ -0,0 +1,128 @@
+<template>
+	<a v-if="isShowA" class="uni-link" :href="href"
+		:class="{'uni-link--withline':showUnderLine===true||showUnderLine==='true'}"
+		:style="{color,fontSize:fontSize+'px'}" :download="download">
+		<slot>{{text}}</slot>
+	</a>
+	<!-- #ifndef APP-NVUE -->
+	<text v-else class="uni-link" :class="{'uni-link--withline':showUnderLine===true||showUnderLine==='true'}"
+		:style="{color,fontSize:fontSize+'px'}" @click="openURL">
+		<slot>{{text}}</slot>
+	</text>
+	<!-- #endif -->
+	<!-- #ifdef APP-NVUE -->
+	<text v-else class="uni-link" :class="{'uni-link--withline':showUnderLine===true||showUnderLine==='true'}"
+		:style="{color,fontSize:fontSize+'px'}" @click="openURL">
+		{{text}}
+	</text>
+	<!-- #endif -->
+</template>
+
+<script>
+	/**
+	 * Link 外部网页超链接组件
+	 * @description uni-link是一个外部网页超链接组件,在小程序内复制url,在app内打开外部浏览器,在h5端打开新网页
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=1182
+	 * @property {String} href 点击后打开的外部网页url
+	 * @property {String} text 显示的文字
+	 * @property {String} downlaod H5平台下载文件名
+	 * @property {Boolean} showUnderLine 是否显示下划线
+	 * @property {String} copyTips 在小程序端复制链接时显示的提示语
+	 * @property {String} color 链接文字颜色
+	 * @property {String} fontSize 链接文字大小
+	 * @example * <uni-link href="https://ext.dcloud.net.cn" text="https://ext.dcloud.net.cn"></uni-link>
+	 */
+	export default {
+		name: 'uniLink',
+		props: {
+			href: {
+				type: String,
+				default: ''
+			},
+			text: {
+				type: String,
+				default: ''
+			},
+			download: {
+				type: String,
+				default: ''
+			},
+			showUnderLine: {
+				type: [Boolean, String],
+				default: true
+			},
+			copyTips: {
+				type: String,
+				default: '已自动复制网址,请在手机浏览器里粘贴该网址'
+			},
+			color: {
+				type: String,
+				default: '#999999'
+			},
+			fontSize: {
+				type: [Number, String],
+				default: 14
+			}
+		},
+		computed: {
+			isShowA() {
+				// #ifdef H5
+				this._isH5 = true;
+				// #endif
+				if ((this.isMail() || this.isTel()) && this._isH5 === true) {
+					return true;
+				}
+				return false;
+			}
+		},
+		created() {
+			this._isH5 = null;
+		},
+		methods: {
+			isMail() {
+				return this.href.startsWith('mailto:');
+			},
+			isTel() {
+				return this.href.startsWith('tel:');
+			},
+			openURL() {
+				// #ifdef APP-PLUS
+				if (this.isTel()) {
+					this.makePhoneCall(this.href.replace('tel:', ''));
+				} else {
+					plus.runtime.openURL(this.href);
+				}
+				// #endif
+				// #ifdef H5
+				window.open(this.href)
+				// #endif
+				// #ifdef MP
+				uni.setClipboardData({
+					data: this.href
+				});
+				uni.showModal({
+					content: this.copyTips,
+					showCancel: false
+				});
+				// #endif
+			},
+			makePhoneCall(phoneNumber) {
+				uni.makePhoneCall({
+					phoneNumber
+				})
+			}
+		}
+	}
+</script>
+
+<style>
+	/* #ifndef APP-NVUE */
+	.uni-link {
+		cursor: pointer;
+	}
+
+	/* #endif */
+	.uni-link--withline {
+		text-decoration: underline;
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-link/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-link/package.json
new file mode 100644
index 000000000..77b198652
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-link/package.json
@@ -0,0 +1,87 @@
+{
+  "id": "uni-link",
+  "displayName": "uni-link 超链接",
+  "version": "1.0.0",
+  "description": "uni-link是一个外部网页超链接组件,在小程序内复制url,在app内打开外部浏览器,在h5端打",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "link",
+    "超链接",
+    ""
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": ["uni-scss"],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "y",
+          "联盟": "y"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-link/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-link/readme.md
new file mode 100644
index 000000000..7f09e941a
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-link/readme.md
@@ -0,0 +1,11 @@
+
+
+## Link 链接
+> **组件名:uni-link**
+> 代码块: `uLink`
+
+
+uni-link是一个外部网页超链接组件,在小程序内复制url,在app内打开外部浏览器,在h5端打开新网页。
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-link)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-list/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-list/changelog.md
new file mode 100644
index 000000000..6aa6e4e00
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-list/changelog.md
@@ -0,0 +1,20 @@
+## 1.2.1(2022-03-30)
+- 删除无用文件
+## 1.2.0(2021-11-23)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-list](https://uniapp.dcloud.io/component/uniui/uni-list)
+## 1.1.3(2021-08-30)
+- 修复 在vue3中to属性在发行应用的时候报错的bug
+## 1.1.2(2021-07-30)
+- 优化 vue3下事件警告的问题
+## 1.1.1(2021-07-21)
+- 修复 与其他组件嵌套使用时,点击失效的Bug
+## 1.1.0(2021-07-13)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.0.17(2021-05-12)
+- 新增 组件示例地址
+## 1.0.16(2021-02-05)
+- 优化 组件引用关系,通过uni_modules引用组件
+## 1.0.15(2021-02-05)
+- 调整为uni_modules目录规范
+- 修复 uni-list-chat 角标显示不正常的问题
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-list/components/uni-list-ad/uni-list-ad.vue b/yudao-ui-admin-uniapp/uni_modules/uni-list/components/uni-list-ad/uni-list-ad.vue
new file mode 100644
index 000000000..b9349c29a
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-list/components/uni-list-ad/uni-list-ad.vue
@@ -0,0 +1,107 @@
+<template>
+	<!-- #ifdef APP-NVUE -->
+	<cell>
+		<!-- #endif -->
+		<view class="uni-list-ad">
+			<view v-if="borderShow" :class="{'uni-list--border':border,'uni-list-item--first':isFirstChild}"></view>
+			<ad style="width: 200px;height: 300px;border-width: 1px;border-color: red;border-style: solid;" adpid="1111111111"
+			 unit-id="" appid="" apid="" type="feed" @error="aderror" @close="closeAd"></ad>
+		</view>
+		<!-- #ifdef APP-NVUE -->
+	</cell>
+	<!-- #endif -->
+
+</template>
+
+<script>
+	// #ifdef APP-NVUE
+	const dom = uni.requireNativePlugin('dom');
+	// #endif
+	export default {
+		name: 'UniListAd',
+		props: {
+			title: {
+				type: String,
+				default: '',
+
+			}
+		},
+		// inject: ['list'],
+		data() {
+			return {
+				isFirstChild: false,
+				border: false,
+				borderShow: true,
+			}
+		},
+
+		mounted() {
+			this.list = this.getForm()
+			if (this.list) {
+				if (!this.list.firstChildAppend) {
+					this.list.firstChildAppend = true
+					this.isFirstChild = true
+				}
+				this.border = this.list.border
+			}
+		},
+		methods: {
+			/**
+			 * 获取父元素实例
+			 */
+			getForm(name = 'uniList') {
+				let parent = this.$parent;
+				let parentName = parent.$options.name;
+				while (parentName !== name) {
+					parent = parent.$parent;
+					if (!parent) return false
+					parentName = parent.$options.name;
+				}
+				return parent;
+			},
+			aderror(e) {
+				console.log("aderror: " + JSON.stringify(e.detail));
+			},
+			closeAd(e) {
+				this.borderShow = false
+			}
+		}
+	}
+</script>
+
+<style lang="scss" >
+	.uni-list-ad {
+		position: relative;
+		border: 1px red solid;
+	}
+
+	.uni-list--border {
+		position: relative;
+		padding-bottom: 1px;
+		/* #ifdef APP-PLUS */
+		border-top-color: $uni-border-color;
+		border-top-style: solid;
+		border-top-width: 0.5px;
+		/* #endif */
+		margin-left: $uni-spacing-row-lg;
+	}
+
+	/* #ifndef APP-NVUE */
+	.uni-list--border:after {
+		position: absolute;
+		top: 0;
+		right: 0;
+		left: 0;
+		height: 1px;
+		content: '';
+		-webkit-transform: scaleY(.5);
+		transform: scaleY(.5);
+		background-color: $uni-border-color;
+	}
+
+	.uni-list-item--first:after {
+		height: 0px;
+	}
+
+	/* #endif */
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.scss b/yudao-ui-admin-uniapp/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.scss
new file mode 100644
index 000000000..311f8d9fa
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.scss
@@ -0,0 +1,58 @@
+/**
+ * 这里是 uni-list 组件内置的常用样式变量
+ * 如果需要覆盖样式,这里提供了基本的组件样式变量,您可以尝试修改这里的变量,去完成样式替换,而不用去修改源码
+ *
+ */
+
+// 背景色
+$background-color : #fff;
+// 分割线颜色
+$divide-line-color : #e5e5e5;
+
+// 默认头像大小,如需要修改此值,注意同步修改 js 中的值 const avatarWidth = xx ,目前只支持方形头像
+// nvue 页面不支持修改头像大小
+$avatar-width : 45px ;
+
+// 头像边框
+$avatar-border-radius: 5px;
+$avatar-border-color: #eee;
+$avatar-border-width: 1px;
+
+// 标题文字样式
+$title-size : 16px;
+$title-color : #3b4144;
+$title-weight : normal;
+
+// 描述文字样式
+$note-size : 12px;
+$note-color : #999;
+$note-weight : normal;
+
+// 右侧额外内容默认样式
+$right-text-size : 12px;
+$right-text-color : #999;
+$right-text-weight : normal;
+
+// 角标样式
+// nvue 页面不支持修改圆点位置以及大小
+// 角标在左侧时,角标的位置,默认为 0 ,负数左/下移动,正数右/上移动
+$badge-left: 0px;
+$badge-top: 0px;
+
+// 显示圆点时,圆点大小
+$dot-width: 10px;
+$dot-height: 10px;
+
+// 显示角标时,角标大小和字体大小
+$badge-size : 18px;
+$badge-font : 12px;
+// 显示角标时,角标前景色
+$badge-color : #fff;
+// 显示角标时,角标背景色
+$badge-background-color : #ff5a5f;
+// 显示角标时,角标左右间距
+$badge-space : 6px;
+
+// 状态样式
+// 选中颜色
+$hover : #f5f5f5;
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.vue b/yudao-ui-admin-uniapp/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.vue
new file mode 100644
index 000000000..2b3100859
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.vue
@@ -0,0 +1,538 @@
+<template>
+	<!-- #ifdef APP-NVUE -->
+	<cell>
+		<!-- #endif -->
+		<view :hover-class="!clickable && !link ? '' : 'uni-list-chat--hover'" class="uni-list-chat" @click.stop="onClick">
+			<view :class="{ 'uni-list--border': border, 'uni-list-chat--first': isFirstChild }"></view>
+			<view class="uni-list-chat__container">
+				<view class="uni-list-chat__header-warp">
+					<view v-if="avatarCircle || avatarList.length === 0" class="uni-list-chat__header" :class="{ 'header--circle': avatarCircle }">
+						<image class="uni-list-chat__header-image" :class="{ 'header--circle': avatarCircle }" :src="avatar" mode="aspectFill"></image>
+					</view>
+					<!-- 头像组 -->
+					<view v-else class="uni-list-chat__header">
+						<view v-for="(item, index) in avatarList" :key="index" class="uni-list-chat__header-box" :class="computedAvatar"
+						 :style="{ width: imageWidth + 'px', height: imageWidth + 'px' }">
+							<image class="uni-list-chat__header-image" :style="{ width: imageWidth + 'px', height: imageWidth + 'px' }" :src="item.url"
+							 mode="aspectFill"></image>
+						</view>
+					</view>
+				</view>
+				<view v-if="badgeText && badgePositon === 'left'" class="uni-list-chat__badge uni-list-chat__badge-pos" :class="[isSingle]">
+					<text class="uni-list-chat__badge-text">{{ badgeText === 'dot' ? '' : badgeText }}</text>
+				</view>
+				<view class="uni-list-chat__content">
+					<view class="uni-list-chat__content-main">
+						<text class="uni-list-chat__content-title uni-ellipsis">{{ title }}</text>
+						<text class="uni-list-chat__content-note uni-ellipsis">{{ note }}</text>
+					</view>
+					<view class="uni-list-chat__content-extra">
+						<slot>
+							<text class="uni-list-chat__content-extra-text">{{ time }}</text>
+							<view v-if="badgeText && badgePositon === 'right'" class="uni-list-chat__badge" :class="[isSingle, badgePositon === 'right' ? 'uni-list-chat--right' : '']">
+								<text class="uni-list-chat__badge-text">{{ badgeText === 'dot' ? '' : badgeText }}</text>
+							</view>
+						</slot>
+					</view>
+				</view>
+			</view>
+		</view>
+		<!-- #ifdef APP-NVUE -->
+	</cell>
+	<!-- #endif -->
+</template>
+
+<script>
+	// 头像大小
+	const avatarWidth = 45;
+
+	/**
+	 * ListChat 聊天列表
+	 * @description 聊天列表,用于创建聊天类列表
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=24
+	 * @property {String} 	title 							标题
+	 * @property {String} 	note 							描述
+	 * @property {Boolean} 	clickable = [true|false] 		是否开启点击反馈,默认为false
+	 * @property {String} 	badgeText						数字角标内容
+	 * @property {String}  	badgePositon = [left|right]		角标位置,默认为 right
+	 * @property {String} 	link = [false|navigateTo|redirectTo|reLaunch|switchTab] 是否展示右侧箭头并开启点击反馈,默认为false
+	 *  @value false	 	不开启
+	 *  @value navigateTo 	同 uni.navigateTo()
+	 * 	@value redirectTo 	同 uni.redirectTo()
+	 * 	@value reLaunch   	同 uni.reLaunch()
+	 * 	@value switchTab  	同 uni.switchTab()
+	 * @property {String | PageURIString} 	to  			跳转目标页面
+	 * @property {String} 	time							右侧时间显示
+	 * @property {Boolean} 	avatarCircle = [true|false]		是否显示圆形头像,默认为false
+	 * @property {String} 	avatar							头像地址,avatarCircle 不填时生效
+	 * @property {Array} 	avatarList 						头像组,格式为 [{url:''}]
+	 * @event {Function} 	click 							点击 uniListChat 触发事件
+	 */
+	export default {
+		name: 'UniListChat',
+		emits:['click'],
+		props: {
+			title: {
+				type: String,
+				default: ''
+			},
+			note: {
+				type: String,
+				default: ''
+			},
+			clickable: {
+				type: Boolean,
+				default: false
+			},
+			link: {
+				type: [Boolean, String],
+				default: false
+			},
+			to: {
+				type: String,
+				default: ''
+			},
+			badgeText: {
+				type: [String, Number],
+				default: ''
+			},
+			badgePositon: {
+				type: String,
+				default: 'right'
+			},
+			time: {
+				type: String,
+				default: ''
+			},
+			avatarCircle: {
+				type: Boolean,
+				default: false
+			},
+			avatar: {
+				type: String,
+				default: ''
+			},
+			avatarList: {
+				type: Array,
+				default () {
+					return [];
+				}
+			}
+		},
+		// inject: ['list'],
+		computed: {
+			isSingle() {
+				if (this.badgeText === 'dot') {
+					return 'uni-badge--dot';
+				} else {
+					const badgeText = this.badgeText.toString();
+					if (badgeText.length > 1) {
+						return 'uni-badge--complex';
+					} else {
+						return 'uni-badge--single';
+					}
+				}
+			},
+			computedAvatar() {
+				if (this.avatarList.length > 4) {
+					this.imageWidth = avatarWidth * 0.31;
+					return 'avatarItem--3';
+				} else if (this.avatarList.length > 1) {
+					this.imageWidth = avatarWidth * 0.47;
+					return 'avatarItem--2';
+				} else {
+					this.imageWidth = avatarWidth;
+					return 'avatarItem--1';
+				}
+			}
+		},
+		data() {
+			return {
+				isFirstChild: false,
+				border: true,
+				// avatarList: 3,
+				imageWidth: 50
+			};
+		},
+		mounted() {
+			this.list = this.getForm()
+			if (this.list) {
+				if (!this.list.firstChildAppend) {
+					this.list.firstChildAppend = true;
+					this.isFirstChild = true;
+				}
+				this.border = this.list.border;
+			}
+		},
+		methods: {
+			/**
+			 * 获取父元素实例
+			 */
+			getForm(name = 'uniList') {
+				let parent = this.$parent;
+				let parentName = parent.$options.name;
+				while (parentName !== name) {
+					parent = parent.$parent;
+					if (!parent) return false
+					parentName = parent.$options.name;
+				}
+				return parent;
+			},
+			onClick() {
+				if (this.to !== '') {
+					this.openPage();
+					return;
+				}
+
+				if (this.clickable || this.link) {
+					this.$emit('click', {
+						data: {}
+					});
+				}
+			},
+			openPage() {
+				if (['navigateTo', 'redirectTo', 'reLaunch', 'switchTab'].indexOf(this.link) !== -1) {
+					this.pageApi(this.link);
+				} else {
+					this.pageApi('navigateTo');
+				}
+			},
+			pageApi(api) {
+				uni[api]({
+					url: this.to,
+					success: res => {
+						this.$emit('click', {
+							data: res
+						});
+					},
+					fail: err => {
+						this.$emit('click', {
+							data: err
+						});
+						console.error(err.errMsg);
+					}
+				});
+			}
+		}
+	};
+</script>
+
+<style lang="scss" >
+	$uni-font-size-lg:16px;
+	$uni-spacing-row-sm: 5px;
+	$uni-spacing-row-base: 10px;
+	$uni-spacing-row-lg: 15px;
+	$background-color: #fff;
+	$divide-line-color: #e5e5e5;
+	$avatar-width: 45px;
+	$avatar-border-radius: 5px;
+	$avatar-border-color: #eee;
+	$avatar-border-width: 1px;
+	$title-size: 16px;
+	$title-color: #3b4144;
+	$title-weight: normal;
+	$note-size: 12px;
+	$note-color: #999;
+	$note-weight: normal;
+	$right-text-size: 12px;
+	$right-text-color: #999;
+	$right-text-weight: normal;
+	$badge-left: 0px;
+	$badge-top: 0px;
+	$dot-width: 10px;
+	$dot-height: 10px;
+	$badge-size: 18px;
+	$badge-font: 12px;
+	$badge-color: #fff;
+	$badge-background-color: #ff5a5f;
+	$badge-space: 6px;
+	$hover: #f5f5f5;
+
+	.uni-list-chat {
+		font-size: $uni-font-size-lg;
+		position: relative;
+		flex-direction: column;
+		justify-content: space-between;
+		background-color: $background-color;
+	}
+
+	// .uni-list-chat--disabled {
+	// 	opacity: 0.3;
+	// }
+
+	.uni-list-chat--hover {
+		background-color: $hover;
+	}
+
+	.uni-list--border {
+		position: relative;
+		margin-left: $uni-spacing-row-lg;
+		/* #ifdef APP-PLUS */
+		border-top-color: $divide-line-color;
+		border-top-style: solid;
+		border-top-width: 0.5px;
+		/* #endif */
+	}
+
+	/* #ifndef APP-NVUE */
+	.uni-list--border:after {
+		position: absolute;
+		top: 0;
+		right: 0;
+		left: 0;
+		height: 1px;
+		content: '';
+		-webkit-transform: scaleY(0.5);
+		transform: scaleY(0.5);
+		background-color: $divide-line-color;
+	}
+
+	.uni-list-item--first:after {
+		height: 0px;
+	}
+
+	/* #endif */
+
+	.uni-list-chat--first {
+		border-top-width: 0px;
+	}
+
+	.uni-ellipsis {
+		/* #ifndef APP-NVUE */
+		overflow: hidden;
+		white-space: nowrap;
+		text-overflow: ellipsis;
+		/* #endif */
+		/* #ifdef APP-NVUE */
+		lines: 1;
+		/* #endif */
+	}
+
+	.uni-ellipsis-2 {
+		/* #ifndef APP-NVUE */
+		overflow: hidden;
+		text-overflow: ellipsis;
+		display: -webkit-box;
+		-webkit-line-clamp: 2;
+		-webkit-box-orient: vertical;
+		/* #endif */
+
+		/* #ifdef APP-NVUE */
+		lines: 2;
+		/* #endif */
+	}
+
+	.uni-list-chat__container {
+		position: relative;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		flex: 1;
+		padding: $uni-spacing-row-base $uni-spacing-row-lg;
+		position: relative;
+		overflow: hidden;
+	}
+
+	.uni-list-chat__header-warp {
+		position: relative;
+	}
+
+	.uni-list-chat__header {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		align-content: center;
+		/* #endif */
+		flex-direction: row;
+		justify-content: center;
+		align-items: center;
+		flex-wrap: wrap-reverse;
+		/* #ifdef APP-NVUE */
+		width: 50px;
+		height: 50px;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		width: $avatar-width;
+		height: $avatar-width;
+		/* #endif */
+
+		border-radius: $avatar-border-radius;
+		border-color: $avatar-border-color;
+		border-width: $avatar-border-width;
+		border-style: solid;
+		overflow: hidden;
+	}
+
+	.uni-list-chat__header-box {
+		/* #ifndef APP-PLUS */
+		box-sizing: border-box;
+		display: flex;
+		width: $avatar-width;
+		height: $avatar-width;
+		/* #endif */
+		/* #ifdef APP-NVUE */
+		width: 50px;
+		height: 50px;
+		/* #endif */
+		overflow: hidden;
+		border-radius: 2px;
+	}
+
+	.uni-list-chat__header-image {
+		margin: 1px;
+		/* #ifdef APP-NVUE */
+		width: 50px;
+		height: 50px;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		width: $avatar-width;
+		height: $avatar-width;
+		/* #endif */
+	}
+
+	/* #ifndef APP-NVUE */
+	.uni-list-chat__header-image {
+		display: block;
+		width: 100%;
+		height: 100%;
+	}
+
+	.avatarItem--1 {
+		width: 100%;
+		height: 100%;
+	}
+
+	.avatarItem--2 {
+		width: 47%;
+		height: 47%;
+	}
+
+	.avatarItem--3 {
+		width: 32%;
+		height: 32%;
+	}
+
+	/* #endif */
+	.header--circle {
+		border-radius: 50%;
+	}
+
+	.uni-list-chat__content {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		flex: 1;
+		overflow: hidden;
+		padding: 2px 0;
+	}
+
+	.uni-list-chat__content-main {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		justify-content: space-between;
+		padding-left: $uni-spacing-row-base;
+		flex: 1;
+		overflow: hidden;
+	}
+
+	.uni-list-chat__content-title {
+		font-size: $title-size;
+		color: $title-color;
+		font-weight: $title-weight;
+		overflow: hidden;
+	}
+
+	.uni-list-chat__content-note {
+		margin-top: 3px;
+		color: $note-color;
+		font-size: $note-size;
+		font-weight: $title-weight;
+		overflow: hidden;
+	}
+
+	.uni-list-chat__content-extra {
+		/* #ifndef APP-NVUE */
+		flex-shrink: 0;
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		justify-content: space-between;
+		align-items: flex-end;
+		margin-left: 5px;
+	}
+
+	.uni-list-chat__content-extra-text {
+		color: $right-text-color;
+		font-size: $right-text-size;
+		font-weight: $right-text-weight;
+		overflow: hidden;
+	}
+
+	.uni-list-chat__badge-pos {
+		position: absolute;
+		/* #ifdef APP-NVUE */
+		left: 55px;
+		top: 3px;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		left: calc(#{$avatar-width} + 10px - #{$badge-space} + #{$badge-left});
+		top: calc(#{$uni-spacing-row-base}/ 2 + 1px + #{$badge-top});
+		/* #endif */
+	}
+
+	.uni-list-chat__badge {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		justify-content: center;
+		align-items: center;
+		border-radius: 100px;
+		background-color: $badge-background-color;
+	}
+
+	.uni-list-chat__badge-text {
+		color: $badge-color;
+		font-size: $badge-font;
+	}
+
+	.uni-badge--single {
+		/* #ifndef APP-NVUE */
+		// left: calc(#{$avatar-width} + 7px + #{$badge-left});
+		/* #endif */
+		width: $badge-size;
+		height: $badge-size;
+	}
+
+	.uni-badge--complex {
+		/* #ifdef APP-NVUE */
+		left: 50px;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		width: auto;
+		/* #endif */
+		height: $badge-size;
+		padding: 0 $badge-space;
+	}
+
+	.uni-badge--dot {
+		/* #ifdef APP-NVUE */
+		left: 60px;
+		top: 6px;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		left: calc(#{$avatar-width} + 15px - #{$dot-width}/ 2 + 1px + #{$badge-left});
+		/* #endif */
+		width: $dot-width;
+		height: $dot-height;
+		padding: 0;
+	}
+
+	.uni-list-chat--right {
+		/* #ifdef APP-NVUE */
+		left: 0;
+		/* #endif */
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-list/components/uni-list-item/uni-list-item.vue b/yudao-ui-admin-uniapp/uni_modules/uni-list/components/uni-list-item/uni-list-item.vue
new file mode 100644
index 000000000..2c7d9ea7c
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-list/components/uni-list-item/uni-list-item.vue
@@ -0,0 +1,454 @@
+<template>
+	<!-- #ifdef APP-NVUE -->
+	<cell>
+		<!-- #endif -->
+
+		<view :class="{ 'uni-list-item--disabled': disabled }"
+			:hover-class="(!clickable && !link) || disabled || showSwitch ? '' : 'uni-list-item--hover'"
+			class="uni-list-item" @click="onClick">
+			<view v-if="!isFirstChild" class="border--left" :class="{ 'uni-list--border': border }"></view>
+			<view class="uni-list-item__container"
+				:class="{ 'container--right': showArrow || link, 'flex--direction': direction === 'column' }">
+				<slot name="header">
+					<view class="uni-list-item__header">
+						<view v-if="thumb" class="uni-list-item__icon">
+							<image :src="thumb" class="uni-list-item__icon-img" :class="['uni-list--' + thumbSize]" />
+						</view>
+						<view v-else-if="showExtraIcon" class="uni-list-item__icon">
+							<uni-icons :color="extraIcon.color" :size="extraIcon.size" :type="extraIcon.type" />
+						</view>
+					</view>
+				</slot>
+				<slot name="body">
+					<view class="uni-list-item__content"
+						:class="{ 'uni-list-item__content--center': thumb || showExtraIcon || showBadge || showSwitch }">
+						<text v-if="title" class="uni-list-item__content-title"
+							:class="[ellipsis !== 0 && ellipsis <= 2 ? 'uni-ellipsis-' + ellipsis : '']">{{ title }}</text>
+						<text v-if="note" class="uni-list-item__content-note">{{ note }}</text>
+					</view>
+				</slot>
+				<slot name="footer">
+					<view v-if="rightText || showBadge || showSwitch" class="uni-list-item__extra"
+						:class="{ 'flex--justify': direction === 'column' }">
+						<text v-if="rightText" class="uni-list-item__extra-text">{{ rightText }}</text>
+						<uni-badge v-if="showBadge" :type="badgeType" :text="badgeText" :custom-style="badgeStyle" />
+						<switch v-if="showSwitch" :disabled="disabled" :checked="switchChecked"
+							@change="onSwitchChange" />
+					</view>
+				</slot>
+			</view>
+			<uni-icons v-if="showArrow || link" :size="16" class="uni-icon-wrapper" color="#bbb" type="arrowright" />
+		</view>
+		<!-- #ifdef APP-NVUE -->
+	</cell>
+	<!-- #endif -->
+</template>
+
+<script>
+	/**
+	 * ListItem 列表子组件
+	 * @description 列表子组件
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=24
+	 * @property {String} 	title 							标题
+	 * @property {String} 	note 							描述
+	 * @property {String} 	thumb 							左侧缩略图,若thumb有值,则不会显示扩展图标
+	 * @property {String}  	thumbSize = [lg|base|sm]		略缩图大小
+	 * 	@value 	 lg			大图
+	 * 	@value 	 base		一般
+	 * 	@value 	 sm			小图
+	 * @property {String} 	badgeText						数字角标内容
+	 * @property {String} 	badgeType 						数字角标类型,参考[uni-icons](https://ext.dcloud.net.cn/plugin?id=21)
+	 * @property {Object}   badgeStyle           数字角标样式
+	 * @property {String} 	rightText 						右侧文字内容
+	 * @property {Boolean} 	disabled = [true|false]			是否禁用
+	 * @property {Boolean} 	clickable = [true|false] 		是否开启点击反馈
+	 * @property {String} 	link = [navigateTo|redirectTo|reLaunch|switchTab] 是否展示右侧箭头并开启点击反馈
+	 *  @value 	navigateTo 	同 uni.navigateTo()
+	 * 	@value redirectTo 	同 uni.redirectTo()
+	 * 	@value reLaunch   	同 uni.reLaunch()
+	 * 	@value switchTab  	同 uni.switchTab()
+	 * @property {String | PageURIString} 	to  			跳转目标页面
+	 * @property {Boolean} 	showBadge = [true|false] 		是否显示数字角标
+	 * @property {Boolean} 	showSwitch = [true|false] 		是否显示Switch
+	 * @property {Boolean} 	switchChecked = [true|false] 	Switch是否被选中
+	 * @property {Boolean} 	showExtraIcon = [true|false] 	左侧是否显示扩展图标
+	 * @property {Object} 	extraIcon 						扩展图标参数,格式为 {color: '#4cd964',size: '22',type: 'spinner'}
+	 * @property {String} 	direction = [row|column]		排版方向
+	 * @value row 			水平排列
+	 * @value column 		垂直排列
+	 * @event {Function} 	click 							点击 uniListItem 触发事件
+	 * @event {Function} 	switchChange 					点击切换 Switch 时触发
+	 */
+	export default {
+		name: 'UniListItem',
+		emits: ['click', 'switchChange'],
+		props: {
+			direction: {
+				type: String,
+				default: 'row'
+			},
+			title: {
+				type: String,
+				default: ''
+			},
+			note: {
+				type: String,
+				default: ''
+			},
+			ellipsis: {
+				type: [Number,String],
+				default: 0
+			},
+			disabled: {
+				type: [Boolean, String],
+				default: false
+			},
+			clickable: {
+				type: Boolean,
+				default: false
+			},
+			showArrow: {
+				type: [Boolean, String],
+				default: false
+			},
+			link: {
+				type: [Boolean, String],
+				default: false
+			},
+			to: {
+				type: String,
+				default: ''
+			},
+			showBadge: {
+				type: [Boolean, String],
+				default: false
+			},
+			showSwitch: {
+				type: [Boolean, String],
+				default: false
+			},
+			switchChecked: {
+				type: [Boolean, String],
+				default: false
+			},
+			badgeText: {
+				type: String,
+				default: ''
+			},
+			badgeType: {
+				type: String,
+				default: 'success'
+			},
+			badgeStyle:{
+				type: Object,
+				default () {
+					return {}
+				}
+			},
+			rightText: {
+				type: String,
+				default: ''
+			},
+			thumb: {
+				type: String,
+				default: ''
+			},
+			thumbSize: {
+				type: String,
+				default: 'base'
+			},
+			showExtraIcon: {
+				type: [Boolean, String],
+				default: false
+			},
+			extraIcon: {
+				type: Object,
+				default () {
+					return {
+						type: '',
+						color: '#000000',
+						size: 20
+					};
+				}
+			},
+			border: {
+				type: Boolean,
+				default: true
+			}
+		},
+		// inject: ['list'],
+		data() {
+			return {
+				isFirstChild: false
+			};
+		},
+		mounted() {
+			this.list = this.getForm()
+			// 判断是否存在 uni-list 组件
+			if (this.list) {
+				if (!this.list.firstChildAppend) {
+					this.list.firstChildAppend = true;
+					this.isFirstChild = true;
+				}
+			}
+		},
+		methods: {
+			/**
+			 * 获取父元素实例
+			 */
+			getForm(name = 'uniList') {
+				let parent = this.$parent;
+				let parentName = parent.$options.name;
+				while (parentName !== name) {
+					parent = parent.$parent;
+					if (!parent) return false
+					parentName = parent.$options.name;
+				}
+				return parent;
+			},
+			onClick() {
+				if (this.to !== '') {
+					this.openPage();
+					return;
+				}
+				if (this.clickable || this.link) {
+					this.$emit('click', {
+						data: {}
+					});
+				}
+			},
+			onSwitchChange(e) {
+				this.$emit('switchChange', e.detail);
+			},
+			openPage() {
+				if (['navigateTo', 'redirectTo', 'reLaunch', 'switchTab'].indexOf(this.link) !== -1) {
+					this.pageApi(this.link);
+				} else {
+					this.pageApi('navigateTo');
+				}
+			},
+			pageApi(api) {
+				let callback = {
+					url: this.to,
+					success: res => {
+						this.$emit('click', {
+							data: res
+						});
+					},
+					fail: err => {
+						this.$emit('click', {
+							data: err
+						});
+					}
+				}
+				switch (api) {
+					case 'navigateTo':
+						uni.navigateTo(callback)
+						break
+					case 'redirectTo':
+						uni.redirectTo(callback)
+						break
+					case 'reLaunch':
+						uni.reLaunch(callback)
+						break
+					case 'switchTab':
+						uni.switchTab(callback)
+						break
+					default:
+					uni.navigateTo(callback)
+				}
+			}
+		}
+	};
+</script>
+
+<style lang="scss">
+	$uni-font-size-sm:12px;
+	$uni-font-size-base:14px;
+	$uni-font-size-lg:16px;
+	$uni-spacing-col-lg: 12px;
+	$uni-spacing-row-lg: 15px;
+	$uni-img-size-sm:20px;
+	$uni-img-size-base:26px;
+	$uni-img-size-lg:40px;
+	$uni-border-color:#e5e5e5;
+	$uni-bg-color-hover:#f1f1f1;
+	$uni-text-color-grey:#999;
+	$list-item-pd: $uni-spacing-col-lg $uni-spacing-row-lg;
+	.uni-list-item {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		font-size: $uni-font-size-lg;
+		position: relative;
+		justify-content: space-between;
+		align-items: center;
+		background-color: #fff;
+		flex-direction: row;
+		/* #ifdef H5 */
+		cursor: pointer;
+		/* #endif */
+	}
+	.uni-list-item--disabled {
+		opacity: 0.3;
+	}
+	.uni-list-item--hover {
+		background-color: $uni-bg-color-hover;
+	}
+	.uni-list-item__container {
+		position: relative;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		padding: $list-item-pd;
+		padding-left: $uni-spacing-row-lg;
+		flex: 1;
+		overflow: hidden;
+		// align-items: center;
+	}
+	.container--right {
+		padding-right: 0;
+	}
+	// .border--left {
+	// 	margin-left: $uni-spacing-row-lg;
+	// }
+	.uni-list--border {
+		position: absolute;
+		top: 0;
+		right: 0;
+		left: 0;
+		/* #ifdef APP-NVUE */
+		border-top-color: $uni-border-color;
+		border-top-style: solid;
+		border-top-width: 0.5px;
+		/* #endif */
+	}
+	/* #ifndef APP-NVUE */
+	.uni-list--border:after {
+		position: absolute;
+		top: 0;
+		right: 0;
+		left: 0;
+		height: 1px;
+		content: '';
+		-webkit-transform: scaleY(0.5);
+		transform: scaleY(0.5);
+		background-color: $uni-border-color;
+	}
+	/* #endif */
+	.uni-list-item__content {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		padding-right: 8px;
+		flex: 1;
+		color: #3b4144;
+		// overflow: hidden;
+		flex-direction: column;
+		justify-content: space-between;
+		overflow: hidden;
+	}
+	.uni-list-item__content--center {
+		justify-content: center;
+	}
+	.uni-list-item__content-title {
+		font-size: $uni-font-size-base;
+		color: #3b4144;
+		overflow: hidden;
+	}
+	.uni-list-item__content-note {
+		margin-top: 6rpx;
+		color: $uni-text-color-grey;
+		font-size: $uni-font-size-sm;
+		overflow: hidden;
+	}
+	.uni-list-item__extra {
+		// width: 25%;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		justify-content: flex-end;
+		align-items: center;
+	}
+	.uni-list-item__header {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		align-items: center;
+	}
+	.uni-list-item__icon {
+		margin-right: 18rpx;
+		flex-direction: row;
+		justify-content: center;
+		align-items: center;
+	}
+	.uni-list-item__icon-img {
+		/* #ifndef APP-NVUE */
+		display: block;
+		/* #endif */
+		height: $uni-img-size-base;
+		width: $uni-img-size-base;
+		margin-right: 10px;
+	}
+	.uni-icon-wrapper {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		align-items: center;
+		padding: 0 10px;
+	}
+	.flex--direction {
+		flex-direction: column;
+		/* #ifndef APP-NVUE */
+		align-items: initial;
+		/* #endif */
+	}
+	.flex--justify {
+		/* #ifndef APP-NVUE */
+		justify-content: initial;
+		/* #endif */
+	}
+	.uni-list--lg {
+		height: $uni-img-size-lg;
+		width: $uni-img-size-lg;
+	}
+	.uni-list--base {
+		height: $uni-img-size-base;
+		width: $uni-img-size-base;
+	}
+	.uni-list--sm {
+		height: $uni-img-size-sm;
+		width: $uni-img-size-sm;
+	}
+	.uni-list-item__extra-text {
+		color: $uni-text-color-grey;
+		font-size: $uni-font-size-sm;
+	}
+	.uni-ellipsis-1 {
+		/* #ifndef APP-NVUE */
+		overflow: hidden;
+		white-space: nowrap;
+		text-overflow: ellipsis;
+		/* #endif */
+		/* #ifdef APP-NVUE */
+		lines: 1;
+		text-overflow:ellipsis;
+		/* #endif */
+	}
+	.uni-ellipsis-2 {
+		/* #ifndef APP-NVUE */
+		overflow: hidden;
+		text-overflow: ellipsis;
+		display: -webkit-box;
+		-webkit-line-clamp: 2;
+		-webkit-box-orient: vertical;
+		/* #endif */
+		/* #ifdef APP-NVUE */
+		lines: 2;
+		text-overflow:ellipsis;
+		/* #endif */
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-list/components/uni-list/uni-list.vue b/yudao-ui-admin-uniapp/uni_modules/uni-list/components/uni-list/uni-list.vue
new file mode 100644
index 000000000..ecda67653
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-list/components/uni-list/uni-list.vue
@@ -0,0 +1,108 @@
+<template>
+	<!-- #ifndef APP-NVUE -->
+	<view class="uni-list uni-border-top-bottom">
+		<view v-if="border" class="uni-list--border-top"></view>
+		<slot />
+		<view v-if="border" class="uni-list--border-bottom"></view>
+	</view>
+	<!-- #endif -->
+	<!-- #ifdef APP-NVUE -->
+	<list class="uni-list" :class="{ 'uni-list--border': border }" :enableBackToTop="enableBackToTop" loadmoreoffset="15"><slot /></list>
+	<!-- #endif -->
+</template>
+
+<script>
+/**
+ * List 列表
+ * @description 列表组件
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=24
+ * @property {String} 	border = [true|false] 		标题
+ */
+export default {
+	name: 'uniList',
+	'mp-weixin': {
+		options: {
+			multipleSlots: false
+		}
+	},
+	props: {
+		enableBackToTop: {
+			type: [Boolean, String],
+			default: false
+		},
+		scrollY: {
+			type: [Boolean, String],
+			default: false
+		},
+		border: {
+			type: Boolean,
+			default: true
+		}
+	},
+	// provide() {
+	// 	return {
+	// 		list: this
+	// 	};
+	// },
+	created() {
+		this.firstChildAppend = false;
+	},
+	methods: {
+		loadMore(e) {
+			this.$emit('scrolltolower');
+		}
+	}
+};
+</script>
+<style lang="scss" >
+$uni-bg-color:#ffffff;
+$uni-border-color:#e5e5e5;
+.uni-list {
+	/* #ifndef APP-NVUE */
+	display: flex;
+	/* #endif */
+	background-color: $uni-bg-color;
+	position: relative;
+	flex-direction: column;
+}
+
+.uni-list--border {
+	position: relative;
+	/* #ifdef APP-NVUE */
+	border-top-color: $uni-border-color;
+	border-top-style: solid;
+	border-top-width: 0.5px;
+	border-bottom-color: $uni-border-color;
+	border-bottom-style: solid;
+	border-bottom-width: 0.5px;
+	/* #endif */
+	z-index: -1;
+}
+
+/* #ifndef APP-NVUE */
+
+.uni-list--border-top {
+	position: absolute;
+	top: 0;
+	right: 0;
+	left: 0;
+	height: 1px;
+	-webkit-transform: scaleY(0.5);
+	transform: scaleY(0.5);
+	background-color: $uni-border-color;
+	z-index: 1;
+}
+
+.uni-list--border-bottom {
+	position: absolute;
+	bottom: 0;
+	right: 0;
+	left: 0;
+	height: 1px;
+	-webkit-transform: scaleY(0.5);
+	transform: scaleY(0.5);
+	background-color: $uni-border-color;
+}
+
+/* #endif */
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-list/components/uni-list/uni-refresh.vue b/yudao-ui-admin-uniapp/uni_modules/uni-list/components/uni-list/uni-refresh.vue
new file mode 100644
index 000000000..3b4c5a230
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-list/components/uni-list/uni-refresh.vue
@@ -0,0 +1,65 @@
+<template>
+    <!-- #ifdef APP-NVUE -->
+    <refresh :display="display" @refresh="onrefresh" @pullingdown="onpullingdown">
+        <slot />
+    </refresh>
+    <!-- #endif -->
+    <!-- #ifndef APP-NVUE -->
+    <view ref="uni-refresh" class="uni-refresh" v-show="isShow">
+        <slot />
+    </view>
+    <!-- #endif -->
+</template>
+
+<script>
+    export default {
+        name: 'UniRefresh',
+        props: {
+            display: {
+                type: [String],
+                default: "hide"
+            }
+        },
+        data() {
+            return {
+                pulling: false
+            }
+        },
+        computed: {
+            isShow() {
+                if (this.display === "show" || this.pulling === true) {
+                    return true;
+                }
+                return false;
+            }
+        },
+        created() {},
+        methods: {
+            onchange(value) {
+                this.pulling = value;
+            },
+            onrefresh(e) {
+                this.$emit("refresh", e);
+            },
+            onpullingdown(e) {
+                // #ifdef APP-NVUE
+                this.$emit("pullingdown", e);
+                // #endif
+                // #ifndef APP-NVUE
+                var detail = {
+                    viewHeight: 90,
+                    pullingDistance: e.height
+                }
+                this.$emit("pullingdown", detail);
+                // #endif
+            }
+        }
+    }
+</script>
+
+<style>
+    .uni-refresh {
+        height: 0;
+        overflow: hidden;
+    }
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-list/components/uni-list/uni-refresh.wxs b/yudao-ui-admin-uniapp/uni_modules/uni-list/components/uni-list/uni-refresh.wxs
new file mode 100644
index 000000000..818a6b721
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-list/components/uni-list/uni-refresh.wxs
@@ -0,0 +1,87 @@
+var pullDown = {
+    threshold: 95,
+    maxHeight: 200,
+    callRefresh: 'onrefresh',
+    callPullingDown: 'onpullingdown',
+    refreshSelector: '.uni-refresh'
+};
+
+function ready(newValue, oldValue, ownerInstance, instance) {
+    var state = instance.getState()
+    state.canPullDown = newValue;
+    // console.log(newValue);
+}
+
+function touchStart(e, instance) {
+    var state = instance.getState();
+    state.refreshInstance = instance.selectComponent(pullDown.refreshSelector);
+    state.canPullDown = (state.refreshInstance != null && state.refreshInstance != undefined);
+    if (!state.canPullDown) {
+        return
+    }
+
+    // console.log("touchStart");
+
+    state.height = 0;
+    state.touchStartY = e.touches[0].pageY || e.changedTouches[0].pageY;
+    state.refreshInstance.setStyle({
+        'height': 0
+    });
+    state.refreshInstance.callMethod("onchange", true);
+}
+
+function touchMove(e, ownerInstance) {
+    var instance = e.instance;
+    var state = instance.getState();
+    if (!state.canPullDown) {
+        return
+    }
+
+    var oldHeight = state.height;
+    var endY = e.touches[0].pageY || e.changedTouches[0].pageY;
+    var height = endY - state.touchStartY;
+    if (height > pullDown.maxHeight) {
+        return;
+    }
+
+    var refreshInstance = state.refreshInstance;
+    refreshInstance.setStyle({
+        'height': height + 'px'
+    });
+
+    height = height < pullDown.maxHeight ? height : pullDown.maxHeight;
+    state.height = height;
+    refreshInstance.callMethod(pullDown.callPullingDown, {
+        height: height
+    });
+}
+
+function touchEnd(e, ownerInstance) {
+    var state = e.instance.getState();
+    if (!state.canPullDown) {
+        return
+    }
+
+    state.refreshInstance.callMethod("onchange", false);
+
+    var refreshInstance = state.refreshInstance;
+    if (state.height > pullDown.threshold) {
+        refreshInstance.callMethod(pullDown.callRefresh);
+        return;
+    }
+
+    refreshInstance.setStyle({
+        'height': 0
+    });
+}
+
+function propObserver(newValue, oldValue, instance) {
+    pullDown = newValue;
+}
+
+module.exports = {
+    touchmove: touchMove,
+    touchstart: touchStart,
+    touchend: touchEnd,
+    propObserver: propObserver
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-list/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-list/package.json
new file mode 100644
index 000000000..66e8bef0c
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-list/package.json
@@ -0,0 +1,91 @@
+{
+  "id": "uni-list",
+  "displayName": "uni-list 列表",
+  "version": "1.2.1",
+  "description": "List 组件 ,帮助使用者快速构建列表。",
+  "keywords": [
+    "",
+    "uni-ui",
+    "uniui",
+    "列表",
+    "",
+    "list"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": [
+      "uni-badge",
+      "uni-icons"
+    ],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-list/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-list/readme.md
new file mode 100644
index 000000000..32c28654e
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-list/readme.md
@@ -0,0 +1,346 @@
+## List 列表
+> **组件名:uni-list**
+> 代码块: `uList`、`uListItem`
+> 关联组件:`uni-list-item`、`uni-badge`、`uni-icons`、`uni-list-chat`、`uni-list-ad`
+
+
+List 列表组件,包含基本列表样式、可扩展插槽机制、长列表性能优化、多端兼容。
+
+在vue页面里,它默认使用页面级滚动。在app-nvue页面里,它默认使用原生list组件滚动。这样的长列表,在滚动出屏幕外后,系统会回收不可见区域的渲染内存资源,不会造成滚动越长手机越卡的问题。
+
+uni-list组件是父容器,里面的核心是uni-list-item子组件,它代表列表中的一个可重复行,子组件可以无限循环。
+
+uni-list-item有很多风格,uni-list-item组件通过内置的属性,满足一些常用的场景。当内置属性不满足需求时,可以通过扩展插槽来自定义列表内容。
+
+内置属性可以覆盖的场景包括:导航列表、设置列表、小图标列表、通信录列表、聊天记录列表。
+
+涉及很多大图或丰富内容的列表,比如类今日头条的新闻列表、类淘宝的电商列表,需要通过扩展插槽实现。
+
+下文均有样例给出。
+
+uni-list不包含下拉刷新和上拉翻页。上拉翻页另见组件:[uni-load-more](https://ext.dcloud.net.cn/plugin?id=29)
+
+
+### 安装方式
+
+本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。
+
+如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55)
+
+> **注意事项**
+> 为了避免错误使用,给大家带来不好的开发体验,请在使用组件前仔细阅读下面的注意事项,可以帮你避免一些错误。
+> - 组件需要依赖 `sass` 插件 ,请自行手动安装
+> - 组件内部依赖 `'uni-icons'` 、`uni-badge` 组件
+> - `uni-list` 和 `uni-list-item` 需要配套使用,暂不支持单独使用 `uni-list-item`
+> - 只有开启点击反馈后,会有点击选中效果
+> - 使用插槽时,可以完全自定义内容
+> - note 、rightText 属性暂时没做限制,不支持文字溢出隐藏,使用时应该控制长度显示或通过默认插槽自行扩展
+> - 支付宝小程序平台需要在支付宝小程序开发者工具里开启 component2 编译模式,开启方式: 详情 --> 项目配置 --> 启用 component2 编译
+> - 如果需要修改 `switch`、`badge` 样式,请使用插槽自定义
+> - 在 `HBuilderX` 低版本中,可能会出现组件显示 `undefined` 的问题,请升级最新的 `HBuilderX` 或者 `cli`
+> - 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839
+ 
+
+### 基本用法 
+
+- 设置 `title` 属性,可以显示列表标题
+- 设置 `disabled` 属性,可以禁用当前项
+
+```html
+<uni-list>
+	<uni-list-item  title="列表文字" ></uni-list-item>
+	<uni-list-item :disabled="true" title="列表禁用状态" ></uni-list-item>
+</uni-list>
+			 
+```
+
+### 多行内容显示
+
+- 设置 `note` 属性 ,可以在第二行显示描述文本信息
+
+```html
+<uni-list>
+	<uni-list-item title="列表文字" note="列表描述信息"></uni-list-item>
+	<uni-list-item :disabled="true" title="列表文字" note="列表禁用状态"></uni-list-item>
+</uni-list>
+
+```
+
+### 右侧显示角标、switch
+
+- 设置 `show-badge` 属性 ,可以显示角标内容
+- 设置 `show-switch` 属性,可以显示 switch 开关
+
+```html
+<uni-list>
+	<uni-list-item  title="列表右侧显示角标" :show-badge="true" badge-text="12" ></uni-list-item>
+	<uni-list-item title="列表右侧显示 switch"  :show-switch="true"  @switchChange="switchChange" ></uni-list-item>
+</uni-list>
+
+```
+
+### 左侧显示略缩图、图标  
+
+- 设置 `thumb` 属性 ,可以在列表左侧显示略缩图
+- 设置 `show-extra-icon` 属性,并指定 `extra-icon` 可以在左侧显示图标
+
+```html
+ <uni-list>
+ 	<uni-list-item title="列表左侧带略缩图" note="列表描述信息" thumb="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png"
+ 	 thumb-size="lg" rightText="右侧文字"></uni-list-item>
+ 	<uni-list-item :show-extra-icon="true" :extra-icon="extraIcon1" title="列表左侧带扩展图标" ></uni-list-item>
+</uni-list>
+```
+
+### 开启点击反馈和右侧箭头
+- 设置 `clickable` 为 `true` ,则表示这是一个可点击的列表,会默认给一个点击效果,并可以监听 `click` 事件
+- 设置 `link` 属性,会自动开启点击反馈,并给列表右侧添加一个箭头
+- 设置 `to` 属性,可以跳转页面,`link` 的值表示跳转方式,如果不指定,默认为 `navigateTo`
+
+```html
+
+<uni-list>
+	<uni-list-item title="开启点击反馈" clickable  @click="onClick" ></uni-list-item>
+	<uni-list-item title="默认 navigateTo 方式跳转页面" link to="/pages/vue/index/index" @click="onClick($event,1)" ></uni-list-item>
+	<uni-list-item title="reLaunch 方式跳转页面" link="reLaunch" to="/pages/vue/index/index" @click="onClick($event,1)" ></uni-list-item>
+</uni-list>
+
+```
+
+
+### 聊天列表示例
+- 设置 `clickable` 为 `true` ,则表示这是一个可点击的列表,会默认给一个点击效果,并可以监听 `click` 事件
+- 设置 `link` 属性,会自动开启点击反馈,`link` 的值表示跳转方式,如果不指定,默认为 `navigateTo`
+- 设置 `to` 属性,可以跳转页面
+- `time` 属性,通常会设置成时间显示,但是这个属性不仅仅可以设置时间,你可以传入任何文本,注意文本长度可能会影响显示
+- `avatar` 和 `avatarList` 属性同时只会有一个生效,同时设置的话,`avatarList` 属性的长度大于1 ,`avatar` 属性将失效
+- 可以通过默认插槽自定义列表右侧内容
+
+```html
+
+<uni-list>
+	<uni-list :border="true">
+		<!-- 显示圆形头像 -->
+		<uni-list-chat :avatar-circle="true" title="uni-app" avatar="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png" note="您收到一条新的消息" time="2020-02-02 20:20" ></uni-list-chat>
+		<!-- 右侧带角标 -->
+		<uni-list-chat title="uni-app" avatar="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png" note="您收到一条新的消息" time="2020-02-02 20:20" badge-text="12" :badge-style="{backgroundColor:'#FF80AB'}"></uni-list-chat>
+		<!-- 头像显示圆点 -->
+		<uni-list-chat title="uni-app" avatar="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png" note="您收到一条新的消息" time="2020-02-02 20:20" badge-positon="left" badge-text="dot"></uni-list-chat>
+		<!-- 头像显示角标 -->
+		<uni-list-chat title="uni-app" avatar="https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png" note="您收到一条新的消息" time="2020-02-02 20:20" badge-positon="left" badge-text="99"></uni-list-chat>
+		<!-- 显示多头像 -->
+		<uni-list-chat title="uni-app" :avatar-list="avatarList" note="您收到一条新的消息" time="2020-02-02 20:20" badge-positon="left" badge-text="dot"></uni-list-chat>
+		<!-- 自定义右侧内容 -->
+		<uni-list-chat title="uni-app" :avatar-list="avatarList" note="您收到一条新的消息" time="2020-02-02 20:20" badge-positon="left" badge-text="dot">
+			<view class="chat-custom-right">
+				<text class="chat-custom-text">刚刚</text>
+				<!-- 需要使用 uni-icons 请自行引入 -->
+				<uni-icons type="star-filled" color="#999" size="18"></uni-icons>
+			</view>
+		</uni-list-chat>
+	</uni-list>
+</uni-list>
+
+```
+
+```javascript
+
+export default {
+	components: {},
+	data() {
+		return {
+			avatarList: [{
+				url: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png'
+			}, {
+				url: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png'
+			}, {
+				url: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png'
+			}]
+		}
+	}
+}
+
+```
+
+
+```css
+
+.chat-custom-right {
+	flex: 1;
+	/* #ifndef APP-NVUE */
+	display: flex;
+	/* #endif */
+	flex-direction: column;
+	justify-content: space-between;
+	align-items: flex-end;
+}
+
+.chat-custom-text {
+	font-size: 12px;
+	color: #999;
+}
+
+```
+
+## API
+
+### List Props
+
+属性名			|类型		|默认值		|	说明																									
+:-:				|:-:		|:-:		|	:-:	
+border			|Boolean	|true		|	是否显示边框
+
+
+### ListItem Props
+
+属性名			|类型		|默认值		|	说明																					
+:-:				|:-:		|:-:		|	:-:	
+title			|String		|-			|	标题
+note			|String		|-			|	描述
+ellipsis		|Number		|0			|	title 是否溢出隐藏,可选值,0:默认;  1:显示一行;	2:显示两行;【nvue 暂不支持】
+thumb			|String		|-			|	左侧缩略图,若thumb有值,则不会显示扩展图标
+thumbSize		|String 	|medium 	|	略缩图尺寸,可选值,lg:大图;  medium:一般;	sm:小图;
+showBadge		|Boolean	|false		|	是否显示数字角标	
+badgeText		|String		|-			|	数字角标内容
+badgeType		|String		|-			|	数字角标类型,参考[uni-icons](https://ext.dcloud.net.cn/plugin?id=21)	
+badgeStyle  |Object   |-      | 数字角标样式,使用uni-badge的custom-style参数
+rightText		|String		|-			|	右侧文字内容
+disabled		|Boolean	|false		|	是否禁用	
+showArrow 		|Boolean	|true		|	是否显示箭头图标			
+link			|String 	|navigateTo	|	新页面跳转方式,可选值见下表
+to				|String		|-			|	新页面跳转地址,如填写此属性,click 会返回页面是否跳转成功			
+clickable		|Boolean	|false		|	是否开启点击反馈
+showSwitch	    |Boolean	|false		|	是否显示Switch																			
+switchChecked	|Boolean	|false		|	Switch是否被选中																			
+showExtraIcon   |Boolean	|false		|	左侧是否显示扩展图标																		
+extraIcon		|Object		|-			|	扩展图标参数,格式为 ``{color: '#4cd964',size: '22',type: 'spinner'}``,参考 [uni-icons](https://ext.dcloud.net.cn/plugin?id=28)	
+direction		| String	|row		|	排版方向,可选值,row:水平排列;  column:垂直排列; 3个插槽是水平排还是垂直排,也受此属性控制
+
+
+#### Link Options
+
+属性名				|	说明
+:-:					|	:-:
+navigateTo 	| 	同 uni.navigateTo()
+redirectTo 	|	同 uni.reLaunch()
+reLaunch		|	同 uni.reLaunch()
+switchTab  	|	同 uni.switchTab()
+
+### ListItem Events
+
+事件称名			|说明									|返回参数			
+:-:				|:-:									|:-:				
+click			|点击 uniListItem 触发事件,需开启点击反馈	|-					
+switchChange	|点击切换 Switch 时触发,需显示 switch		|e={value:checked}	
+
+
+
+### ListItem Slots
+
+名称	 	|	说明					
+:-:		|	:-:						
+header	|	左/上内容插槽,可完全自定义默认显示
+body	|	中间内容插槽,可完全自定义中间内容				
+footer	|	右/下内容插槽,可完全自定义右侧内容		
+
+
+> **通过插槽扩展**
+> 需要注意的是当使用插槽时,内置样式将会失效,只保留排版样式,此时的样式需要开发者自己实现
+> 如果	`uni-list-item` 组件内置属性样式无法满足需求,可以使用插槽来自定义uni-list-item里的内容。
+> uni-list-item提供了3个可扩展的插槽:`header`、`body`、`footer`
+> - 当 `direction` 属性为 `row` 时表示水平排列,此时 `header` 表示列表的左边部分,`body` 表示列表的中间部分,`footer` 表示列表的右边部分
+> - 当 `direction` 属性为 `column` 时表示垂直排列,此时 `header` 表示列表的上边部分,`body` 表示列表的中间部分,`footer` 表示列表的下边部分
+> 开发者可以只用1个插槽,也可以3个一起使用。在插槽中可自主编写view标签,实现自己所需的效果。
+
+	
+**示例**
+
+```html
+<uni-list>
+	<uni-list-item title="自定义右侧插槽" note="列表描述信息" link>
+		<template slot="header">
+			<image class="slot-image" src="/static/logo.png" mode="widthFix"></image>
+		</template>
+	</uni-list-item>
+	<uni-list-item>
+		<!-- 自定义 header -->
+		<view slot="header" class="slot-box"><image class="slot-image" src="/static/logo.png" mode="widthFix"></image></view>
+		<!-- 自定义 body -->
+		<text slot="body" class="slot-box slot-text">自定义插槽</text>
+		<!-- 自定义 footer-->
+		<template slot="footer">
+			<image class="slot-image" src="/static/logo.png" mode="widthFix"></image>
+		</template>
+	</uni-list-item>
+</uni-list>
+```
+
+
+
+
+
+### ListItemChat Props
+
+属性名			|类型		|默认值		|	说明																		
+:-:				|:-:		|:-:		|	:-:	
+title 			|String		|-			|	标题
+note 			|String		|-			|	描述
+clickable		|Boolean	|false		|	是否开启点击反馈
+badgeText		|String		|-			|	数字角标内容,设置为 `dot` 将显示圆点
+badgePositon 	|String		|right		|	角标位置
+link			|String 	|navigateTo	|	是否展示右侧箭头并开启点击反馈,可选值见下表
+clickable		|Boolean	|false		|	是否开启点击反馈
+to				|String		|-			|	跳转页面地址,如填写此属性,click 会返回页面是否跳转成功	
+time			|String 	|-			|	右侧时间显示
+avatarCircle 	|Boolean 	|false		|	是否显示圆形头像
+avatar			|String 	|-			|	头像地址,avatarCircle 不填时生效
+avatarList 		|Array	 	|-			|	头像组,格式为 [{url:''}]
+
+#### Link Options
+
+属性名		|	说明
+:-:			|	:-:
+navigateTo 	| 	同 uni.navigateTo()
+redirectTo 	|	同 uni.reLaunch()
+reLaunch	|	同 uni.reLaunch()
+switchTab  	|	同 uni.switchTab()
+
+### ListItemChat Slots
+
+名称	 	|	说明					
+:-		|	:-						
+default	|	自定义列表右侧内容(包括时间和角标显示)
+
+### ListItemChat Events
+事件称名			|	说明						|	返回参数			
+:-:				|	:-:						|	:-:	
+@click			|	点击 uniListChat 触发事件	|	{data:{}}	,如有 to 属性,会返回页面跳转信息	
+
+
+
+
+
+
+## 基于uni-list扩展的页面模板
+
+通过扩展插槽,可实现多种常见样式的列表
+
+**新闻列表类**
+
+1. 云端一体混合布局:[https://ext.dcloud.net.cn/plugin?id=2546](https://ext.dcloud.net.cn/plugin?id=2546)
+2. 云端一体垂直布局,大图模式:[https://ext.dcloud.net.cn/plugin?id=2583](https://ext.dcloud.net.cn/plugin?id=2583)
+3. 云端一体垂直布局,多行图文混排:[https://ext.dcloud.net.cn/plugin?id=2584](https://ext.dcloud.net.cn/plugin?id=2584)
+4. 云端一体垂直布局,多图模式:[https://ext.dcloud.net.cn/plugin?id=2585](https://ext.dcloud.net.cn/plugin?id=2585)
+5. 云端一体水平布局,左图右文:[https://ext.dcloud.net.cn/plugin?id=2586](https://ext.dcloud.net.cn/plugin?id=2586)
+6. 云端一体水平布局,左文右图:[https://ext.dcloud.net.cn/plugin?id=2587](https://ext.dcloud.net.cn/plugin?id=2587)
+7. 云端一体垂直布局,无图模式,主标题+副标题:[https://ext.dcloud.net.cn/plugin?id=2588](https://ext.dcloud.net.cn/plugin?id=2588)
+
+**商品列表类**
+
+1. 云端一体列表/宫格视图互切:[https://ext.dcloud.net.cn/plugin?id=2651](https://ext.dcloud.net.cn/plugin?id=2651)
+2. 云端一体列表(宫格模式):[https://ext.dcloud.net.cn/plugin?id=2671](https://ext.dcloud.net.cn/plugin?id=2671)
+3. 云端一体列表(列表模式):[https://ext.dcloud.net.cn/plugin?id=2672](https://ext.dcloud.net.cn/plugin?id=2672)
+
+## 组件示例
+
+点击查看:[https://hellouniapp.dcloud.net.cn/pages/extUI/list/list](https://hellouniapp.dcloud.net.cn/pages/extUI/list/list)
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-load-more/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-load-more/changelog.md
new file mode 100644
index 000000000..8f03f1d57
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-load-more/changelog.md
@@ -0,0 +1,19 @@
+## 1.3.3(2022-01-20)
+- 新增 showText属性 ,是否显示文本
+## 1.3.2(2022-01-19)
+- 修复 nvue 平台下不显示文本的bug
+## 1.3.1(2022-01-19)
+- 修复 微信小程序平台样式选择器报警告的问题
+## 1.3.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-load-more](https://uniapp.dcloud.io/component/uniui/uni-load-more)
+## 1.2.1(2021-08-24)
+- 新增 支持国际化
+## 1.2.0(2021-07-30)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.1.8(2021-05-12)
+- 新增 组件示例地址
+## 1.1.7(2021-03-30)
+- 修复 uni-load-more 在首页使用时,h5 平台报 'uni is not defined' 的 bug
+## 1.1.6(2021-02-05)
+- 调整为uni_modules目录规范
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-load-more/components/uni-load-more/i18n/en.json b/yudao-ui-admin-uniapp/uni_modules/uni-load-more/components/uni-load-more/i18n/en.json
new file mode 100644
index 000000000..a4f14a545
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-load-more/components/uni-load-more/i18n/en.json
@@ -0,0 +1,5 @@
+{
+	"uni-load-more.contentdown": "Pull up to show more",
+	"uni-load-more.contentrefresh": "loading...",
+	"uni-load-more.contentnomore": "No more data"
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-load-more/components/uni-load-more/i18n/index.js b/yudao-ui-admin-uniapp/uni_modules/uni-load-more/components/uni-load-more/i18n/index.js
new file mode 100644
index 000000000..de7509c87
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-load-more/components/uni-load-more/i18n/index.js
@@ -0,0 +1,8 @@
+import en from './en.json'
+import zhHans from './zh-Hans.json'
+import zhHant from './zh-Hant.json'
+export default {
+	en,
+	'zh-Hans': zhHans,
+	'zh-Hant': zhHant
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hans.json b/yudao-ui-admin-uniapp/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hans.json
new file mode 100644
index 000000000..f15d51050
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hans.json
@@ -0,0 +1,5 @@
+{
+	"uni-load-more.contentdown": "上拉显示更多",
+	"uni-load-more.contentrefresh": "正在加载...",
+	"uni-load-more.contentnomore": "没有更多数据了"
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hant.json b/yudao-ui-admin-uniapp/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hant.json
new file mode 100644
index 000000000..a255c6ded
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-load-more/components/uni-load-more/i18n/zh-Hant.json
@@ -0,0 +1,5 @@
+{
+	"uni-load-more.contentdown": "上拉顯示更多",
+	"uni-load-more.contentrefresh": "正在加載...",
+	"uni-load-more.contentnomore": "沒有更多數據了"
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-load-more/components/uni-load-more/uni-load-more.vue b/yudao-ui-admin-uniapp/uni_modules/uni-load-more/components/uni-load-more/uni-load-more.vue
new file mode 100644
index 000000000..e5eff4d65
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-load-more/components/uni-load-more/uni-load-more.vue
@@ -0,0 +1,399 @@
+<template>
+	<view class="uni-load-more" @click="onClick">
+		<!-- #ifdef APP-NVUE -->
+		<loading-indicator v-if="!webviewHide && status === 'loading' && showIcon"
+			:style="{color: color,width:iconSize+'px',height:iconSize+'px'}" :animating="true"
+			class="uni-load-more__img uni-load-more__img--nvue"></loading-indicator>
+		<!-- #endif -->
+		<!-- #ifdef H5 -->
+		<svg width="24" height="24" viewBox="25 25 50 50"
+			v-if="!webviewHide && (iconType==='circle' || iconType==='auto' && platform === 'android') && status === 'loading' && showIcon"
+			:style="{width:iconSize+'px',height:iconSize+'px'}"
+			class="uni-load-more__img uni-load-more__img--android-H5">
+			<circle cx="50" cy="50" r="20" fill="none" :style="{color:color}" :stroke-width="3"></circle>
+		</svg>
+		<!-- #endif -->
+		<!-- #ifndef APP-NVUE || H5 -->
+		<view
+			v-if="!webviewHide && (iconType==='circle' || iconType==='auto' && platform === 'android') && status === 'loading' && showIcon"
+			:style="{width:iconSize+'px',height:iconSize+'px'}"
+			class="uni-load-more__img uni-load-more__img--android-MP">
+			<view class="uni-load-more__img-icon" :style="{borderTopColor:color,borderTopWidth:iconSize/12}"></view>
+			<view class="uni-load-more__img-icon" :style="{borderTopColor:color,borderTopWidth:iconSize/12}"></view>
+			<view class="uni-load-more__img-icon" :style="{borderTopColor:color,borderTopWidth:iconSize/12}"></view>
+		</view>
+		<!-- #endif -->
+		<!-- #ifndef APP-NVUE -->
+		<view v-else-if="!webviewHide && status === 'loading' && showIcon"
+			:style="{width:iconSize+'px',height:iconSize+'px'}" class="uni-load-more__img uni-load-more__img--ios-H5">
+			<image :src="imgBase64" mode="widthFix"></image>
+		</view>
+		<!-- #endif -->
+		<text v-if="showText" class="uni-load-more__text"
+			:style="{color: color}">{{ status === 'more' ? contentdownText : status === 'loading' ? contentrefreshText : contentnomoreText }}</text>
+	</view>
+</template>
+
+<script>
+	let platform
+	setTimeout(() => {
+		platform = uni.getSystemInfoSync().platform
+	}, 16)
+
+	import {
+		initVueI18n
+	} from '@dcloudio/uni-i18n'
+	import messages from './i18n/index.js'
+	const {
+		t
+	} = initVueI18n(messages)
+
+	/**
+	 * LoadMore 加载更多
+	 * @description 用于列表中,做滚动加载使用,展示 loading 的各种状态
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=29
+	 * @property {String} status = [more|loading|noMore] loading 的状态
+	 * 	@value more loading前
+	 * 	@value loading loading中
+	 * 	@value noMore 没有更多了
+	 * @property {Number} iconSize 指定图标大小
+	 * @property {Boolean} iconSize = [true|false] 是否显示 loading 图标
+	 * @property {String} iconType = [snow|circle|auto] 指定图标样式
+	 * 	@value snow ios雪花加载样式
+	 * 	@value circle 安卓唤醒加载样式
+	 * 	@value auto 根据平台自动选择加载样式
+	 * @property {String} color 图标和文字颜色
+	 * @property {Object} contentText 各状态文字说明,值为:{contentdown: "上拉显示更多",contentrefresh: "正在加载...",contentnomore: "没有更多数据了"}
+	 * @event {Function} clickLoadMore 点击加载更多时触发
+	 */
+	export default {
+		name: 'UniLoadMore',
+		emits: ['clickLoadMore'],
+		props: {
+			status: {
+				// 上拉的状态:more-loading前;loading-loading中;noMore-没有更多了
+				type: String,
+				default: 'more'
+			},
+			showIcon: {
+				type: Boolean,
+				default: true
+			},
+			iconType: {
+				type: String,
+				default: 'auto'
+			},
+			iconSize: {
+				type: Number,
+				default: 24
+			},
+			color: {
+				type: String,
+				default: '#777777'
+			},
+			contentText: {
+				type: Object,
+				default () {
+					return {
+						contentdown: '',
+						contentrefresh: '',
+						contentnomore: ''
+					}
+				}
+			},
+			showText: {
+				type: Boolean,
+				default: true
+			}
+		},
+		data() {
+			return {
+				webviewHide: false,
+				platform: platform,
+				imgBase64: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QzlBMzU3OTlEOUM0MTFFOUI0NTZDNERBQURBQzI4RkUiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QzlBMzU3OUFEOUM0MTFFOUI0NTZDNERBQURBQzI4RkUiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpDOUEzNTc5N0Q5QzQxMUU5QjQ1NkM0REFBREFDMjhGRSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpDOUEzNTc5OEQ5QzQxMUU5QjQ1NkM0REFBREFDMjhGRSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pt+ALSwAAA6CSURBVHja1FsLkFZVHb98LM+F5bHL8khA1iSeiyQBCRM+YGqKUnnJTDLGI0BGZlKDIU2MMglUiDApEZvSsZnQtBRJtKwQNKQMFYeRDR10WOLd8ljYXdh+v8v5fR3Od+797t1dnOnO/Ofce77z+J//+b/P+ZqtXbs2sJ9MJhNUV1cHJ06cCJo3bx7EPc2aNcvpy7pWrVoF+/fvDyoqKoI2bdoE9fX1F7TjN8a+EXBn/fkfvw942Tf+wYMHg9mzZwfjxo0LDhw4EPa1x2MbFw/fOGfPng1qa2tzcCkILsLDydq2bRsunpOTMM7TD/W/tZDZhPdeKD+yGxHhdu3aBV27dg3OnDlzMVANMheLAO3btw8KCwuDmpoaX5OxbgUIMEq7K8IcPnw4KCsrC/r37x8cP378/4cAXAB3vqSkJMuiDhTkw+XcuXNhOWbMmKBly5YhUT8xArhyFvP0BfwRsAuwxJZJsm/nzp2DTp06he/OU+cZ64K6o0ePBkOHDg2GDx8e6gEbJ5Q/NHNuAJQ1hgBeHUDlR7nVTkY8rQAvAi4z34vR/mPs1FoRsaCgIJThI0eOBC1atEiFGGV+5MiRoS45efJkqFjJFXV1dQuA012m2WcwTw98fy6CqBdsaiIO4CScrGPHjvk4odhavPquRtFWXEC25VgkREKOCh/qDSq+vn37htzD/mZTOmOc5U7zKzBPEedygWshcDyWvs30igAbU+6oyMgJBCFhwQE0fccxN60Ay9iebbjoDh06hMowjQxT4fXq1SskArmHZpkArvixp/kWzHdMeArExSJEaiXIjjRjRJ4DaAGWpibLzXN3Fm1vA5teBgh3j1Rv3bp1YgKwPdmf2p9zcyNYYgPKMfY0T5f5nNYdw158nJ8QawW4CLKwiOBSEgO/hok2eBydR+3dYH+PLxA5J8Vv0KBBwenTp0P2JWAx6+yFEBfs8lMY+y0SWMBNI9E4ThKi58VKTg3FQZS1RQF1cz27eC0QHMu+3E0SkUowjhVt5VdaWhp07949ZHv2Qd1EjDXM2cla1M0nl3GxAs3J9yREzyTdFVKVFOaE9qRA8GM0WebRuo9JGZKA7Mv2SeS/Z8+eoQ9BArMfFrLGo6jvxbhHbJZnKX2Rzz1O7QhJJ9Cs2ZMaWIyq/zhdeqPNfIoHd58clIQD+JSXl4dKlyIAuBdVXZwFVWKspSSoxE++h8x4k3uCnEhE4I5KwRiFWGOU0QWKiCYLbdoRMRKAu2kQ9vkfLU6dOhX06NEjlH+yMRZSinnuyWnYosVcji8CEA/6Cg2JF+IIUBqnGKUTCNwtwBN4f89RiK1R96DEgO2o0NDmtEdvVFdVVYV+P3UAPUEs6GFwV3PHmXkD4vh74iDFJysVI/MlaQhwKeBNTLYX5VuA8T4/gZxA4MRGFxDB6R7OmYPfyykGRJbyie+XnGYnQIC/coH9+vULiYrxrkL9ZA9+0ykaHIfEpM7ge8TiJ2CsHYwyMfafAF1yCGBHYIbCVDjDjKt7BeB51D+LgQa6OkG7IDYEEtvQ7lnXLKLtLdLuJBpE4gPUXcW2+PkZwOex+4cGDhwYDBkyRL7/HFcEwUGPo/8uWRUpYnfxGHco8HkewLHLyYmAawAPuIFZxhOpDfJQ8gbUv41yORAptMWBNr6oqMhWird5+u+iHmBb2nhjDV7HWBNQTgK8y11l5NetWzc5ULscAtSj7nbNI0skhWeUZCc0W4nyH/jO4Vz0u1IeYhbk4AiwM6tjxIWByHsoZ9qcIBPJd/y+DwPfBESOmCa/QF3WiZHucLlEDpNxcNhmheEOPgdQNx6/VZFQzFZ5TN08AHXQt2Ii3EdyFuUsPtTcGPhW5iMiCNELvz+Gdn9huG4HUJaW/w3g0wxV0XaG7arG2WeKiUWYM4Y7GO5ezshTARbbWGw/DvXkpp/ivVvE0JVoMxN4rpGzJMhE5Pl+xlATsDIqikP9F9D2z3h9nOksEUFhK+qO4rcPkoalMQ/HqJLIyb3F3JdjrCcw1yZ8joyJLR5gCo54etlag7qIoeNh1N1BRYj3DTFJ0elotxPlVzkGuYAmL0VSJVGAJA41c4Z6A3BzTLfn0HYwYKEI6CUAMzZEWvLsIcQOo1AmmyyM72nHJCfYsogflGV6jEk9vyQZXSuq6w4c16NsGcGZbwOPr+H1RkOk2LEzjNepxQkihHSCQ4ynAYNRx2zMKV92CQMWqj8J0BRE8EShxRFN6YrfCRhC0x3r/Zm4IbQCcmJoV0kMamllccR6FjHqUC5F2R/wS2dcymOlfAKOS4KmzQb5cpNC2MC7JhVn5wjXoJ44rYhLh8n0eXOCorJxa7POjbSlCGVczr34/RsAmrcvo9s+wGp3tzVhntxiXiJ4nvEYb4FJkf0O8HocAePmLvCxnL0AORraVekJk6TYjDabRVXfRE2lCN1h6ZQRN1+InUbsCpKwoBZHh0dODN9JBCUffItXxEavTQkUtnfTVAplCWL3JISz29h4NjotnuSsQKJCk8dF+kJR6RARjrqFVmfPnj3ZbK8cIJ0msd6jgHPGtfVTQ8VLmlvh4mct9sobRmPic0DyDQQnx/NlfYUgyz59+oScsH379pAwXABD32nTpoUHIToESeI5mnbE/UqDdyLcafEBf2MCqgC7NwxIbMREJQ0g4D4sfJwnD+AmRrII05cfMWJE+L1169bQr+fip06dGp4oJ83lmYd5wj/EmMa4TaHivo4EeCguYZBnkB5g2aWA69OIEnUHOaGysjIYMGBAMGnSpODYsWPZwCpFmm4lNq+4gSLQA7jcX8DwtjEyRC8wjabnXEx9kfWnTJkSJkAo90xpJVV+FmcVNeYAF5zWngS4C4O91MBxmAv8blLEpbjI5sz9MTdAhcgkCT1RO8mZkAjfiYpTEvStAS53Uw1vAiUGgZ3GpuQEYvoiBqlIan7kSDHnTwJQFNiPu0+5VxCVYhcZIjNrdXUDdp+Eq5AZ3Gkg8QAyVZRZIk4Tl4QAbF9cXJxNYZMAtAokgs4BrNxEpCtteXg7DDTMDKYNSuQdKsnJBek7HxewvxaosWxLYXtw+cJp18217wql4aKCfBNoEu0O5VU+PhctJ0YeXD4C6JQpyrlpSLTojpGGGN5YwNziChdIZLk4lvLcFJ9jMX3QdiImY9bmGQU+TRUL5CHITTRlgF8D9ouD1MfmLoEPl5xokIumZ2cfgMpHt47IW9N64Hsh7wQYYjyIugWuF5fCqYncXRd5vPMWyizzvhi/32+nvG0dZc9vR6fZOu0md5e+uC408FvKSIOZwXlGvxPv95izA2Vtvg1xKFWARI+vMX66HUhpQQb643uW1bSjuTWyw2SBvDrBvjFic1eGGlz5esq3ko9uSIlBRqPuFcCv8F4WIcN12nVaBd0SaYwI6PDDImR11JkqgHcPmQssjxIn6bUshygDFJUTxPMpHk+jfjPgupgdnYV2R/g7xSjtpah8RJBewhwf0gGK6XI92u4wXFEU40afJ4DN4h5LcAd+40HI3JgJecuT0c062W0i2hQJUTcxan3/CMW1PF2K6bbA+Daz4xRs1D3Br1Cm0OihKCqizW78/nXAF/G5TXrEcVzaNMH6CyMswqsAHqDyDLEyou8lwOXnKF8DjI6KjV3KzMBiXkDH8ij/H214J5A596ekrZ3F0zXlWeL7+P5eUrNo3/QwC15uxthuzidy7DzKRwEDaAViiDgKbTbz7CJnzo0bN7pIfIiid8SuPwn25o3QCmpnyjlZkyxPP8EomCJzrGb7GJMx7tNsq4MT2xMUYaiErZOluTzKsnz3gwCeCZyVRZJfYplNEokEjwrPtxlxjeYAk+F1F74VAzPxQRNYYdtpOUvWs8J1sGhBJMNsb7igN8plJs1eSmLIhLKE4rvaCX27gOhLpLOsIzJ7qn/i+wZzcvSOZ23/du8TZjwV8zHIXoP4R3ifBxiFz1dcVpa3aPntPE+c6TmIWE9EtcMmAcPdWAhYhAXxcLOQi9L1WhD1Sc8p1d2oL7XGiRKp8F4A2i8K/nfI+y/gsTDJ/YC/8+AD5Uh04KHiGl+cIFPnBDDrPMjwRGkLXyxO4VGbfQWnDH2v0bVWE3C9QOXlepbgjEfIJQI6XDG3z5ahD9cw2pS78ipB85wyScNTvsVzlzzhL8/jRrnmVjfFJK/m3m4nj9vbgQTguT8XZTjsm672R5uJKEaQmBI/c58gyus8ZDagLpEVSJBIyHp4jn++xqPV71OgQgJYEWOtZ/haxRtKmWOBu8xdBLftWltsY84zE6WIEy/eIOWL+BaayMx+KHtL7EAkqdNDLiEXmEMUHniedtJqg9HmZtfvt26vNi0BdG3Ft3g8ZOf7PAu59TxtzivLNIekyi+wD1i8CuUiD9FXAa8C+/xS3JPmZnomyc7H+fb4/Se0bk41Fel621r4cgVxbq91V4jVqwB7HTe2M7jgB+QWHavZkDRPmZcASoZEmBx6i75bGjPcMdL4/VKGFAGWZkGzPG0XAbdL9A81G5LOmUnC9hHKJeO7dcUMjblSl12867ElFTtaGl20xvvLGPdVz/8TVuU7y0x1PG7vtNg24oz9Uo/Z412++VFWI7Fcog9tu9Lm6gvRmIPv9x1xmQAu6RDkXtbOtlGEmpgD5Nvnyc0dcv0EE6cfdi1HmhMf9wDF3k3gtRvEedhxjpgfqPb9PU9iEJHnyOUA7bQUXh6kq/D7l2iTjWv7XOD530BDr8jIrus+srXjt4MzumJMHuTsBa63YKE1+RR5lBjEikCCnWKWiHdzOgKO+nRIBAF88za/IFmJ3eMZov4CYxGBabcpGL8EYx+SeMXJeRwHNsV/h+vdxeuhEpN3ZyNY78Gm2fknJxVGhyjixPiQvVkNzT1elD9Py/aTAL64Hb9vcYmC9zfdXdT/C1LeGbg4rnBaAihDFJH12W5ulfNCNe/xTsP3bp8ikzJs5BF+5PNfAQYAPaseTdsEcaYAAAAASUVORK5CYII='
+			}
+		},
+		computed: {
+			iconSnowWidth() {
+				return (Math.floor(this.iconSize / 24) || 1) * 2
+			},
+			contentdownText() {
+				return this.contentText.contentdown || t("uni-load-more.contentdown")
+			},
+			contentrefreshText() {
+				return this.contentText.contentrefresh || t("uni-load-more.contentrefresh")
+			},
+			contentnomoreText() {
+				return this.contentText.contentnomore || t("uni-load-more.contentnomore")
+			}
+		},
+		mounted() {
+			// #ifdef APP-PLUS
+			var pages = getCurrentPages();
+			var page = pages[pages.length - 1];
+			var currentWebview = page.$getAppWebview();
+			currentWebview.addEventListener('hide', () => {
+				this.webviewHide = true
+			})
+			currentWebview.addEventListener('show', () => {
+				this.webviewHide = false
+			})
+			// #endif
+		},
+		methods: {
+			onClick() {
+				this.$emit('clickLoadMore', {
+					detail: {
+						status: this.status,
+					}
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss" >
+	.uni-load-more {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		height: 40px;
+		align-items: center;
+		justify-content: center;
+	}
+
+	.uni-load-more__text {
+		font-size: 14px;
+		margin-left: 8px;
+	}
+
+	.uni-load-more__img {
+		width: 24px;
+		height: 24px;
+		// margin-right: 8px;
+	}
+
+	.uni-load-more__img--nvue {
+		color: #666666;
+	}
+
+	.uni-load-more__img--android,
+	.uni-load-more__img--ios {
+		width: 24px;
+		height: 24px;
+		transform: rotate(0deg);
+	}
+
+	/* #ifndef APP-NVUE */
+	.uni-load-more__img--android {
+		animation: loading-ios 1s 0s linear infinite;
+	}
+
+	@keyframes loading-android {
+		0% {
+			transform: rotate(0deg);
+		}
+
+		100% {
+			transform: rotate(360deg);
+		}
+	}
+
+	.uni-load-more__img--ios-H5 {
+		position: relative;
+		animation: loading-ios-H5 1s 0s step-end infinite;
+	}
+
+	.uni-load-more__img--ios-H5 image {
+		position: absolute;
+		width: 100%;
+		height: 100%;
+		left: 0;
+		top: 0;
+	}
+
+	@keyframes loading-ios-H5 {
+		0% {
+			transform: rotate(0deg);
+		}
+
+		8% {
+			transform: rotate(30deg);
+		}
+
+		16% {
+			transform: rotate(60deg);
+		}
+
+		24% {
+			transform: rotate(90deg);
+		}
+
+		32% {
+			transform: rotate(120deg);
+		}
+
+		40% {
+			transform: rotate(150deg);
+		}
+
+		48% {
+			transform: rotate(180deg);
+		}
+
+		56% {
+			transform: rotate(210deg);
+		}
+
+		64% {
+			transform: rotate(240deg);
+		}
+
+		73% {
+			transform: rotate(270deg);
+		}
+
+		82% {
+			transform: rotate(300deg);
+		}
+
+		91% {
+			transform: rotate(330deg);
+		}
+
+		100% {
+			transform: rotate(360deg);
+		}
+	}
+
+	/* #endif */
+
+	/* #ifdef H5 */
+	.uni-load-more__img--android-H5 {
+		animation: loading-android-H5-rotate 2s linear infinite;
+		transform-origin: center center;
+	}
+
+	.uni-load-more__img--android-H5 circle {
+		display: inline-block;
+		animation: loading-android-H5-dash 1.5s ease-in-out infinite;
+		stroke: currentColor;
+		stroke-linecap: round;
+	}
+
+	@keyframes loading-android-H5-rotate {
+		0% {
+			transform: rotate(0deg);
+		}
+
+		100% {
+			transform: rotate(360deg);
+		}
+	}
+
+	@keyframes loading-android-H5-dash {
+		0% {
+			stroke-dasharray: 1, 200;
+			stroke-dashoffset: 0;
+		}
+
+		50% {
+			stroke-dasharray: 90, 150;
+			stroke-dashoffset: -40;
+		}
+
+		100% {
+			stroke-dasharray: 90, 150;
+			stroke-dashoffset: -120;
+		}
+	}
+
+	/* #endif */
+
+	/* #ifndef APP-NVUE || H5 */
+	.uni-load-more__img--android-MP {
+		position: relative;
+		width: 24px;
+		height: 24px;
+		transform: rotate(0deg);
+		animation: loading-ios 1s 0s ease infinite;
+	}
+
+	.uni-load-more__img--android-MP .uni-load-more__img-icon {
+		position: absolute;
+		box-sizing: border-box;
+		width: 100%;
+		height: 100%;
+		border-radius: 50%;
+		border: solid 2px transparent;
+		border-top: solid 2px #777777;
+		transform-origin: center;
+	}
+
+	.uni-load-more__img--android-MP .uni-load-more__img-icon:nth-child(1) {
+		animation: loading-android-MP-1 1s 0s linear infinite;
+	}
+
+	.uni-load-more__img--android-MP .uni-load-more__img-icon:nth-child(2) {
+		animation: loading-android-MP-2 1s 0s linear infinite;
+	}
+
+	.uni-load-more__img--android-MP .uni-load-more__img-icon:nth-child(3) {
+		animation: loading-android-MP-3 1s 0s linear infinite;
+	}
+
+	@keyframes loading-android {
+		0% {
+			transform: rotate(0deg);
+		}
+
+		100% {
+			transform: rotate(360deg);
+		}
+	}
+
+	@keyframes loading-android-MP-1 {
+		0% {
+			transform: rotate(0deg);
+		}
+
+		50% {
+			transform: rotate(90deg);
+		}
+
+		100% {
+			transform: rotate(360deg);
+		}
+	}
+
+	@keyframes loading-android-MP-2 {
+		0% {
+			transform: rotate(0deg);
+		}
+
+		50% {
+			transform: rotate(180deg);
+		}
+
+		100% {
+			transform: rotate(360deg);
+		}
+	}
+
+	@keyframes loading-android-MP-3 {
+		0% {
+			transform: rotate(0deg);
+		}
+
+		50% {
+			transform: rotate(270deg);
+		}
+
+		100% {
+			transform: rotate(360deg);
+		}
+	}
+
+	/* #endif */
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-load-more/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-load-more/package.json
new file mode 100644
index 000000000..2fa6f040a
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-load-more/package.json
@@ -0,0 +1,86 @@
+{
+  "id": "uni-load-more",
+  "displayName": "uni-load-more 加载更多",
+  "version": "1.3.3",
+  "description": "LoadMore 组件,常用在列表里面,做滚动加载使用。",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "加载更多",
+    "load-more"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": ["uni-scss"],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-load-more/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-load-more/readme.md
new file mode 100644
index 000000000..54dc1fad2
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-load-more/readme.md
@@ -0,0 +1,14 @@
+
+
+### LoadMore 加载更多
+> **组件名:uni-load-more**
+> 代码块: `uLoadMore`
+
+
+用于列表中,做滚动加载使用,展示 loading 的各种状态。
+
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-load-more)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
+
+
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-nav-bar/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-nav-bar/changelog.md
new file mode 100644
index 000000000..f0f6b5661
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-nav-bar/changelog.md
@@ -0,0 +1,41 @@
+## 1.3.6(2022-06-30)
+- 修复 组件示例中插槽用法无法显示内容的bug
+## 1.3.5(2022-05-24)
+- 新增 stat 属性 ,可开启统计title 上报 ,仅使用了title 属性且项目开启了uni统计生效
+## 1.3.4(2022-01-24)
+- 更新 组件示例
+## 1.3.3(2022-01-24)
+- 新增 left-width/right-width属性 ,可修改左右两侧的宽度
+## 1.3.2(2022-01-18)
+- 修复 在vue下,标题不垂直居中的bug
+## 1.3.1(2022-01-18)
+- 修复 height 属性类型错误
+## 1.3.0(2022-01-18)
+- 新增 height 属性,可修改组件高度
+- 新增 dark 属性可可开启暗黑模式
+- 优化 标题字数过多显示省略号
+- 优化 插槽,插入内容可完全覆盖
+## 1.2.1(2022-01-10)
+- 修复 color 属性不生效的bug
+## 1.2.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-nav-bar](https://uniapp.dcloud.io/component/uniui/uni-nav-bar)
+## 1.1.0(2021-07-30)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.0.11(2021-05-12)
+- 新增 组件示例地址
+## 1.0.10(2021-04-30)
+- 修复 在nvue下fixed为true,宽度不能撑满的Bug
+## 1.0.9(2021-04-21)
+- 优化 添加依赖 uni-icons, 导入后自动下载依赖
+## 1.0.8(2021-04-14)
+- uni-ui 修复 uni-nav-bar 当 fixed 属性为 true 时铺不满屏幕的 bug
+
+## 1.0.7(2021-02-25)
+- 修复 easycom 下,找不到 uni-status-bar 的bug
+
+## 1.0.6(2021-02-05)
+- 优化 组件引用关系,通过uni_modules引用组件
+
+## 1.0.5(2021-02-05)
+- 调整为uni_modules目录规范
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-nav-bar.vue b/yudao-ui-admin-uniapp/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-nav-bar.vue
new file mode 100644
index 000000000..cbfc16859
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-nav-bar.vue
@@ -0,0 +1,348 @@
+<template>
+	<view class="uni-navbar" :class="{'uni-dark':dark}">
+		<view :class="{ 'uni-navbar--fixed': fixed, 'uni-navbar--shadow': shadow, 'uni-navbar--border': border }"
+			:style="{ 'background-color': themeBgColor }" class="uni-navbar__content">
+			<status-bar v-if="statusBar" />
+			<view :style="{ color: themeColor,backgroundColor: themeBgColor ,height:navbarHeight}"
+				class="uni-navbar__header">
+				<view @tap="onClickLeft" class="uni-navbar__header-btns uni-navbar__header-btns-left"
+					:style="{width:leftIconWidth}">
+					<slot name="left">
+						<view class="uni-navbar__content_view" v-if="leftIcon.length > 0">
+							<uni-icons :color="themeColor" :type="leftIcon" size="20" />
+						</view>
+						<view :class="{ 'uni-navbar-btn-icon-left': !leftIcon.length > 0 }" class="uni-navbar-btn-text"
+							v-if="leftText.length">
+							<text :style="{ color: themeColor, fontSize: '12px' }">{{ leftText }}</text>
+						</view>
+					</slot>
+				</view>
+				<view class="uni-navbar__header-container " @tap="onClickTitle">
+					<slot>
+						<view class="uni-navbar__header-container-inner" v-if="title.length>0">
+							<text class="uni-nav-bar-text uni-ellipsis-1"
+								:style="{color: themeColor }">{{ title }}</text>
+						</view>
+					</slot>
+				</view>
+				<view @click="onClickRight" class="uni-navbar__header-btns uni-navbar__header-btns-right"
+					:style="{width:rightIconWidth}">
+					<slot name="right">
+						<view v-if="rightIcon.length">
+							<uni-icons :color="themeColor" :type="rightIcon" size="22" />
+						</view>
+						<view class="uni-navbar-btn-text" v-if="rightText.length && !rightIcon.length">
+							<text class="uni-nav-bar-right-text" :style="{ color: themeColor}">{{ rightText }}</text>
+						</view>
+					</slot>
+				</view>
+			</view>
+		</view>
+		<view class="uni-navbar__placeholder" v-if="fixed">
+			<status-bar v-if="statusBar" />
+			<view class="uni-navbar__placeholder-view" :style="{ height:navbarHeight}" />
+		</view>
+	</view>
+</template>
+
+<script>
+	import statusBar from "./uni-status-bar.vue";
+	const getVal = (val) => typeof val === 'number' ? val + 'px' : val;
+
+	/**
+	 * NavBar 自定义导航栏
+	 * @description 导航栏组件,主要用于头部导航
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=52
+	 * @property {Boolean} dark 开启黑暗模式
+	 * @property {String} title 标题文字
+	 * @property {String} leftText 左侧按钮文本
+	 * @property {String} rightText 右侧按钮文本
+	 * @property {String} leftIcon 左侧按钮图标(图标类型参考 [Icon 图标](http://ext.dcloud.net.cn/plugin?id=28) type 属性)
+	 * @property {String} rightIcon 右侧按钮图标(图标类型参考 [Icon 图标](http://ext.dcloud.net.cn/plugin?id=28) type 属性)
+	 * @property {String} color 图标和文字颜色
+	 * @property {String} backgroundColor 导航栏背景颜色
+	 * @property {Boolean} fixed = [true|false] 是否固定顶部
+	 * @property {Boolean} statusBar = [true|false] 是否包含状态栏
+	 * @property {Boolean} shadow = [true|false] 导航栏下是否有阴影
+	 * @property {Boolean} stat 是否开启统计标题上报
+	 * @event {Function} clickLeft 左侧按钮点击时触发
+	 * @event {Function} clickRight 右侧按钮点击时触发
+	 * @event {Function} clickTitle 中间标题点击时触发
+	 */
+	export default {
+		name: "UniNavBar",
+		components: {
+			statusBar
+		},
+		emits: ['clickLeft', 'clickRight', 'clickTitle'],
+		props: {
+			dark: {
+				type: Boolean,
+				default: false
+			},
+			title: {
+				type: String,
+				default: ""
+			},
+			leftText: {
+				type: String,
+				default: ""
+			},
+			rightText: {
+				type: String,
+				default: ""
+			},
+			leftIcon: {
+				type: String,
+				default: ""
+			},
+			rightIcon: {
+				type: String,
+				default: ""
+			},
+			fixed: {
+				type: [Boolean, String],
+				default: false
+			},
+			color: {
+				type: String,
+				default: ""
+			},
+			backgroundColor: {
+				type: String,
+				default: ""
+			},
+			statusBar: {
+				type: [Boolean, String],
+				default: false
+			},
+			shadow: {
+				type: [Boolean, String],
+				default: false
+			},
+			border: {
+				type: [Boolean, String],
+				default: true
+			},
+			height: {
+				type: [Number, String],
+				default: 44
+			},
+			leftWidth: {
+				type: [Number, String],
+				default: 60
+			},
+			rightWidth: {
+				type: [Number, String],
+				default: 60
+			},
+			stat: {
+				type: [Boolean, String],
+				default: ''
+			}
+		},
+		computed: {
+			themeBgColor() {
+				if (this.dark) {
+					// 默认值
+					if (this.backgroundColor) {
+						return this.backgroundColor
+					} else {
+						return this.dark ? '#333' : '#FFF'
+					}
+				}
+				return this.backgroundColor || '#FFF'
+			},
+			themeColor() {
+				if (this.dark) {
+					// 默认值
+					if (this.color) {
+						return this.color
+					} else {
+						return this.dark ? '#fff' : '#333'
+					}
+				}
+				return this.color || '#333'
+			},
+			navbarHeight() {
+				return getVal(this.height)
+			},
+			leftIconWidth() {
+				return getVal(this.leftWidth)
+			},
+			rightIconWidth() {
+				return getVal(this.rightWidth)
+			}
+		},
+		mounted() {
+			if (uni.report && this.stat && this.title !== '') {
+				uni.report('title', this.title)
+			}
+		},
+		methods: {
+			onClickLeft() {
+				this.$emit("clickLeft");
+			},
+			onClickRight() {
+				this.$emit("clickRight");
+			},
+			onClickTitle() {
+				this.$emit("clickTitle");
+			}
+		}
+	};
+</script>
+
+<style lang="scss" scoped>
+	$nav-height: 44px;
+
+	.uni-navbar {
+		// box-sizing: border-box;
+	}
+
+	.uni-nav-bar-text {
+		/* #ifdef APP-PLUS */
+		font-size: 34rpx;
+		/* #endif */
+		/* #ifndef APP-PLUS */
+		font-size: 14px;
+		/* #endif */
+	}
+
+	.uni-nav-bar-right-text {
+		font-size: 12px;
+	}
+
+	.uni-navbar__content {
+		position: relative;
+		// background-color: #fff;
+		// box-sizing: border-box;
+		background-color: transparent;
+	}
+
+	.uni-navbar__content_view {
+		// box-sizing: border-box;
+	}
+
+	.uni-navbar-btn-text {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		justify-content: flex-start;
+		align-items: center;
+		line-height: 12px;
+	}
+
+	.uni-navbar__header {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		padding: 0 10px;
+		flex-direction: row;
+		height: $nav-height;
+		font-size: 12px;
+	}
+
+	.uni-navbar__header-btns {
+		/* #ifndef APP-NVUE */
+		overflow: hidden;
+		display: flex;
+		/* #endif */
+		flex-wrap: nowrap;
+		flex-direction: row;
+		width: 120rpx;
+		// padding: 0 6px;
+		justify-content: center;
+		align-items: center;
+		/* #ifdef H5 */
+		cursor: pointer;
+		/* #endif */
+	}
+
+	.uni-navbar__header-btns-left {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		width: 120rpx;
+		justify-content: flex-start;
+		align-items: center;
+	}
+
+	.uni-navbar__header-btns-right {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		// width: 150rpx;
+		// padding-right: 30rpx;
+		justify-content: flex-end;
+		align-items: center;
+	}
+
+	.uni-navbar__header-container {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex: 1;
+		padding: 0 10px;
+		overflow: hidden;
+	}
+
+	.uni-navbar__header-container-inner {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex: 1;
+		flex-direction: row;
+		align-items: center;
+		justify-content: center;
+		font-size: 12px;
+		overflow: hidden;
+		// box-sizing: border-box;
+	}
+
+
+	.uni-navbar__placeholder-view {
+		height: $nav-height;
+	}
+
+	.uni-navbar--fixed {
+		position: fixed;
+		z-index: 998;
+		/* #ifdef H5 */
+		left: var(--window-left);
+		right: var(--window-right);
+		/* #endif */
+		/* #ifndef H5 */
+		left: 0;
+		right: 0;
+		/* #endif */
+
+	}
+
+	.uni-navbar--shadow {
+		box-shadow: 0 1px 6px #ccc;
+	}
+
+	.uni-navbar--border {
+		border-bottom-width: 1rpx;
+		border-bottom-style: solid;
+		border-bottom-color: #eee;
+	}
+
+	.uni-ellipsis-1 {
+		overflow: hidden;
+		/* #ifndef APP-NVUE */
+		white-space: nowrap;
+		text-overflow: ellipsis;
+		/* #endif */
+		/* #ifdef APP-NVUE */
+		lines: 1;
+		text-overflow: ellipsis;
+		/* #endif */
+	}
+
+	// 暗主题配置
+	.uni-dark {}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-status-bar.vue b/yudao-ui-admin-uniapp/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-status-bar.vue
new file mode 100644
index 000000000..6a688744f
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-status-bar.vue
@@ -0,0 +1,27 @@
+<template>
+	<view :style="{ height: statusBarHeight }" class="uni-status-bar">
+		<slot />
+	</view>
+</template>
+
+<script>
+	export default {
+		name: 'UniStatusBar',
+		data() {
+			return {
+				statusBarHeight: 20
+			}
+		},
+		mounted() {
+			this.statusBarHeight = uni.getSystemInfoSync().statusBarHeight + 'px'
+		}
+	}
+</script>
+
+<style lang="scss" >
+	.uni-status-bar {
+		// width: 750rpx;
+		height: 20px;
+		// height: var(--status-bar-height);
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-nav-bar/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-nav-bar/package.json
new file mode 100644
index 000000000..e3fe073d4
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-nav-bar/package.json
@@ -0,0 +1,89 @@
+{
+  "id": "uni-nav-bar",
+  "displayName": "uni-nav-bar 自定义导航栏",
+  "version": "1.3.6",
+  "description": "自定义导航栏组件,主要用于头部导航。",
+  "keywords": [
+    "uni-ui",
+    "导航",
+    "导航栏",
+    "自定义导航栏"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": [
+			"uni-scss",
+			"uni-icons"
+		],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-nav-bar/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-nav-bar/readme.md
new file mode 100644
index 000000000..3934b3277
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-nav-bar/readme.md
@@ -0,0 +1,15 @@
+
+
+## NavBar 导航栏
+> **组件名:uni-nav-bar**
+> 代码块: `uNavBar`
+
+导航栏组件,主要用于头部导航。
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-nav-bar)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
+
+
+
+
+
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-notice-bar/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-notice-bar/changelog.md
new file mode 100644
index 000000000..9ee75a017
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-notice-bar/changelog.md
@@ -0,0 +1,16 @@
+## 1.2.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-notice-bar](https://uniapp.dcloud.io/component/uniui/uni-notice-bar)
+## 1.1.1(2021-11-09) 
+- 新增 提供组件设计资源,组件样式调整
+## 1.1.0(2021-07-30)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.0.9(2021-05-12)
+- 新增 组件示例地址
+## 1.0.8(2021-04-21)
+- 优化 添加依赖 uni-icons, 导入后自动下载依赖
+## 1.0.7(2021-02-05)
+- 优化 组件引用关系,通过uni_modules引用组件
+
+## 1.0.6(2021-02-05)
+- 调整为uni_modules目录规范
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-notice-bar/components/uni-notice-bar/uni-notice-bar.vue b/yudao-ui-admin-uniapp/uni_modules/uni-notice-bar/components/uni-notice-bar/uni-notice-bar.vue
new file mode 100644
index 000000000..1d2ac1dc1
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-notice-bar/components/uni-notice-bar/uni-notice-bar.vue
@@ -0,0 +1,395 @@
+<template>
+	<view v-if="show" class="uni-noticebar" :style="{ backgroundColor: backgroundColor }" @click="onClick">
+		<uni-icons v-if="showIcon === true || showIcon === 'true'" class="uni-noticebar-icon" type="sound"
+			:color="color" size="22" />
+		<view ref="textBox" class="uni-noticebar__content-wrapper"
+			:class="{'uni-noticebar__content-wrapper--scrollable':scrollable, 'uni-noticebar__content-wrapper--single':!scrollable && (single || moreText)}">
+			<view :id="elIdBox" class="uni-noticebar__content"
+				:class="{'uni-noticebar__content--scrollable':scrollable, 'uni-noticebar__content--single':!scrollable && (single || moreText)}">
+				<text :id="elId" ref="animationEle" class="uni-noticebar__content-text"
+					:class="{'uni-noticebar__content-text--scrollable':scrollable,'uni-noticebar__content-text--single':!scrollable && (single || showGetMore)}"
+					:style="{color:color, width:wrapWidth+'px', 'animationDuration': animationDuration, '-webkit-animationDuration': animationDuration ,animationPlayState: webviewHide?'paused':animationPlayState,'-webkit-animationPlayState':webviewHide?'paused':animationPlayState, animationDelay: animationDelay, '-webkit-animationDelay':animationDelay}">{{text}}</text>
+			</view>
+		</view>
+		<view v-if="showGetMore === true || showGetMore === 'true'" class="uni-noticebar__more uni-cursor-point"
+			@click="clickMore">
+			<text v-if="moreText.length > 0" :style="{ color: moreColor }" class="uni-noticebar__more-text">{{ moreText }}</text>
+			<uni-icons v-else type="right" :color="moreColor" size="16" />
+		</view>
+		<view class="uni-noticebar-close uni-cursor-point" v-if="(showClose === true || showClose === 'true') && (showGetMore === false || showGetMore === 'false')">
+			<uni-icons
+				type="closeempty" :color="color" size="16" @click="close" />
+		</view>
+	</view>
+</template>
+
+<script>
+	// #ifdef APP-NVUE
+	const dom = weex.requireModule('dom');
+	const animation = weex.requireModule('animation');
+	// #endif
+
+	/**
+	 * NoticeBar 自定义导航栏
+	 * @description 通告栏组件
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=30
+	 * @property {Number} speed 文字滚动的速度,默认100px/秒
+	 * @property {String} text 显示文字
+	 * @property {String} backgroundColor 背景颜色
+	 * @property {String} color 文字颜色
+	 * @property {String} moreColor 查看更多文字的颜色
+	 * @property {String} moreText 设置“查看更多”的文本
+	 * @property {Boolean} single = [true|false] 是否单行
+	 * @property {Boolean} scrollable = [true|false] 是否滚动,为true时,NoticeBar为单行
+	 * @property {Boolean} showIcon = [true|false] 是否显示左侧喇叭图标
+	 * @property {Boolean} showClose = [true|false] 是否显示左侧关闭按钮
+	 * @property {Boolean} showGetMore = [true|false] 是否显示右侧查看更多图标,为true时,NoticeBar为单行
+	 * @event {Function} click 点击 NoticeBar 触发事件
+	 * @event {Function} close 关闭 NoticeBar 触发事件
+	 * @event {Function} getmore 点击”查看更多“时触发事件
+	 */
+
+	export default {
+		name: 'UniNoticeBar',
+		emits: ['click', 'getmore', 'close'],
+		props: {
+			text: {
+				type: String,
+				default: ''
+			},
+			moreText: {
+				type: String,
+				default: ''
+			},
+			backgroundColor: {
+				type: String,
+				default: '#FFF9EA'
+			},
+			speed: {
+				// 默认1s滚动100px
+				type: Number,
+				default: 100
+			},
+			color: {
+				type: String,
+				default: '#FF9A43'
+			},
+			moreColor: {
+				type: String,
+				default: '#FF9A43'
+			},
+			single: {
+				// 是否单行
+				type: [Boolean, String],
+				default: false
+			},
+			scrollable: {
+				// 是否滚动,添加后控制单行效果取消
+				type: [Boolean, String],
+				default: false
+			},
+			showIcon: {
+				// 是否显示左侧icon
+				type: [Boolean, String],
+				default: false
+			},
+			showGetMore: {
+				// 是否显示右侧查看更多
+				type: [Boolean, String],
+				default: false
+			},
+			showClose: {
+				// 是否显示左侧关闭按钮
+				type: [Boolean, String],
+				default: false
+			}
+		},
+		data() {
+			const elId = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`
+			const elIdBox = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`
+			return {
+				textWidth: 0,
+				boxWidth: 0,
+				wrapWidth: '',
+				webviewHide: false,
+				// #ifdef APP-NVUE
+				stopAnimation: false,
+				// #endif
+				elId: elId,
+				elIdBox: elIdBox,
+				show: true,
+				animationDuration: 'none',
+				animationPlayState: 'paused',
+				animationDelay: '0s'
+			}
+		},
+		mounted() {
+			// #ifdef APP-PLUS
+			var pages = getCurrentPages();
+			var page = pages[pages.length - 1];
+			var currentWebview = page.$getAppWebview();
+			currentWebview.addEventListener('hide', () => {
+				this.webviewHide = true
+			})
+			currentWebview.addEventListener('show', () => {
+				this.webviewHide = false
+			})
+			// #endif
+			this.$nextTick(() => {
+				this.initSize()
+			})
+		},
+		// #ifdef APP-NVUE
+		beforeDestroy() {
+			this.stopAnimation = true
+		},
+		// #endif
+		methods: {
+			initSize() {
+				if (this.scrollable) {
+					// #ifndef APP-NVUE
+					let query = [],
+						boxWidth = 0,
+						textWidth = 0;
+					let textQuery = new Promise((resolve, reject) => {
+						uni.createSelectorQuery()
+							// #ifndef MP-ALIPAY
+							.in(this)
+							// #endif
+							.select(`#${this.elId}`)
+							.boundingClientRect()
+							.exec(ret => {
+								this.textWidth = ret[0].width
+								resolve()
+							})
+					})
+					let boxQuery = new Promise((resolve, reject) => {
+						uni.createSelectorQuery()
+							// #ifndef MP-ALIPAY
+							.in(this)
+							// #endif
+							.select(`#${this.elIdBox}`)
+							.boundingClientRect()
+							.exec(ret => {
+								this.boxWidth = ret[0].width
+								resolve()
+							})
+					})
+					query.push(textQuery)
+					query.push(boxQuery)
+					Promise.all(query).then(() => {
+						this.animationDuration = `${this.textWidth / this.speed}s`
+						this.animationDelay = `-${this.boxWidth / this.speed}s`
+						setTimeout(() => {
+							this.animationPlayState = 'running'
+						}, 1000)
+					})
+					// #endif
+					// #ifdef APP-NVUE
+					dom.getComponentRect(this.$refs['animationEle'], (res) => {
+						let winWidth = uni.getSystemInfoSync().windowWidth
+						this.textWidth = res.size.width
+						animation.transition(this.$refs['animationEle'], {
+							styles: {
+								transform: `translateX(-${winWidth}px)`
+							},
+							duration: 0,
+							timingFunction: 'linear',
+							delay: 0
+						}, () => {
+							if (!this.stopAnimation) {
+								animation.transition(this.$refs['animationEle'], {
+									styles: {
+										transform: `translateX(-${this.textWidth}px)`
+									},
+									timingFunction: 'linear',
+									duration: (this.textWidth - winWidth) / this.speed * 1000,
+									delay: 1000
+								}, () => {
+									if (!this.stopAnimation) {
+										this.loopAnimation()
+									}
+								});
+							}
+						});
+					})
+					// #endif
+				}
+				// #ifdef APP-NVUE
+				if (!this.scrollable && (this.single || this.moreText)) {
+					dom.getComponentRect(this.$refs['textBox'], (res) => {
+						this.wrapWidth = res.size.width
+					})
+				}
+				// #endif
+			},
+			loopAnimation() {
+				// #ifdef APP-NVUE
+				animation.transition(this.$refs['animationEle'], {
+					styles: {
+						transform: `translateX(0px)`
+					},
+					duration: 0
+				}, () => {
+					if (!this.stopAnimation) {
+						animation.transition(this.$refs['animationEle'], {
+							styles: {
+								transform: `translateX(-${this.textWidth}px)`
+							},
+							duration: this.textWidth / this.speed * 1000,
+							timingFunction: 'linear',
+							delay: 0
+						}, () => {
+							if (!this.stopAnimation) {
+								this.loopAnimation()
+							}
+						});
+					}
+				});
+				// #endif
+			},
+			clickMore() {
+				this.$emit('getmore')
+			},
+			close() {
+				this.show = false;
+				this.$emit('close')
+			},
+			onClick() {
+				this.$emit('click')
+			}
+		}
+	}
+</script>
+
+<style lang="scss" >
+	.uni-noticebar {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		width: 100%;
+		box-sizing: border-box;
+		/* #endif */
+		flex-direction: row;
+		align-items: center;
+		padding: 10px 12px;
+		margin-bottom: 10px;
+	}
+
+	.uni-cursor-point {
+		/* #ifdef H5 */
+		cursor: pointer;
+		/* #endif */
+	}
+
+	.uni-noticebar-close {
+		margin-left: 8px;
+		margin-right: 5px;
+	}
+
+	.uni-noticebar-icon {
+		margin-right: 5px;
+	}
+
+	.uni-noticebar__content-wrapper {
+		flex: 1;
+		flex-direction: column;
+		overflow: hidden;
+	}
+
+	.uni-noticebar__content-wrapper--single {
+		/* #ifndef APP-NVUE */
+		line-height: 18px;
+		/* #endif */
+	}
+
+	.uni-noticebar__content-wrapper--single,
+	.uni-noticebar__content-wrapper--scrollable {
+		flex-direction: row;
+	}
+
+	/* #ifndef APP-NVUE */
+	.uni-noticebar__content-wrapper--scrollable {
+		position: relative;
+		height: 18px;
+	}
+
+	/* #endif */
+
+	.uni-noticebar__content--scrollable {
+		/* #ifdef APP-NVUE */
+		flex: 0;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		flex: 1;
+		display: block;
+		overflow: hidden;
+		/* #endif */
+	}
+
+	.uni-noticebar__content--single {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		flex: none;
+		width: 100%;
+		justify-content: center;
+		/* #endif */
+	}
+
+	.uni-noticebar__content-text {
+		font-size: 14px;
+		line-height: 18px;
+		/* #ifndef APP-NVUE */
+		word-break: break-all;
+		/* #endif */
+	}
+
+	.uni-noticebar__content-text--single {
+		/* #ifdef APP-NVUE */
+		lines: 1;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		display: block;
+		width: 100%;
+		white-space: nowrap;
+		/* #endif */
+		overflow: hidden;
+		text-overflow: ellipsis;
+	}
+
+	.uni-noticebar__content-text--scrollable {
+		/* #ifdef APP-NVUE */
+		lines: 1;
+		padding-left: 750rpx;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		position: absolute;
+		display: block;
+		height: 18px;
+		line-height: 18px;
+		white-space: nowrap;
+		padding-left: 100%;
+		animation: notice 10s 0s linear infinite both;
+		animation-play-state: paused;
+		/* #endif */
+	}
+
+	.uni-noticebar__more {
+		/* #ifndef APP-NVUE */
+		display: inline-flex;
+		/* #endif */
+		flex-direction: row;
+		flex-wrap: nowrap;
+		align-items: center;
+		padding-left: 5px;
+	}
+
+	.uni-noticebar__more-text {
+		font-size: 14px;
+	}
+
+	@keyframes notice {
+		100% {
+			transform: translate3d(-100%, 0, 0);
+		}
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-notice-bar/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-notice-bar/package.json
new file mode 100644
index 000000000..97719a0ff
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-notice-bar/package.json
@@ -0,0 +1,90 @@
+{
+  "id": "uni-notice-bar",
+  "displayName": "uni-notice-bar 通告栏",
+  "version": "1.2.0",
+  "description": "NoticeBar 通告栏组件,常用于展示公告信息,可设为滚动公告",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "通告栏",
+    "公告",
+    "跑马灯"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": [
+			"uni-scss",
+			"uni-icons"
+		],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-notice-bar/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-notice-bar/readme.md
new file mode 100644
index 000000000..fb2ede244
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-notice-bar/readme.md
@@ -0,0 +1,13 @@
+
+
+## NoticeBar 通告栏
+> **组件名:uni-notice-bar**
+> 代码块: `uNoticeBar`
+
+
+通告栏组件 。
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-notice-bar)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
+
+
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-number-box/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-number-box/changelog.md
new file mode 100644
index 000000000..5925c32a2
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-number-box/changelog.md
@@ -0,0 +1,25 @@
+## 1.2.1(2021-11-22)
+- 修复 vue3中某些scss变量无法找到的问题
+## 1.2.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-number-box](https://uniapp.dcloud.io/component/uniui/uni-number-box)
+## 1.1.2(2021-11-09) 
+- 新增 提供组件设计资源,组件样式调整
+## 1.1.1(2021-07-30)
+- 优化 vue3下事件警告的问题
+## 1.1.0(2021-07-13)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.0.7(2021-05-12)
+- 新增 组件示例地址
+## 1.0.6(2021-04-20)
+- 修复 uni-number-box 浮点数运算不精确的 bug
+- 修复 uni-number-box change 事件触发不正确的 bug
+- 新增 uni-number-box v-model 双向绑定
+## 1.0.5(2021-02-05)
+- 调整为uni_modules目录规范
+
+## 1.0.7(2021-02-05)
+- 调整为uni_modules目录规范
+- 新增 支持 v-model
+- 新增 支持 focus、blur 事件
+- 新增 支持 PC 端
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-number-box/components/uni-number-box/uni-number-box.vue b/yudao-ui-admin-uniapp/uni_modules/uni-number-box/components/uni-number-box/uni-number-box.vue
new file mode 100644
index 000000000..e91c03212
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-number-box/components/uni-number-box/uni-number-box.vue
@@ -0,0 +1,221 @@
+<template>
+	<view class="uni-numbox">
+		<view @click="_calcValue('minus')" class="uni-numbox__minus uni-numbox-btns" :style="{background}">
+			<text class="uni-numbox--text" :class="{ 'uni-numbox--disabled': inputValue <= min || disabled }" :style="{color}">-</text>
+		</view>
+		<input :disabled="disabled" @focus="_onFocus" @blur="_onBlur" class="uni-numbox__value" type="number"
+			v-model="inputValue" :style="{background, color}" />
+		<view @click="_calcValue('plus')" class="uni-numbox__plus uni-numbox-btns" :style="{background}">
+			<text class="uni-numbox--text" :class="{ 'uni-numbox--disabled': inputValue >= max || disabled }" :style="{color}">+</text>
+		</view>
+	</view>
+</template>
+<script>
+	/**
+	 * NumberBox 数字输入框
+	 * @description 带加减按钮的数字输入框
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=31
+	 * @property {Number} value 输入框当前值
+	 * @property {Number} min 最小值
+	 * @property {Number} max 最大值
+	 * @property {Number} step 每次点击改变的间隔大小
+	 * @property {String} background 背景色
+	 * @property {String} color 字体颜色(前景色)
+	 * @property {Boolean} disabled = [true|false] 是否为禁用状态
+	 * @event {Function} change 输入框值改变时触发的事件,参数为输入框当前的 value
+	 * @event {Function} focus 输入框聚焦时触发的事件,参数为 event 对象
+	 * @event {Function} blur 输入框失焦时触发的事件,参数为 event 对象
+	 */
+
+	export default {
+		name: "UniNumberBox",
+		emits: ['change', 'input', 'update:modelValue', 'blur', 'focus'],
+		props: {
+			value: {
+				type: [Number, String],
+				default: 1
+			},
+			modelValue: {
+				type: [Number, String],
+				default: 1
+			},
+			min: {
+				type: Number,
+				default: 0
+			},
+			max: {
+				type: Number,
+				default: 100
+			},
+			step: {
+				type: Number,
+				default: 1
+			},
+			background: {
+				type: String,
+				default: '#f5f5f5'
+			},
+			color: {
+				type: String,
+				default: '#333'
+			},
+			disabled: {
+				type: Boolean,
+				default: false
+			}
+		},
+		data() {
+			return {
+				inputValue: 0
+			};
+		},
+		watch: {
+			value(val) {
+				this.inputValue = +val;
+			},
+			modelValue(val) {
+				this.inputValue = +val;
+			}
+		},
+		created() {
+			if (this.value === 1) {
+				this.inputValue = +this.modelValue;
+			}
+			if (this.modelValue === 1) {
+				this.inputValue = +this.value;
+			}
+		},
+		methods: {
+			_calcValue(type) {
+				if (this.disabled) {
+					return;
+				}
+				const scale = this._getDecimalScale();
+				let value = this.inputValue * scale;
+				let step = this.step * scale;
+				if (type === "minus") {
+					value -= step;
+					if (value < (this.min * scale)) {
+						return;
+					}
+					if (value > (this.max * scale)) {
+						value = this.max * scale
+					}
+				}
+
+				if (type === "plus") {
+					value += step;
+					if (value > (this.max * scale)) {
+						return;
+					}
+					if (value < (this.min * scale)) {
+						value = this.min * scale
+					}
+				}
+
+				this.inputValue = (value / scale).toFixed(String(scale).length - 1);
+				this.$emit("change", +this.inputValue);
+				// TODO vue2 兼容
+				this.$emit("input", +this.inputValue);
+				// TODO vue3 兼容
+				this.$emit("update:modelValue", +this.inputValue);
+			},
+			_getDecimalScale() {
+
+				let scale = 1;
+				// 浮点型
+				if (~~this.step !== this.step) {
+					scale = Math.pow(10, String(this.step).split(".")[1].length);
+				}
+				return scale;
+			},
+			_onBlur(event) {
+				this.$emit('blur', event)
+				let value = event.detail.value;
+				if (isNaN(value)) {
+					this.inputValue = this.min;
+					return;
+				}
+				value = +value;
+				if (value > this.max) {
+					value = this.max;
+				} else if (value < this.min) {
+					value = this.min;
+				}
+				const scale = this._getDecimalScale();
+				this.inputValue = value.toFixed(String(scale).length - 1);
+				this.$emit("change", +this.inputValue);
+				this.$emit("input", +this.inputValue);
+				this.$emit("update:modelValue", +this.inputValue);
+			},
+			_onFocus(event) {
+				this.$emit('focus', event)
+			}
+		}
+	};
+</script>
+<style lang="scss" >
+	$box-height: 26px;
+	$bg: #f5f5f5;
+	$br: 2px;
+	$color: #333;
+
+	.uni-numbox {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+	}
+
+	.uni-numbox-btns {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		align-items: center;
+		justify-content: center;
+		padding: 0 8px;
+		background-color: $bg;
+		/* #ifdef H5 */
+		cursor: pointer;
+		/* #endif */
+	}
+
+	.uni-numbox__value {
+		margin: 0 2px;
+		background-color: $bg;
+		width: 40px;
+		height: $box-height;
+		text-align: center;
+		font-size: 14px;
+		border-left-width: 0;
+		border-right-width: 0;
+		color: $color;
+	}
+
+	.uni-numbox__minus {
+		border-top-left-radius: $br;
+		border-bottom-left-radius: $br;
+	}
+
+	.uni-numbox__plus {
+		border-top-right-radius: $br;
+		border-bottom-right-radius: $br;
+	}
+
+	.uni-numbox--text {
+		// fix nvue
+		line-height: 20px;
+
+		font-size: 20px;
+		font-weight: 300;
+		color: $color;
+	}
+
+	.uni-numbox .uni-numbox--disabled {
+		color: #c0c0c0 !important;
+		/* #ifdef H5 */
+		cursor: not-allowed;
+		/* #endif */
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-number-box/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-number-box/package.json
new file mode 100644
index 000000000..ad8233685
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-number-box/package.json
@@ -0,0 +1,85 @@
+{
+  "id": "uni-number-box",
+  "displayName": "uni-number-box 数字输入框",
+  "version": "1.2.1",
+  "description": "NumberBox 带加减按钮的数字输入框组件,用户可以控制每次点击增加的数值,支持小数。",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "数字输入框"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": ["uni-scss"],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-number-box/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-number-box/readme.md
new file mode 100644
index 000000000..affc56fa7
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-number-box/readme.md
@@ -0,0 +1,13 @@
+
+
+## NumberBox 数字输入框
+> **组件名:uni-number-box**
+> 代码块: `uNumberBox`
+
+
+带加减按钮的数字输入框。
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-number-box)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
+
+
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-pagination/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-pagination/changelog.md
new file mode 100644
index 000000000..336c2ba6d
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-pagination/changelog.md
@@ -0,0 +1,20 @@
+## 1.2.1(2021-11-22)
+- 修复 vue3中某些scss变量无法找到的问题
+## 1.2.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-pagination](https://uniapp.dcloud.io/component/uniui/uni-pagination)
+## 1.1.2(2021-10-08)
+- 修复 current 、value 属性未监听,导致高亮样式失效的 bug
+## 1.1.1(2021-08-20)
+- 新增 支持国际化
+## 1.1.0(2021-07-30)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.0.7(2021-05-12)
+- 新增 组件示例地址
+## 1.0.6(2021-04-12)
+- 新增 PC 和 移动端适配不同的 ui 
+## 1.0.5(2021-02-05)
+- 优化 组件引用关系,通过uni_modules引用组件
+
+## 1.0.4(2021-02-05)
+- 调整为uni_modules目录规范
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-pagination/components/uni-pagination/i18n/en.json b/yudao-ui-admin-uniapp/uni_modules/uni-pagination/components/uni-pagination/i18n/en.json
new file mode 100644
index 000000000..a57becdcd
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-pagination/components/uni-pagination/i18n/en.json
@@ -0,0 +1,4 @@
+{
+	"uni-pagination.prevText": "prev",
+	"uni-pagination.nextText": "next"
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-pagination/components/uni-pagination/i18n/es.json b/yudao-ui-admin-uniapp/uni_modules/uni-pagination/components/uni-pagination/i18n/es.json
new file mode 100644
index 000000000..ccbba2f63
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-pagination/components/uni-pagination/i18n/es.json
@@ -0,0 +1,4 @@
+{
+	"uni-pagination.prevText": "anterior",
+	"uni-pagination.nextText": "próxima"
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-pagination/components/uni-pagination/i18n/fr.json b/yudao-ui-admin-uniapp/uni_modules/uni-pagination/components/uni-pagination/i18n/fr.json
new file mode 100644
index 000000000..9b5f2d92d
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-pagination/components/uni-pagination/i18n/fr.json
@@ -0,0 +1,4 @@
+{
+	"uni-pagination.prevText": "précédente",
+	"uni-pagination.nextText": "suivante"
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-pagination/components/uni-pagination/i18n/index.js b/yudao-ui-admin-uniapp/uni_modules/uni-pagination/components/uni-pagination/i18n/index.js
new file mode 100644
index 000000000..2469dd02b
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-pagination/components/uni-pagination/i18n/index.js
@@ -0,0 +1,12 @@
+import en from './en.json'
+import es from './es.json'
+import fr from './fr.json'
+import zhHans from './zh-Hans.json'
+import zhHant from './zh-Hant.json'
+export default {
+	en,
+	es,
+	fr,
+	'zh-Hans': zhHans,
+	'zh-Hant': zhHant
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-pagination/components/uni-pagination/i18n/zh-Hans.json b/yudao-ui-admin-uniapp/uni_modules/uni-pagination/components/uni-pagination/i18n/zh-Hans.json
new file mode 100644
index 000000000..fedbe82a9
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-pagination/components/uni-pagination/i18n/zh-Hans.json
@@ -0,0 +1,4 @@
+{
+	"uni-pagination.prevText": "上一页",
+	"uni-pagination.nextText": "下一页"
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-pagination/components/uni-pagination/i18n/zh-Hant.json b/yudao-ui-admin-uniapp/uni_modules/uni-pagination/components/uni-pagination/i18n/zh-Hant.json
new file mode 100644
index 000000000..133b3404b
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-pagination/components/uni-pagination/i18n/zh-Hant.json
@@ -0,0 +1,4 @@
+{
+	"uni-pagination.prevText": "上一頁",
+	"uni-pagination.nextText": "下一頁"
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-pagination/components/uni-pagination/uni-pagination.vue b/yudao-ui-admin-uniapp/uni_modules/uni-pagination/components/uni-pagination/uni-pagination.vue
new file mode 100644
index 000000000..79db4b880
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-pagination/components/uni-pagination/uni-pagination.vue
@@ -0,0 +1,409 @@
+<template>
+	<view class="uni-pagination">
+		<!-- #ifndef APP-NVUE -->
+		<view class="uni-pagination__total is-phone-hide">共 {{ total }} 条</view>
+		<!-- #endif -->
+		<view class="uni-pagination__btn"
+			:class="currentIndex === 1 ? 'uni-pagination--disabled' : 'uni-pagination--enabled'"
+			:hover-class="currentIndex === 1 ? '' : 'uni-pagination--hover'" :hover-start-time="20"
+			:hover-stay-time="70" @click="clickLeft">
+			<template v-if="showIcon === true || showIcon === 'true'">
+				<uni-icons color="#666" size="16" type="left" />
+			</template>
+			<template v-else>
+				<text class="uni-pagination__child-btn">{{ prevPageText }}</text>
+			</template>
+		</view>
+		<view class="uni-pagination__num uni-pagination__num-flex-none">
+			<view class="uni-pagination__num-current">
+				<text class="uni-pagination__num-current-text is-pc-hide"
+					style="color:#409EFF">{{ currentIndex }}</text>
+				<text class="uni-pagination__num-current-text is-pc-hide">/{{ maxPage || 0 }}</text>
+				<!-- #ifndef APP-NVUE -->
+				<view v-for="(item, index) in paper" :key="index" :class="{ 'page--active': item === currentIndex }"
+					class="uni-pagination__num-tag tag--active is-phone-hide" @click.top="selectPage(item, index)">
+					<text>{{ item }}</text>
+				</view>
+				<!-- #endif -->
+
+			</view>
+		</view>
+		<view class="uni-pagination__btn"
+			:class="currentIndex >= maxPage ? 'uni-pagination--disabled' : 'uni-pagination--enabled'"
+			:hover-class="currentIndex === maxPage ? '' : 'uni-pagination--hover'" :hover-start-time="20"
+			:hover-stay-time="70" @click="clickRight">
+			<template v-if="showIcon === true || showIcon === 'true'">
+				<uni-icons color="#666" size="16" type="right" />
+			</template>
+			<template v-else>
+				<text class="uni-pagination__child-btn">{{ nextPageText }}</text>
+			</template>
+		</view>
+	</view>
+</template>
+
+<script>
+	/**
+	 * Pagination 分页器
+	 * @description 分页器组件,用于展示页码、请求数据等
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=32
+	 * @property {String} prevText 左侧按钮文字
+	 * @property {String} nextText 右侧按钮文字
+	 * @property {Number} current 当前页
+	 * @property {Number} total 数据总量
+	 * @property {Number} pageSize 每页数据量
+	 * @property {Number} showIcon = [true|false] 是否以 icon 形式展示按钮
+	 * @event {Function} change 点击页码按钮时触发 ,e={type,current} current为当前页,type值为:next/prev,表示点击的是上一页还是下一个
+	 */
+
+	import {
+		initVueI18n
+	} from '@dcloudio/uni-i18n'
+	import messages from './i18n/index.js'
+	const {
+		t
+	} = initVueI18n(messages)
+	export default {
+		name: 'UniPagination',
+		emits: ['update:modelValue', 'input', 'change'],
+		props: {
+			value: {
+				type: [Number, String],
+				default: 1
+			},
+			modelValue: {
+				type: [Number, String],
+				default: 1
+			},
+			prevText: {
+				type: String,
+			},
+			nextText: {
+				type: String,
+			},
+			current: {
+				type: [Number, String],
+				default: 1
+			},
+			total: {
+				// 数据总量
+				type: [Number, String],
+				default: 0
+			},
+			pageSize: {
+				// 每页数据量
+				type: [Number, String],
+				default: 10
+			},
+			showIcon: {
+				// 是否以 icon 形式展示按钮
+				type: [Boolean, String],
+				default: false
+			},
+			pagerCount: {
+				type: Number,
+				default: 7
+			}
+		},
+		data() {
+			return {
+				currentIndex: 1,
+				paperData: []
+			}
+		},
+		computed: {
+			prevPageText() {
+				return this.prevText || t('uni-pagination.prevText')
+			},
+			nextPageText() {
+				return this.nextText || t('uni-pagination.nextText')
+			},
+			maxPage() {
+				let maxPage = 1
+				let total = Number(this.total)
+				let pageSize = Number(this.pageSize)
+				if (total && pageSize) {
+					maxPage = Math.ceil(total / pageSize)
+				}
+				return maxPage
+			},
+			paper() {
+				const num = this.currentIndex
+				// TODO 最大页数
+				const pagerCount = this.pagerCount
+				// const total = 181
+				const total = this.total
+				const pageSize = this.pageSize
+				let totalArr = []
+				let showPagerArr = []
+				let pagerNum = Math.ceil(total / pageSize)
+				for (let i = 0; i < pagerNum; i++) {
+					totalArr.push(i + 1)
+				}
+				showPagerArr.push(1)
+				const totalNum = totalArr[totalArr.length - (pagerCount + 1) / 2]
+				totalArr.forEach((item, index) => {
+					if ((pagerCount + 1) / 2 >= num) {
+						if (item < pagerCount + 1 && item > 1) {
+							showPagerArr.push(item)
+						}
+					} else if (num + 2 <= totalNum) {
+						if (item > num - (pagerCount + 1) / 2 && item < num + (pagerCount + 1) / 2) {
+							showPagerArr.push(item)
+						}
+					} else {
+						if ((item > num - (pagerCount + 1) / 2 || pagerNum - pagerCount < item) && item < totalArr[
+								totalArr.length - 1]) {
+							showPagerArr.push(item)
+						}
+					}
+				})
+				if (pagerNum > pagerCount) {
+					if ((pagerCount + 1) / 2 >= num) {
+						showPagerArr[showPagerArr.length - 1] = '...'
+					} else if (num + 2 <= totalNum) {
+						showPagerArr[1] = '...'
+						showPagerArr[showPagerArr.length - 1] = '...'
+					} else {
+						showPagerArr[1] = '...'
+					}
+					showPagerArr.push(totalArr[totalArr.length - 1])
+				} else {
+					if ((pagerCount + 1) / 2 >= num) {} else if (num + 2 <= totalNum) {} else {
+						showPagerArr.shift()
+						showPagerArr.push(totalArr[totalArr.length - 1])
+					}
+				}
+
+				return showPagerArr
+			}
+		},
+		watch: {
+			current: {
+				immediate: true,
+				handler(val, old) {
+					if (val < 1) {
+						this.currentIndex = 1
+					} else {
+						this.currentIndex = val
+					}
+				}
+			},
+			value: {
+				immediate: true,
+				handler(val) {
+					if (Number(this.current) !== 1) return
+					if (val < 1) {
+						this.currentIndex = 1
+					} else {
+						this.currentIndex = val
+					}
+				}
+			}
+		},
+		methods: {
+			// 选择标签
+			selectPage(e, index) {
+				if (parseInt(e)) {
+					this.currentIndex = e
+					this.change('current')
+				} else {
+					let pagerNum = Math.ceil(this.total / this.pageSize)
+					// let pagerNum = Math.ceil(181 / this.pageSize)
+					// 上一页
+					if (index <= 1) {
+						if (this.currentIndex - 5 > 1) {
+							this.currentIndex -= 5
+						} else {
+							this.currentIndex = 1
+						}
+						return
+					}
+					// 下一页
+					if (index >= 6) {
+						if (this.currentIndex + 5 > pagerNum) {
+							this.currentIndex = pagerNum
+						} else {
+							this.currentIndex += 5
+						}
+						return
+					}
+				}
+			},
+			clickLeft() {
+				if (Number(this.currentIndex) === 1) {
+					return
+				}
+				this.currentIndex -= 1
+				this.change('prev')
+			},
+			clickRight() {
+				if (Number(this.currentIndex) >= this.maxPage) {
+					return
+				}
+				this.currentIndex += 1
+				this.change('next')
+			},
+			change(e) {
+				this.$emit('input', this.currentIndex)
+				this.$emit('update:modelValue', this.currentIndex)
+				this.$emit('change', {
+					type: e,
+					current: this.currentIndex
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss" >
+	$uni-primary: #2979ff;
+	.uni-pagination {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		position: relative;
+		overflow: hidden;
+		flex-direction: row;
+		justify-content: center;
+		align-items: center;
+	}
+
+	.uni-pagination__total {
+		font-size: 14px;
+		color: #999;
+		margin-right: 15px;
+	}
+
+	.uni-pagination__btn {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		cursor: pointer;
+		/* #endif */
+		padding: 0 8px;
+		line-height: 30px;
+		font-size: 12px;
+		position: relative;
+		background-color: #F0F0F0;
+		flex-direction: row;
+		justify-content: center;
+		align-items: center;
+		text-align: center;
+		border-radius: 5px;
+		// border-width: 1px;
+		// border-style: solid;
+		// border-color: $uni-border-color;
+	}
+
+	.uni-pagination__child-btn {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		font-size: 12px;
+		position: relative;
+		flex-direction: row;
+		justify-content: center;
+		align-items: center;
+		text-align: center;
+		color: #666;
+		font-size: 12px;
+	}
+
+	.uni-pagination__num {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex: 1;
+		flex-direction: row;
+		justify-content: center;
+		align-items: center;
+		height: 30px;
+		line-height: 30px;
+		font-size: 12px;
+		color: #666;
+		margin: 0 5px;
+	}
+
+	.uni-pagination__num-tag {
+		/* #ifdef H5 */
+		cursor: pointer;
+		min-width: 30px;
+		/* #endif */
+		margin: 0 5px;
+		height: 30px;
+		text-align: center;
+		line-height: 30px;
+		// border: 1px red solid;
+		color: #999;
+		border-radius: 4px;
+		// border-width: 1px;
+		// border-style: solid;
+		// border-color: $uni-border-color;
+	}
+
+	.uni-pagination__num-current {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+	}
+
+	.uni-pagination__num-current-text {
+		font-size: 15px;
+	}
+
+	.uni-pagination--enabled {
+		color: #333333;
+		opacity: 1;
+	}
+
+	.uni-pagination--disabled {
+		opacity: 0.5;
+		/* #ifdef H5 */
+		cursor: default;
+		/* #endif */
+	}
+
+	.uni-pagination--hover {
+		color: rgba(0, 0, 0, 0.6);
+		background-color: #eee;
+	}
+
+	.tag--active:hover {
+		color: $uni-primary;
+	}
+
+	.page--active {
+		color: #fff;
+		background-color: $uni-primary;
+	}
+
+	.page--active:hover {
+		color: #fff;
+	}
+
+	/* #ifndef APP-NVUE */
+	.is-pc-hide {
+		display: block;
+	}
+
+	.is-phone-hide {
+		display: none;
+	}
+
+	@media screen and (min-width: 450px) {
+		.is-pc-hide {
+			display: none;
+		}
+
+		.is-phone-hide {
+			display: block;
+		}
+
+		.uni-pagination__num-flex-none {
+			flex: none;
+		}
+	}
+
+	/* #endif */
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-pagination/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-pagination/package.json
new file mode 100644
index 000000000..adce67041
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-pagination/package.json
@@ -0,0 +1,86 @@
+{
+  "id": "uni-pagination",
+  "displayName": "uni-pagination 分页器",
+  "version": "1.2.1",
+  "description": "Pagination 分页器组件,用于展示页码、请求数据等。",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "分页器",
+    "页码"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": ["uni-scss","uni-icons"],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-pagination/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-pagination/readme.md
new file mode 100644
index 000000000..eefa26348
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-pagination/readme.md
@@ -0,0 +1,13 @@
+
+
+## Pagination 分页器
+> **组件名:uni-pagination**
+> 代码块: `uPagination`
+
+
+分页器组件,用于展示页码、请求数据等。
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-pagination)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
+
+
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-popup/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-popup/changelog.md
new file mode 100644
index 000000000..a9e2d6682
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-popup/changelog.md
@@ -0,0 +1,60 @@
+## 1.7.9(2022-04-02)
+- 修复 弹出层内部无法滚动的bug
+## 1.7.8(2022-03-28)
+- 修复 小程序中高度错误的bug
+## 1.7.7(2022-03-17)
+- 修复 快速调用open出现问题的Bug
+## 1.7.6(2022-02-14)
+- 修复 safeArea 属性不能设置为false的bug
+## 1.7.5(2022-01-19)
+- 修复 isMaskClick 失效的bug
+## 1.7.4(2022-01-19)
+- 新增 cancelText \ confirmText 属性 ,可自定义文本
+- 新增 maskBackgroundColor 属性 ,可以修改蒙版颜色
+- 优化 maskClick属性 更新为 isMaskClick ,解决微信小程序警告的问题
+## 1.7.3(2022-01-13)
+- 修复 设置 safeArea 属性不生效的bug
+## 1.7.2(2021-11-26)
+- 优化 组件示例
+## 1.7.1(2021-11-26)
+- 修复 vuedoc 文字错误
+## 1.7.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-popup](https://uniapp.dcloud.io/component/uniui/uni-popup)
+## 1.6.2(2021-08-24)
+- 新增 支持国际化
+## 1.6.1(2021-07-30)
+- 优化 vue3下事件警告的问题
+## 1.6.0(2021-07-13)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.5.0(2021-06-23)
+- 新增 mask-click 遮罩层点击事件
+## 1.4.5(2021-06-22)
+- 修复 nvue 平台中间弹出后,点击内容,再点击遮罩无法关闭的Bug
+## 1.4.4(2021-06-18)
+- 修复 H5平台中间弹出后,点击内容,再点击遮罩无法关闭的Bug
+## 1.4.3(2021-06-08)
+- 修复 错误的 watch 字段
+- 修复 safeArea 属性不生效的问题
+- 修复 点击内容,再点击遮罩无法关闭的Bug
+## 1.4.2(2021-05-12)
+- 新增 组件示例地址
+## 1.4.1(2021-04-29)
+- 修复 组件内放置 input 、textarea 组件,无法聚焦的问题
+## 1.4.0 (2021-04-29)
+- 新增 type 属性的 left\right 值,支持左右弹出
+- 新增 open(String:type) 方法参数 ,可以省略 type 属性 ,直接传入类型打开指定弹窗
+- 新增 backgroundColor 属性,可定义主窗口背景色,默认不显示背景色
+- 新增 safeArea 属性,是否适配底部安全区
+- 修复 App\h5\微信小程序底部安全区占位不对的Bug
+- 修复 App 端弹出等待的Bug
+- 优化 提升低配设备性能,优化动画卡顿问题
+- 优化 更简单的组件自定义方式
+## 1.2.9(2021-02-05)
+- 优化 组件引用关系,通过uni_modules引用组件
+## 1.2.8(2021-02-05)
+- 调整为uni_modules目录规范
+## 1.2.7(2021-02-05)
+- 调整为uni_modules目录规范
+- 新增 支持 PC 端
+- 新增 uni-popup-message 、uni-popup-dialog扩展组件支持 PC 端
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-popup/components/uni-popup-dialog/keypress.js b/yudao-ui-admin-uniapp/uni_modules/uni-popup/components/uni-popup-dialog/keypress.js
new file mode 100644
index 000000000..6ef26a262
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-popup/components/uni-popup-dialog/keypress.js
@@ -0,0 +1,45 @@
+// #ifdef H5
+export default {
+  name: 'Keypress',
+  props: {
+    disable: {
+      type: Boolean,
+      default: false
+    }
+  },
+  mounted () {
+    const keyNames = {
+      esc: ['Esc', 'Escape'],
+      tab: 'Tab',
+      enter: 'Enter',
+      space: [' ', 'Spacebar'],
+      up: ['Up', 'ArrowUp'],
+      left: ['Left', 'ArrowLeft'],
+      right: ['Right', 'ArrowRight'],
+      down: ['Down', 'ArrowDown'],
+      delete: ['Backspace', 'Delete', 'Del']
+    }
+    const listener = ($event) => {
+      if (this.disable) {
+        return
+      }
+      const keyName = Object.keys(keyNames).find(key => {
+        const keyName = $event.key
+        const value = keyNames[key]
+        return value === keyName || (Array.isArray(value) && value.includes(keyName))
+      })
+      if (keyName) {
+        // 避免和其他按键事件冲突
+        setTimeout(() => {
+          this.$emit(keyName, {})
+        }, 0)
+      }
+    }
+    document.addEventListener('keyup', listener)
+    this.$once('hook:beforeDestroy', () => {
+      document.removeEventListener('keyup', listener)
+    })
+  },
+	render: () => {}
+}
+// #endif
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue b/yudao-ui-admin-uniapp/uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue
new file mode 100644
index 000000000..a5d0f2a2d
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue
@@ -0,0 +1,271 @@
+<template>
+	<view class="uni-popup-dialog">
+		<view class="uni-dialog-title">
+			<text class="uni-dialog-title-text" :class="['uni-popup__'+dialogType]">{{titleText}}</text>
+		</view>
+		<view v-if="mode === 'base'" class="uni-dialog-content">
+			<slot>
+				<text class="uni-dialog-content-text">{{content}}</text>
+			</slot>
+		</view>
+		<view v-else class="uni-dialog-content">
+			<slot>
+				<input class="uni-dialog-input" v-model="val" type="text" :placeholder="placeholderText" :focus="focus" >
+			</slot>
+		</view>
+		<view class="uni-dialog-button-group">
+			<view class="uni-dialog-button" @click="closeDialog">
+				<text class="uni-dialog-button-text">{{closeText}}</text>
+			</view>
+			<view class="uni-dialog-button uni-border-left" @click="onOk">
+				<text class="uni-dialog-button-text uni-button-color">{{okText}}</text>
+			</view>
+		</view>
+
+	</view>
+</template>
+
+<script>
+	import popup from '../uni-popup/popup.js'
+	import {
+	initVueI18n
+	} from '@dcloudio/uni-i18n'
+	import messages from '../uni-popup/i18n/index.js'
+	const {	t } = initVueI18n(messages)
+	/**
+	 * PopUp 弹出层-对话框样式
+	 * @description 弹出层-对话框样式
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=329
+	 * @property {String} value input 模式下的默认值
+	 * @property {String} placeholder input 模式下输入提示
+	 * @property {String} type = [success|warning|info|error] 主题样式
+	 *  @value success 成功
+	 * 	@value warning 提示
+	 * 	@value info 消息
+	 * 	@value error 错误
+	 * @property {String} mode = [base|input] 模式、
+	 * 	@value base 基础对话框
+	 * 	@value input 可输入对话框
+	 * @property {String} content 对话框内容
+	 * @property {Boolean} beforeClose 是否拦截取消事件
+	 * @event {Function} confirm 点击确认按钮触发
+	 * @event {Function} close 点击取消按钮触发
+	 */
+
+	export default {
+		name: "uniPopupDialog",
+		mixins: [popup],
+		emits:['confirm','close'],
+		props: {
+			value: {
+				type: [String, Number],
+				default: ''
+			},
+			placeholder: {
+				type: [String, Number],
+				default: ''
+			},
+			type: {
+				type: String,
+				default: 'error'
+			},
+			mode: {
+				type: String,
+				default: 'base'
+			},
+			title: {
+				type: String,
+				default: ''
+			},
+			content: {
+				type: String,
+				default: ''
+			},
+			beforeClose: {
+				type: Boolean,
+				default: false
+			},
+			cancelText:{
+				type: String,
+				default: ''
+			},
+			confirmText:{
+				type: String,
+				default: ''
+			}
+		},
+		data() {
+			return {
+				dialogType: 'error',
+				focus: false,
+				val: ""
+			}
+		},
+		computed: {
+			okText() {
+				return this.confirmText || t("uni-popup.ok")
+			},
+			closeText() {
+				return this.cancelText || t("uni-popup.cancel")
+			},
+			placeholderText() {
+				return this.placeholder || t("uni-popup.placeholder")
+			},
+			titleText() {
+				return this.title || t("uni-popup.title")
+			}
+		},
+		watch: {
+			type(val) {
+				this.dialogType = val
+			},
+			mode(val) {
+				if (val === 'input') {
+					this.dialogType = 'info'
+				}
+			},
+			value(val) {
+				this.val = val
+			}
+		},
+		created() {
+			// 对话框遮罩不可点击
+			this.popup.disableMask()
+			// this.popup.closeMask()
+			if (this.mode === 'input') {
+				this.dialogType = 'info'
+				this.val = this.value
+			} else {
+				this.dialogType = this.type
+			}
+		},
+		mounted() {
+			this.focus = true
+		},
+		methods: {
+			/**
+			 * 点击确认按钮
+			 */
+			onOk() {
+				if (this.mode === 'input'){
+					this.$emit('confirm', this.val)
+				}else{
+					this.$emit('confirm')
+				}
+				if(this.beforeClose) return
+				this.popup.close()
+			},
+			/**
+			 * 点击取消按钮
+			 */
+			closeDialog() {
+				this.$emit('close')
+				if(this.beforeClose) return
+				this.popup.close()
+			},
+			close(){
+				this.popup.close()
+			}
+		}
+	}
+</script>
+
+<style lang="scss" >
+	.uni-popup-dialog {
+		width: 300px;
+		border-radius: 11px;
+		background-color: #fff;
+	}
+
+	.uni-dialog-title {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		justify-content: center;
+		padding-top: 25px;
+	}
+
+	.uni-dialog-title-text {
+		font-size: 16px;
+		font-weight: 500;
+	}
+
+	.uni-dialog-content {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		justify-content: center;
+		align-items: center;
+		padding: 20px;
+	}
+
+	.uni-dialog-content-text {
+		font-size: 14px;
+		color: #6C6C6C;
+	}
+
+	.uni-dialog-button-group {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		border-top-color: #f5f5f5;
+		border-top-style: solid;
+		border-top-width: 1px;
+	}
+
+	.uni-dialog-button {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+
+		flex: 1;
+		flex-direction: row;
+		justify-content: center;
+		align-items: center;
+		height: 45px;
+	}
+
+	.uni-border-left {
+		border-left-color: #f0f0f0;
+		border-left-style: solid;
+		border-left-width: 1px;
+	}
+
+	.uni-dialog-button-text {
+		font-size: 16px;
+		color: #333;
+	}
+
+	.uni-button-color {
+		color: #007aff;
+	}
+
+	.uni-dialog-input {
+		flex: 1;
+		font-size: 14px;
+		border: 1px #eee solid;
+		height: 40px;
+		padding: 0 10px;
+		border-radius: 5px;
+		color: #555;
+	}
+
+	.uni-popup__success {
+		color: #4cd964;
+	}
+
+	.uni-popup__warn {
+		color: #f0ad4e;
+	}
+
+	.uni-popup__error {
+		color: #dd524d;
+	}
+
+	.uni-popup__info {
+		color: #909399;
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-popup/components/uni-popup-message/uni-popup-message.vue b/yudao-ui-admin-uniapp/uni_modules/uni-popup/components/uni-popup-message/uni-popup-message.vue
new file mode 100644
index 000000000..91370a829
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-popup/components/uni-popup-message/uni-popup-message.vue
@@ -0,0 +1,143 @@
+<template>
+	<view class="uni-popup-message">
+		<view class="uni-popup-message__box fixforpc-width" :class="'uni-popup__'+type">
+			<slot>
+				<text class="uni-popup-message-text" :class="'uni-popup__'+type+'-text'">{{message}}</text>
+			</slot>
+		</view>
+	</view>
+</template>
+
+<script>
+	import popup from '../uni-popup/popup.js'
+	/**
+	 * PopUp 弹出层-消息提示
+	 * @description 弹出层-消息提示
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=329
+	 * @property {String} type = [success|warning|info|error] 主题样式
+	 *  @value success 成功
+	 * 	@value warning 提示
+	 * 	@value info 消息
+	 * 	@value error 错误
+	 * @property {String} message 消息提示文字
+	 * @property {String} duration 显示时间,设置为 0 则不会自动关闭
+	 */
+
+	export default {
+		name: 'uniPopupMessage',
+		mixins:[popup],
+		props: {
+			/**
+			 * 主题 success/warning/info/error	  默认 success
+			 */
+			type: {
+				type: String,
+				default: 'success'
+			},
+			/**
+			 * 消息文字
+			 */
+			message: {
+				type: String,
+				default: ''
+			},
+			/**
+			 * 显示时间,设置为 0 则不会自动关闭
+			 */
+			duration: {
+				type: Number,
+				default: 3000
+			},
+			maskShow:{
+				type:Boolean,
+				default:false
+			}
+		},
+		data() {
+			return {}
+		},
+		created() {
+			this.popup.maskShow = this.maskShow
+			this.popup.messageChild = this
+		},
+		methods: {
+			timerClose(){
+				if(this.duration === 0) return
+				clearTimeout(this.timer) 
+				this.timer = setTimeout(()=>{
+					this.popup.close()
+				},this.duration)
+			}
+		}
+	}
+</script>
+<style lang="scss" >
+	.uni-popup-message {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		justify-content: center;
+	}
+
+	.uni-popup-message__box {
+		background-color: #e1f3d8;
+		padding: 10px 15px;
+		border-color: #eee;
+		border-style: solid;
+		border-width: 1px;
+		flex: 1;
+	}
+
+	@media screen and (min-width: 500px) {
+		.fixforpc-width {
+			margin-top: 20px;
+			border-radius: 4px;
+			flex: none;
+			min-width: 380px;
+			/* #ifndef APP-NVUE */
+			max-width: 50%;
+			/* #endif */
+			/* #ifdef APP-NVUE */
+			max-width: 500px;
+			/* #endif */
+		}
+	}
+
+	.uni-popup-message-text {
+		font-size: 14px;
+		padding: 0;
+	}
+
+	.uni-popup__success {
+		background-color: #e1f3d8;
+	}
+
+	.uni-popup__success-text {
+		color: #67C23A;
+	}
+
+	.uni-popup__warn {
+		background-color: #faecd8;
+	}
+
+	.uni-popup__warn-text {
+		color: #E6A23C;
+	}
+
+	.uni-popup__error {
+		background-color: #fde2e2;
+	}
+
+	.uni-popup__error-text {
+		color: #F56C6C;
+	}
+
+	.uni-popup__info {
+		background-color: #F2F6FC;
+	}
+
+	.uni-popup__info-text {
+		color: #909399;
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-popup/components/uni-popup-share/uni-popup-share.vue b/yudao-ui-admin-uniapp/uni_modules/uni-popup/components/uni-popup-share/uni-popup-share.vue
new file mode 100644
index 000000000..5be76247a
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-popup/components/uni-popup-share/uni-popup-share.vue
@@ -0,0 +1,187 @@
+<template>
+	<view class="uni-popup-share">
+		<view class="uni-share-title"><text class="uni-share-title-text">{{shareTitleText}}</text></view>
+		<view class="uni-share-content">
+			<view class="uni-share-content-box">
+				<view class="uni-share-content-item" v-for="(item,index) in bottomData" :key="index" @click.stop="select(item,index)">
+					<image class="uni-share-image" :src="item.icon" mode="aspectFill"></image>
+					<text class="uni-share-text">{{item.text}}</text>
+				</view>
+
+			</view>
+		</view>
+		<view class="uni-share-button-box">
+			<button class="uni-share-button" @click="close">{{cancelText}}</button>
+		</view>
+	</view>
+</template>
+
+<script>
+	import popup from '../uni-popup/popup.js'
+	import {
+	initVueI18n
+	} from '@dcloudio/uni-i18n'
+	import messages from '../uni-popup/i18n/index.js'
+	const {	t	} = initVueI18n(messages)
+	export default {
+		name: 'UniPopupShare',
+		mixins:[popup],
+		emits:['select'],
+		props: {
+			title: {
+				type: String,
+				default: ''
+			},
+			beforeClose: {
+				type: Boolean,
+				default: false
+			}
+		},
+		data() {
+			return {
+				bottomData: [{
+						text: '微信',
+						icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/c2b17470-50be-11eb-b680-7980c8a877b8.png',
+						name: 'wx'
+					},
+					{
+						text: '支付宝',
+						icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/d684ae40-50be-11eb-8ff1-d5dcf8779628.png',
+						name: 'wx'
+					},
+					{
+						text: 'QQ',
+						icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/e7a79520-50be-11eb-b997-9918a5dda011.png',
+						name: 'qq'
+					},
+					{
+						text: '新浪',
+						icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/0dacdbe0-50bf-11eb-8ff1-d5dcf8779628.png',
+						name: 'sina'
+					},
+					// {
+					// 	text: '百度',
+					// 	icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/1ec6e920-50bf-11eb-8a36-ebb87efcf8c0.png',
+					// 	name: 'copy'
+					// },
+					// {
+					// 	text: '其他',
+					// 	icon: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/2e0fdfe0-50bf-11eb-b997-9918a5dda011.png',
+					// 	name: 'more'
+					// }
+				]
+			}
+		},
+		created() {},
+		computed: {
+			cancelText() {
+				return t("uni-popup.cancel")
+			},
+		shareTitleText() {
+				return this.title || t("uni-popup.shareTitle")
+			}
+		},
+		methods: {
+			/**
+			 * 选择内容
+			 */
+			select(item, index) {
+				this.$emit('select', {
+					item,
+					index
+				})
+				this.close()
+
+			},
+			/**
+			 * 关闭窗口
+			 */
+			close() {
+				if(this.beforeClose) return
+				this.popup.close()
+			}
+		}
+	}
+</script>
+<style lang="scss" >
+	.uni-popup-share {
+		background-color: #fff;
+		border-top-left-radius: 11px;
+		border-top-right-radius: 11px;
+	}
+	.uni-share-title {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		align-items: center;
+		justify-content: center;
+		height: 40px;
+	}
+	.uni-share-title-text {
+		font-size: 14px;
+		color: #666;
+	}
+	.uni-share-content {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		justify-content: center;
+		padding-top: 10px;
+	}
+
+	.uni-share-content-box {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		flex-wrap: wrap;
+		width: 360px;
+	}
+
+	.uni-share-content-item {
+		width: 90px;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		justify-content: center;
+		padding: 10px 0;
+		align-items: center;
+	}
+
+	.uni-share-content-item:active {
+		background-color: #f5f5f5;
+	}
+
+	.uni-share-image {
+		width: 30px;
+		height: 30px;
+	}
+
+	.uni-share-text {
+		margin-top: 10px;
+		font-size: 14px;
+		color: #3B4144;
+	}
+
+	.uni-share-button-box {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		padding: 10px 15px;
+	}
+
+	.uni-share-button {
+		flex: 1;
+		border-radius: 50px;
+		color: #666;
+		font-size: 16px;
+	}
+
+	.uni-share-button::after {
+		border-radius: 50px;
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-popup/components/uni-popup/i18n/en.json b/yudao-ui-admin-uniapp/uni_modules/uni-popup/components/uni-popup/i18n/en.json
new file mode 100644
index 000000000..7f1bd06a0
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-popup/components/uni-popup/i18n/en.json
@@ -0,0 +1,7 @@
+{
+	"uni-popup.cancel": "cancel",
+	"uni-popup.ok": "ok",
+	"uni-popup.placeholder": "pleace enter",
+	"uni-popup.title": "Hint",
+	"uni-popup.shareTitle": "Share to"
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-popup/components/uni-popup/i18n/index.js b/yudao-ui-admin-uniapp/uni_modules/uni-popup/components/uni-popup/i18n/index.js
new file mode 100644
index 000000000..de7509c87
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-popup/components/uni-popup/i18n/index.js
@@ -0,0 +1,8 @@
+import en from './en.json'
+import zhHans from './zh-Hans.json'
+import zhHant from './zh-Hant.json'
+export default {
+	en,
+	'zh-Hans': zhHans,
+	'zh-Hant': zhHant
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hans.json b/yudao-ui-admin-uniapp/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hans.json
new file mode 100644
index 000000000..5e3003cab
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hans.json
@@ -0,0 +1,7 @@
+{
+	"uni-popup.cancel": "取消",
+	"uni-popup.ok": "确定",
+	"uni-popup.placeholder": "请输入",
+		"uni-popup.title": "提示",
+		"uni-popup.shareTitle": "分享到"
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hant.json b/yudao-ui-admin-uniapp/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hant.json
new file mode 100644
index 000000000..13e39eba1
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hant.json
@@ -0,0 +1,7 @@
+{
+	"uni-popup.cancel": "取消",
+	"uni-popup.ok": "確定",
+	"uni-popup.placeholder": "請輸入",
+	"uni-popup.title": "提示",
+	"uni-popup.shareTitle": "分享到"
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-popup/components/uni-popup/keypress.js b/yudao-ui-admin-uniapp/uni_modules/uni-popup/components/uni-popup/keypress.js
new file mode 100644
index 000000000..62dda461b
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-popup/components/uni-popup/keypress.js
@@ -0,0 +1,45 @@
+// #ifdef H5
+export default {
+  name: 'Keypress',
+  props: {
+    disable: {
+      type: Boolean,
+      default: false
+    }
+  },
+  mounted () {
+    const keyNames = {
+      esc: ['Esc', 'Escape'],
+      tab: 'Tab',
+      enter: 'Enter',
+      space: [' ', 'Spacebar'],
+      up: ['Up', 'ArrowUp'],
+      left: ['Left', 'ArrowLeft'],
+      right: ['Right', 'ArrowRight'],
+      down: ['Down', 'ArrowDown'],
+      delete: ['Backspace', 'Delete', 'Del']
+    }
+    const listener = ($event) => {
+      if (this.disable) {
+        return
+      }
+      const keyName = Object.keys(keyNames).find(key => {
+        const keyName = $event.key
+        const value = keyNames[key]
+        return value === keyName || (Array.isArray(value) && value.includes(keyName))
+      })
+      if (keyName) {
+        // 避免和其他按键事件冲突
+        setTimeout(() => {
+          this.$emit(keyName, {})
+        }, 0)
+      }
+    }
+    document.addEventListener('keyup', listener)
+    // this.$once('hook:beforeDestroy', () => {
+    //   document.removeEventListener('keyup', listener)
+    // })
+  },
+	render: () => {}
+}
+// #endif
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-popup/components/uni-popup/popup.js b/yudao-ui-admin-uniapp/uni_modules/uni-popup/components/uni-popup/popup.js
new file mode 100644
index 000000000..c4e5781dd
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-popup/components/uni-popup/popup.js
@@ -0,0 +1,26 @@
+
+export default {
+	data() {
+		return {
+			
+		}
+	},
+	created(){
+		this.popup = this.getParent()
+	},
+	methods:{
+		/**
+		 * 获取父元素实例
+		 */
+		getParent(name = 'uniPopup') {
+			let parent = this.$parent;
+			let parentName = parent.$options.name;
+			while (parentName !== name) {
+				parent = parent.$parent;
+				if (!parent) return false
+				parentName = parent.$options.name;
+			}
+			return parent;
+		},
+	}
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-popup/components/uni-popup/uni-popup.vue b/yudao-ui-admin-uniapp/uni_modules/uni-popup/components/uni-popup/uni-popup.vue
new file mode 100644
index 000000000..db90c599e
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-popup/components/uni-popup/uni-popup.vue
@@ -0,0 +1,474 @@
+<template>
+	<view v-if="showPopup" class="uni-popup" :class="[popupstyle, isDesktop ? 'fixforpc-z-index' : '']">
+		<view @touchstart="touchstart">
+			<uni-transition key="1" v-if="maskShow" name="mask" mode-class="fade" :styles="maskClass"
+				:duration="duration" :show="showTrans" @click="onTap" />
+			<uni-transition key="2" :mode-class="ani" name="content" :styles="transClass" :duration="duration"
+				:show="showTrans" @click="onTap">
+				<view class="uni-popup__wrapper" :style="{ backgroundColor: bg }" :class="[popupstyle]" @click="clear">
+					<slot />
+				</view>
+			</uni-transition>
+		</view>
+		<!-- #ifdef H5 -->
+		<keypress v-if="maskShow" @esc="onTap" />
+		<!-- #endif -->
+	</view>
+</template>
+
+<script>
+	// #ifdef H5
+	import keypress from './keypress.js'
+	// #endif
+
+	/**
+	 * PopUp 弹出层
+	 * @description 弹出层组件,为了解决遮罩弹层的问题
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=329
+	 * @property {String} type = [top|center|bottom|left|right|message|dialog|share] 弹出方式
+	 * 	@value top 顶部弹出
+	 * 	@value center 中间弹出
+	 * 	@value bottom 底部弹出
+	 * 	@value left		左侧弹出
+	 * 	@value right  右侧弹出
+	 * 	@value message 消息提示
+	 * 	@value dialog 对话框
+	 * 	@value share 底部分享示例
+	 * @property {Boolean} animation = [true|false] 是否开启动画
+	 * @property {Boolean} maskClick = [true|false] 蒙版点击是否关闭弹窗(废弃)
+	 * @property {Boolean} isMaskClick = [true|false] 蒙版点击是否关闭弹窗
+	 * @property {String}  backgroundColor 主窗口背景色
+	 * @property {String}  maskBackgroundColor 蒙版颜色
+	 * @property {Boolean} safeArea		   是否适配底部安全区
+	 * @event {Function} change 打开关闭弹窗触发,e={show: false}
+	 * @event {Function} maskClick 点击遮罩触发
+	 */
+
+	export default {
+		name: 'uniPopup',
+		components: {
+			// #ifdef H5
+			keypress
+			// #endif
+		},
+		emits: ['change', 'maskClick'],
+		props: {
+			// 开启动画
+			animation: {
+				type: Boolean,
+				default: true
+			},
+			// 弹出层类型,可选值,top: 顶部弹出层;bottom:底部弹出层;center:全屏弹出层
+			// message: 消息提示 ; dialog : 对话框
+			type: {
+				type: String,
+				default: 'center'
+			},
+			// maskClick
+			isMaskClick: {
+				type: Boolean,
+				default: null
+			},
+			// TODO 2 个版本后废弃属性 ,使用 isMaskClick
+			maskClick: {
+				type: Boolean,
+				default: null
+			},
+			backgroundColor: {
+				type: String,
+				default: 'none'
+			},
+			safeArea: {
+				type: Boolean,
+				default: true
+			},
+			maskBackgroundColor: {
+				type: String,
+				default: 'rgba(0, 0, 0, 0.4)'
+			},
+		},
+
+		watch: {
+			/**
+			 * 监听type类型
+			 */
+			type: {
+				handler: function(type) {
+					if (!this.config[type]) return
+					this[this.config[type]](true)
+				},
+				immediate: true
+			},
+			isDesktop: {
+				handler: function(newVal) {
+					if (!this.config[newVal]) return
+					this[this.config[this.type]](true)
+				},
+				immediate: true
+			},
+			/**
+			 * 监听遮罩是否可点击
+			 * @param {Object} val
+			 */
+			maskClick: {
+				handler: function(val) {
+					this.mkclick = val
+				},
+				immediate: true
+			},
+			isMaskClick: {
+				handler: function(val) {
+					this.mkclick = val
+				},
+				immediate: true
+			},
+			// H5 下禁止底部滚动
+			showPopup(show) {
+				// #ifdef H5
+				// fix by mehaotian 处理 h5 滚动穿透的问题
+				document.getElementsByTagName('body')[0].style.overflow = show ? 'hidden' : 'visible'
+				// #endif
+			}
+		},
+		data() {
+			return {
+				duration: 300,
+				ani: [],
+				showPopup: false,
+				showTrans: false,
+				popupWidth: 0,
+				popupHeight: 0,
+				config: {
+					top: 'top',
+					bottom: 'bottom',
+					center: 'center',
+					left: 'left',
+					right: 'right',
+					message: 'top',
+					dialog: 'center',
+					share: 'bottom'
+				},
+				maskClass: {
+					position: 'fixed',
+					bottom: 0,
+					top: 0,
+					left: 0,
+					right: 0,
+					backgroundColor: 'rgba(0, 0, 0, 0.4)'
+				},
+				transClass: {
+					position: 'fixed',
+					left: 0,
+					right: 0
+				},
+				maskShow: true,
+				mkclick: true,
+				popupstyle: this.isDesktop ? 'fixforpc-top' : 'top'
+			}
+		},
+		computed: {
+			isDesktop() {
+				return this.popupWidth >= 500 && this.popupHeight >= 500
+			},
+			bg() {
+				if (this.backgroundColor === '' || this.backgroundColor === 'none') {
+					return 'transparent'
+				}
+				return this.backgroundColor
+			}
+		},
+		mounted() {
+			const fixSize = () => {
+				const {
+					windowWidth,
+					windowHeight,
+					windowTop,
+					safeArea,
+					screenHeight,
+					safeAreaInsets
+				} = uni.getSystemInfoSync()
+				this.popupWidth = windowWidth
+				this.popupHeight = windowHeight + (windowTop || 0)
+				// TODO fix by mehaotian 是否适配底部安全区 ,目前微信ios 、和 app ios 计算有差异,需要框架修复
+				if (safeArea && this.safeArea) {
+					// #ifdef MP-WEIXIN
+					this.safeAreaInsets = screenHeight - safeArea.bottom
+					// #endif
+					// #ifndef MP-WEIXIN
+					this.safeAreaInsets = safeAreaInsets.bottom
+					// #endif
+				} else {
+					this.safeAreaInsets = 0
+				}
+			}
+			fixSize()
+			// #ifdef H5
+			// window.addEventListener('resize', fixSize)
+			// this.$once('hook:beforeDestroy', () => {
+			// 	window.removeEventListener('resize', fixSize)
+			// })
+			// #endif
+		},
+		// #ifndef VUE3
+		// TODO vue2
+		destroyed() {
+			this.setH5Visible()
+		},
+		// #endif
+		// #ifdef VUE3
+		// TODO vue3
+		unmounted() {
+			this.setH5Visible()
+		},
+		// #endif
+		created() {
+			// this.mkclick =  this.isMaskClick || this.maskClick
+			if (this.isMaskClick === null && this.maskClick === null) {
+				this.mkclick = true
+			} else {
+				this.mkclick = this.isMaskClick !== null ? this.isMaskClick : this.maskClick
+			}
+			if (this.animation) {
+				this.duration = 300
+			} else {
+				this.duration = 0
+			}
+			// TODO 处理 message 组件生命周期异常的问题
+			this.messageChild = null
+			// TODO 解决头条冒泡的问题
+			this.clearPropagation = false
+			this.maskClass.backgroundColor = this.maskBackgroundColor
+		},
+		methods: {
+			setH5Visible() {
+				// #ifdef H5
+				// fix by mehaotian 处理 h5 滚动穿透的问题
+				document.getElementsByTagName('body')[0].style.overflow = 'visible'
+				// #endif
+			},
+			/**
+			 * 公用方法,不显示遮罩层
+			 */
+			closeMask() {
+				this.maskShow = false
+			},
+			/**
+			 * 公用方法,遮罩层禁止点击
+			 */
+			disableMask() {
+				this.mkclick = false
+			},
+			// TODO nvue 取消冒泡
+			clear(e) {
+				// #ifndef APP-NVUE
+				e.stopPropagation()
+				// #endif
+				this.clearPropagation = true
+			},
+
+			open(direction) {
+				// fix by mehaotian 处理快速打开关闭的情况
+				if (this.showPopup) {
+					clearTimeout(this.timer)
+					this.showPopup = false
+				}
+				let innerType = ['top', 'center', 'bottom', 'left', 'right', 'message', 'dialog', 'share']
+				if (!(direction && innerType.indexOf(direction) !== -1)) {
+					direction = this.type
+				}
+				if (!this.config[direction]) {
+					console.error('缺少类型:', direction)
+					return
+				}
+				this[this.config[direction]]()
+				this.$emit('change', {
+					show: true,
+					type: direction
+				})
+			},
+			close(type) {
+				this.showTrans = false
+				this.$emit('change', {
+					show: false,
+					type: this.type
+				})
+				clearTimeout(this.timer)
+				// // 自定义关闭事件
+				// this.customOpen && this.customClose()
+				this.timer = setTimeout(() => {
+					this.showPopup = false
+				}, 300)
+			},
+			// TODO 处理冒泡事件,头条的冒泡事件有问题 ,先这样兼容
+			touchstart() {
+				this.clearPropagation = false
+			},
+
+			onTap() {
+				if (this.clearPropagation) {
+					// fix by mehaotian 兼容 nvue
+					this.clearPropagation = false
+					return
+				}
+				this.$emit('maskClick')
+				if (!this.mkclick) return
+				this.close()
+			},
+			/**
+			 * 顶部弹出样式处理
+			 */
+			top(type) {
+				this.popupstyle = this.isDesktop ? 'fixforpc-top' : 'top'
+				this.ani = ['slide-top']
+				this.transClass = {
+					position: 'fixed',
+					left: 0,
+					right: 0,
+					backgroundColor: this.bg
+				}
+				// TODO 兼容 type 属性 ,后续会废弃
+				if (type) return
+				this.showPopup = true
+				this.showTrans = true
+				this.$nextTick(() => {
+					if (this.messageChild && this.type === 'message') {
+						this.messageChild.timerClose()
+					}
+				})
+			},
+			/**
+			 * 底部弹出样式处理
+			 */
+			bottom(type) {
+				this.popupstyle = 'bottom'
+				this.ani = ['slide-bottom']
+				this.transClass = {
+					position: 'fixed',
+					left: 0,
+					right: 0,
+					bottom: 0,
+					paddingBottom: this.safeAreaInsets + 'px',
+					backgroundColor: this.bg
+				}
+				// TODO 兼容 type 属性 ,后续会废弃
+				if (type) return
+				this.showPopup = true
+				this.showTrans = true
+			},
+			/**
+			 * 中间弹出样式处理
+			 */
+			center(type) {
+				this.popupstyle = 'center'
+				this.ani = ['zoom-out', 'fade']
+				this.transClass = {
+					position: 'fixed',
+					/* #ifndef APP-NVUE */
+					display: 'flex',
+					flexDirection: 'column',
+					/* #endif */
+					bottom: 0,
+					left: 0,
+					right: 0,
+					top: 0,
+					justifyContent: 'center',
+					alignItems: 'center'
+				}
+				// TODO 兼容 type 属性 ,后续会废弃
+				if (type) return
+				this.showPopup = true
+				this.showTrans = true
+			},
+			left(type) {
+				this.popupstyle = 'left'
+				this.ani = ['slide-left']
+				this.transClass = {
+					position: 'fixed',
+					left: 0,
+					bottom: 0,
+					top: 0,
+					backgroundColor: this.bg,
+					/* #ifndef APP-NVUE */
+					display: 'flex',
+					flexDirection: 'column'
+					/* #endif */
+				}
+				// TODO 兼容 type 属性 ,后续会废弃
+				if (type) return
+				this.showPopup = true
+				this.showTrans = true
+			},
+			right(type) {
+				this.popupstyle = 'right'
+				this.ani = ['slide-right']
+				this.transClass = {
+					position: 'fixed',
+					bottom: 0,
+					right: 0,
+					top: 0,
+					backgroundColor: this.bg,
+					/* #ifndef APP-NVUE */
+					display: 'flex',
+					flexDirection: 'column'
+					/* #endif */
+				}
+				// TODO 兼容 type 属性 ,后续会废弃
+				if (type) return
+				this.showPopup = true
+				this.showTrans = true
+			}
+		}
+	}
+</script>
+<style lang="scss">
+	.uni-popup {
+		position: fixed;
+		/* #ifndef APP-NVUE */
+		z-index: 99;
+
+		/* #endif */
+		&.top,
+		&.left,
+		&.right {
+			/* #ifdef H5 */
+			top: var(--window-top);
+			/* #endif */
+			/* #ifndef H5 */
+			top: 0;
+			/* #endif */
+		}
+
+		.uni-popup__wrapper {
+			/* #ifndef APP-NVUE */
+			display: block;
+			/* #endif */
+			position: relative;
+
+			/* iphonex 等安全区设置,底部安全区适配 */
+			/* #ifndef APP-NVUE */
+			// padding-bottom: constant(safe-area-inset-bottom);
+			// padding-bottom: env(safe-area-inset-bottom);
+			/* #endif */
+			&.left,
+			&.right {
+				/* #ifdef H5 */
+				padding-top: var(--window-top);
+				/* #endif */
+				/* #ifndef H5 */
+				padding-top: 0;
+				/* #endif */
+				flex: 1;
+			}
+		}
+	}
+
+	.fixforpc-z-index {
+		/* #ifndef APP-NVUE */
+		z-index: 999;
+		/* #endif */
+	}
+
+	.fixforpc-top {
+		top: 0;
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-popup/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-popup/package.json
new file mode 100644
index 000000000..069e9ce51
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-popup/package.json
@@ -0,0 +1,90 @@
+{
+	"id": "uni-popup",
+	"displayName": "uni-popup 弹出层",
+	"version": "1.7.9",
+	"description": " Popup 组件,提供常用的弹层",
+	"keywords": [
+        "uni-ui",
+        "弹出层",
+        "弹窗",
+        "popup",
+        "弹框"
+    ],
+	"repository": "https://github.com/dcloudio/uni-ui",
+	"engines": {
+		"HBuilderX": ""
+	},
+	"directories": {
+		"example": "../../temps/example_temps"
+	},
+	"dcloudext": {
+		"category": [
+			"前端组件",
+			"通用组件"
+		],
+		"sale": {
+			"regular": {
+				"price": "0.00"
+			},
+			"sourcecode": {
+				"price": "0.00"
+			}
+		},
+		"contact": {
+			"qq": ""
+		},
+		"declaration": {
+			"ads": "无",
+			"data": "无",
+			"permissions": "无"
+		},
+		"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+	},
+	"uni_modules": {
+		"dependencies": [
+			"uni-scss",
+			"uni-transition"
+		],
+		"encrypt": [],
+		"platforms": {
+			"cloud": {
+				"tcb": "y",
+				"aliyun": "y"
+			},
+			"client": {
+				"App": {
+					"app-vue": "y",
+					"app-nvue": "y"
+				},
+				"H5-mobile": {
+					"Safari": "y",
+					"Android Browser": "y",
+					"微信浏览器(Android)": "y",
+					"QQ浏览器(Android)": "y"
+				},
+				"H5-pc": {
+					"Chrome": "y",
+					"IE": "y",
+					"Edge": "y",
+					"Firefox": "y",
+					"Safari": "y"
+				},
+				"小程序": {
+					"微信": "y",
+					"阿里": "y",
+					"百度": "y",
+					"字节跳动": "y",
+					"QQ": "y"
+				},
+				"快应用": {
+					"华为": "u",
+					"联盟": "u"
+                },
+                "Vue": {
+                    "vue2": "y",
+                    "vue3": "y"
+                }
+			}
+		}
+	}
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-popup/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-popup/readme.md
new file mode 100644
index 000000000..fdad4b3d7
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-popup/readme.md
@@ -0,0 +1,17 @@
+
+
+## Popup 弹出层
+> **组件名:uni-popup**
+> 代码块: `uPopup`
+> 关联组件:`uni-transition`
+
+
+弹出层组件,在应用中弹出一个消息提示窗口、提示框等
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-popup)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
+
+
+
+
+
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-rate/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-rate/changelog.md
new file mode 100644
index 000000000..8a98a6127
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-rate/changelog.md
@@ -0,0 +1,25 @@
+## 1.3.1(2022-02-25)
+- 修复 条件判断 `NaN` 错误的 bug
+## 1.3.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-rate](https://uniapp.dcloud.io/component/uniui/uni-rate)
+## 1.2.2(2021-09-10)
+- 优化 默认值修改为 0 颗星
+## 1.2.1(2021-07-30)
+- 优化 vue3下事件警告的问题
+## 1.2.0(2021-07-13)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.1.2(2021-05-12)
+- 新增 组件示例地址
+## 1.1.1(2021-04-21)
+- 修复 布局变化后 uni-rate  星星计算不准确的 bug
+- 优化 添加依赖 uni-icons, 导入 uni-rate 自动下载依赖
+## 1.1.0(2021-04-16)
+- 修复 uni-rate 属性 margin 值为 string 组件失效的 bug
+
+## 1.0.9(2021-02-05)
+- 优化 组件引用关系,通过uni_modules引用组件
+
+## 1.0.8(2021-02-05)
+- 调整为uni_modules目录规范
+- 支持 pc 端
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-rate/components/uni-rate/uni-rate.vue b/yudao-ui-admin-uniapp/uni_modules/uni-rate/components/uni-rate/uni-rate.vue
new file mode 100644
index 000000000..857f5f9c9
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-rate/components/uni-rate/uni-rate.vue
@@ -0,0 +1,361 @@
+<template>
+	<view>
+		<view ref="uni-rate" class="uni-rate">
+			<view class="uni-rate__icon" :class="{'uni-cursor-not-allowed': disabled}"
+				:style="{ 'margin-right': marginNumber + 'px' }" v-for="(star, index) in stars" :key="index"
+				@touchstart.stop="touchstart" @touchmove.stop="touchmove" @mousedown.stop="mousedown"
+				@mousemove.stop="mousemove" @mouseleave="mouseleave">
+				<uni-icons :color="color" :size="size" :type="isFill ? 'star-filled' : 'star'" />
+				<!-- #ifdef APP-NVUE -->
+				<view :style="{ width: star.activeWitch.replace('%','')*size/100+'px'}" class="uni-rate__icon-on">
+					<uni-icons style="text-align: left;" :color="disabled?'#ccc':activeColor" :size="size"
+						type="star-filled" />
+				</view>
+				<!-- #endif -->
+				<!-- #ifndef APP-NVUE -->
+				<view :style="{ width: star.activeWitch}" class="uni-rate__icon-on">
+					<uni-icons :color="disabled?disabledColor:activeColor" :size="size" type="star-filled" />
+				</view>
+				<!-- #endif -->
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	// #ifdef APP-NVUE
+	const dom = uni.requireNativePlugin('dom');
+	// #endif
+	/**
+	 * Rate 评分
+	 * @description 评分组件
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=33
+	 * @property {Boolean} 	isFill = [true|false] 		星星的类型,是否为实心类型, 默认为实心
+	 * @property {String} 	color 						未选中状态的星星颜色,默认为 "#ececec"
+	 * @property {String} 	activeColor 				选中状态的星星颜色,默认为 "#ffca3e"
+	 * @property {String} 	disabledColor 				禁用状态的星星颜色,默认为 "#c0c0c0"
+	 * @property {Number} 	size 						星星的大小
+	 * @property {Number} 	value/v-model 				当前评分
+	 * @property {Number} 	max 						最大评分评分数量,目前一分一颗星
+	 * @property {Number} 	margin 						星星的间距,单位 px
+	 * @property {Boolean} 	disabled = [true|false] 	是否为禁用状态,默认为 false
+	 * @property {Boolean} 	readonly = [true|false] 	是否为只读状态,默认为 false
+	 * @property {Boolean} 	allowHalf = [true|false] 	是否实现半星,默认为 false
+	 * @property {Boolean} 	touchable = [true|false] 	是否支持滑动手势,默认为 true
+	 * @event {Function} change 						uniRate 的 value 改变时触发事件,e={value:Number}
+	 */
+
+	export default {
+		name: "UniRate",
+		props: {
+			isFill: {
+				// 星星的类型,是否镂空
+				type: [Boolean, String],
+				default: true
+			},
+			color: {
+				// 星星未选中的颜色
+				type: String,
+				default: "#ececec"
+			},
+			activeColor: {
+				// 星星选中状态颜色
+				type: String,
+				default: "#ffca3e"
+			},
+			disabledColor: {
+				// 星星禁用状态颜色
+				type: String,
+				default: "#c0c0c0"
+			},
+			size: {
+				// 星星的大小
+				type: [Number, String],
+				default: 24
+			},
+			value: {
+				// 当前评分
+				type: [Number, String],
+				default: 0
+			},
+			modelValue: {
+				// 当前评分
+				type: [Number, String],
+				default: 0
+			},
+			max: {
+				// 最大评分
+				type: [Number, String],
+				default: 5
+			},
+			margin: {
+				// 星星的间距
+				type: [Number, String],
+				default: 0
+			},
+			disabled: {
+				// 是否可点击
+				type: [Boolean, String],
+				default: false
+			},
+			readonly: {
+				// 是否只读
+				type: [Boolean, String],
+				default: false
+			},
+			allowHalf: {
+				// 是否显示半星
+				type: [Boolean, String],
+				default: false
+			},
+			touchable: {
+				// 是否支持滑动手势
+				type: [Boolean, String],
+				default: true
+			}
+		},
+		data() {
+			return {
+				valueSync: "",
+				userMouseFristMove: true,
+				userRated: false,
+				userLastRate: 1
+			};
+		},
+		watch: {
+			value(newVal) {
+				this.valueSync = Number(newVal);
+			},
+			modelValue(newVal) {
+				this.valueSync = Number(newVal);
+			},
+		},
+		computed: {
+			stars() {
+				const value = this.valueSync ? this.valueSync : 0;
+				const starList = [];
+				const floorValue = Math.floor(value);
+				const ceilValue = Math.ceil(value);
+				for (let i = 0; i < this.max; i++) {
+					if (floorValue > i) {
+						starList.push({
+							activeWitch: "100%"
+						});
+					} else if (ceilValue - 1 === i) {
+						starList.push({
+							activeWitch: (value - floorValue) * 100 + "%"
+						});
+					} else {
+						starList.push({
+							activeWitch: "0"
+						});
+					}
+				}
+				return starList;
+			},
+
+			marginNumber() {
+				return Number(this.margin)
+			}
+		},
+		created() {
+			this.valueSync = Number(this.value || this.modelValue);
+			this._rateBoxLeft = 0
+			this._oldValue = null
+		},
+		mounted() {
+			setTimeout(() => {
+				this._getSize()
+			}, 100)
+			// #ifdef H5
+			this.PC = this.IsPC()
+			// #endif
+		},
+		methods: {
+			touchstart(e) {
+				// #ifdef H5
+				if (this.IsPC()) return
+				// #endif
+				if (this.readonly || this.disabled) return
+				const {
+					clientX,
+					screenX
+				} = e.changedTouches[0]
+				// TODO 做一下兼容,只有 Nvue 下才有 screenX,其他平台式 clientX
+				this._getRateCount(clientX || screenX)
+			},
+			touchmove(e) {
+				// #ifdef H5
+				if (this.IsPC()) return
+				// #endif
+				if (this.readonly || this.disabled || !this.touchable) return
+				const {
+					clientX,
+					screenX
+				} = e.changedTouches[0]
+				this._getRateCount(clientX || screenX)
+			},
+
+			/**
+			 * 兼容 PC @tian
+			 */
+
+			mousedown(e) {
+				// #ifdef H5
+				if (!this.IsPC()) return
+				if (this.readonly || this.disabled) return
+				const {
+					clientX,
+				} = e
+				this.userLastRate = this.valueSync
+				this._getRateCount(clientX)
+				this.userRated = true
+				// #endif
+			},
+			mousemove(e) {
+				// #ifdef H5
+				if (!this.IsPC()) return
+				if (this.userRated) return
+				if (this.userMouseFristMove) {
+					console.log('---mousemove----', this.valueSync);
+					this.userLastRate = this.valueSync
+					this.userMouseFristMove = false
+				}
+				if (this.readonly || this.disabled || !this.touchable) return
+				const {
+					clientX,
+				} = e
+				this._getRateCount(clientX)
+				// #endif
+			},
+			mouseleave(e) {
+				// #ifdef H5
+				if (!this.IsPC()) return
+				if (this.readonly || this.disabled || !this.touchable) return
+				if (this.userRated) {
+					this.userRated = false
+					return
+				}
+				this.valueSync = this.userLastRate
+				// #endif
+			},
+			// #ifdef H5
+			IsPC() {
+				var userAgentInfo = navigator.userAgent;
+				var Agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"];
+				var flag = true;
+				for (let v = 0; v < Agents.length - 1; v++) {
+					if (userAgentInfo.indexOf(Agents[v]) > 0) {
+						flag = false;
+						break;
+					}
+				}
+				return flag;
+			},
+			// #endif
+
+			/**
+			 * 获取星星个数
+			 */
+			_getRateCount(clientX) {
+				this._getSize()
+				const size = Number(this.size)
+				if (isNaN(size)) {
+					return new Error('size 属性只能设置为数字')
+				}
+				const rateMoveRange = clientX - this._rateBoxLeft
+				let index = parseInt(rateMoveRange / (size + this.marginNumber))
+				index = index < 0 ? 0 : index;
+				index = index > this.max ? this.max : index;
+				const range = parseInt(rateMoveRange - (size + this.marginNumber) * index);
+				let value = 0;
+				if (this._oldValue === index && !this.PC) return;
+				this._oldValue = index;
+				if (this.allowHalf) {
+					if (range > (size / 2)) {
+						value = index + 1
+					} else {
+						value = index + 0.5
+					}
+				} else {
+					value = index + 1
+				}
+
+				value = Math.max(0.5, Math.min(value, this.max))
+				this.valueSync = value
+				this._onChange()
+			},
+
+			/**
+			 * 触发动态修改
+			 */
+			_onChange() {
+
+				this.$emit("input", this.valueSync);
+				this.$emit("update:modelValue", this.valueSync);
+				this.$emit("change", {
+					value: this.valueSync
+				});
+			},
+			/**
+			 * 获取星星距离屏幕左侧距离
+			 */
+			_getSize() {
+				// #ifndef APP-NVUE
+				uni.createSelectorQuery()
+					.in(this)
+					.select('.uni-rate')
+					.boundingClientRect()
+					.exec(ret => {
+						if (ret) {
+							this._rateBoxLeft = ret[0].left
+						}
+					})
+				// #endif
+				// #ifdef APP-NVUE
+				dom.getComponentRect(this.$refs['uni-rate'], (ret) => {
+					const size = ret.size
+					if (size) {
+						this._rateBoxLeft = size.left
+					}
+				})
+				// #endif
+			}
+		}
+	};
+</script>
+
+<style lang="scss">
+	.uni-rate {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		line-height: 1;
+		font-size: 0;
+		flex-direction: row;
+		/* #ifdef H5 */
+		cursor: pointer;
+		/* #endif */
+	}
+
+	.uni-rate__icon {
+		position: relative;
+		line-height: 1;
+		font-size: 0;
+	}
+
+	.uni-rate__icon-on {
+		overflow: hidden;
+		position: absolute;
+		top: 0;
+		left: 0;
+		line-height: 1;
+		text-align: left;
+	}
+
+	.uni-cursor-not-allowed {
+		/* #ifdef H5 */
+		cursor: not-allowed !important;
+		/* #endif */
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-rate/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-rate/package.json
new file mode 100644
index 000000000..64e8e3320
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-rate/package.json
@@ -0,0 +1,88 @@
+{
+  "id": "uni-rate",
+  "displayName": "uni-rate 评分",
+  "version": "1.3.1",
+  "description": "Rate 评分组件,可自定义评分星星图标的大小、间隔、评分数。",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "评分"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": [
+			"uni-scss",
+			"uni-icons"
+		],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-rate/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-rate/readme.md
new file mode 100644
index 000000000..eae7b5ced
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-rate/readme.md
@@ -0,0 +1,12 @@
+
+
+## Rate 评分
+> **组件名:uni-rate**
+> 代码块: `uRate`
+> 关联组件:`uni-icons`
+
+
+评分组件,多用于购买商品后,对商品进行评价等场景
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-rate)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-row/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-row/changelog.md
new file mode 100644
index 000000000..5b465bc61
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-row/changelog.md
@@ -0,0 +1,10 @@
+## 1.0.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-row](https://uniapp.dcloud.io/component/uniui/uni-row)
+## 0.1.0(2021-07-13)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 0.0.4(2021-05-12)
+- 新增 组件示例地址
+## 0.0.3(2021-02-05)
+- 调整为uni_modules目录规范
+- 新增uni-row组件
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-row/components/uni-col/uni-col.vue b/yudao-ui-admin-uniapp/uni_modules/uni-row/components/uni-col/uni-col.vue
new file mode 100644
index 000000000..d5f372831
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-row/components/uni-col/uni-col.vue
@@ -0,0 +1,317 @@
+<template>
+	<!-- #ifndef APP-NVUE -->
+	<view :class="['uni-col', sizeClass, pointClassList]" :style="{
+		paddingLeft:`${Number(gutter)}rpx`,
+		paddingRight:`${Number(gutter)}rpx`,
+	}">
+		<slot></slot>
+	</view>
+	<!-- #endif -->
+	<!-- #ifdef APP-NVUE -->
+	<!-- 在nvue上,类名样式不生效,换为style -->
+	<!-- 设置right正值失效,设置 left 负值 -->
+	<view :class="['uni-col']" :style="{
+		paddingLeft:`${Number(gutter)}rpx`,
+		paddingRight:`${Number(gutter)}rpx`,
+		width:`${nvueWidth}rpx`,
+		position:'relative',
+		marginLeft:`${marginLeft}rpx`,
+		left:`${right === 0 ? left : -right}rpx`
+	}">
+		<slot></slot>
+	</view>
+	<!-- #endif -->
+</template>
+
+<script>
+	/**
+	 * Col	布局-列
+	 * @description	搭配uni-row使用,构建布局。
+	 * @tutorial	https://ext.dcloud.net.cn/plugin?id=3958
+	 *
+	 * @property	{span} type = Number 栅格占据的列数
+	 * 						默认 24
+	 * @property	{offset} type = Number 栅格左侧的间隔格数
+	 * @property	{push} type = Number 栅格向右移动格数
+	 * @property	{pull} type = Number 栅格向左移动格数
+	 * @property	{xs} type = [Number, Object] <768px 响应式栅格数或者栅格属性对象
+	 * 						@description	Number时表示在此屏幕宽度下,栅格占据的列数。Object时可配置多个描述{span: 4, offset: 4}
+	 * @property	{sm} type = [Number, Object] ≥768px 响应式栅格数或者栅格属性对象
+	 * 						@description	Number时表示在此屏幕宽度下,栅格占据的列数。Object时可配置多个描述{span: 4, offset: 4}
+	 * @property	{md} type = [Number, Object] ≥992px 响应式栅格数或者栅格属性对象
+	 * 						@description	Number时表示在此屏幕宽度下,栅格占据的列数。Object时可配置多个描述{span: 4, offset: 4}
+	 * @property	{lg} type = [Number, Object] ≥1200px 响应式栅格数或者栅格属性对象
+	 * 						@description	Number时表示在此屏幕宽度下,栅格占据的列数。Object时可配置多个描述{span: 4, offset: 4}
+	 * @property	{xl} type = [Number, Object] ≥1920px 响应式栅格数或者栅格属性对象
+	 * 						@description	Number时表示在此屏幕宽度下,栅格占据的列数。Object时可配置多个描述{span: 4, offset: 4}
+	 */
+	const ComponentClass = 'uni-col';
+
+	// -1 默认值,因为在微信小程序端只给Number会有默认值0
+	export default {
+		name: 'uniCol',
+		// #ifdef MP-WEIXIN
+		options: {
+			virtualHost: true // 在微信小程序中将组件节点渲染为虚拟节点,更加接近Vue组件的表现
+		},
+		// #endif
+		props: {
+			span: {
+				type: Number,
+				default: 24
+			},
+			offset: {
+				type: Number,
+				default: -1
+			},
+			pull: {
+				type: Number,
+				default: -1
+			},
+			push: {
+				type: Number,
+				default: -1
+			},
+			xs: [Number, Object],
+			sm: [Number, Object],
+			md: [Number, Object],
+			lg: [Number, Object],
+			xl: [Number, Object]
+		},
+		data() {
+			return {
+				gutter: 0,
+				sizeClass: '',
+				parentWidth: 0,
+				nvueWidth: 0,
+				marginLeft: 0,
+				right: 0,
+				left: 0
+			}
+		},
+		created() {
+			// 字节小程序中,在computed中读取$parent为undefined
+			let parent = this.$parent;
+
+			while (parent && parent.$options.componentName !== 'uniRow') {
+				parent = parent.$parent;
+			}
+
+			this.updateGutter(parent.gutter)
+			parent.$watch('gutter', (gutter) => {
+				this.updateGutter(gutter)
+			})
+
+			// #ifdef APP-NVUE
+			this.updateNvueWidth(parent.width)
+			parent.$watch('width', (width) => {
+				this.updateNvueWidth(width)
+			})
+			// #endif
+		},
+		computed: {
+			sizeList() {
+				let {
+					span,
+					offset,
+					pull,
+					push
+				} = this;
+
+				return {
+					span,
+					offset,
+					pull,
+					push
+				}
+			},
+			// #ifndef APP-NVUE
+			pointClassList() {
+				let classList = [];
+
+				['xs', 'sm', 'md', 'lg', 'xl'].forEach(point => {
+					const props = this[point];
+					if (typeof props === 'number') {
+						classList.push(`${ComponentClass}-${point}-${props}`)
+					} else if (typeof props === 'object' && props) {
+						Object.keys(props).forEach(pointProp => {
+							classList.push(
+								pointProp === 'span' ?
+								`${ComponentClass}-${point}-${props[pointProp]}` :
+								`${ComponentClass}-${point}-${pointProp}-${props[pointProp]}`
+							)
+						})
+					}
+				});
+
+				// 支付宝小程序使用 :class=[ ['a','b'] ],渲染错误
+				return classList.join(' ');
+			}
+			// #endif
+		},
+		methods: {
+			updateGutter(parentGutter) {
+				parentGutter = Number(parentGutter);
+				if (!isNaN(parentGutter)) {
+					this.gutter = parentGutter / 2
+				}
+			},
+			// #ifdef APP-NVUE
+			updateNvueWidth(width) {
+				// 用于在nvue端,span,offset,pull,push的计算
+				this.parentWidth = width;
+				['span', 'offset', 'pull', 'push'].forEach(size => {
+					const curSize = this[size];
+					if ((curSize || curSize === 0) && curSize !== -1) {
+						let RPX = 1 / 24 * curSize * width
+						RPX = Number(RPX);
+						switch (size) {
+							case 'span':
+								this.nvueWidth = RPX
+								break;
+							case 'offset':
+								this.marginLeft = RPX
+								break;
+							case 'pull':
+								this.right = RPX
+								break;
+							case 'push':
+								this.left = RPX
+								break;
+						}
+					}
+				});
+			}
+			// #endif
+		},
+		watch: {
+			sizeList: {
+				immediate: true,
+				handler(newVal) {
+					// #ifndef APP-NVUE
+					let classList = [];
+					for (let size in newVal) {
+						const curSize = newVal[size];
+						if ((curSize || curSize === 0) && curSize !== -1) {
+							classList.push(
+								size === 'span' ?
+								`${ComponentClass}-${curSize}` :
+								`${ComponentClass}-${size}-${curSize}`
+							)
+						}
+					}
+					// 支付宝小程序使用 :class=[ ['a','b'] ],渲染错误
+					this.sizeClass = classList.join(' ');
+					// #endif
+					// #ifdef APP-NVUE
+					this.updateNvueWidth(this.parentWidth);
+					// #endif
+				}
+			}
+		}
+	}
+</script>
+
+<style lang='scss' >
+	/* breakpoints */
+	$--sm: 768px !default;
+	$--md: 992px !default;
+	$--lg: 1200px !default;
+	$--xl: 1920px !default;
+
+	$breakpoints: ('xs' : (max-width: $--sm - 1),
+	'sm' : (min-width: $--sm),
+	'md' : (min-width: $--md),
+	'lg' : (min-width: $--lg),
+	'xl' : (min-width: $--xl));
+
+	$layout-namespace: ".uni-";
+	$col: $layout-namespace+"col";
+
+	@function getSize($size) {
+		/* TODO 1/24 * $size * 100 * 1%; 使用计算后的值,为了解决 vue3 控制台报错 */
+		@return 0.04166666666 * $size * 100 * 1%;
+	}
+
+	@mixin res($key, $map:$breakpoints) {
+		@if map-has-key($map, $key) {
+			@media screen and #{inspect(map-get($map,$key))} {
+				@content;
+			}
+		}
+
+		@else {
+			@warn "Undeinfed point: `#{$key}`";
+		}
+	}
+
+	/* #ifndef APP-NVUE */
+	#{$col} {
+		float: left;
+		box-sizing: border-box;
+	}
+
+	#{$col}-0 {
+		/* #ifdef APP-NVUE */
+		width: 0;
+		height: 0;
+		margin-top: 0;
+		margin-right: 0;
+		margin-bottom: 0;
+		margin-left: 0;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		display: none;
+		/* #endif */
+	}
+
+	@for $i from 0 through 24 {
+		#{$col}-#{$i} {
+			width: getSize($i);
+		}
+
+		#{$col}-offset-#{$i} {
+			margin-left: getSize($i);
+		}
+
+		#{$col}-pull-#{$i} {
+			position: relative;
+			right: getSize($i);
+		}
+
+		#{$col}-push-#{$i} {
+			position: relative;
+			left: getSize($i);
+		}
+	}
+
+	@each $point in map-keys($breakpoints) {
+		@include res($point) {
+			#{$col}-#{$point}-0 {
+				display: none;
+			}
+
+			@for $i from 0 through 24 {
+				#{$col}-#{$point}-#{$i} {
+					width: getSize($i);
+				}
+
+				#{$col}-#{$point}-offset-#{$i} {
+					margin-left: getSize($i);
+				}
+
+				#{$col}-#{$point}-pull-#{$i} {
+					position: relative;
+					right: getSize($i);
+				}
+
+				#{$col}-#{$point}-push-#{$i} {
+					position: relative;
+					left: getSize($i);
+				}
+			}
+		}
+	}
+
+	/* #endif */
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-row/components/uni-row/uni-row.vue b/yudao-ui-admin-uniapp/uni_modules/uni-row/components/uni-row/uni-row.vue
new file mode 100644
index 000000000..c7d93701e
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-row/components/uni-row/uni-row.vue
@@ -0,0 +1,190 @@
+<template>
+	<view :class="[ 'uni-row', typeClass , justifyClass, alignClass, ]" :style="{
+		marginLeft:`${Number(marginValue)}rpx`,
+		marginRight:`${Number(marginValue)}rpx`,
+	}">
+		<slot></slot>
+	</view>
+</template>
+
+<script>
+	const ComponentClass = 'uni-row';
+	const modifierSeparator = '--';
+	/**
+	 * Row	布局-行
+	 * @description	流式栅格系统,随着屏幕或视口分为 24 份,可以迅速简便地创建布局。
+	 * @tutorial	https://ext.dcloud.net.cn/plugin?id=3958
+	 *
+	 * @property	{gutter} type = Number 栅格间隔
+	 * @property	{justify} type = String flex 布局下的水平排列方式
+	 * 						可选	start/end/center/space-around/space-between	start
+	 * 						默认值	start
+	 * @property	{align} type = String flex 布局下的垂直排列方式
+	 * 						可选	top/middle/bottom
+	 * 						默认值	top
+	 * @property	{width} type = String|Number nvue下需要自行配置宽度用于计算
+	 * 						默认值 750
+	 */
+
+
+	export default {
+		name: 'uniRow',
+		componentName: 'uniRow',
+		// #ifdef MP-WEIXIN
+		options: {
+			virtualHost: true // 在微信小程序中将组件节点渲染为虚拟节点,更加接近Vue组件的表现,可使用flex布局
+		},
+		// #endif
+		props: {
+			type: String,
+			gutter: Number,
+			justify: {
+				type: String,
+				default: 'start'
+			},
+			align: {
+				type: String,
+				default: 'top'
+			},
+			// nvue如果使用span等属性,需要配置宽度
+			width: {
+				type: [String, Number],
+				default: 750
+			}
+		},
+		created() {
+			// #ifdef APP-NVUE
+			this.type = 'flex';
+			// #endif
+		},
+		computed: {
+			marginValue() {
+				// #ifndef APP-NVUE
+				if (this.gutter) {
+					return -(this.gutter / 2);
+				}
+				// #endif
+				return 0;
+			},
+			typeClass() {
+				return this.type === 'flex' ? `${ComponentClass + modifierSeparator}flex` : '';
+			},
+			justifyClass() {
+				return this.justify !== 'start' ? `${ComponentClass + modifierSeparator}flex-justify-${this.justify}` : ''
+			},
+			alignClass() {
+				return this.align !== 'top' ? `${ComponentClass + modifierSeparator}flex-align-${this.align}` : ''
+			}
+		}
+	};
+</script>
+
+<style lang="scss">
+	$layout-namespace: ".uni-";
+	$row:$layout-namespace+"row";
+	$modifier-separator: "--";
+
+	@mixin utils-clearfix {
+		$selector: &;
+
+		@at-root {
+
+			/* #ifndef APP-NVUE */
+			#{$selector}::before,
+			#{$selector}::after {
+				display: table;
+				content: "";
+			}
+
+			#{$selector}::after {
+				clear: both;
+			}
+
+			/* #endif */
+		}
+
+	}
+
+	@mixin utils-flex ($direction: row) {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: $direction;
+	}
+
+	@mixin set-flex($state) {
+		@at-root &-#{$state} {
+			@content
+		}
+	}
+
+	#{$row} {
+		position: relative;
+		flex-direction: row;
+
+		/* #ifdef APP-NVUE */
+		flex: 1;
+		/* #endif */
+
+		/* #ifndef APP-NVUE */
+		box-sizing: border-box;
+		/* #endif */
+
+		// 非nvue使用float布局
+		@include utils-clearfix;
+
+		// 在QQ、字节、百度小程序平台,编译后使用shadow dom,不可使用flex布局,使用float
+		@at-root {
+
+			/* #ifndef MP-QQ || MP-TOUTIAO || MP-BAIDU */
+			&#{$modifier-separator}flex {
+				@include utils-flex;
+				flex-wrap: wrap;
+				flex: 1;
+
+				&:before,
+				&:after {
+					/* #ifndef APP-NVUE */
+					display: none;
+					/* #endif */
+				}
+
+				@include set-flex(justify-center) {
+					justify-content: center;
+				}
+
+				@include set-flex(justify-end) {
+					justify-content: flex-end;
+				}
+
+				@include set-flex(justify-space-between) {
+					justify-content: space-between;
+				}
+
+				@include set-flex(justify-space-around) {
+					justify-content: space-around;
+				}
+
+				@include set-flex(align-middle) {
+					align-items: center;
+				}
+
+				@include set-flex(align-bottom) {
+					align-items: flex-end;
+				}
+			}
+
+			/* #endif */
+		}
+
+	}
+
+	// 字节、QQ配置后不生效
+	// 此处用法无法使用
+	/* #ifdef MP-WEIXIN || MP-TOUTIAO || MP-QQ */
+	:host {
+		display: block;
+	}
+
+	/* #endif */
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-row/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-row/package.json
new file mode 100644
index 000000000..3f52fa647
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-row/package.json
@@ -0,0 +1,87 @@
+{
+  "id": "uni-row",
+  "displayName": "uni-row 布局-行",
+  "version": "1.0.0",
+  "description": "流式栅格系统,随着屏幕或视口分为 24 份,可以迅速简便地创建布局。",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "栅格",
+    "布局",
+    "layout"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": ["uni-scss"],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "u"
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-row/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-row/readme.md
new file mode 100644
index 000000000..3c9c8b99e
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-row/readme.md
@@ -0,0 +1,10 @@
+## Layout 布局
+
+> **组件名 uni-row、uni-col**
+> 代码块: `uRow`、`uCol`
+
+
+流式栅格系统,随着屏幕或视口分为 24 份,可以迅速简便地创建布局。
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-row)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-scss/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-scss/changelog.md
new file mode 100644
index 000000000..b863bb0f5
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-scss/changelog.md
@@ -0,0 +1,8 @@
+## 1.0.3(2022-01-21)
+- 优化 组件示例
+## 1.0.2(2021-11-22)
+- 修复 / 符号在 vue 不同版本兼容问题引起的报错问题
+## 1.0.1(2021-11-22)
+- 修复 vue3中scss语法兼容问题
+## 1.0.0(2021-11-18)
+- init
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-scss/index.scss b/yudao-ui-admin-uniapp/uni_modules/uni-scss/index.scss
new file mode 100644
index 000000000..1744a5f98
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-scss/index.scss
@@ -0,0 +1 @@
+@import './styles/index.scss';
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-scss/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-scss/package.json
new file mode 100644
index 000000000..7cc0ccb73
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-scss/package.json
@@ -0,0 +1,82 @@
+{
+  "id": "uni-scss",
+  "displayName": "uni-scss 辅助样式",
+  "version": "1.0.3",
+  "description": "uni-sass是uni-ui提供的一套全局样式 ,通过一些简单的类名和sass变量,实现简单的页面布局操作,比如颜色、边距、圆角等。",
+  "keywords": [
+    "uni-scss",
+    "uni-ui",
+    "辅助样式"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": "^3.1.0"
+  },
+  "dcloudext": {
+    "category": [
+        "JS SDK",
+        "通用 SDK"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": [],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "u"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "n",
+          "联盟": "n"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-scss/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-scss/readme.md
new file mode 100644
index 000000000..b7d1c25f3
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-scss/readme.md
@@ -0,0 +1,4 @@
+`uni-sass` 是 `uni-ui`提供的一套全局样式 ,通过一些简单的类名和`sass`变量,实现简单的页面布局操作,比如颜色、边距、圆角等。
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-sass)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-scss/styles/index.scss b/yudao-ui-admin-uniapp/uni_modules/uni-scss/styles/index.scss
new file mode 100644
index 000000000..ffac4fecd
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-scss/styles/index.scss
@@ -0,0 +1,7 @@
+@import './setting/_variables.scss';
+@import './setting/_border.scss';
+@import './setting/_color.scss';
+@import './setting/_space.scss';
+@import './setting/_radius.scss';
+@import './setting/_text.scss';
+@import './setting/_styles.scss';
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-scss/styles/setting/_border.scss b/yudao-ui-admin-uniapp/uni_modules/uni-scss/styles/setting/_border.scss
new file mode 100644
index 000000000..12a11c322
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-scss/styles/setting/_border.scss
@@ -0,0 +1,3 @@
+.uni-border {
+	border: 1px $uni-border-1 solid;
+}
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-scss/styles/setting/_color.scss b/yudao-ui-admin-uniapp/uni_modules/uni-scss/styles/setting/_color.scss
new file mode 100644
index 000000000..1ededd94d
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-scss/styles/setting/_color.scss
@@ -0,0 +1,66 @@
+
+// TODO 暂时不需要 class ,需要用户使用变量实现 ,如果使用类名其实并不推荐
+// @mixin get-styles($k,$c) {
+// 	@if $k == size or $k == weight{
+// 		font-#{$k}:#{$c}
+// 	}@else{
+// 		#{$k}:#{$c}
+// 	}
+// }
+$uni-ui-color:(
+	// 主色
+	primary: $uni-primary,
+	primary-disable: $uni-primary-disable,
+	primary-light: $uni-primary-light,
+	// 辅助色
+	success: $uni-success,
+	success-disable: $uni-success-disable,
+	success-light: $uni-success-light,
+	warning: $uni-warning,
+	warning-disable: $uni-warning-disable,
+	warning-light: $uni-warning-light,
+	error: $uni-error,
+	error-disable: $uni-error-disable,
+	error-light: $uni-error-light,
+	info: $uni-info,
+	info-disable: $uni-info-disable,
+	info-light: $uni-info-light,
+	// 中性色
+	main-color: $uni-main-color,
+	base-color: $uni-base-color,
+	secondary-color: $uni-secondary-color,
+	extra-color: $uni-extra-color,
+	// 背景色
+	bg-color: $uni-bg-color,
+	// 边框颜色
+	border-1: $uni-border-1,
+	border-2: $uni-border-2,
+	border-3: $uni-border-3,
+	border-4: $uni-border-4,
+	// 黑色
+	black:$uni-black,
+	// 白色
+	white:$uni-white,
+	// 透明
+	transparent:$uni-transparent
+) !default;
+@each $key, $child in $uni-ui-color {
+	.uni-#{"" + $key} {
+		color: $child;
+	}
+	.uni-#{"" + $key}-bg {
+		background-color: $child;
+	}
+}
+.uni-shadow-sm {
+	box-shadow: $uni-shadow-sm;
+}
+.uni-shadow-base {
+	box-shadow: $uni-shadow-base;
+}
+.uni-shadow-lg {
+	box-shadow: $uni-shadow-lg;
+}
+.uni-mask {
+	background-color:$uni-mask;
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-scss/styles/setting/_radius.scss b/yudao-ui-admin-uniapp/uni_modules/uni-scss/styles/setting/_radius.scss
new file mode 100644
index 000000000..9a0428bb8
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-scss/styles/setting/_radius.scss
@@ -0,0 +1,55 @@
+@mixin radius($r,$d:null ,$important: false){
+  $radius-value:map-get($uni-radius, $r) if($important, !important, null);
+  // Key exists within the $uni-radius variable
+  @if (map-has-key($uni-radius, $r) and  $d){
+		@if $d == t {
+				border-top-left-radius:$radius-value;
+				border-top-right-radius:$radius-value;
+		}@else if $d == r {
+				border-top-right-radius:$radius-value;
+				border-bottom-right-radius:$radius-value;
+		}@else if $d == b {
+				border-bottom-left-radius:$radius-value;
+				border-bottom-right-radius:$radius-value;
+		}@else if $d == l {
+				border-top-left-radius:$radius-value;
+				border-bottom-left-radius:$radius-value;
+		}@else if $d == tl {
+				border-top-left-radius:$radius-value;
+		}@else if $d == tr {
+				border-top-right-radius:$radius-value;
+		}@else if $d == br {
+				border-bottom-right-radius:$radius-value;
+		}@else if $d == bl {
+				border-bottom-left-radius:$radius-value;
+		}
+  }@else{
+		border-radius:$radius-value;
+  }
+}
+
+@each $key, $child in $uni-radius {
+	@if($key){
+		.uni-radius-#{"" + $key} {
+				@include radius($key)
+		}
+	}@else{
+		.uni-radius {
+				@include radius($key)
+		}
+	}
+}
+
+@each $direction in t, r, b, l,tl, tr, br, bl {
+	@each $key, $child in $uni-radius {
+		@if($key){
+			.uni-radius-#{"" + $direction}-#{"" + $key} {
+				@include radius($key,$direction,false)
+			}
+		}@else{
+			.uni-radius-#{$direction} {
+				@include radius($key,$direction,false)
+			}
+		}
+	}
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-scss/styles/setting/_space.scss b/yudao-ui-admin-uniapp/uni_modules/uni-scss/styles/setting/_space.scss
new file mode 100644
index 000000000..3c8952897
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-scss/styles/setting/_space.scss
@@ -0,0 +1,56 @@
+
+@mixin fn($space,$direction,$size,$n) {
+	@if $n {
+		#{$space}-#{$direction}: #{$size*$uni-space-root}px
+	} @else {
+		 #{$space}-#{$direction}: #{-$size*$uni-space-root}px
+	}
+}
+@mixin get-styles($direction,$i,$space,$n){
+	@if $direction == t {
+		@include fn($space, top,$i,$n);
+	} 
+	@if $direction == r {
+		@include fn($space, right,$i,$n);
+	} 
+	@if $direction == b {
+		@include fn($space, bottom,$i,$n);
+	} 
+	@if $direction == l {
+	 @include fn($space, left,$i,$n);
+	} 
+	@if $direction == x {
+		@include fn($space, left,$i,$n);
+		@include fn($space, right,$i,$n);
+	} 
+	@if $direction == y {
+		@include fn($space, top,$i,$n);
+		@include fn($space, bottom,$i,$n);
+	} 
+	@if $direction == a {
+		@if $n {
+			#{$space}:#{$i*$uni-space-root}px;
+		} @else {
+			#{$space}:#{-$i*$uni-space-root}px;
+		}
+	} 
+}
+
+@each $orientation in m,p {
+	$space: margin;
+	@if $orientation == m {
+		$space: margin;
+	} @else {
+		$space: padding;
+	}
+	@for $i from 0 through 16 {
+		@each $direction in t, r, b, l, x, y, a {
+			.uni-#{$orientation}#{$direction}-#{$i} { 
+				@include  get-styles($direction,$i,$space,true);
+			} 
+			.uni-#{$orientation}#{$direction}-n#{$i} { 
+				@include  get-styles($direction,$i,$space,false);
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-scss/styles/setting/_styles.scss b/yudao-ui-admin-uniapp/uni_modules/uni-scss/styles/setting/_styles.scss
new file mode 100644
index 000000000..689afec66
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-scss/styles/setting/_styles.scss
@@ -0,0 +1,167 @@
+/* #ifndef APP-NVUE */
+
+$-color-white:#fff;
+$-color-black:#000;
+@mixin base-style($color) {
+	color: #fff;
+	background-color: $color;
+	border-color: mix($-color-black, $color, 8%);
+	&:not([hover-class]):active {
+		background: mix($-color-black, $color, 10%);
+		border-color: mix($-color-black, $color, 20%);
+		color: $-color-white;
+		outline: none;
+	}
+}
+@mixin is-color($color) {
+	@include base-style($color);
+	&[loading] {
+		@include base-style($color);
+		&::before {
+			margin-right:5px;
+		}
+	}
+	&[disabled] {
+	  &,
+		&[loading],
+	  &:not([hover-class]):active {
+	    color: $-color-white;
+			border-color: mix(darken($color,10%), $-color-white);
+	    background-color: mix($color, $-color-white);
+	  }
+	}
+
+}
+@mixin base-plain-style($color) {
+	color:$color;
+	background-color: mix($-color-white, $color, 90%);
+	border-color: mix($-color-white, $color, 70%);
+	&:not([hover-class]):active {
+	  background: mix($-color-white, $color, 80%);
+	  color: $color;
+	  outline: none;
+		border-color: mix($-color-white, $color, 50%);
+	}
+}
+@mixin is-plain($color){
+	&[plain] {
+		@include base-plain-style($color);
+		&[loading] {
+			@include base-plain-style($color);
+			&::before {
+				margin-right:5px;
+			}
+		}
+		&[disabled] {
+		  &,
+		  &:active {
+		    color: mix($-color-white, $color, 40%);
+		    background-color: mix($-color-white, $color, 90%);
+				border-color: mix($-color-white, $color, 80%);
+		  }
+		}
+	}
+}
+
+
+.uni-btn {
+	margin: 5px;
+	color: #393939;
+	border:1px solid #ccc;
+	font-size: 16px;
+	font-weight: 200;
+	background-color: #F9F9F9;
+	// TODO 暂时处理边框隐藏一边的问题
+	overflow: visible;
+	&::after{
+		border: none;
+	}
+
+	&:not([type]),&[type=default] {
+		color: #999;
+		&[loading] {
+			background: none;
+			&::before {
+				margin-right:5px;
+			}
+		}
+
+
+
+		&[disabled]{
+			color: mix($-color-white, #999, 60%);
+		  &,
+			&[loading],
+		  &:active {
+				color: mix($-color-white, #999, 60%);
+		    background-color: mix($-color-white,$-color-black , 98%);
+				border-color: mix($-color-white,  #999, 85%);
+		  }
+		}
+
+		&[plain] {
+			color: #999;
+			background: none;
+			border-color: $uni-border-1;
+			&:not([hover-class]):active {
+				background: none;
+			  color: mix($-color-white, $-color-black, 80%);
+				border-color: mix($-color-white, $-color-black, 90%);
+			  outline: none;
+			}
+			&[disabled]{
+			  &,
+				&[loading],
+			  &:active {
+			    background: none;
+					color: mix($-color-white, #999, 60%);
+					border-color: mix($-color-white,  #999, 85%);
+			  }
+			}
+		}
+	}
+
+	&:not([hover-class]):active {
+	  color: mix($-color-white, $-color-black, 50%);
+	}
+
+	&[size=mini] {
+		font-size: 16px;
+		font-weight: 200;
+		border-radius: 8px;
+	}
+
+
+
+	&.uni-btn-small {
+		font-size: 14px;
+	}
+	&.uni-btn-mini {
+		font-size: 12px;
+	}
+
+	&.uni-btn-radius {
+		border-radius: 999px;
+	}
+	&[type=primary] {
+		@include is-color($uni-primary);
+		@include is-plain($uni-primary)
+	}
+	&[type=success] {
+		@include is-color($uni-success);
+		@include is-plain($uni-success)
+	}
+	&[type=error] {
+		@include is-color($uni-error);
+		@include is-plain($uni-error)
+	}
+	&[type=warning] {
+		@include is-color($uni-warning);
+		@include is-plain($uni-warning)
+	}
+	&[type=info] {
+		@include is-color($uni-info);
+		@include is-plain($uni-info)
+	}
+}
+/* #endif */
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-scss/styles/setting/_text.scss b/yudao-ui-admin-uniapp/uni_modules/uni-scss/styles/setting/_text.scss
new file mode 100644
index 000000000..a34d08f3f
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-scss/styles/setting/_text.scss
@@ -0,0 +1,24 @@
+@mixin get-styles($k,$c) {
+	@if $k == size or $k == weight{
+		font-#{$k}:#{$c}
+	}@else{
+		#{$k}:#{$c}
+	}
+}
+
+@each $key, $child in $uni-headings {
+	/* #ifndef APP-NVUE */
+	.uni-#{$key} {
+		@each $k, $c in $child {
+			@include get-styles($k,$c)
+		}
+	}
+	/* #endif */
+	/* #ifdef APP-NVUE */
+	.container .uni-#{$key} {
+		@each $k, $c in $child {
+			@include get-styles($k,$c)
+		}
+	}
+	/* #endif */
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-scss/styles/setting/_variables.scss b/yudao-ui-admin-uniapp/uni_modules/uni-scss/styles/setting/_variables.scss
new file mode 100644
index 000000000..557d3d7c9
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-scss/styles/setting/_variables.scss
@@ -0,0 +1,146 @@
+// @use "sass:math";
+@import  '../tools/functions.scss';
+// 间距基础倍数
+$uni-space-root: 2 !default;
+// 边框半径默认值
+$uni-radius-root:5px !default;
+$uni-radius: () !default;
+// 边框半径断点
+$uni-radius: map-deep-merge(
+  (
+    0: 0,
+		// TODO 当前版本暂时不支持 sm 属性
+    // 'sm': math.div($uni-radius-root, 2),
+    null: $uni-radius-root,
+    'lg': $uni-radius-root * 2,
+    'xl': $uni-radius-root * 6,
+    'pill': 9999px,
+    'circle': 50%
+  ),
+  $uni-radius
+);
+// 字体家族
+$body-font-family: 'Roboto', sans-serif !default;
+// 文本
+$heading-font-family: $body-font-family !default;
+$uni-headings: () !default;
+$letterSpacing: -0.01562em;
+$uni-headings: map-deep-merge(
+  (
+    'h1': (
+      size: 32px,
+			weight: 300,
+			line-height: 50px,
+			// letter-spacing:-0.01562em
+    ),
+    'h2': (
+      size: 28px,
+      weight: 300,
+      line-height: 40px,
+      // letter-spacing: -0.00833em
+    ),
+    'h3': (
+      size: 24px,
+      weight: 400,
+      line-height: 32px,
+      // letter-spacing: normal
+    ),
+    'h4': (
+      size: 20px,
+      weight: 400,
+      line-height: 30px,
+      // letter-spacing: 0.00735em
+    ),
+    'h5': (
+      size: 16px,
+      weight: 400,
+      line-height: 24px,
+      // letter-spacing: normal
+    ),
+    'h6': (
+      size: 14px,
+      weight: 500,
+      line-height: 18px,
+      // letter-spacing: 0.0125em
+    ),
+    'subtitle': (
+      size: 12px,
+      weight: 400,
+      line-height: 20px,
+      // letter-spacing: 0.00937em
+    ),
+    'body': (
+      font-size: 14px,
+			font-weight: 400,
+			line-height: 22px,
+			// letter-spacing: 0.03125em
+    ),
+    'caption': (
+      'size': 12px,
+      'weight': 400,
+      'line-height': 20px,
+      // 'letter-spacing': 0.03333em,
+      // 'text-transform': false
+    )
+  ),
+  $uni-headings
+);
+
+
+
+// 主色
+$uni-primary: #2979ff !default;
+$uni-primary-disable:lighten($uni-primary,20%) !default;
+$uni-primary-light: lighten($uni-primary,25%) !default;
+
+// 辅助色
+// 除了主色外的场景色,需要在不同的场景中使用(例如危险色表示危险的操作)。
+$uni-success: #18bc37 !default;
+$uni-success-disable:lighten($uni-success,20%) !default;
+$uni-success-light: lighten($uni-success,25%) !default;
+
+$uni-warning: #f3a73f !default;
+$uni-warning-disable:lighten($uni-warning,20%) !default;
+$uni-warning-light: lighten($uni-warning,25%) !default;
+
+$uni-error: #e43d33 !default;
+$uni-error-disable:lighten($uni-error,20%) !default;
+$uni-error-light: lighten($uni-error,25%) !default;
+
+$uni-info: #8f939c !default;
+$uni-info-disable:lighten($uni-info,20%) !default;
+$uni-info-light: lighten($uni-info,25%) !default;
+
+// 中性色
+// 中性色用于文本、背景和边框颜色。通过运用不同的中性色,来表现层次结构。
+$uni-main-color: #3a3a3a !default; 			// 主要文字
+$uni-base-color: #6a6a6a !default;			// 常规文字
+$uni-secondary-color: #909399 !default;	// 次要文字
+$uni-extra-color: #c7c7c7 !default;			// 辅助说明
+
+// 边框颜色
+$uni-border-1: #F0F0F0 !default;
+$uni-border-2: #EDEDED !default;
+$uni-border-3: #DCDCDC !default;
+$uni-border-4: #B9B9B9 !default;
+
+// 常规色
+$uni-black: #000000 !default;
+$uni-white: #ffffff !default;
+$uni-transparent: rgba($color: #000000, $alpha: 0) !default;
+
+// 背景色
+$uni-bg-color: #f7f7f7 !default;
+
+/* 水平间距 */
+$uni-spacing-sm: 8px !default;
+$uni-spacing-base: 15px !default;
+$uni-spacing-lg: 30px !default;
+
+// 阴影
+$uni-shadow-sm:0 0 5px rgba($color: #d8d8d8, $alpha: 0.5) !default;
+$uni-shadow-base:0 1px 8px 1px rgba($color: #a5a5a5, $alpha: 0.2) !default;
+$uni-shadow-lg:0px 1px 10px 2px rgba($color: #a5a4a4, $alpha: 0.5) !default;
+
+// 蒙版
+$uni-mask: rgba($color: #000000, $alpha: 0.4) !default;
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-scss/styles/tools/functions.scss b/yudao-ui-admin-uniapp/uni_modules/uni-scss/styles/tools/functions.scss
new file mode 100644
index 000000000..ac6f63e53
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-scss/styles/tools/functions.scss
@@ -0,0 +1,19 @@
+// 合并 map
+@function map-deep-merge($parent-map, $child-map){
+	$result: $parent-map;
+	@each $key, $child in $child-map {
+		$parent-has-key: map-has-key($result, $key);
+		$parent-value: map-get($result, $key);
+		$parent-type: type-of($parent-value);
+		$child-type: type-of($child);
+		$parent-is-map: $parent-type == map;
+		$child-is-map: $child-type == map;
+			
+		@if (not $parent-has-key) or ($parent-type != $child-type) or (not ($parent-is-map and $child-is-map)){
+			$result: map-merge($result, ( $key: $child ));
+		}@else {
+			$result: map-merge($result, ( $key: map-deep-merge($parent-value, $child) ));
+		}
+	}
+	@return $result;
+};
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-scss/theme.scss b/yudao-ui-admin-uniapp/uni_modules/uni-scss/theme.scss
new file mode 100644
index 000000000..80ee62f7d
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-scss/theme.scss
@@ -0,0 +1,31 @@
+// 间距基础倍数
+$uni-space-root: 2;
+// 边框半径默认值
+$uni-radius-root:5px;
+// 主色
+$uni-primary: #2979ff;
+// 辅助色
+$uni-success: #4cd964;
+// 警告色
+$uni-warning: #f0ad4e;
+// 错误色
+$uni-error: #dd524d;
+// 描述色
+$uni-info: #909399;
+// 中性色
+$uni-main-color: #303133;
+$uni-base-color: #606266;
+$uni-secondary-color: #909399;
+$uni-extra-color: #C0C4CC;
+// 背景色
+$uni-bg-color: #f5f5f5;
+// 边框颜色
+$uni-border-1: #DCDFE6;
+$uni-border-2: #E4E7ED;
+$uni-border-3: #EBEEF5;
+$uni-border-4: #F2F6FC;
+
+// 常规色
+$uni-black: #000000;
+$uni-white: #ffffff;
+$uni-transparent: rgba($color: #000000, $alpha: 0);
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-scss/variables.scss b/yudao-ui-admin-uniapp/uni_modules/uni-scss/variables.scss
new file mode 100644
index 000000000..1c062d42b
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-scss/variables.scss
@@ -0,0 +1,62 @@
+@import './styles/setting/_variables.scss';
+// 间距基础倍数
+$uni-space-root: 2;
+// 边框半径默认值
+$uni-radius-root:5px;
+
+// 主色
+$uni-primary: #2979ff;
+$uni-primary-disable:mix(#fff,$uni-primary,50%);
+$uni-primary-light: mix(#fff,$uni-primary,80%);
+
+// 辅助色
+// 除了主色外的场景色,需要在不同的场景中使用(例如危险色表示危险的操作)。
+$uni-success: #18bc37;
+$uni-success-disable:mix(#fff,$uni-success,50%);
+$uni-success-light: mix(#fff,$uni-success,80%);
+
+$uni-warning: #f3a73f;
+$uni-warning-disable:mix(#fff,$uni-warning,50%);
+$uni-warning-light: mix(#fff,$uni-warning,80%);
+
+$uni-error: #e43d33;
+$uni-error-disable:mix(#fff,$uni-error,50%);
+$uni-error-light: mix(#fff,$uni-error,80%);
+
+$uni-info: #8f939c;
+$uni-info-disable:mix(#fff,$uni-info,50%);
+$uni-info-light: mix(#fff,$uni-info,80%);
+
+// 中性色
+// 中性色用于文本、背景和边框颜色。通过运用不同的中性色,来表现层次结构。
+$uni-main-color: #3a3a3a; 			// 主要文字
+$uni-base-color: #6a6a6a;			// 常规文字
+$uni-secondary-color: #909399;	// 次要文字
+$uni-extra-color: #c7c7c7;			// 辅助说明
+
+// 边框颜色
+$uni-border-1: #F0F0F0;
+$uni-border-2: #EDEDED;
+$uni-border-3: #DCDCDC;
+$uni-border-4: #B9B9B9;
+
+// 常规色
+$uni-black: #000000;
+$uni-white: #ffffff;
+$uni-transparent: rgba($color: #000000, $alpha: 0);
+
+// 背景色
+$uni-bg-color: #f7f7f7;
+
+/* 水平间距 */
+$uni-spacing-sm: 8px;
+$uni-spacing-base: 15px;
+$uni-spacing-lg: 30px;
+
+// 阴影
+$uni-shadow-sm:0 0 5px rgba($color: #d8d8d8, $alpha: 0.5);
+$uni-shadow-base:0 1px 8px 1px rgba($color: #a5a5a5, $alpha: 0.2);
+$uni-shadow-lg:0px 1px 10px 2px rgba($color: #a5a4a4, $alpha: 0.5);
+
+// 蒙版
+$uni-mask: rgba($color: #000000, $alpha: 0.4);
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-search-bar/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-search-bar/changelog.md
new file mode 100644
index 000000000..b41fdd3ba
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-search-bar/changelog.md
@@ -0,0 +1,33 @@
+## 1.2.3(2022-05-24)
+- 新增 readonly 属性,组件只读
+## 1.2.2(2022-05-06)
+- 修复  vue3 input 事件不生效的bug
+## 1.2.1(2022-05-06)
+- 修复 多余代码导致的bug
+## 1.2.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-search-bar](https://uniapp.dcloud.io/component/uniui/uni-search-bar)
+## 1.1.2(2021-08-30)
+- 修复 value 属性与 modelValue 属性不兼容的Bug
+## 1.1.1(2021-08-24)
+- 新增 支持国际化
+## 1.1.0(2021-07-30)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.0.9(2021-05-12)
+- 新增 项目示例地址
+## 1.0.8(2021-04-21)
+- 优化 添加依赖 uni-icons, 导入后自动下载依赖
+## 1.0.7(2021-04-15)
+- uni-ui 新增 uni-search-bar 的 focus 事件
+
+## 1.0.6(2021-02-05)
+- 优化 组件引用关系,通过uni_modules引用组件
+
+## 1.0.5(2021-02-05)
+- 调整为uni_modules目录规范
+- 新增 支持双向绑定
+- 更改 input 事件的返回值,e={value:Number} --> e=value
+- 新增 支持图标插槽
+- 新增 支持 clear、blur 事件
+- 新增 支持 focus 属性
+- 去掉组件背景色
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-search-bar/components/uni-search-bar/i18n/en.json b/yudao-ui-admin-uniapp/uni_modules/uni-search-bar/components/uni-search-bar/i18n/en.json
new file mode 100644
index 000000000..dd083a535
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-search-bar/components/uni-search-bar/i18n/en.json
@@ -0,0 +1,4 @@
+{
+	"uni-search-bar.cancel": "cancel",
+	"uni-search-bar.placeholder": "Search enter content"
+}
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-search-bar/components/uni-search-bar/i18n/index.js b/yudao-ui-admin-uniapp/uni_modules/uni-search-bar/components/uni-search-bar/i18n/index.js
new file mode 100644
index 000000000..de7509c87
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-search-bar/components/uni-search-bar/i18n/index.js
@@ -0,0 +1,8 @@
+import en from './en.json'
+import zhHans from './zh-Hans.json'
+import zhHant from './zh-Hant.json'
+export default {
+	en,
+	'zh-Hans': zhHans,
+	'zh-Hant': zhHant
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hans.json b/yudao-ui-admin-uniapp/uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hans.json
new file mode 100644
index 000000000..d4e5c120c
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hans.json
@@ -0,0 +1,4 @@
+{
+	"uni-search-bar.cancel": "cancel",
+	"uni-search-bar.placeholder": "请输入搜索内容"
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hant.json b/yudao-ui-admin-uniapp/uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hant.json
new file mode 100644
index 000000000..318b6ef1b
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-search-bar/components/uni-search-bar/i18n/zh-Hant.json
@@ -0,0 +1,4 @@
+{
+	"uni-search-bar.cancel": "cancel",
+	"uni-search-bar.placeholder": "請輸入搜索內容"
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-search-bar/components/uni-search-bar/uni-search-bar.vue b/yudao-ui-admin-uniapp/uni_modules/uni-search-bar/components/uni-search-bar/uni-search-bar.vue
new file mode 100644
index 000000000..5a518a8cc
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-search-bar/components/uni-search-bar/uni-search-bar.vue
@@ -0,0 +1,298 @@
+<template>
+	<view class="uni-searchbar">
+		<view :style="{borderRadius:radius+'px',backgroundColor: bgColor}" class="uni-searchbar__box"
+			@click="searchClick">
+			<view class="uni-searchbar__box-icon-search">
+				<slot name="searchIcon">
+					<uni-icons color="#c0c4cc" size="18" type="search" />
+				</slot>
+			</view>
+			<input v-if="show || searchVal" :focus="showSync" :disabled="readonly" :placeholder="placeholderText" :maxlength="maxlength"
+				class="uni-searchbar__box-search-input" confirm-type="search" type="text" v-model="searchVal"
+				@confirm="confirm" @blur="blur" @focus="emitFocus" />
+			<text v-else class="uni-searchbar__text-placeholder">{{ placeholder }}</text>
+			<view v-if="show && (clearButton==='always'||clearButton==='auto'&&searchVal!=='') &&!readonly"
+				class="uni-searchbar__box-icon-clear" @click="clear">
+				<slot name="clearIcon">
+					<uni-icons color="#c0c4cc" size="20" type="clear" />
+				</slot>
+			</view>
+		</view>
+		<text @click="cancel" class="uni-searchbar__cancel"
+			v-if="cancelButton ==='always' || show && cancelButton ==='auto'">{{cancelTextI18n}}</text>
+	</view>
+</template>
+
+<script>
+	import {
+		initVueI18n
+	} from '@dcloudio/uni-i18n'
+	import messages from './i18n/index.js'
+	const {
+		t
+	} = initVueI18n(messages)
+
+	/**
+	 * SearchBar 搜索栏
+	 * @description 搜索栏组件,通常用于搜索商品、文章等
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=866
+	 * @property {Number} radius 搜索栏圆角
+	 * @property {Number} maxlength 输入最大长度
+	 * @property {String} placeholder 搜索栏Placeholder
+	 * @property {String} clearButton = [always|auto|none] 是否显示清除按钮
+	 * 	@value always 一直显示
+	 * 	@value auto 输入框不为空时显示
+	 * 	@value none 一直不显示
+	 * @property {String} cancelButton = [always|auto|none] 是否显示取消按钮
+	 * 	@value always 一直显示
+	 * 	@value auto 输入框不为空时显示
+	 * 	@value none 一直不显示
+	 * @property {String} cancelText 取消按钮的文字
+	 * @property {String} bgColor 输入框背景颜色
+	 * @property {Boolean} focus 是否自动聚焦
+	 * @property {Boolean} readonly 组件只读,不能有任何操作,只做展示
+	 * @event {Function} confirm uniSearchBar 的输入框 confirm 事件,返回参数为uniSearchBar的value,e={value:Number}
+	 * @event {Function} input uniSearchBar 的 value 改变时触发事件,返回参数为uniSearchBar的value,e=value
+	 * @event {Function} cancel 点击取消按钮时触发事件,返回参数为uniSearchBar的value,e={value:Number}
+	 * @event {Function} clear 点击清除按钮时触发事件,返回参数为uniSearchBar的value,e={value:Number}
+	 * @event {Function} blur input失去焦点时触发事件,返回参数为uniSearchBar的value,e={value:Number}
+	 */
+
+	export default {
+		name: "UniSearchBar",
+		emits: ['input', 'update:modelValue', 'clear', 'cancel', 'confirm', 'blur', 'focus'],
+		props: {
+			placeholder: {
+				type: String,
+				default: ""
+			},
+			radius: {
+				type: [Number, String],
+				default: 5
+			},
+			clearButton: {
+				type: String,
+				default: "auto"
+			},
+			cancelButton: {
+				type: String,
+				default: "auto"
+			},
+			cancelText: {
+				type: String,
+				default: '取消'
+			},
+			bgColor: {
+				type: String,
+				default: "#F8F8F8"
+			},
+			maxlength: {
+				type: [Number, String],
+				default: 100
+			},
+			value: {
+				type: [Number, String],
+				default: ""
+			},
+			modelValue: {
+				type: [Number, String],
+				default: ""
+			},
+			focus: {
+				type: Boolean,
+				default: false
+			},
+			readonly: {
+				type: Boolean,
+				default: false
+			}
+		},
+		data() {
+			return {
+				show: false,
+				showSync: false,
+				searchVal: ''
+			}
+		},
+		computed: {
+			cancelTextI18n() {
+				return this.cancelText || t("uni-search-bar.cancel")
+			},
+			placeholderText() {
+				return this.placeholder || t("uni-search-bar.placeholder")
+			}
+		},
+		watch: {
+			// #ifndef VUE3
+			value: {
+				immediate: true,
+				handler(newVal) {
+					this.searchVal = newVal
+					if (newVal) {
+						this.show = true
+					}
+				}
+			},
+			// #endif
+			// #ifdef VUE3
+			modelValue: {
+				immediate: true,
+				handler(newVal) {
+					this.searchVal = newVal
+					if (newVal) {
+						this.show = true
+					}
+				}
+			},
+			// #endif
+			focus: {
+				immediate: true,
+				handler(newVal) {
+					if (newVal) {
+						if(this.readonly) return
+						this.show = true;
+						this.$nextTick(() => {
+							this.showSync = true
+						})
+					}
+				}
+			},
+			searchVal(newVal, oldVal) {
+				this.$emit("input", newVal)
+				// #ifdef VUE3
+				this.$emit("update:modelValue", newVal)
+				// #endif
+			}
+		},
+		methods: {
+			searchClick() {
+				if(this.readonly) return
+				if (this.show) {
+					return
+				}
+				this.show = true;
+				this.$nextTick(() => {
+					this.showSync = true
+				})
+			},
+			clear() {
+				this.$emit("clear", {
+					value: this.searchVal
+				})
+				this.searchVal = ""
+			},
+			cancel() {
+				if(this.readonly) return
+				this.$emit("cancel", {
+					value: this.searchVal
+				});
+				this.searchVal = ""
+				this.show = false
+				this.showSync = false
+				// #ifndef APP-PLUS
+				uni.hideKeyboard()
+				// #endif
+				// #ifdef APP-PLUS
+				plus.key.hideSoftKeybord()
+				// #endif
+			},
+			confirm() {
+				// #ifndef APP-PLUS
+				uni.hideKeyboard();
+				// #endif
+				// #ifdef APP-PLUS
+				plus.key.hideSoftKeybord()
+				// #endif
+				this.$emit("confirm", {
+					value: this.searchVal
+				})
+			},
+			blur() {
+				// #ifndef APP-PLUS
+				uni.hideKeyboard();
+				// #endif
+				// #ifdef APP-PLUS
+				plus.key.hideSoftKeybord()
+				// #endif
+				this.$emit("blur", {
+					value: this.searchVal
+				})
+			},
+			emitFocus(e) {
+				this.$emit("focus", e.detail)
+			}
+		}
+	};
+</script>
+
+<style lang="scss">
+	$uni-searchbar-height: 36px;
+
+	.uni-searchbar {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		position: relative;
+		padding: 10px;
+		// background-color: #fff;
+	}
+
+	.uni-searchbar__box {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		box-sizing: border-box;
+		/* #endif */
+		overflow: hidden;
+		position: relative;
+		flex: 1;
+		justify-content: center;
+		flex-direction: row;
+		align-items: center;
+		height: $uni-searchbar-height;
+		padding: 5px 8px 5px 0px;
+	}
+
+	.uni-searchbar__box-icon-search {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		// width: 32px;
+		padding: 0 8px;
+		justify-content: center;
+		align-items: center;
+		color: #B3B3B3;
+	}
+
+	.uni-searchbar__box-search-input {
+		flex: 1;
+		font-size: 14px;
+		color: #333;
+	}
+
+	.uni-searchbar__box-icon-clear {
+		align-items: center;
+		line-height: 24px;
+		padding-left: 8px;
+		/* #ifdef H5 */
+		cursor: pointer;
+		/* #endif */
+	}
+
+	.uni-searchbar__text-placeholder {
+		font-size: 14px;
+		color: #B3B3B3;
+		margin-left: 5px;
+	}
+
+	.uni-searchbar__cancel {
+		padding-left: 10px;
+		line-height: $uni-searchbar-height;
+		font-size: 14px;
+		color: #333333;
+		/* #ifdef H5 */
+		cursor: pointer;
+		/* #endif */
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-search-bar/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-search-bar/package.json
new file mode 100644
index 000000000..9352c574f
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-search-bar/package.json
@@ -0,0 +1,89 @@
+{
+  "id": "uni-search-bar",
+  "displayName": "uni-search-bar 搜索栏",
+  "version": "1.2.3",
+  "description": "搜索栏组件,通常用于搜索商品、文章等",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "搜索框",
+    "搜索栏"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": [
+			"uni-scss",
+			"uni-icons"
+		],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-search-bar/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-search-bar/readme.md
new file mode 100644
index 000000000..253092f0b
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-search-bar/readme.md
@@ -0,0 +1,14 @@
+
+
+## SearchBar 搜索栏
+
+> **组件名:uni-search-bar**
+> 代码块: `uSearchBar`
+
+
+搜索栏组件
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-search-bar)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
+
+
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-segmented-control/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-segmented-control/changelog.md
new file mode 100644
index 000000000..a44385d7c
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-segmented-control/changelog.md
@@ -0,0 +1,9 @@
+## 1.2.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-segmented-control](https://uniapp.dcloud.io/component/uniui/uni-segmented-control)
+## 1.1.0(2021-07-30)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.0.5(2021-05-12)
+- 新增 项目示例地址
+## 1.0.4(2021-02-05)
+- 调整为uni_modules目录规范
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-segmented-control/components/uni-segmented-control/uni-segmented-control.vue b/yudao-ui-admin-uniapp/uni_modules/uni-segmented-control/components/uni-segmented-control/uni-segmented-control.vue
new file mode 100644
index 000000000..ddbcf8849
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-segmented-control/components/uni-segmented-control/uni-segmented-control.vue
@@ -0,0 +1,145 @@
+<template>
+	<view :class="[styleType === 'text'?'segmented-control--text' : 'segmented-control--button' ]"
+		:style="{ borderColor: styleType === 'text' ? '' : activeColor }" class="segmented-control">
+		<view v-for="(item, index) in values" :class="[ styleType === 'text' ? '': 'segmented-control__item--button',
+		index === currentIndex&&styleType === 'button' ? 'segmented-control__item--button--active': '',
+		index === 0&&styleType === 'button' ? 'segmented-control__item--button--first': '',
+			index === values.length - 1&&styleType === 'button' ? 'segmented-control__item--button--last': '' ]" :key="index"
+			:style="{ backgroundColor: index === currentIndex && styleType === 'button' ? activeColor : '',borderColor: index === currentIndex&&styleType === 'text'||styleType === 'button'?activeColor:'transparent' }"
+			class="segmented-control__item" @click="_onClick(index)">
+			<view>
+				<text :style="{color:
+				    index === currentIndex
+				      ? styleType === 'text'
+				        ? activeColor
+				        : '#fff'
+				      : styleType === 'text'
+				        ? '#000'
+				        : activeColor}" class="segmented-control__text" :class="styleType === 'text' && index === currentIndex ? 'segmented-control__item--text': ''">{{ item }}</text>
+			</view>
+
+		</view>
+	</view>
+</template>
+
+<script>
+	/**
+	 * SegmentedControl 分段器
+	 * @description 用作不同视图的显示
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=54
+	 * @property {Number} current 当前选中的tab索引值,从0计数
+	 * @property {String} styleType = [button|text] 分段器样式类型
+	 * 	@value button 按钮类型
+	 * 	@value text 文字类型
+	 * @property {String} activeColor 选中的标签背景色与边框颜色
+	 * @property {Array} values 选项数组
+	 * @event {Function} clickItem 组件触发点击事件时触发,e={currentIndex}
+	 */
+
+	export default {
+		name: 'UniSegmentedControl',
+		emits: ['clickItem'],
+		props: {
+			current: {
+				type: Number,
+				default: 0
+			},
+			values: {
+				type: Array,
+				default () {
+					return []
+				}
+			},
+			activeColor: {
+				type: String,
+				default: '#2979FF'
+			},
+			styleType: {
+				type: String,
+				default: 'button'
+			}
+		},
+		data() {
+			return {
+				currentIndex: 0
+			}
+		},
+		watch: {
+			current(val) {
+				if (val !== this.currentIndex) {
+					this.currentIndex = val
+				}
+			}
+		},
+		created() {
+			this.currentIndex = this.current
+		},
+		methods: {
+			_onClick(index) {
+				if (this.currentIndex !== index) {
+					this.currentIndex = index
+					this.$emit('clickItem', {
+						currentIndex: index
+					})
+				}
+			}
+		}
+	}
+</script>
+
+<style lang="scss" >
+	.segmented-control {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		box-sizing: border-box;
+		/* #endif */
+		flex-direction: row;
+		height: 36px;
+		overflow: hidden;
+		/* #ifdef H5 */
+		cursor: pointer;
+		/* #endif */
+	}
+
+	.segmented-control__item {
+		/* #ifndef APP-NVUE */
+		display: inline-flex;
+		box-sizing: border-box;
+		/* #endif */
+		position: relative;
+		flex: 1;
+		justify-content: center;
+		align-items: center;
+	}
+
+	.segmented-control__item--button {
+		border-style: solid;
+		border-top-width: 1px;
+		border-bottom-width: 1px;
+		border-right-width: 1px;
+		border-left-width: 0;
+	}
+
+	.segmented-control__item--button--first {
+		border-left-width: 1px;
+		border-top-left-radius: 5px;
+		border-bottom-left-radius: 5px;
+	}
+
+	.segmented-control__item--button--last {
+		border-top-right-radius: 5px;
+		border-bottom-right-radius: 5px;
+	}
+
+	.segmented-control__item--text {
+		border-bottom-style: solid;
+		border-bottom-width: 2px;
+		padding: 6px 0;
+	}
+
+	.segmented-control__text {
+		font-size: 14px;
+		line-height: 20px;
+		text-align: center;
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-segmented-control/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-segmented-control/package.json
new file mode 100644
index 000000000..6cae41db2
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-segmented-control/package.json
@@ -0,0 +1,87 @@
+{
+  "id": "uni-segmented-control",
+  "displayName": "uni-segmented-control 分段器",
+  "version": "1.2.0",
+  "description": "分段器由至少 2 个分段控件组成,用作不同视图的显示",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "分段器",
+    "segement",
+    "顶部选择"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": ["uni-scss"],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-segmented-control/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-segmented-control/readme.md
new file mode 100644
index 000000000..3527b03f6
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-segmented-control/readme.md
@@ -0,0 +1,13 @@
+
+
+## SegmentedControl 分段器
+> **组件名:uni-segmented-control**
+> 代码块: `uSegmentedControl`
+
+
+用作不同视图的显示
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-segmented-control)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
+
+
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-steps/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-steps/changelog.md
new file mode 100644
index 000000000..cb9d36793
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-steps/changelog.md
@@ -0,0 +1,16 @@
+## 1.1.1(2021-11-22)
+- 修复 vue3中某些scss变量无法找到的问题
+## 1.1.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-steps](https://uniapp.dcloud.io/component/uniui/uni-steps)
+## 1.0.8(2021-05-12)
+- 新增 项目示例地址
+## 1.0.7(2021-05-06)
+- 修复 uni-steps 横向布局时,多行文字高度不合理的 bug
+## 1.0.6(2021-04-21)
+- 优化 添加依赖 uni-icons, 导入后自动下载依赖
+## 1.0.5(2021-02-05)
+- 优化 组件引用关系,通过uni_modules引用组件
+
+## 1.0.4(2021-02-05)
+- 调整为uni_modules目录规范
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-steps/components/uni-steps/uni-steps.vue b/yudao-ui-admin-uniapp/uni_modules/uni-steps/components/uni-steps/uni-steps.vue
new file mode 100644
index 000000000..a6c8f2879
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-steps/components/uni-steps/uni-steps.vue
@@ -0,0 +1,269 @@
+<template>
+	<view class="uni-steps">
+		<view :class="[direction==='column'?'uni-steps__column':'uni-steps__row']">
+			<view :class="[direction==='column'?'uni-steps__column-text-container':'uni-steps__row-text-container']">
+				<view v-for="(item,index) in options" :key="index"
+					:class="[direction==='column'?'uni-steps__column-text':'uni-steps__row-text']">
+					<text :style="{color:index === active?activeColor:deactiveColor}"
+						:class="[direction==='column'?'uni-steps__column-title':'uni-steps__row-title']">{{item.title}}</text>
+					<text :style="{color: deactiveColor}"
+						:class="[direction==='column'?'uni-steps__column-desc':'uni-steps__row-desc']">{{item.desc}}</text>
+				</view>
+			</view>
+			<view :class="[direction==='column'?'uni-steps__column-container':'uni-steps__row-container']">
+				<view :class="[direction==='column'?'uni-steps__column-line-item':'uni-steps__row-line-item']"
+					v-for="(item,index) in options" :key="index">
+					<view
+						:class="[direction==='column'?'uni-steps__column-line':'uni-steps__row-line',direction==='column'?'uni-steps__column-line--before':'uni-steps__row-line--before']"
+						:style="{backgroundColor:index<=active&&index!==0?activeColor:index===0?'transparent':deactiveColor}">
+					</view>
+					<view :class="[direction==='column'?'uni-steps__column-check':'uni-steps__row-check']"
+						v-if="index === active">
+						<uni-icons :color="activeColor" :type="activeIcon" size="14"></uni-icons>
+					</view>
+					<view v-else :class="[direction==='column'?'uni-steps__column-circle':'uni-steps__row-circle']"
+						:style="{backgroundColor:index<active?activeColor:deactiveColor}"></view>
+					<view
+						:class="[direction==='column'?'uni-steps__column-line':'uni-steps__row-line',direction==='column'?'uni-steps__column-line--after':'uni-steps__row-line--after']"
+						:style="{backgroundColor:index<active&&index!==options.length-1?activeColor:index===options.length-1?'transparent':deactiveColor}">
+					</view>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	/**
+	 * Steps 步骤条
+	 * @description 评分组件
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=34
+	 * @property {Number} active 当前步骤
+	 * @property {String} direction = [row|column] 当前步骤
+	 * 	@value row 横向
+	 * 	@value column 纵向
+	 * @property {String} activeColor 选中状态的颜色
+	 * @property {Array} options 数据源,格式为:[{title:'xxx',desc:'xxx'},{title:'xxx',desc:'xxx'}]
+	 */
+
+	export default {
+		name: 'UniSteps',
+		props: {
+			direction: {
+				// 排列方向 row column
+				type: String,
+				default: 'row'
+			},
+			activeColor: {
+				// 激活状态颜色
+				type: String,
+				default: '#2979FF'
+			},
+			deactiveColor: {
+				// 未激活状态颜色
+				type: String,
+				default: '#B7BDC6'
+			},
+			active: {
+				// 当前步骤
+				type: Number,
+				default: 0
+			},
+			activeIcon: {
+				// 当前步骤
+				type: String,
+				default: 'checkbox-filled'
+			},
+			options: {
+				type: Array,
+				default () {
+					return []
+				}
+			} // 数据
+		},
+		data() {
+			return {}
+		}
+	}
+</script>
+
+<style lang="scss">
+	$uni-primary: #2979ff !default;
+	$uni-border-color:#EDEDED;
+	.uni-steps {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		width: 100%;
+		/* #endif */
+		/* #ifdef APP-NVUE */
+		flex: 1;
+		/* #endif */
+		flex-direction: column;
+	}
+
+	.uni-steps__row {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+	}
+
+	.uni-steps__column {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row-reverse;
+	}
+
+	.uni-steps__row-text-container {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		align-items: flex-end;
+		margin-bottom: 8px;
+	}
+
+	.uni-steps__column-text-container {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		flex: 1;
+	}
+
+	.uni-steps__row-text {
+		/* #ifndef APP-NVUE */
+		display: inline-flex;
+		/* #endif */
+		flex: 1;
+		flex-direction: column;
+	}
+
+	.uni-steps__column-text {
+		padding: 6px 0px;
+		border-bottom-style: solid;
+		border-bottom-width: 1px;
+		border-bottom-color: $uni-border-color;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+	}
+
+	.uni-steps__row-title {
+		font-size: 14px;
+		line-height: 16px;
+		text-align: center;
+	}
+
+	.uni-steps__column-title {
+		font-size: 14px;
+		text-align: left;
+		line-height: 18px;
+	}
+
+	.uni-steps__row-desc {
+		font-size: 12px;
+		line-height: 14px;
+		text-align: center;
+	}
+
+	.uni-steps__column-desc {
+		font-size: 12px;
+		text-align: left;
+		line-height: 18px;
+	}
+
+	.uni-steps__row-container {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+	}
+
+	.uni-steps__column-container {
+		/* #ifndef APP-NVUE */
+		display: inline-flex;
+		/* #endif */
+		width: 30px;
+		flex-direction: column;
+	}
+
+	.uni-steps__row-line-item {
+		/* #ifndef APP-NVUE */
+		display: inline-flex;
+		/* #endif */
+		flex-direction: row;
+		flex: 1;
+		height: 14px;
+		line-height: 14px;
+		align-items: center;
+		justify-content: center;
+	}
+
+	.uni-steps__column-line-item {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		flex: 1;
+		align-items: center;
+		justify-content: center;
+	}
+
+	.uni-steps__row-line {
+		flex: 1;
+		height: 1px;
+		background-color: #B7BDC6;
+	}
+
+	.uni-steps__column-line {
+		width: 1px;
+		background-color: #B7BDC6;
+	}
+
+	.uni-steps__row-line--after {
+		transform: translateX(1px);
+	}
+
+	.uni-steps__column-line--after {
+		flex: 1;
+		transform: translate(0px, 1px);
+	}
+
+	.uni-steps__row-line--before {
+		transform: translateX(-1px);
+	}
+
+	.uni-steps__column-line--before {
+		height: 6px;
+		transform: translate(0px, -13px);
+	}
+
+	.uni-steps__row-circle {
+		width: 5px;
+		height: 5px;
+		border-radius: 50%;
+		background-color: #B7BDC6;
+		margin: 0px 3px;
+	}
+
+	.uni-steps__column-circle {
+		width: 5px;
+		height: 5px;
+		border-radius: 50%;
+		background-color: #B7BDC6;
+		margin: 4px 0px 5px 0px;
+	}
+
+	.uni-steps__row-check {
+		margin: 0px 6px;
+	}
+
+	.uni-steps__column-check {
+		height: 14px;
+		line-height: 14px;
+		margin: 2px 0px;
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-steps/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-steps/package.json
new file mode 100644
index 000000000..c687b40ab
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-steps/package.json
@@ -0,0 +1,89 @@
+{
+  "id": "uni-steps",
+  "displayName": "uni-steps 步骤条",
+  "version": "1.1.1",
+  "description": "步骤条组件,提供横向和纵向两种布局格式。",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "步骤条",
+    "时间轴"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": [
+			"uni-scss",
+			"uni-icons"
+		],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-steps/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-steps/readme.md
new file mode 100644
index 000000000..da7a4bfaa
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-steps/readme.md
@@ -0,0 +1,13 @@
+
+
+## Steps 步骤条
+> **组件名:uni-steps**
+> 代码块: `uSteps`
+
+
+步骤条,常用于显示进度
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-steps)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
+
+
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-swipe-action/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-swipe-action/changelog.md
new file mode 100644
index 000000000..c007cb5c4
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-swipe-action/changelog.md
@@ -0,0 +1,41 @@
+## 1.3.7(2022-06-06)
+- 修复 vue3 下使用组件不能正常运行的Bug
+## 1.3.6(2022-05-31)
+- 修复 h5端点击click触发两次的Bug
+## 1.3.5(2022-05-23)
+- 修复 isPC 找不到的Bug
+## 1.3.4(2022-05-19)
+-  修复 在 nvue 下 disabled 失效的bug
+## 1.3.3(2022-03-31)
+- 修复 按钮字体大小不能设置的bug
+## 1.3.2(2022-03-16)
+- 修复 h5和app端下报el错误的bug
+## 1.3.1(2022-03-07)
+- 修复 HBuilderX 1.4.X 版本中,h5和app端下报错的bug
+## 1.3.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-swipe-action](https://uniapp.dcloud.io/component/uniui/uni-swipe-action)
+## 1.2.4(2021-08-20)
+- 优化 close-all 方法
+## 1.2.3(2021-08-20)
+- 新增 close-all 方法,关闭所有已打开的组件
+## 1.2.2(2021-08-17)
+- 新增 resize() 方法,在非微信小程序、h5、app-vue端出现不能滑动的问题的时候,重置组件
+- 修复 app 端偶尔出现类似 Page[x][-x,xx;-x,xx,x,x-x] 的问题 
+- 优化 微信小程序、h5、app-vue 滑动逻辑,避免出现动态新增组件后不能滑动的问题
+## 1.2.1(2021-07-30)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+- 修复 跨页面修改组件数据 ,导致不能滑动的问题
+## 1.1.10(2021-06-17)
+- 修复 按钮点击执行两次的bug
+## 1.1.9(2021-05-12)
+- 新增 项目示例地址
+## 1.1.8(2021-03-26)
+- 修复 微信小程序 nv_navigator is not defined 报错的bug
+## 1.1.7(2021-02-05)
+- 调整为uni_modules目录规范
+- 新增 左侧滑动
+- 新增 插槽使用方式
+- 新增 threshold 属性,可以控制滑动缺省值
+- 优化 长列表滚动性能
+- 修复 滚动页面时触发组件滑动的Bug
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-swipe-action/components/uni-swipe-action-item/bindingx.js b/yudao-ui-admin-uniapp/uni_modules/uni-swipe-action/components/uni-swipe-action-item/bindingx.js
new file mode 100644
index 000000000..755c97c96
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-swipe-action/components/uni-swipe-action-item/bindingx.js
@@ -0,0 +1,302 @@
+let bindIngXMixins = {}
+
+// #ifdef APP-NVUE
+const BindingX = uni.requireNativePlugin('bindingx');
+const dom = uni.requireNativePlugin('dom');
+const animation = uni.requireNativePlugin('animation');
+
+bindIngXMixins = {
+	data() {
+		return {}
+	},
+
+	watch: {
+		show(newVal) {
+			if (this.autoClose) return
+			if (this.stop) return
+			this.stop = true
+			if (newVal) {
+				this.open(newVal)
+			} else {
+				this.close()
+			}
+		},
+		leftOptions() {
+			this.getSelectorQuery()
+			this.init()
+		},
+		rightOptions(newVal) {
+			this.init()
+		}
+	},
+	created() {
+		this.swipeaction = this.getSwipeAction()
+		if (this.swipeaction.children !== undefined) {
+			this.swipeaction.children.push(this)
+		}
+	},
+	mounted() {
+		this.box = this.getEl(this.$refs['selector-box--hock'])
+		this.selector = this.getEl(this.$refs['selector-content--hock']);
+		this.leftButton = this.getEl(this.$refs['selector-left-button--hock']);
+		this.rightButton = this.getEl(this.$refs['selector-right-button--hock']);
+		this.init()
+	},
+	// beforeDestroy() {
+	// 	this.swipeaction.children.forEach((item, index) => {
+	// 		if (item === this) {
+	// 			this.swipeaction.children.splice(index, 1)
+	// 		}
+	// 	})
+	// },
+	methods: {
+		init() {
+			this.$nextTick(() => {
+				this.x = 0
+				this.button = {
+					show: false
+				}
+				setTimeout(() => {
+					this.getSelectorQuery()
+				}, 200)
+			})
+		},
+		onClick(index, item, position) {
+			this.$emit('click', {
+				content: item,
+				index,
+				position
+			})
+		},
+		touchstart(e) {
+			// fix by mehaotian 禁止滑动
+			if (this.disabled) return
+			// 每次只触发一次,避免多次监听造成闪烁
+			if (this.stop) return
+			this.stop = true
+			if (this.autoClose) {
+				this.swipeaction.closeOther(this)
+			}
+
+			const leftWidth = this.button.left.width
+			const rightWidth = this.button.right.width
+			let expression = this.range(this.x, -rightWidth, leftWidth)
+			let leftExpression = this.range(this.x - leftWidth, -leftWidth, 0)
+			let rightExpression = this.range(this.x + rightWidth, 0, rightWidth)
+
+			this.eventpan = BindingX.bind({
+				anchor: this.box,
+				eventType: 'pan',
+				props: [{
+					element: this.selector,
+					property: 'transform.translateX',
+					expression
+				}, {
+					element: this.leftButton,
+					property: 'transform.translateX',
+					expression: leftExpression
+				}, {
+					element: this.rightButton,
+					property: 'transform.translateX',
+					expression: rightExpression
+				}, ]
+			}, (e) => {
+				// nope
+				if (e.state === 'end') {
+					this.x = e.deltaX + this.x;
+					this.isclick = true
+					this.bindTiming(e.deltaX)
+				}
+			});
+		},
+		touchend(e) {
+			if (this.isopen !== 'none' && !this.isclick) {
+				this.open('none')
+			}
+		},
+		bindTiming(x) {
+			const left = this.x
+			const leftWidth = this.button.left.width
+			const rightWidth = this.button.right.width
+			const threshold = this.threshold
+			if (!this.isopen || this.isopen === 'none') {
+				if (left > threshold) {
+					this.open('left')
+				} else if (left < -threshold) {
+					this.open('right')
+				} else {
+					this.open('none')
+				}
+			} else {
+				if ((x > -leftWidth && x < 0) || x > rightWidth) {
+					if ((x > -threshold && x < 0) || (x - rightWidth > threshold)) {
+						this.open('left')
+					} else {
+						this.open('none')
+					}
+				} else {
+					if ((x < threshold && x > 0) || (x + leftWidth < -threshold)) {
+						this.open('right')
+					} else {
+						this.open('none')
+					}
+				}
+			}
+		},
+
+		/**
+		 * 移动范围
+		 * @param {Object} num
+		 * @param {Object} mix
+		 * @param {Object} max
+		 */
+		range(num, mix, max) {
+			return `min(max(x+${num}, ${mix}), ${max})`
+		},
+
+		/**
+		 * 开启swipe
+		 */
+		open(type) {
+			this.animation(type)
+		},
+
+		/**
+		 * 关闭swipe
+		 */
+		close() {
+			this.animation('none')
+		},
+
+		/**
+		 * 开启关闭动画
+		 * @param {Object} type
+		 */
+		animation(type) {
+			const time = 300
+			const leftWidth = this.button.left.width
+			const rightWidth = this.button.right.width
+			if (this.eventpan && this.eventpan.token) {
+				BindingX.unbind({
+					token: this.eventpan.token,
+					eventType: 'pan'
+				})
+			}
+
+			switch (type) {
+				case 'left':
+					Promise.all([
+						this.move(this.selector, leftWidth),
+						this.move(this.leftButton, 0),
+						this.move(this.rightButton, rightWidth * 2)
+					]).then(() => {
+						this.setEmit(leftWidth, type)
+					})
+					break
+				case 'right':
+					Promise.all([
+						this.move(this.selector, -rightWidth),
+						this.move(this.leftButton, -leftWidth * 2),
+						this.move(this.rightButton, 0)
+					]).then(() => {
+						this.setEmit(-rightWidth, type)
+					})
+					break
+				default:
+					Promise.all([
+						this.move(this.selector, 0),
+						this.move(this.leftButton, -leftWidth),
+						this.move(this.rightButton, rightWidth)
+					]).then(() => {
+						this.setEmit(0, type)
+					})
+
+			}
+		},
+		setEmit(x, type) {
+			const leftWidth = this.button.left.width
+			const rightWidth = this.button.right.width
+			this.isopen = this.isopen || 'none'
+			this.stop = false
+			this.isclick = false
+			// 只有状态不一致才会返回结果
+			if (this.isopen !== type && this.x !== x) {
+				if (type === 'left' && leftWidth > 0) {
+					this.$emit('change', 'left')
+				}
+				if (type === 'right' && rightWidth > 0) {
+					this.$emit('change', 'right')
+				}
+				if (type === 'none') {
+					this.$emit('change', 'none')
+				}
+			}
+			this.x = x
+			this.isopen = type
+		},
+		move(ref, value) {
+			return new Promise((resolve, reject) => {
+				animation.transition(ref, {
+					styles: {
+						transform: `translateX(${value})`,
+					},
+					duration: 150, //ms
+					timingFunction: 'linear',
+					needLayout: false,
+					delay: 0 //ms
+				}, function(res) {
+					resolve(res)
+				})
+			})
+
+		},
+
+		/**
+		 * 获取ref
+		 * @param {Object} el
+		 */
+		getEl(el) {
+			return el.ref
+		},
+		/**
+		 * 获取节点信息
+		 */
+		getSelectorQuery() {
+			Promise.all([
+				this.getDom('left'),
+				this.getDom('right'),
+			]).then((data) => {
+				let show = 'none'
+				if (this.autoClose) {
+					show = 'none'
+				} else {
+					show = this.show
+				}
+
+				if (show === 'none') {
+					// this.close()
+				} else {
+					this.open(show)
+				}
+
+			})
+
+		},
+		getDom(str) {
+			return new Promise((resolve, reject) => {
+				dom.getComponentRect(this.$refs[`selector-${str}-button--hock`], (data) => {
+					if (data) {
+						this.button[str] = data.size
+						resolve(data)
+					} else {
+						reject()
+					}
+				})
+			})
+		}
+	}
+}
+
+// #endif
+
+export default bindIngXMixins
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-swipe-action/components/uni-swipe-action-item/isPC.js b/yudao-ui-admin-uniapp/uni_modules/uni-swipe-action/components/uni-swipe-action-item/isPC.js
new file mode 100644
index 000000000..917cb4890
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-swipe-action/components/uni-swipe-action-item/isPC.js
@@ -0,0 +1,12 @@
+export function isPC() {
+	var userAgentInfo = navigator.userAgent;
+	var Agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"];
+	var flag = true;
+	for (let v = 0; v < Agents.length - 1; v++) {
+		if (userAgentInfo.indexOf(Agents[v]) > 0) {
+			flag = false;
+			break;
+		}
+	}
+	return flag;
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpalipay.js b/yudao-ui-admin-uniapp/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpalipay.js
new file mode 100644
index 000000000..43cd56bdf
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpalipay.js
@@ -0,0 +1,193 @@
+export default {
+	data() {
+		return {
+			x: 0,
+			transition: false,
+			width: 0,
+			viewWidth: 0,
+			swipeShow: 0
+		}
+	},
+	watch: {
+		show(newVal) {
+			if (this.autoClose) return
+			if (newVal && newVal !== 'none') {
+				this.transition = true
+				this.open(newVal)
+			} else {
+				this.close()
+			}
+		}
+	},
+	created() {
+		this.swipeaction = this.getSwipeAction()
+		if (this.swipeaction.children !== undefined) {
+			this.swipeaction.children.push(this)
+		}
+	},
+	mounted() {
+		this.isopen = false
+		setTimeout(() => {
+			this.getQuerySelect()
+		}, 50)
+	},
+	methods: {
+		appTouchStart(e) {
+			const {
+				clientX
+			} = e.changedTouches[0]
+			this.clientX = clientX
+			this.timestamp = new Date().getTime()
+		},
+		appTouchEnd(e, index, item, position) {
+			const {
+				clientX
+			} = e.changedTouches[0]
+			// fixed by xxxx 模拟点击事件,解决 ios 13 点击区域错位的问题
+			let diff = Math.abs(this.clientX - clientX)
+			let time = (new Date().getTime()) - this.timestamp
+			if (diff < 40 && time < 300) {
+				this.$emit('click', {
+					content: item,
+					index,
+					position
+				})
+			}
+		},
+		/**
+		 * 移动触发
+		 * @param {Object} e
+		 */
+		onChange(e) {
+			this.moveX = e.detail.x
+			this.isclose = false
+		},
+		touchstart(e) {
+			this.transition = false
+			this.isclose = true
+			this.autoClose && this.swipeaction.closeOther(this)
+		},
+		touchmove(e) {},
+		touchend(e) {
+			// 0的位置什么都不执行
+			if (this.isclose && this.isopen === 'none') return
+			if (this.isclose && this.isopen !== 'none') {
+				this.transition = true
+				this.close()
+			} else {
+				this.move(this.moveX + this.leftWidth)
+			}
+		},
+
+		/**
+		 * 移动
+		 * @param {Object} moveX
+		 */
+		move(moveX) {
+			// 打开关闭的处理逻辑不太一样
+			this.transition = true
+			// 未打开状态
+			if (!this.isopen || this.isopen === 'none') {
+				if (moveX > this.threshold) {
+					this.open('left')
+				} else if (moveX < -this.threshold) {
+					this.open('right')
+				} else {
+					this.close()
+				}
+			} else {
+				if (moveX < 0 && moveX < this.rightWidth) {
+					const rightX = this.rightWidth + moveX
+					if (rightX < this.threshold) {
+						this.open('right')
+					} else {
+						this.close()
+					}
+				} else if (moveX > 0 && moveX < this.leftWidth) {
+					const leftX = this.leftWidth - moveX
+					if (leftX < this.threshold) {
+						this.open('left')
+					} else {
+						this.close()
+					}
+				}
+
+			}
+
+		},
+
+		/**
+		 * 打开
+		 */
+		open(type) {
+			this.x = this.moveX
+			this.animation(type)
+		},
+
+		/**
+		 * 关闭
+		 */
+		close() {
+			this.x = this.moveX
+			// TODO 解决 x 值不更新的问题,所以会多触发一次 nextTick ,待优化
+			this.$nextTick(() => {
+				this.x = -this.leftWidth
+				if (this.isopen !== 'none') {
+					this.$emit('change', 'none')
+				}
+				this.isopen = 'none'
+			})
+		},
+
+		/**
+		 * 执行结束动画
+		 * @param {Object} type
+		 */
+		animation(type) {
+			this.$nextTick(() => {
+				if (type === 'left') {
+					this.x = 0
+				} else {
+					this.x = -this.rightWidth - this.leftWidth
+				}
+
+				if (this.isopen !== type) {
+					this.$emit('change', type)
+				}
+				this.isopen = type
+			})
+
+		},
+		getSlide(x) {},
+		getQuerySelect() {
+			const query = uni.createSelectorQuery().in(this);
+			query.selectAll('.movable-view--hock').boundingClientRect(data => {
+				this.leftWidth = data[1].width
+				this.rightWidth = data[2].width
+				this.width = data[0].width
+				this.viewWidth = this.width + this.rightWidth + this.leftWidth
+				if (this.leftWidth === 0) {
+					// TODO 疑似bug ,初始化的时候如果x 是0,会导致移动位置错误,所以让元素超出一点
+					this.x = -0.1
+				} else {
+					this.x = -this.leftWidth
+				}
+				this.moveX = this.x
+				this.$nextTick(() => {
+					this.swipeShow = 1
+				})
+
+				if (!this.buttonWidth) {
+					this.disabledView = true
+				}
+
+				if (this.autoClose) return
+				if (this.show !== 'none') {
+					this.transition = true
+					this.open(this.shows)
+				}
+			}).exec();
+
+		}
+	}
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpother.js b/yudao-ui-admin-uniapp/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpother.js
new file mode 100644
index 000000000..9a8bcbb64
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpother.js
@@ -0,0 +1,259 @@
+let otherMixins = {}
+
+// #ifndef APP-PLUS|| MP-WEIXIN  ||  H5
+const MIN_DISTANCE = 10;
+otherMixins = {
+	data() {
+		// TODO 随机生生元素ID,解决百度小程序获取同一个元素位置信息的bug
+		const elClass = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`
+		return {
+			uniShow: false,
+			left: 0,
+			buttonShow: 'none',
+			ani: false,
+			moveLeft: '',
+			elClass
+		}
+	},
+	watch: {
+		show(newVal) {
+			if (this.autoClose) return
+			this.openState(newVal)
+		},
+		left() {
+			this.moveLeft = `translateX(${this.left}px)`
+		},
+		buttonShow(newVal) {
+			if (this.autoClose) return
+			this.openState(newVal)
+		},
+		leftOptions() {
+			this.init()
+		},
+		rightOptions() {
+			this.init()
+		}
+	},
+	mounted() {
+		this.swipeaction = this.getSwipeAction()
+		if (this.swipeaction.children !== undefined) {
+			this.swipeaction.children.push(this)
+		}
+		this.init()
+	},
+	methods: {
+		init() {
+			clearTimeout(this.timer)
+			this.timer = setTimeout(() => {
+				this.getSelectorQuery()
+			}, 100)
+			// 移动距离
+			this.left = 0
+			this.x = 0
+		},
+
+		closeSwipe(e) {
+			if (!this.autoClose) return
+			this.swipeaction.closeOther(this)
+		},
+		appTouchStart(e) {
+			const {
+				clientX
+			} = e.changedTouches[0]
+			this.clientX = clientX
+			this.timestamp = new Date().getTime()
+		},
+		appTouchEnd(e, index, item, position) {
+			const {
+				clientX
+			} = e.changedTouches[0]
+			// fixed by xxxx 模拟点击事件,解决 ios 13 点击区域错位的问题
+			let diff = Math.abs(this.clientX - clientX)
+			let time = (new Date().getTime()) - this.timestamp
+			if (diff < 40 && time < 300) {
+				this.$emit('click', {
+					content: item,
+					index,
+					position
+				})
+			}
+		},
+		touchstart(e) {
+			if (this.disabled) return
+			this.ani = false
+			this.x = this.left || 0
+			this.stopTouchStart(e)
+			this.autoClose && this.closeSwipe()
+		},
+		touchmove(e) {
+			if (this.disabled) return
+			// 是否可以滑动页面
+			this.stopTouchMove(e);
+			if (this.direction !== 'horizontal') {
+				return;
+			}
+			this.move(this.x + this.deltaX)
+			return false
+		},
+		touchend() {
+			if (this.disabled) return
+			this.moveDirection(this.left)
+		},
+		/**
+		 * 设置移动距离
+		 * @param {Object} value
+		 */
+		move(value) {
+			value = value || 0
+			const leftWidth = this.leftWidth
+			const rightWidth = this.rightWidth
+			// 获取可滑动范围
+			this.left = this.range(value, -rightWidth, leftWidth);
+		},
+
+		/**
+		 * 获取范围
+		 * @param {Object} num
+		 * @param {Object} min
+		 * @param {Object} max
+		 */
+		range(num, min, max) {
+			return Math.min(Math.max(num, min), max);
+		},
+		/**
+		 * 移动方向判断
+		 * @param {Object} left
+		 * @param {Object} value
+		 */
+		moveDirection(left) {
+			const threshold = this.threshold
+			const isopen = this.isopen || 'none'
+			const leftWidth = this.leftWidth
+			const rightWidth = this.rightWidth
+			if (this.deltaX === 0) {
+				this.openState('none')
+				return
+			}
+			if ((isopen === 'none' && rightWidth > 0 && -left > threshold) || (isopen !== 'none' && rightWidth >
+					0 && rightWidth +
+					left < threshold)) {
+				// right
+				this.openState('right')
+			} else if ((isopen === 'none' && leftWidth > 0 && left > threshold) || (isopen !== 'none' && leftWidth >
+					0 &&
+					leftWidth - left < threshold)) {
+				// left
+				this.openState('left')
+			} else {
+				// default
+				this.openState('none')
+			}
+		},
+
+		/**
+		 * 开启状态
+		 * @param {Boolean} type
+		 */
+		openState(type) {
+			const leftWidth = this.leftWidth
+			const rightWidth = this.rightWidth
+			let left = ''
+			this.isopen = this.isopen ? this.isopen : 'none'
+			switch (type) {
+				case "left":
+					left = leftWidth
+					break
+				case "right":
+					left = -rightWidth
+					break
+				default:
+					left = 0
+			}
+
+
+			if (this.isopen !== type) {
+				this.throttle = true
+				this.$emit('change', type)
+			}
+
+			this.isopen = type
+			// 添加动画类
+			this.ani = true
+			this.$nextTick(() => {
+				this.move(left)
+			})
+			// 设置最终移动位置,理论上只要进入到这个函数,肯定是要打开的
+		},
+		close() {
+			this.openState('none')
+		},
+		getDirection(x, y) {
+			if (x > y && x > MIN_DISTANCE) {
+				return 'horizontal';
+			}
+			if (y > x && y > MIN_DISTANCE) {
+				return 'vertical';
+			}
+			return '';
+		},
+
+		/**
+		 * 重置滑动状态
+		 * @param {Object} event
+		 */
+		resetTouchStatus() {
+			this.direction = '';
+			this.deltaX = 0;
+			this.deltaY = 0;
+			this.offsetX = 0;
+			this.offsetY = 0;
+		},
+
+		/**
+		 * 设置滑动开始位置
+		 * @param {Object} event
+		 */
+		stopTouchStart(event) {
+			this.resetTouchStatus();
+			const touch = event.touches[0];
+			this.startX = touch.clientX;
+			this.startY = touch.clientY;
+		},
+
+		/**
+		 * 滑动中,是否禁止打开
+		 * @param {Object} event
+		 */
+		stopTouchMove(event) {
+			const touch = event.touches[0];
+			this.deltaX = touch.clientX - this.startX;
+			this.deltaY = touch.clientY - this.startY;
+			this.offsetX = Math.abs(this.deltaX);
+			this.offsetY = Math.abs(this.deltaY);
+			this.direction = this.direction || this.getDirection(this.offsetX, this.offsetY);
+		},
+
+		getSelectorQuery() {
+			const views = uni.createSelectorQuery().in(this)
+			views
+				.selectAll('.' + this.elClass)
+				.boundingClientRect(data => {
+					if (data.length === 0) return
+					let show = 'none'
+					if (this.autoClose) {
+						show = 'none'
+					} else {
+						show = this.show
+					}
+					this.leftWidth = data[0].width || 0
+					this.rightWidth = data[1].width || 0
+					this.buttonShow = show
+				})
+				.exec()
+		}
+	}
+}
+
+// #endif
+
+export default otherMixins
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpwxs.js b/yudao-ui-admin-uniapp/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpwxs.js
new file mode 100644
index 000000000..435e0fbcb
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpwxs.js
@@ -0,0 +1,83 @@
+let mpMixins = {}
+let is_pc = null
+// #ifdef H5
+import {
+	isPC
+} from "./isPC"
+is_pc = isPC()
+// #endif
+// #ifdef APP-VUE|| MP-WEIXIN || H5
+
+mpMixins = {
+	data() {
+		return {
+			is_show: 'none'
+		}
+	},
+	watch: {
+		show(newVal) {
+			this.is_show = this.show
+		}
+	},
+	created() {
+		this.swipeaction = this.getSwipeAction()
+		if (this.swipeaction.children !== undefined) {
+			this.swipeaction.children.push(this)
+		}
+	},
+	mounted() {
+		this.is_show = this.show
+	},
+	methods: {
+		// wxs 中调用
+		closeSwipe(e) {
+			if (!this.autoClose) return
+			this.swipeaction.closeOther(this)
+		},
+
+		change(e) {
+			this.$emit('change', e.open)
+			if (this.is_show !== e.open) {
+				this.is_show = e.open
+			}
+		},
+
+		appTouchStart(e) {
+			if (is_pc) return
+			const {
+				clientX
+			} = e.changedTouches[0]
+			this.clientX = clientX
+			this.timestamp = new Date().getTime()
+		},
+		appTouchEnd(e, index, item, position) {
+			if (is_pc) return
+			const {
+				clientX
+			} = e.changedTouches[0]
+			// fixed by xxxx 模拟点击事件,解决 ios 13 点击区域错位的问题
+			let diff = Math.abs(this.clientX - clientX)
+			let time = (new Date().getTime()) - this.timestamp
+			if (diff < 40 && time < 300) {
+				this.$emit('click', {
+					content: item,
+					index,
+					position
+				})
+			}
+		},
+		onClickForPC(index, item, position) {
+			if (!is_pc) return
+			// #ifdef H5
+			this.$emit('click', {
+				content: item,
+				index,
+				position
+			})
+			// #endif
+		}
+	}
+}
+
+// #endif
+export default mpMixins
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-swipe-action/components/uni-swipe-action-item/render.js b/yudao-ui-admin-uniapp/uni_modules/uni-swipe-action/components/uni-swipe-action-item/render.js
new file mode 100644
index 000000000..78f0ec60e
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-swipe-action/components/uni-swipe-action-item/render.js
@@ -0,0 +1,270 @@
+const MIN_DISTANCE = 10;
+export default {
+	showWatch(newVal, oldVal, ownerInstance, instance, self) {
+		var state = self.state
+		var $el = ownerInstance.$el || ownerInstance.$vm && ownerInstance.$vm.$el
+		if (!$el) return
+		this.getDom(instance, ownerInstance, self)
+		if (newVal && newVal !== 'none') {
+			this.openState(newVal, instance, ownerInstance, self)
+			return
+		}
+
+		if (state.left) {
+			this.openState('none', instance, ownerInstance, self)
+		}
+		this.resetTouchStatus(instance, self)
+	},
+
+	/**
+	 * 开始触摸操作
+	 * @param {Object} e
+	 * @param {Object} ins
+	 */
+	touchstart(e, ownerInstance, self) {
+		let instance = e.instance;
+		let disabled = instance.getDataset().disabled
+		let state = self.state;
+		this.getDom(instance, ownerInstance, self)
+		// fix by mehaotian, TODO 兼容 app-vue 获取dataset为字符串 , h5 获取 为 undefined 的问题,待框架修复
+		disabled = this.getDisabledType(disabled)
+		if (disabled) return
+		// 开始触摸时移除动画类
+		instance.requestAnimationFrame(function() {
+			instance.removeClass('ani');
+			ownerInstance.callMethod('closeSwipe');
+		})
+
+		// 记录上次的位置
+		state.x = state.left || 0
+		// 计算滑动开始位置
+		this.stopTouchStart(e, ownerInstance, self)
+	},
+
+	/**
+	 * 开始滑动操作
+	 * @param {Object} e
+	 * @param {Object} ownerInstance
+	 */
+	touchmove(e, ownerInstance, self) {
+		let instance = e.instance;
+		// 删除之后已经那不到实例了
+		if (!instance) return;
+		let disabled = instance.getDataset().disabled
+		let state = self.state
+		// fix by mehaotian, TODO 兼容 app-vue 获取dataset为字符串 , h5 获取 为 undefined 的问题,待框架修复
+		disabled = this.getDisabledType(disabled)
+		if (disabled) return
+		// 是否可以滑动页面
+		this.stopTouchMove(e, self);
+		if (state.direction !== 'horizontal') {
+			return;
+		}
+		if (e.preventDefault) {
+			// 阻止页面滚动
+			e.preventDefault()
+		}
+		let x = state.x + state.deltaX
+		this.move(x, instance, ownerInstance, self)
+	},
+
+	/**
+	 * 结束触摸操作
+	 * @param {Object} e
+	 * @param {Object} ownerInstance
+	 */
+	touchend(e, ownerInstance, self) {
+		let instance = e.instance;
+		let disabled = instance.getDataset().disabled
+		let state = self.state
+		// fix by mehaotian, TODO 兼容 app-vue 获取dataset为字符串 , h5 获取 为 undefined 的问题,待框架修复
+		disabled = this.getDisabledType(disabled)
+
+		if (disabled) return
+		// 滑动过程中触摸结束,通过阙值判断是开启还是关闭
+		// fixed by mehaotian 定时器解决点击按钮,touchend 触发比 click 事件时机早的问题 ,主要是 ios13
+		this.moveDirection(state.left, instance, ownerInstance, self)
+
+	},
+
+	/**
+	 * 设置移动距离
+	 * @param {Object} value
+	 * @param {Object} instance
+	 * @param {Object} ownerInstance
+	 */
+	move(value, instance, ownerInstance, self) {
+		value = value || 0
+		let state = self.state
+		let leftWidth = state.leftWidth
+		let rightWidth = state.rightWidth
+		// 获取可滑动范围
+		state.left = this.range(value, -rightWidth, leftWidth);
+		instance.requestAnimationFrame(function() {
+			instance.setStyle({
+				transform: 'translateX(' + state.left + 'px)',
+				'-webkit-transform': 'translateX(' + state.left + 'px)'
+			})
+		})
+
+	},
+
+	/**
+	 * 获取元素信息
+	 * @param {Object} instance
+	 * @param {Object} ownerInstance
+	 */
+	getDom(instance, ownerInstance, self) {
+		var state = self.state
+		var $el = ownerInstance.$el || ownerInstance.$vm && ownerInstance.$vm.$el
+		var leftDom = $el.querySelector('.button-group--left')
+		var rightDom = $el.querySelector('.button-group--right')
+
+		state.leftWidth = leftDom.offsetWidth || 0
+		state.rightWidth = rightDom.offsetWidth || 0
+		state.threshold = instance.getDataset().threshold
+	},
+
+	getDisabledType(value) {
+		return (typeof(value) === 'string' ? JSON.parse(value) : value) || false;
+	},
+
+	/**
+	 * 获取范围
+	 * @param {Object} num
+	 * @param {Object} min
+	 * @param {Object} max
+	 */
+	range(num, min, max) {
+		return Math.min(Math.max(num, min), max);
+	},
+
+
+	/**
+	 * 移动方向判断
+	 * @param {Object} left
+	 * @param {Object} value
+	 * @param {Object} ownerInstance
+	 * @param {Object} ins
+	 */
+	moveDirection(left, ins, ownerInstance, self) {
+		var state = self.state
+		var threshold = state.threshold
+		var position = state.position
+		var isopen = state.isopen || 'none'
+		var leftWidth = state.leftWidth
+		var rightWidth = state.rightWidth
+		if (state.deltaX === 0) {
+			this.openState('none', ins, ownerInstance, self)
+			return
+		}
+		if ((isopen === 'none' && rightWidth > 0 && -left > threshold) || (isopen !== 'none' && rightWidth > 0 &&
+				rightWidth +
+				left < threshold)) {
+			// right
+			this.openState('right', ins, ownerInstance, self)
+		} else if ((isopen === 'none' && leftWidth > 0 && left > threshold) || (isopen !== 'none' && leftWidth > 0 &&
+				leftWidth - left < threshold)) {
+			// left
+			this.openState('left', ins, ownerInstance, self)
+		} else {
+			// default
+			this.openState('none', ins, ownerInstance, self)
+		}
+	},
+
+
+	/**
+	 * 开启状态
+	 * @param {Boolean} type
+	 * @param {Object} ins
+	 * @param {Object} ownerInstance
+	 */
+	openState(type, ins, ownerInstance, self) {
+		let state = self.state
+		let leftWidth = state.leftWidth
+		let rightWidth = state.rightWidth
+		let left = ''
+		state.isopen = state.isopen ? state.isopen : 'none'
+		switch (type) {
+			case "left":
+				left = leftWidth
+				break
+			case "right":
+				left = -rightWidth
+				break
+			default:
+				left = 0
+		}
+
+		// && !state.throttle
+
+		if (state.isopen !== type) {
+			state.throttle = true
+			ownerInstance.callMethod('change', {
+				open: type
+			})
+
+		}
+
+		state.isopen = type
+		// 添加动画类
+		ins.requestAnimationFrame(() => {
+			ins.addClass('ani');
+			this.move(left, ins, ownerInstance, self)
+		})
+	},
+
+
+	getDirection(x, y) {
+		if (x > y && x > MIN_DISTANCE) {
+			return 'horizontal';
+		}
+		if (y > x && y > MIN_DISTANCE) {
+			return 'vertical';
+		}
+		return '';
+	},
+
+	/**
+	 * 重置滑动状态
+	 * @param {Object} event
+	 */
+	resetTouchStatus(instance, self) {
+		let state = self.state;
+		state.direction = '';
+		state.deltaX = 0;
+		state.deltaY = 0;
+		state.offsetX = 0;
+		state.offsetY = 0;
+	},
+
+	/**
+	 * 设置滑动开始位置
+	 * @param {Object} event
+	 */
+	stopTouchStart(event, ownerInstance, self) {
+		let instance = event.instance;
+		let state = self.state
+		this.resetTouchStatus(instance, self);
+		var touch = event.touches[0];
+		state.startX = touch.clientX;
+		state.startY = touch.clientY;
+	},
+
+	/**
+	 * 滑动中,是否禁止打开
+	 * @param {Object} event
+	 */
+	stopTouchMove(event, self) {
+		let instance = event.instance;
+		let state = self.state;
+		let touch = event.touches[0];
+
+		state.deltaX = touch.clientX - state.startX;
+		state.deltaY = touch.clientY - state.startY;
+		state.offsetY = Math.abs(state.deltaY);
+		state.offsetX = Math.abs(state.deltaX);
+		state.direction = state.direction || this.getDirection(state.offsetX, state.offsetY);
+	}
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-swipe-action/components/uni-swipe-action-item/uni-swipe-action-item.vue b/yudao-ui-admin-uniapp/uni_modules/uni-swipe-action/components/uni-swipe-action-item/uni-swipe-action-item.vue
new file mode 100644
index 000000000..d79c2979f
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-swipe-action/components/uni-swipe-action-item/uni-swipe-action-item.vue
@@ -0,0 +1,347 @@
+<template>
+	<!-- 在微信小程序 app vue端 h5 使用wxs 实现-->
+	<!-- #ifdef APP-VUE || MP-WEIXIN || H5 -->
+	<view class="uni-swipe">
+		<!--  #ifdef MP-WEIXIN || VUE3 -->
+		<view class="uni-swipe_box" :change:prop="wxsswipe.showWatch" :prop="is_show" :data-threshold="threshold"
+			:data-disabled="disabled" @touchstart="wxsswipe.touchstart" @touchmove="wxsswipe.touchmove"
+			@touchend="wxsswipe.touchend">
+			<!-- #endif -->
+			<!--  #ifndef MP-WEIXIN || VUE3 -->
+			<view class="uni-swipe_box" :change:prop="renderswipe.showWatch" :prop="is_show" :data-threshold="threshold"
+				:data-disabled="disabled+''" @touchstart="renderswipe.touchstart" @touchmove="renderswipe.touchmove"
+				@touchend="renderswipe.touchend">
+				<!-- #endif -->
+				<!-- 在微信小程序 app vue端 h5 使用wxs 实现-->
+				<view class="uni-swipe_button-group button-group--left">
+					<slot name="left">
+						<view v-for="(item,index) in leftOptions" :key="index" :style="{
+					  backgroundColor: item.style && item.style.backgroundColor ? item.style.backgroundColor : '#C7C6CD'
+					}" class="uni-swipe_button button-hock" @touchstart="appTouchStart"
+							@touchend="appTouchEnd($event,index,item,'left')"
+							@click.stop="onClickForPC(index,item,'left')">
+							<text class="uni-swipe_button-text"
+								:style="{color: item.style && item.style.color ? item.style.color : '#FFFFFF',fontSize: item.style && item.style.fontSize ? item.style.fontSize : '16px'}">{{ item.text }}</text>
+						</view>
+					</slot>
+				</view>
+				<view class="uni-swipe_text--center">
+					<slot></slot>
+				</view>
+				<view class="uni-swipe_button-group button-group--right">
+					<slot name="right">
+						<view v-for="(item,index) in rightOptions" :key="index" :style="{
+					  backgroundColor: item.style && item.style.backgroundColor ? item.style.backgroundColor : '#C7C6CD'
+					}" class="uni-swipe_button button-hock" @touchstart="appTouchStart"
+							@touchend="appTouchEnd($event,index,item,'right')"
+							@click.stop="onClickForPC(index,item,'right')"><text class="uni-swipe_button-text"
+								:style="{color: item.style && item.style.color ? item.style.color : '#FFFFFF',fontSize: item.style && item.style.fontSize ? item.style.fontSize : '16px'}">{{ item.text }}</text>
+						</view>
+					</slot>
+				</view>
+			</view>
+		</view>
+		<!-- #endif -->
+		<!-- app nvue端 使用 bindingx -->
+		<!-- #ifdef APP-NVUE -->
+		<view ref="selector-box--hock" class="uni-swipe" @horizontalpan="touchstart" @touchend="touchend">
+			<view ref='selector-left-button--hock' class="uni-swipe_button-group button-group--left">
+				<slot name="left">
+					<view v-for="(item,index) in leftOptions" :key="index" :style="{
+				  backgroundColor: item.style && item.style.backgroundColor ? item.style.backgroundColor : '#C7C6CD'
+				}" class="uni-swipe_button button-hock" @click.stop="onClick(index,item,'left')"><text
+							class="uni-swipe_button-text"
+							:style="{color: item.style && item.style.color ? item.style.color : '#FFFFFF', fontSize: item.style && item.style.fontSize ? item.style.fontSize : '16px'}">{{ item.text }}</text>
+					</view>
+				</slot>
+			</view>
+			<view ref='selector-right-button--hock' class="uni-swipe_button-group button-group--right">
+				<slot name="right">
+					<view v-for="(item,index) in rightOptions" :key="index" :style="{
+				  backgroundColor: item.style && item.style.backgroundColor ? item.style.backgroundColor : '#C7C6CD'
+				}" class="uni-swipe_button button-hock" @click.stop="onClick(index,item,'right')"><text
+							class="uni-swipe_button-text"
+							:style="{color: item.style && item.style.color ? item.style.color : '#FFFFFF',fontSize: item.style && item.style.fontSize ? item.style.fontSize : '16px'}">{{ item.text }}</text>
+					</view>
+				</slot>
+			</view>
+			<view ref='selector-content--hock' class="uni-swipe_box">
+				<slot></slot>
+			</view>
+		</view>
+		<!-- #endif -->
+		<!-- 其他平台使用 js ,长列表性能可能会有影响-->
+		<!-- #ifdef MP-ALIPAY || MP-BAIDU || MP-TOUTIAO || MP-QQ -->
+		<view class="uni-swipe">
+			<view class="uni-swipe_box" @touchstart="touchstart" @touchmove="touchmove" @touchend="touchend"
+				:style="{transform:moveLeft}" :class="{ani:ani}">
+				<view class="uni-swipe_button-group button-group--left" :class="[elClass]">
+					<slot name="left">
+						<view v-for="(item,index) in leftOptions" :key="index" :style="{
+					  backgroundColor: item.style && item.style.backgroundColor ? item.style.backgroundColor : '#C7C6CD',
+					  fontSize: item.style && item.style.fontSize ? item.style.fontSize : '16px'
+					}" class="uni-swipe_button button-hock" @touchstart="appTouchStart"
+							@touchend="appTouchEnd($event,index,item,'left')"><text class="uni-swipe_button-text"
+								:style="{color: item.style && item.style.color ? item.style.color : '#FFFFFF',}">{{ item.text }}</text>
+						</view>
+					</slot>
+				</view>
+				<slot></slot>
+				<view class="uni-swipe_button-group button-group--right" :class="[elClass]">
+					<slot name="right">
+						<view v-for="(item,index) in rightOptions" :key="index" :style="{
+					  backgroundColor: item.style && item.style.backgroundColor ? item.style.backgroundColor : '#C7C6CD',
+					  fontSize: item.style && item.style.fontSize ? item.style.fontSize : '16px'
+					}" @touchstart="appTouchStart" @touchend="appTouchEnd($event,index,item,'right')"
+							class="uni-swipe_button button-hock"><text class="uni-swipe_button-text"
+								:style="{color: item.style && item.style.color ? item.style.color : '#FFFFFF',}">{{ item.text }}</text>
+						</view>
+					</slot>
+				</view>
+			</view>
+		</view>
+		<!-- #endif -->
+
+</template>
+<script src="./wx.wxs" module="wxsswipe" lang="wxs"></script>
+
+<script module="renderswipe" lang="renderjs">
+	import render from './render.js'
+	export default {
+		mounted(e, ins, owner) {
+			this.state = {}
+		},
+		methods: {
+			showWatch(newVal, oldVal, ownerInstance, instance) {
+				render.showWatch(newVal, oldVal, ownerInstance, instance, this)
+			},
+			touchstart(e, ownerInstance) {
+				render.touchstart(e, ownerInstance, this)
+			},
+			touchmove(e, ownerInstance) {
+				render.touchmove(e, ownerInstance, this)
+			},
+			touchend(e, ownerInstance) {
+				render.touchend(e, ownerInstance, this)
+			}
+		}
+	}
+</script>
+<script>
+	import mpwxs from './mpwxs'
+	import bindingx from './bindingx.js'
+	import mpother from './mpother'
+
+	/**
+	 * SwipeActionItem 滑动操作子组件
+	 * @description 通过滑动触发选项的容器
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=181
+	 * @property {Boolean} show = [left|right|none] 	开启关闭组件,auto-close = false 时生效
+	 * @property {Boolean} disabled = [true|false] 		是否禁止滑动
+	 * @property {Boolean} autoClose = [true|false] 	滑动打开当前组件,是否关闭其他组件
+	 * @property {Number}  threshold 					滑动缺省值
+	 * @property {Array} leftOptions 					左侧选项内容及样式
+	 * @property {Array} rgihtOptions 					右侧选项内容及样式
+	 * @event {Function} click 							点击选项按钮时触发事件,e = {content,index} ,content(点击内容)、index(下标)
+	 * @event {Function} change 						组件打开或关闭时触发,left\right\none
+	 */
+
+	export default {
+		mixins: [mpwxs, bindingx, mpother],
+		emits: ['click', 'change'],
+		props: {
+			// 控制开关
+			show: {
+				type: String,
+				default: 'none'
+			},
+
+			// 禁用
+			disabled: {
+				type: Boolean,
+				default: false
+			},
+
+			// 是否自动关闭
+			autoClose: {
+				type: Boolean,
+				default: true
+			},
+
+			// 滑动缺省距离
+			threshold: {
+				type: Number,
+				default: 20
+			},
+
+			// 左侧按钮内容
+			leftOptions: {
+				type: Array,
+				default () {
+					return []
+				}
+			},
+
+			// 右侧按钮内容
+			rightOptions: {
+				type: Array,
+				default () {
+					return []
+				}
+			}
+
+		},
+		// #ifndef VUE3
+		// TODO vue2
+		destroyed() {
+			if (this.__isUnmounted) return
+			this.uninstall()
+		},
+		// #endif
+		// #ifdef VUE3
+		// TODO vue3
+		unmounted() {
+			this.__isUnmounted = true
+			this.uninstall()
+		},
+		// #endif
+
+		methods: {
+			uninstall() {
+				if (this.swipeaction) {
+					this.swipeaction.children.forEach((item, index) => {
+						if (item === this) {
+							this.swipeaction.children.splice(index, 1)
+						}
+					})
+				}
+			},
+			/**
+			 * 获取父元素实例
+			 */
+			getSwipeAction(name = 'uniSwipeAction') {
+				let parent = this.$parent;
+				let parentName = parent.$options.name;
+				while (parentName !== name) {
+					parent = parent.$parent;
+					if (!parent) return false;
+					parentName = parent.$options.name;
+				}
+				return parent;
+			}
+		}
+	}
+</script>
+<style lang="scss">
+	.uni-swipe {
+		position: relative;
+		/* #ifndef APP-NVUE */
+		overflow: hidden;
+		/* #endif */
+	}
+
+	.uni-swipe_box {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		flex-shrink: 0;
+		// touch-action: none;
+		/* #endif */
+		position: relative;
+	}
+
+	.uni-swipe_content {
+		// border: 1px red solid;
+	}
+
+	.uni-swipe_text--center {
+		width: 100%;
+		/* #ifndef APP-NVUE */
+		cursor: grab;
+		/* #endif */
+	}
+
+	.uni-swipe_button-group {
+		/* #ifndef APP-NVUE */
+		box-sizing: border-box;
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		position: absolute;
+		top: 0;
+		bottom: 0;
+		/* #ifdef H5 */
+		cursor: pointer;
+		/* #endif */
+	}
+
+	.button-group--left {
+		left: 0;
+		transform: translateX(-100%)
+	}
+
+	.button-group--right {
+		right: 0;
+		transform: translateX(100%)
+	}
+
+	.uni-swipe_button {
+		/* #ifdef APP-NVUE */
+		flex: 1;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		justify-content: center;
+		align-items: center;
+		padding: 0 20px;
+	}
+
+	.uni-swipe_button-text {
+		/* #ifndef APP-NVUE */
+		flex-shrink: 0;
+		/* #endif */
+		font-size: 14px;
+	}
+
+	.ani {
+		transition-property: transform;
+		transition-duration: 0.3s;
+		transition-timing-function: cubic-bezier(0.165, 0.84, 0.44, 1);
+	}
+
+	/* #ifdef MP-ALIPAY */
+	.movable-area {
+		/* width: 100%; */
+		height: 45px;
+	}
+
+	.movable-view {
+		display: flex;
+		/* justify-content: center; */
+		position: relative;
+		flex: 1;
+		height: 45px;
+		z-index: 2;
+	}
+
+	.movable-view-button {
+		display: flex;
+		flex-shrink: 0;
+		flex-direction: row;
+		height: 100%;
+		background: #C0C0C0;
+	}
+
+	/* .transition {
+		transition: all 0.3s;
+	} */
+
+	.movable-view-box {
+		flex-shrink: 0;
+		height: 100%;
+		background-color: #fff;
+	}
+
+	/* #endif */
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-swipe-action/components/uni-swipe-action-item/wx.wxs b/yudao-ui-admin-uniapp/uni_modules/uni-swipe-action/components/uni-swipe-action-item/wx.wxs
new file mode 100644
index 000000000..b394244f2
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-swipe-action/components/uni-swipe-action-item/wx.wxs
@@ -0,0 +1,341 @@
+var MIN_DISTANCE = 10;
+
+/**
+ * 判断当前是否为H5、app-vue
+ */
+var IS_HTML5 = false
+if (typeof window === 'object') IS_HTML5 = true
+
+/**
+ * 监听页面内值的变化,主要用于动态开关swipe-action
+ * @param {Object} newValue
+ * @param {Object} oldValue
+ * @param {Object} ownerInstance
+ * @param {Object} instance
+ */
+function showWatch(newVal, oldVal, ownerInstance, instance) {
+	var state = instance.getState()
+	getDom(instance, ownerInstance)
+	if (newVal && newVal !== 'none') {
+		openState(newVal, instance, ownerInstance)
+		return
+	}
+
+	if (state.left) {
+		openState('none', instance, ownerInstance)
+	}
+	resetTouchStatus(instance)
+}
+
+/**
+ * 开始触摸操作
+ * @param {Object} e
+ * @param {Object} ins
+ */
+function touchstart(e, ownerInstance) {
+	var instance = e.instance;
+	var disabled = instance.getDataset().disabled
+	var state = instance.getState();
+	getDom(instance, ownerInstance)
+	// fix by mehaotian, TODO 兼容 app-vue 获取dataset为字符串 , h5 获取 为 undefined 的问题,待框架修复
+	disabled = (typeof(disabled) === 'string' ? JSON.parse(disabled) : disabled) || false;
+	if (disabled) return
+	// 开始触摸时移除动画类
+	instance.requestAnimationFrame(function() {
+		instance.removeClass('ani');
+		ownerInstance.callMethod('closeSwipe');
+	})
+
+	// 记录上次的位置
+	state.x = state.left || 0
+	// 计算滑动开始位置
+	stopTouchStart(e, ownerInstance)
+}
+
+/**
+ * 开始滑动操作
+ * @param {Object} e
+ * @param {Object} ownerInstance
+ */
+function touchmove(e, ownerInstance) {
+	var instance = e.instance;
+	var disabled = instance.getDataset().disabled
+	var state = instance.getState()
+	// fix by mehaotian, TODO 兼容 app-vue 获取dataset为字符串 , h5 获取 为 undefined 的问题,待框架修复
+	disabled = (typeof(disabled) === 'string' ? JSON.parse(disabled) : disabled) || false;
+	if (disabled) return
+	// 是否可以滑动页面
+	stopTouchMove(e);
+	if (state.direction !== 'horizontal') {
+		return;
+	}
+
+	if (e.preventDefault) {
+		// 阻止页面滚动
+		e.preventDefault()
+	}
+
+	move(state.x + state.deltaX, instance, ownerInstance)
+}
+
+/**
+ * 结束触摸操作
+ * @param {Object} e
+ * @param {Object} ownerInstance
+ */
+function touchend(e, ownerInstance) {
+	var instance = e.instance;
+	var disabled = instance.getDataset().disabled
+	var state = instance.getState()
+	// fix by mehaotian, TODO 兼容 app-vue 获取dataset为字符串 , h5 获取 为 undefined 的问题,待框架修复
+	disabled = (typeof(disabled) === 'string' ? JSON.parse(disabled) : disabled) || false;
+
+	if (disabled) return
+	// 滑动过程中触摸结束,通过阙值判断是开启还是关闭
+	// fixed by mehaotian 定时器解决点击按钮,touchend 触发比 click 事件时机早的问题 ,主要是 ios13
+	moveDirection(state.left, instance, ownerInstance)
+
+}
+
+/**
+ * 设置移动距离
+ * @param {Object} value
+ * @param {Object} instance
+ * @param {Object} ownerInstance
+ */
+function move(value, instance, ownerInstance) {
+	value = value || 0
+	var state = instance.getState()
+	var leftWidth = state.leftWidth
+	var rightWidth = state.rightWidth
+	// 获取可滑动范围
+	state.left = range(value, -rightWidth, leftWidth);
+	instance.requestAnimationFrame(function() {
+		instance.setStyle({
+			transform: 'translateX(' + state.left + 'px)',
+			'-webkit-transform': 'translateX(' + state.left + 'px)'
+		})
+	})
+
+}
+
+/**
+ * 获取元素信息
+ * @param {Object} instance
+ * @param {Object} ownerInstance
+ */
+function getDom(instance, ownerInstance) {
+	var state = instance.getState()
+	var leftDom = ownerInstance.selectComponent('.button-group--left')
+	var rightDom = ownerInstance.selectComponent('.button-group--right')
+	var leftStyles = {
+		width: 0
+	}
+	var rightStyles = {
+		width: 0
+	}
+	leftStyles = leftDom.getBoundingClientRect()
+	rightStyles = rightDom.getBoundingClientRect()
+
+	state.leftWidth = leftStyles.width || 0
+	state.rightWidth = rightStyles.width || 0
+	state.threshold = instance.getDataset().threshold
+}
+
+/**
+ * 获取范围
+ * @param {Object} num
+ * @param {Object} min
+ * @param {Object} max
+ */
+function range(num, min, max) {
+	return Math.min(Math.max(num, min), max);
+}
+
+
+/**
+ * 移动方向判断
+ * @param {Object} left
+ * @param {Object} value
+ * @param {Object} ownerInstance
+ * @param {Object} ins
+ */
+function moveDirection(left, ins, ownerInstance) {
+	var state = ins.getState()
+	var threshold = state.threshold
+	var position = state.position
+	var isopen = state.isopen || 'none'
+	var leftWidth = state.leftWidth
+	var rightWidth = state.rightWidth
+	if (state.deltaX === 0) {
+		openState('none', ins, ownerInstance)
+		return
+	}
+	if ((isopen === 'none' && rightWidth > 0 && -left > threshold) || (isopen !== 'none' && rightWidth > 0 &&
+			rightWidth +
+			left < threshold)) {
+		// right
+		openState('right', ins, ownerInstance)
+	} else if ((isopen === 'none' && leftWidth > 0 && left > threshold) || (isopen !== 'none' && leftWidth > 0 &&
+			leftWidth - left < threshold)) {
+		// left
+		openState('left', ins, ownerInstance)
+	} else {
+		// default
+		openState('none', ins, ownerInstance)
+	}
+}
+
+
+/**
+ * 开启状态
+ * @param {Boolean} type
+ * @param {Object} ins
+ * @param {Object} ownerInstance
+ */
+function openState(type, ins, ownerInstance) {
+	var state = ins.getState()
+	var leftWidth = state.leftWidth
+	var rightWidth = state.rightWidth
+	var left = ''
+	state.isopen = state.isopen ? state.isopen : 'none'
+	switch (type) {
+		case "left":
+			left = leftWidth
+			break
+		case "right":
+			left = -rightWidth
+			break
+		default:
+			left = 0
+	}
+
+	// && !state.throttle
+
+	if (state.isopen !== type) {
+		state.throttle = true
+		ownerInstance.callMethod('change', {
+			open: type
+		})
+
+	}
+
+	state.isopen = type
+	// 添加动画类
+	ins.requestAnimationFrame(function() {
+		ins.addClass('ani');
+		move(left, ins, ownerInstance)
+	})
+	// 设置最终移动位置,理论上只要进入到这个函数,肯定是要打开的
+}
+
+
+function getDirection(x, y) {
+	if (x > y && x > MIN_DISTANCE) {
+		return 'horizontal';
+	}
+	if (y > x && y > MIN_DISTANCE) {
+		return 'vertical';
+	}
+	return '';
+}
+
+/**
+ * 重置滑动状态
+ * @param {Object} event
+ */
+function resetTouchStatus(instance) {
+	var state = instance.getState();
+	state.direction = '';
+	state.deltaX = 0;
+	state.deltaY = 0;
+	state.offsetX = 0;
+	state.offsetY = 0;
+}
+
+/**
+ * 设置滑动开始位置
+ * @param {Object} event
+ */
+function stopTouchStart(event) {
+	var instance = event.instance;
+	var state = instance.getState();
+	resetTouchStatus(instance);
+	var touch = event.touches[0];
+	if (IS_HTML5 && isPC()) {
+		touch = event;
+	}
+	state.startX = touch.clientX;
+	state.startY = touch.clientY;
+}
+
+/**
+ * 滑动中,是否禁止打开
+ * @param {Object} event
+ */
+function stopTouchMove(event) {
+	var instance = event.instance;
+	var state = instance.getState();
+	var touch = event.touches[0];
+	if (IS_HTML5 && isPC()) {
+		touch = event;
+	}
+	state.deltaX = touch.clientX - state.startX;
+	state.deltaY = touch.clientY - state.startY;
+	state.offsetY = Math.abs(state.deltaY);
+	state.offsetX = Math.abs(state.deltaX);
+	state.direction = state.direction || getDirection(state.offsetX, state.offsetY);
+}
+
+function isPC() {
+	var userAgentInfo = navigator.userAgent;
+	var Agents = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"];
+	var flag = true;
+	for (var v = 0; v < Agents.length - 1; v++) {
+		if (userAgentInfo.indexOf(Agents[v]) > 0) {
+			flag = false;
+			break;
+		}
+	}
+	return flag;
+}
+
+var movable = false
+
+function mousedown(e, ins) {
+	if (!IS_HTML5) return
+	if (!isPC()) return
+	touchstart(e, ins)
+	movable = true
+}
+
+function mousemove(e, ins) {
+	if (!IS_HTML5) return
+	if (!isPC()) return
+	if (!movable) return
+	touchmove(e, ins)
+}
+
+function mouseup(e, ins) {
+	if (!IS_HTML5) return
+	if (!isPC()) return
+	touchend(e, ins)
+	movable = false
+}
+
+function mouseleave(e, ins) {
+	if (!IS_HTML5) return
+	if (!isPC()) return
+	movable = false
+}
+
+module.exports = {
+	showWatch: showWatch,
+	touchstart: touchstart,
+	touchmove: touchmove,
+	touchend: touchend,
+	mousedown: mousedown,
+	mousemove: mousemove,
+	mouseup: mouseup,
+	mouseleave: mouseleave
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-swipe-action/components/uni-swipe-action/uni-swipe-action.vue b/yudao-ui-admin-uniapp/uni_modules/uni-swipe-action/components/uni-swipe-action/uni-swipe-action.vue
new file mode 100644
index 000000000..49717824c
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-swipe-action/components/uni-swipe-action/uni-swipe-action.vue
@@ -0,0 +1,60 @@
+<template>
+	<view>
+		<slot></slot>
+	</view>
+</template>
+
+<script>
+	/**
+	 * SwipeAction 滑动操作
+	 * @description 通过滑动触发选项的容器
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=181
+	 */
+	export default {
+		name:"uniSwipeAction",
+		data() {
+			return {};
+		},
+		created() {
+			this.children = [];
+		},
+		methods: {
+			// 公开给用户使用,重制组件样式
+			resize(){
+				// wxs 会自己计算组件大小,所以无需执行下面代码
+				// #ifndef APP-VUE || H5 || MP-WEIXIN
+				this.children.forEach(vm=>{
+					vm.init()
+				})
+				// #endif
+			},
+			// 公开给用户使用,关闭全部 已经打开的组件
+			closeAll(){
+				this.children.forEach(vm=>{
+					// #ifdef APP-VUE || H5 || MP-WEIXIN
+					vm.is_show = 'none'
+					// #endif
+
+					// #ifndef APP-VUE || H5 || MP-WEIXIN
+					vm.close()
+					// #endif
+				})
+			},
+			closeOther(vm) {
+				if (this.openItem && this.openItem !== vm) {
+					// #ifdef APP-VUE || H5 || MP-WEIXIN
+					this.openItem.is_show = 'none'
+					// #endif
+
+					// #ifndef APP-VUE || H5 || MP-WEIXIN
+					this.openItem.close()
+					// #endif
+				}
+				// 记录上一个打开的 swipe-action-item ,用于 auto-close
+				this.openItem = vm
+			}
+		}
+	};
+</script>
+
+<style></style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-swipe-action/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-swipe-action/package.json
new file mode 100644
index 000000000..c8998d9d6
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-swipe-action/package.json
@@ -0,0 +1,87 @@
+{
+	"id": "uni-swipe-action",
+	"displayName": "uni-swipe-action 滑动操作",
+	"version": "1.3.7",
+	"description": "SwipeAction 滑动操作操作组件",
+	"keywords": [
+        "",
+        "uni-ui",
+        "uniui",
+        "滑动删除",
+        "侧滑删除"
+    ],
+	"repository": "https://github.com/dcloudio/uni-ui",
+	"engines": {
+		"HBuilderX": ""
+	},
+	"directories": {
+		"example": "../../temps/example_temps"
+	},
+	"dcloudext": {
+		"category": [
+			"前端组件",
+			"通用组件"
+		],
+		"sale": {
+			"regular": {
+				"price": "0.00"
+			},
+			"sourcecode": {
+				"price": "0.00"
+			}
+		},
+		"contact": {
+			"qq": ""
+		},
+		"declaration": {
+			"ads": "无",
+			"data": "无",
+			"permissions": "无"
+		},
+		"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+	},
+	"uni_modules": {
+		"dependencies": ["uni-scss"],
+		"encrypt": [],
+		"platforms": {
+			"cloud": {
+				"tcb": "y",
+				"aliyun": "y"
+			},
+			"client": {
+				"App": {
+					"app-vue": "y",
+					"app-nvue": "y"
+				},
+				"H5-mobile": {
+					"Safari": "y",
+					"Android Browser": "y",
+					"微信浏览器(Android)": "y",
+					"QQ浏览器(Android)": "y"
+				},
+				"H5-pc": {
+					"Chrome": "y",
+					"IE": "y",
+					"Edge": "y",
+					"Firefox": "y",
+					"Safari": "y"
+				},
+				"小程序": {
+					"微信": "y",
+					"阿里": "y",
+					"百度": "y",
+					"字节跳动": "y",
+					"QQ": "y"
+				},
+				"快应用": {
+					"华为": "y",
+					"联盟": "u"
+				},
+				"Vue": {
+					"vue2": "y",
+					"vue3": "y"
+				}
+			}
+		}
+	}
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-swipe-action/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-swipe-action/readme.md
new file mode 100644
index 000000000..93a5cac6e
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-swipe-action/readme.md
@@ -0,0 +1,11 @@
+
+
+## SwipeAction 滑动操作
+> **组件名:uni-swipe-action**
+> 代码块: `uSwipeAction`、`uSwipeActionItem`
+
+
+通过滑动触发选项的容器
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-swipe-action)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-swiper-dot/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-swiper-dot/changelog.md
new file mode 100644
index 000000000..85cf54d2a
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-swiper-dot/changelog.md
@@ -0,0 +1,12 @@
+## 1.2.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-swiper-dot](https://uniapp.dcloud.io/component/uniui/uni-swiper-dot)
+## 1.1.0(2021-07-30)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.0.6(2021-05-12)
+- 新增 示例地址
+- 修复 示例项目缺少组件的Bug
+## 1.0.5(2021-02-05)
+- 调整为uni_modules目录规范
+- 新增 clickItem 事件,支持指示点控制轮播
+- 新增 支持 pc 可用
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-swiper-dot/components/uni-swiper-dot/uni-swiper-dot.vue b/yudao-ui-admin-uniapp/uni_modules/uni-swiper-dot/components/uni-swiper-dot/uni-swiper-dot.vue
new file mode 100644
index 000000000..46eb8c1fa
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-swiper-dot/components/uni-swiper-dot/uni-swiper-dot.vue
@@ -0,0 +1,218 @@
+<template>
+	<view class="uni-swiper__warp">
+		<slot />
+		<view v-if="mode === 'default'" :style="{'bottom':dots.bottom + 'px'}" class="uni-swiper__dots-box" key='default'>
+			<view v-for="(item,index) in info" @click="clickItem(index)" :style="{
+        'width': (index === current? dots.width*2:dots.width ) + 'px','height':dots.width/2 +'px' ,'background-color':index !== current?dots.backgroundColor:dots.selectedBackgroundColor,'border-radius':'0px'}"
+			 :key="index" class="uni-swiper__dots-item uni-swiper__dots-bar" />
+		</view>
+		<view v-if="mode === 'dot'" :style="{'bottom':dots.bottom + 'px'}" class="uni-swiper__dots-box" key='dot'>
+			<view v-for="(item,index) in info" @click="clickItem(index)" :style="{
+        'width': dots.width + 'px','height':dots.height +'px' ,'background-color':index !== current?dots.backgroundColor:dots.selectedBackgroundColor,'border':index !==current ? dots.border:dots.selectedBorder}"
+			 :key="index" class="uni-swiper__dots-item" />
+		</view>
+		<view v-if="mode === 'round'" :style="{'bottom':dots.bottom + 'px'}" class="uni-swiper__dots-box" key='round'>
+			<view v-for="(item,index) in info" @click="clickItem(index)" :class="[index === current&&'uni-swiper__dots-long']" :style="{
+		    'width':(index === current? dots.width*3:dots.width ) + 'px','height':dots.height +'px' ,'background-color':index !== current?dots.backgroundColor:dots.selectedBackgroundColor,'border':index !==current ? dots.border:dots.selectedBorder}"
+			 :key="index" class="uni-swiper__dots-item " />
+		</view>
+		<view v-if="mode === 'nav'" key='nav' :style="{'background-color':dotsStyles.backgroundColor,'bottom':'0'}" class="uni-swiper__dots-box uni-swiper__dots-nav">
+			<text :style="{'color':dotsStyles.color}" class="uni-swiper__dots-nav-item">{{ (current+1)+"/"+info.length +' ' +info[current][field] }}</text>
+		</view>
+		<view v-if="mode === 'indexes'" key='indexes' :style="{'bottom':dots.bottom + 'px'}" class="uni-swiper__dots-box">
+			<view v-for="(item,index) in info" @click="clickItem(index)" :style="{
+        'width':dots.width + 'px','height':dots.height +'px' ,'color':index === current?dots.selectedColor:dots.color,'background-color':index !== current?dots.backgroundColor:dots.selectedBackgroundColor,'border':index !==current ? dots.border:dots.selectedBorder}"
+			 :key="index" class="uni-swiper__dots-item uni-swiper__dots-indexes"><text class="uni-swiper__dots-indexes-text">{{ index+1 }}</text></view>
+		</view>
+	</view>
+</template>
+
+<script>
+
+	/**
+	 * SwiperDod 轮播图指示点
+	 * @description 自定义轮播图指示点
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=284
+	 * @property {Number} current 当前指示点索引,必须是通过 `swiper` 的 `change` 事件获取到的 `e.detail.current`
+	 * @property {String} mode = [default|round|nav|indexes] 指示点的类型
+	 * 	@value defualt 默认指示点
+	 * 	@value round 圆形指示点
+	 * 	@value nav 条形指示点
+	 * 	@value indexes 索引指示点
+	 * @property {String} field mode 为 nav 时,显示的内容字段(mode = nav 时必填)
+	 * @property {String} info 轮播图的数据,通过数组长度决定指示点个数
+	 * @property {Object} dotsStyles 指示点样式
+	 * @event {Function} clickItem 组件触发点击事件时触发,e={currentIndex}
+	 */
+
+	export default {
+		name: 'UniSwiperDot',
+		emits:['clickItem'],
+		props: {
+			info: {
+				type: Array,
+				default () {
+					return []
+				}
+			},
+			current: {
+				type: Number,
+				default: 0
+			},
+			dotsStyles: {
+				type: Object,
+				default () {
+					return {}
+				}
+			},
+			// 类型 :default(默认) indexes long nav
+			mode: {
+				type: String,
+				default: 'default'
+			},
+			// 只在 nav 模式下生效,变量名称
+			field: {
+				type: String,
+				default: ''
+			}
+		},
+		data() {
+			return {
+				dots: {
+					width: 6,
+					height: 6,
+					bottom: 10,
+					color: '#fff',
+					backgroundColor: 'rgba(0, 0, 0, .3)',
+					border: '1px rgba(0, 0, 0, .3) solid',
+					selectedBackgroundColor: '#333',
+					selectedBorder: '1px rgba(0, 0, 0, .9) solid'
+				}
+			}
+		},
+		watch: {
+			dotsStyles(newVal) {
+				this.dots = Object.assign(this.dots, this.dotsStyles)
+			},
+			mode(newVal) {
+				if (newVal === 'indexes') {
+					this.dots.width = 14
+					this.dots.height = 14
+				} else {
+					this.dots.width = 6
+					this.dots.height = 6
+				}
+			}
+
+		},
+		created() {
+			if (this.mode === 'indexes') {
+				this.dots.width = 12
+				this.dots.height = 12
+			}
+			this.dots = Object.assign(this.dots, this.dotsStyles)
+		},
+		methods: {
+			clickItem(index) {
+				this.$emit('clickItem', index)
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.uni-swiper__warp {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex: 1;
+		flex-direction: column;
+		position: relative;
+		overflow: hidden;
+	}
+
+	.uni-swiper__dots-box {
+		position: absolute;
+		bottom: 10px;
+		left: 0;
+		right: 0;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex: 1;
+		flex-direction: row;
+		justify-content: center;
+		align-items: center;
+	}
+
+	.uni-swiper__dots-item {
+		width: 8px;
+		border-radius: 100px;
+		margin-left: 6px;
+		background-color: rgba(0, 0, 0, 0.4);
+		/* #ifndef APP-NVUE */
+		cursor: pointer;
+		/* #endif */
+		/* #ifdef H5 */
+		// border-width: 5px 0;
+		// border-style: solid;
+		// border-color: transparent;
+		// background-clip: padding-box;
+		/* #endif */
+		// transition: width 0.2s linear;  不要取消注释,不然会不能变色
+	}
+
+	.uni-swiper__dots-item:first-child {
+		margin: 0;
+	}
+
+	.uni-swiper__dots-default {
+		border-radius: 100px;
+	}
+
+	.uni-swiper__dots-long {
+		border-radius: 50px;
+	}
+
+	.uni-swiper__dots-bar {
+		border-radius: 50px;
+	}
+
+	.uni-swiper__dots-nav {
+		bottom: 0px;
+		// height: 26px;
+		padding: 8px 0;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex: 1;
+		flex-direction: row;
+		justify-content: flex-start;
+		align-items: center;
+		background-color: rgba(0, 0, 0, 0.2);
+	}
+
+	.uni-swiper__dots-nav-item {
+		/* overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap; */
+		font-size: 14px;
+		color: #fff;
+		margin: 0 15px;
+	}
+
+	.uni-swiper__dots-indexes {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		// flex: 1;
+		justify-content: center;
+		align-items: center;
+	}
+
+	.uni-swiper__dots-indexes-text {
+		color: #fff;
+		font-size: 12px;
+		line-height: 14px;
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-swiper-dot/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-swiper-dot/package.json
new file mode 100644
index 000000000..f2dd8d2a8
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-swiper-dot/package.json
@@ -0,0 +1,87 @@
+{
+  "id": "uni-swiper-dot",
+  "displayName": "uni-swiper-dot 轮播图指示点",
+  "version": "1.2.0",
+  "description": "自定义轮播图指示点组件",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "轮播图指示点",
+    "dot",
+    "swiper"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": ["uni-scss"],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-swiper-dot/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-swiper-dot/readme.md
new file mode 100644
index 000000000..7d397e2cc
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-swiper-dot/readme.md
@@ -0,0 +1,11 @@
+
+
+## SwiperDot 轮播图指示点
+> **组件名:uni-swiper-dot**
+> 代码块: `uSwiperDot`
+
+
+自定义轮播图指示点
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-swiper-dot)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-table/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-table/changelog.md
new file mode 100644
index 000000000..8233b20f1
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-table/changelog.md
@@ -0,0 +1,23 @@
+## 1.2.1(2022-06-06)
+- 修复 微信小程序存在无使用组件的问题
+## 1.2.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-table](https://uniapp.dcloud.io/component/uniui/uni-table)
+## 1.1.0(2021-07-30)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.0.7(2021-07-08)
+- 新增 uni-th 支持 date 日期筛选范围
+## 1.0.6(2021-07-05)
+- 新增 uni-th 支持 range 筛选范围
+## 1.0.5(2021-06-28)
+- 新增 uni-th 筛选功能
+## 1.0.4(2021-05-12)
+- 新增 示例地址
+- 修复 示例项目缺少组件的Bug
+## 1.0.3(2021-04-16)
+- 新增 sortable 属性,是否开启单列排序
+- 优化 表格多选逻辑
+## 1.0.2(2021-03-22)
+- uni-tr 添加 disabled 属性,用于 type=selection 时,设置某行是否可由全选按钮控制
+## 1.0.1(2021-02-05)
+- 调整为uni_modules目录规范
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-table/components/uni-table/uni-table.vue b/yudao-ui-admin-uniapp/uni_modules/uni-table/components/uni-table/uni-table.vue
new file mode 100644
index 000000000..91b74fa78
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-table/components/uni-table/uni-table.vue
@@ -0,0 +1,455 @@
+<template>
+	<view class="uni-table-scroll" :class="{ 'table--border': border, 'border-none': !noData }">
+		<!-- #ifdef H5 -->
+		<table class="uni-table" border="0" cellpadding="0" cellspacing="0" :class="{ 'table--stripe': stripe }" :style="{ 'min-width': minWidth + 'px' }">
+			<slot></slot>
+			<view v-if="noData" class="uni-table-loading">
+				<view class="uni-table-text" :class="{ 'empty-border': border }">{{ emptyText }}</view>
+			</view>
+			<view v-if="loading" class="uni-table-mask" :class="{ 'empty-border': border }"><div class="uni-table--loader"></div></view>
+		</table>
+		<!-- #endif -->
+		<!-- #ifndef H5 -->
+		<view class="uni-table" :style="{ 'min-width': minWidth + 'px' }" :class="{ 'table--stripe': stripe }">
+			<slot></slot>
+			<view v-if="noData" class="uni-table-loading">
+				<view class="uni-table-text" :class="{ 'empty-border': border }">{{ emptyText }}</view>
+			</view>
+			<view v-if="loading" class="uni-table-mask" :class="{ 'empty-border': border }"><div class="uni-table--loader"></div></view>
+		</view>
+		<!-- #endif -->
+	</view>
+</template>
+
+<script>
+/**
+ * Table 表格
+ * @description 用于展示多条结构类似的数据
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=3270
+ * @property {Boolean} 	border 				是否带有纵向边框
+ * @property {Boolean} 	stripe 				是否显示斑马线
+ * @property {Boolean} 	type 					是否开启多选
+ * @property {String} 	emptyText 			空数据时显示的文本内容
+ * @property {Boolean} 	loading 			显示加载中
+ * @event {Function} 	selection-change 	开启多选时,当选择项发生变化时会触发该事件
+ */
+export default {
+	name: 'uniTable',
+	options: {
+		virtualHost: true
+	},
+	emits:['selection-change'],
+	props: {
+		data: {
+			type: Array,
+			default() {
+				return []
+			}
+		},
+		// 是否有竖线
+		border: {
+			type: Boolean,
+			default: false
+		},
+		// 是否显示斑马线
+		stripe: {
+			type: Boolean,
+			default: false
+		},
+		// 多选
+		type: {
+			type: String,
+			default: ''
+		},
+		// 没有更多数据
+		emptyText: {
+			type: String,
+			default: '没有更多数据'
+		},
+		loading: {
+			type: Boolean,
+			default: false
+		},
+		rowKey: {
+			type: String,
+			default: ''
+		}
+	},
+	data() {
+		return {
+			noData: true,
+			minWidth: 0,
+			multiTableHeads: []
+		}
+	},
+	watch: {
+		loading(val) {},
+		data(newVal) {
+			let theadChildren = this.theadChildren
+			let rowspan = 1
+			if (this.theadChildren) {
+				rowspan = this.theadChildren.rowspan
+			}
+			
+			// this.trChildren.length - rowspan
+			this.noData = false
+			// this.noData = newVal.length === 0 
+		}
+	},
+	created() {
+		// 定义tr的实例数组
+		this.trChildren = []
+		this.thChildren = []
+		this.theadChildren = null
+		this.backData = []
+		this.backIndexData = []
+	},
+
+	methods: {
+		isNodata() {
+			let theadChildren = this.theadChildren
+			let rowspan = 1
+			if (this.theadChildren) {
+				rowspan = this.theadChildren.rowspan
+			}
+			this.noData = this.trChildren.length - rowspan <= 0
+		},
+		/**
+		 * 选中所有
+		 */
+		selectionAll() {
+			let startIndex = 1
+			let theadChildren = this.theadChildren
+			if (!this.theadChildren) {
+				theadChildren = this.trChildren[0]
+			} else {
+				startIndex = theadChildren.rowspan - 1
+			}
+			let isHaveData = this.data && this.data.length.length > 0
+			theadChildren.checked = true
+			theadChildren.indeterminate = false
+			this.trChildren.forEach((item, index) => {
+				if (!item.disabled) {
+					item.checked = true
+					if (isHaveData && item.keyValue) {
+						const row = this.data.find(v => v[this.rowKey] === item.keyValue)
+						if (!this.backData.find(v => v[this.rowKey] === row[this.rowKey])) {
+							this.backData.push(row)
+						}
+					}
+					if (index > (startIndex - 1) && this.backIndexData.indexOf(index - startIndex) === -1) {
+						this.backIndexData.push(index - startIndex)
+					}
+				}
+			})
+			// this.backData = JSON.parse(JSON.stringify(this.data))
+			this.$emit('selection-change', {
+				detail: {
+					value: this.backData,
+					index: this.backIndexData
+				}
+			})
+		},
+		/**
+		 * 用于多选表格,切换某一行的选中状态,如果使用了第二个参数,则是设置这一行选中与否(selected 为 true 则选中)
+		 */
+		toggleRowSelection(row, selected) {
+			// if (!this.theadChildren) return
+			row = [].concat(row)
+
+			this.trChildren.forEach((item, index) => {
+				// if (item.keyValue) {
+
+				const select = row.findIndex(v => {
+					//
+					if (typeof v === 'number') {
+						return v === index - 1
+					} else {
+						return v[this.rowKey] === item.keyValue
+					}
+				})
+				let ischeck = item.checked
+				if (select !== -1) {
+					if (typeof selected === 'boolean') {
+						item.checked = selected
+					} else {
+						item.checked = !item.checked
+					}
+					if (ischeck !== item.checked) {
+						this.check(item.rowData||item, item.checked, item.rowData?item.keyValue:null, true)
+					}
+				}
+				// }
+			})
+			this.$emit('selection-change', {
+				detail: {
+					value: this.backData,
+					index:this.backIndexData
+				}
+			})
+		},
+
+		/**
+		 * 用于多选表格,清空用户的选择
+		 */
+		clearSelection() {
+			let theadChildren = this.theadChildren
+			if (!this.theadChildren) {
+				theadChildren = this.trChildren[0]
+			}
+			// if (!this.theadChildren) return
+			theadChildren.checked = false
+			theadChildren.indeterminate = false
+			this.trChildren.forEach(item => {
+				// if (item.keyValue) {
+					item.checked = false
+				// }
+			})
+			this.backData = []
+			this.backIndexData = []
+			this.$emit('selection-change', {
+				detail: {
+					value: [],
+					index: []
+				}
+			})
+		},
+		/**
+		 * 用于多选表格,切换所有行的选中状态
+		 */
+		toggleAllSelection() {
+			let list = []
+			let startIndex = 1
+			let theadChildren = this.theadChildren
+			if (!this.theadChildren) {
+				theadChildren = this.trChildren[0]
+			} else {
+				startIndex = theadChildren.rowspan - 1
+			}
+			this.trChildren.forEach((item, index) => {
+				if (!item.disabled) {
+					if (index > (startIndex - 1) ) {
+						list.push(index-startIndex)
+					}
+				}
+			})
+			this.toggleRowSelection(list)
+		},
+
+		/**
+		 * 选中\取消选中
+		 * @param {Object} child
+		 * @param {Object} check
+		 * @param {Object} rowValue
+		 */
+		check(child, check, keyValue, emit) {
+			let theadChildren = this.theadChildren
+			if (!this.theadChildren) {
+				theadChildren = this.trChildren[0]
+			}
+			
+			
+			
+			let childDomIndex = this.trChildren.findIndex((item, index) => child === item)
+			if(childDomIndex < 0){
+				childDomIndex = this.data.findIndex(v=>v[this.rowKey] === keyValue) + 1
+			}
+			const dataLen = this.trChildren.filter(v => !v.disabled && v.keyValue).length
+			if (childDomIndex === 0) {
+				check ? this.selectionAll() : this.clearSelection()
+				return
+			}
+
+			if (check) {
+				if (keyValue) {
+					this.backData.push(child)
+				}
+				this.backIndexData.push(childDomIndex - 1)
+			} else {
+				const index = this.backData.findIndex(v => v[this.rowKey] === keyValue)
+				const idx = this.backIndexData.findIndex(item => item === childDomIndex - 1)
+				if (keyValue) {
+					this.backData.splice(index, 1)
+				}
+				this.backIndexData.splice(idx, 1)
+			}
+
+			const domCheckAll = this.trChildren.find((item, index) => index > 0 && !item.checked && !item.disabled)
+			if (!domCheckAll) {
+				theadChildren.indeterminate = false
+				theadChildren.checked = true
+			} else {
+				theadChildren.indeterminate = true
+				theadChildren.checked = false
+			}
+
+			if (this.backIndexData.length === 0) {
+				theadChildren.indeterminate = false
+			}
+
+			if (!emit) {
+				this.$emit('selection-change', {
+					detail: {
+						value: this.backData,
+						index: this.backIndexData
+					}
+				})
+			}
+		}
+	}
+}
+</script>
+
+<style lang="scss">
+$border-color: #ebeef5;
+
+.uni-table-scroll {
+	width: 100%;
+	/* #ifndef APP-NVUE */
+	overflow-x: auto;
+	/* #endif */
+}
+
+.uni-table {
+	position: relative;
+	width: 100%;
+	border-radius: 5px;
+	// box-shadow: 0px 0px 3px 1px rgba(0, 0, 0, 0.1);
+	background-color: #fff;
+	/* #ifndef APP-NVUE */
+	box-sizing: border-box;
+	display: table;
+	overflow-x: auto;
+	::v-deep .uni-table-tr:nth-child(n + 2) {
+		&:hover {
+			background-color: #f5f7fa;
+		}
+	}
+	::v-deep .uni-table-thead {
+		.uni-table-tr {
+			// background-color: #f5f7fa;
+			&:hover {
+				background-color:#fafafa;
+			}
+		}
+	}
+	/* #endif */
+}
+
+.table--border {
+	border: 1px $border-color solid;
+	border-right: none;
+}
+
+.border-none {
+	/* #ifndef APP-NVUE */
+	border-bottom: none;
+	/* #endif */
+}
+
+.table--stripe {
+	/* #ifndef APP-NVUE */
+	::v-deep .uni-table-tr:nth-child(2n + 3) {
+		background-color: #fafafa;
+	}
+	/* #endif */
+}
+
+/* 表格加载、无数据样式 */
+.uni-table-loading {
+	position: relative;
+	/* #ifndef APP-NVUE */
+	display: table-row;
+	/* #endif */
+	height: 50px;
+	line-height: 50px;
+	overflow: hidden;
+	box-sizing: border-box;
+}
+.empty-border {
+	border-right: 1px $border-color solid;
+}
+.uni-table-text {
+	position: absolute;
+	right: 0;
+	left: 0;
+	text-align: center;
+	font-size: 14px;
+	color: #999;
+}
+
+.uni-table-mask {
+	position: absolute;
+	top: 0;
+	bottom: 0;
+	left: 0;
+	right: 0;
+	background-color: rgba(255, 255, 255, 0.8);
+	z-index: 99;
+	/* #ifndef APP-NVUE */
+	display: flex;
+	margin: auto;
+	transition: all 0.5s;
+	/* #endif */
+	justify-content: center;
+	align-items: center;
+}
+
+.uni-table--loader {
+	width: 30px;
+	height: 30px;
+	border: 2px solid #aaa;
+	// border-bottom-color: transparent;
+	border-radius: 50%;
+	/* #ifndef APP-NVUE */
+	animation: 2s uni-table--loader linear infinite;
+	/* #endif */
+	position: relative;
+}
+
+@keyframes uni-table--loader {
+	0% {
+		transform: rotate(360deg);
+	}
+
+	10% {
+		border-left-color: transparent;
+	}
+
+	20% {
+		border-bottom-color: transparent;
+	}
+
+	30% {
+		border-right-color: transparent;
+	}
+
+	40% {
+		border-top-color: transparent;
+	}
+
+	50% {
+		transform: rotate(0deg);
+	}
+
+	60% {
+		border-top-color: transparent;
+	}
+
+	70% {
+		border-left-color: transparent;
+	}
+
+	80% {
+		border-bottom-color: transparent;
+	}
+
+	90% {
+		border-right-color: transparent;
+	}
+
+	100% {
+		transform: rotate(-360deg);
+	}
+}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-table/components/uni-tbody/uni-tbody.vue b/yudao-ui-admin-uniapp/uni_modules/uni-table/components/uni-tbody/uni-tbody.vue
new file mode 100644
index 000000000..fbe1bdcb1
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-table/components/uni-tbody/uni-tbody.vue
@@ -0,0 +1,29 @@
+<template>
+	<!-- #ifdef H5 -->
+	<tbody>
+		<slot></slot>
+	</tbody>
+	<!-- #endif -->
+	<!-- #ifndef H5 -->
+	<view><slot></slot></view>
+	<!-- #endif -->
+</template>
+
+<script>
+export default {
+	name: 'uniBody',
+	options: {
+		virtualHost: true
+	},
+	data() {
+		return {
+			
+		}
+	},
+	created() {},
+	methods: {}
+}
+</script>
+
+<style>
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-table/components/uni-td/uni-td.vue b/yudao-ui-admin-uniapp/uni_modules/uni-table/components/uni-td/uni-td.vue
new file mode 100644
index 000000000..9ce93e936
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-table/components/uni-td/uni-td.vue
@@ -0,0 +1,90 @@
+<template>
+	<!-- #ifdef H5 -->
+	<td class="uni-table-td" :rowspan="rowspan" :colspan="colspan" :class="{'table--border':border}" :style="{width:width + 'px','text-align':align}">
+		<slot></slot>
+	</td>
+	<!-- #endif -->
+	<!-- #ifndef H5 -->
+	<!-- :class="{'table--border':border}"  -->
+	<view class="uni-table-td" :class="{'table--border':border}" :style="{width:width + 'px','text-align':align}">
+		<slot></slot>
+	</view>
+	<!-- #endif -->
+	
+</template>
+
+<script>
+	/**
+	 * Td 单元格
+	 * @description 表格中的标准单元格组件
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=3270
+	 * @property {Number} 	align = [left|center|right]	单元格对齐方式
+	 */
+	export default {
+		name: 'uniTd',
+		options: {
+			virtualHost: true
+		},
+		props: {
+			width: {
+				type: [String, Number],
+				default: ''
+			},
+			align: {
+				type: String,
+				default: 'left'
+			},
+			rowspan: {
+				type: [Number,String],
+				default: 1
+			},
+			colspan: {
+					type: [Number,String],
+				default: 1
+			}
+		},
+		data() {
+			return {
+				border: false
+			};
+		},
+		created() {
+			this.root = this.getTable()
+			this.border = this.root.border
+		},
+		methods: {
+			/**
+			 * 获取父元素实例
+			 */
+			getTable() {
+				let parent = this.$parent;
+				let parentName = parent.$options.name;
+				while (parentName !== 'uniTable') {
+					parent = parent.$parent;
+					if (!parent) return false;
+					parentName = parent.$options.name;
+				}
+				return parent;
+			},
+		}
+	}
+</script>
+
+<style lang="scss">
+	$border-color:#EBEEF5;
+
+	.uni-table-td {
+		display: table-cell;
+		padding: 8px 10px;
+		font-size: 14px;
+		border-bottom: 1px $border-color solid;
+		font-weight: 400;
+		color: #606266;
+		line-height: 23px;
+		box-sizing: border-box;
+	}
+
+	.table--border {
+		border-right: 1px $border-color solid;
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-table/components/uni-th/filter-dropdown.vue b/yudao-ui-admin-uniapp/uni_modules/uni-table/components/uni-th/filter-dropdown.vue
new file mode 100644
index 000000000..bc9a0e3b0
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-table/components/uni-th/filter-dropdown.vue
@@ -0,0 +1,503 @@
+<template>
+	<view class="uni-filter-dropdown">
+		<view class="dropdown-btn" @click="onDropdown">
+			<view class="icon-select" :class="{active: canReset}" v-if="isSelect || isRange"></view>
+			<view class="icon-search" :class="{active: canReset}" v-if="isSearch">
+				<view class="icon-search-0"></view>
+				<view class="icon-search-1"></view>
+			</view>
+			<view class="icon-calendar" :class="{active: canReset}" v-if="isDate">
+				<view class="icon-calendar-0"></view>
+				<view class="icon-calendar-1"></view>
+			</view>
+		</view>
+		<view class="uni-dropdown-cover" v-if="isOpened" @click="handleClose"></view>
+		<view class="dropdown-popup dropdown-popup-right" v-if="isOpened" @click.stop>
+			<!-- select-->
+			<view v-if="isSelect" class="list">
+				<label class="flex-r a-i-c list-item" v-for="(item,index) in dataList" :key="index"
+					@click="onItemClick($event, index)">
+					<check-box class="check" :checked="item.checked" />
+					<view class="checklist-content">
+						<text class="checklist-text" :style="item.styleIconText">{{item[map.text]}}</text>
+					</view>
+				</label>
+			</view>
+			<view v-if="isSelect" class="flex-r opera-area">
+				<view class="flex-f btn btn-default" :class="{disable: !canReset}" @click="handleSelectReset">
+					{{resource.reset}}</view>
+				<view class="flex-f btn btn-submit" @click="handleSelectSubmit">{{resource.submit}}</view>
+			</view>
+			<!-- search -->
+			<view v-if="isSearch" class="search-area">
+				<input class="search-input" v-model="filterValue" />
+			</view>
+			<view v-if="isSearch" class="flex-r opera-area">
+				<view class="flex-f btn btn-submit" @click="handleSearchSubmit">{{resource.search}}</view>
+				<view class="flex-f btn btn-default" :class="{disable: !canReset}" @click="handleSearchReset">
+					{{resource.reset}}</view>
+			</view>
+			<!-- range -->
+			<view v-if="isRange">
+				<view class="input-label">{{resource.gt}}</view>
+				<input class="input" v-model="gtValue" />
+				<view class="input-label">{{resource.lt}}</view>
+				<input class="input" v-model="ltValue" />
+			</view>
+			<view v-if="isRange" class="flex-r opera-area">
+				<view class="flex-f btn btn-default" :class="{disable: !canReset}" @click="handleRangeReset">
+					{{resource.reset}}</view>
+				<view class="flex-f btn btn-submit" @click="handleRangeSubmit">{{resource.submit}}</view>
+			</view>
+			<!-- date -->
+			<view v-if="isDate">
+				<uni-datetime-picker ref="datetimepicker" :value="dateRange" type="datetimerange" return-type="timestamp" @change="datetimechange" @maskClick="timepickerclose">
+					<view></view>
+				</uni-datetime-picker>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import checkBox from '../uni-tr/table-checkbox.vue'
+
+	const resource = {
+		"reset": "重置",
+		"search": "搜索",
+		"submit": "确定",
+		"filter": "筛选",
+		"gt": "大于等于",
+		"lt": "小于等于",
+		"date": "日期范围"
+	}
+
+	const DropdownType = {
+		Select: "select",
+		Search: "search",
+		Range: "range",
+		Date: "date",
+		Timestamp: "timestamp"
+	}
+
+	export default {
+		name: 'FilterDropdown',
+		emits:['change'],
+		components: {
+			checkBox
+		},
+		options: {
+			virtualHost: true
+		},
+		props: {
+			filterType: {
+				type: String,
+				default: DropdownType.Select
+			},
+			filterData: {
+				type: Array,
+				default () {
+					return []
+				}
+			},
+			mode: {
+				type: String,
+				default: 'default'
+			},
+			map: {
+				type: Object,
+				default () {
+					return {
+						text: 'text',
+						value: 'value'
+					}
+				}
+			}
+		},
+		computed: {
+			canReset() {
+				if (this.isSearch) {
+					return this.filterValue.length > 0
+				}
+				if (this.isSelect) {
+					return this.checkedValues.length > 0
+				}
+				if (this.isRange) {
+					return (this.gtValue.length > 0 && this.ltValue.length > 0)
+				}
+				if (this.isDate) {
+					return this.dateSelect.length > 0
+				}
+				return false
+			},
+			isSelect() {
+				return this.filterType === DropdownType.Select
+			},
+			isSearch() {
+				return this.filterType === DropdownType.Search
+			},
+			isRange() {
+				return this.filterType === DropdownType.Range
+			},
+			isDate() {
+				return (this.filterType === DropdownType.Date || this.filterType === DropdownType.Timestamp)
+			}
+		},
+		watch: {
+			filterData(newVal) {
+				this._copyFilters()
+			},
+			indeterminate(newVal) {
+				this.isIndeterminate = newVal
+			}
+		},
+		data() {
+			return {
+				resource,
+				enabled: true,
+				isOpened: false,
+				dataList: [],
+				filterValue: '',
+				checkedValues: [],
+				gtValue: '',
+				ltValue: '',
+				dateRange: [],
+				dateSelect: []
+			};
+		},
+		created() {
+			this._copyFilters()
+		},
+		methods: {
+			_copyFilters() {
+				let dl = JSON.parse(JSON.stringify(this.filterData))
+				for (let i = 0; i < dl.length; i++) {
+					if (dl[i].checked === undefined) {
+						dl[i].checked = false
+					}
+				}
+				this.dataList = dl
+			},
+			openPopup() {
+				this.isOpened = true
+				if (this.isDate) {
+					this.$nextTick(() => {
+						if (!this.dateRange.length) {
+							this.resetDate()
+						}
+						this.$refs.datetimepicker.show()
+					})
+				}
+			},
+			closePopup() {
+				this.isOpened = false
+			},
+			handleClose(e) {
+				this.closePopup()
+			},
+			resetDate() {
+				let date = new Date()
+				let dateText = date.toISOString().split('T')[0]
+				this.dateRange = [dateText + ' 0:00:00', dateText + ' 23:59:59']
+			},
+			onDropdown(e) {
+				this.openPopup()
+			},
+			onItemClick(e, index) {
+				let items = this.dataList
+				let listItem = items[index]
+				if (listItem.checked === undefined) {
+					items[index].checked = true
+				} else {
+					items[index].checked = !listItem.checked
+				}
+
+				let checkvalues = []
+				for (let i = 0; i < items.length; i++) {
+					const item = items[i]
+					if (item.checked) {
+						checkvalues.push(item.value)
+					}
+				}
+				this.checkedValues = checkvalues
+			},
+			datetimechange(e) {
+				this.closePopup()
+				this.dateRange = e
+				this.dateSelect = e
+				this.$emit('change', {
+					filterType: this.filterType,
+					filter: e
+				})
+			},
+			timepickerclose(e) {
+				this.closePopup()
+			},
+			handleSelectSubmit() {
+				this.closePopup()
+				this.$emit('change', {
+					filterType: this.filterType,
+					filter: this.checkedValues
+				})
+			},
+			handleSelectReset() {
+				if (!this.canReset) {
+					return;
+				}
+				var items = this.dataList
+				for (let i = 0; i < items.length; i++) {
+					let item = items[i]
+					this.$set(item, 'checked', false)
+				}
+				this.checkedValues = []
+				this.handleSelectSubmit()
+			},
+			handleSearchSubmit() {
+				this.closePopup()
+				this.$emit('change', {
+					filterType: this.filterType,
+					filter: this.filterValue
+				})
+			},
+			handleSearchReset() {
+				if (!this.canReset) {
+					return;
+				}
+				this.filterValue = ''
+				this.handleSearchSubmit()
+			},
+			handleRangeSubmit(isReset) {
+				this.closePopup()
+				this.$emit('change', {
+					filterType: this.filterType,
+					filter: isReset === true ? [] : [parseInt(this.gtValue), parseInt(this.ltValue)]
+				})
+			},
+			handleRangeReset() {
+				if (!this.canReset) {
+					return;
+				}
+				this.gtValue = ''
+				this.ltValue = ''
+				this.handleRangeSubmit(true)
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.flex-r {
+		display: flex;
+		flex-direction: row;
+	}
+
+	.flex-f {
+		flex: 1;
+	}
+
+	.a-i-c {
+		align-items: center;
+	}
+
+	.j-c-c {
+		justify-content: center;
+	}
+
+	.icon-select {
+		width: 14px;
+		height: 16px;
+		border: solid 6px transparent;
+		border-top: solid 6px #ddd;
+		border-bottom: none;
+		background-color: #ddd;
+		background-clip: content-box;
+		box-sizing: border-box;
+	}
+
+	.icon-select.active {
+		background-color: #1890ff;
+		border-top-color: #1890ff;
+	}
+
+	.icon-search {
+		width: 12px;
+		height: 16px;
+		position: relative;
+	}
+
+	.icon-search-0 {
+		border: 2px solid #ddd;
+		border-radius: 8px;
+		width: 7px;
+		height: 7px;
+	}
+
+	.icon-search-1 {
+		position: absolute;
+		top: 8px;
+		right: 0;
+		width: 1px;
+		height: 7px;
+		background-color: #ddd;
+		transform: rotate(-45deg);
+	}
+
+	.icon-search.active .icon-search-0 {
+		border-color: #1890ff;
+	}
+
+	.icon-search.active .icon-search-1 {
+		background-color: #1890ff;
+	}
+
+	.icon-calendar {
+		color: #ddd;
+		width: 14px;
+		height: 16px;
+	}
+
+	.icon-calendar-0 {
+		height: 4px;
+		margin-top: 3px;
+		margin-bottom: 1px;
+		background-color: #ddd;
+		border-radius: 2px 2px 1px 1px;
+		position: relative;
+	}
+	.icon-calendar-0:before, .icon-calendar-0:after {
+		content: '';
+		position: absolute;
+		top: -3px;
+		width: 4px;
+		height: 3px;
+		border-radius: 1px;
+		background-color: #ddd;
+	}
+	.icon-calendar-0:before {
+		left: 2px;
+	}
+	.icon-calendar-0:after {
+		right: 2px;
+	}
+
+	.icon-calendar-1 {
+		height: 9px;
+		background-color: #ddd;
+		border-radius: 1px 1px 2px 2px;
+	}
+
+	.icon-calendar.active {
+		color: #1890ff;
+	}
+
+	.icon-calendar.active .icon-calendar-0,
+	.icon-calendar.active .icon-calendar-1,
+	.icon-calendar.active .icon-calendar-0:before,
+	.icon-calendar.active .icon-calendar-0:after {
+		background-color: #1890ff;
+	}
+
+	.uni-filter-dropdown {
+		position: relative;
+		font-weight: normal;
+	}
+
+	.dropdown-popup {
+		position: absolute;
+		top: 100%;
+		background-color: #fff;
+		box-shadow: 0 3px 6px -4px #0000001f, 0 6px 16px #00000014, 0 9px 28px 8px #0000000d;
+		min-width: 150px;
+		z-index: 1000;
+	}
+
+	.dropdown-popup-left {
+		left: 0;
+	}
+
+	.dropdown-popup-right {
+		right: 0;
+	}
+
+	.uni-dropdown-cover {
+		position: fixed;
+		left: 0;
+		top: 0;
+		right: 0;
+		bottom: 0;
+		background-color: transparent;
+		z-index: 100;
+	}
+
+	.list {
+		margin-top: 5px;
+		margin-bottom: 5px;
+	}
+
+	.list-item {
+		padding: 5px 10px;
+		text-align: left;
+	}
+
+	.list-item:hover {
+		background-color: #f0f0f0;
+	}
+
+	.check {
+		margin-right: 5px;
+	}
+
+	.search-area {
+		padding: 10px;
+	}
+
+	.search-input {
+		font-size: 12px;
+		border: 1px solid #f0f0f0;
+		border-radius: 3px;
+		padding: 2px 5px;
+		min-width: 150px;
+		text-align: left;
+	}
+
+	.input-label {
+		margin: 10px 10px 5px 10px;
+		text-align: left;
+	}
+
+	.input {
+		font-size: 12px;
+		border: 1px solid #f0f0f0;
+		border-radius: 3px;
+		margin: 10px;
+		padding: 2px 5px;
+		min-width: 150px;
+		text-align: left;
+	}
+
+	.opera-area {
+		cursor: default;
+		border-top: 1px solid #ddd;
+		padding: 5px;
+	}
+
+	.opera-area .btn {
+		font-size: 12px;
+		border-radius: 3px;
+		margin: 5px;
+		padding: 4px 4px;
+	}
+
+	.btn-default {
+		border: 1px solid #ddd;
+	}
+
+	.btn-default.disable {
+		border-color: transparent;
+	}
+
+	.btn-submit {
+		background-color: #1890ff;
+		color: #ffffff;
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-table/components/uni-th/uni-th.vue b/yudao-ui-admin-uniapp/uni_modules/uni-table/components/uni-th/uni-th.vue
new file mode 100644
index 000000000..883e3f2ab
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-table/components/uni-th/uni-th.vue
@@ -0,0 +1,278 @@
+<template>
+	<!-- #ifdef H5 -->
+	<th :rowspan="rowspan" :colspan="colspan" class="uni-table-th" :class="{ 'table--border': border }" :style="{ width: customWidth + 'px', 'text-align': align }">
+		<view class="uni-table-th-row">
+			<view class="uni-table-th-content" :style="{ 'justify-content': contentAlign }" @click="sort">
+				<slot></slot>
+				<view v-if="sortable" class="arrow-box">
+					<text class="arrow up" :class="{ active: ascending }" @click.stop="ascendingFn"></text>
+					<text class="arrow down" :class="{ active: descending }" @click.stop="descendingFn"></text>
+				</view>
+			</view>
+			<dropdown v-if="filterType || filterData.length" :filterData="filterData" :filterType="filterType" @change="ondropdown"></dropdown>
+		</view>
+	</th>
+	<!-- #endif -->
+	<!-- #ifndef H5 -->
+	<view class="uni-table-th" :class="{ 'table--border': border }" :style="{ width: customWidth + 'px', 'text-align': align }"><slot></slot></view>
+	<!-- #endif -->
+</template>
+
+<script>
+	// #ifdef H5
+	import dropdown from './filter-dropdown.vue'
+	// #endif
+/**
+ * Th 表头
+ * @description 表格内的表头单元格组件
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=3270
+ * @property {Number | String} 	width 	单元格宽度(支持纯数字、携带单位px或rpx)
+ * @property {Boolean} 	sortable 					是否启用排序
+ * @property {Number} 	align = [left|center|right]	单元格对齐方式
+ * @value left   	单元格文字左侧对齐
+ * @value center	单元格文字居中
+ * @value right		单元格文字右侧对齐
+ * @property {Array}	filterData 筛选数据
+ * @property {String}	filterType	[search|select] 筛选类型
+ * @value search	关键字搜素
+ * @value select	条件选择
+ * @event {Function} sort-change 排序触发事件
+ */
+export default {
+	name: 'uniTh',
+	options: {
+		virtualHost: true
+	},
+	components: {
+		// #ifdef H5
+		dropdown
+		// #endif
+	},
+	emits:['sort-change','filter-change'],
+	props: {
+		width: {
+			type: [String, Number],
+			default: ''
+		},
+		align: {
+			type: String,
+			default: 'left'
+		},
+		rowspan: {
+			type: [Number, String],
+			default: 1
+		},
+		colspan: {
+			type: [Number, String],
+			default: 1
+		},
+		sortable: {
+			type: Boolean,
+			default: false
+		},
+		filterType: {
+			type: String,
+			default: ""
+		},
+		filterData: {
+			type: Array,
+			default () {
+				return []
+			}
+		}
+	},
+	data() {
+		return {
+			border: false,
+			ascending: false,
+			descending: false
+		}
+	},
+	computed: {
+		// 根据props中的width属性 自动匹配当前th的宽度(px)
+		customWidth(){
+			if(typeof this.width === 'number'){
+				return this.width
+			} else if(typeof this.width === 'string') {
+				let regexHaveUnitPx = new RegExp(/^[1-9][0-9]*px$/g)
+				let regexHaveUnitRpx = new RegExp(/^[1-9][0-9]*rpx$/g)
+				let regexHaveNotUnit = new RegExp(/^[1-9][0-9]*$/g)
+				if (this.width.match(regexHaveUnitPx) !== null) { // 携带了 px
+					return this.width.replace('px', '')
+				} else if (this.width.match(regexHaveUnitRpx) !== null) { // 携带了 rpx
+					let numberRpx = Number(this.width.replace('rpx', ''))
+					let widthCoe = uni.getSystemInfoSync().screenWidth / 750
+					return Math.round(numberRpx * widthCoe)
+				} else if (this.width.match(regexHaveNotUnit) !== null) { // 未携带 rpx或px 的纯数字 String
+					return this.width
+				} else { // 不符合格式
+					return ''
+				}
+			} else {
+				return ''
+			}
+		},
+		contentAlign() {
+			let align = 'left'
+			switch (this.align) {
+				case 'left':
+					align = 'flex-start'
+					break
+				case 'center':
+					align = 'center'
+					break
+				case 'right':
+					align = 'flex-end'
+					break
+			}
+			return align
+		}
+	},
+	created() {
+		this.root = this.getTable('uniTable')
+		this.rootTr = this.getTable('uniTr')
+		this.rootTr.minWidthUpdate(this.customWidth ? this.customWidth : 140)
+		this.border = this.root.border
+		this.root.thChildren.push(this)
+	},
+	methods: {
+		sort() {
+			if (!this.sortable) return
+			this.clearOther()
+			if (!this.ascending && !this.descending) {
+				this.ascending = true
+				this.$emit('sort-change', { order: 'ascending' })
+				return
+			}
+			if (this.ascending && !this.descending) {
+				this.ascending = false
+				this.descending = true
+				this.$emit('sort-change', { order: 'descending' })
+				return
+			}
+
+			if (!this.ascending && this.descending) {
+				this.ascending = false
+				this.descending = false
+				this.$emit('sort-change', { order: null })
+			}
+		},
+		ascendingFn() {
+			this.clearOther()
+			this.ascending = !this.ascending
+			this.descending = false
+			this.$emit('sort-change', { order: this.ascending ? 'ascending' : null })
+		},
+		descendingFn() {
+			this.clearOther()
+			this.descending = !this.descending
+			this.ascending = false
+			this.$emit('sort-change', { order: this.descending ? 'descending' : null })
+		},
+		clearOther() {
+			this.root.thChildren.map(item => {
+				if (item !== this) {
+					item.ascending = false
+					item.descending = false
+				}
+				return item
+			})
+		},
+		ondropdown(e) {
+			this.$emit("filter-change", e)
+		},
+		/**
+		 * 获取父元素实例
+		 */
+		getTable(name) {
+			let parent = this.$parent
+			let parentName = parent.$options.name
+			while (parentName !== name) {
+				parent = parent.$parent
+				if (!parent) return false
+				parentName = parent.$options.name
+			}
+			return parent
+		}
+	}
+}
+</script>
+
+<style lang="scss">
+$border-color: #ebeef5;
+
+.uni-table-th {
+	padding: 12px 10px;
+	/* #ifndef APP-NVUE */
+	display: table-cell;
+	box-sizing: border-box;
+	/* #endif */
+	font-size: 14px;
+	font-weight: bold;
+	color: #909399;
+	border-bottom: 1px $border-color solid;
+}
+
+.uni-table-th-row {
+	/* #ifndef APP-NVUE */
+	display: flex;
+	/* #endif */
+	flex-direction: row;
+}
+
+.table--border {
+	border-right: 1px $border-color solid;
+}
+.uni-table-th-content {
+	display: flex;
+	align-items: center;
+	flex: 1;
+}
+.arrow-box {
+}
+.arrow {
+	display: block;
+	position: relative;
+	width: 10px;
+	height: 8px;
+	// border: 1px red solid;
+	left: 5px;
+	overflow: hidden;
+	cursor: pointer;
+}
+.down {
+	top: 3px;
+	::after {
+		content: '';
+		width: 8px;
+		height: 8px;
+		position: absolute;
+		left: 2px;
+		top: -5px;
+		transform: rotate(45deg);
+		background-color: #ccc;
+	}
+	&.active {
+		::after {
+			background-color: #007aff;
+		}
+	}
+}
+.up {
+	::after {
+		content: '';
+		width: 8px;
+		height: 8px;
+		position: absolute;
+		left: 2px;
+		top: 5px;
+		transform: rotate(45deg);
+		background-color: #ccc;
+	}
+	&.active {
+		::after {
+			background-color: #007aff;
+		}
+	}
+}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-table/components/uni-thead/uni-thead.vue b/yudao-ui-admin-uniapp/uni_modules/uni-table/components/uni-thead/uni-thead.vue
new file mode 100644
index 000000000..0dd18cd8c
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-table/components/uni-thead/uni-thead.vue
@@ -0,0 +1,129 @@
+<template>
+	<!-- #ifdef H5 -->
+	<thead class="uni-table-thead">
+		<tr class="uni-table-tr">
+			<th :rowspan="rowspan" colspan="1" class="checkbox" :class="{ 'tr-table--border': border }">
+				<table-checkbox :indeterminate="indeterminate" :checked="checked" @checkboxSelected="checkboxSelected"></table-checkbox>
+			</th>
+		</tr>
+		<slot></slot>
+	</thead>
+	<!-- #endif -->
+	<!-- #ifndef H5 -->
+	<view class="uni-table-thead"><slot></slot></view>
+	<!-- #endif -->
+</template>
+
+<script>
+import tableCheckbox from '../uni-tr/table-checkbox.vue'
+export default {
+	name: 'uniThead',
+	components: {
+		tableCheckbox
+	},
+	options: {
+		virtualHost: true
+	},
+	data() {
+		return {
+			border: false,
+			selection: false,
+			rowspan: 1,
+			indeterminate: false,
+			checked: false
+		}
+	},
+	created() {
+		this.root = this.getTable()
+		// #ifdef H5
+		this.root.theadChildren = this
+		// #endif
+		this.border = this.root.border
+		this.selection = this.root.type
+	},
+	methods: {
+		init(self) {
+			this.rowspan++
+		},
+		checkboxSelected(e) {
+			this.indeterminate = false
+			const backIndexData = this.root.backIndexData
+			const data = this.root.trChildren.filter(v => !v.disabled && v.keyValue)
+			if (backIndexData.length === data.length) {
+				this.checked = false
+				this.root.clearSelection()
+			} else {
+				this.checked = true
+				this.root.selectionAll()
+			}
+		},
+		/**
+		 * 获取父元素实例
+		 */
+		getTable(name = 'uniTable') {
+			let parent = this.$parent
+			let parentName = parent.$options.name
+			while (parentName !== name) {
+				parent = parent.$parent
+				if (!parent) return false
+				parentName = parent.$options.name
+			}
+			return parent
+		}
+	}
+}
+</script>
+
+<style lang="scss">
+$border-color: #ebeef5;
+
+.uni-table-thead {
+	display: table-header-group;
+}
+
+.uni-table-tr {
+	/* #ifndef APP-NVUE */
+	display: table-row;
+	transition: all 0.3s;
+	box-sizing: border-box;
+	/* #endif */
+	border: 1px red solid;
+	background-color: #fafafa;
+}
+
+.checkbox {
+	padding: 0 8px;
+	width: 26px;
+	padding-left: 12px;
+	/* #ifndef APP-NVUE */
+	display: table-cell;
+	vertical-align: middle;
+	/* #endif */
+	color: #333;
+	font-weight: 500;
+	border-bottom: 1px $border-color solid;
+	font-size: 14px;
+	// text-align: center;
+}
+
+.tr-table--border {
+	border-right: 1px $border-color solid;
+}
+
+/* #ifndef APP-NVUE */
+.uni-table-tr {
+	::v-deep .uni-table-th {
+		&.table--border:last-child {
+			// border-right: none;
+		}
+	}
+
+	::v-deep .uni-table-td {
+		&.table--border:last-child {
+			// border-right: none;
+		}
+	}
+}
+
+/* #endif */
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-table/components/uni-tr/table-checkbox.vue b/yudao-ui-admin-uniapp/uni_modules/uni-table/components/uni-tr/table-checkbox.vue
new file mode 100644
index 000000000..158f3ffd0
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-table/components/uni-tr/table-checkbox.vue
@@ -0,0 +1,179 @@
+<template>
+	<view class="uni-table-checkbox" @click="selected">
+		<view v-if="!indeterminate" class="checkbox__inner" :class="{'is-checked':isChecked,'is-disable':isDisabled}">
+			<view class="checkbox__inner-icon"></view>
+		</view>
+		<view v-else class="checkbox__inner checkbox--indeterminate">
+			<view class="checkbox__inner-icon"></view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: 'TableCheckbox',
+		emits:['checkboxSelected'],
+		props: {
+			indeterminate: {
+				type: Boolean,
+				default: false
+			},
+			checked: {
+				type: [Boolean,String],
+				default: false
+			},
+			disabled: {
+				type: Boolean,
+				default: false
+			},
+			index: {
+				type: Number,
+				default: -1
+			},
+			cellData: {
+				type: Object,
+				default () {
+					return {}
+				}
+			}
+		},
+		watch:{
+			checked(newVal){
+				if(typeof this.checked === 'boolean'){
+					this.isChecked = newVal
+				}else{
+					this.isChecked = true
+				}
+			},
+			indeterminate(newVal){
+				this.isIndeterminate = newVal
+			}
+		},
+		data() {
+			return {
+				isChecked: false,
+				isDisabled: false,
+				isIndeterminate:false
+			}
+		},
+		created() {
+			if(typeof this.checked === 'boolean'){
+				this.isChecked = this.checked
+			}
+			this.isDisabled = this.disabled
+		},
+		methods: {
+			selected() {
+				if (this.isDisabled) return
+				this.isIndeterminate = false
+				this.isChecked = !this.isChecked
+				this.$emit('checkboxSelected', {
+					checked: this.isChecked,
+					data: this.cellData
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	$checked-color: #007aff;
+	$border-color: #DCDFE6;
+	$disable:0.4;
+
+	.uni-table-checkbox {
+		display: flex;
+		flex-direction: row;
+		align-items: center;
+		justify-content: center;
+		position: relative;
+		margin: 5px 0;
+		cursor: pointer;
+
+		// 多选样式
+		.checkbox__inner {
+			/* #ifndef APP-NVUE */
+			flex-shrink: 0;
+			box-sizing: border-box;
+			/* #endif */
+			position: relative;
+			width: 16px;
+			height: 16px;
+			border: 1px solid $border-color;
+			border-radius: 2px;
+			background-color: #fff;
+			z-index: 1;
+
+			.checkbox__inner-icon {
+				position: absolute;
+				/* #ifdef APP-NVUE */
+				top: 2px;
+				/* #endif */
+				/* #ifndef APP-NVUE */
+				top: 2px;
+				/* #endif */
+				left: 5px;
+				height: 7px;
+				width: 3px;
+				border: 1px solid #fff;
+				border-left: 0;
+				border-top: 0;
+				opacity: 0;
+				transform-origin: center;
+				transform: rotate(45deg);
+				box-sizing: content-box;
+			}
+
+			&.checkbox--indeterminate {
+				border-color: $checked-color;
+				background-color: $checked-color;
+
+				.checkbox__inner-icon {
+					position: absolute;
+					opacity: 1;
+					transform: rotate(0deg);
+					height: 2px;
+					top: 0;
+					bottom: 0;
+					margin: auto;
+					left: 0px;
+					right: 0px;
+					bottom: 0;
+					width: auto;
+					border: none;
+					border-radius: 2px;
+					transform: scale(0.5);
+					background-color: #fff;
+				}
+			}
+			&:hover{
+				border-color: $checked-color;
+			}
+			// 禁用
+			&.is-disable {
+				/* #ifdef H5 */
+				cursor: not-allowed;
+				/* #endif */
+				background-color: #F2F6FC;
+				border-color: $border-color;
+			}
+
+			// 选中
+			&.is-checked {
+				border-color: $checked-color;
+				background-color: $checked-color;
+
+				.checkbox__inner-icon {
+					opacity: 1;
+					transform: rotate(45deg);
+				}
+
+				// 选中禁用
+				&.is-disable {
+					opacity: $disable;
+				}
+			}
+			
+		}
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-table/components/uni-tr/uni-tr.vue b/yudao-ui-admin-uniapp/uni_modules/uni-table/components/uni-tr/uni-tr.vue
new file mode 100644
index 000000000..f9b96716c
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-table/components/uni-tr/uni-tr.vue
@@ -0,0 +1,171 @@
+<template>
+	<!-- #ifdef H5 -->
+	<tr class="uni-table-tr">
+		<th v-if="selection === 'selection' && ishead" class="checkbox" :class="{ 'tr-table--border': border }">
+			<table-checkbox :checked="checked" :indeterminate="indeterminate" :disabled="disabled" @checkboxSelected="checkboxSelected"></table-checkbox>
+		</th>
+		<slot></slot>
+		<!-- <uni-th class="th-fixed">123</uni-th> -->
+	</tr>
+	<!-- #endif -->
+	<!-- #ifndef H5 -->
+	<view class="uni-table-tr">
+		<view v-if="selection === 'selection' " class="checkbox" :class="{ 'tr-table--border': border }">
+			<table-checkbox :checked="checked" :indeterminate="indeterminate" :disabled="disabled" @checkboxSelected="checkboxSelected"></table-checkbox>
+		</view>
+		<slot></slot>
+	</view>
+	<!-- #endif -->
+</template>
+
+<script>
+	import tableCheckbox from './table-checkbox.vue'
+/**
+ * Tr 表格行组件
+ * @description 表格行组件 仅包含 th,td 组件
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=
+ */
+export default {
+	name: 'uniTr',
+	components: { tableCheckbox },
+	props: {
+		disabled: {
+			type: Boolean,
+			default: false
+		},
+		keyValue: {
+			type: [String, Number],
+			default: ''
+		}
+	},
+	options: {
+		virtualHost: true
+	},
+	data() {
+		return {
+			value: false,
+			border: false,
+			selection: false,
+			widthThArr: [],
+			ishead: true,
+			checked: false,
+			indeterminate:false
+		}
+	},
+	created() {
+		this.root = this.getTable()
+		this.head = this.getTable('uniThead')
+		if (this.head) {
+			this.ishead = false
+			this.head.init(this)
+		}
+		this.border = this.root.border
+		this.selection = this.root.type
+		this.root.trChildren.push(this)
+		const rowData = this.root.data.find(v => v[this.root.rowKey] === this.keyValue)
+		if(rowData){
+			this.rowData = rowData
+		}
+		this.root.isNodata()
+	},
+	mounted() {
+		if (this.widthThArr.length > 0) {
+			const selectionWidth = this.selection === 'selection' ? 50 : 0
+			this.root.minWidth = this.widthThArr.reduce((a, b) => Number(a) + Number(b)) + selectionWidth
+		}
+	},
+	// #ifndef VUE3
+	destroyed() {
+		const index = this.root.trChildren.findIndex(i => i === this)
+		this.root.trChildren.splice(index, 1)
+		this.root.isNodata()
+	},
+	// #endif
+	// #ifdef VUE3
+	unmounted() {
+		const index = this.root.trChildren.findIndex(i => i === this)
+		this.root.trChildren.splice(index, 1)
+		this.root.isNodata()
+	},
+	// #endif
+	methods: {
+		minWidthUpdate(width) {
+			this.widthThArr.push(width)
+		},
+		// 选中
+		checkboxSelected(e) {
+			let rootData = this.root.data.find(v => v[this.root.rowKey] === this.keyValue)
+			this.checked = e.checked
+			this.root.check(rootData||this, e.checked,rootData? this.keyValue:null)
+		},
+		change(e) {
+			this.root.trChildren.forEach(item => {
+				if (item === this) {
+					this.root.check(this, e.detail.value.length > 0 ? true : false)
+				}
+			})
+		},
+		/**
+		 * 获取父元素实例
+		 */
+		getTable(name = 'uniTable') {
+			let parent = this.$parent
+			let parentName = parent.$options.name
+			while (parentName !== name) {
+				parent = parent.$parent
+				if (!parent) return false
+				parentName = parent.$options.name
+			}
+			return parent
+		}
+	}
+}
+</script>
+
+<style lang="scss">
+$border-color: #ebeef5;
+
+.uni-table-tr {
+	/* #ifndef APP-NVUE */
+	display: table-row;
+	transition: all 0.3s;
+	box-sizing: border-box;
+	/* #endif */
+}
+
+.checkbox {
+	padding: 0 8px;
+	width: 26px;
+	padding-left: 12px;
+	/* #ifndef APP-NVUE */
+	display: table-cell;
+	vertical-align: middle;
+	/* #endif */
+	color: #333;
+	font-weight: 500;
+	border-bottom: 1px $border-color solid;
+	font-size: 14px;
+	// text-align: center;
+}
+
+.tr-table--border {
+	border-right: 1px $border-color solid;
+}
+
+/* #ifndef APP-NVUE */
+.uni-table-tr {
+	::v-deep .uni-table-th {
+		&.table--border:last-child {
+			// border-right: none;
+		}
+	}
+
+	::v-deep .uni-table-td {
+		&.table--border:last-child {
+			// border-right: none;
+		}
+	}
+}
+
+/* #endif */
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-table/i18n/en.json b/yudao-ui-admin-uniapp/uni_modules/uni-table/i18n/en.json
new file mode 100644
index 000000000..e32023cc1
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-table/i18n/en.json
@@ -0,0 +1,9 @@
+{
+	"filter-dropdown.reset": "Reset",
+	"filter-dropdown.search": "Search",
+	"filter-dropdown.submit": "Submit",
+	"filter-dropdown.filter": "Filter",
+	"filter-dropdown.gt": "Greater or equal to",
+	"filter-dropdown.lt": "Less than or equal to",
+	"filter-dropdown.date": "Date"
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-table/i18n/es.json b/yudao-ui-admin-uniapp/uni_modules/uni-table/i18n/es.json
new file mode 100644
index 000000000..9afd04bb6
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-table/i18n/es.json
@@ -0,0 +1,9 @@
+{
+	"filter-dropdown.reset": "Reiniciar",
+	"filter-dropdown.search": "Búsqueda",
+	"filter-dropdown.submit": "Entregar",
+	"filter-dropdown.filter": "Filtrar",
+	"filter-dropdown.gt": "Mayor o igual a",
+	"filter-dropdown.lt": "Menos que o igual a",
+	"filter-dropdown.date": "Fecha"
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-table/i18n/fr.json b/yudao-ui-admin-uniapp/uni_modules/uni-table/i18n/fr.json
new file mode 100644
index 000000000..b0062371d
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-table/i18n/fr.json
@@ -0,0 +1,9 @@
+{
+	"filter-dropdown.reset": "Réinitialiser",
+	"filter-dropdown.search": "Chercher",
+	"filter-dropdown.submit": "Soumettre",
+	"filter-dropdown.filter": "Filtre",
+	"filter-dropdown.gt": "Supérieur ou égal à",
+	"filter-dropdown.lt": "Inférieur ou égal à",
+	"filter-dropdown.date": "Date"
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-table/i18n/index.js b/yudao-ui-admin-uniapp/uni_modules/uni-table/i18n/index.js
new file mode 100644
index 000000000..2469dd02b
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-table/i18n/index.js
@@ -0,0 +1,12 @@
+import en from './en.json'
+import es from './es.json'
+import fr from './fr.json'
+import zhHans from './zh-Hans.json'
+import zhHant from './zh-Hant.json'
+export default {
+	en,
+	es,
+	fr,
+	'zh-Hans': zhHans,
+	'zh-Hant': zhHant
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-table/i18n/zh-Hans.json b/yudao-ui-admin-uniapp/uni_modules/uni-table/i18n/zh-Hans.json
new file mode 100644
index 000000000..862af1794
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-table/i18n/zh-Hans.json
@@ -0,0 +1,9 @@
+{
+	"filter-dropdown.reset": "重置",
+	"filter-dropdown.search": "搜索",
+	"filter-dropdown.submit": "确定",
+	"filter-dropdown.filter": "筛选",
+	"filter-dropdown.gt": "大于等于",
+	"filter-dropdown.lt": "小于等于",
+	"filter-dropdown.date": "日期范围"
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-table/i18n/zh-Hant.json b/yudao-ui-admin-uniapp/uni_modules/uni-table/i18n/zh-Hant.json
new file mode 100644
index 000000000..64f80615b
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-table/i18n/zh-Hant.json
@@ -0,0 +1,9 @@
+{
+	"filter-dropdown.reset": "重置",
+	"filter-dropdown.search": "搜索",
+	"filter-dropdown.submit": "確定",
+	"filter-dropdown.filter": "篩選",
+	"filter-dropdown.gt": "大於等於",
+	"filter-dropdown.lt": "小於等於",
+	"filter-dropdown.date": "日期範圍"
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-table/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-table/package.json
new file mode 100644
index 000000000..f224ab72a
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-table/package.json
@@ -0,0 +1,86 @@
+{
+  "id": "uni-table",
+  "displayName": "uni-table 表格",
+  "version": "1.2.1",
+  "description": "表格组件,多用于展示多条结构类似的数据,如",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "table",
+    "表格"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": ["uni-scss","uni-datetime-picker"],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "n"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "n",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "n",
+          "联盟": "n"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-table/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-table/readme.md
new file mode 100644
index 000000000..bb08c7918
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-table/readme.md
@@ -0,0 +1,13 @@
+
+
+## Table 表单
+> 组件名:``uni-table``,代码块: `uTable`。
+
+用于展示多条结构类似的数据
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-table)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
+
+
+
+
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-tag/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-tag/changelog.md
new file mode 100644
index 000000000..c0c5839b1
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-tag/changelog.md
@@ -0,0 +1,21 @@
+## 2.1.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-tag](https://uniapp.dcloud.io/component/uniui/uni-tag)
+## 2.0.0(2021-11-09)
+- 新增 提供组件设计资源,组件样式调整
+- 移除 插槽
+- 移除 type 属性的 royal 选项
+## 1.1.1(2021-08-11)
+- type 不是 default 时,size 为 small 字体大小显示不正确
+## 1.1.0(2021-07-30)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.0.7(2021-06-18)
+- 修复 uni-tag 在字节跳动小程序上 css 类名编译错误的 bug
+## 1.0.6(2021-06-04)
+- 修复 未定义 sass 变量 "$uni-color-royal" 的bug
+## 1.0.5(2021-05-10)
+- 修复 royal 类型无效的bug
+- 修复 uni-tag 宽度不自适应的bug
+- 新增 uni-tag 支持属性 custom-style 自定义样式
+## 1.0.4(2021-02-05)
+- 调整为uni_modules目录规范
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-tag/components/uni-tag/uni-tag.vue b/yudao-ui-admin-uniapp/uni_modules/uni-tag/components/uni-tag/uni-tag.vue
new file mode 100644
index 000000000..6378a0b97
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-tag/components/uni-tag/uni-tag.vue
@@ -0,0 +1,252 @@
+<template>
+	<text class="uni-tag" v-if="text" :class="classes" :style="customStyle" @click="onClick">{{text}}</text>
+</template>
+
+<script>
+	/**
+	 * Tag 标签
+	 * @description 用于展示1个或多个文字标签,可点击切换选中、不选中的状态
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=35
+	 * @property {String} text 标签内容
+	 * @property {String} size = [default|small|mini] 大小尺寸
+	 * 	@value default 正常
+	 * 	@value small 小尺寸
+	 * 	@value mini 迷你尺寸
+	 * @property {String} type = [default|primary|success|warning|error]  颜色类型
+	 * 	@value default 灰色
+	 * 	@value primary 蓝色
+	 * 	@value success 绿色
+	 * 	@value warning 黄色
+	 * 	@value error 红色
+	 * @property {Boolean} disabled = [true|false] 是否为禁用状态
+	 * @property {Boolean} inverted = [true|false] 是否无需背景颜色(空心标签)
+	 * @property {Boolean} circle = [true|false] 是否为圆角
+	 * @event {Function} click 点击 Tag 触发事件
+	 */
+
+	export default {
+		name: "UniTag",
+		emits: ['click'],
+		props: {
+			type: {
+				// 标签类型default、primary、success、warning、error、royal
+				type: String,
+				default: "default"
+			},
+			size: {
+				// 标签大小 normal, small
+				type: String,
+				default: "normal"
+			},
+			// 标签内容
+			text: {
+				type: String,
+				default: ""
+			},
+			disabled: {
+				// 是否为禁用状态
+				type: [Boolean, String],
+				default: false
+			},
+			inverted: {
+				// 是否为空心
+				type: [Boolean, String],
+				default: false
+			},
+			circle: {
+				// 是否为圆角样式
+				type: [Boolean, String],
+				default: false
+			},
+			mark: {
+				// 是否为标记样式
+				type: [Boolean, String],
+				default: false
+			},
+			customStyle: {
+				type: String,
+				default: ''
+			}
+		},
+		computed: {
+			classes() {
+				const {
+					type,
+					disabled,
+					inverted,
+					circle,
+					mark,
+					size,
+					isTrue
+				} = this
+				const classArr = [
+					'uni-tag--' + type,
+					'uni-tag--' + size,
+					isTrue(disabled) ? 'uni-tag--disabled' : '',
+					isTrue(inverted) ? 'uni-tag--' + type + '--inverted' : '',
+					isTrue(circle) ? 'uni-tag--circle' : '',
+					isTrue(mark) ? 'uni-tag--mark' : '',
+					// type === 'default' ? 'uni-tag--default' : 'uni-tag-text',
+					isTrue(inverted) ? 'uni-tag--inverted uni-tag-text--' + type : '',
+					size === 'small' ? 'uni-tag-text--small' : ''
+				]
+				// 返回类的字符串,兼容字节小程序
+				return classArr.join(' ')
+			}
+		},
+		methods: {
+			isTrue(value) {
+				return value === true || value === 'true'
+			},
+			onClick() {
+				if (this.isTrue(this.disabled)) return
+				this.$emit("click");
+			}
+		}
+	};
+</script>
+
+<style lang="scss">
+	$uni-primary: #2979ff !default;
+	$uni-success: #18bc37 !default;
+	$uni-warning: #f3a73f !default;
+	$uni-error: #e43d33 !default;
+	$uni-info: #8f939c !default;
+
+
+	$tag-default-pd: 4px 7px;
+	$tag-small-pd: 2px 5px;
+	$tag-mini-pd: 1px 3px;
+
+	.uni-tag {
+		line-height: 14px;
+		font-size: 12px;
+		font-weight: 200;
+		padding: $tag-default-pd;
+		color: #fff;
+		border-radius: 3px;
+		background-color: $uni-info;
+		border-width: 1rpx;
+		border-style: solid;
+		border-color: $uni-info;
+		/* #ifdef H5 */
+		cursor: pointer;
+		/* #endif */
+
+		// size attr
+		&--default {
+			font-size: 12px;
+		}
+
+		&--default--inverted {
+			color: $uni-info;
+			border-color: $uni-info;
+		}
+
+		&--small {
+			padding: $tag-small-pd;
+			font-size: 12px;
+			border-radius: 2px;
+		}
+
+		&--mini {
+			padding: $tag-mini-pd;
+			font-size: 12px;
+			border-radius: 2px;
+		}
+
+		// type attr
+		&--primary {
+			background-color: $uni-primary;
+			border-color: $uni-primary;
+			color: #fff;
+		}
+
+		&--success {
+			color: #fff;
+			background-color: $uni-success;
+			border-color: $uni-success;
+		}
+
+		&--warning {
+			color: #fff;
+			background-color: $uni-warning;
+			border-color: $uni-warning;
+		}
+
+		&--error {
+			color: #fff;
+			background-color: $uni-error;
+			border-color: $uni-error;
+		}
+
+		&--primary--inverted {
+			color: $uni-primary;
+			border-color: $uni-primary;
+		}
+
+		&--success--inverted {
+			color: $uni-success;
+			border-color: $uni-success;
+		}
+
+		&--warning--inverted {
+			color: $uni-warning;
+			border-color: $uni-warning;
+		}
+
+		&--error--inverted {
+			color: $uni-error;
+			border-color: $uni-error;
+		}
+
+		&--inverted {
+			background-color: #fff;
+		}
+
+		// other attr
+		&--circle {
+			border-radius: 15px !important;
+		}
+
+		&--mark {
+			border-top-left-radius: 0 !important;
+			border-bottom-left-radius: 0 !important;
+			border-top-right-radius: 15px !important;
+			border-bottom-right-radius: 15px !important;
+		}
+
+		&--disabled {
+			opacity: 0.5;
+			/* #ifdef H5 */
+			cursor: not-allowed;
+			/* #endif */
+		}
+	}
+
+
+	.uni-tag-text {
+		color: #fff;
+		font-size: 14px;
+
+		&--primary {
+			color: $uni-primary;
+		}
+
+		&--success {
+			color: $uni-success;
+		}
+
+		&--warning {
+			color: $uni-warning;
+		}
+
+		&--error {
+			color: $uni-error;
+		}
+
+		&--small {
+			font-size: 12px;
+		}
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-tag/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-tag/package.json
new file mode 100644
index 000000000..187808863
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-tag/package.json
@@ -0,0 +1,87 @@
+{
+  "id": "uni-tag",
+  "displayName": "uni-tag 标签",
+  "version": "2.1.0",
+  "description": "Tag 组件,用于展示1个或多个文字标签,可点击切换选中、不选中的状态。",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "",
+    "tag",
+    "标签"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": ["uni-scss"],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-tag/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-tag/readme.md
new file mode 100644
index 000000000..6e78ff5e4
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-tag/readme.md
@@ -0,0 +1,13 @@
+
+
+## Tag 标签
+> **组件名:uni-tag**
+> 代码块: `uTag`
+
+
+用于展示1个或多个文字标签,可点击切换选中、不选中的状态 。
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-tag)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
+
+
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-title/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-title/changelog.md
new file mode 100644
index 000000000..762621653
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-title/changelog.md
@@ -0,0 +1,10 @@
+## 1.1.1(2022-05-19)
+- 修改组件描述
+## 1.1.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-title](https://uniapp.dcloud.io/component/uniui/uni-title)
+## 1.0.2(2021-05-12)
+- 新增 示例地址
+- 修复 示例项目缺少组件的Bug
+## 1.0.1(2021-02-05)
+- 调整为uni_modules目录规范
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-title/components/uni-title/uni-title.vue b/yudao-ui-admin-uniapp/uni_modules/uni-title/components/uni-title/uni-title.vue
new file mode 100644
index 000000000..bf4f92659
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-title/components/uni-title/uni-title.vue
@@ -0,0 +1,171 @@
+<template>
+	<view class="uni-title__box" :style="{'align-items':textAlign}">
+		<text class="uni-title__base" :class="['uni-'+type]" :style="{'color':color}">{{title}}</text>
+	</view>
+</template>
+
+<script>
+	/**
+	 * Title 标题
+	 * @description 标题,通常用于记录页面标题,使用当前组件,uni-app 如果开启统计,将会自动统计页面标题
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=1066
+	 * @property {String} type = [h1|h2|h3|h4|h5] 标题类型
+	 * 	@value h1 一级标题
+	 * 	@value h2 二级标题
+	 * 	@value h3 三级标题
+	 * 	@value h4 四级标题
+	 * 	@value h5 五级标题
+	 * @property {String} title 标题内容
+	 * @property {String} align = [left|center|right] 对齐方式
+	 * 	@value left 做对齐
+	 * 	@value center 居中对齐
+	 * 	@value right 右对齐
+	 * @property {String} color 字体颜色
+	 * @property {Boolean} stat = [true|false] 是否开启统计功能呢,如不填写type值,默认为开启,填写 type 属性,默认为关闭
+	 */
+	export default {
+		name:"UniTitle",
+		props: {
+			type: {
+				type: String,
+				default: ''
+			},
+			title: {
+				type: String,
+				default: ''
+			},
+			align: {
+				type: String,
+				default: 'left'
+			},
+			color: {
+				type: String,
+				default: '#333333'
+			},
+			stat: {
+				type: [Boolean, String],
+				default: ''
+			}
+		},
+		data() {
+			return {
+
+			};
+		},
+		computed: {
+			textAlign() {
+				let align = 'center';
+				switch (this.align) {
+					case 'left':
+						align = 'flex-start'
+						break;
+					case 'center':
+						align = 'center'
+						break;
+					case 'right':
+						align = 'flex-end'
+						break;
+				}
+				return align
+			}
+		},
+		watch: {
+			title(newVal) {
+				if (this.isOpenStat()) {
+					// 上报数据
+					if (uni.report) {
+						uni.report('title', this.title)
+					}
+				}
+			}
+		},
+		mounted() {
+			if (this.isOpenStat()) {
+				// 上报数据
+				if (uni.report) {
+					uni.report('title', this.title)
+				}
+			}
+		},
+		methods: {
+			isOpenStat() {
+				if (this.stat === '') {
+					this.isStat = false
+				}
+				let stat_type = (typeof(this.stat) === 'boolean' && this.stat) || (typeof(this.stat) === 'string' && this.stat !==
+					'')
+				if (this.type === "") {
+					this.isStat = true
+					if (this.stat.toString() === 'false') {
+						this.isStat = false
+					}
+				}
+
+				if (this.type !== '') {
+					this.isStat = true
+					if (stat_type) {
+						this.isStat = true
+					} else {
+						this.isStat = false
+					}
+				}
+				return this.isStat
+			}
+		}
+	}
+</script>
+
+<style>
+	/* .uni-title {
+
+	} */
+	.uni-title__box {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		align-items: flex-start;
+		justify-content: center;
+		padding: 8px 0;
+		flex: 1;
+	}
+
+	.uni-title__base {
+		font-size: 15px;
+		color: #333;
+		font-weight: 500;
+	}
+
+	.uni-h1 {
+		font-size: 20px;
+		color: #333;
+		font-weight: bold;
+	}
+
+	.uni-h2 {
+		font-size: 18px;
+		color: #333;
+		font-weight: bold;
+	}
+
+	.uni-h3 {
+		font-size: 16px;
+		color: #333;
+		font-weight: bold;
+		/* font-weight: 400; */
+	}
+
+	.uni-h4 {
+		font-size: 14px;
+		color: #333;
+		font-weight: bold;
+		/* font-weight: 300; */
+	}
+
+	.uni-h5 {
+		font-size: 12px;
+		color: #333;
+		font-weight: bold;
+		/* font-weight: 200; */
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-title/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-title/package.json
new file mode 100644
index 000000000..2249f5a1c
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-title/package.json
@@ -0,0 +1,88 @@
+{
+  "id": "uni-title",
+  "displayName": "uni-title 章节标题",
+  "version": "1.1.1",
+  "description": "章节标题,通常用于记录页面标题,使用当前组件,uni-app 如果开启统计,将会自动统计页面标题",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "标题",
+    "章节",
+    "章节标题",
+    ""
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": ["uni-scss"],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-title/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-title/readme.md
new file mode 100644
index 000000000..0e60b1b95
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-title/readme.md
@@ -0,0 +1,14 @@
+
+
+## Title 标题
+> **组件名:uni-title**
+> 代码块: `uTitle`
+
+
+章节标题,通常用于记录页面标题,使用当前组件,uni-app 如果开启统计,将会自动统计页面标题 。
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-title)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
+
+
+
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-tooltip/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-tooltip/changelog.md
new file mode 100644
index 000000000..00f1572d7
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-tooltip/changelog.md
@@ -0,0 +1,10 @@
+## 0.2.1(2022-05-09)
+- 修复 content 为空时仍然弹出的bug
+## 0.2.0(2022-05-07)
+**注意:破坏性更新**
+- 更新 text 属性变更为 content
+- 更新 移除 width 属性
+## 0.1.1(2022-04-27)
+- 修复 组件根 text 嵌套组件 warning
+## 0.1.0(2022-04-21)
+- 初始化
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-tooltip/components/uni-tooltip/uni-tooltip.vue b/yudao-ui-admin-uniapp/uni_modules/uni-tooltip/components/uni-tooltip/uni-tooltip.vue
new file mode 100644
index 000000000..ffbb6fa5d
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-tooltip/components/uni-tooltip/uni-tooltip.vue
@@ -0,0 +1,68 @@
+<template>
+	<view class="uni-tooltip">
+		<slot></slot>
+		<view v-if="content || $slots.content" class="uni-tooltip-popup">
+			<slot name="content">
+				{{content}}
+			</slot>
+		</view>
+	</view>
+</template>
+
+
+<script>
+	/**
+	 * Tooltip 提示文字
+	 * @description 常用于展示鼠标 hover 时的提示信息。
+	 * @tutorial https://uniapp.dcloud.io/component/uniui/uni-tooltip
+	 * @property {String} content   弹出层显示的内容
+	 * @property {String}  placement出现位置, 目前只支持 left
+	 */
+
+
+	export default {
+		name: "uni-tooltip",
+		data() {
+			return {
+
+			};
+		},
+		props: {
+			content: {
+				type: String,
+				default: ''
+			},
+
+			placement: {
+				type: String,
+				default: 'bottom'
+			},
+		}
+	}
+</script>
+
+<style>
+	.uni-tooltip {
+		position: relative;
+		cursor: pointer;
+	}
+
+	.uni-tooltip-popup {
+		z-index: 1;
+		display: none;
+		position: absolute;
+		left: 0;
+		background-color: #333;
+		border-radius: 8px;
+		color: #fff;
+		font-size: 12px;
+		text-align: left;
+		line-height: 16px;
+		padding: 12px;
+	}
+
+
+	.uni-tooltip:hover .uni-tooltip-popup {
+		display: block;
+	}
+</style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-tooltip/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-tooltip/package.json
new file mode 100644
index 000000000..e88ecf8da
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-tooltip/package.json
@@ -0,0 +1,88 @@
+{
+  "id": "uni-tooltip",
+  "displayName": "uni-tooltip 提示文字",
+  "version": "0.2.1",
+  "description": "Tooltip 提示文字",
+  "keywords": [
+    "uni-tooltip",
+    "uni-ui",
+    "tooltip",
+    "tip",
+    "文字提示"
+  ],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无 ",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": ""
+  },
+  "uni_modules": {
+    "dependencies": [],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "Vue": {
+          "vue2": "y",
+          "vue3": "y"
+        },
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "u"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "u",
+          "百度": "u",
+          "字节跳动": "u",
+          "QQ": "u",
+          "京东": "u"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-tooltip/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-tooltip/readme.md
new file mode 100644
index 000000000..faafa2ecb
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-tooltip/readme.md
@@ -0,0 +1,8 @@
+## Badge 数字角标
+> **组件名:uni-tooltip**
+> 代码块: `uTooltip`
+
+数字角标一般和其它控件(列表、9宫格等)配合使用,用于进行数量提示,默认为实心灰色背景,
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-tooltip)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-transition/changelog.md b/yudao-ui-admin-uniapp/uni_modules/uni-transition/changelog.md
new file mode 100644
index 000000000..b1a824b89
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-transition/changelog.md
@@ -0,0 +1,20 @@
+## 1.3.1(2021-11-23)
+- 修复 init 方法初始化问题
+## 1.3.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-transition](https://uniapp.dcloud.io/component/uniui/uni-transition)
+## 1.2.1(2021-09-27)
+- 修复 init 方法不生效的 Bug
+## 1.2.0(2021-07-30)
+- 组件兼容 vue3,如何创建 vue3 项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.1.1(2021-05-12)
+- 新增 示例地址
+- 修复 示例项目缺少组件的 Bug
+## 1.1.0(2021-04-22)
+- 新增 通过方法自定义动画
+- 新增 custom-class 非 NVUE 平台支持自定义 class 定制样式
+- 优化 动画触发逻辑,使动画更流畅
+- 优化 支持单独的动画类型
+- 优化 文档示例
+## 1.0.2(2021-02-05)
+- 调整为 uni_modules 目录规范
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-transition/components/uni-transition/createAnimation.js b/yudao-ui-admin-uniapp/uni_modules/uni-transition/components/uni-transition/createAnimation.js
new file mode 100644
index 000000000..5f54365e6
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-transition/components/uni-transition/createAnimation.js
@@ -0,0 +1,128 @@
+// const defaultOption = {
+// 	duration: 300,
+// 	timingFunction: 'linear',
+// 	delay: 0,
+// 	transformOrigin: '50% 50% 0'
+// }
+// #ifdef APP-NVUE
+const nvueAnimation = uni.requireNativePlugin('animation')
+// #endif
+class MPAnimation {
+	constructor(options, _this) {
+		this.options = options
+		this.animation = uni.createAnimation(options)
+		this.currentStepAnimates = {}
+		this.next = 0
+		this.$ = _this
+
+	}
+
+	_nvuePushAnimates(type, args) {
+		let aniObj = this.currentStepAnimates[this.next]
+		let styles = {}
+		if (!aniObj) {
+			styles = {
+				styles: {},
+				config: {}
+			}
+		} else {
+			styles = aniObj
+		}
+		if (animateTypes1.includes(type)) {
+			if (!styles.styles.transform) {
+				styles.styles.transform = ''
+			}
+			let unit = ''
+			if(type === 'rotate'){
+				unit = 'deg'
+			}
+			styles.styles.transform += `${type}(${args+unit}) `
+		} else {
+			styles.styles[type] = `${args}`
+		}
+		this.currentStepAnimates[this.next] = styles
+	}
+	_animateRun(styles = {}, config = {}) {
+		let ref = this.$.$refs['ani'].ref
+		if (!ref) return
+		return new Promise((resolve, reject) => {
+			nvueAnimation.transition(ref, {
+				styles,
+				...config
+			}, res => {
+				resolve()
+			})
+		})
+	}
+
+	_nvueNextAnimate(animates, step = 0, fn) {
+		let obj = animates[step]
+		if (obj) {
+			let {
+				styles,
+				config
+			} = obj
+			this._animateRun(styles, config).then(() => {
+				step += 1
+				this._nvueNextAnimate(animates, step, fn)
+			})
+		} else {
+			this.currentStepAnimates = {}
+			typeof fn === 'function' && fn()
+			this.isEnd = true
+		}
+	}
+
+	step(config = {}) {
+		// #ifndef APP-NVUE
+		this.animation.step(config)
+		// #endif
+		// #ifdef APP-NVUE
+		this.currentStepAnimates[this.next].config = Object.assign({}, this.options, config)
+		this.currentStepAnimates[this.next].styles.transformOrigin = this.currentStepAnimates[this.next].config.transformOrigin
+		this.next++
+		// #endif
+		return this
+	}
+
+	run(fn) {
+		// #ifndef APP-NVUE
+		this.$.animationData = this.animation.export()
+		this.$.timer = setTimeout(() => {
+			typeof fn === 'function' && fn()
+		}, this.$.durationTime)
+		// #endif
+		// #ifdef APP-NVUE
+		this.isEnd = false
+		let ref = this.$.$refs['ani'] && this.$.$refs['ani'].ref
+		if(!ref) return
+		this._nvueNextAnimate(this.currentStepAnimates, 0, fn)
+		this.next = 0
+		// #endif
+	}
+}
+
+
+const animateTypes1 = ['matrix', 'matrix3d', 'rotate', 'rotate3d', 'rotateX', 'rotateY', 'rotateZ', 'scale', 'scale3d',
+	'scaleX', 'scaleY', 'scaleZ', 'skew', 'skewX', 'skewY', 'translate', 'translate3d', 'translateX', 'translateY',
+	'translateZ'
+]
+const animateTypes2 = ['opacity', 'backgroundColor']
+const animateTypes3 = ['width', 'height', 'left', 'right', 'top', 'bottom']
+animateTypes1.concat(animateTypes2, animateTypes3).forEach(type => {
+	MPAnimation.prototype[type] = function(...args) {
+		// #ifndef APP-NVUE
+		this.animation[type](...args)
+		// #endif
+		// #ifdef APP-NVUE
+		this._nvuePushAnimates(type, args)
+		// #endif
+		return this
+	}
+})
+
+export function createAnimation(option, _this) {
+	if(!_this) return
+	clearTimeout(_this.timer)
+	return new MPAnimation(option, _this)
+}
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-transition/components/uni-transition/uni-transition.vue b/yudao-ui-admin-uniapp/uni_modules/uni-transition/components/uni-transition/uni-transition.vue
new file mode 100644
index 000000000..0d739bd55
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-transition/components/uni-transition/uni-transition.vue
@@ -0,0 +1,277 @@
+<template>
+	<view v-if="isShow" ref="ani" :animation="animationData" :class="customClass" :style="transformStyles" @click="onClick"><slot></slot></view>
+</template>
+
+<script>
+import { createAnimation } from './createAnimation'
+
+/**
+ * Transition 过渡动画
+ * @description 简单过渡动画组件
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=985
+ * @property {Boolean} show = [false|true] 控制组件显示或隐藏
+ * @property {Array|String} modeClass = [fade|slide-top|slide-right|slide-bottom|slide-left|zoom-in|zoom-out] 过渡动画类型
+ *  @value fade 渐隐渐出过渡
+ *  @value slide-top 由上至下过渡
+ *  @value slide-right 由右至左过渡
+ *  @value slide-bottom 由下至上过渡
+ *  @value slide-left 由左至右过渡
+ *  @value zoom-in 由小到大过渡
+ *  @value zoom-out 由大到小过渡
+ * @property {Number} duration 过渡动画持续时间
+ * @property {Object} styles 组件样式,同 css 样式,注意带’-‘连接符的属性需要使用小驼峰写法如:`backgroundColor:red`
+ */
+export default {
+	name: 'uniTransition',
+	emits:['click','change'],
+	props: {
+		show: {
+			type: Boolean,
+			default: false
+		},
+		modeClass: {
+			type: [Array, String],
+			default() {
+				return 'fade'
+			}
+		},
+		duration: {
+			type: Number,
+			default: 300
+		},
+		styles: {
+			type: Object,
+			default() {
+				return {}
+			}
+		},
+		customClass:{
+			type: String,
+			default: ''
+		}
+	},
+	data() {
+		return {
+			isShow: false,
+			transform: '',
+			opacity: 1,
+			animationData: {},
+			durationTime: 300,
+			config: {}
+		}
+	},
+	watch: {
+		show: {
+			handler(newVal) {
+				if (newVal) {
+					this.open()
+				} else {
+					// 避免上来就执行 close,导致动画错乱
+					if (this.isShow) {
+						this.close()
+					}
+				}
+			},
+			immediate: true
+		}
+	},
+	computed: {
+		// 生成样式数据
+		stylesObject() {
+			let styles = {
+				...this.styles,
+				'transition-duration': this.duration / 1000 + 's'
+			}
+			let transform = ''
+			for (let i in styles) {
+				let line = this.toLine(i)
+				transform += line + ':' + styles[i] + ';'
+			}
+			return transform
+		},
+		// 初始化动画条件
+		transformStyles() {
+			return 'transform:' + this.transform + ';' + 'opacity:' + this.opacity + ';' + this.stylesObject
+		}
+	},
+	created() {
+		// 动画默认配置
+		this.config = {
+			duration: this.duration,
+			timingFunction: 'ease',
+			transformOrigin: '50% 50%',
+			delay: 0
+		}
+		this.durationTime = this.duration
+	},
+	methods: {
+		/**
+		 *  ref 触发 初始化动画
+		 */
+		init(obj = {}) {
+			if (obj.duration) {
+				this.durationTime = obj.duration
+			}
+			this.animation = createAnimation(Object.assign(this.config, obj),this)
+		},
+		/**
+		 * 点击组件触发回调
+		 */
+		onClick() {
+			this.$emit('click', {
+				detail: this.isShow
+			})
+		},
+		/**
+		 * ref 触发 动画分组
+		 * @param {Object} obj
+		 */
+		step(obj, config = {}) {
+			if (!this.animation) return
+			for (let i in obj) {
+				try {
+					if(typeof obj[i] === 'object'){
+						this.animation[i](...obj[i])
+					}else{
+						this.animation[i](obj[i])
+					}
+				} catch (e) {
+					console.error(`方法 ${i} 不存在`)
+				}
+			}
+			this.animation.step(config)
+			return this
+		},
+		/**
+		 *  ref 触发 执行动画
+		 */
+		run(fn) {
+			if (!this.animation) return
+			this.animation.run(fn)
+		},
+		// 开始过度动画
+		open() {
+			clearTimeout(this.timer)
+			this.transform = ''
+			this.isShow = true
+			let { opacity, transform } = this.styleInit(false)
+			if (typeof opacity !== 'undefined') {
+				this.opacity = opacity
+			}
+			this.transform = transform
+			// 确保动态样式已经生效后,执行动画,如果不加 nextTick ,会导致 wx 动画执行异常
+			this.$nextTick(() => {
+				// TODO 定时器保证动画完全执行,目前有些问题,后面会取消定时器
+				this.timer = setTimeout(() => {
+					this.animation = createAnimation(this.config, this)
+					this.tranfromInit(false).step()
+					this.animation.run()
+					this.$emit('change', {
+						detail: this.isShow
+					})
+				}, 20)
+			})
+		},
+		// 关闭过度动画
+		close(type) {
+			if (!this.animation) return
+			this.tranfromInit(true)
+				.step()
+				.run(() => {
+					this.isShow = false
+					this.animationData = null
+					this.animation = null
+					let { opacity, transform } = this.styleInit(false)
+					this.opacity = opacity || 1
+					this.transform = transform
+					this.$emit('change', {
+						detail: this.isShow
+					})
+				})
+		},
+		// 处理动画开始前的默认样式
+		styleInit(type) {
+			let styles = {
+				transform: ''
+			}
+			let buildStyle = (type, mode) => {
+				if (mode === 'fade') {
+					styles.opacity = this.animationType(type)[mode]
+				} else {
+					styles.transform += this.animationType(type)[mode] + ' '
+				}
+			}
+			if (typeof this.modeClass === 'string') {
+				buildStyle(type, this.modeClass)
+			} else {
+				this.modeClass.forEach(mode => {
+					buildStyle(type, mode)
+				})
+			}
+			return styles
+		},
+		// 处理内置组合动画
+		tranfromInit(type) {
+			let buildTranfrom = (type, mode) => {
+				let aniNum = null
+				if (mode === 'fade') {
+					aniNum = type ? 0 : 1
+				} else {
+					aniNum = type ? '-100%' : '0'
+					if (mode === 'zoom-in') {
+						aniNum = type ? 0.8 : 1
+					}
+					if (mode === 'zoom-out') {
+						aniNum = type ? 1.2 : 1
+					}
+					if (mode === 'slide-right') {
+						aniNum = type ? '100%' : '0'
+					}
+					if (mode === 'slide-bottom') {
+						aniNum = type ? '100%' : '0'
+					}
+				}
+				this.animation[this.animationMode()[mode]](aniNum)
+			}
+			if (typeof this.modeClass === 'string') {
+				buildTranfrom(type, this.modeClass)
+			} else {
+				this.modeClass.forEach(mode => {
+					buildTranfrom(type, mode)
+				})
+			}
+
+			return this.animation
+		},
+		animationType(type) {
+			return {
+				fade: type ? 1 : 0,
+				'slide-top': `translateY(${type ? '0' : '-100%'})`,
+				'slide-right': `translateX(${type ? '0' : '100%'})`,
+				'slide-bottom': `translateY(${type ? '0' : '100%'})`,
+				'slide-left': `translateX(${type ? '0' : '-100%'})`,
+				'zoom-in': `scaleX(${type ? 1 : 0.8}) scaleY(${type ? 1 : 0.8})`,
+				'zoom-out': `scaleX(${type ? 1 : 1.2}) scaleY(${type ? 1 : 1.2})`
+			}
+		},
+		// 内置动画类型与实际动画对应字典
+		animationMode() {
+			return {
+				fade: 'opacity',
+				'slide-top': 'translateY',
+				'slide-right': 'translateX',
+				'slide-bottom': 'translateY',
+				'slide-left': 'translateX',
+				'zoom-in': 'scale',
+				'zoom-out': 'scale'
+			}
+		},
+		// 驼峰转中横线
+		toLine(name) {
+			return name.replace(/([A-Z])/g, '-$1').toLowerCase()
+		}
+	}
+}
+</script>
+
+<style></style>
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-transition/package.json b/yudao-ui-admin-uniapp/uni_modules/uni-transition/package.json
new file mode 100644
index 000000000..d15fdf018
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-transition/package.json
@@ -0,0 +1,87 @@
+{
+  "id": "uni-transition",
+  "displayName": "uni-transition 过渡动画",
+  "version": "1.3.1",
+  "description": "元素的简单过渡动画",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "动画",
+    "过渡",
+    "过渡动画"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+  "dcloudext": {
+    "category": [
+      "前端组件",
+      "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": ["uni-scss"],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/uni_modules/uni-transition/readme.md b/yudao-ui-admin-uniapp/uni_modules/uni-transition/readme.md
new file mode 100644
index 000000000..2f8a77e10
--- /dev/null
+++ b/yudao-ui-admin-uniapp/uni_modules/uni-transition/readme.md
@@ -0,0 +1,11 @@
+
+
+## Transition 过渡动画
+> **组件名:uni-transition**
+> 代码块: `uTransition`
+
+
+元素过渡动画
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-transition)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/utils/auth.js b/yudao-ui-admin-uniapp/utils/auth.js
new file mode 100644
index 000000000..cf27e275a
--- /dev/null
+++ b/yudao-ui-admin-uniapp/utils/auth.js
@@ -0,0 +1,22 @@
+const AccessTokenKey = 'ACCESS_TOKEN'
+const RefreshTokenKey = 'REFRESH_TOKEN'
+
+// ========== Token 相关 ==========
+
+export function getAccessToken() {
+  return uni.getStorageSync(AccessTokenKey)
+}
+
+export function getRefreshToken() {
+  return uni.getStorageSync(RefreshTokenKey)
+}
+
+export function setToken(token) {
+  uni.setStorageSync(AccessTokenKey, token.accessToken)
+  uni.setStorageSync(RefreshTokenKey, token.refreshToken)
+}
+
+export function removeToken() {
+  uni.removeStorageSync(AccessTokenKey)
+  uni.removeStorageSync(RefreshTokenKey)
+}
diff --git a/yudao-ui-admin-uniapp/utils/common.js b/yudao-ui-admin-uniapp/utils/common.js
new file mode 100644
index 000000000..00d4137d5
--- /dev/null
+++ b/yudao-ui-admin-uniapp/utils/common.js
@@ -0,0 +1,54 @@
+/**
+* 显示消息提示框
+* @param content 提示的标题
+*/
+export function toast(content) {
+  uni.showToast({
+    icon: 'none',
+    title: content
+  })
+}
+
+/**
+* 显示模态弹窗
+* @param content 提示的标题
+*/
+export function showConfirm(content) {
+  return new Promise((resolve, reject) => {
+    uni.showModal({
+      title: '提示',
+      content: content,
+      cancelText: '取消',
+      confirmText: '确定',
+      success: function(res) {
+        resolve(res)
+      }
+    })
+  })
+}
+
+/**
+* 参数处理
+* @param params 参数
+*/
+export function tansParams(params) {
+  let result = ''
+  for (const propName of Object.keys(params)) {
+    const value = params[propName]
+    var part = encodeURIComponent(propName) + "="
+    if (value !== null && value !== "" && typeof (value) !== "undefined") {
+      if (typeof value === 'object') {
+        for (const key of Object.keys(value)) {
+          if (value[key] !== null && value[key] !== "" && typeof (value[key]) !== 'undefined') {
+            let params = propName + '[' + key + ']'
+            var subPart = encodeURIComponent(params) + "="
+            result += subPart + encodeURIComponent(value[key]) + "&"
+          }
+        }
+      } else {
+        result += part + encodeURIComponent(value) + "&"
+      }
+    }
+  }
+  return result
+}
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/utils/constant.js b/yudao-ui-admin-uniapp/utils/constant.js
new file mode 100644
index 000000000..8becd84fa
--- /dev/null
+++ b/yudao-ui-admin-uniapp/utils/constant.js
@@ -0,0 +1,8 @@
+const constant = {
+   avatar: 'vuex_avatar',
+   name: 'vuex_name',
+   roles: 'vuex_roles',
+   permissions: 'vuex_permissions'
+ }
+
+ export default constant
diff --git a/yudao-ui-admin-uniapp/utils/errorCode.js b/yudao-ui-admin-uniapp/utils/errorCode.js
new file mode 100644
index 000000000..d2111ee10
--- /dev/null
+++ b/yudao-ui-admin-uniapp/utils/errorCode.js
@@ -0,0 +1,6 @@
+export default {
+  '401': '认证失败,无法访问系统资源',
+  '403': '当前操作没有权限',
+  '404': '访问资源不存在',
+  'default': '系统未知错误,请反馈给管理员'
+}
diff --git a/yudao-ui-admin-uniapp/utils/permission.js b/yudao-ui-admin-uniapp/utils/permission.js
new file mode 100644
index 000000000..17969f2f1
--- /dev/null
+++ b/yudao-ui-admin-uniapp/utils/permission.js
@@ -0,0 +1,51 @@
+import store from '@/store'
+
+/**
+ * 字符权限校验
+ * @param {Array} value 校验值
+ * @returns {Boolean}
+ */
+export function checkPermi(value) {
+  if (value && value instanceof Array && value.length > 0) {
+    const permissions = store.getters && store.getters.permissions
+    const permissionDatas = value
+    const all_permission = "*:*:*"
+
+    const hasPermission = permissions.some(permission => {
+      return all_permission === permission || permissionDatas.includes(permission)
+    })
+
+    if (!hasPermission) {
+      return false
+    }
+    return true
+  } else {
+    console.error(`need roles! Like checkPermi="['system:user:add','system:user:edit']"`)
+    return false
+  }
+}
+
+/**
+ * 角色权限校验
+ * @param {Array} value 校验值
+ * @returns {Boolean}
+ */
+export function checkRole(value) {
+  if (value && value instanceof Array && value.length > 0) {
+    const roles = store.getters && store.getters.roles
+    const permissionRoles = value
+    const super_admin = "admin"
+
+    const hasRole = roles.some(role => {
+      return super_admin === role || permissionRoles.includes(role)
+    })
+
+    if (!hasRole) {
+      return false
+    }
+    return true
+  } else {
+    console.error(`need roles! Like checkRole="['admin','editor']"`)
+    return false
+  }
+}
\ No newline at end of file
diff --git a/yudao-ui-admin-uniapp/utils/request.js b/yudao-ui-admin-uniapp/utils/request.js
new file mode 100644
index 000000000..6c00a3f09
--- /dev/null
+++ b/yudao-ui-admin-uniapp/utils/request.js
@@ -0,0 +1,76 @@
+import store from '@/store'
+import config from '@/config'
+import { getAccessToken } from '@/utils/auth'
+import errorCode from '@/utils/errorCode'
+import { toast, showConfirm, tansParams } from '@/utils/common'
+
+let timeout = 10000
+const baseUrl = config.baseUrl
+
+const request = config => {
+  // 是否需要设置 token
+  const isToken = (config.headers || {}).isToken === false
+  config.header = config.header || {}
+  if (getAccessToken() && !isToken) {
+    config.header['Authorization'] = 'Bearer ' + getAccessToken()
+  }
+  // 设置租户 TODO 芋艿:强制 1 先
+  config.header['tenant-id'] = '1';
+  // get请求映射params参数
+  if (config.params) {
+    let url = config.url + '?' + tansParams(config.params)
+    url = url.slice(0, -1)
+    config.url = url
+  }
+  return new Promise((resolve, reject) => {
+    uni.request({
+        method: config.method || 'get',
+        timeout: config.timeout ||  timeout,
+        url: config.baseUrl || baseUrl + config.url,
+        data: config.data,
+        // header: config.header,
+        header: config.header,
+        dataType: 'json'
+      }).then(response => {
+        let [error, res] = response
+        if (error) {
+          toast('后端接口连接异常')
+          reject('后端接口连接异常')
+          return
+        }
+        const code = res.data.code || 200
+        const msg = errorCode[code] || res.data.msg || errorCode['default']
+        if (code === 401) {
+          showConfirm('登录状态已过期,您可以继续留在该页面,或者重新登录?').then(res => {
+            if (res.confirm) {
+              store.dispatch('LogOut').then(res => {
+                uni.reLaunch({ url: '/pages/login' })
+              })
+            }
+          })
+          reject('无效的会话,或者会话已过期,请重新登录。')
+        } else if (code === 500) {
+          toast(msg)
+          reject('500')
+        } else if (code !== 200) {
+          toast(msg)
+          reject(code)
+        }
+        resolve(res.data)
+      })
+      .catch(error => {
+        let { message } = error
+        if (message === 'Network Error') {
+          message = '后端接口连接异常'
+        } else if (message.includes('timeout')) {
+          message = '系统接口请求超时'
+        } else if (message.includes('Request failed with status code')) {
+          message = '系统接口' + message.substr(message.length - 3) + '异常'
+        }
+        toast(message)
+        reject(error)
+      })
+  })
+}
+
+export default request
diff --git a/yudao-ui-admin-uniapp/utils/ruoyi.js b/yudao-ui-admin-uniapp/utils/ruoyi.js
new file mode 100644
index 000000000..fb6021758
--- /dev/null
+++ b/yudao-ui-admin-uniapp/utils/ruoyi.js
@@ -0,0 +1,47 @@
+/**
+ * 通用js方法封装处理
+ * Copyright (c) 2019 ruoyi
+ */
+
+// 日期格式化
+export function parseTime(time, pattern) {
+  if (arguments.length === 0 || !time) {
+    return null
+  }
+  const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}'
+  let date
+  if (typeof time === 'object') {
+    date = time
+  } else {
+    if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
+      time = parseInt(time)
+    } else if (typeof time === 'string') {
+      time = time.replace(new RegExp(/-/gm), '/').replace('T', ' ').replace(new RegExp(/\.[\d]{3}/gm),'');
+    }
+    if ((typeof time === 'number') && (time.toString().length === 10)) {
+      time = time * 1000
+    }
+    date = new Date(time)
+  }
+  const formatObj = {
+    y: date.getFullYear(),
+    m: date.getMonth() + 1,
+    d: date.getDate(),
+    h: date.getHours(),
+    i: date.getMinutes(),
+    s: date.getSeconds(),
+    a: date.getDay()
+  }
+  const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
+    let value = formatObj[key]
+    // Note: getDay() returns 0 on Sunday
+    if (key === 'a') {
+      return ['日', '一', '二', '三', '四', '五', '六'][value]
+    }
+    if (result.length > 0 && value < 10) {
+      value = '0' + value
+    }
+    return value || 0
+  })
+  return time_str
+}
diff --git a/yudao-ui-admin-uniapp/utils/storage.js b/yudao-ui-admin-uniapp/utils/storage.js
new file mode 100644
index 000000000..dd5c38bbf
--- /dev/null
+++ b/yudao-ui-admin-uniapp/utils/storage.js
@@ -0,0 +1,33 @@
+import constant from './constant'
+
+// 存储变量名
+let storageKey = 'storage_data'
+
+// 存储节点变量名
+let storageNodeKeys = [constant.avatar, constant.name, constant.roles, constant.permissions]
+
+// 存储的数据
+let storageData = uni.getStorageSync(storageKey) || {}
+
+const storage = {
+  set: function(key, value) {
+    if (storageNodeKeys.indexOf(key) != -1) {
+      let tmp = uni.getStorageSync(storageKey)
+      tmp = tmp ? tmp : {}
+      tmp[key] = value
+      uni.setStorageSync(storageKey, tmp)
+    }
+  },
+  get: function(key) {
+    return storageData[key] || ""
+  },
+  remove: function(key) {
+    delete storageData[key]
+    uni.setStorageSync(storageKey, storageData)
+  },
+  clean: function() {
+    uni.removeStorageSync(storageKey)
+  }
+}
+
+export default storage
diff --git a/yudao-ui-admin-uniapp/utils/upload.js b/yudao-ui-admin-uniapp/utils/upload.js
new file mode 100644
index 000000000..fb6b37985
--- /dev/null
+++ b/yudao-ui-admin-uniapp/utils/upload.js
@@ -0,0 +1,73 @@
+import store from '@/store'
+import config from '@/config'
+import { getAccessToken } from '@/utils/auth'
+import errorCode from '@/utils/errorCode'
+import { toast, showConfirm, tansParams } from '@/utils/common'
+
+let timeout = 10000
+const baseUrl = config.baseUrl
+
+const upload = config => {
+  // 是否需要设置 token
+  const isToken = (config.headers || {}).isToken === false
+  config.header = config.header || {}
+  if (getAccessToken() && !isToken) {
+    config.header['Authorization'] = 'Bearer ' + getAccessToken()
+  }
+  // get请求映射params参数
+  if (config.params) {
+    let url = config.url + '?' + tansParams(config.params)
+    url = url.slice(0, -1)
+    config.url = url
+  }
+  // 设置租户 TODO 芋艿:强制 1 先
+  config.header['tenant-id'] = '1';
+  return new Promise((resolve, reject) => {
+      uni.uploadFile({
+        timeout: config.timeout || timeout,
+        url: baseUrl + config.url,
+        filePath: config.filePath,
+        name: config.name || 'file',
+        header: config.header,
+        formData: config.formData,
+        method: config.method || 'post',
+        success: (res) => {
+          let result = JSON.parse(res.data)
+          const code = result.code || 200
+          const msg = errorCode[code] || result.msg || errorCode['default']
+          if (code === 200) {
+            resolve(result)
+          } else if (code == 401) {
+            showConfirm("登录状态已过期,您可以继续留在该页面,或者重新登录?").then(res => {
+              if (res.confirm) {
+                store.dispatch('LogOut').then(res => {
+                  uni.reLaunch({ url: '/pages/login/login' })
+                })
+              }
+            })
+            reject('无效的会话,或者会话已过期,请重新登录。')
+          } else if (code === 500) {
+            toast(msg)
+            reject('500')
+          } else if (code !== 200) {
+            toast(msg)
+            reject(code)
+          }
+        },
+        fail: (error) => {
+          let { message } = error
+          if (message == 'Network Error') {
+            message = '后端接口连接异常'
+          } else if (message.includes('timeout')) {
+            message = '系统接口请求超时'
+          } else if (message.includes('Request failed with status code')) {
+            message = '系统接口' + message.substr(message.length - 3) + '异常'
+          }
+          toast(message)
+          reject(error)
+        }
+      })
+  })
+}
+
+export default upload
diff --git a/yudao-ui-admin/src/api/login.js b/yudao-ui-admin/src/api/login.js
index 390f66900..734e5a12a 100644
--- a/yudao-ui-admin/src/api/login.js
+++ b/yudao-ui-admin/src/api/login.js
@@ -134,3 +134,6 @@ export function authorize(responseType, clientId, redirectUri, state,
     method: 'post'
   })
 }
+
+export class socialBindLogin {
+}
diff --git a/yudao-ui-admin/src/store/modules/user.js b/yudao-ui-admin/src/store/modules/user.js
index 5b0b74994..aed5535bf 100644
--- a/yudao-ui-admin/src/store/modules/user.js
+++ b/yudao-ui-admin/src/store/modules/user.js
@@ -1,5 +1,5 @@
 import {login, logout, getInfo, socialLogin, socialBindLogin, smsLogin} from '@/api/login'
-import {getAccessToken, setToken, removeToken, getRefreshToken} from '@/utils/auth'
+import {setToken, removeToken} from '@/utils/auth'
 
 const user = {
   state: {