瀏覽代碼

本地同步

zhibin 6 年之前
當前提交
b361a74731
共有 100 個文件被更改,包括 2736 次插入0 次删除
  1. 17 0
      .gitignore
  2. 二進制
      FdageServer.zip
  3. 42 0
      app.js
  4. 31 0
      config/sys.json
  5. 31 0
      config/sys_test.json
  6. 59 0
      intercept/error.js
  7. 21 0
      intercept/permission.js
  8. 39 0
      module/Case.js
  9. 253 0
      module/DBModule.js
  10. 37 0
      module/News.js
  11. 21 0
      module/User.js
  12. 74 0
      module/database.sql
  13. 610 0
      package-lock.json
  14. 23 0
      package.json
  15. 149 0
      router/case.js
  16. 20 0
      router/index.js
  17. 145 0
      router/news.js
  18. 53 0
      router/public.js
  19. 32 0
      router/user.js
  20. 267 0
      static/creation/index.html
  21. 7 0
      static/creation/js/detect.mobile.js
  22. 44 0
      static/creation/js/jquery.easing.min.js
  23. 2 0
      static/creation/js/jquery.min.js
  24. 759 0
      static/creation/js/model-data.js
  25. 二進制
      static/creation/photos/01.png
  26. 二進制
      static/creation/photos/02.png
  27. 二進制
      static/creation/photos/03.png
  28. 二進制
      static/creation/photos/04.png
  29. 二進制
      static/creation/photos/05.png
  30. 二進制
      static/creation/photos/06.png
  31. 二進制
      static/creation/photos/07.png
  32. 二進制
      static/creation/photos/08.png
  33. 二進制
      static/creation/photos/09.png
  34. 二進制
      static/creation/photos/10.png
  35. 二進制
      static/creation/photos/100.png
  36. 二進制
      static/creation/photos/11.png
  37. 二進制
      static/creation/photos/12.png
  38. 二進制
      static/creation/photos/13.png
  39. 二進制
      static/creation/photos/14.png
  40. 二進制
      static/creation/photos/15.png
  41. 二進制
      static/creation/photos/16.png
  42. 二進制
      static/creation/photos/17.png
  43. 二進制
      static/creation/photos/18.png
  44. 二進制
      static/creation/photos/19.png
  45. 二進制
      static/creation/photos/20.png
  46. 二進制
      static/creation/photos/21.png
  47. 二進制
      static/creation/photos/22.png
  48. 二進制
      static/creation/photos/23.png
  49. 二進制
      static/creation/photos/24.png
  50. 二進制
      static/creation/photos/25.png
  51. 二進制
      static/creation/photos/26.png
  52. 二進制
      static/creation/photos/27.png
  53. 二進制
      static/creation/photos/28.png
  54. 二進制
      static/creation/photos/29.png
  55. 二進制
      static/creation/photos/30.png
  56. 二進制
      static/creation/photos/31.png
  57. 二進制
      static/creation/photos/32.png
  58. 二進制
      static/creation/photos/33.png
  59. 二進制
      static/creation/photos/34.png
  60. 二進制
      static/creation/photos/35.png
  61. 二進制
      static/creation/photos/36.png
  62. 二進制
      static/creation/photos/37.png
  63. 二進制
      static/creation/photos/38.png
  64. 二進制
      static/creation/photos/39.png
  65. 二進制
      static/creation/photos/40.png
  66. 二進制
      static/creation/photos/41.png
  67. 二進制
      static/creation/photos/42.png
  68. 二進制
      static/creation/photos/43.png
  69. 二進制
      static/creation/photos/44.png
  70. 二進制
      static/creation/photos/45.png
  71. 二進制
      static/creation/photos/46.png
  72. 二進制
      static/creation/photos/47.png
  73. 二進制
      static/creation/photos/48.png
  74. 二進制
      static/creation/photos/49.png
  75. 二進制
      static/creation/photos/50.png
  76. 二進制
      static/creation/photos/51.png
  77. 二進制
      static/creation/photos/52.png
  78. 二進制
      static/creation/photos/53.png
  79. 二進制
      static/creation/photos/54.png
  80. 二進制
      static/creation/photos/55.png
  81. 二進制
      static/creation/photos/56.png
  82. 二進制
      static/creation/photos/57.png
  83. 二進制
      static/creation/photos/58.png
  84. 二進制
      static/creation/photos/59.png
  85. 二進制
      static/creation/photos/60.png
  86. 二進制
      static/creation/photos/61.png
  87. 二進制
      static/creation/photos/62.png
  88. 二進制
      static/creation/photos/63.png
  89. 二進制
      static/creation/photos/64.png
  90. 二進制
      static/creation/photos/65.png
  91. 二進制
      static/creation/photos/66.png
  92. 二進制
      static/creation/photos/67.png
  93. 二進制
      static/creation/photos/68.png
  94. 二進制
      static/creation/photos/69.png
  95. 二進制
      static/creation/photos/70.png
  96. 二進制
      static/creation/photos/71.png
  97. 二進制
      static/creation/photos/72.png
  98. 二進制
      static/creation/photos/73.png
  99. 二進制
      static/creation/photos/74.png
  100. 0 0
      static/creation/photos/75.png

+ 17 - 0
.gitignore

@@ -0,0 +1,17 @@
+.DS_Store
+node_modules/
+/dist/
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+/test/unit/coverage/
+/test/e2e/reports/
+selenium-debug.log
+
+# Editor directories and files
+.idea
+.vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln

二進制
FdageServer.zip


+ 42 - 0
app.js

@@ -0,0 +1,42 @@
+const Koa = require('koa');
+const bodyParser = require('koa-bodyparser');
+const session = require('koa-session-minimal');
+const MysqlSession = require('koa-mysql-session');
+const static = require('koa-static');
+const path = require('path');
+const sys = require('./config/sys.json');
+const router = require('./router');
+
+const app = new Koa();
+const store = new MysqlSession({
+  connectTimeout  : 60* 60 * 60 * 1000,
+  host: sys.session.host,
+  user: sys.session.user,
+  password: sys.session.pwd,
+  database: sys.session.db
+});
+const cookie = {
+  maxAge: sys.session.max_age,
+  path: sys.session.path,
+  domain: sys.session.domain,
+  httpOnly: sys.session.http_only
+}
+
+
+app.use(bodyParser({
+  "formLimit": "50mb",
+  "jsonLimit": "50mb",
+  "textLimit": "50mb"
+}));
+app.use(session({
+  key: sys.session.key,
+  store: store,
+  cookie: cookie
+}));
+app.use(router.routes());
+app.use(router.allowedMethods());
+app.use(static(path.join(__dirname, sys.static_dir), {handle: true}));
+
+app.listen(sys.port, () => {
+    console.log(`${sys.pro_name} is starting at port ${sys.port}`);
+});

+ 31 - 0
config/sys.json

@@ -0,0 +1,31 @@
+{
+  "static_dir": "/static",
+  "session": {
+    "host": "localhost",
+    "db": "4dageOffcial",
+    "user": "4dage",
+    "pwd": "123456",
+    "key": "session key",
+    "path": "/",
+    "max_age": 86400000,
+    "http_only": false,
+    "domain": null
+  },
+  "mysql": {
+    "host": "localhost",
+    "db": "4dageOffcial",
+    "user": "4dage",
+    "pwd": "123456"
+  },
+  "mail": {
+    "service": "qq",
+    "account": "854556519@qq.com",
+    "pass": "gjoiykrnepbabebi"
+  },
+  "static_prefix": "/newOfficialapi",
+  "port": 3000,
+  "pro_name": "Fdageserve",
+  "err_sendee": "854556519@qq.com",
+  "debug": true,
+  "tourist": "tourist"
+}

+ 31 - 0
config/sys_test.json

@@ -0,0 +1,31 @@
+{
+    "static_dir": "/static",
+    "session": {
+        "host": "localhost",
+        "db": "4dageOffcial_test",
+        "user": "4dage",
+        "pwd": "123456",
+        "key": "session key",
+        "path": "/",
+        "max_age": 86400000,
+        "http_only": false,
+        "domain": null
+    },
+    "mysql": {
+        "host": "localhost",
+        "db": "4dageOffcial_test",
+        "user": "4dage",
+        "pwd": "123456"
+    },
+    "mail": {
+        "service": "qq",
+        "account": "854556519@qq.com",
+        "pass": "gjoiykrnepbabebi"
+    },
+    "static_prefix": "/newOfficialapi",
+    "port": 7000,
+    "pro_name": "Fdageserve",
+    "err_sendee": "854556519@qq.com",
+    "debug": true,
+    "tourist": "tourist"
+}

+ 59 - 0
intercept/error.js

@@ -0,0 +1,59 @@
+const mailSend = require('../util/mailSend');
+const sys = require('../config/sys');
+
+let api, adminMail;
+
+class OwnError extends Error {
+  constructor(msg = '', code = 400, additional = undefined) {
+    super();
+    this.msg = msg;
+    this.code = code;
+    this.additional = additional;
+  }
+}
+
+function err(msg, code, additional) {
+  throw (new OwnError(msg, code, additional));
+}
+
+async function error(ctx, next) {
+  try {
+    ctx[api] = err;
+    await next()
+  } catch (e) {
+    let body;
+
+    if (e instanceof OwnError) {
+      ctx.status = e.code
+      body = {
+        msg: e.msg,
+        content: e.additional
+      }
+    } else {
+      ctx.status = 500
+      body = {code: 500, msg: '系统发生错误,请稍后再试!'};
+
+      if (!sys.debug && adminMail) {
+        await mailSend({
+            to: adminMail,
+            subject: '4维时代错误提醒',
+            html: `<h1>${e.message}</h1><div>${e.stack ? e.stack.replace(/\n/ig, '<br>') : e}</div>`
+        });
+      } else {
+        throw e;
+      }
+    }
+
+    ctx.body = body;
+  }
+}
+
+
+function init(_api = 'error', _adminMail) {
+  api = _api;
+  adminMail = _adminMail;
+
+  return error;
+}
+
+module.exports = exports = init;

+ 21 - 0
intercept/permission.js

