Selaa lähdekoodia

激活指南前端sql

zhb 6 kuukautta sitten
vanhempi
commit
16da6183f3
100 muutettua tiedostoa jossa 870 lisäystä ja 1 poistoa
  1. 14 0
      card_server/.editorconfig
  2. 1 0
      card_server/.env.dev
  3. 1 0
      card_server/.env.production
  4. 4 0
      card_server/.eslintignore
  5. 259 0
      card_server/.eslintrc.js
  6. 21 0
      card_server/.gitignore
  7. 6 0
      card_server/.prettierrc
  8. 7 0
      card_server/.sequelizerc
  9. 45 0
      card_server/db/config/config.json
  10. 45 0
      card_server/db/models/index.js
  11. 55 0
      card_server/db/models/web_information.js
  12. 43 0
      card_server/db/models/web_information_tag.js
  13. 69 0
      card_server/downloadTask.js
  14. 9 0
      card_server/jsconfig.json
  15. 62 0
      card_server/package.json
  16. 62 0
      card_server/src/card.js
  17. 17 0
      card_server/src/router/index.js
  18. 54 0
      card_server/src/router/wasabi.router.js
  19. 42 0
      card_server/src/utils/common.js
  20. 10 0
      card_server/src/utils/setting.js
  21. 36 0
      card_server/src/utils/verify.js
  22. 0 0
      next/.env
  23. 0 0
      next/.env.prod
  24. 0 0
      next/.env.test
  25. 0 0
      next/.gitignore
  26. 0 0
      next/README.md
  27. 0 0
      next/card-server.js
  28. 0 0
      next/eslint.config.mjs
  29. 0 0
      next/global.ts
  30. 0 0
      next/jest.config.js
  31. 0 0
      next/messages/ar.json
  32. 0 0
      next/messages/cn.json
  33. 0 0
      next/messages/de.json
  34. 0 0
      next/messages/en.json
  35. 0 0
      next/messages/es.json
  36. 0 0
      next/messages/fa.json
  37. 0 0
      next/messages/id.json
  38. 0 0
      next/messages/ko.json
  39. 0 0
      next/messages/ms.json
  40. 0 0
      next/messages/pt.json
  41. 0 0
      next/messages/th.json
  42. 0 0
      next/messages/tr.json
  43. 0 0
      next/messages/vi.json
  44. 0 0
      next/messages/zh.json
  45. 1 1
      next/next-env.d.ts
  46. 0 0
      next/next.config.ts
  47. 7 0
      next/package.json
  48. 0 0
      next/playwright.config.ts
  49. 0 0
      next/postcss.config.js
  50. 0 0
      next/public/favicon.ico
  51. 0 0
      next/public/icons/icon_account.svg
  52. 0 0
      next/public/icons/icon_back.svg
  53. 0 0
      next/public/icons/icon_candle.svg
  54. 0 0
      next/public/icons/icon_chart.svg
  55. 0 0
      next/public/icons/icon_course.svg
  56. 0 0
      next/public/icons/icon_dropdown.svg
  57. 0 0
      next/public/icons/icon_flip.svg
  58. 0 0
      next/public/icons/icon_format comfy.svg
  59. 0 0
      next/public/icons/icon_format list.svg
  60. 0 0
      next/public/icons/icon_forward-1.svg
  61. 0 0
      next/public/icons/icon_forward.svg
  62. 0 0
      next/public/icons/icon_language.svg
  63. 0 0
      next/public/icons/icon_more.svg
  64. 0 0
      next/public/icons/icon_save.svg
  65. 0 0
      next/public/icons/icon_search.svg
  66. 0 0
      next/public/icons/icon_time.svg
  67. 0 0
      next/public/icons/icon_to.svg
  68. 0 0
      next/public/icons/icon_up.svg
  69. 0 0
      next/public/images/favicon.png
  70. 0 0
      next/public/images/imgs/back-office-management.webp
  71. 0 0
      next/public/images/imgs/cwg-logo.svg
  72. 0 0
      next/public/images/imgs/cwg-step.png
  73. 0 0
      next/public/images/imgs/cwg-visa-card.png
  74. 0 0
      next/public/images/imgs/desktop.ini
  75. 0 0
      next/public/images/imgs/favicon.ico
  76. 0 0
      next/public/images/imgs/globe-payment.webp
  77. 0 0
      next/public/images/imgs/header-bg.gif
  78. 0 0
      next/public/images/imgs/header-bg.png
  79. 0 0
      next/public/images/imgs/icon-1-01.svg
  80. 0 0
      next/public/images/imgs/icon.png
  81. 0 0
      next/public/images/imgs/money-deposit.webp
  82. 0 0
      next/public/images/imgs/separator-01.svg
  83. 0 0
      next/public/images/imgs/separator-02.svg
  84. 0 0
      next/public/js/jquery.js
  85. 0 0
      next/public/js/main.js
  86. 0 0
      next/public/js/pdf.worker.min.js
  87. 0 0
      next/public/js/vendors.js
  88. 0 0
      next/public/js/vendors.min.js
  89. 0 0
      next/public/js/vendors/anime.min.js
  90. 0 0
      next/public/js/vendors/atropos.js
  91. 0 0
      next/public/js/vendors/bootstrap.bundle.js
  92. 0 0
      next/public/js/vendors/bootstrap.bundle.js.map
  93. 0 0
      next/public/js/vendors/gsap.js
  94. 0 0
      next/public/js/vendors/imagesloaded.pkgd.js
  95. 0 0
      next/public/js/vendors/interactive-portfolio.js
  96. 0 0
      next/public/js/vendors/isotope.pkgd.js
  97. 0 0
      next/public/js/vendors/jquery-cookie.js
  98. 0 0
      next/public/js/vendors/jquery.appear.js
  99. 0 0
      next/public/js/vendors/jquery.count-to.js
  100. 0 0
      next/public/js/vendors/jquery.countdown.js

