mo 1 năm trước cách đây
mục cha
commit
44ae533787

+ 496 - 8
package-lock.json

@@ -18,6 +18,7 @@
         "html2canvas": "^1.4.1",
         "numeral": "^2.0.6",
         "plyr": "^3.7.8",
+        "qrcode": "^1.5.3",
         "query-string": "^8.1.0",
         "swiper": "^9.3.2",
         "terser": "^5.17.6",
@@ -3022,7 +3023,6 @@
       "version": "5.0.1",
       "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz",
       "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
-      "dev": true,
       "engines": {
         "node": ">=8"
       }
@@ -3464,6 +3464,82 @@
         "node": ">= 10"
       }
     },
+    "node_modules/cliui": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmmirror.com/cliui/-/cliui-6.0.0.tgz",
+      "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
+      "dependencies": {
+        "string-width": "^4.2.0",
+        "strip-ansi": "^6.0.0",
+        "wrap-ansi": "^6.2.0"
+      }
+    },
+    "node_modules/cliui/node_modules/ansi-styles": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz",
+      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+      "dependencies": {
+        "color-convert": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/cliui/node_modules/color-convert": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz",
+      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+      "dependencies": {
+        "color-name": "~1.1.4"
+      },
+      "engines": {
+        "node": ">=7.0.0"
+      }
+    },
+    "node_modules/cliui/node_modules/color-name": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz",
+      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+    },
+    "node_modules/cliui/node_modules/emoji-regex": {
+      "version": "8.0.0",
+      "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz",
+      "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+    },
+    "node_modules/cliui/node_modules/is-fullwidth-code-point": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+      "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/cliui/node_modules/string-width": {
+      "version": "4.2.3",
+      "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz",
+      "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+      "dependencies": {
+        "emoji-regex": "^8.0.0",
+        "is-fullwidth-code-point": "^3.0.0",
+        "strip-ansi": "^6.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/cliui/node_modules/wrap-ansi": {
+      "version": "6.2.0",
+      "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+      "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+      "dependencies": {
+        "ansi-styles": "^4.0.0",
+        "string-width": "^4.1.0",
+        "strip-ansi": "^6.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
     "node_modules/clone": {
       "version": "1.0.4",
       "resolved": "https://registry.npmmirror.com/clone/-/clone-1.0.4.tgz",
@@ -3630,6 +3706,14 @@
         }
       }
     },
+    "node_modules/decamelize": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmmirror.com/decamelize/-/decamelize-1.2.0.tgz",
+      "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
     "node_modules/decode-uri-component": {
       "version": "0.4.1",
       "resolved": "https://registry.npmmirror.com/decode-uri-component/-/decode-uri-component-0.4.1.tgz",
@@ -3694,6 +3778,11 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/dijkstrajs": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/dijkstrajs/-/dijkstrajs-1.0.3.tgz",
+      "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA=="
+    },
     "node_modules/dir-glob": {
       "version": "3.0.1",
       "resolved": "https://registry.npmmirror.com/dir-glob/-/dir-glob-3.0.1.tgz",
@@ -3760,6 +3849,11 @@
       "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
       "dev": true
     },
+    "node_modules/encode-utf8": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/encode-utf8/-/encode-utf8-1.0.3.tgz",
+      "integrity": "sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw=="
+    },
     "node_modules/encoding": {
       "version": "0.1.13",
       "resolved": "https://registry.npmmirror.com/encoding/-/encoding-0.1.13.tgz",
@@ -4498,6 +4592,14 @@
         "node": ">=6.9.0"
       }
     },
+    "node_modules/get-caller-file": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmmirror.com/get-caller-file/-/get-caller-file-2.0.5.tgz",
+      "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+      "engines": {
+        "node": "6.* || 8.* || >= 10.*"
+      }
+    },
     "node_modules/get-intrinsic": {
       "version": "1.2.0",
       "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.2.0.tgz",
@@ -6384,6 +6486,14 @@
         "node": ">=10"
       }
     },
+    "node_modules/p-try": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmmirror.com/p-try/-/p-try-2.2.0.tgz",
+      "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+      "engines": {
+        "node": ">=6"
+      }
+    },
     "node_modules/param-case": {
       "version": "3.0.4",
       "resolved": "https://registry.npmmirror.com/param-case/-/param-case-3.0.4.tgz",
@@ -6462,7 +6572,6 @@
       "version": "4.0.0",
       "resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz",
       "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
-      "dev": true,
       "engines": {
         "node": ">=8"
       }
@@ -6600,6 +6709,14 @@
         "url-polyfill": "^1.1.12"
       }
     },
+    "node_modules/pngjs": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmmirror.com/pngjs/-/pngjs-5.0.0.tgz",
+      "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==",
+      "engines": {
+        "node": ">=10.13.0"
+      }
+    },
     "node_modules/postcss": {
       "version": "8.4.23",
       "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.4.23.tgz",
@@ -6696,6 +6813,23 @@
         "node": ">=6"
       }
     },
+    "node_modules/qrcode": {
+      "version": "1.5.3",
+      "resolved": "https://registry.npmmirror.com/qrcode/-/qrcode-1.5.3.tgz",
+      "integrity": "sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg==",
+      "dependencies": {
+        "dijkstrajs": "^1.0.1",
+        "encode-utf8": "^1.0.3",
+        "pngjs": "^5.0.0",
+        "yargs": "^15.3.1"
+      },
+      "bin": {
+        "qrcode": "bin/qrcode"
+      },
+      "engines": {
+        "node": ">=10.13.0"
+      }
+    },
     "node_modules/qs": {
       "version": "6.11.1",
       "resolved": "https://registry.npmmirror.com/qs/-/qs-6.11.1.tgz",
@@ -6839,6 +6973,19 @@
         "jsesc": "bin/jsesc"
       }
     },
+    "node_modules/require-directory": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmmirror.com/require-directory/-/require-directory-2.1.1.tgz",
+      "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/require-main-filename": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/require-main-filename/-/require-main-filename-2.0.0.tgz",
+      "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg=="
+    },
     "node_modules/resolve": {
       "version": "1.22.2",
       "resolved": "https://registry.npmmirror.com/resolve/-/resolve-1.22.2.tgz",
@@ -7018,6 +7165,11 @@
         "upper-case-first": "^2.0.2"
       }
     },
