From 8006af20920a7686465351b11778d156cec6f239 Mon Sep 17 00:00:00 2001
From: "Mr.jiang" <714156421@qq.com>
Date: Wed, 14 Aug 2024 15:48:32 +0800
Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9bug?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
components/xlh-picker/xlh-picker.vue | 113 +++
my/gird/shoucang.vue | 4 +-
package.json | 28 +-
pages/my/cooperation.vue | 140 +++-
pages/my/hehuo.vue | 232 ++++--
uni_modules/uni-data-picker/changelog.md | 77 ++
.../components/uni-data-picker/keypress.js | 45 ++
.../uni-data-picker/uni-data-picker.uvue | 380 ++++++++++
.../uni-data-picker/uni-data-picker.vue | 551 ++++++++++++++
.../uni-data-pickerview/loading.uts | 1 +
.../uni-data-pickerview/uni-data-picker.js | 622 ++++++++++++++++
.../uni-data-pickerview/uni-data-picker.uts | 693 ++++++++++++++++++
.../uni-data-pickerview.css | 76 ++
.../uni-data-pickerview.uvue | 69 ++
.../uni-data-pickerview.vue | 323 ++++++++
uni_modules/uni-data-picker/package.json | 91 +++
uni_modules/uni-data-picker/readme.md | 22 +
uni_modules/uni-forms/changelog.md | 94 +++
.../uni-forms-item/uni-forms-item.vue | 627 ++++++++++++++++
.../components/uni-forms/uni-forms.vue | 397 ++++++++++
.../uni-forms/components/uni-forms/utils.js | 293 ++++++++
.../components/uni-forms/validate.js | 486 ++++++++++++
uni_modules/uni-forms/package.json | 88 +++
uni_modules/uni-forms/readme.md | 23 +
24 files changed, 5401 insertions(+), 74 deletions(-)
create mode 100644 components/xlh-picker/xlh-picker.vue
create mode 100644 uni_modules/uni-data-picker/changelog.md
create mode 100644 uni_modules/uni-data-picker/components/uni-data-picker/keypress.js
create mode 100644 uni_modules/uni-data-picker/components/uni-data-picker/uni-data-picker.uvue
create mode 100644 uni_modules/uni-data-picker/components/uni-data-picker/uni-data-picker.vue
create mode 100644 uni_modules/uni-data-picker/components/uni-data-pickerview/loading.uts
create mode 100644 uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-picker.js
create mode 100644 uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-picker.uts
create mode 100644 uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.css
create mode 100644 uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.uvue
create mode 100644 uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.vue
create mode 100644 uni_modules/uni-data-picker/package.json
create mode 100644 uni_modules/uni-data-picker/readme.md
create mode 100644 uni_modules/uni-forms/changelog.md
create mode 100644 uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue
create mode 100644 uni_modules/uni-forms/components/uni-forms/uni-forms.vue
create mode 100644 uni_modules/uni-forms/components/uni-forms/utils.js
create mode 100644 uni_modules/uni-forms/components/uni-forms/validate.js
create mode 100644 uni_modules/uni-forms/package.json
create mode 100644 uni_modules/uni-forms/readme.md
diff --git a/components/xlh-picker/xlh-picker.vue b/components/xlh-picker/xlh-picker.vue
new file mode 100644
index 0000000..419b23e
--- /dev/null
+++ b/components/xlh-picker/xlh-picker.vue
@@ -0,0 +1,113 @@
+
+
+
+
+
+ 请选择城市
+
+ {{cityArr[0][pickVal2[0]].AreaName}}
+ {{cityArr[1][pickVal2[1]].AreaName}}
+ {{cityArr[2][pickVal2[2]].AreaName}}
+
+
+
+
+
+
+
+
+
diff --git a/my/gird/shoucang.vue b/my/gird/shoucang.vue
index c44b727..eb6ae3c 100644
--- a/my/gird/shoucang.vue
+++ b/my/gird/shoucang.vue
@@ -72,7 +72,7 @@
{{item.consortiaName}}
-
立即预约
@@ -80,7 +80,7 @@
立即预约
-
+ -->
diff --git a/package.json b/package.json
index 278247b..200b866 100644
--- a/package.json
+++ b/package.json
@@ -1,13 +1,19 @@
{
- "id": "jc-record",
- "name": "基于jsfun-record修正并优化的声音录制插件",
- "version": "1.0.5",
- "description": "基于jsfun-record修正并优化的声音录制插件",
+ "id": "xlh-picker",
+ "name": "APP、小程序城市选择器、三级联动、二级联动",
+ "displayName": "APP、小程序城市选择器、三级联动、二级联动",
+ "version": "1.0.0",
+ "description": "适于用于各端的城市选择器、地址选择器、三级联动耳机联动",
"keywords": [
- "录制",
- "声音",
- "音频",
- "录音",
- "长按录音"
- ]
-}
+ "picker",
+ "选择器",
+ "城市",
+ "三级联动"
+ ],
+ "dcloudext": {
+ "category": [
+ "前端组件",
+ "通用组件"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/pages/my/cooperation.vue b/pages/my/cooperation.vue
index 3819f37..cae5b17 100644
--- a/pages/my/cooperation.vue
+++ b/pages/my/cooperation.vue
@@ -14,11 +14,35 @@
-
+
+
+
+
+
+
+ {{applyContent}}
+
+
+
+
+
+
+
+
+
+ 请选择城市
+
+ {{cityData}}
+
+
+
+
@@ -33,24 +57,106 @@
diff --git a/uni_modules/uni-data-picker/components/uni-data-picker/uni-data-picker.vue b/uni_modules/uni-data-picker/components/uni-data-picker/uni-data-picker.vue
new file mode 100644
index 0000000..179a4e0
--- /dev/null
+++ b/uni_modules/uni-data-picker/components/uni-data-picker/uni-data-picker.vue
@@ -0,0 +1,551 @@
+
+
+
+
+
+ {{errorMessage}}
+
+
+
+
+
+
+ {{item.text}}{{split}}
+
+
+
+ {{placeholder}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{popupTitle}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/uni-data-picker/components/uni-data-pickerview/loading.uts b/uni_modules/uni-data-picker/components/uni-data-pickerview/loading.uts
new file mode 100644
index 0000000..baa0dff
--- /dev/null
+++ b/uni_modules/uni-data-picker/components/uni-data-pickerview/loading.uts
@@ -0,0 +1 @@
+export const imgbase : string = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QzlBMzU3OTlEOUM0MTFFOUI0NTZDNERBQURBQzI4RkUiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QzlBMzU3OUFEOUM0MTFFOUI0NTZDNERBQURBQzI4RkUiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpDOUEzNTc5N0Q5QzQxMUU5QjQ1NkM0REFBREFDMjhGRSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpDOUEzNTc5OEQ5QzQxMUU5QjQ1NkM0REFBREFDMjhGRSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pt+ALSwAAA6CSURBVHja1FsLkFZV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'
\ No newline at end of file
diff --git a/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-picker.js b/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-picker.js
new file mode 100644
index 0000000..cfae22a
--- /dev/null
+++ b/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-picker.js
@@ -0,0 +1,622 @@
+export default {
+ props: {
+ localdata: {
+ type: [Array, Object],
+ default () {
+ return []
+ }
+ },
+ spaceInfo: {
+ type: Object,
+ default () {
+ return {}
+ }
+ },
+ collection: {
+ type: String,
+ default: ''
+ },
+ action: {
+ type: String,
+ default: ''
+ },
+ field: {
+ type: String,
+ default: ''
+ },
+ orderby: {
+ type: String,
+ default: ''
+ },
+ where: {
+ type: [String, Object],
+ default: ''
+ },
+ pageData: {
+ type: String,
+ default: 'add'
+ },
+ pageCurrent: {
+ type: Number,
+ default: 1
+ },
+ pageSize: {
+ type: Number,
+ default: 500
+ },
+ getcount: {
+ type: [Boolean, String],
+ default: false
+ },
+ getone: {
+ type: [Boolean, String],
+ default: false
+ },
+ gettree: {
+ type: [Boolean, String],
+ default: false
+ },
+ manual: {
+ type: Boolean,
+ default: false
+ },
+ value: {
+ type: [Array, String, Number],
+ default () {
+ return []
+ }
+ },
+ modelValue: {
+ type: [Array, String, Number],
+ default () {
+ return []
+ }
+ },
+ preload: {
+ type: Boolean,
+ default: false
+ },
+ stepSearh: {
+ type: Boolean,
+ default: true
+ },
+ selfField: {
+ type: String,
+ default: ''
+ },
+ parentField: {
+ type: String,
+ default: ''
+ },
+ multiple: {
+ type: Boolean,
+ default: false
+ },
+ map: {
+ type: Object,
+ default () {
+ return {
+ text: "text",
+ value: "value"
+ }
+ }
+ }
+ },
+ data() {
+ return {
+ loading: false,
+ errorMessage: '',
+ loadMore: {
+ contentdown: '',
+ contentrefresh: '',
+ contentnomore: ''
+ },
+ dataList: [],
+ selected: [],
+ selectedIndex: 0,
+ page: {
+ current: this.pageCurrent,
+ size: this.pageSize,
+ count: 0
+ }
+ }
+ },
+ computed: {
+ isLocalData() {
+ return !this.collection.length;
+ },
+ isCloudData() {
+ return this.collection.length > 0;
+ },
+ isCloudDataList() {
+ return (this.isCloudData && (!this.parentField && !this.selfField));
+ },
+ isCloudDataTree() {
+ return (this.isCloudData && this.parentField && this.selfField);
+ },
+ dataValue() {
+ let isModelValue = Array.isArray(this.modelValue) ? (this.modelValue.length > 0) : (this.modelValue !== null ||
+ this.modelValue !== undefined);
+ return isModelValue ? this.modelValue : this.value;
+ },
+ hasValue() {
+ if (typeof this.dataValue === 'number') {
+ return true
+ }
+ return (this.dataValue != null) && (this.dataValue.length > 0)
+ }
+ },
+ created() {
+ this.$watch(() => {
+ var al = [];
+ ['pageCurrent',
+ 'pageSize',
+ 'spaceInfo',
+ 'value',
+ 'modelValue',
+ 'localdata',
+ 'collection',
+ 'action',
+ 'field',
+ 'orderby',
+ 'where',
+ 'getont',
+ 'getcount',
+ 'gettree'
+ ].forEach(key => {
+ al.push(this[key])
+ });
+ return al
+ }, (newValue, oldValue) => {
+ let needReset = false
+ for (let i = 2; i < newValue.length; i++) {
+ if (newValue[i] != oldValue[i]) {
+ needReset = true
+ break
+ }
+ }
+ if (newValue[0] != oldValue[0]) {
+ this.page.current = this.pageCurrent
+ }
+ this.page.size = this.pageSize
+
+ this.onPropsChange()
+ })
+ this._treeData = []
+ },
+ methods: {
+ onPropsChange() {
+ this._treeData = [];
+ },
+
+ // 填充 pickview 数据
+ async loadData() {
+ if (this.isLocalData) {
+ this.loadLocalData();
+ } else if (this.isCloudDataList) {
+ this.loadCloudDataList();
+ } else if (this.isCloudDataTree) {
+ this.loadCloudDataTree();
+ }
+ },
+
+ // 加载本地数据
+ async loadLocalData() {
+ this._treeData = [];
+ this._extractTree(this.localdata, this._treeData);
+
+ let inputValue = this.dataValue;
+ if (inputValue === undefined) {
+ return;
+ }
+
+ if (Array.isArray(inputValue)) {
+ inputValue = inputValue[inputValue.length - 1];
+ if (typeof inputValue === 'object' && inputValue[this.map.value]) {
+ inputValue = inputValue[this.map.value];
+ }
+ }
+
+ this.selected = this._findNodePath(inputValue, this.localdata);
+ },
+
+ // 加载 Cloud 数据 (单列)
+ async loadCloudDataList() {
+ if (this.loading) {
+ return;
+ }
+ this.loading = true;
+
+ try {
+ let response = await this.getCommand();
+ let responseData = response.result.data;
+
+ this._treeData = responseData;
+
+ this._updateBindData();
+ this._updateSelected();
+
+ this.onDataChange();
+ } catch (e) {
+ this.errorMessage = e;
+ } finally {
+ this.loading = false;
+ }
+ },
+
+ // 加载 Cloud 数据 (树形)
+ async loadCloudDataTree() {
+ if (this.loading) {
+ return;
+ }
+ this.loading = true;
+
+ try {
+ let commandOptions = {
+ field: this._cloudDataPostField(),
+ where: this._cloudDataTreeWhere()
+ };
+ if (this.gettree) {
+ commandOptions.startwith = `${this.selfField}=='${this.dataValue}'`;
+ }
+
+ let response = await this.getCommand(commandOptions);
+ let responseData = response.result.data;
+
+ this._treeData = responseData;
+ this._updateBindData();
+ this._updateSelected();
+
+ this.onDataChange();
+ } catch (e) {
+ this.errorMessage = e;
+ } finally {
+ this.loading = false;
+ }
+ },
+
+ // 加载 Cloud 数据 (节点)
+ async loadCloudDataNode(callback) {
+ if (this.loading) {
+ return;
+ }
+ this.loading = true;
+
+ try {
+ let commandOptions = {
+ field: this._cloudDataPostField(),
+ where: this._cloudDataNodeWhere()
+ };
+
+ let response = await this.getCommand(commandOptions);
+ let responseData = response.result.data;
+
+ callback(responseData);
+ } catch (e) {
+ this.errorMessage = e;
+ } finally {
+ this.loading = false;
+ }
+ },
+
+ // 回显 Cloud 数据
+ getCloudDataValue() {
+ if (this.isCloudDataList) {
+ return this.getCloudDataListValue();
+ }
+
+ if (this.isCloudDataTree) {
+ return this.getCloudDataTreeValue();
+ }
+ },
+
+ // 回显 Cloud 数据 (单列)
+ getCloudDataListValue() {
+ // 根据 field's as value标识匹配 where 条件
+ let where = [];
+ let whereField = this._getForeignKeyByField();
+ if (whereField) {
+ where.push(`${whereField} == '${this.dataValue}'`)
+ }
+
+ where = where.join(' || ');
+
+ if (this.where) {
+ where = `(${this.where}) && (${where})`
+ }
+
+ return this.getCommand({
+ field: this._cloudDataPostField(),
+ where
+ }).then((res) => {
+ this.selected = res.result.data;
+ return res.result.data;
+ });
+ },
+
+ // 回显 Cloud 数据 (树形)
+ getCloudDataTreeValue() {
+ return this.getCommand({
+ field: this._cloudDataPostField(),
+ getTreePath: {
+ startWith: `${this.selfField}=='${this.dataValue}'`
+ }
+ }).then((res) => {
+ let treePath = [];
+ this._extractTreePath(res.result.data, treePath);
+ this.selected = treePath;
+ return treePath;
+ });
+ },
+
+ getCommand(options = {}) {
+ /* eslint-disable no-undef */
+ let db = uniCloud.database(this.spaceInfo)
+
+ const action = options.action || this.action
+ if (action) {
+ db = db.action(action)
+ }
+
+ const collection = options.collection || this.collection
+ db = db.collection(collection)
+
+ const where = options.where || this.where
+ if (!(!where || !Object.keys(where).length)) {
+ db = db.where(where)
+ }
+
+ const field = options.field || this.field
+ if (field) {
+ db = db.field(field)
+ }
+
+ const orderby = options.orderby || this.orderby
+ if (orderby) {
+ db = db.orderBy(orderby)
+ }
+
+ const current = options.pageCurrent !== undefined ? options.pageCurrent : this.page.current
+ const size = options.pageSize !== undefined ? options.pageSize : this.page.size
+ const getCount = options.getcount !== undefined ? options.getcount : this.getcount
+ const getTree = options.gettree !== undefined ? options.gettree : this.gettree
+
+ const getOptions = {
+ getCount,
+ getTree
+ }
+ if (options.getTreePath) {
+ getOptions.getTreePath = options.getTreePath
+ }
+
+ db = db.skip(size * (current - 1)).limit(size).get(getOptions)
+
+ return db
+ },
+
+ _cloudDataPostField() {
+ let fields = [this.field];
+ if (this.parentField) {
+ fields.push(`${this.parentField} as parent_value`);
+ }
+ return fields.join(',');
+ },
+
+ _cloudDataTreeWhere() {
+ let result = []
+ let selected = this.selected
+ let parentField = this.parentField
+ if (parentField) {
+ result.push(`${parentField} == null || ${parentField} == ""`)
+ }
+ if (selected.length) {
+ for (var i = 0; i < selected.length - 1; i++) {
+ result.push(`${parentField} == '${selected[i].value}'`)
+ }
+ }
+
+ let where = []
+ if (this.where) {
+ where.push(`(${this.where})`)
+ }
+
+ if (result.length) {
+ where.push(`(${result.join(' || ')})`)
+ }
+
+ return where.join(' && ')
+ },
+
+ _cloudDataNodeWhere() {
+ let where = []
+ let selected = this.selected;
+ if (selected.length) {
+ where.push(`${this.parentField} == '${selected[selected.length - 1].value}'`);
+ }
+
+ where = where.join(' || ');
+
+ if (this.where) {
+ return `(${this.where}) && (${where})`
+ }
+
+ return where
+ },
+
+ _getWhereByForeignKey() {
+ let result = []
+ let whereField = this._getForeignKeyByField();
+ if (whereField) {
+ result.push(`${whereField} == '${this.dataValue}'`)
+ }
+
+ if (this.where) {
+ return `(${this.where}) && (${result.join(' || ')})`
+ }
+
+ return result.join(' || ')
+ },
+
+ _getForeignKeyByField() {
+ let fields = this.field.split(',');
+ let whereField = null;
+ for (let i = 0; i < fields.length; i++) {
+ const items = fields[i].split('as');
+ if (items.length < 2) {
+ continue;
+ }
+ if (items[1].trim() === 'value') {
+ whereField = items[0].trim();
+ break;
+ }
+ }
+ return whereField;
+ },
+
+ _updateBindData(node) {
+ const {
+ dataList,
+ hasNodes
+ } = this._filterData(this._treeData, this.selected)
+
+ let isleaf = this._stepSearh === false && !hasNodes
+
+ if (node) {
+ node.isleaf = isleaf
+ }
+
+ this.dataList = dataList
+ this.selectedIndex = dataList.length - 1
+
+ if (!isleaf && this.selected.length < dataList.length) {
+ this.selected.push({
+ value: null,
+ text: "请选择"
+ })
+ }
+
+ return {
+ isleaf,
+ hasNodes
+ }
+ },
+
+ _updateSelected() {
+ let dl = this.dataList
+ let sl = this.selected
+ let textField = this.map.text
+ let valueField = this.map.value
+ for (let i = 0; i < sl.length; i++) {
+ let value = sl[i].value
+ let dl2 = dl[i]
+ for (let j = 0; j < dl2.length; j++) {
+ let item2 = dl2[j]
+ if (item2[valueField] === value) {
+ sl[i].text = item2[textField]
+ break
+ }
+ }
+ }
+ },
+
+ _filterData(data, paths) {
+ let dataList = []
+ let hasNodes = true
+
+ dataList.push(data.filter((item) => {
+ return (item.parent_value === null || item.parent_value === undefined || item.parent_value === '')
+ }))
+ for (let i = 0; i < paths.length; i++) {
+ let value = paths[i].value
+ let nodes = data.filter((item) => {
+ return item.parent_value === value
+ })
+
+ if (nodes.length) {
+ dataList.push(nodes)
+ } else {
+ hasNodes = false
+ }
+ }
+
+ return {
+ dataList,
+ hasNodes
+ }
+ },
+
+ _extractTree(nodes, result, parent_value) {
+ let list = result || []
+ let valueField = this.map.value
+ for (let i = 0; i < nodes.length; i++) {
+ let node = nodes[i]
+
+ let child = {}
+ for (let key in node) {
+ if (key !== 'children') {
+ child[key] = node[key]
+ }
+ }
+ if (parent_value !== null && parent_value !== undefined && parent_value !== '') {
+ child.parent_value = parent_value
+ }
+ result.push(child)
+
+ let children = node.children
+ if (children) {
+ this._extractTree(children, result, node[valueField])
+ }
+ }
+ },
+
+ _extractTreePath(nodes, result) {
+ let list = result || []
+ for (let i = 0; i < nodes.length; i++) {
+ let node = nodes[i]
+
+ let child = {}
+ for (let key in node) {
+ if (key !== 'children') {
+ child[key] = node[key]
+ }
+ }
+ result.push(child)
+
+ let children = node.children
+ if (children) {
+ this._extractTreePath(children, result)
+ }
+ }
+ },
+
+ _findNodePath(key, nodes, path = []) {
+ let textField = this.map.text
+ let valueField = this.map.value
+ for (let i = 0; i < nodes.length; i++) {
+ let node = nodes[i]
+ let children = node.children
+ let text = node[textField]
+ let value = node[valueField]
+
+ path.push({
+ value,
+ text
+ })
+
+ if (value === key) {
+ return path
+ }
+
+ if (children) {
+ const p = this._findNodePath(key, children, path)
+ if (p.length) {
+ return p
+ }
+ }
+
+ path.pop()
+ }
+ return []
+ }
+ }
+}
diff --git a/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-picker.uts b/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-picker.uts
new file mode 100644
index 0000000..372795d
--- /dev/null
+++ b/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-picker.uts
@@ -0,0 +1,693 @@
+export type PaginationType = {
+ current : number,
+ size : number,
+ count : number
+}
+
+export type LoadMoreType = {
+ contentdown : string,
+ contentrefresh : string,
+ contentnomore : string
+}
+
+export type SelectedItemType = {
+ name : string,
+ value : string,
+}
+
+export type GetCommandOptions = {
+ collection ?: UTSJSONObject,
+ field ?: string,
+ orderby ?: string,
+ where ?: any,
+ pageData ?: string,
+ pageCurrent ?: number,
+ pageSize ?: number,
+ getCount ?: boolean,
+ getTree ?: any,
+ getTreePath ?: UTSJSONObject,
+ startwith ?: string,
+ limitlevel ?: number,
+ groupby ?: string,
+ groupField ?: string,
+ distinct ?: boolean,
+ pageIndistinct ?: boolean,
+ foreignKey ?: string,
+ loadtime ?: string,
+ manual ?: boolean
+}
+
+const DefaultSelectedNode = {
+ text: '请选择',
+ value: ''
+}
+
+export const dataPicker = defineMixin({
+ props: {
+ localdata: {
+ type: Array as PropType>,
+ default: [] as Array
+ },
+ collection: {
+ type: Object,
+ default: ''
+ },
+ field: {
+ type: String,
+ default: ''
+ },
+ orderby: {
+ type: String,
+ default: ''
+ },
+ where: {
+ type: Object,
+ default: ''
+ },
+ pageData: {
+ type: String,
+ default: 'add'
+ },
+ pageCurrent: {
+ type: Number,
+ default: 1
+ },
+ pageSize: {
+ type: Number,
+ default: 20
+ },
+ getcount: {
+ type: Boolean,
+ default: false
+ },
+ gettree: {
+ type: Object,
+ default: ''
+ },
+ gettreepath: {
+ type: Object,
+ default: ''
+ },
+ startwith: {
+ type: String,
+ default: ''
+ },
+ limitlevel: {
+ type: Number,
+ default: 10
+ },
+ groupby: {
+ type: String,
+ default: ''
+ },
+ groupField: {
+ type: String,
+ default: ''
+ },
+ distinct: {
+ type: Boolean,
+ default: false
+ },
+ pageIndistinct: {
+ type: Boolean,
+ default: false
+ },
+ foreignKey: {
+ type: String,
+ default: ''
+ },
+ loadtime: {
+ type: String,
+ default: 'auto'
+ },
+ manual: {
+ type: Boolean,
+ default: false
+ },
+ preload: {
+ type: Boolean,
+ default: false
+ },
+ stepSearh: {
+ type: Boolean,
+ default: true
+ },
+ selfField: {
+ type: String,
+ default: ''
+ },
+ parentField: {
+ type: String,
+ default: ''
+ },
+ multiple: {
+ type: Boolean,
+ default: false
+ },
+ value: {
+ type: Object,
+ default: ''
+ },
+ modelValue: {
+ type: Object,
+ default: ''
+ },
+ defaultProps: {
+ type: Object as PropType,
+ }
+ },
+ data() {
+ return {
+ loading: false,
+ error: null as UniCloudError | null,
+ treeData: [] as Array,
+ selectedIndex: 0,
+ selectedNodes: [] as Array,
+ selectedPages: [] as Array[],
+ selectedValue: '',
+ selectedPaths: [] as Array,
+ pagination: {
+ current: 1,
+ size: 20,
+ count: 0
+ } as PaginationType
+ }
+ },
+ computed: {
+ mappingTextName() : string {
+ // TODO
+ return (this.defaultProps != null) ? this.defaultProps!.getString('text', 'text') : 'text'
+ },
+ mappingValueName() : string {
+ // TODO
+ return (this.defaultProps != null) ? this.defaultProps!.getString('value', 'value') : 'value'
+ },
+ currentDataList() : Array {
+ if (this.selectedIndex > this.selectedPages.length - 1) {
+ return [] as Array
+ }
+ return this.selectedPages[this.selectedIndex]
+ },
+ isLocalData() : boolean {
+ return this.localdata.length > 0
+ },
+ isCloudData() : boolean {
+ return this._checkIsNotNull(this.collection)
+ },
+ isCloudDataList() : boolean {
+ return (this.isCloudData && (this.parentField.length == 0 && this.selfField.length == 0))
+ },
+ isCloudDataTree() : boolean {
+ return (this.isCloudData && this.parentField.length > 0 && this.selfField.length > 0)
+ },
+ dataValue() : any {
+ return this.hasModelValue ? this.modelValue : this.value
+ },
+ hasCloudTreeData() : boolean {
+ return this.treeData.length > 0
+ },
+ hasModelValue() : boolean {
+ if (typeof this.modelValue == 'string') {
+ const valueString = this.modelValue as string
+ return (valueString.length > 0)
+ } else if (Array.isArray(this.modelValue)) {
+ const valueArray = this.modelValue as Array
+ return (valueArray.length > 0)
+ }
+ return false
+ },
+ hasCloudDataValue() : boolean {
+ if (typeof this.dataValue == 'string') {
+ const valueString = this.dataValue as string
+ return (valueString.length > 0)
+ }
+ return false
+ }
+ },
+ created() {
+ this.pagination.current = this.pageCurrent
+ this.pagination.size = this.pageSize
+
+ this.$watch(
+ () : any => [
+ this.pageCurrent,
+ this.pageSize,
+ this.localdata,
+ this.value,
+ this.collection,
+ this.field,
+ this.getcount,
+ this.orderby,
+ this.where,
+ this.groupby,
+ this.groupField,
+ this.distinct
+ ],
+ (newValue : Array, oldValue : Array) => {
+ this.pagination.size = this.pageSize
+ if (newValue[0] !== oldValue[0]) {
+ this.pagination.current = this.pageCurrent
+ }
+
+ this.onPropsChange()
+ }
+ )
+ },
+ methods: {
+ onPropsChange() {
+ this.selectedIndex = 0
+ this.treeData.length = 0
+ this.selectedNodes.length = 0
+ this.selectedPages.length = 0
+ this.selectedPaths.length = 0
+
+ // 加载数据
+ this.$nextTick(() => {
+ this.loadData()
+ })
+ },
+
+ onTabSelect(index : number) {
+ this.selectedIndex = index
+ },
+
+ onNodeClick(nodeData : UTSJSONObject) {
+ if (nodeData.getBoolean('disable', false)) {
+ return
+ }
+
+ const isLeaf = this._checkIsLeafNode(nodeData)
+
+ this._trimSelectedNodes(nodeData)
+
+ this.$emit('nodeclick', nodeData)
+
+ if (this.isLocalData) {
+ if (isLeaf || !this._checkHasChildren(nodeData)) {
+ this.onFinish()
+ }
+ } else if (this.isCloudDataList) {
+ this.onFinish()
+ } else if (this.isCloudDataTree) {
+ if (isLeaf) {
+ this.onFinish()
+ } else if (!this._checkHasChildren(nodeData)) {
+ // 尝试请求一次,如果没有返回数据标记为叶子节点
+ this.loadCloudDataNode(nodeData)
+ }
+ }
+ },
+
+ getChangeNodes(): Array {
+ const nodes: Array = []
+ this.selectedNodes.forEach((node : UTSJSONObject) => {
+ const newNode: UTSJSONObject = {}
+ newNode[this.mappingTextName] = node.getString(this.mappingTextName)
+ newNode[this.mappingValueName] = node.getString(this.mappingValueName)
+ nodes.push(newNode)
+ })
+ return nodes
+ },
+
+ onFinish() { },
+
+ // 加载数据(自动判定环境)
+ loadData() {
+ if (this.isLocalData) {
+ this.loadLocalData()
+ } else if (this.isCloudDataList) {
+ this.loadCloudDataList()
+ } else if (this.isCloudDataTree) {
+ this.loadCloudDataTree()
+ }
+ },
+
+ // 加载本地数据
+ loadLocalData() {
+ this.treeData = this.localdata
+ if (Array.isArray(this.dataValue)) {
+ const value = this.dataValue as Array
+ this.selectedPaths = value.slice(0)
+ this._pushSelectedTreeNodes(value, this.localdata)
+ } else {
+ this._pushSelectedNodes(this.localdata)
+ }
+ },
+
+ // 加载 Cloud 数据 (单列)
+ loadCloudDataList() {
+ this._loadCloudData(null, (data : Array) => {
+ this.treeData = data
+ this._pushSelectedNodes(data)
+ })
+ },
+
+ // 加载 Cloud 数据 (树形)
+ loadCloudDataTree() {
+ let commandOptions = {
+ field: this._cloudDataPostField(),
+ where: this._cloudDataTreeWhere(),
+ getTree: true
+ } as GetCommandOptions
+ if (this._checkIsNotNull(this.gettree)) {
+ commandOptions.startwith = `${this.selfField}=='${this.dataValue as string}'`
+ }
+ this._loadCloudData(commandOptions, (data : Array) => {
+ this.treeData = data
+ if (this.selectedPaths.length > 0) {
+ this._pushSelectedTreeNodes(this.selectedPaths, data)
+ } else {
+ this._pushSelectedNodes(data)
+ }
+ })
+ },
+
+ // 加载 Cloud 数据 (节点)
+ loadCloudDataNode(nodeData : UTSJSONObject) {
+ const commandOptions = {
+ field: this._cloudDataPostField(),
+ where: this._cloudDataNodeWhere()
+ } as GetCommandOptions
+ this._loadCloudData(commandOptions, (data : Array) => {
+ nodeData['children'] = data
+ if (data.length == 0) {
+ nodeData['isleaf'] = true
+ this.onFinish()
+ } else {
+ this._pushSelectedNodes(data)
+ }
+ })
+ },
+
+ // 回显 Cloud Tree Path
+ loadCloudDataPath() {
+ if (!this.hasCloudDataValue) {
+ return
+ }
+
+ const command : GetCommandOptions = {}
+
+ // 单列
+ if (this.isCloudDataList) {
+ // 根据 field's as value标识匹配 where 条件
+ let where : Array = [];
+ let whereField = this._getForeignKeyByField();
+ if (whereField.length > 0) {
+ where.push(`${whereField} == '${this.dataValue as string}'`)
+ }
+
+ let whereString = where.join(' || ')
+ if (this._checkIsNotNull(this.where)) {
+ whereString = `(${this.where}) && (${whereString})`
+ }
+
+ command.field = this._cloudDataPostField()
+ command.where = whereString
+ }
+
+ // 树形
+ if (this.isCloudDataTree) {
+ command.field = this._cloudDataPostField()
+ command.getTreePath = {
+ startWith: `${this.selfField}=='${this.dataValue as string}'`
+ }
+ }
+
+ this._loadCloudData(command, (data : Array) => {
+ this._extractTreePath(data, this.selectedPaths)
+ })
+ },
+
+ _loadCloudData(options ?: GetCommandOptions, callback ?: ((data : Array) => void)) {
+ if (this.loading) {
+ return
+ }
+ this.loading = true
+
+ this.error = null
+
+ this._getCommand(options).then((response : UniCloudDBGetResult) => {
+ callback?.(response.data)
+ }).catch((err : any | null) => {
+ this.error = err as UniCloudError
+ }).finally(() => {
+ this.loading = false
+ })
+ },
+
+ _cloudDataPostField() : string {
+ let fields = [this.field];
+ if (this.parentField.length > 0) {
+ fields.push(`${this.parentField} as parent_value`)
+ }
+ return fields.join(',')
+ },
+
+ _cloudDataTreeWhere() : string {
+ let result : Array = []
+ let selectedNodes = this.selectedNodes.length > 0 ? this.selectedNodes : this.selectedPaths
+ let parentField = this.parentField
+ if (parentField.length > 0) {
+ result.push(`${parentField} == null || ${parentField} == ""`)
+ }
+ if (selectedNodes.length > 0) {
+ for (var i = 0; i < selectedNodes.length - 1; i++) {
+ const parentFieldValue = selectedNodes[i].getString('value', '')
+ result.push(`${parentField} == '${parentFieldValue}'`)
+ }
+ }
+
+ let where : Array = []
+ if (this._checkIsNotNull(this.where)) {
+ where.push(`(${this.where as string})`)
+ }
+
+ if (result.length > 0) {
+ where.push(`(${result.join(' || ')})`)
+ }
+
+ return where.join(' && ')
+ },
+
+ _cloudDataNodeWhere() : string {
+ const where : Array = []
+ if (this.selectedNodes.length > 0) {
+ const value = this.selectedNodes[this.selectedNodes.length - 1].getString('value', '')
+ where.push(`${this.parentField} == '${value}'`)
+ }
+
+ let whereString = where.join(' || ')
+ if (this._checkIsNotNull(this.where)) {
+ return `(${this.where as string}) && (${whereString})`
+ }
+
+ return whereString
+ },
+
+ _getWhereByForeignKey() : string {
+ let result : Array = []
+ let whereField = this._getForeignKeyByField();
+ if (whereField.length > 0) {
+ result.push(`${whereField} == '${this.dataValue as string}'`)
+ }
+
+ if (this._checkIsNotNull(this.where)) {
+ return `(${this.where}) && (${result.join(' || ')})`
+ }
+
+ return result.join(' || ')
+ },
+
+ _getForeignKeyByField() : string {
+ const fields = this.field.split(',')
+ let whereField = ''
+ for (let i = 0; i < fields.length; i++) {
+ const items = fields[i].split('as')
+ if (items.length < 2) {
+ continue
+ }
+ if (items[1].trim() === 'value') {
+ whereField = items[0].trim()
+ break
+ }
+ }
+ return whereField
+ },
+
+ _getCommand(options ?: GetCommandOptions) : Promise {
+ let db = uniCloud.databaseForJQL()
+
+ let collection = Array.isArray(this.collection) ? db.collection(...(this.collection as Array)) : db.collection(this.collection)
+
+ let filter : UniCloudDBFilter | null = null
+ if (this.foreignKey.length > 0) {
+ filter = collection.foreignKey(this.foreignKey)
+ }
+
+ const where : any = options?.where ?? this.where
+ if (typeof where == 'string') {
+ const whereString = where as string
+ if (whereString.length > 0) {
+ filter = (filter != null) ? filter.where(where) : collection.where(where)
+ }
+ } else {
+ filter = (filter != null) ? filter.where(where) : collection.where(where)
+ }
+
+ let query : UniCloudDBQuery | null = null
+ if (this.field.length > 0) {
+ query = (filter != null) ? filter.field(this.field) : collection.field(this.field)
+ }
+ if (this.groupby.length > 0) {
+ if (query != null) {
+ query = query.groupBy(this.groupby)
+ } else if (filter != null) {
+ query = filter.groupBy(this.groupby)
+ }
+ }
+ if (this.groupField.length > 0) {
+ if (query != null) {
+ query = query.groupField(this.groupField)
+ } else if (filter != null) {
+ query = filter.groupField(this.groupField)
+ }
+ }
+ if (this.distinct == true) {
+ if (query != null) {
+ query = query.distinct(this.field)
+ } else if (filter != null) {
+ query = filter.distinct(this.field)
+ }
+ }
+ if (this.orderby.length > 0) {
+ if (query != null) {
+ query = query.orderBy(this.orderby)
+ } else if (filter != null) {
+ query = filter.orderBy(this.orderby)
+ }
+ }
+
+ const size = this.pagination.size
+ const current = this.pagination.current
+ if (query != null) {
+ query = query.skip(size * (current - 1)).limit(size)
+ } else if (filter != null) {
+ query = filter.skip(size * (current - 1)).limit(size)
+ } else {
+ query = collection.skip(size * (current - 1)).limit(size)
+ }
+
+ const getOptions = {}
+ const treeOptions = {
+ limitLevel: this.limitlevel,
+ startWith: this.startwith
+ }
+ if (this.getcount == true) {
+ getOptions['getCount'] = this.getcount
+ }
+
+ const getTree : any = options?.getTree ?? this.gettree
+ if (typeof getTree == 'string') {
+ const getTreeString = getTree as string
+ if (getTreeString.length > 0) {
+ getOptions['getTree'] = treeOptions
+ }
+ } else if (typeof getTree == 'object') {
+ getOptions['getTree'] = treeOptions
+ } else {
+ getOptions['getTree'] = getTree
+ }
+
+ const getTreePath = options?.getTreePath ?? this.gettreepath
+ if (typeof getTreePath == 'string') {
+ const getTreePathString = getTreePath as string
+ if (getTreePathString.length > 0) {
+ getOptions['getTreePath'] = getTreePath
+ }
+ } else {
+ getOptions['getTreePath'] = getTreePath
+ }
+
+ return query.get(getOptions)
+ },
+
+ _checkIsNotNull(value : any) : boolean {
+ if (typeof value == 'string') {
+ const valueString = value as string
+ return (valueString.length > 0)
+ } else if (value instanceof UTSJSONObject) {
+ return true
+ }
+ return false
+ },
+
+ _checkIsLeafNode(nodeData : UTSJSONObject) : boolean {
+ if (this.selectedIndex >= this.limitlevel) {
+ return true
+ }
+
+ if (nodeData.getBoolean('isleaf', false)) {
+ return true
+ }
+
+ return false
+ },
+
+ _checkHasChildren(nodeData : UTSJSONObject) : boolean {
+ const children = nodeData.getArray('children') ?? ([] as Array)
+ return children.length > 0
+ },
+
+ _pushSelectedNodes(nodes : Array) {
+ this.selectedNodes.push(DefaultSelectedNode)
+ this.selectedPages.push(nodes)
+ this.selectedIndex = this.selectedPages.length - 1
+ },
+
+ _trimSelectedNodes(nodeData : UTSJSONObject) {
+ this.selectedNodes.splice(this.selectedIndex)
+ this.selectedNodes.push(nodeData)
+
+ if (this.selectedPages.length > 0) {
+ this.selectedPages.splice(this.selectedIndex + 1)
+ }
+
+ const children = nodeData.getArray('children') ?? ([] as Array)
+ if (children.length > 0) {
+ this.selectedNodes.push(DefaultSelectedNode)
+ this.selectedPages.push(children)
+ }
+
+ this.selectedIndex = this.selectedPages.length - 1
+ },
+
+ _pushSelectedTreeNodes(paths : Array, nodes : Array) {
+ let children : Array = nodes
+ paths.forEach((node : UTSJSONObject) => {
+ const findNode = children.find((item : UTSJSONObject) : boolean => {
+ return (item.getString(this.mappingValueName) == node.getString(this.mappingValueName))
+ })
+ if (findNode != null) {
+ this.selectedPages.push(children)
+ this.selectedNodes.push(node)
+ children = findNode.getArray('children') ?? ([] as Array)
+ }
+ })
+ this.selectedIndex = this.selectedPages.length - 1
+ },
+
+ _extractTreePath(nodes : Array, result : Array) {
+ if (nodes.length == 0) {
+ return
+ }
+
+ const node = nodes[0]
+ result.push(node)
+
+ const children = node.getArray('children')
+ if (Array.isArray(children) && children!.length > 0) {
+ this._extractTreePath(children, result)
+ }
+ }
+ }
+})
diff --git a/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.css b/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.css
new file mode 100644
index 0000000..39fe1c3
--- /dev/null
+++ b/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.css
@@ -0,0 +1,76 @@
+.uni-data-pickerview {
+ position: relative;
+ flex-direction: column;
+ overflow: hidden;
+}
+
+.loading-cover {
+ position: absolute;
+ left: 0;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ align-items: center;
+ justify-content: center;
+ background-color: rgba(150, 150, 150, .1);
+}
+
+.error {
+ background-color: #fff;
+ padding: 15px;
+}
+
+.error-text {
+ color: #DD524D;
+}
+
+.selected-node-list {
+ flex-direction: row;
+ flex-wrap: nowrap;
+}
+
+.selected-node-item {
+ margin-left: 10px;
+ margin-right: 10px;
+ padding: 8px 10px 8px 10px;
+ border-bottom: 2px solid transparent;
+}
+
+.selected-node-item-active {
+ color: #007aff;
+ border-bottom-color: #007aff;
+}
+
+.list-view {
+ flex: 1;
+}
+
+.list-item {
+ flex-direction: row;
+ justify-content: space-between;
+ padding: 12px 15px;
+ border-bottom: 1px solid #f0f0f0;
+}
+
+.item-text {
+ color: #333333;
+}
+
+.item-text-disabled {
+ opacity: .5;
+}
+
+.item-text-overflow {
+ overflow: hidden;
+}
+
+.check {
+ margin-right: 5px;
+ border: 2px solid #007aff;
+ border-left: 0;
+ border-top: 0;
+ height: 12px;
+ width: 6px;
+ transform-origin: center;
+ transform: rotate(45deg);
+}
diff --git a/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.uvue b/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.uvue
new file mode 100644
index 0000000..f4780f3
--- /dev/null
+++ b/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.uvue
@@ -0,0 +1,69 @@
+
+
+
+ {{error!.errMsg}}
+
+
+
+
+
+ {{item[mappingTextName]}}
+
+
+
+
+
+
+ {{item[mappingTextName]}}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.vue b/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.vue
new file mode 100644
index 0000000..6ebced9
--- /dev/null
+++ b/uni_modules/uni-data-picker/components/uni-data-pickerview/uni-data-pickerview.vue
@@ -0,0 +1,323 @@
+
+
+
+
+
+ {{item.text || ''}}
+
+
+
+
+
+
+ {{item[map.text]}}
+
+
+
+
+
+
+
+
+ {{errorMessage}}
+
+
+
+
+
+
+
+
diff --git a/uni_modules/uni-data-picker/package.json b/uni_modules/uni-data-picker/package.json
new file mode 100644
index 0000000..a508162
--- /dev/null
+++ b/uni_modules/uni-data-picker/package.json
@@ -0,0 +1,91 @@
+{
+ "id": "uni-data-picker",
+ "displayName": "uni-data-picker 数据驱动的picker选择器",
+ "version": "2.0.0",
+ "description": "单列、多列级联选择器,常用于省市区城市选择、公司部门选择、多级分类等场景",
+ "keywords": [
+ "uni-ui",
+ "uniui",
+ "picker",
+ "级联",
+ "省市区",
+ ""
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+"dcloudext": {
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "无",
+ "data": "无",
+ "permissions": "无"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+ "type": "component-vue"
+ },
+ "uni_modules": {
+ "dependencies": [
+ "uni-load-more",
+ "uni-icons",
+ "uni-scss"
+ ],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y",
+ "app-uvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "微信浏览器(Android)": "y",
+ "QQ浏览器(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "小程序": {
+ "微信": "y",
+ "阿里": "y",
+ "百度": "y",
+ "字节跳动": "y",
+ "QQ": "y",
+ "京东": "u"
+ },
+ "快应用": {
+ "华为": "u",
+ "联盟": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
diff --git a/uni_modules/uni-data-picker/readme.md b/uni_modules/uni-data-picker/readme.md
new file mode 100644
index 0000000..19dd0e8
--- /dev/null
+++ b/uni_modules/uni-data-picker/readme.md
@@ -0,0 +1,22 @@
+## DataPicker 级联选择
+> **组件名:uni-data-picker**
+> 代码块: `uDataPicker`
+> 关联组件:`uni-data-pickerview`、`uni-load-more`。
+
+
+`` 是一个选择类[datacom组件](https://uniapp.dcloud.net.cn/component/datacom)。
+
+支持单列、和多列级联选择。列数没有限制,如果屏幕显示不全,顶部tab区域会左右滚动。
+
+候选数据支持一次性加载完毕,也支持懒加载,比如示例图中,选择了“北京”后,动态加载北京的区县数据。
+
+`` 组件尤其适用于地址选择、分类选择等选择类。
+
+`` 支持本地数据、云端静态数据(json),uniCloud云数据库数据。
+
+`` 可以通过JQL直连uniCloud云数据库,配套[DB Schema](https://uniapp.dcloud.net.cn/uniCloud/schema),可在schema2code中自动生成前端页面,还支持服务器端校验。
+
+在uniCloud数据表中新建表“uni-id-address”和“opendb-city-china”,这2个表的schema自带foreignKey关联。在“uni-id-address”表的表结构页面使用schema2code生成前端页面,会自动生成地址管理的维护页面,自动从“opendb-city-china”表包含的中国所有省市区信息里选择地址。
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-data-picker)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839
\ No newline at end of file
diff --git a/uni_modules/uni-forms/changelog.md b/uni_modules/uni-forms/changelog.md
new file mode 100644
index 0000000..3d998bc
--- /dev/null
+++ b/uni_modules/uni-forms/changelog.md
@@ -0,0 +1,94 @@
+## 1.4.10(2023-11-03)
+- 优化 labelWidth 描述错误
+## 1.4.9(2023-02-10)
+- 修复 required 参数无法动态绑定
+## 1.4.8(2022-08-23)
+- 优化 根据 rules 自动添加 required 的问题
+## 1.4.7(2022-08-22)
+- 修复 item 未设置 require 属性,rules 设置 require 后,星号也显示的 bug,详见:[https://ask.dcloud.net.cn/question/151540](https://ask.dcloud.net.cn/question/151540)
+## 1.4.6(2022-07-13)
+- 修复 model 需要校验的值没有声明对应字段时,导致第一次不触发校验的bug
+## 1.4.5(2022-07-05)
+- 新增 更多表单示例
+- 优化 子表单组件过期提示的问题
+- 优化 子表单组件uni-datetime-picker、uni-data-select、uni-data-picker的显示样式
+## 1.4.4(2022-07-04)
+- 更新 删除组件日志
+## 1.4.3(2022-07-04)
+- 修复 由 1.4.0 引发的 label 插槽不生效的bug
+## 1.4.2(2022-07-04)
+- 修复 子组件找不到 setValue 报错的bug
+## 1.4.1(2022-07-04)
+- 修复 uni-data-picker 在 uni-forms-item 中报错的bug
+- 修复 uni-data-picker 在 uni-forms-item 中宽度不正确的bug
+## 1.4.0(2022-06-30)
+- 【重要】组件逻辑重构,部分用法用旧版本不兼容,请注意兼容问题
+- 【重要】组件使用 Provide/Inject 方式注入依赖,提供了自定义表单组件调用 uni-forms 校验表单的能力
+- 新增 model 属性,等同于原 value/modelValue 属性,旧属性即将废弃
+- 新增 validateTrigger 属性的 blur 值,仅 uni-easyinput 生效
+- 新增 onFieldChange 方法,可以对子表单进行校验,可替代binddata方法
+- 新增 子表单的 setRules 方法,配合自定义校验函数使用
+- 新增 uni-forms-item 的 setRules 方法,配置动态表单使用可动态更新校验规则
+- 优化 动态表单校验方式,废弃拼接name的方式
+## 1.3.3(2022-06-22)
+- 修复 表单校验顺序无序问题
+## 1.3.2(2021-12-09)
+-
+## 1.3.1(2021-11-19)
+- 修复 label 插槽不生效的bug
+## 1.3.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-forms](https://uniapp.dcloud.io/component/uniui/uni-forms)
+## 1.2.7(2021-08-13)
+- 修复 没有添加校验规则的字段依然报错的Bug
+## 1.2.6(2021-08-11)
+- 修复 重置表单错误信息无法清除的问题
+## 1.2.5(2021-08-11)
+- 优化 组件文档
+## 1.2.4(2021-08-11)
+- 修复 表单验证只生效一次的问题
+## 1.2.3(2021-07-30)
+- 优化 vue3下事件警告的问题
+## 1.2.2(2021-07-26)
+- 修复 vue2 下条件编译导致destroyed生命周期失效的Bug
+- 修复 1.2.1 引起的示例在小程序平台报错的Bug
+## 1.2.1(2021-07-22)
+- 修复 动态校验表单,默认值为空的情况下校验失效的Bug
+- 修复 不指定name属性时,运行报错的Bug
+- 优化 label默认宽度从65调整至70,使required为true且四字时不换行
+- 优化 组件示例,新增动态校验示例代码
+- 优化 组件文档,使用方式更清晰
+## 1.2.0(2021-07-13)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.1.2(2021-06-25)
+- 修复 pattern 属性在微信小程序平台无效的问题
+## 1.1.1(2021-06-22)
+- 修复 validate-trigger属性为submit且err-show-type属性为toast时不能弹出的Bug
+## 1.1.0(2021-06-22)
+- 修复 只写setRules方法而导致校验不生效的Bug
+- 修复 由上个办法引发的错误提示文字错位的Bug
+## 1.0.48(2021-06-21)
+- 修复 不设置 label 属性 ,无法设置label插槽的问题
+## 1.0.47(2021-06-21)
+- 修复 不设置label属性,label-width属性不生效的bug
+- 修复 setRules 方法与rules属性冲突的问题
+## 1.0.46(2021-06-04)
+- 修复 动态删减数据导致报错的问题
+## 1.0.45(2021-06-04)
+- 新增 modelValue 属性 ,value 即将废弃
+## 1.0.44(2021-06-02)
+- 新增 uni-forms-item 可以设置单独的 rules
+- 新增 validate 事件增加 keepitem 参数,可以选择那些字段不过滤
+- 优化 submit 事件重命名为 validate
+## 1.0.43(2021-05-12)
+- 新增 组件示例地址
+## 1.0.42(2021-04-30)
+- 修复 自定义检验器失效的问题
+## 1.0.41(2021-03-05)
+- 更新 校验器
+- 修复 表单规则设置类型为 number 的情况下,值为0校验失败的Bug
+## 1.0.40(2021-03-04)
+- 修复 动态显示uni-forms-item的情况下,submit 方法获取值错误的Bug
+## 1.0.39(2021-02-05)
+- 调整为uni_modules目录规范
+- 修复 校验器传入 int 等类型 ,返回String类型的Bug
diff --git a/uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue b/uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue
new file mode 100644
index 0000000..0aef9cc
--- /dev/null
+++ b/uni_modules/uni-forms/components/uni-forms-item/uni-forms-item.vue
@@ -0,0 +1,627 @@
+
+
+
+
+ *
+ {{label}}
+
+
+
+
+
+
+ {{msg}}
+
+
+
+
+
+
+
+
+
+ {{msg}}
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/uni-forms/components/uni-forms/uni-forms.vue b/uni_modules/uni-forms/components/uni-forms/uni-forms.vue
new file mode 100644
index 0000000..9bb9ae7
--- /dev/null
+++ b/uni_modules/uni-forms/components/uni-forms/uni-forms.vue
@@ -0,0 +1,397 @@
+
+
+
+
+
+
+
+
+
diff --git a/uni_modules/uni-forms/components/uni-forms/utils.js b/uni_modules/uni-forms/components/uni-forms/utils.js
new file mode 100644
index 0000000..6da2421
--- /dev/null
+++ b/uni_modules/uni-forms/components/uni-forms/utils.js
@@ -0,0 +1,293 @@
+/**
+ * 简单处理对象拷贝
+ * @param {Obejct} 被拷贝对象
+ * @@return {Object} 拷贝对象
+ */
+export const deepCopy = (val) => {
+ return JSON.parse(JSON.stringify(val))
+}
+/**
+ * 过滤数字类型
+ * @param {String} format 数字类型
+ * @@return {Boolean} 返回是否为数字类型
+ */
+export const typeFilter = (format) => {
+ return format === 'int' || format === 'double' || format === 'number' || format === 'timestamp';
+}
+
+/**
+ * 把 value 转换成指定的类型,用于处理初始值,原因是初始值需要入库不能为 undefined
+ * @param {String} key 字段名
+ * @param {any} value 字段值
+ * @param {Object} rules 表单校验规则
+ */
+export const getValue = (key, value, rules) => {
+ const isRuleNumType = rules.find(val => val.format && typeFilter(val.format));
+ const isRuleBoolType = rules.find(val => (val.format && val.format === 'boolean') || val.format === 'bool');
+ // 输入类型为 number
+ if (!!isRuleNumType) {
+ if (!value && value !== 0) {
+ value = null
+ } else {
+ value = isNumber(Number(value)) ? Number(value) : value
+ }
+ }
+
+ // 输入类型为 boolean
+ if (!!isRuleBoolType) {
+ value = isBoolean(value) ? value : false
+ }
+
+ return value;
+}
+
+/**
+ * 获取表单数据
+ * @param {String|Array} name 真实名称,需要使用 realName 获取
+ * @param {Object} data 原始数据
+ * @param {any} value 需要设置的值
+ */
+export const setDataValue = (field, formdata, value) => {
+ formdata[field] = value
+ return value || ''
+}
+
+/**
+ * 获取表单数据
+ * @param {String|Array} field 真实名称,需要使用 realName 获取
+ * @param {Object} data 原始数据
+ */
+export const getDataValue = (field, data) => {
+ return objGet(data, field)
+}
+
+/**
+ * 获取表单类型
+ * @param {String|Array} field 真实名称,需要使用 realName 获取
+ */
+export const getDataValueType = (field, data) => {
+ const value = getDataValue(field, data)
+ return {
+ type: type(value),
+ value
+ }
+}
+
+/**
+ * 获取表单可用的真实name
+ * @param {String|Array} name 表单name
+ * @@return {String} 表单可用的真实name
+ */
+export const realName = (name, data = {}) => {
+ const base_name = _basePath(name)
+ if (typeof base_name === 'object' && Array.isArray(base_name) && base_name.length > 1) {
+ const realname = base_name.reduce((a, b) => a += `#${b}`, '_formdata_')
+ return realname
+ }
+ return base_name[0] || name
+}
+
+/**
+ * 判断是否表单可用的真实name
+ * @param {String|Array} name 表单name
+ * @@return {String} 表单可用的真实name
+ */
+export const isRealName = (name) => {
+ const reg = /^_formdata_#*/
+ return reg.test(name)
+}
+
+/**
+ * 获取表单数据的原始格式
+ * @@return {Object|Array} object 需要解析的数据
+ */
+export const rawData = (object = {}, name) => {
+ let newData = JSON.parse(JSON.stringify(object))
+ let formData = {}
+ for(let i in newData){
+ let path = name2arr(i)
+ objSet(formData,path,newData[i])
+ }
+ return formData
+}
+
+/**
+ * 真实name还原为 array
+ * @param {*} name
+ */
+export const name2arr = (name) => {
+ let field = name.replace('_formdata_#', '')
+ field = field.split('#').map(v => (isNumber(v) ? Number(v) : v))
+ return field
+}
+
+/**
+ * 对象中设置值
+ * @param {Object|Array} object 源数据
+ * @param {String| Array} path 'a.b.c' 或 ['a',0,'b','c']
+ * @param {String} value 需要设置的值
+ */
+export const objSet = (object, path, value) => {
+ if (typeof object !== 'object') return object;
+ _basePath(path).reduce((o, k, i, _) => {
+ if (i === _.length - 1) {
+ // 若遍历结束直接赋值
+ o[k] = value
+ return null
+ } else if (k in o) {
+ // 若存在对应路径,则返回找到的对象,进行下一次遍历
+ return o[k]
+ } else {
+ // 若不存在对应路径,则创建对应对象,若下一路径是数字,新对象赋值为空数组,否则赋值为空对象
+ o[k] = /^[0-9]{1,}$/.test(_[i + 1]) ? [] : {}
+ return o[k]
+ }
+ }, object)
+ // 返回object
+ return object;
+}
+
+// 处理 path, path有三种形式:'a[0].b.c'、'a.0.b.c' 和 ['a','0','b','c'],需要统一处理成数组,便于后续使用
+function _basePath(path) {
+ // 若是数组,则直接返回
+ if (Array.isArray(path)) return path
+ // 若有 '[',']',则替换成将 '[' 替换成 '.',去掉 ']'
+ return path.replace(/\[/g, '.').replace(/\]/g, '').split('.')
+}
+
+/**
+ * 从对象中获取值
+ * @param {Object|Array} object 源数据
+ * @param {String| Array} path 'a.b.c' 或 ['a',0,'b','c']
+ * @param {String} defaultVal 如果无法从调用链中获取值的默认值
+ */
+export const objGet = (object, path, defaultVal = 'undefined') => {
+ // 先将path处理成统一格式
+ let newPath = _basePath(path)
+ // 递归处理,返回最后结果
+ let val = newPath.reduce((o, k) => {
+ return (o || {})[k]
+ }, object);
+ return !val || val !== undefined ? val : defaultVal
+}
+
+
+/**
+ * 是否为 number 类型
+ * @param {any} num 需要判断的值
+ * @return {Boolean} 是否为 number
+ */
+export const isNumber = (num) => {
+ return !isNaN(Number(num))
+}
+
+/**
+ * 是否为 boolean 类型
+ * @param {any} bool 需要判断的值
+ * @return {Boolean} 是否为 boolean
+ */
+export const isBoolean = (bool) => {
+ return (typeof bool === 'boolean')
+}
+/**
+ * 是否有必填字段
+ * @param {Object} rules 规则
+ * @return {Boolean} 是否有必填字段
+ */
+export const isRequiredField = (rules) => {
+ let isNoField = false;
+ for (let i = 0; i < rules.length; i++) {
+ const ruleData = rules[i];
+ if (ruleData.required) {
+ isNoField = true;
+ break;
+ }
+ }
+ return isNoField;
+}
+
+
+/**
+ * 获取数据类型
+ * @param {Any} obj 需要获取数据类型的值
+ */
+export const type = (obj) => {
+ var class2type = {};
+
+ // 生成class2type映射
+ "Boolean Number String Function Array Date RegExp Object Error".split(" ").map(function(item, index) {
+ class2type["[object " + item + "]"] = item.toLowerCase();
+ })
+ if (obj == null) {
+ return obj + "";
+ }
+ return typeof obj === "object" || typeof obj === "function" ?
+ class2type[Object.prototype.toString.call(obj)] || "object" :
+ typeof obj;
+}
+
+/**
+ * 判断两个值是否相等
+ * @param {any} a 值
+ * @param {any} b 值
+ * @return {Boolean} 是否相等
+ */
+export const isEqual = (a, b) => {
+ //如果a和b本来就全等
+ if (a === b) {
+ //判断是否为0和-0
+ return a !== 0 || 1 / a === 1 / b;
+ }
+ //判断是否为null和undefined
+ if (a == null || b == null) {
+ return a === b;
+ }
+ //接下来判断a和b的数据类型
+ var classNameA = toString.call(a),
+ classNameB = toString.call(b);
+ //如果数据类型不相等,则返回false
+ if (classNameA !== classNameB) {
+ return false;
+ }
+ //如果数据类型相等,再根据不同数据类型分别判断
+ switch (classNameA) {
+ case '[object RegExp]':
+ case '[object String]':
+ //进行字符串转换比较
+ return '' + a === '' + b;
+ case '[object Number]':
+ //进行数字转换比较,判断是否为NaN
+ if (+a !== +a) {
+ return +b !== +b;
+ }
+ //判断是否为0或-0
+ return +a === 0 ? 1 / +a === 1 / b : +a === +b;
+ case '[object Date]':
+ case '[object Boolean]':
+ return +a === +b;
+ }
+ //如果是对象类型
+ if (classNameA == '[object Object]') {
+ //获取a和b的属性长度
+ var propsA = Object.getOwnPropertyNames(a),
+ propsB = Object.getOwnPropertyNames(b);
+ if (propsA.length != propsB.length) {
+ return false;
+ }
+ for (var i = 0; i < propsA.length; i++) {
+ var propName = propsA[i];
+ //如果对应属性对应值不相等,则返回false
+ if (a[propName] !== b[propName]) {
+ return false;
+ }
+ }
+ return true;
+ }
+ //如果是数组类型
+ if (classNameA == '[object Array]') {
+ if (a.toString() == b.toString()) {
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/uni_modules/uni-forms/components/uni-forms/validate.js b/uni_modules/uni-forms/components/uni-forms/validate.js
new file mode 100644
index 0000000..1834c6c
--- /dev/null
+++ b/uni_modules/uni-forms/components/uni-forms/validate.js
@@ -0,0 +1,486 @@
+var pattern = {
+ email: /^\S+?@\S+?\.\S+?$/,
+ idcard: /^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/,
+ url: new RegExp(
+ "^(?!mailto:)(?:(?:http|https|ftp)://|//)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-*)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-*)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?$",
+ 'i')
+};
+
+const FORMAT_MAPPING = {
+ "int": 'integer',
+ "bool": 'boolean',
+ "double": 'number',
+ "long": 'number',
+ "password": 'string'
+ // "fileurls": 'array'
+}
+
+function formatMessage(args, resources = '') {
+ var defaultMessage = ['label']
+ defaultMessage.forEach((item) => {
+ if (args[item] === undefined) {
+ args[item] = ''
+ }
+ })
+
+ let str = resources
+ for (let key in args) {
+ let reg = new RegExp('{' + key + '}')
+ str = str.replace(reg, args[key])
+ }
+ return str
+}
+
+function isEmptyValue(value, type) {
+ if (value === undefined || value === null) {
+ return true;
+ }
+
+ if (typeof value === 'string' && !value) {
+ return true;
+ }
+
+ if (Array.isArray(value) && !value.length) {
+ return true;
+ }
+
+ if (type === 'object' && !Object.keys(value).length) {
+ return true;
+ }
+
+ return false;
+}
+
+const types = {
+ integer(value) {
+ return types.number(value) && parseInt(value, 10) === value;
+ },
+ string(value) {
+ return typeof value === 'string';
+ },
+ number(value) {
+ if (isNaN(value)) {
+ return false;
+ }
+ return typeof value === 'number';
+ },
+ "boolean": function(value) {
+ return typeof value === 'boolean';
+ },
+ "float": function(value) {
+ return types.number(value) && !types.integer(value);
+ },
+ array(value) {
+ return Array.isArray(value);
+ },
+ object(value) {
+ return typeof value === 'object' && !types.array(value);
+ },
+ date(value) {
+ return value instanceof Date;
+ },
+ timestamp(value) {
+ if (!this.integer(value) || Math.abs(value).toString().length > 16) {
+ return false
+ }
+ return true;
+ },
+ file(value) {
+ return typeof value.url === 'string';
+ },
+ email(value) {
+ return typeof value === 'string' && !!value.match(pattern.email) && value.length < 255;
+ },
+ url(value) {
+ return typeof value === 'string' && !!value.match(pattern.url);
+ },
+ pattern(reg, value) {
+ try {
+ return new RegExp(reg).test(value);
+ } catch (e) {
+ return false;
+ }
+ },
+ method(value) {
+ return typeof value === 'function';
+ },
+ idcard(value) {
+ return typeof value === 'string' && !!value.match(pattern.idcard);
+ },
+ 'url-https'(value) {
+ return this.url(value) && value.startsWith('https://');
+ },
+ 'url-scheme'(value) {
+ return value.startsWith('://');
+ },
+ 'url-web'(value) {
+ return false;
+ }
+}
+
+class RuleValidator {
+
+ constructor(message) {
+ this._message = message
+ }
+
+ async validateRule(fieldKey, fieldValue, value, data, allData) {
+ var result = null
+
+ let rules = fieldValue.rules
+
+ let hasRequired = rules.findIndex((item) => {
+ return item.required
+ })
+ if (hasRequired < 0) {
+ if (value === null || value === undefined) {
+ return result
+ }
+ if (typeof value === 'string' && !value.length) {
+ return result
+ }
+ }
+
+ var message = this._message
+
+ if (rules === undefined) {
+ return message['default']
+ }
+
+ for (var i = 0; i < rules.length; i++) {
+ let rule = rules[i]
+ let vt = this._getValidateType(rule)
+
+ Object.assign(rule, {
+ label: fieldValue.label || `["${fieldKey}"]`
+ })
+
+ if (RuleValidatorHelper[vt]) {
+ result = RuleValidatorHelper[vt](rule, value, message)
+ if (result != null) {
+ break
+ }
+ }
+
+ if (rule.validateExpr) {
+ let now = Date.now()
+ let resultExpr = rule.validateExpr(value, allData, now)
+ if (resultExpr === false) {
+ result = this._getMessage(rule, rule.errorMessage || this._message['default'])
+ break
+ }
+ }
+
+ if (rule.validateFunction) {
+ result = await this.validateFunction(rule, value, data, allData, vt)
+ if (result !== null) {
+ break
+ }
+ }
+ }
+
+ if (result !== null) {
+ result = message.TAG + result
+ }
+
+ return result
+ }
+
+ async validateFunction(rule, value, data, allData, vt) {
+ let result = null
+ try {
+ let callbackMessage = null
+ const res = await rule.validateFunction(rule, value, allData || data, (message) => {
+ callbackMessage = message
+ })
+ if (callbackMessage || (typeof res === 'string' && res) || res === false) {
+ result = this._getMessage(rule, callbackMessage || res, vt)
+ }
+ } catch (e) {
+ result = this._getMessage(rule, e.message, vt)
+ }
+ return result
+ }
+
+ _getMessage(rule, message, vt) {
+ return formatMessage(rule, message || rule.errorMessage || this._message[vt] || message['default'])
+ }
+
+ _getValidateType(rule) {
+ var result = ''
+ if (rule.required) {
+ result = 'required'
+ } else if (rule.format) {
+ result = 'format'
+ } else if (rule.arrayType) {
+ result = 'arrayTypeFormat'
+ } else if (rule.range) {
+ result = 'range'
+ } else if (rule.maximum !== undefined || rule.minimum !== undefined) {
+ result = 'rangeNumber'
+ } else if (rule.maxLength !== undefined || rule.minLength !== undefined) {
+ result = 'rangeLength'
+ } else if (rule.pattern) {
+ result = 'pattern'
+ } else if (rule.validateFunction) {
+ result = 'validateFunction'
+ }
+ return result
+ }
+}
+
+const RuleValidatorHelper = {
+ required(rule, value, message) {
+ if (rule.required && isEmptyValue(value, rule.format || typeof value)) {
+ return formatMessage(rule, rule.errorMessage || message.required);
+ }
+
+ return null
+ },
+
+ range(rule, value, message) {
+ const {
+ range,
+ errorMessage
+ } = rule;
+
+ let list = new Array(range.length);
+ for (let i = 0; i < range.length; i++) {
+ const item = range[i];
+ if (types.object(item) && item.value !== undefined) {
+ list[i] = item.value;
+ } else {
+ list[i] = item;
+ }
+ }
+
+ let result = false
+ if (Array.isArray(value)) {
+ result = (new Set(value.concat(list)).size === list.length);
+ } else {
+ if (list.indexOf(value) > -1) {
+ result = true;
+ }
+ }
+
+ if (!result) {
+ return formatMessage(rule, errorMessage || message['enum']);
+ }
+
+ return null
+ },
+
+ rangeNumber(rule, value, message) {
+ if (!types.number(value)) {
+ return formatMessage(rule, rule.errorMessage || message.pattern.mismatch);
+ }
+
+ let {
+ minimum,
+ maximum,
+ exclusiveMinimum,
+ exclusiveMaximum
+ } = rule;
+ let min = exclusiveMinimum ? value <= minimum : value < minimum;
+ let max = exclusiveMaximum ? value >= maximum : value > maximum;
+
+ if (minimum !== undefined && min) {
+ return formatMessage(rule, rule.errorMessage || message['number'][exclusiveMinimum ?
+ 'exclusiveMinimum' : 'minimum'
+ ])
+ } else if (maximum !== undefined && max) {
+ return formatMessage(rule, rule.errorMessage || message['number'][exclusiveMaximum ?
+ 'exclusiveMaximum' : 'maximum'
+ ])
+ } else if (minimum !== undefined && maximum !== undefined && (min || max)) {
+ return formatMessage(rule, rule.errorMessage || message['number'].range)
+ }
+
+ return null
+ },
+
+ rangeLength(rule, value, message) {
+ if (!types.string(value) && !types.array(value)) {
+ return formatMessage(rule, rule.errorMessage || message.pattern.mismatch);
+ }
+
+ let min = rule.minLength;
+ let max = rule.maxLength;
+ let val = value.length;
+
+ if (min !== undefined && val < min) {
+ return formatMessage(rule, rule.errorMessage || message['length'].minLength)
+ } else if (max !== undefined && val > max) {
+ return formatMessage(rule, rule.errorMessage || message['length'].maxLength)
+ } else if (min !== undefined && max !== undefined && (val < min || val > max)) {
+ return formatMessage(rule, rule.errorMessage || message['length'].range)
+ }
+
+ return null
+ },
+
+ pattern(rule, value, message) {
+ if (!types['pattern'](rule.pattern, value)) {
+ return formatMessage(rule, rule.errorMessage || message.pattern.mismatch);
+ }
+
+ return null
+ },
+
+ format(rule, value, message) {
+ var customTypes = Object.keys(types);
+ var format = FORMAT_MAPPING[rule.format] ? FORMAT_MAPPING[rule.format] : (rule.format || rule.arrayType);
+
+ if (customTypes.indexOf(format) > -1) {
+ if (!types[format](value)) {
+ return formatMessage(rule, rule.errorMessage || message.typeError);
+ }
+ }
+
+ return null
+ },
+
+ arrayTypeFormat(rule, value, message) {
+ if (!Array.isArray(value)) {
+ return formatMessage(rule, rule.errorMessage || message.typeError);
+ }
+
+ for (let i = 0; i < value.length; i++) {
+ const element = value[i];
+ let formatResult = this.format(rule, element, message)
+ if (formatResult !== null) {
+ return formatResult
+ }
+ }
+
+ return null
+ }
+}
+
+class SchemaValidator extends RuleValidator {
+
+ constructor(schema, options) {
+ super(SchemaValidator.message);
+
+ this._schema = schema
+ this._options = options || null
+ }
+
+ updateSchema(schema) {
+ this._schema = schema
+ }
+
+ async validate(data, allData) {
+ let result = this._checkFieldInSchema(data)
+ if (!result) {
+ result = await this.invokeValidate(data, false, allData)
+ }
+ return result.length ? result[0] : null
+ }
+
+ async validateAll(data, allData) {
+ let result = this._checkFieldInSchema(data)
+ if (!result) {
+ result = await this.invokeValidate(data, true, allData)
+ }
+ return result
+ }
+
+ async validateUpdate(data, allData) {
+ let result = this._checkFieldInSchema(data)
+ if (!result) {
+ result = await this.invokeValidateUpdate(data, false, allData)
+ }
+ return result.length ? result[0] : null
+ }
+
+ async invokeValidate(data, all, allData) {
+ let result = []
+ let schema = this._schema
+ for (let key in schema) {
+ let value = schema[key]
+ let errorMessage = await this.validateRule(key, value, data[key], data, allData)
+ if (errorMessage != null) {
+ result.push({
+ key,
+ errorMessage
+ })
+ if (!all) break
+ }
+ }
+ return result
+ }
+
+ async invokeValidateUpdate(data, all, allData) {
+ let result = []
+ for (let key in data) {
+ let errorMessage = await this.validateRule(key, this._schema[key], data[key], data, allData)
+ if (errorMessage != null) {
+ result.push({
+ key,
+ errorMessage
+ })
+ if (!all) break
+ }
+ }
+ return result
+ }
+
+ _checkFieldInSchema(data) {
+ var keys = Object.keys(data)
+ var keys2 = Object.keys(this._schema)
+ if (new Set(keys.concat(keys2)).size === keys2.length) {
+ return ''
+ }
+
+ var noExistFields = keys.filter((key) => {
+ return keys2.indexOf(key) < 0;
+ })
+ var errorMessage = formatMessage({
+ field: JSON.stringify(noExistFields)
+ }, SchemaValidator.message.TAG + SchemaValidator.message['defaultInvalid'])
+ return [{
+ key: 'invalid',
+ errorMessage
+ }]
+ }
+}
+
+function Message() {
+ return {
+ TAG: "",
+ default: '验证错误',
+ defaultInvalid: '提交的字段{field}在数据库中并不存在',
+ validateFunction: '验证无效',
+ required: '{label}必填',
+ 'enum': '{label}超出范围',
+ timestamp: '{label}格式无效',
+ whitespace: '{label}不能为空',
+ typeError: '{label}类型无效',
+ date: {
+ format: '{label}日期{value}格式无效',
+ parse: '{label}日期无法解析,{value}无效',
+ invalid: '{label}日期{value}无效'
+ },
+ length: {
+ minLength: '{label}长度不能少于{minLength}',
+ maxLength: '{label}长度不能超过{maxLength}',
+ range: '{label}必须介于{minLength}和{maxLength}之间'
+ },
+ number: {
+ minimum: '{label}不能小于{minimum}',
+ maximum: '{label}不能大于{maximum}',
+ exclusiveMinimum: '{label}不能小于等于{minimum}',
+ exclusiveMaximum: '{label}不能大于等于{maximum}',
+ range: '{label}必须介于{minimum}and{maximum}之间'
+ },
+ pattern: {
+ mismatch: '{label}格式不匹配'
+ }
+ };
+}
+
+
+SchemaValidator.message = new Message();
+
+export default SchemaValidator
diff --git a/uni_modules/uni-forms/package.json b/uni_modules/uni-forms/package.json
new file mode 100644
index 0000000..464b4e6
--- /dev/null
+++ b/uni_modules/uni-forms/package.json
@@ -0,0 +1,88 @@
+{
+ "id": "uni-forms",
+ "displayName": "uni-forms 表单",
+ "version": "1.4.10",
+ "description": "由输入框、选择器、单选框、多选框等控件组成,用以收集、校验、提交数据",
+ "keywords": [
+ "uni-ui",
+ "表单",
+ "校验",
+ "表单校验",
+ "表单验证"
+],
+ "repository": "https://github.com/dcloudio/uni-ui",
+ "engines": {
+ "HBuilderX": ""
+ },
+ "directories": {
+ "example": "../../temps/example_temps"
+ },
+"dcloudext": {
+ "sale": {
+ "regular": {
+ "price": "0.00"
+ },
+ "sourcecode": {
+ "price": "0.00"
+ }
+ },
+ "contact": {
+ "qq": ""
+ },
+ "declaration": {
+ "ads": "无",
+ "data": "无",
+ "permissions": "无"
+ },
+ "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+ "type": "component-vue"
+ },
+ "uni_modules": {
+ "dependencies": [
+ "uni-scss",
+ "uni-icons"
+ ],
+ "encrypt": [],
+ "platforms": {
+ "cloud": {
+ "tcb": "y",
+ "aliyun": "y"
+ },
+ "client": {
+ "App": {
+ "app-vue": "y",
+ "app-nvue": "y"
+ },
+ "H5-mobile": {
+ "Safari": "y",
+ "Android Browser": "y",
+ "微信浏览器(Android)": "y",
+ "QQ浏览器(Android)": "y"
+ },
+ "H5-pc": {
+ "Chrome": "y",
+ "IE": "y",
+ "Edge": "y",
+ "Firefox": "y",
+ "Safari": "y"
+ },
+ "小程序": {
+ "微信": "y",
+ "阿里": "y",
+ "百度": "y",
+ "字节跳动": "y",
+ "QQ": "y",
+ "京东": "u"
+ },
+ "快应用": {
+ "华为": "u",
+ "联盟": "u"
+ },
+ "Vue": {
+ "vue2": "y",
+ "vue3": "y"
+ }
+ }
+ }
+ }
+}
diff --git a/uni_modules/uni-forms/readme.md b/uni_modules/uni-forms/readme.md
new file mode 100644
index 0000000..63d5a04
--- /dev/null
+++ b/uni_modules/uni-forms/readme.md
@@ -0,0 +1,23 @@
+
+
+## Forms 表单
+
+> **组件名:uni-forms**
+> 代码块: `uForms`、`uni-forms-item`
+> 关联组件:`uni-forms-item`、`uni-easyinput`、`uni-data-checkbox`、`uni-group`。
+
+
+uni-app的内置组件已经有了 `