+ 14 - 0
card_server/.editorconfig

@@ -0,0 +1,14 @@
+# http://editorconfig.org
+root = true
+
+[*]
+charset = utf-8
+indent_style = space
+indent_size = 2
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.md]
+insert_final_newline = false
+trim_trailing_whitespace = false

+ 1 - 0
card_server/.env.dev

@@ -0,0 +1 @@
+DB_HOST="development"

+ 1 - 0
card_server/.env.production

@@ -0,0 +1 @@
+DB_HOST="production"

+ 4 - 0
card_server/.eslintignore

@@ -0,0 +1,4 @@
+build/*.js
+src/assets
+public
+dist

+ 259 - 0
card_server/.eslintrc.js

@@ -0,0 +1,259 @@
+module.exports = {
+  parserOptions: {
+    parser: '@babel/eslint-parser',
+    ecmaVersion: 8,
+    sourceType: 'module'
+  },
+  extends: ['plugin:prettier/recommended', 'airbnb-base'],
+  root: true,
+  env: {
+    node: true,
+    jest: true
+  },
+  ignorePatterns: ['.eslintrc.js'],
+  rules: {
+    'accessor-pairs': 2,
+    'arrow-spacing': [
+      2,
+      {
+        before: true,
+        after: true
+      }
+    ],
+    'block-spacing': [2, 'always'],
+    'brace-style': [
+      2,
+      '1tbs',
+      {
+        allowSingleLine: true
+      }
+    ],
+    camelcase: [
+      0,
+      {
+        properties: 'always'
+      }
+    ],
+    'comma-dangle': [2, 'never'],
+    'comma-spacing': [
+      2,
+      {
+        before: false,
+        after: true
+      }
+    ],
+    'comma-style': [2, 'last'],
+    'constructor-super': 2,
+    curly: [2, 'multi-line'],
+    'dot-location': [2, 'property'],
+    'eol-last': 2,
+    eqeqeq: ['error', 'always', { null: 'ignore' }],
+    'generator-star-spacing': [
+      2,
+      {
+        before: true,
+        after: true
+      }
+    ],
+    'handle-callback-err': [2, '^(err|error)$'],
+    indent: [
+      2,
+      2,
+      {
+        SwitchCase: 1
+      }
+    ],
+    'jsx-quotes': [2, 'prefer-single'],
+    'key-spacing': [
+      2,
+      {
+        beforeColon: false,
+        afterColon: true
+      }
+    ],
+    'keyword-spacing': [
+      2,
+      {
+        before: true,
+        after: true
+      }
+    ],
+    'new-cap': [
+      2,
+      {
+        newIsCap: true,
+        capIsNew: false
+      }
+    ],
+    'new-parens': 2,
+    'no-array-constructor': 2,
+    'no-caller': 2,
+    'no-console': 'off',
+    'no-class-assign': 2,
+    'no-cond-assign': 2,
+    'no-const-assign': 2,
+    'no-control-regex': 0,
+    'no-delete-var': 2,
+    'no-dupe-args': 2,
+    'no-dupe-class-members': 2,
+    'no-dupe-keys': 2,
+    'no-duplicate-case': 2,
+    'no-empty-character-class': 2,
+    'no-empty-pattern': 2,
+    'no-eval': 2,
+    'no-ex-assign': 2,
+    'no-extend-native': 2,
+    'no-extra-bind': 2,
+    'no-extra-boolean-cast': 2,
+    'no-extra-parens': [2, 'functions'],
+    'no-fallthrough': 2,
+    'no-floating-decimal': 2,
+    'no-func-assign': 2,
+    'no-implied-eval': 2,
+    'no-inner-declarations': [2, 'functions'],
+    'no-invalid-regexp': 2,
+    'no-irregular-whitespace': 2,
+    'no-iterator': 2,
+    'no-label-var': 2,
+    'no-labels': [
+      2,
+      {
+        allowLoop: false,
+        allowSwitch: false
+      }
+    ],
+    'no-lone-blocks': 2,
+    'no-mixed-spaces-and-tabs': 2,
+    'no-multi-spaces': 2,
+    'no-multi-str': 2,
+    'no-multiple-empty-lines': [
+      2,
+      {
+        max: 1
+      }
+    ],
+    'no-native-reassign': 2,
+    'no-negated-in-lhs': 2,
+    'no-new-object': 2,
+    'no-new-require': 2,
+    'no-new-symbol': 2,
+    'no-new-wrappers': 2,
+    'no-obj-calls': 2,
+    'no-octal': 2,
+    'no-octal-escape': 2,
+    'no-path-concat': 2,
+    'no-proto': 2,
+    'no-redeclare': 2,
+    'no-regex-spaces': 2,
+    'no-return-assign': [2, 'except-parens'],
+    'no-self-assign': 2,
+    'no-self-compare': 2,
+    'no-sequences': 2,
+    'no-shadow-restricted-names': 2,
+    'no-spaced-func': 2,
+    'no-sparse-arrays': 2,
+    'no-this-before-super': 2,
+    'no-throw-literal': 2,
+    'no-trailing-spaces': 2,
+    'no-undef': 2,
+    'no-undef-init': 2,
+    'no-unexpected-multiline': 2,
+    'no-unmodified-loop-condition': 2,
+    'no-unneeded-ternary': [
+      2,
+      {
+        defaultAssignment: false
+      }
+    ],
+    'no-unreachable': 2,
+    'no-unsafe-finally': 2,
+    'no-unused-vars': [
+      2,
+      {
+        vars: 'all',
+        args: 'none'
+      }
+    ],
+    'no-useless-call': 2,
+    'no-useless-computed-key': 2,
+    'no-useless-constructor': 2,
+    'no-useless-escape': 0,
+    'no-whitespace-before-property': 2,
+    'no-with': 2,
+    'one-var': [
+      2,
+      {
+        initialized: 'never'
+      }
+    ],
+    'operator-linebreak': [
+      2,
+      'after',
+      {
+        overrides: {
+          '?': 'before',
+          ':': 'before'
+        }
+      }
+    ],
+    'padded-blocks': [2, 'never'],
+    quotes: [
+      2,
+      'single',
+      {
+        avoidEscape: true,
+        allowTemplateLiterals: true
+      }
+    ],
+    semi: [2, 'never'],
+    'semi-spacing': [
+      2,
+      {
+        before: false,
+        after: true
+      }
+    ],
+    'space-before-blocks': [2, 'always'],
+    'space-before-function-paren': 0,
+    'space-in-parens': [2, 'never'],
+    'space-infix-ops': 2,
+    'space-unary-ops': [
+      2,
+      {
+        words: true,
+        nonwords: false
+      }
+    ],
+    'spaced-comment': [
+      2,
+      'always',
+      {
+        markers: [
+          'global',
+          'globals',
+          'eslint',
+          'eslint-disable',
+          '*package',
+          '!',
+          ','
+        ]
+      }
+    ],
+    'template-curly-spacing': [2, 'never'],
+    'use-isnan': 2,
+    'valid-typeof': 2,
+    'wrap-iife': [2, 'any'],
+    'yield-star-spacing': [2, 'both'],
+    yoda: [2, 'never'],
+    'prefer-const': 2,
+    'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
+    'object-curly-spacing': [
+      2,
+      'always',
+      {
+        objectsInObjects: false
+      }
+    ],
+    'array-bracket-spacing': [2, 'never']
+  }
+}

+ 21 - 0
card_server/.gitignore

@@ -0,0 +1,21 @@
+.DS_Store
+node_modules/
+dist/
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+package-lock.json
+tests/**/coverage/
+
+# Editor directories and files
+.idea
+.vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+**.local
+yarn.lock
+static/
+*.BIN
+*.TXT