+    "node_modules/set-blocking": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/set-blocking/-/set-blocking-2.0.0.tgz",
+      "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw=="
+    },
     "node_modules/shebang-command": {
       "version": "2.0.0",
       "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz",
@@ -7209,7 +7361,6 @@
       "version": "6.0.1",
       "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz",
       "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
-      "dev": true,
       "dependencies": {
         "ansi-regex": "^5.0.1"
       },
@@ -8026,6 +8177,11 @@
         "node": ">= 8"
       }
     },
+    "node_modules/which-module": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmmirror.com/which-module/-/which-module-2.0.1.tgz",
+      "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ=="
+    },
     "node_modules/word-wrap": {
       "version": "1.2.3",
       "resolved": "https://registry.npmmirror.com/word-wrap/-/word-wrap-1.2.3.tgz",
@@ -8129,6 +8285,11 @@
         "node": ">=12"
       }
     },
+    "node_modules/y18n": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmmirror.com/y18n/-/y18n-4.0.3.tgz",
+      "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ=="
+    },
     "node_modules/yallist": {
       "version": "3.1.1",
       "resolved": "https://registry.npmmirror.com/yallist/-/yallist-3.1.1.tgz",
@@ -8144,6 +8305,118 @@
         "node": ">= 14"
       }
     },
+    "node_modules/yargs": {
+      "version": "15.4.1",
+      "resolved": "https://registry.npmmirror.com/yargs/-/yargs-15.4.1.tgz",
+      "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
+      "dependencies": {
+        "cliui": "^6.0.0",
+        "decamelize": "^1.2.0",
+        "find-up": "^4.1.0",
+        "get-caller-file": "^2.0.1",
+        "require-directory": "^2.1.1",
+        "require-main-filename": "^2.0.0",
+        "set-blocking": "^2.0.0",
+        "string-width": "^4.2.0",
+        "which-module": "^2.0.0",
+        "y18n": "^4.0.0",
+        "yargs-parser": "^18.1.2"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/yargs-parser": {
+      "version": "18.1.3",
+      "resolved": "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-18.1.3.tgz",
+      "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
+      "dependencies": {
+        "camelcase": "^5.0.0",
+        "decamelize": "^1.2.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/yargs-parser/node_modules/camelcase": {
+      "version": "5.3.1",
+      "resolved": "https://registry.npmmirror.com/camelcase/-/camelcase-5.3.1.tgz",
+      "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/yargs/node_modules/emoji-regex": {
+      "version": "8.0.0",
+      "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz",
+      "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+    },
+    "node_modules/yargs/node_modules/find-up": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmmirror.com/find-up/-/find-up-4.1.0.tgz",
+      "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+      "dependencies": {
+        "locate-path": "^5.0.0",
+        "path-exists": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/yargs/node_modules/is-fullwidth-code-point": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+      "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/yargs/node_modules/locate-path": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-5.0.0.tgz",
+      "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+      "dependencies": {
+        "p-locate": "^4.1.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/yargs/node_modules/p-limit": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-2.3.0.tgz",
+      "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+      "dependencies": {
+        "p-try": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/yargs/node_modules/p-locate": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-4.1.0.tgz",
+      "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+      "dependencies": {
+        "p-limit": "^2.2.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/yargs/node_modules/string-width": {
+      "version": "4.2.3",
+      "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz",
+      "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+      "dependencies": {
+        "emoji-regex": "^8.0.0",
+        "is-fullwidth-code-point": "^3.0.0",
+        "strip-ansi": "^6.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
     "node_modules/yocto-queue": {
       "version": "0.1.0",
       "resolved": "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz",
@@ -10369,8 +10642,7 @@
     "ansi-regex": {
       "version": "5.0.1",
       "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz",
-      "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
-      "dev": true
+      "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
     },
     "ansi-styles": {
       "version": "3.2.1",
@@ -10725,6 +10997,69 @@
       "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==",
       "dev": true
     },
+    "cliui": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmmirror.com/cliui/-/cliui-6.0.0.tgz",
+      "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
+      "requires": {
+        "string-width": "^4.2.0",
+        "strip-ansi": "^6.0.0",
+        "wrap-ansi": "^6.2.0"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "4.3.0",
+          "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz",
+          "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+          "requires": {
+            "color-convert": "^2.0.1"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "color-name": {
+          "version": "1.1.4",
+          "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz",
+          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+        },
+        "emoji-regex": {
+          "version": "8.0.0",
+          "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz",
+          "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+        },
+        "is-fullwidth-code-point": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+          "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
+        },
+        "string-width": {
+          "version": "4.2.3",
+          "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz",
+          "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+          "requires": {
+            "emoji-regex": "^8.0.0",
+            "is-fullwidth-code-point": "^3.0.0",
+            "strip-ansi": "^6.0.1"
+          }
+        },
+        "wrap-ansi": {
+          "version": "6.2.0",
+          "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+          "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+          "requires": {
+            "ansi-styles": "^4.0.0",
+            "string-width": "^4.1.0",
+            "strip-ansi": "^6.0.0"
+          }
+        }
+      }
+    },
     "clone": {
       "version": "1.0.4",
       "resolved": "https://registry.npmmirror.com/clone/-/clone-1.0.4.tgz",
@@ -10864,6 +11199,11 @@
         "ms": "2.1.2"
       }
     },
+    "decamelize": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmmirror.com/decamelize/-/decamelize-1.2.0.tgz",
+      "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA=="
+    },
     "decode-uri-component": {
       "version": "0.4.1",
       "resolved": "https://registry.npmmirror.com/decode-uri-component/-/decode-uri-component-0.4.1.tgz",
@@ -10916,6 +11256,11 @@
       "integrity": "sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==",
       "dev": true
     },
+    "dijkstrajs": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/dijkstrajs/-/dijkstrajs-1.0.3.tgz",
+      "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA=="
+    },
     "dir-glob": {
       "version": "3.0.1",
       "resolved": "https://registry.npmmirror.com/dir-glob/-/dir-glob-3.0.1.tgz",
@@ -10978,6 +11323,11 @@
       "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
       "dev": true
     },
+    "encode-utf8": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/encode-utf8/-/encode-utf8-1.0.3.tgz",
+      "integrity": "sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw=="
+    },
     "encoding": {
       "version": "0.1.13",
       "resolved": "https://registry.npmmirror.com/encoding/-/encoding-0.1.13.tgz",
@@ -11552,6 +11902,11 @@
       "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
       "dev": true
     },
+    "get-caller-file": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmmirror.com/get-caller-file/-/get-caller-file-2.0.5.tgz",
+      "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
+    },
     "get-intrinsic": {
       "version": "1.2.0",
       "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.2.0.tgz",
@@ -13042,6 +13397,11 @@
         "aggregate-error": "^3.0.0"
       }
     },
