Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a8f0f64868 | ||
|
|
e53c2db532 | ||
|
|
62cc947be5 | ||
|
|
415d5952c2 |
123
README-en-US.md
@@ -1,83 +1,66 @@
|
||||
### English | [简体中文](README.md)
|
||||
<h1 align="center">
|
||||
Douyin
|
||||
</h1>
|
||||
|
||||
## Preview Demo
|
||||
[Online Demo](http://dy.ttentau.top/)
|
||||
<p align="center">
|
||||
<a href="README.md">简体中文</a> |
|
||||
<a href="README-en-US.md">English</a>
|
||||
</p>
|
||||
|
||||
### Note: Please use mobile mode of Chrome browser to access the PC side. To switch Chrome to mobile mode, press F12 to bring up the console, then Ctrl+Shift+M
|
||||
### Note: For Android phones please use [Via mobile browser](https://viayoo.com/zh-cn/) or Chrome mobile version preview. When other browsers detect a video on the page, they force the video to be in full screen and display the control button. As a result, both css and js are invalid
|
||||
<div style="text-align:center">
|
||||
<img width="180px" src='http://www.ttentau.top/dy/imgs/0.png' />
|
||||
<img width="180px" src='http://www.ttentau.top/dy/imgs/1.png' />
|
||||
<img width="180px" src='http://www.ttentau.top/dy/imgs/6.png' />
|
||||
<img width="180px" src='http://www.ttentau.top/dy/imgs/3.png' />
|
||||
<img width="180px" src='http://www.ttentau.top/dy/imgs/2.png' />
|
||||
<img width="180px" src='http://www.ttentau.top/dy/imgs/8.png' />
|
||||
<img width="180px" src='http://www.ttentau.top/dy/imgs/9.png' />
|
||||
<img width="180px" src='http://www.ttentau.top/dy/imgs/11.png' />
|
||||
|
||||
<p align="center">
|
||||
<b>douyin</b>It is a mobile short video project imitating Douyin.,
|
||||
It is based on <a href="https://v3.cn.vuejs.org">Vue</a>, <a href="https://cn.vitejs.dev/">Vite</a> implementation.
|
||||
The latest Vue family bucket technology stack is used, and the background data is built by <a href="https://github.com/ctimmerm/axios-mock-adapter">axios-mock-adapter</a>.
|
||||
</p>
|
||||
|
||||
## 📸 在线访问
|
||||
|
||||
Netlify: <https://douyins.netlify.app> (If you are in China, you need Vpn)
|
||||
|
||||
Vercel: <http://dy.ttentau.top> (This is recommended in China.)
|
||||
|
||||
**Note**: PC browsers should be accessed in mobile mode.
|
||||
Press F12 to bring up the console, and then press Ctrl+Shift+M to switch to mobile mode.
|
||||
|
||||
**Note**: for mobile phones, please use [Via browser] (https://viayoo.com/zh-cn/) or Chrome browser preview).
|
||||
Other browsers will force the video to be full-screen, invalidating the style.
|
||||
|
||||
## 🖼️ Effect screenshot
|
||||
|
||||
<div>
|
||||
<img width="150px" src='./public/docs/1.gif' />
|
||||
<img width="150px" src='./public/docs/2.gif' />
|
||||
<img width="150px" src='./public/docs/3.gif' />
|
||||
<img width="150px" src='./public/docs/4.gif' />
|
||||
<img width="150px" src='./public/docs/5.gif' />
|
||||
<img width="150px" src='./public/docs/img-1.jpg' />
|
||||
<img width="150px" src='./public/docs/img-2.jpg' />
|
||||
<img width="150px" src='./public/docs/img-3.jpg' />
|
||||
<img width="150px" src='./public/docs/img-4.jpg' />
|
||||
<img width="150px" src='./public/docs/img-5.jpg' />
|
||||
</div>
|
||||
|
||||
## Introduction
|
||||
## Run the project
|
||||
|
||||
**Douyin** is a mobile short video project imitating Tiktok,It is based on [vue 3](https://v3.cn.vuejs.org/),
|
||||
[vite 2](https://cn.vitejs.dev/)
|
||||
implementation。
|
||||
The latest Vue family bucket technology stack is used, and the background data is built through [mock-js](http://mockjs.com).
|
||||
This project is based on `Vue` and needs node environment to run.
|
||||
|
||||
## Function point
|
||||
1. To install NodeJS, refer to [official documentation] (https://nodejs.org/en/download))
|
||||
2. Use `git clone https://github.com/zyronon/douyin.git` to download the project locally.
|
||||
3. Enter the project directory `npm install` and run `project install` under the project root directory to download the dependency.
|
||||
4. Execute `project dev` to start the project. The default address of the project is [`http://localhost:3000`](http://localhost:3000)].
|
||||
5. Open [`http://localhost:3000`](http://localhost:3000)] in the browser to access the project.
|
||||
Chrome switch to mobile phone mode shortcut key, press F12 to bring up the console, and then press Ctrl+Shift+M
|
||||
|
||||
Page | Progress
|
||||
--------------|---------
|
||||
Home | 50%
|
||||
-- Music | ☑
|
||||
-- 抖音音乐榜 | ☑
|
||||
-- Search | 50%
|
||||
-- Live | 50%
|
||||
Friend | 0%
|
||||
Message | ☑
|
||||
-- Chat | ☑
|
||||
-- 各种通知 | ☑
|
||||
Me | 90%
|
||||
-- 求更新 | ☑
|
||||
-- 关注和粉丝 | ☑
|
||||
-- 编辑资料 | ☑
|
||||
-- Add friend | ☑
|
||||
-- My music | ☑
|
||||
-- Shop | 0
|
||||
-- 收藏视频\音乐 | ☑
|
||||
-- 右侧菜单子页面 | 10%
|
||||
-- Setting | ☑
|
||||
-- -- 具体设置页面 | 0%
|
||||
Sign in\Sign up | ☑
|
||||
## 🎙 Functions and suggestions
|
||||
|
||||
## How to start
|
||||
At present, the project is in the early stage of development, and new features are being added continuously. If you have any functions and suggestions for the software, you are welcome to put forward them in Issues.
|
||||
If you also like the design idea of this software, welcome to submit pr, thank you very much for your support!
|
||||
|
||||
```bash
|
||||
# Clone the project to local
|
||||
git clone https://github.com/zyronon/douyin.git
|
||||
## Contact me
|
||||
|
||||
# Enter the project directory
|
||||
cd douyin
|
||||
You can contact my email address < a href= "mailto:zyronon@163.com" > zyronon@163.com < / a >
|
||||
|
||||
# Install dependencies
|
||||
npm install
|
||||
|
||||
# Start the service
|
||||
npm run dev
|
||||
|
||||
# Visit
|
||||
Chrome browser access http://localhost:5173
|
||||
Chrome switches to mobile mode by pressing F12 to bring up the console, then Ctrl+Shift+M
|
||||
|
||||
```
|
||||
|
||||
## Contribution
|
||||
|
||||
Feel free to contribute by opening issues with any questions, bug reports or feature requests.
|
||||
|
||||
## Get in touch
|
||||
|
||||
You can reach us at <a href="mailto:zyronon@163.com">zyronon@163.com</a>
|
||||
|
||||
## License
|
||||
## MIT license Agreement
|
||||
|
||||
[MIT](LICENSE)
|
||||
|
||||
115
README.md
@@ -1,83 +1,60 @@
|
||||
### 简体中文 | [English](README-en-US.md)
|
||||
<h1 align="center">
|
||||
Douyin
|
||||
</h1>
|
||||
|
||||
## 预览
|
||||
<p align="center">
|
||||
<a href="README.md">简体中文</a> |
|
||||
<a href="README-en-US.md">English</a>
|
||||
</p>
|
||||
|
||||
[在线预览DEMO](http://dy.ttentau.top/)
|
||||
|
||||
#### 注意:电脑端请用Chrome浏览器的手机模式访问。Chrome切换成手机模式快捷键,先按F12调出控制台,再按Ctrl+Shift+M
|
||||
<p align="center">
|
||||
<b>douyin</b>是一个模仿抖音的移动端短视频项目,它基于 <a href="https://v3.cn.vuejs.org">Vue</a>,
|
||||
<a href="https://cn.vitejs.dev/">Vite</a>实现。使用了最新的Vue全家桶技术栈,接口数据通过
|
||||
<a href="https://github.com/ctimmerm/axios-mock-adapter">axios-mock-adapter</a>模拟
|
||||
</p>
|
||||
|
||||
#### 注意:安卓手机请用[Via手机浏览器](https://viayoo.com/zh-cn/)或者Chrome浏览器手机版本预览。其他浏览器检测到页面内有视频会强制将视频全屏,并显示控制按钮,导致css和js都失效
|
||||
## 📸 在线访问
|
||||
|
||||
<div style="text-align:center">
|
||||
<img width="180px" src='http://www.ttentau.top/dy/imgs/0.png' />
|
||||
<img width="180px" src='http://www.ttentau.top/dy/imgs/1.png' />
|
||||
<img width="180px" src='http://www.ttentau.top/dy/imgs/6.png' />
|
||||
<img width="180px" src='http://www.ttentau.top/dy/imgs/3.png' />
|
||||
<img width="180px" src='http://www.ttentau.top/dy/imgs/2.png' />
|
||||
<img width="180px" src='http://www.ttentau.top/dy/imgs/8.png' />
|
||||
<img width="180px" src='http://www.ttentau.top/dy/imgs/9.png' />
|
||||
<img width="180px" src='http://www.ttentau.top/dy/imgs/11.png' />
|
||||
Vercel: <http://dy.ttentau.top> (国内推荐访问这个)
|
||||
|
||||
Netlify: <https://douyins.netlify.app> (需要翻墙)
|
||||
|
||||
**注意**:PC浏览器请用手机模式访问。先按F12调出控制台,再按Ctrl+Shift+M切换到手机模式
|
||||
|
||||
**注意**:手机请用[Via浏览器](https://viayoo.com/zh-cn/)或者Chrome浏览器预览。其他浏览器会强制将视频全屏,导致样式都失效
|
||||
|
||||
## 🖼️ 效果截图
|
||||
|
||||
<div>
|
||||
<img width="150px" src='./public/docs/1.gif' />
|
||||
<img width="150px" src='./public/docs/2.gif' />
|
||||
<img width="150px" src='./public/docs/3.gif' />
|
||||
<img width="150px" src='./public/docs/4.gif' />
|
||||
<img width="150px" src='./public/docs/5.gif' />
|
||||
<img width="150px" src='./public/docs/img-1.jpg' />
|
||||
<img width="150px" src='./public/docs/img-2.jpg' />
|
||||
<img width="150px" src='./public/docs/img-3.jpg' />
|
||||
<img width="150px" src='./public/docs/img-4.jpg' />
|
||||
<img width="150px" src='./public/docs/img-5.jpg' />
|
||||
</div>
|
||||
|
||||
## 简介
|
||||
## 运行项目
|
||||
|
||||
**douyin** 是一个模仿抖音的移动端短视频项目,它基于 [Vue 3](https://v3.cn.vuejs.org/),
|
||||
[Vite](https://cn.vitejs.dev/)
|
||||
实现。使用了最新的Vue全家桶技术栈,后台数据通过[mock-js](http://mockjs.com)搭建
|
||||
本项目是基于`Vue`开发的,需要 node 环境来运行。
|
||||
|
||||
## 效果截图
|
||||
1. 安装 NodeJS,参考[官方文档](https://nodejs.org/en/download)
|
||||
2. 使用 `git clone https://github.com/zyronon/douyin.git` 下载项目到本地
|
||||
3. 进入项目目录` cd douyin `,在项目根目录下,运行`npm install`来下载依赖。
|
||||
4. 执行`npm run dev`来启动项目,项目默认地址为[`http://localhost:3000`](http://localhost:3000)
|
||||
5. 在浏览器中打开[`http://localhost:3000`](http://localhost:3000) 来访问项目。
|
||||
Chrome切换成手机模式快捷键,先按F12调出控制台,再按Ctrl+Shift+M
|
||||
|
||||
## 功能点
|
||||
|
||||
页面 | 进度
|
||||
--------------|---------
|
||||
首页 | 50%
|
||||
-- 音乐 | ☑
|
||||
-- 抖音音乐榜 | ☑
|
||||
-- 搜索 | 50%
|
||||
-- 直播 | 50%
|
||||
朋友 | 0%
|
||||
消息 | ☑
|
||||
-- 聊天 | ☑
|
||||
-- 各种通知 | ☑
|
||||
我 | 90%
|
||||
-- 求更新 | ☑
|
||||
-- 关注和粉丝 | ☑
|
||||
-- 编辑资料 | ☑
|
||||
-- 添加朋友 | ☑
|
||||
-- 我的音乐 | ☑
|
||||
-- 抖音商城 | 0
|
||||
-- 收藏视频\音乐 | ☑
|
||||
-- 右侧菜单子页面 | 10%
|
||||
-- 设置 | ☑
|
||||
-- -- 具体设置页面 | 0%
|
||||
登录\注册 | ☑
|
||||
|
||||
## 运行
|
||||
|
||||
```bash
|
||||
# 克隆项目到本地
|
||||
git clone https://github.com/zyronon/douyin.git
|
||||
|
||||
# 进入项目目录
|
||||
cd douyin
|
||||
|
||||
# 安装依赖
|
||||
npm install
|
||||
|
||||
# 启动服务
|
||||
npm run dev
|
||||
|
||||
# 访问
|
||||
Chrome浏览器访问 http://localhost:5173
|
||||
Chrome切换成手机模式快捷键,先按F12调出控制台,再按Ctrl+Shift+M
|
||||
|
||||
```
|
||||
|
||||
## 问题反馈
|
||||
|
||||
如果有任何问题、错误报告或功能请求,请随时提出Issues。
|
||||
## 🎙 功能与建议
|
||||
|
||||
目前项目处于开发初期,新功能正在持续添加中,如果你对软件有任何功能与建议,欢迎在 Issues 中提出
|
||||
如果你也喜欢本软件的设计思想,欢迎提交 pr,非常感谢你对我们的支持!
|
||||
|
||||
## 联系我
|
||||
|
||||
您可以联系我的邮箱 <a href="mailto:zyronon@163.com">zyronon@163.com</a>
|
||||
|
||||
653
public/data/goods.json
Normal file
@@ -0,0 +1,653 @@
|
||||
[
|
||||
{
|
||||
"name": "小米电视6 65\" OLED 65英寸",
|
||||
"cover": "g6-0.jpg",
|
||||
"imgs": [
|
||||
"g6-0.jpg",
|
||||
"g6-1.jpg",
|
||||
"g6-2.jpg",
|
||||
"g6-3.jpg",
|
||||
"g6-4.jpg"
|
||||
],
|
||||
"price": 6699,
|
||||
"real_price": 399,
|
||||
"isLowPrice": false,
|
||||
"discount": "",
|
||||
"sold": 863
|
||||
},
|
||||
{
|
||||
"name": "红白撞色条纹软糯针织上衣女2022年秋季新款甜美减龄短款毛衣开衫",
|
||||
"cover": "g1-0.jpg",
|
||||
"imgs": [
|
||||
"g1-0.jpg",
|
||||
"g1-1.jpg",
|
||||
"g1-2.jpg",
|
||||
"g1-3.jpg"
|
||||
],
|
||||
"isLowPrice": true,
|
||||
"discount": "满4减3",
|
||||
"sold": 134,
|
||||
"price": 39.9,
|
||||
"real_price": 9.9
|
||||
},
|
||||
{
|
||||
"name": "森马t恤男2023男士纯棉上衣白色情侣装凉感短袖打底衫纯色体恤潮",
|
||||
"imgs": [
|
||||
"g2-0.webp",
|
||||
"g2-1.webp",
|
||||
"g2-2.webp",
|
||||
"g2-3.webp"
|
||||
],
|
||||
"cover": "g2-0.webp",
|
||||
"real_price": 9.9,
|
||||
"price": 49.99,
|
||||
"isLowPrice": false,
|
||||
"discount": "满20减5",
|
||||
"sold": 3314
|
||||
},
|
||||
{
|
||||
"name": "ins潮牌长袖t恤男宽松纯色内搭上衣潮牌百搭秋冬季潮流帅气打底衫",
|
||||
"cover": "g3-0.jpg",
|
||||
"imgs": [
|
||||
"g3-0.jpg",
|
||||
"g3-1.jpg",
|
||||
"g3-2.jpg",
|
||||
"g3-3.jpg",
|
||||
"g3-4.jpg"
|
||||
],
|
||||
"real_price": 9.9,
|
||||
"price": 22.90,
|
||||
"isLowPrice": true,
|
||||
"discount": "满10减3",
|
||||
"sold": 129
|
||||
},
|
||||
{
|
||||
"name": "Redmi K60狠快狠强,狠旗舰!2023,第一台梦幻手机",
|
||||
"cover": "g4-0.png",
|
||||
"imgs": [
|
||||
"g4-0.png",
|
||||
"g4-1.png",
|
||||
"g4-2.png",
|
||||
"g4-3.png"
|
||||
],
|
||||
"real_price": 199.9,
|
||||
"price": 2999,
|
||||
"isLowPrice": true,
|
||||
"discount": "",
|
||||
"sold": 967
|
||||
},
|
||||
{
|
||||
"name": "小米笔记本Pro X 14",
|
||||
"imgs": [
|
||||
"g5-0.jpg",
|
||||
"g5-1.jpg",
|
||||
"g5-2.jpg",
|
||||
"g5-3.jpg",
|
||||
"g5-4.jpg"
|
||||
],
|
||||
"cover": "g5-0.jpg",
|
||||
"real_price": 1559.9,
|
||||
"price": 6999,
|
||||
"isLowPrice": false,
|
||||
"discount": "",
|
||||
"sold": 473
|
||||
},
|
||||
{
|
||||
"name": "小米电视6 65\" OLED 65英寸",
|
||||
"cover": "g6-0.jpg",
|
||||
"imgs": [
|
||||
"g6-0.jpg",
|
||||
"g6-1.jpg",
|
||||
"g6-2.jpg",
|
||||
"g6-3.jpg",
|
||||
"g6-4.jpg"
|
||||
],
|
||||
"price": 6699,
|
||||
"real_price": 399,
|
||||
"isLowPrice": false,
|
||||
"discount": "",
|
||||
"sold": 863
|
||||
},
|
||||
{
|
||||
"name": "红白撞色条纹软糯针织上衣女2022年秋季新款甜美减龄短款毛衣开衫",
|
||||
"cover": "g1-0.jpg",
|
||||
"imgs": [
|
||||
"g1-0.jpg",
|
||||
"g1-1.jpg",
|
||||
"g1-2.jpg",
|
||||
"g1-3.jpg"
|
||||
],
|
||||
"isLowPrice": true,
|
||||
"discount": "满4减3",
|
||||
"sold": 134,
|
||||
"price": 39.9,
|
||||
"real_price": 9.9
|
||||
},
|
||||
{
|
||||
"name": "森马t恤男2023男士纯棉上衣白色情侣装凉感短袖打底衫纯色体恤潮",
|
||||
"imgs": [
|
||||
"g2-0.webp",
|
||||
"g2-1.webp",
|
||||
"g2-2.webp",
|
||||
"g2-3.webp"
|
||||
],
|
||||
"cover": "g2-0.webp",
|
||||
"real_price": 9.9,
|
||||
"price": 49.99,
|
||||
"isLowPrice": false,
|
||||
"discount": "满20减5",
|
||||
"sold": 3314
|
||||
},
|
||||
{
|
||||
"name": "ins潮牌长袖t恤男宽松纯色内搭上衣潮牌百搭秋冬季潮流帅气打底衫",
|
||||
"cover": "g3-0.jpg",
|
||||
"imgs": [
|
||||
"g3-0.jpg",
|
||||
"g3-1.jpg",
|
||||
"g3-2.jpg",
|
||||
"g3-3.jpg",
|
||||
"g3-4.jpg"
|
||||
],
|
||||
"real_price": 9.9,
|
||||
"price": 22.90,
|
||||
"isLowPrice": true,
|
||||
"discount": "满10减3",
|
||||
"sold": 129
|
||||
},
|
||||
{
|
||||
"name": "Redmi K60狠快狠强,狠旗舰!2023,第一台梦幻手机",
|
||||
"cover": "g4-0.png",
|
||||
"imgs": [
|
||||
"g4-0.png",
|
||||
"g4-1.png",
|
||||
"g4-2.png",
|
||||
"g4-3.png"
|
||||
],
|
||||
"real_price": 199.9,
|
||||
"price": 2999,
|
||||
"isLowPrice": true,
|
||||
"discount": "",
|
||||
"sold": 967
|
||||
},
|
||||
{
|
||||
"name": "小米笔记本Pro X 14",
|
||||
"imgs": [
|
||||
"g5-0.jpg",
|
||||
"g5-1.jpg",
|
||||
"g5-2.jpg",
|
||||
"g5-3.jpg",
|
||||
"g5-4.jpg"
|
||||
],
|
||||
"cover": "g5-0.jpg",
|
||||
"real_price": 1559.9,
|
||||
"price": 6999,
|
||||
"isLowPrice": false,
|
||||
"discount": "",
|
||||
"sold": 473
|
||||
},
|
||||
{
|
||||
"name": "小米电视6 65\" OLED 65英寸",
|
||||
"cover": "g6-0.jpg",
|
||||
"imgs": [
|
||||
"g6-0.jpg",
|
||||
"g6-1.jpg",
|
||||
"g6-2.jpg",
|
||||
"g6-3.jpg",
|
||||
"g6-4.jpg"
|
||||
],
|
||||
"price": 6699,
|
||||
"real_price": 399,
|
||||
"isLowPrice": false,
|
||||
"discount": "",
|
||||
"sold": 863
|
||||
},
|
||||
{
|
||||
"name": "红白撞色条纹软糯针织上衣女2022年秋季新款甜美减龄短款毛衣开衫",
|
||||
"cover": "g1-0.jpg",
|
||||
"imgs": [
|
||||
"g1-0.jpg",
|
||||
"g1-1.jpg",
|
||||
"g1-2.jpg",
|
||||
"g1-3.jpg"
|
||||
],
|
||||
"isLowPrice": true,
|
||||
"discount": "满4减3",
|
||||
"sold": 134,
|
||||
"price": 39.9,
|
||||
"real_price": 9.9
|
||||
},
|
||||
{
|
||||
"name": "森马t恤男2023男士纯棉上衣白色情侣装凉感短袖打底衫纯色体恤潮",
|
||||
"imgs": [
|
||||
"g2-0.webp",
|
||||
"g2-1.webp",
|
||||
"g2-2.webp",
|
||||
"g2-3.webp"
|
||||
],
|
||||
"cover": "g2-0.webp",
|
||||
"real_price": 9.9,
|
||||
"price": 49.99,
|
||||
"isLowPrice": false,
|
||||
"discount": "满20减5",
|
||||
"sold": 3314
|
||||
},
|
||||
{
|
||||
"name": "ins潮牌长袖t恤男宽松纯色内搭上衣潮牌百搭秋冬季潮流帅气打底衫",
|
||||
"cover": "g3-0.jpg",
|
||||
"imgs": [
|
||||
"g3-0.jpg",
|
||||
"g3-1.jpg",
|
||||
"g3-2.jpg",
|
||||
"g3-3.jpg",
|
||||
"g3-4.jpg"
|
||||
],
|
||||
"real_price": 9.9,
|
||||
"price": 22.90,
|
||||
"isLowPrice": true,
|
||||
"discount": "满10减3",
|
||||
"sold": 129
|
||||
},
|
||||
{
|
||||
"name": "Redmi K60狠快狠强,狠旗舰!2023,第一台梦幻手机",
|
||||
"cover": "g4-0.png",
|
||||
"imgs": [
|
||||
"g4-0.png",
|
||||
"g4-1.png",
|
||||
"g4-2.png",
|
||||
"g4-3.png"
|
||||
],
|
||||
"real_price": 199.9,
|
||||
"price": 2999,
|
||||
"isLowPrice": true,
|
||||
"discount": "",
|
||||
"sold": 967
|
||||
},
|
||||
{
|
||||
"name": "小米笔记本Pro X 14",
|
||||
"imgs": [
|
||||
"g5-0.jpg",
|
||||
"g5-1.jpg",
|
||||
"g5-2.jpg",
|
||||
"g5-3.jpg",
|
||||
"g5-4.jpg"
|
||||
],
|
||||
"cover": "g5-0.jpg",
|
||||
"real_price": 1559.9,
|
||||
"price": 6999,
|
||||
"isLowPrice": false,
|
||||
"discount": "",
|
||||
"sold": 473
|
||||
},
|
||||
{
|
||||
"name": "小米电视6 65\" OLED 65英寸",
|
||||
"cover": "g6-0.jpg",
|
||||
"imgs": [
|
||||
"g6-0.jpg",
|
||||
"g6-1.jpg",
|
||||
"g6-2.jpg",
|
||||
"g6-3.jpg",
|
||||
"g6-4.jpg"
|
||||
],
|
||||
"price": 6699,
|
||||
"real_price": 399,
|
||||
"isLowPrice": false,
|
||||
"discount": "",
|
||||
"sold": 863
|
||||
},
|
||||
{
|
||||
"name": "红白撞色条纹软糯针织上衣女2022年秋季新款甜美减龄短款毛衣开衫",
|
||||
"cover": "g1-0.jpg",
|
||||
"imgs": [
|
||||
"g1-0.jpg",
|
||||
"g1-1.jpg",
|
||||
"g1-2.jpg",
|
||||
"g1-3.jpg"
|
||||
],
|
||||
"isLowPrice": true,
|
||||
"discount": "满4减3",
|
||||
"sold": 134,
|
||||
"price": 39.9,
|
||||
"real_price": 9.9
|
||||
},
|
||||
{
|
||||
"name": "森马t恤男2023男士纯棉上衣白色情侣装凉感短袖打底衫纯色体恤潮",
|
||||
"imgs": [
|
||||
"g2-0.webp",
|
||||
"g2-1.webp",
|
||||
"g2-2.webp",
|
||||
"g2-3.webp"
|
||||
],
|
||||
"cover": "g2-0.webp",
|
||||
"real_price": 9.9,
|
||||
"price": 49.99,
|
||||
"isLowPrice": false,
|
||||
"discount": "满20减5",
|
||||
"sold": 3314
|
||||
},
|
||||
{
|
||||
"name": "ins潮牌长袖t恤男宽松纯色内搭上衣潮牌百搭秋冬季潮流帅气打底衫",
|
||||
"cover": "g3-0.jpg",
|
||||
"imgs": [
|
||||
"g3-0.jpg",
|
||||
"g3-1.jpg",
|
||||
"g3-2.jpg",
|
||||
"g3-3.jpg",
|
||||
"g3-4.jpg"
|
||||
],
|
||||
"real_price": 9.9,
|
||||
"price": 22.90,
|
||||
"isLowPrice": true,
|
||||
"discount": "满10减3",
|
||||
"sold": 129
|
||||
},
|
||||
{
|
||||
"name": "Redmi K60狠快狠强,狠旗舰!2023,第一台梦幻手机",
|
||||
"cover": "g4-0.png",
|
||||
"imgs": [
|
||||
"g4-0.png",
|
||||
"g4-1.png",
|
||||
"g4-2.png",
|
||||
"g4-3.png"
|
||||
],
|
||||
"real_price": 199.9,
|
||||
"price": 2999,
|
||||
"isLowPrice": true,
|
||||
"discount": "",
|
||||
"sold": 967
|
||||
},
|
||||
{
|
||||
"name": "小米笔记本Pro X 14",
|
||||
"imgs": [
|
||||
"g5-0.jpg",
|
||||
"g5-1.jpg",
|
||||
"g5-2.jpg",
|
||||
"g5-3.jpg",
|
||||
"g5-4.jpg"
|
||||
],
|
||||
"cover": "g5-0.jpg",
|
||||
"real_price": 1559.9,
|
||||
"price": 6999,
|
||||
"isLowPrice": false,
|
||||
"discount": "",
|
||||
"sold": 473
|
||||
},
|
||||
{
|
||||
"name": "小米电视6 65\" OLED 65英寸",
|
||||
"cover": "g6-0.jpg",
|
||||
"imgs": [
|
||||
"g6-0.jpg",
|
||||
"g6-1.jpg",
|
||||
"g6-2.jpg",
|
||||
"g6-3.jpg",
|
||||
"g6-4.jpg"
|
||||
],
|
||||
"price": 6699,
|
||||
"real_price": 399,
|
||||
"isLowPrice": false,
|
||||
"discount": "",
|
||||
"sold": 863
|
||||
},
|
||||
{
|
||||
"name": "红白撞色条纹软糯针织上衣女2022年秋季新款甜美减龄短款毛衣开衫",
|
||||
"cover": "g1-0.jpg",
|
||||
"imgs": [
|
||||
"g1-0.jpg",
|
||||
"g1-1.jpg",
|
||||
"g1-2.jpg",
|
||||
"g1-3.jpg"
|
||||
],
|
||||
"isLowPrice": true,
|
||||
"discount": "满4减3",
|
||||
"sold": 134,
|
||||
"price": 39.9,
|
||||
"real_price": 9.9
|
||||
},
|
||||
{
|
||||
"name": "森马t恤男2023男士纯棉上衣白色情侣装凉感短袖打底衫纯色体恤潮",
|
||||
"imgs": [
|
||||
"g2-0.webp",
|
||||
"g2-1.webp",
|
||||
"g2-2.webp",
|
||||
"g2-3.webp"
|
||||
],
|
||||
"cover": "g2-0.webp",
|
||||
"real_price": 9.9,
|
||||
"price": 49.99,
|
||||
"isLowPrice": false,
|
||||
"discount": "满20减5",
|
||||
"sold": 3314
|
||||
},
|
||||
{
|
||||
"name": "ins潮牌长袖t恤男宽松纯色内搭上衣潮牌百搭秋冬季潮流帅气打底衫",
|
||||
"cover": "g3-0.jpg",
|
||||
"imgs": [
|
||||
"g3-0.jpg",
|
||||
"g3-1.jpg",
|
||||
"g3-2.jpg",
|
||||
"g3-3.jpg",
|
||||
"g3-4.jpg"
|
||||
],
|
||||
"real_price": 9.9,
|
||||
"price": 22.90,
|
||||
"isLowPrice": true,
|
||||
"discount": "满10减3",
|
||||
"sold": 129
|
||||
},
|
||||
{
|
||||
"name": "Redmi K60狠快狠强,狠旗舰!2023,第一台梦幻手机",
|
||||
"cover": "g4-0.png",
|
||||
"imgs": [
|
||||
"g4-0.png",
|
||||
"g4-1.png",
|
||||
"g4-2.png",
|
||||
"g4-3.png"
|
||||
],
|
||||
"real_price": 199.9,
|
||||
"price": 2999,
|
||||
"isLowPrice": true,
|
||||
"discount": "",
|
||||
"sold": 967
|
||||
},
|
||||
{
|
||||
"name": "小米笔记本Pro X 14",
|
||||
"imgs": [
|
||||
"g5-0.jpg",
|
||||
"g5-1.jpg",
|
||||
"g5-2.jpg",
|
||||
"g5-3.jpg",
|
||||
"g5-4.jpg"
|
||||
],
|
||||
"cover": "g5-0.jpg",
|
||||
"real_price": 1559.9,
|
||||
"price": 6999,
|
||||
"isLowPrice": false,
|
||||
"discount": "",
|
||||
"sold": 473
|
||||
},
|
||||
{
|
||||
"name": "小米电视6 65\" OLED 65英寸",
|
||||
"cover": "g6-0.jpg",
|
||||
"imgs": [
|
||||
"g6-0.jpg",
|
||||
"g6-1.jpg",
|
||||
"g6-2.jpg",
|
||||
"g6-3.jpg",
|
||||
"g6-4.jpg"
|
||||
],
|
||||
"price": 6699,
|
||||
"real_price": 399,
|
||||
"isLowPrice": false,
|
||||
"discount": "",
|
||||
"sold": 863
|
||||
},
|
||||
{
|
||||
"name": "红白撞色条纹软糯针织上衣女2022年秋季新款甜美减龄短款毛衣开衫",
|
||||
"cover": "g1-0.jpg",
|
||||
"imgs": [
|
||||
"g1-0.jpg",
|
||||
"g1-1.jpg",
|
||||
"g1-2.jpg",
|
||||
"g1-3.jpg"
|
||||
],
|
||||
"isLowPrice": true,
|
||||
"discount": "满4减3",
|
||||
"sold": 134,
|
||||
"price": 39.9,
|
||||
"real_price": 9.9
|
||||
},
|
||||
{
|
||||
"name": "森马t恤男2023男士纯棉上衣白色情侣装凉感短袖打底衫纯色体恤潮",
|
||||
"imgs": [
|
||||
"g2-0.webp",
|
||||
"g2-1.webp",
|
||||
"g2-2.webp",
|
||||
"g2-3.webp"
|
||||
],
|
||||
"cover": "g2-0.webp",
|
||||
"real_price": 9.9,
|
||||
"price": 49.99,
|
||||
"isLowPrice": false,
|
||||
"discount": "满20减5",
|
||||
"sold": 3314
|
||||
},
|
||||
{
|
||||
"name": "ins潮牌长袖t恤男宽松纯色内搭上衣潮牌百搭秋冬季潮流帅气打底衫",
|
||||
"cover": "g3-0.jpg",
|
||||
"imgs": [
|
||||
"g3-0.jpg",
|
||||
"g3-1.jpg",
|
||||
"g3-2.jpg",
|
||||
"g3-3.jpg",
|
||||
"g3-4.jpg"
|
||||
],
|
||||
"real_price": 9.9,
|
||||
"price": 22.90,
|
||||
"isLowPrice": true,
|
||||
"discount": "满10减3",
|
||||
"sold": 129
|
||||
},
|
||||
{
|
||||
"name": "Redmi K60狠快狠强,狠旗舰!2023,第一台梦幻手机",
|
||||
"cover": "g4-0.png",
|
||||
"imgs": [
|
||||
"g4-0.png",
|
||||
"g4-1.png",
|
||||
"g4-2.png",
|
||||
"g4-3.png"
|
||||
],
|
||||
"real_price": 199.9,
|
||||
"price": 2999,
|
||||
"isLowPrice": true,
|
||||
"discount": "",
|
||||
"sold": 967
|
||||
},
|
||||
{
|
||||
"name": "小米笔记本Pro X 14",
|
||||
"imgs": [
|
||||
"g5-0.jpg",
|
||||
"g5-1.jpg",
|
||||
"g5-2.jpg",
|
||||
"g5-3.jpg",
|
||||
"g5-4.jpg"
|
||||
],
|
||||
"cover": "g5-0.jpg",
|
||||
"real_price": 1559.9,
|
||||
"price": 6999,
|
||||
"isLowPrice": false,
|
||||
"discount": "",
|
||||
"sold": 473
|
||||
},
|
||||
{
|
||||
"name": "小米电视6 65\" OLED 65英寸",
|
||||
"cover": "g6-0.jpg",
|
||||
"imgs": [
|
||||
"g6-0.jpg",
|
||||
"g6-1.jpg",
|
||||
"g6-2.jpg",
|
||||
"g6-3.jpg",
|
||||
"g6-4.jpg"
|
||||
],
|
||||
"price": 6699,
|
||||
"real_price": 399,
|
||||
"isLowPrice": false,
|
||||
"discount": "",
|
||||
"sold": 863
|
||||
},
|
||||
{
|
||||
"name": "红白撞色条纹软糯针织上衣女2022年秋季新款甜美减龄短款毛衣开衫",
|
||||
"cover": "g1-0.jpg",
|
||||
"imgs": [
|
||||
"g1-0.jpg",
|
||||
"g1-1.jpg",
|
||||
"g1-2.jpg",
|
||||
"g1-3.jpg"
|
||||
],
|
||||
"isLowPrice": true,
|
||||
"discount": "满4减3",
|
||||
"sold": 134,
|
||||
"price": 39.9,
|
||||
"real_price": 9.9
|
||||
},
|
||||
{
|
||||
"name": "森马t恤男2023男士纯棉上衣白色情侣装凉感短袖打底衫纯色体恤潮",
|
||||
"imgs": [
|
||||
"g2-0.webp",
|
||||
"g2-1.webp",
|
||||
"g2-2.webp",
|
||||
"g2-3.webp"
|
||||
],
|
||||
"cover": "g2-0.webp",
|
||||
"real_price": 9.9,
|
||||
"price": 49.99,
|
||||
"isLowPrice": false,
|
||||
"discount": "满20减5",
|
||||
"sold": 3314
|
||||
},
|
||||
{
|
||||
"name": "ins潮牌长袖t恤男宽松纯色内搭上衣潮牌百搭秋冬季潮流帅气打底衫",
|
||||
"cover": "g3-0.jpg",
|
||||
"imgs": [
|
||||
"g3-0.jpg",
|
||||
"g3-1.jpg",
|
||||
"g3-2.jpg",
|
||||
"g3-3.jpg",
|
||||
"g3-4.jpg"
|
||||
],
|
||||
"real_price": 9.9,
|
||||
"price": 22.90,
|
||||
"isLowPrice": true,
|
||||
"discount": "满10减3",
|
||||
"sold": 129
|
||||
},
|
||||
{
|
||||
"name": "Redmi K60狠快狠强,狠旗舰!2023,第一台梦幻手机",
|
||||
"cover": "g4-0.png",
|
||||
"imgs": [
|
||||
"g4-0.png",
|
||||
"g4-1.png",
|
||||
"g4-2.png",
|
||||
"g4-3.png"
|
||||
],
|
||||
"real_price": 199.9,
|
||||
"price": 2999,
|
||||
"isLowPrice": true,
|
||||
"discount": "",
|
||||
"sold": 967
|
||||
},
|
||||
{
|
||||
"name": "小米笔记本Pro X 14",
|
||||
"imgs": [
|
||||
"g5-0.jpg",
|
||||
"g5-1.jpg",
|
||||
"g5-2.jpg",
|
||||
"g5-3.jpg",
|
||||
"g5-4.jpg"
|
||||
],
|
||||
"cover": "g5-0.jpg",
|
||||
"real_price": 1559.9,
|
||||
"price": 6999,
|
||||
"isLowPrice": false,
|
||||
"discount": "",
|
||||
"sold": 473
|
||||
}
|
||||
]
|
||||
BIN
public/docs/1.gif
Normal file
|
After Width: | Height: | Size: 2.9 MiB |
BIN
public/docs/2.gif
Normal file
|
After Width: | Height: | Size: 2.3 MiB |
BIN
public/docs/3.gif
Normal file
|
After Width: | Height: | Size: 3.9 MiB |
BIN
public/docs/4.gif
Normal file
|
After Width: | Height: | Size: 2.4 MiB |
BIN
public/docs/5.gif
Normal file
|
After Width: | Height: | Size: 3.2 MiB |
BIN
public/docs/img-1.jpg
Normal file
|
After Width: | Height: | Size: 160 KiB |
BIN
public/docs/img-2.jpg
Normal file
|
After Width: | Height: | Size: 236 KiB |
BIN
public/docs/img-3.jpg
Normal file
|
After Width: | Height: | Size: 179 KiB |
BIN
public/docs/img-4.jpg
Normal file
|
After Width: | Height: | Size: 102 KiB |
BIN
public/docs/img-5.jpg
Normal file
|
After Width: | Height: | Size: 200 KiB |
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 68 KiB |
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 231 KiB After Width: | Height: | Size: 231 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 63 KiB |
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 8.1 KiB |
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 8.9 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
BIN
public/images/icon/love.webp
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
@@ -61,12 +61,10 @@ export default {
|
||||
this.setVh()
|
||||
// 监听resize事件 视图大小发生变化就重新计算1vh的值
|
||||
window.addEventListener('resize', () => {
|
||||
// location.reload()
|
||||
location.reload()
|
||||
this.setVh()
|
||||
})
|
||||
// window.onresize = () => {
|
||||
//
|
||||
// }
|
||||
|
||||
try {
|
||||
navigator.control.gesture(false);
|
||||
} catch (e) {
|
||||
|
||||
@@ -3,6 +3,7 @@ import request from "../utils/request";
|
||||
export function userinfo(params, data) {
|
||||
return request({url: '/user/userinfo', method: 'get', params, data})
|
||||
}
|
||||
|
||||
export function userVideoList(params, data) {
|
||||
return request({url: '/user/video_list', method: 'get', params, data})
|
||||
}
|
||||
@@ -21,4 +22,8 @@ export function userCollect(params, data) {
|
||||
|
||||
export function recommendedPost(params, data) {
|
||||
return request({url: '/post/recommended', method: 'get', params, data})
|
||||
}
|
||||
|
||||
export function recommendedShop(params, data) {
|
||||
return request({url: '/shop/recommended', method: 'get', params, data})
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
export default {
|
||||
list: [
|
||||
{
|
||||
"name": "小米电视6 65\" OLED 65英寸",
|
||||
"cover": new URL('@/assets/img/goods/g6-0.jpg', import.meta.url).href,
|
||||
imgs:[
|
||||
new URL('../img/goods/g6-0.jpg', import.meta.url).href,
|
||||
new URL('../img/goods/g6-1.jpg', import.meta.url).href,
|
||||
new URL('../img/goods/g6-2.jpg', import.meta.url).href,
|
||||
new URL('../img/goods/g6-3.jpg', import.meta.url).href,
|
||||
new URL('../img/goods/g6-4.jpg', import.meta.url).href,
|
||||
],
|
||||
price: 6699,
|
||||
isLowPrice: false,
|
||||
discount: '',
|
||||
sold: 863,
|
||||
},
|
||||
{
|
||||
"name": "红白撞色条纹软糯针织上衣女2022年秋季新款甜美减龄短款毛衣开衫",
|
||||
"cover": new URL('../img/goods/g1-0.jpg', import.meta.url).href,
|
||||
imgs:[
|
||||
new URL('../img/goods/g1-0.jpg', import.meta.url).href,
|
||||
new URL('../img/goods/g1-1.jpg', import.meta.url).href,
|
||||
new URL('../img/goods/g1-2.jpg', import.meta.url).href,
|
||||
new URL('../img/goods/g1-3.jpg', import.meta.url).href,
|
||||
],
|
||||
isLowPrice: true,
|
||||
discount: '满4减3',
|
||||
sold: 134,
|
||||
price: 39.9,
|
||||
},
|
||||
{
|
||||
"name": "森马t恤男2023男士纯棉上衣白色情侣装凉感短袖打底衫纯色体恤潮",
|
||||
"cover": new URL('../img/goods/g2-0.webp', import.meta.url).href,
|
||||
price: 49.99,
|
||||
isLowPrice: false,
|
||||
discount: '满20减5',
|
||||
sold: 3314,
|
||||
},
|
||||
{
|
||||
"name": "ins潮牌长袖t恤男宽松纯色内搭上衣潮牌百搭秋冬季潮流帅气打底衫",
|
||||
"cover": new URL('../img/goods/g3-0.jpg', import.meta.url).href,
|
||||
price: 22.90,
|
||||
isLowPrice: true,
|
||||
discount: '满10减3',
|
||||
sold: 129,
|
||||
},
|
||||
{
|
||||
"name": "Redmi K60狠快狠强,狠旗舰!2023,第一台梦幻手机",
|
||||
"cover": new URL('../img/goods/g4-0.png', import.meta.url).href,
|
||||
price: 2999,
|
||||
isLowPrice: true,
|
||||
discount: '',
|
||||
sold: 967,
|
||||
},
|
||||
{
|
||||
"name": "小米笔记本Pro X 14",
|
||||
"cover": new URL('../img/goods/g5-0.jpg', import.meta.url).href,
|
||||
price: 6999,
|
||||
isLowPrice: false,
|
||||
discount: '',
|
||||
sold: 473,
|
||||
},
|
||||
]
|
||||
}
|
||||
@@ -404,6 +404,9 @@ export default {
|
||||
span {
|
||||
margin-right: 5rem;
|
||||
}
|
||||
svg{
|
||||
font-size: 10rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
<div class="DouyinCode" v-if="modelValue">
|
||||
<div class="content">
|
||||
<div class="video-poster">
|
||||
<img src="../assets/img/poster/1.jpg" class="poster">
|
||||
<img :src="_checkImgUrl(item.video.cover.url_list[0])" class="poster">
|
||||
</div>
|
||||
<div class="desc">
|
||||
<div class="left">
|
||||
<div class="user">@名字</div>
|
||||
<div class="title">#窃书不能算偷……窃书!……读书人的事,能算偷么?</div>
|
||||
<div class="user">@{{item.author.nickname}}</div>
|
||||
<div class="title">{{item.desc}}</div>
|
||||
</div>
|
||||
<img class="code" src="../assets/img/icon/components/video/douyin-code.jpg" alt="">
|
||||
</div>
|
||||
@@ -43,9 +43,12 @@
|
||||
</transition>
|
||||
</template>
|
||||
<script>
|
||||
import {_checkImgUrl} from "@/utils";
|
||||
|
||||
export default {
|
||||
name: "DouyinCode",
|
||||
props: {
|
||||
item:{},
|
||||
modelValue: false
|
||||
},
|
||||
data() {
|
||||
@@ -55,6 +58,7 @@ export default {
|
||||
created() {
|
||||
},
|
||||
methods: {
|
||||
_checkImgUrl,
|
||||
cancel() {
|
||||
this.$emit('update:modelValue', false)
|
||||
}
|
||||
@@ -87,16 +91,22 @@ export default {
|
||||
overflow: hidden;
|
||||
|
||||
.desc {
|
||||
margin-bottom: 20rem;
|
||||
display: flex;
|
||||
gap: 20rem;
|
||||
padding: 10rem;
|
||||
|
||||
.left {
|
||||
font-size: 18rem;
|
||||
|
||||
.title {
|
||||
margin-top: 10rem;
|
||||
font-size: 14rem;
|
||||
color: var(--second-text-color);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box; //作为弹性伸缩盒子模型显示。
|
||||
-webkit-box-orient: vertical; //设置伸缩盒子的子元素排列方式--从上到下垂直排列
|
||||
-webkit-line-clamp: 1; //显示的行
|
||||
}
|
||||
}
|
||||
.code {
|
||||
@@ -134,11 +144,11 @@ export default {
|
||||
|
||||
.shares {
|
||||
display: flex;
|
||||
padding-right: @space-width * 2;
|
||||
margin-bottom: @space-width;
|
||||
gap: 20rem;
|
||||
padding-left: 20rem;
|
||||
|
||||
.share-to {
|
||||
margin-left: 28rem;
|
||||
margin-bottom: @space-width;
|
||||
|
||||
img {
|
||||
width: @icon-width;
|
||||
@@ -159,6 +169,7 @@ export default {
|
||||
.cancel {
|
||||
font-size: 16rem;
|
||||
background: rgb(38, 38, 38);
|
||||
color: rgba(white,.8);
|
||||
padding: 15rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
</div>
|
||||
<div class="shares list">
|
||||
<template v-if="mode === 'video'">
|
||||
<div class="option" @click.stop="$no">
|
||||
<div class="option" @click.stop="closeShare($emit('ShareToFriend'))">
|
||||
<img class="avatar" src="../assets/img/icon/components/video/torichang.png" alt="">
|
||||
<span>转发</span>
|
||||
</div>
|
||||
@@ -51,7 +51,7 @@
|
||||
<img class="small" src="../assets/img/icon/components/video/warring.png" alt="">
|
||||
<span>举报</span>
|
||||
</div>
|
||||
<div class="option" @click.stop="$nav('/home/report',{mode:this.mode})">
|
||||
<div class="option" @click.stop="closeShare($emit('ShareToFriend'))">
|
||||
<Icon icon="ion:paper-plane"/>
|
||||
<span>私信朋友</span>
|
||||
</div>
|
||||
@@ -73,7 +73,7 @@
|
||||
<span>不感兴趣</span>
|
||||
</div>
|
||||
<div class="option" @click.stop="closeShare($emit('showDouyinCode'))">
|
||||
<img class="small" src="../assets/img/icon/components/video/dislike.png" alt="">
|
||||
<Icon icon="tabler:photo"/>
|
||||
<span>生成图片</span>
|
||||
</div>
|
||||
<div class="option" @click.stop="$no">
|
||||
@@ -133,7 +133,7 @@ import Check from "./Check";
|
||||
import FromBottomDialog from "./dialog/FromBottomDialog";
|
||||
import DouyinCode from "./DouyinCode";
|
||||
import {useBaseStore} from "@/store/pinia";
|
||||
import {$no} from "@/utils";
|
||||
import {$no, _copy} from "@/utils";
|
||||
|
||||
export default {
|
||||
name: "Share",
|
||||
@@ -144,6 +144,7 @@ export default {
|
||||
},
|
||||
props: {
|
||||
modelValue: false,
|
||||
item: {},
|
||||
videoId: {
|
||||
type: String,
|
||||
default: null
|
||||
@@ -170,8 +171,7 @@ export default {
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
}
|
||||
return {}
|
||||
},
|
||||
methods: {
|
||||
$no,
|
||||
@@ -180,6 +180,7 @@ export default {
|
||||
this.$showLoading()
|
||||
await this.$sleep(500)
|
||||
this.$hideLoading()
|
||||
_copy(this.item.share_info.share_link_desc + this.item.share_info.share_url)
|
||||
//TODO 抖音样式改了
|
||||
this.$notice('复制成功')
|
||||
},
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<Icon @click="$emit('back')" class="icon" icon="eva:arrow-ios-back-fill"/>
|
||||
<transition name="fade">
|
||||
<div class="float-user" v-if="state.floatFixed">
|
||||
<img v-lazy="Utils.$imgPreview(props.currentItem.author.avatar_168x168.url_list[0])" class="avatar"/>
|
||||
<img v-lazy="_checkImgUrl(props.currentItem.author.avatar_168x168.url_list[0])" class="avatar"/>
|
||||
<img v-if="!props.currentItem.author.follow_status" src="@/assets/img/icon/add-light.png" alt=""
|
||||
class="add">
|
||||
<span @click="followButton">{{ props.currentItem.author.follow_status ? '私信' : '关注' }}</span>
|
||||
@@ -99,7 +99,7 @@
|
||||
<div class="other">
|
||||
<div class="scroll-x" @touchmove="stop">
|
||||
<div class="item" v-for="item in props.currentItem.author.card_entries">
|
||||
<img :src="item.icon_dark.url_list[0]" alt="">
|
||||
<img :src="_checkImgUrl(item.icon_dark.url_list[0])" alt="">
|
||||
<div class="right">
|
||||
<div class="top">{{ item.title }}</div>
|
||||
<div class="bottom">{{ item.sub_title }}</div>
|
||||
|
||||
@@ -62,7 +62,7 @@ export default {
|
||||
},
|
||||
borderRadius: {
|
||||
type: String,
|
||||
default: '5rem 5rem 0 0'
|
||||
default: '15rem 15rem 0 0'
|
||||
},
|
||||
tag: {
|
||||
type: String,
|
||||
@@ -218,11 +218,11 @@ export default {
|
||||
}
|
||||
|
||||
.heng-gang {
|
||||
border-radius: 5rem 5rem 0 0;
|
||||
border-radius: 15rem 15rem 0 0;
|
||||
z-index: 3;
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
height: 20rem;
|
||||
height: 30rem;
|
||||
display: flex;
|
||||
transform: translateY(-24rem);
|
||||
justify-content: center;
|
||||
|
||||
@@ -20,57 +20,67 @@
|
||||
<p> 您的浏览器不支持 video 标签。</p>
|
||||
</video>
|
||||
<Icon icon="fluent:play-28-filled" class="pause-icon" v-if="!isPlaying"/>
|
||||
<div class="float" :style="{opacity: isUp?0:1}">
|
||||
<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"
|
||||
/>
|
||||
</template>
|
||||
<div v-if="isMy" class="comment-status">
|
||||
<div class="comment">
|
||||
<div class="type-comment">
|
||||
<img src="../../assets/img/icon/head-image.jpeg" alt="" class="avatar">
|
||||
<div class="right">
|
||||
<p>
|
||||
<span class="name">zzzzz</span>
|
||||
<span class="time">2020-01-20</span>
|
||||
</p>
|
||||
<p class="text">北京</p>
|
||||
</div>
|
||||
</div>
|
||||
<transition-group name="comment-status" tag="div" class="loveds">
|
||||
<div class="type-loved" :key="i" v-for="i in test">
|
||||
<div class="float">
|
||||
<template v-if="isLive">
|
||||
<div class="living">点击进入直播间</div>
|
||||
<ItemDesc
|
||||
:is-live="true"
|
||||
v-model:item="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"
|
||||
/>
|
||||
</template>
|
||||
<div v-if="isMy" class="comment-status">
|
||||
<div class="comment">
|
||||
<div class="type-comment">
|
||||
<img src="../../assets/img/icon/head-image.jpeg" alt="" class="avatar">
|
||||
<img src="../../assets/img/icon/love.svg" alt="" class="loved">
|
||||
<div class="right">
|
||||
<p>
|
||||
<span class="name">zzzzz</span>
|
||||
<span class="time">2020-01-20</span>
|
||||
</p>
|
||||
<p class="text">北京</p>
|
||||
</div>
|
||||
</div>
|
||||
</transition-group>
|
||||
<transition-group name="comment-status" tag="div" class="loveds">
|
||||
<div class="type-loved" :key="i" v-for="i in test">
|
||||
<img src="../../assets/img/icon/head-image.jpeg" alt="" class="avatar">
|
||||
<img src="../../assets/img/icon/love.svg" alt="" class="loved">
|
||||
</div>
|
||||
</transition-group>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress"
|
||||
:class="progressClass"
|
||||
ref="progress"
|
||||
@click="null"
|
||||
@touchstart="touchstart"
|
||||
@touchmove="touchmove"
|
||||
@touchend="touchend"
|
||||
>
|
||||
<div class="time" v-if="isMove">
|
||||
<span class="currentTime">{{ LUtils.$duration(currentTime) }}</span>
|
||||
<span class="duration"> / {{ LUtils.$duration(duration) }}</span>
|
||||
<div class="progress"
|
||||
:class="progressClass"
|
||||
ref="progress"
|
||||
@click="null"
|
||||
@touchstart="touchstart"
|
||||
@touchmove="touchmove"
|
||||
@touchend="touchend"
|
||||
>
|
||||
<div class="time" v-if="isMove">
|
||||
<span class="currentTime">{{ LUtils.$duration(currentTime) }}</span>
|
||||
<span class="duration"> / {{ LUtils.$duration(duration) }}</span>
|
||||
</div>
|
||||
<template v-if="duration > 15 || isMove || !isPlaying">
|
||||
<div class="bg"></div>
|
||||
<div class="progress-line" :style="durationStyle"></div>
|
||||
<div class="point"></div>
|
||||
</template>
|
||||
</div>
|
||||
<template v-if="duration > 15 || isMove || !isPlaying">
|
||||
<div class="bg"></div>
|
||||
<div class="progress-line" :style="durationStyle"></div>
|
||||
<div class="point"></div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -125,7 +135,7 @@ export default {
|
||||
return false
|
||||
}
|
||||
},
|
||||
isUp: {
|
||||
isLive: {
|
||||
type: Boolean,
|
||||
default: () => {
|
||||
return false
|
||||
@@ -290,29 +300,34 @@ export default {
|
||||
}
|
||||
},
|
||||
click({uniqueId, index, type}) {
|
||||
// console.log(this.position)
|
||||
if (
|
||||
this.position.uniqueId === uniqueId &&
|
||||
this.position.index === index
|
||||
) {
|
||||
if (type === EVENT_KEY.ITEM_TOGGLE) {
|
||||
if (this.status === SlideItemPlayStatus.Play) {
|
||||
this.pause()
|
||||
} else {
|
||||
this.play()
|
||||
if (this.isLive) {
|
||||
if (type === EVENT_KEY.ITEM_TOGGLE) {
|
||||
bus.emit(EVENT_KEY.NAV, {path: '/home/live', query: {id: this.item.id}})
|
||||
}
|
||||
} else {
|
||||
if (type === EVENT_KEY.ITEM_TOGGLE) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -713,4 +728,17 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
.living {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
font-size: 18rem;
|
||||
border-radius: 50rem;
|
||||
border: 1px solid #e0e0e0;
|
||||
padding: 15rem 20rem;
|
||||
line-height: 1;
|
||||
color: white;
|
||||
top: 70%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -22,6 +22,12 @@ const props = defineProps({
|
||||
return false
|
||||
}
|
||||
},
|
||||
isLive: {
|
||||
type: Boolean,
|
||||
default: () => {
|
||||
return false
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
const state = reactive({
|
||||
@@ -43,14 +49,15 @@ const state = reactive({
|
||||
<span>{{ props.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 }}</div>
|
||||
<div class="description mb1r">
|
||||
<div class="description">
|
||||
{{ props.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>
|
||||
</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>-->
|
||||
<!-- </div>-->
|
||||
</div>
|
||||
<div v-else class="comment-status">
|
||||
<div class="comment">
|
||||
@@ -113,6 +120,16 @@ const state = reactive({
|
||||
}
|
||||
}
|
||||
|
||||
.live{
|
||||
border-radius: 3rem;
|
||||
margin-bottom: 10rem;
|
||||
padding: 3rem 6rem;
|
||||
font-size: 11rem;
|
||||
display: inline-flex;
|
||||
background: var(--primary-btn-color);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.music {
|
||||
position: relative;
|
||||
display: flex;
|
||||
|
||||
@@ -203,15 +203,16 @@ function getInsEl(item, index, play = false) {
|
||||
}
|
||||
})
|
||||
return parent
|
||||
} else {
|
||||
const app = createApp({
|
||||
render() {
|
||||
return <SlideItem data-index={index}>{slideVNode}</SlideItem>
|
||||
}
|
||||
})
|
||||
const ins = app.mount(parent)
|
||||
appInsMap.set(index, app)
|
||||
return ins.$el
|
||||
}
|
||||
const app = createApp({
|
||||
render() {
|
||||
return <SlideItem data-index={index}>{slideVNode}</SlideItem>
|
||||
}
|
||||
})
|
||||
const ins = app.mount(parent)
|
||||
appInsMap.set(index, app)
|
||||
return ins.$el
|
||||
}
|
||||
|
||||
function touchStart(e) {
|
||||
|
||||
@@ -78,7 +78,7 @@ async function fetchData() {
|
||||
export async function startMock() {
|
||||
mock.onGet(/video\/recommended/).reply(async (config) => {
|
||||
let page = getPage2(config.params)
|
||||
console.log('allRecommendVideos', cloneDeep(allRecommendVideos.length),page)
|
||||
console.log('allRecommendVideos', cloneDeep(allRecommendVideos.length), page)
|
||||
return [200, {
|
||||
data: {
|
||||
total: 844,
|
||||
@@ -143,7 +143,7 @@ export async function startMock() {
|
||||
if (!userVideos.length) {
|
||||
// let r = await fetch(BASE_URL + '/data/user-71158770.json')
|
||||
// let r = await fetch(BASE_URL + '/data/user-8357999.json')
|
||||
let r = await fetch(BASE_URL + '/data/user-12345xiaolaohu.json')
|
||||
let r = await fetch(BASE_URL + '/data/user_video_list/user-12345xiaolaohu.json')
|
||||
let list = await r.json()
|
||||
const baseStore = useBaseStore()
|
||||
let userList = cloneDeep(baseStore.users)
|
||||
@@ -243,5 +243,18 @@ export async function startMock() {
|
||||
}]
|
||||
})
|
||||
|
||||
mock.onGet(/shop\/recommended/).reply(async (config) => {
|
||||
let page = getPage2(config.params)
|
||||
|
||||
let r2 = await fetch(BASE_URL + '/data/goods.json')
|
||||
let v = await r2.json()
|
||||
return [200, {
|
||||
data: {
|
||||
total: v.length,
|
||||
list: v.slice(page.offset, page.limit)
|
||||
}, code: 200
|
||||
}]
|
||||
})
|
||||
|
||||
setTimeout(fetchData, 1000)
|
||||
}
|
||||
@@ -1,16 +1,30 @@
|
||||
<template>
|
||||
<div class="LivePage" ref="page">
|
||||
<div class="live-wrapper">
|
||||
<img src="../../assets/img/poster/1.jpg" alt="">
|
||||
<video
|
||||
src="https://www.douyin.com/aweme/v1/play/?video_id=v0d00fg10000cj1lq4jc77u0ng6s1gt0&line=0&file_id=bed51c00899b458cbc5d8280147c22a1&sign=7749aec7bd62a3760065f60e40fc1867&is_play_url=1&source=PackSourceEnum_PUBLISH"
|
||||
poster="/images/jwWCPZVTIA4IKM-8WipLF.png"
|
||||
preload=""
|
||||
loop=""
|
||||
muted
|
||||
x5-video-player-type="h5-page"
|
||||
x5-video-player-fullscreen="false"
|
||||
webkit-playsinline="true"
|
||||
x5-playsinline="true"
|
||||
playsinline="true"
|
||||
fullscreen="false"
|
||||
autoplay="">
|
||||
<p> 您的浏览器不支持 video 标签。</p>
|
||||
</video>
|
||||
</div>
|
||||
<div class="float">
|
||||
<div class="top">
|
||||
<div class="left">
|
||||
<div class="liver">
|
||||
<img class="avatar" src="../../assets/img/icon/avatar/10.png" alt="">
|
||||
<img class="avatar" :src="_checkImgUrl(userinfo.avatar_168x168.url_list[0])" alt="">
|
||||
<div class="desc">
|
||||
<div class="desc-wrapper">
|
||||
<div class="name">大司马大司马大司马</div>
|
||||
<div class="name">{{ userinfo.nickname }}</div>
|
||||
<div class="count">2万本场点赞</div>
|
||||
</div>
|
||||
<div class="follow-btn">关注</div>
|
||||
@@ -58,8 +72,8 @@
|
||||
<span>30</span>
|
||||
</div>
|
||||
</div>
|
||||
<span class="name">嘻嘻哈哈</span>
|
||||
<span class="text">{{ i }}</span>
|
||||
<span class="name">{{ i.name}}</span>
|
||||
<span class="text">{{ i.text }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -85,8 +99,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<base-button @click="sendComment">点击</base-button>
|
||||
</div>
|
||||
</template>
|
||||
@@ -94,6 +106,10 @@
|
||||
import BaseButton from "../../components/BaseButton";
|
||||
import Dom from "../../utils/dom";
|
||||
import {nextTick} from "vue";
|
||||
import {mapState} from "pinia";
|
||||
import {useBaseStore} from "@/store/pinia";
|
||||
import {_checkImgUrl, random} from "@/utils";
|
||||
import Mock from "mockjs";
|
||||
|
||||
export default {
|
||||
name: "LivePage",
|
||||
@@ -101,23 +117,25 @@ export default {
|
||||
props: {},
|
||||
data() {
|
||||
return {
|
||||
timer1: -1,
|
||||
timer2: -1,
|
||||
timer3: -1,
|
||||
isFollowed: false,
|
||||
list: [
|
||||
'asdfasdf',
|
||||
'asdfasdf',
|
||||
'asdfasdf',
|
||||
],
|
||||
list: [],
|
||||
barrage: [],
|
||||
barrageTemplate: () => {
|
||||
let name = Mock.mock('@cname')
|
||||
let a = Mock.mock('@csentence')
|
||||
return `
|
||||
<div class="barrage">
|
||||
<div class="type">管理</div>
|
||||
<div class="text">感谢老铁送的火箭</div>
|
||||
<div class="type">${name}</div>
|
||||
<div class="text">${a}</div>
|
||||
</div>
|
||||
`
|
||||
},
|
||||
userJoinedTemplate: () => {
|
||||
let src = new URL('../../assets/img/icon/home/level.webp')
|
||||
let src = '/images/icon/love.webp'
|
||||
let name = Mock.mock('@cname')
|
||||
return `
|
||||
<div class="user-joined">
|
||||
<div class="level">
|
||||
@@ -126,23 +144,36 @@ export default {
|
||||
<span>30</span>
|
||||
</div>
|
||||
</div>
|
||||
<span class="name">嘻嘻哈哈</span>
|
||||
<span class="name">${name}</span>
|
||||
<span class="text">加入了直播间</span>
|
||||
</div>
|
||||
`
|
||||
},
|
||||
sendGiftTemplate: () => {
|
||||
let avatar = new URL('../../assets/img/icon/avatar/3.png')
|
||||
let gift = new URL('../../assets/img/icon/home/love.webp')
|
||||
let avatarList = [
|
||||
'/images/EPsQ7u4sNnrHC-ix-a9yQ.png',
|
||||
'/images/Xex2IhY-Zm338cNlcGuNW.png',
|
||||
'/images/gddHyRZrdk0Em3RRgVa9g.png',
|
||||
'/images/LJ-8p2jF3HydBD5j28PgQ.png',
|
||||
'/images/KwJ9N7yFjYylfwYeThWjx.png',
|
||||
'/images/EKkC06GI4yXC2mNHMrm46.png',
|
||||
'/images/rlkpmpGPdhYZRJl3J4Xl7.png',
|
||||
'/images/Ge4mMWQoICdpyTyixk3Sf.png',
|
||||
]
|
||||
let avatar = avatarList[random(0, avatarList.length - 1)]
|
||||
let gift = '/images/icon/love.webp'
|
||||
let name = Mock.mock('@cname')
|
||||
let name2 = Mock.mock('@cname')
|
||||
let num = Mock.mock('@integer(60,400)')
|
||||
return `
|
||||
<div class="send-gift">
|
||||
<div class="left">
|
||||
<img src="${avatar}" alt="" class="avatar">
|
||||
<div class="desc">
|
||||
<div class="name">哈哈哈哈哈哈哈哈哈</div>
|
||||
<div class="name">${name}</div>
|
||||
<div class="sendto">
|
||||
<span class="send">送</span>
|
||||
<span class="to">嘻嘻嘻嘻嘻嘻嘻嘻嘻嘻嘻嘻</span>
|
||||
<span class="to">${name2}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gift-wrapper">
|
||||
@@ -150,7 +181,7 @@ export default {
|
||||
</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
x339
|
||||
x${num}
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
@@ -158,25 +189,33 @@ export default {
|
||||
page: null,
|
||||
}
|
||||
},
|
||||
computed: {},
|
||||
computed: {
|
||||
...mapState(useBaseStore, ['friends', 'userinfo']),
|
||||
},
|
||||
created() {
|
||||
},
|
||||
mounted() {
|
||||
this.page = this.$refs.page
|
||||
// setInterval(async () => {
|
||||
// this.sendGift()
|
||||
// await this.$sleep(300)
|
||||
// this.sendGift()
|
||||
// this.joinUser()
|
||||
// }, 3000)
|
||||
// setInterval(async () => {
|
||||
// this.sendBarrage()
|
||||
// }, 5100)
|
||||
// setInterval(async () => {
|
||||
// this.sendComment()
|
||||
// }, 500)
|
||||
this.timer1 = setInterval(async () => {
|
||||
this.sendGift()
|
||||
await this.$sleep(300)
|
||||
this.sendGift()
|
||||
this.joinUser()
|
||||
}, 1000)
|
||||
this.timer2 = setInterval(async () => {
|
||||
this.sendBarrage()
|
||||
}, 1500)
|
||||
this.timer3 = setInterval(async () => {
|
||||
this.sendComment()
|
||||
}, 700)
|
||||
},
|
||||
unmounted() {
|
||||
clearInterval(this.timer1)
|
||||
clearInterval(this.timer2)
|
||||
clearInterval(this.timer3)
|
||||
},
|
||||
methods: {
|
||||
_checkImgUrl,
|
||||
sendGift() {
|
||||
let page = new Dom(this.page)
|
||||
let sendGift = new Dom().create(this.sendGiftTemplate())
|
||||
@@ -188,6 +227,10 @@ export default {
|
||||
if (oldSendGift.els.length !== 0) {
|
||||
top = sendGift.removePx(oldSendGift.css('top')) - 70
|
||||
}
|
||||
if (top < 100) {
|
||||
top = document.body.clientHeight * .6
|
||||
}
|
||||
console.log('top', top)
|
||||
sendGift.css('top', top)
|
||||
page.append(sendGift)
|
||||
},
|
||||
@@ -210,11 +253,17 @@ export default {
|
||||
if (oldBarrages.els.length !== 0) {
|
||||
top = barrage.removePx(oldBarrages.css('top')) + 20
|
||||
}
|
||||
if (top > document.body.clientHeight * .5) {
|
||||
top = document.body.clientHeight * .35
|
||||
}
|
||||
barrage.css('top', top)
|
||||
page.append(barrage)
|
||||
},
|
||||
sendComment() {
|
||||
this.list.push('评论评论评论评论评论评论评论评论评论评论' + this.list.length)
|
||||
this.list.push({
|
||||
name: Mock.mock('@cname'),
|
||||
text: Mock.mock('@csentence')
|
||||
})
|
||||
nextTick(() => {
|
||||
let comments = this.$refs['comments']
|
||||
comments.scrollTo({top: comments.scrollHeight - comments.clientHeight, behavior: 'smooth'})
|
||||
@@ -272,6 +321,8 @@ export default {
|
||||
.avatar {
|
||||
margin-right: 5rem;
|
||||
width: 40rem;
|
||||
height: 40rem;
|
||||
object-fit: cover;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
@@ -417,6 +468,14 @@ export default {
|
||||
width: 100vw;
|
||||
height: calc(var(--vh, 1vh) * 100);
|
||||
background: black;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
video {
|
||||
width: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 100vw;
|
||||
|
||||
@@ -146,6 +146,7 @@
|
||||
ref="share"
|
||||
page-id="home-index"
|
||||
@dislike="dislike"
|
||||
:item="state.currentItem"
|
||||
:videoId="state.recommendList[state.itemIndex]?.id"
|
||||
:canDownload="state.recommendList[state.itemIndex]?.canDownload"
|
||||
@play-feedback="state.showPlayFeedback = true"
|
||||
@@ -156,7 +157,9 @@
|
||||
|
||||
<PlayFeedback v-model="state.showPlayFeedback"/>
|
||||
|
||||
<DouyinCode v-model="state.showDouyinCode"/>
|
||||
<DouyinCode
|
||||
:item="state.currentItem"
|
||||
v-model="state.showDouyinCode"/>
|
||||
|
||||
<ShareTo v-model:type="state.shareType"
|
||||
:videoId="state.recommendList[state.itemIndex]?.id"
|
||||
@@ -195,7 +198,7 @@ import SlideItem from '@/components/slide/SlideItem.vue'
|
||||
import Comment from "../../components/Comment.vue";
|
||||
import Share from "../../components/Share.vue";
|
||||
import IndicatorHome from "./components/IndicatorHome.vue";
|
||||
import {onMounted, onUnmounted, reactive} from "vue";
|
||||
import {onActivated, onDeactivated, onMounted, onUnmounted, reactive} from "vue";
|
||||
import bus, {EVENT_KEY} from "../../utils/bus";
|
||||
import {useNav} from "@/utils/hooks/useNav";
|
||||
import PlayFeedback from "@/pages/home/components/PlayFeedback.vue";
|
||||
@@ -221,6 +224,7 @@ const nav = useNav()
|
||||
const baseStore = useBaseStore()
|
||||
|
||||
const state = reactive({
|
||||
active: true,
|
||||
baseIndex: 1,
|
||||
navIndex: 4,
|
||||
test: '',
|
||||
@@ -253,6 +257,7 @@ function delayShowDialog(cb) {
|
||||
}
|
||||
|
||||
function setCurrentItem(item) {
|
||||
if (!state.active) return
|
||||
// console.log('sss',item,state.baseIndex)
|
||||
if (state.baseIndex !== 1) return
|
||||
if (state.currentItem.author.uid !== item.author.uid) {
|
||||
@@ -266,21 +271,34 @@ function setCurrentItem(item) {
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
bus.on(EVENT_KEY.ENTER_FULLSCREEN, (e) => state.fullScreen = true)
|
||||
bus.on(EVENT_KEY.EXIT_FULLSCREEN, (e) => state.fullScreen = false)
|
||||
bus.on(EVENT_KEY.ENTER_FULLSCREEN, (e) => {
|
||||
if (!state.active) return
|
||||
state.fullScreen = true
|
||||
})
|
||||
bus.on(EVENT_KEY.EXIT_FULLSCREEN, (e) => {
|
||||
if (!state.active) return
|
||||
state.fullScreen = false
|
||||
})
|
||||
bus.on(EVENT_KEY.OPEN_COMMENTS, (e) => {
|
||||
if (!state.active) return
|
||||
bus.emit(EVENT_KEY.ENTER_FULLSCREEN)
|
||||
state.commentVisible = true
|
||||
})
|
||||
bus.on(EVENT_KEY.CLOSE_COMMENTS, (e) => {
|
||||
if (!state.active) return
|
||||
bus.emit(EVENT_KEY.EXIT_FULLSCREEN)
|
||||
state.commentVisible = false
|
||||
})
|
||||
bus.on(EVENT_KEY.SHOW_SHARE, (e) => {
|
||||
if (!state.active) return
|
||||
state.isSharing = true
|
||||
})
|
||||
bus.on(EVENT_KEY.NAV, ({path, query}) => nav(path, query))
|
||||
bus.on(EVENT_KEY.NAV, ({path, query}) => {
|
||||
if (!state.active) return
|
||||
nav(path, query)
|
||||
})
|
||||
bus.on(EVENT_KEY.GO_USERINFO, () => {
|
||||
if (!state.active) return
|
||||
state.baseIndex = 2
|
||||
})
|
||||
bus.on(EVENT_KEY.CURRENT_ITEM, setCurrentItem)
|
||||
@@ -290,6 +308,15 @@ onUnmounted(() => {
|
||||
bus.offAll()
|
||||
})
|
||||
|
||||
onActivated(() => {
|
||||
state.active = true
|
||||
})
|
||||
|
||||
onDeactivated(() => {
|
||||
state.active = false
|
||||
})
|
||||
|
||||
|
||||
function closeComments() {
|
||||
bus.emit(EVENT_KEY.CLOSE_COMMENTS)
|
||||
}
|
||||
|
||||
@@ -1,228 +0,0 @@
|
||||
<script setup>
|
||||
|
||||
import {onMounted, onUnmounted, reactive, watch} from "vue";
|
||||
import {_checkImgUrl, _duration, _formatNumber} from "@/utils";
|
||||
import {recommendedVideo} from "@/api/videos";
|
||||
import {useBaseStore} from "@/store/pinia";
|
||||
|
||||
const baseStore = useBaseStore()
|
||||
|
||||
const props = defineProps({
|
||||
active: Boolean
|
||||
})
|
||||
|
||||
const p = {
|
||||
onShowComments() {
|
||||
console.log('onShowComments')
|
||||
}
|
||||
}
|
||||
|
||||
const state = reactive({
|
||||
index: 0,
|
||||
list: [],
|
||||
totalSize: 0,
|
||||
pageSize: 10,
|
||||
pageNo: 0,
|
||||
})
|
||||
|
||||
function loadMore() {
|
||||
if (!baseStore.loading) {
|
||||
state.pageNo++
|
||||
getData()
|
||||
}
|
||||
}
|
||||
|
||||
async function getData(refresh = false) {
|
||||
if (baseStore.loading) return
|
||||
baseStore.loading = true
|
||||
let res = await recommendedVideo({pageNo: refresh ? 0 : state.pageNo, pageSize: state.pageSize})
|
||||
console.log('getSlide4Data-', 'refresh', refresh, res)
|
||||
baseStore.loading = false
|
||||
if (res.code === 200) {
|
||||
state.totalSize = res.data.total
|
||||
if (refresh) {
|
||||
state.list = []
|
||||
}
|
||||
state.list = state.list.concat(res.data.list)
|
||||
} else {
|
||||
state.pageNo--
|
||||
}
|
||||
}
|
||||
|
||||
watch(() => props.active, n => {
|
||||
if (!state.list.length && n) {
|
||||
baseStore.loading = false
|
||||
getData()
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
})
|
||||
onUnmounted(() => {
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<div class="page">
|
||||
<div class="item"
|
||||
:class="[
|
||||
i % 5 === 0 && 'big',
|
||||
i % 5 === 0 ? '' : (i % 2 === 1 && 'l'),
|
||||
i % 5 === 0 ? '' : (i % 2 === 0 && 'r'),
|
||||
]"
|
||||
v-for="(item,i) in state.list">
|
||||
<video
|
||||
controls
|
||||
:poster="_checkImgUrl(item.video.cover.url_list[0])"
|
||||
:src="item.video.play_addr.url_list[0]"
|
||||
></video>
|
||||
<img v-lazy="_checkImgUrl(item.video.cover.url_list[0])" alt="" class="poster">
|
||||
<div class="duration">{{ _duration(item.duration / 1000) }}</div>
|
||||
<div class="title">
|
||||
{{ item.desc }}
|
||||
</div>
|
||||
<div class="bottom">
|
||||
<div class="l">
|
||||
<img v-lazy="_checkImgUrl(item.author.avatar_168x168.url_list[0])" alt="" class="avatar">
|
||||
<div class="name">{{ item.author.nickname }}</div>
|
||||
</div>
|
||||
<div class="r">
|
||||
<Icon icon="icon-park-outline:like"/>
|
||||
<div class="num">{{ _formatNumber(item.statistics.digg_count) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="less">
|
||||
.page {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
row-gap: 15rem;
|
||||
height: calc(var(--vh, 1vh) * 100 - var(--common-header-height) - var(--footer-height));
|
||||
margin-top: var(--common-header-height);
|
||||
overflow: auto;
|
||||
box-sizing: border-box;
|
||||
|
||||
.item {
|
||||
margin: 0 10rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8rem;
|
||||
position: relative;
|
||||
|
||||
.poster {
|
||||
border-radius: 12rem;
|
||||
width: 100%;
|
||||
height: 140rem;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
video {
|
||||
display: none;
|
||||
height: 220rem;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.title {
|
||||
height: 36rem;
|
||||
color: white;
|
||||
font-size: 14rem;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box; //作为弹性伸缩盒子模型显示。
|
||||
-webkit-box-orient: vertical; //设置伸缩盒子的子元素排列方式--从上到下垂直排列
|
||||
-webkit-line-clamp: 2; //显示的行
|
||||
}
|
||||
|
||||
.f {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 5rem;
|
||||
}
|
||||
|
||||
.duration {
|
||||
color: white;
|
||||
position: absolute;
|
||||
bottom: 80rem;
|
||||
right: 10rem;
|
||||
font-size: 13rem;
|
||||
}
|
||||
|
||||
.bottom {
|
||||
color: gray;
|
||||
.f;
|
||||
font-size: 13rem;
|
||||
|
||||
.l {
|
||||
.f;
|
||||
justify-content: flex-start;
|
||||
|
||||
.name {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box; //作为弹性伸缩盒子模型显示。
|
||||
-webkit-box-orient: vertical; //设置伸缩盒子的子元素排列方式--从上到下垂直排列
|
||||
-webkit-line-clamp: 1; //显示的行
|
||||
}
|
||||
|
||||
.avatar {
|
||||
@w: 20rem;
|
||||
width: @w;
|
||||
height: @w;
|
||||
object-fit: cover;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.r {
|
||||
word-break: keep-all;
|
||||
.f;
|
||||
|
||||
svg {
|
||||
font-size: 16rem;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
&.big {
|
||||
grid-column-start: 1;
|
||||
grid-column-end: 3;
|
||||
margin: 0;
|
||||
|
||||
.duration {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.poster {
|
||||
display: none;
|
||||
}
|
||||
|
||||
video {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.title {
|
||||
height: unset;
|
||||
-webkit-line-clamp: 1;
|
||||
}
|
||||
|
||||
.title, .bottom {
|
||||
padding: 0 10rem;
|
||||
}
|
||||
}
|
||||
|
||||
&.l {
|
||||
margin-right: 5rem;
|
||||
}
|
||||
|
||||
&.r {
|
||||
margin-left: 5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -4,17 +4,18 @@
|
||||
:class="state.subTypeIsTop?'top':''"
|
||||
ref="subTypeRef">
|
||||
<div class="card" @touchmove.capture="stop">
|
||||
<div class="nav-item" v-for="i in 2">
|
||||
<img src="@/assets/img/icon/msg-icon9.webp" alt="">
|
||||
<span>美食美食美食美食美食美食美食</span>
|
||||
<div class="nav-item" v-for="i in store.users">
|
||||
<img :src="_checkImgUrl(i.avatar_168x168.url_list[0])" alt="">
|
||||
<span>{{ i.nickname }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sub-type-notice"
|
||||
v-if="state.subType===-1 && !state.subTypeVisible"
|
||||
@click="showSubType">1个直播
|
||||
@click.stop="showSubType">{{store.users.length}}个直播
|
||||
</div>
|
||||
<SlideList
|
||||
:cbs="{isLive:true}"
|
||||
:active="props.active"
|
||||
:style="{background: 'black',marginTop:state.subTypeVisible?state.subTypeHeight:0}"
|
||||
:api="recommendedVideo"
|
||||
@@ -27,10 +28,12 @@
|
||||
import SlideItem from '@/components/slide/SlideItem.vue'
|
||||
import {onMounted, onUnmounted, reactive, ref} from "vue";
|
||||
import bus, {EVENT_KEY} from "@/utils/bus";
|
||||
import Utils from "@/utils";
|
||||
import Utils, {_checkImgUrl} from "@/utils";
|
||||
import SlideList from './SlideList.vue';
|
||||
import {recommendedVideo} from "@/api/videos";
|
||||
import {useBaseStore} from "@/store/pinia";
|
||||
|
||||
const store = useBaseStore()
|
||||
const props = defineProps({
|
||||
active: {
|
||||
type: Boolean,
|
||||
@@ -104,6 +107,8 @@ onUnmounted(() => {
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
overflow: auto;
|
||||
gap: 10rem;
|
||||
padding-left: 20rem;
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
@@ -126,7 +131,7 @@ onUnmounted(() => {
|
||||
img {
|
||||
width: @width;
|
||||
height: @width;
|
||||
margin-bottom: 5rem;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +62,30 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 消息-->
|
||||
<div class="message" @click="$nav('/message/chat')">
|
||||
<div class="avatar on-line">
|
||||
<img src="../../assets/img/icon/avatar/2.png" alt="" class="head-image">
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="left">
|
||||
<div class="name">
|
||||
<span>{{ userinfo.nickname }}</span>
|
||||
</div>
|
||||
<div class="detail">
|
||||
哈哈哈哈哈哈
|
||||
<div class="point"></div>
|
||||
10-10
|
||||
</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<!-- <div class="not-read"></div>-->
|
||||
<!-- <img class="camera" src="../../assets/img/icon/close-white.png" alt="">-->
|
||||
<!-- <img class="arrow" src="../../assets/img/icon/close-white.png" alt="">-->
|
||||
<div class="badge">12</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 抖音小助手-->
|
||||
<div class="message" @click="$nav('/message/douyin-helper')">
|
||||
<div class="avatar">
|
||||
@@ -195,30 +219,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 消息-->
|
||||
<div class="message" @click="$nav('/message/chat')">
|
||||
<div class="avatar on-line">
|
||||
<img src="../../assets/img/icon/avatar/2.png" alt="" class="head-image">
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="left">
|
||||
<div class="name">
|
||||
<span>{{ userinfo.nickname }}</span>
|
||||
</div>
|
||||
<div class="detail">
|
||||
哈哈哈哈哈哈
|
||||
<div class="point"></div>
|
||||
10-10
|
||||
</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<!-- <div class="not-read"></div>-->
|
||||
<!-- <img class="camera" src="../../assets/img/icon/close-white.png" alt="">-->
|
||||
<!-- <img class="arrow" src="../../assets/img/icon/close-white.png" alt="">-->
|
||||
<div class="badge">12</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<NoMore/>
|
||||
|
||||
|
||||
@@ -67,6 +67,7 @@ export default {
|
||||
.avatar {
|
||||
margin-top: 55rem;
|
||||
width: 55rem;
|
||||
height: 55rem;
|
||||
border-radius: 50%;
|
||||
margin-bottom: 20rem;
|
||||
}
|
||||
|
||||
@@ -219,36 +219,7 @@ export default {
|
||||
avatar: '../../assets/img/icon/head-image.jpg'
|
||||
}
|
||||
},
|
||||
{
|
||||
type: MESSAGE_TYPE.RED_PACKET,
|
||||
state: AUDIO_STATE.NORMAL,
|
||||
mode: RED_PACKET_MODE.MULTIPLE,
|
||||
data: {
|
||||
money: 5.11,
|
||||
title: '大吉大利',
|
||||
state: '未领取'
|
||||
},
|
||||
time: '2021-01-02 21:21',
|
||||
user: {
|
||||
id: '2739632844317827',
|
||||
avatar: '../../assets/img/icon/head-image.jpg'
|
||||
}
|
||||
},
|
||||
{
|
||||
type: MESSAGE_TYPE.RED_PACKET,
|
||||
state: AUDIO_STATE.NORMAL,
|
||||
mode: RED_PACKET_MODE.SINGLE,
|
||||
data: {
|
||||
money: 5.11,
|
||||
title: '大吉大利',
|
||||
state: '已过期'
|
||||
},
|
||||
time: '2021-01-02 21:21',
|
||||
user: {
|
||||
id: 1,
|
||||
avatar: '../../assets/img/icon/head-image.jpg'
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
type: MESSAGE_TYPE.MEME,
|
||||
state: AUDIO_STATE.NORMAL,
|
||||
@@ -441,6 +412,36 @@ export default {
|
||||
avatar: '../../../assets/img/icon/head-image.jpg'
|
||||
}
|
||||
},
|
||||
{
|
||||
type: MESSAGE_TYPE.RED_PACKET,
|
||||
state: AUDIO_STATE.NORMAL,
|
||||
mode: RED_PACKET_MODE.MULTIPLE,
|
||||
data: {
|
||||
money: 5.11,
|
||||
title: '大吉大利',
|
||||
state: '未领取'
|
||||
},
|
||||
time: '2021-01-02 21:21',
|
||||
user: {
|
||||
id: '2739632844317827',
|
||||
avatar: '../../assets/img/icon/head-image.jpg'
|
||||
}
|
||||
},
|
||||
{
|
||||
type: MESSAGE_TYPE.RED_PACKET,
|
||||
state: AUDIO_STATE.NORMAL,
|
||||
mode: RED_PACKET_MODE.SINGLE,
|
||||
data: {
|
||||
money: 5.11,
|
||||
title: '大吉大利',
|
||||
state: '已过期'
|
||||
},
|
||||
time: '2021-01-02 21:21',
|
||||
user: {
|
||||
id: 1,
|
||||
avatar: '../../assets/img/icon/head-image.jpg'
|
||||
}
|
||||
},
|
||||
],
|
||||
typing: false,
|
||||
loading: false,
|
||||
@@ -466,15 +467,19 @@ export default {
|
||||
created() {
|
||||
},
|
||||
mounted() {
|
||||
$('img').on('load', this.scrollBottom)
|
||||
this.scrollBottom()
|
||||
},
|
||||
unmounted() {
|
||||
$('img').off('load', this.scrollBottom)
|
||||
},
|
||||
methods: {
|
||||
_checkImgUrl,
|
||||
scrollBottom() {
|
||||
nextTick(() => {
|
||||
let wrapper = this.$refs.msgWrapper
|
||||
console.log('wrapper.clientHeight', wrapper.clientHeight)
|
||||
console.log('wrapper.scrollHeight', wrapper.scrollHeight)
|
||||
// console.log('wrapper.clientHeight', wrapper.clientHeight)
|
||||
// console.log('wrapper.scrollHeight', wrapper.scrollHeight)
|
||||
wrapper.scrollTo({top: wrapper.scrollHeight - wrapper.clientHeight})
|
||||
})
|
||||
|
||||
@@ -804,6 +809,7 @@ export default {
|
||||
.avatar {
|
||||
margin-top: 60rem;
|
||||
width: 55rem;
|
||||
height: 55rem;
|
||||
border-radius: 50%;
|
||||
margin-bottom: 20rem;
|
||||
}
|
||||
|
||||
@@ -1,360 +0,0 @@
|
||||
<template>
|
||||
<div class="goods-detail base-page1">
|
||||
<header>
|
||||
<Icon
|
||||
@click="$back()"
|
||||
icon="material-symbols-light:arrow-back-ios-new"/>
|
||||
<div class="option" @click="nav('/home/search')">
|
||||
<Icon icon="jam:search"/>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="slide-imgs">
|
||||
<SlideHorizontal v-model:index="state.index">
|
||||
<SlideItem v-for="item in state.detail.note_card?.image_list">
|
||||
<img :src="_checkImgUrl(item.info_list?.[0]?.url)" alt="">
|
||||
</SlideItem>
|
||||
</SlideHorizontal>
|
||||
|
||||
<div class="indicator-bar" v-if="state.detail.note_card?.image_list?.length > 1">
|
||||
<div class="indicator"
|
||||
:class="[i <= state.index+1 && 'active']"
|
||||
v-for="i in state.detail.note_card?.image_list?.length"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
<div class="shop">
|
||||
<header>
|
||||
<img class="avatar" :src="_checkImgUrl(state.detail.note_card?.user?.avatar)"/>
|
||||
<div class="right">
|
||||
<div class="name">{{ state.detail.note_card.user.nick_name }}</div>
|
||||
<div class="r">关注</div>
|
||||
</div>
|
||||
</header>
|
||||
<div class="desc">
|
||||
{{ state.detail.note_card?.display_title }}
|
||||
</div>
|
||||
<div class="date">{{ state.detail.note_card.createTime }}</div>
|
||||
</div>
|
||||
|
||||
<div class="card comments">
|
||||
<header>
|
||||
<span class="l">评论 {{ state.detail.note_card.comment_list.length }}</span>
|
||||
<div class="r">
|
||||
<span>查看全部</span>
|
||||
<Icon class="arrow" icon="mingcute:right-line"/>
|
||||
</div>
|
||||
</header>
|
||||
<div class="comment" v-for="i in state.detail.note_card.comment_list.slice(0,2)">
|
||||
<img src="https://cdn.seovx.com/?mom=302" alt="" class="avatar">
|
||||
<span>
|
||||
{{ i.name }}:{{ i.text }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="toolbar">
|
||||
<div class="input-wrap">
|
||||
说点什么...
|
||||
</div>
|
||||
<div class="options">
|
||||
<div class="option">
|
||||
<Icon icon="solar:heart-linear"/>
|
||||
<div class="text">{{ state.detail.note_card?.interact_info?.liked_count }}</div>
|
||||
</div>
|
||||
<div class="option">
|
||||
<Icon icon="mage:message-dots-round" class="icon"/>
|
||||
<div class="text">{{ state.detail.note_card.comment_list.length }}</div>
|
||||
</div>
|
||||
<div class="option">
|
||||
<Icon icon="mage:star"/>
|
||||
<div class="text">{{ state.detail.note_card?.interact_info?.collect_count }}</div>
|
||||
</div>
|
||||
<div class="option">
|
||||
<Icon icon="ph:share-fat-light"/>
|
||||
<div class="text">{{ state.detail.note_card?.interact_info?.share_count }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import SlideHorizontal from "@/components/slide/SlideHorizontal.vue";
|
||||
import SlideItem from "@/components/slide/SlideItem.vue";
|
||||
import {onMounted, reactive} from "vue";
|
||||
import {useNav} from "@/utils/hooks/useNav";
|
||||
import {Icon} from "@iconify/vue";
|
||||
import {useBaseStore} from "@/store/pinia";
|
||||
import {_checkImgUrl, cloneDeep} from "@/utils";
|
||||
import Mock from 'mockjs'
|
||||
|
||||
const nav = useNav()
|
||||
const store = useBaseStore()
|
||||
|
||||
defineOptions({
|
||||
name: 'Album-Detail'
|
||||
})
|
||||
|
||||
const state = reactive({
|
||||
detail: {
|
||||
"id": "",
|
||||
"note_card": {
|
||||
"interact_info": {},
|
||||
"cover": {},
|
||||
"image_list": [],
|
||||
"display_title": "",
|
||||
"user": {},
|
||||
comment_list: [],
|
||||
createTime: ''
|
||||
}
|
||||
},
|
||||
index: 0,
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
state.detail = cloneDeep(store.routeData)
|
||||
let data = Mock.mock({
|
||||
'comment_list|3-50': [{
|
||||
name: '@cname',
|
||||
text: '@cparagraph(3)'
|
||||
}]
|
||||
})
|
||||
state.detail.note_card.comment_list = data.comment_list
|
||||
state.detail.note_card.createTime = Mock.Random.date('MM-dd')
|
||||
state.detail.note_card.interact_info.collect_count = Mock.Random.integer(60, 3000)
|
||||
state.detail.note_card.interact_info.share_count = Mock.Random.integer(60, 3000)
|
||||
console.log('sta', state.detail)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
@import "@/assets/less/index.less";
|
||||
|
||||
.goods-detail {
|
||||
background: var(--color-message);
|
||||
color: white;
|
||||
font-size: 14rem;
|
||||
@c: #a2a2a2;
|
||||
@c2: #c0c0c0;
|
||||
@red: rgb(248, 38, 74);
|
||||
|
||||
& > header {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100vw;
|
||||
z-index: 9;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 15rem;
|
||||
box-sizing: border-box;
|
||||
|
||||
svg {
|
||||
font-size: 20rem;
|
||||
background: rgba(176, 176, 176, 0.4);
|
||||
padding: 5rem;
|
||||
color: white;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.slide-imgs {
|
||||
position: relative;
|
||||
height: 55vh;
|
||||
|
||||
img {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
object-fit: cover;
|
||||
touch-action: none;
|
||||
}
|
||||
|
||||
.indicator-bar {
|
||||
position: absolute;
|
||||
bottom: 5rem;
|
||||
left: 3vw;
|
||||
width: 94vw;
|
||||
display: flex;
|
||||
gap: 5rem;
|
||||
|
||||
.indicator {
|
||||
background: rgba(162, 160, 160, 0.5);
|
||||
height: 3rem;
|
||||
flex: 1;
|
||||
border-radius: 2rem;
|
||||
}
|
||||
|
||||
.active {
|
||||
background: rgba(250, 246, 246, 0.58);
|
||||
}
|
||||
}
|
||||
|
||||
.index {
|
||||
font-size: 12rem;
|
||||
position: absolute;
|
||||
padding: 3rem 10rem;
|
||||
border-radius: 15rem;
|
||||
background: rgba(91, 89, 89, 0.5);
|
||||
right: 10rem;
|
||||
bottom: 30rem;
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
.card {
|
||||
margin-top: 15rem;
|
||||
border-radius: 10rem;
|
||||
padding: 10rem 15rem;
|
||||
background: black;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
font-size: 16rem;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 15rem;
|
||||
padding-bottom: 10vh;
|
||||
border-radius: 16rem 16rem 0 0;
|
||||
|
||||
.comments {
|
||||
& > header {
|
||||
margin-bottom: 16rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.l {
|
||||
font-size: 15rem;
|
||||
}
|
||||
|
||||
.r {
|
||||
color: gray;
|
||||
font-size: 12rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.comment {
|
||||
margin-bottom: 16rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5rem;
|
||||
|
||||
span {
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
flex: 1;
|
||||
word-break: break-all;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
img {
|
||||
border-radius: 50%;
|
||||
width: 20rem;
|
||||
height: 20rem;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.shop {
|
||||
& > header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10rem;
|
||||
|
||||
img {
|
||||
width: 36rem;
|
||||
height: 36rem;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.right {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.name {
|
||||
font-size: 16rem;
|
||||
}
|
||||
|
||||
.r {
|
||||
border-radius: 4rem;
|
||||
padding: 6rem 16rem;
|
||||
background: var(--primary-btn-color);
|
||||
font-size: 12rem;
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.desc {
|
||||
margin-top: 10rem;
|
||||
}
|
||||
|
||||
.date {
|
||||
font-size: 12rem;
|
||||
margin-top: 10rem;
|
||||
color: gray;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.toolbar {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 100vw;
|
||||
left: 0;
|
||||
background: var(--color-message);
|
||||
border-top: 1px solid rgba(white, .1);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 8rem 10rem;
|
||||
padding-right: 0;
|
||||
box-sizing: border-box;
|
||||
gap: 6rem;
|
||||
|
||||
.input-wrap {
|
||||
width: 110rem;
|
||||
padding-left: 15rem;
|
||||
height: 34rem;
|
||||
border-radius: 30rem;
|
||||
background: var(--second-btn-color-tran);
|
||||
color: gray;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.options {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
|
||||
.option {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
font-size: 13rem;
|
||||
color: white;
|
||||
|
||||
svg {
|
||||
font-size: 24rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -1,8 +1,17 @@
|
||||
<template>
|
||||
<div id="video-detail">
|
||||
<div class="search-wrapper">
|
||||
<dy-back class="back" @click="$back"/>
|
||||
<Search></Search>
|
||||
<Icon class="back" icon="icon-park-outline:left" @click="$back"/>
|
||||
<div class="search" @click="nav('/home/search')">
|
||||
<div class="left">
|
||||
<Icon class="icon" icon="ion:search"/>
|
||||
<span>搜你想看的</span>
|
||||
</div>
|
||||
<div class="right">
|
||||
<span class="gang">|</span>
|
||||
<span class="txt">搜索</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<SlideVerticalInfinite
|
||||
@@ -19,116 +28,139 @@
|
||||
/>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<div class="share-to-friend" v-if="!data.isMy">
|
||||
<span>留下你的精彩评论吧</span>
|
||||
<div class="share-btn" @click="data.dialog.shareToFriend = true">分享给朋友</div>
|
||||
</div>
|
||||
<div class="permission-setting" v-if="data.isMy">
|
||||
<div class="right">
|
||||
<img src="../../assets/img/icon/play-white.png" alt="">
|
||||
<span>3030浏览</span>
|
||||
<div class="comment">
|
||||
<div class="left">
|
||||
<img :src="_checkImgUrl(baseStore.userinfo.avatar_168x168.url_list[0])" class="avatar" alt=""/>
|
||||
<span>善语结善缘,恶言伤人心</span>
|
||||
</div>
|
||||
<div class="right">
|
||||
<Icon icon="tabler:photo"/>
|
||||
<Icon icon="ion:at-sharp"/>
|
||||
<Icon icon="fa-regular:laugh"/>
|
||||
</div>
|
||||
<div class="share-btn" @click="data.dialog.permissionDialog = true">权限设置</div>
|
||||
</div>
|
||||
</div>
|
||||
<from-bottom-dialog
|
||||
page-id="video-detail"
|
||||
v-model="data.dialog.shareToFriend"
|
||||
height="50vh"
|
||||
mode="light"
|
||||
mask-mode="light"
|
||||
|
||||
<Comment page-id="video-detail"
|
||||
:video-id="state.currentItem.aweme_id"
|
||||
v-model="state.commentVisible"
|
||||
@close="closeComments"
|
||||
/>
|
||||
|
||||
<Share v-model="state.isSharing"
|
||||
ref="share"
|
||||
page-id="video-detail"
|
||||
@dislike="dislike"
|
||||
:item="state.currentItem"
|
||||
:videoId="state.recommendList[state.itemIndex]?.id"
|
||||
:canDownload="state.recommendList[state.itemIndex]?.canDownload"
|
||||
@play-feedback="state.showPlayFeedback = true"
|
||||
@shareToFriend="delayShowDialog(e => state.shareToFriend = true)"
|
||||
@showDouyinCode="state.showDouyinCode = true"
|
||||
@download="state.shareType = 9"
|
||||
/>
|
||||
|
||||
<PlayFeedback v-model="state.showPlayFeedback"/>
|
||||
|
||||
<DouyinCode
|
||||
:item="state.currentItem"
|
||||
v-model="state.showDouyinCode"/>
|
||||
|
||||
<ShareTo v-model:type="state.shareType"
|
||||
:videoId="state.recommendList[state.itemIndex]?.id"
|
||||
:canDownload="state.recommendList[state.itemIndex]?.canDownload"
|
||||
/>
|
||||
|
||||
<FollowSetting
|
||||
v-model:currentItem="state.currentItem"
|
||||
@showChangeNote="delayShowDialog( e => state.showChangeNote = true)"
|
||||
@showBlockDialog="delayShowDialog(e => state.showBlockDialog = true)"
|
||||
@showShare="delayShowDialog( e => state.isSharing = true)"
|
||||
v-model="state.showFollowSetting"/>
|
||||
|
||||
<FollowSetting2
|
||||
v-model:currentItem="state.currentItem"
|
||||
@cancelFollow="$refs.uploader.cancelFollow()"
|
||||
v-model="state.showFollowSetting2"/>
|
||||
|
||||
<BlockDialog v-model="state.showBlockDialog"/>
|
||||
|
||||
<ConfirmDialog
|
||||
title="设置备注名"
|
||||
ok-text="确认"
|
||||
v-model:visible="state.showChangeNote"
|
||||
>
|
||||
<div class="share-dialog">
|
||||
<div class="collection" @click="data.dialog.shareToFriend = false">
|
||||
<img src="../../assets/img/icon/me/collection-black.png" alt="">
|
||||
收藏
|
||||
</div>
|
||||
<div class="friends">
|
||||
<div class="friend" v-for="i in 6">
|
||||
<img src="../../assets/img/icon/head-image.jpeg" alt="">
|
||||
<div class="right">
|
||||
<span>三分钟情、</span>
|
||||
<div class="share-btn">分享</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="friend">
|
||||
<img src="../../assets/img/icon/head-image.jpeg" alt="">
|
||||
<div class="right">
|
||||
<span>更多好友</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</from-bottom-dialog>
|
||||
<from-bottom-dialog
|
||||
page-id="video-detail"
|
||||
v-model="data.dialog.permissionDialog"
|
||||
height="40vh"
|
||||
mode="white"
|
||||
mask-mode="white"
|
||||
>
|
||||
<div class="permission-dialog">
|
||||
<div class="setting" @click="data.dialog.permissionDialog = false">
|
||||
<img src="../../assets/img/icon/head-image.jpeg" alt="">
|
||||
<div class="right">
|
||||
<span>公开 所有人可见</span>
|
||||
<img src="../../assets/img/icon/head-image.jpeg" alt="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting">
|
||||
<img src="../../assets/img/icon/head-image.jpeg" alt="">
|
||||
<div class="right">
|
||||
<span>朋友 互关朋友可见</span>
|
||||
<img src="../../assets/img/icon/head-image.jpeg" alt="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting">
|
||||
<img src="../../assets/img/icon/head-image.jpeg" alt="">
|
||||
<div class="right">
|
||||
<span>私密 仅自己见</span>
|
||||
<img src="../../assets/img/icon/head-image.jpeg" alt="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting" style="border-bottom: none;">
|
||||
<img src="../../assets/img/icon/head-image.jpeg" alt="">
|
||||
<div class="right">
|
||||
<span>不给谁看</span>
|
||||
<img src="../../assets/img/icon/head-image.jpeg" alt="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="space"></div>
|
||||
<div class="setting pb4r">
|
||||
<img src="../../assets/img/icon/head-image.jpeg" alt="">
|
||||
<div class="right">
|
||||
<span>更多好友</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</from-bottom-dialog>
|
||||
<Search mode="light" v-model="state.test" :isShowSearchIcon="false"/>
|
||||
</ConfirmDialog>
|
||||
|
||||
<ShareToFriend v-model="state.shareToFriend"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
<script setup lang="jsx">
|
||||
import Comment from "../../components/Comment.vue";
|
||||
import Share from "../../components/Share.vue";
|
||||
import {onMounted, onUnmounted, reactive} from "vue";
|
||||
import bus, {EVENT_KEY} from "../../utils/bus";
|
||||
import {useNav} from "@/utils/hooks/useNav";
|
||||
import PlayFeedback from "@/pages/home/components/PlayFeedback.vue";
|
||||
import ShareTo from "@/pages/home/components/ShareTo.vue";
|
||||
import DouyinCode from "../../components/DouyinCode.vue";
|
||||
import FollowSetting from "@/pages/home/components/FollowSetting.vue";
|
||||
import BlockDialog from "../message/components/BlockDialog.vue";
|
||||
import Search from "../../components/Search.vue";
|
||||
import FromBottomDialog from "../../components/dialog/FromBottomDialog.vue";
|
||||
import {onMounted, reactive} from "vue";
|
||||
import ConfirmDialog from "../../components/dialog/ConfirmDialog.vue";
|
||||
import FollowSetting2 from "@/pages/home/components/FollowSetting2.vue";
|
||||
import ShareToFriend from "@/pages/home/components/ShareToFriend.vue";
|
||||
import {DefaultUser} from "@/utils/const_var";
|
||||
import {_checkImgUrl} from "@/utils";
|
||||
import {useBaseStore} from "@/store/pinia";
|
||||
import SlideVerticalInfinite from "@/components/slide/SlideVerticalInfinite.vue";
|
||||
import {useSlideListItemRender} from "@/utils/hooks/useSlideListItemRender";
|
||||
import {useRouter} from "vue-router";
|
||||
|
||||
defineOptions({
|
||||
name: 'VideoDetail'
|
||||
})
|
||||
const store = useBaseStore()
|
||||
const nav = useNav()
|
||||
const router = useRouter()
|
||||
|
||||
const baseStore = useBaseStore()
|
||||
const data = reactive({
|
||||
dialog: {
|
||||
shareToFriend: false,
|
||||
permissionDialog: false,
|
||||
test: false,
|
||||
},
|
||||
isMy: true
|
||||
isMy: false
|
||||
})
|
||||
|
||||
const state = reactive({
|
||||
baseIndex: 1,
|
||||
navIndex: 4,
|
||||
test: '',
|
||||
recommendList: [],
|
||||
isSharing: false,
|
||||
canMove: true,
|
||||
shareType: -1,
|
||||
showPlayFeedback: false,
|
||||
showShareDuoshan: false,
|
||||
showShareDialog: false,
|
||||
showShare2WeChatZone: false,
|
||||
showDouyinCode: false,
|
||||
showFollowSetting: false,
|
||||
showFollowSetting2: false,
|
||||
showBlockDialog: false,
|
||||
showChangeNote: false,
|
||||
shareToFriend: false,
|
||||
|
||||
commentVisible: false,
|
||||
fullScreen: false,
|
||||
currentItem: {
|
||||
author: DefaultUser,
|
||||
isRequest: false,
|
||||
aweme_list: [],
|
||||
},
|
||||
index: 0,
|
||||
list: [],
|
||||
uniqueId: 'uniqueId_2',
|
||||
@@ -136,47 +168,137 @@ const state = reactive({
|
||||
pageSize: 10,
|
||||
pageNo: 0,
|
||||
})
|
||||
|
||||
|
||||
const render = useSlideListItemRender()
|
||||
|
||||
onMounted(() => {
|
||||
console.log('s', store.routeData)
|
||||
state.index = store.routeData.index
|
||||
state.list = store.routeData.list
|
||||
|
||||
console.log('sss', state.list[state.index])
|
||||
// console.log('s', store.routeData)
|
||||
state.index = baseStore.routeData.index
|
||||
state.list = baseStore.routeData.list
|
||||
// console.log('sss', state.list[state.index])
|
||||
})
|
||||
|
||||
function delayShowDialog(cb) {
|
||||
setTimeout(cb, 400)
|
||||
}
|
||||
|
||||
function setCurrentItem(item) {
|
||||
// console.log('sss',item,state.baseIndex)
|
||||
if (state.baseIndex !== 1) return
|
||||
if (state.currentItem.author.uid !== item.author.uid) {
|
||||
state.currentItem = {
|
||||
...item,
|
||||
isRequest: false,
|
||||
aweme_list: [],
|
||||
}
|
||||
}
|
||||
// console.log('item', item)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
bus.on(EVENT_KEY.ENTER_FULLSCREEN, (e) => state.fullScreen = true)
|
||||
bus.on(EVENT_KEY.EXIT_FULLSCREEN, (e) => state.fullScreen = false)
|
||||
bus.on(EVENT_KEY.OPEN_COMMENTS, (e) => {
|
||||
bus.emit(EVENT_KEY.ENTER_FULLSCREEN)
|
||||
state.commentVisible = true
|
||||
})
|
||||
bus.on(EVENT_KEY.CLOSE_COMMENTS, (e) => {
|
||||
bus.emit(EVENT_KEY.EXIT_FULLSCREEN)
|
||||
state.commentVisible = false
|
||||
})
|
||||
bus.on(EVENT_KEY.SHOW_SHARE, (e) => {
|
||||
state.isSharing = true
|
||||
})
|
||||
bus.on(EVENT_KEY.NAV, ({path, query}) => nav(path, query))
|
||||
bus.on(EVENT_KEY.GO_USERINFO, () => {
|
||||
router.back()
|
||||
})
|
||||
bus.on(EVENT_KEY.CURRENT_ITEM, setCurrentItem)
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
bus.offAll()
|
||||
})
|
||||
|
||||
function closeComments() {
|
||||
bus.emit(EVENT_KEY.CLOSE_COMMENTS)
|
||||
}
|
||||
|
||||
function dislike() {
|
||||
// listRef.value.dislike(state.list[1])
|
||||
// state.list[state.index] = state.list[1]
|
||||
// Utils.$notice('操作成功,将减少此类视频的推荐')
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
@import "../../assets/less/index";
|
||||
|
||||
#video-detail {
|
||||
position: fixed;
|
||||
font-size: 14rem;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background: black;
|
||||
|
||||
.search-wrapper {
|
||||
height: var(--common-header-height);
|
||||
z-index: 9;
|
||||
position: fixed;
|
||||
top: 10rem;
|
||||
left: 15rem;
|
||||
right: 15rem;
|
||||
top: 8rem;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
padding: 0 15rem;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 15rem;
|
||||
|
||||
.back {
|
||||
width: 20rem;
|
||||
height: 20rem;
|
||||
margin-right: 10rem;
|
||||
color: white;
|
||||
font-size: 30rem;
|
||||
}
|
||||
|
||||
.search-ctn {
|
||||
width: 100%;
|
||||
.search {
|
||||
color: var(--second-btn-color);
|
||||
display: flex;
|
||||
background: rgba(171, 169, 169, 0.4);
|
||||
border-radius: 8rem;
|
||||
flex: 1;
|
||||
padding: 8rem;
|
||||
justify-content: space-between;
|
||||
|
||||
.left {
|
||||
font-size: 15rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: gainsboro;
|
||||
gap: 5rem;
|
||||
line-height: 1;
|
||||
|
||||
svg {
|
||||
font-size: 14rem;
|
||||
}
|
||||
}
|
||||
|
||||
.right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10rem;
|
||||
font-size: 16rem;
|
||||
|
||||
.gang {
|
||||
color: dimgrey;
|
||||
}
|
||||
|
||||
.txt {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,167 +308,45 @@ onMounted(() => {
|
||||
|
||||
.footer {
|
||||
height: var(--footer-height);
|
||||
}
|
||||
|
||||
.share-to-friend {
|
||||
color: var(--second-text-color);
|
||||
height: var(--footer-height);
|
||||
z-index: 9;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.comment {
|
||||
color: var(--second-text-color);
|
||||
z-index: 9;
|
||||
width: 95%;
|
||||
height: 75%;
|
||||
box-sizing: border-box;
|
||||
padding: 0 20px;
|
||||
padding: 0 10px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
background: rgb(37, 37, 37);
|
||||
border-radius: 50rem;
|
||||
|
||||
.share-btn {
|
||||
color: darkgray;
|
||||
padding: 6px 14px;
|
||||
background: rgb(44, 44, 44);
|
||||
border-radius: 50px;
|
||||
.avatar {
|
||||
height: 70%;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.permission-setting {
|
||||
color: var(--second-text-color);
|
||||
height: var(--footer-height);
|
||||
z-index: 9;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 0 20px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
.left {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10rem;
|
||||
}
|
||||
|
||||
.right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 14rem;
|
||||
|
||||
img {
|
||||
margin-right: 10px;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.share-btn {
|
||||
color: darkgray;
|
||||
padding: 6px 14px;
|
||||
background: rgb(44, 44, 44);
|
||||
border-radius: 50px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.share-dialog {
|
||||
.collection {
|
||||
background: white;
|
||||
margin: 0 10rem 10rem 10rem;
|
||||
width: calc(100% - 20rem);
|
||||
border-radius: 6px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 16rem;
|
||||
font-weight: bold;
|
||||
padding: 10px;
|
||||
box-sizing: border-box;
|
||||
|
||||
img {
|
||||
background: white;
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.friends {
|
||||
margin: 10rem 10rem 0 10rem;
|
||||
width: calc(100% - 20rem);
|
||||
background: white;
|
||||
border-radius: 6px 6px 0 0;
|
||||
|
||||
.friend {
|
||||
box-sizing: border-box;
|
||||
padding: 10px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
//border-bottom: 1px solid ghostwhite;
|
||||
border-bottom: 1px solid gainsboro;
|
||||
|
||||
img {
|
||||
border-radius: 50%;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.right {
|
||||
margin: 0 5px 0 15px;
|
||||
font-size: 16rem;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
.share-btn {
|
||||
font-size: 14rem;
|
||||
color: white;
|
||||
padding: 5px 20px;
|
||||
background: var(--primary-btn-color);
|
||||
border-radius: 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.permission-dialog {
|
||||
.space {
|
||||
height: 10rem;
|
||||
background: whitesmoke;
|
||||
}
|
||||
|
||||
.setting {
|
||||
background: white;
|
||||
box-sizing: border-box;
|
||||
padding: 10rem 20rem;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
//border-bottom: 1px solid ghostwhite;
|
||||
border-bottom: 1px solid gainsboro;
|
||||
|
||||
img {
|
||||
border-radius: 50%;
|
||||
width: 30rem;
|
||||
height: 30rem;
|
||||
}
|
||||
|
||||
.right {
|
||||
margin: 0 5rem 0 15rem;
|
||||
font-size: 14rem;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
.share-btn {
|
||||
font-size: 14rem;
|
||||
color: white;
|
||||
padding: 5rem 20rem;
|
||||
background: var(--primary-btn-color);
|
||||
border-radius: 2rem;
|
||||
}
|
||||
}
|
||||
.left;
|
||||
gap: 15rem;
|
||||
font-size: 24rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
201
src/pages/other/VideoDetail2.vue
Normal file
@@ -0,0 +1,201 @@
|
||||
<template>
|
||||
<div id="video-detail">
|
||||
<div class="search-wrapper">
|
||||
<Icon class="back" icon="icon-park-outline:left" @click="$back"/>
|
||||
<div class="search" @click="nav('/home/search')">
|
||||
<div class="left">
|
||||
<Icon class="icon" icon="ion:search"/>
|
||||
<span>搜你想看的</span>
|
||||
</div>
|
||||
<div class="right">
|
||||
<span class="gang">|</span>
|
||||
<span class="txt">搜索</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<SlideVerticalInfinite
|
||||
ref="listRef"
|
||||
v-love="state.uniqueId"
|
||||
:id="state.uniqueId"
|
||||
:uniqueId="state.uniqueId"
|
||||
name="main"
|
||||
:active="true"
|
||||
:loading="false"
|
||||
v-model:index="state.index"
|
||||
:render="render"
|
||||
:list="state.list"
|
||||
/>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<div class="comment">
|
||||
<div class="left">
|
||||
<img :src="_checkImgUrl(store.userinfo.avatar_168x168.url_list[0])" class="avatar" alt=""/>
|
||||
<span>善语结善缘,恶言伤人心</span>
|
||||
</div>
|
||||
<div class="right">
|
||||
<Icon icon="tabler:photo"/>
|
||||
<Icon icon="ion:at-sharp"/>
|
||||
<Icon icon="fa-regular:laugh"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {onMounted, reactive} from "vue";
|
||||
import {useBaseStore} from "@/store/pinia";
|
||||
import SlideVerticalInfinite from "@/components/slide/SlideVerticalInfinite.vue";
|
||||
import {useSlideListItemRender} from "@/utils/hooks/useSlideListItemRender";
|
||||
import {_checkImgUrl} from "@/utils";
|
||||
import {useNav} from "@/utils/hooks/useNav";
|
||||
|
||||
defineOptions({
|
||||
name: 'VideoDetail'
|
||||
})
|
||||
const nav = useNav()
|
||||
const store = useBaseStore()
|
||||
const data = reactive({
|
||||
dialog: {
|
||||
shareToFriend: false,
|
||||
permissionDialog: false,
|
||||
test: false,
|
||||
},
|
||||
isMy: false
|
||||
})
|
||||
const state = reactive({
|
||||
index: 0,
|
||||
list: [],
|
||||
uniqueId: 'uniqueId_2',
|
||||
totalSize: 0,
|
||||
pageSize: 10,
|
||||
pageNo: 0,
|
||||
})
|
||||
const render = useSlideListItemRender()
|
||||
|
||||
onMounted(() => {
|
||||
// console.log('s', store.routeData)
|
||||
state.index = store.routeData.index
|
||||
state.list = store.routeData.list
|
||||
// console.log('sss', state.list[state.index])
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
@import "../../assets/less/index";
|
||||
|
||||
#video-detail {
|
||||
position: fixed;
|
||||
font-size: 14rem;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background: black;
|
||||
|
||||
.search-wrapper {
|
||||
z-index: 9;
|
||||
position: fixed;
|
||||
top: 8rem;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
padding: 0 15rem;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 15rem;
|
||||
|
||||
.back {
|
||||
color: white;
|
||||
font-size: 30rem;
|
||||
}
|
||||
|
||||
.search {
|
||||
color: var(--second-btn-color);
|
||||
display: flex;
|
||||
background: rgba(171, 169, 169, 0.4);
|
||||
border-radius: 8rem;
|
||||
flex: 1;
|
||||
padding: 8rem;
|
||||
justify-content: space-between;
|
||||
|
||||
.left {
|
||||
font-size: 15rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: gainsboro;
|
||||
gap: 5rem;
|
||||
line-height: 1;
|
||||
|
||||
svg {
|
||||
font-size: 14rem;
|
||||
}
|
||||
}
|
||||
|
||||
.right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10rem;
|
||||
font-size: 16rem;
|
||||
|
||||
.gang {
|
||||
color: dimgrey;
|
||||
}
|
||||
|
||||
.txt {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
height: calc(var(--vh, 1vh) * 100 - var(--footer-height));
|
||||
}
|
||||
|
||||
.footer {
|
||||
height: var(--footer-height);
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.comment {
|
||||
color: var(--second-text-color);
|
||||
z-index: 9;
|
||||
width: 95%;
|
||||
height: 75%;
|
||||
box-sizing: border-box;
|
||||
padding: 0 10px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
background: rgb(37, 37, 37);
|
||||
border-radius: 50rem;
|
||||
|
||||
.avatar {
|
||||
height: 70%;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.left {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10rem;
|
||||
}
|
||||
|
||||
.right {
|
||||
.left;
|
||||
gap: 15rem;
|
||||
font-size: 24rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -56,7 +56,7 @@
|
||||
<div class="slide-imgs">
|
||||
<SlideHorizontal v-model:index="state.index">
|
||||
<SlideItem v-for="item in state.detail.imgs">
|
||||
<img :src="item" alt="">
|
||||
<img v-lazy="_checkImgUrl('goods/'+item)" alt=""/>
|
||||
</SlideItem>
|
||||
</SlideHorizontal>
|
||||
<div class="index">{{ state.index + 1 }}/{{ state.detail.imgs.length }}</div>
|
||||
@@ -66,20 +66,20 @@
|
||||
<div class="price-wrap">
|
||||
<div class="price">
|
||||
<span class="symbol">¥</span>
|
||||
<span class="int">8</span>
|
||||
<span class="decimal">.8</span>
|
||||
<span class="int">{{ state.detail.price }}</span>
|
||||
<!-- <span class="decimal">.8</span>-->
|
||||
</div>
|
||||
<div class="discount">
|
||||
<span class="text">热销款券后</span>
|
||||
<div class="price">
|
||||
<span class="symbol">¥</span>
|
||||
<span class="int">5</span>
|
||||
<span class="decimal">.9</span>
|
||||
<span class="int">{{ state.detail.real_price }}</span>
|
||||
<!-- <span class="decimal">.9</span>-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="name">{{ state.detail.name }}</div>
|
||||
<div class="num">已售20/100</div>
|
||||
<div class="num">已售{{ state.detail.sold }}</div>
|
||||
</div>
|
||||
|
||||
<div class="card desc-wrapper">
|
||||
@@ -145,9 +145,9 @@
|
||||
<div class="tag">推荐 <span class="gray">18</span></div>
|
||||
<div class="tag">商用服务好 <span class="gray">15</span></div>
|
||||
</div>
|
||||
<div class="comment" v-for="i in 2">
|
||||
<div class="comment">
|
||||
<header>
|
||||
<img src="https://cdn.seovx.com/?mom=302" alt="" class="avatar">
|
||||
<img :src="_checkImgUrl('2S9bbgb-Sf2kIdSTxoeTw.png')" alt="" class="avatar">
|
||||
<span class="gray">花***栽</span>
|
||||
</header>
|
||||
<div class="w">
|
||||
@@ -159,14 +159,31 @@
|
||||
china款/超值【买る双+送2双】共5双
|
||||
</div>
|
||||
</div>
|
||||
<img src="https://cdn.seovx.com/?mom=302" alt="" class="avatar">
|
||||
<img :src="_checkImgUrl('NYEfuYS-LVZ620UYgQNAM.png')" alt="" class="avatar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="comment">
|
||||
<header>
|
||||
<img :src="_checkImgUrl('9Tx6cZkUOoHqPkbETUZ5Y.png')" alt="" class="avatar">
|
||||
<span class="gray">花***栽</span>
|
||||
</header>
|
||||
<div class="w">
|
||||
<div class="left">
|
||||
<div class="d">
|
||||
东西不错质量也很好 性价比很高 良心商家就冲这图必须给好评
|
||||
</div>
|
||||
<div class="c2">
|
||||
china款/超值【买る双+送2双】共5双
|
||||
</div>
|
||||
</div>
|
||||
<img :src="_checkImgUrl('2b2rpive_RVzDrYgo-F9K.png')" alt="" class="avatar">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card shop">
|
||||
<header>
|
||||
<img src="https://cdn.seovx.com/?mom=302" alt="" class="avatar">
|
||||
<img :src="_checkImgUrl('LJ-8p2jF3HydBD5j28PgQ.png')" alt="" class="avatar">
|
||||
<div class="right">
|
||||
<div class="l">
|
||||
<div class="name">店铺名</div>
|
||||
@@ -207,9 +224,36 @@
|
||||
</div>
|
||||
</header>
|
||||
<div class="wrap">
|
||||
<div class="item" v-for="i in 4">
|
||||
<img src="https://cdn.seovx.com/?mom=302" alt="" class="avatar">
|
||||
<div class="name">【热销中】袜子男潮流百搭中筒袜子袜子男潮流百搭中筒袜子</div>
|
||||
<div class="item">
|
||||
<img :src="_checkImgUrl('/goods/g6-0.jpg')" alt="" class="avatar">
|
||||
<div class="name">小米电视6 65" OLED 65英寸</div>
|
||||
<div class="price">
|
||||
<span class="symbol">¥</span>
|
||||
<span class="int">8</span>
|
||||
<span class="decimal">.8</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<img :src="_checkImgUrl('/goods/g1-0.jpg')" alt="" class="avatar">
|
||||
<div class="name">红白撞色条纹软糯针织上衣女2022年秋季新款甜美减龄短款毛衣开衫</div>
|
||||
<div class="price">
|
||||
<span class="symbol">¥</span>
|
||||
<span class="int">8</span>
|
||||
<span class="decimal">.8</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<img :src="_checkImgUrl('/goods/g2-0.webp')" alt="" class="avatar">
|
||||
<div class="name">森马t恤男2023男士纯棉上衣白色情侣装凉感短袖打底衫纯色体恤潮</div>
|
||||
<div class="price">
|
||||
<span class="symbol">¥</span>
|
||||
<span class="int">8</span>
|
||||
<span class="decimal">.8</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<img :src="_checkImgUrl('/goods/g3-0.jpg')" alt="" class="avatar">
|
||||
<div class="name">ins潮牌长袖t恤男宽松纯色内搭上衣潮牌百搭秋冬季潮流帅气打底衫</div>
|
||||
<div class="price">
|
||||
<span class="symbol">¥</span>
|
||||
<span class="int">8</span>
|
||||
@@ -221,7 +265,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="img-list" v-if="true">
|
||||
<div class="img-list">
|
||||
<header>
|
||||
<div class="l"></div>
|
||||
<span class="gray">商品详情</span>
|
||||
@@ -229,7 +273,7 @@
|
||||
</header>
|
||||
|
||||
<div class="imgs">
|
||||
<img v-lazy="`https://cdn.seovx.com/?mom=302&d=${i}`" alt="" class="avatar" v-for="i in 5">
|
||||
<img v-lazy="_checkImgUrl('goods/'+i)" alt="" class="avatar" v-for="i in state.detail.imgs">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -254,34 +298,39 @@
|
||||
你可以还会喜欢
|
||||
</header>
|
||||
|
||||
<div v-masonry class="goods-list"
|
||||
:class="{fixed:state.fixed}"
|
||||
transition-duration="0s"
|
||||
item-selector=".goods">
|
||||
<div v-masonry-tile class="goods"
|
||||
@click="nav('/shop/detail')"
|
||||
v-for="(item, index) in state.list">
|
||||
<div class="item">
|
||||
<img class="poster" v-lazy="Utils.$imgPreview(item.cover)"/>
|
||||
<div class="bottom">
|
||||
<div class="desc">
|
||||
{{ item.name }}
|
||||
</div>
|
||||
<div class="discounts" v-if="item.discount">{{ item.discount }}</div>
|
||||
<div class="info">
|
||||
<div class="price">
|
||||
¥
|
||||
<div class="big">{{ item.price }}</div>
|
||||
<ScrollList
|
||||
class="Scroll"
|
||||
:api="recommendedShop"
|
||||
>
|
||||
<template v-slot="{list}">
|
||||
<WaterfallList :list="list">
|
||||
<template v-slot="{item}">
|
||||
<div class="goods"
|
||||
@click="nav('/shop/detail',{},item)">
|
||||
<div class="item">
|
||||
<img class="poster" v-lazy="_checkImgUrl('goods/'+item.cover)"/>
|
||||
<div class="bottom">
|
||||
<div class="desc">
|
||||
{{ item.name }}
|
||||
</div>
|
||||
<div class="discounts" v-if="item.discount">{{ item.discount }}</div>
|
||||
<div class="info">
|
||||
<div class="price">
|
||||
¥
|
||||
<div class="big">{{ item.price }}</div>
|
||||
</div>
|
||||
<div class="num">已售{{ item.sold }}件</div>
|
||||
</div>
|
||||
<div class="low" v-if="item.isLowPrice">
|
||||
近30天低价
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="num">已售{{ item.sold }}件</div>
|
||||
</div>
|
||||
<div class="low" v-if="item.isLowPrice">
|
||||
近30天低价
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</WaterfallList>
|
||||
</template>
|
||||
</ScrollList>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@@ -312,19 +361,21 @@
|
||||
<script setup>
|
||||
import SlideHorizontal from "@/components/slide/SlideHorizontal.vue";
|
||||
import SlideItem from "@/components/slide/SlideItem.vue";
|
||||
import {reactive, ref} from "vue";
|
||||
import goods from "@/assets/data/goods";
|
||||
import {onMounted, onUnmounted, reactive, ref} from "vue";
|
||||
import {useNav} from "@/utils/hooks/useNav";
|
||||
import Utils from "@/utils";
|
||||
import {_checkImgUrl} from "@/utils";
|
||||
import {useBaseStore} from "@/store/pinia";
|
||||
import {recommendedShop} from "@/api/user";
|
||||
import WaterfallList from "@/components/WaterfallList.vue";
|
||||
import ScrollList from "@/components/ScrollList.vue";
|
||||
|
||||
defineOptions({
|
||||
name: 'GoodsDetail'
|
||||
})
|
||||
|
||||
let activeIndexs = ref([])
|
||||
const nav = useNav()
|
||||
const props = defineProps({
|
||||
id: {
|
||||
type: String,
|
||||
default: () => ''
|
||||
}
|
||||
})
|
||||
const store = useBaseStore()
|
||||
let page = ref()
|
||||
let header = ref()
|
||||
let headerShadow = ref()
|
||||
@@ -341,9 +392,10 @@ function scroll() {
|
||||
}
|
||||
|
||||
const state = reactive({
|
||||
detail: goods.list[1],
|
||||
index: 2,
|
||||
list: goods.list,
|
||||
detail: {
|
||||
imgs: []
|
||||
},
|
||||
index: 0,
|
||||
listEl: null,
|
||||
fixed: false
|
||||
})
|
||||
@@ -356,6 +408,15 @@ function toggle(i) {
|
||||
activeIndexs.value.push(i)
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
console.log('r', store.routeData.imgs)
|
||||
state.detail = store.routeData
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
console.log('onUnmounted')
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
@@ -946,7 +1007,6 @@ function toggle(i) {
|
||||
|
||||
& > header {
|
||||
padding: 15rem;
|
||||
padding-bottom: 5rem;
|
||||
font-weight: 900;
|
||||
font-size: 15rem;
|
||||
}
|
||||
@@ -959,14 +1019,13 @@ function toggle(i) {
|
||||
|
||||
@p: 5rem;
|
||||
|
||||
.goods-list {
|
||||
padding-bottom: 20rem;
|
||||
.Scroll {
|
||||
padding: 5rem;
|
||||
}
|
||||
|
||||
.goods {
|
||||
width: 50%;
|
||||
box-sizing: border-box;
|
||||
padding: 5rem;
|
||||
margin-bottom: 10rem;
|
||||
|
||||
.item {
|
||||
border-radius: 8rem;
|
||||
|
||||
@@ -13,106 +13,105 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Scroll class="Scroll"
|
||||
fixedHeight="100"
|
||||
@fixed="e=>state.fixed = e"
|
||||
@pulldown="loadData">
|
||||
<div class="wrapper">
|
||||
<div class="card">
|
||||
<div class="options">
|
||||
<div class="option" @click="$no">
|
||||
<Icon icon="lets-icons:order-light"/>
|
||||
<div>我的订单</div>
|
||||
</div>
|
||||
<div class="option" @click="$no">
|
||||
<Icon icon="material-symbols-light:charging-station-outline"/>
|
||||
<div>手机充值</div>
|
||||
</div>
|
||||
<div class="option" @click="$no">
|
||||
<Icon icon="lucide:message-square-quote"/>
|
||||
<div>购物消息</div>
|
||||
</div>
|
||||
<div class="option" @click="$no">
|
||||
<Icon icon="fluent:location-16-regular"/>
|
||||
<div>小时达</div>
|
||||
</div>
|
||||
<div class="option" @click="$no">
|
||||
<Icon icon="ri:refund-2-fill"/>
|
||||
<div>退款/售后</div>
|
||||
</div>
|
||||
<div class="option" @click="$no">
|
||||
<Icon icon="icon-park-outline:clothes-turtleneck"/>
|
||||
<div>潮流服饰</div>
|
||||
<ScrollList
|
||||
class="Scroll"
|
||||
:api="recommendedShop"
|
||||
>
|
||||
<template v-slot="{list}">
|
||||
<div class="top-card">
|
||||
<div class="card">
|
||||
<div class="options">
|
||||
<div class="option" @click="$no">
|
||||
<Icon icon="lets-icons:order-light"/>
|
||||
<div>我的订单</div>
|
||||
</div>
|
||||
<div class="option" @click="$no">
|
||||
<Icon icon="material-symbols-light:charging-station-outline"/>
|
||||
<div>手机充值</div>
|
||||
</div>
|
||||
<div class="option" @click="$no">
|
||||
<Icon icon="system-uicons:message" />
|
||||
<div>购物消息</div>
|
||||
</div>
|
||||
<div class="option" @click="$no">
|
||||
<Icon icon="fluent:location-16-regular"/>
|
||||
<div>小时达</div>
|
||||
</div>
|
||||
<div class="option" @click="$no">
|
||||
<Icon icon="dashicons:money-alt" />
|
||||
<div>退款/售后</div>
|
||||
</div>
|
||||
<div class="option" @click="$no">
|
||||
<Icon icon="icon-park-outline:clothes-turtleneck"/>
|
||||
<div>潮流服饰</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card" style="margin-bottom: 5rem;">
|
||||
<div class="baiyibutie">
|
||||
<div class="item">
|
||||
<img src="@/assets/img/icon/shop/baiyibutie.png" alt="">
|
||||
<span>38节补贴</span>
|
||||
</div>
|
||||
<div class="item">
|
||||
<img src="@/assets/img/icon/shop/1.webp" alt="">
|
||||
<span class="price">
|
||||
<div class="card" style="margin-bottom: 5rem;">
|
||||
<div class="baiyibutie">
|
||||
<div class="item">
|
||||
<img src="@/assets/img/icon/shop/baiyibutie.png" alt="">
|
||||
<span>38节补贴</span>
|
||||
</div>
|
||||
<div class="item">
|
||||
<img src="@/assets/img/icon/shop/1.webp" alt="">
|
||||
<span class="price">
|
||||
<span class="m">¥</span>
|
||||
<span>470</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="item">
|
||||
<img src="@/assets/img/icon/shop/2.webp" alt="">
|
||||
<span class="price">
|
||||
</div>
|
||||
<div class="item">
|
||||
<img src="@/assets/img/icon/shop/2.webp" alt="">
|
||||
<span class="price">
|
||||
<span class="m">¥</span>
|
||||
<span>699</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="item">
|
||||
<img src="@/assets/img/icon/shop/3.png" alt="">
|
||||
<span class="price">
|
||||
</div>
|
||||
<div class="item">
|
||||
<img src="@/assets/img/icon/shop/3.png" alt="">
|
||||
<span class="price">
|
||||
<span class="m">¥</span>
|
||||
<span>8.8</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="item">
|
||||
<img src="@/assets/img/icon/shop/4.jpg" alt="">
|
||||
<span class="price">
|
||||
</div>
|
||||
<div class="item">
|
||||
<img src="@/assets/img/icon/shop/4.jpg" alt="">
|
||||
<span class="price">
|
||||
<span class="m">¥</span>
|
||||
<span>2.99</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-masonry class="goods-list"
|
||||
:class="{fixed:state.fixed}"
|
||||
transition-duration="0s"
|
||||
item-selector=".goods">
|
||||
<div v-masonry-tile class="goods"
|
||||
@click="nav('/shop/detail')"
|
||||
v-for="(item, index) in state.list">
|
||||
<div class="item">
|
||||
<img class="poster" :src="Utils.$imgPreview(item.cover)"/>
|
||||
<div class="bottom">
|
||||
<div class="desc">
|
||||
{{ item.name }}
|
||||
</div>
|
||||
<div class="discounts" v-if="item.discount">{{ item.discount }}</div>
|
||||
<div class="info">
|
||||
<div class="price">
|
||||
¥
|
||||
<div class="big">{{ item.price }}</div>
|
||||
<WaterfallList :list="list">
|
||||
<template v-slot="{item}">
|
||||
<div class="goods"
|
||||
@click="nav('/shop/detail',{},item)">
|
||||
<div class="item">
|
||||
<img class="poster" v-lazy="_checkImgUrl('goods/'+item.cover)"/>
|
||||
<div class="bottom">
|
||||
<div class="desc">
|
||||
{{ item.name }}
|
||||
</div>
|
||||
<div class="discounts" v-if="item.discount">{{ item.discount }}</div>
|
||||
<div class="info">
|
||||
<div class="price">
|
||||
¥
|
||||
<div class="big">{{ item.price }}</div>
|
||||
</div>
|
||||
<div class="num">已售{{ item.sold }}件</div>
|
||||
</div>
|
||||
<div class="low" v-if="item.isLowPrice">
|
||||
近30天低价
|
||||
</div>
|
||||
</div>
|
||||
<div class="num">已售{{ item.sold }}件</div>
|
||||
</div>
|
||||
<div class="low" v-if="item.isLowPrice">
|
||||
近30天低价
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Scroll>
|
||||
</template>
|
||||
</WaterfallList>
|
||||
</template>
|
||||
</ScrollList>
|
||||
<Footer v-bind:init-tab="2"
|
||||
:is-white="true"
|
||||
style="position: fixed;left: 0;"/>
|
||||
@@ -124,9 +123,10 @@
|
||||
|
||||
import {onMounted, reactive} from "vue";
|
||||
import {useNav} from "@/utils/hooks/useNav";
|
||||
import Utils, {$no} from "@/utils";
|
||||
import Scroll from "@/components/Scroll.vue";
|
||||
import goods from "@/assets/data/goods";
|
||||
import {$no, _checkImgUrl} from "@/utils";
|
||||
import ScrollList from "@/components/ScrollList.vue";
|
||||
import {recommendedShop} from "@/api/user";
|
||||
import WaterfallList from "@/components/WaterfallList.vue";
|
||||
|
||||
defineOptions({
|
||||
name: 'Shop'
|
||||
@@ -134,15 +134,10 @@ defineOptions({
|
||||
|
||||
const nav = useNav()
|
||||
const state = reactive({
|
||||
list: goods.list,
|
||||
listEl: null,
|
||||
fixed: false
|
||||
})
|
||||
|
||||
function loadData() {
|
||||
console.log('loadData')
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
})
|
||||
</script>
|
||||
@@ -155,13 +150,11 @@ onMounted(() => {
|
||||
#Shop {
|
||||
font-size: 14rem;
|
||||
position: relative;
|
||||
background: @fColor;
|
||||
background: #f1f1f1;
|
||||
padding: 10rem 5rem;
|
||||
background: #f8f8f8;
|
||||
padding: 10rem;
|
||||
color: black;
|
||||
|
||||
.wrapper {
|
||||
padding: 0 5rem;
|
||||
}
|
||||
|
||||
.search {
|
||||
@@ -174,12 +167,13 @@ onMounted(() => {
|
||||
margin-bottom: 10rem;
|
||||
|
||||
svg {
|
||||
font-size: 22rem;
|
||||
color: gray;
|
||||
font-size: 20rem;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
border: 1rem solid rgb(140, 48, 74);
|
||||
border-radius: 8rem;
|
||||
border: 2rem solid red;
|
||||
border-radius: 12rem;
|
||||
height: 100%;
|
||||
padding: 0 10rem;
|
||||
padding-right: 3rem;
|
||||
@@ -200,7 +194,7 @@ onMounted(() => {
|
||||
background: rgb(242, 62, 92);
|
||||
padding: 0 10rem;
|
||||
height: 85%;
|
||||
border-radius: 6rem;
|
||||
border-radius: 10rem;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
@@ -284,16 +278,15 @@ onMounted(() => {
|
||||
background: @fColor;
|
||||
}
|
||||
|
||||
@p: 5rem;
|
||||
|
||||
.goods-list {
|
||||
padding-bottom: 20rem;
|
||||
.top-card {
|
||||
margin-bottom: 10rem;
|
||||
}
|
||||
|
||||
@p: 5rem;
|
||||
|
||||
.goods {
|
||||
width: 50%;
|
||||
box-sizing: border-box;
|
||||
padding: 5rem;
|
||||
margin-bottom: 10rem;
|
||||
|
||||
.item {
|
||||
border-radius: 8rem;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import Home from "../pages/home";
|
||||
import Test from "../pages/test/Test";
|
||||
import Test4 from "../pages/test/Test4";
|
||||
import GoodsDetail from "@/pages/shop/GoodsDetail.vue";
|
||||
|
||||
const routes = [
|
||||
// {path: '/', redirect: '/attention'},
|
||||
@@ -93,7 +92,7 @@ const routes = [
|
||||
{path: '/message/share-to-friend', component: () => import('@/pages/message/Share2Friend.vue')},
|
||||
|
||||
{path: '/video-detail', name: 'video-detail', component: () => import('@/pages/other/VideoDetail.vue')},
|
||||
{path: '/album-detail', component: () => import('@/pages/other/AlbumDetail.vue')},
|
||||
// {path: '/album-detail', component: () => import('@/pages/other/AlbumDetail.vue')},
|
||||
|
||||
{path: '/home/search', component: () => import('@/pages/home/SearchPage.vue')},
|
||||
|
||||
|
||||