+ 6 - 0
card_server/.prettierrc

@@ -0,0 +1,6 @@
+{
+    "bracketSpacing": true,
+    "singleQuote": true,
+    "trailingComma": "none",
+    "semi": false
+}

+ 7 - 0
card_server/.sequelizerc

@@ -0,0 +1,7 @@
+const path = require('path');
+module.exports = {
+  'config': path.resolve('db', 'config', 'config.json'),
+  'models-path': path.resolve('db', 'models'),
+  'seeders-path': path.resolve('db', 'seeders'),
+  'migrations-path': path.resolve('db', 'migrations')
+}

+ 45 - 0
card_server/db/config/config.json

@@ -0,0 +1,45 @@
+
+{
+  "development": {
+    "username": "root",
+    "password": "NSH01Y0GTmUNjgg6xw80qg==",
+    "database": "cwg_crm",
+    "host": "103.171.34.61",
+    "port": "28571",
+    "dialect": "mysql",
+    "define": {
+      "timestamps": false
+    }
+  },
+  "development1": {
+    "username": "root",
+    "password": "NSH01Y0GTmUNjgg6xw80qg==",
+    "database": "cwg_crm",
+    "host": "103.214.175.29",
+    "port": "28571",
+    "dialect": "mysql",
+    "define": {
+      "timestamps": false
+    }
+  },
+  "test": {
+    "username": "7star",
+    "password": "123456",
+    "database": "cwg_crm",
+    "host": "103.171.34.61",
+    "port": "28571",
+    "dialect": "mysql"
+  },
+  "production": {
+    "username": "website_user_new",
+    "password": "dR9ZAk(#DH9I&QYVH6AD",
+    "database": "cwg_crm",
+    "port": "3306",
+    "host": "8.211.56.222",
+    "dialect": "mysql",
+    "define": {
+      "timestamps": false
+    }
+  },
+  "secret": "a secret that no one should guess"
+}

