Browse Source

cv老项目代码(原代码已丢失) 报告开放出去的静态页面

Karsa 2 years ago
commit
0b26abca18
73 changed files with 2713 additions and 0 deletions
  1. 4 0
      .env.development
  2. 4 0
      .env.product
  3. 2 0
      .env.test
  4. 9 0
      .gitignore
  5. 0 0
      README.md
  6. 14 0
      index.html
  7. 26 0
      package.json
  8. 1 0
      public/jquery-3.6.0.min.js
  9. 4 0
      src/App.vue
  10. 19 0
      src/api/api.js
  11. 787 0
      src/api/crypto.js
  12. 56 0
      src/api/http.js
  13. BIN
      src/assets/img/accessbg.png
  14. BIN
      src/assets/img/account.png
  15. BIN
      src/assets/img/addup.png
  16. BIN
      src/assets/img/arrow_left.png
  17. BIN
      src/assets/img/company.png
  18. BIN
      src/assets/img/down.png
  19. BIN
      src/assets/img/downicon.png
  20. BIN
      src/assets/img/downsort.png
  21. BIN
      src/assets/img/jiandown.png
  22. BIN
      src/assets/img/kongbtnbg.png
  23. BIN
      src/assets/img/listplay.png
  24. BIN
      src/assets/img/liststop.png
  25. BIN
      src/assets/img/loading.gif
  26. BIN
      src/assets/img/loginbtn.png
  27. BIN
      src/assets/img/loginfooter.png
  28. BIN
      src/assets/img/logo.png
  29. BIN
      src/assets/img/moreimg.png
  30. BIN
      src/assets/img/name.png
  31. BIN
      src/assets/img/newbtn.png
  32. BIN
      src/assets/img/newbtn600.png
  33. BIN
      src/assets/img/newclosesmall.png
  34. BIN
      src/assets/img/newshouqi.png
  35. BIN
      src/assets/img/newstopimg.png
  36. BIN
      src/assets/img/newwhitepause.png
  37. BIN
      src/assets/img/newwhitepausesmall.png
  38. BIN
      src/assets/img/newwhiteplay.png
  39. BIN
      src/assets/img/newwhiteplaysmall.png
  40. BIN
      src/assets/img/next.png
  41. BIN
      src/assets/img/noaccessbtn.png
  42. BIN
      src/assets/img/nonedata.png
  43. BIN
      src/assets/img/nosort.png
  44. BIN
      src/assets/img/pauseImg.png
  45. BIN
      src/assets/img/play.png
  46. BIN
      src/assets/img/playImg.png
  47. BIN
      src/assets/img/pre.png
  48. BIN
      src/assets/img/returnhome.png
  49. BIN
      src/assets/img/returntop.png
  50. BIN
      src/assets/img/righticon.png
  51. BIN
      src/assets/img/shouqi.png
  52. BIN
      src/assets/img/stopimg.png
  53. BIN
      src/assets/img/tele.png
  54. BIN
      src/assets/img/turndown.png
  55. BIN
      src/assets/img/turnup.png
  56. BIN
      src/assets/img/upicon.png
  57. BIN
      src/assets/img/upselect.png
  58. BIN
      src/assets/img/upsort.png
  59. BIN
      src/assets/img/videocover.png
  60. BIN
      src/assets/img/whitepause.png
  61. BIN
      src/assets/img/whiteplay.png
  62. 125 0
      src/components/progress-bar.vue
  63. 14 0
      src/main.js
  64. 36 0
      src/router/index.js
  65. 39 0
      src/store/index.js
  66. 25 0
      src/style/common.scss
  67. 6 0
      src/style/mixin.scss
  68. 114 0
      src/utils/rem.js
  69. 21 0
      src/views/Error.vue
  70. 557 0
      src/views/report/audioPlay.vue
  71. 446 0
      src/views/report/reportDetail.vue
  72. 383 0
      src/views/reportEn/detail.vue
  73. 21 0
      vite.config.js

+ 4 - 0
.env.development

@@ -0,0 +1,4 @@
+VITE_APP_BASE_URL="/"
+VITE_APP_OUTDIR="rddp_share"
+
+VITE_APP_BASEAPIURL="https://share.hzinsights.com/api"

+ 4 - 0
.env.product

@@ -0,0 +1,4 @@
+VITE_APP_BASE_URL="/"
+VITE_APP_OUTDIR="rddp_share"
+
+VITE_APP_BASEAPIURL="https://share.hzinsights.com/api"

+ 2 - 0
.env.test

@@ -0,0 +1,2 @@
+
+

+ 9 - 0
.gitignore

@@ -0,0 +1,9 @@
+node_modules
+.DS_Store
+dist
+dist-ssr
+rddp_share
+rddp_share.zip
+*.local
+.vscode
+package-lock.json

+ 0 - 0
README.md


+ 14 - 0
index.html

@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover">
+    <title>弘则研报</title>
+    <script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
+    <script src="/jquery-3.6.0.min.js"></script>
+  </head>
+  <body>
+    <div id="app"></div>
+    <script type="module" src="/src/main.js"></script>
+  </body>
+</html>

+ 26 - 0
package.json

@@ -0,0 +1,26 @@
+{
+  "name": "hongze_xcx_h5",
+  "version": "0.0.0",
+  "scripts": {
+    "dev": "vite --host 0.0.0.0",
+    "build": "vite build --mode product",
+    "serve": "vite preview --port 3001"
+  },
+  "dependencies": {
+    "@vant/touch-emulator": "^1.3.2",
+    "axios": "^0.24.0",
+    "lodash": "^4.17.21",
+    "moment": "^2.29.1",
+    "normalize.css": "^8.0.1",
+    "vant": "^3.3.4",
+    "vue": "^3.2.16",
+    "vue-router": "^4.0.12",
+    "vuex": "^4.0.2"
+  },
+  "devDependencies": {
+    "@vitejs/plugin-vue": "^1.9.3",
+    "sass": "^1.44.0",
+    "vite": "^2.6.4",
+    "vite-plugin-style-import": "^1.4.0"
+  }
+}

File diff suppressed because it is too large
+ 1 - 0
public/jquery-3.6.0.min.js


+ 4 - 0
src/App.vue

@@ -0,0 +1,4 @@
+<template>
+  <router-view />
+</template>
+

+ 19 - 0
src/api/api.js

@@ -0,0 +1,19 @@
+import { get, post } from "./http";
+
+/**
+ * 研报详情
+ * @param {*} params ReportCode
+ * @returns 
+ */
+export const reportDetail = params => {
+  return get('/report/share/detail',params)
+}
+
+/**
+ * 英文研报详情
+ * @param {*} params ReportCode
+ * @returns 
+ */
+export const reportEnDetail = params => {
+  return get('/english_report/share/detail',params)
+}

+ 787 - 0
src/api/crypto.js

