Merge remote-tracking branch 'origin/master'

# Conflicts:
#	README.md
This commit is contained in:
zyronon 2024-04-28 15:46:04 +08:00
commit 4f80219a5e
50 changed files with 2564 additions and 3627 deletions

View File

@ -13,8 +13,9 @@
<a><img src="https://img.shields.io/badge/Powered%20by-Vue-blue"/></a>
</p>
`douyin-vue` 是一个模仿 `抖音|TikTok` 的移动端短视频项目完全度90%。使用了最新的 `Vue` 全家桶技术栈,它基于 [`Vue3`](https://cn.vuejs.org/)、[`Vite5`](https://cn.vitejs.dev/)
、[`Pinia`](https://pinia.vuejs.org/)实现。数据保存在项目本地,视频采集自`抖音|TikTok`,图集采集自`小红书|Xiaohongshu`,通过 [`axios-mock-adapter`](https://github.com/ctimmerm/axios-mock-adapter) 库拦截Api 并返回本地json数据模拟真实后端请求
`douyin-vue` 是一个模仿 `抖音|TikTok` 的移动端短视频项目。`Vue` 在移动端的"最佳实践",媲美原生 `App` 丝滑流畅的使用体验。使用了最新的 `Vue` 技术栈,基于 [`Vue3`](https://cn.vuejs.org/)、[`Vite5`](https://cn.vitejs.dev/)
、[`Pinia`](https://pinia.vuejs.org/)实现。数据保存在项目本地,通过 [`axios-mock-adapter`](https://github.com/ctimmerm/axios-mock-adapter) 库拦截Api 并返回本地json数据模拟真实后端请求
<div>
<img width="150px" src='docs/imgs/1.gif' />
@ -31,12 +32,14 @@
## 在线访问
Gitee Pages: [https://zyronon.gitee.io/douyin/](https://zyronon.gitee.io/douyin/) (中国推荐访问这个地址)
Github Pages: [https://zyronon.github.io/douyin/](https://zyronon.github.io/douyin/)
Gitee pages: [https://dy.ttentau.top/](https://dy.ttentau.top/) (中国地区推荐访问这个地址)
Netlify: [https://douyins.netlify.app/](https://douyins.netlify.app/)
[//]: # (~~Vercel: [http://dy.ttentau.top/]&#40;http://dy.ttentau.top/&#41;~~)
[//]: # (Vercel: [https://douyins.vercel.app]&#40;https://douyins.vercel.app&#41;)
[//]: # (~~Netlify: [https://douyins.netlify.app/]&#40;https://douyins.netlify.app/&#41;~~)
[//]: # (Gitee pages: [https://zyronon.gitee.io/douyin/]&#40;https://zyronon.gitee.io/douyin/&#41; &#40;中国地区推荐访问这个地址&#41; )
[//]: # (Github pages: [https://zyronon.github.io/douyin/]&#40;https://zyronon.github.io/douyin/&#41; )
[//]: # (Vercel和Netlify分别送的100G免费流量已经用完了...🤣)

View File

@ -3,8 +3,8 @@
</h1>
<p align="center">
<a href="README.en.md">English</a> | <a href="README.es.md">Spanish</a> | <a href="README.de.md">German</a> |
<a href="README.fr.md">French</a> | <a href="../README.md">简体中文</a> | <a href="README.ja.md">日本語</a>
<a href="docs/README.en.md">English</a> | <a href="docs/README.es.md">Spanish</a> | <a href="docs/README.de.md">German</a> |
<a href="docs/README.fr.md">French</a> | <a href="../README.md">简体中文</a> | <a href="docs/README.ja.md">日本語</a>
</p>
<p align="center">
@ -13,7 +13,7 @@
<a><img src="https://img.shields.io/badge/Powered%20by-Vue-blue"/></a>
</p>
`douyin-vue`ist eine Parodie`抖音|TikTok`Das mobile Kurzvideoprojekt weist eine Vollständigkeit von 90 % auf. Habe das Neueste verwendet`Vue`FamilyMart-Technologie-Stack, der auf basiert[`Vue3`](https://cn.vuejs.org/)、[`Vite5`](https://cn.vitejs.dev/)、[`Pinia`](https://pinia.vuejs.org/)erreichen. Die Daten werden lokal im Projekt gespeichert und das Video daraus gesammelt`抖音|TikTok`, der Atlas stammt aus`小红书|Xiaohongshu`,passieren[`axios-mock-adapter`](https://github.com/ctimmerm/axios-mock-adapter)Die Bibliothek fängt die API ab und gibt lokale JSON-Daten zurück, um echte Backend-Anfragen zu simulieren.
`douyin-vue`ist eine Parodie`抖音|TikTok`mobiles Kurzvideoprojekt.`Vue`„Best Practices“ auf der mobilen Seite, vergleichbar mit Native`App`Seidiges und geschmeidiges Erlebnis. Habe das Neueste verwendet`Vue`Technologie-Stack, basierend auf[`Vue3`](https://cn.vuejs.org/)、[`Vite5`](https://cn.vitejs.dev/)、[`Pinia`](https://pinia.vuejs.org/)erreichen. Die Daten werden lokal im Projekt gespeichert[`axios-mock-adapter`](https://github.com/ctimmerm/axios-mock-adapter)Die Bibliothek fängt die API ab und gibt lokale JSON-Daten zurück, um echte Backend-Anfragen zu simulieren.
<div>
<img width="150px" src='imgs/1.gif' />
@ -30,12 +30,14 @@
## Online-Zugang
Gitee-Seiten:<https://zyronon.gitee.io/douyin/>(Es wird empfohlen, diese Adresse in China zu besuchen)
Github-Seiten:<https://zyronon.github.io/douyin/>
Gitee-Seiten:<https://dy.ttentau.top/>(Es wird empfohlen, diese Adresse in China zu besuchen)
Netlify:<https://douyins.netlify.app/>
[//]: # "~~Vercel: [http://dy.ttentau.top/](http://dy.ttentau.top/)~~"
[//]: # "Vercel: [https://douyins.vercel.app](https://douyins.vercel.app)"
[//]: # "~~Netlify: [https://douyins.netlify.app/](https://douyins.netlify.app/)~~"
[//]: # "Gitee pages: [https://zyronon.gitee.io/douyin/](https://zyronon.gitee.io/douyin/) (中国地区推荐访问这个地址) "
[//]: # "Github pages: [https://zyronon.github.io/douyin/](https://zyronon.github.io/douyin/) "
[//]: # "Vercel和Netlify分别送的100G免费流量已经用完了...🤣"
@ -47,7 +49,7 @@ Github-Seiten:<https://zyronon.github.io/douyin/>
## Verknüpfung
\[douyin-vue] Eins:[200 Codezeilen zur Implementierung einer Karussellkomponente ähnlich wie Swiper.js](https://juejin.cn/post/7360512664317018146)
\[douyin-vue] Eins:[200 Codezeilen zur Implementierung einer Karussellkomponente ähnlich Swiper.js](https://juejin.cn/post/7360512664317018146)
\[douyin-vue] Zweitens:[Verwirklichen Sie den „unendlich gleitenden Video“-Effekt auf Douyin](https://juejin.cn/post/7361614921519054883)
Weitere Artikel sind in Vorbereitung...
@ -68,7 +70,7 @@ npm install
npm run dev
```
打开浏览器并访问: <http://127.0.0.1:3000>
Öffnen Sie Ihren Browser und besuchen Sie:<http://127.0.0.1:3000>
**Hinweis: Sie müssen den Browser in den Mobilmodus schalten, indem Sie zuerst drücken`F12`Um die Konsole aufzurufen, drücken Sie`Ctrl+Shift+M`um eine normale Vorschau anzuzeigen**

View File

@ -3,8 +3,8 @@
</h1>
<p align="center">
<a href="README.en.md">English</a> | <a href="README.es.md">Spanish</a> | <a href="README.de.md">German</a> |
<a href="README.fr.md">French</a> | <a href="../README.md">简体中文</a> | <a href="README.ja.md">日本語</a>
<a href="docs/README.en.md">English</a> | <a href="docs/README.es.md">Spanish</a> | <a href="docs/README.de.md">German</a> |
<a href="docs/README.fr.md">French</a> | <a href="../README.md">简体中文</a> | <a href="docs/README.ja.md">日本語</a>
</p>
<p align="center">
@ -13,7 +13,7 @@
<a><img src="https://img.shields.io/badge/Powered%20by-Vue-blue"/></a>
</p>
`douyin-vue`is a parody`抖音|TikTok`The mobile short video project has a completeness of 90%. Used the latest`Vue`FamilyMart technology stack, which is based on[`Vue3`](https://cn.vuejs.org/)、[`Vite5`](https://cn.vitejs.dev/)、[`Pinia`](https://pinia.vuejs.org/)accomplish. The data is saved locally in the project, and the video is collected from`抖音|TikTok`, the atlas is collected from`小红书|Xiaohongshu`,pass[`axios-mock-adapter`](https://github.com/ctimmerm/axios-mock-adapter)The library intercepts the API and returns local json data to simulate real backend requests.
`douyin-vue`is a parody`抖音|TikTok`mobile short video project.`Vue`"Best practices" on the mobile side, comparable to native`App`Silky and smooth experience. Used the latest`Vue`technology stack, based on[`Vue3`](https://cn.vuejs.org/)、[`Vite5`](https://cn.vitejs.dev/)、[`Pinia`](https://pinia.vuejs.org/)accomplish. The data is saved locally in the project through[`axios-mock-adapter`](https://github.com/ctimmerm/axios-mock-adapter)The library intercepts the API and returns local json data to simulate real backend requests.
<div>
<img width="150px" src='imgs/1.gif' />
@ -28,14 +28,16 @@
<img width="150px" src='imgs/img-5.jpg' />
</div>
## online access
## Online access
Gitee pages:<https://zyronon.gitee.io/douyin/>(It is recommended to visit this address in China)
Github pages:<https://zyronon.github.io/douyin/>
Gitee pages:<https://dy.ttentau.top/>(It is recommended to visit this address in China)
Netlify:<https://douyins.netlify.app/>
[//]: # "~~Vercel: [http://dy.ttentau.top/](http://dy.ttentau.top/)~~"
[//]: # "Vercel: [https://douyins.vercel.app](https://douyins.vercel.app)"
[//]: # "~~Netlify: [https://douyins.netlify.app/](https://douyins.netlify.app/)~~"
[//]: # "Gitee pages: [https://zyronon.gitee.io/douyin/](https://zyronon.gitee.io/douyin/) (中国地区推荐访问这个地址) "
[//]: # "Github pages: [https://zyronon.github.io/douyin/](https://zyronon.github.io/douyin/) "
[//]: # "Vercel和Netlify分别送的100G免费流量已经用完了...🤣"
@ -49,11 +51,11 @@ Github pages:<https://zyronon.github.io/douyin/>
\[douyin-vue] One:[200 lines of code to implement a carousel component similar to Swiper.js](https://juejin.cn/post/7360512664317018146)
\[douyin-vue] Second:[Realize the "infinite sliding video" effect on Douyin](https://juejin.cn/post/7361614921519054883)
更多文章正在准备中...
More articles are in preparation...
## run
注意:本项目仅适用于学习和研究,不得用于商业使用
Note: This project is only suitable for study and research, not for commercial use
### Quickly deploy to Vercel
@ -68,7 +70,7 @@ npm install
npm run dev
```
打开浏览器并访问: <http://127.0.0.1:3000>
Open your browser and visit:<http://127.0.0.1:3000>
**Note: You need to switch the browser to mobile mode, first press`F12`To bring up the console, press`Ctrl+Shift+M`to preview normally**
@ -96,7 +98,7 @@ The above content is all public information on the Internet
## Features and suggestions
The project is currently in the early stages of development and new features are being added continuously. If you have any features or suggestions for the software, please feel free to contact us.`Issues`raised in
The project is currently in the early stages of development, and new features are being added continuously. If you have any features or suggestions for the software, please feel free to contact us.`Issues`raised in
If you also like the design ideas of this software, please submit it`PR`, thank you very much for your support!
## contact me

View File

@ -3,8 +3,8 @@
</h1>
<p align="center">
<a href="README.en.md">English</a> | <a href="README.es.md">Spanish</a> | <a href="README.de.md">German</a> |
<a href="README.fr.md">French</a> | <a href="../README.md">简体中文</a> | <a href="README.ja.md">日本語</a>
<a href="docs/README.en.md">English</a> | <a href="docs/README.es.md">Spanish</a> | <a href="docs/README.de.md">German</a> |
<a href="docs/README.fr.md">French</a> | <a href="../README.md">简体中文</a> | <a href="docs/README.ja.md">日本語</a>
</p>
<p align="center">
@ -13,7 +13,7 @@
<a><img src="https://img.shields.io/badge/Powered%20by-Vue-blue"/></a>
</p>
`douyin-vue`es una parodia`抖音|TikTok`El proyecto de vídeo corto móvil tiene un avance del 90%. Usado lo último`Vue`Pila de tecnología FamilyMart, que se basa en[`Vue3`](https://cn.vuejs.org/)、[`Vite5`](https://cn.vitejs.dev/)、[`Pinia`](https://pinia.vuejs.org/)lograr. Los datos se guardan localmente en el proyecto y el vídeo se recopila de`抖音|TikTok`, el atlas se recoge de`小红书|Xiaohongshu`,aprobar[`axios-mock-adapter`](https://github.com/ctimmerm/axios-mock-adapter)La biblioteca intercepta la API y devuelve datos json locales para simular solicitudes de backend reales.
`douyin-vue`es una parodia`抖音|TikTok`Proyecto de vídeo corto móvil.`Vue`"Mejores prácticas" en el lado móvil, comparables a las nativas`App`Experiencia sedosa y suave. Usado lo último`Vue`pila de tecnología, basada en[`Vue3`](https://cn.vuejs.org/)、[`Vite5`](https://cn.vitejs.dev/)、[`Pinia`](https://pinia.vuejs.org/)lograr. Los datos se guardan localmente en el proyecto a través de[`axios-mock-adapter`](https://github.com/ctimmerm/axios-mock-adapter)La biblioteca intercepta la API y devuelve datos json locales para simular solicitudes de backend reales.
<div>
<img width="150px" src='imgs/1.gif' />
@ -30,12 +30,14 @@
## Acceso en linea
Páginas del albergue:<https://zyronon.gitee.io/douyin/> (中国地区推荐访问这个地址)
Páginas de Github:<https://zyronon.github.io/douyin/>
Páginas del albergue:<https://dy.ttentau.top/>(Se recomienda visitar esta dirección en China)
Netlificar:<https://douyins.netlify.app/>
[//]: # "~~Vercel: [http://dy.ttentau.top/](http://dy.ttentau.top/)~~"
[//]: # "Vercel: [https://douyins.vercel.app](https://douyins.vercel.app)"
[//]: # "~~Netlify: [https://douyins.netlify.app/](https://douyins.netlify.app/)~~"
[//]: # "Gitee pages: [https://zyronon.gitee.io/douyin/](https://zyronon.gitee.io/douyin/) (中国地区推荐访问这个地址) "
[//]: # "Github pages: [https://zyronon.github.io/douyin/](https://zyronon.github.io/douyin/) "
[//]: # "Vercel和Netlify分别送的100G免费流量已经用完了...🤣"
@ -77,7 +79,7 @@ Abra su navegador y visite:<http://127.0.0.1:3000>
El video proviene de las siguientes celebridades de Douyin.
- `我是香秀 🐂🍺`:<https://v.douyin.com/iYRAPA2L/>
- `杨老虎 🐯(磕穿下巴掉牙版)`: <https://v.douyin.com/iYRA56de/>
- `杨老虎 🐯(磕穿下巴掉牙版)`:<https://v.douyin.com/iYRA56de/>
- `条子`:<https://v.douyin.com/iYRAaqjr/>
- `达莎 Digi`<https://v.douyin.com/iYRA6rwT/>
- `小橙子`:<https://v.douyin.com/iYRAnudw/>
@ -86,7 +88,7 @@ El video proviene de las siguientes celebridades de Douyin.
- `奶茶妹 ◕🌱`:<https://v.douyin.com/iYRACKhP/>
- `我才是岚岚`:<https://v.douyin.com/iYRAQM1C/>
- `周憬艺 ziran`:<https://v.douyin.com/iYRAQs4h/>
- `刘思瑶 nice`: <https://v.douyin.com/iYRAaERn/>
- `刘思瑶 nice`:<https://v.douyin.com/iYRAaERn/>
- `彭十六 elf`:<https://v.douyin.com/iYRAHrVG/>
- `李子柒`:<https://v.douyin.com/iYRA5B88/>
@ -97,7 +99,7 @@ El contenido anterior es toda información pública en Internet.
## Funciones y sugerencias
El proyecto se encuentra actualmente en las primeras etapas de desarrollo y continuamente se agregan nuevas funciones. Si tiene alguna característica o sugerencia para el software, no dude en contactarnos.`Issues`criado en
Si también le gustan las ideas de diseño de este software, envíelas.`PR`, ¡Muchas gracias por tu apoyo!
Si también le gustan las ideas de diseño de este software, envíelas.`PR`,非常感谢你对我们的支持!
## contáctame

View File

@ -3,8 +3,8 @@
</h1>
<p align="center">
<a href="README.en.md">English</a> | <a href="README.es.md">Spanish</a> | <a href="README.de.md">German</a> |
<a href="README.fr.md">French</a> | <a href="../README.md">简体中文</a> | <a href="README.ja.md">日本語</a>
<a href="docs/README.en.md">English</a> | <a href="docs/README.es.md">Spanish</a> | <a href="docs/README.de.md">German</a> |
<a href="docs/README.fr.md">French</a> | <a href="README.md">简体中文</a> | <a href="docs/README.ja.md">日本語</a>
</p>
<p align="center">
@ -13,29 +13,31 @@
<a><img src="https://img.shields.io/badge/Powered%20by-Vue-blue"/></a>
</p>
`douyin-vue`est une parodie`抖音|TikTok`Le projet de courte vidéo mobile a un taux d'exhaustivité de 90 %. Utilisé le dernier`Vue`Pile technologique FamilyMart, basée sur[`Vue3`](https://cn.vuejs.org/)、[`Vite5`](https://cn.vitejs.dev/)、[`Pinia`](https://pinia.vuejs.org/)accomplir. Les données sont enregistrées localement dans le projet et la vidéo est collectée à partir de`抖音|TikTok`, l'atlas est collecté auprès de`小红书|Xiaohongshu`,passer[`axios-mock-adapter`](https://github.com/ctimmerm/axios-mock-adapter)La bibliothèque intercepte l'API et renvoie des données json locales pour simuler de véritables requêtes backend.
`douyin-vue`est une parodie`抖音|TikTok`projet de courte vidéo mobile.`Vue`Des « bonnes pratiques » côté mobile, comparables au natif`App`Expérience soyeuse et douce. Utilisé le dernier`Vue`pile technologique, basée sur[`Vue3`](https://cn.vuejs.org/)、[`Vite5`](https://cn.vitejs.dev/)、[`Pinia`](https://pinia.vuejs.org/)accomplir. Les données sont enregistrées localement dans le projet via[`axios-mock-adapter`](https://github.com/ctimmerm/axios-mock-adapter)La bibliothèque intercepte l'API et renvoie des données json locales pour simuler de véritables requêtes backend.
<div>
<img width="150px" src='imgs/1.gif' />
<img width="150px" src='imgs/2.gif' />
<img width="150px" src='imgs/3.gif' />
<img width="150px" src='imgs/4.gif' />
<img width="150px" src='imgs/5.gif' />
<img width="150px" src='imgs/img-1.jpg' />
<img width="150px" src='imgs/img-2.jpg' />
<img width="150px" src='imgs/img-3.jpg' />
<img width="150px" src='imgs/img-4.jpg' />
<img width="150px" src='imgs/img-5.jpg' />
<img width="150px" src='docs/imgs/1.gif' />
<img width="150px" src='docs/imgs/2.gif' />
<img width="150px" src='docs/imgs/3.gif' />
<img width="150px" src='docs/imgs/4.gif' />
<img width="150px" src='docs/imgs/5.gif' />
<img width="150px" src='docs/imgs/img-1.jpg' />
<img width="150px" src='docs/imgs/img-2.jpg' />
<img width="150px" src='docs/imgs/img-3.jpg' />
<img width="150px" src='docs/imgs/img-4.jpg' />
<img width="150px" src='docs/imgs/img-5.jpg' />
</div>
## accès en ligne
## Accès en ligne
Pages du gîte :<https://zyronon.gitee.io/douyin/>(Il est recommandé de visiter cette adresse en Chine)
Pages GitHub :<https://zyronon.github.io/douyin/>
Pages du gîte :<https://dy.ttentau.top/>(Il est recommandé de visiter cette adresse en Chine)
Netlifier :<https://douyins.netlify.app/>
[//]: # "~~Vercel: [http://dy.ttentau.top/](http://dy.ttentau.top/)~~"
[//]: # "Vercel: [https://douyins.vercel.app](https://douyins.vercel.app)"
[//]: # "~~Netlify: [https://douyins.netlify.app/](https://douyins.netlify.app/)~~"
[//]: # "Gitee pages: [https://zyronon.gitee.io/douyin/](https://zyronon.gitee.io/douyin/) (中国地区推荐访问这个地址) "
[//]: # "Github pages: [https://zyronon.github.io/douyin/](https://zyronon.github.io/douyin/) "
[//]: # "Vercel和Netlify分别送的100G免费流量已经用完了...🤣"
@ -47,7 +49,7 @@ Pages GitHub :<https://zyronon.github.io/douyin/>
## Lien
\[douyin-vue] Un :[200 lignes de code pour implémenter un composant carrousel similaire à Swiper.js](https://juejin.cn/post/7360512664317018146)
\[douyin-vue] Un :[200行代码实现类似Swiper.js的轮播组件](https://juejin.cn/post/7360512664317018146)
\[douyin-vue] Deuxièmement :[Réaliser l'effet "vidéo coulissante infinie" sur Douyin](https://juejin.cn/post/7361614921519054883)
D'autres articles sont en préparation...
@ -85,7 +87,7 @@ La vidéo provient des célébrités Douyin suivantes
- `小霸宠牛排 🥩`<https://v.douyin.com/iYRSosVB/>
- `奶茶妹 ◕🌱`:<https://v.douyin.com/iYRACKhP/>
- `我才是岚岚`:<https://v.douyin.com/iYRAQM1C/>
- `周憬艺 ziran`: <https://v.douyin.com/iYRAQs4h/>
- `周憬艺 ziran`:<https://v.douyin.com/iYRAQs4h/>
- `刘思瑶 nice`:<https://v.douyin.com/iYRAaERn/>
- `彭十六 elf`:<https://v.douyin.com/iYRAHrVG/>
- `李子柒`:<https://v.douyin.com/iYRA5B88/>

View File

@ -3,8 +3,8 @@
</h1>
<p align="center">
<a href="README.en.md">English</a> | <a href="README.es.md">Spanish</a> | <a href="README.de.md">German</a> |
<a href="README.fr.md">French</a> | <a href="../README.md">简体中文</a> | <a href="README.ja.md">日本語</a>
<a href="docs/README.en.md">English</a> | <a href="docs/README.es.md">Spanish</a> | <a href="docs/README.de.md">German</a> |
<a href="docs/README.fr.md">French</a> | <a href="../README.md">简体中文</a> | <a href="docs/README.ja.md">日本語</a>
</p>
<p align="center">
@ -13,7 +13,7 @@
<a><img src="https://img.shields.io/badge/Powered%20by-Vue-blue"/></a>
</p>
`douyin-vue`パロディです`抖音|TikTok`モバイル向けショートビデオプロジェクトの完成度は90。最新のものを使用しました`Vue` 全家桶技术栈,它基于 [`Vue3`](https://cn.vuejs.org/)、[`Vite5`](https://cn.vitejs.dev/)、[`Pinia`](https://pinia.vuejs.org/)成し遂げる。データはプロジェクトのローカルに保存され、ビデオは次から収集されます。`抖音|TikTok`、アトラスはから収集されています`小红书|Xiaohongshu`、合格[`axios-mock-adapter`](https://github.com/ctimmerm/axios-mock-adapter)ライブラリは API をインターセプトし、ローカルの JSON データを返して、実際のバックエンド リクエストをシミュレートします。
`douyin-vue`パロディです`抖音|TikTok`モバイルショートビデオプロジェクト。`Vue`ネイティブと同等のモバイル側の「ベスト プラクティス」`App`シルキーで滑らかな使い心地。最新のものを使用しました`Vue`テクノロジースタック、に基づく[`Vue3`](https://cn.vuejs.org/)、[`Vite5`](https://cn.vitejs.dev/)、[`Pinia`](https://pinia.vuejs.org/)成し遂げる。データはプロジェクト内でローカルに保存されます。[`axios-mock-adapter`](https://github.com/ctimmerm/axios-mock-adapter)ライブラリは API をインターセプトし、ローカルの JSON データを返して、実際のバックエンド リクエストをシミュレートします。
<div>
<img width="150px" src='imgs/1.gif' />
@ -30,12 +30,14 @@
## オンラインアクセス
Gite ページ:[hっtps://zyろのん。ぎてえ。いお/どうyいん/](https://zyronon.gitee.io/douyin/)(中国ではこのアドレスにアクセスすることをお勧めします)
Github ページ:[hっtps://zyろのん。ぎてゅb。いお/どうyいん/](https://zyronon.github.io/douyin/)
Gite ページ:[hっtps://dy。ってんたう。とp/](https://dy.ttentau.top/)(中国ではこのアドレスにアクセスすることをお勧めします)
ネットリファイ:[hっtps://どうyいんs。ねtぃfy。あっp/](https://douyins.netlify.app/)
[//]: # "~~Vercel: [http://dy.ttentau.top/](http://dy.ttentau.top/)~~"
[//]: # "Vercel: [https://douyins.vercel.app](https://douyins.vercel.app)"
[//]: # "~~Netlify: [https://douyins.netlify.app/](https://douyins.netlify.app/)~~"
[//]: # "Gitee pages: [https://zyronon.gitee.io/douyin/](https://zyronon.gitee.io/douyin/) (中国地区推荐访问这个地址) "
[//]: # "Github pages: [https://zyronon.github.io/douyin/](https://zyronon.github.io/douyin/) "
[//]: # "Vercel和Netlify分别送的100G免费流量已经用完了...🤣"
@ -96,12 +98,12 @@ npm run dev
## 特徴と提案
プロジェクトは現在開発の初期段階にあり、ソフトウェアの新機能や提案があれば、お気軽にお問い合わせください。`Issues`で育ちました
プロジェクトは現在開発の初期段階にあり、新しい機能が継続的に追加されています。ソフトウェアに関する機能や提案がありましたら、お気軽にお問い合わせください。`Issues`で育ちました
このソフトウェアのデザインアイデアも気に入っていただけましたら、ぜひ送信してください`PR`、 ご支援ありがとうございました!
## 私に連絡して
私のメールアドレスにご連絡いただけます<a href="mailto:zyronon@163.com">zyろのん@163。こm</a>
您可以联系我的邮箱 <a href="mailto:zyronon@163.com">zyろのん@163。こm</a>
> 私の他のオープンソース プロジェクトを共有してください:
>

3
env.d.ts vendored
View File

@ -1,10 +1,13 @@
/// <reference types="vite/client" />
/// <reference types="unplugin-vue-macros/macros-global" />
declare const LATEST_COMMIT_HASH: string
declare global {
interface Window {
isMoved: boolean
isMuted: boolean
showMutedNotice: boolean
}
interface Navigator {

View File

@ -27,7 +27,6 @@
"axios-mock-adapter": "^1.22.0",
"core-js": "3.21.1",
"libarchive-wasm": "^1.1.0",
"mitt": "3.0.0",
"mockjs": "^1.1.0",
"pinia": "^2.1.7",
"vue": "3.4.21",
@ -58,7 +57,7 @@
"prettier": "^3.2.5",
"rollup-plugin-visualizer": "^5.9.2",
"typescript": "5.3.3",
"unplugin-vue-define-options": "^1.4.1",
"unplugin-vue-macros": "^2.9.1",
"vite": "^5.1.7",
"vite-plugin-cdn-import": "0.3.5",
"vite-plugin-commonjs": "^0.10.1",

View File

@ -20,9 +20,6 @@ dependencies:
libarchive-wasm:
specifier: ^1.1.0
version: 1.1.0
mitt:
specifier: 3.0.0
version: 3.0.0
mockjs:
specifier: ^1.1.0
version: 1.1.0
@ -109,9 +106,9 @@ devDependencies:
typescript:
specifier: 5.3.3
version: 5.3.3
unplugin-vue-define-options:
specifier: ^1.4.1
version: 1.4.2(rollup@2.79.1)(vue@3.4.21)
unplugin-vue-macros:
specifier: ^2.9.1
version: 2.9.1(rollup@2.79.1)(typescript@5.3.3)(vite@5.1.7)(vue@3.4.21)
vite:
specifier: ^5.1.7
version: 5.1.7(@types/node@20.12.4)(less@4.1.3)
@ -140,6 +137,10 @@ packages:
'@jridgewell/trace-mapping': 0.3.20
dev: true
/@antfu/utils@0.7.7:
resolution: {integrity: sha512-gFPqTG7otEJ8uP6wrhDv6mqwGWYZKNvAcCq6u9hOj0c+IKCEsY4L1oC9trPq2SaWIzAfHvqfBDxF591JkMf+kg==}
dev: true
/@babel/code-frame@7.22.13:
resolution: {integrity: sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==}
engines: {node: '>=6.9.0'}
@ -401,6 +402,14 @@ packages:
'@babel/types': 7.24.0
dev: true
/@babel/parser@7.24.4:
resolution: {integrity: sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==}
engines: {node: '>=6.0.0'}
hasBin: true
dependencies:
'@babel/types': 7.24.0
dev: true
/@babel/plugin-syntax-jsx@7.22.5(@babel/core@7.24.3):
resolution: {integrity: sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==}
engines: {node: '>=6.9.0'}
@ -1034,6 +1043,10 @@ packages:
engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
dev: true
/@polka/url@1.0.0-next.25:
resolution: {integrity: sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==}
dev: true
/@rollup/plugin-commonjs@25.0.7(rollup@2.79.1):
resolution: {integrity: sha512-nEvcR+LRjEjsaSsc4x3XZfCCvZIaSMenZu/OiwOKGN2UhQpAYI7ru7czFvyWbErlpoGjnSX3D5Ch5FcMA3kRWQ==}
engines: {node: '>=14.0.0'}
@ -1426,8 +1439,54 @@ packages:
path-browserify: r2.cnpmjs.org/path-browserify@1.0.1
dev: true
/@vue-macros/common@1.10.1(rollup@2.79.1)(vue@3.4.21):
resolution: {integrity: sha512-uftSpfwdwitcQT2lM8aVxcfe5rKQBzC9jMrtJM5sG4hEuFyfIvnJihpPpnaWxY+X4p64k+YYXtBFv+1O5Bq3dg==}
/@vue-macros/api@0.9.5(rollup@2.79.1)(vue@3.4.21):
resolution: {integrity: sha512-ybaOuoB3HIMJsH2Cj3903cf6YM65UOl7U1Vbq4ZH4drDLymlgIqEri5ufhq76XXn6mi6xx4cZ3JUqo5VwteHkQ==}
engines: {node: '>=16.14.0'}
dependencies:
'@babel/types': 7.24.0
'@vue-macros/common': 1.10.2(rollup@2.79.1)(vue@3.4.21)
resolve.exports: 2.0.2
transitivePeerDependencies:
- rollup
- vue
dev: true
/@vue-macros/better-define@1.7.5(rollup@2.79.1)(vue@3.4.21):
resolution: {integrity: sha512-XKByxQ+867gujPUKfRWnC5ajBfFChX2bgqVGK5fSVr+EAbkxZmMAa6KhxkGTWSn0R0T7TJIULXGlRj0TV4j6EQ==}
engines: {node: '>=16.14.0'}
dependencies:
'@vue-macros/api': 0.9.5(rollup@2.79.1)(vue@3.4.21)
'@vue-macros/common': 1.10.2(rollup@2.79.1)(vue@3.4.21)
unplugin: 1.10.1
transitivePeerDependencies:
- rollup
- vue
dev: true
/@vue-macros/boolean-prop@0.3.3(rollup@2.79.1)(vue@3.4.21):
resolution: {integrity: sha512-FAHBAXtI0qcoLIfq5AAfHokz191nC/ciYcqbBUygvI4DEPINOnrb/QN0M56LkszJUl7girx/JxUOixUDHozUyA==}
engines: {node: '>=16.14.0'}
dependencies:
'@vue-macros/common': 1.10.2(rollup@2.79.1)(vue@3.4.21)
'@vue/compiler-core': 3.4.21
transitivePeerDependencies:
- rollup
- vue
dev: true
/@vue-macros/chain-call@0.2.3(rollup@2.79.1)(vue@3.4.21):
resolution: {integrity: sha512-THXfqdpqcdcz0ugCW3AfTcAqa6vXeHHCgKsDc9wvdITjsxIwiXmGIiA22rNZxdXGnXVSY+v18VdzChv/dbZ0RA==}
engines: {node: '>=16.14.0'}
dependencies:
'@vue-macros/common': 1.10.2(rollup@2.79.1)(vue@3.4.21)
unplugin: 1.10.1
transitivePeerDependencies:
- rollup
- vue
dev: true
/@vue-macros/common@1.10.2(rollup@2.79.1)(vue@3.4.21):
resolution: {integrity: sha512-WC66NPVh2mJWqm4L0l/u/cOqm4pNOIwVdMGnDYAH2rHcOWy5x68GkhpkYTBu1+xwCSeHWOQn1TCGGbD+98fFpA==}
engines: {node: '>=16.14.0'}
peerDependencies:
vue: ^2.7.0 || ^3.2.25
@ -1438,7 +1497,7 @@ packages:
'@babel/types': 7.24.0
'@rollup/pluginutils': 5.1.0(rollup@2.79.1)
'@vue/compiler-sfc': 3.4.21
ast-kit: 0.11.3(rollup@2.79.1)
ast-kit: 0.12.1
local-pkg: 0.5.0
magic-string-ast: 0.3.0
vue: 3.4.21(typescript@5.3.3)
@ -1446,6 +1505,280 @@ packages:
- rollup
dev: true
/@vue-macros/define-emit@0.2.5(rollup@2.79.1)(vue@3.4.21):
resolution: {integrity: sha512-QsmzVLkxYdPaJr5hi/S3K9hr9hQ8Q55SIMmDiUsYABJpmSzczGv6HcJKkvP3k1J5UHxGx9rkytTv5KKxEaAYyw==}
engines: {node: '>=16.14.0'}
peerDependencies:
vue: ^2.7.0 || ^3.2.25
dependencies:
'@vue-macros/api': 0.9.5(rollup@2.79.1)(vue@3.4.21)
'@vue-macros/common': 1.10.2(rollup@2.79.1)(vue@3.4.21)
unplugin: 1.10.1
vue: 3.4.21(typescript@5.3.3)
transitivePeerDependencies:
- rollup
dev: true
/@vue-macros/define-models@1.2.3(rollup@2.79.1)(vue@3.4.21):
resolution: {integrity: sha512-yeAcE3W9wZG1tePzY6+Ldpzj+zZJs7YZcQGLYxoXiEOii5Koh5VLaLm+qEQaXToMwjV/904YaJHKPH7Gsi0Tfg==}
engines: {node: '>=16.14.0'}
peerDependencies:
'@vueuse/core': '>=9.0.0'
peerDependenciesMeta:
'@vueuse/core':
optional: true
dependencies:
'@vue-macros/common': 1.10.2(rollup@2.79.1)(vue@3.4.21)
ast-walker-scope: 0.6.1
unplugin: 1.10.1
transitivePeerDependencies:
- rollup
- vue
dev: true
/@vue-macros/define-prop@0.3.5(rollup@2.79.1)(vue@3.4.21):
resolution: {integrity: sha512-1eTmUQh5Oz2UldFPlsK6CuNw8N+zIUGIQB8SxgN8m0V0xKvyJpjJrSWs0WfFBivCl+gxYJUZ7ZjiwTuCc9Z7kA==}
engines: {node: '>=16.14.0'}
peerDependencies:
vue: ^2.7.0 || ^3.2.25
dependencies:
'@vue-macros/api': 0.9.5(rollup@2.79.1)(vue@3.4.21)
'@vue-macros/common': 1.10.2(rollup@2.79.1)(vue@3.4.21)
unplugin: 1.10.1
vue: 3.4.21(typescript@5.3.3)
transitivePeerDependencies:
- rollup
dev: true
/@vue-macros/define-props-refs@1.2.3(rollup@2.79.1)(vue@3.4.21):
resolution: {integrity: sha512-7nZKCZhr5CsQ93wBHauvwO3/NxYe6+IP2mvKYBxAlq9oADGptZbrK6jarUpBE2V0tTyq0AynfAOG6GueGxvJEg==}
engines: {node: '>=16.14.0'}
peerDependencies:
vue: ^2.7.0 || ^3.2.25
dependencies:
'@vue-macros/common': 1.10.2(rollup@2.79.1)(vue@3.4.21)
unplugin: 1.10.1
vue: 3.4.21(typescript@5.3.3)
transitivePeerDependencies:
- rollup
dev: true
/@vue-macros/define-props@2.0.4(@vue-macros/reactivity-transform@0.4.4)(rollup@2.79.1)(vue@3.4.21):
resolution: {integrity: sha512-opifxLT9yF+A/bEfEpuFxNcAMPEmnPv/ewlCDmOH8VX+CBnlWbDqY0n0LcimPGRTYkRDAkNBHRRQulxNfRXNpw==}
engines: {node: '>=16.14.0'}
peerDependencies:
'@vue-macros/reactivity-transform': ^0.4.4
vue: ^2.7.0 || ^3.2.25
dependencies:
'@vue-macros/common': 1.10.2(rollup@2.79.1)(vue@3.4.21)
'@vue-macros/reactivity-transform': 0.4.4(rollup@2.79.1)(vue@3.4.21)
unplugin: 1.10.1
vue: 3.4.21(typescript@5.3.3)
transitivePeerDependencies:
- rollup
dev: true
/@vue-macros/define-render@1.5.3(rollup@2.79.1)(vue@3.4.21):
resolution: {integrity: sha512-phdDLTHvZi0AxK2kEJ1Gt6TDMH9vHQib+eU5k+GXV/WPz43n+Cp4a9tq5Mpkc1rojc796w/+O1bE6jE0fyGxjw==}
engines: {node: '>=16.14.0'}
peerDependencies:
vue: ^2.7.0 || ^3.0.0
dependencies:
'@vue-macros/common': 1.10.2(rollup@2.79.1)(vue@3.4.21)
unplugin: 1.10.1
vue: 3.4.21(typescript@5.3.3)
transitivePeerDependencies:
- rollup
dev: true
/@vue-macros/define-slots@1.1.3(rollup@2.79.1)(vue@3.4.21):
resolution: {integrity: sha512-b8lhEOMS8kl3x2ihOIrfz9xjCCUdBKliLzs5mqdQlaLRVRSxHxXVnBq1Ek7dCIxrc2Mp9VyvBn7E4Q4i0StpmQ==}
engines: {node: '>=16.14.0'}
peerDependencies:
vue: ^2.7.0 || ^3.0.0
dependencies:
'@vue-macros/common': 1.10.2(rollup@2.79.1)(vue@3.4.21)
unplugin: 1.10.1
vue: 3.4.21(typescript@5.3.3)
transitivePeerDependencies:
- rollup
dev: true
/@vue-macros/devtools@0.2.0(typescript@5.3.3)(vite@5.1.7):
resolution: {integrity: sha512-jHjvY1bFgQLe/2+5pBOG4fgmL5MPhsqQDj7Barhj8YN+Oe7U2hBImvfAyOGpqd2uucLOWQTP1cWrp3q9b1svsg==}
engines: {node: '>=16.14.0'}
peerDependencies:
vite: ^4.0.0 || ^5.0.0-0
peerDependenciesMeta:
vite:
optional: true
dependencies:
sirv: 2.0.4
vite: 5.1.7(@types/node@20.12.4)(less@4.1.3)
vue: 3.4.21(typescript@5.3.3)
transitivePeerDependencies:
- typescript
dev: true
/@vue-macros/export-expose@0.1.3(rollup@2.79.1)(vue@3.4.21):
resolution: {integrity: sha512-K2cFoVXqzLjVe0kpOKS+QlLdI3P9+zjDDj8LQQreaWTBuAYQIyEIIjEt5aw5MImLrmmoSqbWNFf/iiZNJrDl1w==}
engines: {node: '>=16.14.0'}
peerDependencies:
vue: ^2.7.0 || ^3.2.25
dependencies:
'@vue-macros/common': 1.10.2(rollup@2.79.1)(vue@3.4.21)
'@vue/compiler-sfc': 3.4.21
unplugin: 1.10.1
vue: 3.4.21(typescript@5.3.3)
transitivePeerDependencies:
- rollup
dev: true
/@vue-macros/export-props@0.4.3(rollup@2.79.1)(vue@3.4.21):
resolution: {integrity: sha512-UhIZFb9lwuZfuOdPTUIRs4D74YGdZjBKpUZNjDQG1P2VbIsqXZ5nwKo1nPH4XYoAzXmJcpGqP+gwemCITpTewA==}
engines: {node: '>=16.14.0'}
peerDependencies:
vue: ^2.7.0 || ^3.2.25
dependencies:
'@vue-macros/common': 1.10.2(rollup@2.79.1)(vue@3.4.21)
unplugin: 1.10.1
vue: 3.4.21(typescript@5.3.3)
transitivePeerDependencies:
- rollup
dev: true
/@vue-macros/export-render@0.2.3(rollup@2.79.1)(vue@3.4.21):
resolution: {integrity: sha512-0iQnVNxMuTjfmF1N6mWR+21dClHwJRd/WJXwGhjABOBX8g90JM7kj0pXvhdpQZ4CBiDTHrNMl0s4C0c3tjwjnw==}
engines: {node: '>=16.14.0'}
peerDependencies:
vue: ^2.7.0 || ^3.2.25
dependencies:
'@vue-macros/common': 1.10.2(rollup@2.79.1)(vue@3.4.21)
'@vue/compiler-sfc': 3.4.21
unplugin: 1.10.1
vue: 3.4.21(typescript@5.3.3)
transitivePeerDependencies:
- rollup
dev: true
/@vue-macros/hoist-static@1.5.3(rollup@2.79.1)(vue@3.4.21):
resolution: {integrity: sha512-17IcyI2EnMRgC7YtDr1PpjI4inca7jqSeRJZVHemU9oYZxYes1lIh5A/x18vVh1+ZP2xFFHjJr69AEhPzedk1g==}
engines: {node: '>=16.14.0'}
dependencies:
'@vue-macros/common': 1.10.2(rollup@2.79.1)(vue@3.4.21)
unplugin: 1.10.1
transitivePeerDependencies:
- rollup
- vue
dev: true
/@vue-macros/jsx-directive@0.8.12(rollup@2.79.1)(vue@3.4.21):
resolution: {integrity: sha512-+50MSQfcG5d+Sv2AVi3DAOSxcVmEuxdpghZzismg1dYWPikbFu7f4RH6wvexFnCjKoYKDw/E02DBup5wLEGJSA==}
engines: {node: '>=16.14.0'}
dependencies:
'@vue-macros/common': 1.10.2(rollup@2.79.1)(vue@3.4.21)
unplugin: 1.10.1
transitivePeerDependencies:
- rollup
- vue
dev: true
/@vue-macros/named-template@0.4.3(rollup@2.79.1)(vue@3.4.21):
resolution: {integrity: sha512-d3PcaVE/aSF7sHOJrbQlNZaODQYpTidbSk4DK6i/ucgYBD5eOx3dwr/37gtmjLu4vXM1l8igouaSLhWVf3bPsg==}
engines: {node: '>=16.14.0'}
dependencies:
'@vue-macros/common': 1.10.2(rollup@2.79.1)(vue@3.4.21)
'@vue/compiler-dom': 3.4.21
unplugin: 1.10.1
transitivePeerDependencies:
- rollup
- vue
dev: true
/@vue-macros/reactivity-transform@0.4.4(rollup@2.79.1)(vue@3.4.21):
resolution: {integrity: sha512-Yn22Ls+KAJzjwdjrjwaDkjx+lxSXlk4ev+s0hD9biTpjaf1Sv7AKYq5381TGZIeDadklkhHzYwQWueROqvpG6w==}
engines: {node: '>=16.14.0'}
peerDependencies:
vue: ^2.7.0 || ^3.2.25
dependencies:
'@babel/parser': 7.24.4
'@vue-macros/common': 1.10.2(rollup@2.79.1)(vue@3.4.21)
'@vue/compiler-core': 3.4.21
'@vue/shared': 3.4.21
magic-string: 0.30.10
unplugin: 1.10.1
vue: 3.4.21(typescript@5.3.3)
transitivePeerDependencies:
- rollup
dev: true
/@vue-macros/setup-block@0.3.3(rollup@2.79.1)(vue@3.4.21):
resolution: {integrity: sha512-06UnxX8wDKJcJHvSgnxi7aJo2jdGvbeAur+aSLcmYgTfNUwRtuC2KmJKQohjos24USpQEYyGqMKPYuxkdoQ+Wg==}
engines: {node: '>=16.14.0'}
dependencies:
'@vue-macros/common': 1.10.2(rollup@2.79.1)(vue@3.4.21)
'@vue/compiler-dom': 3.4.21
unplugin: 1.10.1
transitivePeerDependencies:
- rollup
- vue
dev: true
/@vue-macros/setup-component@0.17.3(rollup@2.79.1)(vue@3.4.21):
resolution: {integrity: sha512-zBZCPBhVh5gZMKQKE/K+SJYiXjIoK+Hc/FxhHkijZd4njx2a3CtpW5BX3bDr0498E78+f7vlqcPHaE9IRNUGsQ==}
engines: {node: '>=16.14.0'}
dependencies:
'@vue-macros/common': 1.10.2(rollup@2.79.1)(vue@3.4.21)
unplugin: 1.10.1
transitivePeerDependencies:
- rollup
- vue
dev: true
/@vue-macros/setup-sfc@0.17.3(rollup@2.79.1)(vue@3.4.21):
resolution: {integrity: sha512-6D6UMLi1qdgpBhgwRo2VevVpNlo9QtnzsOIag4seAl3zEI1jB5KfOoUWl8yHZ5MUGfs5jSPzOhlQfEzefrgO4g==}
engines: {node: '>=16.14.0'}
dependencies:
'@vue-macros/common': 1.10.2(rollup@2.79.1)(vue@3.4.21)
unplugin: 1.10.1
transitivePeerDependencies:
- rollup
- vue
dev: true
/@vue-macros/short-bind@0.2.3(rollup@2.79.1)(vue@3.4.21):
resolution: {integrity: sha512-3QwHQQDVNpsWh36/q4sB5QmGGedwIZUmL2rvQ8YQD6EA455samG0r2zB9Q6Z7DA8+qk6TjpmkvltubDY9TWtEQ==}
engines: {node: '>=16.14.0'}
dependencies:
'@vue-macros/common': 1.10.2(rollup@2.79.1)(vue@3.4.21)
'@vue/compiler-core': 3.4.21
transitivePeerDependencies:
- rollup
- vue
dev: true
/@vue-macros/short-emits@1.5.3(rollup@2.79.1)(vue@3.4.21):
resolution: {integrity: sha512-DTzJ1Bj2cwJK9kCRWw9VUeNjuAnmyXoTC05J76lGBa7Ftr/04UZM31h8/NyTKqG/oXHBnNa4X8kGy9A7kRwG9g==}
engines: {node: '>=16.14.0'}
dependencies:
'@vue-macros/common': 1.10.2(rollup@2.79.1)(vue@3.4.21)
unplugin: 1.10.1
transitivePeerDependencies:
- rollup
- vue
dev: true
/@vue-macros/short-vmodel@1.4.3(rollup@2.79.1)(vue@3.4.21):
resolution: {integrity: sha512-ZQph4GuKl4kEXtzGDddqSgfykAZ9cT7tu14G4K3ZGJ8wsLmhuLGWfFL596UVg5zfVyMWuC/SbTmR8UEp/eMPJA==}
engines: {node: '>=16.14.0'}
dependencies:
'@vue-macros/common': 1.10.2(rollup@2.79.1)(vue@3.4.21)
'@vue/compiler-core': 3.4.21
transitivePeerDependencies:
- rollup
- vue
dev: true
/@vue/babel-helper-vue-transform-on@1.1.5:
resolution: {integrity: sha512-SgUymFpMoAyWeYWLAY+MkCK3QEROsiUnfaw5zxOVD/M64KQs8D/4oK6Q5omVA2hnvEOE0SCkH2TZxs/jnnUj7w==}
dev: true
@ -1679,36 +2012,20 @@ packages:
engines: {node: '>=8'}
dev: true
/ast-kit@0.11.3(rollup@2.79.1):
resolution: {integrity: sha512-qdwwKEhckRk0XE22/xDdmU3v/60E8Edu4qFhgTLIhGGDs/PAJwLw9pQn8Rj99PitlbBZbYpx0k/lbir4kg0SuA==}
/ast-kit@0.12.1:
resolution: {integrity: sha512-O+33g7x6irsESUcd47KdfWUrS2F6aGp9KeVJFGj0YjIznfXpBxVGjA0w+y/1OKqX4mFOfmZ9Xpf1ixPT4n9xxw==}
engines: {node: '>=16.14.0'}
dependencies:
'@babel/parser': 7.24.0
'@rollup/pluginutils': 5.1.0(rollup@2.79.1)
'@babel/parser': 7.24.4
pathe: 1.1.2
transitivePeerDependencies:
- rollup
dev: true
/ast-kit@0.9.5(rollup@2.79.1):
resolution: {integrity: sha512-kbL7ERlqjXubdDd+szuwdlQ1xUxEz9mCz1+m07ftNVStgwRb2RWw+U6oKo08PAvOishMxiqz1mlJyLl8yQx2Qg==}
/ast-walker-scope@0.6.1:
resolution: {integrity: sha512-0ZdQEsSfH3mX4BFbRCc3xOBjx5bDbm73+aAdQOHerPQNf8K0XFMAv79ucd2BpnSc4UMyvBDixiroT8yjm2Y6bw==}
engines: {node: '>=16.14.0'}
dependencies:
'@babel/parser': 7.24.0
'@rollup/pluginutils': 5.1.0(rollup@2.79.1)
pathe: 1.1.2
transitivePeerDependencies:
- rollup
dev: true
/ast-walker-scope@0.5.0(rollup@2.79.1):
resolution: {integrity: sha512-NsyHMxBh4dmdEHjBo1/TBZvCKxffmZxRYhmclfu0PP6Aftre47jOHYaYaNqJcV0bxihxFXhDkzLHUwHc0ocd0Q==}
engines: {node: '>=16.14.0'}
dependencies:
'@babel/parser': 7.24.0
ast-kit: 0.9.5(rollup@2.79.1)
transitivePeerDependencies:
- rollup
'@babel/parser': 7.24.4
ast-kit: 0.12.1
dev: true
/axios-mock-adapter@1.22.0(axios@1.6.8):
@ -2888,6 +3205,12 @@ packages:
sourcemap-codec: 1.4.8
dev: true
/magic-string@0.30.10:
resolution: {integrity: sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==}
dependencies:
'@jridgewell/sourcemap-codec': 1.4.15
dev: true
/magic-string@0.30.7:
resolution: {integrity: sha512-8vBuFF/I/+OSLRmdf2wwFCJCz+nSn0m6DPvGH1fS/KiQoSaR+sETbov0eIk9KhEKy8CYqIkIAnbohxT/4H0kuA==}
engines: {node: '>=12'}
@ -2980,10 +3303,6 @@ packages:
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
dev: true
/mitt@3.0.0:
resolution: {integrity: sha512-7dX2/10ITVyqh4aOSVI9gdape+t9l2/8QxHrFmUXu4EEUpdlxl6RudZUPZoc+zuY2hk1j7XxVroIVIan/pD/SQ==}
dev: false
/mlly@1.6.1:
resolution: {integrity: sha512-vLgaHvaeunuOXHSmEbZ9izxPx3USsk8KCQ8iC+aTlp5sKRSoZvwhHh5L9VbKSaVC6sJDqbyohIS76E2VmHIPAA==}
dependencies:
@ -3000,6 +3319,11 @@ packages:
commander: 1.1.1
dev: false
/mrmime@2.0.0:
resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==}
engines: {node: '>=10'}
dev: true
/ms@2.1.2:
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
dev: true
@ -3257,6 +3581,11 @@ packages:
engines: {node: '>=4'}
dev: true
/resolve.exports@2.0.2:
resolution: {integrity: sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==}
engines: {node: '>=10'}
dev: true
/restore-cursor@4.0.0:
resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
@ -3409,6 +3738,15 @@ packages:
engines: {node: '>=14'}
dev: true
/sirv@2.0.4:
resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==}
engines: {node: '>= 10'}
dependencies:
'@polka/url': 1.0.0-next.25
mrmime: 2.0.0
totalist: 3.0.1
dev: true
/slash@3.0.0:
resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
engines: {node: '>=8'}
@ -3546,6 +3884,11 @@ packages:
is-number: 7.0.0
dev: true
/totalist@3.0.1:
resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==}
engines: {node: '>=6'}
dev: true
/ts-api-utils@1.3.0(typescript@5.3.3):
resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==}
engines: {node: '>=16'}
@ -3594,20 +3937,89 @@ packages:
engines: {node: '>= 10.0.0'}
dev: true
/unplugin-vue-define-options@1.4.2(rollup@2.79.1)(vue@3.4.21):
resolution: {integrity: sha512-jQ3nJ1olC107QUA67UEB1CWJXnbVA7SF4UibKQF+jvME7UZ/XomctISHtAkJSJ9YHn0eqnqqzyNkng/KnLUZBw==}
/unplugin-combine@0.9.0(rollup@2.79.1)(vite@5.1.7):
resolution: {integrity: sha512-1bXgHXIhw/bNEFCwNnYRlOOcamsBNQObSWBuy3FcDcnMoFLIi4ZaMsi/L0cNxltfYBTS+QvGSZ1F+LgQ0vbcLg==}
engines: {node: '>=16.14.0'}
peerDependencies:
esbuild: '>=0.13'
rollup: ^3.2.0 || ^4.0.0
vite: ^2.3.0 || ^3.0.0 || ^4.0.0 || ^5.0.0
webpack: 4 || 5
peerDependenciesMeta:
esbuild:
optional: true
rollup:
optional: true
vite:
optional: true
webpack:
optional: true
dependencies:
'@antfu/utils': 0.7.7
rollup: 2.79.1
unplugin: 1.10.1
vite: 5.1.7(@types/node@20.12.4)(less@4.1.3)
dev: true
/unplugin-vue-define-options@1.4.3(rollup@2.79.1)(vue@3.4.21):
resolution: {integrity: sha512-CN5xF8l8bySD6okw6PCt1zWFHf5vX+q4Cg2ssn9usANHtxmeyCgMccC7ywZyzI32dQS+pq6hvuSz/GewtYnbEQ==}
engines: {node: '>=16.14.0'}
dependencies:
'@vue-macros/common': 1.10.1(rollup@2.79.1)(vue@3.4.21)
ast-walker-scope: 0.5.0(rollup@2.79.1)
unplugin: 1.7.1
'@vue-macros/common': 1.10.2(rollup@2.79.1)(vue@3.4.21)
ast-walker-scope: 0.6.1
unplugin: 1.10.1
transitivePeerDependencies:
- rollup
- vue
dev: true
/unplugin@1.7.1:
resolution: {integrity: sha512-JqzORDAPxxs8ErLV4x+LL7bk5pk3YlcWqpSNsIkAZj972KzFZLClc/ekppahKkOczGkwIG6ElFgdOgOlK4tXZw==}
/unplugin-vue-macros@2.9.1(rollup@2.79.1)(typescript@5.3.3)(vite@5.1.7)(vue@3.4.21):
resolution: {integrity: sha512-r9y6e5GhUgRGzHr+Od9X6S2irdzwSAdU2BvSz0dXN00tDHNm/Y/iCn/Iypdzbe4ai9b09lMfB5MFUpT3jfOlQA==}
engines: {node: '>=16.14.0'}
peerDependencies:
vue: ^2.7.0 || ^3.2.25
dependencies:
'@vue-macros/better-define': 1.7.5(rollup@2.79.1)(vue@3.4.21)
'@vue-macros/boolean-prop': 0.3.3(rollup@2.79.1)(vue@3.4.21)
'@vue-macros/chain-call': 0.2.3(rollup@2.79.1)(vue@3.4.21)
'@vue-macros/common': 1.10.2(rollup@2.79.1)(vue@3.4.21)
'@vue-macros/define-emit': 0.2.5(rollup@2.79.1)(vue@3.4.21)
'@vue-macros/define-models': 1.2.3(rollup@2.79.1)(vue@3.4.21)
'@vue-macros/define-prop': 0.3.5(rollup@2.79.1)(vue@3.4.21)
'@vue-macros/define-props': 2.0.4(@vue-macros/reactivity-transform@0.4.4)(rollup@2.79.1)(vue@3.4.21)
'@vue-macros/define-props-refs': 1.2.3(rollup@2.79.1)(vue@3.4.21)
'@vue-macros/define-render': 1.5.3(rollup@2.79.1)(vue@3.4.21)
'@vue-macros/define-slots': 1.1.3(rollup@2.79.1)(vue@3.4.21)
'@vue-macros/devtools': 0.2.0(typescript@5.3.3)(vite@5.1.7)
'@vue-macros/export-expose': 0.1.3(rollup@2.79.1)(vue@3.4.21)
'@vue-macros/export-props': 0.4.3(rollup@2.79.1)(vue@3.4.21)
'@vue-macros/export-render': 0.2.3(rollup@2.79.1)(vue@3.4.21)
'@vue-macros/hoist-static': 1.5.3(rollup@2.79.1)(vue@3.4.21)
'@vue-macros/jsx-directive': 0.8.12(rollup@2.79.1)(vue@3.4.21)
'@vue-macros/named-template': 0.4.3(rollup@2.79.1)(vue@3.4.21)
'@vue-macros/reactivity-transform': 0.4.4(rollup@2.79.1)(vue@3.4.21)
'@vue-macros/setup-block': 0.3.3(rollup@2.79.1)(vue@3.4.21)
'@vue-macros/setup-component': 0.17.3(rollup@2.79.1)(vue@3.4.21)
'@vue-macros/setup-sfc': 0.17.3(rollup@2.79.1)(vue@3.4.21)
'@vue-macros/short-bind': 0.2.3(rollup@2.79.1)(vue@3.4.21)
'@vue-macros/short-emits': 1.5.3(rollup@2.79.1)(vue@3.4.21)
'@vue-macros/short-vmodel': 1.4.3(rollup@2.79.1)(vue@3.4.21)
unplugin: 1.10.1
unplugin-combine: 0.9.0(rollup@2.79.1)(vite@5.1.7)
unplugin-vue-define-options: 1.4.3(rollup@2.79.1)(vue@3.4.21)
vue: 3.4.21(typescript@5.3.3)
transitivePeerDependencies:
- '@vueuse/core'
- esbuild
- rollup
- typescript
- vite
- webpack
dev: true
/unplugin@1.10.1:
resolution: {integrity: sha512-d6Mhq8RJeGA8UfKCu54Um4lFA0eSaRa3XxdAJg8tIdxbu1ubW0hBCZUL7yI2uGyYCRndvbK8FLHzqy2XKfeMsg==}
engines: {node: '>=14.0.0'}
dependencies:
acorn: 8.11.3
chokidar: 3.6.0

View File

@ -400,163 +400,6 @@
]
}
},
{
"aweme_id": "7346191904205327631",
"desc": "我的女友",
"create_time": 1710418599,
"music": {
"id": 7346191940615933000,
"title": "@条子创作的原声",
"author": "条子",
"cover_medium": {
"uri": "720x720/aweme-avatar/tos-cn-avt-0015_75c5ef8973e1d665252306ea58f7d10b",
"url_list": [
"https://p3-pc.douyinpic.com/aweme/720x720/aweme-avatar/tos-cn-avt-0015_75c5ef8973e1d665252306ea58f7d10b.jpeg?from=116350172"
],
"width": 720,
"height": 720
},
"cover_thumb": {
"uri": "100x100/aweme-avatar/tos-cn-avt-0015_75c5ef8973e1d665252306ea58f7d10b",
"url_list": [
"https://p3-pc.douyinpic.com/aweme/100x100/aweme-avatar/tos-cn-avt-0015_75c5ef8973e1d665252306ea58f7d10b.jpeg?from=116350172"
],
"width": 720,
"height": 720
},
"play_url": {
"uri": "https://sf5-hl-cdn-tos.douyinstatic.com/obj/ies-music/7346191933737356059.mp3",
"url_list": [
"https://sf5-hl-cdn-tos.douyinstatic.com/obj/ies-music/7346191933737356059.mp3",
"https://sf6-cdn-tos.douyinstatic.com/obj/ies-music/7346191933737356059.mp3"
],
"width": 720,
"height": 720,
"url_key": "7346191940615932722"
},
"duration": 7,
"user_count": 0,
"owner_id": "83160533866",
"owner_nickname": "条子",
"is_original": false
},
"video": {
"play_addr": {
"uri": "v0300fg10000cnpel5bc77u9pqctt5hg",
"url_list": [
"https://www.douyin.com/aweme/v1/play/?video_id=v0300fg10000cnpel5bc77u9pqctt5hg&line=0&file_id=0ab371e7a5ac419fb88d8b616f1b9a70&sign=c689ddfb4d16aec5ae605822e5b2c4f6&is_play_url=1&source=PackSourceEnum_PUBLISH"
],
"width": 1870,
"height": 1052,
"url_key": "v0300fg10000cnpel5bc77u9pqctt5hg_h264_1080p_2690491",
"data_size": 2467517,
"file_hash": "c689ddfb4d16aec5ae605822e5b2c4f6",
"file_cs": "c:0-7442-daae|d:0-1233757-8a1a,1233758-2467516-f27e|a:v0300fg10000cnpel5bc77u9pqctt5hg"
},
"cover": {
"uri": "tos-cn-i-0813/owgAVhXilAAZ6yTAAzCsDnqefAVEDIN9qALqyg",
"url_list": ["Ig9gQdI0FjieZ_SnquVR-.png"],
"width": 720,
"height": 720
},
"height": 1052,
"width": 1870,
"ratio": "1080p",
"use_static_cover": true,
"duration": 7337,
"horizontal_type": 1
},
"share_url": "https://www.iesdouyin.com/share/video/7346191904205327631/?region=CN&mid=7346191940615932722&u_code=13kgm680k&did=MS4wLjABAAAAiOgYyZm8XbWZMr5o3OvhR-TEOuNygb_hQOwkie-VXJpDYaR4vZfpiIGBfAWKCFHB&iid=MS4wLjABAAAANwkJuWIRFOzg5uCpDRpMj4OX-QryoDgn-yYlXQnRwQQ&with_sec_did=1&titleType=title&share_sign=GBtbcDEKOakwrzsCjMztEGgSeaHW_xrERQNESLGFXFw-&share_version=170400&ts=1710489511&from_aid=6383&from_ssr=1",
"statistics": {
"admire_count": 1,
"comment_count": 602,
"digg_count": 17913,
"collect_count": 2393,
"play_count": 0,
"share_count": 13227
},
"status": {
"listen_video_status": 0,
"is_delete": false,
"allow_share": true,
"is_prohibited": false,
"in_reviewing": false,
"part_see": 0,
"private_status": 0,
"review_result": {
"review_status": 0
}
},
"text_extra": [],
"is_top": 0,
"share_info": {
"share_url": "https://www.iesdouyin.com/share/video/7346191904205327631/?region=CN&mid=7346191940615932722&u_code=13kgm680k&did=MS4wLjABAAAAiOgYyZm8XbWZMr5o3OvhR-TEOuNygb_hQOwkie-VXJpDYaR4vZfpiIGBfAWKCFHB&iid=MS4wLjABAAAANwkJuWIRFOzg5uCpDRpMj4OX-QryoDgn-yYlXQnRwQQ&with_sec_did=1&titleType=title&share_sign=GBtbcDEKOakwrzsCjMztEGgSeaHW_xrERQNESLGFXFw-&share_version=170400&ts=1710489511&from_aid=6383&from_ssr=1",
"share_link_desc": "2.89 G@V.LW mDU:/ 11/22 我的女友 %s 复制此链接打开Dou音搜索直接观看视频"
},
"duration": 7337,
"image_infos": null,
"risk_infos": {
"vote": false,
"warn": false,
"risk_sink": false,
"type": 0,
"content": ""
},
"position": null,
"author_user_id": 83160533866,
"prevent_download": false,
"long_video": null,
"aweme_control": {
"can_forward": true,
"can_share": true,
"can_comment": true,
"can_show_comment": true
},
"images": null,
"suggest_words": {
"suggest_words": [
{
"words": [
{
"word": "条子被黑社会堵到超市后续",
"word_id": "7129083023886554400",
"info": "{\"qrec_for_search\":\"{}\"}"
}
],
"scene": "comment_top_rec",
"icon_url": "",
"hint_text": "大家都在搜:",
"extra_info": "{}"
},
{
"words": [
{
"word": "埃安y plus70乐享版",
"word_id": "7147998601692026127",
"info": "{\"qrec_for_search\":\"{\\\"query_ecom\\\":\\\"1\\\"}\"}"
}
],
"scene": "feed_bottom_rec",
"icon_url": "",
"hint_text": "相关搜索",
"extra_info": "{}"
},
{
"words": [
{
"word": "条子被黑社会堵到超市后续",
"word_id": "7129083023886554400",
"info": "{\"qrec_for_search\":\"{}\"}"
}
],
"scene": "detail_inbox_rex",
"icon_url": "",
"hint_text": "",
"extra_info": "{}"
}
]
}
},
{
"aweme_id": "7345439525113433384",
"desc": "",

View File

@ -455,160 +455,6 @@
]
}
},
{
"aweme_id": "7346457849054235913",
"desc": "#小蛮腰马甲线 他居然把脸转过去",
"create_time": 1710480523,
"music": {
"id": 7346457898803154000,
"title": "@奶茶妹◕🌱创作的原声",
"author": "奶茶妹◕🌱",
"cover_medium": {
"uri": "720x720/aweme-avatar/tos-cn-avt-0015_c7784af3a0bd2e7c5fc92ece450f12e0",
"url_list": [
"https://p3-pc.douyinpic.com/aweme/720x720/aweme-avatar/tos-cn-avt-0015_c7784af3a0bd2e7c5fc92ece450f12e0.jpeg?from=116350172"
],
"width": 720,
"height": 720
},
"cover_thumb": {
"uri": "100x100/aweme-avatar/tos-cn-avt-0015_c7784af3a0bd2e7c5fc92ece450f12e0",
"url_list": [
"https://p3-pc.douyinpic.com/aweme/100x100/aweme-avatar/tos-cn-avt-0015_c7784af3a0bd2e7c5fc92ece450f12e0.jpeg?from=116350172"
],
"width": 720,
"height": 720
},
"play_url": {
"uri": "https://sf5-hl-cdn-tos.douyinstatic.com/obj/ies-music/7346457902686882570.mp3",
"url_list": [
"https://sf5-hl-cdn-tos.douyinstatic.com/obj/ies-music/7346457902686882570.mp3",
"https://sf6-cdn-tos.douyinstatic.com/obj/ies-music/7346457902686882570.mp3"
],
"width": 720,
"height": 720,
"url_key": "7346457898803153673"
},
"duration": 11,
"user_count": 0,
"owner_id": "62790495105",
"owner_nickname": "奶茶妹◕🌱",
"is_original": false
},
"video": {
"play_addr": {
"uri": "v0d00fg10000cnptoirc77u3atmcsskg",
"url_list": [
"https://www.douyin.com/aweme/v1/play/?video_id=v0d00fg10000cnptoirc77u3atmcsskg&line=0&file_id=3b2bcdfe44f0468aacc265bb778c2e2c&sign=fccec71c7a910d752161cb82b89c8474&is_play_url=1&source=PackSourceEnum_PUBLISH"
],
"width": 1080,
"height": 1920,
"url_key": "v0d00fg10000cnptoirc77u3atmcsskg_h264_1080p_2062873",
"data_size": 3017468,
"file_hash": "fccec71c7a910d752161cb82b89c8474",
"file_cs": "c:0-10842-2631|d:0-1508733-7add,1508734-3017467-357f|a:v0d00fg10000cnptoirc77u3atmcsskg"
},
"cover": {
"uri": "tos-cn-i-0813c001/oIzsg8zAAIlAfDH5ANtC9BE6IANk3eAyAhAn0E",
"url_list": ["R3o8KAoPnLSiZLkSs66H3.png"],
"width": 720,
"height": 720
},
"height": 1920,
"width": 1080,
"ratio": "1080p",
"use_static_cover": true,
"duration": 11702
},
"share_url": "https://www.iesdouyin.com/share/video/7346457849054235913/?region=CN&mid=7346457898803153673&u_code=13kgm680k&did=MS4wLjABAAAAiOgYyZm8XbWZMr5o3OvhR-TEOuNygb_hQOwkie-VXJpDYaR4vZfpiIGBfAWKCFHB&iid=MS4wLjABAAAANwkJuWIRFOzg5uCpDRpMj4OX-QryoDgn-yYlXQnRwQQ&with_sec_did=1&titleType=title&share_sign=KmI.XiEwwiCE.iLBUp3QNtoJoUyXFirMExGYSa9SBI8-&share_version=170400&ts=1710488702&from_aid=6383&from_ssr=1",
"statistics": {
"admire_count": 0,
"comment_count": 20,
"digg_count": 1572,
"collect_count": 137,
"play_count": 0,
"share_count": 112
},
"status": {
"listen_video_status": 0,
"is_delete": false,
"allow_share": true,
"is_prohibited": false,
"in_reviewing": false,
"part_see": 0,
"private_status": 0,
"review_result": {
"review_status": 0
}
},
"text_extra": [
{
"start": 0,
"end": 7,
"type": 1,
"hashtag_name": "小蛮腰马甲线",
"hashtag_id": "1622790756032686",
"is_commerce": false,
"caption_start": 0,
"caption_end": 7
}
],
"is_top": 0,
"share_info": {
"share_url": "https://www.iesdouyin.com/share/video/7346457849054235913/?region=CN&mid=7346457898803153673&u_code=13kgm680k&did=MS4wLjABAAAAiOgYyZm8XbWZMr5o3OvhR-TEOuNygb_hQOwkie-VXJpDYaR4vZfpiIGBfAWKCFHB&iid=MS4wLjABAAAANwkJuWIRFOzg5uCpDRpMj4OX-QryoDgn-yYlXQnRwQQ&with_sec_did=1&titleType=title&share_sign=KmI.XiEwwiCE.iLBUp3QNtoJoUyXFirMExGYSa9SBI8-&share_version=170400&ts=1710488702&from_aid=6383&from_ssr=1",
"share_link_desc": "8.99 09/14 P@X.MJ dAT:/ # 小蛮腰马甲线 他居然把脸转过去 %s 复制此链接打开Dou音搜索直接观看视频"
},
"duration": 11702,
"image_infos": null,
"risk_infos": {
"vote": false,
"warn": false,
"risk_sink": false,
"type": 0,
"content": ""
},
"position": null,
"author_user_id": 62790495105,
"prevent_download": false,
"long_video": null,
"aweme_control": {
"can_forward": true,
"can_share": true,
"can_comment": true,
"can_show_comment": true
},
"images": null,
"suggest_words": {
"suggest_words": [
{
"words": [
{
"word": "章若楠",
"word_id": "6585508016810890499",
"info": "{\"qrec_for_search\":\"{}\"}"
}
],
"scene": "comment_top_rec",
"icon_url": "",
"hint_text": "大家都在搜:",
"extra_info": "{}"
},
{
"words": [
{
"word": "章若楠",
"word_id": "6585508016810890499",
"info": "{\"qrec_for_search\":\"{}\"}"
}
],
"scene": "detail_inbox_rex",
"icon_url": "",
"hint_text": "",
"extra_info": "{}"
}
]
}
},
{
"aweme_id": "7346190579807702310",
"desc": "#背影杀 哈~",

View File

@ -449,184 +449,6 @@
]
}
},
{
"aweme_id": "7345796955571784997",
"desc": "体验调酒师的一天🍸 Bartender\n#微醺时刻 #记录生活",
"create_time": 1710326646,
"music": {
"id": 7023044224681511000,
"title": "Starboy (抖音热播)",
"author": "佐助",
"cover_medium": {
"uri": "tos-cn-v-2774c002/b3583f56f54e4451b7d301187585bcdb",
"url_list": [
"https://p11.douyinpic.com/aweme/200x200/tos-cn-v-2774c002/b3583f56f54e4451b7d301187585bcdb.jpeg",
"https://p3.douyinpic.com/aweme/200x200/tos-cn-v-2774c002/b3583f56f54e4451b7d301187585bcdb.jpeg"
],
"width": 720,
"height": 720
},
"cover_thumb": {
"uri": "tos-cn-v-2774c002/b3583f56f54e4451b7d301187585bcdb",
"url_list": [
"https://p11.douyinpic.com/aweme/100x100/tos-cn-v-2774c002/b3583f56f54e4451b7d301187585bcdb.jpeg",
"https://p3.douyinpic.com/aweme/100x100/tos-cn-v-2774c002/b3583f56f54e4451b7d301187585bcdb.jpeg"
],
"width": 720,
"height": 720
},
"play_url": {
"uri": "https://sf5-hl-cdn-tos.douyinstatic.com/obj/tos-cn-ve-2774/ogjEQCutCnDe2gAG2KGBb8ieUACWSoFhZRgMQg",
"url_list": [
"https://sf5-hl-cdn-tos.douyinstatic.com/obj/tos-cn-ve-2774/ogjEQCutCnDe2gAG2KGBb8ieUACWSoFhZRgMQg",
"https://sf3-cdn-tos.douyinstatic.com/obj/tos-cn-ve-2774/ogjEQCutCnDe2gAG2KGBb8ieUACWSoFhZRgMQg"
],
"width": 720,
"height": 720,
"url_key": "7023044224681510949"
},
"duration": 194,
"user_count": 0,
"owner_nickname": "",
"is_original": false
},
"video": {
"play_addr": {
"uri": "v0d00fg10000cnoo6mjc77ubta3125dg",
"url_list": [
"https://www.douyin.com/aweme/v1/play/?video_id=v0d00fg10000cnoo6mjc77ubta3125dg&line=0&file_id=b4fc9157732e4eee81b0d3d071b4d32f&sign=8057edcee0fd27ffce9615b1048d2e2c&is_play_url=1&source=PackSourceEnum_PUBLISH"
],
"width": 1080,
"height": 1920,
"url_key": "v0d00fg10000cnoo6mjc77ubta3125dg_h264_1080p_2264177",
"data_size": 5443649,
"file_hash": "8057edcee0fd27ffce9615b1048d2e2c",
"file_cs": "c:0-17318-d0c8|d:0-2721823-7d6d,2721824-5443648-e625|a:v0d00fg10000cnoo6mjc77ubta3125dg"
},
"cover": {
"uri": "tos-cn-i-0813c001/oo3M3ze0IAN67MAAJAghvhGARED9gAfElxC0BN",
"url_list": ["2ww4W1Pu86xeLjl07K28u.png"],
"width": 720,
"height": 720
},
"height": 1920,
"width": 1080,
"ratio": "1080p",
"use_static_cover": true,
"duration": 19234
},
"share_url": "https://www.iesdouyin.com/share/video/7345796955571784997/?region=CN&mid=7023044224681510949&u_code=13kgm680k&did=MS4wLjABAAAAiOgYyZm8XbWZMr5o3OvhR-TEOuNygb_hQOwkie-VXJpDYaR4vZfpiIGBfAWKCFHB&iid=MS4wLjABAAAANwkJuWIRFOzg5uCpDRpMj4OX-QryoDgn-yYlXQnRwQQ&with_sec_did=1&titleType=title&share_sign=XUuhtQ9LwR_2_xNHoNSw2nfWpq_SiDhebnwzUPGq.Yw-&share_version=170400&ts=1710491939&from_aid=6383&from_ssr=1",
"statistics": {
"admire_count": 59,
"comment_count": 1644,
"digg_count": 256919,
"collect_count": 5279,
"play_count": 0,
"share_count": 8961
},
"status": {
"listen_video_status": 0,
"is_delete": false,
"allow_share": true,
"is_prohibited": false,
"in_reviewing": false,
"part_see": 0,
"private_status": 0,
"review_result": {
"review_status": 0
}
},
"text_extra": [
{
"start": 21,
"end": 26,
"type": 1,
"hashtag_name": "微醺时刻",
"hashtag_id": "1647996185380875",
"is_commerce": false,
"caption_start": 21,
"caption_end": 26
},
{
"start": 27,
"end": 32,
"type": 1,
"hashtag_name": "记录生活",
"hashtag_id": "1767586437643341",
"is_commerce": false,
"caption_start": 27,
"caption_end": 32
}
],
"is_top": 0,
"share_info": {
"share_url": "https://www.iesdouyin.com/share/video/7345796955571784997/?region=CN&mid=7023044224681510949&u_code=13kgm680k&did=MS4wLjABAAAAiOgYyZm8XbWZMr5o3OvhR-TEOuNygb_hQOwkie-VXJpDYaR4vZfpiIGBfAWKCFHB&iid=MS4wLjABAAAANwkJuWIRFOzg5uCpDRpMj4OX-QryoDgn-yYlXQnRwQQ&with_sec_did=1&titleType=title&share_sign=XUuhtQ9LwR_2_xNHoNSw2nfWpq_SiDhebnwzUPGq.Yw-&share_version=170400&ts=1710491939&from_aid=6383&from_ssr=1",
"share_link_desc": "5.10 02/04 z@t.eo GvF:/ 体验调酒师的一天🍸 Bartender # 微醺时刻 # 记录生活 %s 复制此链接打开Dou音搜索直接观看视频"
},
"duration": 19234,
"image_infos": null,
"risk_infos": {
"vote": false,
"warn": false,
"risk_sink": false,
"type": 0,
"content": ""
},
"position": null,
"author_user_id": 24058267831,
"prevent_download": false,
"long_video": null,
"aweme_control": {
"can_forward": true,
"can_share": true,
"can_comment": true,
"can_show_comment": true
},
"images": null,
"suggest_words": {
"suggest_words": [
{
"words": [
{
"word": "冰淇淋kiki",
"word_id": "6732949666079446276",
"info": "{\"qrec_for_search\":\"{}\"}"
}
],
"scene": "comment_top_rec",
"icon_url": "",
"hint_text": "大家都在搜:",
"extra_info": "{}"
},
{
"words": [
{
"word": "调酒师工资一般是多少",
"word_id": "6572390336566400259",
"info": "{\"qrec_for_search\":\"{}\"}"
}
],
"scene": "feed_bottom_rec",
"icon_url": "",
"hint_text": "相关搜索",
"extra_info": "{}"
},
{
"words": [
{
"word": "冰淇淋kiki",
"word_id": "6732949666079446276",
"info": "{\"qrec_for_search\":\"{}\"}"
}
],
"scene": "detail_inbox_rex",
"icon_url": "",
"hint_text": "",
"extra_info": "{}"
}
]
}
},
{
"aweme_id": "7345057414233836850",
"desc": "开在酒瓶里的春天呀🌷🌸",

View File

@ -425,149 +425,6 @@
]
}
},
{
"aweme_id": "7338089394705894682",
"desc": "陈年老库存🐿️",
"create_time": 1708532099,
"music": {
"id": 7338089490520509000,
"title": "@周子然JingYi创作的原声",
"author": "周子然JingYi",
"cover_medium": {
"uri": "720x720/aweme-avatar/tos-cn-avt-0015_f59bfced5c6a3b56d152f1e0437f06ec",
"url_list": [
"https://p3-pc.douyinpic.com/aweme/720x720/aweme-avatar/tos-cn-avt-0015_f59bfced5c6a3b56d152f1e0437f06ec.jpeg?from=116350172"
],
"width": 720,
"height": 720
},
"cover_thumb": {
"uri": "100x100/aweme-avatar/tos-cn-avt-0015_f59bfced5c6a3b56d152f1e0437f06ec",
"url_list": [
"https://p3-pc.douyinpic.com/aweme/100x100/aweme-avatar/tos-cn-avt-0015_f59bfced5c6a3b56d152f1e0437f06ec.jpeg?from=116350172"
],
"width": 720,
"height": 720
},
"play_url": {
"uri": "https://sf6-cdn-tos.douyinstatic.com/obj/ies-music/7338089476511550234.mp3",
"url_list": [
"https://sf6-cdn-tos.douyinstatic.com/obj/ies-music/7338089476511550234.mp3",
"https://sf5-hl-cdn-tos.douyinstatic.com/obj/ies-music/7338089476511550234.mp3"
],
"width": 720,
"height": 720,
"url_key": "7338089490520509235"
},
"duration": 9,
"user_count": 0,
"owner_id": "62839305427",
"owner_nickname": "周子然JingYi",
"is_original": false
},
"video": {
"play_addr": {
"uri": "v0300fg10000cnb217rc77uah3ri5o00",
"url_list": [
"https://www.douyin.com/aweme/v1/play/?video_id=v0300fg10000cnb217rc77uah3ri5o00&line=0&file_id=d0de6a0d7fc0498a812e8527e94a887a&sign=ab93708a219baa2ffde338e8bf652e0d&is_play_url=1&source=PackSourceEnum_PUBLISH"
],
"width": 1080,
"height": 1920,
"url_key": "v0300fg10000cnb217rc77uah3ri5o00_h264_1080p_2556391",
"data_size": 3078535,
"file_hash": "ab93708a219baa2ffde338e8bf652e0d",
"file_cs": "c:0-9310-07ec|d:0-1539266-16e6,1539267-3078534-e6cd|a:v0300fg10000cnb217rc77uah3ri5o00"
},
"cover": {
"uri": "tos-cn-i-0813c001/oAiCAVAbDWOleAAIEGYb9IengDrADCAjAW1pIA",
"url_list": ["7SFxN5HcILUxUdJe-EXfX.png"],
"width": 720,
"height": 720
},
"height": 3840,
"width": 2160,
"ratio": "1080p",
"use_static_cover": true,
"duration": 9634
},
"share_url": "https://www.iesdouyin.com/share/video/7338089394705894682/?region=CN&mid=7338089490520509235&u_code=13kgm680k&did=MS4wLjABAAAAiOgYyZm8XbWZMr5o3OvhR-TEOuNygb_hQOwkie-VXJpDYaR4vZfpiIGBfAWKCFHB&iid=MS4wLjABAAAANwkJuWIRFOzg5uCpDRpMj4OX-QryoDgn-yYlXQnRwQQ&with_sec_did=1&titleType=title&share_sign=ig8SDm7Oq1NBxQweWS4eMzrdjlHmjkr7WIazmFWKoZY-&share_version=170400&ts=1710490324&from_aid=6383&from_ssr=1",
"statistics": {
"admire_count": 2,
"comment_count": 149,
"digg_count": 6367,
"collect_count": 635,
"play_count": 0,
"share_count": 784
},
"status": {
"listen_video_status": 0,
"is_delete": false,
"allow_share": true,
"is_prohibited": false,
"in_reviewing": false,
"part_see": 0,
"private_status": 0,
"review_result": {
"review_status": 0
}
},
"text_extra": [],
"is_top": 0,
"share_info": {
"share_url": "https://www.iesdouyin.com/share/video/7338089394705894682/?region=CN&mid=7338089490520509235&u_code=13kgm680k&did=MS4wLjABAAAAiOgYyZm8XbWZMr5o3OvhR-TEOuNygb_hQOwkie-VXJpDYaR4vZfpiIGBfAWKCFHB&iid=MS4wLjABAAAANwkJuWIRFOzg5uCpDRpMj4OX-QryoDgn-yYlXQnRwQQ&with_sec_did=1&titleType=title&share_sign=ig8SDm7Oq1NBxQweWS4eMzrdjlHmjkr7WIazmFWKoZY-&share_version=170400&ts=1710490324&from_aid=6383&from_ssr=1",
"share_link_desc": "3.07 CUL:/ 05/15 n@Q.kp 陈年老库存🐿️ %s 复制此链接打开Dou音搜索直接观看视频"
},
"duration": 9634,
"image_infos": null,
"risk_infos": {
"vote": false,
"warn": false,
"risk_sink": false,
"type": 0,
"content": ""
},
"position": null,
"author_user_id": 62839305427,
"prevent_download": false,
"long_video": null,
"aweme_control": {
"can_forward": true,
"can_share": true,
"can_comment": true,
"can_show_comment": true
},
"images": null,
"suggest_words": {
"suggest_words": [
{
"words": [
{
"word": "周子然早期照片",
"word_id": "6900178207296673032",
"info": "{\"qrec_for_search\":\"{}\"}"
}
],
"scene": "comment_top_rec",
"icon_url": "",
"hint_text": "大家都在搜:",
"extra_info": "{}"
},
{
"words": [
{
"word": "我有个朋友周子然",
"word_id": "6925278082983957772",
"info": "{\"qrec_for_search\":\"{}\"}"
}
],
"scene": "detail_inbox_rex",
"icon_url": "",
"hint_text": "",
"extra_info": "{}"
}
]
}
},
{
"aweme_id": "7322483619946040585",
"desc": "🍦。我是难伺候的小雪糕\n没有礼貌随时在考虑化掉",

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -1,47 +1,45 @@
<template>
<img class="close" ref="img" :src="src" />
<img class="close" ref="imgEl" :src="src" />
</template>
<script>
<script setup lang="ts">
import { _css } from '@/utils/dom'
import { onMounted } from 'vue'
export default {
name: 'Back',
props: {
mode: {
type: String,
default: 'gray'
},
img: {
type: String,
default: 'back'
},
direction: {
type: String,
default: 'left'
},
scale: {
type: [Number, String],
default: 1
}
defineOptions({
name: 'Back'
})
const props = defineProps({
mode: {
type: String,
default: 'gray'
},
data() {
return {}
img: {
type: String,
default: 'back'
},
computed: {
src() {
return new URL(`../assets/img/icon/components/${this.mode}-${this.img}.png`, import.meta.url)
.href
}
direction: {
type: String,
default: 'left'
},
mounted() {
_css(
this.$refs.img,
'transform',
`rotate(${this.direction === 'left' ? '0' : '180'}deg) scale(${this.scale})`
)
},
methods: {}
}
scale: {
type: [Number, String],
default: 1
}
})
const imgEl = $ref()
const src = $computed(() => {
return new URL(`../assets/img/icon/components/${props.mode}-${props.img}.png`, import.meta.url)
.href
})
onMounted(() => {
_css(
imgEl,
'transform',
`rotate(${props.direction === 'left' ? '0' : '180'}deg) scale(${props.scale})`
)
})
</script>
<style scoped lang="less">

View File

@ -1,36 +1,50 @@
<template>
<div class="music-wrapper">
<div
class="mute-icon"
:class="showMutedNotice && 'notice'"
v-click="() => bus.emit(EVENT_KEY.REMOVE_MUTED)"
v-if="isMuted"
>
<div class="wrap">
<Icon icon="flowbite:volume-mute-solid" />
<span :style="{ opacity: showMutedNotice ? 1 : 0 }">取消静音</span>
</div>
</div>
<img
class="music"
:src="props.item.music?.cover_thumb.url_list[0]"
:src="item.music?.cover_thumb.url_list[0]"
:style="style"
@click.stop="
bus.emit(EVENT_KEY.NAV, {
path: '/home/music',
query: { id: props.item.id }
})
v-click="
() =>
bus.emit(EVENT_KEY.NAV, {
path: '/home/music',
query: { id: item.aweme_id }
})
"
/>
</div>
</template>
<script setup>
import { computed, inject } from 'vue'
<script setup lang="ts">
import { inject, onMounted } from 'vue'
import bus, { EVENT_KEY } from '@/utils/bus'
import { Icon } from '@iconify/vue'
import { useClick } from '@/utils/hooks/useClick'
const props = defineProps({
item: {
type: Object,
default: () => {
return {}
}
}
})
const isPlaying = inject<boolean>('isPlaying')
const isMuted = inject('isMuted')
const item = inject<any>('item')
const vClick = useClick()
let showMutedNotice = $ref(window.showMutedNotice)
const isPlaying = inject('isPlaying')
const style = computed(() => {
const style = $computed(() => {
return { webkitAnimationPlayState: isPlaying.value ? 'running' : 'paused' }
})
onMounted(() => {
bus.on(EVENT_KEY.HIDE_MUTED_NOTICE, () => {
showMutedNotice = false
})
})
</script>
<style lang="less">
@ -38,11 +52,14 @@ const style = computed(() => {
display: flex;
justify-content: center;
@w: 45rem;
width: @w;
height: @w;
position: relative;
.music {
border-radius: 50%;
width: @w;
height: @w;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
@ -59,5 +76,43 @@ const style = computed(() => {
transform: rotate(360deg);
}
}
.mute-icon {
.music;
cursor: pointer;
position: absolute;
z-index: 1;
right: 0;
background: white;
animation: unset;
color: black;
transition: all 0.5s;
overflow: hidden;
.wrap {
width: 100rem;
position: absolute;
left: 0;
display: flex;
align-items: center;
justify-content: center;
}
&.notice {
border-radius: 50rem;
width: 100rem;
}
svg {
font-size: 22rem;
}
span {
margin-left: 5rem;
font-size: 13rem;
word-break: keep-all;
transition: all 0.5s;
}
}
}
</style>

View File

@ -1,11 +1,11 @@
<template>
<div
class="call-float"
v-if="isSmall"
v-if="state.isSmall"
:style="callFloatStyle"
@touchmove="touchmove"
@touchend="touchend"
@click="isSmall = false"
@click="state.isSmall = false"
>
<img src="@/assets/img/icon/message/chat/call-float.png" alt="" />
<span>呼叫中</span>
@ -14,134 +14,145 @@
<transition name="scale">
<div
class="audio-call"
:style="isSmall ? callFloatStyle : { zIndex: 10 }"
:class="isSmall ? 'small' : ''"
v-if="isShowAudioCall"
:style="state.isSmall ? callFloatStyle : { zIndex: 10 }"
:class="state.isSmall ? 'small' : ''"
v-if="state.isShowAudioCall"
>
<div class="float">
<div class="header">
<div class="left">
<img @click="isSmall = true" src="@/assets/img/icon/message/chat/narrow.png" alt="" />
<img
@click="state.isSmall = true"
src="@/assets/img/icon/message/chat/narrow.png"
alt=""
/>
</div>
<span class="center">等待对方接听...</span>
<div class="right">
<div class="option">
<img
v-show="!isOpenCamera"
@click="isOpenCamera = !isOpenCamera"
v-show="!state.isOpenCamera"
@click="state.isOpenCamera = !state.isOpenCamera"
src="@/assets/img/icon/message/chat/disabled-camera.png"
alt=""
/>
<img
v-show="isOpenCamera"
@click="isOpenCamera = !isOpenCamera"
v-show="state.isOpenCamera"
@click="state.isOpenCamera = !state.isOpenCamera"
src="@/assets/img/icon/message/chat/able-camera.png"
alt=""
/>
<span>摄像头</span>
</div>
<div class="option" v-if="isExpand">
<div class="option" v-if="state.isExpand">
<img
v-show="!isOpenAudio"
@click="isOpenAudio = !isOpenAudio"
v-show="!state.isOpenAudio"
@click="state.isOpenAudio = !state.isOpenAudio"
src="@/assets/img/icon/message/chat/disabled-volume.png"
alt=""
/>
<img
v-show="isOpenAudio"
@click="isOpenAudio = !isOpenAudio"
v-show="state.isOpenAudio"
@click="state.isOpenAudio = !state.isOpenAudio"
src="@/assets/img/icon/message/chat/able-volume.png"
alt=""
/>
<span>免提</span>
</div>
<div class="option">
<dy-back mode="light" @click="isExpand = !isExpand" img="back" class="shrink" />
<dy-back
mode="light"
@click="state.isExpand = !state.isExpand"
img="back"
class="shrink"
/>
<!-- <img src="@/assets/img/icon/message/chat/narrow.png" alt="">-->
</div>
</div>
</div>
<img src="@/assets/img/icon/avatar/2.png" alt="" class="big-avatar" />
<div class="footer">
<img @click="isShowAudioCall = false" src="@/assets/img/icon/message/chat/call-end.png" />
<img
@click="state.isShowAudioCall = false"
src="@/assets/img/icon/message/chat/call-end.png"
/>
<span>挂断</span>
</div>
</div>
</div>
</transition>
</template>
<script>
import { inject } from 'vue'
<script setup lang="ts">
import { onMounted, reactive, watch } from 'vue'
import bus, { EVENT_KEY } from '@/utils/bus'
export default {
name: 'Call',
components: {},
props: {
modelValue: {
type: Boolean,
default() {
return false
}
defineOptions({
name: 'Call'
})
defineProps({
modelValue: {
type: Boolean,
default() {
return false
}
},
data() {
return {
mitt: inject('mitt'),
callFloatTransitionTime: 300,
callFloatLeft: 15,
callFloatTop: 100,
isOpenCamera: false,
isOpenAudio: true,
isExpand: true,
isSmall: false,
isShowAudioCall: false,
height: 0,
width: 0
}
})
const state = reactive({
callFloatTransitionTime: 300,
callFloatLeft: 15,
callFloatTop: 100,
isOpenCamera: false,
isOpenAudio: true,
isExpand: true,
isSmall: false,
isShowAudioCall: false,
height: 0,
width: 0
})
const callFloatStyle = $computed(() => {
return {
'transition-duration': state.callFloatTransitionTime + 'ms',
left: state.callFloatLeft + 'px',
top: state.callFloatTop + 'px'
}
})
watch(
() => state.isShowAudioCall,
(newVal) => {
if (!newVal) {
state.isOpenCamera = false
state.isOpenAudio = true
}
},
computed: {
callFloatStyle() {
return {
'transition-duration': this.callFloatTransitionTime + 'ms',
left: this.callFloatLeft + 'px',
top: this.callFloatTop + 'px'
}
}
)
onMounted(() => {
bus.on(EVENT_KEY.SHOW_AUDIO_CALL, () => {
if (state.isShowAudioCall) {
state.isSmall = false
} else {
state.isShowAudioCall = true
}
},
watch: {
isShowAudioCall(newVal) {
if (!newVal) {
this.isOpenCamera = false
this.isOpenAudio = true
}
}
},
created() {},
methods: {
touchmove(e) {
this.callFloatTransitionTime = 0
this.callFloatLeft = e.touches[0].pageX - 35
this.callFloatTop = e.touches[0].pageY - 40
},
touchend() {
this.callFloatTransitionTime = 300
if (this.callFloatLeft < this.width / 2) {
this.callFloatLeft = 15
} else {
this.callFloatLeft = this.width - 15 - 70
}
}
},
mounted() {
this.mitt.on('showAudioCall', () => {
if (this.isShowAudioCall) {
this.isSmall = false
} else {
this.isShowAudioCall = true
}
})
this.height = document.body.clientHeight
this.width = document.body.clientWidth
})
state.height = document.body.clientHeight
state.width = document.body.clientWidth
})
function touchmove(e) {
state.callFloatTransitionTime = 0
state.callFloatLeft = e.touches[0].pageX - 35
state.callFloatTop = e.touches[0].pageY - 40
}
function touchend() {
state.callFloatTransitionTime = 300
if (state.callFloatLeft < state.width / 2) {
state.callFloatLeft = 15
} else {
state.callFloatLeft = state.width - 15 - 70
}
}
</script>

View File

@ -35,7 +35,7 @@
src="../assets/img/icon/components/check/check-red-share.png"
/>
</div>
<div class="option" @click.stop="closeShare($nav('/message/share-to-friend'))">
<div class="option" @click.stop="closeShare($router.push('/message/share-to-friend'))">
<dy-back class="more" mode="light" direction="right"></dy-back>
<span>更多朋友</span>
</div>
@ -62,7 +62,7 @@
<img class="small" src="../assets/img/icon/components/video/dou.webp" alt="" />
<span>帮上热门</span>
</div>
<div class="option" @click.stop="$nav('/home/report', { mode: this.mode })">
<div class="option" @click.stop="$router.push('/home/report', { mode: this.mode })">
<img class="small" src="../assets/img/icon/components/video/warring.png" alt="" />
<span>举报</span>
</div>
@ -105,7 +105,7 @@
<img class="small" src="../assets/img/icon/components/video/tofriend.webp" alt="" />
<span>私信朋友</span>
</div>
<div class="option" @click.stop="$nav('/home/report', { mode: this.mode })">
<div class="option" @click.stop="$router.push('/home/report', { mode: this.mode })">
<img class="small" src="../assets/img/icon/components/video/warring.png" alt="" />
<span>举报音乐</span>
</div>

View File

@ -1,13 +1,13 @@
<template>
<div class="video-wrapper" ref="videoWrapper" :class="positionName">
<Loading v-if="loading" style="position: absolute" />
<Loading v-if="state.loading" style="position: absolute" />
<!-- <video :src="item.video + '?v=123'"-->
<video
:src="item.video.play_addr.url_list[0]"
:poster="poster"
ref="video"
muted
preload
ref="videoEl"
:muted="state.isMuted"
preload="true"
loop
x5-video-player-type="h5-page"
:x5-video-player-fullscreen="false"
@ -23,13 +23,13 @@
<div class="float">
<template v-if="isLive">
<div class="living">点击进入直播间</div>
<ItemDesc :is-live="true" v-model:item="localItem" :position="position" />
<ItemDesc :is-live="true" v-model:item="state.localItem" :position="position" />
</template>
<template v-else>
<div :style="{ opacity: isMove ? 0 : 1 }" class="normal">
<template v-if="!commentVisible">
<ItemToolbar v-model:item="localItem" :position="position" v-bind="$attrs" />
<ItemDesc v-model:item="localItem" :position="position" />
<div :style="{ opacity: state.isMove ? 0 : 1 }" class="normal">
<template v-if="!state.commentVisible">
<ItemToolbar v-model:item="state.localItem" />
<ItemDesc v-model:item="state.localItem" />
</template>
<div v-if="isMy" class="comment-status">
<div class="comment">
@ -44,7 +44,7 @@
</div>
</div>
<transition-group name="comment-status" tag="div" class="loveds">
<div class="type-loved" :key="i" v-for="i in test">
<div class="type-loved" :key="i" v-for="i in state.test">
<img src="../../assets/img/icon/head-image.jpeg" alt="" class="avatar" />
<img src="../../assets/img/icon/love.svg" alt="" class="loved" />
</div>
@ -55,17 +55,17 @@
<div
class="progress"
:class="progressClass"
ref="progress"
ref="progressEl"
@click="null"
@touchstart="touchstart"
@touchmove="touchmove"
@touchend="touchend"
>
<div class="time" v-if="isMove">
<span class="currentTime">{{ _duration(currentTime) }}</span>
<span class="duration"> / {{ _duration(duration) }}</span>
<div class="time" v-if="state.isMove">
<span class="currentTime">{{ _duration(state.currentTime) }}</span>
<span class="duration"> / {{ _duration(state.duration) }}</span>
</div>
<template v-if="duration > 15 || isMove || !isPlaying">
<template v-if="state.duration > 15 || state.isMove || !isPlaying">
<div class="bg"></div>
<div class="progress-line" :style="durationStyle"></div>
<div class="point"></div>
@ -76,310 +76,326 @@
</div>
</template>
<script>
<script setup lang="ts">
import { _checkImgUrl, _duration, _stopPropagation } from '@/utils'
import Loading from '../Loading'
import ItemToolbar from './ItemToolbar'
import ItemDesc from './ItemDesc'
import Loading from '../Loading.vue'
import ItemToolbar from './ItemToolbar.vue'
import ItemDesc from './ItemDesc.vue'
import bus, { EVENT_KEY } from '../../utils/bus'
import { SlideItemPlayStatus } from '@/utils/const_var'
import { computed } from 'vue'
import { computed, onMounted, onUnmounted, provide, reactive } from 'vue'
import { Icon } from '@iconify/vue'
import { _css } from '@/utils/dom'
export default {
name: 'BaseVideo',
components: {
Loading,
ItemToolbar,
ItemDesc,
Icon
},
provide() {
return {
// isPlaying: computed(() => this.status)
isPlaying: computed(() => this.isPlaying)
}
},
props: {
item: {
type: Object,
default: () => {
return {}
}
},
position: {
type: Object,
default: () => {
return {}
}
},
//
isPlay: {
type: Boolean,
default: () => {
return true
}
},
isMy: {
type: Boolean,
default: () => {
return false
}
},
isLive: {
type: Boolean,
default: () => {
return false
}
}
},
computed: {
poster() {
return _checkImgUrl(this.item.video.poster ?? this.item.video.cover.url_list[0])
},
durationStyle() {
return { width: this.playX + 'px' }
},
progressClass() {
if (this.isMove) {
return 'move'
} else {
return this.isPlaying ? '' : 'stop'
}
},
positionName() {
return 'item-' + Object.values(this.position).join('-')
},
isPlaying() {
return this.status === SlideItemPlayStatus.Play
}
},
data() {
return {
loading: false,
paused: false,
status: this.isPlay ? SlideItemPlayStatus.Play : SlideItemPlayStatus.Pause,
duration: 0,
step: 0,
currentTime: -1,
playX: 0,
start: { x: 0 },
last: { x: 0, time: 0 },
height: 0,
width: 0,
isMove: false,
ignoreWaiting: false, //waitingwaiting
test: [1, 2],
localItem: this.item,
progressBarRect: {},
videoScreenHeight: 0,
commentVisible: false
}
},
mounted() {
// console.log('video', this.localItem.aweme_id)
// console.log(this.commentVisible)
this.height = document.body.clientHeight
this.width = document.body.clientWidth
let video = this.$refs.video
video.currentTime = 0
let fun = (e) => {
this.currentTime = Math.ceil(e.target.currentTime)
this.playX = (this.currentTime - 1) * this.step
}
video.addEventListener('loadedmetadata', () => {
this.videoScreenHeight = video.videoHeight / (video.videoWidth / this.width)
this.duration = video.duration
this.progressBarRect = this.$refs.progress.getBoundingClientRect()
this.step = this.progressBarRect.width / Math.floor(this.duration)
video.addEventListener('timeupdate', fun)
})
defineOptions({
name: 'BaseVideo'
})
let eventTester = (e) => {
video.addEventListener(
e,
() => {
// console.log('eventTester', e, this.item.aweme_id)
if (e === 'playing') this.loading = false
if (e === 'waiting') {
if (!this.paused && !this.ignoreWaiting) {
this.loading = true
}
}
// console.log(e, t)
},
false
)
const props = defineProps({
item: {
type: Object,
default: () => {
return {}
}
// eventTester("loadstart", ''); //
// eventTester("abort", ''); //
// eventTester("loadstart", ''); //
// eventTester("progress", ''); //
// // eventTester("suspend", ''); //
// eventTester("abort", ''); //
// eventTester("error", ''); //
// eventTester("stalled", ''); //
// eventTester("play", 'play()autoplay'); //play()autoplay
// eventTester("pause", 'pause()'); //pause()
// eventTester("loadedmetadata", ''); //
// eventTester("loadeddata"); //
eventTester('waiting', '等待数据,并非错误') //
eventTester('playing', '开始回放') //
// eventTester("canplay", '/'); //
// eventTester("canplaythrough", ''); //
// eventTester("seeking", ''); //
// eventTester("seeked", ''); //
// // eventTester("timeupdate",''); //
// eventTester("ended", ''); //
// eventTester("ratechange", ''); //
// eventTester("durationchange", ''); //
// eventTester("volumechange", ''); //
// console.log('mounted')
// bus.off('singleClickBroadcast')
bus.on(EVENT_KEY.SINGLE_CLICK_BROADCAST, this.click)
bus.on(EVENT_KEY.DIALOG_MOVE, this.onDialogMove)
bus.on(EVENT_KEY.DIALOG_END, this.onDialogEnd)
bus.on(EVENT_KEY.OPEN_COMMENTS, this.onOpenComments)
bus.on(EVENT_KEY.CLOSE_COMMENTS, this.onCloseComments)
bus.on(EVENT_KEY.OPEN_SUB_TYPE, this.onOpenSubType)
bus.on(EVENT_KEY.CLOSE_SUB_TYPE, this.onCloseSubType)
},
unmounted() {
// console.log('unmounted')
bus.off(EVENT_KEY.SINGLE_CLICK_BROADCAST, this.click)
bus.off(EVENT_KEY.DIALOG_MOVE, this.onDialogMove)
bus.off(EVENT_KEY.DIALOG_END, this.onDialogEnd)
bus.off(EVENT_KEY.OPEN_COMMENTS, this.onOpenComments)
bus.off(EVENT_KEY.CLOSE_COMMENTS, this.onCloseComments)
bus.off(EVENT_KEY.OPEN_SUB_TYPE, this.onOpenSubType)
bus.off(EVENT_KEY.CLOSE_SUB_TYPE, this.onCloseSubType)
position: {
type: Object,
default: () => {
return {}
}
},
methods: {
_duration,
_checkImgUrl,
onOpenSubType() {
this.commentVisible = true
},
onCloseSubType() {
this.commentVisible = false
},
onDialogMove({ tag, e }) {
if (this.commentVisible && tag === 'comment') {
_css(this.$refs.video, 'transition-duration', `0ms`)
_css(this.$refs.video, 'height', `calc(var(--vh, 1vh) * 30 + ${e}px)`)
}
},
onDialogEnd({ tag, isClose }) {
if (this.commentVisible && tag === 'comment') {
console.log('isClose', isClose)
_css(this.$refs.video, 'transition-duration', `300ms`)
if (isClose) {
this.commentVisible = false
_css(this.$refs.video, 'height', '100%')
} else {
_css(this.$refs.video, 'height', 'calc(var(--vh, 1vh) * 30)')
}
}
},
onOpenComments(id) {
if (id === this.item.aweme_id) {
_css(this.$refs.video, 'transition-duration', `300ms`)
_css(this.$refs.video, 'height', 'calc(var(--vh, 1vh) * 30)')
this.commentVisible = true
}
},
onCloseComments() {
if (this.commentVisible) {
_css(this.$refs.video, 'transition-duration', `300ms`)
_css(this.$refs.video, 'height', '100%')
this.commentVisible = false
}
},
click({ uniqueId, index, type }) {
if (this.position.uniqueId === uniqueId && this.position.index === index) {
if (type === EVENT_KEY.ITEM_TOGGLE) {
if (this.isLive) {
if (type === EVENT_KEY.ITEM_TOGGLE) {
this.pause()
bus.emit(EVENT_KEY.NAV, {
path: '/home/live',
query: { id: this.item.aweme_id }
})
}
} else {
if (this.status === SlideItemPlayStatus.Play) {
this.pause()
} else {
this.play()
}
}
}
if (type === EVENT_KEY.ITEM_STOP) {
this.$refs.video.currentTime = 0
this.ignoreWaiting = true
this.pause()
setTimeout(() => (this.ignoreWaiting = false), 300)
}
if (type === EVENT_KEY.ITEM_PLAY) {
this.$refs.video.currentTime = 0
this.ignoreWaiting = true
this.play()
setTimeout(() => (this.ignoreWaiting = false), 300)
}
}
},
play() {
this.status = SlideItemPlayStatus.Play
this.$refs.video.volume = 1
this.$refs.video.play()
},
pause() {
this.status = SlideItemPlayStatus.Pause
this.$refs.video.pause()
},
touchstart(e) {
_stopPropagation(e)
this.start.x = e.touches[0].pageX
this.last.x = this.playX
this.last.time = this.currentTime
},
touchmove(e) {
// console.log('move',e)
_stopPropagation(e)
this.isMove = true
this.pause()
let dx = e.touches[0].pageX - this.start.x
this.playX = this.last.x + dx
this.currentTime = this.last.time + Math.ceil(Math.ceil(dx) / this.step)
if (this.currentTime <= 0) this.currentTime = 0
if (this.currentTime >= this.duration) this.currentTime = this.duration
},
touchend(e) {
// console.log('end', e)
_stopPropagation(e)
if (this.isPlaying) return
setTimeout(() => (this.isMove = false), 1000)
this.$refs.video.currentTime = this.currentTime
this.play()
//
isPlay: {
type: Boolean,
default: () => {
return true
}
},
isMy: {
type: Boolean,
default: () => {
return false
}
},
isLive: {
type: Boolean,
default: () => {
return false
}
}
})
provide(
'isPlaying',
computed(() => isPlaying)
)
provide(
'isMuted',
computed(() => state.isMuted)
)
provide(
'position',
computed(() => props.position)
)
provide(
'item',
computed(() => props.item)
)
const videoEl = $ref<HTMLVideoElement>()
const progressEl = $ref<HTMLDivElement>()
let state = reactive({
loading: false,
paused: false,
isMuted: window.isMuted,
status: props.isPlay ? SlideItemPlayStatus.Play : SlideItemPlayStatus.Pause,
duration: 0,
step: 0,
currentTime: -1,
playX: 0,
start: { x: 0 },
last: { x: 0, time: 0 },
height: 0,
width: 0,
isMove: false,
ignoreWaiting: false, //waitingwaiting
test: [1, 2],
localItem: props.item,
progressBarRect: {
height: 0,
width: 0
},
videoScreenHeight: 0,
commentVisible: false
})
const poster = $computed(() => {
return _checkImgUrl(props.item.video.poster ?? props.item.video.cover.url_list[0])
})
const durationStyle = $computed(() => {
return { width: state.playX + 'px' }
})
const isPlaying = $computed(() => {
return state.status === SlideItemPlayStatus.Play
})
const positionName = $computed(() => {
return 'item-' + Object.values(props.position).join('-')
})
const progressClass = $computed(() => {
if (state.isMove) {
return 'move'
} else {
return isPlaying ? '' : 'stop'
}
})
onMounted(() => {
// console.log('video', this.localItem.aweme_id)
// console.log(this.commentVisible)
state.height = document.body.clientHeight
state.width = document.body.clientWidth
videoEl.currentTime = 0
let fun = (e) => {
state.currentTime = Math.ceil(e.target.currentTime)
state.playX = (state.currentTime - 1) * state.step
}
videoEl.addEventListener('loadedmetadata', () => {
state.videoScreenHeight = videoEl.videoHeight / (videoEl.videoWidth / state.width)
state.duration = videoEl.duration
state.progressBarRect = progressEl.getBoundingClientRect()
state.step = state.progressBarRect.width / Math.floor(state.duration)
videoEl.addEventListener('timeupdate', fun)
})
let eventTester = (e, t: string) => {
videoEl.addEventListener(
e,
() => {
// console.log('eventTester', e, state.item.aweme_id)
if (e === 'playing') state.loading = false
if (e === 'waiting') {
if (!state.paused && !state.ignoreWaiting) {
state.loading = true
}
}
let s = false
if (s) {
console.log(e, t)
}
},
false
)
}
// eventTester("loadstart", ''); //
// eventTester("abort", ''); //
// eventTester("loadstart", ''); //
// eventTester("progress", ''); //
// // eventTester("suspend", ''); //
// eventTester("abort", ''); //
// eventTester("error", ''); //
// eventTester("stalled", ''); //
// eventTester("play", 'play()autoplay'); //play()autoplay
// eventTester("pause", 'pause()'); //pause()
// eventTester("loadedmetadata", ''); //
// eventTester("loadeddata"); //
eventTester('waiting', '等待数据,并非错误') //
eventTester('playing', '开始回放') //
// eventTester("canplay", '/'); //
// eventTester("canplaythrough", ''); //
// eventTester("seeking", ''); //
// eventTester("seeked", ''); //
// // eventTester("timeupdate",''); //
// eventTester("ended", ''); //
// eventTester("ratechange", ''); //
// eventTester("durationchange", ''); //
// eventTester("volumechange", ''); //
// console.log('mounted')
// bus.off('singleClickBroadcast')
bus.on(EVENT_KEY.SINGLE_CLICK_BROADCAST, click)
bus.on(EVENT_KEY.DIALOG_MOVE, onDialogMove)
bus.on(EVENT_KEY.DIALOG_END, onDialogEnd)
bus.on(EVENT_KEY.OPEN_COMMENTS, onOpenComments)
bus.on(EVENT_KEY.CLOSE_COMMENTS, onCloseComments)
bus.on(EVENT_KEY.OPEN_SUB_TYPE, onOpenSubType)
bus.on(EVENT_KEY.CLOSE_SUB_TYPE, onCloseSubType)
bus.on(EVENT_KEY.REMOVE_MUTED, removeMuted)
})
onUnmounted(() => {
// console.log('unmounted')
bus.off(EVENT_KEY.SINGLE_CLICK_BROADCAST, click)
bus.off(EVENT_KEY.DIALOG_MOVE, onDialogMove)
bus.off(EVENT_KEY.DIALOG_END, onDialogEnd)
bus.off(EVENT_KEY.OPEN_COMMENTS, onOpenComments)
bus.off(EVENT_KEY.CLOSE_COMMENTS, onCloseComments)
bus.off(EVENT_KEY.OPEN_SUB_TYPE, onOpenSubType)
bus.off(EVENT_KEY.CLOSE_SUB_TYPE, onCloseSubType)
bus.off(EVENT_KEY.REMOVE_MUTED, removeMuted)
})
function removeMuted() {
state.isMuted = false
}
function onOpenSubType() {
state.commentVisible = true
}
function onCloseSubType() {
state.commentVisible = false
}
function onDialogMove({ tag, e }) {
if (state.commentVisible && tag === 'comment') {
_css(videoEl, 'transition-duration', `0ms`)
_css(videoEl, 'height', `calc(var(--vh, 1vh) * 30 + ${e}px)`)
}
}
function onDialogEnd({ tag, isClose }) {
if (state.commentVisible && tag === 'comment') {
console.log('isClose', isClose)
_css(videoEl, 'transition-duration', `300ms`)
if (isClose) {
state.commentVisible = false
_css(videoEl, 'height', '100%')
} else {
_css(videoEl, 'height', 'calc(var(--vh, 1vh) * 30)')
}
}
}
function onOpenComments(id) {
if (id === props.item.aweme_id) {
_css(videoEl, 'transition-duration', `300ms`)
_css(videoEl, 'height', 'calc(var(--vh, 1vh) * 30)')
state.commentVisible = true
}
}
function onCloseComments() {
if (state.commentVisible) {
_css(videoEl, 'transition-duration', `300ms`)
_css(videoEl, 'height', '100%')
state.commentVisible = false
}
}
function click({ uniqueId, index, type }) {
if (props.position.uniqueId === uniqueId && props.position.index === index) {
if (type === EVENT_KEY.ITEM_TOGGLE) {
if (props.isLive) {
pause()
bus.emit(EVENT_KEY.NAV, {
path: '/home/live',
query: { id: props.item.aweme_id }
})
} else {
if (state.status === SlideItemPlayStatus.Play) {
pause()
} else {
play()
}
}
}
if (type === EVENT_KEY.ITEM_STOP) {
videoEl.currentTime = 0
state.ignoreWaiting = true
pause()
setTimeout(() => (state.ignoreWaiting = false), 300)
}
if (type === EVENT_KEY.ITEM_PLAY) {
videoEl.currentTime = 0
state.ignoreWaiting = true
play()
setTimeout(() => (state.ignoreWaiting = false), 300)
}
}
}
function play() {
state.status = SlideItemPlayStatus.Play
videoEl.volume = 1
videoEl.play()
}
function pause() {
state.status = SlideItemPlayStatus.Pause
videoEl.pause()
}
function touchstart(e) {
_stopPropagation(e)
state.start.x = e.touches[0].pageX
state.last.x = state.playX
state.last.time = state.currentTime
}
function touchmove(e) {
// console.log('move',e)
_stopPropagation(e)
state.isMove = true
pause()
let dx = e.touches[0].pageX - state.start.x
state.playX = state.last.x + dx
state.currentTime = state.last.time + Math.ceil(Math.ceil(dx) / state.step)
if (state.currentTime <= 0) state.currentTime = 0
if (state.currentTime >= state.duration) state.currentTime = state.duration
}
function touchend(e) {
// console.log('end', e)
_stopPropagation(e)
if (isPlaying) return
setTimeout(() => (state.isMove = false), 1000)
videoEl.currentTime = state.currentTime
play()
}
</script>
<style scoped lang="less">
.fade-enter-active,
.fade-leave-active {
transition: transform 0.5s linear;
}
.fade-enter-from,
.fade-leave-to {
transform: scale(0);
}
.video-wrapper {
position: relative;
font-size: 14rem;
@ -410,140 +426,6 @@ export default {
width: 100%;
transition: all 0.3s;
.toolbar {
//width: 40px;
position: absolute;
bottom: 0;
right: 5px;
color: #fff;
.avatar-ctn {
position: relative;
.avatar {
width: 55px;
height: 55px;
border-radius: 50%;
}
.options {
position: absolute;
border-radius: 50%;
margin: auto;
left: 0;
right: 0;
bottom: -5px;
background: red;
//background: black;
width: 18px;
height: 18px;
display: flex;
justify-content: center;
align-items: center;
transition: all 1s;
img {
position: absolute;
width: 12px;
height: 12px;
transition: all 1s;
}
.yes {
opacity: 0;
transform: rotate(-180deg);
}
&.attention {
background: white;
.no {
opacity: 0;
transform: rotate(180deg);
}
.yes {
opacity: 1;
transform: rotate(0deg);
}
}
}
}
.love,
.message,
.share {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
@width: 35rem;
img {
width: @width;
height: @width;
}
span {
font-size: 12rem;
}
}
.loved {
background: red;
}
}
.content {
color: #fff;
position: absolute;
bottom: 0;
width: 75%;
//display: flex;
//flex-direction: column;
.location-wrapper {
display: flex;
.location {
margin-bottom: 10rem;
display: flex;
align-items: center;
font-size: 12rem;
padding: 4rem;
border-radius: 3rem;
background: var(--second-btn-color-tran);
.gang {
height: 8rem;
width: 1.5px;
margin: 0 5rem;
background: gray;
}
img {
margin-right: 7rem;
width: 18rem;
}
}
}
.music {
position: relative;
width: 60%;
display: flex;
align-items: center;
.music-image {
width: 20px;
height: 20px;
margin-top: 3px;
}
}
}
.comment-status {
display: flex;
align-items: center;

View File

@ -1,19 +1,7 @@
<script setup>
import { reactive } from 'vue'
<script setup lang="ts">
import { inject, reactive } from 'vue'
const props = defineProps({
item: {
type: Object,
default: () => {
return {}
}
},
position: {
type: Object,
default: () => {
return {}
}
},
isMy: {
type: Boolean,
default: () => {
@ -28,6 +16,8 @@ const props = defineProps({
}
})
const item = inject<any>('item')
const state = reactive({
isAttention: false,
test: [1, 2]
@ -36,26 +26,26 @@ const state = reactive({
<template>
<div class="item-desc ml1r mb1r">
<div class="content" v-if="!props.isMy">
<div class="location-wrapper" v-if="props.item.city || item.address">
<div class="location-wrapper" v-if="item.city || item.address">
<div class="location">
<img src="../../assets/img/icon/location.webp" alt="" />
<span>{{ props.item.city }}</span>
<template v-if="props.item.address">
<span>{{ item.city }}</span>
<template v-if="item.address">
<div class="gang"></div>
</template>
<span>{{ props.item.address }}</span>
<span>{{ item.address }}</span>
</div>
</div>
<div class="live" v-if="props.isLive">直播中</div>
<div class="name mb1r f18 fb" @click.stop="$emit('goUserInfo')">
@{{ props.item.author.nickname }}
@{{ item.author.nickname }}
</div>
<div class="description">
{{ props.item.desc }}
{{ item.desc }}
</div>
<!-- <div class="music" @click.stop="bus.emit('nav','/home/music')">-->
<!-- <img src="../../assets/img/icon/music.svg" alt="" class="music-image">-->
<!-- <span>{{ props.item.music.title }}</span>-->
<!-- <span>{{ item.music.title }}</span>-->
<!-- </div>-->
</div>
<div v-else class="comment-status">
@ -88,7 +78,7 @@ const state = reactive({
.content {
color: #fff;
width: 75vw;
width: 70vw;
text-align: left;
.location-wrapper {

View File

@ -1,23 +1,12 @@
<script setup lang="ts">
import BaseMusic from '../BaseMusic.vue'
import { _dateFormat, _formatNumber, _stopPropagation, _updateItem } from '@/utils'
import { _formatNumber, _updateItem } from '@/utils'
import bus, { EVENT_KEY } from '@/utils/bus'
import { Icon } from '@iconify/vue'
import { useClick } from '@/utils/hooks/useClick'
import { inject } from 'vue'
const props = defineProps({
item: {
type: Object,
default: () => {
return {}
}
},
position: {
type: Object,
default: () => {
return {}
}
},
isMy: {
type: Boolean,
default: () => {
@ -25,10 +14,13 @@ const props = defineProps({
}
}
})
const item = inject<any>('item')
const emit = defineEmits(['update:item', 'goUserInfo', 'showComments', 'showShare', 'goMusic'])
function loved() {
_updateItem(props, 'isLoved', !props.item.isLoved, emit)
_updateItem(props, 'isLoved', !item.value.isLoved, emit)
}
function attention(e) {
@ -39,7 +31,7 @@ function attention(e) {
}
function showComments() {
bus.emit(EVENT_KEY.OPEN_COMMENTS, props.item.aweme_id)
bus.emit(EVENT_KEY.OPEN_COMMENTS, item.value.aweme_id)
}
const vClick = useClick()
@ -50,12 +42,12 @@ const vClick = useClick()
<div class="avatar-ctn mb2r">
<img
class="avatar"
:src="props.item.author.avatar_168x168.url_list[0]"
:src="item.author.avatar_168x168.url_list[0]"
alt=""
v-click="() => bus.emit(EVENT_KEY.GO_USERINFO)"
/>
<transition name="fade">
<div v-if="!props.item.isAttention" v-click="attention" class="options">
<div v-if="!item.isAttention" v-click="attention" class="options">
<img class="no" src="../../assets/img/icon/add-light.png" alt="" />
<img class="yes" src="../../assets/img/icon/ok-red.png" alt="" />
</div>
@ -63,36 +55,36 @@ const vClick = useClick()
</div>
<div class="love mb2r" v-click="loved">
<div>
<img src="../../assets/img/icon/love.svg" class="love-image" v-if="!props.item.isLoved" />
<img src="../../assets/img/icon/loved.svg" class="love-image" v-if="props.item.isLoved" />
<img src="../../assets/img/icon/love.svg" class="love-image" v-if="!item.isLoved" />
<img src="../../assets/img/icon/loved.svg" class="love-image" v-if="item.isLoved" />
</div>
<span>{{ _formatNumber(props.item.statistics.digg_count) }}</span>
<span>{{ _formatNumber(item.statistics.digg_count) }}</span>
</div>
<div class="message mb2r" v-click="showComments">
<Icon icon="mage:message-dots-round-fill" class="icon" style="color: white" />
<span>{{ _formatNumber(props.item.statistics.comment_count) }}</span>
<span>{{ _formatNumber(item.statistics.comment_count) }}</span>
</div>
<!--TODO -->
<div
class="message mb2r"
v-click="() => _updateItem(props, 'isCollect', !props.item.isCollect, emit)"
v-click="() => _updateItem(props, 'isCollect', !item.isCollect, emit)"
>
<Icon v-if="props.item.isCollect" icon="ic:round-star" class="icon" style="color: yellow" />
<Icon v-if="item.isCollect" icon="ic:round-star" class="icon" style="color: yellow" />
<Icon v-else icon="ic:round-star" class="icon" style="color: white" />
<span>{{ _formatNumber(props.item.statistics.comment_count) }}</span>
<span>{{ _formatNumber(item.statistics.comment_count) }}</span>
</div>
<div v-if="!props.isMy" class="share mb2r" v-click="() => bus.emit(EVENT_KEY.SHOW_SHARE)">
<img src="../../assets/img/icon/share-white-full.png" alt="" class="share-image" />
<span>{{ _formatNumber(props.item.statistics.share_count) }}</span>
<span>{{ _formatNumber(item.statistics.share_count) }}</span>
</div>
<div v-else class="share mb2r" v-click="() => bus.emit(EVENT_KEY.SHOW_SHARE)">
<img src="../../assets/img/icon/menu-white.png" alt="" class="share-image" />
</div>
<!-- <BaseMusic-->
<!-- :cover="props.item.music.cover"-->
<!-- v-click="$nav('/home/music')"-->
<!-- :cover="item.music.cover"-->
<!-- v-click="$router.push('/home/music')"-->
<!-- /> -->
<BaseMusic :item="props.item" />
<BaseMusic />
</div>
</template>
@ -101,8 +93,11 @@ const vClick = useClick()
//width: 40px;
position: absolute;
bottom: 0;
right: 5px;
right: 10rem;
color: #fff;
display: flex;
flex-direction: column;
align-items: center;
.avatar-ctn {
position: relative;

View File

@ -139,15 +139,18 @@ watch(
if (newVal && !props.list.length) {
return emit('refresh')
}
let t = newVal ? 0 : 200
// console.log('active', 'newVal', newVal, 'oldVal', oldVal)
if (newVal) {
bus.emit(EVENT_KEY.CURRENT_ITEM, props.list[state.localIndex])
}
bus.emit(EVENT_KEY.SINGLE_CLICK_BROADCAST, {
uniqueId: props.uniqueId,
index: state.localIndex,
type: newVal === false ? EVENT_KEY.ITEM_STOP : EVENT_KEY.ITEM_PLAY
})
setTimeout(() => {
bus.emit(EVENT_KEY.SINGLE_CLICK_BROADCAST, {
uniqueId: props.uniqueId,
index: state.localIndex,
type: newVal === false ? EVENT_KEY.ITEM_STOP : EVENT_KEY.ITEM_PLAY
})
}, t)
},
{ immediate: true }
)
@ -271,8 +274,9 @@ function touchEnd(e) {
slideTouchEnd(e, state, canNext, (isNext) => {
let half = (props.virtualTotal - 1) / 2
if (props.list.length > props.virtualTotal) {
//
//()
if (isNext) {
// `dom` `dom`
if (state.localIndex > props.list.length - props.virtualTotal && state.localIndex > half) {
emit('loadMore')
}
@ -297,6 +301,7 @@ function touchEnd(e) {
})
}
} else {
// `dom` `dom`
if (state.localIndex >= half && state.localIndex < props.list.length - (half + 1)) {
let addIndex = state.localIndex - half
if (addIndex >= 0) {
@ -321,7 +326,7 @@ function touchEnd(e) {
slideReset(e, slideListEl.value, state, emit)
}
function canNext(state, isNext) {
function canNext(state, isNext: boolean) {
return !(
(state.localIndex === 0 && !isNext) ||
(state.localIndex === props.list.length - 1 && isNext)

View File

@ -13,6 +13,7 @@ const BASE_URL_MAP = {
}
export const IS_SUB_DOMAIN = ['GITEE_PAGES', 'GP_PAGES'].includes(import.meta.env.VITE_ENV)
export const IS_GITEE_PAGES = ['GITEE_PAGES'].includes(import.meta.env.VITE_ENV)
export const BASE_URL = BASE_URL_MAP[import.meta.env.VITE_ENV]
export const IMG_URL = BASE_URL + '/images/'
export const FILE_URL = BASE_URL + '/data/'

View File

@ -1,6 +1,5 @@
import { createApp } from 'vue'
import App from './App.vue'
import mitt from 'mitt'
import './assets/less/index.less'
import { startMock } from '@/mock'
import router from './router'
@ -8,8 +7,11 @@ import mixin from './utils/mixin'
import VueLazyload from '@jambonn/vue-lazyload'
import { createPinia } from 'pinia'
import { useClick } from '@/utils/hooks/useClick'
import bus, { EVENT_KEY } from '@/utils/bus'
window.isMoved = false
window.isMuted = true
window.showMutedNotice = true
HTMLElement.prototype.addEventListener = new Proxy(HTMLElement.prototype.addEventListener, {
apply(target, ctx, args) {
const eventName = args[0]
@ -34,10 +36,7 @@ HTMLElement.prototype.addEventListener = new Proxy(HTMLElement.prototype.addEven
const vClick = useClick()
const pinia = createPinia()
const emitter = mitt()
const app = createApp(App)
app.config.globalProperties.emitter = emitter
app.provide('mitt', emitter)
app.mixin(mixin)
const loadImage = new URL('./assets/img/icon/img-loading.png', import.meta.url).href
app.use(VueLazyload, {
@ -52,3 +51,10 @@ app.directive('click', vClick)
//放到最后才可以使用pinia
startMock()
setTimeout(() => {
bus.emit(EVENT_KEY.HIDE_MUTED_NOTICE)
window.showMutedNotice = false
}, 2000)
bus.on(EVENT_KEY.REMOVE_MUTED, () => {
window.isMuted = false
})

View File

@ -22,11 +22,11 @@
<img src="../../../assets/img/icon/components/follow/share.png" alt="" />
<span>分享主页</span>
</div>
<div class="option" @click="cancel((e) => $nav('/message/chat'))">
<div class="option" @click="cancel((e) => $router.push('/message/chat'))">
<img src="../../../assets/img/icon/components/follow/private-chat.png" alt="" />
<span>发私信</span>
</div>
<div class="option" @click="cancel((e) => $nav('/home/report', { mode: 'chat' }))">
<div class="option" @click="cancel((e) => $router.push('/home/report', { mode: 'chat' }))">
<img src="../../../assets/img/icon/components/follow/report.png" alt="" />
<span>举报</span>
</div>

View File

@ -37,7 +37,12 @@
</div>
<div class="indicator" ref="indicator"></div>
</div>
<Icon v-hide="loading" icon="ion:search" class="search" @click="$nav('/home/search')" />
<Icon
v-hide="loading"
icon="ion:search"
class="search"
@click="$router.push('/home/search')"
/>
</div>
<div class="toggle-type" :class="{ open }">
<div class="l-button" :class="{ active: type === 0 }" @click="toggleType(0)">
@ -276,6 +281,7 @@ export default {
color: rgba(white, 0.7);
position: relative;
font-size: 17rem;
cursor: pointer;
.tab1-img {
position: absolute;

View File

@ -109,7 +109,7 @@
<div class="share-btn shared" v-else>已私信</div>
</div>
</div>
<div class="more" @click="cancel($nav('/message/share-to-friend'))">
<div class="more" @click="cancel($router.push('/message/share-to-friend'))">
<img src="../../../assets/img/icon/components/video/more-dark.png" />
<div class="right">
<span>更多好友</span>

View File

@ -38,7 +38,7 @@
:can-download="canDownload"
@click="closeShare()"
/>
<to-share item-type="report" @click="$nav('/home/report', { mode: this.mode })" />
<to-share item-type="report" @click="$router.push('/home/report', { mode: this.mode })" />
<to-share item-type="copyPassword" @click="copyLink" />
<to-share :item-type="isCollect ? 'collectYellow' : 'collect'" @click="toggleCollect" />
<to-share item-type="comeon" @click="_no" />
@ -67,7 +67,7 @@
</dy-button>
</div>
</div>
<div class="more" @click="closeShare($nav('/message/share-to-friend'))">
<div class="more" @click="closeShare($router.push('/message/share-to-friend'))">
<img class="left" src="../../../assets/img/icon/components/video/more-dark.png" />
<span>更多朋友</span>
</div>

View File

@ -320,10 +320,12 @@ onUnmounted(() => {
onActivated(() => {
state.active = true
bus.emit(EVENT_KEY.TOGGLE_CURRENT_VIDEO)
})
onDeactivated(() => {
state.active = false
bus.emit(EVENT_KEY.TOGGLE_CURRENT_VIDEO)
})
function closeComments() {

View File

@ -47,7 +47,7 @@
</div>
<SlideList
:active="props.active"
uniqueId="uniqueId3"
uniqueId="hot"
:style="{
background: 'black',
marginTop: state.subTypeVisible ? state.subTypeHeight : 0

View File

@ -18,7 +18,7 @@
<SlideList
:cbs="{ isLive: true }"
:active="props.active"
uniqueId="uniqueId2"
uniqueId="live"
:style="{
background: 'black',
marginTop: state.subTypeVisible ? state.subTypeHeight : 0

View File

@ -1,6 +1,11 @@
<template>
<SlideItem>
<SlideList style="background: #000" :active="props.active" :api="recommendedVideo" />
<SlideList
uniqueId="home"
style="background: #000"
:active="props.active"
:api="recommendedVideo"
/>
</SlideItem>
</template>

View File

@ -109,6 +109,7 @@ async function getData(refresh = false) {
// }
function click(uniqueId) {
if (!props.active) return
if (uniqueId !== props.uniqueId) return
bus.emit(EVENT_KEY.SINGLE_CLICK_BROADCAST, {
uniqueId,
@ -123,12 +124,23 @@ function updateItem({ position, item }) {
}
}
function togglePlay() {
if (!props.active) return
bus.emit(EVENT_KEY.SINGLE_CLICK_BROADCAST, {
uniqueId: props.uniqueId,
index: state.index,
type: EVENT_KEY.ITEM_TOGGLE
})
}
onMounted(() => {
bus.on(EVENT_KEY.SINGLE_CLICK, click)
bus.on(EVENT_KEY.UPDATE_ITEM, updateItem)
bus.on(EVENT_KEY.TOGGLE_CURRENT_VIDEO, togglePlay)
})
onUnmounted(() => {
bus.off(EVENT_KEY.SINGLE_CLICK, click)
bus.on(EVENT_KEY.UPDATE_ITEM, updateItem)
bus.off(EVENT_KEY.UPDATE_ITEM, updateItem)
bus.off(EVENT_KEY.TOGGLE_CURRENT_VIDEO, togglePlay)
})
</script>

View File

@ -2,7 +2,7 @@
<div class="other-login" id="other-login">
<BaseHeader mode="light" backMode="dark" backImg="back">
<template v-slot:right>
<span class="f14" @click="$nav('/login/help')">帮助与设置</span>
<span class="f14" @click="$router.push('/login/help')">帮助与设置</span>
</template>
</BaseHeader>
<div class="content">
@ -24,11 +24,13 @@
</div>
<div class="right">
已阅读并同意
<span class="link" @click="$nav('/service-protocol', { type: '“抖音”用户服务协议' })"
<span
class="link"
@click="$router.push('/service-protocol', { type: '“抖音”用户服务协议' })"
>用户协议</span
>
<span class="link" @click="$nav('/service-protocol', { type: '“抖音”隐私政策' })"
<span class="link" @click="$router.push('/service-protocol', { type: '“抖音”隐私政策' })"
>隐私政策</span
>
同时登录并使用抖音火山版火山小视频和抖音
@ -46,7 +48,7 @@
</dy-button>
<div class="options">
<span class="link" @click="$nav('/login/password')">密码登录</span>
<span class="link" @click="$router.push('/login/password')">密码登录</span>
<span class="link" @click="otherLogin">其他方式登录</span>
</div>

View File

@ -2,7 +2,7 @@
<div class="PasswordLogin">
<BaseHeader mode="light" backMode="dark" backImg="back">
<template v-slot:right>
<span class="f14" @click="$nav('/login/help')">帮助与设置</span>
<span class="f14" @click="$router.push('/login/help')">帮助与设置</span>
</template>
</BaseHeader>
<div class="content">
@ -26,11 +26,13 @@
</div>
<div class="right">
已阅读并同意
<span class="link" @click="$nav('/service-protocol', { type: '“抖音”用户服务协议' })"
<span
class="link"
@click="$router.push('/service-protocol', { type: '“抖音”用户服务协议' })"
>用户协议</span
>
<span class="link" @click="$nav('/service-protocol', { type: '“抖音”隐私政策' })"
<span class="link" @click="$router.push('/service-protocol', { type: '“抖音”隐私政策' })"
>隐私政策</span
>
同时登录并使用抖音火山版火山小视频和抖音
@ -53,7 +55,9 @@
<div class="options">
<span>
忘记了<span class="link" @click="$nav('/login/retrieve-password')">找回密码</span>
忘记了<span class="link" @click="$router.push('/login/retrieve-password')"
>找回密码</span
>
</span>
</div>
</div>

View File

@ -32,11 +32,13 @@
</div>
<div class="right">
已阅读并同意
<span class="link" @click="$nav('/service-protocol', { type: '“抖音”用户服务协议' })"
<span
class="link"
@click="$router.push('/service-protocol', { type: '“抖音”用户服务协议' })"
>用户协议</span
>
<span class="link" @click="$nav('/service-protocol', { type: '“抖音”隐私政策' })"
<span class="link" @click="$router.push('/service-protocol', { type: '“抖音”隐私政策' })"
>隐私政策</span
>
同时登录并使用抖音火山版火山小视频和抖音

View File

@ -19,7 +19,7 @@
<span class="notice">抖音扫一扫立即关注我</span>
</div>
<div class="footer">
<!-- <div class="btn" @click="$nav('/scan')">-->
<!-- <div class="btn" @click="$router.push('/scan')">-->
<div class="btn" @click="_no">
<div class="wrapper">
<img src="../../assets/img/icon/scan.png" alt="" />

View File

@ -11,7 +11,7 @@
<span class="belong">{{ store.userinfo.nickname }}的红包</span>
<div class="password">大吉大利</div>
<span class="money">0.01</span>
<!-- <span class="notice" @click="$nav('/me/money')">已存入我的零钱可直接使用></span>-->
<!-- <span class="notice" @click="$router.push('/me/money')">已存入我的零钱可直接使用></span>-->
<span class="notice" @click="_no">已存入我的零钱可直接使用></span>
</div>
<img src="../../assets/img/icon/message/chat/money-detail-bg.png" alt="" class="bg" />

View File

@ -9,7 +9,7 @@
</div>
<div class="right">
<img
@click="mitt.emit('showAudioCall')"
@click="bus.emit(EVENT_KEY.SHOW_AUDIO_CALL)"
src="../../../assets/img/icon/message/chat/call.png"
alt=""
/>
@ -187,12 +187,13 @@
</template>
<script setup lang="ts">
import ChatMessage from '../components/ChatMessage.vue'
import { computed, inject, nextTick, onMounted, onUnmounted, reactive, ref } from 'vue'
import { computed, nextTick, onMounted, onUnmounted, reactive, ref } from 'vue'
import Loading from '@/components/Loading.vue'
import { useBaseStore } from '@/store/pinia'
import { _checkImgUrl, _no, _sleep } from '@/utils'
import { useRouter } from 'vue-router'
import { useNav } from '@/utils/hooks/useNav'
import bus, { EVENT_KEY } from '@/utils/bus'
let CALL_STATE = {
REJECT: 0,
@ -233,7 +234,6 @@ defineOptions({
name: 'Chat'
})
const mitt = inject('mitt')
const router = useRouter()
const nav = useNav()
const store = useBaseStore()

View File

@ -62,5 +62,9 @@ export const EVENT_KEY = {
GO_USERINFO: 'GO_USERINFO',
SHOW_SHARE: 'SHOW_SHARE',
UPDATE_ITEM: 'UPDATE_ITEM',
CURRENT_ITEM: 'CURRENT_ITEM'
CURRENT_ITEM: 'CURRENT_ITEM',
REMOVE_MUTED: 'REMOVE_MUTED',
HIDE_MUTED_NOTICE: 'HIDE_MUTED_NOTICE',
TOGGLE_CURRENT_VIDEO: 'TOGGLE_CURRENT_VIDEO',
SHOW_AUDIO_CALL: 'SHOW_AUDIO_CALL'
}

View File

@ -8,10 +8,11 @@ export function useClick() {
el.addEventListener('pointerdown', (e) => _stopPropagation(e))
el.addEventListener('pointerup', (e) => {
_stopPropagation(e)
binding.value?.()
binding.value?.(e)
})
},
unmounted(el: HTMLDivElement) {
// eslint-disable-next-line
el = null
}
}

View File

@ -3,7 +3,7 @@ import SelectDialog from '../components/dialog/SelectDialog.vue'
import SimpleConfirmDialog from '../components/dialog/SimpleConfirmDialog.vue'
import ConfirmDialog from '../components/dialog/ConfirmDialog.vue'
import Loading from '../components/Loading.vue'
import { IMG_URL, IS_DEV } from '@/config'
import { IMG_URL, IS_DEV, IS_GITEE_PAGES } from '@/config'
import NoticeDialog from '../components/dialog/NoticeDialog.vue'
import bus, { EVENT_KEY } from './bus'
import { ArchiveReader, libarchiveWasm } from 'libarchive-wasm'
@ -381,7 +381,7 @@ export function _no() {
* @privateF
*/
export async function _fetch(url: string): Promise<{ json(): Promise<any> } | Response> {
if (IS_DEV) {
if (IS_DEV || !IS_GITEE_PAGES) {
url = url.replace('.md', '.json')
return fetch(url)
} else {

View File

@ -10,7 +10,7 @@ import BaseButton from '../components/BaseButton.vue'
import CONST_VAR from './const_var'
import Dom from './dom'
import bus, { EVENT_KEY } from './bus'
import { _stopPropagation, random } from '@/utils'
import { random } from '@/utils'
import { Icon } from '@iconify/vue'
import SlideHorizontal from '@/components/slide/SlideHorizontal.vue'
@ -152,7 +152,7 @@ export default {
const up = (e) => {
if (!isDown) return
if (!isMove) check(e)
if (!isMove && !window.isMoved) check(e)
isMove = isDown = false
}

View File

@ -22,8 +22,8 @@ axiosInstance.interceptors.request.use(
)
/*
* { code: xxx, data: xxx }reject和抛error
* { code: Xxx, data:xxx }then里面总是会接收到
* { success: boolean, data: xxx }reject和抛error
* then里面总是会接收到返回值
* */
axiosInstance.interceptors.response.use(
(response: AxiosResponse) => {

View File

@ -107,7 +107,7 @@ export function slideTouchMove(
notNextCb = null,
slideOtherDirectionCb = null
) {
console.log('move', state.name)
// console.log('move', state.name)
if (!checkEvent(e)) return
if (!state.isDown) return

View File

@ -18,6 +18,9 @@
"@/*": [
"./src/*"
]
}
},
"types": [
"unplugin-vue-macros/macros-global"
]
}
}

View File

@ -1,13 +1,11 @@
import { defineConfig, PluginOption } from 'vite'
import Vue from '@vitejs/plugin-vue'
import VueJsx from '@vitejs/plugin-vue-jsx'
import { resolve } from 'path'
import { visualizer } from 'rollup-plugin-visualizer'
import DefineOptions from 'unplugin-vue-define-options/vite' // 引入插件
import { Plugin as importToCDN } from 'vite-plugin-cdn-import'
import commonjs from 'vite-plugin-commonjs'
import { fileURLToPath, URL } from 'node:url'
import { getLastCommit } from 'git-last-commit'
import VueMacros from 'unplugin-vue-macros/vite'
// import viteImagemin from 'vite-plugin-imagemin'
// import viteCompression from 'vite-plugin-compression'
@ -28,20 +26,19 @@ export default defineConfig(async () => {
base: './',
envDir: 'env',
plugins: [
// VueMacros({
// plugins: {
// vue: Vue(),
// vueJsx: VueJsx(), // if needed
// },
// betterDefine: true,
// // reactivityTransform: {
// // exclude: [/node_modules/, /jQuery\.js/]
// // }
// }),
VueMacros({
plugins: {
vue: Vue(),
vueJsx: VueJsx() // if needed
}
// betterDefine: true,
// reactivityTransform: {
// exclude: [/node_modules/, /jQuery\.js/]
// }
}),
// Vue(),
// VueJsx(),
lifecycle === 'report' ? (visualizer({ open: false }) as any as PluginOption) : null,
DefineOptions(),
Vue(),
VueJsx(),
importToCDN({
modules: [
{