+ 45 - 0
card_server/db/models/index.js

@@ -0,0 +1,45 @@
+'use strict'
+const fs = require('fs')
+const path = require('path')
+const Sequelize = require('sequelize')
+const basename = path.basename(__filename)
+const config = require('../config/config.json')[
+  process.env.NODE_ENV || 'development'
+]
+const db = {}
+
+let sequelize
+if (config.use_env_variable) {
+  sequelize = new Sequelize(process.env[config.use_env_variable], config)
+} else {
+  sequelize = new Sequelize(
+    config.database,
+    config.username,
+    config.password,
+    config
+  )
+}
+
+fs.readdirSync(__dirname)
+  .filter((file) => {
+    return (
+      file.indexOf('.') !== 0 && file !== basename && file.slice(-3) === '.js'
+    )
+  })
+  .forEach((file) => {
+    const model = require(path.join(__dirname, file))(
+      sequelize,
+      Sequelize.DataTypes
+    )
+    db[model.name] = model
+  })
+
+Object.keys(db).forEach((modelName) => {
+  if (db[modelName].associate) {
+    db[modelName].associate(db)
+  }
+})
+
+db.sequelize = sequelize
+db.Sequelize = Sequelize
+module.exports = db

+ 55 - 0
card_server/db/models/web_information.js

@@ -0,0 +1,55 @@
+'use strict'
+const Sequelize = require('sequelize')
+module.exports = (sequelize, DataTypes) => {
+  class web_information extends Sequelize.Model {
+    /**
+     * Helper method for defining associations.
+     * This method is not a part of Sequelize lifecycle.
+     * The `models/index` file will call this method automatically.
+     */
+    static associate(models) {
+      // define association here
+    }
+  }
+  web_information.init(
+    {
+      id: {
+        type: DataTypes.INTEGER,
+        primaryKey: true
+      },
+      title: {
+        type: DataTypes.STRING
+      },
+      sub_title: {
+        type: DataTypes.STRING
+      },
+      delivery_time: {
+        type: DataTypes.DATE
+      },
+      lang: {
+        type: DataTypes.STRING
+      },
+      content: {
+        type: DataTypes.STRING
+      },
+      add_time: {
+        type: DataTypes.DATE
+      },
+      add_user: {
+        type: DataTypes.STRING
+      },
+      add_ip: {
+        type: DataTypes.STRING
+      },
+      cover_image: {
+        type: DataTypes.STRING
+      },
+    },
+    {
+      sequelize,
+      freezeTableName: true,
+      modelName: 'web_information'
+    }
+  )
+  return web_information
+}

+ 43 - 0
card_server/db/models/web_information_tag.js

@@ -0,0 +1,43 @@
+'use strict'
+const Sequelize = require('sequelize')
+module.exports = (sequelize, DataTypes) => {
+  class web_information_tag extends Sequelize.Model {
+    /**
+     * Helper method for defining associations.
+     * This method is not a part of Sequelize lifecycle.
+     * The `models/index` file will call this method automatically.
+     */
+    static associate(models) {
+      // define association here
+    }
+  }
+  web_information_tag.init(
+    {
+      id: {
+        type: DataTypes.INTEGER,
+        primaryKey: true
+      },
+      tag: {
+        type: DataTypes.INTEGER
+      },
+      information_id: {
+        type: DataTypes.INTEGER
+      },
+      add_time: {
+        type: DataTypes.DATE
+      },
+      add_user: {
+        type: DataTypes.STRING
+      },
+      add_ip: {
+        type: DataTypes.STRING
+      }
+    },
+    {
+      sequelize,
+      freezeTableName: true,
+      modelName: 'web_information_tag'
+    }
+  )
+  return web_information_tag
+}

+ 69 - 0
card_server/downloadTask.js