+    "p-try": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmmirror.com/p-try/-/p-try-2.2.0.tgz",
+      "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
+    },
     "param-case": {
       "version": "3.0.4",
       "resolved": "https://registry.npmmirror.com/param-case/-/param-case-3.0.4.tgz",
@@ -13107,8 +13467,7 @@
     "path-exists": {
       "version": "4.0.0",
       "resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz",
-      "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
-      "dev": true
+      "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="
     },
     "path-is-absolute": {
       "version": "1.0.1",
@@ -13209,6 +13568,11 @@
         "url-polyfill": "^1.1.12"
       }
     },
+    "pngjs": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmmirror.com/pngjs/-/pngjs-5.0.0.tgz",
+      "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw=="
+    },
     "postcss": {
       "version": "8.4.23",
       "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.4.23.tgz",
@@ -13281,6 +13645,17 @@
       "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
       "dev": true
     },
+    "qrcode": {
+      "version": "1.5.3",
+      "resolved": "https://registry.npmmirror.com/qrcode/-/qrcode-1.5.3.tgz",
+      "integrity": "sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg==",
+      "requires": {
+        "dijkstrajs": "^1.0.1",
+        "encode-utf8": "^1.0.3",
+        "pngjs": "^5.0.0",
+        "yargs": "^15.3.1"
+      }
+    },
     "qs": {
       "version": "6.11.1",
       "resolved": "https://registry.npmmirror.com/qs/-/qs-6.11.1.tgz",
@@ -13399,6 +13774,16 @@
         }
       }
     },
+    "require-directory": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmmirror.com/require-directory/-/require-directory-2.1.1.tgz",
+      "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="
+    },
+    "require-main-filename": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/require-main-filename/-/require-main-filename-2.0.0.tgz",
+      "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg=="
+    },
     "resolve": {
       "version": "1.22.2",
       "resolved": "https://registry.npmmirror.com/resolve/-/resolve-1.22.2.tgz",
@@ -13542,6 +13927,11 @@
         "upper-case-first": "^2.0.2"
       }
     },
+    "set-blocking": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/set-blocking/-/set-blocking-2.0.0.tgz",
+      "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw=="
+    },
     "shebang-command": {
       "version": "2.0.0",
       "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz",
@@ -13697,7 +14087,6 @@
       "version": "6.0.1",
       "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz",
       "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
-      "dev": true,
       "requires": {
         "ansi-regex": "^5.0.1"
       }
@@ -14289,6 +14678,11 @@
         "isexe": "^2.0.0"
       }
     },
+    "which-module": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmmirror.com/which-module/-/which-module-2.0.1.tgz",
+      "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ=="
+    },
     "word-wrap": {
       "version": "1.2.3",
       "resolved": "https://registry.npmmirror.com/word-wrap/-/word-wrap-1.2.3.tgz",
@@ -14373,6 +14767,11 @@
       "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==",
       "dev": true
     },
+    "y18n": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmmirror.com/y18n/-/y18n-4.0.3.tgz",
+      "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ=="
+    },
     "yallist": {
       "version": "3.1.1",
       "resolved": "https://registry.npmmirror.com/yallist/-/yallist-3.1.1.tgz",
@@ -14385,6 +14784,95 @@
       "integrity": "sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA==",
       "dev": true
     },
+    "yargs": {
+      "version": "15.4.1",
+      "resolved": "https://registry.npmmirror.com/yargs/-/yargs-15.4.1.tgz",
+      "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
+      "requires": {
+        "cliui": "^6.0.0",
+        "decamelize": "^1.2.0",
+        "find-up": "^4.1.0",
+        "get-caller-file": "^2.0.1",
+        "require-directory": "^2.1.1",
+        "require-main-filename": "^2.0.0",
+        "set-blocking": "^2.0.0",
+        "string-width": "^4.2.0",
+        "which-module": "^2.0.0",
+        "y18n": "^4.0.0",
+        "yargs-parser": "^18.1.2"
+      },
+      "dependencies": {
+        "emoji-regex": {
+          "version": "8.0.0",
+          "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz",
+          "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+        },
+        "find-up": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmmirror.com/find-up/-/find-up-4.1.0.tgz",
+          "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+          "requires": {
+            "locate-path": "^5.0.0",
+            "path-exists": "^4.0.0"
+          }
+        },
+        "is-fullwidth-code-point": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+          "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
+        },
+        "locate-path": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-5.0.0.tgz",
+          "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+          "requires": {
+            "p-locate": "^4.1.0"
+          }
+        },
+        "p-limit": {
+          "version": "2.3.0",
+          "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-2.3.0.tgz",
+          "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+          "requires": {
+            "p-try": "^2.0.0"
+          }
+        },
+        "p-locate": {
+          "version": "4.1.0",
+          "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-4.1.0.tgz",
+          "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+          "requires": {
+            "p-limit": "^2.2.0"
+          }
+        },
+        "string-width": {
+          "version": "4.2.3",
+          "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz",
+          "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+          "requires": {
+            "emoji-regex": "^8.0.0",
+            "is-fullwidth-code-point": "^3.0.0",
+            "strip-ansi": "^6.0.1"
+          }
+        }
+      }
+    },
+    "yargs-parser": {
+      "version": "18.1.3",
+      "resolved": "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-18.1.3.tgz",
+      "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
+      "requires": {
+        "camelcase": "^5.0.0",
+        "decamelize": "^1.2.0"
+      },
+      "dependencies": {
+        "camelcase": {
+          "version": "5.3.1",
+          "resolved": "https://registry.npmmirror.com/camelcase/-/camelcase-5.3.1.tgz",
+          "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
+        }
+      }
+    },
     "yocto-queue": {
       "version": "0.1.0",
       "resolved": "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz",

+ 1 - 0
package.json

@@ -31,6 +31,7 @@
     "html2canvas": "^1.4.1",
     "numeral": "^2.0.6",
     "plyr": "^3.7.8",
+    "qrcode": "^1.5.3",
     "query-string": "^8.1.0",
     "swiper": "^9.3.2",
     "terser": "^5.17.6",

BIN
src/common/images/smallLogo.png


+ 26 - 0
src/components/m-qrcode/index.module.less

@@ -0,0 +1,26 @@
+.qrcode {
+  position: relative;
+
+  .qrcodeCanvas {
+    width: 100% !important;
+    height: 100% !important;
+  }
+
+  .qrcodeLogo {
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    margin-left: -20px;
+    margin-top: -20px;
+    width: 40px !important;
+    height: 40px !important;
+    border-radius: 4px;
+
+    &.small {
+      margin-left: -10px;
+      margin-top: -10px;
+      width: 20px !important;
+      height: 20px !important;
+    }
+  }
+}

+ 63 - 0
src/components/m-qrcode/index.tsx

@@ -0,0 +1,63 @@
+import { defineComponent, nextTick, onMounted, ref, watch } from 'vue';
+import logo from '@common/images/smallLogo.png';
+import QRCode from 'qrcode';
+import styles from './index.module.less';
+
+export default defineComponent({
+  props: {
+    text: {
+      type: String,
+      default: ''
+    },
+    size: {
+      type: String,
+      default: '200px'
+    },
+    logoSize: {
+      type: String,
+      default: 'default'
+    }
+  },
+  setup(props) {
+    const canvas = ref();
+
+    const init = () => {
+      QRCode.toCanvas(
+        canvas.value,
+        props.text,
+        {
+          margin: 1
+        },
+        (error: any) => {
+          if (error) console.log(error);
+          console.log('success');
+        }
+      );
+    };
+    watch(
+      () => props.text,
+      () => {
+        init();
+      }
+    );
+    onMounted(() => {
+      nextTick(() => {
+        init();
+      });
+    });
+    return () => (
+      <div
+        class={styles.qrcode}
+        style={{ width: props.size, height: props.size }}>
+        <canvas ref={canvas} class={styles.qrcodeCanvas}></canvas>
+        <img
+          src={logo}
+          class={[
+            styles.qrcodeLogo,
+            props.logoSize === 'small' && styles.small
+          ]}
+        />
+      </div>
+    );
+  }
+});

+ 20 - 0
src/helpers/utils.ts

@@ -132,3 +132,23 @@ export const toChinesNum = (num: any) => {
   }
   return overWan ? getWan(overWan) + '万' + getWan(noWan) : getWan(num);
 };