@@ -0,0 +1,787 @@
+const key = 'KcSJaJoUBC2ZAA7HEWpaiH49';
+
+class CryptoJS {
+	// 3DES加密,CBC/PKCS5Padding
+	static Des3Encrypt (input) {
+		let genKey = genkey(key, 0, 24);
+		return base64encode(des(genKey.key, input, 1, 1, key.substr(0, 8), 1));
+	}
+
+	// 3DES解密,CBC/PKCS5Padding
+	static Des3Decrypt (input) {
+		let genKey = genkey(key, 0, 24);
+		return des(genKey.key, base64decode(input), 0, 1, key.substr(0, 8), 1);
+	}
+
+	// md5
+	static Md5Encrypt (input) {
+		return md5(String(input));
+	}
+}
+
+function des (key, message, encrypt, mode, iv, padding) {
+	if (encrypt) // 如果是加密的话,首先转换编码
+	{ message = unescape(encodeURIComponent(message)); }
+	// declaring this locally speeds things up a bit
+	let spfunction1 = new Array(0x1010400, 0, 0x10000, 0x1010404, 0x1010004, 0x10404, 0x4, 0x10000, 0x400, 0x1010400, 0x1010404, 0x400, 0x1000404, 0x1010004, 0x1000000, 0x4, 0x404, 0x1000400, 0x1000400, 0x10400, 0x10400, 0x1010000, 0x1010000, 0x1000404, 0x10004, 0x1000004, 0x1000004, 0x10004, 0, 0x404, 0x10404, 0x1000000, 0x10000, 0x1010404, 0x4, 0x1010000, 0x1010400, 0x1000000, 0x1000000, 0x400, 0x1010004, 0x10000, 0x10400, 0x1000004, 0x400, 0x4, 0x1000404, 0x10404, 0x1010404, 0x10004, 0x1010000, 0x1000404, 0x1000004, 0x404, 0x10404, 0x1010400, 0x404, 0x1000400, 0x1000400, 0, 0x10004, 0x10400, 0, 0x1010004);
+	let spfunction2 = new Array(-0x7fef7fe0, -0x7fff8000, 0x8000, 0x108020, 0x100000, 0x20, -0x7fefffe0, -0x7fff7fe0, -0x7fffffe0, -0x7fef7fe0, -0x7fef8000, -0x80000000, -0x7fff8000, 0x100000, 0x20, -0x7fefffe0, 0x108000, 0x100020, -0x7fff7fe0, 0, -0x80000000, 0x8000, 0x108020, -0x7ff00000, 0x100020, -0x7fffffe0, 0, 0x108000, 0x8020, -0x7fef8000, -0x7ff00000, 0x8020, 0, 0x108020, -0x7fefffe0, 0x100000, -0x7fff7fe0, -0x7ff00000, -0x7fef8000, 0x8000, -0x7ff00000, -0x7fff8000, 0x20, -0x7fef7fe0, 0x108020, 0x20, 0x8000, -0x80000000, 0x8020, -0x7fef8000, 0x100000, -0x7fffffe0, 0x100020, -0x7fff7fe0, -0x7fffffe0, 0x100020, 0x108000, 0, -0x7fff8000, 0x8020, -0x80000000, -0x7fefffe0, -0x7fef7fe0, 0x108000);
+	let spfunction3 = new Array(0x208, 0x8020200, 0, 0x8020008, 0x8000200, 0, 0x20208, 0x8000200, 0x20008, 0x8000008, 0x8000008, 0x20000, 0x8020208, 0x20008, 0x8020000, 0x208, 0x8000000, 0x8, 0x8020200, 0x200, 0x20200, 0x8020000, 0x8020008, 0x20208, 0x8000208, 0x20200, 0x20000, 0x8000208, 0x8, 0x8020208, 0x200, 0x8000000, 0x8020200, 0x8000000, 0x20008, 0x208, 0x20000, 0x8020200, 0x8000200, 0, 0x200, 0x20008, 0x8020208, 0x8000200, 0x8000008, 0x200, 0, 0x8020008, 0x8000208, 0x20000, 0x8000000, 0x8020208, 0x8, 0x20208, 0x20200, 0x8000008, 0x8020000, 0x8000208, 0x208, 0x8020000, 0x20208, 0x8, 0x8020008, 0x20200);
+	let spfunction4 = new Array(0x802001, 0x2081, 0x2081, 0x80, 0x802080, 0x800081, 0x800001, 0x2001, 0, 0x802000, 0x802000, 0x802081, 0x81, 0, 0x800080, 0x800001, 0x1, 0x2000, 0x800000, 0x802001, 0x80, 0x800000, 0x2001, 0x2080, 0x800081, 0x1, 0x2080, 0x800080, 0x2000, 0x802080, 0x802081, 0x81, 0x800080, 0x800001, 0x802000, 0x802081, 0x81, 0, 0, 0x802000, 0x2080, 0x800080, 0x800081, 0x1, 0x802001, 0x2081, 0x2081, 0x80, 0x802081, 0x81, 0x1, 0x2000, 0x800001, 0x2001, 0x802080, 0x800081, 0x2001, 0x2080, 0x800000, 0x802001, 0x80, 0x800000, 0x2000, 0x802080);
+	let spfunction5 = new Array(0x100, 0x2080100, 0x2080000, 0x42000100, 0x80000, 0x100, 0x40000000, 0x2080000, 0x40080100, 0x80000, 0x2000100, 0x40080100, 0x42000100, 0x42080000, 0x80100, 0x40000000, 0x2000000, 0x40080000, 0x40080000, 0, 0x40000100, 0x42080100, 0x42080100, 0x2000100, 0x42080000, 0x40000100, 0, 0x42000000, 0x2080100, 0x2000000, 0x42000000, 0x80100, 0x80000, 0x42000100, 0x100, 0x2000000, 0x40000000, 0x2080000, 0x42000100, 0x40080100, 0x2000100, 0x40000000, 0x42080000, 0x2080100, 0x40080100, 0x100, 0x2000000, 0x42080000, 0x42080100, 0x80100, 0x42000000, 0x42080100, 0x2080000, 0, 0x40080000, 0x42000000, 0x80100, 0x2000100, 0x40000100, 0x80000, 0, 0x40080000, 0x2080100, 0x40000100);
+	let spfunction6 = new Array(0x20000010, 0x20400000, 0x4000, 0x20404010, 0x20400000, 0x10, 0x20404010, 0x400000, 0x20004000, 0x404010, 0x400000, 0x20000010, 0x400010, 0x20004000, 0x20000000, 0x4010, 0, 0x400010, 0x20004010, 0x4000, 0x404000, 0x20004010, 0x10, 0x20400010, 0x20400010, 0, 0x404010, 0x20404000, 0x4010, 0x404000, 0x20404000, 0x20000000, 0x20004000, 0x10, 0x20400010, 0x404000, 0x20404010, 0x400000, 0x4010, 0x20000010, 0x400000, 0x20004000, 0x20000000, 0x4010, 0x20000010, 0x20404010, 0x404000, 0x20400000, 0x404010, 0x20404000, 0, 0x20400010, 0x10, 0x4000, 0x20400000, 0x404010, 0x4000, 0x400010, 0x20004010, 0, 0x20404000, 0x20000000, 0x400010, 0x20004010);
+	let spfunction7 = new Array(0x200000, 0x4200002, 0x4000802, 0, 0x800, 0x4000802, 0x200802, 0x4200800, 0x4200802, 0x200000, 0, 0x4000002, 0x2, 0x4000000, 0x4200002, 0x802, 0x4000800, 0x200802, 0x200002, 0x4000800, 0x4000002, 0x4200000, 0x4200800, 0x200002, 0x4200000, 0x800, 0x802, 0x4200802, 0x200800, 0x2, 0x4000000, 0x200800, 0x4000000, 0x200800, 0x200000, 0x4000802, 0x4000802, 0x4200002, 0x4200002, 0x2, 0x200002, 0x4000000, 0x4000800, 0x200000, 0x4200800, 0x802, 0x200802, 0x4200800, 0x802, 0x4000002, 0x4200802, 0x4200000, 0x200800, 0, 0x2, 0x4200802, 0, 0x200802, 0x4200000, 0x800, 0x4000002, 0x4000800, 0x800, 0x200002);
+	let spfunction8 = new Array(0x10001040, 0x1000, 0x40000, 0x10041040, 0x10000000, 0x10001040, 0x40, 0x10000000, 0x40040, 0x10040000, 0x10041040, 0x41000, 0x10041000, 0x41040, 0x1000, 0x40, 0x10040000, 0x10000040, 0x10001000, 0x1040, 0x41000, 0x40040, 0x10040040, 0x10041000, 0x1040, 0, 0, 0x10040040, 0x10000040, 0x10001000, 0x41040, 0x40000, 0x41040, 0x40000, 0x10041000, 0x1000, 0x40, 0x10040040, 0x1000, 0x41040, 0x10001000, 0x40, 0x10000040, 0x10040000, 0x10040040, 0x10000000, 0x40000, 0x10001040, 0, 0x10041040, 0x40040, 0x10000040, 0x10040000, 0x10001000, 0x10001040, 0, 0x10041040, 0x41000, 0x41000, 0x1040, 0x1040, 0x40040, 0x10000000, 0x10041000);
+
+	// create the 16 or 48 subkeys we will need
+	let keys = des_createKeys(key);
+
+	let m = 0, i, j, temp, temp2, right1, right2, left, right, looping;
+	let cbcleft, cbcleft2, cbcright, cbcright2;
+	let endloop, loopinc;
+	var len = message.length;
+	let chunk = 0;
+	// set up the loops for single and triple des
+	let iterations = keys.length === 32 ? 3 : 9; // single or triple des
+	if (iterations === 3) { looping = encrypt ? new Array(0, 32, 2) : new Array(30, -2, -2); } else { looping = encrypt ? new Array(0, 32, 2, 62, 30, -2, 64, 96, 2) : new Array(94, 62, -2, 32, 64, 2, 30, -2, -2); }
+
+	// pad the message depending on the padding parameter
+	if (padding === 2) message += '        '; // pad the message with spaces
+	else if (padding === 1) {
+		if (encrypt) {
+			temp = 8 - (len % 8);
+			message += String.fromCharCode(temp, temp, temp, temp, temp, temp, temp, temp);
+			if (temp === 8) len += 8;
+		}
+	} // PKCS7 padding
+	else if (!padding) message += '\0\0\0\0\0\0\0\0'; // pad the message out with null bytes
+
+	// store the result here
+	let result = '';
+	let tempresult = '';
+
+	if (mode === 1) { // CBC mode
+		cbcleft = (iv.charCodeAt(m++) << 24) | (iv.charCodeAt(m++) << 16) | (iv.charCodeAt(m++) << 8) | iv.charCodeAt(m++);
+		cbcright = (iv.charCodeAt(m++) << 24) | (iv.charCodeAt(m++) << 16) | (iv.charCodeAt(m++) << 8) | iv.charCodeAt(m++);
+		m = 0;
+	}
+
+	// loop through each 64 bit chunk of the message
+	while (m < len) {
+		left = (message.charCodeAt(m++) << 24) | (message.charCodeAt(m++) << 16) | (message.charCodeAt(m++) << 8) | message.charCodeAt(m++);
+		right = (message.charCodeAt(m++) << 24) | (message.charCodeAt(m++) << 16) | (message.charCodeAt(m++) << 8) | message.charCodeAt(m++);
+
+		// for Cipher Block Chaining mode, xor the message with the previous result
+		if (mode === 1) {
+			if (encrypt) {
+				left ^= cbcleft;
+				right ^= cbcright;
+			} else {
+				cbcleft2 = cbcleft;
+				cbcright2 = cbcright;
+				cbcleft = left;
+				cbcright = right;
+			}
+		}
+
+		// first each 64 but chunk of the message must be permuted according to IP
+		temp = ((left >>> 4) ^ right) & 0x0f0f0f0f;
+		right ^= temp;
+		left ^= (temp << 4);
+		temp = ((left >>> 16) ^ right) & 0x0000ffff;
+		right ^= temp;
+		left ^= (temp << 16);
+		temp = ((right >>> 2) ^ left) & 0x33333333;
+		left ^= temp;
+		right ^= (temp << 2);
+		temp = ((right >>> 8) ^ left) & 0x00ff00ff;
+		left ^= temp;
+		right ^= (temp << 8);
+		temp = ((left >>> 1) ^ right) & 0x55555555;
+		right ^= temp;
+		left ^= (temp << 1);
+
+		left = ((left << 1) | (left >>> 31));
+		right = ((right << 1) | (right >>> 31));
+
+		// do this either 1 or 3 times for each chunk of the message
+		for (j = 0; j < iterations; j += 3) {
+			endloop = looping[j + 1];
+			loopinc = looping[j + 2];
+			// now go through and perform the encryption or decryption
+			for (i = looping[j]; i !== endloop; i += loopinc) { // for efficiency
+				right1 = right ^ keys[i];
+				right2 = ((right >>> 4) | (right << 28)) ^ keys[i + 1];
+				// the result is attained by passing these bytes through the S selection functions
+				temp = left;
+				left = right;
+				right = temp ^ (spfunction2[(right1 >>> 24) & 0x3f] | spfunction4[(right1 >>> 16) & 0x3f] |
+					spfunction6[(right1 >>> 8) & 0x3f] | spfunction8[right1 & 0x3f] |
+					spfunction1[(right2 >>> 24) & 0x3f] | spfunction3[(right2 >>> 16) & 0x3f] |
+					spfunction5[(right2 >>> 8) & 0x3f] | spfunction7[right2 & 0x3f]);
+			}
+			temp = left;
+			left = right;
+			right = temp; // unreverse left and right
+		} // for either 1 or 3 iterations
+
+		// move then each one bit to the right
+		left = ((left >>> 1) | (left << 31));
+		right = ((right >>> 1) | (right << 31));
+
+		// now perform IP-1, which is IP in the opposite direction
+		temp = ((left >>> 1) ^ right) & 0x55555555;
+		right ^= temp;
+		left ^= (temp << 1);
+		temp = ((right >>> 8) ^ left) & 0x00ff00ff;
+		left ^= temp;
+		right ^= (temp << 8);
+		temp = ((right >>> 2) ^ left) & 0x33333333;
+		left ^= temp;
+		right ^= (temp << 2);
+		temp = ((left >>> 16) ^ right) & 0x0000ffff;
+		right ^= temp;
+		left ^= (temp << 16);
+		temp = ((left >>> 4) ^ right) & 0x0f0f0f0f;
+		right ^= temp;
+		left ^= (temp << 4);
+
+		// for Cipher Block Chaining mode, xor the message with the previous result
+		if (mode === 1) {
+			if (encrypt) {
+				cbcleft = left;
+				cbcright = right;
+			} else {
+				left ^= cbcleft2;
+				right ^= cbcright2;
+			}
+		}
+		tempresult += String.fromCharCode((left >>> 24), ((left >>> 16) & 0xff), ((left >>> 8) & 0xff), (left & 0xff), (right >>> 24), ((right >>> 16) & 0xff), ((right >>> 8) & 0xff), (right & 0xff));
+
+		chunk += 8;
+		if (chunk === 512) {
+			result += tempresult;
+			tempresult = '';
+			chunk = 0;
+		}
+	} // for every 8 characters, or 64 bits in the message
+
+	// return the result as an array
+	result += tempresult;
+	result = result.replace(/\0*$/g, '');
+
+	if (!encrypt) { // 如果是解密的话,解密结束后对PKCS7 padding进行解码,并转换成utf-8编码
+		if (padding === 1) { // PKCS7 padding解码
+			var len = result.length, paddingChars = 0;
+			len && (paddingChars = result.charCodeAt(len - 1));
+			(paddingChars <= 8) && (result = result.substring(0, len - paddingChars));
+		}
+		// 转换成UTF-8编码
+		result = decodeURIComponent(escape(result));
+	}
+
+	return result;
+} // end of des
+
+// des_createKeys
+// this takes as input a 64 bit key (even though only 56 bits are used)
+// as an array of 2 integers, and returns 16 48 bit keys
+function des_createKeys (key) {
+	// declaring this locally speeds things up a bit
+	let pc2bytes0 = new Array(0, 0x4, 0x20000000, 0x20000004, 0x10000, 0x10004, 0x20010000, 0x20010004, 0x200, 0x204, 0x20000200, 0x20000204, 0x10200, 0x10204, 0x20010200, 0x20010204);
+	let pc2bytes1 = new Array(0, 0x1, 0x100000, 0x100001, 0x4000000, 0x4000001, 0x4100000, 0x4100001, 0x100, 0x101, 0x100100, 0x100101, 0x4000100, 0x4000101, 0x4100100, 0x4100101);
+	let pc2bytes2 = new Array(0, 0x8, 0x800, 0x808, 0x1000000, 0x1000008, 0x1000800, 0x1000808, 0, 0x8, 0x800, 0x808, 0x1000000, 0x1000008, 0x1000800, 0x1000808);
+	let pc2bytes3 = new Array(0, 0x200000, 0x8000000, 0x8200000, 0x2000, 0x202000, 0x8002000, 0x8202000, 0x20000, 0x220000, 0x8020000, 0x8220000, 0x22000, 0x222000, 0x8022000, 0x8222000);
+	let pc2bytes4 = new Array(0, 0x40000, 0x10, 0x40010, 0, 0x40000, 0x10, 0x40010, 0x1000, 0x41000, 0x1010, 0x41010, 0x1000, 0x41000, 0x1010, 0x41010);
+	let pc2bytes5 = new Array(0, 0x400, 0x20, 0x420, 0, 0x400, 0x20, 0x420, 0x2000000, 0x2000400, 0x2000020, 0x2000420, 0x2000000, 0x2000400, 0x2000020, 0x2000420);
+	let pc2bytes6 = new Array(0, 0x10000000, 0x80000, 0x10080000, 0x2, 0x10000002, 0x80002, 0x10080002, 0, 0x10000000, 0x80000, 0x10080000, 0x2, 0x10000002, 0x80002, 0x10080002);
+	let pc2bytes7 = new Array(0, 0x10000, 0x800, 0x10800, 0x20000000, 0x20010000, 0x20000800, 0x20010800, 0x20000, 0x30000, 0x20800, 0x30800, 0x20020000, 0x20030000, 0x20020800, 0x20030800);
+	let pc2bytes8 = new Array(0, 0x40000, 0, 0x40000, 0x2, 0x40002, 0x2, 0x40002, 0x2000000, 0x2040000, 0x2000000, 0x2040000, 0x2000002, 0x2040002, 0x2000002, 0x2040002);
+	let pc2bytes9 = new Array(0, 0x10000000, 0x8, 0x10000008, 0, 0x10000000, 0x8, 0x10000008, 0x400, 0x10000400, 0x408, 0x10000408, 0x400, 0x10000400, 0x408, 0x10000408);
+	let pc2bytes10 = new Array(0, 0x20, 0, 0x20, 0x100000, 0x100020, 0x100000, 0x100020, 0x2000, 0x2020, 0x2000, 0x2020, 0x102000, 0x102020, 0x102000, 0x102020);
+	let pc2bytes11 = new Array(0, 0x1000000, 0x200, 0x1000200, 0x200000, 0x1200000, 0x200200, 0x1200200, 0x4000000, 0x5000000, 0x4000200, 0x5000200, 0x4200000, 0x5200000, 0x4200200, 0x5200200);
+	let pc2bytes12 = new Array(0, 0x1000, 0x8000000, 0x8001000, 0x80000, 0x81000, 0x8080000, 0x8081000, 0x10, 0x1010, 0x8000010, 0x8001010, 0x80010, 0x81010, 0x8080010, 0x8081010);
+	let pc2bytes13 = new Array(0, 0x4, 0x100, 0x104, 0, 0x4, 0x100, 0x104, 0x1, 0x5, 0x101, 0x105, 0x1, 0x5, 0x101, 0x105);
+
+	// how many iterations (1 for des, 3 for triple des)
+	let iterations = key.length > 8 ? 3 : 1; // changed by Paul 16/6/2007 to use Triple DES for 9+ byte keys
+	// stores the return keys
+	let keys = new Array(32 * iterations);
+	// now define the left shifts which need to be done
+	let shifts = new Array(0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0);
+	// other variables
+	let lefttemp, righttemp, m = 0, n = 0, temp;
+
+	for (let j = 0; j < iterations; j++) { // either 1 or 3 iterations
+		let left = (key.charCodeAt(m++) << 24) | (key.charCodeAt(m++) << 16) | (key.charCodeAt(m++) << 8) | key.charCodeAt(m++);
+		let right = (key.charCodeAt(m++) << 24) | (key.charCodeAt(m++) << 16) | (key.charCodeAt(m++) << 8) | key.charCodeAt(m++);
+
+		temp = ((left >>> 4) ^ right) & 0x0f0f0f0f;
+		right ^= temp;
+		left ^= (temp << 4);
+		temp = ((right >>> -16) ^ left) & 0x0000ffff;
+		left ^= temp;
+		right ^= (temp << -16);
+		temp = ((left >>> 2) ^ right) & 0x33333333;
+		right ^= temp;
+		left ^= (temp << 2);
+		temp = ((right >>> -16) ^ left) & 0x0000ffff;
+		left ^= temp;
+		right ^= (temp << -16);
+		temp = ((left >>> 1) ^ right) & 0x55555555;
+		right ^= temp;
+		left ^= (temp << 1);
+		temp = ((right >>> 8) ^ left) & 0x00ff00ff;
+		left ^= temp;
+		right ^= (temp << 8);
+		temp = ((left >>> 1) ^ right) & 0x55555555;
+		right ^= temp;
+		left ^= (temp << 1);
+
+		// the right side needs to be shifted and to get the last four bits of the left side
+		temp = (left << 8) | ((right >>> 20) & 0x000000f0);
+		// left needs to be put upside down
+		left = (right << 24) | ((right << 8) & 0xff0000) | ((right >>> 8) & 0xff00) | ((right >>> 24) & 0xf0);
+		right = temp;
+
+		// now go through and perform these shifts on the left and right keys
+		for (let i = 0; i < shifts.length; i++) {
+			// shift the keys either one or two bits to the left
+			if (shifts[i]) {
+				left = (left << 2) | (left >>> 26);
+				right = (right << 2) | (right >>> 26);
+			} else {
+				left = (left << 1) | (left >>> 27);
+				right = (right << 1) | (right >>> 27);
+			}
+			left &= -0xf;
+			right &= -0xf;
+
+			// now apply PC-2, in such a way that E is easier when encrypting or decrypting
+			// this conversion will look like PC-2 except only the last 6 bits of each byte are used
+			// rather than 48 consecutive bits and the order of lines will be according to
+			// how the S selection functions will be applied: S2, S4, S6, S8, S1, S3, S5, S7
+			lefttemp = pc2bytes0[left >>> 28] | pc2bytes1[(left >>> 24) & 0xf] |
+				pc2bytes2[(left >>> 20) & 0xf] | pc2bytes3[(left >>> 16) & 0xf] |
+				pc2bytes4[(left >>> 12) & 0xf] | pc2bytes5[(left >>> 8) & 0xf] |
+				pc2bytes6[(left >>> 4) & 0xf];
+			righttemp = pc2bytes7[right >>> 28] | pc2bytes8[(right >>> 24) & 0xf] |
+				pc2bytes9[(right >>> 20) & 0xf] | pc2bytes10[(right >>> 16) & 0xf] |
+				pc2bytes11[(right >>> 12) & 0xf] | pc2bytes12[(right >>> 8) & 0xf] |
+				pc2bytes13[(right >>> 4) & 0xf];
+			temp = ((righttemp >>> 16) ^ lefttemp) & 0x0000ffff;
+			keys[n++] = lefttemp ^ temp;
+			keys[n++] = righttemp ^ (temp << 16);
+		}
+	} // for each iterations
+	// return the keys we've created
+	return keys;
+} // end of des_createKeys
+function genkey (key, start, end) {
+	// 8 byte / 64 bit Key (DES) or 192 bit Key
+	return { key: pad(key.slice(start, end)), vector: 1 };
+}
+function pad (key) {
+	for (let i = key.length; i < 24; i++) {
+		key += '0';
+	}
+	return key;
+}
+
+let BASE64_MAPPING = [
+	'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+	'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+	'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
+	'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
+	'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+	'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+	'w', 'x', 'y', 'z', '0', '1', '2', '3',
+	'4', '5', '6', '7', '8', '9', '+', '/'
+];
+
+/**
+ *ascii convert to binary
+ */
+let _toBinary = function (ascii) {
+	let binary = new Array();
+	while (ascii > 0) {
+		let b = ascii % 2;
+		ascii = Math.floor(ascii / 2);
+		binary.push(b);
+	}
+	/*
+	 var len = binary.length;
+	 if(6-len > 0){
+	 for(var i = 6-len ; i > 0 ; --i){
+	 binary.push(0);
+	 }
+	 } */
+	binary.reverse();
+	return binary;
+};
+
+/**
+ *binary convert to decimal
+ */
+let _toDecimal = function (binary) {
+	let dec = 0;
+	let p = 0;
+	for (let i = binary.length - 1; i >= 0; --i) {
+		let b = binary[i];
+		if (b === 1) {
+			dec += Math.pow(2, p);
+		}
+		++p;
+	}
+	return dec;
+};
+
+/**
+ *unicode convert to utf-8
+ */
+let _toUTF8Binary = function (c, binaryArray) {
+	let mustLen = (8 - (c + 1)) + ((c - 1) * 6);
+	let fatLen = binaryArray.length;
+	let diff = mustLen - fatLen;
+	while (--diff >= 0) {
+		binaryArray.unshift(0);
+	}
+	let binary = [];
+	let _c = c;
+	while (--_c >= 0) {
+		binary.push(1);
+	}
+	binary.push(0);
+	let i = 0, len = 8 - (c + 1);
+	for (; i < len; ++i) {
+		binary.push(binaryArray[i]);
+	}
+
+	for (let j = 0; j < c - 1; ++j) {
+		binary.push(1);
+		binary.push(0);
+		let sum = 6;
+		while (--sum >= 0) {
+			binary.push(binaryArray[i++]);
+		}
+	}
+	return binary;
+};
+
+let BASE64 = {
+	/**
+	 *BASE64 Encode
+	 */
+	encoder: function (str) {
+		let base64_Index = [];
+		let binaryArray = [];
+		for (var i = 0, len = str.length; i < len; ++i) {
+			let unicode = str.charCodeAt(i);
+			let _tmpBinary = _toBinary(unicode);
+			if (unicode < 0x80) {
+				let _tmpdiff = 8 - _tmpBinary.length;
+				while (--_tmpdiff >= 0) {
+					_tmpBinary.unshift(0);
+				}
+				binaryArray = binaryArray.concat(_tmpBinary);
+			} else if (unicode >= 0x80 && unicode <= 0x7FF) {
+				binaryArray = binaryArray.concat(_toUTF8Binary(2, _tmpBinary));
+			} else if (unicode >= 0x800 && unicode <= 0xFFFF) { // UTF-8 3byte
+				binaryArray = binaryArray.concat(_toUTF8Binary(3, _tmpBinary));
+			} else if (unicode >= 0x10000 && unicode <= 0x1FFFFF) { // UTF-8 4byte
+				binaryArray = binaryArray.concat(_toUTF8Binary(4, _tmpBinary));
+			} else if (unicode >= 0x200000 && unicode <= 0x3FFFFFF) { // UTF-8 5byte
+				binaryArray = binaryArray.concat(_toUTF8Binary(5, _tmpBinary));
+			} else if (unicode >= 4000000 && unicode <= 0x7FFFFFFF) { // UTF-8 6byte
+				binaryArray = binaryArray.concat(_toUTF8Binary(6, _tmpBinary));
+			}
+		}
+
+		let extra_Zero_Count = 0;
+		for (var i = 0, len = binaryArray.length; i < len; i += 6) {
+			let diff = (i + 6) - len;
+			if (diff === 2) {
+				extra_Zero_Count = 2;
+			} else if (diff === 4) {
+				extra_Zero_Count = 4;
+			}
+			// if(extra_Zero_Count > 0){
+			//  len += extra_Zero_Count+1;
+			// }
+			let _tmpExtra_Zero_Count = extra_Zero_Count;
+			while (--_tmpExtra_Zero_Count >= 0) {
+				binaryArray.push(0);
+			}
+			base64_Index.push(_toDecimal(binaryArray.slice(i, i + 6)));
+		}
+
+		let base64 = '';
+		for (var i = 0, len = base64_Index.length; i < len; ++i) {
+			base64 += BASE64_MAPPING[base64_Index[i]];
+		}
+
+		for (var i = 0, len = extra_Zero_Count / 2; i < len; ++i) {
+			base64 += '=';
+		}
+		return base64;
+	},
+	/**
+	 *BASE64  Decode for UTF-8
+	 */
+	decoder: function (_base64Str) {
+		let _len = _base64Str.length;
+		let extra_Zero_Count = 0;
+		/**
+		 *计算在进行BASE64编码的时候,补了几个0
+		 */
+		if (_base64Str.charAt(_len - 1) === '=') {
+			// alert(_base64Str.charAt(_len-1));
+			// alert(_base64Str.charAt(_len-2));
+			if (_base64Str.charAt(_len - 2) === '=') { // 两个等号说明补了4个0
+				extra_Zero_Count = 4;
+				_base64Str = _base64Str.substring(0, _len - 2);
+			} else { // 一个等号说明补了2个0
+				extra_Zero_Count = 2;
+				_base64Str = _base64Str.substring(0, _len - 1);
+			}
+		}
+
+		let binaryArray = [];
+		for (var i = 0, len = _base64Str.length; i < len; ++i) {
+			let c = _base64Str.charAt(i);
+			for (let j = 0, size = BASE64_MAPPING.length; j < size; ++j) {
+				if (c === BASE64_MAPPING[j]) {
+					let _tmp = _toBinary(j);
+					/* 不足6位的补0 */
+					let _tmpLen = _tmp.length;
+					if (6 - _tmpLen > 0) {
+						for (let k = 6 - _tmpLen; k > 0; --k) {
+							_tmp.unshift(0);
+						}
+					}
+					binaryArray = binaryArray.concat(_tmp);
+					break;
+				}
+			}
+		}
+
+		if (extra_Zero_Count > 0) {
+			binaryArray = binaryArray.slice(0, binaryArray.length - extra_Zero_Count);
+		}
+
+		let unicode = [];
+		let unicodeBinary = [];
+		for (var i = 0, len = binaryArray.length; i < len;) {
+			if (binaryArray[i] === 0) {
+				unicode = unicode.concat(_toDecimal(binaryArray.slice(i, i + 8)));
+				i += 8;
+			} else {
+				let sum = 0;
+				while (i < len) {
+					if (binaryArray[i] === 1) {
+						++sum;
+					} else {
+						break;
+					}
+					++i;
+				}
+				unicodeBinary = unicodeBinary.concat(binaryArray.slice(i + 1, i + 8 - sum));
+				i += 8 - sum;
+				while (sum > 1) {
+					unicodeBinary = unicodeBinary.concat(binaryArray.slice(i + 2, i + 8));
+					i += 8;
+					--sum;
+				}
+				unicode = unicode.concat(_toDecimal(unicodeBinary));
+				unicodeBinary = [];
+			}
+		}
+		// ---------直接转换为结果
+		let strResult = '';
+		for (var i = 0, len = unicode.length; i < len; ++i) {
+			strResult += String.fromCharCode(unicode[i]);
+		}
+		return strResult;
+	}
+};
+
+let rotateLeft = function (lValue, iShiftBits) {
+	return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits));
+};
+
+let addUnsigned = function (lX, lY) {
+	let lX4, lY4, lX8, lY8, lResult;
+	lX8 = (lX & 0x80000000);
+	lY8 = (lY & 0x80000000);
+	lX4 = (lX & 0x40000000);
+	lY4 = (lY & 0x40000000);
+	lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF);
+	if (lX4 & lY4) return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
+	if (lX4 | lY4) {
+		if (lResult & 0x40000000) return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
+		else return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
+	} else {
+		return (lResult ^ lX8 ^ lY8);
+	}
+};
+
+let F = function (x, y, z) {
+	return (x & y) | ((~x) & z);
+};
+
+let G = function (x, y, z) {
+	return (x & z) | (y & (~z));
+};
+
+let H = function (x, y, z) {
+	return (x ^ y ^ z);
+};
+
+let I = function (x, y, z) {
+	return (y ^ (x | (~z)));
+};
+
+let FF = function (a, b, c, d, x, s, ac) {
+	a = addUnsigned(a, addUnsigned(addUnsigned(F(b, c, d), x), ac));
+	return addUnsigned(rotateLeft(a, s), b);
+};
+
+let GG = function (a, b, c, d, x, s, ac) {
+	a = addUnsigned(a, addUnsigned(addUnsigned(G(b, c, d), x), ac));
+	return addUnsigned(rotateLeft(a, s), b);
+};
+
+let HH = function (a, b, c, d, x, s, ac) {
+	a = addUnsigned(a, addUnsigned(addUnsigned(H(b, c, d), x), ac));
+	return addUnsigned(rotateLeft(a, s), b);
+};
+
+let II = function (a, b, c, d, x, s, ac) {
+	a = addUnsigned(a, addUnsigned(addUnsigned(I(b, c, d), x), ac));
+	return addUnsigned(rotateLeft(a, s), b);
+};
+
+let convertToWordArray = function (string) {
+	let lWordCount;
+	let lMessageLength = string.length;
+	let lNumberOfWordsTempOne = lMessageLength + 8;
+	let lNumberOfWordsTempTwo = (lNumberOfWordsTempOne - (lNumberOfWordsTempOne % 64)) / 64;
+	let lNumberOfWords = (lNumberOfWordsTempTwo + 1) * 16;
+	let lWordArray = Array(lNumberOfWords - 1);
+	let lBytePosition = 0;
+	let lByteCount = 0;
+	while (lByteCount < lMessageLength) {
+		lWordCount = (lByteCount - (lByteCount % 4)) / 4;
+		lBytePosition = (lByteCount % 4) * 8;
+		lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount) << lBytePosition));
+		lByteCount++;
+	}
+	lWordCount = (lByteCount - (lByteCount % 4)) / 4;
+	lBytePosition = (lByteCount % 4) * 8;
+	lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition);
+	lWordArray[lNumberOfWords - 2] = lMessageLength << 3;
+	lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29;
+	return lWordArray;
+};
+
+let wordToHex = function (lValue) {
+	let WordToHexValue = '', WordToHexValueTemp = '', lByte, lCount;
+	for (lCount = 0; lCount <= 3; lCount++) {
+		lByte = (lValue >>> (lCount * 8)) & 255;
+		WordToHexValueTemp = '0' + lByte.toString(16);
+		WordToHexValue = WordToHexValue + WordToHexValueTemp.substr(WordToHexValueTemp.length - 2, 2);
+	}
+	return WordToHexValue;
+};
+
+let uTF8Encode = function (str) {
+	str = str.replace(/\x0d\x0a/g, '\x0a');
+	let output = '';
+	for (let n = 0; n < str.length; n++) {
+		let c = str.charCodeAt(n);
+		if (c < 128) {
+			output += String.fromCharCode(c);
+		} else if ((c > 127) && (c < 2048)) {
+			output += String.fromCharCode((c >> 6) | 192);
+			output += String.fromCharCode((c & 63) | 128);
+		} else {
+			output += String.fromCharCode((c >> 12) | 224);
+			output += String.fromCharCode(((c >> 6) & 63) | 128);
+			output += String.fromCharCode((c & 63) | 128);
+		}
+	}
+	return output;
+};
+
+var md5 = function (string) {
+	let x = Array();
+	let k, AA, BB, CC, DD, a, b, c, d;
+	let S11 = 7, S12 = 12, S13 = 17, S14 = 22;
+	let S21 = 5, S22 = 9, S23 = 14, S24 = 20;
+	let S31 = 4, S32 = 11, S33 = 16, S34 = 23;
+	let S41 = 6, S42 = 10, S43 = 15, S44 = 21;
+	string = uTF8Encode(string);
+	x = convertToWordArray(string);
+	a = 0x67452301;
+	b = 0xEFCDAB89;
+	c = 0x98BADCFE;
+	d = 0x10325476;
+	for (k = 0; k < x.length; k += 16) {
+		AA = a;
+		BB = b;
+		CC = c;
+		DD = d;
+		a = FF(a, b, c, d, x[k + 0], S11, 0xD76AA478);
+		d = FF(d, a, b, c, x[k + 1], S12, 0xE8C7B756);
+		c = FF(c, d, a, b, x[k + 2], S13, 0x242070DB);
+		b = FF(b, c, d, a, x[k + 3], S14, 0xC1BDCEEE);
+		a = FF(a, b, c, d, x[k + 4], S11, 0xF57C0FAF);
+		d = FF(d, a, b, c, x[k + 5], S12, 0x4787C62A);
+		c = FF(c, d, a, b, x[k + 6], S13, 0xA8304613);
+		b = FF(b, c, d, a, x[k + 7], S14, 0xFD469501);
+		a = FF(a, b, c, d, x[k + 8], S11, 0x698098D8);
+		d = FF(d, a, b, c, x[k + 9], S12, 0x8B44F7AF);
+		c = FF(c, d, a, b, x[k + 10], S13, 0xFFFF5BB1);
+		b = FF(b, c, d, a, x[k + 11], S14, 0x895CD7BE);
+		a = FF(a, b, c, d, x[k + 12], S11, 0x6B901122);
+		d = FF(d, a, b, c, x[k + 13], S12, 0xFD987193);
+		c = FF(c, d, a, b, x[k + 14], S13, 0xA679438E);
+		b = FF(b, c, d, a, x[k + 15], S14, 0x49B40821);
+		a = GG(a, b, c, d, x[k + 1], S21, 0xF61E2562);
+		d = GG(d, a, b, c, x[k + 6], S22, 0xC040B340);
+		c = GG(c, d, a, b, x[k + 11], S23, 0x265E5A51);
+		b = GG(b, c, d, a, x[k + 0], S24, 0xE9B6C7AA);
+		a = GG(a, b, c, d, x[k + 5], S21, 0xD62F105D);
+		d = GG(d, a, b, c, x[k + 10], S22, 0x2441453);
+		c = GG(c, d, a, b, x[k + 15], S23, 0xD8A1E681);
+		b = GG(b, c, d, a, x[k + 4], S24, 0xE7D3FBC8);
+		a = GG(a, b, c, d, x[k + 9], S21, 0x21E1CDE6);
+		d = GG(d, a, b, c, x[k + 14], S22, 0xC33707D6);
+		c = GG(c, d, a, b, x[k + 3], S23, 0xF4D50D87);
+		b = GG(b, c, d, a, x[k + 8], S24, 0x455A14ED);
+		a = GG(a, b, c, d, x[k + 13], S21, 0xA9E3E905);
+		d = GG(d, a, b, c, x[k + 2], S22, 0xFCEFA3F8);
+		c = GG(c, d, a, b, x[k + 7], S23, 0x676F02D9);
+		b = GG(b, c, d, a, x[k + 12], S24, 0x8D2A4C8A);
+		a = HH(a, b, c, d, x[k + 5], S31, 0xFFFA3942);
+		d = HH(d, a, b, c, x[k + 8], S32, 0x8771F681);
+		c = HH(c, d, a, b, x[k + 11], S33, 0x6D9D6122);
+		b = HH(b, c, d, a, x[k + 14], S34, 0xFDE5380C);
+		a = HH(a, b, c, d, x[k + 1], S31, 0xA4BEEA44);
+		d = HH(d, a, b, c, x[k + 4], S32, 0x4BDECFA9);
+		c = HH(c, d, a, b, x[k + 7], S33, 0xF6BB4B60);
+		b = HH(b, c, d, a, x[k + 10], S34, 0xBEBFBC70);
+		a = HH(a, b, c, d, x[k + 13], S31, 0x289B7EC6);
+		d = HH(d, a, b, c, x[k + 0], S32, 0xEAA127FA);
+		c = HH(c, d, a, b, x[k + 3], S33, 0xD4EF3085);
+		b = HH(b, c, d, a, x[k + 6], S34, 0x4881D05);
+		a = HH(a, b, c, d, x[k + 9], S31, 0xD9D4D039);
+		d = HH(d, a, b, c, x[k + 12], S32, 0xE6DB99E5);
+		c = HH(c, d, a, b, x[k + 15], S33, 0x1FA27CF8);
+		b = HH(b, c, d, a, x[k + 2], S34, 0xC4AC5665);
+		a = II(a, b, c, d, x[k + 0], S41, 0xF4292244);
+		d = II(d, a, b, c, x[k + 7], S42, 0x432AFF97);
+		c = II(c, d, a, b, x[k + 14], S43, 0xAB9423A7);
+		b = II(b, c, d, a, x[k + 5], S44, 0xFC93A039);
+		a = II(a, b, c, d, x[k + 12], S41, 0x655B59C3);
+		d = II(d, a, b, c, x[k + 3], S42, 0x8F0CCC92);
+		c = II(c, d, a, b, x[k + 10], S43, 0xFFEFF47D);
+		b = II(b, c, d, a, x[k + 1], S44, 0x85845DD1);
+		a = II(a, b, c, d, x[k + 8], S41, 0x6FA87E4F);
+		d = II(d, a, b, c, x[k + 15], S42, 0xFE2CE6E0);
+		c = II(c, d, a, b, x[k + 6], S43, 0xA3014314);
+		b = II(b, c, d, a, x[k + 13], S44, 0x4E0811A1);
+		a = II(a, b, c, d, x[k + 4], S41, 0xF7537E82);
+		d = II(d, a, b, c, x[k + 11], S42, 0xBD3AF235);
+		c = II(c, d, a, b, x[k + 2], S43, 0x2AD7D2BB);
+		b = II(b, c, d, a, x[k + 9], S44, 0xEB86D391);
+		a = addUnsigned(a, AA);
+		b = addUnsigned(b, BB);
+		c = addUnsigned(c, CC);
+		d = addUnsigned(d, DD);
+	}
+	let tempValue = wordToHex(a) + wordToHex(b) + wordToHex(c) + wordToHex(d);
+	return tempValue.toLowerCase();
+};
+let base64EncodeChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
+let base64DecodeChars = new Array(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1);
+/**
+ * base64编码
+ * @param {Object} str
+ */
+function base64encode (str) {
+	let out, i, len;
+	let c1, c2, c3;
+	len = str.length;
+	i = 0;
+	out = '';
+	while (i < len) {
+		c1 = str.charCodeAt(i++) & 0xff;
+		if (i === len) {
+			out += base64EncodeChars.charAt(c1 >> 2);
+			out += base64EncodeChars.charAt((c1 & 0x3) << 4);
+			out += '==';
+			break;
+		}
+		c2 = str.charCodeAt(i++);
+		if (i === len) {
+			out += base64EncodeChars.charAt(c1 >> 2);
+			out += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
+			out += base64EncodeChars.charAt((c2 & 0xF) << 2);
+			out += '=';
+			break;
+		}
+		c3 = str.charCodeAt(i++);
+		out += base64EncodeChars.charAt(c1 >> 2);
+		out += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
+		out += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6));
+		out += base64EncodeChars.charAt(c3 & 0x3F);
+	}
+	return out;
+}
+/**
+ * base64解码
+ * @param {Object} str
+ */
+function base64decode (str) {
+	let c1, c2, c3, c4;
+	let i, len, out;
+	len = str.length;
+	i = 0;
+	out = '';
+	while (i < len) {
+		/* c1 */
+		do {
+			c1 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
+		}
+		while (i < len && c1 === -1);
+		if (c1 === -1) { break; }
+		/* c2 */
+		do {
+			c2 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
+		}
+		while (i < len && c2 === -1);
+		if (c2 === -1) { break; }
+		out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4));
+		/* c3 */
+		do {
+			c3 = str.charCodeAt(i++) & 0xff;
+			if (c3 === 61) { return out; }
+			c3 = base64DecodeChars[c3];
+		}
+		while (i < len && c3 === -1);
+		if (c3 === -1) { break; }
+		out += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2));
+		/* c4 */
+		do {
+			c4 = str.charCodeAt(i++) & 0xff;
+			if (c4 === 61) { return out; }
+			c4 = base64DecodeChars[c4];
+		}
+		while (i < len && c4 === -1);
+		if (c4 === -1) { break; }
+		out += String.fromCharCode(((c3 & 0x03) << 6) | c4);
+	}
+	return out;
+}
+
+export default CryptoJS;