@@ -0,0 +1,69 @@
+const cron = require("node-cron");
+const axios = require("axios");
+const fs = require("fs-extra");
+const path = require("path");
+const unzipper = require("unzipper");
+const time = "0 0 2 * *" //设置时间
+// 下载链接
+const DOWNLOAD_URL = "https://www.ip2location.com/download/?token=3Fi4pprzwKQUHVgw8F8HOnfWrmLTjpLCvJ9w8E7nzIlm3avAT2aJp8u68VHGiPyb&file=DB1LITEBIN";
+// 文件保存路径
+const DESTINATION_PATH = path.join(__dirname, "src/db");
+const ZIP_FILE_PATH = path.join(DESTINATION_PATH, "db_download.zip"); // 临时 ZIP 文件路径
+// 下载文件(带重试机制)
+async function downloadFileWithRetry(url, destination, retries = 3) {
+  for (let attempt = 1; attempt <= retries; attempt++) {
+    try {
+      console.log(`📥 尝试下载 (${attempt}/${retries})...`);
+      const response = await axios({
+        method: "GET",
+        url,
+        responseType: "stream",
+      });
+      // 确保目录存在
+      await fs.ensureDir(path.dirname(destination));
+      // 保存 ZIP 文件
+      const writer = fs.createWriteStream(destination);
+      response.data.pipe(writer);
+      await new Promise((resolve, reject) => {
+        writer.on("finish", resolve);
+        writer.on("error", reject);
+      });
+      console.log("✅ ZIP 文件下载成功!");
+      return true;
+    } catch (error) {
+      console.error(`❌ 下载失败 (尝试 ${attempt}/${retries}):`, error.message);
+      if (attempt === retries) {
+        console.error("⚠️ 最终下载失败,放弃重试!");
+        return false;
+      }
+      await new Promise((resolve) => setTimeout(resolve, 5000)); // 等待 5 秒再重试
+    }
+  }
+}
+
+// 解压 ZIP 文件
+async function unzipFile(zipPath, extractTo) {
+  try {
+    console.log("📂 开始解压 ZIP 文件...");
+    await fs.ensureDir(extractTo); // 确保解压目录存在
+    await fs.createReadStream(zipPath)
+      .pipe(unzipper.Extract({ path: extractTo }))
+      .promise();
+    console.log("✅ ZIP 文件解压成功!");
+    await fs.remove(zipPath); // 删除 ZIP 文件,节省空间
+  } catch (error) {
+    console.error("❌ 解压 ZIP 文件时出错:", error.message);
+  }
+}
+
+// 定时任务:每天 16:14 执行
+cron.schedule(time, async () => {
+  console.log("📌 开始下载 IP2Location 数据库...");
+  const success = await downloadFileWithRetry(DOWNLOAD_URL, ZIP_FILE_PATH);
+  if (success) {
+    await unzipFile(ZIP_FILE_PATH, DESTINATION_PATH);
+  }
+});
+
+// 让进程保持运行,防止定时任务停止
+process.stdin.resume();

+ 9 - 0
card_server/jsconfig.json

@@ -0,0 +1,9 @@
+{
+  "compilerOptions": {
+    "baseUrl": "./",
+    "paths": {
+      "@/*": ["src/*"]
+    }
+  },
+  "exclude": ["node_modules"]
+}

+ 62 - 0
card_server/package.json

@@ -0,0 +1,62 @@
+{
+  "name": "cwg_server",
+  "version": "1.0.0",
+  "description": "",
+  "main": "card.js",
+  "scripts": {
+    "dev": "cross-env NODE_ENV=development nodemon src/card.js",
+    "lint": "eslint --fix --ext .js,.vue src/",
+    "sequelize-prod": "npx sequelize-cli db:migrate",
+    "sequelize-cli": "npx sequelize-cli migration:generate --name migration-skeleton",
+    "pm2:logs": "cross-env NODE_ENV=development pm2 logs",
+    "pm2:restart": "cross-env NODE_ENV=development pm2 restart all",
+    "pm2:delete": "cross-env NODE_ENV=development pm2 delete all",
+    "pm2:start": "cross-env NODE_ENV=development pm2 start ./src/card.js --watch",
+    "pm2:logs-pro": "cross-env NODE_ENV=production pm2 logs",
+    "pm2:restart-pro": "cross-env NODE_ENV=production pm2 restart all",
+    "pm2:delete-pro": "cross-env NODE_ENV=production pm2 delete all",
+    "pm2:start-pro": "cross-env NODE_ENV=production pm2 start ./src/card.js --watch"
+  },
+  "keywords": [],
+  "author": "",
+  "dependencies": {
+    "axios": "^1.9.0",
+    "babel-eslint": "^10.1.0",
+    "bcryptjs": "^2.4.3",
+    "circular-json": "^0.5.9",
+    "connect-multiparty": "^2.2.0",
+    "cookie-parser": "^1.4.6",
+    "cors": "^2.8.5",
+    "dayjs": "^1.10.7",
+    "express": "^4.17.1",
+    "express-fileupload": "^1.2.1",
+    "express-jwt": "^6.1.1",
+    "express-session": "^1.17.3",
+    "fs-extra": "^11.3.0",
+    "ip2location-nodejs": "^9.6.1",
+    "jsonwebtoken": "^8.5.1",
+    "mysql2": "^2.3.2",
+    "node-cron": "^3.0.3",
+    "node-xlsx": "^0.21.0",
+    "nodemon": "^2.0.14",
+    "request-ip": "^3.3.0",
+    "sequelize": "^6.8.0",
+    "sequelize-cli": "^6.2.0",
+    "svg-captcha": "^1.4.0",
+    "unzipper": "^0.12.3",
+    "xlsx": "^0.18.5"
+  },
+  "devDependencies": {
+    "@babel/eslint-parser": "^7.16.0",
+    "@types/express": "^4.17.13",
+    "@types/express-fileupload": "^1.1.7",
+    "cross-env": "^7.0.3",
+    "eslint": "^7.22.0",
+    "eslint-config-prettier": "^8.1.0",
+    "eslint-plugin-prettier": "^3.3.1",
+    "prettier": "^2.2.1"
+  },
+  "eslintConfig": {
+    "parser": "babel-eslint"
+  }
+}