+
+// 教务地址
+export function vaildTeachingUrl() {
+  let url = window.location.href;
+  let returnUrl = '';
+  if (/online/.test(url)) {
+    //线上
+    returnUrl = 'https://manonline.dayaedu.com';
+  } else if (/dev/.test(url)) {
+    // dev 环境
+    returnUrl = 'http://mandev.dayaedu.com';
+  } else if (/test/.test(url)) {
+    // dev 环境
+    returnUrl = 'http://mantest.dayaedu.com';
+  } else {
+    // 默认dev环境
+    returnUrl = 'http://mantest.dayaedu.com';
+  }
+  return returnUrl;
+}

+ 8 - 0
src/router/router-root.ts

@@ -54,5 +54,13 @@ export default [
     meta: {
       title: '404'
     }
+  },
+  {
+    path: '/activity-record-detail',
+    name: 'activity-record-detail',
+    component: () => import('@/views/activity-record/detail'),
+    meta: {
+      title: '活动节目单'
+    }
   }
 ];

+ 149 - 0
src/views/activity-record/detail-swiper.tsx

@@ -0,0 +1,149 @@
+import { Cell, CellGroup, Skeleton, SkeletonParagraph, Image } from 'vant';
+import { defineComponent, onMounted, reactive, watch, ref } from 'vue';
+import styles from './detail.module.less';
+import SwiperClass, { Navigation, Thumbs, Pagination } from 'swiper';
+import { Swiper, SwiperSlide } from 'swiper/vue';
+import 'swiper/css';
+import 'swiper/css/navigation';
+import 'swiper/css/thumbs';
+import 'swiper/css/pagination';
+import iconVideoDefault from '@common/images/icon-video-c.png';
+import { checkFile } from '@/helpers/toolsValidate';
+import palyBtn from './images/palyBtn.png';
+import arrayIcon from './images/array-icon.png';
+export default defineComponent({
+  name: 'detail-swiper',
+  emits: ['showImageToas'],
+  props: {
+    item: {
+      type: Object,
+      default: {}
+    }
+  },
+  setup(props, { slots, emit }) {
+    const forms = reactive({
+      loading: false
+    });
+    const thumbsSwiper = ref<SwiperClass>();
+    const setThumbsSwiper = (swiper: SwiperClass) => {
+      thumbsSwiper.value = swiper;
+      console.log(thumbsSwiper.value, 'setThumbsSwiper');
+    };
+    const modules = [Navigation, Thumbs, Pagination];
+    onMounted(() => {});
+
+    return () => (
+      <>
+        <div class={styles.progItemList}>
+          <Swiper
+            class="topSwiper"
+            style={{
+              '--swiper-navigation-color': '#fff',
+              '--swiper-pagination-color': '#fff'
+            }}
+            modules={modules}
+            space-between={10}
+            pagination={true}
+            thumbs={{ swiper: thumbsSwiper.value }}>
+            {props.item.attachmentUrl.map(
+              (i: any, index: number) =>
+                index <= 3 && (
+                  <SwiperSlide class="slide">
+                    <div
+                      class={styles.photo}
+                      onClick={() => {
+                        emit('showImageToas', {
+                          imagePreview: props.item.attachmentUrl,
+                          imageShow: true,
+                          startPosition: index
+                        });
+                        // forms.imagePreview = item.attachmentUrl;
+                        // forms.imageShow = true;
+                        // forms.startPosition = index;
+                      }}>
+                      {checkFile(i, 'image') ? (
+                        <Image src={i + '@base@tag=imgScale'} fit="cover" />
+                      ) : (
+                        <div class={styles.videoWErap}>
+                          <Image src={palyBtn} class={styles.palyBtn}></Image>
+                          <video
+                            style={{ backgroundColor: '#F8F8F8' }}
+                            poster={iconVideoDefault}
+                            src={i + '#t=1,4'}
+                          />
+                        </div>
+                      )}
+
+                      {props.item.attachmentUrl.length > 4 && index === 3 ? (
+                        <div class={styles.photoMore}>
+                          +{props.item.attachmentUrl.length - 4}
+                        </div>
+                      ) : (
+                        ''
+                      )}
+                    </div>
+                  </SwiperSlide>
+                )
+            )}
+          </Swiper>
+          <div class={styles.thumbsWrap}>
+            <div
+              class={styles.thumbsMore}
+              onClick={() => {
+                emit('showImageToas', {
+                  imagePreview: props.item.attachmentUrl,
+                  imageShow: true,
+                  startPosition: 0
+                });
+              }}>
+              全部
+              <Image class={styles.arrayIcon} src={arrayIcon}></Image>
+            </div>
+            <Swiper
+              class="thumbs-swiper"
+              modules={modules}
+              space-between={10}
+              slides-per-view={4}
+              watch-slides-progress={true}
+              prevent-clicks={true}
+              prevent-clicks-propagation={false}
+              onSwiper={setThumbsSwiper}>
+              {props.item.attachmentUrl.map(
+                (i: any, index: number) =>
+                  index <= 3 && (
+                    <SwiperSlide class="slide">
+                      <div class={styles.photo}>
+                        {checkFile(i, 'image') ? (
+                          <Image
+                            src={i + '@base@tag=imgScale&w=120'}
+                            fit="cover"
+                          />
+                        ) : (
+                          <div class={styles.videoSmallWErap}>
+                            <Image src={palyBtn} class={styles.playBtn}></Image>
+                            <video
+                              style={{ backgroundColor: '#F8F8F8' }}
+                              poster={iconVideoDefault}
+                              src={i + '#t=1,4'}
+                            />
+                          </div>
+                        )}
+
+                        {props.item.attachmentUrl.length > 4 && index === 3 ? (
+                          <div class={styles.photoMore}>
+                            +{props.item.attachmentUrl.length - 4}
+                          </div>
+                        ) : (
+                          ''
+                        )}
+                      </div>
+                    </SwiperSlide>
+                  )
+              )}
+            </Swiper>
+          </div>
+        </div>
+      </>
+    );
+  }
+});

