├── publish.bat ├── test ├── mocha.opts ├── helpers │ └── _helper.js ├── test1.spec.js ├── datacache.spec.js └── adm.spec.js ├── .babelrc ├── lib ├── adm.jquery.min.js ├── adm.jquery.min.js.map ├── adm.jquery.js └── adm.jquery.js.map ├── example ├── index.html └── test.js ├── bower.json ├── .gitignore ├── LICENSE ├── webpack.config.js ├── server └── app.js ├── src ├── common │ ├── DataCache.js │ ├── settings.js │ └── cache-helper.js └── adm.jquery.js ├── jsdoc.json ├── package.json ├── README.md ├── .eslintrc └── USEAGE.md /publish.bat: -------------------------------------------------------------------------------- 1 | call npm publish --registry=https://registry.npmjs.org/ 2 | pause -------------------------------------------------------------------------------- /test/mocha.opts: -------------------------------------------------------------------------------- 1 | --require babel-register 2 | --compilers js:babel-register 3 | --colors 4 | -w 5 | ./test/*.spec.js 6 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { 4 | "targets": { 5 | "chrome": 52, 6 | "browsers": ["last 2 versions", "safari 7"] 7 | } 8 | }] 9 | ], 10 | "plugins": ["babel-plugin-add-module-exports"] 11 | } -------------------------------------------------------------------------------- /lib/adm.jquery.min.js: -------------------------------------------------------------------------------- 1 | !function(e,o){"object"==typeof exports&&"object"==typeof module?module.exports=o():"function"==typeof define&&define.amd?define("adm",[],o):"object"==typeof exports?exports.adm=o():e.adm=o()}(this,function(){return function(e){function o(n){if(t[n])return t[n].exports;var r=t[n]={exports:{},id:n,loaded:!1};return e[n].call(r.exports,r,r.exports,o),r.loaded=!0,r.exports}var t={};return o.m=e,o.c=t,o.p="",o(0)}([function(e,o,t){!function(){throw new Error('Cannot find module "./src/adm.jquery.js"')}()}])}); 2 | //# sourceMappingURL=adm.jquery.min.js.map -------------------------------------------------------------------------------- /example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 17 | 18 | 19 |

example test:

20 | 21 | 22 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ajax-data-model", 3 | "description": "ajax data model, ajax 通用数据请求处理", 4 | "main": "lib/adm.jquery.js", 5 | "authors": [ 6 | "lzwme", 7 | "renxia" 8 | ], 9 | "moduleType": [ 10 | "umd" 11 | ], 12 | "license": "MIT", 13 | "keywords": [ 14 | "ajax", 15 | "data-model", 16 | "webpack", 17 | "es6", 18 | "library", 19 | "universal", 20 | "umd", 21 | "commonjs" 22 | ], 23 | "homepage": "https://github.com/lzwme/ajax-data-model", 24 | "ignore": [ 25 | "**/.*", 26 | "node_modules", 27 | "bower_components", 28 | "test", 29 | "tests", 30 | "api", 31 | "server" 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # node-waf configuration 20 | .lock-wscript 21 | 22 | # Compiled binary addons (http://nodejs.org/api/addons.html) 23 | build/Release 24 | 25 | # Dependency directory 26 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 27 | node_modules 28 | localStorageTemp 29 | 30 | # api docs 31 | /api/ 32 | 33 | coverage/ 34 | 35 | package-lock.json 36 | yarn.lock -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 任侠 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /test/helpers/_helper.js: -------------------------------------------------------------------------------- 1 | /** 2 | * global helpers 3 | * @see http://chaijs.com/api/bdd/ 4 | */ 5 | import chai from 'chai'; 6 | import jsdom from 'mocha-jsdom'; 7 | import fs from 'fs'; 8 | // import adm from '../../src/adm.jquery.js'; 9 | 10 | jsdom({ 11 | url: 'http://127.0.0.1:3131', 12 | skipWindowCheck: true, 13 | html: undefined, 14 | src: fs.readFileSync('./node_modules/jquery/dist/jquery.js', 'utf-8') 15 | }); 16 | 17 | global.fs = fs; 18 | global.chai = chai; 19 | // global.adm = adm; 20 | 21 | // 使用 chai.expect 断言 22 | chai.expect(); 23 | global.expect = chai.expect; 24 | 25 | // localStorage 26 | const LocalStorage = require('node-localstorage').LocalStorage; 27 | 28 | global.localStorage = new LocalStorage('./test/localStorageTemp'); 29 | before(function (next) { 30 | global.adm = require('../../src/adm.jquery.js'); 31 | global.window = document.defaultView; 32 | global.localStorage = global.localStorage || new LocalStorage('./test/localStorageTemp'); 33 | global.window.localStorage = global.localStorage; 34 | 35 | next(); 36 | }); 37 | 38 | // import test from 'ava'; 39 | // global.test = test; 40 | 41 | // global.document = jsdom('