+ 56 - 0
src/api/http.js

@@ -0,0 +1,56 @@
+"use strict";
+import axios from "axios";
+import { Toast } from 'vant';
+import CryptoJS from './crypto'
+
+let config = {
+  baseURL: import.meta.env.VITE_APP_BASEAPIURL,
+  timeout: 60 * 1000, // Timeout
+};
+
+const _axios = axios.create(config);
+
+_axios.interceptors.request.use(
+  function (config) {
+    return config;
+  },
+  function (error) {
+    // Do something with request error
+    return Promise.reject(error);
+  }
+);
+
+// Add a response interceptor
+_axios.interceptors.response.use(
+  function (response) {
+      const data=JSON.parse(CryptoJS.Des3Decrypt(response.data));//解密
+      // const data = response.data;
+
+    if(data.Ret === 403) {
+      Toast(data.Msg)
+    }
+    return data;
+  },
+  function (error) {
+    // Do something with response error
+    return Promise.reject(error);
+  }
+);
+
+/**
+ * 导出get请求方法
+ * @url 请求地址
+ * @params get请求参数
+ */
+export const get = (url, params) => {
+  return _axios.get(url, { params })
+};
+
+/**
+ * 导出post请求方法
+ * @url 请求地址
+ * @params post请求参数
+ */
+export const post = (url,params) => {
+  return _axios.post(url, params)
+};