@@ -0,0 +1,21 @@
+const User = require('../module/User');
+
+async function permission(ctx, next) {
+  if (!ctx.session.user) {
+    return ctx.error('请登陆后在执行此操作!', 401);
+  }
+
+  let user = new User();
+  user.name = ctx.session.user.name;
+  
+  let result = await user.query();
+  if (result.length === 0 || result[0].hide) {
+    ctx.error('该账号不存在!');
+  } else if (result[0].psw !== ctx.session.user.psw) {
+    ctx.error('密码错误');
+  } else {
+    await next();
+  }
+}
+
+module.exports = exports = permission;

+ 39 - 0
module/Case.js

@@ -0,0 +1,39 @@
+const DBModule = require('./DBModule');
+
+class Case extends DBModule {
+
+  get table() {
+    return 'case'
+  }
+
+  get primary() {
+    return 'id'
+  }
+
+  get fields() {
+    return [
+      'id', 'title', 'content', 'cover', 'logo', 'label',
+      'date', 'sort', 'link', 'address', 'hide', 'user_id', 'type', 
+      'english_id', 'chinese_id', 'language', 'pro_type'
+    ]
+  }
+
+  paging(page, limit, keyword = '', label, language) {
+    let joinSql = '';
+
+    label && (joinSql += `and label = '${label}'`);
+    language && (joinSql += `and language = '${language}'`);
+
+    let sql = `select {{header}} from \`case\` where title like '%${keyword}%' and hide=${this.hide} ${joinSql} order by \`sort\` asc`
+    return super.paging({
+      page,
+      limit,
+      start: page * limit,
+      sql,
+      paging: 1,
+      headers: '*'
+    })
+  }
+}
+
+module.exports = exports = Case;

+ 253 - 0
module/DBModule.js

@@ -0,0 +1,253 @@
+const mysql = require('mysql');
+const sys = require('../config/sys_test');
+const pool = mysql.createPool({
+  connectionLimit: 1,
+  connectTimeout: 60 * 60 * 1000,
+  host: sys.mysql.host,
+  user: sys.mysql.user,
+  password: sys.mysql.pwd,
+  database: sys.mysql.db
+});
+
+class DBModule {
+  constructor(args = {}) {
+    Object.keys(args).forEach(key => {
+      this[key] = args[key];
+    })
+  }
+
+  /**
+   * 使用连接池中已有的连接执行sql脚本
+   * @param  {string} sql sql脚本
+   * @param  {array} args sql中的参数
+   * @return {promise}      
+   */
+  _query(sql, args = []) {
+    return new Promise((resolve, reject) => {
+      pool.getConnection((err, connection) => {
+        if (err) return reject(err);
+
+        if (sys.debug) {
+          console.log(`run ${sql} \narray ${args.map(item=> `${item}  type: ${typeof item}\n`)}`)
+        }
+        connection.query(sql, args, (err, result) => {
+          if (err) {
+            reject(err);
+          } else {
+            resolve(result);
+          }
+  
+          connection.release();
+        });
+      });
+    });
+  }
+
+  
+  /**
+   * 执行对象插入数据库操作
+   * @return {promise}      
+   */
+  insert() {
+    let sql, {attrs, vals, err} = DBModule.getDBModuleArgs(this);
+
+    if (err) {
+      throw `object ${this.constructor.toString()} lack necessary field (table, fields)`;
+    } 
+
+    sql = `insert into \`${this.table}\`(${attrs.join(',')}) values(${vals.map(()=>'?')})`;
+
+    return this._query(sql, vals);
+  }
+
+  /**
+   * 执行对象更新映射到数据库操作,对象必须存在有效的主键
+   * @return {promise}      
+   */
+  update() {
+    let sql, setFields, attrs, vals, err;
+
+    if (this[this.primary] === undefined || this[this.primary] === null) {
+      throw `object ${this.constructor.toString()} ${this.primary} is ${this[this.primary]}`;
+    }
+
+    ({attrs, vals, err} = DBModule.getDBModuleArgs(this));
+
+    if (err) {
+      throw `object ${this.constructor.toString()} lack necessary field (table, fields)`;
+    } 
+
+    vals.push(this[this.primary]);
+
+    setFields = attrs.map(attr=>`${attr}=?`);
+    sql = `update \`${this.table}\` set ${setFields.join(',')} where ${this.primary}=?`;
+
+    return this._query(sql, vals);
+  }
+
+  /**
+   * 查看某条件的数据是否存在
+   * @return {promise}      
+   */
+  exists() {
+    let fields, {attrs, vals, err} = DBModule.getDBModuleArgs(this);
+    
+    if (err) {
+      throw `object ${this.constructor.toString()} lack necessary field (table, fields)`;
+    }
+
+    fields = attrs.map(attr=>` ${attr}=? `);
+    fields.push(' 1=1 ');
+
+    return this._query(`select count(*) as count from \`${this.table}\` where ${fields.join(' and ')}`, vals)
+        .then(result => {
+          return result[0].count !== 0
+        });
+  }
+
+  /**
+   * 删除数据库中单行操作,对象必须存在有效的主键
+   * @return {promise}      
+   */
+  delete() {
+    let sql, vals;
+
+    if (this[this.primary] === undefined || this[this.primary] === null) {
+      throw `object ${this.constructor.toString()} ${this.primary} is ${this[this.primary]}`;
+    } else if (DBModule.getDBModuleArgs(this).err) {
+      throw `object ${this.constructor.toString()} lack necessary field (table, fields)`;
+    }
+
+    vals = [this[this.primary]]
+    sql = `delete from \`${this.table}\` where ${this.primary}=?`;
+
+    return this._query(sql, vals);
+  }
+
+  /**
+   * 查询该对象表中的数据
+   * @param connect 多字段要连接字符 如 and or
+   * @param start 分页时开始位置
+   * @param limit 分页时要获取的条数
+   * @param afterAgs 要附加的参数
+   * @return {promise}      
+   */
+  query({connect = DBModule.AND, start = 0, limit, sql} = {}, beforeAgs) {
+    let conneSql = '', fields, {attrs, vals, err} = DBModule.getDBModuleArgs(this);
+
+    if (err) {
+      throw `object ${this.constructor.toString()} lack necessary field (table, fields)`;
+    } else if (connect !== DBModule.AND && connect !== DBModule.OR) {
+      throw `query functiton connect args must be DBModule.AND or DBModule.OR`;
+    }
+
+    if (Number.isFinite(Number(this[this.primary]))) {
+      attrs.push(this.primary);
+      vals.push(this[this.primary]);
+    }
+
+    if (limit > 0) {
+      conneSql = ` LIMIT ?,?`;
+      vals.push(start);
+      vals.push(limit);
+    }
+
+    fields = attrs.map(attr => ` \`${this.table}\`.${attr}=? `);
+    fields.push(' 1=1 ');
+
+    if (sql) {
+      sql = `select * from (${sql}) as \`${this.table}\` `;
+    } else {
+      sql = `select * from \`${this.table}\` `;
+    }
+
+    sql = `${sql} where ${fields.join(connect)} ${conneSql}`
+
+    if (beforeAgs && beforeAgs.length > 0) {
+      vals = beforeAgs.concat(vals);
+    }
+
+    return this._query(sql, vals);
+  }
+
+  /**
+   * 分页模式数据统一处理
+   * @param {*} paging number 是否要开启分页模式
+   *      limit  number 每页的条数
+   *      start  number 从哪条开始读取
+   *      header string 获取表的表头
+   *      vals   array  sql的参数
+   *      sql  string sql语句表头用{{header}}代替
+   */
+  paging({paging = 0, limit = 15, start = 0, sql, headers = 'header', vals = []} = {}) {
+    let pData, pCount, conneSql = '';
+
+    if (!sql) return Promise.resolve(1);
+    if (limit > 0) {
+      conneSql = ` LIMIT ?,?`;
+      vals.push(start);
+      vals.push(limit);
+    }
+
+    pData = this._query(sql.replace('{{header}}', headers) + conneSql, vals);
+
+    if (paging) {
+      pCount = this._query(sql.replace('{{header}}', 'count(*) as len'), vals);
+      return Promise.all([pData, pCount])
+          .then((arrs) => {
+            return {
+              total: arrs[1][0].len, 
+              data: arrs[0],
+              average: limit
+            }
+          });
+    } else {
+      return pData;
+    }
+  }
+
+  /**
+   * 检测对象是否符合DBModule要求并获取对象能执行_query的参数
+   * @param {object} dbModule要检测的对象
+   * @return {object} fileds: err attrs vals
+   *    {boolean} err 是否符合DBModule的要求
+   *    {array} attrs 要进行数据库操作的字段
+   *    {array} vals 要进行数据库操作的字段对应的值 
+   */
+  static getDBModuleArgs(dbModule) {
+    if(!((dbModule.table && dbModule.table.length > 0) &&
+       (dbModule.fields && dbModule.fields instanceof Array && dbModule.fields.length > 0) 
+      )) {
+      return {err: true};
+    }
+
+    let attrs = [], vals = [];
+
+    for (let field of dbModule.fields) {
+      if (dbModule[field] !== undefined) {
+        attrs.push('`'+field+'`');
+        vals.push(dbModule[field]);
+      }
+    }
+
+    return {attrs, vals, err: false};
+  }
+
+  static get AND() {
+    return 'and';
+  } 
+
+  static get OR() {
+    return 'or';
+  }
+
+  static get HOT() {
+    return 'hot';
+  }
+
+  static get SOAR() {
+    return 'soar';
+  }
+}
+
+module.exports = exports = DBModule;

+ 37 - 0
module/News.js

@@ -0,0 +1,37 @@
+const DBModule = require('./DBModule');
+
+class News extends DBModule {
+
+  get table() {
+    return 'news'
+  }
+
+  get primary() {
+    return 'id'
+  }
+
+  get fields() {
+    return [
+      'id', 'title', 'content', 'cover', 'label',
+      'date', 'sort', 'address', 'hide', 'user_id', 'origin',
+      'english_id', 'chinese_id', 'language', 'redire'
+    ]
+  }
+
+  paging(page, limit, keyword = '', language) {
+    let joinSql = '';
+
+    language && (joinSql += `and language = '${language}'`);
+    let sql = `select {{header}} from \`news\` where title like '%${keyword}%' and hide=${this.hide} ${joinSql} order by \`sort\` asc`
+    return super.paging({
+      page,
+      limit,
+      start: page * limit,
+      sql,
+      paging: 1,
+      headers: '*'
+    })
+  }
+}
+
+module.exports = exports = News;

