初始化中

This commit is contained in:
abu 2025-03-18 16:49:28 +08:00
parent fc1fd22662
commit b4965d0068
19 changed files with 3170 additions and 562 deletions

View File

@ -14,7 +14,7 @@
import provinceList from "./json/area_province.js";
import cityList from "./json/area_city.js";
import districtList from "./json/area_district.js";
import storage from "@/utils/storage.js"; //
export default {
data() {
return {
@ -82,7 +82,7 @@
uni.onTabBarMidButtonTap(() => {
console.log('center')
//
let myUserInfo = null
let myUserInfo = storage.getVlogUserInfo()||null;
if (myUserInfo == null) {
uni.navigateTo({
// url: "../loginRegist/loginRegist",

464
README.md
View File

@ -1,218 +1,276 @@
## 🔥 Lilishop B2B2C商城系统
## 插件说明
##### 🌹 开源不易如有帮助请点Star
> 这是 `v-tabs` 插件的升级版本,参数上有很大变动,支持 `H5` `小程序` `手机端`,如果是在之前的插件上升级的话,请注意参数的变更,触发的事件没有变更。
## 使用说明
### 1、最基本用法
#### 欢迎交流需求,交流业务,交流技术(基础问题自行解决,进群先看文档后提问)
- 视图文件
##### 交流 qq 1群 961316482已满
##### 交流 qq 2群 875294241
##### 商城 公众号/小程序体验,扫描二维码
![image-20210511171611793](https://pickmall.cn/assets/imgs/h5-qrcode.png)
[![star](https://gitee.com/beijing_hongye_huicheng/lilishop/badge/star.svg?theme=dark)](https://gitee.com/beijing_hongye_huicheng/lilishop/stargazers)
  ![github](https://img.shields.io/github/stars/hongyehuicheng/lilishop.svg?style=social&logo=#181717)
### 🔥 商城介绍
**官网**https://pickmall.cn
Lilishop 商城系统 基于SpringBoot 研发B2B2C多用户商城系统前端使用 Vue、uniapp开发 **系统全端全部代码开源**
业务兼容O2O商城/B2B商城/B2B2C商城/F2B2C商城/S2B2C商城。支持小程序商城、H5商城、APP商城、 PC商城。
商城前后端分离、支持分布式部署。
商城包含 会员模块、**第三方登录模块**、**第三方支付模块**、**楼层装修模块**、订单模块、分销模块、文章模块、系统设置模块、流量分析模块
商城包含各种中间件、搜索引擎、多级缓存、分布式事务、分布式任务调度等支持Docker支持k8s。是一款高性能支持高并发的商城系统。
##### 商城 API/消费者 聚合版
api不需要单独部署只需启动一个jar包就可以正常运转 如有需要可以点击跳转https://gitee.com/beijing_hongye_huicheng/lilishop-simplify
### ☃️ 商城 开发/使用/常见问题 帮助文档
https://docs.pickmall.cn
### 💧 开源商城项目地址(gitee)
**API商城所有API**https://gitee.com/beijing_hongye_huicheng/lilishop.git
**UI商城管理端/商家端/买家PC端** https://gitee.com/beijing_hongye_huicheng/lilishop-ui.git
**uniapp商城移动端支持小程序/APP/H5**https://gitee.com/beijing_hongye_huicheng/lilishop-uniapp.git
**docker一键部署商城部署脚本**https://gitee.com/beijing_hongye_huicheng/docker.git
### 💧 开源商城项目地址(github)
**API商城所有API**https://github.com/hongyehuicheng/lilishop.git
**UI商城管理端/商家端/买家PC端** https://github.com/hongyehuicheng/lilishop-ui.git
**uniapp商城移动端支持小程序/APP/H5**https://github.com/hongyehuicheng/lilishop-uniapp.git
**docker一键部署商城部署脚本**https://github.com/hongyehuicheng/docker.git
☃️ UI 项目下3个文件夹 buyer买家PC端seller商家端manager后台管理端
### 💧 演示地址(手机验证码为 111111)
**商城管理端**https://admin-b2b2c.pickmall.cn 账号admin/123456
**商城店铺后台**https://store-b2b2c.pickmall.cn 账号13011111111/111111
**商城PC页面**https://pc-b2b2c.pickmall.cn
**商城移动端(请使浏览器手机模式,或者用手机浏览器打开)**https://m-b2b2c.pickmall.cn
**小程序/公众号**:扫描二维码
![image-20210511171611793](https://pickmall.cn/assets/imgs/h5-qrcode.png)
### 🚙 3行命令搭建本地商城只能本机访问如需调整请自行操作镜像
温馨提示由于服务中间件较多如果笔记本环境启动内存没有32g可能无法启动成功macbookpro 2020 16g内存启动无法成功台式机在16g内存、AMD 3700x 的ubuntu系统成功运行。
##### docker环境安装 [点击跳转](https://docs.pickmall.cn/deploy/%E8%BF%90%E8%A1%8C%E7%8E%AF%E5%A2%83%E5%87%86%E5%A4%87.html)
##### 下载docker-compose脚本
`git clone https://gitee.com/beijing_hongye_huicheng/docker.git `
##### 部署商城所需中间件
`docker-compose up -d`
##### 部署商城应用
`docker-compose -f docker-compose-application.yml up -d`
PS:商城数据库单独部署 https://gitee.com/beijing_hongye_huicheng/docker/tree/master/init/mysql 这里有与tag版本一致的sql根据tag获取sql如果使用master代码则需要在lilishop项目根目录的DB目录中获取对应的升级sql。
##### 商城 API/UI 地址
| API | 地址 |
| -------------- | --------------- |
| 商城买家API | http://127.0.0.1:8888 |
| 商城商家API | http://127.0.0.1:8889 |
| 商城管理端API | http://127.0.0.1:8887 |
| 商城基础API | http://127.0.0.1:8890 |
| 前端演示 | 地址 |
| -------------- | --------------- |
| 商城PC端 | http://127.0.0.1:10000 |
| 商城WAP端 | http://127.0.0.1:10001 |
| 商城卖家端 | http://127.0.0.1:10002 |
| 商城管理端 | http://127.0.0.1:10003 |
### ⚾️ 功能列表
#### 🥎 商城平台功能
![平台功能](https://pickmall.cn/assets/imgs/other/managerList.jpg)
#### 🥎 商城卖家功能
![商家端功能](https://pickmall.cn/assets/imgs/other/storeList.jpg)
### 🧩 商城前端功能展示
#### ⚽️ 商城移动端
<img src="https://pickmall.cn/assets/imgs/other/app.gif" alt="移动端功能展示" style="zoom:50%;" />
#### ⚽️ 商城管理端
![管理端功能展示](https://pickmall.cn/assets/imgs/other/manager.gif)
### 商城技术选型
#### 🥅 架构图
![架构](https://lili-system.oss-cn-beijing.aliyuncs.com/docs/%E6%9E%B6%E6%9E%84.png)
##### 🕹 后台技术选型
| 说明 | 框架 | 说明 | |
| -------------- | --------------- | -------------- | ------------- |
| 基础框架 | Spring Boot | MVC框架 | Spring MVC |
| 持久框架 | Mybatis-Plus | 程序构建 | Maven |
| 关系型数据库 | MySQL | 消息中间件AMQP | RocketMQ |
| 缓存 | Redis +MongoDB | 搜索引擎 | Elasticsearch |
| 安全框架 | Spring Security | 数据库连接池 | Druid |
| 数据库分库分表 | sharding | 定时任务 | xxl-job |
| 负载均衡 | Nginx | 静态资源 | 阿里云OSS |
| 短信 | 阿里云短信 | 认证 | JWT |
| 日志处理 | Log4j | 接口规范 | RESTful |
##### 🖥 前端-运营后台、店铺后台
| 说明 | 框架 | 说明 | 框架 |
| ---------- | ---------- | ---------- | ------- |
| 构建工具 | webpack | JS版本 | ES6 |
| 基础JS框架 | Vue.js | 视频播放器 | Dplayer |
| 路由管理 | Vue Router | 状态管理 | Vuex |
| 基础UI库 | iView | UI界面基于 | iView |
| 网络请求 | axios | | |
##### 📱前端-移动端
| 说明 | 架构 | 说明 | 架构 |
| --------- | ------- | -------- | ------- |
| 基础UI库 | uViewui | 基础框架 | uni-app |
| CSS预处理 | scss | 地图引擎 | amap |
### 🌟 版本升级
```
商城后续会持续版本升级修复bug完善功能覆盖更多业务场景 o2o/b2b/s2b2b2c/跨境电商
后续会考虑推出微服务商城系统/商城中台等
```html
<v-tabs v-model="current" :tabs="tabs" @change="changeTab"></v-tabs>
```
- 脚本文件
### ⚠️ 开源须知
1.仅允许用于个人学习研究使用.
```js
export default {
data() {
return {
current: 0,
tabs: ['军事', '国内', '新闻新闻', '军事', '国内', '新闻', '军事', '国内', '新闻']
}
},
methods: {
changeTab(index) {
console.log('当前选中的项:' + index)
}
}
}
```
2.禁止将本开源的代码和资源进行任何形式任何名义的出售.
### 2、平铺整个屏幕
3.软件受国家计算机软件著作权保护登记号2021SR0805085
- 视图文件
4.限制商用如果需要商业使用请联系我们。QQ3409056806.
```html
<v-tabs v-model="activeTab" :scroll="false" :tabs="['全部', '进行中', '已完成']"></v-tabs>
```
- 脚本文件
### 🐧 交流群
```js
export default {
data() {
return {
activeTab: 0
}
}
}
```
##### 官方qq 1群 961316482已满
##### 官方qq 2群 875294241
### 3、胶囊用法
- 视图文件
```html
<v-tabs v-model="current" :tabs="tabs" :pills="true" line-height="0" activeColor="#fff" @change="changeTab"></v-tabs>
```
- 脚本文件
```js
data() {
return {
current: 2,
tabs: [
'军事',
'国内',
'新闻新闻',
'军事',
'国内',
'新闻',
'军事',
'国内',
'新闻',
],
},
methods: {
changeTab(index) {
console.log('当前选中索引:' + index)
}
}
}
```
## 文档说明
### 1、属性说明
| 参数 | 类型 | 默认值 | 说明 |
| :---------------: | :-----: | :-------: | :-----------------------------------------------------------------------: |
| tabs | Array | [] | 控制 tab 的列表 |
| value | Number | 0 | 必传(双向绑定的值) |
| color | String | '#333' | 默认文字颜色 |
| activeColor | String | '#2979ff' | 选中文字的颜色 |
| fontSize | String | '28rpx' | 默认文字大小(rpx 或 px)(弃用) |
| bold | Boolean | true | 是否加粗选中项 |
| scroll | Boolean | true | 是否显示滚动条,平铺设置 false |
| height | String | '70rpx' | tab 高度(rpx 或 px) |
| lineHeight | String | '10rpx' | 滑块高度(rpx 或 px) |
| lineColor | String | '#2979ff' | 滑块的颜色 |
| lineScale | Number | 0.5 | 滑块宽度缩放值 |
| lineRadius | String | '10rpx' | 滑块圆角宽度(rpx 或 px) |
| pills | Boolean | false | 是否开启胶囊 |
| pillsColor | String | '#2979ff' | 胶囊背景颜色(rpx 或 px) |
| pillsBorderRadius | String | '10rpx' | 胶囊圆角宽度(rpx 或 px) |
| field | String | '' | 如果 tabs 子项是对象,输入需要展示的键名 |
| bgColor | String | '#fff' | 背景色,支持 linear-gradient 渐变 |
| padding | String | '0' | 整个 tab padding 属性 |
| fixed | Boolean | false | 是否固定在顶部 |
| paddingItem | String | '0 22rpx' | 选项的边距(设置上下不生效,需要设置高度) |
| lineAnimation | Boolean | true | 是否需要 line 和 pills 的动画,在隐藏页面后默认移动到第一个的时候比较实用 |
| zIndex | Number | 1993 | 控制 tab 的层级默认1993 |
### 1.1 `tabs`参数展开说明
#### 1.1.1 当`tabs`仅仅是单纯的数组时候,没有什么特别的地方
```js
export default {
data() {
return {
tabs: ['全部', '待付款', '待消费', '已完成', '已评价', '已过期', '已退款']
}
}
}
```
#### 1.1.2 当`tabs`使用的数组对象的方式,特定参数需要注意一下
- `disabled` 参数,可以控制按钮是否可以点击
```js
export default {
data() {
return {
tabs: [
{ id: 1, name: '待付款', disabled: false },
{ id: 2, name: '待收货', disabled: false },
{ id: 3, name: '待评价', disabled: false },
{ id: 4, name: '退款/售后', disabled: true },
{ id: 5, name: '我的订单', disabled: false }
]
}
}
}
```
### 2、事件说明
| 名称 | 参数 | 说明 |
| :----: | :---: | :--------------------------------: |
| change | index | 改变选中项触发, index 选中项的下标 |
## 更新日志
### 2.2.22024-12-10
1. [修复]修复`change`事件不生效的bug
### 2.2.12024-11-13
1. [修复]修复摇树打包出现的bug
### 2.2.02024-07-19
1. [修改]增加节流函数控制tab的点击间隔
### 2.1.92024-06-14
1. [修改]当`current`初始值大于`tabs.length`或者小于`0`,自动设置`current`的值为`0`
2. [抛弃]压缩包方式的源码不提供维护了,只维护`uni_modules`中的源码
### 2.1.82024-06-06
1. [新增]支持`vue3`
### 2.1.62024-06-06
1. [修复]使用`fixed`属性之后在支付宝小程序无法滚动的bug
### 2.1.52023-11-02
1. [修复]修复`change``v-model`绑定的值不同步
2. [修复]暂时停用`activeFontSize`选项
3. [修改]修改默认激活的文字不加粗
### 2.1.42023-10-12
1. [修改]修改计算方式
2. [新增]外部可以通过`this.$refs.tabs.update()`方法主动更新
### 2.1.32023-09-11
1. [新增]支持自定义插槽模式,具体可以查看示例代码使用方式。[gitee demo](https://github.com/xfjpeter/uni-plugins/blob/master/pages/tabs/tabs.vue#L47-L50) 或 [github demo](https://github.com/xfjpeter/uni-plugins/blob/master/pages/tabs/tabs.vue#L47-L50)
### 2.1.22023-06-12
1. [新增]添加`z-index`参数控制层级大小默认1993
2. [说明]以后该插件只更新`uni_modules`方式的,`zip`方式的不提供更新了,如果需要的请到 [gitee uni-plugins](https://gitee.com/xfjpeter/uni-plugins) 或 [github uni-plugins](https://github.com/xfjpeter/uni-plugins)下载源码,自行使用
### 2.1.12022-09-16
1. 将插件更新为`uni_modules`方式
### 2022-08-12
1. 增加`disable`参数,控制是否可以点击,只能应用在数组对象中,见[disabled 的用法](#112-当tabs使用的数组对象的方式特定参数需要注意一下)
```js
export default {
data() {
return {
tabs: [{ id: 1, name: '' }]
}
}
}
```
### 2022-01-27
1. 更新属性`line-animation`设置为`false`可以不要动画,这是好多朋友问到,特此加上
### 2020-09-24
1. 修复 `v-tabs` 第一次可能出现第一个标签显示不完整的情况
2. 修改了 `pages/tabs/order` 示例文件
### 2020-09-21
1. 修复添加 `fixed` 属性后,滚动条无效
2. 修复选项很少的情况下,下划线计算计算错误
3. 新增 `paddingItem` 属性,设置选项左右边距(上下边距需要设置 `height` 属性,或者设置 `padding` 属性)
**写在最后:**
欢迎各位老铁反馈 bug ,本人后端 PHP 一枚,只是应为感兴趣前端,自己琢磨,自己搞。如果你在使用的过程中有什么不合理,需要优化的,都可以在下面评论(或加我 QQ: 1207791534本人看见后回复、修正感谢。
### 2020-09-17
1. 紧急修复 bug横向滑动不了的情况
### 2020-09-16
1. 新增 `fixed` 属性,是否固定在顶部,示例地址:`pages/tabs/tabs-static`
2. 优化之前的页面结构
**注意:**
1. 使用 `padding` 属性的时候,尽量不要左右边距,会导致下划线位置不对
2. 如果不绑定 `v-model` 会导致 `change` 事件改变的时候,下划线不跟随问题
### 2020-09-09
1. 修复 `width` 错误dom 加载的时候没有及时获取到 `data` 属性导致的。
### 2020-08-29
1. 优化异步改变 `tabs` 后,下划线不初始化问题
2. `github` 地址上有图 2 的源码,需要的自行下载,页面路径:`pages/tabs/order`
### 2020-08-20
1. 优化 `节点查询``选中渲染`
2. 优化支付宝中 `createSelectorQuery()` 的影响
### 2020-08-19
1. 优化 `change` 事件触发机制
### 2020-08-16
1. 修改默认高度为 `70rpx`
2. 新增属性 `bgColor`,可设置背景颜色,默认 `#fff`
3. 新增整个 `tab``padding` 属性,默认 `0`
### 2020-08-13
1. 全新的 `v-tabs 2.0`
2. 支持 `H5` `小程序` `APP`
3. 属性高度可配置
## 预览
![v-tabs 2.0.1.gif](https://tva1.sinaimg.cn/large/007S8ZIlgy1ghsv40mj76g30ai0i2tsd.gif)
![v-tabs 2.0.2.gif](https://img-cdn-aliyun.dcloud.net.cn/stream/plugin_screens/42f3a920-a674-11ea-8a24-ffee00625e2e_1.png?v=1597912963)

View File

@ -73,7 +73,7 @@ export function getLogisticsMessages(params) {
*/
export function getAppVersion(appType) {
return http.request({
url: `/appVersion/${appType}`,
url: `/other/appVersion/${appType}`,
method: Method.GET,
type:"manager"
});
@ -86,7 +86,7 @@ export function getLogisticsMessages(params) {
*/
export function getAppVersionList(type,data) {
return http.request({
url: `/appVersion/appVersion/${type}`,
url: `/other/appVersion/appVersion/${type}`,
method: Method.GET,
type:"manager",
data

View File

@ -8,8 +8,9 @@ import api from "@/config/api.js";
/**
* 短视频列表
* 短视频列表-true
*/
export function vlogList(page, pageSize) {
return http.request({

149
changelog.md Normal file
View File

@ -0,0 +1,149 @@
## 2.2.22024-12-10
1. [修复]修复`change`事件不生效的bug
## 2.2.12024-11-13
1. [修复]修复摇树打包出现的bug
## 2.2.02024-07-19
1. [修改]增加节流函数控制tab的点击间隔
## 2.1.92024-06-14
1. [修改]当`current`初始值大于`tabs.length`或者小于`0`,自动设置`current`的值为`0`
2. [抛弃]压缩包方式的源码不提供维护了,只维护`uni_modules`中的源码
## 2.1.82024-06-07
1. [新增]支持`vue3`
## 2.1.62024-06-06
1. [修复]当有`fixed`属性之后在支付宝小程序无法滚动的bug
## 2.1.52023-11-02
1. [修复]修复`change``v-model`绑定的值不同步
2. [修复]暂时停用`activeFontSize`选项
3. [修改]修改默认激活的文字不加粗
## 2.1.42023-10-12
1. [修改]修改计算方式
2. [新增]外部可以通过`this.$refs.tabs.update()`方法主动更新
## 2.1.32023-09-11
1. [新增]支持自定义插槽模式,具体可以查看示例代码使用方式。[gitee demo](https://github.com/xfjpeter/uni-plugins/blob/3e2bd062163f664889122fd74b8bd6ccad6a97f1/pages/tabs/tabs.vue#L47C10-L50C16) 或 [github demo](https://github.com/xfjpeter/uni-plugins/blob/3e2bd062163f664889122fd74b8bd6ccad6a97f1/pages/tabs/tabs.vue#L47C10-L50C16)
## 2.1.22023-06-12
1. [新增]添加`z-index`参数控制层级大小默认1993
2. [说明]以后该插件只更新`uni_modules`方式的,`zip`方式的不提供更新了
## 2.1.12022-09-16
1. 将插件更新为`uni_modules`方式
## 2.1.02022-08-12
1. 增加`disable`参数,控制是否可以点击,只能应用在数组对象中,见[disabled 的用法](#112-当tabs使用的数组对象的方式特定参数需要注意一下)
```js
export default {
data() {
return {
tabs: [{ id: 1, name: '' }]
}
}
}
```
## 2.0.102022-01-27
1. 更新属性line-animation设置为false可以不要动画这是好多朋友问到特此加上
## 2.0.92020-10-12
1. 修复 v-tabs 第一次可能出现第一个标签显示不完整的情况
2. 修改了 pages/tabs/order 示例文件
## 2.0.82020-09-21
1. 修复添加 fixed 属性后,滚动条无效
2. 修复选项很少的情况下,下划线计算计算错误
3. 新增 paddingItem 属性,设置选项左右边距(上下边距需要设置 height 属性,或者设置 padding 属性)
## 2.0.72020-09-17
1. 紧急修复 bug横向滑动不了的情况
## 2.0.62020-09-16
1. 新增 fixed 属性是否固定在顶部示例地址pages/tabs/tabs-static
2. 优化之前的页面结构
## 2.0.52020-09-09
1. 修复 width 错误dom 加载的时候没有及时获取到 data 属性导致的 。
## 2.0.42020-08-29
1. 优化异步改变 tabs 后,下划线不初始化问题
2. github 地址上有图 2 的源码需要的自行下载页面路径pages/tabs/order.vue
## 2.0.32020-08-20
1. 优化 节点查询 和 选中渲染
2. 优化支付宝中 createSelectorQuery() 的影响
**特别说明:**
> 支付宝中平铺方法和其他方法不能在一个页面中出现,不然有一个显示错误(具体什么原因没查到,有好心的人发现了,望告知一下,感谢
## 2.0.22020-08-19
1. 优化 change 事件触发机制
## 2.0.12020-08-16
1. 修改默认高度为 70rpx
2. 新增属性 bgColor可设置背景颜色默认 #fff
3. 新增整个 tab 的 padding 属性,默认 0
## 2.0.02020-08-13
1. 全新的 v-tabs 2.0
2. 支持 H5 小程序 APP
3. 属性高度可配置
## 1.3.22020-07-21
1. 新增 auto 的配置,是否平铺 tab
2. 修复文档上的错误示例(感谢 lushgwe@163.com 的反馈)
## 1.3.02020-07-05
1. 新增 padding 的可配置
2. 修复 v-model 双向绑定问题
3. 修复初始化下划线没定位的为题
## 1.2.02020-06-19
1. 添加注释
2. 修复 bug
## 1.1.82020-06-11
1. 添加 change 事件
2. 修复插件内容问题
3. 修复下划线不居中问题
## 1.1.62020-06-11
1. 添加 change 事件
2. 修复插件内容问题
## 1.1.42020-06-11
1. 添加 change 事件
2. 修复插件内容问题
## 1.1.22020-06-11
1. 添加 change 事件
## 1.1.12020-06-09
1. 修复小程序端选中的下划线不显示问题
2. 新增 tab 高度设置
3. lineHeight 修改为只支持 String 方式
## 1.1.02020-06-09
1. 修复小程序端选中的下划线不显示问题
2. 新增 tab 高度设置
3. lineHeight 修改为只支持 String 方式
## 1.0.02020-06-04
1. 更新插件1.0.0

View File

@ -1,7 +1,7 @@
<template>
<view style="flex: 1">
<!-- <uni-list @change="onchange" :num="playerList.length"> -->
<list :pagingEnabled="true" :show-scrollbar="false" @scroll="listScroll" @scrollend="scroll" :scrollable="true">
<list ref="list" :pagingEnabled="true" :show-scrollbar="false" @scroll="listScroll" @scrollend="scroll" :scrollable="true">
<refresh @pullingdown="onpullingdown" @refresh="onrefresh" :display="refreshing ? 'show' : 'hide'">
<text class="refresh-info-txt"></text>
<loading-indicator></loading-indicator>
@ -116,7 +116,16 @@
},
pagingList: {
default: [],
},
},
//
pid: {
type: [Number, String],
default: ''
},
parentId: {
type: String,
default: ''
}
},
data() {
return {
@ -131,7 +140,8 @@
playerCur: 0,
page: 0,
totalPage: 0,
playerList: this.videoList,
playerList: [],
// playerList: this.videoList,
thisVlogTotalComentCounts: 0,
videoContext: {},
@ -187,7 +197,25 @@
}
},
},
methods: {
methods: {
//------------addd
setScrollRef(height) {
if (this.$refs['list'].setSpecialEffects) {
this.$refs['list'].setSpecialEffects({
id: this.parentId,
headerHeight: height
});
}
},
loadData() {
// 首次激活时被调用
this.displayVideoPaging(this.page + 1, true);
},
clear() {
// 释放数据时被调用,参考 swiper-list 缓存配置
this.playerList.length = 0;
},
//---------------------------------
// 把超过1000或10000的数字调整比如1.3k/6.8w
getGraceNumber(num) {
return graceNumber(num);
@ -352,13 +380,13 @@
// 查看用户详情
goUserInfoSeeSee(userId) {
uni.setStorageSync("userPageId", userId);
const info = storage.getVlogUserInfo()
const info = storage.getVlogUserInfo()||null
// 是否是当前登录的用户
let myUserId = "";
if (info) {
if (info==null) {
myUserId = info.id;
}
if (myUserId == userId) {
if (myUserId == userId) {
uni.switchTab({
url: "/pages/me/me",
});

View File

@ -104,7 +104,7 @@
<template>
<view style="flex: 1;">
<!-- <uni-list @change="onchange" :num="playerList.length"> -->
<list :pagingEnabled="true" :show-scrollbar="false" @scroll="listScroll" @scrollend="scroll" :scrollable="true" >
<list ref="list" :pagingEnabled="true" :show-scrollbar="false" @scroll="listScroll" @scrollend="scroll" :scrollable="true" >
<refresh @pullingdown="onpullingdown" @refresh="onrefresh" :display="refreshing ? 'show' : 'hide'">
<text class="refresh-info-txt"></text>
<loading-indicator></loading-indicator>
@ -248,7 +248,8 @@
playerCur: 0,
page: 0,
totalPage: 0,
playerList: this.videoList,
// playerList: this.videoList,
playerList: [],
thisVlogTotalComentCounts: 0,
videoContext: {},
@ -298,6 +299,24 @@
}
},
methods: {
//------------addd
setScrollRef(height) {
if (this.$refs['list'].setSpecialEffects) {
this.$refs['list'].setSpecialEffects({
id: this.parentId,
headerHeight: height
});
}
},
loadData() {
// 首次激活时被调用
this.displayVideoPaging(this.page + 1, true);
},
clear() {
// 释放数据时被调用,参考 swiper-list 缓存配置
this.playerList.length = 0;
},
//---------------------------------
freshCommentCounts() {
var me = this;
var userId = getApp().getUserInfoSession().id;

View File

@ -27,7 +27,7 @@ Object.keys(filters).forEach((key) => {
// 引入Vuex
Vue.prototype.$store = store;
Vue.use(uView);
Vue.use(uView);
Vue.config.productionTip = false;

18
package.json Normal file
View File

@ -0,0 +1,18 @@
{
"id": "ir-tabs",
"name": "ir-tabs tabs tab选项卡组件",
"version": "1.0.3",
"description": "用于展示同一页面不同标题下内容可通过左右滑动和点击tab的方式切换页面支持自定义颜色、下拉刷新",
"keywords": [
"tab",
"tabs",
"选项卡",
"导航栏"
],
"dcloudext": {
"category": [
"前端组件",
"通用组件"
]
}
}

View File

@ -86,7 +86,257 @@
"style": {
}
}
},
{
"path" : "pages/publish/publish",
"style" : {
"navigationBarTitleText" : "发布视频",
"navigationBarBackgroundColor" : "#181b27",
"navigationBarTextStyle": "#FFFFFF"
}
},
{
"path" : "pages/publish/preview",
"style" : {
"navigationBarTitleText" : "预览视频",
"navigationBarBackgroundColor" : "#181b27",
"enablePullDownRefresh" : false
}
}
// {
// "path" : "pages/me/vlogerInfo",
// "style" : {
// "app-plus" : {
// "titleNView" : false //
// }
// }
// }
// {
// "path" : "pages/me/me",
// "style" : {
// "app-plus" : {
// "titleNView" : false //
// }
// }
// }
// {
// "path" : "pages/me/myBackImg",
// "style" : {
// "app-plus" : {
// "titleNView" : false //
// }
// }
// },
// {
// "path" : "pages/me/myFace",
// "style" : {
// "app-plus" : {
// "titleNView" : false //
// }
// }
// },
// {
// "path" : "pages/me/myInfo",
// "style" : {
// "navigationBarTitleText" : "修改个人资料",
// "navigationBarBackgroundColor" : "#181b27"
// }
// },
// {
// "path" : "pages/me/modifyNickname",
// "style" : {
// "navigationBarTitleText" : "修改昵称",
// "navigationBarTextStyle" : "white",
// "navigationBarBackgroundColor" : "#181b27",
// "app-plus" : {
// "titleNView" : {
// "buttons" : [
// {
// "text" : "保存",
// "color" : "#ef274d",
// "width" : "60px",
// "fontSize" : "15px",
// "fontWeight" : "bold"
// }
// ]
// }
// }
// }
// },
// {
// "path" : "pages/me/modifyPass",
// "style" : {
// "navigationBarTitleText" : "修改密码",
// "navigationBarTextStyle" : "white",
// "navigationBarBackgroundColor" : "#181b27",
// "app-plus" : {
// "titleNView" : {
// "buttons" : [
// {
// "text" : "保存",
// "color" : "#ef274d",
// "width" : "60px",
// "fontSize" : "15px",
// "fontWeight" : "bold"
// }
// ]
// }
// }
// }
// },
// {
// "path" : "pages/me/modifyTioktokNum",
// "style" : {
// "navigationBarTitleText" : "修改视频号",
// "navigationBarTextStyle" : "white",
// "navigationBarBackgroundColor" : "#181b27",
// "app-plus" : {
// "titleNView" : {
// "buttons" : [
// {
// "text" : "保存",
// "color" : "#ef274d",
// "width" : "60px",
// "fontSize" : "15px",
// "fontWeight" : "bold"
// }
// ]
// }
// }
// }
// },
// {
// "path" : "pages/me/modifyDesc",
// "style" : {
// "navigationBarTitleText" : "修改简介",
// "navigationBarTextStyle" : "white",
// "navigationBarBackgroundColor" : "#181b27",
// "app-plus" : {
// "titleNView" : {
// "buttons" : [
// {
// "text" : "保存",
// "color" : "#ef274d",
// "width" : "60px",
// "fontSize" : "15px",
// "fontWeight" : "bold"
// }
// ]
// }
// }
// }
// },
// {
// "path" : "pages/me/modifySex",
// "style" : {
// "navigationBarTitleText" : "修改性别",
// "navigationBarTextStyle" : "white",
// "navigationBarBackgroundColor" : "#181b27",
// "app-plus" : {
// "titleNView" : {
// "buttons" : [
// {
// "text" : "保存",
// "color" : "#ef274d",
// "width" : "60px",
// "fontSize" : "15px",
// "fontWeight" : "bold"
// }
// ]
// }
// }
// }
// },
// {
// "path" : "pages/me/modifyBirthday",
// "style" : {
// "navigationBarTitleText" : "修改生日",
// "navigationBarTextStyle" : "white",
// "navigationBarBackgroundColor" : "#181b27",
// "app-plus" : {
// "titleNView" : {
// "buttons" : [
// {
// "text" : "保存",
// "color" : "#ef274d",
// "width" : "60px",
// "fontSize" : "15px",
// "fontWeight" : "bold"
// }
// ]
// }
// }
// }
// },
// {
// "path" : "pages/me/modifyLocation",
// "style" : {
// "navigationBarTitleText" : "修改所在地",
// "navigationBarTextStyle" : "white",
// "navigationBarBackgroundColor" : "#181b27",
// "app-plus" : {
// "titleNView" : {
// "buttons" : [
// {
// "text" : "保存",
// "color" : "#ef274d",
// "width" : "60px",
// "fontSize" : "15px",
// "fontWeight" : "bold"
// }
// ]
// }
// }
// }
// },
// {
// "path" : "pages/me/chooseProvince",
// "style" : {
// "navigationBarTitleText" : "选择省份",
// "navigationBarTextStyle" : "white",
// "navigationBarBackgroundColor" : "#181b27"
// }
// },
// {
// "path" : "pages/me/chooseCity",
// "style" : {
// "navigationBarTitleText" : "选择城市",
// "navigationBarTextStyle" : "white",
// "navigationBarBackgroundColor" : "#181b27"
// }
// },
// {
// "path" : "pages/me/settings",
// "style" : {
// "navigationBarTitleText" : "设置",
// "navigationBarTextStyle" : "white",
// "navigationBarBackgroundColor" : "#181b27"
// }
// },
// {
// "path" : "pages/me/myFans",
// "style" : {
// "navigationBarTitleText" : "粉丝",
// "navigationBarTextStyle" : "white",
// "navigationBarBackgroundColor" : "#181b27"
// }
// },
// {
// "path" : "pages/me/myFollows",
// "style" : {
// "navigationBarTitleText" : "关注",
// "navigationBarTextStyle" : "white",
// "navigationBarBackgroundColor" : "#181b27"
// }
// },
// {
// "path" : "pages/me/chooseDistrict",
// "style" : {
// "navigationBarTitleText" : "选择地区",
// "navigationBarTextStyle" : "white",
// "navigationBarBackgroundColor" : "#181b27"
// }
// }
],
"subPackages": [

672
pages/me/me.nvue Executable file
View File

@ -0,0 +1,672 @@
<template>
<view class="page">
<!-- 未登录 -->
<view
v-if="!userIsLogin"
class="login-info-wrapper"
:style="{ height: screenHeightUnLogin + 'px' }"
@click="goLogin">
<text class="login-info">
{{ loginWords }}
</text>
</view>
<!-- 已登录 -->
<scroll-view
v-if="userIsLogin"
class="isLogin-info-wrapper"
:style="{ height: screenHeight + 'px' }"
scroll-y="true"
@scrolltolower="loadMore">
<image
class="mybg"
:src="pageUserInfo.bgImg"
mode="aspectFill"
@click="changeMyBg" />
<!-- 安卓下使用一个灰色图片来替代阴影效果, ios支持阴影, 安卓则不支持 -->
<!-- <image
v-if="isAndroid"
@click.self="changeMyBg"
:src="pageUserInfo.bgImg"
mode="aspectFill"
style="width: 750rpx; height: 750rpx; opacity: 0.5" /> -->
<view class="my-info-wrapper">
<view class="my-info">
<image
:src="pageUserInfo.face"
mode="aspectFill"
class="my-face"
@click="changeMyFace" />
<view class="info-wrapper">
<text class="nickname">
{{ pageUserInfo.nickname }}
</text>
<view class="tiktok-num-wrapper">
<text class="tiktok-num">视频号:</text>
<text class="tiktok-num">
{{ pageUserInfo.tiktokNum }}
</text>
</view>
<view class="location">
<text class="location-text">所在地:</text>
<text class="location-text">
{{ pageUserInfo.city == "" ? "中国" : "" + pageUserInfo.city
}}{{
pageUserInfo.district == "" ? "" : "·" + pageUserInfo.district
}}
</text>
</view>
<view class="sex-wrapper">
<view class="constellation">
<image
class="sex-img"
v-if="pageUserInfo.sex == 1"
src="../../static/images/icon-sex-boy.png" />
<image
class="sex-img"
v-if="pageUserInfo.sex == 0"
src="../../static/images/icon-sex-girl.png" />
<image
class="sex-img"
v-if="pageUserInfo.sex == 2"
src="../../static/images/icon-sex-secret.png" />
<text class="astro">{{ astro }}座</text>
</view>
<view class="animal">
<text class="animal-text">
{{ animal }}
</text>
</view>
</view>
</view>
</view>
</view>
<text class="desc">
{{ pageUserInfo.description }}
</text>
<view class="bottom-wrapper">
<view class="bottom">
<view @click="goMyFollows(pageUserInfo.id)" class="bottom-item">
<text class="item-num">
{{ getGraceNumber(pageUserInfo.myFollowsCounts) }}
</text>
<text class="item-text">关注</text>
</view>
<view class="bottom-item" @click="goMyFans(pageUserInfo.id)">
<text class="item-num">
{{ getGraceNumber(pageUserInfo.myFansCounts) }}
</text>
<text class="item-text">粉丝</text>
</view>
<view class="bottom-item">
<text class="item-num">
{{ getGraceNumber(pageUserInfo.totalLikeMeCounts) }}
</text>
<text class="item-text">获赞</text>
</view>
</view>
<view class="edit">
<view @click="goMyInfo" class="edit-info">
<text class="edit-text">编辑资料</text>
</view>
<view @click="goSettings" class="setting">
<image
src="../../static/images/icon-settings.png"
class="setting-img" />
</view>
</view>
</view>
<view class="tab-wrapper">
<view class="tab-item" @click="switchTab(0)">
<text class="tab-normal" :class="{ 'tab-selected': currentTab == 0 }">
作品
</text>
<view v-if="currentTab == 0" class="selected-tab"></view>
</view>
<view class="tab-item" @click="switchTab(1)">
<text class="tab-normal" :class="{ 'tab-selected': currentTab == 1 }">
私密
</text>
<view v-if="currentTab == 1" class="selected-tab"></view>
</view>
<view class="tab-item" @click="switchTab(2)">
<text class="tab-normal" :class="{ 'tab-selected': currentTab == 2 }">
赞过
</text>
<view v-if="currentTab == 2" class="selected-tab"></view>
</view>
</view>
<view class="vlog-list">
<block v-for="(vlog, index) in vlogList" :key="index">
<image
class="vlog-cover"
:src="vlog.cover"
@click="goToVlog(vlog)"
mode="aspectFill"></image>
</block>
</view>
<view v-if="vlogList.length == 0" class="empty">
<text class="empty-text">~ 空空如也 ~</text>
</view>
<view v-if="vlogList.length > 0" class="not-empty">
<text class="not-empty-text">~ 没有更多了 ~</text>
</view>
</scroll-view>
</view>
</template>
<script>
let system = uni.getSystemInfoSync();
let app = getApp();
export default {
data() {
return {
userIsLogin: false,
pageUserInfo: {}, // 用户信息
userPageId: "",
astro: "", // 星座
animal: "", // 生肖
loginWords: "请登录",
screenHeight: 0,
screenHeightUnLogin: 0,
currentTab: 0,
isAndroid: uni.getSystemInfoSync().platform == "android",
page: 0,
toalPage: 0,
vlogList: [],
};
},
onLoad() {
let screenHeight = system.safeArea.bottom + 50;
this.screenHeight = screenHeight;
let screenHeightUnLogin = system.safeArea.bottom;
this.screenHeightUnLogin = screenHeightUnLogin;
},
onShow() {
let me = this;
// 判断我有没有登录
this.userIsLogin = app.userIsLogin();
console.log(this.userIsLogin)
let myUserInfo = app.getUserInfoSession();
console.log(myUserInfo)
if (myUserInfo == null) {
return;
}
this.pageUserInfo = myUserInfo;
let myUserId = myUserInfo.id;
let serverUrl = app.globalData.serverUrl;
uni.showLoading({
title: "正在加载!",
});
// 查询用户信息
uni.request({
method: "GET",
url: serverUrl + "/userInfo/query?userId=" + myUserId,
success(result) {
uni.hideLoading();
console.log(result)
if (result.data.status == 200) {
me.pageUserInfo = result.data.data;
app.setUserInfoSession(result.data.data);
me.setBasicUserInfo(me.pageUserInfo);
} else {
uni.navigateTo({
url: "../loginRegist/loginRegist",
animationType: "slide-in-bottom",
success() {
me.loginWords = "请登录";
},
});
}
},
});
this.switchTab(0);
},
onTabItemTap: function (e) {
let me = this;
// 判断当前用户有没有登录, 有没有token, 如果有, 则展示当前页, 如果没有表示未登录, 展示登录注册页
if (!app.userIsLogin()) {
// 为空, 弹出页面
uni.navigateTo({
url: "../loginRegist/loginRegist",
animationType: "slide-in-bottom",
success() {
me.loginWords = "请登录";
},
});
}
},
methods: {
setBasicUserInfo(myUserInfo) {
// if (app.isStrEmpty(myUserInfo.bgImg)) {
// myUserInfo.bgImg = "http://120.26.164.63:9000/tiktok/IMG_4566.HEIC";
// app.setUserInfoSession(myUserInfo);
// }
// if (app.isStrEmpty(myUserInfo.face)) {
// myUserInfo.face = "http://120.26.164.63:9000/tiktok/IMG_4845.JPG";
// app.setUserInfoSession(myUserInfo);
// }
// 根据生日判断星座
let birthday = myUserInfo.birthday;
let birth = app.dateFormat("YYYY-mm-dd", new Date(birthday));
let birthArr = birth.split("-");
let year = birthArr[0];
let month = birthArr[1];
let day = birthArr[2];
let astro = app.getAstro(month, day);
this.astro = astro;
// 根据生日判断生肖
let animal = app.getAnimal(year);
this.animal = animal;
},
switchTab(index) {
this.currentTab = index;
if (index == 0) {
this.page = 0;
this.toalPage = 0;
this.vlogList = [];
this.myList(0,'myPublicList');
} else if (index == 1) {
this.vlogList = [];
this.page = 0;
this.toalPage = 0;
this.myList(0,'myPrivateList');
} else if (index == 2) {
this.vlogList = [];
this.page = 0;
this.toalPage = 0;
this.myList(0,'myLikedList');
}
},
loadMore() {
let requestArr = ['myPublicList','myPrivateList','myLikedList']
if (this.page >= this.toalPage) {
return;
} else {
this.myList(this.page,requestArr[this.currentTab]);
}
},
myList(page,requrl) {
let me = this;
page = page + 1;
me.page = page;
let userId = getApp().getUserInfoSession().id;
let serverUrl = app.globalData.serverUrl;
uni.request({
method: "GET",
url:`${serverUrl}/vlog/${requrl}`,
data:{
userId,
page,
pageSize:20
},
success(result) {
console.log(result)
if (result.data.status == 200) {
let vlogList = result.data.data.rows;
let toalPage = result.data.data.total;
me.vlogList = me.vlogList.concat(vlogList);
me.page = page;
me.toalPage = toalPage;
}
},
});
},
goLogin() {
uni.navigateTo({
url: "../loginRegist/loginRegist",
animationType: "slide-in-bottom",
});
},
// 把超过1000或10000的数字调整, 比如1.3k/6.8w
getGraceNumber(num) {
return getApp().graceNumber(num);
},
goToVlog(vlog) {
let vlogId = vlog.id ? vlog.id : vlog.vlogId;
uni.navigateTo({
url: "../vlog/vlog?vlogId=" + vlogId,
});
},
changeMyBg() {
uni.navigateTo({
animationType: "fade-in",
url: "myBackImg",
});
},
changeMyFace() {
uni.navigateTo({
animationType: "fade-in",
url: "myFace",
});
},
goMyInfo() {
uni.navigateTo({
animationType: "fade-in",
url: "myInfo",
});
},
goSettings() {
uni.navigateTo({
animationType: "fade-in",
url: "settings",
});
},
goMyFans(userId) {
uni.navigateTo({
animationType: "fade-in",
url: "myFans?userId=" + userId,
});
},
goMyFollows(userId) {
uni.navigateTo({
animationType: "fade-in",
url: "myFollows?userId=" + userId,
});
},
},
};
</script>
<style lang="scss">
.page {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: #000000;
.login-info-wrapper {
display: flex;
flex-direction: column;
justify-content: center;
.login-info {
align-self: center;
color: #ffffff;
font-size: 36rpx;
font-weight: 600;
}
}
.isLogin-info-wrapper {
.mybg {
width: 750rpx;
height: 750rpx;
box-shadow: inset 0 -150px 180px #313030;
}
.my-info-wrapper {
position: relative;
left: 30rpx;
top: -560rpx;
display: flex;
flex-direction: column;
width: 1000rpx;
.my-info {
display: flex;
flex-direction: row;
.my-face {
width: 200rpx;
height: 200rpx;
border-radius: 100rpx;
border-width: 1px;
border-color: #f1f1f1;
}
.info-wrapper {
margin-left: 30rpx;
padding-top: 20rpx;
width: 500rpx;
.nickname {
font-size: 20px;
color: #ffffff;
font-weight: 600;
}
.tiktok-num-wrapper {
display: flex;
flex-direction: row;
.tiktok-num {
font-size: 10px;
color: #ffffff;
font-weight: 300;
}
}
.location {
display: flex;
flex-direction: row;
height: 20px;
margin-top: 2px;
font-size: 1px;
.location-text {
line-height: 20px;
color: #ffffff;
font-size: 10px;
font-weight: 300;
}
}
.sex-wrapper {
display: flex;
flex-direction: row;
margin-top: 10rpx;
.constellation {
display: flex;
flex-direction: row;
justify-content: center;
background-color: #000000;
opacity: 0.5;
width: 130rpx;
height: 40rpx;
border-radius: 10px;
.sex-img {
width: 22rpx;
height: 22rpx;
align-self: center;
}
.astro {
font-size: 10px;
color: #ffffff;
line-height: 20px;
font-weight: bold;
margin-left: 6rpx;
align-self: center;
}
}
.animal {
margin-left: 10rpx;
display: flex;
flex-direction: row;
justify-content: center;
background-color: #000000;
opacity: 0.5;
width: 60rpx;
height: 40rpx;
border-radius: 10px;
.animal-text {
font-size: 10px;
color: #ffffff;
line-height: 20px;
font-weight: bold;
align-self: center;
}
}
}
}
}
}
.desc {
position: relative;
top: -520rpx;
color: #ffffff;
font-size: 14px;
margin: 0 30rpx;
}
.bottom-wrapper {
position: relative;
top: -510rpx;
display: flex;
flex-direction: row;
justify-content: space-between;
.bottom {
display: flex;
flex-direction: row;
.bottom-item {
margin-left: 30rpx;
display: flex;
flex-direction: column;
justify-content: center;
.item-num {
color: #ffffff;
font-size: 14px;
font-weight: bold;
align-self: center;
}
.item-text {
color: #ffffff;
font-size: 12px;
font-weight: 300;
align-self: center;
}
}
}
.edit {
display: flex;
flex-direction: row;
justify-content: center;
margin-right: 30rpx;
.edit-info {
margin-left: 20rpx;
border-width: 1px;
border-color: #ffffff;
width: 200rpx;
height: 66rpx;
background-color: #545456;
opacity: 0.8;
border-radius: 40rpx;
display: flex;
flex-direction: row;
justify-content: center;
align-self: center;
.edit-text {
font-size: 13px;
color: #ffffff;
font-weight: 500;
align-self: center;
}
}
.setting {
margin-left: 20rpx;
border-width: 1px;
border-color: #ffffff;
width: 100rpx;
height: 66rpx;
background-color: #545456;
opacity: 0.8;
border-radius: 40rpx;
display: flex;
flex-direction: row;
justify-content: center;
align-self: center;
.setting-img {
width: 32rpx;
height: 32rpx;
align-self: center;
}
}
}
}
.tab-wrapper {
position: relative;
top: -480rpx;
height: 40px;
background-color: #171825;
display: flex;
flex-direction: row;
justify-content: space-between;
padding-top: 3px;
border-top-left-radius: 12px;
border-top-right-radius: 12px;
.tab-item {
width: 250rpx;
align-self: center;
.tab-normal {
font-size: 18px;
font-weight: 500;
align-self: center;
color: #808080;
}
.tab-selected {
color: #ffffff;
}
.selected-tab {
margin-top: 5px;
height: 5rpx;
width: 250rpx;
border-radius: 6rpx;
background-color: #ef274d;
}
}
}
.vlog-list {
position: relative;
top: -480rpx;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
background-color: #000000;
.vlog-cover {
align-self: center;
width: 248rpx;
height: 360rpx;
border-width: 1rpx;
}
}
.empty {
background-color: #000000;
width: 750rpx;
height: 300rpx;
display: flex;
flex-direction: row;
justify-content: center;
position: relative;
top: -480rpx;
.empty-text {
color: #ffffff;
font-size: 14px;
margin-top: 200rpx;
}
}
.not-empty {
width: 750rpx;
display: flex;
flex-direction: row;
justify-content: center;
position: relative;
top: -260rpx;
.not-empty-text {
color: #ffffff;
font-size: 14px;
}
}
}
}
</style>

724
pages/me/vlogerInfo.nvue Executable file
View File

@ -0,0 +1,724 @@
<template>
<view class="page">
<scroll-view
class="isLogin-info-wrapper"
:style="{ height: screenHeight + 'px' }"
scroll-y="true"
@scrolltolower="loadMore">
<image class="mybg" :src="pageUserInfo.bgImg" mode="aspectFill" />
<!-- 安卓下使用一个灰色图片来替代阴影效果, ios支持阴影, 安卓则不支持 -->
<!-- <image
v-if="isAndroid"
:src="pageUserInfo.bgImg"
mode="aspectFill"
style="width: 750rpx; height: 750rpx; opacity: 0.5" /> -->
<view class="header" :style="{ marginTop: statusBarHeight + 'px' }">
<image
class="header-right-search"
src="../../static/images/icon-back.png"
@click="back()" />
</view>
<view class="my-info-wrapper">
<view class="my-info">
<image :src="pageUserInfo.face" mode="aspectFill" class="my-face" />
<view class="info-wrapper">
<text class="nickname">
{{ pageUserInfo.nickname }}
</text>
<view class="tiktok-num-wrapper">
<text class="tiktok-num">视频号:</text>
<text class="tiktok-num">
{{ pageUserInfo.tiktokNum }}
</text>
</view>
<view class="location">
<text class="location-text">所在地:</text>
<text class="location-text">
{{ pageUserInfo.city == "" ? "中国" : "" + pageUserInfo.city
}}{{
pageUserInfo.district == "" ? "" : "·" + pageUserInfo.district
}}
</text>
</view>
<view class="sex-wrapper">
<view class="constellation">
<image
class="sex-img"
v-if="pageUserInfo.sex == 1"
src="../../static/images/icon-sex-boy.png" />
<image
class="sex-img"
v-if="pageUserInfo.sex == 0"
src="../../static/images/icon-sex-girl.png" />
<image
class="sex-img"
v-if="pageUserInfo.sex == 2"
src="../../static/images/icon-sex-secret.png" />
<text class="astro">{{ astro }}座</text>
</view>
<view class="animal">
<text class="animal-text">
{{ animal }}
</text>
</view>
</view>
</view>
</view>
</view>
<text class="desc">
{{ pageUserInfo.description }}
</text>
<view class="bottom-wrapper">
<view class="bottom">
<view class="bottom-item" @click="goMyFollows(pageUserInfo.id)">
<text class="item-num">
{{ getGraceNumber(pageUserInfo.myFollowsCounts) }}
</text>
<text class="item-text">关注</text>
</view>
<view class="bottom-item" @click="goMyFans(pageUserInfo.id)">
<text class="item-num">
{{ getGraceNumber(pageUserInfo.myFansCounts) }}
</text>
<text class="item-text">粉丝</text>
</view>
<view class="bottom-item">
<text class="item-num">
{{ getGraceNumber(pageUserInfo.totalLikeMeCounts) }}
</text>
<text class="item-text">获赞</text>
</view>
</view>
<view class="edit">
<view
v-if="isFollow && !isFan"
@click="cancelFollow()"
class="follow-btn">
<text class="follow-text">已关注</text>
</view>
<view
v-if="isFollow && isFan"
@click="cancelFollow()"
class="follow-btn">
<text class="follow-text">相互关注</text>
</view>
<view
v-if="!isFollow"
@click="followMe()"
class="follow-btn"
style="background-color: #ef274d">
<text class="follow-text">关注我</text>
</view>
</view>
</view>
<view class="tab-wrapper">
<view class="tab-item" @click="switchTab(0)">
<text class="tab-normal" :class="{ 'tab-selected': currentTab == 0 }">
作品
</text>
<view v-if="currentTab == 0" class="selected-tab"></view>
</view>
<view class="tab-item" @click="switchTab(1)">
<text class="tab-normal" :class="{ 'tab-selected': currentTab == 1 }">
私密
</text>
<view v-if="currentTab == 1" class="selected-tab"></view>
</view>
<view class="tab-item" @click="switchTab(2)">
<text class="tab-normal" :class="{ 'tab-selected': currentTab == 2 }">
赞过
</text>
<view v-if="currentTab == 2" class="selected-tab"></view>
</view>
</view>
<view class="vlog-list">
<block v-for="(vlog, index) in vlogList" :key="index">
<image
class="vlog-cover"
:src="vlog.cover"
@click="goToVlog(vlog)"
mode="aspectFill"></image>
</block>
</view>
<view v-if="vlogList.length == 0" class="empty">
<text class="empty-text">~ 空空如也 ~</text>
</view>
<view v-if="vlogList.length > 0" class="not-empty">
<text class="not-empty-text">~ 没有更多了 ~</text>
</view>
</scroll-view>
</view>
</template>
<script>
let system = uni.getSystemInfoSync();
const app = getApp();
export default {
data() {
return {
pageUserInfo: {},
userPageId: "",
astro: "",
animal: "",
loginWords: "请登录",
statusBarHeight: 0,
screenHeight: 0,
screenHeightUnLogin: 0,
currentTab: 0,
isFollow: false,
isFan: false,
isAndroid: uni.getSystemInfoSync().platform == "android",
page: 0,
totalpage: 0,
vlogList: [],
};
},
onLoad(params) {
this.statusBarHeight = system.statusBarHeight;
let screenHeight = system.safeArea.bottom + 50;
this.screenHeight = screenHeight;
let screenHeightUnLogin = system.safeArea.bottom;
this.screenHeightUnLogin = screenHeightUnLogin;
let me = this;
// 从视频页面, 点击用户头像传递过来的id
let userPageId = params.userPageId;
if (app.isStrEmpty(userPageId)) {
uni.showToast({
title: "出错啦~",
icon: " none",
duration: 2000,
});
settimeout(() => {
uni.navigateBack({
delta: 1,
});
}, 1500);
}
me.userPageId = userPageId;
let serverUrl = app.globalData.serverUrl;
// 查询用户信息
uni.request({
method: "GET",
url: serverUrl + "/userInfo/query?userId=" + userPageId,
success(result) {
if (result.data.status == 200) {
me.pageUserInfo = result.data.data;
me.setBasicUserInfo(me.pageUserInfo);
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
}
},
});
this.switchTab(0);
let myUserId = "";
if (!app.isStrEmpty(app.getUserInfoSession())) {
myUserId = app.getUserInfoSession().id;
}
if (!app.isStrEmpty(myUserId)) {
// 查询用户是否关注博主
uni.request({
method: "GET",
header: {
headerUserId: myUserId,
headerUserToken: app.getUserSessionToken(),
},
url:
serverUrl +
"/fans/queryRelationship?myId=" +
myUserId +
"&vlogerId=" +
userPageId,
success(result) {
if (result.data.status == 200) {
me.isFollow = result.data.data.follow;
me.isFan = result.data.data.fan;
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
}
},
});
}
},
methods: {
setBasicUserInfo(myUserInfo) {
if (app.isStrEmpty(myUserInfo.bgImg)) {
myUserInfo.bgImg = "http://120.26.164.63:9000/tiktok/IMG_4566.HEIC";
}
if (app.isStrEmpty(myUserInfo.face)) {
myUserInfo.face = "http://120.26.164.63:9000/tiktok/IMG_4845.JPG";
}
// 根据生日判断星座
let birthday = myUserInfo.birthday;
let birth = app.dateFormat("YYYY-mm-dd", new Date(birthday));
let birthArr = birth.split("-");
let year = birthArr[0];
let month = birthArr[1];
let day = birthArr[2];
let astro = app.getAstro(month, day);
this.astro = astro;
// 根据生日判断生肖
let animal = app.getAnimal(year);
this.animal = animal;
},
switchTab(index) {
this.currentTab = index;
if (index == 0) {
this.vlogList = [];
this.page = 0;
this.toalPage = 0;
this.myList(0,'myPublicList');
} else if (index == 1) {
this.vlogList = [];
} else if (index == 2) {
this.vlogList = [];
this.page = 0;
this.toalPage = 0;
this.myList(2,'myLikedList');
}
},
loadMore() {
let requestArr = ['myPublicList','myPrivateList','myLikedList']
if (this.page >= this.toalPage) {
return;
} else {
this.myList(this.page,requestArr[this.currentTab]);
}
},
myList(page,requrl) {
let me = this;
page = page + 1;
me.page = page;
let vlogerId = me.userPageId;
let serverUrl = app.globalData.serverUrl;
uni.request({
method: "GET",
url:`${serverUrl}/vlog/${requrl}`,
data:{
userId:vlogerId,
page,
pageSize:20
},
success(result) {
if (result.data.status == 200) {
let vlogList = result.data.data.rows;
let toalPage = result.data.data.total;
me.vlogList = me.vlogList.concat(vlogList);
me.page = page;
me.toalPage = toalPage;
}
},
});
},
back() {
uni.navigateBack({
delta: 1,
});
},
cancelFollow() {
let me = this;
let vlogerId = me.userPageId;
let userId = getApp().getUserInfoSession().id;
let serverUrl = app.globalData.serverUrl;
uni.request({
method: "POST",
header: {
headerUserId: userId,
headerUserToken: app.getUserSessionToken(),
},
url:
serverUrl + "/fans/cancel?myId=" + userId + "&vlogerId=" + vlogerId,
success(result) {
if (result.data.status == 200) {
me.isFollow = false;
uni.setStorageSync("justCancelVlogerId", vlogerId);
// 刷新当前页的粉丝数
let pendingInfo = me.pageUserInfo;
me.pageUserInfo.myFansCounts = pendingInfo.myFansCounts - 1;
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
}
},
});
},
// 关注
followMe() {
let me = this;
let myUserInfo = getApp().getUserInfoSession();
if (app.isStrEmpty(myUserInfo)) {
uni.showToast({
duration: 3000,
title: "请登录后再进行操作~",
icon: "none",
});
uni.switchTab({
url: "me",
});
uni.navigateTo({
url: "../loginRegist/loginRegist",
animationType: "slide-in-bottom",
success() {
me.loginWords = "请登录";
},
});
return;
}
let vlogerId = me.userPageId;
let userId = myUserInfo.id;
let serverUrl = app.globalData.serverUrl;
uni.request({
method: "POST",
header: {
headerUserId: userId,
headerUserToken: app.getUserSessionToken(),
},
url:
serverUrl + "/fans/follow?myId=" + userId + "&vlogerId=" + vlogerId,
success(result) {
if (result.data.status == 200) {
me.isFollow = true;
uni.setStorageSync("justFollowVlogerId", vlogerId);
// 刷新当前页的粉丝数
let pendingInfo = me.pageUserInfo;
me.pageUserInfo.myFansCounts = pendingInfo.myFansCounts + 1;
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
}
},
});
},
// 把超过1000或10000的数字调整, 比如1.3k/6.8w
getGraceNumber(num) {
return getApp().graceNumber(num);
},
goToVlog(vlog) {
let vlogId = vlog.id ? vlog.id : vlog.vlogId;
uni.navigateTo({
url: "../vlog/vlog?type=mine&isNeedPage=1&vlogId=" + vlogId,
});
},
goMyFans(userId) {
uni.navigateTo({
animationType: "fade-in",
url: "myFans?userId=" + userId,
});
},
goMyFollows(userId) {
uni.navigateTo({
animationType: "fade-in",
url: "myFollows?userId=" + userId,
});
},
},
};
</script>
<style lang="scss">
.page {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: #000000;
.isLogin-info-wrapper {
.header {
position: absolute;
left: 0;
right: 0;
flex-direction: row;
height: 100rpx;
line-height: 100rpx;
align-items: center;
padding-left: 40rpx;
padding-right: 40rpx;
.header-right-search {
width: 40rpx;
height: 40rpx;
opacity: 0.8;
}
}
.mybg {
width: 750rpx;
height: 750rpx;
box-shadow: inset 0 -150px 180px #313030;
}
.my-info-wrapper {
position: relative;
left: 30rpx;
top: -560rpx;
display: flex;
flex-direction: column;
width: 1000rpx;
.my-info {
display: flex;
flex-direction: row;
.my-face {
width: 200rpx;
height: 200rpx;
border-radius: 100rpx;
border-width: 1px;
border-color: #f1f1f1;
}
.info-wrapper {
margin-left: 30rpx;
padding-top: 20rpx;
width: 500rpx;
.nickname {
font-size: 20px;
color: #ffffff;
font-weight: 600;
}
.tiktok-num-wrapper {
display: flex;
flex-direction: row;
.tiktok-num {
font-size: 10px;
color: #ffffff;
font-weight: 300;
}
}
.location {
display: flex;
flex-direction: row;
height: 20px;
margin-top: 2px;
font-size: 1px;
.location-text {
line-height: 20px;
color: #ffffff;
font-size: 10px;
font-weight: 300;
}
}
.sex-wrapper {
display: flex;
flex-direction: row;
margin-top: 10rpx;
.constellation {
display: flex;
flex-direction: row;
justify-content: center;
background-color: #000000;
opacity: 0.5;
width: 130rpx;
height: 40rpx;
border-radius: 10px;
.sex-img {
width: 22rpx;
height: 22rpx;
align-self: center;
}
.astro {
font-size: 10px;
color: #ffffff;
line-height: 20px;
font-weight: bold;
margin-left: 6rpx;
align-self: center;
}
}
.animal {
margin-left: 10rpx;
display: flex;
flex-direction: row;
justify-content: center;
background-color: #000000;
opacity: 0.5;
width: 60rpx;
height: 40rpx;
border-radius: 10px;
.animal-text {
font-size: 10px;
color: #ffffff;
line-height: 20px;
font-weight: bold;
align-self: center;
}
}
}
}
}
}
.desc {
position: relative;
top: -520rpx;
color: #ffffff;
font-size: 14px;
margin: 0 30rpx;
}
.bottom-wrapper {
position: relative;
top: -510rpx;
display: flex;
flex-direction: row;
justify-content: space-between;
.bottom {
display: flex;
flex-direction: row;
.bottom-item {
margin-left: 30rpx;
display: flex;
flex-direction: column;
justify-content: center;
.item-num {
color: #ffffff;
font-size: 14px;
font-weight: bold;
align-self: center;
}
.item-text {
color: #ffffff;
font-size: 12px;
font-weight: 300;
align-self: center;
}
}
}
.edit {
display: flex;
flex-direction: row;
justify-content: center;
margin-right: 30rpx;
.follow-btn {
margin-right: 20rpx;
border-width: 1px;
border-color: #ffffff;
width: 200rpx;
height: 66rpx;
background-color: #545456;
opacity: 0.8;
border-radius: 40rpx;
display: flex;
flex-direction: row;
justify-content: center;
align-self: center;
.follow-text {
font-size: 13px;
color: #ffffff;
font-weight: 500;
align-self: center;
}
}
}
}
.tab-wrapper {
position: relative;
top: -480rpx;
height: 40px;
background-color: #171825;
display: flex;
flex-direction: row;
justify-content: space-between;
padding-top: 3px;
border-top-left-radius: 12px;
border-top-right-radius: 12px;
.tab-item {
width: 250rpx;
align-self: center;
.tab-normal {
font-size: 18px;
font-weight: 500;
align-self: center;
color: #808080;
}
.tab-selected {
color: #ffffff;
}
.selected-tab {
margin-top: 5px;
height: 5rpx;
width: 250rpx;
border-radius: 6rpx;
background-color: #ef274d;
}
}
}
.vlog-list {
position: relative;
top: -480rpx;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
background-color: #000000;
.vlog-cover {
align-self: center;
width: 248rpx;
height: 360rpx;
border-width: 1rpx;
}
}
.empty {
background-color: #000000;
width: 750rpx;
height: 300rpx;
display: flex;
flex-direction: row;
justify-content: center;
position: relative;
top: -480rpx;
.empty-text {
color: #ffffff;
font-size: 14px;
margin-top: 200rpx;
}
}
.not-empty {
width: 750rpx;
display: flex;
flex-direction: row;
justify-content: center;
position: relative;
top: -260rpx;
.not-empty-text {
color: #ffffff;
font-size: 14px;
}
}
}
}
</style>

55
pages/publish/preview.nvue Executable file
View File

@ -0,0 +1,55 @@
<template>
<view class="page">
<video
class="video"
:style="{ height: screenSafeHeight + 'px' }"
:src="videoUrl"
autoplay="true"
controls="true"
:object-fit="objectFit"></video>
</view>
</template>
<script>
let system = uni.getSystemInfoSync();
export default {
data() {
return {
videoUrl: "",
objectFit: "fill",
screenSafeHeight: system.safeArea.bottom,
};
},
onLoad(params) {
let me = this;
let videoUrl = params.videoUrl;
this.videoUrl = videoUrl;
let width = parseInt(params.width);
let height = parseInt(params.height);
this.width = width;
this.height = height;
if (width >= height) {
me.objectFit = "contain";
} else {
me.objectFit = "fill";
}
},
methods: {},
};
</script>
<style lang="scss">
.page {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: #181b27;
.video {
width: 750rpx;
}
}
</style>

369
pages/publish/publish.nvue Executable file
View File

@ -0,0 +1,369 @@
<template>
<scroll-view class="prpage" scroll-y="true">
<view class="line"></view>
<!-- 进度条 -->
<view class="progress" v-if="percentCompleted != 100">
<progress :percent="percentCompleted" stroke-width="3" activeColor="#ef274d" backgroundColor="#F1F1F1" />
<text class="progress-text">视频上传中,请耐心等待~~</text>
<image class="progress-img" mode="aspectFit" src="/static/images/loading-4.gif" />
</view>
<!-- 发布主体内容 -->
<view class="main-body" v-if="percentCompleted == 100">
<image class="main-body-img" :src="tempCover" mode="widthFix" />
<view class="main-body-content">
<view class="preplay-wrapper" @click="preview" @touchstart="touchstartPreplay"
@touchend="touchendPreplay">
<image class="preplay-icon" src="/static/images/btn-play.png" />
<text class="preplay-text">预览视频</text>
</view>
<view class="choose-cover" @click="chooseCover">
<text class="choose-cover-text">选择封面</text>
</view>
</view>
<textarea class="vlog-content" placeholder-style="color: #9798a0;" placeholder="添加合适的描述内容~" :value="title"
:model="title" maxlength="60" @input="typingContent" confirm-type="done"></textarea>
<view class="btn" :class="{
'btn-publish': !publishTouched,
'btn-publish-touched': publishTouched,
}" @touchstart="touchstartPublish" @touchend="touchendPublish" @click="doPublich">
<text class="btn-text">发布视频</text>
</view>
</view>
</scroll-view>
</template>
<script>
import storage from "@/utils/storage.js"; //缓存
// import {
// graceNumber
// } from '@/utils/tools.js'
import api from "@/config/api.js";
export default {
data() {
return {
publishTouched: false,
preplayTouched: false,
tempFilePath: "",
videoUrl: "",
tempCover: "", // 视频封面
title: "",
width: 0,
height: 0,
percentCompleted: 0, // 进度
};
},
onLoad(params) {
let me = this;
let vlogInfo = storage.getVlogUserInfo()
// 上个页面传过来的文件事件对象, 其中包含了相册中选择的视频内容
let fileObjectEvent = JSON.parse(params.fileObjectEvent);
let times = new Date().getTime();
var userId = vlogInfo.id;
let nickname = vlogInfo.nickname;
let serverUrl = api.vlog;
const uploadTask = uni.uploadFile({
filePath: fileObjectEvent.tempFilePath,
url: serverUrl + "/upload",
name: 'file',
formData: {
filetype: 'video'
},
header: {
headerUserId: userId,
headerUserToken: storage.getVlogToken()
},
success: (f) => {
console.log(f)
let jsondata = f.data
let data = JSON.parse(jsondata)
let videoUrl = data.data;
me.videoUrl = videoUrl;
me.width = fileObjectEvent.width;
me.height = fileObjectEvent.height;
}
})
uploadTask.onProgressUpdate((res) => {
console.log('上传进度' + res.progress);
// console.log('已经上传的数据长度' + res.totalBytesSent);
// console.log('预期需要上传的数据总长度' + res.totalBytesExpectedToSend);
// 显示进度
// let percentCompleted = Math.round(
// (res.progress * 100) / res.total
// );
me.percentCompleted = res.progress
})
},
methods: {
typingContent(e) {
let event = e;
this.title = e.detail.value;
},
doPublich() {
if (this.title.length < 5) {
uni.showToast({
title: "请输入5个字以上的标题",
icon: "none",
});
return;
}
let me = this;
let vlogInfo = storage.getVlogUserInfo()
let userId = vlogInfo.id;
let vlog = {
vlogerId: userId,
url: me.videoUrl,
cover: me.tempCover || '',
title: me.title,
width: me.width,
height: me.height,
};
// 发布视频
let serverUrl = api.vlog
uni.request({
method: "POST",
header: {
headerUserId: userId,
headerUserToken: storage.getVlogToken(),
},
url: serverUrl + "/vlog/publish",
data: vlog,
success(result) {
if (result.data.status == 200) {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 2000,
});
setTimeout(() => {
uni.switchTab({
url: "/pages/tabbar/user/my",
});
}, 2000);
} else {
uni.showToast({
title: result.data.msg,
icon: "none",
duration: 3000,
});
}
},
});
},
preview() {
uni.navigateTo({
url: "/pages/publish/preview?videoUrl=" +
this.videoUrl +
"&width=" +
this.width +
"&height=" +
this.height,
animationType: "slide-in-bottom",
animationDuration: 500,
});
},
touchstartPreplay() {
this.preplayTouched = true;
},
touchendPreplay() {
this.preplayTouched = false;
},
touchstartPublish() {
this.publishTouched = true;
},
touchendPublish() {
this.publishTouched = false;
},
chooseCover() {
let me = this;
let vlogInfo = storage.getVlogUserInfo()
let userId = vlogInfo.id;
uni.chooseImage({
count: 1,
sizeType: "original",
sourceType: ["album"],
success(e) {
me.tempCover = e.tempFilePaths[0]; //先在本地回显
// 上传封面
let serverUrl = api.vlog;
uni.uploadFile({
filePath: e.tempFilePaths[0],
url: serverUrl + "/upload",
formData: {
filetype: 'video'
},
header: {
headerUserId: userId,
headerUserToken: storage.getVlogToken(),
},
name: "file",
success(result) {
let res = JSON.parse(result.data);
console.log(res)
if (res.status == 200) {
let imageUrl = res.data;
me.tempCover = imageUrl;
uni.showToast({
title: res.msg,
duration: 2000,
});
} else {
uni.showToast({
title: res.msg,
icon: "none",
duration: 3000,
});
}
},
});
},
});
},
},
};
</script>
<style scoped>
.prpage {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: #181b27;
}
.main-body-img {
/* width: 750rpx; */
flex: 1;
border: 2rpx solid #545456;
border-radius: 20rpx;
align-self: center;
}
.choose-cover-text {
color: #ffffff;
font-size: 28rpx;
align-self: center;
}
.choose-cover {
display: flex;
flex-direction: column;
justify-content: center;
margin-left: 100rpx;
width: 200rpx;
height: 100rpx;
position: relative;
}
.preplay-icon {
width: 22rpx;
height: 22rpx;
align-self: center;
}
.preplay-text {
color: #e6e6e6;
font-size: 28rpx;
align-self: center;
margin-left: 15rpx;
}
.preplay-wrapper {
display: flex;
flex-direction: row;
justify-content: center;
padding: 6rpx 16rpx;
width: 200rpx;
}
.main-body-content {
display: flex;
flex-direction: row;
justify-content: flex-start;
}
.vlog-content {
margin-top: 30rpx;
height: 200rpx;
color: #000000;
font-size: 16px;
background-color: #ffffff;
padding-left: 20rpx;
padding-top: 20rpx;
padding-right: 20rpx;
padding-bottom: 20rpx;
border-radius: 20rpx;
}
.btn-text {
color: #e6e6e6;
font-size: 36rpx;
align-self: center;
font-weight: 500;
}
.btn {
margin-top: 30rpx;
height: 90rpx;
display: flex;
justify-content: center;
border-radius: 40rpx;
}
.btn-publish {
background-color: #ef274d;
}
.btn-publish-touched {
background-color: #de6981;
}
.main-body {
margin-top: 20rpx;
}
.line {
height: 1rpx;
background-color: #393a41;
width: 750rpx;
}
.progress {
margintop: 60rpx;
display: flex;
flex-direction: column;
justify-content: center;
width: 750rpx;
}
.progress-text {
color: #f1f1f1;
font-size: 32rpx;
text-align: center;
margin-top: 40rpx;
}
.progress-img {
width: 600rpx;
height: 600rpx;
align-self: center;
}
</style>

View File

@ -1,341 +1,602 @@
<template>
<view class="page">
<!-- 左中右的三个页面切换, 依次是: 附近 - 关注 - 推荐 -->
<swiper style="my-swiper" :style="{height: screenHeight + 'px'}" :current="curIndex" @change="changeTopTab" >
<swiper-item>
<view class="near-by" :style="{height: screenHeight+'px'}">
<text class="warn-info">暂未开放,敬请期待!</text>
</view>
</swiper-item>
<swiper-item>
<view v-if="myUserInfo == null" class="my-follow" :style="{height: screenHeight+'px'}">
<text class="warn-info">请登录后查看!</text>
</view>
<video-follow-comp
ref="videoFollowComp"
:screenHeight="screenHeight"
:playFollowStatus="playFollowStatus"
:videoList="videoList"
:refreshList="refreshList"
:pagingList="pagingList"
@showLoading="showLoading"
@hideLoading="hideLoading"
@letFollowVideoPause="letFollowVideoPause"
@displayVideoPaging="displayVideoPaging"></video-follow-comp>
</swiper-item>
<swiper-item>
<video-comp
ref="videoComp"
:screenHeight="screenHeight"
:playStatus="playStatus"
:videoList="videoList"
:refreshList="refreshList"
:pagingList="pagingList"
@showLoading="showLoading"
@hideLoading="hideLoading"
@displayVideoPaging="displayVideoPaging"></video-comp>
</swiper-item>
</swiper>
<view class="header" :style="{marginTop:statusBarHeight+'px'}" v-if="!isLoading">
<text class="header-left"></text>
<view class="header-center">
<view class="header-item" @click="tapFollow(0)">
<text class="header-item-title">附近</text>
<view class="header-item-line" :class="{'activate-line': curIndex === 0}"></view>
</view>
<view class="header-item" @click="tapFollow(1)">
<text class="header-item-title">关注</text>
<view class="header-item-line" :class="{'activate-line': curIndex === 1}"></view>
</view>
<view class="header-item" @click="tapFollow(2)">
<text class="header-item-title">推荐</text>
<view class="header-item-line" :class="{'activate-line': curIndex === 2}"></view>
</view>
</view>
<image class="header-right-search normal-img" src="/static/images/icon-search.png" @click="goSearch">
</view>
<view class="header" :style="{marginTop:statusBarHeight+'px'}" v-if="isLoading">
<text class="header-left"></text>
<view class="header-center">
<view class="header-item">
<text class="header-refresh-title">下拉刷新视频</text>
</view>
</view>
<image class="header-right-search normal-img" src="/static/images/loading.gif">
</view>
<!-- 顶部切换的导航 end -->
</view>
</template>
<script>
let system = uni.getSystemInfoSync();
import storage from "@/utils/storage.js"; //缓存
import {vlogList} from "@/api/vlog"
import {isStrEmpty} from '@/utils/tools.js'
import videoComp from '@/components/vlog/videoComp.vue';
import videoFollowComp from '@/components/vlog/videoFollowComp.vue';
export default {
components: {
videoComp,
videoFollowComp
},
data() {
return {
isLoading: false,
statusBarHeight: system.statusBarHeight,
screenHeight: system.screenHeight,
curIndex: 2,
playStatus: false,
playFollowStatus: false,
videoList: [], // 首页一开始查询所得的默认视频列表
refreshList: [], // 下拉刷新后获得的新的列表
pagingList: [], // 分页list
refresh: 0, // 从me页面传来的refresh用于退出登录后重新刷新当前页的视频
}
},
onLoad() {
let have = plus.navigator.hasNotchInScreen(); // 判断是否有下巴
},
onTabItemTap: function(e) {
let tabIndex = e.index;
// this.playStatus = tabIndex === 0 ? true : false;
// 切换视频要做暂停或播放的判断
let me = this;
if (tabIndex == 0) {
// 虚位以待
} else if (tabIndex == 1) {
me.playStatus = false;
me.playFollowStatus = true;
} else if (tabIndex == 2) {
me.playStatus = true;
me.playFollowStatus = false;
}
},
onShow() {
let me = this;
this.myUserInfo = storage.getVlogUserInfo();
// 如果当前没有list, 则relaunch
if (this.$refs.videoComp != undefined) {
let playerList = this.$refs.videoComp.playerList;
if (playerList != undefined && playerList.length == 0) {
this.$refs.videoComp.displayVideoPaging(1, true);
}
}
// 判断如果当前是tab为1或2则播放否则不播放
if (me.curIndex == 0) {
// 虚位以待
} else if (me.curIndex == 1) {
me.playFollowStatus = true;
} else if (me.curIndex == 2) {
me.playStatus = true;
}
// onShow的时候关注的话则重新刷一下list
var justFollowVlogerId = uni.getStorageSync("justFollowVlogerId");
console.log('我是justFollowVlogerId',justFollowVlogerId)
if (!isStrEmpty(justFollowVlogerId)) {
this.$refs.videoComp.reFollowPlayList(justFollowVlogerId);
uni.setStorageSync("justFollowVlogerId", "");
}
// 取消关注也要重新刷一下list
var justCancelVlogerId = uni.getStorageSync("justCancelVlogerId");
if (!isStrEmpty(justCancelVlogerId)) {
this.$refs.videoComp.reCancelPlayList(justCancelVlogerId);
uni.setStorageSync("justCancelVlogerId", "");
}
},
onHide() {
var me = this;
// 显示和隐藏需要判断根据不同tab做暂停或者隐藏
if (me.curIndex == 0) {
// 虚位以待
} else if (me.curIndex == 1) {
me.playFollowStatus = false;
} else if (me.curIndex == 2) {
me.playStatus = false;
}
},
// 当前页下拉刷新
// onPullDownRefresh() {
// var me = this;
// // 下拉刷新判断如果是不同tab那么组件中刷新的请求也不同
// if (me.curIndex == 0) {
// // 虚位以待
// } else if (me.curIndex == 1) {
// this.$refs.videoFollowComp.displayVideoPaging(1, true);
// } else if (me.curIndex == 2) {
// this.$refs.videoComp.displayVideoPaging(1, true);
// }
// },
methods: {
// 获取视频数据
//
// getVideoList(){
// let serverUrl = app.globalData.serverUrl;
// uni.request({
// method: "GET",
// url: serverUrl + "/vlog/indexList",
// data:{
// page:1,
// pageSize:10
// },
// success: () => {
// }
// })
// },
// 前往搜索页面
goSearch() {
uni.navigateTo({
url: "/pages/search/search"
})
},
// 左滑右滑选项卡改变选中状态
changeTopTab: function(e) {
var current = e.detail.current;
this.curIndex = current;
this.playFollowStatus = this.curIndex === 1 ? true : false;
this.playStatus = this.curIndex === 2 ? true : false;
},
// 点击头部选项卡,切换页面
tapFollow: function(current) {
this.curIndex = current;
this.playFollowStatus = this.curIndex === 1 ? true : false;
this.playStatus = this.curIndex === 2 ? true : false;
},
// 下拉刷新改变head的字样显示
showLoading() {
this.isLoading = true;
},
hideLoading() {
this.isLoading = false;
},
letFollowVideoPause() {
this.playFollowStatus = false;
}
}
}
</script>
<style scoped>
/* index start */
.page {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: #000000;
}
/* index end */
/* 顶部选项卡 start */
.header {
position: absolute;
left: 0;
right: 0;
flex-direction: row;
height: 100rpx;
line-height: 100rpx;
align-items: center;
padding-left: 40rpx;
padding-right: 40rpx;
}
.header-center {
flex: 1;
flex-direction: row;
align-items: center;
justify-content: center;
}
.header-left,
.header-right {
color: #999;
height: 100rpx;
line-height: 100rpx;
align-items: flex-start;
justify-content: flex-end;
font-family: iconfont;
}
.header-right-search {
height: 100rpx;
/* align-items: flex-start;
justify-content: flex-end; */
}
.header-item {
align-items: center;
margin-left: 6rpx;
margin-right: 6rpx;
}
.header-item-title {
width: 120rpx;
text-align: center;
height: 60rpx;
line-height: 60rpx;
color: #FFFFFF;
font-size: 16px;
font-weight: 600;
}
.header-refresh-title {
width: 300rpx;
text-align: center;
height: 60rpx;
line-height: 60rpx;
color: #FFFFFF;
font-size: 16px;
font-weight: 600;
}
.header-item-line {
height: 5rpx;
line-height: 8rpx;
width: 60rpx;
border-radius: 8rpx;
}
/* 顶部选项卡 end */
/* 选项卡轮播组件 start */
.my-swiper {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
.near-by {
background-color: #000000;
align-items: center;
justify-content: center;
}
.my-follow {
background-color: #000000;
align-items: center;
justify-content: center;
}
/* 选项卡轮播组件 end */
.warn-info {
color: #FFFFFF;
font-size: 36rpx;
font-weight: 600;
}
.normal-img {
width: 50rpx;
height: 50rpx;
opacity: 0.8;
}
<template>
<view class="page" :id="pageId">
<!-- <list :id="pageId" class="page" :bounce="true" isSwiperList="true"> -->
<!-- 左中右的三个页面切换, 依次是: 附近 - 关注 - 推荐 -->
<swiper ref="swiper1" id="tab-bar-view" style="my-swiper" :style="{height: screenHeight + 'px'}"
:current="curIndex" @change="changeTopTab" @transition="onswiperscroll" @animationfinish="animationfinish"
@onAnimationEnd="animationfinish">
<swiper-item>
<view class="near-by" :style="{height: screenHeight+'px'}">
<text ref="fujin" :pid="0" :parentId="pageId" class="warn-info">暂未开放,敬请期待!</text>
</view>
</swiper-item>
<swiper-item>
<view v-if="myUserInfo == null" class="my-follow" :style="{height: screenHeight+'px'}">
<text class="warn-info">请登录后查看!</text>
</view>
<video-follow-comp ref="videoFollowComp" :pid="1" :parentId="pageId" :screenHeight="screenHeight"
:playFollowStatus="playFollowStatus" :videoList="videoList" :refreshList="refreshList"
:pagingList="pagingList" @showLoading="showLoading" @hideLoading="hideLoading"
@letFollowVideoPause="letFollowVideoPause"
@displayVideoPaging="displayVideoPaging"></video-follow-comp>
</swiper-item>
<swiper-item>
<video-comp ref="videoComp" :pid="2" :parentId="pageId" :screenHeight="screenHeight"
:playStatus="playStatus" :videoList="videoList" :refreshList="refreshList" :pagingList="pagingList"
@showLoading="showLoading" @hideLoading="hideLoading"
@displayVideoPaging="displayVideoPaging"></video-comp>
</swiper-item>
</swiper>
<view class="header" id="head" :style="{marginTop:statusBarHeight+'px'}" v-if="!isLoading">
<text class="header-left"></text>
<view class="header-center">
<!-- <view class="header-item" @click="tapFollow(0)">
<text class="header-item-title">附近</text>
<view class="header-item-line" :class="{'activate-line': curIndex === 0}"></view>
</view>
<view class="header-item" @click="tapFollow(1)">
<text class="header-item-title">关注</text>
<view class="header-item-line" :class="{'activate-line': curIndex === 1}"></view>
</view>
<view class="header-item" @click="tapFollow(2)">
<text class="header-item-title">推荐</text>
<view class="header-item-line" :class="{'activate-line': curIndex === 2}"></view>
</view> -->
<scroll-view ref="tabbar1" id="tab-bar" class="tab-bar" :scroll="false" :scroll-x="true"
:show-scrollbar="false" :scroll-into-view="scrollInto">
<view style="flex-direction: column;flex: 1;">
<view style="flex-direction: row;flex: 1;justify-content: space-around;">
<view class="uni-tab-item" v-for="(tab,index) in tabList" :key="tab.id" :id="tab.id"
:ref="'tabitem'+index" :data-id="index" :data-current="index" @click="ontabtap">
<text class="uni-tab-item-title"
:class="tabIndex==index ? 'uni-tab-item-title-active' : ''">{{tab.name}}</text>
</view>
</view>
<view class="scroll-view-indicator">
<view ref="underline" class="scroll-view-underline" :class="'scroll-view-animation'"
:style="{left: indicatorLineLeft + 'px', width: indicatorLineWidth + 'px'}"></view>
</view>
</view>
</scroll-view>
<view class="tab-bar-line"></view>
</view>
<image class="header-right-search normal-img" src="/static/images/icon-search.png" @click="goSearch">
</view>
<view class="header" :style="{marginTop:statusBarHeight+'px'}" v-if="isLoading">
<text class="header-left"></text>
<view class="header-center">
<view class="header-item">
<text class="header-refresh-title">下拉刷新视频</text>
</view>
</view>
<image class="header-right-search normal-img" src="/static/images/loading.gif">
</view>
<!-- 顶部切换的导航 end -->
</view>
<!-- </list> -->
</template>
<script>
let animation = weex.requireModule('animation')
let dom = weex.requireModule('dom');
let system = uni.getSystemInfoSync();
// 缓存每页最多
const MAX_CACHE_DATA = 100;
// 缓存页签数量
const MAX_CACHE_PAGE = 3;
const TAB_PRELOAD_OFFSET = 1;
import storage from "@/utils/storage.js"; //缓存
import {
vlogList
} from "@/api/vlog"
import {
isStrEmpty
} from '@/utils/tools.js'
import videoComp from '@/components/vlog/videoComp.nvue';
import videoFollowComp from '@/components/vlog/videoFollowComp.nvue';
export default {
components: {
videoComp,
videoFollowComp
},
data() {
return {
isLoading: false,
statusBarHeight: system.statusBarHeight,
screenHeight: system.screenHeight,
curIndex: 2,
playStatus: false,
playFollowStatus: false,
videoList: [], // 首页一开始查询所得的默认视频列表
refreshList: [], // 下拉刷新后获得的新的列表
pagingList: [], // 分页list
refresh: 0, // 从me页面传来的refresh用于退出登录后重新刷新当前页的视频
/////////////////
tabList: [], //tabs内容,'fujin','videoFollowComp','videoComp'
indicatorLineLeft: 0,
indicatorLineWidth: 0,
cacheTab: [],
scrollInto: "",
pageId: "page",
tabIndex: 2,
}
},
onLoad() {
let have = plus.navigator.hasNotchInScreen(); // 判断是否有下巴
let tabs = [{
name: '附近',
value: 'fujin',
id: 1
}, {
name: '关注',
value: 'videoFollowComp',
id: 2
}, {
name: '推荐',
value: 'videoComp',
id: 3
}]
for (var i = 0; i < tabs.length; i++) {
this.tabList.push({
id: "tab" + i,
name: tabs[i].name,
pageid: tabs[i].id
})
}
},
onTabItemTap: function(e) {
let tabIndex = e.index;
// this.playStatus = tabIndex === 0 ? true : false;
// 切换视频要做暂停或播放的判断
let me = this;
if (tabIndex == 0) {
// 虚位以待
} else if (tabIndex == 1) {
me.playStatus = false;
me.playFollowStatus = true;
} else if (tabIndex == 2) {
me.playStatus = true;
me.playFollowStatus = false;
}
},
onShow() {
let me = this;
this.myUserInfo = storage.getVlogUserInfo();
// 如果当前没有list, 则relaunch
if (this.$refs.videoComp != undefined) {
let playerList = this.$refs.videoComp.playerList;
if (playerList != undefined && playerList.length == 0) {
this.$refs.videoComp.displayVideoPaging(1, true);
}
}
// 判断如果当前是tab为1或2则播放否则不播放
if (me.curIndex == 0) {
// 虚位以待
} else if (me.curIndex == 1) {
me.playFollowStatus = true;
} else if (me.curIndex == 2) {
me.playStatus = true;
}
// onShow的时候关注的话则重新刷一下list
var justFollowVlogerId = uni.getStorageSync("justFollowVlogerId") || '';
console.log('我是justFollowVlogerId', justFollowVlogerId)
if (!isStrEmpty(justFollowVlogerId)) {
this.$refs.videoComp.reFollowPlayList(justFollowVlogerId);
uni.setStorageSync("justFollowVlogerId", "");
}
// 取消关注也要重新刷一下list
var justCancelVlogerId = uni.getStorageSync("justCancelVlogerId");
if (!isStrEmpty(justCancelVlogerId)) {
this.$refs.videoComp.reCancelPlayList(justCancelVlogerId);
uni.setStorageSync("justCancelVlogerId", "");
}
},
onHide() {
var me = this;
// 显示和隐藏需要判断根据不同tab做暂停或者隐藏
if (me.curIndex == 0) {
// 虚位以待
} else if (me.curIndex == 1) {
me.playFollowStatus = false;
} else if (me.curIndex == 2) {
me.playStatus = false;
}
},
onReady() {
// this.pageHeight = systemInfo.windowHeight + systemInfo.windowBottom;
this._lastTabIndex = 0;
this.swiperWidth = 0;
this.tabbarWidth = 0;
this.tabListSize = {};
this._touchTabIndex = 0;
this._headHeight = 100;
// var data = ['fujin','videoFollowComp','videoComp']
// var props = data[this.curIndex]
this.pageList = ['fujin', 'videoFollowComp', 'videoComp']
this.selectorQuery();
},
// 当前页下拉刷新
// onPullDownRefresh() {
// var me = this;
// // 下拉刷新判断如果是不同tab那么组件中刷新的请求也不同
// if (me.curIndex == 0) {
// // 虚位以待
// } else if (me.curIndex == 1) {
// this.$refs.videoFollowComp.displayVideoPaging(1, true);
// } else if (me.curIndex == 2) {
// this.$refs.videoComp.displayVideoPaging(1, true);
// }
// },
methods: {
// 获取视频数据
//
// getVideoList(){
// let serverUrl = app.globalData.serverUrl;
// uni.request({
// method: "GET",
// url: serverUrl + "/vlog/indexList",
// data:{
// page:1,
// pageSize:10
// },
// success: () => {
// }
// })
// },
// 前往搜索页面
goSearch() {
uni.navigateTo({
url: "/pages/search/search"
})
},
// ----------头部区域点击tabs
ontabtap(e) {
let index = e.target.dataset.current || e.currentTarget.dataset.current;
this.tapFollow(index)
this.switchTab(index);
},
//
selectorQuery() {
uni.createSelectorQuery().in(this).select('#head').boundingClientRect().exec(rect => {
this._headHeight = rect[0].height;
});
// 查询 tabbar 宽度
uni.createSelectorQuery().in(this).select('#tab-bar').boundingClientRect().exec(rect => {
this.tabbarWidth = rect[0].width;
console.log(this.tabbarWidth)
});
// 查询 tabview 宽度
uni.createSelectorQuery().in(this).select('#tab-bar-view').boundingClientRect().exec(rect => {
this.swiperWidth = rect[0].width;
console.log(this.swiperWidth)
});
// 因 nvue 暂不支持 class 查询
var queryTabSize = uni.createSelectorQuery().in(this);
for (var i = 0; i < this.tabList.length; i++) {
queryTabSize.select('#' + this.tabList[i].id).boundingClientRect();
}
queryTabSize.exec(rects => {
rects.forEach((rect) => {
this.tabListSize[rect.dataset.id] = rect;
})
this.updateIndicator(this.tabListSize[this.tabIndex].left, this.tabListSize[this.tabIndex]
.width);
this.switchTab(this.tabIndex);
});
},
onswiperscroll(e) {
var offsetX = e.detail.dx;
var preloadIndex = this._lastTabIndex;
if (offsetX > TAB_PRELOAD_OFFSET) {
preloadIndex++;
} else if (offsetX < -TAB_PRELOAD_OFFSET) {
preloadIndex--;
}
if (preloadIndex === this._lastTabIndex || preloadIndex < 0 || preloadIndex > this.pageList.length - 1) {
return;
}
let prop = this.pageList[preloadIndex]
let obj = this.$refs[prop]
if (obj.playerList.length === 0) {
// this.loadTabData(preloadIndex);
}
var percentage = Math.abs(this.swiperWidth / offsetX);
var currentSize = this.tabListSize[this._lastTabIndex];
var preloadSize = this.tabListSize[preloadIndex];
var lineL = currentSize.left + (preloadSize.left - currentSize.left) / percentage;
var lineW = currentSize.width + (preloadSize.width - currentSize.width) / percentage;
this.updateIndicator(lineL, lineW);
},
animationfinish(e) {
let index = e.detail.current;
this._lastTabIndex = index;
this.switchTab(index);
this.updateIndicator(this.tabListSize[index].left, this.tabListSize[index].width);
},
updateIndicator(left, width) {
console.log(left)
console.log(width)
this.indicatorLineLeft = left - 40; //40的padding偏移量
this.indicatorLineWidth = width;
},
switchTab(index) {
// console.dir(this.$refs)
let props = this.pageList[index]
let obj = this.$refs[props]
if (obj.playerList.length === 0) {
// this.loadTabData(index);
}
obj.setScrollRef(this._headHeight);
if (this.tabIndex === index) {
return;
}
// 缓存 tabId
if (obj.playerList.length > MAX_CACHE_DATA) {
let isExist = this.cacheTab.indexOf(this.tabIndex);
if (isExist < 0) {
this.cacheTab.push(this.tabIndex);
}
}
this.tabIndex = index;
this.curIndex = index;
this.scrollTabTo(index);
this.scrollInto = this.tabList[index].id;
// 释放 tabId
if (this.cacheTab.length > MAX_CACHE_PAGE) {
let cacheIndex = this.cacheTab[0];
this.clearTabData(cacheIndex);
this.cacheTab.splice(0, 1);
}
// const el = this.$refs['tabitem' + index][0];
// animation.transition(el, {
// duration: 3000, //ms
// timingFunction: 'ease',
// delay: 1000 //ms
// });
},
scrollTabTo(index) {
const el = this.$refs['tabitem' + index][0];
let offset = 0;
// TODO fix ios offset
if (index > 0) {
offset = this.tabbarWidth / 2 - this.tabListSize[index].width / 2;
if (this.tabListSize[index].right < this.tabbarWidth / 2) {
offset = this.tabListSize[0].width;
}
}
dom.scrollToElement(el, {
offset: -offset
});
},
//----------------------------
// 左滑右滑选项卡改变选中状态
changeTopTab: function(e) {
var current = e.detail.current;
this.switchTab(current)
this.curIndex = current;
this.playFollowStatus = this.curIndex === 1 ? true : false;
this.playStatus = this.curIndex === 2 ? true : false;
},
// 点击头部选项卡,切换页面
tapFollow: function(current) {
this.curIndex = current;
this.playFollowStatus = this.curIndex === 1 ? true : false;
this.playStatus = this.curIndex === 2 ? true : false;
},
// 下拉刷新改变head的字样显示
showLoading() {
this.isLoading = true;
},
hideLoading() {
this.isLoading = false;
},
letFollowVideoPause() {
this.playFollowStatus = false;
}
}
}
</script>
<style scoped>
/* index start */
.page {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: #000000;
}
/* index end */
/* 顶部选项卡 start */
.header {
position: absolute;
left: 0;
right: 0;
flex-direction: row;
height: 100rpx;
line-height: 100rpx;
align-items: center;
padding-left: 40px;
padding-right: 40px;
}
.header-center {
flex: 1;
flex-direction: row;
align-items: center;
justify-content: center;
}
.header-left,
.header-right {
color: #999;
height: 100rpx;
line-height: 100rpx;
align-items: flex-start;
justify-content: flex-end;
font-family: iconfont;
}
.header-right-search {
height: 100rpx;
/* align-items: flex-start;
justify-content: flex-end; */
}
.header-item {
align-items: center;
margin-left: 6rpx;
margin-right: 6rpx;
}
.header-item-title {
width: 120rpx;
text-align: center;
height: 60rpx;
line-height: 60rpx;
color: #FFFFFF;
font-size: 16px;
font-weight: 600;
}
.header-refresh-title {
width: 300rpx;
text-align: center;
height: 60rpx;
line-height: 60rpx;
color: #FFFFFF;
font-size: 16px;
font-weight: 600;
}
.header-item-line {
height: 5rpx;
line-height: 8rpx;
width: 60rpx;
border-radius: 8rpx;
}
/* 顶部选项卡 end */
/* 选项卡轮播组件 start */
.my-swiper {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
.near-by {
background-color: #000000;
align-items: center;
justify-content: center;
}
.my-follow {
background-color: #000000;
align-items: center;
justify-content: center;
}
/* 选项卡轮播组件 end */
.warn-info {
color: #FFFFFF;
font-size: 36rpx;
font-weight: 600;
}
.normal-img {
width: 50rpx;
height: 50rpx;
opacity: 0.8;
}
/* */
.tab-bar {
/* width: 750upx; */
flex: 1;
height: 84upx;
flex-direction: row;
white-space: nowrap;
justify-content: center;
align-items: center;
}
.uni-tab-item {
display: inline-block;
flex-wrap: nowrap;
/* padding-left: 25px; */
/* padding-right: 25px; */
}
.uni-tab-item-title {
color: #999;
font-size: 30upx;
height: 80upx;
line-height: 80upx;
flex-wrap: nowrap;
white-space: nowrap;
}
.uni-tab-item-title-active {
color: #FFFFFF;
}
.scroll-view-indicator {
position: relative;
height: 2px;
background-color: transparent;
}
.scroll-view-underline {
position: absolute;
top: 0;
bottom: 0;
width: 0;
/* background-color: #007AFF; */
background-color: #FFFFFF;
}
.scroll-view-animation {
transition-duration: 0.2s;
transition-property: left;
}
.tab-bar-line {
height: 1upx;
background-color: #cccccc;
}
</style>

View File

@ -850,7 +850,8 @@ function downloadPopup(data, callback, cancelCallback, rebootCallback) {
popupView.hide();
},
});
}
}
// APPUpdate
export default function (isPrompt = false) {
getCurrentNo((version) => {
getServerNo((res) => {

View File

@ -124,7 +124,8 @@ let isRefreshing = false;
let requests = [];
// 必须使用异步函数,注意
http.interceptors.response.use(
async (response) => {
async (response) => {
console.log(isRefreshing)
console.log(response)
/* 请求之后拦截器。可以使用async await 做异步操作 */
// token存在并且token过期

View File

@ -410,7 +410,9 @@
}
.u-tabs-scroll-box {
position: relative;
position: relative;
display: flex;
flex-direction: row;
}
.u-tabs-scorll-flex {