├── pages
└── index
│ ├── index.wxss
│ ├── index.wxml
│ ├── index.json
│ └── index.js
├── component
└── uploadImages
│ ├── index.json
│ ├── index.wxml
│ ├── index.wxss
│ └── index.js
├── README.md
├── app.wxss
├── app.json
├── utils
├── util.js
├── diff.js
└── create.js
├── project.config.json
└── app.js
/pages/index/index.wxss:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/component/uploadImages/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {}
4 | }
--------------------------------------------------------------------------------
/pages/index/index.wxml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/pages/index/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "navigationBarTitleText": "多张图片上传",
3 | "usingComponents": {
4 | "uploadImages": "/component/uploadImages/index"
5 | }
6 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | uploadImages 微信小程序上传多张图片
2 | ====================
3 | ## 使用需要填写uploadImgUrl
4 | ```
5 | showImgUrl: "", //路径拼接,一般上传返回的都是文件名
6 |
7 | uploadImgUrl:''//图片的上传的路径
8 | ```
9 |
--------------------------------------------------------------------------------
/app.wxss:
--------------------------------------------------------------------------------
1 | /**app.wxss**/
2 | .container {
3 | height: 100%;
4 | display: flex;
5 | flex-direction: column;
6 | align-items: center;
7 | justify-content: space-between;
8 | padding: 200rpx 0;
9 | box-sizing: border-box;
10 | }
11 |
--------------------------------------------------------------------------------
/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "pages":[
3 | "pages/index/index"
4 | ],
5 | "window":{
6 | "backgroundTextStyle":"light",
7 | "navigationBarBackgroundColor": "#fff",
8 | "navigationBarTitleText": "WeChat",
9 | "navigationBarTextStyle":"black"
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/pages/index/index.js:
--------------------------------------------------------------------------------
1 | // pages/weijieke/product/index.js
2 | const app = getApp();
3 | Page({
4 |
5 | /**
6 | * 页面的初始数据
7 | */
8 | data: {
9 | countPic:9,//上传图片最大数量
10 | showImgUrl: "", //路径拼接,一般上传返回的都是文件名,
11 | uploadImgUrl:''//图片的上传的路径
12 | },
13 |
14 | //监听组件事件,返回的结果
15 | myEventListener:function(e){
16 | console.log("上传的图片结果集合")
17 | console.log(e.detail.picsList)
18 | },
19 |
20 | })
--------------------------------------------------------------------------------
/utils/util.js:
--------------------------------------------------------------------------------
1 | const formatTime = date => {
2 | const year = date.getFullYear()
3 | const month = date.getMonth() + 1
4 | const day = date.getDate()
5 | const hour = date.getHours()
6 | const minute = date.getMinutes()
7 | const second = date.getSeconds()
8 |
9 | return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':')
10 | }
11 |
12 | const formatNumber = n => {
13 | n = n.toString()
14 | return n[1] ? n : '0' + n
15 | }
16 |
17 | module.exports = {
18 | formatTime: formatTime
19 | }
20 |
--------------------------------------------------------------------------------
/component/uploadImages/index.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | 长按对应的图片即可删除
14 |
15 |
--------------------------------------------------------------------------------
/project.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "description": "项目配置文件",
3 | "packOptions": {
4 | "ignore": []
5 | },
6 | "setting": {
7 | "urlCheck": false,
8 | "es6": true,
9 | "postcss": true,
10 | "minified": true,
11 | "newFeature": true
12 | },
13 | "compileType": "miniprogram",
14 | "libVersion": "2.3.0",
15 | "appid": "wx2ab3b0e447dbecf4",
16 | "projectname": "uploadImages",
17 | "debugOptions": {
18 | "hidedInDevtools": []
19 | },
20 | "isGameTourist": false,
21 | "condition": {
22 | "search": {
23 | "current": -1,
24 | "list": []
25 | },
26 | "conversation": {
27 | "current": -1,
28 | "list": []
29 | },
30 | "game": {
31 | "currentL": -1,
32 | "list": []
33 | },
34 | "miniprogram": {
35 | "current": -1,
36 | "list": []
37 | }
38 | }
39 | }
--------------------------------------------------------------------------------
/app.js:
--------------------------------------------------------------------------------
1 | //app.js
2 | App({
3 | onLaunch: function () {
4 | // 展示本地存储能力
5 | var logs = wx.getStorageSync('logs') || []
6 | logs.unshift(Date.now())
7 | wx.setStorageSync('logs', logs)
8 |
9 | // 登录
10 | wx.login({
11 | success: res => {
12 | // 发送 res.code 到后台换取 openId, sessionKey, unionId
13 | }
14 | })
15 | // 获取用户信息
16 | wx.getSetting({
17 | success: res => {
18 | if (res.authSetting['scope.userInfo']) {
19 | // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
20 | wx.getUserInfo({
21 | success: res => {
22 | // 可以将 res 发送给后台解码出 unionId
23 | this.globalData.userInfo = res.userInfo
24 |
25 | // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
26 | // 所以此处加入 callback 以防止这种情况
27 | if (this.userInfoReadyCallback) {
28 | this.userInfoReadyCallback(res)
29 | }
30 | }
31 | })
32 | }
33 | }
34 | })
35 | },
36 | globalData: {
37 | userInfo: null
38 | }
39 | })
--------------------------------------------------------------------------------
/component/uploadImages/index.wxss:
--------------------------------------------------------------------------------
1 | page {
2 | background-color: #f1f0f5;
3 | }
4 |
5 | .content {
6 | width: 100%;
7 | background-color: #fff;
8 | }
9 |
10 | .img-list {
11 | display: flex;
12 | display: -webkit-flex;
13 | flex-direction: row;
14 | justify-content: flex-start;
15 | align-items: center;
16 | flex-wrap: wrap;
17 | }
18 |
19 | .img-item {
20 | width: 30%;
21 | text-align: left;
22 | margin-right: 20rpx;
23 | margin-bottom: 10rpx;
24 | }
25 |
26 | .img-item image {
27 | width: 180rpx;
28 | height: 180rpx;
29 | }
30 |
31 | .submit-btn {
32 | width: 100%;
33 | background-color: #fff;
34 | height: 80rpx;
35 | text-align: center;
36 | line-height: 80rpx;
37 | font-size: 30rpx;
38 | position: fixed;
39 | bottom: 100rpx;
40 | }
41 |
42 | .chooseimg {
43 | background-color: #fff;
44 | }
45 |
46 | .weui-uploader__input-box {
47 | float: left;
48 | position: relative;
49 | margin-right: 9px;
50 | margin-bottom: 9px;
51 | width: 180rpx;
52 | height: 180rpx;
53 | border: 1px solid #d9d9d9;
54 | }
55 |
56 | .weui-uploader__input-box:before {
57 | width: 2px;
58 | height: 39.5px;
59 | }
60 |
61 | .weui-uploader__input-box:after, .weui-uploader__input-box:before {
62 | content: " ";
63 | position: absolute;
64 | top: 50%;
65 | left: 50%;
66 | -webkit-transform: translate(-50%, -50%);
67 | transform: translate(-50%, -50%);
68 | background-color: #d9d9d9;
69 | }
70 |
71 | .weui-uploader__input-box:after {
72 | width: 39.5px;
73 | height: 2px;
74 | }
75 |
76 | .weui-uploader__input-box:after, .weui-uploader__input-box:before {
77 | content: " ";
78 | position: absolute;
79 | top: 50%;
80 | left: 50%;
81 | -webkit-transform: translate(-50%, -50%);
82 | transform: translate(-50%, -50%);
83 | background-color: #d9d9d9;
84 | }
85 |
86 | .tips {
87 | color: #666;
88 | font-size: 24rpx;
89 | padding-bottom: 20rpx;
90 | }
91 |
92 | .img-box {
93 | width: 92%;
94 | margin: auto;
95 | padding-top: 20rpx;
96 | }
97 |
--------------------------------------------------------------------------------
/component/uploadImages/index.js:
--------------------------------------------------------------------------------
1 | // component/uploadImages/index.js
2 | Component({
3 | /**
4 | * 组件的属性列表
5 | */
6 | properties: {
7 | count: { //最多选择图片的张数,默认9张
8 | type: Number,
9 | value: 9
10 | },
11 | uploadUrl: { //图片上传的服务器路径
12 | type: String,
13 | value: ''
14 | },
15 | showUrl: { //图片的拼接路径
16 | type: String,
17 | value: ''
18 | }
19 | },
20 |
21 | /**
22 | * 组件的初始数据
23 | */
24 | data: {
25 | detailPics: [], //上传的结果图片集合
26 | },
27 |
28 | ready: function() {
29 | console.log(this.data)
30 | },
31 |
32 | /**
33 | * 组件的方法列表
34 | */
35 | methods: {
36 |
37 | /**
38 | * 上传详细图片
39 | */
40 | uploadDetailImage: function(e) { //这里是选取图片的方法
41 | var that = this;
42 | var pics = [];
43 | var detailPics = that.data.detailPics;
44 | if (detailPics.length >= that.data.count) {
45 | wx.showToast({
46 | title: '最多选择' + that.data.count + '张!',
47 | })
48 | return;
49 | }
50 | wx.chooseImage({
51 | count: that.data.count, // 最多可以选择的图片张数,默认9
52 | sizeType: ['original', 'compressed'], // original 原图,compressed 压缩图,默认二者都有
53 | sourceType: ['album', 'camera'], // album 从相册选图,camera 使用相机,默认二者都有
54 | success: function(res) {
55 | var imgs = res.tempFilePaths;
56 | for (var i = 0; i < imgs.length; i++) {
57 | pics.push(imgs[i])
58 | }
59 | that.uploadimg({
60 | url: that.data.uploadUrl, //这里是你图片上传的接口
61 | path: pics, //这里是选取的图片的地址数组
62 | });
63 | },
64 | })
65 |
66 | },
67 | //多张图片上传
68 | uploadimg: function(data) {
69 | wx.showLoading({
70 | title: '上传中...',
71 | mask: true,
72 | })
73 | var that = this,
74 | i = data.i ? data.i : 0,
75 | success = data.success ? data.success : 0,
76 | fail = data.fail ? data.fail : 0;
77 | wx.uploadFile({
78 | url: data.url,
79 | filePath: data.path[i],
80 | name: 'fileData',
81 | formData: null,
82 | success: (resp) => {
83 | wx.hideLoading();
84 | success++;
85 | var str = resp.data //返回的结果,可能不同项目结果不一样
86 | var pic = JSON.parse(str);
87 | var pic_name = that.data.showUrl + pic.Data;
88 | var detailPics = that.data.detailPics;
89 | detailPics.push(pic_name)
90 | that.setData({
91 | detailPics: detailPics
92 | })
93 | },
94 | fail: (res) => {
95 | fail++;
96 | console.log('fail:' + i + "fail:" + fail);
97 | },
98 | complete: () => {
99 | i++;
100 | if (i == data.path.length) { //当图片传完时,停止调用
101 | console.log('执行完毕');
102 | console.log('成功:' + success + " 失败:" + fail);
103 | var myEventDetail = {
104 | picsList: that.data.detailPics
105 | } // detail对象,提供给事件监听函数
106 | var myEventOption = {} // 触发事件的选项
107 | that.triggerEvent('myevent', myEventDetail, myEventOption)
108 | } else { //若图片还没有传完,则继续调用函数
109 | data.i = i;
110 | data.success = success;
111 | data.fail = fail;
112 | that.uploadimg(data);
113 | }
114 | }
115 | });
116 | },
117 |
118 | }
119 | })
--------------------------------------------------------------------------------
/utils/diff.js:
--------------------------------------------------------------------------------
1 | const ARRAYTYPE = '[object Array]'
2 | const OBJECTTYPE = '[object Object]'
3 | const FUNCTIONTYPE = '[object Function]'
4 |
5 | export default function diff(current, pre) {
6 | const result = {}
7 | syncKeys(current, pre)
8 | _diff(current, pre, '', result)
9 | return result
10 | }
11 |
12 | function syncKeys(current, pre) {
13 | if (current === pre) return
14 | const rootCurrentType = type(current)
15 | const rootPreType = type(pre)
16 | if (rootCurrentType == OBJECTTYPE && rootPreType == OBJECTTYPE) {
17 | if(Object.keys(current).length >= Object.keys(pre).length){
18 | for (let key in pre) {
19 | const currentValue = current[key]
20 | if (currentValue === undefined) {
21 | current[key] = null
22 | } else {
23 | syncKeys(currentValue, pre[key])
24 | }
25 | }
26 | }
27 | } else if (rootCurrentType == ARRAYTYPE && rootPreType == ARRAYTYPE) {
28 | if (current.length >= pre.length) {
29 | pre.forEach((item, index) => {
30 | syncKeys(current[index], item)
31 | })
32 | }
33 | }
34 | }
35 |
36 | function _diff(current, pre, path, result) {
37 | if (current === pre) return
38 | const rootCurrentType = type(current)
39 | const rootPreType = type(pre)
40 | if (rootCurrentType == OBJECTTYPE) {
41 | if (rootPreType != OBJECTTYPE || Object.keys(current).length < Object.keys(pre).length) {
42 | setResult(result, path, current)
43 | } else {
44 | for (let key in current) {
45 | const currentValue = current[key]
46 | const preValue = pre[key]
47 | const currentType = type(currentValue)
48 | const preType = type(preValue)
49 | if (currentType != ARRAYTYPE && currentType != OBJECTTYPE) {
50 | if (currentValue != pre[key]) {
51 | setResult(result, (path == '' ? '' : path + ".") + key, currentValue)
52 | }
53 | } else if (currentType == ARRAYTYPE) {
54 | if (preType != ARRAYTYPE) {
55 | setResult(result, (path == '' ? '' : path + ".") + key, currentValue)
56 | } else {
57 | if (currentValue.length < preValue.length) {
58 | setResult(result, (path == '' ? '' : path + ".") + key, currentValue)
59 | } else {
60 | currentValue.forEach((item, index) => {
61 | _diff(item, preValue[index], (path == '' ? '' : path + ".") + key + '[' + index + ']', result)
62 | })
63 | }
64 | }
65 | } else if (currentType == OBJECTTYPE) {
66 | if (preType != OBJECTTYPE || Object.keys(currentValue).length < Object.keys(preValue).length) {
67 | setResult(result, (path == '' ? '' : path + ".") + key, currentValue)
68 | } else {
69 | for (let subKey in currentValue) {
70 | _diff(currentValue[subKey], preValue[subKey], (path == '' ? '' : path + ".") + key + '.' + subKey, result)
71 | }
72 | }
73 | }
74 | }
75 | }
76 | } else if (rootCurrentType == ARRAYTYPE) {
77 | if (rootPreType != ARRAYTYPE) {
78 | setResult(result, path, current)
79 | } else {
80 | if (current.length < pre.length) {
81 | setResult(result, path, current)
82 | } else {
83 | current.forEach((item, index) => {
84 | _diff(item, pre[index], path + '[' + index + ']', result)
85 | })
86 | }
87 | }
88 | } else {
89 | setResult(result, path, current)
90 | }
91 | }
92 |
93 | function setResult(result, k, v) {
94 | const t = type(v)
95 | if (t != FUNCTIONTYPE) {
96 | //if (t != OBJECTTYPE && t != ARRAYTYPE) {
97 | result[k] = v
98 | // } else {
99 | // result[k] = JSON.parse(JSON.stringify(v))
100 | // }
101 | }
102 | }
103 |
104 | function type(obj) {
105 | return Object.prototype.toString.call(obj)
106 | }
--------------------------------------------------------------------------------
/utils/create.js:
--------------------------------------------------------------------------------
1 | import diff from './diff'
2 |
3 | let originData = null
4 | let globalStore = null
5 | let fnMapping = {}
6 |
7 | const ARRAYTYPE = '[object Array]'
8 | const OBJECTTYPE = '[object Object]'
9 | const FUNCTIONTYPE = '[object Function]'
10 |
11 | export default function create(store, option) {
12 | let updatePath = null
13 | if (arguments.length === 2) {
14 | if (option.data && Object.keys(option.data).length > 0) {
15 | updatePath = getUpdatePath(option.data)
16 | syncValues(store.data, option.data)
17 | }
18 | if (!originData) {
19 | originData = JSON.parse(JSON.stringify(store.data))
20 | globalStore = store
21 | store.instances = {}
22 | store.update = update
23 | store.push = push
24 | store.pull = pull
25 | store.add = add
26 | store.remove = remove
27 | store.originData = originData
28 | store.env && initCloud(store.env)
29 | extendStoreMethod(store)
30 | }
31 | getApp().globalData && (getApp().globalData.store = store)
32 | option.data = store.data
33 | const onLoad = option.onLoad
34 | walk(store.data)
35 | option.onLoad = function (e) {
36 | this.store = store
37 | this._updatePath = updatePath
38 | rewriteUpdate(this)
39 | store.instances[this.route] = []
40 | store.instances[this.route].push(this)
41 | onLoad && onLoad.call(this, e)
42 | }
43 | Page(option)
44 | } else {
45 | const ready = store.ready
46 | const pure = store.pure
47 | store.ready = function () {
48 | if (pure) {
49 | this.store = { data: store.data || {} }
50 | this.store.originData = store.data ? JSON.parse(JSON.stringify(store.data)) : {}
51 | walk(store.data || {})
52 | rewritePureUpdate(this)
53 | } else {
54 | this.page = getCurrentPages()[getCurrentPages().length - 1]
55 | this.store = this.page.store
56 | this._updatePath = getUpdatePath(store.data)
57 | syncValues(this.store.data, store.data)
58 | walk(store.data || {})
59 | this.setData.call(this, this.store.data)
60 | rewriteUpdate(this)
61 | this.store.instances[this.page.route].push(this)
62 | }
63 | ready && ready.call(this)
64 | }
65 | Component(store)
66 | }
67 | }
68 |
69 | function syncValues(from, to){
70 | Object.keys(to).forEach(key=>{
71 | to[key] = from[key]
72 | })
73 | }
74 |
75 |
76 | function getUpdatePath(data) {
77 | const result = {}
78 | dataToPath(data, result)
79 | return result
80 | }
81 |
82 | function dataToPath(data, result) {
83 | Object.keys(data).forEach(key => {
84 | result[key] = true
85 | const type = Object.prototype.toString.call(data[key])
86 | if (type === OBJECTTYPE) {
87 | _objToPath(data[key], key, result)
88 | } else if (type === ARRAYTYPE) {
89 | _arrayToPath(data[key], key, result)
90 | }
91 | })
92 | }
93 |
94 | function _objToPath(data, path, result) {
95 | Object.keys(data).forEach(key => {
96 | result[path + '.' + key] = true
97 | delete result[path]
98 | const type = Object.prototype.toString.call(data[key])
99 | if (type === OBJECTTYPE) {
100 | _objToPath(data[key], path + '.' + key, result)
101 | } else if (type === ARRAYTYPE) {
102 | _arrayToPath(data[key], path + '.' + key, result)
103 | }
104 | })
105 | }
106 |
107 | function _arrayToPath(data, path, result) {
108 | data.forEach((item, index) => {
109 | result[path + '[' + index + ']'] = true
110 | delete result[path]
111 | const type = Object.prototype.toString.call(item)
112 | if (type === OBJECTTYPE) {
113 | _objToPath(item, path + '[' + index + ']', result)
114 | } else if (type === ARRAYTYPE) {
115 | _arrayToPath(item, path + '[' + index + ']', result)
116 | }
117 | })
118 | }
119 |
120 | function rewritePureUpdate(ctx) {
121 | ctx.update = function (patch) {
122 | const store = this.store
123 | //defineFnProp(store.data)
124 | if (patch) {
125 | for (let key in patch) {
126 | updateByPath(store.data, key, patch[key])
127 | }
128 | }
129 | let diffResult = diff(store.data, store.originData)
130 | if (Object.keys(diffResult)[0] == '') {
131 | diffResult = diffResult['']
132 | }
133 | if (Object.keys(diffResult).length > 0) {
134 | this.setData(diffResult)
135 | store.onChange && store.onChange(diffResult)
136 | for (let key in diffResult) {
137 | updateByPath(store.originData, key, typeof diffResult[key] === 'object' ? JSON.parse(JSON.stringify(diffResult[key])) : diffResult[key])
138 | }
139 | }
140 | return diffResult
141 | }
142 | }
143 |
144 | function initCloud(env) {
145 | wx.cloud.init()
146 | globalStore.db = wx.cloud.database({
147 | env: env
148 | })
149 | }
150 |
151 | function push(patch) {
152 | return new Promise(function (resolve, reject) {
153 | _push(update(patch), resolve, reject)
154 | })
155 | }
156 |
157 | function _push(diffResult, resolve) {
158 | const objs = diffToPushObj(diffResult)
159 | Object.keys(objs).forEach((path) => {
160 | const arr = path.split('-')
161 | const id = globalStore.data[arr[0]][parseInt(arr[1])]._id
162 | const obj = objs[path]
163 | if (globalStore.methods && globalStore.methods[arr[0]]) {
164 | Object.keys(globalStore.methods[arr[0]]).forEach(key => {
165 | if (obj.hasOwnProperty(key)) {
166 | delete obj[key]
167 | }
168 | })
169 | }
170 | globalStore.db.collection(arr[0]).doc(id).update({
171 | data: obj
172 | }).then((res) => {
173 | resolve(res)
174 | })
175 | })
176 | }
177 |
178 | function update(patch) {
179 | //defineFnProp(globalStore.data)
180 | if (patch) {
181 | for (let key in patch) {
182 | updateByPath(globalStore.data, key, patch[key])
183 | }
184 | }
185 | let diffResult = diff(globalStore.data, originData)
186 | if (Object.keys(diffResult)[0] == '') {
187 | diffResult = diffResult['']
188 | }
189 | const updateAll = matchGlobalData(diffResult)
190 | if (Object.keys(diffResult).length > 0) {
191 | for (let key in globalStore.instances) {
192 | globalStore.instances[key].forEach(ins => {
193 | if(updateAll || globalStore.updateAll || ins._updatePath && needUpdate(diffResult, ins._updatePath)){
194 | ins.setData.call(ins, diffResult)
195 | }
196 | })
197 | }
198 | globalStore.onChange && globalStore.onChange(diffResult)
199 | for (let key in diffResult) {
200 | updateByPath(originData, key, typeof diffResult[key] === 'object' ? JSON.parse(JSON.stringify(diffResult[key])) : diffResult[key])
201 | }
202 | }
203 | return diffResult
204 | }
205 |
206 | function matchGlobalData(diffResult) {
207 | if(!globalStore.globalData) return false
208 | for (let keyA in diffResult) {
209 | if (globalStore.globalData.indexOf(keyA) > -1) {
210 | return true
211 | }
212 | for (let i = 0, len = globalStore.globalData.length; i < len; i++) {
213 | if (includePath(keyA, globalStore.globalData[i])) {
214 | return true
215 | }
216 | }
217 | }
218 | return false
219 | }
220 |
221 | function needUpdate(diffResult, updatePath){
222 | for(let keyA in diffResult){
223 | if(updatePath[keyA]){
224 | return true
225 | }
226 | for(let keyB in updatePath){
227 | if(includePath(keyA, keyB)){
228 | return true
229 | }
230 | }
231 | }
232 | return false
233 | }
234 |
235 | function includePath(pathA, pathB){
236 | if(pathA.indexOf(pathB)===0){
237 | const next = pathA.substr(pathB.length, 1)
238 | if(next === '['||next === '.'){
239 | return true
240 | }
241 | }
242 | return false
243 | }
244 |
245 | function rewriteUpdate(ctx) {
246 | ctx.update = update
247 | }
248 |
249 | function updateByPath(origin, path, value) {
250 | const arr = path.replace(/]/g, '').replace(/\[/g, '.').split('.')
251 | let current = origin
252 | for (let i = 0, len = arr.length; i < len; i++) {
253 | if (i === len - 1) {
254 | current[arr[i]] = value
255 | } else {
256 | current = current[arr[i]]
257 | }
258 | }
259 | }
260 |
261 | function pull(cn, where) {
262 | return new Promise(function (resolve) {
263 | globalStore.db.collection(cn).where(where || {}).get().then(res => {
264 | extend(res, cn)
265 | resolve(res)
266 | })
267 | })
268 | }
269 |
270 | function extend(res, cn) {
271 | res.data.forEach(item => {
272 | const mds = globalStore.methods[cn]
273 | mds && Object.keys(mds).forEach(key => {
274 | Object.defineProperty(item, key, {
275 | enumerable: true,
276 | get: () => {
277 | return mds[key].call(item)
278 | },
279 | set: () => {
280 | //方法不能改写
281 | }
282 | })
283 | })
284 | })
285 | }
286 |
287 | function add(cn, data) {
288 | return globalStore.db.collection(cn).add({ data })
289 | }
290 |
291 | function remove(cn, id) {
292 | return globalStore.db.collection(cn).doc(id).remove()
293 | }
294 |
295 | function diffToPushObj(diffResult) {
296 | const result = {}
297 | Object.keys(diffResult).forEach(key => {
298 | diffItemToObj(key, diffResult[key], result)
299 | })
300 | return result
301 | }
302 |
303 | function diffItemToObj(path, value, result) {
304 | const arr = path.replace(/]/g, '').replace(/\[/g, '.').split('.')
305 | const obj = {}
306 | let current = null
307 | const len = arr.length
308 | for (let i = 2; i < len; i++) {
309 | if (len === 3) {
310 | obj[arr[i]] = value
311 | } else {
312 | if (i === len - 1) {
313 | current[arr[i]] = value
314 | } else {
315 | const pre = current
316 | current = {}
317 | if (i === 2) {
318 | obj[arr[i]] = current
319 | } else {
320 | pre[arr[i]] = current
321 | }
322 | }
323 | }
324 | }
325 | const key = arr[0] + '-' + arr[1]
326 | result[key] = Object.assign(result[key] || {}, obj)
327 | }
328 |
329 | function extendStoreMethod() {
330 | globalStore.method = function (path, fn) {
331 | fnMapping[path] = fn
332 | let ok = getObjByPath(path)
333 | Object.defineProperty(ok.obj, ok.key, {
334 | enumerable: true,
335 | get: () => {
336 | return fnMapping[path].call(globalStore.data)
337 | },
338 | set: () => {
339 | console.warn('Please using store.method to set method prop of data!')
340 | }
341 | })
342 | }
343 | }
344 |
345 | function getObjByPath(path) {
346 | const arr = path.replace(/]/g, '').replace(/\[/g, '.').split('.')
347 | const len = arr.length
348 | if (len > 1) {
349 | let current = globalStore.data[arr[0]]
350 | for (let i = 1; i < len - 1; i++) {
351 | current = current[arr[i]]
352 | }
353 | return { obj: current, key: arr[len - 1] }
354 | } else {
355 | return { obj: globalStore.data, key: arr[0] }
356 | }
357 | }
358 |
359 | function walk(data) {
360 | Object.keys(data).forEach(key => {
361 | const obj = data[key]
362 | const tp = type(obj)
363 | if (tp == FUNCTIONTYPE) {
364 | setProp(key, obj)
365 | } else if (tp == OBJECTTYPE) {
366 | Object.keys(obj).forEach(subKey => {
367 | _walk(obj[subKey], key + '.' + subKey)
368 | })
369 |
370 | } else if (tp == ARRAYTYPE) {
371 | obj.forEach((item, index) => {
372 | _walk(item, key + '[' + index + ']')
373 | })
374 |
375 | }
376 | })
377 | }
378 |
379 | function _walk(obj, path) {
380 | const tp = type(obj)
381 | if (tp == FUNCTIONTYPE) {
382 | setProp(path, obj)
383 | } else if (tp == OBJECTTYPE) {
384 | Object.keys(obj).forEach(subKey => {
385 | _walk(obj[subKey], path + '.' + subKey)
386 | })
387 |
388 | } else if (tp == ARRAYTYPE) {
389 | obj.forEach((item, index) => {
390 | _walk(item, path + '[' + index + ']')
391 | })
392 |
393 | }
394 | }
395 |
396 | function setProp(path, fn) {
397 | const ok = getObjByPath(path)
398 | fnMapping[path] = fn
399 | Object.defineProperty(ok.obj, ok.key, {
400 | enumerable: true,
401 | get: () => {
402 | return fnMapping[path].call(globalStore.data)
403 | },
404 | set: () => {
405 | console.warn('Please using store.method to set method prop of data!')
406 | }
407 | })
408 | }
409 |
410 | function type(obj) {
411 | return Object.prototype.toString.call(obj)
412 | }
--------------------------------------------------------------------------------