+ 21 - 0
module/User.js

@@ -0,0 +1,21 @@
+const DBModule = require('./DBModule');
+
+class User extends DBModule {
+
+    get table() { 
+        return 'user' 
+    }
+
+    get primary() {
+        return 'id'
+    }
+
+    get fields() {
+        return [
+            'id', 'name', 'psw', 'describe',
+            'time', 'hide'
+        ]
+    }
+}
+
+module.exports = User;

+ 74 - 0
module/database.sql

@@ -0,0 +1,74 @@
+create database if not exists 4dageOffcial default character set utf8mb4 collate utf8mb4_unicode_ci;
+
+-- 切换到4维官网数据库
+use 4dageOffcial;
+
+/**
+* 清除所有表
+*/
+drop table if exists `case`;
+drop table if exists `news`;
+drop table if exists `user`;
+
+
+/**
+ * 用户表
+ */
+create table if not exists `user`(
+    `id`          integer         not null    auto_increment,
+    `name`        char(36)        not null,
+    `psw`         char(33),
+    `describe`    varchar(100),      
+    `time`        datetime        not null    default CURRENT_TIMESTAMP,
+    `hide`        integer         not null    default 0,
+    primary key(`id`)
+) engine=InnoDB charset=utf8mb4;
+
+
+/**
+ * 如果没有初始化管理员账号则初始化一个
+ */
+INSERT INTO `user`(`name`, `psw`, `describe`) 
+SELECT 'admin', 'c3284d0f94606de1fd2af172aba15bf3', '管理员' FROM DUAL 
+WHERE NOT EXISTS(SELECT `describe` FROM `user` WHERE `describe` = '管理员');
+
+-- 案例
+create table if not exists `case`(
+    `id`      integer         not null    auto_increment,
+    `title`   varchar(255)    not null,
+    `content` longtext        not null,
+    `cover`   varchar(500),
+    `logo`    varchar(500),
+    `label`   varchar(500),
+    `date`    varchar(33)        not null,
+    `sort`    integer,
+    `link`    varchar(255),
+    `type`    integer         not null    default 1,
+    `address` varchar(255),
+    `hide`    integer         not null    default 0,
+    `user_id` integer         not null,
+
+    primary key(`id`),
+    fulltext (`title`) WITH PARSER ngram,
+    constraint FK_case_user foreign key(`user_id`) references user(`id`)
+) engine=InnoDB charset=utf8mb4;
+
+
+-- 案例
+create table if not exists `news`(
+    `id`      integer         not null    auto_increment,
+    `title`   varchar(255)    not null,
+    `content` longtext        not null,
+    `cover`   varchar(500),
+    `label`   varchar(500),
+    `date`    varchar(33)     not null ,
+    `sort`    integer,
+    `address` varchar(255),
+    `origin`  varchar(255),
+    `hide`    integer         not null    default 0,
+    `user_id` integer         not null,
+
+    primary key(`id`),
+    fulltext (`title`) WITH PARSER ngram,
+    constraint FK_news_user foreign key(`user_id`) references user(`id`)
+) engine=InnoDB charset=utf8mb4;

+ 610 - 0
package-lock.json

