diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..269295a6105bf7c8a7197f19c64d66cb0d317372
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+unpackage/
+.hbuilderx
+node_modules
+.DS_Store
\ No newline at end of file
diff --git a/App.vue b/App.vue
new file mode 100644
index 0000000000000000000000000000000000000000..42a70c28aca7bf240fba373db156227623bc9486
--- /dev/null
+++ b/App.vue
@@ -0,0 +1,26 @@
+
+
+
diff --git a/changelog.md b/changelog.md
new file mode 100644
index 0000000000000000000000000000000000000000..b4657f5cb4471288fba30038348fabef493235f6
--- /dev/null
+++ b/changelog.md
@@ -0,0 +1,2 @@
+## 0.1.4(2021-03-01)
+- 调整为uni_modules目录规范
diff --git a/common/login.css b/common/login.css
new file mode 100644
index 0000000000000000000000000000000000000000..f8b355745fb4c9e4754a5e83eaeec48bf77198ec
--- /dev/null
+++ b/common/login.css
@@ -0,0 +1,504 @@
+
+ /* 头条小程序需要把 iconfont 样式放到组件外 */
+ @font-face {
+ font-family: uniicons;
+ font-weight: normal;
+ font-style: normal;
+ src: url('/static/uni.ttf') format('truetype');
+ }
+
+ .m-icon {
+ font-family: uniicons;
+ /* font-size: 24px; */
+ margin-left: 20px;
+ font-weight: normal;
+ font-style: normal;
+ line-height: 1;
+ display: inline-block;
+ text-decoration: none;
+ -webkit-font-smoothing: antialiased;
+ }
+
+ .m-icon.uni-active {
+ color: #007aff;
+ }
+
+ .m-icon-contact:before {
+ content: '\e100';
+ }
+
+ .m-icon-person:before {
+ content: '\e101';
+ }
+
+ .m-icon-personadd:before {
+ content: '\e102';
+ }
+
+ .m-icon-contact-filled:before {
+ content: '\e130';
+ }
+
+ .m-icon-person-filled:before {
+ content: '\e131';
+ }
+
+ .m-icon-personadd-filled:before {
+ content: '\e132';
+ }
+
+ .m-icon-phone:before {
+ content: '\e200';
+ }
+
+ .m-icon-email:before {
+ content: '\e201';
+ }
+
+ .m-icon-chatbubble:before {
+ content: '\e202';
+ }
+
+ .m-icon-chatboxes:before {
+ content: '\e203';
+ }
+
+ .m-icon-phone-filled:before {
+ content: '\e230';
+ }
+
+ .m-icon-email-filled:before {
+ content: '\e231';
+ }
+
+ .m-icon-chatbubble-filled:before {
+ content: '\e232';
+ }
+
+ .m-icon-chatboxes-filled:before {
+ content: '\e233';
+ }
+
+ .m-icon-weibo:before {
+ content: '\e260';
+ }
+
+ .m-icon-weixin:before {
+ content: '\e261';
+ }
+
+ .m-icon-pengyouquan:before {
+ content: '\e262';
+ }
+
+ .m-icon-chat:before {
+ content: '\e263';
+ }
+
+ .m-icon-qq:before {
+ content: '\e264';
+ }
+
+ .m-icon-videocam:before {
+ content: '\e300';
+ }
+
+ .m-icon-camera:before {
+ content: '\e301';
+ }
+
+ .m-icon-mic:before {
+ content: '\e302';
+ }
+
+ .m-icon-location:before {
+ content: '\e303';
+ }
+
+ .m-icon-mic-filled:before,
+ .m-icon-speech:before {
+ content: '\e332';
+ }
+
+ .m-icon-location-filled:before {
+ content: '\e333';
+ }
+
+ .m-icon-micoff:before {
+ content: '\e360';
+ }
+
+ .m-icon-image:before {
+ content: '\e363';
+ }
+
+ .m-icon-map:before {
+ content: '\e364';
+ }
+
+ .m-icon-compose:before {
+ content: '\e400';
+ }
+
+ .m-icon-trash:before {
+ content: '\e401';
+ }
+
+ .m-icon-upload:before {
+ content: '\e402';
+ }
+
+ .m-icon-download:before {
+ content: '\e403';
+ }
+
+ .m-icon-close:before {
+ content: '\e404';
+ }
+
+ .m-icon-redo:before {
+ content: '\e405';
+ }
+
+ .m-icon-undo:before {
+ content: '\e406';
+ }
+
+ .m-icon-refresh:before {
+ content: '\e407';
+ }
+
+ .m-icon-star:before {
+ content: '\e408';
+ }
+
+ .m-icon-plus:before {
+ content: '\e409';
+ }
+
+ .m-icon-minus:before {
+ content: '\e410';
+ }
+
+ .m-icon-circle:before,
+ .m-icon-checkbox:before {
+ content: '\e411';
+ }
+
+ .m-icon-close-filled:before,
+ .m-icon-clear:before {
+ content: '\e434';
+ }
+
+ .m-icon-refresh-filled:before {
+ content: '\e437';
+ }
+
+ .m-icon-star-filled:before {
+ content: '\e438';
+ }
+
+ .m-icon-plus-filled:before {
+ content: '\e439';
+ }
+
+ .m-icon-minus-filled:before {
+ content: '\e440';
+ }
+
+ .m-icon-circle-filled:before {
+ content: '\e441';
+ }
+
+ .m-icon-checkbox-filled:before {
+ content: '\e442';
+ }
+
+ .m-icon-closeempty:before {
+ content: '\e460';
+ }
+
+ .m-icon-refreshempty:before {
+ content: '\e461';
+ }
+
+ .m-icon-reload:before {
+ content: '\e462';
+ }
+
+ .m-icon-starhalf:before {
+ content: '\e463';
+ }
+
+ .m-icon-spinner:before {
+ content: '\e464';
+ }
+
+ .m-icon-spinner-cycle:before {
+ content: '\e465';
+ }
+
+ .m-icon-search:before {
+ content: '\e466';
+ }
+
+ .m-icon-plusempty:before {
+ content: '\e468';
+ }
+
+ .m-icon-forward:before {
+ content: '\e470';
+ }
+
+ .m-icon-back:before,
+ .m-icon-left-nav:before {
+ content: '\e471';
+ }
+
+ .m-icon-checkmarkempty:before {
+ content: '\e472';
+ }
+
+ .m-icon-home:before {
+ content: '\e500';
+ }
+
+ .m-icon-navigate:before {
+ content: '\e501';
+ }
+
+ .m-icon-gear:before {
+ content: '\e502';
+ }
+
+ .m-icon-paperplane:before {
+ content: '\e503';
+ }
+
+ .m-icon-info:before {
+ content: '\e504';
+ }
+
+ .m-icon-help:before {
+ content: '\e505';
+ }
+
+ .m-icon-locked:before {
+ content: '\e506';
+ }
+
+ .m-icon-more:before {
+ content: '\e507';
+ }
+
+ .m-icon-flag:before {
+ content: '\e508';
+ }
+
+ .m-icon-home-filled:before {
+ content: '\e530';
+ }
+
+ .m-icon-gear-filled:before {
+ content: '\e532';
+ }
+
+ .m-icon-info-filled:before {
+ content: '\e534';
+ }
+
+ .m-icon-help-filled:before {
+ content: '\e535';
+ }
+
+ .m-icon-more-filled:before {
+ content: '\e537';
+ }
+
+ .m-icon-settings:before {
+ content: '\e560';
+ }
+
+ .m-icon-list:before {
+ content: '\e562';
+ }
+
+ .m-icon-bars:before {
+ content: '\e563';
+ }
+
+ .m-icon-loop:before {
+ content: '\e565';
+ }
+
+ .m-icon-paperclip:before {
+ content: '\e567';
+ }
+
+ .m-icon-eye:before {
+ content: '\e568';
+ }
+
+ .m-icon-arrowup:before {
+ content: '\e580';
+ }
+
+ .m-icon-arrowdown:before {
+ content: '\e581';
+ }
+
+ .m-icon-arrowleft:before {
+ content: '\e582';
+ }
+
+ .m-icon-arrowright:before {
+ content: '\e583';
+ }
+
+ .m-icon-arrowthinup:before {
+ content: '\e584';
+ }
+
+ .m-icon-arrowthindown:before {
+ content: '\e585';
+ }
+
+ .m-icon-arrowthinleft:before {
+ content: '\e586';
+ }
+
+ .m-icon-arrowthinright:before {
+ content: '\e587';
+ }
+
+ .m-icon-pulldown:before {
+ content: '\e588';
+ }
+
+ .m-icon-scan:before {
+ content: "\e612";
+ }
+
+
+ /*每个页面公共css */
+ page {
+ min-height: 100%;
+ display: flex;
+ font-size: 14px;
+ }
+
+ input,
+ textarea,
+ button {
+ font-size: 14px;
+ }
+
+ /* #ifdef MP-BAIDU */
+ page {
+ width: 100%;
+ height: 100%;
+ display: block;
+ }
+
+ swan-template {
+ width: 100%;
+ min-height: 100%;
+ display: flex;
+ }
+
+ /* 原生组件模式下需要注意组件外部样式 */
+ custom-component {
+ width: 100%;
+ min-height: 100%;
+ display: flex;
+ }
+
+ /* #endif */
+
+ /* #ifdef MP-ALIPAY */
+ page {
+ min-height: 100vh;
+ }
+
+ /* #endif */
+
+ /* 原生组件模式下需要注意组件外部样式 */
+ m-input {
+ width: 100%;
+ /* min-height: 100%; */
+ display: flex;
+ flex: 1;
+ }
+
+ .content {
+ display: flex;
+ flex: 1;
+ flex-direction: column;
+ background-color: #efeff4;
+ padding: 10px;
+ }
+
+ .input-group {
+ background-color: #ffffff;
+ margin-top: 20px;
+ position: relative;
+ }
+
+ .input-group::before {
+ position: absolute;
+ right: 0;
+ top: 0;
+ left: 0;
+ height: 1px;
+ content: '';
+ -webkit-transform: scaleY(.5);
+ transform: scaleY(.5);
+ background-color: #c8c7cc;
+ }
+
+ .input-group::after {
+ position: absolute;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ height: 1px;
+ content: '';
+ -webkit-transform: scaleY(.5);
+ transform: scaleY(.5);
+ background-color: #c8c7cc;
+ }
+
+ .input-row {
+ display: flex;
+ flex-direction: row;
+ position: relative;
+ /* font-size: 18px; */
+ height: 40px;
+ line-height: 40px;
+ }
+
+ .input-row .title {
+ width: 70px;
+ padding-left: 15px;
+ }
+
+ .input-row.border::after {
+ position: absolute;
+ right: 0;
+ bottom: 0;
+ left: 8px;
+ height: 1px;
+ content: '';
+ -webkit-transform: scaleY(.5);
+ transform: scaleY(.5);
+ background-color: #c8c7cc;
+ }
+
+ .btn-row {
+ margin-top: 25px;
+ padding: 10px;
+ }
+
+ button.primary {
+ background-color: #0faeff;
+ }
\ No newline at end of file
diff --git a/common/uni-ui.scss b/common/uni-ui.scss
new file mode 100644
index 0000000000000000000000000000000000000000..6ba0990e19375953d8b035291a06be680dde6b51
--- /dev/null
+++ b/common/uni-ui.scss
@@ -0,0 +1,120 @@
+
+.uni-flex {
+ display: flex;
+}
+
+.uni-flex-row {
+ @extend .uni-flex;
+ flex-direction: row;
+ box-sizing: border-box;
+}
+
+.uni-flex-column {
+ @extend .uni-flex;
+ flex-direction: column;
+}
+
+.uni-color-gary {
+ color: #3b4144;
+}
+
+/* 标题 */
+.uni-title {
+ display: flex;
+ margin-bottom: $uni-spacing-col-base;
+ font-size: $uni-font-size-lg;
+ font-weight: bold;
+ color: #3b4144;
+}
+
+.uni-title-sub {
+ display: flex;
+ // margin-bottom: $uni-spacing-col-base;
+ font-size: $uni-font-size-base;
+ font-weight: 500;
+ color: #3b4144;
+}
+
+/* 描述 额外文本 */
+.uni-note {
+ margin-top: 10px;
+ color: #999;
+ font-size: $uni-font-size-sm;
+}
+
+/* 列表内容 */
+.uni-list-box {
+ @extend .uni-flex-row;
+ flex: 1;
+ margin-top: 10px;
+}
+
+/* 略缩图 */
+.uni-thumb {
+ flex-shrink: 0;
+ margin-right: $uni-spacing-row-base;
+ width: 125px;
+ height: 75px;
+ border-radius: $uni-border-radius-lg;
+ overflow: hidden;
+ border: 1px #f5f5f5 solid;
+ image {
+ width: 100%;
+ height: 100%;
+ }
+}
+
+.uni-media-box {
+ @extend .uni-flex-row;
+ // margin-bottom: $uni-spacing-col-base;
+ border-radius: $uni-border-radius-lg;
+ overflow: hidden;
+ .uni-thumb {
+ margin: 0;
+ margin-left: 4px;
+ flex-shrink: 1;
+ width: 33%;
+ border-radius:0;
+ &:first-child {
+ margin: 0;
+ }
+ }
+}
+
+/* 内容 */
+.uni-content {
+ @extend .uni-flex-column;
+ justify-content: space-between;
+}
+
+/* 列表footer */
+.uni-footer {
+ @extend .uni-flex-row;
+ justify-content: space-between;
+ margin-top: $uni-spacing-col-lg;
+}
+.uni-footer-text {
+ font-size: $uni-font-size-sm;
+ color: $uni-text-color-grey;
+ margin-left: 5px;
+}
+
+/* 标签 */
+
+.uni-tag {
+ flex-shrink: 0;
+ padding: 0 5px;
+ border: 1px $uni-border-color solid;
+ margin-right: $uni-spacing-row-sm;
+ border-radius: $uni-border-radius-base;
+ background: $uni-bg-color-grey;
+ color: $uni-text-color;
+ font-size: $uni-font-size-sm;
+}
+
+/* 链接 */
+.uni-link {
+ margin-left: 10px;
+ color: $uni-text-color;
+ text-decoration: underline;
+}
diff --git a/common/univerify.js b/common/univerify.js
new file mode 100644
index 0000000000000000000000000000000000000000..e92fab6b3597ea321471ff1a872e5753829c773b
--- /dev/null
+++ b/common/univerify.js
@@ -0,0 +1,142 @@
+import Vuex from '@/store/index.js'
+
+export function univerifyLogin() {
+ const commit = Vuex.commit;
+ const PROVIDER = 'univerify';
+
+ /**
+ * reject(true) 点击其他登录方式
+ * reject(false) 关闭登录框
+ */
+ return new Promise((resolve, reject) => {
+ uni.getProvider({
+ service: 'oauth',
+ success: (res) => {
+ if (res.provider.indexOf(PROVIDER) !== -1) {
+ // 一键登录已在APP onLaunch的时候进行了预登陆,可以显著提高登录速度。登录成功后,预登陆状态会重置
+ uni.login({
+ provider: PROVIDER,
+ success: (res) => {
+ uni.closeAuthView();
+ uni.showLoading();
+
+ uniCloud.callFunction({
+ name: 'user-center',
+ data: {
+ action: 'loginByUniverify',
+ params: res.authResult
+ },
+ success: (e) => {
+ console.log('login success', e);
+
+ if (e.result.code == 0) {
+ const username = e.result.username || e.result.mobile || '一键登录新用户'
+
+ uni.setStorageSync('uni_id_token', e.result.token)
+ uni.setStorageSync('username', username)
+ uni.setStorageSync('login_type', 'online')
+
+ commit('login', username)
+ resolve();
+
+ uni.switchTab({
+ url: '../main/main',
+ });
+ } else {
+ uni.showModal({
+ title: `登录失败: ${e.result.code}`,
+ content: e.result.message,
+ showCancel: false
+ })
+ console.log('登录失败', e);
+
+ e.result.errMsg = e.result.message;
+ }
+ },
+ fail: (e) => {
+ uni.showModal({
+ title: `登录失败`,
+ content: e.errMsg,
+ showCancel: false
+ })
+ },
+ complete: () => {
+ uni.hideLoading()
+ }
+ })
+ },
+ fail: (err) => {
+ console.error('授权登录失败:' + JSON.stringify(err));
+
+ // 一键登录点击其他登录方式
+ if (err.code == 30002) {
+ uni.closeAuthView();
+ reject(true);
+ return;
+ }
+
+ // 关闭登录
+ if (err.code == 30003) {
+ uni.closeAuthView();
+ reject(false);
+ return;
+ }
+
+ reject(err);
+ }
+ })
+ } else {
+ reject();
+ }
+ },
+ fail: (err) => {
+ console.error('获取服务供应商失败:' + err.errMsg);
+ reject(err)
+ }
+ });
+ })
+}
+
+export function univerifyErrorHandler(err, cb) {
+ if (!err) {
+ cb && cb()
+ return
+ };
+
+ const state = Vuex.state;
+ const obj = {
+ /* showCancel: true,
+ cancelText: '其他登录方式',
+ success(res) {
+ if (res.cancel) {
+ cb && cb()
+ }
+ } */
+ }
+
+ switch (true) {
+ // 未开通
+ case err.code == 1000:
+ uni.showModal(Object.assign({
+ title: `登录失败`,
+ content: `${err.errMsg},错误码:${err.code}\n开通指南:https://ask.dcloud.net.cn/article/37965`,
+ }, obj));
+ break;
+ // 预登陆失败
+ case err.code == 30005:
+ uni.showModal(Object.assign({
+ showCancel: false,
+ title: `预登录失败`,
+ content: `${err.errMsg},错误码:${err.code}`
+ }, obj));
+ break;
+ //用户关闭验证界面
+ case err.code != 30003:
+ uni.showModal(Object.assign({
+ showCancel: false,
+ title: `登录失败`,
+ content: `${err.errMsg},错误码:${err.code}`,
+ }, obj));
+ break;
+ }
+}
diff --git a/common/uqrcode.js b/common/uqrcode.js
new file mode 100644
index 0000000000000000000000000000000000000000..22a947d75b422025fc3320bed3bdda3f72bd9437
--- /dev/null
+++ b/common/uqrcode.js
@@ -0,0 +1,1382 @@
+//---------------------------------------------------------------------
+// github https://github.com/Sansnn/uQRCode
+//---------------------------------------------------------------------
+
+let uQRCode = {};
+
+(function() {
+ //---------------------------------------------------------------------
+ // QRCode for JavaScript
+ //
+ // Copyright (c) 2009 Kazuhiko Arase
+ //
+ // URL: http://www.d-project.com/
+ //
+ // Licensed under the MIT license:
+ // http://www.opensource.org/licenses/mit-license.php
+ //
+ // The word "QR Code" is registered trademark of
+ // DENSO WAVE INCORPORATED
+ // http://www.denso-wave.com/qrcode/faqpatent-e.html
+ //
+ //---------------------------------------------------------------------
+
+ //---------------------------------------------------------------------
+ // QR8bitByte
+ //---------------------------------------------------------------------
+
+ function QR8bitByte(data) {
+ this.mode = QRMode.MODE_8BIT_BYTE;
+ this.data = data;
+ }
+
+ QR8bitByte.prototype = {
+
+ getLength: function(buffer) {
+ return this.data.length;
+ },
+
+ write: function(buffer) {
+ for (var i = 0; i < this.data.length; i++) {
+ // not JIS ...
+ buffer.put(this.data.charCodeAt(i), 8);
+ }
+ }
+ };
+
+ //---------------------------------------------------------------------
+ // QRCode
+ //---------------------------------------------------------------------
+
+ function QRCode(typeNumber, errorCorrectLevel) {
+ this.typeNumber = typeNumber;
+ this.errorCorrectLevel = errorCorrectLevel;
+ this.modules = null;
+ this.moduleCount = 0;
+ this.dataCache = null;
+ this.dataList = new Array();
+ }
+
+ QRCode.prototype = {
+
+ addData: function(data) {
+ var newData = new QR8bitByte(data);
+ this.dataList.push(newData);
+ this.dataCache = null;
+ },
+
+ isDark: function(row, col) {
+ if (row < 0 || this.moduleCount <= row || col < 0 || this.moduleCount <= col) {
+ throw new Error(row + "," + col);
+ }
+ return this.modules[row][col];
+ },
+
+ getModuleCount: function() {
+ return this.moduleCount;
+ },
+
+ make: function() {
+ // Calculate automatically typeNumber if provided is < 1
+ if (this.typeNumber < 1) {
+ var typeNumber = 1;
+ for (typeNumber = 1; typeNumber < 40; typeNumber++) {
+ var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, this.errorCorrectLevel);
+
+ var buffer = new QRBitBuffer();
+ var totalDataCount = 0;
+ for (var i = 0; i < rsBlocks.length; i++) {
+ totalDataCount += rsBlocks[i].dataCount;
+ }
+
+ for (var i = 0; i < this.dataList.length; i++) {
+ var data = this.dataList[i];
+ buffer.put(data.mode, 4);
+ buffer.put(data.getLength(), QRUtil.getLengthInBits(data.mode, typeNumber));
+ data.write(buffer);
+ }
+ if (buffer.getLengthInBits() <= totalDataCount * 8)
+ break;
+ }
+ this.typeNumber = typeNumber;
+ }
+ this.makeImpl(false, this.getBestMaskPattern());
+ },
+
+ makeImpl: function(test, maskPattern) {
+
+ this.moduleCount = this.typeNumber * 4 + 17;
+ this.modules = new Array(this.moduleCount);
+
+ for (var row = 0; row < this.moduleCount; row++) {
+
+ this.modules[row] = new Array(this.moduleCount);
+
+ for (var col = 0; col < this.moduleCount; col++) {
+ this.modules[row][col] = null; //(col + row) % 3;
+ }
+ }
+
+ this.setupPositionProbePattern(0, 0);
+ this.setupPositionProbePattern(this.moduleCount - 7, 0);
+ this.setupPositionProbePattern(0, this.moduleCount - 7);
+ this.setupPositionAdjustPattern();
+ this.setupTimingPattern();
+ this.setupTypeInfo(test, maskPattern);
+
+ if (this.typeNumber >= 7) {
+ this.setupTypeNumber(test);
+ }
+
+ if (this.dataCache == null) {
+ this.dataCache = QRCode.createData(this.typeNumber, this.errorCorrectLevel, this.dataList);
+ }
+
+ this.mapData(this.dataCache, maskPattern);
+ },
+
+ setupPositionProbePattern: function(row, col) {
+
+ for (var r = -1; r <= 7; r++) {
+
+ if (row + r <= -1 || this.moduleCount <= row + r) continue;
+
+ for (var c = -1; c <= 7; c++) {
+
+ if (col + c <= -1 || this.moduleCount <= col + c) continue;
+
+ if ((0 <= r && r <= 6 && (c == 0 || c == 6)) ||
+ (0 <= c && c <= 6 && (r == 0 || r == 6)) ||
+ (2 <= r && r <= 4 && 2 <= c && c <= 4)) {
+ this.modules[row + r][col + c] = true;
+ } else {
+ this.modules[row + r][col + c] = false;
+ }
+ }
+ }
+ },
+
+ getBestMaskPattern: function() {
+
+ var minLostPoint = 0;
+ var pattern = 0;
+
+ for (var i = 0; i < 8; i++) {
+
+ this.makeImpl(true, i);
+
+ var lostPoint = QRUtil.getLostPoint(this);
+
+ if (i == 0 || minLostPoint > lostPoint) {
+ minLostPoint = lostPoint;
+ pattern = i;
+ }
+ }
+
+ return pattern;
+ },
+
+ createMovieClip: function(target_mc, instance_name, depth) {
+
+ var qr_mc = target_mc.createEmptyMovieClip(instance_name, depth);
+ var cs = 1;
+
+ this.make();
+
+ for (var row = 0; row < this.modules.length; row++) {
+
+ var y = row * cs;
+
+ for (var col = 0; col < this.modules[row].length; col++) {
+
+ var x = col * cs;
+ var dark = this.modules[row][col];
+
+ if (dark) {
+ qr_mc.beginFill(0, 100);
+ qr_mc.moveTo(x, y);
+ qr_mc.lineTo(x + cs, y);
+ qr_mc.lineTo(x + cs, y + cs);
+ qr_mc.lineTo(x, y + cs);
+ qr_mc.endFill();
+ }
+ }
+ }
+
+ return qr_mc;
+ },
+
+ setupTimingPattern: function() {
+
+ for (var r = 8; r < this.moduleCount - 8; r++) {
+ if (this.modules[r][6] != null) {
+ continue;
+ }
+ this.modules[r][6] = (r % 2 == 0);
+ }
+
+ for (var c = 8; c < this.moduleCount - 8; c++) {
+ if (this.modules[6][c] != null) {
+ continue;
+ }
+ this.modules[6][c] = (c % 2 == 0);
+ }
+ },
+
+ setupPositionAdjustPattern: function() {
+
+ var pos = QRUtil.getPatternPosition(this.typeNumber);
+
+ for (var i = 0; i < pos.length; i++) {
+
+ for (var j = 0; j < pos.length; j++) {
+
+ var row = pos[i];
+ var col = pos[j];
+
+ if (this.modules[row][col] != null) {
+ continue;
+ }
+
+ for (var r = -2; r <= 2; r++) {
+
+ for (var c = -2; c <= 2; c++) {
+
+ if (r == -2 || r == 2 || c == -2 || c == 2 ||
+ (r == 0 && c == 0)) {
+ this.modules[row + r][col + c] = true;
+ } else {
+ this.modules[row + r][col + c] = false;
+ }
+ }
+ }
+ }
+ }
+ },
+
+ setupTypeNumber: function(test) {
+
+ var bits = QRUtil.getBCHTypeNumber(this.typeNumber);
+
+ for (var i = 0; i < 18; i++) {
+ var mod = (!test && ((bits >> i) & 1) == 1);
+ this.modules[Math.floor(i / 3)][i % 3 + this.moduleCount - 8 - 3] = mod;
+ }
+
+ for (var i = 0; i < 18; i++) {
+ var mod = (!test && ((bits >> i) & 1) == 1);
+ this.modules[i % 3 + this.moduleCount - 8 - 3][Math.floor(i / 3)] = mod;
+ }
+ },
+
+ setupTypeInfo: function(test, maskPattern) {
+
+ var data = (this.errorCorrectLevel << 3) | maskPattern;
+ var bits = QRUtil.getBCHTypeInfo(data);
+
+ // vertical
+ for (var i = 0; i < 15; i++) {
+
+ var mod = (!test && ((bits >> i) & 1) == 1);
+
+ if (i < 6) {
+ this.modules[i][8] = mod;
+ } else if (i < 8) {
+ this.modules[i + 1][8] = mod;
+ } else {
+ this.modules[this.moduleCount - 15 + i][8] = mod;
+ }
+ }
+
+ // horizontal
+ for (var i = 0; i < 15; i++) {
+
+ var mod = (!test && ((bits >> i) & 1) == 1);
+
+ if (i < 8) {
+ this.modules[8][this.moduleCount - i - 1] = mod;
+ } else if (i < 9) {
+ this.modules[8][15 - i - 1 + 1] = mod;
+ } else {
+ this.modules[8][15 - i - 1] = mod;
+ }
+ }
+
+ // fixed module
+ this.modules[this.moduleCount - 8][8] = (!test);
+
+ },
+
+ mapData: function(data, maskPattern) {
+
+ var inc = -1;
+ var row = this.moduleCount - 1;
+ var bitIndex = 7;
+ var byteIndex = 0;
+
+ for (var col = this.moduleCount - 1; col > 0; col -= 2) {
+
+ if (col == 6) col--;
+
+ while (true) {
+
+ for (var c = 0; c < 2; c++) {
+
+ if (this.modules[row][col - c] == null) {
+
+ var dark = false;
+
+ if (byteIndex < data.length) {
+ dark = (((data[byteIndex] >>> bitIndex) & 1) == 1);
+ }
+
+ var mask = QRUtil.getMask(maskPattern, row, col - c);
+
+ if (mask) {
+ dark = !dark;
+ }
+
+ this.modules[row][col - c] = dark;
+ bitIndex--;
+
+ if (bitIndex == -1) {
+ byteIndex++;
+ bitIndex = 7;
+ }
+ }
+ }
+
+ row += inc;
+
+ if (row < 0 || this.moduleCount <= row) {
+ row -= inc;
+ inc = -inc;
+ break;
+ }
+ }
+ }
+
+ }
+
+ };
+
+ QRCode.PAD0 = 0xEC;
+ QRCode.PAD1 = 0x11;
+
+ QRCode.createData = function(typeNumber, errorCorrectLevel, dataList) {
+
+ var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectLevel);
+
+ var buffer = new QRBitBuffer();
+
+ for (var i = 0; i < dataList.length; i++) {
+ var data = dataList[i];
+ buffer.put(data.mode, 4);
+ buffer.put(data.getLength(), QRUtil.getLengthInBits(data.mode, typeNumber));
+ data.write(buffer);
+ }
+
+ // calc num max data.
+ var totalDataCount = 0;
+ for (var i = 0; i < rsBlocks.length; i++) {
+ totalDataCount += rsBlocks[i].dataCount;
+ }
+
+ if (buffer.getLengthInBits() > totalDataCount * 8) {
+ throw new Error("code length overflow. (" +
+ buffer.getLengthInBits() +
+ ">" +
+ totalDataCount * 8 +
+ ")");
+ }
+
+ // end code
+ if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) {
+ buffer.put(0, 4);
+ }
+
+ // padding
+ while (buffer.getLengthInBits() % 8 != 0) {
+ buffer.putBit(false);
+ }
+
+ // padding
+ while (true) {
+
+ if (buffer.getLengthInBits() >= totalDataCount * 8) {
+ break;
+ }
+ buffer.put(QRCode.PAD0, 8);
+
+ if (buffer.getLengthInBits() >= totalDataCount * 8) {
+ break;
+ }
+ buffer.put(QRCode.PAD1, 8);
+ }
+
+ return QRCode.createBytes(buffer, rsBlocks);
+ }
+
+ QRCode.createBytes = function(buffer, rsBlocks) {
+
+ var offset = 0;
+
+ var maxDcCount = 0;
+ var maxEcCount = 0;
+
+ var dcdata = new Array(rsBlocks.length);
+ var ecdata = new Array(rsBlocks.length);
+
+ for (var r = 0; r < rsBlocks.length; r++) {
+
+ var dcCount = rsBlocks[r].dataCount;
+ var ecCount = rsBlocks[r].totalCount - dcCount;
+
+ maxDcCount = Math.max(maxDcCount, dcCount);
+ maxEcCount = Math.max(maxEcCount, ecCount);
+
+ dcdata[r] = new Array(dcCount);
+
+ for (var i = 0; i < dcdata[r].length; i++) {
+ dcdata[r][i] = 0xff & buffer.buffer[i + offset];
+ }
+ offset += dcCount;
+
+ var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount);
+ var rawPoly = new QRPolynomial(dcdata[r], rsPoly.getLength() - 1);
+
+ var modPoly = rawPoly.mod(rsPoly);
+ ecdata[r] = new Array(rsPoly.getLength() - 1);
+ for (var i = 0; i < ecdata[r].length; i++) {
+ var modIndex = i + modPoly.getLength() - ecdata[r].length;
+ ecdata[r][i] = (modIndex >= 0) ? modPoly.get(modIndex) : 0;
+ }
+
+ }
+
+ var totalCodeCount = 0;
+ for (var i = 0; i < rsBlocks.length; i++) {
+ totalCodeCount += rsBlocks[i].totalCount;
+ }
+
+ var data = new Array(totalCodeCount);
+ var index = 0;
+
+ for (var i = 0; i < maxDcCount; i++) {
+ for (var r = 0; r < rsBlocks.length; r++) {
+ if (i < dcdata[r].length) {
+ data[index++] = dcdata[r][i];
+ }
+ }
+ }
+
+ for (var i = 0; i < maxEcCount; i++) {
+ for (var r = 0; r < rsBlocks.length; r++) {
+ if (i < ecdata[r].length) {
+ data[index++] = ecdata[r][i];
+ }
+ }
+ }
+
+ return data;
+
+ }
+
+ //---------------------------------------------------------------------
+ // QRMode
+ //---------------------------------------------------------------------
+
+ var QRMode = {
+ MODE_NUMBER: 1 << 0,
+ MODE_ALPHA_NUM: 1 << 1,
+ MODE_8BIT_BYTE: 1 << 2,
+ MODE_KANJI: 1 << 3
+ };
+
+ //---------------------------------------------------------------------
+ // QRErrorCorrectLevel
+ //---------------------------------------------------------------------
+
+ var QRErrorCorrectLevel = {
+ L: 1,
+ M: 0,
+ Q: 3,
+ H: 2
+ };
+
+ //---------------------------------------------------------------------
+ // QRMaskPattern
+ //---------------------------------------------------------------------
+
+ var QRMaskPattern = {
+ PATTERN000: 0,
+ PATTERN001: 1,
+ PATTERN010: 2,
+ PATTERN011: 3,
+ PATTERN100: 4,
+ PATTERN101: 5,
+ PATTERN110: 6,
+ PATTERN111: 7
+ };
+
+ //---------------------------------------------------------------------
+ // QRUtil
+ //---------------------------------------------------------------------
+
+ var QRUtil = {
+
+ PATTERN_POSITION_TABLE: [
+ [],
+ [6, 18],
+ [6, 22],
+ [6, 26],
+ [6, 30],
+ [6, 34],
+ [6, 22, 38],
+ [6, 24, 42],
+ [6, 26, 46],
+ [6, 28, 50],
+ [6, 30, 54],
+ [6, 32, 58],
+ [6, 34, 62],
+ [6, 26, 46, 66],
+ [6, 26, 48, 70],
+ [6, 26, 50, 74],
+ [6, 30, 54, 78],
+ [6, 30, 56, 82],
+ [6, 30, 58, 86],
+ [6, 34, 62, 90],
+ [6, 28, 50, 72, 94],
+ [6, 26, 50, 74, 98],
+ [6, 30, 54, 78, 102],
+ [6, 28, 54, 80, 106],
+ [6, 32, 58, 84, 110],
+ [6, 30, 58, 86, 114],
+ [6, 34, 62, 90, 118],
+ [6, 26, 50, 74, 98, 122],
+ [6, 30, 54, 78, 102, 126],
+ [6, 26, 52, 78, 104, 130],
+ [6, 30, 56, 82, 108, 134],
+ [6, 34, 60, 86, 112, 138],
+ [6, 30, 58, 86, 114, 142],
+ [6, 34, 62, 90, 118, 146],
+ [6, 30, 54, 78, 102, 126, 150],
+ [6, 24, 50, 76, 102, 128, 154],
+ [6, 28, 54, 80, 106, 132, 158],
+ [6, 32, 58, 84, 110, 136, 162],
+ [6, 26, 54, 82, 110, 138, 166],
+ [6, 30, 58, 86, 114, 142, 170]
+ ],
+
+ G15: (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0),
+ G18: (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0),
+ G15_MASK: (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1),
+
+ getBCHTypeInfo: function(data) {
+ var d = data << 10;
+ while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) >= 0) {
+ d ^= (QRUtil.G15 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15)));
+ }
+ return ((data << 10) | d) ^ QRUtil.G15_MASK;
+ },
+
+ getBCHTypeNumber: function(data) {
+ var d = data << 12;
+ while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) >= 0) {
+ d ^= (QRUtil.G18 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18)));
+ }
+ return (data << 12) | d;
+ },
+
+ getBCHDigit: function(data) {
+
+ var digit = 0;
+
+ while (data != 0) {
+ digit++;
+ data >>>= 1;
+ }
+
+ return digit;
+ },
+
+ getPatternPosition: function(typeNumber) {
+ return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1];
+ },
+
+ getMask: function(maskPattern, i, j) {
+
+ switch (maskPattern) {
+
+ case QRMaskPattern.PATTERN000:
+ return (i + j) % 2 == 0;
+ case QRMaskPattern.PATTERN001:
+ return i % 2 == 0;
+ case QRMaskPattern.PATTERN010:
+ return j % 3 == 0;
+ case QRMaskPattern.PATTERN011:
+ return (i + j) % 3 == 0;
+ case QRMaskPattern.PATTERN100:
+ return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 == 0;
+ case QRMaskPattern.PATTERN101:
+ return (i * j) % 2 + (i * j) % 3 == 0;
+ case QRMaskPattern.PATTERN110:
+ return ((i * j) % 2 + (i * j) % 3) % 2 == 0;
+ case QRMaskPattern.PATTERN111:
+ return ((i * j) % 3 + (i + j) % 2) % 2 == 0;
+
+ default:
+ throw new Error("bad maskPattern:" + maskPattern);
+ }
+ },
+
+ getErrorCorrectPolynomial: function(errorCorrectLength) {
+
+ var a = new QRPolynomial([1], 0);
+
+ for (var i = 0; i < errorCorrectLength; i++) {
+ a = a.multiply(new QRPolynomial([1, QRMath.gexp(i)], 0));
+ }
+
+ return a;
+ },
+
+ getLengthInBits: function(mode, type) {
+
+ if (1 <= type && type < 10) {
+
+ // 1 - 9
+
+ switch (mode) {
+ case QRMode.MODE_NUMBER:
+ return 10;
+ case QRMode.MODE_ALPHA_NUM:
+ return 9;
+ case QRMode.MODE_8BIT_BYTE:
+ return 8;
+ case QRMode.MODE_KANJI:
+ return 8;
+ default:
+ throw new Error("mode:" + mode);
+ }
+
+ } else if (type < 27) {
+
+ // 10 - 26
+
+ switch (mode) {
+ case QRMode.MODE_NUMBER:
+ return 12;
+ case QRMode.MODE_ALPHA_NUM:
+ return 11;
+ case QRMode.MODE_8BIT_BYTE:
+ return 16;
+ case QRMode.MODE_KANJI:
+ return 10;
+ default:
+ throw new Error("mode:" + mode);
+ }
+
+ } else if (type < 41) {
+
+ // 27 - 40
+
+ switch (mode) {
+ case QRMode.MODE_NUMBER:
+ return 14;
+ case QRMode.MODE_ALPHA_NUM:
+ return 13;
+ case QRMode.MODE_8BIT_BYTE:
+ return 16;
+ case QRMode.MODE_KANJI:
+ return 12;
+ default:
+ throw new Error("mode:" + mode);
+ }
+
+ } else {
+ throw new Error("type:" + type);
+ }
+ },
+
+ getLostPoint: function(qrCode) {
+
+ var moduleCount = qrCode.getModuleCount();
+
+ var lostPoint = 0;
+
+ // LEVEL1
+
+ for (var row = 0; row < moduleCount; row++) {
+
+ for (var col = 0; col < moduleCount; col++) {
+
+ var sameCount = 0;
+ var dark = qrCode.isDark(row, col);
+
+ for (var r = -1; r <= 1; r++) {
+
+ if (row + r < 0 || moduleCount <= row + r) {
+ continue;
+ }
+
+ for (var c = -1; c <= 1; c++) {
+
+ if (col + c < 0 || moduleCount <= col + c) {
+ continue;
+ }
+
+ if (r == 0 && c == 0) {
+ continue;
+ }
+
+ if (dark == qrCode.isDark(row + r, col + c)) {
+ sameCount++;
+ }
+ }
+ }
+
+ if (sameCount > 5) {
+ lostPoint += (3 + sameCount - 5);
+ }
+ }
+ }
+
+ // LEVEL2
+
+ for (var row = 0; row < moduleCount - 1; row++) {
+ for (var col = 0; col < moduleCount - 1; col++) {
+ var count = 0;
+ if (qrCode.isDark(row, col)) count++;
+ if (qrCode.isDark(row + 1, col)) count++;
+ if (qrCode.isDark(row, col + 1)) count++;
+ if (qrCode.isDark(row + 1, col + 1)) count++;
+ if (count == 0 || count == 4) {
+ lostPoint += 3;
+ }
+ }
+ }
+
+ // LEVEL3
+
+ for (var row = 0; row < moduleCount; row++) {
+ for (var col = 0; col < moduleCount - 6; col++) {
+ if (qrCode.isDark(row, col) &&
+ !qrCode.isDark(row, col + 1) &&
+ qrCode.isDark(row, col + 2) &&
+ qrCode.isDark(row, col + 3) &&
+ qrCode.isDark(row, col + 4) &&
+ !qrCode.isDark(row, col + 5) &&
+ qrCode.isDark(row, col + 6)) {
+ lostPoint += 40;
+ }
+ }
+ }
+
+ for (var col = 0; col < moduleCount; col++) {
+ for (var row = 0; row < moduleCount - 6; row++) {
+ if (qrCode.isDark(row, col) &&
+ !qrCode.isDark(row + 1, col) &&
+ qrCode.isDark(row + 2, col) &&
+ qrCode.isDark(row + 3, col) &&
+ qrCode.isDark(row + 4, col) &&
+ !qrCode.isDark(row + 5, col) &&
+ qrCode.isDark(row + 6, col)) {
+ lostPoint += 40;
+ }
+ }
+ }
+
+ // LEVEL4
+
+ var darkCount = 0;
+
+ for (var col = 0; col < moduleCount; col++) {
+ for (var row = 0; row < moduleCount; row++) {
+ if (qrCode.isDark(row, col)) {
+ darkCount++;
+ }
+ }
+ }
+
+ var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;
+ lostPoint += ratio * 10;
+
+ return lostPoint;
+ }
+
+ };
+
+
+ //---------------------------------------------------------------------
+ // QRMath
+ //---------------------------------------------------------------------
+
+ var QRMath = {
+
+ glog: function(n) {
+
+ if (n < 1) {
+ throw new Error("glog(" + n + ")");
+ }
+
+ return QRMath.LOG_TABLE[n];
+ },
+
+ gexp: function(n) {
+
+ while (n < 0) {
+ n += 255;
+ }
+
+ while (n >= 256) {
+ n -= 255;
+ }
+
+ return QRMath.EXP_TABLE[n];
+ },
+
+ EXP_TABLE: new Array(256),
+
+ LOG_TABLE: new Array(256)
+
+ };
+
+ for (var i = 0; i < 8; i++) {
+ QRMath.EXP_TABLE[i] = 1 << i;
+ }
+ for (var i = 8; i < 256; i++) {
+ QRMath.EXP_TABLE[i] = QRMath.EXP_TABLE[i - 4] ^
+ QRMath.EXP_TABLE[i - 5] ^
+ QRMath.EXP_TABLE[i - 6] ^
+ QRMath.EXP_TABLE[i - 8];
+ }
+ for (var i = 0; i < 255; i++) {
+ QRMath.LOG_TABLE[QRMath.EXP_TABLE[i]] = i;
+ }
+
+ //---------------------------------------------------------------------
+ // QRPolynomial
+ //---------------------------------------------------------------------
+
+ function QRPolynomial(num, shift) {
+
+ if (num.length == undefined) {
+ throw new Error(num.length + "/" + shift);
+ }
+
+ var offset = 0;
+
+ while (offset < num.length && num[offset] == 0) {
+ offset++;
+ }
+
+ this.num = new Array(num.length - offset + shift);
+ for (var i = 0; i < num.length - offset; i++) {
+ this.num[i] = num[i + offset];
+ }
+ }
+
+ QRPolynomial.prototype = {
+
+ get: function(index) {
+ return this.num[index];
+ },
+
+ getLength: function() {
+ return this.num.length;
+ },
+
+ multiply: function(e) {
+
+ var num = new Array(this.getLength() + e.getLength() - 1);
+
+ for (var i = 0; i < this.getLength(); i++) {
+ for (var j = 0; j < e.getLength(); j++) {
+ num[i + j] ^= QRMath.gexp(QRMath.glog(this.get(i)) + QRMath.glog(e.get(j)));
+ }
+ }
+
+ return new QRPolynomial(num, 0);
+ },
+
+ mod: function(e) {
+
+ if (this.getLength() - e.getLength() < 0) {
+ return this;
+ }
+
+ var ratio = QRMath.glog(this.get(0)) - QRMath.glog(e.get(0));
+
+ var num = new Array(this.getLength());
+
+ for (var i = 0; i < this.getLength(); i++) {
+ num[i] = this.get(i);
+ }
+
+ for (var i = 0; i < e.getLength(); i++) {
+ num[i] ^= QRMath.gexp(QRMath.glog(e.get(i)) + ratio);
+ }
+
+ // recursive call
+ return new QRPolynomial(num, 0).mod(e);
+ }
+ };
+
+ //---------------------------------------------------------------------
+ // QRRSBlock
+ //---------------------------------------------------------------------
+
+ function QRRSBlock(totalCount, dataCount) {
+ this.totalCount = totalCount;
+ this.dataCount = dataCount;
+ }
+
+ QRRSBlock.RS_BLOCK_TABLE = [
+
+ // L
+ // M
+ // Q
+ // H
+
+ // 1
+ [1, 26, 19],
+ [1, 26, 16],
+ [1, 26, 13],
+ [1, 26, 9],
+
+ // 2
+ [1, 44, 34],
+ [1, 44, 28],
+ [1, 44, 22],
+ [1, 44, 16],
+
+ // 3
+ [1, 70, 55],
+ [1, 70, 44],
+ [2, 35, 17],
+ [2, 35, 13],
+
+ // 4
+ [1, 100, 80],
+ [2, 50, 32],
+ [2, 50, 24],
+ [4, 25, 9],
+
+ // 5
+ [1, 134, 108],
+ [2, 67, 43],
+ [2, 33, 15, 2, 34, 16],
+ [2, 33, 11, 2, 34, 12],
+
+ // 6
+ [2, 86, 68],
+ [4, 43, 27],
+ [4, 43, 19],
+ [4, 43, 15],
+
+ // 7
+ [2, 98, 78],
+ [4, 49, 31],
+ [2, 32, 14, 4, 33, 15],
+ [4, 39, 13, 1, 40, 14],
+
+ // 8
+ [2, 121, 97],
+ [2, 60, 38, 2, 61, 39],
+ [4, 40, 18, 2, 41, 19],
+ [4, 40, 14, 2, 41, 15],
+
+ // 9
+ [2, 146, 116],
+ [3, 58, 36, 2, 59, 37],
+ [4, 36, 16, 4, 37, 17],
+ [4, 36, 12, 4, 37, 13],
+
+ // 10
+ [2, 86, 68, 2, 87, 69],
+ [4, 69, 43, 1, 70, 44],
+ [6, 43, 19, 2, 44, 20],
+ [6, 43, 15, 2, 44, 16],
+
+ // 11
+ [4, 101, 81],
+ [1, 80, 50, 4, 81, 51],
+ [4, 50, 22, 4, 51, 23],
+ [3, 36, 12, 8, 37, 13],
+
+ // 12
+ [2, 116, 92, 2, 117, 93],
+ [6, 58, 36, 2, 59, 37],
+ [4, 46, 20, 6, 47, 21],
+ [7, 42, 14, 4, 43, 15],
+
+ // 13
+ [4, 133, 107],
+ [8, 59, 37, 1, 60, 38],
+ [8, 44, 20, 4, 45, 21],
+ [12, 33, 11, 4, 34, 12],
+
+ // 14
+ [3, 145, 115, 1, 146, 116],
+ [4, 64, 40, 5, 65, 41],
+ [11, 36, 16, 5, 37, 17],
+ [11, 36, 12, 5, 37, 13],
+
+ // 15
+ [5, 109, 87, 1, 110, 88],
+ [5, 65, 41, 5, 66, 42],
+ [5, 54, 24, 7, 55, 25],
+ [11, 36, 12],
+
+ // 16
+ [5, 122, 98, 1, 123, 99],
+ [7, 73, 45, 3, 74, 46],
+ [15, 43, 19, 2, 44, 20],
+ [3, 45, 15, 13, 46, 16],
+
+ // 17
+ [1, 135, 107, 5, 136, 108],
+ [10, 74, 46, 1, 75, 47],
+ [1, 50, 22, 15, 51, 23],
+ [2, 42, 14, 17, 43, 15],
+
+ // 18
+ [5, 150, 120, 1, 151, 121],
+ [9, 69, 43, 4, 70, 44],
+ [17, 50, 22, 1, 51, 23],
+ [2, 42, 14, 19, 43, 15],
+
+ // 19
+ [3, 141, 113, 4, 142, 114],
+ [3, 70, 44, 11, 71, 45],
+ [17, 47, 21, 4, 48, 22],
+ [9, 39, 13, 16, 40, 14],
+
+ // 20
+ [3, 135, 107, 5, 136, 108],
+ [3, 67, 41, 13, 68, 42],
+ [15, 54, 24, 5, 55, 25],
+ [15, 43, 15, 10, 44, 16],
+
+ // 21
+ [4, 144, 116, 4, 145, 117],
+ [17, 68, 42],
+ [17, 50, 22, 6, 51, 23],
+ [19, 46, 16, 6, 47, 17],
+
+ // 22
+ [2, 139, 111, 7, 140, 112],
+ [17, 74, 46],
+ [7, 54, 24, 16, 55, 25],
+ [34, 37, 13],
+
+ // 23
+ [4, 151, 121, 5, 152, 122],
+ [4, 75, 47, 14, 76, 48],
+ [11, 54, 24, 14, 55, 25],
+ [16, 45, 15, 14, 46, 16],
+
+ // 24
+ [6, 147, 117, 4, 148, 118],
+ [6, 73, 45, 14, 74, 46],
+ [11, 54, 24, 16, 55, 25],
+ [30, 46, 16, 2, 47, 17],
+
+ // 25
+ [8, 132, 106, 4, 133, 107],
+ [8, 75, 47, 13, 76, 48],
+ [7, 54, 24, 22, 55, 25],
+ [22, 45, 15, 13, 46, 16],
+
+ // 26
+ [10, 142, 114, 2, 143, 115],
+ [19, 74, 46, 4, 75, 47],
+ [28, 50, 22, 6, 51, 23],
+ [33, 46, 16, 4, 47, 17],
+
+ // 27
+ [8, 152, 122, 4, 153, 123],
+ [22, 73, 45, 3, 74, 46],
+ [8, 53, 23, 26, 54, 24],
+ [12, 45, 15, 28, 46, 16],
+
+ // 28
+ [3, 147, 117, 10, 148, 118],
+ [3, 73, 45, 23, 74, 46],
+ [4, 54, 24, 31, 55, 25],
+ [11, 45, 15, 31, 46, 16],
+
+ // 29
+ [7, 146, 116, 7, 147, 117],
+ [21, 73, 45, 7, 74, 46],
+ [1, 53, 23, 37, 54, 24],
+ [19, 45, 15, 26, 46, 16],
+
+ // 30
+ [5, 145, 115, 10, 146, 116],
+ [19, 75, 47, 10, 76, 48],
+ [15, 54, 24, 25, 55, 25],
+ [23, 45, 15, 25, 46, 16],
+
+ // 31
+ [13, 145, 115, 3, 146, 116],
+ [2, 74, 46, 29, 75, 47],
+ [42, 54, 24, 1, 55, 25],
+ [23, 45, 15, 28, 46, 16],
+
+ // 32
+ [17, 145, 115],
+ [10, 74, 46, 23, 75, 47],
+ [10, 54, 24, 35, 55, 25],
+ [19, 45, 15, 35, 46, 16],
+
+ // 33
+ [17, 145, 115, 1, 146, 116],
+ [14, 74, 46, 21, 75, 47],
+ [29, 54, 24, 19, 55, 25],
+ [11, 45, 15, 46, 46, 16],
+
+ // 34
+ [13, 145, 115, 6, 146, 116],
+ [14, 74, 46, 23, 75, 47],
+ [44, 54, 24, 7, 55, 25],
+ [59, 46, 16, 1, 47, 17],
+
+ // 35
+ [12, 151, 121, 7, 152, 122],
+ [12, 75, 47, 26, 76, 48],
+ [39, 54, 24, 14, 55, 25],
+ [22, 45, 15, 41, 46, 16],
+
+ // 36
+ [6, 151, 121, 14, 152, 122],
+ [6, 75, 47, 34, 76, 48],
+ [46, 54, 24, 10, 55, 25],
+ [2, 45, 15, 64, 46, 16],
+
+ // 37
+ [17, 152, 122, 4, 153, 123],
+ [29, 74, 46, 14, 75, 47],
+ [49, 54, 24, 10, 55, 25],
+ [24, 45, 15, 46, 46, 16],
+
+ // 38
+ [4, 152, 122, 18, 153, 123],
+ [13, 74, 46, 32, 75, 47],
+ [48, 54, 24, 14, 55, 25],
+ [42, 45, 15, 32, 46, 16],
+
+ // 39
+ [20, 147, 117, 4, 148, 118],
+ [40, 75, 47, 7, 76, 48],
+ [43, 54, 24, 22, 55, 25],
+ [10, 45, 15, 67, 46, 16],
+
+ // 40
+ [19, 148, 118, 6, 149, 119],
+ [18, 75, 47, 31, 76, 48],
+ [34, 54, 24, 34, 55, 25],
+ [20, 45, 15, 61, 46, 16]
+ ];
+
+ QRRSBlock.getRSBlocks = function(typeNumber, errorCorrectLevel) {
+
+ var rsBlock = QRRSBlock.getRsBlockTable(typeNumber, errorCorrectLevel);
+
+ if (rsBlock == undefined) {
+ throw new Error("bad rs block @ typeNumber:" + typeNumber + "/errorCorrectLevel:" + errorCorrectLevel);
+ }
+
+ var length = rsBlock.length / 3;
+
+ var list = new Array();
+
+ for (var i = 0; i < length; i++) {
+
+ var count = rsBlock[i * 3 + 0];
+ var totalCount = rsBlock[i * 3 + 1];
+ var dataCount = rsBlock[i * 3 + 2];
+
+ for (var j = 0; j < count; j++) {
+ list.push(new QRRSBlock(totalCount, dataCount));
+ }
+ }
+
+ return list;
+ }
+
+ QRRSBlock.getRsBlockTable = function(typeNumber, errorCorrectLevel) {
+
+ switch (errorCorrectLevel) {
+ case QRErrorCorrectLevel.L:
+ return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0];
+ case QRErrorCorrectLevel.M:
+ return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1];
+ case QRErrorCorrectLevel.Q:
+ return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2];
+ case QRErrorCorrectLevel.H:
+ return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3];
+ default:
+ return undefined;
+ }
+ }
+
+ //---------------------------------------------------------------------
+ // QRBitBuffer
+ //---------------------------------------------------------------------
+
+ function QRBitBuffer() {
+ this.buffer = new Array();
+ this.length = 0;
+ }
+
+ QRBitBuffer.prototype = {
+
+ get: function(index) {
+ var bufIndex = Math.floor(index / 8);
+ return ((this.buffer[bufIndex] >>> (7 - index % 8)) & 1) == 1;
+ },
+
+ put: function(num, length) {
+ for (var i = 0; i < length; i++) {
+ this.putBit(((num >>> (length - i - 1)) & 1) == 1);
+ }
+ },
+
+ getLengthInBits: function() {
+ return this.length;
+ },
+
+ putBit: function(bit) {
+
+ var bufIndex = Math.floor(this.length / 8);
+ if (this.buffer.length <= bufIndex) {
+ this.buffer.push(0);
+ }
+
+ if (bit) {
+ this.buffer[bufIndex] |= (0x80 >>> (this.length % 8));
+ }
+
+ this.length++;
+ }
+ };
+
+ //---------------------------------------------------------------------
+ // Support Chinese
+ //---------------------------------------------------------------------
+ function utf16To8(text) {
+ var result = '';
+ var c;
+ for (var i = 0; i < text.length; i++) {
+ c = text.charCodeAt(i);
+ if (c >= 0x0001 && c <= 0x007F) {
+ result += text.charAt(i);
+ } else if (c > 0x07FF) {
+ result += String.fromCharCode(0xE0 | c >> 12 & 0x0F);
+ result += String.fromCharCode(0x80 | c >> 6 & 0x3F);
+ result += String.fromCharCode(0x80 | c >> 0 & 0x3F);
+ } else {
+ result += String.fromCharCode(0xC0 | c >> 6 & 0x1F);
+ result += String.fromCharCode(0x80 | c >> 0 & 0x3F);
+ }
+ }
+ return result;
+ }
+
+ uQRCode = {
+
+ errorCorrectLevel: QRErrorCorrectLevel,
+
+ defaults: {
+ size: 354,
+ margin: 0,
+ backgroundColor: '#ffffff',
+ foregroundColor: '#000000',
+ fileType: 'png', // 'jpg', 'png'
+ errorCorrectLevel: QRErrorCorrectLevel.H,
+ typeNumber: -1
+ },
+
+ make: function(options) {
+ var defaultOptions = {
+ canvasId: options.canvasId,
+ componentInstance: options.componentInstance,
+ text: options.text,
+ size: this.defaults.size,
+ margin: this.defaults.margin,
+ backgroundColor: this.defaults.backgroundColor,
+ foregroundColor: this.defaults.foregroundColor,
+ fileType: this.defaults.fileType,
+ errorCorrectLevel: this.defaults.errorCorrectLevel,
+ typeNumber: this.defaults.typeNumber
+ };
+ if (options) {
+ for (var i in options) {
+ defaultOptions[i] = options[i];
+ }
+ }
+ options = defaultOptions;
+ if (!options.canvasId) {
+ console.error('uQRCode: Please set canvasId!');
+ return;
+ }
+
+ function createCanvas() {
+ var qrcode = new QRCode(options.typeNumber, options.errorCorrectLevel);
+ qrcode.addData(utf16To8(options.text));
+ qrcode.make();
+
+ var ctx = uni.createCanvasContext(options.canvasId, options.componentInstance);
+ ctx.setFillStyle(options.backgroundColor);
+ ctx.fillRect(0, 0, options.size, options.size);
+
+ var tileW = (options.size - options.margin * 2) / qrcode.getModuleCount();
+ var tileH = tileW;
+
+ for (var row = 0; row < qrcode.getModuleCount(); row++) {
+ for (var col = 0; col < qrcode.getModuleCount(); col++) {
+ var style = qrcode.isDark(row, col) ? options.foregroundColor : options.backgroundColor;
+ ctx.setFillStyle(style);
+ var x = Math.round(col * tileW) + options.margin;
+ var y = Math.round(row * tileH) + options.margin;
+ var w = Math.ceil((col + 1) * tileW) - Math.floor(col * tileW);
+ var h = Math.ceil((row + 1) * tileW) - Math.floor(row * tileW);
+ ctx.fillRect(x, y, w, h);
+ }
+ }
+
+ setTimeout(function() {
+ ctx.draw(false, (function() {
+ setTimeout(function() {
+ uni.canvasToTempFilePath({
+ canvasId: options.canvasId,
+ fileType: options.fileType,
+ width: options.size,
+ height: options.size,
+ destWidth: options.size,
+ destHeight: options.size,
+ success: function(res) {
+ options.success && options.success(res.tempFilePath);
+ },
+ fail: function(error) {
+ options.fail && options.fail(error);
+ },
+ complete: function(res) {
+ options.complete && options.complete(res);
+ }
+ }, options.componentInstance);
+ }, options.text.length + 100);
+ })());
+ }, 150);
+ }
+
+ createCanvas();
+ }
+
+ }
+
+})()
+
+export default uQRCode
diff --git a/common/utils.js b/common/utils.js
new file mode 100644
index 0000000000000000000000000000000000000000..11276b2c1d2727ede7a807f06b6350b903b696e0
--- /dev/null
+++ b/common/utils.js
@@ -0,0 +1,57 @@
+export function getDeviceUUID() {
+ let deviceId = uni.getStorageSync('uni_deviceId') ||
+ uni.getSystemInfoSync().deviceId ||
+ uni.getSystemInfoSync().system + '_' + Math.random().toString(36).substr(2);
+
+ uni.setStorageSync('uni_deviceId', deviceId)
+ return deviceId;
+}
+export function friendlyDate(timestamp) {
+ var formats = {
+ 'year': '%n% 年前',
+ 'month': '%n% 月前',
+ 'day': '%n% 天前',
+ 'hour': '%n% 小时前',
+ 'minute': '%n% 分钟前',
+ 'second': '%n% 秒前',
+ };
+
+ var now = Date.now();
+ var seconds = Math.floor((now - timestamp) / 1000);
+ var minutes = Math.floor(seconds / 60);
+ var hours = Math.floor(minutes / 60);
+ var days = Math.floor(hours / 24);
+ var months = Math.floor(days / 30);
+ var years = Math.floor(months / 12);
+
+ var diffType = '';
+ var diffValue = 0;
+ if (years > 0) {
+ diffType = 'year';
+ diffValue = years;
+ } else {
+ if (months > 0) {
+ diffType = 'month';
+ diffValue = months;
+ } else {
+ if (days > 0) {
+ diffType = 'day';
+ diffValue = days;
+ } else {
+ if (hours > 0) {
+ diffType = 'hour';
+ diffValue = hours;
+ } else {
+ if (minutes > 0) {
+ diffType = 'minute';
+ diffValue = minutes;
+ } else {
+ diffType = 'second';
+ diffValue = seconds === 0 ? (seconds = 1) : seconds;
+ }
+ }
+ }
+ }
+ }
+ return formats[diffType].replace('%n%', diffValue);
+}
\ No newline at end of file
diff --git a/components/m-icon/m-icon.css b/components/m-icon/m-icon.css
new file mode 100644
index 0000000000000000000000000000000000000000..438151e0367fe6d674040d527f2fc5a2f516f5ae
--- /dev/null
+++ b/components/m-icon/m-icon.css
@@ -0,0 +1,378 @@
+@font-face {
+ font-family: uniicons;
+ font-weight: normal;
+ font-style: normal;
+ src: url('/static/uni.ttf') format('truetype');
+}
+
+.m-icon {
+ font-family: uniicons;
+ /* font-size: 24px; */
+ margin-left: 20px;
+ font-weight: normal;
+ font-style: normal;
+ line-height: 1;
+ display: inline-block;
+ text-decoration: none;
+ -webkit-font-smoothing: antialiased;
+}
+
+.m-icon.uni-active {
+ color: #007aff;
+}
+
+.m-icon-contact:before {
+ content: '\e100';
+}
+
+.m-icon-person:before {
+ content: '\e101';
+}
+
+.m-icon-personadd:before {
+ content: '\e102';
+}
+
+.m-icon-contact-filled:before {
+ content: '\e130';
+}
+
+.m-icon-person-filled:before {
+ content: '\e131';
+}
+
+.m-icon-personadd-filled:before {
+ content: '\e132';
+}
+
+.m-icon-phone:before {
+ content: '\e200';
+}
+
+.m-icon-email:before {
+ content: '\e201';
+}
+
+.m-icon-chatbubble:before {
+ content: '\e202';
+}
+
+.m-icon-chatboxes:before {
+ content: '\e203';
+}
+
+.m-icon-phone-filled:before {
+ content: '\e230';
+}
+
+.m-icon-email-filled:before {
+ content: '\e231';
+}
+
+.m-icon-chatbubble-filled:before {
+ content: '\e232';
+}
+
+.m-icon-chatboxes-filled:before {
+ content: '\e233';
+}
+
+.m-icon-weibo:before {
+ content: '\e260';
+}
+
+.m-icon-weixin:before {
+ content: '\e261';
+}
+
+.m-icon-pengyouquan:before {
+ content: '\e262';
+}
+
+.m-icon-chat:before {
+ content: '\e263';
+}
+
+.m-icon-qq:before {
+ content: '\e264';
+}
+
+.m-icon-videocam:before {
+ content: '\e300';
+}
+
+.m-icon-camera:before {
+ content: '\e301';
+}
+
+.m-icon-mic:before {
+ content: '\e302';
+}
+
+.m-icon-location:before {
+ content: '\e303';
+}
+
+.m-icon-mic-filled:before,
+.m-icon-speech:before {
+ content: '\e332';
+}
+
+.m-icon-location-filled:before {
+ content: '\e333';
+}
+
+.m-icon-micoff:before {
+ content: '\e360';
+}
+
+.m-icon-image:before {
+ content: '\e363';
+}
+
+.m-icon-map:before {
+ content: '\e364';
+}
+
+.m-icon-compose:before {
+ content: '\e400';
+}
+
+.m-icon-trash:before {
+ content: '\e401';
+}
+
+.m-icon-upload:before {
+ content: '\e402';
+}
+
+.m-icon-download:before {
+ content: '\e403';
+}
+
+.m-icon-close:before {
+ content: '\e404';
+}
+
+.m-icon-redo:before {
+ content: '\e405';
+}
+
+.m-icon-undo:before {
+ content: '\e406';
+}
+
+.m-icon-refresh:before {
+ content: '\e407';
+}
+
+.m-icon-star:before {
+ content: '\e408';
+}
+
+.m-icon-plus:before {
+ content: '\e409';
+}
+
+.m-icon-minus:before {
+ content: '\e410';
+}
+
+.m-icon-circle:before,
+.m-icon-checkbox:before {
+ content: '\e411';
+}
+
+.m-icon-close-filled:before,
+.m-icon-clear:before {
+ content: '\e434';
+}
+
+.m-icon-refresh-filled:before {
+ content: '\e437';
+}
+
+.m-icon-star-filled:before {
+ content: '\e438';
+}
+
+.m-icon-plus-filled:before {
+ content: '\e439';
+}
+
+.m-icon-minus-filled:before {
+ content: '\e440';
+}
+
+.m-icon-circle-filled:before {
+ content: '\e441';
+}
+
+.m-icon-checkbox-filled:before {
+ content: '\e442';
+}
+
+.m-icon-closeempty:before {
+ content: '\e460';
+}
+
+.m-icon-refreshempty:before {
+ content: '\e461';
+}
+
+.m-icon-reload:before {
+ content: '\e462';
+}
+
+.m-icon-starhalf:before {
+ content: '\e463';
+}
+
+.m-icon-spinner:before {
+ content: '\e464';
+}
+
+.m-icon-spinner-cycle:before {
+ content: '\e465';
+}
+
+.m-icon-search:before {
+ content: '\e466';
+}
+
+.m-icon-plusempty:before {
+ content: '\e468';
+}
+
+.m-icon-forward:before {
+ content: '\e470';
+}
+
+.m-icon-back:before,
+.m-icon-left-nav:before {
+ content: '\e471';
+}
+
+.m-icon-checkmarkempty:before {
+ content: '\e472';
+}
+
+.m-icon-home:before {
+ content: '\e500';
+}
+
+.m-icon-navigate:before {
+ content: '\e501';
+}
+
+.m-icon-gear:before {
+ content: '\e502';
+}
+
+.m-icon-paperplane:before {
+ content: '\e503';
+}
+
+.m-icon-info:before {
+ content: '\e504';
+}
+
+.m-icon-help:before {
+ content: '\e505';
+}
+
+.m-icon-locked:before {
+ content: '\e506';
+}
+
+.m-icon-more:before {
+ content: '\e507';
+}
+
+.m-icon-flag:before {
+ content: '\e508';
+}
+
+.m-icon-home-filled:before {
+ content: '\e530';
+}
+
+.m-icon-gear-filled:before {
+ content: '\e532';
+}
+
+.m-icon-info-filled:before {
+ content: '\e534';
+}
+
+.m-icon-help-filled:before {
+ content: '\e535';
+}
+
+.m-icon-more-filled:before {
+ content: '\e537';
+}
+
+.m-icon-settings:before {
+ content: '\e560';
+}
+
+.m-icon-list:before {
+ content: '\e562';
+}
+
+.m-icon-bars:before {
+ content: '\e563';
+}
+
+.m-icon-loop:before {
+ content: '\e565';
+}
+
+.m-icon-paperclip:before {
+ content: '\e567';
+}
+
+.m-icon-eye:before {
+ content: '\e568';
+}
+
+.m-icon-arrowup:before {
+ content: '\e580';
+}
+
+.m-icon-arrowdown:before {
+ content: '\e581';
+}
+
+.m-icon-arrowleft:before {
+ content: '\e582';
+}
+
+.m-icon-arrowright:before {
+ content: '\e583';
+}
+
+.m-icon-arrowthinup:before {
+ content: '\e584';
+}
+
+.m-icon-arrowthindown:before {
+ content: '\e585';
+}
+
+.m-icon-arrowthinleft:before {
+ content: '\e586';
+}
+
+.m-icon-arrowthinright:before {
+ content: '\e587';
+}
+
+.m-icon-pulldown:before {
+ content: '\e588';
+}
+
+.m-icon-scan:before {
+ content: "\e612";
+}
diff --git a/components/m-icon/m-icon.vue b/components/m-icon/m-icon.vue
new file mode 100644
index 0000000000000000000000000000000000000000..57cb1f73d7bdb15ad3a4b078a70aa4cf493eb275
--- /dev/null
+++ b/components/m-icon/m-icon.vue
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
diff --git a/components/m-input.vue b/components/m-input.vue
new file mode 100644
index 0000000000000000000000000000000000000000..adc4327b169a0c6c371ade734faaf8fcc55c24a0
--- /dev/null
+++ b/components/m-input.vue
@@ -0,0 +1,125 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/u-parse/components/wxParseAudio.vue b/components/u-parse/components/wxParseAudio.vue
new file mode 100644
index 0000000000000000000000000000000000000000..b277717f10b99d3f569da411b04528a40c22d222
--- /dev/null
+++ b/components/u-parse/components/wxParseAudio.vue
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
diff --git a/components/u-parse/components/wxParseImg.vue b/components/u-parse/components/wxParseImg.vue
new file mode 100644
index 0000000000000000000000000000000000000000..de9978b1db7ad66b051a3cc506486ff9c28c9ce9
--- /dev/null
+++ b/components/u-parse/components/wxParseImg.vue
@@ -0,0 +1,94 @@
+
+
+
+
+
diff --git a/components/u-parse/components/wxParseTable.vue b/components/u-parse/components/wxParseTable.vue
new file mode 100644
index 0000000000000000000000000000000000000000..e1e25bf5ebeeb03d4de0c30eaac30eade2a7011e
--- /dev/null
+++ b/components/u-parse/components/wxParseTable.vue
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/u-parse/components/wxParseTemplate0.vue b/components/u-parse/components/wxParseTemplate0.vue
new file mode 100644
index 0000000000000000000000000000000000000000..01bf8e167bd04c35944a1aa215bf21872db0566f
--- /dev/null
+++ b/components/u-parse/components/wxParseTemplate0.vue
@@ -0,0 +1,98 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ \n
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{node.text}}
+
+
+
diff --git a/components/u-parse/components/wxParseTemplate1.vue b/components/u-parse/components/wxParseTemplate1.vue
new file mode 100644
index 0000000000000000000000000000000000000000..7054e35fa54630114d83705331c35d8041ef1306
--- /dev/null
+++ b/components/u-parse/components/wxParseTemplate1.vue
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ \n
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{node.text}}
+
+
+
diff --git a/components/u-parse/components/wxParseTemplate10.vue b/components/u-parse/components/wxParseTemplate10.vue
new file mode 100644
index 0000000000000000000000000000000000000000..11c252ce6a46fb73063dc69f5742a0e5112d3792
--- /dev/null
+++ b/components/u-parse/components/wxParseTemplate10.vue
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ \n
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{node.text}}
+
+
+
diff --git a/components/u-parse/components/wxParseTemplate11.vue b/components/u-parse/components/wxParseTemplate11.vue
new file mode 100644
index 0000000000000000000000000000000000000000..0d04e53c4fca34129d60c608e73f10a994cf2b24
--- /dev/null
+++ b/components/u-parse/components/wxParseTemplate11.vue
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ \n
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{node.text}}
+
+
+
diff --git a/components/u-parse/components/wxParseTemplate2.vue b/components/u-parse/components/wxParseTemplate2.vue
new file mode 100644
index 0000000000000000000000000000000000000000..f06782a14c142d95f5536a9603b0bc28de88bfb7
--- /dev/null
+++ b/components/u-parse/components/wxParseTemplate2.vue
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ \n
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{node.text}}
+
+
+
diff --git a/components/u-parse/components/wxParseTemplate3.vue b/components/u-parse/components/wxParseTemplate3.vue
new file mode 100644
index 0000000000000000000000000000000000000000..b0943f8498307ce0375e700935ce6cbf4d2a3991
--- /dev/null
+++ b/components/u-parse/components/wxParseTemplate3.vue
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ \n
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{node.text}}
+
+
+
diff --git a/components/u-parse/components/wxParseTemplate4.vue b/components/u-parse/components/wxParseTemplate4.vue
new file mode 100644
index 0000000000000000000000000000000000000000..8a437564ccf7d7b5f33936b7a8a8281012d8247d
--- /dev/null
+++ b/components/u-parse/components/wxParseTemplate4.vue
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ \n
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{node.text}}
+
+
+
diff --git a/components/u-parse/components/wxParseTemplate5.vue b/components/u-parse/components/wxParseTemplate5.vue
new file mode 100644
index 0000000000000000000000000000000000000000..0c0993e39cd367438d2899cc53398ede4c089fe0
--- /dev/null
+++ b/components/u-parse/components/wxParseTemplate5.vue
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ \n
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{node.text}}
+
+
+
diff --git a/components/u-parse/components/wxParseTemplate6.vue b/components/u-parse/components/wxParseTemplate6.vue
new file mode 100644
index 0000000000000000000000000000000000000000..0dca28ae3de8c8d103e62dd4bc527f7a9de500ae
--- /dev/null
+++ b/components/u-parse/components/wxParseTemplate6.vue
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ \n
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{node.text}}
+
+
+
diff --git a/components/u-parse/components/wxParseTemplate7.vue b/components/u-parse/components/wxParseTemplate7.vue
new file mode 100644
index 0000000000000000000000000000000000000000..b62acafe60976999276dcafc01ed5e07d7943221
--- /dev/null
+++ b/components/u-parse/components/wxParseTemplate7.vue
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ \n
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{node.text}}
+
+
+
diff --git a/components/u-parse/components/wxParseTemplate8.vue b/components/u-parse/components/wxParseTemplate8.vue
new file mode 100644
index 0000000000000000000000000000000000000000..f6fa037d7cdc02c5b26264a8fd4253a3a56276bb
--- /dev/null
+++ b/components/u-parse/components/wxParseTemplate8.vue
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ \n
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{node.text}}
+
+
+
diff --git a/components/u-parse/components/wxParseTemplate9.vue b/components/u-parse/components/wxParseTemplate9.vue
new file mode 100644
index 0000000000000000000000000000000000000000..47ac81a2bf68433a4e87b53ad6541716c65b42a7
--- /dev/null
+++ b/components/u-parse/components/wxParseTemplate9.vue
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ \n
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{node.text}}
+
+
+
diff --git a/components/u-parse/components/wxParseVideo.vue b/components/u-parse/components/wxParseVideo.vue
new file mode 100644
index 0000000000000000000000000000000000000000..7d05285ea5cb5d97bef8cc36a763b498fff4593d
--- /dev/null
+++ b/components/u-parse/components/wxParseVideo.vue
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
diff --git a/components/u-parse/libs/html2json.js b/components/u-parse/libs/html2json.js
new file mode 100644
index 0000000000000000000000000000000000000000..09273820f381c410931de744a511a962d75985f1
--- /dev/null
+++ b/components/u-parse/libs/html2json.js
@@ -0,0 +1,261 @@
+/**
+ * html2Json 改造来自: https://github.com/Jxck/html2json
+ *
+ *
+ * author: Di (微信小程序开发工程师)
+ * organization: WeAppDev(微信小程序开发论坛)(http://weappdev.com)
+ * 垂直微信小程序开发交流社区
+ *
+ * github地址: https://github.com/icindy/wxParse
+ *
+ * for: 微信小程序富文本解析
+ * detail : http://weappdev.com/t/wxparse-alpha0-1-html-markdown/184
+ */
+
+import wxDiscode from './wxDiscode';
+import HTMLParser from './htmlparser';
+
+function makeMap(str) {
+ const obj = {};
+ const items = str.split(',');
+ for (let i = 0; i < items.length; i += 1) obj[items[i]] = true;
+ return obj;
+}
+
+// Block Elements - HTML 5
+const block = makeMap('br,code,address,article,applet,aside,audio,blockquote,button,canvas,center,dd,del,dir,div,dl,dt,fieldset,figcaption,figure,footer,form,frameset,h1,h2,h3,h4,h5,h6,header,hgroup,hr,iframe,ins,isindex,li,map,menu,noframes,noscript,object,ol,output,p,pre,section,script,table,tbody,td,tfoot,th,thead,tr,ul,video');
+
+// Inline Elements - HTML 5
+const inline = makeMap('a,abbr,acronym,applet,b,basefont,bdo,big,button,cite,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,script,select,small,span,strike,strong,sub,sup,textarea,tt,u,var');
+
+// Elements that you can, intentionally, leave open
+// (and which close themselves)
+const closeSelf = makeMap('colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr');
+
+function removeDOCTYPE(html) {
+ const isDocument = /
([^]*)<\/body>/.test(html);
+ return isDocument ? RegExp.$1 : html;
+}
+
+function trimHtml(html) {
+ return html
+ .replace(//gi, '')
+ .replace(/\/\*.*?\*\//gi, '')
+ .replace(/[ ]+/gi, '')
+ .replace(/
diff --git a/components/uni-clientdb/license.md b/components/uni-clientdb/license.md
new file mode 100644
index 0000000000000000000000000000000000000000..2b0e438f54060672fcd743e27bec84bd78015cc4
--- /dev/null
+++ b/components/uni-clientdb/license.md
@@ -0,0 +1,30 @@
+# clientDB使用许可协议
+本协议是数字天堂(北京)网络技术有限公司(以下称“DCloud”)与您之间达成的关于clientDB框架(以下简称本框架)的协议。
+本协议签订地点为中华人民共和国北京市海淀区。
+您使用本框架即视为您已阅读并同意受本协议的约束。
+
+## 知识产权及使用授权
+您可以自由下载、使用、复制本框架而不需要向DCloud付费。
+DCloud所拥有的知识产权,包括但不限于商标、专利、著作权、商业秘密、专有数据、源码,并不发生转移或共享。
+您使用本框架开发的代码及输出物,包括但不限于网站、移动应用,其知识产权归属您所有。
+本框架未包含第三方软件或技术,不涉及额外遵循第三方软件的授权协议问题。
+
+## 您的义务
+您不得破解、反编译、逆向工程本框架,不得破解或劫持本框架网络请求,不得对DCloud服务进行网络攻击,不得利用DCloud系统漏洞谋利或侵害DCloud利益,不得替换、删改本框架自带的非用户自定义文件。
+未经书面许可您不可利用DCloud产品的全部或部分文件、模块、组件来制作与DCloud争夺用户的产品(通过DCloud插件市场服务开发者不属于此范围)。
+如果您违反您的义务,DCloud将有权停止您使用本框架,造成的损失由您自行承担。
+如果您给DCloud造成重大损失,或者在接收到DCloud的停止违约通知后拒不改正,DCloud将有权停止对您的DCloud所有产品和服务的使用授权,冻结您在DCloud所有产品服务中的预付款项和应收款项,因此造成的损失由您自行承担。
+如果您的行为产生法律问题,DCloud有权追责您的法律责任。
+
+## 隐私条款
+本框架未进行任何数据采集、发送等涉及数据隐私的行为。
+
+## 安全
+您理解并同意,本框架同其他软件一样,无法承诺绝对的安全性。
+当DCloud发现本框架的任何安全漏洞时,将及时在[社区](https://ask.dcloud.net.cn/explore/)发送公告,并将及时发布紧急更新补丁和升级推送通知。
+
+## 免责声明
+DCloud不因开发者使用本框架而承担任何法律责任。
+
+## 协议修订
+根据发展,DCloud可能会对本协议进行修改。修改时,DCloud会在产品或者网页中显著的位置发布相关信息以便及时通知到用户。如果您选择继续使用本框架,即表示您同意接受这些修改。
diff --git a/components/uni-clientdb/uni-clientdb.vue b/components/uni-clientdb/uni-clientdb.vue
new file mode 100644
index 0000000000000000000000000000000000000000..dea1ac45f8e7429659c4535f9aa46b69fbf639bf
--- /dev/null
+++ b/components/uni-clientdb/uni-clientdb.vue
@@ -0,0 +1,377 @@
+
+
+
+
+
+
+
diff --git a/components/uni-forms-item/uni-forms-item.vue b/components/uni-forms-item/uni-forms-item.vue
new file mode 100644
index 0000000000000000000000000000000000000000..cb914124702eca7103493b7c94b40468ea34cd2f
--- /dev/null
+++ b/components/uni-forms-item/uni-forms-item.vue
@@ -0,0 +1,437 @@
+
+
+
+
+
+
+ {{label}}
+ *
+
+
+
+
+
+
+ {{ showMsg === 'undertext' ? msg:'' }}
+
+
+
+
+
+
diff --git a/components/uni-forms/uni-forms.vue b/components/uni-forms/uni-forms.vue
new file mode 100644
index 0000000000000000000000000000000000000000..5065cde4473e562b48783cdca6022e2b4b5e283c
--- /dev/null
+++ b/components/uni-forms/uni-forms.vue
@@ -0,0 +1,420 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/components/uni-forms/validate.js b/components/uni-forms/validate.js
new file mode 100644
index 0000000000000000000000000000000000000000..e369abb5539aefff5b9e2d3696b51c73731735cd
--- /dev/null
+++ b/components/uni-forms/validate.js
@@ -0,0 +1,442 @@
+
+var pattern = {
+ email: /^\S+?@\S+?\.\S+?$/,
+ 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": 'number',
+ "bool": 'boolean',
+ "double": 'number',
+ "long": 'number',
+ "password": 'string'
+}
+
+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) {
+ var v
+ if (value instanceof Date) {
+ v = value;
+ } else {
+ v = new Date(value);
+ }
+ return typeof v.getTime === 'function' && typeof v.getMonth === 'function' && typeof v.getYear === 'function' && !isNaN(v.getTime());
+ },
+ timestamp(value) {
+ if (!this.integer(value) || Math.abs(value).toString().length > 16) {
+ return false
+ }
+
+ return this.date(value);
+ },
+ 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';
+ }
+}
+
+class RuleValidator {
+
+ constructor(message) {
+ this._message = message
+ }
+
+ async validateRule(key, value, data, allData) {
+ var result = null
+
+ let rules = key.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)
+
+ if (key.label !== undefined) {
+ Object.assign(rule, {
+ label: key.label
+ })
+ }
+
+ 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
+ }
+ }
+ }
+
+ 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) {
+ // TODO
+ var result = ''
+ if (rule.required) {
+ result = 'required'
+ } else if (rule.format) {
+ result = 'format'
+ } else if (rule.range) {
+ result = 'range'
+ } else if (rule.maximum || rule.minimum) {
+ result = 'rangeNumber'
+ } else if (rule.maxLength || rule.minLength) {
+ result = 'rangeLength'
+ } else if (rule.pattern) {
+ result = 'pattern'
+ }
+ 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'].min)
+ } else if (maximum !== undefined && max) {
+ return formatMessage(rule, rule.errorMessage || message['number'].max)
+ } 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'].min)
+ } else if (max !== undefined && val > max) {
+ return formatMessage(rule, rule.errorMessage || message['length'].max)
+ } 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;
+
+ if (customTypes.indexOf(format) > -1) {
+ if (!types[format](value)) {
+ return formatMessage(rule, rule.errorMessage || message.types[format]);
+ }
+ }
+
+ 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(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(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 ''
+ }
+ return [{
+ key: 'invalid',
+ errorMessage: SchemaValidator.message['defaultInvalid']
+ }]
+ }
+}
+
+function Message() {
+ return {
+ default: '验证错误',
+ defaultInvalid: '字段超出范围',
+ required: '{label}必填',
+ 'enum': '{label}超出范围',
+ whitespace: '{label}不能为空',
+ date: {
+ format: '{label}日期{value}格式无效',
+ parse: '{label}日期无法解析,{value}无效',
+ invalid: '{label}日期{value}无效'
+ },
+ types: {
+ string: '{label}类型无效',
+ array: '{label}类型无效',
+ object: '{label}类型无效',
+ number: '{label}类型无效',
+ date: '{label}类型无效',
+ boolean: '{label}类型无效',
+ integer: '{label}类型无效',
+ float: '{label}类型无效',
+ regexp: '{label}无效',
+ email: '{label}类型无效',
+ url: '{label}类型无效'
+ },
+ length: {
+ min: '{label}长度不能少于{minLength}',
+ max: '{label}长度不能超过{maxLength}',
+ range: '{label}必须介于{minLength}和{maxLength}之间'
+ },
+ number: {
+ min: '{label}不能小于{minimum}',
+ max: '{label}不能大于{maximum}',
+ range: '{label}必须介于{minimum}and{maximum}之间'
+ },
+ pattern: {
+ mismatch: '{label}格式不匹配'
+ }
+ };
+}
+
+
+SchemaValidator.message = new Message();
+
+export default SchemaValidator
diff --git a/components/uni-icons/icons.js b/components/uni-icons/icons.js
new file mode 100644
index 0000000000000000000000000000000000000000..60b733214dc67b78c1523ae31f878d937e5a830b
--- /dev/null
+++ b/components/uni-icons/icons.js
@@ -0,0 +1,132 @@
+export default {
+ "pulldown": "\ue588",
+ "refreshempty": "\ue461",
+ "back": "\ue471",
+ "forward": "\ue470",
+ "more": "\ue507",
+ "more-filled": "\ue537",
+ "scan": "\ue612",
+ "qq": "\ue264",
+ "weibo": "\ue260",
+ "weixin": "\ue261",
+ "pengyouquan": "\ue262",
+ "loop": "\ue565",
+ "refresh": "\ue407",
+ "refresh-filled": "\ue437",
+ "arrowthindown": "\ue585",
+ "arrowthinleft": "\ue586",
+ "arrowthinright": "\ue587",
+ "arrowthinup": "\ue584",
+ "undo-filled": "\ue7d6",
+ "undo": "\ue406",
+ "redo": "\ue405",
+ "redo-filled": "\ue7d9",
+ "bars": "\ue563",
+ "chatboxes": "\ue203",
+ "camera": "\ue301",
+ "chatboxes-filled": "\ue233",
+ "camera-filled": "\ue7ef",
+ "cart-filled": "\ue7f4",
+ "cart": "\ue7f5",
+ "checkbox-filled": "\ue442",
+ "checkbox": "\ue7fa",
+ "arrowleft": "\ue582",
+ "arrowdown": "\ue581",
+ "arrowright": "\ue583",
+ "smallcircle-filled": "\ue801",
+ "arrowup": "\ue580",
+ "circle": "\ue411",
+ "eye-filled": "\ue568",
+ "eye-slash-filled": "\ue822",
+ "eye-slash": "\ue823",
+ "eye": "\ue824",
+ "flag-filled": "\ue825",
+ "flag": "\ue508",
+ "gear-filled": "\ue532",
+ "reload": "\ue462",
+ "gear": "\ue502",
+ "hand-thumbsdown-filled": "\ue83b",
+ "hand-thumbsdown": "\ue83c",
+ "hand-thumbsup-filled": "\ue83d",
+ "heart-filled": "\ue83e",
+ "hand-thumbsup": "\ue83f",
+ "heart": "\ue840",
+ "home": "\ue500",
+ "info": "\ue504",
+ "home-filled": "\ue530",
+ "info-filled": "\ue534",
+ "circle-filled": "\ue441",
+ "chat-filled": "\ue847",
+ "chat": "\ue263",
+ "mail-open-filled": "\ue84d",
+ "email-filled": "\ue231",
+ "mail-open": "\ue84e",
+ "email": "\ue201",
+ "checkmarkempty": "\ue472",
+ "list": "\ue562",
+ "locked-filled": "\ue856",
+ "locked": "\ue506",
+ "map-filled": "\ue85c",
+ "map-pin": "\ue85e",
+ "map-pin-ellipse": "\ue864",
+ "map": "\ue364",
+ "minus-filled": "\ue440",
+ "mic-filled": "\ue332",
+ "minus": "\ue410",
+ "micoff": "\ue360",
+ "mic": "\ue302",
+ "clear": "\ue434",
+ "smallcircle": "\ue868",
+ "close": "\ue404",
+ "closeempty": "\ue460",
+ "paperclip": "\ue567",
+ "paperplane": "\ue503",
+ "paperplane-filled": "\ue86e",
+ "person-filled": "\ue131",
+ "contact-filled": "\ue130",
+ "person": "\ue101",
+ "contact": "\ue100",
+ "images-filled": "\ue87a",
+ "phone": "\ue200",
+ "images": "\ue87b",
+ "image": "\ue363",
+ "image-filled": "\ue877",
+ "location-filled": "\ue333",
+ "location": "\ue303",
+ "plus-filled": "\ue439",
+ "plus": "\ue409",
+ "plusempty": "\ue468",
+ "help-filled": "\ue535",
+ "help": "\ue505",
+ "navigate-filled": "\ue884",
+ "navigate": "\ue501",
+ "mic-slash-filled": "\ue892",
+ "search": "\ue466",
+ "settings": "\ue560",
+ "sound": "\ue590",
+ "sound-filled": "\ue8a1",
+ "spinner-cycle": "\ue465",
+ "download-filled": "\ue8a4",
+ "personadd-filled": "\ue132",
+ "videocam-filled": "\ue8af",
+ "personadd": "\ue102",
+ "upload": "\ue402",
+ "upload-filled": "\ue8b1",
+ "starhalf": "\ue463",
+ "star-filled": "\ue438",
+ "star": "\ue408",
+ "trash": "\ue401",
+ "phone-filled": "\ue230",
+ "compose": "\ue400",
+ "videocam": "\ue300",
+ "trash-filled": "\ue8dc",
+ "download": "\ue403",
+ "chatbubble-filled": "\ue232",
+ "chatbubble": "\ue202",
+ "cloud-download": "\ue8e4",
+ "cloud-upload-filled": "\ue8e5",
+ "cloud-upload": "\ue8e6",
+ "cloud-download-filled": "\ue8e9",
+ "headphones":"\ue8bf",
+ "shop":"\ue609"
+}
diff --git a/components/uni-icons/uni-icons.vue b/components/uni-icons/uni-icons.vue
new file mode 100644
index 0000000000000000000000000000000000000000..5f303e401f6c514a566964d119fc38a9d989ff79
--- /dev/null
+++ b/components/uni-icons/uni-icons.vue
@@ -0,0 +1,67 @@
+
+ {{icons[type]}}
+
+
+
+
+
diff --git a/components/uni-list-item/uni-list-item.vue b/components/uni-list-item/uni-list-item.vue
new file mode 100644
index 0000000000000000000000000000000000000000..7688e6447588283281ddb6178929ce64624969ca
--- /dev/null
+++ b/components/uni-list-item/uni-list-item.vue
@@ -0,0 +1,440 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ title }}
+ {{ note }}
+
+
+
+
+
+
+
+
+
+ |
+
+
+
+
+
+
diff --git a/components/uni-list/uni-list.vue b/components/uni-list/uni-list.vue
new file mode 100644
index 0000000000000000000000000000000000000000..d478729b27d0d456920434be21749a280fde6816
--- /dev/null
+++ b/components/uni-list/uni-list.vue
@@ -0,0 +1,106 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/uni-list/uni-refresh.vue b/components/uni-list/uni-refresh.vue
new file mode 100644
index 0000000000000000000000000000000000000000..3b4c5a230061935d31d8332663b8a511b5143759
--- /dev/null
+++ b/components/uni-list/uni-refresh.vue
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/uni-list/uni-refresh.wxs b/components/uni-list/uni-refresh.wxs
new file mode 100644
index 0000000000000000000000000000000000000000..818a6b721b1172073d91c1f6a456d2b54d772f77
--- /dev/null
+++ b/components/uni-list/uni-refresh.wxs
@@ -0,0 +1,87 @@
+var pullDown = {
+ threshold: 95,
+ maxHeight: 200,
+ callRefresh: 'onrefresh',
+ callPullingDown: 'onpullingdown',
+ refreshSelector: '.uni-refresh'
+};
+
+function ready(newValue, oldValue, ownerInstance, instance) {
+ var state = instance.getState()
+ state.canPullDown = newValue;
+ // console.log(newValue);
+}
+
+function touchStart(e, instance) {
+ var state = instance.getState();
+ state.refreshInstance = instance.selectComponent(pullDown.refreshSelector);
+ state.canPullDown = (state.refreshInstance != null && state.refreshInstance != undefined);
+ if (!state.canPullDown) {
+ return
+ }
+
+ // console.log("touchStart");
+
+ state.height = 0;
+ state.touchStartY = e.touches[0].pageY || e.changedTouches[0].pageY;
+ state.refreshInstance.setStyle({
+ 'height': 0
+ });
+ state.refreshInstance.callMethod("onchange", true);
+}
+
+function touchMove(e, ownerInstance) {
+ var instance = e.instance;
+ var state = instance.getState();
+ if (!state.canPullDown) {
+ return
+ }
+
+ var oldHeight = state.height;
+ var endY = e.touches[0].pageY || e.changedTouches[0].pageY;
+ var height = endY - state.touchStartY;
+ if (height > pullDown.maxHeight) {
+ return;
+ }
+
+ var refreshInstance = state.refreshInstance;
+ refreshInstance.setStyle({
+ 'height': height + 'px'
+ });
+
+ height = height < pullDown.maxHeight ? height : pullDown.maxHeight;
+ state.height = height;
+ refreshInstance.callMethod(pullDown.callPullingDown, {
+ height: height
+ });
+}
+
+function touchEnd(e, ownerInstance) {
+ var state = e.instance.getState();
+ if (!state.canPullDown) {
+ return
+ }
+
+ state.refreshInstance.callMethod("onchange", false);
+
+ var refreshInstance = state.refreshInstance;
+ if (state.height > pullDown.threshold) {
+ refreshInstance.callMethod(pullDown.callRefresh);
+ return;
+ }
+
+ refreshInstance.setStyle({
+ 'height': 0
+ });
+}
+
+function propObserver(newValue, oldValue, instance) {
+ pullDown = newValue;
+}
+
+module.exports = {
+ touchmove: touchMove,
+ touchstart: touchStart,
+ touchend: touchEnd,
+ propObserver: propObserver
+}
diff --git a/components/uni-load-more/config.json b/components/uni-load-more/config.json
new file mode 100644
index 0000000000000000000000000000000000000000..12c522641b6717913453389f00db86deb405e393
--- /dev/null
+++ b/components/uni-load-more/config.json
@@ -0,0 +1,10 @@
+{
+ "id": "29",
+ "name": "LoadMore",
+ "desc": "加载更多",
+ "url": "load-more",
+ "type": "功能组件",
+ "edition": "1.1.5",
+ "path": "https://ext.dcloud.net.cn/plugin?id=29",
+ "update_log": "- 新增 颜色大小等配置项"
+}
diff --git a/components/uni-load-more/readme.md b/components/uni-load-more/readme.md
new file mode 100644
index 0000000000000000000000000000000000000000..7dc215a8829fe2aaf4511907e283e3955b419646
--- /dev/null
+++ b/components/uni-load-more/readme.md
@@ -0,0 +1,48 @@
+### LoadMore 加载更多
+*已经支持在nvue页面中使用*
+
+用于列表中,做滚动加载使用,展示 loading 的各种状态,组件名:``uni-load-more``,代码块: uLoadMore。
+
+### 使用方式
+
+在 ``script`` 中引用组件
+
+```javascript
+import uniLoadMore from '@/components/uni-load-more/uni-load-more.vue'
+export default {
+ components: {uniLoadMore}
+}
+```
+
+在 ``template`` 中使用组件
+
+```html
+
+```
+
+
+### 属性说明
+
+|属性名 |类型 |默认值 |说明 |
+|--- |---- |--- |--- |
+|iconSize |Number |24 |指定图标大小 |
+|status |String |more |loading 的状态,可选值:more(loading前)、loading(loading中)、noMore(没有更多了) |
+|showIcon |Boolean|true |是否显示 loading 图标 |
+|iconType |String |auto |指定图标样式,可选值:snow(ios雪花加载样式)、circle(安卓环形加载样式)、auto(根据平台自动选择加载样式)。**注意:**APP-NVUE不支持此选项|
+|color |String |#777777 |图标和文字颜色 |
+|contentText |Object |`{contentdown: "上拉显示更多",contentrefresh: "正在加载...",contentnomore: "没有更多数据了"}` |各状态文字说明 |
+
+**说明**
+
+- `iconType`为`snow`时,在`APP-NVUE`平台不可设置大小,在非`APP-NVUE`平台不可设置颜色
+
+
+### 事件说明
+
+|事件名 |说明 |返回值 |
+|--- |--- |--- |
+|clickLoadMore |点击加载更多时触发 |e.detail={status:'loading'}|
+
+### 插件预览地址
+
+[https://uniapp.dcloud.io/h5/pages/extUI/load-more/load-more](https://uniapp.dcloud.io/h5/pages/extUI/load-more/load-more)
\ No newline at end of file
diff --git a/components/uni-load-more/uni-load-more.vue b/components/uni-load-more/uni-load-more.vue
new file mode 100644
index 0000000000000000000000000000000000000000..9430321c094ea87c7d7c078d4f8e44b9c516edae
--- /dev/null
+++ b/components/uni-load-more/uni-load-more.vue
@@ -0,0 +1,359 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ status === 'more' ? contentText.contentdown : status === 'loading' ? contentText.contentrefresh : contentText.contentnomore }}
+
+
+
+
+
+
diff --git a/components/uni-qrcode/uni-qrcode.vue b/components/uni-qrcode/uni-qrcode.vue
new file mode 100644
index 0000000000000000000000000000000000000000..a0ecadaaa23c2f1eb9635e1e5992ef8cd950644b
--- /dev/null
+++ b/components/uni-qrcode/uni-qrcode.vue
@@ -0,0 +1,196 @@
+
+
+
+
+
+
+
diff --git a/components/uni-section/config.json b/components/uni-section/config.json
new file mode 100644
index 0000000000000000000000000000000000000000..43d5d0103eea3dd7078bc4f66e9ad5f153cff89d
--- /dev/null
+++ b/components/uni-section/config.json
@@ -0,0 +1,12 @@
+{
+ "id": "99999",
+ "name": "Section",
+ "desc": "标题栏",
+ "edition": "0.0.1",
+ "url": "section",
+ "type": "布局组件",
+ "path": "https://ext.dcloud.net.cn/plugin?id=",
+ "hidden": true,
+ "test":true,
+ "update_log": []
+}
diff --git a/components/uni-section/readme.md b/components/uni-section/readme.md
new file mode 100644
index 0000000000000000000000000000000000000000..c5998fad378c059a39eb0cebff3bb58871a630f1
--- /dev/null
+++ b/components/uni-section/readme.md
@@ -0,0 +1,30 @@
+### Section 标题栏
+
+标题栏,用于显示标题,组件名:``uni-section``,代码块: uSection。
+
+### 使用方式
+
+在 ``script`` 中引用组件
+
+```javascript
+import uniSection from "@/components/uni-section/uni-section.vue"
+export default {
+ components: {uniSection}
+}
+```
+
+在 ``template`` 中使用组件
+
+```html
+
+
+
+```
+
+### 属性说明
+
+|属性名 |类型 |默认值 |说明 |
+|--- |---- |--- |--- |
+|type |String |- |标题装饰类型 ,可选值:line(竖线)、circle(圆形)|
+|title |String |- |主标题 |
+|sub-title |String |- |副标题 |
diff --git a/components/uni-section/uni-section.vue b/components/uni-section/uni-section.vue
new file mode 100644
index 0000000000000000000000000000000000000000..52a1567a2ba0b70336061a41ee7dedaa7d365d2e
--- /dev/null
+++ b/components/uni-section/uni-section.vue
@@ -0,0 +1,136 @@
+
+
+
+
+
+
+ {{ title }}
+ {{ subTitle }}
+
+
+
+
+
+
+
diff --git a/main.js b/main.js
new file mode 100644
index 0000000000000000000000000000000000000000..f9717dbe4b112f686b2d11775c84565cd5f70084
--- /dev/null
+++ b/main.js
@@ -0,0 +1,13 @@
+import Vue from 'vue'
+import App from './App'
+import store from './store/index.js';
+
+Vue.config.productionTip = false
+
+App.mpType = 'app'
+
+const app = new Vue({
+ ...App,
+ store
+})
+app.$mount()
diff --git a/manifest.json b/manifest.json
new file mode 100644
index 0000000000000000000000000000000000000000..b2681479f53b2e509b48a3bbfe6276ae1c4a71f6
--- /dev/null
+++ b/manifest.json
@@ -0,0 +1,63 @@
+{
+ "name" : "云端一体搜索模板",
+ "appid" : "__UNI__BC54A00",
+ "description": "",
+ "versionName": "1.0.0",
+ "versionCode": "100",
+ "transformPx": false,
+ "app-plus": {
+ "usingComponents": true,
+ "nvueCompiler": "uni-app",
+ "compilerVersion": 3,
+ "splashscreen": {
+ "alwaysShowBeforeRender": true,
+ "waiting": true,
+ "autoclose": true,
+ "delay": 0
+ },
+ "modules": {},
+ "distribute": {
+ "android": {
+ "permissions": [
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ]
+ },
+ "ios": {},
+ "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
+ }
+}
\ No newline at end of file
diff --git a/package.json b/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..29611437e99b9ea8f3199ebdc0770ade8175007f
--- /dev/null
+++ b/package.json
@@ -0,0 +1,80 @@
+{
+ "id": "uni-search-template",
+ "displayName": "云端一体搜索模板",
+ "version": "0.1.4",
+ "description": "uniCloud云端一体搜索模板,自带下拉候选、历史搜索、热搜。无需再开发服务器代码",
+ "keywords": [
+ "uniCloud",
+ "搜索",
+ "search",
+ "usearch",
+ "unisearch"
+ ],
+ "repository": "https://gitee.com/dcloud/uniCloud-search",
+ "engines": {
+ "HBuilderX": "^3.1.0"
+ },
+ "dcloudext": {
+ "category": [
+ "uniCloud",
+ "云端一体项目模板"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "无",
+ "data": "无",
+ "permissions": "无"
+ },
+ "npmurl": ""
+ },
+ "uni_modules": {
+ "dependencies": [],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "u",
+ "Android Browser": "u",
+ "微信浏览器(Android)": "u",
+ "QQ浏览器(Android)": "u"
+ },
+ "H5-pc": {
+ "Chrome": "u",
+ "IE": "u",
+ "Edge": "u",
+ "Firefox": "u",
+ "Safari": "u"
+ },
+ "小程序": {
+ "微信": "u",
+ "阿里": "u",
+ "百度": "u",
+ "字节跳动": "u",
+ "QQ": "u"
+ },
+ "快应用": {
+ "华为": "u",
+ "联盟": "u"
+ }
+ }
+ }
+ }
+}
diff --git a/pages.json b/pages.json
new file mode 100644
index 0000000000000000000000000000000000000000..acf7166c3b0d9969073addd317ec593385bd0d5c
--- /dev/null
+++ b/pages.json
@@ -0,0 +1,78 @@
+{
+ "pages": [{
+ "path": "pages/list/list",
+ "style": {
+ "enablePullDownRefresh": true,
+ "navigationBarTitleText": "列表"
+ }
+ }, {
+ "path":"pages/grid/grid",
+ "style":{
+ "navigationBarTitleText": "宫格"
+ }
+ }, {
+ "path": "pages/search/search",
+ "style": {
+ "navigationBarTitleText": ""
+ }
+ }, {
+ "path": "pages/list/detail",
+ "style": {
+ "app-plus": {
+ "titleNView": {
+ "buttons": [{
+ "type": "share"
+ }],
+ "type": "transparent"
+ }
+ },
+ "h5": {
+ "titleNView": {
+ "buttons": [],
+ "type": "transparent"
+ }
+ },
+ "navigationBarTitleText": "文章详情"
+ }
+
+ }, {
+ "path": "pages/ucenter/ucenter",
+ "style":{
+ "navigationBarTitleText": "个人中心",
+ "navigationBarBackgroundColor":"#2F85FC",
+ "navigationBarTextStyle":"white"
+ }
+ },{
+ "path":"pages/login/login",
+ "style":{
+ "navigationBarTitleText":"登录"
+ }
+ },{
+ "path":"pages/reg/reg",
+ "style":{
+ "navigationBarTitleText":"注册"
+ }
+ }],
+ "globalStyle": {
+ "navigationBarTextStyle": "black",
+ "navigationBarTitleText": "base-app",
+ "navigationBarBackgroundColor": "#F8F8F8",
+ "backgroundColor": "#F8F8F8"
+ },
+ "tabBar": {
+ "color": "#7A7E83",
+ "selectedColor": "#007AFF",
+ "borderStyle": "black",
+ "backgroundColor": "#F8F8F8",
+ "list": [{
+ "pagePath": "pages/list/list",
+ "text": "列表"
+ }, {
+ "pagePath": "pages/grid/grid",
+ "text": "宫格"
+ }, {
+ "pagePath": "pages/ucenter/ucenter",
+ "text": "我的"
+ }]
+ }
+}
diff --git a/pages/grid/banner.json b/pages/grid/banner.json
new file mode 100644
index 0000000000000000000000000000000000000000..359304a89361cc9e3fcbb8fe187a09742677117e
--- /dev/null
+++ b/pages/grid/banner.json
@@ -0,0 +1,34 @@
+{
+ "bannerfile":"https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/094a9dc0-50c0-11eb-b680-7980c8a877b8.jpg",
+ "open_url":"https://www.dcloud.io/",
+ "title":"内容 A",
+ "sort":0,
+ "category_id":"grid",
+ "status":true,
+ "description":"备注"
+}
+{
+ "bannerfile":"https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/094a9dc0-50c0-11eb-b680-7980c8a877b8.jpg",
+ "open_url":"https://www.dcloud.io/",
+ "title":"内容 A",
+ "sort":0,
+ "category_id":"grid",
+ "status":true,
+ "description":"备注"
+}{
+ "bannerfile":"https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/094a9dc0-50c0-11eb-b680-7980c8a877b8.jpg",
+ "open_url":"https://www.dcloud.io/",
+ "title":"内容 A",
+ "sort":0,
+ "category_id":"grid",
+ "status":true,
+ "description":"备注"
+}{
+ "bannerfile":"https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/094a9dc0-50c0-11eb-b680-7980c8a877b8.jpg",
+ "open_url":"https://www.dcloud.io/",
+ "title":"内容 A",
+ "sort":0,
+ "category_id":"grid",
+ "status":true,
+ "description":"备注"
+}
\ No newline at end of file
diff --git a/pages/grid/grid.nvue b/pages/grid/grid.nvue
new file mode 100644
index 0000000000000000000000000000000000000000..c8c9fbd0eca59e1a65e4108b40436b22177d411d
--- /dev/null
+++ b/pages/grid/grid.nvue
@@ -0,0 +1,313 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.text }}
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/index/index.vue b/pages/index/index.vue
new file mode 100644
index 0000000000000000000000000000000000000000..769731664a5e1becd66fa18db82f634965b03f61
--- /dev/null
+++ b/pages/index/index.vue
@@ -0,0 +1,29 @@
+
+
+
+ 本项目已包含uni ui组件,无需import和注册,可直接使用。在代码区键入字母u,即可通过代码助手列出所有可用组件。光标置于组件名称处按F1,即可查看组件文档。
+ 详见:
+
+
+
+
+
+
+
diff --git a/pages/invite-reg/invite-reg.vue b/pages/invite-reg/invite-reg.vue
new file mode 100644
index 0000000000000000000000000000000000000000..f8d67f1401799f1cc021be345765404e916cff12
--- /dev/null
+++ b/pages/invite-reg/invite-reg.vue
@@ -0,0 +1,255 @@
+
+
+
+
+
+ 手机号:
+
+
+
+ 验证码:
+
+ {{codeDuration ? codeDuration + 's' : '发送验证码' }}
+
+
+ 邀请码:
+
+
+
+ 密码:
+
+
+
+ 确认密码:
+
+
+
+
+
+
+
+ 已有账号下载APP登录
+
+
+
+
+
+
+
diff --git a/pages/invite/invite.vue b/pages/invite/invite.vue
new file mode 100644
index 0000000000000000000000000000000000000000..6230928d95102f3d1664e1198f3797260d7920d5
--- /dev/null
+++ b/pages/invite/invite.vue
@@ -0,0 +1,184 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/invited-user/invited-user.vue b/pages/invited-user/invited-user.vue
new file mode 100644
index 0000000000000000000000000000000000000000..c5e2657bb03ff7a0b0c029c42ceec4d2d90d8eb0
--- /dev/null
+++ b/pages/invited-user/invited-user.vue
@@ -0,0 +1,149 @@
+
+
+
+
+ 我邀请的用户
+
+ {{item}}级下线
+
+
+
+ {{item.username || '新用户'}}
+ {{item.mobile}}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/list-news/list-news.vue b/pages/list-news/list-news.vue
new file mode 100644
index 0000000000000000000000000000000000000000..cdd5394ba56702e97f0bda6e59d8c0efbfd899fa
--- /dev/null
+++ b/pages/list-news/list-news.vue
@@ -0,0 +1,169 @@
+
+
+
+
+ 为您更新了10条最新新闻动态
+
+
+
+
+
+
+
+ {{item.title}}
+
+
+
+
+
+
+
+
+
+ {{item.excerpt}}
+ {{ item.origin }} {{ item.last_modify_date | beforTime }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/list/detail.vue b/pages/list/detail.vue
new file mode 100644
index 0000000000000000000000000000000000000000..1b0bc53347ec5da78d68a83091f1c46e453734b1
--- /dev/null
+++ b/pages/list/detail.vue
@@ -0,0 +1,286 @@
+
+
+
+
+
+ {{title}}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{data.excerpt}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/list/list.nvue b/pages/list/list.nvue
new file mode 100644
index 0000000000000000000000000000000000000000..119903828b96a60c1475658660e4029eccc57f46
--- /dev/null
+++ b/pages/list/list.nvue
@@ -0,0 +1,321 @@
+
+
+
+
+
+
+
+
+
+ 为您更新了10条内容
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{item.title}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/login/login.vue b/pages/login/login.vue
new file mode 100644
index 0000000000000000000000000000000000000000..6c516c7139a95975a5241204b75702a3a6a5b1c7
--- /dev/null
+++ b/pages/login/login.vue
@@ -0,0 +1,654 @@
+
+
+
+ {{item}}
+
+
+
+ 手机:
+
+
+
+ 验证码:
+
+ {{codeDuration ? codeDuration + 's' : '发送验证码' }}
+
+
+
+
+ 账号:
+
+
+
+ 密码:
+
+
+
+ 验证码:
+
+
+
+
+
+
+
+
+
+
+
+ 注册账号
+
+
+
+
+
+
+
+
+
+
+ 暂无法使用苹果登录,请查阅
+ Apple登录集成教程
+
+
+
+
+
+
+
+
diff --git a/pages/main/main.vue b/pages/main/main.vue
new file mode 100644
index 0000000000000000000000000000000000000000..5804203e48c9848bf6fc1131e9278e5f9dc53d02
--- /dev/null
+++ b/pages/main/main.vue
@@ -0,0 +1,134 @@
+
+
+
+
+ 您好 {{userName}},您已成功登录。
+
+
+ 这是 uni-app 带登录模板的示例App首页。
+ 在 “我的” 中点击 “退出” 可以 “注销当前账户”
+
+
+
+
+ 您好 游客。
+
+
+ 这是 uni-app 带登录模板的示例App首页。
+ 在 “我的” 中点击 “登录” 可以 “登录您的账户”
+
+
+
+
+
+
+
+
diff --git a/pages/pwd/pwd.vue b/pages/pwd/pwd.vue
new file mode 100644
index 0000000000000000000000000000000000000000..1bead5044eb786d6adfbaf8981c00949634f5b2d
--- /dev/null
+++ b/pages/pwd/pwd.vue
@@ -0,0 +1,52 @@
+
+
+
+
+ 邮箱:
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/pwd/update-password.vue b/pages/pwd/update-password.vue
new file mode 100644
index 0000000000000000000000000000000000000000..39540199ffebf0e17294c78aab1c5e1b4160e4dd
--- /dev/null
+++ b/pages/pwd/update-password.vue
@@ -0,0 +1,261 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/reg/reg.vue b/pages/reg/reg.vue
new file mode 100644
index 0000000000000000000000000000000000000000..25ee5e41f7234bddc9ab821565a6b961287307d2
--- /dev/null
+++ b/pages/reg/reg.vue
@@ -0,0 +1,109 @@
+
+
+
+
+ 账号:
+
+
+
+ 密码:
+
+
+
+ 确认密码:
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/search/search.nvue b/pages/search/search.nvue
new file mode 100644
index 0000000000000000000000000000000000000000..2e9193b71c65c852eb4b0839eb7f917ddb0466a4
--- /dev/null
+++ b/pages/search/search.nvue
@@ -0,0 +1,496 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{word}}
+
+
+
+
+
+
+
+
+
+ 正在加载...
+
+
+ {{error.message}}
+
+ {{word.content}}
+
+
+
+ 当前搜索发现已隐藏
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/ucenter/ucenter.nvue b/pages/ucenter/ucenter.nvue
new file mode 100644
index 0000000000000000000000000000000000000000..2f098c250ebd112cd62c09c1e04ded7fee716bbb
--- /dev/null
+++ b/pages/ucenter/ucenter.nvue
@@ -0,0 +1,182 @@
+
+
+
+
+
+ Hi,{{login ? userInfo.username : '您未登录'}}
+
+
+
+
+
+
+
+ |
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pages/uni-feedback/uni-feedback.nvue b/pages/uni-feedback/uni-feedback.nvue
new file mode 100644
index 0000000000000000000000000000000000000000..a02203c6b86b7241bd86d6c064215a315606b8b8
--- /dev/null
+++ b/pages/uni-feedback/uni-feedback.nvue
@@ -0,0 +1,235 @@
+
+
+
+ 问题和意见
+ 快速键入
+
+
+ 图片(选填,提供问题截图,总大小10M以下)
+
+
+
+ 点击预览图片
+ {{ imageList.length }}/5
+
+
+
+
+
+
+ x
+
+
+
+
+
+
+
+ QQ/邮箱
+
+
+ 应用评分
+
+
+
+
+
+ 用户反馈的结果可在app打包后于DCloud开发者中心查看
+
+
+
+
+
+
diff --git a/pages/user/user.vue b/pages/user/user.vue
new file mode 100644
index 0000000000000000000000000000000000000000..549d277d0792b04d37927deed12a62acb1acb071
--- /dev/null
+++ b/pages/user/user.vue
@@ -0,0 +1,279 @@
+
+
+
+
+
+
+ Hi,{{hasLogin ? userName : '您未登录'}}
+
+
+
+
+
+
+ 修改密码
+
+
+
+
+
+ 邀请好友
+
+
+
+
+
+ 新消息通知
+
+
+
+
+
+
+ 帮助与反馈
+
+
+
+
+ 服务条款及隐私
+
+
+
+
+
+
+ 关于应用
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/static/api.png b/static/api.png
new file mode 100644
index 0000000000000000000000000000000000000000..58f93e13a4eabd82f830e125521d315f8332cbe3
Binary files /dev/null and b/static/api.png differ
diff --git a/static/apiHL.png b/static/apiHL.png
new file mode 100644
index 0000000000000000000000000000000000000000..f8cbd7d244729603bbaa68ad0981cbf450accc29
Binary files /dev/null and b/static/apiHL.png differ
diff --git a/static/c1.png b/static/c1.png
new file mode 100644
index 0000000000000000000000000000000000000000..9d38fdc45f54393919608143278902961ebfc03e
Binary files /dev/null and b/static/c1.png differ
diff --git a/static/c2.png b/static/c2.png
new file mode 100644
index 0000000000000000000000000000000000000000..ce956d76c7547cc90469647a2a1f6cd34731dbb7
Binary files /dev/null and b/static/c2.png differ
diff --git a/static/c3.png b/static/c3.png
new file mode 100644
index 0000000000000000000000000000000000000000..216202ad01c5d093a15c247cf791bf66759cf54d
Binary files /dev/null and b/static/c3.png differ
diff --git a/static/c4.png b/static/c4.png
new file mode 100644
index 0000000000000000000000000000000000000000..fb8b4770c323cc87544a502c4efcd9792ec6047a
Binary files /dev/null and b/static/c4.png differ
diff --git a/static/c5.png b/static/c5.png
new file mode 100644
index 0000000000000000000000000000000000000000..310bfb123ba811240a23883c589557cced22af97
Binary files /dev/null and b/static/c5.png differ
diff --git a/static/c6.png b/static/c6.png
new file mode 100644
index 0000000000000000000000000000000000000000..c3c45d8814b2657a1c603b1a44c8207da134cb40
Binary files /dev/null and b/static/c6.png differ
diff --git a/static/c7.png b/static/c7.png
new file mode 100644
index 0000000000000000000000000000000000000000..a1e73908c282c8ce053a037a9b0d0ff2bcdb5f28
Binary files /dev/null and b/static/c7.png differ
diff --git a/static/c8.png b/static/c8.png
new file mode 100644
index 0000000000000000000000000000000000000000..c32633c0b399d119fe940b19fb48ee0efd986ca1
Binary files /dev/null and b/static/c8.png differ
diff --git a/static/c9.png b/static/c9.png
new file mode 100644
index 0000000000000000000000000000000000000000..51bcf6a1b39ff986d5e347f16a34c8d3e5dfccec
Binary files /dev/null and b/static/c9.png differ
diff --git a/static/component.png b/static/component.png
new file mode 100644
index 0000000000000000000000000000000000000000..fbb116d59b9cbabc51476ce2ac48eb1fd15297da
Binary files /dev/null and b/static/component.png differ
diff --git a/static/componentHL.png b/static/componentHL.png
new file mode 100644
index 0000000000000000000000000000000000000000..31f83a029feca7066cbf6139a9524fcbf508582c
Binary files /dev/null and b/static/componentHL.png differ
diff --git a/static/img/apple.png b/static/img/apple.png
new file mode 100644
index 0000000000000000000000000000000000000000..5fd31c621254aff8bfb08f497ff8cc04a063da5e
Binary files /dev/null and b/static/img/apple.png differ
diff --git a/static/img/home.png b/static/img/home.png
new file mode 100644
index 0000000000000000000000000000000000000000..3d9412aaf1dc1d5ad9823a875a4cd55a8cfa290b
Binary files /dev/null and b/static/img/home.png differ
diff --git a/static/img/homeHL.png b/static/img/homeHL.png
new file mode 100644
index 0000000000000000000000000000000000000000..553bedf0f80d328e1b36eab2c9e0ccc8df252423
Binary files /dev/null and b/static/img/homeHL.png differ
diff --git a/static/img/logo.png b/static/img/logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..6cbdbb2167ba2fe7400ad42c5491b78e60886a8e
Binary files /dev/null and b/static/img/logo.png differ
diff --git a/static/img/more.png b/static/img/more.png
new file mode 100644
index 0000000000000000000000000000000000000000..cdfe39223017f5ed522e36b30d80f22f80c9bf8e
Binary files /dev/null and b/static/img/more.png differ
diff --git a/static/img/qq.png b/static/img/qq.png
new file mode 100644
index 0000000000000000000000000000000000000000..961f83d0791b7a5fcf7aec1c69c4ac7e8807f500
Binary files /dev/null and b/static/img/qq.png differ
diff --git a/static/img/sinaweibo.png b/static/img/sinaweibo.png
new file mode 100644
index 0000000000000000000000000000000000000000..16a3a1b851ecc06d949dc657e035b6208fd59716
Binary files /dev/null and b/static/img/sinaweibo.png differ
diff --git a/static/img/univerify.png b/static/img/univerify.png
new file mode 100644
index 0000000000000000000000000000000000000000..37bc8f202634ba50e03fd016cd4f40f4a1f5b47d
Binary files /dev/null and b/static/img/univerify.png differ
diff --git a/static/img/user.png b/static/img/user.png
new file mode 100644
index 0000000000000000000000000000000000000000..aa2d3b43787c35c051abcfae87b2555bf21fa0e6
Binary files /dev/null and b/static/img/user.png differ
diff --git a/static/img/userHL.png b/static/img/userHL.png
new file mode 100644
index 0000000000000000000000000000000000000000..ffcb4fc0dbb112b9e13867b61e64f4ea3a65fe94
Binary files /dev/null and b/static/img/userHL.png differ
diff --git a/static/img/weixin.png b/static/img/weixin.png
new file mode 100644
index 0000000000000000000000000000000000000000..c6f6076260e3688aaefaa3ce1ebe3ee3498d3ef9
Binary files /dev/null and b/static/img/weixin.png differ
diff --git a/static/logo.png b/static/logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..b5771e209bb677e2ebd5ff766ad5ee11790f305a
Binary files /dev/null and b/static/logo.png differ
diff --git a/static/template.png b/static/template.png
new file mode 100644
index 0000000000000000000000000000000000000000..409ec9b92b041d306115335da13dfdc0f4ac257a
Binary files /dev/null and b/static/template.png differ
diff --git a/static/templateHL.png b/static/templateHL.png
new file mode 100644
index 0000000000000000000000000000000000000000..4018448570ec27da1d0ab57496f094ffe028eab0
Binary files /dev/null and b/static/templateHL.png differ
diff --git a/static/text-icon.ttf b/static/text-icon.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..69772689e05fb74224fdae19840fc21660c13520
Binary files /dev/null and b/static/text-icon.ttf differ
diff --git a/static/uni-center/logo.png b/static/uni-center/logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..6cbdbb2167ba2fe7400ad42c5491b78e60886a8e
Binary files /dev/null and b/static/uni-center/logo.png differ
diff --git a/static/uni.png b/static/uni.png
new file mode 100644
index 0000000000000000000000000000000000000000..8e3a80f4b84ca9dfad7bc1ab724810a1b3be3ba8
Binary files /dev/null and b/static/uni.png differ
diff --git a/static/uni.ttf b/static/uni.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..60a1968d08cc6056c70b5402b2effac43c6f96a3
Binary files /dev/null and b/static/uni.ttf differ
diff --git a/store/index.js b/store/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..883f933f785d6628f1ef21095ed4dce94d83d2ff
--- /dev/null
+++ b/store/index.js
@@ -0,0 +1,20 @@
+import Vue from 'vue'
+import Vuex from 'vuex'
+
+const modulesFiles = require.context('./modules', false, /\.js$/)
+
+const modules = modulesFiles.keys().reduce((modules, modulePath) => {
+ const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
+ const value = modulesFiles(modulePath)
+ modules[moduleName] = value.default
+ modules[moduleName]['namespaced'] = true;
+ return modules
+}, {})
+Vue.use(Vuex)
+
+const store = new Vuex.Store({
+ modules,
+ strict: true
+})
+
+export default store
\ No newline at end of file
diff --git a/store/modules/user.js b/store/modules/user.js
new file mode 100644
index 0000000000000000000000000000000000000000..30bf1765d7a7a4407927053ad83e1bea43395635
--- /dev/null
+++ b/store/modules/user.js
@@ -0,0 +1,42 @@
+// 上次启动时的用户信息
+let userHistory = uni.getStorageSync('userInfo') || null;
+
+let state = {
+ /**
+ * 是否需要强制登录
+ */
+ forcedLogin: false,
+ hasLogin: Boolean(userHistory),
+ info: userHistory
+ },
+ getters = {
+ info(state) {
+ return state.info;
+ },
+ hasLogin(state){
+ return state.hasLogin;
+ }
+ },
+ mutations = {
+ login(state, info) {
+ state.info = info;
+ state.hasLogin = true;
+ uni.setStorageSync('userInfo', info);
+ },
+ logout(state) {
+ state.info = null;
+ state.hasLogin = false;
+ uni.setStorageSync('userInfo', null);
+ }
+ },
+ actions = {
+
+ }
+
+
+export default {
+ state,
+ getters,
+ mutations,
+ actions
+}
diff --git a/uni.scss b/uni.scss
new file mode 100644
index 0000000000000000000000000000000000000000..845142dd5eb11438513b665ccb5f83d4f08b8fb5
--- /dev/null
+++ b/uni.scss
@@ -0,0 +1,76 @@
+/**
+ * 这里是uni-app内置的常用样式变量
+ *
+ * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
+ * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
+ *
+ */
+
+/**
+ * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
+ *
+ * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 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:24rpx;
+$uni-font-size-base:28rpx;
+$uni-font-size-lg:32rpx;
+
+/* 图片尺寸 */
+$uni-img-size-sm:40rpx;
+$uni-img-size-base:52rpx;
+$uni-img-size-lg:80rpx;
+
+/* Border Radius */
+$uni-border-radius-sm: 4rpx;
+$uni-border-radius-base: 6rpx;
+$uni-border-radius-lg: 12rpx;
+$uni-border-radius-circle: 50%;
+
+/* 水平间距 */
+$uni-spacing-row-sm: 10px;
+$uni-spacing-row-base: 20rpx;
+$uni-spacing-row-lg: 30rpx;
+
+/* 垂直间距 */
+$uni-spacing-col-sm: 8rpx;
+$uni-spacing-col-base: 16rpx;
+$uni-spacing-col-lg: 24rpx;
+
+/* 透明度 */
+$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
+
+/* 文章场景相关 */
+$uni-color-title: #2C405A; // 文章标题颜色
+$uni-font-size-title:40rpx;
+$uni-color-subtitle: #555555; // 二级标题颜色
+$uni-font-size-subtitle:36rpx;
+$uni-color-paragraph: #3F536E; // 文章段落颜色
+$uni-font-size-paragraph:30rpx;
\ No newline at end of file
diff --git a/uniCloud-aliyun/cloudfunctions/uni-analyse-searchhot/index.js b/uniCloud-aliyun/cloudfunctions/uni-analyse-searchhot/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..1f16dc2fe70cfe7a79f8ce4dece68d49ccf51947
--- /dev/null
+++ b/uniCloud-aliyun/cloudfunctions/uni-analyse-searchhot/index.js
@@ -0,0 +1,49 @@
+'use strict';
+exports.main = async (event, context) => {
+ /**
+ * 根据搜索记录,设定时间间隔来归纳出热搜数据并存储在热搜表中
+ */
+ const SEARCHHOT = 'opendb-search-hot'; // 热搜数据库名称
+ const SEARCHLOG = 'opendb-search-log'; // 搜索记录数据库名称
+ const SEARCHLOG_timeZone = 604800000; // 归纳搜索记录时间间隔,毫秒数,默认为最近7天
+ const SEARCHHOT_size = 10; // 热搜条数
+
+ const DB = uniCloud.database();
+ const DBCmd = DB.command;
+ const $ = DB.command.aggregate;
+ const SEARCHHOT_db = DB.collection(SEARCHHOT);
+ const SEARCHLOG_db = DB.collection(SEARCHLOG);
+ const timeEnd = Date.now() - SEARCHLOG_timeZone;
+
+ let {
+ data: searchHotData
+ } = await SEARCHLOG_db
+ .aggregate()
+ .match({
+ create_date: DBCmd.gt(timeEnd)
+ })
+ .group({
+ _id: {
+ 'content': '$content',
+ },
+ count: $.sum(1)
+ })
+ .replaceRoot({
+ newRoot: $.mergeObjects(['$_id', '$$ROOT'])
+ })
+ .project({
+ _id: false
+ })
+ .sort({
+ count: -1
+ })
+ .end();
+
+ let now = Date.now();
+ searchHotData.map(item => {
+ item.create_date = now;
+ return item;
+ }).slice(0, SEARCHHOT_size);
+ // searchHotData = searchHotData.sort((a, b) => b.count - a.count).slice(0, SEARCHHOT_size);
+ return searchHotData.length ? await SEARCHHOT_db.add(searchHotData) : ''
+};
diff --git a/uniCloud-aliyun/cloudfunctions/uni-analyse-searchhot/package.json b/uniCloud-aliyun/cloudfunctions/uni-analyse-searchhot/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..6005add8563ac879001ba7f5fdeb304768ed8486
--- /dev/null
+++ b/uniCloud-aliyun/cloudfunctions/uni-analyse-searchhot/package.json
@@ -0,0 +1,14 @@
+{
+ "name": "uni-analyse-searchhot",
+ "version": "1.0.0",
+ "description": "定时归纳热搜",
+ "main": "index.js",
+ "dependencies": {},
+ "cloudfunction-config": {
+ "triggers": [{
+ "name": "analyse-searchHot",
+ "type": "timer",
+ "config": "0 0 */2 * * * *"
+ }]
+ }
+}
diff --git a/uniCloud-aliyun/cloudfunctions/user-center/index.js b/uniCloud-aliyun/cloudfunctions/user-center/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..fc48912158752a1e651f13a2d73db68cb1355768
--- /dev/null
+++ b/uniCloud-aliyun/cloudfunctions/user-center/index.js
@@ -0,0 +1,210 @@
+'use strict';
+
+const uniID = require('uni-id')
+const uniCaptcha = require('uni-captcha')
+const db = uniCloud.database()
+const dbCmd = db.command
+
+exports.main = async (event, context) => {
+ let params = event.params || {}
+
+ // 登录记录
+ const loginLog = async (res = {}, type = 'login') => {
+ const now = Date.now()
+ const uniIdLogCollection = db.collection('uni-id-log')
+ let logData = {
+ deviceId: params.deviceId || context.DEVICEID,
+ ip: params.ip || context.CLIENTIP,
+ type,
+ ua: context.CLIENTUA,
+ create_date: now
+ };
+
+ Object.assign(logData,
+ res.code === 0 ? {
+ user_id: res.uid,
+ state: 1
+ } : {
+ state: 0
+ })
+
+ return uniIdLogCollection.add(logData)
+ }
+
+ const getNeedCaptcha = async () => {
+ const now = Date.now()
+ // 查询是否在 {2小时} 内 {前2条} 有 {登录失败} 数据,来确定是否需要验证码
+ const recordSize = 2;
+ const recordDate = 120 * 60 * 1000;
+
+ const uniIdLogCollection = db.collection('uni-id-log')
+ let recentRecord = await uniIdLogCollection.where({
+ deviceId: params.deviceId || context.DEVICEID,
+ create_date: dbCmd.gt(now - recordDate),
+ type: 'login'
+ })
+ .orderBy('create_date', 'desc')
+ .limit(recordSize)
+ .get();
+
+ return recentRecord.data.filter(item => item.state === 0).length === recordSize;
+ }
+
+ //event为客户端上传的参数
+ console.log('event : ' + event)
+
+ let payload = {}
+ let noCheckAction = [
+ 'register', 'loginByWeixin', 'checkToken',
+ 'login', 'logout', 'sendSmsCode',
+ 'loginBySms', 'inviteLogin', 'loginByUniverify',
+ 'loginByApple', 'createCaptcha', 'verifyCaptcha',
+ 'refreshCaptcha'
+ ]
+
+ if (noCheckAction.indexOf(event.action) === -1) {
+ if (!event.uniIdToken) {
+ return {
+ code: 403,
+ msg: '缺少token'
+ }
+ }
+ payload = await uniID.checkToken(event.uniIdToken)
+ if (payload.code && payload.code > 0) {
+ return payload
+ }
+ params.uid = payload.uid
+ }
+
+ let res = {}
+
+ switch (event.action) {
+ case 'register':
+ res = await uniID.register(params);
+ break;
+ case 'login':
+ let passed = false;
+ let needCaptcha = await getNeedCaptcha();
+
+ if (needCaptcha) {
+ res = await uniCaptcha.verify(params)
+ if (res.code === 0) passed = true;
+ }
+
+ if (!needCaptcha || passed) {
+ res = await uniID.login(params);
+ await loginLog(res);
+ needCaptcha = await getNeedCaptcha();
+ }
+
+ res.needCaptcha = needCaptcha;
+ break;
+ case 'loginByWeixin':
+ res = await uniID.loginByWeixin(params);
+ loginLog(res)
+ break;
+ case 'checkToken':
+ res = await uniID.checkToken(event.uniIdToken);
+ break;
+ case 'logout':
+ res = await uniID.logout(event.uniIdToken)
+ break;
+ case 'sendSmsCode':
+ // 简单限制一下客户端调用频率
+ const ipLimit = await db.collection('uni-verify').where({
+ ip: context.CLIENTIP,
+ created_at: dbCmd.gt(Date.now() - 60000)
+ }).get()
+ if (ipLimit.data.length > 0) {
+ return {
+ code: 429,
+ msg: '请求过于频繁'
+ }
+ }
+ const templateId = '' // 替换为自己申请的模板id
+ if (!templateId) {
+ return {
+ code: 500,
+ msg: 'sendSmsCode需要传入自己的templateId,参考https://uniapp.dcloud.net.cn/uniCloud/uni-id?id=sendsmscode'
+ }
+ }
+ const randomStr = '00000' + Math.floor(Math.random() * 1000000)
+ const code = randomStr.substring(randomStr.length - 6)
+ res = await uniID.sendSmsCode({
+ mobile: params.mobile,
+ code,
+ type: params.type,
+ templateId
+ })
+ break;
+ case 'loginBySms':
+ if (!params.code) {
+ return {
+ code: 500,
+ msg: '请填写验证码'
+ }
+ }
+ if (!/^1\d{10}$/.test(params.mobile)) {
+ return {
+ code: 500,
+ msg: '手机号码填写错误'
+ }
+ }
+ res = await uniID.loginBySms(params)
+ loginLog(res)
+ break;
+ case 'inviteLogin':
+ if (!params.code) {
+ return {
+ code: 500,
+ msg: '请填写验证码'
+ }
+ }
+ res = await uniID.loginBySms({
+ ...params,
+ type: 'register'
+ })
+ break;
+ case 'getInviteCode':
+ res = await uniID.getUserInfo({
+ uid: params.uid,
+ field: ['my_invite_code']
+ })
+ if (res.code === 0) {
+ res.myInviteCode = res.userInfo.my_invite_code
+ delete res.userInfo
+ }
+ break;
+ case 'getInvitedUser':
+ res = await uniID.getInvitedUser(params)
+ break;
+ case 'loginByUniverify':
+ res = await uniID.loginByUniverify(params)
+ break;
+ case 'loginByApple':
+ res = await uniID.loginByApple(params)
+ loginLog(res)
+ break;
+ case 'updatePwd':
+ res = await uniID.updatePwd({
+ uid: params.uid,
+ ...params
+ })
+ break;
+ case 'createCaptcha':
+ res = await uniCaptcha.create(params)
+ break;
+ case 'refreshCaptcha':
+ res = await uniCaptcha.refresh(params)
+ break;
+ default:
+ res = {
+ code: 403,
+ msg: '非法访问'
+ }
+ break;
+ }
+
+ //返回数据给客户端
+ return res
+};
diff --git a/uniCloud-aliyun/cloudfunctions/user-center/package-lock.json b/uniCloud-aliyun/cloudfunctions/user-center/package-lock.json
new file mode 100644
index 0000000000000000000000000000000000000000..1dbe97bd484b02b02874e343d97a59fbc6145185
--- /dev/null
+++ b/uniCloud-aliyun/cloudfunctions/user-center/package-lock.json
@@ -0,0 +1,14 @@
+{
+ "name": "user-center",
+ "version": "1.0.0",
+ "lockfileVersion": 1,
+ "requires": true,
+ "dependencies": {
+ "uni-captcha": {
+ "version": "file:../../../uni_modules/uni-captcha/uniCloud/cloudfunctions/common/uni-captcha"
+ },
+ "uni-id": {
+ "version": "file:../../../uni_modules/uni-id/uniCloud/cloudfunctions/common/uni-id"
+ }
+ }
+}
diff --git a/uniCloud-aliyun/cloudfunctions/user-center/package.json b/uniCloud-aliyun/cloudfunctions/user-center/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..7b569dc56655f160526dc2cc2d31c20849b0f6b4
--- /dev/null
+++ b/uniCloud-aliyun/cloudfunctions/user-center/package.json
@@ -0,0 +1,15 @@
+{
+ "name": "user-center",
+ "version": "1.0.0",
+ "description": "",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "author": "",
+ "license": "ISC",
+ "dependencies": {
+ "uni-captcha": "file:../../../uni_modules/uni-captcha/uniCloud/cloudfunctions/common/uni-captcha",
+ "uni-id": "file:../../../uni_modules/uni-id/uniCloud/cloudfunctions/common/uni-id"
+ }
+}
diff --git "a/uniCloud-aliyun/database/JQL\346\237\245\350\257\242.jql" "b/uniCloud-aliyun/database/JQL\346\237\245\350\257\242.jql"
new file mode 100644
index 0000000000000000000000000000000000000000..680e8987bb99075ab51c0044f4fd659659f877a2
--- /dev/null
+++ "b/uniCloud-aliyun/database/JQL\346\237\245\350\257\242.jql"
@@ -0,0 +1,9 @@
+// 本查询文件用于,使用JQL语法查询项目关联的uniCloud空间的数据库,方便开发调试
+// 选中查询代码,点击工具栏上的运行按钮或者【F5】运行查询语句
+// 如果没有选中代码,直接运行,则会执行整个文档的JQL语句。但如果文档中存在多条JQL语句,只有最后一条语句生效
+// 本文档支持简单js,但不支持clientDB的action
+// 数据库查询有最大返回条数限制,详见:https://uniapp.dcloud.net.cn/uniCloud/cf-database?id=limit
+// 详细JQL语法,请参考 https://uniapp.dcloud.net.cn/uniCloud/clientdb?id=jsquery
+
+// 下面示例查询uni-id-users表的所有数据
+db.collection('uni-id-users').get();
diff --git a/uniCloud-aliyun/database/db_init.json b/uniCloud-aliyun/database/db_init.json
new file mode 100644
index 0000000000000000000000000000000000000000..b62093a4d58efc81d8a19f19d0dd0bf31b7aae33
--- /dev/null
+++ b/uniCloud-aliyun/database/db_init.json
@@ -0,0 +1,163 @@
+// 在本文件中可配置云数据库初始化,数据格式见:https://uniapp.dcloud.io/uniCloud/cf-database?id=db_init
+// 编写完毕后对本文件点右键,可按配置规则创建表和添加数据
+{
+ "opendb-news-articles-detail": {
+ "data": [
+ {
+ "article_status": 1,
+ "author_avatar": "https://pic.36krcnd.com/avatar/201804/11034847/2w2w8ix0d1x98939.jpg!120",
+ "author_name": "土土土槽",
+ "category_id": "223",
+ "comment_count": 1204,
+ "comment_status": 0,
+ "content": "编者按:本文来自微信公众号“土土土槽”(ID:xtutux6),作者:林安,36氪经授权发布。
大家好,我是林安。今天想跟你们聊一聊自由职业者的五险一金问题。
因为这个是想做自由职业的朋友问我最多的问题,也是自由职业初期必须思考的问题,所以今天就展开给大家讲讲。
在成为自由职业者以前,我没有任何一次裸辞经历,基本都是找好下家才跳槽,所以你应该看得出来,我不是一名“冲动型”选手,做任何决定前一定会三思后行。
所以产生了辞职想法后,我着手准备的第一件事,就是“搞清楚社保和公积金怎么交”,“断交或不交会对我的生活产生哪些影响”。
这些也是想做自由职业的朋友问我最多的问题。下面我就结合自己的实际情况,分4部分给大家讲讲。

一、自由职业后,还有必要交五险一金吗?
其实五险一金中最重要的是“养老险”和“医疗险”。
一般社保交满15年后养老保险终身有效,养老金也是“多缴多得、长缴多得”;
社保交满25年后,医疗保险终身有效,看病时医保可以报销一部分费用。
关于“五险一金”交或不交,要根据不同人的不同情况来看。
如果你在户口所在地的城市工作,且在本地已有房,那么交不交、交多少完全看你需求。
如果你已经购买了性价比更高的商业保险,并且没有在本地再买房的打算,那你可以不交五险一金。
当然,如果你还是想买一份国民保险,图个安心,或者害怕以后办理一些事情被社保拖住(毕竟不同城市的政策也是经常变动),也可以自己在当地的社保局缴纳。
但如果你是外地户口且没有当地房产,将来又想在所在地买房落户,那我建议你最好继续缴纳五险,因为社保和大部分城市的落户买房政策挂钩,交不满年限,就无法买房落户。
而且五险中除了养老保险可以断交之外,其他一旦停交则不能补缴,需要重新开始再次缴纳。
我当初就是考虑到应该会在上海定居,才决定继续在上海缴纳五险的。
至于公积金,如果你近1年内没有买房需求,可以暂时不缴,等到你决定买房了,再开始重新缴纳也不迟。
停缴的公积金账户会暂时封存,等你重新交的时候,再去公积金中心解封就可以了。
但如果你没有在所在地定居的打算,比如很多朋友想年轻的时候在一线城市工作生活,等年纪大了或结婚成家了再退居二三线城市工作,这种情况其实可以不在当地缴纳社保,在户籍所在地缴纳或者给自己买一份商业保险也是OK的。

二、不交五险一金会有什么影响?
公积金断交只对已经存在公积金贷款者或者准备申请公积金贷款者存在影响,其他则无直接影响。
如果你还有房贷要还却断交公积金,那么剩余的贷款就会按照商业利率来计算了。
社保断交的影响主要有2点:
1.影响医疗报销和报销上限
很多城市社保只要断缴一个月,第二月就不能继续使用了。
而且有的城市政策是连续缴纳社保的时间越久,报销上限就越高。这个具体看不同城市的政策,你们可以自行上网查一下。
2.影响买房买车、积分落户、孩子上学
部分热门城市要求社保交够一定年份,才可以买房买车。
还有的一线城市会把社保缴纳的额度和积分落户、孩子上学捆绑在一起,比如北上广深。
我所在的上海,就是连续缴纳5年社保才有资格买房买车,交满7年,才有资格申请落户。

三、自由职业者如何缴纳五险一金?
那么自由职业者应该如何缴纳五险一金呢?常见的方式有4种。
1.自己去社保局和公积金中心以灵活就业的方式缴纳
这种只适合本地户籍的人,社保部分也只能缴纳养老保险和医疗保险。
你们可以根据自身的需求和具体状况,自由选择社保和公积金的缴费级别。
2.如果你是外地户籍,可以找第三方机构代缴
通过这种方式缴纳的社保一般会像上班时一样把五险交齐,不同的是以前公司替员工缴纳的部分也要你自己承担。
现在网上类似的代理机构挺多的,支付宝、淘宝和小程序上有很多,一般每个月会收几十块的代理费。
记得一定要找正规、有名的机构,每次交完以后,也要登陆自己的账号查询是否有按时缴纳。
3.挂靠在朋友公司下缴纳
如果你有朋友本身就是开公司的,可以把你的社保挂靠在他们公司下缴纳,这种比找机构省点钱,但是公司缴纳的部分金额也完全是你自己承担的。
4.开一家公司自行缴纳
这种比较适合有稳定客户且业务量比较大的自由职业者,公司的用途除了可以帮你缴纳五险一金外,还可以给客户开正规发票。
但开一家公司又会面临很多税务上的问题,不太建议自由职业新人或收入不稳定的自由职业者开公司。具体原因我和自由税务师骆盈合开的课程里有详细讲到(传送门:不懂一点税务知识,你“敢”成为自由职业者吗?)。

以上,就是不同类型自由职业者交五险一金的方式了。我目前的情况是挂靠在朋友公司下缴纳五险,公积金暂时断交了,等到要买房的时候再重新开始交。
大家可以根据自己的实际情况选择交或不交,以及缴纳方式和数额。
",
+ "cover": "https://img.36krcdn.com/20200410/v2_d748f06964014bafbd0e9cd9371de6d1_img_000?x-oss-process=image/resize,m_mfit,w_432,h_288/crop,w_432,h_288,g_center",
+ "excerpt": "自由职业前,应该想清楚的问题。",
+ "is_essence": false,
+ "is_sticky": false,
+ "last_comment_user_id": "",
+ "last_modify_date": "2020-04-10 18:44:10",
+ "last_modify_ip": "",
+ "like_count": 4603,
+ "publish_date": "2020-04-10 18:39:00",
+ "publish_ip": "",
+ "title": "干货:自由职业者如何搞定五险一金?",
+ "user_id": 121321,
+ "user_name": "未来汽车日报",
+ "view_count": 32053
+ }
+ ],
+ "schema": {
+ "bsonType": "object",
+ "required": [
+ "user_id",
+ "title",
+ "content",
+ "article_status",
+ "view_count",
+ "like_count",
+ "is_sticky",
+ "is_essence",
+ "comment_status",
+ "comment_count",
+ "mode"
+ ],
+ "permission": {
+ "read": true,
+ "create": "auth.uid != null",
+ "update": "doc.uid == auth.uid",
+ "delete": "doc.uid == auth.uid"
+ },
+ "properties": {
+ "_id": {
+ "description": "存储文档 ID(用户 ID),系统自动生成"
+ },
+ "user_id": {
+ "bsonType": "string",
+ "description": "文章作者ID, 参考`uni-id-users` 表"
+ },
+ "category_id": {
+ "bsonType": "string",
+ "description": "分类 id,参考`uni-news-categories`表"
+ },
+ "title": {
+ "bsonType": "string",
+ "description": "标题",
+ "label": "标题"
+ },
+ "content": {
+ "bsonType": "string",
+ "description": "文章内容",
+ "label": "文章内容"
+ },
+ "excerpt": {
+ "bsonType": "string",
+ "description": "文章摘录",
+ "label": "摘要"
+ },
+ "article_status": {
+ "bsonType": "int",
+ "minimum": 0,
+ "maximum": 1,
+ "description": "文章状态:0 草稿箱 1 已发布"
+ },
+ "view_count": {
+ "bsonType": "int",
+ "description": "阅读数量",
+ "permission": {
+ "write": false
+ }
+ },
+ "like_count": {
+ "bsonType": "int",
+ "description": "喜欢数、点赞数",
+ "permission": {
+ "write": false
+ }
+ },
+ "is_sticky": {
+ "bsonType": "bool",
+ "description": "是否置顶",
+ "permission": {
+ "write": false
+ }
+ },
+ "is_essence": {
+ "bsonType": "bool",
+ "description": "阅读加精",
+ "permission": {
+ "write": false
+ }
+ },
+ "comment_status": {
+ "bsonType": "int",
+ "minimum": 0,
+ "maximum": 1,
+ "description": "评论状态:0 关闭 1 开放"
+ },
+ "comment_count": {
+ "bsonType": "int",
+ "description": "评论数量",
+ "permission": {
+ "write": false
+ }
+ },
+ "last_comment_user_id": {
+ "bsonType": "string",
+ "description": "最后回复用户 id,参考`uni-id-users` 表"
+ },
+ "avatar": {
+ "bsonType": "string",
+ "description": "缩略图地址",
+ "label": "封面大图"
+ },
+ "publish_date": {
+ "bsonType": "timestamp",
+ "description": "发表时间",
+ "defaultValue": {
+ "$env": "now"
+ }
+ },
+ "publish_ip": {
+ "bsonType": "string",
+ "description": "发表时 IP 地址",
+ "forceDefaultValue": {
+ "$env": "clientIP"
+ }
+ },
+ "last_modify_date": {
+ "bsonType": "timestamp",
+ "description": "最后修改时间"
+ },
+ "last_modify_ip": {
+ "bsonType": "string",
+ "description": "最后修改时 IP 地址"
+ },
+ "mode": {
+ "bsonType": "number",
+ "description": "排版显示模式"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/uniCloud-aliyun/database/opendb-banner.schema.json b/uniCloud-aliyun/database/opendb-banner.schema.json
new file mode 100644
index 0000000000000000000000000000000000000000..a027517e79b756cdb0af19666759f54845e1377b
--- /dev/null
+++ b/uniCloud-aliyun/database/opendb-banner.schema.json
@@ -0,0 +1,54 @@
+{
+ "bsonType": "object",
+ "required": ["bannerfile"],
+ "permission": {
+ "read": true
+ },
+ "properties": {
+ "_id": {
+ "description": "ID,系统自动生成"
+ },
+ "bannerfile": {
+ "bsonType": "file",
+ "fileMediaType": "image",
+ "title": "图片文件",
+ "description": "图片文件信息,包括文件名、url等"
+ },
+ "open_url": {
+ "bsonType": "string",
+ "description": "点击跳转目标地址。如果是web地址则使用内置web-view打开;如果是本地页面则跳转本地页面;如果是schema地址则打开本地的app",
+ "title": "点击目标地址",
+ "format": "url",
+ "pattern": "^(http:\/\/|https:\/\/|\/|.\/|@\/)\\S",
+ "trim": "both"
+ },
+ "title": {
+ "bsonType": "string",
+ "description": "注意标题文字颜色和背景图靠色导致看不清的问题",
+ "maxLength": 20,
+ "title": "标题",
+ "trim": "both"
+ },
+ "sort": {
+ "bsonType": "int",
+ "description": "数字越小,排序越前",
+ "title": "排序"
+ },
+ "category_id": {
+ "bsonType": "string",
+ "description": "多个栏目的banner都存在一个表里时可用这个字段区分",
+ "title": "分类id"
+ },
+ "status": {
+ "bsonType": "bool",
+ "defaultValue": true,
+ "title": "生效状态"
+ },
+ "description": {
+ "bsonType": "string",
+ "description": "维护者自用描述",
+ "title": "备注",
+ "trim": "both"
+ }
+ }
+}
diff --git a/uniCloud-aliyun/database/opendb-mall-goods.schema.json b/uniCloud-aliyun/database/opendb-mall-goods.schema.json
new file mode 100644
index 0000000000000000000000000000000000000000..b3c24cc6506c60543bd011741f599fcfbbd62c50
--- /dev/null
+++ b/uniCloud-aliyun/database/opendb-mall-goods.schema.json
@@ -0,0 +1,123 @@
+{
+ "bsonType": "object",
+ "permission": {
+ "create": false,
+ "delete": false,
+ "read": "doc.is_on_sale == true",
+ "update": false
+ },
+ "properties": {
+ "_id": {
+ "description": "存储文档 ID(商品 ID),系统自动生成"
+ },
+ "add_date": {
+ "bsonType": "timestamp",
+ "defaultValue": {
+ "$env": "now"
+ },
+ "description": "上架时间"
+ },
+ "category_id": {
+ "bsonType": "string",
+ "description": "分类 id,参考`opendb-mall-categories`表",
+ "foreignKey": "opendb-mall-categories._id"
+ },
+ "comment_count": {
+ "bsonType": "int",
+ "description": "累计评论数"
+ },
+ "goods_banner_imgs": {
+ "bsonType": "array",
+ "description": "商品详情页的banner图地址"
+ },
+ "goods_desc": {
+ "bsonType": "string",
+ "description": "商品详细描述",
+ "title": "详细描述",
+ "trim": "both"
+ },
+ "goods_sn": {
+ "bsonType": "string",
+ "description": "商品的唯一货号",
+ "title": "货号",
+ "trim": "both"
+ },
+ "goods_thumb": {
+ "bsonType": "string",
+ "description": "商品缩略图,用于在列表或搜索结果中预览显示",
+ "pattern": "^(http:\/\/|https:\/\/|\/|.\/|@\/)\\S",
+ "title": "缩略图地址",
+ "trim": "both"
+ },
+ "is_alone_sale": {
+ "bsonType": "bool",
+ "description": "是否能单独销售;如果不能单独销售,则只能作为某商品的配件或者赠品销售"
+ },
+ "is_best": {
+ "bsonType": "bool",
+ "description": "是否精品"
+ },
+ "is_hot": {
+ "bsonType": "bool",
+ "description": "是否热销"
+ },
+ "is_new": {
+ "bsonType": "bool",
+ "description": "是否新品",
+ "title": "是否新品"
+ },
+ "is_on_sale": {
+ "bsonType": "bool",
+ "description": "是否上架销售",
+ "title": "是否上架"
+ },
+ "is_real": {
+ "bsonType": "bool",
+ "description": "是否实物",
+ "title": "是否为实物"
+ },
+ "keywords": {
+ "bsonType": "string",
+ "description": "商品关键字,为搜索引擎收录使用",
+ "title": "关键字",
+ "trim": "both"
+ },
+ "last_modify_date": {
+ "bsonType": "timestamp",
+ "defaultValue": {
+ "$env": "now"
+ },
+ "description": "最后修改时间"
+ },
+ "month_sell_count": {
+ "bsonType": "int",
+ "description": "月销量"
+ },
+ "name": {
+ "bsonType": "string",
+ "description": "商品名称",
+ "title": "名称",
+ "trim": "both"
+ },
+ "remain_count": {
+ "bsonType": "int",
+ "description": "库存数量",
+ "title": "库存数量"
+ },
+ "seller_note": {
+ "bsonType": "string",
+ "description": "商家备注,仅商家可见",
+ "permission": {
+ "read": false
+ },
+ "trim": "both"
+ },
+ "total_sell_count": {
+ "bsonType": "int",
+ "description": "总销量"
+ }
+ },
+ "required": ["goods_sn", "name", "remain_count", "month_sell_count", "total_sell_count", "comment_count", "is_real",
+ "is_on_sale", "is_alone_sale", "is_best", "is_new", "is_hot"
+ ]
+}
diff --git a/uniCloud-aliyun/database/opendb-news-articles.schema.json b/uniCloud-aliyun/database/opendb-news-articles.schema.json
new file mode 100644
index 0000000000000000000000000000000000000000..eb2160fea4135de21b6feb7e372abf8cc1134539
--- /dev/null
+++ b/uniCloud-aliyun/database/opendb-news-articles.schema.json
@@ -0,0 +1,175 @@
+{
+ "bsonType": "object",
+ "required": ["user_id", "title", "content"],
+ "permission": {
+ "read": "doc.uid == auth.uid && doc.article_status == 0 || doc.article_status == 1",
+ "create": "auth.uid != null",
+ "update": "doc.uid == auth.uid",
+ "delete": "doc.uid == auth.uid"
+ },
+ "properties": {
+ "_id": {
+ "description": "存储文档 ID(用户 ID),系统自动生成"
+ },
+ "user_id": {
+ "bsonType": "string",
+ "description": "文章作者ID, 参考`uni-id-users` 表",
+ "foreignKey": "uni-id-users._id",
+ "defaultValue": {
+ "$env": "uid"
+ }
+ },
+ "author": {
+ "bsonType": "string",
+ "title": "作者信息",
+ "description": "冗余字段,用于保存联表查询结果,参考`uni-id-users`表",
+ "foreignKey": "uni-id-users._id",
+ "enum": {
+ "collection": "uni-id-users",
+ "field": "username, _id as text, _id as value"
+ }
+ },
+ "category_id": {
+ "bsonType": "string",
+ "title": "分类",
+ "description": "分类 id,参考`uni-news-categories`表",
+ "foreignKey": "opendb-news-categories._id",
+ "enum": {
+ "collection": "opendb-news-categories",
+ "field": "name as text, _id as value"
+ }
+ },
+ "title": {
+ "bsonType": "string",
+ "title": "标题",
+ "description": "标题",
+ "label": "标题",
+ "trim": "both"
+ },
+ "content": {
+ "bsonType": "string",
+ "title": "文章内容",
+ "description": "文章内容",
+ "label": "文章内容",
+ "trim": "right"
+ },
+ "excerpt": {
+ "bsonType": "string",
+ "title": "文章摘录",
+ "description": "文章摘录",
+ "label": "摘要",
+ "trim": "both"
+ },
+ "article_status": {
+ "bsonType": "int",
+ "title": "文章状态",
+ "description": "文章状态:0 草稿箱 1 已发布",
+ "defaultValue": 0,
+ "enum": [{
+ "value": 0,
+ "text": "草稿箱"
+ }, {
+ "value": 1,
+ "text": "已发布"
+ }]
+ },
+ "view_count": {
+ "bsonType": "int",
+ "title": "阅读数量",
+ "description": "阅读数量",
+ "permission": {
+ "write": false
+ }
+ },
+ "like_count": {
+ "bsonType": "int",
+ "description": "喜欢数、点赞数",
+ "permission": {
+ "write": false
+ }
+ },
+ "is_sticky": {
+ "bsonType": "bool",
+ "title": "是否置顶",
+ "description": "是否置顶",
+ "permission": {
+ "write": false
+ }
+ },
+ "is_essence": {
+ "bsonType": "bool",
+ "title": "阅读加精",
+ "description": "阅读加精",
+ "permission": {
+ "write": false
+ }
+ },
+ "comment_status": {
+ "bsonType": "int",
+ "title": "开放评论",
+ "description": "评论状态:0 关闭 1 开放",
+ "enum": [{
+ "value": 0,
+ "text": "关闭"
+ }, {
+ "value": 1,
+ "text": "开放"
+ }]
+ },
+ "comment_count": {
+ "bsonType": "int",
+ "description": "评论数量",
+ "permission": {
+ "write": false
+ }
+ },
+ "last_comment_user_id": {
+ "bsonType": "string",
+ "description": "最后回复用户 id,参考`uni-id-users` 表",
+ "foreignKey": "uni-id-users._id"
+ },
+ "avatar": {
+ "bsonType": "string",
+ "title": "封面大图",
+ "description": "缩略图地址",
+ "label": "封面大图",
+ "trim": "both"
+ },
+ "publish_date": {
+ "bsonType": "timestamp",
+ "title": "发表时间",
+ "description": "发表时间",
+ "defaultValue": {
+ "$env": "now"
+ }
+ },
+ "publish_ip": {
+ "bsonType": "string",
+ "title": "发布文章时IP地址",
+ "description": "发表时 IP 地址",
+ "forceDefaultValue": {
+ "$env": "clientIP"
+ }
+ },
+ "last_modify_date": {
+ "bsonType": "timestamp",
+ "title": "最后修改时间",
+ "description": "最后修改时间",
+ "defaultValue": {
+ "$env": "now"
+ }
+ },
+ "last_modify_ip": {
+ "bsonType": "string",
+ "description": "最后修改时 IP 地址",
+ "forceDefaultValue": {
+ "$env": "clientIP"
+ }
+ },
+ "mode": {
+ "bsonType": "number",
+ "title": "排版显示模式",
+ "description": "排版显示模式,如左图右文、上图下文等"
+ }
+ }
+}
diff --git a/uniCloud-aliyun/database/opendb-news-categories.schema.json b/uniCloud-aliyun/database/opendb-news-categories.schema.json
new file mode 100644
index 0000000000000000000000000000000000000000..976c8a8f4fd0d89c87a28365b8cacafb641b1a95
--- /dev/null
+++ b/uniCloud-aliyun/database/opendb-news-categories.schema.json
@@ -0,0 +1,50 @@
+{
+ "bsonType": "object",
+ "required": ["name"],
+ "permission": {
+ "read": true,
+ "create": false,
+ "update": false,
+ "delete": false
+ },
+ "properties": {
+ "_id": {
+ "description": "存储文档 ID(文章 ID),系统自动生成"
+ },
+ "name": {
+ "bsonType": "string",
+ "description": "类别名称",
+ "label": "名称",
+ "trim": "both"
+ },
+ "description": {
+ "bsonType": "string",
+ "description": "类别描述",
+ "label": "描述",
+ "trim": "both"
+ },
+ "icon": {
+ "bsonType": "string",
+ "description": "类别图标地址",
+ "label": "图标地址",
+ "pattern": "^(http:\/\/|https:\/\/|\/|.\/|@\/)\\S",
+ "trim": "both"
+ },
+ "sort": {
+ "bsonType": "int",
+ "description": "类别显示顺序",
+ "label": "排序"
+ },
+ "article_count": {
+ "bsonType": "int",
+ "description": "该类别下文章数量"
+ },
+ "create_date": {
+ "bsonType": "timestamp",
+ "description": "创建时间",
+ "forceDefaultValue": {
+ "$env": "now"
+ }
+ }
+ }
+}
diff --git a/uniCloud-aliyun/database/opendb-news-comments.schema.json b/uniCloud-aliyun/database/opendb-news-comments.schema.json
new file mode 100644
index 0000000000000000000000000000000000000000..e8e855ca9bdd50d666255198f9d9a017c34e7e6d
--- /dev/null
+++ b/uniCloud-aliyun/database/opendb-news-comments.schema.json
@@ -0,0 +1,68 @@
+{
+ "bsonType": "object",
+ "required": ["article_id", "user_id", "comment_content", "like_count", "comment_type", "reply_user_id",
+ "reply_comment_id"
+ ],
+ "permission": {
+ "read": true,
+ "create": "auth.uid != null && get(`database.opendb-news-article.${doc.article_id}`).comment_status == 1",
+ "update": "doc.uid == auth.uid",
+ "delete": "doc.uid == auth.uid"
+ },
+ "properties": {
+ "_id": {
+ "description": "存储文档 ID(文章 ID),系统自动生成"
+ },
+ "article_id": {
+ "bsonType": "string",
+ "description": "文章ID,opendb-news-posts 表中的`_id`字段",
+ "foreignKey": "opendb-news-articles._id"
+ },
+ "user_id": {
+ "bsonType": "string",
+ "description": "评论者ID,参考`uni-id-users` 表",
+ "forceDefaultValue": {
+ "$env": "uid"
+ },
+ "foreignKey": "uni-id-users._id"
+ },
+ "comment_content": {
+ "bsonType": "string",
+ "description": "评论内容",
+ "title": "评论内容",
+ "trim": "right"
+ },
+ "like_count": {
+ "bsonType": "int",
+ "description": "评论喜欢数、点赞数"
+ },
+ "comment_type": {
+ "bsonType": "int",
+ "description": "回复类型: 0 针对文章的回复 1 针对评论的回复"
+ },
+ "reply_user_id": {
+ "bsonType": "string",
+ "description": "被回复的评论用户ID,comment_type为1时有效",
+ "foreignKey": "uni-id-users._id"
+ },
+ "reply_comment_id": {
+ "bsonType": "string",
+ "description": "被回复的评论ID,comment_type为1时有效",
+ "foreignKey": "opendb-news-comments._id"
+ },
+ "comment_date": {
+ "bsonType": "timestamp",
+ "description": "评论发表时间",
+ "forceDefaultValue": {
+ "$env": "now"
+ }
+ },
+ "comment_ip": {
+ "bsonType": "string",
+ "description": "评论发表时 IP 地址",
+ "forceDefaultValue": {
+ "$env": "clientIP"
+ }
+ }
+ }
+}
diff --git a/uniCloud-aliyun/database/opendb-news-favorite.schema.json b/uniCloud-aliyun/database/opendb-news-favorite.schema.json
new file mode 100644
index 0000000000000000000000000000000000000000..c18e9695068e13885963002594595da56697c5f5
--- /dev/null
+++ b/uniCloud-aliyun/database/opendb-news-favorite.schema.json
@@ -0,0 +1,35 @@
+{
+ "bsonType": "object",
+ "required": ["user_id", "article_id"],
+ "permission": {
+ "read": true,
+ "create": "auth.uid != null",
+ "update": false,
+ "delete": "doc.uid == auth.uid"
+ },
+ "properties": {
+ "_id": {
+ "description": "ID,系统自动生成"
+ },
+ "article_id": {
+ "bsonType": "string",
+ "description": "文章id,参考opendb-news-articles表",
+ "foreignKey": "opendb-news-articles._id"
+ },
+ "user_id": {
+ "bsonType": "string",
+ "description": "收藏者id,参考uni-id-users表",
+ "forceDefaultValue": {
+ "$env": "uid"
+ },
+ "foreignKey": "uni-id-users._id"
+ },
+ "create_date": {
+ "bsonType": "timestamp",
+ "description": "收藏时间",
+ "forceDefaultValue": {
+ "$env": "now"
+ }
+ }
+ }
+}
diff --git a/uniCloud-aliyun/database/opendb-search-hot.schema.json b/uniCloud-aliyun/database/opendb-search-hot.schema.json
new file mode 100644
index 0000000000000000000000000000000000000000..1230be4c8bd443f26ab8136c69854dfe47d27e03
--- /dev/null
+++ b/uniCloud-aliyun/database/opendb-search-hot.schema.json
@@ -0,0 +1,27 @@
+{
+ "bsonType": "object",
+ "permission": {
+ "create": false,
+ "delete": false,
+ "read": true,
+ "update": false
+ },
+ "properties": {
+ "_id": {
+ "description": "ID,系统自动生成"
+ },
+ "content": {
+ "bsonType": "string",
+ "description": "搜索内容"
+ },
+ "count": {
+ "bsonType": "long",
+ "description": "搜索次数"
+ },
+ "create_date": {
+ "bsonType": "timestamp",
+ "description": "统计时间"
+ }
+ },
+ "required": ["content", "count"]
+}
diff --git a/uniCloud-aliyun/database/opendb-search-log.schema.json b/uniCloud-aliyun/database/opendb-search-log.schema.json
new file mode 100644
index 0000000000000000000000000000000000000000..421ee8c0aa01062fcd3cc86ccffe00bbb2b32cab
--- /dev/null
+++ b/uniCloud-aliyun/database/opendb-search-log.schema.json
@@ -0,0 +1,31 @@
+{
+ "bsonType": "object",
+ "permission": {
+ "create": true,
+ "delete": false,
+ "read": false,
+ "update": false
+ },
+ "properties": {
+ "_id": {
+ "description": "ID,系统自动生成"
+ },
+ "content": {
+ "bsonType": "string",
+ "description": "搜索内容"
+ },
+ "create_date": {
+ "bsonType": "timestamp",
+ "description": "统计时间"
+ },
+ "device_id": {
+ "bsonType": "string",
+ "description": "设备id"
+ },
+ "user_id": {
+ "bsonType": "string",
+ "description": "收藏者id,参考uni-id-users表"
+ }
+ },
+ "required": ["content"]
+}
diff --git a/uniCloud-aliyun/database/opendb-verify-codes.schema.json b/uniCloud-aliyun/database/opendb-verify-codes.schema.json
new file mode 100644
index 0000000000000000000000000000000000000000..91a0962b777f6f57adfcff5ca1d468256fa7d4b9
--- /dev/null
+++ b/uniCloud-aliyun/database/opendb-verify-codes.schema.json
@@ -0,0 +1,45 @@
+{
+ "bsonType": "object",
+ "properties": {
+ "_id": {
+ "description": "ID,系统自动生成"
+ },
+ "code": {
+ "bsonType": "string",
+ "description": "验证码"
+ },
+ "create_date": {
+ "bsonType": "timestamp",
+ "description": "创建时间"
+ },
+ "device_uuid": {
+ "bsonType": "string",
+ "description": "设备UUID,常用于图片验证码"
+ },
+ "email": {
+ "bsonType": "string",
+ "description": "邮箱"
+ },
+ "expired_date": {
+ "bsonType": "timestamp",
+ "description": "过期时间"
+ },
+ "ip": {
+ "bsonType": "string",
+ "description": "请求时客户端IP地址"
+ },
+ "mobile": {
+ "bsonType": "string",
+ "description": "手机号码"
+ },
+ "scene": {
+ "bsonType": "string",
+ "description": "使用验证码的场景,如:login, bind, unbind, pay"
+ },
+ "state": {
+ "bsonType": "int",
+ "description": "验证状态:0 未验证、1 已验证、2 已作废"
+ }
+ },
+ "required": []
+}
diff --git a/uniCloud-aliyun/database/uni-id-log.schema.json b/uniCloud-aliyun/database/uni-id-log.schema.json
new file mode 100644
index 0000000000000000000000000000000000000000..33e0ad8a485d840af0dd5fd6fb48868ac1c28d90
--- /dev/null
+++ b/uniCloud-aliyun/database/uni-id-log.schema.json
@@ -0,0 +1,41 @@
+{
+ "bsonType": "object",
+ "properties": {
+ "_id": {
+ "description": "ID,系统自动生成"
+ },
+ "create_date": {
+ "bsonType": "timestamp",
+ "description": "创建时间",
+ "forceDefaultValue": {
+ "$env": "now"
+ }
+ },
+ "device_uuid": {
+ "bsonType": "string",
+ "description": "设备唯一标识"
+ },
+ "ip": {
+ "bsonType": "string",
+ "description": "ip地址"
+ },
+ "state": {
+ "bsonType": "int",
+ "description": "结果:0 失败、1 成功"
+ },
+ "type": {
+ "bsonType": "string",
+ "description": "登录类型",
+ "enum": ["login", "logout"]
+ },
+ "ua": {
+ "bsonType": "string",
+ "description": "userAgent"
+ },
+ "user_id": {
+ "bsonType": "string",
+ "description": "用户id,参考uni-id-users表"
+ }
+ },
+ "required": []
+}
diff --git a/uniCloud-aliyun/database/uni-id-users.schema.json b/uniCloud-aliyun/database/uni-id-users.schema.json
new file mode 100644
index 0000000000000000000000000000000000000000..854eb1748536a70268b545e49723d6da37250d26
--- /dev/null
+++ b/uniCloud-aliyun/database/uni-id-users.schema.json
@@ -0,0 +1,269 @@
+{
+ "bsonType": "object",
+ "permission": {
+ "read": true,
+ "create": false,
+ "update": false,
+ "delete": false
+ },
+ "properties": {
+ "_id": {
+ "description": "存储文档 ID(用户 ID),系统自动生成"
+ },
+ "ali_openid": {
+ "bsonType": "string",
+ "description": "支付宝平台openid"
+ },
+ "apple_openid": {
+ "bsonType": "string",
+ "description": "苹果登录openid"
+ },
+ "avatar": {
+ "bsonType": "string",
+ "description": "头像地址",
+ "title": "头像地址",
+ "trim": "both"
+ },
+ "comment": {
+ "bsonType": "string",
+ "description": "备注",
+ "title": "备注",
+ "trim": "both"
+ },
+ "department_id": {
+ "bsonType": "array",
+ "description": "部门ID",
+ "enum": {
+ "collection": "opendb-department",
+ "field": "_id as value, name as text",
+ "orderby": "name asc"
+ },
+ "enumType": "tree",
+ "title": "部门"
+ },
+ "email": {
+ "bsonType": "string",
+ "description": "邮箱地址",
+ "format": "email",
+ "title": "邮箱",
+ "trim": "both"
+ },
+ "email_confirmed": {
+ "bsonType": "int",
+ "defaultValue": 0,
+ "description": "邮箱验证状态:0 未验证 1 已验证",
+ "enum": [{
+ "text": "未验证",
+ "value": 0
+ }, {
+ "text": "已验证",
+ "value": 1
+ }],
+ "title": "邮箱验证状态"
+ },
+ "gender": {
+ "bsonType": "int",
+ "defaultValue": 0,
+ "description": "用户性别:0 未知 1 男性 2 女性",
+ "enum": [{
+ "text": "未知",
+ "value": 0
+ }, {
+ "text": "男",
+ "value": 1
+ }, {
+ "text": "女",
+ "value": 2
+ }],
+ "title": "性别"
+ },
+ "inviter_uid": {
+ "bsonType": "array",
+ "description": "用户全部上级邀请者",
+ "trim": "both"
+ },
+ "last_login_date": {
+ "bsonType": "timestamp",
+ "description": "最后登录时间"
+ },
+ "last_login_ip": {
+ "bsonType": "string",
+ "description": "最后登录时 IP 地址"
+ },
+ "mobile": {
+ "bsonType": "string",
+ "description": "手机号码",
+ "pattern": "^\\+?[0-9-]{3,20}$",
+ "title": "手机号码",
+ "trim": "both"
+ },
+ "mobile_confirmed": {
+ "bsonType": "int",
+ "defaultValue": 0,
+ "description": "手机号验证状态:0 未验证 1 已验证",
+ "enum": [{
+ "text": "未验证",
+ "value": 0
+ }, {
+ "text": "已验证",
+ "value": 1
+ }],
+ "title": "手机号验证状态"
+ },
+ "my_invite_code": {
+ "bsonType": "string",
+ "description": "用户自身邀请码"
+ },
+ "nickname": {
+ "bsonType": "string",
+ "description": "用户昵称",
+ "title": "昵称",
+ "trim": "both"
+ },
+ "password": {
+ "bsonType": "password",
+ "description": "密码,加密存储",
+ "title": "密码",
+ "trim": "both"
+ },
+ "password_secret_version": {
+ "bsonType": "int",
+ "description": "密码使用的passwordSecret版本",
+ "title": "passwordSecret"
+ },
+ "realname_auth": {
+ "bsonType": "object",
+ "description": "实名认证信息",
+ "properties": {
+ "auth_date": {
+ "bsonType": "timestamp",
+ "description": "认证通过时间"
+ },
+ "auth_status": {
+ "bsonType": "int",
+ "description": "认证状态:0 未认证 1 等待认证 2 认证通过 3 认证失败",
+ "maximum": 3,
+ "minimum": 0
+ },
+ "contact_email": {
+ "bsonType": "string",
+ "description": "联系人邮箱"
+ },
+ "contact_mobile": {
+ "bsonType": "string",
+ "description": "联系人手机号码"
+ },
+ "contact_person": {
+ "bsonType": "string",
+ "description": "联系人姓名"
+ },
+ "id_card_back": {
+ "bsonType": "string",
+ "description": "身份证反面照 URL"
+ },
+ "id_card_front": {
+ "bsonType": "string",
+ "description": "身份证正面照 URL"
+ },
+ "identity": {
+ "bsonType": "string",
+ "description": "身份证号码\/营业执照号码"
+ },
+ "in_hand": {
+ "bsonType": "string",
+ "description": "手持身份证照片 URL"
+ },
+ "license": {
+ "bsonType": "string",
+ "description": "营业执照 URL"
+ },
+ "real_name": {
+ "bsonType": "string",
+ "description": "真实姓名\/企业名称"
+ },
+ "type": {
+ "bsonType": "int",
+ "description": "用户类型:0 个人用户 1 企业用户",
+ "maximum": 1,
+ "minimum": 0
+ }
+ },
+ "required": ["type", "auth_status"]
+ },
+ "register_date": {
+ "bsonType": "timestamp",
+ "description": "注册时间",
+ "forceDefaultValue": {
+ "$env": "now"
+ }
+ },
+ "register_ip": {
+ "bsonType": "string",
+ "description": "注册时 IP 地址",
+ "forceDefaultValue": {
+ "$env": "clientIP"
+ }
+ },
+ "role": {
+ "bsonType": "array",
+ "description": "用户角色",
+ "enum": {
+ "collection": "uni-id-roles",
+ "field": "role_id as value, role_name as text"
+ },
+ "foreignKey": "uni-id-roles.role_id",
+ "permission": {
+ "write": false
+ },
+ "title": "角色"
+ },
+ "status": {
+ "bsonType": "int",
+ "defaultValue": 0,
+ "description": "用户状态:0 正常 1 禁用 2 审核中 3 审核拒绝",
+ "enum": [{
+ "text": "正常",
+ "value": 0
+ }, {
+ "text": "禁用",
+ "value": 1
+ }, {
+ "text": "审核中",
+ "value": 2
+ }, {
+ "text": "审核拒绝",
+ "value": 3
+ }],
+ "title": "用户状态"
+ },
+ "token": {
+ "bsonType": "array",
+ "description": "用户token"
+ },
+ "username": {
+ "bsonType": "string",
+ "description": "用户名,不允许重复",
+ "title": "用户名",
+ "trim": "both"
+ },
+ "wx_openid": {
+ "bsonType": "object",
+ "description": "微信各个平台openid",
+ "properties": {
+ "app-plus": {
+ "bsonType": "string",
+ "description": "app平台微信openid"
+ },
+ "mp-weixin": {
+ "bsonType": "string",
+ "description": "微信小程序平台openid"
+ }
+ }
+ },
+ "wx_unionid": {
+ "bsonType": "string",
+ "description": "微信unionid"
+ }
+ },
+ "required": []
+}
diff --git a/uni_modules/m-icon/m-icon.css b/uni_modules/m-icon/m-icon.css
new file mode 100644
index 0000000000000000000000000000000000000000..438151e0367fe6d674040d527f2fc5a2f516f5ae
--- /dev/null
+++ b/uni_modules/m-icon/m-icon.css
@@ -0,0 +1,378 @@
+@font-face {
+ font-family: uniicons;
+ font-weight: normal;
+ font-style: normal;
+ src: url('/static/uni.ttf') format('truetype');
+}
+
+.m-icon {
+ font-family: uniicons;
+ /* font-size: 24px; */
+ margin-left: 20px;
+ font-weight: normal;
+ font-style: normal;
+ line-height: 1;
+ display: inline-block;
+ text-decoration: none;
+ -webkit-font-smoothing: antialiased;
+}
+
+.m-icon.uni-active {
+ color: #007aff;
+}
+
+.m-icon-contact:before {
+ content: '\e100';
+}
+
+.m-icon-person:before {
+ content: '\e101';
+}
+
+.m-icon-personadd:before {
+ content: '\e102';
+}
+
+.m-icon-contact-filled:before {
+ content: '\e130';
+}
+
+.m-icon-person-filled:before {
+ content: '\e131';
+}
+
+.m-icon-personadd-filled:before {
+ content: '\e132';
+}
+
+.m-icon-phone:before {
+ content: '\e200';
+}
+
+.m-icon-email:before {
+ content: '\e201';
+}
+
+.m-icon-chatbubble:before {
+ content: '\e202';
+}
+
+.m-icon-chatboxes:before {
+ content: '\e203';
+}
+
+.m-icon-phone-filled:before {
+ content: '\e230';
+}
+
+.m-icon-email-filled:before {
+ content: '\e231';
+}
+
+.m-icon-chatbubble-filled:before {
+ content: '\e232';
+}
+
+.m-icon-chatboxes-filled:before {
+ content: '\e233';
+}
+
+.m-icon-weibo:before {
+ content: '\e260';
+}
+
+.m-icon-weixin:before {
+ content: '\e261';
+}
+
+.m-icon-pengyouquan:before {
+ content: '\e262';
+}
+
+.m-icon-chat:before {
+ content: '\e263';
+}
+
+.m-icon-qq:before {
+ content: '\e264';
+}
+
+.m-icon-videocam:before {
+ content: '\e300';
+}
+
+.m-icon-camera:before {
+ content: '\e301';
+}
+
+.m-icon-mic:before {
+ content: '\e302';
+}
+
+.m-icon-location:before {
+ content: '\e303';
+}
+
+.m-icon-mic-filled:before,
+.m-icon-speech:before {
+ content: '\e332';
+}
+
+.m-icon-location-filled:before {
+ content: '\e333';
+}
+
+.m-icon-micoff:before {
+ content: '\e360';
+}
+
+.m-icon-image:before {
+ content: '\e363';
+}
+
+.m-icon-map:before {
+ content: '\e364';
+}
+
+.m-icon-compose:before {
+ content: '\e400';
+}
+
+.m-icon-trash:before {
+ content: '\e401';
+}
+
+.m-icon-upload:before {
+ content: '\e402';
+}
+
+.m-icon-download:before {
+ content: '\e403';
+}
+
+.m-icon-close:before {
+ content: '\e404';
+}
+
+.m-icon-redo:before {
+ content: '\e405';
+}
+
+.m-icon-undo:before {
+ content: '\e406';
+}
+
+.m-icon-refresh:before {
+ content: '\e407';
+}
+
+.m-icon-star:before {
+ content: '\e408';
+}
+
+.m-icon-plus:before {
+ content: '\e409';
+}
+
+.m-icon-minus:before {
+ content: '\e410';
+}
+
+.m-icon-circle:before,
+.m-icon-checkbox:before {
+ content: '\e411';
+}
+
+.m-icon-close-filled:before,
+.m-icon-clear:before {
+ content: '\e434';
+}
+
+.m-icon-refresh-filled:before {
+ content: '\e437';
+}
+
+.m-icon-star-filled:before {
+ content: '\e438';
+}
+
+.m-icon-plus-filled:before {
+ content: '\e439';
+}
+
+.m-icon-minus-filled:before {
+ content: '\e440';
+}
+
+.m-icon-circle-filled:before {
+ content: '\e441';
+}
+
+.m-icon-checkbox-filled:before {
+ content: '\e442';
+}
+
+.m-icon-closeempty:before {
+ content: '\e460';
+}
+
+.m-icon-refreshempty:before {
+ content: '\e461';
+}
+
+.m-icon-reload:before {
+ content: '\e462';
+}
+
+.m-icon-starhalf:before {
+ content: '\e463';
+}
+
+.m-icon-spinner:before {
+ content: '\e464';
+}
+
+.m-icon-spinner-cycle:before {
+ content: '\e465';
+}
+
+.m-icon-search:before {
+ content: '\e466';
+}
+
+.m-icon-plusempty:before {
+ content: '\e468';
+}
+
+.m-icon-forward:before {
+ content: '\e470';
+}
+
+.m-icon-back:before,
+.m-icon-left-nav:before {
+ content: '\e471';
+}
+
+.m-icon-checkmarkempty:before {
+ content: '\e472';
+}
+
+.m-icon-home:before {
+ content: '\e500';
+}
+
+.m-icon-navigate:before {
+ content: '\e501';
+}
+
+.m-icon-gear:before {
+ content: '\e502';
+}
+
+.m-icon-paperplane:before {
+ content: '\e503';
+}
+
+.m-icon-info:before {
+ content: '\e504';
+}
+
+.m-icon-help:before {
+ content: '\e505';
+}
+
+.m-icon-locked:before {
+ content: '\e506';
+}
+
+.m-icon-more:before {
+ content: '\e507';
+}
+
+.m-icon-flag:before {
+ content: '\e508';
+}
+
+.m-icon-home-filled:before {
+ content: '\e530';
+}
+
+.m-icon-gear-filled:before {
+ content: '\e532';
+}
+
+.m-icon-info-filled:before {
+ content: '\e534';
+}
+
+.m-icon-help-filled:before {
+ content: '\e535';
+}
+
+.m-icon-more-filled:before {
+ content: '\e537';
+}
+
+.m-icon-settings:before {
+ content: '\e560';
+}
+
+.m-icon-list:before {
+ content: '\e562';
+}
+
+.m-icon-bars:before {
+ content: '\e563';
+}
+
+.m-icon-loop:before {
+ content: '\e565';
+}
+
+.m-icon-paperclip:before {
+ content: '\e567';
+}
+
+.m-icon-eye:before {
+ content: '\e568';
+}
+
+.m-icon-arrowup:before {
+ content: '\e580';
+}
+
+.m-icon-arrowdown:before {
+ content: '\e581';
+}
+
+.m-icon-arrowleft:before {
+ content: '\e582';
+}
+
+.m-icon-arrowright:before {
+ content: '\e583';
+}
+
+.m-icon-arrowthinup:before {
+ content: '\e584';
+}
+
+.m-icon-arrowthindown:before {
+ content: '\e585';
+}
+
+.m-icon-arrowthinleft:before {
+ content: '\e586';
+}
+
+.m-icon-arrowthinright:before {
+ content: '\e587';
+}
+
+.m-icon-pulldown:before {
+ content: '\e588';
+}
+
+.m-icon-scan:before {
+ content: "\e612";
+}
diff --git a/uni_modules/m-icon/m-icon.vue b/uni_modules/m-icon/m-icon.vue
new file mode 100644
index 0000000000000000000000000000000000000000..57cb1f73d7bdb15ad3a4b078a70aa4cf493eb275
--- /dev/null
+++ b/uni_modules/m-icon/m-icon.vue
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
diff --git a/uni_modules/m-input.vue b/uni_modules/m-input.vue
new file mode 100644
index 0000000000000000000000000000000000000000..adc4327b169a0c6c371ade734faaf8fcc55c24a0
--- /dev/null
+++ b/uni_modules/m-input.vue
@@ -0,0 +1,125 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/uni-badge/changelog.md b/uni_modules/uni-badge/changelog.md
new file mode 100644
index 0000000000000000000000000000000000000000..bd9ce336a0a64b556edfe013b6ffb42a28948808
--- /dev/null
+++ b/uni_modules/uni-badge/changelog.md
@@ -0,0 +1,2 @@
+## 1.0.6(2021-02-04)
+- 调整为uni_modules目录规范
diff --git a/uni_modules/uni-badge/components/uni-badge/uni-badge.vue b/uni_modules/uni-badge/components/uni-badge/uni-badge.vue
new file mode 100644
index 0000000000000000000000000000000000000000..670b53292c96c35fd4b7bd89e7c2c712bc28afd2
--- /dev/null
+++ b/uni_modules/uni-badge/components/uni-badge/uni-badge.vue
@@ -0,0 +1,156 @@
+
+ {{ text }}
+
+
+
+
+
diff --git a/uni_modules/uni-badge/package.json b/uni_modules/uni-badge/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..02789c0bad822025214bb7f07dd2cceba2f22aa1
--- /dev/null
+++ b/uni_modules/uni-badge/package.json
@@ -0,0 +1,83 @@
+{
+ "id": "uni-badge",
+ "displayName": "Badge 数字角标",
+ "version": "1.0.6",
+ "description": "数字角标(徽章)组件,在元素周围展示消息提醒,一般用于列表、九宫格、按钮等地方。",
+ "keywords": [
+ "",
+ "badge",
+ "uni-ui",
+ "数字角标",
+ "徽章"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example"
+ },
+ "dcloudext": {
+ "category": [
+ "前端组件",
+ "通用组件"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "无",
+ "data": "无",
+ "permissions": "无"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": [],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "u",
+ "app-nvue": "u"
+ },
+ "H5-mobile": {
+ "Safari": "u",
+ "Android Browser": "u",
+ "微信浏览器(Android)": "u",
+ "QQ浏览器(Android)": "u"
+ },
+ "H5-pc": {
+ "Chrome": "u",
+ "IE": "u",
+ "Edge": "u",
+ "Firefox": "u",
+ "Safari": "u"
+ },
+ "小程序": {
+ "微信": "u",
+ "阿里": "u",
+ "百度": "u",
+ "字节跳动": "u",
+ "QQ": "u"
+ },
+ "快应用": {
+ "华为": "u",
+ "联盟": "u"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/uni_modules/uni-badge/readme.md b/uni_modules/uni-badge/readme.md
new file mode 100644
index 0000000000000000000000000000000000000000..ecb886cba7bbe5890fa5028a31e69ed46932ad9d
--- /dev/null
+++ b/uni_modules/uni-badge/readme.md
@@ -0,0 +1,43 @@
+
+
+## Badge 数字角标
+> 代码块: `uBadge`
+
+
+数字角标一般和其它控件(列表、9宫格等)配合使用,用于进行数量提示,默认为实心灰色背景,
+
+### 安装方式
+
+本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。
+
+如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55)
+
+### 基本用法
+
+在 ``template`` 中使用组件
+
+```html
+
+
+
+```
+
+
+## API
+
+### Badge Props
+
+|属性名 |类型 |默认值 |说明 |
+|:-: |:-: |:-: |:-: |
+|text |String |- |角标内容 |
+|type |String |default|颜色类型,可选值:default(灰色)、primary(蓝色)、success(绿色)、warning(黄色)、error(红色)|
+|size |String |normal|Badge 大小,可取值:normal、small|
+|inverted |Boolean |false |是否无需背景颜色,为 true 时,背景颜色将变为文字的字体颜色 |
+
+### Badge Events
+
+|事件名 |事件说明 |返回参数 |
+|:-: |:-: |:-: |
+|@click |点击 Badge 触发事件| - |
+
+
diff --git a/uni_modules/uni-calendar/changelog.md b/uni_modules/uni-calendar/changelog.md
new file mode 100644
index 0000000000000000000000000000000000000000..cd8fdb9fa65129e9110f5b666cbbbbb67f9e08be
--- /dev/null
+++ b/uni_modules/uni-calendar/changelog.md
@@ -0,0 +1,2 @@
+## 1.3.15(2021-02-04)
+- 调整为uni_modules目录规范
diff --git a/uni_modules/uni-calendar/components/uni-calendar/calendar.js b/uni_modules/uni-calendar/components/uni-calendar/calendar.js
new file mode 100644
index 0000000000000000000000000000000000000000..b8d7d6fc44038901fe7a47def32b53764575c1a8
--- /dev/null
+++ b/uni_modules/uni-calendar/components/uni-calendar/calendar.js
@@ -0,0 +1,546 @@
+/**
+* @1900-2100区间内的公历、农历互转
+* @charset UTF-8
+* @github https://github.com/jjonline/calendar.js
+* @Author Jea杨(JJonline@JJonline.Cn)
+* @Time 2014-7-21
+* @Time 2016-8-13 Fixed 2033hex、Attribution Annals
+* @Time 2016-9-25 Fixed lunar LeapMonth Param Bug
+* @Time 2017-7-24 Fixed use getTerm Func Param Error.use solar year,NOT lunar year
+* @Version 1.0.3
+* @公历转农历:calendar.solar2lunar(1987,11,01); //[you can ignore params of prefix 0]
+* @农历转公历:calendar.lunar2solar(1987,09,10); //[you can ignore params of prefix 0]
+*/
+/* eslint-disable */
+var calendar = {
+
+ /**
+ * 农历1900-2100的润大小信息表
+ * @Array Of Property
+ * @return Hex
+ */
+ lunarInfo: [0x04bd8, 0x04ae0, 0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0, 0x055d2, // 1900-1909
+ 0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540, 0x0d6a0, 0x0ada2, 0x095b0, 0x14977, // 1910-1919
+ 0x04970, 0x0a4b0, 0x0b4b5, 0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970, // 1920-1929
+ 0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3, 0x092e0, 0x1c8d7, 0x0c950, // 1930-1939
+ 0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0, 0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, // 1940-1949
+ 0x06ca0, 0x0b550, 0x15355, 0x04da0, 0x0a5b0, 0x14573, 0x052b0, 0x0a9a8, 0x0e950, 0x06aa0, // 1950-1959
+ 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570, 0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, // 1960-1969
+ 0x096d0, 0x04dd5, 0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b6a0, 0x195a6, // 1970-1979
+ 0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50, 0x06d40, 0x0af46, 0x0ab60, 0x09570, // 1980-1989
+ 0x04af5, 0x04970, 0x064b0, 0x074a3, 0x0ea50, 0x06b58, 0x05ac0, 0x0ab60, 0x096d5, 0x092e0, // 1990-1999
+ 0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7, 0x025d0, 0x092d0, 0x0cab5, // 2000-2009
+ 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50, 0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, // 2010-2019
+ 0x07954, 0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260, 0x0ea65, 0x0d530, // 2020-2029
+ 0x05aa0, 0x076a3, 0x096d0, 0x04afb, 0x04ad0, 0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, // 2030-2039
+ 0x0b5a0, 0x056d0, 0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20, 0x0ada0, // 2040-2049
+ /** Add By JJonline@JJonline.Cn**/
+ 0x14b63, 0x09370, 0x049f8, 0x04970, 0x064b0, 0x168a6, 0x0ea50, 0x06b20, 0x1a6c4, 0x0aae0, // 2050-2059
+ 0x0a2e0, 0x0d2e3, 0x0c960, 0x0d557, 0x0d4a0, 0x0da50, 0x05d55, 0x056a0, 0x0a6d0, 0x055d4, // 2060-2069
+ 0x052d0, 0x0a9b8, 0x0a950, 0x0b4a0, 0x0b6a6, 0x0ad50, 0x055a0, 0x0aba4, 0x0a5b0, 0x052b0, // 2070-2079
+ 0x0b273, 0x06930, 0x07337, 0x06aa0, 0x0ad50, 0x14b55, 0x04b60, 0x0a570, 0x054e4, 0x0d160, // 2080-2089
+ 0x0e968, 0x0d520, 0x0daa0, 0x16aa6, 0x056d0, 0x04ae0, 0x0a9d4, 0x0a2d0, 0x0d150, 0x0f252, // 2090-2099
+ 0x0d520], // 2100
+
+ /**
+ * 公历每个月份的天数普通表
+ * @Array Of Property
+ * @return Number
+ */
+ solarMonth: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
+
+ /**
+ * 天干地支之天干速查表
+ * @Array Of Property trans["甲","乙","丙","丁","戊","己","庚","辛","壬","癸"]
+ * @return Cn string
+ */
+ Gan: ['\u7532', '\u4e59', '\u4e19', '\u4e01', '\u620a', '\u5df1', '\u5e9a', '\u8f9b', '\u58ec', '\u7678'],
+
+ /**
+ * 天干地支之地支速查表
+ * @Array Of Property
+ * @trans["子","丑","寅","卯","辰","巳","午","未","申","酉","戌","亥"]
+ * @return Cn string
+ */
+ Zhi: ['\u5b50', '\u4e11', '\u5bc5', '\u536f', '\u8fb0', '\u5df3', '\u5348', '\u672a', '\u7533', '\u9149', '\u620c', '\u4ea5'],
+
+ /**
+ * 天干地支之地支速查表<=>生肖
+ * @Array Of Property
+ * @trans["鼠","牛","虎","兔","龙","蛇","马","羊","猴","鸡","狗","猪"]
+ * @return Cn string
+ */
+ Animals: ['\u9f20', '\u725b', '\u864e', '\u5154', '\u9f99', '\u86c7', '\u9a6c', '\u7f8a', '\u7334', '\u9e21', '\u72d7', '\u732a'],
+
+ /**
+ * 24节气速查表
+ * @Array Of Property
+ * @trans["小寒","大寒","立春","雨水","惊蛰","春分","清明","谷雨","立夏","小满","芒种","夏至","小暑","大暑","立秋","处暑","白露","秋分","寒露","霜降","立冬","小雪","大雪","冬至"]
+ * @return Cn string
+ */
+ solarTerm: ['\u5c0f\u5bd2', '\u5927\u5bd2', '\u7acb\u6625', '\u96e8\u6c34', '\u60ca\u86f0', '\u6625\u5206', '\u6e05\u660e', '\u8c37\u96e8', '\u7acb\u590f', '\u5c0f\u6ee1', '\u8292\u79cd', '\u590f\u81f3', '\u5c0f\u6691', '\u5927\u6691', '\u7acb\u79cb', '\u5904\u6691', '\u767d\u9732', '\u79cb\u5206', '\u5bd2\u9732', '\u971c\u964d', '\u7acb\u51ac', '\u5c0f\u96ea', '\u5927\u96ea', '\u51ac\u81f3'],
+
+ /**
+ * 1900-2100各年的24节气日期速查表
+ * @Array Of Property
+ * @return 0x string For splice
+ */
+ sTermInfo: ['9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf97c3598082c95f8c965cc920f',
+ '97bd0b06bdb0722c965ce1cfcc920f', 'b027097bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
+ '97bcf97c359801ec95f8c965cc920f', '97bd0b06bdb0722c965ce1cfcc920f', 'b027097bd097c36b0b6fc9274c91aa',
+ '97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f', '97bd0b06bdb0722c965ce1cfcc920f',
+ 'b027097bd097c36b0b6fc9274c91aa', '9778397bd19801ec9210c965cc920e', '97b6b97bd19801ec95f8c965cc920f',
+ '97bd09801d98082c95f8e1cfcc920f', '97bd097bd097c36b0b6fc9210c8dc2', '9778397bd197c36c9210c9274c91aa',
+ '97b6b97bd19801ec95f8c965cc920e', '97bd09801d98082c95f8e1cfcc920f', '97bd097bd097c36b0b6fc9210c8dc2',
+ '9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec95f8c965cc920e', '97bcf97c3598082c95f8e1cfcc920f',
+ '97bd097bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec9210c965cc920e',
+ '97bcf97c3598082c95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
+ '97b6b97bd19801ec9210c965cc920e', '97bcf97c3598082c95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722',
+ '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f',
+ '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
+ '97bcf97c359801ec95f8c965cc920f', '97bd097bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
+ '97b6b97bd19801ec9210c965cc920e', '97bcf97c359801ec95f8c965cc920f', '97bd097bd07f595b0b6fc920fb0722',
+ '9778397bd097c36b0b6fc9210c8dc2', '9778397bd19801ec9210c9274c920e', '97b6b97bd19801ec95f8c965cc920f',
+ '97bd07f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c920e',
+ '97b6b97bd19801ec95f8c965cc920f', '97bd07f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2',
+ '9778397bd097c36c9210c9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bd07f1487f595b0b0bc920fb0722',
+ '7f0e397bd097c36b0b6fc9210c8dc2', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
+ '97bcf7f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
+ '97b6b97bd19801ec9210c965cc920e', '97bcf7f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722',
+ '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e', '97bcf7f1487f531b0b0bb0b6fb0722',
+ '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b97bd19801ec9210c965cc920e',
+ '97bcf7f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
+ '97b6b97bd19801ec9210c9274c920e', '97bcf7f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722',
+ '9778397bd097c36b0b6fc9210c91aa', '97b6b97bd197c36c9210c9274c920e', '97bcf7f0e47f531b0b0bb0b6fb0722',
+ '7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9210c8dc2', '9778397bd097c36c9210c9274c920e',
+ '97b6b7f0e47f531b0723b0b6fb0722', '7f0e37f5307f595b0b0bc920fb0722', '7f0e397bd097c36b0b6fc9210c8dc2',
+ '9778397bd097c36b0b70c9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', '7f0e37f1487f595b0b0bb0b6fb0722',
+ '7f0e397bd097c35b0b6fc9210c8dc2', '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721',
+ '7f0e27f1487f595b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
+ '97b6b7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722',
+ '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722',
+ '7f0e397bd097c35b0b6fc920fb0722', '9778397bd097c36b0b6fc9274c91aa', '97b6b7f0e47f531b0723b0b6fb0721',
+ '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9274c91aa',
+ '97b6b7f0e47f531b0723b0787b0721', '7f0e27f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722',
+ '9778397bd097c36b0b6fc9210c91aa', '97b6b7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722',
+ '7f0e397bd07f595b0b0bc920fb0722', '9778397bd097c36b0b6fc9210c8dc2', '977837f0e37f149b0723b0787b0721',
+ '7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f5307f595b0b0bc920fb0722', '7f0e397bd097c35b0b6fc9210c8dc2',
+ '977837f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e37f1487f595b0b0bb0b6fb0722',
+ '7f0e397bd097c35b0b6fc9210c8dc2', '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
+ '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722', '977837f0e37f14998082b0787b06bd',
+ '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd097c35b0b6fc920fb0722',
+ '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722',
+ '7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
+ '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14998082b0787b06bd',
+ '7f07e7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0b0bb0b6fb0722', '7f0e397bd07f595b0b0bc920fb0722',
+ '977837f0e37f14998082b0723b06bd', '7f07e7f0e37f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722',
+ '7f0e397bd07f595b0b0bc920fb0722', '977837f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b0721',
+ '7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f1487f595b0b0bb0b6fb0722', '7f0e37f0e37f14898082b0723b02d5',
+ '7ec967f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0722', '7f0e37f1487f531b0b0bb0b6fb0722',
+ '7f0e37f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
+ '7f0e37f1487f531b0b0bb0b6fb0722', '7f0e37f0e37f14898082b072297c35', '7ec967f0e37f14998082b0787b06bd',
+ '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e37f0e37f14898082b072297c35',
+ '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722',
+ '7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f149b0723b0787b0721',
+ '7f0e27f1487f531b0b0bb0b6fb0722', '7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14998082b0723b06bd',
+ '7f07e7f0e47f149b0723b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722', '7f0e37f0e366aa89801eb072297c35',
+ '7ec967f0e37f14998082b0723b06bd', '7f07e7f0e37f14998083b0787b0721', '7f0e27f0e47f531b0723b0b6fb0722',
+ '7f0e37f0e366aa89801eb072297c35', '7ec967f0e37f14898082b0723b02d5', '7f07e7f0e37f14998082b0787b0721',
+ '7f07e7f0e47f531b0723b0b6fb0722', '7f0e36665b66aa89801e9808297c35', '665f67f0e37f14898082b0723b02d5',
+ '7ec967f0e37f14998082b0787b0721', '7f07e7f0e47f531b0723b0b6fb0722', '7f0e36665b66a449801e9808297c35',
+ '665f67f0e37f14898082b0723b02d5', '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721',
+ '7f0e36665b66a449801e9808297c35', '665f67f0e37f14898082b072297c35', '7ec967f0e37f14998082b0787b06bd',
+ '7f07e7f0e47f531b0723b0b6fb0721', '7f0e26665b66a449801e9808297c35', '665f67f0e37f1489801eb072297c35',
+ '7ec967f0e37f14998082b0787b06bd', '7f07e7f0e47f531b0723b0b6fb0721', '7f0e27f1487f531b0b0bb0b6fb0722'],
+
+ /**
+ * 数字转中文速查表
+ * @Array Of Property
+ * @trans ['日','一','二','三','四','五','六','七','八','九','十']
+ * @return Cn string
+ */
+ nStr1: ['\u65e5', '\u4e00', '\u4e8c', '\u4e09', '\u56db', '\u4e94', '\u516d', '\u4e03', '\u516b', '\u4e5d', '\u5341'],
+
+ /**
+ * 日期转农历称呼速查表
+ * @Array Of Property
+ * @trans ['初','十','廿','卅']
+ * @return Cn string
+ */
+ nStr2: ['\u521d', '\u5341', '\u5eff', '\u5345'],
+
+ /**
+ * 月份转农历称呼速查表
+ * @Array Of Property
+ * @trans ['正','一','二','三','四','五','六','七','八','九','十','冬','腊']
+ * @return Cn string
+ */
+ nStr3: ['\u6b63', '\u4e8c', '\u4e09', '\u56db', '\u4e94', '\u516d', '\u4e03', '\u516b', '\u4e5d', '\u5341', '\u51ac', '\u814a'],
+
+ /**
+ * 返回农历y年一整年的总天数
+ * @param lunar Year
+ * @return Number
+ * @eg:var count = calendar.lYearDays(1987) ;//count=387
+ */
+ lYearDays: function (y) {
+ var i; var sum = 348
+ for (i = 0x8000; i > 0x8; i >>= 1) { sum += (this.lunarInfo[y - 1900] & i) ? 1 : 0 }
+ return (sum + this.leapDays(y))
+ },
+
+ /**
+ * 返回农历y年闰月是哪个月;若y年没有闰月 则返回0
+ * @param lunar Year
+ * @return Number (0-12)
+ * @eg:var leapMonth = calendar.leapMonth(1987) ;//leapMonth=6
+ */
+ leapMonth: function (y) { // 闰字编码 \u95f0
+ return (this.lunarInfo[y - 1900] & 0xf)
+ },
+
+ /**
+ * 返回农历y年闰月的天数 若该年没有闰月则返回0
+ * @param lunar Year
+ * @return Number (0、29、30)
+ * @eg:var leapMonthDay = calendar.leapDays(1987) ;//leapMonthDay=29
+ */
+ leapDays: function (y) {
+ if (this.leapMonth(y)) {
+ return ((this.lunarInfo[y - 1900] & 0x10000) ? 30 : 29)
+ }
+ return (0)
+ },
+
+ /**
+ * 返回农历y年m月(非闰月)的总天数,计算m为闰月时的天数请使用leapDays方法
+ * @param lunar Year
+ * @return Number (-1、29、30)
+ * @eg:var MonthDay = calendar.monthDays(1987,9) ;//MonthDay=29
+ */
+ monthDays: function (y, m) {
+ if (m > 12 || m < 1) { return -1 }// 月份参数从1至12,参数错误返回-1
+ return ((this.lunarInfo[y - 1900] & (0x10000 >> m)) ? 30 : 29)
+ },
+
+ /**
+ * 返回公历(!)y年m月的天数
+ * @param solar Year
+ * @return Number (-1、28、29、30、31)
+ * @eg:var solarMonthDay = calendar.leapDays(1987) ;//solarMonthDay=30
+ */
+ solarDays: function (y, m) {
+ if (m > 12 || m < 1) { return -1 } // 若参数错误 返回-1
+ var ms = m - 1
+ if (ms == 1) { // 2月份的闰平规律测算后确认返回28或29
+ return (((y % 4 == 0) && (y % 100 != 0) || (y % 400 == 0)) ? 29 : 28)
+ } else {
+ return (this.solarMonth[ms])
+ }
+ },
+
+ /**
+ * 农历年份转换为干支纪年
+ * @param lYear 农历年的年份数
+ * @return Cn string
+ */
+ toGanZhiYear: function (lYear) {
+ var ganKey = (lYear - 3) % 10
+ var zhiKey = (lYear - 3) % 12
+ if (ganKey == 0) ganKey = 10// 如果余数为0则为最后一个天干
+ if (zhiKey == 0) zhiKey = 12// 如果余数为0则为最后一个地支
+ return this.Gan[ganKey - 1] + this.Zhi[zhiKey - 1]
+ },
+
+ /**
+ * 公历月、日判断所属星座
+ * @param cMonth [description]
+ * @param cDay [description]
+ * @return Cn string
+ */
+ toAstro: function (cMonth, cDay) {
+ var s = '\u9b54\u7faf\u6c34\u74f6\u53cc\u9c7c\u767d\u7f8a\u91d1\u725b\u53cc\u5b50\u5de8\u87f9\u72ee\u5b50\u5904\u5973\u5929\u79e4\u5929\u874e\u5c04\u624b\u9b54\u7faf'
+ var arr = [20, 19, 21, 21, 21, 22, 23, 23, 23, 23, 22, 22]
+ return s.substr(cMonth * 2 - (cDay < arr[cMonth - 1] ? 2 : 0), 2) + '\u5ea7'// 座
+ },
+
+ /**
+ * 传入offset偏移量返回干支
+ * @param offset 相对甲子的偏移量
+ * @return Cn string
+ */
+ toGanZhi: function (offset) {
+ return this.Gan[offset % 10] + this.Zhi[offset % 12]
+ },
+
+ /**
+ * 传入公历(!)y年获得该年第n个节气的公历日期
+ * @param y公历年(1900-2100);n二十四节气中的第几个节气(1~24);从n=1(小寒)算起
+ * @return day Number
+ * @eg:var _24 = calendar.getTerm(1987,3) ;//_24=4;意即1987年2月4日立春
+ */
+ getTerm: function (y, n) {
+ if (y < 1900 || y > 2100) { return -1 }
+ if (n < 1 || n > 24) { return -1 }
+ var _table = this.sTermInfo[y - 1900]
+ var _info = [
+ parseInt('0x' + _table.substr(0, 5)).toString(),
+ parseInt('0x' + _table.substr(5, 5)).toString(),
+ parseInt('0x' + _table.substr(10, 5)).toString(),
+ parseInt('0x' + _table.substr(15, 5)).toString(),
+ parseInt('0x' + _table.substr(20, 5)).toString(),
+ parseInt('0x' + _table.substr(25, 5)).toString()
+ ]
+ var _calday = [
+ _info[0].substr(0, 1),
+ _info[0].substr(1, 2),
+ _info[0].substr(3, 1),
+ _info[0].substr(4, 2),
+
+ _info[1].substr(0, 1),
+ _info[1].substr(1, 2),
+ _info[1].substr(3, 1),
+ _info[1].substr(4, 2),
+
+ _info[2].substr(0, 1),
+ _info[2].substr(1, 2),
+ _info[2].substr(3, 1),
+ _info[2].substr(4, 2),
+
+ _info[3].substr(0, 1),
+ _info[3].substr(1, 2),
+ _info[3].substr(3, 1),
+ _info[3].substr(4, 2),
+
+ _info[4].substr(0, 1),
+ _info[4].substr(1, 2),
+ _info[4].substr(3, 1),
+ _info[4].substr(4, 2),
+
+ _info[5].substr(0, 1),
+ _info[5].substr(1, 2),
+ _info[5].substr(3, 1),
+ _info[5].substr(4, 2)
+ ]
+ return parseInt(_calday[n - 1])
+ },
+
+ /**
+ * 传入农历数字月份返回汉语通俗表示法
+ * @param lunar month
+ * @return Cn string
+ * @eg:var cnMonth = calendar.toChinaMonth(12) ;//cnMonth='腊月'
+ */
+ toChinaMonth: function (m) { // 月 => \u6708
+ if (m > 12 || m < 1) { return -1 } // 若参数错误 返回-1
+ var s = this.nStr3[m - 1]
+ s += '\u6708'// 加上月字
+ return s
+ },
+
+ /**
+ * 传入农历日期数字返回汉字表示法
+ * @param lunar day
+ * @return Cn string
+ * @eg:var cnDay = calendar.toChinaDay(21) ;//cnMonth='廿一'
+ */
+ toChinaDay: function (d) { // 日 => \u65e5
+ var s
+ switch (d) {
+ case 10:
+ s = '\u521d\u5341'; break
+ case 20:
+ s = '\u4e8c\u5341'; break
+ break
+ case 30:
+ s = '\u4e09\u5341'; break
+ break
+ default :
+ s = this.nStr2[Math.floor(d / 10)]
+ s += this.nStr1[d % 10]
+ }
+ return (s)
+ },
+
+ /**
+ * 年份转生肖[!仅能大致转换] => 精确划分生肖分界线是“立春”
+ * @param y year
+ * @return Cn string
+ * @eg:var animal = calendar.getAnimal(1987) ;//animal='兔'
+ */
+ getAnimal: function (y) {
+ return this.Animals[(y - 4) % 12]
+ },
+
+ /**
+ * 传入阳历年月日获得详细的公历、农历object信息 <=>JSON
+ * @param y solar year
+ * @param m solar month
+ * @param d solar day
+ * @return JSON object
+ * @eg:console.log(calendar.solar2lunar(1987,11,01));
+ */
+ solar2lunar: function (y, m, d) { // 参数区间1900.1.31~2100.12.31
+ // 年份限定、上限
+ if (y < 1900 || y > 2100) {
+ return -1// undefined转换为数字变为NaN
+ }
+ // 公历传参最下限
+ if (y == 1900 && m == 1 && d < 31) {
+ return -1
+ }
+ // 未传参 获得当天
+ if (!y) {
+ var objDate = new Date()
+ } else {
+ var objDate = new Date(y, parseInt(m) - 1, d)
+ }
+ var i; var leap = 0; var temp = 0
+ // 修正ymd参数
+ var y = objDate.getFullYear()
+ var m = objDate.getMonth() + 1
+ var d = objDate.getDate()
+ var offset = (Date.UTC(objDate.getFullYear(), objDate.getMonth(), objDate.getDate()) - Date.UTC(1900, 0, 31)) / 86400000
+ for (i = 1900; i < 2101 && offset > 0; i++) {
+ temp = this.lYearDays(i)
+ offset -= temp
+ }
+ if (offset < 0) {
+ offset += temp; i--
+ }
+
+ // 是否今天
+ var isTodayObj = new Date()
+ var isToday = false
+ if (isTodayObj.getFullYear() == y && isTodayObj.getMonth() + 1 == m && isTodayObj.getDate() == d) {
+ isToday = true
+ }
+ // 星期几
+ var nWeek = objDate.getDay()
+ var cWeek = this.nStr1[nWeek]
+ // 数字表示周几顺应天朝周一开始的惯例
+ if (nWeek == 0) {
+ nWeek = 7
+ }
+ // 农历年
+ var year = i
+ var leap = this.leapMonth(i) // 闰哪个月
+ var isLeap = false
+
+ // 效验闰月
+ for (i = 1; i < 13 && offset > 0; i++) {
+ // 闰月
+ if (leap > 0 && i == (leap + 1) && isLeap == false) {
+ --i
+ isLeap = true; temp = this.leapDays(year) // 计算农历闰月天数
+ } else {
+ temp = this.monthDays(year, i)// 计算农历普通月天数
+ }
+ // 解除闰月
+ if (isLeap == true && i == (leap + 1)) { isLeap = false }
+ offset -= temp
+ }
+ // 闰月导致数组下标重叠取反
+ if (offset == 0 && leap > 0 && i == leap + 1) {
+ if (isLeap) {
+ isLeap = false
+ } else {
+ isLeap = true; --i
+ }
+ }
+ if (offset < 0) {
+ offset += temp; --i
+ }
+ // 农历月
+ var month = i
+ // 农历日
+ var day = offset + 1
+ // 天干地支处理
+ var sm = m - 1
+ var gzY = this.toGanZhiYear(year)
+
+ // 当月的两个节气
+ // bugfix-2017-7-24 11:03:38 use lunar Year Param `y` Not `year`
+ var firstNode = this.getTerm(y, (m * 2 - 1))// 返回当月「节」为几日开始
+ var secondNode = this.getTerm(y, (m * 2))// 返回当月「节」为几日开始
+
+ // 依据12节气修正干支月
+ var gzM = this.toGanZhi((y - 1900) * 12 + m + 11)
+ if (d >= firstNode) {
+ gzM = this.toGanZhi((y - 1900) * 12 + m + 12)
+ }
+
+ // 传入的日期的节气与否
+ var isTerm = false
+ var Term = null
+ if (firstNode == d) {
+ isTerm = true
+ Term = this.solarTerm[m * 2 - 2]
+ }
+ if (secondNode == d) {
+ isTerm = true
+ Term = this.solarTerm[m * 2 - 1]
+ }
+ // 日柱 当月一日与 1900/1/1 相差天数
+ var dayCyclical = Date.UTC(y, sm, 1, 0, 0, 0, 0) / 86400000 + 25567 + 10
+ var gzD = this.toGanZhi(dayCyclical + d - 1)
+ // 该日期所属的星座
+ var astro = this.toAstro(m, d)
+
+ return { 'lYear': year, 'lMonth': month, 'lDay': day, 'Animal': this.getAnimal(year), 'IMonthCn': (isLeap ? '\u95f0' : '') + this.toChinaMonth(month), 'IDayCn': this.toChinaDay(day), 'cYear': y, 'cMonth': m, 'cDay': d, 'gzYear': gzY, 'gzMonth': gzM, 'gzDay': gzD, 'isToday': isToday, 'isLeap': isLeap, 'nWeek': nWeek, 'ncWeek': '\u661f\u671f' + cWeek, 'isTerm': isTerm, 'Term': Term, 'astro': astro }
+ },
+
+ /**
+ * 传入农历年月日以及传入的月份是否闰月获得详细的公历、农历object信息 <=>JSON
+ * @param y lunar year
+ * @param m lunar month
+ * @param d lunar day
+ * @param isLeapMonth lunar month is leap or not.[如果是农历闰月第四个参数赋值true即可]
+ * @return JSON object
+ * @eg:console.log(calendar.lunar2solar(1987,9,10));
+ */
+ lunar2solar: function (y, m, d, isLeapMonth) { // 参数区间1900.1.31~2100.12.1
+ var isLeapMonth = !!isLeapMonth
+ var leapOffset = 0
+ var leapMonth = this.leapMonth(y)
+ var leapDay = this.leapDays(y)
+ if (isLeapMonth && (leapMonth != m)) { return -1 }// 传参要求计算该闰月公历 但该年得出的闰月与传参的月份并不同
+ if (y == 2100 && m == 12 && d > 1 || y == 1900 && m == 1 && d < 31) { return -1 }// 超出了最大极限值
+ var day = this.monthDays(y, m)
+ var _day = day
+ // bugFix 2016-9-25
+ // if month is leap, _day use leapDays method
+ if (isLeapMonth) {
+ _day = this.leapDays(y, m)
+ }
+ if (y < 1900 || y > 2100 || d > _day) { return -1 }// 参数合法性效验
+
+ // 计算农历的时间差
+ var offset = 0
+ for (var i = 1900; i < y; i++) {
+ offset += this.lYearDays(i)
+ }
+ var leap = 0; var isAdd = false
+ for (var i = 1; i < m; i++) {
+ leap = this.leapMonth(y)
+ if (!isAdd) { // 处理闰月
+ if (leap <= i && leap > 0) {
+ offset += this.leapDays(y); isAdd = true
+ }
+ }
+ offset += this.monthDays(y, i)
+ }
+ // 转换闰月农历 需补充该年闰月的前一个月的时差
+ if (isLeapMonth) { offset += day }
+ // 1900年农历正月一日的公历时间为1900年1月30日0时0分0秒(该时间也是本农历的最开始起始点)
+ var stmap = Date.UTC(1900, 1, 30, 0, 0, 0)
+ var calObj = new Date((offset + d - 31) * 86400000 + stmap)
+ var cY = calObj.getUTCFullYear()
+ var cM = calObj.getUTCMonth() + 1
+ var cD = calObj.getUTCDate()
+
+ return this.solar2lunar(cY, cM, cD)
+ }
+}
+
+export default calendar
diff --git a/uni_modules/uni-calendar/components/uni-calendar/uni-calendar-item.vue b/uni_modules/uni-calendar/components/uni-calendar/uni-calendar-item.vue
new file mode 100644
index 0000000000000000000000000000000000000000..c66a58d31b757837da706ec0a6b37a8df1aa2b1f
--- /dev/null
+++ b/uni_modules/uni-calendar/components/uni-calendar/uni-calendar-item.vue
@@ -0,0 +1,170 @@
+
+
+
+
+ {{weeks.date}}
+ 今天
+ {{weeks.isDay?'今天': (weeks.lunar.IDayCn === '初一'?weeks.lunar.IMonthCn:weeks.lunar.IDayCn)}}
+ {{weeks.extraInfo.info}}
+
+
+
+
+
+
+
diff --git a/uni_modules/uni-calendar/components/uni-calendar/uni-calendar.vue b/uni_modules/uni-calendar/components/uni-calendar/uni-calendar.vue
new file mode 100644
index 0000000000000000000000000000000000000000..9c856ccb01e6ceea771febd562d0bbafd7413bd5
--- /dev/null
+++ b/uni_modules/uni-calendar/components/uni-calendar/uni-calendar.vue
@@ -0,0 +1,505 @@
+
+
+
+
+
+
+
+
+ {{nowDate.month}}
+
+
+
+ 日
+
+
+ 一
+
+
+ 二
+
+
+ 三
+
+
+ 四
+
+
+ 五
+
+
+ 六
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/uni-calendar/components/uni-calendar/util.js b/uni_modules/uni-calendar/components/uni-calendar/util.js
new file mode 100644
index 0000000000000000000000000000000000000000..37f44321ebc299212eea8646c9e7e63e9b2ed6f8
--- /dev/null
+++ b/uni_modules/uni-calendar/components/uni-calendar/util.js
@@ -0,0 +1,352 @@
+import CALENDAR from './calendar.js'
+
+class Calendar {
+ constructor({
+ date,
+ selected,
+ startDate,
+ endDate,
+ range
+ } = {}) {
+ // 当前日期
+ this.date = this.getDate(new Date()) // 当前初入日期
+ // 打点信息
+ this.selected = selected || [];
+ // 范围开始
+ this.startDate = startDate
+ // 范围结束
+ this.endDate = endDate
+ this.range = range
+ // 多选状态
+ this.cleanMultipleStatus()
+ // 每周日期
+ this.weeks = {}
+ // this._getWeek(this.date.fullDate)
+ }
+ /**
+ * 设置日期
+ * @param {Object} date
+ */
+ setDate(date) {
+ this.selectDate = this.getDate(date)
+ this._getWeek(this.selectDate.fullDate)
+ }
+
+ /**
+ * 清理多选状态
+ */
+ cleanMultipleStatus() {
+ this.multipleStatus = {
+ before: '',
+ after: '',
+ data: []
+ }
+ }
+
+ /**
+ * 重置开始日期
+ */
+ resetSatrtDate(startDate) {
+ // 范围开始
+ this.startDate = startDate
+
+ }
+
+ /**
+ * 重置结束日期
+ */
+ resetEndDate(endDate) {
+ // 范围结束
+ this.endDate = endDate
+ }
+
+ /**
+ * 获取任意时间
+ */
+ getDate(date, AddDayCount = 0, str = 'day') {
+ if (!date) {
+ date = new Date()
+ }
+ if (typeof date !== 'object') {
+ date = date.replace(/-/g, '/')
+ }
+ const dd = new Date(date)
+ switch (str) {
+ case 'day':
+ dd.setDate(dd.getDate() + AddDayCount) // 获取AddDayCount天后的日期
+ break
+ case 'month':
+ if (dd.getDate() === 31) {
+ dd.setDate(dd.getDate() + AddDayCount)
+ } else {
+ dd.setMonth(dd.getMonth() + AddDayCount) // 获取AddDayCount天后的日期
+ }
+ break
+ case 'year':
+ dd.setFullYear(dd.getFullYear() + AddDayCount) // 获取AddDayCount天后的日期
+ break
+ }
+ const y = dd.getFullYear()
+ const m = dd.getMonth() + 1 < 10 ? '0' + (dd.getMonth() + 1) : dd.getMonth() + 1 // 获取当前月份的日期,不足10补0
+ const d = dd.getDate() < 10 ? '0' + dd.getDate() : dd.getDate() // 获取当前几号,不足10补0
+ return {
+ fullDate: y + '-' + m + '-' + d,
+ year: y,
+ month: m,
+ date: d,
+ day: dd.getDay()
+ }
+ }
+
+
+ /**
+ * 获取上月剩余天数
+ */
+ _getLastMonthDays(firstDay, full) {
+ let dateArr = []
+ for (let i = firstDay; i > 0; i--) {
+ const beforeDate = new Date(full.year, full.month - 1, -i + 1).getDate()
+ dateArr.push({
+ date: beforeDate,
+ month: full.month - 1,
+ lunar: this.getlunar(full.year, full.month - 1, beforeDate),
+ disable: true
+ })
+ }
+ return dateArr
+ }
+ /**
+ * 获取本月天数
+ */
+ _currentMonthDys(dateData, full) {
+ let dateArr = []
+ let fullDate = this.date.fullDate
+ for (let i = 1; i <= dateData; i++) {
+ let isinfo = false
+ let nowDate = full.year + '-' + (full.month < 10 ?
+ full.month : full.month) + '-' + (i < 10 ?
+ '0' + i : i)
+ // 是否今天
+ let isDay = fullDate === nowDate
+ // 获取打点信息
+ let info = this.selected && this.selected.find((item) => {
+ if (this.dateEqual(nowDate, item.date)) {
+ return item
+ }
+ })
+
+ // 日期禁用
+ let disableBefore = true
+ let disableAfter = true
+ if (this.startDate) {
+ let dateCompBefore = this.dateCompare(this.startDate, fullDate)
+ disableBefore = this.dateCompare(dateCompBefore ? this.startDate : fullDate, nowDate)
+ }
+
+ if (this.endDate) {
+ let dateCompAfter = this.dateCompare(fullDate, this.endDate)
+ disableAfter = this.dateCompare(nowDate, dateCompAfter ? this.endDate : fullDate)
+ }
+ let multiples = this.multipleStatus.data
+ let checked = false
+ let multiplesStatus = -1
+ if (this.range) {
+ if (multiples) {
+ multiplesStatus = multiples.findIndex((item) => {
+ return this.dateEqual(item, nowDate)
+ })
+ }
+ if (multiplesStatus !== -1) {
+ checked = true
+ }
+ }
+ let data = {
+ fullDate: nowDate,
+ year: full.year,
+ date: i,
+ multiple: this.range ? checked : false,
+ beforeMultiple: this.dateEqual(this.multipleStatus.before, nowDate),
+ afterMultiple: this.dateEqual(this.multipleStatus.after, nowDate),
+ month: full.month,
+ lunar: this.getlunar(full.year, full.month, i),
+ disable: !disableBefore || !disableAfter,
+ isDay
+ }
+ if (info) {
+ data.extraInfo = info
+ }
+
+ dateArr.push(data)
+ }
+ return dateArr
+ }
+ /**
+ * 获取下月天数
+ */
+ _getNextMonthDays(surplus, full) {
+ let dateArr = []
+ for (let i = 1; i < surplus + 1; i++) {
+ dateArr.push({
+ date: i,
+ month: Number(full.month) + 1,
+ lunar: this.getlunar(full.year, Number(full.month) + 1, i),
+ disable: true
+ })
+ }
+ return dateArr
+ }
+
+ /**
+ * 获取当前日期详情
+ * @param {Object} date
+ */
+ getInfo(date) {
+ if (!date) {
+ date = new Date()
+ }
+ const dateInfo = this.canlender.find(item => item.fullDate === this.getDate(date).fullDate)
+ return dateInfo
+ }
+
+ /**
+ * 比较时间大小
+ */
+ dateCompare(startDate, endDate) {
+ // 计算截止时间
+ startDate = new Date(startDate.replace('-', '/').replace('-', '/'))
+ // 计算详细项的截止时间
+ endDate = new Date(endDate.replace('-', '/').replace('-', '/'))
+ if (startDate <= endDate) {
+ return true
+ } else {
+ return false
+ }
+ }
+
+ /**
+ * 比较时间是否相等
+ */
+ dateEqual(before, after) {
+ // 计算截止时间
+ before = new Date(before.replace('-', '/').replace('-', '/'))
+ // 计算详细项的截止时间
+ after = new Date(after.replace('-', '/').replace('-', '/'))
+ if (before.getTime() - after.getTime() === 0) {
+ return true
+ } else {
+ return false
+ }
+ }
+
+
+ /**
+ * 获取日期范围内所有日期
+ * @param {Object} begin
+ * @param {Object} end
+ */
+ geDateAll(begin, end) {
+ var arr = []
+ var ab = begin.split('-')
+ var ae = end.split('-')
+ var db = new Date()
+ db.setFullYear(ab[0], ab[1] - 1, ab[2])
+ var de = new Date()
+ de.setFullYear(ae[0], ae[1] - 1, ae[2])
+ var unixDb = db.getTime() - 24 * 60 * 60 * 1000
+ var unixDe = de.getTime() - 24 * 60 * 60 * 1000
+ for (var k = unixDb; k <= unixDe;) {
+ k = k + 24 * 60 * 60 * 1000
+ arr.push(this.getDate(new Date(parseInt(k))).fullDate)
+ }
+ return arr
+ }
+ /**
+ * 计算阴历日期显示
+ */
+ getlunar(year, month, date) {
+ return CALENDAR.solar2lunar(year, month, date)
+ }
+ /**
+ * 设置打点
+ */
+ setSelectInfo(data, value) {
+ this.selected = value
+ this._getWeek(data)
+ }
+
+ /**
+ * 获取多选状态
+ */
+ setMultiple(fullDate) {
+ let {
+ before,
+ after
+ } = this.multipleStatus
+
+ if (!this.range) return
+ if (before && after) {
+ this.multipleStatus.before = ''
+ this.multipleStatus.after = ''
+ this.multipleStatus.data = []
+ } else {
+ if (!before) {
+ this.multipleStatus.before = fullDate
+ } else {
+ this.multipleStatus.after = fullDate
+ if (this.dateCompare(this.multipleStatus.before, this.multipleStatus.after)) {
+ this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus.after);
+ } else {
+ this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus.before);
+ }
+ }
+ }
+ this._getWeek(fullDate)
+ }
+
+ /**
+ * 获取每周数据
+ * @param {Object} dateData
+ */
+ _getWeek(dateData) {
+ const {
+ fullDate,
+ year,
+ month,
+ date,
+ day
+ } = this.getDate(dateData)
+ let firstDay = new Date(year, month - 1, 1).getDay()
+ let currentDay = new Date(year, month, 0).getDate()
+ let dates = {
+ lastMonthDays: this._getLastMonthDays(firstDay, this.getDate(dateData)), // 上个月末尾几天
+ currentMonthDys: this._currentMonthDys(currentDay, this.getDate(dateData)), // 本月天数
+ nextMonthDays: [], // 下个月开始几天
+ weeks: []
+ }
+ let canlender = []
+ const surplus = 42 - (dates.lastMonthDays.length + dates.currentMonthDys.length)
+ dates.nextMonthDays = this._getNextMonthDays(surplus, this.getDate(dateData))
+ canlender = canlender.concat(dates.lastMonthDays, dates.currentMonthDys, dates.nextMonthDays)
+ let weeks = {}
+ // 拼接数组 上个月开始几天 + 本月天数+ 下个月开始几天
+ for (let i = 0; i < canlender.length; i++) {
+ if (i % 7 === 0) {
+ weeks[parseInt(i / 7)] = new Array(7)
+ }
+ weeks[parseInt(i / 7)][i % 7] = canlender[i]
+ }
+ this.canlender = canlender
+ this.weeks = weeks
+ }
+
+ //静态方法
+ // static init(date) {
+ // if (!this.instance) {
+ // this.instance = new Calendar(date);
+ // }
+ // return this.instance;
+ // }
+}
+
+
+export default Calendar
diff --git a/uni_modules/uni-calendar/package.json b/uni_modules/uni-calendar/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..158377b9a27c1e122f4430e95c7decbf1714359a
--- /dev/null
+++ b/uni_modules/uni-calendar/package.json
@@ -0,0 +1,81 @@
+{
+ "id": "uni-calendar",
+ "displayName": "Calendar 日历",
+ "version": "1.3.15",
+ "description": "日历组件",
+ "keywords": [
+ "日历",
+ "打卡",
+ "日历选择"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "前端组件",
+ "通用组件"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "无",
+ "data": "无",
+ "permissions": "无"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": [],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "微信浏览器(Android)": "y",
+ "QQ浏览器(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "小程序": {
+ "微信": "y",
+ "阿里": "y",
+ "百度": "y",
+ "字节跳动": "y",
+ "QQ": "y"
+ },
+ "快应用": {
+ "华为": "u",
+ "联盟": "u"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/uni_modules/uni-calendar/readme.md b/uni_modules/uni-calendar/readme.md
new file mode 100644
index 0000000000000000000000000000000000000000..5475fecf993640abb50d84731638ae2af0e563e8
--- /dev/null
+++ b/uni_modules/uni-calendar/readme.md
@@ -0,0 +1,96 @@
+
+
+## Calendar 日历
+> 代码块: `uCalendar`
+
+
+日历组件
+
+> 为了避免错误使用,给大家带来不好的开发体验,请在使用组件前仔细阅读下面的注意事项,可以帮你避免一些错误。
+> - 本组件农历转换使用的js是 [@1900-2100区间内的公历、农历互转](https://github.com/jjonline/calendar.js)
+> - 仅支持自定义组件模式
+> - `date`属性传入的应该是一个 String ,如: 2019-06-27 ,而不是 new Date()
+> - 通过 `insert` 属性来确定当前的事件是 @change 还是 @confirm 。理应合并为一个事件,但是为了区分模式,现使用两个事件,这里需要注意
+> - 弹窗模式下无法阻止后面的元素滚动,如有需要阻止,请在弹窗弹出后,手动设置滚动元素为不可滚动
+
+
+### 安装方式
+
+本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。
+
+如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55)
+
+### 基本用法
+
+在 ``template`` 中使用组件
+
+```html
+
+
+
+```
+
+### 通过方法打开日历
+
+需要设置 `insert` 为 `false`
+
+```html
+
+
+
+
+```
+
+```javascript
+
+export default {
+ data() {
+ return {};
+ },
+ methods: {
+ open(){
+ this.$refs.calendar.open();
+ },
+ confirm(e) {
+ console.log(e);
+ }
+ }
+};
+
+```
+
+
+## API
+
+### Calendar Props
+
+| 属性名 | 类型 | 默认值| 说明 |
+| | |
+| date | String |- | 自定义当前时间,默认为今天 |
+| lunar | Boolean | false | 显示农历 |
+| startDate | String |- | 日期选择范围-开始日期 |
+| endDate | String |- | 日期选择范围-结束日期 |
+| range | Boolean | false | 范围选择 |
+| insert | Boolean | false | 插入模式,可选值,ture:插入模式;false:弹窗模式;默认为插入模式 |
+|clearDate |Boolean |true |弹窗模式是否清空上次选择内容 |
+| selected | Array |- | 打点,期待格式[{date: '2019-06-27', info: '签到', data: { custom: '自定义信息', name: '自定义消息头',xxx:xxx... }}] |
+|showMonth | Boolean | true | 是否显示月份为背景 |
+
+### Calendar Events
+
+| 事件名 | 说明 |返回值|
+| | | |
+| open | 弹出日历组件,`insert :false` 时生效|- |
+
+
+
diff --git a/uni_modules/uni-captcha/changelog.md b/uni_modules/uni-captcha/changelog.md
new file mode 100644
index 0000000000000000000000000000000000000000..73b16920af0d87989cf80b4924d49ee7b03d800a
--- /dev/null
+++ b/uni_modules/uni-captcha/changelog.md
@@ -0,0 +1,2 @@
+## 0.1.0(2021-03-01)
+- 调整为uni_modules目录规范
diff --git a/uni_modules/uni-captcha/package.json b/uni_modules/uni-captcha/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..0a368492e8839161b0529a683929ef54fb86d126
--- /dev/null
+++ b/uni_modules/uni-captcha/package.json
@@ -0,0 +1,80 @@
+{
+ "id": "uni-captcha",
+ "displayName": "uni-captcha",
+ "version": "0.1.0",
+ "description": "简洁、高效、灵活可配置的云端验证码模块",
+ "keywords": [
+ "uniCloud",
+ "captcha",
+ "验证码",
+ "图形验证码",
+ "人机验证"
+],
+ "repository": "https://gitee.com/dcloud/uni-captcha",
+ "engines": {
+ "HBuilderX": "^3.1.0"
+ },
+ "dcloudext": {
+ "category": [
+ "uniCloud",
+ "云函数模板"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "无",
+ "data": "无",
+ "permissions": "无"
+ },
+ "npmurl": ""
+ },
+ "uni_modules": {
+ "dependencies": [],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "u",
+ "app-nvue": "u"
+ },
+ "H5-mobile": {
+ "Safari": "u",
+ "Android Browser": "u",
+ "微信浏览器(Android)": "u",
+ "QQ浏览器(Android)": "u"
+ },
+ "H5-pc": {
+ "Chrome": "u",
+ "IE": "u",
+ "Edge": "u",
+ "Firefox": "u",
+ "Safari": "u"
+ },
+ "小程序": {
+ "微信": "u",
+ "阿里": "u",
+ "百度": "u",
+ "字节跳动": "u",
+ "QQ": "u"
+ },
+ "快应用": {
+ "华为": "u",
+ "联盟": "u"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/uni_modules/uni-captcha/readme.md b/uni_modules/uni-captcha/readme.md
new file mode 100644
index 0000000000000000000000000000000000000000..295d852f7646fb801eefa88dfdb4dddac6b14cbe
--- /dev/null
+++ b/uni_modules/uni-captcha/readme.md
@@ -0,0 +1,92 @@
+## uni 验证码验证文档
+
+> 用途:主要使用在登录、需要人机校验或其他限制调用的场景
+
+> 验证码生成、校验都在服务端。页面使用返回的 base64 显示。[云端一体登陆模板](https://ext.dcloud.net.cn/plugin?id=13)已集成,可下载体验。
+
+> 数据表使用[opendb-verify-codes](https://gitee.com/dcloud/opendb/blob/master/collection/opendb-verify-codes/collection.json)
+
+### 获取验证码@create
+
+用法:`uniCaptcha.create(Object params);`
+
+**参数说明**
+
+| 字段 | 类型 | 必填 | 默认值 | 说明 |
+| --------------- | ------ | ---- | ------- | ----------------------------------------------- |
+| scene | String | 是 | 4 | 使用场景值,用于防止不同功能的验证码混用 |
+| deviceId | String | - | - | 设备 id,如果不传,将自动从 uniCloud 上下文获取 |
+| width | Number | - | 100 | 图片宽度 |
+| height | Number | - | 40 | 图片高度 |
+| backgroundColor | String | - | #FFFAE8 | 验证码背景色 |
+| size | Number | - | 4 | 验证码长度,最多 6 个字符 |
+| noise | Number | - | 4 | 验证码干扰线条数 |
+| expiresDate | Number | - | 180 | 验证码过期时间(s) |
+
+**响应参数**
+
+| 字段 | 类型 | 说明 |
+| ------------- | ------ | ------------------- |
+| code | Number | 错误码,0 表示成功 |
+| message | String | 详细信息 |
+| captchaBase64 | String | 验证码:base64 格式 |
+
+`注意:`
+
+- 重新生成后,上条验证码作废
+
+### 校验验证码@verify
+
+用法:`uniCaptcha.verify(Object params);`
+
+**参数说明**
+
+| 字段 | 类型 | 必填 | 默认值 | 说明 |
+| -------- | ------ | ---- | ------ | ----------------------------------------------- |
+| scene | String | 是 | - | 类型,用于防止不同功能的验证码混用 |
+| captcha | String | 是 | - | 验证码 |
+| deviceId | String | - | - | 设备 id,如果不传,将自动从 uniCloud 上下文获取 |
+
+**响应参数**
+
+| 字段 | 类型 | 说明 |
+| ------- | ------ | ------------------ |
+| code | Number | 错误码,0 表示成功 |
+| message | String | 详细信息 |
+
+`注意:`
+
+- 若提示验证码失效,请重新获取
+
+### 刷新验证码@refresh
+
+用法:`uniCaptcha.refresh(Object params);`
+
+**参数说明**
+
+| 字段 | 类型 | 必填 | 默认值 | 说明 |
+| -------- | ------ | ---- | ------ | ----------------------------------------------- |
+| scene | String | 是 | - | 类型,用于防止不同功能的验证码混用 |
+| deviceId | String | - | - | 设备 id,如果不传,将自动从 uniCloud 上下文获取 |
+
+**响应参数**
+
+| 字段 | 类型 | 说明 |
+| ------------- | ------ | ------------------- |
+| code | Number | 错误码,0 表示成功 |
+| message | String | 详细信息 |
+| captchaBase64 | String | 验证码:base64 格式 |
+
+`注意:`
+
+- 支持传入 create 方法的所有参数,如果不传,则自动按照 deviceId 匹配上次生成时的配置生成新的验证码
+
+## 错误码
+
+_详细信息请查看 message 中查看_
+
+| 模块 | 模块码 | 错误代码 | 错误信息 |
+| :----: | :----: | :------: | :---------------------: |
+| 验证码 | 100 | 01 | (10001)验证码生成失败 |
+| | | 02 | (10002)验证码校验失败 |
+| | | 03 | (10003)验证码刷新失败 |
diff --git a/uni_modules/uni-captcha/uniCloud/cloudfunctions/common/uni-captcha/LICENSE.md b/uni_modules/uni-captcha/uniCloud/cloudfunctions/common/uni-captcha/LICENSE.md
new file mode 100644
index 0000000000000000000000000000000000000000..261eeb9e9f8b2b4b0d119366dda99c6fd7d35c64
--- /dev/null
+++ b/uni_modules/uni-captcha/uniCloud/cloudfunctions/common/uni-captcha/LICENSE.md
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/uni_modules/uni-captcha/uniCloud/cloudfunctions/common/uni-captcha/index.js b/uni_modules/uni-captcha/uniCloud/cloudfunctions/common/uni-captcha/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..3bc88f4e1c501200d1d9fc04417eb2a04d93e99d
--- /dev/null
+++ b/uni_modules/uni-captcha/uniCloud/cloudfunctions/common/uni-captcha/index.js
@@ -0,0 +1 @@
+"use strict";var t,e=(t=require("fs"))&&"object"==typeof t&&"default"in t?t.default:t,n="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function r(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}function o(t,e){return t(e={exports:{}},e.exports),e.exports}var i=o((function(t,e){Object.defineProperty(e,"__esModule",{value:!0}),e.font16x32=e.font12x24=e.font8x16=void 0;var n="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";e.font8x16={w:8,h:16,fonts:n,data:[[0,0,0,0,0,0,0,60,66,30,34,66,66,63,0,0],[0,0,0,192,64,64,64,88,100,66,66,66,100,88,0,0],[0,0,0,0,0,0,0,28,34,64,64,64,34,28,0,0],[0,0,0,6,2,2,2,30,34,66,66,66,38,27,0,0],[0,0,0,0,0,0,0,60,66,126,64,64,66,60,0,0],[0,0,0,15,17,16,16,126,16,16,16,16,16,124,0,0],[0,0,0,0,0,0,0,62,68,68,56,64,60,66,66,60],[0,0,0,192,64,64,64,92,98,66,66,66,66,231,0,0],[0,0,0,48,48,0,0,112,16,16,16,16,16,124,0,0],[0,0,0,12,12,0,0,28,4,4,4,4,4,4,68,120],[0,0,0,192,64,64,64,78,72,80,104,72,68,238,0,0],[0,0,0,112,16,16,16,16,16,16,16,16,16,124,0,0],[0,0,0,0,0,0,0,254,73,73,73,73,73,237,0,0],[0,0,0,0,0,0,0,220,98,66,66,66,66,231,0,0],[0,0,0,0,0,0,0,60,66,66,66,66,66,60,0,0],[0,0,0,0,0,0,0,216,100,66,66,66,68,120,64,224],[0,0,0,0,0,0,0,30,34,66,66,66,34,30,2,7],[0,0,0,0,0,0,0,238,50,32,32,32,32,248,0,0],[0,0,0,0,0,0,0,62,66,64,60,2,66,124,0,0],[0,0,0,0,0,16,16,124,16,16,16,16,16,12,0,0],[0,0,0,0,0,0,0,198,66,66,66,66,70,59,0,0],[0,0,0,0,0,0,0,231,66,36,36,40,16,16,0,0],[0,0,0,0,0,0,0,215,146,146,170,170,68,68,0,0],[0,0,0,0,0,0,0,110,36,24,24,24,36,118,0,0],[0,0,0,0,0,0,0,231,66,36,36,40,24,16,16,224],[0,0,0,0,0,0,0,126,68,8,16,16,34,126,0,0],[0,0,0,16,16,24,40,40,36,60,68,66,66,231,0,0],[0,0,0,248,68,68,68,120,68,66,66,66,68,248,0,0],[0,0,0,62,66,66,128,128,128,128,128,66,68,56,0,0],[0,0,0,248,68,66,66,66,66,66,66,66,68,248,0,0],[0,0,0,252,66,72,72,120,72,72,64,66,66,252,0,0],[0,0,0,252,66,72,72,120,72,72,64,64,64,224,0,0],[0,0,0,60,68,68,128,128,128,142,132,68,68,56,0,0],[0,0,0,231,66,66,66,66,126,66,66,66,66,231,0,0],[0,0,0,124,16,16,16,16,16,16,16,16,16,124,0,0],[0,0,0,62,8,8,8,8,8,8,8,8,8,8,136,240],[0,0,0,238,68,72,80,112,80,72,72,68,68,238,0,0],[0,0,0,224,64,64,64,64,64,64,64,64,66,254,0,0],[0,0,0,238,108,108,108,108,84,84,84,84,84,214,0,0],[0,0,0,199,98,98,82,82,74,74,74,70,70,226,0,0],[0,0,0,56,68,130,130,130,130,130,130,130,68,56,0,0],[0,0,0,252,66,66,66,66,124,64,64,64,64,224,0,0],[0,0,0,56,68,130,130,130,130,130,178,202,76,56,6,0],[0,0,0,252,66,66,66,124,72,72,68,68,66,227,0,0],[0,0,0,62,66,66,64,32,24,4,2,66,66,124,0,0],[0,0,0,254,146,16,16,16,16,16,16,16,16,56,0,0],[0,0,0,231,66,66,66,66,66,66,66,66,66,60,0,0],[0,0,0,231,66,66,68,36,36,40,40,24,16,16,0,0],[0,0,0,214,146,146,146,146,170,170,108,68,68,68,0,0],[0,0,0,231,66,36,36,24,24,24,36,36,66,231,0,0],[0,0,0,238,68,68,40,40,16,16,16,16,16,56,0,0],[0,0,0,126,132,4,8,8,16,32,32,66,66,252,0,0],[0,0,0,24,36,66,66,66,66,66,66,66,36,24,0,0],[0,0,0,16,112,16,16,16,16,16,16,16,16,124,0,0],[0,0,0,60,66,66,66,4,4,8,16,32,66,126,0,0],[0,0,0,60,66,66,4,24,4,2,2,66,68,56,0,0],[0,0,0,4,12,20,36,36,68,68,126,4,4,30,0,0],[0,0,0,126,64,64,64,88,100,2,2,66,68,56,0,0],[0,0,0,28,36,64,64,88,100,66,66,66,36,24,0,0],[0,0,0,126,68,68,8,8,16,16,16,16,16,16,0,0],[0,0,0,60,66,66,66,36,24,36,66,66,66,60,0,0],[0,0,0,24,36,66,66,66,38,26,2,2,36,56,0,0]]},e.font12x24={w:12,h:24,fonts:n,data:[[0,0,0,0,0,0,0,0,0,0,15,48,48,7,28,48,96,96,96,113,62,0,0,0,0,0,0,0,0,0,0,0,0,0,128,192,192,192,192,192,192,192,192,208,240,0,0,0],[0,0,0,0,16,112,48,48,48,48,51,60,56,48,48,48,48,48,48,56,47,0,0,0,0,0,0,0,0,0,0,0,0,0,128,192,96,96,96,96,96,96,64,192,128,0,0,0],[0,0,0,0,0,0,0,0,0,0,15,49,49,97,96,96,96,96,48,48,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,128,128,0,0,0,64,64,128,0,0,0,0],[0,0,0,0,0,1,0,0,0,0,30,49,48,96,96,96,96,96,32,49,30,0,0,0,0,0,0,0,64,192,192,192,192,192,192,192,192,192,192,192,192,192,192,224,128,0,0,0],[0,0,0,0,0,0,0,0,0,0,7,24,16,48,63,48,48,48,24,28,7,0,0,0,0,0,0,0,0,0,0,0,0,0,128,192,96,96,224,0,0,0,32,64,128,0,0,0],[0,0,0,0,0,3,6,12,12,12,127,12,12,12,12,12,12,12,12,12,63,0,0,0,0,0,0,0,0,192,96,96,0,0,192,0,0,0,0,0,0,0,0,0,128,0,0,0],[0,0,0,0,0,0,0,0,0,0,15,25,48,48,48,25,31,48,62,31,96,96,112,31,0,0,0,0,0,0,0,0,0,0,112,144,192,192,192,128,0,0,0,192,96,96,224,128],[0,0,0,0,16,112,48,48,48,48,55,56,48,48,48,48,48,48,48,48,121,0,0,0,0,0,0,0,0,0,0,0,0,0,128,192,192,192,192,192,192,192,192,192,224,0,0,0],[0,0,0,0,0,6,6,0,0,0,62,6,6,6,6,6,6,6,6,6,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,0,0,0],[0,0,0,0,0,1,1,0,0,0,15,1,1,1,1,1,1,1,1,1,1,1,51,62,0,0,0,0,0,128,128,0,0,0,128,128,128,128,128,128,128,128,128,128,128,128,0,0],[0,0,0,0,16,112,48,48,48,48,51,49,51,50,54,62,59,51,49,49,121,0,0,0,0,0,0,0,0,0,0,0,0,0,192,0,0,0,0,0,0,0,128,128,224,0,0,0],[0,0,0,0,2,62,6,6,6,6,6,6,6,6,6,6,6,6,6,6,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,0,0,0],[0,0,0,0,0,0,0,0,0,0,238,119,102,102,102,102,102,102,102,102,247,0,0,0,0,0,0,0,0,0,0,0,0,0,224,96,96,96,96,96,96,96,96,96,112,0,0,0],[0,0,0,0,0,0,0,0,0,0,115,60,48,48,48,48,48,48,48,48,121,0,0,0,0,0,0,0,0,0,0,0,0,0,128,192,192,192,192,192,192,192,192,192,224,0,0,0],[0,0,0,0,0,0,0,0,0,0,15,25,48,96,96,96,96,96,48,48,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,192,96,96,96,96,96,192,192,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,119,56,48,48,48,48,48,48,48,56,55,48,48,124,0,0,0,0,0,0,0,0,0,0,128,192,96,96,96,96,96,96,192,192,128,0,0,0],[0,0,0,0,0,0,0,0,0,0,30,49,48,96,96,96,96,96,32,49,30,0,0,3,0,0,0,0,0,0,0,0,0,0,64,192,192,192,192,192,192,192,192,192,192,192,192,224],[0,0,0,0,0,0,0,0,0,0,249,26,28,24,24,24,24,24,24,24,255,0,0,0,0,0,0,0,0,0,0,0,0,0,224,96,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,15,24,48,48,28,15,1,32,32,48,63,0,0,0,0,0,0,0,0,0,0,0,0,0,224,96,32,0,0,128,192,96,96,192,128,0,0,0],[0,0,0,0,0,0,4,4,12,12,127,12,12,12,12,12,12,12,12,12,7,0,0,0,0,0,0,0,0,0,0,0,0,0,128,0,0,0,0,0,0,0,64,64,128,0,0,0],[0,0,0,0,0,0,0,0,0,16,113,48,48,48,48,48,48,48,48,57,30,0,0,0,0,0,0,0,0,0,0,0,0,64,192,192,192,192,192,192,192,192,192,224,128,0,0,0],[0,0,0,0,0,0,0,0,0,0,124,56,24,24,12,12,12,7,7,7,2,0,0,0,0,0,0,0,0,0,0,0,0,0,240,96,64,64,128,128,128,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,247,99,99,103,55,53,57,57,57,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,176,32,32,32,32,192,192,192,192,128,128,0,0,0],[0,0,0,0,0,0,0,0,0,0,125,24,25,13,14,6,7,11,25,17,123,0,0,0,0,0,0,0,0,0,0,0,0,0,224,128,128,0,0,0,0,0,128,192,224,0,0,0],[0,0,0,0,0,0,0,0,0,0,125,56,24,24,13,13,13,6,6,2,4,4,40,56,0,0,0,0,0,0,0,0,0,0,224,128,128,128,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,63,33,35,3,7,6,14,12,28,24,63,0,0,0,0,0,0,0,0,0,0,0,0,0,192,128,128,0,0,0,0,32,32,96,192,0,0,0],[0,0,0,0,0,6,6,14,11,11,19,17,17,17,31,32,32,32,32,96,240,0,0,0,0,0,0,0,0,0,0,0,0,0,0,128,128,128,128,192,192,192,96,96,240,0,0,0],[0,0,0,0,0,255,97,96,96,96,96,97,127,96,96,96,96,96,96,96,255,0,0,0,0,0,0,0,0,0,128,192,192,192,192,128,0,192,64,96,96,96,96,192,128,0,0,0],[0,0,0,0,0,7,24,48,48,32,96,96,96,96,96,96,96,48,48,24,15,0,0,0,0,0,0,0,0,224,96,32,32,0,0,0,0,0,0,0,32,32,64,128,0,0,0,0],[0,0,0,0,0,254,97,96,96,96,96,96,96,96,96,96,96,96,96,99,254,0,0,0,0,0,0,0,0,0,128,192,192,96,96,96,96,96,96,96,96,192,192,128,0,0,0,0],[0,0,0,0,0,255,96,96,96,96,97,97,127,97,97,96,96,96,96,96,255,0,0,0,0,0,0,0,0,192,64,32,0,0,0,0,0,0,0,0,0,32,32,64,192,0,0,0],[0,0,0,0,0,255,96,96,96,96,97,97,127,97,97,96,96,96,96,96,240,0,0,0,0,0,0,0,0,192,192,32,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,15,24,48,48,32,96,96,96,96,99,96,96,48,48,24,15,0,0,0,0,0,0,0,0,64,192,64,64,0,0,0,0,0,240,192,192,192,192,192,0,0,0,0],[0,0,0,0,0,240,96,96,96,96,96,96,127,96,96,96,96,96,96,96,240,0,0,0,0,0,0,0,0,240,96,96,96,96,96,96,224,96,96,96,96,96,96,96,240,0,0,0],[0,0,0,0,0,63,6,6,6,6,6,6,6,6,6,6,6,6,6,6,63,0,0,0,0,0,0,0,0,192,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,0,0,0],[0,0,0,0,0,15,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,97,99,62,0,0,0,0,0,240,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,0,0],[0,0,0,0,0,243,96,97,98,98,100,108,124,118,103,99,99,97,96,96,241,0,0,0,0,0,0,0,0,224,128,0,0,0,0,0,0,0,0,0,128,128,192,224,240,0,0,0],[0,0,0,0,0,240,96,96,96,96,96,96,96,96,96,96,96,96,96,96,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,32,64,192,0,0,0],[0,0,0,0,0,240,112,112,112,89,89,89,89,90,78,78,78,78,68,68,228,0,0,0,0,0,0,0,0,240,224,224,224,96,96,96,96,96,96,96,96,96,96,96,240,0,0,0],[0,0,0,0,0,224,112,112,88,88,76,70,70,67,67,65,64,64,64,64,224,0,0,0,0,0,0,0,0,112,32,32,32,32,32,32,32,32,32,160,224,224,96,96,32,0,0,0],[0,0,0,0,0,15,25,48,48,96,96,96,96,96,96,96,96,48,48,25,15,0,0,0,0,0,0,0,0,0,128,192,64,96,96,96,96,96,96,96,96,64,192,128,0,0,0,0],[0,0,0,0,0,255,96,96,96,96,96,96,96,127,96,96,96,96,96,96,240,0,0,0,0,0,0,0,0,128,192,96,96,96,96,96,192,128,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,15,25,48,48,96,96,96,96,96,96,96,110,50,49,17,15,1,0,0,0,0,0,0,0,0,128,192,64,96,96,96,96,96,96,96,96,64,192,128,128,224,192,0],[0,0,0,0,0,255,96,96,96,96,96,96,127,102,99,99,97,97,96,96,240,0,0,0,0,0,0,0,0,128,192,96,96,96,96,192,0,0,0,0,128,128,192,192,112,0,0,0],[0,0,0,0,0,31,48,96,96,96,112,60,15,3,0,0,64,64,96,112,79,0,0,0,0,0,0,0,0,32,224,32,32,0,0,0,0,192,192,96,96,96,96,192,128,0,0,0],[0,0,0,0,0,127,70,134,134,6,6,6,6,6,6,6,6,6,6,6,15,0,0,0,0,0,0,0,0,224,32,16,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,240,96,96,96,96,96,96,96,96,96,96,96,96,96,48,31,0,0,0,0,0,0,0,0,112,32,32,32,32,32,32,32,32,32,32,32,32,32,64,128,0,0,0],[0,0,0,0,0,248,112,48,48,48,48,24,24,24,24,13,13,13,15,6,6,0,0,0,0,0,0,0,0,240,96,64,64,64,128,128,128,128,128,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,247,102,102,102,102,103,55,55,59,59,59,59,57,17,17,17,0,0,0,0,0,0,0,0,112,32,32,64,64,64,64,64,128,128,128,128,128,0,0,0,0,0,0],[0,0,0,0,0,121,48,24,24,25,13,14,6,6,7,11,11,25,17,48,121,0,0,0,0,0,0,0,0,224,192,128,128,0,0,0,0,0,0,0,128,128,128,192,224,0,0,0],[0,0,0,0,0,248,112,48,48,24,24,13,13,14,6,6,6,6,6,6,31,0,0,0,0,0,0,0,0,240,96,64,128,128,128,0,0,0,0,0,0,0,0,0,128,0,0,0],[0,0,0,0,0,63,32,65,1,3,3,3,6,6,12,12,24,24,56,48,127,0,0,0,0,0,0,0,0,224,192,192,128,128,0,0,0,0,0,0,0,32,32,64,192,0,0,0],[0,0,0,0,0,15,25,48,48,96,96,96,96,96,96,96,96,48,48,25,15,0,0,0,0,0,0,0,0,0,128,192,192,96,96,96,96,96,96,96,96,192,192,128,0,0,0,0],[0,0,0,0,0,2,6,62,6,6,6,6,6,6,6,6,6,6,6,6,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,0,0,0],[0,0,0,0,0,31,33,64,96,96,0,1,1,3,4,8,16,32,64,127,127,0,0,0,0,0,0,0,0,0,128,192,192,192,192,128,128,0,0,0,64,64,64,192,192,0,0,0],[0,0,0,0,0,30,35,97,97,97,1,3,14,1,0,0,96,96,96,33,31,0,0,0,0,0,0,0,0,0,0,128,128,128,128,0,0,128,128,192,192,192,192,128,0,0,0,0],[0,0,0,0,0,1,3,3,5,9,9,17,33,33,65,127,1,1,1,1,7,0,0,0,0,0,0,0,128,128,128,128,128,128,128,128,128,128,128,224,128,128,128,128,224,0,0,0],[0,0,0,0,0,63,63,32,32,32,32,47,49,32,0,0,96,96,65,33,31,0,0,0,0,0,0,0,0,192,192,0,0,0,0,0,128,192,192,192,192,192,128,128,0,0,0,0],[0,0,0,0,0,7,24,48,48,32,96,103,104,112,96,96,96,32,48,24,15,0,0,0,0,0,0,0,0,128,192,192,0,0,0,128,192,96,96,96,96,96,64,192,0,0,0,0],[0,0,0,0,0,31,63,48,32,32,0,1,1,2,2,2,6,6,6,6,6,0,0,0,0,0,0,0,0,224,224,64,128,128,128,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,31,48,96,96,96,112,60,15,51,32,96,96,96,96,48,15,0,0,0,0,0,0,0,0,128,192,96,96,96,64,192,0,128,192,96,96,96,96,192,128,0,0,0],[0,0,0,0,0,15,48,48,96,96,96,96,96,49,30,0,0,0,48,49,30,0,0,0,0,0,0,0,0,0,128,192,64,96,96,96,224,96,96,96,192,192,128,128,0,0,0,0]]},e.font16x32={w:16,h:32,fonts:n,data:[[0,0,0,0,0,0,0,0,0,0,0,0,0,15,24,48,48,0,1,14,56,48,96,96,96,48,31,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,96,48,48,48,240,48,48,48,48,48,50,242,28,0,0,0,0,0],[0,0,0,0,0,8,120,24,24,24,24,24,24,24,27,28,28,24,24,24,24,24,24,24,28,30,19,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,240,24,12,6,6,6,6,6,6,6,4,12,24,224,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,3,14,24,24,48,48,48,48,48,48,24,24,12,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,224,48,24,24,24,0,0,0,0,4,4,8,16,224,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,7,12,24,24,48,48,48,48,48,48,16,24,12,7,0,0,0,0,0,0,0,0,0,0,8,120,24,24,24,24,24,24,216,56,24,24,24,24,24,24,24,24,24,56,94,144,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,3,12,24,16,48,48,63,48,48,48,24,24,14,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,224,48,24,8,12,12,252,0,0,0,4,8,24,224,0,0,0,0,0],[0,0,0,0,0,0,0,1,1,3,3,3,3,63,3,3,3,3,3,3,3,3,3,3,3,3,31,0,0,0,0,0,0,0,0,0,0,0,124,195,3,3,0,0,0,248,0,0,0,0,0,0,0,0,0,0,0,0,240,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,3,12,8,24,24,24,8,12,15,24,24,15,15,16,48,48,48,28,7,0,0,0,0,0,0,0,0,0,0,0,0,0,238,54,24,24,24,24,24,48,224,0,0,240,252,14,6,6,6,28,240],[0,0,0,0,0,8,120,24,24,24,24,24,24,25,27,28,24,24,24,24,24,24,24,24,24,24,126,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,240,24,12,12,12,12,12,12,12,12,12,12,12,63,0,0,0,0,0],[0,0,0,0,0,0,1,1,1,0,0,0,0,31,1,1,1,1,1,1,1,1,1,1,1,1,31,0,0,0,0,0,0,0,0,0,0,0,192,192,192,0,0,0,128,128,128,128,128,128,128,128,128,128,128,128,128,128,248,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,24,15,0,0,0,0,0,0,28,28,28,0,0,0,8,248,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,48,96,192],[0,0,0,0,0,8,120,24,24,24,24,24,24,24,24,24,24,24,25,27,28,24,24,24,24,24,126,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,124,48,96,192,128,128,128,192,224,96,48,56,24,62,0,0,0,0,0],[0,0,0,0,0,0,31,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,31,0,0,0,0,0,0,0,0,0,0,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,248,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,16,119,57,49,49,49,49,49,49,49,49,49,49,49,123,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,56,204,140,140,140,140,140,140,140,140,140,140,140,222,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,8,120,27,28,24,24,24,24,24,24,24,24,24,24,126,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,240,24,12,12,12,12,12,12,12,12,12,12,12,63,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,3,14,8,24,48,48,48,48,48,48,24,24,12,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,224,56,12,12,6,6,6,6,6,6,12,12,24,224,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,8,121,26,28,24,24,24,24,24,24,24,24,28,30,25,24,24,24,24,126,0,0,0,0,0,0,0,0,0,0,0,0,0,240,24,12,4,6,6,6,6,6,6,12,12,24,224,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,3,12,24,24,48,48,48,48,48,48,16,24,12,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,196,60,28,12,12,12,12,12,12,12,12,28,60,204,12,12,12,12,63],[0,0,0,0,0,0,0,0,0,0,0,0,6,126,6,6,7,7,6,6,6,6,6,6,6,6,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,60,102,134,0,0,0,0,0,0,0,0,0,0,224,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,7,12,24,24,24,14,7,1,0,32,32,48,56,55,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,228,28,12,4,0,0,192,240,56,12,12,12,24,240,0,0,0,0,0],[0,0,0,0,0,0,0,0,1,1,1,3,7,63,3,3,3,3,3,3,3,3,3,3,3,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,248,0,0,0,0,0,0,0,0,0,4,4,136,240,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,8,120,24,24,24,24,24,24,24,24,24,24,24,12,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,60,12,12,12,12,12,12,12,12,12,12,28,47,200,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,126,24,24,28,12,12,14,6,6,7,3,3,3,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,60,24,16,16,32,32,64,64,64,128,128,128,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,251,113,48,49,49,25,25,26,26,14,14,14,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,239,198,196,196,196,200,200,104,104,112,112,112,32,32,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,63,14,14,7,3,3,1,1,2,6,4,8,24,124,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,124,16,32,32,64,128,192,192,224,96,48,48,24,126,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,126,24,24,12,12,12,6,6,3,3,3,1,1,1,1,1,1,50,60,0,0,0,0,0,0,0,0,0,0,0,0,0,62,24,16,16,16,32,32,32,64,64,64,128,128,128,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,63,48,32,32,0,1,1,3,7,14,12,28,56,63,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,248,48,112,96,192,192,128,0,0,4,4,12,24,248,0,0,0,0,0],[0,0,0,0,0,0,3,3,3,2,6,4,4,4,12,8,8,8,31,16,16,16,48,32,32,96,248,0,0,0,0,0,0,0,0,0,0,128,128,128,128,128,192,192,192,192,96,96,96,96,240,48,48,48,48,24,24,24,62,0,0,0,0,0],[0,0,0,0,0,0,127,24,24,24,24,24,24,24,24,31,24,24,24,24,24,24,24,24,24,24,127,0,0,0,0,0,0,0,0,0,0,0,224,56,28,12,12,12,12,24,48,224,24,12,4,6,6,6,6,6,12,24,240,0,0,0,0,0],[0,0,0,0,0,0,3,6,8,24,48,48,32,96,96,96,96,96,96,96,96,48,48,48,24,12,3,0,0,0,0,0,0,0,0,0,0,0,228,28,12,4,2,2,0,0,0,0,0,0,0,0,0,2,2,4,12,24,224,0,0,0,0,0],[0,0,0,0,0,0,127,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,127,0,0,0,0,0,0,0,0,0,0,0,192,112,24,12,12,12,6,6,6,6,6,6,6,6,6,12,12,8,24,112,192,0,0,0,0,0],[0,0,0,0,0,0,127,24,24,24,24,24,24,24,24,31,24,24,24,24,24,24,24,24,24,24,127,0,0,0,0,0,0,0,0,0,0,0,252,12,4,6,2,0,16,16,48,240,48,16,16,0,0,0,2,2,4,12,252,0,0,0,0,0],[0,0,0,0,0,0,127,24,24,24,24,24,24,24,24,31,24,24,24,24,24,24,24,24,24,24,126,0,0,0,0,0,0,0,0,0,0,0,254,14,2,3,1,0,8,8,24,248,24,8,8,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,3,14,8,24,48,48,32,96,96,96,96,96,96,96,96,48,48,24,24,12,3,0,0,0,0,0,0,0,0,0,0,0,200,56,8,8,4,4,0,0,0,0,0,0,63,12,12,12,12,12,12,16,224,0,0,0,0,0],[0,0,0,0,0,0,252,48,48,48,48,48,48,48,48,48,63,48,48,48,48,48,48,48,48,48,252,0,0,0,0,0,0,0,0,0,0,0,126,24,24,24,24,24,24,24,24,24,248,24,24,24,24,24,24,24,24,24,126,0,0,0,0,0],[0,0,0,0,0,0,31,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,31,0,0,0,0,0,0,0,0,0,0,0,248,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,248,0,0,0,0,0],[0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,112,112,113,63,0,0,0,0,0,0,254,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,192,128,0],[0,0,0,0,0,0,126,24,24,24,24,24,24,25,25,27,29,28,24,24,24,24,24,24,24,24,126,0,0,0,0,0,0,0,0,0,0,0,62,24,16,32,96,64,128,128,128,128,192,192,224,96,112,48,56,24,12,12,63,0,0,0,0,0],[0,0,0,0,0,0,126,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,4,12,252,0,0,0,0,0],[0,0,0,0,0,0,248,56,56,56,56,44,44,44,44,46,38,38,38,38,35,35,35,35,35,33,249,0,0,0,0,0,0,0,0,0,0,0,31,28,28,28,60,44,44,44,108,76,76,76,76,140,140,140,140,12,12,12,63,0,0,0,0,0],[0,0,0,0,0,0,248,56,60,44,44,46,38,39,35,35,33,33,32,32,32,32,32,32,32,32,248,0,0,0,0,0,0,0,0,0,0,0,62,8,8,8,8,8,8,8,8,136,136,200,200,232,104,120,56,56,56,24,24,0,0,0,0,0],[0,0,0,0,0,0,3,12,24,16,48,48,96,96,96,96,96,96,96,96,96,48,48,16,24,12,3,0,0,0,0,0,0,0,0,0,0,0,192,48,24,8,12,12,6,6,6,6,6,6,6,6,6,4,12,8,24,48,192,0,0,0,0,0],[0,0,0,0,0,0,127,24,24,24,24,24,24,24,24,24,31,24,24,24,24,24,24,24,24,24,126,0,0,0,0,0,0,0,0,0,0,0,240,24,12,6,6,6,6,6,12,24,240,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,3,12,24,48,48,48,96,96,96,96,96,96,96,96,96,39,52,56,24,12,3,0,0,0,0,0,0,0,0,0,0,0,192,48,24,8,12,4,6,6,6,6,6,6,6,6,6,134,204,76,104,112,224,50,62,28,0,0],[0,0,0,0,0,0,127,24,24,24,24,24,24,24,24,31,25,24,24,24,24,24,24,24,24,24,126,0,0,0,0,0,0,0,0,0,0,0,224,56,28,12,12,12,12,24,48,224,192,192,224,96,96,112,48,48,56,24,30,0,0,0,0,0],[0,0,0,0,0,0,7,12,24,48,48,48,48,24,30,7,1,0,0,0,0,32,32,16,24,28,19,0,0,0,0,0,0,0,0,0,0,0,228,28,12,4,4,0,0,0,0,192,240,120,28,14,6,6,6,6,12,24,240,0,0,0,0,0],[0,0,0,0,0,0,63,49,33,65,65,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,0,0,0,0,0,0,0,0,0,0,0,252,132,134,130,130,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,224,0,0,0,0,0],[0,0,0,0,0,0,252,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,16,28,7,0,0,0,0,0,0,0,0,0,0,0,62,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,16,32,192,0,0,0,0,0],[0,0,0,0,0,0,124,24,24,24,12,12,12,12,6,6,6,7,3,3,3,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,31,4,4,4,8,8,8,8,16,16,16,48,32,32,32,192,192,192,192,128,128,0,0,0,0,0],[0,0,0,0,0,0,251,97,97,97,49,48,49,49,49,49,50,26,26,26,28,28,28,12,8,8,8,0,0,0,0,0,0,0,0,0,0,0,207,134,132,132,132,132,196,200,200,200,200,72,104,112,112,112,112,48,32,32,32,0,0,0,0,0],[0,0,0,0,0,0,126,24,28,12,12,14,6,7,3,3,1,1,2,2,4,4,8,8,16,16,124,0,0,0,0,0,0,0,0,0,0,0,124,16,16,32,32,64,64,128,128,128,128,192,192,224,96,96,48,48,24,24,62,0,0,0,0,0],[0,0,0,0,0,0,126,56,24,24,12,12,14,6,6,3,3,3,1,1,1,1,1,1,1,1,7,0,0,0,0,0,0,0,0,0,0,0,62,8,8,16,16,48,32,32,64,64,64,128,128,128,128,128,128,128,128,128,224,0,0,0,0,0],[0,0,0,0,0,0,31,24,16,32,32,0,0,0,1,1,3,3,7,6,14,12,28,24,56,48,127,0,0,0,0,0,0,0,0,0,0,0,252,24,24,48,112,96,224,192,192,128,128,0,0,0,0,0,4,4,8,24,248,0,0,0,0,0],[0,0,0,0,0,0,3,6,12,24,24,24,48,48,48,48,48,48,48,48,48,24,24,24,12,6,3,0,0,0,0,0,0,0,0,0,0,0,224,48,24,12,12,4,6,6,6,6,6,6,6,6,6,4,12,12,24,48,224,0,0,0,0,0],[0,0,0,0,0,0,0,1,31,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,31,0,0,0,0,0,0,0,0,0,0,0,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,192,248,0,0,0,0,0],[0,0,0,0,0,0,7,8,16,32,32,48,48,0,0,0,0,0,0,1,2,4,8,16,32,63,63,0,0,0,0,0,0,0,0,0,0,0,224,56,24,12,12,12,12,12,24,16,32,64,128,0,0,4,4,4,12,248,248,0,0,0,0,0],[0,0,0,0,0,0,7,24,48,48,48,48,0,0,0,3,0,0,0,0,0,48,48,48,48,24,7,0,0,0,0,0,0,0,0,0,0,0,192,112,48,24,24,24,24,48,96,192,112,24,8,12,12,12,12,8,24,48,192,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,1,1,2,6,4,8,8,16,32,32,127,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,48,112,112,240,112,112,112,112,112,112,112,112,112,112,254,112,112,112,112,112,112,254,0,0,0,0],[0,0,0,0,0,0,15,15,8,8,8,16,16,19,20,24,16,0,0,0,0,48,48,32,32,16,15,0,0,0,0,0,0,0,0,0,0,0,252,252,0,0,0,0,0,224,48,24,8,12,12,12,12,12,12,24,24,48,192,0,0,0,0,0],[0,0,0,0,0,0,1,3,4,8,24,24,16,48,49,54,60,56,48,48,48,48,24,24,12,6,3,0,0,0,0,0,0,0,0,0,0,0,240,8,12,12,0,0,0,0,240,24,12,6,6,6,6,6,6,4,12,24,224,0,0,0,0,0],[0,0,0,0,0,0,31,31,56,48,32,32,0,0,0,0,0,0,1,1,1,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,252,252,8,16,16,32,32,64,64,128,128,128,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,7,12,24,48,48,48,56,28,14,7,13,24,48,96,96,96,96,96,48,24,7,0,0,0,0,0,0,0,0,0,0,0,224,48,24,12,12,12,12,24,16,224,224,112,56,28,12,12,12,12,24,48,192,0,0,0,0,0],[0,0,0,0,0,0,7,24,48,48,96,96,96,96,96,96,48,24,15,0,0,0,0,48,48,48,15,0,0,0,0,0,0,0,0,0,0,0,192,32,16,24,8,12,12,12,12,28,60,108,140,12,24,24,24,48,96,192,128,0,0,0,0,0]]}}));r(i);i.font16x32,i.font12x24,i.font8x16;var a=o((function(t,r){var o=n&&n.__awaiter||function(t,e,n,r){return new(n||(n=Promise))((function(o,i){function a(t){try{s(r.next(t))}catch(t){i(t)}}function c(t){try{s(r.throw(t))}catch(t){i(t)}}function s(t){var e;t.done?o(t.value):(e=t.value,e instanceof n?e:new n((function(t){t(e)}))).then(a,c)}s((r=r.apply(t,e||[])).next())}))},a=n&&n.__generator||function(t,e){var n,r,o,i,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:c(0),throw:c(1),return:c(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function c(i){return function(c){return function(i){if(n)throw new TypeError("Generator is already executing.");for(;a;)try{if(n=1,r&&(o=2&i[0]?r.return:i[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,i[1])).done)return o;switch(r=0,o&&(i=[2&i[0],o.value]),i[0]){case 0:case 1:o=i;break;case 4:return a.label++,{value:i[1],done:!1};case 5:a.label++,r=i[1],i=[0];continue;case 7:i=a.ops.pop(),a.trys.pop();continue;default:if(!(o=a.trys,(o=o.length>0&&o[o.length-1])||6!==i[0]&&2!==i[0])){a=0;continue}if(3===i[0]&&(!o||i[1]>o[0]&&i[1]>16&255,green:n>>8&255,blue:255&n})},t.prototype.drawPointRGB=function(t,e,n){if(!(t>=this.w||e>=this.h||t<0||e<0)){var r=this.h-e-1,o=54+3*t+this._lineByteNum*r;this._data.writeUInt8(n.blue,o),this._data.writeUInt8(n.green,o+1),this._data.writeUInt8(n.red,o+2)}},t.prototype.getPointRGB=function(t,e){if(t>=this.w||e>=this.h||t<0||e<0)throw new Error("out of range");var n=this.h-e-1,r=54+3*t+this._lineByteNum*n;return{blue:this._data.readUInt8(r),green:this._data.readUInt8(r+1),red:this._data.readUInt8(r+2)}},t.prototype.drawLineH=function(t,e,n,r){if(t>e){var o=e;e=t,t=o}for(;t<=e;t++)this.drawPoint(t,n,r)},t.prototype.drawLineV=function(t,e,n,r){if(t>e){var o=e;e=t,t=o}for(;t<=e;t++)this.drawPoint(n,t,r)},t.prototype.drawLine=function(t,e,n,r,o){var i=t,a=e,c=n>t?n-t:t-n,s=r>e?r-e:e-r,d=!1,f=n>t?1:-1,u=r>e?1:-1;if(s>c){var h=c;c=s,s=h,d=!0}for(var l=(s<<1)-c,w=0;w<=c;w++)this.drawPoint(i,a,o),l>=0&&(d?i+=f:a+=u,l-=c<<1),d?a+=u:i+=f,l+=s<<1},t.prototype.drawRect=function(t,e,n,r,o){var i=t+n-1,a=e+r-1;this.drawLineH(t,i,e,o),this.drawLineH(t,i,a,o),this.drawLineV(e,a,t,o),this.drawLineV(e,a,i,o)},t.prototype.fillRect=function(t,e,n,r,o){var i=t+n-1,a=e+r-1;if(t>i){var c=i;i=t,t=c}if(e>a){c=a;a=e,e=c}for(;e<=a;e++)for(var s=t;s<=i;s++)this.drawPoint(s,e,o)},t.prototype.drawCircle=function(t,e,n,r){for(var o=0,i=n,a=3-2*n;o0;f<<=1)128&f&&this.drawPoint(c,a,o),c++;++a-n>=r.h&&(a=n,e+=8)}},t.prototype.drawString=function(t,e,n,r,o){for(var i=0,a=t;i(t.includes(r)&&n.push(e[r]),n),[]);return n[Math.random()*n.length|0]}function u(t={}){const e=["small","medium","big"],n={backgroundColor:16775912,size:4,noise:4,width:100,height:40,fontSize:["medium","big"]};let{backgroundColor:r,size:o,noise:i,width:a,height:s,fontSize:f}=Object.assign({},n,t);"string"==typeof r&&(r=r.replace("#","0x")),f instanceof Array||(f=[]),f.filter(t=>e.includes(t)),f.length||(f=n.fontSize),o=o>6?6:o;const u=new c(a,s);u.fillRect(0,0,a,s,r),function(t,e){for(let n=1;n>16,r=e>>8&255,o=255&e,i=Math.max(n,r,o),a=Math.min(n,r,o);return(i+a)/510}(t):1;let o,i;r>=.5?(o=Math.round(100*r)-45,i=Math.round(100*r)-25):(o=Math.round(100*r)+25,i=Math.round(100*r)+45);const a=h(o,i)/100,c=a<.5?a*(a+n):a+n-a*n,s=2*a-c,d=Math.floor(255*w(s,c,e+1/3)),f=Math.floor(255*w(s,c,e));return"#"+(Math.floor(255*w(s,c,e-1/3))|f<<8|d<<16|1<<24).toString(16).slice(1)};function w(t,e,n){return 6*(n=(n+1)%1)<1?t+(e-t)*n*6:2*n<1?e:3*n<2?t+(e-t)*(2/3-n)*6:t}const p=Object.prototype.toString;function g(t){return"[object Object]"===p.call(t)}function y(){"development"===process.env.NODE_ENV&&console.log(...arguments)}const v=async function(){};function m(t){return v.constructor===t.constructor?async function(){const e=await t.apply(this,arguments);return g(e)&&e.msg&&(e.message=e.msg),e}:function(){const e=t.apply(this,arguments);return g(e)&&e.msg&&(e.message=e.msg),e}}const b=uniCloud.database().collection("opendb-verify-codes"),_={};var I=Object.freeze({__proto__:null,create:async function(t={}){let{scene:e,expiresDate:n,deviceId:r,...o}=t;if(r=r||__ctx__.DEVICEID,!r)throw new Error("deviceId不可为空");if(!e)throw new Error("scene验证码场景不可为空");try{const{text:i,base64:a}=u(o),c=await this.setVerifyCode({deviceId:r,code:i,expiresDate:n,scene:e});return c.code>0?{...c,code:10001}:(_[r]=t,{code:0,msg:"验证码获取成功",captchaBase64:a})}catch(t){return{code:10001,msg:"验证码生成失败:"+t.message}}},verify:async function({deviceId:t,captcha:e,scene:n}){if(!(t=t||__ctx__.DEVICEID))throw new Error("deviceId不可为空");if(!n)throw new Error("scene验证码场景不可为空");try{const r=await this.verifyCode({deviceId:t,code:e,scene:n});return r.code>0?{...r,code:10002}:{code:0,msg:"验证码通过"}}catch(t){return{code:10002,msg:"验证码校验失败:"+t.message}}},refresh:async function(t={}){let{scene:e,expiresDate:n,deviceId:r,...o}=t;if(r=r||__ctx__.DEVICEID,!r)throw new Error("deviceId不可为空");if(!e)throw new Error("scene验证码场景不可为空");const i=await b.where({deviceId:r,scene:e,state:0}).orderBy("created_date","desc").limit(1).get();if(i&&i.data&&i.data.length>0){const t=i.data[0];await b.doc(t._id).update({state:2});let a={};Object.keys(o).length>0&&(_[r]=Object.assign({},_[r],o)),a=_[r];let c={};try{c=await this.create(Object.assign({},a,{deviceId:r,scene:e,expiresDate:n}))}catch(t){return{code:50403,msg:t.message}}return c.code>0?{...c,code:10003}:{code:0,msg:"验证码刷新成功",captchaBase64:c.captchaBase64}}return{code:10003,msg:"验证码刷新失败:无此设备信息,请重新获取"}},setVerifyCode:async function({deviceId:t,code:e,expiresDate:n,scene:r}){if(!t)return{code:10101,msg:"deviceId不可为空"};if(!e)return{code:10102,msg:"验证码不可为空"};n||(n=180);const o=Date.now(),i={deviceId:t,scene:r,code:e.toLocaleLowerCase(),state:0,ip:__ctx__.CLIENTIP,created_date:o,expired_date:o+1e3*n};return y("addRes",await b.add(i)),{code:0,deviceId:t}},verifyCode:async function({deviceId:t,code:e,scene:n}){if(!t)return{code:10101,msg:"deviceId不可为空"};if(!e)return{code:10102,msg:"验证码不可为空"};const r=Date.now(),o={deviceId:t,scene:n,code:e.toLocaleLowerCase(),state:0},i=await b.where(o).orderBy("created_date","desc").limit(1).get();if(y("verifyRecord:",i),i&&i.data&&i.data.length>0){const t=i.data[0];if(t.expired_date
+
+
+
+
+
+
+
+
+ {{ title }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ title }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/uni-card/package.json b/uni_modules/uni-card/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..902399c6cd506a38a6dc6885c0e1851baa4885f2
--- /dev/null
+++ b/uni_modules/uni-card/package.json
@@ -0,0 +1,81 @@
+{
+ "id": "uni-card",
+ "displayName": "Card 卡片",
+ "version": "1.1.6",
+ "description": "Card 组件,提供常见的卡片样式。",
+ "keywords": [
+ "card",
+ "uni-ui",
+ "卡片"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "前端组件",
+ "通用组件"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "无",
+ "data": "无",
+ "permissions": "无"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": [],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "微信浏览器(Android)": "y",
+ "QQ浏览器(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "小程序": {
+ "微信": "y",
+ "阿里": "y",
+ "百度": "y",
+ "字节跳动": "y",
+ "QQ": "y"
+ },
+ "快应用": {
+ "华为": "u",
+ "联盟": "u"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/uni_modules/uni-card/readme.md b/uni_modules/uni-card/readme.md
new file mode 100644
index 0000000000000000000000000000000000000000..1b8f63cfe33ba03484a1cab8597a6540e06344cc
--- /dev/null
+++ b/uni_modules/uni-card/readme.md
@@ -0,0 +1,97 @@
+
+
+## Card 卡片
+> 代码块: `uCard`
+
+
+卡片视图组件。
+
+### 安装方式
+
+本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。
+
+如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55)
+
+> 为了避免错误使用,给大家带来不好的开发体验,请在使用组件前仔细阅读下面的注意事项,可以帮你避免一些错误。
+> - 因为平台兼容问题 , 目前 APP-NVUE 安卓平台下不支持阴影
+
+
+### 基本用法
+
+在 ``template`` 中使用组件
+
+```html
+
+
+ 内容主体,可自定义内容及样式
+
+
+
+
+
+
+
+
+
+ uni-app 是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可编译到iOS、Android、H5、以及各种小程序等多个平台。即使不跨端,uni-app同时也是更好的小程序开发框架。
+
+
+
+
+ uni-app 是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可编译到iOS、Android、H5、以及各种小程序等多个平台。即使不跨端,uni-app同时也是更好的小程序开发框架。
+
+
+
+
+ 默认内容
+
+
+
+
+```
+
+## API
+
+### Card Props
+
+|属性名 |类型 |默认值 |说明 |
+|:-: |:-: |:-: |:-: |
+|title |String |- |标题文字 |
+|extra |String |- |标题额外信息 |
+|note |String |- |底部信息 |
+|thumbnail |String |- |标题左侧缩略图,支持网络图片,本地图片,本图片需要传入一个绝对路径,如:`/static/xxx.png` |
+|mode |String |basic |卡片模式 ,可选值, basic:基础卡片 ;style :图文卡片 ; title :标题卡片 |
+|isFull |Boolean|false |卡片内容是否通栏,为true时将去除padding值 |
+|isShadow |Boolean|false |卡片内容是否开启阴影 |
+
+
+### Card Events
+
+|事件称名 |事件说明 |返回参数 |
+|:-: |:-: |:-: |
+|@click |点击 Card 触发事件 |- |
+
+
+### Card Slots
+
+|插槽称名 |说明 |
+|:-: |:-: |
+|footer |卡片底部插槽 |
\ No newline at end of file
diff --git a/uni_modules/uni-clientDB/db_init.json b/uni_modules/uni-clientDB/db_init.json
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/uni_modules/uni-clientDB/license.md b/uni_modules/uni-clientDB/license.md
new file mode 100644
index 0000000000000000000000000000000000000000..2b0e438f54060672fcd743e27bec84bd78015cc4
--- /dev/null
+++ b/uni_modules/uni-clientDB/license.md
@@ -0,0 +1,30 @@
+# clientDB使用许可协议
+本协议是数字天堂(北京)网络技术有限公司(以下称“DCloud”)与您之间达成的关于clientDB框架(以下简称本框架)的协议。
+本协议签订地点为中华人民共和国北京市海淀区。
+您使用本框架即视为您已阅读并同意受本协议的约束。
+
+## 知识产权及使用授权
+您可以自由下载、使用、复制本框架而不需要向DCloud付费。
+DCloud所拥有的知识产权,包括但不限于商标、专利、著作权、商业秘密、专有数据、源码,并不发生转移或共享。
+您使用本框架开发的代码及输出物,包括但不限于网站、移动应用,其知识产权归属您所有。
+本框架未包含第三方软件或技术,不涉及额外遵循第三方软件的授权协议问题。
+
+## 您的义务
+您不得破解、反编译、逆向工程本框架,不得破解或劫持本框架网络请求,不得对DCloud服务进行网络攻击,不得利用DCloud系统漏洞谋利或侵害DCloud利益,不得替换、删改本框架自带的非用户自定义文件。
+未经书面许可您不可利用DCloud产品的全部或部分文件、模块、组件来制作与DCloud争夺用户的产品(通过DCloud插件市场服务开发者不属于此范围)。
+如果您违反您的义务,DCloud将有权停止您使用本框架,造成的损失由您自行承担。
+如果您给DCloud造成重大损失,或者在接收到DCloud的停止违约通知后拒不改正,DCloud将有权停止对您的DCloud所有产品和服务的使用授权,冻结您在DCloud所有产品服务中的预付款项和应收款项,因此造成的损失由您自行承担。
+如果您的行为产生法律问题,DCloud有权追责您的法律责任。
+
+## 隐私条款
+本框架未进行任何数据采集、发送等涉及数据隐私的行为。
+
+## 安全
+您理解并同意,本框架同其他软件一样,无法承诺绝对的安全性。
+当DCloud发现本框架的任何安全漏洞时,将及时在[社区](https://ask.dcloud.net.cn/explore/)发送公告,并将及时发布紧急更新补丁和升级推送通知。
+
+## 免责声明
+DCloud不因开发者使用本框架而承担任何法律责任。
+
+## 协议修订
+根据发展,DCloud可能会对本协议进行修改。修改时,DCloud会在产品或者网页中显著的位置发布相关信息以便及时通知到用户。如果您选择继续使用本框架,即表示您同意接受这些修改。
diff --git a/uni_modules/uni-clientDB/package.json b/uni_modules/uni-clientDB/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..ea5c7869ecd3819491db0fea40efe34a5f30906d
--- /dev/null
+++ b/uni_modules/uni-clientDB/package.json
@@ -0,0 +1,16 @@
+{
+ "id": "uni-clientDB", // 必选 插件标识,需要保证唯一性
+ "name": "uni-clientDB", // 必选 插件名称
+ "version": "1.0.8", // 必选 插件版本
+ "description": "写法更灵活的客户端访问云端数据方案", // 插件描述
+ "author": "DCloud", // 插件作者
+ "license": "MIT",
+ "homepage": "https://ext.dcloud.net.cn/plugin?id=2314", // 插件地址
+ "files": [ // 必选 插件自身文件列表(支持通配,规范:https://docs.npmjs.com/files/package.json#files)
+ ],
+ "bundledFiles": [ // 插件依赖的文件列表,通常是依赖的三方插件的 files 合并
+ "cloudfunctions/uni-clientDB",
+ "cloudfunctions/common/uni-id",
+ "js_sdk"
+ ]
+}
diff --git a/uni_modules/uni-clientDB/pages.json b/uni_modules/uni-clientDB/pages.json
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/uni_modules/uni-clientDB/readme.md b/uni_modules/uni-clientDB/readme.md
new file mode 100644
index 0000000000000000000000000000000000000000..d99af46bac12a7341bdb75f149f9d6f60f93e95d
--- /dev/null
+++ b/uni_modules/uni-clientDB/readme.md
@@ -0,0 +1,248 @@
+## 简介
+
+每个查询业务,都要写一个云函数,很麻烦,也占用云函数的总数量。
+
+本插件提供了一个通用的数据库查询云函数,由前端向云函数传递要查询的条件,比如查询哪个表、查询哪些字段、where条件和排序是什么。
+
+> 举例:在前端的list.vue列表页面,可以调用本云函数,传入列表查询条件。然后写content.vue详情页面时,无需再新建一个云函数,可以直接在content.vue页面继续调用相同的本云函数,传入详情的查询条件。
+
+客户端的查询条件语法,与云函数里查询数据库的语法是相同的。[查询api手册](https://uniapp.dcloud.io/uniCloud/cf-database?id=%e6%9f%a5%e8%af%a2%e6%96%87%e6%a1%a3)
+
+与某些小程序云的客户端直接操作数据库不同,本方案有2个明显优势:
+- 安全:查询权限是在云函数里控制台的,能查什么表、什么字段,在云端控制。如果全部放在前端,由于前端的不可信任,相当于无法控制权限了。而某些小程序云提供的客户端权限,并不可编程,无法满足开发者的实际业务权限需求
+- 包体积:某些小程序云的客户端操作数据库是一个数M大小的js sdk,如果迁移到H5和App,对应用的启动速度、性能、体积影响非常大
+
+综上,本插件的优势在于:
+1. 提高开发效率
+2. 减少云函数数量
+3. 安全,可控制权限
+4. 性能好
+
+本项目包括云函数和客户端两部分,需要搭配使用,具体请参考下面文档。
+
+**示例项目使用须知**
+
+1. 下载示例项目后选择服务空间
+2. 在db_init.json上右键初始化数据库
+3. 上传公共模块及云函数,公共模块用法参考[使用公共模块](https://uniapp.dcloud.net.cn/uniCloud/cf-common)
+4. 运行项目即可
+
+示例项目文件介绍:
+
+
+
+┌─cloudfunctions 云函数
+│ ├─common 公共模块
+| │ └─uni-curd 数据库查询通用公共模块
+| ├─uni-clientDB 在云函数中控制权限,并调用uni-curd完成查询
+| └─db_init.json 初始化数据库
+├─js_sdk 前端公共js目录
+| └─uni-clientDB 前端的js库,封装了查询语法
+├─pages 业务页面文件存放的目录
+│ ├─index
+│ │ └─index.vue index示例页面
+├─main.js Vue初始化入口文件
+├─App.vue 应用配置,用来配置App全局样式以及监听 应用生命周期
+├─manifest.json 配置应用名称、appid、logo、版本等打包信息,详见
+└─pages.json 配置页面路由、导航条、选项卡等页面类信息,详见
+
+
+
+- 云函数里包括一个公共模块`uni-curd`和一个云函数`uni-clientDB`
+- 前端包括一个js sdk`uni-clientDB`,然后就是index.vue里的示例调用
+- index示例页面,里面包含两个示例一个简单查询一个分页查询
+
+## 客户端公共模块
+
+客户端js-sdk主要负责组装查询逻辑
+
+**示例代码**
+
+```js
+// 引入公共模块
+import db from '@/js_sdk/uni-clientDB/index.js'
+const dbCmd = db.command
+
+// 使用uni-clientDB
+uniCloud.callFunction({
+ name: 'uni-clientDB',
+ data: {
+ command: db.collection('list').where({
+ name: new RegExp('龚','g'),
+ time: dbCmd.gt(1105885393581)
+ }).field({
+ extra: false
+ }).get()
+ },
+ success(res) {
+ // ...
+ },
+ fail(err) {
+ // ...
+ }
+})
+```
+
+**使用说明**
+
+语法与云函数写查询数据库一致,目前有以下限制:
+
+- 不可使用db.serverDate、db.Geo、db.RegExp
+- 上传时会对query进行序列化,除Date类型、RegExp之外的所有不可序列化的参数类型均不支持(例如:undefined)
+- 为方便控制禁止前端使用set方法,一般情况下也不需要前端使用set
+
+## 云函数公共模块
+
+云函数公共模块`uni-curd`主要负责解析客户端查询逻辑,对客户端行为做简单的限制
+
+**使用示例**
+
+```js
+'use strict';
+const uniCurd = require('uni-curd')
+const db = uniCloud.database()
+const dbCmd = db.command
+exports.main = async (event, context) => {
+ // 这里可以判断用户身份给予不同权限,例如:可以从event里拿到uni-id的token,根据token和客户端参数决定查询权限限制
+ try {
+ const res = await uniCurd({
+ command: event.command,
+ pagination: event.pagination,
+ rules: {
+ list: { // 数据表名
+ // CRUD权限
+ create: false,
+ read: true,
+ update: false,
+ delete: false,
+ // 是否允许使用聚合
+ aggregate: false,
+ // 是否允许使用联表查询,联表查询时blockedField不会对被连接的数据表生效
+ lookup: false,
+ // 使用聚合时blockField不会覆盖客户端的project,而是在聚合第一阶段插入project,不使用聚合时会在最后阶段插入一个field(会覆盖客户端的field方法)
+ blockedField: ['extra'],
+ // 不使用聚合时mixinCondition会在没有where的时候在collection方法之后插入where,有where时会跟where条件进行合并,取原条件且mixinCondition。使用聚合时会在第一阶段插入match使用混入的条件,如果有blockedField会插入在blockedField对应的project之前
+ mixinCondition: {
+ time: dbCmd.gt(1000000000000)
+ },
+ // 更多用法请参考下方参数说明文档
+ }
+ }
+ })
+ return res
+
+ } catch (e) {
+ return {
+ code: 10001,
+ msg: e.message
+ }
+ }
+};
+
+```
+
+**参数说明**
+
+|参数名 |类型 |是否必填 |默认值 |说明 |
+|:-: |:-: |:-: |:-: |:-: |
+|command |Object |是 |- |客户端上传的查询条件 |
+|pagination |Object |否 |- |如需分页,请在此字段内配置 |
+|rules |Object |是 |- |权限规则 |
+
+**pagination参数说明**
+
+|参数名 |类型 |是否必填 |默认值 |说明 |
+|:-: |:-: |:-: |:-: |:-: |
+|pageSize |Object |是 |- |每页数量 |
+|current |Object |是 |- |当前页码 |
+
+**rules参数说明**
+
+rules下可以对不同的数据表配置不同的权限,比如以下规则代表”数据表list允许插入,数据表goods允许更新“
+
+```js
+{
+ list: {
+ create: true,
+ },
+ goods: {
+ update: true
+ }
+}
+```
+
+|参数名 |类型 |是否必填 |默认值 |说明 |
+|:-: |:-: |:-: |:-: |:-: |
+|create |Boolean|否 |false |是否开启插入权限 |
+|read |Boolean|否 |true |是否开启读权限 |
+|update |Boolean|否 |false |是否开启更新权限 |
+|delete |Boolean|否 |false |是否开启删除权限 |
+|aggregate |Boolean|否 |false |是否允许聚合 |
+|lookup |Boolean|否 |false |是否允许联表查询 |
+|blockedField |Array |否 |- |屏蔽的数据库字段,请阅读注意事项 |
+|mixinCondition |Object |否 |- |混入条件,请阅读注意事项 |
+|hooks |Object |否 |- |回调方法 |
+
+**hooks参数说明**
+
+|参数名 |类型 |是否必填 |默认值 |说明 |
+|:-: |:-: |:-: |:-: |:-: |
+|beforeStageAppend |Function |否 |- |每个阶段被添加之前执行 |
+|afterStageAppend |Function |否 |- |每个阶段被添加之后执行 |
+|beforeSend |Function |否 |- |最终阶段'get', 'end', 'count', 'add', 'remove', 'update'添加之前执行,在beforeStageAppend之后 |
+
+**回调方法的使用**
+
+回调参数如下:
+
+```js
+{
+ state: {
+ useAggregate, // 是否使用了聚合
+ useLookup, // 是否使用了联表查询
+ type, // 操作类型,可能的值为create、read、update、delete
+ collection, // 当前数据表名
+ methodList // 使用到的方法列表
+ },
+ stage: {
+ method, // 当前阶段方法名
+ args // 当前阶段方法参数
+ },
+ exec // 已经组装的查询指令
+}
+```
+
+回调方法中可以通过返回结果修改数据库指令,例如以下示例在skip之后插入一个limit
+
+```js
+afterStageAppend: function({
+ state,
+ stage,
+ exec
+}) {
+ if(stage.method === 'skip') {
+ return exec.limit(1)
+ }
+},
+```
+
+**注意事项**
+
+- 关于blockedField
+ + 使用聚合时blockField不会覆盖客户端的project,而是在聚合第一阶段插入project
+ + 不使用聚合时会在最后阶段插入一个field(会覆盖客户端的field方法)
+ + blockedField仅对读操作生效
+
+- 关于mixinCondition
+ + mixinCondition内可以使用数据库操作符
+ + 不使用聚合时mixinCondition会在没有where的时候在collection方法之后插入where,有where时会跟where条件进行合并,取原条件且mixinCondition。
+ + 使用聚合时会在第一阶段插入match使用混入的条件,如果有blockedField会插入在blockedField对应的project之前
+ + mixinCondition会对除插入以外的所有操作生效
+ + 使用mixinCondition时客户端不可使用`collection('xxx').doc('xxx')`方法(1.0.8版本起即使有mixinCondition客户端也可以使用doc方法)
+
+- 关于联表查询
+ + 连接的数据表也会受所配置的权限规则中对应数据表规则限制,主要是read,目前连接的数据表不会受blockedField限制
+
+**参考**
+
+在线通讯录项目,完整的演示了如何基于clientDB在客户端代码里实现数据的增删改查,是学习clientDB的重要示例项目。该项目插件地址:[https://ext.dcloud.net.cn/plugin?id=2574](https://ext.dcloud.net.cn/plugin?id=2574)
\ No newline at end of file
diff --git a/uni_modules/uni-collapse/changelog.md b/uni_modules/uni-collapse/changelog.md
new file mode 100644
index 0000000000000000000000000000000000000000..f8f136f455782ed6f826a9ad558965be3dc0161b
--- /dev/null
+++ b/uni_modules/uni-collapse/changelog.md
@@ -0,0 +1,4 @@
+## 1.1.6(2021-02-05)
+- 优化 组件引用关系,通过uni_modules引用组件
+## 1.1.5(2021-02-05)
+- 调整为uni_modules目录规范
\ No newline at end of file
diff --git a/uni_modules/uni-collapse/components/uni-collapse-item/uni-collapse-item.vue b/uni_modules/uni-collapse/components/uni-collapse-item/uni-collapse-item.vue
new file mode 100644
index 0000000000000000000000000000000000000000..b40420036a7211030d30015327483c3981c5ded3
--- /dev/null
+++ b/uni_modules/uni-collapse/components/uni-collapse-item/uni-collapse-item.vue
@@ -0,0 +1,220 @@
+
+
+
+
+ {{ title }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/uni-collapse/components/uni-collapse/uni-collapse.vue b/uni_modules/uni-collapse/components/uni-collapse/uni-collapse.vue
new file mode 100644
index 0000000000000000000000000000000000000000..bb3745f2a38ff57315e74b3a01058ae969ecc0b0
--- /dev/null
+++ b/uni_modules/uni-collapse/components/uni-collapse/uni-collapse.vue
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
diff --git a/uni_modules/uni-collapse/package.json b/uni_modules/uni-collapse/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..8297315f63bd33f41dd36e46315f8166ee7590fd
--- /dev/null
+++ b/uni_modules/uni-collapse/package.json
@@ -0,0 +1,84 @@
+{
+ "id": "uni-collapse",
+ "displayName": "Collapse 折叠面板",
+ "version": "1.1.6",
+ "description": " collapse uni-ui 折叠面板 手风琴",
+ "keywords": [
+ "Collapse",
+ "组件,可以折叠",
+ "/",
+ "展开的内容区域。"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "前端组件",
+ "通用组件"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "无",
+ "data": "无",
+ "permissions": "无"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": [
+ "uni-icons"
+ ],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "微信浏览器(Android)": "y",
+ "QQ浏览器(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "小程序": {
+ "微信": "y",
+ "阿里": "y",
+ "百度": "y",
+ "字节跳动": "y",
+ "QQ": "y"
+ },
+ "快应用": {
+ "华为": "u",
+ "联盟": "u"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/uni_modules/uni-collapse/readme.md b/uni_modules/uni-collapse/readme.md
new file mode 100644
index 0000000000000000000000000000000000000000..6fefb29f9801467a90224c316cdd9607a8289422
--- /dev/null
+++ b/uni_modules/uni-collapse/readme.md
@@ -0,0 +1,107 @@
+
+
+## Collapse 折叠面板
+> 代码块: `uCollapse`
+> 关联组件:`uni-collapse-item`、`uni-icons`。
+
+
+展示可以折叠 / 展开的内容区域。
+
+### 安装方式
+
+本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。
+
+如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55)
+
+### 基本用法
+
+在 ``template`` 中引用组件
+
+```html
+
+
+
+
+
+
+
+
+
+
+ 折叠内容主体,可自定义内容及样式
+
+
+ 禁用状态
+
+
+
+
+
+
+
+ 手风琴效果
+
+
+
+
+ 手风琴效果
+
+
+
+
+ 手风琴效果
+
+
+
+
+
+
+
+
+ 折叠内容主体,可自定义内容及样式
+
+
+
+
+ 折叠内容主体,可自定义内容及样式
+
+
+
+```
+
+## API
+
+### Collapse Props
+
+|属性名 |类型 |默认值 |说明 |
+|:-: |:-: |:-: |:-: |
+|accordion |Boolean|false |是否开启手风琴效果 |
+
+
+### Collapse Event
+
+|事件称名 |说明 |返回值 |
+|:-: |:-: :-: |
+|@change |切换面板时触发 |activeNames(Array):展开状态的uniCollapseItem的name值|
+
+
+### Collapse Methods
+
+|方法名称 |说明 |
+|:-: |:-: |
+|resize |更新当前列表高度,只有 `animation:true` 下生效|
+
+
+> - resize 方法解决动态添加数据,带动画的折叠面板高度不更新的问题
+> - 需要在数据渲染完毕之后使用 `resize` 方法。推荐在 `this.nextTick()` 中使用
+
+
+### CollapseItem Props
+
+|属性名 |类型 |默认值 |说明 |
+|:-: |:-: |:-: |:-: |
+|title |String |- |标题文字 |
+|thumb |String |- |标题左侧缩略图 |
+|disabled |Boolean|false |是否禁用 |
+|open |Boolean|false |是否展开面板 |
+|showAnimation |Boolean |false |开启动画 |
\ No newline at end of file
diff --git a/uni_modules/uni-combox/changelog.md b/uni_modules/uni-combox/changelog.md
new file mode 100644
index 0000000000000000000000000000000000000000..7e2e90934feb20c7df51a2b67829dbf63d18334d
--- /dev/null
+++ b/uni_modules/uni-combox/changelog.md
@@ -0,0 +1,4 @@
+## 0.0.4(2021-02-05)
+- 优化 组件引用关系,通过uni_modules引用组件
+## 0.0.3(2021-02-04)
+- 调整为uni_modules目录规范
diff --git a/uni_modules/uni-combox/components/uni-combox/uni-combox.vue b/uni_modules/uni-combox/components/uni-combox/uni-combox.vue
new file mode 100644
index 0000000000000000000000000000000000000000..e815b202b54b315c7ef4dee1a4e7f0b2a426ca6b
--- /dev/null
+++ b/uni_modules/uni-combox/components/uni-combox/uni-combox.vue
@@ -0,0 +1,218 @@
+
+
+
+ {{label}}
+
+
+
+
+
+
+
+ {{emptyTips}}
+
+
+ {{item}}
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/uni-combox/package.json b/uni_modules/uni-combox/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..acbca008cf92ca2307fd7cadbb84833fc5378938
--- /dev/null
+++ b/uni_modules/uni-combox/package.json
@@ -0,0 +1,82 @@
+{
+ "id": "uni-combox",
+ "displayName": "Combox 组合框",
+ "version": "0.0.4",
+ "description": "可以选择也可以输入的表单项 ",
+ "keywords": [
+ "combox",
+ "组合框",
+ "可下拉输入框",
+ "select"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "前端组件",
+ "通用组件"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "无",
+ "data": "无",
+ "permissions": "无"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": [],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "n"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "微信浏览器(Android)": "y",
+ "QQ浏览器(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "小程序": {
+ "微信": "y",
+ "阿里": "y",
+ "百度": "y",
+ "字节跳动": "y",
+ "QQ": "y"
+ },
+ "快应用": {
+ "华为": "u",
+ "联盟": "u"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/uni_modules/uni-combox/readme.md b/uni_modules/uni-combox/readme.md
new file mode 100644
index 0000000000000000000000000000000000000000..b8120566dd768261664f0b61a9e59545328baeed
--- /dev/null
+++ b/uni_modules/uni-combox/readme.md
@@ -0,0 +1,46 @@
+
+
+## Combox 组合框
+> 代码块: `uCombox`
+
+
+组合框组件。
+
+### 平台兼容性说明
+
+**暂不支持nvue**
+
+### 安装方式
+
+本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。
+
+如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55)
+
+### 基本用法
+
+在 ``template`` 中使用组件
+```html
+
+```
+
+## API
+
+### Combox Props
+
+|属性名 |类型 |默认值 |说明 |
+|:-: |:-: |:-: |:-: |
+|label |String |- |标签文字 |
+|value |String |- |combox的值 |
+|labelWidth |String |auto |标签宽度,有单位字符串,如:'100px' |
+|placeholder|String |- |输入框占位符 |
+|candidates |Array/String |[] |候选字段 |
+|emptyTips |String |无匹配项 |无匹配项时的提示语 |
+
+### Combox Events
+
+|事件称名 |说明 |返回值 |
+|:-: |:-: |:-: |
+|@input |combox输入事件 |返回combox值|
+
+
+
diff --git a/uni_modules/uni-countdown/changelog.md b/uni_modules/uni-countdown/changelog.md
new file mode 100644
index 0000000000000000000000000000000000000000..733ef50454c39ea39f9a0fe56cabb24f8726cef1
--- /dev/null
+++ b/uni_modules/uni-countdown/changelog.md
@@ -0,0 +1,2 @@
+## 1.0.2(2021-02-04)
+- 调整为uni_modules目录规范
diff --git a/uni_modules/uni-countdown/components/uni-countdown/uni-countdown.vue b/uni_modules/uni-countdown/components/uni-countdown/uni-countdown.vue
new file mode 100644
index 0000000000000000000000000000000000000000..7e9c508ece50acbd398881fcab2c68b9241a19b9
--- /dev/null
+++ b/uni_modules/uni-countdown/components/uni-countdown/uni-countdown.vue
@@ -0,0 +1,211 @@
+
+
+ {{ d }}
+ 天
+ {{ h }}
+ {{ showColon ? ':' : '时' }}
+ {{ i }}
+ {{ showColon ? ':' : '分' }}
+ {{ s }}
+ 秒
+
+
+
+
diff --git a/uni_modules/uni-countdown/package.json b/uni_modules/uni-countdown/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..91ed1a1344eb75d6182a6a22e9feb5fb46fcc4ab
--- /dev/null
+++ b/uni_modules/uni-countdown/package.json
@@ -0,0 +1,81 @@
+{
+ "id": "uni-countdown",
+ "displayName": "Countdown 倒计时",
+ "version": "1.0.2",
+ "description": "CountDown 倒计时组件",
+ "keywords": [
+ "countdown",
+ "uni-ui",
+ "倒计时"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "前端组件",
+ "通用组件"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "无",
+ "data": "无",
+ "permissions": "无"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": [],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "微信浏览器(Android)": "y",
+ "QQ浏览器(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "小程序": {
+ "微信": "y",
+ "阿里": "y",
+ "百度": "y",
+ "字节跳动": "y",
+ "QQ": "y"
+ },
+ "快应用": {
+ "华为": "u",
+ "联盟": "u"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/uni_modules/uni-countdown/readme.md b/uni_modules/uni-countdown/readme.md
new file mode 100644
index 0000000000000000000000000000000000000000..567fd05f7be06ad9fafedf7095ba508c69c12ccd
--- /dev/null
+++ b/uni_modules/uni-countdown/readme.md
@@ -0,0 +1,50 @@
+
+
+## CountDown 倒计时
+> 代码块: `uCountDown`
+
+
+倒计时组件。
+
+### 安装方式
+
+本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。
+
+如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55)
+
+### 基本用法
+
+在 ``template`` 中使用组件
+
+```html
+
+
+
+
+
+
+
+
+```
+
+## API
+
+### Countdown Props
+
+|属性名 |类型 |默认值 |说明 |
+|:-: |:-: |:-: |:-: |
+|backgroundColor |String |#FFFFFF|背景色 |
+|color |String |#000000|文字颜色 |
+|splitorColor |String |#000000|分割符号颜色 |
+|day |Number |0 |天数 |
+|hour |Number |0 |小时 |
+|minute |Number |0 |分钟 |
+|second |Number |0 |秒 |
+|showDay |Boolean|true |是否显示天数 |
+|showColon |Boolean|true |是否以冒号为分隔符 |
+
+### Countdown Events
+
+|事件称名 |说明 |返回值 |
+|:-: |:-: |:-: |
+|@timeup|倒计时时间到触发事件 |- |
diff --git a/uni_modules/uni-data-checkbox/changelog.md b/uni_modules/uni-data-checkbox/changelog.md
new file mode 100644
index 0000000000000000000000000000000000000000..5fa34d21693b3f97958a186e23cc07728df32660
--- /dev/null
+++ b/uni_modules/uni-data-checkbox/changelog.md
@@ -0,0 +1,8 @@
+## 0.1.3(2021-03-22)
+- 新增 disabled属性
+## 0.1.2(2021-02-24)
+- 优化 默认颜色显示
+## 0.1.1(2021-02-24)
+- 新增 支持nvue
+## 0.1.0(2021-02-18)
+- “暂无数据”显示居中
diff --git a/uni_modules/uni-data-checkbox/components/uni-data-checkbox/uni-data-checkbox.vue b/uni_modules/uni-data-checkbox/components/uni-data-checkbox/uni-data-checkbox.vue
new file mode 100644
index 0000000000000000000000000000000000000000..c6bf68a6954bcb3f9531bd4bc53f4fdca2372469
--- /dev/null
+++ b/uni_modules/uni-data-checkbox/components/uni-data-checkbox/uni-data-checkbox.vue
@@ -0,0 +1,785 @@
+
+
+
+
+
+ {{mixinDatacomErrorMessage}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/uni-data-checkbox/package.json b/uni_modules/uni-data-checkbox/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..c5fcbfc73f7c09e9b3fabec955bf2eec6b2a0117
--- /dev/null
+++ b/uni_modules/uni-data-checkbox/package.json
@@ -0,0 +1,81 @@
+{
+ "id": "uni-data-checkbox",
+ "displayName": "DataCheckbox 数据选择器",
+ "version": "0.1.3",
+ "description": "通过数据驱动的单选框和复选框",
+ "keywords": [
+ "checkbox",
+ "uni-data-checkbox",
+ "单选多选"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": "^3.1.1"
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "前端组件",
+ "通用组件"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "无",
+ "data": "无",
+ "permissions": "无"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": ["uni-load-more"],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "微信浏览器(Android)": "y",
+ "QQ浏览器(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "小程序": {
+ "微信": "y",
+ "阿里": "y",
+ "百度": "y",
+ "字节跳动": "y",
+ "QQ": "y"
+ },
+ "快应用": {
+ "华为": "u",
+ "联盟": "u"
+ }
+ }
+ }
+ }
+}
diff --git a/uni_modules/uni-data-checkbox/readme.md b/uni_modules/uni-data-checkbox/readme.md
new file mode 100644
index 0000000000000000000000000000000000000000..c34450c5f51a856477bd57f1c0920bb39844bdc2
--- /dev/null
+++ b/uni_modules/uni-data-checkbox/readme.md
@@ -0,0 +1,291 @@
+
+
+## DataCheckbox 数据驱动的单选复选框
+> 代码块: `uDataCheckbox`
+
+
+本组件是基于uni-app基础组件checkbox的封装。本组件要解决问题包括:
+
+1. 数据绑定型组件:给本组件绑定一个data,会自动渲染一组候选内容。再以往,开发者需要编写不少代码实现类似功能
+2. 自动的表单校验:组件绑定了data,且符合[uni-forms](https://ext.dcloud.net.cn/plugin?id=2773)组件的表单校验规范,搭配使用会自动实现表单校验
+3. 本组件合并了单选多选
+4. 本组件有若干风格选择,如普通的单选多选框、并列button风格、tag风格。开发者可以快速选择需要的风格。但作为一个封装组件,样式代码虽然不用自己写了,却会牺牲一定的样式自定义性
+
+在uniCloud开发中,`DB Schema`中配置了enum枚举等类型后,在web控制台的[自动生成表单](https://uniapp.dcloud.io/uniCloud/schema?id=autocode)功能中,会自动生成``uni-data-checkbox``组件并绑定好data
+
+> 为了避免错误使用,给大家带来不好的开发体验,请在使用组件前仔细阅读下面的注意事项,可以帮你避免一些错误。
+> - 组件需要依赖 `sass` 插件 ,请自行手动安装
+> - 本组件为数据驱动,目的是快速投入使用,只可通过 style 覆盖有限样式,不支持自定义更多样式
+> - 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839
+> - 组件支持 nvue ,需要在 `manifest.json > app-plus` 节点下配置 `"nvueStyleCompiler" : "uni-app"`
+> - 如组件显示有问题 ,请升级 `HBuilderX` 为 `v3.1.0` 以上
+
+
+### 安装方式
+
+本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。
+
+如需通过`npm`方式使用`uni-ui`组件,另行文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55)
+
+### 基本用法
+
+设置 `localdata` 属性后,组件会通过数据渲染出对应的内容,默认显示的是单选框
+
+需要注意 `:multiple="false"` 时(单选) , `value/v-model` 的值是 `String|Number` 类型
+
+```html
+
+
+
+
+
+
+```
+
+```javascript
+
+export default {
+ data() {
+ return {
+ value: 0,
+ range: [{"value": 0,"text": "篮球" },{"value": 1,"text": "足球"},{"value": 2,"text": "游泳"}]
+ }
+ },
+ methods: {
+ change(e){
+ console.log('e:',e);
+ }
+ }
+}
+```
+
+### 多选框
+
+设置 `multiple` 属性,组件显示为多选框
+
+需要注意 `:multiple="true"` 时(多选) , `value/v-model` 的值是 `Array` 类型
+
+```html
+
+
+
+
+
+
+```
+
+```javascript
+
+export default {
+ data() {
+ return {
+ value: [0,2],
+ range: [{"value": 0,"text": "篮球" },{"value": 1,"text": "足球"},{"value": 2,"text": "游泳"}]
+ }
+ },
+ methods: {
+ change(e){
+ console.log('e:',e);
+ }
+ }
+}
+```
+
+### 设置最大最小值
+
+设置 `:multiple="true"` 时(多选) ,可以设置 `min`、`max` 属性
+
+如果选中个数小于 `min` 属性设置的值,那么选中内容将不可取消,只有当选中个数大于等于 `min`且小于 `max` 时,才可取消选中
+
+如果选中个数大于等于 `max` 属性设置的值,那么其他未选中内容将不可选
+
+```html
+
+
+
+
+
+
+```
+
+```javascript
+
+export default {
+ data() {
+ return {
+ value: [0,2],
+ range: [{"value": 0,"text": "篮球" },{"value": 1,"text": "足球"},{"value": 2,"text": "游泳"}]
+ }
+ },
+ methods: {
+ change(e){
+ console.log('e:',e);
+ }
+ }
+}
+```
+
+### 设置禁用
+
+如果需要禁用某项,需要在 `localdata` 属性的数据源中添加 `disable` 属性,而不是在组件中添加 `disable` 属性
+
+```html
+
+
+
+
+
+
+```
+
+```javascript
+
+export default {
+ data() {
+ return {
+ value: 0,
+ range: [{
+ "value": 0,
+ "text": "篮球"
+ },
+ {
+ "value": 1,
+ "text": "足球",
+ // 禁用当前项
+ "disable":true
+ },
+ {
+ "value": 2,
+ "text": "游泳"
+ }
+ ]
+ }
+ },
+ methods: {
+ change(e){
+ console.log('e:',e);
+ }
+ }
+}
+```
+
+
+### 自定义选中颜色
+
+设置 `selectedColor` 属性,可以修改组件选中后的图标及边框颜色
+
+设置 `selectedTextColor` 属性,可以修改组件选中后的文字颜色,如不填写默认同 `selectedColor` 属性 ,`mode` 属性为 `tag` 时,默认为白色
+
+```html
+
+
+
+
+
+
+```
+
+```javascript
+
+export default {
+ data() {
+ return {
+ value: [0,2],
+ range: [{"value": 0,"text": "篮球" },{"value": 1,"text": "足球"},{"value": 2,"text": "游泳"}]
+ }
+ },
+ methods: {
+ change(e){
+ console.log('e:',e);
+ }
+ }
+}
+```
+
+### 更多模式
+
+设置 `mode` 属性,可以设置更多显示样式,目前内置样式有四种 `default/list/button/tag`
+
+如果需要禁用某项,需要在 `localdata` 属性的数据源中添加 `disable` 属性,而不是在组件中添加 `disable` 属性
+
+```html
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+```javascript
+
+export default {
+ data() {
+ return {
+ value: 0,
+ range: [{"value": 0,"text": "篮球" },{"value": 1,"text": "足球"},{"value": 2,"text": "游泳"}]
+ }
+ },
+ methods: {
+ change(e){
+ console.log('e:',e);
+ }
+ }
+}
+```
+
+
+## API
+
+### DataCheckbox Props
+
+| 属性名 | 类型 |可选值 | 默认值| 说明 |
+| :-: | :-: |:-: |:-: | :-: |
+|value/v-model|Array/String/Number|- |- |默认值,multiple=true时为 Array类型,否则为 String或Number类型 |
+|localdata |Array |- |- |本地渲染数据, |
+|mode | String |default/list/button/tag|default|显示模式 |
+|multiple |Boolean |- |false |是否多选 |
+|min |String/Number |- |- |最小选择个数 ,multiple为true时生效 |
+|max |String/Number |- |- |最大选择个数 ,multiple为true时生效 |
+|wrap |Boolean |- |- |是否换行显示 |
+|icon |String |left/right |left |list 列表模式下 icon 显示的位置 |
+|selectedColor|String |- |#007aff|选中颜色|
+|selectedTextColor|String |- |#333 |选中文本颜色,如不填写则自动显示|
+|emptyText |String |- |暂无数据 |没有数据时显示的文字 ,本地数据无效|
+
+#### Localdata Options
+
+`localdata` 属性的格式为数组,数组内每项是对象,需要严格遵循如下格式
+
+|属性名 | 说明 |
+|:-: | :-: |
+|text |显示文本 |
+|value |选中后的值 |
+|disable |是否禁用 |
+
+#### Mode Options
+
+|属性名 | 说明 |
+|:-: | :-: |
+|default |默认值,横向显示 |
+|list |列表 |
+|button |按钮 |
+|tag |标签 |
+
+
+### DataCheckbox Events
+
+| 事件名 | 事件说明 | 返回参数|
+| :-: | :-: | :-: |
+| @chage| 选中状态改变时触发事件 | - |
+
+
diff --git a/uni_modules/uni-data-picker/changelog.md b/uni_modules/uni-data-picker/changelog.md
new file mode 100644
index 0000000000000000000000000000000000000000..8ad6f35bc8c56e84b4b04af637302e6ef8040d2b
--- /dev/null
+++ b/uni_modules/uni-data-picker/changelog.md
@@ -0,0 +1,8 @@
+## 0.2.0(2021-03-15)
+- 修复 nodeclick、popupopened、popupclosed事件无法触发的问题
+## 0.1.9(2021-03-09)
+- 修复 微信小程序某些情况下无法选择的问题
+## 0.1.8(2021-02-05)
+- 优化 部分样式在nvue上的兼容表现
+## 0.1.7(2021-02-05)
+- 调整为uni_modules目录规范
diff --git a/uni_modules/uni-data-picker/components/uni-data-picker/config.json b/uni_modules/uni-data-picker/components/uni-data-picker/config.json
new file mode 100644
index 0000000000000000000000000000000000000000..dc6b403974e5b00c4bc44de7334de52448cff076
--- /dev/null
+++ b/uni_modules/uni-data-picker/components/uni-data-picker/config.json
@@ -0,0 +1,12 @@
+{
+ "id": "3796",
+ "name": "DataPicker",
+ "desc": "数据驱动的picker选择器",
+ "url": "data-picker",
+ "type": "表单组件",
+ "edition": "0.0.8",
+ "suffix": "vue",
+ "module": ["uni-data-picker","uni-data-pickerview","uni-load-more"],
+ "path": "https://ext.dcloud.net.cn/plugin?id=3796",
+ "update_log": ["- 优化 增加下拉箭头"]
+}
diff --git a/uni_modules/uni-data-picker/components/uni-data-picker/keypress.js b/uni_modules/uni-data-picker/components/uni-data-picker/keypress.js
new file mode 100644
index 0000000000000000000000000000000000000000..6ef26a26211ff28976e6fc835fbef5d2ea5b5b1e
--- /dev/null
+++ b/uni_modules/uni-data-picker/components/uni-data-picker/keypress.js
@@ -0,0 +1,45 @@
+// #ifdef H5
+export default {
+ name: 'Keypress',
+ props: {
+ disable: {
+ type: Boolean,
+ default: false
+ }
+ },
+ mounted () {
+ const keyNames = {
+ esc: ['Esc', 'Escape'],
+ tab: 'Tab',
+ enter: 'Enter',
+ space: [' ', 'Spacebar'],
+ up: ['Up', 'ArrowUp'],
+ left: ['Left', 'ArrowLeft'],
+ right: ['Right', 'ArrowRight'],
+ down: ['Down', 'ArrowDown'],
+ delete: ['Backspace', 'Delete', 'Del']
+ }
+ const listener = ($event) => {
+ if (this.disable) {
+ return
+ }
+ const keyName = Object.keys(keyNames).find(key => {
+ const keyName = $event.key
+ const value = keyNames[key]
+ return value === keyName || (Array.isArray(value) && value.includes(keyName))
+ })
+ if (keyName) {
+ // 避免和其他按键事件冲突
+ setTimeout(() => {
+ this.$emit(keyName, {})
+ }, 0)
+ }
+ }
+ document.addEventListener('keyup', listener)
+ this.$once('hook:beforeDestroy', () => {
+ document.removeEventListener('keyup', listener)
+ })
+ },
+ render: () => {}
+}
+// #endif
diff --git a/uni_modules/uni-data-picker/components/uni-data-picker/uni-data-picker.vue b/uni_modules/uni-data-picker/components/uni-data-picker/uni-data-picker.vue
new file mode 100644
index 0000000000000000000000000000000000000000..a3bd82182d39cda5a5c61efa5d29e29afcef7015
--- /dev/null
+++ b/uni_modules/uni-data-picker/components/uni-data-picker/uni-data-picker.vue
@@ -0,0 +1,462 @@
+
+
+
+
+
+ {{errorMessage}}
+
+
+
+
+
+
+ {{item.text}}{{split}}
+
+
+
+ {{placeholder}}
+
+
+
+
+
+
+
+
+
+
+ {{popupTitle}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-picker.js b/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-picker.js
new file mode 100644
index 0000000000000000000000000000000000000000..af69e741ae0172cac3e179096178ee9d1e93bd8b
--- /dev/null
+++ b/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-picker.js
@@ -0,0 +1,468 @@
+export default {
+ props: {
+ localdata: {
+ type: [Array, Object],
+ default () {
+ return []
+ }
+ },
+ collection: {
+ type: String,
+ default: ''
+ },
+ action: {
+ type: String,
+ default: ''
+ },
+ field: {
+ type: String,
+ default: ''
+ },
+ orderby: {
+ type: String,
+ default: ''
+ },
+ where: {
+ type: [String, Object],
+ default: ''
+ },
+ pageData: {
+ type: String,
+ default: 'add'
+ },
+ pageCurrent: {
+ type: Number,
+ default: 1
+ },
+ pageSize: {
+ type: Number,
+ default: 20
+ },
+ getcount: {
+ type: [Boolean, String],
+ default: false
+ },
+ getone: {
+ type: [Boolean, String],
+ default: false
+ },
+ gettree: {
+ type: [Boolean, String],
+ default: false
+ },
+ manual: {
+ type: Boolean,
+ default: false
+ },
+ value: {
+ type: [Array, String, Number],
+ default () {
+ return []
+ }
+ },
+ preload: {
+ type: Boolean,
+ default: false
+ },
+ stepSearh: {
+ type: Boolean,
+ default: true
+ },
+ selfField: {
+ type: String,
+ default: ''
+ },
+ parentField: {
+ type: String,
+ default: ''
+ },
+ multiple: {
+ type: Boolean,
+ default: false
+ }
+ },
+ data() {
+ return {
+ loading: false,
+ errorMessage: '',
+ loadMore: {
+ contentdown: '',
+ contentrefresh: '',
+ contentnomore: ''
+ },
+ dataList: [],
+ selected: [],
+ selectedIndex: 0,
+ page: {
+ current: this.pageCurrent,
+ size: this.pageSize,
+ count: 0
+ }
+ }
+ },
+ computed: {
+ isLocaldata() {
+ return this.localdata.length > 0
+ },
+ postField() {
+ return `${this.field}, ${this.parentField} as parent_value`
+ }
+ },
+ created() {
+ this.$watch(() => {
+ var al = [];
+ ['pageCurrent',
+ 'pageSize',
+ 'value',
+ 'localdata',
+ 'collection',
+ 'action',
+ 'field',
+ 'orderby',
+ 'where',
+ 'getont',
+ 'getcount',
+ 'gettree'
+ ].forEach(key => {
+ al.push(this[key])
+ });
+ return al
+ }, (newValue, oldValue) => {
+ let needReset = false
+ for (let i = 2; i < newValue.length; i++) {
+ if (newValue[i] != oldValue[i]) {
+ needReset = true
+ break
+ }
+ }
+ if (newValue[0] != oldValue[0]) {
+ this.page.current = this.pageCurrent
+ }
+ this.page.size = this.pageSize
+
+ this.onPropsChange()
+ })
+ this._treeData = []
+ },
+ methods: {
+ onPropsChange() {
+ this._treeData = []
+ },
+ getCommand(options = {}) {
+ /* eslint-disable no-undef */
+ let db = uniCloud.database()
+
+ const action = options.action || this.action
+ if (action) {
+ db = db.action(action)
+ }
+
+ const collection = options.collection || this.collection
+ db = db.collection(collection)
+
+ const where = options.where || this.where
+ if (!(!where || !Object.keys(where).length)) {
+ db = db.where(where)
+ }
+
+ const field = options.field || this.field
+ if (field) {
+ db = db.field(field)
+ }
+
+ const orderby = options.orderby || this.orderby
+ if (orderby) {
+ db = db.orderBy(orderby)
+ }
+
+ const current = options.pageCurrent !== undefined ? options.pageCurrent : this.page.current
+ const size = options.pageSize !== undefined ? options.pageSize : this.page.size
+ const getCount = options.getcount !== undefined ? options.getcount : this.getcount
+ const getTree = options.gettree !== undefined ? options.gettree : this.gettree
+
+ const getOptions = {
+ getCount,
+ getTree
+ }
+ if (options.getTreePath) {
+ getOptions.getTreePath = options.getTreePath
+ }
+
+ db = db.skip(size * (current - 1)).limit(size).get(getOptions)
+
+ return db
+ },
+ getTreePath(callback) {
+ if (this.loading) {
+ return
+ }
+ this.loading = true
+
+ this.getCommand({
+ field: this.postField,
+ getTreePath: {
+ startWith: `${this.selfField}=='${this.value}'`
+ }
+ }).then((res) => {
+ this.loading = false
+ let treePath = []
+ this._extractTreePath(res.result.data, treePath)
+ this.selected = treePath
+ callback && callback()
+ }).catch((err) => {
+ this.loading = false
+ this.errorMessage = err
+ })
+ },
+ loadData() {
+ if (this.isLocaldata) {
+ this._processLocalData()
+ return
+ }
+
+ if (this.value.length) {
+ this._loadNodeData((data) => {
+ this._treeData = data
+ this._updateBindData()
+ this._updateSelected()
+ })
+ return
+ }
+
+ if (this.stepSearh) {
+ this._loadNodeData((data) => {
+ this._treeData = data
+ this._updateBindData()
+ })
+ } else {
+ this._loadAllData((data) => {
+ this._treeData = []
+ this._extractTree(data, this._treeData, null)
+ this._updateBindData()
+ })
+ }
+ },
+ _loadAllData(callback) {
+ if (this.loading) {
+ return
+ }
+ this.loading = true
+
+ this.getCommand({
+ field: this.postField,
+ gettree: true,
+ startwith: `${this.selfField}=='${this.value}'`
+ }).then((res) => {
+ this.loading = false
+ callback(res.result.data)
+ this.onDataChange()
+ }).catch((err) => {
+ this.loading = false
+ this.errorMessage = err
+ })
+ },
+ _loadNodeData(callback, pw) {
+ if (this.loading) {
+ return
+ }
+ this.loading = true
+
+ this.getCommand({
+ field: this.postField,
+ where: pw || this._postWhere(),
+ pageSize: 500
+ }).then((res) => {
+ this.loading = false
+ callback(res.result.data)
+ this.onDataChange()
+ }).catch((err) => {
+ this.loading = false
+ this.errorMessage = err
+ })
+ },
+ _postWhere() {
+ let result = []
+ let selected = this.selected
+ result.push(`${this.parentField} == null`)
+ if (selected.length) {
+ for (var i = 0; i < selected.length - 1; i++) {
+ result.push(`${this.parentField} == '${selected[i].value}'`)
+ }
+ }
+
+ if (this.where) {
+ return `(${this.where}) && (${result.join(' || ')})`
+ }
+
+ return result.join(' || ')
+ },
+ _nodeWhere() {
+ let result = []
+ let selected = this.selected
+ if (selected.length) {
+ result.push(`${this.parentField} == '${selected[selected.length - 1].value}'`)
+ }
+
+ if (this.where) {
+ return `(${this.where}) && (${result.join(' || ')})`
+ }
+
+ return result.join(' || ')
+ },
+ _updateSelected() {
+ var dl = this.dataList
+ var sl = this.selected
+ for (var i = 0; i < sl.length; i++) {
+ var value = sl[i].value
+ var dl2 = dl[i]
+ for (var j = 0; j < dl2.length; j++) {
+ var item2 = dl2[j]
+ if (item2.value === value) {
+ sl[i].text = item2.text
+ break
+ }
+ }
+ }
+ },
+ _updateBindData(node) {
+ const {
+ dataList,
+ hasNodes
+ } = this._filterData(this._treeData, this.selected)
+
+ let isleaf = this._stepSearh === false && !hasNodes
+
+ if (node) {
+ node.isleaf = isleaf
+ }
+
+ this.dataList = dataList
+ this.selectedIndex = dataList.length - 1
+
+ if (!isleaf && this.selected.length < dataList.length) {
+ this.selected.push({
+ value: null,
+ text: "请选择"
+ })
+ }
+
+ return {
+ isleaf,
+ hasNodes
+ }
+ },
+ _filterData(data, paths) {
+ let dataList = []
+
+ let hasNodes = true
+
+ dataList.push(data.filter((item) => {
+ return item.parent_value === undefined
+ }))
+ for (let i = 0; i < paths.length; i++) {
+ var value = paths[i].value
+ var nodes = data.filter((item) => {
+ return item.parent_value === value
+ })
+
+ if (nodes.length) {
+ dataList.push(nodes)
+ } else {
+ hasNodes = false
+ }
+ }
+
+ return {
+ dataList,
+ hasNodes
+ }
+ },
+ _extractTree(nodes, result, parent_value) {
+ let list = result || []
+ for (let i = 0; i < nodes.length; i++) {
+ let node = nodes[i]
+
+ let child = {}
+ for (let key in node) {
+ if (key !== 'children') {
+ child[key] = node[key]
+ }
+ }
+ if (parent_value !== null) {
+ child.parent_value = parent_value
+ }
+ result.push(child)
+
+ let children = node.children
+ if (children) {
+ this._extractTree(children, result, node.value)
+ }
+ }
+ },
+ _extractTreePath(nodes, result) {
+ let list = result || []
+ for (let i = 0; i < nodes.length; i++) {
+ let node = nodes[i]
+
+ let child = {}
+ for (let key in node) {
+ if (key !== 'children') {
+ child[key] = node[key]
+ }
+ }
+ result.push(child)
+
+ let children = node.children
+ if (children) {
+ this._extractTreePath(children, result)
+ }
+ }
+ },
+ _findNodePath(key, nodes, path = []) {
+ for (let i = 0; i < nodes.length; i++) {
+ let {
+ value,
+ text,
+ children
+ } = nodes[i]
+
+ path.push({
+ value,
+ text
+ })
+
+ if (value === key) {
+ return path
+ }
+
+ if (children) {
+ const p = this._findNodePath(key, children, path)
+ if (p.length) {
+ return p
+ }
+ }
+
+ path.pop()
+ }
+ return []
+ },
+ _processLocalData() {
+ this._treeData = []
+ this._extractTree(this.localdata, this._treeData)
+
+ var inputValue = this.value
+ if (inputValue === undefined) {
+ return
+ }
+
+ if (Array.isArray(inputValue)) {
+ inputValue = inputValue[inputValue.length - 1]
+ if (typeof inputValue === 'object' && inputValue.value) {
+ inputValue = inputValue.value
+ }
+ }
+
+ this.selected = this._findNodePath(inputValue, this.localdata)
+ }
+ }
+}
diff --git a/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.vue b/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.vue
new file mode 100644
index 0000000000000000000000000000000000000000..80075ac59bfcd0beac42bd3da19cde171e6d4314
--- /dev/null
+++ b/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.vue
@@ -0,0 +1,289 @@
+
+
+
+
+
+ {{item.text}}
+
+
+
+
+
+
+ {{item.text}}
+
+
+
+
+
+
+
+ {{errorMessage}}
+
+
+
+
+
+
+
+
diff --git a/uni_modules/uni-data-picker/package.json b/uni_modules/uni-data-picker/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..72cd4ce06afc80f196e6e098dda0589c9e380afb
--- /dev/null
+++ b/uni_modules/uni-data-picker/package.json
@@ -0,0 +1,86 @@
+{
+ "id": "uni-data-picker",
+ "displayName": "DataPicker 数据驱动的picker选择器",
+ "version": "0.2.0",
+ "description": "Picker选择器",
+ "keywords": [
+ "",
+ "picker",
+ "级联",
+ "uni-data-picker",
+ "省市区选择",
+ "地址选择"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "前端组件",
+ "通用组件"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "无",
+ "data": "无",
+ "permissions": "无"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": [
+ "uni-load-more"
+ ],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "微信浏览器(Android)": "y",
+ "QQ浏览器(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "小程序": {
+ "微信": "y",
+ "阿里": "y",
+ "百度": "y",
+ "字节跳动": "y",
+ "QQ": "y"
+ },
+ "快应用": {
+ "华为": "u",
+ "联盟": "u"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/uni_modules/uni-data-picker/readme.md b/uni_modules/uni-data-picker/readme.md
new file mode 100644
index 0000000000000000000000000000000000000000..b449f73be7e693620b765f01395bc1075baad15e
--- /dev/null
+++ b/uni_modules/uni-data-picker/readme.md
@@ -0,0 +1,253 @@
+## DataPicker 级联选择
+> 代码块: `uDataPicker`
+> 关联组件:`uni-data-pickerview`、`uni-load-more`。
+
+
+`` 是一个选择类[datacom组件](https://uniapp.dcloud.net.cn/component/datacom)。
+
+支持单列、和多列级联选择。列数没有限制,如果屏幕显示不全,顶部tab区域会左右滚动。
+
+候选数据支持一次性加载完毕,也支持懒加载,比如示例图中,选择了“北京”后,动态加载北京的区县数据。
+
+`` 组件尤其适用于地址选择、分类选择等选择类。
+
+`` 支持本地数据、云端静态数据(json),uniCloud云数据库数据。
+
+`` 可以通过JQL直连uniCloud云数据库,配套[DB Schema](https://uniapp.dcloud.net.cn/uniCloud/schema),可在schema2code中自动生成前端页面,还支持服务器端校验。
+
+在uniCloud数据表中新建表“uni-id-address”和“opendb-city-china”,这2个表的schema自带foreignKey关联。在“uni-id-address”表的表结构页面使用schema2code生成前端页面,会自动生成地址管理的维护页面,自动从“opendb-city-china”表包含的中国所有省市区信息里选择地址。
+
+
+> 为了避免错误使用,给大家带来不好的开发体验,请在使用组件前仔细阅读下面的注意事项,可以帮你避免一些错误。
+> - 组件需要依赖 `sass` 插件 ,请自行手动安装
+> - 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839
+> - `` 内部包含了弹出层组件 `` 外层的布局可能会影响弹出层,[详情](https://developer.mozilla.org/zh-CN/docs/Web/CSS/Common_CSS_Questions)
+
+
+
+### 平台差异说明
+
+暂不支持在nvue页面中使用
+
+### 安装方式
+
+本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`componets`。
+
+如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55)
+
+## API
+
+### DataPicker Props
+
+|属性名 | 类型 | 可选值 | 默认值 | 说明|
+|:-: | :-: |:-: | :-: | :-: |
+|v-model |String/ Number | - | - |绑定数据|
+|localdata |Array | | |数据,[详情](https://gitee.com/dcloud/datacom)|
+|preload |Boolean | true/false | false |预加载数据|
+|step-searh |Boolean | true/false | true |分步查询时,点击节点请求数据|
+|step-search-url |String | | |分步查询时,动态加载云端数据url格式,`https://xxx.com/{parentValue}`(当前版本暂不支持,下版支持)|
+|self-field |String | | |分步查询时当前字段名称|
+|parent-field |String | | |分步查询时父字段名称|
+|collection |String | | |表名。支持输入多个表名,用 `,` 分割|
+|field |String | | |查询字段,多个字段用 `,` 分割|
+|where |String | | |查询条件,内容较多,另见jql文档:[详情](https://uniapp.dcloud.net.cn/uniCloud/uni-clientDB?id=jsquery)|
+|orderby |String | | |排序字段及正序倒叙设置|
+|popup-title |String | | |弹出层标题|
+
+
+> `collection/where/orderby` 和 `` 的用法一致,[详情](https://uniapp.dcloud.net.cn/uniCloud/unicloud-db)
+
+
+
+### DataPicker Events
+
+|事件称名 | 类型 | 说明 |
+|:-: | :-: | :-: |
+|@change |EventHandle | 选择完成时触发 {detail: {value}} |
+|@nodeclick |EventHandle | 节点被点击时触发 |
+|@stepsearch |EventHandle | 动态加载节点数据前触发(当前版本暂不支持,下版支持) |
+|@popupopened |EventHandle | 弹出层弹出时触发 |
+|@popupclosed |EventHandle | 弹出层关闭时触发 |
+
+
+
+### 基本用法
+
+#### 云端数据
+
+> - 云端数据需要关联服务空间
+> - 下面示例中使用的表 `opendb-city-china`(中国城市省市区数据,含港澳台), 在[uniCloud控制台](https://unicloud.dcloud.net.cn/)使用opendb创建,[详情](https://gitee.com/dcloud/opendb)
+
+
+```html
+
+
+
+
+
+
+
+
+
+```
+
+
+
+
+
+#### 本地数据
+
+```html
+
+
+
+
+
+
+
+
+```
+
+
+#### 自定义solt
+
+```html
+
+
+ {{error}}
+
+
+
+ {{item.text}}
+
+
+
+ 请选择
+
+
+```
+
+
+> `localdata` 和 `collection` 同时配置时,`localdata` 优先
+
+
+
+#### 完整示例
+
+```html
+
+
+
+
+
+
+
+
+
+```
diff --git a/uni_modules/uni-dateformat/changelog.md b/uni_modules/uni-dateformat/changelog.md
new file mode 100644
index 0000000000000000000000000000000000000000..9dee4463dd2dda3cbbd4e763ac6a138d31dc3c21
--- /dev/null
+++ b/uni_modules/uni-dateformat/changelog.md
@@ -0,0 +1,3 @@
+## 0.0.3(2021-02-04)
+- 调整为uni_modules目录规范
+- 修复 iOS 平台日期格式化出错的问题
diff --git a/uni_modules/uni-dateformat/components/uni-dateformat/date-format.js b/uni_modules/uni-dateformat/components/uni-dateformat/date-format.js
new file mode 100644
index 0000000000000000000000000000000000000000..579aded153c433a3ce23bcccff99589b08c74e73
--- /dev/null
+++ b/uni_modules/uni-dateformat/components/uni-dateformat/date-format.js
@@ -0,0 +1,197 @@
+// yyyy-MM-dd hh:mm:ss.SSS 所有支持的类型
+function pad(str, length = 2) {
+ str += ''
+ while (str.length < length) {
+ str = '0' + str
+ }
+ return str.slice(-length)
+}
+
+const parser = {
+ yyyy: (dateObj) => {
+ return pad(dateObj.year, 4)
+ },
+ yy: (dateObj) => {
+ return pad(dateObj.year)
+ },
+ MM: (dateObj) => {
+ return pad(dateObj.month)
+ },
+ M: (dateObj) => {
+ return dateObj.month
+ },
+ dd: (dateObj) => {
+ return pad(dateObj.day)
+ },
+ d: (dateObj) => {
+ return dateObj.day
+ },
+ hh: (dateObj) => {
+ return pad(dateObj.hour)
+ },
+ h: (dateObj) => {
+ return dateObj.hour
+ },
+ mm: (dateObj) => {
+ return pad(dateObj.minute)
+ },
+ m: (dateObj) => {
+ return dateObj.minute
+ },
+ ss: (dateObj) => {
+ return pad(dateObj.second)
+ },
+ s: (dateObj) => {
+ return dateObj.second
+ },
+ SSS: (dateObj) => {
+ return pad(dateObj.millisecond, 3)
+ },
+ S: (dateObj) => {
+ return dateObj.millisecond
+ },
+}
+
+// 这都n年了iOS依然不认识2020-12-12,需要转换为2020/12/12
+function getDate(time) {
+ if (time instanceof Date) {
+ return time
+ }
+ switch (typeof time) {
+ case 'string':
+ {
+ // 2020-12-12T12:12:12.000Z、2020-12-12T12:12:12.000
+ if (time.indexOf('T') > -1) {
+ return new Date(time)
+ }
+ return new Date(time.replace(/-/g, '/'))
+ }
+ default:
+ return new Date(time)
+ }
+}
+
+export function formatDate(date, format = 'yyyy/MM/dd hh:mm:ss') {
+ if (!date && date !== 0) {
+ return ''
+ }
+ date = getDate(date)
+ const dateObj = {
+ year: date.getFullYear(),
+ month: date.getMonth() + 1,
+ day: date.getDate(),
+ hour: date.getHours(),
+ minute: date.getMinutes(),
+ second: date.getSeconds(),
+ millisecond: date.getMilliseconds()
+ }
+ const tokenRegExp = /yyyy|yy|MM|M|dd|d|hh|h|mm|m|ss|s|SSS|SS|S/
+ let flag = true
+ let result = format
+ while (flag) {
+ flag = false
+ result = result.replace(tokenRegExp, function(matched) {
+ flag = true
+ return parser[matched](dateObj)
+ })
+ }
+ return result
+}
+
+export function friendlyDate(time, {
+ locale = 'zh',
+ threshold = [60000, 3600000],
+ format = 'yyyy/MM/dd hh:mm:ss'
+}) {
+ if (!time && time !== 0) {
+ return ''
+ }
+ const localeText = {
+ zh: {
+ year: '年',
+ month: '月',
+ day: '天',
+ hour: '小时',
+ minute: '分钟',
+ second: '秒',
+ ago: '前',
+ later: '后',
+ justNow: '刚刚',
+ soon: '马上',
+ template: '{num}{unit}{suffix}'
+ },
+ en: {
+ year: 'year',
+ month: 'month',
+ day: 'day',
+ hour: 'hour',
+ minute: 'minute',
+ second: 'second',
+ ago: 'ago',
+ later: 'later',
+ justNow: 'just now',
+ soon: 'soon',
+ template: '{num} {unit} {suffix}'
+ }
+ }
+ const text = localeText[locale] || localeText.zh
+ let date = getDate(time)
+ let ms = date.getTime() - Date.now()
+ let absMs = Math.abs(ms)
+ if (absMs < threshold[0]) {
+ return ms < 0 ? text.justNow : text.soon
+ }
+ if (absMs >= threshold[1]) {
+ return formatDate(date, format)
+ }
+ let num
+ let unit
+ let suffix = text.later
+ if (ms < 0) {
+ suffix = text.ago
+ ms = -ms
+ }
+ const seconds = Math.floor((ms) / 1000)
+ const minutes = Math.floor(seconds / 60)
+ const hours = Math.floor(minutes / 60)
+ const days = Math.floor(hours / 24)
+ const months = Math.floor(days / 30)
+ const years = Math.floor(months / 12)
+ switch (true) {
+ case years > 0:
+ num = years
+ unit = text.year
+ break
+ case months > 0:
+ num = months
+ unit = text.month
+ break
+ case days > 0:
+ num = days
+ unit = text.day
+ break
+ case hours > 0:
+ num = hours
+ unit = text.hour
+ break
+ case minutes > 0:
+ num = minutes
+ unit = text.minute
+ break
+ default:
+ num = seconds
+ unit = text.second
+ break
+ }
+
+ if (locale === 'en') {
+ if (num === 1) {
+ num = 'a'
+ } else {
+ unit += 's'
+ }
+ }
+
+ return text.template.replace(/{\s*num\s*}/g, num + '').replace(/{\s*unit\s*}/g, unit).replace(/{\s*suffix\s*}/g,
+ suffix)
+}
diff --git a/uni_modules/uni-dateformat/components/uni-dateformat/uni-dateformat.vue b/uni_modules/uni-dateformat/components/uni-dateformat/uni-dateformat.vue
new file mode 100644
index 0000000000000000000000000000000000000000..af4520551d2ef78033288d0f5b75566668e378ed
--- /dev/null
+++ b/uni_modules/uni-dateformat/components/uni-dateformat/uni-dateformat.vue
@@ -0,0 +1,90 @@
+
+ {{dateShow}}
+
+
+
+
+
diff --git a/uni_modules/uni-dateformat/package.json b/uni_modules/uni-dateformat/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..718062f74a4483e0f8714b810676eb41898a598a
--- /dev/null
+++ b/uni_modules/uni-dateformat/package.json
@@ -0,0 +1,83 @@
+{
+ "id": "uni-dateformat",
+ "displayName": "Dateformat 日期格式化",
+ "version": "0.0.3",
+ "description": "日期格式化组件,可以将日期格式化为1分钟前、刚刚等形式",
+ "keywords": [
+ "日期格式化",
+ "时间格式化",
+ "格式化时间",
+ "",
+ "date-format"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "前端组件",
+ "通用组件"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "无",
+ "data": "无",
+ "permissions": "无"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": [],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "微信浏览器(Android)": "y",
+ "QQ浏览器(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "小程序": {
+ "微信": "y",
+ "阿里": "y",
+ "百度": "y",
+ "字节跳动": "y",
+ "QQ": "y"
+ },
+ "快应用": {
+ "华为": "y",
+ "联盟": "y"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/uni_modules/uni-dateformat/readme.md b/uni_modules/uni-dateformat/readme.md
new file mode 100644
index 0000000000000000000000000000000000000000..e54f7a8131db28ad90bd33a365eedb96ea6d017a
--- /dev/null
+++ b/uni_modules/uni-dateformat/readme.md
@@ -0,0 +1,71 @@
+
+
+### DateFormat 日期格式化
+> 代码块: `uDateformat`
+
+
+日期格式化组件。
+
+### 安装方式
+
+本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。
+
+如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55)
+
+### 基本用法
+
+在 ``template`` 中使用组件
+
+```html
+
+
+
+
+
+```
+
+## API
+
+### Dateformat Props
+
+|属性名 |类型 |默认值 |说明 |
+|:-: |:-: |:-: |:-: |
+|date |Object|String|Number |Date.now() |要格式化的日期对象/日期字符串/时间戳 |
+|threshold |Array |[0, 0] |转化类型阈值 |
+|format |String |'yyyy/MM/dd hh:mm:ss' |格式字符串 |
+|locale |String |zh |格式化使用的语言,目前支持zh(中文)、en(英文) |
+
+
+#### Threshold Options
+
+格式化组件会对时间进行用户友好转化,threshold就是用来控制转化的时间阈值的。
+
+以`[60000, 3600000]`为例,将传入时间与当前时间差的绝对值记为delta(单位毫秒)
+
+- `delta < 60000`时,时间会被转化为“刚刚|马上”
+- `delta >= 60000 && delta < 3600000`时,时间会被转化为“xx分钟前|xx分钟后”,如果超过1小时会显示成“xx小时前|xx小时后”,以此类推
+- `delta >= 3600000`时,会按照format参数传入的格式进行格式化
+
+如果不想转化为“马上|刚刚”可以传入`:threshold = "[0,3600000]"`。默认值`[0,0]`既不会转换为“马上|刚刚”也不会转化为“xx分钟前|xx分钟后”
+
+#### Format Options
+
+format接收字符以及含义如下:
+
+|字符 |说明 |
+|:-: |:-: |
+|yyyy |四位年份 |
+|yy |两位年份 |
+|MM |两位月份(不足两位在前面补0) |
+|M |月份,不自动补0 |
+|dd |两位天(不足两位在前面补0) |
+|d |天,不自动补0 |
+|hh |两位小时(不足两位在前面补0) |
+|h |小时,不自动补0 |
+|mm |两位分钟(不足两位在前面补0) |
+|m |分钟,不自动补0 |
+|ss |两位秒(不足两位在前面补0) |
+|s |秒,不自动补0 |
+|SSS |三位毫秒(不足三位在前面补0) |
+|S |毫秒,不自动补0 |
+
diff --git a/uni_modules/uni-datetime-picker/changelog.md b/uni_modules/uni-datetime-picker/changelog.md
new file mode 100644
index 0000000000000000000000000000000000000000..223a003b8685c32caf5d67e256b75b4b2356968e
--- /dev/null
+++ b/uni_modules/uni-datetime-picker/changelog.md
@@ -0,0 +1,6 @@
+## 1.0.6(2021-03-18)
+- 新增 hide-second 属性,时间支持仅选择时、分
+- 修复 选择跟显示的日期不一样的 bug
+- 修复 chang事件触发2次的 bug
+- 修复 分、秒 end 范围错误的 bug
+- 优化 更好的 nvue 适配
diff --git a/uni_modules/uni-datetime-picker/components/uni-datetime-picker/keypress.js b/uni_modules/uni-datetime-picker/components/uni-datetime-picker/keypress.js
new file mode 100644
index 0000000000000000000000000000000000000000..9601abae31babfc7ce5892085b07dab20ae355b0
--- /dev/null
+++ b/uni_modules/uni-datetime-picker/components/uni-datetime-picker/keypress.js
@@ -0,0 +1,45 @@
+// #ifdef H5
+export default {
+ name: 'Keypress',
+ props: {
+ disable: {
+ type: Boolean,
+ default: false
+ }
+ },
+ mounted () {
+ const keyNames = {
+ esc: ['Esc', 'Escape'],
+ tab: 'Tab',
+ enter: 'Enter',
+ space: [' ', 'Spacebar'],
+ up: ['Up', 'ArrowUp'],
+ left: ['Left', 'ArrowLeft'],
+ right: ['Right', 'ArrowRight'],
+ down: ['Down', 'ArrowDown'],
+ delete: ['Backspace', 'Delete', 'Del']
+ }
+ const listener = ($event) => {
+ if (this.disable) {
+ return
+ }
+ const keyName = Object.keys(keyNames).find(key => {
+ const keyName = $event.key
+ const value = keyNames[key]
+ return value === keyName || (Array.isArray(value) && value.includes(keyName))
+ })
+ if (keyName) {
+ // 避免和其他按键事件冲突
+ setTimeout(() => {
+ this.$emit(keyName, {})
+ }, 0)
+ }
+ }
+ document.addEventListener('keyup', listener)
+ this.$once('hook:beforeDestroy', () => {
+ document.removeEventListener('keyup', listener)
+ })
+ },
+ render: () => {}
+}
+// #endif
\ No newline at end of file
diff --git a/uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue b/uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue
new file mode 100644
index 0000000000000000000000000000000000000000..4a09b4b914f1c29d966e58fb8dfb2e17aa305af8
--- /dev/null
+++ b/uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue
@@ -0,0 +1,903 @@
+
+
+
+
+
+ {{time}}
+
+ 选择{{title}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/uni-datetime-picker/package.json b/uni_modules/uni-datetime-picker/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..40ce95d63a359f985eb9caf85084fc1c86ac580c
--- /dev/null
+++ b/uni_modules/uni-datetime-picker/package.json
@@ -0,0 +1,82 @@
+{
+ "id": "uni-datetime-picker",
+ "displayName": "DatetimePicker 日期选择器",
+ "version": "1.0.6",
+ "description": "DatetimePicker 可以同时选择日期和时间的选择器",
+ "keywords": [
+ "DatetimePicker",
+ "uni-ui",
+ "日期时间选择器",
+ "日期时间"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "前端组件",
+ "通用组件"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "无",
+ "data": "无",
+ "permissions": "无"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": [],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "n"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "微信浏览器(Android)": "y",
+ "QQ浏览器(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "小程序": {
+ "微信": "y",
+ "阿里": "y",
+ "百度": "y",
+ "字节跳动": "y",
+ "QQ": "y"
+ },
+ "快应用": {
+ "华为": "u",
+ "联盟": "u"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/uni_modules/uni-datetime-picker/readme.md b/uni_modules/uni-datetime-picker/readme.md
new file mode 100644
index 0000000000000000000000000000000000000000..f263ca88a97df9967a27c746d2d7c35d820364e0
--- /dev/null
+++ b/uni_modules/uni-datetime-picker/readme.md
@@ -0,0 +1,61 @@
+
+
+## DatetimePicker 时间选择器
+> 代码块: `uDatetimePicker`
+
+
+该组件的优势是,支持**时间戳**输入和输出(起始时间、终止时间也支持时间戳),可**同时选择**日期和时间。
+
+若只是需要单独选择日期和时间,不需要时间戳输入和输出,可使用原生的 picker 组件。
+
+
+___点击 picker 默认值规则:___
+
+- 若设置初始值 value, 会显示在 picker 显示框中; 若无初始值 value,则初始值 value 为当前本地时间 Date.now(), 但不会显示在 picker 显示框中
+ - 设置了起始时间 start、终止时间 end,并 start < value < end,初始值为 value, 否则初始值为 start
+ - 只设置了起始时间 start,并 start < value,初始值为 value,否则初始值为 start
+ - 只设置了终止时间 end,并 value < end,初始值为 value,否则初始值为 end
+ - 无起始终止时间,则初始值为 value
+
+### 安装方式
+
+本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。
+
+如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55)
+
+### 基本用法
+
+在 ``template`` 中使用组件
+
+```html
+
+
+
+
+
+```
+
+## API
+
+### DatetimePicker Props
+
+|属性名 |类型 |默认值 |值域 |说明 |
+|:-: |:-: |:-: | |:-: |
+|type |String |datetime |datetime、date、time |选择器类型 |
+|value |String、Number |- |- |输入框当前值 |
+|start |String、Number |- |- |最小值,可以使用日期的字符串(String)、时间戳(Number) |
+|end |String、Number |- |- |最大值,可以使用日期的字符串(String)、时间戳(Number) |
+|return-type|String |timestamp|timestamp 、string |返回值格式 |
+|border |Boolean、String|true | |是否有边框 |
+|hide-second|Boolean、String|false | |是否隐藏秒 |
+|disabled |Boolean、String|false | |是否不可选择 |
+
+
+
+注:如 type 为 time 类型,无对应的时间戳,则返回值格式 return-type 无论为何值,都会返回 string
+
+### DatetimePicker Events
+
+|事件名称 |说明 |返回值 |
+|:-: |:-: |:-: |
+|change |确定日期时间时触发的事件,参数为当前选择的 value |- |
\ No newline at end of file
diff --git a/uni_modules/uni-drawer/changelog.md b/uni_modules/uni-drawer/changelog.md
new file mode 100644
index 0000000000000000000000000000000000000000..bd9ce336a0a64b556edfe013b6ffb42a28948808
--- /dev/null
+++ b/uni_modules/uni-drawer/changelog.md
@@ -0,0 +1,2 @@
+## 1.0.6(2021-02-04)
+- 调整为uni_modules目录规范
diff --git a/uni_modules/uni-drawer/components/uni-drawer/keypress.js b/uni_modules/uni-drawer/components/uni-drawer/keypress.js
new file mode 100644
index 0000000000000000000000000000000000000000..6ef26a26211ff28976e6fc835fbef5d2ea5b5b1e
--- /dev/null
+++ b/uni_modules/uni-drawer/components/uni-drawer/keypress.js
@@ -0,0 +1,45 @@
+// #ifdef H5
+export default {
+ name: 'Keypress',
+ props: {
+ disable: {
+ type: Boolean,
+ default: false
+ }
+ },
+ mounted () {
+ const keyNames = {
+ esc: ['Esc', 'Escape'],
+ tab: 'Tab',
+ enter: 'Enter',
+ space: [' ', 'Spacebar'],
+ up: ['Up', 'ArrowUp'],
+ left: ['Left', 'ArrowLeft'],
+ right: ['Right', 'ArrowRight'],
+ down: ['Down', 'ArrowDown'],
+ delete: ['Backspace', 'Delete', 'Del']
+ }
+ const listener = ($event) => {
+ if (this.disable) {
+ return
+ }
+ const keyName = Object.keys(keyNames).find(key => {
+ const keyName = $event.key
+ const value = keyNames[key]
+ return value === keyName || (Array.isArray(value) && value.includes(keyName))
+ })
+ if (keyName) {
+ // 避免和其他按键事件冲突
+ setTimeout(() => {
+ this.$emit(keyName, {})
+ }, 0)
+ }
+ }
+ document.addEventListener('keyup', listener)
+ this.$once('hook:beforeDestroy', () => {
+ document.removeEventListener('keyup', listener)
+ })
+ },
+ render: () => {}
+}
+// #endif
diff --git a/uni_modules/uni-drawer/components/uni-drawer/uni-drawer.vue b/uni_modules/uni-drawer/components/uni-drawer/uni-drawer.vue
new file mode 100644
index 0000000000000000000000000000000000000000..1081fe5c2ec0cf7662eb6f0bc00b18da5861acb5
--- /dev/null
+++ b/uni_modules/uni-drawer/components/uni-drawer/uni-drawer.vue
@@ -0,0 +1,181 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/uni-drawer/package.json b/uni_modules/uni-drawer/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..c425744a2faedf750ace5972512be456814483d2
--- /dev/null
+++ b/uni_modules/uni-drawer/package.json
@@ -0,0 +1,83 @@
+{
+ "id": "uni-drawer",
+ "displayName": "Drawer 抽屉",
+ "version": "1.0.6",
+ "description": "抽屉式导航,用于展示侧滑菜单,侧滑导航。",
+ "keywords": [
+ "drawer",
+ "uni-ui",
+ "抽屉",
+ "侧滑导航",
+ "侧滑"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "前端组件",
+ "通用组件"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "无",
+ "data": "无",
+ "permissions": "无"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": [],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "微信浏览器(Android)": "y",
+ "QQ浏览器(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "小程序": {
+ "微信": "y",
+ "阿里": "y",
+ "百度": "y",
+ "字节跳动": "y",
+ "QQ": "y"
+ },
+ "快应用": {
+ "华为": "u",
+ "联盟": "u"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/uni_modules/uni-drawer/readme.md b/uni_modules/uni-drawer/readme.md
new file mode 100644
index 0000000000000000000000000000000000000000..00e2ba41dbd3917445ed3429097c5b59d32b8a2b
--- /dev/null
+++ b/uni_modules/uni-drawer/readme.md
@@ -0,0 +1,59 @@
+
+
+## Drawer 抽屉
+> 代码块: `uDrawer`
+
+
+抽屉侧滑菜单。
+
+> 为了避免错误使用,给大家带来不好的开发体验,请在使用组件前仔细阅读下面的注意事项,可以帮你避免一些错误。
+> - `width` 属性仅在 `vue` 页面生效,`nvue` 页面因性能问题,不支持动态设置宽度,如需修改,请下载组件修改源码
+
+
+### 安装方式
+
+本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。
+
+如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55)
+
+### 基本用法
+
+
+在 ``template`` 中使用组件
+
+```html
+
+
+ 抽屉式导航
+
+
+```
+
+## API
+
+### Drawer Props
+
+|属性名 |类型 |默认值 |说明 |
+|:-: |:-: |:-: |:-: |
+|mask |Boolean|true |是否显示遮罩 |
+|maskClick |Boolean|true |点击遮罩是否可以关闭抽屉 |
+|mode |String |left |Drawe滑出位置,可选值:left(从左侧滑出), right(从右侧滑出)|
+|width |Number |220 |Drawe 宽度,仅vue页面设置生效 |
+
+
+
+
+### Drawer Events
+
+|事件名 |说明 |返回值 |
+|:-: |:-: |:-: |
+|@change|抽屉状态发生变化触发事件 |true:抽屉已经打开;false:抽屉已经关闭; |
+
+### Drawer Methods
+
+|方法称名 |说明 |参数|
+|:-: |:-: |:-:|
+|open |打开抽屉 |-|
+|close |关闭抽屉 |-|
+
+
diff --git a/uni_modules/uni-easyinput/changelog.md b/uni_modules/uni-easyinput/changelog.md
new file mode 100644
index 0000000000000000000000000000000000000000..c6516a87ed57cab119458aabf93feac6c82cbe75
--- /dev/null
+++ b/uni_modules/uni-easyinput/changelog.md
@@ -0,0 +1,3 @@
+## 0.0.9(2021-02-05)
+- 调整为uni_modules目录规范
+- 优化 兼容 nvue 页面
diff --git a/uni_modules/uni-easyinput/components/uni-easyinput/common.js b/uni_modules/uni-easyinput/components/uni-easyinput/common.js
new file mode 100644
index 0000000000000000000000000000000000000000..df9abe1da71fd2245aba33c6d31dadd62e39c47c
--- /dev/null
+++ b/uni_modules/uni-easyinput/components/uni-easyinput/common.js
@@ -0,0 +1,56 @@
+/**
+ * @desc 函数防抖
+ * @param func 目标函数
+ * @param wait 延迟执行毫秒数
+ * @param immediate true - 立即执行, false - 延迟执行
+ */
+export const debounce = function(func, wait = 1000, immediate = true) {
+ let timer;
+ console.log(1);
+ return function() {
+ console.log(123);
+ let context = this,
+ args = arguments;
+ if (timer) clearTimeout(timer);
+ if (immediate) {
+ let callNow = !timer;
+ timer = setTimeout(() => {
+ timer = null;
+ }, wait);
+ if (callNow) func.apply(context, args);
+ } else {
+ timer = setTimeout(() => {
+ func.apply(context, args);
+ }, wait)
+ }
+ }
+}
+/**
+ * @desc 函数节流
+ * @param func 函数
+ * @param wait 延迟执行毫秒数
+ * @param type 1 使用表时间戳,在时间段开始的时候触发 2 使用表定时器,在时间段结束的时候触发
+ */
+export const throttle = (func, wait = 1000, type = 1) => {
+ let previous = 0;
+ let timeout;
+ return function() {
+ let context = this;
+ let args = arguments;
+ if (type === 1) {
+ let now = Date.now();
+
+ if (now - previous > wait) {
+ func.apply(context, args);
+ previous = now;
+ }
+ } else if (type === 2) {
+ if (!timeout) {
+ timeout = setTimeout(() => {
+ timeout = null;
+ func.apply(context, args)
+ }, wait)
+ }
+ }
+ }
+}
diff --git a/uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue b/uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue
new file mode 100644
index 0000000000000000000000000000000000000000..ac338bbe20d6038a125e6cc318ce537642e5cd58
--- /dev/null
+++ b/uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue
@@ -0,0 +1,427 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/uni-easyinput/package.json b/uni_modules/uni-easyinput/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..03d399c0c975af4a2236b255d0515349e876982e
--- /dev/null
+++ b/uni_modules/uni-easyinput/package.json
@@ -0,0 +1,83 @@
+{
+ "id": "uni-easyinput",
+ "displayName": "Easyinput 增强输入框",
+ "version": "0.0.9",
+ "description": "Easyinput 组件是对原生input组件的增强",
+ "keywords": [
+ "input",
+ "uni-easyinput",
+ "输入框"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "前端组件",
+ "通用组件"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "无",
+ "data": "无",
+ "permissions": "无"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": [
+ "uni-icons"
+ ],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "微信浏览器(Android)": "y",
+ "QQ浏览器(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "小程序": {
+ "微信": "y",
+ "阿里": "y",
+ "百度": "y",
+ "字节跳动": "y",
+ "QQ": "y"
+ },
+ "快应用": {
+ "华为": "u",
+ "联盟": "u"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/uni_modules/uni-easyinput/readme.md b/uni_modules/uni-easyinput/readme.md
new file mode 100644
index 0000000000000000000000000000000000000000..945d635a76410c0e87989989d0d20eca75670ce6
--- /dev/null
+++ b/uni_modules/uni-easyinput/readme.md
@@ -0,0 +1,192 @@
+
+
+### Easyinput 增强输入框
+> 代码块: `uEasyinput`
+
+
+easyinput 组件是对原生input组件的增强 ,是专门为配合表单组件[uni-forms](https://ext.dcloud.net.cn/plugin?id=2773)而设计的,easyinput 内置了边框,图标等,同时包含 input 所有功能
+
+
+> 为了避免错误使用,给大家带来不好的开发体验,请在使用组件前仔细阅读下面的注意事项,可以帮你避免一些错误。
+> - 组件需要依赖 `sass` 插件 ,请自行手动安装
+> - 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839
+
+
+### 平台差异说明
+
+暂不支持在nvue页面中使用
+
+### 安装方式
+
+本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。
+
+如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55)
+
+### 基本用法
+
+输入内容后,输入框尾部会显示清除按钮,点击可清除内容,如不需要展示图标,`clearable` 属性设置为 `false` 即可
+
+`clearable` 属性设置为 `true` ,输入框聚焦且内容不为空时,才会显示内容
+
+```html
+
+```
+
+
+### 输入框带左右图标
+
+设置 `prefixIcon` 属性来显示输入框的头部图标
+
+设置 `suffixIcon` 属性来显示输入框的尾部图标
+
+注意图标当前只支持 `uni-icons` 内置的图标,当配置 `suffixIcon` 属性后,会覆盖 `:clearable="true"` 和 `type="password"` 时的原有图标
+
+绑定 `@iconClick` 事件可以触发图标的点击 ,返回 `prefix` 表示点击左侧图标,返回 `suffix` 表示点击右侧图标
+
+```html
+
+
+
+
+
+```
+
+### 输入框禁用
+
+设置 `disable` 属性可以禁用输入框,此时输入框不可编辑
+
+```html
+
+```
+
+### 密码框
+
+设置 `type="password"` 时,输入框内容将会不可见,由实心点代替,同时输入框尾部会显示眼睛图标,点击可切换内容显示状态
+
+```html
+
+```
+
+### 输入框聚焦
+
+设置 `focus` 属性可以使输入框聚焦
+
+如果页面存在多个设置 `focus` 属性的输入框,只有最后一个输入框的 `focus` 属性会生效
+
+```html
+
+```
+
+
+### 多行文本
+
+设置 `type="textarea"` 时可输入多行文本
+
+```html
+
+```
+
+### 多行文本自动高度
+
+设置 `type="textarea"` 时且设置 `autoHeight` 属性,可使用多行文本的自动高度,会跟随内容调整输入框的显示高度
+
+```html
+
+```
+
+### 取消边框
+
+设置 `:inputBorder="false"` 时可取消输入框的边框显示,同时搭配 `uni-forms` 的 `:border="true"` 有较好的效果
+
+```html
+
+
+
+
+
+
+
+
+```
+
+
+## API
+
+### Easyinput Props
+
+|属性名 | 类型 | 可选值 | 默认值 | 说明|
+|:-: | :-: |:-: | :-: | :-: |
+|value |String/ Number | - | - |输入内容|
+|type |String | 见 type Options |text| 输入框的类型(默认text) |
+|clearable |Boolean | - |true| 是否显示右侧清空内容的图标控件(输入框有内容,且获得焦点时才显示),点击可清空输入框内容|
+|autoHeight |Boolean | - |false| 是否自动增高输入区域,type为textarea时有效|
+|placeholder |String | - | - | 输入框的提示文字|
+|placeholderStyle |String | - | - | placeholder的样式(内联样式,字符串),如"color: #ddd"|
+|focus |Boolean | - |false| 是否自动获得焦点|
+|disabled |Boolean | - |false| 是否不可输入|
+|maxlength |Number | - |140| 最大输入长度,设置为 -1 的时候不限制最大长度|
+|confirmType |String | - |done| 设置键盘右下角按钮的文字,仅在type="text"时生效|
+|clearSize |Number | - |15| 清除图标的大小,单位px|
+|prefixIcon |String | - | - |输入框头部图标 |
+|suffixIcon |String | - | - |输入框尾部图标|
+|trim |Boolean/String | 见 trim Options | false | 是否自动去除空格,传入类型为 Boolean 时,自动去除前后空格|
+|inputBorder |Boolean | - |false| 是否显示input输入框的边框|
+|styles |Object | - | - | 样式自定义|
+
+
+#### Type Options
+
+|属性名 | 说明 |
+|:-: | :-: |
+|text |文本输入键盘 |
+|textarea |多行文本输入键盘 |
+|password |密码输入键盘 |
+|number |数字输入键盘,注意iOS上app-vue弹出的数字键盘并非9宫格方式 |
+|idcard |身份证输入键盘,仅支持微信、支付宝、百度、QQ小程序 |
+|digit |带小数点的数字键盘,仅支持微信、支付宝、百度、头条、QQ小程序 |
+
+#### ConfirmType Options
+
+平台差异与 [input](https://uniapp.dcloud.io/component/input) 相同
+
+|属性名 | 说明 |
+|:-: | :-: |
+|send |右下角按钮为“发送” |
+|search |右下角按钮为“搜索” |
+|next |右下角按钮为“下一个”|
+|go |右下角按钮为“前往” |
+|done |右下角按钮为“完成” |
+
+
+#### Styles Options
+
+|属性名 | 默认值 |说明 |
+|:-: | :-: | :-: |
+|color | #333 | 输入文字颜色 |
+|disableColor |#eee | 输入框禁用背景色 |
+|borderColor |#e5e5e5 | 边框颜色 |
+
+#### Trim Options
+
+传入类型为 `Boolean` 时,自动去除前后空格,传入类型为 `String` 时,可以单独控制,下面是可选值
+
+|属性名 |说明 |
+|:-: | :-: |
+|both | 去除两端空格 |
+|left | 去除左侧空格 |
+|right | 去除右侧空格 |
+|all | 去除所有空格 |
+|none | 不去除空格 |
+
+
+### Easyinput Events
+
+|事件称名 | 说明 |返回值 |
+|:-: | :-: |:-: |
+|@input |输入框内容发生变化时触发 | - |
+|@focus |输入框获得焦点时触发 | - |
+|@blur |输入框失去焦点时触发 | - |
+|@confirm |点击完成按钮时触发 | - |
+|@iconClick |点击图标时触发 | prefix/suffix |
+
+
diff --git a/uni_modules/uni-fab/changelog.md b/uni_modules/uni-fab/changelog.md
new file mode 100644
index 0000000000000000000000000000000000000000..d8e69eb9c55e8f815ffd585eebb78236bc0bf446
--- /dev/null
+++ b/uni_modules/uni-fab/changelog.md
@@ -0,0 +1,4 @@
+## 1.0.6(2021-02-05)
+- 调整为uni_modules目录规范
+- 优化 按钮背景色调整
+- 优化 兼容pc端
diff --git a/uni_modules/uni-fab/components/uni-fab/uni-fab.vue b/uni_modules/uni-fab/components/uni-fab/uni-fab.vue
new file mode 100644
index 0000000000000000000000000000000000000000..e6fe5a9e6083504bfc21a543dfa7d01a38298916
--- /dev/null
+++ b/uni_modules/uni-fab/components/uni-fab/uni-fab.vue
@@ -0,0 +1,447 @@
+
+
+
+
+
+
+
+ {{ item.text }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/uni-fab/components/uni-fab/uni-fab.vue.bak b/uni_modules/uni-fab/components/uni-fab/uni-fab.vue.bak
new file mode 100644
index 0000000000000000000000000000000000000000..9df4dcd7f5958b17b962e9d37c52c298d549ad00
--- /dev/null
+++ b/uni_modules/uni-fab/components/uni-fab/uni-fab.vue.bak
@@ -0,0 +1,383 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.text }}
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/uni-fab/package.json b/uni_modules/uni-fab/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..4fbe37684c8762da7e8dd191c1d3fc72cef2409a
--- /dev/null
+++ b/uni_modules/uni-fab/package.json
@@ -0,0 +1,82 @@
+{
+ "id": "uni-fab",
+ "displayName": "Fab 悬浮按钮",
+ "version": "1.0.6",
+ "description": "悬浮按钮 fab button ,点击可展开一个图标按钮菜单。",
+ "keywords": [
+ "按钮",
+ "悬浮按钮",
+ "fab",
+ "uni-fab"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "前端组件",
+ "通用组件"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "无",
+ "data": "无",
+ "permissions": "无"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": [],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "微信浏览器(Android)": "y",
+ "QQ浏览器(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "小程序": {
+ "微信": "y",
+ "阿里": "y",
+ "百度": "y",
+ "字节跳动": "y",
+ "QQ": "y"
+ },
+ "快应用": {
+ "华为": "u",
+ "联盟": "u"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/uni_modules/uni-fab/readme.md b/uni_modules/uni-fab/readme.md
new file mode 100644
index 0000000000000000000000000000000000000000..725f67a3d72982594cae7e7c1f3d14051b4b13bb
--- /dev/null
+++ b/uni_modules/uni-fab/readme.md
@@ -0,0 +1,84 @@
+
+
+## Fab 悬浮按钮
+> 代码块: `uFab`
+
+
+点击可展开一个图形按钮菜单
+
+### 安装方式
+
+本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。
+
+如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55)
+
+> 为了避免错误使用,给大家带来不好的开发体验,请在使用组件前仔细阅读下面的注意事项,可以帮你避免一些错误。
+> - 不建议动态修改属性,可能会耗损部分性能。
+> - 展开菜单暂不支持字体图标,使用图片路径时建议使用绝对路径,相对路径可能会有问题。
+> - 选中状态要通过自己控制,如果不希望有选中状态,不处理 `active` 即可。
+> - 展开菜单建议最多显示四个,如果过多对于小屏手机可能会超出屏幕。
+
+
+### 基本用法
+
+在 `template` 中使用组件
+
+```html
+
+
+
+
+
+```
+
+
+## API
+
+### Fab Props
+
+| 属性名 | 类型 | 默认值 | 说明 |
+| :-: | :-: | :-: | :-: |
+| pattern | Object | - | 可选样式配置项 |
+| horizontal| String | 'left' | 水平对齐方式。`left`:左对齐,`right`:右对齐 |
+| vertical | String | 'bottom' | 垂直对齐方式。`bottom`:下对齐,`top`:上对齐 |
+| direction | String | 'horizontal' | 展开菜单显示方式。`horizontal`:水平显示,`vertical`:垂直显示 |
+| popMenu | Boolean | true | 是否使用弹出菜单 |
+| content | Array | - | 展开菜单内容配置项 |
+
+
+
+**pattern配置项:**
+
+| 参数 | 类型 | 默认值 | 说明 |
+| :-: | :-: | :-: | :-: |
+| color | String | #3c3e49 | 文字默认颜色 |
+| selectedColor | String | #007AFF | 文字选中时的颜色 |
+| backgroundColor | String | #ffffff | 背景色 |
+| buttonColor | String | #3c3e49 | 按钮背景色 |
+
+**content配置项:**
+
+| 参数 | 类型 | 说明 |
+| :-: | :-: | :-: | :-: |
+| iconPath | String | 图片路径 |
+| selectedIconPath | String | 选中后图片路径|
+| text | String | 文字 |
+| active | Boolean | 是否选中当前 |
+
+### Fab Events
+
+| 参数 | 类型 | 说明 |
+| :-: | :-: | :-: |
+| @trigger | Function | 展开菜单点击事件,返回点击信息|
+| @fabClick | Function | 悬浮按钮点击事件 |
+
+
+
+
diff --git a/uni_modules/uni-fav/changelog.md b/uni_modules/uni-fav/changelog.md
new file mode 100644
index 0000000000000000000000000000000000000000..33e5d90c278ff41a0084db68e9da473b1bc44483
--- /dev/null
+++ b/uni_modules/uni-fav/changelog.md
@@ -0,0 +1,6 @@
+## 1.0.4(2021-02-05)
+- 优化 组件引用关系,通过uni_modules引用组件
+## 1.0.3(2021-02-05)
+- 优化 组件引用关系,通过uni_modules引用组件
+## 1.0.2(2021-02-05)
+- 调整为uni_modules目录规范
diff --git a/uni_modules/uni-fav/components/uni-fav/uni-fav.vue b/uni_modules/uni-fav/components/uni-fav/uni-fav.vue
new file mode 100644
index 0000000000000000000000000000000000000000..42144b520f9bd539678e5818b48fc0b98c80fc54
--- /dev/null
+++ b/uni_modules/uni-fav/components/uni-fav/uni-fav.vue
@@ -0,0 +1,139 @@
+
+
+
+
+
+
+
+
+
+
+ {{ checked ? contentText.contentFav : contentText.contentDefault }}
+
+
+
+
+
+
diff --git a/uni_modules/uni-fav/package.json b/uni_modules/uni-fav/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..11e28e39921b30410e976556d549db3fb1170994
--- /dev/null
+++ b/uni_modules/uni-fav/package.json
@@ -0,0 +1,81 @@
+{
+ "id": "uni-fav",
+ "displayName": "Fav 收藏按钮",
+ "version": "1.0.4",
+ "description": " Fav 收藏组件,可自定义颜色、大小。",
+ "keywords": [
+ "fav",
+ "uni-ui",
+ "收藏"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "前端组件",
+ "通用组件"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "无",
+ "data": "无",
+ "permissions": "无"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": [],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "微信浏览器(Android)": "y",
+ "QQ浏览器(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "小程序": {
+ "微信": "y",
+ "阿里": "y",
+ "百度": "y",
+ "字节跳动": "y",
+ "QQ": "y"
+ },
+ "快应用": {
+ "华为": "u",
+ "联盟": "u"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/uni_modules/uni-fav/readme.md b/uni_modules/uni-fav/readme.md
new file mode 100644
index 0000000000000000000000000000000000000000..d4a70092d6a65ee8b4163d9b0d3784bb23988f08
--- /dev/null
+++ b/uni_modules/uni-fav/readme.md
@@ -0,0 +1,44 @@
+
+
+## Fav 收藏按钮
+> 代码块: `uFav`
+
+
+用于收藏功能,可点击切换选中、不选中的状态。
+
+### 安装方式
+
+本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。
+
+如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55)
+
+### 基本用法
+
+在 ``template`` 中使用组件
+
+```html
+
+
+```
+
+## API
+
+### Fav Props
+
+|属性名 |类型 |默认值 |说明 |
+|:-: |:-: |:-: |:-: |
+|star |Boolean|true |按钮是否带星星 |
+|bgColor |String |#eeeeee |未收藏时的背景色 |
+|bgColorChecked |String |#007aff |已收藏时的背景色 |
+|fgColor |String |#666666 |未收藏时的文字颜色 |
+|fgColorChecked |String |#FFFFFF |已收藏时的文字颜色 |
+|circle |Boolean|false |是否为圆角 |
+|checked |Boolean|false |是否为已收藏 |
+|contentText |Object |```{contentDefault: '收藏',contentFav: '已收藏'}```|收藏按钮文字 |
+
+
+### Fav Events
+
+|事件称名 |说明 |返回值 |
+|:-: |:-: |:-: |
+|click |点击 fav按钮 触发事件 |- |
diff --git a/uni_modules/uni-field/changelog.md b/uni_modules/uni-field/changelog.md
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/uni_modules/uni-field/components/uni-field/uni-field.vue b/uni_modules/uni-field/components/uni-field/uni-field.vue
new file mode 100644
index 0000000000000000000000000000000000000000..e55d8cec97dfd743892ee7982500a1bde2c16318
--- /dev/null
+++ b/uni_modules/uni-field/components/uni-field/uni-field.vue
@@ -0,0 +1,712 @@
+
+
+
+
+
+
+
+
+
+ {{ label }}
+
+ {{ msg }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ msg }}
+
+
+
+
+
+
+
diff --git a/uni_modules/uni-field/package.json b/uni_modules/uni-field/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..8163fb75cac4a3432669f5e040511ec2fbbb6cf6
--- /dev/null
+++ b/uni_modules/uni-field/package.json
@@ -0,0 +1,79 @@
+{
+ "id": "uni-field",
+ "displayName": "Field 输入框",
+ "version": "1.0.0",
+ "description": "",
+ "keywords": [
+ ""
+ ],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "前端组件",
+ "通用组件"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "无",
+ "data": "无",
+ "permissions": "无"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": [],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "u",
+ "aliyun": "u"
+ },
+ "client": {
+ "App": {
+ "app-vue": "u",
+ "app-nvue": "u"
+ },
+ "H5-mobile": {
+ "Safari": "u",
+ "Android Browser": "u",
+ "微信浏览器(Android)": "u",
+ "QQ浏览器(Android)": "u"
+ },
+ "H5-pc": {
+ "Chrome": "u",
+ "IE": "u",
+ "Edge": "u",
+ "Firefox": "u",
+ "Safari": "u"
+ },
+ "小程序": {
+ "微信": "u",
+ "阿里": "u",
+ "百度": "u",
+ "字节跳动": "u",
+ "QQ": "u"
+ },
+ "快应用": {
+ "华为": "u",
+ "联盟": "u"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/uni_modules/uni-field/readme.md b/uni_modules/uni-field/readme.md
new file mode 100644
index 0000000000000000000000000000000000000000..ffebb33f9e383f1011874f692731dbe38e1049e5
--- /dev/null
+++ b/uni_modules/uni-field/readme.md
@@ -0,0 +1,165 @@
+### Field 输入框
+
+输入框组件一般和表单控件 uni-form 配合使用,也可以单独使用,用于实现输入与校验,包括 "text" 和 "textarea" 类型,组件名:``uni-field``,代码块: uField。
+
+### 平台差异说明
+
+暂不支持在nvue页面中使用
+
+### 组件使用注意事项
+
+为了避免错误使用,给大家带来不好的开发体验,请在使用组件前仔细阅读下面的注意事项,可以帮你避免一些错误。
+
+- 组件需要依赖 `sass` 插件 ,请自行手动安装
+- 组件校验需要依赖 `uni-forms` 组件的`forms-rule`属性,`uni-field` 组件暂时不支持单独校验内容
+- 组件提供了右侧按钮的插槽,可传入 ``slot="right"``的标签或组件,例如发送验证码的按钮:````
+- 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839
+
+### 使用方式
+
+#### 方式1 (推荐)
+
+`HBuilderX 2.5.5`起支持 `easycom` 组件模式。在使用 `uni-ui` 的时候,只要[`uni-ui` 组件](https://ext.dcloud.net.cn/plugin?id=55) 安装在项目的 `components` 目录下,并符合 `components/组件名称/组件名称.vue` 目录结构。就可以不用引用、注册,直接在页面中使用 `uni-ui` 组件
+
+`easycom` 组件模式的好处在于不管 `components` 目录下安装了多少组件,`easycom` 打包后会自动剔除没有使用的组件,对组件库的使用尤为友好,组件库批量安装,随意使用,自动按需打包。 关于 `easycom` 更详细内容 [参考文档](https://uniapp.dcloud.io/collocation/pages?id=easycom)
+
+#### 方式2(vue-cli)
+
+**初始化项目**
+
+如果是使用 `HBuiderX` 创建的项目,需先执行以下命令初始化:
+
+```
+npm init -y
+```
+
+**安装 uni-ui**
+
+```
+npm install @dcloudio/uni-ui -D
+```
+
+在 ``script`` 中引用组件
+
+```javascript
+import uniField from '@/components/uni-field/uni-field.vue'
+export default {
+ components: {uniField}
+}
+```
+
+#### 方式3(vue-cli + easycom)
+
+使用 `方式2` 安装好 `uni-ui` 之后,需要配置 `easycom` 规则,让 `npm` 安装的组件支持 `easycom`
+
+打开项目根目录下的 `pages.json` 并添加 `easycom` 节点:
+
+```javascript
+// pages.json
+
+{
+ "easycom": {
+ "autoscan": true,
+ "custom": {
+ // uni-ui 规则如下配置
+ "^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue"
+ }
+ },
+
+ // 其他内容
+ pages:[
+ // ...
+ ]
+}
+
+```
+
+### 基本用法
+
+在 ``template`` 中使用组件
+
+```html
+
+
+
+
+
+```
+
+### uni-field 属性说明
+
+**uni-field 属性说明**
+
+属性名 |类型 |默认值 |说明
+:-: |:-: |:-: |:-:
+type |String | text | 输入框的类型
+required |Boolean| false | 是否必填,左边您显示红色"*"号
+left-icon |String | - | label左边的图标,限uni-ui的图标名称
+icon-color |String | #606266 | 左边通过icon配置的图标的颜色
+right-icon |Boolean| false | 输入框右边的图标名称,限uni-ui的图标名称
+label |String | - | 输入框左边的文字提示
+label-width |Number | 65 | label的宽度,单位px
+label-align |String | left | label的文字对齐方式
+label-position |String | left | label的文字的位置
+clearable |Boolean| true | 是否显示右侧清空内容的图标控件(输入框有内容,且获得焦点时显示),点击可清空输入框内容
+placeholder |String | - | 输入框的提示文字
+placeholder-style |String | - | placeholder的样式(内联样式,字符串),如color: #ddd"
+password |Boolean| false | 是否密码输入方式(用点替换文字),type为text时有效
+focus |Boolean| false | 是否自动获得焦点
+disabled |Boolean| false | 是否不可输入
+maxlength |Number | 140 | 最大输入长度,设置为 -1 的时候不限制最大长度
+confirm-type |String | done | 设置键盘右下角按钮的文字,仅在type="text"时生效
+clear-size |Number | 15 | 清除图标的大小,单位px
+trim |Boolean| true | 是否自动去除两端的空格
+name |String | - | 表单域的属性名,在使用校验规则时必填
+input-border |Boolean| false | 是否显示input输入框的边框
+border-bottom |Boolean| true | 是否显示field的下边框
+border-top |Boolean| false | 是否显示field的上边框
+auto-height |Boolean| true | 是否自动增高输入区域,type为textarea时有效
+
+**uni-field 事件说明**
+
+事件称名 |说明 | 返回参数
+:-: |:-: | :-:
+input | 输入框内容发生变化时触发 | value 输入的值
+focus | 输入框获得焦点时触发 | event 获取焦点的事件对象
+blur | 输入框失去焦点时触发 | event 失去焦点的事件对象
+confirm | 点击完成按钮时触发 | value 输入的值
+right-icon-click| 通过right-icon生成的图标被点击时触发 | -
+click | 输入框被点击或者通过right-icon生成的图标被点击时触发 | -
+
+**插槽**
+
+名称 | 说明
+:-: | :-:
+leftIcon | 左侧插槽
+right | 右侧插槽
+
+
+
diff --git a/uni_modules/uni-file-picker/changelog.md b/uni_modules/uni-file-picker/changelog.md
new file mode 100644
index 0000000000000000000000000000000000000000..c591273eb3c6c5c53056d3900cae870521a19dd8
--- /dev/null
+++ b/uni_modules/uni-file-picker/changelog.md
@@ -0,0 +1,3 @@
+## 0.0.3(2021-02-05)
+- 调整为uni_modules目录规范
+- 修复 微信小程序不指定 fileExtname 属性选择失败的Bug
diff --git a/uni_modules/uni-file-picker/components/uni-file-picker/choose-and-upload-file.js b/uni_modules/uni-file-picker/components/uni-file-picker/choose-and-upload-file.js
new file mode 100644
index 0000000000000000000000000000000000000000..e810428ede06a084d6848006a492b36f61bcd809
--- /dev/null
+++ b/uni_modules/uni-file-picker/components/uni-file-picker/choose-and-upload-file.js
@@ -0,0 +1,186 @@
+'use strict';
+
+Object.defineProperty(exports, '__esModule', { value: true });
+
+const ERR_MSG_OK = 'chooseAndUploadFile:ok';
+const ERR_MSG_FAIL = 'chooseAndUploadFile:fail';
+function chooseImage(opts) {
+ const { count, sizeType, sourceType, extension } = opts;
+ return new Promise((resolve, reject) => {
+ uni.chooseImage({
+ count,
+ sizeType,
+ sourceType,
+ extension,
+ success(res) {
+ resolve(normalizeChooseAndUploadFileRes(res, 'image'));
+ },
+ fail(res) {
+ reject({
+ errMsg: res.errMsg.replace('chooseImage:fail', ERR_MSG_FAIL),
+ });
+ },
+ });
+ });
+}
+function chooseVideo(opts) {
+ const { camera, compressed, maxDuration, sourceType, extension } = opts;
+ return new Promise((resolve, reject) => {
+ uni.chooseVideo({
+ camera,
+ compressed,
+ maxDuration,
+ sourceType,
+ extension,
+ success(res) {
+ const { tempFilePath, duration, size, height, width } = res;
+ resolve(normalizeChooseAndUploadFileRes({
+ errMsg: 'chooseVideo:ok',
+ tempFilePaths: [tempFilePath],
+ tempFiles: [
+ {
+ name: (res.tempFile && res.tempFile.name) || '',
+ path: tempFilePath,
+ size,
+ type: (res.tempFile && res.tempFile.type) || '',
+ width,
+ height,
+ duration,
+ fileType: 'video',
+ cloudPath: '',
+ },
+ ],
+ }, 'video'));
+ },
+ fail(res) {
+ reject({
+ errMsg: res.errMsg.replace('chooseVideo:fail', ERR_MSG_FAIL),
+ });
+ },
+ });
+ });
+}
+function chooseAll(opts) {
+ const { count, extension } = opts;
+ return new Promise((resolve, reject) => {
+ let chooseFile = uni.chooseFile;
+ if (typeof wx !== 'undefined' &&
+ typeof wx.chooseMessageFile === 'function') {
+ chooseFile = wx.chooseMessageFile;
+ }
+ if (typeof chooseFile !== 'function') {
+ return reject({
+ errMsg: ERR_MSG_FAIL + ' 请指定 type 类型,该平台仅支持选择 image 或 video。',
+ });
+ }
+ chooseFile({
+ type: 'all',
+ count,
+ extension,
+ success(res) {
+ resolve(normalizeChooseAndUploadFileRes(res));
+ },
+ fail(res) {
+ reject({
+ errMsg: res.errMsg.replace('chooseFile:fail', ERR_MSG_FAIL),
+ });
+ },
+ });
+ });
+}
+function normalizeChooseAndUploadFileRes(res, fileType) {
+ res.tempFiles.forEach((item, index) => {
+ if (!item.name) {
+ item.name = item.path.substring(item.path.lastIndexOf('/') + 1);
+ }
+ if (fileType) {
+ item.fileType = fileType;
+ }
+ item.cloudPath =
+ Date.now() + '_' + index + item.name.substring(item.name.lastIndexOf('.'));
+ });
+ // wx.chooseMessageFile
+ if (!res.tempFilePaths) {
+ res.tempFilePaths = res.tempFiles.map((file) => file.path);
+ }
+ return res;
+}
+function uploadCloudFiles(res, max = 5, onUploadProgress) {
+ res = Object.assign({}, res);
+ res.errMsg = ERR_MSG_OK;
+ const files = res.tempFiles;
+ const len = files.length;
+ let count = 0;
+ return new Promise((resolve) => {
+ while (count < max) {
+ next();
+ }
+ function next() {
+ let cur = count++;
+ if (cur >= len) {
+ !files.find((item) => !item.url && !item.errMsg) && resolve(res);
+ return;
+ }
+ const fileItem = files[cur];
+ uniCloud
+ .uploadFile({
+ filePath: fileItem.path,
+ cloudPath: fileItem.cloudPath,
+ fileType: fileItem.fileType,
+ onUploadProgress(res) {
+ res.index = cur;
+ res.tempFile = fileItem;
+ res.tempFilePath = fileItem.path;
+ onUploadProgress &&
+ onUploadProgress(res);
+ },
+ })
+ .then((res) => {
+ fileItem.url = res.fileID;
+ if (cur < len) {
+ next();
+ }
+ })
+ .catch((res) => {
+ // fileItem.errMsg = res.message;
+ fileItem.errMsg = res.errMsg || res.message;
+ if (cur < len) {
+ next();
+ }
+ });
+ }
+ });
+}
+function uploadFiles(choosePromise, { onChooseFile, onUploadProgress }) {
+ return choosePromise
+ .then((res) => {
+ if (onChooseFile) {
+ const customChooseRes = onChooseFile(res);
+ if (typeof customChooseRes !== 'undefined') {
+ return Promise.resolve(customChooseRes).then((chooseRes) => typeof chooseRes === 'undefined' ? res : chooseRes);
+ }
+ }
+ return res;
+ })
+ .then((res) => {
+ if (res === false) {
+ return {
+ errMsg: ERR_MSG_OK,
+ tempFilePaths: [],
+ tempFiles: [],
+ };
+ }
+ return uploadCloudFiles(res, 5, onUploadProgress);
+ });
+}
+function chooseAndUploadFile(opts = { type: 'all' }) {
+ if (opts.type === 'image') {
+ return uploadFiles(chooseImage(opts), opts);
+ }
+ else if (opts.type === 'video') {
+ return uploadFiles(chooseVideo(opts), opts);
+ }
+ return uploadFiles(chooseAll(opts), opts);
+}
+
+exports.chooseAndUploadFile = chooseAndUploadFile;
diff --git a/uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue b/uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue
new file mode 100644
index 0000000000000000000000000000000000000000..6262411442ed4ed798503fb728627ef12bd64fa6
--- /dev/null
+++ b/uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue
@@ -0,0 +1,646 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/uni-file-picker/components/uni-file-picker/upload-file.vue b/uni_modules/uni-file-picker/components/uni-file-picker/upload-file.vue
new file mode 100644
index 0000000000000000000000000000000000000000..445dad5a90c0de43d25df0c75bea5619d8a27555
--- /dev/null
+++ b/uni_modules/uni-file-picker/components/uni-file-picker/upload-file.vue
@@ -0,0 +1,325 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{item.name}}
+
+
+
+
+
+
+
+
+
+ 点击重试
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/uni-file-picker/components/uni-file-picker/upload-image.vue b/uni_modules/uni-file-picker/components/uni-file-picker/upload-image.vue
new file mode 100644
index 0000000000000000000000000000000000000000..7cee3f080ec42ac8e8e6b6d2b8f9fbd6ceb5ff62
--- /dev/null
+++ b/uni_modules/uni-file-picker/components/uni-file-picker/upload-image.vue
@@ -0,0 +1,289 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 点击重试
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/uni-file-picker/package.json b/uni_modules/uni-file-picker/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..d20798619cdfbf75fee441e141d929baa48d132a
--- /dev/null
+++ b/uni_modules/uni-file-picker/package.json
@@ -0,0 +1,82 @@
+{
+ "id": "uni-file-picker",
+ "displayName": "FilePicker 文件选择上传",
+ "version": "0.0.3",
+ "description": "文件选择上传组件,可以选择图片、视频等任意文件并上传到当前绑定的服务空间",
+ "keywords": [
+ "uni-ui",
+ "图片上传",
+ "文件上传",
+ "uni-file-picker"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "前端组件",
+ "通用组件"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "无",
+ "data": "无",
+ "permissions": "无"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": [],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "n"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "微信浏览器(Android)": "y",
+ "QQ浏览器(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "小程序": {
+ "微信": "y",
+ "阿里": "y",
+ "百度": "y",
+ "字节跳动": "y",
+ "QQ": "y"
+ },
+ "快应用": {
+ "华为": "u",
+ "联盟": "u"
+ }
+ }
+ }
+ }
+}
diff --git a/uni_modules/uni-file-picker/readme.md b/uni_modules/uni-file-picker/readme.md
new file mode 100644
index 0000000000000000000000000000000000000000..bf206a8039fa2ea037277775346415e5ee9a7be7
--- /dev/null
+++ b/uni_modules/uni-file-picker/readme.md
@@ -0,0 +1,294 @@
+
+## FilePicker 文件选择上传
+
+> 代码块: `uFilePicker`
+
+
+文件选择上传组件,可以选择图片、视频等任意文件并上传到当前绑定的服务空间
+
+> 为了避免错误使用,给大家带来不好的开发体验,请在使用组件前仔细阅读下面的注意事项,可以帮你避免一些错误。
+> - 组件需要依赖 `sass` 插件 ,请自行手动安装
+> - 使用组件需要绑定服务空间
+> - 选择文件目前只支持 `H5` 和 `微信小程序平台` ,且 `微信小程序平台` 使用 `wx.chooseMessageFile()`
+> - 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839
+
+
+
+## API
+
+### FilePicker Props
+
+| 属性名 | 类型 | 默认值 | 可选值 | 说明 |
+| :-: | :-: | :-: | :-: | :-: |
+| v-model/value | Array\Object | - | - | 组件数据,通常用来回显 ,类型由`return-type`属性决定 ,**格式见下文** |
+| disabled | Boolean | false | - | 组件禁用 |
+| readonly | Boolean | false | - | 组件只读,不可选择,不显示进度,不显示删除按钮 |
+| return-type | String | array | array/object | 限制 `value` 格式,当为 `object` 时 ,组件只能单选,且会覆盖 |
+| disable-preview| Boolean | false | - | 禁用图片预览,仅 `mode:grid`生效 |
+| del-icon | Boolean | true | - | 是否显示删除按钮 |
+| auto-upload | Boolean | true | - | 是否自动上传,值为`true`则只触发@select,可自行上传|
+| limit | Number\String | 9 | - | 最大选择个数 ,h5 会自动忽略多选的部分 |
+| title | String | - | - | 组件标题,右侧显示上传计数 |
+| mode | String | list | list/grid | 选择文件后的文件列表样式 |
+| file-mediatype| String | image | image/video/all | 选择文件类型,all 只支持 H5 和微信小程序平台 |
+| file-extname | Array | - | - | 选择文件后缀,根据 `file-mediatype` 属性而不同|
+| list-styles | Object | - | - | `mode:list` 时的样式 |
+| image-styles | Object | - | - | `mode:grid` 时的样式 |
+
+
+### value 格式
+
+三个属性必填,否则影响组件显示
+
+```json
+[
+ {
+ "name":"file.txt",
+ "extname":"txt",
+ "url":"https://xxxx",
+ // ...
+ }
+]
+
+```
+
+### list-styles 格式
+
+```json
+{
+ "borderStyle":{
+ "color":"#eee", // 边框颜色
+ "width":"1px", // 边框宽度
+ "style":"solid", // 边框样式
+ "radius":"5px" // 边框圆角,不支持百分比
+ },
+ "border":false, // 是否显示边框
+ "dividline":true // 是否显示分隔线
+}
+```
+
+### image-styles 格式
+
+```json
+{
+ "height": 60, // 边框高度
+ "width": 60, // 边框宽度
+ "border":{ // 如果为 Boolean 值,可以控制边框显示与否
+ "color":"#eee", // 边框颜色
+ "width":"1px", // 边框宽度
+ "style":"solid", // 边框样式
+ "radius":"50%" // 边框圆角,支持百分比
+ }
+}
+```
+
+### FilePicker Events
+
+|事件称名 |说明 | 返回值 |
+|:-: |:-: | :-: |
+|@select | 选择文件后触发 | 见下文|
+|@progress|文件上传时触发 | 见下文|
+|@success |上传成功触发 | 见下文|
+|@fail |上传失败触发 | 见下文|
+|@delete |文件从列表移除时触发| 见下文|
+
+
+#### Callback Params
+
+```json
+{
+ "progress" : Number, // 上传进度 ,仅 @progress 事件包含此字段
+ "index" : Number, // 上传文件索引 ,仅 @progress 事件包含此字段
+ "tempFile" : file, // 当前文件对象 ,包含文件流,文件大小,文件名称等,仅 @progress 事件包含此字段
+ "tempFiles" : files, // 文件列表,包含文件流,文件大小,文件名称等
+ "tempFilePaths" : filePaths, // 文件地址列表,@sucess 事件为上传后的线上文件地址
+}
+
+```
+
+
+### FilePicker Methods
+
+通过 `$ref` 调用
+
+| 方法称名 | 说明 | 参数 |
+| :-: | :-: | :-: |
+| upload | 手动上传 ,如`autoUpload`为`false` ,必须调用此方法| - |
+
+### FilePicker Slots
+
+插槽可定义上传按钮显示样式
+
+| 插槽名 | 说明 |
+| :-: | :-: |
+| default |默认插槽|
+
+## 组件用法
+
+### 基础用法
+
+```html
+
+```
+
+```javascript
+export default {
+ data() {
+ return {
+ imageValue:[]
+ }
+ },
+ methods:{
+ // 获取上传状态
+ select(e){
+ console.log('选择文件:',e)
+ }
+ // 获取上传进度
+ progress(e){
+ console.log('上传进度:',e)
+ },
+
+ // 上传成功
+ success(e){
+ console.log('上传成功')
+ },
+
+ // 上传失败
+ fail(e){
+ console.log('上传失败:',e)
+ }
+ }
+}
+
+```
+
+### 选择指定后缀图片,且限制选择个数
+
+配置 `file-mediatype` 属性为 `image`,限定只选择图片
+
+配置 `file-extname` 属性为 `['png','jpg']`,限定只选择 `png`和`jpg`后缀的图片
+
+配置 `limit` 属性为 1 ,则最多选择一张图片
+
+配置 `mode` 属性为 `grid` ,可以使用九宫格样式选择图片
+
+
+```html
+
+```
+
+### 手动上传
+
+配置 `auto-upload` 属性为 `false` ,可以停止自动上传,通过`ref`调用`upload`方法自行选择上传时机
+
+```html
+
+
+
+
+```
+
+```javascript
+export default {
+ data() {},
+ methods:{
+ upload(){
+ this.$refs.files.upload()
+ }
+ }
+}
+
+```
+
+### 单选图片且点击再次选择
+
+配置 `disable-preview` 属性为 `true`,禁用点击预览图片功能
+
+配置 `del-icon` 属性为 `false`,隐藏删除按钮
+
+配置 `return-type` 属性为 `object`,设置 `value` 类型 ,如需绑定 `array`类型 ,则设置`limit:1`,可达到一样的效果
+
+
+
+```html
+选择头像
+```
+
+### 自定义样式
+
+配置 `image-styles` 属性,可以自定义`mode:image`时的回显样式
+
+配置 `list-styles` 属性,可以自定义`mode:video|| mode:all`时的回显样式
+
+```html
+
+
+
+
+```
+
+```javascript
+export default {
+ data() {
+ imageStyles:{
+ width:64,
+ height:64,
+ border:{
+ color:"#ff5a5f",
+ width:2,
+ style:'dashed',
+ radius:'2px'
+ }
+ },
+ listStyles:{
+ // 是否显示边框
+ border: true,
+ // 是否显示分隔线
+ dividline: true,
+ // 线条样式
+ borderStyle: {
+ width:1,
+ color:'blue',
+ radius:2
+ }
+ }
+ }
+}
+
+```
+
+
+
+### 使用插槽
+
+使用默认插槽可以自定义选择文件按钮样式
+
+```html
+
+
+
+```
+
diff --git a/uni_modules/uni-forms/changelog.md b/uni_modules/uni-forms/changelog.md
new file mode 100644
index 0000000000000000000000000000000000000000..11a78e163c30d9885c2593ec9400f775eb61251a
--- /dev/null
+++ b/uni_modules/uni-forms/changelog.md
@@ -0,0 +1,8 @@
+## 1.0.41(2021-03-05)
+- 更新 校验器
+- 修复 表单规则设置类型为 number 的情况下,值为0校验失败我Bug
+## 1.0.40(2021-03-04)
+- 修复 动态显示uni-forms-item的情况下,submit 方法获取值错误的Bug
+## 1.0.39(2021-02-05)
+- 调整为uni_modules目录规范
+- 修复 修复 校验器传入 int 等类型 ,返回String类型的Bug
diff --git a/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 0000000000000000000000000000000000000000..22d18892606d4f558a533412819bc4427ab11663
--- /dev/null
+++ b/uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue
@@ -0,0 +1,453 @@
+
+
+
+
+
+
+
+ {{label}}
+ *
+
+
+
+
+
+
+ {{ showMsg === 'undertext' ? msg:'' }}
+
+
+
+
+
+
+
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 0000000000000000000000000000000000000000..64aa51340c71c0f4e99679af6ef3d9b9f0c92e97
--- /dev/null
+++ b/uni_modules/uni-forms/components/uni-forms/uni-forms.vue
@@ -0,0 +1,456 @@
+
+
+
+
+
+
+
+
+
+
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 0000000000000000000000000000000000000000..46eeccb278e79db15ef6d91595e2e1462aad40e3
--- /dev/null
+++ b/uni_modules/uni-forms/components/uni-forms/validate.js
@@ -0,0 +1,472 @@
+
+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) {
+ // TODO
+ 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 || rule.minimum) {
+ result = 'rangeNumber'
+ } else if (rule.maxLength || rule.minLength) {
+ result = 'rangeLength'
+ } else if (rule.pattern) {
+ result = 'pattern'
+ } else if (rule.validateFunction) {
+ result = 'validateFunction'
+ }
+ return result
+ }
+}
+
+const RuleValidatorHelper = {
+ required(rule, value, message) {
+ if (rule.required && isEmptyValue(value, rule.format || typeof value)) {
+ return formatMessage(rule, rule.errorMessage || message.required);
+ }
+
+ return null
+ },
+
+ range(rule, value, message) {
+ const { range, errorMessage } = rule;
+
+ let list = new Array(range.length);
+ for (let i = 0; i < range.length; i++) {
+ const item = range[i];
+ if (types.object(item) && item.value !== undefined) {
+ list[i] = item.value;
+ } else {
+ list[i] = item;
+ }
+ }
+
+ let result = false
+ if (Array.isArray(value)) {
+ result = (new Set(value.concat(list)).size === list.length);
+ } else {
+ if (list.indexOf(value) > -1) {
+ result = true;
+ }
+ }
+
+ if (!result) {
+ return formatMessage(rule, errorMessage || message['enum']);
+ }
+
+ return null
+ },
+
+ rangeNumber(rule, value, message) {
+ if (!types.number(value)) {
+ return formatMessage(rule, rule.errorMessage || message.pattern.mismatch);
+ }
+
+ let { minimum, maximum, exclusiveMinimum, exclusiveMaximum } = rule;
+ let min = exclusiveMinimum ? value <= minimum : value < minimum;
+ let max = exclusiveMaximum ? value >= maximum : value > maximum;
+
+ if (minimum !== undefined && min) {
+ return formatMessage(rule, rule.errorMessage || message['number'][exclusiveMinimum ? 'exclusiveMinimum' : 'minimum'])
+ } else if (maximum !== undefined && max) {
+ return formatMessage(rule, rule.errorMessage || message['number'][exclusiveMaximum ? 'exclusiveMaximum' : 'maximum'])
+ } else if (minimum !== undefined && maximum !== undefined && (min || max)) {
+ return formatMessage(rule, rule.errorMessage || message['number'].range)
+ }
+
+ return null
+ },
+
+ rangeLength(rule, value, message) {
+ if (!types.string(value) && !types.array(value)) {
+ return formatMessage(rule, rule.errorMessage || message.pattern.mismatch);
+ }
+
+ let min = rule.minLength;
+ let max = rule.maxLength;
+ let val = value.length;
+
+ if (min !== undefined && val < min) {
+ return formatMessage(rule, rule.errorMessage || message['length'].minLength)
+ } else if (max !== undefined && val > max) {
+ return formatMessage(rule, rule.errorMessage || message['length'].maxLength)
+ } else if (min !== undefined && max !== undefined && (val < min || val > max)) {
+ return formatMessage(rule, rule.errorMessage || message['length'].range)
+ }
+
+ return null
+ },
+
+ pattern(rule, value, message) {
+ if (!types['pattern'](rule.pattern, value)) {
+ return formatMessage(rule, rule.errorMessage || message.pattern.mismatch);
+ }
+
+ return null
+ },
+
+ format(rule, value, message) {
+ var customTypes = Object.keys(types);
+ var format = FORMAT_MAPPING[rule.format] ? FORMAT_MAPPING[rule.format] : (rule.format || rule.arrayType);
+
+ if (customTypes.indexOf(format) > -1) {
+ if (!types[format](value)) {
+ return formatMessage(rule, rule.errorMessage || message.typeError);
+ }
+ }
+
+ return null
+ },
+
+ arrayTypeFormat(rule, value, message) {
+ if (!Array.isArray(value)) {
+ return formatMessage(rule, rule.errorMessage || message.typeError);
+ }
+
+ for (let i = 0; i < value.length; i++) {
+ const element = value[i];
+ let formatResult = this.format(rule, element, message)
+ if (formatResult !== null) {
+ return formatResult
+ }
+ }
+
+ return null
+ }
+}
+
+class SchemaValidator extends RuleValidator {
+
+ constructor(schema, options) {
+ super(SchemaValidator.message);
+
+ this._schema = schema
+ this._options = options || null
+ }
+
+ updateSchema(schema) {
+ this._schema = schema
+ }
+
+ async validate(data, allData) {
+ let result = this._checkFieldInSchema(data)
+ if (!result) {
+ result = await this.invokeValidate(data, false, allData)
+ }
+ return result.length ? result[0] : null
+ }
+
+ async validateAll(data, allData) {
+ let result = this._checkFieldInSchema(data)
+ if (!result) {
+ result = await this.invokeValidate(data, true, allData)
+ }
+ return result
+ }
+
+ async validateUpdate(data, allData) {
+ let result = this._checkFieldInSchema(data)
+ if (!result) {
+ result = await this.invokeValidateUpdate(data, false, allData)
+ }
+ return result.length ? result[0] : null
+ }
+
+ async invokeValidate(data, all, allData) {
+ let result = []
+ let schema = this._schema
+ for (let key in schema) {
+ let value = schema[key]
+ let errorMessage = await this.validateRule(key, value, data[key], data, allData)
+ if (errorMessage != null) {
+ result.push({
+ key,
+ errorMessage
+ })
+ if (!all) break
+ }
+ }
+ return result
+ }
+
+ async invokeValidateUpdate(data, all, allData) {
+ let result = []
+ for (let key in data) {
+ let errorMessage = await this.validateRule(key, this._schema[key], data[key], data, allData)
+ if (errorMessage != null) {
+ result.push({
+ key,
+ errorMessage
+ })
+ if (!all) break
+ }
+ }
+ return result
+ }
+
+ _checkFieldInSchema(data) {
+ var keys = Object.keys(data)
+ var keys2 = Object.keys(this._schema)
+ if (new Set(keys.concat(keys2)).size === keys2.length) {
+ return ''
+ }
+
+ var noExistFields = keys.filter((key) => { return keys2.indexOf(key) < 0; })
+ var errorMessage = formatMessage({
+ field: JSON.stringify(noExistFields)
+ }, SchemaValidator.message.TAG + SchemaValidator.message['defaultInvalid'])
+ return [{
+ key: 'invalid',
+ errorMessage
+ }]
+ }
+}
+
+function Message() {
+ return {
+ TAG: "",
+ default: '验证错误',
+ defaultInvalid: '提交的字段{field}在数据库中并不存在',
+ validateFunction: '验证无效',
+ required: '{label}必填',
+ 'enum': '{label}超出范围',
+ timestamp: '{label}格式无效',
+ whitespace: '{label}不能为空',
+ typeError: '{label}类型无效',
+ date: {
+ format: '{label}日期{value}格式无效',
+ parse: '{label}日期无法解析,{value}无效',
+ invalid: '{label}日期{value}无效'
+ },
+ length: {
+ minLength: '{label}长度不能少于{minLength}',
+ maxLength: '{label}长度不能超过{maxLength}',
+ range: '{label}必须介于{minLength}和{maxLength}之间'
+ },
+ number: {
+ minimum: '{label}不能小于{minimum}',
+ maximum: '{label}不能大于{maximum}',
+ exclusiveMinimum: '{label}不能小于等于{minimum}',
+ exclusiveMaximum: '{label}不能大于等于{maximum}',
+ range: '{label}必须介于{minimum}and{maximum}之间'
+ },
+ pattern: {
+ mismatch: '{label}格式不匹配'
+ }
+ };
+}
+
+
+SchemaValidator.message = new Message();
+
+export default SchemaValidator
diff --git a/uni_modules/uni-forms/package.json b/uni_modules/uni-forms/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..640d2fcbf6aa21bf4649c1783b95b5c92e9fd7f7
--- /dev/null
+++ b/uni_modules/uni-forms/package.json
@@ -0,0 +1,86 @@
+{
+ "id": "uni-forms",
+ "displayName": "Forms 表单",
+ "version": "1.0.41",
+ "description": "由输入框、选择器、单选框、多选框等控件组成,用以收集、校验、提交数据",
+ "keywords": [
+ "",
+ "uni-forms",
+ "form",
+ "表单",
+ "表单校验",
+ "表单验证"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+ "dcloudext": {
+ "category": [
+ "前端组件",
+ "通用组件"
+ ],
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "无",
+ "data": "无",
+ "permissions": "无"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui"
+ },
+ "uni_modules": {
+ "dependencies": [
+ "uni-icons"
+ ],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "微信浏览器(Android)": "y",
+ "QQ浏览器(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "小程序": {
+ "微信": "y",
+ "阿里": "y",
+ "百度": "y",
+ "字节跳动": "y",
+ "QQ": "y"
+ },
+ "快应用": {
+ "华为": "u",
+ "联盟": "u"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/uni_modules/uni-forms/readme.md b/uni_modules/uni-forms/readme.md
new file mode 100644
index 0000000000000000000000000000000000000000..6eabd747185665212d9af87ed4037369bb008993
--- /dev/null
+++ b/uni_modules/uni-forms/readme.md
@@ -0,0 +1,533 @@
+
+
+## Forms 表单
+
+> 代码块: `uForms`、`uni-forms-item`
+> 关联组件:`uni-forms-item`、`uni-easyinput`、`uni-data-checkbox`、`uni-group`。
+
+
+uni-app的内置组件已经有了 `