BIN
src/assets/img/accessbg.png


BIN
src/assets/img/account.png


BIN
src/assets/img/addup.png


BIN
src/assets/img/arrow_left.png


BIN
src/assets/img/company.png


BIN
src/assets/img/down.png


BIN
src/assets/img/downicon.png


BIN
src/assets/img/downsort.png


BIN
src/assets/img/jiandown.png


BIN
src/assets/img/kongbtnbg.png


BIN
src/assets/img/listplay.png


BIN
src/assets/img/liststop.png


BIN
src/assets/img/loading.gif


BIN
src/assets/img/loginbtn.png


BIN
src/assets/img/loginfooter.png


BIN
src/assets/img/logo.png


BIN
src/assets/img/moreimg.png


BIN
src/assets/img/name.png


BIN
src/assets/img/newbtn.png


BIN
src/assets/img/newbtn600.png


BIN
src/assets/img/newclosesmall.png


BIN
src/assets/img/newshouqi.png


BIN
src/assets/img/newstopimg.png


BIN
src/assets/img/newwhitepause.png


BIN
src/assets/img/newwhitepausesmall.png


BIN
src/assets/img/newwhiteplay.png


BIN
src/assets/img/newwhiteplaysmall.png


BIN
src/assets/img/next.png


BIN
src/assets/img/noaccessbtn.png


BIN
src/assets/img/nonedata.png


BIN
src/assets/img/nosort.png


BIN
src/assets/img/pauseImg.png


BIN
src/assets/img/play.png


BIN
src/assets/img/playImg.png


BIN
src/assets/img/pre.png


BIN
src/assets/img/returnhome.png


BIN
src/assets/img/returntop.png


BIN
src/assets/img/righticon.png


BIN
src/assets/img/shouqi.png


BIN
src/assets/img/stopimg.png


BIN
src/assets/img/tele.png


BIN
src/assets/img/turndown.png


BIN
src/assets/img/turnup.png


BIN
src/assets/img/upicon.png


BIN
src/assets/img/upselect.png


BIN
src/assets/img/upsort.png


BIN
src/assets/img/videocover.png


BIN
src/assets/img/whitepause.png


BIN
src/assets/img/whiteplay.png


+ 125 - 0
src/components/progress-bar.vue

