From 30311cd24ee3b1567ffafac002494bb67feda657 Mon Sep 17 00:00:00 2001
From: cuiqian2004 <cuiqian2004@163.com>
Date: 星期四, 10 七月 2025 09:17:34 +0800
Subject: [PATCH] init

---
 uni_modules/uni-popup/components/uni-popup-share/uni-popup-share.vue                    |  188 
 images/material-symbols-light_pause-rounded.svg                                         |    3 
 images/站点-6.svg                                                                         |    4 
 uni_modules/uni-swipe-action/components/uni-swipe-action-item/render.js                 |  277 
 images/站点.svg                                                                           |   11 
 uni_modules/uni-scss/readme.md                                                          |    4 
 pages/my/log.vue                                                                        |  117 
 images/earth.svg                                                                        |    6 
 images/material-symbols_cancel-rounded.svg                                              |    3 
 uni_modules/uni-swipe-action/components/uni-swipe-action-item/wx.wxs                    |  346 
 static/images/station8.svg                                                              |   11 
 images/Frame 5.png                                                                      |    0 
 package.json                                                                            |   15 
 pages/task/map-task.vue                                                                 |  441 
 .gitignore                                                                              |    7 
 pages/task/log-list.vue                                                                 |  419 
 images/line-md_play-filled.svg                                                          |    4 
 uni_modules/uni-swipe-action/components/uni-swipe-action/uni-swipe-action.vue           |   60 
 components/j-video.vue                                                                  |  220 
 pages/my/instruction.vue                                                                |   96 
 static/images/angle-135.svg                                                             |    4 
 static/images/radix-icons_update.svg                                                    |    3 
 uni_modules/uni-scss/styles/setting/_space.scss                                         |   56 
 pages/task/infos/task-log-item.vue                                                      |  168 
 uni_modules/uni-transition/components/uni-transition/createAnimation.js                 |  131 
 pages/task/update.vue                                                                   |  684 +
 static/images/station6.svg                                                              |   11 
 pages/index/connect.vue                                                                 |  454 
 images/material-symbols_my-location-rounded.svg                                         |    3 
 images/mage_location.svg                                                                |    4 
 static/images/remove.svg                                                                |    3 
 images/ooui_user-avatar2.svg                                                            |   11 
 uni_modules/uni-scss/styles/setting/_radius.scss                                        |   55 
 pages/task/infos/task-item.vue                                                          |  262 
 fonts/fonticon/fonts/fonticon.woff                                                      |    0 
 uni_modules/uni-popup/components/uni-popup/keypress.js                                  |   45 
 pages/my/version-update.vue                                                             |  207 
 uni_modules/uni-scss/styles/setting/_text.scss                                          |   24 
 uni_modules/uni-popup/components/uni-popup-message/uni-popup-message.vue                |  143 
 uni_modules/uni-scss/styles/setting/_styles.scss                                        |  167 
 uni_modules/uni-nav-bar/components/uni-nav-bar/uni-status-bar.vue                       |   30 
 images/image 15.png                                                                     |    0 
 images/mdi_rename.svg                                                                   |    3 
 static/map.png                                                                          |    0 
 uni_modules/uni-nav-bar/changelog.md                                                    |   57 
 pages/vehicle/index.vue                                                                 |    8 
 vite.config.js                                                                          |   18 
 images/mingcute_add-line.svg                                                            |    3 
 pages/my/help-feedback.vue                                                              |  126 
 pages/station/index.vue                                                                 | 1046 ++
 uni_modules/uni-swipe-action/readme.md                                                  |   11 
 images/mobile.svg                                                                       |    1 
 static/logo.png                                                                         |    0 
 images/ri_more-fill.svg                                                                 |    3 
 static/tabbar/ooui_user-avatar2.png                                                     |    0 
 images/ooui_user-avatar.svg                                                             |   11 
 images/站点-1.svg                                                                         |   11 
 images/proicons_task-list.svg                                                           |    3 
 images/bx_battery2.svg                                                                  |    3 
 images/angle-45.svg                                                                     |    4 
 App.vue                                                                                 |   59 
 uni_modules/uni-swipe-action/package.json                                               |   87 
 images/bx_battery1.svg                                                                  |    4 
 uni_modules/uni-scss/variables.scss                                                     |   62 
 static/tabbar/mdi_hand-truck.png                                                        |    0 
 static/images/station4.svg                                                              |   11 
 uni.promisify.adaptor.js                                                                |   13 
 images/angle0.svg                                                                       |    4 
 uni_modules/uni-popup/components/uni-popup/uni-popup.vue                                |  518 +
 static/images/station1.svg                                                              |   11 
 images/van.svg                                                                          |   10 
 images/bx_battery4.svg                                                                  |    3 
 uni_modules/uni-scss/package.json                                                       |   82 
 fonts/fonticon/fonts/fonticon.eot                                                       |    0 
 images/icon-park-outline_attention.svg                                                  |    8 
 static/images/angle0.svg                                                                |    4 
 images/material-symbols_delete-outline-1.svg                                            |    3 
 fonts/fonticon/fonts/fonticon.ttf                                                       |    0 
 images/chat.svg                                                                         |    1 
 pages/my/index.vue                                                                      |  345 
 static/images/station7.svg                                                              |    4 
 static/images/tdesign_book.svg                                                          |    3 
 pages/map/js/ctx.js                                                                     | 1430 +++
 .hbuilderx/launch.json                                                                  |   14 
 uni_modules/uni-icons/components/uni-icons/uni-icons.uvue                               |   91 
 uni_modules/uni-swipe-action/components/uni-swipe-action-item/bindingx.js               |  302 
 images/angle45.svg                                                                      |    4 
 uni_modules/uni-swipe-action/changelog.md                                               |   54 
 uni_modules/uni-icons/package.json                                                      |   89 
 uni_modules/uni-popup/components/uni-popup/i18n/index.js                                |    8 
 uni_modules/uni-scss/styles/tools/functions.scss                                        |   19 
 uni_modules/uni-scss/styles/setting/_border.scss                                        |    3 
 images/proicons_task-list-1.svg                                                         |    3 
 static/images/angle45.svg                                                               |    4 
 uni_modules/uni-nav-bar/readme.md                                                       |   15 
 images/Vector.svg                                                                       |    3 
 uni_modules/uni-scss/index.scss                                                         |    1 
 static/images/van.svg                                                                   |   10 
 manifest.json                                                                           |   76 
 main.js                                                                                 |   26 
 images/Frame 180.svg                                                                    |    5 
 uni_modules/uni-forms/components/uni-forms/uni-forms.vue                                |  404 
 comm/utils.js                                                                           |   63 
 uni_modules/uni-scss/styles/setting/_color.scss                                         |   66 
 comm/wifi/android.js                                                                    |  168 
 comm/wifi/ios.js                                                                        |   18 
 images/grommet-icons_map.svg                                                            |    3 
 uni_modules/uni-icons/components/uni-icons/uniicons.ttf                                 |    0 
 pages/map/task.vue                                                                      |  353 
 static/images/station2.svg                                                              |   11 
 uni_modules/uni-transition/components/uni-transition/uni-transition.vue                 |  289 
 uni_modules/uni-scss/styles/setting/_variables.scss                                     |  146 
 package-lock.json                                                                       | 3983 ++++++++
 images/Toggle2.png                                                                      |    0 
 images/mingcute_edit-line-1.svg                                                         |    3 
 images/material-symbols_skip-next-rounded.svg                                           |    3 
 pages/login/forgot-password.vue                                                         |  217 
 static/images/mingcute_edit-line.svg                                                    |    3 
 uni_modules/uni-popup/changelog.md                                                      |   94 
 images/angle-90.svg                                                                     |    4 
 index.html                                                                              |   20 
 static/play.png                                                                         |    0 
 images/站点-7.svg                                                                         |   11 
 uni_modules/uni-forms/components/uni-forms/validate.js                                  |  486 +
 images/image 23.png                                                                     |    0 
 pages/teaching/index.vue                                                                |  997 ++
 uni_modules/uni-forms/changelog.md                                                      |  100 
 static/images/material-symbols_delete-outline.svg                                       |    3 
 uni_modules/uni-nav-bar/components/uni-nav-bar/uni-nav-bar.vue                          |  357 
 pages/my/log-detail.vue                                                                 |  126 
 AndroidManifest.xml                                                                     |   16 
 uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue                  |  327 
 pages/task/add.vue                                                                      |  602 +
 uni_modules/uni-icons/components/uni-icons/uniicons_file_vue.js                         |  649 +
 uni_modules/uni-forms/components/uni-forms/utils.js                                     |  293 
 uni_modules/uni-popup/components/uni-popup/uni-popup.uvue                               |   90 
 static/images/tabler_copy.svg                                                           |    4 
 uni_modules/uni-scss/theme.scss                                                         |   31 
 pages/index/index.vue                                                                   |  884 +
 images/站点-5.svg                                                                         |   11 
 images/Frame 153.svg                                                                    |   43 
 static/tabbar/mdi_hand-truck2.png                                                       |    0 
 uni_modules/uni-popup/components/uni-popup/i18n/zh-Hant.json                            |    7 
 uni_modules/uni-forms/package.json                                                      |   89 
 uni_modules/uni-forms/readme.md                                                         |   23 
 uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpalipay.js               |  195 
 pages.json                                                                              |  204 
 uni_modules/uni-swipe-action/components/uni-swipe-action-item/uni-swipe-action-item.vue |  348 
 images/angle135.svg                                                                     |    4 
 static/images/angle180.svg                                                              |    4 
 static/images/confirm.svg                                                               |    3 
 pages/map/edit.vue                                                                      |  345 
 images/站点-2.svg                                                                         |    4 
 fonts/fonticon/fonticon.css                                                             |  146 
 images/Frame 178.svg                                                                    |    3 
 uni_modules/uni-popup/readme.md                                                         |   17 
 uni_modules/uni-icons/changelog.md                                                      |   42 
 uni_modules/uni-scss/changelog.md                                                       |    8 
 pages/my/language.vue                                                                   |   74 
 uni_modules/uni-scss/styles/index.scss                                                  |    7 
 api/request.js                                                                          |  133 
 static/images/station.svg                                                               |   11 
 images/站点-4.svg                                                                         |    4 
 static/tabbar/ooui_user-avatar.png                                                      |    0 
 uni_modules/uni-icons/components/uni-icons/uni-icons.vue                                |  110 
 static/images/angle90.svg                                                               |    4 
 images/Frame 139.svg                                                                    |    3 
 uni_modules/uni-transition/readme.md                                                    |   11 
 static/images/angle135.svg                                                              |    4 
 api/vehicle.js                                                                          |  671 +
 images/angle90.svg                                                                      |    4 
 uni_modules/uni-popup/components/uni-popup/i18n/en.json                                 |    7 
 uni_modules/uni-popup/package.json                                                      |   90 
 static/images/station5.svg                                                              |    4 
 static/images/material-symbols_share.svg                                                |    3 
 images/Frame 179.svg                                                                    |    4 
 uni_modules/uni-transition/package.json                                                 |   87 
 images/Frame 174.svg                                                                    |    4 
 images/bx_battery3.svg                                                                  |    4 
 uni_modules/uni-icons/readme.md                                                         |    8 
 images/ooui_user-avatar2-1.svg                                                          |   11 
 uni_modules/uni-popup/components/uni-popup/i18n/zh-Hans.json                            |    7 
 images/angle-135.svg                                                                    |    4 
 uni.scss                                                                                |   76 
 images/fa_repeat.svg                                                                    |    3 
 uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue                      |  632 +
 images/站点-3.svg                                                                         |   11 
 images/stop.svg                                                                         |    3 
 images/image 11.png                                                                     |    0 
 uni_modules/uni-icons/components/uni-icons/uniicons_file.ts                             |  664 +
 images/tabler_line-scan.svg                                                             |    3 
 images/ooui_user-avatar-1.svg                                                           |   11 
 static/images/angle-45.svg                                                              |    4 
 uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpwxs.js                  |   84 
 uni_modules/uni-nav-bar/package.json                                                    |   87 
 images/icon-park-outline_point.svg                                                      |    3 
 static/images/angle-90.svg                                                              |    4 
 uni_modules/uni-transition/changelog.md                                                 |   27 
 static/images/station3.svg                                                              |    4 
 images/line-md_confirm-circle-filled.svg                                                |    9 
 images/image 25.png                                                                     |    0 
 pages/login/index.vue                                                                   |  323 
 images/lock.svg                                                                         |    1 
 pages/login/register.vue                                                                |  234 
 pages/task/list.vue                                                                     |  445 
 pages/teaching/list.vue                                                                 |  491 +
 images/Toggle.png                                                                       |    0 
 pages/index/detail.vue                                                                  |  249 
 cmd.exe                                                                                 |    0 
 uni_modules/uni-popup/components/uni-popup-dialog/keypress.js                           |   45 
 images/小红点.png                                                                          |    0 
 pages/map/index.vue                                                                     |  357 
 uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpother.js                |  260 
 images/angle180.svg                                                                     |    4 
 static/images/view1.png                                                                 |    0 
 uni_modules/uni-icons/components/uni-icons/uniicons.css                                 |  664 +
 uni_modules/uni-popup/components/uni-popup/popup.js                                     |   26 
 uni_modules/uni-swipe-action/components/uni-swipe-action-item/isPC.js                   |   12 
 comm/base64.js                                                                          |  109 
 pages/task/index.vue                                                                    |  155 
 220 files changed, 27,982 insertions(+), 1 deletions(-)

diff --git a/.gitignore b/.gitignore
index 32858aa..5a7368f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,8 +5,13 @@
 
 # Package Files #
 *.jar
-*.war
+*.w
 *.ear
+
+# unpackage
+unpackage
+node_modules
 
 # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
 hs_err_pid*
+
diff --git a/.hbuilderx/launch.json b/.hbuilderx/launch.json
new file mode 100644
index 0000000..422b9af
--- /dev/null
+++ b/.hbuilderx/launch.json
@@ -0,0 +1,14 @@
+{
+    "version" : "1.0",
+    "configurations" : [
+        {
+            "openVueDevtools" : false,
+            "type" : "uni-app:app-ios"
+        },
+        {
+            "openVueDevtools" : false,
+            "playground" : "standard",
+            "type" : "uni-app:app-android"
+        }
+    ]
+}
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
new file mode 100644
index 0000000..e77f76c
--- /dev/null
+++ b/AndroidManifest.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" 
+  package="io.dcloud.nativeresouce">
+    <!--permissions-->
+	<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+	<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
+	<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+	<uses-permission android:name="android.permission.INTERNET" />
+	<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
+	<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+    <application>
+        <!--meta-data-->
+ 
+
+    </application>
+</manifest>
diff --git a/App.vue b/App.vue
new file mode 100644
index 0000000..61d819a
--- /dev/null
+++ b/App.vue
@@ -0,0 +1,59 @@
+<script>
+
+	export default {
+		globalData: {
+			platform: "",
+			deviceModel: "",
+			osVersion: 0
+		},
+		onLaunch: function() {
+			console.log('App Launch')
+		},
+		onShow: function() {
+			console.log('App Show')
+		},
+		onHide: function() {
+			console.log('App Hide')
+		}
+	}
+</script>
+
+<style>
+	@import '@/fonts/fonticon/fonticon.css';
+	@import 'ant-design-vue/dist/reset.css';
+	/*姣忎釜椤甸潰鍏叡css */
+	page {
+		background-color: #fff;
+	}
+
+	a {
+		color: #36a9f8;
+	}
+
+
+	.uni-navbar-container-inner {
+		display: flex;
+		flex: 1;
+		flex-direction: row;
+		align-items: center;
+		font-size: 40rpx;
+		overflow: hidden;
+		color: #333;
+		align-items: center;
+		justify-content: center;
+	}
+
+	.uni-nav-bar-text {
+		overflow: hidden;
+		white-space: nowrap;
+		text-overflow: ellipsis;
+	}
+	.uni-navbar-btn-text {
+		font-size: 32rpx;
+	}
+
+	.uni-panel-bar-icon {
+		cursor: pointer;
+		margin: 10rpx;
+	}
+</style>
\ No newline at end of file
diff --git a/api/request.js b/api/request.js
new file mode 100644
index 0000000..54ac8d1
--- /dev/null
+++ b/api/request.js
@@ -0,0 +1,133 @@
+import {
+	session,
+} from "@/comm/utils.js"
+export default {
+	common: {
+		data: {},
+		// header: {
+		// 	"Content-Type": "application/json;charset=UTF-8"
+		// },
+		method: "GET",
+		dataType: "json"
+	},
+	addLog(item) {
+		const list = session.getValue("request_log") || []
+
+		const res = typeof item.data == 'string' ? item.data : JSON.stringify(item.data)
+		if (res.length > 100 * 1024) {
+			const maxData = session.getValue("request_log_max_data") || {}
+			const key = `data${new Date().getTime()}`
+			maxData[key] = item.data
+			item.data_key = key
+			delete item.data
+			session.setValue("request_log_max_data", maxData)
+		}
+		list.unshift(item)
+		if (list.length > 1000) {
+			const oldItem = list.shift()
+			if (oldItem.data_key) {
+				const maxData = session.getValue("request_log_max_data") || {}
+				delete maxData[oldItem.data_key]
+				session.setValue("request_log_max_data", maxData)
+			}
+		}
+		session.setValue("request_log", list)
+
+	},
+	request(options = {}) {
+		options.data = options.data || this.common.data;
+		options.header = options.header || {
+			"Content-Type": "application/json;charset=UTF-8"
+		};
+		options.method = options.method || this.common.method;
+		options.dataType = options.dataType || this.common.dataType;
+		console.log("url", options.url, options.data)
+		return new Promise((resolve, reject) => {
+			const app = getApp()
+			uni.request({
+				url: options.url,
+				data: options.data,
+				// header: options.header,
+				method: options.method,
+				dataType: options.dataType,
+				success: (result) => {
+					console.log("result", result)
+					const now = new Date()
+					const date = `${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}`
+					if (result.statusCode != 200) {
+						this.addLog({
+							date,
+							method: `${options.method || ""}`,
+							url: options.url,
+							param: options.data,
+							statusCode: result.statusCode,
+							data: ""
+						})
+						if (result.statusCode == 404) {
+
+							return reject({
+								msg: "鍦板潃涓嶅锛岃妫�煡璇ュ湴鍧�細" + options.url
+							});
+						}
+						return reject({
+							msg: "璁块棶澶辫触锛岀姸鎬佺爜锛� + result.statusCode
+						})
+					}
+					this.addLog({
+						date,
+						method: `${options.method || ""}`,
+						url: options.url,
+						param: options.data,
+						statusCode: result.statusCode,
+						data: result.data
+					})
+					var ret = result.data
+					if (typeof ret == 'string') {
+						try {
+							try {
+								try {
+									ret = JSON.parse(ret.replace(/\\"/g, '"'));
+								} catch (ex) {
+									ret = JSON.parse(ret.replace(/\\/g, '\\\\'))
+								}
+							} catch (ex) {
+								ret = JSON.parse(ret.replace(/\\"/g, "'").replace(
+									/[\r\n]/g,
+									'<br>').replace(/[\t]/g, '    '));
+							}
+						} catch (ex) {
+
+							return reject({
+								msg: '灏嗐�json string銆戣浆鎹负銆恓son object銆戝け璐�
+							})
+						}
+					}
+					if (ret.code == 0) {
+
+						resolve(ret.data);
+					} else {
+
+						reject({
+							msg: ret.msg || ""
+						});
+					}
+				},
+				fail: (err) => {
+					console.log("fail", err)
+					const now = new Date()
+					const date = `${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}`
+					this.addLog({
+						date,
+						method: `${options.method || ""}`,
+						url: options.url,
+						param: options.data,
+						statusCode: -1,
+						data: err
+					})
+					return reject(err);
+				}
+			})
+		})
+	},
+
+}
\ No newline at end of file
diff --git a/api/vehicle.js b/api/vehicle.js
new file mode 100644
index 0000000..37f4b36
--- /dev/null
+++ b/api/vehicle.js
@@ -0,0 +1,671 @@
+import http from './request.js';
+import {
+	session,
+} from "@/comm/utils.js"
+
+const addLog = (item) => {
+	const list = session.getValue("request_log") || []
+	list.unshift(item)
+	session.setValue("request_log", list)
+}
+// 鍒ゆ柇ip鏄惁鍙互杩炴帴涓�+export const checkIpLinkSuccess = (ip) => {
+	var url = `http://${ip}:4405/api/mt/battery`;
+	console.log("url", url)
+	return new Promise((resolve, reject) => {
+		uni.request({
+			url: url,
+			method: "GET",
+			header: {
+				"Content-Type": "application/json;charset=UTF-8"
+			},
+			timeout: 5000,
+			success: (result) => {
+				//console.log("result",  result)
+				if (result.statusCode != 200) {
+					if (result.statusCode == 404) {
+						return reject({
+							errMsg: "鍦板潃涓嶅锛岃妫�煡璇ュ湴鍧�細" + url
+						});
+					}
+					resolve({
+						code: -1,
+						msg: "璁块棶澶辫触锛岀姸鎬佺爜锛� + result.statusCode
+					});
+				}
+				var ret = result.data
+				if (typeof ret == 'string') {
+					try {
+						try {
+							try {
+								ret = JSON.parse(ret.replace(/\\"/g, '"'));
+							} catch (ex) {
+								ret = JSON.parse(ret.replace(/\\/g, '\\\\'))
+							}
+						} catch (ex) {
+							ret = JSON.parse(ret.replace(/\\"/g, "'").replace(
+								/[\r\n]/g,
+								'<br>').replace(/[\t]/g, '    '));
+						}
+					} catch (ex) {
+						resolve({
+							code: -1,
+							msg: '灏嗐�json string銆戣浆鎹负銆恓son object銆戝け璐�
+						});
+					}
+				}
+				if (ret.code == 0) {
+					resolve({
+						code: 0,
+						data: ret.data
+					});
+				} else {
+					resolve({
+						code: ret.code,
+						msg: ret.msg || ""
+					});
+				}
+			},
+			fail: (err) => {
+				console.log("err", err)
+				return reject(err);
+			}
+		})
+	})
+
+}
+/**
+ * GET 5000/api/get_agv_state
+ * 鏌ヨ杞﹁締淇℃伅
+ * @param 
+ * @returns 
+ */
+export const getAgvState = (ip) => {
+	var header = {
+		"Content-Type": "application/json;charset=UTF-8"
+	};
+	var url = `http://${ip}:5000/api/get_agv_state`;
+	return http.request({
+		method: "GET",
+		url,
+		header,
+	})
+
+
+
+}
+/**
+ * GET 4405/api/mt/batter
+ * // 鏌ヨ杞﹁締淇℃伅
+ * @param 
+ * @returns 
+ */
+export const mtBattery = (ip) => {
+	var header = {
+		"Content-Type": "application/json;charset=UTF-8"
+	};
+	var url = `http://${ip}:4405/api/mt/battery`;
+	return http.request({
+		method: "GET",
+		url,
+		header,
+	})
+
+}
+/**
+ * GET 4405/api/shell/version
+ * 鏌ヨshell鐗堟湰
+ * @param 
+ * @returns 
+ */
+export const shellVersion = (ip) => {
+	var header = {
+		"Content-Type": "application/json;charset=UTF-8"
+	};
+	var url = `http://${ip}:4405/api/shell/version`;
+	return http.request({
+		method: "GET",
+		url,
+		header,
+	})
+
+}
+/**
+ * POST 5000/api/add_station
+ * 鑾峰彇杞﹁締鍦板浘鍒楄〃
+ * @param 
+ *  stationID, //绔欏彴ID
+ *	name, //绔欏彴鍚�+ * @returns 
+ */
+
+export const mapInfo = (ip) => {
+	// var header = {
+	// 	"Content-Type": "application/json;charset=UTF-8"
+	// };
+	// var url = `http://${ip}:4405/api/shell/version`;
+	// return http.request({
+	// 	method: "GET",
+	// 	url,
+	// 	header,
+	// })
+	return new Promise((resolve, reject) => {
+		return resolve(
+			[{
+				name: "鍦板浘1",
+				img: 'static/map.png',
+			}]
+		)
+	})
+
+
+}
+
+/**
+ * POST 5000/api/add_station
+ * 娣诲姞绔欏彴
+ * @param 
+ *  stationID, //绔欏彴ID
+ *	name, //绔欏彴鍚�+ * @returns 
+ */
+export const addStation = (ip, param) => {
+	var header = {
+		"Content-Type": "application/json;charset=UTF-8"
+	};
+	const {
+		stationID,
+		name
+
+	} = param
+	var url = `http://${ip}:5000/api/add_station/`;
+	return http.request({
+		method: "POST",
+		url,
+		header,
+		data: {
+			stationID,
+			name,
+		},
+	})
+
+}
+
+/**
+ * GET 5000/api/update_station
+ * 鏌ヨ绔欑偣
+ * @param 
+ * @returns 
+ */
+export const stations = (ip) => {
+	var header = {
+		"Content-Type": "application/json;charset=UTF-8"
+	};
+	var url = `http://${ip}:5000/api/stations`;
+	return http.request({
+		method: "GET",
+		url,
+		header,
+
+	})
+}
+
+/**
+ * POST 5000/api/update_station
+ * 淇敼绔欑偣淇℃伅
+ * @param 
+ * @returns 
+ */
+export const updateStation = (ip, param) => {
+	var header = {
+		"Content-Type": "application/json;charset=UTF-8"
+	};
+	const {
+		stationID,
+		name,
+		x,
+		y,
+		angle
+	} = param
+
+	var url = `http://${ip}:5000/api/update_station/`;
+	return http.request({
+		method: "POST",
+		url,
+		header,
+		data: {
+			stationID,
+			name,
+			x: Number(x),
+			y: Number(y),
+			angle
+		}
+
+	})
+
+}
+
+/**
+ * POST 5000/api/delete_station
+ * 鍒犻櫎绔欑偣淇℃伅
+ * @param 
+ * stationID 绔欑偣id闆嗗悎
+ * @returns 
+ */
+export const delStation = (ip, stationID = []) => {
+	var header = {
+		"Content-Type": "application/json;charset=UTF-8"
+	};
+
+	var url = `http://${ip}:5000/api/delete_station/`;
+	return http.request({
+		method: "POST",
+		url,
+		header,
+		data: {
+			stationID
+		}
+	})
+
+}
+
+/**
+ * POST 5000/api/add_task
+ * 娣诲姞浠诲姟
+ * @param 
+ * taskGroupID #浠诲姟缁処D
+ * taskGroupName #浠诲姟缁勫悕
+ * cycleTime #寰幆娆℃暟
+ * taskButton #缁戝畾鎸夐挳
+ * taskList [{
+	 * stationID
+	 * actionType 浠诲姟鐘舵�1鍙栬揣锛�鍗歌揣锛�瀵艰埅
+	 * wait 绛夊緟鏃堕棿
+  }]
+ * taskGroupNameID #浠诲姟缁勫悕
+ * @returns 
+ */
+
+export const addTask = (ip, param) => {
+	var header = {
+		"Content-Type": "application/json;charset=UTF-8"
+	};
+	const {
+		taskGroupID,
+		taskGroupName,
+		cycleTime,
+		taskButton,
+		tasktype,
+		taskList
+	} = param
+
+	var url = `http://${ip}:5000/api/add_task/`;
+	return http.request({
+		method: "POST",
+		url,
+		data: {
+			taskGroupID,
+			taskGroupName,
+			cycleTime,
+			taskButton,
+			tasktype,
+			taskList
+		}
+
+	})
+
+}
+
+/**
+ * GET 5000/api/tasks
+ * 鏌ヨ浠诲姟
+ * @param 
+ * @returns 
+ */
+export const tasks = (ip) => {
+	var header = {
+		"Content-Type": "application/json;charset=UTF-8"
+	};
+	var url = `http://${ip}:5000/api/tasks`;
+	return http.request({
+		method: "GET",
+		url,
+		header,
+
+	})
+
+}
+
+/**
+ * POST 5000/api/update_task
+ * 淇敼浠诲姟
+ * @param 
+ * taskGroupID #浠诲姟缁処D
+ * taskGroupName #浠诲姟缁勫悕
+ * cycleTime #寰幆娆℃暟
+ * taskButton #缁戝畾鎸夐挳
+ * taskList [{
+	 * actionType 浠诲姟鐘舵�1鍙栬揣锛�鍗歌揣锛�瀵艰埅
+	 "dest": {
+			"angle": 1,
+			"name": "Work1212",
+			"stationID": 6,
+			"x": 2,
+			"y": 2,   
+			"_checked": false
+	},
+	"taskID": 1,
+	"wait": 10
+  }]
+ * taskGroupNameID #浠诲姟缁勫悕
+ * @returns 
+ */
+
+export const updateTask = (ip, param) => {
+	var header = {
+		"Content-Type": "application/json;charset=UTF-8"
+	};
+	const {
+		taskGroupID,
+		taskGroupName,
+		cycleTime,
+		taskButton,
+		tasktype,
+		taskList
+	} = param
+
+	var url = `http://${ip}:5000/api/update_task/`;
+	return http.request({
+		method: "POST",
+		url,
+		header,
+		data: {
+			taskGroupID,
+			taskGroupName,
+			cycleTime,
+			tasktype,
+			taskButton,
+			taskList
+		}
+
+	})
+
+}
+
+/**
+ * POST 5000/api/delete_station
+ * 鍒犻櫎浠诲姟
+ * @param 
+ * [{
+	 * taskGroupID  浠诲姟缁処D
+	 * taskID 浠诲姟ID
+ }]
+ * @returns 
+ */
+export const delTask = (ip, list = []) => {
+	var header = {
+		"Content-Type": "application/json;charset=UTF-8"
+	};
+
+	var url = `http://${ip}:5000/api/delete_task/`;
+	return http.request({
+		method: "POST",
+		url,
+		header,
+		data: {
+			data: list
+		}
+	})
+
+}
+
+/**
+ * POST 5000/api/add_taskGroupCmd
+ * 寮�浠诲姟
+ * @param 
+ *  taskGroupID 
+ * taskGroupCmdID鐢变簬鍓嶇鐢熸垚uuid锛屽垱寤哄悗闇�瀛樺偍璧锋潵锛屽悗缁湪鏌ヨ褰撳墠浠诲姟鏃跺�鍋氬垽鏂娇鐢�+ * taskGroupCmd 1 # 1.寮�浠诲姟 2.缁撴潫浠诲姟
+ * @returns 
+ */
+
+export const addTaskGroupCmd = (ip, taskGroupID, taskGroupCmdID, taskGroupCmd = 1) => {
+	var header = {
+		"Content-Type": "application/json;charset=UTF-8"
+	};
+	var url = `http://${ip}:5000/api/add_taskGroupCmd/`;
+	return http.request({
+		method: "POST",
+		url,
+		header,
+		data: {
+			taskGroupID,
+			taskGroupCmd,
+			taskGroupCmdID,
+		}
+	})
+
+}
+
+/**
+ * POST 5000/api/cancel_task
+ * 鍙栨秷浠诲姟
+ * @param 
+ *  taskGroupID 
+ * taskGroupCmdID 姝e湪鎵ц浠诲姟鐨刢mdId
+ * taskList[{
+	 * taskID锛�+	 * is_cancel
+ }]
+ * @returns 
+ */
+export const cancelTask = (ip, taskGroupID, taskGroupCmdID, taskList = []) => {
+	var header = {
+		"Content-Type": "application/json;charset=UTF-8"
+	};
+
+	var url = `http://${ip}:5000/api/cancel_task/`;
+	return http.request({
+		method: "POST",
+		url,
+		header,
+		data: {
+			taskGroupID,
+			taskGroupCmdID,
+			taskList
+		}
+	})
+
+}
+
+/**
+ * GET 5000/api/taskGroupStatus
+ * 鏌ヨ浠诲姟鐘舵�
+ * @param 
+ * @returns 
+ */
+export const taskGroupStatus = (ip) => {
+	var header = {
+		"Content-Type": "application/json;charset=UTF-8"
+	};
+	var url = `http://${ip}:5000/api/taskGroupStatus/`;
+	return http.request({
+		method: "GET",
+		url,
+		header,
+
+	})
+
+}
+
+/**
+ * GET 5000/api/getAllScene
+ * 鑾峰彇鍦烘櫙鍒楄〃
+ * @param 
+ * @returns 
+ */
+export const getAllScene = (ip) => {
+	var header = {
+		"Content-Type": "application/json;charset=UTF-8"
+	};
+	var url = `http://${ip}:5000/api/getAllScene/`;
+	return http.request({
+		method: "GET",
+		url,
+		header,
+
+	})
+}
+
+/**
+ * POST 5000/api/getMapUrl
+ * 閫氳繃鍦烘櫙鑾峰彇鍦板浘鏂囦欢鍦板潃
+ * @param 
+ * @returns 
+ */
+export const getMapUrl = (ip, id) => {
+	var header = {
+		"Content-Type": "application/json;charset=UTF-8"
+	};
+	var url = `http://${ip}:5000/api/getMapUrl/`;
+	return http.request({
+		method: "POST",
+		url,
+		header,
+		data: {
+			sceneId: id,
+		},
+	})
+}
+/**
+ * POST 5000/api/get_task_log
+ * 鑾峰彇浠诲姟璁板綍
+ * @param 
+ * start_time  #寮�鏃堕棿鏃堕棿鎴�+ * end_time #缁撴潫鏃堕棿鏃堕棿鎴�+ * @returns 
+ */
+export const getTaskLog = (ip, start_time = "", end_time = "") => {
+	var header = {
+		"Content-Type": "application/json;charset=UTF-8"
+	};
+	var url = `http://${ip}:5000/api/get_task_log/`;
+	return http.request({
+		method: "POST",
+		url,
+		header,
+		data: {
+			start_time,
+			end_time
+		}
+
+	})
+}
+
+/**
+ * GET 5000/api/teaching_mode
+ * 绀烘暀鏌ヨ
+ * @param 
+ * @returns 
+ */
+export const getTeachingMode = (ip) => {
+	var header = {
+		"Content-Type": "application/json;charset=UTF-8"
+	};
+
+	var url = `http://${ip}:5000/api/teaching_mode/`;
+	return http.request({
+		method: "GET",
+		url,
+		header,
+
+	})
+}
+
+/**
+ * POST 5000/api/teaching_mode_flag
+ * 寮�/鍋滄绀烘暀
+ * @param 
+ * mode # 鍏叡绀烘暀绫诲瀷锛�Public锛�绔欏彴绀烘暀绫诲瀷Stations
+ * src_dst  濡傛灉mode涓虹珯鍙扮ず鏁欐墠鏈夊�鍚﹀垯涓虹┖瀛楃涓诧紝 浼犲叆璧风偣 + _ + 缁堢偣鐨勬牸寮�渚嬪 "loc1_loc2"
+ * name 绀烘暀鍚嶇О
+ * teaching_flag # 1 寮�绀烘暀锛�0 鍋滄绀烘暀
+ * main_road 1,# 1涓昏矾锛�鏀矾
+ * @returns 
+ */
+export const teachingModeFlag = (ip, param) => {
+	var header = {
+		"Content-Type": "application/json;charset=UTF-8"
+	};
+	const {
+		mode,
+		src_dst,
+		name,
+		teaching_flag,
+		main_road,
+	} = param
+
+	var url = `http://${ip}:5000/api/teaching_mode_flag/`;
+	return http.request({
+		method: "POST",
+		url,
+		header,
+		data: {
+			mode,
+			src_dst,
+			name,
+			teaching_flag,
+			main_road
+		}
+
+	})
+}
+
+/**
+ * POST 5000/api/delete_teaching_mode
+ * 鍒犻櫎绀烘暀
+ * @param 
+ * 鏁扮粍[]
+ * mode: 鍏叡绀烘暀绫诲瀷锛�Public锛�绔欏彴绀烘暀绫诲瀷Stations	
+ *name: #绀烘暀鍚嶇О, 
+ * src_dst: #璧风偣缁堢偣,
+ * @returns 
+ */
+export const delTeachingMode = (ip, list) => {
+	var header = {
+		"Content-Type": "application/json;charset=UTF-8"
+	};
+	var url = `http://${ip}:5000/api/delete_teaching_mode/`;
+	return http.request({
+		method: "POST",
+		url,
+		header,
+		data: {
+			data: list
+		}
+
+	})
+}
+
+/**
+ * POST 5000/api/check_agv_location_distance_error
+ * 鍒ゆ柇搴撲綅鍜岃溅璺濈鏄惁杩囧ぇ
+ * @param 
+ * location_name  搴撲綅
+ * @returns 
+ */
+export const checkAgvLocationDistanceError = (ip, location_name) => {
+	var header = {
+		"Content-Type": "application/json;charset=UTF-8"
+	};
+	var url = `http://${ip}:5000/api/check_agv_location_distance_error/`;
+	return http.request({
+		method: "POST",
+		url,
+		header,
+		data: {
+			location_name
+		}
+
+	})
+}
\ No newline at end of file
diff --git a/cmd.exe b/cmd.exe
new file mode 100644
index 0000000..44f2b95
--- /dev/null
+++ b/cmd.exe
Binary files differ
diff --git a/comm/base64.js b/comm/base64.js
new file mode 100644
index 0000000..ea13995
--- /dev/null
+++ b/comm/base64.js
@@ -0,0 +1,109 @@
+//鍔犲瘑銆佽В瀵嗙畻娉曞皝瑁咃細
+const _base64KeyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+var Base64 ={
+	
+	
+	// public method for encoding  
+	encode(input) {	
+		var output = "";
+		var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
+		var i = 0;
+		input = this._utf8_encode(input);
+		while (i < input.length) {
+			chr1 = input.charCodeAt(i++);
+			chr2 = input.charCodeAt(i++);
+			chr3 = input.charCodeAt(i++);
+			enc1 = chr1 >> 2;
+			enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
+			enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
+			enc4 = chr3 & 63;
+			if (isNaN(chr2)) {
+				enc3 = enc4 = 64;
+			} else if (isNaN(chr3)) {
+				enc4 = 64;
+			}
+			output = output +
+				_base64KeyStr.charAt(enc1) + _base64KeyStr.charAt(enc2) +
+				_base64KeyStr.charAt(enc3) + _base64KeyStr.charAt(enc4);
+		}
+		return output;
+	},
+
+	// public method for decoding  
+	decode(input) {
+		var output = "";
+		var chr1, chr2, chr3;
+		var enc1, enc2, enc3, enc4;
+		var i = 0;
+		input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
+		while (i < input.length) {
+			enc1 = _base64KeyStr.indexOf(input.charAt(i++));
+			enc2 = _base64KeyStr.indexOf(input.charAt(i++));
+			enc3 = _base64KeyStr.indexOf(input.charAt(i++));
+			enc4 = _base64KeyStr.indexOf(input.charAt(i++));
+			chr1 = (enc1 << 2) | (enc2 >> 4);
+			chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
+			chr3 = ((enc3 & 3) << 6) | enc4;
+			output = output + String.fromCharCode(chr1);
+			if (enc3 != 64) {
+				output = output + String.fromCharCode(chr2);
+			}
+			if (enc4 != 64) {
+				output = output + String.fromCharCode(chr3);
+			}
+		}
+		output = this._utf8_decode(output);
+		return output;
+	},
+
+	// private method for UTF-8 encoding  
+	_utf8_encode(string) {
+		string = string.replace(/\r\n/g, "\n");
+		var utftext = "";
+		for (var n = 0; n < string.length; n++) {
+			var c = string.charCodeAt(n);
+			if (c < 128) {
+				utftext += String.fromCharCode(c);
+			} else if ((c > 127) && (c < 2048)) {
+				utftext += String.fromCharCode((c >> 6) | 192);
+				utftext += String.fromCharCode((c & 63) | 128);
+			} else {
+				utftext += String.fromCharCode((c >> 12) | 224);
+				utftext += String.fromCharCode(((c >> 6) & 63) | 128);
+				utftext += String.fromCharCode((c & 63) | 128);
+			}
+
+		}
+		return utftext;
+	},
+
+	// private method for UTF-8 decoding  
+	_utf8_decode (utftext) {
+		var string = "";
+		var i = 0;
+		var c = 0,c1 = 0,c2 = 0;
+		let c3
+		while (i < utftext.length) {
+			c = utftext.charCodeAt(i);
+			if (c < 128) {
+				string += String.fromCharCode(c);
+				i++;
+			} else if ((c > 191) && (c < 224)) {
+				c2 = utftext.charCodeAt(i + 1);
+				string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
+				i += 2;
+			} else {
+				c2 = utftext.charCodeAt(i + 1);
+				c3 = utftext.charCodeAt(i + 2);
+				string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
+				i += 3;
+			}
+		}
+		return string;
+	},
+
+}
+ 
+export   {
+	Base64,
+}
\ No newline at end of file
diff --git a/comm/utils.js b/comm/utils.js
new file mode 100644
index 0000000..9e3ec1a
--- /dev/null
+++ b/comm/utils.js
@@ -0,0 +1,63 @@
+
+var SESSION_SUFFIX = "diniu_app_"
+export function showModal(message, title = '鎻愮ず', iscancel = true) {
+	return new Promise((resolve) => {
+		uni.showModal({
+			title: title,
+			content: message,
+			showCancel: iscancel,
+			success: function(res) {
+				if (res.confirm) {
+					resolve(true)
+				} else if (res.cancel) {
+					resolve(false)
+				}
+			}
+		});
+	})
+}
+
+export function showToast(title, icon) {
+	uni.showToast({
+		title: title,
+		icon: icon ? icon : 'none'
+	})
+}
+export function showLoading(title) {
+
+
+	uni.showLoading({
+		title: title,
+		mask: true
+	})
+
+}
+
+export function hideLoading() {
+
+	uni.hideLoading()
+}
+
+let session = {
+	setValue(key, value) {
+		let suffixStr = SESSION_SUFFIX
+		if (value == null) {
+			uni.removeStorageSync(suffixStr + key)
+		} else {
+			uni.setStorageSync(suffixStr + key, value);
+		}
+	},
+
+	getValue(key) {
+		let suffixStr = SESSION_SUFFIX
+		return uni.getStorageSync(suffixStr + key) || null;
+	},
+
+	clearValue(key) {
+		let suffixStr = SESSION_SUFFIX
+		return uni.removeStorageSync(suffixStr + key);
+	},
+}
+export {
+	session
+}
\ No newline at end of file
diff --git a/comm/wifi/android.js b/comm/wifi/android.js
new file mode 100644
index 0000000..3b92078
--- /dev/null
+++ b/comm/wifi/android.js
@@ -0,0 +1,168 @@
+export default {
+	data() {
+		return {
+			// 榛樿鐨勫叏灞�垎浜唴瀹�+			wifiManager: null,
+			wifiManager: null,
+			arrayList: null,
+		}
+	},
+	initWifi() {
+		const MainActivity = plus.android.runtimeMainActivity();
+		const Context = plus.android.importClass("android.content.Context");
+		this.arrayList = plus.android.importClass("java.util.ArrayList");
+		plus.android.importClass("android.net.wifi.WifiManager");
+		plus.android.importClass("android.net.wifi.WifiInfo");
+		plus.android.importClass("android.net.wifi.ScanResult");
+		this.WifiConfiguration = plus.android.importClass("android.net.wifi.WifiConfiguration");
+		this.wifiManager = MainActivity.getSystemService(Context.WIFI_SERVICE);
+
+	},
+
+	openWifiSetting() {
+		let main = plus.android.runtimeMainActivity();
+		let Intent = plus.android.importClass("android.content.Intent");
+		let intent = new Intent();
+		intent.setAction("android.settings.WIFI_SETTINGS"); // 鎸囧畾action涓鸿烦杞埌WLAN璁剧疆鐣岄潰
+		main.startActivity(intent);
+	},
+	getConnectionWifi() {
+		const wifiInfo = this.wifiManager.getConnectionInfo()
+		let ssid = wifiInfo.getSSID(); // 鑾峰彇SSID
+		let mac = wifiInfo.getBSSID(); // 鑾峰彇mac鍦板潃
+		let ipAddress = wifiInfo.getIpAddress();
+		let ip =
+			`${(ipAddress & 0xff)}.${(ipAddress >> 8 & 0xff)}.${(ipAddress >> 16 & 0xff)}.${(ipAddress >> 24 & 0xff)}`
+		console.log(ssid, ip, mac)
+		return {
+			ssid,
+			ip,
+			mac
+		}
+	},
+	getWifiList() {
+		const resultList = this.wifiManager.getScanResults();
+		const len = resultList.size();
+		this.wifiList = [];
+		for (let i = 0; i < len; i++) {
+			const oneWiFi = {
+				sid: resultList.get(i).plusGetAttribute('SSID'),
+				bssid: resultList.get(i).plusGetAttribute('BSSID'),
+			};
+			this.wifiList.push(oneWiFi);
+		}
+		console.log(this.wifiList);
+	},
+	// 杩炴帴 WiFi
+	connectWifi(SSID, pwd) {
+
+		// 鑾峰彇褰撳墠杩炴帴鐨刉iFi淇℃伅
+		// console.log("connectWifi", plus);
+		// plus.wifi.connect({
+		// 	SSID: SSID,
+		// 	password: pwd
+		// }, function() {
+		// 	console.log('杩炴帴鎴愬姛');
+		// 	uni.showToast({
+		// 		title: '杩炴帴鎴愬姛',
+		// 		icon: 'success'
+		// 	});
+		// }, function(e) {
+		// 	console.log('杩炴帴澶辫触:', e);
+		// 	uni.showToast({
+		// 		title: '杩炴帴澶辫触',
+		// 		icon: 'none'
+		// 	});
+		// });
+		// return
+		let BSSID = ""
+		console.log("connectWifi", SSID, BSSID, pwd);
+		const wifiConfig = this.createWifiConfig(SSID, pwd, 'wpa', BSSID);
+		if (wifiConfig == null) {
+			console.log("wifiConfig is null!");
+			return;
+		}
+		console.log("createWifiConfig");
+		const tempConfig = this.isExsitsAndroid(SSID);
+		console.log("isExsitsAndroid");
+		if (tempConfig != null) {
+			this.wifiManager.removeNetwork(tempConfig.networkId);
+		}
+		console.log("addNetwork");
+		const netID = this.wifiManager.addNetwork(wifiConfig);
+		const enabled = this.wifiManager.enableNetwork(netID, true);
+		console.log("enableNetwork status enable=" + enabled);
+		const connected = this.wifiManager.reconnect();
+		console.log("enableNetwork connected=" + connected);
+	},
+	// 鍒涘缓鏂扮殑 WiFi 淇℃伅
+	createWifiConfig(SSID, Password, Type, BSSID) {
+		const WifiConfiguration = this.WifiConfiguration;
+
+		let config = new WifiConfiguration();
+		console.log("createWifiConfig config", WifiConfiguration);
+		config.allowedAuthAlgorithms.clear();
+		console.log("createWifiConfig allowedAuthAlgorithms");
+		config.allowedGroupCiphers.clear();
+		console.log("createWifiConfig allowedGroupCiphers");
+		config.allowedKeyManagement.clear();
+		console.log("createWifiConfig allowedKeyManagement");
+		config.allowedPairwiseCiphers.clear();
+		console.log("createWifiConfig allowedPairwiseCiphers");
+		config.allowedProtocols.clear();
+		console.log("createWifiConfig allowedProtocols");
+		config.SSID = '"' + SSID + '"';
+		console.log("createWifiConfig2", config);
+		if (Type === "nopass") {
+			config.preSharedKey = "";
+			config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+			config.wepTxKeyIndex = 0;
+		}
+		if (Type === "wep") {
+			if (Password !== "") {
+				if (this.isHexWepKey(Password)) {
+					config.preSharedKey = Password;
+				} else {
+					config.preSharedKey = "\"" + Password + "\"";
+				}
+			}
+			config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
+			config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
+			config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
+			config.wepTxKeyIndex = 0;
+		}
+		if (Type === "wpa") {
+			console.log("createWifiConfig3", Type);
+			config.preSharedKey = "\"" + Password + "\"";
+			config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
+			config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
+			config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
+			config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
+			config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
+			config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
+			config.status = WifiConfiguration.Status.ENABLED;
+		}
+		console.log("createWifiConfig end", config);
+		return config;
+	},
+	// 鍒ゆ柇鏄惁鏄崄鍏繘鍒剁殑 WEP 瀵嗛挜
+	isHexWepKey(key) {
+		const hexPattern = /^([0-9a-fA-F]{2})+$/;
+		return hexPattern.test(key);
+	},
+	// 鏌ョ湅浠ュ墠鏄惁閰嶇疆杩囪繖涓綉缁�+	isExsitsAndroid(sSID) {
+		const existingConfigs = this.wifiManager.getConfiguredNetworks();
+		if (existingConfigs.size() != 0) {
+			for (let i = 0; i < existingConfigs.size(); i++) {
+				if (existingConfigs.get(i).SSID === ('"' + sSID + '"')) {
+					console.log("璇ユ寚瀹氱殑 ssid 瀛樺湪浜庨厤缃腑:" + sSID);
+					return existingConfigs.get(i);
+				}
+			}
+		}
+		console.log("璇�ssid 娌℃湁閰嶇疆杩�);
+		return null;
+	},
+
+}
\ No newline at end of file
diff --git a/comm/wifi/ios.js b/comm/wifi/ios.js
new file mode 100644
index 0000000..a8c4ea9
--- /dev/null
+++ b/comm/wifi/ios.js
@@ -0,0 +1,18 @@
+export default {
+
+	openWifiSetting() {
+		plus.runtime.launchApplication({
+			action: "prefs:root=WIFI", // iOS绯荤粺WLAN杩炴帴鐣岄潰鐨刄RL Scheme
+			success: function() {
+				console.log("璺宠浆鍒癢LAN杩炴帴鐣岄潰鎴愬姛");
+			},
+			fail: function(e) {
+				console.error("璺宠浆澶辫触锛�, e);
+			}
+		});
+	},
+	getConnectionWifi() {
+
+		return ""
+	},
+}
\ No newline at end of file
diff --git a/components/j-video.vue b/components/j-video.vue
new file mode 100644
index 0000000..86bb210
--- /dev/null
+++ b/components/j-video.vue
@@ -0,0 +1,220 @@
+<template>
+	<view class="jvideo-root" :style="{width,height}">
+		<image :style="{width,height}" class="jvideo-posterImg" :src="posterUrl" mode="aspectFit"></image>
+		<view class="jvideo-text">
+			<text style="justify-content: flex-end;">{{durationStr}}</text>
+		</view>
+		<view v-if="!isTransit" :style="{width,height}" @click="clickPaly" class="jvideo-box">
+			<image class="jvideo-playIcon" src="../static/play.png" mode="widthFix"></image>
+		</view>
+<!-- 		<video :id="videoId" controls ref="videoMsg" :style="{height,width:state?width:'0rpx'}" @pause="state=0"
+			@timeupdate="timeupdate" @play="onPlay" @fullscreenchange="fullscreenchange" @error="videoErrorCallback"
+			class="jvideo-video" :src="urlVideo"></video> -->
+	</view>
+</template>
+
+<script>
+	export default {
+		computed: {
+			posterUrl() {
+				if (this.poster) return this.poster
+				return this.defaultIco
+			},
+			durationStr() {
+				if(this.duration)
+				{
+					let min = parseInt(this.duration / 60);
+					let sec = this.duration % 60;
+					min = min < 10 ? '0' + min : min;
+					sec = sec < 10 ? '0' + sec : sec;
+					return min + ':' + sec;
+				}
+				
+				return  ""
+			}
+		},
+		created() {
+			const app = getApp()
+			this.defaultIco =  "/static/logo.png"
+			this.videoId = Date.now() + Math.ceil(Math.random() * 10000000) + "";
+		},
+		mounted() {
+
+			if (this.url) {
+				//#ifdef MP-DINGTALK
+				this.urlVideo = this.url
+				//#endif
+				//#ifndef MP-DINGTALK
+				this.urlVideo = decodeURIComponent(this.url)
+				//#endif
+			}
+			this.duration = this.len || 0
+			this.VideoContext = uni.createVideoContext(this.videoId, this)
+		},
+		methods: {
+			fullscreenchange(e) {
+				this.state = e.detail.fullScreen
+			},
+			onPlay(e) {
+				console.log("onPlay", e, this.urlVideo);
+				//this.state = e.detail.fullScreen
+			},
+
+			timeupdate(e) {
+				console.log("timeupdate", e.detail);
+				let duration = parseInt(e.detail.duration)
+				if (duration != this.duration)
+					this.duration = duration
+				//this.currentTime = e.detail.currentTime
+			},
+			clickPaly() {
+				// this.state = !this.state
+				this.$emit('play')
+			},
+
+			videoErrorCallback(e) {
+				console.log('onPlayError, e=' + JSON.stringify(e));
+			},
+
+		},
+		watch: {
+			state(state, oldValue) {
+				console.log(state, 'state');
+				if (!state) {
+					//this.$refs.videoMsg.pause()
+					this.VideoContext.pause()
+				} else {
+					console.log('state videoId', this.videoId);
+					console.log('state play', this.VideoContext);
+					//this.$refs.videoMsg.play()
+					this.VideoContext.requestFullScreen({
+						direction: this.direction
+					})
+					this.VideoContext.play()
+
+					/* this.$nextTick(()=>{
+						console.log('state requestFullScreen',this.direction);
+						//this.$refs.videoMsg.requestFullScreen({direction:this.direction})
+						this.VideoContext.requestFullScreen({direction:this.direction})
+					}) */
+				}
+			},
+			len(value, oldValue) {
+				console.log(value, 'len');
+				this.duration = value
+			},
+			url(value, oldValue) {
+				//#ifdef MP-DINGTALK
+				this.urlVideo = value
+				//#endif
+				//#ifndef MP-DINGTALK
+				this.urlVideo = decodeURIComponent(value)
+				//#endif
+				console.log(value, 'url');
+
+			}
+		},
+		data() {
+			return {
+				VideoContext: {},
+				state: false,
+				currentTime: 0,
+				duration: 0,
+				videoId: '',
+				defaultIco: '',
+				urlVideo: '',
+			};
+		},
+		props: {
+			poster: {
+				type: [String, Boolean],
+				default () {
+					return ''
+				}
+			},
+			url: {
+				type: String,
+				default () {
+					return ''
+				}
+			},
+			direction: {
+				type: Number,
+				default () {
+					return 0
+				}
+			},
+			len: {
+				type: Number,
+				default () {
+					return 0
+				}
+			},
+			width: {
+				type: String,
+				default () {
+					return "750rpx";
+				}
+			},
+			height: {
+				type: String,
+				default () {
+					return "450rpx";
+				}
+			},
+			isTransit: {
+				type: Boolean,
+				default () {
+					return false
+				}
+			},
+		},
+	}
+</script>
+
+<style lang="scss" scoped>
+	.jvideo-root {
+		position: relative;
+		width: 750rpx;
+		height: 300px;
+		overflow: hidden;
+		border-radius: 10rpx;
+	}
+
+	.jvideo-posterImg {
+		display: flex;
+		width: 750rpx;
+		height: 300px;
+		position: absolute;
+	}
+
+	.jvideo-box {
+		display: flex;
+		width: 750rpx;
+		height: 300px;
+		justify-content: center;
+		align-items: center;
+		position: absolute;
+	}
+
+	.jvideo-text {
+		display: flex;
+		bottom: 10rpx;
+		right: 10rpx;
+		height: 20px;
+		color: #ddd;
+		font-size: 12px;
+		position: absolute;
+	}
+
+	.jvideo-video {
+		display: flex;
+		width: 750rpx;
+		height: 300px;
+		position: absolute;
+	}
+
+	.jvideo-playIcon {
+		width: 100rpx;
+	}
+</style>
\ No newline at end of file
diff --git a/fonts/fonticon/fonticon.css b/fonts/fonticon/fonticon.css
new file mode 100644
index 0000000..752b95c
--- /dev/null
+++ b/fonts/fonticon/fonticon.css
@@ -0,0 +1,146 @@
+@font-face {
+	font-family: 'fonticon';
+	src: url("./fonts/fonticon.ttf") format("truetype"),
+		url("./fonts/fonticon.eot") format("embedded-opentype"),
+		url("./fonts/fonticon.woff") format("woff");
+}
+
+.ico {
+	font-family: 'fonticon' !important;
+	font-size: 18px;
+	font-style: normal;
+	-webkit-font-smoothing: antialiased;
+	-moz-osx-font-smoothing: grayscale;
+}
+
+.conversion-path:before {
+	content: "\ea01";
+}
+
+.edit-road-outline-rounded:before {
+	content: "\ea02";
+}
+
+.teach:before {
+	content: "\ea03";
+}
+
+.placeholder-bold:before {
+	content: "\ea04";
+}
+
+.layer:before {
+	content: "\ea05";
+}
+
+.arrow:before {
+	content: "\ea06";
+}
+
+.edit-line:before {
+	content: "\ea07";
+}
+
+.update:before {
+	content: "\ea08";
+}
+
+.book:before {
+	content: "\ea09";
+}
+
+.share:before {
+	content: "\ea0a";
+}
+
+.copy:before {
+	content: "\ea0b";
+}
+
+.map:before {
+	content: "\ea0c";
+}
+
+.hand-truck:before {
+	content: "\ea0d";
+}
+
+.line-scan:before {
+	content: "\ea0e";
+}
+
+.more-fill:before {
+	content: "\ea0f";
+}
+
+.back:before {
+	content: "\ea10";
+}
+
+.cancel1:before {
+	content: "\ea11";
+}
+
+.location1:before {
+	content: "\ea12";
+}
+
+.task-list:before {
+	content: "\ea13";
+}
+
+.location:before {
+	content: "\ea14";
+}
+
+.my-location-rounded:before {
+	content: "\ea15";
+}
+
+.confirm-circle-filled:before {
+	content: "\ea16";
+}
+
+.cancel-rounded:before {
+	content: "\ea17";
+}
+
+.delete-outline:before {
+	content: "\ea18";
+}
+
+.rename:before {
+	content: "\ea19";
+}
+
+.pause-rounded:before {
+	content: "\ea1a";
+}
+
+.play-filled:before {
+	content: "\ea1b";
+}
+
+.add-line:before {
+	content: "\ea1c";
+}
+
+.skip-next-rounded:before {
+	content: "\ea1d";
+}
+
+.repeat:before {
+	content: "\ea1e";
+}
+
+.stop:before {
+	content: "\ea1f";
+}
+
+.more:before {
+	content: "\ea20";
+}
+
+.user-avatar:before {
+	content: "\ea21";
+}
\ No newline at end of file
diff --git a/fonts/fonticon/fonts/fonticon.eot b/fonts/fonticon/fonts/fonticon.eot
new file mode 100644
index 0000000..7a4f789
--- /dev/null
+++ b/fonts/fonticon/fonts/fonticon.eot
Binary files differ
diff --git a/fonts/fonticon/fonts/fonticon.ttf b/fonts/fonticon/fonts/fonticon.ttf
new file mode 100644
index 0000000..ad7fccb
--- /dev/null
+++ b/fonts/fonticon/fonts/fonticon.ttf
Binary files differ
diff --git a/fonts/fonticon/fonts/fonticon.woff b/fonts/fonticon/fonts/fonticon.woff
new file mode 100644
index 0000000..92ac957
--- /dev/null
+++ b/fonts/fonticon/fonts/fonticon.woff
Binary files differ
diff --git a/images/Frame 139.svg b/images/Frame 139.svg
new file mode 100644
index 0000000..4503d21
--- /dev/null
+++ b/images/Frame 139.svg
@@ -0,0 +1,3 @@
+<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M19.6667 13.75C19.6667 14.181 19.4911 14.5943 19.1785 14.899C18.866 15.2038 18.442 15.375 18 15.375C17.558 15.375 17.1341 15.2038 16.8215 14.899C16.5089 14.5943 16.3333 14.181 16.3333 13.75C16.3333 13.319 16.5089 12.9057 16.8215 12.601C17.1341 12.2962 17.558 12.125 18 12.125C18.442 12.125 18.866 12.2962 19.1785 12.601C19.4911 12.9057 19.6667 13.319 19.6667 13.75ZM8 13.75C8 21.875 18 30 18 30C18 30 28 21.875 28 13.75C28 8.19737 23.5233 4 18 4C12.4767 4 8 8.19737 8 13.75Z" stroke="#1890FF" stroke-width="3" stroke-linejoin="round"/>
+</svg>
diff --git a/images/Frame 153.svg b/images/Frame 153.svg
new file mode 100644
index 0000000..cf82d06
--- /dev/null
+++ b/images/Frame 153.svg
@@ -0,0 +1,43 @@
+<svg width="310" height="32" viewBox="0 0 310 32" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M35 8V32" stroke="#002766" stroke-width="2"/>
+<path d="M41 16V32" stroke="#002766"/>
+<path d="M47 16V32" stroke="#002766"/>
+<path d="M53 16V32" stroke="#002766"/>
+<path d="M59 16V32" stroke="#002766"/>
+<path d="M65 8V32" stroke="#002766" stroke-width="2"/>
+<path d="M71 16V32" stroke="#002766"/>
+<path d="M77 16V32" stroke="#002766"/>
+<path d="M83 16V32" stroke="#002766"/>
+<path d="M89 16V32" stroke="#002766"/>
+<path d="M95 8V32" stroke="#002766" stroke-width="2"/>
+<path d="M101 16V32" stroke="#002766"/>
+<path d="M107 16V32" stroke="#002766"/>
+<path d="M113 16V32" stroke="#002766"/>
+<path d="M119 16V32" stroke="#002766"/>
+<path d="M125 8V32" stroke="#002766" stroke-width="2"/>
+<path d="M131 16V32" stroke="#002766"/>
+<path d="M137 16V32" stroke="#002766"/>
+<path d="M143 16V32" stroke="#002766"/>
+<path d="M149 16V32" stroke="#002766"/>
+<path d="M155 0V32" stroke="#002766" stroke-width="2"/>
+<path d="M161 16V32" stroke="#002766"/>
+<path d="M167 16V32" stroke="#002766"/>
+<path d="M173 16V32" stroke="#002766"/>
+<path d="M179 16V32" stroke="#002766"/>
+<path d="M185 8V32" stroke="#002766" stroke-width="2"/>
+<path d="M191 16V32" stroke="#002766"/>
+<path d="M197 16V32" stroke="#002766"/>
+<path d="M203 16V32" stroke="#002766"/>
+<path d="M209 16V32" stroke="#002766"/>
+<path d="M215 8V32" stroke="#002766" stroke-width="2"/>
+<path d="M221 16V32" stroke="#002766"/>
+<path d="M227 16V32" stroke="#002766"/>
+<path d="M233 16V32" stroke="#002766"/>
+<path d="M239 16V32" stroke="#002766"/>
+<path d="M245 8V32" stroke="#002766" stroke-width="2"/>
+<path d="M251 16V32" stroke="#002766"/>
+<path d="M257 16V32" stroke="#002766"/>
+<path d="M263 16V32" stroke="#002766"/>
+<path d="M269 16V32" stroke="#002766"/>
+<path d="M275 8V32" stroke="#002766" stroke-width="2"/>
+</svg>
diff --git a/images/Frame 174.svg b/images/Frame 174.svg
new file mode 100644
index 0000000..9de66ad
--- /dev/null
+++ b/images/Frame 174.svg
@@ -0,0 +1,4 @@
+<svg width="187" height="100" viewBox="0 0 187 100" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M109.125 74.9993H77.8751C76.2175 74.9993 74.6278 75.6578 73.4557 76.8299C72.2835 78.002 71.6251 79.5917 71.6251 81.2493V87.4993C71.6251 89.1569 72.2835 90.7466 73.4557 91.9187C74.6278 93.0908 76.2175 93.7493 77.8751 93.7493H109.125C110.783 93.7493 112.372 93.0908 113.544 91.9187C114.717 90.7466 115.375 89.1569 115.375 87.4993V81.2493C115.375 79.5917 114.717 78.002 113.544 76.8299C112.372 75.6578 110.783 74.9993 109.125 74.9993ZM109.125 87.4993H77.8751V81.2493H109.125V87.4993ZM133.209 44.665L95.7094 7.16496C95.1234 6.57911 94.3287 6.25 93.5001 6.25C92.6714 6.25 91.8767 6.57911 91.2907 7.16496L53.7907 44.665C53.3538 45.102 53.0563 45.6588 52.9357 46.2649C52.8152 46.871 52.8771 47.4992 53.1136 48.0701C53.35 48.6411 53.7505 49.1291 54.2643 49.4725C54.778 49.8158 55.3821 49.9992 56.0001 49.9993H71.6251V62.4993C71.6251 64.1569 72.2835 65.7466 73.4557 66.9187C74.6278 68.0908 76.2175 68.7493 77.8751 68.7493H109.125C110.782 68.7468 112.37 68.0876 113.542 66.916C114.713 65.7444 115.373 64.1562 115.375 62.4993V49.9993H131C131.618 49.9992 132.222 49.8158 132.736 49.4725C133.25 49.1291 133.65 48.6411 133.887 48.0701C134.123 47.4992 134.185 46.871 134.064 46.2649C133.944 45.6588 133.646 45.102 133.209 44.665ZM109.125 43.7493V62.4993H77.8751V43.7493H63.5438L93.5001 13.7931L123.456 43.7493H109.125Z" fill="#7F7F7F" fill-opacity="0.5" style="mix-blend-mode:luminosity"/>
+<path d="M109.125 74.9993H77.8751C76.2175 74.9993 74.6278 75.6578 73.4557 76.8299C72.2835 78.002 71.6251 79.5917 71.6251 81.2493V87.4993C71.6251 89.1569 72.2835 90.7466 73.4557 91.9187C74.6278 93.0908 76.2175 93.7493 77.8751 93.7493H109.125C110.783 93.7493 112.372 93.0908 113.544 91.9187C114.717 90.7466 115.375 89.1569 115.375 87.4993V81.2493C115.375 79.5917 114.717 78.002 113.544 76.8299C112.372 75.6578 110.783 74.9993 109.125 74.9993ZM109.125 87.4993H77.8751V81.2493H109.125V87.4993ZM133.209 44.665L95.7094 7.16496C95.1234 6.57911 94.3287 6.25 93.5001 6.25C92.6714 6.25 91.8767 6.57911 91.2907 7.16496L53.7907 44.665C53.3538 45.102 53.0563 45.6588 52.9357 46.2649C52.8152 46.871 52.8771 47.4992 53.1136 48.0701C53.35 48.6411 53.7505 49.1291 54.2643 49.4725C54.778 49.8158 55.3821 49.9992 56.0001 49.9993H71.6251V62.4993C71.6251 64.1569 72.2835 65.7466 73.4557 66.9187C74.6278 68.0908 76.2175 68.7493 77.8751 68.7493H109.125C110.782 68.7468 112.37 68.0876 113.542 66.916C114.713 65.7444 115.373 64.1562 115.375 62.4993V49.9993H131C131.618 49.9992 132.222 49.8158 132.736 49.4725C133.25 49.1291 133.65 48.6411 133.887 48.0701C134.123 47.4992 134.185 46.871 134.064 46.2649C133.944 45.6588 133.646 45.102 133.209 44.665ZM109.125 43.7493V62.4993H77.8751V43.7493H63.5438L93.5001 13.7931L123.456 43.7493H109.125Z" fill="#3D3D3D" style="mix-blend-mode:overlay"/>
+</svg>
diff --git a/images/Frame 178.svg b/images/Frame 178.svg
new file mode 100644
index 0000000..7317d7a
--- /dev/null
+++ b/images/Frame 178.svg
@@ -0,0 +1,3 @@
+<svg width="140" height="140" viewBox="0 0 140 140" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M69.9999 12C37.9676 12 12 37.9676 12 69.9999C12 102.032 37.9676 128 69.9999 128C102.032 128 128 102.032 128 69.9999C128 37.9676 102.032 12 69.9999 12ZM69.9999 116.4C44.4151 116.4 23.6001 95.5849 23.6001 69.9999C23.6001 44.4148 44.4148 23.6001 69.9999 23.6001C95.5849 23.6001 116.4 44.4148 116.4 69.9999C116.4 95.5849 95.5849 116.4 69.9999 116.4ZM91.8412 49.2778L100.043 57.4795L64.2 93.4724L42.6993 71.9718L50.9007 63.7701L64.2 77.0694L91.8412 49.2778Z" fill="#1890FF"/>
+</svg>
diff --git a/images/Frame 179.svg b/images/Frame 179.svg
new file mode 100644
index 0000000..e58bde9
--- /dev/null
+++ b/images/Frame 179.svg
@@ -0,0 +1,4 @@
+<svg width="140" height="140" viewBox="0 0 140 140" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M69.9999 12C37.9676 12 12 37.9676 12 69.9999C12 102.032 37.9676 128 69.9999 128C102.032 128 128 102.032 128 69.9999C128 37.9676 102.032 12 69.9999 12ZM69.9999 116.4C44.4151 116.4 23.6001 95.5849 23.6001 69.9999C23.6001 44.4148 44.4148 23.6001 69.9999 23.6001C95.5849 23.6001 116.4 44.4148 116.4 69.9999C116.4 95.5849 95.5849 116.4 69.9999 116.4Z" fill="#1890FF"/>
+<path d="M95 51.7843L88.2111 45L69.983 63.2157L51.7889 45.034L45 51.8182L63.1941 70L45 88.182L51.7889 94.9663L69.983 76.7841L88.2111 95L95 88.2157L76.7719 70L95 51.7843Z" fill="#1890FF"/>
+</svg>
diff --git a/images/Frame 180.svg b/images/Frame 180.svg
new file mode 100644
index 0000000..79044df
--- /dev/null
+++ b/images/Frame 180.svg
@@ -0,0 +1,5 @@
+<svg width="156" height="183" viewBox="0 0 156 183" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M61.875 146.438C60.7561 146.438 59.6831 146.882 58.8919 147.673C58.1007 148.464 57.6562 149.537 57.6562 150.656C57.6562 151.775 58.1007 152.848 58.8919 153.639C59.6831 154.431 60.7561 154.875 61.875 154.875H73.125C74.2439 154.875 75.3169 154.431 76.1081 153.639C76.8993 152.848 77.3438 151.775 77.3438 150.656C77.3438 149.537 76.8993 148.464 76.1081 147.673C75.3169 146.882 74.2439 146.438 73.125 146.438H61.875Z" fill="#1890FF"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M45 59.25C41.6434 59.25 38.4242 60.5834 36.0507 62.9569C33.6772 65.3304 32.3438 68.5496 32.3438 71.9062V159.094C32.3438 162.45 33.6772 165.67 36.0507 168.043C38.4242 170.417 41.6434 171.75 45 171.75H90C93.3566 171.75 96.5758 170.417 98.9493 168.043C101.323 165.67 102.656 162.45 102.656 159.094V71.9062C102.656 68.5496 101.323 65.3304 98.9493 62.9569C96.5758 60.5834 93.3566 59.25 90 59.25H45ZM40.7812 71.9062C40.7812 70.7874 41.2257 69.7143 42.0169 68.9231C42.8081 68.132 43.8811 67.6875 45 67.6875H90C91.1189 67.6875 92.1919 68.132 92.9831 68.9231C93.7743 69.7143 94.2188 70.7874 94.2188 71.9062V159.094C94.2188 160.213 93.7743 161.286 92.9831 162.077C92.1919 162.868 91.1189 163.312 90 163.312H45C43.8811 163.312 42.8081 162.868 42.0169 162.077C41.2257 161.286 40.7813 160.213 40.7812 159.094V71.9062Z" fill="#1890FF"/>
+<path d="M124.5 55.125C122.663 55.125 121.109 54.4906 119.841 53.2219C118.572 51.9531 117.938 50.4 117.938 48.5625C117.938 46.725 118.572 45.1719 119.841 43.9031C121.109 42.6344 122.663 42 124.5 42C126.338 42 127.891 42.6344 129.159 43.9031C130.428 45.1719 131.063 46.725 131.063 48.5625C131.063 50.4 130.428 51.9531 129.159 53.2219C127.891 54.4906 126.338 55.125 124.5 55.125ZM124.5 26.25C127.781 26.25 130.899 26.775 133.853 27.825C136.807 28.875 139.486 30.3188 141.891 32.1562C142.766 32.8125 143.215 33.677 143.237 34.7497C143.26 35.8225 142.877 36.7518 142.088 37.5375C141.344 38.2813 140.425 38.6645 139.331 38.6872C138.238 38.71 137.253 38.4142 136.378 37.8C134.716 36.6625 132.878 35.7656 130.866 35.1094C128.853 34.4531 126.731 34.125 124.5 34.125C122.269 34.125 120.147 34.4531 118.134 35.1094C116.122 35.7656 114.284 36.6625 112.622 37.8C111.747 38.4125 110.763 38.6969 109.669 38.6531C108.575 38.6094 107.656 38.2156 106.913 37.4719C106.169 36.6844 105.797 35.7551 105.797 34.6841C105.797 33.6131 106.234 32.7486 107.109 32.0906C109.516 30.2531 112.196 28.8199 115.15 27.7909C118.104 26.7619 121.221 26.2483 124.5 26.25ZM124.5 10.5C129.969 10.5 135.121 11.3969 139.956 13.1906C144.791 14.9844 149.133 17.5219 152.981 20.8031C153.856 21.5469 154.316 22.4656 154.359 23.5594C154.403 24.6531 154.031 25.5938 153.244 26.3813C152.5 27.125 151.581 27.5082 150.488 27.531C149.394 27.5537 148.409 27.2143 147.534 26.5125C144.384 23.9313 140.852 21.9301 136.937 20.5091C133.023 19.0881 128.877 18.3767 124.5 18.375C120.123 18.3733 115.978 19.0846 112.065 20.5091C108.152 21.9336 104.619 23.9348 101.466 26.5125C100.591 27.2125 99.6063 27.552 98.5125 27.531C97.4188 27.51 96.5 27.1268 95.7563 26.3813C94.9688 25.5938 94.5969 24.6531 94.6407 23.5594C94.6844 22.4656 95.1438 21.5469 96.0188 20.8031C99.8688 17.5219 104.211 14.9844 109.047 13.1906C113.882 11.3969 119.033 10.5 124.5 10.5Z" fill="#1890FF"/>
+</svg>
diff --git a/images/Frame 5.png b/images/Frame 5.png
new file mode 100644
index 0000000..e9e9f36
--- /dev/null
+++ b/images/Frame 5.png
Binary files differ
diff --git a/images/Toggle.png b/images/Toggle.png
new file mode 100644
index 0000000..ed28180
--- /dev/null
+++ b/images/Toggle.png
Binary files differ
diff --git a/images/Toggle2.png b/images/Toggle2.png
new file mode 100644
index 0000000..30da6cf
--- /dev/null
+++ b/images/Toggle2.png
Binary files differ
diff --git a/images/Vector.svg b/images/Vector.svg
new file mode 100644
index 0000000..6a1609c
--- /dev/null
+++ b/images/Vector.svg
@@ -0,0 +1,3 @@
+<svg width="14" height="7" viewBox="0 0 14 7" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M0 0L6.66667 6.66667L13.3333 0H0Z" fill="black"/>
+</svg>
diff --git a/images/angle-135.svg b/images/angle-135.svg
new file mode 100644
index 0000000..a0341eb
--- /dev/null
+++ b/images/angle-135.svg
@@ -0,0 +1,4 @@
+<svg width="64" height="21" viewBox="0 0 64 21" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="64" height="21" rx="4" fill="#D4B106"/>
+<path d="M15.4861 12.64V11.45H19.1821V12.64H15.4861ZM21.022 16V14.67H23.29V7.502H21.442V6.48C21.9274 6.396 22.3474 6.28867 22.702 6.158C23.066 6.02733 23.3974 5.86867 23.696 5.682H24.914V14.67H26.916V16H21.022ZM31.5684 16.196C31.0271 16.196 30.5464 16.1307 30.1264 16C29.7157 15.8693 29.3517 15.6967 29.0344 15.482C28.7171 15.258 28.4417 15.02 28.2084 14.768L28.9924 13.732C29.3004 14.0307 29.6504 14.292 30.0424 14.516C30.4344 14.74 30.8964 14.852 31.4284 14.852C31.8204 14.852 32.1611 14.7867 32.4504 14.656C32.7397 14.516 32.9637 14.32 33.1224 14.068C33.2904 13.816 33.3744 13.508 33.3744 13.144C33.3744 12.7707 33.2811 12.444 33.0944 12.164C32.9171 11.8747 32.6044 11.6553 32.1564 11.506C31.7177 11.3473 31.1111 11.268 30.3364 11.268V10.064C31.0177 10.064 31.5497 9.98933 31.9324 9.84C32.3244 9.68133 32.6044 9.46667 32.7724 9.196C32.9497 8.92533 33.0384 8.61733 33.0384 8.272C33.0384 7.824 32.8984 7.46933 32.6184 7.208C32.3384 6.93733 31.9511 6.802 31.4564 6.802C31.0644 6.802 30.6957 6.89067 30.3504 7.068C30.0144 7.236 29.6971 7.46467 29.3984 7.754L28.5584 6.746C28.9691 6.37267 29.4171 6.074 29.9024 5.85C30.3877 5.61667 30.9244 5.5 31.5124 5.5C32.1284 5.5 32.6744 5.60733 33.1504 5.822C33.6264 6.02733 33.9997 6.326 34.2704 6.718C34.5411 7.11 34.6764 7.59067 34.6764 8.16C34.6764 8.748 34.5131 9.24733 34.1864 9.658C33.8691 10.0687 33.4397 10.3767 32.8984 10.582V10.638C33.2904 10.7407 33.6451 10.9087 33.9624 11.142C34.2891 11.366 34.5457 11.6553 34.7324 12.01C34.9191 12.3647 35.0124 12.7707 35.0124 13.228C35.0124 13.844 34.8537 14.376 34.5364 14.824C34.2284 15.2627 33.8131 15.6033 33.2904 15.846C32.7677 16.0793 32.1937 16.196 31.5684 16.196ZM39.5528 16.196C39.0208 16.196 38.5448 16.1307 38.1248 16C37.7048 15.8693 37.3361 15.6967 37.0188 15.482C36.7014 15.2673 36.4214 15.0433 36.1788 14.81L36.9488 13.76C37.1448 13.956 37.3594 14.138 37.5928 14.306C37.8261 14.4647 38.0874 14.5953 38.3768 14.698C38.6754 14.8007 39.0068 14.852 39.3708 14.852C39.7534 14.852 40.0988 14.768 40.4068 14.6C40.7148 14.4227 40.9574 14.1707 41.1348 13.844C41.3121 13.508 41.4008 13.1113 41.4008 12.654C41.4008 11.982 41.2188 11.4593 40.8548 11.086C40.5001 10.7127 40.0288 10.526 39.4408 10.526C39.1141 10.526 38.8341 10.5727 38.6008 10.666C38.3674 10.7593 38.1014 10.904 37.8028 11.1L37.0048 10.582L37.3128 5.682H42.5348V7.054H38.7128L38.4748 9.686C38.6988 9.574 38.9228 9.49 39.1468 9.434C39.3708 9.36867 39.6181 9.336 39.8888 9.336C40.4674 9.336 40.9948 9.45267 41.4708 9.686C41.9468 9.91933 42.3248 10.2787 42.6048 10.764C42.8848 11.24 43.0248 11.856 43.0248 12.612C43.0248 13.368 42.8614 14.0167 42.5348 14.558C42.2081 15.09 41.7788 15.496 41.2468 15.776C40.7241 16.056 40.1594 16.196 39.5528 16.196ZM46.4872 9.392C46.1138 9.392 45.7685 9.308 45.4512 9.14C45.1338 8.96267 44.8818 8.72 44.6952 8.412C44.5085 8.09467 44.4152 7.726 44.4152 7.306C44.4152 6.886 44.5085 6.522 44.6952 6.214C44.8818 5.89667 45.1338 5.64933 45.4512 5.472C45.7685 5.29467 46.1138 5.206 46.4872 5.206C46.8605 5.206 47.2012 5.29467 47.5092 5.472C47.8265 5.64933 48.0785 5.89667 48.2652 6.214C48.4518 6.522 48.5452 6.886 48.5452 7.306C48.5452 7.726 48.4518 8.09467 48.2652 8.412C48.0785 8.72 47.8265 8.96267 47.5092 9.14C47.2012 9.308 46.8605 9.392 46.4872 9.392ZM46.4872 8.552C46.8232 8.552 47.0985 8.43533 47.3132 8.202C47.5278 7.96867 47.6352 7.67 47.6352 7.306C47.6352 6.93267 47.5278 6.62933 47.3132 6.396C47.0985 6.16267 46.8232 6.046 46.4872 6.046C46.1512 6.046 45.8758 6.16267 45.6612 6.396C45.4465 6.62933 45.3392 6.93267 45.3392 7.306C45.3392 7.67 45.4465 7.96867 45.6612 8.202C45.8758 8.43533 46.1512 8.552 46.4872 8.552Z" fill="#FFEC3D"/>
+</svg>
diff --git a/images/angle-45.svg b/images/angle-45.svg
new file mode 100644
index 0000000..864bc6f
--- /dev/null
+++ b/images/angle-45.svg
@@ -0,0 +1,4 @@
+<svg width="64" height="21" viewBox="0 0 64 21" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="64" height="21" rx="4" fill="#7CB305"/>
+<path d="M19.4783 12.64V11.45H23.1743V12.64H19.4783ZM28.5702 16V9.28C28.5702 9 28.5796 8.66867 28.5982 8.286C28.6169 7.894 28.6309 7.558 28.6402 7.278H28.5842C28.4536 7.53933 28.3182 7.80533 28.1782 8.076C28.0476 8.34667 27.9076 8.61267 27.7582 8.874L25.7422 11.968H31.3842V13.228H24.1042V12.15L28.2062 5.682H30.0822V16H28.5702ZM35.5606 16.196C35.0286 16.196 34.5526 16.1307 34.1326 16C33.7126 15.8693 33.3439 15.6967 33.0266 15.482C32.7093 15.2673 32.4293 15.0433 32.1866 14.81L32.9566 13.76C33.1526 13.956 33.3673 14.138 33.6006 14.306C33.8339 14.4647 34.0953 14.5953 34.3846 14.698C34.6833 14.8007 35.0146 14.852 35.3786 14.852C35.7613 14.852 36.1066 14.768 36.4146 14.6C36.7226 14.4227 36.9653 14.1707 37.1426 13.844C37.3199 13.508 37.4086 13.1113 37.4086 12.654C37.4086 11.982 37.2266 11.4593 36.8626 11.086C36.5079 10.7127 36.0366 10.526 35.4486 10.526C35.1219 10.526 34.8419 10.5727 34.6086 10.666C34.3753 10.7593 34.1093 10.904 33.8106 11.1L33.0126 10.582L33.3206 5.682H38.5426V7.054H34.7206L34.4826 9.686C34.7066 9.574 34.9306 9.49 35.1546 9.434C35.3786 9.36867 35.6259 9.336 35.8966 9.336C36.4753 9.336 37.0026 9.45267 37.4786 9.686C37.9546 9.91933 38.3326 10.2787 38.6126 10.764C38.8926 11.24 39.0326 11.856 39.0326 12.612C39.0326 13.368 38.8693 14.0167 38.5426 14.558C38.2159 15.09 37.7866 15.496 37.2546 15.776C36.7319 16.056 36.1673 16.196 35.5606 16.196ZM42.495 9.392C42.1216 9.392 41.7763 9.308 41.459 9.14C41.1416 8.96267 40.8896 8.72 40.703 8.412C40.5163 8.09467 40.423 7.726 40.423 7.306C40.423 6.886 40.5163 6.522 40.703 6.214C40.8896 5.89667 41.1416 5.64933 41.459 5.472C41.7763 5.29467 42.1216 5.206 42.495 5.206C42.8683 5.206 43.209 5.29467 43.517 5.472C43.8343 5.64933 44.0863 5.89667 44.273 6.214C44.4596 6.522 44.553 6.886 44.553 7.306C44.553 7.726 44.4596 8.09467 44.273 8.412C44.0863 8.72 43.8343 8.96267 43.517 9.14C43.209 9.308 42.8683 9.392 42.495 9.392ZM42.495 8.552C42.831 8.552 43.1063 8.43533 43.321 8.202C43.5356 7.96867 43.643 7.67 43.643 7.306C43.643 6.93267 43.5356 6.62933 43.321 6.396C43.1063 6.16267 42.831 6.046 42.495 6.046C42.159 6.046 41.8836 6.16267 41.669 6.396C41.4543 6.62933 41.347 6.93267 41.347 7.306C41.347 7.67 41.4543 7.96867 41.669 8.202C41.8836 8.43533 42.159 8.552 42.495 8.552Z" fill="#D3F261"/>
+</svg>
diff --git a/images/angle-90.svg b/images/angle-90.svg
new file mode 100644
index 0000000..5018aae
--- /dev/null
+++ b/images/angle-90.svg
@@ -0,0 +1,4 @@
+<svg width="64" height="21" viewBox="0 0 64 21" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="64" height="21" rx="4" fill="#D3F261"/>
+<path d="M19.4783 12.64V11.45H23.1743V12.64H19.4783ZM27.2402 16.196C26.6429 16.196 26.1249 16.0887 25.6862 15.874C25.2569 15.65 24.8929 15.3887 24.5942 15.09L25.4762 14.082C25.6816 14.3153 25.9336 14.502 26.2322 14.642C26.5309 14.782 26.8389 14.852 27.1562 14.852C27.4829 14.852 27.7909 14.7773 28.0802 14.628C28.3789 14.4787 28.6356 14.236 28.8502 13.9C29.0742 13.564 29.2469 13.116 29.3682 12.556C29.4989 11.996 29.5642 11.31 29.5642 10.498C29.5642 9.63933 29.4802 8.93467 29.3122 8.384C29.1442 7.824 28.9062 7.41333 28.5982 7.152C28.2996 6.88133 27.9402 6.746 27.5202 6.746C27.2216 6.746 26.9509 6.83467 26.7082 7.012C26.4656 7.18 26.2742 7.42267 26.1342 7.74C25.9942 8.05733 25.9242 8.44 25.9242 8.888C25.9242 9.32667 25.9849 9.7 26.1062 10.008C26.2369 10.316 26.4282 10.554 26.6802 10.722C26.9322 10.8807 27.2356 10.96 27.5902 10.96C27.9169 10.96 28.2529 10.8573 28.5982 10.652C28.9436 10.4467 29.2702 10.1107 29.5782 9.644L29.6482 10.834C29.4522 11.0953 29.2236 11.324 28.9622 11.52C28.7009 11.716 28.4302 11.87 28.1502 11.982C27.8702 12.0847 27.5902 12.136 27.3102 12.136C26.7409 12.136 26.2369 12.0147 25.7982 11.772C25.3689 11.5293 25.0282 11.17 24.7762 10.694C24.5336 10.2087 24.4122 9.60667 24.4122 8.888C24.4122 8.20667 24.5522 7.614 24.8322 7.11C25.1216 6.59667 25.4996 6.2 25.9662 5.92C26.4329 5.64 26.9416 5.5 27.4922 5.5C27.9869 5.5 28.4489 5.60267 28.8782 5.808C29.3169 6.004 29.6949 6.30733 30.0122 6.718C30.3389 7.12867 30.5956 7.64667 30.7822 8.272C30.9689 8.89733 31.0622 9.63933 31.0622 10.498C31.0622 11.506 30.9596 12.374 30.7542 13.102C30.5489 13.8207 30.2642 14.4087 29.9002 14.866C29.5362 15.314 29.1256 15.65 28.6682 15.874C28.2109 16.0887 27.7349 16.196 27.2402 16.196ZM35.8126 16.196C35.1406 16.196 34.5526 15.9953 34.0486 15.594C33.5446 15.1927 33.1526 14.5953 32.8726 13.802C32.6019 12.9993 32.4666 12.0007 32.4666 10.806C32.4666 9.61133 32.6019 8.622 32.8726 7.838C33.1526 7.054 33.5446 6.47067 34.0486 6.088C34.5526 5.696 35.1406 5.5 35.8126 5.5C36.4846 5.5 37.0679 5.696 37.5626 6.088C38.0573 6.48 38.4399 7.068 38.7106 7.852C38.9906 8.62667 39.1306 9.61133 39.1306 10.806C39.1306 12.0007 38.9906 12.9993 38.7106 13.802C38.4399 14.5953 38.0573 15.1927 37.5626 15.594C37.0679 15.9953 36.4846 16.196 35.8126 16.196ZM35.8126 14.908C36.1579 14.908 36.4659 14.7727 36.7366 14.502C37.0073 14.2313 37.2173 13.7973 37.3666 13.2C37.5159 12.5933 37.5906 11.7953 37.5906 10.806C37.5906 9.81667 37.5159 9.028 37.3666 8.44C37.2173 7.852 37.0073 7.42733 36.7366 7.166C36.4659 6.90467 36.1579 6.774 35.8126 6.774C35.4673 6.774 35.1593 6.90467 34.8886 7.166C34.6179 7.42733 34.4033 7.852 34.2446 8.44C34.0953 9.028 34.0206 9.81667 34.0206 10.806C34.0206 11.7953 34.0953 12.5933 34.2446 13.2C34.4033 13.7973 34.6179 14.2313 34.8886 14.502C35.1593 14.7727 35.4673 14.908 35.8126 14.908ZM42.495 9.392C42.1216 9.392 41.7763 9.308 41.459 9.14C41.1416 8.96267 40.8896 8.72 40.703 8.412C40.5163 8.09467 40.423 7.726 40.423 7.306C40.423 6.886 40.5163 6.522 40.703 6.214C40.8896 5.89667 41.1416 5.64933 41.459 5.472C41.7763 5.29467 42.1216 5.206 42.495 5.206C42.8683 5.206 43.209 5.29467 43.517 5.472C43.8343 5.64933 44.0863 5.89667 44.273 6.214C44.4596 6.522 44.553 6.886 44.553 7.306C44.553 7.726 44.4596 8.09467 44.273 8.412C44.0863 8.72 43.8343 8.96267 43.517 9.14C43.209 9.308 42.8683 9.392 42.495 9.392ZM42.495 8.552C42.831 8.552 43.1063 8.43533 43.321 8.202C43.5356 7.96867 43.643 7.67 43.643 7.306C43.643 6.93267 43.5356 6.62933 43.321 6.396C43.1063 6.16267 42.831 6.046 42.495 6.046C42.159 6.046 41.8836 6.16267 41.669 6.396C41.4543 6.62933 41.347 6.93267 41.347 7.306C41.347 7.67 41.4543 7.96867 41.669 8.202C41.8836 8.43533 42.159 8.552 42.495 8.552Z" fill="#7CB305"/>
+</svg>
diff --git a/images/angle0.svg b/images/angle0.svg
new file mode 100644
index 0000000..4965556
--- /dev/null
+++ b/images/angle0.svg
@@ -0,0 +1,4 @@
+<svg width="64" height="21" viewBox="0 0 64 21" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="64" height="21" rx="4" fill="#FFA39E"/>
+<path d="M29.3185 16.196C28.6465 16.196 28.0585 15.9953 27.5545 15.594C27.0505 15.1927 26.6585 14.5953 26.3785 13.802C26.1078 12.9993 25.9725 12.0007 25.9725 10.806C25.9725 9.61133 26.1078 8.622 26.3785 7.838C26.6585 7.054 27.0505 6.47067 27.5545 6.088C28.0585 5.696 28.6465 5.5 29.3185 5.5C29.9905 5.5 30.5738 5.696 31.0685 6.088C31.5631 6.48 31.9458 7.068 32.2165 7.852C32.4965 8.62667 32.6365 9.61133 32.6365 10.806C32.6365 12.0007 32.4965 12.9993 32.2165 13.802C31.9458 14.5953 31.5631 15.1927 31.0685 15.594C30.5738 15.9953 29.9905 16.196 29.3185 16.196ZM29.3185 14.908C29.6638 14.908 29.9718 14.7727 30.2425 14.502C30.5131 14.2313 30.7231 13.7973 30.8725 13.2C31.0218 12.5933 31.0965 11.7953 31.0965 10.806C31.0965 9.81667 31.0218 9.028 30.8725 8.44C30.7231 7.852 30.5131 7.42733 30.2425 7.166C29.9718 6.90467 29.6638 6.774 29.3185 6.774C28.9731 6.774 28.6651 6.90467 28.3945 7.166C28.1238 7.42733 27.9091 7.852 27.7505 8.44C27.6011 9.028 27.5265 9.81667 27.5265 10.806C27.5265 11.7953 27.6011 12.5933 27.7505 13.2C27.9091 13.7973 28.1238 14.2313 28.3945 14.502C28.6651 14.7727 28.9731 14.908 29.3185 14.908ZM36.0008 9.392C35.6275 9.392 35.2822 9.308 34.9648 9.14C34.6475 8.96267 34.3955 8.72 34.2088 8.412C34.0222 8.09467 33.9288 7.726 33.9288 7.306C33.9288 6.886 34.0222 6.522 34.2088 6.214C34.3955 5.89667 34.6475 5.64933 34.9648 5.472C35.2822 5.29467 35.6275 5.206 36.0008 5.206C36.3742 5.206 36.7148 5.29467 37.0228 5.472C37.3402 5.64933 37.5922 5.89667 37.7788 6.214C37.9655 6.522 38.0588 6.886 38.0588 7.306C38.0588 7.726 37.9655 8.09467 37.7788 8.412C37.5922 8.72 37.3402 8.96267 37.0228 9.14C36.7148 9.308 36.3742 9.392 36.0008 9.392ZM36.0008 8.552C36.3368 8.552 36.6122 8.43533 36.8268 8.202C37.0415 7.96867 37.1488 7.67 37.1488 7.306C37.1488 6.93267 37.0415 6.62933 36.8268 6.396C36.6122 6.16267 36.3368 6.046 36.0008 6.046C35.6648 6.046 35.3895 6.16267 35.1748 6.396C34.9602 6.62933 34.8528 6.93267 34.8528 7.306C34.8528 7.67 34.9602 7.96867 35.1748 8.202C35.3895 8.43533 35.6648 8.552 36.0008 8.552Z" fill="#F5222D"/>
+</svg>
diff --git a/images/angle135.svg b/images/angle135.svg
new file mode 100644
index 0000000..e9cc60b
--- /dev/null
+++ b/images/angle135.svg
@@ -0,0 +1,4 @@
+<svg width="64" height="21" viewBox="0 0 64 21" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="64" height="21" rx="4" fill="#FA8C16"/>
+<path d="M18.5201 16V14.67H20.7881V7.502H18.9401V6.48C19.4254 6.396 19.8454 6.28867 20.2001 6.158C20.5641 6.02733 20.8954 5.86867 21.1941 5.682H22.4121V14.67H24.4141V16H18.5201ZM29.0665 16.196C28.5251 16.196 28.0445 16.1307 27.6245 16C27.2138 15.8693 26.8498 15.6967 26.5325 15.482C26.2151 15.258 25.9398 15.02 25.7065 14.768L26.4905 13.732C26.7985 14.0307 27.1485 14.292 27.5405 14.516C27.9325 14.74 28.3945 14.852 28.9265 14.852C29.3185 14.852 29.6591 14.7867 29.9485 14.656C30.2378 14.516 30.4618 14.32 30.6205 14.068C30.7885 13.816 30.8725 13.508 30.8725 13.144C30.8725 12.7707 30.7791 12.444 30.5925 12.164C30.4151 11.8747 30.1025 11.6553 29.6545 11.506C29.2158 11.3473 28.6091 11.268 27.8345 11.268V10.064C28.5158 10.064 29.0478 9.98933 29.4305 9.84C29.8225 9.68133 30.1025 9.46667 30.2705 9.196C30.4478 8.92533 30.5365 8.61733 30.5365 8.272C30.5365 7.824 30.3965 7.46933 30.1165 7.208C29.8365 6.93733 29.4491 6.802 28.9545 6.802C28.5625 6.802 28.1938 6.89067 27.8485 7.068C27.5125 7.236 27.1951 7.46467 26.8965 7.754L26.0565 6.746C26.4671 6.37267 26.9151 6.074 27.4005 5.85C27.8858 5.61667 28.4225 5.5 29.0105 5.5C29.6265 5.5 30.1725 5.60733 30.6485 5.822C31.1245 6.02733 31.4978 6.326 31.7685 6.718C32.0391 7.11 32.1745 7.59067 32.1745 8.16C32.1745 8.748 32.0111 9.24733 31.6845 9.658C31.3671 10.0687 30.9378 10.3767 30.3965 10.582V10.638C30.7885 10.7407 31.1431 10.9087 31.4605 11.142C31.7871 11.366 32.0438 11.6553 32.2305 12.01C32.4171 12.3647 32.5105 12.7707 32.5105 13.228C32.5105 13.844 32.3518 14.376 32.0345 14.824C31.7265 15.2627 31.3111 15.6033 30.7885 15.846C30.2658 16.0793 29.6918 16.196 29.0665 16.196ZM37.0508 16.196C36.5188 16.196 36.0428 16.1307 35.6228 16C35.2028 15.8693 34.8342 15.6967 34.5168 15.482C34.1995 15.2673 33.9195 15.0433 33.6768 14.81L34.4468 13.76C34.6428 13.956 34.8575 14.138 35.0908 14.306C35.3242 14.4647 35.5855 14.5953 35.8748 14.698C36.1735 14.8007 36.5048 14.852 36.8688 14.852C37.2515 14.852 37.5968 14.768 37.9048 14.6C38.2128 14.4227 38.4555 14.1707 38.6328 13.844C38.8102 13.508 38.8988 13.1113 38.8988 12.654C38.8988 11.982 38.7168 11.4593 38.3528 11.086C37.9982 10.7127 37.5268 10.526 36.9388 10.526C36.6122 10.526 36.3322 10.5727 36.0988 10.666C35.8655 10.7593 35.5995 10.904 35.3008 11.1L34.5028 10.582L34.8108 5.682H40.0328V7.054H36.2108L35.9728 9.686C36.1968 9.574 36.4208 9.49 36.6448 9.434C36.8688 9.36867 37.1162 9.336 37.3868 9.336C37.9655 9.336 38.4928 9.45267 38.9688 9.686C39.4448 9.91933 39.8228 10.2787 40.1028 10.764C40.3828 11.24 40.5228 11.856 40.5228 12.612C40.5228 13.368 40.3595 14.0167 40.0328 14.558C39.7062 15.09 39.2768 15.496 38.7448 15.776C38.2222 16.056 37.6575 16.196 37.0508 16.196ZM43.9852 9.392C43.6119 9.392 43.2665 9.308 42.9492 9.14C42.6319 8.96267 42.3799 8.72 42.1932 8.412C42.0065 8.09467 41.9132 7.726 41.9132 7.306C41.9132 6.886 42.0065 6.522 42.1932 6.214C42.3799 5.89667 42.6319 5.64933 42.9492 5.472C43.2665 5.29467 43.6119 5.206 43.9852 5.206C44.3585 5.206 44.6992 5.29467 45.0072 5.472C45.3245 5.64933 45.5765 5.89667 45.7632 6.214C45.9499 6.522 46.0432 6.886 46.0432 7.306C46.0432 7.726 45.9499 8.09467 45.7632 8.412C45.5765 8.72 45.3245 8.96267 45.0072 9.14C44.6992 9.308 44.3585 9.392 43.9852 9.392ZM43.9852 8.552C44.3212 8.552 44.5965 8.43533 44.8112 8.202C45.0259 7.96867 45.1332 7.67 45.1332 7.306C45.1332 6.93267 45.0259 6.62933 44.8112 6.396C44.5965 6.16267 44.3212 6.046 43.9852 6.046C43.6492 6.046 43.3739 6.16267 43.1592 6.396C42.9445 6.62933 42.8372 6.93267 42.8372 7.306C42.8372 7.67 42.9445 7.96867 43.1592 8.202C43.3739 8.43533 43.6492 8.552 43.9852 8.552Z" fill="#FFD591"/>
+</svg>
diff --git a/images/angle180.svg b/images/angle180.svg
new file mode 100644
index 0000000..2337e52
--- /dev/null
+++ b/images/angle180.svg
@@ -0,0 +1,4 @@
+<svg width="64" height="21" viewBox="0 0 64 21" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="64" height="21" rx="4" fill="#FFEC3D"/>
+<path d="M18.5201 16V14.67H20.7881V7.502H18.9401V6.48C19.4254 6.396 19.8454 6.28867 20.2001 6.158C20.5641 6.02733 20.8954 5.86867 21.1941 5.682H22.4121V14.67H24.4141V16H18.5201ZM29.3185 16.196C28.6745 16.196 28.1005 16.0793 27.5965 15.846C27.0925 15.6033 26.6911 15.2767 26.3925 14.866C26.1031 14.446 25.9585 13.97 25.9585 13.438C25.9585 12.9807 26.0471 12.5747 26.2245 12.22C26.4018 11.8653 26.6305 11.562 26.9105 11.31C27.1905 11.0487 27.4845 10.834 27.7925 10.666V10.596C27.4191 10.3253 27.0971 9.994 26.8265 9.602C26.5558 9.20067 26.4205 8.72933 26.4205 8.188C26.4205 7.656 26.5465 7.18933 26.7985 6.788C27.0598 6.38667 27.4098 6.07867 27.8485 5.864C28.2965 5.64 28.8051 5.528 29.3745 5.528C29.9718 5.528 30.4851 5.64467 30.9145 5.878C31.3438 6.11133 31.6751 6.43333 31.9085 6.844C32.1511 7.24533 32.2725 7.71667 32.2725 8.258C32.2725 8.60333 32.2025 8.93 32.0625 9.238C31.9225 9.546 31.7498 9.826 31.5445 10.078C31.3485 10.3207 31.1385 10.5213 30.9145 10.68V10.75C31.2318 10.918 31.5211 11.128 31.7825 11.38C32.0438 11.6227 32.2538 11.9167 32.4125 12.262C32.5711 12.6073 32.6505 13.0133 32.6505 13.48C32.6505 13.984 32.5105 14.4413 32.2305 14.852C31.9598 15.2627 31.5725 15.5893 31.0685 15.832C30.5738 16.0747 29.9905 16.196 29.3185 16.196ZM30.0045 10.274C30.3031 9.98467 30.5271 9.68133 30.6765 9.364C30.8351 9.03733 30.9145 8.69667 30.9145 8.342C30.9145 8.034 30.8538 7.754 30.7325 7.502C30.6111 7.25 30.4291 7.054 30.1865 6.914C29.9531 6.76467 29.6685 6.69 29.3325 6.69C28.9125 6.69 28.5625 6.82533 28.2825 7.096C28.0025 7.35733 27.8625 7.72133 27.8625 8.188C27.8625 8.56133 27.9605 8.874 28.1565 9.126C28.3525 9.378 28.6138 9.59267 28.9405 9.77C29.2671 9.94733 29.6218 10.1153 30.0045 10.274ZM29.3605 15.02C29.7058 15.02 30.0091 14.9547 30.2705 14.824C30.5411 14.6933 30.7511 14.5113 30.9005 14.278C31.0498 14.0353 31.1245 13.7507 31.1245 13.424C31.1245 13.116 31.0591 12.85 30.9285 12.626C30.7978 12.3927 30.6158 12.192 30.3825 12.024C30.1585 11.856 29.8925 11.702 29.5845 11.562C29.2765 11.4127 28.9451 11.268 28.5905 11.128C28.2358 11.38 27.9465 11.6927 27.7225 12.066C27.4985 12.43 27.3865 12.8313 27.3865 13.27C27.3865 13.6153 27.4705 13.9187 27.6385 14.18C27.8158 14.4413 28.0538 14.6467 28.3525 14.796C28.6511 14.9453 28.9871 15.02 29.3605 15.02ZM37.3028 16.196C36.6308 16.196 36.0428 15.9953 35.5388 15.594C35.0348 15.1927 34.6428 14.5953 34.3628 13.802C34.0922 12.9993 33.9568 12.0007 33.9568 10.806C33.9568 9.61133 34.0922 8.622 34.3628 7.838C34.6428 7.054 35.0348 6.47067 35.5388 6.088C36.0428 5.696 36.6308 5.5 37.3028 5.5C37.9748 5.5 38.5582 5.696 39.0528 6.088C39.5475 6.48 39.9302 7.068 40.2008 7.852C40.4808 8.62667 40.6208 9.61133 40.6208 10.806C40.6208 12.0007 40.4808 12.9993 40.2008 13.802C39.9302 14.5953 39.5475 15.1927 39.0528 15.594C38.5582 15.9953 37.9748 16.196 37.3028 16.196ZM37.3028 14.908C37.6482 14.908 37.9562 14.7727 38.2268 14.502C38.4975 14.2313 38.7075 13.7973 38.8568 13.2C39.0062 12.5933 39.0808 11.7953 39.0808 10.806C39.0808 9.81667 39.0062 9.028 38.8568 8.44C38.7075 7.852 38.4975 7.42733 38.2268 7.166C37.9562 6.90467 37.6482 6.774 37.3028 6.774C36.9575 6.774 36.6495 6.90467 36.3788 7.166C36.1082 7.42733 35.8935 7.852 35.7348 8.44C35.5855 9.028 35.5108 9.81667 35.5108 10.806C35.5108 11.7953 35.5855 12.5933 35.7348 13.2C35.8935 13.7973 36.1082 14.2313 36.3788 14.502C36.6495 14.7727 36.9575 14.908 37.3028 14.908ZM43.9852 9.392C43.6119 9.392 43.2665 9.308 42.9492 9.14C42.6319 8.96267 42.3799 8.72 42.1932 8.412C42.0065 8.09467 41.9132 7.726 41.9132 7.306C41.9132 6.886 42.0065 6.522 42.1932 6.214C42.3799 5.89667 42.6319 5.64933 42.9492 5.472C43.2665 5.29467 43.6119 5.206 43.9852 5.206C44.3585 5.206 44.6992 5.29467 45.0072 5.472C45.3245 5.64933 45.5765 5.89667 45.7632 6.214C45.9499 6.522 46.0432 6.886 46.0432 7.306C46.0432 7.726 45.9499 8.09467 45.7632 8.412C45.5765 8.72 45.3245 8.96267 45.0072 9.14C44.6992 9.308 44.3585 9.392 43.9852 9.392ZM43.9852 8.552C44.3212 8.552 44.5965 8.43533 44.8112 8.202C45.0259 7.96867 45.1332 7.67 45.1332 7.306C45.1332 6.93267 45.0259 6.62933 44.8112 6.396C44.5965 6.16267 44.3212 6.046 43.9852 6.046C43.6492 6.046 43.3739 6.16267 43.1592 6.396C42.9445 6.62933 42.8372 6.93267 42.8372 7.306C42.8372 7.67 42.9445 7.96867 43.1592 8.202C43.3739 8.43533 43.6492 8.552 43.9852 8.552Z" fill="#D4B106"/>
+</svg>
diff --git a/images/angle45.svg b/images/angle45.svg
new file mode 100644
index 0000000..ec0a609
--- /dev/null
+++ b/images/angle45.svg
@@ -0,0 +1,4 @@
+<svg width="64" height="21" viewBox="0 0 64 21" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="64" height="21" rx="4" fill="#F5222D"/>
+<path d="M26.0683 16V9.28C26.0683 9 26.0776 8.66867 26.0963 8.286C26.1149 7.894 26.1289 7.558 26.1383 7.278H26.0823C25.9516 7.53933 25.8163 7.80533 25.6763 8.076C25.5456 8.34667 25.4056 8.61267 25.2563 8.874L23.2403 11.968H28.8823V13.228H21.6023V12.15L25.7043 5.682H27.5803V16H26.0683ZM33.0586 16.196C32.5266 16.196 32.0506 16.1307 31.6306 16C31.2106 15.8693 30.842 15.6967 30.5246 15.482C30.2073 15.2673 29.9273 15.0433 29.6846 14.81L30.4546 13.76C30.6506 13.956 30.8653 14.138 31.0986 14.306C31.332 14.4647 31.5933 14.5953 31.8826 14.698C32.1813 14.8007 32.5126 14.852 32.8766 14.852C33.2593 14.852 33.6046 14.768 33.9126 14.6C34.2206 14.4227 34.4633 14.1707 34.6406 13.844C34.818 13.508 34.9066 13.1113 34.9066 12.654C34.9066 11.982 34.7246 11.4593 34.3606 11.086C34.006 10.7127 33.5346 10.526 32.9466 10.526C32.62 10.526 32.34 10.5727 32.1066 10.666C31.8733 10.7593 31.6073 10.904 31.3086 11.1L30.5106 10.582L30.8186 5.682H36.0406V7.054H32.2186L31.9806 9.686C32.2046 9.574 32.4286 9.49 32.6526 9.434C32.8766 9.36867 33.124 9.336 33.3946 9.336C33.9733 9.336 34.5006 9.45267 34.9766 9.686C35.4526 9.91933 35.8306 10.2787 36.1106 10.764C36.3906 11.24 36.5306 11.856 36.5306 12.612C36.5306 13.368 36.3673 14.0167 36.0406 14.558C35.714 15.09 35.2846 15.496 34.7526 15.776C34.23 16.056 33.6653 16.196 33.0586 16.196ZM39.993 9.392C39.6197 9.392 39.2743 9.308 38.957 9.14C38.6397 8.96267 38.3877 8.72 38.201 8.412C38.0143 8.09467 37.921 7.726 37.921 7.306C37.921 6.886 38.0143 6.522 38.201 6.214C38.3877 5.89667 38.6397 5.64933 38.957 5.472C39.2743 5.29467 39.6197 5.206 39.993 5.206C40.3663 5.206 40.707 5.29467 41.015 5.472C41.3323 5.64933 41.5843 5.89667 41.771 6.214C41.9577 6.522 42.051 6.886 42.051 7.306C42.051 7.726 41.9577 8.09467 41.771 8.412C41.5843 8.72 41.3323 8.96267 41.015 9.14C40.707 9.308 40.3663 9.392 39.993 9.392ZM39.993 8.552C40.329 8.552 40.6043 8.43533 40.819 8.202C41.0337 7.96867 41.141 7.67 41.141 7.306C41.141 6.93267 41.0337 6.62933 40.819 6.396C40.6043 6.16267 40.329 6.046 39.993 6.046C39.657 6.046 39.3817 6.16267 39.167 6.396C38.9523 6.62933 38.845 6.93267 38.845 7.306C38.845 7.67 38.9523 7.96867 39.167 8.202C39.3817 8.43533 39.657 8.552 39.993 8.552Z" fill="#FFA39E"/>
+</svg>
diff --git a/images/angle90.svg b/images/angle90.svg
new file mode 100644
index 0000000..991ca9c
--- /dev/null
+++ b/images/angle90.svg
@@ -0,0 +1,4 @@
+<svg width="64" height="21" viewBox="0 0 64 21" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="64" height="21" rx="4" fill="#FFD591"/>
+<path d="M24.7383 16.196C24.1409 16.196 23.6229 16.0887 23.1843 15.874C22.7549 15.65 22.3909 15.3887 22.0923 15.09L22.9743 14.082C23.1796 14.3153 23.4316 14.502 23.7303 14.642C24.0289 14.782 24.3369 14.852 24.6543 14.852C24.9809 14.852 25.2889 14.7773 25.5783 14.628C25.8769 14.4787 26.1336 14.236 26.3483 13.9C26.5723 13.564 26.7449 13.116 26.8663 12.556C26.9969 11.996 27.0623 11.31 27.0623 10.498C27.0623 9.63933 26.9783 8.93467 26.8103 8.384C26.6423 7.824 26.4043 7.41333 26.0963 7.152C25.7976 6.88133 25.4383 6.746 25.0183 6.746C24.7196 6.746 24.4489 6.83467 24.2063 7.012C23.9636 7.18 23.7723 7.42267 23.6323 7.74C23.4923 8.05733 23.4223 8.44 23.4223 8.888C23.4223 9.32667 23.4829 9.7 23.6043 10.008C23.7349 10.316 23.9263 10.554 24.1783 10.722C24.4303 10.8807 24.7336 10.96 25.0883 10.96C25.4149 10.96 25.7509 10.8573 26.0963 10.652C26.4416 10.4467 26.7683 10.1107 27.0763 9.644L27.1463 10.834C26.9503 11.0953 26.7216 11.324 26.4603 11.52C26.1989 11.716 25.9283 11.87 25.6483 11.982C25.3683 12.0847 25.0883 12.136 24.8083 12.136C24.2389 12.136 23.7349 12.0147 23.2963 11.772C22.8669 11.5293 22.5263 11.17 22.2743 10.694C22.0316 10.2087 21.9103 9.60667 21.9103 8.888C21.9103 8.20667 22.0503 7.614 22.3303 7.11C22.6196 6.59667 22.9976 6.2 23.4643 5.92C23.9309 5.64 24.4396 5.5 24.9903 5.5C25.4849 5.5 25.9469 5.60267 26.3763 5.808C26.8149 6.004 27.1929 6.30733 27.5103 6.718C27.8369 7.12867 28.0936 7.64667 28.2803 8.272C28.4669 8.89733 28.5603 9.63933 28.5603 10.498C28.5603 11.506 28.4576 12.374 28.2523 13.102C28.0469 13.8207 27.7623 14.4087 27.3983 14.866C27.0343 15.314 26.6236 15.65 26.1663 15.874C25.7089 16.0887 25.2329 16.196 24.7383 16.196ZM33.3106 16.196C32.6386 16.196 32.0506 15.9953 31.5466 15.594C31.0426 15.1927 30.6506 14.5953 30.3706 13.802C30.1 12.9993 29.9646 12.0007 29.9646 10.806C29.9646 9.61133 30.1 8.622 30.3706 7.838C30.6506 7.054 31.0426 6.47067 31.5466 6.088C32.0506 5.696 32.6386 5.5 33.3106 5.5C33.9826 5.5 34.566 5.696 35.0606 6.088C35.5553 6.48 35.938 7.068 36.2086 7.852C36.4886 8.62667 36.6286 9.61133 36.6286 10.806C36.6286 12.0007 36.4886 12.9993 36.2086 13.802C35.938 14.5953 35.5553 15.1927 35.0606 15.594C34.566 15.9953 33.9826 16.196 33.3106 16.196ZM33.3106 14.908C33.656 14.908 33.964 14.7727 34.2346 14.502C34.5053 14.2313 34.7153 13.7973 34.8646 13.2C35.014 12.5933 35.0886 11.7953 35.0886 10.806C35.0886 9.81667 35.014 9.028 34.8646 8.44C34.7153 7.852 34.5053 7.42733 34.2346 7.166C33.964 6.90467 33.656 6.774 33.3106 6.774C32.9653 6.774 32.6573 6.90467 32.3866 7.166C32.116 7.42733 31.9013 7.852 31.7426 8.44C31.5933 9.028 31.5186 9.81667 31.5186 10.806C31.5186 11.7953 31.5933 12.5933 31.7426 13.2C31.9013 13.7973 32.116 14.2313 32.3866 14.502C32.6573 14.7727 32.9653 14.908 33.3106 14.908ZM39.993 9.392C39.6197 9.392 39.2743 9.308 38.957 9.14C38.6397 8.96267 38.3877 8.72 38.201 8.412C38.0143 8.09467 37.921 7.726 37.921 7.306C37.921 6.886 38.0143 6.522 38.201 6.214C38.3877 5.89667 38.6397 5.64933 38.957 5.472C39.2743 5.29467 39.6197 5.206 39.993 5.206C40.3663 5.206 40.707 5.29467 41.015 5.472C41.3323 5.64933 41.5843 5.89667 41.771 6.214C41.9577 6.522 42.051 6.886 42.051 7.306C42.051 7.726 41.9577 8.09467 41.771 8.412C41.5843 8.72 41.3323 8.96267 41.015 9.14C40.707 9.308 40.3663 9.392 39.993 9.392ZM39.993 8.552C40.329 8.552 40.6043 8.43533 40.819 8.202C41.0337 7.96867 41.141 7.67 41.141 7.306C41.141 6.93267 41.0337 6.62933 40.819 6.396C40.6043 6.16267 40.329 6.046 39.993 6.046C39.657 6.046 39.3817 6.16267 39.167 6.396C38.9523 6.62933 38.845 6.93267 38.845 7.306C38.845 7.67 38.9523 7.96867 39.167 8.202C39.3817 8.43533 39.657 8.552 39.993 8.552Z" fill="#FA8C16"/>
+</svg>
diff --git a/images/bx_battery1.svg b/images/bx_battery1.svg
new file mode 100644
index 0000000..8ef8bd9
--- /dev/null
+++ b/images/bx_battery1.svg
@@ -0,0 +1,4 @@
+<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect x="5" y="10" width="19" height="12" fill="#D8D8D8"/>
+<path d="M5.33317 24H23.9998C25.4705 24 26.6665 22.804 26.6665 21.3333V18.6667H29.3332V13.3333H26.6665V10.6667C26.6665 9.196 25.4705 8 23.9998 8H5.33317C3.8625 8 2.6665 9.196 2.6665 10.6667V21.3333C2.6665 22.804 3.8625 24 5.33317 24ZM5.33317 10.6667H23.9998L24.0025 21.3333H5.33317V10.6667Z" fill="#818181"/>
+</svg>
diff --git a/images/bx_battery2.svg b/images/bx_battery2.svg
new file mode 100644
index 0000000..6ae0775
--- /dev/null
+++ b/images/bx_battery2.svg
@@ -0,0 +1,3 @@
+<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M5.33317 24H23.9998C25.4705 24 26.6665 22.804 26.6665 21.3333V18.6667H29.3332V13.3333H26.6665V10.6667C26.6665 9.196 25.4705 8 23.9998 8H5.33317C3.8625 8 2.6665 9.196 2.6665 10.6667V21.3333C2.6665 22.804 3.8625 24 5.33317 24ZM5.33317 10.6667H23.9998L24.0025 21.3333H5.33317V10.6667Z" fill="black"/>
+</svg>
diff --git a/images/bx_battery3.svg b/images/bx_battery3.svg
new file mode 100644
index 0000000..2d884d0
--- /dev/null
+++ b/images/bx_battery3.svg
@@ -0,0 +1,4 @@
+<svg width="44" height="32" viewBox="0 0 44 32" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M34.94 18.0875H32.7267C32.4411 18.0875 32.2298 17.9612 32.0927 17.7085C31.9556 17.4559 31.9706 17.2117 32.1377 16.976L37.4746 9.38998C37.5936 9.22532 37.7483 9.11076 37.9387 9.04631C38.1291 8.98186 38.3254 8.98468 38.5277 9.05478C38.73 9.12488 38.8787 9.24837 38.9739 9.42526C39.0691 9.60215 39.1048 9.79033 39.081 9.98981L38.5098 14.5591H41.2765C41.5859 14.5591 41.8031 14.6943 41.9283 14.9649C42.0535 15.2354 42.0147 15.4882 41.8119 15.7235L35.9395 22.6744C35.8087 22.8273 35.648 22.9273 35.4576 22.9743C35.2672 23.0214 35.0828 23.0037 34.9043 22.9214C34.7258 22.8391 34.5861 22.7128 34.4852 22.5425C34.3843 22.3722 34.3455 22.1868 34.3688 21.9864L34.94 18.0875Z" fill="#73D13D"/>
+<path d="M5.33317 24H23.9998C25.4705 24 26.6665 22.804 26.6665 21.3333V18.6667H29.3332V13.3333H26.6665V10.6667C26.6665 9.196 25.4705 8 23.9998 8H5.33317C3.8625 8 2.6665 9.196 2.6665 10.6667V21.3333C2.6665 22.804 3.8625 24 5.33317 24ZM5.33317 10.6667H23.9998L24.0025 21.3333H5.33317V10.6667Z" fill="black"/>
+</svg>
diff --git a/images/bx_battery4.svg b/images/bx_battery4.svg
new file mode 100644
index 0000000..8088626
--- /dev/null
+++ b/images/bx_battery4.svg
@@ -0,0 +1,3 @@
+<svg width="21" height="12" viewBox="0 0 21 12" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="21" height="12" fill="#73D13D"/>
+</svg>
diff --git a/images/chat.svg b/images/chat.svg
new file mode 100644
index 0000000..91b200f
--- /dev/null
+++ b/images/chat.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1490768070570" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="15572" xmlns:xlink="http://www.w3.org/1999/xlink" width="20" height="20"><defs><style type="text/css"></style></defs><path d="M537.440415 64.020082c-282.543028 0-506.216273 172.632779-506.216273 385.567449 0 120.593566 69.146846 228.241284 184.161347 298.948673 26.057469 16.007579 29.008684 136.187729-117.490901 208.739115 0 0 207.42519 34.229592 338.964038-139.744741 32.529881 4.88424 66.168002 15.305591 100.582813 15.305591 282.543028 0 454.749088-170.300664 454.749088-383.249661C992.18848 236.651838 819.983443 64.020082 537.440415 64.020082zM255.863389 543.725562c-52.986795 0-95.941096-42.954301-95.941096-95.941096s42.954301-95.941096 95.941096-95.941096c52.986795 0 95.941096 42.954301 95.941096 95.941096S308.850184 543.725562 255.863389 543.725562zM511.706311 543.725562c-52.986795 0-95.941096-42.954301-95.941096-95.941096s42.954301-95.941096 95.941096-95.941096c52.986795 0 95.941096 42.954301 95.941096 95.941096S564.693106 543.725562 511.706311 543.725562zM767.549234 543.725562c-52.986795 0-95.941096-42.954301-95.941096-95.941096s42.954301-95.941096 95.941096-95.941096c52.986795 0 95.941096 42.954301 95.941096 95.941096S820.536029 543.725562 767.549234 543.725562z" p-id="15573"></path></svg>
\ No newline at end of file
diff --git a/images/earth.svg b/images/earth.svg
new file mode 100644
index 0000000..b6d9666
--- /dev/null
+++ b/images/earth.svg
@@ -0,0 +1,6 @@
+锘�?xml version="1.0" encoding="utf-8"?>
+<svg version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="89px" height="89px" xmlns="http://www.w3.org/2000/svg">
+  <g transform="matrix(1 0 0 1 -141 -51 )">
+    <path d="M 22.1630859375 5.96809895833333  C 28.981011284722225 1.9893663194444366  36.42664930555556 0  44.5 0  C 52.57335069444445 0  60.018988715277786 1.9893663194444366  66.8369140625 5.96809895833333  C 73.65483940972223 9.946831597222214  79.05316840277779 15.345160590277777  83.03190104166667 22.1630859375  C 87.01063368055554 28.981011284722214  89 36.42664930555554  89 44.5  C 89 52.57335069444445  87.01063368055554 60.018988715277764  83.03190104166667 66.8369140625  C 79.05316840277779 73.65483940972223  73.65483940972223 79.05316840277777  66.8369140625 83.03190104166667  C 60.018988715277786 87.01063368055556  52.57335069444445 89  44.5 89  C 36.42664930555556 89  28.981011284722225 87.01063368055556  22.1630859375 83.03190104166667  C 15.345160590277779 79.05316840277777  9.946831597222223 73.65483940972223  5.968098958333334 66.8369140625  C 1.9893663194444442 60.018988715277764  0 52.57335069444445  0 44.5  C 0 36.42664930555554  1.9893663194444442 28.981011284722214  5.968098958333334 22.1630859375  C 9.946831597222223 15.345160590277777  15.345160590277779 9.946831597222214  22.1630859375 5.96809895833333  Z M 62.86783854166667 29.49283854166667  C 62.21115451388889 29.299696180555543  61.380642361111114 29.531467013888882  60.37630208333333 30.18815104166667  C 60.29904513888889 30.226779513888882  60.11555989583333 30.410264756944436  59.82584635416667 30.73860677083333  C 59.5361328125 31.066948784722225  59.275390625 31.250434027777775  59.04361979166667 31.2890625  C 59.120876736111114 31.2890625  59.207790798611114 31.192491319444436  59.30436197916667 30.99934895833333  C 59.40093315972222 30.806206597222225  59.497504340277786 30.59375  59.59407552083333 30.36197916666667  C 59.69064670138889 30.13020833333333  59.758246527777786 29.995008680555554  59.796875 29.95638020833333  C 60.02864583333333 29.685980902777775  60.453559027777786 29.396267361111107  61.07161458333333 29.08723958333333  C 61.61241319444446 28.85546875  62.61675347222222 28.62369791666667  64.08463541666667 28.39192708333333  C 65.39800347222223 28.082899305555543  66.3830295138889 28.295355902777775  67.03971354166667 29.029296875  C 66.96245659722223 28.952039930555543  67.14594184027779 28.700954861111107  67.59016927083333 28.27604166666667  C 68.0343967013889 27.851128472222214  68.314453125 27.619357638888882  68.43033854166667 27.58072916666667  C 68.54622395833333 27.503472222222214  68.8359375 27.416558159722214  69.29947916666667 27.31998697916667  C 69.76302083333333 27.223415798611107  70.052734375 27.078559027777775  70.16861979166667 26.88541666666667  L 70.28450520833333 25.61067708333333  C 69.82096354166667 25.649305555555543  69.48296440972223 25.514105902777775  69.2705078125 25.205078125  C 69.05805121527779 24.896050347222214  68.93250868055556 24.490451388888882  68.89388020833333 23.98828125  C 68.89388020833333 24.065538194444436  68.77799479166667 24.22005208333333  68.54622395833333 24.45182291666667  C 68.54622395833333 24.181423611111107  68.45930989583333 24.026909722222214  68.28548177083333 23.98828125  C 68.11165364583333 23.949652777777775  67.88953993055556 23.968967013888882  67.619140625 24.04622395833333  C 67.34874131944446 24.123480902777775  67.17491319444446 24.142795138888882  67.09765625 24.10416666666667  C 66.71137152777779 23.98828125  66.42165798611111 23.84342447916667  66.228515625 23.66959635416667  C 66.0353732638889 23.49576822916667  65.880859375 23.17708333333333  65.76497395833333 22.71354166666667  C 65.64908854166667 22.25  65.57183159722223 21.96028645833333  65.533203125 21.84440104166667  C 65.45594618055556 21.651258680555543  65.2724609375 21.43880208333333  64.98274739583333 21.20703125  C 64.69303385416667 20.97526041666667  64.50954861111111 20.782118055555543  64.43229166666667 20.62760416666667  C 64.39366319444446 20.550347222222214  64.34537760416667 20.444118923611107  64.28743489583333 20.30891927083333  C 64.2294921875 20.173719618055543  64.17154947916667 20.04817708333333  64.11360677083333 19.93229166666667  C 64.0556640625 19.81640625  63.978407118055564 19.710177951388882  63.8818359375 19.61360677083333  C 63.78526475694446 19.517035590277775  63.67903645833333 19.46875  63.56315104166667 19.46875  C 63.447265625 19.46875  63.31206597222222 19.565321180555543  63.15755208333333 19.75846354166667  C 63.00303819444446 19.951605902777775  62.858181423611114 20.144748263888882  62.72298177083333 20.337890625  C 62.587782118055564 20.531032986111107  62.500868055555564 20.62760416666667  62.46223958333333 20.62760416666667  C 62.34635416666667 20.550347222222214  62.23046875 20.521375868055543  62.11458333333333 20.54069010416667  C 61.99869791666667 20.560004340277775  61.91178385416667 20.579318576388882  61.85384114583333 20.5986328125  C 61.7958984375 20.617947048611107  61.708984375 20.675889756944436  61.59309895833333 20.7724609375  C 61.47721354166667 20.869032118055543  61.380642361111114 20.936631944444436  61.30338541666667 20.97526041666667  C 61.1875 21.052517361111107  61.023328993055564 21.110460069444436  60.81087239583333 21.14908854166667  C 60.598415798611114 21.187717013888882  60.43424479166667 21.226345486111107  60.318359375 21.26497395833333  C 60.89778645833333 21.071831597222214  60.87847222222222 20.859375  60.26041666666667 20.62760416666667  C 59.87413194444446 20.473090277777775  59.56510416666667 20.415147569444436  59.33333333333333 20.45377604166667  C 59.68098958333333 20.299262152777775  59.82584635416667 20.067491319444436  59.76790364583333 19.75846354166667  C 59.7099609375 19.449435763888882  59.545789930555564 19.17903645833333  59.275390625 18.947265625  L 59.56510416666667 18.947265625  C 59.52647569444446 18.792751736111107  59.3623046875 18.62858072916667  59.07259114583333 18.45475260416667  C 58.78287760416667 18.28092447916667  58.44487847222222 18.116753472222214  58.05859375 17.96223958333333  C 57.67230902777778 17.807725694444436  57.42122395833333 17.691840277777775  57.30533854166667 17.61458333333333  C 56.99631076388889 17.421440972222214  56.339626736111114 17.23795572916667  55.33528645833333 17.06412760416667  C 54.330946180555564 16.89029947916667  53.69357638888889 16.880642361111107  53.42317708333333 17.03515625  C 53.23003472222222 17.26692708333333  53.14312065972222 17.4697265625  53.16243489583333 17.6435546875  C 53.18174913194446 17.8173828125  53.25900607638889 18.087782118055543  53.39420572916667 18.45475260416667  C 53.52940538194445 18.821723090277775  53.59700520833333 19.06315104166667  53.59700520833333 19.17903645833333  C 53.635633680555564 19.41080729166667  53.52940538194445 19.661892361111107  53.2783203125 19.93229166666667  C 53.027235243055564 20.202690972222214  52.90169270833333 20.434461805555543  52.90169270833333 20.62760416666667  C 52.90169270833333 20.898003472222214  53.17209201388889 21.197374131944436  53.712890625 21.52571614583333  C 54.253689236111114 21.854058159722214  54.44683159722222 22.269314236111107  54.29231770833333 22.771484375  C 54.17643229166667 23.080512152777775  53.86740451388889 23.389539930555543  53.365234375 23.69856770833333  C 52.863064236111114 24.007595486111107  52.55403645833333 24.239366319444436  52.43815104166667 24.39388020833333  C 52.245008680555564 24.702907986111107  52.21603732638889 25.06022135416667  52.35123697916667 25.4658203125  C 52.48643663194445 25.87141927083333  52.689236111111114 26.19010416666667  52.95963541666667 26.421875  C 53.036892361111114 26.499131944444436  53.06586371527778 26.576388888888882  53.04654947916667 26.65364583333333  C 53.027235243055564 26.730902777777775  52.95963541666667 26.817816840277775  52.84375 26.91438802083333  C 52.72786458333334 27.010959201388882  52.62163628472222 27.08821614583333  52.52506510416667 27.14615885416667  C 52.428493923611114 27.2041015625  52.30295138888889 27.271701388888882  52.1484375 27.34895833333333  L 51.974609375 27.46484375  C 51.549696180555564 27.657986111111107  51.15375434027778 27.542100694444436  50.78678385416667 27.1171875  C 50.419813368055564 26.692274305555543  50.159071180555564 26.19010416666667  50.00455729166667 25.61067708333333  C 49.734157986111114 24.644965277777775  49.42513020833333 24.065538194444436  49.07747395833333 23.87239583333333  C 48.18901909722222 23.563368055555543  47.62890625 23.58268229166667  47.39713541666667 23.93033854166667  C 47.203993055555564 23.428168402777775  46.41210937500001 22.925998263888882  45.021484375 22.423828125  C 44.05577256944445 22.076171875  42.935546875 21.998914930555543  41.660807291666664 22.19205729166667  C 41.892578125 22.153428819444436  41.892578125 21.863715277777775  41.660807291666664 21.32291666666667  C 41.390407986111114 20.74348958333333  41.0234375 20.51171875  40.559895833333336 20.62760416666667  C 40.67578125 20.39583333333333  40.75303819444445 20.057834201388882  40.791666666666664 19.61360677083333  C 40.83029513888889 19.169379340277775  40.849609375 18.908637152777775  40.849609375 18.83138020833333  C 40.965494791666664 18.329210069444436  41.197265625 17.884982638888882  41.544921875 17.49869791666667  C 41.58355034722223 17.460069444444436  41.71875 17.2958984375  41.950520833333336 17.00618489583333  C 42.182291666666664 16.71647135416667  42.36577690972223 16.45572916666667  42.5009765625 16.22395833333333  C 42.63617621527778 15.9921875  42.645833333333336 15.87630208333333  42.529947916666664 15.87630208333333  C 43.88194444444445 16.030815972222214  44.84765625 15.818359375  45.42708333333333 15.23893229166667  C 45.62022569444446 15.045789930555543  45.84233940972222 14.71744791666667  46.09342447916667 14.25390625  C 46.344509548611114 13.79036458333333  46.54730902777778 13.462022569444438  46.70182291666667 13.26888020833333  C 47.04947916666667 13.037109375  47.31987847222222 12.930881076388884  47.51302083333333 12.9501953125  C 47.70616319444446 12.969509548611107  47.986219618055564 13.075737847222214  48.35319010416667 13.26888020833333  C 48.72016059027778 13.462022569444438  49.00021701388889 13.55859375  49.193359375 13.55859375  C 49.734157986111114 13.597222222222214  50.03352864583333 13.384765625  50.09147135416667 12.92122395833333  C 50.1494140625 12.45768229166667  50.00455729166667 12.071397569444438  49.65690104166667 11.76236979166667  C 50.12044270833333 11.800998263888884  50.17838541666667 11.47265625  49.83072916666667 10.77734375  C 49.67621527777778 10.506944444444438  49.52170138888889 10.333116319444438  49.3671875 10.255859375  C 48.90364583333334 10.101345486111107  48.38216145833334 10.19791666666667  47.802734375 10.54557291666667  C 47.49370659722222 10.700086805555543  47.53233506944445 10.854600694444438  47.91861979166667 11.00911458333333  C 47.87999131944445 10.970486111111107  47.69650607638889 11.173285590277777  47.3681640625 11.61751302083333  C 47.039822048611114 12.061740451388884  46.72113715277778 12.39973958333333  46.412109375 12.63151041666667  C 46.10308159722222 12.86328125  45.79405381944445 12.766710069444438  45.48502604166667 12.341796875  C 45.44639756944445 12.303168402777777  45.34016927083333 12.042426215277777  45.16634114583333 11.5595703125  C 44.99251302083333 11.076714409722214  44.80902777777778 10.815972222222214  44.61588541666667 10.77734375  C 44.30685763888889 10.77734375  43.997829861111114 11.06705729166667  43.688802083333336 11.646484375  C 43.8046875 11.337456597222214  43.59223090277778 11.047743055555543  43.051432291666664 10.77734375  C 42.51063368055556 10.506944444444438  42.04709201388889 10.352430555555543  41.660807291666664 10.31380208333333  C 42.39474826388889 9.85026041666667  42.240234375 9.32877604166667  41.197265625 8.74934895833333  C 40.92686631944445 8.594835069444438  40.530924479166664 8.498263888888884  40.009440104166664 8.45963541666667  C 39.487955729166664 8.421006944444438  39.111328125 8.498263888888884  38.879557291666664 8.69140625  C 38.68641493055556 8.961805555555543  38.58018663194445 9.18391927083333  38.560872395833336 9.35774739583333  C 38.54155815972223 9.53157552083333  38.63812934027778 9.686089409722214  38.8505859375 9.8212890625  C 39.06304253472223 9.956488715277777  39.26584201388889 10.062717013888884  39.458984375 10.13997395833333  C 39.652126736111114 10.217230902777777  39.87424045138889 10.294487847222214  40.125325520833336 10.37174479166667  C 40.37641059027778 10.449001736111107  40.54058159722223 10.506944444444438  40.617838541666664 10.54557291666667  C 41.15863715277778 10.931857638888884  41.313151041666664 11.202256944444438  41.081380208333336 11.35677083333333  C 41.00412326388889 11.395399305555543  40.83995225694445 11.462999131944438  40.5888671875 11.5595703125  C 40.33778211805556 11.656141493055543  40.11566840277778 11.743055555555543  39.922526041666664 11.8203125  C 39.72938368055556 11.897569444444438  39.61349826388889 11.974826388888884  39.574869791666664 12.05208333333333  C 39.458984375 12.206597222222214  39.458984375 12.476996527777777  39.574869791666664 12.86328125  C 39.690755208333336 13.249565972222214  39.652126736111114 13.519965277777777  39.458984375 13.67447916666667  C 39.26584201388889 13.481336805555543  39.09201388888889 13.143337673611107  38.9375 12.66048177083333  C 38.782986111111114 12.177625868055543  38.647786458333336 11.858940972222214  38.531901041666664 11.70442708333333  C 38.80230034722223 12.05208333333333  38.31944444444445 12.16796875  37.083333333333336 12.05208333333333  L 36.50390625 11.994140625  C 36.349392361111114 11.994140625  36.040364583333336 12.032769097222214  35.576822916666664 12.11002604166667  C 35.11328125 12.187282986111107  34.71733940972223 12.206597222222214  34.388997395833336 12.16796875  C 34.06065538194445 12.129340277777777  33.79991319444445 11.974826388888884  33.606770833333336 11.70442708333333  C 33.45225694444445 11.395399305555543  33.45225694444445 11.00911458333333  33.606770833333336 10.54557291666667  C 33.64539930555556 10.391059027777777  33.72265625 10.352430555555543  33.838541666666664 10.4296875  C 33.68402777777778 10.31380208333333  33.47157118055556 10.130316840277777  33.201171875 9.87923177083333  C 32.93077256944445 9.628146701388884  32.737630208333336 9.463975694444438  32.621744791666664 9.38671875  C 30.844835069444446 9.96614583333333  29.029296875 10.758029513888884  27.175130208333336 11.76236979166667  C 27.406901041666664 11.800998263888884  27.638671875 11.781684027777777  27.870442708333336 11.70442708333333  C 28.063585069444446 11.627170138888884  28.314670138888893 11.50162760416667  28.623697916666664 11.32779947916667  C 28.932725694444446 11.15397135416667  29.125868055555557 11.047743055555543  29.203125 11.00911458333333  C 30.516493055555557 10.468315972222214  31.32769097222223 10.333116319444438  31.63671875 10.603515625  L 31.926432291666664 10.31380208333333  C 32.46723090277778 10.931857638888884  32.853515625 11.41471354166667  33.085286458333336 11.76236979166667  C 32.81488715277778 11.607855902777777  32.23546006944445 11.58854166666667  31.347005208333336 11.70442708333333  C 30.574435763888893 11.93619791666667  30.149522569444446 12.16796875  30.072265625 12.39973958333333  C 30.342664930555557 12.86328125  30.43923611111111 13.2109375  30.361979166666664 13.44270833333333  C 30.207465277777782 13.32682291666667  29.9853515625 13.133680555555543  29.695638020833336 12.86328125  C 29.405924479166664 12.592881944444438  29.125868055555557 12.380425347222214  28.85546875 12.22591145833333  C 28.585069444444446 12.071397569444438  28.295355902777782 11.974826388888884  27.986328125 11.93619791666667  C 27.368272569444446 11.93619791666667  26.943359375 11.955512152777777  26.711588541666664 11.994140625  C 21.071831597222225 15.084418402777777  16.532986111111114 19.372178819444436  13.095052083333332 24.857421875  C 13.365451388888891 25.127821180555543  13.597222222222223 25.282335069444436  13.790364583333332 25.32096354166667  C 13.944878472222223 25.359592013888882  14.041449652777779 25.533420138888882  14.080078125 25.84244791666667  C 14.118706597222223 26.151475694444436  14.1669921875 26.36393229166667  14.224934895833332 26.47981770833333  C 14.282877604166668 26.595703125  14.504991319444445 26.53776041666667  14.891276041666668 26.30598958333333  C 15.238932291666668 26.615017361111107  15.296875 26.981987847222214  15.065104166666668 27.40690104166667  C 15.103732638888891 27.368272569444436  15.953559027777779 27.889756944444436  17.614583333333332 28.97135416666667  C 18.348524305555557 29.628038194444436  18.75412326388889 30.033637152777775  18.831380208333332 30.18815104166667  C 18.947265625 30.613064236111107  18.75412326388889 30.960720486111107  18.251953125 31.23111979166667  C 18.21332465277778 31.153862847222225  18.03949652777778 30.980034722222225  17.73046875 30.70963541666667  C 17.421440972222225 30.439236111111107  17.247612847222225 30.36197916666666  17.208984375 30.47786458333333  C 17.093098958333332 30.671006944444436  17.10275607638889 31.0283203125  17.237955729166668 31.5498046875  C 17.373155381944446 32.0712890625  17.575954861111114 32.312717013888886  17.846354166666668 32.27408854166667  C 17.575954861111114 32.27408854166667  17.392469618055557 32.583116319444436  17.2958984375 33.201171875  C 17.199327256944446 33.81922743055554  17.151041666666668 34.50488281249999  17.151041666666668 35.25813802083333  C 17.151041666666668 36.01139322916666  17.131727430555557 36.46527777777778  17.093098958333332 36.61979166666667  L 17.208984375 36.677734375  C 17.093098958333332 37.14127604166667  17.199327256944446 37.8076171875  17.527669270833332 38.6767578125  C 17.856011284722225 39.5458984375  18.271267361111114 39.92252604166667  18.7734375 39.806640625  C 18.271267361111114 39.92252604166667  18.657552083333332 40.753038194444436  19.932291666666668 42.29817708333333  C 20.1640625 42.60720486111111  20.31857638888889 42.78103298611111  20.395833333333332 42.81966145833333  C 20.51171875 42.89691840277778  20.743489583333332 43.04177517361111  21.091145833333332 43.25423177083333  C 21.438802083333332 43.46668836805555  21.728515625 43.65983072916667  21.960286458333332 43.83365885416667  C 22.192057291666668 44.00748697916667  22.385199652777782 44.21028645833333  22.539713541666664 44.44205729166667  C 22.694227430555557 44.635199652777764  22.88736979166667 45.069769965277764  23.119140625 45.74576822916666  C 23.350911458333336 46.42176649305555  23.621310763888893 46.87565104166666  23.930338541666664 47.107421875  C 23.85308159722223 47.33919270833334  24.036566840277782 47.72547743055555  24.480794270833336 48.26627604166666  C 24.92502170138889 48.807074652777764  25.127821180555557 49.25130208333334  25.089192708333336 49.59895833333334  C 25.05056423611111 49.59895833333334  25.002278645833336 49.61827256944445  24.9443359375 49.65690104166666  C 24.88639322916667 49.69552951388889  24.838107638888893 49.71484375  24.799479166666664 49.71484375  C 24.915364583333336 49.98524305555555  25.214735243055557 50.25564236111111  25.697591145833336 50.52604166666666  C 26.18044704861111 50.796440972222214  26.479817708333336 51.04752604166666  26.595703125 51.279296875  C 26.634331597222225 51.39518229166666  26.672960069444446 51.588324652777764  26.711588541666664 51.85872395833334  C 26.750217013888893 52.12912326388889  26.80815972222223 52.34157986111111  26.885416666666664 52.49609375  C 26.96267361111111 52.65060763888889  27.1171875 52.68923611111111  27.348958333333336 52.61197916666666  C 27.426215277777782 51.839409722222214  26.96267361111111 50.64192708333334  25.958333333333336 49.01953125  C 25.37890625 48.05381944444445  25.05056423611111 47.493706597222214  24.973307291666664 47.33919270833334  C 24.857421875 47.146050347222214  24.75119357638889 46.8466796875  24.654622395833336 46.44108072916666  C 24.558051215277782 46.03548177083334  24.471137152777782 45.755425347222214  24.393880208333336 45.60091145833334  C 24.471137152777782 45.60091145833334  24.587022569444446 45.6298828125  24.741536458333336 45.68782552083334  C 24.896050347222225 45.74576822916666  25.060221354166664 45.81336805555555  25.234049479166664 45.890625  C 25.407877604166664 45.96788194444445  25.552734375 46.04513888888889  25.668619791666664 46.12239583333334  C 25.784505208333336 46.199652777777764  25.823133680555557 46.25759548611111  25.784505208333336 46.29622395833334  C 25.668619791666664 46.56662326388889  25.70724826388889 46.90462239583334  25.900390625 47.31022135416666  C 26.09353298611111 47.7158203125  26.325303819444446 48.07313368055555  26.595703125 48.38216145833334  C 26.866102430555557 48.69118923611111  27.194444444444446 49.058159722222214  27.580729166666664 49.48307291666666  C 27.967013888888893 49.90798611111111  28.19878472222223 50.15907118055555  28.276041666666664 50.236328125  C 28.5078125 50.46809895833334  28.778211805555557 50.8447265625  29.087239583333336 51.3662109375  C 29.39626736111111 51.8876953125  29.39626736111111 52.1484375  29.087239583333336 52.1484375  C 29.434895833333336 52.1484375  29.821180555555557 52.35123697916666  30.24609375 52.7568359375  C 30.671006944444446 53.16243489583334  30.999348958333336 53.5390625  31.231119791666664 53.88671875  C 31.424262152777782 54.195746527777764  31.578776041666664 54.69791666666666  31.694661458333336 55.39322916666666  C 31.810546875 56.08854166666666  31.907118055555557 56.55208333333334  31.984375 56.78385416666666  C 32.06163194444445 57.054253472222214  32.22580295138889 57.314995659722214  32.476888020833336 57.56608072916666  C 32.72797309027778 57.81716579861111  32.969401041666664 58.00065104166666  33.201171875 58.11653645833334  L 34.128255208333336 58.580078125  C 34.128255208333336 58.580078125  34.37934027777778 58.715277777777764  34.881510416666664 58.98567708333334  C 35.07465277777778 59.062934027777764  35.431966145833336 59.26573350694445  35.953450520833336 59.59407552083334  C 36.474934895833336 59.922417534722214  36.89019097222223 60.14453125  37.19921875 60.26041666666666  C 37.58550347222223 60.41493055555555  37.89453125 60.4921875  38.126302083333336 60.4921875  C 38.358072916666664 60.4921875  38.63812934027778 60.443901909722214  38.966471354166664 60.34733072916666  C 39.29481336805556 60.25075954861111  39.55555555555556 60.183159722222214  39.748697916666664 60.14453125  C 40.328125 60.06727430555555  40.88823784722223 60.356987847222214  41.429036458333336 61.013671875  C 41.96983506944445 61.670355902777764  42.37543402777778 62.07595486111111  42.645833333333336 62.23046875  C 44.036458333333336 62.964409722222214  45.09874131944445 63.17686631944445  45.83268229166667 62.86783854166666  C 45.75542534722222 62.90646701388887  45.765082465277786 63.051323784722214  45.86165364583333 63.30240885416666  C 45.95822482638889 63.55349392361111  46.11273871527778 63.85286458333334  46.3251953125 64.20052083333334  C 46.53765190972222 64.54817708333334  46.71148003472222 64.82823350694444  46.8466796875 65.04069010416666  C 46.98187934027778 65.25314670138887  47.08810763888889 65.41731770833334  47.16536458333333 65.533203125  C 47.35850694444446 65.76497395833334  47.70616319444446 66.0546875  48.20833333333333 66.40234375  C 48.71050347222222 66.75  49.05815972222222 67.03971354166667  49.25130208333333 67.271484375  C 49.48307291666667 67.1169704861111  49.61827256944445 66.9431423611111  49.65690104166667 66.75  C 49.541015625 67.05902777777777  49.67621527777778 67.4453125  50.0625 67.90885416666667  C 50.44878472222222 68.37239583333333  50.79644097222222 68.56553819444444  51.10546875 68.48828125  C 51.646267361111114 68.37239583333333  51.91666666666667 67.75434027777777  51.91666666666667 66.63411458333334  C 50.71918402777778 67.21354166666667  49.77278645833333 66.86588541666667  49.07747395833333 65.59114583333334  C 49.07747395833333 65.5525173611111  49.029188368055564 65.4462890625  48.9326171875 65.2724609375  C 48.83604600694445 65.0986328125  48.7587890625 64.93446180555556  48.70084635416667 64.77994791666666  C 48.64290364583333 64.62543402777777  48.594618055555564 64.46126302083334  48.55598958333333 64.28743489583334  C 48.517361111111114 64.11360677083334  48.517361111111114 63.96875  48.55598958333333 63.85286458333334  C 48.594618055555564 63.73697916666666  48.691189236111114 63.67903645833334  48.845703125 63.67903645833334  C 49.19335937500001 63.67903645833334  49.386501736111114 63.61143663194445  49.42513020833333 63.47623697916666  C 49.463758680555564 63.34103732638887  49.42513020833333 63.099609375  49.30924479166667 62.751953125  C 49.193359375 62.404296875  49.116102430555564 62.15321180555555  49.07747395833333 61.99869791666666  C 49.038845486111114 61.68967013888887  48.82638888888889 61.30338541666666  48.44010416666667 60.83984375  C 48.05381944444445 60.37630208333334  47.822048611111114 60.08658854166666  47.74479166666667 59.970703125  C 47.551649305555564 60.318359375  47.242621527777786 60.47287326388887  46.81770833333333 60.43424479166666  C 46.39279513888889 60.39561631944445  46.083767361111114 60.22178819444445  45.890625 59.91276041666666  C 45.89062500000001 59.95138888888887  45.86165364583334 60.0576171875  45.8037109375 60.2314453125  C 45.74576822916667 60.4052734375  45.71679687500001 60.530815972222214  45.716796875 60.60807291666666  C 45.214626736111114 60.60807291666666  44.92491319444445 60.58875868055555  44.84765625 60.55013020833334  C 44.88628472222222 60.43424479166666  44.9345703125 60.096245659722214  44.99251302083333 59.5361328125  C 45.05045572916667 58.976019965277764  45.118055555555564 58.541449652777764  45.1953125 58.232421875  C 45.23394097222222 58.07790798611111  45.34016927083333 57.846137152777764  45.51399739583333 57.537109375  C 45.68782552083333 57.228081597222214  45.83268229166667 56.94802517361111  45.94856770833333 56.69694010416666  C 46.064453125 56.445855034722214  46.14171006944445 56.20442708333334  46.18033854166667 55.97265625  C 46.21896701388889 55.74088541666666  46.13205295138889 55.55740017361111  45.91959635416667 55.42220052083334  C 45.70713975694445 55.28700086805555  45.369140625 55.238715277777764  44.90559895833333 55.27734375  C 44.171657986111114 55.315972222222214  43.66948784722223 55.70225694444445  43.399088541666664 56.43619791666666  C 43.36046006944445 56.55208333333334  43.302517361111114 56.7548828125  43.225260416666664 57.04459635416666  C 43.14800347222223 57.33430989583334  43.051432291666664 57.55642361111111  42.935546875 57.7109375  C 42.819661458333336 57.86545138888887  42.645833333333336 58.00065104166666  42.4140625 58.11653645833334  C 42.14366319444445 58.232421875  41.68012152777778 58.271050347222214  41.0234375 58.232421875  C 40.36675347222223 58.193793402777764  39.90321180555556 58.097222222222214  39.6328125 57.94270833333334  C 39.130642361111114 57.63368055555555  38.696072048611114 57.07356770833334  38.3291015625 56.26236979166666  C 37.96213107638889 55.451171875  37.778645833333336 54.73654513888887  37.778645833333336 54.11848958333334  C 37.778645833333336 53.73220486111111  37.826931423611114 53.22037760416666  37.923502604166664 52.5830078125  C 38.02007378472223 51.94563802083334  38.07801649305556 51.46278211805555  38.097330729166664 51.13444010416666  C 38.11664496527778 50.806098090277764  38.010416666666664 50.33289930555555  37.778645833333336 49.71484375  C 37.89453125 49.63758680555555  38.068359375 49.4541015625  38.300130208333336 49.16438802083334  C 38.531901041666664 48.87467447916666  38.72504340277778 48.671875  38.879557291666664 48.55598958333334  C 38.956814236111114 48.51736111111111  39.043728298611114 48.48838975694445  39.140299479166664 48.46907552083334  C 39.23687065972223 48.449761284722214  39.32378472222223 48.449761284722214  39.401041666666664 48.46907552083334  C 39.478298611111114 48.48838975694445  39.55555555555556 48.459418402777764  39.6328125 48.38216145833334  C 39.71006944444445 48.30490451388889  39.76801215277778 48.189019097222214  39.806640625 48.03450520833334  C 39.76801215277778 47.99587673611111  39.690755208333336 47.937934027777764  39.574869791666664 47.86067708333334  C 39.458984375 47.74479166666666  39.38172743055556 47.68684895833334  39.343098958333336 47.68684895833334  C 39.61349826388889 47.802734375  40.16395399305556 47.77376302083334  40.994466145833336 47.59993489583334  C 41.824978298611114 47.42610677083334  42.356119791666664 47.455078125  42.587890625 47.68684895833334  C 43.167317708333336 48.111762152777764  43.59223090277778 48.07313368055555  43.862630208333336 47.57096354166666  C 43.862630208333336 47.53233506944445  43.81434461805556 47.34884982638889  43.7177734375 47.0205078125  C 43.62120225694445 46.69216579861111  43.61154513888889 46.43142361111111  43.688802083333336 46.23828125  C 43.88194444444445 47.28125  44.442057291666664 47.455078125  45.369140625 46.759765625  C 45.48502604166667 46.87565104166666  45.78439670138889 46.972222222222214  46.26725260416667 47.04947916666666  C 46.75010850694445 47.12673611111111  47.08810763888889 47.22330729166666  47.28125 47.33919270833334  C 47.39713541666667 47.416449652777764  47.53233506944446 47.52267795138889  47.68684895833333 47.65787760416666  C 47.84136284722222 47.79307725694445  47.94759114583333 47.87999131944445  48.00553385416667 47.91861979166666  C 48.0634765625 47.95724826388889  48.160047743055564 47.94759114583334  48.29524739583333 47.8896484375  C 48.430447048611114 47.83170572916666  48.594618055555564 47.70616319444445  48.78776041666667 47.51302083333334  C 49.17404513888889 48.05381944444445  49.40581597222222 48.51736111111111  49.48307291666667 48.90364583333334  C 49.907986111111114 50.448784722222214  50.27495659722222 51.29861111111111  50.583984375 51.453125  C 50.854383680555564 51.56901041666666  51.06684027777778 51.60763888888889  51.22135416666667 51.56901041666666  C 51.375868055555564 51.53038194444445  51.462782118055564 51.34689670138889  51.48209635416667 51.0185546875  C 51.50141059027778 50.69021267361111  51.50141059027778 50.41981336805555  51.48209635416667 50.20735677083334  C 51.462782118055564 49.99490017361111  51.43381076388889 49.753472222222214  51.39518229166667 49.48307291666666  L 51.33723958333333 49.01953125  L 51.33723958333333 47.9765625  L 51.279296875 47.51302083333334  C 50.69986979166667 47.39713541666666  50.342556423611114 47.16536458333334  50.20735677083333 46.81770833333334  C 50.072157118055564 46.47005208333334  50.10112847222222 46.112738715277764  50.29427083333333 45.74576822916666  C 50.48741319444446 45.37879774305555  50.777126736111114 45.021484375  51.16341145833333 44.673828125  C 51.202039930555564 44.635199652777764  51.35655381944445 44.56759982638889  51.626953125 44.47102864583333  C 51.897352430555564 44.37445746527778  52.19672309027778 44.24891493055555  52.52506510416667 44.09440104166667  C 52.853407118055564 43.93988715277778  53.09483506944446 43.785373263888886  53.24934895833333 43.630859375  C 54.060546875 42.89691840277778  54.35026041666667 42.220920138888886  54.11848958333333 41.60286458333333  C 54.38888888888889 41.60286458333333  54.601345486111114 41.42903645833333  54.755859375 41.08138020833333  C 54.71723090277778 41.08138020833333  54.62065972222222 41.0234375  54.46614583333333 40.90755208333333  C 54.31163194444446 40.79166666666667  54.166775173611114 40.69509548611111  54.03157552083333 40.61783854166667  C 53.896375868055564 40.54058159722222  53.809461805555564 40.501953125  53.77083333333333 40.501953125  C 54.11848958333333 40.308810763888886  54.157118055555564 39.99978298611111  53.88671875 39.57486979166667  C 54.079861111111114 39.458984375  54.22471788194445 39.24652777777778  54.3212890625 38.9375  C 54.417860243055564 38.62847222222222  54.56271701388889 38.43532986111111  54.755859375 38.35807291666667  C 55.10351562500001 38.82161458333333  55.50911458333334 38.86024305555555  55.97265625 38.47395833333333  C 56.28168402777778 38.16493055555555  56.30099826388889 37.85590277777778  56.03059895833333 37.546875  C 56.22374131944446 37.276475694444436  56.61968315972222 37.07367621527778  57.21842447916667 36.9384765625  C 57.817165798611114 36.803276909722214  58.17447916666667 36.61979166666666  58.29036458333333 36.38802083333333  C 58.56076388888889 36.46527777777778  58.71527777777778 36.42664930555555  58.75390625 36.27213541666667  C 58.79253472222222 36.11762152777778  58.81184895833333 35.885850694444436  58.81184895833333 35.57682291666667  C 58.81184895833333 35.267795138888886  58.86979166666667 35.03602430555555  58.98567708333333 34.88151041666667  C 59.14019097222222 34.68836805555555  59.42990451388889 34.51453993055555  59.85481770833333 34.36002604166667  C 60.279730902777786 34.20551215277778  60.53081597222222 34.108940972222214  60.60807291666667 34.0703125  L 61.59309895833333 33.43294270833333  C 61.708984375 33.278428819444436  61.708984375 33.201171875  61.59309895833333 33.201171875  C 62.28841145833333 33.278428819444436  62.887152777777786 33.06597222222222  63.38932291666667 32.56380208333333  C 63.77560763888889 32.138888888888886  63.65972222222222 31.75260416666667  63.04166666666667 31.40494791666667  C 63.15755208333333 31.17317708333333  63.099609375 30.989691840277775  62.86783854166667 30.8544921875  C 62.63606770833333 30.719292534722214  62.34635416666667 30.613064236111107  61.99869791666667 30.53580729166667  C 62.11458333333333 30.497178819444436  62.336697048611114 30.487521701388882  62.6650390625 30.5068359375  C 62.99338107638889 30.526150173611107  63.196180555555564 30.497178819444436  63.2734375 30.419921875  C 63.85286458333333 30.033637152777775  63.717664930555564 29.724609375  62.86783854166667 29.49283854166667  Z M 50.81575520833333 80.07682291666667  C 50.81575520833333 80.30859375  50.854383680555564 80.61762152777777  50.931640625 81.00390625  C 58.88910590277778 79.61328125  65.66840277777779 75.962890625  71.26953125 70.052734375  C 71.15364583333333 69.93684895833333  70.91221788194446 69.84993489583333  70.54524739583333 69.7919921875  C 70.17827690972223 69.73404947916667  69.93684895833333 69.66644965277777  69.82096354166667 69.58919270833333  C 69.12565104166667 69.31879340277777  68.662109375 69.1642795138889  68.43033854166667 69.12565104166667  C 68.4689670138889 68.8552517361111  68.42068142361111 68.60416666666667  68.28548177083333 68.37239583333333  C 68.15028211805556 68.140625  67.99576822916667 67.966796875  67.82194010416667 67.85091145833333  C 67.64811197916667 67.73502604166667  67.40668402777779 67.58051215277777  67.09765625 67.38736979166667  C 66.78862847222223 67.19422743055556  66.576171875 67.05902777777777  66.46028645833333 66.98177083333333  C 66.3830295138889 66.9045138888889  66.24782986111111 66.78862847222223  66.0546875 66.63411458333334  C 65.8615451388889 66.47960069444444  65.72634548611111 66.37337239583334  65.64908854166667 66.3154296875  C 65.57183159722223 66.25748697916666  65.4269748263889 66.17057291666666  65.21451822916667 66.0546875  C 65.00206163194446 65.93880208333334  64.837890625 65.9001736111111  64.72200520833333 65.93880208333334  C 64.60611979166667 65.97743055555556  64.41297743055556 65.99674479166666  64.142578125 65.99674479166666  L 63.96875 66.0546875  C 63.85286458333333 66.09331597222221  63.74663628472222 66.1416015625  63.65006510416667 66.19954427083334  C 63.553493923611114 66.25748697916666  63.447265625 66.3154296875  63.33138020833333 66.37337239583334  C 63.21549479166667 66.43131510416666  63.13823784722222 66.4892578125  63.099609375 66.54720052083334  C 63.060980902777786 66.60514322916666  63.060980902777786 66.65342881944444  63.099609375 66.69205729166666  C 62.28841145833333 66.03537326388887  61.59309895833333 65.61046006944444  61.013671875 65.41731770833334  C 60.82052951388889 65.3786892361111  60.60807291666667 65.2724609375  60.37630208333333 65.0986328125  C 60.14453125 64.9248046875  59.94173177083333 64.78960503472221  59.76790364583333 64.69303385416666  C 59.59407552083333 64.5964626736111  59.40093315972222 64.56749131944444  59.1884765625 64.60611979166666  C 58.97601996527778 64.64474826388887  58.75390625 64.77994791666666  58.52213541666667 65.01171875  C 58.328993055555564 65.2048611111111  58.21310763888889 65.49457465277777  58.17447916666667 65.880859375  C 58.13585069444445 66.26714409722221  58.09722222222222 66.51822916666666  58.05859375 66.63411458333334  C 57.78819444444445 66.44097222222221  57.78819444444445 66.10297309027777  58.05859375 65.6201171875  C 58.328993055555564 65.13726128472221  58.36762152777778 64.77994791666666  58.17447916666667 64.54817708333334  C 58.05859375 64.31640625  57.85579427083333 64.2294921875  57.56608072916667 64.28743489583334  C 57.2763671875 64.34537760416666  57.04459635416667 64.43229166666666  56.87076822916667 64.54817708333334  C 56.69694010416667 64.6640625  56.47482638888889 64.82823350694444  56.20442708333333 65.04069010416666  C 55.934027777777786 65.25314670138887  55.760199652777786 65.3786892361111  55.68294270833333 65.41731770833334  C 55.60568576388889 65.45594618055556  55.44151475694445 65.56217447916666  55.1904296875 65.73600260416666  C 54.939344618055564 65.90983072916666  54.775173611111114 66.0546875  54.69791666666667 66.17057291666666  C 54.58203125 66.32508680555556  54.46614583333333 66.55685763888887  54.35026041666667 66.86588541666667  C 54.234375 67.17491319444444  54.13780381944445 67.38736979166667  54.060546875 67.50325520833333  C 53.983289930555564 67.34874131944444  53.76117621527778 67.22319878472223  53.39420572916667 67.12662760416667  C 53.027235243055564 67.0300564236111  52.84375000000001 66.923828125  52.84375 66.80794270833333  C 52.92100694444445 67.19422743055556  52.99826388888889 67.87022569444444  53.07552083333333 68.8359375  C 53.152777777777786 69.80164930555554  53.24934895833334 70.53559027777777  53.365234375 71.03776041666667  C 53.635633680555564 72.23524305555556  53.40386284722222 73.1623263888889  52.669921875 73.81901041666667  C 51.62695312500001 74.78472222222223  51.066840277777786 75.55729166666667  50.98958333333333 76.13671875  C 50.83506944444446 76.9865451388889  51.066840277777786 77.48871527777777  51.68489583333333 77.64322916666667  C 51.68489583333333 77.91362847222223  51.53038194444445 78.3095703125  51.22135416666667 78.8310546875  C 50.91232638888889 79.3525390625  50.777126736111114 79.7677951388889  50.81575520833333 80.07682291666667  Z " fill-rule="nonzero" fill="#1abc9c" stroke="none" transform="matrix(1 0 0 1 141 51 )" />
+  </g>
+</svg>
\ No newline at end of file
diff --git a/images/fa_repeat.svg b/images/fa_repeat.svg
new file mode 100644
index 0000000..c2971d8
--- /dev/null
+++ b/images/fa_repeat.svg
@@ -0,0 +1,3 @@
+<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M18 31C14.8367 31 12.0746 30.0146 9.7138 28.0438C7.99949 26.6127 6.74721 24.9124 5.95694 22.943C5.48596 21.7692 6.44293 20.6 7.70766 20.6H7.79544C8.68175 20.6 9.44102 21.1949 9.82227 21.995C10.4355 23.282 11.331 24.377 12.5088 25.28C14.0913 26.4933 15.9217 27.1 18 27.1C20.5133 27.1 22.6583 26.2117 24.435 24.435C26.2117 22.6583 27.1 20.5133 27.1 18C27.1 15.4867 26.2117 13.3417 24.435 11.565C22.6583 9.78833 20.5133 8.9 18 8.9C16.7433 8.9 15.5733 9.12707 14.49 9.5812C13.4067 10.0353 12.4533 10.6749 11.63 11.5H13.45C14.527 11.5 15.4 12.373 15.4 13.45C15.4 14.527 14.527 15.4 13.45 15.4H7C5.89543 15.4 5 14.5046 5 13.4V6.95C5 5.87305 5.87304 5 6.95 5C8.02696 5 8.9 5.87305 8.9 6.95V8.705C10.07 7.57833 11.435 6.6796 12.995 6.0088C14.555 5.338 16.2233 5.00173 18 5C21.5967 5 24.6629 6.26793 27.1988 8.8038C29.7347 11.3397 31.0017 14.4051 31 18C30.9983 21.5949 29.7303 24.6612 27.1962 27.1988C24.6621 29.7364 21.5967 31.0035 18 31Z" fill="#1890FF"/>
+</svg>
diff --git a/images/grommet-icons_map.svg b/images/grommet-icons_map.svg
new file mode 100644
index 0000000..fe85402
--- /dev/null
+++ b/images/grommet-icons_map.svg
@@ -0,0 +1,3 @@
+<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M22.5 22.5H28.5L33 33H3L7.5 22.5H13.5M19.5 12C19.5 12.3978 19.342 12.7794 19.0607 13.0607C18.7794 13.342 18.3978 13.5 18 13.5C17.6022 13.5 17.2206 13.342 16.9393 13.0607C16.658 12.7794 16.5 12.3978 16.5 12C16.5 11.6022 16.658 11.2206 16.9393 10.9393C17.2206 10.658 17.6022 10.5 18 10.5C18.3978 10.5 18.7794 10.658 19.0607 10.9393C19.342 11.2206 19.5 11.6022 19.5 12ZM9 12C9 19.5 18 27 18 27C18 27 27 19.5 27 12C27 6.8745 22.971 3 18 3C13.029 3 9 6.8745 9 12Z" stroke="#1890FF" stroke-width="3" stroke-linejoin="round"/>
+</svg>
diff --git a/images/icon-park-outline_attention.svg b/images/icon-park-outline_attention.svg
new file mode 100644
index 0000000..60d0368
--- /dev/null
+++ b/images/icon-park-outline_attention.svg
@@ -0,0 +1,8 @@
+<svg width="128" height="128" viewBox="0 0 128 128" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M63.9999 117.333C71.005 117.341 77.9427 115.966 84.4146 113.285C90.8864 110.604 96.7648 106.671 101.712 101.711C106.671 96.7643 110.605 90.8859 113.285 84.4141C115.966 77.9422 117.342 71.0045 117.333 63.9994C117.342 56.9943 115.966 50.0565 113.285 43.5847C110.605 37.1129 106.671 31.2345 101.712 26.2874C96.7648 21.3278 90.8864 17.3946 84.4146 14.7138C77.9427 12.033 71.005 10.6574 63.9999 10.6661C56.9948 10.6574 50.057 12.033 43.5852 14.7138C37.1134 17.3946 31.235 21.3278 26.2879 26.2874C21.3283 31.2345 17.3951 37.1129 14.7143 43.5847C12.0335 50.0565 10.6579 56.9943 10.6665 63.9994C10.6579 71.0045 12.0335 77.9422 14.7143 84.4141C17.3951 90.8859 21.3283 96.7643 26.2879 101.711C31.235 106.671 37.1134 110.604 43.5852 113.285C50.057 115.966 56.9948 117.341 63.9999 117.333Z" stroke="#7F7F7F" stroke-opacity="0.5" stroke-width="10.6667" stroke-linejoin="round" style="mix-blend-mode:luminosity"/>
+<path d="M63.9999 117.333C71.005 117.341 77.9427 115.966 84.4146 113.285C90.8864 110.604 96.7648 106.671 101.712 101.711C106.671 96.7643 110.605 90.8859 113.285 84.4141C115.966 77.9422 117.342 71.0045 117.333 63.9994C117.342 56.9943 115.966 50.0565 113.285 43.5847C110.605 37.1129 106.671 31.2345 101.712 26.2874C96.7648 21.3278 90.8864 17.3946 84.4146 14.7138C77.9427 12.033 71.005 10.6574 63.9999 10.6661C56.9948 10.6574 50.057 12.033 43.5852 14.7138C37.1134 17.3946 31.235 21.3278 26.2879 26.2874C21.3283 31.2345 17.3951 37.1129 14.7143 43.5847C12.0335 50.0565 10.6579 56.9943 10.6665 63.9994C10.6579 71.0045 12.0335 77.9422 14.7143 84.4141C17.3951 90.8859 21.3283 96.7643 26.2879 101.711C31.235 106.671 37.1134 110.604 43.5852 113.285C50.057 115.966 56.9948 117.341 63.9999 117.333Z" stroke="#3D3D3D" stroke-width="10.6667" stroke-linejoin="round" style="mix-blend-mode:overlay"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M64.0002 98.6654C65.7683 98.6654 67.464 97.963 68.7142 96.7127C69.9644 95.4625 70.6668 93.7668 70.6668 91.9987C70.6668 90.2306 69.9644 88.5349 68.7142 87.2846C67.464 86.0344 65.7683 85.332 64.0002 85.332C62.2321 85.332 60.5364 86.0344 59.2861 87.2846C58.0359 88.5349 57.3335 90.2306 57.3335 91.9987C57.3335 93.7668 58.0359 95.4625 59.2861 96.7127C60.5364 97.963 62.2321 98.6654 64.0002 98.6654Z" fill="#7F7F7F" fill-opacity="0.5" style="mix-blend-mode:luminosity"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M64.0002 98.6654C65.7683 98.6654 67.464 97.963 68.7142 96.7127C69.9644 95.4625 70.6668 93.7668 70.6668 91.9987C70.6668 90.2306 69.9644 88.5349 68.7142 87.2846C67.464 86.0344 65.7683 85.332 64.0002 85.332C62.2321 85.332 60.5364 86.0344 59.2861 87.2846C58.0359 88.5349 57.3335 90.2306 57.3335 91.9987C57.3335 93.7668 58.0359 95.4625 59.2861 96.7127C60.5364 97.963 62.2321 98.6654 64.0002 98.6654Z" fill="#3D3D3D" style="mix-blend-mode:overlay"/>
+<path d="M64 32V74.6667" stroke="#7F7F7F" stroke-opacity="0.5" stroke-width="10.6667" stroke-linecap="round" stroke-linejoin="round" style="mix-blend-mode:luminosity"/>
+<path d="M64 32V74.6667" stroke="#3D3D3D" stroke-width="10.6667" stroke-linecap="round" stroke-linejoin="round" style="mix-blend-mode:overlay"/>
+</svg>
diff --git a/images/icon-park-outline_point.svg b/images/icon-park-outline_point.svg
new file mode 100644
index 0000000..17fcb91
--- /dev/null
+++ b/images/icon-park-outline_point.svg
@@ -0,0 +1,3 @@
+<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M14.2498 30.75C10.1248 28.6875 6.00055 22.5 3.7498 18.75C1.49905 15 6.23455 11.4847 8.9998 14.25L11.9998 17.25V5.625C11.9998 4.92881 12.2764 4.26113 12.7686 3.76884C13.2609 3.27656 13.9286 3 14.6248 3C15.321 3 15.9887 3.27656 16.481 3.76884C16.9732 4.26113 17.2498 4.92881 17.2498 5.625V12C17.2498 11.3038 17.5264 10.6361 18.0186 10.1438C18.5109 9.65156 19.1786 9.375 19.8748 9.375C20.571 9.375 21.2387 9.65156 21.731 10.1438C22.2232 10.6361 22.4998 11.3038 22.4998 12V13.125C22.4996 12.4288 22.776 11.761 23.2681 11.2686C23.7603 10.7762 24.4279 10.4994 25.1241 10.4992C25.8202 10.4991 26.488 10.7754 26.9804 11.2676C27.4729 11.7597 27.7496 12.4273 27.7498 13.1235V16.875C27.7498 16.1788 28.0264 15.5111 28.5186 15.0188C29.0109 14.5266 29.6786 14.25 30.3748 14.25C31.071 14.25 31.7387 14.5266 32.231 15.0188C32.7232 15.5111 32.9998 16.1788 32.9998 16.875V23.433C32.9998 24.2992 32.8033 25.158 32.3151 25.8735C31.4376 27.159 29.7013 29.2762 26.9998 30.75C22.8748 33 18.3748 32.8125 14.2498 30.75Z" stroke="#1890FF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>
diff --git a/images/image 11.png b/images/image 11.png
new file mode 100644
index 0000000..697cbd9
--- /dev/null
+++ b/images/image 11.png
Binary files differ
diff --git a/images/image 15.png b/images/image 15.png
new file mode 100644
index 0000000..affe510
--- /dev/null
+++ b/images/image 15.png
Binary files differ
diff --git a/images/image 23.png b/images/image 23.png
new file mode 100644
index 0000000..32bf0bc
--- /dev/null
+++ b/images/image 23.png
Binary files differ
diff --git a/images/image 25.png b/images/image 25.png
new file mode 100644
index 0000000..2067fab
--- /dev/null
+++ b/images/image 25.png
Binary files differ
diff --git a/images/line-md_confirm-circle-filled.svg b/images/line-md_confirm-circle-filled.svg
new file mode 100644
index 0000000..890edf5
--- /dev/null
+++ b/images/line-md_confirm-circle-filled.svg
@@ -0,0 +1,9 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<mask id="mask0_647_20217" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="2" y="2" width="20" height="20">
+<path d="M3 12C3 7.03 7.03 3 12 3C16.97 3 21 7.03 21 12C21 16.97 16.97 21 12 21C7.03 21 3 16.97 3 12Z" fill="white" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M8 12L11 15L16 10" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+</mask>
+<g mask="url(#mask0_647_20217)">
+<path d="M24 0H0V24H24V0Z" fill="#52C41A"/>
+</g>
+</svg>
diff --git a/images/line-md_play-filled.svg b/images/line-md_play-filled.svg
new file mode 100644
index 0000000..0ac0f63
--- /dev/null
+++ b/images/line-md_play-filled.svg
@@ -0,0 +1,4 @@
+<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M11 7L29 18L11 29V7Z" fill="#1890FF"/>
+<path d="M10.5963 6.15577C10.9651 5.94276 11.4185 5.94857 11.7819 6.171L29.429 16.9711C29.7833 17.188 30 17.5785 30 18C30 18.4215 29.7833 18.812 29.429 19.0289L11.7819 29.829C11.4185 30.0514 10.9651 30.0572 10.5963 29.8442C10.2277 29.6312 10 29.2322 10 28.8001V7.19992L10.0103 7.03937C10.0591 6.67075 10.2739 6.34215 10.5963 6.15577ZM12.3529 26.6801L26.5361 18L12.3529 9.31868V26.6801Z" fill="#1890FF"/>
+</svg>
diff --git a/images/lock.svg b/images/lock.svg
new file mode 100644
index 0000000..dc3e73b
--- /dev/null
+++ b/images/lock.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1490754711787" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8945" xmlns:xlink="http://www.w3.org/1999/xlink" width="20" height="20"><defs><style type="text/css"></style></defs><path d="M794.555819 1022.209214 229.439064 1022.209214c-69.305459 0-125.607766-59.490929-125.607766-132.73407L103.831298 491.571738c0-73.144904 56.30333-132.63481 125.607766-132.63481l32.587186 0c-3.338025-16.541745-5.132904-33.580816-5.132904-51.021024l0-51.021024c0-140.90517 114.199948-255.104095 255.107165-255.104095 140.854005 0 255.104095 114.198925 255.104095 255.104095l0 51.021024c0 17.439184-1.795902 34.479279-5.132904 51.021024l32.584116 0c69.258387 0 125.611859 59.489906 125.611859 132.63481l0 397.903405C920.167678 962.718285 863.814206 1022.209214 794.555819 1022.209214zM460.977441 702.132338l0 115.993804c0 28.099988 22.870894 51.02 51.02307 51.02 28.149107 0 51.02-22.920012 51.02-51.02L563.020512 702.132338c30.93864-17.538445 52.014654-50.223868 52.014654-88.090291 0-56.402591-46.137807-102.042047-103.034655-102.042047-56.952106 0-103.089913 45.639456-103.089913 102.042047C408.910599 651.90847 430.036755 684.593893 460.977441 702.132338zM665.06256 256.894881c0-84.552721-68.509327-153.063071-153.062048-153.063071-84.554768 0-153.065118 68.509327-153.065118 153.063071l0 102.042047 306.127166 0L665.06256 256.894881z" p-id="8946"></path></svg>
\ No newline at end of file
diff --git a/images/mage_location.svg b/images/mage_location.svg
new file mode 100644
index 0000000..ca557ef
--- /dev/null
+++ b/images/mage_location.svg
@@ -0,0 +1,4 @@
+<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M32.25 18H29.0835M29.0835 18C29.0835 20.9397 27.9164 23.7583 25.8377 25.837C23.759 27.9157 20.9397 29.0835 18 29.0835M29.0835 18C29.0835 15.0603 27.9164 12.2402 25.8377 10.1615C23.759 8.0828 20.9397 6.9165 18 6.9165M18 3.75V6.9165M18 6.9165C15.0605 6.9165 12.2413 8.08272 10.1628 10.1613C8.08422 12.2398 6.9165 15.059 6.9165 17.9985C6.9165 20.938 8.08422 23.7572 10.1628 25.8357C12.2413 27.9143 15.0605 29.0835 18 29.0835M3.75 18H6.9165M18 32.25V29.0835" stroke="#1890FF" stroke-width="3" stroke-miterlimit="10" stroke-linecap="round"/>
+<path d="M18 24.334C19.6796 24.334 21.2904 23.6667 22.4781 22.4791C23.6658 21.2914 24.333 19.6806 24.333 18.001C24.333 16.3214 23.6658 14.7105 22.4781 13.5229C21.2904 12.3352 19.6796 11.668 18 11.668C16.3204 11.668 14.7096 12.3352 13.5219 13.5229C12.3342 14.7105 11.667 16.3214 11.667 18.001C11.667 19.6806 12.3342 21.2914 13.5219 22.4791C14.7096 23.6667 16.3204 24.334 18 24.334Z" stroke="#1890FF" stroke-width="3" stroke-miterlimit="10" stroke-linecap="round"/>
+</svg>
diff --git a/images/material-symbols-light_pause-rounded.svg b/images/material-symbols-light_pause-rounded.svg
new file mode 100644
index 0000000..16075e3
--- /dev/null
+++ b/images/material-symbols-light_pause-rounded.svg
@@ -0,0 +1,3 @@
+<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M24 30C23.464 30 22.9967 29.8007 22.598 29.402C22.1993 29.0033 22 28.536 22 28V8C22 7.464 22.1993 6.99667 22.598 6.598C22.9967 6.19933 23.464 6 24 6H27C27.536 6 28.0033 6.19933 28.402 6.598C28.8007 6.99667 29 7.464 29 8V28C29 28.536 28.8007 29.0033 28.402 29.402C28.0033 29.8007 27.536 30 27 30H24ZM9 30C8.464 30 7.99667 29.8007 7.598 29.402C7.19933 29.0033 7 28.536 7 28V8C7 7.464 7.19933 6.99667 7.598 6.598C7.99667 6.19933 8.464 6 9 6H12C12.536 6 13.0033 6.19933 13.402 6.598C13.8007 6.99667 14 7.464 14 8V28C14 28.536 13.8007 29.0033 13.402 29.402C13.0033 29.8007 12.536 30 12 30H9Z" fill="#1890FF"/>
+</svg>
diff --git a/images/material-symbols_cancel-rounded.svg b/images/material-symbols_cancel-rounded.svg
new file mode 100644
index 0000000..43b9a32
--- /dev/null
+++ b/images/material-symbols_cancel-rounded.svg
@@ -0,0 +1,3 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M12 13.4L14.9 16.3C15.0833 16.4833 15.3167 16.575 15.6 16.575C15.8833 16.575 16.1167 16.4833 16.3 16.3C16.4833 16.1167 16.575 15.8833 16.575 15.6C16.575 15.3167 16.4833 15.0833 16.3 14.9L13.4 12L16.3 9.1C16.4833 8.91667 16.575 8.68333 16.575 8.4C16.575 8.11667 16.4833 7.88333 16.3 7.7C16.1167 7.51667 15.8833 7.425 15.6 7.425C15.3167 7.425 15.0833 7.51667 14.9 7.7L12 10.6L9.1 7.7C8.91667 7.51667 8.68333 7.425 8.4 7.425C8.11667 7.425 7.88333 7.51667 7.7 7.7C7.51667 7.88333 7.425 8.11667 7.425 8.4C7.425 8.68333 7.51667 8.91667 7.7 9.1L10.6 12L7.7 14.9C7.51667 15.0833 7.425 15.3167 7.425 15.6C7.425 15.8833 7.51667 16.1167 7.7 16.3C7.88333 16.4833 8.11667 16.575 8.4 16.575C8.68333 16.575 8.91667 16.4833 9.1 16.3L12 13.4ZM12 22C10.6167 22 9.31667 21.7373 8.1 21.212C6.88334 20.6867 5.825 19.9743 4.925 19.075C4.025 18.1757 3.31267 17.1173 2.788 15.9C2.26333 14.6827 2.00067 13.3827 2 12C1.99933 10.6173 2.262 9.31733 2.788 8.1C3.314 6.88267 4.02633 5.82433 4.925 4.925C5.82367 4.02567 6.882 3.31333 8.1 2.788C9.318 2.26267 10.618 2 12 2C13.382 2 14.682 2.26267 15.9 2.788C17.118 3.31333 18.1763 4.02567 19.075 4.925C19.9737 5.82433 20.6863 6.88267 21.213 8.1C21.7397 9.31733 22.002 10.6173 22 12C21.998 13.3827 21.7353 14.6827 21.212 15.9C20.6887 17.1173 19.9763 18.1757 19.075 19.075C18.1737 19.9743 17.1153 20.687 15.9 21.213C14.6847 21.739 13.3847 22.0013 12 22Z" fill="#F5222D"/>
+</svg>
diff --git a/images/material-symbols_delete-outline-1.svg b/images/material-symbols_delete-outline-1.svg
new file mode 100644
index 0000000..1c0e89f
--- /dev/null
+++ b/images/material-symbols_delete-outline-1.svg
@@ -0,0 +1,3 @@
+<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M10.5 31.5C9.675 31.5 8.969 31.2065 8.382 30.6195C7.795 30.0325 7.501 29.326 7.5 28.5V9H6V6H13.5V4.5H22.5V6H30V9H28.5V28.5C28.5 29.325 28.2065 30.0315 27.6195 30.6195C27.0325 31.2075 26.326 31.501 25.5 31.5H10.5ZM25.5 9H10.5V28.5H25.5V9ZM13.5 25.5H16.5V12H13.5V25.5ZM19.5 25.5H22.5V12H19.5V25.5Z" fill="#FF3B30"/>
+</svg>
diff --git a/images/material-symbols_my-location-rounded.svg b/images/material-symbols_my-location-rounded.svg
new file mode 100644
index 0000000..139c5b1
--- /dev/null
+++ b/images/material-symbols_my-location-rounded.svg
@@ -0,0 +1,3 @@
+<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M16.5002 32.9242V31.4242C13.3752 31.0742 10.6937 29.7807 8.4557 27.5437C6.2177 25.3067 4.9242 22.6252 4.5752 19.4992H3.0752C2.6502 19.4992 2.2942 19.3552 2.0072 19.0672C1.7202 18.7792 1.5762 18.4232 1.5752 17.9992C1.5742 17.5752 1.7182 17.2192 2.0072 16.9312C2.2962 16.6432 2.6522 16.4992 3.0752 16.4992H4.5752C4.9252 13.3742 6.2192 10.6927 8.4572 8.45472C10.6952 6.21672 13.3762 4.92322 16.5002 4.57422V3.07422C16.5002 2.64922 16.6442 2.29322 16.9322 2.00622C17.2202 1.71922 17.5762 1.57522 18.0002 1.57422C18.4242 1.57322 18.7807 1.71722 19.0697 2.00622C19.3587 2.29522 19.5022 2.65122 19.5002 3.07422V4.57422C22.6252 4.92422 25.3067 6.21822 27.5447 8.45622C29.7827 10.6942 31.0762 13.3752 31.4252 16.4992H32.9252C33.3502 16.4992 33.7067 16.6432 33.9947 16.9312C34.2827 17.2192 34.4262 17.5752 34.4252 17.9992C34.4242 18.4232 34.2807 18.7797 33.9947 19.0687C33.7087 19.3577 33.3522 19.5012 32.9252 19.4992H31.4252C31.0752 22.6242 29.7817 25.3057 27.5447 27.5437C25.3077 29.7817 22.6262 31.0752 19.5002 31.4242V32.9242C19.5002 33.3492 19.3562 33.7057 19.0682 33.9937C18.7802 34.2817 18.4242 34.4252 18.0002 34.4242C17.5762 34.4232 17.2202 34.2797 16.9322 33.9937C16.6442 33.7077 16.5002 33.3512 16.5002 32.9242ZM18.0002 28.4992C20.9002 28.4992 23.3752 27.4742 25.4252 25.4242C27.4752 23.3742 28.5002 20.8992 28.5002 17.9992C28.5002 15.0992 27.4752 12.6242 25.4252 10.5742C23.3752 8.52422 20.9002 7.49922 18.0002 7.49922C15.1002 7.49922 12.6252 8.52422 10.5752 10.5742C8.5252 12.6242 7.5002 15.0992 7.5002 17.9992C7.5002 20.8992 8.5252 23.3742 10.5752 25.4242C12.6252 27.4742 15.1002 28.4992 18.0002 28.4992ZM18.0002 23.9992C16.3502 23.9992 14.9377 23.4117 13.7627 22.2367C12.5877 21.0617 12.0002 19.6492 12.0002 17.9992C12.0002 16.3492 12.5877 14.9367 13.7627 13.7617C14.9377 12.5867 16.3502 11.9992 18.0002 11.9992C19.6502 11.9992 21.0627 12.5867 22.2377 13.7617C23.4127 14.9367 24.0002 16.3492 24.0002 17.9992C24.0002 19.6492 23.4127 21.0617 22.2377 22.2367C21.0627 23.4117 19.6502 23.9992 18.0002 23.9992Z" fill="#1890FF"/>
+</svg>
diff --git a/images/material-symbols_skip-next-rounded.svg b/images/material-symbols_skip-next-rounded.svg
new file mode 100644
index 0000000..265001b
--- /dev/null
+++ b/images/material-symbols_skip-next-rounded.svg
@@ -0,0 +1,3 @@
+<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M26.3077 27.1667V8.83334C26.3077 8.31389 26.4849 7.87878 26.8394 7.52801C27.1938 7.17723 27.632 7.00123 28.1538 7.00001C28.6757 6.99878 29.1144 7.17478 29.4701 7.52801C29.8258 7.88123 30.0024 8.31634 30 8.83334V27.1667C30 27.6861 29.8227 28.1218 29.4683 28.4738C29.1138 28.8258 28.6757 29.0012 28.1538 29C27.632 28.9988 27.1938 28.8228 26.8394 28.472C26.4849 28.1212 26.3077 27.6861 26.3077 27.1667ZM6 25.5625V10.4375C6 9.8875 6.18462 9.44445 6.55385 9.10834C6.92308 8.77223 7.35384 8.60417 7.84615 8.60417C8 8.60417 8.16923 8.61945 8.35384 8.65001C8.53846 8.68056 8.70769 8.75695 8.86154 8.87917L20.3077 16.4875C20.5846 16.6708 20.7926 16.8927 20.9317 17.153C21.0708 17.4133 21.1397 17.6957 21.1384 18C21.1372 18.3043 21.0683 18.5873 20.9317 18.8488C20.7951 19.1104 20.5871 19.3316 20.3077 19.5125L8.86154 27.1208C8.70769 27.2431 8.53846 27.3194 8.35384 27.35C8.16923 27.3806 8 27.3958 7.84615 27.3958C7.35384 27.3958 6.92308 27.2278 6.55385 26.8917C6.18462 26.5555 6 26.1125 6 25.5625Z" fill="#1890FF"/>
+</svg>
diff --git a/images/mdi_rename.svg b/images/mdi_rename.svg
new file mode 100644
index 0000000..eff9cc7
--- /dev/null
+++ b/images/mdi_rename.svg
@@ -0,0 +1,3 @@
+<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M22.5 23.9992L16.5 29.9992H31.5V23.9992H22.5ZM18.09 10.7842L4.5 24.3742V29.9992H10.125L23.715 16.4092L18.09 10.7842ZM28.065 12.0592C28.65 11.4742 28.65 10.4992 28.065 9.94424L24.555 6.43424C24.274 6.15486 23.8938 5.99805 23.4975 5.99805C23.1012 5.99805 22.721 6.15486 22.44 6.43424L19.695 9.17924L25.32 14.8042L28.065 12.0592Z" fill="#1890FF"/>
+</svg>
diff --git a/images/mingcute_add-line.svg b/images/mingcute_add-line.svg
new file mode 100644
index 0000000..499c1da
--- /dev/null
+++ b/images/mingcute_add-line.svg
@@ -0,0 +1,3 @@
+<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M16.5 30C16.5 30.3978 16.658 30.7794 16.9393 31.0607C17.2206 31.342 17.6022 31.5 18 31.5C18.3978 31.5 18.7794 31.342 19.0607 31.0607C19.342 30.7794 19.5 30.3978 19.5 30V19.5H30C30.3978 19.5 30.7794 19.342 31.0607 19.0607C31.342 18.7794 31.5 18.3978 31.5 18C31.5 17.6022 31.342 17.2206 31.0607 16.9393C30.7794 16.658 30.3978 16.5 30 16.5H19.5V6C19.5 5.60218 19.342 5.22064 19.0607 4.93934C18.7794 4.65804 18.3978 4.5 18 4.5C17.6022 4.5 17.2206 4.65804 16.9393 4.93934C16.658 5.22064 16.5 5.60218 16.5 6V16.5H6C5.60218 16.5 5.22064 16.658 4.93934 16.9393C4.65804 17.2206 4.5 17.6022 4.5 18C4.5 18.3978 4.65804 18.7794 4.93934 19.0607C5.22064 19.342 5.60218 19.5 6 19.5H16.5V30Z" fill="#1890FF"/>
+</svg>
diff --git a/images/mingcute_edit-line-1.svg b/images/mingcute_edit-line-1.svg
new file mode 100644
index 0000000..6aec0a2
--- /dev/null
+++ b/images/mingcute_edit-line-1.svg
@@ -0,0 +1,3 @@
+<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M19.2791 4C19.643 4.0004 19.9931 4.13976 20.2577 4.38961C20.5224 4.63945 20.6817 4.98092 20.703 5.34425C20.7243 5.70757 20.6061 6.06533 20.3725 6.34443C20.1389 6.62352 19.8076 6.80288 19.4462 6.84587L19.2791 6.85587H7.85562V26.8469H27.8467V15.4235C27.8471 15.0595 27.9865 14.7095 28.2363 14.4448C28.4861 14.1802 28.8276 14.0209 29.1909 13.9996C29.5543 13.9782 29.912 14.0965 30.1911 14.33C30.4702 14.5636 30.6496 14.895 30.6926 15.2564L30.7026 15.4235V26.8469C30.7028 27.5674 30.4307 28.2614 29.9408 28.7897C29.4508 29.318 28.7793 29.6416 28.0609 29.6957L27.8467 29.7028H7.85562C7.13512 29.703 6.44116 29.4309 5.91285 28.941C5.38454 28.4511 5.06093 27.7796 5.0069 27.0611L4.99976 26.8469V6.85587C4.99953 6.13537 5.27164 5.4414 5.76155 4.91309C6.25146 4.38479 6.92296 4.06118 7.64143 4.00714L7.85562 4H19.2791ZM28.1937 4.48978C28.4506 4.23368 28.7955 4.085 29.1581 4.07393C29.5207 4.06285 29.8739 4.19022 30.1461 4.43016C30.4182 4.6701 30.5888 5.00462 30.6232 5.36578C30.6576 5.72694 30.5532 6.08765 30.3313 6.37465L30.2128 6.51031L16.0762 20.6454C15.8193 20.9015 15.4745 21.0502 15.1118 21.0613C14.7492 21.0723 14.396 20.945 14.1239 20.705C13.8517 20.4651 13.6812 20.1306 13.6467 19.7694C13.6123 19.4083 13.7167 19.0475 13.9386 18.7605L14.0571 18.6263L28.1937 4.48978Z" fill="#1890FF"/>
+</svg>
diff --git a/images/mobile.svg b/images/mobile.svg
new file mode 100644
index 0000000..2462753
--- /dev/null
+++ b/images/mobile.svg
@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1490767992262" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="14858" xmlns:xlink="http://www.w3.org/1999/xlink" width="20" height="20"><defs><style type="text/css"></style></defs><path d="M758.217704 46.175669l-487.318878 0c-25.63075 0-46.411029 20.781302-46.411029 46.411029l0 838.826604c0 25.63075 20.781302 46.411029 46.411029 46.411029l487.318878 0c25.63075 0 46.411029-20.781302 46.411029-46.411029L804.628734 92.586698C804.628734 66.955948 783.848455 46.175669 758.217704 46.175669zM514.558265 929.554978c-28.871561 0-52.280714-23.409153-52.280714-52.280714 0-28.871561 23.409153-52.280714 52.280714-52.280714 28.871561 0 52.280714 23.409153 52.280714 52.280714C566.838979 906.144802 543.428803 929.554978 514.558265 929.554978zM758.217704 757.370407l-487.318878 0L270.898827 130.817418l487.318878 0L758.217704 757.370407z" p-id="14859" fill="#999999"></path></svg>
\ No newline at end of file
diff --git a/images/ooui_user-avatar-1.svg b/images/ooui_user-avatar-1.svg
new file mode 100644
index 0000000..3316565
--- /dev/null
+++ b/images/ooui_user-avatar-1.svg
@@ -0,0 +1,11 @@
+<svg width="81" height="81" viewBox="0 0 81 81" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g clip-path="url(#clip0_647_20369)">
+<path d="M40.5 47.9258C15.525 47.9258 6.75 60.582 6.75 69.0195V81.6758H74.25V69.0195C74.25 60.582 65.475 47.9258 40.5 47.9258Z" fill="#1890FF"/>
+<path d="M40.5 43.875C51.6838 43.875 60.75 34.8088 60.75 23.625C60.75 12.4412 51.6838 3.375 40.5 3.375C29.3162 3.375 20.25 12.4412 20.25 23.625C20.25 34.8088 29.3162 43.875 40.5 43.875Z" fill="#1890FF"/>
+</g>
+<defs>
+<clipPath id="clip0_647_20369">
+<rect width="81" height="81" fill="white"/>
+</clipPath>
+</defs>
+</svg>
diff --git a/images/ooui_user-avatar.svg b/images/ooui_user-avatar.svg
new file mode 100644
index 0000000..bb300d6
--- /dev/null
+++ b/images/ooui_user-avatar.svg
@@ -0,0 +1,11 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g clip-path="url(#clip0_647_20366)">
+<path d="M12 14.1992C4.6 14.1992 2 17.9492 2 20.4492V24.1992H22V20.4492C22 17.9492 19.4 14.1992 12 14.1992Z" fill="#1890FF"/>
+<path d="M12 13C15.3137 13 18 10.3137 18 7C18 3.68629 15.3137 1 12 1C8.68629 1 6 3.68629 6 7C6 10.3137 8.68629 13 12 13Z" fill="#1890FF"/>
+</g>
+<defs>
+<clipPath id="clip0_647_20366">
+<rect width="24" height="24" fill="white"/>
+</clipPath>
+</defs>
+</svg>
diff --git a/images/ooui_user-avatar2-1.svg b/images/ooui_user-avatar2-1.svg
new file mode 100644
index 0000000..d1dc30e
--- /dev/null
+++ b/images/ooui_user-avatar2-1.svg
@@ -0,0 +1,11 @@
+<svg width="81" height="81" viewBox="0 0 81 81" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g clip-path="url(#clip0_647_20363)">
+<path d="M40.5 47.9258C15.525 47.9258 6.75 60.582 6.75 69.0195V81.6758H74.25V69.0195C74.25 60.582 65.475 47.9258 40.5 47.9258Z" fill="#999999"/>
+<path d="M40.5 43.875C51.6838 43.875 60.75 34.8088 60.75 23.625C60.75 12.4412 51.6838 3.375 40.5 3.375C29.3162 3.375 20.25 12.4412 20.25 23.625C20.25 34.8088 29.3162 43.875 40.5 43.875Z" fill="#999999"/>
+</g>
+<defs>
+<clipPath id="clip0_647_20363">
+<rect width="81" height="81" fill="white"/>
+</clipPath>
+</defs>
+</svg>
diff --git a/images/ooui_user-avatar2.svg b/images/ooui_user-avatar2.svg
new file mode 100644
index 0000000..1db3f5d
--- /dev/null
+++ b/images/ooui_user-avatar2.svg
@@ -0,0 +1,11 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g clip-path="url(#clip0_647_20360)">
+<path d="M12 14.1992C4.6 14.1992 2 17.9492 2 20.4492V24.1992H22V20.4492C22 17.9492 19.4 14.1992 12 14.1992Z" fill="#999999"/>
+<path d="M12 13C15.3137 13 18 10.3137 18 7C18 3.68629 15.3137 1 12 1C8.68629 1 6 3.68629 6 7C6 10.3137 8.68629 13 12 13Z" fill="#999999"/>
+</g>
+<defs>
+<clipPath id="clip0_647_20360">
+<rect width="24" height="24" fill="white"/>
+</clipPath>
+</defs>
+</svg>
diff --git a/images/proicons_task-list-1.svg b/images/proicons_task-list-1.svg
new file mode 100644
index 0000000..7c16afd
--- /dev/null
+++ b/images/proicons_task-list-1.svg
@@ -0,0 +1,3 @@
+<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M15.7297 7.85882H30M11.8378 6L8.08476 9.71764L6 7.65314M15.7297 17.5H30M11.8378 15.6412L8.08476 19.3588L6 17.2943M15.7297 27.1412H30M11.8378 25.2824L8.08476 29L6 26.9355" stroke="#1890FF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>
diff --git a/images/proicons_task-list.svg b/images/proicons_task-list.svg
new file mode 100644
index 0000000..e0d583c
--- /dev/null
+++ b/images/proicons_task-list.svg
@@ -0,0 +1,3 @@
+<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M15.375 6.74908H31.875M10.875 4.58008L6.5355 8.91808L4.125 6.50908M15.375 17.9991H31.875M10.875 15.8301L6.5355 20.1681L4.125 17.7591M15.375 29.2491H31.875M10.875 27.0801L6.5355 31.4181L4.125 29.0091" stroke="#1890FF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>
diff --git a/images/ri_more-fill.svg b/images/ri_more-fill.svg
new file mode 100644
index 0000000..f00b3d3
--- /dev/null
+++ b/images/ri_more-fill.svg
@@ -0,0 +1,3 @@
+<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M6.25 12.5C4.875 12.5 3.75 13.625 3.75 15C3.75 16.375 4.875 17.5 6.25 17.5C7.625 17.5 8.75 16.375 8.75 15C8.75 13.625 7.625 12.5 6.25 12.5ZM23.75 12.5C22.375 12.5 21.25 13.625 21.25 15C21.25 16.375 22.375 17.5 23.75 17.5C25.125 17.5 26.25 16.375 26.25 15C26.25 13.625 25.125 12.5 23.75 12.5ZM15 12.5C13.625 12.5 12.5 13.625 12.5 15C12.5 16.375 13.625 17.5 15 17.5C16.375 17.5 17.5 16.375 17.5 15C17.5 13.625 16.375 12.5 15 12.5Z" fill="black"/>
+</svg>
diff --git a/images/stop.svg b/images/stop.svg
new file mode 100644
index 0000000..e6ab88e
--- /dev/null
+++ b/images/stop.svg
@@ -0,0 +1,3 @@
+<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M6 9C6 7.34315 7.34315 6 9 6H27C28.6569 6 30 7.34315 30 9V27C30 28.6569 28.6569 30 27 30H9C7.34315 30 6 28.6569 6 27V9Z" fill="#1890FF"/>
+</svg>
diff --git a/images/tabler_line-scan.svg b/images/tabler_line-scan.svg
new file mode 100644
index 0000000..ef673bf
--- /dev/null
+++ b/images/tabler_line-scan.svg
@@ -0,0 +1,3 @@
+<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M5 10V7.5C5 6.83696 5.26339 6.20107 5.73223 5.73223C6.20107 5.26339 6.83696 5 7.5 5H10M5 20V22.5C5 23.163 5.26339 23.7989 5.73223 24.2678C6.20107 24.7366 6.83696 25 7.5 25H10M20 5H22.5C23.163 5 23.7989 5.26339 24.2678 5.73223C24.7366 6.20107 25 6.83696 25 7.5V10M20 25H22.5C23.163 25 23.7989 24.7366 24.2678 24.2678C24.7366 23.7989 25 23.163 25 22.5V20M8.75 15H21.25" stroke="black" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>
diff --git a/images/van.svg b/images/van.svg
new file mode 100644
index 0000000..356c12c
--- /dev/null
+++ b/images/van.svg
@@ -0,0 +1,10 @@
+<svg width="40" height="84" viewBox="0 0 40 84" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect x="18" y="74" width="4" height="10" fill="#434343"/>
+<rect x="34" y="80" width="4" height="28" rx="2" transform="rotate(90 34 80)" fill="#434343"/>
+<rect x="4" width="12" height="62" rx="6" fill="#434343"/>
+<rect x="24" width="12" height="62" rx="6" fill="#434343"/>
+<rect x="8" y="8" width="4" height="8" rx="2" fill="#FA8C16"/>
+<rect x="28" y="8" width="4" height="8" rx="2" fill="#FA8C16"/>
+<rect y="48" width="40" height="28" rx="4" fill="#FA8C16"/>
+<circle cx="32" cy="56" r="4" fill="#434343"/>
+</svg>
diff --git "a/images/\345\260\217\347\272\242\347\202\271.png" "b/images/\345\260\217\347\272\242\347\202\271.png"
new file mode 100644
index 0000000..90aa541
--- /dev/null
+++ "b/images/\345\260\217\347\272\242\347\202\271.png"
Binary files differ
diff --git "a/images/\347\253\231\347\202\271-1.svg" "b/images/\347\253\231\347\202\271-1.svg"
new file mode 100644
index 0000000..108376f
--- /dev/null
+++ "b/images/\347\253\231\347\202\271-1.svg"
@@ -0,0 +1,11 @@
+<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="36" height="36" rx="18" fill="#F5222D"/>
+<g clip-path="url(#clip0_647_7173)">
+<path d="M14.2546 12.9093C14.2546 12.5911 14.381 12.2859 14.606 12.0609C14.831 11.8359 15.1362 11.7095 15.4544 11.7095L23.0911 11.7095C23.4093 11.7095 23.7145 11.8359 23.9395 12.0609C24.1645 12.2859 24.2909 12.5911 24.291 12.9093L24.291 20.546C24.2855 20.8606 24.1567 21.1605 23.9323 21.3811C23.7079 21.6016 23.4058 21.7252 23.0911 21.7252C22.7765 21.7252 22.4744 21.6016 22.25 21.3811C22.0256 21.1605 21.8968 20.8606 21.8913 20.546L21.8184 15.8791L13.7573 23.9402C13.5323 24.1652 13.2271 24.2916 12.9088 24.2916C12.5905 24.2916 12.2853 24.1652 12.0603 23.9402C11.8352 23.7151 11.7088 23.4099 11.7088 23.0916C11.7088 22.7734 11.8352 22.4681 12.0603 22.2431L20.1213 14.1821L15.4544 14.1091C15.1362 14.1091 14.831 13.9826 14.606 13.7576C14.381 13.5326 14.2546 13.2275 14.2546 12.9093Z" fill="#FFA39E"/>
+</g>
+<defs>
+<clipPath id="clip0_647_7173">
+<rect width="18" height="18" fill="white" transform="translate(5.27197 18) rotate(-45)"/>
+</clipPath>
+</defs>
+</svg>
diff --git "a/images/\347\253\231\347\202\271-2.svg" "b/images/\347\253\231\347\202\271-2.svg"
new file mode 100644
index 0000000..bd171a8
--- /dev/null
+++ "b/images/\347\253\231\347\202\271-2.svg"
@@ -0,0 +1,4 @@
+<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="36" height="36" rx="18" fill="#FFD591"/>
+<path d="M18.9517 11.7517C19.1767 11.5268 19.4819 11.4004 19.8001 11.4004C20.1183 11.4004 20.4235 11.5268 20.6485 11.7517L26.0485 17.1517C26.2735 17.3768 26.3998 17.6819 26.3998 18.0001C26.3998 18.3183 26.2735 18.6235 26.0485 18.8485L20.6485 24.2485C20.4222 24.4671 20.1191 24.5881 19.8044 24.5853C19.4898 24.5826 19.1888 24.4564 18.9663 24.2339C18.7438 24.0114 18.6176 23.7105 18.6149 23.3958C18.6122 23.0812 18.7331 22.7781 18.9517 22.5517L22.2001 19.2001H10.8001C10.4818 19.2001 10.1766 19.0737 9.95157 18.8487C9.72653 18.6236 9.6001 18.3184 9.6001 18.0001C9.6001 17.6819 9.72653 17.3766 9.95157 17.1516C10.1766 16.9266 10.4818 16.8001 10.8001 16.8001H22.2001L18.9517 13.4485C18.7267 13.2235 18.6004 12.9183 18.6004 12.6001C18.6004 12.2819 18.7267 11.9768 18.9517 11.7517Z" fill="#FA8C16"/>
+</svg>
diff --git "a/images/\347\253\231\347\202\271-3.svg" "b/images/\347\253\231\347\202\271-3.svg"
new file mode 100644
index 0000000..479e9d0
--- /dev/null
+++ "b/images/\347\253\231\347\202\271-3.svg"
@@ -0,0 +1,11 @@
+<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="36" height="36" rx="18" fill="#FA8C16"/>
+<g clip-path="url(#clip0_647_7175)">
+<path d="M23.0912 14.2536C23.4094 14.2536 23.7145 14.3801 23.9395 14.6051C24.1645 14.8301 24.291 15.1352 24.291 15.4534L24.291 23.0902C24.291 23.4084 24.1645 23.7135 23.9395 23.9385C23.7145 24.1635 23.4094 24.2899 23.0912 24.29L15.4544 24.29C15.1398 24.2845 14.84 24.1557 14.6194 23.9313C14.3989 23.7069 14.2753 23.4048 14.2753 23.0902C14.2753 22.7755 14.3989 22.4735 14.6194 22.249C14.84 22.0246 15.1398 21.8958 15.4544 21.8903L20.1213 21.8174L12.0603 13.7564C11.8353 13.5313 11.7089 13.2261 11.7089 12.9078C11.7089 12.5896 11.8353 12.2843 12.0603 12.0593C12.2854 11.8343 12.5906 11.7078 12.9089 11.7078C13.2271 11.7078 13.5323 11.8343 13.7574 12.0593L21.8184 20.1203L21.8914 15.4534C21.8914 15.1352 22.0178 14.8301 22.2428 14.6051C22.4678 14.3801 22.773 14.2536 23.0912 14.2536Z" fill="#FFD591"/>
+</g>
+<defs>
+<clipPath id="clip0_647_7175">
+<rect width="18" height="18" fill="white" transform="translate(18 5.27148) rotate(45)"/>
+</clipPath>
+</defs>
+</svg>
diff --git "a/images/\347\253\231\347\202\271-4.svg" "b/images/\347\253\231\347\202\271-4.svg"
new file mode 100644
index 0000000..f99446d
--- /dev/null
+++ "b/images/\347\253\231\347\202\271-4.svg"
@@ -0,0 +1,4 @@
+<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="36" height="36" rx="18" fill="#FFEC3D"/>
+<path d="M24.2485 18.9512C24.4735 19.1762 24.5999 19.4814 24.5999 19.7996C24.5999 20.1178 24.4735 20.423 24.2485 20.648L18.8485 26.048C18.6235 26.273 18.3183 26.3994 18.0001 26.3994C17.6819 26.3994 17.3767 26.273 17.1517 26.048L11.7517 20.648C11.5331 20.4217 11.4122 20.1186 11.4149 19.8039C11.4176 19.4893 11.5438 19.1883 11.7663 18.9658C11.9888 18.7433 12.2898 18.6171 12.6044 18.6144C12.9191 18.6117 13.2222 18.7326 13.4485 18.9512L16.8001 22.1996L16.8001 10.7996C16.8001 10.4813 16.9265 10.1761 17.1516 9.95108C17.3766 9.72604 17.6819 9.59961 18.0001 9.59961C18.3184 9.59961 18.6236 9.72604 18.8486 9.95108C19.0737 10.1761 19.2001 10.4813 19.2001 10.7996L19.2001 22.1996L22.5517 18.9512C22.7767 18.7262 23.0819 18.5999 23.4001 18.5999C23.7183 18.5999 24.0235 18.7262 24.2485 18.9512Z" fill="#D4B106"/>
+</svg>
diff --git "a/images/\347\253\231\347\202\271-5.svg" "b/images/\347\253\231\347\202\271-5.svg"
new file mode 100644
index 0000000..f03839a
--- /dev/null
+++ "b/images/\347\253\231\347\202\271-5.svg"
@@ -0,0 +1,11 @@
+<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="36" height="36" rx="18" fill="#D4B106"/>
+<g clip-path="url(#clip0_647_7177)">
+<path d="M21.7454 23.0907C21.7454 23.4089 21.619 23.7141 21.394 23.9391C21.169 24.1641 20.8638 24.2905 20.5456 24.2905L12.9089 24.2905C12.5907 24.2905 12.2855 24.1641 12.0605 23.9391C11.8355 23.7141 11.7091 23.4089 11.709 23.0907L11.709 15.454C11.7145 15.1394 11.8433 14.8395 12.0677 14.6189C12.2921 14.3984 12.5942 14.2748 12.9089 14.2748C13.2235 14.2748 13.5256 14.3984 13.75 14.6189C13.9744 14.8395 14.1032 15.1394 14.1087 15.454L14.1816 20.1209L22.2427 12.0598C22.4677 11.8348 22.7729 11.7084 23.0912 11.7084C23.4095 11.7084 23.7147 11.8348 23.9397 12.0598C24.1648 12.2849 24.2912 12.5901 24.2912 12.9084C24.2912 13.2266 24.1648 13.5319 23.9397 13.7569L15.8787 21.8179L20.5456 21.8909C20.8638 21.8909 21.169 22.0174 21.394 22.2424C21.619 22.4674 21.7454 22.7725 21.7454 23.0907Z" fill="#FFEC3D"/>
+</g>
+<defs>
+<clipPath id="clip0_647_7177">
+<rect width="18" height="18" fill="white" transform="translate(30.728 18) rotate(135)"/>
+</clipPath>
+</defs>
+</svg>
diff --git "a/images/\347\253\231\347\202\271-6.svg" "b/images/\347\253\231\347\202\271-6.svg"
new file mode 100644
index 0000000..9e86480
--- /dev/null
+++ "b/images/\347\253\231\347\202\271-6.svg"
@@ -0,0 +1,4 @@
+<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="36" height="36" rx="18" fill="#D3F261"/>
+<path d="M17.0483 24.2483C16.8233 24.4732 16.5181 24.5996 16.1999 24.5996C15.8817 24.5996 15.5765 24.4732 15.3515 24.2483L9.9515 18.8483C9.72654 18.6232 9.60016 18.3181 9.60016 17.9999C9.60016 17.6817 9.72654 17.3765 9.9515 17.1515L15.3515 11.7515C15.5778 11.5329 15.8809 11.4119 16.1956 11.4147C16.5102 11.4174 16.8112 11.5436 17.0337 11.7661C17.2562 11.9886 17.3824 12.2895 17.3851 12.6042C17.3878 12.9188 17.2669 13.2219 17.0483 13.4483L13.7999 16.7999L25.1999 16.7999C25.5182 16.7999 25.8234 16.9263 26.0484 17.1513C26.2735 17.3764 26.3999 17.6816 26.3999 17.9999C26.3999 18.3181 26.2735 18.6234 26.0484 18.8484C25.8234 19.0734 25.5182 19.1999 25.1999 19.1999L13.7999 19.1999L17.0483 22.5515C17.2733 22.7765 17.3996 23.0817 17.3996 23.3999C17.3996 23.7181 17.2733 24.0232 17.0483 24.2483Z" fill="#7CB305"/>
+</svg>
diff --git "a/images/\347\253\231\347\202\271-7.svg" "b/images/\347\253\231\347\202\271-7.svg"
new file mode 100644
index 0000000..ee2f1e5
--- /dev/null
+++ "b/images/\347\253\231\347\202\271-7.svg"
@@ -0,0 +1,11 @@
+<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="36" height="36" rx="18" fill="#7CB305"/>
+<g clip-path="url(#clip0_647_7179)">
+<path d="M12.9088 21.7464C12.5906 21.7464 12.2855 21.6199 12.0605 21.3949C11.8355 21.1699 11.709 20.8648 11.709 20.5466L11.709 12.9098C11.709 12.5916 11.8355 12.2865 12.0605 12.0615C12.2855 11.8365 12.5906 11.7101 12.9088 11.71L20.5456 11.71C20.8602 11.7155 21.16 11.8443 21.3806 12.0687C21.6011 12.2931 21.7247 12.5952 21.7247 12.9098C21.7247 13.2245 21.6011 13.5265 21.3806 13.751C21.16 13.9754 20.8602 14.1042 20.5456 14.1097L15.8787 14.1826L23.9397 22.2436C24.1647 22.4687 24.2911 22.7739 24.2911 23.0922C24.2911 23.4104 24.1647 23.7157 23.9397 23.9407C23.7146 24.1657 23.4094 24.2922 23.0911 24.2922C22.7729 24.2922 22.4677 24.1657 22.2426 23.9407L14.1816 15.8797L14.1086 20.5466C14.1086 20.8648 13.9822 21.1699 13.7572 21.3949C13.5322 21.6199 13.227 21.7464 12.9088 21.7464Z" fill="#D3F261"/>
+</g>
+<defs>
+<clipPath id="clip0_647_7179">
+<rect width="18" height="18" fill="white" transform="translate(18 30.7285) rotate(-135)"/>
+</clipPath>
+</defs>
+</svg>
diff --git "a/images/\347\253\231\347\202\271.svg" "b/images/\347\253\231\347\202\271.svg"
new file mode 100644
index 0000000..8cce281
--- /dev/null
+++ "b/images/\347\253\231\347\202\271.svg"
@@ -0,0 +1,11 @@
+<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="36" height="36" rx="18" fill="#FFA39E"/>
+<g clip-path="url(#clip0_647_7172)">
+<path d="M11.7515 17.0488C11.5265 16.8238 11.4001 16.5186 11.4001 16.2004C11.4001 15.8822 11.5265 15.577 11.7515 15.352L17.1515 9.95199C17.3765 9.72702 17.6817 9.60065 17.9999 9.60065C18.3181 9.60065 18.6233 9.72702 18.8483 9.95199L24.2483 15.352C24.4669 15.5783 24.5878 15.8814 24.5851 16.1961C24.5824 16.5107 24.4562 16.8117 24.2337 17.0342C24.0112 17.2567 23.7102 17.3829 23.3956 17.3856C23.0809 17.3883 22.7778 17.2674 22.5515 17.0488L19.1999 13.8004L19.1999 25.2004C19.1999 25.5187 19.0735 25.8239 18.8484 26.0489C18.6234 26.274 18.3181 26.4004 17.9999 26.4004C17.6816 26.4004 17.3764 26.274 17.1514 26.0489C16.9263 25.8239 16.7999 25.5187 16.7999 25.2004L16.7999 13.8004L13.4483 17.0488C13.2233 17.2738 12.9181 17.4001 12.5999 17.4001C12.2817 17.4001 11.9765 17.2738 11.7515 17.0488Z" fill="#F5222D"/>
+</g>
+<defs>
+<clipPath id="clip0_647_7172">
+<rect width="18" height="18" fill="white" transform="translate(9 27) rotate(-90)"/>
+</clipPath>
+</defs>
+</svg>
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..c3ff205
--- /dev/null
+++ b/index.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8" />
+    <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>
+    <title></title>
+    <!--preload-links-->
+    <!--app-context-->
+  </head>
+  <body>
+    <div id="app"><!--app-html--></div>
+    <script type="module" src="/main.js"></script>
+  </body>
+</html>
diff --git a/main.js b/main.js
new file mode 100644
index 0000000..c1a55cd
--- /dev/null
+++ b/main.js
@@ -0,0 +1,26 @@
+import App from './App'
+
+// #ifndef VUE3
+import Vue from 'vue'
+import './uni.promisify.adaptor'
+Vue.config.productionTip = false
+App.mpType = 'app'
+const app = new Vue({
+  ...App
+})
+app.$mount()
+// #endif
+
+// #ifdef VUE3
+
+import { createSSRApp } from 'vue'
+import {Button} from 'antd-mobile-vue-next'
+
+export function createApp() {
+  const app = createSSRApp(App)
+app.use(Button)
+  return {
+    app
+  }
+}
+// #endif
\ No newline at end of file
diff --git a/manifest.json b/manifest.json
new file mode 100644
index 0000000..9655901
--- /dev/null
+++ b/manifest.json
@@ -0,0 +1,76 @@
+{
+    "name" : "鍦扮墰App",
+    "appid" : "__UNI__C988375",
+    "description" : "",
+    "versionName" : "1.1.2",
+    "versionCode" : 112,
+    "transformPx" : false,
+    /* 5+App鐗规湁鐩稿叧 */
+    "app-plus" : {
+        "usingComponents" : true,
+        "nvueStyleCompiler" : "uni-app",
+        "compilerVersion" : 3,
+        "splashscreen" : {
+            "alwaysShowBeforeRender" : true,
+            "waiting" : true,
+            "autoclose" : true,
+            "delay" : 0
+        },
+        /* 妯″潡閰嶇疆 */
+        "modules" : {
+            "Barcode" : {}
+        },
+        /* 搴旂敤鍙戝竷淇℃伅 */
+        "distribute" : {
+            /* android鎵撳寘閰嶇疆 */
+            "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鎵撳寘閰嶇疆 */
+            "ios" : {
+                "dSYMs" : false
+            },
+            /* SDK閰嶇疆 */
+            "sdkConfigs" : {}
+        }
+    },
+    /* 蹇簲鐢ㄧ壒鏈夌浉鍏�*/
+    "quickapp" : {},
+    /* 灏忕▼搴忕壒鏈夌浉鍏�*/
+    "mp-weixin" : {
+        "appid" : "",
+        "setting" : {
+            "urlCheck" : false
+        },
+        "usingComponents" : true
+    },
+    "mp-alipay" : {
+        "usingComponents" : true
+    },
+    "mp-baidu" : {
+        "usingComponents" : true
+    },
+    "mp-toutiao" : {
+        "usingComponents" : true
+    },
+    "uniStatistics" : {
+        "enable" : false
+    },
+    "vueVersion" : "3"
+}
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..9b54f8c
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,3983 @@
+{
+  "name": "鍦扮墰App",
+  "lockfileVersion": 3,
+  "requires": true,
+  "packages": {
+    "": {
+      "dependencies": {
+        "ant-design-vue": "^4.0.0-rc.6",
+        "antd-mobile-vue-next": "^0.1.0-16",
+        "dayjs": "^1.11.13",
+        "fabric": "^6.6.7",
+        "rxjs": "^7.8.2",
+        "uuid": "^11.1.0"
+      },
+      "devDependencies": {
+        "babel-plugin-import": "^1.13.8",
+        "less": "^4.3.0",
+        "less-loader": "^12.3.0"
+      }
+    },
+    "node_modules/@ant-design/colors": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmmirror.com/@ant-design/colors/-/colors-6.0.0.tgz",
+      "integrity": "sha512-qAZRvPzfdWHtfameEGP2Qvuf838NhergR35o+EuVyB5XvSA98xod5r4utvi4TJ3ywmevm290g9nsCG5MryrdWQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@ctrl/tinycolor": "^3.4.0"
+      }
+    },
+    "node_modules/@ant-design/icons-svg": {
+      "version": "4.4.2",
+      "resolved": "https://registry.npmmirror.com/@ant-design/icons-svg/-/icons-svg-4.4.2.tgz",
+      "integrity": "sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA==",
+      "license": "MIT"
+    },
+    "node_modules/@ant-design/icons-vue": {
+      "version": "6.1.0",
+      "resolved": "https://registry.npmmirror.com/@ant-design/icons-vue/-/icons-vue-6.1.0.tgz",
+      "integrity": "sha512-EX6bYm56V+ZrKN7+3MT/ubDkvJ5rK/O2t380WFRflDcVFgsvl3NLH7Wxeau6R8DbrO5jWR6DSTC3B6gYFp77AA==",
+      "license": "MIT",
+      "dependencies": {
+        "@ant-design/colors": "^6.0.0",
+        "@ant-design/icons-svg": "^4.2.1"
+      },
+      "peerDependencies": {
+        "vue": ">=3.0.3"
+      }
+    },
+    "node_modules/@antv/adjust": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmmirror.com/@antv/adjust/-/adjust-0.1.1.tgz",
+      "integrity": "sha512-9FaMOyBlM4AgoRL0b5o0VhEKAYkexBNUrxV8XmpHU/9NBPJONBOB/NZUlQDqxtLItrt91tCfbAuMQmF529UX2Q==",
+      "license": "MIT",
+      "dependencies": {
+        "@antv/util": "~1.3.1"
+      }
+    },
+    "node_modules/@antv/adjust/node_modules/@antv/util": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmmirror.com/@antv/util/-/util-1.3.1.tgz",
+      "integrity": "sha512-cbUta0hIJrKEaW3eKoGarz3Ita+9qUPF2YzTj8A6wds/nNiy20G26ztIWHU+5ThLc13B1n5Ik52LbaCaeg9enA==",
+      "license": "ISC",
+      "dependencies": {
+        "@antv/gl-matrix": "^2.7.1"
+      }
+    },
+    "node_modules/@antv/f2": {
+      "version": "3.8.13",
+      "resolved": "https://registry.npmmirror.com/@antv/f2/-/f2-3.8.13.tgz",
+      "integrity": "sha512-bt8blPrcRIUOkComn593gq9dDLyyrbB5929dEJlKTlLirBWHDEa7xgigE7J1lL7WlnsH9yRxA4WwE1oHJug7EA==",
+      "dependencies": {
+        "@antv/adjust": "~0.1.1",
+        "@antv/scale": "~0.3.3",
+        "@antv/util": "~2.0.6",
+        "@babel/runtime": "^7.7.7",
+        "@types/hammerjs": "^2.0.36",
+        "hammerjs": "^2.0.8",
+        "type-fest": "^0.15.1"
+      }
+    },
+    "node_modules/@antv/gl-matrix": {
+      "version": "2.7.1",
+      "resolved": "https://registry.npmmirror.com/@antv/gl-matrix/-/gl-matrix-2.7.1.tgz",
+      "integrity": "sha512-oOWcVNlpELIKi9x+Mm1Vwbz8pXfkbJKykoCIOJ/dNK79hSIANbpXJ5d3Rra9/wZqK6MC961B7sybFhPlLraT3Q==",
+      "license": "MIT"
+    },
+    "node_modules/@antv/scale": {
+      "version": "0.3.18",
+      "resolved": "https://registry.npmmirror.com/@antv/scale/-/scale-0.3.18.tgz",
+      "integrity": "sha512-GHwE6Lo7S/Q5fgaLPaCsW+CH+3zl4aXpnN1skOiEY0Ue9/u+s2EySv6aDXYkAqs//i0uilMDD/0/4n8caX9U9w==",
+      "license": "MIT",
+      "dependencies": {
+        "@antv/util": "~2.0.3",
+        "fecha": "~4.2.0",
+        "tslib": "^2.0.0"
+      }
+    },
+    "node_modules/@antv/util": {
+      "version": "2.0.17",
+      "resolved": "https://registry.npmmirror.com/@antv/util/-/util-2.0.17.tgz",
+      "integrity": "sha512-o6I9hi5CIUvLGDhth0RxNSFDRwXeywmt6ExR4+RmVAzIi48ps6HUy+svxOCayvrPBN37uE6TAc2KDofRo0nK9Q==",
+      "license": "ISC",
+      "dependencies": {
+        "csstype": "^3.0.8",
+        "tslib": "^2.0.3"
+      }
+    },
+    "node_modules/@babel/code-frame": {
+      "version": "7.27.1",
+      "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.27.1.tgz",
+      "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-validator-identifier": "^7.27.1",
+        "js-tokens": "^4.0.0",
+        "picocolors": "^1.1.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/generator": {
+      "version": "7.27.1",
+      "resolved": "https://registry.npmmirror.com/@babel/generator/-/generator-7.27.1.tgz",
+      "integrity": "sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/parser": "^7.27.1",
+        "@babel/types": "^7.27.1",
+        "@jridgewell/gen-mapping": "^0.3.5",
+        "@jridgewell/trace-mapping": "^0.3.25",
+        "jsesc": "^3.0.2"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-module-imports": {
+      "version": "7.27.1",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz",
+      "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/traverse": "^7.27.1",
+        "@babel/types": "^7.27.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-string-parser": {
+      "version": "7.27.1",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
+      "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-validator-identifier": {
+      "version": "7.27.1",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
+      "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/parser": {
+      "version": "7.27.2",
+      "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.27.2.tgz",
+      "integrity": "sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/types": "^7.27.1"
+      },
+      "bin": {
+        "parser": "bin/babel-parser.js"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@babel/runtime": {
+      "version": "7.27.1",
+      "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.27.1.tgz",
+      "integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/template": {
+      "version": "7.27.2",
+      "resolved": "https://registry.npmmirror.com/@babel/template/-/template-7.27.2.tgz",
+      "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/code-frame": "^7.27.1",
+        "@babel/parser": "^7.27.2",
+        "@babel/types": "^7.27.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/traverse": {
+      "version": "7.27.1",
+      "resolved": "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.27.1.tgz",
+      "integrity": "sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/code-frame": "^7.27.1",
+        "@babel/generator": "^7.27.1",
+        "@babel/parser": "^7.27.1",
+        "@babel/template": "^7.27.1",
+        "@babel/types": "^7.27.1",
+        "debug": "^4.3.1",
+        "globals": "^11.1.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/types": {
+      "version": "7.27.1",
+      "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.27.1.tgz",
+      "integrity": "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-string-parser": "^7.27.1",
+        "@babel/helper-validator-identifier": "^7.27.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@ctrl/tinycolor": {
+      "version": "3.6.1",
+      "resolved": "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz",
+      "integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/@emotion/hash": {
+      "version": "0.9.2",
+      "resolved": "https://registry.npmmirror.com/@emotion/hash/-/hash-0.9.2.tgz",
+      "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==",
+      "license": "MIT"
+    },
+    "node_modules/@emotion/unitless": {
+      "version": "0.8.1",
+      "resolved": "https://registry.npmmirror.com/@emotion/unitless/-/unitless-0.8.1.tgz",
+      "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==",
+      "license": "MIT"
+    },
+    "node_modules/@isaacs/cliui": {
+      "version": "8.0.2",
+      "resolved": "https://registry.npmmirror.com/@isaacs/cliui/-/cliui-8.0.2.tgz",
+      "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+      "license": "ISC",
+      "dependencies": {
+        "string-width": "^5.1.2",
+        "string-width-cjs": "npm:string-width@^4.2.0",
+        "strip-ansi": "^7.0.1",
+        "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+        "wrap-ansi": "^8.1.0",
+        "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@jridgewell/gen-mapping": {
+      "version": "0.3.8",
+      "resolved": "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
+      "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@jridgewell/set-array": "^1.2.1",
+        "@jridgewell/sourcemap-codec": "^1.4.10",
+        "@jridgewell/trace-mapping": "^0.3.24"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/resolve-uri": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+      "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/set-array": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmmirror.com/@jridgewell/set-array/-/set-array-1.2.1.tgz",
+      "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/sourcemap-codec": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
+      "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
+      "license": "MIT"
+    },
+    "node_modules/@jridgewell/trace-mapping": {
+      "version": "0.3.25",
+      "resolved": "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
+      "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@jridgewell/resolve-uri": "^3.1.0",
+        "@jridgewell/sourcemap-codec": "^1.4.14"
+      }
+    },
+    "node_modules/@mapbox/node-pre-gyp": {
+      "version": "1.0.11",
+      "resolved": "https://registry.npmmirror.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz",
+      "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==",
+      "license": "BSD-3-Clause",
+      "optional": true,
+      "dependencies": {
+        "detect-libc": "^2.0.0",
+        "https-proxy-agent": "^5.0.0",
+        "make-dir": "^3.1.0",
+        "node-fetch": "^2.6.7",
+        "nopt": "^5.0.0",
+        "npmlog": "^5.0.1",
+        "rimraf": "^3.0.2",
+        "semver": "^7.3.5",
+        "tar": "^6.1.11"
+      },
+      "bin": {
+        "node-pre-gyp": "bin/node-pre-gyp"
+      }
+    },
+    "node_modules/@mapbox/node-pre-gyp/node_modules/abbrev": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmmirror.com/abbrev/-/abbrev-1.1.1.tgz",
+      "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
+      "license": "ISC",
+      "optional": true
+    },
+    "node_modules/@mapbox/node-pre-gyp/node_modules/nopt": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmmirror.com/nopt/-/nopt-5.0.0.tgz",
+      "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
+      "license": "ISC",
+      "optional": true,
+      "dependencies": {
+        "abbrev": "1"
+      },
+      "bin": {
+        "nopt": "bin/nopt.js"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/@one-ini/wasm": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmmirror.com/@one-ini/wasm/-/wasm-0.1.1.tgz",
+      "integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==",
+      "license": "MIT"
+    },
+    "node_modules/@pkgjs/parseargs": {
+      "version": "0.11.0",
+      "resolved": "https://registry.npmmirror.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
+      "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
+      "license": "MIT",
+      "optional": true,
+      "engines": {
+        "node": ">=14"
+      }
+    },
+    "node_modules/@rollup/pluginutils": {
+      "version": "4.2.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/pluginutils/-/pluginutils-4.2.1.tgz",
+      "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==",
+      "license": "MIT",
+      "dependencies": {
+        "estree-walker": "^2.0.1",
+        "picomatch": "^2.2.2"
+      },
+      "engines": {
+        "node": ">= 8.0.0"
+      }
+    },
+    "node_modules/@rollup/rollup-android-arm-eabi": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.41.1.tgz",
+      "integrity": "sha512-NELNvyEWZ6R9QMkiytB4/L4zSEaBC03KIXEghptLGLZWJ6VPrL63ooZQCOnlx36aQPGhzuOMwDerC1Eb2VmrLw==",
+      "cpu": [
+        "arm"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "peer": true
+    },
+    "node_modules/@rollup/rollup-android-arm64": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.41.1.tgz",
+      "integrity": "sha512-DXdQe1BJ6TK47ukAoZLehRHhfKnKg9BjnQYUu9gzhI8Mwa1d2fzxA1aw2JixHVl403bwp1+/o/NhhHtxWJBgEA==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "peer": true
+    },
+    "node_modules/@rollup/rollup-darwin-arm64": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.41.1.tgz",
+      "integrity": "sha512-5afxvwszzdulsU2w8JKWwY8/sJOLPzf0e1bFuvcW5h9zsEg+RQAojdW0ux2zyYAz7R8HvvzKCjLNJhVq965U7w==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "peer": true
+    },
+    "node_modules/@rollup/rollup-darwin-x64": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.41.1.tgz",
+      "integrity": "sha512-egpJACny8QOdHNNMZKf8xY0Is6gIMz+tuqXlusxquWu3F833DcMwmGM7WlvCO9sB3OsPjdC4U0wHw5FabzCGZg==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "peer": true
+    },
+    "node_modules/@rollup/rollup-freebsd-arm64": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.41.1.tgz",
+      "integrity": "sha512-DBVMZH5vbjgRk3r0OzgjS38z+atlupJ7xfKIDJdZZL6sM6wjfDNo64aowcLPKIx7LMQi8vybB56uh1Ftck/Atg==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "peer": true
+    },
+    "node_modules/@rollup/rollup-freebsd-x64": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.41.1.tgz",
+      "integrity": "sha512-3FkydeohozEskBxNWEIbPfOE0aqQgB6ttTkJ159uWOFn42VLyfAiyD9UK5mhu+ItWzft60DycIN1Xdgiy8o/SA==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "peer": true
+    },
+    "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.41.1.tgz",
+      "integrity": "sha512-wC53ZNDgt0pqx5xCAgNunkTzFE8GTgdZ9EwYGVcg+jEjJdZGtq9xPjDnFgfFozQI/Xm1mh+D9YlYtl+ueswNEg==",
+      "cpu": [
+        "arm"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "peer": true
+    },
+    "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.41.1.tgz",
+      "integrity": "sha512-jwKCca1gbZkZLhLRtsrka5N8sFAaxrGz/7wRJ8Wwvq3jug7toO21vWlViihG85ei7uJTpzbXZRcORotE+xyrLA==",
+      "cpu": [
+        "arm"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "peer": true
+    },
+    "node_modules/@rollup/rollup-linux-arm64-gnu": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.41.1.tgz",
+      "integrity": "sha512-g0UBcNknsmmNQ8V2d/zD2P7WWfJKU0F1nu0k5pW4rvdb+BIqMm8ToluW/eeRmxCared5dD76lS04uL4UaNgpNA==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "peer": true
+    },
+    "node_modules/@rollup/rollup-linux-arm64-musl": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.41.1.tgz",
+      "integrity": "sha512-XZpeGB5TKEZWzIrj7sXr+BEaSgo/ma/kCgrZgL0oo5qdB1JlTzIYQKel/RmhT6vMAvOdM2teYlAaOGJpJ9lahg==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "peer": true
+    },
+    "node_modules/@rollup/rollup-linux-loongarch64-gnu": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.41.1.tgz",
+      "integrity": "sha512-bkCfDJ4qzWfFRCNt5RVV4DOw6KEgFTUZi2r2RuYhGWC8WhCA8lCAJhDeAmrM/fdiAH54m0mA0Vk2FGRPyzI+tw==",
+      "cpu": [
+        "loong64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "peer": true
+    },
+    "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.41.1.tgz",
+      "integrity": "sha512-3mr3Xm+gvMX+/8EKogIZSIEF0WUu0HL9di+YWlJpO8CQBnoLAEL/roTCxuLncEdgcfJcvA4UMOf+2dnjl4Ut1A==",
+      "cpu": [
+        "ppc64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "peer": true
+    },
+    "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.41.1.tgz",
+      "integrity": "sha512-3rwCIh6MQ1LGrvKJitQjZFuQnT2wxfU+ivhNBzmxXTXPllewOF7JR1s2vMX/tWtUYFgphygxjqMl76q4aMotGw==",
+      "cpu": [
+        "riscv64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "peer": true
+    },
+    "node_modules/@rollup/rollup-linux-riscv64-musl": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.41.1.tgz",
+      "integrity": "sha512-LdIUOb3gvfmpkgFZuccNa2uYiqtgZAz3PTzjuM5bH3nvuy9ty6RGc/Q0+HDFrHrizJGVpjnTZ1yS5TNNjFlklw==",
+      "cpu": [
+        "riscv64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "peer": true
+    },
+    "node_modules/@rollup/rollup-linux-s390x-gnu": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.41.1.tgz",
+      "integrity": "sha512-oIE6M8WC9ma6xYqjvPhzZYk6NbobIURvP/lEbh7FWplcMO6gn7MM2yHKA1eC/GvYwzNKK/1LYgqzdkZ8YFxR8g==",
+      "cpu": [
+        "s390x"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "peer": true
+    },
+    "node_modules/@rollup/rollup-linux-x64-gnu": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.41.1.tgz",
+      "integrity": "sha512-cWBOvayNvA+SyeQMp79BHPK8ws6sHSsYnK5zDcsC3Hsxr1dgTABKjMnMslPq1DvZIp6uO7kIWhiGwaTdR4Og9A==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "peer": true
+    },
+    "node_modules/@rollup/rollup-linux-x64-musl": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.41.1.tgz",
+      "integrity": "sha512-y5CbN44M+pUCdGDlZFzGGBSKCA4A/J2ZH4edTYSSxFg7ce1Xt3GtydbVKWLlzL+INfFIZAEg1ZV6hh9+QQf9YQ==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "peer": true
+    },
+    "node_modules/@rollup/rollup-win32-arm64-msvc": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.41.1.tgz",
+      "integrity": "sha512-lZkCxIrjlJlMt1dLO/FbpZbzt6J/A8p4DnqzSa4PWqPEUUUnzXLeki/iyPLfV0BmHItlYgHUqJe+3KiyydmiNQ==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "peer": true
+    },
+    "node_modules/@rollup/rollup-win32-ia32-msvc": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.41.1.tgz",
+      "integrity": "sha512-+psFT9+pIh2iuGsxFYYa/LhS5MFKmuivRsx9iPJWNSGbh2XVEjk90fmpUEjCnILPEPJnikAU6SFDiEUyOv90Pg==",
+      "cpu": [
+        "ia32"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "peer": true
+    },
+    "node_modules/@rollup/rollup-win32-x64-msvc": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.41.1.tgz",
+      "integrity": "sha512-Wq2zpapRYLfi4aKxf2Xff0tN+7slj2d4R87WEzqw7ZLsVvO5zwYCIuEGSZYiK41+GlwUo1HiR+GdkLEJnCKTCw==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "peer": true
+    },
+    "node_modules/@simonwep/pickr": {
+      "version": "1.8.2",
+      "resolved": "https://registry.npmmirror.com/@simonwep/pickr/-/pickr-1.8.2.tgz",
+      "integrity": "sha512-/l5w8BIkrpP6n1xsetx9MWPWlU6OblN5YgZZphxan0Tq4BByTCETL6lyIeY8lagalS2Nbt4F2W034KHLIiunKA==",
+      "license": "MIT",
+      "dependencies": {
+        "core-js": "^3.15.1",
+        "nanopop": "^2.1.0"
+      }
+    },
+    "node_modules/@tootallnate/once": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/@tootallnate/once/-/once-2.0.0.tgz",
+      "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==",
+      "license": "MIT",
+      "optional": true,
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@types/estree": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.7.tgz",
+      "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==",
+      "license": "MIT",
+      "peer": true
+    },
+    "node_modules/@types/hammerjs": {
+      "version": "2.0.46",
+      "resolved": "https://registry.npmmirror.com/@types/hammerjs/-/hammerjs-2.0.46.tgz",
+      "integrity": "sha512-ynRvcq6wvqexJ9brDMS4BnBLzmr0e14d6ZJTEShTBWKymQiHwlAyGu0ZPEFI2Fh1U53F7tN9ufClWM5KvqkKOw==",
+      "license": "MIT"
+    },
+    "node_modules/@vue/compiler-core": {
+      "version": "3.5.14",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.14.tgz",
+      "integrity": "sha512-k7qMHMbKvoCXIxPhquKQVw3Twid3Kg4s7+oYURxLGRd56LiuHJVrvFKI4fm2AM3c8apqODPfVJGoh8nePbXMRA==",
+      "license": "MIT",
+      "peer": true,
+      "dependencies": {
+        "@babel/parser": "^7.27.2",
+        "@vue/shared": "3.5.14",
+        "entities": "^4.5.0",
+        "estree-walker": "^2.0.2",
+        "source-map-js": "^1.2.1"
+      }
+    },
+    "node_modules/@vue/compiler-dom": {
+      "version": "3.5.14",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.14.tgz",
+      "integrity": "sha512-1aOCSqxGOea5I80U2hQJvXYpPm/aXo95xL/m/mMhgyPUsKe9jhjwWpziNAw7tYRnbz1I61rd9Mld4W9KmmRoug==",
+      "license": "MIT",
+      "peer": true,
+      "dependencies": {
+        "@vue/compiler-core": "3.5.14",
+        "@vue/shared": "3.5.14"
+      }
+    },
+    "node_modules/@vue/compiler-sfc": {
+      "version": "3.5.14",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.14.tgz",
+      "integrity": "sha512-9T6m/9mMr81Lj58JpzsiSIjBgv2LiVoWjIVa7kuXHICUi8LiDSIotMpPRXYJsXKqyARrzjT24NAwttrMnMaCXA==",
+      "license": "MIT",
+      "peer": true,
+      "dependencies": {
+        "@babel/parser": "^7.27.2",
+        "@vue/compiler-core": "3.5.14",
+        "@vue/compiler-dom": "3.5.14",
+        "@vue/compiler-ssr": "3.5.14",
+        "@vue/shared": "3.5.14",
+        "estree-walker": "^2.0.2",
+        "magic-string": "^0.30.17",
+        "postcss": "^8.5.3",
+        "source-map-js": "^1.2.1"
+      }
+    },
+    "node_modules/@vue/compiler-ssr": {
+      "version": "3.5.14",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.14.tgz",
+      "integrity": "sha512-Y0G7PcBxr1yllnHuS/NxNCSPWnRGH4Ogrp0tsLA5QemDZuJLs99YjAKQ7KqkHE0vCg4QTKlQzXLKCMF7WPSl7Q==",
+      "license": "MIT",
+      "peer": true,
+      "dependencies": {
+        "@vue/compiler-dom": "3.5.14",
+        "@vue/shared": "3.5.14"
+      }
+    },
+    "node_modules/@vue/reactivity": {
+      "version": "3.5.14",
+      "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.14.tgz",
+      "integrity": "sha512-7cK1Hp343Fu/SUCCO52vCabjvsYu7ZkOqyYu7bXV9P2yyfjUMUXHZafEbq244sP7gf+EZEz+77QixBTuEqkQQw==",
+      "license": "MIT",
+      "peer": true,
+      "dependencies": {
+        "@vue/shared": "3.5.14"
+      }
+    },
+    "node_modules/@vue/runtime-core": {
+      "version": "3.5.14",
+      "resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.14.tgz",
+      "integrity": "sha512-w9JWEANwHXNgieAhxPpEpJa+0V5G0hz3NmjAZwlOebtfKyp2hKxKF0+qSh0Xs6/PhfGihuSdqMprMVcQU/E6ag==",
+      "license": "MIT",
+      "peer": true,
+      "dependencies": {
+        "@vue/reactivity": "3.5.14",
+        "@vue/shared": "3.5.14"
+      }
+    },
+    "node_modules/@vue/runtime-dom": {
+      "version": "3.5.14",
+      "resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.14.tgz",
+      "integrity": "sha512-lCfR++IakeI35TVR80QgOelsUIdcKjd65rWAMfdSlCYnaEY5t3hYwru7vvcWaqmrK+LpI7ZDDYiGU5V3xjMacw==",
+      "license": "MIT",
+      "peer": true,
+      "dependencies": {
+        "@vue/reactivity": "3.5.14",
+        "@vue/runtime-core": "3.5.14",
+        "@vue/shared": "3.5.14",
+        "csstype": "^3.1.3"
+      }
+    },
+    "node_modules/@vue/server-renderer": {
+      "version": "3.5.14",
+      "resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.14.tgz",
+      "integrity": "sha512-Rf/ISLqokIvcySIYnv3tNWq40PLpNLDLSJwwVWzG6MNtyIhfbcrAxo5ZL9nARJhqjZyWWa40oRb2IDuejeuv6w==",
+      "license": "MIT",
+      "peer": true,
+      "dependencies": {
+        "@vue/compiler-ssr": "3.5.14",
+        "@vue/shared": "3.5.14"
+      },
+      "peerDependencies": {
+        "vue": "3.5.14"
+      }
+    },
+    "node_modules/@vue/shared": {
+      "version": "3.5.14",
+      "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.14.tgz",
+      "integrity": "sha512-oXTwNxVfc9EtP1zzXAlSlgARLXNC84frFYkS0HHz0h3E4WZSP9sywqjqzGCP9Y34M8ipNmd380pVgmMuwELDyQ==",
+      "license": "MIT",
+      "peer": true
+    },
+    "node_modules/abab": {
+      "version": "2.0.6",
+      "resolved": "https://registry.npmmirror.com/abab/-/abab-2.0.6.tgz",
+      "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==",
+      "deprecated": "Use your platform's native atob() and btoa() methods instead",
+      "license": "BSD-3-Clause",
+      "optional": true
+    },
+    "node_modules/abbrev": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/abbrev/-/abbrev-2.0.0.tgz",
+      "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==",
+      "license": "ISC",
+      "engines": {
+        "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+      }
+    },
+    "node_modules/acorn": {
+      "version": "8.14.1",
+      "resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.14.1.tgz",
+      "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
+      "license": "MIT",
+      "optional": true,
+      "bin": {
+        "acorn": "bin/acorn"
+      },
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
+    "node_modules/acorn-globals": {
+      "version": "7.0.1",
+      "resolved": "https://registry.npmmirror.com/acorn-globals/-/acorn-globals-7.0.1.tgz",
+      "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "acorn": "^8.1.0",
+        "acorn-walk": "^8.0.2"
+      }
+    },
+    "node_modules/acorn-walk": {
+      "version": "8.3.4",
+      "resolved": "https://registry.npmmirror.com/acorn-walk/-/acorn-walk-8.3.4.tgz",
+      "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "acorn": "^8.11.0"
+      },
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
+    "node_modules/agent-base": {
+      "version": "6.0.2",
+      "resolved": "https://registry.npmmirror.com/agent-base/-/agent-base-6.0.2.tgz",
+      "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "debug": "4"
+      },
+      "engines": {
+        "node": ">= 6.0.0"
+      }
+    },
+    "node_modules/ansi-regex": {
+      "version": "6.1.0",
+      "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.1.0.tgz",
+      "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+      }
+    },
+    "node_modules/ansi-styles": {
+      "version": "6.2.1",
+      "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.2.1.tgz",
+      "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+      }
+    },
+    "node_modules/ant-design-vue": {
+      "version": "4.0.0-rc.6",
+      "resolved": "https://registry.npmmirror.com/ant-design-vue/-/ant-design-vue-4.0.0-rc.6.tgz",
+      "integrity": "sha512-j+GAhgC1p1+nmQVbaEeY2miZ1h+8jBLlxTESX93MwcshVaYTkZNhiyddtl92VvEDJTedzuX+1oT3TP5wG/+tHg==",
+      "license": "MIT",
+      "dependencies": {
+        "@ant-design/colors": "^6.0.0",
+        "@ant-design/icons-vue": "^6.1.0",
+        "@babel/runtime": "^7.10.5",
+        "@ctrl/tinycolor": "^3.5.0",
+        "@emotion/hash": "^0.9.0",
+        "@emotion/unitless": "^0.8.0",
+        "@simonwep/pickr": "~1.8.0",
+        "array-tree-filter": "^2.1.0",
+        "async-validator": "^4.0.0",
+        "csstype": "^3.1.1",
+        "dayjs": "^1.10.5",
+        "dom-align": "^1.12.1",
+        "dom-scroll-into-view": "^2.0.0",
+        "lodash": "^4.17.21",
+        "lodash-es": "^4.17.15",
+        "resize-observer-polyfill": "^1.5.1",
+        "scroll-into-view-if-needed": "^2.2.25",
+        "shallow-equal": "^1.0.0",
+        "stylis": "^4.1.3",
+        "throttle-debounce": "^5.0.0",
+        "vue-types": "^3.0.0",
+        "warning": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=12.22.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/ant-design-vue"
+      },
+      "peerDependencies": {
+        "vue": ">=3.2.0"
+      }
+    },
+    "node_modules/antd-mobile-vue-next": {
+      "version": "0.1.0-16",
+      "resolved": "https://registry.npmmirror.com/antd-mobile-vue-next/-/antd-mobile-vue-next-0.1.0-16.tgz",
+      "integrity": "sha512-k5qi68So6Rye0CBa4l6orxxFukWDtn656P6q/KyAjmJEjBVRbGO2jfEW2b8PVh0nFTipcyVS/hygn1K34zjfDw==",
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@antv/f2": "^3.7.7",
+        "async-validator": "^4.0.1",
+        "classnames": "^2.2.6",
+        "cssbeautify": "^0.3.1",
+        "debounce": "^1.2.0",
+        "exenv": "^1.2.2",
+        "fs": "0.0.1-security",
+        "html": "^1.0.0",
+        "js-beautify": "^1.9.1",
+        "lodash.clonedeep": "^4.5.0",
+        "lodash.debounce": "^4.0.8",
+        "lodash.isequal": "^4.5.0",
+        "lodash.merge": "^4.6.2",
+        "normalize.css": "^8.0.1",
+        "omit.js": "^1.0.2",
+        "raf": "^3.4.1",
+        "rollup-plugin-typescript2": "^0.30.0",
+        "shallowequal": "^1.1.0"
+      }
+    },
+    "node_modules/aproba": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/aproba/-/aproba-2.0.0.tgz",
+      "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==",
+      "license": "ISC",
+      "optional": true
+    },
+    "node_modules/are-we-there-yet": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz",
+      "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==",
+      "deprecated": "This package is no longer supported.",
+      "license": "ISC",
+      "optional": true,
+      "dependencies": {
+        "delegates": "^1.0.0",
+        "readable-stream": "^3.6.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/are-we-there-yet/node_modules/readable-stream": {
+      "version": "3.6.2",
+      "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz",
+      "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "inherits": "^2.0.3",
+        "string_decoder": "^1.1.1",
+        "util-deprecate": "^1.0.1"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/array-tree-filter": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/array-tree-filter/-/array-tree-filter-2.1.0.tgz",
+      "integrity": "sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==",
+      "license": "MIT"
+    },
+    "node_modules/async-validator": {
+      "version": "4.2.5",
+      "resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-4.2.5.tgz",
+      "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==",
+      "license": "MIT"
+    },
+    "node_modules/asynckit": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz",
+      "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+      "license": "MIT",
+      "optional": true
+    },
+    "node_modules/babel-plugin-import": {
+      "version": "1.13.8",
+      "resolved": "https://registry.npmmirror.com/babel-plugin-import/-/babel-plugin-import-1.13.8.tgz",
+      "integrity": "sha512-36babpjra5m3gca44V6tSTomeBlPA7cHUynrE2WiQIm3rEGD9xy28MKsx5IdO45EbnpJY7Jrgd00C6Dwt/l/2Q==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-module-imports": "^7.0.0"
+      }
+    },
+    "node_modules/babel-runtime": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmmirror.com/babel-runtime/-/babel-runtime-6.26.0.tgz",
+      "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==",
+      "license": "MIT",
+      "dependencies": {
+        "core-js": "^2.4.0",
+        "regenerator-runtime": "^0.11.0"
+      }
+    },
+    "node_modules/babel-runtime/node_modules/core-js": {
+      "version": "2.6.12",
+      "resolved": "https://registry.npmmirror.com/core-js/-/core-js-2.6.12.tgz",
+      "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==",
+      "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.",
+      "hasInstallScript": true,
+      "license": "MIT"
+    },
+    "node_modules/balanced-match": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz",
+      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+      "license": "MIT"
+    },
+    "node_modules/brace-expansion": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz",
+      "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+      "license": "MIT",
+      "dependencies": {
+        "balanced-match": "^1.0.0"
+      }
+    },
+    "node_modules/buffer-from": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz",
+      "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+      "license": "MIT"
+    },
+    "node_modules/call-bind-apply-helpers": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+      "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "es-errors": "^1.3.0",
+        "function-bind": "^1.1.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/canvas": {
+      "version": "2.11.2",
+      "resolved": "https://registry.npmmirror.com/canvas/-/canvas-2.11.2.tgz",
+      "integrity": "sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==",
+      "hasInstallScript": true,
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "@mapbox/node-pre-gyp": "^1.0.0",
+        "nan": "^2.17.0",
+        "simple-get": "^3.0.3"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/chownr": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/chownr/-/chownr-2.0.0.tgz",
+      "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
+      "license": "ISC",
+      "optional": true,
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/classnames": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmmirror.com/classnames/-/classnames-2.5.1.tgz",
+      "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==",
+      "license": "MIT"
+    },
+    "node_modules/color-convert": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz",
+      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+      "license": "MIT",
+      "dependencies": {
+        "color-name": "~1.1.4"
+      },
+      "engines": {
+        "node": ">=7.0.0"
+      }
+    },
+    "node_modules/color-name": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz",
+      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+      "license": "MIT"
+    },
+    "node_modules/color-support": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmmirror.com/color-support/-/color-support-1.1.3.tgz",
+      "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
+      "license": "ISC",
+      "optional": true,
+      "bin": {
+        "color-support": "bin.js"
+      }
+    },
+    "node_modules/combined-stream": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz",
+      "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "delayed-stream": "~1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/commander": {
+      "version": "10.0.1",
+      "resolved": "https://registry.npmmirror.com/commander/-/commander-10.0.1.tgz",
+      "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=14"
+      }
+    },
+    "node_modules/commondir": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/commondir/-/commondir-1.0.1.tgz",
+      "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==",
+      "license": "MIT"
+    },
+    "node_modules/compute-scroll-into-view": {
+      "version": "1.0.20",
+      "resolved": "https://registry.npmmirror.com/compute-scroll-into-view/-/compute-scroll-into-view-1.0.20.tgz",
+      "integrity": "sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==",
+      "license": "MIT"
+    },
+    "node_modules/concat-map": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz",
+      "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+      "license": "MIT",
+      "optional": true
+    },
+    "node_modules/concat-stream": {
+      "version": "1.6.2",
+      "resolved": "https://registry.npmmirror.com/concat-stream/-/concat-stream-1.6.2.tgz",
+      "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
+      "engines": [
+        "node >= 0.8"
+      ],
+      "license": "MIT",
+      "dependencies": {
+        "buffer-from": "^1.0.0",
+        "inherits": "^2.0.3",
+        "readable-stream": "^2.2.2",
+        "typedarray": "^0.0.6"
+      }
+    },
+    "node_modules/config-chain": {
+      "version": "1.1.13",
+      "resolved": "https://registry.npmmirror.com/config-chain/-/config-chain-1.1.13.tgz",
+      "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==",
+      "license": "MIT",
+      "dependencies": {
+        "ini": "^1.3.4",
+        "proto-list": "~1.2.1"
+      }
+    },
+    "node_modules/console-control-strings": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmmirror.com/console-control-strings/-/console-control-strings-1.1.0.tgz",
+      "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==",
+      "license": "ISC",
+      "optional": true
+    },
+    "node_modules/copy-anything": {
+      "version": "2.0.6",
+      "resolved": "https://registry.npmmirror.com/copy-anything/-/copy-anything-2.0.6.tgz",
+      "integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "is-what": "^3.14.1"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/mesqueeb"
+      }
+    },
+    "node_modules/core-js": {
+      "version": "3.42.0",
+      "resolved": "https://registry.npmmirror.com/core-js/-/core-js-3.42.0.tgz",
+      "integrity": "sha512-Sz4PP4ZA+Rq4II21qkNqOEDTDrCvcANId3xpIgB34NDkWc3UduWj2dqEtN9yZIq8Dk3HyPI33x9sqqU5C8sr0g==",
+      "hasInstallScript": true,
+      "license": "MIT",
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/core-js"
+      }
+    },
+    "node_modules/core-util-is": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/core-util-is/-/core-util-is-1.0.3.tgz",
+      "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
+      "license": "MIT"
+    },
+    "node_modules/cross-spawn": {
+      "version": "7.0.6",
+      "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.6.tgz",
+      "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+      "license": "MIT",
+      "dependencies": {
+        "path-key": "^3.1.0",
+        "shebang-command": "^2.0.0",
+        "which": "^2.0.1"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/cssbeautify": {
+      "version": "0.3.1",
+      "resolved": "https://registry.npmmirror.com/cssbeautify/-/cssbeautify-0.3.1.tgz",
+      "integrity": "sha512-ljnSOCOiMbklF+dwPbpooyB78foId02vUrTDogWzu6ca2DCNB7Kc/BHEGBnYOlUYtwXvSW0mWTwaiO2pwFIoRg==",
+      "bin": {
+        "cssbeautify": "bin/cssbeautify"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/cssom": {
+      "version": "0.5.0",
+      "resolved": "https://registry.npmmirror.com/cssom/-/cssom-0.5.0.tgz",
+      "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==",
+      "license": "MIT",
+      "optional": true
+    },
+    "node_modules/cssstyle": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmmirror.com/cssstyle/-/cssstyle-2.3.0.tgz",
+      "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "cssom": "~0.3.6"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/cssstyle/node_modules/cssom": {
+      "version": "0.3.8",
+      "resolved": "https://registry.npmmirror.com/cssom/-/cssom-0.3.8.tgz",
+      "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==",
+      "license": "MIT",
+      "optional": true
+    },
+    "node_modules/csstype": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.1.3.tgz",
+      "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
+      "license": "MIT"
+    },
+    "node_modules/data-urls": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmmirror.com/data-urls/-/data-urls-3.0.2.tgz",
+      "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "abab": "^2.0.6",
+        "whatwg-mimetype": "^3.0.0",
+        "whatwg-url": "^11.0.0"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/dayjs": {
+      "version": "1.11.13",
+      "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.13.tgz",
+      "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==",
+      "license": "MIT"
+    },
+    "node_modules/debounce": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmmirror.com/debounce/-/debounce-1.2.1.tgz",
+      "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==",
+      "license": "MIT"
+    },
+    "node_modules/debug": {
+      "version": "4.4.1",
+      "resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.1.tgz",
+      "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+      "devOptional": true,
+      "license": "MIT",
+      "dependencies": {
+        "ms": "^2.1.3"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependenciesMeta": {
+        "supports-color": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/decimal.js": {
+      "version": "10.5.0",
+      "resolved": "https://registry.npmmirror.com/decimal.js/-/decimal.js-10.5.0.tgz",
+      "integrity": "sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==",
+      "license": "MIT",
+      "optional": true
+    },
+    "node_modules/decompress-response": {
+      "version": "4.2.1",
+      "resolved": "https://registry.npmmirror.com/decompress-response/-/decompress-response-4.2.1.tgz",
+      "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "mimic-response": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/delayed-stream": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz",
+      "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+      "license": "MIT",
+      "optional": true,
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
+    "node_modules/delegates": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/delegates/-/delegates-1.0.0.tgz",
+      "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==",
+      "license": "MIT",
+      "optional": true
+    },
+    "node_modules/detect-libc": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-2.0.4.tgz",
+      "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==",
+      "license": "Apache-2.0",
+      "optional": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/dom-align": {
+      "version": "1.12.4",
+      "resolved": "https://registry.npmmirror.com/dom-align/-/dom-align-1.12.4.tgz",
+      "integrity": "sha512-R8LUSEay/68zE5c8/3BDxiTEvgb4xZTF0RKmAHfiEVN3klfIpXfi2/QCoiWPccVQ0J/ZGdz9OjzL4uJEP/MRAw==",
+      "license": "MIT"
+    },
+    "node_modules/dom-scroll-into-view": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmmirror.com/dom-scroll-into-view/-/dom-scroll-into-view-2.0.1.tgz",
+      "integrity": "sha512-bvVTQe1lfaUr1oFzZX80ce9KLDlZ3iU+XGNE/bz9HnGdklTieqsbmsLHe+rT2XWqopvL0PckkYqN7ksmm5pe3w==",
+      "license": "MIT"
+    },
+    "node_modules/domexception": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmmirror.com/domexception/-/domexception-4.0.0.tgz",
+      "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==",
+      "deprecated": "Use your platform's native DOMException instead",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "webidl-conversions": "^7.0.0"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/dunder-proto": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz",
+      "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "call-bind-apply-helpers": "^1.0.1",
+        "es-errors": "^1.3.0",
+        "gopd": "^1.2.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/eastasianwidth": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmmirror.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+      "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
+      "license": "MIT"
+    },
+    "node_modules/editorconfig": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmmirror.com/editorconfig/-/editorconfig-1.0.4.tgz",
+      "integrity": "sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==",
+      "license": "MIT",
+      "dependencies": {
+        "@one-ini/wasm": "0.1.1",
+        "commander": "^10.0.0",
+        "minimatch": "9.0.1",
+        "semver": "^7.5.3"
+      },
+      "bin": {
+        "editorconfig": "bin/editorconfig"
+      },
+      "engines": {
+        "node": ">=14"
+      }
+    },
+    "node_modules/emoji-regex": {
+      "version": "9.2.2",
+      "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-9.2.2.tgz",
+      "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+      "license": "MIT"
+    },
+    "node_modules/entities": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmmirror.com/entities/-/entities-4.5.0.tgz",
+      "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+      "license": "BSD-2-Clause",
+      "peer": true,
+      "engines": {
+        "node": ">=0.12"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/entities?sponsor=1"
+      }
+    },
+    "node_modules/errno": {
+      "version": "0.1.8",
+      "resolved": "https://registry.npmmirror.com/errno/-/errno-0.1.8.tgz",
+      "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==",
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "prr": "~1.0.1"
+      },
+      "bin": {
+        "errno": "cli.js"
+      }
+    },
+    "node_modules/es-define-property": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz",
+      "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+      "license": "MIT",
+      "optional": true,
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-errors": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz",
+      "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+      "license": "MIT",
+      "optional": true,
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-object-atoms": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
+      "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "es-errors": "^1.3.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-set-tostringtag": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+      "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "es-errors": "^1.3.0",
+        "get-intrinsic": "^1.2.6",
+        "has-tostringtag": "^1.0.2",
+        "hasown": "^2.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/escodegen": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/escodegen/-/escodegen-2.1.0.tgz",
+      "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==",
+      "license": "BSD-2-Clause",
+      "optional": true,
+      "dependencies": {
+        "esprima": "^4.0.1",
+        "estraverse": "^5.2.0",
+        "esutils": "^2.0.2"
+      },
+      "bin": {
+        "escodegen": "bin/escodegen.js",
+        "esgenerate": "bin/esgenerate.js"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "optionalDependencies": {
+        "source-map": "~0.6.1"
+      }
+    },
+    "node_modules/esprima": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmmirror.com/esprima/-/esprima-4.0.1.tgz",
+      "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+      "license": "BSD-2-Clause",
+      "optional": true,
+      "bin": {
+        "esparse": "bin/esparse.js",
+        "esvalidate": "bin/esvalidate.js"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/estraverse": {
+      "version": "5.3.0",
+      "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz",
+      "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+      "license": "BSD-2-Clause",
+      "optional": true,
+      "engines": {
+        "node": ">=4.0"
+      }
+    },
+    "node_modules/estree-walker": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz",
+      "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
+      "license": "MIT"
+    },
+    "node_modules/esutils": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmmirror.com/esutils/-/esutils-2.0.3.tgz",
+      "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+      "license": "BSD-2-Clause",
+      "optional": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/exenv": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmmirror.com/exenv/-/exenv-1.2.2.tgz",
+      "integrity": "sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw==",
+      "license": "BSD-3-Clause"
+    },
+    "node_modules/fabric": {
+      "version": "6.6.7",
+      "resolved": "https://registry.npmmirror.com/fabric/-/fabric-6.6.7.tgz",
+      "integrity": "sha512-5wLf0F9PouwfgG11nsPs7mSVIGTRG3R3I4fCE9iT8fpQyG8OKHSe1N6/KVGRgAgrQN2AAh2xF+K/Gv5UVfkqlQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=16.20.0"
+      },
+      "optionalDependencies": {
+        "canvas": "^2.11.2",
+        "jsdom": "^20.0.1"
+      }
+    },
+    "node_modules/fecha": {
+      "version": "4.2.3",
+      "resolved": "https://registry.npmmirror.com/fecha/-/fecha-4.2.3.tgz",
+      "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==",
+      "license": "MIT"
+    },
+    "node_modules/find-cache-dir": {
+      "version": "3.3.2",
+      "resolved": "https://registry.npmmirror.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz",
+      "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==",
+      "license": "MIT",
+      "dependencies": {
+        "commondir": "^1.0.1",
+        "make-dir": "^3.0.2",
+        "pkg-dir": "^4.1.0"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/avajs/find-cache-dir?sponsor=1"
+      }
+    },
+    "node_modules/find-up": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmmirror.com/find-up/-/find-up-4.1.0.tgz",
+      "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+      "license": "MIT",
+      "dependencies": {
+        "locate-path": "^5.0.0",
+        "path-exists": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/foreground-child": {
+      "version": "3.3.1",
+      "resolved": "https://registry.npmmirror.com/foreground-child/-/foreground-child-3.3.1.tgz",
+      "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
+      "license": "ISC",
+      "dependencies": {
+        "cross-spawn": "^7.0.6",
+        "signal-exit": "^4.0.1"
+      },
+      "engines": {
+        "node": ">=14"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/form-data": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.2.tgz",
+      "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "asynckit": "^0.4.0",
+        "combined-stream": "^1.0.8",
+        "es-set-tostringtag": "^2.1.0",
+        "mime-types": "^2.1.12"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/fs": {
+      "version": "0.0.1-security",
+      "resolved": "https://registry.npmmirror.com/fs/-/fs-0.0.1-security.tgz",
+      "integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==",
+      "license": "ISC"
+    },
+    "node_modules/fs-extra": {
+      "version": "8.1.0",
+      "resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-8.1.0.tgz",
+      "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
+      "license": "MIT",
+      "dependencies": {
+        "graceful-fs": "^4.2.0",
+        "jsonfile": "^4.0.0",
+        "universalify": "^0.1.0"
+      },
+      "engines": {
+        "node": ">=6 <7 || >=8"
+      }
+    },
+    "node_modules/fs-minipass": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/fs-minipass/-/fs-minipass-2.1.0.tgz",
+      "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
+      "license": "ISC",
+      "optional": true,
+      "dependencies": {
+        "minipass": "^3.0.0"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/fs-minipass/node_modules/minipass": {
+      "version": "3.3.6",
+      "resolved": "https://registry.npmmirror.com/minipass/-/minipass-3.3.6.tgz",
+      "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+      "license": "ISC",
+      "optional": true,
+      "dependencies": {
+        "yallist": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/fs.realpath": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz",
+      "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+      "license": "ISC",
+      "optional": true
+    },
+    "node_modules/fsevents": {
+      "version": "2.3.3",
+      "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz",
+      "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+      "hasInstallScript": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "peer": true,
+      "engines": {
+        "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+      }
+    },
+    "node_modules/function-bind": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz",
+      "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+      "license": "MIT",
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/gauge": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmmirror.com/gauge/-/gauge-3.0.2.tgz",
+      "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==",
+      "deprecated": "This package is no longer supported.",
+      "license": "ISC",
+      "optional": true,
+      "dependencies": {
+        "aproba": "^1.0.3 || ^2.0.0",
+        "color-support": "^1.1.2",
+        "console-control-strings": "^1.0.0",
+        "has-unicode": "^2.0.1",
+        "object-assign": "^4.1.1",
+        "signal-exit": "^3.0.0",
+        "string-width": "^4.2.3",
+        "strip-ansi": "^6.0.1",
+        "wide-align": "^1.1.2"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/gauge/node_modules/ansi-regex": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz",
+      "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+      "license": "MIT",
+      "optional": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/gauge/node_modules/emoji-regex": {
+      "version": "8.0.0",
+      "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz",
+      "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+      "license": "MIT",
+      "optional": true
+    },
+    "node_modules/gauge/node_modules/signal-exit": {
+      "version": "3.0.7",
+      "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz",
+      "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+      "license": "ISC",
+      "optional": true
+    },
+    "node_modules/gauge/node_modules/string-width": {
+      "version": "4.2.3",
+      "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz",
+      "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "emoji-regex": "^8.0.0",
+        "is-fullwidth-code-point": "^3.0.0",
+        "strip-ansi": "^6.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/gauge/node_modules/strip-ansi": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz",
+      "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "ansi-regex": "^5.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/get-intrinsic": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+      "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "call-bind-apply-helpers": "^1.0.2",
+        "es-define-property": "^1.0.1",
+        "es-errors": "^1.3.0",
+        "es-object-atoms": "^1.1.1",
+        "function-bind": "^1.1.2",
+        "get-proto": "^1.0.1",
+        "gopd": "^1.2.0",
+        "has-symbols": "^1.1.0",
+        "hasown": "^2.0.2",
+        "math-intrinsics": "^1.1.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/get-proto": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/get-proto/-/get-proto-1.0.1.tgz",
+      "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "dunder-proto": "^1.0.1",
+        "es-object-atoms": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/glob": {
+      "version": "10.4.5",
+      "resolved": "https://registry.npmmirror.com/glob/-/glob-10.4.5.tgz",
+      "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
+      "license": "ISC",
+      "dependencies": {
+        "foreground-child": "^3.1.0",
+        "jackspeak": "^3.1.2",
+        "minimatch": "^9.0.4",
+        "minipass": "^7.1.2",
+        "package-json-from-dist": "^1.0.0",
+        "path-scurry": "^1.11.1"
+      },
+      "bin": {
+        "glob": "dist/esm/bin.mjs"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/glob/node_modules/minimatch": {
+      "version": "9.0.5",
+      "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.5.tgz",
+      "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+      "license": "ISC",
+      "dependencies": {
+        "brace-expansion": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=16 || 14 >=14.17"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/globals": {
+      "version": "11.12.0",
+      "resolved": "https://registry.npmmirror.com/globals/-/globals-11.12.0.tgz",
+      "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/gopd": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz",
+      "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+      "license": "MIT",
+      "optional": true,
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/graceful-fs": {
+      "version": "4.2.11",
+      "resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz",
+      "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+      "license": "ISC"
+    },
+    "node_modules/hammerjs": {
+      "version": "2.0.8",
+      "resolved": "https://registry.npmmirror.com/hammerjs/-/hammerjs-2.0.8.tgz",
+      "integrity": "sha512-tSQXBXS/MWQOn/RKckawJ61vvsDpCom87JgxiYdGwHdOa0ht0vzUWDlfioofFCRU0L+6NGDt6XzbgoJvZkMeRQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.8.0"
+      }
+    },
+    "node_modules/has-symbols": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz",
+      "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+      "license": "MIT",
+      "optional": true,
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/has-tostringtag": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+      "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "has-symbols": "^1.0.3"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/has-unicode": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmmirror.com/has-unicode/-/has-unicode-2.0.1.tgz",
+      "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==",
+      "license": "ISC",
+      "optional": true
+    },
+    "node_modules/hasown": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz",
+      "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+      "license": "MIT",
+      "dependencies": {
+        "function-bind": "^1.1.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/html": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/html/-/html-1.0.0.tgz",
+      "integrity": "sha512-lw/7YsdKiP3kk5PnR1INY17iJuzdAtJewxr14ozKJWbbR97znovZ0mh+WEMZ8rjc3lgTK+ID/htTjuyGKB52Kw==",
+      "license": "BSD",
+      "dependencies": {
+        "concat-stream": "^1.4.7"
+      },
+      "bin": {
+        "html": "bin/html.js"
+      }
+    },
+    "node_modules/html-encoding-sniffer": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmmirror.com/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz",
+      "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "whatwg-encoding": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/http-proxy-agent": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmmirror.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz",
+      "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "@tootallnate/once": "2",
+        "agent-base": "6",
+        "debug": "4"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/https-proxy-agent": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmmirror.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+      "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "agent-base": "6",
+        "debug": "4"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/iconv-lite": {
+      "version": "0.6.3",
+      "resolved": "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.6.3.tgz",
+      "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "safer-buffer": ">= 2.1.2 < 3.0.0"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/image-size": {
+      "version": "0.5.5",
+      "resolved": "https://registry.npmmirror.com/image-size/-/image-size-0.5.5.tgz",
+      "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==",
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "bin": {
+        "image-size": "bin/image-size.js"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/inflight": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmmirror.com/inflight/-/inflight-1.0.6.tgz",
+      "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+      "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
+      "license": "ISC",
+      "optional": true,
+      "dependencies": {
+        "once": "^1.3.0",
+        "wrappy": "1"
+      }
+    },
+    "node_modules/inherits": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz",
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+      "license": "ISC"
+    },
+    "node_modules/ini": {
+      "version": "1.3.8",
+      "resolved": "https://registry.npmmirror.com/ini/-/ini-1.3.8.tgz",
+      "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
+      "license": "ISC"
+    },
+    "node_modules/is-core-module": {
+      "version": "2.16.1",
+      "resolved": "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.16.1.tgz",
+      "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
+      "license": "MIT",
+      "dependencies": {
+        "hasown": "^2.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-fullwidth-code-point": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+      "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/is-plain-object": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmmirror.com/is-plain-object/-/is-plain-object-3.0.1.tgz",
+      "integrity": "sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-potential-custom-element-name": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
+      "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==",
+      "license": "MIT",
+      "optional": true
+    },
+    "node_modules/is-what": {
+      "version": "3.14.1",
+      "resolved": "https://registry.npmmirror.com/is-what/-/is-what-3.14.1.tgz",
+      "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/isarray": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/isarray/-/isarray-1.0.0.tgz",
+      "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
+      "license": "MIT"
+    },
+    "node_modules/isexe": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz",
+      "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+      "license": "ISC"
+    },
+    "node_modules/jackspeak": {
+      "version": "3.4.3",
+      "resolved": "https://registry.npmmirror.com/jackspeak/-/jackspeak-3.4.3.tgz",
+      "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
+      "license": "BlueOak-1.0.0",
+      "dependencies": {
+        "@isaacs/cliui": "^8.0.2"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      },
+      "optionalDependencies": {
+        "@pkgjs/parseargs": "^0.11.0"
+      }
+    },
+    "node_modules/js-beautify": {
+      "version": "1.15.4",
+      "resolved": "https://registry.npmmirror.com/js-beautify/-/js-beautify-1.15.4.tgz",
+      "integrity": "sha512-9/KXeZUKKJwqCXUdBxFJ3vPh467OCckSBmYDwSK/EtV090K+iMJ7zx2S3HLVDIWFQdqMIsZWbnaGiba18aWhaA==",
+      "license": "MIT",
+      "dependencies": {
+        "config-chain": "^1.1.13",
+        "editorconfig": "^1.0.4",
+        "glob": "^10.4.2",
+        "js-cookie": "^3.0.5",
+        "nopt": "^7.2.1"
+      },
+      "bin": {
+        "css-beautify": "js/bin/css-beautify.js",
+        "html-beautify": "js/bin/html-beautify.js",
+        "js-beautify": "js/bin/js-beautify.js"
+      },
+      "engines": {
+        "node": ">=14"
+      }
+    },
+    "node_modules/js-cookie": {
+      "version": "3.0.5",
+      "resolved": "https://registry.npmmirror.com/js-cookie/-/js-cookie-3.0.5.tgz",
+      "integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=14"
+      }
+    },
+    "node_modules/js-tokens": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz",
+      "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+      "license": "MIT"
+    },
+    "node_modules/jsdom": {
+      "version": "20.0.3",
+      "resolved": "https://registry.npmmirror.com/jsdom/-/jsdom-20.0.3.tgz",
+      "integrity": "sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "abab": "^2.0.6",
+        "acorn": "^8.8.1",
+        "acorn-globals": "^7.0.0",
+        "cssom": "^0.5.0",
+        "cssstyle": "^2.3.0",
+        "data-urls": "^3.0.2",
+        "decimal.js": "^10.4.2",
+        "domexception": "^4.0.0",
+        "escodegen": "^2.0.0",
+        "form-data": "^4.0.0",
+        "html-encoding-sniffer": "^3.0.0",
+        "http-proxy-agent": "^5.0.0",
+        "https-proxy-agent": "^5.0.1",
+        "is-potential-custom-element-name": "^1.0.1",
+        "nwsapi": "^2.2.2",
+        "parse5": "^7.1.1",
+        "saxes": "^6.0.0",
+        "symbol-tree": "^3.2.4",
+        "tough-cookie": "^4.1.2",
+        "w3c-xmlserializer": "^4.0.0",
+        "webidl-conversions": "^7.0.0",
+        "whatwg-encoding": "^2.0.0",
+        "whatwg-mimetype": "^3.0.0",
+        "whatwg-url": "^11.0.0",
+        "ws": "^8.11.0",
+        "xml-name-validator": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=14"
+      },
+      "peerDependencies": {
+        "canvas": "^2.5.0"
+      },
+      "peerDependenciesMeta": {
+        "canvas": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/jsesc": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmmirror.com/jsesc/-/jsesc-3.1.0.tgz",
+      "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
+      "dev": true,
+      "license": "MIT",
+      "bin": {
+        "jsesc": "bin/jsesc"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/jsonfile": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmmirror.com/jsonfile/-/jsonfile-4.0.0.tgz",
+      "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
+      "license": "MIT",
+      "optionalDependencies": {
+        "graceful-fs": "^4.1.6"
+      }
+    },
+    "node_modules/less": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmmirror.com/less/-/less-4.3.0.tgz",
+      "integrity": "sha512-X9RyH9fvemArzfdP8Pi3irr7lor2Ok4rOttDXBhlwDg+wKQsXOXgHWduAJE1EsF7JJx0w0bcO6BC6tCKKYnXKA==",
+      "dev": true,
+      "license": "Apache-2.0",
+      "dependencies": {
+        "copy-anything": "^2.0.1",
+        "parse-node-version": "^1.0.1",
+        "tslib": "^2.3.0"
+      },
+      "bin": {
+        "lessc": "bin/lessc"
+      },
+      "engines": {
+        "node": ">=14"
+      },
+      "optionalDependencies": {
+        "errno": "^0.1.1",
+        "graceful-fs": "^4.1.2",
+        "image-size": "~0.5.0",
+        "make-dir": "^2.1.0",
+        "mime": "^1.4.1",
+        "needle": "^3.1.0",
+        "source-map": "~0.6.0"
+      }
+    },
+    "node_modules/less-loader": {
+      "version": "12.3.0",
+      "resolved": "https://registry.npmmirror.com/less-loader/-/less-loader-12.3.0.tgz",
+      "integrity": "sha512-0M6+uYulvYIWs52y0LqN4+QM9TqWAohYSNTo4htE8Z7Cn3G/qQMEmktfHmyJT23k+20kU9zHH2wrfFXkxNLtVw==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 18.12.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/webpack"
+      },
+      "peerDependencies": {
+        "@rspack/core": "0.x || 1.x",
+        "less": "^3.5.0 || ^4.0.0",
+        "webpack": "^5.0.0"
+      },
+      "peerDependenciesMeta": {
+        "@rspack/core": {
+          "optional": true
+        },
+        "webpack": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/less/node_modules/make-dir": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/make-dir/-/make-dir-2.1.0.tgz",
+      "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "pify": "^4.0.1",
+        "semver": "^5.6.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/less/node_modules/semver": {
+      "version": "5.7.2",
+      "resolved": "https://registry.npmmirror.com/semver/-/semver-5.7.2.tgz",
+      "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
+      "dev": true,
+      "license": "ISC",
+      "optional": true,
+      "bin": {
+        "semver": "bin/semver"
+      }
+    },
+    "node_modules/locate-path": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-5.0.0.tgz",
+      "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+      "license": "MIT",
+      "dependencies": {
+        "p-locate": "^4.1.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/lodash": {
+      "version": "4.17.21",
+      "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz",
+      "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+      "license": "MIT"
+    },
+    "node_modules/lodash-es": {
+      "version": "4.17.21",
+      "resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.21.tgz",
+      "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==",
+      "license": "MIT"
+    },
+    "node_modules/lodash.clonedeep": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmmirror.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
+      "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==",
+      "license": "MIT"
+    },
+    "node_modules/lodash.debounce": {
+      "version": "4.0.8",
+      "resolved": "https://registry.npmmirror.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
+      "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==",
+      "license": "MIT"
+    },
+    "node_modules/lodash.isequal": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmmirror.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
+      "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==",
+      "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.",
+      "license": "MIT"
+    },
+    "node_modules/lodash.merge": {
+      "version": "4.6.2",
+      "resolved": "https://registry.npmmirror.com/lodash.merge/-/lodash.merge-4.6.2.tgz",
+      "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+      "license": "MIT"
+    },
+    "node_modules/loose-envify": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmmirror.com/loose-envify/-/loose-envify-1.4.0.tgz",
+      "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+      "license": "MIT",
+      "dependencies": {
+        "js-tokens": "^3.0.0 || ^4.0.0"
+      },
+      "bin": {
+        "loose-envify": "cli.js"
+      }
+    },
+    "node_modules/lru-cache": {
+      "version": "10.4.3",
+      "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-10.4.3.tgz",
+      "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+      "license": "ISC"
+    },
+    "node_modules/magic-string": {
+      "version": "0.30.17",
+      "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.17.tgz",
+      "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==",
+      "license": "MIT",
+      "peer": true,
+      "dependencies": {
+        "@jridgewell/sourcemap-codec": "^1.5.0"
+      }
+    },
+    "node_modules/make-dir": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmmirror.com/make-dir/-/make-dir-3.1.0.tgz",
+      "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
+      "license": "MIT",
+      "dependencies": {
+        "semver": "^6.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/make-dir/node_modules/semver": {
+      "version": "6.3.1",
+      "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz",
+      "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+      "license": "ISC",
+      "bin": {
+        "semver": "bin/semver.js"
+      }
+    },
+    "node_modules/math-intrinsics": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+      "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+      "license": "MIT",
+      "optional": true,
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/mime": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmmirror.com/mime/-/mime-1.6.0.tgz",
+      "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "bin": {
+        "mime": "cli.js"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/mime-db": {
+      "version": "1.52.0",
+      "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz",
+      "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+      "license": "MIT",
+      "optional": true,
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/mime-types": {
+      "version": "2.1.35",
+      "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz",
+      "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "mime-db": "1.52.0"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/mimic-response": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/mimic-response/-/mimic-response-2.1.0.tgz",
+      "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==",
+      "license": "MIT",
+      "optional": true,
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/minimatch": {
+      "version": "9.0.1",
+      "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.1.tgz",
+      "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==",
+      "license": "ISC",
+      "dependencies": {
+        "brace-expansion": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=16 || 14 >=14.17"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/minipass": {
+      "version": "7.1.2",
+      "resolved": "https://registry.npmmirror.com/minipass/-/minipass-7.1.2.tgz",
+      "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
+      "license": "ISC",
+      "engines": {
+        "node": ">=16 || 14 >=14.17"
+      }
+    },
+    "node_modules/minizlib": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmmirror.com/minizlib/-/minizlib-2.1.2.tgz",
+      "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "minipass": "^3.0.0",
+        "yallist": "^4.0.0"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/minizlib/node_modules/minipass": {
+      "version": "3.3.6",
+      "resolved": "https://registry.npmmirror.com/minipass/-/minipass-3.3.6.tgz",
+      "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+      "license": "ISC",
+      "optional": true,
+      "dependencies": {
+        "yallist": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/mkdirp": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-1.0.4.tgz",
+      "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+      "license": "MIT",
+      "optional": true,
+      "bin": {
+        "mkdirp": "bin/cmd.js"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/ms": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz",
+      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+      "devOptional": true,
+      "license": "MIT"
+    },
+    "node_modules/nan": {
+      "version": "2.22.2",
+      "resolved": "https://registry.npmmirror.com/nan/-/nan-2.22.2.tgz",
+      "integrity": "sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ==",
+      "license": "MIT",
+      "optional": true
+    },
+    "node_modules/nanoid": {
+      "version": "3.3.11",
+      "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.11.tgz",
+      "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "license": "MIT",
+      "peer": true,
+      "bin": {
+        "nanoid": "bin/nanoid.cjs"
+      },
+      "engines": {
+        "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+      }
+    },
+    "node_modules/nanopop": {
+      "version": "2.4.2",
+      "resolved": "https://registry.npmmirror.com/nanopop/-/nanopop-2.4.2.tgz",
+      "integrity": "sha512-NzOgmMQ+elxxHeIha+OG/Pv3Oc3p4RU2aBhwWwAqDpXrdTbtRylbRLQztLy8dMMwfl6pclznBdfUhccEn9ZIzw==",
+      "license": "MIT"
+    },
+    "node_modules/needle": {
+      "version": "3.3.1",
+      "resolved": "https://registry.npmmirror.com/needle/-/needle-3.3.1.tgz",
+      "integrity": "sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q==",
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "iconv-lite": "^0.6.3",
+        "sax": "^1.2.4"
+      },
+      "bin": {
+        "needle": "bin/needle"
+      },
+      "engines": {
+        "node": ">= 4.4.x"
+      }
+    },
+    "node_modules/node-fetch": {
+      "version": "2.7.0",
+      "resolved": "https://registry.npmmirror.com/node-fetch/-/node-fetch-2.7.0.tgz",
+      "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "whatwg-url": "^5.0.0"
+      },
+      "engines": {
+        "node": "4.x || >=6.0.0"
+      },
+      "peerDependencies": {
+        "encoding": "^0.1.0"
+      },
+      "peerDependenciesMeta": {
+        "encoding": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/node-fetch/node_modules/tr46": {
+      "version": "0.0.3",
+      "resolved": "https://registry.npmmirror.com/tr46/-/tr46-0.0.3.tgz",
+      "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
+      "license": "MIT",
+      "optional": true
+    },
+    "node_modules/node-fetch/node_modules/webidl-conversions": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+      "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
+      "license": "BSD-2-Clause",
+      "optional": true
+    },
+    "node_modules/node-fetch/node_modules/whatwg-url": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-5.0.0.tgz",
+      "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "tr46": "~0.0.3",
+        "webidl-conversions": "^3.0.0"
+      }
+    },
+    "node_modules/nopt": {
+      "version": "7.2.1",
+      "resolved": "https://registry.npmmirror.com/nopt/-/nopt-7.2.1.tgz",
+      "integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==",
+      "license": "ISC",
+      "dependencies": {
+        "abbrev": "^2.0.0"
+      },
+      "bin": {
+        "nopt": "bin/nopt.js"
+      },
+      "engines": {
+        "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+      }
+    },
+    "node_modules/normalize.css": {
+      "version": "8.0.1",
+      "resolved": "https://registry.npmmirror.com/normalize.css/-/normalize.css-8.0.1.tgz",
+      "integrity": "sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg==",
+      "license": "MIT"
+    },
+    "node_modules/npmlog": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmmirror.com/npmlog/-/npmlog-5.0.1.tgz",
+      "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==",
+      "deprecated": "This package is no longer supported.",
+      "license": "ISC",
+      "optional": true,
+      "dependencies": {
+        "are-we-there-yet": "^2.0.0",
+        "console-control-strings": "^1.1.0",
+        "gauge": "^3.0.0",
+        "set-blocking": "^2.0.0"
+      }
+    },
+    "node_modules/nwsapi": {
+      "version": "2.2.20",
+      "resolved": "https://registry.npmmirror.com/nwsapi/-/nwsapi-2.2.20.tgz",
+      "integrity": "sha512-/ieB+mDe4MrrKMT8z+mQL8klXydZWGR5Dowt4RAGKbJ3kIGEx3X4ljUo+6V73IXtUPWgfOlU5B9MlGxFO5T+cA==",
+      "license": "MIT",
+      "optional": true
+    },
+    "node_modules/object-assign": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmmirror.com/object-assign/-/object-assign-4.1.1.tgz",
+      "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+      "license": "MIT",
+      "optional": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/omit.js": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/omit.js/-/omit.js-1.0.2.tgz",
+      "integrity": "sha512-/QPc6G2NS+8d4L/cQhbk6Yit1WTB6Us2g84A7A/1+w9d/eRGHyEqC5kkQtHVoHZ5NFWGG7tUGgrhVZwgZanKrQ==",
+      "license": "MIT",
+      "dependencies": {
+        "babel-runtime": "^6.23.0"
+      }
+    },
+    "node_modules/once": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmmirror.com/once/-/once-1.4.0.tgz",
+      "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+      "license": "ISC",
+      "optional": true,
+      "dependencies": {
+        "wrappy": "1"
+      }
+    },
+    "node_modules/p-limit": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-2.3.0.tgz",
+      "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+      "license": "MIT",
+      "dependencies": {
+        "p-try": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/p-locate": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-4.1.0.tgz",
+      "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+      "license": "MIT",
+      "dependencies": {
+        "p-limit": "^2.2.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/p-try": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmmirror.com/p-try/-/p-try-2.2.0.tgz",
+      "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/package-json-from-dist": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
+      "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
+      "license": "BlueOak-1.0.0"
+    },
+    "node_modules/parse-node-version": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/parse-node-version/-/parse-node-version-1.0.1.tgz",
+      "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.10"
+      }
+    },
+    "node_modules/parse5": {
+      "version": "7.3.0",
+      "resolved": "https://registry.npmmirror.com/parse5/-/parse5-7.3.0.tgz",
+      "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "entities": "^6.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/inikulin/parse5?sponsor=1"
+      }
+    },
+    "node_modules/parse5/node_modules/entities": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmmirror.com/entities/-/entities-6.0.0.tgz",
+      "integrity": "sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==",
+      "license": "BSD-2-Clause",
+      "optional": true,
+      "engines": {
+        "node": ">=0.12"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/entities?sponsor=1"
+      }
+    },
+    "node_modules/path-exists": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz",
+      "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/path-is-absolute": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+      "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+      "license": "MIT",
+      "optional": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/path-key": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz",
+      "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/path-parse": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz",
+      "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+      "license": "MIT"
+    },
+    "node_modules/path-scurry": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmmirror.com/path-scurry/-/path-scurry-1.11.1.tgz",
+      "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
+      "license": "BlueOak-1.0.0",
+      "dependencies": {
+        "lru-cache": "^10.2.0",
+        "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+      },
+      "engines": {
+        "node": ">=16 || 14 >=14.18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/performance-now": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/performance-now/-/performance-now-2.1.0.tgz",
+      "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==",
+      "license": "MIT"
+    },
+    "node_modules/picocolors": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz",
+      "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+      "license": "ISC"
+    },
+    "node_modules/picomatch": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz",
+      "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=8.6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/jonschlinkert"
+      }
+    },
+    "node_modules/pify": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmmirror.com/pify/-/pify-4.0.1.tgz",
+      "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/pkg-dir": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmmirror.com/pkg-dir/-/pkg-dir-4.2.0.tgz",
+      "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+      "license": "MIT",
+      "dependencies": {
+        "find-up": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/postcss": {
+      "version": "8.5.3",
+      "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.3.tgz",
+      "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==",
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/postcss/"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/postcss"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "license": "MIT",
+      "peer": true,
+      "dependencies": {
+        "nanoid": "^3.3.8",
+        "picocolors": "^1.1.1",
+        "source-map-js": "^1.2.1"
+      },
+      "engines": {
+        "node": "^10 || ^12 || >=14"
+      }
+    },
+    "node_modules/process-nextick-args": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmmirror.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+      "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
+      "license": "MIT"
+    },
+    "node_modules/proto-list": {
+      "version": "1.2.4",
+      "resolved": "https://registry.npmmirror.com/proto-list/-/proto-list-1.2.4.tgz",
+      "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==",
+      "license": "ISC"
+    },
+    "node_modules/prr": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/prr/-/prr-1.0.1.tgz",
+      "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==",
+      "dev": true,
+      "license": "MIT",
+      "optional": true
+    },
+    "node_modules/psl": {
+      "version": "1.15.0",
+      "resolved": "https://registry.npmmirror.com/psl/-/psl-1.15.0.tgz",
+      "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "punycode": "^2.3.1"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/lupomontero"
+      }
+    },
+    "node_modules/punycode": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmmirror.com/punycode/-/punycode-2.3.1.tgz",
+      "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+      "license": "MIT",
+      "optional": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/querystringify": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmmirror.com/querystringify/-/querystringify-2.2.0.tgz",
+      "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
+      "license": "MIT",
+      "optional": true
+    },
+    "node_modules/raf": {
+      "version": "3.4.1",
+      "resolved": "https://registry.npmmirror.com/raf/-/raf-3.4.1.tgz",
+      "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
+      "license": "MIT",
+      "dependencies": {
+        "performance-now": "^2.1.0"
+      }
+    },
+    "node_modules/readable-stream": {
+      "version": "2.3.8",
+      "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.8.tgz",
+      "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
+      "license": "MIT",
+      "dependencies": {
+        "core-util-is": "~1.0.0",
+        "inherits": "~2.0.3",
+        "isarray": "~1.0.0",
+        "process-nextick-args": "~2.0.0",
+        "safe-buffer": "~5.1.1",
+        "string_decoder": "~1.1.1",
+        "util-deprecate": "~1.0.1"
+      }
+    },
+    "node_modules/regenerator-runtime": {
+      "version": "0.11.1",
+      "resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
+      "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==",
+      "license": "MIT"
+    },
+    "node_modules/requires-port": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/requires-port/-/requires-port-1.0.0.tgz",
+      "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
+      "license": "MIT",
+      "optional": true
+    },
+    "node_modules/resize-observer-polyfill": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmmirror.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
+      "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==",
+      "license": "MIT"
+    },
+    "node_modules/resolve": {
+      "version": "1.20.0",
+      "resolved": "https://registry.npmmirror.com/resolve/-/resolve-1.20.0.tgz",
+      "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==",
+      "license": "MIT",
+      "dependencies": {
+        "is-core-module": "^2.2.0",
+        "path-parse": "^1.0.6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/rimraf": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz",
+      "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+      "deprecated": "Rimraf versions prior to v4 are no longer supported",
+      "license": "ISC",
+      "optional": true,
+      "dependencies": {
+        "glob": "^7.1.3"
+      },
+      "bin": {
+        "rimraf": "bin.js"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/rimraf/node_modules/brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "node_modules/rimraf/node_modules/glob": {
+      "version": "7.2.3",
+      "resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz",
+      "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+      "deprecated": "Glob versions prior to v9 are no longer supported",
+      "license": "ISC",
+      "optional": true,
+      "dependencies": {
+        "fs.realpath": "^1.0.0",
+        "inflight": "^1.0.4",
+        "inherits": "2",
+        "minimatch": "^3.1.1",
+        "once": "^1.3.0",
+        "path-is-absolute": "^1.0.0"
+      },
+      "engines": {
+        "node": "*"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/rimraf/node_modules/minimatch": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz",
+      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+      "license": "ISC",
+      "optional": true,
+      "dependencies": {
+        "brace-expansion": "^1.1.7"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/rollup": {
+      "version": "4.41.1",
+      "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.41.1.tgz",
+      "integrity": "sha512-cPmwD3FnFv8rKMBc1MxWCwVQFxwf1JEmSX3iQXrRVVG15zerAIXRjMFVWnd5Q5QvgKF7Aj+5ykXFhUl+QGnyOw==",
+      "license": "MIT",
+      "peer": true,
+      "dependencies": {
+        "@types/estree": "1.0.7"
+      },
+      "bin": {
+        "rollup": "dist/bin/rollup"
+      },
+      "engines": {
+        "node": ">=18.0.0",
+        "npm": ">=8.0.0"
+      },
+      "optionalDependencies": {
+        "@rollup/rollup-android-arm-eabi": "4.41.1",
+        "@rollup/rollup-android-arm64": "4.41.1",
+        "@rollup/rollup-darwin-arm64": "4.41.1",
+        "@rollup/rollup-darwin-x64": "4.41.1",
+        "@rollup/rollup-freebsd-arm64": "4.41.1",
+        "@rollup/rollup-freebsd-x64": "4.41.1",
+        "@rollup/rollup-linux-arm-gnueabihf": "4.41.1",
+        "@rollup/rollup-linux-arm-musleabihf": "4.41.1",
+        "@rollup/rollup-linux-arm64-gnu": "4.41.1",
+        "@rollup/rollup-linux-arm64-musl": "4.41.1",
+        "@rollup/rollup-linux-loongarch64-gnu": "4.41.1",
+        "@rollup/rollup-linux-powerpc64le-gnu": "4.41.1",
+        "@rollup/rollup-linux-riscv64-gnu": "4.41.1",
+        "@rollup/rollup-linux-riscv64-musl": "4.41.1",
+        "@rollup/rollup-linux-s390x-gnu": "4.41.1",
+        "@rollup/rollup-linux-x64-gnu": "4.41.1",
+        "@rollup/rollup-linux-x64-musl": "4.41.1",
+        "@rollup/rollup-win32-arm64-msvc": "4.41.1",
+        "@rollup/rollup-win32-ia32-msvc": "4.41.1",
+        "@rollup/rollup-win32-x64-msvc": "4.41.1",
+        "fsevents": "~2.3.2"
+      }
+    },
+    "node_modules/rollup-plugin-typescript2": {
+      "version": "0.30.0",
+      "resolved": "https://registry.npmmirror.com/rollup-plugin-typescript2/-/rollup-plugin-typescript2-0.30.0.tgz",
+      "integrity": "sha512-NUFszIQyhgDdhRS9ya/VEmsnpTe+GERDMmFo0Y+kf8ds51Xy57nPNGglJY+W6x1vcouA7Au7nsTgsLFj2I0PxQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@rollup/pluginutils": "^4.1.0",
+        "find-cache-dir": "^3.3.1",
+        "fs-extra": "8.1.0",
+        "resolve": "1.20.0",
+        "tslib": "2.1.0"
+      },
+      "peerDependencies": {
+        "rollup": ">=1.26.3",
+        "typescript": ">=2.4.0"
+      }
+    },
+    "node_modules/rollup-plugin-typescript2/node_modules/tslib": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.1.0.tgz",
+      "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==",
+      "license": "0BSD"
+    },
+    "node_modules/rxjs": {
+      "version": "7.8.2",
+      "resolved": "https://registry.npmmirror.com/rxjs/-/rxjs-7.8.2.tgz",
+      "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==",
+      "license": "Apache-2.0",
+      "dependencies": {
+        "tslib": "^2.1.0"
+      }
+    },
+    "node_modules/safe-buffer": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz",
+      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+      "license": "MIT"
+    },
+    "node_modules/safer-buffer": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz",
+      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+      "license": "MIT",
+      "optional": true
+    },
+    "node_modules/sax": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmmirror.com/sax/-/sax-1.4.1.tgz",
+      "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==",
+      "dev": true,
+      "license": "ISC",
+      "optional": true
+    },
+    "node_modules/saxes": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmmirror.com/saxes/-/saxes-6.0.0.tgz",
+      "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==",
+      "license": "ISC",
+      "optional": true,
+      "dependencies": {
+        "xmlchars": "^2.2.0"
+      },
+      "engines": {
+        "node": ">=v12.22.7"
+      }
+    },
+    "node_modules/scroll-into-view-if-needed": {
+      "version": "2.2.31",
+      "resolved": "https://registry.npmmirror.com/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.31.tgz",
+      "integrity": "sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==",
+      "license": "MIT",
+      "dependencies": {
+        "compute-scroll-into-view": "^1.0.20"
+      }
+    },
+    "node_modules/semver": {
+      "version": "7.7.2",
+      "resolved": "https://registry.npmmirror.com/semver/-/semver-7.7.2.tgz",
+      "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
+      "license": "ISC",
+      "bin": {
+        "semver": "bin/semver.js"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/set-blocking": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/set-blocking/-/set-blocking-2.0.0.tgz",
+      "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
+      "license": "ISC",
+      "optional": true
+    },
+    "node_modules/shallow-equal": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmmirror.com/shallow-equal/-/shallow-equal-1.2.1.tgz",
+      "integrity": "sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==",
+      "license": "MIT"
+    },
+    "node_modules/shallowequal": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmmirror.com/shallowequal/-/shallowequal-1.1.0.tgz",
+      "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==",
+      "license": "MIT"
+    },
+    "node_modules/shebang-command": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz",
+      "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+      "license": "MIT",
+      "dependencies": {
+        "shebang-regex": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/shebang-regex": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz",
+      "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/signal-exit": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-4.1.0.tgz",
+      "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+      "license": "ISC",
+      "engines": {
+        "node": ">=14"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/simple-concat": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/simple-concat/-/simple-concat-1.0.1.tgz",
+      "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ],
+      "license": "MIT",
+      "optional": true
+    },
+    "node_modules/simple-get": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmmirror.com/simple-get/-/simple-get-3.1.1.tgz",
+      "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "decompress-response": "^4.2.0",
+        "once": "^1.3.1",
+        "simple-concat": "^1.0.0"
+      }
+    },
+    "node_modules/source-map": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz",
+      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+      "license": "BSD-3-Clause",
+      "optional": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/source-map-js": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz",
+      "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+      "license": "BSD-3-Clause",
+      "peer": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/string_decoder": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.1.1.tgz",
+      "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+      "license": "MIT",
+      "dependencies": {
+        "safe-buffer": "~5.1.0"
+      }
+    },
+    "node_modules/string-width": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmmirror.com/string-width/-/string-width-5.1.2.tgz",
+      "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+      "license": "MIT",
+      "dependencies": {
+        "eastasianwidth": "^0.2.0",
+        "emoji-regex": "^9.2.2",
+        "strip-ansi": "^7.0.1"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/string-width-cjs": {
+      "name": "string-width",
+      "version": "4.2.3",
+      "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz",
+      "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+      "license": "MIT",
+      "dependencies": {
+        "emoji-regex": "^8.0.0",
+        "is-fullwidth-code-point": "^3.0.0",
+        "strip-ansi": "^6.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/string-width-cjs/node_modules/ansi-regex": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz",
+      "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/string-width-cjs/node_modules/emoji-regex": {
+      "version": "8.0.0",
+      "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz",
+      "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+      "license": "MIT"
+    },
+    "node_modules/string-width-cjs/node_modules/strip-ansi": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz",
+      "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+      "license": "MIT",
+      "dependencies": {
+        "ansi-regex": "^5.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/strip-ansi": {
+      "version": "7.1.0",
+      "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.1.0.tgz",
+      "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+      "license": "MIT",
+      "dependencies": {
+        "ansi-regex": "^6.0.1"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+      }
+    },
+    "node_modules/strip-ansi-cjs": {
+      "name": "strip-ansi",
+      "version": "6.0.1",
+      "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz",
+      "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+      "license": "MIT",
+      "dependencies": {
+        "ansi-regex": "^5.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/strip-ansi-cjs/node_modules/ansi-regex": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz",
+      "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/stylis": {
+      "version": "4.3.6",
+      "resolved": "https://registry.npmmirror.com/stylis/-/stylis-4.3.6.tgz",
+      "integrity": "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==",
+      "license": "MIT"
+    },
+    "node_modules/symbol-tree": {
+      "version": "3.2.4",
+      "resolved": "https://registry.npmmirror.com/symbol-tree/-/symbol-tree-3.2.4.tgz",
+      "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
+      "license": "MIT",
+      "optional": true
+    },
+    "node_modules/tar": {
+      "version": "6.2.1",
+      "resolved": "https://registry.npmmirror.com/tar/-/tar-6.2.1.tgz",
+      "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
+      "license": "ISC",
+      "optional": true,
+      "dependencies": {
+        "chownr": "^2.0.0",
+        "fs-minipass": "^2.0.0",
+        "minipass": "^5.0.0",
+        "minizlib": "^2.1.1",
+        "mkdirp": "^1.0.3",
+        "yallist": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/tar/node_modules/minipass": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmmirror.com/minipass/-/minipass-5.0.0.tgz",
+      "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
+      "license": "ISC",
+      "optional": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/throttle-debounce": {
+      "version": "5.0.2",
+      "resolved": "https://registry.npmmirror.com/throttle-debounce/-/throttle-debounce-5.0.2.tgz",
+      "integrity": "sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=12.22"
+      }
+    },
+    "node_modules/tough-cookie": {
+      "version": "4.1.4",
+      "resolved": "https://registry.npmmirror.com/tough-cookie/-/tough-cookie-4.1.4.tgz",
+      "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==",
+      "license": "BSD-3-Clause",
+      "optional": true,
+      "dependencies": {
+        "psl": "^1.1.33",
+        "punycode": "^2.1.1",
+        "universalify": "^0.2.0",
+        "url-parse": "^1.5.3"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/tough-cookie/node_modules/universalify": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmmirror.com/universalify/-/universalify-0.2.0.tgz",
+      "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==",
+      "license": "MIT",
+      "optional": true,
+      "engines": {
+        "node": ">= 4.0.0"
+      }
+    },
+    "node_modules/tr46": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmmirror.com/tr46/-/tr46-3.0.0.tgz",
+      "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "punycode": "^2.1.1"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/tslib": {
+      "version": "2.8.1",
+      "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.8.1.tgz",
+      "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
+      "license": "0BSD"
+    },
+    "node_modules/type-fest": {
+      "version": "0.15.1",
+      "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-0.15.1.tgz",
+      "integrity": "sha512-n+UXrN8i5ioo7kqT/nF8xsEzLaqFra7k32SEsSPwvXVGyAcRgV/FUQN/sgfptJTR1oRmmq7z4IXMFSM7im7C9A==",
+      "license": "(MIT OR CC0-1.0)",
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/typedarray": {
+      "version": "0.0.6",
+      "resolved": "https://registry.npmmirror.com/typedarray/-/typedarray-0.0.6.tgz",
+      "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==",
+      "license": "MIT"
+    },
+    "node_modules/typescript": {
+      "version": "5.8.3",
+      "resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.8.3.tgz",
+      "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
+      "license": "Apache-2.0",
+      "peer": true,
+      "bin": {
+        "tsc": "bin/tsc",
+        "tsserver": "bin/tsserver"
+      },
+      "engines": {
+        "node": ">=14.17"
+      }
+    },
+    "node_modules/universalify": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmmirror.com/universalify/-/universalify-0.1.2.tgz",
+      "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 4.0.0"
+      }
+    },
+    "node_modules/url-parse": {
+      "version": "1.5.10",
+      "resolved": "https://registry.npmmirror.com/url-parse/-/url-parse-1.5.10.tgz",
+      "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "querystringify": "^2.1.1",
+        "requires-port": "^1.0.0"
+      }
+    },
+    "node_modules/util-deprecate": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz",
+      "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+      "license": "MIT"
+    },
+    "node_modules/uuid": {
+      "version": "11.1.0",
+      "resolved": "https://registry.npmmirror.com/uuid/-/uuid-11.1.0.tgz",
+      "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==",
+      "funding": [
+        "https://github.com/sponsors/broofa",
+        "https://github.com/sponsors/ctavan"
+      ],
+      "license": "MIT",
+      "bin": {
+        "uuid": "dist/esm/bin/uuid"
+      }
+    },
+    "node_modules/vue": {
+      "version": "3.5.14",
+      "resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.14.tgz",
+      "integrity": "sha512-LbOm50/vZFG6Mhy6KscQYXZMQ0LMCC/y40HDJPPvGFQ+i/lUH+PJHR6C3assgOQiXdl6tAfsXHbXYVBZZu65ew==",
+      "license": "MIT",
+      "peer": true,
+      "dependencies": {
+        "@vue/compiler-dom": "3.5.14",
+        "@vue/compiler-sfc": "3.5.14",
+        "@vue/runtime-dom": "3.5.14",
+        "@vue/server-renderer": "3.5.14",
+        "@vue/shared": "3.5.14"
+      },
+      "peerDependencies": {
+        "typescript": "*"
+      },
+      "peerDependenciesMeta": {
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/vue-types": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmmirror.com/vue-types/-/vue-types-3.0.2.tgz",
+      "integrity": "sha512-IwUC0Aq2zwaXqy74h4WCvFCUtoV0iSWr0snWnE9TnU18S66GAQyqQbRf2qfJtUuiFsBf6qp0MEwdonlwznlcrw==",
+      "license": "MIT",
+      "dependencies": {
+        "is-plain-object": "3.0.1"
+      },
+      "engines": {
+        "node": ">=10.15.0"
+      },
+      "peerDependencies": {
+        "vue": "^3.0.0"
+      }
+    },
+    "node_modules/w3c-xmlserializer": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmmirror.com/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz",
+      "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "xml-name-validator": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=14"
+      }
+    },
+    "node_modules/warning": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmmirror.com/warning/-/warning-4.0.3.tgz",
+      "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
+      "license": "MIT",
+      "dependencies": {
+        "loose-envify": "^1.0.0"
+      }
+    },
+    "node_modules/webidl-conversions": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
+      "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
+      "license": "BSD-2-Clause",
+      "optional": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/whatwg-encoding": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz",
+      "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "iconv-lite": "0.6.3"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/whatwg-mimetype": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmmirror.com/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz",
+      "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==",
+      "license": "MIT",
+      "optional": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/whatwg-url": {
+      "version": "11.0.0",
+      "resolved": "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-11.0.0.tgz",
+      "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "tr46": "^3.0.0",
+        "webidl-conversions": "^7.0.0"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/which": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz",
+      "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+      "license": "ISC",
+      "dependencies": {
+        "isexe": "^2.0.0"
+      },
+      "bin": {
+        "node-which": "bin/node-which"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/wide-align": {
+      "version": "1.1.5",
+      "resolved": "https://registry.npmmirror.com/wide-align/-/wide-align-1.1.5.tgz",
+      "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==",
+      "license": "ISC",
+      "optional": true,
+      "dependencies": {
+        "string-width": "^1.0.2 || 2 || 3 || 4"
+      }
+    },
+    "node_modules/wide-align/node_modules/ansi-regex": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz",
+      "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+      "license": "MIT",
+      "optional": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/wide-align/node_modules/emoji-regex": {
+      "version": "8.0.0",
+      "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz",
+      "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+      "license": "MIT",
+      "optional": true
+    },
+    "node_modules/wide-align/node_modules/string-width": {
+      "version": "4.2.3",
+      "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz",
+      "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "emoji-regex": "^8.0.0",
+        "is-fullwidth-code-point": "^3.0.0",
+        "strip-ansi": "^6.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/wide-align/node_modules/strip-ansi": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz",
+      "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "ansi-regex": "^5.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/wrap-ansi": {
+      "version": "8.1.0",
+      "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
+      "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+      "license": "MIT",
+      "dependencies": {
+        "ansi-styles": "^6.1.0",
+        "string-width": "^5.0.1",
+        "strip-ansi": "^7.0.1"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+      }
+    },
+    "node_modules/wrap-ansi-cjs": {
+      "name": "wrap-ansi",
+      "version": "7.0.0",
+      "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+      "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+      "license": "MIT",
+      "dependencies": {
+        "ansi-styles": "^4.0.0",
+        "string-width": "^4.1.0",
+        "strip-ansi": "^6.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+      }
+    },
+    "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz",
+      "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz",
+      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+      "license": "MIT",
+      "dependencies": {
+        "color-convert": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+      }
+    },
+    "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": {
+      "version": "8.0.0",
+      "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz",
+      "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+      "license": "MIT"
+    },
+    "node_modules/wrap-ansi-cjs/node_modules/string-width": {
+      "version": "4.2.3",
+      "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz",
+      "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+      "license": "MIT",
+      "dependencies": {
+        "emoji-regex": "^8.0.0",
+        "is-fullwidth-code-point": "^3.0.0",
+        "strip-ansi": "^6.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz",
+      "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+      "license": "MIT",
+      "dependencies": {
+        "ansi-regex": "^5.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/wrappy": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz",
+      "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+      "license": "ISC",
+      "optional": true
+    },
+    "node_modules/ws": {
+      "version": "8.18.2",
+      "resolved": "https://registry.npmmirror.com/ws/-/ws-8.18.2.tgz",
+      "integrity": "sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==",
+      "license": "MIT",
+      "optional": true,
+      "engines": {
+        "node": ">=10.0.0"
+      },
+      "peerDependencies": {
+        "bufferutil": "^4.0.1",
+        "utf-8-validate": ">=5.0.2"
+      },
+      "peerDependenciesMeta": {
+        "bufferutil": {
+          "optional": true
+        },
+        "utf-8-validate": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/xml-name-validator": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmmirror.com/xml-name-validator/-/xml-name-validator-4.0.0.tgz",
+      "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==",
+      "license": "Apache-2.0",
+      "optional": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/xmlchars": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmmirror.com/xmlchars/-/xmlchars-2.2.0.tgz",
+      "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
+      "license": "MIT",
+      "optional": true
+    },
+    "node_modules/yallist": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz",
+      "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+      "license": "ISC",
+      "optional": true
+    }
+  }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..9220115
--- /dev/null
+++ b/package.json
@@ -0,0 +1,15 @@
+{
+  "dependencies": {
+    "ant-design-vue": "^4.0.0-rc.6",
+    "antd-mobile-vue-next": "^0.1.0-16",
+    "dayjs": "^1.11.13",
+    "fabric": "^6.6.7",
+    "rxjs": "^7.8.2",
+    "uuid": "^11.1.0"
+  },
+  "devDependencies": {
+    "babel-plugin-import": "^1.13.8",
+    "less": "^4.3.0",
+    "less-loader": "^12.3.0"
+  }
+}
diff --git a/pages.json b/pages.json
new file mode 100644
index 0000000..54fdc2c
--- /dev/null
+++ b/pages.json
@@ -0,0 +1,204 @@
+{
+	"pages": [ //pages鏁扮粍涓涓�」琛ㄧず搴旂敤鍚姩椤碉紝鍙傝�锛歨ttps://uniapp.dcloud.io/collocation/pages
+		{
+			"path": "pages/login/index",
+			"style": {
+				"navigationBarTitleText": "鐧诲綍"
+			}
+		},
+		{
+			"path": "pages/login/register",
+			"style": {
+				"navigationBarTitleText": "娉ㄥ唽鐢ㄦ埛"
+			}
+		},
+		{
+			"path": "pages/login/forgot-password",
+			"style": {
+				"navigationBarTitleText": "蹇樿瀵嗙爜"
+			}
+		},
+		{
+			"path": "pages/index/index",
+
+			"style": {
+				"navigationStyle": "custom", //鑷畾涔夋爣棰樻爮
+				"app-plus": {
+					"titleNView": false //绂佺敤鍘熺敓瀵艰埅鏍�+				}
+			}
+		},
+		{
+			"path": "pages/index/connect",
+			"style": {
+				"navigationBarTitleText": "杞﹁締杩炴帴"
+			}
+		},
+
+		{
+			"path": "pages/index/detail",
+			"style": {
+				"navigationStyle": "custom", //鑷畾涔夋爣棰樻爮
+				"app-plus": {
+					"titleNView": false //绂佺敤鍘熺敓瀵艰埅鏍�+				}
+			}
+		},
+		{
+			"path": "pages/my/index",
+			"style": {
+				"navigationBarTitleText": "鎴戠殑"
+			}
+		},
+		{
+			"path": "pages/my/language",
+			"style": {
+				"navigationBarTitleText": "澶氳瑷�缃�
+			}
+		},
+		{
+			"path": "pages/my/version-update",
+			"style": {
+				"navigationBarTitleText": "鐗堟湰鏇存柊"
+			}
+		},
+		{
+			"path": "pages/my/help-feedback",
+			"style": {
+				"navigationBarTitleText": "甯姪涓庡弽棣�
+			}
+		},
+		{
+			"path": "pages/my/instruction",
+			"style": {
+				"navigationBarTitleText": "鏌ョ湅璇存槑涔�
+			}
+		},
+		{
+			"path": "pages/my/log",
+			"style": {
+				"navigationBarTitleText": "鎺ュ彛鏃ュ織"
+			}
+		},
+		{
+			"path": "pages/my/log-detail",
+			"style": {
+				"navigationBarTitleText": "鎺ュ彛鏃ュ織璇︽儏"
+			}
+		},
+		{
+			"path": "pages/map/index",
+			"style": {
+				"navigationBarTitleText": "鍦板浘"
+			}
+		},
+		{
+			"path": "pages/map/task",
+			"style": {
+				"navigationBarTitleText": "鍦板浘"
+			}
+		},
+		{
+			"path": "pages/map/edit",
+			"style": {
+				"navigationBarTitleText": "缂栬緫鍦板浘"
+			}
+		},
+
+		{
+			"path": "pages/task/index",
+			"style": {
+				"navigationBarTitleText": "浠诲姟"
+			}
+		},
+		{
+			"path": "pages/task/list",
+			"style": {
+				"navigationBarTitleText": "璁剧疆浠诲姟"
+			}
+		},
+		{
+			"path": "pages/task/add",
+			"style": {
+				"navigationStyle": "custom", //鑷畾涔夋爣棰樻爮
+				"app-plus": {
+					"titleNView": false //绂佺敤鍘熺敓瀵艰埅鏍�+				}
+			}
+		},
+		{
+			"path": "pages/task/update",
+			"style": {
+				"navigationStyle": "custom", //鑷畾涔夋爣棰樻爮
+				"app-plus": {
+					"titleNView": false //绂佺敤鍘熺敓瀵艰埅鏍�+				}
+			}
+		},
+		{
+			"path": "pages/task/log-list",
+			"style": {
+				"navigationBarTitleText": "浠诲姟璁板綍"
+			}
+		},
+		{
+			"path": "pages/task/map-task",
+			"style": {
+				"navigationBarTitleText": "浠诲姟"
+			}
+		},
+		{
+			"path": "pages/station/index",
+			"style": {
+				"navigationBarTitleText": "绔欑偣鍒楄〃"
+			}
+		},
+		{
+			"path": "pages/teaching/index",
+			"style": {
+				"navigationBarTitleText": "绀烘暀璺嚎鍒楄〃"
+			}
+		},
+		{
+			"path": "pages/teaching/list",
+			"style": {
+				"navigationBarTitleText": "绀烘暀璺嚎鍒楄〃"
+			}
+		}
+
+	],
+	"globalStyle": {
+		"navigationBarTextStyle": "black",
+		"navigationBarTitleText": "鍦扮墰App",
+		"navigationBarBackgroundColor": "#F8F8F8",
+		"backgroundColor": "#FFFFFF"
+	},
+	"uniIdRouter": {},
+	"easycom": {
+		"autoscan": true,
+		"custom": {
+			"^a-(.*)": "ant-design-vue/es/$1/index.js"
+		}
+	},
+	"tabBar": {
+		"borderStyle": "white",
+		"color": "#808080",
+		"selectedColor": "#36a9f8",
+		"backgroundColor": "#FFFFFF",
+		"list": [{
+				"pagePath": "pages/index/index",
+				"text": "杞﹁締",
+				"iconPath": "/static/tabbar/mdi_hand-truck2.png",
+				"selectedIconPath": "/static/tabbar/mdi_hand-truck.png"
+			},
+
+			{
+				"pagePath": "pages/my/index",
+				"text": "鎴戠殑",
+				"iconPath": "/static/tabbar/ooui_user-avatar2.png",
+				"selectedIconPath": "/static/tabbar/ooui_user-avatar.png"
+			}
+		]
+	}
+
+}
\ No newline at end of file
diff --git a/pages/index/connect.vue b/pages/index/connect.vue
new file mode 100644
index 0000000..9fcc16b
--- /dev/null
+++ b/pages/index/connect.vue
@@ -0,0 +1,454 @@
+<template>
+	<view class="pages-vehicle-connect">
+
+		<view class="content" v-if="connectState == 1">
+			<view class="title">杩炴帴涓�/view>
+			<view class="content2">
+				<view class="auto-circle"></view>
+				<view>杩炴帴涓�..</view>
+			</view>
+		</view>
+		<view class="content" v-else-if="connectState == 2">
+			<view class="title">杩炴帴鎴愬姛</view>
+			<view class="content2">
+				<image class="img" src="/images/Frame 178.svg" alt=" 鍥剧墖" />
+				<view>銆恵{connectedDevice}}銆戣繛鎺ユ垚鍔�/view>
+			</view>
+		</view>
+		<view class="content" v-else-if="connectState == 3">
+			<view class="title">杩炴帴澶辫触</view>
+			<view class="content2">
+				<image class="img" src="/images/Frame 179.svg" alt=" 鍥剧墖" />
+				<view class="title">鏃犳硶杩炴帴璁惧</view>
+				<view>璇风‘淇濊溅杈嗗紑鏈轰笖鏈笌鍏朵粬缁堢閰嶅</view>
+			</view>
+		</view>
+		<view class="content" v-else-if="connectState == 4">
+			<view class="title">杩炴帴鍑嗗</view>
+			<view class="content2">
+
+				<view>1銆佽灏嗘墜鏈鸿繛鎺ュ埌鈥榹{ip}}鈥欑殑Wifi缃戠粶</view>
+				<view>2銆佽繛鎺ュ悗鍥炲埌鏈簲鐢�/view>
+				<image class="img-2" src="/images/Frame 180.svg" alt=" 鍥剧墖" />
+			</view>
+		</view>
+		<view class="content" v-else>
+			<view class="title">杩炴帴鍑嗗</view>
+		</view>
+		<view v-if="connectState == 3" class="button-group">
+			<a-button type="primary" plain="true" class="button" @click="clickTry">
+				{{reconnectFlag ? "閲嶆柊杩炴帴WiFi":"鍐嶈瘯"}}
+			</a-button>
+			<a-button  type="ghost" class="button" @click="clickCancel">鍙栨秷
+			</a-button>
+			<view class="link-text"> <a @click="clickStudyMore">瀛︿範鏇村...</a> </view>
+		</view>
+		<view v-if="connectState == 4" class="button-group">
+			<a-button type="primary" plain="true" class="button" @click="clickLinkWifi">鍘昏繛鎺�+			</a-button>
+			<a-button  type="ghost" class="button" @click="clickTry">鍒囨崲鎵爜杩炴帴
+			</a-button>
+		</view>
+	</view>
+</template>
+
+<script>
+	import {
+		session,
+		showToast,
+		showModal
+	} from "@/comm/utils.js"
+	import {
+		Button
+	} from 'antd-mobile-vue-next'
+	import androidWifi from "@/comm/wifi/android.js"
+	import iosWifi from "@/comm/wifi/ios.js"
+	import {
+		mtBattery,
+		checkIpLinkSuccess
+	} from "@/api/vehicle.js"
+
+	// 鍦ㄩ〉闈腑浣跨敤
+	export default {
+		name: "PagesVehicleConnect",
+		components: {
+			'a-button': Button,
+		},
+		data() {
+			return {
+				ip: "",
+				wifiSID: "",
+				wifiPassword: "",
+				connectState: 0,
+				connectedDevice: "",
+				reconnectFlag: false,
+				unloadFlag: false
+			}
+		},
+		computed: {
+
+		},
+		onLoad(option) {
+			this.ip = option.ip
+			this.wifiSID = option.sid || ""
+			this.wifiPassword = option.passwpord || ""
+			this.reconnectFlag = option.reconnect ? true : false
+			this.unloadFlag = false
+			this.loadData()
+		},
+		onUnload() {
+			this.unloadFlag = true
+		},
+		methods: {
+			setData(obj) {
+				let that = this;
+				let keys = [];
+				let val, data;
+
+				Object.keys(obj).forEach(function(key) {
+					keys = key.split(".");
+					val = obj[key];
+					data = that.$data;
+					keys.forEach(function(key2, index) {
+						if (index + 1 == keys.length) {
+							that.$set(data, key2, val);
+						} else {
+							if (!data[key2]) {
+								that.$set(data, key2, {});
+							}
+						}
+						data = data[key2];
+					});
+				});
+			},
+			loadData() {
+				try {
+					const app = getApp()
+					const platform = app.globalData.platform
+					console.log("platform connect", platform)
+					if (this.reconnectFlag) {
+						this.connectState = 3
+						setTimeout(() => {
+							if (platform == "android") {
+								androidWifi.initWifi()
+							}
+						}, 10000)
+						return
+					}
+					this.connectState = 1
+					setTimeout(() => {
+						this.checkConnectStatus()
+
+					}, 1000)
+
+
+				} catch (ex) {
+					this.showError(ex)
+				}
+			},
+			checkConnectStatus() {
+				const app = getApp()
+				const platform = app.globalData.platform
+				if (platform == "android") {
+					androidWifi.initWifi()
+				} else if (platform == "ios") {
+
+				}
+				console.log("checkConnectStatus", this.wifiSID)
+
+				let res = this.checkConnectSuccess().then((res) => {
+					if (!res)
+						if (this.wifiSID.trim()) {
+							this.connectWifi()
+						} else {
+							this.connectState = 4
+						}
+					else {
+						this.connectState = 2
+						this.connectedSuccess()
+					}
+				})
+
+			},
+			clickTry() {
+				const that = this
+				if (that.reconnectFlag) {
+					that.clickLinkWifi()
+				} else {
+					uni.scanCode({
+						scanType: ["qrCode"],
+						success: function(res) {
+							const result = res.result || ""
+							const arCode = result.split(";")
+							if (arCode.length != 3) {
+								showModal("鏃犳晥鐨勪簩缁寸爜锛�, "鎻愮ず")
+								return
+							}
+							if (!arCode[0].trim() || !arCode[0].trim()) {
+								showModal("鏃犳晥鐨勪簩缁寸爜锛�, "鎻愮ず")
+								return
+							}
+							that.ip = arCode[0]
+							that.wifiSID = arCode[1]
+							that.wifiPassword = arCode[2]
+							console.log(that.ip, arCode)
+							if (that.wifiSID.trim()) {
+								that.connectWifi()
+							} else {
+								that.connectVehicle()
+							}
+
+						}
+					})
+				}
+
+			},
+			clickCancel() {
+				uni.navigateBack({
+					delta: 1
+				})
+			},
+			clickLinkWifi() {
+				const app = getApp()
+				const platform = app.globalData.platform
+
+				if (platform == "android") {
+					androidWifi.openWifiSetting()
+				} else if (platform == "ios") {
+					iosWifi.openWifiSetting()
+				}
+				this.connectState = 1
+
+				this.checkConnectVehicle()
+			},
+			clickStudyMore() {
+				showToast("鍚庣画鍙戝紑涓�)
+			},
+			connectWifi(first) {
+				const app = getApp()
+				const platform = app.globalData.platform
+				const osVersion = app.globalData.osVersion
+				let ssid = ""
+				const wifiInfo = this.getConnectionWifi()
+				ssid = wifiInfo.ssid || ""
+				console.log("connectWifi", ssid)
+				if (`"${this.wifiSID}"` != ssid && `${this.wifiSID}` != ssid) {
+					if (platform == "android" && osVersion < 10) {
+						showModal(`銆�{app.globalData.deviceModel}銆戞兂鍔犲叆鏃犵嚎灞�煙缃戙�${this.wifiSID}銆戝悧锛焋, "璇㈤棶").then((res) => {
+							if (res) {
+								this.connectState = 1
+
+								androidWifi.connectWifi(this.wifiSID,
+									this.wifiPassword
+								)
+								this.checkConnectVehicle()
+								// 
+							} else {
+								if (first) {
+									uni.navigateBack({
+										delta: 1
+									})
+								}
+
+							}
+						})
+					} else {
+
+						if (platform == "android") {
+							androidWifi.openWifiSetting()
+						} else if (platform == "ios") {
+							iosWifi.openWifiSetting()
+						}
+						this.connectState = 1
+
+						this.checkConnectVehicle()
+
+					}
+				} else {
+					this.connectState = 1
+					this.connectVehicle()
+				}
+			},
+
+			getConnectionWifi() {
+				const app = getApp()
+				const platform = app.globalData.platform
+				if (platform == "android") {
+					const wifiInfo = androidWifi.getConnectionWifi()
+					return wifiInfo
+				} else if (platform == "ios") {
+					const wifiInfo = iosWifi.getConnectionWifi()
+					return wifiInfo
+				}
+				return {}
+			},
+			async connectVehicle() {
+				try {
+					const info = await mtBattery(this.ip)
+					this.connectState = 2
+					this.connectedSuccess()
+				} catch (ex) {
+					this.connectState = 3
+					// this.showError(ex)
+				}
+			},
+
+			async checkConnectSuccess() {
+				try {
+					const res = await checkIpLinkSuccess(this.ip)
+					return true
+				} catch (ex) {
+					return false
+				}
+
+			},
+			connectedSuccess() {
+				this.connectState = 2
+				this.connectedDevice = this.ip
+				const list = session.getValue("vehicles") || []
+				const wifiInfo = this.getConnectionWifi()
+				const curIndex = list.findIndex((a) => a.ip == this.ip)
+				let info = {}
+				if (curIndex < 0) {
+					info = {
+						link_status: true,
+						name: this.ip,
+						ip: this.ip,
+						wifi: {
+							sid: wifiInfo.sid || "",
+							mac: wifiInfo.mac || "",
+							ip: wifiInfo.ip || ""
+						},
+					}
+					list.push(info)
+				} else {
+					info = list[curIndex]
+					info.wifi = {
+						sid: wifiInfo.sid || "",
+						mac: wifiInfo.mac || "",
+						ip: wifiInfo.ip || ""
+					}
+				}
+				session.setValue("vehicles", list)
+				setTimeout(() => {
+					uni.reLaunch({
+						url: `/pages/index/index?connectedIp=${info.ip}`
+					})
+				}, 1000)
+			},
+			checkConnectVehicle() {
+				if (this.unloadFlag) {
+					return
+				}
+				checkIpLinkSuccess(this.ip).then((res) => {
+					if (res.code) {
+						this.connectState = 3
+					} else {
+						this.connectState = 2
+						this.connectedSuccess()
+					}
+				}).catch((ex) => {
+					setTimeout(() => {
+						this.checkConnectVehicle()
+					}, 2000)
+				})
+			},
+			showError(ex) {
+				let exStr = JSON.stringify(ex)
+				if (exStr == "{}")
+					exStr = ex
+				let tip = typeof ex.msg == "string" ? ex.msg : exStr
+				showModal(tip, "閿欒", false)
+			},
+
+		}
+	}
+</script>
+
+<style lang="scss">
+	.pages-vehicle-connect {
+		display: flex;
+		width: 750rpx;
+		height: 100vh;
+		flex-direction: column;
+
+		.content {
+			padding: 20rpx 40rpx;
+			align-items: center;
+			text-align: center;
+			flex: 1;
+			display: flex;
+			flex-direction: column;
+			font-size: 36rpx;
+			font-weight: 400;
+
+			.title {
+				font-size: 40rpx;
+				font-weight: 700;
+			}
+
+			.content2 {
+				margin: auto;
+				padding-bottom: 80rpx;
+
+				.img {
+					width: 280rpx;
+					height: 280rpx;
+					margin-bottom: 50rpx;
+				}
+
+				.img-2 {
+					margin-top: 50rpx;
+					width: 300rpx;
+					height: 360rpx;
+
+				}
+
+				.auto-circle {
+					margin-bottom: 50rpx;
+					width: 200rpx;
+					height: 200rpx;
+					border-radius: 50%;
+					border: 30rpx solid #1890FF;
+					border-top-color: transparent;
+					animation: drawCircle 1s infinite linear;
+				}
+
+				@keyframes drawCircle {
+					0% {
+						transform: rotate(0deg);
+					}
+
+					100% {
+						transform: rotate(360deg);
+					}
+				}
+
+			}
+
+		}
+
+		.button-group {
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			flex-direction: column;
+			font-size: 30rpx !important;
+
+			.button {
+				margin: 20rpx !important;
+				width: 320rpx !important;
+				border-radius: 4rpx;
+			}
+		}
+
+		.link-text {
+			padding: 20rpx;
+			width: calc(100% - 40rpx);
+			align-items: center;
+			text-align: center;
+		}
+
+
+	}
+</style>
\ No newline at end of file
diff --git a/pages/index/detail.vue b/pages/index/detail.vue
new file mode 100644
index 0000000..94db021
--- /dev/null
+++ b/pages/index/detail.vue
@@ -0,0 +1,249 @@
+<template>
+	<view class="pages-vehicle-detail">
+		<uni-nav-bar :fixed="true" status-bar right-text="" left-text="" leftWidth="72rpx" rightWidth="72rpx"
+			:title="navigationBarTitle">
+			<view class="uni-navbar-container-inner">
+				<text class="uni-nav-bar-text">{{navigationBarTitle }}</text>
+			</view>
+			<template v-slot:right>
+				<view class="uni-navbar-btn-text">
+					<a @click="clickSave" class="uni-nav-bar-right-text">
+						淇濆瓨
+					</a>
+				</view>
+
+			</template>
+			<template v-slot:left>
+				<view class="uni-navbar-btn-text">
+					<a @click="clickCancel" class="uni-nav-bar-left-text">
+						鍙栨秷
+					</a>
+				</view>
+
+			</template>
+		</uni-nav-bar>
+		<view class="content">
+			<view class="group">
+				<view class="item line">
+					<view>鍚嶇О锛�/view>
+					<input class="input" v-model="vehicleName"> </input>
+				</view>
+				<view class="item line">
+					<view>ip鍦板潃锛�/view>
+					<view class="text">{{vehicleInfo.ip }} </view>
+				</view>
+				<view class="item line">
+					<view>鍨嬪彿锛�/view>
+					<view class="text">{{vehicleInfo.model_number|| ""}}</view>
+				</view>
+				<view class="item line">
+					<view>杞﹁浇鐗堟湰锛�/view>
+					<view class="text">{{car_version|| ""}}</view>
+				</view>
+				<view class="item line">
+					<view>鎺堟潈鏈夋晥鏈燂細</view>
+					<view class="text">{{vehicleInfo.authorization_period|| ""}}</view>
+				</view>
+				<!-- <view class="item" @click="clickUpgrade">
+					<view>鍥轰欢鐗堟湰锛�/view>
+					<view class="text2">{{firmware_version|| ""}}</view>
+					<a>
+						<uni-icons color="#888" type="right" size="24"></uni-icons>
+					</a>
+				</view> -->
+			</view>
+			<view class="group">
+				<view class="item line">
+					<view>鏃犵嚎灞�煙缃戝湴鍧�細</view>
+					<!-- 	<input class="input" v-model="vehicleInfo.wifi.mac"> </input> -->
+					<view class="text">{{vehicleInfo.wifi?.mac|| ""}}</view>
+				</view>
+				<!-- <view class="item">
+					<view>钃濈墮锛�/view>
+					<view class="text">{{vehicleInfo.bluetooth|| ""}}</view>
+				</view> -->
+			</view>
+			<a-button  type="ghost" class="button" @click="clickDelete">鍒犻櫎杞﹁締</a-button>
+		</view>
+
+	</view>
+</template>
+<script>
+	import {
+		showToast,
+		showModal
+	} from "@/comm/utils.js"
+	import {
+		Button
+	} from 'antd-mobile-vue-next'
+	import {
+		shellVersion,
+	} from "@/api/vehicle.js"
+	export default {
+		name: "PagesVehicleDetail",
+		components: {
+			'a-button': Button
+		},
+		data() {
+			return {
+				vehicleIp: '',
+				navigationBarTitle: '',
+				vehicleInfo: {},
+				car_version: "",
+				vehicleName: "",
+			}
+		},
+		onLoad(option) {
+			if (option.param)
+				this.vehicleInfo = JSON.parse(option.param)
+
+			this.navigationBarTitle = ""
+			this.vehicleName = this.vehicleInfo?.name || ""
+			this.vehicleIp = this.vehicleInfo?.ip || ""
+			this.loadVersion()
+		},
+		methods: {
+			setData(obj) {
+				let that = this;
+				let keys = [];
+				let val, data;
+
+				Object.keys(obj).forEach(function(key) {
+					keys = key.split(".");
+					val = obj[key];
+					data = that.$data;
+					keys.forEach(function(key2, index) {
+						if (index + 1 == keys.length) {
+							that.$set(data, key2, val);
+						} else {
+							if (!data[key2]) {
+								that.$set(data, key2, {});
+							}
+						}
+						data = data[key2];
+					});
+				});
+			},
+			async loadVersion() {
+				try {
+					const info = await shellVersion(this.vehicleIp)
+					this.car_version = info.software_version
+				} catch (ex) {
+					this.showError(ex)
+				}
+			},
+			clickDelete() {
+				showModal(`纭畾瑕佸垹闄よ澶団�${ this.vehicleInfo.name}鈥濆悧`, "璀﹀憡").then((res) => {
+					if (res) {
+						const eventChannel = this.getOpenerEventChannel();
+						eventChannel.emit('delete_vehicle', this.vehicleInfo);
+						uni.navigateBack({
+							delta: 1, //杩斿洖灞傛暟锛�鍒欎笂涓婇〉
+						})
+					}
+
+				})
+			},
+			clickUpgrade() {
+				uni.navigateTo({
+					url: "/pages/vehicle/upgrade"
+				})
+			},
+			clickSave() {
+				this.vehicleInfo.name = this.vehicleName || this.vehicleInfo.name || this.vehicleInfo.ip
+
+				const eventChannel = this.getOpenerEventChannel();
+				eventChannel.emit('update_vehicle', this.vehicleInfo);
+
+				uni.navigateBack({
+					delta: 1, //杩斿洖灞傛暟锛�鍒欎笂涓婇〉
+				})
+			},
+			clickCancel() {
+				uni.navigateBack({
+					delta: 1
+				})
+			},
+			showError(ex) {
+				let exStr = JSON.stringify(ex)
+				if (exStr == "{}")
+					exStr = ex
+				let tip = typeof ex.msg == "string" ? ex.msg : exStr
+				showModal(tip, "閿欒", false)
+			},
+
+		}
+	}
+</script>
+
+<style lang="scss">
+	.pages-vehicle-detail {
+		display: flex;
+		width: 750rpx;
+		height: 100vh;
+		flex-direction: column;
+		background-color: #F4F4F4;
+
+		// .uni-nav-bar-left-text {
+		// 	font-size: 32rpx;
+		// }
+
+		// .uni-nav-bar-right-text {
+		// 	font-size: 32rpx;
+		// }
+
+		.content {
+			width: 750rpx;
+			flex: 1;
+
+			.group {
+				width: calc(100% - 60rpx);
+				border-radius: 20rpx;
+				margin: 20rpx;
+				padding-left: 20rpx;
+				display: flex;
+				flex-direction: column;
+				background-color: #FFF;
+
+				.item {
+					width: 100%;
+					padding: 20rpx 0;
+					display: flex;
+					flex-direction: row;
+
+					.text {
+						flex: 1;
+						text-align: right;
+						color: #ccc;
+						padding-right: 40rpx;
+					}
+
+					.input {
+						flex: 1;
+						text-align: right;
+						padding-right: 40rpx;
+					}
+
+					.text2 {
+						flex: 1;
+						text-align: right;
+						color: #ccc;
+					}
+
+				}
+
+				.line {
+					border-bottom: 1px solid #F5F5F5;
+				}
+			}
+
+			.button {
+				margin: 20rpx !important;
+				width: calc(100% - 40rpx);
+				border-radius: 4rpx;
+
+				color: red;
+			}
+		}
+	}
+</style>
\ No newline at end of file
diff --git a/pages/index/index.vue b/pages/index/index.vue
new file mode 100644
index 0000000..d3e179b
--- /dev/null
+++ b/pages/index/index.vue
@@ -0,0 +1,884 @@
+<template>
+	<view class="pages-main">
+		<uni-nav-bar :fixed="true" status-bar right-text="" left-text="" :leftWidth="0" rightWidth="72px"
+			:title="navigationBarTitle">
+			<view class="uni-navbar-container-inner">
+				<text class="uni-nav-bar-text">{{navigationBarTitle }}</text>
+			</view>
+			<template v-slot:right>
+				<view v-if="currentPage < pageList.length">
+					<a @click="clickScanCode">
+						<uni-icons class="uni-panel-bar-icon" type="scan" size="28"></uni-icons>
+					</a>
+					<a @click="clickMore">
+						<uni-icons class="uni-panel-bar-icon" type="more-filled" size="28"></uni-icons>
+					</a>
+				</view>
+
+			</template>
+		</uni-nav-bar>
+		<swiper v-if="pageList.length > 0" circular indicator-dots class="swiper" :current="currentPage"
+			@change="changeSwiper">
+			<swiper-item v-for="(page,index) in pageList" class="swiper-item">
+				<view class="vehicle-header">
+					<view class="link-view">
+						<view v-if="page.link_status">
+							<!-- <image class="img-battery-charging" src="/images/bx_battery3.svg" alt="SVG 鍥剧墖" /> -->
+							<image class="img-battery-charging" src="/images/bx_battery2.svg" alt="SVG 鍥剧墖" />
+							<image class="img-battery-soc" :style="{width:(page.soc*0.4)+'rpx'}"
+								src="/images/bx_battery4.svg" alt="SVG 鍥剧墖" />
+
+						</view>
+						<view v-else>
+							<image class="img-battery" src="/images/bx_battery1.svg" alt="SVG 鍥剧墖" />
+						</view>
+						<template v-if="page.link_status">
+							<view class="soc-text">{{page.soc}}%</view>
+							<view class="status-text">{{getAgvStateText(page)}}</view>
+						</template>
+
+
+						<view v-else class="gray-text">宸茬绾�/view>
+					</view>
+				</view>
+				<image class="vehicle-img " :class="page.link_status ?'':'gray-image'" mode="aspectFit"
+					src="/images/image 11.png" alt="鍥剧墖" />
+				<view v-if="page.link_status" class="img-button-group">
+					<view type="primary" class="img-text-button" @click="clickToTask(index,page)">
+						<a-button class="img-button" color='primary' disabled>
+							<text class="ico task-list" />
+						</a-button>
+						<text>浠诲姟鍒楄〃</text>
+					</view>
+					<view type="primary" plain="true" class="img-text-button" @click="clickToMap(index,page)">
+						<a-button class="img-button" color='primary'>
+							<text class="ico map" />
+						</a-button>
+						<text>杩涘叆鍦板浘</text>
+
+					</view>
+				</view>
+				<view v-else class="unlink-content">
+					<view class="content2" v-if="page.conntecting">
+						<view class="auto-circle"></view>
+
+						<view class="text">杩炴帴涓�..</view>
+					</view>
+					<view class="content2" v-else>
+						<view class="text"> 杞﹁締宸茬绾匡紝璇烽噸鏂拌繛鎺�/view>
+						<a-button type="primary" class="button" @click="clickRelink">閲嶆柊杩炴帴
+						</a-button>
+					</view>
+
+				</view>
+
+
+			</swiper-item>
+			<swiper-item class="swiper-item">
+
+				<image class="title-img gray-image" src="/images/image 15.png" alt="鍥剧墖" />
+				<view class="button-group">
+					<a-button type="primary" class="button" @click="clickScanCode">鎵弿娣诲姞璁惧</a-button>
+					<a-button type="ghost" class="button" @click="clickManualAdd">鎵嬪姩娣诲姞璁惧</a-button>
+				</view>
+			</swiper-item>
+		</swiper>
+		<view v-else class="no-page items-center">
+			<view class="content ">
+				<image class="title-img gray-image" src="/images/image 15.png" alt="鍥剧墖" />
+				<view class="button-group">
+					<a-button type="primary" class="button" @click="clickScanCode">鎵弿娣诲姞璁惧</a-button>
+					<a-button type="ghost" class="button" @click="clickManualAdd">鎵嬪姩娣诲姞璁惧</a-button>
+				</view>
+			</view>
+		</view>
+		<view>
+			<uni-popup ref="refPopupInput" type="dialog">
+				<uni-popup-dialog mode="input" title="杈撳叆杞﹁締IP" :value="inputPopupValue" placeholder="杞﹁締IP"
+					:beforeClose="true" @confirm="dialogInputConfirm" @close="dialogInputClose"></uni-popup-dialog>
+			</uni-popup>
+			<!-- 		<uni-popup ref="refPopupMessage" type="dialog">
+				<uni-popup-dialog type="info" title="" :content="inputPopupValue" 
+					 @confirm="dialogMessageConfirm"></uni-popup-dialog>
+			</uni-popup> -->
+			<uni-popup ref="refPopupMenu" background-color="transparent" maskBackgroundColor="rgba(0, 0, 0, 0.2)">
+				<view class="popup-content" @click="closeMenu">
+					<view class="popup-content-menu ">
+						<a-button class="popup-content-menu-item" v-for="(item,index) in menuList" :key="index"
+							@click="menuItemChange(item)" :style="{'color':item.color}">
+							<view class="text">{{item.text}}</view>
+							<text class="ico" :class="item.ico" />
+						</a-button>
+					</view>
+				</view>
+			</uni-popup>
+		</view>
+	</view>
+</template>
+
+<script>
+	import {
+		ref
+	} from "vue";
+	import {
+		session,
+		showToast,
+		showModal
+	} from "@/comm/utils.js"
+	import {
+		mtBattery,
+		getAgvState,
+		checkIpLinkSuccess,
+	} from "@/api/vehicle.js"
+	import {
+		Button
+	} from 'antd-mobile-vue-next'
+	import {
+		async
+	} from "rxjs";
+	export default {
+		name: "PagesMain",
+		components: {
+			'a-button': Button
+		},
+		data() {
+			return {
+				navigationBarTitle: "",
+				currentPage: 0,
+				pageList: [],
+				timerBatteryId: 0,
+				inputPopupValue: "",
+				menuList: [{
+					ico: "edit-line",
+					text: "缂栬緫",
+					color: "black"
+				}, {
+					ico: "update",
+					text: "鏇存柊",
+					color: "black"
+				}, {
+					ico: "book",
+					text: "鏁欑▼",
+					color: "black"
+				}, {
+					ico: "share",
+					text: "鍏变韩",
+					color: "black"
+				}, {
+					ico: "copy",
+					text: "澶囦唤",
+					color: "black"
+				}, {
+					ico: "delete-outline",
+					text: "鍒犻櫎",
+					color: "red"
+				}]
+
+			}
+		},
+		onShow() {
+			console.log("show")
+			if (this.timerBatteryId) {
+				clearInterval(this.timerBatteryId)
+			}
+			setTimeout(() => {
+				this.loadVehicleBattery()
+			}, 2000)
+			this.timerBatteryId = setInterval(() => {
+				this.loadVehicleBattery()
+			}, 60 * 1000)
+
+		},
+		onHide() {
+			if (this.timerBatteryId) {
+				clearInterval(this.timerBatteryId)
+				this.timerBatteryId = 0
+			}
+		},
+		onLoad(option) {
+			const ip = option.connectedIp || ""
+			this.loadData(ip)
+			console.log("hide")
+		},
+		computed: {
+
+		},
+		methods: {
+			setData(obj) {
+				let that = this;
+				let keys = [];
+				let val, data;
+
+				Object.keys(obj).forEach(function(key) {
+					keys = key.split(".");
+					val = obj[key];
+					data = that.$data;
+					keys.forEach(function(key2, index) {
+						if (index + 1 == keys.length) {
+							that.$set(data, key2, val);
+						} else {
+							if (!data[key2]) {
+								that.$set(data, key2, {});
+							}
+						}
+						data = data[key2];
+					});
+				});
+			},
+			async loadData(ip) {
+
+				try {
+
+					let list = session.getValue("vehicles") || []
+
+					list.forEach((page) => {
+						page.soc = 0
+						page.link_status = false
+					})
+					let curIndex = -1
+					if (ip)
+						curIndex = list.findIndex((a) => a.ip == ip)
+					if (curIndex < 0) {
+
+						this.pageList = list
+						if (this.pageList.length > 0)
+							this.navigationBarTitle = this.pageList[0].name
+						else
+							this.navigationBarTitle = "娣诲姞璁惧"
+						for (let i in list) {
+							const page = list[i]
+							const battery = await this.loadMTBattery(page.ip)
+							if (battery > -1) {
+								page.soc = battery
+								page.status = await this.loadAgvState(page.ip)
+								page.link_status = true
+								this.setData({
+									currentPage: i
+								})
+								break
+							}
+						}
+
+						this.pageList = [...list]
+					} else {
+						this.setData({
+							currentPage: curIndex
+						})
+						const page = list[curIndex]
+						const battery = await this.loadMTBattery(page.ip)
+						if (battery > -1) {
+							page.soc = battery
+							page.link_status = true
+							page.status = await this.loadAgvState(page.ip)
+						} else {
+							page.link_status = false
+						}
+
+						this.pageList = [...list]
+						this.navigationBarTitle = page.name
+					}
+				} catch (ex) {
+
+					this.showError(ex)
+				}
+			},
+
+			async loadVehicleBattery() {
+				try {
+					
+					const list = this.pageList
+					if (this.currentPage < list.length && this.currentPage > -1) {
+						const page = list[this.currentPage]
+						const battery = await this.loadMTBattery(page.ip)
+						if (battery > -1) {
+							page.soc = battery
+							page.status = await this.loadAgvState(page.ip)
+							page.link_status = true
+
+						} else {
+							page.soc = 0
+							page.link_status = false
+						}
+					}
+					this.pageList = [...list]
+
+				} catch (ex) {
+					this.showError(ex)
+				}
+
+			},
+			async loadMTBattery(ip) {
+				try {
+					let battery = await mtBattery(ip)
+					let str = `${battery}`
+					str = str.trim()
+					str = str.replace("%", "")
+					battery = parseInt(str)
+					return battery
+				} catch (ex) {
+
+					return -1
+				}
+
+			},
+
+
+			async loadAgvState(ip) {
+				try {
+					let info = await getAgvState(ip)
+					return info.status || 0
+				} catch (ex) {
+
+					return 0
+				}
+
+			},
+			getAgvStateText(page) {
+				let text = ""
+				if (page.status == 1) {
+					text = "绌洪棽涓�
+				} else if (page.status == 2) {
+					text = "宸ヤ綔涓�
+				} else if (page.status == 3) {
+					text = "鏁呴殰"
+				} else {
+					text = `鐘舵�${page.status}`
+				}
+				return text
+			},
+			async checkPageConnected(index) {
+				try {
+					const list = this.pageList
+					const page = list[index]
+					let battery = await this.loadMTBattery(page.ip)
+					if (battery > -1) {
+						page.soc = battery
+						page.link_status = true
+						page.status = await this.loadAgvState(page.ip)
+					} else {
+						page.link_status = false
+					}
+					this.pageList = [...list]
+				} catch (ex) {
+
+
+				}
+
+			},
+			changeSwiper(evt) {
+
+				let index = evt.target.current || evt.detail.current;
+				this.setData({
+					currentPage: index
+				})
+				if (this.pageList.length == this.currentPage)
+					this.navigationBarTitle = "娣诲姞璁惧"
+				else
+					this.navigationBarTitle = this.pageList[this.currentPage].name
+			},
+			async clickRelink() {
+				try {
+
+					const page = this.pageList[this.currentPage]
+					page.conntecting = true
+					let res = await this.checkConnectSuccess(page.ip)
+					if (!res) {
+						page.conntecting = false
+						uni.navigateTo({
+							url: `/pages/index/connect?ip=${ page.ip}&sid=${ page.wifi?.sid || ""}&reconnect=true`
+						})
+					} else {
+						page.conntecting = false
+						const list = this.pageList
+						list.forEach((page2) => {
+							if (page.ip != page2.ip) {
+								page2.soc = 0
+								page2.link_status = false
+							}
+						})
+						page.connectState = 2
+						const battery = await this.loadMTBattery(page.ip)
+						if (battery > -1) {
+							page.soc = battery
+							page.link_status = true
+							page.status = await this.loadAgvState(page.ip)
+							this.setData({
+								pageList: list
+							})
+						}
+					}
+				} catch (ex) {
+					this.showError(ex)
+				}
+			},
+			async checkConnectSuccess(ip) {
+				try {
+					const res = await checkIpLinkSuccess(ip)
+					return true
+				} catch (ex) {
+					return false
+				}
+
+			},
+
+
+			clickScanCode() {
+				const that = this
+				uni.scanCode({
+					scanType: ["qrCode"],
+					success: function(res) {
+						console.log(res)
+						const result = res.result || ""
+						const arCode = result.split(";")
+						if (arCode.length != 3) {
+							showToast("鏃犳晥鐨勪簩缁寸爜锛�)
+							return
+						}
+						let ip = arCode[0].trim()
+						if (!ip || !arCode[0].trim()) {
+							showToast("鏃犳晥鐨勪簩缁寸爜锛�)
+							return
+						}
+						const curIndex = that.pageList.findIndex((a) => a.ip == ip)
+						if (curIndex < 0) {
+							if (that.pageList.length === 3) {
+								showToast("瀵瑰鍙厑璁告坊鍔�杈嗚溅锛�)
+								return
+							}
+							uni.navigateTo({
+								url: `/pages/index/connect?ip=${ ip}&sid=${ arCode[1]}&password=${ arCode[2]}`
+							})
+						} else {
+							showToast("涓嶅厑璁告坊鍔犵浉鍚孖P鐨勮澶囷紒")
+						}
+					},
+				})
+
+			},
+			clickManualAdd() {
+				this.inputPopupValue = ""
+				this.$refs.refPopupInput.open()
+			},
+			clickToTask(index, page) {
+				showToast("璇ュ姛鑳借繕鍦ㄥ紑鍙戜腑")
+				// uni.navigateTo({
+				// 	url: `/pages/task/index?ip=${page.ip}`
+				// })
+			},
+			clickMore() {
+				if (this.currentPage < this.pageList.length) {
+					this.$refs.refPopupMenu.open("top")
+				}
+
+			},
+			clickInfo(page) {
+				const that = this
+				uni.navigateTo({
+					url: `/pages/index/detail?param=${JSON.stringify(page)}`,
+					events: {
+						// 涓烘寚瀹氫簨浠舵坊鍔犱竴涓洃鍚櫒锛岃幏鍙栬鎵撳紑椤甸潰浼犻�鍒板綋鍓嶉〉闈㈢殑鏁版嵁
+						delete_vehicle: function(data) {
+							const list = that.pageList
+							const index = that.currentPage
+							list.splice(index, 1)
+							that.setData({
+								currentPage: index,
+								pageList: list
+							})
+							session.setValue("vehicles", list)
+							if (list.length > 0)
+								that.navigationBarTitle = that.pageList[that.currentPage].name
+							else
+								that.navigationBarTitle = "娣诲姞璁惧"
+						},
+						update_vehicle: function(data) {
+							console.log("update_vehicle", data)
+							const list = that.pageList
+							Object.assign(list[that.currentPage], data)
+							that.setData({
+								pageList: list
+							})
+							session.setValue("vehicles", list)
+							that.navigationBarTitle = list[that.currentPage].name
+						},
+					}
+				})
+			},
+
+			clickToMap(index, page) {
+				const _this = this
+				uni.navigateTo({
+					url: `/pages/map/index?ip=${page.ip}`,
+					events: {
+						// 涓烘寚瀹氫簨浠舵坊鍔犱竴涓洃鍚櫒锛岃幏鍙栬鎵撳紑椤甸潰浼犻�鍒板綋鍓嶉〉闈㈢殑鏁版嵁
+						check_connect: function(flag) {
+							page.link_status = flag
+							_this.checkPageConnected(index)
+						},
+					}
+				})
+			},
+			isValidIP(ip) {
+				// IPv4 鍦板潃姝e垯琛ㄨ揪寮�+				const ipRegex =
+					/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
+
+				// 妫�煡鏄惁绗﹀悎 IPv4 鍦板潃鏍煎紡
+				return ipRegex.test(ip);
+			},
+			dialogInputConfirm(val) {
+
+				let text = val.trim()
+				if (!text) {
+					showToast("璇疯緭鍏ヨ溅杈咺P锛�)
+					this.$refs.refPopupInput.open()
+					return
+				}
+				if (!this.isValidIP(text)) {
+					showToast("IP鏃犳晥锛�)
+					this.$refs.refPopupInput.open()
+					return
+				}
+
+
+				this.$refs.refPopupInput.close()
+
+				const curIndex = this.pageList.findIndex((a) => a.ip == text)
+				if (curIndex < 0) {
+					if (this.pageList.length === 3) {
+						showToast("瀵瑰鍙厑璁告坊鍔�杈嗚溅锛�)
+						return
+					}
+					uni.navigateTo({
+						url: `/pages/index/connect?ip=${text}`
+					})
+				} else {
+					showToast("涓嶅厑璁告坊鍔犵浉鍚孖P鐨勮澶囷紒")
+					return
+				}
+
+
+			},
+			dialogInputClose() {
+				this.$refs.refPopupInput.close()
+			},
+			menuItemChange(item) {
+				if (item.text == "缂栬緫") {
+					const page = this.pageList[this.currentPage]
+					this.clickInfo(page)
+
+				} else if (item.text == "鍒犻櫎") {
+					const page = this.pageList[this.currentPage]
+					showModal(`纭畾瑕佸垹闄よ澶団�${ page.name}鈥濆悧`, "璀﹀憡").then((res) => {
+						if (res) {
+							const list = this.pageList
+							const curPage = this.currentPage
+							list.splice(this.currentPage, 1)
+							this.setData({
+								currentPage: curPage,
+								pageList: list
+							})
+							session.setValue("vehicles", list)
+							if (list.length > 0)
+								this.navigationBarTitle = this.pageList[this.currentPage].name
+							else
+								this.navigationBarTitle = "娣诲姞璁惧"
+
+						}
+					})
+				}
+			},
+			showError(ex) {
+				let exStr = JSON.stringify(ex)
+				if (exStr == "{}")
+					exStr = ex
+				let tip = typeof ex.msg == "string" ? ex.msg : exStr
+				showModal(tip, "閿欒", false)
+			},
+			closeMenu() {
+				this.$refs.refPopupMenu.close()
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.pages-main {
+		display: flex;
+		width: 750rpx;
+		height: 100vh;
+		flex-direction: column;
+		font-size: 30rpx;
+		background-color: #fff;
+
+		.justify-center {
+			justify-content: center;
+		}
+
+		.items-center {
+			align-items: center
+		}
+
+		.swiper {
+			flex: 1;
+			width: 100%;
+
+
+			.swiper-item {
+				width: 100%;
+				height: 100vh;
+				display: flex;
+				flex-direction: column;
+
+				.vehicle-header {
+
+					width: 700rpx;
+					margin-left: 20rpx;
+
+
+					.link-view {
+						width: 100%;
+						height: 80rpx;
+						position: relative;
+
+						.img-battery {
+							position: absolute;
+							left: 0;
+							width: 64rpx;
+							height: 64rpx;
+						}
+
+						.img-battery-charging {
+							position: absolute;
+							left: 0;
+							width: 65rpx;
+							height: 64rpx;
+						}
+
+						.img-battery-charging2 {
+							position: absolute;
+							left: 0;
+							width: 90rpx;
+							height: 64rpx;
+						}
+
+						.img-battery-soc {
+							position: absolute;
+							left: 10rpx;
+							top: 21rpx;
+							width: 40rpx;
+							height: 22rpx;
+							background-color: #73D13D;
+						}
+
+						.gray-text {
+							position: absolute;
+							left: 90rpx;
+							height: 72rpx;
+							line-height: 72rpx;
+							color: #ccc;
+						}
+
+
+						.soc-text {
+							border-width: 0px;
+							position: absolute;
+							left: 90rpx;
+							height: 72rpx;
+							line-height: 72rpx;
+						}
+
+						.status-text {
+							border-width: 0px;
+							position: absolute;
+							left: 160rpx;
+							height: 72rpx;
+							line-height: 72rpx;
+						}
+
+						.charge2 {
+							background-color: #fff;
+						}
+
+					}
+				}
+
+
+				.img-button-group {
+					display: flex;
+					justify-content: center;
+					align-items: center;
+					flex-direction: row;
+
+
+					.img-text-button {
+						display: flex;
+						align-items: center;
+						justify-content: center;
+						flex-direction: column;
+						margin: 50rpx;
+
+						.img-button {
+							display: flex;
+							width: 160rpx !important;
+							height: 160rpx !important;
+							align-items: center;
+							justify-content: center;
+
+							.ico {
+								font-size: 72rpx;
+								color: #1890FF;
+							}
+
+
+						}
+
+						text {
+							margin-top: 20rpx;
+						}
+
+					}
+				}
+
+			}
+		}
+
+		.no-page {
+			display: flex;
+			width: 100%;
+			flex: 1;
+
+			.content {
+				width: 750rpx;
+				display: flex;
+				flex-direction: column;
+
+			}
+
+		}
+
+		.title-img {
+			margin-top: 40rpx;
+			display: block;
+			margin-left: calc(50% - 180rpx);
+			width: 360rpx;
+			height: 500rpx;
+		}
+
+		.vehicle-img {
+			margin-top: 20rpx;
+			margin-left: calc(50% - 280rpx);
+			display: block;
+			width: 560rpx;
+			height: 560rpx;
+
+		}
+
+		.gray-image {
+			filter: grayscale(100%);
+			opacity: 0.5;
+		}
+
+		.unlink-content {
+			width: 100%;
+			flex: 1;
+
+			.content {
+				align-items: center;
+				text-align: center;
+				display: flex;
+				flex-direction: column;
+				font-size: 36rpx;
+				font-weight: 400;
+			}
+
+			.content2 {
+				margin: auto;
+
+				.auto-circle {
+					margin: auto;
+					width: 160rpx;
+					height: 160rpx;
+					border-radius: 50%;
+					border: 28rpx solid #1890FF;
+					border-top-color: transparent;
+					animation: drawCircle 1s infinite linear;
+				}
+
+				@keyframes drawCircle {
+					0% {
+						transform: rotate(0deg);
+					}
+
+					100% {
+						transform: rotate(360deg);
+					}
+				}
+
+				.text {
+					text-align: center;
+					margin-top: 20rpx;
+					margin-bottom: 20rpx;
+				}
+
+			}
+
+		}
+
+		.button-group {
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			flex-direction: column;
+			font-size: 30rpx !important;
+		}
+
+		.button {
+			margin: auto;
+			margin-top: 20rpx;
+			width: 320rpx !important;
+			border-radius: 4rpx;
+		}
+
+		.popup-content {
+			display: flex;
+			justify-content: center;
+			flex-direction: column;
+			background-color: transparent;
+		}
+
+		.popup-content-menu {
+			margin-top: 150rpx;
+			margin-left: calc(750rpx - 330rpx);
+			width: 320rpx;
+			align-items: center;
+			justify-content: center;
+			flex-direction: column;
+			background-color: #fff;
+			border-radius: 4rpx;
+			border: 2rpx solid gray;
+		}
+
+		.popup-content-menu-item {
+			display: flex;
+			flex-wrap: nowrap;
+			flex-direction: row !important;
+			align-items: center;
+			padding: 8rpx 16rpx;
+			font-size: 32rpx;
+
+			.text {
+				flex: 1;
+			}
+
+			.img {
+				width: 40rpx;
+				height: 40rpx;
+				margin: 10rpx;
+			}
+		}
+
+
+
+	}
+</style>
\ No newline at end of file
diff --git a/pages/login/forgot-password.vue b/pages/login/forgot-password.vue
new file mode 100644
index 0000000..599b55e
--- /dev/null
+++ b/pages/login/forgot-password.vue
@@ -0,0 +1,217 @@
+<template>
+	<view class="pages-login-forgot-password">
+		<view class="uni-panel-content items-center">
+			<view class="login-content">
+				<view class="justify-center">
+					<image class="title-img" src="/images/earth.svg" alt="svg 鍥剧墖" />
+				</view>
+				<view class="login-form">
+					<view class="login-form-item ">
+						<image class="icon" src="/images/mobile.svg" alt="svg 鍥剧墖" />
+						<input class="input" :focus="formData.accountFocus" name="account" comfirm-type="done"
+							type="text" v-model="form.account" placeholder="杈撳叆鎵嬫満鍙风爜" />
+					</view>
+					<view class="login-form-item ">
+						<image class="icon" src="/images/chat.svg" alt="svg 鍥剧墖" />
+						<input class="input" comfirm-type="done" v-model="form.mobileCode" placeholder="鐭俊楠岃瘉鐮� />
+						<view v-if="disabledSendCode" class="disabled">{{sendCodeCountdown}}绉掑悗閲嶆柊鍙戦�</view>
+						<a v-else @click="clickSendVerifyCode">鍙戦�楠岃瘉鐮�/a>
+
+					</view>
+					<view class="login-form-item ">
+						<image class="icon" src="/images/lock.svg" alt="svg 鍥剧墖" />
+						<input class="input" :focus="formData.passwordFocus" name="password" password
+							comfirm-type="done" v-model="form.password" placeholder="璁剧疆鐧诲綍瀵嗙爜" />
+
+					</view>
+
+					<view class="button-group">
+						<a-button :disabled="disabledOk" type="primary" class="button" @click="clickOk">纭</a-button>
+					</view>
+				</view>
+
+			</view>
+		</view>
+
+	</view>
+</template>
+
+<script>
+	import {
+		showToast,
+		showModal
+	} from "@/comm/utils.js"
+	import {
+		Button
+	} from 'antd-mobile-vue-next'
+	export default {
+		name: "PagesLoginForgotPassword",
+		components: {
+			'a-button': Button
+		},
+		data() {
+			return {
+				form: {
+					account: '',
+					password: '',
+					mobileCode: "",
+				},
+				formData: {
+					accountFocus: true,
+					passwordFocus: false
+				},
+				hidePassContent: false,
+				disabledSendCode: false,
+				sendCodeCountdown: 0,
+			}
+		},
+		computed: {
+			disabledOk() {
+				let text = this.form.account.trim()
+				if (!text) {
+					return true
+				}
+				text = this.form.password.trim()
+				if (!text) {
+					return true
+				}
+				text = this.form.mobileCode.trim()
+				if (!text) {
+					return true
+				}
+				return false
+			}
+		},
+
+		methods: {
+			setData(obj) {
+				let that = this;
+				let keys = [];
+				let val, data;
+
+				Object.keys(obj).forEach(function(key) {
+					keys = key.split(".");
+					val = obj[key];
+					data = that.$data;
+					keys.forEach(function(key2, index) {
+						if (index + 1 == keys.length) {
+							that.$set(data, key2, val);
+						} else {
+							if (!data[key2]) {
+								that.$set(data, key2, {});
+							}
+						}
+						data = data[key2];
+					});
+				});
+			},
+
+			clickOk() {
+				uni.reLaunch({
+					url: "/pages/login/index"
+				})
+			},
+			clickSendVerifyCode() {
+				if (this.disabledSendCode) {
+					return
+				}
+				let text = this.form.account.trim()
+				if (!text) {
+					showToast("璇疯緭鍏ユ墜鏈哄彿")
+					return
+				}
+				this.sendCodeCountdown = 60
+				this.disabledSendCode = true
+				const idInterval = setInterval(() => {
+					if (this.sendCodeCountdown > 0) {
+						this.sendCodeCountdown--
+					} else {
+						this.sendCodeCountdown = 0
+						clearInterval(idInterval);
+						this.disabledSendCode = false
+					}
+				}, 1000)
+			},
+
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.pages-login-forgot-password {
+		display: flex;
+		width: 750rpx;
+		height: 100vh;
+		flex-direction: column;
+
+		.uni-panel-content {
+			display: flex;
+			flex: 1;
+			width: 750rpx;
+		}
+
+		.login-content {
+			width: 750rpx;
+		}
+
+		.justify-center {
+			justify-content: center;
+		}
+
+		.items-center {
+			align-items: center
+		}
+
+		.title-img {
+			display: block;
+			margin: auto;
+			width: 300rpx;
+			height: 300rpx;
+		}
+
+		.login-form {
+			display: flex;
+			padding: 20rpx 40rpx;
+			flex-direction: column;
+		}
+
+		.login-form-item {
+			padding: 10rpx;
+			display: flex;
+			margin: 10rpx;
+			font-size: 30rpx !important;
+			flex-direction: row;
+			border-bottom: 2rpx solid #ddd;
+
+			.icon {
+				opacity: 0.3;
+				margin: 12rpx 20rpx;
+				width: 40rpx;
+				height: 40rpx;
+			}
+
+			.input {
+				flex: 1;
+				padding: 12rpx 16rpx;
+				background-color: transparent;
+			}
+
+		}
+
+		.button-group {
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			flex-direction: column;
+			font-size: 30rpx !important;
+		}
+
+		.button {
+			margin: auto;
+			margin-top: 20rpx;
+			width: 300rpx;
+		}
+
+
+	}
+</style>
\ No newline at end of file
diff --git a/pages/login/index.vue b/pages/login/index.vue
new file mode 100644
index 0000000..dd07fe2
--- /dev/null
+++ b/pages/login/index.vue
@@ -0,0 +1,323 @@
+<template>
+	<view class="pages-login">
+		<view class="uni-panel-content items-center">
+
+			<view class="login-content">
+				<view class="items-center">
+					<!-- <image class="title-img" src="/images/earth.svg" alt=" 鍥剧墖" /> -->
+
+				</view>
+				<text class="title">璇风櫥褰�/text>
+				<view class="login-form">
+					<view class="login-form-item line">
+						<text class="label">鐢ㄦ埛鍚�/text>
+						<input class="input" :focus="formData.accountFocus" comfirm-type="done" type="text"
+							v-model="form.account" placeholder="鎵嬫満鍙风爜" />
+					</view>
+
+					<view class="login-form-item line">
+						<text class="label">瀵嗙爜</text>
+						<input class="input" :focus="formData.passwordFocus" :password="hidePassContent"
+							comfirm-type="done" v-model="form.password" placeholder="鐧诲綍瀵嗙爜" />
+						<uni-icons :type="hidePassContent?'eye-slash':'eye'" size="28"
+							@click="clickHidePassContent"></uni-icons>
+					</view>
+					<view class="login-form-item">
+						<checkbox-group @change="handleSavePwdChange">
+							<label>
+								<checkbox value="1" :checked="savePsw" />
+								<text>璁颁綇瀵嗙爜</text>
+							</label>
+						</checkbox-group>
+
+
+						<!-- 	<a @click="clickForgotPassword">蹇樿瀵嗙爜</a> -->
+					</view>
+					<view class="button-group">
+						<a-button :disabled="disabledOk" type="primary" class="button" @click="clickLogin">鐧诲綍</a-button>
+						<!-- <a-button class="button" type="ghost"  @click="clickNewAccount">鍒涘缓璐﹀彿</a-button> -->
+					</view>
+				</view>
+
+			</view>
+		</view>
+		<view class="bottom">
+			<view class="version">
+				鐗堟湰锛歿{version}}
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import {
+		session,
+		showToast,
+		showModal
+	} from "@/comm/utils.js"
+	import {
+		Button
+	} from 'antd-mobile-vue-next'
+	export default {
+		name: "PagesLogin",
+		components: {
+			'a-button': Button
+		},
+		data() {
+
+			return {
+				form: {
+					account: '',
+					password: ''
+				},
+				formData: {
+					accountFocus: true,
+					passwordFocus: false
+				},
+				hidePassContent: true,
+				savePsw: false,
+				version: "1.0.0",
+			}
+		},
+		computed: {
+			disabledOk() {
+				// let text = this.form.account.trim()
+				// if (!text) {
+				// 	return true
+				// }
+				// text = this.form.password.trim()
+				// if (!text) {
+				// 	return true
+				// }
+				return false
+			}
+		},
+		onLoad() {
+
+			uni.getSystemInfo({
+				success(e) {
+					const app = getApp()
+					app.globalData.platform = e.platform
+					app.globalData.deviceModel = e.deviceModel
+					app.globalData.osVersion = parseInt(e.osVersion)
+					console.log(e)
+				},
+
+			})
+			const info = session.getValue("login_info")
+			console.log(info)
+			this.setData({
+				form: {
+					account: info?.id || '',
+					password: info?.password || ''
+
+				},
+				savePsw: info?.savePsw || false
+			})
+			// #ifdef APP-PLUS
+			plus.runtime.getProperty(plus.runtime.appid, (info) => {
+				// console.log(info);
+				this.version = info.version;
+			});
+			//#endif
+
+		},
+		methods: {
+			setData(obj) {
+				let that = this;
+				let keys = [];
+				let val, data;
+
+				Object.keys(obj).forEach(function(key) {
+					keys = key.split(".");
+					val = obj[key];
+					data = that.$data;
+					keys.forEach(function(key2, index) {
+						if (index + 1 == keys.length) {
+							that.$set(data, key2, val);
+						} else {
+							if (!data[key2]) {
+								that.$set(data, key2, {});
+							}
+						}
+						data = data[key2];
+					});
+				});
+			},
+			clickHidePassContent() {
+				this.hidePassContent = !this.hidePassContent
+			},
+			handleSavePwdChange(e) {
+
+				if (e.detail.value[0] == '1') {
+					this.savePsw = true
+				} else {
+					this.savePsw = false
+				}
+
+			},
+			clickLogin() {
+				let account = this.form.account.trim()
+				if (!account) {
+					showToast("璇疯緭鍏ユ墜鏈哄彿")
+					return
+				}
+				let password = this.form.password.trim()
+				if (!password) {
+					showToast("璇疯緭鍏ュ瘑鐮�)
+					return
+				}
+				if (account != "sa") {
+					showToast("鎵嬫満鍙蜂笉瀛樺湪")
+					return
+				}
+				if (password != "0000") {
+					showToast("瀵嗙爜閿欒")
+					return
+				}
+				if (this.savePsw) {
+
+					session.setValue("login_info", {
+						id: account,
+						password,
+						savePsw: true,
+					})
+				} else {
+					session.setValue("login_info", {
+						id: account,
+						password: ""
+					})
+				}
+
+				uni.reLaunch({
+					url: "/pages/index/index"
+				})
+				// uni.navigateTo({
+				// 	url: `/pages/index/connect?ip=192.168.1.2&sid=HH&password=HH888888`
+				// })
+			},
+			clickNewAccount() {
+				uni.navigateTo({
+					url: "/pages/login/register"
+				})
+			},
+			clickForgotPassword() {
+				uni.navigateTo({
+					url: "/pages/login/forgot-password"
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.pages-login {
+		display: flex;
+		width: 750rpx;
+		height: 100vh;
+		flex-direction: column;
+
+		.uni-panel-content {
+			display: flex;
+			flex: 1;
+			width: 750rpx;
+			flex-direction: column;
+		}
+
+		.bottom {
+			width: calc(100% - 40rpx);
+			padding: 10rpx 20rpx;
+
+			.version {
+				float: right;
+				color: #888;
+				flex-direction: row;
+				display: flex;
+			}
+		}
+
+		.login-content {
+			width: 750rpx;
+			display: flex;
+			flex-direction: column;
+		}
+
+		.justify-center {
+			justify-content: center;
+		}
+
+		.items-center {
+			align-items: center
+		}
+
+		.title-img {
+			display: block;
+			margin: auto;
+			width: 300rpx;
+			height: 300rpx;
+		}
+
+		.title {
+			font-size: 40rpx;
+			margin: auto;
+			padding: 100rpx;
+		}
+
+		.login-form {
+			display: flex;
+			padding: 20rpx 40rpx;
+			flex-direction: column;
+		}
+
+		.login-form-item {
+			padding: 10rpx;
+			display: flex;
+			margin: 20rpx 10rpx;
+			font-size: 28rpx !important;
+			flex-direction: row;
+			
+
+			.label {
+				text-align: right;
+				width: 120rpx;
+				margin-top: 15rpx;
+			}
+
+			.input {
+				flex: 1;
+				margin: 10rpx 20rpx 15rpx 20rpx;
+			}
+
+		}
+		.line{
+			border-bottom: 2rpx solid #ddd;
+		}
+
+		.button-group {
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			flex-direction: column;
+			font-size: 30rpx !important;
+			padding: 100rpx;
+
+			.am-button {
+				border-radius: 30px;
+			}
+
+			.am-button-ghost {
+				border: 1px solid #1677ff !important;
+
+			}
+		}
+
+		.button {
+			margin: auto;
+			margin-top: 20rpx;
+			width: 500rpx;
+
+		}
+
+
+	}
+</style>
\ No newline at end of file
diff --git a/pages/login/register.vue b/pages/login/register.vue
new file mode 100644
index 0000000..ffac145
--- /dev/null
+++ b/pages/login/register.vue
@@ -0,0 +1,234 @@
+<template>
+	<view class="pages-login-register">
+		<view class="uni-panel-content items-center">
+			<view class="login-content">
+				<view class="justify-center">
+					<image class="title-img" src="/images/earth.svg" alt="svg 鍥剧墖" />
+				</view>
+				<view class="login-form">
+					<view class="login-form-item ">
+						<image class="icon" src="/images/mobile.svg" alt="svg 鍥剧墖" />
+						<input class="input" :focus="formData.accountFocus" name="account" comfirm-type="done"
+							type="text" v-model="form.account" placeholder="杈撳叆鎵嬫満鍙风爜" />
+					</view>
+					<view class="login-form-item ">
+						<image class="icon" src="/images/chat.svg" alt="svg 鍥剧墖" />
+						<input class="input" comfirm-type="done" v-model="form.mobileCode" placeholder="鐭俊楠岃瘉鐮� />
+						<view v-if="disabledSendCode" class="disabled">{{sendCodeCountdown}}绉掑悗閲嶆柊鍙戦�</view>
+						<a v-else @click="clickSendVerifyCode">鍙戦�楠岃瘉鐮�/a>
+
+					</view>
+					<view class="login-form-item ">
+						<image class="icon" src="/images/lock.svg" alt="svg 鍥剧墖" />
+						<input class="input" :focus="formData.passwordFocus" name="password" password
+							comfirm-type="done" v-model="form.password" placeholder="璁剧疆鐧诲綍瀵嗙爜" />
+
+					</view>
+					<view class=" login-form-item ">
+						<checkbox :value="checkedAgree" @change="handleAgreeChange" />宸查槄璇诲苟鍚屾剰銆�a
+							@click="clickUserAgreement">鐢ㄦ埛鍗忚</a>銆�+					</view>
+					<view class="button-group">
+						<a-button :disabled="disabledOk" type="primary" class="button" @click="clickOK">纭</a-button>
+					</view>
+				</view>
+
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import {
+		showToast,
+		showModal
+	} from "@/comm/utils.js"
+	import {
+		Button
+	} from 'antd-mobile-vue-next'
+	export default {
+		name: "PagesLoginRegister",
+		components: {
+			'a-button': Button
+		},
+		data() {
+			return {
+				form: {
+					account: '',
+					password: '',
+					mobileCode: "",
+				},
+				formData: {
+					accountFocus: true,
+					passwordFocus: false
+				},
+				disabledSendCode: false,
+				sendCodeCountdown: 0,
+				checkedAgree: false
+			}
+		},
+		computed: {
+			disabledOk() {
+				let text = this.form.account.trim()
+				if (!text) {
+					return true
+				}
+				text = this.form.password.trim()
+				if (!text) {
+					return true
+				}
+				text = this.form.mobileCode.trim()
+				if (!text) {
+					return true
+				}
+				return false
+			}
+		},
+		methods: {
+			setData(obj) {
+				let that = this;
+				let keys = [];
+				let val, data;
+
+				Object.keys(obj).forEach(function(key) {
+					keys = key.split(".");
+					val = obj[key];
+					data = that.$data;
+					keys.forEach(function(key2, index) {
+						if (index + 1 == keys.length) {
+							that.$set(data, key2, val);
+						} else {
+							if (!data[key2]) {
+								that.$set(data, key2, {});
+							}
+						}
+						data = data[key2];
+					});
+				});
+			},
+			handleAgreeChange(e) {
+
+				console.log(e)
+				this.checkedAgree = e.detail.value;
+			},
+			clickOK() {
+				if (!this.checkedAgree) {
+					showToast("璇烽槄璇诲苟鍚屾剰鐢ㄦ埛鍗忚")
+					return
+				}
+				uni.reLaunch({
+					url: "/pages/login/index"
+				})
+			},
+			clickSendVerifyCode() {
+
+				if (this.disabledSendCode) {
+					return
+				}
+				let text = this.form.account.trim()
+				if (!text) {
+					showToast("璇疯緭鍏ユ墜鏈哄彿")
+					return
+				}
+
+				this.sendCodeCountdown = 60
+				this.disabledSendCode = true
+				const idInterval = setInterval(() => {
+					if (this.sendCodeCountdown > 0) {
+						this.sendCodeCountdown--
+					} else {
+						this.sendCodeCountdown = 0
+						clearInterval(idInterval);
+						this.disabledSendCode = false
+					}
+				}, 1000)
+			},
+			clickUserAgreement() {},
+
+
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.pages-login-register {
+		display: flex;
+		width: 750rpx;
+		height: 100vh;
+		flex-direction: column;
+
+		.uni-panel-content {
+			display: flex;
+			flex: 1;
+			width: 750rpx;
+		}
+
+		.login-content {
+			width: 750rpx;
+		}
+
+		.justify-center {
+			justify-content: center;
+		}
+
+		.items-center {
+			align-items: center
+		}
+
+		.title-img {
+			display: block;
+			margin: auto;
+			width: 300rpx;
+			height: 300rpx;
+		}
+
+		.login-form {
+			display: flex;
+			padding: 20rpx 40rpx;
+			flex-direction: column;
+		}
+
+		.login-form-item {
+			padding: 10rpx;
+			display: flex;
+			margin: 10rpx;
+			font-size: 30rpx !important;
+			flex-direction: row;
+			border-bottom: 2rpx solid #ddd;
+
+			.icon {
+				opacity: 0.3;
+				margin: 12rpx 20rpx;
+				width: 40rpx;
+				height: 40rpx;
+			}
+
+			.input {
+				flex: 1;
+				padding: 12rpx 16rpx;
+				background-color: transparent;
+			}
+
+		}
+
+		.button-group {
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			flex-direction: column;
+			font-size: 30rpx !important;
+		}
+
+		.disabled {
+			color: #888;
+		}
+
+		.button {
+			margin: auto;
+			margin-top: 20rpx;
+			width: 300rpx;
+			
+		}
+
+	}
+</style>
\ No newline at end of file
diff --git a/pages/map/edit.vue b/pages/map/edit.vue
new file mode 100644
index 0000000..a6943d2
--- /dev/null
+++ b/pages/map/edit.vue
@@ -0,0 +1,345 @@
+<template>
+	<view class="pages-map-edit">
+		<view class="view-content">
+			<view class="no-content" v-if="unlinked">
+				<image class="img" src="/images/image 25.png" alt=" 鍥剧墖" mode="aspectFit" />
+				<view class="title">杞﹁締杩炴帴澶辫触</view>
+				<view class="space">璇锋鏌ヤ綘鐨勭綉缁滆缃垨閲嶆柊鍔犺浇</view>
+			</view>
+			<view class="map-content" v-show="!unlinked">
+
+			</view>
+		</view>
+		<view class="bottom" v-if="!unlinked">
+
+			<view class="bottom-content">
+				<view class="img-button-group">
+					<view fill="none" class="button" @click="clickPathTeaching">
+						<text class="ico teach"></text>
+						<view class="text">璺緞绀烘暀</view>
+					</view>
+					<view fill="none" class="button" @click="clickMapRename">
+						<text class="ico teach disabled"></text>
+						<view class="text disabled">閲嶅懡鍚�/view>
+					</view>
+					<view fill="none" class="button" @click="clickRegionalPlanning">
+						<text class="ico teach disabled"></text>
+						<view class="text disabled">鍖哄煙瑙勫垝</view>
+					</view>
+					<view fill="none" class="button " @click="clickMapEdit">
+						<text class="ico teach disabled"></text>
+						<view class="text disabled">淇敼鍦板浘</view>
+					</view>
+				</view>
+
+			</view>
+		</view>
+
+	</view>
+</template>
+<script>
+	import {
+		showToast,
+		showModal
+	} from "@/comm/utils.js"
+	// import OIFabric from "@/components/oi-fabric/index.vue"
+	import {
+		Button
+	} from 'antd-mobile-vue-next'
+
+	import {
+		getAgvState,
+	} from "@/api/vehicle.js"
+	export default {
+		name: "PagesMapEdit",
+		components: {
+			'a-button': Button
+		},
+		data() {
+			return {
+				navigationBarTitle: "",
+				vehicleIp: "",
+				stationList: [],
+				unlinked: true
+			}
+		},
+		computed: {
+			getMaxStationNo() {
+				let num = 0
+				this.stationList.forEach((item) => {
+					if (num < item.stationID) {
+						num = item.stationID
+					}
+				})
+				return num
+			},
+		},
+		watch: {
+
+		},
+		onLoad(option) {
+			const _this = this
+			this.vehicleIp = option.ip || ""
+
+			this.loadData()
+
+		},
+		methods: {
+			setData(obj) {
+				let that = this;
+				let keys = [];
+				let val, data;
+
+				Object.keys(obj).forEach(function(key) {
+					keys = key.split(".");
+					val = obj[key];
+					data = that.$data;
+					keys.forEach(function(key2, index) {
+						if (index + 1 == keys.length) {
+							that.$set(data, key2, val);
+						} else {
+							if (!data[key2]) {
+								that.$set(data, key2, {});
+							}
+						}
+						data = data[key2];
+					});
+				});
+			},
+			async loadData() {
+				try {
+					const info = await getAgvState(this.vehicleIp)
+					this.setData({
+						unlinked: false
+					})
+				} catch (ex) {
+					this.setData({
+						unlinked: true
+					})
+
+				}
+			},
+			clickShowMenu() {
+				this.$refs.refPopupMenu.open("top")
+			},
+			clickBack() {
+				uni.navigateBack({
+					delta: 1
+				})
+
+			},
+			clickPathTeaching() {
+				uni.navigateTo({
+					url: `/pages/teaching/index?ip=${this.vehicleIp}`
+				})
+			},
+			clickRegionalPlanning() {
+
+			},
+			clickMapRename() {
+
+			},
+			clickMapEdit() {
+
+			},
+
+			showError(ex) {
+				let exStr = JSON.stringify(ex)
+				if (exStr == "{}")
+					exStr = ex
+				let tip = typeof ex.msg == "string" ? ex.msg : exStr
+				showModal(tip, "閿欒", false)
+			},
+
+
+		}
+	}
+</script>
+
+<style lang="scss">
+	.pages-map-edit {
+		display: flex;
+		width: 750rpx;
+		height: 100vh;
+		background-color: #fff;
+		position: relative;
+
+		.uni-navbar-container-inner {
+			display: flex;
+			flex: 1;
+			flex-direction: row;
+			align-items: center;
+			justify-content: center;
+			font-size: 40rpx;
+			overflow: hidden;
+			font-weight: 700;
+			color: #333;
+
+			.icon {
+				width: 30rpx;
+				height: 16rpx;
+			}
+		}
+
+		.uni-nav-bar-text {
+			overflow: hidden;
+			white-space: nowrap;
+			text-overflow: ellipsis;
+		}
+
+		.view-content {
+			position: absolute;
+			top: 0;
+			left: 0;
+			right: 0;
+			bottom: 0;
+			display: flex;
+			flex-direction: column;
+		}
+
+		.map-content {
+			width: 100%;
+			display: flex;
+			flex: 1;
+			margin: auto;
+
+			.text-button-group {
+				display: flex;
+				width: 100%;
+				justify-content: center;
+				align-items: center;
+				flex-direction: column;
+				font-size: 30rpx !important;
+				background-color: #eee;
+
+				.button {
+					margin-top: 20rpx;
+					width: 375rpx;
+				}
+			}
+
+
+		}
+
+		.no-content {
+			margin-top: 50px;
+			padding: 20rpx 40rpx;
+			align-items: center;
+			text-align: center;
+			display: flex;
+			flex-direction: column;
+			font-size: 30rpx;
+			font-weight: 400;
+
+			.title {
+				font-size: 40rpx;
+				margin-bottom: 10rpx;
+			}
+
+
+		}
+
+		.bottom {
+			position: fixed;
+			left: 50rpx;
+			right: 50rpx;
+			bottom: 20rpx;
+			display: flex;
+
+			.bottom-content {
+				display: flex;
+				flex-direction: column;
+				width: 100%;
+				// justify-content: center;
+				// align-items: center;
+				padding: 0 10rpx;
+				padding-bottom: 10rpx;
+				background-color: #fff;
+				border-radius: 10rpx;
+			}
+
+
+
+		}
+
+		.img-button-group {
+			display: flex;
+			//width: 100%;
+			flex-direction: row;
+			border-radius: 10px;
+			border: 1px solid #fff;
+			font-size: 30rpx !important;
+			justify-content: space-around;
+
+			.button {
+				margin: 10rpx 20rpx;
+
+				height: 144rpx !important;
+				border: 0;
+				display: flex;
+				flex-direction: column;
+				background-color: #00000000;
+
+				.img {
+					margin: auto;
+					width: 72rpx;
+					height: 72rpx;
+
+				}
+
+				.ico {
+					margin: auto;
+					font-size: 72rpx;
+					color: #1890FF;
+				}
+
+				.text {
+					margin: auto;
+
+				}
+			}
+
+		}
+
+		.disabled {
+			color: #ccc !important;
+		}
+
+		.popup-content {
+			display: flex;
+			justify-content: center;
+			flex-direction: column;
+			background-color: transparent;
+		}
+
+		.popup-content-menu {
+			margin-top: 75px;
+			margin-left: 120px;
+			width: 150px;
+			align-items: center;
+			justify-content: center;
+			flex-direction: column;
+			background-color: #fff;
+			border-radius: 5px;
+			border: 1px solid gray;
+		}
+
+		.popup-content-menu-item {
+			display: flex;
+			flex-wrap: nowrap;
+			flex-direction: row !important;
+			align-items: center;
+			padding: 4px 8px;
+			font-size: 16px;
+
+			.img {
+				width: 20px;
+				height: 20px;
+				margin: 5px;
+			}
+		}
+
+
+
+	}
+</style>
\ No newline at end of file
diff --git a/pages/map/index.vue b/pages/map/index.vue
new file mode 100644
index 0000000..8a606f2
--- /dev/null
+++ b/pages/map/index.vue
@@ -0,0 +1,357 @@
+<template>
+	<view class="pages-map">
+		<view class="view-content">
+			<view class="no-content" v-if="unlinked">
+				<image class="img" src="/images/image 25.png" alt=" 鍥剧墖" mode="aspectFit" />
+				<view class="title">杞﹁締杩炴帴澶辫触</view>
+				<view class="space">璇锋鏌ヤ綘鐨勭綉缁滆缃垨閲嶆柊鍔犺浇</view>
+			</view>
+			<view class="map-content" v-show="!unlinked">
+				<view class="text-button-group">
+					<a-button type="primary" class="button" @click="clickStationList">
+						绔欑偣鍒楄〃
+					</a-button>
+					<a-button type="primary" class="button" @click="clickTeachingList">
+						绀烘暀璺嚎鍒楄〃
+					</a-button>
+				</view>
+			</view>
+		</view>
+		<view class="bottom" v-if="!unlinked">
+
+			<view class="bottom-content">
+				<view class="img-button-group">
+					<view fill="none" class="button" @click="clickMapStation">
+						<text class="ico location1"></text>
+						<view class="text"> 娣诲姞绔欑偣</view>
+					</view>
+					<view type="text" class="button" @click="clickMapEdit">
+						<text class="ico edit-line"></text>
+						<view class="text"> 缂栬緫鍦板浘</view>
+					</view>
+					<view type="text" class="button" @click="clickMapTask">
+						<text class="ico task-list"></text>
+						<view class="text">杞﹁締浠诲姟</view>
+
+					</view>
+				</view>
+
+			</view>
+		</view>
+
+	</view>
+</template>
+<script>
+	import {
+		showToast,
+		showModal
+	} from "@/comm/utils.js"
+	// import OIFabric from "@/components/oi-fabric/index.vue"
+	import {
+		Button
+	} from 'antd-mobile-vue-next'
+
+	import {
+		getAgvState,
+	} from "@/api/vehicle.js"
+	export default {
+		name: "PagesMap",
+		components: {
+			'a-button': Button
+		},
+		data() {
+			return {
+				navigationBarTitle: "",
+				vehicleIp: "",
+				stationList: [],
+				unlinked: true
+			}
+		},
+		computed: {
+			getMaxStationNo() {
+				let num = 0
+				this.stationList.forEach((item) => {
+					if (num < item.stationID) {
+						num = item.stationID
+					}
+				})
+				return num
+			},
+		},
+		watch: {
+
+		},
+		onLoad(option) {
+			const _this = this
+			this.vehicleIp = option.ip || ""
+
+			this.loadData()
+
+		},
+		methods: {
+			setData(obj) {
+				let that = this;
+				let keys = [];
+				let val, data;
+
+				Object.keys(obj).forEach(function(key) {
+					keys = key.split(".");
+					val = obj[key];
+					data = that.$data;
+					keys.forEach(function(key2, index) {
+						if (index + 1 == keys.length) {
+							that.$set(data, key2, val);
+						} else {
+							if (!data[key2]) {
+								that.$set(data, key2, {});
+							}
+						}
+						data = data[key2];
+					});
+				});
+			},
+			async loadData() {
+				try {
+					const info = await getAgvState(this.vehicleIp)
+					this.setData({
+						unlinked: false
+					})
+				} catch (ex) {
+					this.setData({
+						unlinked: true
+					})
+
+				}
+			},
+			clickShowMenu() {
+				this.$refs.refPopupMenu.open("top")
+			},
+			clickBack() {
+				uni.navigateBack({
+					delta: 1
+				})
+
+			},
+			clickStationList() {
+				uni.navigateTo({
+					url: `/pages/station/index?ip=${this.vehicleIp}`
+				})
+			},
+			clickTeachingList() {
+				uni.navigateTo({
+					url: `/pages/teaching/list?ip=${this.vehicleIp}`
+				})
+			},
+			clickMapStation() {
+				uni.navigateTo({
+					url: `/pages/station/index?ip=${this.vehicleIp}&isAdd=1`
+				})
+			},
+			clickMapEdit() {
+				uni.navigateTo({
+					url: `/pages/map/edit?ip=${this.vehicleIp}`
+				})
+			},
+			clickMapTask() {
+				uni.navigateTo({
+					url: `/pages/map/task?ip=${this.vehicleIp}`
+				})
+			},
+
+			showError(ex) {
+				let exStr = JSON.stringify(ex)
+				if (exStr == "{}")
+					exStr = ex
+				let tip = typeof ex.msg == "string" ? ex.msg : exStr
+				showModal(tip, "閿欒", false)
+			},
+
+
+		}
+	}
+</script>
+
+<style lang="scss">
+	.pages-map {
+		display: flex;
+		width: 750rpx;
+		height: 100vh;
+		background-color: #fff;
+		position: relative;
+
+		.uni-navbar-container-inner {
+			display: flex;
+			flex: 1;
+			flex-direction: row;
+			align-items: center;
+			justify-content: center;
+			font-size: 40rpx;
+			overflow: hidden;
+			font-weight: 700;
+			color: #333;
+
+			.icon {
+				width: 30rpx;
+				height: 16rpx;
+			}
+		}
+
+		.uni-nav-bar-text {
+			overflow: hidden;
+			white-space: nowrap;
+			text-overflow: ellipsis;
+		}
+
+		.view-content {
+			position: absolute;
+			top: 0;
+			left: 0;
+			right: 0;
+			bottom: 0;
+			display: flex;
+			flex-direction: column;
+		}
+
+		.map-content {
+			width: 100%;
+			display: flex;
+			flex: 1;
+			margin: auto;
+
+			.text-button-group {
+				display: flex;
+				width: 100%;
+				justify-content: center;
+				align-items: center;
+				flex-direction: column;
+				font-size: 30rpx !important;
+				background-color: #eee;
+
+				.button {
+					margin-top: 20rpx;
+					width: 375rpx;
+				}
+			}
+
+
+		}
+
+		.no-content {
+			margin-top: 50px;
+			padding: 20rpx 40rpx;
+			align-items: center;
+			text-align: center;
+			display: flex;
+			flex-direction: column;
+			font-size: 30rpx;
+			font-weight: 400;
+
+			.title {
+				font-size: 40rpx;
+				margin-bottom: 10rpx;
+			}
+
+
+		}
+
+		.bottom {
+			position: fixed;
+			left: 50rpx;
+			right: 50rpx;
+			bottom: 20rpx;
+			display: flex;
+
+			.bottom-content {
+				display: flex;
+				flex-direction: column;
+				width: 100%;
+				// justify-content: center;
+				// align-items: center;
+				padding: 0 10rpx;
+				padding-bottom: 10rpx;
+				background-color: #fff;
+				border-radius: 10rpx;
+			}
+
+
+
+		}
+
+		.img-button-group {
+			display: flex;
+			//width: 100%;
+			flex-direction: row;
+			border-radius: 10px;
+			border: 1px solid #fff;
+			font-size: 30rpx !important;
+			justify-content: space-around;
+
+			.button {
+				margin: 10rpx 20rpx;
+
+				height: 144rpx !important;
+				border: 0;
+				display: flex;
+				flex-direction: column;
+				background-color: #00000000;
+
+				.img {
+					margin: auto;
+					width: 72rpx;
+					height: 72rpx;
+
+				}
+
+				.ico {
+					margin: auto;
+					font-size: 72rpx;
+					color: #1890FF;
+				}
+
+				.text {
+					margin: auto;
+
+				}
+			}
+
+		}
+
+
+		.popup-content {
+			display: flex;
+			justify-content: center;
+			flex-direction: column;
+			background-color: transparent;
+		}
+
+		.popup-content-menu {
+			margin-top: 75px;
+			margin-left: 120px;
+			width: 150px;
+			align-items: center;
+			justify-content: center;
+			flex-direction: column;
+			background-color: #fff;
+			border-radius: 5px;
+			border: 1px solid gray;
+		}
+
+		.popup-content-menu-item {
+			display: flex;
+			flex-wrap: nowrap;
+			flex-direction: row !important;
+			align-items: center;
+			padding: 4px 8px;
+			font-size: 16px;
+
+			.img {
+				width: 20px;
+				height: 20px;
+				margin: 5px;
+			}
+		}
+
+
+
+	}
+</style>
\ No newline at end of file
diff --git a/pages/map/js/ctx.js b/pages/map/js/ctx.js
new file mode 100644
index 0000000..14b32ad
--- /dev/null
+++ b/pages/map/js/ctx.js
@@ -0,0 +1,1430 @@
+import * as fabric from "fabric" //'../../../components/fabric';
+import {
+	v4 as uuidv4
+} from 'uuid';
+import {
+	Base64
+} from '../../../comm/base64.js';
+// import okIcon from '../../../static/images/confirm.svg';
+// import cancelIcon from '../../../static/images/remove.svg';
+export default {
+	data() {
+		return {
+			vehicleIp: "",
+			canvasId: "",
+			canvas: null,
+			eleWidth: 0,
+			eleHeight: 0,
+			touchStartPoint: {
+				x: 0,
+				y: 0
+			},
+			isDrawing: false,
+			drawType: "",
+			drawSvg: "",
+			initialDistance: null,
+			initialZoom: 1,
+			isDragging: false,
+			lastPosX: 0,
+			lastPosY: 0,
+			agvObj: null,
+			initFlag: false,
+			editMode: false,
+
+
+		}
+	},
+	mounted() {
+		console.log("ctx mounted")
+		this.init()
+	},
+	methods: {
+		async init(ip) {
+			try {
+				this.agvObj = null
+				const _this = this
+				fabric.Object.prototype.setControlsVisibility({
+					mt: false, // 涓棿涓�+					mb: false, // 涓棿涓�+					ml: false, // 涓棿宸�+					mr: false, // 涓棿鍙�+					mtr: false, // 鏃嬭浆鎺у埗
+
+					tl: false, //鏄惁鏄剧ず涓棿妯潬
+					bl: false, //鏄惁鏄剧ず涓棿妯潬
+					tr: false, //鏄惁鏄剧ず涓棿妯潬
+					br: false, //鏄惁鏄剧ず涓棿妯潬
+				})
+				// 鍏ㄥ眬鏍峰紡璋冩暣
+				fabric.Object.prototype.set({
+					borderColor: '#1890FF',
+					cornerColor: '#fff',
+					cornerStrokeColor: '#1890FF',
+					cornerSize: 36,
+					//	touchCornerSize: 48,
+					transparentCorners: false,
+					cornerStyle: 'circle',
+					borderScaleFactor: 2,
+					padding: 10,
+
+				});
+				this.canvasId = `canvas_${uuidv4()}`
+				const cantainerEl = document.getElementById("canvasMap")
+				let canvas = document.getElementById(this.canvasId)
+				canvas = document.createElement("canvas")
+				canvas.setAttribute("id", this.canvasId)
+				canvas.setAttribute("type", "2d")
+				cantainerEl.appendChild(canvas)
+				this.canvas = new fabric.Canvas(this.canvasId, {
+					allowTouchScrolling: true, // 鍏佽瑙︽懜婊氬姩
+					selection: true,
+					isTouchDevice: true, // 鍏抽敭閰嶇疆
+					stopContextMenu: true, // 绂佹闀挎寜鑿滃崟
+					fireRightClick: true,
+					fireMiddleClick: true,
+					targetFindTolerance: 15, // 澧炲ぇ瑙︽懜瀹瑰樊
+					isTouchSupported: true
+				})
+				this.canvas.clear()
+				this.eleWidth = cantainerEl.clientWidth
+				this.eleHeight = cantainerEl.clientHeight
+				this.canvas.setWidth(this.eleWidth);
+				this.canvas.setHeight(this.eleHeight);
+				this.workSpace = new fabric.Rect({
+					id: "workspace",
+					eleType: "workspace",
+					left: 0,
+					top: 0,
+					width: this.eleWidth,
+					height: this.eleHeight,
+					selectable: false,
+					hasControls: false,
+					fill: "#FFFFFF"
+				})
+				this.canvas.add(this.workSpace)
+				this.patchFabricForUniApp(this.canvas)
+				this.initFlag = true
+				await this.$nextTick();
+				this.canvasEventListener()
+
+			} catch (ex) {
+				this.showError(ex)
+			}
+		},
+		patchFabricForUniApp(canvas) {
+			// 淇濆瓨鍘熷鏂规硶
+			const originalSetActiveObject = canvas.setActiveObject.bind(canvas);
+
+			// 閲嶅啓setActiveObject
+			canvas.setActiveObject = function(object, e) {
+				originalSetActiveObject(object, e);
+				if (object) {
+					object.canvas = this;
+					this._activeObject = object;
+				}
+			};
+
+			// 纭繚瀵硅薄鍒濆鍖栨椂璁剧疆姝g‘鐨刢anvas寮曠敤
+			fabric.Object.prototype.initialize = function(options) {
+				const originalInit = fabric.util.getOriginalMethod(this, 'initialize');
+				originalInit.call(this, options);
+
+				if (this.canvas && this.canvas._activeObject === this) {
+					this.canvas._activeObject = this;
+				}
+				return this;
+			};
+		},
+		createDeleteControl(obj) {
+			// 鍒涘缓鍒犻櫎鎸夐挳鐨勫浘鐗囧厓绱�+			const _this = this
+			const deleteIcon =
+				"data:image/svg+xml,%3C%3Fxml version='1.0' encoding='utf-8'%3F%3E%3C!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'%3E%3Csvg version='1.1' id='Ebene_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' width='595.275px' height='595.275px' viewBox='200 215 230 470' xml:space='preserve'%3E%3Ccircle style='fill:%23F44336;' cx='299.76' cy='439.067' r='218.516'/%3E%3Cg%3E%3Crect x='267.162' y='307.978' transform='matrix(0.7071 -0.7071 0.7071 0.7071 -222.6202 340.6915)' style='fill:white;' width='65.545' height='262.18'/%3E%3Crect x='266.988' y='308.153' transform='matrix(0.7071 0.7071 -0.7071 0.7071 398.3889 -83.3116)' style='fill:white;' width='65.544' height='262.179'/%3E%3C/g%3E%3C/svg%3E";
+			const deleteImg = document.createElement('img');
+			deleteImg.src = deleteIcon;
+			// 娣诲姞鑷畾涔夊垹闄ゆ帶浠跺埌鎵�湁瀵硅薄鐨勫師鍨嬩笂
+			//	console.log("controls", JSON.stringify(fabric.Object.prototype))
+			obj.controls.deleteControl = new fabric.Control({
+				x: 0.5,
+				y: 0,
+				offsetY: 0,
+				offsetX: 36,
+				mouseDownHandler: _this.deleteObject, // 瑙︽懜浜嬩欢澶勭悊鍣�+				render: (ctx, left, top, styleOverride, fabricObject) => {
+
+					if (fabricObject.lockRemove) {
+						return;
+					}
+					if (fabricObject.canvas?.skipTargetFind) {
+						return;
+					}
+					const size = this.cornerSize || 36;
+					// drawImg(ctx, left, top, imgDelete, 24, 24, fabricObject.angle);
+					ctx.save();
+					ctx.translate(left, top);
+					ctx.drawImage(deleteImg, -size / 2, -size / 2, size, size);
+					ctx.restore();
+				},
+				cornerSize: 36,
+				withConnection: false,
+				actionName: 'delete', // 鍔ㄤ綔鍚嶇О
+				pointerStyle: 'pointer' // 鎸囬拡鏍峰紡
+			});
+		},
+		deleteObject(eventData, transform, x, y) {
+			console.log("")
+			const target = transform.target;
+			const canvas = target.canvas;
+
+			canvas.remove(target);
+			canvas.requestRenderAll();
+		},
+		editCancelObject(eventData, transform, x, y) {
+			const target = transform.target;
+			const canvas = target.canvas;
+			this.$ownerInstance.callMethod('receiveRenderData', {
+				method: "edit_finish",
+				cmd: "cancel",
+				station: target.data,
+			});
+			target.set({
+				lockEdit: true
+			})
+			this.canvas.requestRenderAll()
+		},
+		editOkObject(eventData, transform, x, y) {
+			const target = transform.target;
+			const canvas = target.canvas;
+			this.$ownerInstance.callMethod('receiveRenderData', {
+				method: "edit_finish",
+				cmd: "ok",
+				station: target.data,
+			});
+			target.set({
+				lockEdit: true
+			})
+			this.canvas.requestRenderAll()
+		},
+		createOkCancelControl(obj) {
+			// 鍒涘缓鍒犻櫎鎸夐挳鐨勫浘鐗囧厓绱�+			const _this = this
+			const cancelImg = document.createElement('img');
+			cancelImg.src = "static/images/remove.svg"
+			const okImg = document.createElement('img');
+			okImg.src = "static/images/confirm.svg"
+			// 娣诲姞鑷畾涔夊垹闄ゆ帶浠跺埌鎵�湁瀵硅薄鐨勫師鍨嬩笂
+			//	console.log("controls", JSON.stringify(fabric.Object.prototype))
+			obj.controls.cancelControl = new fabric.Control({
+				x: -0.5,
+				y: 0,
+				offsetY: 0,
+				offsetX: -32,
+				mouseDownHandler: _this.editCancelObject, // 瑙︽懜浜嬩欢澶勭悊鍣�+				render: (ctx, left, top, styleOverride, fabricObject) => {
+
+					if (fabricObject.lockEdit) {
+						return;
+					}
+					if (fabricObject.canvas?.skipTargetFind) {
+						return;
+					}
+					const size = this.cornerSize || 32;
+					// drawImg(ctx, left, top, imgDelete, 24, 24, fabricObject.angle);
+					ctx.save();
+					ctx.translate(left, top);
+					ctx.drawImage(cancelImg, -size / 2, -size / 2, size, size);
+					ctx.restore();
+				},
+				cornerSize: 32,
+				withConnection: false,
+				actionName: 'delete', // 鍔ㄤ綔鍚嶇О
+				pointerStyle: 'pointer' // 鎸囬拡鏍峰紡
+			});
+			obj.controls.okControl = new fabric.Control({
+				x: 0.5,
+				y: 0,
+				offsetY: 0,
+				offsetX: 32,
+				mouseDownHandler: _this.editOkObject, // 瑙︽懜浜嬩欢澶勭悊鍣�+				render: (ctx, left, top, styleOverride, fabricObject) => {
+
+					if (fabricObject.lockEdit) {
+						return;
+					}
+					if (fabricObject.canvas?.skipTargetFind) {
+						return;
+					}
+					const size = this.cornerSize || 32;
+					// drawImg(ctx, left, top, imgDelete, 24, 24, fabricObject.angle);
+					ctx.save();
+					ctx.translate(left, top);
+					ctx.drawImage(okImg, -size / 2, -size / 2, size, size);
+					ctx.restore();
+				},
+				cornerSize: 32,
+				withConnection: false,
+				actionName: 'delete', // 鍔ㄤ綔鍚嶇О
+				pointerStyle: 'pointer' // 鎸囬拡鏍峰紡
+			});
+
+		},
+		addObject(obj) {
+			obj.set({
+				lockEdit: true
+			})
+			this.canvas.add(obj)
+			this.createOkCancelControl(obj)
+		},
+		canvasEventListener() {
+			const _this = this
+
+			const cantainerEl = document.getElementById("canvasMap")
+			_this.canvas.on('touch:gesture', function(e) {
+				console.log("touch:gesture", e);
+				// 澶勭悊鎵嬪娍鎿嶄綔
+			});
+			_this.canvas.on("selection:created", function(e) {
+				const activeObj = _this.canvas.getActiveObject();
+				activeObj.set({
+					borderColor: '#1890ff',
+					borderScaleFactor: 3,
+					padding: 5,
+					borderDashArray: [5, 5], //5px 瀹炵嚎鍜�px 闂撮殧
+				});
+				_this.canvas.requestRenderAll();
+
+				_this.onSelectionChanage()
+				//_this.selectionChangeCanvas();
+			});
+			_this.canvas.on("selection:updated", function(e) {
+				console.log("selection:updated", e);
+				const activeObj = _this.canvas.getActiveObject();
+				activeObj.set({
+					borderColor: '#1890ff',
+					borderScaleFactor: 3,
+					padding: 5,
+					borderDashArray: [5, 5], //5px 瀹炵嚎鍜�px 闂撮殧
+				});
+				_this.canvas.requestRenderAll();
+				_this.onSelectionChanage()
+
+
+			});
+			_this.canvas.on("selection:cleared", function(e) {
+				console.log("selection:cleared", e);
+
+				//_this.selectionChangeCanvas();
+			});
+			_this.canvas.on("object:removed", function(e) {
+				// console.log("object:removed", e.target);
+				if (e.target) {
+					e.target.isRemoved = true;
+				}
+			});
+			_this.canvas.on("object:modified", function(e) {
+				// console.log("object:modified", e.target);
+				if (e?.target.eleType == "station") {
+					const obj = e.target
+					obj.data.x = obj.left
+					obj.data.y = obj.top
+					_this.$ownerInstance.callMethod('receiveRenderData', {
+						method: "update_station",
+						station: obj.data,
+
+					});
+				}
+				// _this.resizetCanvas();
+			});
+			_this.canvas.on("object:moving", function(e) {
+				// console.log("object:modified", e.target);
+
+			});
+
+			var pressObjTimer
+			cantainerEl.addEventListener('touchstart', function(e) {
+				console.log('touchstart:', e);
+				e.preventDefault(); // 闃绘榛樿琛屼负
+				_this.canvas.fire('touch:start', {
+					e: e
+				});
+				//	_this.canvas._onMouseDown(e);
+				if (!_this.canvas.getActiveObject()) {
+					// 鏍规嵁瑙︽懜鐐规暟閲忓垽鏂氦浜掔被鍨�+					if (e.touches.length === 1) {
+
+
+						_this.handleSingleTouch(e.touches[0]);
+					} else if (e.touches.length >= 2) {
+
+
+						_this.handleMultiTouch(e.touches);
+					}
+				} else {
+					if (e.touches.length === 1) {
+						const touch = e.touches[0]
+						this.lastPosX = touch.clientX;
+						this.lastPosY = touch.clientY;
+						const list = _this.canvas.getActiveObjects()
+						if (list.length === 1) {
+							pressObjTimer = setTimeout(function() {
+								console.log("edit_station", list[0].eleType)
+								if (list[0].eleType == "station") {
+									_this.setAllObjectSelectable(false)
+
+									list[0].set({
+										selectable: true
+									})
+									const zoom = _this.canvas.getZoom();
+									let deltaX = list[0].left * zoom
+									let deltaY = list[0].top * zoom
+									const vpt = _this.canvas.viewportTransform;
+
+									_this.$ownerInstance.callMethod('receiveRenderData', {
+										method: "edit_station",
+										station: list[0].data,
+										view: {
+											x: vpt[4] + deltaX,
+											y: vpt[5] + deltaY,
+											// x: e.touches[0].clientX,
+											// y: e.touches[0].clientY,
+											width: list[0].width * zoom,
+											height: list[0].height * zoom
+										}
+									});
+								}
+							}, 3000); //
+						}
+					}
+				}
+			});
+
+			cantainerEl.addEventListener('touchmove', function(e) {
+				//	_this.canvas._onMouseMove(e);
+				e.preventDefault(); // 闃绘榛樿琛屼负
+				// 澶勭悊绉诲姩
+				if (!_this.canvas.getActiveObject()) {
+					if (e.touches.length === 1) {
+						_this.handleSingleTouchMove(e.touches[0]);
+					} else if (e.touches.length >= 2) {
+						_this.handleMultiTouchMove(e.touches);
+					}
+				} else {
+					if (e.touches.length === 1) {
+						const touch = e.touches[0]
+						const deltaX = touch.clientX - this.lastPosX;
+						const deltaY = touch.clientY - this.lastPosY;
+						if (Math.abs(deltaX) > 20)
+							clearTimeout(pressObjTimer);
+					}
+				}
+			});
+
+			cantainerEl.addEventListener('touchend', function(e) {
+				//	_this.canvas._onMouseUp(e);
+				e.preventDefault(); // 闃绘榛樿琛屼负
+				_this.touchPoint = {
+					x: 0,
+					y: 0
+				};
+				if (!_this.canvas.getActiveObject()) {
+					// 澶勭悊缁撴潫浜嬩欢
+					if (e.touches.length === 0) {
+						_this.handleTouchEnd();
+					}
+					if (_this.editObject) {
+						_this.canvas.setActiveObject(_this.editObject)
+					}
+				} else {
+					clearTimeout(pressObjTimer);
+				}
+
+
+			});
+			cantainerEl.addEventListener('touchcancel', function(e) {
+				if (_this.canvas.getActiveObject()) {
+					// 澶勭悊缁撴潫浜嬩欢
+					clearTimeout(pressObjTimer);
+				} else {
+					if (_this.editObject) {
+						_this.canvas.setActiveObject(_this.editObject)
+					}
+				}
+			})
+
+		},
+		onSelectionChanage() {
+			const _this = this
+			const list = _this.canvas.getActiveObjects()
+			if (list.length === 1) {
+				if (list[0].eleType == "station") {
+					_this.$ownerInstance.callMethod('receiveRenderData', {
+						method: "selected_change",
+						type: list[0].eleType,
+						param: list[0].data
+					});
+				} else if (list[0].eleType == "agv") {
+					_this.$ownerInstance.callMethod('receiveRenderData', {
+						method: "selected_change",
+						type: list[0].eleType,
+						param: list[0].data
+					});
+				} else if (list[0].eleType == "agv_line") {
+					_this.$ownerInstance.callMethod('receiveRenderData', {
+						method: "selected_change",
+						type: list[0].eleType,
+						param: list[0].data
+					});
+				} else {
+					_this.$ownerInstance.callMethod('receiveRenderData', {
+						method: "selected_change",
+						type: ""
+					});
+				}
+
+			} else {
+				_this.$ownerInstance.callMethod('receiveRenderData', {
+					method: "selected_change",
+					type: ""
+				});
+			}
+		},
+		safeLoadImage(url, maxSize = 2048) {
+			console.log(url)
+			return new Promise((resolve) => {
+				const img = new Image();
+				img.onload = () => {
+					// 妫�煡灏哄鏄惁瓒呭嚭闄愬埗
+					const scale = Math.min(
+						maxSize / Math.max(img.width, img.height),
+						1
+					);
+					resolve(new fabric.Image(img, {
+						scaleX: scale,
+						scaleY: scale
+					}));
+				};
+				img.onerror = () => {
+					console.error('鍥剧墖鍔犺浇澶辫触');
+					resolve(null);
+				};
+				img.src = url;
+			});
+		},
+		safeLoadImageData(data, maxSize = 2048) {
+			//console.log("safeLoadImageData")
+			const _this = this
+			return new Promise((resolve) => {
+				let base64Image = data
+				if (base64Image.indexOf("data:image/png;base64,") < 0) {
+					base64Image = "data:image/png;base64," + data
+				}
+				// var img = new fabric.Image();
+				// img.setSrc(base64Image, function() {
+				// 	console.log("img", JSON.stringify(img))
+				// 	const scale = Math.min(
+				// 		maxSize / Math.max(img.width, img.height),
+				// 		1
+				// 	);
+				// 	img.set({
+				// 		scaleX: scale,
+				// 		scaleY: scale
+				// 	})
+				// 	resolve(img)
+				// });
+				fabric.Image.fromURL(base64Image, {
+					crossOrigin: 'anonymous' // 閲嶈锛氳缃法鍩�+				}).then((img) => {
+
+					//console.log("img",JSON.stringify(img))
+					const scale = Math.min(
+						maxSize / Math.max(img.width, img.height),
+						1
+					);
+					img.set({
+						scaleX: scale,
+						scaleY: scale,
+					})
+					resolve(img)
+				}).catch((err) => {
+					console.error("鍥剧墖鍔犺浇澶辫触", err)
+					_this.showError("鍥剧墖鍔犺浇澶辫触")
+					resolve(null);
+				})
+
+			});
+		},
+		async loadBase64ImageWithProgress(data, maxSize = 2048) {
+			const _this = this
+			return new Promise((resolve, reject) => {
+				// 鍒涘缓涓存椂Image瀵硅薄鐩戞帶鍔犺浇杩涘害
+				var base64Image = data
+				if (base64Image.indexOf("data:image/png;base64,") < 0) {
+					base64Image = "data:image/png;base64," + data
+				}
+				_this.$ownerInstance.callMethod('receiveRenderData', {
+					method: "set_backgroud_progress",
+					type: "start",
+				});
+				const img = new Image();
+				img.onloadstart = () => {
+					_this.$ownerInstance.callMethod('receiveRenderData', {
+						method: "set_backgroud_progress",
+						type: "progress",
+						percent: 5
+					});
+				};
+				img.onprogress = (e) => {
+					if (e.lengthComputable) {
+						const percent = Math.min(99, Math.round((e.loaded / e.total) * 100));
+						_this.$ownerInstance.callMethod('receiveRenderData', {
+							method: "set_backgroud_progress",
+							type: "progress",
+							percent
+						});
+					} else {
+						// 鏃犳硶璁$畻杩涘害鏃剁殑妯℃嫙杩涘害
+						const percent = Math.min(this.progressPercent + 10, 95);
+						_this.$ownerInstance.callMethod('receiveRenderData', {
+							method: "set_backgroud_progress",
+							type: "progress",
+							percent
+						});
+					}
+				};
+				img.onload = () => {
+					const percent = Math.min(this.progressPercent + 10, 95);
+					_this.$ownerInstance.callMethod('receiveRenderData', {
+						method: "set_backgroud_progress",
+						type: "progress",
+						percent: 100
+					});
+					// 杞崲涓篎abric鍥惧儚
+					const scale = Math.min(
+						maxSize / Math.max(img.width, img.height),
+						1
+					);
+					const fabricImg = new fabric.Image(img, {
+						left: 0,
+						top: 0,
+						scaleX: scale,
+						scaleY: scale,
+					});
+					_this.$ownerInstance.callMethod('receiveRenderData', {
+						method: "set_backgroud_progress",
+						type: "end",
+					});
+					resolve(fabricImg);
+				};
+
+				img.onerror = (err) => {
+					_this.$ownerInstance.callMethod('receiveRenderData', {
+						method: "set_backgroud_progress",
+						type: "error",
+					});
+					console.error("鍥剧墖鍔犺浇澶辫触", err)
+					reject(new Error('鍥剧墖鍔犺浇澶辫触'));
+				};
+				// 寮�鍔犺浇
+				img.src = base64Image;
+			});
+		},
+
+		// 鐩戞帶鍐呭瓨浣跨敤鎯呭喌
+		checkMemoryUsage() {
+			if (window.performance && window.performance.memory) {
+				const usedMB = window.performance.memory.usedJSHeapSize / (1024 * 1024);
+				console.log(`鍐呭瓨浣跨敤: ${usedMB.toFixed(2)}MB`);
+				return usedMB;
+			}
+			return null;
+		},
+
+		setBackground(info) {
+			const _this = this
+
+			if (!this.canvas)
+				return
+			this.canvas.clear()
+			this.canvas.selectionColor = 'rgba(100, 200, 255, 0.3)'; // 閫変腑鑳屾櫙鑹�+			this.canvas.selectionBorderColor = '#1890ff'; // 杈规棰滆壊
+			this.canvas.selectionLineWidth = 3; // 杈规瀹藉害
+			this.agvObj = null
+			const cantainerEl = document.getElementById("canvasMap")
+			this.eleWidth = cantainerEl.clientWidth
+			this.eleHeight = cantainerEl.clientHeight
+			console.log("client", this.eleWidth, this.eleHeight)
+			this.canvas.setWidth(this.eleWidth);
+			this.canvas.setHeight(this.eleHeight);
+
+			//console.log("setBackground", JSON.stringify(info))
+
+			return new Promise((resolve, reject) => {
+				// if (svgUrl) {
+				// 	fabric.loadSVGFromURL(svgUrl).then(({
+				// 		objects,
+				// 		options
+				// 	}) => {
+				// 		const workSpace = fabric.util.groupSVGElements(objects, options);
+				// 		workSpace.set({
+				// 			id: "workspace",
+				// 			eleType: "workspace",
+				// 			left: 0,
+				// 			top: 0,
+				// 			selectable: false,
+				// 			hasControls: false,
+
+
+				// 		});
+				// 		_this.canvas.add(workSpace)
+				// 		if (_this.workSpace) {
+				// 			_this.canvas.remove(_this.workSpace)
+				// 		}
+				// 		_this.workSpace = workSpace
+				// 		//	_this.auto()
+				// 		resolve()
+				// 	});
+				// } else if (imgUrl) {
+				if (info.filedata) {
+					_this.loadBase64ImageWithProgress(info.filedata).then((img) => {
+						//console.warn('setBackground', JSON.stringify(img));
+						if (img) {
+							img.set({
+								id: "workspace",
+								eleType: "workspace",
+								left: 0,
+								top: 0,
+								selectable: false,
+								hasControls: false,
+							});
+							_this.canvas.add(img)
+							if (_this.workSpace) {
+								_this.canvas.remove(_this.workSpace)
+							}
+							_this.workSpace = img
+
+						}
+						//_this.checkMemoryUsage()
+						resolve()
+
+					}).catch((err) => {
+						resolve()
+					})
+
+				} else {
+					resolve()
+				}
+				// fabric.Image.fromURL(imgUrl).then((img) => {
+				// 	// 璁剧疆鑳屾櫙鍥惧儚鐨勫睘鎬�+				// 	img.set({
+				// 		id: "workspace",
+				// 		eleType: "workspace",
+				// 		left: 0,
+				// 		top: 0,
+				// 		selectable: false,
+				// 		hasControls: false,
+				// 	});
+
+				// 	_this.canvas.add(img)
+				// 	if (_this.workSpace) {
+				// 		_this.canvas.remove(_this.workSpace)
+				// 	}
+				// 	_this.workSpace = img
+				// 	//_this.auto()
+				// 	resolve()
+				// })
+
+				//}
+			})
+		},
+		getAutoScale() {
+			// 鎸夌収瀹藉害
+
+			const eleWidth = this.eleWidth
+			const eleHeight = this.eleHeight
+			if (!this.workSpace)
+				return 1
+			const width = this.workSpace.width
+			const height = this.workSpace.height
+			if (eleWidth / eleHeight < width / height) {
+				return eleWidth / width;
+			} // 鎸夌収瀹藉害缂╂斁
+			return eleHeight / height;
+		},
+
+		auto() {
+			const scale = this.getAutoScale()
+			this.setZoomAuto((98 * scale) / 100);
+		},
+		one() {
+			this.setZoomAuto(1, ); //
+			this.canvas.requestRenderAll();
+		},
+		setZoomAuto(scale, zoomPoint) {
+			const _this = this
+			let center = this.canvas.getCenter();
+			if (zoomPoint) {
+				this.canvas.zoomToPoint(new fabric.Point(zoomPoint.x, zoomPoint.y), scale);
+			} else {
+				this.canvas.zoomToPoint(new fabric.Point(center.left, center.top), scale);
+			}
+			this.canvas.fire("transform", {
+				scale: scale
+			});
+			if (!this.workSpace) return;
+			this.setCenterFromObject(this.workSpace);
+			// 瓒呭嚭鐢诲竷涓嶅睍绀�+			_this.workSpace.clone().then((cloned) => {
+				_this.canvas.clipPath = cloned;
+				_this.canvas.requestRenderAll();
+			});
+		},
+		setDrawingType(type, svg) {
+			if (svg) {
+				if (type == "svg") {
+					this.drawType = "svg"
+					this.drawSvg = svg
+					return
+				}
+			}
+			if (type == "line") {
+				this.drawType = "line"
+			} else {
+				this.drawType = ""
+			}
+		},
+		deleteSelected() {
+			const list = this.canvas.getActiveObjects()
+			list.map((item) => this.canvas.remove(item));
+			this.canvas.requestRenderAll();
+			this.canvas.discardActiveObject();
+			this.canvas.fire("object:modified");
+
+		},
+		/**
+		 * 璁剧疆鐢诲竷涓績鍒版寚瀹氬璞′腑蹇冪偣涓�+		 * @param {Object} obj 鎸囧畾鐨勫璞�+		 */
+		setCenterFromObject(obj) {
+			const objCenter = obj.getCenterPoint();
+			const viewportTransform = this.canvas.viewportTransform;
+			if (this.canvas.width === undefined || this.canvas.height === undefined || !viewportTransform)
+				return;
+			viewportTransform[4] = this.canvas.width / 2 - objCenter.x * viewportTransform[0];
+			viewportTransform[5] = this.canvas.height / 2 - objCenter.y * viewportTransform[3];
+			this.canvas.setViewportTransform(viewportTransform);
+			this.canvas.renderAll();
+		},
+		handleSingleTouch(touch) {
+			this.touchStartPoint = {
+				x: touch.clientX,
+				y: touch.clientY
+			};
+			console.log('鍗曠偣瑙︽懜寮�');
+
+			let activeObj = this.canvas.getActiveObject();
+			if (!activeObj) {
+				if (!this.drawType) {
+					this.isDrawing = false;
+					this.isDragging = true;
+					this.lastPosX = touch.clientX;
+					this.lastPosY = touch.clientY;
+				} else {
+					this.isDragging = false;
+					this.isDrawing = true;
+
+				}
+			}
+
+			// 鍗曠偣瑙︽懜閫昏緫
+		},
+		handleMultiTouch(touches) {
+			const _this = this
+			const touch1 = touches[0];
+			const touch2 = touches[1];
+			this.initialDistance = Math.sqrt(
+				Math.pow(touch2.clientX - touch1.clientX, 2) +
+				Math.pow(touch2.clientY - touch1.clientY, 2)
+			);
+			this.initialZoom = this.canvas.getZoom();
+			// 澶氱偣瑙︽懜鍒濆閫昏緫
+		},
+		handleSingleTouchMove(touch) {
+			console.log('鍗曠偣绉诲姩', touch.clientX, touch.clientY);
+			if (this.isDragging) {
+				const deltaX = touch.clientX - this.lastPosX;
+				const deltaY = touch.clientY - this.lastPosY;
+				// 绉诲姩瑙嗗彛
+				console.log('relativePan', deltaX, deltaY);
+
+				this.canvas.relativePan(new fabric.Point(deltaX, deltaY));
+				this.lastPosX = touch.clientX;
+				this.lastPosY = touch.clientY;
+			} else if (this.isDrawing) {
+				const vpt = this.canvas.viewportTransform;
+				console.log("viewportTransform", vpt[4], vpt[5])
+				let startX = this.touchStartPoint.x - vpt[4]
+				let startY = this.touchStartPoint.y - vpt[5]
+				let endX = touch.clientX - vpt[4]
+				let endY = touch.clientY - vpt[5]
+
+				const scale = this.canvas.getZoom();
+				startX /= scale
+				startY /= scale
+				endX /= scale
+				endY /= scale
+				console.log("viewportTransform", startX, startY, endX, endY)
+				const left =
+					endX > startX ?
+					startX :
+					endX;
+				const top =
+					endY > startY ?
+					startY :
+					endY;
+				let width = Math.abs(endX - startX)
+				let height = Math.abs(endY - startY)
+
+
+				if (this.drawType == "rect") {
+					if (this.drawingObj) {
+						this.drawingObj.set({
+							left,
+							top,
+							width,
+							height
+						})
+						this.drawingObj.setCoords()
+					} else {
+						const rect = new fabric.Rect({
+							id: `${new Date().getTime()}`,
+							eleType: "rect",
+							left,
+							top,
+							width,
+							height,
+							stroke: "#333",
+							strokeWidth: 1,
+							fill: "#fff",
+							lockEdit: true
+						});
+						this.canvas.add(rect);
+						this.drawingObj = rect
+					}
+					this.canvas.requestRenderAll();
+				} else if (this.drawType == "ellipse") {
+					if (this.drawingObj) {
+						this.drawingObj.set({
+							left,
+							top,
+							rx: width / 2,
+							ry: height / 2,
+						})
+						this.drawingObj.setCoords()
+					} else {
+						const ellipse = new fabric.Ellipse({
+							id: `${new Date().getTime()}`,
+							eleType: "ellipse",
+							left,
+							top,
+							rx: width / 2,
+							ry: height / 2,
+							stroke: "#333",
+							strokeWidth: 1,
+							fill: "#fff",
+							lockEdit: true
+						});
+						this.canvas.add(ellipse);
+						this.drawingObj = ellipse
+					}
+					this.canvas.requestRenderAll();
+				} else if (this.drawType == "line") {
+					if (this.drawingObj) {
+						this.drawingObj.set({
+							left,
+							top,
+							x1: startX,
+							y1: startY,
+							x2: endX,
+							y2: endY,
+						})
+						this.drawingObj.setCoords()
+					} else {
+						const line = new fabric.Line([startX, startY, endX,
+							endY
+						], {
+							id: `${new Date().getTime()}`,
+							eleType: "line",
+							stroke: "#333",
+							strokeWidth: 5,
+							lockEdit: true
+						});
+						this.canvas.add(line);
+						this.drawingObj = line
+					}
+					this.canvas.requestRenderAll();
+				} else if (this.drawType == "arrow") {
+					if (this.drawingObj) {
+						this.setArrowPath(this.drawingObj, startX, startY, endX, endY);
+						this.drawingObj.setCoords()
+					} else {
+						let path = this.getArrowPath(
+							startX, startY, endX, endY,
+							30, 40
+						)
+						const line = new fabric.Path(path, {
+							id: `${new Date().getTime()}`,
+							eleType: "arrow",
+							stroke: "#333",
+							strokeWidth: 5,
+							lockEdit: true
+						});
+						this.canvas.add(line);
+						this.drawingObj = line
+					}
+					this.canvas.requestRenderAll();
+				} else if (this.drawType == "svg") {
+					if (this.drawingObj) {
+						this.drawingObj.set({
+							left,
+							top,
+							width,
+							height,
+						});
+						this.drawingObj.setCoords()
+					} else {
+						const _this = this
+						fabric.loadSVGFromURL(this.drawSvg).then(({
+							objects,
+							options
+						}) => {
+							const objGroup = fabric.util.groupSVGElements(objects, options);
+							objGroup.set({
+								id: `${new Date().getTime()}`,
+								eleType: "svg",
+								left,
+								top,
+								width,
+								height,
+								viewBoxWidth: options.viewBoxWidth || options.width,
+								viewBoxHeight: options.viewBoxHeight || options.height,
+								lockEdit: true
+							});
+							_this.canvas.add(objGroup)
+
+						});
+
+
+
+						this.drawingObj = line
+					}
+					this.canvas.requestRenderAll();
+				}
+
+
+			}
+
+			// 鍗曠偣绉诲姩閫昏緫
+		},
+		handleMultiTouchMove(touches) {
+			// 璁$畻涓ょ偣闂磋窛绂伙紙缂╂斁锛�+			if (!this.initialDistance) {
+				return
+			}
+			const _this = this
+			const touch1 = touches[0];
+			const touch2 = touches[1];
+			console.log('澶氱偣绉诲姩', touch1.identifier, touch2.identifier);
+
+			const distance = Math.sqrt(
+				Math.pow(touch2.clientX - touch1.clientX, 2) +
+				Math.pow(touch2.clientY - touch1.clientY, 2)
+			);
+
+			// 璁$畻鏃嬭浆瑙掑害
+			const angle = Math.atan2(
+				touch2.clientY - touch1.clientY,
+				touch2.clientX - touch1.clientX
+			) * 180 / Math.PI;
+
+			// 璁$畻涓績鐐�+			const center = {
+				x: (touch1.clientX + touch2.clientX) / 2,
+				y: (touch1.clientY + touch2.clientY) / 2
+			};
+
+			// 璁$畻缂╂斁姣斾緥 (闄愬埗鍦�.1-10鍊嶄箣闂�
+			let scale = Math.min(Math.max(
+				this.initialZoom * (distance / this.initialDistance),
+				0.1), 10);
+			let scaleAuto = this.getAutoScale()
+			if (scale < scaleAuto) {
+				scale = scaleAuto
+			} else if (scale == scaleAuto) {
+				return
+			}
+			console.log(scale, scaleAuto)
+			this.setZoomAuto(scale, center)
+
+			console.log('澶氱偣绉诲姩 - 璺濈:', distance, '瑙掑害:', angle);
+			// 澶氱偣绉诲姩閫昏緫
+		},
+		handleTouchEnd() {
+			console.log('鎵�湁瑙︽懜缁撴潫');
+			this.isDrawing = false
+			this.drawingObj = undefined
+			this.initialDistance = null;
+			// 瑙︽懜缁撴潫閫昏緫
+		},
+		addStation(info) {
+			const _this = this
+			return new Promise((resolve) => {
+				const zoom = _this.canvas.getZoom();
+				let svg = "static/images/station.svg"
+				// if (info.angle > 0) {
+				// 	if (info.angle / 3.14 <= 0.25) {
+				// 		svg = "static/images/station2.svg"
+				// 	} else if (info.angle / 3.14 <= 0.50) {
+				// 		svg = "static/images/station3.svg"
+				// 	} else if (info.angle / 3.14 <= 0.75) {
+				// 		svg = "static/images/station4.svg"
+				// 	} else if (info.angle / 3.14 <= 1) {
+				// 		svg = "static/images/station5.svg"
+				// 	}
+				// } else if (info.angle < 0) {
+				// 	if (info.angle / 3.14 < -0.75) {
+				// 		svg = "static/images/station5.svg"
+				// 	} else if (info.angle / 3.14 < -0.5) {
+				// 		svg = "static/images/station6.svg"
+				// 	} else if (info.angle / 3.14 < -0.25) {
+				// 		svg = "static/images/station7.svg"
+				// 	} else if (info.angle / 3.14 < 0) {
+				// 		svg = "static/images/station8.svg"
+				// 	}
+				// }
+
+				//	const scale = this.getAutoScale()
+				const left = info.x // * scale
+				const top = info.y //* scale
+				const angle = info.angle * 180 / 3.14
+				console.log("addStation", svg, info)
+				fabric.loadSVGFromURL(svg).then(
+					({
+						objects,
+						options
+					}) => {
+
+						const obj = fabric.util.groupSVGElements(objects, options);
+						obj.set({
+							id: `station_${new Date().getTime()}`,
+							eleType: "station",
+							left,
+							top,
+							angle,
+							data: info,
+							originX: "center",
+							originY: "center",
+							hasControls: this.editMode,
+							lockRotation: true,
+							lockScalingX: true,
+							lockScalingY: true,
+							lockMovementX: true,
+							lockMovementY: true,
+							canSelect: true,
+							lockEdit: true
+						});
+						_this.addObject(obj)
+						resolve()
+					}
+				)
+			})
+		},
+		updateAgv(info) {
+			const _this = this
+			return new Promise((resolve) => {
+				//	const scale = this.getAutoScale()
+				const left = info.x // * scale
+				const top = info.y // * scale
+				const angle = info.angle * 180 / 3.14
+				if (this.agvObj) {
+					this.agvObj.set({
+						left,
+						top,
+						angle,
+						data: info
+					});
+					this.agvObj.setCoords()
+					_this.canvas.requestRenderAll();
+					resolve()
+				} else {
+					const zoom = _this.canvas.getZoom();
+					fabric.loadSVGFromURL("static/images/van.svg").then(
+						({
+							objects,
+							options
+						}) => {
+
+							const obj = fabric.util.groupSVGElements(objects, options);
+
+							obj.set({
+								id: "agv",
+								eleType: "agv",
+								left,
+								top,
+								angle,
+								data: info,
+								originX: "center",
+								originY: "center",
+								//	scale: 1 / zoom,
+								hasControls: false,
+								lockRotation: true,
+								lockScalingX: true,
+								lockScalingY: true,
+								lockMovementX: true,
+								lockMovementY: true,
+								selectable: false,
+								lockEdit: true
+
+							});
+							console.log("agv", JSON.stringify(info))
+							_this.canvas.add(obj)
+							_this.agvObj = obj
+							resolve()
+						}
+					)
+				}
+
+			})
+		},
+		setAllObjectSelectable(selectable) {
+			let flag = false
+			this.canvas.forEachObject(function(obj) {
+				if (obj.canSelect) {
+					if (!obj.flag) {
+						flag = true
+					}
+					obj.set({
+						selectable: selectable,
+						lockEdit: true
+					})
+
+				}
+
+			});
+			if (flag) {
+				this.canvas.requestRenderAll()
+			}
+		},
+		receiveMsg(newValue, oldValue) {
+			if (typeof newValue == "undefined")
+				return;
+			const _this = this
+			//console.log("receiveMsg",_this.initFlag)
+			setTimeout(() => {
+				if (_this.initFlag) {
+					_this.handleMsg(newValue, oldValue)
+				} else {
+					_this.receiveMsg(newValue, oldValue)
+				}
+			}, 500)
+
+		},
+		async handleMsg(newValue, oldValue) {
+
+			const _this = this
+			try {
+				var data = JSON.parse(newValue);
+				for (var i = 0; i < data.length; i++) {
+					const item = data[i]
+
+					if (item.method == "init") {
+						if (item.param?.editMode) {
+							_this.editMode = true
+						} else {
+							_this.editMode = false
+						}
+					}
+
+					if (item.method == "background") {
+						await _this.setBackground(item.param)
+					} else if (item.method == "update_agv_state") {
+						const info = item.param || {}
+						await _this.updateAgv(info)
+						// const workSpaceWidth = this.workSpace.width
+						// const workSpaceHeight = this.workSpace.height
+
+
+					} else if (item.method == "move_canvas") {
+						const info = item.param || {}
+						//	const scale = this.getAutoScale()
+						const zoom = this.canvas.getZoom();
+						const eleHeight = this.eleHeight - 150
+
+						let deltaX = info.x * zoom - this.eleWidth / 2 // * scale;
+						let deltaY = info.y * zoom - eleHeight / 2 //* scale;
+						const vpt = this.canvas.viewportTransform;
+						const oldX = vpt[4]
+						const oldY = vpt[5]
+						if (deltaX + this.eleWidth > this.workSpace.width)
+							deltaX = this.workSpace.width - this.eleWidth
+						if (deltaY + eleHeight > this.workSpace.height)
+							deltaY = this.workSpace.height - eleHeight
+						if (oldX + this.eleWidth >= info.x * zoom && info.x * zoom >= oldX) {
+							deltaX = -oldX
+							//console.log("move_canvas X", oldX)
+						}
+						if (oldY + eleHeight >= info.y * zoom && info.y * zoom >= oldY) {
+							//	console.log("move_canvas Y", oldY)
+							deltaY = -oldY
+						}
+						_this.canvas.absolutePan(new fabric.Point(deltaX, deltaY));
+
+					} else if (item.method == "add_station") {
+						const stationList = item.param || []
+						let list = _this.canvas.getObjects() || []
+						for (let i2 in stationList) {
+							const station = stationList[i2]
+							const curIndex = list.findIndex((a) => a.data?.stationID == station.stationID)
+							if (curIndex < 0) {
+								await _this.addStation(station)
+							}
+						}
+					} else if (item.method == "update_station") {
+						const stationList = item.param || []
+						let list = _this.canvas.getObjects() || []
+						list = list.filter((a) => a.eleType == "station")
+						for (let i2 in stationList) {
+							const station = stationList[i2]
+							const curIndex = list.findIndex((a) => a.data.stationID == station.stationID)
+							if (curIndex < 0) {
+								await _this.addStation(station)
+							} else {
+								//	_this.canvas.remove(list[curIndex])
+								const curStationObj = list[curIndex]
+								const angle = station.angle * 180 / 3.14
+								//const scale = this.getAutoScale()
+								const left = station.x //* scale
+								const top = station.y //* scale
+								console.log("update_station", curIndex, left,
+									top,
+									angle)
+								if (curStationObj.left != left || top != station.y || curStationObj.angle !=
+									angle) {
+									curStationObj.set({
+										left,
+										top,
+										angle,
+										data: station
+									})
+									curStationObj.setCoords()
+								}
+							}
+
+						}
+
+					} else if (item.method == "remove_station") {
+						const stationList = item.param || []
+						let list = _this.canvas.getObjects() || []
+						list = list.filter((a) => a.eleType == "station")
+						for (let i2 in stationList) {
+							const station = stationList[i2]
+							const curIndex = list.findIndex((a) => a.data.stationID == station.stationID)
+							if (curIndex > -1) {
+								_this.canvas.remove(list[curIndex])
+							}
+						}
+
+					} else if (item.method == "select_station") {
+						const station = item.param || {}
+						let list = _this.canvas.getObjects() || []
+						list = list.filter((a) => a.eleType == "station")
+						_this.setAllObjectSelectable(false)
+
+						let listSel = []
+						const curIndex = list.findIndex((a) => a.data.stationID == station.stationID)
+						if (curIndex > -1) {
+							console.log("select_station", curIndex, list[curIndex])
+							listSel.push(list[curIndex])
+
+							list[curIndex].set({
+								selectable: true
+							})
+							_this.canvas.discardActiveObject();
+							// let sel = new fabric.ActiveSelection(listSel, {
+							// 	canvas: _this.canvas,
+							// });
+							_this.canvas.setActiveObject(list[curIndex]);
+						}
+					} else if (item.method == "edit_station_pos") {
+						const station = item.param || undefined
+						if (!station) {
+							if (_this.editObject) {
+								_this.editObject.set({
+									lockMovementX: true,
+									lockMovementY: true,
+								})
+								_this.editObject = null
+							}
+							continue
+						}
+						let list = _this.canvas.getObjects() || []
+						list = list.filter((a) => a.eleType == "station")
+						_this.setAllObjectSelectable(false)
+						const curIndex = list.findIndex((a) => a.data.stationID == station.stationID)
+						if (curIndex > -1) {
+							console.log("edit_station_pos", curIndex, list[curIndex])
+							if (_this.editObject != list[curIndex]) {
+								if (_this.editObject) {
+									_this.editObject.set({
+										lockMovementX: true,
+										lockMovementY: true,
+									})
+								}
+								_this.editObject = list[curIndex]
+								_this.editObject.set({
+									lockMovementX: false,
+									lockMovementY: false,
+								})
+							}
+							list[curIndex].set({
+								selectable: true,
+								lockEdit: false
+							})
+						}
+
+					} else if (item.method == "set_selectable") {
+						if (item.param)
+							_this.setAllObjectSelectable(true)
+						else
+							_this.setAllObjectSelectable(false)
+						if (_this.editObject) {
+							_this.editObject.set({
+								lockMovementX: true,
+								lockMovementY: true,
+							})
+							_this.editObject = null
+						}
+					}
+
+				}
+				_this.canvas.renderAll()
+			} catch (ex) {
+				console.log(ex)
+			}
+		},
+		showError(ex) {
+			const type = typeof ex
+			if (type == "string") {
+				let tip = ex
+				plus.nativeUI.alert(tip, undefined, "閿欒");
+				return
+			}
+			let exStr = JSON.stringify(ex)
+			if (exStr == "{}")
+				exStr = ex
+
+			let tip = typeof ex.msg == "string" ? ex.msg : exStr
+			plus.nativeUI.alert(tip, undefined, "閿欒");
+		},
+
+	},
+}
\ No newline at end of file
diff --git a/pages/map/task.vue b/pages/map/task.vue
new file mode 100644
index 0000000..a8c0a67
--- /dev/null
+++ b/pages/map/task.vue
@@ -0,0 +1,353 @@
+<template>
+	<view class="pages-map-task">
+		<view class="no-content" v-if="unlinked">
+			<image class="img" src="/images/image 25.png" alt=" 鍥剧墖" mode="aspectFit" />
+			<view class="title">杞﹁締杩炴帴澶辫触</view>
+			<view class="space">璇锋鏌ヤ綘鐨勭綉缁滆缃垨閲嶆柊鍔犺浇</view>
+		</view>
+		<view class="map-content" v-else>
+			<view class="content">
+
+			</view>
+			<view class="bottom">
+				<view class="button-group">
+					<view type="text" class="button" @click="clickTaskSet">
+						<uni-icons class="img" type="gear-filled" size="40" color="#1890FF"></uni-icons>
+						<view class="text"> 璁剧疆浠诲姟</view>
+
+					</view>
+					<view type="text" class="button" @click="clickTaskRecord">
+						<text class="ico task-list" />
+						<view class="text"> 浠诲姟璁板綍</view>
+						
+						
+
+					</view>
+				</view>
+
+			</view>
+		</view>
+
+	</view>
+</template>
+<script>
+	import {
+		showToast,
+		showModal
+	} from "@/comm/utils.js"
+	import {
+		Button
+	} from 'antd-mobile-vue-next'
+
+	import {
+		stations,
+		getAgvState,
+		getMapUrl,
+	} from "@/api/vehicle.js"
+	export default {
+		name: "PagesMapTask",
+		components: {
+			'a-button': Button
+		},
+		data() {
+			return {
+				vehicleIp: "",
+				navigationBarTitle: "鍦板浘浠诲姟",
+				unlinked: false
+			}
+		},
+		computed: {
+
+		},
+		onLoad(option) {
+
+			this.vehicleIp = option.ip || ""
+			this.loadData()
+		},
+		methods: {
+			setData(obj) {
+				let that = this;
+				let keys = [];
+				let val, data;
+
+				Object.keys(obj).forEach(function(key) {
+					keys = key.split(".");
+					val = obj[key];
+					data = that.$data;
+					keys.forEach(function(key2, index) {
+						if (index + 1 == keys.length) {
+							that.$set(data, key2, val);
+						} else {
+							if (!data[key2]) {
+								that.$set(data, key2, {});
+							}
+						}
+						data = data[key2];
+					});
+				});
+			},
+			async loadData() {
+				try {
+					const info = await getAgvState(this.vehicleIp)
+					this.setData({
+						unlinked: false
+					})
+				} catch (ex) {
+					this.setData({
+						unlinked: true
+					})
+
+				}
+			},
+			clickBack() {
+				const eventChannel = this.getOpenerEventChannel();
+				eventChannel.emit('check_connect', this.unlinked);
+				uni.navigateBack({
+					delta: 1
+				})
+			},
+			closeMenu() {
+				this.$refs.refPopupMenu.close()
+			},
+
+			async loadAgvState() {
+				try {
+					const info = await getAgvState(this.vehicleIp)
+					return info
+				} catch (ex) {
+					this.showError(ex)
+					return {}
+				}
+			},
+			async loadStations() {
+				try {
+					const info = await stations(this.vehicleIp)
+					return info.station_list || []
+				} catch (ex) {
+					this.showError(ex)
+					return []
+				}
+			},
+			clickTaskSet() {
+				uni.navigateTo({
+					url: `/pages/task/list?ip=${this.vehicleIp}`
+				})
+			},
+			clickTaskRecord() {
+				uni.navigateTo({
+					url: `/pages/task/log-list?ip=${this.vehicleIp}`
+				})
+			},
+			showError(ex) {
+				let exStr = JSON.stringify(ex)
+				if (exStr == "{}")
+					exStr = ex
+				let tip = typeof ex.msg == "string" ? ex.msg : exStr
+				showModal(tip, "閿欒", false)
+			},
+
+
+		}
+	}
+</script>
+
+<style lang="scss">
+	.pages-map-task {
+		display: flex;
+		width: 750rpx;
+		height: 100vh;
+		flex-direction: column;
+		background-color: #fff;
+
+		.uni-navbar-container-inner {
+			display: flex;
+			flex: 1;
+			flex-direction: row;
+			align-items: center;
+			justify-content: center;
+			font-size: 40rpx;
+			overflow: hidden;
+			font-weight: 700;
+			color: #333;
+
+			.icon {
+				width: 30rpx;
+				height: 16rpx;
+			}
+		}
+
+		.uni-nav-bar-text {
+			overflow: hidden;
+			white-space: nowrap;
+			text-overflow: ellipsis;
+		}
+
+		.map-content {
+			width: 100%;
+			display: flex;
+			flex-direction: column;
+			flex: 1;
+
+			.loading-overlay {
+				position: fixed;
+				top: 0;
+				left: 0;
+				right: 0;
+				bottom: 0;
+				background-color: rgba(0, 0, 0, 0.5);
+				display: flex;
+				justify-content: center;
+				align-items: center;
+				z-index: 999;
+
+				.loading-content {
+					background-color: #fff;
+					padding: 60rpx 100rpx;
+					border-radius: 20rpx;
+					text-align: center;
+				}
+
+				.loading-spinner {
+					width: 120rpx;
+					height: 120rpx;
+					border: 20rpx solid #f3f3f3;
+					border-top: 20rpx solid #1890FF;
+					border-radius: 50%;
+					animation: spin 1s linear infinite;
+					margin: 0 auto 40rpx;
+				}
+
+				@keyframes spin {
+					0% {
+						transform: rotate(0deg);
+					}
+
+					100% {
+						transform: rotate(360deg);
+					}
+				}
+
+			}
+
+
+			.content {
+				flex: 1;
+				overflow: auto;
+				display: flex;
+				position: relative;
+
+				.fabric {
+					width: 100%;
+					height: 100%;
+				}
+
+				.position {
+					position: absolute;
+					right: 30rpx;
+					bottom: 50rpx;
+
+					.img {
+						width: 65rpx;
+						height: 65rpx;
+					}
+				}
+			}
+
+			.bottom {
+				justify-content: center;
+				align-items: center;
+				margin: auto;
+				margin-bottom: 10px;
+
+				.button-group {
+					display: flex;
+					flex-direction: row;
+					border-radius: 10px;
+					border: 1px solid #fff;
+					font-size: 14px !important;
+
+					.button {
+						margin: 10rpx 20rpx;
+						width: 144rpx !important;
+						height: 144rpx !important;
+						border: 0;
+						display: flex;
+						flex-direction: column;
+						background-color: #00000000;
+
+						.img {
+							margin: auto;
+							width: 72rpx;
+							height: 72rpx;
+						}
+						.ico{
+							margin: auto;
+							font-size:60rpx;
+							color: #1890FF;
+						}
+						.text {
+							margin: auto;
+
+						}
+					}
+
+				}
+			}
+		}
+
+		.no-content {
+			margin-top: 50px;
+			padding: 20rpx 40rpx;
+			align-items: center;
+			text-align: center;
+			display: flex;
+			flex-direction: column;
+			font-size: 30rpx;
+			font-weight: 400;
+
+
+			.title {
+				font-size: 40rpx;
+				margin-bottom: 10rpx;
+			}
+
+
+		}
+
+		.popup-content {
+			display: flex;
+			justify-content: center;
+			flex-direction: column;
+			background-color: transparent;
+		}
+
+		.popup-content-menu {
+			margin-top: 75px;
+			margin-left: 120px;
+			width: 150px;
+			align-items: center;
+			justify-content: center;
+			flex-direction: column;
+			background-color: #fff;
+			border-radius: 5px;
+			border: 1px solid gray;
+		}
+
+		.popup-content-menu-item {
+			display: flex;
+			flex-wrap: nowrap;
+			flex-direction: row !important;
+			align-items: center;
+			padding: 4px 8px;
+			font-size: 16px;
+
+			.img {
+				width: 20px;
+				height: 20px;
+				margin: 5px;
+			}
+		}
+
+
+	}
+</style>
\ No newline at end of file
diff --git a/pages/my/help-feedback.vue b/pages/my/help-feedback.vue
new file mode 100644
index 0000000..ec3c404
--- /dev/null
+++ b/pages/my/help-feedback.vue
@@ -0,0 +1,126 @@
+<template>
+	<view class="pages-my">
+		<view class="group">
+			<view class="item line" @click="clickRemoteAssistance">
+				<view>杩滅▼鍗忓姪锛�/view>
+				<view class="right"></view>
+				<a>
+					<uni-icons class="icon" type="right" size="24" color="#888"></uni-icons>
+				</a>
+			</view>
+			<view class="item line" @click="clickUploadLog">
+				<view>鏃ュ織涓婁紶锛�/view>
+				<view class="right"></view>
+				<a>
+					<uni-icons class="icon" type="right" size="24" color="#888"></uni-icons>
+				</a>
+			</view>
+			<view class="item line" @click="clickViewInstruction">
+				<view>鏌ョ湅璇存槑涔︼細</view>
+				<view class="right"></view>
+				<a>
+					<uni-icons class="icon" type="right" size="24" color="#888"></uni-icons>
+				</a>
+			</view>
+			<view class="item line" @click="clickApiLog">
+				<view>鎺ュ彛鏃ュ織锛�/view>
+				<view class="right"></view>
+				<a>
+					<uni-icons class="icon" type="right" size="24" color="#888"></uni-icons>
+				</a>
+			</view>
+		</view>
+	</view>
+</template>
+<script>
+	import {
+		session,
+		showToast,
+		showModal
+	} from "@/comm/utils.js"
+	import {
+		Button
+	} from 'antd-mobile-vue-next'
+	export default {
+		name: "PagesMy",
+		components: {
+			'a-button': Button
+		},
+		data() {
+			return {
+
+			}
+		},
+		onLoad() {
+
+		},
+		computed: {
+
+		},
+		methods: {
+
+			clickRemoteAssistance() {
+				showToast("鏆傛湭瀹炵幇")
+			},
+			clickUploadLog() {
+				showToast("鏆傛湭瀹炵幇")
+			},
+			clickViewInstruction() {
+				uni.navigateTo({
+					url: "/pages/my/instruction"
+				})
+			},
+			clickApiLog() {
+				uni.navigateTo({
+					url: "/pages/my/log"
+				})
+			},
+
+
+
+
+		}
+	}
+</script>
+
+<style lang="scss">
+	.pages-my {
+		display: flex;
+		width: 750rpx;
+		height: 100vh;
+		flex-direction: column;
+
+		.group {
+			width: calc(100% - 40rpx);
+			border: 2rpx solid #ccc;
+			border-radius: 20rpx;
+			margin: 20rpx;
+			padding: 0 10rpx;
+			display: flex;
+			flex-direction: column;
+			background-color: #fff;
+
+			.item {
+				width: 100%;
+				padding: 20rpx 10rpx;
+				display: flex;
+				flex-direction: row;
+				align-items: center;
+
+				.right {
+					flex: 1;
+					text-align: right;
+					color: #888;
+				}
+			}
+
+			.line {
+				border-bottom: 2rpx solid #ccc;
+			}
+		}
+
+
+
+
+	}
+</style>
\ No newline at end of file
diff --git a/pages/my/index.vue b/pages/my/index.vue
new file mode 100644
index 0000000..9205263
--- /dev/null
+++ b/pages/my/index.vue
@@ -0,0 +1,345 @@
+<template>
+	<view class="pages-my">
+		<view class="group">
+			<view class="item line"  @click="clickAppVersion">
+				<view>App鐗堟湰锛�/view>
+				<view class="right">{{app_version}}</view>
+				<a>
+					<uni-icons class="icon" type="right" size="24" color="#888"></uni-icons>
+				</a>
+			</view>
+			<view class="item line" @click="clickLanguage">
+				<view>璇█鍒囨崲锛�/view>
+				<view class="right">{{languageStr}}</view>
+				<a >
+					<uni-icons class="icon" type="right" size="24" color="#888"></uni-icons>
+				</a>
+			</view>
+
+			<!-- 	<view class="item line">
+				<view>闅愮鏀跨瓥锛�/view>
+				<view class="right"></view>
+				<a @click="clickPrivacyPolicy">
+					<uni-icons class="icon" type="right" size="24"></uni-icons>
+				</a>
+			</view>
+			<view class="item line">
+				<view>澶囦唤杞﹁締涓庡叡浜細</view>
+				<view class="right"></view>
+				<a @click="clickBackupVehicleShare">
+					<uni-icons class="icon" type="right" size="24"></uni-icons>
+				</a>
+			</view>
+		 -->
+			<view class="item line" @click="clickClearCache">
+				<view>娓呮缂撳瓨锛�/view>
+				<view class="right">{{cacheSizeStr}}</view>
+				<a >
+					<uni-icons class="icon" type="right" size="24" color="#888"></uni-icons>
+				</a>
+			</view>
+			<view class="item line"  @click="clickHelp">
+				<view>甯姪涓庡弽棣堬細</view>
+				<view class="right"></view>
+				<a>
+					<uni-icons class="icon" type="right" size="24" color="#888"></uni-icons>
+				</a>
+			</view>
+			<!-- 			<view class="item">
+				<view>鐢ㄦ埛鍗忚锛�/view>
+				<view class="right"></view>
+				<a @click="clickUserAgreement">
+					<uni-icons class="icon" type="right" size="24"  color="#888"></uni-icons>
+				</a>
+			</view> -->
+		</view>
+
+		<view class="button-group">
+			<!-- 	<button class="button" @click="clickModifyPassword">淇敼瀵嗙爜</button>
+			<button class="button" @click="clickChangeAccount">鍒囨崲璐﹀彿</button> -->
+			<a-button class="button" type="ghost" @click="clickExitAccount">閫�嚭鐧诲綍</a-button>
+		</view>
+		<view>
+			<uni-popup ref="refPopupMenu" background-color="transparent" maskBackgroundColor="rgba(0, 0, 0, 0.2)">
+				<view class="popup-content" @click="closeMenu">
+					<picker-view class="popup-content-view" :indicator-style="indicatorStyle" :value="[langIndex]"
+						@change="bindLanguageChange">
+						<picker-view-column>
+							<view class="item" v-for="(item,index) in langList" :key="index">{{item.name}}</view>
+						</picker-view-column>
+
+					</picker-view>
+				</view>
+			</uni-popup>
+		</view>
+	</view>
+</template>
+<script>
+	import {
+		session,
+		showToast,
+		showModal
+	} from "@/comm/utils.js"
+	import {
+		Button
+	} from 'antd-mobile-vue-next'
+	export default {
+		name: "PagesMy",
+		components: {
+			'a-button': Button
+		},
+		data() {
+			return {
+				indicatorStyle: `height: 75rpx;`,
+				app_version: "1.0.0",
+				backup_vehicle_share: "",
+				langIndex: 0,
+				cache_size: 5000000,
+				langList: [{
+					value: "zh-Hans",
+					name: "涓枃绠�綋"
+				}, {
+					value: "zh-Hant",
+					name: "涓枃绻佷綋"
+				}, {
+					value: "en",
+					name: "English"
+				}],
+			}
+		},
+		onLoad() {
+			// this.loadData()
+
+		},
+		computed: {
+			cacheSizeStr() {
+				let size = 0
+				if (this.cache_size < 1024) {
+					size = Math.round(this.cache_size * 100)
+					return `${size/100} KB`
+				} else if (this.cache_size < 1024 * 1024) {
+					size = Math.round(this.cache_size * 100 / 1024)
+					return `${size/100} MB`
+				} else {
+					size = Math.round(this.cache_size * 100 / (1024 * 1024 * 1024))
+					return `${size/100} GB`
+				}
+			},
+			languageStr() {
+				if (this.langIndex > -1) {
+					return this.langList[this.langIndex].name || ""
+				}
+
+
+			}
+
+		},
+		onTabItemTap() {
+			this.loadData()
+		},
+		methods: {
+			setData(obj) {
+				let that = this;
+				let keys = [];
+				let val, data;
+
+				Object.keys(obj).forEach(function(key) {
+					keys = key.split(".");
+					val = obj[key];
+					data = that.$data;
+					keys.forEach(function(key2, index) {
+						if (index + 1 == keys.length) {
+							that.$set(data, key2, val);
+						} else {
+							if (!data[key2]) {
+								that.$set(data, key2, {});
+							}
+						}
+						data = data[key2];
+					});
+				});
+			},
+			loadData() {
+				const _this = this
+
+				const language = uni.getLocale()
+				this.langIndex = this.langList.findIndex((a) => a.value == language)
+
+				this.loadCache()
+				// #ifdef APP-PLUS
+				plus.runtime.getProperty(plus.runtime.appid, (info) => {
+					// console.log(info);
+					_this.setData({
+						app_version: info.version
+					})
+				});
+				//#endif
+			},
+			loadCache() {
+				const _this = this
+				uni.getStorageInfo({
+					success: (res) => {
+						_this.setData({
+							cache_size: res.currentSize
+						})
+						console.log('褰撳墠缂撳瓨澶у皬锛�, res, 'KB');
+					},
+					fail: (err) => {
+						console.error('鑾峰彇缂撳瓨淇℃伅澶辫触锛�, err);
+					},
+					complete: () => {
+						console.log('缂撳瓨淇℃伅鑾峰彇瀹屾垚');
+					},
+				});
+			},
+			bindLanguageChange(e) {
+				console.log(e)
+				const val = e.detail.value
+				this.langIndex = val[0]
+				uni.setLocale(this.langList[this.langIndex].value)
+			},
+			closeMenu() {
+				this.$refs.refPopupMenu.close()
+			},
+			clickAppVersion() {
+				uni.navigateTo({
+					url: "/pages/my/version-update"
+				})
+			},
+			clickPrivacyPolicy() {
+
+			},
+			clickBackupVehicleShare() {
+
+			},
+			clickLanguage() {
+
+				this.$refs.refPopupMenu.open("right")
+			},
+			clickClearCache() {
+				try {
+					let list = session.getValue("vehicles") || []
+					const info = session.getValue("login_info")
+					uni.clearStorageSync();
+					session.setValue("vehicles", list)
+					session.setValue("login_info", info)
+					showToast("娓呴櫎缂撳瓨鎴愬姛锛�)
+					this.loadCache()
+				} catch (e) {
+					// error
+				}
+			},
+			clickHelp() {
+				uni.navigateTo({
+					url: "/pages/my/help-feedback"
+				})
+			},
+			clickUserAgreement() {
+
+			},
+	
+			clickModifyPassword() {
+
+			},
+			clickChangeAccount() {
+
+			},
+			clickExitAccount() {
+				uni.reLaunch({
+					url: "/pages/login/index"
+				})
+			},
+
+		}
+	}
+</script>
+
+<style lang="scss">
+	.pages-my {
+		display: flex;
+		width: 750rpx;
+		height: 100vh;
+		flex-direction: column;
+
+		.group {
+			width: calc(100% - 40rpx);
+			border: 2rpx solid #ccc;
+			border-radius: 20rpx;
+			margin: 20rpx;
+			padding: 0 10rpx;
+			display: flex;
+			flex-direction: column;
+			background-color: #fff;
+
+			.item {
+				width: 100%;
+				padding: 20rpx 10rpx;
+				display: flex;
+				flex-direction: row;
+				align-items: center;
+
+				.right {
+					flex: 1;
+					text-align: right;
+					color: #888;
+				}
+			}
+
+			.line {
+				border-bottom: 2rpx solid #ccc;
+			}
+		}
+
+
+		.button-group {
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			flex-direction: column;
+			font-size: 30rpx !important;
+
+			.am-button {
+				border-radius: 30px;
+			}
+
+			.am-button-ghost {
+				border: 1px solid red !important;
+				color: red !important;
+
+			}
+		}
+
+		.button {
+			margin: auto;
+			margin-top: 20rpx;
+			border-radius: 4rpx;
+			width: 500rpx;
+		}
+
+		.popup-content {
+			display: flex;
+			justify-content: center;
+			flex-direction: column;
+			background-color: transparent;
+		}
+
+		.popup-content-view {
+			width: 150px;
+			height: 150px;
+			border-radius: 10rpx;
+			padding: 10rpx 20rpx;
+			background-color: #fff;
+			margin-top: 100px;
+			margin-right: 50px;
+
+			.item {
+				line-height: 75rpx;
+				text-align: center;
+				border: 0;
+
+			}
+		}
+
+
+	}
+</style>
\ No newline at end of file
diff --git a/pages/my/instruction.vue b/pages/my/instruction.vue
new file mode 100644
index 0000000..a5be107
--- /dev/null
+++ b/pages/my/instruction.vue
@@ -0,0 +1,96 @@
+<template>
+	<view class="pages-my-instruction">
+		<view class="content">
+			<view class="title">瑙嗛璇存槑</view>
+			<view class="vidio">
+				<video></video>
+				
+			</view>
+		</view>
+
+	</view>
+</template>
+<script>
+	import {
+		showToast,
+		showModal
+	} from "@/comm/utils.js"
+	import jvideo from '@/components/j-video.vue'
+	export default {
+		name: "PagesMyInstruction",
+		components:{jvideo},
+		data() {
+			return {
+
+
+			}
+		},
+		onLoad() {
+
+		},
+
+		methods: {
+			setData(obj) {
+				let that = this;
+				let keys = [];
+				let val, data;
+
+				Object.keys(obj).forEach(function(key) {
+					keys = key.split(".");
+					val = obj[key];
+					data = that.$data;
+					keys.forEach(function(key2, index) {
+						if (index + 1 == keys.length) {
+							that.$set(data, key2, val);
+						} else {
+							if (!data[key2]) {
+								that.$set(data, key2, {});
+							}
+						}
+						data = data[key2];
+					});
+				});
+			},
+			clickRemoteAssistance() {
+
+			},
+			clickUploadLog() {
+
+			},
+			clickViewInstruction() {
+
+			},
+
+
+		}
+	}
+</script>
+
+<style lang="scss">
+	.pages-my-instruction {
+		display: flex;
+		width: 750rpx;
+		height: 100vh;
+		flex-direction: column;
+
+		.content {
+
+			.title {
+				font-size: 30rpx;
+				margin: 20rpx 20rpx 20rpx 80rpx;
+
+			}
+
+			.vidio {
+				margin: auto;
+				width: 600rpx;
+				height: 400rpx;
+				background-color: #fff;
+			}
+		}
+
+
+
+
+	}
+</style>
\ No newline at end of file
diff --git a/pages/my/language.vue b/pages/my/language.vue
new file mode 100644
index 0000000..d4dcf05
--- /dev/null
+++ b/pages/my/language.vue
@@ -0,0 +1,74 @@
+<template>
+	<view class="pages-my-language">
+		<view class="uni-line" v-for="item in langList" :key='item.value' @click="clickLanguage(item.value)"><text
+				class="name">{{item.name }}</text> <uni-icons v-if="curLang==item.value " type="checkmarkempty"
+				:size="20"></uni-icons> </view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				langList: [{
+					value: "zh-Hans",
+					name: "涓枃绠�綋"
+				}, {
+					value: "zh-Hant",
+					name: "涓枃绻佷綋"
+				}, {
+					value: "en",
+					name: "English"
+				}],
+				curLang: "",
+				oldLang: "",
+			}
+		},
+		methods: {
+			clickLanguage(lang) {
+				this.curLang = lang
+				const _this = this
+				uni.setLocale(lang)
+				// this.$i18n.locale =lang;
+
+			},
+			translateSys(t) {
+				if (typeof this.$t == "function") return this.$t(`sys.${t}`)
+				else return t;
+			},
+		},
+		onLoad() {
+
+			this.curLang = uni.getLocale()
+			this.oldLang = this.curLang
+		},
+		onUnload() {
+			if (this.oldLang != this.curLang) {
+				uni.reLaunch({
+					url: '/pages/my/index'
+				});
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.pages-my-language {
+		display: flex;
+		width: 720rpx;
+		flex-direction: column !important;
+		padding: 15rpx;
+
+		.uni-line {
+			padding: 15rpx 5rpx;
+			border-bottom: 1px solid #e8eaec;
+			display: flex;
+			flex-direction: row;
+
+			.name {
+				flex: 1;
+			}
+
+		}
+	}
+</style>
\ No newline at end of file
diff --git a/pages/my/log-detail.vue b/pages/my/log-detail.vue
new file mode 100644
index 0000000..82168f5
--- /dev/null
+++ b/pages/my/log-detail.vue
@@ -0,0 +1,126 @@
+<template>
+	<view class="pages-my-log-detail">
+		<view class="title"> {{'鎺ュ彛 '+ info.date}}
+		</view>
+		<view class="content">{{info.method + " " + info.url}}
+		</view>
+		<template v-if="info.method == 'POST'">
+			<view class="title">鍙傛暟
+			</view>
+			<textarea class="param" disabled :value="paramText"></textarea>
+		</template>
+		<template v-if="info.statusCode!=200">
+			<view class="title">閿欒鐮�+			</view>
+			<view class="content error">{{info.statusCode}}
+			</view>
+			<view class="title">閿欒淇℃伅
+			</view>
+			<view class="content error">{{info.msg}}
+			</view>
+		</template>
+		<template v-else>
+			<view class="title">缁撴灉
+			</view>
+			<textarea class="result" disabled :value="result"></textarea>
+			<!-- <view class="result">{{result}}
+			</view> -->
+		</template>
+	</view>
+</template>
+<script>
+	import {
+		session,
+	} from "@/comm/utils.js"
+	export default {
+		name: "PagesMyLogDetail",
+		data() {
+			return {
+				info: {}
+
+			}
+		},
+		onLoad(option) {
+			this.info = JSON.parse(option.info) || {}
+			if(this.info.data_key)
+			{
+				const maxData = session.getValue("request_log_max_data") || {}
+				this.info.data = maxData[this.info.data_key]
+			}
+			uni.setNavigationBarTitle({
+				title: this.info.method || "鎺ュ彛鏃ュ織璇︽儏"
+			})
+			
+			
+		},
+		computed: {
+			paramText() {
+				const res = this.info.param
+				return typeof res == 'string' ? res : JSON.stringify(res)
+			},
+			result() {
+				const res = this.info.data
+				return typeof res == 'string' ? res : JSON.stringify(res)
+			}
+		},
+		methods: {
+
+		}
+	}
+</script>
+
+<style lang="scss">
+	.pages-my-log-detail {
+		display: flex;
+		width: 750rpx;
+		height: 100vh;
+		flex-direction: column;
+		background-color: #F5F5F5;
+
+		.title {
+			margin: 5rpx;
+			font-size: 32rpx;
+			font-weight: 700;
+		}
+
+		.content {
+			padding: 20rpx 10rpx;
+			border-radius: 10rpx;
+			background-color: #fff;
+			width: 710rpx;
+			margin: 10rpx;
+			word-wrap: break-word;
+			/* 鍏佽闀垮崟璇嶆垨 URL 鍦板潃鎹㈣鍒颁笅涓� */
+			word-break: break-all;
+			/* 寮哄埗鏂囨湰鍦ㄨ秴鍑哄鍣ㄥ搴︽椂鎹㈣ */
+			white-space: normal;
+			/* 鍏佽鏂囨湰鎹㈣ */
+		}
+
+		.result {
+			flex: 1;
+			overflow: auto;
+			padding: 20rpx 10rpx;
+			border-radius: 10rpx;
+			background-color: #fff;
+			width: 710rpx;
+			margin: 10rpx;
+		}
+
+		.param {
+			max-height: 50vh;
+			overflow: auto;
+			padding: 20rpx 10rpx;
+			border-radius: 10rpx;
+			background-color: #fff;
+			width: 710rpx;
+			margin: 10rpx;
+		}
+
+		.error {
+			color: red;
+
+		}
+
+	}
+</style>
\ No newline at end of file
diff --git a/pages/my/log.vue b/pages/my/log.vue
new file mode 100644
index 0000000..a824105
--- /dev/null
+++ b/pages/my/log.vue
@@ -0,0 +1,117 @@
+<template>
+	<view class="pages-my-log">
+		<view class="list">
+			<view class="group" v-for="(item,index) in list" :key="index">
+				<view class="title" :class="item.statusCode!=200 ? 'error':''">{{ item.date+" "+item.url}}
+				</view>
+				<a @click="clickDetail(item)">
+					<uni-icons type="right" size="24"></uni-icons>
+				</a>
+			</view>
+		</view>
+		<view class="bottom">
+			<a-button class="button" @click="clickClearLog">娓呯┖</a-button>
+		</view>
+	</view>
+</template>
+<script>
+	import {
+		session,
+		showToast,
+		showModal
+	} from "@/comm/utils.js"
+	import {
+		Button
+	} from 'antd-mobile-vue-next'
+	export default {
+		name: "PagesMyLog",
+		components: {
+			'a-button': Button
+		},
+		data() {
+			return {
+				list: []
+
+			}
+		},
+		onLoad() {
+			this.list = session.getValue("request_log") || []
+		},
+		methods: {
+			clickDetail(item) {
+				uni.navigateTo({
+					url: `/pages/my/log-detail?info=${JSON.stringify(item)}`
+				})
+			},
+			clickClearLog() {
+				session.setValue("request_log", [])
+				session.setValue("request_log_max_data", {})
+				
+				this.list = []
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.pages-my-log {
+		display: flex;
+		width: 750rpx;
+		height: 100vh;
+		flex-direction: column;
+		background-color: #F5F5F5;
+
+		.list {
+			flex: 1;
+			overflow: auto;
+			display: flex;
+			flex-direction: column;
+		}
+
+		.group {
+
+
+			width: calc(100% - 30rpx);
+			padding: 10rpx 10rpx;
+			display: flex;
+			flex-direction: row;
+			margin: 5rpx;
+			background-color: #fff;
+			border-radius: 10rpx;
+			font-size: 30rpx;
+
+			.title {
+				flex: 1;
+				display: flex;
+				flex-direction: row;
+				margin: 5rpx;
+				word-wrap: break-word;
+				/* 鍏佽闀垮崟璇嶆垨 URL 鍦板潃鎹㈣鍒颁笅涓� */
+				word-break: break-all;
+				/* 寮哄埗鏂囨湰鍦ㄨ秴鍑哄鍣ㄥ搴︽椂鎹㈣ */
+				white-space: normal;
+				/* 鍏佽鏂囨湰鎹㈣ */
+			}
+
+			.error {
+				margin: 5rpx;
+				color: red;
+			}
+
+		}
+
+		.bottom {
+			margin: 10rpx;
+			display: flex;
+			flex-direction: row;
+			justify-content: center;
+			align-items: center;
+
+			.button {
+				width: 500rpx;
+				color: red;
+			}
+		}
+
+	}
+</style>
\ No newline at end of file
diff --git a/pages/my/version-update.vue b/pages/my/version-update.vue
new file mode 100644
index 0000000..c579404
--- /dev/null
+++ b/pages/my/version-update.vue
@@ -0,0 +1,207 @@
+<template>
+	<view class="pages-my-version-update">
+		<view class="group">
+			<view class="item">
+				<view>鑷姩鏇存柊</view>
+				<view class="right"></view>
+				<switch :checked="autoUpdate" @change="switchChangeAutoUpdate" />
+			</view>
+
+		</view>
+		<view class="tip">
+			寮�惎鍚庯紝璁惧灏嗗湪2:00-6:00鑷姩鏇存柊杞欢鐗堟湰
+		</view>
+		<view class="group" v-if="newPack.size > 0">
+			<view class="item big-text ">
+				鍙洿鏂扮増鏈瑊{newPack.version}}
+			</view>
+			<view class="item gray-text">
+				{{newVersionSize}}
+			</view>
+			<view class="item">
+				鏈夋洿鏂扮殑鐗堟湰{{newPack.version}}
+			</view>
+			<view class="item">
+				褰撳墠鐗堟湰涓簕{appVersion}}
+			</view>
+		</view>
+		<view class="no-version gray-text" v-else>
+			<uni-icons type="upload-filled" size="150" color="#888"></uni-icons>
+			褰撳墠涓烘渶鏂扮増鏈瑊{appVersion}}
+		</view>
+
+		<view class="button-group" v-if="newPack.size > 0">
+			<a-button type="primary" class="button" @click="clickNowUpdate">鐜板湪鏇存柊</a-button>
+		</view>
+	</view>
+</template>
+<script>
+	import {
+		session,
+		showToast,
+		showModal
+	} from "@/comm/utils.js"
+	import {
+		Button
+	} from 'antd-mobile-vue-next'
+	export default {
+		name: "PagesMyVersionUpdate",
+		components: {
+			'a-button': Button
+		},
+		data() {
+			return {
+				autoUpdate:false,
+				appVersion: "1.0.0",
+				newPack:{}
+				// newPack: {
+				// 	version: "1.0.0",
+				// 	size: 200 * 1024 * 1024,
+				// }
+			}
+		},
+		onLoad() {
+			this.loadData()
+
+		},
+		computed: {
+			newVersionSize() {
+				const packSize = this.newPack?.size || 0
+				let size = 0
+				if (packSize < 1024) {
+					size = Math.round(packSize * 100)
+					return `${size/100} KB`
+				} else if (packSize < 1024 * 1024) {
+					size = Math.round(packSize * 100 / 1024)
+					return `${size/100} MB`
+				} else {
+					size = Math.round(packSize * 100 / (1024 * 1024 * 1024))
+					return `${size/100} GB`
+				}
+			}
+
+		},
+		methods: {
+			setData(obj) {
+				let that = this;
+				let keys = [];
+				let val, data;
+
+				Object.keys(obj).forEach(function(key) {
+					keys = key.split(".");
+					val = obj[key];
+					data = that.$data;
+					keys.forEach(function(key2, index) {
+						if (index + 1 == keys.length) {
+							that.$set(data, key2, val);
+						} else {
+							if (!data[key2]) {
+								that.$set(data, key2, {});
+							}
+						}
+						data = data[key2];
+					});
+				});
+			},
+			loadData() {
+				
+					this.autoUpdate = session.getValue("auto_update") ? true :false
+				const _this = this
+				// #ifdef APP-PLUS
+				plus.runtime.getProperty(plus.runtime.appid, (info) => {
+					// console.log(info);
+					_this.setData({
+						appVersion: info.version
+					})
+				});
+				//#endif
+			},
+
+
+			switchChangeAutoUpdate(e) {
+				this.autoUpdate = e.detail.value
+				session.setValue("auto_update", this.autoUpdate ? 1 :0)
+			},
+
+			clickNowUpdate() {
+			
+			},
+
+		}
+	}
+</script>
+
+<style lang="scss">
+	.pages-my-version-update {
+		display: flex;
+		width: 750rpx;
+		height: 100vh;
+		flex-direction: column;
+
+		.group {
+			width: calc(100% - 40rpx);
+			border: 2rpx solid #ccc;
+			background-color: #fff;
+			border-radius: 20rpx;
+			margin: 20rpx;
+			padding: 0 10rpx;
+			display: flex;
+			flex-direction: column;
+
+			.item {
+				width: 100%;
+				padding: 20rpx 10rpx;
+				display: flex;
+				flex-direction: row;
+				align-items: center;
+
+				.right {
+					flex: 1;
+					text-align: right;
+					color: #888;
+				}
+			}
+
+
+		}
+		.tip{
+			color: #888;
+			padding: 10rpx;
+			margin-left: 50rpx;
+		}
+		.gray-text {
+			color: #888;
+		}
+
+		.big-text {
+			font-size: 40rpx;
+		}
+		.no-version{
+			margin: auto;
+			display: flex;
+			flex-direction: column;
+		}
+
+		.button-group {
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			flex-direction: column;
+			font-size: 30rpx !important;
+
+			.am-button {
+				border-radius: 30px;
+			}
+
+		}
+
+		.button {
+			margin: auto;
+			margin-top: 20rpx;
+			border-radius: 4rpx;
+			width: 500rpx;
+		}
+
+
+	}
+</style>
\ No newline at end of file
diff --git a/pages/station/index.vue b/pages/station/index.vue
new file mode 100644
index 0000000..82b6154
--- /dev/null
+++ b/pages/station/index.vue
@@ -0,0 +1,1046 @@
+<template>
+	<view class="pages-station">
+		<view class="view-content" v-if="opStationType =='edit_pos'">
+			<view class="map-content">
+				<view class="position-site">
+					<a-button type="ghost" class="button" @click="clickPositionStation">
+						<text class="ico my-location-rounded" />
+						<text class="text">鑾峰彇鎼繍杞︿綅缃拰鏈濆悜</text>
+					</a-button>
+				</view>
+			</view>
+		</view>
+		<view class="view-content" v-else-if="!onlyAdd">
+			<view class="list-content" v-if="stationList.length > 0">
+				<uni-swipe-action class="list">
+					<uni-swipe-action-item class="list-item"
+						:class="{'selected':stationEdit.stationID ==item.stationID,'border-top':index!= 0}"
+						v-for="(item,index) in stationList" :key="index" :auto-close="true"
+						@touchstart="onTouchStartStation(item)" @mousedown="onTouchStartStation(item)"
+						@mouseup="onTouchCancelStation" @touchend="onTouchCancelStation"
+						@touchcancel="onTouchCancelStation">
+						<view class="item-title">{{item.name}}</view>
+						<view class="item-text">
+							瑙掑害锛歿{Math.round(item.angle *180/3.14)}}锛屽潗鏍囷紙{{Math.round(Number(item.x)*100)/100}},{{Math.round(Number(item.y)*100)/100}})
+						</view>
+						<template v-slot:right>
+							<view class="btn-del" @click="clickDelStation(item)">鍒犻櫎</view>
+						</template>
+					</uni-swipe-action-item>
+				</uni-swipe-action>
+			</view>
+			<view class="list-no-content" v-else>
+				<uni-icons color="#ccc" type="info" size="128"></uni-icons>
+				<view class="space">杩樻病鏈夌珯鐐�/view>
+			</view>
+			<view class="position-add" v-if="opStationType ==''" @click="clickAddStation" @touchstart='btnAddTouchStart'
+				@touchmove='btnAddTouchMove'
+				:style="{transform:`translate(${btnAddInfo.x}px,${btnAddInfo.y}px) scale(1)`}">
+				<uni-icons type="plus-filled" size="80" color="#1890FF"></uni-icons>
+			</view>
+		</view>
+
+		<view class="bottom">
+			<view class="bottom-content" v-if="opStationType =='edit_name'  ">
+				<view class="tip">璇疯緭鍏ョ珯鐐瑰悕绉�/view>
+				<view class="name-input">
+					<input ref="refInputName" :focus="true" placeholder="杈撳叆绔欑偣鍚嶇О" :value="stationEdit.name"
+						@input="onInputName"></input>
+					<uni-icons class="clear" color="#ccc" type="clear" size="20" v-if="showClearName"
+						@click="clickClearName"></uni-icons>
+				</view>
+				<view class="text-button-group">
+					<a-button type="ghost" class="button" @click="clickNameCancel">鍙栨秷</a-button>
+					<a-button type="primary" class="button" @click="clickNameOK">纭畾</a-button>
+				</view>
+			</view>
+			<view class="bottom-content" v-else-if=" opStationType =='edit_pos'">
+				<view class="tip">璋冭妭浣嶇疆</view>
+				<view class="row-group">
+					<view class="coordinate">
+						<text class="name">妯潗鏍�</text>
+						<input ref="refInputX" class="number-input" type="number" :value="stationEdit.x"
+							@input="onInputX"></input>
+					</view>
+					<view class="coordinate">
+						<text class="name">绔栧潗鏍�</text>
+						<input ref="refInputX" class="number-input" type="number" :value="stationEdit.y"
+							@input="onInputY"></input>
+					</view>
+				</view>
+
+				<view class="tip">璋冭妭鏈濆悜</view>
+				<view class="angle-group">
+					<image class="img-angle" :src="angleSvg" alt="SVG 鍥剧墖" />
+					<image class="img-angle-pos" src="/images/Frame 153.svg" alt="SVG 鍥剧墖"
+						@touchstart="handleAngleTouchStart" @touchmove="handleAngleTouchMove" />
+				</view>
+				<a-button type="primary" class="button" @click="clickPosOK">瀹屾垚</a-button>
+			</view>
+		</view>
+		<view>
+			<uni-popup ref="refPopupOperateStation" background-color="transparent"
+				maskBackgroundColor="rgba(0, 0, 0, 0.2)">
+				<view class="popup-content">
+					<view class="popup-content-btn">
+						<view class="img-button-group">
+							<view fill="none" class="button" @click.stop="clickStationDelete">
+								<text class="ico delete-outline"></text>
+								<view class="text"> 鍒犻櫎绔欑偣</view>
+							</view>
+							<view type="text" class="button" @click.stop="clickStationPostion">
+								<text class="ico edit-line"></text>
+								<view class="text">璋冩暣浣嶇疆鏈濆悜</view>
+							</view>
+							<view type="text" class="button" @click.stop="clickStationRename">
+								<text class="ico rename"></text>
+								<view class="text">閲嶅懡鍚�/view>
+
+							</view>
+						</view>
+					</view>
+
+				</view>
+			</uni-popup>
+		</view>
+	</view>
+</template>
+<script>
+	import {
+		showToast,
+		showModal,
+		session,
+	} from "@/comm/utils.js"
+	// import OIFabric from "@/components/oi-fabric/index.vue"
+	import {
+		Button
+	} from 'antd-mobile-vue-next'
+
+	import {
+		stations,
+		getAgvState,
+		addStation,
+		updateStation,
+		delStation
+	} from "@/api/vehicle.js"
+	export default {
+		name: "PagesStation",
+		components: {
+			'a-button': Button
+		},
+		data() {
+			return {
+				ip: "",
+				opStationType: "",
+				isEdit: false,
+				windowWidth: 375,
+				stationEdit: {
+					stationID: "",
+					name: "",
+					x: 0,
+					y: 0,
+					angle: 0
+				},
+				showClearName: false,
+				stationList: [],
+				angleSvg: "/static/images/angle0.svg",
+				onlyAdd: false,
+				btnAddInfo: {
+					lx: 0,
+					ly: 0,
+					x: 0,
+					y: 0
+				},
+			}
+		},
+		computed: {
+			getMaxStationNo() {
+				let num = 0
+				this.stationList.forEach((item) => {
+					if (num < item.stationID) {
+						num = item.stationID
+					}
+				})
+				return num
+			},
+		},
+		watch: {
+
+		},
+		onLoad(option) {
+			const _this = this
+			this.ip = option.ip || ""
+			this.onlyAdd = option.isAdd ? true : false
+
+			uni.setNavigationBarTitle({
+				title: "绔欑偣鍒楄〃"
+			})
+			uni.getSystemInfo({
+				success(e) {
+					_this.windowWidth = e.windowWidth
+				},
+
+			})
+			if (this.onlyAdd) {
+				this.opStationType = "edit_name"
+				uni.setNavigationBarTitle({
+					title: "娣诲姞绔欑偣"
+				})
+			}
+
+			this.loadData()
+
+		},
+		onBackPress() {
+			if (this.onlyAdd) {
+				if (this.opStationType == "edit_pos") {
+					this.opStationType = "edit_name"
+					return true
+				}
+				return false
+			}
+			if (this.isEdit) {
+				if (this.opStationType == "edit_name" || this.opStationType == "edit_pos") {
+					this.opStationType = ""
+					uni.setNavigationBarTitle({
+						title: "绔欑偣鍒楄〃"
+					})
+					this.$refs.refPopupOperateStation.open("bottom")
+
+					return true
+				}
+			} else {
+				if (this.opStationType == "edit_pos") {
+					this.opStationType = "edit_name"
+					return true
+				}
+			}
+
+			return false
+
+		},
+		methods: {
+			setData(obj) {
+				let that = this;
+				let keys = [];
+				let val, data;
+
+				Object.keys(obj).forEach(function(key) {
+					keys = key.split(".");
+					val = obj[key];
+					data = that.$data;
+					keys.forEach(function(key2, index) {
+						if (index + 1 == keys.length) {
+							that.$set(data, key2, val);
+						} else {
+							if (!data[key2]) {
+								that.$set(data, key2, {});
+							}
+						}
+						data = data[key2];
+					});
+				});
+			},
+			async loadData() {
+				try {
+					let btninfo = session.getValue('station_btn_add')
+					if (btninfo) {
+
+						if (btninfo.x > 10) {
+							btninfo.x = 10
+						}
+						if (btninfo.x > 40) {
+							btninfo.x = 40
+						}
+						this.btnAddInfo = btninfo
+					}
+					this.stationList = await this.loadStations() || []
+
+				} catch (ex) {
+
+					this.showError(ex)
+				}
+			},
+			async loadAgvState() {
+				try {
+					const info = await getAgvState(this.ip)
+					return info
+				} catch (ex) {
+					this.showError(ex)
+					return {}
+				}
+			},
+			async loadStations() {
+				try {
+					const info = await stations(this.ip)
+					return info.station_list || []
+				} catch (ex) {
+					this.showError(ex)
+					return []
+				}
+			},
+			clickAddStation() {
+				const _this = this
+				this.isEdit = false
+				this.stationEdit = {
+					stationID: "",
+					name: "",
+					x: 0,
+					y: 0,
+					angle: 0,
+				}
+				this.opStationType = "edit_name"
+				uni.setNavigationBarTitle({
+					title: "娣诲姞绔欑偣"
+				})
+
+			},
+			btnAddTouchStart(e) {
+				this.btnAddInfo.lx = e.touches[0].clientX;
+				this.btnAddInfo.ly = e.touches[0].clientY;
+			},
+			btnAddTouchMove(e) {
+
+				if (this.btnAddInfo.ly < 40) {
+
+					this.btnAddInfo.x += (e.touches[0].clientX - this.btnAddInfo.lx)
+					this.btnAddInfo.lx = e.touches[0].clientX;
+					this.btnAddInfo.ly = e.touches[0].clientY;
+					if (this.btnAddInfo.x < 50 - this.windowWidth) {
+						this.btnAddInfo.x = 50 - this.windowWidth
+					}
+					if (this.btnAddInfo.x > 40) {
+						this.btnAddInfo.x = 40
+					}
+					session.setValue('station_btn_add', this.btnAddInfo)
+					return
+				}
+
+				this.btnAddInfo.x += (e.touches[0].clientX - this.btnAddInfo.lx)
+				this.btnAddInfo.y += (e.touches[0].clientY - this.btnAddInfo.ly)
+				this.btnAddInfo.lx = e.touches[0].clientX;
+				this.btnAddInfo.ly = e.touches[0].clientY;
+
+
+				if (this.btnAddInfo.x < 50 - this.windowWidth) {
+					this.btnAddInfo.x = 50 - this.windowWidth
+				}
+				if (this.btnAddInfo.x > 40) {
+					this.btnAddInfo.x = 40
+				}
+				if (this.btnAddInfo.y > 80) {
+					this.btnAddInfo.y = 80
+				}
+
+
+
+				session.setValue('station_btn_add', this.btnAddInfo)
+			},
+			onTouchStartStation(item) {
+				const _this = this
+				let now = new Date()
+				//console.log(`${now.getMinutes()}:${now.getSeconds()}:${now.getMilliseconds()}`)
+				Object.assign(this.stationEdit, item)
+
+				const angle = this.getStantardAngle(this.stationEdit.angle * 180 / 3.14)
+				this.angleSvg = `/static/images/angle${angle}.svg`
+				this.opStationType = ""
+				now = new Date()
+				//console.log(`${now.getMinutes()}:${now.getSeconds()}:${now.getMilliseconds()}`)
+				this.pressStationTimer = setTimeout(function() {
+					this.isEdit = true
+					let now = new Date()
+					//console.log(`${now.getMinutes()}:${now.getSeconds()}:${now.getMilliseconds()}`)
+					_this.$refs.refPopupOperateStation.open("bottom")
+				}, 1500)
+			},
+			onTouchCancelStation() {
+				clearTimeout(this.pressStationTimer);
+				this.pressStationTimer = null;
+			},
+			clickDelStation(item) {
+				showModal("纭鍒犻櫎绔欑偣", "璀﹀憡").then((res) => {
+					if (res) {
+						this.deleteStation(item)
+					}
+				})
+			},
+
+			async deleteStation(item) {
+				try {
+					await delStation(this.ip, [item.stationID])
+					const list = this.stationList
+					const index = list.findIndex((a) => {
+						return a.stationID == item.stationID
+					})
+					if (index < 0)
+						return
+					list.splice(index, 1)
+					this.stationList = [...list]
+					this.stationEdit = {
+						stationID: "",
+						name: "",
+						x: 0,
+						y: 0,
+						angle: 0
+					}
+
+				} catch (ex) {
+					this.showError(ex)
+				}
+
+			},
+			clickStationDelete() {
+				const _this = this
+				showModal("纭鍒犻櫎绔欑偣", "璀﹀憡").then((res) => {
+					if (res) {
+						_this.deleteStation(this.stationEdit)
+						_this.$refs.refPopupOperateStation.close()
+					} else {
+
+					}
+				})
+			},
+			clickStationPostion() {
+				this.isEdit = true
+
+				this.opStationType = "edit_pos"
+				uni.setNavigationBarTitle({
+					title: "璋冩暣绔欑偣浣嶇疆鍜屾湞鍚�
+				})
+				this.$refs.refPopupOperateStation.close()
+			},
+			clickStationRename() {
+				this.isEdit = true
+				this.opStationType = "edit_name"
+				uni.setNavigationBarTitle({
+					title: "绔欑偣閲嶅懡鍚�
+				})
+				this.$refs.refPopupOperateStation.close()
+			},
+
+			async stationAdd(item) {
+				try {
+					await addStation(this.ip, item)
+					await updateStation(this.ip, item)
+					this.stationList.push({
+						stationID: item.stationID,
+						name: item.name,
+						angle: item.angle,
+						x: item.x,
+						y: item.y
+					})
+
+
+				} catch (ex) {
+					this.showError(ex)
+				}
+			},
+			async stationUpdate(item) {
+				try {
+					await updateStation(this.ip, item)
+					const curIndex = this.stationList.findIndex((a) => a.stationID == item.stationID)
+					if (curIndex > -1) {
+						const station = this.stationList[curIndex]
+						station.name = item.name
+						station.angle = item.angle
+						station.x = item.x
+						station.y = item.y
+					}
+
+				} catch (ex) {
+					this.showError(ex)
+				}
+			},
+
+			clickNameCancel() {
+				if (this.onlyAdd) {
+					uni.navigateBack({
+						delta: 1, //杩斿洖灞傛暟锛�鍒欎笂涓婇〉
+					})
+					return
+				}
+				if (this.isEdit) {
+					this.opStationType = ""
+					uni.setNavigationBarTitle({
+						title: "绔欑偣鍒楄〃"
+					})
+					this.$refs.refPopupOperateStation.open("bottom")
+				} else {
+					this.opStationType = ""
+				}
+			},
+			async clickNameOK() {
+				try {
+					const name = this.stationEdit.name.trim()
+					if (!name) {
+						showToast("绔欑偣鍚嶇О杩樻湭杈撳叆")
+						return
+					}
+					if (this.isEdit) {
+						this.stationEdit.name = name
+						await this.stationUpdate(this.stationEdit)
+						this.opStationType = ""
+						uni.setNavigationBarTitle({
+							title: "绔欑偣鍒楄〃"
+						})
+						this.$refs.refPopupOperateStation.open("bottom")
+					} else {
+						this.stationEdit = {
+							stationID: this.getMaxStationNo + 1,
+							name: name,
+							x: 0,
+							y: 0,
+							angle: 0,
+						}
+						this.opStationType = "edit_pos"
+					}
+
+				} catch (ex) {
+					this.showError(ex)
+				}
+
+			},
+			async clickPosOK() {
+				try {
+					if (this.onlyAdd) {
+						await this.stationAdd(this.stationEdit)
+						this.opStationType = ""
+						const eventChannel = this.getOpenerEventChannel();
+						eventChannel.emit('add', this.stationEdit);
+						uni.navigateBack({
+							delta: 1, //杩斿洖灞傛暟锛�鍒欎笂涓婇〉
+						})
+						return
+					}
+					if (this.isEdit) {
+						await this.stationUpdate(this.stationEdit)
+						this.opStationType = ""
+						uni.setNavigationBarTitle({
+							title: "绔欑偣鍒楄〃"
+						})
+						this.$refs.refPopupOperateStation.open("bottom")
+					} else {
+						await this.stationAdd(this.stationEdit)
+						this.opStationType = ""
+
+					}
+				} catch (ex) {
+
+					this.showError(ex)
+				}
+			},
+			clickClearName() {
+				this.stationEdit.name = ""
+				this.showClearName = false
+			},
+			onInputName(event) {
+				this.stationEdit.name = event.detail.value;
+				if (this.stationEdit.name)
+					this.showClearName = true
+				else
+					this.showClearName = false
+			},
+			onInputX(event) {
+				const strictRegex = /^[-+]?(\d+\.?\d*|\.\d+)$/;
+				let num = event.detail.value
+				if (!strictRegex.test(num)) {
+					showToast("杈撳叆鍐呭鍙兘鍖呭惈鏁板瓧銆佹璐熷彿鍜屽皬鏁扮偣")
+					return
+				} else {
+					if (Math.round(Number(num)) === Number(num)) {
+						if (!Number.isSafeInteger(Number(num))) {
+							showToast("杈撳叆鏁板瓧瓒呭嚭鏁板�瀹夊叏鑼冨洿")
+						}
+					} else {
+						if (!Number.isSafeInteger(Math.round(Number(num)))) {
+							showToast("杈撳叆鏁板瓧瓒呭嚭鏁板�瀹夊叏鑼冨洿")
+						}
+					}
+				}
+				this.stationEdit.x = event.detail.value
+
+			},
+			onInputY(event) {
+				const strictRegex = /^[-+]?(\d+\.?\d*|\.\d+)$/;
+				let num = event.detail.value
+				if (!strictRegex.test(num)) {
+					showToast("杈撳叆鍐呭鍙兘鍖呭惈鏁板瓧銆佹璐熷彿鍜屽皬鏁扮偣")
+				} else {
+					if (Math.round(Number(num)) === Number(num)) {
+						if (!Number.isSafeInteger(Number(num))) {
+							showToast("杈撳叆鏁板瓧瓒呭嚭鏁板�瀹夊叏鑼冨洿")
+						}
+					} else {
+						if (!Number.isSafeInteger(Math.round(Number(num)))) {
+							showToast("杈撳叆鏁板瓧瓒呭嚭鏁板�瀹夊叏鑼冨洿")
+						}
+					}
+
+				}
+				this.stationEdit.y = event.detail.value
+
+			},
+			getStantardAngle(angle) {
+				let resAngle = 0
+				if (angle < -157.5) {
+					resAngle = 180
+				} else if (angle < -112.5) {
+					resAngle = -135
+				} else if (angle < -67.5) {
+					resAngle = -90
+				} else if (angle < -22.5) {
+					resAngle = -45
+				} else if (angle < 22.5) {
+					resAngle = 0
+				} else if (angle < 67.5) {
+					resAngle = 45
+				} else if (angle < 112.5) {
+					resAngle = 90
+				} else if (angle < 157.5) {
+					resAngle = 135
+				} else if (angle <= 180) {
+					resAngle = 180
+				} else {
+					resAngle = 0
+				}
+				return resAngle
+
+			},
+
+			touchAngleChange(e) {
+				let angle = 0
+
+				const ptX = e.touches[0].clientX
+
+				const offX = ptX // ptX - e.target.offsetLeft
+				const offW = 300 / 16
+				const centerPt = this.windowWidth / 2
+				if (offX < centerPt - 8 * offW) {
+					return
+				} else if (offX < centerPt - 7 * offW) {
+					angle = 180
+				} else if (offX < centerPt - 5 * offW) {
+					angle = -135
+				} else if (offX < centerPt - 3 * offW) {
+					angle = -90
+				} else if (offX <= centerPt - offW) {
+					angle = -45
+				} else if (offX < centerPt + offW) {
+					angle = 0
+				} else if (offX < centerPt + 3 * offW) {
+					angle = 45
+				} else if (offX < centerPt + 5 * offW) {
+					angle = 90
+				} else if (offX < centerPt + 7 * offW) {
+					angle = 135
+				} else if (offX <= centerPt + 8 * offW) {
+					angle = 180
+				} else {
+					return
+				}
+				this.stationEdit.angle = angle * 3.14 / 180
+
+				this.angleSvg = `/static/images/angle${angle}.svg`
+
+			},
+			handleAngleTouchStart(e) {
+				// console.log("handleAngleTouchStart", e)
+				this.touchAngleChange(e)
+
+			},
+			handleAngleTouchMove(e) {
+				// console.log("handleAngleTouchMove", e)
+				this.touchAngleChange(e)
+			},
+
+			async clickPositionStation() {
+				try {
+					const infoAgv = await this.loadAgvState()
+					this.stationEdit.x = infoAgv.x
+					this.stationEdit.y = infoAgv.y
+
+					const angle = this.getStantardAngle(infoAgv.angle * 180 / 3.14)
+					this.angleSvg = `/static/images/angle${angle}.svg`
+					this.stationEdit.angle = angle * 3.14 / 180
+				} catch (ex) {
+					this.showError(ex)
+				}
+			},
+			showError(ex) {
+				let exStr = JSON.stringify(ex)
+				if (exStr == "{}")
+					exStr = ex
+				let tip = typeof ex.msg == "string" ? ex.msg : exStr
+				showModal(tip, "閿欒", false)
+			},
+
+
+		}
+	}
+</script>
+
+<style lang="scss">
+	.pages-station {
+		display: flex;
+		width: 750rpx;
+		height: 100vh;
+		position: relative;
+
+		.view-content {
+			position: absolute;
+			top: 0;
+			left: 0;
+			right: 0;
+			bottom: 0;
+			display: flex;
+			flex-direction: column;
+
+			.position-add {
+				position: fixed;
+				right: 10px;
+				bottom: 40px;
+			}
+		}
+
+		.map-content {
+			width: 100%;
+			display: flex;
+			flex: 1;
+			position: relative;
+
+			.content {
+				overflow: auto;
+				position: absolute;
+				left: 0;
+				right: 0;
+				bottom: 0;
+				top: 0;
+
+				.fabric {
+					width: 100%;
+					height: 100%;
+					background-color: #fff;
+				}
+			}
+
+			.position-site {
+				display: flex;
+				position: absolute;
+				margin: 2rpx;
+				right: 40rpx;
+				bottom: 500rpx;
+
+				.button {
+					font-size: 32rpx;
+
+					.ico {
+						margin-right: 8rpx;
+					}
+
+				}
+
+
+
+			}
+
+
+
+		}
+
+		.list-content {
+			display: flex;
+			width: 100%;
+			padding: 20rpx;
+			flex: 1;
+			flex-direction: column;
+			overflow-y: auto;
+			overflow-x: hidden;
+
+			.list {
+				border-radius: 10px;
+				background-color: #fff;
+
+				.list-item {
+
+					padding: 10rpx 0;
+
+
+					.item-title {
+						font-size: 32rpx;
+						padding: 10rpx 20rpx;
+					}
+
+
+					.item-text {
+						font-size: 28rpx;
+						color: #888;
+						padding: 10rpx 20rpx;
+					}
+				}
+
+				.border-top {
+					border-top: 1px solid #f5f5f5;
+				}
+
+				.selected {
+					background-color: #eee;
+				}
+
+				.btn-del {
+					margin: 0 10rpx;
+					display: flex;
+					padding: 0 10rpx;
+					background-color: #FF4D4F;
+					font-weight: 700;
+					color: #fff;
+					justify-content: center;
+					align-items: center;
+				}
+
+			}
+		}
+
+		.list-no-content {
+			margin-top: 50px;
+			padding: 20rpx 40rpx;
+			align-items: center;
+			text-align: center;
+			display: flex;
+			flex-direction: column;
+			font-size: 30rpx;
+			font-weight: 400;
+
+			.img {
+				width: 212rpx;
+				height: 212rpx;
+				color: #ddd;
+			}
+
+			.space {
+				margin-top: 20rpx;
+			}
+
+		}
+
+		.bottom {
+			position: fixed;
+			left: 50rpx;
+			right: 50rpx;
+			bottom: 20rpx;
+			display: flex;
+
+			.bottom-content {
+				display: flex;
+				flex-direction: column;
+				width: 100%;
+				// justify-content: center;
+				// align-items: center;
+				padding: 0 10rpx;
+				padding-bottom: 10rpx;
+				background-color: #fff;
+				border-radius: 10rpx;
+
+
+				.title {
+					font-size: 40rpx;
+					margin-bottom: 10rpx;
+				}
+
+				.tip {
+					color: #888;
+					margin: 10rpx;
+					text-align: left;
+				}
+
+				.row-group {
+					display: flex;
+					flex-direction: row;
+					margin: 10rpx 0;
+
+				}
+
+				.angle-group {
+					padding: 10rpx;
+					display: flex;
+					flex-direction: column;
+					justify-content: center;
+					align-items: center;
+
+					.img-angle {
+						width: 128rpx;
+						height: 42rpx;
+						margin-bottom: 10rpx;
+					}
+
+					.img-angle-pos {
+						width: 300px;
+						height: 64rpx;
+						margin: 10rpx;
+					}
+
+				}
+
+				.coordinate {
+					flex: 1;
+					display: flex;
+					flex-direction: row;
+					align-items: center;
+					// .name{
+					// 	padding: 10rpx 0;
+
+					// }
+				}
+
+				.number-input {
+					flex: 1;
+					background-color: #fff;
+					padding: 0 10rpx;
+					border-radius: 8rpx;
+					color: #1890FF;
+				}
+
+
+				.name-input {
+					width: calc(100% - 20rpx);
+					margin-bottom: 10rpx;
+					background-color: #fff;
+					padding: 10rpx;
+					border-radius: 8rpx;
+					display: flex;
+					flex-direction: row;
+					color: #1890FF;
+
+					input {
+						flex: 1;
+					}
+				}
+			}
+
+			.img-button-group {
+				display: flex;
+				//width: 100%;
+				flex-direction: row;
+				border-radius: 10px;
+				border: 1px solid #fff;
+				font-size: 30rpx !important;
+				justify-content: space-around;
+
+				.button {
+					margin: 10rpx 20rpx;
+
+					height: 144rpx !important;
+					border: 0;
+					display: flex;
+					flex-direction: column;
+					background-color: #00000000;
+
+					.img {
+						margin: auto;
+						width: 72rpx;
+						height: 72rpx;
+
+					}
+
+					.ico {
+						margin: auto;
+						font-size: 72rpx;
+						color: #1890FF;
+					}
+
+					.text {
+						margin: auto;
+
+					}
+				}
+
+			}
+
+
+			.text-button-group {
+				display: flex;
+				width: 100%;
+				justify-content: center;
+				align-items: center;
+				flex-direction: column;
+				font-size: 30rpx !important;
+
+				.button {
+					margin: auto;
+					margin-top: 20rpx;
+					width: calc(100% - 10rpx);
+				}
+
+				.am-button {
+					border-radius: 30px;
+				}
+
+				.am-button-ghost {
+					border: 1px solid #1677ff !important;
+
+				}
+			}
+
+
+		}
+
+		.popup-content {
+			display: flex;
+			justify-content: center;
+			flex-direction: column;
+			background-color: transparent;
+		}
+
+		.popup-content-btn {
+			margin-bottom: 20rpx;
+			margin-left: 50rpx;
+			width: 600rpx;
+			background-color: #fff;
+			border-radius: 5px;
+			display: flex;
+
+			.img-button-group {
+				display: flex;
+				//width: 100%;
+				flex-direction: row;
+				border-radius: 10px;
+				border: 1px solid #fff;
+				font-size: 30rpx !important;
+
+				margin: auto;
+
+				.button {
+					margin: 10rpx 20rpx;
+
+					height: 144rpx !important;
+					border: 0;
+					display: flex;
+					flex-direction: column;
+					background-color: #00000000;
+
+					.img {
+						margin: auto;
+						width: 72rpx;
+						height: 72rpx;
+
+					}
+
+					.ico {
+						margin: auto;
+						font-size: 72rpx;
+						color: #1890FF;
+					}
+
+					.text {
+						margin: auto;
+
+					}
+				}
+
+			}
+
+		}
+
+
+	}
+</style>
\ No newline at end of file
diff --git a/pages/task/add.vue b/pages/task/add.vue
new file mode 100644
index 0000000..4214475
--- /dev/null
+++ b/pages/task/add.vue
@@ -0,0 +1,602 @@
+<template>
+	<view class="pages-task-add">
+		<uni-nav-bar :fixed="true" status-bar right-text="" left-text="" leftWidth="72rpx" rightWidth="72rpx"
+			:title="navigationBarTitle">
+			<view class="uni-navbar-container-inner">
+				<text class="uni-nav-bar-text">{{navigationBarTitle }}</text>
+			</view>
+			<template v-slot:right>
+				<view class="uni-navbar-btn-text">
+					<a @click="clickSave" class="uni-nav-bar-right-text">
+						淇濆瓨
+					</a>
+				</view>
+			</template>
+			<template v-slot:left>
+				<view class="uni-navbar-btn-text">
+					<a @click="clickCancel" class="uni-nav-bar-left-text">
+						鍙栨秷
+					</a>
+				</view>
+
+			</template>
+		</uni-nav-bar>
+		<view class="content">
+			<view class="header">浠诲姟灞炴�</view>
+			<view class="group">
+				<view class="item">
+					<view>鍚嶇О锛�/view>
+					<input class="right-input" placeholder="杈撳叆浠诲姟鍚嶇О" v-model="info.taskGroupName" />
+				</view>
+				<view class="item">
+					<view>灞炴�锛�/view>
+					<view class="right" v-if="info.tasktype > 0">{{info.tasktype ==1 ? '鍥哄畾':'涓存椂'}}</view>
+					<view class="right" v-else>閫夋嫨灞炴�</view>
+					<a @click="clickType">
+						<uni-icons class="icon" type="right" size="20"></uni-icons>
+					</a>
+				</view>
+				<view class="item" v-if="info.tasktype == 1">
+					<view>寰幆娆℃暟锛�/view>
+					<input class="right-input" type="number" :value="info.cycleTime" :maxlength="4"
+						@input="onInputCycleTime" />
+				</view>
+				<view class="item">
+					<view>鎸夐挳鍙凤細</view>
+					<view class="right">{{info.taskButton ?info.taskButton:""}}</view>
+					<a @click="clickTaskButton">
+						<uni-icons class="icon" type="right" size="20"></uni-icons>
+					</a>
+				</view>
+			</view>
+			<view class="header">浠诲姟璺嚎</view>
+			<view class="group">
+
+				<uni-swipe-action class="list">
+					<uni-swipe-action-item class="list-item" v-for="(item,index) in pathwayList" :key="index"
+						:auto-close="true">
+						<view class="item">
+							<view>鐩爣鐐箋{index+1}}锛�/view>
+							<view class="right"></view>
+							<a @click.stop="(e)=>{ this.clickPathwayPoint(e,index,'stationID')}">
+								{{item.stationID ?stationName(item.stationID) : "鐩爣鐐�}}
+
+							</a>
+							<a @click.stop="(e)=>{ clickPathwayPoint(e,index,'actionType')}">
+								{{actionTypeText(item.actionType)}}
+							</a>
+							<view v-if="item.actionType === 3">
+								<a @click.stop="()=>{item.wait = 0}" v-if="item.wait===undefined">
+									绛夊緟鏃堕棿
+								</a>
+								<view v-else class="time"> <input class="input" type="number" v-model="item.wait"
+										:maxlength="4" />绉�/view>
+							</view>
+						</view>
+						<template v-slot:right>
+							<view class="btn-del" @click="clickDelPathWay(index)">鍒犻櫎</view>
+						</template>
+					</uni-swipe-action-item>
+				</uni-swipe-action>
+				<view class="item">
+					<a-button class="button" @click="clickAddPathway">+ 娣诲姞鐩爣鐐�+					</a-button>
+				</view>
+			</view>
+		</view>
+		<view>
+			<uni-popup ref="refPopupMenu" background-color="transparent" maskBackgroundColor="rgba(0, 0, 0, 0.2)">
+				<view class="popup-content" @click="closeMenu">
+					<picker-view class="popup-content-view"
+						:style="{'margin-top':pickerView.top +'px','margin-right': pickerView.right +'px'}"
+						:indicator-style="indicatorStyle" :value="pickerView.value" @change="bindPickerChange">
+						<picker-view-column>
+							<view class="item" v-for="(item,index) in pickerView.list" :key="index">{{item.name}}</view>
+						</picker-view-column>
+
+					</picker-view>
+				</view>
+			</uni-popup>
+		</view>
+	</view>
+</template>
+<script>
+	import {
+		showToast,
+		showModal
+	} from "@/comm/utils.js"
+	import {
+		Button
+	} from 'antd-mobile-vue-next'
+	import {
+		stations,
+		addTask,
+		delTask,
+
+	} from "@/api/vehicle.js"
+	import {
+		v4 as uuidv4
+	} from 'uuid';
+	export default {
+		name: "PagesTaskAdd",
+		components: {
+			'a-button': Button
+		},
+		data() {
+			return {
+				indicatorStyle: `height: 75rpx;`,
+				ip: '',
+				navigationBarTitle: '鏂板浠诲姟',
+				info: {
+					taskGroupName: "",
+					cycleTime: 1,
+					taskButton: 0,
+				},
+				pathwayList: [{}],
+				pickerView: {
+					type: "",
+					list: [],
+					value: []
+				},
+				stationList: [],
+				windowSize: {},
+
+
+				actionList: [{
+					name: "瀵艰埅",
+					type: 1,
+				}, {
+					name: "鍙栬揣",
+					type: 2,
+				}, {
+					name: "鍗歌揣",
+					type: 3,
+				}, {
+					name: "浜哄伐",
+					type: 4,
+				}]
+			}
+		},
+		computed: {
+
+		},
+
+		onLoad(option) {
+			const _this = this
+			this.navigationBarTitle = option.title || "鏂板浠诲姟"
+			this.ip = option.ip || ""
+			uni.getSystemInfo({
+				success(e) {
+					_this.windowSize = {
+						width: e.windowWidth,
+						height: e.windowHeight - (e.statusBarHeight || 0)
+					}
+				},
+
+			})
+			this.loadStations()
+		},
+		methods: {
+			setData(obj) {
+				let that = this;
+				let keys = [];
+				let val, data;
+
+				Object.keys(obj).forEach(function(key) {
+					keys = key.split(".");
+					val = obj[key];
+					data = that.$data;
+					keys.forEach(function(key2, index) {
+						if (index + 1 == keys.length) {
+							that.$set(data, key2, val);
+						} else {
+							if (!data[key2]) {
+								that.$set(data, key2, {});
+							}
+						}
+						data = data[key2];
+					});
+				});
+			},
+			async loadStations() {
+				try {
+					const info = await stations(this.ip)
+					this.stationList = info.station_list || []
+				} catch (ex) {
+					this.showError(ex)
+				}
+			},
+			async clickSave() {
+				try {
+					const name = this.info.taskGroupName.trim()
+					if (!name) {
+						showToast("鏈緭鍏ヤ换鍔″悕绉帮紒")
+						return
+					}
+					if (!this.info.tasktype) {
+						showToast("鏈�鎷╀换鍔″睘鎬э紒")
+						return
+					}
+					const taskList = []
+					const task = {
+						taskGroupID: uuidv4(),
+						taskGroupName: name,
+						cycleTime: parseInt(this.info.cycleTime),
+						taskButton: this.info.taskButton,
+						tasktype: this.info.tasktype,
+						taskList: []
+					}
+					const taskStartTimeStamp = `${new Date().getTime()}`
+
+					this.pathwayList.forEach((item) => {
+						if (item.stationID) {
+							task.taskList.push({
+								stationID: item.stationID,
+								actionType: item.actionType || 0,
+								wait: parseInt(item.wait) || 0,
+								taskStartTimeStamp,
+							})
+							const dest = this.stationList.find((a) => a.stationID == item.stationID)
+							taskList.push({
+								stationID: item.stationID,
+								actionType: item.actionType || 0,
+								dest: dest || {},
+								taskStartTimeStamp,
+
+							})
+						}
+					})
+					if (taskList.length == 0) {
+						showToast("鐩爣鐐规湭閫夋嫨绔欏彴锛�)
+						return
+					}
+					await addTask(this.ip, task)
+					task.taskList = taskList
+					const eventChannel = this.getOpenerEventChannel();
+					eventChannel.emit('add_task', task);
+					uni.navigateBack({
+						delta: 1, //杩斿洖灞傛暟锛�鍒欎笂涓婇〉
+					})
+				} catch (ex) {
+					this.showError(ex)
+				}
+			},
+			clickCancel() {
+				let flag = false
+				if (this.info.taskGroupName.trim()) {
+					flag = true
+				} else if (this.info.taskButtonn) {
+					flag = true
+				} else if (this.info.tasktype) {
+					flag = true
+				} else if (this.info.cycleTime > 1) {
+					flag = true
+				} else if (this.pathwayList.length > 0) {
+					this.pathwayList.forEach((ele) => {
+						if (ele.stationID)
+							flag = true
+					})
+
+				}
+				if (flag) {
+
+					showModal(`褰撳墠缂栬緫鐨勫唴瀹瑰皢涓嶄細琚繚瀛榒, "纭畾瑕侀�鍑虹紪杈戝悧?").then((res) => {
+						if (res) {
+							uni.navigateBack({
+								delta: 1, //杩斿洖灞傛暟锛�鍒欎笂涓婇〉
+							})
+						}
+					})
+				} else {
+					uni.navigateBack({
+						delta: 1, //杩斿洖灞傛暟锛�鍒欎笂涓婇〉
+					})
+				}
+
+
+			},
+			stationLst(id) {
+				const list = []
+
+				const list3 = [...this.pathwayList]
+
+				this.stationList.forEach((item) => {
+					let curIndex
+					if (id) {
+						if (item.stationID != id) {
+							curIndex = list3.findIndex((a) => a.stationID == item.stationID)
+						} else {
+							curIndex = -1
+						}
+					} else {
+						curIndex = list3.findIndex((a) => a.stationID == item.stationID)
+					}
+					if (curIndex < 0) {
+						list.push(item)
+					}
+				})
+				return list
+			},
+			stationName(id) {
+				const curIndex = this.stationList.findIndex((a) => a.stationID == id)
+				if (curIndex > -1) {
+					return this.stationList[curIndex].name
+				}
+				return ""
+
+			},
+			actionTypeText(type) {
+				if (type > 0) {
+					const curIndex = this.actionList.findIndex((a) => a.type == type)
+					if (curIndex > -1) {
+						return this.actionList[curIndex].name
+					} else {
+						return "鎿嶄綔"
+					}
+				} else {
+					return "鎿嶄綔"
+				}
+			},
+
+			clickPathwayPoint(e, index, type) {
+				let top = e.target.offsetTop + 30
+				if (this.windowSize.height > 0) {
+					if (e.detail.y + 180 > this.windowSize.height) {
+						top = e.detail.y - 180
+					}
+				}
+				let right = 0
+				const item = this.pathwayList[index]
+				if (type == "stationID") {
+
+					const list = this.stationLst(item.stationID)
+					let index2 = 0
+					if (list.length > 0) {
+						if (item.stationID) {
+							index2 = list.findIndex((a) => a.stationID == item.stationID)
+							if (index2 < 0) {
+								item.stationID = list[0].stationID
+								index2 = 0
+							}
+
+						} else {
+							item.stationID = list[0].stationID
+							index2 = 0
+						}
+					}
+					if (this.windowSize.width > 0) {
+						right = this.windowSize.width - e.detail.x
+					}
+					this.pickerView = {
+						type: "pathwayPoint",
+						list,
+						value: [index2],
+						index,
+						top,
+						right,
+					}
+					this.$refs.refPopupMenu.open("right")
+				} else if (type == "actionType") {
+					if (this.windowSize.width > 0) {
+						right = this.windowSize.width - e.detail.x
+					}
+
+					let index2 = 0
+					if (item.actionType)
+						index2 = this.actionList.findIndex((a) => a.type == item.actionType)
+					if (index2 < 0)
+						index2 = 0
+					item.actionType = this.actionList[index2].type
+					this.pickerView = {
+						type: "pathwayPointActionType",
+						list: this.actionList,
+						value: [index2],
+						index,
+						top,
+						right,
+					}
+					this.$refs.refPopupMenu.open("right")
+				}
+
+			},
+
+
+			clickType(e) {
+				if (!this.info.tasktype) {
+					this.info.tasktype = 1
+				}
+				this.pickerView = {
+					type: "type",
+					list: [{
+						name: "鍥哄畾"
+					}, {
+						name: "涓存椂"
+					}],
+					value: [this.info.tasktype - 1],
+					top: e.target.offsetTop + 30,
+					right: 0,
+				}
+				this.$refs.refPopupMenu.open("right")
+
+			},
+			bindPickerChange(e) {
+				const val = e.detail.value
+				const val2 = val[0]
+				if (this.pickerView.type == "type") {
+					this.info.tasktype = val2 + 1
+				} else if (this.pickerView.type == "pathwayPoint") {
+					this.pathwayList[this.pickerView.index].stationID = this.pickerView.list[val2].stationID
+				} else if (this.pickerView.type == "pathwayPointActionType") {
+					this.pathwayList[this.pickerView.index].actionType = this.pickerView.list[val2].type
+				} else if (this.pickerView.type == "taskButton") {
+					this.info.taskButton = val2 + 1
+				}
+			},
+			clickAddPathway() {
+				this.pathwayList.push({})
+			},
+			clickDelPathWay(index) {
+				if (this.pathwayList.length > 1) {
+					this.pathwayList.splice(index, 1)
+				} else {
+					showToast("蹇呴』鏈変竴涓洰鏍囩偣")
+				}
+			},
+			onInputCycleTime(event) {
+				this.info.cycleTime = event.detail.value;
+			},
+			clickTaskButton(e) {
+				const list = []
+				for (let i = 1; i < 100; i++) {
+					list.push({
+						name: i
+					})
+				}
+				if (!this.info.taskButton) {
+					this.info.taskButton = 1
+				}
+				this.pickerView = {
+					type: "taskButton",
+					list,
+					value: [this.info.taskButton - 1],
+					top: e.target.offsetTop + 30,
+					right: 0,
+				}
+
+				this.$refs.refPopupMenu.open("right")
+			},
+			closeMenu() {
+				this.$refs.refPopupMenu.close()
+			},
+			showError(ex) {
+				let exStr = JSON.stringify(ex)
+				if (exStr == "{}")
+					exStr = ex
+				let tip = typeof ex.msg == "string" ? ex.msg : exStr
+				showModal(tip, "閿欒", false)
+			},
+
+		}
+	}
+</script>
+
+<style lang="scss">
+	.pages-task-add {
+		display: flex;
+		width: 750rpx;
+		height: 100vh;
+		flex-direction: column;
+		background-color: #F8F8F8;
+
+		.content {
+			width: 750rpx;
+			display: flex;
+			flex-direction: column;
+			flex: 1;
+		}
+
+		.header {
+			margin: 10rpx 30rpx;
+		}
+
+		.group {
+			width: calc(100% - 60rpx);
+			// border: 1px solid #ccc;
+			border-radius: 20rpx;
+			margin: 10rpx 20rpx;
+			padding: 0 10rpx;
+			display: flex;
+			flex-direction: column;
+			background-color: #fff;
+			font-size: 30rpx;
+
+			.item {
+				width: calc(100% - 20rpx);
+				padding: 20rpx 10rpx;
+				display: flex;
+				flex-direction: row;
+
+				.right {
+					flex: 1;
+					text-align: right;
+					color: #888;
+					padding-right: 5px;
+
+				}
+
+
+
+				.right-input {
+					text-align: right;
+					flex: 1;
+				}
+
+				.text {
+					flex: 1;
+					color: #888;
+
+				}
+
+				.icon {
+					color: #888;
+				}
+
+				a {
+					margin-left: 20rpx;
+				}
+
+				.time {
+					display: flex;
+					flex-direction: row;
+					margin-left: 20rpx;
+
+					.input {
+						width: 75rpx;
+					}
+				}
+			}
+
+			.btn-del {
+				display: flex;
+				padding: 0 10rpx;
+				background-color: #FF4D4F;
+				font-weight: 700;
+				color: #fff;
+				justify-content: center;
+				align-items: center;
+			}
+
+			.line {
+				border-bottom: 2rpx solid #ccc;
+			}
+		}
+
+		.button {
+			margin: auto;
+			width: 700rpx;
+			color: #1890FF;
+		}
+
+		.popup-content {
+			display: flex;
+			justify-content: center;
+			flex-direction: column;
+			background-color: transparent;
+		}
+
+		.popup-content-view {
+			width: 150px;
+			height: 150px;
+			border-radius: 10rpx;
+			padding: 10rpx 20rpx;
+			background-color: #fff;
+
+			.item {
+				line-height: 75rpx;
+				text-align: center;
+				border: 0;
+
+			}
+		}
+	}
+</style>
\ No newline at end of file
diff --git a/pages/task/index.vue b/pages/task/index.vue
new file mode 100644
index 0000000..00fa805
--- /dev/null
+++ b/pages/task/index.vue
@@ -0,0 +1,155 @@
+<template>
+	<view class="pages-task">
+		<view class="header">
+			<view class="item">
+				<view class="title">{{accumulated_duration}}<text class="text">min</text></view>
+				<view class="text">绱鏃堕暱</view>
+			</view>
+			<view class="item">
+				<view class="title">{{accumulated_mileage}}<text class="text">m</text></view>
+				<view class="text">绱閲岀▼</view>
+			</view>
+			<view class="item">
+				<view class="title">{{cumulative_number}}</view>
+				<view class="text">绱娆℃暟</view>
+			</view>
+		</view>
+		<view class="list">
+			<TaskItemView class="item" v-for="(item,index) in list" :key="index" :taskData="item"
+				@click-item="clickMap">
+
+			</TaskItemView>
+		</view>
+	</view>
+</template>
+
+<script>
+	import {
+		showToast,
+		showModal
+	} from "@/comm/utils.js"
+	import TaskItemView from "./infos/task-item.vue"
+	export default {
+		name: "PagesTask",
+		components: {
+			TaskItemView
+		},
+		data() {
+			return {
+				accumulated_duration: 167991,
+				accumulated_mileage: 7532556,
+				cumulative_number: 6000,
+				list: [{
+					name: "鍦板浘1",
+					date: "5-18",
+					accumulated_duration: 5693,
+					accumulated_mileage: 6421,
+					cumulative_number: 55,
+				}, {
+					name: "鍦板浘2",
+					date: "5-08",
+					accumulated_duration: 888,
+					accumulated_mileage: 642,
+					cumulative_number: 31,
+				}, {
+					name: "鍦板浘3",
+					date: "4-28",
+					accumulated_duration: 998,
+					accumulated_mileage: 2421,
+					cumulative_number: 85,
+				}, {
+					name: "鍦板浘4",
+					date: "4-28",
+					accumulated_duration: 688,
+					accumulated_mileage: 1421,
+					cumulative_number: 65,
+				}]
+			}
+		},
+		computed: {
+
+		},
+
+		methods: {
+			setData(obj) {
+				let that = this;
+				let keys = [];
+				let val, data;
+
+				Object.keys(obj).forEach(function(key) {
+					keys = key.split(".");
+					val = obj[key];
+					data = that.$data;
+					keys.forEach(function(key2, index) {
+						if (index + 1 == keys.length) {
+							that.$set(data, key2, val);
+						} else {
+							if (!data[key2]) {
+								that.$set(data, key2, {});
+							}
+						}
+						data = data[key2];
+					});
+				});
+			},
+			clickMap(item) {
+				uni.navigateTo({
+					url: "/pages/task/map-task"
+				})
+			}
+
+		}
+	}
+</script>
+
+<style lang="scss">
+	.pages-task {
+		display: flex;
+		width: 750rpx;
+		height: 100vh;
+		flex-direction: column;
+
+		.header {
+			width: 100%;
+			padding: 10px;
+			height: 30px;
+			display: flex;
+			flex-direction: row;
+
+			.item {
+				padding: 0 10px;
+				display: flex;
+				width: 100%;
+				flex-direction: column;
+				flex: 1;
+
+				.title {
+					font-size: 20px;
+					font-weight: 700;
+				}
+
+				.text {
+					font-size: 14px;
+					color: #888;
+				}
+			}
+		}
+
+		.list {
+			width: calc(100% - 40px);
+			margin: 10px;
+			padding: 0 10px;
+			display: flex;
+			flex-direction: column;
+			flex: 1;
+			overflow: auto;
+
+			.item {
+				border-bottom: 1px solid #ddd;
+			}
+
+
+		}
+
+	}
+</style>
\ No newline at end of file
diff --git a/pages/task/infos/task-item.vue b/pages/task/infos/task-item.vue
new file mode 100644
index 0000000..0d9e44b
--- /dev/null
+++ b/pages/task/infos/task-item.vue
@@ -0,0 +1,262 @@
+<template>
+	<view class="pages-task-item">
+		<view class="btn-no " :class="taskIsRun?'active':'' ">
+			{{taskData.taskButton}}
+		</view>
+		<view class="content" @click="clickTask">
+			<view class="line">
+				<view class="title"> {{taskData.taskGroupName}}</view>
+			</view>
+			<view class="line">
+				{{taskListDesc}}
+			</view>
+		</view>
+		<view class="action-button" v-if="taskIsRun">
+<!-- 			<button type="primary" v-show="false" :plain="true" class="button" @click.stop="clickRepeatTask">
+				<text class="ico repeat" />
+			</button> -->
+			<button type="primary" :plain="true" class="button" @click.stop="clickSkipTask">
+				<text class="ico skip-next-rounded" />
+			</button>
+			<button type="primary" :plain="true" class="button" @click.stop="clickStopTask">
+				<text class="ico stop" />
+			</button>
+			<!-- 			<button type="primary" v-show="false" :plain="true" class="button" @click.stop="clickPauseTask">
+				<text class="ico pause-rounded" />
+			</button>
+			<button type="primary" v-show="false" :plain="true" class="button" @click.stop="clickPlayTask">
+				<text class="ico play-filled" />
+			</button> -->
+		</view>
+		<view class="action-button" v-else>
+			<button :type=" !taskCanRun ? 'default':'primary'" :plain="true" class="button" :disabled=" !taskCanRun"
+				@click.stop="clickPlayTask">
+				<text class="ico play-filled " :class="taskCanRun ? '':'disabled'" />
+			</button>
+		</view>
+		<!-- <view class="btn-del" :style="{ transform: `translateX(${deleteX || 0}px)` }" @click="clickDelete">
+			鍒犻櫎</view> -->
+
+	</view>
+
+</template>
+
+<script>
+	import {
+		showToast,
+		showModal
+	} from "@/comm/utils.js"
+	import {
+		Button
+	} from 'antd-mobile-vue-next'
+	export default {
+		name: "PagesTaskItem",
+		components: {
+			'a-button': Button
+		},
+		props: {
+			taskData: {
+				type: Object,
+				default () {
+					return {};
+				}
+			},
+			taskStatus: {
+				type: Object,
+				default () {
+					return {};
+				}
+			},
+			deleteX: {
+				type: Number,
+				default () {
+					return 0;
+				}
+			},
+		},
+		data() {
+			return {}
+		},
+		computed: {
+			taskListDesc() {
+				let list = this.taskData.taskList || []
+				list = list.map((a) => a.dest?.name)
+				return list.join("-")
+			},
+			taskIsRun() {
+				if (this.taskStatus?.taskGroupID == this.taskData.taskGroupID) {
+					return true
+				} else {
+					return false
+				}
+			},
+			taskCanRun() {
+				if (this.taskStatus?.taskGroupID) {
+					return false
+				} else {
+					return true
+				}
+			},
+
+		},
+
+		methods: {
+			setData(obj) {
+				let that = this;
+				let keys = [];
+				let val, data;
+
+				Object.keys(obj).forEach(function(key) {
+					keys = key.split(".");
+					val = obj[key];
+					data = that.$data;
+					keys.forEach(function(key2, index) {
+						if (index + 1 == keys.length) {
+							that.$set(data, key2, val);
+						} else {
+							if (!data[key2]) {
+								that.$set(data, key2, {});
+							}
+						}
+						data = data[key2];
+					});
+				});
+			},
+			clickTask() {
+				this.$emit('click-item', this.taskData)
+			},
+			clickPlayTask() {
+				if (this.taskStatus?.taskGroupID)
+					return
+				this.$emit('click-play', this.taskData)
+			},
+
+			clickStopTask() {
+				this.$emit('click-stop', this.taskData)
+			},
+
+			clickSkipTask() {
+				this.$emit('click-skip', this.taskData)
+			},
+
+			clickRepeatTask() {
+				this.$emit('click-repeat', this.taskData)
+			},
+
+			clickPauseTask() {
+				this.$emit('click-pause', this.taskData)
+			},
+
+			clickDelete() {
+				this.$emit('click-delete', this.taskData)
+			},
+
+
+
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.pages-task-item {
+		width: 100%;
+		display: flex;
+		flex-direction: row;
+		position: relative;
+		align-items: center;
+
+		.btn-no {
+			margin: 0 10rpx 0 20rpx;
+			border-radius: 25rpx;
+			background-color: #E6F7FF;
+			color: #1890FF;
+			width: 50rpx;
+			height: 50rpx;
+			line-height:54rpx ;
+			justify-content: center;
+			align-items: center;
+			text-align: center;
+		}
+
+		.active {
+			background-color: #1890FF;
+			color: #fff;
+		}
+
+		.content {
+			flex: 1;
+			padding: 5px;
+
+			.line {
+				padding: 5px 0;
+				width: 100%;
+				display: flex;
+				flex-direction: row;
+
+				.title {
+					font-size: 36rpx;
+					font-weight: 600;
+				}
+
+				.text {
+					padding: 0 10px;
+					font-size: 14px;
+					color: #1ABC9C;
+					flex: 1;
+				}
+
+
+
+			}
+		}
+
+		.action-button {
+			display: flex;
+			flex-direction: row;
+
+			.button {
+				display: flex;
+				margin: 10rpx;
+				border-radius: 50%;
+				//padding: 5rpx !important;
+				width: 60rpx;
+				height: 60rpx;
+				justify-content: center;
+				align-items: center;
+
+				.ico {
+					font-size: 30rpx;
+					color: #1890FF;
+
+				}
+				.disabled{
+					color: gray !important;
+				}
+
+			}
+			.disabled{
+				color: gray;
+			}
+
+
+		}
+
+		.btn-del {
+			position: absolute;
+			right: -80px;
+			top: 0;
+			padding: 0 8px;
+			line-height: 100px;
+			background-color: #CC001A;
+			font-weight: 700;
+			color: #fff;
+			border: none;
+			border-radius: 10px;
+			border-bottom-right-radius: 0px;
+			border-bottom-left-radius: 0px;
+			border-top-left-radius: 0px;
+			transform: translateX(100%);
+			transition: transform 0.3s;
+		}
+	}
+</style>
\ No newline at end of file
diff --git a/pages/task/infos/task-log-item.vue b/pages/task/infos/task-log-item.vue
new file mode 100644
index 0000000..5dba57c
--- /dev/null
+++ b/pages/task/infos/task-log-item.vue
@@ -0,0 +1,168 @@
+<template>
+	<view class="pages-task-log-item vert-line">
+		<view class="btn-no "> {{taskData.taskButton}}
+		</view>
+		<view class="content">
+			<view class="line">
+				<view class="title"> {{taskData.taskGroupName}}</view>
+				<view class="status" :style="{'background-color':taskStatusColor+ '20','color':taskStatusColor}">
+					{{taskStatusText}}
+				</view>
+			</view>
+			<view class="line"><text class="text">{{taskData.startTime}}-{{taskData.endTime}} </text>
+				<text class="text">{{taskData.duration}}min</text>
+				<text class="text">{{taskData.cycleNumber}}娆�/text>
+			</view>
+		</view>
+	</view>
+
+</template>
+
+<script>
+	import {
+		showToast,
+		showModal
+	} from "@/comm/utils.js"
+	export default {
+		name: "PagesTaskLogItem",
+		props: {
+			taskData: {
+				type: Object,
+				default () {
+					return {};
+				}
+			},
+		},
+		data() {
+			return {
+
+			}
+		},
+		computed: {
+			taskStatusText() {
+				let statusText = ""
+				if (this.taskData.status == 1) {
+					statusText = "浠诲姟鎵ц涓�
+				} else if (this.taskData.status == 2) {
+					statusText = "浠诲姟瀹屾垚"
+				} else if (this.taskData.status == 3) {
+					statusText = "浠诲姟鍙栨秷"
+				} else if (this.taskData.status == 4) {
+					statusText = "浠诲姟寮傚父"
+				} else if (this.taskData.status == 5) {
+					statusText = "浠诲姟寮哄埗瀹屾垚"
+				} else {
+					statusText = ""
+				}
+				return statusText
+			},
+			taskStatusColor() {
+				let statusColor = ""
+				if (this.taskData.status == 1) {
+					statusColor = "#0055ff"
+				} else if (this.taskData.status == 2) {
+					statusColor = "#237804"
+				} else if (this.taskData.status == 3) {
+					statusColor = "#787277"
+				} else if (this.taskData.status == 4) {
+					statusColor = "#D4380D"
+				} else if (this.taskData.status == 5) {
+					statusColor = "#55aa00"
+				} else if (this.taskData.status == 5) {
+					statusColor = "#000000"
+				}
+				return statusColor
+			}
+		},
+
+		methods: {
+			setData(obj) {
+				let that = this;
+				let keys = [];
+				let val, data;
+
+				Object.keys(obj).forEach(function(key) {
+					keys = key.split(".");
+					val = obj[key];
+					data = that.$data;
+					keys.forEach(function(key2, index) {
+						if (index + 1 == keys.length) {
+							that.$set(data, key2, val);
+						} else {
+							if (!data[key2]) {
+								that.$set(data, key2, {});
+							}
+						}
+						data = data[key2];
+					});
+				});
+			},
+			clickTask() {
+				this.$emit('click-item', this.taskData)
+			}
+
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.pages-task-log-item {
+		width: 100%;
+		display: flex;
+		flex-direction: row;
+		align-items: center;
+
+		.btn-no {
+			margin: 0 10rpx 0 20rpx;
+			border-radius: 25rpx;
+			background-color: #E6F7FF;
+			color: #1890FF;
+			width: 50rpx;
+			height: 50rpx;
+			line-height: 54rpx;
+			justify-content: center;
+			align-items: center;
+			text-align: center;
+		}
+
+
+		.content {
+			flex: 1;
+
+			.line {
+				padding: 10rpx 0;
+				width: 100%;
+				display: flex;
+				flex-direction: row;
+				flex-wrap: wrap;
+
+				.title {
+					font-size: 36rpx;
+					font-weight: 600;
+				}
+
+				.status {
+					margin-left: 10rpx;
+					padding: 4rpx;
+				}
+
+				.text {
+					padding: 0 20rpx;
+					font-size: 30rpx;
+					color: #888;
+				}
+
+				.date {
+					padding: 0 20rpx;
+					font-size: 30rpx;
+				}
+
+				.vert-line {
+					border-right: 2rpx solid #ccc;
+				}
+			}
+		}
+
+
+	}
+</style>
\ No newline at end of file
diff --git a/pages/task/list.vue b/pages/task/list.vue
new file mode 100644
index 0000000..0f2d992
--- /dev/null
+++ b/pages/task/list.vue
@@ -0,0 +1,445 @@
+<template>
+	<view class="pages-task-list">
+		<view class="list-content" v-if="list.length > 0">
+			<view class="list-header" v-if="fixedList.length > 0">鍥哄畾浠诲姟</view>
+			<uni-swipe-action class="list">
+				<uni-swipe-action-item :class="index== 0 ?'':'list-item'" v-for="(item,index) in fixedList" :key="index"
+					:auto-close="true" :disabled="taskStatus.taskGroupID == item.taskGroupID">
+					<TaskItemView :taskData="item" :taskStatus="taskStatus" @click-item="clickEditTask"
+						@click-play="clickPlayTask" @click-pause="clickPauseTask" @click-stop="clickStopTask"
+						@click-skip="clickSkipTask" @click-repeat="clickRepeatTask">
+					</TaskItemView>
+					<template v-slot:right>
+						<view class="btn-del" @click="clickDelSetTask(item)">鍒犻櫎</view>
+					</template>
+				</uni-swipe-action-item>
+			</uni-swipe-action>
+			<view class="list-header" v-if="tempList.length > 0">涓存椂浠诲姟</view>
+			<uni-swipe-action class="list">
+				<uni-swipe-action-item :class="index== 0 ?'':'list-item'" v-for="(item,index) in tempList" :key="index"
+					:auto-close="true" :disabled="taskStatus.taskGroupID == item.taskGroupID">
+					<TaskItemView :taskData="item" :taskStatus="taskStatus" @click-item="clickEditTask"
+						@click-play="clickPlayTask" @click-pause="clickPauseTask" @click-stop="clickStopTask"
+						@click-skip="clickSkipTask" @click-repeat="clickRepeatTask">
+					</TaskItemView>
+					<template v-slot:right>
+						<view class="btn-del" @click="clickDelSetTask(item)">鍒犻櫎</view>
+					</template>
+				</uni-swipe-action-item>
+			</uni-swipe-action>
+		</view>
+		<view class="list-no-content" v-else>
+			<uni-icons color="#ccc" type="info" size="128"></uni-icons>
+			<view class="space">娌℃湁鎵惧埌绗﹀悎鏉′欢鐨勪换鍔�/view>
+		</view>
+		<view class="position-add" @click="clickAddTask()" @touchstart='btnAddTouchStart' @touchmove='btnAddTouchMove'
+			:style="{transform:`translate(${btnAddInfo.x}px,${btnAddInfo.y}px) scale(1)`}">
+			<uni-icons class="img" type="plus-filled" size="80" color="#1890FF"></uni-icons>
+		</view>
+	</view>
+</template>
+
+<script>
+	import {
+		showToast,
+		showModal,
+		session,
+	} from "@/comm/utils.js"
+	import TaskItemView from "./infos/task-item.vue"
+	import {
+		tasks,
+		taskGroupStatus,
+		addTaskGroupCmd,
+		cancelTask,
+		delTask
+
+	} from "@/api/vehicle.js"
+	import {
+		v4 as uuidv4
+	} from 'uuid';
+	export default {
+		name: "PagesTasklist",
+		components: {
+			TaskItemView
+		},
+		data() {
+			return {
+				ip: "",
+				sceneId: "",
+				list: [],
+				startX: 0, // 瑙︽懜璧峰鐐�+				deleteX: [
+					[],
+					[]
+				], // 姣忎釜椤圭洰鐨勫亸绉婚噺
+				options: [{
+					text: '鍒犻櫎',
+					style: {
+						backgroundColor: '#F56C6C'
+					}
+				}],
+				taskStatus: {},
+				btnAddInfo: {
+					lx: 0,
+					ly: 0,
+					x: 0,
+					y: 0
+				},
+			}
+		},
+		computed: {
+			fixedList() {
+				return this.list.filter((a) => a.tasktype == 1)
+			},
+			tempList() {
+				return this.list.filter((a) => a.tasktype != 1)
+			},
+		},
+		onLoad(option) {
+			this.ip = option.ip || ""
+			this.sceneId = option.sceneId || ""
+			this.loadData()
+		},
+		methods: {
+			setData(obj) {
+				let that = this;
+				let keys = [];
+				let val, data;
+
+				Object.keys(obj).forEach(function(key) {
+					keys = key.split(".");
+					val = obj[key];
+					data = that.$data;
+					keys.forEach(function(key2, index) {
+						if (index + 1 == keys.length) {
+							that.$set(data, key2, val);
+						} else {
+							if (!data[key2]) {
+								that.$set(data, key2, {});
+							}
+						}
+						data = data[key2];
+					});
+				});
+			},
+			async loadData() {
+				try {
+					let btninfo = session.getValue('task_btn_add')
+					if (btninfo) {
+
+						if (btninfo.x > 10) {
+							btninfo.x = 10
+						}
+						if (btninfo.x > 40) {
+							btninfo.x = 40
+						}
+						this.btnAddInfo = btninfo
+					}
+					const res = await tasks(this.ip)
+					const list = res?.data || []
+					this.list = list
+					if (this.list.length > 0) {
+						this.timerCheckTaskGroupStatus()
+					}
+				} catch (ex) {
+
+					this.showError(ex)
+				}
+			},
+			async timerCheckTaskGroupStatus() {
+				if (this.timerCheckStatusId) {
+					return
+				}
+				if (this.list.length == 0) {
+					return
+				}
+				await this.checkTaskGroupStatus()
+				this.timerCheckStatusId = setTimeout(() => {
+					this.timerCheckStatusId = 0
+					this.timerCheckTaskGroupStatus()
+				}, 1000)
+			},
+			async checkTaskGroupStatus() {
+				try {
+					const key = `task_cmd_id_${this.ip.replace(".","_")}`
+					const cmdID = session.getValue(key)
+					if (cmdID) {
+						const info = await taskGroupStatus(this.ip) || {}
+						if (info.taskGroupCmdID == cmdID) {
+
+							const list = info.taskStatusList || []
+							for (let i in list) {
+								if (list[i].status != 1 && list[i].status != 0) {
+									this.taskStatus = {}
+									return
+								}
+							}
+							this.taskStatus = info
+							return
+						}
+
+					}
+					this.taskStatus = {}
+
+				} catch (ex) {
+
+					this.taskStatus = {}
+					this.showError(ex)
+				}
+			},
+			setTaskGroupStatus(cmdID) {
+				const key = `task_cmd_id_${this.ip.replace(".","_")}`
+				session.setValue(key, cmdID)
+
+			},
+			clickAddTask() {
+				const _this = this
+				uni.navigateTo({
+					url: `/pages/task/add?ip=${this.ip}&title=鏂板浠诲姟`,
+					events: {
+						// 涓烘寚瀹氫簨浠舵坊鍔犱竴涓洃鍚櫒锛岃幏鍙栬鎵撳紑椤甸潰浼犻�鍒板綋鍓嶉〉闈㈢殑鏁版嵁
+						add_task: function(data) {
+							_this.loadData()
+						},
+					}
+				})
+			},
+			btnAddTouchStart(e) {
+				this.btnAddInfo.lx = e.touches[0].clientX;
+				this.btnAddInfo.ly = e.touches[0].clientY;
+			},
+			btnAddTouchMove(e) {
+
+				if (this.btnAddInfo.ly < 40) {
+					this.btnAddInfo.x += (e.touches[0].clientX - this.btnAddInfo.lx)
+					this.btnAddInfo.lx = e.touches[0].clientX;
+					this.btnAddInfo.ly = e.touches[0].clientY;
+					if (this.btnAddInfo.x < 50 - this.windowWidth) {
+						this.btnAddInfo.x = 50 - this.windowWidth
+					}
+					if (this.btnAddInfo.x > 40) {
+						this.btnAddInfo.x = 40
+					}
+					session.setValue('task_btn_add', this.btnAddInfo)
+					return
+				}
+
+				this.btnAddInfo.x += (e.touches[0].clientX - this.btnAddInfo.lx)
+				this.btnAddInfo.y += (e.touches[0].clientY - this.btnAddInfo.ly)
+				this.btnAddInfo.lx = e.touches[0].clientX;
+				this.btnAddInfo.ly = e.touches[0].clientY;
+
+
+				if (this.btnAddInfo.x < 50 - this.windowWidth) {
+					this.btnAddInfo.x = 50 - this.windowWidth
+				}
+				if (this.btnAddInfo.x > 40) {
+					this.btnAddInfo.x = 40
+				}
+				if (this.btnAddInfo.y > 80) {
+					this.btnAddInfo.y = 80
+				}
+
+
+
+				session.setValue('task_btn_add', this.btnAddInfo)
+			},
+
+
+			clickEditTask(item) {
+				const _this = this
+				if (this.taskStatus.taskGroupID == item.taskGroupID) {
+					return
+				}
+				uni.navigateTo({
+					url: `/pages/task/update?ip=${this.ip}&title=鏇存柊浠诲姟&task=${JSON.stringify(item)}`,
+					events: {
+						// 涓烘寚瀹氫簨浠舵坊鍔犱竴涓洃鍚櫒锛岃幏鍙栬鎵撳紑椤甸潰浼犻�鍒板綋鍓嶉〉闈㈢殑鏁版嵁
+						update_task: function(data) {
+							const curIndex = _this.list.findIndex((a) => a.taskGroupID == data.taskGroupID)
+							if (curIndex > -1) {
+								_this.list[curIndex] = {
+									taskGroupID: data.taskGroupID,
+									taskGroupName: data.taskGroupName,
+									cycleTime: data.cycleTime,
+									taskButton: data.taskButton,
+									tasktype: data.tasktype,
+									taskList: data.taskList
+								}
+							}
+						},
+					}
+				})
+			},
+			async clickPlayTask(item) {
+				try {
+					const cmdID = uuidv4()
+					await addTaskGroupCmd(this.ip, item.taskGroupID, cmdID, 1)
+					this.setTaskGroupStatus(cmdID)
+
+				} catch (ex) {
+					this.showError(ex)
+				}
+			},
+
+			async clickStopTask(item) {
+				try {
+					await addTaskGroupCmd(this.ip, item.taskGroupID, this.taskStatus.taskGroupCmdID, 2)
+				} catch (ex) {
+					this.showError(ex)
+				}
+			},
+
+			async clickSkipTask(item) {
+				try {
+
+
+					const taskStatusList = this.taskStatus.taskStatusList || []
+					let curIdx = taskStatusList.findIndex((a) => a.status == 1)
+					if (curIdx < 0)
+						curIdx = taskStatusList.findIndex((a) => a.status == 0)
+					if (curIdx > -1) {
+						const taskList = []
+						taskList.push({
+							taskID: taskStatusList[curIdx].taskID,
+							is_cancel: 1
+						})
+						await cancelTask(this.ip,
+							item.taskGroupID,
+							 this.taskStatus.taskGroupCmdID,
+							taskList
+						)
+
+						showToast("璺宠繃瀛愪换鍔℃垚鍔�)
+
+					} else {
+						showToast("鏈壘鍒版湭寮�鎴栨鍦ㄦ墽琛岀殑瀛愪换鍔�)
+					}
+				} catch (ex) {
+					this.showError(ex)
+				}
+			},
+
+			async clickRepeatTask(item) {
+
+
+			},
+
+			async clickPauseTask(item) {},
+			clickDelSetTask(item) {
+				showModal("纭鍒犻櫎浠诲姟璁剧疆", "璀﹀憡").then((res) => {
+					if (res) {
+						this.deleteTask(item)
+
+					}
+				})
+			},
+			async deleteTask(item) {
+				try {
+					await delTask(this.ip, [{
+						taskGroupID: item.taskGroupID,
+					}])
+					const list = this.list
+					const index = list.findIndex((a) =>
+						a.taskGroupID == item.taskGroupID
+					)
+					console.log(index, item, list)
+					if (index < 0)
+						return
+					list.splice(index, 1)
+					this.list = [...list]
+
+				} catch (ex) {
+					this.showError(ex)
+				}
+
+			},
+
+
+			showError(ex) {
+				let exStr = JSON.stringify(ex)
+				if (exStr == "{}")
+					exStr = ex
+				let tip = typeof ex.msg == "string" ? ex.msg : exStr
+				showModal(tip, "閿欒", false)
+			},
+		}
+	}
+</script>
+
+<style lang="scss">
+	.pages-task-list {
+		display: flex;
+		width: 750rpx;
+		height: 100vh;
+		flex-direction: column;
+		position: relative;
+
+		.list-content {
+			display: flex;
+			width: 100%;
+			padding: 0 10px;
+			flex: 1;
+			flex-direction: column;
+			overflow-y: auto;
+			overflow-x: hidden;
+
+			.list-header {
+				margin: 10px;
+				// border-bottom: 1px solid #ddd;
+			}
+
+			.list {
+				// border: 1px solid #ccc;
+				border-radius: 10px;
+
+				background-color: #fff;
+
+				.list-item {
+
+					border-top: 1px solid #ddd;
+				}
+			}
+
+			.btn-del {
+				margin: 10rpx;
+				display: flex;
+				padding: 0 10rpx;
+				background-color: #FF4D4F;
+				font-weight: 700;
+				color: #fff;
+				justify-content: center;
+				align-items: center;
+			}
+
+		}
+
+		.list-no-content {
+			margin-top: 50px;
+			padding: 20rpx 40rpx;
+			align-items: center;
+			text-align: center;
+			display: flex;
+			flex-direction: column;
+			font-size: 30rpx;
+			font-weight: 400;
+
+			.img {
+				width: 212rpx;
+				height: 212rpx;
+				color: #ddd;
+			}
+
+			.space {
+				margin-top: 20rpx;
+			}
+
+		}
+
+		.position-add {
+			position: fixed;
+			right: 10px;
+			bottom: 40px;
+		}
+	}
+</style>
\ No newline at end of file
diff --git a/pages/task/log-list.vue b/pages/task/log-list.vue
new file mode 100644
index 0000000..80acc20
--- /dev/null
+++ b/pages/task/log-list.vue
@@ -0,0 +1,419 @@
+<template>
+	<view class="pages-task-log-list">
+		<view class="list-content" v-if="list.length > 0">
+			<view class="header">
+				<view class="item">
+					<view class="title">{{accumulatedDuration}}<text class="text">min</text></view>
+					<view class="text">绱鏃堕暱</view>
+				</view>
+				<!-- 		<view class="item">
+					<view class="title">{{accumulatedMileage}}<text class="text">m</text></view>
+					<view class="text">绱閲岀▼</view>
+				</view> -->
+				<view class="item">
+					<view class="title">{{cumulativeCount}}</view>
+					<view class="text">绱娆℃暟</view>
+				</view>
+			</view>
+			<view class="list">
+				<view class="task-header" v-if="fixedList.length > 0">鍥哄畾浠诲姟</view>
+				<template v-for="(group) in fixedList" :key="group.date">
+					<view class="task-header">{{group.date}}</view>
+					<view class="task-list-view">
+						<TaskLogItemView v-for="(item,index) in group.list" :key="index" :taskData="item">
+						</TaskLogItemView>
+					</view>
+				</template>
+				<view class="task-header" v-if="tempList.length > 0">涓存椂浠诲姟</view>
+				<template v-for="(group) in tempList" :key="group.date">
+					<view class="task-header">{{group.date}}</view>
+					<view class="task-list-view">
+						<TaskLogItemView v-for="(item,index) in group.list" :key="index" :taskData="item">
+
+						</TaskLogItemView>
+					</view>
+				</template>
+			</view>
+		</view>
+		<view class="list-no-content" v-else>
+			<!-- <image class="img" src="/images/icon-park-outline_attention.svg" alt=" 鍥剧墖" mode="aspectFit" />-->
+			<uni-icons color="#ccc" type="info" size="128"></uni-icons>
+			<view class="space">娌℃湁鎵惧埌绗﹀悎鏉′欢鐨勪换鍔¤褰�/view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import {
+		showToast,
+		showModal
+	} from "@/comm/utils.js"
+	import TaskLogItemView from "./infos/task-log-item.vue"
+	import {
+		getTaskLog
+	} from "@/api/vehicle.js"
+	export default {
+		name: "PagesTaskLogList",
+		components: {
+			TaskLogItemView
+		},
+		data() {
+			return {
+				sceneId: "",
+				list: [],
+			}
+		},
+		computed: {
+			fixedList() {
+				let list = this.list.filter((a) => a.tasktype == 1)
+				let group
+				const listRes = []
+				list.sort((a, b) => {
+					return a.date > b.date
+				});
+				list.forEach((item) => {
+					if (group) {
+						if (item.date != group.date) {
+							group = {
+								date: item.date,
+								list: []
+							}
+							listRes.push(group)
+						}
+					} else {
+						group = {
+							date: item.date,
+							list: []
+						}
+						listRes.push(group)
+					}
+					group.list.push(item)
+				})
+				return listRes
+			},
+			tempList() {
+				let list = this.list.filter((a) => a.tasktype == 2)
+				let group
+				const listRes = []
+				list.sort((a, b) => {
+					return a.date > b.date
+				});
+				list.forEach((item) => {
+					if (group) {
+						if (item.date != group.date) {
+							group = {
+								date: item.date,
+								list: []
+							}
+							listRes.push(group)
+						}
+					} else {
+						group = {
+							date: item.date,
+							list: []
+						}
+						listRes.push(group)
+					}
+					group.list.push(item)
+				})
+				return listRes
+			},
+			accumulatedDuration() {
+				let res = 0
+				this.list.forEach((item) => {
+					res += item.duration || 0
+				})
+				return res
+			},
+			accumulatedMileage() {
+				let res = 0
+				this.list.forEach((item) => {
+					res += item.accumulated_mileage || 0
+				})
+				return res
+			},
+			cumulativeCount() {
+				let res = 0
+				this.list.forEach((item) => {
+					res += item.cycleNumber || 0
+				})
+				return res
+			},
+		},
+		onLoad(option) {
+			this.ip = option.ip || ""
+			this.sceneId = option.sceneId || ""
+			this.loadData()
+		},
+		methods: {
+			setData(obj) {
+				let that = this;
+				let keys = [];
+				let val, data;
+
+				Object.keys(obj).forEach(function(key) {
+					keys = key.split(".");
+					val = obj[key];
+					data = that.$data;
+					keys.forEach(function(key2, index) {
+						if (index + 1 == keys.length) {
+							that.$set(data, key2, val);
+						} else {
+							if (!data[key2]) {
+								that.$set(data, key2, {});
+							}
+						}
+						data = data[key2];
+					});
+				});
+			},
+			async loadData() {
+				try {
+					/*this.list = [{
+						type: 0,
+						taskButton: 1,
+						name: "1鍙风珯鐐瑰埌2鍙风珯鐐�,
+						date: "5-18",
+						accumulated_duration: 5693,
+						accumulated_mileage: 6421,
+						cumulative_number: 55,
+						status: 1,
+					}, {
+						type: 0,
+						taskButton: 2,
+						name: "2鍙风珯鐐瑰埌1鍙风珯鐐�,
+						date: "5-08",
+						accumulated_duration: 888,
+						accumulated_mileage: 642,
+						cumulative_number: 31,
+						status: 2,
+					}, {
+						type: 0,
+						taskButton: 1,
+						name: "1鍙风珯鐐瑰埌2鍙风珯鐐�,
+						date: "4-28",
+						accumulated_duration: 998,
+						accumulated_mileage: 2421,
+						cumulative_number: 85,
+						status: 2,
+					}, {
+						type: 0,
+						taskButton: 2,
+						name: "2鍙风珯鐐瑰埌1鍙风珯鐐�,
+						date: "4-28",
+						accumulated_duration: 688,
+						accumulated_mileage: 1421,
+						cumulative_number: 65,
+						status: 4,
+					}, {
+						type: 1,
+						taskButton: 3,
+						name: "1鍙风珯鐐瑰埌2鍙风珯鐐�,
+						date: "5-18",
+						accumulated_duration: 5693,
+						accumulated_mileage: 6421,
+						cumulative_number: 55,
+						status: 2,
+					}, {
+						type: 1,
+						taskButton: 4,
+						name: "2鍙风珯鐐瑰埌1鍙风珯鐐�,
+						date: "5-08",
+						accumulated_duration: 888,
+						accumulated_mileage: 642,
+						cumulative_number: 31,
+						status: 2,
+					}, {
+						type: 1,
+						taskButton: 3,
+						name: "1鍙风珯鐐瑰埌2鍙风珯鐐�,
+						date: "4-28",
+						accumulated_duration: 998,
+						accumulated_mileage: 2421,
+						cumulative_number: 85,
+						status: 2,
+					}, {
+						type: 1,
+						taskButton: 4,
+						name: "2鍙风珯鐐瑰埌1鍙风珯鐐�,
+						date: "4-28",
+						accumulated_duration: 688,
+						accumulated_mileage: 1421,
+						cumulative_number: 65,
+						status: 2,
+
+					}]*/
+					this.list = await this.loadTaskLog()
+				} catch (ex) {
+					show.showError(ex)
+				}
+			},
+			async loadTaskLog() {
+				try {
+					const now = new Date();
+					const oneWeekAgo = new Date();
+					const endTimeStamp = `${now.getTime()}`
+					oneWeekAgo.setDate(now.getDate() - 7);
+					const startTimeStamp = `${oneWeekAgo.getTime()}`
+					const res = await getTaskLog(this.ip, startTimeStamp, endTimeStamp)
+
+					const list = res?.task_info || []
+					console.log(list)
+					list.forEach((ele) => {
+
+						console.log(ele)
+						const dateStart = new Date()
+						dateStart.setTime(Number(ele.taskStartTimeStamp))
+						ele.date = `${dateStart.getMonth()}-${dateStart.getDay()}`;
+						let taskList = ele.taskList || []
+						taskList.sort((a, b) => {
+							return a.lastUpdateTimeStamp > b.lastUpdateTimeStamp
+						});
+						console.log(taskList)
+						ele.startTime = `${dateStart.getHours()}:${dateStart.getMinutes()}`;
+						ele.endTime = ele.startTime
+						ele.duration = 0;
+						ele.status = 0
+					//	console.log(ele)
+						if (taskList.length > 0) {
+							const dateEnd = new Date()
+							dateEnd.setTime(Number(taskList[taskList.length - 1].lastUpdateTimeStamp))
+							for (let i in taskList) {
+								const ele2 = taskList[i]
+								if (ele2.status == 1) {
+									ele.status = 1
+									break;
+								} else if (ele2.status == 2 || ele2.status == 4 || ele2.status == 5) {
+									ele.status = 2
+									break;
+								}
+							}
+							if (!ele.status) {
+								if (taskList.filter((a) => a.status != 3).length == 0) {
+									ele.status = 3
+								}
+							}
+							const diffInMs = dateEnd - dateStart; // 鎴栬� Math.abs(date1 - date2)
+							ele.endTime = `${dateEnd.getHours()}:${dateEnd.getMinutes()}`;
+							ele.duration = Math.round(diffInMs / (1000 * 60))
+							console.log(ele)
+						}
+					})
+					console.log(list)
+					return list
+				} catch (ex) {
+					show.showError(ex)
+					return []
+				}
+			},
+
+			clickTask(item) {
+				// uni.navigateTo({
+				// 	url: "/pages/task/index"
+				// })
+			},
+			showError(ex) {
+				let exStr = JSON.stringify(ex)
+				if (exStr == "{}")
+					exStr = ex
+				let tip = typeof ex.msg == "string" ? ex.msg : exStr
+				showModal(tip, "閿欒", false)
+			},
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.pages-task-log-list {
+		display: flex;
+		width: 750rpx;
+		height: 100vh;
+		flex-direction: column;
+		background-color: #F5F5F5;
+
+		.list-content {
+			display: flex;
+			width: 100%;
+			padding: 0 10px;
+			flex: 1;
+			flex-direction: column;
+			overflow-y: auto;
+			overflow-x: hidden;
+
+
+			.header {
+				width: calc(100% - 40rpx);
+				padding: 20rpx;
+				display: flex;
+				flex-direction: row;
+
+				.item {
+					padding: 0 20rpx;
+					display: flex;
+					width: calc(100% - 40rpx);
+					flex-direction: column;
+					flex: 1;
+
+					.title {
+						font-size: 40rpx;
+						font-weight: 700;
+					}
+
+					.text {
+						font-size: 30rpx;
+						color: #888;
+					}
+				}
+			}
+
+			.list {
+				width: calc(100% - 20rpx);
+				margin: 10rpx;
+				padding: 0 10rpx;
+				display: flex;
+				flex-direction: column;
+				flex: 1;
+				overflow: auto;
+
+				.task-header {
+					width: 100% ;
+					padding: 10rpx;
+					font-size: 32rpx;
+				}
+
+				.task-list-view {
+					width: 100% ;
+					border-radius: 10rpx;
+					padding: 0 10rpx;
+					background-color: #fff;
+				}
+
+
+			}
+		}
+
+		.list-no-content {
+			margin-top: 50px;
+			padding: 20rpx 40rpx;
+			align-items: center;
+			text-align: center;
+			display: flex;
+			flex-direction: column;
+			font-size: 30rpx;
+			font-weight: 400;
+
+			.img {
+				width: 212rpx;
+				height: 212rpx;
+				color: #ddd;
+			}
+
+			.space {
+				margin-top: 20rpx;
+			}
+
+		}
+
+
+	}
+</style>
\ No newline at end of file
diff --git a/pages/task/map-task.vue b/pages/task/map-task.vue
new file mode 100644
index 0000000..0859ffc
--- /dev/null
+++ b/pages/task/map-task.vue
@@ -0,0 +1,441 @@
+<template>
+	<view class="pages-map-task">
+		<view class="task-div" v-if="selectedType !='set'">
+			<view class="header">
+				<view class="item">
+					<view class="title">{{accumulated_duration}}<text class="text">min</text></view>
+					<view class="text">绱鏃堕暱</view>
+				</view>
+				<view class="item">
+					<view class="title">{{accumulated_mileage}}<text class="text">m</text></view>
+					<view class="text">绱閲岀▼</view>
+				</view>
+				<view class="item">
+					<view class="title">{{cumulative_number}}</view>
+					<view class="text">绱娆℃暟</view>
+				</view>
+			</view>
+			<view class="list">
+				<view class="task-header" v-if="fixedList.length > 0">鍥哄畾浠诲姟</view>
+				<view class="task-list" v-if="fixedList.length > 0">
+					<TaskLogItemView class="item" v-for="(item,index) in fixedList" :key="index" :taskData="item"
+						@click-item="clickTask">
+
+					</TaskLogItemView>
+				</view>
+				<view class="task-header" v-if="tempList.length > 0">涓存椂浠诲姟</view>
+				<view class="task-list" v-if="tempList.length > 0">
+					<TaskLogItemView class="item" v-for="(item,index) in tempList" :key="index" :taskData="item"
+						@click-item="clickTask">
+
+					</TaskLogItemView>
+				</view>
+			</view>
+		</view>
+		<view class="task-set" v-else>
+			<view class="list-header" v-if="fixedSetList.length > 0">鍥哄畾浠诲姟</view>
+			<view class="set-list">
+				<TaskItemView class="list-item" v-for="(item,index) in fixedSetList" :key="index" :taskData="item"
+					:deleteX="deleteX[0][index]" @click-item="clickSetTask" @click-delete="clickDelSetTask"
+					@touchstart="touchStart($event,0, index)" @touchmove="touchMove($event,0, index)"
+					@touchend="touchEnd($event, 0,index)">
+
+				</TaskItemView>
+			</view>
+			<view class="list-header" v-if="tempSetList.length > 0">涓存椂浠诲姟</view>
+			<view class="set-list">
+				<TaskItemView class="list-item" v-for="(item,index) in tempSetList" :key="index" :taskData="item"
+					:deleteX="deleteX[1][index]" @click-item="clickSetTask" @click-delete="clickDelSetTask"
+					@touchstart="touchStart($event, 1,index)" @touchmove="touchMove($event,1, index)"
+					@touchend="touchEnd($event, 1,index)">
+
+				</TaskItemView>
+			</view>
+		</view>
+		<view class="bottom">
+			<view class="button" :class="selectedType =='set'?'':'selected'" @click="clickTaskList">
+				<uni-icons class="icon" :color="selectedType !='set'?'#1ABC9C':'#ccc'" type="bars"
+					size="36"></uni-icons>浠诲姟璁板綍
+			</view>
+			<view class="button" :color="selectedType =='set'?'#1ABC9C':'#ccc'"
+				:class="selectedType =='set'?'selected':''" @click="clickTaskSet">
+				<uni-icons class="icon" :color="selectedType =='set'?'#1ABC9C':'#ccc'" type="gear-filled"
+					size="36"></uni-icons>浠诲姟璁剧疆
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import {
+		showToast,
+		showModal
+	} from "@/comm/utils.js"
+	import TaskLogItemView from "./infos/task-log-item.vue"
+	import TaskItemView from "./infos/task-item.vue"
+	export default {
+		name: "PagesMapTask",
+		components: {
+			TaskLogItemView,
+			TaskItemView
+		},
+		data() {
+			return {
+				selectedType: "list",
+				accumulated_duration: 167991,
+				accumulated_mileage: 7532556,
+				cumulative_number: 6000,
+				taskList: [{
+						name: "1鍙风珯鐐瑰埌2鍙风珯鐐�,
+						date: "5-18",
+						accumulated_duration: 5693,
+						accumulated_mileage: 6421,
+						cumulative_number: 55,
+						type: 0,
+					}, {
+						name: "2鍙风珯鐐瑰埌1鍙风珯鐐�,
+						date: "5-08",
+						accumulated_duration: 888,
+						accumulated_mileage: 642,
+						cumulative_number: 31,
+						type: 0,
+					}, {
+						name: "1鍙风珯鐐瑰埌2鍙风珯鐐�,
+						date: "4-28",
+						accumulated_duration: 998,
+						accumulated_mileage: 2421,
+						cumulative_number: 85,
+						type: 0,
+					}, {
+						name: "2鍙风珯鐐瑰埌1鍙风珯鐐�,
+						date: "4-28",
+						accumulated_duration: 688,
+						accumulated_mileage: 1421,
+						cumulative_number: 65,
+						type: 0,
+					},
+					{
+						name: "1鍙风珯鐐瑰埌2鍙风珯鐐�,
+						date: "5-18",
+						accumulated_duration: 5693,
+						accumulated_mileage: 6421,
+						cumulative_number: 55,
+						type: 1,
+					}, {
+						name: "2鍙风珯鐐瑰埌1鍙风珯鐐�,
+						date: "5-08",
+						accumulated_duration: 888,
+						accumulated_mileage: 642,
+						cumulative_number: 31,
+						type: 1,
+					}, {
+						name: "1鍙风珯鐐瑰埌2鍙风珯鐐�,
+						date: "4-28",
+						accumulated_duration: 998,
+						accumulated_mileage: 2421,
+						cumulative_number: 85,
+						type: 1,
+					}, {
+						name: "2鍙风珯鐐瑰埌1鍙风珯鐐�,
+						date: "4-28",
+						accumulated_duration: 688,
+						accumulated_mileage: 1421,
+						cumulative_number: 65,
+						type: 1,
+					}
+				],
+				setList: [{
+					id: "1",
+					name: "2鍙风珯鐐瑰埌1鍙风珯鐐�,
+					status: 1,
+					type: 0,
+					attribute: 0,
+					start_point: "2鍙风珯鐐�,
+					end_point: "1鍙风珯鐐�,
+					start_time: "15:00",
+					end_time: "21:00",
+					button_no: "1",
+					button_color: "#aa00ff"
+				}, {
+					id: "2",
+					name: "1鍙风珯鐐瑰埌2鍙风珯鐐�,
+					status: 0,
+					type: 0,
+					attribute: 0,
+					start_point: "2鍙风珯鐐�,
+					end_point: "1鍙风珯鐐�,
+					start_time: "15:00",
+					end_time: "21:00",
+					button_no: "2",
+					button_color: "#55aaff"
+				}, {
+					id: "3",
+					name: "2鍙风珯鐐瑰埌1鍙风珯鐐�,
+					status: 0,
+					type: 1,
+					attribute: 0,
+					start_point: "2鍙风珯鐐�,
+					end_point: "1鍙风珯鐐�,
+					start_time: "15:00",
+					end_time: "21:00",
+					button_no: "3",
+					button_color: "#ffaa7f"
+
+				}],
+
+				startX: 0, // 瑙︽懜璧峰鐐�+				deleteX: [
+					[],
+					[]
+				], // 姣忎釜椤圭洰鐨勫亸绉婚噺
+			}
+		},
+		computed: {
+			fixedList() {
+				return this.taskList.filter((a) => a.type != 1)
+			},
+			tempList() {
+				return this.taskList.filter((a) => a.type == 1)
+			},
+			fixedSetList() {
+				return this.setList.filter((a) => a.type != 1)
+			},
+			tempSetList() {
+				return this.setList.filter((a) => a.type == 1)
+			},
+		},
+
+		methods: {
+			setData(obj) {
+				let that = this;
+				let keys = [];
+				let val, data;
+
+				Object.keys(obj).forEach(function(key) {
+					keys = key.split(".");
+					val = obj[key];
+					data = that.$data;
+					keys.forEach(function(key2, index) {
+						if (index + 1 == keys.length) {
+							that.$set(data, key2, val);
+						} else {
+							if (!data[key2]) {
+								that.$set(data, key2, {});
+							}
+						}
+						data = data[key2];
+					});
+				});
+			},
+			clickTask(item) {
+				uni.navigateTo({
+					url: "/pages/task/index"
+				})
+			},
+			clickSetTask(item) {
+				uni.navigateTo({
+					url: `/pages/task/set?param=${JSON.stringify(item)}`
+				})
+			},
+			clickDelSetTask(item) {
+				showModal("纭鍒犻櫎浠诲姟璁剧疆", "璀﹀憡").then((res) => {
+					if (res) {
+						const list = this.setList
+						const index = list.findIndex((a) => {
+							a.id == item.id
+						})
+						if (index < 0)
+							return
+						list.splice(index, 1)
+						this.setData({
+							setList: list
+						})
+					}
+				})
+			},
+
+			clickTaskList() {
+				this.selectedType = "list"
+			},
+			clickTaskSet() {
+				this.selectedType = "set"
+			},
+			touchStart(event, root, index) {
+				this.startX = event.touches[0].pageX;
+				const old = this.deleteX[root][index]
+				if (old) {
+					this.deleteX = [
+						[],
+						[]
+					]
+					this.deleteX[root][index] = old; // 閲嶇疆鍋忕Щ閲�+				} else
+				{
+					this.deleteX = [
+						[],
+						[]
+					]
+					this.deleteX[root][index] = 0; // 閲嶇疆鍋忕Щ閲�+				}
+				
+			},
+			touchMove(event, root, index) {
+				const moveX = event.touches[0].pageX - this.startX;
+				if (moveX < 0) {
+					this.deleteX[root][index] = moveX; // 宸︽粦鏃舵洿鏂板亸绉婚噺
+				}
+				else if (moveX > 0) {
+					this.deleteX[root][index] =0
+				}
+			},
+			touchEnd(event, root, index) {
+				if (this.deleteX[root][index] < -50) { // 濡傛灉婊戝姩璺濈瓒呰繃涓�畾闃堝�锛屾樉绀哄垹闄ゆ寜閽�+					this.deleteX[root][index] = -80; // 璁剧疆鍥哄畾鍋忕Щ閲�+				} else {
+					this.deleteX[root][index] = 0; // 鍚﹀垯鎭㈠鍘熶綅
+				}
+			},
+
+
+		}
+	}
+</script>
+
+<style lang="scss">
+	.pages-map-task {
+		display: flex;
+		width: 750rpx;
+		height: 100vh;
+		flex-direction: column;
+
+		.task-div {
+			display: flex;
+			width: 100%;
+			flex: 1;
+			flex-direction: column;
+			overflow: auto;
+		}
+
+		.header {
+			width: 100%;
+			padding: 10px;
+			height: 30px;
+			display: flex;
+			flex-direction: row;
+
+			.item {
+				padding: 0 10px;
+				display: flex;
+				width: 100%;
+				flex-direction: column;
+				flex: 1;
+
+				.title {
+					font-size: 20px;
+					font-weight: 700;
+				}
+
+				.text {
+					font-size: 14px;
+					color: #888;
+				}
+			}
+		}
+
+		.list {
+			width: calc(100% - 40px);
+			margin: 10px;
+			padding: 0 10px;
+			display: flex;
+			flex-direction: column;
+			flex: 1;
+			overflow: auto;
+
+		}
+
+		.task-header {
+			width: 100%;
+			padding: 10px;
+			font-size: 15px;
+		}
+
+		.task-list {
+			border: 1px solid #ccc;
+			border-radius: 5px;
+			padding: 0 10px;
+
+			.item {
+
+				border-bottom: 1px solid #ddd;
+			}
+		}
+
+		.task-set {
+			display: flex;
+			width: calc(100% - 20px);
+			padding: 0 10px;
+			flex: 1;
+			flex-direction: column;
+			overflow-y: auto;
+			overflow-x: hidden;
+
+			.list-header {
+				margin: 10px;
+				border-bottom: 1px solid #ddd;
+			}
+
+			.set-list {
+				// border: 1px solid #ccc;
+				border-radius: 10px;
+
+				background-color: #fff;
+
+				.list-item {
+
+					border-bottom: 1px solid #ddd;
+				}
+			}
+
+		}
+
+		.bottom {
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			flex-direction: row;
+			font-size: 14px !important;
+			color: #ccc;
+
+			.button {
+				margin: 10px 20px;
+				width: 100px !important;
+				height: 100px !important;
+				border: 0;
+				display: flex;
+				flex-direction: column;
+				background-color: #00000000;
+
+				.icon {
+					margin: 10px !important;
+					width: 28px;
+					height: 28px;
+
+				}
+			}
+
+			.selected {
+				color: #1ABC9C;
+
+				.icon {
+					margin: 10px !important;
+					width: 28px;
+					height: 28px;
+
+				}
+			}
+
+
+		}
+
+	}
+</style>
\ No newline at end of file
diff --git a/pages/task/update.vue b/pages/task/update.vue
new file mode 100644
index 0000000..dd00fe8
--- /dev/null
+++ b/pages/task/update.vue
@@ -0,0 +1,684 @@
+<template>
+	<view class="pages-task-update">
+		<uni-nav-bar :fixed="true" status-bar right-text="" left-text="" leftWidth="72rpx" rightWidth="72rpx"
+			:title="navigationBarTitle">
+			<view class="uni-navbar-container-inner">
+				<text class="uni-nav-bar-text">{{navigationBarTitle }}</text>
+			</view>
+			<template v-slot:right>
+				<view class="uni-navbar-btn-text">
+					<a @click="clickSave" class="uni-nav-bar-right-text">
+						淇濆瓨
+					</a>
+				</view>
+
+			</template>
+			<template v-slot:left>
+				<view class="uni-navbar-btn-text">
+					<a @click="clickCancel" class="uni-nav-bar-left-text">
+						鍙栨秷
+					</a>
+				</view>
+
+			</template>
+		</uni-nav-bar>
+		<view class="content">
+			<view class="header">浠诲姟灞炴�</view>
+			<view class="group">
+				<view class="item">
+					<view>鍚嶇О锛�/view>
+					<input class="right-input" placeholder="杈撳叆浠诲姟鍚嶇О" v-model="form.taskGroupName" />
+				</view>
+				<view class="item">
+					<view>灞炴�锛�/view>
+					<view class="right" v-if="form.tasktype > 0">{{form.tasktype ==1 ? '鍥哄畾':'涓存椂'}}</view>
+					<view class="right" v-else>閫夋嫨灞炴�</view>
+					<a @click="clickType">
+						<uni-icons class="icon" type="right" size="20"></uni-icons>
+					</a>
+				</view>
+				<view class="item" v-if="form.tasktype == 1">
+					<view>寰幆娆℃暟锛�/view>
+					<input class="right-input" type="number" :value="form.cycleTime" :maxlength="4"
+						@input="onInputCycleTime" />
+				</view>
+				<view class="item">
+					<view>鎸夐挳鍙凤細</view>
+					<view class="right">{{form.taskButton ?form.taskButton:""}}</view>
+					<a @click="clickTaskButton">
+						<uni-icons class="icon" type="right" size="20"></uni-icons>
+					</a>
+				</view>
+			</view>
+			<view class="header">浠诲姟璺嚎</view>
+			<view class="group">
+				<view class="list">
+					<view class="list-item" v-for="(item,index) in pathwayList" :key="index" :auto-close="true">
+						<view class="item">
+							<view>鐩爣鐐箋{index+1}}锛�/view>
+							<view class="right"></view>
+							<a @click.stop="(e)=>{ this.clickPathwayPoint(e,index,'stationID')}">
+								{{item.dest?.stationID ?item.dest?.name : "鐩爣鐐�}}
+
+							</a>
+							<a @click.stop="(e)=>{ clickPathwayPoint(e,index,'actionType')}">
+								{{actionTypeText(item.actionType)}}
+							</a>
+							<view v-if="item.actionType === 3">
+								<a @click.stop="()=>{item.wait = 0}" v-if="item.wait===undefined">
+									绛夊緟鏃堕棿
+								</a>
+								<view v-else class="time"> <input class="input" type="number" v-model="item.wait"
+										:maxlength="4" />绉�/view>
+							</view>
+						</view>
+					</view>
+				</view>
+			</view>
+		</view>
+		<view>
+			<uni-popup ref="refPopupMenu" background-color="transparent" maskBackgroundColor="rgba(0, 0, 0, 0.2)">
+				<view class="popup-content" @click="closeMenu">
+					<picker-view class="popup-content-view"
+						:style="{'margin-top':pickerView.top +'px','margin-right': pickerView.right +'px'}"
+						:indicator-style="indicatorStyle" :value="pickerView.value" @change="bindPickerChange">
+						<picker-view-column>
+							<view class="item" v-for="(item,index) in pickerView.list" :key="index">{{item.name}}</view>
+						</picker-view-column>
+
+					</picker-view>
+				</view>
+			</uni-popup>
+		</view>
+	</view>
+</template>
+<script>
+	import {
+		showToast,
+		showModal
+	} from "@/comm/utils.js"
+	import {
+		Button
+	} from 'antd-mobile-vue-next'
+	import {
+		stations,
+		addTask,
+		updateTask,
+		delTask,
+
+	} from "@/api/vehicle.js"
+	import {
+		v4 as uuidv4
+	} from 'uuid';
+	export default {
+		name: "PagesTaskUpdate",
+		components: {
+			'a-button': Button
+		},
+		data() {
+			return {
+				indicatorStyle: `height: 75rpx;`,
+				ip: '',
+				navigationBarTitle: '鏇存柊浠诲姟',
+				info: {
+
+				},
+				form: {
+					taskGroupID: "",
+					taskGroupName: "",
+					cycleTime: 1,
+					taskButton: 0,
+					tasktype: 0,
+					taskList: []
+				},
+				pathwayList: [],
+
+				pickerView: {
+					type: "",
+					list: [],
+					value: []
+				},
+				stationList: [],
+				windowSize: {},
+				isEditContent: false,
+				actionList: [{
+					name: "瀵艰埅",
+					type: 1,
+				}, {
+					name: "鍙栬揣",
+					type: 2,
+				}, {
+					name: "鍗歌揣",
+					type: 3,
+				}, {
+					name: "浜哄伐",
+					type: 4,
+				}]
+			}
+		},
+		computed: {
+
+		},
+
+		onLoad(option) {
+
+			const _this = this
+			this.navigationBarTitle = option.title || "鏇存柊浠诲姟"
+			this.ip = option.ip || ""
+			if (option.task) {
+				const info = JSON.parse(option.task)
+				this.form = {
+					taskGroupID: info.taskGroupID || "",
+					taskGroupName: info.taskGroupName || "",
+					cycleTime: parseInt(info.cycleTime) || 1,
+					taskButton: info.taskButton || 0,
+					tasktype: info.tasktype || 0,
+
+				}
+				this.info = info
+				let list = info.taskList || []
+
+				for (let i = 0; i < list.length; i++) {
+					const item = list[i]
+					this.pathwayList.push({
+						actionType: item.actionType,
+						dest: item.dest || {},
+						wait: parseInt(item.wait) || 0,
+						taskID: item.taskID,
+						taskStartTimeStamp: item.taskStartTimeStamp,
+					})
+				}
+
+
+			}
+			uni.getSystemInfo({
+				success(e) {
+					_this.windowSize = {
+						width: e.windowWidth,
+						height: e.windowHeight - (e.statusBarHeight || 0)
+					}
+				},
+
+			})
+			this.loadStations()
+		},
+		methods: {
+			setData(obj) {
+				let that = this;
+				let keys = [];
+				let val, data;
+
+				Object.keys(obj).forEach(function(key) {
+					keys = key.split(".");
+					val = obj[key];
+					data = that.$data;
+					keys.forEach(function(key2, index) {
+						if (index + 1 == keys.length) {
+							that.$set(data, key2, val);
+						} else {
+							if (!data[key2]) {
+								that.$set(data, key2, {});
+							}
+						}
+						data = data[key2];
+					});
+				});
+			},
+			async loadStations() {
+				try {
+					const info = await stations(this.ip)
+					this.stationList = info.station_list || []
+				} catch (ex) {
+					this.showError(ex)
+				}
+			},
+			async clickSave() {
+				try {
+					const name = this.form.taskGroupName.trim()
+					if (!name) {
+						showToast("鏈緭鍏ヤ换鍔″悕绉帮紒")
+						return
+					}
+					if (!this.form.tasktype) {
+						showToast("鏈�鎷╀换鍔″睘鎬э紒")
+						return
+					}
+					const task = {
+						taskGroupID: this.form.taskGroupID,
+						taskGroupName: name,
+						cycleTime: parseInt(this.form.cycleTime),
+						taskButton: this.form.taskButton,
+						tasktype: this.form.tasktype,
+						taskList: {}
+					}
+					const taskStartTimeStamp = `${new Date().getTime()}`
+					let bUpdated = false
+					for (let i = 0; i < this.pathwayList.length; i++) {
+						const item2 = this.info.taskList[i]
+						const item = this.pathwayList[i]
+						let flag = false
+						if (item?.actionType != item2.actionType) {
+							flag = true
+						} else if (item?.dest?.stationID != item2.dest?.stationID) {
+							flag = true
+						} else {
+							if (item?.actionType == 1) {
+								if (item?.wait != item2.wait) {
+									flag = true
+								}
+							}
+						}
+						if (flag) {
+							task.taskList = {
+								dest: item.dest,
+								actionType: item.actionType || 0,
+								wait: parseInt(item.wait) || 0,
+								taskID: item.taskID,
+								taskStartTimeStamp: item.taskStartTimeStamp || taskStartTimeStamp,
+							}
+							await updateTask(this.ip, task)
+							this.info.taskList[i] = task.taskList
+							bUpdated = true
+						}
+
+					}
+					if (!bUpdated) {
+						task.taskList.taskID = -1
+						await updateTask(this.ip, task)
+					}
+					this.info.taskGroupID = task.taskGroupID
+					this.info.taskGroupName = task.taskGroupName
+					this.info.cycleTime = task.cycleTime
+					this.info.taskButton = task.taskButton
+					this.info.tasktype = task.tasktype
+
+					const eventChannel = this.getOpenerEventChannel();
+					eventChannel.emit('update_task', this.info);
+					uni.navigateBack({
+						delta: 1, //杩斿洖灞傛暟锛�鍒欎笂涓婇〉
+					})
+				} catch (ex) {
+					this.showError(ex)
+				}
+			},
+			clickCancel() {
+				let flag = false
+				if (this.form.taskGroupName.trim() != this.info.taskGroupName) {
+					flag = true
+				} else if (this.form.taskButton != this.info.taskButton) {
+					flag = true
+				} else if (this.form.tasktype != this.info.tasktype) {
+					flag = true
+				} else if (this.form.cycleTime != this.info.cycleTime) {
+					flag = true
+				}
+				for (let i = 0; i < this.info.taskList.length; i++) {
+					const item = this.info.taskList[i]
+					const item2 = this.pathwayList[i]
+					if (item?.actionType != item2.actionType) {
+						flag = true
+						break
+					} else if (item?.dest?.stationID != item2.dest?.stationID) {
+						flag = true
+						break
+					} else {
+						if (item?.actionType == 3) {
+							if (item?.wait != item2.wait) {
+								flag = true
+								break
+							}
+						}
+					}
+				}
+
+
+
+				if (flag) {
+					showModal(`褰撳墠缂栬緫鐨勫唴瀹瑰皢涓嶄細琚繚瀛榒, "纭畾瑕侀�鍑虹紪杈戝悧?").then((res) => {
+						if (res) {
+							uni.navigateBack({
+								delta: 1, //杩斿洖灞傛暟锛�鍒欎笂涓婇〉
+							})
+						}
+
+					})
+				} else {
+					uni.navigateBack({
+						delta: 1, //杩斿洖灞傛暟锛�鍒欎笂涓婇〉
+					})
+				}
+
+			},
+			stationLst(id) {
+				const list = []
+
+				const list3 = [...this.pathwayList]
+
+				this.stationList.forEach((item) => {
+					let curIndex
+					if (id) {
+						if (item.stationID != id) {
+							curIndex = list3.findIndex((a) => a.dest?.stationID == item.stationID)
+						} else {
+							curIndex = -1
+						}
+					} else {
+						curIndex = list3.findIndex((a) => a.dest?.stationID == item.stationID)
+					}
+					if (curIndex < 0) {
+						list.push(item)
+					}
+				})
+				return list
+			},
+
+			stationName(id) {
+				const curIndex = this.stationList.findIndex((a) => a.stationID == id)
+				if (curIndex > -1) {
+					return this.stationList[curIndex].name
+				}
+				return ""
+
+			},
+
+			actionTypeText(type) {
+				if (type > 0) {
+					const curIndex = this.actionList.findIndex((a) => a.type == type)
+					if (curIndex > -1) {
+						return this.actionList[curIndex].name
+					} else {
+						return "鎿嶄綔"
+					}
+				} else {
+					return "鎿嶄綔"
+				}
+			},
+
+			clickPathwayPoint(e, index, type) {
+				let top = e.target.offsetTop + 30
+				if (this.windowSize.height > 0) {
+					if (e.detail.y + 180 > this.windowSize.height) {
+						top = e.detail.y - 180
+					}
+				}
+				let right = 0
+				const item = this.pathwayList[index]
+				if (type == "stationID") {
+
+					const list = this.stationLst(item.dest?.stationID)
+					let index2 = 0
+					if (list.length > 0) {
+						if (item.dest?.stationID) {
+							index2 = list.findIndex((a) => a.stationID == item.dest?.stationID)
+							if (index2 < 0) {
+								item.dest = list[0]
+								index2 = 0
+							}
+
+						} else {
+							item.dest = list[0]
+							index2 = 0
+						}
+					}
+					if (this.windowSize.width > 0) {
+						right = this.windowSize.width - e.detail.x
+					}
+					this.pickerView = {
+						type: "pathwayPoint",
+						list,
+						value: [index2],
+						index,
+						top,
+						right,
+					}
+					this.$refs.refPopupMenu.open("right")
+				} else if (type == "actionType") {
+					if (this.windowSize.width > 0) {
+						right = this.windowSize.width - e.detail.x
+					}
+
+					let index2 = 0
+					if (item.actionType)
+						index2 = this.actionList.findIndex((a) => a.type == item.actionType)
+					if (index2 < 0)
+						index2 = 0
+					item.actionType = this.actionList[index2].type
+					this.pickerView = {
+						type: "pathwayPointActionType",
+						list: this.actionList,
+						value: [index2],
+						index,
+						top,
+						right,
+					}
+					this.$refs.refPopupMenu.open("right")
+				}
+
+			},
+			clickType(e) {
+				if (!this.form.tasktype) {
+					this.form.tasktype = 1
+				}
+				this.pickerView = {
+					type: "type",
+					list: [{
+						name: "鍥哄畾"
+					}, {
+						name: "涓存椂"
+					}],
+					value: [this.form.tasktype - 1],
+					top: e.target.offsetTop + 30,
+					right: 0,
+				}
+				this.$refs.refPopupMenu.open("right")
+
+			},
+			bindPickerChange(e) {
+				const val = e.detail.value
+				const val2 = val[0]
+				if (this.pickerView.type == "type") {
+					this.form.tasktype = val2 + 1
+				} else if (this.pickerView.type == "pathwayPoint") {
+					if (this.pathwayList[this.pickerView.index].dest?.stationID != this.pickerView.list[val2]
+						?.stationID)
+						this.pathwayList[this.pickerView.index].taskStartTimeStamp = `${new Date().getTime()}`
+					this.pathwayList[this.pickerView.index].dest = this.pickerView.list[val2]
+				} else if (this.pickerView.type == "pathwayPointActionType") {
+					if (this.pathwayList[this.pickerView.index].actionType != this.pickerView.list[val2].type)
+						this.pathwayList[this.pickerView.index].taskStartTimeStamp = `${new Date().getTime()}`
+					this.pathwayList[this.pickerView.index].actionType = this.pickerView.list[val2].type
+				} else if (this.pickerView.type == "taskButton") {
+					this.form.taskButton = val2 + 1
+				}
+			},
+			clickAddPathway() {
+				this.pathwayList.push({})
+			},
+			async clickDelPathWay(item, index) {
+				try {
+					if (this.pathwayList.length == 1) {
+
+						showToast("蹇呴』鏈変竴涓洰鏍囩偣")
+						return
+					}
+					if (item.taskID) {
+						await delTask({
+							taskGroupID: item.taskGroupID,
+							taskID: item.taskID
+						})
+					}
+					const list = this.pathwayList
+					const index = list.findIndex((a) => {
+						a.id == item.id
+					})
+					if (index < 0)
+						return
+					list.splice(index, 1)
+					this.setData({
+						pathwayList: list
+					})
+
+				} catch (ex) {
+					this.showError(ex)
+				}
+
+			},
+			onInputCycleTime(event) {
+				this.form.cycleTime = event.detail.value;
+			},
+
+			clickTaskButton(e) {
+				const list = []
+				for (let i = 1; i < 100; i++) {
+					list.push({
+						name: i
+					})
+				}
+				if (!this.form.taskButton) {
+					this.form.taskButton = 1
+				}
+				this.pickerView = {
+					type: "taskButton",
+					list,
+					value: [this.form.taskButton - 1],
+					top: e.target.offsetTop + 30,
+					right: 0,
+				}
+
+				this.$refs.refPopupMenu.open("right")
+			},
+			closeMenu() {
+				this.$refs.refPopupMenu.close()
+			},
+			showError(ex) {
+				let exStr = JSON.stringify(ex)
+				if (exStr == "{}")
+					exStr = ex
+				let tip = typeof ex.msg == "string" ? ex.msg : exStr
+				showModal(tip, "閿欒", false)
+			},
+
+		}
+	}
+</script>
+
+<style lang="scss">
+	.pages-task-update {
+		display: flex;
+		width: 750rpx;
+		height: 100vh;
+		flex-direction: column;
+		background-color: #F8F8F8;
+
+		.content {
+			width: 750rpx;
+			display: flex;
+			flex-direction: column;
+			flex: 1;
+		}
+
+		.header {
+			margin: 10rpx 30rpx;
+		}
+
+		.group {
+			width: calc(100% - 60rpx);
+			// border: 1px solid #ccc;
+			border-radius: 20rpx;
+			margin: 10rpx 20rpx;
+			padding: 0 10rpx;
+			display: flex;
+			flex-direction: column;
+			background-color: #fff;
+			font-size: 30rpx;
+
+			.item {
+				width: calc(100% - 20rpx);
+				padding: 20rpx 10rpx;
+				display: flex;
+				flex-direction: row;
+
+				.right {
+					flex: 1;
+					text-align: right;
+					color: #888;
+					padding-right: 5px;
+
+				}
+
+
+
+				.right-input {
+					text-align: right;
+					flex: 1;
+				}
+
+				.text {
+					flex: 1;
+					color: #888;
+
+				}
+
+				.icon {
+					color: #888;
+				}
+
+				a {
+					margin-left: 20rpx;
+				}
+
+				.time {
+					display: flex;
+					flex-direction: row;
+					margin-left: 20rpx;
+
+					.input {
+						width: 75rpx;
+					}
+				}
+			}
+
+			.btn-del {
+				display: flex;
+				padding: 0 10rpx;
+				background-color: #FF4D4F;
+				font-weight: 700;
+				color: #fff;
+				justify-content: center;
+				align-items: center;
+			}
+
+			.line {
+				border-bottom: 2rpx solid #ccc;
+			}
+		}
+
+		.button {
+			margin: auto;
+			width: 700rpx;
+			color: #1890FF;
+		}
+
+		.popup-content {
+			display: flex;
+			justify-content: center;
+			flex-direction: column;
+			background-color: transparent;
+		}
+
+		.popup-content-view {
+			width: 150px;
+			height: 150px;
+			border-radius: 10rpx;
+			padding: 10rpx 20rpx;
+			background-color: #fff;
+
+			.item {
+				line-height: 75rpx;
+				text-align: center;
+				border: 0;
+
+			}
+		}
+	}
+</style>
\ No newline at end of file
diff --git a/pages/teaching/index.vue b/pages/teaching/index.vue
new file mode 100644
index 0000000..2b171f9
--- /dev/null
+++ b/pages/teaching/index.vue
@@ -0,0 +1,997 @@
+<template>
+	<view class="pages-teaching">
+		<view class="view-content">
+			<view class="map-content">
+			</view>
+		</view>
+		<view class="bottom">
+			<template v-if="mapOperationType =='public_teaching' || mapOperationType =='station_teaching'">
+				<view class="bottom-content" v-if="teachingStatus =='teaching'">
+					<view class="tip">璺緞璁板綍涓�..</view>
+					<view v-if="mapOperationType =='public_teaching'">
+						<view>姝e湪璁板綍鎼繍杞﹁杩涜矾寰勶紝鍙殢鏃跺垏鎹富璺�鏀矾绀烘暀锛屽畬鎴愬悗鐐规寜閽互缁撴潫绀烘暀銆傚湪绀烘暀杩囩▼涓彲浠ユ坊鍔犵珯鐐广�</view>
+						<view class="switch-type">
+							<view class="switch-button-group">
+								<view class="switch-button"
+									:class="teachingModeCur.main_road ==1?'switch-button-checked':''"
+									@click="onTeachingModeMainRoad(1)">涓昏矾绀烘暀</view>
+								<view class="switch-button "
+									:class="teachingModeCur.main_road ==0?'switch-button-checked':''"
+									@click="onTeachingModeMainRoad(0)">鏀矾绀烘暀</view>
+							</view>
+						</view>
+					</view>
+
+					<view v-else>
+						姝e湪璁板綍鎼繍杞﹁杩涜矾寰勶紝瀹屾垚鍚庣偣鎸夐挳浠ョ粨鏉熺ず鏁�+					</view>
+					<view class="text-button-group">
+						<a-button v-if="mapOperationType =='public_teaching'" type="ghost" class="button"
+							@click="clickAddDatation">娣诲姞绔欑偣</a-button>
+						<a-button type="primary" class="button" @click="clickTeachingEnd">缁撴潫璁板綍</a-button>
+					</view>
+				</view>
+				<view class="bottom-content" v-else-if="teachingStatus =='end'">
+					<view class="tip">璺緞璁板綍瀹屾垚</view>
+					<view>
+						瑕佸皢璇ユ璺緞淇濆瓨涓虹ず鏁欒矾寰勫悧锛�+					</view>
+					<view class="text-button-group">
+						<a-button type="primary" class="button" @click="clickTeachingSave">淇濆瓨涓虹ず鏁欒矾寰�/a-button>
+						<a-button type="ghost" class="button" @click="clickTeachingReset">閲嶆柊璁板綍</a-button>
+					</view>
+				</view>
+				<view class="bottom-content" v-else-if="teachingStatus =='save'">
+					<view class="tip">绀烘暀瀹屾垚</view>
+					<view>
+						宸插皢璺緞淇濆瓨涓虹ず鏁欒矾寰�+					</view>
+					<view class="text-button-group">
+						<a-button type="primary" class="button" @click="clickTeachingFinish">瀹屾垚</a-button>
+					</view>
+				</view>
+				<template v-else>
+					<view class="bottom-content" v-if=" mapOperationType =='station_teaching'">
+						<view class="tip">璇烽�鎷╃ず鏁欒矾绾跨殑璧风偣鍜岀粓鐐�/view>
+						<view class="row-group">
+							<view class="coordinate">
+								<text class="name">璧风偣:</text>
+								<a @click="clickStartStation">
+									{{startStationID ? stationName(startStationID) : "璇烽�鎷╄捣鐐�}}
+								</a>
+							</view>
+							<view class="coordinate">
+								<text class="name">缁堢偣:</text>
+								<a @click="clickEndStation">
+									{{endStationID ? stationName(endStationID) : "璇烽�鎷╃粓鐐�}}
+								</a>
+
+							</view>
+						</view>
+						<view>璇峰皢鎼繍杞︾Щ鑷宠捣鐐癸紝鐐光�寮�璁板綍鈥濆悗灏嗚溅寮�埌缁堢偣锛屾娆¤杩涜矾绾垮皢浣滀负鎵��绔欑偣闂寸殑绀烘暀璺嚎銆�/view>
+						<view class="text-button-group">
+							<a-button type="primary" :disabled="startStationID=='' || endStationID==''" class="button"
+								@click="clickTeachingStart">寮�璁板綍</a-button>
+						</view>
+					</view>
+					<view class="bottom-content" v-else>
+						<view class="tip">鍗冲皢寮�鍏叡绀烘暀</view>
+						<view>
+							璇烽�鎷╄杩涜涓昏矾杩樻槸鏀矾绀烘暀锛岀偣銆愬紑濮嬭褰曘�鍚庡皢璁板綍鎼繍杞︾殑琛岃繘璺嚎浣滀负鍏叡绀烘暀璺嚎銆傚紑濮嬭褰曞悗鍙殢鏃跺垏鎹富璺�鏀矾绀烘暀銆�+						</view>
+						<view class="text-button-group">
+							<view class="switch-type">
+								<view class="switch-button-group">
+									<view class="switch-button"
+										:class="teachingModeCur.main_road ==1?'switch-button-checked':''"
+										@click="onTeachingModeMainRoad(1)">涓昏矾绀烘暀</view>
+									<view class="switch-button "
+										:class="teachingModeCur.main_road ==0?'switch-button-checked':''"
+										@click="onTeachingModeMainRoad(0)">鏀矾绀烘暀</view>
+								</view>
+							</view>
+							<a-button type="primary" class="button" @click="clickTeachingStart">寮�璁板綍</a-button>
+						</view>
+					</view>
+				</template>
+			</template>
+			<view class="bottom-content" v-else>
+				<view class="img-button-group">
+					<view fill="none" class="button" @click="clickStationTeaching">
+						<text class="ico conversion-path"></text>
+						<view class="text">绔欑偣绀烘暀</view>
+					</view>
+					<view type="text" class="button " @click="clickPublicTeaching">
+						<text class="ico edit-road-outline-rounded"></text>
+						<view class="text">鍏叡绀烘暀</view>
+					</view>
+				</view>
+
+			</view>
+		</view>
+		<view>
+			<uni-popup ref="refPopupPicker" background-color="transparent" maskBackgroundColor="rgba(0, 0, 0, 0.2)">
+				<view class="popup-content" @click="closePopupPicker">
+					<picker-view class="popup-content-view" :style="{'margin-left':pickerView.left +'px'}"
+						:indicator-style="indicatorStyle" :value="pickerView.value" @change="bindPickerChange">
+						<picker-view-column>
+							<view class="item" @click="clickPickerViewItem(index)"
+								v-for="(item,index) in pickerView.list" :key="index">{{item.name}}</view>
+						</picker-view-column>
+
+					</picker-view>
+				</view>
+			</uni-popup>
+			<uni-popup ref="refPopupCalibration">
+				<view class="popup-dialog">
+					<view class="popup-dialog-title">
+						<text class="uni-dialog-title-text">鏄惁瑕佹牎鍑嗙珯鐐逛綅缃紵</text>
+					</view>
+					<view class="popup-dialog-content">
+						妫�祴鍒皗{calibratioStationTypeName}}浣嶇疆鏈濆悜涓庢墍閫夌珯鐐规湁鍋忓樊锛屾槸鍚﹀皢绔欑偣浣嶇疆鏈濆悜鏍″噯鍒板綋鍓嶅�锛�+					</view>
+					<view class="popup-dialog-button-group">
+
+						<view class="popup-dialog-button" @click="clickCalibration">
+							鏍″噯
+						</view>
+						<view class="popup-dialog-button" @click="clickNoCalibration">
+							涓嶆牎鍑�+						</view>
+						<view class="popup-dialog-button" @click="clickBackTeaching">
+							鍥炲埌绀烘暀
+						</view>
+					</view>
+				</view>
+			</uni-popup>
+		</view>
+	</view>
+</template>
+<script>
+	import {
+		showToast,
+		showModal
+	} from "@/comm/utils.js"
+	import {
+		Button
+	} from 'antd-mobile-vue-next'
+
+	import {
+		stations,
+		updateStation,
+		getAgvState,
+		getTeachingMode,
+		teachingModeFlag,
+		delTeachingMode,
+		checkAgvLocationDistanceError
+
+	} from "@/api/vehicle.js"
+	import {
+		async
+	} from "rxjs"
+	export default {
+		name: "PagesTeaching",
+		components: {
+			'a-button': Button
+		},
+		onBackPress() {
+			const _this = this
+			if (this.mapOperationType == "") {
+				return false
+			} else if (this.mapOperationType == "public_teaching" || this.mapOperationType == "station_teaching") {
+
+				if (this.teachingStatus) {
+					showModal("宸茶褰曠殑璺緞灏嗕細琚垹闄ゃ�", "鏄惁瑕侀�鍑虹ず鏁欙紵").then((res) => {
+						if (res) {
+							this.mapOperationType = ""
+						}
+					})
+				} else {
+					this.mapOperationType = ""
+				}
+
+			}
+			return true
+		},
+		data() {
+			return {
+				indicatorStyle: `height: 75rpx;`,
+				navigationBarTitle: "",
+				ip: "",
+				mapOperationType: "",
+				teachingStatus: "",
+				teachingMode: {},
+				teachingModeCur: {},
+
+				startStationID: "",
+				endStationID: "",
+				calibratioStationType: "",
+				pickerView: {
+					type: "",
+					list: [],
+					value: []
+				},
+				stationList: [],
+
+
+			}
+		},
+		computed: {
+
+		},
+		watch: {
+			mapOperationType(val) {
+				let name = "璺緞绀烘暀"
+				if (val == "public_teaching") {
+					name = "鍏叡绀烘暀"
+				} else if (val == "station_teaching") {
+					name = "绔欑偣绀烘暀"
+				}
+				this.setData({
+					navigationBarTitle: name
+				})
+			},
+			navigationBarTitle(val) {
+				uni.setNavigationBarTitle({
+					title: val
+				})
+			},
+			calibratioStationTypeName() {
+				if (this.calibratioStationType == "start") {
+					return "璧风偣"
+				} else if (this.calibratioStationType == "end") {
+					return "缁堢偣"
+				} else {
+					return "绔欑偣"
+				}
+			},
+		},
+		onLoad(option) {
+			this.ip = option.ip || ""
+			this.loadData()
+
+		},
+		methods: {
+			setData(obj) {
+				let that = this;
+				let keys = [];
+				let val, data;
+
+				Object.keys(obj).forEach(function(key) {
+					keys = key.split(".");
+					val = obj[key];
+					data = that.$data;
+					keys.forEach(function(key2, index) {
+						if (index + 1 == keys.length) {
+							that.$set(data, key2, val);
+						} else {
+							if (!data[key2]) {
+								that.$set(data, key2, {});
+							}
+						}
+						data = data[key2];
+					});
+				});
+			},
+
+			async loadData() {
+				try {
+
+					const stationLst = await this.loadStations()
+
+					this.stationList = stationLst
+					this.teachingMode = await getTeachingMode(this.ip)
+
+				} catch (ex) {
+
+					this.showError(ex)
+				}
+			},
+			async loadAgvState() {
+				try {
+					const info = await getAgvState(this.ip)
+					return info
+				} catch (ex) {
+					this.showError(ex)
+					return {}
+				}
+			},
+			async loadStations() {
+				try {
+					const info = await stations(this.ip)
+					return info.station_list || []
+				} catch (ex) {
+					this.showError(ex)
+					return []
+				}
+			},
+			stationName(id) {
+				const curIndex = this.stationList.findIndex((a) => a.stationID == id)
+				if (curIndex > -1) {
+					return this.stationList[curIndex].name
+				}
+				return ""
+
+			},
+			clickPublicTeaching() {
+
+				this.teachingStatus = ""
+				this.teachingModeCur = {
+					mode: "Public",
+					main_road: 1,
+				}
+				this.mapOperationType = "public_teaching"
+
+			},
+			clickStationTeaching() {
+
+				this.startStationID = ""
+				this.endStationID = ""
+				this.teachingStatus = ""
+				this.mapOperationType = "station_teaching"
+			},
+			async teachingStart(mode) {
+				try {
+					if (mode == "Stations") {
+						const res = await checkAgvLocationDistanceError(this.ip, this.startStationID)
+						if (res?.error) {
+							this.calibratioStationType = "start"
+							this.$refs.refPopupCalibration.open()
+						} else {
+							// const name =
+							// 	`${ this.stationName(this.startStationID)}_${ this.stationName(this.endStationID)}`
+
+							this.teachingModeCur = {
+								mode: "Stations",
+								src_dst: `${this.startStationID}_${this.endStationID}`,
+								name: "",
+								teaching_flag: 1,
+							}
+							const res2 = await teachingModeFlag(this.ip, this.teachingModeCur)
+							if (res2?.name)
+								this.teachingModeCur.name = res2.name
+						}
+					} else {
+						//	const name = `绀烘暀_${new Date().getTime()}`
+						const main_road = this.teachingModeCur.main_road
+						this.teachingModeCur = {
+							mode: "Public",
+							src_dst: ``,
+							name: "",
+							teaching_flag: 1,
+							main_road
+						}
+						const res2 = await teachingModeFlag(this.ip, this.teachingModeCur)
+						if (res2?.name)
+							this.teachingModeCur.name = res2.name
+					}
+
+				} catch (ex) {
+					this.showError(ex)
+				}
+
+			},
+			async teachingEnd(mode) {
+				try {
+					if (mode == "Stations") {
+						const res = await checkAgvLocationDistanceError(this.ip, this.endStationID)
+						if (res.error) {
+							this.calibratioStationType = "end"
+							this.$refs.refPopupCalibration.open()
+						} else {
+							this.teachingModeCur.teaching_flag = 0
+							await teachingModeFlag(this.ip, this.teachingModeCur)
+							this.teachingMode = await getTeachingMode(this.ip)
+
+							this.teachingStatus = "end"
+
+						}
+					} else {
+						this.teachingModeCur.teaching_flag = 0
+						await teachingModeFlag(this.ip, this.teachingModeCur)
+						this.teachingMode = await getTeachingMode(this.ip)
+						this.teachingStatus = "end"
+					}
+				} catch (ex) {
+					this.showError(ex)
+				}
+
+			},
+			async onTeachingModeMainRoad(val) {
+				try {
+					if (this.teachingStatus) {
+
+						this.teachingModeCur.main_road = val
+						this.teachingModeCur.teaching_flag = 1
+						this.teachingModeCur.mode = "Public"
+						const res = await teachingModeFlag(this.ip, this.teachingModeCur)
+						if (res?.name)
+							this.teachingModeCur.name = res.name
+					} else {
+						this.teachingModeCur.main_road = val
+					}
+
+				} catch (ex) {
+					this.showError(ex)
+				}
+			},
+			async clickTeachingStart() {
+
+				const _this = this
+				try {
+					if (this.mapOperationType == "station_teaching") {
+						const stationTeaching = this.teachingMode?.stations || []
+						const srcDst = `${this.startStationID}_${this.endStationID}`
+						const name =
+							`${ this.stationName(this.startStationID)}_${ this.stationName(this.endStationID)}`
+
+						const curIndex = stationTeaching.findIndex((a) => a.src_dst == srcDst)
+						if (curIndex > -1) {
+							showModal("璇ョ珯鐐归棿宸叉湁绀烘暀璺緞锛岄噸鏂拌褰曚細瑕嗙洊涔嬪墠鐨勮矾寰勩�", "鏄惁瑕侀噸鏂拌褰曪紵").then(async (res) => {
+								if (res) {
+									try {
+										_this.teachingStatus = "teaching"
+										await delTeachingMode(this.ip, [{
+											mode: "Stations",
+											name,
+											src_dst: srcDst
+
+										}])
+										stationTeaching.splice(curIndex, 1)
+										_this.teachingStart("Stations")
+									} catch (ex) {
+										this.showError(ex)
+									}
+
+								} else {
+
+									_this.teachingStatus = ""
+								}
+							})
+						} else {
+							_this.teachingStatus = "teaching"
+							_this.teachingStart("Stations")
+						}
+
+					} else {
+						this.teachingStatus = "teaching"
+						_this.teachingStart("Public")
+					}
+
+				} catch (ex) {
+					this.showError(ex)
+				}
+			},
+			clickTeachingEnd() {
+				if (this.mapOperationType == "station_teaching") {
+					this.teachingEnd("Stations")
+				} else {
+					this.teachingEnd("Public")
+				}
+
+			},
+			clickTeachingReset() {
+				const _this = this
+				showModal("宸茶褰曠殑璺緞灏嗕細琚垹闄ゃ�", "鏄惁瑕侀噸鏂拌褰曪紵").then(async (res) => {
+					if (res) {
+						try {
+							await delTeachingMode(_this.ip, [_this.teachingModeCur])
+							_this.teachingStatus = ""
+							_this.teachingMode = await getTeachingMode(_this.ip)
+
+						} catch (ex) {
+							this.showError(ex)
+						}
+					} else {
+						_this.teachingStatus = "save"
+					}
+				})
+
+			},
+			async clickTeachingSave() {
+
+				this.teachingStatus = "save"
+				try {} catch (ex) {
+					this.showError(ex)
+				}
+
+			},
+			clickTeachingFinish() {
+				this.mapOperationType = ""
+				const eventChannel = this.getOpenerEventChannel();
+				eventChannel.emit('add');
+				uni.navigateBack({
+					delta: 1, //杩斿洖灞傛暟锛�鍒欎笂涓婇〉
+				})
+			},
+			clickEndStation(e) {
+				const list = this.stationList.filter((a) => a.stationID != this.startStationID)
+				let index = 0
+
+				if (this.endStationID) {
+					index = list.findIndex((a) => a.stationID == this.endStationID)
+					if (index < 0) {
+						this.endStationID = list[0].stationID
+						index = 0
+					}
+
+				} else {
+					this.endStationID = list[0].stationID
+					index = 0
+				}
+				this.pickerView = {
+					type: "endStation",
+					list,
+					value: [index],
+					left: e.target.offsetLeft - 150,
+				}
+				this.$refs.refPopupPicker.open("bottom")
+			},
+			clickStartStation(e) {
+				const list = this.stationList.filter((a) => a.stationID != this.endStationID)
+				let index = 0
+
+				if (this.startStationID) {
+					index = list.findIndex((a) => a.stationID == this.startStationID)
+					if (index < 0) {
+						this.startStationID = list[0].stationID
+						index = 0
+					}
+
+				} else {
+					this.startStationID = list[0].stationID
+					index = 0
+				}
+				this.pickerView = {
+					type: "startStation",
+					list,
+					value: [index],
+					left: e.target.offsetLeft + 50,
+				}
+				this.$refs.refPopupPicker.open("bottom")
+			},
+			clickAddDatation() {
+				const _this = this
+				uni.navigateTo({
+					url: `/pages/station/index?ip=${this.ip}&isAdd=1`,
+					events: {
+						// 涓烘寚瀹氫簨浠舵坊鍔犱竴涓洃鍚櫒锛岃幏鍙栬鎵撳紑椤甸潰浼犻�鍒板綋鍓嶉〉闈㈢殑鏁版嵁
+						add: function(data) {
+							_this.stationList.push({
+								stationID: data.stationID,
+								name: data.name,
+								x: data.x,
+								y: data.y,
+								angle: data.angle
+							})
+						},
+					}
+				})
+			},
+			bindPickerChange(e) {
+				const val = e.detail.value
+				const val2 = val[0]
+				this.pickerView.value = val2
+				if (this.pickerView.type == "startStation") {
+					this.startStationID = this.pickerView.list[val2].stationID
+				} else if (this.pickerView.type == "endStation") {
+					this.endStationID = this.pickerView.list[val2].stationID
+				}
+			},
+			clickPickerViewItem(index) {
+				if (index == this.pickerView.value) {
+					this.$refs.refPopupPicker.close()
+				}
+			},
+			closePopupPicker() {
+				this.$refs.refPopupPicker.close()
+			},
+			async clickCalibration() {
+				try {
+					this.$refs.refPopupCalibration.close()
+					if (this.calibratioStationType == "start") {
+						const list = this.stationList
+						const curIndex = list.findIndex((a) => a.stationID == this.startStationID)
+						if (curIndex > -1) {
+							const station = {}
+							station.stationID = list[curIndex].stationID
+							station.name = list[curIndex].name
+							const infoAgv = await getAgvState(this.ip)
+							station.angle = infoAgv.angle
+							station.x = infoAgv.x
+							station.y = infoAgv.y
+							await updateStation(this.ip, station)
+							showToast(`${station.name}浣嶇疆宸叉洿鏂癭)
+							list[curIndex].angle = infoAgv.angle
+							list[curIndex].x = infoAgv.x
+							list[curIndex].y = infoAgv.y
+
+
+						}
+						// const name =
+						// 	`${ this.stationName(this.startStationID)}_${ this.stationName(this.endStationID)}`
+
+						this.teachingModeCur = {
+							mode: "Stations",
+							src_dst: `${this.startStationID}_${this.endStationID}`,
+							name: "",
+							teaching_flag: 1
+						}
+						const res2 = await teachingModeFlag(this.ip, this.teachingModeCur)
+						if (res2?.name)
+							this.teachingModeCur.name = res2.name
+
+					} else if (this.calibratioStationType == "end") {
+						const list = this.stationList
+						const curIndex = list.findIndex((a) => a.stationID == this.endStationID)
+						if (curIndex > -1) {
+							const station = {}
+							station.stationID = list[curIndex].stationID
+							station.name = list[curIndex].name
+							const infoAgv = await getAgvState(this.ip)
+							station.angle = infoAgv.angle
+							station.x = infoAgv.x
+							station.y = infoAgv.y
+							await updateStation(this.ip, station)
+							showToast(`${station.name}浣嶇疆宸叉洿鏂癭)
+							list[curIndex].angle = infoAgv.angle
+							list[curIndex].x = infoAgv.x
+							list[curIndex].y = infoAgv.y
+
+						}
+						this.teachingStatus = "end"
+						this.teachingModeCur.teaching_flag = 0
+						await teachingModeFlag(this.ip, this.teachingModeCur)
+						this.teachingMode = await getTeachingMode(this.ip)
+
+					}
+				} catch (ex) {
+					this.showError(ex)
+				}
+			},
+			async clickNoCalibration() {
+				try {
+					this.$refs.refPopupCalibration.close()
+					if (this.calibratioStationType == "start") {
+						// const name =
+						// 	`${ this.stationName(this.startStationID)}_${ this.stationName(this.endStationID)}`
+						this.teachingModeCur = {
+							mode: "Stations",
+							src_dst: `${this.startStationID}_${this.endStationID}`,
+							name: "",
+							teaching_flag: 1
+						}
+						const res = await teachingModeFlag(this.ip, this.teachingModeCur)
+						if (res?.name)
+							this.teachingModeCur.name = res.name
+
+					} else if (this.calibratioStationType == "end") {
+
+						this.teachingModeCur.teaching_flag = 0
+						await teachingModeFlag(this.ip, this.teachingModeCur)
+						this.teachingMode = await getTeachingMode(this.ip)
+
+					}
+				} catch (ex) {
+					this.showError(ex)
+				}
+			},
+			clickBackTeaching() {
+				this.$refs.refPopupCalibration.close()
+				this.teachingStatus = ""
+			},
+			showError(ex) {
+				let exStr = JSON.stringify(ex)
+				if (exStr == "{}")
+					exStr = ex
+				let tip = typeof ex.msg == "string" ? ex.msg : exStr
+				showModal(tip, "閿欒", false)
+			},
+
+
+		}
+	}
+</script>
+
+<style lang="scss">
+	.pages-teaching {
+		display: flex;
+		width: 750rpx;
+		height: 100vh;
+		background-color: #fff;
+		position: relative;
+
+
+		.view-content {
+			position: absolute;
+			top: 0;
+			left: 0;
+			right: 0;
+			bottom: 0;
+			background-color: #ddd;
+			display: flex;
+			flex-direction: column;
+		}
+
+		.map-content {
+			width: 100%;
+			display: flex;
+			flex: 1;
+			position: relative;
+
+			.content {
+				overflow: auto;
+				position: absolute;
+				left: 0;
+				right: 0;
+				bottom: 0;
+				top: 0;
+
+				.fabric {
+					width: 100%;
+					height: 100%;
+				}
+			}
+		}
+
+		.no-content {
+			margin-top: 50px;
+			padding: 20rpx 40rpx;
+			align-items: center;
+			text-align: center;
+			display: flex;
+			flex-direction: column;
+			font-size: 30rpx;
+			font-weight: 400;
+			background-color: #000fff;
+
+			.title {
+				font-size: 40rpx;
+				margin-bottom: 10rpx;
+			}
+
+
+		}
+
+		.bottom {
+			position: fixed;
+			left: 50rpx;
+			right: 50rpx;
+			bottom: 20rpx;
+			display: flex;
+
+			.bottom-content {
+				display: flex;
+				flex-direction: column;
+				width: 100%;
+				// justify-content: center;
+				// align-items: center;
+				padding: 0 10rpx;
+				padding-bottom: 10rpx;
+				background-color: #fff;
+				border-radius: 10rpx;
+				//background-color: #eee;
+
+				.title {
+					font-size: 40rpx;
+					margin-bottom: 10rpx;
+				}
+
+				.tip {
+					color: #888;
+					margin: 10rpx;
+					text-align: left;
+				}
+
+				.row-group {
+					display: flex;
+					flex-direction: row;
+					margin: 10rpx 0;
+
+				}
+
+				.disabled {
+					color: #ccc !important;
+				}
+
+				.coordinate {
+					flex: 1;
+					display: flex;
+					flex-direction: row;
+					align-items: center;
+					// .name{
+					// 	padding: 10rpx 0;
+
+					// }
+				}
+
+				.number-input {
+					flex: 1;
+					background-color: #fff;
+					padding: 10rpx;
+					border-radius: 8rpx;
+					color: #1890FF;
+				}
+
+
+				.name-input {
+					width: calc(100% - 20rpx);
+					margin-bottom: 10rpx;
+					background-color: #fff;
+					padding: 10rpx;
+					border-radius: 8rpx;
+					display: flex;
+					flex-direction: row;
+					color: #1890FF;
+
+					input {
+						flex: 1;
+					}
+				}
+			}
+
+			.img-button-group {
+				display: flex;
+				//width: 100%;
+				flex-direction: row;
+				border-radius: 10px;
+				border: 1px solid #fff;
+				font-size: 30rpx !important;
+				justify-content: space-around;
+
+				.button {
+					margin: 10rpx 20rpx;
+					height: 144rpx !important;
+					border: 0;
+					display: flex;
+					flex-direction: column;
+					background-color: #00000000;
+
+					.img {
+						margin: auto;
+						width: 72rpx;
+						height: 72rpx;
+
+					}
+
+					.ico {
+						margin: auto;
+						font-size: 72rpx;
+						color: #1890FF;
+					}
+
+					.text {
+						margin: auto;
+
+					}
+
+				}
+
+			}
+
+
+			.text-button-group {
+				display: flex;
+				width: 100%;
+				justify-content: center;
+				align-items: center;
+				flex-direction: column;
+				font-size: 30rpx !important;
+
+				.button {
+					margin: auto;
+					margin-top: 20rpx;
+					width: calc(100% - 10rpx);
+					border-radius: 30rpx;
+				}
+
+				.am-button {
+					border-radius: 30px;
+				}
+
+				.am-button-ghost {
+					border: 1px solid #1677ff !important;
+				}
+			}
+
+			.switch-type {
+				width: 100%;
+				align-items: center;
+				vertical-align: middle;
+
+				.switch-button-group {
+					width: 96%;
+					height: 32px;
+					border: 1px solid #dfdfdf;
+					border-radius: 16px;
+					background-color: #dfdfdf;
+					display: flex;
+					flex: row;
+
+					.switch-button {
+						flex: 1;
+						border-radius: 16px;
+						color: #000000A5;
+						height: 32px;
+						line-height: 32px;
+						text-align: center;
+					}
+
+					.switch-button-checked {
+						box-shadow: 0px 2px 8px 0px #0000000C;
+						background-color: #fff;
+						color: #262626;
+					}
+
+				}
+
+
+
+
+			}
+		}
+
+
+
+		.popup-content {
+			display: flex;
+			justify-content: center;
+			flex-direction: column;
+			background-color: transparent;
+		}
+
+		.popup-dialog {
+			width: 300px;
+			border-radius: 11px;
+			background-color: #fff;
+
+			.popup-dialog-title {
+				display: flex;
+				flex-direction: row;
+				justify-content: center;
+				padding-top: 15px;
+				font-size: 18px;
+				font-weight: 500;
+			}
+
+			.popup-dialog-content {
+				display: flex;
+				flex-direction: row;
+				justify-content: center;
+				align-items: center;
+				padding: 10px;
+			}
+
+			.popup-dialog-button-group {
+				display: flex;
+				flex-direction: column;
+
+				.popup-dialog-button {
+					display: flex;
+					flex-direction: row;
+					justify-content: center;
+					align-items: center;
+					height: 45px;
+					border-top: 1px solid #f5f5f5;
+					color: #1890FF;
+				}
+			}
+
+		}
+
+		.popup-content-view {
+			width: 150px;
+			height: 150px;
+			border-radius: 10rpx;
+			padding: 10rpx 20rpx;
+			background-color: #fff;
+
+			.item {
+				line-height: 75rpx;
+				text-align: center;
+				border: 0;
+
+			}
+		}
+	}
+</style>
\ No newline at end of file
diff --git a/pages/teaching/list.vue b/pages/teaching/list.vue
new file mode 100644
index 0000000..35d2ef8
--- /dev/null
+++ b/pages/teaching/list.vue
@@ -0,0 +1,491 @@
+<template>
+	<view class="pages-teaching-list">
+		<view class="view-content">
+			<view class="list-content" v-if="teachingPublic.length + teachingStation.length > 0">
+				<uni-swipe-action class="list">
+					<uni-swipe-action-item class="list-item"
+						:class="{'selected':selTeachingName == item.name,'border-top':index!= 0}"
+						v-for="(item,index) in teachingPublic" :key="index" :auto-close="true"
+						@click.stop="clickTeachingItem(item)">
+						<view class="item-title">{{item.name}}</view>
+						<view class="item-text">{{getTeachingSrcDst(item)}}</view>
+						<template v-slot:right>
+							<view class="btn-del" @click="clickDelTeachingMode('Public',item)">鍒犻櫎</view>
+						</template>
+					</uni-swipe-action-item>
+					<uni-swipe-action-item class="list-item"
+						:class="{'selected':selTeachingName == item.name,'border-top':index!= 0}"
+						v-for="(item,index) in teachingStation" :key="index" :auto-close="true"
+						@click.stop="clickTeachingItem(item)">
+						<view class="item-title">{{item.name}}</view>
+						<view class="item-text">{{getTeachingSrcDst(item)}}</view>
+						<template v-slot:right>
+							<view class="btn-del" @click="clickDelTeachingMode('Stations',item)">鍒犻櫎</view>
+						</template>
+					</uni-swipe-action-item>
+				</uni-swipe-action>
+			</view>
+			<view class="list-no-content" v-else>
+				<uni-icons color="#ccc" type="info" size="128"></uni-icons>
+				<view class="space">杩樻病鏈夌ず鏁�/view>
+			</view>
+			<view class="position-add" @click="clickAddTeaching" @touchstart='btnAddTouchStart'
+				@touchmove='btnAddTouchMove'
+				:style="{transform:`translate(${btnAddInfo.x}px,${btnAddInfo.y}px) scale(1)`}">
+				<uni-icons class="img" type="plus-filled" size="80" color="#1890FF"></uni-icons>
+			</view>
+		</view>
+
+
+	</view>
+</template>
+<script>
+	import {
+		showToast,
+		showModal,
+		session,
+	} from "@/comm/utils.js"
+	import {
+		Button
+	} from 'antd-mobile-vue-next'
+
+	import {
+		getTeachingMode,
+		delTeachingMode
+	} from "@/api/vehicle.js"
+	export default {
+		name: "PagesTeachingList",
+		components: {
+			'a-button': Button,
+		},
+		data() {
+			return {
+				ip: "",
+				teachingPublic: [],
+				teachingStation: [],
+				selTeachingName: "",
+				isEditTeaching: false,
+				btnAddInfo: {
+					lx: 0,
+					ly: 0,
+					x: 0,
+					y: 0
+				},
+			}
+		},
+		computed: {
+
+		},
+		watch: {
+
+		},
+		onLoad(option) {
+			const _this = this
+			this.ip = option.ip || ""
+
+			uni.setNavigationBarTitle({
+				title: "绀烘暀璺嚎鍒楄〃"
+			})
+
+			this.loadData()
+
+		},
+		methods: {
+			setData(obj) {
+				let that = this;
+				let keys = [];
+				let val, data;
+
+				Object.keys(obj).forEach(function(key) {
+					keys = key.split(".");
+					val = obj[key];
+					data = that.$data;
+					keys.forEach(function(key2, index) {
+						if (index + 1 == keys.length) {
+							that.$set(data, key2, val);
+						} else {
+							if (!data[key2]) {
+								that.$set(data, key2, {});
+							}
+						}
+						data = data[key2];
+					});
+				});
+			},
+			async loadData() {
+				try {
+					let btninfo = session.getValue('teaching_btn_add')
+					if (btninfo) {
+
+						if (btninfo.x > 10) {
+							btninfo.x = 10
+						}
+						if (btninfo.x > 40) {
+							btninfo.x = 40
+						}
+						this.btnAddInfo = btninfo
+					}
+					await this.loadTeachingMode()
+
+				} catch (ex) {
+
+					this.showError(ex)
+				}
+			},
+
+			async loadTeachingMode() {
+				try {
+					const {
+						data
+					} = await getTeachingMode(this.ip)
+					this.teachingPublic = data?.Public || []
+					this.teachingStation = data?.Stations || []
+				} catch (ex) {
+					this.showError(ex)
+				}
+			},
+			clickAddTeaching() {
+				const _this = this
+				uni.navigateTo({
+					url: `/pages/teaching/index?ip=${this.ip}`,
+					events: {
+						// 涓烘寚瀹氫簨浠舵坊鍔犱竴涓洃鍚櫒锛岃幏鍙栬鎵撳紑椤甸潰浼犻�鍒板綋鍓嶉〉闈㈢殑鏁版嵁
+						add: function(data) {
+							_this.loadTeachingMode()
+						},
+					}
+
+				})
+			},
+			btnAddTouchStart(e) {
+				this.btnAddInfo.lx = e.touches[0].clientX;
+				this.btnAddInfo.ly = e.touches[0].clientY;
+			},
+			btnAddTouchMove(e) {
+
+				if (this.btnAddInfo.ly < 40) {
+
+					this.btnAddInfo.x += (e.touches[0].clientX - this.btnAddInfo.lx)
+					this.btnAddInfo.lx = e.touches[0].clientX;
+					this.btnAddInfo.ly = e.touches[0].clientY;
+					if (this.btnAddInfo.x < 50 - this.windowWidth) {
+						this.btnAddInfo.x = 50 - this.windowWidth
+					}
+					if (this.btnAddInfo.x > 40) {
+						this.btnAddInfo.x = 40
+					}
+					session.setValue('teaching_btn_add', this.btnAddInfo)
+					return
+				}
+				if (this.btnAddInfo.lx < 40) {
+					this.btnAddInfo.y += (e.touches[0].clientY - this.btnAddInfo.ly)
+					this.btnAddInfo.lx = e.touches[0].clientX;
+					this.btnAddInfo.ly = e.touches[0].clientY;
+					if (this.btnAddInfo.y > 80) {
+						this.btnAddInfo.y = 80
+					}
+					session.setValue('teaching_btn_add', this.btnAddInfo)
+					return
+				}
+
+				this.btnAddInfo.x += (e.touches[0].clientX - this.btnAddInfo.lx)
+				this.btnAddInfo.y += (e.touches[0].clientY - this.btnAddInfo.ly)
+				this.btnAddInfo.lx = e.touches[0].clientX;
+				this.btnAddInfo.ly = e.touches[0].clientY;
+
+
+				if (this.btnAddInfo.x < 50 - this.windowWidth) {
+					this.btnAddInfo.x = 50 - this.windowWidth
+				}
+				if (this.btnAddInfo.x > 40) {
+					this.btnAddInfo.x = 40
+				}
+				if (this.btnAddInfo.y > 80) {
+					this.btnAddInfo.y = 80
+				}
+				session.setValue('teaching_btn_add', this.btnAddInfo)
+			},
+
+			clickTeachingItem(item) {
+				this.setData({
+					isAdd: false
+				})
+				this.selTeachingName = item.name
+
+			},
+			getTeachingSrcDst(item) {
+				const list = item.pos_list || []
+				let tip = ""
+				if (list.length > 1) {
+					tip = `(${Number(list[0].x).toFixed(2)},${Number(list[0].y).toFixed(2)}) (${Number(list[1].x).toFixed(2)},${Number(list[1].y).toFixed(2)})`
+				}
+				if (list.length == 1) {
+					tip = `(${Number(list[0].x).toFixed(2)},${Number(list[0].y).toFixed(2)})`
+				}
+				return tip
+			},
+			clickDelTeachingMode(mode, item) {
+				showModal("纭鍒犻櫎绀烘暀", "璀﹀憡").then((res) => {
+					if (res) {
+						this.deleteTeachingMode(mode, item)
+					}
+				})
+			},
+
+			async deleteTeachingMode(mode, item) {
+				try {
+					item.mode = mode
+					await delTeachingMode(this.ip, [item])
+					if (mode == "Public") {
+						const list = this.teachingPublic
+						const index = list.findIndex((a) => {
+							return a.name == item.name
+						})
+						if (index < 0)
+							return
+						list.splice(index, 1)
+						this.teachingPublic = [...list]
+
+					} else if (mode == "Stations") {
+						const list = this.teachingStation
+						const index = list.findIndex((a) => {
+							return a.name == item.name
+						})
+						if (index < 0)
+							return
+						list.splice(index, 1)
+						this.teachingStation = [...list]
+
+					}
+
+				} catch (ex) {
+					this.showError(ex)
+				}
+
+			},
+
+			showError(ex) {
+				let exStr = JSON.stringify(ex)
+				if (exStr == "{}")
+					exStr = ex
+				let tip = typeof ex.msg == "string" ? ex.msg : exStr
+				showModal(tip, "閿欒", false)
+			},
+
+
+		}
+	}
+</script>
+
+<style lang="scss">
+	.pages-teaching-list {
+		display: flex;
+		width: 750rpx;
+		height: 100vh;
+		position: relative;
+
+		.view-content {
+			position: absolute;
+			top: 0;
+			left: 0;
+			right: 0;
+			bottom: 0;
+			display: flex;
+			flex-direction: column;
+
+			.position-add {
+				position: fixed;
+				right: 10px;
+				bottom: 40px;
+			}
+		}
+
+		.map-content {
+			width: 100%;
+			display: flex;
+			flex: 1;
+			position: relative;
+
+			.content {
+				overflow: auto;
+				position: absolute;
+				left: 0;
+				right: 0;
+				bottom: 0;
+				top: 0;
+
+				.fabric {
+					width: 100%;
+					height: 100%;
+					background-color: #fff;
+				}
+			}
+
+			.position-site {
+				display: flex;
+				position: absolute;
+				margin: 2rpx;
+				right: 40rpx;
+				bottom: 500rpx;
+				flex-direction: row;
+				padding: 10rpx;
+				border-radius: 10rpx;
+				background-color: #fff;
+				border: 2rpx solid #1890FF;
+				justify-content: center;
+				align-items: center;
+				color: #1890FF;
+				font-size: 32rpx;
+
+				.img {
+					width: 40rpx;
+					height: 40rpx;
+					margin: 0 10rpx;
+				}
+			}
+
+
+
+		}
+
+		.list-content {
+			display: flex;
+			width: 100%;
+			padding: 20rpx;
+			flex: 1;
+			flex-direction: column;
+			overflow-y: auto;
+			overflow-x: hidden;
+
+			.list {
+				border-radius: 10px;
+				background-color: #fff;
+
+
+
+				.list-item {
+					padding: 10rpx 0;
+
+					.item-title {
+						font-size: 32rpx;
+						padding:  10rpx 20rpx;
+					}
+
+
+					.item-text {
+						font-size: 28rpx;
+						color: #888;
+						padding: 10rpx 20rpx;
+					}
+				}
+
+				.border-top {
+					border-top: 1px solid #ddd;
+				}
+
+				.selected {
+					background-color: #eee;
+				}
+
+				.btn-del {
+					margin: 0 10rpx;
+					display: flex;
+					padding: 0 10rpx;
+					background-color: #FF4D4F;
+					font-weight: 700;
+					color: #fff;
+					justify-content: center;
+					align-items: center;
+				}
+
+			}
+		}
+
+		.list-no-content {
+			margin-top: 50px;
+			padding: 20rpx 40rpx;
+			align-items: center;
+			text-align: center;
+			display: flex;
+			flex-direction: column;
+			font-size: 30rpx;
+			font-weight: 400;
+
+			.img {
+				width: 212rpx;
+				height: 212rpx;
+				color: #ddd;
+			}
+
+			.space {
+				margin-top: 20rpx;
+			}
+
+		}
+
+		.bottom {
+			position: fixed;
+			left: 50rpx;
+			right: 50rpx;
+			bottom: 20rpx;
+			display: flex;
+
+			.bottom-content {
+				display: flex;
+				flex-direction: column;
+				width: 100%;
+				// justify-content: center;
+				// align-items: center;
+				padding: 0 10rpx;
+				padding-bottom: 10rpx;
+				background-color: #fff;
+				border-radius: 10rpx;
+
+
+
+			}
+
+			.img-button-group {
+				display: flex;
+				//width: 100%;
+				flex-direction: row;
+				border-radius: 10px;
+				border: 1px solid #fff;
+				font-size: 30rpx !important;
+				justify-content: space-around;
+
+				.button {
+					margin: 10rpx 20rpx;
+
+					height: 144rpx !important;
+					border: 0;
+					display: flex;
+					flex-direction: column;
+					background-color: #00000000;
+
+					.img {
+						margin: auto;
+						width: 72rpx;
+						height: 72rpx;
+
+					}
+
+					.ico {
+						margin: auto;
+						font-size: 72rpx;
+						color: #1890FF;
+					}
+
+					.text {
+						margin: auto;
+
+					}
+				}
+
+			}
+
+
+		}
+
+	}
+</style>
\ No newline at end of file
diff --git a/pages/vehicle/index.vue b/pages/vehicle/index.vue
new file mode 100644
index 0000000..02409e3
--- /dev/null
+++ b/pages/vehicle/index.vue
@@ -0,0 +1,8 @@
+<template>
+</template>
+
+<script>
+</script>
+
+<style>
+</style>
\ No newline at end of file
diff --git a/static/images/angle-135.svg b/static/images/angle-135.svg
new file mode 100644
index 0000000..a0341eb
--- /dev/null
+++ b/static/images/angle-135.svg
@@ -0,0 +1,4 @@
+<svg width="64" height="21" viewBox="0 0 64 21" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="64" height="21" rx="4" fill="#D4B106"/>
+<path d="M15.4861 12.64V11.45H19.1821V12.64H15.4861ZM21.022 16V14.67H23.29V7.502H21.442V6.48C21.9274 6.396 22.3474 6.28867 22.702 6.158C23.066 6.02733 23.3974 5.86867 23.696 5.682H24.914V14.67H26.916V16H21.022ZM31.5684 16.196C31.0271 16.196 30.5464 16.1307 30.1264 16C29.7157 15.8693 29.3517 15.6967 29.0344 15.482C28.7171 15.258 28.4417 15.02 28.2084 14.768L28.9924 13.732C29.3004 14.0307 29.6504 14.292 30.0424 14.516C30.4344 14.74 30.8964 14.852 31.4284 14.852C31.8204 14.852 32.1611 14.7867 32.4504 14.656C32.7397 14.516 32.9637 14.32 33.1224 14.068C33.2904 13.816 33.3744 13.508 33.3744 13.144C33.3744 12.7707 33.2811 12.444 33.0944 12.164C32.9171 11.8747 32.6044 11.6553 32.1564 11.506C31.7177 11.3473 31.1111 11.268 30.3364 11.268V10.064C31.0177 10.064 31.5497 9.98933 31.9324 9.84C32.3244 9.68133 32.6044 9.46667 32.7724 9.196C32.9497 8.92533 33.0384 8.61733 33.0384 8.272C33.0384 7.824 32.8984 7.46933 32.6184 7.208C32.3384 6.93733 31.9511 6.802 31.4564 6.802C31.0644 6.802 30.6957 6.89067 30.3504 7.068C30.0144 7.236 29.6971 7.46467 29.3984 7.754L28.5584 6.746C28.9691 6.37267 29.4171 6.074 29.9024 5.85C30.3877 5.61667 30.9244 5.5 31.5124 5.5C32.1284 5.5 32.6744 5.60733 33.1504 5.822C33.6264 6.02733 33.9997 6.326 34.2704 6.718C34.5411 7.11 34.6764 7.59067 34.6764 8.16C34.6764 8.748 34.5131 9.24733 34.1864 9.658C33.8691 10.0687 33.4397 10.3767 32.8984 10.582V10.638C33.2904 10.7407 33.6451 10.9087 33.9624 11.142C34.2891 11.366 34.5457 11.6553 34.7324 12.01C34.9191 12.3647 35.0124 12.7707 35.0124 13.228C35.0124 13.844 34.8537 14.376 34.5364 14.824C34.2284 15.2627 33.8131 15.6033 33.2904 15.846C32.7677 16.0793 32.1937 16.196 31.5684 16.196ZM39.5528 16.196C39.0208 16.196 38.5448 16.1307 38.1248 16C37.7048 15.8693 37.3361 15.6967 37.0188 15.482C36.7014 15.2673 36.4214 15.0433 36.1788 14.81L36.9488 13.76C37.1448 13.956 37.3594 14.138 37.5928 14.306C37.8261 14.4647 38.0874 14.5953 38.3768 14.698C38.6754 14.8007 39.0068 14.852 39.3708 14.852C39.7534 14.852 40.0988 14.768 40.4068 14.6C40.7148 14.4227 40.9574 14.1707 41.1348 13.844C41.3121 13.508 41.4008 13.1113 41.4008 12.654C41.4008 11.982 41.2188 11.4593 40.8548 11.086C40.5001 10.7127 40.0288 10.526 39.4408 10.526C39.1141 10.526 38.8341 10.5727 38.6008 10.666C38.3674 10.7593 38.1014 10.904 37.8028 11.1L37.0048 10.582L37.3128 5.682H42.5348V7.054H38.7128L38.4748 9.686C38.6988 9.574 38.9228 9.49 39.1468 9.434C39.3708 9.36867 39.6181 9.336 39.8888 9.336C40.4674 9.336 40.9948 9.45267 41.4708 9.686C41.9468 9.91933 42.3248 10.2787 42.6048 10.764C42.8848 11.24 43.0248 11.856 43.0248 12.612C43.0248 13.368 42.8614 14.0167 42.5348 14.558C42.2081 15.09 41.7788 15.496 41.2468 15.776C40.7241 16.056 40.1594 16.196 39.5528 16.196ZM46.4872 9.392C46.1138 9.392 45.7685 9.308 45.4512 9.14C45.1338 8.96267 44.8818 8.72 44.6952 8.412C44.5085 8.09467 44.4152 7.726 44.4152 7.306C44.4152 6.886 44.5085 6.522 44.6952 6.214C44.8818 5.89667 45.1338 5.64933 45.4512 5.472C45.7685 5.29467 46.1138 5.206 46.4872 5.206C46.8605 5.206 47.2012 5.29467 47.5092 5.472C47.8265 5.64933 48.0785 5.89667 48.2652 6.214C48.4518 6.522 48.5452 6.886 48.5452 7.306C48.5452 7.726 48.4518 8.09467 48.2652 8.412C48.0785 8.72 47.8265 8.96267 47.5092 9.14C47.2012 9.308 46.8605 9.392 46.4872 9.392ZM46.4872 8.552C46.8232 8.552 47.0985 8.43533 47.3132 8.202C47.5278 7.96867 47.6352 7.67 47.6352 7.306C47.6352 6.93267 47.5278 6.62933 47.3132 6.396C47.0985 6.16267 46.8232 6.046 46.4872 6.046C46.1512 6.046 45.8758 6.16267 45.6612 6.396C45.4465 6.62933 45.3392 6.93267 45.3392 7.306C45.3392 7.67 45.4465 7.96867 45.6612 8.202C45.8758 8.43533 46.1512 8.552 46.4872 8.552Z" fill="#FFEC3D"/>
+</svg>
diff --git a/static/images/angle-45.svg b/static/images/angle-45.svg
new file mode 100644
index 0000000..864bc6f
--- /dev/null
+++ b/static/images/angle-45.svg
@@ -0,0 +1,4 @@
+<svg width="64" height="21" viewBox="0 0 64 21" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="64" height="21" rx="4" fill="#7CB305"/>
+<path d="M19.4783 12.64V11.45H23.1743V12.64H19.4783ZM28.5702 16V9.28C28.5702 9 28.5796 8.66867 28.5982 8.286C28.6169 7.894 28.6309 7.558 28.6402 7.278H28.5842C28.4536 7.53933 28.3182 7.80533 28.1782 8.076C28.0476 8.34667 27.9076 8.61267 27.7582 8.874L25.7422 11.968H31.3842V13.228H24.1042V12.15L28.2062 5.682H30.0822V16H28.5702ZM35.5606 16.196C35.0286 16.196 34.5526 16.1307 34.1326 16C33.7126 15.8693 33.3439 15.6967 33.0266 15.482C32.7093 15.2673 32.4293 15.0433 32.1866 14.81L32.9566 13.76C33.1526 13.956 33.3673 14.138 33.6006 14.306C33.8339 14.4647 34.0953 14.5953 34.3846 14.698C34.6833 14.8007 35.0146 14.852 35.3786 14.852C35.7613 14.852 36.1066 14.768 36.4146 14.6C36.7226 14.4227 36.9653 14.1707 37.1426 13.844C37.3199 13.508 37.4086 13.1113 37.4086 12.654C37.4086 11.982 37.2266 11.4593 36.8626 11.086C36.5079 10.7127 36.0366 10.526 35.4486 10.526C35.1219 10.526 34.8419 10.5727 34.6086 10.666C34.3753 10.7593 34.1093 10.904 33.8106 11.1L33.0126 10.582L33.3206 5.682H38.5426V7.054H34.7206L34.4826 9.686C34.7066 9.574 34.9306 9.49 35.1546 9.434C35.3786 9.36867 35.6259 9.336 35.8966 9.336C36.4753 9.336 37.0026 9.45267 37.4786 9.686C37.9546 9.91933 38.3326 10.2787 38.6126 10.764C38.8926 11.24 39.0326 11.856 39.0326 12.612C39.0326 13.368 38.8693 14.0167 38.5426 14.558C38.2159 15.09 37.7866 15.496 37.2546 15.776C36.7319 16.056 36.1673 16.196 35.5606 16.196ZM42.495 9.392C42.1216 9.392 41.7763 9.308 41.459 9.14C41.1416 8.96267 40.8896 8.72 40.703 8.412C40.5163 8.09467 40.423 7.726 40.423 7.306C40.423 6.886 40.5163 6.522 40.703 6.214C40.8896 5.89667 41.1416 5.64933 41.459 5.472C41.7763 5.29467 42.1216 5.206 42.495 5.206C42.8683 5.206 43.209 5.29467 43.517 5.472C43.8343 5.64933 44.0863 5.89667 44.273 6.214C44.4596 6.522 44.553 6.886 44.553 7.306C44.553 7.726 44.4596 8.09467 44.273 8.412C44.0863 8.72 43.8343 8.96267 43.517 9.14C43.209 9.308 42.8683 9.392 42.495 9.392ZM42.495 8.552C42.831 8.552 43.1063 8.43533 43.321 8.202C43.5356 7.96867 43.643 7.67 43.643 7.306C43.643 6.93267 43.5356 6.62933 43.321 6.396C43.1063 6.16267 42.831 6.046 42.495 6.046C42.159 6.046 41.8836 6.16267 41.669 6.396C41.4543 6.62933 41.347 6.93267 41.347 7.306C41.347 7.67 41.4543 7.96867 41.669 8.202C41.8836 8.43533 42.159 8.552 42.495 8.552Z" fill="#D3F261"/>
+</svg>
diff --git a/static/images/angle-90.svg b/static/images/angle-90.svg
new file mode 100644
index 0000000..5018aae
--- /dev/null
+++ b/static/images/angle-90.svg
@@ -0,0 +1,4 @@
+<svg width="64" height="21" viewBox="0 0 64 21" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="64" height="21" rx="4" fill="#D3F261"/>
+<path d="M19.4783 12.64V11.45H23.1743V12.64H19.4783ZM27.2402 16.196C26.6429 16.196 26.1249 16.0887 25.6862 15.874C25.2569 15.65 24.8929 15.3887 24.5942 15.09L25.4762 14.082C25.6816 14.3153 25.9336 14.502 26.2322 14.642C26.5309 14.782 26.8389 14.852 27.1562 14.852C27.4829 14.852 27.7909 14.7773 28.0802 14.628C28.3789 14.4787 28.6356 14.236 28.8502 13.9C29.0742 13.564 29.2469 13.116 29.3682 12.556C29.4989 11.996 29.5642 11.31 29.5642 10.498C29.5642 9.63933 29.4802 8.93467 29.3122 8.384C29.1442 7.824 28.9062 7.41333 28.5982 7.152C28.2996 6.88133 27.9402 6.746 27.5202 6.746C27.2216 6.746 26.9509 6.83467 26.7082 7.012C26.4656 7.18 26.2742 7.42267 26.1342 7.74C25.9942 8.05733 25.9242 8.44 25.9242 8.888C25.9242 9.32667 25.9849 9.7 26.1062 10.008C26.2369 10.316 26.4282 10.554 26.6802 10.722C26.9322 10.8807 27.2356 10.96 27.5902 10.96C27.9169 10.96 28.2529 10.8573 28.5982 10.652C28.9436 10.4467 29.2702 10.1107 29.5782 9.644L29.6482 10.834C29.4522 11.0953 29.2236 11.324 28.9622 11.52C28.7009 11.716 28.4302 11.87 28.1502 11.982C27.8702 12.0847 27.5902 12.136 27.3102 12.136C26.7409 12.136 26.2369 12.0147 25.7982 11.772C25.3689 11.5293 25.0282 11.17 24.7762 10.694C24.5336 10.2087 24.4122 9.60667 24.4122 8.888C24.4122 8.20667 24.5522 7.614 24.8322 7.11C25.1216 6.59667 25.4996 6.2 25.9662 5.92C26.4329 5.64 26.9416 5.5 27.4922 5.5C27.9869 5.5 28.4489 5.60267 28.8782 5.808C29.3169 6.004 29.6949 6.30733 30.0122 6.718C30.3389 7.12867 30.5956 7.64667 30.7822 8.272C30.9689 8.89733 31.0622 9.63933 31.0622 10.498C31.0622 11.506 30.9596 12.374 30.7542 13.102C30.5489 13.8207 30.2642 14.4087 29.9002 14.866C29.5362 15.314 29.1256 15.65 28.6682 15.874C28.2109 16.0887 27.7349 16.196 27.2402 16.196ZM35.8126 16.196C35.1406 16.196 34.5526 15.9953 34.0486 15.594C33.5446 15.1927 33.1526 14.5953 32.8726 13.802C32.6019 12.9993 32.4666 12.0007 32.4666 10.806C32.4666 9.61133 32.6019 8.622 32.8726 7.838C33.1526 7.054 33.5446 6.47067 34.0486 6.088C34.5526 5.696 35.1406 5.5 35.8126 5.5C36.4846 5.5 37.0679 5.696 37.5626 6.088C38.0573 6.48 38.4399 7.068 38.7106 7.852C38.9906 8.62667 39.1306 9.61133 39.1306 10.806C39.1306 12.0007 38.9906 12.9993 38.7106 13.802C38.4399 14.5953 38.0573 15.1927 37.5626 15.594C37.0679 15.9953 36.4846 16.196 35.8126 16.196ZM35.8126 14.908C36.1579 14.908 36.4659 14.7727 36.7366 14.502C37.0073 14.2313 37.2173 13.7973 37.3666 13.2C37.5159 12.5933 37.5906 11.7953 37.5906 10.806C37.5906 9.81667 37.5159 9.028 37.3666 8.44C37.2173 7.852 37.0073 7.42733 36.7366 7.166C36.4659 6.90467 36.1579 6.774 35.8126 6.774C35.4673 6.774 35.1593 6.90467 34.8886 7.166C34.6179 7.42733 34.4033 7.852 34.2446 8.44C34.0953 9.028 34.0206 9.81667 34.0206 10.806C34.0206 11.7953 34.0953 12.5933 34.2446 13.2C34.4033 13.7973 34.6179 14.2313 34.8886 14.502C35.1593 14.7727 35.4673 14.908 35.8126 14.908ZM42.495 9.392C42.1216 9.392 41.7763 9.308 41.459 9.14C41.1416 8.96267 40.8896 8.72 40.703 8.412C40.5163 8.09467 40.423 7.726 40.423 7.306C40.423 6.886 40.5163 6.522 40.703 6.214C40.8896 5.89667 41.1416 5.64933 41.459 5.472C41.7763 5.29467 42.1216 5.206 42.495 5.206C42.8683 5.206 43.209 5.29467 43.517 5.472C43.8343 5.64933 44.0863 5.89667 44.273 6.214C44.4596 6.522 44.553 6.886 44.553 7.306C44.553 7.726 44.4596 8.09467 44.273 8.412C44.0863 8.72 43.8343 8.96267 43.517 9.14C43.209 9.308 42.8683 9.392 42.495 9.392ZM42.495 8.552C42.831 8.552 43.1063 8.43533 43.321 8.202C43.5356 7.96867 43.643 7.67 43.643 7.306C43.643 6.93267 43.5356 6.62933 43.321 6.396C43.1063 6.16267 42.831 6.046 42.495 6.046C42.159 6.046 41.8836 6.16267 41.669 6.396C41.4543 6.62933 41.347 6.93267 41.347 7.306C41.347 7.67 41.4543 7.96867 41.669 8.202C41.8836 8.43533 42.159 8.552 42.495 8.552Z" fill="#7CB305"/>
+</svg>
diff --git a/static/images/angle0.svg b/static/images/angle0.svg
new file mode 100644
index 0000000..4965556
--- /dev/null
+++ b/static/images/angle0.svg
@@ -0,0 +1,4 @@
+<svg width="64" height="21" viewBox="0 0 64 21" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="64" height="21" rx="4" fill="#FFA39E"/>
+<path d="M29.3185 16.196C28.6465 16.196 28.0585 15.9953 27.5545 15.594C27.0505 15.1927 26.6585 14.5953 26.3785 13.802C26.1078 12.9993 25.9725 12.0007 25.9725 10.806C25.9725 9.61133 26.1078 8.622 26.3785 7.838C26.6585 7.054 27.0505 6.47067 27.5545 6.088C28.0585 5.696 28.6465 5.5 29.3185 5.5C29.9905 5.5 30.5738 5.696 31.0685 6.088C31.5631 6.48 31.9458 7.068 32.2165 7.852C32.4965 8.62667 32.6365 9.61133 32.6365 10.806C32.6365 12.0007 32.4965 12.9993 32.2165 13.802C31.9458 14.5953 31.5631 15.1927 31.0685 15.594C30.5738 15.9953 29.9905 16.196 29.3185 16.196ZM29.3185 14.908C29.6638 14.908 29.9718 14.7727 30.2425 14.502C30.5131 14.2313 30.7231 13.7973 30.8725 13.2C31.0218 12.5933 31.0965 11.7953 31.0965 10.806C31.0965 9.81667 31.0218 9.028 30.8725 8.44C30.7231 7.852 30.5131 7.42733 30.2425 7.166C29.9718 6.90467 29.6638 6.774 29.3185 6.774C28.9731 6.774 28.6651 6.90467 28.3945 7.166C28.1238 7.42733 27.9091 7.852 27.7505 8.44C27.6011 9.028 27.5265 9.81667 27.5265 10.806C27.5265 11.7953 27.6011 12.5933 27.7505 13.2C27.9091 13.7973 28.1238 14.2313 28.3945 14.502C28.6651 14.7727 28.9731 14.908 29.3185 14.908ZM36.0008 9.392C35.6275 9.392 35.2822 9.308 34.9648 9.14C34.6475 8.96267 34.3955 8.72 34.2088 8.412C34.0222 8.09467 33.9288 7.726 33.9288 7.306C33.9288 6.886 34.0222 6.522 34.2088 6.214C34.3955 5.89667 34.6475 5.64933 34.9648 5.472C35.2822 5.29467 35.6275 5.206 36.0008 5.206C36.3742 5.206 36.7148 5.29467 37.0228 5.472C37.3402 5.64933 37.5922 5.89667 37.7788 6.214C37.9655 6.522 38.0588 6.886 38.0588 7.306C38.0588 7.726 37.9655 8.09467 37.7788 8.412C37.5922 8.72 37.3402 8.96267 37.0228 9.14C36.7148 9.308 36.3742 9.392 36.0008 9.392ZM36.0008 8.552C36.3368 8.552 36.6122 8.43533 36.8268 8.202C37.0415 7.96867 37.1488 7.67 37.1488 7.306C37.1488 6.93267 37.0415 6.62933 36.8268 6.396C36.6122 6.16267 36.3368 6.046 36.0008 6.046C35.6648 6.046 35.3895 6.16267 35.1748 6.396C34.9602 6.62933 34.8528 6.93267 34.8528 7.306C34.8528 7.67 34.9602 7.96867 35.1748 8.202C35.3895 8.43533 35.6648 8.552 36.0008 8.552Z" fill="#F5222D"/>
+</svg>
diff --git a/static/images/angle135.svg b/static/images/angle135.svg
new file mode 100644
index 0000000..e9cc60b
--- /dev/null
+++ b/static/images/angle135.svg
@@ -0,0 +1,4 @@
+<svg width="64" height="21" viewBox="0 0 64 21" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="64" height="21" rx="4" fill="#FA8C16"/>
+<path d="M18.5201 16V14.67H20.7881V7.502H18.9401V6.48C19.4254 6.396 19.8454 6.28867 20.2001 6.158C20.5641 6.02733 20.8954 5.86867 21.1941 5.682H22.4121V14.67H24.4141V16H18.5201ZM29.0665 16.196C28.5251 16.196 28.0445 16.1307 27.6245 16C27.2138 15.8693 26.8498 15.6967 26.5325 15.482C26.2151 15.258 25.9398 15.02 25.7065 14.768L26.4905 13.732C26.7985 14.0307 27.1485 14.292 27.5405 14.516C27.9325 14.74 28.3945 14.852 28.9265 14.852C29.3185 14.852 29.6591 14.7867 29.9485 14.656C30.2378 14.516 30.4618 14.32 30.6205 14.068C30.7885 13.816 30.8725 13.508 30.8725 13.144C30.8725 12.7707 30.7791 12.444 30.5925 12.164C30.4151 11.8747 30.1025 11.6553 29.6545 11.506C29.2158 11.3473 28.6091 11.268 27.8345 11.268V10.064C28.5158 10.064 29.0478 9.98933 29.4305 9.84C29.8225 9.68133 30.1025 9.46667 30.2705 9.196C30.4478 8.92533 30.5365 8.61733 30.5365 8.272C30.5365 7.824 30.3965 7.46933 30.1165 7.208C29.8365 6.93733 29.4491 6.802 28.9545 6.802C28.5625 6.802 28.1938 6.89067 27.8485 7.068C27.5125 7.236 27.1951 7.46467 26.8965 7.754L26.0565 6.746C26.4671 6.37267 26.9151 6.074 27.4005 5.85C27.8858 5.61667 28.4225 5.5 29.0105 5.5C29.6265 5.5 30.1725 5.60733 30.6485 5.822C31.1245 6.02733 31.4978 6.326 31.7685 6.718C32.0391 7.11 32.1745 7.59067 32.1745 8.16C32.1745 8.748 32.0111 9.24733 31.6845 9.658C31.3671 10.0687 30.9378 10.3767 30.3965 10.582V10.638C30.7885 10.7407 31.1431 10.9087 31.4605 11.142C31.7871 11.366 32.0438 11.6553 32.2305 12.01C32.4171 12.3647 32.5105 12.7707 32.5105 13.228C32.5105 13.844 32.3518 14.376 32.0345 14.824C31.7265 15.2627 31.3111 15.6033 30.7885 15.846C30.2658 16.0793 29.6918 16.196 29.0665 16.196ZM37.0508 16.196C36.5188 16.196 36.0428 16.1307 35.6228 16C35.2028 15.8693 34.8342 15.6967 34.5168 15.482C34.1995 15.2673 33.9195 15.0433 33.6768 14.81L34.4468 13.76C34.6428 13.956 34.8575 14.138 35.0908 14.306C35.3242 14.4647 35.5855 14.5953 35.8748 14.698C36.1735 14.8007 36.5048 14.852 36.8688 14.852C37.2515 14.852 37.5968 14.768 37.9048 14.6C38.2128 14.4227 38.4555 14.1707 38.6328 13.844C38.8102 13.508 38.8988 13.1113 38.8988 12.654C38.8988 11.982 38.7168 11.4593 38.3528 11.086C37.9982 10.7127 37.5268 10.526 36.9388 10.526C36.6122 10.526 36.3322 10.5727 36.0988 10.666C35.8655 10.7593 35.5995 10.904 35.3008 11.1L34.5028 10.582L34.8108 5.682H40.0328V7.054H36.2108L35.9728 9.686C36.1968 9.574 36.4208 9.49 36.6448 9.434C36.8688 9.36867 37.1162 9.336 37.3868 9.336C37.9655 9.336 38.4928 9.45267 38.9688 9.686C39.4448 9.91933 39.8228 10.2787 40.1028 10.764C40.3828 11.24 40.5228 11.856 40.5228 12.612C40.5228 13.368 40.3595 14.0167 40.0328 14.558C39.7062 15.09 39.2768 15.496 38.7448 15.776C38.2222 16.056 37.6575 16.196 37.0508 16.196ZM43.9852 9.392C43.6119 9.392 43.2665 9.308 42.9492 9.14C42.6319 8.96267 42.3799 8.72 42.1932 8.412C42.0065 8.09467 41.9132 7.726 41.9132 7.306C41.9132 6.886 42.0065 6.522 42.1932 6.214C42.3799 5.89667 42.6319 5.64933 42.9492 5.472C43.2665 5.29467 43.6119 5.206 43.9852 5.206C44.3585 5.206 44.6992 5.29467 45.0072 5.472C45.3245 5.64933 45.5765 5.89667 45.7632 6.214C45.9499 6.522 46.0432 6.886 46.0432 7.306C46.0432 7.726 45.9499 8.09467 45.7632 8.412C45.5765 8.72 45.3245 8.96267 45.0072 9.14C44.6992 9.308 44.3585 9.392 43.9852 9.392ZM43.9852 8.552C44.3212 8.552 44.5965 8.43533 44.8112 8.202C45.0259 7.96867 45.1332 7.67 45.1332 7.306C45.1332 6.93267 45.0259 6.62933 44.8112 6.396C44.5965 6.16267 44.3212 6.046 43.9852 6.046C43.6492 6.046 43.3739 6.16267 43.1592 6.396C42.9445 6.62933 42.8372 6.93267 42.8372 7.306C42.8372 7.67 42.9445 7.96867 43.1592 8.202C43.3739 8.43533 43.6492 8.552 43.9852 8.552Z" fill="#FFD591"/>
+</svg>
diff --git a/static/images/angle180.svg b/static/images/angle180.svg
new file mode 100644
index 0000000..2337e52
--- /dev/null
+++ b/static/images/angle180.svg
@@ -0,0 +1,4 @@
+<svg width="64" height="21" viewBox="0 0 64 21" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="64" height="21" rx="4" fill="#FFEC3D"/>
+<path d="M18.5201 16V14.67H20.7881V7.502H18.9401V6.48C19.4254 6.396 19.8454 6.28867 20.2001 6.158C20.5641 6.02733 20.8954 5.86867 21.1941 5.682H22.4121V14.67H24.4141V16H18.5201ZM29.3185 16.196C28.6745 16.196 28.1005 16.0793 27.5965 15.846C27.0925 15.6033 26.6911 15.2767 26.3925 14.866C26.1031 14.446 25.9585 13.97 25.9585 13.438C25.9585 12.9807 26.0471 12.5747 26.2245 12.22C26.4018 11.8653 26.6305 11.562 26.9105 11.31C27.1905 11.0487 27.4845 10.834 27.7925 10.666V10.596C27.4191 10.3253 27.0971 9.994 26.8265 9.602C26.5558 9.20067 26.4205 8.72933 26.4205 8.188C26.4205 7.656 26.5465 7.18933 26.7985 6.788C27.0598 6.38667 27.4098 6.07867 27.8485 5.864C28.2965 5.64 28.8051 5.528 29.3745 5.528C29.9718 5.528 30.4851 5.64467 30.9145 5.878C31.3438 6.11133 31.6751 6.43333 31.9085 6.844C32.1511 7.24533 32.2725 7.71667 32.2725 8.258C32.2725 8.60333 32.2025 8.93 32.0625 9.238C31.9225 9.546 31.7498 9.826 31.5445 10.078C31.3485 10.3207 31.1385 10.5213 30.9145 10.68V10.75C31.2318 10.918 31.5211 11.128 31.7825 11.38C32.0438 11.6227 32.2538 11.9167 32.4125 12.262C32.5711 12.6073 32.6505 13.0133 32.6505 13.48C32.6505 13.984 32.5105 14.4413 32.2305 14.852C31.9598 15.2627 31.5725 15.5893 31.0685 15.832C30.5738 16.0747 29.9905 16.196 29.3185 16.196ZM30.0045 10.274C30.3031 9.98467 30.5271 9.68133 30.6765 9.364C30.8351 9.03733 30.9145 8.69667 30.9145 8.342C30.9145 8.034 30.8538 7.754 30.7325 7.502C30.6111 7.25 30.4291 7.054 30.1865 6.914C29.9531 6.76467 29.6685 6.69 29.3325 6.69C28.9125 6.69 28.5625 6.82533 28.2825 7.096C28.0025 7.35733 27.8625 7.72133 27.8625 8.188C27.8625 8.56133 27.9605 8.874 28.1565 9.126C28.3525 9.378 28.6138 9.59267 28.9405 9.77C29.2671 9.94733 29.6218 10.1153 30.0045 10.274ZM29.3605 15.02C29.7058 15.02 30.0091 14.9547 30.2705 14.824C30.5411 14.6933 30.7511 14.5113 30.9005 14.278C31.0498 14.0353 31.1245 13.7507 31.1245 13.424C31.1245 13.116 31.0591 12.85 30.9285 12.626C30.7978 12.3927 30.6158 12.192 30.3825 12.024C30.1585 11.856 29.8925 11.702 29.5845 11.562C29.2765 11.4127 28.9451 11.268 28.5905 11.128C28.2358 11.38 27.9465 11.6927 27.7225 12.066C27.4985 12.43 27.3865 12.8313 27.3865 13.27C27.3865 13.6153 27.4705 13.9187 27.6385 14.18C27.8158 14.4413 28.0538 14.6467 28.3525 14.796C28.6511 14.9453 28.9871 15.02 29.3605 15.02ZM37.3028 16.196C36.6308 16.196 36.0428 15.9953 35.5388 15.594C35.0348 15.1927 34.6428 14.5953 34.3628 13.802C34.0922 12.9993 33.9568 12.0007 33.9568 10.806C33.9568 9.61133 34.0922 8.622 34.3628 7.838C34.6428 7.054 35.0348 6.47067 35.5388 6.088C36.0428 5.696 36.6308 5.5 37.3028 5.5C37.9748 5.5 38.5582 5.696 39.0528 6.088C39.5475 6.48 39.9302 7.068 40.2008 7.852C40.4808 8.62667 40.6208 9.61133 40.6208 10.806C40.6208 12.0007 40.4808 12.9993 40.2008 13.802C39.9302 14.5953 39.5475 15.1927 39.0528 15.594C38.5582 15.9953 37.9748 16.196 37.3028 16.196ZM37.3028 14.908C37.6482 14.908 37.9562 14.7727 38.2268 14.502C38.4975 14.2313 38.7075 13.7973 38.8568 13.2C39.0062 12.5933 39.0808 11.7953 39.0808 10.806C39.0808 9.81667 39.0062 9.028 38.8568 8.44C38.7075 7.852 38.4975 7.42733 38.2268 7.166C37.9562 6.90467 37.6482 6.774 37.3028 6.774C36.9575 6.774 36.6495 6.90467 36.3788 7.166C36.1082 7.42733 35.8935 7.852 35.7348 8.44C35.5855 9.028 35.5108 9.81667 35.5108 10.806C35.5108 11.7953 35.5855 12.5933 35.7348 13.2C35.8935 13.7973 36.1082 14.2313 36.3788 14.502C36.6495 14.7727 36.9575 14.908 37.3028 14.908ZM43.9852 9.392C43.6119 9.392 43.2665 9.308 42.9492 9.14C42.6319 8.96267 42.3799 8.72 42.1932 8.412C42.0065 8.09467 41.9132 7.726 41.9132 7.306C41.9132 6.886 42.0065 6.522 42.1932 6.214C42.3799 5.89667 42.6319 5.64933 42.9492 5.472C43.2665 5.29467 43.6119 5.206 43.9852 5.206C44.3585 5.206 44.6992 5.29467 45.0072 5.472C45.3245 5.64933 45.5765 5.89667 45.7632 6.214C45.9499 6.522 46.0432 6.886 46.0432 7.306C46.0432 7.726 45.9499 8.09467 45.7632 8.412C45.5765 8.72 45.3245 8.96267 45.0072 9.14C44.6992 9.308 44.3585 9.392 43.9852 9.392ZM43.9852 8.552C44.3212 8.552 44.5965 8.43533 44.8112 8.202C45.0259 7.96867 45.1332 7.67 45.1332 7.306C45.1332 6.93267 45.0259 6.62933 44.8112 6.396C44.5965 6.16267 44.3212 6.046 43.9852 6.046C43.6492 6.046 43.3739 6.16267 43.1592 6.396C42.9445 6.62933 42.8372 6.93267 42.8372 7.306C42.8372 7.67 42.9445 7.96867 43.1592 8.202C43.3739 8.43533 43.6492 8.552 43.9852 8.552Z" fill="#D4B106"/>
+</svg>
diff --git a/static/images/angle45.svg b/static/images/angle45.svg
new file mode 100644
index 0000000..ec0a609
--- /dev/null
+++ b/static/images/angle45.svg
@@ -0,0 +1,4 @@
+<svg width="64" height="21" viewBox="0 0 64 21" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="64" height="21" rx="4" fill="#F5222D"/>
+<path d="M26.0683 16V9.28C26.0683 9 26.0776 8.66867 26.0963 8.286C26.1149 7.894 26.1289 7.558 26.1383 7.278H26.0823C25.9516 7.53933 25.8163 7.80533 25.6763 8.076C25.5456 8.34667 25.4056 8.61267 25.2563 8.874L23.2403 11.968H28.8823V13.228H21.6023V12.15L25.7043 5.682H27.5803V16H26.0683ZM33.0586 16.196C32.5266 16.196 32.0506 16.1307 31.6306 16C31.2106 15.8693 30.842 15.6967 30.5246 15.482C30.2073 15.2673 29.9273 15.0433 29.6846 14.81L30.4546 13.76C30.6506 13.956 30.8653 14.138 31.0986 14.306C31.332 14.4647 31.5933 14.5953 31.8826 14.698C32.1813 14.8007 32.5126 14.852 32.8766 14.852C33.2593 14.852 33.6046 14.768 33.9126 14.6C34.2206 14.4227 34.4633 14.1707 34.6406 13.844C34.818 13.508 34.9066 13.1113 34.9066 12.654C34.9066 11.982 34.7246 11.4593 34.3606 11.086C34.006 10.7127 33.5346 10.526 32.9466 10.526C32.62 10.526 32.34 10.5727 32.1066 10.666C31.8733 10.7593 31.6073 10.904 31.3086 11.1L30.5106 10.582L30.8186 5.682H36.0406V7.054H32.2186L31.9806 9.686C32.2046 9.574 32.4286 9.49 32.6526 9.434C32.8766 9.36867 33.124 9.336 33.3946 9.336C33.9733 9.336 34.5006 9.45267 34.9766 9.686C35.4526 9.91933 35.8306 10.2787 36.1106 10.764C36.3906 11.24 36.5306 11.856 36.5306 12.612C36.5306 13.368 36.3673 14.0167 36.0406 14.558C35.714 15.09 35.2846 15.496 34.7526 15.776C34.23 16.056 33.6653 16.196 33.0586 16.196ZM39.993 9.392C39.6197 9.392 39.2743 9.308 38.957 9.14C38.6397 8.96267 38.3877 8.72 38.201 8.412C38.0143 8.09467 37.921 7.726 37.921 7.306C37.921 6.886 38.0143 6.522 38.201 6.214C38.3877 5.89667 38.6397 5.64933 38.957 5.472C39.2743 5.29467 39.6197 5.206 39.993 5.206C40.3663 5.206 40.707 5.29467 41.015 5.472C41.3323 5.64933 41.5843 5.89667 41.771 6.214C41.9577 6.522 42.051 6.886 42.051 7.306C42.051 7.726 41.9577 8.09467 41.771 8.412C41.5843 8.72 41.3323 8.96267 41.015 9.14C40.707 9.308 40.3663 9.392 39.993 9.392ZM39.993 8.552C40.329 8.552 40.6043 8.43533 40.819 8.202C41.0337 7.96867 41.141 7.67 41.141 7.306C41.141 6.93267 41.0337 6.62933 40.819 6.396C40.6043 6.16267 40.329 6.046 39.993 6.046C39.657 6.046 39.3817 6.16267 39.167 6.396C38.9523 6.62933 38.845 6.93267 38.845 7.306C38.845 7.67 38.9523 7.96867 39.167 8.202C39.3817 8.43533 39.657 8.552 39.993 8.552Z" fill="#FFA39E"/>
+</svg>
diff --git a/static/images/angle90.svg b/static/images/angle90.svg
new file mode 100644
index 0000000..991ca9c
--- /dev/null
+++ b/static/images/angle90.svg
@@ -0,0 +1,4 @@
+<svg width="64" height="21" viewBox="0 0 64 21" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="64" height="21" rx="4" fill="#FFD591"/>
+<path d="M24.7383 16.196C24.1409 16.196 23.6229 16.0887 23.1843 15.874C22.7549 15.65 22.3909 15.3887 22.0923 15.09L22.9743 14.082C23.1796 14.3153 23.4316 14.502 23.7303 14.642C24.0289 14.782 24.3369 14.852 24.6543 14.852C24.9809 14.852 25.2889 14.7773 25.5783 14.628C25.8769 14.4787 26.1336 14.236 26.3483 13.9C26.5723 13.564 26.7449 13.116 26.8663 12.556C26.9969 11.996 27.0623 11.31 27.0623 10.498C27.0623 9.63933 26.9783 8.93467 26.8103 8.384C26.6423 7.824 26.4043 7.41333 26.0963 7.152C25.7976 6.88133 25.4383 6.746 25.0183 6.746C24.7196 6.746 24.4489 6.83467 24.2063 7.012C23.9636 7.18 23.7723 7.42267 23.6323 7.74C23.4923 8.05733 23.4223 8.44 23.4223 8.888C23.4223 9.32667 23.4829 9.7 23.6043 10.008C23.7349 10.316 23.9263 10.554 24.1783 10.722C24.4303 10.8807 24.7336 10.96 25.0883 10.96C25.4149 10.96 25.7509 10.8573 26.0963 10.652C26.4416 10.4467 26.7683 10.1107 27.0763 9.644L27.1463 10.834C26.9503 11.0953 26.7216 11.324 26.4603 11.52C26.1989 11.716 25.9283 11.87 25.6483 11.982C25.3683 12.0847 25.0883 12.136 24.8083 12.136C24.2389 12.136 23.7349 12.0147 23.2963 11.772C22.8669 11.5293 22.5263 11.17 22.2743 10.694C22.0316 10.2087 21.9103 9.60667 21.9103 8.888C21.9103 8.20667 22.0503 7.614 22.3303 7.11C22.6196 6.59667 22.9976 6.2 23.4643 5.92C23.9309 5.64 24.4396 5.5 24.9903 5.5C25.4849 5.5 25.9469 5.60267 26.3763 5.808C26.8149 6.004 27.1929 6.30733 27.5103 6.718C27.8369 7.12867 28.0936 7.64667 28.2803 8.272C28.4669 8.89733 28.5603 9.63933 28.5603 10.498C28.5603 11.506 28.4576 12.374 28.2523 13.102C28.0469 13.8207 27.7623 14.4087 27.3983 14.866C27.0343 15.314 26.6236 15.65 26.1663 15.874C25.7089 16.0887 25.2329 16.196 24.7383 16.196ZM33.3106 16.196C32.6386 16.196 32.0506 15.9953 31.5466 15.594C31.0426 15.1927 30.6506 14.5953 30.3706 13.802C30.1 12.9993 29.9646 12.0007 29.9646 10.806C29.9646 9.61133 30.1 8.622 30.3706 7.838C30.6506 7.054 31.0426 6.47067 31.5466 6.088C32.0506 5.696 32.6386 5.5 33.3106 5.5C33.9826 5.5 34.566 5.696 35.0606 6.088C35.5553 6.48 35.938 7.068 36.2086 7.852C36.4886 8.62667 36.6286 9.61133 36.6286 10.806C36.6286 12.0007 36.4886 12.9993 36.2086 13.802C35.938 14.5953 35.5553 15.1927 35.0606 15.594C34.566 15.9953 33.9826 16.196 33.3106 16.196ZM33.3106 14.908C33.656 14.908 33.964 14.7727 34.2346 14.502C34.5053 14.2313 34.7153 13.7973 34.8646 13.2C35.014 12.5933 35.0886 11.7953 35.0886 10.806C35.0886 9.81667 35.014 9.028 34.8646 8.44C34.7153 7.852 34.5053 7.42733 34.2346 7.166C33.964 6.90467 33.656 6.774 33.3106 6.774C32.9653 6.774 32.6573 6.90467 32.3866 7.166C32.116 7.42733 31.9013 7.852 31.7426 8.44C31.5933 9.028 31.5186 9.81667 31.5186 10.806C31.5186 11.7953 31.5933 12.5933 31.7426 13.2C31.9013 13.7973 32.116 14.2313 32.3866 14.502C32.6573 14.7727 32.9653 14.908 33.3106 14.908ZM39.993 9.392C39.6197 9.392 39.2743 9.308 38.957 9.14C38.6397 8.96267 38.3877 8.72 38.201 8.412C38.0143 8.09467 37.921 7.726 37.921 7.306C37.921 6.886 38.0143 6.522 38.201 6.214C38.3877 5.89667 38.6397 5.64933 38.957 5.472C39.2743 5.29467 39.6197 5.206 39.993 5.206C40.3663 5.206 40.707 5.29467 41.015 5.472C41.3323 5.64933 41.5843 5.89667 41.771 6.214C41.9577 6.522 42.051 6.886 42.051 7.306C42.051 7.726 41.9577 8.09467 41.771 8.412C41.5843 8.72 41.3323 8.96267 41.015 9.14C40.707 9.308 40.3663 9.392 39.993 9.392ZM39.993 8.552C40.329 8.552 40.6043 8.43533 40.819 8.202C41.0337 7.96867 41.141 7.67 41.141 7.306C41.141 6.93267 41.0337 6.62933 40.819 6.396C40.6043 6.16267 40.329 6.046 39.993 6.046C39.657 6.046 39.3817 6.16267 39.167 6.396C38.9523 6.62933 38.845 6.93267 38.845 7.306C38.845 7.67 38.9523 7.96867 39.167 8.202C39.3817 8.43533 39.657 8.552 39.993 8.552Z" fill="#FA8C16"/>
+</svg>
diff --git a/static/images/confirm.svg b/static/images/confirm.svg
new file mode 100644
index 0000000..3e8d230
--- /dev/null
+++ b/static/images/confirm.svg
@@ -0,0 +1,3 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M12 2C17.5223 2 22 6.47772 22 12C22 17.5223 17.5223 22 12 22C6.47772 22 2 17.5223 2 12C2 6.47772 6.47772 2 12 2ZM16.707 9.29297C16.3409 8.92686 15.7619 8.90428 15.3691 9.22461L15.293 9.29297L11 13.5859L8.70703 11.293L8.63086 11.2246C8.23809 10.9043 7.65908 10.9269 7.29297 11.293C6.92685 11.6591 6.90426 12.2381 7.22461 12.6309L7.29297 12.707L10.293 15.707L10.3691 15.7754C10.7619 16.0955 11.341 16.0731 11.707 15.707L16.707 10.707L16.7754 10.6309C17.0957 10.2382 17.0729 9.6591 16.707 9.29297Z" fill="#52C41A"/>
+</svg>
diff --git a/static/images/material-symbols_delete-outline.svg b/static/images/material-symbols_delete-outline.svg
new file mode 100644
index 0000000..f353145
--- /dev/null
+++ b/static/images/material-symbols_delete-outline.svg
@@ -0,0 +1,3 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M5.8335 17.5C5.37516 17.5 4.98294 17.3369 4.65683 17.0108C4.33072 16.6847 4.16738 16.2922 4.16683 15.8333V5H3.3335V3.33333H7.50016V2.5H12.5002V3.33333H16.6668V5H15.8335V15.8333C15.8335 16.2917 15.6704 16.6842 15.3443 17.0108C15.0182 17.3375 14.6257 17.5006 14.1668 17.5H5.8335ZM14.1668 5H5.8335V15.8333H14.1668V5ZM7.50016 14.1667H9.16683V6.66667H7.50016V14.1667ZM10.8335 14.1667H12.5002V6.66667H10.8335V14.1667Z" fill="#FF3B30"/>
+</svg>
diff --git a/static/images/material-symbols_share.svg b/static/images/material-symbols_share.svg
new file mode 100644
index 0000000..ce8ae51
--- /dev/null
+++ b/static/images/material-symbols_share.svg
@@ -0,0 +1,3 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M14.1665 18.3327C13.4721 18.3327 12.8818 18.0896 12.3957 17.6035C11.9096 17.1174 11.6665 16.5271 11.6665 15.8327C11.6665 15.7493 11.6873 15.5549 11.729 15.2493L5.87484 11.8327C5.65262 12.041 5.39567 12.2043 5.104 12.3227C4.81234 12.441 4.49984 12.4999 4.1665 12.4993C3.47206 12.4993 2.88178 12.2563 2.39567 11.7702C1.90956 11.2841 1.6665 10.6938 1.6665 9.99935C1.6665 9.3049 1.90956 8.71463 2.39567 8.22852C2.88178 7.7424 3.47206 7.49935 4.1665 7.49935C4.49984 7.49935 4.81234 7.55852 5.104 7.67685C5.39567 7.79518 5.65262 7.95824 5.87484 8.16602L11.729 4.74935C11.7012 4.65213 11.684 4.55852 11.6773 4.46852C11.6707 4.37852 11.6671 4.27768 11.6665 4.16602C11.6665 3.47157 11.9096 2.88129 12.3957 2.39518C12.8818 1.90907 13.4721 1.66602 14.1665 1.66602C14.8609 1.66602 15.4512 1.90907 15.9373 2.39518C16.4234 2.88129 16.6665 3.47157 16.6665 4.16602C16.6665 4.86046 16.4234 5.45074 15.9373 5.93685C15.4512 6.42296 14.8609 6.66602 14.1665 6.66602C13.8332 6.66602 13.5207 6.60685 13.229 6.48852C12.9373 6.37018 12.6804 6.20713 12.4582 5.99935L6.604 9.41602C6.63178 9.51324 6.64928 9.60713 6.6565 9.69768C6.66373 9.78824 6.66706 9.88879 6.6665 9.99935C6.66595 10.1099 6.66261 10.2107 6.6565 10.3018C6.65039 10.393 6.63289 10.4866 6.604 10.5827L12.4582 13.9993C12.6804 13.791 12.9373 13.628 13.229 13.5102C13.5207 13.3924 13.8332 13.3332 14.1665 13.3327C14.8609 13.3327 15.4512 13.5757 15.9373 14.0618C16.4234 14.548 16.6665 15.1382 16.6665 15.8327C16.6665 16.5271 16.4234 17.1174 15.9373 17.6035C15.4512 18.0896 14.8609 18.3327 14.1665 18.3327Z" fill="black"/>
+</svg>
diff --git a/static/images/mingcute_edit-line.svg b/static/images/mingcute_edit-line.svg
new file mode 100644
index 0000000..a960259
--- /dev/null
+++ b/static/images/mingcute_edit-line.svg
@@ -0,0 +1,3 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M10.8333 2.5C11.0457 2.50024 11.25 2.58157 11.4045 2.72737C11.5589 2.87318 11.6519 3.07246 11.6643 3.2845C11.6768 3.49653 11.6078 3.70532 11.4714 3.86819C11.3351 4.03107 11.1417 4.13575 10.9308 4.16083L10.8333 4.16667H4.16667V15.8333H15.8333V9.16667C15.8336 8.95427 15.9149 8.74997 16.0607 8.59553C16.2065 8.44108 16.4058 8.34814 16.6178 8.33569C16.8299 8.32324 17.0386 8.39223 17.2015 8.52855C17.3644 8.66488 17.4691 8.85825 17.4942 9.06917L17.5 9.16667V15.8333C17.5001 16.2538 17.3413 16.6588 17.0554 16.9671C16.7695 17.2754 16.3776 17.4643 15.9583 17.4958L15.8333 17.5H4.16667C3.74619 17.5001 3.34119 17.3413 3.03288 17.0554C2.72456 16.7695 2.5357 16.3776 2.50417 15.9583L2.5 15.8333V4.16667C2.49987 3.74619 2.65867 3.34119 2.94458 3.03288C3.23049 2.72456 3.62237 2.5357 4.04167 2.50417L4.16667 2.5H10.8333ZM16.0358 2.78583C16.1858 2.63638 16.387 2.54961 16.5987 2.54314C16.8103 2.53668 17.0164 2.61101 17.1752 2.75104C17.334 2.89107 17.4336 3.08629 17.4537 3.29706C17.4737 3.50783 17.4128 3.71834 17.2833 3.88583L17.2142 3.965L8.96417 12.2142C8.8142 12.3636 8.61297 12.4504 8.40135 12.4569C8.18972 12.4633 7.98357 12.389 7.82477 12.249C7.66596 12.1089 7.56641 11.9137 7.54633 11.7029C7.52626 11.4922 7.58716 11.2817 7.71667 11.1142L7.78583 11.0358L16.0358 2.78583Z" fill="black"/>
+</svg>
diff --git a/static/images/radix-icons_update.svg b/static/images/radix-icons_update.svg
new file mode 100644
index 0000000..e156e35
--- /dev/null
+++ b/static/images/radix-icons_update.svg
@@ -0,0 +1,3 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M2.53728 9.73029C2.53728 13.789 5.47995 16.5543 8.78528 17.1263C8.87519 17.1419 8.96116 17.175 9.03826 17.2238C9.11536 17.2726 9.1821 17.3361 9.23466 17.4107C9.28722 17.4853 9.32457 17.5695 9.34458 17.6586C9.36459 17.7476 9.36687 17.8397 9.35128 17.9296C9.3357 18.0195 9.30256 18.1055 9.25375 18.1826C9.20495 18.2597 9.14143 18.3264 9.06684 18.379C8.99224 18.4316 8.90802 18.4689 8.81899 18.4889C8.72996 18.5089 8.63786 18.5112 8.54795 18.4956C4.66662 17.8236 1.14795 14.5516 1.14795 9.73029C1.14795 7.68095 2.07995 6.07029 3.16795 4.84629C3.94795 3.96895 4.83995 3.25562 5.55728 2.71029H3.37595C3.19914 2.71029 3.02957 2.64005 2.90454 2.51502C2.77952 2.39 2.70928 2.22043 2.70928 2.04362C2.70928 1.86681 2.77952 1.69724 2.90454 1.57222C3.02957 1.44719 3.19914 1.37695 3.37595 1.37695H7.37595C7.55276 1.37695 7.72233 1.44719 7.84735 1.57222C7.97238 1.69724 8.04262 1.86681 8.04262 2.04362V6.04362C8.04262 6.22043 7.97238 6.39 7.84735 6.51502C7.72233 6.64005 7.55276 6.71029 7.37595 6.71029C7.19914 6.71029 7.02957 6.64005 6.90455 6.51502C6.77952 6.39 6.70928 6.22043 6.70928 6.04362V3.58229L6.70795 3.58495C5.94528 4.15829 5.01462 4.86095 4.20795 5.76895C3.25462 6.84095 2.53728 8.13829 2.53728 9.73029ZM17.3479 10.2703C17.3479 6.25429 14.4679 3.50629 11.2053 2.89295C11.1143 2.87752 11.0274 2.84414 10.9495 2.79475C10.8716 2.74536 10.8043 2.68095 10.7516 2.60528C10.6988 2.52961 10.6617 2.4442 10.6423 2.35402C10.6229 2.26384 10.6217 2.17071 10.6387 2.08006C10.6557 1.9894 10.6906 1.90304 10.7413 1.82601C10.7921 1.74898 10.8576 1.68282 10.9342 1.63139C11.0108 1.57997 11.0968 1.54431 11.1873 1.52649C11.2778 1.50868 11.3709 1.50906 11.4613 1.52762C15.2933 2.24762 18.7373 5.50095 18.7373 10.2703C18.7373 12.3196 17.8053 13.929 16.7173 15.1543C15.9373 16.0316 15.0453 16.745 14.3279 17.2903H16.5093C16.6861 17.2903 16.8557 17.3605 16.9807 17.4855C17.1057 17.6106 17.1759 17.7801 17.1759 17.957C17.1759 18.1338 17.1057 18.3033 16.9807 18.4284C16.8557 18.5534 16.6861 18.6236 16.5093 18.6236H12.5093C12.3325 18.6236 12.1629 18.5534 12.0379 18.4284C11.9129 18.3033 11.8426 18.1338 11.8426 17.957V13.957C11.8426 13.7801 11.9129 13.6106 12.0379 13.4855C12.1629 13.3605 12.3325 13.2903 12.5093 13.2903C12.6861 13.2903 12.8557 13.3605 12.9807 13.4855C13.1057 13.6106 13.1759 13.7801 13.1759 13.957V16.417H13.1786C13.9399 15.841 14.872 15.1396 15.6773 14.2303C16.6306 13.1596 17.3479 11.8636 17.3479 10.2703Z" fill="black"/>
+</svg>
diff --git a/static/images/remove.svg b/static/images/remove.svg
new file mode 100644
index 0000000..43b9a32
--- /dev/null
+++ b/static/images/remove.svg
@@ -0,0 +1,3 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M12 13.4L14.9 16.3C15.0833 16.4833 15.3167 16.575 15.6 16.575C15.8833 16.575 16.1167 16.4833 16.3 16.3C16.4833 16.1167 16.575 15.8833 16.575 15.6C16.575 15.3167 16.4833 15.0833 16.3 14.9L13.4 12L16.3 9.1C16.4833 8.91667 16.575 8.68333 16.575 8.4C16.575 8.11667 16.4833 7.88333 16.3 7.7C16.1167 7.51667 15.8833 7.425 15.6 7.425C15.3167 7.425 15.0833 7.51667 14.9 7.7L12 10.6L9.1 7.7C8.91667 7.51667 8.68333 7.425 8.4 7.425C8.11667 7.425 7.88333 7.51667 7.7 7.7C7.51667 7.88333 7.425 8.11667 7.425 8.4C7.425 8.68333 7.51667 8.91667 7.7 9.1L10.6 12L7.7 14.9C7.51667 15.0833 7.425 15.3167 7.425 15.6C7.425 15.8833 7.51667 16.1167 7.7 16.3C7.88333 16.4833 8.11667 16.575 8.4 16.575C8.68333 16.575 8.91667 16.4833 9.1 16.3L12 13.4ZM12 22C10.6167 22 9.31667 21.7373 8.1 21.212C6.88334 20.6867 5.825 19.9743 4.925 19.075C4.025 18.1757 3.31267 17.1173 2.788 15.9C2.26333 14.6827 2.00067 13.3827 2 12C1.99933 10.6173 2.262 9.31733 2.788 8.1C3.314 6.88267 4.02633 5.82433 4.925 4.925C5.82367 4.02567 6.882 3.31333 8.1 2.788C9.318 2.26267 10.618 2 12 2C13.382 2 14.682 2.26267 15.9 2.788C17.118 3.31333 18.1763 4.02567 19.075 4.925C19.9737 5.82433 20.6863 6.88267 21.213 8.1C21.7397 9.31733 22.002 10.6173 22 12C21.998 13.3827 21.7353 14.6827 21.212 15.9C20.6887 17.1173 19.9763 18.1757 19.075 19.075C18.1737 19.9743 17.1153 20.687 15.9 21.213C14.6847 21.739 13.3847 22.0013 12 22Z" fill="#F5222D"/>
+</svg>
diff --git a/static/images/station.svg b/static/images/station.svg
new file mode 100644
index 0000000..fae579e
--- /dev/null
+++ b/static/images/station.svg
@@ -0,0 +1,11 @@
+<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="36" height="36" rx="18" fill="#90D3FF"/>
+<g clip-path="url(#clip0_647_7172)">
+<path d="M11.7515 17.0488C11.5265 16.8238 11.4001 16.5186 11.4001 16.2004C11.4001 15.8822 11.5265 15.577 11.7515 15.352L17.1515 9.95199C17.3765 9.72702 17.6817 9.60065 17.9999 9.60065C18.3181 9.60065 18.6233 9.72702 18.8483 9.95199L24.2483 15.352C24.4669 15.5783 24.5878 15.8814 24.5851 16.1961C24.5824 16.5107 24.4562 16.8117 24.2337 17.0342C24.0112 17.2567 23.7102 17.3829 23.3956 17.3856C23.0809 17.3883 22.7778 17.2674 22.5515 17.0488L19.1999 13.8004L19.1999 25.2004C19.1999 25.5187 19.0735 25.8239 18.8484 26.0489C18.6234 26.274 18.3181 26.4004 17.9999 26.4004C17.6816 26.4004 17.3764 26.274 17.1514 26.0489C16.9263 25.8239 16.7999 25.5187 16.7999 25.2004L16.7999 13.8004L13.4483 17.0488C13.2233 17.2738 12.9181 17.4001 12.5999 17.4001C12.2817 17.4001 11.9765 17.2738 11.7515 17.0488Z" fill="#0050B2"/>
+</g>
+<defs>
+<clipPath id="clip0_647_7172">
+<rect width="18" height="18" fill="white" transform="translate(9 27) rotate(-90)"/>
+</clipPath>
+</defs>
+</svg>
diff --git a/static/images/station1.svg b/static/images/station1.svg
new file mode 100644
index 0000000..8cce281
--- /dev/null
+++ b/static/images/station1.svg
@@ -0,0 +1,11 @@
+<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="36" height="36" rx="18" fill="#FFA39E"/>
+<g clip-path="url(#clip0_647_7172)">
+<path d="M11.7515 17.0488C11.5265 16.8238 11.4001 16.5186 11.4001 16.2004C11.4001 15.8822 11.5265 15.577 11.7515 15.352L17.1515 9.95199C17.3765 9.72702 17.6817 9.60065 17.9999 9.60065C18.3181 9.60065 18.6233 9.72702 18.8483 9.95199L24.2483 15.352C24.4669 15.5783 24.5878 15.8814 24.5851 16.1961C24.5824 16.5107 24.4562 16.8117 24.2337 17.0342C24.0112 17.2567 23.7102 17.3829 23.3956 17.3856C23.0809 17.3883 22.7778 17.2674 22.5515 17.0488L19.1999 13.8004L19.1999 25.2004C19.1999 25.5187 19.0735 25.8239 18.8484 26.0489C18.6234 26.274 18.3181 26.4004 17.9999 26.4004C17.6816 26.4004 17.3764 26.274 17.1514 26.0489C16.9263 25.8239 16.7999 25.5187 16.7999 25.2004L16.7999 13.8004L13.4483 17.0488C13.2233 17.2738 12.9181 17.4001 12.5999 17.4001C12.2817 17.4001 11.9765 17.2738 11.7515 17.0488Z" fill="#F5222D"/>
+</g>
+<defs>
+<clipPath id="clip0_647_7172">
+<rect width="18" height="18" fill="white" transform="translate(9 27) rotate(-90)"/>
+</clipPath>
+</defs>
+</svg>
diff --git a/static/images/station2.svg b/static/images/station2.svg
new file mode 100644
index 0000000..108376f
--- /dev/null
+++ b/static/images/station2.svg
@@ -0,0 +1,11 @@
+<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="36" height="36" rx="18" fill="#F5222D"/>
+<g clip-path="url(#clip0_647_7173)">
+<path d="M14.2546 12.9093C14.2546 12.5911 14.381 12.2859 14.606 12.0609C14.831 11.8359 15.1362 11.7095 15.4544 11.7095L23.0911 11.7095C23.4093 11.7095 23.7145 11.8359 23.9395 12.0609C24.1645 12.2859 24.2909 12.5911 24.291 12.9093L24.291 20.546C24.2855 20.8606 24.1567 21.1605 23.9323 21.3811C23.7079 21.6016 23.4058 21.7252 23.0911 21.7252C22.7765 21.7252 22.4744 21.6016 22.25 21.3811C22.0256 21.1605 21.8968 20.8606 21.8913 20.546L21.8184 15.8791L13.7573 23.9402C13.5323 24.1652 13.2271 24.2916 12.9088 24.2916C12.5905 24.2916 12.2853 24.1652 12.0603 23.9402C11.8352 23.7151 11.7088 23.4099 11.7088 23.0916C11.7088 22.7734 11.8352 22.4681 12.0603 22.2431L20.1213 14.1821L15.4544 14.1091C15.1362 14.1091 14.831 13.9826 14.606 13.7576C14.381 13.5326 14.2546 13.2275 14.2546 12.9093Z" fill="#FFA39E"/>
+</g>
+<defs>
+<clipPath id="clip0_647_7173">
+<rect width="18" height="18" fill="white" transform="translate(5.27197 18) rotate(-45)"/>
+</clipPath>
+</defs>
+</svg>
diff --git a/static/images/station3.svg b/static/images/station3.svg
new file mode 100644
index 0000000..bd171a8
--- /dev/null
+++ b/static/images/station3.svg
@@ -0,0 +1,4 @@
+<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="36" height="36" rx="18" fill="#FFD591"/>
+<path d="M18.9517 11.7517C19.1767 11.5268 19.4819 11.4004 19.8001 11.4004C20.1183 11.4004 20.4235 11.5268 20.6485 11.7517L26.0485 17.1517C26.2735 17.3768 26.3998 17.6819 26.3998 18.0001C26.3998 18.3183 26.2735 18.6235 26.0485 18.8485L20.6485 24.2485C20.4222 24.4671 20.1191 24.5881 19.8044 24.5853C19.4898 24.5826 19.1888 24.4564 18.9663 24.2339C18.7438 24.0114 18.6176 23.7105 18.6149 23.3958C18.6122 23.0812 18.7331 22.7781 18.9517 22.5517L22.2001 19.2001H10.8001C10.4818 19.2001 10.1766 19.0737 9.95157 18.8487C9.72653 18.6236 9.6001 18.3184 9.6001 18.0001C9.6001 17.6819 9.72653 17.3766 9.95157 17.1516C10.1766 16.9266 10.4818 16.8001 10.8001 16.8001H22.2001L18.9517 13.4485C18.7267 13.2235 18.6004 12.9183 18.6004 12.6001C18.6004 12.2819 18.7267 11.9768 18.9517 11.7517Z" fill="#FA8C16"/>
+</svg>
diff --git a/static/images/station4.svg b/static/images/station4.svg
new file mode 100644
index 0000000..479e9d0
--- /dev/null
+++ b/static/images/station4.svg
@@ -0,0 +1,11 @@
+<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="36" height="36" rx="18" fill="#FA8C16"/>
+<g clip-path="url(#clip0_647_7175)">
+<path d="M23.0912 14.2536C23.4094 14.2536 23.7145 14.3801 23.9395 14.6051C24.1645 14.8301 24.291 15.1352 24.291 15.4534L24.291 23.0902C24.291 23.4084 24.1645 23.7135 23.9395 23.9385C23.7145 24.1635 23.4094 24.2899 23.0912 24.29L15.4544 24.29C15.1398 24.2845 14.84 24.1557 14.6194 23.9313C14.3989 23.7069 14.2753 23.4048 14.2753 23.0902C14.2753 22.7755 14.3989 22.4735 14.6194 22.249C14.84 22.0246 15.1398 21.8958 15.4544 21.8903L20.1213 21.8174L12.0603 13.7564C11.8353 13.5313 11.7089 13.2261 11.7089 12.9078C11.7089 12.5896 11.8353 12.2843 12.0603 12.0593C12.2854 11.8343 12.5906 11.7078 12.9089 11.7078C13.2271 11.7078 13.5323 11.8343 13.7574 12.0593L21.8184 20.1203L21.8914 15.4534C21.8914 15.1352 22.0178 14.8301 22.2428 14.6051C22.4678 14.3801 22.773 14.2536 23.0912 14.2536Z" fill="#FFD591"/>
+</g>
+<defs>
+<clipPath id="clip0_647_7175">
+<rect width="18" height="18" fill="white" transform="translate(18 5.27148) rotate(45)"/>
+</clipPath>
+</defs>
+</svg>
diff --git a/static/images/station5.svg b/static/images/station5.svg
new file mode 100644
index 0000000..f99446d
--- /dev/null
+++ b/static/images/station5.svg
@@ -0,0 +1,4 @@
+<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="36" height="36" rx="18" fill="#FFEC3D"/>
+<path d="M24.2485 18.9512C24.4735 19.1762 24.5999 19.4814 24.5999 19.7996C24.5999 20.1178 24.4735 20.423 24.2485 20.648L18.8485 26.048C18.6235 26.273 18.3183 26.3994 18.0001 26.3994C17.6819 26.3994 17.3767 26.273 17.1517 26.048L11.7517 20.648C11.5331 20.4217 11.4122 20.1186 11.4149 19.8039C11.4176 19.4893 11.5438 19.1883 11.7663 18.9658C11.9888 18.7433 12.2898 18.6171 12.6044 18.6144C12.9191 18.6117 13.2222 18.7326 13.4485 18.9512L16.8001 22.1996L16.8001 10.7996C16.8001 10.4813 16.9265 10.1761 17.1516 9.95108C17.3766 9.72604 17.6819 9.59961 18.0001 9.59961C18.3184 9.59961 18.6236 9.72604 18.8486 9.95108C19.0737 10.1761 19.2001 10.4813 19.2001 10.7996L19.2001 22.1996L22.5517 18.9512C22.7767 18.7262 23.0819 18.5999 23.4001 18.5999C23.7183 18.5999 24.0235 18.7262 24.2485 18.9512Z" fill="#D4B106"/>
+</svg>
diff --git a/static/images/station6.svg b/static/images/station6.svg
new file mode 100644
index 0000000..f03839a
--- /dev/null
+++ b/static/images/station6.svg
@@ -0,0 +1,11 @@
+<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="36" height="36" rx="18" fill="#D4B106"/>
+<g clip-path="url(#clip0_647_7177)">
+<path d="M21.7454 23.0907C21.7454 23.4089 21.619 23.7141 21.394 23.9391C21.169 24.1641 20.8638 24.2905 20.5456 24.2905L12.9089 24.2905C12.5907 24.2905 12.2855 24.1641 12.0605 23.9391C11.8355 23.7141 11.7091 23.4089 11.709 23.0907L11.709 15.454C11.7145 15.1394 11.8433 14.8395 12.0677 14.6189C12.2921 14.3984 12.5942 14.2748 12.9089 14.2748C13.2235 14.2748 13.5256 14.3984 13.75 14.6189C13.9744 14.8395 14.1032 15.1394 14.1087 15.454L14.1816 20.1209L22.2427 12.0598C22.4677 11.8348 22.7729 11.7084 23.0912 11.7084C23.4095 11.7084 23.7147 11.8348 23.9397 12.0598C24.1648 12.2849 24.2912 12.5901 24.2912 12.9084C24.2912 13.2266 24.1648 13.5319 23.9397 13.7569L15.8787 21.8179L20.5456 21.8909C20.8638 21.8909 21.169 22.0174 21.394 22.2424C21.619 22.4674 21.7454 22.7725 21.7454 23.0907Z" fill="#FFEC3D"/>
+</g>
+<defs>
+<clipPath id="clip0_647_7177">
+<rect width="18" height="18" fill="white" transform="translate(30.728 18) rotate(135)"/>
+</clipPath>
+</defs>
+</svg>
diff --git a/static/images/station7.svg b/static/images/station7.svg
new file mode 100644
index 0000000..9e86480
--- /dev/null
+++ b/static/images/station7.svg
@@ -0,0 +1,4 @@
+<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="36" height="36" rx="18" fill="#D3F261"/>
+<path d="M17.0483 24.2483C16.8233 24.4732 16.5181 24.5996 16.1999 24.5996C15.8817 24.5996 15.5765 24.4732 15.3515 24.2483L9.9515 18.8483C9.72654 18.6232 9.60016 18.3181 9.60016 17.9999C9.60016 17.6817 9.72654 17.3765 9.9515 17.1515L15.3515 11.7515C15.5778 11.5329 15.8809 11.4119 16.1956 11.4147C16.5102 11.4174 16.8112 11.5436 17.0337 11.7661C17.2562 11.9886 17.3824 12.2895 17.3851 12.6042C17.3878 12.9188 17.2669 13.2219 17.0483 13.4483L13.7999 16.7999L25.1999 16.7999C25.5182 16.7999 25.8234 16.9263 26.0484 17.1513C26.2735 17.3764 26.3999 17.6816 26.3999 17.9999C26.3999 18.3181 26.2735 18.6234 26.0484 18.8484C25.8234 19.0734 25.5182 19.1999 25.1999 19.1999L13.7999 19.1999L17.0483 22.5515C17.2733 22.7765 17.3996 23.0817 17.3996 23.3999C17.3996 23.7181 17.2733 24.0232 17.0483 24.2483Z" fill="#7CB305"/>
+</svg>
diff --git a/static/images/station8.svg b/static/images/station8.svg
new file mode 100644
index 0000000..ee2f1e5
--- /dev/null
+++ b/static/images/station8.svg
@@ -0,0 +1,11 @@
+<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="36" height="36" rx="18" fill="#7CB305"/>
+<g clip-path="url(#clip0_647_7179)">
+<path d="M12.9088 21.7464C12.5906 21.7464 12.2855 21.6199 12.0605 21.3949C11.8355 21.1699 11.709 20.8648 11.709 20.5466L11.709 12.9098C11.709 12.5916 11.8355 12.2865 12.0605 12.0615C12.2855 11.8365 12.5906 11.7101 12.9088 11.71L20.5456 11.71C20.8602 11.7155 21.16 11.8443 21.3806 12.0687C21.6011 12.2931 21.7247 12.5952 21.7247 12.9098C21.7247 13.2245 21.6011 13.5265 21.3806 13.751C21.16 13.9754 20.8602 14.1042 20.5456 14.1097L15.8787 14.1826L23.9397 22.2436C24.1647 22.4687 24.2911 22.7739 24.2911 23.0922C24.2911 23.4104 24.1647 23.7157 23.9397 23.9407C23.7146 24.1657 23.4094 24.2922 23.0911 24.2922C22.7729 24.2922 22.4677 24.1657 22.2426 23.9407L14.1816 15.8797L14.1086 20.5466C14.1086 20.8648 13.9822 21.1699 13.7572 21.3949C13.5322 21.6199 13.227 21.7464 12.9088 21.7464Z" fill="#D3F261"/>
+</g>
+<defs>
+<clipPath id="clip0_647_7179">
+<rect width="18" height="18" fill="white" transform="translate(18 30.7285) rotate(-135)"/>
+</clipPath>
+</defs>
+</svg>
diff --git a/static/images/tabler_copy.svg b/static/images/tabler_copy.svg
new file mode 100644
index 0000000..a3a591b
--- /dev/null
+++ b/static/images/tabler_copy.svg
@@ -0,0 +1,4 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M5.8335 8.05648C5.8335 7.46704 6.06765 6.90174 6.48445 6.48494C6.90125 6.06814 7.46655 5.83398 8.056 5.83398H15.2777C15.5695 5.83398 15.8585 5.89147 16.1282 6.00316C16.3978 6.11485 16.6428 6.27856 16.8492 6.48494C17.0556 6.69132 17.2193 6.93632 17.331 7.20597C17.4427 7.47562 17.5002 7.76462 17.5002 8.05648V15.2782C17.5002 15.57 17.4427 15.859 17.331 16.1287C17.2193 16.3983 17.0556 16.6433 16.8492 16.8497C16.6428 17.0561 16.3978 17.2198 16.1282 17.3315C15.8585 17.4432 15.5695 17.5007 15.2777 17.5007H8.056C7.76413 17.5007 7.47513 17.4432 7.20548 17.3315C6.93584 17.2198 6.69083 17.0561 6.48445 16.8497C6.27807 16.6433 6.11437 16.3983 6.00267 16.1287C5.89098 15.859 5.8335 15.57 5.8335 15.2782V8.05648Z" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+<path d="M3.34333 13.9475C3.0875 13.8021 2.87471 13.5916 2.72658 13.3374C2.57846 13.0832 2.50028 12.7942 2.5 12.5V4.16667C2.5 3.25 3.25 2.5 4.16667 2.5H12.5C13.125 2.5 13.465 2.82083 13.75 3.33333" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
+</svg>
diff --git a/static/images/tdesign_book.svg b/static/images/tdesign_book.svg
new file mode 100644
index 0000000..f26093b
--- /dev/null
+++ b/static/images/tdesign_book.svg
@@ -0,0 +1,3 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M2.5 4.99935C2.5 4.11529 2.85119 3.26745 3.47631 2.64233C4.10143 2.01721 4.94928 1.66602 5.83333 1.66602H17.5V18.3327H5.83333C4.94928 18.3327 4.10143 17.9815 3.47631 17.3564C2.85119 16.7312 2.5 15.8834 2.5 14.9993V4.99935ZM4.16667 12.1118C4.67347 11.8195 5.24828 11.6658 5.83333 11.666H15.8333V3.33268H5.83333C5.39131 3.33268 4.96738 3.50828 4.65482 3.82084C4.34226 4.1334 4.16667 4.55732 4.16667 4.99935V12.1118ZM15.8333 13.3327H5.83333C5.39131 13.3327 4.96738 13.5083 4.65482 13.8208C4.34226 14.1334 4.16667 14.5573 4.16667 14.9993C4.16667 15.4414 4.34226 15.8653 4.65482 16.1779C4.96738 16.4904 5.39131 16.666 5.83333 16.666H15.8333V13.3327ZM8.33333 4.99935H14.1667V6.66602H8.33333V4.99935Z" fill="black"/>
+</svg>
diff --git a/static/images/van.svg b/static/images/van.svg
new file mode 100644
index 0000000..356c12c
--- /dev/null
+++ b/static/images/van.svg
@@ -0,0 +1,10 @@
+<svg width="40" height="84" viewBox="0 0 40 84" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect x="18" y="74" width="4" height="10" fill="#434343"/>
+<rect x="34" y="80" width="4" height="28" rx="2" transform="rotate(90 34 80)" fill="#434343"/>
+<rect x="4" width="12" height="62" rx="6" fill="#434343"/>
+<rect x="24" width="12" height="62" rx="6" fill="#434343"/>
+<rect x="8" y="8" width="4" height="8" rx="2" fill="#FA8C16"/>
+<rect x="28" y="8" width="4" height="8" rx="2" fill="#FA8C16"/>
+<rect y="48" width="40" height="28" rx="4" fill="#FA8C16"/>
+<circle cx="32" cy="56" r="4" fill="#434343"/>
+</svg>
diff --git a/static/images/view1.png b/static/images/view1.png
new file mode 100644
index 0000000..cfa3e58
--- /dev/null
+++ b/static/images/view1.png
Binary files differ
diff --git a/static/logo.png b/static/logo.png
new file mode 100644
index 0000000..b5771e2
--- /dev/null
+++ b/static/logo.png
Binary files differ
diff --git a/static/map.png b/static/map.png
new file mode 100644
index 0000000..9007b1f
--- /dev/null
+++ b/static/map.png
Binary files differ
diff --git a/static/play.png b/static/play.png
new file mode 100644
index 0000000..b9a8be5
--- /dev/null
+++ b/static/play.png
Binary files differ
diff --git a/static/tabbar/mdi_hand-truck.png b/static/tabbar/mdi_hand-truck.png
new file mode 100644
index 0000000..0049753
--- /dev/null
+++ b/static/tabbar/mdi_hand-truck.png
Binary files differ
diff --git a/static/tabbar/mdi_hand-truck2.png b/static/tabbar/mdi_hand-truck2.png
new file mode 100644
index 0000000..9e85641
--- /dev/null
+++ b/static/tabbar/mdi_hand-truck2.png
Binary files differ
diff --git a/static/tabbar/ooui_user-avatar.png b/static/tabbar/ooui_user-avatar.png
new file mode 100644
index 0000000..091fa43
--- /dev/null
+++ b/static/tabbar/ooui_user-avatar.png
Binary files differ
diff --git a/static/tabbar/ooui_user-avatar2.png b/static/tabbar/ooui_user-avatar2.png
new file mode 100644
index 0000000..7c56002
--- /dev/null
+++ b/static/tabbar/ooui_user-avatar2.png
Binary files differ
diff --git a/uni.promisify.adaptor.js b/uni.promisify.adaptor.js
new file mode 100644
index 0000000..5fec4f3
--- /dev/null
+++ b/uni.promisify.adaptor.js
@@ -0,0 +1,13 @@
+uni.addInterceptor({
+  returnValue (res) {
+    if (!(!!res && (typeof res === "object" || typeof res === "function") && typeof res.then === "function")) {
+      return res;
+    }
+    return new Promise((resolve, reject) => {
+      res.then((res) => {
+        if (!res) return resolve(res) 
+        return res[0] ? reject(res[0]) : resolve(res[1])
+      });
+    });
+  },
+});
\ No newline at end of file
diff --git a/uni.scss b/uni.scss
new file mode 100644
index 0000000..b9249e9
--- /dev/null
+++ b/uni.scss
@@ -0,0 +1,76 @@
+/**
+ * 杩欓噷鏄痷ni-app鍐呯疆鐨勫父鐢ㄦ牱寮忓彉閲�+ *
+ * uni-app 瀹樻柟鎵╁睍鎻掍欢鍙婃彃浠跺競鍦猴紙https://ext.dcloud.net.cn锛変笂寰堝涓夋柟鎻掍欢鍧囦娇鐢ㄤ簡杩欎簺鏍峰紡鍙橀噺
+ * 濡傛灉浣犳槸鎻掍欢寮�彂鑰咃紝寤鸿浣犱娇鐢╯css棰勫鐞嗭紝骞跺湪鎻掍欢浠g爜涓洿鎺ヤ娇鐢ㄨ繖浜涘彉閲忥紙鏃犻渶 import 杩欎釜鏂囦欢锛夛紝鏂逛究鐢ㄦ埛閫氳繃鎼Н鏈ㄧ殑鏂瑰紡寮�彂鏁翠綋椋庢牸涓�嚧鐨凙pp
+ *
+ */
+
+/**
+ * 濡傛灉浣犳槸App寮�彂鑰咃紙鎻掍欢浣跨敤鑰咃級锛屼綘鍙互閫氳繃淇敼杩欎簺鍙橀噺鏉ュ畾鍒惰嚜宸辩殑鎻掍欢涓婚锛屽疄鐜拌嚜瀹氫箟涓婚鍔熻兘
+ *
+ * 濡傛灉浣犵殑椤圭洰鍚屾牱浣跨敤浜唖css棰勫鐞嗭紝浣犱篃鍙互鐩存帴鍦ㄤ綘鐨�scss 浠g爜涓娇鐢ㄥ涓嬪彉閲忥紝鍚屾椂鏃犻渶 import 杩欎釜鏂囦欢
+ */
+
+/* 棰滆壊鍙橀噺 */
+
+/* 琛屼负鐩稿叧棰滆壊 */
+$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:#c8c7cc;
+
+/* 灏哄鍙橀噺 */
+
+/* 鏂囧瓧灏哄 */
+$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;
diff --git a/uni_modules/uni-forms/changelog.md b/uni_modules/uni-forms/changelog.md
new file mode 100644
index 0000000..0b58ab8
--- /dev/null
+++ b/uni_modules/uni-forms/changelog.md
@@ -0,0 +1,100 @@
+## 1.4.13锛�024-10-08锛�+- 淇 鏍¢獙瑙勫垯鍦ㄦ姈闊冲紑鍙戣�宸ュ叿涓婁笉鐢熸晥鐨刡ug锛岃瑙侊細[https://ask.dcloud.net.cn/question/191933](https://ask.dcloud.net.cn/question/191933)
+## 1.4.12 (2024-9-21)
+- 淇 form涓婃淇敼鐨勯棶棰�+## 1.4.11 (2024-9-14)
+- 淇 binddata鐨勫吋瀹规�闂
+## 1.4.10锛�023-11-03锛�+- 浼樺寲 labelWidth 鎻忚堪閿欒
+## 1.4.9锛�023-02-10锛�+- 淇 required 鍙傛暟鏃犳硶鍔ㄦ�缁戝畾
+## 1.4.8锛�022-08-23锛�+- 浼樺寲 鏍规嵁 rules 鑷姩娣诲姞 required 鐨勯棶棰�+## 1.4.7锛�022-08-22锛�+- 淇 item 鏈缃�require 灞炴�锛宺ules 璁剧疆 require 鍚庯紝鏄熷彿涔熸樉绀虹殑 bug锛岃瑙侊細[https://ask.dcloud.net.cn/question/151540](https://ask.dcloud.net.cn/question/151540)
+## 1.4.6锛�022-07-13锛�+- 淇 model 闇�鏍¢獙鐨勫�娌℃湁澹版槑瀵瑰簲瀛楁鏃讹紝瀵艰嚧绗竴娆′笉瑙﹀彂鏍¢獙鐨刡ug
+## 1.4.5锛�022-07-05锛�+- 鏂板 鏇村琛ㄥ崟绀轰緥
+- 浼樺寲 瀛愯〃鍗曠粍浠惰繃鏈熸彁绀虹殑闂
+- 浼樺寲 瀛愯〃鍗曠粍浠秛ni-datetime-picker銆乽ni-data-select銆乽ni-data-picker鐨勬樉绀烘牱寮�+## 1.4.4锛�022-07-04锛�+- 鏇存柊 鍒犻櫎缁勪欢鏃ュ織
+## 1.4.3锛�022-07-04锛�+- 淇 鐢�1.4.0 寮曞彂鐨�label 鎻掓Ы涓嶇敓鏁堢殑bug
+## 1.4.2锛�022-07-04锛�+- 淇 瀛愮粍浠舵壘涓嶅埌 setValue 鎶ラ敊鐨刡ug
+## 1.4.1锛�022-07-04锛�+- 淇 uni-data-picker 鍦�uni-forms-item 涓姤閿欑殑bug
+- 淇 uni-data-picker 鍦�uni-forms-item 涓搴︿笉姝g‘鐨刡ug
+## 1.4.0锛�022-06-30锛�+- 銆愰噸瑕併�缁勪欢閫昏緫閲嶆瀯锛岄儴鍒嗙敤娉曠敤鏃х増鏈笉鍏煎锛岃娉ㄦ剰鍏煎闂
+- 銆愰噸瑕併�缁勪欢浣跨敤 Provide/Inject 鏂瑰紡娉ㄥ叆渚濊禆锛屾彁渚涗簡鑷畾涔夎〃鍗曠粍浠惰皟鐢�uni-forms 鏍¢獙琛ㄥ崟鐨勮兘鍔�+- 鏂板 model 灞炴�锛岀瓑鍚屼簬鍘�value/modelValue 灞炴�锛屾棫灞炴�鍗冲皢搴熷純
+- 鏂板 validateTrigger 灞炴�鐨�blur 鍊硷紝浠�uni-easyinput 鐢熸晥
+- 鏂板 onFieldChange 鏂规硶锛屽彲浠ュ瀛愯〃鍗曡繘琛屾牎楠岋紝鍙浛浠inddata鏂规硶
+- 鏂板 瀛愯〃鍗曠殑 setRules 鏂规硶锛岄厤鍚堣嚜瀹氫箟鏍¢獙鍑芥暟浣跨敤
+- 鏂板 uni-forms-item 鐨�setRules 鏂规硶锛岄厤缃姩鎬佽〃鍗曚娇鐢ㄥ彲鍔ㄦ�鏇存柊鏍¢獙瑙勫垯
+- 浼樺寲 鍔ㄦ�琛ㄥ崟鏍¢獙鏂瑰紡锛屽簾寮冩嫾鎺ame鐨勬柟寮�+## 1.3.3锛�022-06-22锛�+- 淇 琛ㄥ崟鏍¢獙椤哄簭鏃犲簭闂
+## 1.3.2锛�021-12-09锛�+-
+## 1.3.1锛�021-11-19锛�+- 淇 label 鎻掓Ы涓嶇敓鏁堢殑bug
+## 1.3.0锛�021-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锛�021-08-13锛�+- 淇 娌℃湁娣诲姞鏍¢獙瑙勫垯鐨勫瓧娈典緷鐒舵姤閿欑殑Bug
+## 1.2.6锛�021-08-11锛�+- 淇 閲嶇疆琛ㄥ崟閿欒淇℃伅鏃犳硶娓呴櫎鐨勯棶棰�+## 1.2.5锛�021-08-11锛�+- 浼樺寲 缁勪欢鏂囨。
+## 1.2.4锛�021-08-11锛�+- 淇 琛ㄥ崟楠岃瘉鍙敓鏁堜竴娆$殑闂
+## 1.2.3锛�021-07-30锛�+- 浼樺寲 vue3涓嬩簨浠惰鍛婄殑闂
+## 1.2.2锛�021-07-26锛�+- 淇 vue2 涓嬫潯浠剁紪璇戝鑷磀estroyed鐢熷懡鍛ㄦ湡澶辨晥鐨凚ug
+- 淇 1.2.1 寮曡捣鐨勭ず渚嬪湪灏忕▼搴忓钩鍙版姤閿欑殑Bug
+## 1.2.1锛�021-07-22锛�+- 淇 鍔ㄦ�鏍¢獙琛ㄥ崟锛岄粯璁ゅ�涓虹┖鐨勬儏鍐典笅鏍¢獙澶辨晥鐨凚ug
+- 淇 涓嶆寚瀹歯ame灞炴�鏃讹紝杩愯鎶ラ敊鐨凚ug
+- 浼樺寲 label榛樿瀹藉害浠�5璋冩暣鑷�0锛屼娇required涓簍rue涓斿洓瀛楁椂涓嶆崲琛�+- 浼樺寲 缁勪欢绀轰緥锛屾柊澧炲姩鎬佹牎楠岀ず渚嬩唬鐮�+- 浼樺寲 缁勪欢鏂囨。锛屼娇鐢ㄦ柟寮忔洿娓呮櫚
+## 1.2.0锛�021-07-13锛�+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤簐ue3椤圭洰锛岃瑙�[uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+## 1.1.2锛�021-06-25锛�+- 淇 pattern 灞炴�鍦ㄥ井淇″皬绋嬪簭骞冲彴鏃犳晥鐨勯棶棰�+## 1.1.1锛�021-06-22锛�+- 淇 validate-trigger灞炴�涓簊ubmit涓攅rr-show-type灞炴�涓簍oast鏃朵笉鑳藉脊鍑虹殑Bug
+## 1.1.0锛�021-06-22锛�+- 淇 鍙啓setRules鏂规硶鑰屽鑷存牎楠屼笉鐢熸晥鐨凚ug
+- 淇 鐢变笂涓姙娉曞紩鍙戠殑閿欒鎻愮ず鏂囧瓧閿欎綅鐨凚ug
+## 1.0.48锛�021-06-21锛�+- 淇 涓嶈缃�label 灞炴� 锛屾棤娉曡缃甽abel鎻掓Ы鐨勯棶棰�+## 1.0.47锛�021-06-21锛�+- 淇 涓嶈缃甽abel灞炴�锛宭abel-width灞炴�涓嶇敓鏁堢殑bug
+- 淇 setRules 鏂规硶涓巖ules灞炴�鍐茬獊鐨勯棶棰�+## 1.0.46锛�021-06-04锛�+- 淇 鍔ㄦ�鍒犲噺鏁版嵁瀵艰嚧鎶ラ敊鐨勯棶棰�+## 1.0.45锛�021-06-04锛�+- 鏂板 modelValue 灞炴� 锛寁alue 鍗冲皢搴熷純
+## 1.0.44锛�021-06-02锛�+- 鏂板 uni-forms-item 鍙互璁剧疆鍗曠嫭鐨�rules
+- 鏂板 validate 浜嬩欢澧炲姞 keepitem 鍙傛暟锛屽彲浠ラ�鎷╅偅浜涘瓧娈典笉杩囨护
+- 浼樺寲 submit 浜嬩欢閲嶅懡鍚嶄负 validate
+## 1.0.43锛�021-05-12锛�+- 鏂板 缁勪欢绀轰緥鍦板潃
+## 1.0.42锛�021-04-30锛�+- 淇 鑷畾涔夋楠屽櫒澶辨晥鐨勯棶棰�+## 1.0.41锛�021-03-05锛�+- 鏇存柊 鏍¢獙鍣�+- 淇 琛ㄥ崟瑙勫垯璁剧疆绫诲瀷涓�number 鐨勬儏鍐典笅锛屽�涓�鏍¢獙澶辫触鐨凚ug
+## 1.0.40锛�021-03-04锛�+- 淇 鍔ㄦ�鏄剧ずuni-forms-item鐨勬儏鍐典笅锛宻ubmit 鏂规硶鑾峰彇鍊奸敊璇殑Bug
+## 1.0.39锛�021-02-05锛�+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
+- 淇 鏍¢獙鍣ㄤ紶鍏�int 绛夌被鍨�锛岃繑鍥濻tring绫诲瀷鐨凚ug
diff --git a/uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue b/uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue
new file mode 100644
index 0000000..c924882
--- /dev/null
+++ b/uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue
@@ -0,0 +1,632 @@
+<template>
+	<view class="uni-forms-item"
+		:class="['is-direction-' + localLabelPos ,border?'uni-forms-item--border':'' ,border && isFirstBorder?'is-first-border':'']">
+		<slot name="label">
+			<view class="uni-forms-item__label" :class="{'no-label':!label && !required}"
+				:style="{width:localLabelWidth,justifyContent: localLabelAlign}">
+				<text v-if="required" class="is-required">*</text>
+				<text>{{label}}</text>
+			</view>
+		</slot>
+		<!-- #ifndef APP-NVUE -->
+		<view class="uni-forms-item__content">
+			<slot></slot>
+			<view class="uni-forms-item__error" :class="{'msg--active':msg}">
+				<text>{{msg}}</text>
+			</view>
+		</view>
+		<!-- #endif -->
+		<!-- #ifdef APP-NVUE -->
+		<view class="uni-forms-item__nuve-content">
+			<view class="uni-forms-item__content">
+				<slot></slot>
+			</view>
+			<view class="uni-forms-item__error" :class="{'msg--active':msg}">
+				<text class="error-text">{{msg}}</text>
+			</view>
+		</view>
+		<!-- #endif -->
+	</view>
+</template>
+
+<script>
+	/**
+	 * uni-fomrs-item 琛ㄥ崟瀛愮粍浠�+	 * @description uni-fomrs-item 琛ㄥ崟瀛愮粍浠讹紝鎻愪緵浜嗗熀纭�竷灞�凡缁忔牎楠岃兘鍔�+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=2773
+	 * @property {Boolean} required 鏄惁蹇呭~锛屽乏杈规樉绀虹孩鑹�*"鍙�+	 * @property {String } 	label 				杈撳叆妗嗗乏杈圭殑鏂囧瓧鎻愮ず
+	 * @property {Number } 	labelWidth 			label鐨勫搴︼紝鍗曚綅px锛堥粯璁�0锛�+	 * @property {String } 	labelAlign = [left|center|right] label鐨勬枃瀛楀榻愭柟寮忥紙榛樿left锛�+	 * 	@value left		label 宸︿晶鏄剧ず
+	 * 	@value center	label 灞呬腑
+	 * 	@value right	label 鍙充晶瀵归綈
+	 * @property {String } 	errorMessage 		鏄剧ず鐨勯敊璇彁绀哄唴瀹癸紝濡傛灉涓虹┖瀛楃涓叉垨鑰協alse锛屽垯涓嶆樉绀洪敊璇俊鎭�+	 * @property {String } 	name 				琛ㄥ崟鍩熺殑灞炴�鍚嶏紝鍦ㄤ娇鐢ㄦ牎楠岃鍒欐椂蹇呭~
+	 * @property {String } 	leftIcon 			銆�.4.0搴熷純銆憀abel宸﹁竟鐨勫浘鏍囷紝闄�uni-ui 鐨勫浘鏍囧悕绉�+	 * @property {String } 	iconColor 		銆�.4.0搴熷純銆戝乏杈归�杩噄con閰嶇疆鐨勫浘鏍囩殑棰滆壊锛堥粯璁�606266锛�+	 * @property {String} validateTrigger = [bind|submit|blur]	銆�.4.0搴熷純銆戞牎楠岃Е鍙戝櫒鏂瑰紡 榛樿 submit
+	 * 	@value bind 	鍙戠敓鍙樺寲鏃惰Е鍙�+	 * 	@value submit 鎻愪氦鏃惰Е鍙�+	 * 	@value blur 	澶卞幓鐒︾偣瑙﹀彂
+	 * @property {String } 	labelPosition = [top|left] 銆�.4.0搴熷純銆憀abel鐨勬枃瀛楃殑浣嶇疆锛堥粯璁eft锛�+	 * 	@value top	椤堕儴鏄剧ず label
+	 * 	@value left	宸︿晶鏄剧ず label
+	 */
+
+	export default {
+		name: 'uniFormsItem',
+		options: {
+			// #ifdef MP-TOUTIAO
+			virtualHost: false,
+			// #endif
+			// #ifndef MP-TOUTIAO
+			virtualHost: true
+			// #endif
+		},
+		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鐨勫搴�+			labelWidth: {
+				type: [String, Number],
+				default: ''
+			},
+			// label 灞呬腑鏂瑰紡锛岄粯璁�left 鍙栧� left/center/right
+			labelAlign: {
+				type: String,
+				default: ''
+			},
+			// 寮哄埗鏄剧ず閿欒淇℃伅
+			errorMessage: {
+				type: [String, Boolean],
+				default: ''
+			},
+			// 1.4.0 寮冪敤锛岀粺涓�娇鐢�form 鐨勬牎楠屾椂鏈�+			// validateTrigger: {
+			// 	type: String,
+			// 	default: ''
+			// },
+			// 1.4.0 寮冪敤锛岀粺涓�娇鐢�form 鐨刲abel 浣嶇疆
+			// labelPosition: {
+			// 	type: String,
+			// 	default: ''
+			// },
+			// 1.4.0 浠ヤ笅灞炴�宸茬粡搴熷純锛岃浣跨敤  #label 鎻掓Ы浠f浛
+			leftIcon: String,
+			iconColor: {
+				type: String,
+				default: '#606266'
+			},
+		},
+		data() {
+			return {
+				errMsg: '',
+				userRules: null,
+				localLabelAlign: 'left',
+				localLabelWidth: '70px',
+				localLabelPos: 'left',
+				border: false,
+				isFirstBorder: false,
+			};
+		},
+		computed: {
+			// 澶勭悊閿欒淇℃伅
+			msg() {
+				return this.errorMessage || this.errMsg;
+			}
+		},
+		watch: {
+			// 瑙勫垯鍙戠敓鍙樺寲閫氱煡瀛愮粍浠舵洿鏂�+			'form.formRules'(val) {
+				// TODO 澶勭悊澶存潯vue3 watch涓嶇敓鏁堢殑闂
+				// #ifndef MP-TOUTIAO
+				this.init()
+				// #endif
+			},
+			'form.labelWidth'(val) {
+				// 瀹藉害
+				this.localLabelWidth = this._labelWidthUnit(val)
+
+			},
+			'form.labelPosition'(val) {
+				// 鏍囩浣嶇疆
+				this.localLabelPos = this._labelPosition()
+			},
+			'form.labelAlign'(val) {
+
+			}
+		},
+		created() {
+			this.init(true)
+			if (this.name && this.form) {
+				// TODO 澶勭悊澶存潯vue3 watch涓嶇敓鏁堢殑闂
+				// #ifdef MP-TOUTIAO
+				this.$watch('form.formRules', () => {
+					this.init()
+				})
+				// #endif
+
+				// 鐩戝惉鍙樺寲
+				this.$watch(
+					() => {
+						const val = this.form._getDataValue(this.name, this.form.localData)
+						return val
+					},
+					(value, oldVal) => {
+						const isEqual = this.form._isEqual(value, oldVal)
+						// 绠�崟鍒ゆ柇鍓嶅悗鍊肩殑鍙樺寲锛屽彧鏈夊彂鐢熷彉鍖栨墠浼氬彂鐢熸牎楠�+						// TODO  濡傛灉 oldVal = undefined 锛岄偅涔堝ぇ姒傜巼鏄簮鏁版嵁閲屾病鏈夊�瀵艰嚧 锛岃繖涓儏鍐典笉鍝︽牎楠�,鍙兘涓嶄弗璋�锛岄渶瑕佸湪鍋氳瀵�+						// fix by mehaotian 鏆傛椂鍙栨秷 && oldVal !== undefined 锛屽鏋渇ormData 涓笉瀛樺湪锛屽彲鑳戒細涓嶆牎楠�+						if (!isEqual) {
+							const val = this.itemSetValue(value)
+							this.onFieldChange(val, false)
+						}
+					}, {
+						immediate: false
+					}
+				);
+			}
+
+		},
+		// #ifndef VUE3
+		destroyed() {
+			if (this.__isUnmounted) return
+			this.unInit()
+		},
+		// #endif
+		// #ifdef VUE3
+		unmounted() {
+			this.__isUnmounted = true
+			this.unInit()
+		},
+		// #endif
+		methods: {
+			/**
+			 * 澶栭儴璋冪敤鏂规硶
+			 * 璁剧疆瑙勫垯 锛屼富瑕佺敤浜庡皬绋嬪簭鑷畾涔夋楠岃鍒�+			 * @param {Array} rules 瑙勫垯婧愭暟鎹�+			 */
+			setRules(rules = null) {
+				this.userRules = rules
+				this.init(false)
+			},
+			// 鍏煎鑰佺増鏈〃鍗曠粍浠�+			setValue() {
+				// console.log('setValue 鏂规硶宸茬粡寮冪敤锛岃浣跨敤鏈�柊鐗堟湰鐨�uni-forms 琛ㄥ崟缁勪欢浠ュ強鍏朵粬鍏宠仈缁勪欢銆�);
+			},
+			/**
+			 * 澶栭儴璋冪敤鏂规硶
+			 * 鏍¢獙鏁版嵁
+			 * @param {any} value 闇�鏍¢獙鐨勬暟鎹�+			 * @param {boolean} 鏄惁绔嬪嵆鏍¢獙
+			 * @return {Array|null} 鏍¢獙鍐呭
+			 */
+			async onFieldChange(value, formtrigger = true) {
+				const {
+					formData,
+					localData,
+					errShowType,
+					validateCheck,
+					validateTrigger,
+					_isRequiredField,
+					_realName
+				} = this.form
+				const name = _realName(this.name)
+				if (!value) {
+					value = this.form.formData[name]
+				}
+				// fixd by mehaotian 涓嶅湪鏍¢獙鍓嶆竻绌轰俊鎭紝瑙e喅闂睆鐨勯棶棰�+				// this.errMsg = '';
+
+				// fix by mehaotian 瑙e喅娌℃湁妫�獙瑙勫垯鐨勬儏鍐典笅锛屾姏鍑洪敊璇殑闂
+				const ruleLen = this.itemRules.rules && this.itemRules.rules.length
+				if (!this.validator || !ruleLen || ruleLen === 0) return;
+
+				// 妫�獙鏃舵満
+				// let trigger = this.isTrigger(this.itemRules.validateTrigger, this.validateTrigger, validateTrigger);
+				const isRequiredField = _isRequiredField(this.itemRules.rules || []);
+				let result = null;
+				// 鍙湁绛変簬 bind 鏃�锛屾墠鑳藉紑鍚椂瀹炴牎楠�+				if (validateTrigger === 'bind' || formtrigger) {
+					// 鏍¢獙褰撳墠琛ㄥ崟椤�+					result = await this.validator.validateUpdate({
+							[name]: value
+						},
+						formData
+					);
+
+					// 鍒ゆ柇鏄惁蹇呭~,闈炲繀濉紝涓嶅~涓嶆牎楠岋紝濉啓鎵嶆牎楠�,鏆傛椂鍙鐞�undefined  鍜岀┖鐨勬儏鍐�+					if (!isRequiredField && (value === undefined || value === '')) {
+						result = null;
+					}
+
+					// 鍒ゆ柇閿欒淇℃伅鏄剧ず绫诲瀷
+					if (result && result.errorMessage) {
+						if (errShowType === 'undertext') {
+							// 鑾峰彇閿欒淇℃伅
+							this.errMsg = !result ? '' : result.errorMessage;
+						}
+						if (errShowType === 'toast') {
+							uni.showToast({
+								title: result.errorMessage || '鏍¢獙閿欒',
+								icon: 'none'
+							});
+						}
+						if (errShowType === 'modal') {
+							uni.showModal({
+								title: '鎻愮ず',
+								content: result.errorMessage || '鏍¢獙閿欒'
+							});
+						}
+					} else {
+						this.errMsg = ''
+					}
+					// 閫氱煡 form 缁勪欢鏇存柊浜嬩欢
+					validateCheck(result ? result : null)
+				} else {
+					this.errMsg = ''
+				}
+				return result ? result : null;
+			},
+			/**
+			 * 鍒濆缁勪欢鏁版嵁
+			 */
+			init(type = false) {
+				const {
+					validator,
+					formRules,
+					childrens,
+					formData,
+					localData,
+					_realName,
+					labelWidth,
+					_getDataValue,
+					_setDataValue
+				} = this.form || {}
+				// 瀵归綈鏂瑰紡
+				this.localLabelAlign = this._justifyContent()
+				// 瀹藉害
+				this.localLabelWidth = this._labelWidthUnit(labelWidth)
+				// 鏍囩浣嶇疆
+				this.localLabelPos = this._labelPosition()
+				// 灏嗛渶瑕佹牎楠岀殑瀛愮粍浠跺姞鍏orm 闃熷垪
+				this.form && type && childrens.push(this)
+
+				if (!validator || !formRules) return
+				// 鍒ゆ柇绗竴涓�item
+				if (!this.form.isFirstBorder) {
+					this.form.isFirstBorder = true;
+					this.isFirstBorder = true;
+				}
+
+				// 鍒ゆ柇 group 閲岀殑绗竴涓�item
+				if (this.group) {
+					if (!this.group.isFirstBorder) {
+						this.group.isFirstBorder = true;
+						this.isFirstBorder = true;
+					}
+				}
+				this.border = this.form.border;
+				// 鑾峰彇瀛愬煙鐨勭湡瀹炲悕绉�+				const name = _realName(this.name)
+				const itemRule = this.userRules || this.rules
+				if (typeof formRules === 'object' && itemRule) {
+					// 瀛愯鍒欐浛鎹㈢埗瑙勫垯
+					formRules[name] = {
+						rules: itemRule
+					}
+					validator.updateSchema(formRules);
+				}
+				// 娉ㄥ唽鏍¢獙瑙勫垯
+				const itemRules = formRules[name] || {}
+				this.itemRules = itemRules
+				// 娉ㄥ唽鏍¢獙鍑芥暟
+				this.validator = validator
+				// 榛樿鍊艰祴浜�+				this.itemSetValue(_getDataValue(this.name, localData))
+			},
+			unInit() {
+				if (this.form) {
+					const {
+						childrens,
+						formData,
+						_realName
+					} = this.form
+					childrens.forEach((item, index) => {
+						if (item === this) {
+							this.form.childrens.splice(index, 1)
+							delete formData[_realName(item.name)]
+						}
+					})
+				}
+			},
+			// 璁剧疆item 鐨勫�
+			itemSetValue(value) {
+				const name = this.form._realName(this.name)
+				const rules = this.itemRules.rules || []
+				const val = this.form._getValue(name, value, rules)
+				this.form._setDataValue(name, this.form.formData, val)
+				return val
+			},
+
+			/**
+			 * 绉婚櫎璇ヨ〃鍗曢」鐨勬牎楠岀粨鏋�+			 */
+			clearValidate() {
+				this.errMsg = '';
+			},
+
+			// 鏄惁鏄剧ず鏄熷彿
+			_isRequired() {
+				// TODO 涓嶆牴鎹鍒欐樉绀�鏄熷彿锛岃�铏戝悗缁吋瀹�+				// if (this.form) {
+				// 	if (this.form._isRequiredField(this.itemRules.rules || []) && this.required) {
+				// 		return true
+				// 	}
+				// 	return false
+				// }
+				return this.required
+			},
+
+			// 澶勭悊瀵归綈鏂瑰紡
+			_justifyContent() {
+				if (this.form) {
+					const {
+						labelAlign
+					} = this.form
+					let labelAli = this.labelAlign ? this.labelAlign : labelAlign;
+					if (labelAli === 'left') return 'flex-start';
+					if (labelAli === 'center') return 'center';
+					if (labelAli === 'right') return 'flex-end';
+				}
+				return 'flex-start';
+			},
+			// 澶勭悊 label瀹藉害鍗曚綅 ,缁ф壙鐖跺厓绱犵殑鍊�+			_labelWidthUnit(labelWidth) {
+
+				// if (this.form) {
+				// 	const {
+				// 		labelWidth
+				// 	} = this.form
+				return this.num2px(this.labelWidth ? this.labelWidth : (labelWidth || (this.label ? 70 : 'auto')))
+				// }
+				// return '70px'
+			},
+			// 澶勭悊 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/uni_modules/uni-forms/components/uni-forms/uni-forms.vue b/uni_modules/uni-forms/components/uni-forms/uni-forms.vue
new file mode 100644
index 0000000..d061313
--- /dev/null
+++ b/uni_modules/uni-forms/components/uni-forms/uni-forms.vue
@@ -0,0 +1,404 @@
+<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 瀹藉害锛岄粯璁�70px
+	 * @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: {
+			// #ifdef MP-TOUTIAO
+			virtualHost: false,
+			// #endif
+			// #ifndef MP-TOUTIAO
+			virtualHost: true
+			// #endif
+		},
+		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 灞炴�');
+						if(formVm.model)formVm.model[name] = value
+						if(formVm.modelValue)formVm.modelValue[name] = value
+						if(formVm.value)formVm.value[name] = value
+					}
+				}
+			}
+			// #endif
+
+			// 瀛愮粍浠跺疄渚嬫暟缁�+			this.childrens = []
+			// TODO 鍏煎鏃х増 uni-data-picker ,鏂扮増鏈腑鏃犳晥锛屽彧鏄伩鍏嶆姤閿�+			this.inputChildrens = []
+			this.setRules(this.rules)
+		},
+		methods: {
+			/**
+			 * 澶栭儴璋冪敤鏂规硶
+			 * 璁剧疆瑙勫垯 锛屼富瑕佺敤浜庡皬绋嬪簭鑷畾涔夋楠岃鍒�+			 * @param {Array} rules 瑙勫垯婧愭暟鎹�+			 */
+			setRules(rules) {
+				// TODO 鏈夊彲鑳藉瓙缁勪欢鍚堝苟瑙勫垯鐨勬椂鏈烘瘮杩欎釜瑕佹棭锛屾墍浠ラ渶瑕佸悎骞跺璞�锛岃�涓嶆槸鐩存帴璧嬪�锛屽彲鑳戒細琚鐩�+				this.formRules = Object.assign({}, this.formRules, rules)
+				// 鍒濆鍖栨牎楠屽嚱鏁�+				this.validator = new Validator(rules);
+			},
+
+			/**
+			 * 澶栭儴璋冪敤鏂规硶
+			 * 璁剧疆鏁版嵁锛岀敤浜庤缃〃鍗曟暟鎹紝鍏紑缁欑敤鎴蜂娇鐢�锛�涓嶆敮鎸佸湪鍔ㄦ�琛ㄥ崟涓娇鐢�+			 * @param {Object} key
+			 * @param {Object} value
+			 */
+			setValue(key, value) {
+				let example = this.childrens.find(child => child.name === key);
+				if (!example) return null;
+				this.formData[key] = getValue(key, value, (this.formRules[key] && this.formRules[key].rules) || [])
+				return example.onFieldChange(this.formData[key]);
+			},
+
+			/**
+			 * 澶栭儴璋冪敤鏂规硶
+			 * 鎵嬪姩鎻愪氦鏍¢獙琛ㄥ崟
+			 * 瀵规暣涓〃鍗曡繘琛屾牎楠岀殑鏂规硶锛屽弬鏁颁负涓�釜鍥炶皟鍑芥暟銆�+			 * @param {Array} keepitem 淇濈暀涓嶅弬涓庢牎楠岀殑瀛楁
+			 * @param {type} callback 鏂规硶鍥炶皟
+			 */
+			validate(keepitem, callback) {
+				return this.checkAll(this.formData, keepitem, callback);
+			},
+
+			/**
+			 * 澶栭儴璋冪敤鏂规硶
+			 * 閮ㄥ垎琛ㄥ崟鏍¢獙
+			 * @param {Array|String} props 闇�鏍¢獙鐨勫瓧娈�+			 * @param {Function} 鍥炶皟鍑芥暟
+			 */
+			validateField(props = [], callback) {
+				props = [].concat(props);
+				let invalidFields = {};
+				this.childrens.forEach(item => {
+					const name = realName(item.name)
+					if (props.indexOf(name) !== -1) {
+						invalidFields = Object.assign({}, invalidFields, {
+							[name]: this.formData[name]
+						});
+					}
+				});
+				return this.checkAll(invalidFields, [], callback);
+			},
+
+			/**
+			 * 澶栭儴璋冪敤鏂规硶
+			 * 绉婚櫎琛ㄥ崟椤圭殑鏍¢獙缁撴灉銆備紶鍏ュ緟绉婚櫎鐨勮〃鍗曢」鐨�prop 灞炴�鎴栬� prop 缁勬垚鐨勬暟缁勶紝濡備笉浼犲垯绉婚櫎鏁翠釜琛ㄥ崟鐨勬牎楠岀粨鏋�+			 * @param {Array|String} props 闇�绉婚櫎鏍¢獙鐨勫瓧娈�锛屼笉濉负鎵�湁
+			 */
+			clearValidate(props = []) {
+				props = [].concat(props);
+				this.childrens.forEach(item => {
+					if (props.length === 0) {
+						item.errMsg = '';
+					} else {
+						const name = realName(item.name)
+						if (props.indexOf(name) !== -1) {
+							item.errMsg = '';
+						}
+					}
+				});
+			},
+
+			/**
+			 * 澶栭儴璋冪敤鏂规硶 锛屽嵆灏嗗簾寮�+			 * 鎵嬪姩鎻愪氦鏍¢獙琛ㄥ崟
+			 * 瀵规暣涓〃鍗曡繘琛屾牎楠岀殑鏂规硶锛屽弬鏁颁负涓�釜鍥炶皟鍑芥暟銆�+			 * @param {Array} keepitem 淇濈暀涓嶅弬涓庢牎楠岀殑瀛楁
+			 * @param {type} callback 鏂规硶鍥炶皟
+			 */
+			submit(keepitem, callback, type) {
+				for (let i in this.dataValue) {
+					const itemData = this.childrens.find(v => v.name === i);
+					if (itemData) {
+						if (this.formData[i] === undefined) {
+							this.formData[i] = this._getValue(i, this.dataValue[i]);
+						}
+					}
+				}
+
+				if (!type) {
+					console.warn('submit 鏂规硶鍗冲皢搴熷純锛岃浣跨敤validate鏂规硶浠f浛锛�);
+				}
+
+				return this.checkAll(this.formData, keepitem, callback, 'submit');
+			},
+
+			// 鏍¢獙鎵�湁
+			async checkAll(invalidFields, keepitem, callback, type) {
+				// 涓嶅瓨鍦ㄦ牎楠岃鍒�锛屽垯鍋滄鏍¢獙娴佺▼
+				if (!this.validator) return
+				let childrens = []
+				// 澶勭悊鍙備笌鏍¢獙鐨刬tem瀹炰緥
+				for (let i in invalidFields) {
+					const item = this.childrens.find(v => realName(v.name) === i)
+					if (item) {
+						childrens.push(item)
+					}
+				}
+
+				// 濡傛灉validate绗竴涓弬鏁版槸funciont ,閭e氨璧板洖璋�+				if (!callback && typeof keepitem === 'function') {
+					callback = keepitem;
+				}
+
+				let promise;
+				// 濡傛灉涓嶅瓨鍦ㄥ洖璋冿紝閭d箞浣跨敤 Promise 鏂瑰紡杩斿洖
+				if (!callback && typeof callback !== 'function' && Promise) {
+					promise = new Promise((resolve, reject) => {
+						callback = function(valid, invalidFields) {
+							!valid ? resolve(invalidFields) : reject(valid);
+						};
+					});
+				}
+
+				let results = [];
+				// 閬垮厤寮曠敤閿欎贡 锛屽缓璁嫹璐濆璞″鐞�+				let tempFormData = JSON.parse(JSON.stringify(invalidFields))
+				// 鎵�湁瀛愮粍浠跺弬涓庢牎楠�浣跨敤 for 鍙互浣跨敤  awiat
+				for (let i in childrens) {
+					const child = childrens[i]
+					let name = realName(child.name);
+					const result = await child.onFieldChange(tempFormData[name]);
+					if (result) {
+						results.push(result);
+						// toast ,modal 鍙渶瑕佹墽琛岀涓�灏卞彲浠�+						if (this.errShowType === 'toast' || this.errShowType === 'modal') break;
+					}
+				}
+
+
+				if (Array.isArray(results)) {
+					if (results.length === 0) results = null;
+				}
+				if (Array.isArray(keepitem)) {
+					keepitem.forEach(v => {
+						let vName = realName(v);
+						let value = getDataValue(v, this.localData)
+						if (value !== undefined) {
+							tempFormData[vName] = value
+						}
+					});
+				}
+
+				// TODO submit 鍗冲皢搴熷純
+				if (type === 'submit') {
+					this.$emit('submit', {
+						detail: {
+							value: tempFormData,
+							errors: results
+						}
+					});
+				} else {
+					this.$emit('validate', results);
+				}
+
+				// const resetFormData = rawData(tempFormData, this.localData, this.name)
+				let resetFormData = {}
+				resetFormData = rawData(tempFormData, this.name)
+				callback && typeof callback === 'function' && callback(results, resetFormData);
+
+				if (promise && callback) {
+					return promise;
+				} else {
+					return null;
+				}
+
+			},
+
+			/**
+			 * 杩斿洖validate浜嬩欢
+			 * @param {Object} result
+			 */
+			validateCheck(result) {
+				this.$emit('validate', result);
+			},
+			_getValue: getValue,
+			_isRequiredField: isRequiredField,
+			_setDataValue: setDataValue,
+			_getDataValue: getDataValue,
+			_realName: realName,
+			_isRealName: isRealName,
+			_isEqual: isEqual
+		}
+	};
+</script>
+
+<style lang="scss">
+	.uni-forms {}
+</style>
diff --git a/uni_modules/uni-forms/components/uni-forms/utils.js b/uni_modules/uni-forms/components/uni-forms/utils.js
new file mode 100644
index 0000000..6da2421
--- /dev/null
+++ b/uni_modules/uni-forms/components/uni-forms/utils.js
@@ -0,0 +1,293 @@
+/**
+ * 绠�崟澶勭悊瀵硅薄鎷疯礉
+ * @param {Obejct} 琚嫹璐濆璞�+ * @@return {Object} 鎷疯礉瀵硅薄
+ */
+export const deepCopy = (val) => {
+	return JSON.parse(JSON.stringify(val))
+}
+/**
+ * 杩囨护鏁板瓧绫诲瀷
+ * @param {String} format 鏁板瓧绫诲瀷
+ * @@return {Boolean} 杩斿洖鏄惁涓烘暟瀛楃被鍨�+ */
+export const typeFilter = (format) => {
+	return format === 'int' || format === 'double' || format === 'number' || format === 'timestamp';
+}
+
+/**
+ * 鎶�value 杞崲鎴愭寚瀹氱殑绫诲瀷锛岀敤浜庡鐞嗗垵濮嬪�锛屽師鍥犳槸鍒濆鍊奸渶瑕佸叆搴撲笉鑳戒负 undefined
+ * @param {String} key 瀛楁鍚�+ * @param {any} value 瀛楁鍊�+ * @param {Object} rules 琛ㄥ崟鏍¢獙瑙勫垯
+ */
+export const getValue = (key, value, rules) => {
+	const isRuleNumType = rules.find(val => val.format && typeFilter(val.format));
+	const isRuleBoolType = rules.find(val => (val.format && val.format === 'boolean') || val.format === 'bool');
+	// 杈撳叆绫诲瀷涓�number
+	if (!!isRuleNumType) {
+		if (!value && value !== 0) {
+			value = null
+		} else {
+			value = isNumber(Number(value)) ? Number(value) : value
+		}
+	}
+
+	// 杈撳叆绫诲瀷涓�boolean
+	if (!!isRuleBoolType) {
+		value = isBoolean(value) ? value : false
+	}
+
+	return value;
+}
+
+/**
+ * 鑾峰彇琛ㄥ崟鏁版嵁
+ * @param {String|Array} name 鐪熷疄鍚嶇О锛岄渶瑕佷娇鐢�realName 鑾峰彇
+ * @param {Object} data 鍘熷鏁版嵁
+ * @param {any} value  闇�璁剧疆鐨勫�
+ */
+export const setDataValue = (field, formdata, value) => {
+	formdata[field] = value
+	return value || ''
+}
+
+/**
+ * 鑾峰彇琛ㄥ崟鏁版嵁
+ * @param {String|Array} field 鐪熷疄鍚嶇О锛岄渶瑕佷娇鐢�realName 鑾峰彇
+ * @param {Object} data 鍘熷鏁版嵁
+ */
+export const getDataValue = (field, data) => {
+	return objGet(data, field)
+}
+
+/**
+ * 鑾峰彇琛ㄥ崟绫诲瀷
+ * @param {String|Array} field 鐪熷疄鍚嶇О锛岄渶瑕佷娇鐢�realName 鑾峰彇
+ */
+export const getDataValueType = (field, data) => {
+	const value = getDataValue(field, data)
+	return {
+		type: type(value),
+		value
+	}
+}
+
+/**
+ * 鑾峰彇琛ㄥ崟鍙敤鐨勭湡瀹瀗ame
+ * @param {String|Array} name 琛ㄥ崟name
+ * @@return {String} 琛ㄥ崟鍙敤鐨勭湡瀹瀗ame
+ */
+export const realName = (name, data = {}) => {
+	const base_name = _basePath(name)
+	if (typeof base_name === 'object' && Array.isArray(base_name) && base_name.length > 1) {
+		const realname = base_name.reduce((a, b) => a += `#${b}`, '_formdata_')
+		return realname
+	}
+	return base_name[0] || name
+}
+
+/**
+ * 鍒ゆ柇鏄惁琛ㄥ崟鍙敤鐨勭湡瀹瀗ame
+ * @param {String|Array} name 琛ㄥ崟name
+ * @@return {String} 琛ㄥ崟鍙敤鐨勭湡瀹瀗ame
+ */
+export const isRealName = (name) => {
+	const reg = /^_formdata_#*/
+	return reg.test(name)
+}
+
+/**
+ * 鑾峰彇琛ㄥ崟鏁版嵁鐨勫師濮嬫牸寮�+ * @@return {Object|Array} object 闇�瑙f瀽鐨勬暟鎹�+ */
+export const rawData = (object = {}, name) => {
+	let newData = JSON.parse(JSON.stringify(object))
+	let formData = {}
+	for(let i in newData){
+		let path = name2arr(i)
+		objSet(formData,path,newData[i])
+	}
+	return formData
+}
+
+/**
+ * 鐪熷疄name杩樺師涓�array
+ * @param {*} name 
+ */
+export const name2arr = (name) => {
+	let field = name.replace('_formdata_#', '')
+	field = field.split('#').map(v => (isNumber(v) ? Number(v) : v))
+	return field
+}
+
+/**
+ * 瀵硅薄涓缃�
+ * @param {Object|Array} object 婧愭暟鎹�+ * @param {String| Array} path 'a.b.c' 鎴�['a',0,'b','c']
+ * @param {String} value 闇�璁剧疆鐨勫�
+ */
+export const objSet = (object, path, value) => {
+	if (typeof object !== 'object') return object;
+	_basePath(path).reduce((o, k, i, _) => {
+		if (i === _.length - 1) { 
+			// 鑻ラ亶鍘嗙粨鏉熺洿鎺ヨ祴鍊�+			o[k] = value
+			return null
+		} else if (k in o) { 
+			// 鑻ュ瓨鍦ㄥ搴旇矾寰勶紝鍒欒繑鍥炴壘鍒扮殑瀵硅薄锛岃繘琛屼笅涓�閬嶅巻
+			return o[k]
+		} else { 
+			// 鑻ヤ笉瀛樺湪瀵瑰簲璺緞锛屽垯鍒涘缓瀵瑰簲瀵硅薄锛岃嫢涓嬩竴璺緞鏄暟瀛楋紝鏂板璞¤祴鍊间负绌烘暟缁勶紝鍚﹀垯璧嬪�涓虹┖瀵硅薄
+			o[k] = /^[0-9]{1,}$/.test(_[i + 1]) ? [] : {}
+			return o[k]
+		}
+	}, object)
+	// 杩斿洖object
+	return object;
+}
+
+// 澶勭悊 path锛�path鏈変笁绉嶅舰寮忥細'a[0].b.c'銆�a.0.b.c' 鍜�['a','0','b','c']锛岄渶瑕佺粺涓�鐞嗘垚鏁扮粍锛屼究浜庡悗缁娇鐢�+function _basePath(path) {
+	// 鑻ユ槸鏁扮粍锛屽垯鐩存帴杩斿洖
+	if (Array.isArray(path)) return path
+	// 鑻ユ湁 '[',']'锛屽垯鏇挎崲鎴愬皢 '[' 鏇挎崲鎴�'.',鍘绘帀 ']'
+	return path.replace(/\[/g, '.').replace(/\]/g, '').split('.')
+}
+
+/**
+ * 浠庡璞′腑鑾峰彇鍊�+ * @param {Object|Array} object 婧愭暟鎹�+ * @param {String| Array} path 'a.b.c' 鎴�['a',0,'b','c']
+ * @param {String} defaultVal 濡傛灉鏃犳硶浠庤皟鐢ㄩ摼涓幏鍙栧�鐨勯粯璁ゅ�
+ */
+export const objGet = (object, path, defaultVal = 'undefined') => {
+	// 鍏堝皢path澶勭悊鎴愮粺涓�牸寮�+	let newPath = _basePath(path)
+	// 閫掑綊澶勭悊锛岃繑鍥炴渶鍚庣粨鏋�+	let val = newPath.reduce((o, k) => {
+		return (o || {})[k]
+	}, object);
+	return !val || val !== undefined ? val : defaultVal
+}
+
+
+/**
+ * 鏄惁涓�number 绫诲瀷 
+ * @param {any} num 闇�鍒ゆ柇鐨勫�
+ * @return {Boolean} 鏄惁涓�number
+ */
+export const isNumber = (num) => {
+	return !isNaN(Number(num))
+}
+
+/**
+ * 鏄惁涓�boolean 绫诲瀷 
+ * @param {any} bool 闇�鍒ゆ柇鐨勫�
+ * @return {Boolean} 鏄惁涓�boolean
+ */
+export const isBoolean = (bool) => {
+	return (typeof bool === 'boolean')
+}
+/**
+ * 鏄惁鏈夊繀濉瓧娈�+ * @param {Object} rules 瑙勫垯
+ * @return {Boolean} 鏄惁鏈夊繀濉瓧娈�+ */
+export const isRequiredField = (rules) => {
+	let isNoField = false;
+	for (let i = 0; i < rules.length; i++) {
+		const ruleData = rules[i];
+		if (ruleData.required) {
+			isNoField = true;
+			break;
+		}
+	}
+	return isNoField;
+}
+
+
+/**
+ * 鑾峰彇鏁版嵁绫诲瀷
+ * @param {Any} obj 闇�鑾峰彇鏁版嵁绫诲瀷鐨勫�
+ */
+export const type = (obj) => {
+	var class2type = {};
+
+	// 鐢熸垚class2type鏄犲皠
+	"Boolean Number String Function Array Date RegExp Object Error".split(" ").map(function(item, index) {
+		class2type["[object " + item + "]"] = item.toLowerCase();
+	})
+	if (obj == null) {
+		return obj + "";
+	}
+	return typeof obj === "object" || typeof obj === "function" ?
+		class2type[Object.prototype.toString.call(obj)] || "object" :
+		typeof obj;
+}
+
+/**
+ * 鍒ゆ柇涓や釜鍊兼槸鍚︾浉绛�+ * @param {any} a 鍊� 
+ * @param {any} b 鍊� 
+ * @return {Boolean} 鏄惁鐩哥瓑
+ */
+export const isEqual = (a, b) => {
+	//濡傛灉a鍜宐鏈潵灏卞叏绛�+	if (a === b) {
+		//鍒ゆ柇鏄惁涓�鍜�0
+		return a !== 0 || 1 / a === 1 / b;
+	}
+	//鍒ゆ柇鏄惁涓簄ull鍜寀ndefined
+	if (a == null || b == null) {
+		return a === b;
+	}
+	//鎺ヤ笅鏉ュ垽鏂璦鍜宐鐨勬暟鎹被鍨�+	var classNameA = toString.call(a),
+		classNameB = toString.call(b);
+	//濡傛灉鏁版嵁绫诲瀷涓嶇浉绛夛紝鍒欒繑鍥瀎alse
+	if (classNameA !== classNameB) {
+		return false;
+	}
+	//濡傛灉鏁版嵁绫诲瀷鐩哥瓑锛屽啀鏍规嵁涓嶅悓鏁版嵁绫诲瀷鍒嗗埆鍒ゆ柇
+	switch (classNameA) {
+		case '[object RegExp]':
+		case '[object String]':
+			//杩涜瀛楃涓茶浆鎹㈡瘮杈�+			return '' + a === '' + b;
+		case '[object Number]':
+			//杩涜鏁板瓧杞崲姣旇緝,鍒ゆ柇鏄惁涓篘aN
+			if (+a !== +a) {
+				return +b !== +b;
+			}
+			//鍒ゆ柇鏄惁涓�鎴�0
+			return +a === 0 ? 1 / +a === 1 / b : +a === +b;
+		case '[object Date]':
+		case '[object Boolean]':
+			return +a === +b;
+	}
+	//濡傛灉鏄璞$被鍨�+	if (classNameA == '[object Object]') {
+		//鑾峰彇a鍜宐鐨勫睘鎬ч暱搴�+		var propsA = Object.getOwnPropertyNames(a),
+			propsB = Object.getOwnPropertyNames(b);
+		if (propsA.length != propsB.length) {
+			return false;
+		}
+		for (var i = 0; i < propsA.length; i++) {
+			var propName = propsA[i];
+			//濡傛灉瀵瑰簲灞炴�瀵瑰簲鍊间笉鐩哥瓑锛屽垯杩斿洖false
+			if (a[propName] !== b[propName]) {
+				return false;
+			}
+		}
+		return true;
+	}
+	//濡傛灉鏄暟缁勭被鍨�+	if (classNameA == '[object Array]') {
+		if (a.toString() == b.toString()) {
+			return true;
+		}
+		return false;
+	}
+}
diff --git a/uni_modules/uni-forms/components/uni-forms/validate.js b/uni_modules/uni-forms/components/uni-forms/validate.js
new file mode 100644
index 0000000..1834c6c
--- /dev/null
+++ b/uni_modules/uni-forms/components/uni-forms/validate.js
@@ -0,0 +1,486 @@
+var pattern = {
+	email: /^\S+?@\S+?\.\S+?$/,
+	idcard: /^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/,
+	url: new RegExp(
+		"^(?!mailto:)(?:(?:http|https|ftp)://|//)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-*)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-*)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?$",
+		'i')
+};
+
+const FORMAT_MAPPING = {
+	"int": 'integer',
+	"bool": 'boolean',
+	"double": 'number',
+	"long": 'number',
+	"password": 'string'
+	// "fileurls": 'array'
+}
+
+function formatMessage(args, resources = '') {
+	var defaultMessage = ['label']
+	defaultMessage.forEach((item) => {
+		if (args[item] === undefined) {
+			args[item] = ''
+		}
+	})
+
+	let str = resources
+	for (let key in args) {
+		let reg = new RegExp('{' + key + '}')
+		str = str.replace(reg, args[key])
+	}
+	return str
+}
+
+function isEmptyValue(value, type) {
+	if (value === undefined || value === null) {
+		return true;
+	}
+
+	if (typeof value === 'string' && !value) {
+		return true;
+	}
+
+	if (Array.isArray(value) && !value.length) {
+		return true;
+	}
+
+	if (type === 'object' && !Object.keys(value).length) {
+		return true;
+	}
+
+	return false;
+}
+
+const types = {
+	integer(value) {
+		return types.number(value) && parseInt(value, 10) === value;
+	},
+	string(value) {
+		return typeof value === 'string';
+	},
+	number(value) {
+		if (isNaN(value)) {
+			return false;
+		}
+		return typeof value === 'number';
+	},
+	"boolean": function(value) {
+		return typeof value === 'boolean';
+	},
+	"float": function(value) {
+		return types.number(value) && !types.integer(value);
+	},
+	array(value) {
+		return Array.isArray(value);
+	},
+	object(value) {
+		return typeof value === 'object' && !types.array(value);
+	},
+	date(value) {
+		return value instanceof Date;
+	},
+	timestamp(value) {
+		if (!this.integer(value) || Math.abs(value).toString().length > 16) {
+			return false
+		}
+		return true;
+	},
+	file(value) {
+		return typeof value.url === 'string';
+	},
+	email(value) {
+		return typeof value === 'string' && !!value.match(pattern.email) && value.length < 255;
+	},
+	url(value) {
+		return typeof value === 'string' && !!value.match(pattern.url);
+	},
+	pattern(reg, value) {
+		try {
+			return new RegExp(reg).test(value);
+		} catch (e) {
+			return false;
+		}
+	},
+	method(value) {
+		return typeof value === 'function';
+	},
+	idcard(value) {
+		return typeof value === 'string' && !!value.match(pattern.idcard);
+	},
+	'url-https'(value) {
+		return this.url(value) && value.startsWith('https://');
+	},
+	'url-scheme'(value) {
+		return value.startsWith('://');
+	},
+	'url-web'(value) {
+		return false;
+	}
+}
+
+class RuleValidator {
+
+	constructor(message) {
+		this._message = message
+	}
+
+	async validateRule(fieldKey, fieldValue, value, data, allData) {
+		var result = null
+
+		let rules = fieldValue.rules
+
+		let hasRequired = rules.findIndex((item) => {
+			return item.required
+		})
+		if (hasRequired < 0) {
+			if (value === null || value === undefined) {
+				return result
+			}
+			if (typeof value === 'string' && !value.length) {
+				return result
+			}
+		}
+
+		var message = this._message
+
+		if (rules === undefined) {
+			return message['default']
+		}
+
+		for (var i = 0; i < rules.length; i++) {
+			let rule = rules[i]
+			let vt = this._getValidateType(rule)
+
+			Object.assign(rule, {
+				label: fieldValue.label || `["${fieldKey}"]`
+			})
+
+			if (RuleValidatorHelper[vt]) {
+				result = RuleValidatorHelper[vt](rule, value, message)
+				if (result != null) {
+					break
+				}
+			}
+
+			if (rule.validateExpr) {
+				let now = Date.now()
+				let resultExpr = rule.validateExpr(value, allData, now)
+				if (resultExpr === false) {
+					result = this._getMessage(rule, rule.errorMessage || this._message['default'])
+					break
+				}
+			}
+
+			if (rule.validateFunction) {
+				result = await this.validateFunction(rule, value, data, allData, vt)
+				if (result !== null) {
+					break
+				}
+			}
+		}
+
+		if (result !== null) {
+			result = message.TAG + result
+		}
+
+		return result
+	}
+
+	async validateFunction(rule, value, data, allData, vt) {
+		let result = null
+		try {
+			let callbackMessage = null
+			const res = await rule.validateFunction(rule, value, allData || data, (message) => {
+				callbackMessage = message
+			})
+			if (callbackMessage || (typeof res === 'string' && res) || res === false) {
+				result = this._getMessage(rule, callbackMessage || res, vt)
+			}
+		} catch (e) {
+			result = this._getMessage(rule, e.message, vt)
+		}
+		return result
+	}
+
+	_getMessage(rule, message, vt) {
+		return formatMessage(rule, message || rule.errorMessage || this._message[vt] || message['default'])
+	}
+
+	_getValidateType(rule) {
+		var result = ''
+		if (rule.required) {
+			result = 'required'
+		} else if (rule.format) {
+			result = 'format'
+		} else if (rule.arrayType) {
+			result = 'arrayTypeFormat'
+		} else if (rule.range) {
+			result = 'range'
+		} else if (rule.maximum !== undefined || rule.minimum !== undefined) {
+			result = 'rangeNumber'
+		} else if (rule.maxLength !== undefined || rule.minLength !== undefined) {
+			result = 'rangeLength'
+		} else if (rule.pattern) {
+			result = 'pattern'
+		} else if (rule.validateFunction) {
+			result = 'validateFunction'
+		}
+		return result
+	}
+}
+
+const RuleValidatorHelper = {
+	required(rule, value, message) {
+		if (rule.required && isEmptyValue(value, rule.format || typeof value)) {
+			return formatMessage(rule, rule.errorMessage || message.required);
+		}
+
+		return null
+	},
+
+	range(rule, value, message) {
+		const {
+			range,
+			errorMessage
+		} = rule;
+
+		let list = new Array(range.length);
+		for (let i = 0; i < range.length; i++) {
+			const item = range[i];
+			if (types.object(item) && item.value !== undefined) {
+				list[i] = item.value;
+			} else {
+				list[i] = item;
+			}
+		}
+
+		let result = false
+		if (Array.isArray(value)) {
+			result = (new Set(value.concat(list)).size === list.length);
+		} else {
+			if (list.indexOf(value) > -1) {
+				result = true;
+			}
+		}
+
+		if (!result) {
+			return formatMessage(rule, errorMessage || message['enum']);
+		}
+
+		return null
+	},
+
+	rangeNumber(rule, value, message) {
+		if (!types.number(value)) {
+			return formatMessage(rule, rule.errorMessage || message.pattern.mismatch);
+		}
+
+		let {
+			minimum,
+			maximum,
+			exclusiveMinimum,
+			exclusiveMaximum
+		} = rule;
+		let min = exclusiveMinimum ? value <= minimum : value < minimum;
+		let max = exclusiveMaximum ? value >= maximum : value > maximum;
+
+		if (minimum !== undefined && min) {
+			return formatMessage(rule, rule.errorMessage || message['number'][exclusiveMinimum ?
+				'exclusiveMinimum' : 'minimum'
+			])
+		} else if (maximum !== undefined && max) {
+			return formatMessage(rule, rule.errorMessage || message['number'][exclusiveMaximum ?
+				'exclusiveMaximum' : 'maximum'
+			])
+		} else if (minimum !== undefined && maximum !== undefined && (min || max)) {
+			return formatMessage(rule, rule.errorMessage || message['number'].range)
+		}
+
+		return null
+	},
+
+	rangeLength(rule, value, message) {
+		if (!types.string(value) && !types.array(value)) {
+			return formatMessage(rule, rule.errorMessage || message.pattern.mismatch);
+		}
+
+		let min = rule.minLength;
+		let max = rule.maxLength;
+		let val = value.length;
+
+		if (min !== undefined && val < min) {
+			return formatMessage(rule, rule.errorMessage || message['length'].minLength)
+		} else if (max !== undefined && val > max) {
+			return formatMessage(rule, rule.errorMessage || message['length'].maxLength)
+		} else if (min !== undefined && max !== undefined && (val < min || val > max)) {
+			return formatMessage(rule, rule.errorMessage || message['length'].range)
+		}
+
+		return null
+	},
+
+	pattern(rule, value, message) {
+		if (!types['pattern'](rule.pattern, value)) {
+			return formatMessage(rule, rule.errorMessage || message.pattern.mismatch);
+		}
+
+		return null
+	},
+
+	format(rule, value, message) {
+		var customTypes = Object.keys(types);
+		var format = FORMAT_MAPPING[rule.format] ? FORMAT_MAPPING[rule.format] : (rule.format || rule.arrayType);
+
+		if (customTypes.indexOf(format) > -1) {
+			if (!types[format](value)) {
+				return formatMessage(rule, rule.errorMessage || message.typeError);
+			}
+		}
+
+		return null
+	},
+
+	arrayTypeFormat(rule, value, message) {
+		if (!Array.isArray(value)) {
+			return formatMessage(rule, rule.errorMessage || message.typeError);
+		}
+
+		for (let i = 0; i < value.length; i++) {
+			const element = value[i];
+			let formatResult = this.format(rule, element, message)
+			if (formatResult !== null) {
+				return formatResult
+			}
+		}
+
+		return null
+	}
+}
+
+class SchemaValidator extends RuleValidator {
+
+	constructor(schema, options) {
+		super(SchemaValidator.message);
+
+		this._schema = schema
+		this._options = options || null
+	}
+
+	updateSchema(schema) {
+		this._schema = schema
+	}
+
+	async validate(data, allData) {
+		let result = this._checkFieldInSchema(data)
+		if (!result) {
+			result = await this.invokeValidate(data, false, allData)
+		}
+		return result.length ? result[0] : null
+	}
+
+	async validateAll(data, allData) {
+		let result = this._checkFieldInSchema(data)
+		if (!result) {
+			result = await this.invokeValidate(data, true, allData)
+		}
+		return result
+	}
+
+	async validateUpdate(data, allData) {
+		let result = this._checkFieldInSchema(data)
+		if (!result) {
+			result = await this.invokeValidateUpdate(data, false, allData)
+		}
+		return result.length ? result[0] : null
+	}
+
+	async invokeValidate(data, all, allData) {
+		let result = []
+		let schema = this._schema
+		for (let key in schema) {
+			let value = schema[key]
+			let errorMessage = await this.validateRule(key, value, data[key], data, allData)
+			if (errorMessage != null) {
+				result.push({
+					key,
+					errorMessage
+				})
+				if (!all) break
+			}
+		}
+		return result
+	}
+
+	async invokeValidateUpdate(data, all, allData) {
+		let result = []
+		for (let key in data) {
+			let errorMessage = await this.validateRule(key, this._schema[key], data[key], data, allData)
+			if (errorMessage != null) {
+				result.push({
+					key,
+					errorMessage
+				})
+				if (!all) break
+			}
+		}
+		return result
+	}
+
+	_checkFieldInSchema(data) {
+		var keys = Object.keys(data)
+		var keys2 = Object.keys(this._schema)
+		if (new Set(keys.concat(keys2)).size === keys2.length) {
+			return ''
+		}
+
+		var noExistFields = keys.filter((key) => {
+			return keys2.indexOf(key) < 0;
+		})
+		var errorMessage = formatMessage({
+			field: JSON.stringify(noExistFields)
+		}, SchemaValidator.message.TAG + SchemaValidator.message['defaultInvalid'])
+		return [{
+			key: 'invalid',
+			errorMessage
+		}]
+	}
+}
+
+function Message() {
+	return {
+		TAG: "",
+		default: '楠岃瘉閿欒',
+		defaultInvalid: '鎻愪氦鐨勫瓧娈祘field}鍦ㄦ暟鎹簱涓苟涓嶅瓨鍦�,
+		validateFunction: '楠岃瘉鏃犳晥',
+		required: '{label}蹇呭~',
+		'enum': '{label}瓒呭嚭鑼冨洿',
+		timestamp: '{label}鏍煎紡鏃犳晥',
+		whitespace: '{label}涓嶈兘涓虹┖',
+		typeError: '{label}绫诲瀷鏃犳晥',
+		date: {
+			format: '{label}鏃ユ湡{value}鏍煎紡鏃犳晥',
+			parse: '{label}鏃ユ湡鏃犳硶瑙f瀽,{value}鏃犳晥',
+			invalid: '{label}鏃ユ湡{value}鏃犳晥'
+		},
+		length: {
+			minLength: '{label}闀垮害涓嶈兘灏戜簬{minLength}',
+			maxLength: '{label}闀垮害涓嶈兘瓒呰繃{maxLength}',
+			range: '{label}蹇呴』浠嬩簬{minLength}鍜寋maxLength}涔嬮棿'
+		},
+		number: {
+			minimum: '{label}涓嶈兘灏忎簬{minimum}',
+			maximum: '{label}涓嶈兘澶т簬{maximum}',
+			exclusiveMinimum: '{label}涓嶈兘灏忎簬绛変簬{minimum}',
+			exclusiveMaximum: '{label}涓嶈兘澶т簬绛変簬{maximum}',
+			range: '{label}蹇呴』浠嬩簬{minimum}and{maximum}涔嬮棿'
+		},
+		pattern: {
+			mismatch: '{label}鏍煎紡涓嶅尮閰�
+		}
+	};
+}
+
+
+SchemaValidator.message = new Message();
+
+export default SchemaValidator
diff --git a/uni_modules/uni-forms/package.json b/uni_modules/uni-forms/package.json
new file mode 100644
index 0000000..0d72c63
--- /dev/null
+++ b/uni_modules/uni-forms/package.json
@@ -0,0 +1,89 @@
+{
+  "id": "uni-forms",
+  "displayName": "uni-forms 琛ㄥ崟",
+  "version": "1.4.13",
+  "description": "鐢辫緭鍏ユ銆侀�鎷╁櫒銆佸崟閫夋銆佸閫夋绛夋帶浠剁粍鎴愶紝鐢ㄤ互鏀堕泦銆佹牎楠屻�鎻愪氦鏁版嵁",
+  "keywords": [
+    "uni-ui",
+    "琛ㄥ崟",
+    "鏍¢獙",
+    "琛ㄥ崟鏍¢獙",
+    "琛ㄥ崟楠岃瘉"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+"dcloudext": {
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "鏃�,
+      "data": "鏃�,
+      "permissions": "鏃�
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+    "type": "component-vue"
+  },
+  "uni_modules": {
+    "dependencies": [
+			"uni-scss",
+      "uni-icons"
+    ],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y",
+        "alipay": "n"
+      },
+      "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/uni_modules/uni-forms/readme.md b/uni_modules/uni-forms/readme.md
new file mode 100644
index 0000000..63d5a04
--- /dev/null
+++ b/uni_modules/uni-forms/readme.md
@@ -0,0 +1,23 @@
+
+
+## Forms 琛ㄥ崟
+
+> **缁勪欢鍚嶏細uni-forms**
+> 浠g爜鍧楋細 `uForms`銆乣uni-forms-item`
+> 鍏宠仈缁勪欢锛歚uni-forms-item`銆乣uni-easyinput`銆乣uni-data-checkbox`銆乣uni-group`銆�+
+
+uni-app鐨勫唴缃粍浠跺凡缁忔湁浜�`<form>`缁勪欢锛岀敤浜庢彁浜よ〃鍗曞唴瀹广�
+
+鐒惰�鍑犱箮姣忎釜琛ㄥ崟閮介渶瑕佸仛琛ㄥ崟楠岃瘉锛屼负浜嗘柟渚垮仛琛ㄥ崟楠岃瘉锛屽噺灏戦噸澶嶅紑鍙戯紝`uni ui` 鍙堝熀浜�`<form>`缁勪欢灏佽浜�`<uni-forms>`缁勪欢锛屽唴缃簡琛ㄥ崟楠岃瘉鍔熻兘銆�+
+`<uni-forms>` 鎻愪緵浜�`rules`灞炴�鏉ユ弿杩版牎楠岃鍒欍�`<uni-forms-item>`瀛愮粍浠舵潵鍖呰9鍏蜂綋鐨勮〃鍗曢」锛屼互鍙婄粰鍘熺敓鎴栦笁鏂圭粍浠舵彁渚涗簡 `binddata()` 鏉ヨ缃〃鍗曞�銆�+
+姣忎釜瑕佹牎楠岀殑琛ㄥ崟椤癸紝涓嶇input杩樻槸checkbox锛岄兘蹇呴』鏀惧湪`<uni-forms-item>`缁勪欢涓紝涓斾竴涓猔<uni-forms-item>`缁勪欢鍙兘鏀剧疆涓�釜琛ㄥ崟椤广�
+
+`<uni-forms-item>`缁勪欢鍐呴儴棰勭暀浜嗘樉绀篹rror message鐨勫尯鍩燂紝榛樿鏄湪琛ㄥ崟椤圭殑搴曢儴銆�+
+鍙﹀锛宍<uni-forms>`缁勪欢涓嬮潰鐨勫悇涓〃鍗曢」锛屽彲浠ラ�杩嘸<uni-group>`鍖呰9涓轰笉鍚岀殑鍒嗙粍銆傚悓涓�<uni-group>`涓嬬殑涓嶅悓琛ㄥ崟椤圭洰灏嗚仛鎷㈠湪涓�捣锛屽悓鍏朵粬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/uni_modules/uni-icons/changelog.md b/uni_modules/uni-icons/changelog.md
new file mode 100644
index 0000000..0261131
--- /dev/null
+++ b/uni_modules/uni-icons/changelog.md
@@ -0,0 +1,42 @@
+## 2.0.10锛�024-06-07锛�+- 浼樺寲 uni-app x 涓紝size 灞炴�鐨勭被鍨�+## 2.0.9锛�024-01-12锛�+fix: 淇鍥炬爣澶у皬榛樿鍊奸敊璇殑闂
+## 2.0.8锛�023-12-14锛�+- 淇 椤圭洰鏈娇鐢�ts 鎯呭喌涓嬶紝鎵撳寘鎶ラ敊鐨刡ug
+## 2.0.7锛�023-12-14锛�+- 淇 size 灞炴�涓�string 鏃讹紝涓嶅姞鍗曚綅瀵艰嚧灏哄寮傚父鐨刡ug
+## 2.0.6锛�023-12-11锛�+- 浼樺寲 鍏煎鑰佺増鏈琲con绫诲瀷锛屽 top 锛宐ottom 绛�+## 2.0.5锛�023-12-11锛�+- 浼樺寲 鍏煎鑰佺増鏈琲con绫诲瀷锛屽 top 锛宐ottom 绛�+## 2.0.4锛�023-12-06锛�+- 浼樺寲 uni-app x 涓嬬ず渚嬮」鐩浘鏍囨帓搴�+## 2.0.3锛�023-12-06锛�+- 淇 nvue涓嬪紩鍏ョ粍浠舵姤閿欑殑bug
+## 2.0.2锛�023-12-05锛�+-浼樺寲 size 灞炴�鏀寔鍗曚綅
+## 2.0.1锛�023-12-05锛�+- 鏂板 uni-app x 鏀寔瀹氫箟鍥炬爣
+## 1.3.5锛�022-01-24锛�+- 浼樺寲 size 灞炴�鍙互浼犲叆涓嶅甫鍗曚綅鐨勫瓧绗︿覆鏁板�
+## 1.3.4锛�022-01-24锛�+- 浼樺寲 size 鏀寔鍏朵粬鍗曚綅
+## 1.3.3锛�022-01-17锛�+- 淇 nvue 鏈変簺鍥炬爣涓嶆樉绀虹殑bug锛屽吋瀹硅�鐗堟湰鍥炬爣
+## 1.3.2锛�021-12-01锛�+- 浼樺寲 绀轰緥鍙鍒跺浘鏍囧悕绉�+## 1.3.1锛�021-11-23锛�+- 浼樺寲 鍏煎鏃х粍浠�type 鍊�+## 1.3.0锛�021-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锛�021-11-08锛�+## 1.2.0锛�021-07-30锛�+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤簐ue3椤圭洰锛岃瑙�[uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+## 1.1.5锛�021-05-12锛�+- 鏂板 缁勪欢绀轰緥鍦板潃
+## 1.1.4锛�021-02-05锛�+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
diff --git a/uni_modules/uni-icons/components/uni-icons/uni-icons.uvue b/uni_modules/uni-icons/components/uni-icons/uni-icons.uvue
new file mode 100644
index 0000000..8740559
--- /dev/null
+++ b/uni_modules/uni-icons/components/uni-icons/uni-icons.uvue
@@ -0,0 +1,91 @@
+<template>
+  <text class="uni-icons" :style="styleObj">
+    <slot>{{unicode}}</slot>
+  </text>
+</template>
+
+<script>
+  import { fontData, IconsDataItem } from './uniicons_file'
+
+  /**
+   * Icons 鍥炬爣
+   * @description 鐢ㄤ簬灞曠ず icon 鍥炬爣
+   * @tutorial https://ext.dcloud.net.cn/plugin?id=28
+   * @property {Number,String} size 鍥炬爣澶у皬
+   * @property {String} type 鍥炬爣鍥炬锛屽弬鑰冪ず渚�+   * @property {String} color 鍥炬爣棰滆壊
+   * @property {String} customPrefix 鑷畾涔夊浘鏍�+   * @event {Function} click 鐐瑰嚮 Icon 瑙﹀彂浜嬩欢
+   */
+  export default {
+    name: "uni-icons",
+    props: {
+      type: {
+        type: String,
+        default: ''
+      },
+      color: {
+        type: String,
+        default: '#333333'
+      },
+      size: {
+        type: [Number, String],
+        default: 16
+      },
+      fontFamily: {
+        type: String,
+        default: ''
+      }
+    },
+    data() {
+      return {};
+    },
+    computed: {
+      unicode() : string {
+        let codes = fontData.find((item : IconsDataItem) : boolean => { return item.font_class == this.type })
+        if (codes !== null) {
+          return codes.unicode
+        }
+        return ''
+      },
+      iconSize() : string {
+        const size = this.size
+        if (typeof size == 'string') {
+          const reg = /^[0-9]*$/g
+          return reg.test(size as string) ? '' + size + 'px' : '' + size;
+          // return '' + this.size
+        }
+        return this.getFontSize(size as number)
+      },
+      styleObj() : UTSJSONObject {
+        if (this.fontFamily !== '') {
+          return { color: this.color, fontSize: this.iconSize, fontFamily: this.fontFamily }
+        }
+        return { color: this.color, fontSize: this.iconSize }
+      }
+    },
+    created() { },
+    methods: {
+      /**
+       * 瀛椾綋澶у皬
+       */
+      getFontSize(size : number) : string {
+        return size + 'px';
+      },
+    },
+  }
+</script>
+
+<style scoped>
+  @font-face {
+    font-family: UniIconsFontFamily;
+    src: url('./uniicons.ttf');
+  }
+
+  .uni-icons {
+    font-family: UniIconsFontFamily;
+    font-size: 18px;
+    font-style: normal;
+    color: #333;
+  }
+</style>
diff --git a/uni_modules/uni-icons/components/uni-icons/uni-icons.vue b/uni_modules/uni-icons/components/uni-icons/uni-icons.vue
new file mode 100644
index 0000000..7da5356
--- /dev/null
+++ b/uni_modules/uni-icons/components/uni-icons/uni-icons.vue
@@ -0,0 +1,110 @@
+<template>
+	<!-- #ifdef APP-NVUE -->
+	<text :style="styleObj" class="uni-icons" @click="_onClick">{{unicode}}</text>
+	<!-- #endif -->
+	<!-- #ifndef APP-NVUE -->
+	<text :style="styleObj" class="uni-icons" :class="['uniui-'+type,customPrefix,customPrefix?type:'']" @click="_onClick">
+		<slot></slot>
+	</text>
+	<!-- #endif -->
+</template>
+
+<script>
+	import { fontData } from './uniicons_file_vue.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: ''
+			},
+			fontFamily: {
+				type: String,
+				default: ''
+			}
+		},
+		data() {
+			return {
+				icons: fontData
+			}
+		},
+		computed: {
+			unicode() {
+				let code = this.icons.find(v => v.font_class === this.type)
+				if (code) {
+					return code.unicode
+				}
+				return ''
+			},
+			iconSize() {
+				return getVal(this.size)
+			},
+			styleObj() {
+				if (this.fontFamily !== '') {
+					return `color: ${this.color}; font-size: ${this.iconSize}; font-family: ${this.fontFamily};`
+				}
+				return `color: ${this.color}; font-size: ${this.iconSize};`
+			}
+		},
+		methods: {
+			_onClick() {
+				this.$emit('click')
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	/* #ifndef APP-NVUE */
+	@import './uniicons.css';
+
+	@font-face {
+		font-family: uniicons;
+		src: url('./uniicons.ttf');
+	}
+
+	/* #endif */
+	.uni-icons {
+		font-family: uniicons;
+		text-decoration: none;
+		text-align: center;
+	}
+</style>
diff --git a/uni_modules/uni-icons/components/uni-icons/uniicons.css b/uni_modules/uni-icons/components/uni-icons/uniicons.css
new file mode 100644
index 0000000..0a6b6fe
--- /dev/null
+++ b/uni_modules/uni-icons/components/uni-icons/uniicons.css
@@ -0,0 +1,664 @@
+
+.uniui-cart-filled:before {
+  content: "\e6d0";
+}
+
+.uniui-gift-filled:before {
+  content: "\e6c4";
+}
+
+.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-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-arrowthinleft:before {
+  content: "\e6d2";
+}
+
+.uniui-arrowthinup:before {
+  content: "\e6d3";
+}
+
+.uniui-arrowthindown:before {
+  content: "\e6d4";
+}
+
+.uniui-back:before {
+  content: "\e6b9";
+}
+
+.uniui-forward:before {
+  content: "\e6ba";
+}
+
+.uniui-arrow-right:before {
+  content: "\e6bb";
+}
+
+.uniui-arrow-left:before {
+  content: "\e6bc";
+}
+
+.uniui-arrow-up:before {
+  content: "\e6bd";
+}
+
+.uniui-arrow-down:before {
+  content: "\e6be";
+}
+
+.uniui-arrowthinright:before {
+  content: "\e6d1";
+}
+
+.uniui-down:before {
+  content: "\e6b8";
+}
+
+.uniui-bottom:before {
+  content: "\e6b8";
+}
+
+.uniui-arrowright:before {
+  content: "\e6d5";
+}
+
+.uniui-right:before {
+  content: "\e6b5";
+}
+
+.uniui-up:before {
+  content: "\e6b6";
+}
+
+.uniui-top:before {
+  content: "\e6b6";
+}
+
+.uniui-left:before {
+  content: "\e6b7";
+}
+
+.uniui-arrowup:before {
+  content: "\e6d6";
+}
+
+.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-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/uni_modules/uni-icons/components/uni-icons/uniicons.ttf b/uni_modules/uni-icons/components/uni-icons/uniicons.ttf
new file mode 100644
index 0000000..14696d0
--- /dev/null
+++ b/uni_modules/uni-icons/components/uni-icons/uniicons.ttf
Binary files differ
diff --git a/uni_modules/uni-icons/components/uni-icons/uniicons_file.ts b/uni_modules/uni-icons/components/uni-icons/uniicons_file.ts
new file mode 100644
index 0000000..98e93aa
--- /dev/null
+++ b/uni_modules/uni-icons/components/uni-icons/uniicons_file.ts
@@ -0,0 +1,664 @@
+
+export type IconsData = {
+	id : string
+	name : string
+	font_family : string
+	css_prefix_text : string
+	description : string
+	glyphs : Array<IconsDataItem>
+}
+
+export type IconsDataItem = {
+	font_class : string
+	unicode : string
+}
+
+
+export const fontData = [
+  {
+    "font_class": "arrow-down",
+    "unicode": "\ue6be"
+  },
+  {
+    "font_class": "arrow-left",
+    "unicode": "\ue6bc"
+  },
+  {
+    "font_class": "arrow-right",
+    "unicode": "\ue6bb"
+  },
+  {
+    "font_class": "arrow-up",
+    "unicode": "\ue6bd"
+  },
+  {
+    "font_class": "auth",
+    "unicode": "\ue6ab"
+  },
+  {
+    "font_class": "auth-filled",
+    "unicode": "\ue6cc"
+  },
+  {
+    "font_class": "back",
+    "unicode": "\ue6b9"
+  },
+  {
+    "font_class": "bars",
+    "unicode": "\ue627"
+  },
+  {
+    "font_class": "calendar",
+    "unicode": "\ue6a0"
+  },
+  {
+    "font_class": "calendar-filled",
+    "unicode": "\ue6c0"
+  },
+  {
+    "font_class": "camera",
+    "unicode": "\ue65a"
+  },
+  {
+    "font_class": "camera-filled",
+    "unicode": "\ue658"
+  },
+  {
+    "font_class": "cart",
+    "unicode": "\ue631"
+  },
+  {
+    "font_class": "cart-filled",
+    "unicode": "\ue6d0"
+  },
+  {
+    "font_class": "chat",
+    "unicode": "\ue65d"
+  },
+  {
+    "font_class": "chat-filled",
+    "unicode": "\ue659"
+  },
+  {
+    "font_class": "chatboxes",
+    "unicode": "\ue696"
+  },
+  {
+    "font_class": "chatboxes-filled",
+    "unicode": "\ue692"
+  },
+  {
+    "font_class": "chatbubble",
+    "unicode": "\ue697"
+  },
+  {
+    "font_class": "chatbubble-filled",
+    "unicode": "\ue694"
+  },
+  {
+    "font_class": "checkbox",
+    "unicode": "\ue62b"
+  },
+  {
+    "font_class": "checkbox-filled",
+    "unicode": "\ue62c"
+  },
+  {
+    "font_class": "checkmarkempty",
+    "unicode": "\ue65c"
+  },
+  {
+    "font_class": "circle",
+    "unicode": "\ue65b"
+  },
+  {
+    "font_class": "circle-filled",
+    "unicode": "\ue65e"
+  },
+  {
+    "font_class": "clear",
+    "unicode": "\ue66d"
+  },
+  {
+    "font_class": "close",
+    "unicode": "\ue673"
+  },
+  {
+    "font_class": "closeempty",
+    "unicode": "\ue66c"
+  },
+  {
+    "font_class": "cloud-download",
+    "unicode": "\ue647"
+  },
+  {
+    "font_class": "cloud-download-filled",
+    "unicode": "\ue646"
+  },
+  {
+    "font_class": "cloud-upload",
+    "unicode": "\ue645"
+  },
+  {
+    "font_class": "cloud-upload-filled",
+    "unicode": "\ue648"
+  },
+  {
+    "font_class": "color",
+    "unicode": "\ue6cf"
+  },
+  {
+    "font_class": "color-filled",
+    "unicode": "\ue6c9"
+  },
+  {
+    "font_class": "compose",
+    "unicode": "\ue67f"
+  },
+  {
+    "font_class": "contact",
+    "unicode": "\ue693"
+  },
+  {
+    "font_class": "contact-filled",
+    "unicode": "\ue695"
+  },
+  {
+    "font_class": "down",
+    "unicode": "\ue6b8"
+  },
+	{
+	  "font_class": "bottom",
+	  "unicode": "\ue6b8"
+	},
+  {
+    "font_class": "download",
+    "unicode": "\ue68d"
+  },
+  {
+    "font_class": "download-filled",
+    "unicode": "\ue681"
+  },
+  {
+    "font_class": "email",
+    "unicode": "\ue69e"
+  },
+  {
+    "font_class": "email-filled",
+    "unicode": "\ue69a"
+  },
+  {
+    "font_class": "eye",
+    "unicode": "\ue651"
+  },
+  {
+    "font_class": "eye-filled",
+    "unicode": "\ue66a"
+  },
+  {
+    "font_class": "eye-slash",
+    "unicode": "\ue6b3"
+  },
+  {
+    "font_class": "eye-slash-filled",
+    "unicode": "\ue6b4"
+  },
+  {
+    "font_class": "fire",
+    "unicode": "\ue6a1"
+  },
+  {
+    "font_class": "fire-filled",
+    "unicode": "\ue6c5"
+  },
+  {
+    "font_class": "flag",
+    "unicode": "\ue65f"
+  },
+  {
+    "font_class": "flag-filled",
+    "unicode": "\ue660"
+  },
+  {
+    "font_class": "folder-add",
+    "unicode": "\ue6a9"
+  },
+  {
+    "font_class": "folder-add-filled",
+    "unicode": "\ue6c8"
+  },
+  {
+    "font_class": "font",
+    "unicode": "\ue6a3"
+  },
+  {
+    "font_class": "forward",
+    "unicode": "\ue6ba"
+  },
+  {
+    "font_class": "gear",
+    "unicode": "\ue664"
+  },
+  {
+    "font_class": "gear-filled",
+    "unicode": "\ue661"
+  },
+  {
+    "font_class": "gift",
+    "unicode": "\ue6a4"
+  },
+  {
+    "font_class": "gift-filled",
+    "unicode": "\ue6c4"
+  },
+  {
+    "font_class": "hand-down",
+    "unicode": "\ue63d"
+  },
+  {
+    "font_class": "hand-down-filled",
+    "unicode": "\ue63c"
+  },
+  {
+    "font_class": "hand-up",
+    "unicode": "\ue63f"
+  },
+  {
+    "font_class": "hand-up-filled",
+    "unicode": "\ue63e"
+  },
+  {
+    "font_class": "headphones",
+    "unicode": "\ue630"
+  },
+  {
+    "font_class": "heart",
+    "unicode": "\ue639"
+  },
+  {
+    "font_class": "heart-filled",
+    "unicode": "\ue641"
+  },
+  {
+    "font_class": "help",
+    "unicode": "\ue679"
+  },
+  {
+    "font_class": "help-filled",
+    "unicode": "\ue674"
+  },
+  {
+    "font_class": "home",
+    "unicode": "\ue662"
+  },
+  {
+    "font_class": "home-filled",
+    "unicode": "\ue663"
+  },
+  {
+    "font_class": "image",
+    "unicode": "\ue670"
+  },
+  {
+    "font_class": "image-filled",
+    "unicode": "\ue678"
+  },
+  {
+    "font_class": "images",
+    "unicode": "\ue650"
+  },
+  {
+    "font_class": "images-filled",
+    "unicode": "\ue64b"
+  },
+  {
+    "font_class": "info",
+    "unicode": "\ue669"
+  },
+  {
+    "font_class": "info-filled",
+    "unicode": "\ue649"
+  },
+  {
+    "font_class": "left",
+    "unicode": "\ue6b7"
+  },
+  {
+    "font_class": "link",
+    "unicode": "\ue6a5"
+  },
+  {
+    "font_class": "list",
+    "unicode": "\ue644"
+  },
+  {
+    "font_class": "location",
+    "unicode": "\ue6ae"
+  },
+  {
+    "font_class": "location-filled",
+    "unicode": "\ue6af"
+  },
+  {
+    "font_class": "locked",
+    "unicode": "\ue66b"
+  },
+  {
+    "font_class": "locked-filled",
+    "unicode": "\ue668"
+  },
+  {
+    "font_class": "loop",
+    "unicode": "\ue633"
+  },
+  {
+    "font_class": "mail-open",
+    "unicode": "\ue643"
+  },
+  {
+    "font_class": "mail-open-filled",
+    "unicode": "\ue63a"
+  },
+  {
+    "font_class": "map",
+    "unicode": "\ue667"
+  },
+  {
+    "font_class": "map-filled",
+    "unicode": "\ue666"
+  },
+  {
+    "font_class": "map-pin",
+    "unicode": "\ue6ad"
+  },
+  {
+    "font_class": "map-pin-ellipse",
+    "unicode": "\ue6ac"
+  },
+  {
+    "font_class": "medal",
+    "unicode": "\ue6a2"
+  },
+  {
+    "font_class": "medal-filled",
+    "unicode": "\ue6c3"
+  },
+  {
+    "font_class": "mic",
+    "unicode": "\ue671"
+  },
+  {
+    "font_class": "mic-filled",
+    "unicode": "\ue677"
+  },
+  {
+    "font_class": "micoff",
+    "unicode": "\ue67e"
+  },
+  {
+    "font_class": "micoff-filled",
+    "unicode": "\ue6b0"
+  },
+  {
+    "font_class": "minus",
+    "unicode": "\ue66f"
+  },
+  {
+    "font_class": "minus-filled",
+    "unicode": "\ue67d"
+  },
+  {
+    "font_class": "more",
+    "unicode": "\ue64d"
+  },
+  {
+    "font_class": "more-filled",
+    "unicode": "\ue64e"
+  },
+  {
+    "font_class": "navigate",
+    "unicode": "\ue66e"
+  },
+  {
+    "font_class": "navigate-filled",
+    "unicode": "\ue67a"
+  },
+  {
+    "font_class": "notification",
+    "unicode": "\ue6a6"
+  },
+  {
+    "font_class": "notification-filled",
+    "unicode": "\ue6c1"
+  },
+  {
+    "font_class": "paperclip",
+    "unicode": "\ue652"
+  },
+  {
+    "font_class": "paperplane",
+    "unicode": "\ue672"
+  },
+  {
+    "font_class": "paperplane-filled",
+    "unicode": "\ue675"
+  },
+  {
+    "font_class": "person",
+    "unicode": "\ue699"
+  },
+  {
+    "font_class": "person-filled",
+    "unicode": "\ue69d"
+  },
+  {
+    "font_class": "personadd",
+    "unicode": "\ue69f"
+  },
+  {
+    "font_class": "personadd-filled",
+    "unicode": "\ue698"
+  },
+  {
+    "font_class": "personadd-filled-copy",
+    "unicode": "\ue6d1"
+  },
+  {
+    "font_class": "phone",
+    "unicode": "\ue69c"
+  },
+  {
+    "font_class": "phone-filled",
+    "unicode": "\ue69b"
+  },
+  {
+    "font_class": "plus",
+    "unicode": "\ue676"
+  },
+  {
+    "font_class": "plus-filled",
+    "unicode": "\ue6c7"
+  },
+  {
+    "font_class": "plusempty",
+    "unicode": "\ue67b"
+  },
+  {
+    "font_class": "pulldown",
+    "unicode": "\ue632"
+  },
+  {
+    "font_class": "pyq",
+    "unicode": "\ue682"
+  },
+  {
+    "font_class": "qq",
+    "unicode": "\ue680"
+  },
+  {
+    "font_class": "redo",
+    "unicode": "\ue64a"
+  },
+  {
+    "font_class": "redo-filled",
+    "unicode": "\ue655"
+  },
+  {
+    "font_class": "refresh",
+    "unicode": "\ue657"
+  },
+  {
+    "font_class": "refresh-filled",
+    "unicode": "\ue656"
+  },
+  {
+    "font_class": "refreshempty",
+    "unicode": "\ue6bf"
+  },
+  {
+    "font_class": "reload",
+    "unicode": "\ue6b2"
+  },
+  {
+    "font_class": "right",
+    "unicode": "\ue6b5"
+  },
+  {
+    "font_class": "scan",
+    "unicode": "\ue62a"
+  },
+  {
+    "font_class": "search",
+    "unicode": "\ue654"
+  },
+  {
+    "font_class": "settings",
+    "unicode": "\ue653"
+  },
+  {
+    "font_class": "settings-filled",
+    "unicode": "\ue6ce"
+  },
+  {
+    "font_class": "shop",
+    "unicode": "\ue62f"
+  },
+  {
+    "font_class": "shop-filled",
+    "unicode": "\ue6cd"
+  },
+  {
+    "font_class": "smallcircle",
+    "unicode": "\ue67c"
+  },
+  {
+    "font_class": "smallcircle-filled",
+    "unicode": "\ue665"
+  },
+  {
+    "font_class": "sound",
+    "unicode": "\ue684"
+  },
+  {
+    "font_class": "sound-filled",
+    "unicode": "\ue686"
+  },
+  {
+    "font_class": "spinner-cycle",
+    "unicode": "\ue68a"
+  },
+  {
+    "font_class": "staff",
+    "unicode": "\ue6a7"
+  },
+  {
+    "font_class": "staff-filled",
+    "unicode": "\ue6cb"
+  },
+  {
+    "font_class": "star",
+    "unicode": "\ue688"
+  },
+  {
+    "font_class": "star-filled",
+    "unicode": "\ue68f"
+  },
+  {
+    "font_class": "starhalf",
+    "unicode": "\ue683"
+  },
+  {
+    "font_class": "trash",
+    "unicode": "\ue687"
+  },
+  {
+    "font_class": "trash-filled",
+    "unicode": "\ue685"
+  },
+  {
+    "font_class": "tune",
+    "unicode": "\ue6aa"
+  },
+  {
+    "font_class": "tune-filled",
+    "unicode": "\ue6ca"
+  },
+  {
+    "font_class": "undo",
+    "unicode": "\ue64f"
+  },
+  {
+    "font_class": "undo-filled",
+    "unicode": "\ue64c"
+  },
+  {
+    "font_class": "up",
+    "unicode": "\ue6b6"
+  },
+	{
+	  "font_class": "top",
+	  "unicode": "\ue6b6"
+	},
+  {
+    "font_class": "upload",
+    "unicode": "\ue690"
+  },
+  {
+    "font_class": "upload-filled",
+    "unicode": "\ue68e"
+  },
+  {
+    "font_class": "videocam",
+    "unicode": "\ue68c"
+  },
+  {
+    "font_class": "videocam-filled",
+    "unicode": "\ue689"
+  },
+  {
+    "font_class": "vip",
+    "unicode": "\ue6a8"
+  },
+  {
+    "font_class": "vip-filled",
+    "unicode": "\ue6c6"
+  },
+  {
+    "font_class": "wallet",
+    "unicode": "\ue6b1"
+  },
+  {
+    "font_class": "wallet-filled",
+    "unicode": "\ue6c2"
+  },
+  {
+    "font_class": "weibo",
+    "unicode": "\ue68b"
+  },
+  {
+    "font_class": "weixin",
+    "unicode": "\ue691"
+  }
+] as IconsDataItem[]
+
+// export const fontData = JSON.parse<IconsDataItem>(fontDataJson)
diff --git a/uni_modules/uni-icons/components/uni-icons/uniicons_file_vue.js b/uni_modules/uni-icons/components/uni-icons/uniicons_file_vue.js
new file mode 100644
index 0000000..1cd11e1
--- /dev/null
+++ b/uni_modules/uni-icons/components/uni-icons/uniicons_file_vue.js
@@ -0,0 +1,649 @@
+
+export const fontData = [
+  {
+    "font_class": "arrow-down",
+    "unicode": "\ue6be"
+  },
+  {
+    "font_class": "arrow-left",
+    "unicode": "\ue6bc"
+  },
+  {
+    "font_class": "arrow-right",
+    "unicode": "\ue6bb"
+  },
+  {
+    "font_class": "arrow-up",
+    "unicode": "\ue6bd"
+  },
+  {
+    "font_class": "auth",
+    "unicode": "\ue6ab"
+  },
+  {
+    "font_class": "auth-filled",
+    "unicode": "\ue6cc"
+  },
+  {
+    "font_class": "back",
+    "unicode": "\ue6b9"
+  },
+  {
+    "font_class": "bars",
+    "unicode": "\ue627"
+  },
+  {
+    "font_class": "calendar",
+    "unicode": "\ue6a0"
+  },
+  {
+    "font_class": "calendar-filled",
+    "unicode": "\ue6c0"
+  },
+  {
+    "font_class": "camera",
+    "unicode": "\ue65a"
+  },
+  {
+    "font_class": "camera-filled",
+    "unicode": "\ue658"
+  },
+  {
+    "font_class": "cart",
+    "unicode": "\ue631"
+  },
+  {
+    "font_class": "cart-filled",
+    "unicode": "\ue6d0"
+  },
+  {
+    "font_class": "chat",
+    "unicode": "\ue65d"
+  },
+  {
+    "font_class": "chat-filled",
+    "unicode": "\ue659"
+  },
+  {
+    "font_class": "chatboxes",
+    "unicode": "\ue696"
+  },
+  {
+    "font_class": "chatboxes-filled",
+    "unicode": "\ue692"
+  },
+  {
+    "font_class": "chatbubble",
+    "unicode": "\ue697"
+  },
+  {
+    "font_class": "chatbubble-filled",
+    "unicode": "\ue694"
+  },
+  {
+    "font_class": "checkbox",
+    "unicode": "\ue62b"
+  },
+  {
+    "font_class": "checkbox-filled",
+    "unicode": "\ue62c"
+  },
+  {
+    "font_class": "checkmarkempty",
+    "unicode": "\ue65c"
+  },
+  {
+    "font_class": "circle",
+    "unicode": "\ue65b"
+  },
+  {
+    "font_class": "circle-filled",
+    "unicode": "\ue65e"
+  },
+  {
+    "font_class": "clear",
+    "unicode": "\ue66d"
+  },
+  {
+    "font_class": "close",
+    "unicode": "\ue673"
+  },
+  {
+    "font_class": "closeempty",
+    "unicode": "\ue66c"
+  },
+  {
+    "font_class": "cloud-download",
+    "unicode": "\ue647"
+  },
+  {
+    "font_class": "cloud-download-filled",
+    "unicode": "\ue646"
+  },
+  {
+    "font_class": "cloud-upload",
+    "unicode": "\ue645"
+  },
+  {
+    "font_class": "cloud-upload-filled",
+    "unicode": "\ue648"
+  },
+  {
+    "font_class": "color",
+    "unicode": "\ue6cf"
+  },
+  {
+    "font_class": "color-filled",
+    "unicode": "\ue6c9"
+  },
+  {
+    "font_class": "compose",
+    "unicode": "\ue67f"
+  },
+  {
+    "font_class": "contact",
+    "unicode": "\ue693"
+  },
+  {
+    "font_class": "contact-filled",
+    "unicode": "\ue695"
+  },
+  {
+    "font_class": "down",
+    "unicode": "\ue6b8"
+  },
+	{
+	  "font_class": "bottom",
+	  "unicode": "\ue6b8"
+	},
+  {
+    "font_class": "download",
+    "unicode": "\ue68d"
+  },
+  {
+    "font_class": "download-filled",
+    "unicode": "\ue681"
+  },
+  {
+    "font_class": "email",
+    "unicode": "\ue69e"
+  },
+  {
+    "font_class": "email-filled",
+    "unicode": "\ue69a"
+  },
+  {
+    "font_class": "eye",
+    "unicode": "\ue651"
+  },
+  {
+    "font_class": "eye-filled",
+    "unicode": "\ue66a"
+  },
+  {
+    "font_class": "eye-slash",
+    "unicode": "\ue6b3"
+  },
+  {
+    "font_class": "eye-slash-filled",
+    "unicode": "\ue6b4"
+  },
+  {
+    "font_class": "fire",
+    "unicode": "\ue6a1"
+  },
+  {
+    "font_class": "fire-filled",
+    "unicode": "\ue6c5"
+  },
+  {
+    "font_class": "flag",
+    "unicode": "\ue65f"
+  },
+  {
+    "font_class": "flag-filled",
+    "unicode": "\ue660"
+  },
+  {
+    "font_class": "folder-add",
+    "unicode": "\ue6a9"
+  },
+  {
+    "font_class": "folder-add-filled",
+    "unicode": "\ue6c8"
+  },
+  {
+    "font_class": "font",
+    "unicode": "\ue6a3"
+  },
+  {
+    "font_class": "forward",
+    "unicode": "\ue6ba"
+  },
+  {
+    "font_class": "gear",
+    "unicode": "\ue664"
+  },
+  {
+    "font_class": "gear-filled",
+    "unicode": "\ue661"
+  },
+  {
+    "font_class": "gift",
+    "unicode": "\ue6a4"
+  },
+  {
+    "font_class": "gift-filled",
+    "unicode": "\ue6c4"
+  },
+  {
+    "font_class": "hand-down",
+    "unicode": "\ue63d"
+  },
+  {
+    "font_class": "hand-down-filled",
+    "unicode": "\ue63c"
+  },
+  {
+    "font_class": "hand-up",
+    "unicode": "\ue63f"
+  },
+  {
+    "font_class": "hand-up-filled",
+    "unicode": "\ue63e"
+  },
+  {
+    "font_class": "headphones",
+    "unicode": "\ue630"
+  },
+  {
+    "font_class": "heart",
+    "unicode": "\ue639"
+  },
+  {
+    "font_class": "heart-filled",
+    "unicode": "\ue641"
+  },
+  {
+    "font_class": "help",
+    "unicode": "\ue679"
+  },
+  {
+    "font_class": "help-filled",
+    "unicode": "\ue674"
+  },
+  {
+    "font_class": "home",
+    "unicode": "\ue662"
+  },
+  {
+    "font_class": "home-filled",
+    "unicode": "\ue663"
+  },
+  {
+    "font_class": "image",
+    "unicode": "\ue670"
+  },
+  {
+    "font_class": "image-filled",
+    "unicode": "\ue678"
+  },
+  {
+    "font_class": "images",
+    "unicode": "\ue650"
+  },
+  {
+    "font_class": "images-filled",
+    "unicode": "\ue64b"
+  },
+  {
+    "font_class": "info",
+    "unicode": "\ue669"
+  },
+  {
+    "font_class": "info-filled",
+    "unicode": "\ue649"
+  },
+  {
+    "font_class": "left",
+    "unicode": "\ue6b7"
+  },
+  {
+    "font_class": "link",
+    "unicode": "\ue6a5"
+  },
+  {
+    "font_class": "list",
+    "unicode": "\ue644"
+  },
+  {
+    "font_class": "location",
+    "unicode": "\ue6ae"
+  },
+  {
+    "font_class": "location-filled",
+    "unicode": "\ue6af"
+  },
+  {
+    "font_class": "locked",
+    "unicode": "\ue66b"
+  },
+  {
+    "font_class": "locked-filled",
+    "unicode": "\ue668"
+  },
+  {
+    "font_class": "loop",
+    "unicode": "\ue633"
+  },
+  {
+    "font_class": "mail-open",
+    "unicode": "\ue643"
+  },
+  {
+    "font_class": "mail-open-filled",
+    "unicode": "\ue63a"
+  },
+  {
+    "font_class": "map",
+    "unicode": "\ue667"
+  },
+  {
+    "font_class": "map-filled",
+    "unicode": "\ue666"
+  },
+  {
+    "font_class": "map-pin",
+    "unicode": "\ue6ad"
+  },
+  {
+    "font_class": "map-pin-ellipse",
+    "unicode": "\ue6ac"
+  },
+  {
+    "font_class": "medal",
+    "unicode": "\ue6a2"
+  },
+  {
+    "font_class": "medal-filled",
+    "unicode": "\ue6c3"
+  },
+  {
+    "font_class": "mic",
+    "unicode": "\ue671"
+  },
+  {
+    "font_class": "mic-filled",
+    "unicode": "\ue677"
+  },
+  {
+    "font_class": "micoff",
+    "unicode": "\ue67e"
+  },
+  {
+    "font_class": "micoff-filled",
+    "unicode": "\ue6b0"
+  },
+  {
+    "font_class": "minus",
+    "unicode": "\ue66f"
+  },
+  {
+    "font_class": "minus-filled",
+    "unicode": "\ue67d"
+  },
+  {
+    "font_class": "more",
+    "unicode": "\ue64d"
+  },
+  {
+    "font_class": "more-filled",
+    "unicode": "\ue64e"
+  },
+  {
+    "font_class": "navigate",
+    "unicode": "\ue66e"
+  },
+  {
+    "font_class": "navigate-filled",
+    "unicode": "\ue67a"
+  },
+  {
+    "font_class": "notification",
+    "unicode": "\ue6a6"
+  },
+  {
+    "font_class": "notification-filled",
+    "unicode": "\ue6c1"
+  },
+  {
+    "font_class": "paperclip",
+    "unicode": "\ue652"
+  },
+  {
+    "font_class": "paperplane",
+    "unicode": "\ue672"
+  },
+  {
+    "font_class": "paperplane-filled",
+    "unicode": "\ue675"
+  },
+  {
+    "font_class": "person",
+    "unicode": "\ue699"
+  },
+  {
+    "font_class": "person-filled",
+    "unicode": "\ue69d"
+  },
+  {
+    "font_class": "personadd",
+    "unicode": "\ue69f"
+  },
+  {
+    "font_class": "personadd-filled",
+    "unicode": "\ue698"
+  },
+  {
+    "font_class": "personadd-filled-copy",
+    "unicode": "\ue6d1"
+  },
+  {
+    "font_class": "phone",
+    "unicode": "\ue69c"
+  },
+  {
+    "font_class": "phone-filled",
+    "unicode": "\ue69b"
+  },
+  {
+    "font_class": "plus",
+    "unicode": "\ue676"
+  },
+  {
+    "font_class": "plus-filled",
+    "unicode": "\ue6c7"
+  },
+  {
+    "font_class": "plusempty",
+    "unicode": "\ue67b"
+  },
+  {
+    "font_class": "pulldown",
+    "unicode": "\ue632"
+  },
+  {
+    "font_class": "pyq",
+    "unicode": "\ue682"
+  },
+  {
+    "font_class": "qq",
+    "unicode": "\ue680"
+  },
+  {
+    "font_class": "redo",
+    "unicode": "\ue64a"
+  },
+  {
+    "font_class": "redo-filled",
+    "unicode": "\ue655"
+  },
+  {
+    "font_class": "refresh",
+    "unicode": "\ue657"
+  },
+  {
+    "font_class": "refresh-filled",
+    "unicode": "\ue656"
+  },
+  {
+    "font_class": "refreshempty",
+    "unicode": "\ue6bf"
+  },
+  {
+    "font_class": "reload",
+    "unicode": "\ue6b2"
+  },
+  {
+    "font_class": "right",
+    "unicode": "\ue6b5"
+  },
+  {
+    "font_class": "scan",
+    "unicode": "\ue62a"
+  },
+  {
+    "font_class": "search",
+    "unicode": "\ue654"
+  },
+  {
+    "font_class": "settings",
+    "unicode": "\ue653"
+  },
+  {
+    "font_class": "settings-filled",
+    "unicode": "\ue6ce"
+  },
+  {
+    "font_class": "shop",
+    "unicode": "\ue62f"
+  },
+  {
+    "font_class": "shop-filled",
+    "unicode": "\ue6cd"
+  },
+  {
+    "font_class": "smallcircle",
+    "unicode": "\ue67c"
+  },
+  {
+    "font_class": "smallcircle-filled",
+    "unicode": "\ue665"
+  },
+  {
+    "font_class": "sound",
+    "unicode": "\ue684"
+  },
+  {
+    "font_class": "sound-filled",
+    "unicode": "\ue686"
+  },
+  {
+    "font_class": "spinner-cycle",
+    "unicode": "\ue68a"
+  },
+  {
+    "font_class": "staff",
+    "unicode": "\ue6a7"
+  },
+  {
+    "font_class": "staff-filled",
+    "unicode": "\ue6cb"
+  },
+  {
+    "font_class": "star",
+    "unicode": "\ue688"
+  },
+  {
+    "font_class": "star-filled",
+    "unicode": "\ue68f"
+  },
+  {
+    "font_class": "starhalf",
+    "unicode": "\ue683"
+  },
+  {
+    "font_class": "trash",
+    "unicode": "\ue687"
+  },
+  {
+    "font_class": "trash-filled",
+    "unicode": "\ue685"
+  },
+  {
+    "font_class": "tune",
+    "unicode": "\ue6aa"
+  },
+  {
+    "font_class": "tune-filled",
+    "unicode": "\ue6ca"
+  },
+  {
+    "font_class": "undo",
+    "unicode": "\ue64f"
+  },
+  {
+    "font_class": "undo-filled",
+    "unicode": "\ue64c"
+  },
+  {
+    "font_class": "up",
+    "unicode": "\ue6b6"
+  },
+	{
+	  "font_class": "top",
+	  "unicode": "\ue6b6"
+	},
+  {
+    "font_class": "upload",
+    "unicode": "\ue690"
+  },
+  {
+    "font_class": "upload-filled",
+    "unicode": "\ue68e"
+  },
+  {
+    "font_class": "videocam",
+    "unicode": "\ue68c"
+  },
+  {
+    "font_class": "videocam-filled",
+    "unicode": "\ue689"
+  },
+  {
+    "font_class": "vip",
+    "unicode": "\ue6a8"
+  },
+  {
+    "font_class": "vip-filled",
+    "unicode": "\ue6c6"
+  },
+  {
+    "font_class": "wallet",
+    "unicode": "\ue6b1"
+  },
+  {
+    "font_class": "wallet-filled",
+    "unicode": "\ue6c2"
+  },
+  {
+    "font_class": "weibo",
+    "unicode": "\ue68b"
+  },
+  {
+    "font_class": "weixin",
+    "unicode": "\ue691"
+  }
+]
+
+// export const fontData = JSON.parse<IconsDataItem>(fontDataJson)
diff --git a/uni_modules/uni-icons/package.json b/uni_modules/uni-icons/package.json
new file mode 100644
index 0000000..6b681b4
--- /dev/null
+++ b/uni_modules/uni-icons/package.json
@@ -0,0 +1,89 @@
+{
+  "id": "uni-icons",
+  "displayName": "uni-icons 鍥炬爣",
+  "version": "2.0.10",
+  "description": "鍥炬爣缁勪欢锛岀敤浜庡睍绀虹Щ鍔ㄧ甯歌鐨勫浘鏍囷紝鍙嚜瀹氫箟棰滆壊銆佸ぇ灏忋�",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "icon",
+    "鍥炬爣"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": "^3.2.14"
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+"dcloudext": {
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "鏃�,
+      "data": "鏃�,
+      "permissions": "鏃�
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+    "type": "component-vue"
+  },
+  "uni_modules": {
+    "dependencies": ["uni-scss"],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y",
+        "alipay": "n"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "y",
+          "app-uvue": "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",
+					"椋炰功": "y",
+					"浜笢": "y"
+        },
+        "蹇簲鐢�: {
+          "鍗庝负": "y",
+          "鑱旂洘": "y"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
diff --git a/uni_modules/uni-icons/readme.md b/uni_modules/uni-icons/readme.md
new file mode 100644
index 0000000..86234ba
--- /dev/null
+++ b/uni_modules/uni-icons/readme.md
@@ -0,0 +1,8 @@
+## Icons 鍥炬爣
+> **缁勪欢鍚嶏細uni-icons**
+> 浠g爜鍧楋細 `uIcons`
+
+鐢ㄤ簬灞曠ず icons 鍥炬爣 銆�+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-icons)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�鎮ㄥuni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839 
diff --git a/uni_modules/uni-nav-bar/changelog.md b/uni_modules/uni-nav-bar/changelog.md
new file mode 100644
index 0000000..e3efe12
--- /dev/null
+++ b/uni_modules/uni-nav-bar/changelog.md
@@ -0,0 +1,57 @@
+## 1.3.14锛�024-10-15锛�+- 淇 寰俊灏忕▼搴忎腑鐨刧etSystemInfo璀﹀憡
+## 1.3.13锛�024-10-12锛�+- 淇 寰俊灏忕▼搴忎腑鐨刧etSystemInfo璀﹀憡
+## 1.3.12锛�024-10-12锛�+- 淇 寰俊灏忕▼搴忎腑鐨刧etSystemInfo璀﹀憡
+## 1.3.11锛�023-03-29锛�+- 淇 鑷畾涔夌姸鎬佹爮楂樺害闂姩BUG
+## 1.3.10锛�023-03-29锛�+- 淇 鏆楅粦妯″紡涓嬭竟绾块鑹查敊璇殑bug
+## 1.3.9锛�022-10-13锛�+- 淇 鏉′欢缂栬瘧閿欒鐨刡ug
+## 1.3.8锛�022-10-12锛�+- 淇 nvue 鐜 fixed 涓�true 鐨勬儏鍐典笅锛屾棤娉曠疆椤剁殑 bug
+## 1.3.7锛�022-08-11锛�+- 淇 nvue 鐜涓�fixed 涓�true 鐨勬儏鍐典笅锛屾棤娉曠疆椤剁殑 bug
+## 1.3.6锛�022-06-30锛�+- 淇 缁勪欢绀轰緥涓彃妲界敤娉曟棤娉曟樉绀哄唴瀹圭殑bug
+## 1.3.5锛�022-05-24锛�+- 鏂板 stat 灞炴� 锛屽彲寮�惎缁熻title 涓婃姤 锛屼粎浣跨敤浜唗itle 灞炴�涓旈」鐩紑鍚簡uni缁熻鐢熸晥
+## 1.3.4锛�022-01-24锛�+- 鏇存柊 缁勪欢绀轰緥
+## 1.3.3锛�022-01-24锛�+- 鏂板 left-width/right-width灞炴� 锛屽彲淇敼宸﹀彸涓や晶鐨勫搴�+## 1.3.2锛�022-01-18锛�+- 淇 鍦╲ue涓嬶紝鏍囬涓嶅瀭鐩村眳涓殑bug
+## 1.3.1锛�022-01-18锛�+- 淇 height 灞炴�绫诲瀷閿欒
+## 1.3.0锛�022-01-18锛�+- 鏂板 height 灞炴�,鍙慨鏀圭粍浠堕珮搴�+- 鏂板 dark 灞炴�鍙彲寮�惎鏆楅粦妯″紡
+- 浼樺寲 鏍囬瀛楁暟杩囧鏄剧ず鐪佺暐鍙�+- 浼樺寲 鎻掓Ы锛屾彃鍏ュ唴瀹瑰彲瀹屽叏瑕嗙洊
+## 1.2.1锛�022-01-10锛�+- 淇 color 灞炴�涓嶇敓鏁堢殑bug
+## 1.2.0锛�021-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锛�021-07-30锛�+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤簐ue3椤圭洰锛岃瑙�[uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+## 1.0.11锛�021-05-12锛�+- 鏂板 缁勪欢绀轰緥鍦板潃
+## 1.0.10锛�021-04-30锛�+- 淇 鍦╪vue涓媐ixed涓簍rue锛屽搴︿笉鑳芥拺婊$殑Bug
+## 1.0.9锛�021-04-21锛�+- 浼樺寲 娣诲姞渚濊禆 uni-icons, 瀵煎叆鍚庤嚜鍔ㄤ笅杞戒緷璧�+## 1.0.8锛�021-04-14锛�+- uni-ui 淇 uni-nav-bar 褰�fixed 灞炴�涓�true 鏃堕摵涓嶆弧灞忓箷鐨�bug
+
+## 1.0.7锛�021-02-25锛�+- 淇 easycom 涓嬶紝鎵句笉鍒�uni-status-bar 鐨刡ug
+
+## 1.0.6锛�021-02-05锛�+- 浼樺寲 缁勪欢寮曠敤鍏崇郴锛岄�杩噓ni_modules寮曠敤缁勪欢
+
+## 1.0.5锛�021-02-05锛�+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
diff --git a/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-nav-bar.vue b/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-nav-bar.vue
new file mode 100644
index 0000000..46806c1
--- /dev/null
+++ b/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-nav-bar.vue
@@ -0,0 +1,357 @@
+<template>
+	<view class="uni-navbar" :class="{'uni-dark':dark, 'uni-nvue-fixed': fixed}">
+		<view class="uni-navbar__content" :class="{ 'uni-navbar--fixed': fixed, 'uni-navbar--shadow': shadow, 'uni-navbar--border': border }"
+			:style="{ 'background-color': themeBgColor, 'border-bottom-color':themeColor }" >
+			<status-bar v-if="statusBar" />
+			<view :style="{ color: themeColor,backgroundColor: themeBgColor ,height:navbarHeight}"
+				class="uni-navbar__header">
+				<view @tap="onClickLeft" class="uni-navbar__header-btns uni-navbar__header-btns-left"
+					:style="{width:leftIconWidth}">
+					<slot name="left">
+						<view class="uni-navbar__content_view" v-if="leftIcon.length > 0">
+							<uni-icons :color="themeColor" :type="leftIcon" size="20" />
+						</view>
+						<view :class="{ 'uni-navbar-btn-icon-left': !leftIcon.length > 0 }" class="uni-navbar-btn-text"
+							v-if="leftText.length">
+							<text :style="{ color: themeColor, fontSize: '12px' }">{{ leftText }}</text>
+						</view>
+					</slot>
+				</view>
+				<view class="uni-navbar__header-container " @tap="onClickTitle">
+					<slot>
+						<view class="uni-navbar__header-container-inner" v-if="title.length>0">
+							<text class="uni-nav-bar-text uni-ellipsis-1"
+								:style="{color: themeColor }">{{ title }}</text>
+						</view>
+					</slot>
+				</view>
+				<view @click="onClickRight" class="uni-navbar__header-btns uni-navbar__header-btns-right"
+					:style="{width:rightIconWidth}">
+					<slot name="right">
+						<view v-if="rightIcon.length">
+							<uni-icons :color="themeColor" :type="rightIcon" size="22" />
+						</view>
+						<view class="uni-navbar-btn-text" v-if="rightText.length && !rightIcon.length">
+							<text class="uni-nav-bar-right-text" :style="{ color: themeColor}">{{ rightText }}</text>
+						</view>
+					</slot>
+				</view>
+			</view>
+		</view>
+		<!-- #ifndef APP-NVUE -->
+		<view class="uni-navbar__placeholder" v-if="fixed">
+			<status-bar v-if="statusBar" />
+			<view class="uni-navbar__placeholder-view" :style="{ height:navbarHeight}" />
+		</view>
+		<!-- #endif -->
+	</view>
+</template>
+
+<script>
+	import statusBar from "./uni-status-bar.vue";
+	const getVal = (val) => typeof val === 'number' ? val + 'px' : val;
+
+	/**
+	 * 
+	 * 
+	 * NavBar 鑷畾涔夊鑸爮
+	 * @description 瀵艰埅鏍忕粍浠讹紝涓昏鐢ㄤ簬澶撮儴瀵艰埅
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=52
+	 * @property {Boolean} dark 寮�惎榛戞殫妯″紡
+	 * @property {String} title 鏍囬鏂囧瓧
+	 * @property {String} leftText 宸︿晶鎸夐挳鏂囨湰
+	 * @property {String} rightText 鍙充晶鎸夐挳鏂囨湰
+	 * @property {String} leftIcon 宸︿晶鎸夐挳鍥炬爣锛堝浘鏍囩被鍨嬪弬鑰�[Icon 鍥炬爣](http://ext.dcloud.net.cn/plugin?id=28) type 灞炴�锛�+	 * @property {String} rightIcon 鍙充晶鎸夐挳鍥炬爣锛堝浘鏍囩被鍨嬪弬鑰�[Icon 鍥炬爣](http://ext.dcloud.net.cn/plugin?id=28) type 灞炴�锛�+	 * @property {String} color 鍥炬爣鍜屾枃瀛楅鑹�+	 * @property {String} backgroundColor 瀵艰埅鏍忚儗鏅鑹�+	 * @property {Boolean} fixed = [true|false] 鏄惁鍥哄畾椤堕儴
+	 * @property {Boolean} statusBar = [true|false] 鏄惁鍖呭惈鐘舵�鏍�+	 * @property {Boolean} shadow = [true|false] 瀵艰埅鏍忎笅鏄惁鏈夐槾褰�+	 * @property {Boolean} stat 鏄惁寮�惎缁熻鏍囬涓婃姤
+	 * @event {Function} clickLeft 宸︿晶鎸夐挳鐐瑰嚮鏃惰Е鍙�+	 * @event {Function} clickRight 鍙充晶鎸夐挳鐐瑰嚮鏃惰Е鍙�+	 * @event {Function} clickTitle 涓棿鏍囬鐐瑰嚮鏃惰Е鍙�+	 */
+	export default {
+		name: "UniNavBar",
+		components: {
+			statusBar
+		},
+		emits: ['clickLeft', 'clickRight', 'clickTitle'],
+		props: {
+			dark: {
+				type: Boolean,
+				default: false
+			},
+			title: {
+				type: String,
+				default: ""
+			},
+			leftText: {
+				type: String,
+				default: ""
+			},
+			rightText: {
+				type: String,
+				default: ""
+			},
+			leftIcon: {
+				type: String,
+				default: ""
+			},
+			rightIcon: {
+				type: String,
+				default: ""
+			},
+			fixed: {
+				type: [Boolean, String],
+				default: false
+			},
+			color: {
+				type: String,
+				default: ""
+			},
+			backgroundColor: {
+				type: String,
+				default: ""
+			},
+			statusBar: {
+				type: [Boolean, String],
+				default: false
+			},
+			shadow: {
+				type: [Boolean, String],
+				default: false
+			},
+			border: {
+				type: [Boolean, String],
+				default: true
+			},
+			height: {
+				type: [Number, String],
+				default: 44
+			},
+			leftWidth: {
+				type: [Number, String],
+				default: 60
+			},
+			rightWidth: {
+				type: [Number, String],
+				default: 60
+			},
+			stat: {
+				type: [Boolean, String],
+				default: ''
+			}
+		},
+		computed: {
+			themeBgColor() {
+				if (this.dark) {
+					// 榛樿鍊�+					if (this.backgroundColor) {
+						return this.backgroundColor
+					} else {
+						return this.dark ? '#333' : '#FFF'
+					}
+				}
+				return this.backgroundColor || '#FFF'
+			},
+			themeColor() {
+				if (this.dark) {
+					// 榛樿鍊�+					if (this.color) {
+						return this.color
+					} else {
+						return this.dark ? '#fff' : '#333'
+					}
+				}
+				return this.color || '#333'
+			},
+			navbarHeight() {
+				return getVal(this.height)
+			},
+			leftIconWidth() {
+				return getVal(this.leftWidth)
+			},
+			rightIconWidth() {
+				return getVal(this.rightWidth)
+			}
+		},
+		mounted() {
+			if (uni.report && this.stat && this.title !== '') {
+				uni.report('title', this.title)
+			}
+		},
+		methods: {
+			onClickLeft() {
+				this.$emit("clickLeft");
+			},
+			onClickRight() {
+				this.$emit("clickRight");
+			},
+			onClickTitle() {
+				this.$emit("clickTitle");
+			}
+		}
+	};
+</script>
+
+<style lang="scss" scoped>
+	$nav-height: 44px;
+
+	.uni-nvue-fixed {
+		/* #ifdef APP-NVUE */
+		position: sticky;
+		/* #endif */
+	}
+	.uni-navbar {
+		// box-sizing: border-box;
+	}
+
+	.uni-nav-bar-text {
+		/* #ifdef APP-PLUS */
+		font-size: 34rpx;
+		/* #endif */
+		/* #ifndef APP-PLUS */
+		font-size: 14px;
+		/* #endif */
+	}
+
+	.uni-nav-bar-right-text {
+		font-size: 12px;
+	}
+
+	.uni-navbar__content {
+		position: relative;
+		// background-color: #fff;
+		// box-sizing: border-box;
+		background-color: transparent;
+	}
+
+	.uni-navbar__content_view {
+		// box-sizing: border-box;
+	}
+
+	.uni-navbar-btn-text {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		justify-content: flex-start;
+		align-items: center;
+		line-height: 12px;
+	}
+
+	.uni-navbar__header {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		padding: 0 10px;
+		flex-direction: row;
+		height: $nav-height;
+		font-size: 12px;
+	}
+
+	.uni-navbar__header-btns {
+		/* #ifndef APP-NVUE */
+		overflow: hidden;
+		display: flex;
+		/* #endif */
+		flex-wrap: nowrap;
+		flex-direction: row;
+		width: 120rpx;
+		// padding: 0 6px;
+		justify-content: center;
+		align-items: center;
+		/* #ifdef H5 */
+		cursor: pointer;
+		/* #endif */
+	}
+
+	.uni-navbar__header-btns-left {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		width: 120rpx;
+		justify-content: flex-start;
+		align-items: center;
+	}
+
+	.uni-navbar__header-btns-right {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		// width: 150rpx;
+		// padding-right: 30rpx;
+		justify-content: flex-end;
+		align-items: center;
+	}
+
+	.uni-navbar__header-container {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex: 1;
+		padding: 0 10px;
+		overflow: hidden;
+	}
+
+	.uni-navbar__header-container-inner {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex: 1;
+		flex-direction: row;
+		align-items: center;
+		justify-content: center;
+		font-size: 12px;
+		overflow: hidden;
+		// box-sizing: border-box;
+	}
+
+
+	.uni-navbar__placeholder-view {
+		height: $nav-height;
+	}
+
+	.uni-navbar--fixed {
+		position: fixed;
+		z-index: 99;
+		/* #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/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-status-bar.vue b/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-status-bar.vue
new file mode 100644
index 0000000..6185446
--- /dev/null
+++ b/uni_modules/uni-nav-bar/components/uni-nav-bar/uni-status-bar.vue
@@ -0,0 +1,30 @@
+<template>
+	<view :style="{ height: statusBarHeight }" class="uni-status-bar">
+		<slot />
+	</view>
+</template>
+
+<script>
+	export default {
+		name: 'UniStatusBar',
+		data() {
+			return {
+				// #ifdef MP-WEIXIN
+				statusBarHeight: uni.getWindowInfo().statusBarHeight + 'px',
+				// #endif
+				// #ifndef MP-WEIXIN
+				statusBarHeight: uni.getSystemInfoSync().statusBarHeight + 'px',
+				// #endif
+
+			}
+		}
+	}
+</script>
+
+<style lang="scss" >
+	.uni-status-bar {
+		// width: 750rpx;
+		height: 20px;
+		// height: var(--status-bar-height);
+	}
+</style>
diff --git a/uni_modules/uni-nav-bar/package.json b/uni_modules/uni-nav-bar/package.json
new file mode 100644
index 0000000..d9f53b2
--- /dev/null
+++ b/uni_modules/uni-nav-bar/package.json
@@ -0,0 +1,87 @@
+{
+  "id": "uni-nav-bar",
+  "displayName": "uni-nav-bar 鑷畾涔夊鑸爮",
+  "version": "1.3.14",
+  "description": "鑷畾涔夊鑸爮缁勪欢锛屼富瑕佺敤浜庡ご閮ㄥ鑸�",
+  "keywords": [
+    "uni-ui",
+    "瀵艰埅",
+    "瀵艰埅鏍�,
+    "鑷畾涔夊鑸爮"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+"dcloudext": {
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "鏃�,
+      "data": "鏃�,
+      "permissions": "鏃�
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+    "type": "component-vue"
+  },
+  "uni_modules": {
+    "dependencies": [
+			"uni-scss",
+			"uni-icons"
+		],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y",
+        "alipay": "n"
+      },
+      "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/uni_modules/uni-nav-bar/readme.md b/uni_modules/uni-nav-bar/readme.md
new file mode 100644
index 0000000..3934b32
--- /dev/null
+++ b/uni_modules/uni-nav-bar/readme.md
@@ -0,0 +1,15 @@
+
+
+## NavBar 瀵艰埅鏍�+> **缁勪欢鍚嶏細uni-nav-bar**
+> 浠g爜鍧楋細 `uNavBar`
+
+瀵艰埅鏍忕粍浠讹紝涓昏鐢ㄤ簬澶撮儴瀵艰埅銆�+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-nav-bar)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�鎮ㄥuni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839 
+
+
+
+
+
diff --git a/uni_modules/uni-popup/changelog.md b/uni_modules/uni-popup/changelog.md
new file mode 100644
index 0000000..013272a
--- /dev/null
+++ b/uni_modules/uni-popup/changelog.md
@@ -0,0 +1,94 @@
+## 1.9.8锛�025-04-16锛�+- 淇 鏇存柊缁勪欢绀轰緥 锛岃В鍐虫洿鏂版暟鎹垨淇濆瓨椤圭洰瀵艰嚧寮圭獥娑堝け鐨勯棶棰�+## 1.9.7锛�025-04-14锛�+- 淇 uni-popup-dialog 寮瑰嚭妗嗗湪vue3涓弻鍚戠粦瀹氶棶棰�+## 1.9.6锛�025-01-08锛�+- 淇 绀轰緥涓繃鏈熷浘鐗囧湴鍧�+## 1.9.5锛�024-10-15锛�+- 淇 寰俊灏忕▼搴忎腑鐨刧etSystemInfo璀﹀憡
+## 1.9.2锛�024-09-21锛�+- 淇 uni-popup鍦╝ndroid涓婄殑閲嶅鐐瑰嚮寮瑰嚭浣嶇疆涓嶆纭殑bug
+## 1.9.1锛�024-04-02锛�+- 淇 uni-popup-dialog vue3涓嬩娇鐢╲alue鏃犳硶杩涜缁戝畾鐨刡ug(鍙屽悜缁戝畾鍏煎鏃у啓娉�
+## 1.9.0锛�024-03-28锛�+- 淇 uni-popup-dialog 鍙屽悜缁戝畾鏃跺垵濮嬪寲閫昏緫淇
+## 1.8.9锛�024-03-20锛�+- 淇 uni-popup-dialog 鏁版嵁杈撳叆鏃朵慨姝d负鍙屽悜缁戝畾
+## 1.8.8锛�024-02-20锛�+- 淇 uni-popup 鍦ㄥ井淇″皬绋嬪簭涓嬪嚭鐜版枃瀛楀悜涓婇棯鍔ㄧ殑bug
+## 1.8.7锛�024-02-02锛�+- 鏂板 uni-popup-dialog 鏂板灞炴�focus锛歩nput妯″紡涓嬶紝鏄惁鑷姩鑷姩鑱氱劍
+## 1.8.6锛�024-01-30锛�+- 鏂板 uni-popup-dialog 鏂板灞炴�maxLength:闄愬埗杈撳叆妗嗗瓧鏁�+## 1.8.5锛�024-01-26锛�+- 鏂板 uni-popup-dialog 鏂板灞炴�showClose:鎺у埗鍏抽棴鎸夐挳鐨勬樉绀�+## 1.8.4锛�023-11-15锛�+- 鏂板 uni-popup 鏀寔uni-app-x 娉ㄦ剰鏆傛椂浠呮敮鎸�`maskClick` `@open` `@close`
+## 1.8.3锛�023-04-17锛�+- 淇 uni-popup 閲嶅鎵撳紑鏃剁殑 bug
+## 1.8.2锛�023-02-02锛�+- uni-popup-dialog 缁勪欢鏂板 inputType 灞炴�
+## 1.8.1锛�022-12-01锛�+- 淇 nvue 涓�v-show 鎶ラ敊
+## 1.8.0锛�022-11-29锛�+- 浼樺寲 涓婚鏍峰紡
+## 1.7.9锛�022-04-02锛�+- 淇 寮瑰嚭灞傚唴閮ㄦ棤娉曟粴鍔ㄧ殑bug
+## 1.7.8锛�022-03-28锛�+- 淇 灏忕▼搴忎腑楂樺害閿欒鐨刡ug
+## 1.7.7锛�022-03-17锛�+- 淇 蹇�璋冪敤open鍑虹幇闂鐨凚ug
+## 1.7.6锛�022-02-14锛�+- 淇 safeArea 灞炴�涓嶈兘璁剧疆涓篺alse鐨刡ug
+## 1.7.5锛�022-01-19锛�+- 淇 isMaskClick 澶辨晥鐨刡ug
+## 1.7.4锛�022-01-19锛�+- 鏂板 cancelText \ confirmText 灞炴� 锛屽彲鑷畾涔夋枃鏈�+- 鏂板 maskBackgroundColor 灞炴� 锛屽彲浠ヤ慨鏀硅挋鐗堥鑹�+- 浼樺寲 maskClick灞炴� 鏇存柊涓�isMaskClick 锛岃В鍐冲井淇″皬绋嬪簭璀﹀憡鐨勯棶棰�+## 1.7.3锛�022-01-13锛�+- 淇 璁剧疆 safeArea 灞炴�涓嶇敓鏁堢殑bug
+## 1.7.2锛�021-11-26锛�+- 浼樺寲 缁勪欢绀轰緥
+## 1.7.1锛�021-11-26锛�+- 淇 vuedoc 鏂囧瓧閿欒
+## 1.7.0锛�021-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锛�021-08-24锛�+- 鏂板 鏀寔鍥介檯鍖�+## 1.6.1锛�021-07-30锛�+- 浼樺寲 vue3涓嬩簨浠惰鍛婄殑闂
+## 1.6.0锛�021-07-13锛�+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤簐ue3椤圭洰锛岃瑙�[uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+## 1.5.0锛�021-06-23锛�+- 鏂板 mask-click 閬僵灞傜偣鍑讳簨浠�+## 1.4.5锛�021-06-22锛�+- 淇 nvue 骞冲彴涓棿寮瑰嚭鍚庯紝鐐瑰嚮鍐呭锛屽啀鐐瑰嚮閬僵鏃犳硶鍏抽棴鐨凚ug
+## 1.4.4锛�021-06-18锛�+- 淇 H5骞冲彴涓棿寮瑰嚭鍚庯紝鐐瑰嚮鍐呭锛屽啀鐐瑰嚮閬僵鏃犳硶鍏抽棴鐨凚ug
+## 1.4.3锛�021-06-08锛�+- 淇 閿欒鐨�watch 瀛楁
+- 淇 safeArea 灞炴�涓嶇敓鏁堢殑闂
+- 淇 鐐瑰嚮鍐呭锛屽啀鐐瑰嚮閬僵鏃犳硶鍏抽棴鐨凚ug
+## 1.4.2锛�021-05-12锛�+- 鏂板 缁勪欢绀轰緥鍦板潃
+## 1.4.1锛�021-04-29锛�+- 淇 缁勪欢鍐呮斁缃�input 銆乼extarea 缁勪欢锛屾棤娉曡仛鐒︾殑闂
+## 1.4.0 锛�021-04-29锛�+- 鏂板 type 灞炴�鐨�left\right 鍊硷紝鏀寔宸﹀彸寮瑰嚭
+- 鏂板 open(String:type) 鏂规硶鍙傛暟 锛屽彲浠ョ渷鐣�type 灞炴� 锛岀洿鎺ヤ紶鍏ョ被鍨嬫墦寮�寚瀹氬脊绐�+- 鏂板 backgroundColor 灞炴�锛屽彲瀹氫箟涓荤獥鍙h儗鏅壊,榛樿涓嶆樉绀鸿儗鏅壊
+- 鏂板 safeArea 灞炴�锛屾槸鍚﹂�閰嶅簳閮ㄥ畨鍏ㄥ尯
+- 淇 App\h5\寰俊灏忕▼搴忓簳閮ㄥ畨鍏ㄥ尯鍗犱綅涓嶅鐨凚ug
+- 淇 App 绔脊鍑虹瓑寰呯殑Bug
+- 浼樺寲 鎻愬崌浣庨厤璁惧鎬ц兘锛屼紭鍖栧姩鐢诲崱椤块棶棰�+- 浼樺寲 鏇寸畝鍗曠殑缁勪欢鑷畾涔夋柟寮�+## 1.2.9锛�021-02-05锛�+- 浼樺寲 缁勪欢寮曠敤鍏崇郴锛岄�杩噓ni_modules寮曠敤缁勪欢
+## 1.2.8锛�021-02-05锛�+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
+## 1.2.7锛�021-02-05锛�+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
+- 鏂板 鏀寔 PC 绔�+- 鏂板 uni-popup-message 銆乽ni-popup-dialog鎵╁睍缁勪欢鏀寔 PC 绔�diff --git a/uni_modules/uni-popup/components/uni-popup-dialog/keypress.js b/uni_modules/uni-popup/components/uni-popup-dialog/keypress.js
new file mode 100644
index 0000000..6ef26a2
--- /dev/null
+++ b/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/uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue b/uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue
new file mode 100644
index 0000000..f5731d5
--- /dev/null
+++ b/uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue
@@ -0,0 +1,327 @@
+<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" :maxlength="maxlength" v-model="val" :type="inputType"
+					:placeholder="placeholderText" :focus="focus">
+			</slot>
+		</view>
+		<view class="uni-dialog-button-group">
+			<view class="uni-dialog-button" v-if="showClose" @click="closeDialog">
+				<text class="uni-dialog-button-text">{{closeText}}</text>
+			</view>
+			<view class="uni-dialog-button" :class="showClose?'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 {Boolean} focus input妯″紡涓嬫槸鍚﹁嚜鍔ㄨ仛鐒︼紝榛樿涓簍rue
+	 * @property {String} type = [success|warning|info|error] 涓婚鏍峰紡
+	 *  @value success 鎴愬姛
+	 * 	@value warning 鎻愮ず
+	 * 	@value info 娑堟伅
+	 * 	@value error 閿欒
+	 * @property {String} mode = [base|input] 妯″紡銆�+	 * 	@value base 鍩虹瀵硅瘽妗�+	 * 	@value input 鍙緭鍏ュ璇濇
+	 * @showClose {Boolean} 鏄惁鏄剧ず鍏抽棴鎸夐挳
+	 * @property {String} content 瀵硅瘽妗嗗唴瀹�+	 * @property {Boolean} beforeClose 鏄惁鎷︽埅鍙栨秷浜嬩欢
+	 * @property {Number} maxlength 杈撳叆
+	 * @event {Function} confirm 鐐瑰嚮纭鎸夐挳瑙﹀彂
+	 * @event {Function} close 鐐瑰嚮鍙栨秷鎸夐挳瑙﹀彂
+	 */
+
+	export default {
+		name: "uniPopupDialog",
+		mixins: [popup],
+		emits: ['confirm', 'close', 'update:modelValue', 'input'],
+		props: {
+			inputType: {
+				type: String,
+				default: 'text'
+			},
+			showClose: {
+				type: Boolean,
+				default: true
+			},
+			// #ifdef VUE2
+			value: {
+				type: [String, Number],
+				default: ''
+			},
+			// #endif
+			// #ifdef VUE3
+			modelValue: {
+				type: [Number, String],
+				default: ''
+			},
+			// #endif
+
+
+			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: ''
+			},
+			maxlength: {
+				type: Number,
+				default: -1,
+			},
+			focus: {
+				type: Boolean,
+				default: true,
+			}
+		},
+		data() {
+			return {
+				dialogType: 'error',
+				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) {
+				setVal(val)
+			},
+			// #ifdef VUE3
+			modelValue(val) {
+				setVal(val)
+			},
+			// #endif
+			val(val) {
+				// #ifdef VUE2
+				// TODO 鍏煎 vue2
+				this.$emit('input', val);
+				// #endif
+				// #ifdef VUE3
+				// TODO銆�吋瀹广�vue3
+				this.$emit('update:modelValue', val);
+				// #endif
+			}
+		},
+		created() {
+			// 瀵硅瘽妗嗛伄缃╀笉鍙偣鍑�+			this.popup.disableMask()
+			// this.popup.closeMask()
+			if (this.mode === 'input') {
+				this.dialogType = 'info'
+				this.val = this.value;
+				// #ifdef VUE3
+				this.val = this.modelValue;
+				// #endif
+			} else {
+				this.dialogType = this.type
+			}
+		},
+		methods: {
+			/**
+			 * 缁檝al灞炴�璧嬪�
+			 */
+			setVal(val) {
+				if (this.maxlength != -1 && this.mode === 'input') {
+					this.val = val.slice(0, this.maxlength);
+				} else {
+					this.val = val
+				}
+			},
+			/**
+			 * 鐐瑰嚮纭鎸夐挳
+			 */
+			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/uni_modules/uni-popup/components/uni-popup-message/uni-popup-message.vue b/uni_modules/uni-popup/components/uni-popup-message/uni-popup-message.vue
new file mode 100644
index 0000000..91370a8
--- /dev/null
+++ b/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/uni_modules/uni-popup/components/uni-popup-share/uni-popup-share.vue b/uni_modules/uni-popup/components/uni-popup-share/uni-popup-share.vue
new file mode 100644
index 0000000..c8945d5
--- /dev/null
+++ b/uni_modules/uni-popup/components/uni-popup-share/uni-popup-share.vue
@@ -0,0 +1,188 @@
+<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 {
+				// TODO 鏇挎崲涓鸿嚜宸辩殑鍥炬爣
+				bottomData: [{
+						text: '寰俊',
+						icon: 'https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/unicloudlogo.png',
+						name: 'wx'
+					},
+					{
+						text: '鏀粯瀹�,
+						icon: 'https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/unicloudlogo.png',
+						name: 'ali'
+					},
+					{
+						text: 'QQ',
+						icon: 'https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/unicloudlogo.png',
+						name: 'qq'
+					},
+					{
+						text: '鏂版氮',
+						icon: 'https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/unicloudlogo.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/uni_modules/uni-popup/components/uni-popup/i18n/en.json b/uni_modules/uni-popup/components/uni-popup/i18n/en.json
new file mode 100644
index 0000000..7f1bd06
--- /dev/null
+++ b/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/uni_modules/uni-popup/components/uni-popup/i18n/index.js b/uni_modules/uni-popup/components/uni-popup/i18n/index.js
new file mode 100644
index 0000000..de7509c
--- /dev/null
+++ b/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/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hans.json b/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hans.json
new file mode 100644
index 0000000..5e3003c
--- /dev/null
+++ b/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/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hant.json b/uni_modules/uni-popup/components/uni-popup/i18n/zh-Hant.json
new file mode 100644
index 0000000..13e39eb
--- /dev/null
+++ b/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/uni_modules/uni-popup/components/uni-popup/keypress.js b/uni_modules/uni-popup/components/uni-popup/keypress.js
new file mode 100644
index 0000000..62dda46
--- /dev/null
+++ b/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/uni_modules/uni-popup/components/uni-popup/popup.js b/uni_modules/uni-popup/components/uni-popup/popup.js
new file mode 100644
index 0000000..c4e5781
--- /dev/null
+++ b/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/uni_modules/uni-popup/components/uni-popup/uni-popup.uvue b/uni_modules/uni-popup/components/uni-popup/uni-popup.uvue
new file mode 100644
index 0000000..5eb8d5b
--- /dev/null
+++ b/uni_modules/uni-popup/components/uni-popup/uni-popup.uvue
@@ -0,0 +1,90 @@
+<template>
+  <view class="popup-root" v-if="isOpen" v-show="isShow" @click="clickMask">
+    <view @click.stop>
+      <slot></slot>
+    </view>
+  </view>
+</template>
+
+<script>
+  type CloseCallBack = ()=> void;
+  let closeCallBack:CloseCallBack = () :void => {};
+  export default {
+    emits:["close","clickMask"],
+    data() {
+      return {
+        isShow:false,
+        isOpen:false
+      }
+    },
+    props: {
+      maskClick: {
+        type: Boolean,
+        default: true
+      },
+    },
+    watch: {
+      // 璁剧疆show = true 鏃讹紝濡傛灉娌℃湁 open 闇�璁剧疆涓�open
+      isShow:{
+        handler(isShow) {
+          // console.log("isShow",isShow)
+          if(isShow && this.isOpen == false){
+            this.isOpen = true
+          }
+        },
+        immediate:true
+      },
+      // 璁剧疆isOpen = true 鏃讹紝濡傛灉娌℃湁 isShow 闇�璁剧疆涓�isShow
+      isOpen:{
+        handler(isOpen) {
+          // console.log("isOpen",isOpen)
+          if(isOpen && this.isShow == false){
+            this.isShow = true
+          }
+        },
+        immediate:true
+      }
+    },
+    methods:{
+      open(){
+        // ...funs : CloseCallBack[]
+        // if(funs.length > 0){
+        //   closeCallBack = funs[0]
+        // }
+        this.isOpen = true;
+      },
+      clickMask(){
+        if(this.maskClick == true){
+          this.$emit('clickMask')
+          this.close()
+        }
+      },
+      close(): void{
+        this.isOpen = false;
+        this.$emit('close')
+        closeCallBack()
+      },
+      hiden(){
+        this.isShow = false
+      },
+      show(){
+        this.isShow = true
+      }
+    }
+  }
+</script>
+
+<style>
+.popup-root {
+  position: fixed;
+  top: 0;
+  left: 0;
+  width: 750rpx;
+  height: 100%;
+  flex: 1;
+  background-color: rgba(0, 0, 0, 0.3);
+  justify-content: center;
+  align-items: center;
+  z-index: 99;
+}
+</style>
\ No newline at end of file
diff --git a/uni_modules/uni-popup/components/uni-popup/uni-popup.vue b/uni_modules/uni-popup/components/uni-popup/uni-popup.vue
new file mode 100644
index 0000000..5af55e0
--- /dev/null
+++ b/uni_modules/uni-popup/components/uni-popup/uni-popup.vue
@@ -0,0 +1,518 @@
+<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="getStyles" :class="[popupstyle]" @click="clear">
+					<slot />
+				</view>
+			</uni-transition>
+		</view>
+		<!-- #ifdef H5 -->
+		<keypress v-if="maskShow" @esc="onTap" />
+		<!-- #endif -->
+	</view>
+</template>
+
+<script>
+	// #ifdef H5
+	import keypress from './keypress.js'
+	// #endif
+
+	/**
+	 * PopUp 寮瑰嚭灞�+	 * @description 寮瑰嚭灞傜粍浠讹紝涓轰簡瑙e喅閬僵寮瑰眰鐨勯棶棰�+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=329
+	 * @property {String} type = [top|center|bottom|left|right|message|dialog|share] 寮瑰嚭鏂瑰紡
+	 * 	@value top 椤堕儴寮瑰嚭
+	 * 	@value center 涓棿寮瑰嚭
+	 * 	@value bottom 搴曢儴寮瑰嚭
+	 * 	@value left		宸︿晶寮瑰嚭
+	 * 	@value right  鍙充晶寮瑰嚭
+	 * 	@value message 娑堟伅鎻愮ず
+	 * 	@value dialog 瀵硅瘽妗�+	 * 	@value share 搴曢儴鍒嗕韩绀轰緥
+	 * @property {Boolean} animation = [true|false] 鏄惁寮�惎鍔ㄧ敾
+	 * @property {Boolean} maskClick = [true|false] 钂欑増鐐瑰嚮鏄惁鍏抽棴寮圭獥(搴熷純)
+	 * @property {Boolean} isMaskClick = [true|false] 钂欑増鐐瑰嚮鏄惁鍏抽棴寮圭獥
+	 * @property {String}  backgroundColor 涓荤獥鍙h儗鏅壊
+	 * @property {String}  maskBackgroundColor 钂欑増棰滆壊
+	 * @property {String}  borderRadius 璁剧疆鍦嗚(宸︿笂銆佸彸涓娿�鍙充笅鍜屽乏涓� 绀轰緥:"10px 10px 10px 10px"
+	 * @property {Boolean} safeArea		   鏄惁閫傞厤搴曢儴瀹夊叏鍖�+	 * @event {Function} change 鎵撳紑鍏抽棴寮圭獥瑙﹀彂锛宔={show: false}
+	 * @event {Function} maskClick 鐐瑰嚮閬僵瑙﹀彂
+	 */
+
+	export default {
+		name: 'uniPopup',
+		components: {
+			// #ifdef H5
+			keypress
+			// #endif
+		},
+		emits: ['change', 'maskClick'],
+		props: {
+			// 寮�惎鍔ㄧ敾
+			animation: {
+				type: Boolean,
+				default: true
+			},
+			// 寮瑰嚭灞傜被鍨嬶紝鍙�鍊硷紝top: 椤堕儴寮瑰嚭灞傦紱bottom锛氬簳閮ㄥ脊鍑哄眰锛沜enter锛氬叏灞忓脊鍑哄眰
+			// message: 娑堟伅鎻愮ず ; dialog : 瀵硅瘽妗�+			type: {
+				type: String,
+				default: 'center'
+			},
+			// maskClick
+			isMaskClick: {
+				type: Boolean,
+				default: null
+			},
+			// TODO 2 涓増鏈悗搴熷純灞炴� 锛屼娇鐢�isMaskClick
+			maskClick: {
+				type: Boolean,
+				default: null
+			},
+			backgroundColor: {
+				type: String,
+				default: 'none'
+			},
+			safeArea: {
+				type: Boolean,
+				default: true
+			},
+			maskBackgroundColor: {
+				type: String,
+				default: 'rgba(0, 0, 0, 0.4)'
+			},
+			borderRadius:{
+				type: String,
+			}
+		},
+
+		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: {
+					backgroundColor: 'transparent',
+					borderRadius: this.borderRadius || "0",
+					position: 'fixed',
+					left: 0,
+					right: 0
+				},
+				maskShow: true,
+				mkclick: true,
+				popupstyle: 'top'
+			}
+		},
+		computed: {
+			getStyles() {
+				let res = { backgroundColor: this.bg };
+				if (this.borderRadius || "0") {
+					res = Object.assign(res, { borderRadius: this.borderRadius })
+				}
+				return res;
+			},
+			isDesktop() {
+				return this.popupWidth >= 500 && this.popupHeight >= 500
+			},
+			bg() {
+				if (this.backgroundColor === '' || this.backgroundColor === 'none') {
+					return 'transparent'
+				}
+				return this.backgroundColor
+			}
+		},
+		mounted() {
+			const fixSize = () => {
+				// #ifdef MP-WEIXIN
+				const {
+					windowWidth,
+					windowHeight,
+					windowTop,
+					safeArea,
+					screenHeight,
+					safeAreaInsets
+				} = uni.getWindowInfo()
+				// #endif
+				// #ifndef MP-WEIXIN
+				const {
+					windowWidth,
+					windowHeight,
+					windowTop,
+					safeArea,
+					screenHeight,
+					safeAreaInsets
+				} = uni.getSystemInfoSync()
+				// #endif
+				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
+		activated() {
+   	  this.setH5Visible(!this.showPopup);
+    },
+    deactivated() {
+      this.setH5Visible(true);
+    },
+		created() {
+			// this.mkclick =  this.isMaskClick || this.maskClick
+			if (this.isMaskClick === null && this.maskClick === null) {
+				this.mkclick = true
+			} else {
+				this.mkclick = this.isMaskClick !== null ? this.isMaskClick : this.maskClick
+			}
+			if (this.animation) {
+				this.duration = 300
+			} else {
+				this.duration = 0
+			}
+			// TODO 澶勭悊 message 缁勪欢鐢熷懡鍛ㄦ湡寮傚父鐨勯棶棰�+			this.messageChild = null
+			// TODO 瑙e喅澶存潯鍐掓场鐨勯棶棰�+			this.clearPropagation = false
+			this.maskClass.backgroundColor = this.maskBackgroundColor
+		},
+		methods: {
+			setH5Visible(visible = true) {
+				// #ifdef H5
+				// fix by mehaotian 澶勭悊 h5 婊氬姩绌块�鐨勯棶棰�+				document.getElementsByTagName('body')[0].style.overflow =  visible ? "visible" : "hidden";
+				// #endif
+			},
+			/**
+			 * 鍏敤鏂规硶锛屼笉鏄剧ず閬僵灞�+			 */
+			closeMask() {
+				this.maskShow = false
+			},
+			/**
+			 * 鍏敤鏂规硶锛岄伄缃╁眰绂佹鐐瑰嚮
+			 */
+			disableMask() {
+				this.mkclick = false
+			},
+			// TODO nvue 鍙栨秷鍐掓场
+			clear(e) {
+				// #ifndef APP-NVUE
+				e.stopPropagation()
+				// #endif
+				this.clearPropagation = true
+			},
+
+			open(direction) {
+				// fix by mehaotian 澶勭悊蹇�鎵撳紑鍏抽棴鐨勬儏鍐�+				if (this.showPopup) {
+					return
+				}
+				let innerType = ['top', 'center', 'bottom', 'left', 'right', 'message', 'dialog', 'share']
+				if (!(direction && innerType.indexOf(direction) !== -1)) {
+					direction = this.type
+				}
+				if (!this.config[direction]) {
+					console.error('缂哄皯绫诲瀷锛�, direction)
+					return
+				}
+				this[this.config[direction]]()
+				this.$emit('change', {
+					show: true,
+					type: direction
+				})
+			},
+			close(type) {
+				this.showTrans = false
+				this.$emit('change', {
+					show: false,
+					type: this.type
+				})
+				clearTimeout(this.timer)
+				// // 鑷畾涔夊叧闂簨浠�+				// this.customOpen && this.customClose()
+				this.timer = setTimeout(() => {
+					this.showPopup = false
+				}, 300)
+			},
+			// TODO 澶勭悊鍐掓场浜嬩欢锛屽ご鏉$殑鍐掓场浜嬩欢鏈夐棶棰�锛屽厛杩欐牱鍏煎
+			touchstart() {
+				this.clearPropagation = false
+			},
+
+			onTap() {
+				if (this.clearPropagation) {
+					// fix by mehaotian 鍏煎 nvue
+					this.clearPropagation = false
+					return
+				}
+				this.$emit('maskClick')
+				if (!this.mkclick) return
+				this.close()
+			},
+			/**
+			 * 椤堕儴寮瑰嚭鏍峰紡澶勭悊
+			 */
+			top(type) {
+				this.popupstyle = this.isDesktop ? 'fixforpc-top' : 'top'
+				this.ani = ['slide-top']
+				this.transClass = {
+					position: 'fixed',
+					left: 0,
+					right: 0,
+					backgroundColor: this.bg,
+					borderRadius:this.borderRadius || "0"
+				}
+				// TODO 鍏煎 type 灞炴� 锛屽悗缁細搴熷純
+				if (type) return
+				this.showPopup = true
+				this.showTrans = true
+				this.$nextTick(() => {
+					this.showPoptrans()
+					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,
+					borderRadius:this.borderRadius || "0",
+				}
+				// TODO 鍏煎 type 灞炴� 锛屽悗缁細搴熷純
+				if (type) return
+				this.showPoptrans()
+			},
+			/**
+			 * 涓棿寮瑰嚭鏍峰紡澶勭悊
+			 */
+			center(type) {
+				this.popupstyle = 'center'
+				//寰俊灏忕▼搴忎笅锛岀粍鍚堝姩鐢讳細鍑虹幇鏂囧瓧鍚戜笂闂姩闂锛屽啀姝ゅ仛鐗规畩澶勭悊
+				// #ifdef MP-WEIXIN
+					this.ani = ['fade']
+				// #endif
+				// #ifndef MP-WEIXIN
+					this.ani = ['zoom-out', 'fade']
+				// #endif
+				this.transClass = {
+					position: 'fixed',
+					/* #ifndef APP-NVUE */
+					display: 'flex',
+					flexDirection: 'column',
+					/* #endif */
+					bottom: 0,
+					left: 0,
+					right: 0,
+					top: 0,
+					justifyContent: 'center',
+					alignItems: 'center',
+					borderRadius:this.borderRadius || "0"
+				}
+				// TODO 鍏煎 type 灞炴� 锛屽悗缁細搴熷純
+				if (type) return
+				this.showPoptrans()
+			},
+			left(type) {
+				this.popupstyle = 'left'
+				this.ani = ['slide-left']
+				this.transClass = {
+					position: 'fixed',
+					left: 0,
+					bottom: 0,
+					top: 0,
+					backgroundColor: this.bg,
+					borderRadius:this.borderRadius || "0",
+					/* #ifndef APP-NVUE */
+					display: 'flex',
+					flexDirection: 'column'
+					/* #endif */
+				}
+				// TODO 鍏煎 type 灞炴� 锛屽悗缁細搴熷純
+				if (type) return
+				this.showPoptrans()
+			},
+			right(type) {
+				this.popupstyle = 'right'
+				this.ani = ['slide-right']
+				this.transClass = {
+					position: 'fixed',
+					bottom: 0,
+					right: 0,
+					top: 0,
+					backgroundColor: this.bg,
+					borderRadius:this.borderRadius || "0",
+					/* #ifndef APP-NVUE */
+					display: 'flex',
+					flexDirection: 'column'
+					/* #endif */
+				}
+				// TODO 鍏煎 type 灞炴� 锛屽悗缁細搴熷純
+				if (type) return
+				this.showPoptrans()
+			},
+			showPoptrans(){
+				this.$nextTick(()=>{
+					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/uni_modules/uni-popup/package.json b/uni_modules/uni-popup/package.json
new file mode 100644
index 0000000..d8bfb9f
--- /dev/null
+++ b/uni_modules/uni-popup/package.json
@@ -0,0 +1,90 @@
+{
+	"id": "uni-popup",
+	"displayName": "uni-popup 寮瑰嚭灞�,
+	"version": "1.9.8",
+	"description": " Popup 缁勪欢锛屾彁渚涘父鐢ㄧ殑寮瑰眰",
+	"keywords": [
+        "uni-ui",
+        "寮瑰嚭灞�,
+        "寮圭獥",
+        "popup",
+        "寮规"
+    ],
+	"repository": "https://github.com/dcloudio/uni-ui",
+	"engines": {
+		"HBuilderX": ""
+	},
+	"directories": {
+		"example": "../../temps/example_temps"
+	},
+    "dcloudext": {
+        "sale": {
+			"regular": {
+				"price": "0.00"
+			},
+			"sourcecode": {
+				"price": "0.00"
+			}
+		},
+		"contact": {
+			"qq": ""
+		},
+		"declaration": {
+			"ads": "鏃�,
+			"data": "鏃�,
+			"permissions": "鏃�
+		},
+        "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+        "type": "component-vue"
+	},
+	"uni_modules": {
+		"dependencies": [
+			"uni-scss",
+			"uni-transition"
+		],
+		"encrypt": [],
+		"platforms": {
+			"cloud": {
+				"tcb": "y",
+                "aliyun": "y",
+                "alipay": "n"
+			},
+			"client": {
+				"App": {
+                    "app-vue": "y",
+                    "app-nvue": "y",
+                    "app-harmony": "u",
+                    "app-uvue": "u"
+                },
+				"H5-mobile": {
+					"Safari": "y",
+					"Android Browser": "y",
+					"寰俊娴忚鍣�Android)": "y",
+					"QQ娴忚鍣�Android)": "y"
+				},
+				"H5-pc": {
+					"Chrome": "y",
+					"IE": "y",
+					"Edge": "y",
+					"Firefox": "y",
+					"Safari": "y"
+				},
+				"灏忕▼搴�: {
+					"寰俊": "y",
+					"闃块噷": "y",
+					"鐧惧害": "y",
+					"瀛楄妭璺冲姩": "y",
+					"QQ": "y"
+				},
+				"蹇簲鐢�: {
+					"鍗庝负": "u",
+					"鑱旂洘": "u"
+                },
+                "Vue": {
+                    "vue2": "y",
+                    "vue3": "y"
+                }
+			}
+		}
+	}
+}
diff --git a/uni_modules/uni-popup/readme.md b/uni_modules/uni-popup/readme.md
new file mode 100644
index 0000000..fdad4b3
--- /dev/null
+++ b/uni_modules/uni-popup/readme.md
@@ -0,0 +1,17 @@
+
+
+## Popup 寮瑰嚭灞�+> **缁勪欢鍚嶏細uni-popup**
+> 浠g爜鍧楋細 `uPopup`
+> 鍏宠仈缁勪欢锛歚uni-transition`
+
+
+寮瑰嚭灞傜粍浠讹紝鍦ㄥ簲鐢ㄤ腑寮瑰嚭涓�釜娑堟伅鎻愮ず绐楀彛銆佹彁绀烘绛�+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-popup)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�鎮ㄥuni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839 
+
+
+
+
+
diff --git a/uni_modules/uni-scss/changelog.md b/uni_modules/uni-scss/changelog.md
new file mode 100644
index 0000000..b863bb0
--- /dev/null
+++ b/uni_modules/uni-scss/changelog.md
@@ -0,0 +1,8 @@
+## 1.0.3锛�022-01-21锛�+- 浼樺寲 缁勪欢绀轰緥
+## 1.0.2锛�021-11-22锛�+- 淇 / 绗﹀彿鍦�vue 涓嶅悓鐗堟湰鍏煎闂寮曡捣鐨勬姤閿欓棶棰�+## 1.0.1锛�021-11-22锛�+- 淇 vue3涓璼css璇硶鍏煎闂
+## 1.0.0锛�021-11-18锛�+- init
diff --git a/uni_modules/uni-scss/index.scss b/uni_modules/uni-scss/index.scss
new file mode 100644
index 0000000..1744a5f
--- /dev/null
+++ b/uni_modules/uni-scss/index.scss
@@ -0,0 +1 @@
+@import './styles/index.scss';
diff --git a/uni_modules/uni-scss/package.json b/uni_modules/uni-scss/package.json
new file mode 100644
index 0000000..7cc0ccb
--- /dev/null
+++ b/uni_modules/uni-scss/package.json
@@ -0,0 +1,82 @@
+{
+  "id": "uni-scss",
+  "displayName": "uni-scss 杈呭姪鏍峰紡",
+  "version": "1.0.3",
+  "description": "uni-sass鏄痷ni-ui鎻愪緵鐨勪竴濂楀叏灞�牱寮�锛岄�杩囦竴浜涚畝鍗曠殑绫诲悕鍜宻ass鍙橀噺锛屽疄鐜扮畝鍗曠殑椤甸潰甯冨眬鎿嶄綔锛屾瘮濡傞鑹层�杈硅窛銆佸渾瑙掔瓑銆�,
+  "keywords": [
+    "uni-scss",
+    "uni-ui",
+    "杈呭姪鏍峰紡"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": "^3.1.0"
+  },
+  "dcloudext": {
+    "category": [
+        "JS SDK",
+        "閫氱敤 SDK"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "鏃�,
+      "data": "鏃�,
+      "permissions": "鏃�
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+  },
+  "uni_modules": {
+    "dependencies": [],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "u"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "寰俊娴忚鍣�Android)": "y",
+          "QQ娴忚鍣�Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "灏忕▼搴�: {
+          "寰俊": "y",
+          "闃块噷": "y",
+          "鐧惧害": "y",
+          "瀛楄妭璺冲姩": "y",
+          "QQ": "y"
+        },
+        "蹇簲鐢�: {
+          "鍗庝负": "n",
+          "鑱旂洘": "n"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}
diff --git a/uni_modules/uni-scss/readme.md b/uni_modules/uni-scss/readme.md
new file mode 100644
index 0000000..b7d1c25
--- /dev/null
+++ b/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/uni_modules/uni-scss/styles/index.scss b/uni_modules/uni-scss/styles/index.scss
new file mode 100644
index 0000000..ffac4fe
--- /dev/null
+++ b/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/uni_modules/uni-scss/styles/setting/_border.scss b/uni_modules/uni-scss/styles/setting/_border.scss
new file mode 100644
index 0000000..12a11c3
--- /dev/null
+++ b/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/uni_modules/uni-scss/styles/setting/_color.scss b/uni_modules/uni-scss/styles/setting/_color.scss
new file mode 100644
index 0000000..1ededd9
--- /dev/null
+++ b/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/uni_modules/uni-scss/styles/setting/_radius.scss b/uni_modules/uni-scss/styles/setting/_radius.scss
new file mode 100644
index 0000000..9a0428b
--- /dev/null
+++ b/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/uni_modules/uni-scss/styles/setting/_space.scss b/uni_modules/uni-scss/styles/setting/_space.scss
new file mode 100644
index 0000000..3c89528
--- /dev/null
+++ b/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/uni_modules/uni-scss/styles/setting/_styles.scss b/uni_modules/uni-scss/styles/setting/_styles.scss
new file mode 100644
index 0000000..689afec
--- /dev/null
+++ b/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/uni_modules/uni-scss/styles/setting/_text.scss b/uni_modules/uni-scss/styles/setting/_text.scss
new file mode 100644
index 0000000..a34d08f
--- /dev/null
+++ b/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/uni_modules/uni-scss/styles/setting/_variables.scss b/uni_modules/uni-scss/styles/setting/_variables.scss
new file mode 100644
index 0000000..557d3d7
--- /dev/null
+++ b/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/uni_modules/uni-scss/styles/tools/functions.scss b/uni_modules/uni-scss/styles/tools/functions.scss
new file mode 100644
index 0000000..ac6f63e
--- /dev/null
+++ b/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/uni_modules/uni-scss/theme.scss b/uni_modules/uni-scss/theme.scss
new file mode 100644
index 0000000..80ee62f
--- /dev/null
+++ b/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/uni_modules/uni-scss/variables.scss b/uni_modules/uni-scss/variables.scss
new file mode 100644
index 0000000..1c062d4
--- /dev/null
+++ b/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/uni_modules/uni-swipe-action/changelog.md b/uni_modules/uni-swipe-action/changelog.md
new file mode 100644
index 0000000..2952e95
--- /dev/null
+++ b/uni_modules/uni-swipe-action/changelog.md
@@ -0,0 +1,54 @@
+## 1.3.13锛�025-04-15锛�+- 淇 app 绔�缂哄皯leftOptions 鎴�rightOptions 鏃舵棤娉曟粦鍔ㄧ殑闂
+## 1.3.12锛�025-04-14锛�+- 淇 鐢变笂涓�釜鍏煎鐗堟湰寮曞彂鐨�瀹夊崜杩愯鎶ラ敊涓旀棤娉曞洖寮圭殑闂
+## 1.3.11锛�025-04-08锛�+- 浼樺寲 鍏煎楦胯挋骞冲彴
+- 淇 WEB 骞冲彴鎺у埗鍙版姤閿�+## 1.3.10锛�024-01-17锛�+- 淇 鐐瑰嚮鎸夐挳鏃讹紝鎸夐挳浼氳鐐瑰嚮绌块�瀵艰嚧鑷姩鏀剁缉鐨�bug(鍏煎闃块噷/鐧惧害/鎶栭煶灏忕▼搴�
+## 1.3.9锛�024-01-17锛�+- 淇 鐐瑰嚮鎸夐挳鏃讹紝鎸夐挳浼氳鐐瑰嚮绌块�瀵艰嚧鑷姩鏀剁缉鐨�bug
+## 1.3.8锛�023-04-13锛�+- 淇`uni-swipe-action`鍜宍uni-swipe-action-item`涓嶅悓鏃朵娇鐢ㄥ鑷�closeOther 鏂规硶鎶ラ敊鐨�bug
+## 1.3.7锛�022-06-06锛�+- 淇 vue3 涓嬩娇鐢ㄧ粍浠朵笉鑳芥甯歌繍琛岀殑Bug
+## 1.3.6锛�022-05-31锛�+- 淇 h5绔偣鍑籧lick瑙﹀彂涓ゆ鐨凚ug
+## 1.3.5锛�022-05-23锛�+- 淇 isPC 鎵句笉鍒扮殑Bug
+## 1.3.4锛�022-05-19锛�+-  淇 鍦�nvue 涓�disabled 澶辨晥鐨刡ug
+## 1.3.3锛�022-03-31锛�+- 淇 鎸夐挳瀛椾綋澶у皬涓嶈兘璁剧疆鐨刡ug
+## 1.3.2锛�022-03-16锛�+- 淇 h5鍜宎pp绔笅鎶l閿欒鐨刡ug
+## 1.3.1锛�022-03-07锛�+- 淇 HBuilderX 1.4.X 鐗堟湰涓紝h5鍜宎pp绔笅鎶ラ敊鐨刡ug
+## 1.3.0锛�021-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锛�021-08-20锛�+- 浼樺寲 close-all 鏂规硶
+## 1.2.3锛�021-08-20锛�+- 鏂板 close-all 鏂规硶锛屽叧闂墍鏈夊凡鎵撳紑鐨勭粍浠�+## 1.2.2锛�021-08-17锛�+- 鏂板 resize() 鏂规硶锛屽湪闈炲井淇″皬绋嬪簭銆乭5銆乤pp-vue绔嚭鐜颁笉鑳芥粦鍔ㄧ殑闂鐨勬椂鍊欙紝閲嶇疆缁勪欢
+- 淇 app 绔伓灏斿嚭鐜扮被浼�Page[x][-x,xx;-x,xx,x,x-x] 鐨勯棶棰�
+- 浼樺寲 寰俊灏忕▼搴忋�h5銆乤pp-vue 婊戝姩閫昏緫锛岄伩鍏嶅嚭鐜板姩鎬佹柊澧炵粍浠跺悗涓嶈兘婊戝姩鐨勯棶棰�+## 1.2.1锛�021-07-30锛�+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤簐ue3椤圭洰锛岃瑙�[uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+- 淇 璺ㄩ〉闈慨鏀圭粍浠舵暟鎹�锛屽鑷翠笉鑳芥粦鍔ㄧ殑闂
+## 1.1.10锛�021-06-17锛�+- 淇 鎸夐挳鐐瑰嚮鎵ц涓ゆ鐨刡ug
+## 1.1.9锛�021-05-12锛�+- 鏂板 椤圭洰绀轰緥鍦板潃
+## 1.1.8锛�021-03-26锛�+- 淇 寰俊灏忕▼搴�nv_navigator is not defined 鎶ラ敊鐨刡ug
+## 1.1.7锛�021-02-05锛�+- 璋冩暣涓簎ni_modules鐩綍瑙勮寖
+- 鏂板 宸︿晶婊戝姩
+- 鏂板 鎻掓Ы浣跨敤鏂瑰紡
+- 鏂板 threshold 灞炴�锛屽彲浠ユ帶鍒舵粦鍔ㄧ己鐪佸�
+- 浼樺寲 闀垮垪琛ㄦ粴鍔ㄦ�鑳�+- 淇 婊氬姩椤甸潰鏃惰Е鍙戠粍浠舵粦鍔ㄧ殑Bug
diff --git a/uni_modules/uni-swipe-action/components/uni-swipe-action-item/bindingx.js b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/bindingx.js
new file mode 100644
index 0000000..707e432
--- /dev/null
+++ b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/bindingx.js
@@ -0,0 +1,302 @@
+let bindIngXMixins = {}
+
+// #ifdef APP-NVUE
+const BindingX = uni.requireNativePlugin('bindingx');
+const dom = uni.requireNativePlugin('dom');
+const animation = uni.requireNativePlugin('animation');
+
+bindIngXMixins = {
+	data() {
+		return {}
+	},
+
+	watch: {
+		show(newVal) {
+			if (this.autoClose) return
+			if (this.stop) return
+			this.stop = true
+			if (newVal) {
+				this.open(newVal)
+			} else {
+				this.close()
+			}
+		},
+		leftOptions() {
+			this.getSelectorQuery()
+			this.init()
+		},
+		rightOptions(newVal) {
+			this.init()
+		}
+	},
+	created() {
+		this.swipeaction = this.getSwipeAction()
+		if (this.swipeaction && Array.isArray(this.swipeaction.children)) {
+			this.swipeaction.children.push(this)
+		}
+	},
+	mounted() {
+		this.box = this.getEl(this.$refs['selector-box--hock'])
+		this.selector = this.getEl(this.$refs['selector-content--hock']);
+		this.leftButton = this.getEl(this.$refs['selector-left-button--hock']);
+		this.rightButton = this.getEl(this.$refs['selector-right-button--hock']);
+		this.init()
+	},
+	// beforeDestroy() {
+	// 	this.swipeaction.children.forEach((item, index) => {
+	// 		if (item === this) {
+	// 			this.swipeaction.children.splice(index, 1)
+	// 		}
+	// 	})
+	// },
+	methods: {
+		init() {
+			this.$nextTick(() => {
+				this.x = 0
+				this.button = {
+					show: false
+				}
+				setTimeout(() => {
+					this.getSelectorQuery()
+				}, 200)
+			})
+		},
+		onClick(index, item, position) {
+			this.$emit('click', {
+				content: item,
+				index,
+				position
+			})
+		},
+		touchstart(e) {
+			// fix by mehaotian 绂佹婊戝姩
+			if (this.disabled) return
+			// 姣忔鍙Е鍙戜竴娆★紝閬垮厤澶氭鐩戝惉閫犳垚闂儊
+			if (this.stop) return
+			this.stop = true
+			if (this.autoClose && this.swipeaction) {
+				this.swipeaction.closeOther(this)
+			}
+
+			const leftWidth = this.button.left.width
+			const rightWidth = this.button.right.width
+			let expression = this.range(this.x, -rightWidth, leftWidth)
+			let leftExpression = this.range(this.x - leftWidth, -leftWidth, 0)
+			let rightExpression = this.range(this.x + rightWidth, 0, rightWidth)
+
+			this.eventpan = BindingX.bind({
+				anchor: this.box,
+				eventType: 'pan',
+				props: [{
+					element: this.selector,
+					property: 'transform.translateX',
+					expression
+				}, {
+					element: this.leftButton,
+					property: 'transform.translateX',
+					expression: leftExpression
+				}, {
+					element: this.rightButton,
+					property: 'transform.translateX',
+					expression: rightExpression
+				}, ]
+			}, (e) => {
+				// nope
+				if (e.state === 'end') {
+					this.x = e.deltaX + this.x;
+					this.isclick = true
+					this.bindTiming(e.deltaX)
+				}
+			});
+		},
+		touchend(e) {
+			if (this.isopen !== 'none' && !this.isclick) {
+				this.open('none')
+			}
+		},
+		bindTiming(x) {
+			const left = this.x
+			const leftWidth = this.button.left.width
+			const rightWidth = this.button.right.width
+			const threshold = this.threshold
+			if (!this.isopen || this.isopen === 'none') {
+				if (left > threshold) {
+					this.open('left')
+				} else if (left < -threshold) {
+					this.open('right')
+				} else {
+					this.open('none')
+				}
+			} else {
+				if ((x > -leftWidth && x < 0) || x > rightWidth) {
+					if ((x > -threshold && x < 0) || (x - rightWidth > threshold)) {
+						this.open('left')
+					} else {
+						this.open('none')
+					}
+				} else {
+					if ((x < threshold && x > 0) || (x + leftWidth < -threshold)) {
+						this.open('right')
+					} else {
+						this.open('none')
+					}
+				}
+			}
+		},
+
+		/**
+		 * 绉诲姩鑼冨洿
+		 * @param {Object} num
+		 * @param {Object} mix
+		 * @param {Object} max
+		 */
+		range(num, mix, max) {
+			return `min(max(x+${num}, ${mix}), ${max})`
+		},
+
+		/**
+		 * 寮�惎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/uni_modules/uni-swipe-action/components/uni-swipe-action-item/isPC.js b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/isPC.js
new file mode 100644
index 0000000..917cb48
--- /dev/null
+++ b/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/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpalipay.js b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpalipay.js
new file mode 100644
index 0000000..35c796b
--- /dev/null
+++ b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpalipay.js
@@ -0,0 +1,195 @@
+export default {
+	data() {
+		return {
+			x: 0,
+			transition: false,
+			width: 0,
+			viewWidth: 0,
+			swipeShow: 0
+		}
+	},
+	watch: {
+		show(newVal) {
+			if (this.autoClose) return
+			if (newVal && newVal !== 'none') {
+				this.transition = true
+				this.open(newVal)
+			} else {
+				this.close()
+			}
+		}
+	},
+	created() {
+		this.swipeaction = this.getSwipeAction()
+		if (this.swipeaction && Array.isArray(this.swipeaction.children)) {
+			this.swipeaction.children.push(this)
+		}
+	},
+	mounted() {
+		this.isopen = false
+		setTimeout(() => {
+			this.getQuerySelect()
+		}, 50)
+	},
+	methods: {
+		appTouchStart(e) {
+			const {
+				clientX
+			} = e.changedTouches[0]
+			this.clientX = clientX
+			this.timestamp = new Date().getTime()
+		},
+		appTouchEnd(e, index, item, position) {
+			const {
+				clientX
+			} = e.changedTouches[0]
+			// fixed by xxxx 妯℃嫙鐐瑰嚮浜嬩欢锛岃В鍐�ios 13 鐐瑰嚮鍖哄煙閿欎綅鐨勯棶棰�+			let diff = Math.abs(this.clientX - clientX)
+			let time = (new Date().getTime()) - this.timestamp
+			if (diff < 40 && time < 300) {
+				this.$emit('click', {
+					content: item,
+					index,
+					position
+				})
+			}
+		},
+		/**
+		 * 绉诲姩瑙﹀彂
+		 * @param {Object} e
+		 */
+		onChange(e) {
+			this.moveX = e.detail.x
+			this.isclose = false
+		},
+		touchstart(e) {
+			this.transition = false
+			this.isclose = true
+			if (this.autoClose && this.swipeaction) {
+				this.swipeaction.closeOther(this)
+			}
+		},
+		touchmove(e) {},
+		touchend(e) {
+			// 0鐨勪綅缃粈涔堥兘涓嶆墽琛�+			if (this.isclose && this.isopen === 'none') return
+			if (this.isclose && this.isopen !== 'none') {
+				this.transition = true
+				this.close()
+			} else {
+				this.move(this.moveX + this.leftWidth)
+			}
+		},
+
+		/**
+		 * 绉诲姩
+		 * @param {Object} moveX
+		 */
+		move(moveX) {
+			// 鎵撳紑鍏抽棴鐨勫鐞嗛�杈戜笉澶竴鏍�+			this.transition = true
+			// 鏈墦寮�姸鎬�+			if (!this.isopen || this.isopen === 'none') {
+				if (moveX > this.threshold) {
+					this.open('left')
+				} else if (moveX < -this.threshold) {
+					this.open('right')
+				} else {
+					this.close()
+				}
+			} else {
+				if (moveX < 0 && moveX < this.rightWidth) {
+					const rightX = this.rightWidth + moveX
+					if (rightX < this.threshold) {
+						this.open('right')
+					} else {
+						this.close()
+					}
+				} else if (moveX > 0 && moveX < this.leftWidth) {
+					const leftX = this.leftWidth - moveX
+					if (leftX < this.threshold) {
+						this.open('left')
+					} else {
+						this.close()
+					}
+				}
+
+			}
+
+		},
+
+		/**
+		 * 鎵撳紑
+		 */
+		open(type) {
+			this.x = this.moveX
+			this.animation(type)
+		},
+
+		/**
+		 * 鍏抽棴
+		 */
+		close() {
+			this.x = this.moveX
+			// TODO 瑙e喅 x 鍊间笉鏇存柊鐨勯棶棰橈紝鎵�互浼氬瑙﹀彂涓� nextTick 锛屽緟浼樺寲
+			this.$nextTick(() => {
+				this.x = -this.leftWidth
+				if (this.isopen !== 'none') {
+					this.$emit('change', 'none')
+				}
+				this.isopen = 'none'
+			})
+		},
+
+		/**
+		 * 鎵ц缁撴潫鍔ㄧ敾
+		 * @param {Object} type
+		 */
+		animation(type) {
+			this.$nextTick(() => {
+				if (type === 'left') {
+					this.x = 0
+				} else {
+					this.x = -this.rightWidth - this.leftWidth
+				}
+
+				if (this.isopen !== type) {
+					this.$emit('change', type)
+				}
+				this.isopen = type
+			})
+
+		},
+		getSlide(x) {},
+		getQuerySelect() {
+			const query = uni.createSelectorQuery().in(this);
+			query.selectAll('.movable-view--hock').boundingClientRect(data => {
+				this.leftWidth = data[1].width
+				this.rightWidth = data[2].width
+				this.width = data[0].width
+				this.viewWidth = this.width + this.rightWidth + this.leftWidth
+				if (this.leftWidth === 0) {
+					// TODO 鐤戜技bug ,鍒濆鍖栫殑鏃跺�濡傛灉x 鏄�锛屼細瀵艰嚧绉诲姩浣嶇疆閿欒锛屾墍浠ヨ鍏冪礌瓒呭嚭涓�偣
+					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/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpother.js b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpother.js
new file mode 100644
index 0000000..d389bce
--- /dev/null
+++ b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpother.js
@@ -0,0 +1,260 @@
+let otherMixins = {}
+
+// #ifndef APP-PLUS|| MP-WEIXIN  ||  H5
+const MIN_DISTANCE = 10;
+otherMixins = {
+	data() {
+		// TODO 闅忔満鐢熺敓鍏冪礌ID锛岃В鍐崇櫨搴﹀皬绋嬪簭鑾峰彇鍚屼竴涓厓绱犱綅缃俊鎭殑bug
+		const elClass = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`
+		return {
+			uniShow: false,
+			left: 0,
+			buttonShow: 'none',
+			ani: false,
+			moveLeft: '',
+			elClass
+		}
+	},
+	watch: {
+		show(newVal) {
+			if (this.autoClose) return
+			this.openState(newVal)
+		},
+		left() {
+			this.moveLeft = `translateX(${this.left}px)`
+		},
+		buttonShow(newVal) {
+			if (this.autoClose) return
+			this.openState(newVal)
+		},
+		leftOptions() {
+			this.init()
+		},
+		rightOptions() {
+			this.init()
+		}
+	},
+	mounted() {
+		this.swipeaction = this.getSwipeAction()
+		if (this.swipeaction && Array.isArray(this.swipeaction.children)) {
+			this.swipeaction.children.push(this)
+		}
+		this.init()
+	},
+	methods: {
+		init() {
+			clearTimeout(this.timer)
+			this.timer = setTimeout(() => {
+				this.getSelectorQuery()
+			}, 100)
+			// 绉诲姩璺濈
+			this.left = 0
+			this.x = 0
+		},
+
+		closeSwipe(e) {
+			if (this.autoClose && this.swipeaction) {
+				this.swipeaction.closeOther(this)
+			}
+		},
+		appTouchStart(e) {
+			const {
+				clientX
+			} = e.changedTouches[0]
+			this.clientX = clientX
+			this.timestamp = new Date().getTime()
+		},
+		appTouchEnd(e, index, item, position) {
+			const {
+				clientX
+			} = e.changedTouches[0]
+			// fixed by xxxx 妯℃嫙鐐瑰嚮浜嬩欢锛岃В鍐�ios 13 鐐瑰嚮鍖哄煙閿欎綅鐨勯棶棰�+			let diff = Math.abs(this.clientX - clientX)
+			let time = (new Date().getTime()) - this.timestamp
+			if (diff < 40 && time < 300) {
+				this.$emit('click', {
+					content: item,
+					index,
+					position
+				})
+			}
+		},
+		touchstart(e) {
+			if (this.disabled) return
+			this.ani = false
+			this.x = this.left || 0
+			this.stopTouchStart(e)
+			this.autoClose && this.closeSwipe()
+		},
+		touchmove(e) {
+			if (this.disabled) return
+			// 鏄惁鍙互婊戝姩椤甸潰
+			this.stopTouchMove(e);
+			if (this.direction !== 'horizontal') {
+				return;
+			}
+			this.move(this.x + this.deltaX)
+			return false
+		},
+		touchend() {
+			if (this.disabled) return
+			this.moveDirection(this.left)
+		},
+		/**
+		 * 璁剧疆绉诲姩璺濈
+		 * @param {Object} value
+		 */
+		move(value) {
+			value = value || 0
+			const leftWidth = this.leftWidth
+			const rightWidth = this.rightWidth
+			// 鑾峰彇鍙粦鍔ㄨ寖鍥�+			this.left = this.range(value, -rightWidth, leftWidth);
+		},
+
+		/**
+		 * 鑾峰彇鑼冨洿
+		 * @param {Object} num
+		 * @param {Object} min
+		 * @param {Object} max
+		 */
+		range(num, min, max) {
+			return Math.min(Math.max(num, min), max);
+		},
+		/**
+		 * 绉诲姩鏂瑰悜鍒ゆ柇
+		 * @param {Object} left
+		 * @param {Object} value
+		 */
+		moveDirection(left) {
+			const threshold = this.threshold
+			const isopen = this.isopen || 'none'
+			const leftWidth = this.leftWidth
+			const rightWidth = this.rightWidth
+			if (this.deltaX === 0) {
+				this.openState('none')
+				return
+			}
+			if ((isopen === 'none' && rightWidth > 0 && -left > threshold) || (isopen !== 'none' && rightWidth >
+					0 && rightWidth +
+					left < threshold)) {
+				// right
+				this.openState('right')
+			} else if ((isopen === 'none' && leftWidth > 0 && left > threshold) || (isopen !== 'none' && leftWidth >
+					0 &&
+					leftWidth - left < threshold)) {
+				// left
+				this.openState('left')
+			} else {
+				// default
+				this.openState('none')
+			}
+		},
+
+		/**
+		 * 寮�惎鐘舵�
+		 * @param {Boolean} type
+		 */
+		openState(type) {
+			const leftWidth = this.leftWidth
+			const rightWidth = this.rightWidth
+			let left = ''
+			this.isopen = this.isopen ? this.isopen : 'none'
+			switch (type) {
+				case "left":
+					left = leftWidth
+					break
+				case "right":
+					left = -rightWidth
+					break
+				default:
+					left = 0
+			}
+
+
+			if (this.isopen !== type) {
+				this.throttle = true
+				this.$emit('change', type)
+			}
+
+			this.isopen = type
+			// 娣诲姞鍔ㄧ敾绫�+			this.ani = true
+			this.$nextTick(() => {
+				this.move(left)
+			})
+			// 璁剧疆鏈�粓绉诲姩浣嶇疆,鐞嗚涓婂彧瑕佽繘鍏ュ埌杩欎釜鍑芥暟锛岃偗瀹氭槸瑕佹墦寮�殑
+		},
+		close() {
+			this.openState('none')
+		},
+		getDirection(x, y) {
+			if (x > y && x > MIN_DISTANCE) {
+				return 'horizontal';
+			}
+			if (y > x && y > MIN_DISTANCE) {
+				return 'vertical';
+			}
+			return '';
+		},
+
+		/**
+		 * 閲嶇疆婊戝姩鐘舵�
+		 * @param {Object} event
+		 */
+		resetTouchStatus() {
+			this.direction = '';
+			this.deltaX = 0;
+			this.deltaY = 0;
+			this.offsetX = 0;
+			this.offsetY = 0;
+		},
+
+		/**
+		 * 璁剧疆婊戝姩寮�浣嶇疆
+		 * @param {Object} event
+		 */
+		stopTouchStart(event) {
+			this.resetTouchStatus();
+			const touch = event.touches[0];
+			this.startX = touch.clientX;
+			this.startY = touch.clientY;
+		},
+
+		/**
+		 * 婊戝姩涓紝鏄惁绂佹鎵撳紑
+		 * @param {Object} event
+		 */
+		stopTouchMove(event) {
+			const touch = event.touches[0];
+			this.deltaX = touch.clientX - this.startX;
+			this.deltaY = touch.clientY - this.startY;
+			this.offsetX = Math.abs(this.deltaX);
+			this.offsetY = Math.abs(this.deltaY);
+			this.direction = this.direction || this.getDirection(this.offsetX, this.offsetY);
+		},
+
+		getSelectorQuery() {
+			const views = uni.createSelectorQuery().in(this)
+			views
+				.selectAll('.' + this.elClass)
+				.boundingClientRect(data => {
+					if (data.length === 0) return
+					let show = 'none'
+					if (this.autoClose) {
+						show = 'none'
+					} else {
+						show = this.show
+					}
+					this.leftWidth = data[0].width || 0
+					this.rightWidth = data[1].width || 0
+					this.buttonShow = show
+				})
+				.exec()
+		}
+	}
+}
+
+// #endif
+
+export default otherMixins
diff --git a/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpwxs.js b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpwxs.js
new file mode 100644
index 0000000..0b5de88
--- /dev/null
+++ b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/mpwxs.js
@@ -0,0 +1,84 @@
+let mpMixins = {}
+let is_pc = null
+// #ifdef H5
+import {
+	isPC
+} from "./isPC"
+is_pc = isPC()
+// #endif
+// #ifdef APP-VUE || APP-HARMONY || MP-WEIXIN || H5
+
+mpMixins = {
+	data() {
+		return {
+			is_show: 'none'
+		}
+	},
+	watch: {
+		show(newVal) {
+			this.is_show = this.show
+		}
+	},
+	created() {
+		this.swipeaction = this.getSwipeAction()
+		if (this.swipeaction && Array.isArray(this.swipeaction.children)) {
+			this.swipeaction.children.push(this)
+		}
+	},
+	mounted() {
+		this.is_show = this.show
+	},
+	methods: {
+		// wxs 涓皟鐢�+		closeSwipe(e) {
+			if (this.autoClose && this.swipeaction) {
+				this.swipeaction.closeOther(this)
+			}
+		},
+
+		change(e) {
+			this.$emit('change', e.open)
+			if (this.is_show !== e.open) {
+				this.is_show = e.open
+			}
+		},
+
+		appTouchStart(e) {
+			if (is_pc) return
+			const {
+				clientX
+			} = e.changedTouches[0]
+			this.clientX = clientX
+			this.timestamp = new Date().getTime()
+		},
+		appTouchEnd(e, index, item, position) {
+			if (is_pc) return
+			const {
+				clientX
+			} = e.changedTouches[0]
+			// fixed by xxxx 妯℃嫙鐐瑰嚮浜嬩欢锛岃В鍐�ios 13 鐐瑰嚮鍖哄煙閿欎綅鐨勯棶棰�+			let diff = Math.abs(this.clientX - clientX)
+			let time = (new Date().getTime()) - this.timestamp
+			if (diff < 40 && time < 300) {
+				this.$emit('click', {
+					content: item,
+					index,
+					position
+				})
+			}
+		},
+		onClickForPC(index, item, position) {
+			if (!is_pc) return
+			// #ifdef H5
+			this.$emit('click', {
+				content: item,
+				index,
+				position
+			})
+			// #endif
+		}
+	}
+}
+
+// #endif
+export default mpMixins
diff --git a/uni_modules/uni-swipe-action/components/uni-swipe-action-item/render.js b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/render.js
new file mode 100644
index 0000000..218cb41
--- /dev/null
+++ b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/render.js
@@ -0,0 +1,277 @@
+const MIN_DISTANCE = 10;
+export default {
+	showWatch(newVal, oldVal, ownerInstance, instance, self) {
+		var state = self.state || {}
+		var $el = ownerInstance.$el || ownerInstance.$vm && ownerInstance.$vm.$el
+		if (!$el) return
+		this.getDom(instance, ownerInstance, self)
+		if (newVal && newVal !== 'none') {
+			this.openState(newVal, instance, ownerInstance, self)
+			return
+		}
+
+		if (state.left) {
+			this.openState('none', instance, ownerInstance, self)
+		}
+		this.resetTouchStatus(instance, self)
+	},
+
+	/**
+	 * 寮�瑙︽懜鎿嶄綔
+	 * @param {Object} e
+	 * @param {Object} ins
+	 */
+	touchstart(e, ownerInstance, self) {
+		let instance = e.instance;
+		let disabled = instance.getDataset().disabled
+		let state = self.state || {};
+		this.getDom(instance, ownerInstance, self)
+		// fix by mehaotian, TODO 鍏煎 app-vue 鑾峰彇dataset涓哄瓧绗︿覆 , h5 鑾峰彇 涓�undefined 鐨勯棶棰�寰呮鏋朵慨澶�+		disabled = this.getDisabledType(disabled)
+		if (disabled) return
+		// 寮�瑙︽懜鏃剁Щ闄ゅ姩鐢荤被
+		instance.requestAnimationFrame(function() {
+			instance.removeClass('ani');
+			ownerInstance.callMethod('closeSwipe');
+		})
+
+		// 璁板綍涓婃鐨勪綅缃�+		state.x = state.left || 0
+		// 璁$畻婊戝姩寮�浣嶇疆
+		this.stopTouchStart(e, ownerInstance, self)
+	},
+
+	/**
+	 * 寮�婊戝姩鎿嶄綔
+	 * @param {Object} e
+	 * @param {Object} ownerInstance
+	 */
+	touchmove(e, ownerInstance, self) {
+		let instance = e.instance;
+		// 鍒犻櫎涔嬪悗宸茬粡閭d笉鍒板疄渚嬩簡
+		if (!instance) return;
+		let disabled = instance.getDataset().disabled
+		let state = self.state || {}
+		// fix by mehaotian, TODO 鍏煎 app-vue 鑾峰彇dataset涓哄瓧绗︿覆 , h5 鑾峰彇 涓�undefined 鐨勯棶棰�寰呮鏋朵慨澶�+		disabled = this.getDisabledType(disabled)
+		if (disabled) return
+		// 鏄惁鍙互婊戝姩椤甸潰
+		this.stopTouchMove(e, self);
+		if (state.direction !== 'horizontal') {
+			return;
+		}
+		if (e.preventDefault) {
+			// 闃绘椤甸潰婊氬姩
+			e.preventDefault()
+		}
+		let x = state.x + state.deltaX
+		this.move(x, instance, ownerInstance, self)
+	},
+
+	/**
+	 * 缁撴潫瑙︽懜鎿嶄綔
+	 * @param {Object} e
+	 * @param {Object} ownerInstance
+	 */
+	touchend(e, ownerInstance, self) {
+		let instance = e.instance;
+		let disabled = instance.getDataset().disabled
+		let state = self.state || {}
+		// fix by mehaotian, TODO 鍏煎 app-vue 鑾峰彇dataset涓哄瓧绗︿覆 , h5 鑾峰彇 涓�undefined 鐨勯棶棰�寰呮鏋朵慨澶�+		disabled = this.getDisabledType(disabled)
+
+		if (disabled) return
+		// 婊戝姩杩囩▼涓Е鎽哥粨鏉�閫氳繃闃欏�鍒ゆ柇鏄紑鍚繕鏄叧闂�+		// fixed by mehaotian 瀹氭椂鍣ㄨВ鍐崇偣鍑绘寜閽紝touchend 瑙﹀彂姣�click 浜嬩欢鏃舵満鏃╃殑闂 锛屼富瑕佹槸 ios13
+		this.moveDirection(state.left, instance, ownerInstance, self)
+
+	},
+
+	/**
+	 * 璁剧疆绉诲姩璺濈
+	 * @param {Object} value
+	 * @param {Object} instance
+	 * @param {Object} ownerInstance
+	 */
+	move(value, instance, ownerInstance, self) {
+		value = value || 0
+		let state = self.state || {}
+		let leftWidth = state.leftWidth
+		let rightWidth = state.rightWidth
+		// 鑾峰彇鍙粦鍔ㄨ寖鍥�+		state.left = this.range(value, -rightWidth, leftWidth);
+		instance.requestAnimationFrame(function() {
+			instance.setStyle({
+				transform: 'translateX(' + state.left + 'px)',
+				'-webkit-transform': 'translateX(' + state.left + 'px)'
+			})
+		})
+
+	},
+
+	/**
+	 * 鑾峰彇鍏冪礌淇℃伅
+	 * @param {Object} instance
+	 * @param {Object} ownerInstance
+	 */
+	getDom(instance, ownerInstance, self) {
+		var state = self.state || {}
+		var $el = ownerInstance.$el || ownerInstance.$vm && ownerInstance.$vm.$el
+		var leftDom = $el.querySelector('.button-group--left')
+		var rightDom = $el.querySelector('.button-group--right')
+		if (leftDom && leftDom.offsetWidth) {
+			state.leftWidth = leftDom.offsetWidth || 0
+		} else {
+			state.leftWidth = 0
+		}
+		if (rightDom && rightDom.offsetWidth) {
+			state.rightWidth = rightDom.offsetWidth || 0
+		} else {
+			state.rightWidth = 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/uni_modules/uni-swipe-action/components/uni-swipe-action-item/uni-swipe-action-item.vue b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/uni-swipe-action-item.vue
new file mode 100644
index 0000000..6659d3a
--- /dev/null
+++ b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/uni-swipe-action-item.vue
@@ -0,0 +1,348 @@
+<template>
+	<!-- 鍦ㄥ井淇″皬绋嬪簭 app vue绔�h5 浣跨敤wxs 瀹炵幇-->
+	<!-- #ifdef APP-VUE || APP-HARMONY || MP-WEIXIN || H5 -->
+	<view class="uni-swipe">
+		<!--  #ifdef MP-WEIXIN || H5 -->
+		<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 || H5 -->
+			<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.stop="appTouchStart"
+							@touchend.stop="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.stop="appTouchStart"
+							@touchend.stop="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.stop="appTouchStart"
+							@touchend.stop="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.stop="appTouchStart" @touchend.stop="appTouchEnd($event,index,item,'right')"
+							class="uni-swipe_button button-hock"><text class="uni-swipe_button-text"
+								:style="{color: item.style && item.style.color ? item.style.color : '#FFFFFF',}">{{ item.text }}</text>
+						</view>
+					</slot>
+				</view>
+			</view>
+		</view>
+		<!-- #endif -->
+
+</template>
+<script src="./wx.wxs" module="wxsswipe" lang="wxs"></script>
+
+<script module="renderswipe" lang="renderjs">
+	import render from './render.js'
+	export default {
+		mounted(e, ins, owner) {
+			this.state = {}
+		},
+		methods: {
+			showWatch(newVal, oldVal, ownerInstance, instance) {
+				render.showWatch(newVal, oldVal, ownerInstance, instance, this)
+			},
+			touchstart(e, ownerInstance) {
+				render.touchstart(e, ownerInstance, this)
+			},
+			touchmove(e, ownerInstance) {
+				render.touchmove(e, ownerInstance, this)
+			},
+			touchend(e, ownerInstance) {
+				render.touchend(e, ownerInstance, this)
+			}
+		}
+	}
+</script>
+<script>
+	import mpwxs from './mpwxs'
+	import bindingx from './bindingx.js'
+	import mpother from './mpother'
+
+	/**
+	 * SwipeActionItem 婊戝姩鎿嶄綔瀛愮粍浠�+	 * @description 閫氳繃婊戝姩瑙﹀彂閫夐」鐨勫鍣�+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=181
+	 * @property {Boolean} show = [left|right锝渘one] 	寮�惎鍏抽棴缁勪欢锛宎uto-close = false 鏃剁敓鏁�+	 * @property {Boolean} disabled = [true|false] 		鏄惁绂佹婊戝姩
+	 * @property {Boolean} autoClose = [true|false] 	婊戝姩鎵撳紑褰撳墠缁勪欢锛屾槸鍚﹀叧闂叾浠栫粍浠�+	 * @property {Number}  threshold 					婊戝姩缂虹渷鍊�+	 * @property {Array} leftOptions 					宸︿晶閫夐」鍐呭鍙婃牱寮�+	 * @property {Array} rightOptions 					鍙充晶閫夐」鍐呭鍙婃牱寮�+	 * @event {Function} click 							鐐瑰嚮閫夐」鎸夐挳鏃惰Е鍙戜簨浠讹紝e = {content,index} 锛宑ontent锛堢偣鍑诲唴瀹癸級銆乮ndex锛堜笅鏍�
+	 * @event {Function} change 						缁勪欢鎵撳紑鎴栧叧闂椂瑙﹀彂锛宭eft\right\none
+	 */
+
+	export default {
+		mixins: [mpwxs, bindingx, mpother],
+		emits: ['click', 'change'],
+		props: {
+			// 鎺у埗寮�叧
+			show: {
+				type: String,
+				default: 'none'
+			},
+
+			// 绂佺敤
+			disabled: {
+				type: Boolean,
+				default: false
+			},
+
+			// 鏄惁鑷姩鍏抽棴
+			autoClose: {
+				type: Boolean,
+				default: true
+			},
+
+			// 婊戝姩缂虹渷璺濈
+			threshold: {
+				type: Number,
+				default: 20
+			},
+
+			// 宸︿晶鎸夐挳鍐呭
+			leftOptions: {
+				type: Array,
+				default () {
+					return []
+				}
+			},
+
+			// 鍙充晶鎸夐挳鍐呭
+			rightOptions: {
+				type: Array,
+				default () {
+					return []
+				}
+			}
+
+		},
+		// #ifndef VUE3
+		// TODO vue2
+		destroyed() {
+			if (this.__isUnmounted) return
+			this.uninstall()
+		},
+		// #endif
+		// #ifdef VUE3
+		// TODO vue3
+		unmounted() {
+			this.__isUnmounted = true
+			this.uninstall()
+		},
+		// #endif
+
+		methods: {
+			uninstall() {
+				if (this.swipeaction) {
+					this.swipeaction.children.forEach((item, index) => {
+						if (item === this) {
+							this.swipeaction.children.splice(index, 1)
+						}
+					})
+				}
+			},
+			/**
+			 * 鑾峰彇鐖跺厓绱犲疄渚�+			 */
+			getSwipeAction(name = 'uniSwipeAction') {
+				let parent = this.$parent;
+				let parentName = parent.$options.name;
+				while (parentName !== name) {
+					parent = parent.$parent;
+					if (!parent) return false;
+					parentName = parent.$options.name;
+				}
+				return parent;
+			}
+		}
+	}
+</script>
+<style lang="scss">
+	.uni-swipe {
+		position: relative;
+		/* #ifndef APP-NVUE */
+		overflow: hidden;
+		/* #endif */
+	}
+
+	.uni-swipe_box {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		flex-shrink: 0;
+		// touch-action: none;
+		/* #endif */
+		position: relative;
+	}
+
+	.uni-swipe_content {
+		// border: 1px red solid;
+	}
+
+	.uni-swipe_text--center {
+		width: 100%;
+		/* #ifndef APP-NVUE */
+		cursor: grab;
+		/* #endif */
+	}
+
+	.uni-swipe_button-group {
+		/* #ifndef APP-NVUE */
+		box-sizing: border-box;
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		position: absolute;
+		top: 0;
+		bottom: 0;
+		/* #ifdef H5 */
+		cursor: pointer;
+		/* #endif */
+	}
+
+	.button-group--left {
+		left: 0;
+		transform: translateX(-100%)
+	}
+
+	.button-group--right {
+		right: 0;
+		transform: translateX(100%)
+	}
+
+	.uni-swipe_button {
+		/* #ifdef APP-NVUE */
+		flex: 1;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: row;
+		justify-content: center;
+		align-items: center;
+		padding: 0 20px;
+	}
+
+	.uni-swipe_button-text {
+		/* #ifndef APP-NVUE */
+		flex-shrink: 0;
+		/* #endif */
+		font-size: 14px;
+	}
+
+	.ani {
+		transition-property: transform;
+		transition-duration: 0.3s;
+		transition-timing-function: cubic-bezier(0.165, 0.84, 0.44, 1);
+	}
+
+	/* #ifdef MP-ALIPAY */
+	.movable-area {
+		/* width: 100%; */
+		height: 45px;
+	}
+
+	.movable-view {
+		display: flex;
+		/* justify-content: center; */
+		position: relative;
+		flex: 1;
+		height: 45px;
+		z-index: 2;
+	}
+
+	.movable-view-button {
+		display: flex;
+		flex-shrink: 0;
+		flex-direction: row;
+		height: 100%;
+		background: #C0C0C0;
+	}
+
+	/* .transition {
+		transition: all 0.3s;
+	} */
+
+	.movable-view-box {
+		flex-shrink: 0;
+		height: 100%;
+		background-color: #fff;
+	}
+
+	/* #endif */
+</style>
diff --git a/uni_modules/uni-swipe-action/components/uni-swipe-action-item/wx.wxs b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/wx.wxs
new file mode 100644
index 0000000..a559903
--- /dev/null
+++ b/uni_modules/uni-swipe-action/components/uni-swipe-action-item/wx.wxs
@@ -0,0 +1,346 @@
+var MIN_DISTANCE = 10;
+
+/**
+ * 鍒ゆ柇褰撳墠鏄惁涓篐5銆乤pp-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
+	}
+
+	if (leftDom) {
+		leftStyles = leftDom.getBoundingClientRect()
+	}
+
+	if (rightDom) {
+		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/uni_modules/uni-swipe-action/components/uni-swipe-action/uni-swipe-action.vue b/uni_modules/uni-swipe-action/components/uni-swipe-action/uni-swipe-action.vue
new file mode 100644
index 0000000..4971782
--- /dev/null
+++ b/uni_modules/uni-swipe-action/components/uni-swipe-action/uni-swipe-action.vue
@@ -0,0 +1,60 @@
+<template>
+	<view>
+		<slot></slot>
+	</view>
+</template>
+
+<script>
+	/**
+	 * SwipeAction 婊戝姩鎿嶄綔
+	 * @description 閫氳繃婊戝姩瑙﹀彂閫夐」鐨勫鍣�+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=181
+	 */
+	export default {
+		name:"uniSwipeAction",
+		data() {
+			return {};
+		},
+		created() {
+			this.children = [];
+		},
+		methods: {
+			// 鍏紑缁欑敤鎴蜂娇鐢紝閲嶅埗缁勪欢鏍峰紡
+			resize(){
+				// wxs 浼氳嚜宸辫绠楃粍浠跺ぇ灏忥紝鎵�互鏃犻渶鎵ц涓嬮潰浠g爜
+				// #ifndef APP-VUE || H5 || MP-WEIXIN
+				this.children.forEach(vm=>{
+					vm.init()
+				})
+				// #endif
+			},
+			// 鍏紑缁欑敤鎴蜂娇鐢紝鍏抽棴鍏ㄩ儴 宸茬粡鎵撳紑鐨勭粍浠�+			closeAll(){
+				this.children.forEach(vm=>{
+					// #ifdef APP-VUE || H5 || MP-WEIXIN
+					vm.is_show = 'none'
+					// #endif
+
+					// #ifndef APP-VUE || H5 || MP-WEIXIN
+					vm.close()
+					// #endif
+				})
+			},
+			closeOther(vm) {
+				if (this.openItem && this.openItem !== vm) {
+					// #ifdef APP-VUE || H5 || MP-WEIXIN
+					this.openItem.is_show = 'none'
+					// #endif
+
+					// #ifndef APP-VUE || H5 || MP-WEIXIN
+					this.openItem.close()
+					// #endif
+				}
+				// 璁板綍涓婁竴涓墦寮�殑 swipe-action-item ,鐢ㄤ簬 auto-close
+				this.openItem = vm
+			}
+		}
+	};
+</script>
+
+<style></style>
diff --git a/uni_modules/uni-swipe-action/package.json b/uni_modules/uni-swipe-action/package.json
new file mode 100644
index 0000000..d36e11b
--- /dev/null
+++ b/uni_modules/uni-swipe-action/package.json
@@ -0,0 +1,87 @@
+{
+	"id": "uni-swipe-action",
+	"displayName": "uni-swipe-action 婊戝姩鎿嶄綔",
+	"version": "1.3.13",
+	"description": "SwipeAction 婊戝姩鎿嶄綔鎿嶄綔缁勪欢",
+	"keywords": [
+        "",
+        "uni-ui",
+        "uniui",
+        "婊戝姩鍒犻櫎",
+        "渚ф粦鍒犻櫎"
+    ],
+	"repository": "https://github.com/dcloudio/uni-ui",
+	"engines": {
+		"HBuilderX": ""
+	},
+	"directories": {
+		"example": "../../temps/example_temps"
+	},
+    "dcloudext": {
+        "sale": {
+			"regular": {
+				"price": "0.00"
+			},
+			"sourcecode": {
+				"price": "0.00"
+			}
+		},
+		"contact": {
+			"qq": ""
+		},
+		"declaration": {
+			"ads": "鏃�,
+			"data": "鏃�,
+			"permissions": "鏃�
+		},
+        "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+        "type": "component-vue"
+	},
+	"uni_modules": {
+		"dependencies": ["uni-scss"],
+		"encrypt": [],
+		"platforms": {
+			"cloud": {
+				"tcb": "y",
+                "aliyun": "y",
+                "alipay": "n"
+			},
+			"client": {
+				"App": {
+                    "app-vue": "y",
+                    "app-nvue": "y",
+                    "app-harmony": "u",
+                    "app-uvue": "u"
+                },
+				"H5-mobile": {
+					"Safari": "y",
+					"Android Browser": "y",
+					"寰俊娴忚鍣�Android)": "y",
+					"QQ娴忚鍣�Android)": "y"
+				},
+				"H5-pc": {
+					"Chrome": "u",
+					"IE": "u",
+					"Edge": "u",
+					"Firefox": "u",
+					"Safari": "u"
+				},
+				"灏忕▼搴�: {
+					"寰俊": "y",
+					"闃块噷": "y",
+					"鐧惧害": "y",
+					"瀛楄妭璺冲姩": "y",
+					"QQ": "y"
+				},
+				"蹇簲鐢�: {
+					"鍗庝负": "y",
+					"鑱旂洘": "u"
+				},
+				"Vue": {
+					"vue2": "y",
+					"vue3": "y"
+				}
+			}
+		}
+	}
+}
diff --git a/uni_modules/uni-swipe-action/readme.md b/uni_modules/uni-swipe-action/readme.md
new file mode 100644
index 0000000..93a5cac
--- /dev/null
+++ b/uni_modules/uni-swipe-action/readme.md
@@ -0,0 +1,11 @@
+
+
+## SwipeAction 婊戝姩鎿嶄綔
+> **缁勪欢鍚嶏細uni-swipe-action**
+> 浠g爜鍧楋細 `uSwipeAction`銆乣uSwipeActionItem`
+
+
+閫氳繃婊戝姩瑙﹀彂閫夐」鐨勫鍣�+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-swipe-action)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�鎮ㄥuni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839 
\ No newline at end of file
diff --git a/uni_modules/uni-transition/changelog.md b/uni_modules/uni-transition/changelog.md
new file mode 100644
index 0000000..2f2b10d
--- /dev/null
+++ b/uni_modules/uni-transition/changelog.md
@@ -0,0 +1,27 @@
+## 1.3.4锛�025-04-16锛�+- 淇 椤甸潰鏁版嵁鏇存柊鍒板簳鍔ㄧ敾澶嶅師鐨勯棶棰�+- 淇 绀轰緥椤甸潰鎵撳紑鎶ラ敊鐨勯棶棰�+## 1.3.3锛�024-04-23锛�+- 淇 褰撳厓绱犱細鍙楀彉閲忓奖鍝嶈嚜鍔ㄩ殣钘忕殑bug
+## 1.3.2锛�023-05-04锛�+- 淇 NVUE 骞冲彴鎶ラ敊鐨勯棶棰�+## 1.3.1锛�021-11-23锛�+- 淇 init 鏂规硶鍒濆鍖栭棶棰�+## 1.3.0锛�021-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锛�021-09-27锛�+- 淇 init 鏂规硶涓嶇敓鏁堢殑 Bug
+## 1.2.0锛�021-07-30锛�+- 缁勪欢鍏煎 vue3锛屽浣曞垱寤�vue3 椤圭洰锛岃瑙�[uni-app 椤圭洰鏀寔 vue3 浠嬬粛](https://ask.dcloud.net.cn/article/37834)
+## 1.1.1锛�021-05-12锛�+- 鏂板 绀轰緥鍦板潃
+- 淇 绀轰緥椤圭洰缂哄皯缁勪欢鐨�Bug
+## 1.1.0锛�021-04-22锛�+- 鏂板 閫氳繃鏂规硶鑷畾涔夊姩鐢�+- 鏂板 custom-class 闈�NVUE 骞冲彴鏀寔鑷畾涔�class 瀹氬埗鏍峰紡
+- 浼樺寲 鍔ㄧ敾瑙﹀彂閫昏緫锛屼娇鍔ㄧ敾鏇存祦鐣�+- 浼樺寲 鏀寔鍗曠嫭鐨勫姩鐢荤被鍨�+- 浼樺寲 鏂囨。绀轰緥
+## 1.0.2锛�021-02-05锛�+- 璋冩暣涓�uni_modules 鐩綍瑙勮寖
diff --git a/uni_modules/uni-transition/components/uni-transition/createAnimation.js b/uni_modules/uni-transition/components/uni-transition/createAnimation.js
new file mode 100644
index 0000000..8f89b18
--- /dev/null
+++ b/uni_modules/uni-transition/components/uni-transition/createAnimation.js
@@ -0,0 +1,131 @@
+// const defaultOption = {
+// 	duration: 300,
+// 	timingFunction: 'linear',
+// 	delay: 0,
+// 	transformOrigin: '50% 50% 0'
+// }
+// #ifdef APP-NVUE
+const nvueAnimation = uni.requireNativePlugin('animation')
+// #endif
+class MPAnimation {
+	constructor(options, _this) {
+		this.options = options
+		// 鍦╥OS10+QQ灏忕▼搴忓钩鍙颁笅锛屼紶缁欏師鐢熺殑瀵硅薄涓�畾鏄釜鏅�瀵硅薄鑰屼笉鏄疨roxy瀵硅薄锛屽惁鍒欎細鎶arameter should be Object instead of ProxyObject鐨勯敊璇�+		this.animation = uni.createAnimation({
+			...options
+		})
+		this.currentStepAnimates = {}
+		this.next = 0
+		this.$ = _this
+
+	}
+
+	_nvuePushAnimates(type, args) {
+		let aniObj = this.currentStepAnimates[this.next]
+		let styles = {}
+		if (!aniObj) {
+			styles = {
+				styles: {},
+				config: {}
+			}
+		} else {
+			styles = aniObj
+		}
+		if (animateTypes1.includes(type)) {
+			if (!styles.styles.transform) {
+				styles.styles.transform = ''
+			}
+			let unit = ''
+			if(type === 'rotate'){
+				unit = 'deg'
+			}
+			styles.styles.transform += `${type}(${args+unit}) `
+		} else {
+			styles.styles[type] = `${args}`
+		}
+		this.currentStepAnimates[this.next] = styles
+	}
+	_animateRun(styles = {}, config = {}) {
+		let ref = this.$.$refs['ani'].ref
+		if (!ref) return
+		return new Promise((resolve, reject) => {
+			nvueAnimation.transition(ref, {
+				styles,
+				...config
+			}, res => {
+				resolve()
+			})
+		})
+	}
+
+	_nvueNextAnimate(animates, step = 0, fn) {
+		let obj = animates[step]
+		if (obj) {
+			let {
+				styles,
+				config
+			} = obj
+			this._animateRun(styles, config).then(() => {
+				step += 1
+				this._nvueNextAnimate(animates, step, fn)
+			})
+		} else {
+			this.currentStepAnimates = {}
+			typeof fn === 'function' && fn()
+			this.isEnd = true
+		}
+	}
+
+	step(config = {}) {
+		// #ifndef APP-NVUE
+		this.animation.step(config)
+		// #endif
+		// #ifdef APP-NVUE
+		this.currentStepAnimates[this.next].config = Object.assign({}, this.options, config)
+		this.currentStepAnimates[this.next].styles.transformOrigin = this.currentStepAnimates[this.next].config.transformOrigin
+		this.next++
+		// #endif
+		return this
+	}
+
+	run(fn) {
+		// #ifndef APP-NVUE
+		this.$.animationData = this.animation.export()
+		this.$.timer = setTimeout(() => {
+			typeof fn === 'function' && fn()
+		}, this.$.durationTime)
+		// #endif
+		// #ifdef APP-NVUE
+		this.isEnd = false
+		let ref = this.$.$refs['ani'] && this.$.$refs['ani'].ref
+		if(!ref) return
+		this._nvueNextAnimate(this.currentStepAnimates, 0, fn)
+		this.next = 0
+		// #endif
+	}
+}
+
+
+const animateTypes1 = ['matrix', 'matrix3d', 'rotate', 'rotate3d', 'rotateX', 'rotateY', 'rotateZ', 'scale', 'scale3d',
+	'scaleX', 'scaleY', 'scaleZ', 'skew', 'skewX', 'skewY', 'translate', 'translate3d', 'translateX', 'translateY',
+	'translateZ'
+]
+const animateTypes2 = ['opacity', 'backgroundColor']
+const animateTypes3 = ['width', 'height', 'left', 'right', 'top', 'bottom']
+animateTypes1.concat(animateTypes2, animateTypes3).forEach(type => {
+	MPAnimation.prototype[type] = function(...args) {
+		// #ifndef APP-NVUE
+		this.animation[type](...args)
+		// #endif
+		// #ifdef APP-NVUE
+		this._nvuePushAnimates(type, args)
+		// #endif
+		return this
+	}
+})
+
+export function createAnimation(option, _this) {
+	if(!_this) return
+	clearTimeout(_this.timer)
+	return new MPAnimation(option, _this)
+}
diff --git a/uni_modules/uni-transition/components/uni-transition/uni-transition.vue b/uni_modules/uni-transition/components/uni-transition/uni-transition.vue
new file mode 100644
index 0000000..8772572
--- /dev/null
+++ b/uni_modules/uni-transition/components/uni-transition/uni-transition.vue
@@ -0,0 +1,289 @@
+<template>
+  <!-- #ifndef APP-NVUE -->
+  <view v-show="isShow" ref="ani" :animation="animationData" :class="customClass" :style="transformStyles" @click="onClick"><slot></slot></view>
+  <!-- #endif -->
+  <!-- #ifdef APP-NVUE -->
+  <view v-if="isShow" ref="ani" :animation="animationData" :class="customClass" :style="transformStyles" @click="onClick"><slot></slot></view>
+  <!-- #endif -->
+</template>
+
+<script>
+import { createAnimation } from './createAnimation'
+
+/**
+ * Transition 杩囨浮鍔ㄧ敾
+ * @description 绠�崟杩囨浮鍔ㄧ敾缁勪欢
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=985
+ * @property {Boolean} show = [false|true] 鎺у埗缁勪欢鏄剧ず鎴栭殣钘�+ * @property {Array|String} modeClass = [fade|slide-top|slide-right|slide-bottom|slide-left|zoom-in|zoom-out] 杩囨浮鍔ㄧ敾绫诲瀷
+ *  @value fade 娓愰殣娓愬嚭杩囨浮
+ *  @value slide-top 鐢变笂鑷充笅杩囨浮
+ *  @value slide-right 鐢卞彸鑷冲乏杩囨浮
+ *  @value slide-bottom 鐢变笅鑷充笂杩囨浮
+ *  @value slide-left 鐢卞乏鑷冲彸杩囨浮
+ *  @value zoom-in 鐢卞皬鍒板ぇ杩囨浮
+ *  @value zoom-out 鐢卞ぇ鍒板皬杩囨浮
+ * @property {Number} duration 杩囨浮鍔ㄧ敾鎸佺画鏃堕棿
+ * @property {Object} styles 缁勪欢鏍峰紡锛屽悓 css 鏍峰紡锛屾敞鎰忓甫鈥�鈥樿繛鎺ョ鐨勫睘鎬ч渶瑕佷娇鐢ㄥ皬椹煎嘲鍐欐硶濡傦細`backgroundColor:red`
+ */
+export default {
+	name: 'uniTransition',
+	emits:['click','change'],
+	props: {
+		show: {
+			type: Boolean,
+			default: false
+		},
+		modeClass: {
+			type: [Array, String],
+			default() {
+				return 'fade'
+			}
+		},
+		duration: {
+			type: Number,
+			default: 300
+		},
+		styles: {
+			type: Object,
+			default() {
+				return {}
+			}
+		},
+		customClass:{
+			type: String,
+			default: ''
+		},
+		onceRender:{
+			type:Boolean,
+			default:false
+		},
+	},
+	data() {
+		return {
+			isShow: false,
+			transform: '',
+			opacity: 1,
+			animationData: {},
+			durationTime: 300,
+			config: {}
+		}
+	},
+	watch: {
+		show: {
+			handler(newVal) {
+				if (newVal) {
+					this.open()
+				} else {
+					// 閬垮厤涓婃潵灏辨墽琛�close,瀵艰嚧鍔ㄧ敾閿欎贡
+					if (this.isShow) {
+						this.close()
+					}
+				}
+			},
+			immediate: true
+		}
+	},
+	computed: {
+		// 鐢熸垚鏍峰紡鏁版嵁
+		stylesObject() {
+			let styles = {
+				...this.styles,
+				'transition-duration': this.duration / 1000 + 's'
+			}
+			let transform = ''
+			for (let i in styles) {
+				let line = this.toLine(i)
+				transform += line + ':' + styles[i] + ';'
+			}
+			return transform
+		},
+		// 鍒濆鍖栧姩鐢绘潯浠�+		transformStyles() {
+			return 'transform:' + this.transform + ';' + 'opacity:' + this.opacity + ';' + this.stylesObject
+		}
+	},
+	created() {
+		// 鍔ㄧ敾榛樿閰嶇疆
+		this.config = {
+			duration: this.duration,
+			timingFunction: 'ease',
+			transformOrigin: '50% 50%',
+			delay: 0
+		}
+		this.durationTime = this.duration
+	},
+	methods: {
+		/**
+		 *  ref 瑙﹀彂 鍒濆鍖栧姩鐢�+		 */
+		init(obj = {}) {
+			if (obj.duration) {
+				this.durationTime = obj.duration
+			}
+			this.animation = createAnimation(Object.assign(this.config, obj),this)
+		},
+		/**
+		 * 鐐瑰嚮缁勪欢瑙﹀彂鍥炶皟
+		 */
+		onClick() {
+			this.$emit('click', {
+				detail: this.isShow
+			})
+		},
+		/**
+		 * ref 瑙﹀彂 鍔ㄧ敾鍒嗙粍
+		 * @param {Object} obj
+		 */
+		step(obj, config = {}) {
+			if (!this.animation) return
+			for (let i in obj) {
+				try {
+					if(typeof obj[i] === 'object'){
+						this.animation[i](...obj[i])
+					}else{
+						this.animation[i](obj[i])
+					}
+				} catch (e) {
+					console.error(`鏂规硶 ${i} 涓嶅瓨鍦╜)
+				}
+			}
+			this.animation.step(config)
+			return this
+		},
+		/**
+		 *  ref 瑙﹀彂 鎵ц鍔ㄧ敾
+		 */
+		run(fn) {
+			if (!this.animation) return
+			this.animation.run(fn)
+		},
+		// 寮�杩囧害鍔ㄧ敾
+		open() {
+			clearTimeout(this.timer)
+			this.transform = ''
+			this.isShow = true
+			let { opacity, transform } = this.styleInit(false)
+			if (typeof opacity !== 'undefined') {
+				this.opacity = opacity
+			}
+			this.transform = transform
+			// 纭繚鍔ㄦ�鏍峰紡宸茬粡鐢熸晥鍚庯紝鎵ц鍔ㄧ敾锛屽鏋滀笉鍔�nextTick 锛屼細瀵艰嚧 wx 鍔ㄧ敾鎵ц寮傚父
+			this.$nextTick(() => {
+				// TODO 瀹氭椂鍣ㄤ繚璇佸姩鐢诲畬鍏ㄦ墽琛岋紝鐩墠鏈変簺闂锛屽悗闈細鍙栨秷瀹氭椂鍣�+				this.timer = setTimeout(() => {
+					this.animation = createAnimation(this.config, this)
+					this.tranfromInit(false).step()
+					this.animation.run(() => {
+						this.transform = ''
+						this.opacity = opacity || 1
+					})
+					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 ? 0 : 1,
+				'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/uni_modules/uni-transition/package.json b/uni_modules/uni-transition/package.json
new file mode 100644
index 0000000..b76a3ab
--- /dev/null
+++ b/uni_modules/uni-transition/package.json
@@ -0,0 +1,87 @@
+{
+  "id": "uni-transition",
+  "displayName": "uni-transition 杩囨浮鍔ㄧ敾",
+  "version": "1.3.4",
+  "description": "鍏冪礌鐨勭畝鍗曡繃娓″姩鐢�,
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "鍔ㄧ敾",
+    "杩囨浮",
+    "杩囨浮鍔ㄧ敾"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+"dcloudext": {
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "鏃�,
+      "data": "鏃�,
+      "permissions": "鏃�
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+    "type": "component-vue"
+  },
+  "uni_modules": {
+    "dependencies": ["uni-scss"],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y",
+        "alipay": "n"
+      },
+      "client": {
+        "App": {
+            "app-vue": "y",
+            "app-nvue": "y",
+            "app-harmony": "u",
+            "app-uvue": "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/uni_modules/uni-transition/readme.md b/uni_modules/uni-transition/readme.md
new file mode 100644
index 0000000..2f8a77e
--- /dev/null
+++ b/uni_modules/uni-transition/readme.md
@@ -0,0 +1,11 @@
+
+
+## Transition 杩囨浮鍔ㄧ敾
+> **缁勪欢鍚嶏細uni-transition**
+> 浠g爜鍧楋細 `uTransition`
+
+
+鍏冪礌杩囨浮鍔ㄧ敾
+
+### [鏌ョ湅鏂囨。](https://uniapp.dcloud.io/component/uniui/uni-transition)
+#### 濡備娇鐢ㄨ繃绋嬩腑鏈変换浣曢棶棰橈紝鎴栬�鎮ㄥuni-ui鏈変竴浜涘ソ鐨勫缓璁紝娆㈣繋鍔犲叆 uni-ui 浜ゆ祦缇わ細871950839 
\ No newline at end of file
diff --git a/vite.config.js b/vite.config.js
new file mode 100644
index 0000000..ec64f10
--- /dev/null
+++ b/vite.config.js
@@ -0,0 +1,18 @@
+import { defineConfig } from 'vite'
+import uni from '@dcloudio/vite-plugin-uni'
+
+export default defineConfig({
+  plugins: [uni()],
+  css: {
+    preprocessorOptions: {
+      less: {
+        javascriptEnabled: true,  // 鍏抽敭閰嶇疆锛氬惎鐢�Less 涓殑 JavaScript
+        modifyVars: {
+          // 鍙�锛氳嚜瀹氫箟涓婚鍙橀噺
+          'primary-color': '#1677ff',
+          'border-radius-base': '4px'
+        }
+      }
+    }
+  }
+})
\ No newline at end of file

--
Gitblit v1.9.1