+ 62 - 0
card_server/src/card.js

@@ -0,0 +1,62 @@
+const express = require('express')
+const cors = require('cors')
+const fileUpload = require('express-fileupload')
+const app = express()
+const router = require('./router/index')
+var session = require('express-session')
+var cookieParser = require('cookie-parser')
+app.use(cookieParser())
+// require("../downloadTask");
+app.use(
+  session({
+    secret: '12345',
+    name: 'name',
+    cookie: { maxAge: 60000 },
+    resave: false,
+    saveUninitialized: true
+  })
+)
+function globalError(error, req, res, next) {
+  if (error && error instanceof Error) {
+    const { message } = error
+    res.status(500).json({
+      code: 500,
+      message: `${message || '服务器错误'}`
+    })
+  } else {
+    next(error)
+  }
+}
+function globalSuccessResponseMiddleware(data, req, res, next) {
+  if (data) {
+    res.json({
+      code: 200,
+      message: '请求成功',
+      data
+    })
+  }
+}
+app.use(cors())
+app.use(express.json())
+app.use(fileUpload({ createParentPath: true }))
+app.use(express.urlencoded({ extended: false }))
+
+app.use('/static', express.static('static'))
+
+// 写入路由
+for (const key in router) {
+  app.use(`/${key}`, router[key])
+}
+// 路由不存在
+app.use('*', (req, res) => {
+  res.status(404).json({
+    code: 404,
+    message: 'not found'
+  })
+})
+
+app.use(globalError)
+app.use(globalSuccessResponseMiddleware)
+app.listen(19998, () => {
+  console.log('服务已启动')
+})

+ 17 - 0
card_server/src/router/index.js

@@ -0,0 +1,17 @@
+'use strict'
+
+const fs = require('fs')
+const path = require('path')
+const basename = path.basename(__filename)
+const router = {}
+fs.readdirSync(__dirname)
+  .filter((file) => {
+    return (
+      file.indexOf('.') !== 0 && file !== basename && file.slice(-3) === '.js'
+    )
+  })
+  .forEach((file) => {
+    const name = file.slice(0, file.length - 10)
+    router[name] = require(`./${file}`)
+  })
+module.exports = router

+ 54 - 0
card_server/src/router/wasabi.router.js

@@ -0,0 +1,54 @@
+// information.router
+const express = require('express')
+const db = require('../../db/models')
+const router = express.Router()
+const toCamel = (obj) => {
+  if (!obj || typeof obj !== "object") return obj;
+  const newObj = {};
+  for (const key in obj) {
+    const camelKey = key.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
+    newObj[camelKey] = obj[key];
+  }
+  return newObj;
+};
+const getUcardFile = async (req, _, next) => {
+  try {
+    let { lang } = req.body;
+    let rows = await db.sequelize.query(
+      `
+      SELECT lang, pdf_path, pdf_password, file_info
+      FROM ucard_file
+      WHERE lang = :lang
+      LIMIT 1
+      `,
+      {
+        type: db.sequelize.QueryTypes.SELECT,
+        replacements: { lang }
+      }
+    );
+    if (!rows || rows.length === 0) {
+      rows = await db.sequelize.query(
+        `
+        SELECT lang, pdf_path, pdf_password, file_info
+        FROM ucard_file
+        WHERE lang = 'en'
+        LIMIT 1
+        `,
+        {
+          type: db.sequelize.QueryTypes.SELECT
+        }
+      );
+    }
+    const result = rows[0] ? toCamel(rows[0]) : null;
+    return result;
+  } catch (error) {
+    console.log(error);
+    return error;
+  }
+};
+router.post('/card/file/info', async (req, _, next) => {
+  let res = await getUcardFile(req, _)
+  next({ ...res })
+})
+
+module.exports = router

+ 42 - 0
card_server/src/utils/common.js