@@ -0,0 +1,125 @@
+<template>
+  <div class="progress-bar" ref="progressBar" @click="progressClick">
+    <div class="bar-inner">
+      <div class="progress" ref="progress"></div>
+      <div class="progress-btn-wrapper" ref="progressBtn" @touchstart.prevent="progressTouchStart" @touchmove.prevent="progressTouchMove" @touchend="progressTouchEnd">
+        <div class="progress-btn" ref="progressBtn"></div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  props: {
+    percent: {
+      type: Number,
+      default: 0
+    }
+  },
+  data() {
+    return {
+      progressBtnWidth: ""
+    };
+  },
+  created() {
+    this.touch = {};
+  },
+  methods: {
+    progressTouchStart(e) {
+      this.touch.initiated = true; // 记录已点击
+      this.touch.startX = e.touches[0].pageX; // 记录横向坐标
+      this.touch.left = this.$refs.progress.clientWidth; // 记录进度条长度
+    },
+    progressTouchMove(e) {
+      if (!this.touch.initiated) {
+        return;
+      }
+      const deltaX = e.touches[0].pageX - this.touch.startX; // 当前横向坐标-初始点击横向坐标
+      const offsetWidth = Math.min(
+        this.$refs.progressBar.clientWidth - this.progressBtnWidth,
+        Math.max(0, this.touch.left + deltaX)
+      );
+      this._offset(offsetWidth);
+    },
+    progressTouchEnd() {
+      this.touch.initiated = false;
+      this._triggerPercent();
+    },
+    /* 点击整个进度条时 */
+    progressClick(e) {
+      const rect = this.$refs.progressBar.getBoundingClientRect();
+      const offsetWidth = e.pageX - rect.left;
+      this._offset(offsetWidth);
+      // 这里当我们点击 progressBtn 的时候,e.offsetX 获取不对
+      // this._offset(e.offsetX)
+      this._triggerPercent();
+    },
+    _triggerPercent() {
+      const barWidth =
+        this.$refs.progressBar.clientWidth - this.progressBtnWidth;
+      const percent = this.$refs.progress.clientWidth / barWidth;
+      this.$emit("percentChange", percent);
+    },
+    /* 得知播放过的百分比时操作ui变化 */
+    _offset(offsetWidth) {
+      this.$refs.progress.style.width = `${offsetWidth}px`;
+      this.$refs.progressBtn.style.transform = `translate3d(${offsetWidth}px,0,0)`;
+    }
+  },
+  watch: {
+    percent(newPercent) {
+      if (newPercent >= 0 && !this.touch.initiated) {
+        // 拖动时不能自动跳动
+        this.progressBtnWidth = this.$refs.progressBtn.clientWidth / 2; // 按钮宽度
+        const barWidth =
+          this.$refs.progressBar.clientWidth - this.progressBtnWidth; // 总宽-按钮宽度
+        const offsetWidth = newPercent * barWidth;
+        this._offset(offsetWidth);
+      }
+    }
+  }
+};
+</script>
+
+<style scoped lang="scss">
+@import "@/style/mixin.scss";
+.progress-bar {
+  // width: rem(200);
+  width: 100%;
+  height: rem(30);
+}
+/* 进度线 */
+.bar-inner {
+  position: relative;
+  top: rem(13);
+  height: rem(4);
+  background: rgba(0, 0, 0, 0.3);
+}
+
+.progress {
+  position: absolute;
+  height: 100%;
+  background: rgb(255, 205, 50);
+}
+
+.progress-btn-wrapper {
+  position: absolute;
+  left: rem(-8);
+  top: rem(-13);
+  width: rem(30);
+  height: rem(30);
+}
+
+.progress-btn {
+  position: relative;
+  top: rem(7);
+  left: rem(7);
+  box-sizing: border-box;
+  width: rem(16);
+  height: rem(16);
+  border: rem(3) solid #fff;
+  border-radius: 50%;
+  background: rgb(255, 205, 50);
+}
+</style>

+ 14 - 0
src/main.js

@@ -0,0 +1,14 @@
+import { createApp } from 'vue'
+import App from './App.vue'
+import router from './router'
+import store from './store'
+import 'normalize.css'
+import './style/common.scss'
+import '@vant/touch-emulator';//vant 
+import 'vant/lib/index.css';
+import '@/utils/rem.js';
+
+const app=createApp(App)
+app.use(router).use(store).mount('#app')
+
+app.$store = store;

+ 36 - 0
src/router/index.js

@@ -0,0 +1,36 @@
+
+import { createRouter, createWebHistory } from 'vue-router'
+
+const routes=[
+  {
+    path: '/',
+    redirect: '/reportdtl'
+  },
+  {
+    path: "/reportdtl",
+    name: "reportDetail",
+    component: () => import("@/views/report/reportDetail.vue"),
+  },
+  {
+    path: "/reportEn",
+    name: "reportEn",
+    component: () => import("@/views/reportEn/detail.vue"),
+  },
+  //404
+  {
+      path: "/:pathMatch(.*)",
+      name:"404",
+      component: () => import("@/views/Error.vue"),
+  },
+]
+
+const router = createRouter({
+  history: createWebHistory(import.meta.env.VITE_APP_BASE_URL),
+  routes,
+});
+
+router.beforeEach((to, from, next) => {
+  next();
+});
+
+export default router;

+ 39 - 0
src/store/index.js

@@ -0,0 +1,39 @@
+import { createStore } from "vuex";
+
+const store = createStore({
+  state:{
+    playcount:99999,  //当前播放index
+    isplaying:false,  //播放状态
+    audiolist:[],   //播放文件
+    isshowplay:false,  //是否显示全局底部导航
+  },
+  mutations:{
+    setplaycount(state,i){  //设置当前播放的index
+      state.playcount=i;
+    },
+    setplaystate(state,s){  //设置播放状态
+      state.isplaying=s;
+    },
+    setaudiolist(state,audioarr){  //存储播放队列
+      if( audioarr ){
+        state.audiolist=audioarr;
+      }else{
+        state.audiolist=[];
+      }
+    },
+    setshowplay(state,s){  //设置播放弹窗的显示隐藏
+      state.isshowplay=s;
+    },
+  },
+  actions: {
+    // 统计音频pv
+    audioPv({commit},id) {
+      getPV({
+        ReportId:id
+      }).then(res => {
+      })
+    }
+  }
+});
+
+export default store;

+ 25 - 0
src/style/common.scss

@@ -0,0 +1,25 @@
+#app{
+    font-size: 28px;
+}
+* { margin: 0px; padding:0}
+div{
+    box-sizing: border-box;
+}
+body{
+    line-height: 1.6;
+    font-family: -apple-system-font, "Helvetica Neue", sans-serif;
+}
+p,span {
+    margin: 0;
+    padding: 0;
+}
+a {
+    text-decoration: none;
+}
+input{
+    -webkit-appearance: none;
+}
+
+li {
+    list-style: none;
+}

+ 6 - 0
src/style/mixin.scss

@@ -0,0 +1,6 @@
+// rem 基准
+$screen-width: 37.5;
+
+@function rem($px) {
+  	@return $px / $screen-width * 1rem;
+}

+ 114 - 0
src/utils/rem.js

@@ -0,0 +1,114 @@
+(function(win,lib){
+  var doc = win.document;
+  var docEl = doc.documentElement;
+  var metaEl = doc.querySelector('meta[name="viewport"]');
+  var flexibleEl = doc.querySelector('meta[name="flexible"]');
+  var dpr = 0;
+  var scale = 0;
+  var tid;
+  var flexible = lib.flexible || (lib.flexible = {});
+  //判断html页面上的meta标签值
+  if (metaEl) {  //  	将根据已有的meta标签来设置缩放比例
+      var match = metaEl.getAttribute('content').match(/initial\-scale=([\d\.]+)/);
+      if (match) {
+          scale = parseFloat(match[1]);
+          dpr = parseInt(1 / scale);
+      }
+  } else if (flexibleEl) {
+      var content = flexibleEl.getAttribute('content');
+      if (content) {
+          var initialDpr = content.match(/initial\-dpr=([\d\.]+)/);
+          var maximumDpr = content.match(/maximum\-dpr=([\d\.]+)/);
+          if (initialDpr) {
+              dpr = parseFloat(initialDpr[1]);
+              scale = parseFloat((1 / dpr).toFixed(2));
+          }
+          if (maximumDpr) {
+              dpr = parseFloat(maximumDpr[1]);
+              scale = parseFloat((1 / dpr).toFixed(2));
+          }
+      }
+  }
+  //如果页面未设置meta,使得dpr=0;scale=0.那么进入判断,设置dpr
+  if (!dpr && !scale) {
+      var isAndroid = win.navigator.appVersion.match(/android/gi);
+      var isIPhone = win.navigator.appVersion.match(/iphone/gi);
+      var devicePixelRatio = win.devicePixelRatio;
+      if (isIPhone) {  // iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案
+          if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {
+              dpr = 3;
+          } else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){
+              dpr = 2;
+          } else {
+              dpr = 1;
+          }
+      } else {
+          dpr = 1;  // 其他设备下,仍旧使用1倍的方案
+      }
+      scale = 1 / dpr;
+  }
+  docEl.setAttribute('data-dpr', dpr);
+  if (!metaEl) {  //不处女座meta,就生成meta
+      metaEl = doc.createElement('meta');
+      metaEl.setAttribute('name', 'viewport');
+      metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
+      if (docEl.firstElementChild) {
+          docEl.firstElementChild.appendChild(metaEl);
+      } else {
+          var wrap = doc.createElement('div');
+          wrap.appendChild(metaEl);
+          doc.write(wrap.innerHTML);
+      }
+  }
+  function refreshRem(){
+      var width = docEl.getBoundingClientRect().width;  //getBoundingClientRect().width获取整个页面的物理像素宽度
+      if(width<450){
+          var rem = width / 750*50;   //修改为font-size为50px 这样px->>rem即为100倍关系,方便计算
+          docEl.style.fontSize = rem + 'px';
+          flexible.rem = win.rem = rem;
+      }else if( width>=450&&width<1024 ){
+          var rem = 36;   //修改为font-size为50px 这样px->>rem即为100倍关系,方便计算
+          docEl.style.fontSize = rem + 'px';
+          flexible.rem = win.rem = rem;
+      }else if( width>=1024 ){
+          var rem = 24;   //修改为font-size为50px 这样px->>rem即为100倍关系,方便计算
+          docEl.style.fontSize = rem + 'px';
+          flexible.rem = win.rem = rem;
+      }
+  }
+  win.addEventListener('resize', function() {
+      clearTimeout(tid);
+      tid = setTimeout(refreshRem, 300);
+  }, false);
+  win.addEventListener('pageshow', function(e) {
+      if (e.persisted) {
+          clearTimeout(tid);
+          tid = setTimeout(refreshRem, 300);
+      }
+  }, false);
+  if (doc.readyState === 'complete') {
+      doc.body.style.fontSize = 12 * dpr + 'px';
+  } else {
+      doc.addEventListener('DOMContentLoaded', function(e) {
+          doc.body.style.fontSize = 12 * dpr + 'px';
+      }, false);
+  }
+  refreshRem();
+  flexible.dpr = win.dpr = dpr;
+  flexible.refreshRem = refreshRem;
+  //下面两个函数是px/rem自动换算用的。当用sass或是less的时候会用到。
+  flexible.rem2px = function(d) {
+      var val = parseFloat(d) * this.rem;
+      if (typeof d === 'string' && d.match(/rem$/)) {
+          val += 'px';
+      }
+      return val;
+  }
+  flexible.px2rem = function(d) {
+      var val = parseFloat(d) / this.rem;
+      if (typeof d === 'string' && d.match(/px$/)) {
+          val += 'rem';
+      }
+      return val;
+  }
+})(window, window['lib'] || (window['lib'] = {}));

+ 21 - 0
src/views/Error.vue

@@ -0,0 +1,21 @@
+<template>
+    <div class="no-found-page">
+        <img src="@/assets/404.png" alt="">
+        <p>页面飞走了</p>
+    </div>
+</template>
+
+<style lang="scss" scoped>
+.no-found-page{
+    img{
+        width: 80%;
+        display: block;
+        margin: 150px auto 20px auto;
+    }
+    p{
+        text-align: center;
+        font-size: 32px;
+        color: #666;
+    }
+}
+</style>

+ 557 - 0
src/views/report/audioPlay.vue

