├── .env
├── .env.production
├── .gitignore
├── README.md
├── app.js
├── babel.config.js
├── gene.js
├── genec.js
├── package-lock.json
├── package.json
├── public
├── css
│ ├── font-awesome.min.css
│ └── pluto.css
├── favicon.ico
├── index.html
└── js
│ ├── flexible.js
│ ├── mock-min.js
│ └── pluto.js
├── screenshots
├── S91006-001.png
├── S91006-002.png
├── S91006-003.png
├── S91006-004.png
└── S91006-005.png
├── server
├── config
│ ├── config-default.js
│ ├── config-test.js
│ └── index.js
├── controller.js
├── controller
│ ├── dd.js
│ └── order.js
├── cservice
│ └── process.js
├── db.js
├── dto
│ └── resp.js
├── kits
│ ├── cryptoKit.js
│ └── jwtKit.js
├── middleware
│ ├── error.js
│ ├── tokenError.js
│ └── ukey.js
├── model-base
│ ├── abase.js
│ ├── dd_config.js
│ ├── t_order.js
│ └── t_user.js
├── model.js
├── model
│ ├── DdConfig.js
│ ├── order.js
│ └── user.js
└── service.js
├── src
├── App.vue
├── api.js
├── assets
│ ├── finishOrder.png
│ ├── logo.png
│ ├── photo.png
│ ├── success.png
│ └── unfinishOrder.png
├── components
│ └── HelloWorld.vue
├── cube-ui.js
├── main.js
├── router.js
├── store.js
├── theme.styl
└── views
│ ├── About.vue
│ ├── Empty.vue
│ ├── Home.vue
│ ├── OrderAdd.vue
│ ├── OrderList.vue
│ └── Result.vue
├── static
└── dingding-sdk.sql
└── vue.config.js
/.env:
--------------------------------------------------------------------------------
1 | VUE_APP_REMOTE=0
2 | VUE_APP_IP=http://localhost:9021
3 |
--------------------------------------------------------------------------------
/.env.production:
--------------------------------------------------------------------------------
1 | VUE_APP_REMOTE=1
2 | VUE_APP_IP=http://94.191.121.109:9021
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 | # local env files
6 | .env.local
7 | .env.*.local
8 |
9 | # Log files
10 | npm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 |
14 | # Editor directories and files
15 | .idea
16 | .vscode
17 | *.suo
18 | *.ntvs*
19 | *.njsproj
20 | *.sln
21 | *.sw?
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # dingding-nodejs-sdk
2 |
3 | ## Project setup
4 | ```
5 | npm install
6 | ```
7 |
8 | ### Compiles and hot-reloads for development
9 | ```
10 | npm run serve
11 | ```
12 | ```
13 | node app
14 | ```
15 | ### Compiles and minifies for production
16 | ```
17 | npm run build
18 | ```
19 | ## 应用截图
20 |
21 | ## Screenshots
22 | 
23 |
24 | 
25 |
26 | 
27 |
28 | 
29 |
30 | 
31 |
--------------------------------------------------------------------------------
/app.js:
--------------------------------------------------------------------------------
1 | const Koa = require('koa');
2 | var http = require('http');
3 |
4 | var fs = require('fs');
5 | const path = require('path');
6 | const koaBody = require('koa-body');
7 | const cors = require('koa2-cors');
8 | const static = require('koa-static');
9 |
10 | const controller = require('./server/controller');
11 | const ukey = require('./server/middleware/ukey');
12 | const error = require('./server/middleware/error');
13 | const app = new Koa();
14 | const port = 9021
15 | const compress = require('koa-compress')
16 |
17 |
18 | app.use(compress({ threshold: 2048 }));
19 | app.use(koaBody({
20 | multipart: true,
21 | formidable: {
22 | uploadDir:path.join(__dirname,'static/upload/'), // 设置文件上传目录
23 | keepExtensions: true, // 保持文件的后缀
24 | maxFieldsSize:2 * 1024 * 1024, // 文件上传大小
25 | onFileBegin:(name,file) => { // 文件上传前的设置
26 | // console.log(`name: ${name}`);
27 | // console.log(file);
28 | },
29 | }
30 | }));
31 | app.use(cors({
32 | origin: function (ctx) {
33 | return '*'
34 | },
35 | exposeHeaders: ['WWW-Authenticate', 'Server-Authorization'],
36 | maxAge: 1000,
37 | credentials: true,
38 | allowMethods: ['POST', 'PUT', 'PATCH', 'DELETE','OPTIONS'],
39 | allowHeaders: ['*','x-requested-with','x-key','Accept','Content-Type'],
40 | }))
41 |
42 | const staticPath = path.resolve(__dirname, 'static');
43 | app.use(static(staticPath, {
44 | setHeaders: (res, path, stats) => {
45 | if (path.indexOf('jpg') > -1||path.indexOf('png') > -1) {
46 | res.setHeader('Cache-Control', ['private', 'max-age=60']);
47 | }
48 | }
49 | }));
50 | app.use(ukey())
51 | app.use(async (ctx, next) => {
52 | let d=new Date()
53 | console.log(`Process ${d.toString()} ${ctx.request.method} ${ctx.request.url}`);
54 | await next();
55 | });
56 | app.use(controller());
57 | app.use(error())
58 |
59 | http.createServer(app.callback()).listen(port);
60 |
61 | console.log(`app started at port ${port}...`);
62 |
63 | process.on('uncaughtException', function(err) {
64 | console.log(err)
65 | })
66 |
67 | String.prototype.ellipsis=function(len){
68 | return this.length>len?(this.substring(0,len)+'...'):this
69 | }
70 |
71 | function dateFormat(date, fmt) {
72 | if (null == date || undefined == date) return '';
73 | var o = {
74 | "M+": date.getMonth() + 1, //月份
75 | "d+": date.getDate(), //日
76 | "h+": date.getHours(), //小时
77 | "m+": date.getMinutes(), //分
78 | "s+": date.getSeconds(), //秒
79 | "S": date.getMilliseconds() //毫秒
80 | };
81 | if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
82 | for (var k in o)
83 | if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
84 | return fmt;
85 | }
86 |
87 | Date.prototype.toJSON = function () { return dateFormat(this,'yyyy-MM-dd hh:mm:ss')}
88 | Date.prototype.toString = function () { return dateFormat(this,'yyyy-MM-dd hh:mm:ss')}
89 | Date.prototype.toMM = function () { return dateFormat(this,'yyyyMMddhhmmss')}
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/app'
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/gene.js:
--------------------------------------------------------------------------------
1 | var _ = require('lodash');
2 | const SeqAuto = require('sequelize-auto')
3 | const path = require('path')
4 | const fs = require('fs')
5 | const config = require('./server/config');
6 | const tables = process.argv.slice(2)
7 | const dir = 'server'
8 | if (tables.length === 0) {
9 | throw new Error('No table specified\nUsage: node generate_model table1 table2 table3\n')
10 | }
11 |
12 | const auto = new SeqAuto(config.database, config.username, config.password, {
13 | host: config.host,
14 | port: config.port,
15 | dialect: config.dialect,
16 | directory: path.resolve(__dirname, `${dir}/model-base`),
17 | additional: {
18 | timestamps: false
19 | },
20 | tables: tables
21 | })
22 | const modelStrArr = []
23 | for (let table of tables) {
24 | let name = table.includes("t_") ? table.substring(table.indexOf("t_")+1) : table
25 |
26 | console.log(name)
27 | modelStrArr.push({
28 | name: name,
29 | tpl: `
30 | const table='${table}'
31 | const obj=require('../model-base/abase')(table)
32 |
33 |
34 | exports.obj = obj`
35 | })
36 | }
37 |
38 | auto.run(err => {
39 | if (err) {
40 | throw err
41 | }
42 | for (let modelObj of modelStrArr) {
43 | console.log(modelObj)
44 | let file = path.resolve(__dirname, `${dir}/model`) + '/' + _.camelCase(modelObj.name) + '.js'
45 | if (!fs.existsSync(file)) {
46 | fs.writeFileSync(file, modelObj.tpl)
47 | }
48 | }
49 | console.log('\n\nProcess completed successfully.')
50 | console.log('You may need to add these Foreign Keys mannually:\n', auto.foreignKeys)
51 | })
--------------------------------------------------------------------------------
/genec.js:
--------------------------------------------------------------------------------
1 | var _ = require('lodash');
2 |
3 | const path = require('path')
4 | const fs = require('fs')
5 |
6 | const controllers = process.argv.slice(2)
7 | const dir = 'server'
8 | if (controllers.length === 0) {
9 | throw new Error('No controller specified\nUsage: node generate_model controller1 controller2 controller3\n')
10 | }
11 |
12 |
13 | const modelStrArr = []
14 | for (let controller of controllers) {
15 | let admin=controller.indexOf("-admin")>0
16 | let prefix=admin?'/api':'/v1'
17 | let name = admin? controller.substring(0, controller.indexOf("-admin") + 1) : controller
18 |
19 | modelStrArr.push({
20 | name: name,
21 | admin:admin,
22 | tpl: `
23 | const model = require('../model');
24 | const service = require('../service');
25 | const r=require('../dto/resp');
26 | const Op = require('sequelize').Op;
27 | class ${_.capitalize(name)}{
28 | async index(ctx){
29 | let items = [];
30 | ctx.body=r().setItems(items);
31 | }
32 | async show(ctx){
33 | let {id}=ctx.params;
34 | ctx.body=r().setItemMap({id})
35 | }
36 | }
37 | let ${name}=new ${_.capitalize(name)}()
38 | module.exports = {
39 | 'GET ${prefix}/${name}/index': ${name}.index,
40 | 'GET ${prefix}/${name}/:id': ${name}.show,
41 | };`
42 | })
43 | }
44 |
45 |
46 | for (let modelObj of modelStrArr) {
47 | console.log(modelObj)
48 | let filePath = dir + '/' + (modelObj.admin ? 'controller-admin' : 'controller')
49 | let file = path.resolve(__dirname, filePath) + '/' + _.camelCase(modelObj.name) + '.js'
50 | if (!fs.existsSync(file)) {
51 | fs.writeFileSync(file, modelObj.tpl)
52 | }
53 | }
54 | console.log('\n\nProcess completed successfully.')
55 |
56 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "dingding-nodejs-sdk",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build",
8 | "lint": "vue-cli-service lint"
9 | },
10 | "dependencies": {
11 | "axios": "^0.19.0",
12 | "core-js": "^2.6.5",
13 | "cube-ui": "~1.12.15",
14 | "koa": "^2.8.2",
15 | "koa-body": "^4.1.1",
16 | "koa-compress": "^3.0.0",
17 | "koa-router": "^7.4.0",
18 | "koa-static": "^5.0.0",
19 | "koa2-cors": "^2.0.6",
20 | "mysql": "^2.17.1",
21 | "mysql2": "^1.7.0",
22 | "mz": "^2.7.0",
23 | "node-uuid": "^1.4.8",
24 | "sequelize": "^5.19.1",
25 | "sequelize-auto": "^0.4.29",
26 | "vue": "^2.6.10",
27 | "vue-router": "^3.0.3",
28 | "vuex": "^3.0.1"
29 | },
30 | "devDependencies": {
31 | "@vue/cli-plugin-babel": "^3.11.0",
32 | "@vue/cli-plugin-eslint": "^3.11.0",
33 | "@vue/cli-service": "^3.11.0",
34 | "babel-eslint": "^10.0.1",
35 | "eslint": "^5.16.0",
36 | "eslint-plugin-vue": "^5.0.0",
37 | "less": "^3.0.4",
38 | "less-loader": "^5.0.0",
39 | "postcss-px2rem": "^0.3.0",
40 | "stylus": "^0.54.5",
41 | "stylus-loader": "^3.0.2",
42 | "vue-cli-plugin-cube-ui": "^0.2.5",
43 | "vue-template-compiler": "^2.6.10"
44 | },
45 | "eslintConfig": {
46 | "root": true,
47 | "env": {
48 | "node": true
49 | },
50 | "extends": [
51 | "plugin:vue/essential",
52 | "eslint:recommended"
53 | ],
54 | "rules": {
55 | "no-console": "off",
56 | "no-unused-vars": "off",
57 | "no-undef": "off"
58 | },
59 | "parserOptions": {
60 | "parser": "babel-eslint"
61 | }
62 | },
63 | "postcss": {
64 | "plugins": {
65 | "autoprefixer": {},
66 | "postcss-px2rem": {
67 | "remUnit": 37.5
68 | }
69 | }
70 | },
71 | "browserslist": [
72 | "> 1%",
73 | "last 2 versions",
74 | "not ie <= 11",
75 | "Android >= 4.0",
76 | "iOS >= 8"
77 | ],
78 | "transformModules": {
79 | "cube-ui": {
80 | "transform": "cube-ui/src/modules/${member}",
81 | "kebabCase": true
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/public/css/font-awesome.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome
3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
4 | */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.7.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-signing:before,.fa-sign-language:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-pied-piper:before{content:"\f2ae"}.fa-first-order:before{content:"\f2b0"}.fa-yoast:before{content:"\f2b1"}.fa-themeisle:before{content:"\f2b2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\f2b3"}.fa-fa:before,.fa-font-awesome:before{content:"\f2b4"}.fa-handshake-o:before{content:"\f2b5"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-o:before{content:"\f2b7"}.fa-linode:before{content:"\f2b8"}.fa-address-book:before{content:"\f2b9"}.fa-address-book-o:before{content:"\f2ba"}.fa-vcard:before,.fa-address-card:before{content:"\f2bb"}.fa-vcard-o:before,.fa-address-card-o:before{content:"\f2bc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-circle-o:before{content:"\f2be"}.fa-user-o:before{content:"\f2c0"}.fa-id-badge:before{content:"\f2c1"}.fa-drivers-license:before,.fa-id-card:before{content:"\f2c2"}.fa-drivers-license-o:before,.fa-id-card-o:before{content:"\f2c3"}.fa-quora:before{content:"\f2c4"}.fa-free-code-camp:before{content:"\f2c5"}.fa-telegram:before{content:"\f2c6"}.fa-thermometer-4:before,.fa-thermometer:before,.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\f2cb"}.fa-shower:before{content:"\f2cc"}.fa-bathtub:before,.fa-s15:before,.fa-bath:before{content:"\f2cd"}.fa-podcast:before{content:"\f2ce"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-times-rectangle:before,.fa-window-close:before{content:"\f2d3"}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:"\f2d4"}.fa-bandcamp:before{content:"\f2d5"}.fa-grav:before{content:"\f2d6"}.fa-etsy:before{content:"\f2d7"}.fa-imdb:before{content:"\f2d8"}.fa-ravelry:before{content:"\f2d9"}.fa-eercast:before{content:"\f2da"}.fa-microchip:before{content:"\f2db"}.fa-snowflake-o:before{content:"\f2dc"}.fa-superpowers:before{content:"\f2dd"}.fa-wpexplorer:before{content:"\f2de"}.fa-meetup:before{content:"\f2e0"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}
5 |
--------------------------------------------------------------------------------
/public/css/pluto.css:
--------------------------------------------------------------------------------
1 | ::-webkit-scrollbar {
2 | /*隐藏滚轮*/
3 | display: none;
4 | }
5 |
6 | .ub{
7 | display: flex;
8 | }
9 | .ub-v{
10 | display: flex;
11 | flex-direction:column;
12 | }
13 | .uc{
14 | justify-content: center;
15 | align-items: center;
16 | }
17 | .uf-jc{
18 | justify-content: center;
19 | }
20 | .uf-ac{
21 | align-items: center;
22 | }
23 | .ufe{
24 | justify-content: flex-end;
25 | }
26 | .uf-1{
27 | flex:1;
28 | }
29 | .uf-2{
30 | flex:2;
31 | }
32 | .uf-3{
33 | flex:3;
34 | }
35 |
36 | .bar {
37 | height: 10px;
38 | background-color: #eee;
39 | }
40 | .pad{
41 | padding: 10px;
42 | }
43 | .line-text-1{
44 | overflow: hidden;
45 | text-overflow:ellipsis;
46 | white-space: nowrap;
47 | }
48 | .line-text-2{
49 | display: -webkit-box;
50 | -webkit-box-orient: vertical;
51 | -webkit-line-clamp: 2;
52 | overflow: hidden;
53 | }
54 | .line-text-3{
55 | display: -webkit-box;
56 | -webkit-box-orient: vertical;
57 | -webkit-line-clamp: 3;
58 | overflow: hidden;
59 | }
60 |
61 |
62 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pluto1114/dingding-nodejs-SDK/2426dbeff156a20d0dbb9ea07bda3b278db99687/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | dingding-nodejs-sdk
9 |
10 |
11 |
12 |
15 |
16 |
17 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/public/js/flexible.js:
--------------------------------------------------------------------------------
1 | (function flexible (window, document) {
2 | var docEl = document.documentElement
3 | var dpr = window.devicePixelRatio || 1
4 |
5 | // adjust body font size
6 | function setBodyFontSize () {
7 | if (document.body) {
8 | document.body.style.fontSize = (12 * dpr) + 'px'
9 | }
10 | else {
11 | document.addEventListener('DOMContentLoaded', setBodyFontSize)
12 | }
13 | }
14 | setBodyFontSize();
15 |
16 | // set 1rem = viewWidth / 10
17 | function setRemUnit () {
18 | var rem = docEl.clientWidth / 10
19 | docEl.style.fontSize = rem + 'px'
20 | }
21 |
22 | setRemUnit()
23 |
24 | // reset rem unit on page resize
25 | window.addEventListener('resize', setRemUnit)
26 | window.addEventListener('pageshow', function (e) {
27 | if (e.persisted) {
28 | setRemUnit()
29 | }
30 | })
31 |
32 | // detect 0.5px supports
33 | if (dpr >= 2) {
34 | var fakeBody = document.createElement('body')
35 | var testElement = document.createElement('div')
36 | testElement.style.border = '.5px solid transparent'
37 | fakeBody.appendChild(testElement)
38 | docEl.appendChild(fakeBody)
39 | if (testElement.offsetHeight === 1) {
40 | docEl.classList.add('hairlines')
41 | }
42 | docEl.removeChild(fakeBody)
43 | }
44 | }(window, document))
--------------------------------------------------------------------------------
/public/js/mock-min.js:
--------------------------------------------------------------------------------
1 | !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.Mock=e():t.Mock=e()}(this,function(){return function(t){function e(r){if(n[r])return n[r].exports;var a=n[r]={exports:{},id:r,loaded:!1};return t[r].call(a.exports,a,a.exports,e),a.loaded=!0,a.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){var r,a=n(1),o=n(3),u=n(5),i=n(20),l=n(23),s=n(25);"undefined"!=typeof window&&(r=n(27));/*!
2 | Mock - 模拟请求 & 模拟数据
3 | https://github.com/nuysoft/Mock
4 | 墨智 mozhi.gyy@taobao.com nuysoft@gmail.com
5 | */
6 | var c={Handler:a,Random:u,Util:o,XHR:r,RE:i,toJSONSchema:l,valid:s,heredoc:o.heredoc,setup:function(t){return r.setup(t)},_mocked:{}};c.version="1.0.1-beta3",r&&(r.Mock=c),c.mock=function(t,e,n){return 1===arguments.length?a.gen(t):(2===arguments.length&&(n=e,e=void 0),r&&(window.XMLHttpRequest=r),c._mocked[t+(e||"")]={rurl:t,rtype:e,template:n},c)},t.exports=c},function(module,exports,__webpack_require__){var Constant=__webpack_require__(2),Util=__webpack_require__(3),Parser=__webpack_require__(4),Random=__webpack_require__(5),RE=__webpack_require__(20),Handler={extend:Util.extend};Handler.gen=function(t,e,n){e=void 0==e?"":e+"",n=n||{},n={path:n.path||[Constant.GUID],templatePath:n.templatePath||[Constant.GUID++],currentContext:n.currentContext,templateCurrentContext:n.templateCurrentContext||t,root:n.root||n.currentContext,templateRoot:n.templateRoot||n.templateCurrentContext||t};var r,a=Parser.parse(e),o=Util.type(t);return Handler[o]?(r=Handler[o]({type:o,template:t,name:e,parsedName:e?e.replace(Constant.RE_KEY,"$1"):e,rule:a,context:n}),n.root||(n.root=r),r):t},Handler.extend({array:function(t){var e,n,r=[];if(0===t.template.length)return r;if(t.rule.parameters)if(1===t.rule.min&&void 0===t.rule.max)t.context.path.push(t.name),t.context.templatePath.push(t.name),r=Random.pick(Handler.gen(t.template,void 0,{path:t.context.path,templatePath:t.context.templatePath,currentContext:r,templateCurrentContext:t.template,root:t.context.root||r,templateRoot:t.context.templateRoot||t.template})),t.context.path.pop(),t.context.templatePath.pop();else if(t.rule.parameters[2])t.template.__order_index=t.template.__order_index||0,t.context.path.push(t.name),t.context.templatePath.push(t.name),r=Handler.gen(t.template,void 0,{path:t.context.path,templatePath:t.context.templatePath,currentContext:r,templateCurrentContext:t.template,root:t.context.root||r,templateRoot:t.context.templateRoot||t.template})[t.template.__order_index%t.template.length],t.template.__order_index+=+t.rule.parameters[2],t.context.path.pop(),t.context.templatePath.pop();else for(e=0;e1)return this.getValueByKeyPath(key,options);if(templateContext&&"object"==typeof templateContext&&key in templateContext&&placeholder!==templateContext[key])return templateContext[key]=Handler.gen(templateContext[key],key,{currentContext:obj,templateCurrentContext:templateContext}),templateContext[key];if(!(key in Random||lkey in Random||okey in Random))return placeholder;for(var i=0;i1&&(a=e.context.path.slice(0),a.pop(),a=this.normalizePath(a.concat(r))),t=r[r.length-1];for(var o=e.context.root,u=e.context.templateRoot,i=1;ii;i++)if(t=arguments[i])for(e in t)r=u[e],a=t[e],u!==a&&void 0!==a&&(n.isArray(a)||n.isObject(a)?(n.isArray(a)&&(o=r&&n.isArray(r)?r:[]),n.isObject(a)&&(o=r&&n.isObject(r)?r:{}),u[e]=n.extend(o,a)):u[e]=a);return u},n.each=function(t,e,n){var r,a;if("number"===this.type(t))for(r=0;t>r;r++)e(r,r);else if(t.length===+t.length)for(r=0;r1/(t+e)*t?!n:n):Math.random()>=.5},bool:function(t,e,n){return this["boolean"](t,e,n)},natural:function(t,e){return t="undefined"!=typeof t?parseInt(t,10):0,e="undefined"!=typeof e?parseInt(e,10):9007199254740992,Math.round(Math.random()*(e-t))+t},integer:function(t,e){return t="undefined"!=typeof t?parseInt(t,10):-9007199254740992,e="undefined"!=typeof e?parseInt(e,10):9007199254740992,Math.round(Math.random()*(e-t))+t},"int":function(t,e){return this.integer(t,e)},"float":function(t,e,n,r){n=void 0===n?0:n,n=Math.max(Math.min(n,17),0),r=void 0===r?17:r,r=Math.max(Math.min(r,17),0);for(var a=this.integer(t,e)+".",o=0,u=this.natural(n,r);u>o;o++)a+=u-1>o?this.character("number"):this.character("123456789");return parseFloat(a,10)},character:function(t){var e={lower:"abcdefghijklmnopqrstuvwxyz",upper:"ABCDEFGHIJKLMNOPQRSTUVWXYZ",number:"0123456789",symbol:"!@#$%^&*()[]"};return e.alpha=e.lower+e.upper,e.undefined=e.lower+e.upper+e.number+e.symbol,t=e[(""+t).toLowerCase()]||t,t.charAt(this.natural(0,t.length-1))},"char":function(t){return this.character(t)},string:function(t,e,n){var r;switch(arguments.length){case 0:r=this.natural(3,7);break;case 1:r=t,t=void 0;break;case 2:"string"==typeof arguments[0]?r=e:(r=this.natural(t,e),t=void 0);break;case 3:r=this.natural(e,n)}for(var a="",o=0;r>o;o++)a+=this.character(t);return a},str:function(){return this.string.apply(this,arguments)},range:function(t,e,n){arguments.length<=1&&(e=t||0,t=0),n=arguments[2]||1,t=+t,e=+e,n=+n;for(var r=Math.max(Math.ceil((e-t)/n),0),a=0,o=new Array(r);r>a;)o[a++]=t,t+=n;return o}}},function(t,e){var n={yyyy:"getFullYear",yy:function(t){return(""+t.getFullYear()).slice(2)},y:"yy",MM:function(t){var e=t.getMonth()+1;return 10>e?"0"+e:e},M:function(t){return t.getMonth()+1},dd:function(t){var e=t.getDate();return 10>e?"0"+e:e},d:"getDate",HH:function(t){var e=t.getHours();return 10>e?"0"+e:e},H:"getHours",hh:function(t){var e=t.getHours()%12;return 10>e?"0"+e:e},h:function(t){return t.getHours()%12},mm:function(t){var e=t.getMinutes();return 10>e?"0"+e:e},m:"getMinutes",ss:function(t){var e=t.getSeconds();return 10>e?"0"+e:e},s:"getSeconds",SS:function(t){var e=t.getMilliseconds();return 10>e&&"00"+e||100>e&&"0"+e||e},S:"getMilliseconds",A:function(t){return t.getHours()<12?"AM":"PM"},a:function(t){return t.getHours()<12?"am":"pm"},T:"getTime"};t.exports={_patternLetters:n,_rformat:new RegExp(function(){var t=[];for(var e in n)t.push(e);return"("+t.join("|")+")"}(),"g"),_formatDate:function(t,e){return e.replace(this._rformat,function r(e,a){return"function"==typeof n[a]?n[a](t):n[a]in n?r(e,n[a]):t[n[a]]()})},_randomDate:function(t,e){return t=void 0===t?new Date(0):t,e=void 0===e?new Date:e,new Date(Math.random()*(e.getTime()-t.getTime()))},date:function(t){return t=t||"yyyy-MM-dd",this._formatDate(this._randomDate(),t)},time:function(t){return t=t||"HH:mm:ss",this._formatDate(this._randomDate(),t)},datetime:function(t){return t=t||"yyyy-MM-dd HH:mm:ss",this._formatDate(this._randomDate(),t)},now:function(t,e){1===arguments.length&&(/year|month|day|hour|minute|second|week/.test(t)||(e=t,t="")),t=(t||"").toLowerCase(),e=e||"yyyy-MM-dd HH:mm:ss";var n=new Date;switch(t){case"year":n.setMonth(0);case"month":n.setDate(1);case"week":case"day":n.setHours(0);case"hour":n.setMinutes(0);case"minute":n.setSeconds(0);case"second":n.setMilliseconds(0)}switch(t){case"week":n.setDate(n.getDate()-n.getDay())}return this._formatDate(n,e)}}},function(t,e,n){(function(t){t.exports={_adSize:["300x250","250x250","240x400","336x280","180x150","720x300","468x60","234x60","88x31","120x90","120x60","120x240","125x125","728x90","160x600","120x600","300x600"],_screenSize:["320x200","320x240","640x480","800x480","800x480","1024x600","1024x768","1280x800","1440x900","1920x1200","2560x1600"],_videoSize:["720x480","768x576","1280x720","1920x1080"],image:function(t,e,n,r,a){return 4===arguments.length&&(a=r,r=void 0),3===arguments.length&&(a=n,n=void 0),t||(t=this.pick(this._adSize)),e&&~e.indexOf("#")&&(e=e.slice(1)),n&&~n.indexOf("#")&&(n=n.slice(1)),"http://dummyimage.com/"+t+(e?"/"+e:"")+(n?"/"+n:"")+(r?"."+r:"")+(a?"&text="+a:"")},img:function(){return this.image.apply(this,arguments)},_brandColors:{"4ormat":"#fb0a2a","500px":"#02adea","About.me (blue)":"#00405d","About.me (yellow)":"#ffcc33",Addvocate:"#ff6138",Adobe:"#ff0000",Aim:"#fcd20b",Amazon:"#e47911",Android:"#a4c639","Angie's List":"#7fbb00",AOL:"#0060a3",Atlassian:"#003366",Behance:"#053eff","Big Cartel":"#97b538",bitly:"#ee6123",Blogger:"#fc4f08",Boeing:"#0039a6","Booking.com":"#003580",Carbonmade:"#613854",Cheddar:"#ff7243","Code School":"#3d4944",Delicious:"#205cc0",Dell:"#3287c1",Designmoo:"#e54a4f",Deviantart:"#4e6252","Designer News":"#2d72da",Devour:"#fd0001",DEWALT:"#febd17","Disqus (blue)":"#59a3fc","Disqus (orange)":"#db7132",Dribbble:"#ea4c89",Dropbox:"#3d9ae8",Drupal:"#0c76ab",Dunked:"#2a323a",eBay:"#89c507",Ember:"#f05e1b",Engadget:"#00bdf6",Envato:"#528036",Etsy:"#eb6d20",Evernote:"#5ba525","Fab.com":"#dd0017",Facebook:"#3b5998",Firefox:"#e66000","Flickr (blue)":"#0063dc","Flickr (pink)":"#ff0084",Forrst:"#5b9a68",Foursquare:"#25a0ca",Garmin:"#007cc3",GetGlue:"#2d75a2",Gimmebar:"#f70078",GitHub:"#171515","Google Blue":"#0140ca","Google Green":"#16a61e","Google Red":"#dd1812","Google Yellow":"#fcca03","Google+":"#dd4b39",Grooveshark:"#f77f00",Groupon:"#82b548","Hacker News":"#ff6600",HelloWallet:"#0085ca","Heroku (light)":"#c7c5e6","Heroku (dark)":"#6567a5",HootSuite:"#003366",Houzz:"#73ba37",HTML5:"#ec6231",IKEA:"#ffcc33",IMDb:"#f3ce13",Instagram:"#3f729b",Intel:"#0071c5",Intuit:"#365ebf",Kickstarter:"#76cc1e",kippt:"#e03500",Kodery:"#00af81",LastFM:"#c3000d",LinkedIn:"#0e76a8",Livestream:"#cf0005",Lumo:"#576396",Mixpanel:"#a086d3",Meetup:"#e51937",Nokia:"#183693",NVIDIA:"#76b900",Opera:"#cc0f16",Path:"#e41f11","PayPal (dark)":"#1e477a","PayPal (light)":"#3b7bbf",Pinboard:"#0000e6",Pinterest:"#c8232c",PlayStation:"#665cbe",Pocket:"#ee4056",Prezi:"#318bff",Pusha:"#0f71b4",Quora:"#a82400","QUOTE.fm":"#66ceff",Rdio:"#008fd5",Readability:"#9c0000","Red Hat":"#cc0000",Resource:"#7eb400",Rockpack:"#0ba6ab",Roon:"#62b0d9",RSS:"#ee802f",Salesforce:"#1798c1",Samsung:"#0c4da2",Shopify:"#96bf48",Skype:"#00aff0",Snagajob:"#f47a20",Softonic:"#008ace",SoundCloud:"#ff7700","Space Box":"#f86960",Spotify:"#81b71a",Sprint:"#fee100",Squarespace:"#121212",StackOverflow:"#ef8236",Staples:"#cc0000","Status Chart":"#d7584f",Stripe:"#008cdd",StudyBlue:"#00afe1",StumbleUpon:"#f74425","T-Mobile":"#ea0a8e",Technorati:"#40a800","The Next Web":"#ef4423",Treehouse:"#5cb868",Trulia:"#5eab1f",Tumblr:"#34526f","Twitch.tv":"#6441a5",Twitter:"#00acee",TYPO3:"#ff8700",Ubuntu:"#dd4814",Ustream:"#3388ff",Verizon:"#ef1d1d",Vimeo:"#86c9ef",Vine:"#00a478",Virb:"#06afd8","Virgin Media":"#cc0000",Wooga:"#5b009c","WordPress (blue)":"#21759b","WordPress (orange)":"#d54e21","WordPress (grey)":"#464646",Wunderlist:"#2b88d9",XBOX:"#9bc848",XING:"#126567","Yahoo!":"#720e9e",Yandex:"#ffcc00",Yelp:"#c41200",YouTube:"#c4302b",Zalongo:"#5498dc",Zendesk:"#78a300",Zerply:"#9dcc7a",Zootool:"#5e8b1d"},_brandNames:function(){var t=[];for(var e in this._brandColors)t.push(e);return t},dataImage:function(e,n){var r;if("undefined"!=typeof document)r=document.createElement("canvas");else{var a=t.require("canvas");r=new a}var o=r&&r.getContext&&r.getContext("2d");if(!r||!o)return"";e||(e=this.pick(this._adSize)),n=void 0!==n?n:e,e=e.split("x");var u=parseInt(e[0],10),i=parseInt(e[1],10),l=this._brandColors[this.pick(this._brandNames())],s="#FFF",c=14,h="sans-serif";return r.width=u,r.height=i,o.textAlign="center",o.textBaseline="middle",o.fillStyle=l,o.fillRect(0,0,u,i),o.fillStyle=s,o.font="bold "+c+"px "+h,o.fillText(n,u/2,i/2,u),r.toDataURL("image/png")}}}).call(e,n(9)(t))},function(t,e){t.exports=function(t){return t.webpackPolyfill||(t.deprecate=function(){},t.paths=[],t.children=[],t.webpackPolyfill=1),t}},function(t,e,n){var r=n(11),a=n(12);t.exports={color:function(t){return t||a[t]?a[t].nicer:this.hex()},hex:function(){var t=this._goldenRatioColor(),e=r.hsv2rgb(t),n=r.rgb2hex(e[0],e[1],e[2]);return n},rgb:function(){var t=this._goldenRatioColor(),e=r.hsv2rgb(t);return"rgb("+parseInt(e[0],10)+", "+parseInt(e[1],10)+", "+parseInt(e[2],10)+")"},rgba:function(){var t=this._goldenRatioColor(),e=r.hsv2rgb(t);return"rgba("+parseInt(e[0],10)+", "+parseInt(e[1],10)+", "+parseInt(e[2],10)+", "+Math.random().toFixed(2)+")"},hsl:function(){var t=this._goldenRatioColor(),e=r.hsv2hsl(t);return"hsl("+parseInt(e[0],10)+", "+parseInt(e[1],10)+", "+parseInt(e[2],10)+")"},_goldenRatioColor:function(t,e){return this._goldenRatio=.618033988749895,this._hue=this._hue||Math.random(),this._hue+=this._goldenRatio,this._hue%=1,"number"!=typeof t&&(t=.5),"number"!=typeof e&&(e=.95),[360*this._hue,100*t,100*e]}}},function(t,e){t.exports={rgb2hsl:function(t){var e,n,r,a=t[0]/255,o=t[1]/255,u=t[2]/255,i=Math.min(a,o,u),l=Math.max(a,o,u),s=l-i;return l==i?e=0:a==l?e=(o-u)/s:o==l?e=2+(u-a)/s:u==l&&(e=4+(a-o)/s),e=Math.min(60*e,360),0>e&&(e+=360),r=(i+l)/2,n=l==i?0:.5>=r?s/(l+i):s/(2-l-i),[e,100*n,100*r]},rgb2hsv:function(t){var e,n,r,a=t[0],o=t[1],u=t[2],i=Math.min(a,o,u),l=Math.max(a,o,u),s=l-i;return n=0===l?0:s/l*1e3/10,l==i?e=0:a==l?e=(o-u)/s:o==l?e=2+(u-a)/s:u==l&&(e=4+(a-o)/s),e=Math.min(60*e,360),0>e&&(e+=360),r=l/255*1e3/10,[e,n,r]},hsl2rgb:function(t){var e,n,r,a,o,u=t[0]/360,i=t[1]/100,l=t[2]/100;if(0===i)return o=255*l,[o,o,o];n=.5>l?l*(1+i):l+i-l*i,e=2*l-n,a=[0,0,0];for(var s=0;3>s;s++)r=u+1/3*-(s-1),0>r&&r++,r>1&&r--,o=1>6*r?e+6*(n-e)*r:1>2*r?n:2>3*r?e+(n-e)*(2/3-r)*6:e,a[s]=255*o;return a},hsl2hsv:function(t){var e,n,r=t[0],a=t[1]/100,o=t[2]/100;return o*=2,a*=1>=o?o:2-o,n=(o+a)/2,e=2*a/(o+a),[r,100*e,100*n]},hsv2rgb:function(t){var e=t[0]/60,n=t[1]/100,r=t[2]/100,a=Math.floor(e)%6,o=e-Math.floor(e),u=255*r*(1-n),i=255*r*(1-n*o),l=255*r*(1-n*(1-o));switch(r=255*r,a){case 0:return[r,l,u];case 1:return[i,r,u];case 2:return[u,r,l];case 3:return[u,i,r];case 4:return[l,u,r];case 5:return[r,u,i]}},hsv2hsl:function(t){var e,n,r=t[0],a=t[1]/100,o=t[2]/100;return n=(2-a)*o,e=a*o,e/=1>=n?n:2-n,n/=2,[r,100*e,100*n]},rgb2hex:function(t,e,n){return"#"+((256+t<<8|e)<<8|n).toString(16).slice(1)},hex2rgb:function(t){return t="0x"+t.slice(1).replace(t.length>4?t:/./g,"$&$&")|0,[t>>16,t>>8&255,255&t]}}},function(t,e){t.exports={navy:{value:"#000080",nicer:"#001F3F"},blue:{value:"#0000ff",nicer:"#0074D9"},aqua:{value:"#00ffff",nicer:"#7FDBFF"},teal:{value:"#008080",nicer:"#39CCCC"},olive:{value:"#008000",nicer:"#3D9970"},green:{value:"#008000",nicer:"#2ECC40"},lime:{value:"#00ff00",nicer:"#01FF70"},yellow:{value:"#ffff00",nicer:"#FFDC00"},orange:{value:"#ffa500",nicer:"#FF851B"},red:{value:"#ff0000",nicer:"#FF4136"},maroon:{value:"#800000",nicer:"#85144B"},fuchsia:{value:"#ff00ff",nicer:"#F012BE"},purple:{value:"#800080",nicer:"#B10DC9"},silver:{value:"#c0c0c0",nicer:"#DDDDDD"},gray:{value:"#808080",nicer:"#AAAAAA"},black:{value:"#000000",nicer:"#111111"},white:{value:"#FFFFFF",nicer:"#FFFFFF"}}},function(t,e,n){function r(t,e,n,r){return void 0===n?a.natural(t,e):void 0===r?n:a.natural(parseInt(n,10),parseInt(r,10))}var a=n(6),o=n(14);t.exports={paragraph:function(t,e){for(var n=r(3,7,t,e),a=[],o=0;n>o;o++)a.push(this.sentence());return a.join(" ")},cparagraph:function(t,e){for(var n=r(3,7,t,e),a=[],o=0;n>o;o++)a.push(this.csentence());return a.join("")},sentence:function(t,e){for(var n=r(12,18,t,e),a=[],u=0;n>u;u++)a.push(this.word());return o.capitalize(a.join(" "))+"."},csentence:function(t,e){for(var n=r(12,18,t,e),a=[],o=0;n>o;o++)a.push(this.cword());return a.join("")+"。"},word:function(t,e){for(var n=r(3,10,t,e),o="",u=0;n>u;u++)o+=a.character("lower");return o},cword:function(t,e,n){var r,a="的一是在不了有和人这中大为上个国我以要他时来用们生到作地于出就分对成会可主发年动同工也能下过子说产种面而方后多定行学法所民得经十三之进着等部度家电力里如水化高自二理起小物现实加量都两体制机当使点从业本去把性好应开它合还因由其些然前外天政四日那社义事平形相全表间样与关各重新线内数正心反你明看原又么利比或但质气第向道命此变条只没结解问意建月公无系军很情者最立代想已通并提直题党程展五果料象员革位入常文总次品式活设及管特件长求老头基资边流路级少图山统接知较将组见计别她手角期根论运农指几九区强放决西被干做必战先回则任取据处队南给色光门即保治北造百规热领七海口东导器压志世金增争济阶油思术极交受联什认六共权收证改清己美再采转更单风切打白教速花带安场身车例真务具万每目至达走积示议声报斗完类八离华名确才科张信马节话米整空元况今集温传土许步群广石记需段研界拉林律叫且究观越织装影算低持音众书布复容儿须际商非验连断深难近矿千周委素技备半办青省列习响约支般史感劳便团往酸历市克何除消构府称太准精值号率族维划选标写存候毛亲快效斯院查江型眼王按格养易置派层片始却专状育厂京识适属圆包火住调满县局照参红细引听该铁价严龙飞";switch(arguments.length){case 0:t=a,r=1;break;case 1:"string"==typeof arguments[0]?r=1:(r=t,t=a);break;case 2:"string"==typeof arguments[0]?r=e:(r=this.natural(t,e),t=a);break;case 3:r=this.natural(e,n)}for(var o="",u=0;r>u;u++)o+=t.charAt(this.natural(0,t.length-1));return o},title:function(t,e){for(var n=r(3,7,t,e),a=[],o=0;n>o;o++)a.push(this.capitalize(this.word()));return a.join(" ")},ctitle:function(t,e){for(var n=r(3,7,t,e),a=[],o=0;n>o;o++)a.push(this.cword());return a.join("")}}},function(t,e,n){var r=n(3);t.exports={capitalize:function(t){return(t+"").charAt(0).toUpperCase()+(t+"").substr(1)},upper:function(t){return(t+"").toUpperCase()},lower:function(t){return(t+"").toLowerCase()},pick:function(t,e,n){return r.isArray(t)?(void 0===e&&(e=1),void 0===n&&(n=e)):(t=[].slice.call(arguments),e=1,n=1),1===e&&1===n?t[this.natural(0,t.length-1)]:this.shuffle(t,e,n)},shuffle:function(t,e,n){t=t||[];for(var r=t.slice(0),a=[],o=0,u=r.length,i=0;u>i;i++)o=this.natural(0,r.length-1),a.push(r[o]),r.splice(o,1);switch(arguments.length){case 0:case 1:return a;case 2:n=e;case 3:return e=parseInt(e,10),n=parseInt(n,10),a.slice(0,this.natural(e,n))}},order:function a(t){a.cache=a.cache||{},arguments.length>1&&(t=[].slice.call(arguments,0));var e=a.options,n=e.context.templatePath.join("."),r=a.cache[n]=a.cache[n]||{index:0,array:t};return r.array[r.index++%r.array.length]}}},function(t,e){t.exports={first:function(){var t=["James","John","Robert","Michael","William","David","Richard","Charles","Joseph","Thomas","Christopher","Daniel","Paul","Mark","Donald","George","Kenneth","Steven","Edward","Brian","Ronald","Anthony","Kevin","Jason","Matthew","Gary","Timothy","Jose","Larry","Jeffrey","Frank","Scott","Eric"].concat(["Mary","Patricia","Linda","Barbara","Elizabeth","Jennifer","Maria","Susan","Margaret","Dorothy","Lisa","Nancy","Karen","Betty","Helen","Sandra","Donna","Carol","Ruth","Sharon","Michelle","Laura","Sarah","Kimberly","Deborah","Jessica","Shirley","Cynthia","Angela","Melissa","Brenda","Amy","Anna"]);return this.pick(t)},last:function(){var t=["Smith","Johnson","Williams","Brown","Jones","Miller","Davis","Garcia","Rodriguez","Wilson","Martinez","Anderson","Taylor","Thomas","Hernandez","Moore","Martin","Jackson","Thompson","White","Lopez","Lee","Gonzalez","Harris","Clark","Lewis","Robinson","Walker","Perez","Hall","Young","Allen"];return this.pick(t)},name:function(t){return this.first()+" "+(t?this.first()+" ":"")+this.last()},cfirst:function(){var t="王 李 张 刘 陈 杨 赵 黄 周 吴 徐 孙 胡 朱 高 林 何 郭 马 罗 梁 宋 郑 谢 韩 唐 冯 于 董 萧 程 曹 袁 邓 许 傅 沈 曾 彭 吕 苏 卢 蒋 蔡 贾 丁 魏 薛 叶 阎 余 潘 杜 戴 夏 锺 汪 田 任 姜 范 方 石 姚 谭 廖 邹 熊 金 陆 郝 孔 白 崔 康 毛 邱 秦 江 史 顾 侯 邵 孟 龙 万 段 雷 钱 汤 尹 黎 易 常 武 乔 贺 赖 龚 文".split(" ");return this.pick(t)},clast:function(){var t="伟 芳 娜 秀英 敏 静 丽 强 磊 军 洋 勇 艳 杰 娟 涛 明 超 秀兰 霞 平 刚 桂英".split(" ");return this.pick(t)},cname:function(){return this.cfirst()+this.clast()}}},function(t,e){t.exports={url:function(t,e){return(t||this.protocol())+"://"+(e||this.domain())+"/"+this.word()},protocol:function(){return this.pick("http ftp gopher mailto mid cid news nntp prospero telnet rlogin tn3270 wais".split(" "))},domain:function(t){return this.word()+"."+(t||this.tld())},tld:function(){return this.pick("com net org edu gov int mil cn com.cn net.cn gov.cn org.cn 中国 中国互联.公司 中国互联.网络 tel biz cc tv info name hk mobi asia cd travel pro museum coop aero ad ae af ag ai al am an ao aq ar as at au aw az ba bb bd be bf bg bh bi bj bm bn bo br bs bt bv bw by bz ca cc cf cg ch ci ck cl cm cn co cq cr cu cv cx cy cz de dj dk dm do dz ec ee eg eh es et ev fi fj fk fm fo fr ga gb gd ge gf gh gi gl gm gn gp gr gt gu gw gy hk hm hn hr ht hu id ie il in io iq ir is it jm jo jp ke kg kh ki km kn kp kr kw ky kz la lb lc li lk lr ls lt lu lv ly ma mc md mg mh ml mm mn mo mp mq mr ms mt mv mw mx my mz na nc ne nf ng ni nl no np nr nt nu nz om qa pa pe pf pg ph pk pl pm pn pr pt pw py re ro ru rw sa sb sc sd se sg sh si sj sk sl sm sn so sr st su sy sz tc td tf tg th tj tk tm tn to tp tr tt tv tw tz ua ug uk us uy va vc ve vg vn vu wf ws ye yu za zm zr zw".split(" "))},email:function(t){return this.character("lower")+"."+this.word()+"@"+(t||this.word()+"."+this.tld())},ip:function(){return this.natural(0,255)+"."+this.natural(0,255)+"."+this.natural(0,255)+"."+this.natural(0,255)}}},function(t,e,n){var r=n(18),a=["东北","华北","华东","华中","华南","西南","西北"];t.exports={region:function(){return this.pick(a)},province:function(){return this.pick(r).name},city:function(t){var e=this.pick(r),n=this.pick(e.children);return t?[e.name,n.name].join(" "):n.name},county:function(t){var e=this.pick(r),n=this.pick(e.children),a=this.pick(n.children)||{name:"-"};return t?[e.name,n.name,a.name].join(" "):a.name},zip:function(t){for(var e="",n=0;(t||6)>n;n++)e+=this.natural(0,9);return e}}},function(t,e){function n(t){for(var e,n={},r=0;ra;a++)o=t.charAt(a),"\n"===o?(e.seenCR||e.line++,e.column=1,e.seenCR=!1):"\r"===o||"\u2028"===o||"\u2029"===o?(e.line++,e.column=1,e.seenCR=!0):(e.column++,e.seenCR=!1)}return tr!==e&&(tr>e&&(tr=0,er={line:1,column:1,seenCR:!1}),n(er,tr,e),tr=e),er}function b(t){nr>Zn||(Zn>nr&&(nr=Zn,rr=[]),rr.push(t))}function w(t){var e=0;for(t.sort();eZn?(r=t.charAt(Zn),Zn++):(r=null,0===ar&&b(Hn)),null!==r?(Qn=e,n=Sn(r),null===n?(Zn=e,e=n):e=n):(Zn=e,e=kt)):(Zn=e,e=kt),e}function ft(){var e,n,r;return e=Zn,92===t.charCodeAt(Zn)?(n=Dn,Zn++):(n=null,0===ar&&b(qn)),null!==n?(Fn.test(t.charAt(Zn))?(r=t.charAt(Zn),Zn++):(r=null,0===ar&&b(Ln)),null!==r?(Qn=e,n=On(r),null===n?(Zn=e,e=n):e=n):(Zn=e,e=kt)):(Zn=e,e=kt),e}function dt(){var e,n,r,a;if(e=Zn,t.substr(Zn,2)===In?(n=In,Zn+=2):(n=null,0===ar&&b(jn)),null!==n){if(r=[],Nn.test(t.charAt(Zn))?(a=t.charAt(Zn),Zn++):(a=null,0===ar&&b(zn)),null!==a)for(;null!==a;)r.push(a),Nn.test(t.charAt(Zn))?(a=t.charAt(Zn),Zn++):(a=null,0===ar&&b(zn));else r=kt;null!==r?(Qn=e,n=Un(r),null===n?(Zn=e,e=n):e=n):(Zn=e,e=kt)}else Zn=e,e=kt;return e}function mt(){var e,n,r,a;if(e=Zn,t.substr(Zn,2)===Bn?(n=Bn,Zn+=2):(n=null,0===ar&&b(Gn)),null!==n){if(r=[],Xn.test(t.charAt(Zn))?(a=t.charAt(Zn),Zn++):(a=null,0===ar&&b(Kn)),null!==a)for(;null!==a;)r.push(a),Xn.test(t.charAt(Zn))?(a=t.charAt(Zn),Zn++):(a=null,0===ar&&b(Kn));else r=kt;null!==r?(Qn=e,n=Wn(r),null===n?(Zn=e,e=n):e=n):(Zn=e,e=kt)}else Zn=e,e=kt;return e}function gt(){var e,n,r,a;if(e=Zn,t.substr(Zn,2)===Yn?(n=Yn,Zn+=2):(n=null,0===ar&&b($n)),null!==n){if(r=[],Xn.test(t.charAt(Zn))?(a=t.charAt(Zn),Zn++):(a=null,0===ar&&b(Kn)),null!==a)for(;null!==a;)r.push(a),Xn.test(t.charAt(Zn))?(a=t.charAt(Zn),Zn++):(a=null,0===ar&&b(Kn));else r=kt;null!==r?(Qn=e,n=Jn(r),null===n?(Zn=e,e=n):e=n):(Zn=e,e=kt)}else Zn=e,e=kt;return e}function vt(){var e,n;return e=Zn,t.substr(Zn,2)===In?(n=In,Zn+=2):(n=null,0===ar&&b(jn)),null!==n&&(Qn=e,n=Vn()),null===n?(Zn=e,e=n):e=n,e}function xt(){var e,n,r;return e=Zn,92===t.charCodeAt(Zn)?(n=Dn,Zn++):(n=null,0===ar&&b(qn)),null!==n?(t.length>Zn?(r=t.charAt(Zn),Zn++):(r=null,0===ar&&b(Hn)),null!==r?(Qn=e,n=Fe(r),null===n?(Zn=e,e=n):e=n):(Zn=e,e=kt)):(Zn=e,e=kt),e}var yt,bt=arguments.length>1?arguments[1]:{},wt={regexp:C},Ct=C,kt=null,Et="",Rt="|",At='"|"',_t=function(t,e){return e?new r(t,e[1]):t},Mt=function(t,e,n){return new a([t].concat(e).concat([n]))},Pt="^",Tt='"^"',Ht=function(){return new n("start")},St="$",Dt='"$"',qt=function(){return new n("end")},Ft=function(t,e){return new i(t,e)},Lt="Quantifier",Ot=function(t,e){return e&&(t.greedy=!1),t},It="{",jt='"{"',Nt=",",zt='","',Ut="}",Bt='"}"',Gt=function(t,e){return new l(t,e)},Xt=",}",Kt='",}"',Wt=function(t){return new l(t,1/0)},Yt=function(t){return new l(t,t)},$t="+",Jt='"+"',Vt=function(){return new l(1,1/0)},Zt="*",Qt='"*"',te=function(){return new l(0,1/0)},ee="?",ne='"?"',re=function(){return new l(0,1)},ae=/^[0-9]/,oe="[0-9]",ue=function(t){return+t.join("")},ie="(",le='"("',se=")",ce='")"',he=function(t){return t},pe=function(t){return new u(t)},fe="?:",de='"?:"',me=function(t){return new o("non-capture-group",t)},ge="?=",ve='"?="',xe=function(t){return new o("positive-lookahead",t)},ye="?!",be='"?!"',we=function(t){return new o("negative-lookahead",t)},Ce="CharacterSet",ke="[",Ee='"["',Re="]",Ae='"]"',_e=function(t,e){return new s(!!t,e)},Me="CharacterRange",Pe="-",Te='"-"',He=function(t,e){return new c(t,e)},Se="Character",De=/^[^\\\]]/,qe="[^\\\\\\]]",Fe=function(t){return new h(t)},Le=".",Oe='"."',Ie=function(){return new n("any-character")},je="Literal",Ne=/^[^|\\\/.[()?+*$\^]/,ze="[^|\\\\\\/.[()?+*$\\^]",Ue="\\b",Be='"\\\\b"',Ge=function(){return new n("backspace")},Xe=function(){return new n("word-boundary")},Ke="\\B",We='"\\\\B"',Ye=function(){return new n("non-word-boundary")},$e="\\d",Je='"\\\\d"',Ve=function(){return new n("digit")},Ze="\\D",Qe='"\\\\D"',tn=function(){return new n("non-digit")},en="\\f",nn='"\\\\f"',rn=function(){return new n("form-feed")},an="\\n",on='"\\\\n"',un=function(){return new n("line-feed")},ln="\\r",sn='"\\\\r"',cn=function(){return new n("carriage-return")},hn="\\s",pn='"\\\\s"',fn=function(){return new n("white-space")},dn="\\S",mn='"\\\\S"',gn=function(){return new n("non-white-space")},vn="\\t",xn='"\\\\t"',yn=function(){return new n("tab")},bn="\\v",wn='"\\\\v"',Cn=function(){return new n("vertical-tab")},kn="\\w",En='"\\\\w"',Rn=function(){
9 | return new n("word")},An="\\W",_n='"\\\\W"',Mn=function(){return new n("non-word")},Pn="\\c",Tn='"\\\\c"',Hn="any character",Sn=function(t){return new g(t)},Dn="\\",qn='"\\\\"',Fn=/^[1-9]/,Ln="[1-9]",On=function(t){return new m(t)},In="\\0",jn='"\\\\0"',Nn=/^[0-7]/,zn="[0-7]",Un=function(t){return new d(t.join(""))},Bn="\\x",Gn='"\\\\x"',Xn=/^[0-9a-fA-F]/,Kn="[0-9a-fA-F]",Wn=function(t){return new f(t.join(""))},Yn="\\u",$n='"\\\\u"',Jn=function(t){return new p(t.join(""))},Vn=function(){return new n("null-character")},Zn=0,Qn=0,tr=0,er={line:1,column:1,seenCR:!1},nr=0,rr=[],ar=0;if("startRule"in bt){if(!(bt.startRule in wt))throw new Error("Can't start parsing from rule \""+bt.startRule+'".');Ct=wt[bt.startRule]}if(n.offset=x,n.text=v,yt=Ct(),null!==yt&&Zn===t.length)return yt;throw w(rr),Qn=Math.max(Zn,nr),new e(rr,Qn=r;r++)n+=String.fromCharCode(r);return n}var a=n(3),o=n(5),u={extend:a.extend},i=r(97,122),l=r(65,90),s=r(48,57),c=r(32,47)+r(58,64)+r(91,96)+r(123,126),h=r(32,126),p=" \f\n\r \x0B \u2028\u2029",f={"\\w":i+l+s+"_","\\W":c.replace("_",""),"\\s":p,"\\S":function(){for(var t=h,e=0;ea;a++)e+=this.gen(t.body,e,n);return e},quantifier:function(t,e,n){var r=Math.max(t.min,0),a=isFinite(t.max)?t.max:r+o.integer(3,7);return o.integer(r,a)},charset:function(t,e,n){if(t.invert)return this["invert-charset"](t,e,n);var r=o.pick(t.body);return this.gen(r,e,n)},"invert-charset":function(t,e,n){for(var r,a=h,u=0;u=s;s++)a=a.replace(String.fromCharCode(s),"");default:var c=f[r.text];if(c)for(var p=0;p<=c.length;p++)a=a.replace(c[p],"")}return o.pick(a.split(""))},range:function(t,e,n){var r=this.gen(t.start,e,n).charCodeAt(),a=this.gen(t.end,e,n).charCodeAt();return String.fromCharCode(o.integer(r,a))},literal:function(t,e,n){return t.escaped?t.body:t.text},unicode:function(t,e,n){return String.fromCharCode(parseInt(t.code,16))},hex:function(t,e,n){return String.fromCharCode(parseInt(t.code,16))},octal:function(t,e,n){return String.fromCharCode(parseInt(t.code,8))},"back-reference":function(t,e,n){return n[t.code]||""},CONTROL_CHARACTER_MAP:function(){for(var t="@ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \\ ] ^ _".split(" "),e="\x00 \b \n \x0B \f \r ".split(" "),n={},r=0;rr)return!0;var u={path:e,type:t,actual:n,expected:r,action:"is greater than",message:o};return u.message=l.message(u),a.push(u),!1},lessThan:function(t,e,n,r,a,o){if(r>n)return!0;var u={path:e,type:t,actual:n,expected:r,action:"is less to",message:o};return u.message=l.message(u),a.push(u),!1},greaterThanOrEqualTo:function(t,e,n,r,a,o){if(n>=r)return!0;var u={path:e,type:t,actual:n,expected:r,action:"is greater than or equal to",message:o};return u.message=l.message(u),a.push(u),!1},lessThanOrEqualTo:function(t,e,n,r,a,o){if(r>=n)return!0;var u={path:e,type:t,actual:n,expected:r,action:"is less than or equal to",message:o};return u.message=l.message(u),a.push(u),!1}};r.Diff=i,r.Assert=l,t.exports=r},function(t,e,n){t.exports=n(28)},function(t,e,n){function r(){this.custom={events:{},requestHeaders:{},responseHeaders:{}}}function a(){function t(){try{return new window._XMLHttpRequest}catch(t){}}function e(){try{return new window._ActiveXObject("Microsoft.XMLHTTP")}catch(t){}}var n=function(){var t=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,e=/^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,n=location.href,r=e.exec(n.toLowerCase())||[];return t.test(r[1])}();return window.ActiveXObject?!n&&t()||e():t()}function o(t){function e(t,e){return"string"===i.type(t)?t===e:"regexp"===i.type(t)?t.test(e):void 0}for(var n in r.Mock._mocked){var a=r.Mock._mocked[n];if((!a.rurl||e(a.rurl,t.url))&&(!a.rtype||e(a.rtype,t.type.toLowerCase())))return a}}function u(t,e){return i.isFunction(t.template)?t.template(e):r.Mock.mock(t.template)}var i=n(3);window._XMLHttpRequest=window.XMLHttpRequest,window._ActiveXObject=window.ActiveXObject;try{new window.Event("custom")}catch(l){window.Event=function(t,e,n,r){var a=document.createEvent("CustomEvent");return a.initCustomEvent(t,e,n,r),a}}var s={UNSENT:0,OPENED:1,HEADERS_RECEIVED:2,LOADING:3,DONE:4},c="readystatechange loadstart progress abort error load timeout loadend".split(" "),h="timeout withCredentials".split(" "),p="readyState responseURL status statusText responseType response responseText responseXML".split(" "),f={100:"Continue",101:"Switching Protocols",200:"OK",201:"Created",202:"Accepted",203:"Non-Authoritative Information",204:"No Content",205:"Reset Content",206:"Partial Content",300:"Multiple Choice",301:"Moved Permanently",302:"Found",303:"See Other",304:"Not Modified",305:"Use Proxy",307:"Temporary Redirect",400:"Bad Request",401:"Unauthorized",402:"Payment Required",403:"Forbidden",404:"Not Found",405:"Method Not Allowed",406:"Not Acceptable",407:"Proxy Authentication Required",408:"Request Timeout",409:"Conflict",410:"Gone",411:"Length Required",412:"Precondition Failed",413:"Request Entity Too Large",414:"Request-URI Too Long",415:"Unsupported Media Type",416:"Requested Range Not Satisfiable",417:"Expectation Failed",422:"Unprocessable Entity",500:"Internal Server Error",501:"Not Implemented",502:"Bad Gateway",503:"Service Unavailable",504:"Gateway Timeout",505:"HTTP Version Not Supported"};r._settings={timeout:"10-100"},r.setup=function(t){return i.extend(r._settings,t),r._settings},i.extend(r,s),i.extend(r.prototype,s),r.prototype.mock=!0,r.prototype.match=!1,i.extend(r.prototype,{open:function(t,e,n,u,l){function s(t){for(var e=0;e -1) {
48 | value = value.split('#')[0]
49 | }
50 | res[name] = value;
51 | }
52 | return res;
53 | }
54 | function getDDUser() {
55 | if (window.localStorage.dduser)
56 | return JSON.parse(window.localStorage.dduser);
57 | else
58 | return null;
59 | }
60 | function setNavTitle(title) {
61 | dd.ready(function () {
62 | dd.biz.navigation.setTitle({
63 | title: title
64 | });
65 | })
66 |
67 | }
68 |
69 | function setMenu(param, callback) {
70 | dd.ready(function () {
71 | dd.biz.navigation.setMenu({
72 | // backgroundColor : "#ADD8E6",
73 | // textColor : "#6495ed",
74 | items: [
75 | {
76 | "id": "3",
77 | "iconId": "setting",
78 | "text": "disange",
79 | },
80 | {
81 | "id": "4",
82 | "iconId": "time",
83 | "text": "disige"
84 | }
85 | ],
86 | onSuccess: function (data) {
87 | },
88 | onFail: function (err) { }
89 | });
90 | })
91 | }
92 | function setNavRight(param, callback) {
93 | console.log("setNavRight", param.text)
94 | dd.ready(function () {
95 | dd.biz.navigation.setRight({
96 | control: true,//是否控制点击事件,true 控制,false 不控制, 默认false
97 | text: param.text,//控制显示文本,空字符串表示显示默认文本
98 | onSuccess: function (result) {
99 | callback(result);
100 | },
101 | onFail: function (err) { }
102 | });
103 | })
104 | }
105 | function setNavLeft(param, callback) {
106 | dd.ready(function () {
107 | dd.biz.navigation.setLeft({
108 | control: true,//是否控制点击事件,true 控制,false 不控制, 默认false
109 | text: param.text,//控制显示文本,空字符串表示显示默认文本
110 | onSuccess: function (result) {
111 | // callback(result);
112 | dd.biz.navigation.close()
113 | },
114 | onFail: function (err) { }
115 | });
116 | })
117 | }
118 | function hideNavRight() {
119 | dd.ready(function () {
120 | dd.biz.navigation.setRight({
121 | // control: true,
122 | text: ""
123 | });
124 | })
125 | }
126 | function ddscan(param, callback) {
127 | dd.ready(function () {
128 | dd.biz.util.scan({
129 | type: "qrcode", // type 为 all、qrCode、barCode,默认是all。
130 | tips: param.tips, //进入扫码页面显示的自定义文案
131 | onSuccess: function (data) {
132 | callback(data);
133 | },
134 | onFail: function (err) {
135 | }
136 | })
137 | })
138 | }
139 |
140 |
141 |
142 | //dingcce3c449b62ce9ea35c2f4657eb6378f
143 | function requestAuthCode(corpid, callback) {
144 | try {
145 | dd.ready(function () {
146 | console.log('corpid', corpid)
147 | dd.runtime.permission.requestAuthCode({
148 | corpId: corpid,
149 | onSuccess: function (result) {
150 | callback(result)
151 | },
152 | onFail: function (err) {
153 | console.error(err)
154 | }
155 |
156 | });
157 | });
158 | } catch (e) {
159 | console.error(e.message)
160 | }
161 | }
162 | //调取小鱼第三方应用
163 | function ddLaunchApp(jsconfig, app, callback) {
164 |
165 | console.log('ddconfig')
166 | dd.config({
167 | agentId: jsconfig.agentid,
168 | corpId: jsconfig.corpId,
169 | timeStamp: jsconfig.timeStamp,
170 | nonceStr: jsconfig.nonceStr,
171 | signature: jsconfig.signature,
172 | jsApiList: ['device.launcher.launchApp']
173 | });
174 | dd.ready(function () {
175 | console.log('app', app)
176 | dd.device.launcher.launchApp({
177 | app: app,//iOS:应用scheme;Android:应用包名
178 | onSuccess: function (data) {
179 | console.log('success')
180 | callback(data)
181 | },
182 | onFail: function (err) {
183 | console.log('fail', err)
184 | }
185 | });
186 | });
187 |
188 | dd.error(function (err) {
189 | alert('dd error: ' + JSON.stringify(err));
190 | });
191 | }
192 | function ddConfirm(message, callback) {
193 | try {
194 | dd.ready(function () {
195 | dd.device.notification.confirm({
196 | message: message,
197 | title: "提示",
198 | buttonLabels: ['确定', '取消'],
199 | // buttonLabels: buttonLabels,
200 | onSuccess: function (result) {
201 | callback(result)
202 | },
203 | onFail: function (err) { }
204 | });
205 | })
206 | } catch (e) {
207 | console.error(e.message)
208 | }
209 | }
210 | function ddAlert(message, callback) {
211 | dd.device.notification.alert({
212 | message: message,
213 | title: "提示",//可传空
214 | buttonName: "确定",
215 | onSuccess: function () {
216 | //onSuccess将在点击button之后回调
217 | /*回调*/
218 | },
219 | onFail: function (err) { }
220 | });
221 | }
222 | function complexPicker(jsconfig, callback) {
223 | console.log('ddconfig')
224 |
225 | dd.ready(function () {
226 | dd.biz.contact.complexPicker({
227 | title: "选择处理人", //标题
228 | corpId: jsconfig.corpId, //企业的corpId
229 | multiple: false, //是否多选
230 | limitTips: "超出了", //超过限定人数返回提示
231 | appId: jsconfig.agentid, //微应用的Id
232 | permissionType: "GLOBAL", //选人权限,目前只有GLOBAL这个参数
233 | responseUserOnly: true, //返回人,或者返回人和部门
234 | startWithDepartmentId: 0, // 0表示从企业最上层开始
235 | onSuccess: function (result) {
236 | /**
237 | {
238 | selectedCount:1, //选择人数
239 | users:[{"name":"","avatar":"","emplId":""}],//返回选人的列表,列表中的对象包含name(用户名),avatar(用户头像),emplId(用户工号)三个字段
240 | departments:[{"id":,"name":"","number":}]//返回已选部门列表,列表中每个对象包含id(部门id)、name(部门名称)、number(部门人数)
241 | }
242 | */
243 | console.info('complexPicker', result)
244 | callback(result);
245 | },
246 | onFail: function (err) { }
247 | });
248 | })
249 |
250 | dd.error(function (err) {
251 | alert('dd error: ' + JSON.stringify(err));
252 | });
253 |
254 | }
255 |
256 | function pickConversation(jsconfig, callback) {
257 | console.log('ddconfig')
258 | dd.ready(function () {
259 | dd.biz.chat.pickConversation({
260 | corpId: jsconfig.corpId, //企业id
261 | // isConfirm:'false', //是否弹出确认窗口,默认为true
262 | onSuccess: function (result) {
263 | //onSuccess将在选择结束之后调用
264 | // 该cid和服务端开发文档-普通会话消息接口配合使用,而且只能使用一次,之后将失效
265 | /*{
266 | cid: 'xxxx',
267 | title:'xxx'
268 | }*/
269 | console.info('pickConversation', result)
270 | callback(result);
271 | },
272 | onFail: function () { }
273 | })
274 | })
275 |
276 | dd.error(function (err) {
277 | alert('dd error: ' + JSON.stringify(err));
278 | });
279 | }
280 | function chooseConversationByCorpId(jsconfig, callback) {
281 | console.log('ddconfig')
282 | dd.ready(function () {
283 | dd.biz.chat.chooseConversationByCorpId({
284 | corpId: jsconfig.corpId, //企业id
285 | isAllowCreateGroup:false,
286 | filterNotOwnerGroup:false,
287 | onSuccess: function (result) {
288 | //onSuccess将在选择结束之后调用
289 | /*{
290 | chatId: 'xxxx',
291 | title:'xxx'
292 | }*/
293 | console.info('chooseConversationByCorpId', result)
294 | callback(result);
295 | },
296 | onFail: function () { }
297 | })
298 | })
299 |
300 | dd.error(function (err) {
301 | alert('dd error: ' + JSON.stringify(err));
302 | });
303 | }
304 |
305 | function ddAuthconfig(jsconfig, jsApiList) {
306 | console.info('jsApiList',jsApiList)
307 | dd.config({
308 | agentId: jsconfig.agentId,
309 | corpId: jsconfig.corpId,
310 | timeStamp: jsconfig.timeStamp,
311 | nonceStr: jsconfig.nonceStr,
312 | signature: jsconfig.signature,
313 | jsApiList: jsApiList
314 | });
315 | dd.error(function (err) {
316 | alert('dd error: ' + JSON.stringify(err));
317 | });
318 | }
319 | function openSingleChat(jsconfig, userid) {
320 | console.log('ddconfig', jsconfig, userid)
321 |
322 | dd.ready(function () {
323 | dd.biz.chat.openSingleChat({
324 | corpId: jsconfig.corpId, // 企业id,必须是用户所属的企业的corpid
325 | userId: userid, // 用户的工号
326 | onSuccess: function () {},
327 | onFail: function (e) {
328 | alert(JSON.stringify(e))
329 | }
330 | })
331 | })
332 |
333 |
334 |
335 | }
336 | function showCallMenu(jsconfig, mobile) {
337 | console.log('ddconfig', jsconfig,mobile)
338 |
339 | dd.ready(function () {
340 | dd.biz.telephone.showCallMenu({
341 | phoneNumber: mobile, // 期望拨打的电话号码
342 | code: '+86', // 国家代号,中国是+86
343 | showDingCall: false, // 是否显示钉钉电话
344 | onSuccess: function () { },
345 | onFail: function (e) {
346 | alert(JSON.stringify(e))
347 | }
348 | })
349 | })
350 |
351 | }
352 | function alipay(jsconfig, info, callback) {
353 | console.log('jsconfig')
354 | dd.config({
355 | agentId: jsconfig.agentid,
356 | corpId: jsconfig.corpId,
357 | timeStamp: jsconfig.timeStamp,
358 | nonceStr: jsconfig.nonceStr,
359 | signature: jsconfig.signature,
360 | jsApiList: ['biz.alipay.pay']
361 | });
362 |
363 | dd.ready(function () {
364 | console.log('alipay')
365 | dd.biz.alipay.pay({
366 | info: info,
367 | onSuccess: function (result) {
368 | console.log("alipay success")
369 | callback(result)
370 | },
371 | onFail: function (err) {
372 | console.log("alipay err")
373 | console.error(err)
374 | }
375 | })
376 | })
377 |
378 | dd.error(function (err) {
379 | alert('dd error: ' + JSON.stringify(err));
380 | });
381 |
382 | }
383 |
384 |
--------------------------------------------------------------------------------
/screenshots/S91006-001.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pluto1114/dingding-nodejs-SDK/2426dbeff156a20d0dbb9ea07bda3b278db99687/screenshots/S91006-001.png
--------------------------------------------------------------------------------
/screenshots/S91006-002.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pluto1114/dingding-nodejs-SDK/2426dbeff156a20d0dbb9ea07bda3b278db99687/screenshots/S91006-002.png
--------------------------------------------------------------------------------
/screenshots/S91006-003.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pluto1114/dingding-nodejs-SDK/2426dbeff156a20d0dbb9ea07bda3b278db99687/screenshots/S91006-003.png
--------------------------------------------------------------------------------
/screenshots/S91006-004.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pluto1114/dingding-nodejs-SDK/2426dbeff156a20d0dbb9ea07bda3b278db99687/screenshots/S91006-004.png
--------------------------------------------------------------------------------
/screenshots/S91006-005.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pluto1114/dingding-nodejs-SDK/2426dbeff156a20d0dbb9ea07bda3b278db99687/screenshots/S91006-005.png
--------------------------------------------------------------------------------
/server/config/config-default.js:
--------------------------------------------------------------------------------
1 | var config = {
2 | database: 'dingding-sdk',
3 | dialect:'mysql',
4 | username: 'root',
5 | password: 'pluto1114',
6 | host: '94.191.121.109',
7 | port: 3306,
8 | secret:'pluto1114',
9 | };
10 |
11 | module.exports = config;
--------------------------------------------------------------------------------
/server/config/config-test.js:
--------------------------------------------------------------------------------
1 | var config = {
2 | database: 'selnum',
3 | username: 'root',
4 | password: 'root',
5 | host: 'localhost',
6 | port: 3306
7 | };
8 |
9 | module.exports = config;
--------------------------------------------------------------------------------
/server/config/index.js:
--------------------------------------------------------------------------------
1 | const defaultConfig = './config-default.js';
2 | // 可设定为绝对路径,如 /opt/product/config-override.js
3 | const overrideConfig = 'e:/config-override.js';
4 | const testConfig = './config-test.js';
5 |
6 | const fs = require('fs');
7 |
8 | var config = null;
9 |
10 | if (process.env.NODE_ENV === 'test') {
11 | console.log(`Load ${testConfig}...`);
12 | config = require(testConfig);
13 | } else {
14 | console.log(`Load ${defaultConfig}...`);
15 | config = require(defaultConfig);
16 | try {
17 | // if (fs.statSync(overrideConfig).isFile()) {
18 | // console.log(`Load ${overrideConfig}...`);
19 | // config = Object.assign(config, require(overrideConfig));
20 | // }
21 | } catch (err) {
22 | console.log(err)
23 | console.log(`Cannot load ${overrideConfig}.`);
24 | }
25 | }
26 |
27 | module.exports = config;
--------------------------------------------------------------------------------
/server/controller.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 |
3 | function addMapping(router, mapping) {
4 | for (var url in mapping) {
5 | var
6 | delimiter = url.indexOf(' ');
7 | method = url.slice(0, delimiter);
8 | path = url.slice(delimiter + 1);
9 | router[method.toLowerCase()](path, mapping[url]);
10 | console.log(`register URL mapping: ${method} ${path}`);
11 | }
12 | }
13 |
14 | function addControllers(router, dir) {
15 | var files = fs.readdirSync(__dirname + '/' + dir);
16 | var js_files = files.filter((f) => {
17 | return f.endsWith('.js');
18 | });
19 |
20 |
21 | for (var f of js_files) {
22 | console.log(`process controller: ${f}...`);
23 | let mapping = require(__dirname + `/${dir}/` + f);
24 | let name = f.replace('.js', '');
25 | let keys = Object.keys(mapping);
26 |
27 | if (keys.every(k => k.includes(`/v1/${name}/`)||k.includes(`/v2/${name}/`))) {
28 | addMapping(router, mapping);
29 | } else {
30 | throw new Error(`${f} 路径命名不合法`);
31 | }
32 |
33 | }
34 | }
35 | function _to(s) {
36 | let d = "s", e = "es";
37 | let len = s.length;
38 | if ((s[len - 1] == 'o' || s[len - 1] == 's' || s[len - 1] == 'x') || ((s[len - 2] == 'c' || s[len - 2] == 's') && (s[len - 1] == 'h'))) {
39 | s = s.concat(e);
40 | }
41 | else if (s[len - 1] == 'y') {
42 | s[len - 1] = 'i';
43 | s = s.concat(e);
44 | }
45 | else {
46 | s = s.concat(d);
47 | }
48 | return s;
49 | }
50 | module.exports = function (dir) {
51 | let
52 | controller_dir = dir || 'controller', // 如果不传参数,扫描目录默认为'controllers'
53 | router = require('koa-router')();
54 | addControllers(router, controller_dir);
55 | return router.routes();
56 | }
--------------------------------------------------------------------------------
/server/controller/dd.js:
--------------------------------------------------------------------------------
1 | const model = require('../model')
2 | const r = require('../dto/resp')
3 |
4 | class Dd{
5 | async getCorpid(ctx){
6 | let ddConfig = await model.DdConfig.getBy({ ukey: ctx.ukey })
7 | ctx.body = r().setItemMap({ corpid: ddConfig.corpid })
8 | };
9 | async getUserinfo(ctx){
10 | let ukey = ctx.ukey
11 | let code = ctx.query.code
12 | console.log('code', code)
13 | let options = {
14 | url: 'https://oapi.dingtalk.com/user/getuserinfo',
15 | params: { code },
16 | }
17 | let info = await model.DdConfig.callApi(ctx.ukey, options)
18 | console.log('info', info)
19 |
20 | let user = await model.user.getBy({ userid: info.userid })
21 |
22 | if (user) {
23 | let lasttime = user.accesstime
24 | user.hot = user.hot + 1
25 | user.accesstime = new Date
26 | await user.save()
27 | user.accesstime = lasttime
28 | } else {
29 | user= await model.user.createUser(info.userid,ukey)
30 | }
31 |
32 | ctx.body = r().setItemMap({ user })
33 | };
34 | async getJsconfig(ctx){
35 | let jsconfig = await model.DdConfig.getJsconfig(ctx.ukey)
36 | console.log('info', jsconfig)
37 |
38 | ctx.body = r().setItemMap({ jsconfig })
39 | };
40 |
41 | }
42 |
43 | let dd=new Dd();
44 | module.exports = {
45 | 'GET /v1/dd/corpid': dd.getCorpid,
46 | 'GET /v1/dd/userinfo': dd.getUserinfo,
47 | 'GET /v1/dd/jsconfig': dd.getJsconfig,
48 |
49 | };
--------------------------------------------------------------------------------
/server/controller/order.js:
--------------------------------------------------------------------------------
1 |
2 | const model = require('../model');
3 | const service = require('../service');
4 | const r = require('../dto/resp');
5 | const Op = require('sequelize').Op;
6 | class Order {
7 | async index(ctx) {
8 | let { userid, orderStatus } = ctx.query;
9 | const orders = await model.order.findBy({ userid, orderStatus})
10 | ctx.body = r().setItems(orders);
11 | }
12 | async show(ctx) {
13 | let { id } = ctx.params;
14 | const order = await model.order.getBy({ orderId: id })
15 | ctx.body = r().setItemMap({ order })
16 | }
17 | async count(ctx) {
18 | let { userid } = ctx.query;
19 | let unfinCount = await model.order.countBy({ orderStatus: {[Op.ne]:'orderFinish'}, userid })
20 | let finCount = await model.order.countBy({ orderStatus: 'orderFinish', userid })
21 | ctx.body = r().setItemMap({ unfinCount, finCount });
22 | }
23 | async save(ctx) {
24 | let body = ctx.request.body;
25 | let order = await model.order.create({
26 | orderId: new Date().getTime(),
27 | orderStatus: 'orderStart',
28 | createtime: new Date(),
29 | ...body
30 | })
31 | service.process.createTask({ukey:ctx.ukey,orderId:order.orderId})
32 | ctx.body = r().setItemMap({ order })
33 | }
34 | async finish(ctx) {
35 | let body = ctx.request.body;
36 | const order=await model.order.getBy({orderId:body.orderId})
37 | order.orderStatus='orderFinish'
38 | await order.save()
39 | service.process.cancelTask({ukey:ctx.ukey,orderId:order.orderId})
40 | ctx.body = r()
41 | }
42 | }
43 | let order = new Order()
44 | module.exports = {
45 | 'GET /v1/order/index': order.index,
46 | 'GET /v1/order/count': order.count,
47 | 'GET /v1/order/:id': order.show,
48 | 'POST /v1/order/save': order.save,
49 | 'PUT /v1/order/finish': order.finish,
50 |
51 | };
--------------------------------------------------------------------------------
/server/cservice/process.js:
--------------------------------------------------------------------------------
1 | const model = require('../model');
2 | const Op = require('sequelize').Op;
3 |
4 | class Process {
5 | async createTask({ ukey, orderId }) {
6 | let order = await model.order.getBy({ orderId });
7 | let ddConfig = await model.DdConfig.getBy({ ukey });
8 | let url = `${ddConfig.url}`;
9 | let createInstanceOptions = {
10 | url: 'https://oapi.dingtalk.com/topapi/process/workrecord/create',
11 | data: {
12 | "request": {
13 | "title": `demo未处理工单(${order.orderName})`,
14 | "process_code": `${ddConfig.process_code}`,
15 | "originator_user_id": order.userid,
16 | "form_component_values": {
17 | "name": "待办工单",
18 | "value": `${order.orderId}`
19 | },
20 | "url": `${url}`
21 | }
22 | },
23 | method: 'post'
24 | };
25 | let process_instance_id = order.processInstanceId;
26 | if (process_instance_id == null) {
27 | let instanceData = await model.DdConfig.callApi(ukey, createInstanceOptions);
28 | process_instance_id = instanceData.result.process_instance_id
29 | }
30 |
31 | let createTaskOptions = {
32 | url: 'https://oapi.dingtalk.com/topapi/process/workrecord/task/create',
33 | data: {
34 | "request": {
35 | "process_instance_id": process_instance_id,
36 | "activity_id": "solve",
37 | "tasks": {
38 | "userid": order.userid,
39 | "url": `${url}`
40 | }
41 | }
42 | },
43 | method: 'post'
44 | };
45 | let taskData = await model.DdConfig.callApi(ukey, createTaskOptions);
46 | if (taskData.errcode === 0) {
47 | await order.update({ processInstanceId: process_instance_id });
48 | return process_instance_id;
49 | } else {
50 | return null;
51 | }
52 |
53 | }
54 | async cancelTask({ ukey, orderId }) {
55 | let order = await model.order.getBy({ orderId });
56 | let cancelTaskOptions = {
57 | url: 'https://oapi.dingtalk.com/topapi/process/workrecord/taskgroup/cancel',
58 | data: {
59 | "request": {
60 | "process_instance_id": `${order.processInstanceId}`,
61 | "activity_id": "solve"
62 | }
63 | },
64 | method: 'post'
65 | };
66 | if (order.processInstanceId) {
67 | await model.DdConfig.callApi(ukey, cancelTaskOptions);
68 | }
69 | }
70 | async updateInstance({ ukey, orderId }) {
71 | let order = await model.Order.getBy({ orderId });
72 | let updateInstanceOptions = {
73 | url: 'https://oapi.dingtalk.com/topapi/process/workrecord/update',
74 | data: {
75 | "request": {
76 | "process_instance_id": `${order.processInstanceId}`,
77 | "status": "COMPLETED",
78 | "result": order.revisitCode == "yes" ? "agree" : "refuse"
79 | }
80 | },
81 | method: 'post'
82 | };
83 | if (order.processInstanceId) {
84 | await model.DdConfig.callApi(ukey, updateInstanceOptions);
85 | }
86 | }
87 | }
88 |
89 | const obj=new Process()
90 | exports.obj = obj
91 |
92 |
--------------------------------------------------------------------------------
/server/db.js:
--------------------------------------------------------------------------------
1 | const Sequelize = require('sequelize');
2 |
3 | const uuid = require('node-uuid');
4 |
5 | const config = require('./config');
6 |
7 | console.log('init sequelize...');
8 |
9 | function generateId() {
10 | return uuid.v4();
11 | }
12 |
13 | var sequelize = new Sequelize(config.database, config.username, config.password, {
14 | host: config.host,
15 | port: config.port,
16 | dialect: config.dialect,
17 | timezone:"+08:00",
18 | pool: {
19 | max: 6,
20 | min: 0,
21 | idle: 30000
22 | }
23 | });
24 |
25 | var exp = {
26 | sequelize:sequelize,
27 | dataTypes:Sequelize,
28 | sync: () => {
29 | // only allow create ddl in non-production environment:
30 | if (process.env.NODE_ENV !== 'production') {
31 | return sequelize.sync({ force: true });
32 | } else {
33 | throw new Error('Cannot sync() when NODE_ENV is set to \'production\'.');
34 | }
35 | }
36 | };
37 | exp.SELECT=sequelize.QueryTypes.SELECT
38 | exp.generateId = generateId;
39 | exp.pageSize=15
40 | module.exports = exp;
--------------------------------------------------------------------------------
/server/dto/resp.js:
--------------------------------------------------------------------------------
1 | var r = () => {
2 | return {
3 | errcode: '0',
4 | message: 'success',
5 | items: [],
6 | itemMap: {},
7 |
8 | setErrcode(val) {
9 | this.errcode = val
10 | return this
11 | },
12 |
13 | setMessage(val) {
14 | this.message = val
15 | return this
16 | },
17 |
18 | setItems(val) {
19 | this.items = val
20 | return this
21 | },
22 |
23 | setItemMap(val) {
24 | this.itemMap = val
25 | return this
26 | },
27 | fail(message='fail'){
28 | this.errcode='-1'
29 | this.message=message
30 | return this
31 | }
32 | }
33 | }
34 | module.exports = r
--------------------------------------------------------------------------------
/server/kits/cryptoKit.js:
--------------------------------------------------------------------------------
1 | var crypto = require('crypto');
2 |
3 | var toSha1 = str=>{
4 | return crypto.createHash('sha1').update(str).digest('hex')
5 | }
6 |
7 | module.exports = {
8 | toSha1
9 | };
--------------------------------------------------------------------------------
/server/kits/jwtKit.js:
--------------------------------------------------------------------------------
1 | const jwt = require('jsonwebtoken')
2 | const config=require('../config')
3 | const secret = config.secret
4 |
5 | const expiresIn='6h'
6 | let sign=(userToken)=>{
7 | return jwt.sign(userToken, secret, { expiresIn})
8 | }
9 |
10 | module.exports = {
11 | 'sign':sign
12 | };
--------------------------------------------------------------------------------
/server/middleware/error.js:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | module.exports = function () {
5 | return async function (ctx, next) {
6 | try {
7 | await next();
8 | } catch (err) {
9 | console.error(err)
10 | ctx.body = 'server error';
11 | ctx.status = err.status || 500;
12 | }
13 | }
14 | }
--------------------------------------------------------------------------------
/server/middleware/tokenError.js:
--------------------------------------------------------------------------------
1 | const jwt = require('jsonwebtoken');
2 | const config = require('../config');
3 | const util = require('util');
4 | const verify = util.promisify(jwt.verify);
5 |
6 | /**
7 | * 判断token是否可用
8 | */
9 | module.exports = function () {
10 | return async function (ctx, next) {
11 | try {
12 | // console.log('authorization',ctx.header.authorization)
13 | const token = ctx.header.authorization;
14 | if (token) {
15 | try {
16 | let payload = await verify(token.split(' ')[1], config.secret);
17 | // console.log(payload)
18 | ctx.user = {
19 | code:payload.code,
20 | name: payload.name,
21 | mobile:payload.mobile,
22 | role_code:payload.role_code
23 | };
24 | } catch (err) {
25 | console.log('token verify fail: ', err)
26 | }
27 | }
28 | await next();
29 | } catch (err) {
30 | console.error(err)
31 | if (err.status === 401) {
32 | ctx.status = 401;
33 | ctx.body = {
34 | errcode: -1,
35 | message: '认证失败'
36 | };
37 | } else {
38 | err.status = 404;
39 | ctx.body = {
40 | errcode: -4,
41 | message: '404'
42 | };
43 | }
44 | }
45 | }
46 | }
--------------------------------------------------------------------------------
/server/middleware/ukey.js:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | module.exports = function () {
5 | return async function (ctx, next) {
6 | try {
7 | const keyArr=['nmlt','pluto1114','rcpbe-cs']
8 | const ukey = ctx.header['x-key'];
9 | console.log('ukey',ukey)
10 | if (ukey&&keyArr.findIndex(k=>k==ukey)>-1) {
11 | ctx.ukey=ukey
12 | await next();
13 | }else if(ctx.is('multipart')){
14 | await next();
15 | }else{
16 | await next();
17 | }
18 | } catch (err) {
19 | console.error(err)
20 |
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------
/server/model-base/abase.js:
--------------------------------------------------------------------------------
1 | const db = require('../db');
2 | const pageSize=db.pageSize
3 |
4 | function base(table) {
5 | const contruct = require(`./${table}`)
6 | const obj = contruct(db.sequelize, db.dataTypes)
7 | obj.sql=db.sequelize
8 | obj.SELECT=db.sequelize.QueryTypes.SELECT
9 | obj.getBy = (param) => {
10 | return obj.findOne({ where: param });
11 | }
12 | obj.findBy = (whereParam,otherParams) => {
13 | return obj.findAll({ where: whereParam,...otherParams })
14 | }
15 | obj.findByOrder = (param,order) => {
16 | return obj.findAll({ where: param ,order})
17 | }
18 | obj.pageByOrder = async (param,order,pageNum) => {
19 | // return obj.findAll({ where: param ,order:order,offset:(pageNum-1)*pageSize,limit:pageSize})
20 | let items=await obj.findAll({ where: param ,order:order,offset:(pageNum-1)*pageSize,limit:pageSize})
21 | let total=await obj.count({ where: param})
22 | return {items,total}
23 | }
24 | obj.findBySql=(sql,param)=>{
25 | return obj.sql.query(sql,{replacements:param,type : obj.SELECT})
26 | }
27 | obj.pageBySql=(sql,param,pageNum)=>{
28 | sql=sql+' limit '+(pageNum-1)*pageSize+','+pageSize
29 | return obj.sql.query(sql,{replacements:param,type : obj.SELECT})
30 | }
31 | obj.updateBySql=(sql,param)=>{
32 | return obj.sql.query(sql,{replacements:param,type : obj.UPDATE})
33 | }
34 | obj.updateBy = (model,param) => {
35 | return obj.update(model,{ where: param })
36 | }
37 | obj.deleteBy = (param) => {
38 | return obj.destroy({ where: param })
39 | }
40 | obj.countBy = (param) => {
41 | return obj.count({ where: param })
42 | }
43 |
44 | return obj
45 |
46 | }
47 | module.exports = base
48 |
49 |
--------------------------------------------------------------------------------
/server/model-base/dd_config.js:
--------------------------------------------------------------------------------
1 | /* jshint indent: 1 */
2 |
3 | module.exports = function(sequelize, DataTypes) {
4 | return sequelize.define('dd_config', {
5 | id: {
6 | type: DataTypes.INTEGER(11),
7 | allowNull: false
8 | },
9 | ukey: {
10 | type: DataTypes.STRING(64),
11 | allowNull: false,
12 | primaryKey: true
13 | },
14 | uname: {
15 | type: DataTypes.STRING(128),
16 | allowNull: true
17 | },
18 | sname: {
19 | type: DataTypes.STRING(64),
20 | allowNull: true
21 | },
22 | corpid: {
23 | type: DataTypes.STRING(128),
24 | allowNull: false
25 | },
26 | corpsecret: {
27 | type: DataTypes.STRING(128),
28 | allowNull: true
29 | },
30 | appkey: {
31 | type: DataTypes.STRING(128),
32 | allowNull: true
33 | },
34 | appsecret: {
35 | type: DataTypes.STRING(128),
36 | allowNull: true
37 | },
38 | agentid: {
39 | type: DataTypes.STRING(128),
40 | allowNull: true
41 | },
42 | chatid: {
43 | type: DataTypes.STRING(128),
44 | allowNull: true
45 | },
46 | access_token: {
47 | type: DataTypes.STRING(128),
48 | allowNull: true
49 | },
50 | token_begin_time: {
51 | type: DataTypes.DATE,
52 | allowNull: true
53 | },
54 | ticket: {
55 | type: DataTypes.STRING(128),
56 | allowNull: true
57 | },
58 | ticket_begin_time: {
59 | type: DataTypes.DATE,
60 | allowNull: true
61 | },
62 | url: {
63 | type: DataTypes.STRING(256),
64 | allowNull: true
65 | },
66 | process_code: {
67 | type: DataTypes.STRING(64),
68 | allowNull: true
69 | }
70 | }, {
71 | tableName: 'dd_config',
72 | timestamps: false
73 | });
74 | };
75 |
--------------------------------------------------------------------------------
/server/model-base/t_order.js:
--------------------------------------------------------------------------------
1 | /* jshint indent: 1 */
2 |
3 | module.exports = function(sequelize, DataTypes) {
4 | return sequelize.define('t_order', {
5 | orderId: {
6 | type: DataTypes.BIGINT,
7 | allowNull: false,
8 | primaryKey: true,
9 | autoIncrement: true
10 | },
11 | orderName: {
12 | type: DataTypes.STRING(255),
13 | allowNull: true
14 | },
15 | userid: {
16 | type: DataTypes.STRING(64),
17 | allowNull: true
18 | },
19 | totalPrice: {
20 | type: DataTypes.DECIMAL,
21 | allowNull: true
22 | },
23 | orderStatus: {
24 | type: DataTypes.STRING(64),
25 | allowNull: true
26 | },
27 | processInstanceId: {
28 | type: DataTypes.STRING(64),
29 | allowNull: true
30 | },
31 | createtime: {
32 | type: DataTypes.DATE,
33 | allowNull: true
34 | }
35 | }, {
36 | tableName: 't_order',
37 | timestamps: false
38 | });
39 | };
40 |
--------------------------------------------------------------------------------
/server/model-base/t_user.js:
--------------------------------------------------------------------------------
1 | /* jshint indent: 1 */
2 |
3 | module.exports = function(sequelize, DataTypes) {
4 | return sequelize.define('t_user', {
5 | id: {
6 | type: DataTypes.INTEGER(11),
7 | allowNull: false,
8 | autoIncrement: true,
9 | unique: true
10 | },
11 | userid: {
12 | type: DataTypes.STRING(64),
13 | allowNull: false,
14 | primaryKey: true
15 | },
16 | name: {
17 | type: DataTypes.STRING(64),
18 | allowNull: true
19 | },
20 | department: {
21 | type: DataTypes.STRING(64),
22 | allowNull: true
23 | },
24 | departmentName: {
25 | type: DataTypes.STRING(255),
26 | allowNull: true
27 | },
28 | mobile: {
29 | type: DataTypes.STRING(64),
30 | allowNull: true
31 | },
32 | email: {
33 | type: DataTypes.STRING(64),
34 | allowNull: true
35 | },
36 | avatar: {
37 | type: DataTypes.STRING(256),
38 | allowNull: true
39 | },
40 | openid: {
41 | type: DataTypes.STRING(64),
42 | allowNull: true
43 | },
44 | unionid: {
45 | type: DataTypes.STRING(64),
46 | allowNull: true
47 | },
48 | createtime: {
49 | type: DataTypes.DATE,
50 | allowNull: false
51 | },
52 | accesstime: {
53 | type: DataTypes.DATE,
54 | allowNull: true
55 | },
56 | hot: {
57 | type: DataTypes.INTEGER(11),
58 | allowNull: true,
59 | defaultValue: '0'
60 | },
61 | upDepart: {
62 | type: DataTypes.BIGINT,
63 | allowNull: true
64 | },
65 | ukey: {
66 | type: DataTypes.STRING(64),
67 | allowNull: true
68 | },
69 | point: {
70 | type: DataTypes.INTEGER(11),
71 | allowNull: true,
72 | defaultValue: '0'
73 | },
74 | god: {
75 | type: DataTypes.INTEGER(1),
76 | allowNull: false,
77 | defaultValue: '0'
78 | },
79 | role: {
80 | type: DataTypes.STRING(16),
81 | allowNull: false,
82 | defaultValue: 'P'
83 | }
84 | }, {
85 | tableName: 't_user',
86 | timestamps: false
87 | });
88 | };
89 |
--------------------------------------------------------------------------------
/server/model.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | const db = require('./db');
3 |
4 | let files = fs.readdirSync(__dirname + '/model');
5 |
6 | let js_files = files.filter((f) => {
7 | return f.endsWith('.js');
8 | }, files);
9 |
10 | module.exports = {};
11 |
12 | for (let f of js_files) {
13 | if (f === 'AAA.js') continue
14 | console.log(`import model from file ${f}...`);
15 | let name = f.substring(0, f.length - 3);
16 | module.exports[name] = require(__dirname + '/model/' + f).obj;
17 | }
18 | module.exports.now = () => {
19 | let date = new Date();
20 | return date
21 | }
22 | module.exports.date = (s) => {
23 | let date = new Date(s);
24 | // date.setHours(date.getHours() + 8);
25 | return date
26 | }
27 | module.exports.sync = () => {
28 | db.sync();
29 | };
30 |
31 | module.exports.pageSize=db.pageSize
--------------------------------------------------------------------------------
/server/model/DdConfig.js:
--------------------------------------------------------------------------------
1 |
2 | const table='dd_config'
3 | const obj=require('../model-base/abase')(table)
4 | const axios = require('axios')
5 | const config = require('../config')
6 | const cryptoKit=require('../kits/cryptoKit')
7 |
8 | var _merge = require('lodash/merge')
9 | obj.gettoken = async (ukey) => {
10 | let ddconfig = await obj.getBy({ ukey})
11 | let date=new Date()
12 | date.setHours(date.getHours()-1)
13 | if(ddconfig.ticket_begin_time.getTime()>date.getTime()){
14 | console.log('token used')
15 | return ddconfig.access_token
16 | }
17 | var options = {
18 | url: 'https://oapi.dingtalk.com/gettoken',
19 | params: {
20 | appkey: ddconfig.corpid,
21 | appsecret: ddconfig.corpsecret,
22 | }
23 | };
24 | if(ddconfig.corpsecret){
25 | // console.warn("corpid")
26 | options.params={
27 | appkey: ddconfig.corpid,
28 | appsecret: ddconfig.corpsecret,
29 | }
30 | }else{
31 | // console.warn("appkey")
32 | options.params={
33 | appkey: ddconfig.appkey,
34 | appsecret: ddconfig.appsecret,
35 | }
36 | }
37 |
38 | let { data } = await axios(options)
39 | await ddconfig.update({ access_token: data.access_token, token_begin_time: new Date() })
40 | return data.access_token
41 | }
42 | obj._getticket = async (ukey,access_token) => {
43 | let ddconfig = await obj.getBy({ ukey})
44 | let date=new Date()
45 | date.setHours(date.getHours()-1)
46 | if(ddconfig.ticket_begin_time.getTime()>date.getTime()){
47 | console.log('ticket used')
48 | return ddconfig.ticket
49 | }
50 | var options = {
51 | url: 'https://oapi.dingtalk.com/get_jsapi_ticket',
52 | params: {access_token}
53 | };
54 |
55 | let {data} = await axios(options)
56 | console.log(data)
57 | await ddconfig.update({ticket: data.ticket,ticket_begin_time:new Date()})
58 | return data.ticket
59 | }
60 | function sign(ticket,nonceStr,timeStamp,url){
61 | let plain = "jsapi_ticket=" + ticket + "&noncestr=" + nonceStr + "×tamp=" + timeStamp
62 | + "&url=" + url;
63 | console.log('plain',plain)
64 | return cryptoKit.toSha1(plain)
65 | }
66 |
67 | obj.getJsconfig=async (ukey)=>{
68 | let access_token= await obj.gettoken(ukey)
69 | let ticket=await obj._getticket(ukey,access_token)
70 | let ddconfig = await obj.getBy({ ukey})
71 | let timeStamp=new Date().getTime()
72 | let nonceStr=config.secret
73 |
74 | return {
75 | agentId:ddconfig.agentid,
76 | corpId:ddconfig.corpid,
77 | signature:sign(ticket,nonceStr,timeStamp,ddconfig.url),
78 | timeStamp,
79 | nonceStr
80 | }
81 | }
82 |
83 | obj.callApi=async (ukey,options)=>{
84 | let access_token= await obj.gettoken(ukey)
85 | let DEFAULTS = {
86 | url: 'https://oapi.dingtalk.com/',
87 | params: {access_token}
88 | };
89 | options=_merge(DEFAULTS,options)
90 | console.log('options',options)
91 | let {data} = await axios(options)
92 | return data
93 | }
94 |
95 | exports.obj = obj
--------------------------------------------------------------------------------
/server/model/order.js:
--------------------------------------------------------------------------------
1 |
2 | const table='t_order'
3 | const obj=require('../model-base/abase')(table)
4 |
5 |
6 | exports.obj = obj
7 |
--------------------------------------------------------------------------------
/server/model/user.js:
--------------------------------------------------------------------------------
1 |
2 | const table = 't_user'
3 | const obj = require('../model-base/abase')(table)
4 | const model = require('../model')
5 |
6 | obj.createUser = async (userid, ukey) => {
7 | let options = {
8 | url: 'https://oapi.dingtalk.com/user/get',
9 | params: { userid },
10 | }
11 | let u = await model.DdConfig.callApi(ukey, options)
12 |
13 | let user = await model.user.create({
14 | userid: u.userid, openid: u.openId, name: u.name, mobile: u.mobile, email: u.email, avatar: u.avatar, department: u.department[0], jobnumber: u.jobnumber, ukey: ukey, createtime: new Date, accesstime: new Date, god: 1
15 | })
16 | return user
17 | }
18 | exports.obj = obj
19 |
--------------------------------------------------------------------------------
/server/service.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | let files = fs.readdirSync(__dirname + '/cservice');
3 |
4 | let js_files = files.filter((f) => {
5 | return f.endsWith('.js');
6 | }, files);
7 |
8 | module.exports = {};
9 |
10 | for (let f of js_files) {
11 | console.log(`import service from file ${f}...`);
12 | let name = f.substring(0, f.length - 3);
13 | module.exports[name] = require(__dirname + '/cservice/' + f).obj;
14 | }
15 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
49 |
50 |
67 |
139 |
140 |
141 |
--------------------------------------------------------------------------------
/src/api.js:
--------------------------------------------------------------------------------
1 |
2 | import Vue from 'vue'
3 | import axios from 'axios'
4 |
5 | var debug = true;
6 | var showStr = false;
7 |
8 | export function api(url, options) {
9 | var p = {};
10 | if (!url) url = '/api'
11 | var defaultOptions = {
12 | 'method': 'get'
13 | };
14 | // window.location.href="http://www.baidu.com"
15 | var opt = Object.assign(defaultOptions, options);
16 | console.log("localStorage.ddKey",localStorage.ddKey)
17 |
18 | if(localStorage.ddKey){
19 | axios.defaults.headers.common['x-key'] = localStorage.ddKey;
20 | }
21 |
22 | p = axios(url, opt)
23 | p.then(resp => {
24 | // console.log(resp)
25 | if (debug) {
26 | console.log(`resp.data from ${url}`, opt.data);
27 | console.log(`%c${url} result`, 'color:green', resp.data)
28 | }
29 | if (showStr) {
30 | console.log(JSON.stringify(resp));
31 | }
32 | if (resp.headers.refresh_token) {
33 | window.localStorage.token = resp.headers.refresh_token;
34 | }
35 |
36 | }).catch(err => {
37 | console.error(err)
38 | // window.location.href = "/#/login"
39 | })
40 | return p.then(res=>res.data)
41 | }
42 |
43 |
--------------------------------------------------------------------------------
/src/assets/finishOrder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pluto1114/dingding-nodejs-SDK/2426dbeff156a20d0dbb9ea07bda3b278db99687/src/assets/finishOrder.png
--------------------------------------------------------------------------------
/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pluto1114/dingding-nodejs-SDK/2426dbeff156a20d0dbb9ea07bda3b278db99687/src/assets/logo.png
--------------------------------------------------------------------------------
/src/assets/photo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pluto1114/dingding-nodejs-SDK/2426dbeff156a20d0dbb9ea07bda3b278db99687/src/assets/photo.png
--------------------------------------------------------------------------------
/src/assets/success.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pluto1114/dingding-nodejs-SDK/2426dbeff156a20d0dbb9ea07bda3b278db99687/src/assets/success.png
--------------------------------------------------------------------------------
/src/assets/unfinishOrder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pluto1114/dingding-nodejs-SDK/2426dbeff156a20d0dbb9ea07bda3b278db99687/src/assets/unfinishOrder.png
--------------------------------------------------------------------------------
/src/components/HelloWorld.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{ msg }}
4 |
5 | For a guide and recipes on how to configure / customize this project,
6 | check out the
7 | vue-cli documentation.
8 |
9 |
Installed CLI Plugins
10 |
14 |
Essential Links
15 |
22 |
Ecosystem
23 |
30 |
31 |
32 |
33 |
41 |
42 |
43 |
59 |
--------------------------------------------------------------------------------
/src/cube-ui.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 |
3 | // By default we import all the components.
4 | // Only reserve the components on demand and remove the rest.
5 | // Style is always required.
6 | import {
7 | /* eslint-disable no-unused-vars */
8 | Style,
9 | // basic
10 | Button,
11 | Loading,
12 | Tip,
13 | Toolbar,
14 | TabBar,
15 | TabPanels,
16 | // form
17 | Checkbox,
18 | CheckboxGroup,
19 | Checker,
20 | Radio,
21 | RadioGroup,
22 | Input,
23 | Textarea,
24 | Select,
25 | Switch,
26 | Rate,
27 | Validator,
28 | Upload,
29 | Form,
30 | // popup
31 | Popup,
32 | Toast,
33 | Picker,
34 | CascadePicker,
35 | DatePicker,
36 | TimePicker,
37 | SegmentPicker,
38 | Dialog,
39 | ActionSheet,
40 | Drawer,
41 | ImagePreview,
42 | // scroll
43 | Scroll,
44 | Slide,
45 | IndexList,
46 | Swipe,
47 | Sticky,
48 | ScrollNav,
49 | ScrollNavBar
50 | } from 'cube-ui'
51 |
52 | Vue.use(Button)
53 | Vue.use(Loading)
54 | Vue.use(Tip)
55 | Vue.use(Toolbar)
56 | Vue.use(TabBar)
57 | Vue.use(TabPanels)
58 | Vue.use(Checkbox)
59 | Vue.use(CheckboxGroup)
60 | Vue.use(Checker)
61 | Vue.use(Radio)
62 | Vue.use(RadioGroup)
63 | Vue.use(Input)
64 | Vue.use(Textarea)
65 | Vue.use(Select)
66 | Vue.use(Switch)
67 | Vue.use(Rate)
68 | Vue.use(Validator)
69 | Vue.use(Upload)
70 | Vue.use(Form)
71 | Vue.use(Popup)
72 | Vue.use(Toast)
73 | Vue.use(Picker)
74 | Vue.use(CascadePicker)
75 | Vue.use(DatePicker)
76 | Vue.use(TimePicker)
77 | Vue.use(SegmentPicker)
78 | Vue.use(Dialog)
79 | Vue.use(ActionSheet)
80 | Vue.use(Drawer)
81 | Vue.use(ImagePreview)
82 | Vue.use(Scroll)
83 | Vue.use(Slide)
84 | Vue.use(IndexList)
85 | Vue.use(Swipe)
86 | Vue.use(Sticky)
87 | Vue.use(ScrollNav)
88 | Vue.use(ScrollNavBar)
89 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import './cube-ui'
3 | import App from './App.vue'
4 | import router from './router'
5 | import store from './store'
6 |
7 | Vue.config.productionTip = false
8 | /* eslint-disable */
9 | let query = parseQueryString();
10 | if (query.key) {
11 | localStorage.ddKey = query.key
12 | }
13 | new Vue({
14 | router,
15 | store,
16 | render: h => h(App)
17 | }).$mount('#app');
18 |
19 | Date.prototype.format = function (fmt) { //author: meizz
20 | var o = {
21 | "M+": this.getMonth() + 1, //月份
22 | "d+": this.getDate(), //日
23 | "h+": this.getHours(), //小时
24 | "m+": this.getMinutes(), //分
25 | "s+": this.getSeconds(), //秒
26 | "q+": Math.floor((this.getMonth() + 3) / 3), //季度
27 | "S": this.getMilliseconds() //毫秒
28 | };
29 | if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
30 | for (var k in o)
31 | if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
32 | return fmt;
33 | };
34 |
--------------------------------------------------------------------------------
/src/router.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Router from 'vue-router'
3 | import Home from './views/Home.vue'
4 |
5 | Vue.use(Router)
6 |
7 | export default new Router({
8 | routes: [
9 | {
10 | path: '/',
11 | name: 'home',
12 | component: Home
13 | },
14 | {
15 | path: '/about',
16 | name: 'about',
17 | component: () => import('./views/About.vue')
18 | },
19 | {
20 | path: '/order-add',
21 | name: 'OrderAdd',
22 | component: () => import('./views/OrderAdd.vue')
23 | },
24 | {
25 | path: '/order-list',
26 | name: 'OrderList',
27 | component: () => import('./views/OrderList.vue')
28 | },
29 | {
30 | path: '/result',
31 | name: 'Result',
32 | component: () => import('./views/Result.vue')
33 | },
34 | ]
35 | })
36 |
--------------------------------------------------------------------------------
/src/store.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Vuex from 'vuex'
3 | import { api } from './api'
4 |
5 | const remote = process.env.VUE_APP_REMOTE == '1'
6 |
7 | const HOST = process.env.VUE_APP_IP
8 |
9 | Vue.use(Vuex)
10 | if (!remote) {
11 | localStorage.ddKey = 'pluto1114'
12 | }
13 | export default new Vuex.Store({
14 | state: {
15 | host: HOST,
16 | remote:remote,
17 | dduser: remote ? null : { userid: 'manager8036', upDepart:319411090, name: '高健', mobile: '18698401720', avatar: 'https://static.dingtalk.com/media/lADPBbCc1a_esH_NAkDNAkA_576_576.jpg', points: '16', leader: true, point:0, god:1, ukey:'nmlt', },
18 | // dduser: null,
19 | },
20 | mutations: {
21 | updateDduser(state, payload) {
22 | state.dduser = payload
23 | },
24 | updateJsconfig(state, payload) {
25 | state.jsconfig = payload
26 | },
27 | },
28 | actions: {
29 | /* dingding相关 */
30 | fetchCorpid(context, payload) {
31 | console.log('corpid', `${HOST}/v1/dd/corpid`)
32 | return api(`${HOST}/v1/dd/corpid`)
33 | },
34 | fetchUserinfo(context, payload) {
35 | return api(`${HOST}/v1/dd/userinfo?code=${payload.code}`)
36 | },
37 | fetchJsconfig({ state }, payload) {
38 | return api(`${HOST}/v1/dd/jsconfig`, { params: payload })
39 | },
40 |
41 | fetchMyOrderCount(context, payload) {
42 | return api(`${HOST}/v1/order/count`, { params: payload })
43 | },
44 | fetchOrderList(context, payload) {
45 | return api(`${HOST}/v1/order/index`, { params: payload })
46 | },
47 | saveOrder(context, payload) {
48 | return api(`${HOST}/v1/order/save`, { method:'post', data: payload })
49 | },
50 | finishOrder(context, payload) {
51 | return api(`${HOST}/v1/order/finish`, { method:'put', data: payload })
52 | },
53 | }
54 | })
55 |
--------------------------------------------------------------------------------
/src/theme.styl:
--------------------------------------------------------------------------------
1 | @require "~cube-ui/src/common/stylus/var/color.styl"
2 |
3 |
4 | // action-sheet
5 | $action-sheet-color := $color-grey
6 | $action-sheet-active-color := $color-orange
7 | $action-sheet-bgc := $color-white
8 | $action-sheet-active-bgc := $color-light-grey-opacity
9 | $action-sheet-title-color := $color-dark-grey
10 | $action-sheet-space-bgc := $color-mask-bg
11 | /// picker style
12 | $action-sheet-picker-cancel-color := $color-light-grey
13 | $action-sheet-picker-cancel-active-color := $color-light-grey-s
14 |
15 | // bubble
16 |
17 | // button
18 | $btn-color := $color-white
19 | $btn-bgc := $color-regular-blue
20 | $btn-bdc := $color-regular-blue
21 | $btn-active-bgc := $color-blue
22 | $btn-active-bdc := $color-blue
23 | $btn-disabled-color := $color-white
24 | $btn-disabled-bgc := $color-light-grey-s
25 | $btn-disabled-bdc := $color-light-grey-s
26 | /// primary
27 | $btn-primary-color := $color-white
28 | $btn-primary-bgc := $color-orange
29 | $btn-primary-bdc := $color-orange
30 | $btn-primary-active-bgc := $color-dark-orange
31 | $btn-primary-active-bdc := $color-dark-orange
32 | /// light
33 | $btn-light-color := $color-grey
34 | $btn-light-bgc := $color-light-grey-sss
35 | $btn-light-bdc := $color-light-grey-sss
36 | $btn-light-active-bgc := $color-active-grey
37 | $btn-light-active-bdc := $color-active-grey
38 | /// outline
39 | $btn-outline-color := $color-grey
40 | $btn-outline-bgc := transparent
41 | $btn-outline-bdc := $color-grey
42 | $btn-outline-active-bgc := $color-grey-opacity
43 | $btn-outline-active-bdc := $color-grey
44 | /// outline-primary
45 | $btn-outline-primary-color := $color-orange
46 | $btn-outline-primary-bgc := transparent
47 | $btn-outline-primary-bdc := $color-orange
48 | $btn-outline-primary-active-bgc := $color-orange-opacity
49 | $btn-outline-primary-active-bdc := $color-dark-orange
50 |
51 | // toolbar
52 | $toolbar-bgc := $color-light-grey-sss
53 | $toolbar-active-bgc := $color-active-grey
54 |
55 | // checkbox
56 | $checkbox-color := $color-grey
57 | $checkbox-icon-color := $color-light-grey-s
58 | /// checked
59 | $checkbox-checked-icon-color := $color-orange
60 | $checkbox-checked-icon-bgc := $color-white
61 | /// disabled
62 | $checkbox-disabled-icon-color := $color-light-grey-ss
63 | $checkbox-disabled-icon-bgc := $color-light-grey-ss
64 | // checkbox hollow
65 | $checkbox-hollow-checked-icon-color := $color-orange
66 | $checkbox-hollow-disabled-icon-color := $color-light-grey-ss
67 | // checkbox-group
68 | $checkbox-group-bgc := $color-white
69 | $checkbox-group-horizontal-bdc := $color-light-grey-s
70 |
71 | // radio
72 | $radio-group-bgc := $color-white
73 | $radio-group-horizontal-bdc := $color-light-grey-s
74 | $radio-color := $color-grey
75 | $radio-icon-color := $color-light-grey-s
76 | /// selected
77 | $radio-selected-icon-color := $color-white
78 | $radio-selected-icon-bgc := $color-orange
79 | /// disabled
80 | $radio-disabled-icon-bgc := $color-light-grey-ss
81 | // radio hollow
82 | $radio-hollow-selected-icon-color := $color-orange
83 | $radio-hollow-disabled-icon-color := $color-light-grey-ss
84 |
85 | // dialog
86 | $dialog-color := $color-grey
87 | $dialog-bgc := $color-white
88 | $dialog-icon-color := $color-regular-blue
89 | $dialog-icon-bgc := $color-background
90 | $dialog-title-color := $color-dark-grey
91 | $dialog-close-color := $color-light-grey
92 | $dialog-btn-color := $color-light-grey
93 | $dialog-btn-bgc := $color-white
94 | $dialog-btn-active-bgc := $color-light-grey-opacity
95 | $dialog-btn-highlight-color := $color-orange
96 | $dialog-btn-highlight-active-bgc := $color-light-orange-opacity
97 | $dialog-btn-disabled-color := $color-light-grey
98 | $dialog-btn-disabled-active-bgc := transparent
99 | $dialog-btns-split-color := $color-row-line
100 |
101 | // index-list
102 | $index-list-bgc := $color-white
103 | $index-list-title-color := $color-dark-grey
104 | $index-list-anchor-color := $color-light-grey
105 | $index-list-anchor-bgc := #f7f7f7
106 | $index-list-item-color := $color-dark-grey
107 | $index-list-item-active-bgc := $color-light-grey-opacity
108 | $index-list-nav-color := $color-grey
109 | $index-list-nav-active-color := $color-orange
110 |
111 | // loading
112 |
113 | // picker
114 | $picker-bgc := $color-white
115 | $picker-title-color := $color-dark-grey
116 | $picker-subtitle-color := $color-light-grey
117 | $picker-confirm-btn-color := $color-orange
118 | $picker-confirm-btn-active-color := $color-light-orange
119 | $picker-cancel-btn-color := $color-light-grey
120 | $picker-cancel-btn-active-color := $color-light-grey-s
121 | $picker-item-color := $color-dark-grey
122 |
123 | // popup
124 | $popup-mask-bgc := rgb(37, 38, 45)
125 | $popup-mask-opacity := .4
126 |
127 | //scroll
128 |
129 | // slide
130 | $slide-dot-bgc := $color-light-grey-s
131 | $slide-dot-active-bgc := $color-orange
132 |
133 | // time-picker
134 |
135 | // tip
136 | $tip-color := $color-white
137 | $tip-bgc := $color-dark-grey-opacity
138 |
139 | // toast
140 | $toast-color := $color-light-grey-s
141 | $toast-bgc := rgba(37, 38, 45, 0.9)
142 |
143 | // upload
144 | $upload-btn-color := $color-grey
145 | $upload-btn-bgc := $color-white
146 | $upload-btn-active-bgc := $color-light-grey-opacity
147 | $upload-btn-box-shadow := 0 0 6px 2px $color-grey-opacity
148 | $upload-btn-border-color := #e5e5e5
149 | $upload-file-bgc := $color-white
150 | $upload-file-remove-color := rgba(0, 0, 0, .8)
151 | $upload-file-remove-bgc := $color-white
152 | $upload-file-state-bgc := $color-mask-bg
153 | $upload-file-success-color := $color-orange
154 | $upload-file-error-color := #f43530
155 | $upload-file-status-bgc := $color-white
156 | $upload-file-progress-color := $color-white
157 |
158 | // switch
159 | $switch-on-bgc := $color-orange
160 | $switch-off-bgc := $color-white
161 | $switch-off-border-color := #e4e4e4
162 |
163 | // input
164 | $input-color := $color-grey
165 | $input-bgc := $color-white
166 | $input-border-color := $color-row-line
167 | $input-focus-border-color := $color-orange
168 | $input-placeholder-color := $color-light-grey-s
169 | $input-clear-icon-color := $color-light-grey
170 |
171 | //textarea
172 | $textarea-color := $color-grey
173 | $textarea-bgc := $color-white
174 | $textarea-border-color := $color-row-line
175 | $textarea-focus-border-color := $color-orange
176 | $textarea-outline-color := $color-orange
177 | $textarea-placeholder-color := $color-light-grey-s
178 | $textarea-indicator-color := $color-light-grey-s
179 |
180 | // validator
181 | $validator-msg-def-color := #e64340
182 |
183 | // select
184 | $select-color := $color-grey
185 | $select-bgc := $color-white
186 | $select-disabled-color := #b8b8b8
187 | $select-disabled-bgc := $color-light-grey-opacity
188 | $select-border-color := $color-light-grey-s
189 | $select-border-active-color := $color-orange
190 | $select-icon-color := $color-light-grey
191 | $select-placeholder-color := $color-light-grey-s
192 |
193 | // swipe
194 | $swipe-btn-color := $color-white
195 |
196 | // form
197 | $form-color := $color-grey
198 | $form-bgc := $color-white
199 | $form-invalid-color := #e64340
200 | $form-group-legend-color := $color-light-grey
201 | $form-group-legend-bgc := $color-background
202 | $form-label-required-color := #e64340
203 |
204 | // drawer
205 | $drawer-color := $color-dark-grey
206 | $drawer-title-bdc := $color-light-grey-ss
207 | $drawer-title-bgc := $color-white
208 | $drawer-panel-bgc := $color-white
209 | $drawer-item-active-bgc := $color-light-grey-opacity
210 |
211 | // scroll-nav
212 | $scroll-nav-bgc := $color-white
213 | $scroll-nav-color := $color-grey
214 | $scroll-nav-active-color := $color-orange
215 |
216 | // image-preview
217 | $image-preview-counter-color := $color-white
218 |
219 | // tab-bar & tab-panel
220 | $tab-color := $color-grey
221 | $tab-active-color := $color-dark-orange
222 | $tab-slider-bgc := $color-dark-orange
223 |
--------------------------------------------------------------------------------
/src/views/About.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
This is an about page
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/views/Empty.vue:
--------------------------------------------------------------------------------
1 |
3 |
4 | empty
5 |
6 |
24 |
--------------------------------------------------------------------------------
/src/views/Home.vue:
--------------------------------------------------------------------------------
1 |
69 |
70 |
71 |
81 |
82 |
83 |

84 |
85 |
{{unFinCount}}
86 |
未完成工单
87 |
88 |
89 |
90 |

91 |
92 |
{{finCount}}
93 |
已完成工单
94 |
95 |
96 |
97 |
98 |
118 |
119 |
120 |
121 |
171 |
--------------------------------------------------------------------------------
/src/views/OrderAdd.vue:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
{{time}}
19 |
20 |

21 |
22 |
23 |
24 |
25 |
26 |
27 | 提交
28 |
29 |
30 |
31 |
32 |
33 |
76 |
--------------------------------------------------------------------------------
/src/views/OrderList.vue:
--------------------------------------------------------------------------------
1 |
13 |
14 |
15 |
16 | -
17 |
18 |
{{x.orderName}}
19 |
¥{{x.totalPrice}}
20 |
{{x.createtime}}
21 |
22 | 处理待办
23 |
24 | - 当前没有订单数据
25 |
26 |
27 |
28 |
63 |
--------------------------------------------------------------------------------
/src/views/Result.vue:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
16 |

17 |
恭喜! 信息提交成功
18 |
19 |
20 | 回到首页
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/static/dingding-sdk.sql:
--------------------------------------------------------------------------------
1 | /*
2 | Navicat MySQL Data Transfer
3 |
4 | Source Server : mytencent
5 | Source Server Version : 50726
6 | Source Host : 94.191.121.109:3306
7 | Source Database : dingding-sdk
8 |
9 | Target Server Type : MYSQL
10 | Target Server Version : 50726
11 | File Encoding : 65001
12 |
13 | Date: 2019-10-06 15:19:34
14 | */
15 |
16 | SET FOREIGN_KEY_CHECKS=0;
17 |
18 | -- ----------------------------
19 | -- Table structure for dd_config
20 | -- ----------------------------
21 | DROP TABLE IF EXISTS `dd_config`;
22 | CREATE TABLE `dd_config` (
23 | `id` int(11) NOT NULL AUTO_INCREMENT,
24 | `ukey` varchar(64) NOT NULL,
25 | `uname` varchar(128) DEFAULT NULL,
26 | `sname` varchar(64) DEFAULT NULL,
27 | `corpid` varchar(128) NOT NULL,
28 | `corpsecret` varchar(128) DEFAULT NULL,
29 | `appkey` varchar(128) DEFAULT NULL,
30 | `appsecret` varchar(128) DEFAULT NULL,
31 | `agentid` varchar(128) DEFAULT NULL,
32 | `chatid` varchar(128) DEFAULT NULL,
33 | `access_token` varchar(128) DEFAULT NULL,
34 | `token_begin_time` timestamp NULL DEFAULT NULL,
35 | `ticket` varchar(128) DEFAULT NULL,
36 | `ticket_begin_time` timestamp NULL DEFAULT NULL,
37 | `url` varchar(256) DEFAULT NULL,
38 | `process_code` varchar(64) DEFAULT NULL,
39 | PRIMARY KEY (`ukey`),
40 | KEY `id` (`id`)
41 | ) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8mb4;
42 |
43 | -- ----------------------------
44 | -- Records of dd_config
45 | -- ----------------------------
46 | INSERT INTO `dd_config` VALUES ('2', 'pluto1114', '功夫熊猫', '熊猫', 'ding275ce32e2776968e35c2f4657eb6378f', null, 'ding5xtlfq9fetzeu9lh', 'UxFQjUYies19AdPd7zAkf7Y2ApXre1JryYVOVhM8A8vrCW8QH4KCToVmLinmpgiG', '273096225', 'chat9c5f8af5a1ad3768a648a0a0d3c96dea', '3440a736fff837a3a3e06a74b6caf237', '2019-10-06 14:07:56', 'LyoXbMWD9VGNikFRHmOxP0WUuCz7JjoXrGP3VIdbm1K9B2M4oGUc55qYgkVYFW73R3lITksAcdHCz9skJnpG2t', '2019-10-01 09:05:38', 'http://94.191.121.109/dingding-sdk', 'PROC-8143FE43-735A-400A-8B75-1B64C137F1FB');
47 |
48 | -- ----------------------------
49 | -- Table structure for t_order
50 | -- ----------------------------
51 | DROP TABLE IF EXISTS `t_order`;
52 | CREATE TABLE `t_order` (
53 | `orderId` bigint(20) NOT NULL AUTO_INCREMENT,
54 | `orderName` varchar(255) DEFAULT NULL,
55 | `userid` varchar(64) DEFAULT NULL,
56 | `totalPrice` decimal(10,2) DEFAULT NULL,
57 | `orderStatus` varchar(64) DEFAULT NULL,
58 | `processInstanceId` varchar(64) DEFAULT NULL,
59 | `createtime` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
60 | PRIMARY KEY (`orderId`)
61 | ) ENGINE=InnoDB AUTO_INCREMENT=1570343722608 DEFAULT CHARSET=utf8mb4;
62 |
63 | -- ----------------------------
64 | -- Records of t_order
65 | -- ----------------------------
66 | INSERT INTO `t_order` VALUES ('1570341114736', 'test2', 'manager8036', '666.00', 'orderFinish', '76bf06c0-6fd4-4bfa-921b-4be5917422c9', '2019-10-06 14:29:51');
67 | INSERT INTO `t_order` VALUES ('1570342076477', 'kk', 'manager8036', '456.00', 'orderFinish', '1a7cb361-5e96-4dd9-b09d-7ea0af70d9c6', '2019-10-06 14:29:48');
68 | INSERT INTO `t_order` VALUES ('1570342365605', 'gg', 'manager8036', '899.00', 'orderFinish', '772d6a44-cc30-4286-ab7d-08b33f74d4b6', '2019-10-06 14:15:26');
69 | INSERT INTO `t_order` VALUES ('1570343722607', '音乐', 'manager8036', '487.00', 'orderFinish', 'c6ce5bcf-51d9-4ad8-9ff4-d13634194c9b', '2019-10-06 14:35:54');
70 |
71 | -- ----------------------------
72 | -- Table structure for t_user
73 | -- ----------------------------
74 | DROP TABLE IF EXISTS `t_user`;
75 | CREATE TABLE `t_user` (
76 | `id` int(11) NOT NULL AUTO_INCREMENT,
77 | `userid` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL,
78 | `name` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
79 | `department` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
80 | `departmentName` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
81 | `mobile` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
82 | `email` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
83 | `avatar` varchar(256) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
84 | `openid` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
85 | `unionid` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
86 | `createtime` datetime NOT NULL,
87 | `accesstime` datetime DEFAULT NULL,
88 | `hot` int(11) DEFAULT '0',
89 | `upDepart` bigint(20) DEFAULT NULL,
90 | `ukey` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
91 | `point` int(11) DEFAULT '0',
92 | `god` tinyint(1) NOT NULL DEFAULT '0',
93 | `role` varchar(16) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'P',
94 | PRIMARY KEY (`userid`),
95 | UNIQUE KEY `id` (`id`) USING BTREE
96 | ) ENGINE=InnoDB AUTO_INCREMENT=2325 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
97 |
98 | -- ----------------------------
99 | -- Records of t_user
100 | -- ----------------------------
101 | INSERT INTO `t_user` VALUES ('2324', 'manager8036', '高健', '1', null, '18698401720', '', 'https://static-legacy.dingtalk.com/media/lADPDgQ9q-ph7vDNAoDNAeA_480_640.jpg', '2dNE0hnueBGiSc4pIzii1HSgiEiE', null, '2019-10-06 12:51:51', '2019-10-06 14:35:35', '13', null, 'pluto1114', '0', '1', 'P');
102 |
--------------------------------------------------------------------------------
/vue.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | publicPath: process.env.NODE_ENV === 'production'
3 | ? '/dingding-sdk'
4 | : '/',
5 | productionSourceMap: false,
6 | css: {
7 | loaderOptions: {
8 | stylus: {
9 | 'resolve url': true,
10 | 'import': [
11 | './src/theme'
12 | ]
13 | }
14 | }
15 | },
16 | pluginOptions: {
17 | 'cube-ui': {
18 | postCompile: true,
19 | theme: true
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------