@@ -0,0 +1,610 @@
+{
+  "name": "fdageserver",
+  "version": "1.0.0",
+  "lockfileVersion": 1,
+  "requires": true,
+  "dependencies": {
+    "accepts": {
+      "version": "1.3.5",
+      "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz",
+      "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=",
+      "requires": {
+        "mime-types": "2.1.18",
+        "negotiator": "0.6.1"
+      }
+    },
+    "any-promise": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
+      "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8="
+    },
+    "bignumber.js": {
+      "version": "4.0.4",
+      "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-4.0.4.tgz",
+      "integrity": "sha512-LDXpJKVzEx2/OqNbG9mXBNvHuiRL4PzHCGfnANHMJ+fv68Ads3exDVJeGDJws+AoNEuca93bU3q+S0woeUaCdg=="
+    },
+    "busboy": {
+      "version": "0.2.14",
+      "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz",
+      "integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=",
+      "requires": {
+        "dicer": "0.2.5",
+        "readable-stream": "1.1.14"
+      },
+      "dependencies": {
+        "readable-stream": {
+          "version": "1.1.14",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
+          "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
+          "requires": {
+            "core-util-is": "1.0.2",
+            "inherits": "2.0.3",
+            "isarray": "0.0.1",
+            "string_decoder": "0.10.31"
+          }
+        },
+        "string_decoder": {
+          "version": "0.10.31",
+          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+          "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
+        }
+      }
+    },
+    "bytes": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
+      "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg="
+    },
+    "co": {
+      "version": "4.6.0",
+      "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+      "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
+    },
+    "co-body": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/co-body/-/co-body-6.0.0.tgz",
+      "integrity": "sha512-9ZIcixguuuKIptnY8yemEOuhb71L/lLf+Rl5JfJEUiDNJk0e02MBt7BPxR2GEh5mw8dPthQYR4jPI/BnS1MQgw==",
+      "requires": {
+        "inflation": "2.0.0",
+        "qs": "6.5.2",
+        "raw-body": "2.3.3",
+        "type-is": "1.6.16"
+      }
+    },
+    "co-mysql": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/co-mysql/-/co-mysql-0.4.1.tgz",
+      "integrity": "sha1-cnPr/ydoHAPDivmAvH4o94p7GTk=",
+      "requires": {
+        "mysql": "2.15.0"
+      }
+    },
+    "content-disposition": {
+      "version": "0.5.2",
+      "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz",
+      "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ="
+    },
+    "content-type": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
+      "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
+    },
+    "cookies": {
+      "version": "0.7.1",
+      "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.7.1.tgz",
+      "integrity": "sha1-fIphX1SBxhq58WyDNzG8uPZjuZs=",
+      "requires": {
+        "depd": "1.1.2",
+        "keygrip": "1.0.2"
+      }
+    },
+    "copy-to": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/copy-to/-/copy-to-2.0.1.tgz",
+      "integrity": "sha1-JoD7uAaKSNCGVrYJgJK9r8kG9KU="
+    },
+    "core-util-is": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+      "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
+    },
+    "debug": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+      "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+      "requires": {
+        "ms": "2.0.0"
+      }
+    },
+    "deep-equal": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
+      "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU="
+    },
+    "delegates": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
+      "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
+    },
+    "depd": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+      "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
+    },
+    "destroy": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
+      "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
+    },
+    "dicer": {
+      "version": "0.2.5",
+      "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz",
+      "integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=",
+      "requires": {
+        "readable-stream": "1.1.14",
+        "streamsearch": "0.1.2"
+      },
+      "dependencies": {
+        "readable-stream": {
+          "version": "1.1.14",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
+          "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
+          "requires": {
+            "core-util-is": "1.0.2",
+            "inherits": "2.0.3",
+            "isarray": "0.0.1",
+            "string_decoder": "0.10.31"
+          }
+        },
+        "string_decoder": {
+          "version": "0.10.31",
+          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+          "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
+        }
+      }
+    },
+    "ee-first": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+      "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
+    },
+    "error-inject": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/error-inject/-/error-inject-1.0.0.tgz",
+      "integrity": "sha1-4rPZG1Su1nLzCdlQ0VSFD6EdTzc="
+    },
+    "escape-html": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+      "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
+    },
+    "fresh": {
+      "version": "0.5.2",
+      "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+      "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
+    },
+    "http-assert": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.3.0.tgz",
+      "integrity": "sha1-oxpc+IyHPsu1eWkH1NbxMujAHko=",
+      "requires": {
+        "deep-equal": "1.0.1",
+        "http-errors": "1.6.3"
+      }
+    },
+    "http-errors": {
+      "version": "1.6.3",
+      "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
+      "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
+      "requires": {
+        "depd": "1.1.2",
+        "inherits": "2.0.3",
+        "setprototypeof": "1.1.0",
+        "statuses": "1.5.0"
+      }
+    },
+    "iconv-lite": {
+      "version": "0.4.23",
+      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
+      "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==",
+      "requires": {
+        "safer-buffer": "2.1.2"
+      }
+    },
+    "inflation": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/inflation/-/inflation-2.0.0.tgz",
+      "integrity": "sha1-i0F+R8KPklpFEz2RTKH9OJEH8w8="
+    },
+    "inherits": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+      "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+    },
+    "is-generator-function": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.7.tgz",
+      "integrity": "sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw=="
+    },
+    "isarray": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+      "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
+    },
+    "keygrip": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.0.2.tgz",
+      "integrity": "sha1-rTKXxVcGneqLz+ek+kkbdcXd65E="
+    },
+    "koa": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmjs.org/koa/-/koa-2.5.1.tgz",
+      "integrity": "sha512-cchwbMeG2dv3E2xTAmheDAuvR53tPgJZN/Hf1h7bTzJLSPcFZp8/t5+bNKJ6GaQZoydhZQ+1GNruhKdj3lIrug==",
+      "requires": {
+        "accepts": "1.3.5",
+        "content-disposition": "0.5.2",
+        "content-type": "1.0.4",
+        "cookies": "0.7.1",
+        "debug": "3.1.0",
+        "delegates": "1.0.0",
+        "depd": "1.1.2",
+        "destroy": "1.0.4",
+        "error-inject": "1.0.0",
+        "escape-html": "1.0.3",
+        "fresh": "0.5.2",
+        "http-assert": "1.3.0",
+        "http-errors": "1.6.3",
+        "is-generator-function": "1.0.7",
+        "koa-compose": "4.1.0",
+        "koa-convert": "1.2.0",
+        "koa-is-json": "1.0.0",
+        "mime-types": "2.1.18",
+        "on-finished": "2.3.0",
+        "only": "0.0.2",
+        "parseurl": "1.3.2",
+        "statuses": "1.5.0",
+        "type-is": "1.6.16",
+        "vary": "1.1.2"
+      },
+      "dependencies": {
+        "koa-compose": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-4.1.0.tgz",
+          "integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw=="
+        }
+      }
+    },
+    "koa-bodyparser": {
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/koa-bodyparser/-/koa-bodyparser-4.2.1.tgz",
+      "integrity": "sha512-UIjPAlMZfNYDDe+4zBaOAUKYqkwAGcIU6r2ARf1UOXPAlfennQys5IiShaVeNf7KkVBlf88f2LeLvBFvKylttw==",
+      "requires": {
+        "co-body": "6.0.0",
+        "copy-to": "2.0.1"
+      }
+    },
+    "koa-compose": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-3.2.1.tgz",
+      "integrity": "sha1-qFzLQLfZhtjlo0Wzoazo6rz1Tec=",
+      "requires": {
+        "any-promise": "1.3.0"
+      }
+    },
+    "koa-convert": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/koa-convert/-/koa-convert-1.2.0.tgz",
+      "integrity": "sha1-2kCHXfSd4FOQmNFwC1CCDOvNIdA=",
+      "requires": {
+        "co": "4.6.0",
+        "koa-compose": "3.2.1"
+      }
+    },
+    "koa-is-json": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/koa-is-json/-/koa-is-json-1.0.0.tgz",
+      "integrity": "sha1-JzwH7c3Ljfaiwat9We52SRRR7BQ="
+    },
+    "koa-mysql-session": {
+      "version": "0.0.2",
+      "resolved": "https://registry.npmjs.org/koa-mysql-session/-/koa-mysql-session-0.0.2.tgz",
+      "integrity": "sha1-t/MvTdLDel95kiYXl8WTc3BO3Ik=",
+      "requires": {
+        "co": "3.1.0",
+        "co-mysql": "0.4.1"
+      },
+      "dependencies": {
+        "co": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/co/-/co-3.1.0.tgz",
+          "integrity": "sha1-TqVOpaCJOBUxheFSEMaNkJK8G3g="
+        }
+      }
+    },
+    "koa-router": {
+      "version": "7.4.0",
+      "resolved": "https://registry.npmjs.org/koa-router/-/koa-router-7.4.0.tgz",
+      "integrity": "sha512-IWhaDXeAnfDBEpWS6hkGdZ1ablgr6Q6pGdXCyK38RbzuH4LkUOpPqPw+3f8l8aTDrQmBQ7xJc0bs2yV4dzcO+g==",
+      "requires": {
+        "debug": "3.1.0",
+        "http-errors": "1.6.3",
+        "koa-compose": "3.2.1",
+        "methods": "1.1.2",
+        "path-to-regexp": "1.7.0",
+        "urijs": "1.19.1"
+      }
+    },
+    "koa-send": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/koa-send/-/koa-send-5.0.0.tgz",
+      "integrity": "sha512-90ZotV7t0p3uN9sRwW2D484rAaKIsD8tAVtypw/aBU+ryfV+fR2xrcAwhI8Wl6WRkojLUs/cB9SBSCuIb+IanQ==",
+      "requires": {
+        "debug": "3.1.0",
+        "http-errors": "1.6.3",
+        "mz": "2.7.0",
+        "resolve-path": "1.4.0"
+      }
+    },
+    "koa-session-minimal": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/koa-session-minimal/-/koa-session-minimal-3.0.4.tgz",
+      "integrity": "sha1-1qFb7u131dPiakIdu5imH2Oor80=",
+      "requires": {
+        "co": "4.6.0",
+        "deep-equal": "1.0.1",
+        "uid-safe": "2.1.5"
+      }
+    },
+    "koa-static": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/koa-static/-/koa-static-5.0.0.tgz",
+      "integrity": "sha512-UqyYyH5YEXaJrf9S8E23GoJFQZXkBVJ9zYYMPGz919MSX1KuvAcycIuS0ci150HCoPf4XQVhQ84Qf8xRPWxFaQ==",
+      "requires": {
+        "debug": "3.1.0",
+        "koa-send": "5.0.0"
+      }
+    },
+    "media-typer": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+      "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
+    },
+    "methods": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+      "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
+    },
+    "mime-db": {
+      "version": "1.33.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz",
+      "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ=="
+    },
+    "mime-types": {
+      "version": "2.1.18",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz",
+      "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==",
+      "requires": {
+        "mime-db": "1.33.0"
+      }
+    },
+    "ms": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+      "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+    },
+    "mysql": {
+      "version": "2.15.0",
+      "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.15.0.tgz",
+      "integrity": "sha512-C7tjzWtbN5nzkLIV+E8Crnl9bFyc7d3XJcBAvHKEVkjrYjogz3llo22q6s/hw+UcsE4/844pDob9ac+3dVjQSA==",
+      "requires": {
+        "bignumber.js": "4.0.4",
+        "readable-stream": "2.3.3",
+        "safe-buffer": "5.1.1",
+        "sqlstring": "2.3.0"
+      }
+    },
+    "mz": {
+      "version": "2.7.0",
+      "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
+      "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
+      "requires": {
+        "any-promise": "1.3.0",
+        "object-assign": "4.1.1",
+        "thenify-all": "1.6.0"
+      }
+    },
+    "negotiator": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
+      "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk="
+    },
+    "nodemailer": {
+      "version": "4.6.7",
+      "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-4.6.7.tgz",
+      "integrity": "sha512-GIAAYvs9XIP1fBa8wR89ukUh3yjL44pom5LKY5nTZcL+Zp9sRkqL8wgskyBQECQg9CPsDX/fjTZx8MNz20t0jA=="
+    },
+    "object-assign": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+      "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
+    },
+    "on-finished": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+      "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
+      "requires": {
+        "ee-first": "1.1.1"
+      }
+    },
+    "only": {
+      "version": "0.0.2",
+      "resolved": "https://registry.npmjs.org/only/-/only-0.0.2.tgz",
+      "integrity": "sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q="
+    },
+    "parseurl": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz",
+      "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M="
+    },
+    "path-is-absolute": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+      "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
+    },
+    "path-to-regexp": {
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz",
+      "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=",
+      "requires": {
+        "isarray": "0.0.1"
+      }
+    },
+    "process-nextick-args": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
+      "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
+    },
+    "qs": {
+      "version": "6.5.2",
+      "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
+      "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
+    },
+    "random-bytes": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
+      "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs="
+    },
+    "raw-body": {
+      "version": "2.3.3",
+      "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz",
+      "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==",
+      "requires": {
+        "bytes": "3.0.0",
+        "http-errors": "1.6.3",
+        "iconv-lite": "0.4.23",
+        "unpipe": "1.0.0"
+      }
+    },
+    "readable-stream": {
+      "version": "2.3.3",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz",
+      "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==",
+      "requires": {
+        "core-util-is": "1.0.2",
+        "inherits": "2.0.3",
+        "isarray": "1.0.0",
+        "process-nextick-args": "1.0.7",
+        "safe-buffer": "5.1.1",
+        "string_decoder": "1.0.3",
+        "util-deprecate": "1.0.2"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+        }
+      }
+    },
+    "resolve-path": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/resolve-path/-/resolve-path-1.4.0.tgz",
+      "integrity": "sha1-xL2p9e+y/OZSR4c6s2u02DT+Fvc=",
+      "requires": {
+        "http-errors": "1.6.3",
+        "path-is-absolute": "1.0.1"
+      }
+    },
+    "safe-buffer": {
+      "version": "5.1.1",
+      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
+      "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg=="
+    },
+    "safer-buffer": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+    },
+    "setprototypeof": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
+      "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ=="
+    },
+    "sqlstring": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.0.tgz",
+      "integrity": "sha1-UluKT9Jtb3GqYegipsr5dtMa0qg="
+    },
+    "statuses": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
+      "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
+    },
+    "streamsearch": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz",
+      "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo="
+    },
+    "string_decoder": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
+      "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
+      "requires": {
+        "safe-buffer": "5.1.1"
+      }
+    },
+    "thenify": {
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.0.tgz",
+      "integrity": "sha1-5p44obq+lpsBCCB5eLn2K4hgSDk=",
+      "requires": {
+        "any-promise": "1.3.0"
+      }
+    },
+    "thenify-all": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
+      "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=",
+      "requires": {
+        "thenify": "3.3.0"
+      }
+    },
+    "type-is": {
+      "version": "1.6.16",
+      "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz",
+      "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==",
+      "requires": {
+        "media-typer": "0.3.0",
+        "mime-types": "2.1.18"
+      }
+    },
+    "uid-safe": {
+      "version": "2.1.5",
+      "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
+      "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==",
+      "requires": {
+        "random-bytes": "1.0.0"
+      }
+    },
+    "unpipe": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+      "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
+    },
+    "urijs": {
+      "version": "1.19.1",
+      "resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.1.tgz",
+      "integrity": "sha512-xVrGVi94ueCJNrBSTjWqjvtgvl3cyOTThp2zaMaFNGp3F542TR6sM3f2o8RqZl+AwteClSVmoCyt0ka4RjQOQg=="
+    },
+    "util-deprecate": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+      "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
+    },
+    "vary": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+      "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
+    }
+  }
+}

+ 23 - 0
package.json

@@ -0,0 +1,23 @@
+{
+  "name": "fdageserver",
+  "version": "1.0.0",
+  "description": "",
+  "main": "index.js",
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "author": "",
+  "license": "ISC",
+  "dependencies": {
+    "busboy": "^0.2.14",
+    "koa": "^2.5.1",
+    "koa-bodyparser": "^4.2.1",
+    "koa-mysql-session": "0.0.2",
+    "koa-router": "^7.4.0",
+    "koa-session-minimal": "^3.0.4",
+    "koa-static": "^5.0.0",
+    "mysql": "^2.15.0",
+    "nodemailer": "^4.6.7",
+    "qiniu": "^7.2.1"
+  }
+}

+ 149 - 0
router/case.js