'); 42 | // global.window = document.defaultView; 43 | // global.navigator = window.navigator; 44 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | var UglifyJsPlugin = webpack.optimize.UglifyJsPlugin; 3 | var path = require('path'); 4 | var env = require('yargs').argv.mode; 5 | 6 | var plugins = [], 7 | outputFile, config; 8 | var libraryName = 'adm'; 9 | 10 | if (env === 'build') { 11 | plugins.push(new UglifyJsPlugin({ 12 | minimize: true 13 | })); 14 | outputFile = libraryName + '.jquery.min.js'; 15 | } else { 16 | outputFile = libraryName + '.jquery.js'; 17 | } 18 | 19 | config = { 20 | entry: [ 21 | './src/adm.jquery.js' 22 | ], 23 | devtool: 'source-map', 24 | output: { 25 | path: __dirname + '/lib', 26 | filename: outputFile, 27 | library: libraryName, 28 | libraryTarget: 'umd', 29 | umdNamedDefine: true 30 | }, 31 | module: { 32 | loaders: [{ 33 | test: /(\.jsx|\.js)$/, 34 | loader: 'babel', 35 | exclude: /(node_modules|bower_components)/ 36 | }, { 37 | test: /(\.jsx|\.js)$/, 38 | loader: 'eslint-loader', 39 | include: path.join(__dirname, 'src'), 40 | exclude: /node_modules/ 41 | }] 42 | }, 43 | resolve: { 44 | root: path.resolve('./src'), 45 | extensions: ['', '.js'] 46 | }, 47 | externals: { 48 | jquery: 'jquery' 49 | }, 50 | plugins: plugins 51 | }; 52 | 53 | module.exports = config; 54 | -------------------------------------------------------------------------------- /server/app.js: -------------------------------------------------------------------------------- 1 | /** 2 | * server for example test 3 | */ 4 | 5 | const Koa = require('koa'); 6 | const app = new Koa(); 7 | const Router = require('koa-router'); 8 | const router = new Router(); 9 | const serve = require('koa-static'); 10 | const fs = require('fs'); 11 | const port = process.env.PORT || 3131; 12 | 13 | app.use(serve('./')); 14 | app.use(serve('example/')); 15 | 16 | router.get('/', function (ctx, next) { 17 | ctx.body = fs.readFileSync('./example/index.html', 'utf8'); 18 | }); 19 | 20 | router.all('/rest/user', function (ctx, next) { 21 | ctx.body = JSON.stringify({ 22 | code: 200, 23 | message: 'success', 24 | value: { 25 | name: 'lzwme', 26 | id: '11', 27 | site: 'https://lzw.me' 28 | } 29 | }); 30 | }); 31 | 32 | router.get('*', function (ctx, next) { 33 | ctx.body = JSON.stringify({ 34 | code: 1000, 35 | message: 'not fond.', 36 | value: false 37 | }); 38 | }); 39 | 40 | app 41 | .use(router.routes()) 42 | .use(router.allowedMethods()); 43 | 44 | app.listen(port, () => { 45 | const child = require('child_process'); 46 | let open = 'open'; 47 | 48 | console.log('listen port ' + port); 49 | // process.platform: 'darwin', 'freebsd', 'linux', 'sunos' or 'win32' 50 | if (process.platform === 'win32') { 51 | open = 'start'; 52 | } 53 | 54 | child.exec(open + ' http://127.0.0.1:' + port); 55 | }); 56 | -------------------------------------------------------------------------------- /src/common/DataCache.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 基本的数据缓存类 3 | */ 4 | 5 | /** 6 | * 内存缓存数据对象类,与 `localStorage` API 保持一致 7 | */ 8 | class DataCache { 9 | constructor() { 10 | this.length = 0; 11 | this.cache = {}; 12 | } 13 | /** 14 | * 获取值 15 | * @param {String} key 16 | * @return {*} 17 | */ 18 | getItem(key) { 19 | return this.cache[key]; 20 | } 21 | /** 22 | * 设置值 23 | * @param {String} key 24 | * @param {*} value 25 | */ 26 | setItem(key, value) { 27 | if (!this.cache.hasOwnProperty(key)) { 28 | this.length++; 29 | } 30 | this.cache[key] = value; 31 | } 32 | /** 33 | * 删除一个值 34 | * @param {String} key 35 | * @return {void} 36 | */ 37 | removeItem(key) { 38 | if (this.cache.hasOwnProperty(key)) { 39 | this.length--; 40 | delete this.cache[key]; 41 | } 42 | } 43 | /** 44 | * 清空 45 | */ 46 | clear() { 47 | this.length = 0; 48 | this.cache = {}; 49 | } 50 | /** 51 | * 取得第 index 个数的 key 52 | * @param {Number} index 53 | * @return {*} 54 | */ 55 | key(index) { 56 | let key, _index = 0; 57 | 58 | for (key in this.cache) { 59 | if (index === _index) { 60 | return key; 61 | } 62 | _index++; 63 | } 64 | 65 | return null; 66 | } 67 | } 68 | 69 | export default DataCache; 70 | -------------------------------------------------------------------------------- /test/test1.spec.js: -------------------------------------------------------------------------------- 1 | import './helpers/_helper'; 2 | 3 | /** 4 | * 普通的写读删测试 5 | */ 6 | function testSimpleWRD(data, type) { 7 | let cache; 8 | 9 | before(() => { 10 | // 存 11 | adm.save('user_renxia', data, type); 12 | }); 13 | 14 | // 读取 get 15 | it('读取 adm.get', () => { 16 | cache = adm.get('user_renxia', type); 17 | expect(cache).to.be.deep.equal(data); 18 | }); 19 | 20 | // 读取 adm.getAll 21 | it('读取 adm.getAll', () => { 22 | cache = adm.getAll(type); 23 | expect(cache.user_renxia).to.be.deep.equal(data); 24 | }); 25 | 26 | // 删除 27 | it('删除 adm.delete', () => { 28 | adm.delete('user_renxia', type); 29 | cache = adm.get('user_renxia', type); 30 | expect(cache).to.be.undefined; 31 | }); 32 | 33 | it('删除(正则模糊删除) adm.delete', () => { 34 | adm.save('user_renxia', data, type); 35 | cache = adm.get('user_renxia', type); 36 | expect(cache).to.be.deep.equal(data); 37 | 38 | adm.delete(/user_/i, type); 39 | cache = adm.get('user_renxia', type); 40 | expect(cache).to.be.undefined; 41 | }); 42 | } 43 | 44 | describe('test1: 无 ajax 的数据读写删测试', function () { 45 | before(function () { 46 | adm.clear() 47 | .clear('sessionStorage') 48 | .clear('localStorage'); 49 | }); 50 | 51 | const data = { 52 | user: 'renxia', 53 | site: 'https://lzw.me' 54 | }; 55 | 56 | describe('从内存中写读删', 57 | () => testSimpleWRD(data)); 58 | 59 | describe('从 sessionStorage 中写读删', 60 | () => testSimpleWRD(data, 'sessionStorage')); 61 | 62 | // describe('从 localStorage 中写读删', 63 | // () => testSimpleWRD(data, 'localStorage')); 64 | 65 | describe('测试 adm.get', () => { 66 | it('读取一个不存在的值', () => { 67 | expect(adm.get('addxxxdd')).to.be.equal(undefined); 68 | }); 69 | }); 70 | }); 71 | -------------------------------------------------------------------------------- /test/datacache.spec.js: -------------------------------------------------------------------------------- 1 | import './helpers/_helper'; 2 | import DataCache from '../src/common/DataCache'; 3 | 4 | /** 5 | * DataCache API 测试 6 | */ 7 | let dataCache; 8 | 9 | function setAndGetTest(key, data) { 10 | let item; 11 | 12 | dataCache.setItem(key, data); 13 | item = dataCache.getItem(key); 14 | expect(item).to.be.equal(data); 15 | } 16 | 17 | describe('DataCache API 测试', function () { 18 | 19 | before(function () { 20 | dataCache = new DataCache(); 21 | }); 22 | 23 | it('getItem', () => { 24 | const item = dataCache.getItem('xxx'); 25 | 26 | expect(item).to.be.equal(undefined); 27 | }); 28 | 29 | it('setItem', () => { 30 | setAndGetTest('test1', 0); 31 | setAndGetTest('test1', 10); 32 | setAndGetTest('test2', undefined); 33 | setAndGetTest('test3', '测试测试'); 34 | setAndGetTest('test4', {a: 1, b: 2, c: 5}); 35 | }); 36 | 37 | it('key', () => { 38 | let item; 39 | 40 | dataCache.clear(); 41 | item = dataCache.key(0); 42 | expect(item).to.be.equal(null); 43 | 44 | dataCache.setItem('test', 111); 45 | item = dataCache.key(0); 46 | expect(item).to.be.equal('test'); 47 | }); 48 | 49 | it('removeItem', () => { 50 | setAndGetTest('test', '测试测试'); 51 | expect(dataCache.getItem('test')).to.be.equal('测试测试'); 52 | dataCache.removeItem('test'); 53 | expect(dataCache.getItem('test')).to.be.equal(undefined); 54 | }); 55 | 56 | it('length', () => { 57 | const dc = new DataCache(); 58 | 59 | expect(dc.length).to.be.equal(0); 60 | 61 | dc.setItem('test', 1); 62 | expect(dc.length).to.be.equal(1); 63 | 64 | dc.setItem('test2', 1); 65 | expect(dc.length).to.be.equal(2); 66 | }); 67 | 68 | it('clear', () => { 69 | dataCache.setItem('test', 1); 70 | expect(dataCache.length).to.be.ok; 71 | 72 | dataCache.clear(); 73 | expect(dataCache.length).to.be.equal(0); 74 | }); 75 | }); 76 | -------------------------------------------------------------------------------- /jsdoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "tags": { 3 | "allowUnknownTags": true 4 | }, 5 | "source": { 6 | "include": ["src"], //JavaScript 文件(目录)列表 7 | "exclude": ["src/ui/dialog"], //在 include 中需要过滤的文件(目录)。bigdata 平台上dialog 组件用 DW.modal 替代 8 | "includePattern": ".+\\.(js|es)$" //正则过滤符合规则的文件 9 | }, 10 | "plugins": ["plugins/markdown"], //使用markdown 插件 11 | "markdown": { 12 | "excludeTags": ["author"], 13 | "parser": "gfm", 14 | "hardwrap": true 15 | }, 16 | "templates": { //模板配置,包含了 DocStrap 的配置参数 17 | //"logoFile": "images/logo.png", //logo 文件路径 18 | "cleverLinks": false, 19 | "monospaceLinks": false, 20 | "dateFormat": "ddd MMM Do YYYY", //当需要打印日期时使用的格式 21 | "outputSourceFiles": true, //是否输出文件源码 22 | "outputSourcePath": true, //是否输出源码路径 23 | "systemName": "ajax data model(adm)", //系统名称 24 | "footer": "", //页脚内容 25 | "copyright": "https://lzw.me. ", //页脚版权信息 26 | "navType": "vertical", //vertical 或 inline 27 | //docstrap 模板主题。可取值: cosmo, cyborg, flatly, journal, lumen, paper, 28 | //readable, sandstone, simplex, slate, spacelab, superhero, united, yeti 29 | "theme": "cosmo", 30 | "linenums": true, //是否显示行号 31 | "collapseSymbols": false, //是否折叠太长的内容 32 | "inverseNav": true, //导航是否使用 bootstrap 的 inverse header 33 | "protocol": "html://", //生成文档使用的阅读协议 34 | "methodHeadingReturns": true //method 方法标题上是否包含返回类型 35 | }, 36 | //命令行执行参数配置。在这里配置了后 37 | //命令行只需要执行: jsdoc -c jsdoc-conf.json 即可 38 | "opts": { 39 | //"template": "templates/default", //使用 JSDoc 默认模板 40 | "template": "./node_modules/ink-docstrap/template", //使用 docstrap 模板 41 | "destination": "./api/", //输出目录。等同于 -d ./out/ 42 | "recurse": true, //是否递归查找。等同于 -r 43 | "debug": true, //启用调试模式 44 | "readme": "README.md" //要写到文档首页的 readme 文档 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ajax-data-model", 3 | "version": "0.0.12", 4 | "description": "ajax data model, ajax 通用数据请求处理", 5 | "main": "lib/adm.jquery.js", 6 | "browser": "lib/adm.jquery.min.js", 7 | "scripts": { 8 | "build": "webpack --mode=build", 9 | "start": "node server/app.js", 10 | "dev": "webpack --progress --colors --watch --mode=dev", 11 | "test": "mocha --compilers js:babel-core/register --colors -w ./test/*.spec.js", 12 | "cover": "node_modules/.bin/istanbul cover node_modules/.bin/_mocha -- -R spec", 13 | "jsdoc": "del /s /q /f /s api && jsdoc -c jsdoc.json", 14 | "l-jsdoc": "rm -rf api/* && jsdoc -c jsdoc.json" 15 | }, 16 | "peerDependencies": { 17 | "jquery": "*" 18 | }, 19 | "devDependencies": { 20 | "babel": "^6.23.0", 21 | "babel-core": "^6.26.3", 22 | "babel-eslint": "^10.0.0", 23 | "babel-loader": "^8.0.0", 24 | "babel-plugin-add-module-exports": "^1.0.2", 25 | "babel-preset-env": "^1.7.0", 26 | "chai": "^4.2.0", 27 | "eslint": "^6.8.0", 28 | "eslint-loader": "^3.0.0", 29 | "ink-docstrap": "^1.3.2", 30 | "jsdoc": "^3.6.0", 31 | "jsdom": "^16.0.0", 32 | "koa": "^2.11.0", 33 | "koa-router": "^7.4.0", 34 | "koa-static": "^5.0.0", 35 | "mocha": "^7.0.0", 36 | "mocha-jsdom": "^2.0.0", 37 | "node-localstorage": "^1.3.0", 38 | "webpack": "^1.13.1", 39 | "webpack-dev-server": "^3.10.1", 40 | "yargs": "^15.0.0" 41 | }, 42 | "repository": { 43 | "type": "git", 44 | "url": "https://github.com/lzwme/ajax-data-model.git" 45 | }, 46 | "keywords": [ 47 | "ajax", 48 | "data-model", 49 | "webpack", 50 | "es6", 51 | "library", 52 | "universal", 53 | "umd", 54 | "commonjs" 55 | ], 56 | "author": "lzwme", 57 | "maintainers": [ 58 | { 59 | "name": "renxia", 60 | "url": "https://lzw.me" 61 | } 62 | ], 63 | "license": "MIT", 64 | "bugs": { 65 | "url": "https://github.com/lzwme/ajax-data-model/issues" 66 | }, 67 | "homepage": "https://github.com/lzwme/ajax-data-model" 68 | } 69 | -------------------------------------------------------------------------------- /test/adm.spec.js: -------------------------------------------------------------------------------- 1 | import './helpers/_helper'; 2 | 3 | function cacheTest(cfg) { 4 | const {url, cache: type} = cfg; 5 | 6 | it(`ajax get(缓存到 ${type},然后读写删测试): ${url}`, function (next) { 7 | return adm.get(cfg).done((result) => { 8 | expect(result.code).to.be.equal(200); 9 | }).then(() => { 10 | let cache = adm.get(url, type); 11 | 12 | expect(cache.code).to.be.equal(200); 13 | 14 | if (cfg.expires && cfg.cache) { 15 | // expires 有效期测试 16 | setTimeout(function () { 17 | // 有效期内,可以读取到 18 | cache = adm.get(url, type); 19 | expect(cache.code).to.be.equal(200); 20 | 21 | setTimeout(function () { 22 | // 超过有效期,读取不到 23 | cache = adm.get(url, type); 24 | expect(cache).to.be.equal(undefined); 25 | next(); 26 | }, 200); 27 | }, cfg.expires - 100); 28 | } else { 29 | adm.delete(url, type); 30 | cache = adm.get(url, type); 31 | expect(cache).to.be.equal(undefined); 32 | next(); 33 | } 34 | }); 35 | }); 36 | } 37 | 38 | describe('test: ajax 测试', function () { 39 | before(function () { 40 | adm.clear(); 41 | }); 42 | 43 | describe('测试 adm.get', function () { 44 | const url = '/rest/user'; 45 | 46 | it(`ajax get: ${url}`, function (next) { 47 | adm.get({ 48 | url 49 | }).done((result) => { 50 | expect(result.code).to.be.equal(200); 51 | 52 | next(); 53 | }); 54 | }); 55 | 56 | it(`ajax getJSON: ${url}`, function (next) { 57 | adm.getJSON(url, (result) => { 58 | expect(result.code).to.be.equal(200); 59 | 60 | next(); 61 | }); 62 | }); 63 | 64 | it(`ajax post: ${url}`, function (next) { 65 | adm.post(url, {}, (result) => { 66 | expect(result.code).to.be.equal(200); 67 | 68 | next(); 69 | }); 70 | }); 71 | 72 | cacheTest({url, cache: 'memory'}); 73 | cacheTest({url, cache: 'memory', expires: 1000}); 74 | cacheTest({url, cache: 'sessionStorage'}); 75 | cacheTest({url, cache: 'localStorage'}); 76 | }); 77 | }); 78 | -------------------------------------------------------------------------------- /src/common/settings.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @desc 配置信息,可以通过 `adm.setSettings` 方法修改 3 | * @alias settings 4 | * @type {Object} 5 | */ 6 | export default { 7 | cachePrefix: '__DM__', // 缓存数据时使用的前缀,用于区别普通数据 8 | isJquery: true, // 是否使用 jQuery 的 $.Deferred。为 false 则使用 Promise 9 | errAlert: true, // ajax 出错时是否全局提示,fnAjaxFail 中使用。全局性开关 10 | errMsg: '', // 系统错误(40x/50x)时的提示信息,为空则使用 err.responseText 11 | alert: (msg) => { // 全局性提示方法注册,可根据项目的 alert 组件进行注册 12 | console.trace(msg); 13 | // window.alert(msg); 14 | }, 15 | /** 16 | * ajax 开始/结束时回调方法 17 | * 例如单击按钮后,在开始时禁用按钮,结束时恢复它; 18 | * 再例如,在 ajax 开始时启用页面动画,结束时关闭页面动画。 19 | * @param {Object} config.waiting - 参数内容可根据 `fnWaiting` 具体的处理来设置 20 | * @param {Number} time - 存在值时在 ajax 结束调用,值为 ajax 消耗的时间;省略时在 ajax 开始前被调用 21 | * @return {void} 22 | */ 23 | fnWaiting(config, time) { 24 | // const waiting = config.waiting; 25 | // if ('development' === process.env.NODE_ENV && time) { 26 | // console.trace('ajax 请求消耗时间:', time); 27 | // } 28 | // if (!waiting) { 29 | // return; 30 | // } 31 | // more... 32 | }, 33 | /** 34 | * ajax 请求开始前回调方法 35 | * @param {Object} config - ajax 请求配置,由于是引用传参,可在这里通过修改它实现 mock 数据等功能 36 | * @return {void} 37 | */ 38 | fnBeforeAjax(config) {}, 39 | /** 40 | * 通用 ajax 请求返回时回调方法 41 | * 对于基于接口的约定,如这里的示例:以 `code` 为 `200` 认为是成功的数据,否则为出错 42 | * @param {Object} result - ajax 返回的数据结果 43 | * @param {Function} callback - 成功回调方法 44 | * @param {Function} errCallback - 出错回调方法 45 | * @param {Object} config - ajax 请求参数配置,即 `adm.get/save` 的第一个参数 46 | * @returns {Boolean|Object|Promise} 表示成功或失败,或成功后返回的数据(如对 result 处理后返回),或 Promise 风格回调 47 | */ 48 | fnAjaxDone(result, callback, errCallback, config) { 49 | let success = false; 50 | 51 | if (result && result.code === 200) { 52 | if (callback) { 53 | callback(result); 54 | } 55 | 56 | // code 200 认为成功,否则认为失败 57 | success = true; 58 | } else { 59 | if (errCallback) { 60 | errCallback(result); 61 | } 62 | 63 | // 全局性系统提示,设置为 false,则不提示,适合由用户自定义错误处理的情况 64 | if (config.tipConfig !== false) { 65 | result.message = result.message || '系统错误'; 66 | this.alert(result.message); 67 | } 68 | } 69 | 70 | return success; 71 | }, 72 | /** 73 | * ajax 失败回调方法,一般为 30x、40x、50x 或返回格式不对、网络中断等 74 | * @param {Object} err 75 | * @param {Object} config 76 | * @return {void} 77 | */ 78 | fnAjaxFail(err, config) { 79 | let msg = err.responseText || err.statusText || ''; 80 | 81 | if (msg.length > 300) { 82 | msg = msg.slice(0, 300) + '...'; 83 | } 84 | 85 | if (0 === err.status) { 86 | this.alert('登录超时'); 87 | // window.location.reload(); 88 | } else if (config.errAlert || (void 0) === config.errAlert && this.errAlert) { 89 | // errAlert = false 时禁止 40x/50x 等错误的全局提示 90 | this.alert(config.errMsg || this.errMsg || ('数据请求失败: ' + msg)); 91 | } 92 | } 93 | }; 94 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ajax-Data-Model 2 | 3 | [![NPM version][npm-image]][npm-url] 4 | [![Dependency Status][david-image]][david-url] 5 | [![License][license-image]][license-url] 6 | [![Downloads][downloads-image]][downloads-url] 7 | 8 | ajax 数据请求模型封装。在 ajax 请求的生命周期过程中,实现基于项目约定的通用行为操作。 9 | 10 | ## 特性 11 | 12 | * umd 支持 13 | * memory/sessionStorage/localStorage 级数据缓存支持 14 | * Promise thenable 风格的 API 调用 15 | * 基于接口约定的通用回调处理支持(通用错误处理、loading 状态、通用参数、埋点上报<接口超时、接口错误、接口异常、数据埋点等>...) 16 | 17 | ## 快速开始 18 | 19 | ### 1. 下载安装 20 | 21 | 手动下载:到代码仓库下载 [release](https://github.com/lzwme/ajax-data-model/releases) 的 zip 包,取得 `dist` 目录内文件即可。 22 | 23 | npm 方式: 24 | 25 | ``` 26 | npm i --save ajax-data-model 27 | ``` 28 | 29 | ### 2. 使用 30 | 31 | #### 2.1 浏览器中直接引用使用 32 | 33 | A. 引入 `jquery.min.js` 和 `adm.jquery.min.js` 34 | 35 | ```javascript 36 | 37 | 38 | ``` 39 | 40 | B. 使用 41 | 42 | ```javascript 43 | 54 | ``` 55 | 56 | #### 2.2 ES6 方式使用 57 | 58 | A. 全局性设置 59 | 60 | ```javascript 61 | // adm.js 62 | import $ from 'jquery'; 63 | import adm from 'ajax-data-model'; 64 | 65 | // 全局性设置 66 | adm.setSettings({...}); 67 | 68 | // 示例:注册添加 API 到 adm 上(方便引用) 69 | adm.restapi = { 70 | userlist: '/rest/user/list' 71 | }; 72 | // todo more... 73 | 74 | export default adm; 75 | ``` 76 | 具体可参考 `src/common/settings.js` 中的参数配置示例。 77 | 78 | B. 使用 79 | 80 | ```javascript 81 | import adm from './adm'; 82 | // 使用示例 83 | adm.get({url: '/xxx'}).then((result) => { 84 | console.log(result); 85 | }); 86 | ``` 87 | 88 | 更多详细用法示例:[USEAGE.md](https://github.com/lzwme/ajax-data-model/blob/master/USEAGE.md) 89 | 90 | ## 命令脚本与二次开发 91 | 92 | * `npm start`:开启 `3131` 端口 web 服务,进行测试开发。 93 | * `npm run dev`:开启开发监听模式,监听 `src` 目录。 94 | * `npm test`:`mocha + chai` 测试(需先执行 `npm start`)。 95 | * `npm run build`:构建生产环境使用源码 (mini) 到 `lib` 目录。 96 | * `npm run jsdoc`:生成 `jsdoc` 风格的 `API` 文档。 97 | 98 | ## API 99 | 100 | 请参阅: [API](https://lzw.me/pages/demo/ajax-data-model/api/) 101 | 102 | ## License 103 | 104 | ajax-data-model is released under the MIT license. 105 | 106 | 该插件由[志文工作室](https://lzw.me)开发和维护。 107 | 108 | [npm-image]: https://img.shields.io/npm/v/ajax-data-model.svg?style=flat-square 109 | [npm-url]: https://npmjs.org/package/ajax-data-model 110 | [github-tag]: https://img.shields.io/github/tag/lzwme/ajax-data-model.svg?style=flat-square 111 | [github-url]: https://github.com/lzwme/ajax-data-model/tags 112 | [travis-image]: https://img.shields.io/travis/lzwme/ajax-data-model.svg?style=flat-square 113 | [travis-url]: https://travis-ci.org/lzwme/ajax-data-model 114 | [coveralls-image]: https://img.shields.io/coveralls/lzwme/ajax-data-model.svg?style=flat-square 115 | [coveralls-url]: https://coveralls.io/r/lzwme/ajax-data-model?branch=master 116 | [david-image]: https://img.shields.io/david/lzwme/ajax-data-model.svg?style=flat-square 117 | [david-url]: https://david-dm.org/lzwme/ajax-data-model 118 | [license-image]: https://img.shields.io/npm/l/ajax-data-model.svg?style=flat-square 119 | [license-url]: LICENSE 120 | [downloads-image]: https://img.shields.io/npm/dm/ajax-data-model.svg?style=flat-square 121 | [downloads-url]: https://npmjs.org/package/ajax-data-model 122 | -------------------------------------------------------------------------------- /lib/adm.jquery.min.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["webpack:///webpack/universalModuleDefinition","webpack:///adm.jquery.min.js","webpack:///webpack/bootstrap 2a2f007a7046e7916fd5"],"names":["root","factory","exports","module","define","amd","this","modules","__webpack_require__","moduleId","installedModules","id","loaded","call","m","c","p","Error"],"mappings":"CAAA,SAAAA,EAAAC,GACA,gBAAAC,UAAA,gBAAAC,QACAA,OAAAD,QAAAD,IACA,kBAAAG,gBAAAC,IACAD,OAAA,SAAAH,GACA,gBAAAC,SACAA,QAAA,IAAAD,IAEAD,EAAA,IAAAC,KACCK,KAAA,WACD,MCAgB,UAAUC,GCN1B,QAAAC,GAAAC,GAGA,GAAAC,EAAAD,GACA,MAAAC,GAAAD,GAAAP,OAGA,IAAAC,GAAAO,EAAAD,IACAP,WACAS,GAAAF,EACAG,QAAA,EAUA,OANAL,GAAAE,GAAAI,KAAAV,EAAAD,QAAAC,IAAAD,QAAAM,GAGAL,EAAAS,QAAA,EAGAT,EAAAD,QAvBA,GAAAQ,KAqCA,OATAF,GAAAM,EAAAP,EAGAC,EAAAO,EAAAL,EAGAF,EAAAQ,EAAA,GAGAR,EAAA,KDgBM,SAAUL,EAAQD,EAASM,IAE/B,WAAkC,KAAM,IAAIS,OAAM","file":"adm.jquery.min.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"adm\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"adm\"] = factory();\n\telse\n\t\troot[\"adm\"] = factory();\n})(this, function() {\nreturn \n\n\n// WEBPACK FOOTER //\n// webpack/universalModuleDefinition","(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"adm\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"adm\"] = factory();\n\telse\n\t\troot[\"adm\"] = factory();\n})(this, function() {\nreturn /******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId])\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\texports: {},\n/******/ \t\t\tid: moduleId,\n/******/ \t\t\tloaded: false\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.loaded = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n/******/\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(0);\n/******/ })\n/************************************************************************/\n/******/ ([\n/* 0 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\t(function webpackMissingModule() { throw new Error(\"Cannot find module \\\"./src/adm.jquery.js\\\"\"); }());\n\n\n/***/ })\n/******/ ])\n});\n;\n\n\n// WEBPACK FOOTER //\n// adm.jquery.min.js"," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId])\n \t\t\treturn installedModules[moduleId].exports;\n\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\texports: {},\n \t\t\tid: moduleId,\n \t\t\tloaded: false\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.loaded = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(0);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 2a2f007a7046e7916fd5"],"sourceRoot":""} -------------------------------------------------------------------------------- /example/test.js: -------------------------------------------------------------------------------- 1 | const adm = window.adm; 2 | 3 | function clear() { 4 | localStorage.clear(); 5 | sessionStorage.clear(); 6 | } 7 | 8 | function showMsg() { 9 | let i = 0, len, msg = ''; 10 | 11 | for (len = arguments.length; i < len; i++) { 12 | if (typeof arguments[i] !== 'string') { 13 | arguments[i] = '' + JSON.stringify(arguments[i]) + ''; 14 | } 15 | if (0 === i) { 16 | arguments[i] = '' + arguments[i] + ''; 17 | } 18 | 19 | msg += ' ' + arguments[i]; 20 | } 21 | 22 | $(`

${msg}