@@ -0,0 +1,557 @@
+<template>
+  <div id="report-index">
+    <audio
+      ref="audioTag"
+      preload="auto"
+      @timeupdate="timeUpdated"
+      id="audioplay0"
+      v-if="$store.state.audiolist.length > 0 && isshowaudio"
+    >
+      <source
+        :src="$store.state.audiolist[$store.state.playcount].video_url"
+        type="audio/mpeg"
+      />
+      Your browser does not support the audio element.
+    </audio>
+    <div
+      v-if="
+        $store.state.audiolist.length > 0 &&
+        $store.state.isshowplay &&
+        playwinsize == 'small'
+      "
+      id="playwin"
+    >
+      <p @click="setwinbig">
+        {{ $store.state.audiolist[$store.state.playcount].video_name }}
+      </p>
+      <img
+        @click.stop="playaudiopause"
+        v-if="$store.state.isplaying"
+        src="~@/assets/img/newwhiteplaysmall.png"
+        class="playpauseimg"
+      />
+      <img
+        @click.stop="playaudioplay"
+        v-else
+        src="~@/assets/img/newwhitepausesmall.png"
+        class="playpauseimg"
+      />
+      <img
+        @click.stop="closeplaywin(0)"
+        src="~@/assets/img/newclosesmall.png"
+        style="height: 0.86rem; padding: 0.2rem; float: right"
+      />
+    </div>
+    <div
+      v-if="
+        $store.state.audiolist.length > 0 &&
+        $store.state.isshowplay &&
+        playwinsize == 'big'
+      "
+      id="playwinbig"
+    >
+      <img
+        @click="playwinsize = 'small'"
+        src="~@/assets/img/newshouqi.png"
+        class="shouqi"
+      />
+      <img
+        @click.stop="closeplaywin(0)"
+        src="~@/assets/img/newstopimg.png"
+        class="closewin"
+      />
+      <p
+        style="
+          width: 100%;
+          line-height: 1.2rem;
+          font-size: 0.6rem;
+          white-space: nowrap;
+          overflow: hidden;
+          text-overflow: ellipsis;
+          text-align: center;
+        "
+      >
+        {{ $store.state.audiolist[$store.state.playcount].video_name }}
+      </p>
+      <div
+        style="
+          display: flex;
+          align-items: center;
+          justify-content: center;
+          font-size: 0.5rem;
+          text-align: center;
+          margin: 0.4rem auto 0.3rem;
+          overflow: hidden;
+        "
+      >
+        <div class="inline-block" style="margin-right: 0.4rem">
+          {{ timeCurrent }}
+        </div>
+        <progressBar
+          :percent="percent"
+          @percentChange="percentChange"
+          style="display: inline-block; width: 65%; overflow: hidden"
+        ></progressBar>
+        <div id="audioTime" class="inline-block" style="margin-left: 0.4rem">
+          {{
+            transTime(
+              $store.state.audiolist[$store.state.playcount].video_play_seconds
+            )
+          }}
+        </div>
+      </div>
+      <div style="text-align: center; overflow: hidden">
+        <img
+          @click.stop="pretplay"
+          v-if="$store.state.audiolist.length > 1"
+          src="~@/assets/img/pre.png"
+          class="playpauseimg"
+        />
+        <img
+          @click.stop="playaudiopause"
+          v-if="$store.state.isplaying"
+          src="~@/assets/img/newwhiteplay.png"
+          class="playpauseimg"
+        />
+        <img
+          @click.stop="playaudioplay"
+          v-else
+          src="~@/assets/img/newwhitepause.png"
+          class="playpauseimg"
+        />
+        <img
+          @click.stop="nextplay"
+          v-if="$store.state.audiolist.length > 1"
+          src="~@/assets/img/next.png"
+          class="playpauseimg"
+        />
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import progressBar from "@/components/progress-bar.vue";
+export default {
+  components: { progressBar },
+  computed: {
+    percent() {
+      return (
+        this.currentTime /
+        this.$store.state.audiolist[this.$store.state.playcount]
+          .video_play_seconds
+      );
+    },
+  },
+  data() {
+    return {
+      isshowaudio: true, //是否加载音频audio
+      playwinsize: "small", //音频窗口大小
+      timeCurrent: "00:00", //总时长
+      currentTime: null, //当前播放时长
+      touching: false, //是否触碰进度条中
+    };
+  },
+  mounted() {
+    console.log(this.$store.state);
+  },
+  methods: {
+    percentChange(precent) {
+      const currentTime =
+        this.$store.state.audiolist[this.$store.state.playcount]
+          .video_play_seconds * precent;
+      this.$refs.audioTag.currentTime = currentTime;
+    },
+    setwinbig() {
+      //打开大窗口播放音频
+      this.playwinsize = "big";
+      // this.timeUpdated();
+    },
+    setisshowaudio(audioarr, i) {
+      //父级注入的更新播放音频的方法
+      console.log(audioarr, i);
+      let that = this;
+      that.$store.commit("setaudiolist", audioarr);
+      that.audioplay(i);
+    },
+    audioplay(i) {
+      //音频播放
+      let that = this;
+      that.$store.commit("setplaycount", i);
+      that.audiopause();
+      that.isshowaudio = false;
+      setTimeout(function () {
+        that.isshowaudio = true;
+        that.$nextTick(function () {
+          $("#audioplay0")[0].play();
+          that.$store.commit("setplaystate", true);
+          that.$store.commit("setshowplay", true);
+          $("#audioplay0")[0].addEventListener(
+            "ended",
+            function () {
+              that.$store.commit("setshowplay", false);
+              that.$store.commit("setplaystate", false);
+              that.timeCurrent = "00:00";
+              if (that.$store.state.audiolist.length == 1) {
+                // that.$store.commit('setaudiolist',null);
+                return false;
+              }
+              if (i + 1 < that.$store.state.audiolist.length) {
+                that.audioplay(i + 1);
+              } else {
+                that.audioplay(0);
+              }
+            },
+            false
+          );
+        });
+      }, 100);
+    },
+    audiopause(i) {
+      //音频暂停
+      if (this.$store.state.isplaying) {
+        $("#audioplay0")[0].removeEventListener("ended", function () {}, false);
+        $("#audioplay0")[0].pause();
+        this.$store.commit("setplaystate", false);
+      }
+    },
+    closeplaywin(i) {
+      //关闭音频播放窗口
+      this.audiopause();
+      this.$store.commit("setshowplay", false);
+      this.timeCurrent = "00:00";
+    },
+    nextplay() {
+      //下一首
+      let cindex = this.$store.state.playcount;
+      if (cindex + 1 < this.$store.state.audiolist.length) {
+        this.audioplay(cindex + 1);
+      } else {
+        this.audioplay(0);
+      }
+    },
+    pretplay() {
+      //上一首
+      if (this.$store.state.playcount == 0) {
+        this.audioplay(this.$store.state.audiolist.length - 1);
+      } else {
+        this.audioplay(this.$store.state.playcount - 1);
+      }
+    },
+    playaudiopause() {
+      //当前暂停
+      $("#audioplay0")[0].pause();
+      this.$store.commit("setplaystate", false);
+    },
+    playaudioplay() {
+      //当前播放
+      $("#audioplay0")[0].play();
+      this.$store.commit("setplaystate", true);
+      this.$store.commit("setshowplay", true);
+    },
+    transTime(time) {
+      //转换音频时长显示
+      let duration = parseInt(time);
+      let minute = parseInt(duration / 60);
+      let sec = (duration % 60) + "";
+      let isM0 = ":";
+      if (minute == 0) {
+        minute = "00";
+      } else if (minute < 10) {
+        minute = "0" + minute;
+      }
+      if (sec.length == 1) {
+        sec = "0" + sec;
+      }
+      return minute + isM0 + sec;
+    },
+    timeUpdated(e) {
+      //更新播放进度
+      this.currentTime = e.target.currentTime;
+      this.timeCurrent = this.transTime(this.$refs.audioTag.currentTime);
+      return false;
+      if (this.playwinsize == "small") {
+        return false;
+      }
+      let that = this;
+      let audio = that.$refs.audioTag;
+      that.$nextTick(function () {
+        let timeline = that.$refs.timeline;
+        let playhead = that.$refs.playhead;
+        let timelineWidth = timeline.offsetWidth - playhead.offsetWidth;
+        let playPercent = timelineWidth * (audio.currentTime / audio.duration);
+        playhead.style.webkitTransform = "translateX(" + playPercent + "px)";
+        playhead.style.transform = "translateX(" + playPercent + "px)";
+        let timeCurrent = that.transTime(audio.currentTime);
+        that.timeCurrent = timeCurrent;
+        that.currentTime = audio.currentTime;
+      });
+    },
+    timelineClick(e) {
+      //进度条操作,拖拽和点击都需要调用
+      let audio = $("#audioplay0")[0];
+      let timeline = this.$refs.timeline;
+      let playhead = this.$refs.playhead;
+      let timelineWidth = timeline.offsetWidth - playhead.offsetWidth;
+      // 更新坐标位置,e.pageX 鼠标点击位置,offsetLeft  元素 相对于它的直接父元素 的 偏移量timeline.offsetParent.offsetLeft/2
+      let newLeft;
+      if (this.IsPC()) {
+        newLeft = e.offsetX - 10;
+      } else {
+        newLeft = e.pageX - (screen.width - timeline.offsetWidth) / 2 - 10;
+      }
+      let currentTime = (audio.duration * newLeft) / timelineWidth;
+      if (newLeft >= 0 && newLeft <= timelineWidth) {
+        playhead.style.transform = "translateX(" + newLeft + "px)";
+      }
+      if (newLeft < 0) {
+        playhead.style.transform = "translateX(0)";
+        currentTime = 0;
+      }
+      if (newLeft > timelineWidth) {
+        playhead.style.transform = "translateX(" + timelineWidth + "px)";
+        currentTime = audio.duration;
+      }
+      let timeCurrent = this.transTime(currentTime); // 更新时间
+      this.timeCurrent = timeCurrent;
+      this.currentTime = currentTime;
+      audio.currentTime = currentTime;
+    },
+    touchStart(e) {
+      // 进度条点击
+      this.touching = true;
+      let events = e.touches[0] || e;
+      this.timelineClick(events);
+    },
+    touchMove(e) {
+      if (this.touching !== true) {
+        return false;
+      }
+      let events = e.touches[0] || e;
+      this.timelineClick(events);
+    },
+    touchEnd(e) {
+      this.touching = false;
+    },
+    IsPC() {
+      var userAgentInfo = navigator.userAgent;
+      var Agents = [
+        "Android",
+        "iPhone",
+        "SymbianOS",
+        "Windows Phone",
+        "iPad",
+        "iPod",
+      ];
+      var flag = true;
+      for (var v = 0; v < Agents.length; v++) {
+        if (userAgentInfo.indexOf(Agents[v]) > 0) {
+          flag = false;
+          break;
+        }
+      }
+      return flag;
+    },
+  },
+};
+</script>
+
+<style lang="scss">
+#report-index {
+  background: #f7f7f7;
+  max-width: 1200px;
+  margin: 0 auto;
+  overflow: auto;
+  .router-fade-enter-active,
+  .router-fade-leave-active {
+    transition: opacity 0.3s;
+  }
+  .router-fade-enter,
+  .router-fade-leave-active {
+    opacity: 0;
+  }
+  #playwin {
+    width: 13.8rem;
+    padding: 0.4rem 0.5rem;
+    line-height: 0.86rem;
+    box-sizing: border-box;
+    background: rgba(76, 122, 253, 0.9);
+    border-radius: 0.1rem;
+    color: #fff;
+    position: fixed;
+    left: 50%;
+    margin-left: -6.9rem;
+    bottom: 0.4rem;
+    z-index: 9999;
+    overflow: hidden;
+    p {
+      float: left;
+      width: 10rem;
+      height: 1.26rem;
+      font-size: 0.6rem;
+      line-height: 1.26rem;
+      white-space: nowrap;
+      overflow: hidden;
+      text-overflow: ellipsis;
+    }
+    .playpauseimg {
+      height: 0.86rem;
+      padding: 0.2rem;
+      float: left;
+    }
+  }
+  #playwinbig {
+    width: 13.8rem;
+    height: 7rem;
+    padding: 1.4rem 0.4rem 0.4rem;
+    line-height: 1.2rem;
+    box-sizing: border-box;
+    background: rgba(76, 122, 253, 0.9);
+    border-radius: 0.2rem;
+    color: #fff;
+    position: fixed;
+    left: 50%;
+    margin-left: -6.9rem;
+    bottom: 0.4rem;
+    z-index: 9999;
+    overflow: hidden;
+    moz-user-select: -moz-none;
+    -moz-user-select: none;
+    -o-user-select: none;
+    -khtml-user-select: none;
+    -webkit-user-select: none;
+    -ms-user-select: none;
+    user-select: none;
+    .shouqi {
+      height: 0.5rem;
+      padding: 0.5rem;
+      position: absolute;
+      left: 0;
+      top: 0.1rem;
+    }
+    .closewin {
+      height: 0.6rem;
+      padding: 0.5rem;
+      position: absolute;
+      right: 0;
+      top: 0;
+    }
+    .playpauseimg {
+      display: inline-block;
+      width: 1.1rem;
+      height: 1.1rem;
+      padding: 0.4rem;
+      margin: 0rem 0.5rem;
+    }
+    .timeline {
+      width: 60%;
+      height: 20px;
+      position: relative;
+      bottom: -6px;
+      overflow: hidden;
+      .linesty {
+        width: 100%;
+        height: 2px;
+        background: #d8d8d8;
+        position: absolute;
+        left: 0;
+        top: 8px;
+      }
+      .playhead {
+        background: #fff;
+        width: 20px;
+        height: 20px;
+        border-radius: 100%;
+        position: absolute;
+        top: 0px;
+        z-index: 999;
+      }
+    }
+  }
+  .inline-block {
+    display: inline-block;
+  }
+  .commentsty {
+    position: relative;
+    padding: 0 0 0.6rem 1rem;
+    box-sizing: border-box;
+    color: #000;
+    font-size: 0.72rem;
+    font-weight: 500;
+    line-height: 0.76rem;
+  }
+  .commentsty:before {
+    position: absolute;
+    top: 0rem;
+    left: 0.6rem;
+    content: " ";
+    width: 0.2rem;
+    height: 0.72rem;
+    background: #1479fd;
+  }
+  p[data-f-id="pbf"] {
+    display: none;
+  }
+  iframe {
+    border: none;
+  }
+  .weui-toast__content {
+    padding: 10px;
+    box-sizing: border-box;
+  }
+  #resetcss {
+    font-size: 0.72rem !important;
+    color: #333;
+    letter-spacing: 0.05rem;
+  }
+  ::-webkit-scrollbar {
+    width: 0;
+    height: 1px;
+  }
+  ::-webkit-scrollbar-thumb {
+    border-radius: 5px;
+    -webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
+    background: rgba(0, 0, 0, 0.2);
+  }
+
+  /* reset vant */
+  .van-tab--active {
+    font-weight: 600;
+    font-size: 0.6rem !important;
+  }
+  .videoList_Container .van-tabs__line {
+    width: 0.8rem !important;
+    border-radius: 4px;
+  }
+  .videoList_Container .van-tabs {
+    padding-right: 2rem;
+    border-bottom: 0.04rem solid #e8e8e8;
+  }
+  .videoList_Container .van-hairline--top-bottom::after,
+  .van-hairline-unset--top-bottom::after {
+    border-width: 0;
+  }
+  // .videoList_Container .van-search__content {
+  //   border: 0.5px solid #707070;
+  // }
+  .videoList_Container .van-picker .van-picker__cancel,
+  .videoList_Container .van-picker .van-picker__confirm {
+    color: #108ee9;
+    font-size: 0.68rem;
+  }
+  .videoList_Container .van-picker .van-picker-column__item--selected {
+    font-size: 0.68rem;
+    border-top: solid 0.04rem #ddd;
+    border-bottom: solid 0.04rem #ddd;
+  }
+  .videoList_Container .vjs-custom-skin > .video-js .vjs-big-play-button {
+    width: 1.88rem !important;
+    height: 1.88rem !important;
+    border-radius: 50%;
+    font-size: 3em;
+    line-height: 1.88rem !important;
+    transform: translate(-50%, -50%);
+    margin: 0 !important;
+  }
+}
+</style>