@@ -0,0 +1,42 @@
+const svgCaptcha = require('svg-captcha')
+module.exports = {
+  toArray: function (str) {
+    let newStr = str
+    if (typeof newStr === 'string') {
+      newStr = newStr.split(',')
+    }
+    return newStr
+  },
+  svgCode: function () {
+    const captcha = svgCaptcha.create({
+      size: 4, // 验证码长度
+      noise: 1, // 干扰线条数目
+      width: 300, // 宽度
+      height: 50, // 高度
+      inverse: false, // 翻转颜色
+      fontSize: 65, // 字体大小
+      color: true, // 验证码字符颜色(需设置背景色)
+      background: '#ccc' // 背景
+    })
+    return captcha
+  },
+  guid: function () {
+    function S4() {
+      return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1)
+    }
+    return (
+      S4() +
+      S4() +
+      '-' +
+      S4() +
+      '-' +
+      S4() +
+      '-' +
+      S4() +
+      '-' +
+      S4() +
+      S4() +
+      S4()
+    )
+  }
+}

+ 10 - 0
card_server/src/utils/setting.js

@@ -0,0 +1,10 @@
+module.exports = {
+  token: {
+    // token密钥
+    signKey: 'blog_globM_token_key_',
+    // 过期时间
+    signTime: 3600 * 24 * 3,
+    // 请求头参数
+    header: 'authorization'
+  }
+}

+ 36 - 0
card_server/src/utils/verify.js

@@ -0,0 +1,36 @@
+// verify.js
+const jwt = require('jsonwebtoken')
+const setting = require('./setting')
+
+const verify = {
+  // 设置token
+  setToken(userName, uid) {
+    // eslint-disable-next-line no-undef
+    return new Promise((resolve) => {
+      const token = jwt.sign(
+        // 存储数据,自定义
+        { userName, uid },
+        // 密钥
+        setting.token.signKey,
+        // 过期时间
+        { expiresIn: setting.token.signTime }
+      )
+      resolve(token)
+    })
+  },
+  getToken(token) {
+    // eslint-disable-next-line no-undef
+    return new Promise((resolve, reject) => {
+      // 判断token是否存在,这里是根据空格分割
+      if (!token.split(' ').length) {
+        reject({ error: 'The token value is empty' })
+      } else {
+        // 解密token并返回数据
+        const data = jwt.verify(token.split(' ')[1], setting.token.signKey)
+        resolve(data)
+      }
+    })
+  }
+}
+
+module.exports = verify

+ 0 - 0
.env → next/.env


+ 0 - 0
.env.prod → next/.env.prod


+ 0 - 0
.env.test → next/.env.test


+ 0 - 0
.gitignore → next/.gitignore


+ 0 - 0
README.md → next/README.md


+ 0 - 0
server.js → next/card-server.js


+ 0 - 0
eslint.config.mjs → next/eslint.config.mjs


+ 0 - 0
global.ts → next/global.ts


+ 0 - 0
jest.config.js → next/jest.config.js


+ 0 - 0
messages/ar.json → next/messages/ar.json


+ 0 - 0
messages/cn.json → next/messages/cn.json


+ 0 - 0
messages/de.json → next/messages/de.json


+ 0 - 0
messages/en.json → next/messages/en.json


+ 0 - 0
messages/es.json → next/messages/es.json


+ 0 - 0
messages/fa.json → next/messages/fa.json


+ 0 - 0
messages/id.json → next/messages/id.json


+ 0 - 0
messages/ko.json → next/messages/ko.json


+ 0 - 0
messages/ms.json → next/messages/ms.json


+ 0 - 0
messages/pt.json → next/messages/pt.json


+ 0 - 0
messages/th.json → next/messages/th.json


+ 0 - 0
messages/tr.json → next/messages/tr.json


+ 0 - 0
messages/vi.json → next/messages/vi.json


+ 0 - 0
messages/zh.json → next/messages/zh.json


+ 1 - 1
next-env.d.ts → next/next-env.d.ts

@@ -1,6 +1,6 @@
 /// <reference types="next" />
 /// <reference types="next/image-types/global" />
-import "./.next/dev/types/routes.d.ts";
+import "./.next/types/routes.d.ts";
 
 // NOTE: This file should not be edited
 // see https://nextjs.org/docs/app/api-reference/config/typescript for more information.

+ 0 - 0
next.config.ts → next/next.config.ts


+ 7 - 0
package.json → next/package.json

@@ -11,6 +11,13 @@
     "start:prod": "dotenv -e .env.prod next start",
     "lint": "eslint src && prettier src --check",
     "test": "pnpm run test:playwright && pnpm run test:jest",
+    "pm2:logs": "pm2 logs",
+    "pm2:restart": "pm2 restart all",
+    "pm2:delete": "pm2 delete all",
+    "pm2:list": "pm2 list",
+    "pm2:start": "pm2 start card-server.js",
+    "pm2:stop": "pm2 stop card-server.js",
+    "pm2:reload": "pm2 reload card-server.js",
     "test:playwright": "playwright test",
     "test:jest": "jest"
   },

+ 0 - 0
playwright.config.ts → next/playwright.config.ts


+ 0 - 0
postcss.config.js → next/postcss.config.js


+ 0 - 0
public/favicon.ico → next/public/favicon.ico


+ 0 - 0
public/icons/icon_account.svg → next/public/icons/icon_account.svg


+ 0 - 0
public/icons/icon_back.svg → next/public/icons/icon_back.svg


