From 5da62ee227615c3f7e41cdbc4f52418a1b4eb2d6 Mon Sep 17 00:00:00 2001 From: linju-json Date: Mon, 10 May 2021 18:01:58 +0800 Subject: [PATCH] =?UTF-8?q?=E5=9B=A0=E5=BA=94=E7=94=A8=E5=B8=82=E5=9C=BA?= =?UTF-8?q?=E6=9C=80=E6=96=B0=E8=A6=81=E6=B1=82=EF=BC=8C=E7=99=BB=E9=99=86?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=8E=BB=E6=8E=89=E9=BB=98=E8=AE=A4=E5=90=8C?= =?UTF-8?q?=E6=84=8F=E9=9A=90=E7=A7=81=E6=94=BF=E7=AD=96=E3=80=82=E6=94=B9?= =?UTF-8?q?=E4=B8=BA=E7=94=A8=E6=88=B7=E6=89=8B=E5=8A=A8=E7=82=B9=E5=87=BB?= =?UTF-8?q?=E3=80=82=E8=B4=A6=E5=8F=B7=E7=99=BB=E9=99=86=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=9B=BE=E5=BD=A2=E9=AA=8C=E8=AF=81=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- static/uni-center/defaultAvatarUrl.png | Bin 0 -> 5417 bytes static/uni-center/headers.png | Bin 0 -> 27733 bytes uni-starter.config.js | 63 ++ .../js_sdk/validator/opendb-feedback.js | 55 ++ uni_modules/opendb-feedback/pages.json | 34 + .../pages/opendb-feedback/add.vue | 146 +++ .../pages/opendb-feedback/detail.vue | 109 +++ .../pages/opendb-feedback/edit.vue | 164 ++++ .../pages/opendb-feedback/list.vue | 54 + .../database/opendb-feedback.schema.json | 74 ++ .../uni_modules/uni-badge/changelog.md | 6 + .../components/uni-badge/uni-badge.vue | 159 +++ .../uni_modules/uni-badge/package.json | 83 ++ .../uni_modules/uni-badge/readme.md | 45 + .../uni_modules/uni-dateformat/changelog.md | 3 + .../components/uni-dateformat/date-format.js | 191 ++++ .../uni-dateformat/uni-dateformat.vue | 90 ++ .../uni_modules/uni-dateformat/package.json | 83 ++ .../uni_modules/uni-dateformat/readme.md | 71 ++ .../uni-datetime-picker/changelog.md | 13 + .../uni-datetime-picker/basic/calendar.js | 546 +++++++++++ .../components/time-picker/keypress.js | 45 + .../components/time-picker/time-picker.vue | 924 ++++++++++++++++++ .../basic/uni-calendar-item.vue | 183 ++++ .../basic/uni-calendar.vue | 760 ++++++++++++++ .../uni-datetime-picker/basic/util.js | 408 ++++++++ .../uni-datetime-picker/icon/cale-50.png | Bin 0 -> 673 bytes .../uni-datetime-picker.vue | 780 +++++++++++++++ .../uni-datetime-picker/package.json | 82 ++ .../uni_modules/uni-datetime-picker/readme.md | 62 ++ .../uni_modules/uni-easyinput/changelog.md | 7 + .../components/uni-easyinput/common.js | 56 ++ .../uni-easyinput/uni-easyinput.vue | 425 ++++++++ .../uni_modules/uni-easyinput/package.json | 83 ++ .../uni_modules/uni-easyinput/readme.md | 194 ++++ .../uni_modules/uni-fab/changelog.md | 4 + .../uni-fab/components/uni-fab/uni-fab.vue | 447 +++++++++ .../components/uni-fab/uni-fab.vue.bak | 383 ++++++++ .../uni_modules/uni-fab/package.json | 82 ++ .../uni_modules/uni-fab/readme.md | 84 ++ .../uni_modules/uni-file-picker/changelog.md | 9 + .../uni-file-picker/choose-and-upload-file.js | 186 ++++ .../uni-file-picker/uni-file-picker.vue | 669 +++++++++++++ .../uni-file-picker/upload-file.vue | 324 ++++++ .../uni-file-picker/upload-image.vue | 289 ++++++ .../uni_modules/uni-file-picker/package.json | 82 ++ .../uni_modules/uni-file-picker/readme.md | 296 ++++++ .../uni_modules/uni-forms/changelog.md | 10 + .../uni-forms-item/uni-forms-item.vue | 453 +++++++++ .../components/uni-forms/uni-forms.vue | 456 +++++++++ .../components/uni-forms/validate.js | 472 +++++++++ .../uni_modules/uni-forms/package.json | 86 ++ .../uni_modules/uni-forms/readme.md | 535 ++++++++++ .../uni_modules/uni-group/changelog.md | 3 + .../components/uni-group/uni-group.vue | 128 +++ .../uni_modules/uni-group/package.json | 82 ++ .../uni_modules/uni-group/readme.md | 48 + .../uni_modules/uni-icons/changelog.md | 2 + .../uni-icons/components/uni-icons/icons.js | 132 +++ .../components/uni-icons/uni-icons.vue | 71 ++ .../uni-icons/components/uni-icons/uni.ttf | Bin 0 -> 26164 bytes .../uni_modules/uni-icons/package.json | 81 ++ .../uni_modules/uni-icons/readme.md | 43 + .../uni_modules/uni-link/changelog.md | 4 + .../uni-link/components/uni-link/uni-link.vue | 111 +++ .../uni_modules/uni-link/package.json | 82 ++ .../uni_modules/uni-link/readme.md | 41 + .../uni_modules/uni-list/changelog.md | 5 + .../components/uni-list-ad/uni-list-ad.vue | 107 ++ .../uni-list-chat/uni-list-chat.scss | 58 ++ .../uni-list-chat/uni-list-chat.vue | 533 ++++++++++ .../uni-list-item/uni-list-item.vue | 440 +++++++++ .../uni-list/components/uni-list/uni-list.vue | 106 ++ .../components/uni-list/uni-refresh.vue | 65 ++ .../components/uni-list/uni-refresh.wxs | 87 ++ .../uni_modules/uni-list/package.json | 85 ++ .../uni_modules/uni-list/readme.md | 340 +++++++ .../uni_modules/uni-load-more/changelog.md | 4 + .../uni-load-more/uni-load-more.vue | 362 +++++++ .../uni_modules/uni-load-more/package.json | 82 ++ .../uni_modules/uni-load-more/readme.md | 65 ++ .../common/uni-config-center/hdx/config.json | 3 + 82 files changed, 14035 insertions(+) create mode 100644 static/uni-center/defaultAvatarUrl.png create mode 100644 static/uni-center/headers.png create mode 100644 uni-starter.config.js create mode 100644 uni_modules/opendb-feedback/js_sdk/validator/opendb-feedback.js create mode 100644 uni_modules/opendb-feedback/pages.json create mode 100644 uni_modules/opendb-feedback/pages/opendb-feedback/add.vue create mode 100644 uni_modules/opendb-feedback/pages/opendb-feedback/detail.vue create mode 100644 uni_modules/opendb-feedback/pages/opendb-feedback/edit.vue create mode 100644 uni_modules/opendb-feedback/pages/opendb-feedback/list.vue create mode 100644 uni_modules/opendb-feedback/uniCloud/database/opendb-feedback.schema.json create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-badge/changelog.md create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-badge/components/uni-badge/uni-badge.vue create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-badge/package.json create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-badge/readme.md create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-dateformat/changelog.md create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-dateformat/components/uni-dateformat/date-format.js create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-dateformat/components/uni-dateformat/uni-dateformat.vue create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-dateformat/package.json create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-dateformat/readme.md create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/changelog.md create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/components/uni-datetime-picker/basic/calendar.js create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/components/uni-datetime-picker/basic/time-picker/components/time-picker/keypress.js create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/components/uni-datetime-picker/basic/time-picker/components/time-picker/time-picker.vue create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/components/uni-datetime-picker/basic/uni-calendar-item.vue create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/components/uni-datetime-picker/basic/uni-calendar.vue create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/components/uni-datetime-picker/basic/util.js create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/components/uni-datetime-picker/icon/cale-50.png create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/package.json create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/readme.md create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-easyinput/changelog.md create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-easyinput/components/uni-easyinput/common.js create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-easyinput/package.json create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-easyinput/readme.md create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-fab/changelog.md create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-fab/components/uni-fab/uni-fab.vue create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-fab/components/uni-fab/uni-fab.vue.bak create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-fab/package.json create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-fab/readme.md create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-file-picker/changelog.md create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-file-picker/components/uni-file-picker/choose-and-upload-file.js create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-file-picker/components/uni-file-picker/upload-file.vue create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-file-picker/components/uni-file-picker/upload-image.vue create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-file-picker/package.json create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-file-picker/readme.md create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-forms/changelog.md create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-forms/components/uni-forms/uni-forms.vue create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-forms/components/uni-forms/validate.js create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-forms/package.json create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-forms/readme.md create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-group/changelog.md create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-group/components/uni-group/uni-group.vue create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-group/package.json create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-group/readme.md create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-icons/changelog.md create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-icons/components/uni-icons/icons.js create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-icons/components/uni-icons/uni-icons.vue create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-icons/components/uni-icons/uni.ttf create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-icons/package.json create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-icons/readme.md create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-link/changelog.md create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-link/components/uni-link/uni-link.vue create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-link/package.json create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-link/readme.md create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-list/changelog.md create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-list/components/uni-list-ad/uni-list-ad.vue create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.scss create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.vue create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-list/components/uni-list-item/uni-list-item.vue create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-list/components/uni-list/uni-list.vue create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-list/components/uni-list/uni-refresh.vue create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-list/components/uni-list/uni-refresh.wxs create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-list/package.json create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-list/readme.md create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-load-more/changelog.md create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-load-more/components/uni-load-more/uni-load-more.vue create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-load-more/package.json create mode 100644 uni_modules/opendb-feedback/uni_modules/uni-load-more/readme.md create mode 100644 uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/hdx/config.json diff --git a/static/uni-center/defaultAvatarUrl.png b/static/uni-center/defaultAvatarUrl.png new file mode 100644 index 0000000000000000000000000000000000000000..ed018bff3aacf48696d06378acc0c8acfc37b860 GIT binary patch literal 5417 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 literal 0 HcmV?d00001 diff --git a/static/uni-center/headers.png b/static/uni-center/headers.png new file mode 100644 index 0000000000000000000000000000000000000000..0a8a4ad2bd55122db45c0de819b85da87df4f50f GIT binary patch literal 27733 zcmd41WmH_-wl0dh1_@5#?pk<&;2tbE6a|3*RaD{bgaixj8iFKvaCe6Ux8M@oAy~L% zt+m(Q=f1PgIq$yv<5g?W<{YDsu3wj$H6ye%6mhXAun-UsaFvzhbr2Ac)DaL6k1&uP zS9(AAxIf-V*vZLh=?UyE9VD36^-bCtH_z$)Z zw)eD;vkgKYj@PW#)$;nRB`uzh9~cN-Db@~MwKs2Y?goUB_c|% zs3>!3ppE+nh_W^06omu^@*(!?bMvqvR2m03yr<8}57;LMxQT_dpml2mRp19qg`fbD z=L`ZI0yiSNi2=8mv8C}Lj9Jm$Ve{BXRJpwhW*?JCa3;~1ibeEAMS zGTCCREYATiF)Rf%g)khPoa3;fUp~lG(UDeE7?nwEI5^XgKpf+c6a!A=E*mp6w5(7J zzKcQ}oFE4roW47(C-0uD;#u7F>SWkBpjg5owiXtdmk$ryP&70*b+oXynTLmmmivc? zwjnaI6bK(L)lW18aWAtu_TIXwM|WaEm0rRT5J;JR{~;>tFdicyU`yHQ8oC&&tBHXi zj@*{k5GydZha>cn8UaB<+5>6{dJT2~Sb=TroFwUwn%d|AcGi;g214q*>QFiGD?24G z82E*khAznKH3(=;FD(U-@DO`s;0SiH1b8?)IKjm{B{nhKR@8F z5B;Mwn6-_Vj=aKOvL5dw>0i0HK*e}?+}+)|-37QIFk2ozAP~sI%g@8l&-F;b1^0Av zvGm|_f;0SsgFF}xg4sb`>>y5n-yAKiAg(Tw^pBeUX@Vp4Z?;bGzuffbFdh#}C=VYu z?{Aa-AhZVkO$T*_Is75q8pH#306T)6T;Pwie1FqIUqM_T@K=z3!}{;-{~+Mewd(4B z%lJ=qadiA!1l;Ah+oKtOIpja3hU}>wc+21?=!6>kY-M=CIz4JFIR7?&Awse8ObRiIje_%)JA6^8=$^FI(5WuQ# z39@tg?OL|qhWvF3EN|%omZazB<>%w#72@LK)#VfVjV3-J4qj0)Ufw@R)gjh)HlF`a zQeiQEpcp^ze;|E?vbCj)<$p_T4HC0~z#J_f17YWAX$$6oI@!_#{tmC09K-i36|>gr<3PH-1XClFX!UXuRNLT)=dYcXDswUq!!#EMH) zR20Z1XblqJvIGG^Tvh@iq9QgR8xWXR@E_;pAt2Y^fc$;_&)l?zfF61LQz@X8pa`#s zjVPD3wJ0x_C7&RO3n=)Qg4R|bQC=WWRKOAp`Uf{nnB8M}uypuWuD`Xie&i@9D8OrN z#Ruf#6A~5T5)=Rexqx6R0WJ{OMu?9eEXdE#|H$VzBE%lqJgQ{*I|n7{`Tklo{EbWp z*S{781$iGoJbb_Z|3&cfza#kPzMhlaV+{D|0l!i8r`umV7Pv?E3JVDd2>rFLW#<8Q zFqF4@^bh<`Rrr99+Wc|mkG+@wvL`CU|GR|z({KOq!L!Hcz#pLs|EomFTH5|~v zKcB#3atQMaa|!Z+z+6CUUJ))UenF6xB@hS(0Uz=8U+6C&#wYlXV(@>g|6c+?uPmKx z!H->)hyLGM1cErZfnom=6{sc5^0AqMVQ@)$8yLh9U%V%`-@pL4 zKmh-&KL1vZH5g|1FTVR%DSxW~_`fLczm1fTfPf`GFYqxwyrO(uf+9d+E}*C|h)al1 zRLBM_EWj_o|NpN@{kInV&+7EQ!`}bai2g5Q?~m&8XKCR1->b%-_ws)NMBz8&{umF$ z{(teI9^2Y&Zz~t+nCQmzM0|u)>qRcQ<2uZSm6TQpY=r>$nfsXWJJK z5dZ5-!4&PCE@w_tEXBmF#b*eG> zJT#-bXQqn%3J=L#cT4|8`b}X)KKz(k#T`K4`aCQ6FsJinU6ThokQWY zMr{P2nB)M=H8CWJW3M7(zMtRST=7LNvk9L263|0g%FTChJkkUCcE2ypDp(v?ga?Xo zxISd$4j*xh)fbbI{p>n3ljGR1~Q?aD^F1p3%0@x=9FV8L