`).appendTo('body'); 23 | } 24 | 25 | function eqeq(v1, v2) { 26 | return JSON.stringify(v1) === JSON.stringify(v2) ? 27 | 'true' : 28 | 'false'; 29 | } 30 | 31 | function doRun() { 32 | clear(); 33 | 34 | // 普通的 ajax 请求 35 | adm.get({ 36 | url: '/rest/user' 37 | }).done(function (result) { 38 | console.log(result.value); 39 | showMsg('普通的 ajax 请求(/rest/user): ', result.value); 40 | }).then(function () { 41 | // code !== 200 的 ajax 请求 42 | return adm.get({ 43 | url: '/rest/user/xxx' 44 | }); 45 | }).then(function (result) {}, function (result) { 46 | return showMsg('code !== 200 的 ajax 请求(/rest/user/xxx): ', result); 47 | }).then(function () { 48 | // 缓存到内存 49 | return adm.get({ 50 | url: '/rest/user', 51 | cache: true, 52 | fromCache: true 53 | }); 54 | }).then(function (result) { 55 | // 从内存读取 56 | const cache = adm.get('/rest/user'); 57 | 58 | console.log(result); 59 | 60 | showMsg('从内存读取:', cache); 61 | showMsg('从内存读取与 url 获取值一致:', eqeq(result, cache)); 62 | }).then(function () { 63 | // 缓存到 sessionStorage 64 | return adm.get({ 65 | url: '/rest/user', 66 | cache: 'sessionStorage' 67 | }); 68 | }).then(function (result) { 69 | const cache = adm.get('/rest/user', 'sessionStorage'); 70 | 71 | console.log(result); 72 | 73 | showMsg('从 sessionStorage 读取:', cache); 74 | showMsg('从 sessionStorage 读取与 url 获取值一致:', eqeq(result, cache)); 75 | }).then(function () { 76 | // 缓存到 localStorage 77 | return adm.get({ 78 | url: '/rest/user', 79 | cache: 'localStorage' 80 | }); 81 | }).then(function (result) { 82 | const cache = adm.get('/rest/user', 'localStorage'); 83 | 84 | console.log(result); 85 | 86 | showMsg('从 localStorage 读取:', cache); 87 | showMsg('从 localStorage 读取与 url 获取值一致:', eqeq(result, cache)); 88 | }).then(function () { 89 | // 普通的缓存数据到 sessionStorage 90 | const data = {a: 1, b: 2}; 91 | 92 | adm.save('testdata', data, {cache: 'sessionStorage'}); 93 | 94 | const cache = adm.get('testdata', 'sessionStorage'); 95 | 96 | showMsg('普通的缓存数据到 sessionStorage,读取值:', cache, eqeq(cache, data)); 97 | }).then(function () { 98 | return new Promise(function (rs, rj) { 99 | // 普通的缓存数据到 sessionStorage 100 | const data = {a: 1, b: 2}; 101 | 102 | adm.save('testdata_expires', data, {cache: 'sessionStorage', expires: 1000}); 103 | 104 | let cache = adm.get('testdata_expires', 'sessionStorage'); 105 | 106 | showMsg('普通的缓存数据到 sessionStorage(expires=1000),读取值:', cache, eqeq(cache, data)); 107 | 108 | setTimeout(function () { 109 | cache = adm.get('testdata_expires', 'sessionStorage'); 110 | showMsg('普通的缓存数据到 sessionStorage(expires=1000),2 s 后读取值:', cache, eqeq(cache, undefined)); 111 | 112 | rs(); 113 | }, 2000); 114 | }); 115 | }).then(function () { 116 | return new Promise(function (rs, rj) { 117 | // 普通的缓存数据到 sessionStorage 118 | const data = {a: 1, b: 2}; 119 | 120 | adm.save('testdata_expires_date', data, { 121 | cache: 'sessionStorage', 122 | expires: new Date(new Date().getTime() + 1000) 123 | }); 124 | 125 | let cache = adm.get('testdata_expires_date', 'sessionStorage'); 126 | 127 | showMsg('普通的缓存数据到 sessionStorage(expires为Date类型,1s后过期),读取值:', cache, eqeq(cache, data)); 128 | 129 | setTimeout(function () { 130 | cache = adm.get('testdata_expires_date', 'sessionStorage'); 131 | showMsg('普通的缓存数据到 sessionStorage(expires为Date类型,1s后过期),2 s 后读取值:', cache, eqeq(cache, undefined)); 132 | 133 | rs(); 134 | }, 2000); 135 | }); 136 | }); 137 | } 138 | 139 | doRun(); -------------------------------------------------------------------------------- /src/common/cache-helper.js: -------------------------------------------------------------------------------- 1 | /** 2 | * cache helper 3 | */ 4 | import settings from './settings'; 5 | import DataCache from './DataCache'; 6 | 7 | // 缓存数据对象。为了避免混淆,只缓存至一级结构 8 | const dataCache = new DataCache(); 9 | 10 | // 获取时间戳 11 | function getTime(t) { 12 | return t ? t.getTime() : (new Date()).getTime(); 13 | } 14 | 15 | /** 16 | * 修正 cacheName 17 | * @param {String} cacheName 原始的值,可能是任意格式 18 | * @return {String} 修正后的 cacheName,以 cachePrefix 开头 19 | */ 20 | function adjustCacheName(cacheName) { 21 | if (!cacheName) { 22 | return ''; 23 | } 24 | 25 | cacheName = encodeURIComponent(('' + cacheName).replace(/\//g, '.').replace(/^\./, '').replace(/(^\s+|\s+$)/g, '')); 26 | if (cacheName.indexOf(settings.cachePrefix)) { 27 | // cacheName.indexOf(settings.cachePrefix) !== 0 加上前缀 28 | cacheName = settings.cachePrefix + cacheName; 29 | } 30 | 31 | return cacheName; 32 | } 33 | /** 34 | * 根据 cacheType 取得 cacheStorage 对象 35 | * @param {String} cacheType 36 | * @return {Object} 37 | */ 38 | export function getCacheStor(cacheType) { 39 | let cacheStor = dataCache; 40 | 41 | if (~['sessionStorage', 'localStorage'].indexOf(cacheType)) { 42 | cacheStor = window[cacheType] || cacheStor; 43 | } 44 | 45 | return cacheStor; 46 | } 47 | /** 48 | * 根据 cacheName 名称层级获取对应 dataCache 中的缓存数据 49 | * @param {String} cacheName - 名称,以 . 分割层级,如 ups.pa.query.tags.group 50 | * @param {String} cacheType - 缓存类型:sessionStorage、localStorage 、 memory(默认) 51 | * @return {*} 返回读取到的数据 52 | */ 53 | export function getCacheDataByName(cacheName, cacheType) { 54 | let data; 55 | const undefinedVal = void 0; 56 | const cacheStor = getCacheStor(cacheType); 57 | 58 | if (!(cacheName = adjustCacheName(cacheName))) { 59 | return data; 60 | } 61 | 62 | data = cacheStor.getItem(cacheName); 63 | try { 64 | data = JSON.parse(data); 65 | } catch (e) { 66 | data = data; 67 | } 68 | 69 | // 缓存的数据设置了有效期 data._e 70 | if (data && data._e) { 71 | // console.log(getTime() - data._e, getTime(), data._e); 72 | 73 | if (getTime() - data._e < 0) { 74 | return data.d; 75 | } 76 | // 已过期,数据无效了,移除它 77 | cacheStor.removeItem(cacheName); 78 | 79 | return undefinedVal; 80 | } 81 | 82 | return data || undefinedVal; 83 | } 84 | /** 85 | * 根据 cacheName 名称尝试移除缓存中存在的数据 86 | * @param {String|RegExp} cacheName - 名称,以 . 分割层级,如 ups.pa.query.tags.group。支持正则匹配 87 | * @param {String} cacheType - 缓存类型:sessionStorage、localStorage 、 memory(默认) 88 | * @return {*} 89 | */ 90 | export function deleteCacheDataByName(cacheName, cacheType) { 91 | const cacheStor = getCacheStor(cacheType); 92 | let item, 93 | i, 94 | len; 95 | 96 | // 为正则,支持模糊删除 97 | if (cacheName instanceof RegExp) { 98 | len = cacheStor.length; 99 | 100 | for (i = 0; i < len; i++) { 101 | item = cacheStor.key(i); 102 | 103 | if ( 104 | !item || // 兼容 105 | item.indexOf(settings.cachePrefix) !== 0 || // 过滤前缀 106 | !cacheName.test(item.slice(settings.cachePrefix.length)) // 规则检测 107 | ) { 108 | continue; 109 | } 110 | 111 | // 符合规则,移除 112 | cacheStor.removeItem(item); 113 | } 114 | 115 | return; 116 | } 117 | 118 | // 精确的查找与删除 119 | if (!(cacheName = adjustCacheName(cacheName))) { 120 | return; 121 | } 122 | 123 | cacheStor.removeItem(cacheName); 124 | } 125 | /** 126 | * 存储数据到本地 127 | * @param {String} cacheName - 用于存储的名称 128 | * @param {*} data - 任意类型的数据 129 | * @param {String} cacheType - 存储类型,支持三种方式:sessionStorage、localStorage 和内存中(默认) 130 | */ 131 | export function saveTOCache(cacheName, data, cfg = {}) { 132 | if (!(cacheName = adjustCacheName(cacheName))) { 133 | return; 134 | } 135 | 136 | // console.log(cacheName, data, cfg); 137 | 138 | const {cache: cacheType, expires} = cfg; 139 | const cacheStor = getCacheStor(cacheType); 140 | 141 | // expires 应为毫秒整数 142 | if (+expires) { 143 | data = { 144 | d: data, 145 | _e: (expires instanceof Date) ? getTime(expires) : (getTime() + expires) 146 | }; 147 | } 148 | 149 | if (cacheStor === dataCache) { 150 | // 存到内存 dataCache 151 | cacheStor.setItem(cacheName, data); 152 | } else { 153 | cacheStor.setItem(cacheName, JSON.stringify(data)); 154 | } 155 | } 156 | 157 | /** 158 | * 是否为类字符串 159 | */ 160 | export function isString(text) { 161 | const type = typeof text; 162 | 163 | return 'string' === type || 'number' === type; 164 | } 165 | /** 166 | * 返回包装done/fail API语法糖的 Promise 167 | * @param {Boolean} isJquery 是否为 jQuery,为true 则返回 $.Deferred 168 | * @return {Promise} 169 | */ 170 | export function getPromise(isJquery) { 171 | if (isJquery) { 172 | return $.Deferred(); 173 | } 174 | 175 | let resolve, reject; 176 | const $p = new window.Promise((rs, rj) => { 177 | resolve = rs; 178 | reject = rj; 179 | }); 180 | 181 | $p.resolve = resolve; 182 | $p.reject = reject; 183 | 184 | $p.done = function (cb) { 185 | return $p.then(cb); 186 | }; 187 | 188 | $p.fail = function (cb) { 189 | return $p.then(null, cb); 190 | }; 191 | 192 | $p.always = function (cb) { 193 | return $p.then(cb, cb); 194 | }; 195 | 196 | return $p; 197 | } 198 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "ecmaFeatures": { 3 | "globalReturn": true, 4 | "jsx": true, 5 | "modules": true 6 | }, 7 | 8 | "env": { 9 | "browser": true, 10 | "es6": true, 11 | "node": true 12 | }, 13 | 14 | "globals": { 15 | "document": false, 16 | "escape": false, 17 | "navigator": false, 18 | "unescape": false, 19 | "window": false, 20 | "describe": true, 21 | "before": true, 22 | "it": true, 23 | "expect": true, 24 | "sinon": true, 25 | "chai": true, 26 | "adm": true, 27 | "ava": true, 28 | "test": true, 29 | "$": true 30 | }, 31 | 32 | "parser": "babel-eslint", 33 | 34 | "plugins": [ 35 | 36 | ], 37 | 38 | "rules": { 39 | "block-scoped-var": 2, 40 | "brace-style": [2, "1tbs", { 41 | "allowSingleLine": true 42 | }], 43 | "camelcase": [2, { 44 | "properties": "always" 45 | }], 46 | "comma-dangle": [2, "never"], 47 | "comma-spacing": [2, { 48 | "before": false, 49 | "after": true 50 | }], 51 | "comma-style": [2, "last"], 52 | "complexity": 0, 53 | "consistent-return": 2, 54 | "consistent-this": 0, 55 | "curly": [2, "multi-line"], 56 | "default-case": 0, 57 | "dot-location": [2, "property"], 58 | "dot-notation": 0, 59 | "eol-last": 0, 60 | "eqeqeq": [2, "allow-null"], 61 | "func-names": 0, 62 | "func-style": 0, 63 | "generator-star-spacing": [2, "both"], 64 | "guard-for-in": 0, 65 | "handle-callback-err": [2, "^(err|error|anySpecificError)$"], 66 | "indent": [2, 4, { 67 | "SwitchCase": 1 68 | }], 69 | "key-spacing": [2, { 70 | "beforeColon": false, 71 | "afterColon": true 72 | }], 73 | "linebreak-style": 0, 74 | "max-depth": 0, 75 | "max-len": [2, 120, 4], 76 | "max-nested-callbacks": 0, 77 | "max-params": 0, 78 | "max-statements": 0, 79 | "new-cap": [2, { 80 | "newIsCap": true, 81 | "capIsNew": false 82 | }], 83 | "newline-after-var": [2, "always"], 84 | "new-parens": 2, 85 | "no-alert": 0, 86 | "no-array-constructor": 2, 87 | "no-bitwise": 0, 88 | "no-caller": 2, 89 | "no-catch-shadow": 0, 90 | "no-cond-assign": 2, 91 | "no-console": 0, 92 | "no-constant-condition": 0, 93 | "no-continue": 0, 94 | "no-control-regex": 2, 95 | "no-debugger": 2, 96 | "no-delete-var": 2, 97 | "no-div-regex": 0, 98 | "no-dupe-args": 2, 99 | "no-dupe-keys": 2, 100 | "no-duplicate-case": 2, 101 | "no-else-return": 2, 102 | "no-empty": 0, 103 | "no-empty-character-class": 2, 104 | "no-empty-label": 2, 105 | "no-eq-null": 0, 106 | "no-eval": 2, 107 | "no-ex-assign": 2, 108 | "no-extend-native": 2, 109 | "no-extra-bind": 2, 110 | "no-extra-boolean-cast": 2, 111 | "no-extra-parens": 0, 112 | "no-extra-semi": 0, 113 | "no-extra-strict": 0, 114 | "no-fallthrough": 2, 115 | "no-floating-decimal": 2, 116 | "no-func-assign": 2, 117 | "no-implied-eval": 2, 118 | "no-inline-comments": 0, 119 | "no-inner-declarations": [2, "functions"], 120 | "no-invalid-regexp": 2, 121 | "no-irregular-whitespace": 2, 122 | "no-iterator": 2, 123 | "no-label-var": 2, 124 | "no-labels": 2, 125 | "no-lone-blocks": 0, 126 | "no-lonely-if": 0, 127 | "no-loop-func": 0, 128 | "no-mixed-requires": 0, 129 | "no-mixed-spaces-and-tabs": [2, false], 130 | "no-multi-str": 2, 131 | "no-multiple-empty-lines": [2, { 132 | "max": 1 133 | }], 134 | "no-native-reassign": 2, 135 | "no-negated-in-lhs": 2, 136 | "no-nested-ternary": 0, 137 | "no-new": 2, 138 | "no-new-func": 2, 139 | "no-new-object": 2, 140 | "no-new-require": 2, 141 | "no-new-wrappers": 2, 142 | "no-obj-calls": 2, 143 | "no-octal": 2, 144 | "no-octal-escape": 2, 145 | "no-path-concat": 0, 146 | "no-plusplus": 0, 147 | "no-process-env": 0, 148 | "no-process-exit": 0, 149 | "no-proto": 2, 150 | "no-redeclare": 2, 151 | "no-regex-spaces": 2, 152 | "no-reserved-keys": 0, 153 | "no-restricted-modules": 0, 154 | "no-return-assign": 2, 155 | "no-script-url": 0, 156 | "no-self-compare": 2, 157 | "no-sequences": 2, 158 | "no-shadow": 0, 159 | "no-shadow-restricted-names": 2, 160 | "no-spaced-func": 2, 161 | "no-sparse-arrays": 2, 162 | "no-sync": 0, 163 | "no-ternary": 0, 164 | "no-throw-literal": 2, 165 | "no-trailing-spaces": 2, 166 | "no-undef": 2, 167 | "no-undef-init": 2, 168 | "no-undefined": 0, 169 | "no-underscore-dangle": 0, 170 | "no-unneeded-ternary": 2, 171 | "no-unreachable": 2, 172 | "no-unused-expressions": 0, 173 | "no-unused-vars": [2, { 174 | "vars": "all", 175 | "args": "none" 176 | }], 177 | "no-use-before-define": 2, 178 | "no-var": 0, 179 | "no-void": 0, 180 | "no-warning-comments": 0, 181 | "no-with": 2, 182 | "one-var": 0, 183 | "operator-assignment": 0, 184 | "operator-linebreak": [2, "after"], 185 | "padded-blocks": 0, 186 | "quote-props": 0, 187 | "quotes": [2, "single", "avoid-escape"], 188 | "radix": 2, 189 | "semi": [2, "always"], 190 | "semi-spacing": 0, 191 | "sort-vars": 0, 192 | "space-after-keywords": [2, "always"], 193 | "space-before-blocks": [2, "always"], 194 | "space-before-function-paren": [2, { 195 | "anonymous": "always", 196 | "named": "never" 197 | }], 198 | "space-in-brackets": 0, 199 | "space-in-parens": [2, "never"], 200 | "space-infix-ops": 2, 201 | "space-return-throw-case": 2, 202 | "space-unary-ops": [2, { 203 | "words": true, 204 | "nonwords": false 205 | }], 206 | "spaced-comment": [2, "always"], 207 | "strict": 0, 208 | "use-isnan": 2, 209 | "valid-jsdoc": 0, 210 | "valid-typeof": 2, 211 | "vars-on-top": 2, 212 | "wrap-iife": [2, "any"], 213 | "wrap-regex": 0 214 | } 215 | } 216 | -------------------------------------------------------------------------------- /USEAGE.md: -------------------------------------------------------------------------------- 1 | # ajax-data-model 使用示例 2 | 3 | ## 初始化设置 4 | 5 | 根据具体的项目和开发规范/习惯,设置 ajax 请求过程的一系列通用约定动作 6 | 7 | ```javascript 8 | //adm.js 9 | 10 | import $ from 'jquery'; 11 | import adm from 'ajax-data-model'; 12 | 13 | // 通过这里的设置,实现基于接口约定的通用性处理,可以设置一个或多个参数 14 | adm.setSettings({ 15 | cachePrefix: '__DM__', // 缓存数据时使用的前缀,用于区别普通数据 16 | isJquery: true, // 是否使用 jQuery 的 $.Deferred。为 false 则使用 Promise 17 | errAlert: true, // ajax 出错时是否全局提示,fnAjaxFail 中使用。全局性开关 18 | alert: (msg) => { // 全局性提示方法注册,根据项目的 alert 组件进行注册 19 | // console.trace(msg); 20 | // window.alert(msg); 21 | DW.modal.alert(msg); 22 | }, 23 | /** 24 | * ajax 开始/结束时的状态处理 25 | * 例如单击按钮后,在开始时禁用按钮,结束时恢复它; 26 | * 再例如,在 ajax 开始时启用页面动画,结束时关闭页面动画。 27 | * @param {Object} config.waiting - 参数内容可根据 `fnWaiting` 具体的处理来设置。例如这里为: 28 | * `{$btn:$btn, text:"请求中..", defaultText: "提交"}` 29 | * @param {Number} time - 存在值时在 ajax 结束调用,值为 ajax 消耗的时间;省略时在 ajax 开始调用 30 | * @return {void} 31 | */ 32 | fnWaiting(config, time) { 33 | const waiting = config.waiting; 34 | 35 | if ('development' === process.env.NODE_ENV && time) { 36 | console.trace('ajax 请求消耗时间:', time); 37 | } 38 | 39 | // 超长请求耗时的日志上报... 40 | // if (time > config.timeout || 5000) { 41 | // // 启动 api 上报... 42 | // MZBH('ajax_long_time', time, config.url); 43 | // } 44 | 45 | // 示例:根据 time 区分 ajax 开始与结束,分别做不同的处理 46 | // 这里以处理按钮状态为例,waiting 参数则为关键: {$btn, text, defaultText} 47 | if (!waiting || !waiting.$btn || !waiting.$btn.length) { 48 | return; 49 | } 50 | 51 | if (!time) { 52 | waiting.$btn.data('defaultText', waiting.$btn.html()) 53 | .html(waiting.text || ' 请求中...') 54 | .addClass('disabled').prop('disabled', true); 55 | } else { 56 | setTimeout(function () { 57 | // 连续提交延时处理,两次连续提交不能超过 200 ms 58 | waiting.$btn.html(waiting.defaultText || waiting.$btn.data('defaultText')) 59 | .removeClass('disabled').prop('disabled', false); 60 | }, 200); 61 | } 62 | }, 63 | /** 64 | * ajax 请求开始前回调方法 65 | * @param {Object} config - ajax 请求配置,由于是引用传参,可在这里通过修改它实现 mock 数据等功能 66 | * @return {void} 67 | */ 68 | fnBeforeAjax(config) { 69 | // 示例:增加通用上报参数 70 | cofig.data = $.extend({}, config.data, { 71 | username: Cookie.get('userName'), 72 | now: new Date().getTime() 73 | }); 74 | 75 | return config; 76 | }, 77 | /** 78 | * 通用 ajax 请求返回时回调方法 79 | * 对于基于接口的约定,如这里的示例:以 `code` 为 `200` 认为是成功的数据,否则为出错 80 | * @param {Object} result - ajax 返回的数据结果 81 | * @param {Function} callback - 成功回调方法 82 | * @param {Function} errCallback - 出错回调方法 83 | * @param {Object} config - ajax 请求参数配置,即 `adm.get/save` 的第一个参数 84 | */ 85 | fnAjaxDone(result, callback, errCallback, config) { 86 | const $d = $.Deferred(); 87 | 88 | if (result && result.code === 200) { 89 | if (callback) { 90 | callback(result); 91 | } 92 | 93 | // code 200 认为成功,否则认为失败 94 | $d.resolve(result); 95 | } else { 96 | $d.reject(result); 97 | 98 | if (errCallback) { 99 | errCallback(result); 100 | } 101 | 102 | // 设置为 false,则不进行系统提示,适合由用户自定义错误处理的情况 103 | if (config.tipConfig === false) { 104 | return $d; 105 | } 106 | 107 | result.message = result.message || '系统错误'; 108 | this.alert(result.message); 109 | } 110 | 111 | return $d; 112 | }, 113 | /** 114 | * ajax 失败回调方法,一般为 30x、40x、50x 或返回格式不对、网络中断等 115 | * @param {Object} err 116 | * @param {Object} config 117 | * @return {void} 118 | */ 119 | fnAjaxFail(err, config) { 120 | if (0 === err.status) { 121 | this.alert('登录超时').on('hidden.modal.bs', () => { 122 | window.location.reload(); 123 | }); 124 | } else if (config.errAlert || undefined === config.errAlert && this.errAlert) { 125 | // errAlert = false 时禁止 40x/50x 等错误的全局提示,可全局禁止,或本次禁止 126 | this.alert('数据请求失败: ' + (err.responseText || err.statusText)); 127 | } 128 | } 129 | }); 130 | 131 | export default adm; 132 | ``` 133 | 134 | ## 使用示例 135 | 136 | ### 使用示例一: 137 | 138 | * 基本的 ajax 请求 139 | * 几种回调方法示例 140 | 141 | ```javascript 142 | import adm from `adm`; 143 | 144 | const param = { 145 | url: '/rest/user/list' 146 | }; 147 | 148 | // 基本的 ajax 请求 149 | adm.get(param, (result) => { 150 | console.log(result) 151 | }, (err) => { 152 | console.log(err); 153 | }); 154 | 155 | // Promise 方式处理回调 156 | adm.get(param) 157 | .then((result) => { 158 | console.log(result) 159 | }, (err) => { 160 | console.log(err); 161 | }); 162 | 163 | // $.Deferred 的 done/fail 方式处理回调 164 | adm.get(param) 165 | .done((result) => { 166 | console.log(result) 167 | }) 168 | .fail((err) => { 169 | console.log(err); 170 | }); 171 | ``` 172 | 173 | ### 使用示例二: 174 | 175 | 缓存到 `sessionStorage` 示例,适合很少变动的元数据 176 | 177 | ```javascript 178 | const param = { 179 | url: '/rest/user/list', 180 | cache: 'sessionStorage', // 从 url 读取到了数据时,也缓存到 `sessionStorage` 181 | fromCache: 'sessionStorage', //优先从 `sessionStorage` 获取数据 182 | cacheName: 'userlist' //不写则使用 url 格式化:`rest.user.list` 183 | }; 184 | 185 | adm.get(param).then((result) => {}, (err) => {}); 186 | ``` 187 | 188 | 缓存到内存示例,适合单页应用 189 | 190 | ```javascript 191 | const param = { 192 | url: '/rest/user/list', 193 | cache: true, // 从 url 读取到了数据时,也缓存到内存中 194 | fromCache: true, //优先从内存获取数据 195 | cacheName: 'userlist' //不写则使用 url 格式化:`rest.user.list` 196 | }; 197 | 198 | adm.get(param).then((result) => {}, (err) => {}); 199 | ``` 200 | 201 | 缓存到 `localStorage` 示例,适合永远不会的数据 202 | 203 | ```javascript 204 | const data = {typeId: 2}; 205 | const param = { 206 | data, 207 | url: '/rest/user/list', 208 | cache: 'localStorage', 209 | fromCache: 'localStorage', 210 | cacheName: 'userlist_type_' + data.typeId // 以请求参数区分 211 | }; 212 | 213 | adm.get(param).then((result) => {}, (err) => {}); 214 | 215 | // 从 localStorage 中删除 216 | adm.delete(param.url, 'localStorage'); 217 | ``` 218 | 219 | ### 使用示例三: 220 | 221 | * adm.get/adm.save 222 | * `waiting` 参数,按钮状态处理 223 | * `data` 参数 224 | 225 | ```javascript 226 | const param = { 227 | url: '/rest/user', 228 | data: { 229 | userId: 22 230 | }, 231 | waiting: { 232 | $btn: $('#submit'), 233 | text: '获取中...' 234 | } 235 | }; 236 | 237 | adm.get(param).then((result) => {}, (err) => {}); 238 | ``` 239 | 240 | save 方法使用 `POST` 方式提交。示例: 241 | 242 | ```javascript 243 | const param = { 244 | url: '/rest/save/user', 245 | data: { 246 | userId: 22, 247 | username: 'lzwme', 248 | website: 'https://lzw.me' 249 | }, 250 | waiting: { 251 | $btn: $('#submit'), 252 | text: '正在提交...' 253 | } 254 | }; 255 | 256 | adm.save(param).then((result) => {}, (err) => {}); 257 | ``` 258 | 259 | ### 使用示例四 260 | 261 | 无 ajax 的数据读写删 262 | 263 | ```javascript 264 | const data = { 265 | user: 'renxia', 266 | site: 'https://lzw.me' 267 | }; 268 | 269 | // 存到内存中 270 | adm.save('user_renxia', data); 271 | // 存到 sessionStorage 272 | adm.save('user_renxia', data, 'sessionStorage'); 273 | // 存到 localStorage 274 | adm.save('user_renxia', data, 'localStorage'); 275 | 276 | // 读取 277 | let cache; 278 | 279 | // 从内存中 280 | cache = adm.get('user_renxia'); 281 | console.log('从内存读取(user_renxia): ', cache); 282 | 283 | // 从 sessionStorage 284 | cache = adm.get('user_renxia', 'sessionStorage'); 285 | console.log('从 sessionStorage 读取(user_renxia): ', cache); 286 | 287 | // 从 localStorage 288 | cache = adm.get('user_renxia', 'localStorage'); 289 | console.log('从 localStorage 读取(user_renxia): ', cache); 290 | 291 | // 删除 292 | 293 | // 从内存中删除 294 | adm.delete('user_renxia'); 295 | cache = adm.get('user_renxia'); 296 | console.log('从内存读取(user_renxia): ', cache); // undefined 297 | ``` 298 | 299 | ## 使用示例五 300 | 301 | - `adm.getJSON/adm.post` API 示例 302 | 303 | `adm.getJSON` 和 `adm.post` API 分别是 `adm.get` 和 `adm.save` 的简写版,用于一般的 ajax 请求。 304 | 305 | `adm.getJSON` API 示例: 306 | 307 | ```javascript 308 | const url = '/rest/xxx'; 309 | 310 | // thenable 风格回调 311 | adm.getJSON(url).then((result) => { 312 | console.log(result); 313 | }, (err) => { 314 | console.log(err); 315 | }); 316 | 317 | // thenable 风格回调,带 data 参数 318 | const data = {id: 123} 319 | adm.getJSON(url, data).then()... 320 | 321 | // callback 风格回调 322 | adm.getJSON(url, function(result){}, function(err) {}); 323 | 324 | // callback 风格回调,带 data 参数 325 | adm.getJSON(url, data, function(result){}, function(err) {}); 326 | 327 | ``` 328 | 329 | `adm.post` API 示例: 330 | 331 | ```javascript 332 | const url = '/rest/yyy'; 333 | const data = {id: 333}; 334 | 335 | adm.post(url, data, function(result){}, function(err) {}); 336 | // 或 thenable 风格 337 | adm.post(url, data) 338 | .then(function(result){}, function(err) {})) 339 | .then()... 340 | ``` 341 | 342 | ## 使用示例六 343 | 344 | 设置缓存有效期示例。适用于数据短期内可能会变动,但请求频繁的情况: 345 | 346 | ```javascript 347 | const data = {typeId: 2}; 348 | const param = { 349 | data, 350 | url: '/rest/user/list', 351 | cache: true, 352 | fromCache: true, 353 | expires: 1000 * 60, // 有效期设置为 1 分钟,也可为 Date 类型 354 | cacheName: 'userlist_type_' + data.typeId // 以请求参数区分 355 | }; 356 | 357 | adm.get(param).then((result) => {}, (err) => {}); 358 | ``` -------------------------------------------------------------------------------- /src/adm.jquery.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 全局数据模型 model 3 | * 提供数据的读取、保存/缓存、删除、更新等操作。各模块 model 可继承该模型,以进行模块范围内的数据存取操作。 4 | * @module adm 5 | * @author lzwy0820@qq.com 6 | * @since 2016-03-31 7 | * 8 | * @example 9 | * import adm from 'ajax-data-model'; 10 | * const upsModel = $.extend(true, {}, adm, {aa: 'ccc', restapi: {task_type: '/rest/task/type'}}); 11 | * // 支持的方法:upsModel.get、upsModel.save、upsModel.delete、upsModel.clear 12 | * // 配置了 url,则都返回 Promise 对象,不管是否缓存 13 | * upsModel.get({url: '/rest/xxx'}).done().fail().then(); 14 | * // 保存数据到 localStorage 中 15 | * upsModel.save('appList', [{music: 'test'}], 'localStorage'); 16 | * // 通过名字获取,返回存储的数据或者 undefined 17 | * upsModel.get('appList'); 18 | * upsModel.get('appList', 'localStorage'); 19 | * 20 | * @example 21 | * // 获取 task_type 数据 22 | * const data = {type: 10}; 23 | * adm.get({ 24 | * url: upsModel.restapi.task_type, 25 | * data: data, 26 | * cache: 'sessionStorage', // 缓存到 sessionStorage 27 | * fromCache: 'sessionStorage', // 获取时优先从 sessionStorage 读取 28 | * cacheName: 'task_type_' + data.type, // 缓存、从缓存读取时使用的名称 29 | * expires: 1000 * 60 * 5, // 数据有效时间为 5 分钟 30 | * }).then((result) => { 31 | * let taskTypeList = result.value || []; 32 | * console.log(taskTypeList); 33 | * }, (err) { 34 | * console.log(err); 35 | * }); 36 | */ 37 | 'use strict'; 38 | 39 | // import $ from 'jquery'; 40 | 41 | import settings from './common/settings'; 42 | import { 43 | getCacheStor, 44 | deleteCacheDataByName, 45 | getCacheDataByName, 46 | saveTOCache, 47 | isString, 48 | getPromise 49 | } from './common/cache-helper'; 50 | 51 | // 常量定义 52 | const WIN = window; 53 | const logTrace = WIN.console.trace; 54 | const ERRURLMSG = '配置了 URL 参数,但值为空或类型不对'; 55 | 56 | /** 57 | * ajax 请求通用方法 58 | * @param {Object} config - 请求参数配置 59 | * @param {String} config.url - ajax url,必须存在,`config.ajaxParam` 中配置此参数无效 60 | * @param {Object} config.ajaxParam - ajax 额外参数扩展,如涉及文件上传等 61 | * @param {Object} config.data - ajax 请求的参数 62 | * @param {Object} config.waiting - 用于传递给 settings.fnWaiting 方法使用的参数配置 63 | * @param {Object} config.tipConfig[true] - ajax 出错时的提示配置。配置为 false 时,禁用全局的系统提示,包括 成功/出错/404/50x 等 64 | * @param {Object} config.errAlert[true] - ajax error 时是否给出提示 65 | * @param {Function} callback - ajax 请求成功时回调 66 | * @param {Function} errCallback - ajax 请求失败或 code !== 200 时回调 67 | * @param {Object} param - 传递给 ajax 请求的额外参数 68 | * @param {Function} fnCB - 请求到数据之后的立即回调方法,用于请求成功后需要前置处理的情况 69 | * @return {Promise} 用于自定义回调处理。 70 | * 注意:ajax 请求的 done/fail 回调,与 callback/errCallback 可能有区别,具体取决于 fnAjaxDone 与 fnAjaxFail 回调的实现 71 | */ 72 | function requestAjax(config, callback, errCallback, fnCB) { 73 | const $p = getPromise(settings.isJquery); 74 | 75 | if (!config.url || typeof config.url !== 'string') { 76 | logTrace(ERRURLMSG, config.url); 77 | return $p.reject(ERRURLMSG, config.url); 78 | } 79 | 80 | // data.btnWaiting 的兼容,应使用 config.waiting 参数 81 | if (config.data && config.data.btnWaiting) { 82 | config.waiting = config.waiting || config.data.btnWaiting; 83 | delete config.data.btnWaiting; 84 | } 85 | 86 | // jsonp 兼容 87 | let dataType = 'json'; 88 | 89 | if (/^https?:\/\//.test(config.url) && config.url.search(WIN.location.host) === -1) { 90 | dataType = 'jsonp'; 91 | } 92 | 93 | // 请求前回调,可以引用方式修改 config 94 | if (settings.fnBeforeAjax) { 95 | settings.fnBeforeAjax(config); 96 | } 97 | 98 | // 格式化 config.data 99 | let item; 100 | 101 | if ('object' === typeof config.data) { 102 | for (item in config.data) { 103 | if ('string' !== typeof config.data[item]) { 104 | config.data[item] = JSON.stringify(config.data[item]); 105 | } 106 | } 107 | } 108 | 109 | // ajax 请求前处理,与请求后处理呼应 110 | settings.fnWaiting(config); 111 | 112 | const startTime = new Date(); 113 | 114 | return $.ajax($.extend(true, { 115 | type: 'GET', 116 | dataType 117 | }, config.ajaxParam, { 118 | url: config.url, 119 | data: config.data 120 | })).then((result) => { 121 | const success = settings.fnAjaxDone(result, (res) => { 122 | if (fnCB instanceof Function) { 123 | fnCB(result); 124 | } 125 | 126 | if (callback instanceof Function) { 127 | callback(res); 128 | } 129 | }, errCallback, config); 130 | 131 | // 为 false,设为失败回调 132 | if (!success) { 133 | return $p.reject(result); 134 | } 135 | 136 | // 为 true 137 | if (true === success) { 138 | return $p.resolve(result); 139 | } 140 | 141 | // 为 Promise 风格回调 142 | if ('function' === typeof success.then) { 143 | // $p = success; 144 | // return $p; 145 | return success; 146 | } 147 | 148 | // 为其它类型,返回 success 内容 149 | return $p.resolve(success); 150 | }, (err) => { 151 | settings.fnAjaxFail(err, config); 152 | 153 | if (errCallback instanceof Function) { 154 | errCallback(err); 155 | } 156 | 157 | return $p.reject(err); 158 | }).always(() => { 159 | // ajax 完成后处理 160 | settings.fnWaiting(config, new Date() - startTime); 161 | }); 162 | 163 | // return $p; 164 | } 165 | 166 | // 获取缓存数据的名称 key 167 | function getCacheName(config) { 168 | // 第一个参数为字符串,则为名称,直接返回 config 作为缓存名称 169 | if (isString(config) || !config) { 170 | return config; 171 | } 172 | 173 | let cacheName = config.cacheName; 174 | let dataStr; 175 | const md5 = WIN.$ && WIN.$.md5 || WIN.md5; 176 | const data = config.data; 177 | 178 | if (!cacheName) { 179 | cacheName = config.url; 180 | 181 | if (cacheName && typeof data === 'object') { 182 | let strData = JSON.stringify(data); 183 | 184 | if (typeof md5 === 'function') { 185 | strData = md5(strData); 186 | } 187 | 188 | cacheName += dataStr; 189 | } 190 | } 191 | 192 | return cacheName; 193 | } 194 | 195 | // obj 对象中是否包含键为 key 的项 196 | function hasOwnProperty(obj, key) { 197 | return obj.hasOwnProperty(key); 198 | } 199 | 200 | /** 201 | * 全局数据模型 model 202 | * @alias module:adm 203 | * @type {Object} 204 | */ 205 | export default { 206 | /** 207 | * 数据获取,可为远程url、缓存等 208 | * @param {Object} config 为字符串时,从缓存中读取数据,否则为从远程获取数据,参数如下: 209 | * ```js 210 | * { 211 | * url: '', // API url 地址,可为空。为空时应存在 cacheName,此时为从缓存中读取数据 212 | * data: {}, // url 请求参数 213 | * cache: false, // 配置了 url 获取数据时,是否缓存数据。可取值:`false/true/sessionStorage/localStorage` 214 | * fromCache: false, // 配置了 url,是否首先尝试从缓存中读取数据。可取值:`false/true/sessionStorage/localStorage` 215 | * cacheName: '', // 配置了 url 并且 cache 为 true,配置缓存数据的名称,不配置则取值 url (/ 会替换为 . 作为深度路径) 216 | * expires: 0, // 如果 cache 为 true,设置缓存数据的有效期,可为 毫秒数,或 Date 类型日期 217 | * tipConfig: {delay: 2000} // ajax 出错时的提示配置。配置为 false 时,禁用全局的系统提示,包括 成功/出错/404/50x 等 218 | * errAlert: true // ajax error 时是否给出全局提示,优先级高于 settings.errAlert 219 | * waiting: {} // 按钮等待等配置,用于传递给 settings.fnWaiting 方法 220 | * ajaxParam: null // ajax 额外参数扩展,如涉及文件上传等,需要修改部分参数。其中 url 参数无效,应当使用 config.url 221 | * } 222 | * ``` 223 | * @param {Object} callback 成功回调方法 224 | * @param {Object} errCallback 从 url 获取时,失败后需要做一些处理的回调方法 225 | * } 226 | */ 227 | get(config, callback, errCallback) { 228 | if (!config) { 229 | return undefined; 230 | } 231 | 232 | let cacheData; 233 | const $promise = getPromise(settings.isJquery); 234 | const cacheName = getCacheName(config); 235 | 236 | // 配置了 url,从 url 中获取 237 | if (config.url) { 238 | cacheData = getCacheDataByName(cacheName, config.fromCache); 239 | 240 | // fromCache 为 true,尝试从缓存中获取数据 241 | if (config.fromCache && cacheData) { 242 | if (typeof callback === 'function') { 243 | callback(cacheData); 244 | } 245 | 246 | $promise.resolve(cacheData); 247 | // return cacheData; // 返回数据 248 | return $promise; // 这里改了后不兼容旧的调用,应该注意 bug 的出现! 249 | } 250 | 251 | config.ajaxParam = $.extend(config.ajaxParam, { 252 | type: 'GET' 253 | }); 254 | 255 | return requestAjax(config, callback, errCallback, (result) => { 256 | // cache 为 true,缓存数据 257 | if (config.cache) { 258 | this.save(cacheName, result, config); 259 | } 260 | }); 261 | } else if (hasOwnProperty(config, 'url')) { // 配置了 url,但 url 值为空 262 | logTrace(ERRURLMSG, config); 263 | $promise.reject(ERRURLMSG, config); 264 | } else { 265 | // 未配置 url,则必须配置 config.cacheName,或者 config 为字符串(作为cacheName),此时为从缓存中取得数据 266 | cacheData = getCacheDataByName(cacheName, config.fromCache || callback); 267 | 268 | if (callback instanceof Function) { 269 | callback(cacheData); 270 | } 271 | 272 | return cacheData; 273 | } 274 | 275 | return $promise; 276 | }, 277 | /** 278 | * 设置/存储数据 279 | * @param {Object|String} config - 配置信息。也可以为字符串,则为需存储的数据名称。与 {@link module:adm~get} 的 config 参数相同 280 | * @param {Function|Object} callback - 存储成功后回调方法。当 config 为字符串时,为需存储的数据,或方法执行后返回要存储的数据 281 | * @param {Function|String} errCallback - 从 url 获取时,失败后需要做一些处理的回调方法。config 为字符串时,为配置信息,如 {cacheType, expires} 282 | * @example 283 | * // 存储数据到 localStorage,名称为 testdataName 284 | * adm.save('testdataName', {test: 1}, 'localStorage'); 285 | * @example 286 | * // 存储数据到远程,同时将 API 返回的结果存储到 sessionStorage 287 | * adm.save({url: '/rest/dd', data: {test: 1}, cache: 'sessionStorage'}); 288 | */ 289 | save(config, callback, errCallback) { 290 | const $promise = getPromise(settings.isJquery); 291 | const resolve = $promise.resolve; 292 | const reject = $promise.reject; 293 | 294 | if (!config) { 295 | resolve(); 296 | return $promise; 297 | } 298 | 299 | let cacheData; 300 | const cacheName = getCacheName(config, true); 301 | 302 | if (isString(config)) { // config 为字符串,则作为cacheName 303 | if (callback instanceof Function) { // 可以存储为回调方法执行后的结果 304 | saveTOCache(cacheName, callback(), errCallback); 305 | } else { 306 | saveTOCache(cacheName, callback, errCallback); 307 | } 308 | resolve(cacheName); 309 | } else if (config.url) { // 配置了 url,将数据存储到远程 310 | cacheData = getCacheDataByName(cacheName, config.fromCache); 311 | 312 | // fromCache 为 true,尝试从缓存中获取数据 313 | if (config.fromCache && cacheData) { 314 | if (callback instanceof Function) { 315 | callback(cacheData); 316 | } 317 | 318 | resolve(cacheData); 319 | // return cacheData; // 返回数据 320 | return $promise; // 这里改了后不兼容旧的调用,应该注意 bug 的出现! 321 | } 322 | 323 | config.ajaxParam = $.extend({ 324 | type: 'POST' 325 | }, config.ajaxParam); 326 | 327 | return requestAjax(config, callback, errCallback, (result) => { 328 | if (config.cache) { 329 | // 远程存储成功了,本地也需缓存数据时 330 | saveTOCache(cacheName, result, config); 331 | } 332 | }); 333 | } else if (hasOwnProperty(config, 'url')) { // 配置了url,但 url 值为空 334 | logTrace(ERRURLMSG, config); 335 | reject(ERRURLMSG, config); 336 | } else if (cacheName) { // 没有设置 url,但设置了 config.cacheName(此时 cacheName=config.cacheName),则保存数据到本地 337 | saveTOCache(cacheName, config.data, config); 338 | 339 | if (callback instanceof Function) { 340 | callback(cacheData); 341 | } 342 | resolve(config.data); 343 | } 344 | 345 | return $promise; 346 | }, 347 | /** 348 | * 删除一个数据 349 | * @param {Object} config - 为字符串时,作为 cacheName 尝试从缓存中删除数据。否则格式如下: 350 | * ```js 351 | * { 352 | * url: '', // 配置了 url,从远程删除数据,否则从缓存中删除 353 | * cache: false, // 配置了 url,是否还尝试从缓存中删除数据。可取值:false/true/sessionStorage/localStorage 354 | * cacheName: '' // 从缓存中删除数据时,提供其名称。 355 | * } 356 | * ``` 357 | */ 358 | delete(config, callback, errCallback) { 359 | if (!config) { 360 | return ''; 361 | } 362 | 363 | const $promise = getPromise(settings.isJquery); 364 | const cacheName = getCacheName(config); 365 | 366 | if (isString(config) || config instanceof RegExp) { 367 | // 第一个参数为字符串或正则,callback 就是 cacheType 368 | deleteCacheDataByName(config, callback); 369 | // 删除完成都返回执行成功 370 | $promise.resolve(); 371 | } else if (config.url) { 372 | // 配置了 url,从远程删除数据 373 | return requestAjax(config, callback, errCallback, { 374 | type: 'DELETE' 375 | }, () => { 376 | if (config.cache) { 377 | // 远程删除成功了,本地也需清空时 378 | deleteCacheDataByName(cacheName, config.cache); 379 | } 380 | }); 381 | } else if (hasOwnProperty(config, 'url')) { // 配置了url,但 url 值为空 382 | logTrace(ERRURLMSG, config); 383 | $promise.reject(ERRURLMSG, config); 384 | } else if (cacheName) { 385 | deleteCacheDataByName(cacheName, config.cache); 386 | $promise.resolve(); 387 | } 388 | 389 | return $promise; 390 | }, 391 | /** 392 | * 返回所有存储中的所有数据 393 | * @param {String} cacheType 存储的类型:sessionStorage、localStorage 或 memory 394 | * @return {Object} 395 | */ 396 | getAll(cacheType) { 397 | const cacheStor = getCacheStor(cacheType); 398 | const _cache = {}; 399 | const len = cacheStor.length; 400 | let i; 401 | let item, key; 402 | 403 | for (i = 0; i < len; i++) { 404 | item = cacheStor.key(i); 405 | 406 | if (!item || 0 !== item.indexOf(settings.cachePrefix)) { 407 | continue; 408 | } 409 | 410 | key = item.replace(settings.cachePrefix, ''); 411 | try { 412 | _cache[key] = JSON.parse(cacheStor.getItem(item)); 413 | } catch (e) { 414 | _cache[key] = cacheStor.getItem(item); 415 | } 416 | } 417 | 418 | return _cache; 419 | }, 420 | /** 421 | * {@link module:dataModel.get} 的 ajax 快捷方法 422 | * @see module:dataModel.get 423 | * @param {String} url url 地址 424 | * @param {Object} data 要传递的参数,可省略 425 | * @param {Function} callback 成功回调 426 | * @param {Function} errCallback 失败回调 427 | * @returns {Promise} 428 | */ 429 | getJSON(url, data = {}, callback, errCallback) { 430 | // data 参数可以省略 431 | if (data instanceof Function) { 432 | errCallback = callback; 433 | callback = data; 434 | data = void 0; 435 | } 436 | 437 | return this.get({ 438 | url, 439 | data 440 | }, callback, errCallback); 441 | }, 442 | /** 443 | * {@link module:dataModel.save} 的 ajax 快捷方法 444 | * @see module:dataModel.save 445 | * @param {String} url url 地址 446 | * @param {Object} data 要传递的参数 447 | * @param {Function} callback 成功回调 448 | * @param {Function} errCallback 失败回调 449 | * @returns {Promise} 450 | */ 451 | post(url, data, callback, errCallback) { 452 | return this.save({ 453 | url, 454 | data 455 | }, callback, errCallback); 456 | }, 457 | /** 458 | * 根据存储类型清空存储的所有数据 459 | * @param {String} cacheType 460 | * @return {scope} this 461 | */ 462 | clear(cacheType) { 463 | deleteCacheDataByName(new RegExp('.*'), cacheType); 464 | 465 | return this; 466 | }, 467 | /** 468 | * 修改缓存数据的前缀 469 | * @param {String} prefix 以下划线开头,由字母、数字、或下划线组成 470 | * @param {Boolean} clear[=true] 修改前缀前,是否移除已有的数据 471 | */ 472 | setCachePrefix(prefix, clear = true) { 473 | if (!/^_[_a-zA-Z]*_$/.test(prefix)) { 474 | console.warn('以下划线开头和结尾,由字母、数字、或下划线组成'); 475 | return this; 476 | } 477 | 478 | if (clear) { 479 | this.clear('sessionStorage'); 480 | this.clear('localStorage'); 481 | this.clear(); 482 | } 483 | 484 | settings.cachePrefix = prefix; 485 | 486 | return this; 487 | }, 488 | /** 489 | * 设置配置项 490 | * @param {Object} setting 491 | */ 492 | setSettings(setting) { 493 | let item; 494 | 495 | for (item in setting) { 496 | if ('cachePrefix' === item) { 497 | this.setCachePrefix(setting[item], false); 498 | } else if (hasOwnProperty(settings, item)) { 499 | settings[item] = setting[item]; 500 | } 501 | } 502 | 503 | return settings; 504 | } 505 | }; 506 | -------------------------------------------------------------------------------- /lib/adm.jquery.js: -------------------------------------------------------------------------------- 1 | (function webpackUniversalModuleDefinition(root, factory) { 2 | if(typeof exports === 'object' && typeof module === 'object') 3 | module.exports = factory(); 4 | else if(typeof define === 'function' && define.amd) 5 | define("adm", [], factory); 6 | else if(typeof exports === 'object') 7 | exports["adm"] = factory(); 8 | else 9 | root["adm"] = factory(); 10 | })(this, function() { 11 | return /******/ (function(modules) { // webpackBootstrap 12 | /******/ // The module cache 13 | /******/ var installedModules = {}; 14 | /******/ 15 | /******/ // The require function 16 | /******/ function __webpack_require__(moduleId) { 17 | /******/ 18 | /******/ // Check if module is in cache 19 | /******/ if(installedModules[moduleId]) 20 | /******/ return installedModules[moduleId].exports; 21 | /******/ 22 | /******/ // Create a new module (and put it into the cache) 23 | /******/ var module = installedModules[moduleId] = { 24 | /******/ exports: {}, 25 | /******/ id: moduleId, 26 | /******/ loaded: false 27 | /******/ }; 28 | /******/ 29 | /******/ // Execute the module function 30 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 31 | /******/ 32 | /******/ // Flag the module as loaded 33 | /******/ module.loaded = true; 34 | /******/ 35 | /******/ // Return the exports of the module 36 | /******/ return module.exports; 37 | /******/ } 38 | /******/ 39 | /******/ 40 | /******/ // expose the modules object (__webpack_modules__) 41 | /******/ __webpack_require__.m = modules; 42 | /******/ 43 | /******/ // expose the module cache 44 | /******/ __webpack_require__.c = installedModules; 45 | /******/ 46 | /******/ // __webpack_public_path__ 47 | /******/ __webpack_require__.p = ""; 48 | /******/ 49 | /******/ // Load entry module and return exports 50 | /******/ return __webpack_require__(0); 51 | /******/ }) 52 | /************************************************************************/ 53 | /******/ ([ 54 | /* 0 */ 55 | /***/ (function(module, exports, __webpack_require__) { 56 | 57 | module.exports = __webpack_require__(1); 58 | 59 | 60 | /***/ }), 61 | /* 1 */ 62 | /***/ (function(module, exports, __webpack_require__) { 63 | 64 | /** 65 | * @file 全局数据模型 model 66 | * 提供数据的读取、保存/缓存、删除、更新等操作。各模块 model 可继承该模型,以进行模块范围内的数据存取操作。 67 | * @module adm 68 | * @author lzwy0820@qq.com 69 | * @since 2016-03-31 70 | * 71 | * @example 72 | * import adm from 'ajax-data-model'; 73 | * const upsModel = $.extend(true, {}, adm, {aa: 'ccc', restapi: {task_type: '/rest/task/type'}}); 74 | * // 支持的方法:upsModel.get、upsModel.save、upsModel.delete、upsModel.clear 75 | * // 配置了 url,则都返回 Promise 对象,不管是否缓存 76 | * upsModel.get({url: '/rest/xxx'}).done().fail().then(); 77 | * // 保存数据到 localStorage 中 78 | * upsModel.save('appList', [{music: 'test'}], 'localStorage'); 79 | * // 通过名字获取,返回存储的数据或者 undefined 80 | * upsModel.get('appList'); 81 | * upsModel.get('appList', 'localStorage'); 82 | * 83 | * @example 84 | * // 获取 task_type 数据 85 | * const data = {type: 10}; 86 | * adm.get({ 87 | * url: upsModel.restapi.task_type, 88 | * data: data, 89 | * cache: 'sessionStorage', // 缓存到 sessionStorage 90 | * fromCache: 'sessionStorage', // 获取时优先从 sessionStorage 读取 91 | * cacheName: 'task_type_' + data.type, // 缓存、从缓存读取时使用的名称 92 | * expires: 1000 * 60 * 5, // 数据有效时间为 5 分钟 93 | * }).then((result) => { 94 | * let taskTypeList = result.value || []; 95 | * console.log(taskTypeList); 96 | * }, (err) { 97 | * console.log(err); 98 | * }); 99 | */ 100 | 'use strict'; 101 | 102 | // import $ from 'jquery'; 103 | 104 | Object.defineProperty(exports, "__esModule", { 105 | value: true 106 | }); 107 | 108 | var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; 109 | 110 | var _settings = __webpack_require__(2); 111 | 112 | var _settings2 = _interopRequireDefault(_settings); 113 | 114 | var _cacheHelper = __webpack_require__(3); 115 | 116 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 117 | 118 | // 常量定义 119 | var WIN = window; 120 | var logTrace = WIN.console.trace; 121 | var ERRURLMSG = '配置了 URL 参数,但值为空或类型不对'; 122 | 123 | /** 124 | * ajax 请求通用方法 125 | * @param {Object} config - 请求参数配置 126 | * @param {String} config.url - ajax url,必须存在,`config.ajaxParam` 中配置此参数无效 127 | * @param {Object} config.ajaxParam - ajax 额外参数扩展,如涉及文件上传等 128 | * @param {Object} config.data - ajax 请求的参数 129 | * @param {Object} config.waiting - 用于传递给 settings.fnWaiting 方法使用的参数配置 130 | * @param {Object} config.tipConfig[true] - ajax 出错时的提示配置。配置为 false 时,禁用全局的系统提示,包括 成功/出错/404/50x 等 131 | * @param {Object} config.errAlert[true] - ajax error 时是否给出提示 132 | * @param {Function} callback - ajax 请求成功时回调 133 | * @param {Function} errCallback - ajax 请求失败或 code !== 200 时回调 134 | * @param {Object} param - 传递给 ajax 请求的额外参数 135 | * @param {Function} fnCB - 请求到数据之后的立即回调方法,用于请求成功后需要前置处理的情况 136 | * @return {Promise} 用于自定义回调处理。 137 | * 注意:ajax 请求的 done/fail 回调,与 callback/errCallback 可能有区别,具体取决于 fnAjaxDone 与 fnAjaxFail 回调的实现 138 | */ 139 | function requestAjax(config, callback, errCallback, fnCB) { 140 | var $p = (0, _cacheHelper.getPromise)(_settings2.default.isJquery); 141 | 142 | if (!config.url || typeof config.url !== 'string') { 143 | logTrace(ERRURLMSG, config.url); 144 | return $p.reject(ERRURLMSG, config.url); 145 | } 146 | 147 | // data.btnWaiting 的兼容,应使用 config.waiting 参数 148 | if (config.data && config.data.btnWaiting) { 149 | config.waiting = config.waiting || config.data.btnWaiting; 150 | delete config.data.btnWaiting; 151 | } 152 | 153 | // jsonp 兼容 154 | var dataType = 'json'; 155 | 156 | if (/^https?:\/\//.test(config.url) && config.url.search(WIN.location.host) === -1) { 157 | dataType = 'jsonp'; 158 | } 159 | 160 | // 请求前回调,可以引用方式修改 config 161 | if (_settings2.default.fnBeforeAjax) { 162 | _settings2.default.fnBeforeAjax(config); 163 | } 164 | 165 | // 格式化 config.data 166 | var item = void 0; 167 | 168 | if ('object' === _typeof(config.data)) { 169 | for (item in config.data) { 170 | if ('string' !== typeof config.data[item]) { 171 | config.data[item] = JSON.stringify(config.data[item]); 172 | } 173 | } 174 | } 175 | 176 | // ajax 请求前处理,与请求后处理呼应 177 | _settings2.default.fnWaiting(config); 178 | 179 | var startTime = new Date(); 180 | 181 | return $.ajax($.extend(true, { 182 | type: 'GET', 183 | dataType: dataType 184 | }, config.ajaxParam, { 185 | url: config.url, 186 | data: config.data 187 | })).then(function (result) { 188 | var success = _settings2.default.fnAjaxDone(result, function (res) { 189 | if (fnCB instanceof Function) { 190 | fnCB(result); 191 | } 192 | 193 | if (callback instanceof Function) { 194 | callback(res); 195 | } 196 | }, errCallback, config); 197 | 198 | // 为 false,设为失败回调 199 | if (!success) { 200 | return $p.reject(result); 201 | } 202 | 203 | // 为 true 204 | if (true === success) { 205 | return $p.resolve(result); 206 | } 207 | 208 | // 为 Promise 风格回调 209 | if ('function' === typeof success.then) { 210 | // $p = success; 211 | // return $p; 212 | return success; 213 | } 214 | 215 | // 为其它类型,返回 success 内容 216 | return $p.resolve(success); 217 | }, function (err) { 218 | _settings2.default.fnAjaxFail(err, config); 219 | 220 | if (errCallback instanceof Function) { 221 | errCallback(err); 222 | } 223 | 224 | return $p.reject(err); 225 | }).always(function () { 226 | // ajax 完成后处理 227 | _settings2.default.fnWaiting(config, new Date() - startTime); 228 | }); 229 | 230 | // return $p; 231 | } 232 | 233 | // 获取缓存数据的名称 key 234 | function getCacheName(config) { 235 | // 第一个参数为字符串,则为名称,直接返回 config 作为缓存名称 236 | if ((0, _cacheHelper.isString)(config) || !config) { 237 | return config; 238 | } 239 | 240 | var cacheName = config.cacheName; 241 | var dataStr = void 0; 242 | var md5 = WIN.$ && WIN.$.md5 || WIN.md5; 243 | var data = config.data; 244 | 245 | if (!cacheName) { 246 | cacheName = config.url; 247 | 248 | if (cacheName && (typeof data === 'undefined' ? 'undefined' : _typeof(data)) === 'object') { 249 | var strData = JSON.stringify(data); 250 | 251 | if (typeof md5 === 'function') { 252 | strData = md5(strData); 253 | } 254 | 255 | cacheName += dataStr; 256 | } 257 | } 258 | 259 | return cacheName; 260 | } 261 | 262 | // obj 对象中是否包含键为 key 的项 263 | function hasOwnProperty(obj, key) { 264 | return obj.hasOwnProperty(key); 265 | } 266 | 267 | /** 268 | * 全局数据模型 model 269 | * @alias module:adm 270 | * @type {Object} 271 | */ 272 | exports.default = { 273 | /** 274 | * 数据获取,可为远程url、缓存等 275 | * @param {Object} config 为字符串时,从缓存中读取数据,否则为从远程获取数据,参数如下: 276 | * ```js 277 | * { 278 | * url: '', // API url 地址,可为空。为空时应存在 cacheName,此时为从缓存中读取数据 279 | * data: {}, // url 请求参数 280 | * cache: false, // 配置了 url 获取数据时,是否缓存数据。可取值:`false/true/sessionStorage/localStorage` 281 | * fromCache: false, // 配置了 url,是否首先尝试从缓存中读取数据。可取值:`false/true/sessionStorage/localStorage` 282 | * cacheName: '', // 配置了 url 并且 cache 为 true,配置缓存数据的名称,不配置则取值 url (/ 会替换为 . 作为深度路径) 283 | * expires: 0, // 如果 cache 为 true,设置缓存数据的有效期,可为 毫秒数,或 Date 类型日期 284 | * tipConfig: {delay: 2000} // ajax 出错时的提示配置。配置为 false 时,禁用全局的系统提示,包括 成功/出错/404/50x 等 285 | * errAlert: true // ajax error 时是否给出全局提示,优先级高于 settings.errAlert 286 | * waiting: {} // 按钮等待等配置,用于传递给 settings.fnWaiting 方法 287 | * ajaxParam: null // ajax 额外参数扩展,如涉及文件上传等,需要修改部分参数。其中 url 参数无效,应当使用 config.url 288 | * } 289 | * ``` 290 | * @param {Object} callback 成功回调方法 291 | * @param {Object} errCallback 从 url 获取时,失败后需要做一些处理的回调方法 292 | * } 293 | */ 294 | get: function get(config, callback, errCallback) { 295 | var _this = this; 296 | 297 | if (!config) { 298 | return undefined; 299 | } 300 | 301 | var cacheData = void 0; 302 | var $promise = (0, _cacheHelper.getPromise)(_settings2.default.isJquery); 303 | var cacheName = getCacheName(config); 304 | 305 | // 配置了 url,从 url 中获取 306 | if (config.url) { 307 | cacheData = (0, _cacheHelper.getCacheDataByName)(cacheName, config.fromCache); 308 | 309 | // fromCache 为 true,尝试从缓存中获取数据 310 | if (config.fromCache && cacheData) { 311 | if (typeof callback === 'function') { 312 | callback(cacheData); 313 | } 314 | 315 | $promise.resolve(cacheData); 316 | // return cacheData; // 返回数据 317 | return $promise; // 这里改了后不兼容旧的调用,应该注意 bug 的出现! 318 | } 319 | 320 | config.ajaxParam = $.extend(config.ajaxParam, { 321 | type: 'GET' 322 | }); 323 | 324 | return requestAjax(config, callback, errCallback, function (result) { 325 | // cache 为 true,缓存数据 326 | if (config.cache) { 327 | _this.save(cacheName, result, config); 328 | } 329 | }); 330 | } else if (hasOwnProperty(config, 'url')) { 331 | // 配置了 url,但 url 值为空 332 | logTrace(ERRURLMSG, config); 333 | $promise.reject(ERRURLMSG, config); 334 | } else { 335 | // 未配置 url,则必须配置 config.cacheName,或者 config 为字符串(作为cacheName),此时为从缓存中取得数据 336 | cacheData = (0, _cacheHelper.getCacheDataByName)(cacheName, config.fromCache || callback); 337 | 338 | if (callback instanceof Function) { 339 | callback(cacheData); 340 | } 341 | 342 | return cacheData; 343 | } 344 | 345 | return $promise; 346 | }, 347 | 348 | /** 349 | * 设置/存储数据 350 | * @param {Object|String} config - 配置信息。也可以为字符串,则为需存储的数据名称。与 {@link module:adm~get} 的 config 参数相同 351 | * @param {Function|Object} callback - 存储成功后回调方法。当 config 为字符串时,为需存储的数据,或方法执行后返回要存储的数据 352 | * @param {Function|String} errCallback - 从 url 获取时,失败后需要做一些处理的回调方法。config 为字符串时,为配置信息,如 {cacheType, expires} 353 | * @example 354 | * // 存储数据到 localStorage,名称为 testdataName 355 | * adm.save('testdataName', {test: 1}, 'localStorage'); 356 | * @example 357 | * // 存储数据到远程,同时将 API 返回的结果存储到 sessionStorage 358 | * adm.save({url: '/rest/dd', data: {test: 1}, cache: 'sessionStorage'}); 359 | */ 360 | save: function save(config, callback, errCallback) { 361 | var $promise = (0, _cacheHelper.getPromise)(_settings2.default.isJquery); 362 | var resolve = $promise.resolve; 363 | var reject = $promise.reject; 364 | 365 | if (!config) { 366 | resolve(); 367 | return $promise; 368 | } 369 | 370 | var cacheData = void 0; 371 | var cacheName = getCacheName(config, true); 372 | 373 | if ((0, _cacheHelper.isString)(config)) { 374 | // config 为字符串,则作为cacheName 375 | if (callback instanceof Function) { 376 | // 可以存储为回调方法执行后的结果 377 | (0, _cacheHelper.saveTOCache)(cacheName, callback(), errCallback); 378 | } else { 379 | (0, _cacheHelper.saveTOCache)(cacheName, callback, errCallback); 380 | } 381 | resolve(cacheName); 382 | } else if (config.url) { 383 | // 配置了 url,将数据存储到远程 384 | cacheData = (0, _cacheHelper.getCacheDataByName)(cacheName, config.fromCache); 385 | 386 | // fromCache 为 true,尝试从缓存中获取数据 387 | if (config.fromCache && cacheData) { 388 | if (callback instanceof Function) { 389 | callback(cacheData); 390 | } 391 | 392 | resolve(cacheData); 393 | // return cacheData; // 返回数据 394 | return $promise; // 这里改了后不兼容旧的调用,应该注意 bug 的出现! 395 | } 396 | 397 | config.ajaxParam = $.extend({ 398 | type: 'POST' 399 | }, config.ajaxParam); 400 | 401 | return requestAjax(config, callback, errCallback, function (result) { 402 | if (config.cache) { 403 | // 远程存储成功了,本地也需缓存数据时 404 | (0, _cacheHelper.saveTOCache)(cacheName, result, config); 405 | } 406 | }); 407 | } else if (hasOwnProperty(config, 'url')) { 408 | // 配置了url,但 url 值为空 409 | logTrace(ERRURLMSG, config); 410 | reject(ERRURLMSG, config); 411 | } else if (cacheName) { 412 | // 没有设置 url,但设置了 config.cacheName(此时 cacheName=config.cacheName),则保存数据到本地 413 | (0, _cacheHelper.saveTOCache)(cacheName, config.data, config); 414 | 415 | if (callback instanceof Function) { 416 | callback(cacheData); 417 | } 418 | resolve(config.data); 419 | } 420 | 421 | return $promise; 422 | }, 423 | 424 | /** 425 | * 删除一个数据 426 | * @param {Object} config - 为字符串时,作为 cacheName 尝试从缓存中删除数据。否则格式如下: 427 | * ```js 428 | * { 429 | * url: '', // 配置了 url,从远程删除数据,否则从缓存中删除 430 | * cache: false, // 配置了 url,是否还尝试从缓存中删除数据。可取值:false/true/sessionStorage/localStorage 431 | * cacheName: '' // 从缓存中删除数据时,提供其名称。 432 | * } 433 | * ``` 434 | */ 435 | delete: function _delete(config, callback, errCallback) { 436 | if (!config) { 437 | return ''; 438 | } 439 | 440 | var $promise = (0, _cacheHelper.getPromise)(_settings2.default.isJquery); 441 | var cacheName = getCacheName(config); 442 | 443 | if ((0, _cacheHelper.isString)(config) || config instanceof RegExp) { 444 | // 第一个参数为字符串或正则,callback 就是 cacheType 445 | (0, _cacheHelper.deleteCacheDataByName)(config, callback); 446 | // 删除完成都返回执行成功 447 | $promise.resolve(); 448 | } else if (config.url) { 449 | // 配置了 url,从远程删除数据 450 | return requestAjax(config, callback, errCallback, { 451 | type: 'DELETE' 452 | }, function () { 453 | if (config.cache) { 454 | // 远程删除成功了,本地也需清空时 455 | (0, _cacheHelper.deleteCacheDataByName)(cacheName, config.cache); 456 | } 457 | }); 458 | } else if (hasOwnProperty(config, 'url')) { 459 | // 配置了url,但 url 值为空 460 | logTrace(ERRURLMSG, config); 461 | $promise.reject(ERRURLMSG, config); 462 | } else if (cacheName) { 463 | (0, _cacheHelper.deleteCacheDataByName)(cacheName, config.cache); 464 | $promise.resolve(); 465 | } 466 | 467 | return $promise; 468 | }, 469 | 470 | /** 471 | * 返回所有存储中的所有数据 472 | * @param {String} cacheType 存储的类型:sessionStorage、localStorage 或 memory 473 | * @return {Object} 474 | */ 475 | getAll: function getAll(cacheType) { 476 | var cacheStor = (0, _cacheHelper.getCacheStor)(cacheType); 477 | var _cache = {}; 478 | var len = cacheStor.length; 479 | var i = void 0; 480 | var item = void 0, 481 | key = void 0; 482 | 483 | for (i = 0; i < len; i++) { 484 | item = cacheStor.key(i); 485 | 486 | if (!item || 0 !== item.indexOf(_settings2.default.cachePrefix)) { 487 | continue; 488 | } 489 | 490 | key = item.replace(_settings2.default.cachePrefix, ''); 491 | try { 492 | _cache[key] = JSON.parse(cacheStor.getItem(item)); 493 | } catch (e) { 494 | _cache[key] = cacheStor.getItem(item); 495 | } 496 | } 497 | 498 | return _cache; 499 | }, 500 | 501 | /** 502 | * {@link module:dataModel.get} 的 ajax 快捷方法 503 | * @see module:dataModel.get 504 | * @param {String} url url 地址 505 | * @param {Object} data 要传递的参数,可省略 506 | * @param {Function} callback 成功回调 507 | * @param {Function} errCallback 失败回调 508 | * @returns {Promise} 509 | */ 510 | getJSON: function getJSON(url) { 511 | var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 512 | var callback = arguments[2]; 513 | var errCallback = arguments[3]; 514 | 515 | // data 参数可以省略 516 | if (data instanceof Function) { 517 | errCallback = callback; 518 | callback = data; 519 | data = void 0; 520 | } 521 | 522 | return this.get({ 523 | url: url, 524 | data: data 525 | }, callback, errCallback); 526 | }, 527 | 528 | /** 529 | * {@link module:dataModel.save} 的 ajax 快捷方法 530 | * @see module:dataModel.save 531 | * @param {String} url url 地址 532 | * @param {Object} data 要传递的参数 533 | * @param {Function} callback 成功回调 534 | * @param {Function} errCallback 失败回调 535 | * @returns {Promise} 536 | */ 537 | post: function post(url, data, callback, errCallback) { 538 | return this.save({ 539 | url: url, 540 | data: data 541 | }, callback, errCallback); 542 | }, 543 | 544 | /** 545 | * 根据存储类型清空存储的所有数据 546 | * @param {String} cacheType 547 | * @return {scope} this 548 | */ 549 | clear: function clear(cacheType) { 550 | (0, _cacheHelper.deleteCacheDataByName)(new RegExp('.*'), cacheType); 551 | 552 | return this; 553 | }, 554 | 555 | /** 556 | * 修改缓存数据的前缀 557 | * @param {String} prefix 以下划线开头,由字母、数字、或下划线组成 558 | * @param {Boolean} clear[=true] 修改前缀前,是否移除已有的数据 559 | */ 560 | setCachePrefix: function setCachePrefix(prefix) { 561 | var clear = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; 562 | 563 | if (!/^_[_a-zA-Z]*_$/.test(prefix)) { 564 | console.warn('以下划线开头和结尾,由字母、数字、或下划线组成'); 565 | return this; 566 | } 567 | 568 | if (clear) { 569 | this.clear('sessionStorage'); 570 | this.clear('localStorage'); 571 | this.clear(); 572 | } 573 | 574 | _settings2.default.cachePrefix = prefix; 575 | 576 | return this; 577 | }, 578 | 579 | /** 580 | * 设置配置项 581 | * @param {Object} setting 582 | */ 583 | setSettings: function setSettings(setting) { 584 | var item = void 0; 585 | 586 | for (item in setting) { 587 | if ('cachePrefix' === item) { 588 | this.setCachePrefix(setting[item], false); 589 | } else if (hasOwnProperty(_settings2.default, item)) { 590 | _settings2.default[item] = setting[item]; 591 | } 592 | } 593 | 594 | return _settings2.default; 595 | } 596 | }; 597 | module.exports = exports['default']; 598 | 599 | /***/ }), 600 | /* 2 */ 601 | /***/ (function(module, exports) { 602 | 603 | 'use strict'; 604 | 605 | Object.defineProperty(exports, "__esModule", { 606 | value: true 607 | }); 608 | /** 609 | * @desc 配置信息,可以通过 `adm.setSettings` 方法修改 610 | * @alias settings 611 | * @type {Object} 612 | */ 613 | exports.default = { 614 | cachePrefix: '__DM__', // 缓存数据时使用的前缀,用于区别普通数据 615 | isJquery: true, // 是否使用 jQuery 的 $.Deferred。为 false 则使用 Promise 616 | errAlert: true, // ajax 出错时是否全局提示,fnAjaxFail 中使用。全局性开关 617 | errMsg: '', // 系统错误(40x/50x)时的提示信息,为空则使用 err.responseText 618 | alert: function alert(msg) { 619 | // 全局性提示方法注册,可根据项目的 alert 组件进行注册 620 | console.trace(msg); 621 | // window.alert(msg); 622 | }, 623 | /** 624 | * ajax 开始/结束时回调方法 625 | * 例如单击按钮后,在开始时禁用按钮,结束时恢复它; 626 | * 再例如,在 ajax 开始时启用页面动画,结束时关闭页面动画。 627 | * @param {Object} config.waiting - 参数内容可根据 `fnWaiting` 具体的处理来设置 628 | * @param {Number} time - 存在值时在 ajax 结束调用,值为 ajax 消耗的时间;省略时在 ajax 开始前被调用 629 | * @return {void} 630 | */ 631 | fnWaiting: function fnWaiting(config, time) { 632 | // const waiting = config.waiting; 633 | // if ('development' === process.env.NODE_ENV && time) { 634 | // console.trace('ajax 请求消耗时间:', time); 635 | // } 636 | // if (!waiting) { 637 | // return; 638 | // } 639 | // more... 640 | }, 641 | 642 | /** 643 | * ajax 请求开始前回调方法 644 | * @param {Object} config - ajax 请求配置,由于是引用传参,可在这里通过修改它实现 mock 数据等功能 645 | * @return {void} 646 | */ 647 | fnBeforeAjax: function fnBeforeAjax(config) {}, 648 | 649 | /** 650 | * 通用 ajax 请求返回时回调方法 651 | * 对于基于接口的约定,如这里的示例:以 `code` 为 `200` 认为是成功的数据,否则为出错 652 | * @param {Object} result - ajax 返回的数据结果 653 | * @param {Function} callback - 成功回调方法 654 | * @param {Function} errCallback - 出错回调方法 655 | * @param {Object} config - ajax 请求参数配置,即 `adm.get/save` 的第一个参数 656 | * @returns {Boolean|Object|Promise} 表示成功或失败,或成功后返回的数据(如对 result 处理后返回),或 Promise 风格回调 657 | */ 658 | fnAjaxDone: function fnAjaxDone(result, callback, errCallback, config) { 659 | var success = false; 660 | 661 | if (result && result.code === 200) { 662 | if (callback) { 663 | callback(result); 664 | } 665 | 666 | // code 200 认为成功,否则认为失败 667 | success = true; 668 | } else { 669 | if (errCallback) { 670 | errCallback(result); 671 | } 672 | 673 | // 全局性系统提示,设置为 false,则不提示,适合由用户自定义错误处理的情况 674 | if (config.tipConfig !== false) { 675 | result.message = result.message || '系统错误'; 676 | this.alert(result.message); 677 | } 678 | } 679 | 680 | return success; 681 | }, 682 | 683 | /** 684 | * ajax 失败回调方法,一般为 30x、40x、50x 或返回格式不对、网络中断等 685 | * @param {Object} err 686 | * @param {Object} config 687 | * @return {void} 688 | */ 689 | fnAjaxFail: function fnAjaxFail(err, config) { 690 | var msg = err.responseText || err.statusText || ''; 691 | 692 | if (msg.length > 300) { 693 | msg = msg.slice(0, 300) + '...'; 694 | } 695 | 696 | if (0 === err.status) { 697 | this.alert('登录超时'); 698 | // window.location.reload(); 699 | } else if (config.errAlert || void 0 === config.errAlert && this.errAlert) { 700 | // errAlert = false 时禁止 40x/50x 等错误的全局提示 701 | this.alert(config.errMsg || this.errMsg || '数据请求失败: ' + msg); 702 | } 703 | } 704 | }; 705 | module.exports = exports['default']; 706 | 707 | /***/ }), 708 | /* 3 */ 709 | /***/ (function(module, exports, __webpack_require__) { 710 | 711 | 'use strict'; 712 | 713 | Object.defineProperty(exports, "__esModule", { 714 | value: true 715 | }); 716 | 717 | var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; /** 718 | * cache helper 719 | */ 720 | 721 | 722 | exports.getCacheStor = getCacheStor; 723 | exports.getCacheDataByName = getCacheDataByName; 724 | exports.deleteCacheDataByName = deleteCacheDataByName; 725 | exports.saveTOCache = saveTOCache; 726 | exports.isString = isString; 727 | exports.getPromise = getPromise; 728 | 729 | var _settings = __webpack_require__(2); 730 | 731 | var _settings2 = _interopRequireDefault(_settings); 732 | 733 | var _DataCache = __webpack_require__(4); 734 | 735 | var _DataCache2 = _interopRequireDefault(_DataCache); 736 | 737 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 738 | 739 | // 缓存数据对象。为了避免混淆,只缓存至一级结构 740 | var dataCache = new _DataCache2.default(); 741 | 742 | // 获取时间戳 743 | function getTime(t) { 744 | return t ? t.getTime() : new Date().getTime(); 745 | } 746 | 747 | /** 748 | * 修正 cacheName 749 | * @param {String} cacheName 原始的值,可能是任意格式 750 | * @return {String} 修正后的 cacheName,以 cachePrefix 开头 751 | */ 752 | function adjustCacheName(cacheName) { 753 | if (!cacheName) { 754 | return ''; 755 | } 756 | 757 | cacheName = encodeURIComponent(('' + cacheName).replace(/\//g, '.').replace(/^\./, '').replace(/(^\s+|\s+$)/g, '')); 758 | if (cacheName.indexOf(_settings2.default.cachePrefix)) { 759 | // cacheName.indexOf(settings.cachePrefix) !== 0 加上前缀 760 | cacheName = _settings2.default.cachePrefix + cacheName; 761 | } 762 | 763 | return cacheName; 764 | } 765 | /** 766 | * 根据 cacheType 取得 cacheStorage 对象 767 | * @param {String} cacheType 768 | * @return {Object} 769 | */ 770 | function getCacheStor(cacheType) { 771 | var cacheStor = dataCache; 772 | 773 | if (~['sessionStorage', 'localStorage'].indexOf(cacheType)) { 774 | cacheStor = window[cacheType] || cacheStor; 775 | } 776 | 777 | return cacheStor; 778 | } 779 | /** 780 | * 根据 cacheName 名称层级获取对应 dataCache 中的缓存数据 781 | * @param {String} cacheName - 名称,以 . 分割层级,如 ups.pa.query.tags.group 782 | * @param {String} cacheType - 缓存类型:sessionStorage、localStorage 、 memory(默认) 783 | * @return {*} 返回读取到的数据 784 | */ 785 | function getCacheDataByName(cacheName, cacheType) { 786 | var data = void 0; 787 | var undefinedVal = void 0; 788 | var cacheStor = getCacheStor(cacheType); 789 | 790 | if (!(cacheName = adjustCacheName(cacheName))) { 791 | return data; 792 | } 793 | 794 | data = cacheStor.getItem(cacheName); 795 | try { 796 | data = JSON.parse(data); 797 | } catch (e) { 798 | data = data; 799 | } 800 | 801 | // 缓存的数据设置了有效期 data._e 802 | if (data && data._e) { 803 | // console.log(getTime() - data._e, getTime(), data._e); 804 | 805 | if (getTime() - data._e < 0) { 806 | return data.d; 807 | } 808 | // 已过期,数据无效了,移除它 809 | cacheStor.removeItem(cacheName); 810 | 811 | return undefinedVal; 812 | } 813 | 814 | return data || undefinedVal; 815 | } 816 | /** 817 | * 根据 cacheName 名称尝试移除缓存中存在的数据 818 | * @param {String|RegExp} cacheName - 名称,以 . 分割层级,如 ups.pa.query.tags.group。支持正则匹配 819 | * @param {String} cacheType - 缓存类型:sessionStorage、localStorage 、 memory(默认) 820 | * @return {*} 821 | */ 822 | function deleteCacheDataByName(cacheName, cacheType) { 823 | var cacheStor = getCacheStor(cacheType); 824 | var item = void 0, 825 | i = void 0, 826 | len = void 0; 827 | 828 | // 为正则,支持模糊删除 829 | if (cacheName instanceof RegExp) { 830 | len = cacheStor.length; 831 | 832 | for (i = 0; i < len; i++) { 833 | item = cacheStor.key(i); 834 | 835 | if (!item || // 兼容 836 | item.indexOf(_settings2.default.cachePrefix) !== 0 || // 过滤前缀 837 | !cacheName.test(item.slice(_settings2.default.cachePrefix.length)) // 规则检测 838 | ) { 839 | continue; 840 | } 841 | 842 | // 符合规则,移除 843 | cacheStor.removeItem(item); 844 | } 845 | 846 | return; 847 | } 848 | 849 | // 精确的查找与删除 850 | if (!(cacheName = adjustCacheName(cacheName))) { 851 | return; 852 | } 853 | 854 | cacheStor.removeItem(cacheName); 855 | } 856 | /** 857 | * 存储数据到本地 858 | * @param {String} cacheName - 用于存储的名称 859 | * @param {*} data - 任意类型的数据 860 | * @param {String} cacheType - 存储类型,支持三种方式:sessionStorage、localStorage 和内存中(默认) 861 | */ 862 | function saveTOCache(cacheName, data) { 863 | var cfg = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; 864 | 865 | if (!(cacheName = adjustCacheName(cacheName))) { 866 | return; 867 | } 868 | 869 | // console.log(cacheName, data, cfg); 870 | 871 | var cacheType = cfg.cache, 872 | expires = cfg.expires; 873 | 874 | var cacheStor = getCacheStor(cacheType); 875 | 876 | // expires 应为毫秒整数 877 | if (+expires) { 878 | data = { 879 | d: data, 880 | _e: expires instanceof Date ? getTime(expires) : getTime() + expires 881 | }; 882 | } 883 | 884 | if (cacheStor === dataCache) { 885 | // 存到内存 dataCache 886 | cacheStor.setItem(cacheName, data); 887 | } else { 888 | cacheStor.setItem(cacheName, JSON.stringify(data)); 889 | } 890 | } 891 | 892 | /** 893 | * 是否为类字符串 894 | */ 895 | function isString(text) { 896 | var type = typeof text === 'undefined' ? 'undefined' : _typeof(text); 897 | 898 | return 'string' === type || 'number' === type; 899 | } 900 | /** 901 | * 返回包装done/fail API语法糖的 Promise 902 | * @param {Boolean} isJquery 是否为 jQuery,为true 则返回 $.Deferred 903 | * @return {Promise} 904 | */ 905 | function getPromise(isJquery) { 906 | if (isJquery) { 907 | return $.Deferred(); 908 | } 909 | 910 | var resolve = void 0, 911 | reject = void 0; 912 | var $p = new window.Promise(function (rs, rj) { 913 | resolve = rs; 914 | reject = rj; 915 | }); 916 | 917 | $p.resolve = resolve; 918 | $p.reject = reject; 919 | 920 | $p.done = function (cb) { 921 | return $p.then(cb); 922 | }; 923 | 924 | $p.fail = function (cb) { 925 | return $p.then(null, cb); 926 | }; 927 | 928 | $p.always = function (cb) { 929 | return $p.then(cb, cb); 930 | }; 931 | 932 | return $p; 933 | } 934 | 935 | /***/ }), 936 | /* 4 */ 937 | /***/ (function(module, exports) { 938 | 939 | "use strict"; 940 | 941 | Object.defineProperty(exports, "__esModule", { 942 | value: true 943 | }); 944 | 945 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 946 | 947 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 948 | 949 | /** 950 | * @file 基本的数据缓存类 951 | */ 952 | 953 | /** 954 | * 内存缓存数据对象类,与 `localStorage` API 保持一致 955 | */ 956 | var DataCache = function () { 957 | function DataCache() { 958 | _classCallCheck(this, DataCache); 959 | 960 | this.length = 0; 961 | this.cache = {}; 962 | } 963 | /** 964 | * 获取值 965 | * @param {String} key 966 | * @return {*} 967 | */ 968 | 969 | 970 | _createClass(DataCache, [{ 971 | key: "getItem", 972 | value: function getItem(key) { 973 | return this.cache[key]; 974 | } 975 | /** 976 | * 设置值 977 | * @param {String} key 978 | * @param {*} value 979 | */ 980 | 981 | }, { 982 | key: "setItem", 983 | value: function setItem(key, value) { 984 | if (!this.cache.hasOwnProperty(key)) { 985 | this.length++; 986 | } 987 | this.cache[key] = value; 988 | } 989 | /** 990 | * 删除一个值 991 | * @param {String} key 992 | * @return {void} 993 | */ 994 | 995 | }, { 996 | key: "removeItem", 997 | value: function removeItem(key) { 998 | if (this.cache.hasOwnProperty(key)) { 999 | this.length--; 1000 | delete this.cache[key]; 1001 | } 1002 | } 1003 | /** 1004 | * 清空 1005 | */ 1006 | 1007 | }, { 1008 | key: "clear", 1009 | value: function clear() { 1010 | this.length = 0; 1011 | this.cache = {}; 1012 | } 1013 | /** 1014 | * 取得第 index 个数的 key 1015 | * @param {Number} index 1016 | * @return {*} 1017 | */ 1018 | 1019 | }, { 1020 | key: "key", 1021 | value: function key(index) { 1022 | var key = void 0, 1023 | _index = 0; 1024 | 1025 | for (key in this.cache) { 1026 | if (index === _index) { 1027 | return key; 1028 | } 1029 | _index++; 1030 | } 1031 | 1032 | return null; 1033 | } 1034 | }]); 1035 | 1036 | return DataCache; 1037 | }(); 1038 | 1039 | exports.default = DataCache; 1040 | module.exports = exports['default']; 1041 | 1042 | /***/ }) 1043 | /******/ ]) 1044 | }); 1045 | ; 1046 | //# sourceMappingURL=adm.jquery.js.map -------------------------------------------------------------------------------- /lib/adm.jquery.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["webpack:///webpack/universalModuleDefinition","webpack:///webpack/bootstrap 227c5ed9d5d7a7ff030a","webpack:///./src/adm.jquery.js","webpack:///./src/common/settings.js","webpack:///./src/common/cache-helper.js","webpack:///./src/common/DataCache.js"],"names":["WIN","window","logTrace","console","trace","ERRURLMSG","requestAjax","config","callback","errCallback","fnCB","$p","isJquery","url","reject","data","btnWaiting","waiting","dataType","test","search","location","host","fnBeforeAjax","item","JSON","stringify","fnWaiting","startTime","Date","$","ajax","extend","type","ajaxParam","then","result","success","fnAjaxDone","res","Function","resolve","err","fnAjaxFail","always","getCacheName","cacheName","dataStr","md5","strData","hasOwnProperty","obj","key","get","undefined","cacheData","$promise","fromCache","cache","save","delete","RegExp","getAll","cacheType","cacheStor","_cache","len","length","i","indexOf","cachePrefix","replace","parse","getItem","e","getJSON","post","clear","setCachePrefix","prefix","warn","setSettings","setting","errAlert","errMsg","alert","msg","time","code","tipConfig","message","responseText","statusText","slice","status","getCacheStor","getCacheDataByName","deleteCacheDataByName","saveTOCache","isString","getPromise","dataCache","getTime","t","adjustCacheName","encodeURIComponent","undefinedVal","_e","d","removeItem","cfg","expires","setItem","text","Deferred","Promise","rs","rj","done","cb","fail","DataCache","value","index","_index"],"mappings":"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","file":"adm.jquery.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine(\"adm\", [], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"adm\"] = factory();\n\telse\n\t\troot[\"adm\"] = factory();\n})(this, function() {\nreturn \n\n\n// WEBPACK FOOTER //\n// webpack/universalModuleDefinition"," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId])\n \t\t\treturn installedModules[moduleId].exports;\n\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\texports: {},\n \t\t\tid: moduleId,\n \t\t\tloaded: false\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.loaded = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(0);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 227c5ed9d5d7a7ff030a","/**\n * @file 全局数据模型 model\n * 提供数据的读取、保存/缓存、删除、更新等操作。各模块 model 可继承该模型,以进行模块范围内的数据存取操作。\n * @module adm\n * @author lzwy0820@qq.com\n * @since 2016-03-31\n *\n * @example\n * import adm from 'ajax-data-model';\n * const upsModel = $.extend(true, {}, adm, {aa: 'ccc', restapi: {task_type: '/rest/task/type'}});\n * // 支持的方法:upsModel.get、upsModel.save、upsModel.delete、upsModel.clear\n * // 配置了 url,则都返回 Promise 对象,不管是否缓存\n * upsModel.get({url: '/rest/xxx'}).done().fail().then();\n * // 保存数据到 localStorage 中\n * upsModel.save('appList', [{music: 'test'}], 'localStorage');\n * // 通过名字获取,返回存储的数据或者 undefined\n * upsModel.get('appList');\n * upsModel.get('appList', 'localStorage');\n *\n * @example\n * // 获取 task_type 数据\n * const data = {type: 10};\n * adm.get({\n * url: upsModel.restapi.task_type,\n * data: data,\n * cache: 'sessionStorage', // 缓存到 sessionStorage\n * fromCache: 'sessionStorage', // 获取时优先从 sessionStorage 读取\n * cacheName: 'task_type_' + data.type, // 缓存、从缓存读取时使用的名称\n * expires: 1000 * 60 * 5, // 数据有效时间为 5 分钟\n * }).then((result) => {\n * let taskTypeList = result.value || [];\n * console.log(taskTypeList);\n * }, (err) {\n * console.log(err);\n * });\n */\n'use strict';\n\n// import $ from 'jquery';\n\nimport settings from './common/settings';\nimport {\n getCacheStor,\n deleteCacheDataByName,\n getCacheDataByName,\n saveTOCache,\n isString,\n getPromise\n} from './common/cache-helper';\n\n// 常量定义\nconst WIN = window;\nconst logTrace = WIN.console.trace;\nconst ERRURLMSG = '配置了 URL 参数,但值为空或类型不对';\n\n/**\n * ajax 请求通用方法\n * @param {Object} config - 请求参数配置\n * @param {String} config.url - ajax url,必须存在,`config.ajaxParam` 中配置此参数无效\n * @param {Object} config.ajaxParam - ajax 额外参数扩展,如涉及文件上传等\n * @param {Object} config.data - ajax 请求的参数\n * @param {Object} config.waiting - 用于传递给 settings.fnWaiting 方法使用的参数配置\n * @param {Object} config.tipConfig[true] - ajax 出错时的提示配置。配置为 false 时,禁用全局的系统提示,包括 成功/出错/404/50x 等\n * @param {Object} config.errAlert[true] - ajax error 时是否给出提示\n * @param {Function} callback - ajax 请求成功时回调\n * @param {Function} errCallback - ajax 请求失败或 code !== 200 时回调\n * @param {Object} param - 传递给 ajax 请求的额外参数\n * @param {Function} fnCB - 请求到数据之后的立即回调方法,用于请求成功后需要前置处理的情况\n * @return {Promise} 用于自定义回调处理。\n * 注意:ajax 请求的 done/fail 回调,与 callback/errCallback 可能有区别,具体取决于 fnAjaxDone 与 fnAjaxFail 回调的实现\n */\nfunction requestAjax(config, callback, errCallback, fnCB) {\n const $p = getPromise(settings.isJquery);\n\n if (!config.url || typeof config.url !== 'string') {\n logTrace(ERRURLMSG, config.url);\n return $p.reject(ERRURLMSG, config.url);\n }\n\n // data.btnWaiting 的兼容,应使用 config.waiting 参数\n if (config.data && config.data.btnWaiting) {\n config.waiting = config.waiting || config.data.btnWaiting;\n delete config.data.btnWaiting;\n }\n\n // jsonp 兼容\n let dataType = 'json';\n\n if (/^https?:\\/\\//.test(config.url) && config.url.search(WIN.location.host) === -1) {\n dataType = 'jsonp';\n }\n\n // 请求前回调,可以引用方式修改 config\n if (settings.fnBeforeAjax) {\n settings.fnBeforeAjax(config);\n }\n\n // 格式化 config.data\n let item;\n\n if ('object' === typeof config.data) {\n for (item in config.data) {\n if ('string' !== typeof config.data[item]) {\n config.data[item] = JSON.stringify(config.data[item]);\n }\n }\n }\n\n // ajax 请求前处理,与请求后处理呼应\n settings.fnWaiting(config);\n\n const startTime = new Date();\n\n return $.ajax($.extend(true, {\n type: 'GET',\n dataType\n }, config.ajaxParam, {\n url: config.url,\n data: config.data\n })).then((result) => {\n const success = settings.fnAjaxDone(result, (res) => {\n if (fnCB instanceof Function) {\n fnCB(result);\n }\n\n if (callback instanceof Function) {\n callback(res);\n }\n }, errCallback, config);\n\n // 为 false,设为失败回调\n if (!success) {\n return $p.reject(result);\n }\n\n // 为 true\n if (true === success) {\n return $p.resolve(result);\n }\n\n // 为 Promise 风格回调\n if ('function' === typeof success.then) {\n // $p = success;\n // return $p;\n return success;\n }\n\n // 为其它类型,返回 success 内容\n return $p.resolve(success);\n }, (err) => {\n settings.fnAjaxFail(err, config);\n\n if (errCallback instanceof Function) {\n errCallback(err);\n }\n\n return $p.reject(err);\n }).always(() => {\n // ajax 完成后处理\n settings.fnWaiting(config, new Date() - startTime);\n });\n\n // return $p;\n}\n\n// 获取缓存数据的名称 key\nfunction getCacheName(config) {\n // 第一个参数为字符串,则为名称,直接返回 config 作为缓存名称\n if (isString(config) || !config) {\n return config;\n }\n\n let cacheName = config.cacheName;\n let dataStr;\n const md5 = WIN.$ && WIN.$.md5 || WIN.md5;\n const data = config.data;\n\n if (!cacheName) {\n cacheName = config.url;\n\n if (cacheName && typeof data === 'object') {\n let strData = JSON.stringify(data);\n\n if (typeof md5 === 'function') {\n strData = md5(strData);\n }\n\n cacheName += dataStr;\n }\n }\n\n return cacheName;\n}\n\n// obj 对象中是否包含键为 key 的项\nfunction hasOwnProperty(obj, key) {\n return obj.hasOwnProperty(key);\n}\n\n/**\n * 全局数据模型 model\n * @alias module:adm\n * @type {Object}\n */\nexport default {\n /**\n * 数据获取,可为远程url、缓存等\n * @param {Object} config 为字符串时,从缓存中读取数据,否则为从远程获取数据,参数如下:\n * ```js\n * {\n * url: '', // API url 地址,可为空。为空时应存在 cacheName,此时为从缓存中读取数据\n * data: {}, // url 请求参数\n * cache: false, // 配置了 url 获取数据时,是否缓存数据。可取值:`false/true/sessionStorage/localStorage`\n * fromCache: false, // 配置了 url,是否首先尝试从缓存中读取数据。可取值:`false/true/sessionStorage/localStorage`\n * cacheName: '', // 配置了 url 并且 cache 为 true,配置缓存数据的名称,不配置则取值 url (/ 会替换为 . 作为深度路径)\n * expires: 0, // 如果 cache 为 true,设置缓存数据的有效期,可为 毫秒数,或 Date 类型日期\n * tipConfig: {delay: 2000} // ajax 出错时的提示配置。配置为 false 时,禁用全局的系统提示,包括 成功/出错/404/50x 等\n * errAlert: true // ajax error 时是否给出全局提示,优先级高于 settings.errAlert\n * waiting: {} // 按钮等待等配置,用于传递给 settings.fnWaiting 方法\n * ajaxParam: null // ajax 额外参数扩展,如涉及文件上传等,需要修改部分参数。其中 url 参数无效,应当使用 config.url\n * }\n * ```\n * @param {Object} callback 成功回调方法\n * @param {Object} errCallback 从 url 获取时,失败后需要做一些处理的回调方法\n * }\n */\n get(config, callback, errCallback) {\n if (!config) {\n return undefined;\n }\n\n let cacheData;\n const $promise = getPromise(settings.isJquery);\n const cacheName = getCacheName(config);\n\n // 配置了 url,从 url 中获取\n if (config.url) {\n cacheData = getCacheDataByName(cacheName, config.fromCache);\n\n // fromCache 为 true,尝试从缓存中获取数据\n if (config.fromCache && cacheData) {\n if (typeof callback === 'function') {\n callback(cacheData);\n }\n\n $promise.resolve(cacheData);\n // return cacheData; // 返回数据\n return $promise; // 这里改了后不兼容旧的调用,应该注意 bug 的出现!\n }\n\n config.ajaxParam = $.extend(config.ajaxParam, {\n type: 'GET'\n });\n\n return requestAjax(config, callback, errCallback, (result) => {\n // cache 为 true,缓存数据\n if (config.cache) {\n this.save(cacheName, result, config);\n }\n });\n } else if (hasOwnProperty(config, 'url')) { // 配置了 url,但 url 值为空\n logTrace(ERRURLMSG, config);\n $promise.reject(ERRURLMSG, config);\n } else {\n // 未配置 url,则必须配置 config.cacheName,或者 config 为字符串(作为cacheName),此时为从缓存中取得数据\n cacheData = getCacheDataByName(cacheName, config.fromCache || callback);\n\n if (callback instanceof Function) {\n callback(cacheData);\n }\n\n return cacheData;\n }\n\n return $promise;\n },\n /**\n * 设置/存储数据\n * @param {Object|String} config - 配置信息。也可以为字符串,则为需存储的数据名称。与 {@link module:adm~get} 的 config 参数相同\n * @param {Function|Object} callback - 存储成功后回调方法。当 config 为字符串时,为需存储的数据,或方法执行后返回要存储的数据\n * @param {Function|String} errCallback - 从 url 获取时,失败后需要做一些处理的回调方法。config 为字符串时,为配置信息,如 {cacheType, expires}\n * @example\n * // 存储数据到 localStorage,名称为 testdataName\n * adm.save('testdataName', {test: 1}, 'localStorage');\n * @example\n * // 存储数据到远程,同时将 API 返回的结果存储到 sessionStorage\n * adm.save({url: '/rest/dd', data: {test: 1}, cache: 'sessionStorage'});\n */\n save(config, callback, errCallback) {\n const $promise = getPromise(settings.isJquery);\n const resolve = $promise.resolve;\n const reject = $promise.reject;\n\n if (!config) {\n resolve();\n return $promise;\n }\n\n let cacheData;\n const cacheName = getCacheName(config, true);\n\n if (isString(config)) { // config 为字符串,则作为cacheName\n if (callback instanceof Function) { // 可以存储为回调方法执行后的结果\n saveTOCache(cacheName, callback(), errCallback);\n } else {\n saveTOCache(cacheName, callback, errCallback);\n }\n resolve(cacheName);\n } else if (config.url) { // 配置了 url,将数据存储到远程\n cacheData = getCacheDataByName(cacheName, config.fromCache);\n\n // fromCache 为 true,尝试从缓存中获取数据\n if (config.fromCache && cacheData) {\n if (callback instanceof Function) {\n callback(cacheData);\n }\n\n resolve(cacheData);\n // return cacheData; // 返回数据\n return $promise; // 这里改了后不兼容旧的调用,应该注意 bug 的出现!\n }\n\n config.ajaxParam = $.extend({\n type: 'POST'\n }, config.ajaxParam);\n\n return requestAjax(config, callback, errCallback, (result) => {\n if (config.cache) {\n // 远程存储成功了,本地也需缓存数据时\n saveTOCache(cacheName, result, config);\n }\n });\n } else if (hasOwnProperty(config, 'url')) { // 配置了url,但 url 值为空\n logTrace(ERRURLMSG, config);\n reject(ERRURLMSG, config);\n } else if (cacheName) { // 没有设置 url,但设置了 config.cacheName(此时 cacheName=config.cacheName),则保存数据到本地\n saveTOCache(cacheName, config.data, config);\n\n if (callback instanceof Function) {\n callback(cacheData);\n }\n resolve(config.data);\n }\n\n return $promise;\n },\n /**\n * 删除一个数据\n * @param {Object} config - 为字符串时,作为 cacheName 尝试从缓存中删除数据。否则格式如下:\n * ```js\n * {\n * url: '', // 配置了 url,从远程删除数据,否则从缓存中删除\n * cache: false, // 配置了 url,是否还尝试从缓存中删除数据。可取值:false/true/sessionStorage/localStorage\n * cacheName: '' // 从缓存中删除数据时,提供其名称。\n * }\n * ```\n */\n delete(config, callback, errCallback) {\n if (!config) {\n return '';\n }\n\n const $promise = getPromise(settings.isJquery);\n const cacheName = getCacheName(config);\n\n if (isString(config) || config instanceof RegExp) {\n // 第一个参数为字符串或正则,callback 就是 cacheType\n deleteCacheDataByName(config, callback);\n // 删除完成都返回执行成功\n $promise.resolve();\n } else if (config.url) {\n // 配置了 url,从远程删除数据\n return requestAjax(config, callback, errCallback, {\n type: 'DELETE'\n }, () => {\n if (config.cache) {\n // 远程删除成功了,本地也需清空时\n deleteCacheDataByName(cacheName, config.cache);\n }\n });\n } else if (hasOwnProperty(config, 'url')) { // 配置了url,但 url 值为空\n logTrace(ERRURLMSG, config);\n $promise.reject(ERRURLMSG, config);\n } else if (cacheName) {\n deleteCacheDataByName(cacheName, config.cache);\n $promise.resolve();\n }\n\n return $promise;\n },\n /**\n * 返回所有存储中的所有数据\n * @param {String} cacheType 存储的类型:sessionStorage、localStorage 或 memory\n * @return {Object}\n */\n getAll(cacheType) {\n const cacheStor = getCacheStor(cacheType);\n const _cache = {};\n const len = cacheStor.length;\n let i;\n let item, key;\n\n for (i = 0; i < len; i++) {\n item = cacheStor.key(i);\n\n if (!item || 0 !== item.indexOf(settings.cachePrefix)) {\n continue;\n }\n\n key = item.replace(settings.cachePrefix, '');\n try {\n _cache[key] = JSON.parse(cacheStor.getItem(item));\n } catch (e) {\n _cache[key] = cacheStor.getItem(item);\n }\n }\n\n return _cache;\n },\n /**\n * {@link module:dataModel.get} 的 ajax 快捷方法\n * @see module:dataModel.get\n * @param {String} url url 地址\n * @param {Object} data 要传递的参数,可省略\n * @param {Function} callback 成功回调\n * @param {Function} errCallback 失败回调\n * @returns {Promise}\n */\n getJSON(url, data = {}, callback, errCallback) {\n // data 参数可以省略\n if (data instanceof Function) {\n errCallback = callback;\n callback = data;\n data = void 0;\n }\n\n return this.get({\n url,\n data\n }, callback, errCallback);\n },\n /**\n * {@link module:dataModel.save} 的 ajax 快捷方法\n * @see module:dataModel.save\n * @param {String} url url 地址\n * @param {Object} data 要传递的参数\n * @param {Function} callback 成功回调\n * @param {Function} errCallback 失败回调\n * @returns {Promise}\n */\n post(url, data, callback, errCallback) {\n return this.save({\n url,\n data\n }, callback, errCallback);\n },\n /**\n * 根据存储类型清空存储的所有数据\n * @param {String} cacheType\n * @return {scope} this\n */\n clear(cacheType) {\n deleteCacheDataByName(new RegExp('.*'), cacheType);\n\n return this;\n },\n /**\n * 修改缓存数据的前缀\n * @param {String} prefix 以下划线开头,由字母、数字、或下划线组成\n * @param {Boolean} clear[=true] 修改前缀前,是否移除已有的数据\n */\n setCachePrefix(prefix, clear = true) {\n if (!/^_[_a-zA-Z]*_$/.test(prefix)) {\n console.warn('以下划线开头和结尾,由字母、数字、或下划线组成');\n return this;\n }\n\n if (clear) {\n this.clear('sessionStorage');\n this.clear('localStorage');\n this.clear();\n }\n\n settings.cachePrefix = prefix;\n\n return this;\n },\n /**\n * 设置配置项\n * @param {Object} setting\n */\n setSettings(setting) {\n let item;\n\n for (item in setting) {\n if ('cachePrefix' === item) {\n this.setCachePrefix(setting[item], false);\n } else if (hasOwnProperty(settings, item)) {\n settings[item] = setting[item];\n }\n }\n\n return settings;\n }\n};\n\n\n\n// WEBPACK FOOTER //\n// ./src/adm.jquery.js","/**\n * @desc 配置信息,可以通过 `adm.setSettings` 方法修改\n * @alias settings\n * @type {Object}\n */\nexport default {\n cachePrefix: '__DM__', // 缓存数据时使用的前缀,用于区别普通数据\n isJquery: true, // 是否使用 jQuery 的 $.Deferred。为 false 则使用 Promise\n errAlert: true, // ajax 出错时是否全局提示,fnAjaxFail 中使用。全局性开关\n errMsg: '', // 系统错误(40x/50x)时的提示信息,为空则使用 err.responseText\n alert: (msg) => { // 全局性提示方法注册,可根据项目的 alert 组件进行注册\n console.trace(msg);\n // window.alert(msg);\n },\n /**\n * ajax 开始/结束时回调方法\n * 例如单击按钮后,在开始时禁用按钮,结束时恢复它;\n * 再例如,在 ajax 开始时启用页面动画,结束时关闭页面动画。\n * @param {Object} config.waiting - 参数内容可根据 `fnWaiting` 具体的处理来设置\n * @param {Number} time - 存在值时在 ajax 结束调用,值为 ajax 消耗的时间;省略时在 ajax 开始前被调用\n * @return {void}\n */\n fnWaiting(config, time) {\n // const waiting = config.waiting;\n // if ('development' === process.env.NODE_ENV && time) {\n // console.trace('ajax 请求消耗时间:', time);\n // }\n // if (!waiting) {\n // return;\n // }\n // more...\n },\n /**\n * ajax 请求开始前回调方法\n * @param {Object} config - ajax 请求配置,由于是引用传参,可在这里通过修改它实现 mock 数据等功能\n * @return {void}\n */\n fnBeforeAjax(config) {},\n /**\n * 通用 ajax 请求返回时回调方法\n * 对于基于接口的约定,如这里的示例:以 `code` 为 `200` 认为是成功的数据,否则为出错\n * @param {Object} result - ajax 返回的数据结果\n * @param {Function} callback - 成功回调方法\n * @param {Function} errCallback - 出错回调方法\n * @param {Object} config - ajax 请求参数配置,即 `adm.get/save` 的第一个参数\n * @returns {Boolean|Object|Promise} 表示成功或失败,或成功后返回的数据(如对 result 处理后返回),或 Promise 风格回调\n */\n fnAjaxDone(result, callback, errCallback, config) {\n let success = false;\n\n if (result && result.code === 200) {\n if (callback) {\n callback(result);\n }\n\n // code 200 认为成功,否则认为失败\n success = true;\n } else {\n if (errCallback) {\n errCallback(result);\n }\n\n // 全局性系统提示,设置为 false,则不提示,适合由用户自定义错误处理的情况\n if (config.tipConfig !== false) {\n result.message = result.message || '系统错误';\n this.alert(result.message);\n }\n }\n\n return success;\n },\n /**\n * ajax 失败回调方法,一般为 30x、40x、50x 或返回格式不对、网络中断等\n * @param {Object} err\n * @param {Object} config\n * @return {void}\n */\n fnAjaxFail(err, config) {\n let msg = err.responseText || err.statusText || '';\n\n if (msg.length > 300) {\n msg = msg.slice(0, 300) + '...';\n }\n\n if (0 === err.status) {\n this.alert('登录超时');\n // window.location.reload();\n } else if (config.errAlert || (void 0) === config.errAlert && this.errAlert) {\n // errAlert = false 时禁止 40x/50x 等错误的全局提示\n this.alert(config.errMsg || this.errMsg || ('数据请求失败: ' + msg));\n }\n }\n};\n\n\n\n// WEBPACK FOOTER //\n// ./src/common/settings.js","/**\n * cache helper\n */\nimport settings from './settings';\nimport DataCache from './DataCache';\n\n// 缓存数据对象。为了避免混淆,只缓存至一级结构\nconst dataCache = new DataCache();\n\n// 获取时间戳\nfunction getTime(t) {\n return t ? t.getTime() : (new Date()).getTime();\n}\n\n/**\n * 修正 cacheName\n * @param {String} cacheName 原始的值,可能是任意格式\n * @return {String} 修正后的 cacheName,以 cachePrefix 开头\n */\nfunction adjustCacheName(cacheName) {\n if (!cacheName) {\n return '';\n }\n\n cacheName = encodeURIComponent(('' + cacheName).replace(/\\//g, '.').replace(/^\\./, '').replace(/(^\\s+|\\s+$)/g, ''));\n if (cacheName.indexOf(settings.cachePrefix)) {\n // cacheName.indexOf(settings.cachePrefix) !== 0 加上前缀\n cacheName = settings.cachePrefix + cacheName;\n }\n\n return cacheName;\n}\n/**\n * 根据 cacheType 取得 cacheStorage 对象\n * @param {String} cacheType\n * @return {Object}\n */\nexport function getCacheStor(cacheType) {\n let cacheStor = dataCache;\n\n if (~['sessionStorage', 'localStorage'].indexOf(cacheType)) {\n cacheStor = window[cacheType] || cacheStor;\n }\n\n return cacheStor;\n}\n/**\n * 根据 cacheName 名称层级获取对应 dataCache 中的缓存数据\n * @param {String} cacheName - 名称,以 . 分割层级,如 ups.pa.query.tags.group\n * @param {String} cacheType - 缓存类型:sessionStorage、localStorage 、 memory(默认)\n * @return {*} 返回读取到的数据\n */\nexport function getCacheDataByName(cacheName, cacheType) {\n let data;\n const undefinedVal = void 0;\n const cacheStor = getCacheStor(cacheType);\n\n if (!(cacheName = adjustCacheName(cacheName))) {\n return data;\n }\n\n data = cacheStor.getItem(cacheName);\n try {\n data = JSON.parse(data);\n } catch (e) {\n data = data;\n }\n\n // 缓存的数据设置了有效期 data._e\n if (data && data._e) {\n // console.log(getTime() - data._e, getTime(), data._e);\n\n if (getTime() - data._e < 0) {\n return data.d;\n }\n // 已过期,数据无效了,移除它\n cacheStor.removeItem(cacheName);\n\n return undefinedVal;\n }\n\n return data || undefinedVal;\n}\n/**\n * 根据 cacheName 名称尝试移除缓存中存在的数据\n * @param {String|RegExp} cacheName - 名称,以 . 分割层级,如 ups.pa.query.tags.group。支持正则匹配\n * @param {String} cacheType - 缓存类型:sessionStorage、localStorage 、 memory(默认)\n * @return {*}\n */\nexport function deleteCacheDataByName(cacheName, cacheType) {\n const cacheStor = getCacheStor(cacheType);\n let item,\n i,\n len;\n\n // 为正则,支持模糊删除\n if (cacheName instanceof RegExp) {\n len = cacheStor.length;\n\n for (i = 0; i < len; i++) {\n item = cacheStor.key(i);\n\n if (\n !item || // 兼容\n item.indexOf(settings.cachePrefix) !== 0 || // 过滤前缀\n !cacheName.test(item.slice(settings.cachePrefix.length)) // 规则检测\n ) {\n continue;\n }\n\n // 符合规则,移除\n cacheStor.removeItem(item);\n }\n\n return;\n }\n\n // 精确的查找与删除\n if (!(cacheName = adjustCacheName(cacheName))) {\n return;\n }\n\n cacheStor.removeItem(cacheName);\n}\n/**\n * 存储数据到本地\n * @param {String} cacheName - 用于存储的名称\n * @param {*} data - 任意类型的数据\n * @param {String} cacheType - 存储类型,支持三种方式:sessionStorage、localStorage 和内存中(默认)\n */\nexport function saveTOCache(cacheName, data, cfg = {}) {\n if (!(cacheName = adjustCacheName(cacheName))) {\n return;\n }\n\n // console.log(cacheName, data, cfg);\n\n const {cache: cacheType, expires} = cfg;\n const cacheStor = getCacheStor(cacheType);\n\n // expires 应为毫秒整数\n if (+expires) {\n data = {\n d: data,\n _e: (expires instanceof Date) ? getTime(expires) : (getTime() + expires)\n };\n }\n\n if (cacheStor === dataCache) {\n // 存到内存 dataCache\n cacheStor.setItem(cacheName, data);\n } else {\n cacheStor.setItem(cacheName, JSON.stringify(data));\n }\n}\n\n/**\n * 是否为类字符串\n */\nexport function isString(text) {\n const type = typeof text;\n\n return 'string' === type || 'number' === type;\n}\n/**\n * 返回包装done/fail API语法糖的 Promise\n * @param {Boolean} isJquery 是否为 jQuery,为true 则返回 $.Deferred\n * @return {Promise}\n */\nexport function getPromise(isJquery) {\n if (isJquery) {\n return $.Deferred();\n }\n\n let resolve, reject;\n const $p = new window.Promise((rs, rj) => {\n resolve = rs;\n reject = rj;\n });\n\n $p.resolve = resolve;\n $p.reject = reject;\n\n $p.done = function (cb) {\n return $p.then(cb);\n };\n\n $p.fail = function (cb) {\n return $p.then(null, cb);\n };\n\n $p.always = function (cb) {\n return $p.then(cb, cb);\n };\n\n return $p;\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/common/cache-helper.js","/**\n * @file 基本的数据缓存类\n */\n\n/**\n * 内存缓存数据对象类,与 `localStorage` API 保持一致\n */\nclass DataCache {\n constructor() {\n this.length = 0;\n this.cache = {};\n }\n /**\n * 获取值\n * @param {String} key\n * @return {*}\n */\n getItem(key) {\n return this.cache[key];\n }\n /**\n * 设置值\n * @param {String} key\n * @param {*} value\n */\n setItem(key, value) {\n if (!this.cache.hasOwnProperty(key)) {\n this.length++;\n }\n this.cache[key] = value;\n }\n /**\n * 删除一个值\n * @param {String} key\n * @return {void}\n */\n removeItem(key) {\n if (this.cache.hasOwnProperty(key)) {\n this.length--;\n delete this.cache[key];\n }\n }\n /**\n * 清空\n */\n clear() {\n this.length = 0;\n this.cache = {};\n }\n /**\n * 取得第 index 个数的 key\n * @param {Number} index\n * @return {*}\n */\n key(index) {\n let key, _index = 0;\n\n for (key in this.cache) {\n if (index === _index) {\n return key;\n }\n _index++;\n }\n\n return null;\n }\n}\n\nexport default DataCache;\n\n\n\n// WEBPACK FOOTER //\n// ./src/common/DataCache.js"],"sourceRoot":""} --------------------------------------------------------------------------------