@@ -0,0 +1,149 @@
+const Case = require('../module/Case');
+const Router = require('koa-router');
+const permission = require('../intercept/permission');
+const router = new Router();
+
+async function getCase(id) {
+  let _case = new Case();
+  _case.id = id;
+
+  let [result = {}] = await _case.query()
+
+  return result
+}
+
+/**
+ * 获取案例数据
+ */
+router.get('/', async ctx => {
+  let { page = 1, keyword = '', limit = 15, label, language } = ctx.request.query;
+  let _case = new Case();
+  
+  _case.hide = 0;
+  let result = await _case.paging(page, Number(limit), keyword, label, language)
+
+  ctx.body = {
+    msg: '成功获取数据',
+    content: result
+  }
+});
+
+
+
+/**
+ * 获取具体案例
+ */
+router.get('/:id', async ctx => {
+  let language = Number(ctx.query.language)
+  let id = ctx.params.id;
+
+  (!id || !Number.isFinite(Number(id))) &&
+    ctx.error('该案例不存在,请刷新后重试!');
+
+  let result = await getCase(id)
+
+  if (language && result.language !== language) {
+    let reResult = null
+    let reId = language === 1 ? result.chinese_id:
+      language === 2 ? result.english_id : null
+
+    reId && (reResult = await getCase(reId))
+    reResult && (result = reResult)
+  }
+
+  ctx.body = {
+    msg: '成功获取!',
+    content: result
+  };
+});
+
+/**
+ * 添加案例
+ */
+router.post('/', permission, async ctx => {
+  let body = ctx.request.body;
+  let _case = new Case();
+
+  _case.pro_type = body.proType;
+  _case.title = body.title;
+  _case.content = body.content;
+  _case.cover = body.cover;
+  _case.logo = body.logo;
+  _case.label = body.label;
+  _case.date = body.date;
+  _case.sort = Number(body.sort) || 0;
+  _case.link = body.link;
+  _case.address = body.address;
+  _case.type = body.type;
+  _case.user_id = ctx.session.user.id
+  _case.language = body.language;
+  _case.chinese_id = Number(body.chinese_id) || 0;
+  _case.english_id = Number(body.english_id) || 0;
+
+  let { insertId } = await _case.insert()
+
+  ctx.body = { 
+    msg: '成功添加!',
+    insertId
+  };
+});
+
+
+
+/**
+ * 修改案例
+ */
+router.put('/', permission, async ctx => {
+  let body = ctx.request.body;
+  let _case = new Case();
+  _case.id = body.id;
+
+  if (!await _case.exists()) {
+    ctx.error('该案例不存在!')
+  }
+
+  _case.pro_type = body.proType;
+  _case.title = body.title;
+  _case.content = body.content;
+  _case.cover = body.cover;
+  _case.label = body.label;
+  _case.logo = body.logo;
+  _case.date = body.date;
+  _case.sort = Number(body.sort) || 0;
+  _case.link = body.link;
+  _case.type = body.type;
+  _case.address = body.address;
+  _case.language = body.language;
+  _case.chinese_id = Number(body.chinese_id) || 0;
+  _case.english_id = Number(body.english_id) || 0;
+
+  await _case.update()
+
+  ctx.body = {
+    msg: '成功修改!'
+  };
+});
+
+/**
+ * 删除案例
+ */
+router.delete('/:id', permission, async ctx => {
+  let id = ctx.params.id;
+
+  (!id || !Number.isFinite(Number(id))) && 
+    ctx.error('该案例不存在,请刷新后重试!');
+
+  let _case = new Case();
+  _case.id = id;
+  _case.hide = 0;
+
+  (await _case.exists()) ||
+    ctx.error('该案例不存在,请刷新后重试!');
+
+  _case.hide = 1;
+  await _case.update();
+
+  ctx.body = { msg: '成功删除!' };
+});
+
+module.exports = exports = { path: '/case', router };

+ 20 - 0
router/index.js

@@ -0,0 +1,20 @@
+const Router = require('koa-router');
+const sys = require('../config/sys.json');
+const error = require('../intercept/error');
+const router = new Router();
+const roter_modulars = [
+  require('./user'),
+  require('./case'),
+  require('./news'),
+  require('./public')
+];
+
+router.use(error('error', sys.err_sendee));
+// router.use(permission);
+
+
+for (modular of roter_modulars) {
+  router.use(modular.path || '/', modular.router.routes(), modular.router.allowedMethods());
+}
+
+module.exports = router;

+ 145 - 0
router/news.js

@@ -0,0 +1,145 @@
+const News = require('../module/News');
+const Router = require('koa-router');
+const permission = require('../intercept/permission');
+const router = new Router();
+
+
+async function getNews(id) {
+  let news = new News();
+  news.id = id;
+
+  let [result = {}] = await news.query()
+
+  return result
+}
+
+/**
+ * 获取新闻数据
+ */
+router.get('/', async ctx => {
+  let { page = 1, keyword = '', limit = 15, language } = ctx.request.query;
+  let news = new News();
+
+  news.hide = 0;
+  let result = await news.paging(page, Number(limit), keyword, language)
+
+  ctx.body = {
+    msg: '成功获取数据',
+    content: result
+  }
+});
+
+/**
+ * 获取数据具体数据
+ */
+router.get('/:id', async ctx => {
+  let language = Number(ctx.query.language)
+  let id = ctx.params.id;
+
+  (!id || !Number.isFinite(Number(id))) &&
+    ctx.error('该新闻不存在,请刷新后重试!');
+
+  let result = await getNews(id)
+
+  if (language && result.language !== language && result.redire) {
+    let reResult = null
+    let reId = language === 1 ? result.chinese_id :
+      language === 2 ? result.english_id : null
+
+    reId && (reResult = await getNews(reId))
+    reResult && (result = reResult)
+  }
+
+  ctx.body = {
+    msg: '成功获取!',
+    content: result
+  };
+});
+
+
+/**
+ * 添加新闻
+ */
+router.post('/', permission, async ctx => {
+  let body = ctx.request.body;
+  let news = new News();
+
+  news.title = body.title;
+  news.content = body.content;
+  news.cover = body.cover;
+  news.label = body.label;
+  news.redire = body.redire;
+  news.date = body.date;
+  news.sort = Number(body.sort) || 0;
+  news.address = body.address;
+  news.origin = body.origin;
+  news.language = body.language;
+  news.chinese_id = Number(body.chinese_id) || 0;
+  news.english_id = Number(body.english_id) || 0;
+  news.user_id = ctx.session.user.id
+
+  let { insertId } = await news.insert()
+
+  ctx.body = {
+    msg: '成功添加!',
+    insertId
+  };
+});
+
+
+/**
+ * 修改新闻
+ */
+router.put('/', permission, async ctx => {
+  let body = ctx.request.body;
+  let news = new News();
+  news.id = body.id;
+
+  if (!await news.exists()) {
+    ctx.error('该新闻不存在!')
+  }
+  console.log('----------', body.origin, '--------------')
+
+  news.title = body.title;
+  news.content = body.content;
+  news.cover = body.cover;
+  news.label = body.label;
+  news.date = body.date;
+  news.redire = body.redire;
+  news.origin = body.origin;
+  news.language = body.language;
+  news.chinese_id = Number(body.chinese_id) || 0;
+  news.english_id = Number(body.english_id) || 0;
+  news.sort = Number(body.sort) || 0;
+  news.address = body.address;
+
+  await news.update()
+
+  ctx.body = {
+    msg: '成功修改!'
+  };
+});
+
+/**
+ * 删除文章
+ */
+router.delete('/:id', permission, async ctx => {
+  let id = ctx.params.id;
+
+  (!id || !Number.isFinite(Number(id))) &&
+    ctx.error('该新闻不存在,请刷新后重试!');
+
+  let news = new News();
+  news.id = id;
+  news.hide = 0;
+
+  (await news.exists()) ||
+    ctx.error('该新闻不存在,请刷新后重试!');
+
+  news.hide = 1;
+  await news.update();
+
+  ctx.body = { msg: '成功删除!' };
+});
+
+module.exports = exports = { path: '/news', router };

+ 53 - 0
router/public.js

@@ -0,0 +1,53 @@
+const {static_prefix} = require('../config/sys')
+const Router = require('koa-router');
+// const qiniu = require('qiniu')
+const path = require('path');
+const router = new Router();
+const permission = require('../intercept/permission');
+
+const fileLocal = path.join(__dirname, '../static/images');
+const fileRemote = static_prefix + '/images/';
+const uploadFile = require('../util/upload')(fileLocal)
+
+// const accessKey = 'dlPPwgZky_F-iP8CbSbJpiAtAcqw3BYwb9rdHMrS'
+// const secretKey = 'YEtkLKDsImXB-8m1CT1zV_YwCwwGvrUvo2ktj9KZ'
+// const scope = 'cgaii'
+// const expires = 2 * 60 * 60 * 1000
+// const mac = new qiniu.auth.digest.Mac(accessKey, secretKey)
+// const putPolicy = new qiniu.rs.PutPolicy({ scope, expires});
+// let token
+
+// (function updateToken () {
+//   token = putPolicy.uploadToken(mac);
+//   console.log(token)
+//   setTimeout(updateToken, expires - 60 * 1000)
+// })()
+
+
+/**
+ * 文件上传
+ */
+router.post('/upload', permission, async ctx => {
+  let {file} = await uploadFile(ctx);
+  ctx.body = {
+    msg: '文件上传成功',
+    content: fileRemote + file
+  }
+});
+
+router.post('/uploads', permission, async ctx => {
+  let {file} = await uploadFile(ctx);
+  ctx.body = {
+    errno: 0,
+    data: [ fileRemote + file ]
+  }
+});
+
+// router.get('/qiniuToken', permission, async ctx => {
+//   ctx.body = {
+//     msg: '获取token成功',
+//     content: token
+//   }
+// })
+
+module.exports = exports = { path: '/system', router };

+ 32 - 0
router/user.js

@@ -0,0 +1,32 @@
+const Router = require('koa-router');
+const pubtool = require('../util/pubtool');
+const User = require('../module/User');
+const router = new Router();
+
+/**
+ * 用户登录
+ */
+router.post('/sign', async ctx => {
+  let {name, password} = ctx.request.body;
+  (!password || password.length < 5) && ctx.error('密码错误')
+
+  let user = new User();
+  user.name = name;
+  let result = await user.query();
+
+  if (result.length === 0) {
+    ctx.error('该账号不存在!');
+  } else if (result[0].psw !== pubtool.hashEncryption(password, 2)) {
+    ctx.error('密码错误');
+  } else {
+    await (ctx.session.user = result[0]);
+    ctx.body = { cmsg: '登录成功' };
+  }
+});
+
+router.post('/sinout', async ctx => {
+  await (delete ctx.session.user);
+  ctx.body = { cmsg: '成功退出' };
+})
+
+module.exports = exports = {path: '/user', router};