RwWF?>* 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 as{aS#+1wiZzndHY0000 + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/uni_modules/opendb-feedback/pages/opendb-feedback/detail.vue b/uni_modules/opendb-feedback/pages/opendb-feedback/detail.vue new file mode 100644 index 00000000..d50287e7 --- /dev/null +++ b/uni_modules/opendb-feedback/pages/opendb-feedback/detail.vue @@ -0,0 +1,109 @@ + + + + + diff --git a/uni_modules/opendb-feedback/pages/opendb-feedback/edit.vue b/uni_modules/opendb-feedback/pages/opendb-feedback/edit.vue new file mode 100644 index 00000000..31def1d4 --- /dev/null +++ b/uni_modules/opendb-feedback/pages/opendb-feedback/edit.vue @@ -0,0 +1,164 @@ + + + + + + diff --git a/uni_modules/opendb-feedback/pages/opendb-feedback/list.vue b/uni_modules/opendb-feedback/pages/opendb-feedback/list.vue new file mode 100644 index 00000000..78544af0 --- /dev/null +++ b/uni_modules/opendb-feedback/pages/opendb-feedback/list.vue @@ -0,0 +1,54 @@ + + + + + diff --git a/uni_modules/opendb-feedback/uniCloud/database/opendb-feedback.schema.json b/uni_modules/opendb-feedback/uniCloud/database/opendb-feedback.schema.json new file mode 100644 index 00000000..5db9d6be --- /dev/null +++ b/uni_modules/opendb-feedback/uniCloud/database/opendb-feedback.schema.json @@ -0,0 +1,74 @@ +{ + "bsonType": "object", + "required": [ + "content" + ], + "permission": { + "create": "auth.uid != null", + "read": true, + "delete": true, + "update": true + }, + "properties": { + "_id": { + "description": "ID,系统自动生成" + }, + "user_id": { + "bsonType": "string", + "description": "留言反馈用户ID/回复留言用户ID,参考uni-id-users表", + "foreignKey": "uni-id-users._id", + "forceDefaultValue": { + "$env": "uid" + } + }, + "create_date": { + "bsonType": "timestamp", + "title": "留言时间/回复留言时间", + "forceDefaultValue": { + "$env": "now" + } + }, + "content": { + "bsonType": "string", + "title": "留言内容/回复内容", + "componentForEdit": { + "name": "textarea" + }, + "trim": "right" + }, + "imgs": { + "bsonType": "array", + "arrayType": "file", + "maxLength": 6, + "fileMediaType": "image", + "title": "图片列表" + }, + "is_reply": { + "bsonType": "bool", + "title": "是否是回复类型" + }, + "feedback_id": { + "bsonType": "string", + "title": "被回复留言ID" + }, + "contact": { + "bsonType": "string", + "title": "联系人", + "trim": "both" + }, + "mobile": { + "bsonType": "string", + "title": "联系电话", + "pattern": "^\\+?[0-9-]{3,20}$", + "trim": "both" + }, + "reply_count": { + "permission": { + "write": false + }, + "bsonType": "int", + "title": "被回复条数", + "defaultValue": 0 + } + } +} diff --git a/uni_modules/opendb-feedback/uni_modules/uni-badge/changelog.md b/uni_modules/opendb-feedback/uni_modules/uni-badge/changelog.md new file mode 100644 index 00000000..5ec77203 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-badge/changelog.md @@ -0,0 +1,6 @@ +## 1.0.7(2021-05-07) +- 修复 uni-badge 在 App 端,数字小于10时不是圆形的bug +- 修复 uni-badge 在父元素不是 flex 布局时,宽度缩小的bug +- 新增 uni-badge 属性 custom-style, 支持自定义样式 +## 1.0.6(2021-02-04) +- 调整为uni_modules目录规范 diff --git a/uni_modules/opendb-feedback/uni_modules/uni-badge/components/uni-badge/uni-badge.vue b/uni_modules/opendb-feedback/uni_modules/uni-badge/components/uni-badge/uni-badge.vue new file mode 100644 index 00000000..5d36c388 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-badge/components/uni-badge/uni-badge.vue @@ -0,0 +1,159 @@ + + + + + diff --git a/uni_modules/opendb-feedback/uni_modules/uni-badge/package.json b/uni_modules/opendb-feedback/uni_modules/uni-badge/package.json new file mode 100644 index 00000000..e215ab6a --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-badge/package.json @@ -0,0 +1,83 @@ +{ + "id": "uni-badge", + "displayName": "Badge 数字角标", + "version": "1.0.7", + "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": "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/opendb-feedback/uni_modules/uni-badge/readme.md b/uni_modules/opendb-feedback/uni_modules/uni-badge/readme.md new file mode 100644 index 00000000..0a8c4a04 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-badge/readme.md @@ -0,0 +1,45 @@ + + +## Badge 数字角标 +> **组件名:uni-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 | +|custom-style |String | |自定义 Badge 样式 | +|inverted |Boolean|false |是否无需背景颜色,为 true 时,背景颜色将变为文字的字体颜色 | + +### Badge Events + +|事件名 |事件说明 |返回参数 | +|:-: |:-: |:-: | +|@click |点击 Badge 触发事件| - | + + diff --git a/uni_modules/opendb-feedback/uni_modules/uni-dateformat/changelog.md b/uni_modules/opendb-feedback/uni_modules/uni-dateformat/changelog.md new file mode 100644 index 00000000..9dee4463 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-dateformat/changelog.md @@ -0,0 +1,3 @@ +## 0.0.3(2021-02-04) +- 调整为uni_modules目录规范 +- 修复 iOS 平台日期格式化出错的问题 diff --git a/uni_modules/opendb-feedback/uni_modules/uni-dateformat/components/uni-dateformat/date-format.js b/uni_modules/opendb-feedback/uni_modules/uni-dateformat/components/uni-dateformat/date-format.js new file mode 100644 index 00000000..24b450e1 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-dateformat/components/uni-dateformat/date-format.js @@ -0,0 +1,191 @@ +// 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': + 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/opendb-feedback/uni_modules/uni-dateformat/components/uni-dateformat/uni-dateformat.vue b/uni_modules/opendb-feedback/uni_modules/uni-dateformat/components/uni-dateformat/uni-dateformat.vue new file mode 100644 index 00000000..af452055 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-dateformat/components/uni-dateformat/uni-dateformat.vue @@ -0,0 +1,90 @@ + + + + + diff --git a/uni_modules/opendb-feedback/uni_modules/uni-dateformat/package.json b/uni_modules/opendb-feedback/uni_modules/uni-dateformat/package.json new file mode 100644 index 00000000..718062f7 --- /dev/null +++ b/uni_modules/opendb-feedback/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/opendb-feedback/uni_modules/uni-dateformat/readme.md b/uni_modules/opendb-feedback/uni_modules/uni-dateformat/readme.md new file mode 100644 index 00000000..e54f7a81 --- /dev/null +++ b/uni_modules/opendb-feedback/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/opendb-feedback/uni_modules/uni-datetime-picker/changelog.md b/uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/changelog.md new file mode 100644 index 00000000..43ee2824 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/changelog.md @@ -0,0 +1,13 @@ +## 2.0.2(2021-05-08) +- 修复 在 admin 中获取弹出层定位错误的bug +## 2.0.1(2021-05-08) +- 修复 type 属性向下兼容,默认值从 date 变更为 datetime +## 2.0.0(2021-04-30) +- 支持日历形式的日期+时间的范围选择 + > 注意:此版本不向后兼容,不再支持单独时间选择(type=time)及相关的 hide-second 属性(时间选可使用内置组件 picker) +## 1.0.6(2021-03-18) +- 新增 hide-second 属性,时间支持仅选择时、分 +- 修复 选择跟显示的日期不一样的 bug +- 修复 chang事件触发2次的 bug +- 修复 分、秒 end 范围错误的 bug +- 优化 更好的 nvue 适配 diff --git a/uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/components/uni-datetime-picker/basic/calendar.js b/uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/components/uni-datetime-picker/basic/calendar.js new file mode 100644 index 00000000..b8d7d6fc --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/components/uni-datetime-picker/basic/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/opendb-feedback/uni_modules/uni-datetime-picker/components/uni-datetime-picker/basic/time-picker/components/time-picker/keypress.js b/uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/components/uni-datetime-picker/basic/time-picker/components/time-picker/keypress.js new file mode 100644 index 00000000..9601abae --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/components/uni-datetime-picker/basic/time-picker/components/time-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/opendb-feedback/uni_modules/uni-datetime-picker/components/uni-datetime-picker/basic/time-picker/components/time-picker/time-picker.vue b/uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/components/uni-datetime-picker/basic/time-picker/components/time-picker/time-picker.vue new file mode 100644 index 00000000..08a6a9b1 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/components/uni-datetime-picker/basic/time-picker/components/time-picker/time-picker.vue @@ -0,0 +1,924 @@ + + + + + diff --git a/uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/components/uni-datetime-picker/basic/uni-calendar-item.vue b/uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/components/uni-datetime-picker/basic/uni-calendar-item.vue new file mode 100644 index 00000000..8f4e6f8a --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/components/uni-datetime-picker/basic/uni-calendar-item.vue @@ -0,0 +1,183 @@ + + + + + diff --git a/uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/components/uni-datetime-picker/basic/uni-calendar.vue b/uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/components/uni-datetime-picker/basic/uni-calendar.vue new file mode 100644 index 00000000..8d62f461 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/components/uni-datetime-picker/basic/uni-calendar.vue @@ -0,0 +1,760 @@ + + + + + diff --git a/uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/components/uni-datetime-picker/basic/util.js b/uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/components/uni-datetime-picker/basic/util.js new file mode 100644 index 00000000..6b95347a --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/components/uni-datetime-picker/basic/util.js @@ -0,0 +1,408 @@ +import CALENDAR from './calendar.js' + +class Calendar { + constructor({ + date, + selected, + startDate, + endDate, + range, + // multipleStatus + } = {}) { + // 当前日期 + this.date = this.getDate(new Date()) // 当前初入日期 + // 打点信息 + this.selected = selected || []; + // 范围开始 + this.startDate = startDate + // 范围结束 + this.endDate = endDate + this.range = range + // 多选状态 + this.cleanMultipleStatus() + // 每周日期 + this.weeks = {} + // this._getWeek(this.date.fullDate) + // this.multipleStatus = multipleStatus + this.lastHover = false + } + /** + * 设置日期 + * @param {Object} date + */ + setDate(date) { + this.selectDate = this.getDate(date) + this._getWeek(this.selectDate.fullDate) + } + + /** + * 清理多选状态 + */ + cleanMultipleStatus() { + this.multipleStatus = { + before: '', + after: '', + data: [] + } + } + + /** + * 重置开始日期 + */ + resetSatrtDate(startDate) { + // 范围开始 + this.startDate = startDate + + } + + /** + * 重置结束日期 + */ + resetEndDate(endDate) { + // 范围结束 + this.endDate = endDate + } + + /** + * 获取任意时间 + */ + getDate(date, AddDayCount = 0, str = 'day') { + if (!date) { + date = new Date() + } + if (typeof date !== 'object') { + date = date.replace(/-/g, '/') + } + const dd = new Date(date) + switch (str) { + case 'day': + dd.setDate(dd.getDate() + AddDayCount) // 获取AddDayCount天后的日期 + break + case 'month': + if (dd.getDate() === 31) { + dd.setDate(dd.getDate() + AddDayCount) + } else { + dd.setMonth(dd.getMonth() + AddDayCount) // 获取AddDayCount天后的日期 + } + break + case 'year': + dd.setFullYear(dd.getFullYear() + AddDayCount) // 获取AddDayCount天后的日期 + break + } + const y = dd.getFullYear() + const m = dd.getMonth() + 1 < 10 ? '0' + (dd.getMonth() + 1) : dd.getMonth() + 1 // 获取当前月份的日期,不足10补0 + const d = dd.getDate() < 10 ? '0' + dd.getDate() : dd.getDate() // 获取当前几号,不足10补0 + return { + fullDate: y + '-' + m + '-' + d, + year: y, + month: m, + date: d, + day: dd.getDay() + } + } + + + /** + * 获取上月剩余天数 + */ + _getLastMonthDays(firstDay, full) { + let dateArr = [] + for (let i = firstDay; i > 0; i--) { + const beforeDate = new Date(full.year, full.month - 1, -i + 1).getDate() + dateArr.push({ + date: beforeDate, + month: full.month - 1, + 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) + disableBefore = this.dateCompare(this.startDate, nowDate) + } + + if (this.endDate) { + // let dateCompAfter = this.dateCompare(fullDate, this.endDate) + // disableAfter = this.dateCompare(nowDate, dateCompAfter ? this.endDate : fullDate) + disableAfter = this.dateCompare(nowDate, this.endDate) + } + let multiples = this.multipleStatus.data + let checked = false + let multiplesStatus = -1 + if (this.range) { + if (multiples) { + multiplesStatus = multiples.findIndex((item) => { + return this.dateEqual(item, nowDate) + }) + } + if (multiplesStatus !== -1) { + checked = true + } + } + let data = { + fullDate: nowDate, + year: full.year, + date: i, + multiple: this.range ? checked : false, + beforeMultiple: this.dateEqual(this.multipleStatus.before, nowDate), + afterMultiple: this.dateEqual(this.multipleStatus.after, nowDate), + month: full.month, + lunar: this.getlunar(full.year, full.month, i), + disable: !(disableBefore && disableAfter), + isDay + } + if (info) { + data.extraInfo = info + } + + dateArr.push(data) + } + return dateArr + } + /** + * 获取下月天数 + */ + _getNextMonthDays(surplus, full) { + let dateArr = [] + for (let i = 1; i < surplus + 1; i++) { + dateArr.push({ + date: i, + month: Number(full.month) + 1, + lunar: this.getlunar(full.year, Number(full.month) + 1, i), + disable: true + }) + } + return dateArr + } + + /** + * 获取当前日期详情 + * @param {Object} date + */ + getInfo(date) { + if (!date) { + date = new Date() + } + const dateInfo = this.canlender.find(item => item.fullDate === this.getDate(date).fullDate) + return dateInfo + } + + /** + * 比较时间大小 + */ + dateCompare(startDate, endDate) { + // 计算截止时间 + startDate = new Date(startDate.replace('-', '/').replace('-', '/')) + // 计算详细项的截止时间 + endDate = new Date(endDate.replace('-', '/').replace('-', '/')) + if (startDate <= endDate) { + return true + } else { + return false + } + } + + /** + * 比较时间是否相等 + */ + dateEqual(before, after) { + // 计算截止时间 + before = new Date(before.replace('-', '/').replace('-', '/')) + // 计算详细项的截止时间 + after = new Date(after.replace('-', '/').replace('-', '/')) + if (before.getTime() - after.getTime() === 0) { + return true + } else { + return false + } + } + + + /** + * 获取日期范围内所有日期 + * @param {Object} begin + * @param {Object} end + */ + geDateAll(begin, end) { + var arr = [] + var ab = begin.split('-') + var ae = end.split('-') + var db = new Date() + db.setFullYear(ab[0], ab[1] - 1, ab[2]) + var de = new Date() + de.setFullYear(ae[0], ae[1] - 1, ae[2]) + var unixDb = db.getTime() - 24 * 60 * 60 * 1000 + var unixDe = de.getTime() - 24 * 60 * 60 * 1000 + for (var k = unixDb; k <= unixDe;) { + k = k + 24 * 60 * 60 * 1000 + arr.push(this.getDate(new Date(parseInt(k))).fullDate) + } + return arr + } + /** + * 计算阴历日期显示 + */ + getlunar(year, month, date) { + return CALENDAR.solar2lunar(year, month, date) + } + /** + * 设置打点 + */ + setSelectInfo(data, value) { + this.selected = value + this._getWeek(data) + } + + /** + * 获取多选状态 + */ + setMultiple(fullDate) { + let { + before, + after + } = this.multipleStatus + + if (!this.range) return + if (before && after) { + if (!this.lastHover) { + this.lastHover = true + return + } + this.multipleStatus.before = '' + this.multipleStatus.after = '' + this.multipleStatus.data = [] + this.multipleStatus.fulldate = '' + this.lastHover = false + } else { + this.lastHover = false + 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) + } + + /** + * 鼠标 hover 更新多选状态 + */ + setHoverMultiple(fullDate) { + let { + before, + after + } = this.multipleStatus + + if (!this.range) return + if (this.lastHover) return + + if (!before) { + this.multipleStatus.before = fullDate + } else { + this.multipleStatus.after = fullDate + if (this.dateCompare(this.multipleStatus.before, this.multipleStatus.after)) { + this.multipleStatus.data = this.geDateAll(this.multipleStatus.before, this.multipleStatus.after); + } else { + this.multipleStatus.data = this.geDateAll(this.multipleStatus.after, this.multipleStatus.before); + } + } + this._getWeek(fullDate) + } + + /** + * 更新默认值多选状态 + */ + setDefaultMultiple(before, after) { + this.multipleStatus.before = before + this.multipleStatus.after = after + if (before && after) { + if (this.dateCompare(before, after)) { + this.multipleStatus.data = this.geDateAll(before, after); + this._getWeek(after) + } else { + this.multipleStatus.data = this.geDateAll(after, before); + this._getWeek(before) + } + } + } + + /** + * 获取每周数据 + * @param {Object} dateData + */ + _getWeek(dateData) { + const { + fullDate, + year, + month, + date, + day + } = this.getDate(dateData) + let firstDay = new Date(year, month - 1, 1).getDay() + let currentDay = new Date(year, month, 0).getDate() + let dates = { + lastMonthDays: this._getLastMonthDays(firstDay, this.getDate(dateData)), // 上个月末尾几天 + currentMonthDys: this._currentMonthDys(currentDay, this.getDate(dateData)), // 本月天数 + nextMonthDays: [], // 下个月开始几天 + weeks: [] + } + let canlender = [] + const surplus = 42 - (dates.lastMonthDays.length + dates.currentMonthDys.length) + dates.nextMonthDays = this._getNextMonthDays(surplus, this.getDate(dateData)) + canlender = canlender.concat(dates.lastMonthDays, dates.currentMonthDys, dates.nextMonthDays) + let weeks = {} + // 拼接数组 上个月开始几天 + 本月天数+ 下个月开始几天 + for (let i = 0; i < canlender.length; i++) { + if (i % 7 === 0) { + weeks[parseInt(i / 7)] = new Array(7) + } + weeks[parseInt(i / 7)][i % 7] = canlender[i] + } + this.canlender = canlender + this.weeks = weeks + } + + //静态方法 + // static init(date) { + // if (!this.instance) { + // this.instance = new Calendar(date); + // } + // return this.instance; + // } +} + + +export default Calendar diff --git a/uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/components/uni-datetime-picker/icon/cale-50.png b/uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/components/uni-datetime-picker/icon/cale-50.png new file mode 100644 index 0000000000000000000000000000000000000000..fc72eaae94388cf559207f04e95aba049b878605 GIT binary patch literal 673 zcmV;S0$%-zP)xK~!jg?U}!8(?Jx#KZ+J51T2zjB?Jl5K~o${7U|;V<{(9cPVFcn zI5~)epro^Io%A0tbm&qFPF4resSpd|uNFkK6|0L5cOlO&-}`#^%_SF-`@q5DeedqQ z`+i^EyWBw}5|jr(OSkKTXycG&zYI`9Otq zS7GfMTBgr_ntyk$Ha1LqtCuOb2vz{S06eSkm%w;GP)2*oBX|@U@}K+BCWnLn{r_;n{28zLsUC`6l#17@Dm0 zL&)VGIF$$K$DXNEGPE{OH%Fif)JfpGU%#AaUn{hEZaZ)qb=?*EQYWo_(F?QY3hF>0 zwByM|T*z|TbQxMj6|ovHX8#VnvyTe*N5D=%KO&Jx#4~>ZHrP8;-9Ar000000NkvXX Hu0mjf5KA%s literal 0 HcmV?d00001 diff --git a/uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue b/uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue new file mode 100644 index 00000000..189226de --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue @@ -0,0 +1,780 @@ + + + + diff --git a/uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/package.json b/uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/package.json new file mode 100644 index 00000000..7d7ba31b --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/package.json @@ -0,0 +1,82 @@ +{ + "id": "uni-datetime-picker", + "displayName": "uni-datetime-picker 日期选择器", + "version": "2.0.2", + "description": "uni-datetime-picker 日期时间选择器,支持日历,支持范围选择", + "keywords": [ + "uni-datetime-picker", + "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" + } + } + } + } +} diff --git a/uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/readme.md b/uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/readme.md new file mode 100644 index 00000000..1823a4fd --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-datetime-picker/readme.md @@ -0,0 +1,62 @@ + +> `重要通知:组件升级更新 2.0.0 后,支持日期+时间范围选择,组件 ui 将使用日历选择日期,ui 变化较大,同时支持 PC 和 移动端。此版本不向后兼容,不再支持单独的时间选择(type=time)及相关的 hide-second 属性(时间选可使用内置组件 picker)。若仍需使用旧版本,可在插件市场下载*非uni_modules版本*,旧版本将不再维护` +## DatetimePicker 时间选择器 +> **组件名:uni-datetime-picker** +> 代码块: `uDatetimePicker` + + +该组件的优势是,支持**时间戳**输入和输出(起始时间、终止时间也支持时间戳),可**同时选择**日期和时间。 + +若只是需要单独选择日期和时间,不需要时间戳输入和输出,可使用原生的 picker 组件。 + + +___点击 picker 默认值规则:___ + +- 若设置初始值 value, 会显示在 picker 显示框中 +- 若无初始值 value,则初始值 value 为当前本地时间 Date.now(), 但不会显示在 picker 显示框中 + + +### 安装方式 + +本组件符合[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 |date/daterange/datetime/datetimerange +range|选择器类型 | +|value |String、Number |- |- |输入框当前值 | +|start |String、Number |- |- |最小值,可以使用日期的字符串(String)、时间戳(Number) | +|end |String、Number |- |- |最大值,可以使用日期的字符串(String)、时间戳(Number) | +|return-type|String |timestamp|timestamp 、string |返回值格式 | +|border |Boolean、String|true | |是否有边框 | +|placeholder |String |- |- |非范围选择时的占位内容 | +|start-placeholder |String |- |- |范围选择时开始日期的占位内容 | +|end-placeholder |String |- |- |范围选择时结束日期的占位内容 | +|disabled |Boolean、String|false | |是否不可选择 | + + + + +### DatetimePicker Events + +|事件名称 |说明 |返回值 | +|:-: |:-: |:-: | +|change |确定日期时间时触发的事件,参数为当前选择的日期对象 | 单选返回日期字符串,如:'2010-02-3';范围选返回日期字符串数组,如:['2020-10-1', '2021-4-1'] | \ No newline at end of file diff --git a/uni_modules/opendb-feedback/uni_modules/uni-easyinput/changelog.md b/uni_modules/opendb-feedback/uni_modules/uni-easyinput/changelog.md new file mode 100644 index 00000000..958e44c0 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-easyinput/changelog.md @@ -0,0 +1,7 @@ +## 0.0.11(2021-05-07) +- 修复 input-border 属性不生效的问题 +## 0.0.10(2021-04-30) +- 修复 ios 遮挡文字、显示一半的问题 +## 0.0.9(2021-02-05) +- 调整为uni_modules目录规范 +- 优化 兼容 nvue 页面 diff --git a/uni_modules/opendb-feedback/uni_modules/uni-easyinput/components/uni-easyinput/common.js b/uni_modules/opendb-feedback/uni_modules/uni-easyinput/components/uni-easyinput/common.js new file mode 100644 index 00000000..5549cc99 --- /dev/null +++ b/uni_modules/opendb-feedback/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/opendb-feedback/uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue b/uni_modules/opendb-feedback/uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue new file mode 100644 index 00000000..e4c73e11 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue @@ -0,0 +1,425 @@ + + + + + diff --git a/uni_modules/opendb-feedback/uni_modules/uni-easyinput/package.json b/uni_modules/opendb-feedback/uni_modules/uni-easyinput/package.json new file mode 100644 index 00000000..fac77e33 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-easyinput/package.json @@ -0,0 +1,83 @@ +{ + "id": "uni-easyinput", + "displayName": "Easyinput 增强输入框", + "version": "0.0.11", + "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/opendb-feedback/uni_modules/uni-easyinput/readme.md b/uni_modules/opendb-feedback/uni_modules/uni-easyinput/readme.md new file mode 100644 index 00000000..4d61363e --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-easyinput/readme.md @@ -0,0 +1,194 @@ + + +### Easyinput 增强输入框 +> **组件名:uni-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 | - |true| 是否显示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/opendb-feedback/uni_modules/uni-fab/changelog.md b/uni_modules/opendb-feedback/uni_modules/uni-fab/changelog.md new file mode 100644 index 00000000..d8e69eb9 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-fab/changelog.md @@ -0,0 +1,4 @@ +## 1.0.6(2021-02-05) +- 调整为uni_modules目录规范 +- 优化 按钮背景色调整 +- 优化 兼容pc端 diff --git a/uni_modules/opendb-feedback/uni_modules/uni-fab/components/uni-fab/uni-fab.vue b/uni_modules/opendb-feedback/uni_modules/uni-fab/components/uni-fab/uni-fab.vue new file mode 100644 index 00000000..e077eae7 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-fab/components/uni-fab/uni-fab.vue @@ -0,0 +1,447 @@ + + + + + diff --git a/uni_modules/opendb-feedback/uni_modules/uni-fab/components/uni-fab/uni-fab.vue.bak b/uni_modules/opendb-feedback/uni_modules/uni-fab/components/uni-fab/uni-fab.vue.bak new file mode 100644 index 00000000..9df4dcd7 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-fab/components/uni-fab/uni-fab.vue.bak @@ -0,0 +1,383 @@ + + + + + diff --git a/uni_modules/opendb-feedback/uni_modules/uni-fab/package.json b/uni_modules/opendb-feedback/uni_modules/uni-fab/package.json new file mode 100644 index 00000000..4fbe3768 --- /dev/null +++ b/uni_modules/opendb-feedback/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/opendb-feedback/uni_modules/uni-fab/readme.md b/uni_modules/opendb-feedback/uni_modules/uni-fab/readme.md new file mode 100644 index 00000000..725f67a3 --- /dev/null +++ b/uni_modules/opendb-feedback/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/opendb-feedback/uni_modules/uni-file-picker/changelog.md b/uni_modules/opendb-feedback/uni_modules/uni-file-picker/changelog.md new file mode 100644 index 00000000..8f891261 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-file-picker/changelog.md @@ -0,0 +1,9 @@ +## 0.0.6(2021-04-09) +- 修复 选择的文件非 file-extname 字段指定的扩展名报错的Bug +## 0.0.5(2021-04-09) +- 优化 更新组件示例 +## 0.0.4(2021-04-09) +- 优化 file-extname 字段支持字符串写法,多个扩展名需要用逗号分隔 +## 0.0.3(2021-02-05) +- 调整为uni_modules目录规范 +- 修复 微信小程序不指定 fileExtname 属性选择失败的Bug diff --git a/uni_modules/opendb-feedback/uni_modules/uni-file-picker/components/uni-file-picker/choose-and-upload-file.js b/uni_modules/opendb-feedback/uni_modules/uni-file-picker/components/uni-file-picker/choose-and-upload-file.js new file mode 100644 index 00000000..1d57b5ed --- /dev/null +++ b/uni_modules/opendb-feedback/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/opendb-feedback/uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue b/uni_modules/opendb-feedback/uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue new file mode 100644 index 00000000..370d98e4 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue @@ -0,0 +1,669 @@ + + + + + diff --git a/uni_modules/opendb-feedback/uni_modules/uni-file-picker/components/uni-file-picker/upload-file.vue b/uni_modules/opendb-feedback/uni_modules/uni-file-picker/components/uni-file-picker/upload-file.vue new file mode 100644 index 00000000..c369d7d5 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-file-picker/components/uni-file-picker/upload-file.vue @@ -0,0 +1,324 @@ + + + + + diff --git a/uni_modules/opendb-feedback/uni_modules/uni-file-picker/components/uni-file-picker/upload-image.vue b/uni_modules/opendb-feedback/uni_modules/uni-file-picker/components/uni-file-picker/upload-image.vue new file mode 100644 index 00000000..486e2094 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-file-picker/components/uni-file-picker/upload-image.vue @@ -0,0 +1,289 @@ + + + + + diff --git a/uni_modules/opendb-feedback/uni_modules/uni-file-picker/package.json b/uni_modules/opendb-feedback/uni_modules/uni-file-picker/package.json new file mode 100644 index 00000000..0b8c6d88 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-file-picker/package.json @@ -0,0 +1,82 @@ +{ + "id": "uni-file-picker", + "displayName": "FilePicker 文件选择上传", + "version": "0.0.6", + "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/opendb-feedback/uni_modules/uni-file-picker/readme.md b/uni_modules/opendb-feedback/uni_modules/uni-file-picker/readme.md new file mode 100644 index 00000000..7d360503 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-file-picker/readme.md @@ -0,0 +1,296 @@ + +## FilePicker 文件选择上传 + +> **组件名:uni-file-picker** +> 代码块: `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\String | - | - | 选择文件后缀,字符串的情况下需要用逗号分隔(推荐使用字符串),根据 `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/opendb-feedback/uni_modules/uni-forms/changelog.md b/uni_modules/opendb-feedback/uni_modules/uni-forms/changelog.md new file mode 100644 index 00000000..86e4c391 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-forms/changelog.md @@ -0,0 +1,10 @@ +## 1.0.42(2021-04-30) +- 修复 自定义检验器失效的问题 +## 1.0.41(2021-03-05) +- 更新 校验器 +- 修复 表单规则设置类型为 number 的情况下,值为0校验失败的Bug +## 1.0.40(2021-03-04) +- 修复 动态显示uni-forms-item的情况下,submit 方法获取值错误的Bug +## 1.0.39(2021-02-05) +- 调整为uni_modules目录规范 +- 修复 校验器传入 int 等类型 ,返回String类型的Bug diff --git a/uni_modules/opendb-feedback/uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue b/uni_modules/opendb-feedback/uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue new file mode 100644 index 00000000..acaac80e --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue @@ -0,0 +1,453 @@ + + + + + diff --git a/uni_modules/opendb-feedback/uni_modules/uni-forms/components/uni-forms/uni-forms.vue b/uni_modules/opendb-feedback/uni_modules/uni-forms/components/uni-forms/uni-forms.vue new file mode 100644 index 00000000..7a5ce73d --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-forms/components/uni-forms/uni-forms.vue @@ -0,0 +1,456 @@ + + + + + diff --git a/uni_modules/opendb-feedback/uni_modules/uni-forms/components/uni-forms/validate.js b/uni_modules/opendb-feedback/uni_modules/uni-forms/components/uni-forms/validate.js new file mode 100644 index 00000000..e4aad950 --- /dev/null +++ b/uni_modules/opendb-feedback/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/opendb-feedback/uni_modules/uni-forms/package.json b/uni_modules/opendb-feedback/uni_modules/uni-forms/package.json new file mode 100644 index 00000000..5c9f5370 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-forms/package.json @@ -0,0 +1,86 @@ +{ + "id": "uni-forms", + "displayName": "Forms 表单", + "version": "1.0.42", + "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/opendb-feedback/uni_modules/uni-forms/readme.md b/uni_modules/opendb-feedback/uni_modules/uni-forms/readme.md new file mode 100644 index 00000000..6c811c73 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-forms/readme.md @@ -0,0 +1,535 @@ + + +## Forms 表单 + +> **组件名:uni-forms** +> 代码块: `uForms`、`uni-forms-item` +> 关联组件:`uni-forms-item`、`uni-easyinput`、`uni-data-checkbox`、`uni-group`。 + + +uni-app的内置组件已经有了 `

`组件,用于提交表单内容。 + +然而几乎每个表单都需要做表单验证,为了方便做表单验证,减少重复开发,`uni ui` 又基于 ``组件封装了 ``组件,内置了表单验证功能。 + +`` 提供了 `rules`属性来描述校验规则、``子组件来包裹具体的表单项,以及给原生或三方组件提供了 `binddata()` 来设置表单值。 + +每个要校验的表单项,不管input还是checkbox,都必须放在``组件中,且一个``组件只能放置一个表单项。 + +``组件内部预留了显示error message的区域,默认是在表单项的底部。 + +另外,``组件下面的各个表单项,可以通过``包裹为不同的分组。同一``下的不同表单项目将聚拢在一起,同其他group保持垂直间距。``仅影响视觉效果。 + +> **注意事项** +> 为了避免错误使用,给大家带来不好的开发体验,请在使用组件前仔细阅读下面的注意事项,可以帮你避免一些错误。 +> - 组件需要依赖 `sass` 插件 ,请自行手动安装 +> - `focus` 属性在开发者工具从不生效,需要真机测试 +> - `resetFields` 方法不会重置原生组件和三方组件的值 +> - 如果配置 `validateTrigger` 属性为 `bind` 且表单域组件使用 `input` 事件触发会耗损部分性能,请谨慎使用 +> - 如使用过程中有任何问题,或者您对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) + +### 基本用法 + +`uni-forms` 组件通常用来做表单校验和提交。每一个 `uni-forms-item` 是它的一个表单域组件,用来承载表单具体内容,`uni-forms-item` 中可以嵌套 `uni-easyinput`、`uni-data-checkbox` 和 uni-app内置的表单组件 ,不过 uni-app 的内置表单组件需要通过 `binddata` 或者 `uni-forms` 提供的 `setValue` 方法,将内容与 `uni-forms` 关联,才可完成表单的校验与提交(详见后文`表单校验` 部分) + +- 如需 `submit` 事件返回表单值,必须要指定 `name` 属性 + +```html + + +``` + +```javascript +export default { + data() { + return { + formData:{ + name:'', + age:'' + }, + hobby: [{ + text: '足球', + value: 0 + }, { + text: '篮球', + value: 1 + }, { + text: '游泳', + value: 2 + }] + } + }, + methods: { + submitForm(form) { + // 手动提交表单 + this.$refs.form.submit().then((res)=>{ + console.log('表单返回得值:', res) + }) + } + } +} + +``` + + +## 表单校验 + +表单校验还可以直接通过 `uniCloud web 控制台` 快速根据 `schema` 自动生成表单维护界面,比如新建页面和编辑页面,自动处理校验规则,更多参考[DB Schema](https://uniapp.dcloud.io/uniCloud/schema) + +### 如何使用 + +1. `uni-forms` 需要通过 `rules` 属性传入约定的校验规则(下文会详细描述) +2. `uni-forms` 需要绑定value属性,值为表单的key\value 组成的对象 +3. `uni-forms-item` 需要设置 `name` 属性为当前字段名,字段为 `String` 类型而非变量 +4. 如果使用`uni-easyinput` 和 `uni-data-checkbox` 等关联组件,只需绑定 v-model,无需其他操作 +5. 如果使用原生 input、checkbox 或三方组件等,只需要给组件绑定 `binddata` 方法即可触发表单校验,无需绑定事件到 `methods` 中 +6. `binddata('name',$event.detail.value,'form')"` 方法接受三个值, + - 第一个参数传入当前表单组件所在的 name,同当前父组件 `uni-forms-item` 绑定属性 `name` 的值 + - 第二个参数传入需要校验的值,内置组件可以通过 `$event.detail.value` 获取到组件的返回值,自定义组件传入需要校验的值即可 + - 第三个参数传入 `uni-forms` 组件绑定属性 `ref` 的值,通常在多表单的时候需要传入,用来区分表单,如页面中仅有一个 `uni-forms` 可忽略 +7. 如果内置 `binddata` 方法无法满足需求,在当前页面的 `methods` 中复写此方法即可,复写此方法需要调用 `uni-forms` 的 `setValue` 来触发表单校验 +8. 通过 `button` 按钮调用 `uni-forms` 的 `submit` 事件来校验并提交整个表单 + +```html + + +``` + +```javascript +export default { + data() { + return { + formData: { + name: 'LiMing', + email: 'dcloud@email.com' + }, + rules: { + // 对name字段进行必填验证 + name: { + rules: [{ + required: true, + errorMessage: '请输入姓名', + }, + { + minLength: 3, + maxLength: 5, + errorMessage: '姓名长度在 {minLength} 到 {maxLength} 个字符', + } + ] + }, + // 对email字段进行必填验证 + email: { + rules: [{ + format: 'email', + errorMessage: '请输入正确的邮箱地址', + }] + } + } + } + }, + methods: { + /** + * 复写 binddata 方法,如果只是为了校验,无复杂自定义操作,可忽略此方法 + * @param {String} name 字段名称 + * @param {String} value 表单域的值 + */ + // binddata(name,value){ + // 通过 input 事件设置表单指定 name 的值 + // this.$refs.form.setValue(name, value) + // }, + // 触发提交表单 + submit() { + this.$refs.form.submit().then(res=>{ + console.log('表单数据信息:', res); + }).catch(err =>{ + console.log('表单错误信息:', err); + }) + } + } +} +``` + + + + +### 校验规则 + +校验规则接受一个 `Object` 类型的值,通过传入不同的规则来表示每个表单域的值该如何校验 + +对象的 `key` 表示当前表单域的字段名,`value` 为具体的校验规则 + +以下为 `value` 所包含的内容: + +|属性名 | 类型 | 说明 | +|:-: | :-: | :-: | +|rules | Array | 校验规则,见下方 `rules 属性说明` | +|validateTrigger| String| 表单校验时机| +|label | String| 当前表单域的字段中文名,多用于 `errorMessage` 的显示,可不填| + + +```javascript +rules: { + // 对name字段进行必填验证 + name: { + // name 字段的校验规则 + rules:[ + // 校验 name 不能为空 + { + required: true, + message: '请填写姓名', + }, + // 对name字段进行长度验证 + { + minLength: 3, + maxLength: 5, + message: '{label}长度在 {minLength} 到 {maxLength} 个字符', + } + ], + label:'姓名' + } +} + +``` + + +### rules 属性说明 +每一个验证规则中,可以配置多个属性,下面是一些常见规则属性。实际上这里的规范,与uniCloud的[DB Schema](https://uniapp.dcloud.io/uniCloud/schema?id=validator)规范相同。 + +|属性名 | 类型 | 默认值|可选值 | 说明 | +|:-: | :-: | :-: |:-: | :-: | +|required | Boolean | - | | 是否必填,配置此参数不会显示输入框左边的必填星号,如需要,请配置`uni-forms-item`组件的的required为true| +|range | Array | - | - | 数组至少要有一个元素,且数组内的每一个元素都是唯一的。 | +|format | String | - | - | 内置校验规则,如这些规则无法满足需求,可以使用正则匹配或者自定义规则 | +|pattern | RegExp | - | - | 正则表达式,如验证邮箱:/^\S+?@\S+?\.\S+?$/ (注意不带引号),或使用 "^\\S+?@\\S+?\\.\\S+?$"(注意带引号需要使用 `\` 转义) | +|maximum | Number | - | - | 校验最大值(大于)| +|minimum | Number | - | - | 校验最小值(小于) | +|maxLength | Number | - | - | 校验数据最大长度 | +|errorMessage | String | - | - | 校验失败提示信息语,可添加属性占位符,当前表格内属性都可用作占位符 | +|trigger | String | blur | blur/change/submit| 校验触发时机 | +|validateFunction | Function| - | - | 自定义校验规则 | + + +**format属性值说明** + +|属性名 | 说明 | +|:-: | :-: | +|string | 必须是 string 类型,默认类型| +|number | 必须是 number 类型| +|boolean | 必须是 boolean 类型| +|array | 必须是 array 类型| +|object | 必须是 object 类型| +|url | 必须是 url 类型| +|email | 必须是 email 类型| + + +### validateFunction 自定义校验规则使用说明 +`uni-forms` 的 `rules` 基础规则有时候不能满足项目的所有使用场景,这时候可以使用 `validateFunction` 来自定义校验规则 + +`validateFunction` 方法返回四个参数 `validateFunction:function(rule,value,data,callback){}` ,当然返回参数名开发者可以自定义: + - rule : 当前校验字段在 rules 中所对应的校验规则 + - value : 当前校验字段的值 + - data : 所有校验字段的字段和值的对象 + - callback : 校验完成时的回调,一般无需执行callback,返回true(校验通过)或者false(校验失败)即可 ,如果需要显示不同的 `errMessage`,如果校验不通过需要执行 callback('提示错误信息'),如果校验通过,执行callback()即可 + + +需要注意的是,如果需要使用 `validateFunction` 自定义校验规则,则不能采用 `uni-forms` 的 `rules` 属性来配置校验规则,这时候需要通过`ref`,在`onReady`生命周期调用组件的`setRules`方法绑定验证规则 + +无法通过props传递变量,是因为微信小程序会过滤掉对象中的方法,导致自定义验证规则无效。 + + + +```html + + +``` + +```javascript +export default { + data() { + return { + rules: { + hobby: { + rules: [{ + required: true, + errorMessage: '请选择兴趣', + },{ + validateFunction:function(rule,value,data,callback){ + if (value.length < 2) { + callback('请至少勾选两个兴趣爱好') + } + return true + } + }] + } + } + } + }, + onReady() { + // 需要在onReady中设置规则 + this.$refs.form.setRules(this.rules) + }, + methods: { + submit(form) { + this.$refs.form.submit().then(res=>{ + console.log('表单数据信息:', res); + }).catch(err =>{ + console.log('表单错误信息:', err); + }) + } + } +} + +``` + + +### validateFunction 异步校验 + +上面的自定义校验方式为同步校验 ,如果需要异步校验,`validateFunction` 需要返回一个 `Promise` ,校验不通过 执行 `reject(new Error('错误信息'))` 返回对应的错误信息,如果校验通过则直接执行 `resolve()` 即可,在异步校验方法中,不需要使用 `callback` + +```html + + +``` + +```javascript +export default { + data() { + return { + rules: { + age: { + rules: [{ + required: true, + errorMessage: '请输入年龄', + },{ + validateFunction: (rule, value, data, callback) => { + // 异步需要返回 Promise 对象 + return new Promise((resolve, reject) => { + setTimeout(() => { + if (value > 10 ) { + // 通过返回 resolve + resolve() + } else { + // 不通过返回 reject(new Error('错误信息')) + reject(new Error('年龄必须大于十岁')) + } + }, 2000) + }) + } + }] + } + } + } + }, + onReady() { + // 需要在onReady中设置规则 + this.$refs.form.setRules(this.rules) + }, + methods: { + /** + * 表单提交 + * @param {Object} event + */ + submit() { + uni.showLoading() + this.$refs.form.submit().then(res => { + uni.hideLoading() + console.log('表单数据信息:', res); + }).catch(err => { + uni.hideLoading() + console.log('表单错误信息:', err); + }) + } + } +} + +``` + + +### 表单校验时机说明 + +不管是在规则里还是`uni-forms`、`uni-forms-item`里,都有 `validateTrigger` 属性, `validateTrigger` 属性规定了表单校验时机,当前只有 `bind`、`submit` 两个值域 + +- `bind` : 数据绑定时触发校验,`uni-esayinput` 、`uni-data-checkbox` 组件表现为数据发生变化时。其他内置或三方组件为 `binddata` 事件执行时机 + +```html + + + +``` + +- `submit`: 只有提交表单才会触发表单校验 + + +对于表单校验时机,同时只会有一个 `validateTrigger` 发生作用,它的作用权重为 + +**`规则 > uni-forms-item > uni-forms `** + +- 如果规则里配置 `validateTrigger` ,则优先使用规则里的 `validateTrigger` 属性来决定表单校验时机 +- 如果规则里没有配置 `validateTrigger` ,则优先使用 `uni-forms-item` 的 `validateTrigger` 属性来决定表单校验时机 +- 如果 `uni-forms-item` 组件里没有配置 `validateTrigger` ,则优先使用 `uni-forms` 的 `validateTrigger` 属性来决定表单校验时机 +- 以此类推,如果都没有使用 `validateTrigger` 属性,则会使用 `uni-forms` 的 `validateTrigger` 属性默认值来决定表单校验时机 + + +## API + +### Forms Props + +| 属性名 | 类型 |默认值 | 可选值 | 说明| +| :-: | :-: |:-: | :-: | :-: | +| v-model/value | Object | - | - | 表单数据| +| rules | Object | - | - | 表单校验规则 | +| validate-trigger| String | submit | bind/submit | 表单校验时机| +| label-position | String | left | top/left | label 位置 +| label-width | String/Number | 75 | - | label 宽度,单位 px | +| label-align | String | left | left/center/right | label 居中方式| +| err-show-type | String | undertext | undertext/toast/modal | 表单错误信息提示方式| +| border | Boolean |false |- |是否显示分格线| + +### Forms Events + +事件称名 |说明 +:-: |:-: +validate | 任意表单项被校验后触发,返回表单校验信息 + +### Forms Methods + +| 方法称名 | 说明 | +| :-: | :-: | +| submit | 对整个表单进行校验的方法,会返回一个 promise | +| setValue | 设置表单某一项 name 的对应值,通常在 uni-forms-item 和自定表单组件中使用| +| validateField | 部分表单进行校验 | +| clearValidate | 移除表单的校验结果 | +| resetFields | 重置表单, 需要把 `uni-forms` 的`value`属性改为 `v-model` ,且对内置组件可能不生效| + + +```javascript +/** + * 模板 + */ + +// 对整个表单进行校验,返回一个 Promise +this.$refs.form.submit().then((res)=>{ + // 成功返回,res 为表单数据 + // 其他逻辑处理 + // ... +}).catch((err)=>{ + // 表单校验验失败,err 为具体错误信息 + // 其他逻辑处理 + // ... +}) + +// 设置表单某项对应得值来触发表单校验 +// 接受两个参数,第一个参数为表单域的 name ,第二个参数为表单域的值 +this.$refs.form.setValue('name','内容') + +// 部分表单进行校验,接受一个参数,类型为 String 或 Array ,只校验传入 name 表单域的值 +this.$refs.form.validateField(['name', 'email']).then((res)=>{ + // 成功返回,res 为对应表单数据 + // 其他逻辑处理 + // ... +}).catch((err)=>{ + // 表单校验验失败,err 为具体错误信息 + // 其他逻辑处理 + // ... +}) + +// 移除表单校验,接受一个参数,类型为 String 或 Array ,只移除传入 name 表单域的值,如果不传入参数,则移除所有 +this.$refs.form.clearValidate(['name', 'email']) + +``` + + +### FormsItem Props + +| 属性名 |类型 |默认值 |可选值 |说明| +| :-: |:-: |:-: |:-: |:-: | +| name |String | - |- | 表单域的属性名,在使用校验规则时必填| +| required |Boolean| false | | 左边显示红色"*"号,样式显示不会对校验规则产生效果| +| validate-trigger|String | submit | bind/submit | 表单校验时机| +| left-icon |String | - |- | label左边的图标,限uni-ui的图标名称| +| icon-color |String | #606266 |- | 左边通过icon配置的图标的颜色| +| label |String | - |- | 输入框左边的文字提示| +| label-width |Number | 65 |- | label的宽度,单位px| +| label-align |String | left |left/center/right | label的文字对齐方式| +| label-position |String | left |top/left | label的文字的位置| +| error-message |String | - |- | 显示的错误提示内容,如果为空字符串或者false,则不显示错误信息| diff --git a/uni_modules/opendb-feedback/uni_modules/uni-group/changelog.md b/uni_modules/opendb-feedback/uni_modules/uni-group/changelog.md new file mode 100644 index 00000000..ddaac006 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-group/changelog.md @@ -0,0 +1,3 @@ +## 1.0.2(2021-02-05) +- 调整为uni_modules目录规范 +- 优化 兼容 nvue 页面 diff --git a/uni_modules/opendb-feedback/uni_modules/uni-group/components/uni-group/uni-group.vue b/uni_modules/opendb-feedback/uni_modules/uni-group/components/uni-group/uni-group.vue new file mode 100644 index 00000000..67ba869b --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-group/components/uni-group/uni-group.vue @@ -0,0 +1,128 @@ + + + + diff --git a/uni_modules/opendb-feedback/uni_modules/uni-group/package.json b/uni_modules/opendb-feedback/uni_modules/uni-group/package.json new file mode 100644 index 00000000..127766e0 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-group/package.json @@ -0,0 +1,82 @@ +{ + "id": "uni-group", + "displayName": "Group 分组", + "version": "1.0.2", + "description": "分组组件可用于将组件用于分组,添加间隔,以产生明显的区块", + "keywords": [ + "uni-group", + "group", + "分组", + "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/opendb-feedback/uni_modules/uni-group/readme.md b/uni_modules/opendb-feedback/uni_modules/uni-group/readme.md new file mode 100644 index 00000000..dcce669f --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-group/readme.md @@ -0,0 +1,48 @@ + + +### Group 分组 + +分组组件可用于将组件分组,添加间隔,以产生明显的区块,组件名:``uni-group``,代码块: uGroup。 + +### 平台差异说明 + +如无特殊说明,则全平台可用 + +### 组件使用注意事项 + +为了避免错误使用,给大家带来不好的开发体验,请在使用组件前仔细阅读下面的注意事项,可以帮你避免一些错误。 + +- 组件需要依赖 `sass` 插件 ,请自行手动安装 +- 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 + + +### 安装方式 + +本组件符合[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 + + 分组1 的内容 + 分组1 的内容 + + + + 分组2 的内容 + 分组2 的内容 + +``` + +### 属性说明 + +属性名|类型|默认值|说明 +:-:|:-:|:-:|:-: +title|String|主标题| +top|Number|分组间隔| + diff --git a/uni_modules/opendb-feedback/uni_modules/uni-icons/changelog.md b/uni_modules/opendb-feedback/uni_modules/uni-icons/changelog.md new file mode 100644 index 00000000..887bcdff --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-icons/changelog.md @@ -0,0 +1,2 @@ +## 1.1.4(2021-02-05) +- 调整为uni_modules目录规范 diff --git a/uni_modules/opendb-feedback/uni_modules/uni-icons/components/uni-icons/icons.js b/uni_modules/opendb-feedback/uni_modules/uni-icons/components/uni-icons/icons.js new file mode 100644 index 00000000..5242f227 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-icons/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/uni_modules/opendb-feedback/uni_modules/uni-icons/components/uni-icons/uni-icons.vue b/uni_modules/opendb-feedback/uni_modules/uni-icons/components/uni-icons/uni-icons.vue new file mode 100644 index 00000000..71aef8a0 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-icons/components/uni-icons/uni-icons.vue @@ -0,0 +1,71 @@ + + + + + diff --git a/uni_modules/opendb-feedback/uni_modules/uni-icons/components/uni-icons/uni.ttf b/uni_modules/opendb-feedback/uni_modules/uni-icons/components/uni-icons/uni.ttf new file mode 100644 index 0000000000000000000000000000000000000000..60a1968d08cc6056c70b5402b2effac43c6f96a3 GIT binary patch literal 26164 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 literal 0 HcmV?d00001 diff --git a/uni_modules/opendb-feedback/uni_modules/uni-icons/package.json b/uni_modules/opendb-feedback/uni_modules/uni-icons/package.json new file mode 100644 index 00000000..8a856970 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-icons/package.json @@ -0,0 +1,81 @@ +{ + "id": "uni-icons", + "displayName": "Icons 图标", + "version": "1.1.4", + "description": "图标组件,用于展示移动端常见的图标,可自定义颜色、大小。", + "keywords": [ + "icon", + "图标", + "uni-icons" +], + "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/opendb-feedback/uni_modules/uni-icons/readme.md b/uni_modules/opendb-feedback/uni_modules/uni-icons/readme.md new file mode 100644 index 00000000..a2372048 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-icons/readme.md @@ -0,0 +1,43 @@ + + +## Icons 图标 +> 代码块: `uIcons` + + +用于展示 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 + +### Icons Props + +|属性名 |类型 |默认值 |说明 | +|:-: |:-: |:-: |:-: | +|size |Number |24 |图标大小 | +|type |String |- |图标图案,参考示例 | +|color |String |- |图标颜色 | + + +### Icons Events +|事件名 |说明 |返回值| +|:-: |:-: |:-: | +|@click|点击 Icon 触发事件|- | + diff --git a/uni_modules/opendb-feedback/uni_modules/uni-link/changelog.md b/uni_modules/opendb-feedback/uni_modules/uni-link/changelog.md new file mode 100644 index 00000000..861e56be --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-link/changelog.md @@ -0,0 +1,4 @@ +## 0.0.3(2021-03-09) +- 新增 href 属性支持 tel:|mailto: +## 0.0.2(2021-02-05) +- 调整为uni_modules目录规范 diff --git a/uni_modules/opendb-feedback/uni_modules/uni-link/components/uni-link/uni-link.vue b/uni_modules/opendb-feedback/uni_modules/uni-link/components/uni-link/uni-link.vue new file mode 100644 index 00000000..6b5f4fb7 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-link/components/uni-link/uni-link.vue @@ -0,0 +1,111 @@ + + + + + diff --git a/uni_modules/opendb-feedback/uni_modules/uni-link/package.json b/uni_modules/opendb-feedback/uni_modules/uni-link/package.json new file mode 100644 index 00000000..3908ef07 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-link/package.json @@ -0,0 +1,82 @@ +{ + "id": "uni-link", + "displayName": "Link 超链接", + "version": "0.0.3", + "description": "uni-link是一个外部网页超链接组件,在小程序内复制url,在app内打开外部浏览器,在h5端打", + "keywords": [ + "", + "link", + "超链接", + "ulink" +], + "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": "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/opendb-feedback/uni_modules/uni-link/readme.md b/uni_modules/opendb-feedback/uni_modules/uni-link/readme.md new file mode 100644 index 00000000..43f6c582 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-link/readme.md @@ -0,0 +1,41 @@ + + +## Link 链接 +> 代码块: `uLink` + + +uni-link是一个外部网页超链接组件,在小程序内复制url,在app内打开外部浏览器,在h5端打开新网页。 + +### 安装方式 + +本组件符合[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 + +### Link Props + +|属性名 |类型 |默认值 |说明 | +|:-: |:-: |:-: |:-: | +|href |String |- |链接地址 | +|text |String |- |显示文字 | +|showUnderLine|Boolean|true |是否显示下划线 | +|copyTips |String |已自动复制网址,请在手机浏览器里粘贴该网址 |在小程序端复制链接时的提示语 | +|color |String |#999999 |链接文字颜色 | +|fontSize |String |14 |链接文字大小,单位px | + +### href属性对tel和mailto格式说明 + +|值 |说明 |平台 | +|:-: |:-: |:-: | +|tel:xxxxxxxxxxx |拨打电话 |H5,App | +|mailto:xxx@xxx.xxx |发送邮件 |H5 | diff --git a/uni_modules/opendb-feedback/uni_modules/uni-list/changelog.md b/uni_modules/opendb-feedback/uni_modules/uni-list/changelog.md new file mode 100644 index 00000000..cc4ea776 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-list/changelog.md @@ -0,0 +1,5 @@ +## 1.0.16(2021-02-05) +- 优化 组件引用关系,通过uni_modules引用组件 +## 1.0.15(2021-02-05) +- 调整为uni_modules目录规范 +- 修复 uni-list-chat 角标显示不正常的问题 diff --git a/uni_modules/opendb-feedback/uni_modules/uni-list/components/uni-list-ad/uni-list-ad.vue b/uni_modules/opendb-feedback/uni_modules/uni-list/components/uni-list-ad/uni-list-ad.vue new file mode 100644 index 00000000..553dea2c --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-list/components/uni-list-ad/uni-list-ad.vue @@ -0,0 +1,107 @@ + + + + + diff --git a/uni_modules/opendb-feedback/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.scss b/uni_modules/opendb-feedback/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.scss new file mode 100644 index 00000000..7e2708f7 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.scss @@ -0,0 +1,58 @@ +/** + * 这里是 uni-list 组件内置的常用样式变量 + * 如果需要覆盖样式,这里提供了基本的组件样式变量,您可以尝试修改这里的变量,去完成样式替换,而不用去修改源码 + * + */ + +// 背景色 +$background-color : #fff; +// 分割线颜色 +$divide-line-color : #e5e5e5; + +// 默认头像大小,如需要修改此值,注意同步修改 js 中的值 const avatarWidth = xx ,目前只支持方形头像 +// nvue 页面不支持修改头像大小 +$avatar-width : 45px ; + +// 头像边框 +$avatar-border-radius: 5px; +$avatar-border-color: #eee; +$avatar-border-width: 1px; + +// 标题文字样式 +$title-size : 16px; +$title-color : #3b4144; +$title-weight : normal; + +// 描述文字样式 +$note-size : 12px; +$note-color : #999; +$note-weight : normal; + +// 右侧额外内容默认样式 +$right-text-size : 12px; +$right-text-color : #999; +$right-text-weight : normal; + +// 角标样式 +// nvue 页面不支持修改圆点位置以及大小 +// 角标在左侧时,角标的位置,默认为 0 ,负数左/下移动,正数右/上移动 +$badge-left: 0px; +$badge-top: 0px; + +// 显示圆点时,圆点大小 +$dot-width: 10px; +$dot-height: 10px; + +// 显示角标时,角标大小和字体大小 +$badge-size : 18px; +$badge-font : 12px; +// 显示角标时,角标前景色 +$badge-color : #fff; +// 显示角标时,角标背景色 +$badge-background-color : #ff5a5f; +// 显示角标时,角标左右间距 +$badge-space : 6px; + +// 状态样式 +// 选中颜色 +$hover : #f5f5f5; diff --git a/uni_modules/opendb-feedback/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.vue b/uni_modules/opendb-feedback/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.vue new file mode 100644 index 00000000..8e8b1e67 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-list/components/uni-list-chat/uni-list-chat.vue @@ -0,0 +1,533 @@ + + + + + diff --git a/uni_modules/opendb-feedback/uni_modules/uni-list/components/uni-list-item/uni-list-item.vue b/uni_modules/opendb-feedback/uni_modules/uni-list/components/uni-list-item/uni-list-item.vue new file mode 100644 index 00000000..7f1eced0 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-list/components/uni-list-item/uni-list-item.vue @@ -0,0 +1,440 @@ + + + + + diff --git a/uni_modules/opendb-feedback/uni_modules/uni-list/components/uni-list/uni-list.vue b/uni_modules/opendb-feedback/uni_modules/uni-list/components/uni-list/uni-list.vue new file mode 100644 index 00000000..fc611ef9 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-list/components/uni-list/uni-list.vue @@ -0,0 +1,106 @@ + + + + diff --git a/uni_modules/opendb-feedback/uni_modules/uni-list/components/uni-list/uni-refresh.vue b/uni_modules/opendb-feedback/uni_modules/uni-list/components/uni-list/uni-refresh.vue new file mode 100644 index 00000000..3b4c5a23 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-list/components/uni-list/uni-refresh.vue @@ -0,0 +1,65 @@ + + + + + diff --git a/uni_modules/opendb-feedback/uni_modules/uni-list/components/uni-list/uni-refresh.wxs b/uni_modules/opendb-feedback/uni_modules/uni-list/components/uni-list/uni-refresh.wxs new file mode 100644 index 00000000..818a6b72 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-list/components/uni-list/uni-refresh.wxs @@ -0,0 +1,87 @@ +var pullDown = { + threshold: 95, + maxHeight: 200, + callRefresh: 'onrefresh', + callPullingDown: 'onpullingdown', + refreshSelector: '.uni-refresh' +}; + +function ready(newValue, oldValue, ownerInstance, instance) { + var state = instance.getState() + state.canPullDown = newValue; + // console.log(newValue); +} + +function touchStart(e, instance) { + var state = instance.getState(); + state.refreshInstance = instance.selectComponent(pullDown.refreshSelector); + state.canPullDown = (state.refreshInstance != null && state.refreshInstance != undefined); + if (!state.canPullDown) { + return + } + + // console.log("touchStart"); + + state.height = 0; + state.touchStartY = e.touches[0].pageY || e.changedTouches[0].pageY; + state.refreshInstance.setStyle({ + 'height': 0 + }); + state.refreshInstance.callMethod("onchange", true); +} + +function touchMove(e, ownerInstance) { + var instance = e.instance; + var state = instance.getState(); + if (!state.canPullDown) { + return + } + + var oldHeight = state.height; + var endY = e.touches[0].pageY || e.changedTouches[0].pageY; + var height = endY - state.touchStartY; + if (height > pullDown.maxHeight) { + return; + } + + var refreshInstance = state.refreshInstance; + refreshInstance.setStyle({ + 'height': height + 'px' + }); + + height = height < pullDown.maxHeight ? height : pullDown.maxHeight; + state.height = height; + refreshInstance.callMethod(pullDown.callPullingDown, { + height: height + }); +} + +function touchEnd(e, ownerInstance) { + var state = e.instance.getState(); + if (!state.canPullDown) { + return + } + + state.refreshInstance.callMethod("onchange", false); + + var refreshInstance = state.refreshInstance; + if (state.height > pullDown.threshold) { + refreshInstance.callMethod(pullDown.callRefresh); + return; + } + + refreshInstance.setStyle({ + 'height': 0 + }); +} + +function propObserver(newValue, oldValue, instance) { + pullDown = newValue; +} + +module.exports = { + touchmove: touchMove, + touchstart: touchStart, + touchend: touchEnd, + propObserver: propObserver +} diff --git a/uni_modules/opendb-feedback/uni_modules/uni-list/package.json b/uni_modules/opendb-feedback/uni_modules/uni-list/package.json new file mode 100644 index 00000000..cb108b1f --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-list/package.json @@ -0,0 +1,85 @@ +{ + "id": "uni-list", + "displayName": "List 列表", + "version": "1.0.16", + "description": "List 组件 ,帮助使用者快速构建列表。", + "keywords": [ + "", + "列表", + "uni-list", + "list" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": [ + "uni-badge", + "uni-icons" + ], + "encrypt": [], + "platforms": { + "cloud": { + "tcb": "y", + "aliyun": "y" + }, + "client": { + "App": { + "app-vue": "y", + "app-nvue": "y" + }, + "H5-mobile": { + "Safari": "y", + "Android Browser": "y", + "微信浏览器(Android)": "y", + "QQ浏览器(Android)": "y" + }, + "H5-pc": { + "Chrome": "y", + "IE": "y", + "Edge": "y", + "Firefox": "y", + "Safari": "y" + }, + "小程序": { + "微信": "y", + "阿里": "y", + "百度": "y", + "字节跳动": "y", + "QQ": "y" + }, + "快应用": { + "华为": "u", + "联盟": "u" + } + } + } + } +} \ No newline at end of file diff --git a/uni_modules/opendb-feedback/uni_modules/uni-list/readme.md b/uni_modules/opendb-feedback/uni_modules/uni-list/readme.md new file mode 100644 index 00000000..3dca899a --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-list/readme.md @@ -0,0 +1,340 @@ + + +## List 列表 +> 代码块: `uList`、`uListItem` +> 关联组件:`uni-list-item`、`uni-badge`、`uni-icons`、`uni-list-chat`、`uni-list-ad` + + +List 列表组件,包含基本列表样式、可扩展插槽机制、长列表性能优化、多端兼容。 + +在vue页面里,它默认使用页面级滚动。在app-nvue页面里,它默认使用原生list组件滚动。这样的长列表,在滚动出屏幕外后,系统会回收不可见区域的渲染内存资源,不会造成滚动越长手机越卡的问题。 + +uni-list组件是父容器,里面的核心是uni-list-item子组件,它代表列表中的一个可重复行,子组件可以无限循环。 + +uni-list-item有很多风格,uni-list-item组件通过内置的属性,满足一些常用的场景。当内置属性不满足需求时,可以通过扩展插槽来自定义列表内容。 + +内置属性可以覆盖的场景包括:导航列表、设置列表、小图标列表、通信录列表、聊天记录列表。 + +涉及很多大图或丰富内容的列表,比如类今日头条的新闻列表、类淘宝的电商列表,需要通过扩展插槽实现。 + +下文均有样例给出。 + +uni-list不包含下拉刷新和上拉翻页。上拉翻页另见组件:[uni-load-more](https://ext.dcloud.net.cn/plugin?id=29) + + +### 安装方式 + +本组件符合[easycom](https://uniapp.dcloud.io/collocation/pages?id=easycom)规范,`HBuilderX 2.5.5`起,只需将本组件导入项目,在页面`template`中即可直接使用,无需在页面中`import`和注册`components`。 + +如需通过`npm`方式使用`uni-ui`组件,另见文档:[https://ext.dcloud.net.cn/plugin?id=55](https://ext.dcloud.net.cn/plugin?id=55) + +> 为了避免错误使用,给大家带来不好的开发体验,请在使用组件前仔细阅读下面的注意事项,可以帮你避免一些错误。 +> - 组件需要依赖 `sass` 插件 ,请自行手动安装 +> - 组件内部依赖 `'uni-icons'` 、`uni-badge` 组件 +> - `uni-list` 和 `uni-list-item` 需要配套使用,暂不支持单独使用 `uni-list-item` +> - 只有开启点击反馈后,会有点击选中效果 +> - 使用插槽时,可以完全自定义内容 +> - note 、rightText 属性暂时没做限制,不支持文字溢出隐藏,使用时应该控制长度显示或通过默认插槽自行扩展 +> - 支付宝小程序平台需要在支付宝小程序开发者工具里开启 component2 编译模式,开启方式: 详情 --> 项目配置 --> 启用 component2 编译 +> - 如果需要修改 `switch`、`badge` 样式,请使用插槽自定义 +> - 在 `HBuilderX` 低版本中,可能会出现组件显示 `undefined` 的问题,请升级最新的 `HBuilderX` 或者 `cli` +> - 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 + + +### 基本用法 + +- 设置 `title` 属性,可以显示列表标题 +- 设置 `disabled` 属性,可以禁用当前项 + +```html + + + + + +``` + +### 多行内容显示 + +- 设置 `note` 属性 ,可以在第二行显示描述文本信息 + +```html + + + + + +``` + +### 右侧显示角标、switch + +- 设置 `show-badge` 属性 ,可以显示角标内容 +- 设置 `show-switch` 属性,可以显示 switch 开关 + +```html + + + + + +``` + +### 左侧显示略缩图、图标 + +- 设置 `thumb` 属性 ,可以在列表左侧显示略缩图 +- 设置 `show-extra-icon` 属性,并指定 `extra-icon` 可以在左侧显示图标 + +```html + + + + +``` + +### 开启点击反馈和右侧箭头 +- 设置 `clickable` 为 `true` ,则表示这是一个可点击的列表,会默认给一个点击效果,并可以监听 `click` 事件 +- 设置 `link` 属性,会自动开启点击反馈,并给列表右侧添加一个箭头 +- 设置 `to` 属性,可以跳转页面,`link` 的值表示跳转方式,如果不指定,默认为 `navigateTo` + +```html + + + + + + + +``` + + +### 聊天列表示例 +- 设置 `clickable` 为 `true` ,则表示这是一个可点击的列表,会默认给一个点击效果,并可以监听 `click` 事件 +- 设置 `link` 属性,会自动开启点击反馈,`link` 的值表示跳转方式,如果不指定,默认为 `navigateTo` +- 设置 `to` 属性,可以跳转页面 +- `time` 属性,通常会设置成时间显示,但是这个属性不仅仅可以设置时间,你可以传入任何文本,注意文本长度可能会影响显示 +- `avatar` 和 `avatarList` 属性同时只会有一个生效,同时设置的话,`avatarList` 属性的长度大于1 ,`avatar` 属性将失效 +- 可以通过默认插槽自定义列表右侧内容 + +```html + + + + + + + + + + + + + + + + + 刚刚 + + + + + + + +``` + +```javascript + +export default { + components: {}, + data() { + return { + avatarList: [{ + url: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png' + }, { + url: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png' + }, { + url: 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dc-site/460d46d0-4fcc-11eb-8ff1-d5dcf8779628.png' + }] + } + } +} + +``` + + +```css + +.chat-custom-right { + flex: 1; + /* #ifndef APP-NVUE */ + display: flex; + /* #endif */ + flex-direction: column; + justify-content: space-between; + align-items: flex-end; +} + +.chat-custom-text { + font-size: 12px; + color: #999; +} + +``` + +## API + +### List Props + +属性名 |类型 |默认值 | 说明 +:-: |:-: |:-: | :-: +border |Boolean |true | 是否显示边框 + + +### ListItem Props + +属性名 |类型 |默认值 | 说明 +:-: |:-: |:-: | :-: +title |String |- | 标题 +note |String |- | 描述 +ellipsis |Number |0 | title 是否溢出隐藏,可选值,0:默认; 1:显示一行; 2:显示两行;【nvue 暂不支持】 +thumb |String |- | 左侧缩略图,若thumb有值,则不会显示扩展图标 +thumbSize |String |medium | 略缩图尺寸,可选值,lg:大图; medium:一般; sm:小图; +showBadge |Boolean |false | 是否显示数字角标 +badgeText |String |- | 数字角标内容 +badgeType |String |- | 数字角标类型,参考[uni-icons](https://ext.dcloud.net.cn/plugin?id=21) +rightText |String |- | 右侧文字内容 +disabled |Boolean |false | 是否禁用 +showArrow |Boolean |true | 是否显示箭头图标 +link |String |navigateTo | 新页面跳转方式,可选值见下表 +to |String |- | 新页面跳转地址,如填写此属性,click 会返回页面是否跳转成功 +clickable |Boolean |false | 是否开启点击反馈 +showSwitch |Boolean |false | 是否显示Switch +switchChecked |Boolean |false | Switch是否被选中 +showExtraIcon |Boolean |false | 左侧是否显示扩展图标 +extraIcon |Object |- | 扩展图标参数,格式为 ``{color: '#4cd964',size: '22',type: 'spinner'}``,参考 [uni-icons](https://ext.dcloud.net.cn/plugin?id=28) +direction | String |row | 排版方向,可选值,row:水平排列; column:垂直排列; 3个插槽是水平排还是垂直排,也受此属性控制 + + +#### Link Options + +属性名 | 说明 +:-: | :-: +navigateTo | 同 uni.navigateTo() +redirectTo | 同 uni.reLaunch() +reLaunch | 同 uni.reLaunch() +switchTab | 同 uni.switchTab() + +### ListItem Events + +事件称名 |说明 |返回参数 +:-: |:-: |:-: +click |点击 uniListItem 触发事件,需开启点击反馈 |- +switchChange |点击切换 Switch 时触发,需显示 switch |e={value:checked} + + + +### ListItem Slots + +名称 | 说明 +:-: | :-: +header | 左/上内容插槽,可完全自定义默认显示 +body | 中间内容插槽,可完全自定义中间内容 +footer | 右/下内容插槽,可完全自定义右侧内容 + + +> 需要注意的是当使用插槽时,内置样式将会失效,只保留排版样式,此时的样式需要开发者自己实现 +> 如果 `uni-list-item` 组件内置属性样式无法满足需求,可以使用插槽来自定义uni-list-item里的内容。 +> uni-list-item提供了3个可扩展的插槽:`header`、`body`、`footer` +> - 当 `direction` 属性为 `row` 时表示水平排列,此时 `header` 表示列表的左边部分,`body` 表示列表的中间部分,`footer` 表示列表的右边部分 +> - 当 `direction` 属性为 `column` 时表示垂直排列,此时 `header` 表示列表的上边部分,`body` 表示列表的中间部分,`footer` 表示列表的下边部分 +> 开发者可以只用1个插槽,也可以3个一起使用。在插槽中可自主编写view标签,实现自己所需的效果。 + + +**示例** + +```html + + + + + + + + + 自定义插槽 + + + + +``` + + + + + +### ListItemChat Props + +属性名 |类型 |默认值 | 说明 +:-: |:-: |:-: | :-: +title |String |- | 标题 +note |String |- | 描述 +clickable |Boolean |false | 是否开启点击反馈 +badgeText |String |- | 数字角标内容,设置为 `dot` 将显示圆点 +badgePositon |String |right | 角标位置 +link |String |navigateTo | 是否展示右侧箭头并开启点击反馈,可选值见下表 +clickable |Boolean |false | 是否开启点击反馈 +to |String |- | 跳转页面地址,如填写此属性,click 会返回页面是否跳转成功 +time |String |- | 右侧时间显示 +avatarCircle |Boolean |false | 是否显示圆形头像 +avatar |String |- | 头像地址,avatarCircle 不填时生效 +avatarList |Array |- | 头像组,格式为 [{url:''}] + +#### Link Options + +属性名 | 说明 +:-: | :-: +navigateTo | 同 uni.navigateTo() +redirectTo | 同 uni.reLaunch() +reLaunch | 同 uni.reLaunch() +switchTab | 同 uni.switchTab() + +### ListItemChat Slots + +名称 | 说明 +:- | :- +default | 自定义列表右侧内容(包括时间和角标显示) + +### ListItemChat Events +事件称名 | 说明 | 返回参数 +:-: | :-: | :-: +@click | 点击 uniListChat 触发事件 | {data:{}} ,如有 to 属性,会返回页面跳转信息 + + + + + + +## 基于uni-list扩展的页面模板 + +通过扩展插槽,可实现多种常见样式的列表 + +**新闻列表类** + +1. 云端一体混合布局:[https://ext.dcloud.net.cn/plugin?id=2546](https://ext.dcloud.net.cn/plugin?id=2546) +2. 云端一体垂直布局,大图模式:[https://ext.dcloud.net.cn/plugin?id=2583](https://ext.dcloud.net.cn/plugin?id=2583) +3. 云端一体垂直布局,多行图文混排:[https://ext.dcloud.net.cn/plugin?id=2584](https://ext.dcloud.net.cn/plugin?id=2584) +4. 云端一体垂直布局,多图模式:[https://ext.dcloud.net.cn/plugin?id=2585](https://ext.dcloud.net.cn/plugin?id=2585) +5. 云端一体水平布局,左图右文:[https://ext.dcloud.net.cn/plugin?id=2586](https://ext.dcloud.net.cn/plugin?id=2586) +6. 云端一体水平布局,左文右图:[https://ext.dcloud.net.cn/plugin?id=2587](https://ext.dcloud.net.cn/plugin?id=2587) +7. 云端一体垂直布局,无图模式,主标题+副标题:[https://ext.dcloud.net.cn/plugin?id=2588](https://ext.dcloud.net.cn/plugin?id=2588) + +**商品列表类** + +1. 云端一体列表/宫格视图互切:[https://ext.dcloud.net.cn/plugin?id=2651](https://ext.dcloud.net.cn/plugin?id=2651) +2. 云端一体列表(宫格模式):[https://ext.dcloud.net.cn/plugin?id=2671](https://ext.dcloud.net.cn/plugin?id=2671) +3. 云端一体列表(列表模式):[https://ext.dcloud.net.cn/plugin?id=2672](https://ext.dcloud.net.cn/plugin?id=2672) \ No newline at end of file diff --git a/uni_modules/opendb-feedback/uni_modules/uni-load-more/changelog.md b/uni_modules/opendb-feedback/uni_modules/uni-load-more/changelog.md new file mode 100644 index 00000000..7ed3afeb --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-load-more/changelog.md @@ -0,0 +1,4 @@ +## 1.1.7(2021-03-30) +- 修复 uni-load-more 在首页使用时,h5 平台报 'uni is not defined' 的 bug +## 1.1.6(2021-02-05) +- 调整为uni_modules目录规范 diff --git a/uni_modules/opendb-feedback/uni_modules/uni-load-more/components/uni-load-more/uni-load-more.vue b/uni_modules/opendb-feedback/uni_modules/uni-load-more/components/uni-load-more/uni-load-more.vue new file mode 100644 index 00000000..6e6f4263 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-load-more/components/uni-load-more/uni-load-more.vue @@ -0,0 +1,362 @@ + + + + + diff --git a/uni_modules/opendb-feedback/uni_modules/uni-load-more/package.json b/uni_modules/opendb-feedback/uni_modules/uni-load-more/package.json new file mode 100644 index 00000000..492ee795 --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-load-more/package.json @@ -0,0 +1,82 @@ +{ + "id": "uni-load-more", + "displayName": "LoadMore 加载更多", + "version": "1.1.7", + "description": "LoadMore 组件,常用在列表里面,做滚动加载使用。", + "keywords": [ + "loadmore", + "uni-ui", + "加载更多", + "load-more" +], + "repository": "https://github.com/dcloudio/uni-ui", + "engines": { + "HBuilderX": "" + }, + "directories": { + "example": "../../temps/example_temps" + }, + "dcloudext": { + "category": [ + "前端组件", + "通用组件" + ], + "sale": { + "regular": { + "price": "0.00" + }, + "sourcecode": { + "price": "0.00" + } + }, + "contact": { + "qq": "" + }, + "declaration": { + "ads": "无", + "data": "无", + "permissions": "无" + }, + "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" + }, + "uni_modules": { + "dependencies": [], + "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/opendb-feedback/uni_modules/uni-load-more/readme.md b/uni_modules/opendb-feedback/uni_modules/uni-load-more/readme.md new file mode 100644 index 00000000..af17c9ab --- /dev/null +++ b/uni_modules/opendb-feedback/uni_modules/uni-load-more/readme.md @@ -0,0 +1,65 @@ + + +### LoadMore 加载更多 +> **组件名:uni-load-more** +> 代码块: `uLoadMore` + + +用于列表中,做滚动加载使用,展示 loading 的各种状态。 + +### 安装方式 + +本组件符合[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 + +### LoadMore Props + +|属性名 |类型 | 可选值 |默认值 |说明 | +|:-: |:-: |:-: |:-: |:-: | +|iconSize |Number |- |24 |指定图标大小 | +|status |String |more/loading/noMore |more |loading 的状态 | +|showIcon |Boolean|- |true |是否显示 loading 图标 | +|iconType |String |snow/circle/auto |auto |指定图标样式| +|color |String |- |#777777 |图标和文字颜色 | +|contentText|Object|- |{contentdown: "上拉显示更多",contentrefresh: "正在加载...",contentnomore: "没有更多数据了"}|各状态文字说明 | + + +#### Status Options +|参数名称 |说明 | +|:-: |:-: | +|more |loading前 | +|loading|loading前中 | +|more |没有更多数据 | + +#### IconType Options +|参数名称 |说明 | +|:-: |:-: | +|snow |ios雪花加载样式 | +|circle |安卓环形加载样式 | +|auto |根据平台自动选择加载样式 | + + + + +> **说明** +> `iconType`为`snow`时,在`APP-NVUE`平台不可设置大小,在非`APP-NVUE`平台不可设置颜色 + + + +### 事件说明 + +|事件名 |说明 |返回值 | +|:-: |:-: |:-: | +|clickLoadMore |点击加载更多时触发 |e.detail={status:'loading'}| + diff --git a/uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/hdx/config.json b/uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/hdx/config.json new file mode 100644 index 00000000..d113a9e4 --- /dev/null +++ b/uni_modules/uni-config-center/uniCloud/cloudfunctions/common/uni-config-center/hdx/config.json @@ -0,0 +1,3 @@ +{ + "test":123 +} \ No newline at end of file -- GitLab