Showing
20 changed files
with
825 additions
and
54 deletions
| ... | @@ -8,10 +8,10 @@ VITE_PROXY_TARGET = http://voice.onwall.cn | ... | @@ -8,10 +8,10 @@ VITE_PROXY_TARGET = http://voice.onwall.cn |
| 8 | VITE_PROXY_PREFIX = /srv/ | 8 | VITE_PROXY_PREFIX = /srv/ |
| 9 | 9 | ||
| 10 | # 打包输出文件夹名称 | 10 | # 打包输出文件夹名称 |
| 11 | -VITE_OUTDIR = voice | 11 | +VITE_OUTDIR = carbon |
| 12 | 12 | ||
| 13 | # 是否开启调试 | 13 | # 是否开启调试 |
| 14 | -VITE_CONSOLE = 0 | 14 | +VITE_CONSOLE = 1 |
| 15 | 15 | ||
| 16 | # appID相关 | 16 | # appID相关 |
| 17 | VITE_APPID=微信appID | 17 | VITE_APPID=微信appID | ... | ... |
| ... | @@ -7,37 +7,12 @@ export {} | ... | @@ -7,37 +7,12 @@ export {} |
| 7 | 7 | ||
| 8 | declare module 'vue' { | 8 | declare module 'vue' { |
| 9 | export interface GlobalComponents { | 9 | export interface GlobalComponents { |
| 10 | - '图形验证码': typeof import('./src/components/图形验证码.vue')['default'] | 10 | + Danmaku: typeof import('./src/components/danmaku.vue')['default'] |
| 11 | - Agreement: typeof import('./src/components/DonateFlower/agreement.vue')['default'] | ||
| 12 | - AuditVideoCard: typeof import('./src/components/AuditVideoCard/index.vue')['default'] | ||
| 13 | - Banner: typeof import('./src/components/MuiVideo/banner.vue')['default'] | ||
| 14 | - BookCard: typeof import('./src/components/BookCard/index.vue')['default'] | ||
| 15 | - BVideoCard: typeof import('./src/components/BVideoCard/index.vue')['default'] | ||
| 16 | - CommentBox: typeof import('./src/components/CommentBox/index.vue')['default'] | ||
| 17 | - CommentList: typeof import('./src/components/CommentList/index.vue')['default'] | ||
| 18 | - DonateBar: typeof import('./src/components/DonateBar/index.vue')['default'] | ||
| 19 | - DonateBook: typeof import('./src/components/DonateBook/index.vue')['default'] | ||
| 20 | - DonateCert: typeof import('./src/components/DonateCert/index.vue')['default'] | ||
| 21 | - DonateCertPost: typeof import('./src/components/DonateCertPost/index.vue')['default'] | ||
| 22 | - DonateFlower: typeof import('./src/components/DonateFlower/index.vue')['default'] | ||
| 23 | - FlowerIcon: typeof import('./src/components/FlowerIcon/index.vue')['default'] | ||
| 24 | - ImageSliderVerify: typeof import('./src/components/ImageSliderVerify/index.vue')['default'] | ||
| 25 | - LocalismBox: typeof import('./src/components/LocalismBox/index.vue')['default'] | ||
| 26 | - LoginBox: typeof import('./src/components/LoginBox/index.vue')['default'] | ||
| 27 | - MuiVideo: typeof import('./src/components/MuiVideo/index.vue')['default'] | ||
| 28 | - MyButton: typeof import('./src/components/MyButton/index.vue')['default'] | ||
| 29 | - NoticeOverlay: typeof import('./src/components/NoticeOverlay/index.vue')['default'] | ||
| 30 | - NoticeOverlayModule: typeof import('./src/components/NoticeOverlayModule/index.vue')['default'] | ||
| 31 | - RankingItem: typeof import('./src/components/RankingItem/index.vue')['default'] | ||
| 32 | - RightSideList: typeof import('./src/components/RightSideList/index.vue')['default'] | ||
| 33 | RouterLink: typeof import('vue-router')['RouterLink'] | 11 | RouterLink: typeof import('vue-router')['RouterLink'] |
| 34 | RouterView: typeof import('vue-router')['RouterView'] | 12 | RouterView: typeof import('vue-router')['RouterView'] |
| 35 | - ShortcutFixed: typeof import('./src/components/ShortcutFixed/index.vue')['default'] | 13 | + VanIcon: typeof import('vant/es')['Icon'] |
| 36 | - Status: typeof import('./src/components/MuiVideo/status.vue')['default'] | 14 | + VanImage: typeof import('vant/es')['Image'] |
| 37 | - Template: typeof import('./src/components/template/index.vue')['default'] | 15 | + VanLoading: typeof import('vant/es')['Loading'] |
| 38 | - Test: typeof import('./src/components/LoginBox/test.vue')['default'] | 16 | + VanUploader: typeof import('vant/es')['Uploader'] |
| 39 | - VideoBar: typeof import('./src/components/MuiVideo/videoBar.vue')['default'] | ||
| 40 | - VideoCard: typeof import('./src/components/VideoCard/index.vue')['default'] | ||
| 41 | - VideoDetail: typeof import('./src/components/VideoDetail/index.vue')['default'] | ||
| 42 | } | 17 | } |
| 43 | } | 18 | } | ... | ... |
| ... | @@ -28,6 +28,7 @@ | ... | @@ -28,6 +28,7 @@ |
| 28 | "vite-plugin-dynamic-import": "^0.9.6", | 28 | "vite-plugin-dynamic-import": "^0.9.6", |
| 29 | "vite-plugin-mp": "^1.6.1", | 29 | "vite-plugin-mp": "^1.6.1", |
| 30 | "vue": "^3.2.36", | 30 | "vue": "^3.2.36", |
| 31 | + "vue3-danmaku": "^1.6.0", | ||
| 31 | "weixin-js-sdk": "^1.6.5" | 32 | "weixin-js-sdk": "^1.6.5" |
| 32 | }, | 33 | }, |
| 33 | "devDependencies": { | 34 | "devDependencies": { |
| ... | @@ -5928,6 +5929,14 @@ | ... | @@ -5928,6 +5929,14 @@ |
| 5928 | "vue": "^3.2.0" | 5929 | "vue": "^3.2.0" |
| 5929 | } | 5930 | } |
| 5930 | }, | 5931 | }, |
| 5932 | + "node_modules/vue3-danmaku": { | ||
| 5933 | + "version": "1.6.0", | ||
| 5934 | + "resolved": "https://mirrors.cloud.tencent.com/npm/vue3-danmaku/-/vue3-danmaku-1.6.0.tgz", | ||
| 5935 | + "integrity": "sha512-XjwVKIelupDD3PWn6k22l5qS8y+SCdFUYq4sSpcPInqk7CyzXWSAfz2BL6WWx9HU9CRWS3x2oDMkepLkJoWvNQ==", | ||
| 5936 | + "peerDependencies": { | ||
| 5937 | + "vue": "^3.0.0" | ||
| 5938 | + } | ||
| 5939 | + }, | ||
| 5931 | "node_modules/webpack-sources": { | 5940 | "node_modules/webpack-sources": { |
| 5932 | "version": "3.2.3", | 5941 | "version": "3.2.3", |
| 5933 | "resolved": "https://mirrors.cloud.tencent.com/npm/webpack-sources/-/webpack-sources-3.2.3.tgz", | 5942 | "resolved": "https://mirrors.cloud.tencent.com/npm/webpack-sources/-/webpack-sources-3.2.3.tgz", |
| ... | @@ -10380,6 +10389,12 @@ | ... | @@ -10380,6 +10389,12 @@ |
| 10380 | "@vue/devtools-api": "^6.5.0" | 10389 | "@vue/devtools-api": "^6.5.0" |
| 10381 | } | 10390 | } |
| 10382 | }, | 10391 | }, |
| 10392 | + "vue3-danmaku": { | ||
| 10393 | + "version": "1.6.0", | ||
| 10394 | + "resolved": "https://mirrors.cloud.tencent.com/npm/vue3-danmaku/-/vue3-danmaku-1.6.0.tgz", | ||
| 10395 | + "integrity": "sha512-XjwVKIelupDD3PWn6k22l5qS8y+SCdFUYq4sSpcPInqk7CyzXWSAfz2BL6WWx9HU9CRWS3x2oDMkepLkJoWvNQ==", | ||
| 10396 | + "requires": {} | ||
| 10397 | + }, | ||
| 10383 | "webpack-sources": { | 10398 | "webpack-sources": { |
| 10384 | "version": "3.2.3", | 10399 | "version": "3.2.3", |
| 10385 | "resolved": "https://mirrors.cloud.tencent.com/npm/webpack-sources/-/webpack-sources-3.2.3.tgz", | 10400 | "resolved": "https://mirrors.cloud.tencent.com/npm/webpack-sources/-/webpack-sources-3.2.3.tgz", | ... | ... |
| ... | @@ -9,7 +9,13 @@ | ... | @@ -9,7 +9,13 @@ |
| 9 | "build-watch": "vite build --watch", | 9 | "build-watch": "vite build --watch", |
| 10 | "build-ts": "vue-tsc --noEmit && vite build", | 10 | "build-ts": "vue-tsc --noEmit && vite build", |
| 11 | "serve": "vite preview", | 11 | "serve": "vite preview", |
| 12 | - "cypress:open": "cypress open" | 12 | + "cypress:open": "cypress open", |
| 13 | + "tar": "tar -czvpf dist.tar.gz carbon", | ||
| 14 | + "build_tar": "npm run build && npm run tar", | ||
| 15 | + "scp-oa": "scp dist.tar.gz itomix@ipadbiz.cn:/opt/voice/f/", | ||
| 16 | + "dec-oa": "ssh itomix@ipadbiz.cn 'cd /opt/voice/f/ && tar -xzvf dist.tar.gz && rm -rf dist.tar.gz'", | ||
| 17 | + "remove_tar": "rm -rf dist.tar.gz", | ||
| 18 | + "oa_upload": "npm run build_tar && npm run scp-oa && npm run dec-oa && npm run remove_tar" | ||
| 13 | }, | 19 | }, |
| 14 | "dependencies": { | 20 | "dependencies": { |
| 15 | "@vitejs/plugin-legacy": "^1.8.2", | 21 | "@vitejs/plugin-legacy": "^1.8.2", |
| ... | @@ -32,6 +38,7 @@ | ... | @@ -32,6 +38,7 @@ |
| 32 | "vite-plugin-dynamic-import": "^0.9.6", | 38 | "vite-plugin-dynamic-import": "^0.9.6", |
| 33 | "vite-plugin-mp": "^1.6.1", | 39 | "vite-plugin-mp": "^1.6.1", |
| 34 | "vue": "^3.2.36", | 40 | "vue": "^3.2.36", |
| 41 | + "vue3-danmaku": "^1.6.0", | ||
| 35 | "weixin-js-sdk": "^1.6.5" | 42 | "weixin-js-sdk": "^1.6.5" |
| 36 | }, | 43 | }, |
| 37 | "devDependencies": { | 44 | "devDependencies": { | ... | ... |
| ... | @@ -14,7 +14,7 @@ set -e | ... | @@ -14,7 +14,7 @@ set -e |
| 14 | path=/Users/huyirui/program/itomix/git/isp/f | 14 | path=/Users/huyirui/program/itomix/git/isp/f |
| 15 | 15 | ||
| 16 | # 编译输出文件夹 | 16 | # 编译输出文件夹 |
| 17 | -output=voice | 17 | +output=carbon |
| 18 | 18 | ||
| 19 | # 打包 | 19 | # 打包 |
| 20 | npm run build | 20 | npm run build |
| ... | @@ -37,4 +37,4 @@ git commit -m '前端网页更新' | ... | @@ -37,4 +37,4 @@ git commit -m '前端网页更新' |
| 37 | git push | 37 | git push |
| 38 | 38 | ||
| 39 | # 更新SSH服务器上文件 | 39 | # 更新SSH服务器上文件 |
| 40 | -# ssh -p 22 itomix@ipadbiz.cn 'cd /opt/voice/f/voice && git pull'`` | 40 | +# ssh -p 22 itomix@ipadbiz.cn 'cd /opt/voice/f/carbon && git pull'`` | ... | ... |
| ... | @@ -2,8 +2,8 @@ | ... | @@ -2,8 +2,8 @@ |
| 2 | * @Author: hookehuyr hookehuyr@gmail.com | 2 | * @Author: hookehuyr hookehuyr@gmail.com |
| 3 | * @Date: 2022-05-26 23:52:36 | 3 | * @Date: 2022-05-26 23:52:36 |
| 4 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 4 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 5 | - * @LastEditTime: 2024-01-02 13:59:58 | 5 | + * @LastEditTime: 2024-04-11 09:50:51 |
| 6 | - * @FilePath: /tswj/src/App.vue | 6 | + * @FilePath: /fxPark/src/App.vue |
| 7 | * @Description: | 7 | * @Description: |
| 8 | --> | 8 | --> |
| 9 | <template> | 9 | <template> | ... | ... |
| ... | @@ -2,8 +2,8 @@ | ... | @@ -2,8 +2,8 @@ |
| 2 | * @Author: hookehuyr hookehuyr@gmail.com | 2 | * @Author: hookehuyr hookehuyr@gmail.com |
| 3 | * @Date: 2022-06-09 13:32:44 | 3 | * @Date: 2022-06-09 13:32:44 |
| 4 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 4 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 5 | - * @LastEditTime: 2022-06-14 14:47:01 | 5 | + * @LastEditTime: 2024-04-11 06:06:06 |
| 6 | - * @FilePath: /tswj/src/api/wx/config.js | 6 | + * @FilePath: /fxPark/src/api/wx/config.js |
| 7 | * @Description: | 7 | * @Description: |
| 8 | */ | 8 | */ |
| 9 | import { fn, fetch } from '@/api/fn'; | 9 | import { fn, fetch } from '@/api/fn'; | ... | ... |
src/components/danmaku.vue
0 → 100644
| 1 | +<!-- | ||
| 2 | + * @Date: 2024-04-10 14:16:36 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2024-04-10 14:22:14 | ||
| 5 | + * @FilePath: /fxPark/src/components/danmaku.vue | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | +--> | ||
| 8 | +<template> | ||
| 9 | + <div class="danmaku-page"> | ||
| 10 | + <vue-danmaku ref="danmaku" v-model:danmus="danmus" useSlot loop :channels="4" :speeds="50" :top="20" style="height:12rem; width:100vw; position: absolute; top:0; z-index: 10;"> | ||
| 11 | + <template v-slot:dm="{ index, danmu }"> | ||
| 12 | + <span style="background-color: rgba(48, 48, 48, 0.50); padding: 0.25rem 1rem; border-radius: 14px;">{{ index }}{{ danmu.name }}:{{ danmu.text }}</span> | ||
| 13 | + </template> | ||
| 14 | + </vue-danmaku> | ||
| 15 | + </div> | ||
| 16 | +</template> | ||
| 17 | + | ||
| 18 | +<script setup> | ||
| 19 | +import { ref } from 'vue' | ||
| 20 | +import { useRoute, useRouter } from 'vue-router' | ||
| 21 | + | ||
| 22 | +import vueDanmaku from 'vue3-danmaku' | ||
| 23 | +import { Cookies, $, _, axios, storeToRefs, mainStore, Toast, useTitle } from '@/utils/generatePackage.js' | ||
| 24 | +//import { } from '@/utils/generateModules.js' | ||
| 25 | +//import { } from '@/utils/generateIcons.js' | ||
| 26 | +//import { } from '@/composables' | ||
| 27 | +const $route = useRoute(); | ||
| 28 | +const $router = useRouter(); | ||
| 29 | +useTitle($route.meta.title); | ||
| 30 | + | ||
| 31 | +const danmaku = ref(null) | ||
| 32 | +const danmus = ref([{ avatar: 'http://a.com/a.jpg', name: 'a', text: 'aaa' }, { avatar: 'http://a.com/b.jpg', name: 'b', text: 'bbb' }]) | ||
| 33 | + | ||
| 34 | +</script> | ||
| 35 | + | ||
| 36 | +<style lang="less" scoped> | ||
| 37 | +.danmaku-page {} | ||
| 38 | +</style> |
| 1 | /* | 1 | /* |
| 2 | * @Date: 2024-04-07 10:14:17 | 2 | * @Date: 2024-04-07 10:14:17 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2024-04-07 10:28:36 | 4 | + * @LastEditTime: 2024-04-11 09:39:29 |
| 5 | * @FilePath: /fxPark/src/router/routes/modules/fxPark/index.js | 5 | * @FilePath: /fxPark/src/router/routes/modules/fxPark/index.js |
| 6 | * @Description: 文件描述 | 6 | * @Description: 文件描述 |
| 7 | */ | 7 | */ |
| 8 | const index = [{ | 8 | const index = [{ |
| 9 | - path: '/fxPark', | 9 | + path: '/', |
| 10 | name: '“碳”寻复兴公园', | 10 | name: '“碳”寻复兴公园', |
| 11 | component: () => import('@/views/fxPark/index.vue'), | 11 | component: () => import('@/views/fxPark/index.vue'), |
| 12 | redirect: '', | 12 | redirect: '', |
| ... | @@ -14,6 +14,42 @@ const index = [{ | ... | @@ -14,6 +14,42 @@ const index = [{ |
| 14 | title: '“碳”寻复兴公园', | 14 | title: '“碳”寻复兴公园', |
| 15 | }, | 15 | }, |
| 16 | children: [], | 16 | children: [], |
| 17 | +}, { | ||
| 18 | + path: '/audio', | ||
| 19 | + name: '植物之声', | ||
| 20 | + component: () => import('@/views/fxPark/audio.vue'), | ||
| 21 | + redirect: '', | ||
| 22 | + meta: { | ||
| 23 | + title: '植物之声', | ||
| 24 | + }, | ||
| 25 | + children: [], | ||
| 26 | +}, { | ||
| 27 | + path: '/intro', | ||
| 28 | + name: '植被介绍', | ||
| 29 | + component: () => import('@/views/fxPark/intro.vue'), | ||
| 30 | + redirect: '', | ||
| 31 | + meta: { | ||
| 32 | + title: '植被介绍', | ||
| 33 | + }, | ||
| 34 | + children: [], | ||
| 35 | +}, { | ||
| 36 | + path: '/share', | ||
| 37 | + name: '生成海报±', | ||
| 38 | + component: () => import('@/views/fxPark/share.vue'), | ||
| 39 | + redirect: '', | ||
| 40 | + meta: { | ||
| 41 | + title: '生成海报±', | ||
| 42 | + }, | ||
| 43 | + children: [], | ||
| 44 | +}, { | ||
| 45 | + path: '/poster', | ||
| 46 | + name: '生成海报', | ||
| 47 | + component: () => import('@/views/fxPark/poster.vue'), | ||
| 48 | + redirect: '', | ||
| 49 | + meta: { | ||
| 50 | + title: '生成海报', | ||
| 51 | + }, | ||
| 52 | + children: [], | ||
| 17 | },] | 53 | },] |
| 18 | 54 | ||
| 19 | export default index; | 55 | export default index; | ... | ... |
| ... | @@ -2,8 +2,8 @@ | ... | @@ -2,8 +2,8 @@ |
| 2 | * @Author: hookehuyr hookehuyr@gmail.com | 2 | * @Author: hookehuyr hookehuyr@gmail.com |
| 3 | * @Date: 2022-05-28 10:17:40 | 3 | * @Date: 2022-05-28 10:17:40 |
| 4 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 4 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 5 | - * @LastEditTime: 2024-01-02 18:02:31 | 5 | + * @LastEditTime: 2024-04-10 17:37:44 |
| 6 | - * @FilePath: /tswj/src/utils/axios.js | 6 | + * @FilePath: /fxPark/src/utils/axios.js |
| 7 | * @Description: | 7 | * @Description: |
| 8 | */ | 8 | */ |
| 9 | import axios from 'axios'; | 9 | import axios from 'axios'; |
| ... | @@ -13,7 +13,8 @@ import { strExist } from '@/utils/tools' | ... | @@ -13,7 +13,8 @@ import { strExist } from '@/utils/tools' |
| 13 | // import { parseQueryString } from '@/utils/tools' | 13 | // import { parseQueryString } from '@/utils/tools' |
| 14 | 14 | ||
| 15 | axios.defaults.params = { | 15 | axios.defaults.params = { |
| 16 | - f: 'voice', | 16 | + f: 'carbon', |
| 17 | + client_id: 313939, | ||
| 17 | }; | 18 | }; |
| 18 | 19 | ||
| 19 | /** | 20 | /** | ... | ... |
| ... | @@ -17,7 +17,7 @@ onMounted(() => { | ... | @@ -17,7 +17,7 @@ onMounted(() => { |
| 17 | */ | 17 | */ |
| 18 | let raw_url = encodeURIComponent(location.origin + location.pathname + $route.query.href); // 未授权的地址 | 18 | let raw_url = encodeURIComponent(location.origin + location.pathname + $route.query.href); // 未授权的地址 |
| 19 | // TAG: 开发环境测试数据 | 19 | // TAG: 开发环境测试数据 |
| 20 | - const short_url = `/srv/?f=voice&a=openid_${$route.query.prefixAPI}&res=${raw_url}`; | 20 | + const short_url = `/srv/?f=carbon&a=openid_c&res=${raw_url}`; |
| 21 | location.href = import.meta.env.DEV | 21 | location.href = import.meta.env.DEV |
| 22 | ? `${short_url}&input_openid=${import.meta.env.VITE_OPENID}` | 22 | ? `${short_url}&input_openid=${import.meta.env.VITE_OPENID}` |
| 23 | : `${short_url}`; | 23 | : `${short_url}`; | ... | ... |
src/views/fxPark/audio.vue
0 → 100644
| 1 | +<!-- | ||
| 2 | + * @Date: 2024-04-10 15:08:08 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2024-04-10 15:54:46 | ||
| 5 | + * @FilePath: /fxPark/src/views/fxPark/audio.vue | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | +--> | ||
| 8 | +<template> | ||
| 9 | + <div class="audio-page"> | ||
| 10 | + <div class="audio-player"> | ||
| 11 | + <div style="margin-right: 1rem;"> | ||
| 12 | + <van-icon name="circle" size="5rem" /> | ||
| 13 | + </div> | ||
| 14 | + <div> | ||
| 15 | + <div style="margin-bottom: 1rem;">微风轻轻吹树叶的声音</div> | ||
| 16 | + <div style="display: flex; justify-content: space-between;"> | ||
| 17 | + <van-icon name="arrow-left" size="1.5rem" /> | ||
| 18 | + <van-icon name="play" size="1.5rem" @click="audioPlayer.play()" /> | ||
| 19 | + <van-icon name="pause" size="1.5rem" @click="audioPlayer.pause()" /> | ||
| 20 | + <van-icon name="arrow" size="1.5rem" /> | ||
| 21 | + </div> | ||
| 22 | + </div> | ||
| 23 | + <div> | ||
| 24 | + <audio ref="audioPlayer" loop="loop" id="audios" src="https://m10.music.126.net/20240410161841/940e4a035f48a82b1b4d4b01b2e7b1f1/ymusic/5353/0f0f/0358/d99739615f8e5153d77042092f07fd77.mp3" preoload></audio> | ||
| 25 | + </div> | ||
| 26 | + </div> | ||
| 27 | + </div> | ||
| 28 | +</template> | ||
| 29 | + | ||
| 30 | +<script setup> | ||
| 31 | +import { ref } from 'vue' | ||
| 32 | +import { useRoute, useRouter } from 'vue-router' | ||
| 33 | + | ||
| 34 | +import { Cookies, $, _, axios, storeToRefs, mainStore, Toast, useTitle } from '@/utils/generatePackage.js' | ||
| 35 | +//import { } from '@/utils/generateModules.js' | ||
| 36 | +//import { } from '@/utils/generateIcons.js' | ||
| 37 | +//import { } from '@/composables' | ||
| 38 | +const $route = useRoute(); | ||
| 39 | +const $router = useRouter(); | ||
| 40 | +useTitle($route.meta.title); | ||
| 41 | + | ||
| 42 | +const audioPlayer = ref(null); | ||
| 43 | + | ||
| 44 | +</script> | ||
| 45 | + | ||
| 46 | +<style lang="less" scoped> | ||
| 47 | +.audio-page { | ||
| 48 | + height: 100vh; | ||
| 49 | + position: relative; | ||
| 50 | + background-color: #47A3E4; | ||
| 51 | + display: flex; | ||
| 52 | + justify-content: center; | ||
| 53 | + .audio-player { | ||
| 54 | + border: 1px solid #fff; | ||
| 55 | + border-radius: 10px; | ||
| 56 | + padding: 1rem 2rem 1rem 1rem; | ||
| 57 | + position: absolute; | ||
| 58 | + top: 5rem; | ||
| 59 | + display: flex; | ||
| 60 | + justify-content: center; | ||
| 61 | + align-items: center; | ||
| 62 | + } | ||
| 63 | +} | ||
| 64 | +</style> |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2024-04-07 10:15:55 | 2 | * @Date: 2024-04-07 10:15:55 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2024-04-07 10:19:13 | 4 | + * @LastEditTime: 2024-04-10 15:01:38 |
| 5 | * @FilePath: /fxPark/src/views/fxPark/index.vue | 5 | * @FilePath: /fxPark/src/views/fxPark/index.vue |
| 6 | * @Description: 文件描述 | 6 | * @Description: 文件描述 |
| 7 | --> | 7 | --> |
| 8 | <template> | 8 | <template> |
| 9 | - <div class="">123</div> | 9 | + <div class="fxPark-page"> |
| 10 | + <danmaku /> | ||
| 11 | + <div class="quick-entrance-wrapper"> | ||
| 12 | + <div class="quick-entrance-item" style=""> | ||
| 13 | + <van-icon name="chat-o" /> <span>植物之声</span> | ||
| 14 | + </div> | ||
| 15 | + </div> | ||
| 16 | + <div class="container" v-for="(item, index) in img_list" :key="index" @click="onClick(item)"> | ||
| 17 | + <img :src="item.src" class="img"> | ||
| 18 | + </div> | ||
| 19 | + </div> | ||
| 10 | </template> | 20 | </template> |
| 11 | 21 | ||
| 12 | <script setup> | 22 | <script setup> |
| ... | @@ -17,12 +27,76 @@ import { Cookies, $, _, axios, storeToRefs, mainStore, Toast, useTitle } from '@ | ... | @@ -17,12 +27,76 @@ import { Cookies, $, _, axios, storeToRefs, mainStore, Toast, useTitle } from '@ |
| 17 | //import { } from '@/utils/generateModules.js' | 27 | //import { } from '@/utils/generateModules.js' |
| 18 | //import { } from '@/utils/generateIcons.js' | 28 | //import { } from '@/utils/generateIcons.js' |
| 19 | //import { } from '@/composables' | 29 | //import { } from '@/composables' |
| 30 | +import danmaku from '@/components/danmaku.vue' | ||
| 31 | + | ||
| 32 | +// 初始化WX环境 | ||
| 33 | +import wx from 'weixin-js-sdk' | ||
| 34 | + | ||
| 20 | const $route = useRoute(); | 35 | const $route = useRoute(); |
| 21 | const $router = useRouter(); | 36 | const $router = useRouter(); |
| 22 | useTitle($route.meta.title); | 37 | useTitle($route.meta.title); |
| 23 | 38 | ||
| 39 | +const img_list = ref([{ | ||
| 40 | + src:'https://cdn.ipadbiz.cn/tmp/fx_park/s1.png' , | ||
| 41 | +}, { | ||
| 42 | + src:'https://cdn.ipadbiz.cn/tmp/fx_park/s2.png' , | ||
| 43 | +}, { | ||
| 44 | + src:'https://cdn.ipadbiz.cn/tmp/fx_park/s3.png' , | ||
| 45 | +}, { | ||
| 46 | + src:'https://cdn.ipadbiz.cn/tmp/fx_park/s4.png' , | ||
| 47 | +}, { | ||
| 48 | + src:'https://cdn.ipadbiz.cn/tmp/fx_park/s5.png' , | ||
| 49 | +}, { | ||
| 50 | + src:'https://cdn.ipadbiz.cn/tmp/fx_park/s6.png' , | ||
| 51 | +},]) | ||
| 52 | + | ||
| 53 | +const onClick = (item) => { | ||
| 54 | + wx.scanQRCode({ | ||
| 55 | + needResult: 1, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果, | ||
| 56 | + scanType: ["qrCode","barCode"], // 可以指定扫二维码还是一维码,默认二者都有 | ||
| 57 | + success: function (res) { | ||
| 58 | + var result = res.resultStr; // 当needResult 为 1 时,扫码返回的结果 | ||
| 59 | + console.log("🚀 ~ file: index.vue:73 ~ onClick ~ result:", result); | ||
| 60 | + }, | ||
| 61 | + fail: function (res) { | ||
| 62 | + console.log("🚀 ~ file: index.vue:77 ~ onClick ~ res:", res); | ||
| 63 | + } | ||
| 64 | + }); | ||
| 65 | +} | ||
| 24 | </script> | 66 | </script> |
| 25 | 67 | ||
| 26 | <style lang="less" scoped> | 68 | <style lang="less" scoped> |
| 27 | - | 69 | +.fxPark-page { |
| 70 | + .quick-entrance-wrapper { | ||
| 71 | + .quick-entrance-item { | ||
| 72 | + position: absolute; | ||
| 73 | + right: 0; | ||
| 74 | + top: 1.5rem; | ||
| 75 | + color: white; | ||
| 76 | + background-color: green; | ||
| 77 | + border-top-left-radius: 1rem; | ||
| 78 | + border-bottom-left-radius: 1rem; | ||
| 79 | + z-index: 20; | ||
| 80 | + font-size: 0.9rem; | ||
| 81 | + padding: 0.5rem; | ||
| 82 | + } | ||
| 83 | + } | ||
| 84 | + .container { | ||
| 85 | + width: 100%; | ||
| 86 | + height: 100%; | ||
| 87 | + background-size: contain; | ||
| 88 | + position: absolute; | ||
| 89 | + z-index: 1; | ||
| 90 | + top: 0; | ||
| 91 | + left: 0; | ||
| 92 | + background-repeat: no-repeat; | ||
| 93 | + .img { | ||
| 94 | + position: absolute; | ||
| 95 | + top: 0; | ||
| 96 | + left: 0; | ||
| 97 | + width: 100%; | ||
| 98 | + object-fit: cover; | ||
| 99 | + } | ||
| 100 | + } | ||
| 101 | +} | ||
| 28 | </style> | 102 | </style> | ... | ... |
src/views/fxPark/intro.vue
0 → 100644
| 1 | +<!-- | ||
| 2 | + * @Date: 2024-04-10 16:08:09 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2024-04-10 17:24:25 | ||
| 5 | + * @FilePath: /fxPark/src/views/fxPark/intro.vue | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | +--> | ||
| 8 | +<template> | ||
| 9 | + <div class="intro-page"> | ||
| 10 | + <div></div> | ||
| 11 | + <div style="margin: 1rem;"> | ||
| 12 | + <div style="margin-bottom: 1rem;"> | ||
| 13 | + <span style="font-size: 1.25rem;">悬铃木</span> | ||
| 14 | + <span style="font-size: 0.85rem;">智者长老</span> | ||
| 15 | + </div> | ||
| 16 | + <div style="border: 1px solid #000; padding: 1rem; border-radius: 8px;"> | ||
| 17 | + <div style="margin-bottom: 1.5rem;"><span style="background-color: #D0FCF0; padding: 0.5rem 0.75rem; border-radius: 1rem;">植被类型:</span> 待补充</div> | ||
| 18 | + <div style="margin-bottom: 1.5rem;"><span style="background-color: #D0FCF0; padding: 0.5rem 0.75rem; border-radius: 1rem;">植被学名:</span> 待补充</div> | ||
| 19 | + <div style="margin-bottom: 1.5rem;"> | ||
| 20 | + 截至2022年累计固定二氧化碳约7.7吨,可抵消用煤炭发电7.7万度所排放的二氧化碳量,或者可抵消一辆轻型汽车行驶绕地球1周排放的二氧化碳量。 | ||
| 21 | + </div> | ||
| 22 | + <div style="margin-bottom: 1rem;"><span style="background-color: #D0FCF0; padding: 0.5rem 0.75rem; border-radius: 1rem;">植被介绍:</span></div> | ||
| 23 | + <div> | ||
| 24 | + 这棵悬铃木已经有120岁,胸径为123cm,被称为“沪上老二”,拥有悠久的历史和深厚的底蕴。<br/> | ||
| 25 | + 悬铃木生长快,成型后树大荫浓,是作为庭荫树和行道树的优良树种,是上海最常见的行道树种之一。 | ||
| 26 | + </div> | ||
| 27 | + </div> | ||
| 28 | + </div> | ||
| 29 | + <div class="task-tips"> | ||
| 30 | + <div class="title-wrapper"> | ||
| 31 | + <span class="title-text">任务卡</span> | ||
| 32 | + </div> | ||
| 33 | + <div class="task-wrapper"> | ||
| 34 | + <div class="task-title">自带咖啡杯</div> | ||
| 35 | + <div>去咖啡店时自带咖啡杯,<br/>代替一次性纸杯。</div> | ||
| 36 | + </div> | ||
| 37 | + </div> | ||
| 38 | + <div class="light-up-text">恭喜您植被已被点亮</div> | ||
| 39 | + <div style="margin: 1rem 1rem 2rem 1rem; color: white; text-align: center;"> | ||
| 40 | + <div style="background-color: #F68015; display: inline-block; padding: 0.7rem 2rem; border-radius: 1.5rem;">生成海报</div> | ||
| 41 | + </div> | ||
| 42 | + </div> | ||
| 43 | +</template> | ||
| 44 | + | ||
| 45 | +<script setup> | ||
| 46 | +import { ref } from 'vue' | ||
| 47 | +import { useRoute, useRouter } from 'vue-router' | ||
| 48 | + | ||
| 49 | +import { Cookies, $, _, axios, storeToRefs, mainStore, Toast, useTitle } from '@/utils/generatePackage.js' | ||
| 50 | +//import { } from '@/utils/generateModules.js' | ||
| 51 | +//import { } from '@/utils/generateIcons.js' | ||
| 52 | +//import { } from '@/composables' | ||
| 53 | +const $route = useRoute(); | ||
| 54 | +const $router = useRouter(); | ||
| 55 | +useTitle($route.meta.title); | ||
| 56 | + | ||
| 57 | +</script> | ||
| 58 | + | ||
| 59 | +<style lang="less" scoped> | ||
| 60 | +.intro-page { | ||
| 61 | + display: flex; | ||
| 62 | + flex-direction: column; | ||
| 63 | + .task-tips { | ||
| 64 | + .title-wrapper { | ||
| 65 | + text-align: center; | ||
| 66 | + .title-text { | ||
| 67 | + font-size: 24px; | ||
| 68 | + font-weight: bold; | ||
| 69 | + color: #BBFEE2; /* 文字颜色 */ | ||
| 70 | + text-shadow: | ||
| 71 | + -1px -1px 0 #000, | ||
| 72 | + 1px -1px 0 #000, | ||
| 73 | + -1px 1px 0 #000, | ||
| 74 | + 1px 1px 0 #000; | ||
| 75 | + } | ||
| 76 | + } | ||
| 77 | + .task-wrapper { | ||
| 78 | + border: 1px solid #000; | ||
| 79 | + margin: 1rem; | ||
| 80 | + padding: 1rem; | ||
| 81 | + border-radius: 10px; | ||
| 82 | + background: linear-gradient(to bottom, #FBFFE9, #BEE9F8); | ||
| 83 | + text-align: center; | ||
| 84 | + .task-title { | ||
| 85 | + background-color: #D6F4BD; | ||
| 86 | + padding: 0.5rem 1.5rem; | ||
| 87 | + border-radius: 1.5rem; | ||
| 88 | + display: inline-block; | ||
| 89 | + font-weight: bold; | ||
| 90 | + margin-bottom: 1rem; | ||
| 91 | + } | ||
| 92 | + } | ||
| 93 | + } | ||
| 94 | + .light-up-text { | ||
| 95 | + text-align: center; | ||
| 96 | + font-size: 24px; | ||
| 97 | + font-weight: bold; | ||
| 98 | + color: #F8E9C1; /* 文字颜色 */ | ||
| 99 | + text-shadow: | ||
| 100 | + -1px -1px 0 #000, | ||
| 101 | + 1px -1px 0 #000, | ||
| 102 | + -1px 1px 0 #000, | ||
| 103 | + 1px 1px 0 #000; | ||
| 104 | + margin: 1rem 0; | ||
| 105 | + } | ||
| 106 | +} | ||
| 107 | +</style> |
src/views/fxPark/poster.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div class="poster-page"> | ||
| 3 | + <div style="height: calc(83vh - 2rem); padding: 1rem;"> | ||
| 4 | + <div v-if="flag" ref="canvasRef" style="position: relative; padding: 1rem; background-color: #fff;"> | ||
| 5 | + <div style="position: absolute; top: 3rem; left: 2rem; color: #FFF; writing-mode: vertical-lr; text-orientation: upright;"> | ||
| 6 | + <div style="position: relative;"> | ||
| 7 | + <span style="font-size: 2.5rem; font-weight: bolder; letter-spacing: 5px;">悬铃木</span> | ||
| 8 | + <div style="position: absolute; bottom: -1rem; letter-spacing: 5px;">智者长老</div> | ||
| 9 | + </div> | ||
| 10 | + </div> | ||
| 11 | + <img :src="imgSrc" style="width: 100%; height: 67vh;"> | ||
| 12 | + <div style="color: #CCCCCC; margin-top: 1rem;"> | ||
| 13 | + <div style="font-weight: bold; text-decoration: underline; margin-bottom: 0.5rem;">自带咖啡杯</div> | ||
| 14 | + <div style="font-size: 0.9rem;">去咖啡店时自带咖啡杯,代替一次性纸杯。</div> | ||
| 15 | + </div> | ||
| 16 | + </div> | ||
| 17 | + <div v-if="imgUrl"> | ||
| 18 | + <img :src="imgUrl" alt="" crossOrigin="anonymous" :style="{ width: ref_width, height: ref_height }"> | ||
| 19 | + </div> | ||
| 20 | + </div> | ||
| 21 | + <div class="poster-control-wrapper"> | ||
| 22 | + <p class="save-text">长按保存到相册</p> | ||
| 23 | + <div class="poster-control"> | ||
| 24 | + <div class="poster-prev">上一个</div> | ||
| 25 | + <van-uploader :before-read="beforeRead" :after-read="afterRead" :max-size="1000 * 1024" accept="file"> | ||
| 26 | + <div v-if="!upload_loading" class="poster-upload-btn" style="">上传图片</div> | ||
| 27 | + <van-loading v-else size="24px" color="#E82D2D" text-color="#E82D2D" vertical>上传中...</van-loading> | ||
| 28 | + </van-uploader> | ||
| 29 | + <div class="poster-next">下一个</div> | ||
| 30 | + </div> | ||
| 31 | + </div> | ||
| 32 | + </div> | ||
| 33 | +</template> | ||
| 34 | + | ||
| 35 | +<script setup> | ||
| 36 | +import { ref } from 'vue' | ||
| 37 | +import { useRoute, useRouter } from 'vue-router' | ||
| 38 | +import { v4 as uuidv4 } from 'uuid'; | ||
| 39 | +import { qiniuTokenAPI, qiniuUploadAPI, saveFileAPI } from '@/api/common'; | ||
| 40 | +import html2canvas from "html2canvas"; | ||
| 41 | +import { Cookies, $, _, axios, storeToRefs, mainStore, Toast, useTitle } from '@/utils/generatePackage.js' | ||
| 42 | +//import { } from '@/utils/generateModules.js' | ||
| 43 | +//import { } from '@/utils/generateIcons.js' | ||
| 44 | +//import { } from '@/composables' | ||
| 45 | +const $route = useRoute(); | ||
| 46 | +const $router = useRouter(); | ||
| 47 | +useTitle($route.meta.title); | ||
| 48 | + | ||
| 49 | +const canvasRef = ref(null); | ||
| 50 | +const imgUrl = ref(''); | ||
| 51 | +const imgSrc = ref('https://picsum.photos/800'); | ||
| 52 | +const flag = ref(true); | ||
| 53 | +const ref_width = ref(''); | ||
| 54 | +const ref_height = ref(''); | ||
| 55 | + | ||
| 56 | +onMounted(async () => { | ||
| 57 | + nextTick(() => { | ||
| 58 | + let canvasDom = canvasRef.value; | ||
| 59 | + ref_width.value = canvasDom.offsetWidth + 'px'; | ||
| 60 | + ref_height.value = canvasDom.offsetHeight + 'px'; | ||
| 61 | + // const screenWidth = window.innerWidth; | ||
| 62 | + // alert(screenWidth); // 输出移动设备屏幕的宽度 | ||
| 63 | + }); | ||
| 64 | + createImage(); | ||
| 65 | +}); | ||
| 66 | + | ||
| 67 | +// 获取像素比 | ||
| 68 | +const DPR = () => { | ||
| 69 | + // 获取设备dpi | ||
| 70 | + if (window.devicePixelRatio && window.devicePixelRatio > 1) { | ||
| 71 | + return window.devicePixelRatio * 2 | ||
| 72 | + } | ||
| 73 | + // 直接返回高像素比 | ||
| 74 | + return 8 | ||
| 75 | +} | ||
| 76 | + | ||
| 77 | +const createImage = () => { | ||
| 78 | + nextTick(() => { | ||
| 79 | + // 获取要生成图片的 DOM 元素 | ||
| 80 | + let canvasDom = canvasRef.value; | ||
| 81 | + const options = { | ||
| 82 | + backgroundColor: '#fff', | ||
| 83 | + // canvas: canvas, | ||
| 84 | + useCORS: true,//配置允许跨域 | ||
| 85 | + scale: DPR(), | ||
| 86 | + // windowWidth: document.body.scrollWidth, | ||
| 87 | + // windowHeight: document.body.scrollHeight, | ||
| 88 | + // x: 0, | ||
| 89 | + // y: window.pageYOffset, | ||
| 90 | + // allowTaint: true, | ||
| 91 | + // background: "#d21f2c", // 一定要添加背景颜色,否则出来的图片,背景全部都是透明的 | ||
| 92 | + // dpi: 300 // 处理模糊问题 | ||
| 93 | + }; | ||
| 94 | + // console.log("获取指定的宽高", width, height, canvas); | ||
| 95 | + html2canvas(canvasDom, options) | ||
| 96 | + .then(canvas => { | ||
| 97 | + try { | ||
| 98 | + // 生成图片地址 | ||
| 99 | + imgUrl.value = canvas.toDataURL("image/png"); | ||
| 100 | + // console.log("canvas.toDataURL('image/png')", this.imgUrl); | ||
| 101 | + flag.value = false; | ||
| 102 | + } catch (e) { | ||
| 103 | + alert("图片跨域,保存失败"); | ||
| 104 | + } | ||
| 105 | + }) | ||
| 106 | + .catch(error => { | ||
| 107 | + console.error("绘制失败"); | ||
| 108 | + console.error(error); | ||
| 109 | + }); | ||
| 110 | + }); | ||
| 111 | +} | ||
| 112 | + | ||
| 113 | +const upload_loading = ref(false); | ||
| 114 | +const beforeRead = (file) => { | ||
| 115 | + // if (file.type.indexOf('audio') < 0) { | ||
| 116 | + // showToast('请上传音频格式'); | ||
| 117 | + // return false; | ||
| 118 | + // } | ||
| 119 | + return true; | ||
| 120 | +}; | ||
| 121 | + | ||
| 122 | +const afterRead = async (res) => { | ||
| 123 | + upload_loading.value = true; | ||
| 124 | + let affix = uuidv4(); | ||
| 125 | + // 此时可以自行将文件上传至服务器 | ||
| 126 | + let dataURL = res.content; | ||
| 127 | + let base64url = dataURL.slice(dataURL.indexOf(',') + 1); // 截取前缀的base64 data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAnoAAAJeCAYAA....... | ||
| 128 | + // 获取七牛token | ||
| 129 | + const { token, key, code } = await qiniuTokenAPI({ filename: `${affix}_${res.file.name}`, file: base64url }); | ||
| 130 | + if (code) { | ||
| 131 | + const config = { | ||
| 132 | + headers: { | ||
| 133 | + 'Content-Type': 'application/octet-stream', | ||
| 134 | + 'Authorization': 'UpToken ' + token, // UpToken后必须有一个 ' '(空格) | ||
| 135 | + } | ||
| 136 | + } | ||
| 137 | + // 上传七牛服务器 | ||
| 138 | + const { filekey, hash, image_info } = await qiniuUploadAPI('http://upload.qiniup.com/putb64/-1/key/' + key, base64url, config) | ||
| 139 | + if (filekey) { | ||
| 140 | + // 保存图片 | ||
| 141 | + const { data } = await saveFileAPI({ filekey, hash, format: '0', height: '0', width: '0' }); | ||
| 142 | + flag.value = true; | ||
| 143 | + imgUrl.value = ''; | ||
| 144 | + imgSrc.value = data.src; | ||
| 145 | + upload_loading.value = false; | ||
| 146 | + createImage(); | ||
| 147 | + } | ||
| 148 | + } | ||
| 149 | +}; | ||
| 150 | +</script> | ||
| 151 | + | ||
| 152 | +<style lang="less" scoped> | ||
| 153 | +.poster-page { | ||
| 154 | + height: 100vh; | ||
| 155 | + background-color: green; | ||
| 156 | + .poster-control-wrapper { | ||
| 157 | + .save-text { | ||
| 158 | + text-align: center; | ||
| 159 | + margin-top: 2rem; | ||
| 160 | + margin-bottom: 1rem; | ||
| 161 | + color: #fff; | ||
| 162 | + font-size: 0.9rem; | ||
| 163 | + } | ||
| 164 | + .poster-control { | ||
| 165 | + display: flex; | ||
| 166 | + justify-content: space-between; | ||
| 167 | + align-items: center; | ||
| 168 | + .poster-prev { | ||
| 169 | + background-color: rgba(0, 0, 0, 0.3); | ||
| 170 | + color: #FFF; | ||
| 171 | + padding: 0.5rem 0.8rem 0.5rem 1rem; | ||
| 172 | + border-top-right-radius: 15px; | ||
| 173 | + border-bottom-right-radius: 15px; | ||
| 174 | + font-size: 0.9rem; | ||
| 175 | + } | ||
| 176 | + .poster-next { | ||
| 177 | + background-color: rgba(0, 0, 0, 0.3); | ||
| 178 | + color: #FFF; | ||
| 179 | + padding: 0.5rem 1rem 0.5rem 0.8rem; | ||
| 180 | + border-top-left-radius: 15px; | ||
| 181 | + border-bottom-left-radius: 15px; | ||
| 182 | + font-size: 0.9rem; | ||
| 183 | + } | ||
| 184 | + .poster-upload-btn { | ||
| 185 | + display: inline-block; | ||
| 186 | + background-color: #F68015; | ||
| 187 | + color: #fff; | ||
| 188 | + padding: 0.5rem 2.5rem; | ||
| 189 | + border-radius: 1.5rem; | ||
| 190 | + font-size: 0.95rem; | ||
| 191 | + } | ||
| 192 | + } | ||
| 193 | + } | ||
| 194 | +} | ||
| 195 | +</style> |
src/views/fxPark/share.vue
0 → 100644
| 1 | +<!-- | ||
| 2 | + * @Date: 2023-12-30 22:43:25 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2024-04-11 13:29:29 | ||
| 5 | + * @FilePath: /fxPark/src/views/fxPark/share.vue | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | +--> | ||
| 8 | +<template> | ||
| 9 | + <div class="share-page"> | ||
| 10 | + <div v-if="flag" ref="canvasRef" class="share-bg"> | ||
| 11 | + <div style="width: 90vw; height: 90vh;position: relative; overflow: hidden;"> | ||
| 12 | + <img src="https://cdn.ipadbiz.cn/gy/new_year_2024/-h-%E6%96%B0%E5%B9%B4%E7%AD%BE.png" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); max-width: 100%; max-height: 100%;"> | ||
| 13 | + </div> | ||
| 14 | + <div style="text-align: center; position: absolute; top: 27.5vh; left: calc(50% - 10vw); font-size: 0.6rem;color:#000;">交往 · 交流 · 交融</div> | ||
| 15 | + <div class="desc-text" v-for="(item, index) in sloganStyle" :key="index" :style="{ ...item }">{{ stringToArray(slogan)[index] }}</div> | ||
| 16 | + <!-- <img :src="qr_code" :style="{ ...qrCodeStyle }"> --> | ||
| 17 | + <div style="text-align: center; position: absolute; bottom: 11vh; left: calc(50% - 15vw); font-size: 0.8rem;color:#c53447;">收听来自远方的祝福</div> | ||
| 18 | + </div> | ||
| 19 | + <div v-if="imgUrl" class="share-img"> | ||
| 20 | + <img :src="imgUrl" alt="" crossOrigin="anonymous" :style="{ width: ref_width, height: ref_height }"> | ||
| 21 | + </div> | ||
| 22 | + <div v-if="wish_list.length > 1" class="control-wrapper"> | ||
| 23 | + <div class="prev" @click="prevWish">上一个</div> | ||
| 24 | + <div>长按保存到相册分享</div> | ||
| 25 | + <div class="next" @click="nextWish">下一个</div> | ||
| 26 | + </div> | ||
| 27 | + <div v-else class="control-wrapper" style="justify-content: center;"> | ||
| 28 | + <div>长按保存到相册分享</div> | ||
| 29 | + </div> | ||
| 30 | + </div> | ||
| 31 | +</template> | ||
| 32 | + | ||
| 33 | +<script setup> | ||
| 34 | +import { ref } from 'vue' | ||
| 35 | +import { useRoute, useRouter } from 'vue-router' | ||
| 36 | +import { shareWishListAPI } from '@/api/new_year_2024.js' | ||
| 37 | +import { showToast } from 'vant'; | ||
| 38 | +import { Cookies, $, _, axios, storeToRefs, mainStore, Toast, useTitle } from '@/utils/generatePackage.js' | ||
| 39 | +//import { } from '@/utils/generateModules.js' | ||
| 40 | +//import { } from '@/utils/generateIcons.js' | ||
| 41 | +//import { } from '@/composables' | ||
| 42 | +// import qr_code from '@images/new_year_2024/http_qr_code.png' | ||
| 43 | + | ||
| 44 | +const $route = useRoute(); | ||
| 45 | +const $router = useRouter(); | ||
| 46 | +useTitle($route.meta.title); | ||
| 47 | + | ||
| 48 | +const wish_index = ref(0); | ||
| 49 | +const slogan = ref(''); | ||
| 50 | +const wish_list = ref([]); | ||
| 51 | + | ||
| 52 | +const canvasRef = ref(null); | ||
| 53 | +const imgUrl = ref(''); | ||
| 54 | +const flag = ref(true); | ||
| 55 | +const ref_width = ref(''); | ||
| 56 | +const ref_height = ref(''); | ||
| 57 | + | ||
| 58 | +// TAG: slogan位置配置 | ||
| 59 | +const sloganStyle = [{ | ||
| 60 | + top: '34vh', | ||
| 61 | + left: '26vw', | ||
| 62 | + fontSize: '14vw' | ||
| 63 | +}, { | ||
| 64 | + top: '34vh', | ||
| 65 | + right: '26vw', | ||
| 66 | + fontSize: '14vw' | ||
| 67 | +}, { | ||
| 68 | + top: '48vh', | ||
| 69 | + left: '26vw', | ||
| 70 | + fontSize: '14vw' | ||
| 71 | +}, { | ||
| 72 | + top: '48vh', | ||
| 73 | + right: '26vw', | ||
| 74 | + fontSize: '14vw' | ||
| 75 | +}]; | ||
| 76 | + | ||
| 77 | +const qrCodeStyle = ref({ | ||
| 78 | + position: 'absolute', | ||
| 79 | + bottom: '15.5vh', | ||
| 80 | + left: '36vw', | ||
| 81 | + width: '19vw', | ||
| 82 | + height: '10vh', | ||
| 83 | +}) | ||
| 84 | + | ||
| 85 | +onMounted(async () => { | ||
| 86 | + nextTick(() => { | ||
| 87 | + let canvasDom = canvasRef.value; | ||
| 88 | + ref_width.value = canvasDom.offsetWidth + 'px'; | ||
| 89 | + ref_height.value = canvasDom.offsetHeight + 'px'; | ||
| 90 | + // const screenWidth = window.innerWidth; | ||
| 91 | + // alert(screenWidth); // 输出移动设备屏幕的宽度 | ||
| 92 | + }); | ||
| 93 | + const { code, data } = await shareWishListAPI(); | ||
| 94 | + if (code) { | ||
| 95 | + wish_list.value = data; | ||
| 96 | + if (wish_list.value.length) { | ||
| 97 | + slogan.value = wish_list.value[wish_index.value].slogon; | ||
| 98 | + createImage(); | ||
| 99 | + } | ||
| 100 | + } | ||
| 101 | +}); | ||
| 102 | + | ||
| 103 | +const stringToArray = (str) => { | ||
| 104 | + return str.split(''); | ||
| 105 | +} | ||
| 106 | + | ||
| 107 | +const prevWish = () => { | ||
| 108 | + if (!wish_index.value) { | ||
| 109 | + showToast('已经是第一张了'); | ||
| 110 | + return; | ||
| 111 | + } | ||
| 112 | + wish_index.value -= 1; | ||
| 113 | + slogan.value = wish_list.value[wish_index.value].slogon; | ||
| 114 | + // 生成图片 | ||
| 115 | + imgUrl.value = ''; | ||
| 116 | + flag.value = true; | ||
| 117 | + createImage(); | ||
| 118 | +} | ||
| 119 | + | ||
| 120 | +const nextWish = () => { | ||
| 121 | + if (wish_index.value === wish_list.value.length - 1) { | ||
| 122 | + showToast('已经是最后一张了'); | ||
| 123 | + return; | ||
| 124 | + } | ||
| 125 | + wish_index.value += 1; | ||
| 126 | + slogan.value = wish_list.value[wish_index.value].slogon; | ||
| 127 | + // 生成图片 | ||
| 128 | + imgUrl.value = ''; | ||
| 129 | + flag.value = true; | ||
| 130 | + createImage(); | ||
| 131 | +} | ||
| 132 | + | ||
| 133 | +// 获取像素比 | ||
| 134 | +const DPR = () => { | ||
| 135 | + // 获取设备dpi | ||
| 136 | + if (window.devicePixelRatio && window.devicePixelRatio > 1) { | ||
| 137 | + return window.devicePixelRatio * 2 | ||
| 138 | + } | ||
| 139 | + // 直接返回高像素比 | ||
| 140 | + return 8 | ||
| 141 | +} | ||
| 142 | + | ||
| 143 | +const createImage = () => { | ||
| 144 | + nextTick(() => { | ||
| 145 | + // 获取要生成图片的 DOM 元素 | ||
| 146 | + let canvasDom = canvasRef.value; | ||
| 147 | + const options = { | ||
| 148 | + backgroundColor: '#d21f2c', | ||
| 149 | + // canvas: canvas, | ||
| 150 | + useCORS: true,//配置允许跨域 | ||
| 151 | + scale: DPR(), | ||
| 152 | + // windowWidth: document.body.scrollWidth, | ||
| 153 | + // windowHeight: document.body.scrollHeight, | ||
| 154 | + // x: 0, | ||
| 155 | + // y: window.pageYOffset, | ||
| 156 | + // allowTaint: true, | ||
| 157 | + // background: "#d21f2c", // 一定要添加背景颜色,否则出来的图片,背景全部都是透明的 | ||
| 158 | + // dpi: 300 // 处理模糊问题 | ||
| 159 | + }; | ||
| 160 | + // console.log("获取指定的宽高", width, height, canvas); | ||
| 161 | + html2canvas(canvasDom, options) | ||
| 162 | + .then(canvas => { | ||
| 163 | + try { | ||
| 164 | + // 生成图片地址 | ||
| 165 | + imgUrl.value = canvas.toDataURL("image/png"); | ||
| 166 | + // console.log("canvas.toDataURL('image/png')", this.imgUrl); | ||
| 167 | + flag.value = false; | ||
| 168 | + } catch (e) { | ||
| 169 | + alert("图片跨域,保存失败"); | ||
| 170 | + } | ||
| 171 | + }) | ||
| 172 | + .catch(error => { | ||
| 173 | + console.error("绘制失败"); | ||
| 174 | + console.error(error); | ||
| 175 | + }); | ||
| 176 | + }); | ||
| 177 | +} | ||
| 178 | +</script> | ||
| 179 | + | ||
| 180 | +<script> | ||
| 181 | +import mixin from 'common/mixin'; | ||
| 182 | +import html2canvas from "html2canvas"; | ||
| 183 | +import wx from 'weixin-js-sdk' | ||
| 184 | + | ||
| 185 | +export default { | ||
| 186 | + mixins: [mixin.init], | ||
| 187 | + data() { | ||
| 188 | + return { | ||
| 189 | + } | ||
| 190 | + }, | ||
| 191 | + mounted() { | ||
| 192 | + }, | ||
| 193 | + methods: { | ||
| 194 | + } | ||
| 195 | +} | ||
| 196 | +</script> | ||
| 197 | + | ||
| 198 | +<style lang="less" scoped> | ||
| 199 | +.share-page { | ||
| 200 | + position: relative; | ||
| 201 | + background-color: #d21f2c; | ||
| 202 | + height: 100vh; | ||
| 203 | + width: 100vw; | ||
| 204 | + .share-bg { | ||
| 205 | + position: absolute; | ||
| 206 | + // top: 8vh; | ||
| 207 | + top: 0; | ||
| 208 | + left: 5vw; | ||
| 209 | + width: 90vw; | ||
| 210 | + height: 90vh; | ||
| 211 | + // background-image: url('https://cdn.ipadbiz.cn/gy/new_year_2024/%E6%96%B0%E5%B9%B4%E7%AD%BE@2x.png'); | ||
| 212 | + // background-image: url('https://cdn.ipadbiz.cn/gy/new_year_2024/-h-%E6%96%B0%E5%B9%B4%E7%AD%BE.png'); | ||
| 213 | + // background-repeat: no-repeat; | ||
| 214 | + // background-size: contain; | ||
| 215 | + // background-position: center; | ||
| 216 | + .desc-text { | ||
| 217 | + color: #c53447; | ||
| 218 | + // font-size: 13vw; | ||
| 219 | + // font-size: 7vh; | ||
| 220 | + // font-size: 3.5rem; | ||
| 221 | + position: absolute; | ||
| 222 | + font-weight: bold; | ||
| 223 | + } | ||
| 224 | + } | ||
| 225 | + | ||
| 226 | + .share-img { | ||
| 227 | + position: absolute; | ||
| 228 | + // top: 8vh; | ||
| 229 | + top: 0; | ||
| 230 | + left: 5vw; | ||
| 231 | + } | ||
| 232 | + | ||
| 233 | + .control-wrapper { | ||
| 234 | + display: flex; | ||
| 235 | + position: absolute; | ||
| 236 | + bottom: 5vh; | ||
| 237 | + width: 100%; | ||
| 238 | + justify-content: space-between; | ||
| 239 | + color: #FFF; | ||
| 240 | + align-items: center; | ||
| 241 | + .prev { | ||
| 242 | + background: #B41C1E; | ||
| 243 | + border-radius: 0px 33px 33px 0px; | ||
| 244 | + padding: 0.5rem 1rem 0.5rem 0.35rem; | ||
| 245 | + } | ||
| 246 | + .next { | ||
| 247 | + background: #B41C1E; | ||
| 248 | + border-radius: 33px 0px 0px 33px; | ||
| 249 | + padding: 0.5rem 0.35rem 0.5rem 1rem; | ||
| 250 | + } | ||
| 251 | + } | ||
| 252 | +} | ||
| 253 | +</style> |
| ... | @@ -2,7 +2,7 @@ | ... | @@ -2,7 +2,7 @@ |
| 2 | <div> | 2 | <div> |
| 3 | <!-- 生成图片后隐藏原始结构 --> | 3 | <!-- 生成图片后隐藏原始结构 --> |
| 4 | <div v-if="flag" ref="canvasRef" style="width: 200px; height: 200px;"> | 4 | <div v-if="flag" ref="canvasRef" style="width: 200px; height: 200px;"> |
| 5 | - <img :src="logo_image" alt=""> | 5 | + <!-- <img :src="logo_image" alt=""> --> |
| 6 | </div> | 6 | </div> |
| 7 | <div v-if="imgUrl"> | 7 | <div v-if="imgUrl"> |
| 8 | <img :src="imgUrl" alt="" crossOrigin="anonymous" style="width: 300px; height: 300px;"> | 8 | <img :src="imgUrl" alt="" crossOrigin="anonymous" style="width: 300px; height: 300px;"> |
| ... | @@ -17,7 +17,7 @@ | ... | @@ -17,7 +17,7 @@ |
| 17 | 17 | ||
| 18 | <script setup> | 18 | <script setup> |
| 19 | 19 | ||
| 20 | -import logo_image from '@images/logo@3x.png' | 20 | +// import logo_image from '@images/logo@3x.png' |
| 21 | </script> | 21 | </script> |
| 22 | 22 | ||
| 23 | <script> | 23 | <script> | ... | ... |
| ... | @@ -3307,6 +3307,11 @@ | ... | @@ -3307,6 +3307,11 @@ |
| 3307 | "@vue/server-renderer" "3.3.13" | 3307 | "@vue/server-renderer" "3.3.13" |
| 3308 | "@vue/shared" "3.3.13" | 3308 | "@vue/shared" "3.3.13" |
| 3309 | 3309 | ||
| 3310 | +"vue3-danmaku@^1.6.0": | ||
| 3311 | + "integrity" "sha512-XjwVKIelupDD3PWn6k22l5qS8y+SCdFUYq4sSpcPInqk7CyzXWSAfz2BL6WWx9HU9CRWS3x2oDMkepLkJoWvNQ==" | ||
| 3312 | + "resolved" "https://mirrors.cloud.tencent.com/npm/vue3-danmaku/-/vue3-danmaku-1.6.0.tgz" | ||
| 3313 | + "version" "1.6.0" | ||
| 3314 | + | ||
| 3310 | "webpack-sources@^3.2.3": | 3315 | "webpack-sources@^3.2.3": |
| 3311 | "integrity" "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==" | 3316 | "integrity" "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==" |
| 3312 | "resolved" "https://mirrors.cloud.tencent.com/npm/webpack-sources/-/webpack-sources-3.2.3.tgz" | 3317 | "resolved" "https://mirrors.cloud.tencent.com/npm/webpack-sources/-/webpack-sources-3.2.3.tgz" | ... | ... |
-
Please register or login to post a comment