+ 319 - 22
src/views/activity-record/detail.module.less

@@ -11,7 +11,7 @@
       width: 100%;
       height: 30px;
       top: 18px;
-      z-index: 100;
+      z-index: 500;
       padding: 0 16px;
       position: fixed;
       display: flex;
@@ -120,7 +120,6 @@
         background: #ffffff;
         box-shadow: inset 0px 1px 3px 0px rgba(152, 239, 213, 0.7);
         border-radius: 22px;
-
         background-clip: padding-box;
         border: 2px solid transparent;
         background-clip: padding-box, border-box;
@@ -231,11 +230,53 @@
           background-image: linear-gradient(270deg, #dcf3ff, #effae5),
             linear-gradient(180deg, #bef6e9, #c1e3f7);
           border-radius: 10px;
+          overflow: hidden;
+          .videoWErap {
+            position: relative;
+            .palyBtn {
+              width: 46px !important;
+              height: 46px !important;
+              position: absolute;
+              left: 50%;
+              margin-left: -23px;
+              top: 50%;
+              margin-top: -23px;
+              z-index: 200;
+            }
+          }
 
+          .videoSmallWErap {
+            position: relative;
+            .playBtn {
+              width: 18px !important;
+              height: 18px !important;
+              position: absolute;
+              left: 50%;
+              margin-left: -9px;
+              top: 50%;
+              margin-top: -9px;
+              z-index: 200;
+              img {
+                width: 18px !important;
+                height: 18px !important;
+              }
+            }
+          }
           :global {
+            .swiper-pagination-bullet-active {
+              width: 10px !important;
+              height: 4px;
+              border-radius: 2px;
+            }
+            .swiper-pagination-bullet {
+              width: 4px;
+              height: 4px;
+              border-radius: 2px;
+            }
             .topSwiper {
               width: 311px;
               height: 175px;
+
               .van-image {
                 width: 311px;
                 height: 175px;
@@ -245,42 +286,82 @@
                 height: 175px;
               }
             }
+
             .thumbs-swiper {
               .slide {
+                width: 70px;
+                height: 44px;
                 img {
                   display: block;
-                  width: 74px;
-                  height: 46px;
-                  object-fit: cover;
+                  width: 62px;
+                  height: 42px;
+                  object-fit: cover !important;
                 }
                 video {
-                  width: 74px;
-                  height: 46px;
+                  width: 62px;
+                  height: 43px;
                 }
               }
             }
-          }
+            .thumbs-swiper {
+              box-sizing: border-box;
+
+              margin-top: 8px;
+              margin-left: 8px;
+              margin-bottom: 8px;
 
-          .top-swiper {
-            height: 80%;
-            width: 100%;
+              .slide {
+                width: 74px;
+                height: 46px;
+                background: #ffffff;
+                border-radius: 4px;
+                overflow: hidden;
+                background-clip: padding-box;
+                border: 3px solid transparent;
+                background-clip: padding-box, border-box;
+                background-origin: padding-box, border-box;
+                background-image: linear-gradient(225deg, #fff, #fff),
+                  linear-gradient(
+                    225deg,
+                    rgba(0, 98, 255, 1),
+                    rgba(46, 216, 255, 1)
+                  );
+
+                &:not(.swiper-slide-thumb-active) {
+                  background-image: linear-gradient(225deg, #fff, #fff),
+                    linear-gradient(225deg, transparent, transparent);
+                }
+              }
+            }
           }
+          .thumbsWrap {
+            position: relative;
 
-          .thumbs-swiper {
-            height: 20%;
-            box-sizing: border-box;
-            padding: 5px 0;
-
-            .slide {
-              width: 25%;
-              height: 100%;
-              opacity: 1;
-              &:not(.swiper-slide-thumb-active) {
-                opacity: 0.4;
+            .thumbsMore {
+              z-index: 200;
+              position: absolute;
+              width: 23px;
+              height: 46px;
+              background: #ffffff;
+              border-radius: 4px 0px 0px 4px;
+              display: flex;
+              flex-direction: column;
+              align-items: center;
+              justify-content: center;
+              font-size: 11px;
+              font-weight: 500;
+              color: #131415;
+              text-align: center;
+              top: 0;
+              right: 0px;
+              .arrayIcon {
+                width: 13px;
+                height: 13px;
               }
             }
           }
         }
+
         .colorBg {
           width: 100%;
           position: absolute;
@@ -304,6 +385,20 @@
         }
       }
     }
+    .bottomWrap {
+      position: relative;
+      .bottomBg {
+        width: 100%;
+      }
+      .logo {
+        width: 98px;
+        height: 32px;
+        position: absolute;
+        left: 50%;
+        margin-left: -49px;
+        top: 0;
+      }
+    }
   }
   .iconEdit {
     font-size: 24px;
@@ -450,3 +545,205 @@
     }
   }
 }
+
+.codeContainer {
+  .timerBg {
+    width: 131px;
+    height: 27px;
+    line-height: 27px;
+    text-align: center;
+    background: url('./images/timerBg.png');
+    background-size: 131px 27px;
+    position: absolute;
+    left: 25px;
+    top: 83px;
+    font-weight: 500;
+    color: #ffffff;
+    font-size: 12px;
+  }
+  .codeImg {
+    position: relative;
+    width: 315px;
+    height: 440px;
+    z-index: 9;
+    // background: url('./images/week/popup-week-banner.png') no-repeat top center;
+    // background-size: contain;
+    margin: 0 auto;
+    background-color: #ffffff;
+    border-radius: 8px;
+    overflow: hidden;
+    .popupWeekBanner {
+      width: 100%;
+      // position: absolute;
+      top: 0;
+      left: 0;
+      z-index: -1;
+    }
+
+    &.teacherCodeImg {
+      // background: url('./images/month/popup-week-banner.png') no-repeat top center;
+      // background-size: contain;
+      background-color: #ffffff;
+    }
+
+    .headerContantPopup {
+      padding-top: 23px;
+      padding-left: 18px;
+
+      .trainTimer {
+        &::before,
+        &::after {
+          display: none;
+        }
+        .point {
+          margin-left: 4px;
+          margin-right: 4px;
+          width: 6px;
+          height: 6px;
+        }
+      }
+    }
+
+    .codeTitle {
+      text-align: center;
+      padding-top: 13px;
+      font-size: 24px;
+      font-weight: bold;
+      color: #ffffff;
+      text-shadow: 1px 1px 7px #f4672a;
+      max-width: 90%;
+      padding-left: 5%;
+    }
+
+    .codeName {
+      padding: 36px 8px 0;
+      font-size: 18px;
+      font-weight: 600;
+      color: #ffffff;
+    }
+    .codeContent {
+      position: relative;
+      .schoolLogo {
+        width: 52px;
+        height: 52px;
+        border-radius: 50%;
+        overflow: hidden;
+        border: 3px solid #fff;
+        position: absolute;
+        top: -26px;
+        left: 50%;
+        margin-left: -26px;
+      }
+      .schoolName {
+        padding-top: 36px;
+        text-align: center;
+        font-weight: 500;
+        color: #000000;
+        line-height: 22px;
+        font-size: 16px;
+      }
+      .shareName {
+        padding-top: 4px;
+        font-size: 14px;
+
+        font-weight: 600;
+        color: #1b93ff;
+        line-height: 20px;
+        text-align: center;
+        padding-bottom: 12px;
+      }
+      .shareBottom {
+        width: 194px;
+        height: 38px;
+        margin: 16px auto 0;
+        display: block;
+      }
+      .codeQr {
+        position: relative;
+        margin: 0 auto 0;
+        width: 126px;
+        height: 126px;
+        padding: 12px;
+        // background: url('./images/popup-qrcode-bg.png') no-repeat center;
+        // background-size: contain;
+        border-radius: 11px;
+        overflow: hidden;
+        box-sizing: border-box;
+        img {
+          width: 100%;
+          height: 100%;
+        }
+
+        .popupQrcodeBg {
+          position: absolute;
+          top: 0;
+          left: 0;
+          width: 126px;
+          height: 126px;
+        }
+      }
+    }
+
+    .codeBtnText {
+      margin: 20px auto 0;
+      display: inline-block;
+      background: linear-gradient(
+        132deg,
+        rgba(199, 239, 243, 0.25) 0%,
+        rgba(229, 206, 251, 0.25) 40%,
+        rgba(147, 194, 254, 0.25) 100%
+      );
+      box-shadow: inset 0px 1px 0px 0px rgba(255, 255, 255, 0.62);
+      border-radius: 18px;
+      padding: 6px 16px;
+      font-size: 14px;
+      color: #000977;
+    }
+
+    .codeTips {
+      padding-top: 10px;
+      font-size: 13px;
+      font-weight: 600;
+      color: #f16437;
+      line-height: 18px;
+      text-align: center;
+    }
+  }
+  .close {
+    position: absolute;
+    top: 12px;
+    right: 15px;
+  }
+  .codeBottom {
+    position: relative;
+    margin-top: 32px;
+    background: #ffffff;
+    border-radius: 20px 20px 0px 0px;
+    padding-bottom: 10px;
+  }
+  .title {
+    font-size: 16px;
+    font-weight: 600;
+    color: #333333;
+    line-height: 22px;
+    padding: 15px 15px 0;
+    i {
+      display: inline-block;
+      margin-right: 6px;
+      width: 4px;
+      height: 12px;
+      background: #01c1b5;
+      border-radius: 2px;
+    }
+  }
+  .shareImg {
+    width: 47px;
+    height: 47px;
+  }
+  .shareText {
+    padding-top: 6px;
+    font-size: 14px;
+    color: #333333;
+    line-height: 20px;
+  }
+}

+ 171 - 134
src/views/activity-record/detail.tsx

@@ -10,9 +10,12 @@ import {
   showToast,
   showFailToast,
   showLoadingToast,
-  showSuccessToast
+  showSuccessToast,
+  Popup,
+  Grid,
+  GridItem
 } from 'vant';
-import { defineComponent, onMounted, reactive, ref } from 'vue';
+import { defineComponent, nextTick, onMounted, reactive, ref } from 'vue';
 import styles from './detail.module.less';
 import { browser, toChinesNum } from '@/helpers/utils';
 import SOLO from './images/SOLO.png';
@@ -30,8 +33,7 @@ import { formatterTimer } from './operation';
 import MPopup from '@/components/m-popup';
 import CastModal from './components/cast-modal';
 import iconEdit from './images/icon-edit.png';
-import { checkFile } from '@/helpers/toolsValidate';
-import iconVideoDefault from '@common/images/icon-video-c.png';
+
 import html2canvas from 'html2canvas';
 import { postMessage, promisefiyPostMessage } from '@/helpers/native-message';
 import backIcon from './images/back-icon.png';
@@ -47,12 +49,19 @@ import qBall from './images/q-ball.png';
 import cBall from './images/c-ball.png';
 import hBall from './images/h-ball.png';
 import dotIcon from './images/dot-icon.png';
+import Detailswiper from './detail-swiper';
+import bottomBg from './images/bottomBg.png';
+import logo from './images/logo.png';
+import MQrcode from '@/components/m-qrcode';
 import { state } from '@/state';
-import SwiperClass, { Navigation, Thumbs } from 'swiper';
-import { Swiper, SwiperSlide } from 'swiper/vue';
-import 'swiper/css';
-import 'swiper/css/navigation';
-import 'swiper/css/thumbs';
+import { useRect } from '@vant/use';
+import iconWechat from './images/iconWechat.png';
+import iconSaveImage from './images/iconSaveImage.png';
+import shareBg from './images/shareBg.png';
+import schoolIcon from './images/schoolIcon.png';
+import popupQrcodeBg from './images/popupQrcodeBg.png';
+import shareBottom from './images/shareBottom.png';
+import { vaildTeachingUrl } from '@/helpers/utils';
 export default defineComponent({
   name: 'detail-page',
   setup() {
@@ -73,11 +82,19 @@ export default defineComponent({
       studentAllList: [] as any,
       navBarHeight: state.navBarHeight
     });
-    const thumbsSwiper = ref<SwiperClass>();
-    const setThumbsSwiper = (swiper: SwiperClass) => {
-      thumbsSwiper.value = swiper;
-    };
-    const modules = [Navigation, Thumbs];
+
+    const shareForms = reactive({
+      id: route.query.id,
+      share: route.query.share as any,
+      showQrcode: false,
+      url:
+        vaildTeachingUrl() +
+        '/school/#/activity-record-detail' +
+        `?id=${route.query.id}`,
+      width: 0,
+      height: 0
+    });
+
     const getDetail = async () => {
       try {
         const { data } = await request.get(
@@ -186,6 +203,12 @@ export default defineComponent({
           });
       }
     };
+    const showImageToas = (obj: any) => {
+      forms.imagePreview = obj.imagePreview;
+      forms.imageShow = obj.imageShow;
+      forms.startPosition = obj.index;
+      console.log(forms.imagePreview, 'showImageToas', obj);
+    };
     const onShare = () => {
       console.log('onShare');
       if (imgs.shareLoading) {
@@ -267,7 +290,7 @@ export default defineComponent({
     };
 
     return () => (
-      <div class={styles.detail} id="preview-container">
+      <div class={styles.detail}>
         {/* <MHeader>
           {{
             right: () => (
@@ -296,37 +319,60 @@ export default defineComponent({
         <div
           class={styles.detailTop}
           style={{ 'padding-top': state.navBarHeight + 'px' }}>
-          <div
-            class={styles.fixWrap}
-            style={{ top: state.navBarHeight + 30 + 'px' }}>
-            <div class={styles.fixWrapLeft}>
-              <Image
-                src={backIcon}
-                onClick={() => {
-                  if (browser().isApp) {
-                    postMessage({
-                      api: 'goBack'
-                    });
-                  } else {
-                    router.back();
-                  }
-                }}></Image>
-            </div>
-            <div class={styles.fixWrapRight}>
-              <Image
-                src={eidtIcon}
-                class={styles.editIcon}
-                onClick={() => {
-                  router.push({
-                    path: '/activity-record-operation',
-                    query: {
-                      id: forms.id
-                    }
-                  });
-                }}></Image>
-              <Image src={shareIcon}></Image>
-            </div>
-          </div>
+          {browser().isApp ? (
+            <>
+              {' '}
+              <div
+                class={styles.fixWrap}
+                style={{ top: state.navBarHeight + 30 + 'px' }}>
+                <div class={styles.fixWrapLeft}>
+                  <Image
+                    src={backIcon}
+                    onClick={() => {
+                      if (browser().isApp) {
+                        postMessage({
+                          api: 'goBack'
+                        });
+                      } else {
+                        router.back();
+                      }
+                    }}></Image>
+                </div>
+                <div class={styles.fixWrapRight}>
+                  <Image
+                    src={eidtIcon}
+                    class={styles.editIcon}
+                    onClick={() => {
+                      router.push({
+                        path: '/activity-record-operation',
+                        query: {
+                          id: forms.id
+                        }
+                      });
+                    }}></Image>
+                  <Image
+                    src={shareIcon}
+                    onClick={() => {
+                      shareForms.showQrcode = true;
+                      nextTick(() => {
+                        const previewContainer = document.querySelector(
+                          '#preview-container'
+                        ) as HTMLElement;
+                        const share = useRect(previewContainer);
+                        shareForms.width = share.width;
+                        shareForms.height = share.height;
+                        if (share.width > 0 && share.height > 0) {
+                          previewContainer.style.width =
+                            Math.round(share.width) + 'px';
+                          previewContainer.style.height =
+                            Math.round(share.height) + 'px';
+                        }
+                      });
+                    }}></Image>
+                </div>
+              </div>
+            </>
+          ) : null}
           <div class={styles.wall}> </div>
           <Image src={jiemuIcon} class={styles.jiemuIcon}></Image>
           <div class={styles.typeCard}>
@@ -425,94 +471,9 @@ export default defineComponent({
                       </Col>
                     </Row>
                   </div>
-                  <div class={styles.progItemList}>
-                    <Swiper
-                      class="topSwiper"
-                      style={{
-                        '--swiper-navigation-color': '#fff',
-                        '--swiper-pagination-color': '#fff'
-                      }}
-                      modules={modules}
-                      space-between={10}
-                      ref={thumbsSwiper}>
-                      {item.attachmentUrl.map(
-                        (i: any, index: number) =>
-                          index <= 3 && (
-                            <SwiperSlide class="slide">
-                              <div
-                                class={styles.photo}
-                                onClick={() => {
-                                  forms.imagePreview = item.attachmentUrl;
-                                  forms.imageShow = true;
-                                  forms.startPosition = index;
-                                }}>
-                                {checkFile(i, 'image') ? (
-                                  <Image
-                                    src={i + '@base@tag=imgScale&w=120'}
-                                    fit="cover"
-                                  />
-                                ) : (
-                                  <video
-                                    style={{ backgroundColor: '#F8F8F8' }}
-                                    poster={iconVideoDefault}
-                                    src={i + '#t=1,4'}
-                                  />
-                                )}
-
-                                {item.attachmentUrl.length > 4 &&
-                                index === 3 ? (
-                                  <div class={styles.photoMore}>
-                                    +{item.attachmentUrl.length - 4}
-                                  </div>
-                                ) : (
-                                  ''
-                                )}
-                              </div>
-                            </SwiperSlide>
-                          )
-                      )}
-                    </Swiper>
-                    <Swiper
-                      class="thumbs-swiper"
-                      modules={modules}
-                      space-between={10}
-                      slides-per-view={4}
-                      watch-slides-progress={true}
-                      prevent-clicks={false}
-                      prevent-clicks-propagation={false}
-                      onSwiper={setThumbsSwiper}>
-                      {item.attachmentUrl.map(
-                        (i: any, index: number) =>
-                          index <= 3 && (
-                            <SwiperSlide class="slide">
-                              <div class={styles.photo}>
-                                {checkFile(i, 'image') ? (
-                                  <Image
-                                    src={i + '@base@tag=imgScale&w=120'}
-                                    fit="cover"
-                                  />
-                                ) : (
-                                  <video
-                                    style={{ backgroundColor: '#F8F8F8' }}
-                                    poster={iconVideoDefault}
-                                    src={i + '#t=1,4'}
-                                  />
-                                )}
-
-                                {item.attachmentUrl.length > 4 &&
-                                index === 3 ? (
-                                  <div class={styles.photoMore}>
-                                    +{item.attachmentUrl.length - 4}
-                                  </div>
-                                ) : (
-                                  ''
-                                )}
-                              </div>
-                            </SwiperSlide>
-                          )
-                      )}
-                    </Swiper>
-                  </div>
+                  <Detailswiper
+                    item={item}
+                    onShowImageToas={showImageToas}></Detailswiper>
                   {/* <CellGroup inset class={styles.pCellGroup}>
                     <Cell center>
                       {{
@@ -609,6 +570,13 @@ export default defineComponent({
                 </div>
               ))}
             </div>
+            <div class={styles.bottomWrap}>
+              {browser().isApp ? null : (
+                <Image class={styles.bottomBg} src={bottomBg}></Image>
+              )}
+
+              <Image class={styles.logo} src={logo}></Image>
+            </div>
           </div>
         </SkeletionDetailModal>
 
@@ -626,6 +594,75 @@ export default defineComponent({
             onClose={() => (forms.castStatus = false)}
           />
         </MPopup>
+
+        <Popup
+          v-model:show={shareForms.showQrcode}
+          position="bottom"
+          style={{ background: 'transparent' }}>
+          <div class={styles.codeContainer}>
+            <div
+              class={[styles.codeImg, styles.teacherCodeImg]}
+              id="preview-container">
+              <Image src={shareBg} class={styles.popupWeekBanner} />
+              <div class={styles.timerBg}>
+                {dayjs(forms.headerDetail.startTime).format('YYYY年MM月DD日')}
+              </div>
+              <div class={styles.codeContent}>
+                <Image
+                  class={styles.schoolLogo}
+                  src={
+                    forms.headerDetail?.cooperationOrganLogo
+                      ? forms.headerDetail?.cooperationOrganLogo
+                      : schoolIcon
+                  }></Image>
+                <div class={styles.schoolName}>
+                  {forms.headerDetail?.cooperationOrganName || '武汉小学'}
+                </div>
+                <div class={styles.shareName}>{forms.headerDetail.name}</div>
+                <div class={styles.codeQr}>
+                  <Image src={popupQrcodeBg} class={styles.popupQrcodeBg} />
+                  <MQrcode
+                    text={shareForms.url}
+                    size={'100%'}
+                    logoSize="small"
+                  />
+                </div>
+                <Image src={shareBottom} class={styles.shareBottom}></Image>
+              </div>
+            </div>
+            <div class={styles.codeBottom}>
+              <Icon
+                name="cross"
+                size={22}
+                class={styles.close}
+                color="#666"
+                onClick={() => (shareForms.showQrcode = false)}
+              />
+
+              <h3 class={styles.title}>
+                <i></i>分享方式
+              </h3>
+              <Grid columnNum={2} border={false}>
+                <GridItem onClick={onSaveImg}>
+                  {{
+                    icon: () => (
+                      <Image class={styles.shareImg} src={iconSaveImage} />
+                    ),
+                    text: () => <div class={styles.shareText}>保存图片</div>
+                  }}
+                </GridItem>
+                <GridItem onClick={onShare}>
+                  {{
+                    icon: () => (
+                      <Image class={styles.shareImg} src={iconWechat} />
+                    ),
+                    text: () => <div class={styles.shareText}>微信</div>
+                  }}
+                </GridItem>
+              </Grid>
+            </div>
+          </div>
+        </Popup>
       </div>
     );
   }

BIN
src/views/activity-record/images/array-icon.png


BIN
src/views/activity-record/images/bottomBg.png


BIN
src/views/activity-record/images/iconSaveImage.png


BIN
src/views/activity-record/images/iconWechat.png


BIN
src/views/activity-record/images/logo.png


BIN
src/views/activity-record/images/palyBtn.png


BIN
src/views/activity-record/images/popupQrcodeBg.png


BIN
src/views/activity-record/images/schoolIcon.png


BIN
src/views/activity-record/images/shareBg.png


BIN
src/views/activity-record/images/shareBottom.png


BIN
src/views/activity-record/images/timerBg.png


+ 1 - 1
src/views/activity-record/skeletion-detail-modal.tsx

@@ -47,7 +47,7 @@ export default defineComponent({
               }}>
               {props.showCount.map(() => (
                 <>
-                  <SkeletonParagraph rowWidth={'20%'} class={styles.pTitle} />
+                  {/* <SkeletonParagraph rowWidth={'20%'} class={styles.pTitle} /> */}
 
                   <CellGroup inset class={styles.pCellGroup}>
                     <Cell center>