+ 267 - 0
static/creation/index.html

@@ -0,0 +1,267 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+    <meta charset="UTF-8">
+    <!-- <meta name="viewport" content="width=device-width, initial-scale=1.0"> -->
+    <meta name="renderer" content="webkit">
+    <meta name="viewport" content="width=device-width" />
+    <meta http-equiv="X-UA-Compatible" content="ie=edge">
+    <title>Document</title>
+    <style>
+        *,
+        *::before,
+        *::after {
+            margin: 0;
+            padding: 0;
+            box-sizing: border-box;
+            /* -webkit-backface-visibility: hidden;
+            -moz-backface-visibility: hidden;
+            -ms-backface-visibility: hidden;
+            backface-visibility: hidden; */
+
+        }
+
+        html,
+        body {
+            width: 100%;
+            height: 100%;
+            overflow: hidden;
+        }
+
+        html {
+            font-size: 36px;
+        }
+
+        body {
+            background-color: #292929;
+        }
+
+        li {
+            left: -9999px;
+            position: fixed;
+            cursor: pointer;
+            list-style: none;
+            background-image: -webkit-linear-gradient(top, #555a5f, #efeeed);
+            background-image: -ms-linear-gradient(top, #555a5f, #efeeed);
+            user-select: none;
+            z-index: 5;
+            text-align: center;
+
+        }
+
+
+        li img {
+            transform: scale(0.5);
+            pointer-events: none;
+            vertical-align: middle;
+            transition: all .4s ease-in;
+        }
+
+        li div {
+            display: none;
+            width: 100%;
+            height: 100%;
+        }
+
+        li.focus {
+            z-index: 10 !important;
+        }
+
+        li.focus img {
+            transform: scale(1.2);
+        }
+
+        li.l-4 {
+            opacity: 0.3;
+            z-index: 1;
+            transform: scale(0.4);
+        }
+
+        li.l-3 {
+            opacity: 0.3;
+            z-index: 2;
+            transform: scale(0.6);
+        }
+
+        li.l-2 {
+            opacity: 0.9;
+            z-index: 3;
+            transform: scale(0.8);
+        }
+
+        li.l-1 {
+            opacity: 1;
+            z-index: 4;
+            transform: scale(0.9);
+        }
+
+        li:hover {
+            opacity: 1;
+            transform: scale(1.4);
+            z-index: 20;
+        }
+
+        li.click {
+            left: 50% !important;
+            top: 50% !important;
+            opacity: 1;
+            transform: translate(-50%, -50%) scale(1);
+            z-index: 30 !important;
+            width: 500px !important;
+            height: 460px !important;
+            line-height: 260px !important;
+            border: solid 2px #fff;
+        }
+
+        li.click div {
+            position: absolute;
+            left: 0;
+            top: 0;
+            width: 100%;
+            height: 100%;
+            z-index: 10;
+            display: block;
+        }
+
+        li.click img {
+           transform: scale(0);
+        }
+
+        .panel {
+            display: none;
+            position: fixed;
+            padding: 10px;
+            left: 0;
+            bottom: 0;
+            width: 100%;
+            height: 100px;
+            background-color: #efefef;
+            border-top: solid 1px #ccc;
+        }
+
+        iframe {
+            width: 100%;
+            height: 100%;
+        }
+
+        .mobile ul {
+            transform: scale(0.3) translate(-200%)
+        }
+
+        .mobile li img {
+           transition: none;
+        }
+
+        .mobile li:hover {
+            opacity: 1;
+            transform: unset;
+            z-index: 20;
+        }
+
+        .mobile li.bigger {
+            left: 170% !important;
+            top: 5rem !important;
+            opacity: 1;
+            z-index: 30 !important;
+            border: solid 2px #fff;
+            width: 15rem !important;
+            height: 15rem !important;
+            line-height: 15rem !important;
+        }
+
+        .mobile li.bigger img {
+            width: 80%;
+            height: 80%;
+            ;
+            transform: scale(1) !important;
+        }
+    </style>
+</head>
+
+<body>
+    <ul></ul>
+    <script src="js/detect.mobile.js"></script>
+    <script src="js/jquery.min.js"></script>
+    <script src="js/jquery.easing.min.js"></script>
+    <script src="js/model-data.js"></script>
+    <script>
+        var list = ModelData;
+        var html = [];
+        if (IsMobile()) {
+            list = list.slice(0, 55)
+            $('body').addClass('mobile')
+        }
+
+        list.forEach(function (item, i) {
+            var clazz = item.clazz || '';
+            clazz += (item.focus ? ' focus' : '')
+            html.push('<li data-index="' + i + '" data-url="' + item.url + '" class="' + clazz +
+                '" style="line-height:' + item.height + 'px;top:' + (item.top / 36 || 0) + 'rem;left:' + (
+                    item.left / 36 || 0) + 'rem;width:' + item.width / 36 + 'rem;height:' + item.height /
+                36 + 'rem">');
+            html.push('    <img src="photos/' + item.image_small +
+                '">');
+            html.push('    <div></div>')
+            html.push('</li>');
+        })
+        $(html.join('')).appendTo('ul');
+
+        $("li").css('value', 0).css('opacity', 0).each(function (i) {
+            var time = Math.random() * 1000;
+            $(this).delay(time).animate({
+                value: 1
+            }, {
+                step: function (n) {
+                    ry = (1 - n) * 360;
+                    tz = (1 - n) * 1000;
+                    $(this).css("transform", "rotateY(" + ry + "deg) translateZ(" + tz +
+                        "px)").css('opacity', n);
+                    if (n > .98) {
+                        $(this).css("transform", "").css("opacity", "").css("transition",
+                            "all .4s ease-in")
+                    }
+
+                },
+                duration: 3000,
+                //some easing fun. Comes from the jquery easing plugin.
+                easing: 'easeOutQuint',
+                done: function () {
+
+                }
+            })
+        })
+
+        if (IsMobile()) {
+            // $('li').click(function (e) {
+            //     $('li.click').removeClass('click')
+            //     $(this).addClass('click');
+            //     return false;
+            // })
+            $('li').on('touchstart', function () {
+                $('li.bigger').removeClass('bigger')
+                $(this).addClass('bigger');
+                return false;
+            })
+            $(document).on('touchstart', function () {
+                $('li.bigger').removeClass('bigger')
+            })
+        } else {
+            $('li').click(function (e) {
+                $('li.click').removeClass('click').find('iframe').remove();
+                $(this).addClass('click');
+                var $iframe = $('<iframe style="display:none" frameborder="0" src="' + $(this).data('url') +
+                    '"></iframe>').appendTo($(this).find('div'));
+                setTimeout(function () {
+                    $iframe.css('display', 'block')
+                }, 400);
+                return false;
+            })
+            $(document).click(function () {
+                $('li.click').removeClass('click').find('iframe').remove()
+            })
+        }
+    </script>
+</body>
+
+</html>

文件差異過大導致無法顯示
+ 7 - 0
static/creation/js/detect.mobile.js


文件差異過大導致無法顯示
+ 44 - 0
static/creation/js/jquery.easing.min.js


文件差異過大導致無法顯示
+ 2 - 0
static/creation/js/jquery.min.js


+ 759 - 0
static/creation/js/model-data.js

@@ -0,0 +1,759 @@
+var ModelData = [{
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt03.html",
+    "image_small": "01.png",
+    "width": 144,
+    "height": 248,
+    "left": 1693.5750122070312,
+    "top": 118.1812744140625,
+    "clazz": "l-1"
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt17.html",
+    "image_small": "02.png",
+    "width": 170,
+    "height": 89,
+    "clazz": "l-4",
+    "left": 1123,
+    "top": 409.7624969482422
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt18.html",
+    "image_small": "03.png",
+    "width": 175,
+    "height": 89,
+    "left": 1036,
+    "top": 75
+}, {
+    "url": "http://model.4dage.com/model/JP03.html",
+    "image_small": "04.png",
+    "width": 184,
+    "height": 110,
+    "left": 865.1812744140625,
+    "top": 646,
+    "clazz": "l-2"
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt37.html",
+    "image_small": "05.png",
+    "width": 169,
+    "height": 128,
+    "left": 1262.5718994140625,
+    "top": 536.1906127929688,
+    "clazz": "l-2"
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt43.html",
+    "image_small": "06.png",
+    "width": 194,
+    "height": 126,
+    "left": 1481,
+    "top": 94
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt49.html",
+    "image_small": "07.png",
+    "width": 350,
+    "height": 200,
+    "left": 1384,
+    "top": 472,
+    "focus": true
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt50.html",
+    "image_small": "08.png",
+    "width": 147,
+    "height": 125,
+    "left": 156.80624961853027,
+    "top": 578,
+    "clazz": "l-3"
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt28.html",
+    "image_small": "09.png",
+    "width": 164,
+    "height": 164,
+    "left": 635,
+    "top": -14
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt84.html",
+    "image_small": "10.png",
+    "width": 194,
+    "height": 66,
+    "left": 494,
+    "top": 548
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt85.html",
+    "image_small": "11.png",
+    "width": 192,
+    "height": 141,
+    "left": 214.39999389648438,
+    "top": 529.2000122070312,
+    "clazz": "l-3"
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt86.html",
+    "image_small": "12.png",
+    "width": 237,
+    "height": 60,
+    "left": 383.57501220703125,
+    "top": 201,
+    "clazz": "l-2"
+}, {
+    "url": "http://model.4dage.com/model/JP13.html",
+    "image_small": "13.png",
+    "width": 155,
+    "height": 154,
+    "left": 743.5,
+    "top": 439.92498779296875,
+    "clazz": "l-3"
+}, {
+    "url": "http://model.4dage.com/model/JP12.html",
+    "image_small": "14.png",
+    "width": 71,
+    "height": 162,
+    "left": 1013.3875122070312,
+    "top": 469.7906188964844,
+    "clazz": "l-3"
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt45.html",
+    "image_small": "15.png",
+    "width": 76,
+    "height": 168,
+    "left": 1022.800048828125,
+    "top": 354.4000244140625,
+    "clazz": "l-4"
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt44.html",
+    "image_small": "16.png",
+    "width": 89,
+    "height": 171,
+    "left": 877.5718994140625,
+    "top": 461.3812561035156,
+    "clazz": "l-2"
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt25.html",
+    "image_small": "17.png",
+    "width": 174,
+    "height": 103,
+    "left": 763.3875122070312,
+    "top": 204.29061889648438,
+    "clazz": "l-1"
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt64.html",
+    "image_small": "18.png",
+    "width": 107,
+    "height": 130,
+    "left": 1070,
+    "top": 408
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt06.html",
+    "image_small": "19.png",
+    "width": 94,
+    "height": 164,
+    "left": 832.7625122070312,
+    "top": 681.7625122070312,
+    "clazz": "l-1"
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt13.html",
+    "image_small": "20.png",
+    "width": 107,
+    "height": 156,
+    "left": 667,
+    "top": 312
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt16.html",
+    "image_small": "21.png",
+    "width": 98,
+    "height": 145,
+    "left": 734,
+    "top": 233,
+    "clazz": "l-3"
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt10.html",
+    "image_small": "22.png",
+    "width": 63,
+    "height": 161,
+    "left": 408,
+    "top": 434
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt01.html",
+    "image_small": "23.png",
+    "width": 300,
+    "height": 200,
+    "left": 869.796875,
+    "top": 129,
+    "clazz": "l-1",
+    "focus": true
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt82.html",
+    "image_small": "24.png",
+    "width": 148,
+    "height": 100,
+    "left": 1024,
+    "top": 8
+}, {
+    "url": "http://show.4dage.com/NM/hot/NM12.html",
+    "image_small": "25.png",
+    "width": 160,
+    "height": 141,
+    "left": 1167,
+    "top": 177.0968780517578,
+    "clazz": "l-1"
+}, {
+    "url": "http://show.4dage.com/NM/hot/NM13.html",
+    "image_small": "26.png",
+    "width": 129,
+    "height": 129,
+    "left": 827,
+    "top": 54
+}, {
+    "url": "http://show.4dage.com/NM/hot/NM18.html",
+    "image_small": "27.png",
+    "width": 330,
+    "height": 200,
+    "left": 529,
+    "top": 540,
+    "focus": true
+}, {
+    "url": "http://show.4dage.com/NM/hot/NM20.html",
+    "image_small": "28.png",
+    "width": 134,
+    "height": 177,
+    "left": 614,
+    "top": 124
+}, {
+    "url": "http://show.4dage.com/NM/hot/NM21.html",
+    "image_small": "29.png",
+    "width": 122,
+    "height": 124,
+    "left": 495,
+    "top": 450
+}, {
+    "url": "http://show.4dage.com/NM/hot/NM22.html",
+    "image_small": "30.png",
+    "width": 100,
+    "height": 167,
+    "left": 625,
+    "top": 331
+}, {
+    "url": "http://show.4dage.com/NM/hot/NM27.html",
+    "image_small": "31.png",
+    "width": 43,
+    "height": 96,
+    "left": 277,
+    "top": 553,
+    "clazz": "l-4"
+}, {
+    "url": "http://show.4dage.com/NM/hot/NM33.html",
+    "image_small": "32.png",
+    "width": 175,
+    "height": 57,
+    "left": 95,
+    "top": 528
+}, {
+    "url": "http://model.4dage.com/model/JP06.html",
+    "image_small": "33.png",
+    "width": 89,
+    "height": 90,
+    "left": 117,
+    "top": 473
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt80.html",
+    "image_small": "34.png",
+    "width": 97,
+    "height": 99,
+    "left": 48,
+    "top": 335
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt72.html",
+    "image_small": "35.png",
+    "width": 44,
+    "height": 98,
+    "left": 106,
+    "top": 430
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt67.html",
+    "image_small": "36.png",
+    "width": 106,
+    "height": 101,
+    "left": 58,
+    "top": 255
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt65.html",
+    "image_small": "37.png",
+    "width": 56,
+    "height": 106,
+    "left": 776.3718872070312,
+    "top": 2.371875762939453,
+    "clazz": "l-3"
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt54.html",
+    "image_small": "38.png",
+    "width": 108,
+    "height": 75,
+    "left": 416.59686279296875,
+    "top": 389,
+    "clazz": "l-2"
+}, {
+    "url": "http://model.4dage.com/model/JP02.html",
+    "image_small": "39.png",
+    "width": 62,
+    "height": 103,
+    "left": 581,
+    "top": 356
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt36.html",
+    "image_small": "40.png",
+    "width": 119,
+    "height": 84,
+    "left": 929,
+    "top": 582,
+    "clazz": "l-1"
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt66.html",
+    "image_small": "41.png",
+    "width": 133,
+    "height": 198,
+    "left": 186,
+    "top": 167
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt52.html",
+    "image_small": "42.png",
+    "width": 135,
+    "height": 195,
+    "left": 1780,
+    "top": 311,
+    "focus": false
+}, {
+    "url": "http://model.4dage.com/model/JP11.html",
+    "image_small": "43.png",
+    "width": 136,
+    "height": 211,
+    "left": 1179.1937255859375,
+    "top": 291.1937561035156,
+    "clazz": "l-2"
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt12.html",
+    "image_small": "44.png",
+    "width": 129,
+    "height": 202,
+    "left": 1079.4937744140625,
+    "top": 205.9812469482422,
+    "clazz": "l-2"
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt07.html",
+    "image_small": "45.png",
+    "width": 120,
+    "height": 163,
+    "clazz": "l-3",
+    "left": 1001,
+    "top": 214.38125610351562
+}, {
+    "url": "http://model3d.4dage.com/NJBWZG/NJ36.html",
+    "image_small": "46.png",
+    "width": 183,
+    "height": 179,
+    "left": 873.5999755859375,
+    "top": -19.199996948242188,
+    "clazz": "l-3"
+}, {
+    "url": "http://model3d.4dage.com/NJBWZG/NJ01.html",
+    "image_small": "47.png",
+    "width": 211,
+    "height": 154,
+    "left": 1215.512451171875,
+    "top": 261.37811279296875,
+    "clazz": "l-3"
+}, {
+    "url": "http://model3d.4dage.com/NJBWZG/NJ31.html",
+    "image_small": "48.png",
+    "width": 60,
+    "height": 210,
+    "left": 1824,
+    "top": 25
+}, 
+// {
+//     "url": "http://show.4dage.com/3D/2018/model/NT/nt63.html",
+//     "image_small": "49.png",
+//     "width": 174,
+//     "height": 94,
+//     "left": 1171.0875244140625,
+//     "top": 511.0875244140625,
+//     "clazz": "l-1"
+// }, 
+{
+    "url": "http://model3d.4dage.com/NJBWZG/NJ19.html",
+    "image_small": "50.png",
+    "width": 162,
+    "height": 200,
+    "left": 1391.7906494140625,
+    "top": 646,
+    "clazz": "l-3"
+}, {
+    "url": "http://show.4dage.com/NM/hot/NM2.html",
+    "image_small": "51.png",
+    "width": 200,
+    "height": 123,
+    "left": 1220,
+    "top": 345.0531311035156,
+    "clazz": "l-3"
+}, {
+    "url": "http://show.4dage.com/NM/hot/NM3.html",
+    "image_small": "52.png",
+    "width": 188,
+    "height": 135,
+    "left": 887.7718505859375,
+    "top": 433.25,
+    "clazz": "l-3"
+}, 
+// {
+//     "url": "http://show.4dage.com/NM/hot/NM4.html",
+//     "image_small": "53.png",
+//     "width": 185,
+//     "height": 238,
+//     "left": 221.25,
+//     "top": 319.8999938964844,
+//     "clazz": "l-1"
+// }, 
+{
+    "url": "http://show.4dage.com/NM/hot/NM5.html",
+    "image_small": "54.png",
+    "width": 164,
+    "height": 251,
+    "left": 1047.7593994140625,
+    "top": 526.9281005859375,
+    "clazz": "l-2"
+}, {
+    "url": "http://show.4dage.com/NM/hot/NM7.html",
+    "image_small": "55.png",
+    "width": 200,
+    "height": 126,
+    "left": 371,
+    "top": 576.6000061035156,
+    "clazz": "l-2"
+}, {
+    "url": "http://show.4dage.com/NM/hot/NM6.html",
+    "image_small": "56.png",
+    "width": 194,
+    "height": 260,
+    "left": 1488.878173828125,
+    "top": 315,
+    "clazz": "l-3"
+}, {
+    "url": "http://show.4dage.com/NM/hot/NM8.html",
+    "image_small": "57.png",
+    "width": 350,
+    "height": 230,
+    "left": 267,
+    "top": 37.390625,
+    "clazz": "l-2",
+    "focus": true
+}, {
+    "url": "http://show.4dage.com/NM/hot/NM11.html",
+    "image_small": "58.png",
+    "width": 200,
+    "height": 160,
+    "left": 1199,
+    "top": 4,
+    "clazz": "l-3"
+}, {
+    "url": "http://show.4dage.com/NM/hot/NM14.html",
+    "image_small": "59.png",
+    "width": 196,
+    "height": 146,
+    "left": 904.9874877929688,
+    "top": 265.98748779296875,
+    "clazz": "l-4"
+}, {
+    "url": "http://show.4dage.com/NM/hot/NM15.html",
+    "image_small": "60.png",
+    "width": 174,
+    "height": 260,
+    "left": 1350.5968627929688,
+    "top": 37,
+    "clazz": "l-3"
+}, {
+    "url": "http://show.4dage.com/NM/hot/NM16.html",
+    "image_small": "61.png",
+    "width": 71,
+    "height": 180,
+    "left": 512.0437622070312,
+    "top": 300,
+    "clazz": "l-3"
+}, {
+    "url": "http://show.4dage.com/NM/hot/NM17.html",
+    "image_small": "62.png",
+    "width": 62,
+    "height": 180,
+    "left": 183,
+    "top": 280
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt42.html",
+    "image_small": "63.png",
+    "width": 150,
+    "height": 109,
+    "left": 1343,
+    "top": 12
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt43.html",
+    "image_small": "64.png",
+    "width": 130,
+    "height": 79,
+    "left": 1248,
+    "top": 143
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt48.html",
+    "image_small": "65.png",
+    "width": 110,
+    "height": 132,
+    "left": 684,
+    "top": 689.2000122070312,
+    "clazz": "l-2"
+}, {
+    "url": "http://model3d.4dage.com/NJBWZG/NJ18.html",
+    "image_small": "66.png",
+    "width": 130,
+    "height": 148,
+    "left": 1526,
+    "top": 288.3999938964844,
+    "clazz": "l-4"
+}, {
+    "url": "http://show.4dage.com/NM/hot/NM20.html",
+    "image_small": "67.png",
+    "width": 174,
+    "height": 180,
+    "left": 1597,
+    "top": 199,
+    "clazz": "l-3"
+}, {
+    "url": "http://show.4dage.com/NM/hot/NM23.html",
+    "image_small": "68.png",
+    "width": 164,
+    "height": 180,
+    "left": 1628,
+    "top": -33
+}, {
+    "url": "http://show.4dage.com/NM/hot/NM24.html",
+    "image_small": "69.png",
+    "width": 173,
+    "height": 176,
+    "left": 809.7906494140625,
+    "top": 375.59686279296875,
+    "clazz": "l-4"
+}, {
+    "url": "http://model3d.4dage.com/NJBWZG/NJ25.html",
+    "image_small": "70.png",
+    "width": 83,
+    "height": 180,
+    "left": 1438.7906494140625,
+    "top": 351,
+    "clazz": "l-4"
+}, {
+    "url": "http://show.4dage.com/NM/hot/NM25.html",
+    "image_small": "71.png",
+    "width": 148,
+    "height": 101,
+    "left": 1691,
+    "top": 542,
+    "clazz": "l-4"
+}, {
+    "url": "http://show.4dage.com/NM/hot/NM26.html",
+    "image_small": "72.png",
+    "width": 146,
+    "height": 121,
+    "left": 1295,
+    "top": 662
+}, 
+// {
+//     "url": "http://model3d.4dage.com/NJBWZG/NJ27.html",
+//     "image_small": "73.png",
+//     "width": 149,
+//     "height": 144,
+//     "left": 1534.324951171875,
+//     "top": 694.5750122070312,
+//     "clazz": "l-1"
+// }, 
+// {
+//     "url": "http://model3d.4dage.com/NJBWZG/NJ28.html",
+//     "image_small": "74.png",
+//     "width": 160,
+//     "height": 157,
+//     "left": 1621,
+//     "top": 617
+// }, 
+{
+    "url": "http://model3d.4dage.com/NJBWZG/NJ29.html",
+    "image_small": "75.png",
+    "width": 153,
+    "height": 155,
+    "left": 1717,
+    "top": 532
+}, 
+// {
+//     "url": "http://show.4dage.com/NM/hot/NM29.html",
+//     "image_small": "76.png",
+//     "width": 146,
+//     "height": 97,
+//     "left": 1445.784423828125,
+//     "top": 263.5843811035156,
+//     "clazz": "l-4"
+// },
+ {
+    "url": "http://model3d.4dage.com/NJBWZG/NJ30.html",
+    "image_small": "77.png",
+    "width": 115,
+    "height": 165,
+    "clazz": "l-4",
+    "left": 1539.5,
+    "top": 199.5
+}, {
+    "url": "http://show.4dage.com/NM/hot/NM28.html",
+    "image_small": "78.png",
+    "width": 91,
+    "height": 190,
+    "left": 330.09686279296875,
+    "top": 615,
+    "clazz": "l-1"
+}, 
+// {
+//     "url": "http://show.4dage.com/NM/hot/NM30.html",
+//     "image_small": "79.png",
+//     "width": 152,
+//     "height": 90,
+//     "clazz": "l-4",
+//     "left": 1362.599998474121,
+//     "top": 262
+// }, 
+{
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt02.html",
+    "image_small": "80.png",
+    "width": 154,
+    "height": 182,
+    "left": 406.98748779296875,
+    "top": 635.9781494140625,
+    "clazz": "l-3"
+}, {
+    "url": "http://show.4dage.com/NM/hot/NM32.html",
+    "image_small": "81.png",
+    "width": 190,
+    "height": 34,
+    "left": 971,
+    "top": 367.99688720703125,
+    "clazz": "l-4"
+}, {
+    "url": "http://show.4dage.com/NM/hot/NM34.html",
+    "image_small": "82.png",
+    "width": 143,
+    "height": 104,
+    "clazz": "l-4",
+    "left": 353.4625244140625,
+    "top": 284.95001220703125
+}, {
+    "url": "http://show.4dage.com/NM/hot/NM36.html",
+    "image_small": "83.png",
+    "width": 150,
+    "height": 97,
+    "left": 790,
+    "top": 7.881256103515625,
+    "clazz": "l-4"
+}, {
+    "url": "http://model3d.4dage.com/NJBWZG/NJ39.html",
+    "image_small": "84.png",
+    "width": 31,
+    "height": 110,
+    "left": 572.7625122070312,
+    "top": 263,
+    "clazz": "l-3"
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt04.html",
+    "image_small": "85.png",
+    "width": 82,
+    "height": 79,
+    "left": 227,
+    "top": 52
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt05.html",
+    "image_small": "86.png",
+    "width": 50,
+    "height": 83,
+    "left": 1743,
+    "top": 755
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt08.html",
+    "image_small": "87.png",
+    "width": 54,
+    "height": 94,
+    "left": 1835,
+    "top": 671
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt09.html",
+    "image_small": "88.png",
+    "width": 51,
+    "height": 98,
+    "left": 1849,
+    "top": 532
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt11.html",
+    "image_small": "89.png",
+    "width": 44,
+    "height": 93,
+    "left": 1460.171875,
+    "top": 670.375,
+    "clazz": ""
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt22.html",
+    "image_small": "93.png",
+    "width": 113,
+    "height": 102,
+    "left": 240.08438110351562,
+    "top": 100.3843765258789,
+    "clazz": "l-3"
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt23.html",
+    "image_small": "94.png",
+    "width": 133,
+    "height": 118,
+    "left": 53.30000305175781,
+    "top": 108.80000305175781,
+    "clazz": "l-2"
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt26.html",
+    "image_small": "95.png",
+    "width": 140,
+    "height": 120,
+    "left": 115,
+    "top": 9,
+    "clazz": "l-1"
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt35.html",
+    "image_small": "96.png",
+    "width": 180,
+    "height": 206,
+    "left": 1120,
+    "top": 636.7312622070312,
+    "clazz": "l-3"
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt38.html",
+    "image_small": "97.png",
+    "width": 239,
+    "height": 127,
+    "left": 37.79999923706055,
+    "top": 663.4000244140625,
+    "clazz": "l-3"
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt39.html",
+    "image_small": "98.png",
+    "width": 234,
+    "height": 205,
+    "left": 188.10625076293945,
+    "top": 685.25,
+    "clazz": "l-4"
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt40.html",
+    "image_small": "99.png",
+    "width": 163,
+    "height": 172,
+    "left": 1595.440673828125,
+    "top": 314.79376220703125,
+    "clazz": "l-2"
+}, {
+    "url": "http://show.4dage.com/3D/2018/model/NT/nt41.html",
+    "image_small": "100.png",
+    "width": 173,
+    "height": 143,
+    "left": 1314.784423828125,
+    "top": 396.78436279296875,
+    "clazz": "l-2"
+}];

二進制
static/creation/photos/01.png


二進制
static/creation/photos/02.png


二進制
static/creation/photos/03.png


二進制
static/creation/photos/04.png


二進制
static/creation/photos/05.png


二進制
static/creation/photos/06.png


二進制
static/creation/photos/07.png


二進制
static/creation/photos/08.png


二進制
static/creation/photos/09.png


二進制
static/creation/photos/10.png


二進制
static/creation/photos/100.png


二進制
static/creation/photos/11.png


二進制
static/creation/photos/12.png


二進制
static/creation/photos/13.png


二進制
static/creation/photos/14.png


二進制
static/creation/photos/15.png


二進制
static/creation/photos/16.png


二進制
static/creation/photos/17.png


二進制
static/creation/photos/18.png


二進制
static/creation/photos/19.png


二進制
static/creation/photos/20.png


二進制
static/creation/photos/21.png


二進制
static/creation/photos/22.png


二進制
static/creation/photos/23.png


二進制
static/creation/photos/24.png


二進制
static/creation/photos/25.png


二進制
static/creation/photos/26.png


二進制
static/creation/photos/27.png


二進制
static/creation/photos/28.png


二進制
static/creation/photos/29.png


二進制
static/creation/photos/30.png


二進制
static/creation/photos/31.png


二進制
static/creation/photos/32.png


二進制
static/creation/photos/33.png


二進制
static/creation/photos/34.png


二進制
static/creation/photos/35.png


二進制
static/creation/photos/36.png


二進制
static/creation/photos/37.png


二進制
static/creation/photos/38.png


二進制
static/creation/photos/39.png


二進制
static/creation/photos/40.png


二進制
static/creation/photos/41.png


二進制
static/creation/photos/42.png


二進制
static/creation/photos/43.png


二進制
static/creation/photos/44.png


二進制
static/creation/photos/45.png


二進制
static/creation/photos/46.png


二進制
static/creation/photos/47.png


二進制
static/creation/photos/48.png


二進制
static/creation/photos/49.png


二進制
static/creation/photos/50.png


二進制
static/creation/photos/51.png


二進制
static/creation/photos/52.png


二進制
static/creation/photos/53.png


二進制
static/creation/photos/54.png


二進制
static/creation/photos/55.png


二進制
static/creation/photos/56.png


二進制
static/creation/photos/57.png


二進制
static/creation/photos/58.png


二進制
static/creation/photos/59.png


二進制
static/creation/photos/60.png


二進制
static/creation/photos/61.png


二進制
static/creation/photos/62.png


二進制
static/creation/photos/63.png


二進制
static/creation/photos/64.png


二進制
static/creation/photos/65.png


二進制
static/creation/photos/66.png


二進制
static/creation/photos/67.png


二進制
static/creation/photos/68.png


二進制
static/creation/photos/69.png


二進制
static/creation/photos/70.png


二進制
static/creation/photos/71.png


二進制
static/creation/photos/72.png


二進制
static/creation/photos/73.png


二進制
static/creation/photos/74.png


+ 0 - 0
static/creation/photos/75.png


部分文件因文件數量過多而無法顯示