+ 446 - 0
src/views/report/reportDetail.vue

@@ -0,0 +1,446 @@
+<!-- 原项目丢了 省事直接cv一下老项目代码 -->
+<template>
+  <div class="wrapper" ref="wrapper">
+    <div id="reportdtl" v-if="isshow">
+      <header>
+        <p>
+          <span style="margin-left: -0.45rem"
+            >【第{{ reportInfo.Stage }}期|FICC】{{
+              reportInfo.Title
+            }}</span
+          >
+          <span v-if="reportInfo.CreateTime"
+            >({{ reportInfo.CreateTime.substring(5, 7)
+            }}{{ reportInfo.CreateTime.substring(8, 10) }})</span
+          >
+        </p>
+      </header>
+      <div
+        style="
+          padding: 0rem 0.8rem 0.4rem;
+          box-sizing: border-box;
+          color: #666;
+          font-size: 0.66rem;
+          overflow: hidden;
+        "
+      >
+        <span>{{ reportInfo.Author }}</span>
+        <span style="float: right">{{ reportInfo.PublishTime }}</span>
+      </div>
+
+      <div id="playcon" v-if="reportInfo.VideoUrl">
+        <div>
+          <img
+            @click.stop="$refs.audioRef.playaudiopause()"
+            v-if="
+              $store.state.isplaying &&
+              reportInfo.VideoUrl ==
+                $store.state.audiolist[$store.state.playcount].video_url
+            "
+            src="~@/assets/img/playImg.png"
+            style="width: 2rem; height: 2rem; float: left; margin-right: 0.4rem"
+          />
+          <img
+            @click.stop="playaudio(reportInfo)"
+            v-else
+            src="~@/assets/img/pauseImg.png"
+            style="width: 2rem; height: 2rem; float: left; margin-right: 0.4rem"
+          />
+          <p
+            style="
+              font-size: 0.64rem;
+              line-height: 1rem;
+              color: #333;
+              white-space: nowrap;
+              overflow: hidden;
+              text-overflow: ellipsis;
+            "
+          >
+            {{ reportInfo.VideoName }}
+          </p>
+          <p style="font-size: 0.56rem; line-height: 1rem; color: #878787">
+            {{ parseInt(reportInfo.VideoPlaySeconds / 60) }}分{{
+              parseInt(reportInfo.VideoPlaySeconds % 60)
+            }}秒
+          </p>
+        </div>
+      </div>
+
+      <div id="abstract">
+        <div class="abstract_cont">
+          <div>摘要:{{ reportInfo.Abstract }}</div>
+          <div style="color: #666; margintop: 1.2rem">
+            *注:请务必阅读&nbsp;<strong
+              style="fontweight: normal; cursor: pointer; color: #3e8ce6"
+              @click="showTips"
+              >免责声明</strong
+            >
+          </div>
+        </div>
+      </div>
+      <div style="padding: 0.6rem; box-sizing: border-box; overflow: hidden">
+        <!-- <div id="resetcss" style="overflow:hidden;" v-html="reportInfo.Content"></div> -->
+        <div id="resetcss" style="overflow:hidden;">
+        <ul>
+          <li v-for="(html,index) in realContent" :key="index" v-html="html"></li>
+        </ul>
+      </div>
+      <div id="tipsAlert">
+        <div
+          style="
+            width: 100%;
+            padding: 0.8rem 0.66rem 2.2rem;
+            box-sizing: border-box;
+            font: 0.52rem/0.8rem 'PingFang-SC-Regular';
+            color: #666;
+            background: #fff;
+            overflow: scroll;
+            position: relative;
+            border-radius: 0.2rem;
+          "
+        >
+          <!-- <h1 style="font:0.64rem '微软雅黑'; color:#333; text-align:center; margin-bottom:0.34rem;">免责声明</h1> -->
+          <h1
+            style="
+              font: 0.64rem 'PingFang-SC-Regular';
+              color: #333;
+              text-align: center;
+              margin-bottom: 0.34rem;
+            "
+          >
+            免责声明
+          </h1>
+          <p>
+            1、本报告仅供弘则弥道(上海)投资咨询有限公司正式签约的机构客户使用,不会仅因接收人/接受机构收到本报告而将其视为客户。
+          </p>
+          <p>
+            2、本报告根据国际和行业通行的准则,以合法渠道获得这些信息,尽可能保证可靠、准确和完整,但并不保证报告所述信息的准确性和完整性,也不保证本报告所包含的信息或建议在本报告发出后不会发生任何变更。本报告中所提供的信息仅供参考。
+          </p>
+          <p>
+            3、报告中的内容不对投资者做出的最终操作建议做任何的担保,也没有任何形式的分享投资收益或者分担投资损失的书面或口头承诺。不作为客户在投资、法律、会计或税务等方面的最终操作建议,也不作为道义的、责任的和法律的依据或者凭证,无论是否已经明示或者暗示。
+          </p>
+          <p>
+            4、在任何情况下,本公司不对客户/接受人/接受机构因使用报告中内容所引致的一切损失负责任,客户/接受人/接受机构需自行承担全部风险。
+          </p>
+          <p
+            @click="hideTips"
+            style="
+              position: absolute;
+              bottom: 0;
+              left: 0;
+              right: 0;
+              font-size: 0.56rem;
+              line-height: 1.6rem;
+              color: #2680eb;
+              text-align: center;
+              border-top: 1px solid #eaeaea;
+            "
+          >
+            知道了
+          </p>
+        </div>
+      </div>
+      <div style="width:30px; position:fixed; right:0.6rem; bottom:2.4rem; z-index:100;">
+        <img src="~@/assets/img/returntop.png" @click="goTop" style="width:30px; margin-bottom:0.2rem;" />
+      </div>
+    </div>
+    </div>
+
+    <AudioPlay ref="audioRef"/>
+  </div>
+</template>
+
+<script>
+import {
+  reportDetail,
+} from "@/api/api.js";
+import _ from 'lodash';
+import AudioPlay from './audioPlay.vue';
+export default {
+  components: { AudioPlay },
+  data() {
+    return {
+      id: this.$route.query.code || '',
+      isshow: false,
+      reportInfo: {},
+      reportlist: [],
+
+      totalContent: [],
+      realContent: [],
+      page_no: 0,
+      pageSize: 20, //默认初始加载50个p标签
+      total_page: 0,
+    };
+  },
+  mounted() {
+    this.getreportdetail();
+    window.addEventListener('scroll', this.loadMoreHandle);
+  },
+
+  destroyed() {
+    window.removeEventListener('scroll', this.loadMoreHandle);
+  },
+
+  updated() {
+    // $('#resetcss').css({font:"0.76rem/1.5 '微软雅黑'",color:"#333",letterSpacing:"0.05rem"});
+    $("#resetcss")
+      .find("img")
+      .css({ display: "block", margin: "0 auto", maxWidth: "100%" });
+    $("#resetcss")
+      .find("video")
+      .css({ display: "block", margin: "0 auto", maxWidth: "100%" });
+    $("#resetcss")
+      .find("p")
+      .css({
+        margin: "0 auto 0",
+        font: "0.7rem/1.5 'PingFang-SC-Regular'",
+        color: "#333",
+        letterSpacing: "0.08rem",
+        lineHeight: "1.3rem",
+      });
+    $("#resetcss")
+      .find("span")
+      .css({
+        font: "0.7rem/1.5 'PingFang-SC-Regular'",
+        letterSpacing: "0.08rem",
+        lineHeight: "1.3rem",
+      });
+    $("#resetcss")
+      .find("span.fr-emoticon")
+      .css({
+        width: "20px",
+        height: "20px",
+        backgroundRepeat: "no-repeat",
+        backgroundSize: "cover",
+        display: "inline-block",
+        verticalAlign: "middle",
+      });
+    $("#resetcss").find("ol").css({ listStyleType: "disc" });
+    $("#resetcss")
+      .find("pre")
+      .css({ display: "block", whiteSpace: "pre-wrap" });
+  },
+  methods: {
+    showTips() {
+      //免责声明显示
+      $("#tipsAlert").animate({ top: 0 });
+    },
+    hideTips() {
+      //免责声明收起
+      $("#tipsAlert").animate({ top: "-120rem" });
+    },
+    goTop() {
+      document.body.scrollTop = document.documentElement.scrollTop = 0;
+    },
+    playaudio(item) {
+      //子组件先存后播
+      console.log(item);
+      if (
+        this.$store.state.audiolist.length > 0 &&
+        item.VideoUrl == this.$store.state.audiolist[0].VideoUrl
+      ) {
+        // this.$parent.playaudioplay();
+        this.$refs.audioRef.playaudioplay();
+      } else {
+        this.$refs.audioRef.setisshowaudio(
+          [
+            {
+              video_url: item.VideoUrl,
+              video_name: item.VideoName,
+              video_play_seconds: item.VideoPlaySeconds,
+            },
+          ],
+          0
+        );
+      }
+    },
+
+    async getreportdetail() {
+      const { Data,Ret  } = await reportDetail({ ReportCode: this.id });
+        if (Ret !== 200) return
+
+        this.reportInfo = Data.Report;
+        this.isshow = true;
+
+        this.splitContentHandle(this.reportInfo.Content);
+
+        $(document).on("click", "#resetcss img", function (event) {
+          let imgArray = [];
+          let curImageSrc = $(this).attr("src");
+          let oParent = $(this).parent();
+          if (curImageSrc && !oParent.attr("href")) {
+            $("#resetcss img").each(function (index, el) {
+              let itemSrc = $(this).attr("src");
+              imgArray.push(itemSrc);
+            });
+            wx.previewImage({ current: curImageSrc, urls: imgArray });
+          }
+        });
+    },
+
+    /*内容分割*/
+    splitContentHandle(content) {
+      const arr = content.split("</p>");
+      this.totalContent = arr.map((_) => _ + "</p>");
+      this.realContent = this.totalContent.slice(0, this.pageSize);
+      this.total_page = parseInt(this.totalContent.length / this.pageSize) + 1;
+      // console.log(this.realContent, this.totalContent);
+    },
+
+    /* 加载下一页内容 */
+    loadContent() {
+      this.realContent = this.realContent.concat(
+        this.totalContent.slice(
+          this.page_no * this.pageSize,
+          (this.page_no + 1) * this.pageSize
+        )
+      );
+    },
+    loadMoreHandle: _.throttle(function() {
+
+      if(this.page_no >= this.total_page) return
+
+      const scrollTop = document.documentElement.scrollTop || document.body.scrollTop; // 滚动的高度
+      const clientHeight = document.documentElement.clientHeight || document.body.clientHeight; // 可视高度
+      const scrollHeight = document.body.scrollHeight; // 总高度
+
+      if((scrollHeight - scrollTop - clientHeight) < 500) {
+        console.log('触底')
+        this.page_no = this.page_no+1;
+        this.loadContent();
+      }
+    },300)
+  },
+};
+</script>
+
+<style lang="scss">
+.wrapper {
+  position: relative;
+  overflow: hidden;
+  height: 100%;
+  #noaccess {
+    width: 100%;
+    height: 12rem;
+    padding: 5rem 0.6rem 1rem;
+    box-sizing: border-box;
+    text-align: center;
+    position: absolute;
+    bottom: 0;
+    background: url(~@/assets/img/accessbg.png) no-repeat;
+    background-size: 100% auto;
+    overflow: hidden;
+    > a,
+    button {
+      width: 12rem;
+      height: 2rem;
+      background: url(~@/assets/img/newbtn600.png) no-repeat;
+      background-size: 100% 100%;
+      font-size: 0.48rem;
+      color: #fff;
+      border: none;
+      margin-top: 1.5rem;
+    }
+  }
+}
+#reportdtl {
+  background: #fff;
+  overflow: auto;
+  max-width: 1200px;
+  margin: 0 auto;
+  header {
+    padding: 0.6rem;
+    box-sizing: border-box;
+    text-align: left;
+    background: #fff;
+    p {
+      font-size: 0.84rem;
+      font-weight: 600;
+      color: #000;
+    }
+  }
+  #playcon {
+    padding: 0 0.6rem;
+    box-sizing: border-box;
+    background: #fff;
+    overflow: hidden;
+    > div {
+      width: 100%;
+      height: 2.96rem;
+      padding: 0.48rem 0.6rem;
+      box-sizing: border-box;
+      background: #f1f1f1;
+      border-radius: 0.2rem;
+    }
+  }
+  #abstract {
+    padding: 0.6rem;
+    box-sizing: border-box;
+    font-size: 0.7rem;
+    line-height: 1.4rem;
+    letter-spacing: 0.1rem;
+    .abstract_cont {
+      border-left: 0.2rem solid #007aff;
+      padding: 0.14rem 0.4rem;
+      box-sizing: border-box;
+      color: #333;
+    }
+  }
+  #noaccess {
+    width: 100%;
+    height: 12rem;
+    padding: 5rem 0.6rem 1rem;
+    box-sizing: border-box;
+    text-align: center;
+    position: relative;
+    top: -4rem;
+    background: url(~@/assets/img/accessbg.png) no-repeat;
+    background-size: 100% auto;
+    margin-bottom: -4rem;
+    overflow: hidden;
+    > a,
+    button {
+      width: 12rem;
+      height: 2rem;
+      background: url(~@/assets/img/newbtn600.png) no-repeat;
+      background-size: 100% 100%;
+      font-size: 0.48rem;
+      color: #fff;
+      border: none;
+      margin-top: 1.5rem;
+    }
+  }
+  table {
+    border-top: 1px solid #ccc;
+    border-left: 1px solid #ccc;
+    border-collapse: collapse;
+    th,
+    td {
+      border-right: 1px solid #ccc;
+      border-bottom: 1px solid #ccc;
+      padding: 0.1rem 0.2rem;
+      box-sizing: border-box;
+    }
+  }
+  #resetcss {
+    pre {
+      white-space: pre-wrap;
+    }
+  }
+  // #element .element .element-content .main-container .content tbody td {
+  //   padding: 0.01rem 0;
+  //   word-break: break-all;
+  // }
+  #tipsAlert {
+    width: 100%;
+    height: 100%;
+    padding: 15% 1rem;
+    box-sizing: border-box;
+    position: fixed;
+    top: -120rem;
+    left: 0;
+    background: rgba(0, 0, 0, 0.6);
+    z-index: 200;
+  }
+}
+</style>

+ 383 - 0
src/views/reportEn/detail.vue

@@ -0,0 +1,383 @@
+<!-- 省事直接cv一下老项目代码 -->
+<template>
+  <div class="wrapper" ref="wrapper">
+    <div id="reportdtl" v-if="isshow">
+      <header>
+        <p>
+          <span style="margin-left: -0.45rem"
+            >【第{{ reportInfo.Stage }}期|FICC】{{
+              reportInfo.Title
+            }}</span
+          >
+          <span v-if="reportInfo.CreateTime"
+            >({{ reportInfo.CreateTime.substring(5, 7)
+            }}{{ reportInfo.CreateTime.substring(8, 10) }})</span
+          >
+        </p>
+      </header>
+      <div
+        style="
+          padding: 0rem 0.8rem 0.4rem;
+          box-sizing: border-box;
+          color: #666;
+          font-size: 0.66rem;
+          overflow: hidden;
+        "
+      >
+        <span>{{ reportInfo.Author }}</span>
+        <span style="float: right">{{ reportInfo.PublishTime }}</span>
+      </div>
+
+      <div id="abstract">
+        <div class="abstract_cont">
+          <div>摘要:{{ reportInfo.Abstract }}</div>
+          <div style="color: #666; margintop: 1.2rem">
+            *注:请务必阅读&nbsp;<strong
+              style="fontweight: normal; cursor: pointer; color: #3e8ce6"
+              @click="showTips"
+              >免责声明</strong
+            >
+          </div>
+        </div>
+      </div>
+      <div style="padding: 0.6rem; box-sizing: border-box; overflow: hidden">
+        <!-- <div id="resetcss" style="overflow:hidden;" v-html="reportInfo.Content"></div> -->
+        <div id="resetcss" style="overflow:hidden;">
+        <ul>
+          <li v-for="(html,index) in realContent" :key="index" v-html="html"></li>
+        </ul>
+      </div>
+      <div id="tipsAlert">
+        <div
+          style="
+            width: 100%;
+            padding: 0.8rem 0.66rem 2.2rem;
+            box-sizing: border-box;
+            font: 0.52rem/0.8rem 'PingFang-SC-Regular';
+            color: #666;
+            background: #fff;
+            overflow: scroll;
+            position: relative;
+            border-radius: 0.2rem;
+          "
+        >
+          <!-- <h1 style="font:0.64rem '微软雅黑'; color:#333; text-align:center; margin-bottom:0.34rem;">免责声明</h1> -->
+          <h1
+            style="
+              font: 0.64rem 'PingFang-SC-Regular';
+              color: #333;
+              text-align: center;
+              margin-bottom: 0.34rem;
+            "
+          >
+            免责声明
+          </h1>
+          <p>
+            1、本报告仅供弘则弥道(上海)投资咨询有限公司正式签约的机构客户使用,不会仅因接收人/接受机构收到本报告而将其视为客户。
+          </p>
+          <p>
+            2、本报告根据国际和行业通行的准则,以合法渠道获得这些信息,尽可能保证可靠、准确和完整,但并不保证报告所述信息的准确性和完整性,也不保证本报告所包含的信息或建议在本报告发出后不会发生任何变更。本报告中所提供的信息仅供参考。
+          </p>
+          <p>
+            3、报告中的内容不对投资者做出的最终操作建议做任何的担保,也没有任何形式的分享投资收益或者分担投资损失的书面或口头承诺。不作为客户在投资、法律、会计或税务等方面的最终操作建议,也不作为道义的、责任的和法律的依据或者凭证,无论是否已经明示或者暗示。
+          </p>
+          <p>
+            4、在任何情况下,本公司不对客户/接受人/接受机构因使用报告中内容所引致的一切损失负责任,客户/接受人/接受机构需自行承担全部风险。
+          </p>
+          <p
+            @click="hideTips"
+            style="
+              position: absolute;
+              bottom: 0;
+              left: 0;
+              right: 0;
+              font-size: 0.56rem;
+              line-height: 1.6rem;
+              color: #2680eb;
+              text-align: center;
+              border-top: 1px solid #eaeaea;
+            "
+          >
+            知道了
+          </p>
+        </div>
+      </div>
+      <div style="width:30px; position:fixed; right:0.6rem; bottom:2.4rem; z-index:100;">
+        <img src="~@/assets/img/returntop.png" @click="goTop" style="width:30px; margin-bottom:0.2rem;" />
+      </div>
+    </div>
+    </div>
+
+
+    <AudioPlay ref="audioRef"/>
+  </div>
+</template>
+
+<script>
+import {
+  reportEnDetail,
+} from "@/api/api.js";
+import _ from 'lodash';
+export default {
+  data() {
+    return {
+      id: this.$route.query.code || '',
+      isshow: false,
+      reportInfo: {},
+      reportlist: [],
+
+      totalContent: [],
+      realContent: [],
+      page_no: 0,
+      pageSize: 20, //默认初始加载50个p标签
+      total_page: 0,
+    };
+  },
+  mounted() {
+    this.getreportdetail();
+    window.addEventListener('scroll', this.loadMoreHandle);
+  },
+  destroyed() {
+    window.removeEventListener('scroll', this.loadMoreHandle);
+  },
+
+  updated() {
+    $("#resetcss")
+      .find("img")
+      .css({ display: "block", margin: "0 auto", maxWidth: "100%" });
+    $("#resetcss")
+      .find("video")
+      .css({ display: "block", margin: "0 auto", maxWidth: "100%" });
+    $("#resetcss")
+      .find("p")
+      .css({
+        margin: "0 auto 0",
+        font: "0.7rem/1.5 'PingFang-SC-Regular'",
+        color: "#333",
+        letterSpacing: "0.08rem",
+        lineHeight: "1.3rem",
+      });
+    $("#resetcss")
+      .find("span")
+      .css({
+        font: "0.7rem/1.5 'PingFang-SC-Regular'",
+        letterSpacing: "0.08rem",
+        lineHeight: "1.3rem",
+      });
+    $("#resetcss")
+      .find("span.fr-emoticon")
+      .css({
+        width: "20px",
+        height: "20px",
+        backgroundRepeat: "no-repeat",
+        backgroundSize: "cover",
+        display: "inline-block",
+        verticalAlign: "middle",
+      });
+    $("#resetcss").find("ol").css({ listStyleType: "disc" });
+    $("#resetcss")
+      .find("pre")
+      .css({ display: "block", whiteSpace: "pre-wrap" });
+  },
+  methods: {
+    showTips() {
+      //免责声明显示
+      $("#tipsAlert").animate({ top: 0 });
+    },
+    hideTips() {
+      //免责声明收起
+      $("#tipsAlert").animate({ top: "-120rem" });
+    },
+    goTop() {
+      document.body.scrollTop = document.documentElement.scrollTop = 0;
+    },
+
+    async getreportdetail() {
+      const { Data,Ret  } = await reportEnDetail({ ReportCode: this.id });
+        if (Ret !== 200) return
+
+        this.reportInfo = Data.Report;
+        this.isshow = true;
+
+        this.splitContentHandle(this.reportInfo.Content);
+
+        $(document).on("click", "#resetcss img", function (event) {
+          let imgArray = [];
+          let curImageSrc = $(this).attr("src");
+          let oParent = $(this).parent();
+          if (curImageSrc && !oParent.attr("href")) {
+            $("#resetcss img").each(function (index, el) {
+              let itemSrc = $(this).attr("src");
+              imgArray.push(itemSrc);
+            });
+            wx.previewImage({ current: curImageSrc, urls: imgArray });
+          }
+        });
+    },
+
+    /*内容分割*/
+    splitContentHandle(content) {
+      const arr = content.split("</p>");
+      this.totalContent = arr.map((_) => _ + "</p>");
+      this.realContent = this.totalContent.slice(0, this.pageSize);
+      this.total_page = parseInt(this.totalContent.length / this.pageSize) + 1;
+      // console.log(this.realContent, this.totalContent);
+    },
+
+    /* 加载下一页内容 */
+    loadContent() {
+      this.realContent = this.realContent.concat(
+        this.totalContent.slice(
+          this.page_no * this.pageSize,
+          (this.page_no + 1) * this.pageSize
+        )
+      );
+    },
+    loadMoreHandle: _.throttle(function() {
+
+      if(this.page_no >= this.total_page) return
+
+      const scrollTop = document.documentElement.scrollTop || document.body.scrollTop; // 滚动的高度
+      const clientHeight = document.documentElement.clientHeight || document.body.clientHeight; // 可视高度
+      const scrollHeight = document.body.scrollHeight; // 总高度
+
+      if((scrollHeight - scrollTop - clientHeight) < 500) {
+        console.log('触底')
+        this.page_no = this.page_no+1;
+        this.loadContent();
+      }
+    },300)
+  },
+};
+</script>
+
+<style lang="scss">
+.wrapper {
+  position: relative;
+  overflow: hidden;
+  height: 100%;
+  #noaccess {
+    width: 100%;
+    height: 12rem;
+    padding: 5rem 0.6rem 1rem;
+    box-sizing: border-box;
+    text-align: center;
+    position: absolute;
+    bottom: 0;
+    background: url(~@/assets/img/accessbg.png) no-repeat;
+    background-size: 100% auto;
+    overflow: hidden;
+    > a,
+    button {
+      width: 12rem;
+      height: 2rem;
+      background: url(~@/assets/img/newbtn600.png) no-repeat;
+      background-size: 100% 100%;
+      font-size: 0.48rem;
+      color: #fff;
+      border: none;
+      margin-top: 1.5rem;
+    }
+  }
+}
+#reportdtl {
+  background: #fff;
+  overflow: auto;
+  max-width: 1200px;
+  margin: 0 auto;
+  header {
+    padding: 0.6rem;
+    box-sizing: border-box;
+    text-align: left;
+    background: #fff;
+    p {
+      font-size: 0.84rem;
+      font-weight: 600;
+      color: #000;
+    }
+  }
+  #playcon {
+    padding: 0 0.6rem;
+    box-sizing: border-box;
+    background: #fff;
+    overflow: hidden;
+    > div {
+      width: 100%;
+      height: 2.96rem;
+      padding: 0.48rem 0.6rem;
+      box-sizing: border-box;
+      background: #f1f1f1;
+      border-radius: 0.2rem;
+    }
+  }
+  #abstract {
+    padding: 0.6rem;
+    box-sizing: border-box;
+    font-size: 0.7rem;
+    line-height: 1.4rem;
+    letter-spacing: 0.1rem;
+    .abstract_cont {
+      border-left: 0.2rem solid #007aff;
+      padding: 0.14rem 0.4rem;
+      box-sizing: border-box;
+      color: #333;
+    }
+  }
+  #noaccess {
+    width: 100%;
+    height: 12rem;
+    padding: 5rem 0.6rem 1rem;
+    box-sizing: border-box;
+    text-align: center;
+    position: relative;
+    top: -4rem;
+    background: url(~@/assets/img/accessbg.png) no-repeat;
+    background-size: 100% auto;
+    margin-bottom: -4rem;
+    overflow: hidden;
+    > a,
+    button {
+      width: 12rem;
+      height: 2rem;
+      background: url(~@/assets/img/newbtn600.png) no-repeat;
+      background-size: 100% 100%;
+      font-size: 0.48rem;
+      color: #fff;
+      border: none;
+      margin-top: 1.5rem;
+    }
+  }
+  table {
+    border-top: 1px solid #ccc;
+    border-left: 1px solid #ccc;
+    border-collapse: collapse;
+    th,
+    td {
+      border-right: 1px solid #ccc;
+      border-bottom: 1px solid #ccc;
+      padding: 0.1rem 0.2rem;
+      box-sizing: border-box;
+    }
+  }
+  #resetcss {
+    pre {
+      white-space: pre-wrap;
+    }
+  }
+  // #element .element .element-content .main-container .content tbody td {
+  //   padding: 0.01rem 0;
+  //   word-break: break-all;
+  // }
+  #tipsAlert {
+    width: 100%;
+    height: 100%;
+    padding: 15% 1rem;
+    box-sizing: border-box;
+    position: fixed;
+    top: -120rem;
+    left: 0;
+    background: rgba(0, 0, 0, 0.6);
+    z-index: 200;
+  }
+}
+</style>

+ 21 - 0
vite.config.js

@@ -0,0 +1,21 @@
+import { defineConfig,loadEnv } from 'vite'
+import vue from '@vitejs/plugin-vue'
+import path from "path";
+// https://vitejs.dev/config/
+export default ({mode})=>defineConfig({
+  base:loadEnv(mode, process.cwd()).VITE_APP_BASE_URL,
+  plugins: [
+    vue(),
+  ],
+  resolve: {
+    alias: {
+      "@": path.resolve(__dirname, "./src"),
+    },
+  },
+  build:{
+    outDir:loadEnv(mode, process.cwd()).VITE_APP_OUTDIR
+  },
+  server:{
+    host:'0.0.0.0',
+  }
+})

Some files were not shown because too many files changed in this diff