+ 0 - 0
public/icons/icon_candle.svg → next/public/icons/icon_candle.svg


+ 0 - 0
public/icons/icon_chart.svg → next/public/icons/icon_chart.svg


+ 0 - 0
public/icons/icon_course.svg → next/public/icons/icon_course.svg


+ 0 - 0
public/icons/icon_dropdown.svg → next/public/icons/icon_dropdown.svg


+ 0 - 0
public/icons/icon_flip.svg → next/public/icons/icon_flip.svg


+ 0 - 0
public/icons/icon_format comfy.svg → next/public/icons/icon_format comfy.svg


+ 0 - 0
public/icons/icon_format list.svg → next/public/icons/icon_format list.svg


+ 0 - 0
public/icons/icon_forward-1.svg → next/public/icons/icon_forward-1.svg


+ 0 - 0
public/icons/icon_forward.svg → next/public/icons/icon_forward.svg


+ 0 - 0
public/icons/icon_language.svg → next/public/icons/icon_language.svg


+ 0 - 0
public/icons/icon_more.svg → next/public/icons/icon_more.svg


+ 0 - 0
public/icons/icon_save.svg → next/public/icons/icon_save.svg


+ 0 - 0
public/icons/icon_search.svg → next/public/icons/icon_search.svg


+ 0 - 0
public/icons/icon_time.svg → next/public/icons/icon_time.svg


+ 0 - 0
public/icons/icon_to.svg → next/public/icons/icon_to.svg


+ 0 - 0
public/icons/icon_up.svg → next/public/icons/icon_up.svg


+ 0 - 0
public/images/favicon.png → next/public/images/favicon.png


+ 0 - 0
public/images/imgs/back-office-management.webp → next/public/images/imgs/back-office-management.webp


+ 0 - 0
public/images/imgs/cwg-logo.svg → next/public/images/imgs/cwg-logo.svg


+ 0 - 0
public/images/imgs/cwg-step.png → next/public/images/imgs/cwg-step.png


+ 0 - 0
public/images/imgs/cwg-visa-card.png → next/public/images/imgs/cwg-visa-card.png


+ 0 - 0
public/images/imgs/desktop.ini → next/public/images/imgs/desktop.ini


+ 0 - 0
public/images/imgs/favicon.ico → next/public/images/imgs/favicon.ico


+ 0 - 0
public/images/imgs/globe-payment.webp → next/public/images/imgs/globe-payment.webp


+ 0 - 0
public/images/imgs/header-bg.gif → next/public/images/imgs/header-bg.gif


+ 0 - 0
public/images/imgs/header-bg.png → next/public/images/imgs/header-bg.png


+ 0 - 0
public/images/imgs/icon-1-01.svg → next/public/images/imgs/icon-1-01.svg


+ 0 - 0
public/images/imgs/icon.png → next/public/images/imgs/icon.png


+ 0 - 0
public/images/imgs/money-deposit.webp → next/public/images/imgs/money-deposit.webp


+ 0 - 0
public/images/imgs/separator-01.svg → next/public/images/imgs/separator-01.svg


+ 0 - 0
public/images/imgs/separator-02.svg → next/public/images/imgs/separator-02.svg


+ 0 - 0
public/js/jquery.js → next/public/js/jquery.js


+ 0 - 0
public/js/main.js → next/public/js/main.js


+ 0 - 0
public/js/pdf.worker.min.js → next/public/js/pdf.worker.min.js


+ 0 - 0
public/js/vendors.js → next/public/js/vendors.js


+ 0 - 0
public/js/vendors.min.js → next/public/js/vendors.min.js


+ 0 - 0
public/js/vendors/anime.min.js → next/public/js/vendors/anime.min.js


+ 0 - 0
public/js/vendors/atropos.js → next/public/js/vendors/atropos.js


+ 0 - 0
public/js/vendors/bootstrap.bundle.js → next/public/js/vendors/bootstrap.bundle.js


+ 0 - 0
public/js/vendors/bootstrap.bundle.js.map → next/public/js/vendors/bootstrap.bundle.js.map


+ 0 - 0
public/js/vendors/gsap.js → next/public/js/vendors/gsap.js


+ 0 - 0
public/js/vendors/imagesloaded.pkgd.js → next/public/js/vendors/imagesloaded.pkgd.js


+ 0 - 0
public/js/vendors/interactive-portfolio.js → next/public/js/vendors/interactive-portfolio.js


+ 0 - 0
public/js/vendors/isotope.pkgd.js → next/public/js/vendors/isotope.pkgd.js


+ 0 - 0
public/js/vendors/jquery-cookie.js → next/public/js/vendors/jquery-cookie.js


+ 0 - 0
public/js/vendors/jquery.appear.js → next/public/js/vendors/jquery.appear.js


+ 0 - 0
public/js/vendors/jquery.count-to.js → next/public/js/vendors/jquery.count-to.js


+ 0 - 0
public/js/vendors/jquery.countdown.js → next/public/js/vendors/jquery.countdown.js


Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä