pretty再次格式化所有文件

This commit is contained in:
zyronon
2024-04-02 15:40:18 +08:00
parent 474859c309
commit 6f165f997a
157 changed files with 26249 additions and 30541 deletions

View File

@@ -1,12 +0,0 @@
# Editor configuration, see http://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = tab
indent_size = 2
end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true
max_line_length = 120

14
.eslintrc.cjs Normal file
View File

@@ -0,0 +1,14 @@
/* eslint-env node */
require('@rushstack/eslint-patch/modern-module-resolution')
module.exports = {
root: true,
'extends': [
'plugin:vue/vue3-essential',
'eslint:recommended',
'@vue/eslint-config-prettier/skip-formatting'
],
parserOptions: {
ecmaVersion: 'latest'
}
}

View File

@@ -1,11 +0,0 @@
{
"singleQuote": true,
"semi": false,
"printWidth": 80,
"tabWidth": 2,
"useTabs": false,
"quoteProps": "as-needed",
"jsxSingleQuote": true,
"vueIndentScriptAndStyle": true,
"endOfLine": "lf"
}

8
.prettierrc.json Normal file
View File

@@ -0,0 +1,8 @@
{
"$schema": "https://json.schemastore.org/prettierrc",
"semi": false,
"tabWidth": 2,
"singleQuote": true,
"printWidth": 100,
"trailingComma": "none"
}

8
jsconfig.json Normal file
View File

@@ -0,0 +1,8 @@
{
"compilerOptions": {
"paths": {
"@/*": ["./src/*"]
}
},
"exclude": ["node_modules", "dist"]
}

View File

@@ -6,7 +6,9 @@
"build": "vite build --mode prod", "build": "vite build --mode prod",
"build-uni-app": "vite build --mode uni", "build-uni-app": "vite build --mode uni",
"report": "vite build", "report": "vite build",
"preview": "vite preview" "preview": "vite preview",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore",
"format": "prettier --write src/"
}, },
"dependencies": { "dependencies": {
"@jambonn/vue-lazyload": "1.0.9", "@jambonn/vue-lazyload": "1.0.9",
@@ -27,15 +29,18 @@
"@iconify/vue": "^4.1.1", "@iconify/vue": "^4.1.1",
"@types/lodash-es": "^4.17.9", "@types/lodash-es": "^4.17.9",
"@vitejs/plugin-vue": "4.0.0", "@vitejs/plugin-vue": "4.0.0",
"@vitejs/plugin-vue-jsx": "3.0.0",
"less": "4.1.3", "less": "4.1.3",
"prettier": "3.2.5",
"rollup-plugin-visualizer": "^5.9.2", "rollup-plugin-visualizer": "^5.9.2",
"unplugin-vue-define-options": "^1.4.1", "unplugin-vue-define-options": "^1.4.1",
"unplugin-vue-macros": "^2.7.10",
"vite": "4.5.2", "vite": "4.5.2",
"vite-plugin-cdn-import": "0.3.5", "vite-plugin-cdn-import": "0.3.5",
"vite-plugin-compression": "^0.5.1", "vite-plugin-compression": "^0.5.1",
"vite-plugin-imagemin": "^0.6.1" "vite-plugin-imagemin": "^0.6.1",
"@rushstack/eslint-patch": "^1.3.3",
"@vitejs/plugin-vue-jsx": "^3.1.0",
"@vue/eslint-config-prettier": "^8.0.0",
"eslint": "^8.49.0",
"eslint-plugin-vue": "^9.17.0",
"prettier": "^3.0.3"
} }
} }

4903
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -9,132 +9,129 @@
<Call /> <Call />
</template> </template>
<script> <script>
/* /*
* try {navigator.control.gesture(false);} catch (e) {} //UC浏览器关闭默认手势事件 * try {navigator.control.gesture(false);} catch (e) {} //UC浏览器关闭默认手势事件
try {navigator.control.longpressMenu(false);} catch (e) {} //关闭长按弹出菜单 try {navigator.control.longpressMenu(false);} catch (e) {} //关闭长按弹出菜单
* */ * */
import { mapActions, mapState } from 'pinia' import { mapActions, mapState } from 'pinia'
import routes from './router/routes' import routes from './router/routes'
import Call from './components/Call' import Call from './components/Call'
import { useBaseStore } from '@/store/pinia' import { useBaseStore } from '@/store/pinia'
export default { export default {
name: 'App', name: 'App',
components: { components: {
Call, Call
}, },
data() { data() {
return { return {
transitionName: 'go', transitionName: 'go'
}
},
computed: {
...mapState(useBaseStore, ['excludeRoutes'])
},
// watch $route 决定使用哪种过渡
watch: {
$route(to, from) {
this.setMaskDialog({ state: false, mode: this.maskDialogMode })
//footer下面的5个按钮对跳不要用动画
let noAnimation = [
'/',
'/home',
'/slide',
'/me',
'/shop',
'/message',
'/publish',
'/home/live',
'slide',
'/test'
]
if (noAnimation.indexOf(from.path) !== -1 && noAnimation.indexOf(to.path) !== -1) {
return (this.transitionName = '')
} }
},
computed: {
...mapState(useBaseStore, ['excludeRoutes']),
},
// watch $route 决定使用哪种过渡
watch: {
$route(to, from) {
this.setMaskDialog({ state: false, mode: this.maskDialogMode })
//footer下面的5个按钮对跳不要用动画 const toDepth = routes.findIndex((v) => v.path === to.path)
let noAnimation = [ const fromDepth = routes.findIndex((v) => v.path === from.path)
'/', this.transitionName = toDepth > fromDepth ? 'go' : 'back'
'/home', }
'/slide', },
'/me', methods: {
'/shop', ...mapActions(useBaseStore, ['init', 'setMaskDialog']),
'/message', setVh() {
'/publish', let vh = window.innerHeight * 0.01
'/home/live', document.documentElement.style.setProperty('--vh', `${vh}px`)
'slide', }
'/test', },
] mounted() {
if ( this.init()
noAnimation.indexOf(from.path) !== -1 && this.setVh()
noAnimation.indexOf(to.path) !== -1 // 监听resize事件 视图大小发生变化就重新计算1vh的值
) { window.addEventListener('resize', () => {
return (this.transitionName = '') location.reload()
}
const toDepth = routes.findIndex((v) => v.path === to.path)
const fromDepth = routes.findIndex((v) => v.path === from.path)
this.transitionName = toDepth > fromDepth ? 'go' : 'back'
},
},
methods: {
...mapActions(useBaseStore, ['init', 'setMaskDialog']),
setVh() {
let vh = window.innerHeight * 0.01
document.documentElement.style.setProperty('--vh', `${vh}px`)
},
},
mounted() {
this.init()
this.setVh() this.setVh()
// 监听resize事件 视图大小发生变化就重新计算1vh的值 })
window.addEventListener('resize', () => {
location.reload()
this.setVh()
})
try { try {
navigator.control.gesture(false) navigator.control.gesture(false)
} catch (e) {} } catch (e) {}
try { try {
navigator.control.longpressMenu(false) navigator.control.longpressMenu(false)
} catch (e) {} } catch (e) {}
document.onselectstart = new Function('return false') //禁止选中文字 document.onselectstart = new Function('return false') //禁止选中文字
},
} }
}
</script> </script>
<style lang="less"> <style lang="less">
@import './assets/less/index'; @import './assets/less/index';
#app { #app {
height: 100%; height: 100%;
width: 100%; width: 100%;
position: relative; position: relative;
} }
.go-enter-from { .go-enter-from {
transform: translate3d(100%, 0, 0); transform: translate3d(100%, 0, 0);
} }
//最终状态 //最终状态
.back-enter-to, .back-enter-to,
.back-enter-from, .back-enter-from,
.go-enter-to, .go-enter-to,
.go-leave-from { .go-leave-from {
transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0);
} }
.go-leave-to { .go-leave-to {
transform: translate3d(-100%, 0, 0); transform: translate3d(-100%, 0, 0);
} }
.go-enter-active, .go-enter-active,
.go-leave-active, .go-leave-active,
.back-enter-active, .back-enter-active,
.back-leave-active { .back-leave-active {
transition: all 0.3s; transition: all 0.3s;
} }
.back-enter-from { .back-enter-from {
transform: translate3d(-100%, 0, 0); transform: translate3d(-100%, 0, 0);
} }
.back-leave-to { .back-leave-to {
transform: translate3d(100%, 0, 0); transform: translate3d(100%, 0, 0);
} }
.fade-enter-active, .fade-enter-active,
.fade-leave-active { .fade-leave-active {
transition: opacity 0.3s ease; transition: opacity 0.3s ease;
} }
.fade-enter-from, .fade-enter-from,
.fade-leave-to { .fade-leave-to {
opacity: 0; opacity: 0;
} }
</style> </style>

View File

@@ -8,8 +8,7 @@ export default {
all: [ all: [
{ {
id: '224e9a00-ffa0-4bc1-bb07-c318c7b02fa5', id: '224e9a00-ffa0-4bc1-bb07-c318c7b02fa5',
avatar: new URL('../../assets/img/icon/avatar/1.png', import.meta.url) avatar: new URL('../../assets/img/icon/avatar/1.png', import.meta.url).href,
.href,
name: '何以为家', name: '何以为家',
sex: '', sex: '',
age: 25, age: 25,
@@ -24,12 +23,11 @@ export default {
account: '234', account: '234',
pinyin: 'H', pinyin: 'H',
select: false, select: false,
type: CONST_VAR.RELATE_ENUM.REQUEST_FOLLOW, type: CONST_VAR.RELATE_ENUM.REQUEST_FOLLOW
}, },
{ {
id: '2b446aa8-5d31-429a-8e39-d4705eb4e900', id: '2b446aa8-5d31-429a-8e39-d4705eb4e900',
avatar: new URL('../../assets/img/icon/avatar/19.png', import.meta.url) avatar: new URL('../../assets/img/icon/avatar/19.png', import.meta.url).href,
.href,
name: '浅唱↘我们的歌', name: '浅唱↘我们的歌',
sex: '', sex: '',
age: 25, age: 25,
@@ -44,12 +42,11 @@ export default {
account: '33453', account: '33453',
pinyin: 'Q', pinyin: 'Q',
select: false, select: false,
type: CONST_VAR.RELATE_ENUM.FOLLOW_ME, type: CONST_VAR.RELATE_ENUM.FOLLOW_ME
}, },
{ {
id: '2d8622b4-7112-4bc7-a0cf-00a268a85504', id: '2d8622b4-7112-4bc7-a0cf-00a268a85504',
avatar: new URL('../../assets/img/icon/avatar/25.png', import.meta.url) avatar: new URL('../../assets/img/icon/avatar/25.png', import.meta.url).href,
.href,
name: '‘心’之天空', name: '‘心’之天空',
sex: '', sex: '',
age: 25, age: 25,
@@ -64,12 +61,11 @@ export default {
account: '234234', account: '234234',
pinyin: '#', pinyin: '#',
select: false, select: false,
type: CONST_VAR.RELATE_ENUM.FOLLOW_HE, type: CONST_VAR.RELATE_ENUM.FOLLOW_HE
}, },
{ {
id: '2e38900b-65f7-426a-8e8b-edb403df35fb', id: '2e38900b-65f7-426a-8e8b-edb403df35fb',
avatar: new URL('../../assets/img/icon/avatar/18.png', import.meta.url) avatar: new URL('../../assets/img/icon/avatar/18.png', import.meta.url).href,
.href,
name: '◇、_保持微笑ゞ', name: '◇、_保持微笑ゞ',
sex: '', sex: '',
age: 25, age: 25,
@@ -84,12 +80,11 @@ export default {
account: '1111', account: '1111',
pinyin: '#', pinyin: '#',
select: false, select: false,
type: CONST_VAR.RELATE_ENUM.FOLLOW_EACH_OTHER, type: CONST_VAR.RELATE_ENUM.FOLLOW_EACH_OTHER
}, },
{ {
id: '3cd53cb5-04f8-4439-ad2b-e57b3f9b8c73', id: '3cd53cb5-04f8-4439-ad2b-e57b3f9b8c73',
avatar: new URL('../../assets/img/icon/avatar/26.png', import.meta.url) avatar: new URL('../../assets/img/icon/avatar/26.png', import.meta.url).href,
.href,
name: '好◇°我会Yi直在●', name: '好◇°我会Yi直在●',
sex: '', sex: '',
age: 25, age: 25,
@@ -103,12 +98,11 @@ export default {
isDelete: 0, isDelete: 0,
account: 'sdfs', account: 'sdfs',
pinyin: 'H', pinyin: 'H',
select: false, select: false
}, },
{ {
id: '46c77017-9dc6-4a48-bf96-560c6e7db06f', id: '46c77017-9dc6-4a48-bf96-560c6e7db06f',
avatar: new URL('../../assets/img/icon/avatar/4.png', import.meta.url) avatar: new URL('../../assets/img/icon/avatar/4.png', import.meta.url).href,
.href,
name: '甫韦茹', name: '甫韦茹',
sex: '', sex: '',
age: 25, age: 25,
@@ -122,12 +116,11 @@ export default {
isDelete: 0, isDelete: 0,
account: 'dgfdfg', account: 'dgfdfg',
pinyin: 'F', pinyin: 'F',
select: false, select: false
}, },
{ {
id: '4df770d7-a414-4e02-8f9e-72ebd87eb93e', id: '4df770d7-a414-4e02-8f9e-72ebd87eb93e',
avatar: new URL('../../assets/img/icon/avatar/12.png', import.meta.url) avatar: new URL('../../assets/img/icon/avatar/12.png', import.meta.url).href,
.href,
name: '幸福泡泡', name: '幸福泡泡',
sex: '', sex: '',
age: 25, age: 25,
@@ -141,12 +134,11 @@ export default {
isDelete: 0, isDelete: 0,
account: 'df', account: 'df',
pinyin: 'X', pinyin: 'X',
select: false, select: false
}, },
{ {
id: '5ebb4d7a-c7ad-43c7-a830-9eb3ee423cb7', id: '5ebb4d7a-c7ad-43c7-a830-9eb3ee423cb7',
avatar: new URL('../../assets/img/icon/avatar/3.png', import.meta.url) avatar: new URL('../../assets/img/icon/avatar/3.png', import.meta.url).href,
.href,
name: '蔡傲安', name: '蔡傲安',
sex: '', sex: '',
age: 25, age: 25,
@@ -160,12 +152,11 @@ export default {
isDelete: 0, isDelete: 0,
account: 'ssss', account: 'ssss',
pinyin: 'C', pinyin: 'C',
select: false, select: false
}, },
{ {
id: '7226092d-a2c5-4ffd-98d7-3b7ac814bca3', id: '7226092d-a2c5-4ffd-98d7-3b7ac814bca3',
avatar: new URL('../../assets/img/icon/avatar/16.png', import.meta.url) avatar: new URL('../../assets/img/icon/avatar/16.png', import.meta.url).href,
.href,
name: '心若向阳无谓伤悲', name: '心若向阳无谓伤悲',
sex: '', sex: '',
age: 25, age: 25,
@@ -179,12 +170,11 @@ export default {
isDelete: 0, isDelete: 0,
account: 'asdfasd', account: 'asdfasd',
pinyin: 'X', pinyin: 'X',
select: false, select: false
}, },
{ {
id: '72aef2a9-5573-4205-9288-706e19bccc7f', id: '72aef2a9-5573-4205-9288-706e19bccc7f',
avatar: new URL('../../assets/img/icon/avatar/10.png', import.meta.url) avatar: new URL('../../assets/img/icon/avatar/10.png', import.meta.url).href,
.href,
name: 'A倒影着稚嫩的少年', name: 'A倒影着稚嫩的少年',
sex: '', sex: '',
age: 25, age: 25,
@@ -198,12 +188,11 @@ export default {
isDelete: 0, isDelete: 0,
account: 'wfghdf', account: 'wfghdf',
pinyin: '#', pinyin: '#',
select: false, select: false
}, },
{ {
id: '77c82d2e-9be1-45c2-a733-00445d2e7f2c', id: '77c82d2e-9be1-45c2-a733-00445d2e7f2c',
avatar: new URL('../../assets/img/icon/avatar/22.png', import.meta.url) avatar: new URL('../../assets/img/icon/avatar/22.png', import.meta.url).href,
.href,
name: '一只喵的旅行。', name: '一只喵的旅行。',
sex: '', sex: '',
age: 25, age: 25,
@@ -217,12 +206,11 @@ export default {
isDelete: 0, isDelete: 0,
account: 'sadf', account: 'sadf',
pinyin: 'Y', pinyin: 'Y',
select: false, select: false
}, },
{ {
id: '7b30566d-70eb-4a31-ae43-200917269a43', id: '7b30566d-70eb-4a31-ae43-200917269a43',
avatar: new URL('../../assets/img/icon/avatar/14.png', import.meta.url) avatar: new URL('../../assets/img/icon/avatar/14.png', import.meta.url).href,
.href,
name: '℉阳光下的小情绪', name: '℉阳光下的小情绪',
sex: '', sex: '',
age: 25, age: 25,
@@ -236,12 +224,11 @@ export default {
isDelete: 0, isDelete: 0,
account: 'asdfa', account: 'asdfa',
pinyin: '#', pinyin: '#',
select: false, select: false
}, },
{ {
id: '90c6ccd8-0653-4789-9348-28fba06d6ae3', id: '90c6ccd8-0653-4789-9348-28fba06d6ae3',
avatar: new URL('../../assets/img/icon/avatar/11.png', import.meta.url) avatar: new URL('../../assets/img/icon/avatar/11.png', import.meta.url).href,
.href,
name: '思念一直在', name: '思念一直在',
sex: '', sex: '',
age: 25, age: 25,
@@ -255,12 +242,11 @@ export default {
isDelete: 0, isDelete: 0,
account: 'as', account: 'as',
pinyin: 'S', pinyin: 'S',
select: false, select: false
}, },
{ {
id: 'a2c1310f-1a3c-430f-9b7c-557b9ccdd33d', id: 'a2c1310f-1a3c-430f-9b7c-557b9ccdd33d',
avatar: new URL('../../assets/img/icon/avatar/9.png', import.meta.url) avatar: new URL('../../assets/img/icon/avatar/9.png', import.meta.url).href,
.href,
name: '阎韶丽', name: '阎韶丽',
sex: '', sex: '',
age: 25, age: 25,
@@ -274,12 +260,11 @@ export default {
isDelete: 0, isDelete: 0,
account: 'vbvd', account: 'vbvd',
pinyin: 'Y', pinyin: 'Y',
select: false, select: false
}, },
{ {
id: 'a7443b4f-b0fa-4409-a693-5f090aa763ee', id: 'a7443b4f-b0fa-4409-a693-5f090aa763ee',
avatar: new URL('../../assets/img/icon/avatar/5.png', import.meta.url) avatar: new URL('../../assets/img/icon/avatar/5.png', import.meta.url).href,
.href,
name: '马佳婉清', name: '马佳婉清',
sex: '', sex: '',
age: 25, age: 25,
@@ -293,12 +278,11 @@ export default {
isDelete: 0, isDelete: 0,
account: 'sdf', account: 'sdf',
pinyin: 'M', pinyin: 'M',
select: false, select: false
}, },
{ {
id: 'b49fd828-f8a7-4be0-a3bc-0a8fa312b2e8', id: 'b49fd828-f8a7-4be0-a3bc-0a8fa312b2e8',
avatar: new URL('../../assets/img/icon/avatar/0.png', import.meta.url) avatar: new URL('../../assets/img/icon/avatar/0.png', import.meta.url).href,
.href,
name: '倒影着稚嫩的少年', name: '倒影着稚嫩的少年',
sex: '', sex: '',
age: 25, age: 25,
@@ -312,12 +296,11 @@ export default {
isDelete: 0, isDelete: 0,
account: 'eeee', account: 'eeee',
pinyin: 'D', pinyin: 'D',
select: false, select: false
}, },
{ {
id: 'b632bffe-1cfb-408a-8255-b558e2faf49a', id: 'b632bffe-1cfb-408a-8255-b558e2faf49a',
avatar: new URL('../../assets/img/icon/avatar/8.png', import.meta.url) avatar: new URL('../../assets/img/icon/avatar/8.png', import.meta.url).href,
.href,
name: '买易槐', name: '买易槐',
sex: '', sex: '',
age: 25, age: 25,
@@ -331,12 +314,11 @@ export default {
isDelete: 0, isDelete: 0,
account: 'xczxc', account: 'xczxc',
pinyin: 'M', pinyin: 'M',
select: false, select: false
}, },
{ {
id: 'c01f10dd-a270-42ab-876f-64a8beb22a69', id: 'c01f10dd-a270-42ab-876f-64a8beb22a69',
avatar: new URL('../../assets/img/icon/avatar/7.png', import.meta.url) avatar: new URL('../../assets/img/icon/avatar/7.png', import.meta.url).href,
.href,
name: '章昊苍', name: '章昊苍',
sex: '', sex: '',
age: 25, age: 25,
@@ -350,12 +332,11 @@ export default {
isDelete: 0, isDelete: 0,
account: 'gggggggggr', account: 'gggggggggr',
pinyin: 'Z', pinyin: 'Z',
select: false, select: false
}, },
{ {
id: 'd0bf11a3-a25b-4865-a047-c67de8e8af7b', id: 'd0bf11a3-a25b-4865-a047-c67de8e8af7b',
avatar: new URL('../../assets/img/icon/avatar/2.png', import.meta.url) avatar: new URL('../../assets/img/icon/avatar/2.png', import.meta.url).href,
.href,
name: '凌依晨', name: '凌依晨',
sex: '', sex: '',
age: 25, age: 25,
@@ -369,12 +350,11 @@ export default {
isDelete: 0, isDelete: 0,
account: '12', account: '12',
pinyin: 'L', pinyin: 'L',
select: false, select: false
}, },
{ {
id: 'd300b7a5-115d-41ba-a071-7d1781da331f', id: 'd300b7a5-115d-41ba-a071-7d1781da331f',
avatar: new URL('../../assets/img/icon/avatar/23.png', import.meta.url) avatar: new URL('../../assets/img/icon/avatar/23.png', import.meta.url).href,
.href,
name: '为你锁住心', name: '为你锁住心',
sex: '', sex: '',
age: 25, age: 25,
@@ -388,12 +368,11 @@ export default {
isDelete: 0, isDelete: 0,
account: '1629993515', account: '1629993515',
pinyin: 'W', pinyin: 'W',
select: false, select: false
}, },
{ {
id: 'deceba30-80fc-45c2-bd56-8d65091bb104', id: 'deceba30-80fc-45c2-bd56-8d65091bb104',
avatar: new URL('../../assets/img/icon/avatar/13.png', import.meta.url) avatar: new URL('../../assets/img/icon/avatar/13.png', import.meta.url).href,
.href,
name: '原味青春', name: '原味青春',
sex: '', sex: '',
age: 25, age: 25,
@@ -407,12 +386,11 @@ export default {
isDelete: 0, isDelete: 0,
account: 'werwe', account: 'werwe',
pinyin: 'Y', pinyin: 'Y',
select: false, select: false
}, },
{ {
id: 'e0c3d20d-5978-4339-962f-cffc6e29aff1', id: 'e0c3d20d-5978-4339-962f-cffc6e29aff1',
avatar: new URL('../../assets/img/icon/avatar/24.png', import.meta.url) avatar: new URL('../../assets/img/icon/avatar/24.png', import.meta.url).href,
.href,
name: '一起走过的日子°', name: '一起走过的日子°',
sex: '', sex: '',
age: 25, age: 25,
@@ -426,12 +404,11 @@ export default {
isDelete: 0, isDelete: 0,
account: 'dfgdfg', account: 'dfgdfg',
pinyin: 'Y', pinyin: 'Y',
select: false, select: false
}, },
{ {
id: 'e1fb6274-10fa-4d50-b9b1-6eefacfc2341', id: 'e1fb6274-10fa-4d50-b9b1-6eefacfc2341',
avatar: new URL('../../assets/img/icon/avatar/15.png', import.meta.url) avatar: new URL('../../assets/img/icon/avatar/15.png', import.meta.url).href,
.href,
name: '看,熟悉旳风景', name: '看,熟悉旳风景',
sex: '', sex: '',
age: 25, age: 25,
@@ -445,12 +422,11 @@ export default {
isDelete: 0, isDelete: 0,
account: 'aasdasd', account: 'aasdasd',
pinyin: 'K', pinyin: 'K',
select: false, select: false
}, },
{ {
id: 'eab1ef9b-70e6-4249-8d78-b4f6e1b0cb08', id: 'eab1ef9b-70e6-4249-8d78-b4f6e1b0cb08',
avatar: new URL('../../assets/img/icon/avatar/20.png', import.meta.url) avatar: new URL('../../assets/img/icon/avatar/20.png', import.meta.url).href,
.href,
name: 'dear°学会微笑', name: 'dear°学会微笑',
sex: '', sex: '',
age: 25, age: 25,
@@ -464,12 +440,11 @@ export default {
isDelete: 0, isDelete: 0,
account: 'gggggg', account: 'gggggg',
pinyin: '#', pinyin: '#',
select: false, select: false
}, },
{ {
id: 'ecb405e2-d057-4c85-a12b-a5fe9a7b8a05', id: 'ecb405e2-d057-4c85-a12b-a5fe9a7b8a05',
avatar: new URL('../../assets/img/icon/avatar/6.png', import.meta.url) avatar: new URL('../../assets/img/icon/avatar/6.png', import.meta.url).href,
.href,
name: '富察昕昕', name: '富察昕昕',
sex: '', sex: '',
age: 25, age: 25,
@@ -483,12 +458,11 @@ export default {
isDelete: 0, isDelete: 0,
account: 'ghjg', account: 'ghjg',
pinyin: 'F', pinyin: 'F',
select: false, select: false
}, },
{ {
id: 'f09652a3-d6e1-4517-a15e-583a24a250e1', id: 'f09652a3-d6e1-4517-a15e-583a24a250e1',
avatar: new URL('../../assets/img/icon/avatar/17.png', import.meta.url) avatar: new URL('../../assets/img/icon/avatar/17.png', import.meta.url).href,
.href,
name: '蓝天下的迷彩?', name: '蓝天下的迷彩?',
sex: '', sex: '',
age: 25, age: 25,
@@ -502,12 +476,11 @@ export default {
isDelete: 0, isDelete: 0,
account: 'yhjh', account: 'yhjh',
pinyin: 'L', pinyin: 'L',
select: false, select: false
}, },
{ {
id: 'f676cc30-cc81-487a-9450-cbb1f3c5cde8', id: 'f676cc30-cc81-487a-9450-cbb1f3c5cde8',
avatar: new URL('../../assets/img/icon/avatar/21.png', import.meta.url) avatar: new URL('../../assets/img/icon/avatar/21.png', import.meta.url).href,
.href,
name: '伱的微笑', name: '伱的微笑',
sex: '', sex: '',
age: 25, age: 25,
@@ -521,14 +494,13 @@ export default {
isDelete: 0, isDelete: 0,
account: 'ghj', account: 'ghj',
pinyin: 'N', pinyin: 'N',
select: false, select: false
}, }
], ],
recent: [ recent: [
{ {
id: '3cd53cb5-04f8-4439-ad2b-e57b3f9b8c73', id: '3cd53cb5-04f8-4439-ad2b-e57b3f9b8c73',
avatar: new URL('../../assets/img/icon/avatar/26.png', import.meta.url) avatar: new URL('../../assets/img/icon/avatar/26.png', import.meta.url).href,
.href,
name: '好◇°我会Yi直在●', name: '好◇°我会Yi直在●',
sex: '', sex: '',
age: 25, age: 25,
@@ -542,12 +514,11 @@ export default {
isDelete: 0, isDelete: 0,
account: 'sdfs', account: 'sdfs',
pinyin: 'H', pinyin: 'H',
select: false, select: false
}, },
{ {
id: '77c82d2e-9be1-45c2-a733-00445d2e7f2c', id: '77c82d2e-9be1-45c2-a733-00445d2e7f2c',
avatar: new URL('../../assets/img/icon/avatar/22.png', import.meta.url) avatar: new URL('../../assets/img/icon/avatar/22.png', import.meta.url).href,
.href,
name: '一只喵的旅行。', name: '一只喵的旅行。',
sex: '', sex: '',
age: 25, age: 25,
@@ -561,14 +532,13 @@ export default {
isDelete: 0, isDelete: 0,
account: 'sadf', account: 'sadf',
pinyin: 'Y', pinyin: 'Y',
select: false, select: false
}, }
], ],
eachOther: [ eachOther: [
{ {
id: '2b446aa8-5d31-429a-8e39-d4705eb4e900', id: '2b446aa8-5d31-429a-8e39-d4705eb4e900',
avatar: new URL('../../assets/img/icon/avatar/19.png', import.meta.url) avatar: new URL('../../assets/img/icon/avatar/19.png', import.meta.url).href,
.href,
name: '浅唱↘我们的歌', name: '浅唱↘我们的歌',
sex: '', sex: '',
age: 25, age: 25,
@@ -582,12 +552,11 @@ export default {
isDelete: 0, isDelete: 0,
account: '33453', account: '33453',
pinyin: 'Q', pinyin: 'Q',
select: false, select: false
}, },
{ {
id: 'eab1ef9b-70e6-4249-8d78-b4f6e1b0cb08', id: 'eab1ef9b-70e6-4249-8d78-b4f6e1b0cb08',
avatar: new URL('../../assets/img/icon/avatar/20.png', import.meta.url) avatar: new URL('../../assets/img/icon/avatar/20.png', import.meta.url).href,
.href,
name: 'dear°学会微笑', name: 'dear°学会微笑',
sex: '', sex: '',
age: 25, age: 25,
@@ -601,208 +570,190 @@ export default {
isDelete: 0, isDelete: 0,
account: 'gggggg', account: 'gggggg',
pinyin: '#', pinyin: '#',
select: false, select: false
}, }
], ]
}, },
music: [ music: [
{ {
name: '龙卷风', name: '龙卷风',
mp3: 'http://im5.tongbu.com/rings/singerring/zt_uunGo_1/5605.mp3', mp3: 'http://im5.tongbu.com/rings/singerring/zt_uunGo_1/5605.mp3',
cover: new URL('../../assets/img/music-cover/1.jpg', import.meta.url) cover: new URL('../../assets/img/music-cover/1.jpg', import.meta.url).href,
.href,
author: '周杰伦', author: '周杰伦',
duration: 99, duration: 99,
use_count: 37441000, use_count: 37441000,
is_collect: false, is_collect: false,
is_play: false, is_play: false
}, },
{ {
name: '爱在西元前', name: '爱在西元前',
mp3: 'http://m3.8js.net:99/1916/501204165042405.mp3', mp3: 'http://m3.8js.net:99/1916/501204165042405.mp3',
cover: new URL('../../assets/img/music-cover/2.jpg', import.meta.url) cover: new URL('../../assets/img/music-cover/2.jpg', import.meta.url).href,
.href,
author: '周杰伦', author: '周杰伦',
duration: 60, duration: 60,
use_count: 37441000, use_count: 37441000,
is_collect: false, is_collect: false,
is_play: false, is_play: false
}, },
{ {
name: '蜗牛', name: '蜗牛',
mp3: 'http://im5.tongbu.com/rings/singerring/zt_uunGo_1/3684.mp3', mp3: 'http://im5.tongbu.com/rings/singerring/zt_uunGo_1/3684.mp3',
cover: new URL('../../assets/img/music-cover/3.jpg', import.meta.url) cover: new URL('../../assets/img/music-cover/3.jpg', import.meta.url).href,
.href,
author: '周杰伦', author: '周杰伦',
duration: 60, duration: 60,
use_count: 37441000, use_count: 37441000,
is_collect: false, is_collect: false,
is_play: false, is_play: false
}, },
{ {
name: '半岛铁盒', name: '半岛铁盒',
mp3: 'http://m3.8js.net:99/2016n/46/94745.mp3', mp3: 'http://m3.8js.net:99/2016n/46/94745.mp3',
cover: new URL('../../assets/img/music-cover/4.jpg', import.meta.url) cover: new URL('../../assets/img/music-cover/4.jpg', import.meta.url).href,
.href,
author: '周杰伦', author: '周杰伦',
duration: 60, duration: 60,
use_count: 37441000, use_count: 37441000,
is_collect: false, is_collect: false,
is_play: false, is_play: false
}, },
{ {
name: '轨迹', name: '轨迹',
mp3: 'http://m3.8js.net:99/1832/411204324135934.mp3', mp3: 'http://m3.8js.net:99/1832/411204324135934.mp3',
cover: new URL('../../assets/img/music-cover/5.jpg', import.meta.url) cover: new URL('../../assets/img/music-cover/5.jpg', import.meta.url).href,
.href,
author: '周杰伦', author: '周杰伦',
duration: 60, duration: 60,
use_count: 37441000, use_count: 37441000,
is_collect: false, is_collect: false,
is_play: false, is_play: false
}, },
{ {
name: '七里香', name: '七里香',
mp3: 'http://m3.8js.net:99/2016n/14/53717.mp3', mp3: 'http://m3.8js.net:99/2016n/14/53717.mp3',
cover: new URL('../../assets/img/music-cover/6.jpg', import.meta.url) cover: new URL('../../assets/img/music-cover/6.jpg', import.meta.url).href,
.href,
author: '周杰伦', author: '周杰伦',
duration: 60, duration: 60,
use_count: 37441000, use_count: 37441000,
is_collect: false, is_collect: false,
is_play: false, is_play: false
}, },
{ {
name: '发如雪', name: '发如雪',
mp3: 'http://m3.8js.net:99/2014/211204142150965.mp3', mp3: 'http://m3.8js.net:99/2014/211204142150965.mp3',
cover: new URL('../../assets/img/music-cover/7.jpg', import.meta.url) cover: new URL('../../assets/img/music-cover/7.jpg', import.meta.url).href,
.href,
author: '周杰伦', author: '周杰伦',
duration: 60, duration: 60,
use_count: 37441000, use_count: 37441000,
is_collect: false, is_collect: false,
is_play: false, is_play: false
}, },
{ {
name: '霍元甲', name: '霍元甲',
mp3: 'http://m3.8js.net:99/1921/261204212643140.mp3', mp3: 'http://m3.8js.net:99/1921/261204212643140.mp3',
cover: new URL('../../assets/img/music-cover/8.jpg', import.meta.url) cover: new URL('../../assets/img/music-cover/8.jpg', import.meta.url).href,
.href,
author: '周杰伦', author: '周杰伦',
duration: 60, duration: 60,
use_count: 37441000, use_count: 37441000,
is_collect: false, is_collect: false,
is_play: false, is_play: false
}, },
{ {
name: '千里之外(周杰伦/费玉清)', name: '千里之外(周杰伦/费玉清)',
mp3: 'http://im5.tongbu.com/rings/singerring/zt_uunGo_1/121.mp3', mp3: 'http://im5.tongbu.com/rings/singerring/zt_uunGo_1/121.mp3',
cover: new URL('../../assets/img/music-cover/9.jpg', import.meta.url) cover: new URL('../../assets/img/music-cover/9.jpg', import.meta.url).href,
.href,
author: '周杰伦', author: '周杰伦',
duration: 60, duration: 60,
use_count: 37441000, use_count: 37441000,
is_collect: false, is_collect: false,
is_play: false, is_play: false
}, },
{ {
name: '菊花台', name: '菊花台',
mp3: 'http://im5.tongbu.com/rings/singerring/zt_uunGo_1/2022.mp3', mp3: 'http://im5.tongbu.com/rings/singerring/zt_uunGo_1/2022.mp3',
cover: new URL('../../assets/img/music-cover/10.jpg', import.meta.url) cover: new URL('../../assets/img/music-cover/10.jpg', import.meta.url).href,
.href,
author: '周杰伦', author: '周杰伦',
duration: 60, duration: 60,
use_count: 37441000, use_count: 37441000,
is_collect: false, is_collect: false,
is_play: false, is_play: false
}, },
{ {
name: '不能说的秘密', name: '不能说的秘密',
mp3: 'http://im5.tongbu.com/rings/singerring/zt_uunGo_1/165.mp3', mp3: 'http://im5.tongbu.com/rings/singerring/zt_uunGo_1/165.mp3',
cover: new URL('../../assets/img/music-cover/11.jpg', import.meta.url) cover: new URL('../../assets/img/music-cover/11.jpg', import.meta.url).href,
.href,
author: '周杰伦', author: '周杰伦',
duration: 60, duration: 60,
use_count: 37441000, use_count: 37441000,
is_collect: false, is_collect: false,
is_play: false, is_play: false
}, },
{ {
name: '牛仔很忙', name: '牛仔很忙',
mp3: 'http://im5.tongbu.com/rings/singerring/zt_uunGo_1/219.mp3', mp3: 'http://im5.tongbu.com/rings/singerring/zt_uunGo_1/219.mp3',
cover: new URL('../../assets/img/music-cover/12.jpg', import.meta.url) cover: new URL('../../assets/img/music-cover/12.jpg', import.meta.url).href,
.href,
author: '周杰伦', author: '周杰伦',
duration: 60, duration: 60,
use_count: 37441000, use_count: 37441000,
is_collect: false, is_collect: false,
is_play: false, is_play: false
}, },
{ {
name: '给我一首歌的时间', name: '给我一首歌的时间',
mp3: 'http://m3.8js.net:99/1938/041204380445445.mp3', mp3: 'http://m3.8js.net:99/1938/041204380445445.mp3',
cover: new URL('../../assets/img/music-cover/13.jpg', import.meta.url) cover: new URL('../../assets/img/music-cover/13.jpg', import.meta.url).href,
.href,
author: '周杰伦', author: '周杰伦',
duration: 60, duration: 60,
use_count: 37441000, use_count: 37441000,
is_collect: false, is_collect: false,
is_play: false, is_play: false
}, },
{ {
name: '烟花易冷', name: '烟花易冷',
mp3: 'http://m3.8js.net:99/1828/051204280535192.mp3', mp3: 'http://m3.8js.net:99/1828/051204280535192.mp3',
cover: new URL('../../assets/img/music-cover/14.jpg', import.meta.url) cover: new URL('../../assets/img/music-cover/14.jpg', import.meta.url).href,
.href,
author: '周杰伦', author: '周杰伦',
duration: 60, duration: 60,
use_count: 37441000, use_count: 37441000,
is_collect: false, is_collect: false,
is_play: false, is_play: false
}, },
{ {
name: '惊叹号', name: '惊叹号',
mp3: 'http://m3.8js.net:99/20111103/150.mp3', mp3: 'http://m3.8js.net:99/20111103/150.mp3',
cover: new URL('../../assets/img/music-cover/15.jpg', import.meta.url) cover: new URL('../../assets/img/music-cover/15.jpg', import.meta.url).href,
.href,
author: '周杰伦', author: '周杰伦',
duration: 60, duration: 60,
use_count: 37441000, use_count: 37441000,
is_collect: false, is_collect: false,
is_play: false, is_play: false
}, },
{ {
name: '明明就', name: '明明就',
mp3: 'http://m3.8js.net:99/2016n/27/96537.mp3', mp3: 'http://m3.8js.net:99/2016n/27/96537.mp3',
cover: new URL('../../assets/img/music-cover/16.jpg', import.meta.url) cover: new URL('../../assets/img/music-cover/16.jpg', import.meta.url).href,
.href,
author: '周杰伦', author: '周杰伦',
duration: 60, duration: 60,
use_count: 37441000, use_count: 37441000,
is_collect: false, is_collect: false,
is_play: false, is_play: false
}, },
{ {
name: '算什么男人', name: '算什么男人',
mp3: 'http://m3.8js.net:99/20150107/429.mp3', mp3: 'http://m3.8js.net:99/20150107/429.mp3',
cover: new URL('../../assets/img/music-cover/17.jpg', import.meta.url) cover: new URL('../../assets/img/music-cover/17.jpg', import.meta.url).href,
.href,
author: '周杰伦', author: '周杰伦',
duration: 60, duration: 60,
use_count: 37441000, use_count: 37441000,
is_collect: false, is_collect: false,
is_play: false, is_play: false
}, },
{ {
name: '告白气球', name: '告白气球',
mp3: 'http://m3.8js.net:99/20161016/481.mp3', mp3: 'http://m3.8js.net:99/20161016/481.mp3',
cover: new URL('../../assets/img/music-cover/18.jpg', import.meta.url) cover: new URL('../../assets/img/music-cover/18.jpg', import.meta.url).href,
.href,
author: '周杰伦', author: '周杰伦',
duration: 60, duration: 60,
use_count: 37441000, use_count: 37441000,
is_collect: false, is_collect: false,
is_play: false, is_play: false
}, }
], ]
} }

View File

@@ -11,51 +11,51 @@
</template> </template>
<script> <script>
export default { export default {
name: 'AutoInput', name: 'AutoInput',
props: { props: {
modelValue: String, modelValue: String,
placeholder: { placeholder: {
type: String, type: String,
default: '留下你的精彩评论吧', default: '留下你的精彩评论吧'
}, }
}, },
mounted() { mounted() {
// this.$refs.input.setAttribute("placeholder", "改变") // this.$refs.input.setAttribute("placeholder", "改变")
}, },
computed: {}, computed: {},
data: function () { data: function () {
return {} return {}
}, },
methods: { methods: {
changeText(e) { changeText(e) {
this.$emit('update:modelValue', this.$el.innerText) this.$emit('update:modelValue', this.$el.innerText)
}, }
},
} }
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
.auto-input { .auto-input {
font-size: 14rem; font-size: 14rem;
width: 100%; width: 100%;
max-height: 70rem; max-height: 70rem;
overflow-y: scroll; overflow-y: scroll;
padding: 0 5rem; padding: 0 5rem;
outline: none; outline: none;
} }
.auto-input::-webkit-scrollbar { .auto-input::-webkit-scrollbar {
width: 0 !important; width: 0 !important;
} }
.auto-input:empty::before { .auto-input:empty::before {
/*content: "留下你的精彩评论吧";*/ /*content: "留下你的精彩评论吧";*/
content: attr(placeholder); content: attr(placeholder);
color: #999999; color: #999999;
} }
.auto-input:focus::before { .auto-input:focus::before {
content: none; content: none;
} }
</style> </style>

View File

@@ -2,50 +2,48 @@
<img class="close" ref="img" :src="src" /> <img class="close" ref="img" :src="src" />
</template> </template>
<script> <script>
export default { export default {
name: 'Back', name: 'Back',
props: { props: {
mode: { mode: {
type: String, type: String,
default: 'gray', default: 'gray'
},
img: {
type: String,
default: 'back',
},
direction: {
type: String,
default: 'left',
},
scale: {
type: [Number, String],
default: 1,
},
}, },
data() { img: {
return {} type: String,
default: 'back'
}, },
computed: { direction: {
src() { type: String,
return new URL( default: 'left'
`../assets/img/icon/components/${this.mode}-${this.img}.png`,
import.meta.url,
).href
},
}, },
mounted() { scale: {
this.$setCss( type: [Number, String],
this.$refs.img, default: 1
'transform', }
`rotate(${this.direction === 'left' ? '0' : '180'}deg) scale(${this.scale})`, },
) data() {
}, return {}
methods: {}, },
} computed: {
src() {
return new URL(`../assets/img/icon/components/${this.mode}-${this.img}.png`, import.meta.url)
.href
}
},
mounted() {
this.$setCss(
this.$refs.img,
'transform',
`rotate(${this.direction === 'left' ? '0' : '180'}deg) scale(${this.scale})`
)
},
methods: {}
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
img { img {
width: 20rem; width: 20rem;
} }
</style> </style>

View File

@@ -9,250 +9,246 @@
<slot name="prefix"></slot> <slot name="prefix"></slot>
<slot v-if="showText"></slot> <slot v-if="showText"></slot>
<slot name="suffix"></slot> <slot name="suffix"></slot>
<div <div :style="{ width: progress + '%' }" v-if="$props.progress" class="progress"></div>
:style="{ width: progress + '%' }"
v-if="$props.progress"
class="progress"
></div>
</div> </div>
</template> </template>
<script> <script>
export default { export default {
name: 'BaseButton', name: 'BaseButton',
props: { props: {
loading: { loading: {
type: Boolean, type: Boolean,
default: false, default: false
},
progress: {
type: Number,
default: null,
},
loadingWithText: {
type: Boolean,
default: false,
},
disabled: {
type: Boolean,
default: false,
},
type: {
type: String,
default: '',
},
active: {
type: Boolean,
default: true,
},
border: {
type: Boolean,
default: true,
},
size: {
type: String,
default: 'normal',
//small
},
radius: {
type: String,
default: '3',
},
}, },
data() { progress: {
return {} type: Number,
default: null
}, },
computed: { loadingWithText: {
class1() { type: Boolean,
return [ default: false
this.type,
this.active ? '' : 'no-active',
this.border ? '' : 'no-border',
this.disabled && 'disabled',
this.size,
]
},
showText() {
if (this.loading) {
return this.loadingWithText
}
return true
},
}, },
created() {}, disabled: {
methods: { type: Boolean,
check() { default: false
if (this.disabled) return
if (this.loading) return
return this.$emit('click')
},
}, },
type: {
type: String,
default: ''
},
active: {
type: Boolean,
default: true
},
border: {
type: Boolean,
default: true
},
size: {
type: String,
default: 'normal'
//small
},
radius: {
type: String,
default: '3'
}
},
data() {
return {}
},
computed: {
class1() {
return [
this.type,
this.active ? '' : 'no-active',
this.border ? '' : 'no-border',
this.disabled && 'disabled',
this.size
]
},
showText() {
if (this.loading) {
return this.loadingWithText
}
return true
}
},
created() {},
methods: {
check() {
if (this.disabled) return
if (this.loading) return
return this.$emit('click')
}
} }
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '../assets/less/index'; @import '../assets/less/index';
.button { .button {
color: white; color: white;
height: 40rem; height: 40rem;
line-height: 40rem; line-height: 40rem;
//width: 100%; //width: 100%;
font-size: 14rem; font-size: 14rem;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
position: relative; position: relative;
.progress { .progress {
border-radius: 3rem; border-radius: 3rem;
position: absolute; position: absolute;
left: 0; left: 0;
top: 0; top: 0;
height: 100%; height: 100%;
width: 0; width: 0;
background: rgb(80 80 80 / 10%); background: rgb(80 80 80 / 10%);
} }
img { img {
height: 16rem; height: 16rem;
margin-right: 5rem; margin-right: 5rem;
animation: animal 0.8s infinite linear; animation: animal 0.8s infinite linear;
@keyframes animal { @keyframes animal {
0% { 0% {
transform: rotate(-360deg); transform: rotate(-360deg);
} }
100% { 100% {
transform: rotate(0deg); transform: rotate(0deg);
}
} }
} }
}
&.primary {
background: var(--primary-btn-color);
}
&.dark {
background: var(--second-btn-color);
color: var(--second-text-color);
}
&.dark2 {
background: rgb(36, 36, 36);
color: #fff;
}
&.green {
background: rgb(9, 184, 91);
color: white;
}
&.qqzone {
background: rgb(240, 179, 2);
color: white;
}
&.qq {
background: rgb(27, 177, 228);
color: white;
}
&.webo {
background: rgb(242, 95, 67);
color: white;
}
&.white {
background: white;
color: black;
border: 1px solid gainsboro;
}
&.info {
background: rgba(161, 139, 129, 0.3);
color: white;
}
&:active {
&.primary { &.primary {
background: var(--primary-btn-color); background: var(--disable-primary-btn-color);
} }
&.dark { &.dark {
background: var(--second-btn-color); background: var(--second-btn-color-tran);
color: var(--second-text-color);
}
&.dark2 {
background: rgb(36, 36, 36);
color: #fff;
} }
&.green { &.green {
background: rgb(9, 184, 91); opacity: 0.8;
color: white;
} }
&.qqzone { &.qqzone {
background: rgb(240, 179, 2); opacity: 0.8;
color: white;
} }
&.qq { &.qq {
background: rgb(27, 177, 228); opacity: 0.8;
color: white;
} }
&.webo { &.webo {
background: rgb(242, 95, 67); opacity: 0.8;
}
}
&.no-active {
&:active {
&.primary {
background: var(--primary-btn-color);
}
&.dark {
background: var(--second-btn-color);
}
&.white {
background: white;
}
&.green {
background: rgb(9, 184, 91);
}
&.qqzone {
background: rgb(27, 177, 228);
}
&.qq {
background: rgb(27, 177, 228);
}
}
}
&.disabled {
&.primary {
background: gainsboro;
color: white; color: white;
} }
&.white { &.white {
background: white; background: lightgray;
color: black;
border: 1px solid gainsboro;
}
&.info {
background: rgba(161, 139, 129, 0.3);
color: white;
} }
&:active { &:active {
&.primary {
background: var(--disable-primary-btn-color);
}
&.dark {
background: var(--second-btn-color-tran);
}
&.green {
opacity: 0.8;
}
&.qqzone {
opacity: 0.8;
}
&.qq {
opacity: 0.8;
}
&.webo {
opacity: 0.8;
}
}
&.no-active {
&:active {
&.primary {
background: var(--primary-btn-color);
}
&.dark {
background: var(--second-btn-color);
}
&.white {
background: white;
}
&.green {
background: rgb(9, 184, 91);
}
&.qqzone {
background: rgb(27, 177, 228);
}
&.qq {
background: rgb(27, 177, 228);
}
}
}
&.disabled {
&.primary { &.primary {
background: gainsboro; background: gainsboro;
color: white;
} }
&.white {
background: lightgray;
}
&:active {
&.primary {
background: gainsboro;
}
}
}
&.no-border {
border: none !important;
background: rgb(212 212 212 / 36%);
}
&.small {
font-size: 12rem;
width: 62rem;
height: 26rem;
} }
} }
&.no-border {
border: none !important;
background: rgb(212 212 212 / 36%);
}
&.small {
font-size: 12rem;
width: 62rem;
height: 26rem;
}
}
</style> </style>

View File

@@ -1,13 +1,7 @@
<template> <template>
<div id="BaseHeader" :class="[isFixed ? 'fixed' : '']"> <div id="BaseHeader" :class="[isFixed ? 'fixed' : '']">
<div class="header"> <div class="header">
<dy-back <dy-back :mode="backMode" :img="backImg" @click="back()" class="left" direction="left" />
:mode="backMode"
:img="backImg"
@click="back()"
class="left"
direction="left"
/>
<slot name="center"><span></span></slot> <slot name="center"><span></span></slot>
<slot name="right"><span></span></slot> <slot name="right"><span></span></slot>
</div> </div>
@@ -15,79 +9,79 @@
</div> </div>
</template> </template>
<script> <script>
export default { export default {
name: 'BaseHeader', name: 'BaseHeader',
components: {}, components: {},
props: { props: {
backMode: { backMode: {
type: String, type: String,
default: 'gray', default: 'gray'
},
backImg: {
type: String,
default: 'back',
},
isClose: {
type: Boolean,
default: false,
},
isFixed: {
type: Boolean,
default: true,
},
}, },
data() { backImg: {
return {} type: String,
default: 'back'
}, },
created() {}, isClose: {
computed: {}, type: Boolean,
methods: { default: false
back() {
if (this.$attrs.onBack) {
this.$attrs.onBack()
} else {
this.$back()
}
},
}, },
isFixed: {
type: Boolean,
default: true
}
},
data() {
return {}
},
created() {},
computed: {},
methods: {
back() {
if (this.$attrs.onBack) {
this.$attrs.onBack()
} else {
this.$back()
}
}
} }
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '../assets/less/index'; @import '../assets/less/index';
#BaseHeader { #BaseHeader {
width: 100%; width: 100%;
color: white; color: white;
&.fixed { &.fixed {
z-index: 2; z-index: 2;
top: 0; top: 0;
position: fixed; position: fixed;
}
.header {
display: flex;
justify-content: center;
align-items: center;
height: var(--common-header-height);
box-sizing: border-box;
border-bottom: 1px solid #cccccc11;
position: relative;
.left {
position: absolute;
left: 10rem;
} }
.header { & > :nth-last-child(1) {
height: 100%;
position: absolute;
right: 17px;
top: 0;
display: flex; display: flex;
justify-content: center;
align-items: center; align-items: center;
height: var(--common-header-height);
box-sizing: border-box;
border-bottom: 1px solid #cccccc11;
position: relative;
.left {
position: absolute;
left: 10rem;
}
& > :nth-last-child(1) {
height: 100%;
position: absolute;
right: 17px;
top: 0;
display: flex;
align-items: center;
}
} }
} }
}
</style> </style>

View File

@@ -7,57 +7,57 @@
@click.stop=" @click.stop="
bus.emit(EVENT_KEY.NAV, { bus.emit(EVENT_KEY.NAV, {
path: '/home/music', path: '/home/music',
query: { id: props.item.id }, query: { id: props.item.id }
}) })
" "
/> />
</div> </div>
</template> </template>
<script setup> <script setup>
import { computed, inject } from 'vue' import { computed, inject } from 'vue'
import bus, { EVENT_KEY } from '@/utils/bus' import bus, { EVENT_KEY } from '@/utils/bus'
const props = defineProps({ const props = defineProps({
item: { item: {
type: Object, type: Object,
default: () => { default: () => {
return {} return {}
}, }
}, }
}) })
const isPlaying = inject('isPlaying') const isPlaying = inject('isPlaying')
const style = computed(() => { const style = computed(() => {
return { webkitAnimationPlayState: isPlaying.value ? 'running' : 'paused' } return { webkitAnimationPlayState: isPlaying.value ? 'running' : 'paused' }
}) })
</script> </script>
<style lang="less"> <style lang="less">
.music-wrapper { .music-wrapper {
display: flex;
justify-content: center;
@w: 45rem;
.music {
border-radius: 50%;
width: @w;
height: @w;
display: flex; display: flex;
justify-content: center; justify-content: center;
@w: 45rem; align-items: center;
animation: animations 5s linear forwards infinite;
//animation-play-state:paused;
//display: none;
}
.music { @keyframes animations {
border-radius: 50%; 0% {
width: @w; transform: rotate(0deg);
height: @w;
display: flex;
justify-content: center;
align-items: center;
animation: animations 5s linear forwards infinite;
//animation-play-state:paused;
//display: none;
} }
100% {
@keyframes animations { transform: rotate(360deg);
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
} }
} }
}
</style> </style>

View File

@@ -21,11 +21,7 @@
<div class="float"> <div class="float">
<div class="header"> <div class="header">
<div class="left"> <div class="left">
<img <img @click="isSmall = true" src="@/assets/img/icon/message/chat/narrow.png" alt="" />
@click="isSmall = true"
src="@/assets/img/icon/message/chat/narrow.png"
alt=""
/>
</div> </div>
<span class="center">等待对方接听...</span> <span class="center">等待对方接听...</span>
<div class="right"> <div class="right">
@@ -60,22 +56,14 @@
<span>免提</span> <span>免提</span>
</div> </div>
<div class="option"> <div class="option">
<dy-back <dy-back mode="light" @click="isExpand = !isExpand" img="back" class="shrink" />
mode="light"
@click="isExpand = !isExpand"
img="back"
class="shrink"
/>
<!-- <img src="@/assets/img/icon/message/chat/narrow.png" alt="">--> <!-- <img src="@/assets/img/icon/message/chat/narrow.png" alt="">-->
</div> </div>
</div> </div>
</div> </div>
<img src="@/assets/img/icon/avatar/2.png" alt="" class="big-avatar" /> <img src="@/assets/img/icon/avatar/2.png" alt="" class="big-avatar" />
<div class="footer"> <div class="footer">
<img <img @click="isShowAudioCall = false" src="@/assets/img/icon/message/chat/call-end.png" />
@click="isShowAudioCall = false"
src="@/assets/img/icon/message/chat/call-end.png"
/>
<span>挂断</span> <span>挂断</span>
</div> </div>
</div> </div>
@@ -83,242 +71,242 @@
</transition> </transition>
</template> </template>
<script> <script>
import { inject } from 'vue' import { inject } from 'vue'
export default { export default {
name: 'Call', name: 'Call',
components: {}, components: {},
props: { props: {
modelValue: false, modelValue: false
}, },
data() { data() {
return {
mitt: inject('mitt'),
callFloatTransitionTime: 300,
callFloatLeft: 15,
callFloatTop: 100,
isOpenCamera: false,
isOpenAudio: true,
isExpand: true,
isSmall: false,
isShowAudioCall: false,
height: 0,
width: 0
}
},
computed: {
callFloatStyle() {
return { return {
mitt: inject('mitt'), 'transition-duration': this.callFloatTransitionTime + 'ms',
callFloatTransitionTime: 300, left: this.callFloatLeft + 'px',
callFloatLeft: 15, top: this.callFloatTop + 'px'
callFloatTop: 100,
isOpenCamera: false,
isOpenAudio: true,
isExpand: true,
isSmall: false,
isShowAudioCall: false,
height: 0,
width: 0,
} }
}
},
watch: {
isShowAudioCall(newVal) {
if (!newVal) {
this.isOpenCamera = false
this.isOpenAudio = true
}
}
},
created() {},
methods: {
touchmove(e) {
this.callFloatTransitionTime = 0
this.callFloatLeft = e.touches[0].pageX - 35
this.callFloatTop = e.touches[0].pageY - 40
}, },
computed: { touchend(e) {
callFloatStyle() { this.callFloatTransitionTime = 300
return { if (this.callFloatLeft < this.width / 2) {
'transition-duration': this.callFloatTransitionTime + 'ms', this.callFloatLeft = 15
left: this.callFloatLeft + 'px', } else {
top: this.callFloatTop + 'px', this.callFloatLeft = this.width - 15 - 70
} }
}, }
}, },
watch: { mounted() {
isShowAudioCall(newVal) { this.mitt.on('showAudioCall', () => {
if (!newVal) { if (this.isShowAudioCall) {
this.isOpenCamera = false this.isSmall = false
this.isOpenAudio = true } else {
} this.isShowAudioCall = true
}, }
}, })
created() {}, this.height = document.body.clientHeight
methods: { this.width = document.body.clientWidth
touchmove(e) {
this.callFloatTransitionTime = 0
this.callFloatLeft = e.touches[0].pageX - 35
this.callFloatTop = e.touches[0].pageY - 40
},
touchend(e) {
this.callFloatTransitionTime = 300
if (this.callFloatLeft < this.width / 2) {
this.callFloatLeft = 15
} else {
this.callFloatLeft = this.width - 15 - 70
}
},
},
mounted() {
this.mitt.on('showAudioCall', () => {
if (this.isShowAudioCall) {
this.isSmall = false
} else {
this.isShowAudioCall = true
}
})
this.height = document.body.clientHeight
this.width = document.body.clientWidth
},
} }
}
</script> </script>
<style> <style>
.scale-enter-active, .scale-enter-active,
.scale-leave-active { .scale-leave-active {
transition: transform 0.2s ease; transition: transform 0.2s ease;
} }
.scale-enter-from, .scale-enter-from,
.scale-leave-to { .scale-leave-to {
transform: scale(0); transform: scale(0);
} }
</style> </style>
<style scoped lang="less"> <style scoped lang="less">
.call-float { .call-float {
transition-property: all; transition-property: all;
z-index: 9; z-index: 9;
width: 70rem;
height: 90rem;
position: fixed;
top: 20vh;
left: var(--page-padding);
background: white;
display: flex;
align-items: center;
border-radius: 6rem;
justify-content: center;
flex-direction: column;
color: #14bf5f;
font-size: 12rem;
img {
width: 30rem;
margin-bottom: 2rem;
}
}
.audio-call {
color: white;
position: fixed;
z-index: 8;
top: 0;
left: 0;
width: 100vw;
height: calc(var(--vh, 1vh) * 100);
background: linear-gradient(to bottom, #262626, black);
transition: all 0.3s;
font-size: 12rem;
.float {
transition: all 0.3s;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
span {
transition: all 0.3s;
}
> .header {
transition: all 0.3s;
width: 100%;
padding: var(--page-padding);
box-sizing: border-box;
display: flex;
align-items: flex-start;
justify-content: space-between;
.left {
width: 12%;
img {
width: 50%;
max-width: 24rem;
max-height: 24rem;
}
}
.center {
width: 50%;
overflow: hidden;
text-align: center;
word-break: keep-all;
font-size: 14rem;
}
.right {
width: 12%;
max-width: 40rem;
display: flex;
flex-direction: column;
img {
width: 50%;
max-width: 24rem;
max-height: 24rem;
}
.option {
margin-bottom: 55%;
display: flex;
align-items: center;
flex-direction: column;
overflow: hidden;
span {
word-break: keep-all;
margin-top: 20%;
font-size: 12rem;
}
}
.shrink {
transform: rotate(90deg) scale(0.6) !important;
}
}
}
.big-avatar {
position: absolute;
left: 50%;
top: 50%;
transform: translate3d(-50%, -50%, 0);
width: 25%;
max-width: 100rem;
border-radius: 50%;
}
.footer {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
font-size: 12rem;
margin-bottom: 10%;
img {
width: 15%;
max-width: 50rem;
margin-bottom: 1%;
}
}
}
&.small {
width: 70rem; width: 70rem;
height: 90rem; height: 90rem;
position: fixed; position: fixed;
top: 20vh; top: 20vh;
left: var(--page-padding); left: var(--page-padding);
background: white;
display: flex;
align-items: center;
border-radius: 6rem; border-radius: 6rem;
justify-content: center;
flex-direction: column;
color: #14bf5f;
font-size: 12rem;
img {
width: 30rem;
margin-bottom: 2rem;
}
}
.audio-call {
color: white;
position: fixed;
z-index: 8;
top: 0;
left: 0;
width: 100vw;
height: calc(var(--vh, 1vh) * 100);
background: linear-gradient(to bottom, #262626, black);
transition: all 0.3s;
font-size: 12rem;
.float { .float {
transition: all 0.3s; > .header {
position: absolute; padding: 0;
top: 0; }
left: 0;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
span { span {
transition: all 0.3s; transform: scale(0.2);
}
> .header {
transition: all 0.3s;
width: 100%;
padding: var(--page-padding);
box-sizing: border-box;
display: flex;
align-items: flex-start;
justify-content: space-between;
.left {
width: 12%;
img {
width: 50%;
max-width: 24rem;
max-height: 24rem;
}
}
.center {
width: 50%;
overflow: hidden;
text-align: center;
word-break: keep-all;
font-size: 14rem;
}
.right {
width: 12%;
max-width: 40rem;
display: flex;
flex-direction: column;
img {
width: 50%;
max-width: 24rem;
max-height: 24rem;
}
.option {
margin-bottom: 55%;
display: flex;
align-items: center;
flex-direction: column;
overflow: hidden;
span {
word-break: keep-all;
margin-top: 20%;
font-size: 12rem;
}
}
.shrink {
transform: rotate(90deg) scale(0.6) !important;
}
}
}
.big-avatar {
position: absolute;
left: 50%;
top: 50%;
transform: translate3d(-50%, -50%, 0);
width: 25%;
max-width: 100rem;
border-radius: 50%;
}
.footer {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
font-size: 12rem;
margin-bottom: 10%;
img {
width: 15%;
max-width: 50rem;
margin-bottom: 1%;
}
}
}
&.small {
width: 70rem;
height: 90rem;
position: fixed;
top: 20vh;
left: var(--page-padding);
border-radius: 6rem;
.float {
> .header {
padding: 0;
}
span {
transform: scale(0.2);
}
} }
} }
} }
}
</style> </style>

View File

@@ -1,10 +1,6 @@
<template> <template>
<div class="check" @click.stop="change"> <div class="check" @click.stop="change">
<img <img v-show="!modelValue" src="../assets/img/icon/components/check/round-gray.png" alt="" />
v-show="!modelValue"
src="../assets/img/icon/components/check/round-gray.png"
alt=""
/>
<img <img
v-show="modelValue && mode === 'gray'" v-show="modelValue && mode === 'gray'"
src="../assets/img/icon/components/check/check-gray.png" src="../assets/img/icon/components/check/check-gray.png"
@@ -18,43 +14,43 @@
</div> </div>
</template> </template>
<script> <script>
export default { export default {
name: 'Check', name: 'Check',
props: { props: {
modelValue: { modelValue: {
type: Boolean, type: Boolean,
default: false, default: false
},
mode: {
type: String,
default: 'gray', //red
},
},
data() {
return {}
},
computed: {},
created() {},
methods: {
change() {
this.$emit('update:modelValue', !this.modelValue)
this.$emit('change', !this.modelValue)
},
}, },
mode: {
type: String,
default: 'gray' //red
}
},
data() {
return {}
},
computed: {},
created() {},
methods: {
change() {
this.$emit('update:modelValue', !this.modelValue)
this.$emit('change', !this.modelValue)
}
} }
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '../assets/less/index'; @import '../assets/less/index';
.check { .check {
@width: 14rem; @width: 14rem;
width: @width; width: @width;
height: @width; height: @width;
> img { > img {
width: 100% !important; width: 100% !important;
height: 100% !important; height: 100% !important;
}
} }
}
</style> </style>

View File

@@ -15,10 +15,7 @@
<dy-back mode="dark" img="close" direction="right" style="opacity: 0" /> <dy-back mode="dark" img="close" direction="right" style="opacity: 0" />
<div class="num">{{ formatNumber(comments.length) }}条评论</div> <div class="num">{{ formatNumber(comments.length) }}条评论</div>
<div class="right"> <div class="right">
<Icon <Icon icon="prime:arrow-up-right-and-arrow-down-left-from-center" @click.stop="$no" />
icon="prime:arrow-up-right-and-arrow-down-left-from-center"
@click.stop="$no"
/>
<Icon icon="ic:round-close" @click.stop="cancel" /> <Icon icon="ic:round-close" @click.stop="cancel" />
</div> </div>
</div> </div>
@@ -26,18 +23,10 @@
<div class="comment"> <div class="comment">
<div class="wrapper" v-if="comments.length"> <div class="wrapper" v-if="comments.length">
<div class="items"> <div class="items">
<div <div class="item" v-for="item in comments" v-longpress="(e) => showOptions(item)">
class="item"
v-for="item in comments"
v-longpress="(e) => showOptions(item)"
>
<div class="main"> <div class="main">
<div class="content"> <div class="content">
<img <img :src="_checkImgUrl(item.avatar)" alt="" class="head-image" />
:src="_checkImgUrl(item.avatar)"
alt=""
class="head-image"
/>
<div class="comment-container"> <div class="comment-container">
<div class="name">{{ item.nickname }}</div> <div class="name">{{ item.nickname }}</div>
<div class="detail" :class="item.user_buried && 'gray'"> <div class="detail" :class="item.user_buried && 'gray'">
@@ -52,11 +41,7 @@
<div class="reply-text">回复</div> <div class="reply-text">回复</div>
</div> </div>
<div class="right d-flex" style="gap: 10rem"> <div class="right d-flex" style="gap: 10rem">
<div <div class="love" :class="item.user_digged && 'loved'" @click="loved(item)">
class="love"
:class="item.user_digged && 'loved'"
@click="loved(item)"
>
<Icon <Icon
icon="icon-park-solid:like" icon="icon-park-solid:like"
v-show="item.user_digged" v-show="item.user_digged"
@@ -67,24 +52,15 @@
v-show="!item.user_digged" v-show="!item.user_digged"
class="love-image" class="love-image"
/> />
<span v-if="item.digg_count">{{ <span v-if="item.digg_count">{{ _formatNumber(item.digg_count) }}</span>
_formatNumber(item.digg_count)
}}</span>
</div> </div>
<div <div class="love" @click="item.user_buried = !item.user_buried">
class="love"
@click="item.user_buried = !item.user_buried"
>
<Icon <Icon
v-if="item.user_buried" v-if="item.user_buried"
icon="icon-park-solid:dislike-two" icon="icon-park-solid:dislike-two"
class="love-image" class="love-image"
/> />
<Icon <Icon v-else icon="icon-park-outline:dislike" class="love-image" />
v-else
icon="icon-park-outline:dislike"
class="love-image"
/>
</div> </div>
</div> </div>
</div> </div>
@@ -96,11 +72,7 @@
<div class="reply" v-for="child in item.children"> <div class="reply" v-for="child in item.children">
<!-- v-longpress="e => showOptions(child)"--> <!-- v-longpress="e => showOptions(child)"-->
<div class="content"> <div class="content">
<img <img :src="_checkImgUrl(child.avatar)" alt="" class="head-image" />
:src="_checkImgUrl(child.avatar)"
alt=""
class="head-image"
/>
<div class="comment-container"> <div class="comment-container">
<div class="name"> <div class="name">
{{ child.nickname }} {{ child.nickname }}
@@ -112,9 +84,7 @@
<div class="left"> <div class="left">
<div class="time"> <div class="time">
{{ $time(child.create_time) {{ $time(child.create_time)
}}{{ }}{{ child.ip_location && ` · ${item.ip_location}` }}
child.ip_location && ` · ${item.ip_location}`
}}
</div> </div>
<div class="reply-text">回复</div> <div class="reply-text">回复</div>
</div> </div>
@@ -148,9 +118,7 @@
<div class="more" v-else @click="handShowChildren(item)"> <div class="more" v-else @click="handShowChildren(item)">
<div class="gang"></div> <div class="gang"></div>
<span <span
>展开{{ >展开{{ item.showChildren ? '更多' : `${item.sub_comment_count}条` }}回复</span
item.showChildren ? '更多' : `${item.sub_comment_count}条`
}}回复</span
> >
<Icon icon="ep:arrow-down-bold" /> <Icon icon="ep:arrow-down-bold" />
</div> </div>
@@ -166,11 +134,7 @@
<div class="input-toolbar"> <div class="input-toolbar">
<transition name="fade"> <transition name="fade">
<div class="call-friend" v-if="isCall"> <div class="call-friend" v-if="isCall">
<div <div class="friend" v-for="item in friends.all" @click="toggleCall(item)">
class="friend"
v-for="item in friends.all"
@click="toggleCall(item)"
>
<img <img
:style="item.select ? 'opacity: .5;' : ''" :style="item.select ? 'opacity: .5;' : ''"
class="avatar" class="avatar"
@@ -189,33 +153,16 @@
<div class="toolbar"> <div class="toolbar">
<div class="input-wrapper"> <div class="input-wrapper">
<AutoInput <AutoInput v-model="comment" placeholder="善语结善缘,恶言伤人心"></AutoInput>
v-model="comment"
placeholder="善语结善缘,恶言伤人心"
></AutoInput>
<div class="right"> <div class="right">
<img <img src="../assets/img/icon/message/call.png" @click="isCall = !isCall" />
src="../assets/img/icon/message/call.png" <img src="../assets/img/icon/message/emoji-black.png" @click="$no" />
@click="isCall = !isCall"
/>
<img
src="../assets/img/icon/message/emoji-black.png"
@click="$no"
/>
</div> </div>
</div> </div>
<img <img v-if="comment" src="../assets/img/icon/message/up.png" @click="send" />
v-if="comment"
src="../assets/img/icon/message/up.png"
@click="send"
/>
</div> </div>
</div> </div>
<ConfirmDialog <ConfirmDialog title="私信给" ok-text="发送" v-model:visible="showPrivateChat">
title="私信给"
ok-text="发送"
v-model:visible="showPrivateChat"
>
<Search mode="light" v-model="test" :isShowSearchIcon="false" /> <Search mode="light" v-model="test" :isShowSearchIcon="false" />
</ConfirmDialog> </ConfirmDialog>
</div> </div>
@@ -223,223 +170,242 @@
</template> </template>
<script> <script>
import AutoInput from './AutoInput' import AutoInput from './AutoInput'
import ConfirmDialog from './dialog/ConfirmDialog' import ConfirmDialog from './dialog/ConfirmDialog'
import { mapState } from 'pinia' import { mapState } from 'pinia'
import FromBottomDialog from './dialog/FromBottomDialog' import FromBottomDialog from './dialog/FromBottomDialog'
import Loading from './Loading' import Loading from './Loading'
import Search from './Search' import Search from './Search'
import { $no, _checkImgUrl, _formatNumber, sampleSize } from '@/utils' import { $no, _checkImgUrl, _formatNumber, sampleSize } from '@/utils'
import { useBaseStore } from '@/store/pinia' import { useBaseStore } from '@/store/pinia'
import { videoComments } from '@/api/videos' import { videoComments } from '@/api/videos'
import Popover from '@/pages/login/components/Tooltip.vue' import Popover from '@/pages/login/components/Tooltip.vue'
export default { export default {
name: 'Comment', name: 'Comment',
components: { components: {
Popover, Popover,
AutoInput, AutoInput,
ConfirmDialog, ConfirmDialog,
FromBottomDialog, FromBottomDialog,
Loading, Loading,
Search, Search
},
props: {
modelValue: false,
videoId: {
type: String,
default: null
}, },
props: { pageId: {
modelValue: false, type: String,
videoId: { default: 'home-index'
type: String,
default: null,
},
pageId: {
type: String,
default: 'home-index',
},
height: {
type: String,
default: 'calc(var(--vh, 1vh) * 70)',
},
}, },
computed: { height: {
...mapState(useBaseStore, ['friends']), type: String,
}, default: 'calc(var(--vh, 1vh) * 70)'
watch: { }
modelValue(newVale) { },
if (newVale) { computed: {
this.getData() ...mapState(useBaseStore, ['friends'])
} else { },
this.comments = [] watch: {
} modelValue(newVale) {
}, if (newVale) {
}, this.getData()
data() { } else {
return { this.comments = []
comment: '', }
test: '', }
comments: [], },
options: [ data() {
{ id: 1, name: '私信回复' }, return {
{ id: 2, name: '复制' }, comment: '',
{ id: 3, name: '搜一搜' }, test: '',
{ id: 4, name: '举报' }, comments: [],
], options: [
selectRow: {}, { id: 1, name: '私信回复' },
showPrivateChat: false, { id: 2, name: '复制' },
isInput: false, { id: 3, name: '搜一搜' },
isCall: false, { id: 4, name: '举报' }
loadChildren: false, ],
loadChildrenItemCId: -1, selectRow: {},
showPrivateChat: false,
isInput: false,
isCall: false,
loadChildren: false,
loadChildrenItemCId: -1
}
},
mounted() {},
methods: {
_formatNumber,
_checkImgUrl,
$no,
async handShowChildren(item) {
this.loadChildrenItemCId = item.comment_id
this.loadChildren = true
await this.$sleep(500)
this.loadChildren = false
if (item.showChildren) {
item.children = item.children.concat(sampleSize(this.comments, 10))
} else {
item.children = sampleSize(this.comments, 3)
item.showChildren = true
} }
}, },
mounted() {}, send() {
methods: { this.comments.push({
_formatNumber, id: '2',
_checkImgUrl, avatar: new URL('../assets/img/icon/avatar/4.png', import.meta.url).href,
$no, name: '成都旅行',
async handShowChildren(item) { text: this.comment,
this.loadChildrenItemCId = item.comment_id loveNum: 27,
this.loadChildren = true isLoved: false,
await this.$sleep(500) time: '2021-08-24 20:33',
this.loadChildren = false children: []
if (item.showChildren) { })
item.children = item.children.concat(sampleSize(this.comments, 10)) this.comment = ''
} else { this.isCall = false
item.children = sampleSize(this.comments, 3)
item.showChildren = true
}
},
send() {
this.comments.push({
id: '2',
avatar: new URL('../assets/img/icon/avatar/4.png', import.meta.url)
.href,
name: '成都旅行',
text: this.comment,
loveNum: 27,
isLoved: false,
time: '2021-08-24 20:33',
children: [],
})
this.comment = ''
this.isCall = false
},
async getData() {
let res = await videoComments({ id: this.videoId })
if (res.success) {
res.data.map((v) => {
v.showChildren = false
v.digg_count = Number(v.digg_count)
})
this.comments = res.data
}
},
cancel() {
this.$emit('update:modelValue', false)
this.$emit('close')
},
toggleCall(item) {
item.select = !item.select
let name = item.name
if (this.comment.includes('@' + name)) {
this.comment = this.comment.replace(`@${name} `, '')
} else {
this.comment += `@${name} `
}
},
loved(row) {
if (row.isLoved) {
row.digg_count--
} else {
row.digg_count++
}
row.user_digged = !row.user_digged
},
showOptions(row) {
return
this.$showSelectDialog(this.options, (e) => {
if (e.id === 1) {
this.selectRow = row
this.showPrivateChat = true
}
})
},
// showComment() {
// this.isCommenting = !this.isCommenting;
// console.log(666)
// }
call() {
console.log(this.commit)
},
}, },
async getData() {
let res = await videoComments({ id: this.videoId })
if (res.success) {
res.data.map((v) => {
v.showChildren = false
v.digg_count = Number(v.digg_count)
})
this.comments = res.data
}
},
cancel() {
this.$emit('update:modelValue', false)
this.$emit('close')
},
toggleCall(item) {
item.select = !item.select
let name = item.name
if (this.comment.includes('@' + name)) {
this.comment = this.comment.replace(`@${name} `, '')
} else {
this.comment += `@${name} `
}
},
loved(row) {
if (row.isLoved) {
row.digg_count--
} else {
row.digg_count++
}
row.user_digged = !row.user_digged
},
showOptions(row) {
return
this.$showSelectDialog(this.options, (e) => {
if (e.id === 1) {
this.selectRow = row
this.showPrivateChat = true
}
})
},
// showComment() {
// this.isCommenting = !this.isCommenting;
// console.log(666)
// }
call() {
console.log(this.commit)
}
} }
}
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import '../assets/less/index'; @import '../assets/less/index';
.title { .title {
z-index: 2; z-index: 2;
position: fixed; position: fixed;
left: 0; left: 0;
right: 0; right: 0;
height: 40rem; height: 40rem;
padding: 0 15rem; padding: 0 15rem;
background: white; background: white;
display: flex;
align-items: center;
justify-content: space-between;
border-radius: 10rem 10rem 0 0;
.num {
width: 100%;
position: absolute;
font-size: 12rem;
font-weight: bold;
text-align: center;
}
.right {
display: flex; display: flex;
align-items: center; gap: 12rem;
justify-content: space-between; position: relative;
border-radius: 10rem 10rem 0 0; z-index: 9;
.num { svg {
width: 100%; background: rgb(242, 242, 242);
position: absolute; padding: 4rem;
font-size: 12rem; font-size: 16rem;
font-weight: bold; border-radius: 50%;
text-align: center;
}
.right {
display: flex;
gap: 12rem;
position: relative;
z-index: 9;
svg {
background: rgb(242, 242, 242);
padding: 4rem;
font-size: 16rem;
border-radius: 50%;
}
} }
} }
}
.gray { .gray {
color: var(--second-text-color); color: var(--second-text-color);
}
.comment {
width: 100vw;
height: v-bind(height);
background: #fff;
z-index: 5;
border-radius: 10rem 10rem 0 0;
.wrapper {
width: 100%;
position: relative;
padding-top: 40rem;
padding-bottom: 60rem;
} }
.comment { .items {
width: 100vw; width: 100%;
height: v-bind(height);
background: #fff;
z-index: 5;
border-radius: 10rem 10rem 0 0;
.wrapper { .item {
width: 100%; width: 100%;
position: relative; margin-bottom: 15rem;
padding-top: 40rem;
padding-bottom: 60rem;
}
.items { .main {
width: 100%;
.item {
width: 100%; width: 100%;
margin-bottom: 15rem; padding: 5rem 0;
display: flex;
.main { &:active {
width: 100%; background: #53535321;
padding: 5rem 0; }
.head-image {
margin-left: 15rem;
margin-right: 10rem;
width: 37rem;
height: 37rem;
border-radius: 50%;
}
}
.replies {
padding-left: 55rem;
.reply {
padding: 5rem 0 5rem 5rem;
display: flex; display: flex;
&:active { &:active {
@@ -447,227 +413,207 @@
} }
.head-image { .head-image {
margin-left: 15rem;
margin-right: 10rem; margin-right: 10rem;
width: 37rem;
height: 37rem;
border-radius: 50%;
}
}
.replies {
padding-left: 55rem;
.reply {
padding: 5rem 0 5rem 5rem;
display: flex;
&:active {
background: #53535321;
}
.head-image {
margin-right: 10rem;
width: 20rem;
height: 20rem;
border-radius: 50%;
}
}
.more {
font-size: 13rem;
margin: 5rem;
display: flex;
align-items: center;
color: gray;
.gang {
background: #d5d5d5;
width: 20rem;
margin-right: 10rem;
height: 1px;
}
span {
margin-right: 5rem;
}
svg {
font-size: 10rem;
}
}
}
.content {
width: 100%;
display: flex;
font-size: 14rem;
.comment-container {
flex: 1;
margin-right: 20rem;
.name {
color: var(--second-text-color);
margin-bottom: 5rem;
display: flex;
align-items: center;
.reply-user {
margin-left: 5rem;
width: 0;
height: 0;
border: 5rem solid transparent;
border-left: 6rem solid gray;
}
}
.detail {
margin-bottom: 5rem;
}
.time-wrapper {
display: flex;
align-items: center;
justify-content: space-between;
font-size: 13rem;
.left {
display: flex;
.time {
color: #c4c3c3;
margin-right: 10rem;
}
.reply-text {
color: var(--second-text-color);
}
}
.love {
color: gray;
display: flex;
align-items: center;
&.loved {
color: rgb(231, 58, 87);
}
.love-image {
font-size: 17rem;
margin-right: 4rem;
}
span {
word-break: keep-all;
}
}
}
}
}
}
}
@normal-bg-color: rgb(35, 38, 47);
@chat-bg-color: rgb(105, 143, 244);
.input-toolbar {
border-radius: 10rem 10rem 0 0;
background: white;
position: fixed;
width: 100vw;
bottom: 0;
z-index: 3;
@space-width: 18rem;
@icon-width: 48rem;
.call-friend {
padding-top: 30rem;
overflow-x: scroll;
display: flex;
padding-right: @space-width;
.friend {
width: @icon-width;
position: relative;
margin-left: @space-width;
margin-bottom: @space-width;
font-size: 10rem;
display: flex;
flex-direction: column;
align-items: center;
.avatar {
width: @icon-width;
height: @icon-width;
border-radius: 50%;
}
span {
margin-top: 5rem;
text-align: center;
width: @icon-width;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.checked {
position: absolute;
top: @icon-width - 1.5;
right: -2px;
width: 20rem; width: 20rem;
height: 20rem; height: 20rem;
border-radius: 50%; border-radius: 50%;
} }
} }
}
.toolbar { .more {
@icon-width: 25rem; font-size: 13rem;
display: flex; margin: 5rem;
align-items: center;
padding: 10rem 15rem;
border-top: 1px solid #e2e1e1;
.input-wrapper {
flex: 1;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; color: gray;
box-sizing: border-box;
padding: 5rem 10rem;
background: #eee;
border-radius: 20rem;
.right { .gang {
display: flex; background: #d5d5d5;
align-items: center; width: 20rem;
margin-right: 10rem;
height: 1px;
} }
.auto-input { span {
width: calc(100vw - 180rem); margin-right: 5rem;
}
svg {
font-size: 10rem;
} }
} }
}
img { .content {
width: @icon-width; width: 100%;
height: @icon-width; display: flex;
border-radius: 50%; font-size: 14rem;
margin-left: 15rem;
.comment-container {
flex: 1;
margin-right: 20rem;
.name {
color: var(--second-text-color);
margin-bottom: 5rem;
display: flex;
align-items: center;
.reply-user {
margin-left: 5rem;
width: 0;
height: 0;
border: 5rem solid transparent;
border-left: 6rem solid gray;
}
}
.detail {
margin-bottom: 5rem;
}
.time-wrapper {
display: flex;
align-items: center;
justify-content: space-between;
font-size: 13rem;
.left {
display: flex;
.time {
color: #c4c3c3;
margin-right: 10rem;
}
.reply-text {
color: var(--second-text-color);
}
}
.love {
color: gray;
display: flex;
align-items: center;
&.loved {
color: rgb(231, 58, 87);
}
.love-image {
font-size: 17rem;
margin-right: 4rem;
}
span {
word-break: keep-all;
}
}
}
} }
} }
} }
} }
.comment-enter-active, @normal-bg-color: rgb(35, 38, 47);
.comment-leave-active { @chat-bg-color: rgb(105, 143, 244);
transition: all 0.15s ease;
}
.comment-enter-from, .input-toolbar {
.comment-leave-to { border-radius: 10rem 10rem 0 0;
transform: translateY(60vh); background: white;
position: fixed;
width: 100vw;
bottom: 0;
z-index: 3;
@space-width: 18rem;
@icon-width: 48rem;
.call-friend {
padding-top: 30rem;
overflow-x: scroll;
display: flex;
padding-right: @space-width;
.friend {
width: @icon-width;
position: relative;
margin-left: @space-width;
margin-bottom: @space-width;
font-size: 10rem;
display: flex;
flex-direction: column;
align-items: center;
.avatar {
width: @icon-width;
height: @icon-width;
border-radius: 50%;
}
span {
margin-top: 5rem;
text-align: center;
width: @icon-width;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.checked {
position: absolute;
top: @icon-width - 1.5;
right: -2px;
width: 20rem;
height: 20rem;
border-radius: 50%;
}
}
}
.toolbar {
@icon-width: 25rem;
display: flex;
align-items: center;
padding: 10rem 15rem;
border-top: 1px solid #e2e1e1;
.input-wrapper {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
padding: 5rem 10rem;
background: #eee;
border-radius: 20rem;
.right {
display: flex;
align-items: center;
}
.auto-input {
width: calc(100vw - 180rem);
}
}
img {
width: @icon-width;
height: @icon-width;
border-radius: 50%;
margin-left: 15rem;
}
}
} }
}
.comment-enter-active,
.comment-leave-active {
transition: all 0.15s ease;
}
.comment-enter-from,
.comment-leave-to {
transform: translateY(60vh);
}
</style> </style>

View File

@@ -3,21 +3,14 @@
<div class="DouyinCode" v-if="modelValue"> <div class="DouyinCode" v-if="modelValue">
<div class="content"> <div class="content">
<div class="video-poster"> <div class="video-poster">
<img <img :src="_checkImgUrl(item.video.cover.url_list[0])" class="poster" />
:src="_checkImgUrl(item.video.cover.url_list[0])"
class="poster"
/>
</div> </div>
<div class="desc"> <div class="desc">
<div class="left"> <div class="left">
<div class="user">@{{ item.author.nickname }}</div> <div class="user">@{{ item.author.nickname }}</div>
<div class="title">{{ item.desc }}</div> <div class="title">{{ item.desc }}</div>
</div> </div>
<img <img class="code" src="../assets/img/icon/components/video/douyin-code.jpg" alt="" />
class="code"
src="../assets/img/icon/components/video/douyin-code.jpg"
alt=""
/>
</div> </div>
</div> </div>
<div class="toolbar"> <div class="toolbar">
@@ -32,24 +25,15 @@
<span>QQ空间</span> <span>QQ空间</span>
</div> </div>
<div class="share-to" @click="$no"> <div class="share-to" @click="$no">
<img <img src="../assets/img/icon/components/video/towechatchat.webp" alt="" />
src="../assets/img/icon/components/video/towechatchat.webp"
alt=""
/>
<span>微信好友</span> <span>微信好友</span>
</div> </div>
<div class="share-to" @click="$no"> <div class="share-to" @click="$no">
<img <img src="../assets/img/icon/components/video/towechat.webp" alt="" />
src="../assets/img/icon/components/video/towechat.webp"
alt=""
/>
<span>朋友圈</span> <span>朋友圈</span>
</div> </div>
<div class="share-to" @click="$no"> <div class="share-to" @click="$no">
<img <img src="../assets/img/icon/components/video/todownload.webp" alt="" />
src="../assets/img/icon/components/video/todownload.webp"
alt=""
/>
<span>保存到相册</span> <span>保存到相册</span>
</div> </div>
</div> </div>
@@ -59,134 +43,134 @@
</transition> </transition>
</template> </template>
<script> <script>
import { _checkImgUrl } from '@/utils' import { _checkImgUrl } from '@/utils'
export default { export default {
name: 'DouyinCode', name: 'DouyinCode',
props: { props: {
item: {}, item: {},
modelValue: false, modelValue: false
}, },
data() { data() {
return {} return {}
}, },
computed: {}, computed: {},
created() {}, created() {},
methods: { methods: {
_checkImgUrl, _checkImgUrl,
cancel() { cancel() {
this.$emit('update:modelValue', false) this.$emit('update:modelValue', false)
}, }
},
} }
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '../assets/less/index'; @import '../assets/less/index';
.DouyinCode { .DouyinCode {
position: fixed; position: fixed;
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
top: 0; top: 0;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
justify-content: flex-end; justify-content: flex-end;
background: transparent; background: transparent;
@w: 70vw; @w: 70vw;
.content { .content {
background: white; background: white;
width: @w; width: @w;
margin-bottom: 40rem; margin-bottom: 40rem;
position: relative; position: relative;
border-radius: 10rem; border-radius: 10rem;
overflow: hidden; overflow: hidden;
.desc { .desc {
display: flex; display: flex;
gap: 20rem; gap: 20rem;
padding: 10rem; padding: 10rem;
.left { .left {
font-size: 18rem; font-size: 18rem;
.title { .title {
margin-top: 10rem; margin-top: 10rem;
font-size: 14rem; font-size: 14rem;
color: var(--second-text-color); color: var(--second-text-color);
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
display: -webkit-box; //作为弹性伸缩盒子模型显示。 display: -webkit-box; //作为弹性伸缩盒子模型显示。
-webkit-box-orient: vertical; //设置伸缩盒子的子元素排列方式--从上到下垂直排列 -webkit-box-orient: vertical; //设置伸缩盒子的子元素排列方式--从上到下垂直排列
-webkit-line-clamp: 1; //显示的行 -webkit-line-clamp: 1; //显示的行
}
}
.code {
width: 60rem;
} }
} }
.code {
.video-poster { width: 60rem;
width: @w;
height: @w;
overflow: hidden;
.poster {
width: 100%;
height: 100%;
object-fit: cover;
}
} }
} }
.toolbar { .video-poster {
width: 100vw; width: @w;
background: black; height: @w;
border-radius: 10rem 10rem 0 0; overflow: hidden;
color: white;
.title { .poster {
font-size: 12rem; width: 100%;
padding: 14rem; height: 100%;
text-align: center; object-fit: cover;
}
@space-width: 18rem;
@icon-width: 45rem;
.shares {
display: flex;
margin-bottom: @space-width;
gap: 20rem;
padding-left: 20rem;
.share-to {
img {
width: @icon-width;
height: @icon-width;
border-radius: 50%;
margin-bottom: 5rem;
}
span {
color: var(--second-text-color);
font-size: 10rem;
display: block;
text-align: center;
}
}
}
.cancel {
font-size: 16rem;
background: rgb(38, 38, 38);
color: rgba(white, 0.8);
padding: 15rem;
text-align: center;
} }
} }
} }
.toolbar {
width: 100vw;
background: black;
border-radius: 10rem 10rem 0 0;
color: white;
.title {
font-size: 12rem;
padding: 14rem;
text-align: center;
}
@space-width: 18rem;
@icon-width: 45rem;
.shares {
display: flex;
margin-bottom: @space-width;
gap: 20rem;
padding-left: 20rem;
.share-to {
img {
width: @icon-width;
height: @icon-width;
border-radius: 50%;
margin-bottom: 5rem;
}
span {
color: var(--second-text-color);
font-size: 10rem;
display: block;
text-align: center;
}
}
}
.cancel {
font-size: 16rem;
background: rgb(38, 38, 38);
color: rgba(white, 0.8);
padding: 15rem;
text-align: center;
}
}
}
</style> </style>

View File

@@ -2,21 +2,11 @@
<div v-if="visible" class="footer" :class="{ isWhite }"> <div v-if="visible" class="footer" :class="{ isWhite }">
<div class="l-button" @click="refresh(1)"> <div class="l-button" @click="refresh(1)">
<span v-if="!isRefresh1" :class="{ active: currentTab === 1 }">首页</span> <span v-if="!isRefresh1" :class="{ active: currentTab === 1 }">首页</span>
<img <img v-if="isRefresh1" src="../assets/img/icon/refresh1.png" alt="" class="refresh" />
v-if="isRefresh1"
src="../assets/img/icon/refresh1.png"
alt=""
class="refresh"
/>
</div> </div>
<div class="l-button" @click="refresh(2)"> <div class="l-button" @click="refresh(2)">
<span v-if="!isRefresh2" :class="{ active: currentTab === 2 }">商城</span> <span v-if="!isRefresh2" :class="{ active: currentTab === 2 }">商城</span>
<img <img v-if="isRefresh2" src="../assets/img/icon/refresh1.png" alt="" class="refresh" />
v-if="isRefresh2"
src="../assets/img/icon/refresh1.png"
alt=""
class="refresh"
/>
</div> </div>
<div class="l-button" @click="tab(3)"> <div class="l-button" @click="tab(3)">
<div class="add-ctn"> <div class="add-ctn">
@@ -34,142 +24,142 @@
</template> </template>
<script> <script>
import bus, { EVENT_KEY } from '../utils/bus' import bus, { EVENT_KEY } from '../utils/bus'
export default { export default {
name: 'Footer', name: 'Footer',
props: ['initTab', 'isWhite'], props: ['initTab', 'isWhite'],
data() { data() {
return { return {
isRefresh1: false, isRefresh1: false,
isRefresh2: false, isRefresh2: false,
currentTab: this.initTab, currentTab: this.initTab,
visible: true, visible: true
}
},
created() {
bus.on('setFooterVisible', (e) => (this.visible = e))
bus.on(EVENT_KEY.ENTER_FULLSCREEN, (e) => (this.visible = false))
bus.on(EVENT_KEY.EXIT_FULLSCREEN, (e) => (this.visible = true))
},
unmounted() {
bus.off(EVENT_KEY.ENTER_FULLSCREEN)
bus.off(EVENT_KEY.EXIT_FULLSCREEN)
},
methods: {
tab(index) {
switch (index) {
case 1:
this.$nav('/')
break
case 2:
this.$nav('/shop')
break
case 3:
this.$nav('/publish')
break
case 4:
this.$nav('/message')
break
case 5:
this.$nav('/me')
break
} }
}, },
created() { refresh(index) {
bus.on('setFooterVisible', (e) => (this.visible = e)) if (this.currentTab === index) {
bus.on(EVENT_KEY.ENTER_FULLSCREEN, (e) => (this.visible = false)) this['isRefresh' + index] = !this['isRefresh' + index]
bus.on(EVENT_KEY.EXIT_FULLSCREEN, (e) => (this.visible = true)) setTimeout(() => {
},
unmounted() {
bus.off(EVENT_KEY.ENTER_FULLSCREEN)
bus.off(EVENT_KEY.EXIT_FULLSCREEN)
},
methods: {
tab(index) {
switch (index) {
case 1:
this.$nav('/')
break
case 2:
this.$nav('/shop')
break
case 3:
this.$nav('/publish')
break
case 4:
this.$nav('/message')
break
case 5:
this.$nav('/me')
break
}
},
refresh(index) {
if (this.currentTab === index) {
this['isRefresh' + index] = !this['isRefresh' + index] this['isRefresh' + index] = !this['isRefresh' + index]
setTimeout(() => { }, 2000)
this['isRefresh' + index] = !this['isRefresh' + index] } else {
}, 2000) this.tab(index)
} else { }
this.tab(index) }
}
},
},
} }
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '../assets/less/index'; @import '../assets/less/index';
.footer { .footer {
font-size: 14rem; font-size: 14rem;
position: fixed; position: fixed;
width: 100%; width: 100%;
height: var(--footer-height); height: var(--footer-height);
//border-top: 1px solid #7b7878; //border-top: 1px solid #7b7878;
z-index: 2; z-index: 2;
//不用bottom0是因为在进行页面切换的时候vue的transition //不用bottom0是因为在进行页面切换的时候vue的transition
// 会使footer的bottom0失效不能准确定位 // 会使footer的bottom0失效不能准确定位
top: calc(var(--vh, 1vh) * 100 - var(--footer-height)); top: calc(var(--vh, 1vh) * 100 - var(--footer-height));
//bottom: 0; //bottom: 0;
background: var(--footer-color); background: var(--footer-color);
color: white; color: white;
display: flex;
//justify-content: space-between;
&.isWhite {
background: white !important;
color: #000 !important;
}
.l-button {
width: 20%;
display: flex; display: flex;
//justify-content: space-between; justify-content: center;
align-items: center;
position: relative;
font-size: 16rem;
&.isWhite { .refresh {
background: white !important; width: 25%;
color: #000 !important; animation: rotate 0.5s linear infinite;
} }
.l-button { @keyframes rotate {
width: 20%; from {
transform: rotate(0deg);
}
to {
transform: rotate(-360deg);
}
}
.add-ctn {
@height: 27rem;
@width: 36rem;
height: @height;
width: @width;
border-radius: 6rem;
box-sizing: border-box;
padding: 0 2rem;
border: 3rem solid white;
background: black;
display: flex; display: flex;
justify-content: center;
align-items: center; align-items: center;
position: relative; justify-content: center;
font-size: 16rem;
.refresh { img {
width: 25%; width: 20rem;
animation: rotate 0.5s linear infinite;
} }
}
@keyframes rotate { span {
from { font-weight: bold;
transform: rotate(0deg); opacity: 0.7;
}
to { &.active {
transform: rotate(-360deg); opacity: 1;
}
} }
}
.add-ctn { .badge {
@height: 27rem; right: 10rem;
@width: 36rem; top: 6rem;
height: @height; position: absolute;
width: @width;
border-radius: 6rem;
box-sizing: border-box;
padding: 0 2rem;
border: 3rem solid white;
background: black;
display: flex;
align-items: center;
justify-content: center;
img {
width: 20rem;
}
}
span {
font-weight: bold;
opacity: 0.7;
&.active {
opacity: 1;
}
}
.badge {
right: 10rem;
top: 6rem;
position: absolute;
}
} }
} }
}
</style> </style>

View File

@@ -5,82 +5,82 @@
</div> </div>
</template> </template>
<script> <script>
export default { export default {
name: 'Loading', name: 'Loading',
props: { props: {
isFullScreen: { isFullScreen: {
type: Boolean, type: Boolean,
default: true, default: true
},
type: {
type: String,
default: 'normal',
},
}, },
type: {
type: String,
default: 'normal'
}
} }
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '../assets/less/index'; @import '../assets/less/index';
.Loading { .Loading {
&.inline { &.inline {
width: 100%; width: 100%;
height: 40rem; height: 40rem;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
} }
&.small {
.circle {
width: 8rem;
height: 8rem;
}
}
&.full {
z-index: 999;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
display: flex;
justify-content: space-between;
width: 22rem;
}
&.small {
.circle { .circle {
width: 10rem; width: 8rem;
height: 10rem; height: 8rem;
border-radius: 50%;
}
.blue {
background: cadetblue;
animation: anim-blue 0.4s ease-in-out 0s infinite alternate;
}
.red {
background: var(--primary-btn-color);
animation: anim-red 0.4s ease-in-out 0s infinite alternate;
}
@keyframes anim-blue {
from {
transform: translate3d(0, 0, 0) scale(1);
}
to {
transform: translate3d(10rem, 0, 0) scale(1.2);
}
}
@keyframes anim-red {
from {
transform: translate3d(0, 0, 0) scale(1);
}
to {
transform: translate3d(-10rem, 0, 0) scale(1.2);
}
} }
} }
&.full {
z-index: 999;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
display: flex;
justify-content: space-between;
width: 22rem;
}
.circle {
width: 10rem;
height: 10rem;
border-radius: 50%;
}
.blue {
background: cadetblue;
animation: anim-blue 0.4s ease-in-out 0s infinite alternate;
}
.red {
background: var(--primary-btn-color);
animation: anim-red 0.4s ease-in-out 0s infinite alternate;
}
@keyframes anim-blue {
from {
transform: translate3d(0, 0, 0) scale(1);
}
to {
transform: translate3d(10rem, 0, 0) scale(1.2);
}
}
@keyframes anim-red {
from {
transform: translate3d(0, 0, 0) scale(1);
}
to {
transform: translate3d(-10rem, 0, 0) scale(1.2);
}
}
}
</style> </style>

View File

@@ -2,43 +2,43 @@
<div class="Mask" :class="mode"></div> <div class="Mask" :class="mode"></div>
</template> </template>
<script> <script>
//未以组件的方式使用FromBottomDialog.vue里面是用js append到dom里面去的 //未以组件的方式使用FromBottomDialog.vue里面是用js append到dom里面去的
//以组件的方式使用不好随意插位置插到app下面又会出现定位覆盖的问题 //以组件的方式使用不好随意插位置插到app下面又会出现定位覆盖的问题
export default { export default {
name: 'Mask', name: 'Mask',
props: { props: {
mode: { mode: {
type: String, type: String,
default: 'dark', default: 'dark'
}, }
},
} }
}
</script> </script>
<style lang="less"> <style lang="less">
.Mask { .Mask {
z-index: 3; z-index: 3;
position: fixed; position: fixed;
top: 0; top: 0;
bottom: 0; bottom: 0;
left: 0; left: 0;
right: 0; right: 0;
background: var(--mask-dark);
&.dark {
background: var(--mask-dark); background: var(--mask-dark);
&.dark {
background: var(--mask-dark);
}
&.light {
background: var(--mask-light);
}
&.lightgray {
background: var(--mask-lightgray);
}
&.white {
background: var(--mask-white);
}
} }
&.light {
background: var(--mask-light);
}
&.lightgray {
background: var(--mask-lightgray);
}
&.white {
background: var(--mask-white);
}
}
</style> </style>

View File

@@ -5,20 +5,20 @@
</div> </div>
</template> </template>
<script> <script>
export default { export default {
name: 'NoMore', name: 'NoMore'
} }
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '../assets/less/index'; @import '../assets/less/index';
.NoMore { .NoMore {
font-size: 12rem; font-size: 12rem;
height: 60rem; height: 60rem;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
color: var(--second-text-color); color: var(--second-text-color);
} }
</style> </style>

View File

@@ -1,15 +1,7 @@
<template> <template>
<div class="posters"> <div class="posters">
<div <div class="poster-item" v-for="(i, index) in list" @click="goDetail(index)">
class="poster-item" <img class="poster" v-lazy="_checkImgUrl(i.video.cover.url_list[0])" alt="" />
v-for="(i, index) in list"
@click="goDetail(index)"
>
<img
class="poster"
v-lazy="_checkImgUrl(i.video.cover.url_list[0])"
alt=""
/>
<div class="num" v-if="mode === 'normal'"> <div class="num" v-if="mode === 'normal'">
<Icon icon="icon-park-outline:like" /> <Icon icon="icon-park-outline:like" />
<span>{{ _formatNumber(i.statistics.digg_count) }}</span> <span>{{ _formatNumber(i.statistics.digg_count) }}</span>
@@ -26,139 +18,139 @@
</template> </template>
<script setup> <script setup>
import { _checkImgUrl, _formatNumber } from '@/utils' import { _checkImgUrl, _formatNumber } from '@/utils'
import { useBaseStore } from '@/store/pinia' import { useBaseStore } from '@/store/pinia'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { cloneDeep } from '@/utils' import { cloneDeep } from '@/utils'
const store = useBaseStore() const store = useBaseStore()
const nav = useRouter() const nav = useRouter()
const props = defineProps({ const props = defineProps({
list: { list: {
type: [Array, Number], type: [Array, Number],
default: () => { default: () => {
return [] return []
},
},
mode: {
type: String,
default: 'normal', //date,music
},
})
defineOptions({
name: 'Posters',
})
function goDetail(index) {
store.routeData = cloneDeep({ list: props.list, index })
nav.push({ path: '/video-detail' })
}
function getDay(time) {
let date = new Date(time * 1000)
return date.getDate()
}
function getMonth(time) {
let date = new Date(time * 1000)
let month = date.getMonth() + 1
switch (month) {
case 1:
return '一月'
case 2:
return '二月'
case 3:
return '三月'
case 4:
return '四月'
case 5:
return '五月'
case 6:
return '六月'
case 7:
return '七月'
case 8:
return '八月'
case 9:
return '九月'
case 10:
return '十月'
case 11:
return '十一月'
case 12:
return '十二月'
} }
},
mode: {
type: String,
default: 'normal' //date,music
} }
})
defineOptions({
name: 'Posters'
})
function goDetail(index) {
store.routeData = cloneDeep({ list: props.list, index })
nav.push({ path: '/video-detail' })
}
function getDay(time) {
let date = new Date(time * 1000)
return date.getDate()
}
function getMonth(time) {
let date = new Date(time * 1000)
let month = date.getMonth() + 1
switch (month) {
case 1:
return '一月'
case 2:
return '二月'
case 3:
return '三月'
case 4:
return '四月'
case 5:
return '五月'
case 6:
return '六月'
case 7:
return '七月'
case 8:
return '八月'
case 9:
return '九月'
case 10:
return '十月'
case 11:
return '十一月'
case 12:
return '十二月'
}
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
.posters { .posters {
display: grid; display: grid;
grid-template-columns: 33.33vw 33.33vw 33.33vw; grid-template-columns: 33.33vw 33.33vw 33.33vw;
}
.poster-item {
height: calc(33.33vw * 1.2);
border: 0.5px solid black;
overflow: hidden;
position: relative;
.poster {
width: 100%;
height: 100%;
display: block;
object-fit: cover;
} }
.poster-item { .music {
height: calc(33.33vw * 1.2); position: absolute;
border: 0.5px solid black; font-size: 12rem;
overflow: hidden; background: gold;
position: relative; color: black;
padding: 2rem 3rem;
border-radius: 2rem;
top: 7rem;
left: 7rem;
}
.poster { .num {
width: 100%; color: white;
height: 100%; position: absolute;
display: block; bottom: 5rem;
object-fit: cover; left: 5rem;
} display: flex;
align-items: center;
font-size: 14rem;
gap: 3rem;
.music { .love {
position: absolute; width: 14rem;
font-size: 12rem; height: 14rem;
background: gold; margin-right: 5rem;
color: black;
padding: 2rem 3rem;
border-radius: 2rem;
top: 7rem;
left: 7rem;
}
.num {
color: white;
position: absolute;
bottom: 5rem;
left: 5rem;
display: flex;
align-items: center;
font-size: 14rem;
gap: 3rem;
.love {
width: 14rem;
height: 14rem;
margin-right: 5rem;
}
}
.date {
position: absolute;
top: 5rem;
left: 5rem;
display: flex;
align-items: center;
flex-direction: column;
font-size: 14rem;
color: black;
background: white;
padding: 6rem;
border-radius: 6rem;
.day {
font-weight: bold;
}
.month {
font-size: 10rem;
}
} }
} }
.date {
position: absolute;
top: 5rem;
left: 5rem;
display: flex;
align-items: center;
flex-direction: column;
font-size: 14rem;
color: black;
background: white;
padding: 6rem;
border-radius: 6rem;
.day {
font-weight: bold;
}
.month {
font-size: 10rem;
}
}
}
</style> </style>

View File

@@ -13,12 +13,7 @@
<Loading v-if="loading" :is-full-screen="false" /> <Loading v-if="loading" :is-full-screen="false" />
</div> </div>
</div> </div>
<div <div v-else class="scroll-wrapper scroll Scroll" ref="wrapper" @scroll="scroll">
v-else
class="scroll-wrapper scroll Scroll"
ref="wrapper"
@scroll="scroll"
>
<div class="scroll-content"> <div class="scroll-content">
<slot></slot> <slot></slot>
<Loading v-if="loading" :is-full-screen="fullLoading" /> <Loading v-if="loading" :is-full-screen="fullLoading" />
@@ -26,115 +21,112 @@
</div> </div>
</template> </template>
<script> <script>
import Loading from './Loading' import Loading from './Loading'
import { nextTick } from 'vue' import { nextTick } from 'vue'
export default { export default {
name: 'Scroll', name: 'Scroll',
components: { components: {
Loading, Loading
},
props: {
fixedHeight: {
type: Number,
default: -1
}, },
props: { useRefresh: {
fixedHeight: { type: Boolean,
type: Number, default: false
default: -1,
},
useRefresh: {
type: Boolean,
default: false,
},
loading: {
type: Boolean,
default: false,
},
fullLoading: {
type: Boolean,
default: false,
},
}, },
data() { loading: {
type: Boolean,
default: false
},
fullLoading: {
type: Boolean,
default: false
}
},
data() {
return {
wrapper: null,
startMoveY: null,
distance: null,
refresh: false
}
},
computed: {
pullUpStyle() {
return { return {
wrapper: null, 'transition-duration': this.refresh ? '300ms' : '0ms',
startMoveY: null, transform: `translate3d(0px, ${this.distance !== null ? this.distance : -40}px,0`
distance: null, }
refresh: false, }
},
created() {},
mounted() {
nextTick(() => {
this.wrapper = this.$refs.wrapper
})
},
methods: {
move(e) {
// console.log(this.wrapper)
// console.log(this.wrapper.scrollTop)
if (this.refresh) return
if (this.wrapper.scrollTop > 0) return
if (this.wrapper.scrollTop === 0 && this.startMoveY === null) {
this.startMoveY = e.touches[0].pageY
}
let distance = e.touches[0].pageY - this.startMoveY
this.distance = distance - 40 < 10 ? distance - 40 : 10
},
end() {
this.startMoveY = null
if (this.distance !== null && this.wrapper.scrollTop === 0) {
this.refresh = true
this.distance = 10
this.$emit('refresh')
} else {
this.distance = null
}
// console.log('end')
},
refreshEnd() {
this.distance = null
setTimeout(() => {
this.refresh = false
}, 300)
},
async scroll() {
if (this.fixedHeight !== -1) {
this.$emit('fixed', this.fixedHeight < this.wrapper.scrollTop)
}
if (this.$attrs.onPulldown) {
if (this.wrapper.scrollHeight - this.wrapper.clientHeight < this.wrapper.scrollTop + 60) {
this.$emit('pulldown')
}
} }
}, },
computed: { scrollBottom() {
pullUpStyle() {
return {
'transition-duration': this.refresh ? '300ms' : '0ms',
transform: `translate3d(0px, ${this.distance !== null ? this.distance : -40}px,0`,
}
},
},
created() {},
mounted() {
nextTick(() => { nextTick(() => {
this.wrapper = this.$refs.wrapper this.wrapper.scrollTo({
}) top: this.wrapper.scrollHeight - this.wrapper.clientHeight
},
methods: {
move(e) {
// console.log(this.wrapper)
// console.log(this.wrapper.scrollTop)
if (this.refresh) return
if (this.wrapper.scrollTop > 0) return
if (this.wrapper.scrollTop === 0 && this.startMoveY === null) {
this.startMoveY = e.touches[0].pageY
}
let distance = e.touches[0].pageY - this.startMoveY
this.distance = distance - 40 < 10 ? distance - 40 : 10
},
end() {
this.startMoveY = null
if (this.distance !== null && this.wrapper.scrollTop === 0) {
this.refresh = true
this.distance = 10
this.$emit('refresh')
} else {
this.distance = null
}
// console.log('end')
},
refreshEnd() {
this.distance = null
setTimeout(() => {
this.refresh = false
}, 300)
},
async scroll() {
if (this.fixedHeight !== -1) {
this.$emit('fixed', this.fixedHeight < this.wrapper.scrollTop)
}
if (this.$attrs.onPulldown) {
if (
this.wrapper.scrollHeight - this.wrapper.clientHeight <
this.wrapper.scrollTop + 60
) {
this.$emit('pulldown')
}
}
},
scrollBottom() {
nextTick(() => {
this.wrapper.scrollTo({
top: this.wrapper.scrollHeight - this.wrapper.clientHeight,
})
}) })
}, })
}, }
} }
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '../assets/less/index'; @import '../assets/less/index';
.scroll-wrapper { .scroll-wrapper {
overflow: auto; overflow: auto;
.scroll-content { .scroll-content {
padding-bottom: 30rem; padding-bottom: 30rem;
}
} }
}
</style> </style>

View File

@@ -1,69 +1,65 @@
<template> <template>
<Scroll <Scroll :loading="state.loading" :full-loading="!state.list.length" @pulldown="loadData">
:loading="state.loading"
:full-loading="!state.list.length"
@pulldown="loadData"
>
<slot :list="state.list"></slot> <slot :list="state.list"></slot>
<NoMore v-if="state.total !== 0 && state.total === state.list.length" /> <NoMore v-if="state.total !== 0 && state.total === state.list.length" />
</Scroll> </Scroll>
</template> </template>
<script setup> <script setup>
import { onMounted, reactive } from 'vue' import { onMounted, reactive } from 'vue'
import { _notice } from '@/utils' import { _notice } from '@/utils'
import Scroll from '@/components/Scroll.vue' import Scroll from '@/components/Scroll.vue'
import NoMore from '@/components/NoMore.vue' import NoMore from '@/components/NoMore.vue'
const props = defineProps({ const props = defineProps({
api: { api: {
type: Function, type: Function,
default() { default() {
return () => void 0 return () => void 0
}, }
},
})
const state = reactive({
list: [],
total: 0,
pageNo: 0,
pageSize: 10,
loading: false,
})
function loadData() {
if (state.loading) return
state.pageNo++
getData()
} }
})
async function getData(refresh = false) { const state = reactive({
list: [],
total: 0,
pageNo: 0,
pageSize: 10,
loading: false
})
function loadData() {
if (state.loading) return
state.pageNo++
getData()
}
async function getData(refresh = false) {
if (refresh) {
state.pageNo = 0
} else {
if (state.total !== 0 && state.total === state.list.length) return
}
if (state.loading) return
state.loading = true
let res = await props.api({
pageNo: state.pageNo,
pageSize: state.pageSize
})
state.loading = false
if (res.success) {
if (refresh) { if (refresh) {
state.pageNo = 0 state.list = res.data.list
} else { } else {
if (state.total !== 0 && state.total === state.list.length) return state.list = state.list.concat(res.data.list)
}
if (state.loading) return
state.loading = true
let res = await props.api({
pageNo: state.pageNo,
pageSize: state.pageSize,
})
state.loading = false
if (res.success) {
if (refresh) {
state.list = res.data.list
} else {
state.list = state.list.concat(res.data.list)
}
state.total = res.data.total
} else {
_notice('查询失败')
} }
state.total = res.data.total
} else {
_notice('查询失败')
} }
}
onMounted(getData) onMounted(getData)
</script> </script>
<style scoped lang="less"></style> <style scoped lang="less"></style>

View File

@@ -30,128 +30,128 @@
</template> </template>
<script> <script>
//TODO 背景颜色不对 //TODO 背景颜色不对
export default { export default {
name: 'Search', name: 'Search',
props: { props: {
placeholder: { placeholder: {
type: String, type: String,
default: '搜索', default: '搜索'
},
modelValue: {
type: String,
default: '',
},
rightTextColor: {
type: String,
default: 'red',
},
isShowRightText: {
type: Boolean,
default: false,
},
isShowSearchIcon: {
type: Boolean,
default: true,
},
rightText: {
type: String,
default: '搜索',
},
mode: {
type: String,
default: 'dark',
},
}, },
methods: { modelValue: {
clear() { type: String,
this.value = '' default: ''
},
}, },
mounted() {}, rightTextColor: {
computed: { type: String,
value: { default: 'red'
get() {
return this.modelValue
},
set(val) {
this.$emit('update:modelValue', val)
if (!val) {
this.$emit('clear')
}
},
},
}, },
isShowRightText: {
type: Boolean,
default: false
},
isShowSearchIcon: {
type: Boolean,
default: true
},
rightText: {
type: String,
default: '搜索'
},
mode: {
type: String,
default: 'dark'
}
},
methods: {
clear() {
this.value = ''
}
},
mounted() {},
computed: {
value: {
get() {
return this.modelValue
},
set(val) {
this.$emit('update:modelValue', val)
if (!val) {
this.$emit('clear')
}
}
}
} }
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
.search-ctn { .search-ctn {
display: flex; display: flex;
align-items: center; align-items: center;
&.dark {
.search {
background: var(--second-btn-color-tran);
}
}
&.light {
.search {
background: whitesmoke;
input {
color: black;
}
}
}
.rightTextColor {
margin-left: 15rem;
font-size: 14rem;
}
&.dark {
.search { .search {
font-size: 14rem; background: var(--second-btn-color-tran);
padding: 0; }
flex: 1; }
position: relative;
height: 36rem;
border-radius: 2px;
display: flex;
align-items: center;
.search-icon { &.light {
height: 22rem; .search {
width: 22rem; background: whitesmoke;
margin-left: 7rem;
}
input { input {
//margin-top: .4rem; color: black;
color: white;
height: 50%;
width: 100%;
outline: none;
border: none;
padding: 0 0 0 7rem;
background: transparent;
&::-webkit-input-placeholder {
color: var(--second-text-color);
}
}
.suffix {
display: flex;
align-items: center;
position: absolute;
right: 15rem;
img {
width: 15rem;
}
} }
} }
} }
.rightTextColor {
margin-left: 15rem;
font-size: 14rem;
}
.search {
font-size: 14rem;
padding: 0;
flex: 1;
position: relative;
height: 36rem;
border-radius: 2px;
display: flex;
align-items: center;
.search-icon {
height: 22rem;
width: 22rem;
margin-left: 7rem;
}
input {
//margin-top: .4rem;
color: white;
height: 50%;
width: 100%;
outline: none;
border: none;
padding: 0 0 0 7rem;
background: transparent;
&::-webkit-input-placeholder {
color: var(--second-text-color);
}
}
.suffix {
display: flex;
align-items: center;
position: absolute;
right: 15rem;
img {
width: 15rem;
}
}
}
}
</style> </style>

View File

@@ -13,19 +13,10 @@
<div class="share"> <div class="share">
<div class="title"> <div class="title">
<span>分享给朋友</span> <span>分享给朋友</span>
<dy-back <dy-back mode="light" img="close" direction="right" @click.stop="closeShare"></dy-back>
mode="light"
img="close"
direction="right"
@click.stop="closeShare"
></dy-back>
</div> </div>
<div class="friends list"> <div class="friends list">
<div <div class="option" v-for="item in friends.all" @click.stop="toggleCall(item)">
class="option"
v-for="item in friends.all"
@click.stop="toggleCall(item)"
>
<img <img
:style="item.select ? 'opacity: .5;' : ''" :style="item.select ? 'opacity: .5;' : ''"
class="avatar" class="avatar"
@@ -39,10 +30,7 @@
src="../assets/img/icon/components/check/check-red-share.png" src="../assets/img/icon/components/check/check-red-share.png"
/> />
</div> </div>
<div <div class="option" @click.stop="closeShare($nav('/message/share-to-friend'))">
class="option"
@click.stop="closeShare($nav('/message/share-to-friend'))"
>
<dy-back class="more" mode="light" direction="right"></dy-back> <dy-back class="more" mode="light" direction="right"></dy-back>
<span>更多朋友</span> <span>更多朋友</span>
</div> </div>
@@ -50,11 +38,7 @@
<div class="shares list"> <div class="shares list">
<template v-if="mode === 'video'"> <template v-if="mode === 'video'">
<div class="option" @click.stop="closeShare($emit('ShareToFriend'))"> <div class="option" @click.stop="closeShare($emit('ShareToFriend'))">
<img <img class="avatar" src="../assets/img/icon/components/video/torichang.png" alt="" />
class="avatar"
src="../assets/img/icon/components/video/torichang.png"
alt=""
/>
<span>转发</span> <span>转发</span>
</div> </div>
<div class="option" @click.stop="closeShare($emit('ShareToFriend'))"> <div class="option" @click.stop="closeShare($emit('ShareToFriend'))">
@@ -66,67 +50,36 @@
<span>复制链接</span> <span>复制链接</span>
</div> </div>
<div class="option" @click.stop="$no"> <div class="option" @click.stop="$no">
<img <img class="small" src="../assets/img/icon/components/video/comeonplay.png" alt="" />
class="small"
src="../assets/img/icon/components/video/comeonplay.png"
alt=""
/>
<span>合拍</span> <span>合拍</span>
</div> </div>
<div class="option" @click.stop="$no"> <div class="option" @click.stop="$no">
<img <img class="small" src="../assets/img/icon/components/video/dou.webp" alt="" />
class="small"
src="../assets/img/icon/components/video/dou.webp"
alt=""
/>
<span>帮上热门</span> <span>帮上热门</span>
</div> </div>
<div <div class="option" @click.stop="$nav('/home/report', { mode: this.mode })">
class="option" <img class="small" src="../assets/img/icon/components/video/warring.png" alt="" />
@click.stop="$nav('/home/report', { mode: this.mode })"
>
<img
class="small"
src="../assets/img/icon/components/video/warring.png"
alt=""
/>
<span>举报</span> <span>举报</span>
</div> </div>
<div class="option" @click.stop="closeShare($emit('ShareToFriend'))"> <div class="option" @click.stop="closeShare($emit('ShareToFriend'))">
<Icon icon="ion:paper-plane" /> <Icon icon="ion:paper-plane" />
<span>私信朋友</span> <span>私信朋友</span>
</div> </div>
<div <div class="option" v-if="canDownload" @click.stop="closeShare($emit('download'))">
class="option"
v-if="canDownload"
@click.stop="closeShare($emit('download'))"
>
<Icon icon="mingcute:download-fill" /> <Icon icon="mingcute:download-fill" />
<span>保存本地</span> <span>保存本地</span>
</div> </div>
<div class="option" @click.stop="$no"> <div class="option" @click.stop="$no">
<!--TODO icon不对 --> <!--TODO icon不对 -->
<img <img class="small" src="../assets/img/icon/components/video/feedback.webp" alt="" />
class="small"
src="../assets/img/icon/components/video/feedback.webp"
alt=""
/>
<span>建群分享</span> <span>建群分享</span>
</div> </div>
<div class="option" @click.stop="$no"> <div class="option" @click.stop="$no">
<img <img class="small" src="../assets/img/icon/components/video/comeonlook.webp" alt="" />
class="small"
src="../assets/img/icon/components/video/comeonlook.webp"
alt=""
/>
<span>一起看视频</span> <span>一起看视频</span>
</div> </div>
<div class="option" @click.stop="closeShare($emit('dislike'))"> <div class="option" @click.stop="closeShare($emit('dislike'))">
<img <img class="small" src="../assets/img/icon/components/video/dislike.png" alt="" />
class="small"
src="../assets/img/icon/components/video/dislike.png"
alt=""
/>
<span>不感兴趣</span> <span>不感兴趣</span>
</div> </div>
<div class="option" @click.stop="closeShare($emit('showDouyinCode'))"> <div class="option" @click.stop="closeShare($emit('showDouyinCode'))">
@@ -134,58 +87,31 @@
<span>生成图片</span> <span>生成图片</span>
</div> </div>
<div class="option" @click.stop="$no"> <div class="option" @click.stop="$no">
<img <img class="small" src="../assets/img/icon/components/video/bizhi.webp" alt="" />
class="small"
src="../assets/img/icon/components/video/bizhi.webp"
alt=""
/>
<span>动态壁纸</span> <span>动态壁纸</span>
</div> </div>
<div class="option" @click.stop="closeShare($emit('play-feedback'))"> <div class="option" @click.stop="closeShare($emit('play-feedback'))">
<img <img class="small" src="../assets/img/icon/components/video/feedback.webp" alt="" />
class="small"
src="../assets/img/icon/components/video/feedback.webp"
alt=""
/>
<span>播放反馈</span> <span>播放反馈</span>
</div> </div>
</template> </template>
<template v-if="mode === 'music'"> <template v-if="mode === 'music'">
<div class="option" @click.stop="closeShare($emit('ShareToFriend'))"> <div class="option" @click.stop="closeShare($emit('ShareToFriend'))">
<img <img class="small" src="../assets/img/icon/components/video/tofriend.webp" alt="" />
class="small"
src="../assets/img/icon/components/video/tofriend.webp"
alt=""
/>
<span>私信朋友</span> <span>私信朋友</span>
</div> </div>
<div <div class="option" @click.stop="$nav('/home/report', { mode: this.mode })">
class="option" <img class="small" src="../assets/img/icon/components/video/warring.png" alt="" />
@click.stop="$nav('/home/report', { mode: this.mode })"
>
<img
class="small"
src="../assets/img/icon/components/video/warring.png"
alt=""
/>
<span>举报音乐</span> <span>举报音乐</span>
</div> </div>
</template> </template>
<template v-if="mode === 'my-music'"> <template v-if="mode === 'my-music'">
<div class="option" @click.stop="$no"> <div class="option" @click.stop="$no">
<img <img class="small" src="../assets/img/icon/components/video/torichang.png" alt="" />
class="small"
src="../assets/img/icon/components/video/torichang.png"
alt=""
/>
<span>转发到日常</span> <span>转发到日常</span>
</div> </div>
<div class="option" @click.stop="closeShare($emit('ShareToFriend'))"> <div class="option" @click.stop="closeShare($emit('ShareToFriend'))">
<img <img class="small" src="../assets/img/icon/components/video/tofriend.webp" alt="" />
class="small"
src="../assets/img/icon/components/video/tofriend.webp"
alt=""
/>
<span>私信朋友</span> <span>私信朋友</span>
</div> </div>
</template> </template>
@@ -197,11 +123,7 @@
<img class="poster" src="../assets/img/poster/1.jpg" alt="" /> <img class="poster" src="../assets/img/poster/1.jpg" alt="" />
</div> </div>
<div class="btns"> <div class="btns">
<dy-button <dy-button type="dark2" radius="7" v-if="selectFriends.length > 1" @click.stop="$no"
type="dark2"
radius="7"
v-if="selectFriends.length > 1"
@click.stop="$no"
>建群并发送 >建群并发送
</dy-button> </dy-button>
<dy-button type="primary" radius="7" @click.stop="$no" <dy-button type="primary" radius="7" @click.stop="$no"
@@ -214,229 +136,227 @@
</template> </template>
<script> <script>
import { mapState } from 'pinia' import { mapState } from 'pinia'
import Check from './Check' import Check from './Check'
import FromBottomDialog from './dialog/FromBottomDialog' import FromBottomDialog from './dialog/FromBottomDialog'
import DouyinCode from './DouyinCode' import DouyinCode from './DouyinCode'
import { useBaseStore } from '@/store/pinia' import { useBaseStore } from '@/store/pinia'
import { $no, _copy } from '@/utils' import { $no, _copy } from '@/utils'
export default { export default {
name: 'Share', name: 'Share',
components: { components: {
FromBottomDialog, FromBottomDialog,
Check, Check,
DouyinCode, DouyinCode
},
props: {
modelValue: false,
item: {},
videoId: {
type: String,
default: null
}, },
props: { pageId: {
modelValue: false, type: String,
item: {}, default: 'home-index'
videoId: {
type: String,
default: null,
},
pageId: {
type: String,
default: 'home-index',
},
canDownload: {
type: Boolean,
default: true,
},
mode: {
type: String,
default: 'video',
//music
//qrcode
},
}, },
computed: { canDownload: {
...mapState(useBaseStore, ['friends']), type: Boolean,
selectFriends() { default: true
return this.friends.all.filter((v) => v.select)
},
}, },
data() { mode: {
return {} type: String,
default: 'video'
//music
//qrcode
}
},
computed: {
...mapState(useBaseStore, ['friends']),
selectFriends() {
return this.friends.all.filter((v) => v.select)
}
},
data() {
return {}
},
methods: {
$no,
async copyLink() {
this.closeShare()
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('复制成功')
}, },
methods: {
$no,
async copyLink() {
this.closeShare()
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('复制成功')
},
toggleCall(item) { toggleCall(item) {
item.select = !item.select item.select = !item.select
},
closeShare() {
this.friends.all = this.friends.all.map((v) => {
v.select = false
return v
})
this.$emit('update:modelValue', false)
},
}, },
closeShare() {
this.friends.all = this.friends.all.map((v) => {
v.select = false
return v
})
this.$emit('update:modelValue', false)
}
} }
}
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import '../assets/less/index'; @import '../assets/less/index';
.share { .share {
width: 100%; width: 100%;
background: black; background: black;
border-radius: 10px 10px 0 0; border-radius: 10px 10px 0 0;
color: white; color: white;
box-sizing: border-box; box-sizing: border-box;
@space-width: 26rem; @space-width: 26rem;
@avatar-width: 58rem; @avatar-width: 58rem;
@icon-width: 30rem; @icon-width: 30rem;
.title { .title {
font-size: 14rem; font-size: 14rem;
padding: 10rem 20rem 30rem 20rem; padding: 10rem 20rem 30rem 20rem;
position: relative; position: relative;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
img { img {
width: 14rem; width: 14rem;
height: 14rem; height: 14rem;
padding: 6rem; padding: 6rem;
border-radius: 50%; border-radius: 50%;
background: var(--second-btn-color-tran); background: var(--second-btn-color-tran);
//background: rgb(56, 58, 57); //background: rgb(56, 58, 57);
}
} }
}
.list { .list {
overflow-x: scroll; overflow-x: scroll;
display: flex; display: flex;
padding: 0 20rem; padding: 0 20rem;
gap: 22rem; gap: 22rem;
padding-bottom: 50rem; padding-bottom: 50rem;
} }
@c: rgb(51, 51, 51); @c: rgb(51, 51, 51);
.option { .option {
width: @avatar-width;
position: relative;
font-size: 10rem;
display: flex;
flex-direction: column;
align-items: center;
.avatar {
width: @avatar-width; width: @avatar-width;
position: relative; height: @avatar-width;
font-size: 10rem; border-radius: 50%;
}
.checked {
position: absolute;
top: @avatar-width - 1.5;
right: -2px;
width: 20rem;
height: 20rem;
border-radius: 50%;
}
span {
margin-top: 8rem;
text-align: center;
width: @avatar-width;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.more {
width: 20rem;
padding: 19rem;
border-radius: 50%;
background: @c;
//background: rgb(56, 58, 57);
}
svg {
.more;
width: unset;
padding: 16rem;
font-size: 26rem;
color: rgb(205, 205, 205);
}
.small {
width: @icon-width;
height: @icon-width;
padding: 14rem;
border-radius: 50%;
background: @c;
}
}
.share2friend {
position: fixed;
bottom: 0;
padding: 20rem;
box-sizing: border-box;
width: 100vw;
height: 180rem;
background: black;
display: flex;
flex-direction: column;
justify-content: space-between;
.comment {
display: flex; display: flex;
flex-direction: column; flex: 1;
align-items: center;
.avatar { textarea {
width: @avatar-width; flex: 1;
height: @avatar-width; outline: none;
border-radius: 50%; border: none;
background: transparent;
color: #fff;
} }
.checked { .poster {
position: absolute; margin-left: 20rem;
top: @avatar-width - 1.5; height: 40rem;
right: -2px; width: 40rem;
width: 20rem;
height: 20rem;
border-radius: 50%;
}
span {
margin-top: 8rem;
text-align: center;
width: @avatar-width;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.more {
width: 20rem;
padding: 19rem;
border-radius: 50%;
background: @c;
//background: rgb(56, 58, 57);
}
svg {
.more;
width: unset;
padding: 16rem;
font-size: 26rem;
color: rgb(205, 205, 205);
}
.small {
width: @icon-width;
height: @icon-width;
padding: 14rem;
border-radius: 50%;
background: @c;
} }
} }
.share2friend { .btns {
position: fixed;
bottom: 0;
padding: 20rem;
box-sizing: border-box;
width: 100vw;
height: 180rem;
background: black;
display: flex; display: flex;
flex-direction: column; gap: 10rem;
align-items: center;
justify-content: space-between; justify-content: space-between;
.comment { .button {
display: flex;
flex: 1; flex: 1;
textarea {
flex: 1;
outline: none;
border: none;
background: transparent;
color: #fff;
}
.poster {
margin-left: 20rem;
height: 40rem;
width: 40rem;
}
}
.btns {
display: flex;
gap: 10rem;
align-items: center;
justify-content: space-between;
.button {
flex: 1;
}
} }
} }
} }
}
.share-enter-active, .share-enter-active,
.share-leave-active { .share-leave-active {
transition: all 0.15s ease; transition: all 0.15s ease;
} }
.share-enter-from, .share-enter-from,
.share-leave-to { .share-leave-to {
transform: translateY(60vh); transform: translateY(60vh);
} }
</style> </style>

File diff suppressed because it is too large Load Diff

View File

@@ -1,21 +1,21 @@
<script setup> <script setup>
import { computed } from 'vue' import { computed } from 'vue'
const props = defineProps({ const props = defineProps({
list: { list: {
type: Array, type: Array,
default() { default() {
return [] return []
}, }
}, }
}) })
const leftList = computed(() => { const leftList = computed(() => {
return props.list.filter((v, index) => index % 2 === 0) return props.list.filter((v, index) => index % 2 === 0)
}) })
const rightList = computed(() => { const rightList = computed(() => {
return props.list.filter((v, index) => index % 2 !== 0) return props.list.filter((v, index) => index % 2 !== 0)
}) })
</script> </script>
<template> <template>
@@ -30,14 +30,14 @@
</template> </template>
<style scoped lang="less"> <style scoped lang="less">
.waterfall { .waterfall {
display: flex; display: flex;
gap: 10rem; gap: 10rem;
.waterfall-row { .waterfall-row {
width: 50%; width: 50%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
}
} }
}
</style> </style>

View File

@@ -19,136 +19,136 @@
</div> </div>
</template> </template>
<script> <script>
/*TODO 单独使用时没有mark*/ /*TODO 单独使用时没有mark*/
export default { export default {
name: 'ConfirmDialog', name: 'ConfirmDialog',
props: { props: {
visible: { visible: {
type: Boolean, type: Boolean,
default: true, default: true
},
title: {
type: String,
default() {
return ''
},
},
subtitle: {
type: String,
default() {
return ''
},
},
subtitleColor: {
type: String,
default() {
return 'gray'
},
},
okText: {
type: String,
default() {
return '确定'
},
},
cancelText: {
type: String,
default() {
return '取消'
},
},
cancelTextColor: {
type: String,
default() {
return 'gray'
},
},
}, },
data() { title: {
return {} type: String,
default() {
return ''
}
}, },
methods: { subtitle: {
stop() {}, type: String,
ok() { default() {
this.$emit('ok') return ''
this.$emit('update:visible', false) }
},
cancel() {
this.$emit('cancel')
this.$emit('update:visible', false)
},
}, },
subtitleColor: {
type: String,
default() {
return 'gray'
}
},
okText: {
type: String,
default() {
return '确定'
}
},
cancelText: {
type: String,
default() {
return '取消'
}
},
cancelTextColor: {
type: String,
default() {
return 'gray'
}
}
},
data() {
return {}
},
methods: {
stop() {},
ok() {
this.$emit('ok')
this.$emit('update:visible', false)
},
cancel() {
this.$emit('cancel')
this.$emit('update:visible', false)
}
} }
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '../../assets/less/index'; @import '../../assets/less/index';
.ConfirmDialog { .ConfirmDialog {
z-index: 10; z-index: 10;
position: absolute; position: absolute;
top: 0; top: 0;
bottom: 0; bottom: 0;
left: 0; left: 0;
right: 0; right: 0;
background: #000000bb; background: #000000bb;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
color: black; color: black;
.content { .content {
background: white; background: white;
width: 70%; width: 70%;
border-radius: 2px; border-radius: 2px;
box-sizing: border-box; box-sizing: border-box;
font-size: 15rem; font-size: 15rem;
text-align: center; text-align: center;
.body { .body {
padding: 25rem; padding: 25rem;
.title { .title {
font-size: 15rem; font-size: 15rem;
font-weight: bold; font-weight: bold;
}
.subtitle {
margin-top: 10rem;
font-size: 13rem;
&.gray {
color: var(--second-text-color);
}
}
} }
.footer { .subtitle {
height: 46rem; margin-top: 10rem;
font-size: 13rem;
&.gray {
color: var(--second-text-color);
}
}
}
.footer {
height: 46rem;
display: flex;
border-top: 1px solid whitesmoke;
font-size: 14rem;
.cancel,
.ok {
display: flex; display: flex;
border-top: 1px solid whitesmoke; align-items: center;
font-size: 14rem; justify-content: center;
width: 49%;
}
.cancel, .ok {
.ok { font-weight: bold;
display: flex; }
align-items: center;
justify-content: center;
width: 49%;
}
.ok { .cancel {
font-weight: bold; border-right: 1px solid whitesmoke;
}
.cancel { &.gray {
border-right: 1px solid whitesmoke; color: var(--second-text-color);
&.gray {
color: var(--second-text-color);
}
} }
} }
} }
} }
}
</style> </style>

View File

@@ -4,32 +4,32 @@
</div> </div>
</template> </template>
<script> <script>
export default { export default {
name: 'FadeDialog', name: 'FadeDialog',
data() { data() {
return {} return {}
}, },
computed: {}, computed: {},
created() {}, created() {},
methods: {}, methods: {}
} }
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '../../assets/less/index'; @import '../../assets/less/index';
.FadeDialog { .FadeDialog {
position: fixed; position: fixed;
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
top: 0; top: 0;
overflow: auto; overflow: auto;
color: white; color: white;
font-size: 14rem; font-size: 14rem;
.content { .content {
padding-top: 60rem; padding-top: 60rem;
}
} }
}
</style> </style>

View File

@@ -28,247 +28,236 @@
</transition> </transition>
</template> </template>
<script> <script>
import Dom from '../../utils/dom' import Dom from '../../utils/dom'
import bus, { EVENT_KEY } from '@/utils/bus' import bus, { EVENT_KEY } from '@/utils/bus'
export default { export default {
name: 'FromBottomDialog', name: 'FromBottomDialog',
props: { props: {
modelValue: { modelValue: {
type: Boolean, type: Boolean,
default: false, default: false
},
mode: {
type: String,
default: 'dark',
// default: 'light'
// default: 'white'
},
maskMode: {
type: String,
default: 'dark',
},
height: {
type: String,
default: 'calc(var(--vh, 1vh) * 70)',
},
showHengGang: {
type: Boolean,
default: true,
},
pageId: {
type: String,
default: null,
required: true,
},
borderRadius: {
type: String,
default: '15rem 15rem 0 0',
},
tag: {
type: String,
default: '',
},
}, },
watch: { mode: {
modelValue(newVal) { type: String,
default: 'dark'
// default: 'light'
// default: 'white'
},
maskMode: {
type: String,
default: 'dark'
},
height: {
type: String,
default: 'calc(var(--vh, 1vh) * 70)'
},
showHengGang: {
type: Boolean,
default: true
},
pageId: {
type: String,
default: null,
required: true
},
borderRadius: {
type: String,
default: '15rem 15rem 0 0'
},
tag: {
type: String,
default: ''
}
},
watch: {
modelValue(newVal) {
let page = document.getElementById(this.pageId)
if (newVal) {
this.pagePosition = this.$getCss2(page, 'position')
page.style.position = 'absolute'
this.scroll = document.documentElement.scrollTop
document.body.style.position = 'fixed'
document.body.style.top = -this.scroll + 'px'
let maskTemplate = `<div class="Mask fade-in ${this.maskMode}"></div>`
let mask = new Dom().create(maskTemplate)
mask.on('click', (e) => {
this.$stopPropagation(e)
this.hide(false)
})
page.appendChild(mask.els[0])
} else {
let page = document.getElementById(this.pageId) let page = document.getElementById(this.pageId)
if (newVal) { page.style.position = this.pagePosition || 'fixed'
this.pagePosition = this.$getCss2(page, 'position') document.body.style.position = 'static'
page.style.position = 'absolute' document.documentElement.scrollTop = this.scroll
this.scroll = document.documentElement.scrollTop
document.body.style.position = 'fixed'
document.body.style.top = -this.scroll + 'px'
let maskTemplate = `<div class="Mask fade-in ${this.maskMode}"></div>` let mask = new Dom('.Mask').replaceClass('fade-in', 'fade-out')
let mask = new Dom().create(maskTemplate) setTimeout(() => {
mask.on('click', (e) => { mask.remove()
this.$stopPropagation(e) }, 250)
this.hide(false) }
}) }
page.appendChild(mask.els[0]) },
} else { data() {
let page = document.getElementById(this.pageId) return {
page.style.position = this.pagePosition || 'fixed' scroll: 0,
document.body.style.position = 'static' startLocationY: 0,
document.documentElement.scrollTop = this.scroll moveYDistance: 0,
startTime: 0,
let mask = new Dom('.Mask').replaceClass('fade-in', 'fade-out') pagePosition: null
setTimeout(() => { }
mask.remove() },
}, 250) computed: {},
} created() {},
}, methods: {
beforeEnter(el) {
this.$setCss(el, 'transition-duration', `250ms`)
this.$setCss(el, 'transform', `translate3d(0,${this.height},0)`)
}, },
data() { enter(el, done) {
return { setTimeout(() => {
scroll: 0, this.$setCss(el, 'transform', `translate3d(0,0,0)`)
startLocationY: 0, }, 0)
moveYDistance: 0, setTimeout(() => {
startTime: 0, // this.$setCss(el, 'transition-duration', `0ms`)
pagePosition: null, this.$setCss(el, 'transform', `none`)
done()
}, 250)
},
afterEnter() {},
beforeLeave(el) {
this.$setCss(el, 'transition-duration', `250ms`)
this.$setCss(el, 'transform', `translate3d(0,0,0)`)
},
leave(el, done) {
//ref获取不到
let maxHeight = new Dom('.FromBottomDialog').css('max-height')
this.$setCss(el, 'transform', `translate3d(0,${maxHeight},0)`)
setTimeout(done, 250)
},
afterLeave() {},
hide(val = false) {
this.$emit('update:modelValue', val)
this.$emit('cancel')
},
start(e) {
if (this.$refs.dialog.scrollTop !== 0) return
this.startLocationY = e.touches[0].pageY
this.startTime = Date.now()
this.$setCss(this.$refs.dialog, 'transition-duration', `0ms`)
},
move(e) {
if (this.$refs.dialog.scrollTop !== 0) return
this.moveYDistance = e.touches[0].pageY - this.startLocationY
if (this.moveYDistance > 0) {
bus.emit(EVENT_KEY.DIALOG_MOVE, {
tag: this.tag,
e: this.moveYDistance
})
this.$setCss(this.$refs.dialog, 'transform', `translate3d(0,${this.moveYDistance}px,0)`)
} }
}, },
computed: {}, end(e) {
created() {}, //点击
methods: { if (Date.now() - this.startTime < 150 && Math.abs(this.moveYDistance) < 30) {
beforeEnter(el) { return
this.$setCss(el, 'transition-duration', `250ms`) }
this.$setCss(el, 'transform', `translate3d(0,${this.height},0)`) //滑动
}, if (this.$refs.dialog.scrollTop !== 0) return
enter(el, done) { let clientHeight = this.$refs.dialog.clientHeight
this.$setCss(this.$refs.dialog, 'transition-duration', `250ms`)
if (Math.abs(this.moveYDistance) > clientHeight / 2) {
this.$setCss(this.$refs.dialog, 'transform', `translate3d(0,${clientHeight}px,0)`)
bus.emit(EVENT_KEY.DIALOG_END, { tag: this.tag, isClose: true })
setTimeout(this.hide, 250)
} else {
this.$setCss(this.$refs.dialog, 'transform', `translate3d(0,0,0)`)
bus.emit(EVENT_KEY.DIALOG_END, { tag: this.tag, isClose: false })
setTimeout(() => { setTimeout(() => {
this.$setCss(el, 'transform', `translate3d(0,0,0)`) this.$setCss(this.$refs.dialog, 'transform', 'none')
}, 0) // this.$setCss(this.$refs.dialog, 'transition-duration', `0ms`)
setTimeout(() => {
// this.$setCss(el, 'transition-duration', `0ms`)
this.$setCss(el, 'transform', `none`)
done()
}, 250) }, 250)
}, }
afterEnter() {}, this.moveYDistance = 0
beforeLeave(el) { }
this.$setCss(el, 'transition-duration', `250ms`)
this.$setCss(el, 'transform', `translate3d(0,0,0)`)
},
leave(el, done) {
//ref获取不到
let maxHeight = new Dom('.FromBottomDialog').css('max-height')
this.$setCss(el, 'transform', `translate3d(0,${maxHeight},0)`)
setTimeout(done, 250)
},
afterLeave() {},
hide(val = false) {
this.$emit('update:modelValue', val)
this.$emit('cancel')
},
start(e) {
if (this.$refs.dialog.scrollTop !== 0) return
this.startLocationY = e.touches[0].pageY
this.startTime = Date.now()
this.$setCss(this.$refs.dialog, 'transition-duration', `0ms`)
},
move(e) {
if (this.$refs.dialog.scrollTop !== 0) return
this.moveYDistance = e.touches[0].pageY - this.startLocationY
if (this.moveYDistance > 0) {
bus.emit(EVENT_KEY.DIALOG_MOVE, {
tag: this.tag,
e: this.moveYDistance,
})
this.$setCss(
this.$refs.dialog,
'transform',
`translate3d(0,${this.moveYDistance}px,0)`,
)
}
},
end(e) {
//点击
if (
Date.now() - this.startTime < 150 &&
Math.abs(this.moveYDistance) < 30
) {
return
}
//滑动
if (this.$refs.dialog.scrollTop !== 0) return
let clientHeight = this.$refs.dialog.clientHeight
this.$setCss(this.$refs.dialog, 'transition-duration', `250ms`)
if (Math.abs(this.moveYDistance) > clientHeight / 2) {
this.$setCss(
this.$refs.dialog,
'transform',
`translate3d(0,${clientHeight}px,0)`,
)
bus.emit(EVENT_KEY.DIALOG_END, { tag: this.tag, isClose: true })
setTimeout(this.hide, 250)
} else {
this.$setCss(this.$refs.dialog, 'transform', `translate3d(0,0,0)`)
bus.emit(EVENT_KEY.DIALOG_END, { tag: this.tag, isClose: false })
setTimeout(() => {
this.$setCss(this.$refs.dialog, 'transform', 'none')
// this.$setCss(this.$refs.dialog, 'transition-duration', `0ms`)
}, 250)
}
this.moveYDistance = 0
},
},
} }
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '../../assets/less/index'; @import '../../assets/less/index';
.FromBottomDialog { .FromBottomDialog {
z-index: 9; z-index: 9;
position: fixed; position: fixed;
width: 100%;
overflow-y: auto;
padding-top: 24rem;
bottom: 0;
left: 0;
box-sizing: border-box;
border-radius: v-bind(borderRadius);
transition: all 0.3s;
&.dark {
background: var(--main-bg);
}
&.light {
background: whitesmoke;
}
&.white {
background: white;
}
&.no-heng-gang {
padding-top: 0;
}
.heng-gang {
border-radius: 15rem 15rem 0 0;
z-index: 3;
width: 100%; width: 100%;
overflow-y: auto; position: fixed;
padding-top: 24rem; height: 30rem;
bottom: 0; display: flex;
left: 0; transform: translateY(-24rem);
box-sizing: border-box; justify-content: center;
border-radius: v-bind(borderRadius); align-items: center;
transition: all 0.3s;
&.dark { &.dark {
background: var(--main-bg); background: var(--main-bg);
.content {
background: var(--second-btn-color);
}
} }
&.light { &.light {
background: whitesmoke; background: whitesmoke;
.content {
background: darkgray;
}
} }
&.white { &.white {
background: white; background: white;
}
&.no-heng-gang {
padding-top: 0;
}
.heng-gang {
border-radius: 15rem 15rem 0 0;
z-index: 3;
width: 100%;
position: fixed;
height: 30rem;
display: flex;
transform: translateY(-24rem);
justify-content: center;
align-items: center;
&.dark {
background: var(--main-bg);
.content {
background: var(--second-btn-color);
}
}
&.light {
background: whitesmoke;
.content {
background: darkgray;
}
}
&.white {
background: white;
.content {
background: darkgray;
}
}
.content { .content {
border-radius: 2px; background: darkgray;
height: 4rem;
width: 30rem;
} }
} }
.content {
border-radius: 2px;
height: 4rem;
width: 30rem;
}
} }
}
</style> </style>

View File

@@ -14,101 +14,101 @@
</div> </div>
</template> </template>
<script> <script>
export default { export default {
name: 'NoticeDialog', name: 'NoticeDialog',
props: { props: {
visible: { visible: {
type: Boolean, type: Boolean,
default: false, default: false
},
title: {
type: String,
default() {
return ''
},
},
subtitle: {
type: String,
default() {
return ''
},
},
subtitleColor: {
type: String,
default() {
return 'gray'
},
},
cancelText: {
type: String,
default() {
return '取消'
},
},
}, },
data() { title: {
return {} type: String,
default() {
return ''
}
}, },
methods: { subtitle: {
stop() {}, type: String,
default() {
return ''
}
}, },
subtitleColor: {
type: String,
default() {
return 'gray'
}
},
cancelText: {
type: String,
default() {
return '取消'
}
}
},
data() {
return {}
},
methods: {
stop() {}
} }
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '../../assets/less/index'; @import '../../assets/less/index';
.NoticeDialog { .NoticeDialog {
z-index: 10; z-index: 10;
position: absolute; position: absolute;
top: 0; top: 0;
bottom: 0; bottom: 0;
left: 0; left: 0;
right: 0; right: 0;
background: #000000bb; background: #000000bb;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
color: black; color: black;
.content { .content {
background: white; background: white;
width: 70%; width: 70%;
border-radius: 2px; border-radius: 2px;
box-sizing: border-box; box-sizing: border-box;
font-size: 15rem; font-size: 15rem;
text-align: center; text-align: center;
.body { .body {
padding: 25rem; padding: 25rem;
.title { .title {
font-size: 15rem; font-size: 15rem;
font-weight: bold; font-weight: bold;
}
.subtitle {
margin-top: 10rem;
font-size: 13rem;
&.gray {
color: var(--second-text-color);
}
}
} }
.footer { .subtitle {
height: 46rem; margin-top: 10rem;
display: flex; font-size: 13rem;
justify-content: center;
align-items: center;
border-top: 1px solid whitesmoke;
font-size: 14rem;
.cancel { &.gray {
font-weight: bold; color: var(--second-text-color);
} }
} }
} }
.footer {
height: 46rem;
display: flex;
justify-content: center;
align-items: center;
border-top: 1px solid whitesmoke;
font-size: 14rem;
.cancel {
font-weight: bold;
}
}
} }
}
</style> </style>

View File

@@ -8,55 +8,55 @@
</div> </div>
</template> </template>
<script> <script>
export default { export default {
name: 'SelectDialog', name: 'SelectDialog',
props: { props: {
visible: { visible: {
type: Boolean, type: Boolean,
default: false, default: false
},
list: {
type: Array,
default() {
return []
},
},
},
data() {
return {}
}, },
list: {
type: Array,
default() {
return []
}
}
},
data() {
return {}
} }
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
.SelectDialog { .SelectDialog {
z-index: 10; z-index: 10;
position: absolute; position: absolute;
top: 0; top: 0;
bottom: 0; bottom: 0;
left: 0; left: 0;
right: 0; right: 0;
background: #000000bb; background: #000000bb;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
.content { .content {
background: white; background: white;
width: 80%; width: 80%;
padding: 5rem 0; padding: 5rem 0;
border-radius: 2px; border-radius: 2px;
box-sizing: border-box; box-sizing: border-box;
.item { .item {
font-size: 15rem; font-size: 15rem;
padding: 15rem 20rem; padding: 15rem 20rem;
transition: all 0.2s; transition: all 0.2s;
&:active { &:active {
background: darkgray; background: darkgray;
}
} }
} }
} }
}
</style> </style>

View File

@@ -10,72 +10,72 @@
</div> </div>
</template> </template>
<script> <script>
export default { export default {
name: 'SimpleConfirmDialog', name: 'SimpleConfirmDialog',
props: { props: {
visible: { visible: {
type: Boolean, type: Boolean,
default: false, default: false
},
title: {
type: String,
default() {
return ''
},
},
okText: {
type: String,
default() {
return '保存'
},
},
cancelText: {
type: String,
default() {
return '放弃'
},
},
}, },
data() { title: {
return {} type: String,
default() {
return ''
}
}, },
methods: { okText: {
stop() {}, type: String,
default() {
return '保存'
}
}, },
cancelText: {
type: String,
default() {
return '放弃'
}
}
},
data() {
return {}
},
methods: {
stop() {}
} }
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
.SimpleConfirmDialog { .SimpleConfirmDialog {
z-index: 10; z-index: 10;
position: absolute; position: absolute;
top: 0; top: 0;
bottom: 0; bottom: 0;
left: 0; left: 0;
right: 0; right: 0;
background: #000000bb; background: #000000bb;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
color: black; color: black;
.content { .content {
background: white; background: white;
width: 80%; width: 80%;
border-radius: 2px; border-radius: 2px;
box-sizing: border-box; box-sizing: border-box;
padding: 15rem 20rem; padding: 15rem 20rem;
font-size: 15rem; font-size: 15rem;
.footer { .footer {
margin-top: 20rem; margin-top: 20rem;
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
.cancel { .cancel {
margin-right: 25rem; margin-right: 25rem;
}
} }
} }
} }
}
</style> </style>

View File

@@ -148,18 +148,8 @@
color-stop(rgba(255, 255, 255, 0)), color-stop(rgba(255, 255, 255, 0)),
to(#ffffff) to(#ffffff)
); );
background: -webkit-linear-gradient( background: -webkit-linear-gradient(top, #ffffff, rgba(255, 255, 255, 0), #ffffff);
top, background: linear-gradient(to bottom, #ffffff, rgba(255, 255, 255, 0), #ffffff);
#ffffff,
rgba(255, 255, 255, 0),
#ffffff
);
background: linear-gradient(
to bottom,
#ffffff,
rgba(255, 255, 255, 0),
#ffffff
);
opacity: 0.9; opacity: 0.9;
pointer-events: none; pointer-events: none;
} }

View File

@@ -39,23 +39,17 @@ MobileSelect.prototype = {
var _this = this var _this = this
if (config.wheels[0].data.length == 0) { if (config.wheels[0].data.length == 0) {
console.error( console.error(
'mobileSelect has been successfully installed, but the data is empty and cannot be initialized.', 'mobileSelect has been successfully installed, but the data is empty and cannot be initialized.'
) )
return false return false
} }
_this.keyMap = config.keyMap _this.keyMap = config.keyMap ? config.keyMap : { id: 'id', value: 'value', childs: 'childs' }
? config.keyMap
: { id: 'id', value: 'value', childs: 'childs' }
_this.checkDataType() _this.checkDataType()
_this.renderWheels( _this.renderWheels(_this.wheelsData, config.cancelBtnText, config.ensureBtnText)
_this.wheelsData,
config.cancelBtnText,
config.ensureBtnText,
)
_this.trigger = document.querySelector(config.trigger) _this.trigger = document.querySelector(config.trigger)
if (!_this.trigger) { if (!_this.trigger) {
console.error( console.error(
'mobileSelect has been successfully installed, but no trigger found on your page.', 'mobileSelect has been successfully installed, but no trigger found on your page.'
) )
return false return false
} }
@@ -75,9 +69,7 @@ MobileSelect.prototype = {
_this.initPosition = config.position || [] _this.initPosition = config.position || []
_this.titleText = config.title || '' _this.titleText = config.title || ''
_this.connector = config.connector || ' ' _this.connector = config.connector || ' '
_this.triggerDisplayData = !( _this.triggerDisplayData = !(typeof config.triggerDisplayData == 'undefined')
typeof config.triggerDisplayData == 'undefined'
)
? config.triggerDisplayData ? config.triggerDisplayData
: true : true
_this.trigger.style.cursor = 'pointer' _this.trigger.style.cursor = 'pointer'
@@ -178,8 +170,7 @@ MobileSelect.prototype = {
} }
if (!isNaN(config.maskOpacity)) { if (!isNaN(config.maskOpacity)) {
_this.grayMask = _this.mobileSelect.querySelector('.grayLayer') _this.grayMask = _this.mobileSelect.querySelector('.grayLayer')
_this.grayMask.style.background = _this.grayMask.style.background = 'rgba(0, 0, 0, ' + config.maskOpacity + ')'
'rgba(0, 0, 0, ' + config.maskOpacity + ')'
} }
}, },
@@ -194,16 +185,7 @@ MobileSelect.prototype = {
var bIsAndroid = sUserAgent.match(/android/i) == 'android' var bIsAndroid = sUserAgent.match(/android/i) == 'android'
var bIsCE = sUserAgent.match(/windows ce/i) == 'windows ce' var bIsCE = sUserAgent.match(/windows ce/i) == 'windows ce'
var bIsWM = sUserAgent.match(/windows mobile/i) == 'windows mobile' var bIsWM = sUserAgent.match(/windows mobile/i) == 'windows mobile'
if ( if (bIsIpad || bIsIphoneOs || bIsMidp || bIsUc7 || bIsUc || bIsAndroid || bIsCE || bIsWM) {
bIsIpad ||
bIsIphoneOs ||
bIsMidp ||
bIsUc7 ||
bIsUc ||
bIsAndroid ||
bIsCE ||
bIsWM
) {
_this.isPC = false _this.isPC = false
} }
}, },
@@ -297,21 +279,21 @@ MobileSelect.prototype = {
function () { function () {
_this.touch(event, this.firstChild, index) _this.touch(event, this.firstChild, index)
}, },
false, false
) )
theWheel.addEventListener( theWheel.addEventListener(
'touchend', 'touchend',
function () { function () {
_this.touch(event, this.firstChild, index) _this.touch(event, this.firstChild, index)
}, },
false, false
) )
theWheel.addEventListener( theWheel.addEventListener(
'touchmove', 'touchmove',
function () { function () {
_this.touch(event, this.firstChild, index) _this.touch(event, this.firstChild, index)
}, },
false, false
) )
if (_this.isPC) { if (_this.isPC) {
@@ -321,21 +303,21 @@ MobileSelect.prototype = {
function () { function () {
_this.dragClick(event, this.firstChild, index) _this.dragClick(event, this.firstChild, index)
}, },
false, false
) )
theWheel.addEventListener( theWheel.addEventListener(
'mousemove', 'mousemove',
function () { function () {
_this.dragClick(event, this.firstChild, index) _this.dragClick(event, this.firstChild, index)
}, },
false, false
) )
theWheel.addEventListener( theWheel.addEventListener(
'mouseup', 'mouseup',
function () { function () {
_this.dragClick(event, this.firstChild, index) _this.dragClick(event, this.firstChild, index)
}, },
true, true
) )
} }
}, },
@@ -352,10 +334,7 @@ MobileSelect.prototype = {
if (_this.jsonType) { if (_this.jsonType) {
var node = _this.wheelsData[0].data var node = _this.wheelsData[0].data
for (var i = 0; i < node.length; i++) { for (var i = 0; i < node.length; i++) {
if ( if (_this.keyMap.childs in node[i] && node[i][_this.keyMap.childs].length > 0) {
_this.keyMap.childs in node[i] &&
node[i][_this.keyMap.childs].length > 0
) {
_this.cascade = true _this.cascade = true
_this.cascadeJsonData = _this.wheelsData[0].data _this.cascadeJsonData = _this.wheelsData[0].data
break break
@@ -394,16 +373,10 @@ MobileSelect.prototype = {
initCheckArrDeep: function (parent) { initCheckArrDeep: function (parent) {
var _this = this var _this = this
if (parent) { if (parent) {
if ( if (_this.keyMap.childs in parent && parent[_this.keyMap.childs].length > 0) {
_this.keyMap.childs in parent && _this.displayJson.push(_this.generateArrData(parent[_this.keyMap.childs]))
parent[_this.keyMap.childs].length > 0
) {
_this.displayJson.push(
_this.generateArrData(parent[_this.keyMap.childs]),
)
_this.initDeepCount++ _this.initDeepCount++
var nextNode = var nextNode = parent[_this.keyMap.childs][_this.initPosition[_this.initDeepCount]]
parent[_this.keyMap.childs][_this.initPosition[_this.initDeepCount]]
if (nextNode) { if (nextNode) {
_this.initCheckArrDeep(nextNode) _this.initCheckArrDeep(nextNode)
} else { } else {
@@ -417,13 +390,8 @@ MobileSelect.prototype = {
//检测子节点深度 修改 displayJson //检测子节点深度 修改 displayJson
var _this = this var _this = this
if (parent) { if (parent) {
if ( if (_this.keyMap.childs in parent && parent[_this.keyMap.childs].length > 0) {
_this.keyMap.childs in parent && _this.displayJson.push(_this.generateArrData(parent[_this.keyMap.childs])) //生成子节点数组
parent[_this.keyMap.childs].length > 0
) {
_this.displayJson.push(
_this.generateArrData(parent[_this.keyMap.childs]),
) //生成子节点数组
_this.checkArrDeep(parent[_this.keyMap.childs][0]) //检测下一个子节点 _this.checkArrDeep(parent[_this.keyMap.childs][0]) //检测下一个子节点
} }
} }
@@ -539,18 +507,12 @@ MobileSelect.prototype = {
var _this = this var _this = this
var tempHTML = '' var tempHTML = ''
if (_this.cascade) { if (_this.cascade) {
console.error( console.error('级联格式不支持updateWheel(),请使用updateWheels()更新整个数据源')
'级联格式不支持updateWheel(),请使用updateWheels()更新整个数据源',
)
return false return false
} else if (_this.jsonType) { } else if (_this.jsonType) {
for (var j = 0; j < data.length; j++) { for (var j = 0; j < data.length; j++) {
tempHTML += tempHTML +=
'<li data-id="' + '<li data-id="' + data[j][_this.keyMap.id] + '">' + data[j][_this.keyMap.value] + '</li>'
data[j][_this.keyMap.id] +
'">' +
data[j][_this.keyMap.value] +
'</li>'
} }
_this.wheelsData[sliderIndex] = { data: data } _this.wheelsData[sliderIndex] = { data: data }
} else { } else {
@@ -593,9 +555,7 @@ MobileSelect.prototype = {
} }
} else if (_this.jsonType) { } else if (_this.jsonType) {
for (var i = 0; i < _this.curDistance.length; i++) { for (var i = 0; i < _this.curDistance.length; i++) {
temp.push( temp.push(_this.wheelsData[i].data[_this.getIndex(_this.curDistance[i])])
_this.wheelsData[i].data[_this.getIndex(_this.curDistance[i])],
)
} }
} else { } else {
for (var i = 0; i < _this.curDistance.length; i++) { for (var i = 0; i < _this.curDistance.length; i++) {
@@ -643,13 +603,9 @@ MobileSelect.prototype = {
updateCurDistance: function (theSlider, index) { updateCurDistance: function (theSlider, index) {
if (theSlider.style.transform) { if (theSlider.style.transform) {
this.curDistance[index] = parseInt( this.curDistance[index] = parseInt(theSlider.style.transform.split(',')[1])
theSlider.style.transform.split(',')[1],
)
} else { } else {
this.curDistance[index] = parseInt( this.curDistance[index] = parseInt(theSlider.style.webkitTransform.split(',')[1])
theSlider.style.webkitTransform.split(',')[1],
)
} }
}, },
@@ -680,22 +636,18 @@ MobileSelect.prototype = {
case 'touchend': case 'touchend':
_this.moveEndY = parseInt(event.changedTouches[0].clientY) _this.moveEndY = parseInt(event.changedTouches[0].clientY)
_this.offsetSum = _this.moveEndY - _this.startY _this.offsetSum = _this.moveEndY - _this.startY
_this.oversizeBorder = _this.oversizeBorder = -(theSlider.getElementsByTagName('li').length - 3) * _this.liHeight
-(theSlider.getElementsByTagName('li').length - 3) * _this.liHeight
if (_this.offsetSum == 0) { if (_this.offsetSum == 0) {
//offsetSum为0,相当于点击事件 //offsetSum为0,相当于点击事件
// 0 1 [2] 3 4 // 0 1 [2] 3 4
var clickOffetNum = parseInt( var clickOffetNum = parseInt(
(document.documentElement.clientHeight - _this.moveEndY) / 40, (document.documentElement.clientHeight - _this.moveEndY) / 40
) )
if (clickOffetNum != 2) { if (clickOffetNum != 2) {
var offset = clickOffetNum - 2 var offset = clickOffetNum - 2
var newDistance = _this.curDistance[index] + offset * _this.liHeight var newDistance = _this.curDistance[index] + offset * _this.liHeight
if ( if (newDistance <= 2 * _this.liHeight && newDistance >= _this.oversizeBorder) {
newDistance <= 2 * _this.liHeight &&
newDistance >= _this.oversizeBorder
) {
_this.curDistance[index] = newDistance _this.curDistance[index] = newDistance
_this.movePosition(theSlider, _this.curDistance[index]) _this.movePosition(theSlider, _this.curDistance[index])
_this.transitionEnd(_this.getIndexArr(), _this.getCurValue()) _this.transitionEnd(_this.getIndexArr(), _this.getCurValue())
@@ -713,10 +665,7 @@ MobileSelect.prototype = {
setTimeout(function () { setTimeout(function () {
_this.movePosition(theSlider, _this.curDistance[index]) _this.movePosition(theSlider, _this.curDistance[index])
}, 100) }, 100)
} else if ( } else if (_this.curDistance[index] + _this.offsetSum < _this.oversizeBorder) {
_this.curDistance[index] + _this.offsetSum <
_this.oversizeBorder
) {
_this.curDistance[index] = _this.oversizeBorder _this.curDistance[index] = _this.oversizeBorder
setTimeout(function () { setTimeout(function () {
_this.movePosition(theSlider, _this.curDistance[index]) _this.movePosition(theSlider, _this.curDistance[index])
@@ -757,20 +706,16 @@ MobileSelect.prototype = {
case 'mouseup': case 'mouseup':
_this.moveEndY = event.clientY _this.moveEndY = event.clientY
_this.offsetSum = _this.moveEndY - _this.startY _this.offsetSum = _this.moveEndY - _this.startY
_this.oversizeBorder = _this.oversizeBorder = -(theSlider.getElementsByTagName('li').length - 3) * _this.liHeight
-(theSlider.getElementsByTagName('li').length - 3) * _this.liHeight
if (_this.offsetSum == 0) { if (_this.offsetSum == 0) {
var clickOffetNum = parseInt( var clickOffetNum = parseInt(
(document.documentElement.clientHeight - _this.moveEndY) / 40, (document.documentElement.clientHeight - _this.moveEndY) / 40
) )
if (clickOffetNum != 2) { if (clickOffetNum != 2) {
var offset = clickOffetNum - 2 var offset = clickOffetNum - 2
var newDistance = _this.curDistance[index] + offset * _this.liHeight var newDistance = _this.curDistance[index] + offset * _this.liHeight
if ( if (newDistance <= 2 * _this.liHeight && newDistance >= _this.oversizeBorder) {
newDistance <= 2 * _this.liHeight &&
newDistance >= _this.oversizeBorder
) {
_this.curDistance[index] = newDistance _this.curDistance[index] = newDistance
_this.movePosition(theSlider, _this.curDistance[index]) _this.movePosition(theSlider, _this.curDistance[index])
_this.transitionEnd(_this.getIndexArr(), _this.getCurValue()) _this.transitionEnd(_this.getIndexArr(), _this.getCurValue())
@@ -788,10 +733,7 @@ MobileSelect.prototype = {
setTimeout(function () { setTimeout(function () {
_this.movePosition(theSlider, _this.curDistance[index]) _this.movePosition(theSlider, _this.curDistance[index])
}, 100) }, 100)
} else if ( } else if (_this.curDistance[index] + _this.offsetSum < _this.oversizeBorder) {
_this.curDistance[index] + _this.offsetSum <
_this.oversizeBorder
) {
_this.curDistance[index] = _this.oversizeBorder _this.curDistance[index] = _this.oversizeBorder
setTimeout(function () { setTimeout(function () {
_this.movePosition(theSlider, _this.curDistance[index]) _this.movePosition(theSlider, _this.curDistance[index])
@@ -818,7 +760,7 @@ MobileSelect.prototype = {
} }
break break
} }
}, }
} }
export default MobileSelect export default MobileSelect

File diff suppressed because it is too large Load Diff

View File

@@ -1,46 +1,46 @@
<script lang="jsx"> <script lang="jsx">
import bus from '../../utils/bus' import bus from '../../utils/bus'
import { useBaseStore } from '@/store/pinia' import { useBaseStore } from '@/store/pinia'
export default { export default {
name: 'Indicator', name: 'Indicator',
setup() { setup() {
const baseStore = useBaseStore() const baseStore = useBaseStore()
return { baseStore } return { baseStore }
},
props: {
activeIndex: {
type: Number,
default: () => 0
}, },
props: { tabStyleWidth: {
activeIndex: { type: String,
type: Number, default: () => ''
default: () => 0,
},
tabStyleWidth: {
type: String,
default: () => '',
},
tabTexts: {
type: Array,
default: () => [],
},
tabRender: {
type: Function,
default: null,
},
//用于和slidList绑定因为一个页面可能有多个slidList但只有一个indicator组件
name: {
type: String,
default: () => '',
},
}, },
data() { tabTexts: {
return { type: Array,
currentSlideItemIndex: this.activeIndex, default: () => []
tabIndicatorRelationActiveIndexLefts: [], //指标和slideItem的index的对应left,
indicatorSpace: 0, //indicator之间的间距
}
}, },
computed: {}, tabRender: {
render() { type: Function,
/* default: null
},
//用于和slidList绑定因为一个页面可能有多个slidList但只有一个indicator组件
name: {
type: String,
default: () => ''
}
},
data() {
return {
currentSlideItemIndex: this.activeIndex,
tabIndicatorRelationActiveIndexLefts: [], //指标和slideItem的index的对应left,
indicatorSpace: 0 //indicator之间的间距
}
},
computed: {},
render() {
/*
* <div class="tabs" ref="tabs"> * <div class="tabs" ref="tabs">
<div class="tab" <div class="tab"
style="{width : tabStyleWidth}" style="{width : tabStyleWidth}"
@@ -50,162 +50,148 @@
<span>{{ item }}</span></div> <span>{{ item }}</span></div>
</div> </div>
* */ * */
return ( return (
<div className='indicator-ctn'> <div className="indicator-ctn">
{this.tabRender ? ( {this.tabRender ? (
this.tabRender() this.tabRender()
) : ( ) : (
<div className='tabs' ref='tabs'> <div className="tabs" ref="tabs">
{this.tabTexts.map((item, index) => { {this.tabTexts.map((item, index) => {
return ( return (
<div <div
className={ className={this.currentSlideItemIndex === index ? 'active tab' : 'tab'}
this.currentSlideItemIndex === index style={{
? 'active tab' width: this.tabStyleWidth || 100 / this.tabTexts.length + '%'
: 'tab' }}
} onClick={(e) => this.changeIndex(index)}
style={{ >
width: <span> {item}</span>
this.tabStyleWidth || 100 / this.tabTexts.length + '%', </div>
}} )
onClick={(e) => this.changeIndex(index)} })}
> </div>
<span> {item}</span> )}
</div> <div
) className="indicator"
})} ref="indicator"
</div> style={{
)} width: this.tabStyleWidth || 100 / this.tabTexts.length + '%'
<div }}
className='indicator' />
ref='indicator' </div>
style={{ )
width: this.tabStyleWidth || 100 / this.tabTexts.length + '%', },
}} mounted() {
/> this.initTabs()
</div> bus.on(this.name + '-moved', this.move)
bus.on(this.name + '-end', this.end)
},
methods: {
changeIndex(index) {
this.currentSlideItemIndex = index
this.$attrs['onUpdate:activeIndex'] &&
this.$emit('update:active-index', this.currentSlideItemIndex)
this.$setCss(this.indicatorRef, 'transition-duration', `300ms`)
this.$setCss(
this.indicatorRef,
'left',
this.tabIndicatorRelationActiveIndexLefts[this.currentSlideItemIndex] + 'px'
) )
}, },
mounted() { initTabs() {
this.initTabs() let tabs = this.$refs.tabs
bus.on(this.name + '-moved', this.move) this.indicatorRef = this.$refs.indicator
bus.on(this.name + '-end', this.end) for (let i = 0; i < tabs.children.length; i++) {
}, let item = tabs.children[i]
methods: { this.tabWidth = this.$getCss(item, 'width')
changeIndex(index) { this.tabIndicatorRelationActiveIndexLefts.push(
this.currentSlideItemIndex = index item.getBoundingClientRect().x -
this.$attrs['onUpdate:activeIndex'] && tabs.children[0].getBoundingClientRect().x +
this.$emit('update:active-index', this.currentSlideItemIndex) (this.indicatorType === 'home' ? this.tabWidth * 0.15 : 0)
this.$setCss(this.indicatorRef, 'transition-duration', `300ms`)
this.$setCss(
this.indicatorRef,
'left',
this.tabIndicatorRelationActiveIndexLefts[
this.currentSlideItemIndex
] + 'px',
) )
}, }
initTabs() { this.indicatorSpace =
let tabs = this.$refs.tabs this.tabIndicatorRelationActiveIndexLefts[1] - this.tabIndicatorRelationActiveIndexLefts[0]
this.indicatorRef = this.$refs.indicator this.$setCss(this.indicatorRef, 'transition-duration', `0ms`)
for (let i = 0; i < tabs.children.length; i++) { this.$setCss(
let item = tabs.children[i] this.indicatorRef,
this.tabWidth = this.$getCss(item, 'width') 'left',
this.tabIndicatorRelationActiveIndexLefts.push( this.tabIndicatorRelationActiveIndexLefts[this.currentSlideItemIndex] + 'px'
item.getBoundingClientRect().x - )
tabs.children[0].getBoundingClientRect().x + },
(this.indicatorType === 'home' ? this.tabWidth * 0.15 : 0), move(e) {
) this.$setCss(
} this.indicatorRef,
this.indicatorSpace = 'left',
this.tabIndicatorRelationActiveIndexLefts[1] - this.tabIndicatorRelationActiveIndexLefts[this.currentSlideItemIndex] -
this.tabIndicatorRelationActiveIndexLefts[0] e.x.distance / (this.baseStore.bodyWidth / this.indicatorSpace) +
'px'
)
},
end(index) {
// console.log(index)
this.currentSlideItemIndex = index
this.$setCss(this.indicatorRef, 'transition-duration', `300ms`)
this.$setCss(
this.indicatorRef,
'left',
this.tabIndicatorRelationActiveIndexLefts[this.currentSlideItemIndex] + 'px'
)
setTimeout(() => {
this.$setCss(this.indicatorRef, 'transition-duration', `0ms`) this.$setCss(this.indicatorRef, 'transition-duration', `0ms`)
this.$setCss( }, 300)
this.indicatorRef, }
'left',
this.tabIndicatorRelationActiveIndexLefts[
this.currentSlideItemIndex
] + 'px',
)
},
move(e) {
this.$setCss(
this.indicatorRef,
'left',
this.tabIndicatorRelationActiveIndexLefts[
this.currentSlideItemIndex
] -
e.x.distance / (this.baseStore.bodyWidth / this.indicatorSpace) +
'px',
)
},
end(index) {
// console.log(index)
this.currentSlideItemIndex = index
this.$setCss(this.indicatorRef, 'transition-duration', `300ms`)
this.$setCss(
this.indicatorRef,
'left',
this.tabIndicatorRelationActiveIndexLefts[
this.currentSlideItemIndex
] + 'px',
)
setTimeout(() => {
this.$setCss(this.indicatorRef, 'transition-duration', `0ms`)
}, 300)
},
},
} }
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '../../assets/less/index'; @import '../../assets/less/index';
.indicator-ctn { .indicator-ctn {
font-size: 14rem; font-size: 14rem;
width: 100%; width: 100%;
height: var(--indicator-height); height: var(--indicator-height);
top: 0; top: 0;
left: 0; left: 0;
right: 0; right: 0;
z-index: 1; z-index: 1;
background: var(--main-bg); background: var(--main-bg);
.tabs { .tabs {
display: flex;
justify-content: space-between;
font-weight: bold;
.tab {
height: 40rem;
width: 45%;
display: flex; display: flex;
justify-content: space-between; justify-content: center;
font-weight: bold; align-items: center;
color: gray;
transition: color 0.3s;
font-size: 16rem;
.tab { &.active {
height: 40rem; color: white;
width: 45%; }
display: flex;
justify-content: center;
align-items: center;
color: gray;
transition: color 0.3s;
font-size: 16rem;
&.active { img {
color: white; margin-left: 5rem;
} @width: 12rem;
width: @width;
img { height: @width;
margin-left: 5rem;
@width: 12rem;
width: @width;
height: @width;
}
} }
} }
.indicator {
height: 2px;
background: gold;
width: 45%;
position: relative;
transition: all 0.3s;
}
} }
.indicator {
height: 2px;
background: gold;
width: 45%;
position: relative;
transition: all 0.3s;
}
}
</style> </style>

View File

@@ -1,46 +1,46 @@
<script lang="jsx"> <script lang="jsx">
import bus from '../../utils/bus' import bus from '../../utils/bus'
import { useBaseStore } from '@/store/pinia' import { useBaseStore } from '@/store/pinia'
export default { export default {
name: 'IndicatorLight', name: 'IndicatorLight',
props: { props: {
activeIndex: { activeIndex: {
type: Number, type: Number,
default: () => 0, default: () => 0
},
tabStyleWidth: {
type: String,
default: () => '',
},
tabTexts: {
type: Array,
default: () => [],
},
tabRender: {
type: Function,
default: null,
},
//用于和slidList绑定因为一个页面可能有多个slidList但只有一个indicator组件
name: {
type: String,
default: () => '',
},
}, },
data() { tabStyleWidth: {
return { type: String,
currentSlideItemIndex: this.activeIndex, default: () => ''
tabIndicatorRelationActiveIndexLefts: [], //指标和slideItem的index的对应left,
indicatorSpace: 0, //indicator之间的间距
}
}, },
setup() { tabTexts: {
const baseStore = useBaseStore() type: Array,
return { baseStore } default: () => []
}, },
computed: {}, tabRender: {
render() { type: Function,
/* default: null
},
//用于和slidList绑定因为一个页面可能有多个slidList但只有一个indicator组件
name: {
type: String,
default: () => ''
}
},
data() {
return {
currentSlideItemIndex: this.activeIndex,
tabIndicatorRelationActiveIndexLefts: [], //指标和slideItem的index的对应left,
indicatorSpace: 0 //indicator之间的间距
}
},
setup() {
const baseStore = useBaseStore()
return { baseStore }
},
computed: {},
render() {
/*
* <div class="tabs" ref="tabs"> * <div class="tabs" ref="tabs">
<div class="tab" <div class="tab"
style="{width : tabStyleWidth}" style="{width : tabStyleWidth}"
@@ -50,157 +50,143 @@
<span>{{ item }}</span></div> <span>{{ item }}</span></div>
</div> </div>
* */ * */
return ( return (
<div className='indicator-ctn'> <div className="indicator-ctn">
{this.tabRender ? ( {this.tabRender ? (
this.tabRender() this.tabRender()
) : ( ) : (
<div className='tabs' ref='tabs'> <div className="tabs" ref="tabs">
{this.tabTexts.map((item, index) => { {this.tabTexts.map((item, index) => {
return ( return (
<div <div
className={ className={this.currentSlideItemIndex === index ? 'active tab' : 'tab'}
this.currentSlideItemIndex === index style={{
? 'active tab' width: this.tabStyleWidth || 100 / this.tabTexts.length + '%'
: 'tab' }}
} onClick={(e) => this.changeIndex(index)}
style={{ >
width: <span> {item}</span>
this.tabStyleWidth || 100 / this.tabTexts.length + '%', </div>
}} )
onClick={(e) => this.changeIndex(index)} })}
> </div>
<span> {item}</span> )}
</div> <div className="indicator" ref="indicator" />
) </div>
})} )
</div> },
)} mounted() {
<div className='indicator' ref='indicator' /> this.initTabs()
</div> bus.on(this.name + '-moved', this.move)
bus.on(this.name + '-end', this.end)
},
methods: {
changeIndex(index) {
this.currentSlideItemIndex = index
this.$attrs['onUpdate:activeIndex'] &&
this.$emit('update:active-index', this.currentSlideItemIndex)
this.$setCss(this.indicatorRef, 'transition-duration', `300ms`)
this.$setCss(
this.indicatorRef,
'left',
this.tabIndicatorRelationActiveIndexLefts[this.currentSlideItemIndex] + 'px'
) )
}, },
mounted() { initTabs() {
this.initTabs() let tabs = this.$refs.tabs
bus.on(this.name + '-moved', this.move) this.indicatorRef = this.$refs.indicator
bus.on(this.name + '-end', this.end) let indicatorWidth = this.$getCss(this.indicatorRef, 'width')
}, for (let i = 0; i < tabs.children.length; i++) {
methods: { let item = tabs.children[i]
changeIndex(index) { this.tabWidth = this.$getCss(item, 'width')
this.currentSlideItemIndex = index this.tabIndicatorRelationActiveIndexLefts.push(
this.$attrs['onUpdate:activeIndex'] && item.getBoundingClientRect().x -
this.$emit('update:active-index', this.currentSlideItemIndex) tabs.children[0].getBoundingClientRect().x +
this.$setCss(this.indicatorRef, 'transition-duration', `300ms`) (this.tabWidth * 0.5 - indicatorWidth / 2)
this.$setCss(
this.indicatorRef,
'left',
this.tabIndicatorRelationActiveIndexLefts[
this.currentSlideItemIndex
] + 'px',
) )
}, }
initTabs() {
let tabs = this.$refs.tabs
this.indicatorRef = this.$refs.indicator
let indicatorWidth = this.$getCss(this.indicatorRef, 'width')
for (let i = 0; i < tabs.children.length; i++) {
let item = tabs.children[i]
this.tabWidth = this.$getCss(item, 'width')
this.tabIndicatorRelationActiveIndexLefts.push(
item.getBoundingClientRect().x -
tabs.children[0].getBoundingClientRect().x +
(this.tabWidth * 0.5 - indicatorWidth / 2),
)
}
this.indicatorSpace = this.indicatorSpace =
this.tabIndicatorRelationActiveIndexLefts[1] - this.tabIndicatorRelationActiveIndexLefts[1] - this.tabIndicatorRelationActiveIndexLefts[0]
this.tabIndicatorRelationActiveIndexLefts[0] this.$setCss(this.indicatorRef, 'transition-duration', `0ms`)
this.$setCss(this.indicatorRef, 'transition-duration', `0ms`) this.$setCss(
this.$setCss( this.indicatorRef,
this.indicatorRef, 'left',
'left', this.tabIndicatorRelationActiveIndexLefts[this.currentSlideItemIndex] + 'px'
this.tabIndicatorRelationActiveIndexLefts[ )
this.currentSlideItemIndex
] + 'px',
)
},
move(e) {
this.$setCss(
this.indicatorRef,
'left',
this.tabIndicatorRelationActiveIndexLefts[
this.currentSlideItemIndex
] -
e.x.distance / (this.baseStore.bodyWidth / this.indicatorSpace) +
'px',
)
},
end(index) {
// console.log(index)
this.currentSlideItemIndex = index
this.$setCss(this.indicatorRef, 'transition-duration', `300ms`)
this.$setCss(
this.indicatorRef,
'left',
this.tabIndicatorRelationActiveIndexLefts[
this.currentSlideItemIndex
] + 'px',
)
setTimeout(() => {
this.$setCss(this.indicatorRef, 'transition-duration', `0ms`)
}, 300)
},
}, },
move(e) {
this.$setCss(
this.indicatorRef,
'left',
this.tabIndicatorRelationActiveIndexLefts[this.currentSlideItemIndex] -
e.x.distance / (this.baseStore.bodyWidth / this.indicatorSpace) +
'px'
)
},
end(index) {
// console.log(index)
this.currentSlideItemIndex = index
this.$setCss(this.indicatorRef, 'transition-duration', `300ms`)
this.$setCss(
this.indicatorRef,
'left',
this.tabIndicatorRelationActiveIndexLefts[this.currentSlideItemIndex] + 'px'
)
setTimeout(() => {
this.$setCss(this.indicatorRef, 'transition-duration', `0ms`)
}, 300)
}
} }
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '../../assets/less/index'; @import '../../assets/less/index';
.indicator-ctn { .indicator-ctn {
font-size: 14rem; font-size: 14rem;
width: 100%; width: 100%;
height: var(--indicator-height); height: var(--indicator-height);
top: 0; top: 0;
left: 0; left: 0;
right: 0; right: 0;
z-index: 1; z-index: 1;
.tabs { .tabs {
display: flex;
justify-content: space-between;
font-weight: bold;
.tab {
height: 45rem;
width: 45%;
display: flex; display: flex;
justify-content: space-between; justify-content: center;
font-weight: bold; align-items: center;
color: var(--second-text-color);
transition: color 0.3s;
.tab { &.active {
height: 45rem; color: white;
width: 45%; }
display: flex;
justify-content: center;
align-items: center;
color: var(--second-text-color);
transition: color 0.3s;
&.active { img {
color: white; margin-left: 5rem;
} @width: 12rem;
width: @width;
img { height: @width;
margin-left: 5rem;
@width: 12rem;
width: @width;
height: @width;
}
} }
} }
.indicator {
height: 3px;
width: 25rem;
background: #fff;
border-radius: 5px;
position: relative;
transition: all 0.3s;
}
} }
.indicator {
height: 3px;
width: 25rem;
background: #fff;
border-radius: 5px;
position: relative;
transition: all 0.3s;
}
}
</style> </style>

View File

@@ -1,38 +1,38 @@
<script setup> <script setup>
import { reactive } from 'vue' import { reactive } from 'vue'
import bus from '../../utils/bus' import bus from '../../utils/bus'
const props = defineProps({ const props = defineProps({
item: { item: {
type: Object, type: Object,
default: () => { default: () => {
return {} return {}
}, }
}, },
position: { position: {
type: Object, type: Object,
default: () => { default: () => {
return {} return {}
}, }
}, },
isMy: { isMy: {
type: Boolean, type: Boolean,
default: () => { default: () => {
return false return false
}, }
}, },
isLive: { isLive: {
type: Boolean, type: Boolean,
default: () => { default: () => {
return false return false
}, }
}, }
}) })
const state = reactive({ const state = reactive({
isAttention: false, isAttention: false,
test: [1, 2], test: [1, 2]
}) })
</script> </script>
<template> <template>
<div class="item-desc ml1r mb1r"> <div class="item-desc ml1r mb1r">
@@ -62,11 +62,7 @@
<div v-else class="comment-status"> <div v-else class="comment-status">
<div class="comment"> <div class="comment">
<div class="type-comment"> <div class="type-comment">
<img <img src="../../assets/img/icon/head-image.jpeg" alt="" class="avatar" />
src="../../assets/img/icon/head-image.jpeg"
alt=""
class="avatar"
/>
<div class="right"> <div class="right">
<p> <p>
<span class="name">zzzzz</span> <span class="name">zzzzz</span>
@@ -77,11 +73,7 @@
</div> </div>
<transition-group name="comment-status" tag="div" class="loveds"> <transition-group name="comment-status" tag="div" class="loveds">
<div class="type-loved" :key="i" v-for="i in state.test"> <div class="type-loved" :key="i" v-for="i in state.test">
<img <img src="../../assets/img/icon/head-image.jpeg" alt="" class="avatar" />
src="../../assets/img/icon/head-image.jpeg"
alt=""
class="avatar"
/>
<img src="../../assets/img/icon/love.svg" alt="" class="loved" /> <img src="../../assets/img/icon/love.svg" alt="" class="loved" />
</div> </div>
</transition-group> </transition-group>
@@ -91,137 +83,137 @@
</template> </template>
<style scoped lang="less"> <style scoped lang="less">
.item-desc { .item-desc {
position: absolute; position: absolute;
bottom: 0; bottom: 0;
.content { .content {
color: #fff; color: #fff;
width: 75vw; width: 75vw;
text-align: left; text-align: left;
.location-wrapper { .location-wrapper {
display: flex; display: flex;
.location { .location {
margin-bottom: 10rem;
display: flex;
align-items: center;
font-size: 12rem;
padding: 4rem;
border-radius: 3rem;
background: var(--second-btn-color-tran);
.gang {
height: 8rem;
width: 1.5px;
margin: 0 5rem;
background: gray;
}
img {
margin-right: 7rem;
width: 18rem;
}
}
}
.live {
border-radius: 3rem;
margin-bottom: 10rem; margin-bottom: 10rem;
padding: 3rem 6rem;
font-size: 11rem;
display: inline-flex;
background: var(--primary-btn-color);
color: white;
}
.music {
position: relative;
display: flex; display: flex;
align-items: center; align-items: center;
font-size: 12rem;
padding: 4rem;
border-radius: 3rem;
background: var(--second-btn-color-tran);
.music-image { .gang {
width: 20px; height: 8rem;
height: 20px; width: 1.5px;
margin: 0 5rem;
background: gray;
}
img {
margin-right: 7rem;
width: 18rem;
} }
} }
} }
.comment-status { .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; display: flex;
align-items: center; align-items: center;
.comment { .music-image {
.type-comment { width: 20px;
display: flex; height: 20px;
background: rgb(130, 21, 44); }
border-radius: 50px; }
}
.comment-status {
display: flex;
align-items: center;
.comment {
.type-comment {
display: flex;
background: rgb(130, 21, 44);
border-radius: 50px;
padding: 3px;
margin-bottom: 20px;
.avatar {
width: 36px;
height: 36px;
border-radius: 50%;
}
.right {
margin: 0 10px;
color: var(--second-text-color);
.name {
margin-right: 10px;
}
.text {
color: white;
}
}
}
.loveds {
}
.type-loved {
width: 40px;
height: 40px;
position: relative;
margin-bottom: 20px;
animation: test 1s;
animation-delay: 0.5s;
.avatar {
width: 36px;
height: 36px;
border-radius: 50%;
}
.loved {
position: absolute;
bottom: 0;
left: 20px;
width: 10px;
height: 10px;
background: red;
padding: 3px; padding: 3px;
margin-bottom: 20px; border-radius: 50%;
border: 2px solid white;
.avatar {
width: 36px;
height: 36px;
border-radius: 50%;
}
.right {
margin: 0 10px;
color: var(--second-text-color);
.name {
margin-right: 10px;
}
.text {
color: white;
}
}
} }
}
.loveds { @keyframes test {
from {
display: block;
transform: translate3d(0, 0, 0);
} }
to {
.type-loved { display: none;
width: 40px; transform: translate3d(0, -60px, 0);
height: 40px;
position: relative;
margin-bottom: 20px;
animation: test 1s;
animation-delay: 0.5s;
.avatar {
width: 36px;
height: 36px;
border-radius: 50%;
}
.loved {
position: absolute;
bottom: 0;
left: 20px;
width: 10px;
height: 10px;
background: red;
padding: 3px;
border-radius: 50%;
border: 2px solid white;
}
}
@keyframes test {
from {
display: block;
transform: translate3d(0, 0, 0);
}
to {
display: none;
transform: translate3d(0, -60px, 0);
}
} }
} }
} }
} }
}
</style> </style>

View File

@@ -1,54 +1,48 @@
<script setup> <script setup>
import BaseMusic from '../BaseMusic' import BaseMusic from '../BaseMusic'
import Utils from '../../utils' import Utils from '../../utils'
import { reactive } from 'vue' import { reactive } from 'vue'
import bus, { EVENT_KEY } from '@/utils/bus' import bus, { EVENT_KEY } from '@/utils/bus'
import { Icon } from '@iconify/vue' import { Icon } from '@iconify/vue'
const props = defineProps({ const props = defineProps({
item: { item: {
type: Object, type: Object,
default: () => { default: () => {
return {} return {}
}, }
}, },
position: { position: {
type: Object, type: Object,
default: () => { default: () => {
return {} return {}
}, }
}, },
isMy: { isMy: {
type: Boolean, type: Boolean,
default: () => { default: () => {
return false return false
}, }
},
})
const emit = defineEmits([
'update:item',
'goUserInfo',
'showComments',
'showShare',
'goMusic',
])
const state = reactive({})
function loved() {
Utils.updateItem(props, 'isLoved', !props.item.isLoved, emit)
} }
})
const emit = defineEmits(['update:item', 'goUserInfo', 'showComments', 'showShare', 'goMusic'])
const state = reactive({})
function attention(e) { function loved() {
e.currentTarget.classList.add('attention') Utils.updateItem(props, 'isLoved', !props.item.isLoved, emit)
setTimeout(() => { }
Utils.updateItem(props, 'isAttention', true, emit)
}, 1000)
}
function showComments() { function attention(e) {
// emit('showComments') e.currentTarget.classList.add('attention')
bus.emit(EVENT_KEY.OPEN_COMMENTS, props.item.id) setTimeout(() => {
} Utils.updateItem(props, 'isAttention', true, emit)
}, 1000)
}
function showComments() {
// emit('showComments')
bus.emit(EVENT_KEY.OPEN_COMMENTS, props.item.id)
}
</script> </script>
<template> <template>
@@ -61,11 +55,7 @@
@click.stop="bus.emit(EVENT_KEY.GO_USERINFO)" @click.stop="bus.emit(EVENT_KEY.GO_USERINFO)"
/> />
<transition name="fade"> <transition name="fade">
<div <div v-if="!props.item.isAttention" @click.stop="attention" class="options">
v-if="!props.item.isAttention"
@click.stop="attention"
class="options"
>
<img class="no" src="../../assets/img/icon/add-light.png" alt="" /> <img class="no" src="../../assets/img/icon/add-light.png" alt="" />
<img class="yes" src="../../assets/img/icon/ok-red.png" alt="" /> <img class="yes" src="../../assets/img/icon/ok-red.png" alt="" />
</div> </div>
@@ -73,61 +63,30 @@
</div> </div>
<div class="love mb2r" @click.stop="loved($event)"> <div class="love mb2r" @click.stop="loved($event)">
<div> <div>
<img <img src="../../assets/img/icon/love.svg" class="love-image" v-if="!props.item.isLoved" />
src="../../assets/img/icon/love.svg" <img src="../../assets/img/icon/loved.svg" class="love-image" v-if="props.item.isLoved" />
class="love-image"
v-if="!props.item.isLoved"
/>
<img
src="../../assets/img/icon/loved.svg"
class="love-image"
v-if="props.item.isLoved"
/>
</div> </div>
<span>{{ Utils.formatNumber(props.item.statistics.digg_count) }}</span> <span>{{ Utils.formatNumber(props.item.statistics.digg_count) }}</span>
</div> </div>
<div class="message mb2r" @click.stop="showComments"> <div class="message mb2r" @click.stop="showComments">
<Icon <Icon icon="mage:message-dots-round-fill" class="icon" style="color: white" />
icon="mage:message-dots-round-fill"
class="icon"
style="color: white"
/>
<span>{{ Utils.formatNumber(props.item.statistics.comment_count) }}</span> <span>{{ Utils.formatNumber(props.item.statistics.comment_count) }}</span>
</div> </div>
<!--TODO --> <!--TODO -->
<div <div
class="message mb2r" class="message mb2r"
@click.stop=" @click.stop="Utils.updateItem(props, 'isCollect', !props.item.isCollect, emit)"
Utils.updateItem(props, 'isCollect', !props.item.isCollect, emit)
"
> >
<Icon <Icon v-if="props.item.isCollect" icon="ic:round-star" class="icon" style="color: yellow" />
v-if="props.item.isCollect"
icon="ic:round-star"
class="icon"
style="color: yellow"
/>
<Icon v-else icon="ic:round-star" class="icon" style="color: white" /> <Icon v-else icon="ic:round-star" class="icon" style="color: white" />
<span>{{ Utils.formatNumber(props.item.statistics.comment_count) }}</span> <span>{{ Utils.formatNumber(props.item.statistics.comment_count) }}</span>
</div> </div>
<div <div v-if="!props.isMy" class="share mb2r" @click.stop="bus.emit(EVENT_KEY.SHOW_SHARE)">
v-if="!props.isMy" <img src="../../assets/img/icon/share-white-full.png" alt="" class="share-image" />
class="share mb2r"
@click.stop="bus.emit(EVENT_KEY.SHOW_SHARE)"
>
<img
src="../../assets/img/icon/share-white-full.png"
alt=""
class="share-image"
/>
<span>{{ Utils.formatNumber(props.item.statistics.share_count) }}</span> <span>{{ Utils.formatNumber(props.item.statistics.share_count) }}</span>
</div> </div>
<div v-else class="share mb2r" @click.stop="bus.emit(EVENT_KEY.SHOW_SHARE)"> <div v-else class="share mb2r" @click.stop="bus.emit(EVENT_KEY.SHOW_SHARE)">
<img <img src="../../assets/img/icon/menu-white.png" alt="" class="share-image" />
src="../../assets/img/icon/menu-white.png"
alt=""
class="share-image"
/>
</div> </div>
<!-- <BaseMusic--> <!-- <BaseMusic-->
<!-- :cover="props.item.music.cover"--> <!-- :cover="props.item.music.cover"-->
@@ -138,95 +97,95 @@
</template> </template>
<style scoped lang="less"> <style scoped lang="less">
.toolbar { .toolbar {
//width: 40px; //width: 40px;
position: absolute; position: absolute;
bottom: 0; bottom: 0;
right: 5px; right: 5px;
color: #fff; color: #fff;
.avatar-ctn { .avatar-ctn {
position: relative; position: relative;
@w: 45rem; @w: 45rem;
.avatar { .avatar {
width: @w; width: @w;
height: @w; height: @w;
border: 3rem solid white; border: 3rem solid white;
border-radius: 50%; border-radius: 50%;
}
.options {
position: absolute;
border-radius: 50%;
margin: auto;
left: 0;
right: 0;
bottom: -5px;
background: red;
//background: black;
width: 18px;
height: 18px;
display: flex;
justify-content: center;
align-items: center;
transition: all 1s;
img {
position: absolute;
width: 12px;
height: 12px;
transition: all 1s;
} }
.options { .yes {
position: absolute; opacity: 0;
border-radius: 50%; transform: rotate(-180deg);
margin: auto; }
left: 0;
right: 0;
bottom: -5px;
background: red;
//background: black;
width: 18px;
height: 18px;
display: flex;
justify-content: center;
align-items: center;
transition: all 1s;
img { &.attention {
position: absolute; background: white;
width: 12px;
height: 12px; .no {
transition: all 1s; opacity: 0;
transform: rotate(180deg);
} }
.yes { .yes {
opacity: 0; opacity: 1;
transform: rotate(-180deg); transform: rotate(0deg);
}
&.attention {
background: white;
.no {
opacity: 0;
transform: rotate(180deg);
}
.yes {
opacity: 1;
transform: rotate(0deg);
}
} }
} }
} }
.love,
.message,
.share {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
@width: 35rem;
img {
width: @width;
height: @width;
}
span {
font-size: 12rem;
}
}
.icon {
font-size: 40rem;
}
.loved {
background: red;
}
} }
.love,
.message,
.share {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
@width: 35rem;
img {
width: @width;
height: @width;
}
span {
font-size: 12rem;
}
}
.icon {
font-size: 40rem;
}
.loved {
background: red;
}
}
</style> </style>

File diff suppressed because it is too large Load Diff

View File

@@ -1,105 +1,97 @@
<script setup> <script setup>
import { onMounted, onUnmounted, reactive, ref, watch } from 'vue' import { onMounted, onUnmounted, reactive, ref, watch } from 'vue'
import GM from '../../utils' import GM from '../../utils'
import { import {
getSlideDistance, getSlideDistance,
slideInit, slideInit,
slideReset, slideReset,
slideTouchEnd, slideTouchEnd,
slideTouchMove, slideTouchMove,
slideTouchStart, slideTouchStart
} from './common' } from './common'
import { SlideType } from '@/utils/const_var' import { SlideType } from '@/utils/const_var'
const props = defineProps({ const props = defineProps({
index: { index: {
type: Number, type: Number,
default: () => { default: () => {
return 0 return 0
}, }
}, },
name: { name: {
type: String, type: String,
default: () => '', default: () => ''
}, },
//改变index是否使用动画 //改变index是否使用动画
changeActiveIndexUseAnim: { changeActiveIndexUseAnim: {
type: Boolean, type: Boolean,
default: true, default: true
}, }
}) })
const emit = defineEmits(['update:index']) const emit = defineEmits(['update:index'])
let ob = null let ob = null
const judgeValue = 20 const judgeValue = 20
const wrapperEl = ref(null) const wrapperEl = ref(null)
const state = reactive({ const state = reactive({
name: props.name, name: props.name,
localIndex: props.index, localIndex: props.index,
needCheck: true, needCheck: true,
next: false, next: false,
start: { x: 0, y: 0, time: 0 }, start: { x: 0, y: 0, time: 0 },
move: { x: 0, y: 0 }, move: { x: 0, y: 0 },
wrapper: { width: 0, height: 0, childrenLength: 0 }, wrapper: { width: 0, height: 0, childrenLength: 0 }
}) })
watch( watch(
() => props.index, () => props.index,
(newVal) => { (newVal) => {
if (state.localIndex !== newVal) { if (state.localIndex !== newVal) {
state.localIndex = newVal state.localIndex = newVal
if (props.changeActiveIndexUseAnim) { if (props.changeActiveIndexUseAnim) {
GM.$setCss(wrapperEl.value, 'transition-duration', `300ms`) GM.$setCss(wrapperEl.value, 'transition-duration', `300ms`)
}
GM.$setCss(
wrapperEl.value,
'transform',
`translate3d(${getSlideDistance(state, SlideType.HORIZONTAL, wrapperEl.value)}px, 0, 0)`,
)
} }
}, GM.$setCss(
wrapperEl.value,
'transform',
`translate3d(${getSlideDistance(state, SlideType.HORIZONTAL, wrapperEl.value)}px, 0, 0)`
)
}
}
)
onMounted(() => {
slideInit(wrapperEl.value, state, SlideType.HORIZONTAL)
ob = new MutationObserver(() => {
state.wrapper.childrenLength = wrapperEl.value.children.length
})
ob.observe(wrapperEl.value, { childList: true })
})
onUnmounted(() => {
ob.disconnect()
})
function touchStart(e) {
slideTouchStart(e, wrapperEl.value, state)
}
function touchMove(e) {
slideTouchMove(e, wrapperEl.value, state, judgeValue, canNext, null, SlideType.HORIZONTAL)
}
function touchEnd(e) {
slideTouchEnd(e, state, canNext, () => {})
slideReset(wrapperEl.value, state, SlideType.HORIZONTAL, emit)
}
function canNext(isNext) {
return !(
(state.localIndex === 0 && !isNext) ||
(state.localIndex === state.wrapper.childrenLength - 1 && isNext)
) )
}
onMounted(() => {
slideInit(wrapperEl.value, state, SlideType.HORIZONTAL)
ob = new MutationObserver(() => {
state.wrapper.childrenLength = wrapperEl.value.children.length
})
ob.observe(wrapperEl.value, { childList: true })
})
onUnmounted(() => {
ob.disconnect()
})
function touchStart(e) {
slideTouchStart(e, wrapperEl.value, state)
}
function touchMove(e) {
slideTouchMove(
e,
wrapperEl.value,
state,
judgeValue,
canNext,
null,
SlideType.HORIZONTAL,
)
}
function touchEnd(e) {
slideTouchEnd(e, state, canNext, () => {})
slideReset(wrapperEl.value, state, SlideType.HORIZONTAL, emit)
}
function canNext(isNext) {
return !(
(state.localIndex === 0 && !isNext) ||
(state.localIndex === state.wrapper.childrenLength - 1 && isNext)
)
}
</script> </script>
<template> <template>

View File

@@ -7,10 +7,10 @@
<script setup></script> <script setup></script>
<style lang="less"> <style lang="less">
.slide-item { .slide-item {
height: 100%; height: 100%;
width: 100%; width: 100%;
flex-shrink: 0; flex-shrink: 0;
position: relative; position: relative;
} }
</style> </style>

View File

@@ -1,9 +1,6 @@
<template> <template>
<div id="base-slide-wrapper" ref="slideWrapper"> <div id="base-slide-wrapper" ref="slideWrapper">
<div <div class="indicator-bullets" v-if="indicatorType === 'bullets' && slideItems.length">
class="indicator-bullets"
v-if="indicatorType === 'bullets' && slideItems.length"
>
<div <div
class="bullet" class="bullet"
:class="{ active: currentSlideItemIndex === item - 1 }" :class="{ active: currentSlideItemIndex === item - 1 }"
@@ -25,413 +22,389 @@
</template> </template>
<script> <script>
import bus from '../../utils/bus' import bus from '../../utils/bus'
import Loading from '../Loading' import Loading from '../Loading'
import { useBaseStore } from '@/store/pinia' import { useBaseStore } from '@/store/pinia'
export default { export default {
name: 'BaseSlideList', name: 'BaseSlideList',
components: { components: {
Loading, Loading
},
props: {
canMove: {
type: Boolean,
default: () => true
}, },
props: { autoplay: {
canMove: { type: Boolean,
type: Boolean, default: () => false
default: () => true,
},
autoplay: {
type: Boolean,
default: () => false,
},
indicatorType: {
type: String,
default: '',
//bullets
//fraction
//progressbar
//custom
},
useHomeLoading: {
type: Boolean,
default: () => false,
},
activeIndex: {
type: Number,
default: () => 0,
},
name: {
type: String,
default: () => '',
},
}, },
setup() { indicatorType: {
const baseStore = useBaseStore() type: String,
return { baseStore } default: ''
//bullets
//fraction
//progressbar
//custom
}, },
computed: { useHomeLoading: {
isHome() { type: Boolean,
return this.indicatorType === 'home' default: () => false
}, },
toolbarStyle() { activeIndex: {
if (!this.isHome) return type: Number,
default: () => 0
},
name: {
type: String,
default: () => ''
}
},
setup() {
const baseStore = useBaseStore()
return { baseStore }
},
computed: {
isHome() {
return this.indicatorType === 'home'
},
toolbarStyle() {
if (!this.isHome) return
return {
opacity: 1 - this.homeLoadingMoveYDistance / 20,
'transition-duration': this.toolbarStyleTransitionDuration + 'ms',
transform: `translate3d(0, ${this.homeLoadingMoveYDistance > 60 ? 60 : this.homeLoadingMoveYDistance}px, 0)`
}
},
noticeStyle() {
if (!this.isHome) return
return {
opacity: this.homeLoadingMoveYDistance / 60,
'transition-duration': this.toolbarStyleTransitionDuration + 'ms',
transform: `translate3d(0, ${this.homeLoadingMoveYDistance > 60 ? 60 : this.homeLoadingMoveYDistance}px, 0)`
}
},
loadingStyle() {
if (!this.isHome) return
if (this.loading) {
return { return {
opacity: 1 - this.homeLoadingMoveYDistance / 20, opacity: 1,
'transition-duration': this.toolbarStyleTransitionDuration + 'ms', 'transition-duration': '300ms'
transform: `translate3d(0, ${this.homeLoadingMoveYDistance > 60 ? 60 : this.homeLoadingMoveYDistance}px, 0)`,
} }
}, }
noticeStyle() { if (this.homeLoadingMoveYDistance !== 0) {
if (!this.isHome) return
return { return {
opacity: this.homeLoadingMoveYDistance / 60, opacity: this.homeLoadingMoveYDistance / 60,
'transition-duration': this.toolbarStyleTransitionDuration + 'ms', 'transition-duration': this.toolbarStyleTransitionDuration + 'ms',
transform: `translate3d(0, ${this.homeLoadingMoveYDistance > 60 ? 60 : this.homeLoadingMoveYDistance}px, 0)`, transform: `translate3d(0, ${this.homeLoadingMoveYDistance > 60 ? 60 : this.homeLoadingMoveYDistance}px, 0)`
} }
}, }
loadingStyle() { }
if (!this.isHome) return },
if (this.loading) { data() {
return { return {
opacity: 1, loading: false,
'transition-duration': '300ms', wrapperWidth: 0,
}
startLocationX: 0,
startLocationY: 0,
moveXDistance: 0,
moveYDistance: 0,
judgeValue: 10,
startTime: 0,
currentSlideItemIndex: 0,
isDrawRight: true,
isDrawDown: true,
isCanRightWiping: false,
isCanDownWiping: false,
isNeedCheck: true,
slideList: null,
slideItems: [],
indicatorRef: null,
slideItemsWidths: [],
tabIndicatorRelationActiveIndexLefts: [], //指标和slideItem的index的对应left,
indicatorSpace: 0, //indicator之间的间距
toolbarStyleTransitionDuration: 0,
homeLoadingMoveYDistance: 0 //homeLoading专用的MoveYDistance因为MoveYDistance是一直更新的左右划的时候也在更新会造成
//在往左划但上面的toolbar开始往下移了所以需要用一个专用的值来有条件的保存MoveYDistance即只direction = row的时候
}
},
watch: {
activeIndex() {
this.changeIndex()
}
},
mounted: async function () {
await this.checkChildren(true)
this.isHome && this.initTabs()
this.changeIndex(true)
if (this.autoplay) {
setInterval(() => {
if (this.currentSlideItemIndex === this.slideItems.length - 1) {
this.currentSlideItemIndex = 0
} else {
this.currentSlideItemIndex++
} }
if (this.homeLoadingMoveYDistance !== 0) { this.changeIndex(false, this.currentSlideItemIndex)
return { }, 3000)
opacity: this.homeLoadingMoveYDistance / 60, }
'transition-duration': this.toolbarStyleTransitionDuration + 'ms', },
transform: `translate3d(0, ${this.homeLoadingMoveYDistance > 60 ? 60 : this.homeLoadingMoveYDistance}px, 0)`, methods: {
} changeIndex(init = false, index = null) {
} this.currentSlideItemIndex = index !== null ? index : this.activeIndex
}, !init && this.$setCss(this.slideList, 'transition-duration', `300ms`)
this.$setCss(
this.slideList,
'transform',
`translate3d(${-this.getWidth(this.currentSlideItemIndex) + this.moveXDistance}px, 0px, 0px)`
)
if (this.isHome) {
this.$setCss(
this.indicatorRef,
'left',
this.tabIndicatorRelationActiveIndexLefts[this.currentSlideItemIndex] + 'px'
)
}
this.$attrs['onUpdate:activeIndex'] &&
this.$emit('update:active-index', this.currentSlideItemIndex)
}, },
data() { initTabs() {
return { let tabs = this.$refs.tabs
loading: false, this.indicatorRef = this.$refs.indicator
wrapperWidth: 0, for (let i = 0; i < tabs.children.length; i++) {
let item = tabs.children[i]
startLocationX: 0, this.tabWidth = this.$getCss(item, 'width')
startLocationY: 0, //TODO 这里算得不对两个字时正常字一多就会出问题修改参考IndicatorLight.vue
this.tabIndicatorRelationActiveIndexLefts.push(
moveXDistance: 0, item.getBoundingClientRect().x -
moveYDistance: 0, tabs.children[0].getBoundingClientRect().x +
(this.isHome ? this.tabWidth * 0.15 : 0)
judgeValue: 10, )
startTime: 0, }
// console.log(this.lefts)
currentSlideItemIndex: 0, this.indicatorSpace =
isDrawRight: true, this.tabIndicatorRelationActiveIndexLefts[1] - this.tabIndicatorRelationActiveIndexLefts[0]
isDrawDown: true, if (this.isHome) {
isCanRightWiping: false, this.$setCss(this.indicatorRef, 'transition-duration', `300ms`)
isCanDownWiping: false, this.$setCss(
isNeedCheck: true, this.indicatorRef,
'left',
slideList: null, this.tabIndicatorRelationActiveIndexLefts[this.currentSlideItemIndex] + 'px'
slideItems: [], )
indicatorRef: null,
slideItemsWidths: [],
tabIndicatorRelationActiveIndexLefts: [], //指标和slideItem的index的对应left,
indicatorSpace: 0, //indicator之间的间距
toolbarStyleTransitionDuration: 0,
homeLoadingMoveYDistance: 0, //homeLoading专用的MoveYDistance因为MoveYDistance是一直更新的左右划的时候也在更新会造成
//在往左划但上面的toolbar开始往下移了所以需要用一个专用的值来有条件的保存MoveYDistance即只direction = row的时候
} }
}, },
watch: { async checkChildren(init) {
activeIndex() { this.slideList = this.$refs.slideList
this.changeIndex() this.slideItems = this.slideList.children
}, this.wrapperWidth = this.$getCss(this.slideList, 'width')
}, this.wrapperHeight = this.$getCss(this.slideList, 'height')
mounted: async function () { for (let i = 0; i < this.slideItems.length; i++) {
await this.checkChildren(true) let el = this.slideItems[i]
this.isHome && this.initTabs() this.slideItemsWidths.push(this.$getCss(el, 'width'))
this.changeIndex(true)
if (this.autoplay) {
setInterval(() => {
if (this.currentSlideItemIndex === this.slideItems.length - 1) {
this.currentSlideItemIndex = 0
} else {
this.currentSlideItemIndex++
}
this.changeIndex(false, this.currentSlideItemIndex)
}, 3000)
} }
}, },
methods: { touchStart(e) {
changeIndex(init = false, index = null) { this.$setCss(this.slideList, 'transition-duration', `0ms`)
this.currentSlideItemIndex = index !== null ? index : this.activeIndex this.isHome && this.$setCss(this.indicatorRef, 'transition-duration', `0ms`)
!init && this.$setCss(this.slideList, 'transition-duration', `300ms`) this.toolbarStyleTransitionDuration = 0
this.startLocationX = e.touches[0].pageX
this.startLocationY = e.touches[0].pageY
this.startTime = Date.now()
},
touchMove(e) {
// this.$stopPropagation(e)
if (!this.canMove) return
this.moveXDistance = e.touches[0].pageX - this.startLocationX
this.moveYDistance = e.touches[0].pageY - this.startLocationY
this.isDrawRight = this.moveXDistance < 0
this.isDrawDown = this.moveYDistance < 0
this.checkDirection()
//多重判断this.isCanDownWiping 这个判断是为了只能在一个方向上进行页面更新比如说我斜着画就会出现toolbar又在下移
//slideitem同时在左右移的情况所以不能直接使用moveYDistance
if (this.isCanDownWiping && this.isHome && !this.loading) {
this.homeLoadingMoveYDistance = this.moveYDistance > 0 ? this.moveYDistance : 0
}
if (this.isCanRightWiping) {
// //禁止在index=0页面的时候向左划
if (this.currentSlideItemIndex === 0 && !this.isDrawRight) return
//禁止在最后页面的时候,向右划
if (this.currentSlideItemIndex === this.slideItems.length - 1 && this.isDrawRight) return
bus.emit(this.name + '-moved', {
x: { distance: this.moveXDistance, isDrawRight: this.isDrawRight }
})
this.$stopPropagation(e)
this.$setCss( this.$setCss(
this.slideList, this.slideList,
'transform', 'transform',
`translate3d(${-this.getWidth(this.currentSlideItemIndex) + this.moveXDistance}px, 0px, 0px)`, `translate3d(${
-this.getWidth(this.currentSlideItemIndex) +
this.moveXDistance +
(this.isDrawRight ? this.judgeValue : -this.judgeValue)
}px, 0px, 0px)`
)
this.isHome &&
this.$setCss(
this.indicatorRef,
'left',
this.tabIndicatorRelationActiveIndexLefts[this.currentSlideItemIndex] -
this.moveXDistance / (this.baseStore.bodyWidth / this.indicatorSpace) +
'px'
)
}
},
touchEnd(e) {
if (this.isHome) {
if (this.homeLoadingMoveYDistance > 60) {
this.getData()
}
this.toolbarStyleTransitionDuration = 300
this.homeLoadingMoveYDistance = 0
}
if (this.isCanRightWiping) {
if (this.currentSlideItemIndex === 0 && !this.isDrawRight) return
if (this.currentSlideItemIndex === this.slideItems.length - 1 && this.isDrawRight) return
this.$setCss(this.slideList, 'transition-duration', `300ms`)
this.isHome && this.$setCss(this.indicatorRef, 'transition-duration', `300ms`)
let endTime = Date.now()
let gapTime = endTime - this.startTime
//21/06/28 发现一个bug就是会把所有的点击事件给失效了。。。//已解决
// this.$stopPropagation(e)//todo 如果是嵌套竖状的slide会出问题,会到moveYDistance停下不会移到
//this.getWidth(this.currentSlideItemIndex)位置,但是不禁示冒泡的话,又会出现划动过快,把父级也会移动。
if (this.moveXDistance !== 0) {
this.$stopPropagation(e)
}
if (Math.abs(this.moveXDistance) < 20) gapTime = 1000
if (Math.abs(this.moveXDistance) > this.wrapperWidth / 3) gapTime = 100
if (gapTime < 150) {
if (this.isDrawRight) {
this.currentSlideItemIndex += 1
} else {
this.currentSlideItemIndex -= 1
}
}
this.$setCss(
this.slideList,
'transform',
`translate3d(${-this.getWidth(this.currentSlideItemIndex)}px, 0px, 0px)`
) )
if (this.isHome) { if (this.isHome) {
this.$setCss( this.$setCss(
this.indicatorRef, this.indicatorRef,
'left', 'left',
this.tabIndicatorRelationActiveIndexLefts[ this.tabIndicatorRelationActiveIndexLefts[this.currentSlideItemIndex] + 'px'
this.currentSlideItemIndex
] + 'px',
) )
} }
this.$attrs['onUpdate:activeIndex'] && }
this.$emit('update:active-index', this.currentSlideItemIndex) this.resetConfig()
}, this.$attrs['onUpdate:activeIndex'] &&
initTabs() { this.$emit('update:active-index', this.currentSlideItemIndex)
let tabs = this.$refs.tabs this.$attrs['onEnd'] && this.$emit('end')
this.indicatorRef = this.$refs.indicator bus.emit(this.name + '-end', this.currentSlideItemIndex)
for (let i = 0; i < tabs.children.length; i++) {
let item = tabs.children[i]
this.tabWidth = this.$getCss(item, 'width')
//TODO 这里算得不对两个字时正常字一多就会出问题修改参考IndicatorLight.vue
this.tabIndicatorRelationActiveIndexLefts.push(
item.getBoundingClientRect().x -
tabs.children[0].getBoundingClientRect().x +
(this.isHome ? this.tabWidth * 0.15 : 0),
)
}
// console.log(this.lefts)
this.indicatorSpace =
this.tabIndicatorRelationActiveIndexLefts[1] -
this.tabIndicatorRelationActiveIndexLefts[0]
if (this.isHome) {
this.$setCss(this.indicatorRef, 'transition-duration', `300ms`)
this.$setCss(
this.indicatorRef,
'left',
this.tabIndicatorRelationActiveIndexLefts[
this.currentSlideItemIndex
] + 'px',
)
}
},
async checkChildren(init) {
this.slideList = this.$refs.slideList
this.slideItems = this.slideList.children
this.wrapperWidth = this.$getCss(this.slideList, 'width')
this.wrapperHeight = this.$getCss(this.slideList, 'height')
for (let i = 0; i < this.slideItems.length; i++) {
let el = this.slideItems[i]
this.slideItemsWidths.push(this.$getCss(el, 'width'))
}
},
touchStart(e) {
this.$setCss(this.slideList, 'transition-duration', `0ms`)
this.isHome &&
this.$setCss(this.indicatorRef, 'transition-duration', `0ms`)
this.toolbarStyleTransitionDuration = 0
this.startLocationX = e.touches[0].pageX
this.startLocationY = e.touches[0].pageY
this.startTime = Date.now()
},
touchMove(e) {
// this.$stopPropagation(e)
if (!this.canMove) return
this.moveXDistance = e.touches[0].pageX - this.startLocationX
this.moveYDistance = e.touches[0].pageY - this.startLocationY
this.isDrawRight = this.moveXDistance < 0
this.isDrawDown = this.moveYDistance < 0
this.checkDirection()
//多重判断this.isCanDownWiping 这个判断是为了只能在一个方向上进行页面更新比如说我斜着画就会出现toolbar又在下移
//slideitem同时在左右移的情况所以不能直接使用moveYDistance
if (this.isCanDownWiping && this.isHome && !this.loading) {
this.homeLoadingMoveYDistance =
this.moveYDistance > 0 ? this.moveYDistance : 0
}
if (this.isCanRightWiping) {
// //禁止在index=0页面的时候向左划
if (this.currentSlideItemIndex === 0 && !this.isDrawRight) return
//禁止在最后页面的时候,向右划
if (
this.currentSlideItemIndex === this.slideItems.length - 1 &&
this.isDrawRight
)
return
bus.emit(this.name + '-moved', {
x: { distance: this.moveXDistance, isDrawRight: this.isDrawRight },
})
this.$stopPropagation(e)
this.$setCss(
this.slideList,
'transform',
`translate3d(${
-this.getWidth(this.currentSlideItemIndex) +
this.moveXDistance +
(this.isDrawRight ? this.judgeValue : -this.judgeValue)
}px, 0px, 0px)`,
)
this.isHome &&
this.$setCss(
this.indicatorRef,
'left',
this.tabIndicatorRelationActiveIndexLefts[
this.currentSlideItemIndex
] -
this.moveXDistance /
(this.baseStore.bodyWidth / this.indicatorSpace) +
'px',
)
}
},
touchEnd(e) {
if (this.isHome) {
if (this.homeLoadingMoveYDistance > 60) {
this.getData()
}
this.toolbarStyleTransitionDuration = 300
this.homeLoadingMoveYDistance = 0
}
if (this.isCanRightWiping) {
if (this.currentSlideItemIndex === 0 && !this.isDrawRight) return
if (
this.currentSlideItemIndex === this.slideItems.length - 1 &&
this.isDrawRight
)
return
this.$setCss(this.slideList, 'transition-duration', `300ms`)
this.isHome &&
this.$setCss(this.indicatorRef, 'transition-duration', `300ms`)
let endTime = Date.now()
let gapTime = endTime - this.startTime
//21/06/28 发现一个bug就是会把所有的点击事件给失效了。。。//已解决
// this.$stopPropagation(e)//todo 如果是嵌套竖状的slide会出问题,会到moveYDistance停下不会移到
//this.getWidth(this.currentSlideItemIndex)位置,但是不禁示冒泡的话,又会出现划动过快,把父级也会移动。
if (this.moveXDistance !== 0) {
this.$stopPropagation(e)
}
if (Math.abs(this.moveXDistance) < 20) gapTime = 1000
if (Math.abs(this.moveXDistance) > this.wrapperWidth / 3)
gapTime = 100
if (gapTime < 150) {
if (this.isDrawRight) {
this.currentSlideItemIndex += 1
} else {
this.currentSlideItemIndex -= 1
}
}
this.$setCss(
this.slideList,
'transform',
`translate3d(${-this.getWidth(this.currentSlideItemIndex)}px, 0px, 0px)`,
)
if (this.isHome) {
this.$setCss(
this.indicatorRef,
'left',
this.tabIndicatorRelationActiveIndexLefts[
this.currentSlideItemIndex
] + 'px',
)
}
}
this.resetConfig()
this.$attrs['onUpdate:activeIndex'] &&
this.$emit('update:active-index', this.currentSlideItemIndex)
this.$attrs['onEnd'] && this.$emit('end')
bus.emit(this.name + '-end', this.currentSlideItemIndex)
},
resetConfig() {
this.isCanRightWiping = false
this.isNeedCheck = true
this.moveXDistance = 0
this.moveYDistance = 0
},
getData() {
this.loading = true
setTimeout(() => {
this.loading = false
}, 1500)
},
getWidth(index) {
return this.slideItemsWidths.reduce((p, c, i) => {
if (i < index) {
//最后一页,如果宽度不够屏幕宽度,那不能拉完
if (this.slideItemsWidths.length - 1 === i + 1) {
p = p + c - (this.wrapperWidth - this.slideItemsWidths[index])
} else {
p += c
}
}
return p
}, 0)
},
checkDirection() {
if (!this.isNeedCheck) return
if (
Math.abs(this.moveXDistance) > this.judgeValue ||
Math.abs(this.moveYDistance) > this.judgeValue
) {
let angle =
(Math.abs(this.moveXDistance) * 10) /
(Math.abs(this.moveYDistance) * 10)
if (angle > 1) {
this.isCanDownWiping = false
this.isCanRightWiping = true
// console.log('横划')
} else {
this.isCanDownWiping = true
this.isCanRightWiping = false
// console.log('竖划')
}
// console.log(angle)
return (this.isNeedCheck = false)
}
return (this.isNeedCheck = true)
},
}, },
resetConfig() {
this.isCanRightWiping = false
this.isNeedCheck = true
this.moveXDistance = 0
this.moveYDistance = 0
},
getData() {
this.loading = true
setTimeout(() => {
this.loading = false
}, 1500)
},
getWidth(index) {
return this.slideItemsWidths.reduce((p, c, i) => {
if (i < index) {
//最后一页,如果宽度不够屏幕宽度,那不能拉完
if (this.slideItemsWidths.length - 1 === i + 1) {
p = p + c - (this.wrapperWidth - this.slideItemsWidths[index])
} else {
p += c
}
}
return p
}, 0)
},
checkDirection() {
if (!this.isNeedCheck) return
if (
Math.abs(this.moveXDistance) > this.judgeValue ||
Math.abs(this.moveYDistance) > this.judgeValue
) {
let angle = (Math.abs(this.moveXDistance) * 10) / (Math.abs(this.moveYDistance) * 10)
if (angle > 1) {
this.isCanDownWiping = false
this.isCanRightWiping = true
// console.log('横划')
} else {
this.isCanDownWiping = true
this.isCanRightWiping = false
// console.log('竖划')
}
// console.log(angle)
return (this.isNeedCheck = false)
}
return (this.isNeedCheck = true)
}
} }
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '../../assets/less/index'; @import '../../assets/less/index';
#base-slide-wrapper { #base-slide-wrapper {
width: 100%; width: 100%;
height: 100%;
overflow: hidden;
position: relative;
#base-slide-list {
display: flex;
height: 100%; height: 100%;
overflow: hidden; width: 100%;
position: relative; position: relative;
}
#base-slide-list { .indicator-bullets {
display: flex; position: absolute;
height: 100%; bottom: 10rem;
width: 100%; z-index: 2;
position: relative; left: 0;
} display: flex;
justify-content: center;
width: 100%;
.indicator-bullets { .bullet {
position: absolute; @width: 5rem;
bottom: 10rem; width: @width;
z-index: 2; height: @width;
left: 0; margin: 0 3rem;
display: flex; border-radius: 50%;
justify-content: center; background: var(--second-btn-color);
width: 100%;
.bullet { &.active {
@width: 5rem; background: white;
width: @width;
height: @width;
margin: 0 3rem;
border-radius: 50%;
background: var(--second-btn-color);
&.active {
background: white;
}
} }
} }
} }
}
</style> </style>

View File

@@ -36,349 +36,346 @@
</div> </div>
</template> </template>
<script> <script>
import Posters from '../Posters' import Posters from '../Posters'
import globalMethods from '../../utils' import globalMethods from '../../utils'
import BaseButton from '../BaseButton' import BaseButton from '../BaseButton'
export default { export default {
name: 'SlideUser', name: 'SlideUser',
components: { components: {
Posters, Posters,
BaseButton, BaseButton
}, },
props: { props: {
modelValue: { modelValue: {
type: Object, type: Object,
default() { default() {
return { return {
type: 'user', type: 'user',
id: '224e9a00-ffa0-4bc1-bb07-c318c7b02fa5', id: '224e9a00-ffa0-4bc1-bb07-c318c7b02fa5',
avatar: new URL( avatar: new URL('../../assets/img/icon/avatar/1.png', import.meta.url).href,
'../../assets/img/icon/avatar/1.png', name: '何以为家',
import.meta.url, realName: '王小二',
).href, sex: '',
name: '何以为家', age: 25,
realName: '王小二', idCard: null,
sex: '', phone: '',
age: 25, address: null,
idCard: null, wechat: '',
phone: '', password: null,
address: null, lastLoginTime: '1629993515',
wechat: '', createTime: '1630035089',
password: null, isDelete: 0,
lastLoginTime: '1629993515', account: '234',
createTime: '1630035089', pinyin: 'H',
isDelete: 0, select: false,
account: '234', videos: [
pinyin: 'H', {
select: false, id: '13b462dd-8d81-4744-93ed-815941f4ed3e',
videos: [ cover:
{ 'http://p6.douyinpic.com/img/tos-cn-p-0015/efebaff8e1df46928522e1ac5583d059~c5_300x400.jpeg?from=4257465056_large',
id: '13b462dd-8d81-4744-93ed-815941f4ed3e', dynamic_cover:
cover: 'http://p29.douyinpic.com/obj/tos-cn-p-0015/efebaff8e1df46928522e1ac5583d059?from=4257465056_large',
'http://p6.douyinpic.com/img/tos-cn-p-0015/efebaff8e1df46928522e1ac5583d059~c5_300x400.jpeg?from=4257465056_large', origin_cover:
dynamic_cover: 'http://p3.douyinpic.com/tos-cn-p-0015/d834cf36d4be462f92206543306ff362_1623571220~tplv-dy-360p.jpeg?from=4257465056&s=&se=false&sh=&sc=&l=2021083114303701021217008258017B39&biz_tag=feed_cover',
'http://p29.douyinpic.com/obj/tos-cn-p-0015/efebaff8e1df46928522e1ac5583d059?from=4257465056_large', video:
origin_cover: 'http://api.amemv.com/aweme/v1/play/?video_id=v0300fg10000c32rloe8vall584jaad0&line=1&file_id=d6daaa72874445f5a71c2a671ec9abd4&sign=62621a8cd9f89bab74fb31daa201e148&is_play_url=1&source=PackSourceEnum_PUBLISH',
'http://p3.douyinpic.com/tos-cn-p-0015/d834cf36d4be462f92206543306ff362_1623571220~tplv-dy-360p.jpeg?from=4257465056&s=&se=false&sh=&sc=&l=2021083114303701021217008258017B39&biz_tag=feed_cover', video_data_size: 8569489,
video: duration: 148612,
'http://api.amemv.com/aweme/v1/play/?video_id=v0300fg10000c32rloe8vall584jaad0&line=1&file_id=d6daaa72874445f5a71c2a671ec9abd4&sign=62621a8cd9f89bab74fb31daa201e148&is_play_url=1&source=PackSourceEnum_PUBLISH', desc: '几分钟看科幻片《徐福》 #我的观影报告 #抖音电影',
video_data_size: 8569489, allow_download: 1,
duration: 148612, allow_duet: 0,
desc: '几分钟看科幻片《徐福》 #我的观影报告 #抖音电影', allow_react: 0,
allow_download: 1, allow_music: 1,
allow_duet: 0, allow_douplus: 1,
allow_react: 0, allow_share: 1,
allow_music: 1, digg_count: 55,
allow_douplus: 1, comment_count: 0,
allow_share: 1, download_count: 0,
digg_count: 55, play_count: 0,
comment_count: 0, share_count: 0,
download_count: 0, forward_count: 0,
play_count: 0, collect_count: 0,
share_count: 0, sort: 24,
forward_count: 0, is_top: 0,
collect_count: 0, city: '350100',
sort: 24, musicId: '286f9f80-d497-4914-a5be-65686916e3fe',
is_top: 0, create_time: '1630391775',
city: '350100', creator_id: '54884802577',
musicId: '286f9f80-d497-4914-a5be-65686916e3fe', status: 1,
create_time: '1630391775', topics: [
creator_id: '54884802577', {
status: 1, id: '41821c6d-e14f-47f1-a391-f0b1f42afbe1',
topics: [ name: '抖音电影',
{
id: '41821c6d-e14f-47f1-a391-f0b1f42afbe1',
name: '抖音电影',
creator_id: '54884802577',
create_time: '1630391758',
status: 1,
},
{
id: 'c10178eb-441f-4dc7-93b6-eaae1b6248cc',
name: '我的观影报告',
creator_id: '54884802577',
create_time: '1630391758',
status: 1,
},
],
music: {
id: '8ce2cb26-4772-4c7b-91d9-a2580c667c21',
cover:
'http://p3.douyinpic.com/aweme/100x100/85f000239e43c3c985b5.jpeg?from=116350172',
mp3: 'http://sf6-cdn-tos.douyinstatic.com/obj/ies-music/6995889105167076132.mp3',
title: '@喵嗷污说电影创作的原声',
creator_id: '54884802577', creator_id: '54884802577',
create_time: '1630391758', create_time: '1630391758',
status: 1, status: 1
}, },
}, {
{ id: 'c10178eb-441f-4dc7-93b6-eaae1b6248cc',
id: '1f6871da-73ab-40cc-9481-37ad83b63bde', name: '我的观影报告',
cover:
'http://p3.douyinpic.com/img/tos-cn-p-0015/ba34a7304d6e44cfb159b838e1a6c980~c5_300x400.jpeg?from=4257465056_large',
dynamic_cover:
'http://p3.douyinpic.com/obj/tos-cn-p-0015/ba34a7304d6e44cfb159b838e1a6c980?from=4257465056_large',
origin_cover:
'http://p26.douyinpic.com/tos-cn-p-0015/25898d01cf9c44c2ae63874546d75640_1623570870~tplv-dy-360p.jpeg?from=4257465056&s=&se=false&sh=&sc=&l=2021083114303701021217008258017B39&biz_tag=feed_cover',
video:
'http://api.amemv.com/aweme/v1/play/?video_id=v0d00fg10000c32rhslhtod769sv81r0&line=1&file_id=b16315d063594519a6b9102905da92a7&sign=eef97e748e50854547d9cd10b29e2ead&is_play_url=1&source=PackSourceEnum_PUBLISH',
video_data_size: 10901859,
duration: 188250,
desc: '科学家为永生改造人类基因,结果创造出能力逆天的新物种完虐人类 #我的观影报告',
allow_download: 1,
allow_duet: 0,
allow_react: 0,
allow_music: 1,
allow_douplus: 1,
allow_share: 1,
digg_count: 24,
comment_count: 0,
download_count: 0,
play_count: 0,
share_count: 0,
forward_count: 0,
collect_count: 0,
sort: 25,
is_top: 0,
city: '350100',
musicId: '5ce6dd54-62eb-46d4-8d71-40b3776bee50',
create_time: '1630391775',
creator_id: '54884802577',
status: 1,
topics: [
{
id: 'c10178eb-441f-4dc7-93b6-eaae1b6248cc',
name: '我的观影报告',
creator_id: '54884802577',
create_time: '1630391758',
status: 1,
},
],
music: {
id: '8ce2cb26-4772-4c7b-91d9-a2580c667c21',
cover:
'http://p3.douyinpic.com/aweme/100x100/85f000239e43c3c985b5.jpeg?from=116350172',
mp3: 'http://sf6-cdn-tos.douyinstatic.com/obj/ies-music/6995889105167076132.mp3',
title: '@喵嗷污说电影创作的原声',
creator_id: '54884802577', creator_id: '54884802577',
create_time: '1630391758', create_time: '1630391758',
status: 1, status: 1
}, }
}, ],
{ music: {
id: 'f7657f21-5fee-4f1f-9d88-ec8411ea009b', id: '8ce2cb26-4772-4c7b-91d9-a2580c667c21',
cover: cover:
'http://p3.douyinpic.com/img/tos-cn-p-0015/ef15ae6839104e80871f521447a97b0a~c5_300x400.jpeg?from=4257465056_large', 'http://p3.douyinpic.com/aweme/100x100/85f000239e43c3c985b5.jpeg?from=116350172',
dynamic_cover: mp3: 'http://sf6-cdn-tos.douyinstatic.com/obj/ies-music/6995889105167076132.mp3',
'http://p11.douyinpic.com/obj/tos-cn-p-0015/ef15ae6839104e80871f521447a97b0a?from=4257465056_large', title: '@喵嗷污说电影创作的原声',
origin_cover:
'http://p5-ipv6.douyinpic.com/tos-cn-p-0015/70f6b5f352d4425e8944c038b932c8fd_1623570188~tplv-dy-360p.jpeg?from=4257465056&s=&se=false&sh=&sc=&l=2021083114303701021217008258017B39&biz_tag=feed_cover',
video:
'http://api.amemv.com/aweme/v1/play/?video_id=v0d00fg10000c32rdevdoca093n6gtn0&line=1&file_id=6bd8e6e959b44d83b5ebbd486134aafc&sign=f592f3089c2a3ddae2042ff85bf9ec6f&is_play_url=1&source=PackSourceEnum_PUBLISH',
video_data_size: 19324714,
duration: 300655,
desc: '科学家为永生改造人类基因,结果创造出能力逆天的新物种完虐人类 #我的观影报告',
allow_download: 0,
allow_duet: 0,
allow_react: 0,
allow_music: 1,
allow_douplus: 1,
allow_share: 1,
digg_count: 19,
comment_count: 1,
download_count: 0,
play_count: 0,
share_count: 0,
forward_count: 0,
collect_count: 0,
sort: 26,
is_top: 0,
city: '350100',
musicId: '8170be64-2950-425d-aa7f-b8b6100ed51b',
create_time: '1630391775',
creator_id: '54884802577', creator_id: '54884802577',
status: 1, create_time: '1630391758',
topics: [ status: 1
{ }
id: 'c10178eb-441f-4dc7-93b6-eaae1b6248cc', },
name: '我的观影报告', {
creator_id: '54884802577', id: '1f6871da-73ab-40cc-9481-37ad83b63bde',
create_time: '1630391758', cover:
status: 1, 'http://p3.douyinpic.com/img/tos-cn-p-0015/ba34a7304d6e44cfb159b838e1a6c980~c5_300x400.jpeg?from=4257465056_large',
}, dynamic_cover:
], 'http://p3.douyinpic.com/obj/tos-cn-p-0015/ba34a7304d6e44cfb159b838e1a6c980?from=4257465056_large',
music: { origin_cover:
id: '8ce2cb26-4772-4c7b-91d9-a2580c667c21', 'http://p26.douyinpic.com/tos-cn-p-0015/25898d01cf9c44c2ae63874546d75640_1623570870~tplv-dy-360p.jpeg?from=4257465056&s=&se=false&sh=&sc=&l=2021083114303701021217008258017B39&biz_tag=feed_cover',
cover: video:
'http://p3.douyinpic.com/aweme/100x100/85f000239e43c3c985b5.jpeg?from=116350172', 'http://api.amemv.com/aweme/v1/play/?video_id=v0d00fg10000c32rhslhtod769sv81r0&line=1&file_id=b16315d063594519a6b9102905da92a7&sign=eef97e748e50854547d9cd10b29e2ead&is_play_url=1&source=PackSourceEnum_PUBLISH',
mp3: 'http://sf6-cdn-tos.douyinstatic.com/obj/ies-music/6995889105167076132.mp3', video_data_size: 10901859,
title: '@喵嗷污说电影创作的原声', duration: 188250,
desc: '科学家为永生改造人类基因,结果创造出能力逆天的新物种完虐人类 #我的观影报告',
allow_download: 1,
allow_duet: 0,
allow_react: 0,
allow_music: 1,
allow_douplus: 1,
allow_share: 1,
digg_count: 24,
comment_count: 0,
download_count: 0,
play_count: 0,
share_count: 0,
forward_count: 0,
collect_count: 0,
sort: 25,
is_top: 0,
city: '350100',
musicId: '5ce6dd54-62eb-46d4-8d71-40b3776bee50',
create_time: '1630391775',
creator_id: '54884802577',
status: 1,
topics: [
{
id: 'c10178eb-441f-4dc7-93b6-eaae1b6248cc',
name: '我的观影报告',
creator_id: '54884802577', creator_id: '54884802577',
create_time: '1630391758', create_time: '1630391758',
status: 1, status: 1
}, }
}, ],
], music: {
} id: '8ce2cb26-4772-4c7b-91d9-a2580c667c21',
}, cover:
}, 'http://p3.douyinpic.com/aweme/100x100/85f000239e43c3c985b5.jpeg?from=116350172',
}, mp3: 'http://sf6-cdn-tos.douyinstatic.com/obj/ies-music/6995889105167076132.mp3',
data() { title: '@喵嗷污说电影创作的原声',
return { creator_id: '54884802577',
globalMethods, create_time: '1630391758',
status: 1
}
},
{
id: 'f7657f21-5fee-4f1f-9d88-ec8411ea009b',
cover:
'http://p3.douyinpic.com/img/tos-cn-p-0015/ef15ae6839104e80871f521447a97b0a~c5_300x400.jpeg?from=4257465056_large',
dynamic_cover:
'http://p11.douyinpic.com/obj/tos-cn-p-0015/ef15ae6839104e80871f521447a97b0a?from=4257465056_large',
origin_cover:
'http://p5-ipv6.douyinpic.com/tos-cn-p-0015/70f6b5f352d4425e8944c038b932c8fd_1623570188~tplv-dy-360p.jpeg?from=4257465056&s=&se=false&sh=&sc=&l=2021083114303701021217008258017B39&biz_tag=feed_cover',
video:
'http://api.amemv.com/aweme/v1/play/?video_id=v0d00fg10000c32rdevdoca093n6gtn0&line=1&file_id=6bd8e6e959b44d83b5ebbd486134aafc&sign=f592f3089c2a3ddae2042ff85bf9ec6f&is_play_url=1&source=PackSourceEnum_PUBLISH',
video_data_size: 19324714,
duration: 300655,
desc: '科学家为永生改造人类基因,结果创造出能力逆天的新物种完虐人类 #我的观影报告',
allow_download: 0,
allow_duet: 0,
allow_react: 0,
allow_music: 1,
allow_douplus: 1,
allow_share: 1,
digg_count: 19,
comment_count: 1,
download_count: 0,
play_count: 0,
share_count: 0,
forward_count: 0,
collect_count: 0,
sort: 26,
is_top: 0,
city: '350100',
musicId: '8170be64-2950-425d-aa7f-b8b6100ed51b',
create_time: '1630391775',
creator_id: '54884802577',
status: 1,
topics: [
{
id: 'c10178eb-441f-4dc7-93b6-eaae1b6248cc',
name: '我的观影报告',
creator_id: '54884802577',
create_time: '1630391758',
status: 1
}
],
music: {
id: '8ce2cb26-4772-4c7b-91d9-a2580c667c21',
cover:
'http://p3.douyinpic.com/aweme/100x100/85f000239e43c3c985b5.jpeg?from=116350172',
mp3: 'http://sf6-cdn-tos.douyinstatic.com/obj/ies-music/6995889105167076132.mp3',
title: '@喵嗷污说电影创作的原声',
creator_id: '54884802577',
create_time: '1630391758',
status: 1
}
}
]
}
} }
}, }
computed: {}, },
watch: {}, data() {
created() { return {
console.log('modelValue', this.modelValue) globalMethods
}, }
methods: {}, },
} computed: {},
watch: {},
created() {
console.log('modelValue', this.modelValue)
},
methods: {}
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@p: 15rem; @p: 15rem;
#SlideUser { #SlideUser {
width: 100%;
height: 100%;
//background: #e1e1e1;
background: linear-gradient(to bottom, rgb(49, 75, 98), rgb(65, 48, 40));
display: flex;
align-items: center;
justify-content: center;
position: relative;
padding: 0 @p;
box-sizing: border-box;
.content {
width: 100%; width: 100%;
height: 100%; background: linear-gradient(to bottom, rgb(71, 90, 110), rgb(97, 84, 75));
//background: #e1e1e1;
background: linear-gradient(to bottom, rgb(49, 75, 98), rgb(65, 48, 40));
display: flex; display: flex;
flex-direction: column;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
border-radius: 15rem;
//box-shadow: 0 0 2rem 0 #b3b3b3;
padding: 15rem;
color: black;
position: relative; position: relative;
padding: 0 @p;
box-sizing: border-box;
.content { .close {
width: 100%; top: 15rem;
background: linear-gradient(to bottom, rgb(71, 90, 110), rgb(97, 84, 75)); right: 15rem;
width: 25rem;
height: 25rem;
position: absolute;
}
.avatar {
width: 120rem;
border-radius: 50%;
}
.name {
margin-top: 20rem;
margin-bottom: 20rem;
font-size: 20rem;
letter-spacing: 4rem;
color: white;
}
.desc {
display: flex; display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
border-radius: 15rem;
//box-shadow: 0 0 2rem 0 #b3b3b3;
padding: 15rem;
color: black;
position: relative;
.close { .tag {
top: 15rem; margin: 0 3rem;
right: 15rem; font-size: 10rem;
width: 25rem; background: rgba(161, 158, 156, 0.3);
height: 25rem;
position: absolute;
}
.avatar {
width: 120rem;
border-radius: 50%;
}
.name {
margin-top: 20rem;
margin-bottom: 20rem;
font-size: 20rem;
letter-spacing: 4rem;
color: white;
}
.desc {
display: flex;
.tag {
margin: 0 3rem;
font-size: 10rem;
background: rgba(161, 158, 156, 0.3);
color: gainsboro;
padding: 3rem 5rem;
border-radius: 4rem;
}
}
.realName {
text-align: center;
color: gainsboro; color: gainsboro;
border-top: 1px solid #5e5a5a; padding: 3rem 5rem;
border-bottom: 1px solid #5e5a5a; border-radius: 4rem;
padding: 10rem 0;
margin: 15rem 0;
font-size: 14rem;
letter-spacing: 1.5rem;
width: 90%;
}
.poster-wrapper {
display: grid;
grid-template-columns: repeat(3, 31%);
grid-column-gap: 3.5%;
grid-row-gap: 2%;
}
.poster-item {
border-radius: 8rem;
overflow: hidden;
position: relative;
.poster {
width: 100%;
height: 100%;
display: block;
}
.num {
color: white;
position: absolute;
bottom: 5rem;
left: 5rem;
display: flex;
align-items: center;
font-size: 12rem;
.love {
width: 12rem;
height: 12rem;
margin-right: 5rem;
}
}
} }
} }
.options { .realName {
position: absolute; text-align: center;
bottom: 20rem; color: gainsboro;
display: flex; border-top: 1px solid #5e5a5a;
justify-content: space-between; border-bottom: 1px solid #5e5a5a;
left: @p; padding: 10rem 0;
right: @p; margin: 15rem 0;
font-size: 14rem;
letter-spacing: 1.5rem;
width: 90%;
}
.button { .poster-wrapper {
width: 48%; display: grid;
grid-template-columns: repeat(3, 31%);
grid-column-gap: 3.5%;
grid-row-gap: 2%;
}
.poster-item {
border-radius: 8rem;
overflow: hidden;
position: relative;
.poster {
width: 100%;
height: 100%;
display: block;
}
.num {
color: white;
position: absolute;
bottom: 5rem;
left: 5rem;
display: flex;
align-items: center;
font-size: 12rem;
.love {
width: 12rem;
height: 12rem;
margin-right: 5rem;
}
} }
} }
} }
.options {
position: absolute;
bottom: 20rem;
display: flex;
justify-content: space-between;
left: @p;
right: @p;
.button {
width: 48%;
}
}
}
</style> </style>

View File

@@ -1,91 +1,83 @@
<script setup> <script setup>
import { onMounted, reactive, ref, watch } from 'vue' import { onMounted, reactive, ref, watch } from 'vue'
import GM from '../../utils' import GM from '../../utils'
import { import {
getSlideDistance, getSlideDistance,
slideInit, slideInit,
slideReset, slideReset,
slideTouchEnd, slideTouchEnd,
slideTouchMove, slideTouchMove,
slideTouchStart, slideTouchStart
} from './common' } from './common'
import { SlideType } from '@/utils/const_var' import { SlideType } from '@/utils/const_var'
const props = defineProps({ const props = defineProps({
index: { index: {
type: Number, type: Number,
default: () => { default: () => {
return 0 return 0
}, }
}, },
//改变index是否使用动画 //改变index是否使用动画
changeActiveIndexUseAnim: { changeActiveIndexUseAnim: {
type: Boolean, type: Boolean,
default: true, default: true
}, }
}) })
const emit = defineEmits(['update:index']) const emit = defineEmits(['update:index'])
const judgeValue = 20 const judgeValue = 20
const wrapperEl = ref(null) const wrapperEl = ref(null)
const state = reactive({ const state = reactive({
name: 'SlideVertical', name: 'SlideVertical',
localIndex: props.index, localIndex: props.index,
needCheck: true, needCheck: true,
next: false, next: false,
start: { x: 0, y: 0, time: 0 }, start: { x: 0, y: 0, time: 0 },
move: { x: 0, y: 0 }, move: { x: 0, y: 0 },
wrapper: { width: 0, height: 0, childrenLength: 0 }, wrapper: { width: 0, height: 0, childrenLength: 0 }
}) })
watch( watch(
() => props.index, () => props.index,
(newVal) => { (newVal) => {
if (state.localIndex !== newVal) { if (state.localIndex !== newVal) {
state.localIndex = newVal state.localIndex = newVal
if (props.changeActiveIndexUseAnim) { if (props.changeActiveIndexUseAnim) {
GM.$setCss(wrapperEl.value, 'transition-duration', `300ms`) GM.$setCss(wrapperEl.value, 'transition-duration', `300ms`)
}
GM.$setCss(
wrapperEl.value,
'transform',
`translate3d(0,${getSlideDistance(state, SlideType.VERTICAL)}px, 0)`,
)
} }
}, GM.$setCss(
wrapperEl.value,
'transform',
`translate3d(0,${getSlideDistance(state, SlideType.VERTICAL)}px, 0)`
)
}
}
)
onMounted(() => {
slideInit(wrapperEl.value, state, SlideType.VERTICAL)
})
function touchStart(e) {
slideTouchStart(e, wrapperEl.value, state)
}
function touchMove(e) {
slideTouchMove(e, wrapperEl.value, state, judgeValue, canNext, null, SlideType.VERTICAL)
}
function touchEnd(e) {
slideTouchEnd(e, state, canNext, null, null, SlideType.VERTICAL)
slideReset(wrapperEl.value, state, SlideType.VERTICAL, emit)
}
function canNext(isNext) {
return !(
(state.localIndex === 0 && !isNext) ||
(state.localIndex === state.wrapper.childrenLength - 1 && isNext)
) )
}
onMounted(() => {
slideInit(wrapperEl.value, state, SlideType.VERTICAL)
})
function touchStart(e) {
slideTouchStart(e, wrapperEl.value, state)
}
function touchMove(e) {
slideTouchMove(
e,
wrapperEl.value,
state,
judgeValue,
canNext,
null,
SlideType.VERTICAL,
)
}
function touchEnd(e) {
slideTouchEnd(e, state, canNext, null, null, SlideType.VERTICAL)
slideReset(wrapperEl.value, state, SlideType.VERTICAL, emit)
}
function canNext(isNext) {
return !(
(state.localIndex === 0 && !isNext) ||
(state.localIndex === state.wrapper.childrenLength - 1 && isNext)
)
}
</script> </script>
<template> <template>

View File

@@ -1,383 +1,337 @@
<script setup lang="jsx"> <script setup lang="jsx">
import { createApp, onMounted, reactive, ref, render, watch } from 'vue' import { createApp, onMounted, reactive, ref, render, watch } from 'vue'
import GM from '../../utils' import GM from '../../utils'
import { import {
getSlideDistance, getSlideDistance,
slideInit, slideInit,
slideReset, slideReset,
slideTouchEnd, slideTouchEnd,
slideTouchMove, slideTouchMove,
slideTouchStart, slideTouchStart
} from './common' } from './common'
import { SlideType } from '@/utils/const_var' import { SlideType } from '@/utils/const_var'
import SlideItem from '@/components/slide/SlideItem.vue' import SlideItem from '@/components/slide/SlideItem.vue'
import bus, { EVENT_KEY } from '../../utils/bus' import bus, { EVENT_KEY } from '../../utils/bus'
import Loading from '@/components/Loading.vue' import Loading from '@/components/Loading.vue'
import { useBaseStore } from '@/store/pinia' import { useBaseStore } from '@/store/pinia'
const props = defineProps({ const props = defineProps({
index: { index: {
type: Number, type: Number,
default: () => { default: () => {
return -1 return -1
}, }
}, },
render: { render: {
type: Function, type: Function,
default: () => { default: () => {
return null return null
}, }
}, },
list: { list: {
type: Array, type: Array,
default: () => { default: () => {
return [] return []
}, }
}, },
virtualTotal: { virtualTotal: {
type: Number, type: Number,
default: () => 5, default: () => 5
}, },
name: { name: {
type: String, type: String,
default: () => '', default: () => ''
}, },
uniqueId: { uniqueId: {
type: String, type: String,
default: () => '', default: () => ''
}, },
loading: { loading: {
type: Boolean, type: Boolean,
default: () => false, default: () => false
}, },
active: { active: {
type: Boolean, type: Boolean,
default: () => false, default: () => false
}, }
}) })
const emit = defineEmits(['update:index', 'loadMore', 'refresh']) const emit = defineEmits(['update:index', 'loadMore', 'refresh'])
const appInsMap = new Map() const appInsMap = new Map()
const itemClassName = 'slide-item' const itemClassName = 'slide-item'
const wrapperEl = ref(null) const wrapperEl = ref(null)
const state = reactive({ const state = reactive({
name: props.name, name: props.name,
localIndex: props.index, localIndex: props.index,
needCheck: true, needCheck: true,
next: false, next: false,
start: { x: 0, y: 0, time: 0 }, start: { x: 0, y: 0, time: 0 },
move: { x: 0, y: 0 }, move: { x: 0, y: 0 },
wrapper: { width: 0, height: 0, childrenLength: 0 }, wrapper: { width: 0, height: 0, childrenLength: 0 }
}) })
const baseStore = useBaseStore() const baseStore = useBaseStore()
watch( watch(
() => props.list, () => props.list,
(newVal, oldVal) => { (newVal, oldVal) => {
// console.log('watch-list', newVal.length, oldVal.length, newVal) // console.log('watch-list', newVal.length, oldVal.length, newVal)
//新数据比老数据小,是刷新 //新数据比老数据小,是刷新
if (newVal.length < oldVal.length) { if (newVal.length < oldVal.length) {
insertContent()
} else {
if (oldVal.length === 0) {
insertContent() insertContent()
} else { } else {
if (oldVal.length === 0) { let lastSlideItem = $(wrapperEl.value).find(`.${itemClassName}:last`)
insertContent() let top = lastSlideItem.css('top')
} else { let lastIndex = Number(lastSlideItem.attr('data-index')) + 1
let lastSlideItem = $(wrapperEl.value).find(`.${itemClassName}:last`) console.log('lastIndex', lastIndex)
let top = lastSlideItem.css('top') newVal.slice(lastIndex, lastIndex + 3).map((item, index) => {
let lastIndex = Number(lastSlideItem.attr('data-index')) + 1 let el = getInsEl(item, lastIndex + index)
console.log('lastIndex', lastIndex) //这里必须要设置个top值不然会把前面的条目给覆盖掉
newVal.slice(lastIndex, lastIndex + 3).map((item, index) => { //2022-3-27这里不用计算直接用已用slide-item最后一条的top值
let el = getInsEl(item, lastIndex + index) //因为有一条情况当滑动最后一条和二条的时候top值不会继续加。此时新增的数据如果还
//这里必须要设置个top值不然会把前面的条目给覆盖掉 // 计算top值的会和前面的对不上
//2022-3-27这里不用计算直接用已用slide-item最后一条的top值 $(el).css('top', top)
//因为有一条情况当滑动最后一条和二条的时候top值不会继续加。此时新增的数据如果还 wrapperEl.value.appendChild(el)
// 计算top值的会和前面的对不上 state.wrapper.childrenLength++
$(el).css('top', top)
wrapperEl.value.appendChild(el)
state.wrapper.childrenLength++
})
}
}
},
)
watch(
() => props.index,
(newVal, oldVal) => {
state.localIndex = newVal
// console.log('watch-index', newVal, oldVal)
if (!props.list.length) return
bus.emit(EVENT_KEY.CURRENT_ITEM, props.list[newVal])
bus.emit(EVENT_KEY.SINGLE_CLICK_BROADCAST, {
uniqueId: props.uniqueId,
index: newVal,
type: EVENT_KEY.ITEM_PLAY,
})
setTimeout(() => {
bus.emit(EVENT_KEY.SINGLE_CLICK_BROADCAST, {
uniqueId: props.uniqueId,
index: oldVal,
type: EVENT_KEY.ITEM_STOP,
}) })
}, 200)
},
)
watch(
() => props.active,
(newVal, oldVal) => {
if (newVal && !props.list.length) {
return emit('refresh')
} }
// console.log('active', 'newVal', newVal, 'oldVal', oldVal)
if (newVal) {
bus.emit(EVENT_KEY.CURRENT_ITEM, props.list[state.localIndex])
}
bus.emit(EVENT_KEY.SINGLE_CLICK_BROADCAST, {
uniqueId: props.uniqueId,
index: state.localIndex,
type: newVal === false ? EVENT_KEY.ITEM_STOP : EVENT_KEY.ITEM_PLAY,
})
},
{ immediate: true },
)
onMounted(() => {
slideInit(wrapperEl.value, state, SlideType.VERTICAL)
insertContent()
})
function insertContent(list = props.list) {
if (!list.length) return
$(wrapperEl.value).empty()
let half = (props.virtualTotal - 1) / 2
let start = 0
if (state.localIndex >= half) {
start = state.localIndex - half
} }
let end = start + props.virtualTotal }
if (end >= list.length) { )
end = list.length
start = end - props.virtualTotal watch(
} () => props.index,
if (start < 0) start = 0 (newVal, oldVal) => {
// console.log('start', start, end) state.localIndex = newVal
list.slice(start, end).map((item, index) => { // console.log('watch-index', newVal, oldVal)
//自动播放当前条可能是0可能是其他试了下用jq来找元素然后trigger play事件要慢点样 if (!props.list.length) return
let el = getInsEl(item, start + index, start + index === state.localIndex) bus.emit(EVENT_KEY.CURRENT_ITEM, props.list[newVal])
wrapperEl.value.appendChild(el) bus.emit(EVENT_KEY.SINGLE_CLICK_BROADCAST, {
uniqueId: props.uniqueId,
index: newVal,
type: EVENT_KEY.ITEM_PLAY
}) })
GM.$setCss( setTimeout(() => {
wrapperEl.value, bus.emit(EVENT_KEY.SINGLE_CLICK_BROADCAST, {
'transform', uniqueId: props.uniqueId,
`translate3d(0px,${getSlideDistance(state, SlideType.VERTICAL)}px, 0px)`, index: oldVal,
) type: EVENT_KEY.ITEM_STOP
})
}, 200)
}
)
if (state.localIndex > 2 && list.length > 5) { watch(
$(wrapperEl.value) () => props.active,
.find(`.${itemClassName}`) (newVal, oldVal) => {
.each(function () { if (newVal && !props.list.length) {
if (list.length - state.localIndex > 2) { return emit('refresh')
$(this).css('top', (state.localIndex - 2) * state.wrapper.height) }
} else { // console.log('active', 'newVal', newVal, 'oldVal', oldVal)
$(this).css('top', start * state.wrapper.height) if (newVal) {
bus.emit(EVENT_KEY.CURRENT_ITEM, props.list[state.localIndex])
}
bus.emit(EVENT_KEY.SINGLE_CLICK_BROADCAST, {
uniqueId: props.uniqueId,
index: state.localIndex,
type: newVal === false ? EVENT_KEY.ITEM_STOP : EVENT_KEY.ITEM_PLAY
})
},
{ immediate: true }
)
onMounted(() => {
slideInit(wrapperEl.value, state, SlideType.VERTICAL)
insertContent()
})
function insertContent(list = props.list) {
if (!list.length) return
$(wrapperEl.value).empty()
let half = (props.virtualTotal - 1) / 2
let start = 0
if (state.localIndex >= half) {
start = state.localIndex - half
}
let end = start + props.virtualTotal
if (end >= list.length) {
end = list.length
start = end - props.virtualTotal
}
if (start < 0) start = 0
// console.log('start', start, end)
list.slice(start, end).map((item, index) => {
//自动播放当前条可能是0可能是其他试了下用jq来找元素然后trigger play事件要慢点样
let el = getInsEl(item, start + index, start + index === state.localIndex)
wrapperEl.value.appendChild(el)
})
GM.$setCss(
wrapperEl.value,
'transform',
`translate3d(0px,${getSlideDistance(state, SlideType.VERTICAL)}px, 0px)`
)
if (state.localIndex > 2 && list.length > 5) {
$(wrapperEl.value)
.find(`.${itemClassName}`)
.each(function () {
if (list.length - state.localIndex > 2) {
$(this).css('top', (state.localIndex - 2) * state.wrapper.height)
} else {
$(this).css('top', start * state.wrapper.height)
}
})
}
state.wrapper.childrenLength = wrapperEl.value.children.length
// console.log('list[state.localIndex]',list[state.localIndex])
bus.emit(EVENT_KEY.CURRENT_ITEM, list[state.localIndex])
}
function dislike(item) {
let currentItem = $(wrapperEl.value).find(`.${itemClassName}[data-index=${state.localIndex}]`)
let replaceItem = getInsEl(item, state.localIndex, true)
$(replaceItem).css('top', currentItem.css('top'))
currentItem.replaceWith(replaceItem)
}
defineExpose({ dislike })
function getInsEl(item, index, play = false) {
// console.log('index', cloneDeep(item), index, play)
let slideVNode = props.render(item, index, play, props.uniqueId)
const parent = document.createElement('div')
//TODO 打包到线上时用这个,这个在开发时任何修改都会刷新页面
if (import.meta.env.PROD) {
parent.classList.add('slide-item')
parent.setAttribute('data-index', index)
render(slideVNode, parent)
appInsMap.set(index, {
unmount: () => {
render(null, parent)
parent.remove()
}
})
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
}
}
function touchStart(e) {
slideTouchStart(e, wrapperEl.value, state)
}
//TODO 2022-3-28:在最顶部,反复滑动会抖动一下,初步猜测是因为方向变了,导致的加判断距离变成了减
function touchMove(e) {
slideTouchMove(e, wrapperEl.value, state, baseStore.judgeValue, canNext, null, SlideType.VERTICAL)
}
function touchEnd(e) {
let isNext = state.move.y < 0
if (
state.localIndex === 0 &&
!isNext &&
state.move.y > baseStore.homeRefresh + baseStore.judgeValue
) {
emit('refresh')
}
slideTouchEnd(
e,
state,
canNext,
(isNext) => {
let half = (props.virtualTotal + 1) / 2
if (props.list.length > props.virtualTotal) {
if (isNext) {
if (
state.localIndex > props.list.length - props.virtualTotal &&
state.localIndex >= half
) {
emit('loadMore')
} }
}) let addItemIndex = state.localIndex + 2
} let res = $(wrapperEl.value).find(`.${itemClassName}[data-index=${addItemIndex}]`)
state.wrapper.childrenLength = wrapperEl.value.children.length if (state.wrapper.childrenLength < props.virtualTotal) {
// console.log('list[state.localIndex]',list[state.localIndex]) if (res.length === 0) {
bus.emit(EVENT_KEY.CURRENT_ITEM, list[state.localIndex]) wrapperEl.value.appendChild(getInsEl(props.list[addItemIndex], addItemIndex))
}
function dislike(item) {
let currentItem = $(wrapperEl.value).find(
`.${itemClassName}[data-index=${state.localIndex}]`,
)
let replaceItem = getInsEl(item, state.localIndex, true)
$(replaceItem).css('top', currentItem.css('top'))
currentItem.replaceWith(replaceItem)
}
defineExpose({ dislike })
function getInsEl(item, index, play = false) {
// console.log('index', cloneDeep(item), index, play)
let slideVNode = props.render(item, index, play, props.uniqueId)
const parent = document.createElement('div')
//TODO 打包到线上时用这个,这个在开发时任何修改都会刷新页面
if (import.meta.env.PROD) {
parent.classList.add('slide-item')
parent.setAttribute('data-index', index)
render(slideVNode, parent)
appInsMap.set(index, {
unmount: () => {
render(null, parent)
parent.remove()
},
})
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
}
}
function touchStart(e) {
slideTouchStart(e, wrapperEl.value, state)
}
//TODO 2022-3-28:在最顶部,反复滑动会抖动一下,初步猜测是因为方向变了,导致的加判断距离变成了减
function touchMove(e) {
slideTouchMove(
e,
wrapperEl.value,
state,
baseStore.judgeValue,
canNext,
null,
SlideType.VERTICAL,
)
}
function touchEnd(e) {
let isNext = state.move.y < 0
if (
state.localIndex === 0 &&
!isNext &&
state.move.y > baseStore.homeRefresh + baseStore.judgeValue
) {
emit('refresh')
}
slideTouchEnd(
e,
state,
canNext,
(isNext) => {
let half = (props.virtualTotal + 1) / 2
if (props.list.length > props.virtualTotal) {
if (isNext) {
if (
state.localIndex > props.list.length - props.virtualTotal &&
state.localIndex >= half
) {
emit('loadMore')
} }
let addItemIndex = state.localIndex + 2 }
let res = $(wrapperEl.value).find( if (
`.${itemClassName}[data-index=${addItemIndex}]`, state.wrapper.childrenLength === props.virtualTotal &&
) state.localIndex >= (props.virtualTotal + 1) / 2 &&
if (state.wrapper.childrenLength < props.virtualTotal) { state.localIndex <= props.list.length - 3
if (res.length === 0) { ) {
wrapperEl.value.appendChild( if (res.length === 0) {
getInsEl(props.list[addItemIndex], addItemIndex), wrapperEl.value.appendChild(getInsEl(props.list[addItemIndex], addItemIndex))
) appInsMap
} .get($(wrapperEl.value).find(`.${itemClassName}:first`).data('index'))
} .unmount()
if ( // $(wrapperEl.value).find(".base-slide-item:first").remove()
state.wrapper.childrenLength === props.virtualTotal &&
state.localIndex >= (props.virtualTotal + 1) / 2 &&
state.localIndex <= props.list.length - 3
) {
if (res.length === 0) {
wrapperEl.value.appendChild(
getInsEl(props.list[addItemIndex], addItemIndex),
)
appInsMap
.get(
$(wrapperEl.value)
.find(`.${itemClassName}:first`)
.data('index'),
)
.unmount()
// $(wrapperEl.value).find(".base-slide-item:first").remove()
$(wrapperEl.value)
.find(`.${itemClassName}`)
.each(function () {
$(this).css(
'top',
(state.localIndex - 2) * state.wrapper.height,
)
})
}
}
if (state.wrapper.childrenLength > props.virtualTotal) {
$(wrapperEl.value) $(wrapperEl.value)
.find(`.${itemClassName}`) .find(`.${itemClassName}`)
.each(function () { .each(function () {
let index = $(this).data('index') $(this).css('top', (state.localIndex - 2) * state.wrapper.height)
if (index < state.localIndex - 2) {
appInsMap.get(index).unmount()
}
$(this).css(
'top',
(state.localIndex - 2) * state.wrapper.height,
)
}) })
} }
} else { }
let addItemIndex = state.localIndex - 2 if (state.wrapper.childrenLength > props.virtualTotal) {
let res = $(wrapperEl.value).find( $(wrapperEl.value)
`.${itemClassName}[data-index=${addItemIndex}]`, .find(`.${itemClassName}`)
) .each(function () {
let index = $(this).data('index')
if (index < state.localIndex - 2) {
appInsMap.get(index).unmount()
}
$(this).css('top', (state.localIndex - 2) * state.wrapper.height)
})
}
} else {
let addItemIndex = state.localIndex - 2
let res = $(wrapperEl.value).find(`.${itemClassName}[data-index=${addItemIndex}]`)
if ( if (state.localIndex > 1 && state.localIndex <= props.list.length - 4) {
state.localIndex > 1 && if (res.length === 0) {
state.localIndex <= props.list.length - 4 wrapperEl.value.prepend(getInsEl(props.list[addItemIndex], addItemIndex))
) {
if (res.length === 0) {
wrapperEl.value.prepend(
getInsEl(props.list[addItemIndex], addItemIndex),
)
appInsMap
.get(
$(wrapperEl.value)
.find(`.${itemClassName}:last`)
.data('index'),
)
.unmount()
// $(wrapperEl.value).find(".base-slide-item:last").remove()
$(wrapperEl.value)
.find(`.${itemClassName}`)
.each(function () {
$(this).css(
'top',
(state.localIndex - 2) * state.wrapper.height,
)
})
}
}
if (state.wrapper.childrenLength > props.virtualTotal) {
appInsMap appInsMap
.get( .get($(wrapperEl.value).find(`.${itemClassName}:last`).data('index'))
$(wrapperEl.value)
.find(`.${itemClassName}:last`)
.data('index'),
)
.unmount() .unmount()
// $(wrapperEl.value).find(".base-slide-item:last").remove()
$(wrapperEl.value)
.find(`.${itemClassName}`)
.each(function () {
$(this).css('top', (state.localIndex - 2) * state.wrapper.height)
})
} }
} }
state.wrapper.childrenLength = wrapperEl.value.children.length
}
},
null,
SlideType.VERTICAL,
)
slideReset(wrapperEl.value, state, SlideType.VERTICAL, emit)
}
function canNext(isNext) { if (state.wrapper.childrenLength > props.virtualTotal) {
return !( appInsMap.get($(wrapperEl.value).find(`.${itemClassName}:last`).data('index')).unmount()
(state.localIndex === 0 && !isNext) || }
(state.localIndex === props.list.length - 1 && isNext) }
) state.wrapper.childrenLength = wrapperEl.value.children.length
} }
},
null,
SlideType.VERTICAL
)
slideReset(wrapperEl.value, state, SlideType.VERTICAL, emit)
}
function canNext(isNext) {
return !(
(state.localIndex === 0 && !isNext) ||
(state.localIndex === props.list.length - 1 && isNext)
)
}
</script> </script>
<template> <template>

View File

@@ -29,10 +29,7 @@ export function slideTouchStart(e, el, state) {
//检测能否滑动 //检测能否滑动
export function canSlide(state, judgeValue, type = SlideType.HORIZONTAL) { export function canSlide(state, judgeValue, type = SlideType.HORIZONTAL) {
if (state.needCheck) { if (state.needCheck) {
if ( if (Math.abs(state.move.x) > judgeValue || Math.abs(state.move.y) > judgeValue) {
Math.abs(state.move.x) > judgeValue ||
Math.abs(state.move.y) > judgeValue
) {
let angle = (Math.abs(state.move.x) * 10) / (Math.abs(state.move.y) * 10) let angle = (Math.abs(state.move.x) * 10) / (Math.abs(state.move.y) * 10)
state.next = type === SlideType.HORIZONTAL ? angle > 1 : angle <= 1 state.next = type === SlideType.HORIZONTAL ? angle > 1 : angle <= 1
// console.log('angle', angle, state.next) // console.log('angle', angle, state.next)
@@ -56,22 +53,16 @@ export function slideTouchMove(
nextCb, nextCb,
type = SlideType.HORIZONTAL, type = SlideType.HORIZONTAL,
notNextCb, notNextCb,
slideOtherDirectionCb = null, slideOtherDirectionCb = null
) { ) {
state.move.x = e.touches[0].pageX - state.start.x state.move.x = e.touches[0].pageX - state.start.x
state.move.y = e.touches[0].pageY - state.start.y state.move.y = e.touches[0].pageY - state.start.y
let isNext = let isNext = type === SlideType.HORIZONTAL ? state.move.x < 0 : state.move.y < 0
type === SlideType.HORIZONTAL ? state.move.x < 0 : state.move.y < 0
let canSlideRes = canSlide(state, judgeValue, type) let canSlideRes = canSlide(state, judgeValue, type)
if ( if (canSlideRes && state.localIndex === 0 && !isNext && type === SlideType.VERTICAL) {
canSlideRes &&
state.localIndex === 0 &&
!isNext &&
type === SlideType.VERTICAL
) {
bus.emit(state.name + '-moveY', state.move.y) bus.emit(state.name + '-moveY', state.move.y)
} }
@@ -82,8 +73,7 @@ export function slideTouchMove(
bus.emit(state.name + '-moveX', state.move.x) bus.emit(state.name + '-moveX', state.move.x)
} }
Utils.$stopPropagation(e) Utils.$stopPropagation(e)
let t = let t = getSlideDistance(state, type, el) + (isNext ? judgeValue : -judgeValue)
getSlideDistance(state, type, el) + (isNext ? judgeValue : -judgeValue)
let dx1 = 0 let dx1 = 0
let dx2 = 0 let dx2 = 0
if (type === SlideType.HORIZONTAL) { if (type === SlideType.HORIZONTAL) {
@@ -107,7 +97,7 @@ export function slideTouchEnd(
canNextCb, canNextCb,
nextCb, nextCb,
doNotNextCb, doNotNextCb,
type = SlideType.HORIZONTAL, type = SlideType.HORIZONTAL
) { ) {
let isHorizontal = type === SlideType.HORIZONTAL let isHorizontal = type === SlideType.HORIZONTAL
let isNext = isHorizontal ? state.move.x < 0 : state.move.y < 0 let isNext = isHorizontal ? state.move.x < 0 : state.move.y < 0
@@ -146,12 +136,7 @@ export function slideReset(el, state, type, emit) {
dx2 = t dx2 = t
} }
Utils.$setCss(el, 'transform', `translate3d(${dx1}px, ${dx2}px, 0)`) Utils.$setCss(el, 'transform', `translate3d(${dx1}px, ${dx2}px, 0)`)
state.start.x = state.start.x = state.start.y = state.start.time = state.move.x = state.move.y = 0
state.start.y =
state.start.time =
state.move.x =
state.move.y =
0
state.next = false state.next = false
state.needCheck = true state.needCheck = true
emit?.('update:index', state.localIndex) emit?.('update:index', state.localIndex)

View File

@@ -1,12 +1,12 @@
export default { export default {
baseUrl: 'https://dy.ttentau.top/imgs/', baseUrl: 'https://dy.ttentau.top/imgs/',
imgPath: '/imgs/', imgPath: '/imgs/',
filePreview: 'http://192.168.0.103/static/uploads/', filePreview: 'http://192.168.0.103/static/uploads/'
} }
const BASE_URL_MAP = { const BASE_URL_MAP = {
DEV: '', DEV: '',
PROD: '', PROD: '',
UNI: 'https://dy.ttentau.top', UNI: 'https://dy.ttentau.top'
} }
export const BASE_URL = BASE_URL_MAP[import.meta.env.VITE_ENV] export const BASE_URL = BASE_URL_MAP[import.meta.env.VITE_ENV]

View File

@@ -18,12 +18,11 @@ app.config.globalProperties.emitter = emitter
app.config.unwrapInjectedRef = true app.config.unwrapInjectedRef = true
app.provide('mitt', emitter) app.provide('mitt', emitter)
app.mixin(mixin) app.mixin(mixin)
const loadImage = new URL('./assets/img/icon/img-loading.png', import.meta.url) const loadImage = new URL('./assets/img/icon/img-loading.png', import.meta.url).href
.href
app.use(VueLazyload, { app.use(VueLazyload, {
preLoad: 1.3, preLoad: 1.3,
loading: loadImage, loading: loadImage,
attempt: 1, attempt: 1
}) })
app.use(router) app.use(router)
app.use(pinia) app.use(pinia)

View File

@@ -29,23 +29,23 @@ let t = [
type: 'imgs', type: 'imgs',
src: `https://imgapi.cn/bing.php`, src: `https://imgapi.cn/bing.php`,
author: { author: {
unique_id: 1, unique_id: 1
}, }
}, },
{ {
type: 'user', type: 'user',
src: `https://imgapi.cn/bing.php`, src: `https://imgapi.cn/bing.php`,
author: { author: {
unique_id: 2, unique_id: 2
}, }
}, },
{ {
type: 'img', type: 'img',
src: `https://imgapi.cn/bing.php`, src: `https://imgapi.cn/bing.php`,
author: { author: {
unique_id: 3, unique_id: 3
}, }
}, }
] ]
// allRecommendVideos.unshift(...t) // allRecommendVideos.unshift(...t)
// { // {
@@ -74,9 +74,7 @@ async function fetchData() {
} }
v = v.map((w) => { v = v.map((w) => {
w.type = 'recommend-video' w.type = 'recommend-video'
let item = userList.find( let item = userList.find((a) => String(a.uid) === String(w.author_user_id))
(a) => String(a.uid) === String(w.author_user_id),
)
if (item) w.author = item if (item) w.author = item
return w return w
}) })
@@ -89,21 +87,17 @@ async function fetchData() {
export async function startMock() { export async function startMock() {
mock.onGet(/video\/recommended/).reply(async (config) => { mock.onGet(/video\/recommended/).reply(async (config) => {
let page = getPage2(config.params) let page = getPage2(config.params)
console.log( console.log('allRecommendVideos', cloneDeep(allRecommendVideos.length), page)
'allRecommendVideos',
cloneDeep(allRecommendVideos.length),
page,
)
return [ return [
200, 200,
{ {
data: { data: {
total: 844, total: 844,
list: allRecommendVideos.slice(page.offset, page.limit), // list: allRecommendVideos.slice(0, 6), list: allRecommendVideos.slice(page.offset, page.limit) // list: allRecommendVideos.slice(0, 6),
}, },
code: 200, code: 200,
msg: '', msg: ''
}, }
] ]
}) })
@@ -124,7 +118,7 @@ export async function startMock() {
'7295697246132227343', '7295697246132227343',
'7270431418822446370', '7270431418822446370',
'6882368275695586568', '6882368275695586568',
'7000587983069957383', '7000587983069957383'
] ]
let id = config.params.id let id = config.params.id
if (!videoIds.includes(String(id))) { if (!videoIds.includes(String(id))) {
@@ -145,13 +139,11 @@ export async function startMock() {
{ {
data: { data: {
total: 10, total: 10,
list: allRecommendVideos list: allRecommendVideos.slice(100, 110).slice(page.offset, page.limit)
.slice(100, 110)
.slice(page.offset, page.limit),
}, },
code: 200, code: 200,
msg: '', msg: ''
}, }
] ]
}) })
@@ -162,13 +154,11 @@ export async function startMock() {
{ {
data: { data: {
total: 150, total: 150,
list: allRecommendVideos list: allRecommendVideos.slice(200, 350).slice(page.offset, page.limit)
.slice(200, 350)
.slice(page.offset, page.limit),
}, },
code: 200, code: 200,
msg: '', msg: ''
}, }
] ]
}) })
@@ -177,18 +167,14 @@ export async function startMock() {
if (!userVideos.length) { if (!userVideos.length) {
// let r = await fetch(BASE_URL + '/data/user-71158770.json') // 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-8357999.json')
let r = await fetch( let r = await fetch(BASE_URL + '/data/user_video_list/user-12345xiaolaohu.json')
BASE_URL + '/data/user_video_list/user-12345xiaolaohu.json',
)
let list = await r.json() let list = await r.json()
const baseStore = useBaseStore() const baseStore = useBaseStore()
let userList = cloneDeep(baseStore.users) let userList = cloneDeep(baseStore.users)
userVideos = list.map((w) => { userVideos = list.map((w) => {
if (userList.length) { if (userList.length) {
let item = userList.find( let item = userList.find((a) => String(a.uid) === String(w.author_user_id))
(a) => String(a.uid) === String(w.author_user_id),
)
if (item) w.author = item if (item) w.author = item
} }
return w return w
@@ -201,11 +187,11 @@ export async function startMock() {
data: { data: {
pageNo: page.pageNo, pageNo: page.pageNo,
total: userVideos.length, total: userVideos.length,
list: userVideos.slice(page.offset, page.limit), list: userVideos.slice(page.offset, page.limit)
}, },
code: 200, code: 200,
msg: '', msg: ''
}, }
] ]
}) })
@@ -216,13 +202,11 @@ export async function startMock() {
{ {
data: { data: {
total: 150, total: 150,
list: allRecommendVideos list: allRecommendVideos.slice(200, 350).slice(page.offset, page.limit)
.slice(200, 350)
.slice(page.offset, page.limit),
}, },
code: 200, code: 200,
msg: '', msg: ''
}, }
] ]
}) })
@@ -233,16 +217,16 @@ export async function startMock() {
data: { data: {
video: { video: {
total: 50, total: 50,
list: allRecommendVideos.slice(350, 400), list: allRecommendVideos.slice(350, 400)
}, },
music: { music: {
total: resource.music.length, total: resource.music.length,
list: resource.music, list: resource.music
}, }
}, },
code: 200, code: 200,
msg: '', msg: ''
}, }
] ]
}) })
@@ -282,11 +266,11 @@ export async function startMock() {
data: { data: {
pageNo: page.pageNo, pageNo: page.pageNo,
total: 0, total: 0,
list: [], list: []
}, },
code: 200, code: 200,
msg: '', msg: ''
}, }
] ]
}) })
@@ -303,11 +287,11 @@ export async function startMock() {
data: { data: {
pageNo: page.pageNo, pageNo: page.pageNo,
total: allRecommendPosts.length, total: allRecommendPosts.length,
list: allRecommendPosts.slice(0, 1000).slice(page.offset, page.limit), list: allRecommendPosts.slice(0, 1000).slice(page.offset, page.limit)
}, },
code: 200, code: 200,
msg: '', msg: ''
}, }
] ]
}) })
@@ -321,10 +305,10 @@ export async function startMock() {
{ {
data: { data: {
total: v.length, total: v.length,
list: v.slice(page.offset, page.limit), list: v.slice(page.offset, page.limit)
}, },
code: 200, code: 200
}, }
] ]
}) })

View File

@@ -1,7 +1,7 @@
export default { export default {
data() { data() {
return { return {
mainScrollTop: 0, mainScrollTop: 0
} }
}, },
activated() { activated() {
@@ -13,5 +13,5 @@ export default {
if (this.$refs.mainScroll && this.$refs.mainScroll.wrapper) { if (this.$refs.mainScroll && this.$refs.mainScroll.wrapper) {
this.mainScrollTop = this.$refs.mainScroll.wrapper.scrollTop this.mainScrollTop = this.$refs.mainScroll.wrapper.scrollTop
} }
}, }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -23,18 +23,8 @@
@click.stop="toggleCollect()" @click.stop="toggleCollect()"
/> />
</template> </template>
<div <div class="logo" v-if="!isFixed" @click="$nav('/home/music-rank-list')">抖音音乐榜</div>
class="logo" <img class="share" src="../../assets/img/icon/share-white.png" @click="isSharing = true" />
v-if="!isFixed"
@click="$nav('/home/music-rank-list')"
>
抖音音乐榜
</div>
<img
class="share"
src="../../assets/img/icon/share-white.png"
@click="isSharing = true"
/>
</div> </div>
</div> </div>
<div class="content"> <div class="content">
@@ -47,32 +37,17 @@
<div class="desc"> <div class="desc">
<div class="cover-wrapper" @click="togglePlay()"> <div class="cover-wrapper" @click="togglePlay()">
<img class="cover" :src="$imgPreview(music.cover)" alt="" /> <img class="cover" :src="$imgPreview(music.cover)" alt="" />
<img <img v-if="!isPlay" src="../../assets/img/icon/play-white.png" alt="" class="play" />
v-if="!isPlay" <img v-if="isPlay" src="../../assets/img/icon/pause-white.png" alt="" class="play" />
src="../../assets/img/icon/play-white.png"
alt=""
class="play"
/>
<img
v-if="isPlay"
src="../../assets/img/icon/pause-white.png"
alt=""
class="play"
/>
</div> </div>
<div class="info"> <div class="info">
<div class="name">{{ music.name }}</div> <div class="name">{{ music.name }}</div>
<div> <div>
<div class="user">{{ music.author }}</div> <div class="user">{{ music.author }}</div>
<div class="peoples"> <div class="peoples">>{{ formatNumber(music.use_count) }} 人使用</div>
>{{ formatNumber(music.use_count) }} 人使用
</div>
</div> </div>
<div class="collection" @click.stop="toggleCollect()"> <div class="collection" @click.stop="toggleCollect()">
<img <img v-if="isCollect" src="../../assets/img/icon/star-yellow.png" />
v-if="isCollect"
src="../../assets/img/icon/star-yellow.png"
/>
<img v-else src="../../assets/img/icon/star-white.png" /> <img v-else src="../../assets/img/icon/star-white.png" />
<span>{{ isCollect ? '已' : '' }}收藏</span> <span>{{ isCollect ? '已' : '' }}收藏</span>
</div> </div>
@@ -120,11 +95,7 @@
@cancel="shareType = -1" @cancel="shareType = -1"
> >
<template v-slot:header> <template v-slot:header>
<img <img style="width: 100%" src="../../assets/img/icon/share-password.webp" alt="" />
style="width: 100%"
src="../../assets/img/icon/share-password.webp"
alt=""
/>
</template> </template>
</ConfirmDialog> </ConfirmDialog>
@@ -132,301 +103,300 @@
</div> </div>
</template> </template>
<script> <script>
import Posters from '../../components/Posters' import Posters from '../../components/Posters'
import Scroll from '../../components/Scroll' import Scroll from '../../components/Scroll'
import Loading from '../../components/Loading' import Loading from '../../components/Loading'
import Share from '../../components/Share' import Share from '../../components/Share'
import DouyinCode from '../../components/DouyinCode' import DouyinCode from '../../components/DouyinCode'
import ConfirmDialog from '../../components/dialog/ConfirmDialog' import ConfirmDialog from '../../components/dialog/ConfirmDialog'
import ShareToFriend from './components/ShareToFriend' import ShareToFriend from './components/ShareToFriend'
import resource from '../../assets/data/resource' import resource from '../../assets/data/resource'
import { myVideo } from '@/api/videos' import { myVideo } from '@/api/videos'
export default { export default {
name: 'Music', name: 'Music',
components: { components: {
Scroll, Scroll,
Posters, Posters,
Loading, Loading,
Share, Share,
DouyinCode, DouyinCode,
ConfirmDialog, ConfirmDialog,
ShareToFriend, ShareToFriend
},
data() {
return {
loading: false,
isFixed: false,
isCollect: false,
isPlay: false,
isSharing: false,
okText: '',
showSharePassword: false,
shareToFriend: false,
shareType: -1,
showDouyinCode: false,
audio: new Audio(),
total: 0,
pageNo: 0,
pageSize: 15,
videos: [],
music: {
name: '发如雪',
mp3: 'https://m3.8js.net:99/2014/211204142150965.mp3',
cover: new URL('../../assets/img/music-cover/7.jpg', import.meta.url).href,
author: '周杰伦',
duration: 60,
use_count: 37441000,
is_collect: false,
is_play: false
}
}
},
watch: {
shareType(newVal, oldVal) {
if (newVal === -1) return
this.showSharePassword = true
switch (newVal) {
case 2:
case 3:
return (this.okText = '去微信粘贴')
case 4:
case 5:
return (this.okText = '去QQ粘贴')
case 8:
return (this.okText = '去微博粘贴')
}
}
},
created() {
if (this.$route.query.name) {
this.music = this.$route.query
}
this.loadData(true)
},
computed: {},
methods: {
toggleCollect() {
this.isCollect = !this.isCollect
}, },
data() { async loadData(init = false) {
return { if (this.loading) return
loading: false, if (!init) {
isFixed: false, if (this.total <= this.videos.length) {
isCollect: false, return this.$notice('暂时没有更多了')
isPlay: false, }
isSharing: false, this.pageNo++
okText: '', }
this.loading = true
showSharePassword: false, let res = await myVideo({
shareToFriend: false, pageNo: this.pageNo,
shareType: -1, pageSize: this.pageSize
})
showDouyinCode: false, this.loading = false
audio: new Audio(), if (res.code === this.SUCCESS) {
total: 0, this.videos = this.videos.concat(res.data.list)
pageNo: 0, this.total = res.data.total
pageSize: 15,
videos: [],
music: {
name: '发如雪',
mp3: 'https://m3.8js.net:99/2014/211204142150965.mp3',
cover: new URL('../../assets/img/music-cover/7.jpg', import.meta.url)
.href,
author: '周杰伦',
duration: 60,
use_count: 37441000,
is_collect: false,
is_play: false,
},
} }
}, },
watch: { togglePlay() {
shareType(newVal, oldVal) { this.isPlay = !this.isPlay
if (newVal === -1) return if (this.isPlay) {
this.showSharePassword = true if (!this.audio.src) {
switch (newVal) { this.audio.src = this.music.mp3
case 2:
case 3:
return (this.okText = '去微信粘贴')
case 4:
case 5:
return (this.okText = '去QQ粘贴')
case 8:
return (this.okText = '去微博粘贴')
} }
}, this.audio.play()
}, this.audio.addEventListener('ended', () => (this.isPlay = false))
created() { } else {
if (this.$route.query.name) { this.stopPlay()
this.music = this.$route.query
} }
this.loadData(true)
}, },
computed: {}, delayShowDialog(cb) {
methods: { setTimeout(() => {
toggleCollect() { cb()
this.isCollect = !this.isCollect }, 100)
},
async loadData(init = false) {
if (this.loading) return
if (!init) {
if (this.total <= this.videos.length) {
return this.$notice('暂时没有更多了')
}
this.pageNo++
}
this.loading = true
let res = await myVideo({
pageNo: this.pageNo,
pageSize: this.pageSize,
})
this.loading = false
if (res.code === this.SUCCESS) {
this.videos = this.videos.concat(res.data.list)
this.total = res.data.total
}
},
togglePlay() {
this.isPlay = !this.isPlay
if (this.isPlay) {
if (!this.audio.src) {
this.audio.src = this.music.mp3
}
this.audio.play()
this.audio.addEventListener('ended', () => (this.isPlay = false))
} else {
this.stopPlay()
}
},
delayShowDialog(cb) {
setTimeout(() => {
cb()
}, 100)
},
stopPlay() {
this.audio.pause()
this.audio.removeEventListener('ended', null)
},
},
unmounted() {
this.stopPlay()
},
deactivated() {
this.stopPlay()
}, },
stopPlay() {
this.audio.pause()
this.audio.removeEventListener('ended', null)
}
},
unmounted() {
this.stopPlay()
},
deactivated() {
this.stopPlay()
} }
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '../../assets/less/index'; @import '../../assets/less/index';
#Music { #Music {
position: fixed;
left: 0;
right: 0;
bottom: 0;
top: 0;
overflow: auto;
color: white;
font-size: 14rem;
.header {
position: fixed; position: fixed;
left: 0; z-index: 9;
right: 0;
bottom: 0;
top: 0; top: 0;
overflow: auto; background: var(--main-bg);
color: white; width: 100%;
font-size: 14rem; box-sizing: border-box;
padding: 0 15rem;
height: 60rem;
display: flex;
justify-content: space-between;
align-items: center;
.header { .center {
position: fixed; font-size: 13rem;
z-index: 9; position: absolute;
top: 0; left: 50%;
background: var(--main-bg); transform: translateX(-50%);
width: 100%; }
box-sizing: border-box;
padding: 0 15rem; .right {
height: 60rem;
display: flex; display: flex;
justify-content: space-between;
align-items: center; align-items: center;
.center { .logo {
font-size: 13rem; background: linear-gradient(to bottom, #794cff 5%, #4c3efe 50%);
position: absolute; //padding: .2rem 1rem;
left: 50%; width: 80rem;
transform: translateX(-50%);
}
.right {
display: flex;
align-items: center;
.logo {
background: linear-gradient(to bottom, #794cff 5%, #4c3efe 50%);
//padding: .2rem 1rem;
width: 80rem;
height: 20rem;
border-radius: 10rem;
display: flex;
align-items: center;
justify-content: center;
font-size: 10rem;
}
img {
width: 24rem;
height: 24rem;
margin-left: 15rem;
}
}
}
.content {
padding-top: 60rem;
.Scroll {
height: calc(var(--vh, 1vh) * 100 - 60rem);
}
.desc {
padding: 10rem 15rem 30rem 15rem;
display: flex;
height: 120rem;
.cover-wrapper {
position: relative;
display: flex;
align-items: center;
justify-content: center;
.play {
width: 40rem;
height: 40rem;
position: absolute;
}
.cover {
width: 120rem;
object-fit: cover;
height: 100%;
border-radius: 3rem;
}
}
.info {
margin-left: 15rem;
display: flex;
flex-direction: column;
justify-content: space-between;
.name {
font-size: 18rem;
color: #fff;
font-weight: bold;
margin-bottom: 10rem;
}
.user,
.peoples {
font-size: 12rem;
margin-bottom: 5rem;
color: #999999;
}
.collection {
display: flex;
justify-content: center;
height: 25rem;
width: 70rem;
align-items: center;
color: #ffffff;
background: var(--second-btn-color);
border-radius: 2rem;
font-size: 13rem;
img {
margin-right: 5rem;
width: 13rem;
height: 13rem;
}
}
}
}
}
.options {
font-size: 14rem;
width: 100vw;
position: fixed;
bottom: 20rem;
display: flex;
justify-content: center;
img {
width: 20rem;
height: 20rem; height: 20rem;
margin-right: 5rem; border-radius: 10rem;
}
.l-button {
margin-left: 5rem;
margin-right: 5rem;
width: 140rem;
border-radius: 50rem;
display: flex; display: flex;
padding: 15rem 0;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
font-size: 10rem;
} }
.white { img {
color: black; width: 24rem;
background: white; height: 24rem;
} margin-left: 15rem;
.primary {
background: var(--primary-btn-color);
color: white;
} }
} }
} }
.content {
padding-top: 60rem;
.Scroll {
height: calc(var(--vh, 1vh) * 100 - 60rem);
}
.desc {
padding: 10rem 15rem 30rem 15rem;
display: flex;
height: 120rem;
.cover-wrapper {
position: relative;
display: flex;
align-items: center;
justify-content: center;
.play {
width: 40rem;
height: 40rem;
position: absolute;
}
.cover {
width: 120rem;
object-fit: cover;
height: 100%;
border-radius: 3rem;
}
}
.info {
margin-left: 15rem;
display: flex;
flex-direction: column;
justify-content: space-between;
.name {
font-size: 18rem;
color: #fff;
font-weight: bold;
margin-bottom: 10rem;
}
.user,
.peoples {
font-size: 12rem;
margin-bottom: 5rem;
color: #999999;
}
.collection {
display: flex;
justify-content: center;
height: 25rem;
width: 70rem;
align-items: center;
color: #ffffff;
background: var(--second-btn-color);
border-radius: 2rem;
font-size: 13rem;
img {
margin-right: 5rem;
width: 13rem;
height: 13rem;
}
}
}
}
}
.options {
font-size: 14rem;
width: 100vw;
position: fixed;
bottom: 20rem;
display: flex;
justify-content: center;
img {
width: 20rem;
height: 20rem;
margin-right: 5rem;
}
.l-button {
margin-left: 5rem;
margin-right: 5rem;
width: 140rem;
border-radius: 50rem;
display: flex;
padding: 15rem 0;
align-items: center;
justify-content: center;
}
.white {
color: black;
background: white;
}
.primary {
background: var(--primary-btn-color);
color: white;
}
}
}
</style> </style>

File diff suppressed because it is too large Load Diff

View File

@@ -1,10 +1,6 @@
<template> <template>
<div class="Publish"> <div class="Publish">
<video <video id="video" autoplay="autoplay" style="width: 100%; height: calc(100% - 60rem)"></video>
id="video"
autoplay="autoplay"
style="width: 100%; height: calc(100% - 60rem)"
></video>
<div class="footer"> <div class="footer">
<SlideHorizontal style="height: 60rem" v-model:index="activeIndex"> <SlideHorizontal style="height: 60rem" v-model:index="activeIndex">
<SlideItem style="width: 20vw"></SlideItem> <SlideItem style="width: 20vw"></SlideItem>
@@ -53,141 +49,141 @@
</div> </div>
</template> </template>
<script> <script>
import { mapState } from 'pinia' import { mapState } from 'pinia'
import { useBaseStore } from '@/store/pinia' import { useBaseStore } from '@/store/pinia'
//访问用户媒体设备的兼容方法 //访问用户媒体设备的兼容方法
function getUserMedia(constrains, success, error) { function getUserMedia(constrains, success, error) {
if (navigator.mediaDevices.getUserMedia) { if (navigator.mediaDevices.getUserMedia) {
//最新标准API //最新标准API
navigator.mediaDevices.getUserMedia(constrains).then(success).catch(error) navigator.mediaDevices.getUserMedia(constrains).then(success).catch(error)
} else if (navigator.webkitGetUserMedia) { } else if (navigator.webkitGetUserMedia) {
//webkit内核浏览器 //webkit内核浏览器
navigator.webkitGetUserMedia(constrains).then(success).catch(error) navigator.webkitGetUserMedia(constrains).then(success).catch(error)
} else if (navigator.mozGetUserMedia) { } else if (navigator.mozGetUserMedia) {
//Firefox浏览器 //Firefox浏览器
navagator.mozGetUserMedia(constrains).then(success).catch(error) navagator.mozGetUserMedia(constrains).then(success).catch(error)
} else if (navigator.getUserMedia) { } else if (navigator.getUserMedia) {
//旧版API //旧版API
navigator.getUserMedia(constrains).then(success).catch(error) navigator.getUserMedia(constrains).then(success).catch(error)
}
}
export default {
name: 'Publish',
data() {
return {
video: null,
activeIndex: 1
}
},
computed: {
...mapState(useBaseStore, ['bodyHeight', 'bodyWidth'])
},
mounted() {
//获得video摄像头区域
this.video = document.getElementById('video')
this.getMedia()
},
methods: {
getMedia() {
// let constraints = {video: {width: this.bodyWidth, height: this.bodyHeight - 60}, audio: false};
// let constraints = {video:{width:480,height:320}, audio: false};
let constraints = { video: true, audio: false }
try {
getUserMedia(
constraints,
(MediaStream) => {
this.video.srcObject = MediaStream
this.video.play()
},
function (PermissionDeniedError) {
console.log(PermissionDeniedError)
}
)
} catch (e) {
console.log('e', e)
}
} }
} }
}
export default {
name: 'Publish',
data() {
return {
video: null,
activeIndex: 1,
}
},
computed: {
...mapState(useBaseStore, ['bodyHeight', 'bodyWidth']),
},
mounted() {
//获得video摄像头区域
this.video = document.getElementById('video')
this.getMedia()
},
methods: {
getMedia() {
// let constraints = {video: {width: this.bodyWidth, height: this.bodyHeight - 60}, audio: false};
// let constraints = {video:{width:480,height:320}, audio: false};
let constraints = { video: true, audio: false }
try {
getUserMedia(
constraints,
(MediaStream) => {
this.video.srcObject = MediaStream
this.video.play()
},
function (PermissionDeniedError) {
console.log(PermissionDeniedError)
},
)
} catch (e) {
console.log('e', e)
}
},
},
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '../../assets/less/index'; @import '../../assets/less/index';
.Publish { .Publish {
position: fixed;
left: 0;
right: 0;
bottom: 0;
top: 0;
overflow: auto;
color: white;
background: black;
.footer {
font-size: 15rem;
font-weight: bold;
color: var(--second-text-color);
.base-slide-item {
display: flex;
align-items: center;
}
.active {
color: white;
}
}
.float {
position: fixed; position: fixed;
left: 0; left: 0;
right: 0; right: 0;
bottom: 0;
top: 0; top: 0;
overflow: auto; height: calc(100% - 60px);
color: white;
background: black;
.footer { .close {
font-size: 15rem; font-size: 28rem;
font-weight: bold; position: absolute;
color: var(--second-text-color); left: 20rem;
top: 20rem;
}
.base-slide-item { .choose-music {
display: flex; position: absolute;
align-items: center; left: 50%;
} top: 20rem;
transform: translateX(-50%);
border-radius: 20rem;
background: #333333;
padding: 5rem 15rem;
display: flex;
align-items: center;
font-size: 14rem;
.active { svg {
color: white; font-size: 30rem;
margin-right: 5rem;
width: 12rem;
height: 12rem;
} }
} }
.float { .toolbar {
position: fixed; position: absolute;
left: 0; top: 20rem;
right: 0; right: 10rem;
top: 0;
height: calc(100% - 60px);
.close { .tool {
font-size: 28rem;
position: absolute;
left: 20rem;
top: 20rem;
}
.choose-music {
position: absolute;
left: 50%;
top: 20rem;
transform: translateX(-50%);
border-radius: 20rem;
background: #333333;
padding: 5rem 15rem;
display: flex; display: flex;
flex-direction: column;
align-items: center; align-items: center;
font-size: 14rem; margin-bottom: 20rem;
font-size: 26rem;
svg {
font-size: 30rem;
margin-right: 5rem;
width: 12rem;
height: 12rem;
}
}
.toolbar {
position: absolute;
top: 20rem;
right: 10rem;
.tool {
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 20rem;
font-size: 26rem;
}
} }
} }
} }
}
</style> </style>

View File

@@ -13,75 +13,43 @@
<div class="title"> <div class="title">
<span>内容违规</span> <span>内容违规</span>
</div> </div>
<div <div class="row" @click="$nav('/home/submit-report', { type: '色情低俗', mode })">
class="row"
@click="$nav('/home/submit-report', { type: '色情低俗', mode })"
>
<span>色情低俗</span> <span>色情低俗</span>
<dy-back scale=".8" direction="right"></dy-back> <dy-back scale=".8" direction="right"></dy-back>
</div> </div>
<div <div class="row" @click="$nav('/home/submit-report', { type: '时政不实信息', mode })">
class="row"
@click="$nav('/home/submit-report', { type: '时政不实信息', mode })"
>
<span>时政不实信息</span> <span>时政不实信息</span>
<dy-back scale=".8" direction="right"></dy-back> <dy-back scale=".8" direction="right"></dy-back>
</div> </div>
<div <div class="row" @click="$nav('/home/submit-report', { type: '违法犯罪', mode })">
class="row"
@click="$nav('/home/submit-report', { type: '违法犯罪', mode })"
>
<span>违法犯罪</span> <span>违法犯罪</span>
<dy-back scale=".8" direction="right"></dy-back> <dy-back scale=".8" direction="right"></dy-back>
</div> </div>
<div <div class="row" @click="$nav('/home/submit-report', { type: '垃圾广告、售卖假货等', mode })">
class="row"
@click="
$nav('/home/submit-report', { type: '垃圾广告、售卖假货等', mode })
"
>
<span>垃圾广告售卖假货等</span> <span>垃圾广告售卖假货等</span>
<dy-back scale=".8" direction="right"></dy-back> <dy-back scale=".8" direction="right"></dy-back>
</div> </div>
<div <div class="row" @click="$nav('/home/submit-report', { type: '造谣传播', mode })">
class="row"
@click="$nav('/home/submit-report', { type: '造谣传播', mode })"
>
<span>造谣传播</span> <span>造谣传播</span>
<dy-back scale=".8" direction="right"></dy-back> <dy-back scale=".8" direction="right"></dy-back>
</div> </div>
<div <div class="row" @click="$nav('/home/submit-report', { type: '涉嫌欺诈', mode })">
class="row"
@click="$nav('/home/submit-report', { type: '涉嫌欺诈', mode })"
>
<span>涉嫌欺诈</span> <span>涉嫌欺诈</span>
<dy-back scale=".8" direction="right"></dy-back> <dy-back scale=".8" direction="right"></dy-back>
</div> </div>
<div <div class="row" @click="$nav('/home/submit-report', { type: '侮辱漫骂', mode })">
class="row"
@click="$nav('/home/submit-report', { type: '侮辱漫骂', mode })"
>
<span>侮辱漫骂</span> <span>侮辱漫骂</span>
<dy-back scale=".8" direction="right"></dy-back> <dy-back scale=".8" direction="right"></dy-back>
</div> </div>
<div <div class="row" @click="$nav('/home/submit-report', { type: '危险行为', mode })">
class="row"
@click="$nav('/home/submit-report', { type: '危险行为', mode })"
>
<span>危险行为</span> <span>危险行为</span>
<dy-back scale=".8" direction="right"></dy-back> <dy-back scale=".8" direction="right"></dy-back>
</div> </div>
<div <div class="row" @click="$nav('/home/submit-report', { type: '涉嫌非法集资', mode })">
class="row"
@click="$nav('/home/submit-report', { type: '涉嫌非法集资', mode })"
>
<span>涉嫌非法集资</span> <span>涉嫌非法集资</span>
<dy-back scale=".8" direction="right"></dy-back> <dy-back scale=".8" direction="right"></dy-back>
</div> </div>
<div <div class="row" @click="$nav('/home/submit-report', { type: '价值观导向不良', mode })">
class="row"
@click="$nav('/home/submit-report', { type: '价值观导向不良', mode })"
>
<span>价值观导向不良</span> <span>价值观导向不良</span>
<dy-back scale=".8" direction="right"></dy-back> <dy-back scale=".8" direction="right"></dy-back>
</div> </div>
@@ -95,24 +63,18 @@
@click=" @click="
$nav('/home/submit-report', { $nav('/home/submit-report', {
type: '侵犯名誉、隐私、肖像权等', type: '侵犯名誉、隐私、肖像权等',
mode, mode
}) })
" "
> >
<span>侵犯名誉隐私肖像权等</span> <span>侵犯名誉隐私肖像权等</span>
<dy-back scale=".8" direction="right"></dy-back> <dy-back scale=".8" direction="right"></dy-back>
</div> </div>
<div <div class="row" @click="$nav('/home/submit-report', { type: '内容盗用本人作品', mode })">
class="row"
@click="$nav('/home/submit-report', { type: '内容盗用本人作品', mode })"
>
<span>内容盗用本人作品</span> <span>内容盗用本人作品</span>
<dy-back scale=".8" direction="right"></dy-back> <dy-back scale=".8" direction="right"></dy-back>
</div> </div>
<div <div class="row" @click="$nav('/home/submit-report', { type: '内容盗用他人作品', mode })">
class="row"
@click="$nav('/home/submit-report', { type: '内容盗用他人作品', mode })"
>
<span>内容盗用他人作品</span> <span>内容盗用他人作品</span>
<dy-back scale=".8" direction="right"></dy-back> <dy-back scale=".8" direction="right"></dy-back>
</div> </div>
@@ -120,19 +82,11 @@
<div class="title"> <div class="title">
<span>未成年</span> <span>未成年</span>
</div> </div>
<div <div class="row" @click="$nav('/home/submit-report', { type: '未成年人不当行为', mode })">
class="row"
@click="$nav('/home/submit-report', { type: '未成年人不当行为', mode })"
>
<span>未成年人不当行为</span> <span>未成年人不当行为</span>
<dy-back scale=".8" direction="right"></dy-back> <dy-back scale=".8" direction="right"></dy-back>
</div> </div>
<div <div class="row" @click="$nav('/home/submit-report', { type: '内容不适合未成年观看', mode })">
class="row"
@click="
$nav('/home/submit-report', { type: '内容不适合未成年观看', mode })
"
>
<span>内容不适合未成年观看</span> <span>内容不适合未成年观看</span>
<dy-back scale=".8" direction="right"></dy-back> <dy-back scale=".8" direction="right"></dy-back>
</div> </div>
@@ -140,33 +94,19 @@
<div class="title"> <div class="title">
<span>其他</span> <span>其他</span>
</div> </div>
<div <div class="row" @click="$nav('/home/submit-report', { type: '引人不适', mode })">
class="row"
@click="$nav('/home/submit-report', { type: '引人不适', mode })"
>
<span>引人不适</span> <span>引人不适</span>
<dy-back scale=".8" direction="right"></dy-back> <dy-back scale=".8" direction="right"></dy-back>
</div> </div>
<div <div class="row" @click="$nav('/home/submit-report', { type: '疑似自我伤害', mode })">
class="row"
@click="$nav('/home/submit-report', { type: '疑似自我伤害', mode })"
>
<span>疑似自我伤害</span> <span>疑似自我伤害</span>
<dy-back scale=".8" direction="right"></dy-back> <dy-back scale=".8" direction="right"></dy-back>
</div> </div>
<div <div class="row" @click="$nav('/home/submit-report', { type: '诱导点赞、分享、关注', mode })">
class="row"
@click="
$nav('/home/submit-report', { type: '诱导点赞、分享、关注', mode })
"
>
<span>诱导点赞分享关注</span> <span>诱导点赞分享关注</span>
<dy-back scale=".8" direction="right"></dy-back> <dy-back scale=".8" direction="right"></dy-back>
</div> </div>
<div <div class="row" @click="$nav('/home/submit-report', { type: '其他', mode })">
class="row"
@click="$nav('/home/submit-report', { type: '其他', mode })"
>
<span>其他</span> <span>其他</span>
<dy-back scale=".8" direction="right"></dy-back> <dy-back scale=".8" direction="right"></dy-back>
</div> </div>
@@ -174,56 +114,56 @@
</div> </div>
</template> </template>
<script> <script>
export default { export default {
name: 'Report', name: 'Report',
props: {}, props: {},
data() { data() {
return { return {
mode: 'video', mode: 'video'
} }
}, },
computed: {}, computed: {},
created() { created() {
this.mode = this.$route.query.mode this.mode = this.$route.query.mode
}, },
activated() {}, activated() {},
methods: {}, methods: {}
} }
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '../../assets/less/index'; @import '../../assets/less/index';
.Report { .Report {
position: fixed; position: fixed;
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
top: 0; top: 0;
overflow: auto; overflow: auto;
color: white; color: white;
font-size: 14rem; font-size: 14rem;
.content { .content {
padding-top: 60rem; padding-top: 60rem;
.title { .title {
font-size: 12rem; font-size: 12rem;
padding: 10rem 15rem; padding: 10rem 15rem;
color: var(--second-text-color); color: var(--second-text-color);
img { img {
width: 10rem; width: 10rem;
height: 10rem; height: 10rem;
margin-right: 2rem; margin-right: 2rem;
}
} }
} }
.line {
width: calc(100% - 30rem);
margin-left: 15rem;
background: var(--line-color);
}
} }
.line {
width: calc(100% - 30rem);
margin-left: 15rem;
background: var(--line-color);
}
}
</style> </style>

File diff suppressed because it is too large Load Diff

View File

@@ -53,155 +53,152 @@
</div> </div>
</template> </template>
<script> <script>
export default { export default {
name: 'Report', name: 'Report',
props: {}, props: {},
data() { data() {
return { return {
type: '色情低俗', type: '色情低俗',
mode: 'video', mode: 'video',
desc: '', desc: '',
photos: [], photos: []
} }
}, },
computed: {}, computed: {},
created() { created() {
this.type = this.$route.query.type this.type = this.$route.query.type
this.mode = this.$route.query.mode this.mode = this.$route.query.mode
}, },
methods: { methods: {
async upload() { async upload() {
this.$showLoading() this.$showLoading()
await this.$sleep(500) await this.$sleep(500)
this.$hideLoading() this.$hideLoading()
this.photos.push( this.photos.push(
new URL( new URL(`../../assets/img/poster/${this.photos.length}.jpg`, import.meta.url).href
`../../assets/img/poster/${this.photos.length}.jpg`, )
import.meta.url, }
).href,
)
},
},
} }
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '../../assets/less/index'; @import '../../assets/less/index';
.Report { .Report {
position: fixed; position: fixed;
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
top: 0; top: 0;
overflow: auto; overflow: auto;
color: white; color: white;
font-size: 14rem; font-size: 14rem;
.content { .content {
padding-top: 60rem; padding-top: 60rem;
.title { .title {
font-size: 12rem; font-size: 12rem;
padding: 10rem 15rem; padding: 10rem 15rem;
color: var(--second-text-color);
border-bottom: 1px solid #cccccc11;
img {
width: 10rem;
height: 10rem;
margin-right: 2rem;
}
}
.l-row {
padding: 0 15rem;
.textarea-ctn {
width: 100%;
background: var(--active-main-bg);
padding: 15rem;
box-sizing: border-box;
margin-top: 10rem;
border-radius: 2px;
textarea {
font-family: 'Microsoft YaHei UI';
outline: none;
width: 100%;
border: none;
background: transparent;
color: white;
&::placeholder {
color: var(--second-text-color);
}
}
}
.text-num {
margin-top: 5rem;
font-size: 10rem;
color: var(--second-text-color); color: var(--second-text-color);
border-bottom: 1px solid #cccccc11; text-align: right;
}
}
img { .upload-photo {
margin-top: 5rem;
display: flex;
padding: 0 15rem;
@width: calc((100vw - 3vw - 30rem) / 4);
.photo-wrapper {
width: @width;
height: @width;
position: relative;
margin-right: 1vw;
.photo {
object-fit: cover;
position: absolute;
width: 100%;
height: 100%;
}
.close {
position: absolute;
right: 0;
top: 0;
background: var(--second-btn-color);
padding: 3rem;
width: 10rem; width: 10rem;
height: 10rem; height: 10rem;
margin-right: 2rem;
} }
} }
.l-row { .upload {
padding: 0 15rem; width: @width;
height: @width;
.textarea-ctn {
width: 100%;
background: var(--active-main-bg);
padding: 15rem;
box-sizing: border-box;
margin-top: 10rem;
border-radius: 2px;
textarea {
font-family: 'Microsoft YaHei UI';
outline: none;
width: 100%;
border: none;
background: transparent;
color: white;
&::placeholder {
color: var(--second-text-color);
}
}
}
.text-num {
margin-top: 5rem;
font-size: 10rem;
color: var(--second-text-color);
text-align: right;
}
}
.upload-photo {
margin-top: 5rem;
display: flex; display: flex;
padding: 0 15rem; flex-direction: column;
justify-content: center;
color: var(--second-text-color);
font-size: 12rem;
align-items: center;
background: var(--second-btn-color-tran);
@width: calc((100vw - 3vw - 30rem) / 4); img {
width: 35rem;
.photo-wrapper { height: 35rem;
width: @width;
height: @width;
position: relative;
margin-right: 1vw;
.photo {
object-fit: cover;
position: absolute;
width: 100%;
height: 100%;
}
.close {
position: absolute;
right: 0;
top: 0;
background: var(--second-btn-color);
padding: 3rem;
width: 10rem;
height: 10rem;
}
}
.upload {
width: @width;
height: @width;
display: flex;
flex-direction: column;
justify-content: center;
color: var(--second-text-color);
font-size: 12rem;
align-items: center;
background: var(--second-btn-color-tran);
img {
width: 35rem;
height: 35rem;
}
} }
} }
} }
.button {
position: absolute;
left: 15rem;
right: 15rem;
bottom: 15rem;
}
} }
.button {
position: absolute;
left: 15rem;
right: 15rem;
bottom: 15rem;
}
}
</style> </style>

View File

@@ -13,47 +13,25 @@
<div class="dialog-header"> <div class="dialog-header">
<div class="title-wrapper"> <div class="title-wrapper">
<span class="title">{{ currentItem.author.nickname }}</span> <span class="title">{{ currentItem.author.nickname }}</span>
<span class="subtitle" <span class="subtitle">抖音号{{ _getUserDouyinId(currentItem) }}</span>
>抖音号{{ _getUserDouyinId(currentItem) }}</span
>
</div> </div>
<dy-back <dy-back mode="dark" img="close" direction="right" @click="cancel()"></dy-back>
mode="dark"
img="close"
direction="right"
@click="cancel()"
></dy-back>
</div> </div>
<div class="options"> <div class="options">
<div class="option" @click="cancel((e) => $emit('showShare'))"> <div class="option" @click="cancel((e) => $emit('showShare'))">
<img <img src="../../../assets/img/icon/components/follow/share.png" alt="" />
src="../../../assets/img/icon/components/follow/share.png"
alt=""
/>
<span>分享主页</span> <span>分享主页</span>
</div> </div>
<div class="option" @click="cancel((e) => $nav('/message/chat'))"> <div class="option" @click="cancel((e) => $nav('/message/chat'))">
<img <img src="../../../assets/img/icon/components/follow/private-chat.png" alt="" />
src="../../../assets/img/icon/components/follow/private-chat.png"
alt=""
/>
<span>发私信</span> <span>发私信</span>
</div> </div>
<div <div class="option" @click="cancel((e) => $nav('/home/report', { mode: 'chat' }))">
class="option" <img src="../../../assets/img/icon/components/follow/report.png" alt="" />
@click="cancel((e) => $nav('/home/report', { mode: 'chat' }))"
>
<img
src="../../../assets/img/icon/components/follow/report.png"
alt=""
/>
<span>举报</span> <span>举报</span>
</div> </div>
<div class="option" @click="cancel((e) => $emit('showBlockDialog'))"> <div class="option" @click="cancel((e) => $emit('showBlockDialog'))">
<img <img src="../../../assets/img/icon/components/follow/forbid.png" alt="" />
src="../../../assets/img/icon/components/follow/forbid.png"
alt=""
/>
<span>拉黑</span> <span>拉黑</span>
</div> </div>
</div> </div>
@@ -61,19 +39,13 @@
<div class="l-row" @click="cancel((e) => $emit('showChangeNote'))"> <div class="l-row" @click="cancel((e) => $emit('showChangeNote'))">
<div class="left">设置分组</div> <div class="left">设置分组</div>
<div class="right"> <div class="right">
<img <img src="../../../assets/img/icon/components/follow/write.png" alt="" />
src="../../../assets/img/icon/components/follow/write.png"
alt=""
/>
</div> </div>
</div> </div>
<div class="l-row" @click="cancel((e) => $emit('showChangeNote'))"> <div class="l-row" @click="cancel((e) => $emit('showChangeNote'))">
<div class="left">设置备注名</div> <div class="left">设置备注名</div>
<div class="right"> <div class="right">
<img <img src="../../../assets/img/icon/components/follow/write.png" alt="" />
src="../../../assets/img/icon/components/follow/write.png"
alt=""
/>
</div> </div>
</div> </div>
<div class="l-row"> <div class="l-row">
@@ -85,30 +57,19 @@
<div class="l-row"> <div class="l-row">
<div class="left">在关注列表中置顶</div> <div class="left">在关注列表中置顶</div>
<div class="right"> <div class="right">
<switches <switches v-model="switches1" theme="bootstrap" color="success"></switches>
v-model="switches1"
theme="bootstrap"
color="success"
></switches>
</div> </div>
</div> </div>
<div class="l-row"> <div class="l-row">
<div class="left">不让TA看</div> <div class="left">不让TA看</div>
<div class="right"> <div class="right">
<switches <switches v-model="switches1" theme="bootstrap" color="success"></switches>
v-model="switches1"
theme="bootstrap"
color="success"
></switches>
</div> </div>
</div> </div>
<div class="l-row" @click="cancel((e) => $emit('cancelFollow'))"> <div class="l-row" @click="cancel((e) => $emit('cancelFollow'))">
<div class="left" style="color: red">取消关注</div> <div class="left" style="color: red">取消关注</div>
<div class="right"> <div class="right">
<img <img src="../../../assets/img/icon/components/follow/reduce.png" alt="" />
src="../../../assets/img/icon/components/follow/reduce.png"
alt=""
/>
</div> </div>
</div> </div>
</div> </div>
@@ -116,137 +77,137 @@
</from-bottom-dialog> </from-bottom-dialog>
</template> </template>
<script> <script>
import FromBottomDialog from '../../../components/dialog/FromBottomDialog' import FromBottomDialog from '../../../components/dialog/FromBottomDialog'
import Switches from '../../message/components/swtich/switches' import Switches from '../../message/components/swtich/switches'
import { DefaultUser } from '@/utils/const_var' import { DefaultUser } from '@/utils/const_var'
import { _getUserDouyinId } from '@/utils' import { _getUserDouyinId } from '@/utils'
export default { export default {
name: 'FollowSetting', name: 'FollowSetting',
components: { components: {
FromBottomDialog, FromBottomDialog,
Switches, Switches
}, },
props: { props: {
currentItem: { currentItem: {
type: Object, type: Object,
default: { default: {
user: DefaultUser, user: DefaultUser,
isRequest: false, isRequest: false,
post: [], post: []
},
},
modelValue: false,
},
data() {
return {
switches1: false,
switches2: false,
} }
}, },
computed: {}, modelValue: false
created() {}, },
methods: { data() {
_getUserDouyinId, return {
cancel(cb) { switches1: false,
this.$emit('update:modelValue', false) switches2: false
cb && cb() }
}, },
}, computed: {},
created() {},
methods: {
_getUserDouyinId,
cancel(cb) {
this.$emit('update:modelValue', false)
cb && cb()
}
} }
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '../../../assets/less/index'; @import '../../../assets/less/index';
.follow-setting-dialog { .follow-setting-dialog {
padding: 15rem; padding: 15rem;
font-size: 14rem;
.dialog-header {
color: rgb(81, 81, 89);
font-size: 14rem; font-size: 14rem;
position: relative;
display: flex;
align-items: flex-start;
justify-content: space-between;
.dialog-header { .title-wrapper {
color: rgb(81, 81, 89);
font-size: 14rem;
position: relative;
display: flex; display: flex;
align-items: flex-start; flex-direction: column;
justify-content: space-between; }
.title-wrapper { .title {
display: flex; font-size: 18rem;
flex-direction: column; }
}
.title { .subtitle {
font-size: 18rem; margin-top: 5rem;
} color: var(--second-text-color);
font-size: 13rem;
}
.subtitle { img {
margin-top: 5rem; width: 14rem;
color: var(--second-text-color); height: 14rem;
font-size: 13rem; padding: 6rem;
} border-radius: 50%;
background: rgba(187, 187, 194, 0.4);
}
}
.options {
margin-top: 20rem;
display: flex;
justify-content: space-between;
.option {
box-sizing: border-box;
padding: 10rem;
display: flex;
background: white;
flex-direction: column;
align-items: center;
width: 23%;
font-size: 12rem;
border-radius: 8rem;
img { img {
width: 14rem; margin-top: 5rem;
height: 14rem; margin-bottom: 10rem;
padding: 6rem; @width: 20rem;
border-radius: 50%; width: @width;
background: rgba(187, 187, 194, 0.4); height: @width;
}
}
.options {
margin-top: 20rem;
display: flex;
justify-content: space-between;
.option {
box-sizing: border-box;
padding: 10rem;
display: flex;
background: white;
flex-direction: column;
align-items: center;
width: 23%;
font-size: 12rem;
border-radius: 8rem;
img {
margin-top: 5rem;
margin-bottom: 10rem;
@width: 20rem;
width: @width;
height: @width;
}
}
}
.l-rows {
margin-top: 20rem;
.l-row {
height: 45rem;
padding: 0 20rem;
background: white;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid rgba(222, 222, 222, 0.42);
&:first-child {
border-radius: 10rem 10rem 0 0;
}
&:last-child {
border-bottom: none;
border-radius: 0 0 10rem 10rem;
}
img {
width: 20rem;
height: 20rem;
}
} }
} }
} }
.l-rows {
margin-top: 20rem;
.l-row {
height: 45rem;
padding: 0 20rem;
background: white;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid rgba(222, 222, 222, 0.42);
&:first-child {
border-radius: 10rem 10rem 0 0;
}
&:last-child {
border-bottom: none;
border-radius: 0 0 10rem 10rem;
}
img {
width: 20rem;
height: 20rem;
}
}
}
}
</style> </style>

View File

@@ -13,45 +13,27 @@
<div class="dialog-header"> <div class="dialog-header">
<div class="title-wrapper"> <div class="title-wrapper">
<span class="title">{{ currentItem.author.nickname }}</span> <span class="title">{{ currentItem.author.nickname }}</span>
<span class="subtitle" <span class="subtitle">抖音号{{ _getUserDouyinId(currentItem) }}</span>
>抖音号{{ _getUserDouyinId(currentItem) }}</span
>
</div> </div>
<dy-back <dy-back mode="dark" img="close" direction="right" @click="cancel()"></dy-back>
mode="dark"
img="close"
direction="right"
@click="cancel()"
></dy-back>
</div> </div>
<div class="l-rows"> <div class="l-rows">
<div class="l-row"> <div class="l-row">
<div class="left">不让TA看</div> <div class="left">不让TA看</div>
<div class="right"> <div class="right">
<switches <switches v-model="switches1" theme="bootstrap" color="success"></switches>
v-model="switches1"
theme="bootstrap"
color="success"
></switches>
</div> </div>
</div> </div>
<div class="l-row"> <div class="l-row">
<div class="left">在关注列表中置顶</div> <div class="left">在关注列表中置顶</div>
<div class="right"> <div class="right">
<switches <switches v-model="switches1" theme="bootstrap" color="success"></switches>
v-model="switches1"
theme="bootstrap"
color="success"
></switches>
</div> </div>
</div> </div>
<div class="l-row" @click="cancel((e) => $emit('cancelFollow'))"> <div class="l-row" @click="cancel((e) => $emit('cancelFollow'))">
<div class="left">取消关注</div> <div class="left">取消关注</div>
<div class="right"> <div class="right">
<img <img src="../../../assets/img/icon/components/follow/reduce.png" alt="" />
src="../../../assets/img/icon/components/follow/reduce.png"
alt=""
/>
</div> </div>
</div> </div>
</div> </div>
@@ -59,137 +41,137 @@
</from-bottom-dialog> </from-bottom-dialog>
</template> </template>
<script> <script>
import FromBottomDialog from '../../../components/dialog/FromBottomDialog' import FromBottomDialog from '../../../components/dialog/FromBottomDialog'
import Switches from '../../message/components/swtich/switches' import Switches from '../../message/components/swtich/switches'
import { DefaultUser } from '@/utils/const_var' import { DefaultUser } from '@/utils/const_var'
import { _getUserDouyinId } from '@/utils' import { _getUserDouyinId } from '@/utils'
export default { export default {
name: 'FollowSetting', name: 'FollowSetting',
components: { components: {
FromBottomDialog, FromBottomDialog,
Switches, Switches
}, },
props: { props: {
currentItem: { currentItem: {
type: Object, type: Object,
default: { default: {
user: DefaultUser, user: DefaultUser,
isRequest: false, isRequest: false,
post: [], post: []
},
},
modelValue: false,
},
data() {
return {
switches1: false,
switches2: false,
} }
}, },
computed: {}, modelValue: false
created() {}, },
methods: { data() {
_getUserDouyinId, return {
cancel(cb) { switches1: false,
this.$emit('update:modelValue', false) switches2: false
cb && cb() }
}, },
}, computed: {},
created() {},
methods: {
_getUserDouyinId,
cancel(cb) {
this.$emit('update:modelValue', false)
cb && cb()
}
} }
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '../../../assets/less/index'; @import '../../../assets/less/index';
.follow-setting-dialog { .follow-setting-dialog {
padding: 15rem; padding: 15rem;
font-size: 14rem;
.dialog-header {
color: rgb(81, 81, 89);
font-size: 14rem; font-size: 14rem;
position: relative;
display: flex;
align-items: flex-start;
justify-content: space-between;
.dialog-header { .title-wrapper {
color: rgb(81, 81, 89);
font-size: 14rem;
position: relative;
display: flex; display: flex;
align-items: flex-start; flex-direction: column;
justify-content: space-between; }
.title-wrapper { .title {
display: flex; font-size: 18rem;
flex-direction: column; }
}
.title { .subtitle {
font-size: 18rem; margin-top: 5rem;
} color: var(--second-text-color);
font-size: 13rem;
}
.subtitle { img {
margin-top: 5rem; width: 14rem;
color: var(--second-text-color); height: 14rem;
font-size: 13rem; padding: 6rem;
} border-radius: 50%;
background: rgba(187, 187, 194, 0.4);
}
}
.options {
margin-top: 20rem;
display: flex;
justify-content: space-between;
.option {
box-sizing: border-box;
padding: 10rem;
display: flex;
background: white;
flex-direction: column;
align-items: center;
width: 23%;
font-size: 12rem;
border-radius: 8rem;
img { img {
width: 14rem; margin-top: 5rem;
height: 14rem; margin-bottom: 10rem;
padding: 6rem; @width: 20rem;
border-radius: 50%; width: @width;
background: rgba(187, 187, 194, 0.4); height: @width;
}
}
.options {
margin-top: 20rem;
display: flex;
justify-content: space-between;
.option {
box-sizing: border-box;
padding: 10rem;
display: flex;
background: white;
flex-direction: column;
align-items: center;
width: 23%;
font-size: 12rem;
border-radius: 8rem;
img {
margin-top: 5rem;
margin-bottom: 10rem;
@width: 20rem;
width: @width;
height: @width;
}
}
}
.l-rows {
margin-top: 20rem;
.l-row {
height: 45rem;
padding: 0 20rem;
background: white;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid rgba(222, 222, 222, 0.42);
&:nth-child(1) {
border-radius: 10rem 10rem 0 0;
}
&:nth-child(3) {
border-bottom: none;
border-radius: 0 0 10rem 10rem;
}
img {
width: 20rem;
height: 20rem;
}
} }
} }
} }
.l-rows {
margin-top: 20rem;
.l-row {
height: 45rem;
padding: 0 20rem;
background: white;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid rgba(222, 222, 222, 0.42);
&:nth-child(1) {
border-radius: 10rem 10rem 0 0;
}
&:nth-child(3) {
border-bottom: none;
border-radius: 0 0 10rem 10rem;
}
img {
width: 20rem;
height: 20rem;
}
}
}
}
</style> </style>

View File

@@ -21,409 +21,358 @@
class="tab1-img" class="tab1-img"
/> />
</div> </div>
<div <div class="tab" :class="{ active: index === 1 }" @click.stop="change(1)">
class="tab"
:class="{ active: index === 1 }"
@click.stop="change(1)"
>
<span>长视频</span> <span>长视频</span>
</div> </div>
<div <div class="tab" :class="{ active: index === 2 }" @click.stop="change(2)">
class="tab"
:class="{ active: index === 2 }"
@click.stop="change(2)"
>
<span>关注</span> <span>关注</span>
<img src="../../../assets/img/icon/live.webp" class="tab2-img" /> <img src="../../../assets/img/icon/live.webp" class="tab2-img" />
</div> </div>
<div <div class="tab" :class="{ active: index === 3 }" @click.stop="change(3)">
class="tab"
:class="{ active: index === 3 }"
@click.stop="change(3)"
>
<span>经验</span> <span>经验</span>
</div> </div>
<div <div class="tab" :class="{ active: index === 4 }" @click.stop="change(4)">
class="tab"
:class="{ active: index === 4 }"
@click.stop="change(4)"
>
<span>推荐</span> <span>推荐</span>
</div> </div>
</div> </div>
<div class="indicator" ref="indicator"></div> <div class="indicator" ref="indicator"></div>
</div> </div>
<Icon <Icon v-hide="loading" icon="ion:search" class="search" @click="$nav('/home/search')" />
v-hide="loading"
icon="ion:search"
class="search"
@click="$nav('/home/search')"
/>
</div> </div>
<div class="toggle-type" :class="{ open }"> <div class="toggle-type" :class="{ open }">
<div <div class="l-button" :class="{ active: type === 0 }" @click="toggleType(0)">
class="l-button"
:class="{ active: type === 0 }"
@click="toggleType(0)"
>
<span>同城</span> <span>同城</span>
<img <img v-if="type === 0" src="../../../assets/img/icon/switch.png" alt="" />
v-if="type === 0"
src="../../../assets/img/icon/switch.png"
alt=""
/>
</div>
<div
class="l-button"
:class="{ active: type === 1 }"
@click="toggleType(1)"
>
学习
</div>
<div
class="l-button"
:class="{ active: type === 2 }"
@click="toggleType(2)"
>
热点
</div> </div>
<div class="l-button" :class="{ active: type === 1 }" @click="toggleType(1)">学习</div>
<div class="l-button" :class="{ active: type === 2 }" @click="toggleType(2)">热点</div>
</div> </div>
<Loading <Loading :style="loadingStyle" class="loading" style="width: 40rem" :is-full-screen="false" />
:style="loadingStyle"
class="loading"
style="width: 40rem"
:is-full-screen="false"
/>
</div> </div>
</template> </template>
<script> <script>
import Loading from '../../../components/Loading.vue' import Loading from '../../../components/Loading.vue'
import bus from '../../../utils/bus' import bus from '../../../utils/bus'
import { mapState } from 'pinia' import { mapState } from 'pinia'
import { useBaseStore } from '@/store/pinia' import { useBaseStore } from '@/store/pinia'
export default { export default {
name: 'IndicatorHome', name: 'IndicatorHome',
components: { components: {
Loading, Loading
},
props: {
loading: false,
//用于和slidList绑定因为一个页面可能有多个slidList但只有一个indicator组件
name: {
type: String,
default: () => ''
}, },
props: { index: {
loading: false, type: Number,
//用于和slidList绑定因为一个页面可能有多个slidList但只有一个indicator组件 default: () => 0
name: {
type: String,
default: () => '',
},
index: {
type: Number,
default: () => 0,
},
isLight: {
type: Boolean,
default: () => false,
},
}, },
setup() { isLight: {
const baseStore = useBaseStore() type: Boolean,
return { baseStore } default: () => false
}
},
setup() {
const baseStore = useBaseStore()
return { baseStore }
},
data() {
return {
indicatorRef: null,
lefts: [],
indicatorSpace: 0,
open: false,
type: 1,
moveY: 0
}
},
computed: {
...mapState(useBaseStore, ['judgeValue', 'homeRefresh']),
tabOneClass() {
return { active: this.index === 0, open: this.open }
}, },
data() { transform() {
return { return `translate3d(0, ${this.moveY - this.judgeValue > this.homeRefresh ? this.homeRefresh : this.moveY - this.judgeValue}px, 0)`
indicatorRef: null,
lefts: [],
indicatorSpace: 0,
open: false,
type: 1,
moveY: 0,
}
}, },
computed: { toolbarStyle() {
...mapState(useBaseStore, ['judgeValue', 'homeRefresh']), if (this.loading) {
tabOneClass() {
return { active: this.index === 0, open: this.open }
},
transform() {
return `translate3d(0, ${this.moveY - this.judgeValue > this.homeRefresh ? this.homeRefresh : this.moveY - this.judgeValue}px, 0)`
},
toolbarStyle() {
if (this.loading) {
return {
opacity: 1,
'transition-duration': '300ms',
transform: `translate3d(0, 0, 0)`,
}
}
if (this.moveY) {
return {
opacity:
1 - (this.moveY - this.judgeValue) / (this.homeRefresh / 2),
transform: this.transform,
}
}
return { return {
opacity: 1, opacity: 1,
'transition-duration': '300ms', 'transition-duration': '300ms',
transform: `translate3d(0, 0, 0)`, transform: `translate3d(0, 0, 0)`
} }
}, }
noticeStyle() { if (this.moveY) {
if (this.loading) { return {
return { opacity: 0 } opacity: 1 - (this.moveY - this.judgeValue) / (this.homeRefresh / 2),
} transform: this.transform
if (this.moveY) {
return {
opacity:
(this.moveY - this.judgeValue) / (this.homeRefresh / 2) - 0.5,
transform: this.transform,
}
} }
}
return {
opacity: 1,
'transition-duration': '300ms',
transform: `translate3d(0, 0, 0)`
}
},
noticeStyle() {
if (this.loading) {
return { opacity: 0 } return { opacity: 0 }
}, }
loadingStyle() { if (this.moveY) {
if (this.loading) { return {
return { opacity: 1, 'transition-duration': '300ms' } opacity: (this.moveY - this.judgeValue) / (this.homeRefresh / 2) - 0.5,
transform: this.transform
} }
if (this.moveY) { }
return { return { opacity: 0 }
opacity: },
(this.moveY - this.judgeValue) / (this.homeRefresh / 2) - 0.5, loadingStyle() {
transform: this.transform, if (this.loading) {
} return { opacity: 1, 'transition-duration': '300ms' }
}
if (this.moveY) {
return {
opacity: (this.moveY - this.judgeValue) / (this.homeRefresh / 2) - 0.5,
transform: this.transform
} }
}, }
}, }
created() {}, },
mounted() { created() {},
this.initTabs() mounted() {
bus.on(this.name + '-moveX', this.move) this.initTabs()
bus.on(this.name + '-moveY', (e) => { bus.on(this.name + '-moveX', this.move)
this.moveY = e bus.on(this.name + '-moveY', (e) => {
}) this.moveY = e
bus.on(this.name + '-end', this.end) })
}, bus.on(this.name + '-end', this.end)
unmounted() { },
bus.off(this.name + '-moveX', this.move) unmounted() {
bus.off(this.name + '-moveY') bus.off(this.name + '-moveX', this.move)
bus.off(this.name + '-end', this.end) bus.off(this.name + '-moveY')
}, bus.off(this.name + '-end', this.end)
},
methods: { methods: {
toggleType(type) { toggleType(type) {
if (type !== this.type) { if (type !== this.type) {
this.type = type this.type = type
this.open = false this.open = false
} }
},
change(index) {
if (this.index === 0 && index === 0) {
this.open = !this.open
} else {
this.open = false
}
this.$emit('update:index', index)
this.$setCss(this.indicatorRef, 'transition-duration', `300ms`)
this.$setCss(this.indicatorRef, 'left', this.lefts[index] + 'px')
},
initTabs() {
let tabs = this.$refs.tabs
this.indicatorRef = this.$refs.indicator
let indicatorWidth = this.$getCss(this.indicatorRef, 'width')
for (let i = 0; i < tabs.children.length; i++) {
let item = tabs.children[i]
let tabWidth = this.$getCss(item, 'width')
this.lefts.push(
item.getBoundingClientRect().x -
tabs.children[0].getBoundingClientRect().x +
(tabWidth * 0.5 - indicatorWidth / 2),
)
}
this.indicatorSpace = this.lefts[1] - this.lefts[0]
this.$setCss(this.indicatorRef, 'transition-duration', `300ms`)
this.$setCss(this.indicatorRef, 'left', this.lefts[this.index] + 'px')
},
move(e) {
this.$setCss(this.indicatorRef, 'transition-duration', `0ms`)
this.$setCss(
this.indicatorRef,
'left',
this.lefts[this.index] -
e / (this.baseStore.bodyWidth / this.indicatorSpace) +
'px',
)
},
end(index) {
this.moveY = 0
this.$setCss(this.indicatorRef, 'transition-duration', `300ms`)
this.$setCss(this.indicatorRef, 'left', this.lefts[index] + 'px')
setTimeout(() => {
this.$setCss(this.indicatorRef, 'transition-duration', `0ms`)
}, 300)
},
}, },
change(index) {
if (this.index === 0 && index === 0) {
this.open = !this.open
} else {
this.open = false
}
this.$emit('update:index', index)
this.$setCss(this.indicatorRef, 'transition-duration', `300ms`)
this.$setCss(this.indicatorRef, 'left', this.lefts[index] + 'px')
},
initTabs() {
let tabs = this.$refs.tabs
this.indicatorRef = this.$refs.indicator
let indicatorWidth = this.$getCss(this.indicatorRef, 'width')
for (let i = 0; i < tabs.children.length; i++) {
let item = tabs.children[i]
let tabWidth = this.$getCss(item, 'width')
this.lefts.push(
item.getBoundingClientRect().x -
tabs.children[0].getBoundingClientRect().x +
(tabWidth * 0.5 - indicatorWidth / 2)
)
}
this.indicatorSpace = this.lefts[1] - this.lefts[0]
this.$setCss(this.indicatorRef, 'transition-duration', `300ms`)
this.$setCss(this.indicatorRef, 'left', this.lefts[this.index] + 'px')
},
move(e) {
this.$setCss(this.indicatorRef, 'transition-duration', `0ms`)
this.$setCss(
this.indicatorRef,
'left',
this.lefts[this.index] - e / (this.baseStore.bodyWidth / this.indicatorSpace) + 'px'
)
},
end(index) {
this.moveY = 0
this.$setCss(this.indicatorRef, 'transition-duration', `300ms`)
this.$setCss(this.indicatorRef, 'left', this.lefts[index] + 'px')
setTimeout(() => {
this.$setCss(this.indicatorRef, 'transition-duration', `0ms`)
}, 300)
}
} }
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
.indicator-home { .indicator-home {
position: absolute; position: absolute;
font-size: 16rem; font-size: 16rem;
top: 0;
left: 0;
z-index: 2;
width: 100%;
color: white;
height: var(--home-header-height);
transition: all 0.3s;
font-weight: bold;
.notice {
opacity: 0;
top: 0; top: 0;
left: 0; position: absolute;
width: 100vw;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.loading {
opacity: 0;
top: 7rem;
right: 7rem;
position: absolute;
}
.toolbar {
z-index: 2; z-index: 2;
width: 100%; position: relative;
color: white; color: white;
height: var(--home-header-height); width: 100%;
transition: all 0.3s; height: 100%;
font-weight: bold; box-sizing: border-box;
padding: 0 15rem;
display: flex;
justify-content: space-between;
align-items: center;
.notice { .tab-ctn {
opacity: 0; width: 80%;
top: 0;
position: absolute;
width: 100vw;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.loading {
opacity: 0;
top: 7rem;
right: 7rem;
position: absolute;
}
.toolbar {
z-index: 2;
position: relative; position: relative;
color: white;
width: 100%;
height: 100%;
box-sizing: border-box;
padding: 0 15rem;
display: flex;
justify-content: space-between;
align-items: center;
.tab-ctn { .tabs {
width: 80%; display: flex;
position: relative; justify-content: space-between;
.tabs { .tab {
display: flex; transition: color 0.3s;
justify-content: space-between; color: rgba(white, 0.7);
position: relative;
font-size: 17rem;
.tab { .tab1-img {
transition: color 0.3s; position: absolute;
color: rgba(white, 0.7); @width: 1rem;
position: relative; width: @width;
font-size: 17rem; height: @width;
margin-left: 4rem;
transition: all 0.3s;
margin-top: 7rem;
}
.tab2-img {
position: absolute;
height: 15rem;
left: 24rem;
top: -5rem;
}
&.open {
.tab1-img { .tab1-img {
position: absolute; transform: rotate(180deg);
@width: 1rem;
width: @width;
height: @width;
margin-left: 4rem;
transition: all 0.3s;
margin-top: 7rem;
}
.tab2-img {
position: absolute;
height: 15rem;
left: 24rem;
top: -5rem;
}
&.open {
.tab1-img {
transform: rotate(180deg);
}
}
&.active {
color: white;
} }
} }
}
.indicator { &.active {
//transition: left .3s; color: white;
position: absolute; }
bottom: -6rem;
height: 2rem;
width: 20rem;
//width: calc(100% / 5);
background: #fff;
border-radius: 5rem;
} }
} }
.search { .indicator {
color: white; //transition: left .3s;
font-size: 24rem; position: absolute;
bottom: -6rem;
height: 2rem;
width: 20rem;
//width: calc(100% / 5);
background: #fff;
border-radius: 5rem;
} }
} }
.toggle-type { .search {
@height: 100rem; color: white;
position: absolute; font-size: 24rem;
height: @height;
//padding-top: @height;
padding-left: 10rem;
padding-right: 10rem;
padding-bottom: 10rem;
width: 100%;
background: var(--main-bg);
display: flex;
justify-content: space-between;
align-items: flex-end;
box-sizing: border-box;
font-size: 12rem;
top: -@height;
transition: all 0.3s;
opacity: 0;
&.open {
top: 0;
opacity: 1;
}
.l-button {
flex: 1;
margin: 0 3rem;
height: 28rem;
background: rgb(33, 36, 45);
display: flex;
align-items: center;
justify-content: center;
border-radius: 20rem;
color: rgb(157, 161, 170);
transition: all 0.3s;
&.active {
background: rgb(57, 57, 65);
color: white;
}
img {
@width: 9rem;
width: @width;
height: @width;
margin-left: 8rem;
}
}
}
.mask {
top: 0;
position: absolute;
width: 100vw;
height: calc(var(--vh, 1vh) * 100);
background: #00000066;
} }
} }
.toggle-type {
@height: 100rem;
position: absolute;
height: @height;
//padding-top: @height;
padding-left: 10rem;
padding-right: 10rem;
padding-bottom: 10rem;
width: 100%;
background: var(--main-bg);
display: flex;
justify-content: space-between;
align-items: flex-end;
box-sizing: border-box;
font-size: 12rem;
top: -@height;
transition: all 0.3s;
opacity: 0;
&.open {
top: 0;
opacity: 1;
}
.l-button {
flex: 1;
margin: 0 3rem;
height: 28rem;
background: rgb(33, 36, 45);
display: flex;
align-items: center;
justify-content: center;
border-radius: 20rem;
color: rgb(157, 161, 170);
transition: all 0.3s;
&.active {
background: rgb(57, 57, 65);
color: white;
}
img {
@width: 9rem;
width: @width;
height: @width;
margin-left: 8rem;
}
}
}
.mask {
top: 0;
position: absolute;
width: 100vw;
height: calc(var(--vh, 1vh) * 100);
background: #00000066;
}
}
</style> </style>

View File

@@ -1,13 +1,6 @@
<template> <template>
<svg viewBox="0 0 400 400"> <svg viewBox="0 0 400 400">
<circle <circle :r="150" cx="200" cy="200" :stroke="'darkgrey'" :stroke-width="40" fill="none" />
:r="150"
cx="200"
cy="200"
:stroke="'darkgrey'"
:stroke-width="40"
fill="none"
/>
<circle <circle
transform="rotate(-90)" transform="rotate(-90)"
transform-origin="center" transform-origin="center"
@@ -23,20 +16,20 @@
</svg> </svg>
</template> </template>
<script> <script>
export default { export default {
name: 'LoadingCircle', name: 'LoadingCircle',
components: {}, components: {},
props: { props: {
modelValue: { modelValue: {
type: Number, type: Number,
default: 50, default: 50
}, }
}, },
computed: { computed: {
progress() { progress() {
return 300 * 3.14 * (this.modelValue / 100) return 300 * 3.14 * (this.modelValue / 100)
}, }
}, },
methods: {}, methods: {}
} }
</script> </script>

View File

@@ -154,171 +154,162 @@
</div> </div>
<div class="text-num">{{ desc.length }}/300</div> <div class="text-num">{{ desc.length }}/300</div>
</div> </div>
<dy-button type="primary" :disabled="!disabled" @click="submit" <dy-button type="primary" :disabled="!disabled" @click="submit">提交</dy-button>
>提交</dy-button
>
</div> </div>
</div> </div>
</transition> </transition>
</template> </template>
<script> <script>
import Check from '../../../components/Check' import Check from '../../../components/Check'
export default { export default {
name: 'Test', name: 'Test',
props: { props: {
modelValue: false, modelValue: false
},
components: {
Check
},
watch: {
modelValue(newVal) {
this.type1 = false
this.type2 = false
this.type3 = false
this.type4 = false
this.type5 = false
this.type6 = false
this.type7 = false
this.desc = ''
}
},
data() {
return {
type1: false,
type2: false,
type3: false,
type4: false,
type5: false,
type6: false,
type7: false,
desc: ''
}
},
computed: {
disabled() {
if (this.type7 && this.desc) return true
return this.type1 || this.type2 || this.type3 || this.type4 || this.type5 || this.type6
}
},
created() {},
methods: {
falseOther(cb) {
this.type1 = false
this.type2 = false
this.type3 = false
this.type4 = false
this.type5 = false
this.type6 = false
this.type7 = false
cb()
}, },
components: { cancel() {
Check, this.$emit('update:modelValue', false)
},
watch: {
modelValue(newVal) {
this.type1 = false
this.type2 = false
this.type3 = false
this.type4 = false
this.type5 = false
this.type6 = false
this.type7 = false
this.desc = ''
},
},
data() {
return {
type1: false,
type2: false,
type3: false,
type4: false,
type5: false,
type6: false,
type7: false,
desc: '',
}
},
computed: {
disabled() {
if (this.type7 && this.desc) return true
return (
this.type1 ||
this.type2 ||
this.type3 ||
this.type4 ||
this.type5 ||
this.type6
)
},
},
created() {},
methods: {
falseOther(cb) {
this.type1 = false
this.type2 = false
this.type3 = false
this.type4 = false
this.type5 = false
this.type6 = false
this.type7 = false
cb()
},
cancel() {
this.$emit('update:modelValue', false)
},
async submit() {
this.cancel()
this.$showLoading()
await this.$sleep(1000)
this.$hideLoading()
this.$notice('感谢你的反馈,我们会尽快答复!')
},
}, },
async submit() {
this.cancel()
this.$showLoading()
await this.$sleep(1000)
this.$hideLoading()
this.$notice('感谢你的反馈,我们会尽快答复!')
}
} }
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '../../../assets/less/index'; @import '../../../assets/less/index';
.play-feedback { .play-feedback {
max-height: 490rem; max-height: 490rem;
overflow: auto; overflow: auto;
background: #fff; background: #fff;
color: black; color: black;
position: fixed;
bottom: 50rem;
left: 0;
right: 0;
.feedback-header {
position: fixed; position: fixed;
bottom: 50rem;
left: 0; left: 0;
right: 0; right: 0;
background: white;
height: 30rem;
padding: 15rem;
display: flex;
justify-content: space-between;
align-items: flex-start;
font-weight: bold;
font-size: 18rem;
}
.feedback-header { .content {
position: fixed; padding: 60rem 15rem 15rem 15rem;
left: 0; }
right: 0;
background: white;
height: 30rem;
padding: 15rem;
display: flex;
justify-content: space-between;
align-items: flex-start;
font-weight: bold;
font-size: 18rem;
}
.content { .notice {
padding: 60rem 15rem 15rem 15rem; font-size: 12rem;
} color: var(--second-text-color);
}
.notice { .l-row {
font-size: 12rem; display: flex;
color: var(--second-text-color); align-items: center;
} min-height: 50rem;
font-size: 14rem;
border-bottom: 1px solid #f1f1f1;
.l-row { .check {
display: flex; width: 20rem;
align-items: center; height: 20rem;
min-height: 50rem; margin-right: 10rem;
font-size: 14rem;
border-bottom: 1px solid #f1f1f1;
.check {
width: 20rem;
height: 20rem;
margin-right: 10rem;
}
}
.no-border {
border-bottom: none;
}
.other {
.textarea-ctn {
width: 100%;
background: #eae8e8;
padding: 15rem;
box-sizing: border-box;
margin-top: 10rem;
border-radius: 2px;
textarea {
font-family: 'Microsoft YaHei UI';
outline: none;
width: 100%;
border: none;
background: transparent;
color: black;
&::placeholder {
color: var(--second-text-color);
}
}
}
.text-num {
margin-top: 8rem;
margin-bottom: 8rem;
font-size: 10rem;
color: var(--second-text-color);
text-align: right;
}
} }
} }
.no-border {
border-bottom: none;
}
.other {
.textarea-ctn {
width: 100%;
background: #eae8e8;
padding: 15rem;
box-sizing: border-box;
margin-top: 10rem;
border-radius: 2px;
textarea {
font-family: 'Microsoft YaHei UI';
outline: none;
width: 100%;
border: none;
background: transparent;
color: black;
&::placeholder {
color: var(--second-text-color);
}
}
}
.text-num {
margin-top: 8rem;
margin-bottom: 8rem;
font-size: 10rem;
color: var(--second-text-color);
text-align: right;
}
}
}
</style> </style>

View File

@@ -9,62 +9,39 @@
> >
<div class="option-dialog"> <div class="option-dialog">
<div class="buttons"> <div class="buttons">
<dy-button <dy-button v-if="downloading" class="mb1r" :border="false" :progress="progress">
v-if="downloading" <img src="../../../assets/img/icon/components/video/download-gray.png" alt="" />
class="mb1r"
:border="false"
:progress="progress"
>
<img
src="../../../assets/img/icon/components/video/download-gray.png"
alt=""
/>
<span class="second-text-color">下载中 9.2MB/{{ progress }}%</span> <span class="second-text-color">下载中 9.2MB/{{ progress }}%</span>
</dy-button> </dy-button>
<template v-if="canDownload"> <template v-if="canDownload">
<dy-button type="green" v-if="showShare2WeChatZone" @click="$no"> <dy-button type="green" v-if="showShare2WeChatZone" @click="$no">
<template v-slot:prefix> <template v-slot:prefix>
<img <img src="../../../assets/img/icon/components/video/wechatzone-white.webp" alt="" />
src="../../../assets/img/icon/components/video/wechatzone-white.webp"
alt=""
/>
</template> </template>
发送视频到朋友圈 发送视频到朋友圈
</dy-button> </dy-button>
<dy-button type="green" v-if="showShare2WeChat" @click="$no"> <dy-button type="green" v-if="showShare2WeChat" @click="$no">
<template v-slot:prefix> <template v-slot:prefix>
<img <img src="../../../assets/img/icon/components/video/wechat-white.webp" alt="" />
src="../../../assets/img/icon/components/video/wechat-white.webp"
alt=""
/>
</template> </template>
发送视频到微信 发送视频到微信
</dy-button> </dy-button>
<dy-button type="qqzone" v-if="showShare2QQZone" @click="$no"> <dy-button type="qqzone" v-if="showShare2QQZone" @click="$no">
<template v-slot:prefix> <template v-slot:prefix>
<img <img src="../../../assets/img/icon/components/video/qqzone-white.png" alt="" />
src="../../../assets/img/icon/components/video/qqzone-white.png"
alt=""
/>
</template> </template>
发送视频到QQ空间 发送视频到QQ空间
</dy-button> </dy-button>
<dy-button type="qq" v-if="showShare2QQ" @click="$no"> <dy-button type="qq" v-if="showShare2QQ" @click="$no">
<template v-slot:prefix> <template v-slot:prefix>
<img <img src="../../../assets/img/icon/components/video/qq-white.webp" alt="" />
src="../../../assets/img/icon/components/video/qq-white.webp"
alt=""
/>
</template> </template>
发送视频到QQ 发送视频到QQ
</dy-button> </dy-button>
<dy-button type="webo" v-if="showShare2Webo" @click="$no"> <dy-button type="webo" v-if="showShare2Webo" @click="$no">
<template v-slot:prefix> <template v-slot:prefix>
<img <img src="../../../assets/img/icon/components/video/webo-white.webp" alt="" />
src="../../../assets/img/icon/components/video/webo-white.webp"
alt=""
/>
</template> </template>
发送视频到微博 发送视频到微博
</dy-button> </dy-button>
@@ -76,46 +53,31 @@
<template v-else> <template v-else>
<dy-button type="green" v-if="showShare2WeChatZone" @click="$no"> <dy-button type="green" v-if="showShare2WeChatZone" @click="$no">
<template v-slot:prefix> <template v-slot:prefix>
<img <img src="../../../assets/img/icon/components/video/wechatzone-white.webp" alt="" />
src="../../../assets/img/icon/components/video/wechatzone-white.webp"
alt=""
/>
</template> </template>
复制口令发给好友 复制口令发给好友
</dy-button> </dy-button>
<dy-button type="green" v-if="showShare2WeChat" @click="$no"> <dy-button type="green" v-if="showShare2WeChat" @click="$no">
<template v-slot:prefix> <template v-slot:prefix>
<img <img src="../../../assets/img/icon/components/video/wechat-white.webp" alt="" />
src="../../../assets/img/icon/components/video/wechat-white.webp"
alt=""
/>
</template> </template>
复制口令发给好友 复制口令发给好友
</dy-button> </dy-button>
<dy-button type="qqzone" v-if="showShare2QQZone" @click="$no"> <dy-button type="qqzone" v-if="showShare2QQZone" @click="$no">
<template v-slot:prefix> <template v-slot:prefix>
<img <img src="../../../assets/img/icon/components/video/qqzone-white.png" alt="" />
src="../../../assets/img/icon/components/video/qqzone-white.png"
alt=""
/>
</template> </template>
复制口令发给好友 复制口令发给好友
</dy-button> </dy-button>
<dy-button type="qq" v-if="showShare2QQ" @click="$no"> <dy-button type="qq" v-if="showShare2QQ" @click="$no">
<template v-slot:prefix> <template v-slot:prefix>
<img <img src="../../../assets/img/icon/components/video/qq-white.webp" alt="" />
src="../../../assets/img/icon/components/video/qq-white.webp"
alt=""
/>
</template> </template>
复制口令发给好友 复制口令发给好友
</dy-button> </dy-button>
<dy-button type="webo" v-if="showShare2Webo" @click="$no"> <dy-button type="webo" v-if="showShare2Webo" @click="$no">
<template v-slot:prefix> <template v-slot:prefix>
<img <img src="../../../assets/img/icon/components/video/webo-white.webp" alt="" />
src="../../../assets/img/icon/components/video/webo-white.webp"
alt=""
/>
</template> </template>
复制口令发给好友 复制口令发给好友
</dy-button> </dy-button>
@@ -128,20 +90,13 @@
</dy-button> </dy-button>
<dy-button class="mt1r" type="white" @click="$no"> <dy-button class="mt1r" type="white" @click="$no">
<img <img src="../../../assets/img/icon/components/video/wechat.webp" alt="" />
src="../../../assets/img/icon/components/video/wechat.webp"
alt=""
/>
发送视频到微信 发送视频到微信
</dy-button> </dy-button>
</template> </template>
</div> </div>
<div class="dialog-friends"> <div class="dialog-friends">
<div <div class="dialog-friend" v-for="item in localFriends.all" @click="share(item)">
class="dialog-friend"
v-for="item in localFriends.all"
@click="share(item)"
>
<img :src="$imgPreview(item.avatar)" alt="" /> <img :src="$imgPreview(item.avatar)" alt="" />
<div class="right"> <div class="right">
<span>{{ item.name }}</span> <span>{{ item.name }}</span>
@@ -160,202 +115,199 @@
</from-bottom-dialog> </from-bottom-dialog>
</template> </template>
<script> <script>
import FromBottomDialog from '../../../components/dialog/FromBottomDialog' import FromBottomDialog from '../../../components/dialog/FromBottomDialog'
import { mapState } from 'pinia' import { mapState } from 'pinia'
import { useBaseStore } from '@/store/pinia' import { useBaseStore } from '@/store/pinia'
/* /*
* 分享到各种工具 * 分享到各种工具
* */ * */
export default { export default {
name: 'ShareTo', name: 'ShareTo',
components: { components: {
FromBottomDialog, FromBottomDialog
},
props: {
type: {
type: Number,
default: -1
}, },
props: { videoId: {
type: { type: String,
type: Number, default: null
default: -1,
},
videoId: {
type: String,
default: null,
},
canDownload: {
type: Boolean,
default: true,
},
}, },
watch: { canDownload: {
type(newVal, oldVal) { type: Boolean,
this.change(newVal) default: true
}, }
showShareDialog() { },
this.localFriends = this.$clone(this.friends) watch: {
}, type(newVal, oldVal) {
this.change(newVal)
}, },
data() { showShareDialog() {
return { this.localFriends = this.$clone(this.friends)
progress: 0, }
downloading: false, },
data() {
return {
progress: 0,
downloading: false,
showShareDialog: false, showShareDialog: false,
showDownload: false, showDownload: false,
showShare2WeChatZone: false, showShare2WeChatZone: false,
showShare2WeChat: false, showShare2WeChat: false,
showShare2QQZone: false, showShare2QQZone: false,
showShare2QQ: false, showShare2QQ: false,
showShare2Webo: false, showShare2Webo: false,
localFriends: [], localFriends: []
}
},
computed: {
...mapState(useBaseStore, ['friends'])
},
created() {},
methods: {
async change(newVal) {
if (newVal === -1) return
this.showShareDialog = true
if (this.canDownload) {
let downloadedVideo = this.$storageGet('downloadedVideo', [])
if (!downloadedVideo.find((v) => v === this.videoId) && !this.downloading) {
await this.downloadVideo()
}
}
switch (newVal) {
case 2:
return (this.showShare2WeChatZone = true)
case 3:
return (this.showShare2WeChat = true)
case 4:
return (this.showShare2QQZone = true)
case 5:
return (this.showShare2QQ = true)
case 8:
return (this.showShare2Webo = true)
case 9:
return (this.showDownload = true)
} }
}, },
computed: { cancel() {
...mapState(useBaseStore, ['friends']), this.showShareDialog = false
this.showDownload = false
this.showShare2WeChatZone = false
this.showShare2WeChat = false
this.showShare2QQZone = false
this.showShare2QQ = false
this.showShare2Webo = false
this.$emit('update:type', -1)
}, },
created() {}, downloadVideo() {
methods: { return new Promise((resolve, reject) => {
async change(newVal) { this.progress = 0
if (newVal === -1) return this.downloading = true
this.showShareDialog = true let time = setInterval(() => {
if (this.canDownload) { if (this.progress >= 100) {
let downloadedVideo = this.$storageGet('downloadedVideo', []) let downloadedVideo = this.$storageGet('downloadedVideo', [])
if ( downloadedVideo.push(this.videoId)
!downloadedVideo.find((v) => v === this.videoId) && this.$storageSet('downloadedVideo', downloadedVideo)
!this.downloading clearInterval(time)
) { this.downloading = false
await this.downloadVideo() resolve()
} else {
this.progress++
} }
} }, 5)
switch (newVal) { })
case 2:
return (this.showShare2WeChatZone = true)
case 3:
return (this.showShare2WeChat = true)
case 4:
return (this.showShare2QQZone = true)
case 5:
return (this.showShare2QQ = true)
case 8:
return (this.showShare2Webo = true)
case 9:
return (this.showDownload = true)
}
},
cancel() {
this.showShareDialog = false
this.showDownload = false
this.showShare2WeChatZone = false
this.showShare2WeChat = false
this.showShare2QQZone = false
this.showShare2QQ = false
this.showShare2Webo = false
this.$emit('update:type', -1)
},
downloadVideo() {
return new Promise((resolve, reject) => {
this.progress = 0
this.downloading = true
let time = setInterval(() => {
if (this.progress >= 100) {
let downloadedVideo = this.$storageGet('downloadedVideo', [])
downloadedVideo.push(this.videoId)
this.$storageSet('downloadedVideo', downloadedVideo)
clearInterval(time)
this.downloading = false
resolve()
} else {
this.progress++
}
}, 5)
})
},
share(item) {
if (item.select) {
this.$notice('已分享给朋友')
}
item.select = true
},
}, },
share(item) {
if (item.select) {
this.$notice('已分享给朋友')
}
item.select = true
}
} }
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '../../../assets/less/index'; @import '../../../assets/less/index';
.option-dialog { .option-dialog {
.buttons { .buttons {
padding: 0 15rem; padding: 0 15rem;
img {
height: 22rem;
margin-right: 5rem;
}
}
.dialog-friends {
color: black;
margin: 10rem 10rem 0 10rem;
width: calc(100% - 20rem);
background: white;
border-radius: 6px 6px 0 0;
> .dialog-friend {
box-sizing: border-box;
padding: 8rem;
width: 100%;
display: flex;
align-items: center;
border-bottom: 1px solid #efefef;
img { img {
height: 22rem; border-radius: 50%;
margin-right: 5rem; width: 38rem;
height: 38rem;
} }
}
.dialog-friends { .right {
color: black; margin: 0 5rem 0 15rem;
margin: 10rem 10rem 0 10rem; font-size: 14rem;
width: calc(100% - 20rem);
background: white;
border-radius: 6px 6px 0 0;
> .dialog-friend {
box-sizing: border-box;
padding: 8rem;
width: 100%; width: 100%;
display: flex; display: flex;
align-items: center; align-items: center;
border-bottom: 1px solid #efefef; justify-content: space-between;
img { .share-btn {
border-radius: 50%; font-size: 13rem;
width: 38rem; color: white;
height: 38rem; height: 25rem;
} width: 60rem;
.right {
margin: 0 5rem 0 15rem;
font-size: 14rem;
width: 100%;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: center;
background: var(--primary-btn-color);
border-radius: 2px;
.share-btn { &.shared {
font-size: 13rem; background: lightgray;
color: white; color: var(--second-text-color);
height: 25rem;
width: 60rem;
display: flex;
align-items: center;
justify-content: center;
background: var(--primary-btn-color);
border-radius: 2px;
&.shared {
background: lightgray;
color: var(--second-text-color);
}
} }
} }
} }
}
.more { .more {
box-sizing: border-box; box-sizing: border-box;
height: 55rem; height: 55rem;
width: 100%; width: 100%;
display: flex; display: flex;
align-items: center; align-items: center;
border-bottom: 1px solid #efefef; border-bottom: 1px solid #efefef;
font-size: 14rem; font-size: 14rem;
margin-bottom: 15rem; margin-bottom: 15rem;
img { img {
border-radius: 50%; border-radius: 50%;
width: 20rem; width: 20rem;
height: 20rem; height: 20rem;
margin: 0 22rem 0 15rem; margin: 0 22rem 0 15rem;
}
} }
} }
} }
}
</style> </style>

View File

@@ -20,11 +20,7 @@
/> />
<template v-if="searchKey"> <template v-if="searchKey">
<div class="friend-list" v-if="searchResult.length"> <div class="friend-list" v-if="searchResult.length">
<div <div class="friend-item" v-for="item in searchResult" @click="handleClick2(item)">
class="friend-item"
v-for="item in searchResult"
@click="handleClick2(item)"
>
<img class="left" v-lazy="$imgPreview(item.avatar)" alt="" /> <img class="left" v-lazy="$imgPreview(item.avatar)" alt="" />
<div class="right"> <div class="right">
<div class="info"> <div class="info">
@@ -32,19 +28,12 @@
<span v-if="item.name.indexOf(searchKey) > -1"> <span v-if="item.name.indexOf(searchKey) > -1">
{{ item.name.substr(0, item.name.indexOf(searchKey)) {{ item.name.substr(0, item.name.indexOf(searchKey))
}}<span style="color: #fc2f56">{{ searchKey }}</span }}<span style="color: #fc2f56">{{ searchKey }}</span
>{{ >{{ item.name.substr(item.name.indexOf(searchKey) + searchKey.length) }}
item.name.substr(
item.name.indexOf(searchKey) + searchKey.length,
)
}}
</span> </span>
<span v-else>{{ item.name }}</span> <span v-else>{{ item.name }}</span>
</span> </span>
</div> </div>
<dy-button <dy-button :type="item.shared ? 'dark' : 'primary'" @click="item.shared = true">
:type="item.shared ? 'dark' : 'primary'"
@click="item.shared = true"
>
{{ item.shared ? '' : '' }}分享 {{ item.shared ? '' : '' }}分享
</dy-button> </dy-button>
</div> </div>
@@ -57,11 +46,7 @@
</template> </template>
<template v-else> <template v-else>
<div class="joined-chat-group-nav" @click="showJoinedChat = true"> <div class="joined-chat-group-nav" @click="showJoinedChat = true">
<img <img class="left" src="../../../assets/img/icon/people-gray.png" alt="" />
class="left"
src="../../../assets/img/icon/people-gray.png"
alt=""
/>
<div class="right"> <div class="right">
<span>已加入的群聊</span> <span>已加入的群聊</span>
<dy-back direction="right" mode="gray" scale=".7" /> <dy-back direction="right" mode="gray" scale=".7" />
@@ -73,10 +58,7 @@
<img class="left" v-lazy="$imgPreview(item.avatar)" alt="" /> <img class="left" v-lazy="$imgPreview(item.avatar)" alt="" />
<div class="right"> <div class="right">
<span>{{ item.name }}</span> <span>{{ item.name }}</span>
<dy-button <dy-button :type="item.shared ? 'dark' : 'primary'" @click="item.shared = true">
:type="item.shared ? 'dark' : 'primary'"
@click="item.shared = true"
>
{{ item.shared ? '' : '' }}分享 {{ item.shared ? '' : '' }}分享
</dy-button> </dy-button>
</div> </div>
@@ -86,11 +68,7 @@
</div> </div>
<div class="joined-chat-group" v-show="showJoinedChat"> <div class="joined-chat-group" v-show="showJoinedChat">
<div class="nav"> <div class="nav">
<dy-back <dy-back @click="showJoinedChat = false" mode="light" scale="1"></dy-back>
@click="showJoinedChat = false"
mode="light"
scale="1"
></dy-back>
<span>已加入的群聊</span> <span>已加入的群聊</span>
<span>&nbsp;</span> <span>&nbsp;</span>
</div> </div>
@@ -103,10 +81,7 @@
<div class="name">{{ text }}</div> <div class="name">{{ text }}</div>
<div class="num">(3)</div> <div class="num">(3)</div>
</div> </div>
<dy-button <dy-button :type="item.shared ? 'dark' : 'primary'" @click="item.shared = true">
:type="item.shared ? 'dark' : 'primary'"
@click="item.shared = true"
>
{{ item.shared ? '' : '' }}分享 {{ item.shared ? '' : '' }}分享
</dy-button> </dy-button>
</div> </div>
@@ -117,127 +92,165 @@
</from-bottom-dialog> </from-bottom-dialog>
</template> </template>
<script> <script>
import FromBottomDialog from '../../../components/dialog/FromBottomDialog' import FromBottomDialog from '../../../components/dialog/FromBottomDialog'
import { mapState } from 'pinia' import { mapState } from 'pinia'
import Search from '../../../components/Search' import Search from '../../../components/Search'
import Check from '../../../components/Check' import Check from '../../../components/Check'
import { useBaseStore } from '@/store/pinia' import { useBaseStore } from '@/store/pinia'
/* /*
分享给朋友 分享给朋友
* */ * */
export default { export default {
name: 'ShareTo', name: 'ShareTo',
components: { components: {
FromBottomDialog, FromBottomDialog,
Search, Search,
Check, Check
}, },
props: { props: {
modelValue: false, modelValue: false,
pageId: { pageId: {
type: String, type: String,
default: 'home-index', default: 'home-index'
}, }
}, },
data() { data() {
return { return {
height: '70vh', height: '70vh',
showJoinedChat: false, showJoinedChat: false,
isShowRightText: false, isShowRightText: false,
text: 'AAAAAAA、BBBBBBBB、CCCCCCCCCCCCC', text: 'AAAAAAA、BBBBBBBB、CCCCCCCCCCCCC',
localFriends: [], localFriends: [],
searchResult: [], searchResult: [],
searchKey: '', searchKey: ''
}
},
watch: {
searchKey(newVal) {
if (newVal) {
let temp = this.$clone(this.localFriends)
this.searchResult = temp.filter((v) => {
// return v.name.includes(newVal) || v.account.includes(newVal);
return v.name.includes(newVal)
})
} else {
this.searchResult = []
} }
}, },
watch: { modelValue(newVal) {
searchKey(newVal) { if (newVal) {
if (newVal) { this.localFriends = this.$clone(this.friends.all)
let temp = this.$clone(this.localFriends) this.localFriends.map((v) => (v.shared = false))
this.searchResult = temp.filter((v) => { } else {
// return v.name.includes(newVal) || v.account.includes(newVal);
return v.name.includes(newVal)
})
} else {
this.searchResult = []
}
},
modelValue(newVal) {
if (newVal) {
this.localFriends = this.$clone(this.friends.all)
this.localFriends.map((v) => (v.shared = false))
} else {
this.searchKey = ''
this.height = '70vh'
this.isShowRightText = false
this.showJoinedChat = false
}
},
},
computed: {
...mapState(useBaseStore, ['friends']),
selectFriends() {
return this.localFriends.filter((v) => v.shared)
},
},
created() {},
methods: {
handleClick() {
this.isShowRightText = true
this.height = 'calc(var(--vh, 1vh) * 100)'
},
handleClick2(item) {
item.select = !item.select
this.searchKey = '' this.searchKey = ''
}, this.height = '70vh'
onNotice() {
this.isShowRightText = false this.isShowRightText = false
this.searchKey = '' this.showJoinedChat = false
this.height = '70vh' }
}, }
cancel() { },
this.height = '70vh' computed: {
this.$emit('update:modelValue', false) ...mapState(useBaseStore, ['friends']),
}, selectFriends() {
return this.localFriends.filter((v) => v.shared)
}
},
created() {},
methods: {
handleClick() {
this.isShowRightText = true
this.height = 'calc(var(--vh, 1vh) * 100)'
}, },
handleClick2(item) {
item.select = !item.select
this.searchKey = ''
},
onNotice() {
this.isShowRightText = false
this.searchKey = ''
this.height = '70vh'
},
cancel() {
this.height = '70vh'
this.$emit('update:modelValue', false)
}
} }
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '../../../assets/less/index'; @import '../../../assets/less/index';
.button { .button {
width: 64rem; width: 64rem;
height: 26rem !important; height: 26rem !important;
}
@avatar-width: 38rem;
.friend-list {
padding: 0 15rem;
.index {
color: var(--second-text-color);
height: 60rem;
line-height: 60rem;
font-size: 13rem;
} }
@avatar-width: 38rem; .friend-item {
margin-bottom: 20rem;
display: flex;
align-items: center;
//background: #fff;
.friend-list { &:nth-child(1) {
padding: 0 15rem; margin-top: 10rem;
.index {
color: var(--second-text-color);
height: 60rem;
line-height: 60rem;
font-size: 13rem;
} }
.friend-item { .left {
margin-bottom: 20rem; width: @avatar-width;
height: @avatar-width;
border-radius: 50%;
margin-right: 15rem;
}
.right {
font-size: 14rem;
flex: 1;
display: flex; display: flex;
align-items: center; align-items: center;
//background: #fff; justify-content: space-between;
&:nth-child(1) { img {
margin-top: 10rem; height: 20rem;
} }
}
}
}
.content {
color: white;
.create-chat {
padding-bottom: 40rem;
background: var(--main-bg);
.search-ctn {
padding: 0 15rem;
}
.joined-chat-group-nav {
border-bottom: 1px solid var(--line-color);
height: 50rem;
padding: 0 15rem;
display: flex;
align-items: center;
.left { .left {
width: @avatar-width; width: 22rem;
height: @avatar-width; height: 22rem;
border-radius: 50%; margin-right: 10rem;
margin-right: 15rem;
} }
.right { .right {
@@ -246,36 +259,89 @@
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
}
}
img { .btn-wrapper {
height: 20rem; position: fixed;
bottom: 0;
left: 0;
right: 0;
background: var(--main-bg);
//background: red;
display: flex;
align-items: center;
justify-content: center;
.btn {
margin-bottom: 20rem;
width: calc(100% - 40rem);
height: 40rem;
display: flex;
align-items: center;
font-size: 14rem;
justify-content: center;
background: #3f445c;
border-radius: 2rem;
&.primary {
background: var(--primary-btn-color);
} }
} }
} }
.no-result {
height: 50vh;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
.notice-h1 {
font-size: 16rem;
}
.notice-h2 {
margin-top: 10rem;
font-size: 14rem;
color: var(--second-text-color);
}
}
} }
.content { .joined-chat-group {
color: white; background: var(--main-bg);
.create-chat { .nav {
padding-bottom: 40rem; font-size: 16rem;
background: var(--main-bg); padding: 15rem;
display: flex;
justify-content: space-between;
}
.search-ctn { .chat-list {
padding: 0 15rem; padding: 0 15rem;
}
.joined-chat-group-nav { .chat-item {
border-bottom: 1px solid var(--line-color); margin-bottom: 20rem;
height: 50rem;
padding: 0 15rem;
display: flex; display: flex;
align-items: center; align-items: center;
position: relative;
overflow: hidden;
&:nth-last-child(1) {
margin-bottom: 0;
}
&:nth-child(1) {
margin-top: 10rem;
}
.left { .left {
width: 22rem; width: @avatar-width;
height: 22rem; height: @avatar-width;
margin-right: 10rem; border-radius: 50%;
margin-right: 15rem;
} }
.right { .right {
@@ -284,123 +350,32 @@
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
}
}
.btn-wrapper { .title {
position: fixed; width: 55vw;
bottom: 0; overflow: hidden;
left: 0; box-sizing: border-box;
right: 0;
background: var(--main-bg);
//background: red;
display: flex;
align-items: center;
justify-content: center;
.btn {
margin-bottom: 20rem;
width: calc(100% - 40rem);
height: 40rem;
display: flex;
align-items: center;
font-size: 14rem;
justify-content: center;
background: #3f445c;
border-radius: 2rem;
&.primary {
background: var(--primary-btn-color);
}
}
}
.no-result {
height: 50vh;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
.notice-h1 {
font-size: 16rem;
}
.notice-h2 {
margin-top: 10rem;
font-size: 14rem;
color: var(--second-text-color);
}
}
}
.joined-chat-group {
background: var(--main-bg);
.nav {
font-size: 16rem;
padding: 15rem;
display: flex;
justify-content: space-between;
}
.chat-list {
padding: 0 15rem;
.chat-item {
margin-bottom: 20rem;
display: flex;
align-items: center;
position: relative;
overflow: hidden;
&:nth-last-child(1) {
margin-bottom: 0;
}
&:nth-child(1) {
margin-top: 10rem;
}
.left {
width: @avatar-width;
height: @avatar-width;
border-radius: 50%;
margin-right: 15rem;
}
.right {
font-size: 14rem;
flex: 1;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between;
.title { .name {
width: 55vw; white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
box-sizing: border-box;
display: flex;
align-items: center;
.name {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.num {
margin-left: 5rem;
color: var(--second-text-color);
}
} }
img { .num {
height: 15rem; margin-left: 5rem;
color: var(--second-text-color);
} }
} }
img {
height: 15rem;
}
} }
} }
} }
} }
}
</style> </style>

View File

@@ -38,15 +38,9 @@
:can-download="canDownload" :can-download="canDownload"
@click="closeShare()" @click="closeShare()"
/> />
<to-share <to-share item-type="report" @click="$nav('/home/report', { mode: this.mode })" />
item-type="report"
@click="$nav('/home/report', { mode: this.mode })"
/>
<to-share item-type="copyPassword" @click="copyLink" /> <to-share item-type="copyPassword" @click="copyLink" />
<to-share <to-share :item-type="isCollect ? 'collectYellow' : 'collect'" @click="toggleCollect" />
:item-type="isCollect ? 'collectYellow' : 'collect'"
@click="toggleCollect"
/>
<to-share item-type="comeon" @click="$no" /> <to-share item-type="comeon" @click="$no" />
<to-share item-type="dou" @click="$no" /> <to-share item-type="dou" @click="$no" />
<to-share item-type="copyLink" @click="copyLink" /> <to-share item-type="copyLink" @click="copyLink" />
@@ -74,10 +68,7 @@
</div> </div>
</div> </div>
<div class="more" @click="closeShare($nav('/message/share-to-friend'))"> <div class="more" @click="closeShare($nav('/message/share-to-friend'))">
<img <img class="left" src="../../../assets/img/icon/components/video/more-dark.png" />
class="left"
src="../../../assets/img/icon/components/video/more-dark.png"
/>
<span>更多朋友</span> <span>更多朋友</span>
</div> </div>
</div> </div>
@@ -86,342 +77,336 @@
</template> </template>
<script lang="jsx"> <script lang="jsx">
import { mapState } from 'pinia' import { mapState } from 'pinia'
import FromBottomDialog from '../../../components/dialog/FromBottomDialog' import FromBottomDialog from '../../../components/dialog/FromBottomDialog'
import LoadingCircle from './LoadingCircle' import LoadingCircle from './LoadingCircle'
import { useBaseStore } from '@/store/pinia' import { useBaseStore } from '@/store/pinia'
// import DouyinCode from "./DouyinCode"; // import DouyinCode from "./DouyinCode";
export default { export default {
name: 'Share', name: 'Share',
components: { components: {
FromBottomDialog, FromBottomDialog,
LoadingCircle, LoadingCircle,
// DouyinCode, // DouyinCode,
ToShare: { ToShare: {
components: { components: {
LoadingCircle, LoadingCircle
},
props: {
itemType: {
type: String,
default: 'weChat'
}, },
props: { needDown: {
itemType: { type: Boolean,
type: String, default: false
default: 'weChat',
},
needDown: {
type: Boolean,
default: false,
},
canDownload: {
type: Boolean,
default: true,
},
}, },
data() { canDownload: {
return { type: Boolean,
progress: 0, default: true
loading: false, }
text: { },
weChat: '微信', data() {
weChatZone: '朋友圈', return {
qq: 'QQ', progress: 0,
download: '保存本地', loading: false,
report: '举报', text: {
copyPassword: '复制口令', weChat: '微信',
copyLink: '复制链接', weChatZone: '朋友圈',
collect: '收藏', qq: 'QQ',
collectYellow: '取消收藏', download: '保存本地',
comeon: '一起看', report: '举报',
dou: '帮上热门', copyPassword: '复制口令',
share: '更多分享', copyLink: '复制链接',
duoshan: '多闪', collect: '收藏',
totoutiao: '今日头条', collectYellow: '取消收藏',
dislike: '不感兴趣', comeon: '一起看',
bizhi: '动态壁纸', dou: '帮上热门',
code: '抖音码', share: '更多分享',
}, duoshan: '多闪',
totoutiao: '今日头条',
dislike: '不感兴趣',
bizhi: '动态壁纸',
code: '抖音码'
} }
}
},
computed: {
styleCanDownload() {
if (!this.canDownload) {
return this.itemType !== 'download'
}
return true
}
},
methods: {
displayText() {
if (this.loading) {
return this.progress !== 100 ? '下载中' : this.text[this.itemType]
}
return this.text[this.itemType]
}, },
computed: { click(e) {
styleCanDownload() { if (!this.canDownload) {
if (!this.canDownload) { if (this.itemType === 'download') {
return this.itemType !== 'download' this.$stopPropagation(e)
}
return true
},
},
methods: {
displayText() {
if (this.loading) {
return this.progress !== 100 ? '下载中' : this.text[this.itemType]
}
return this.text[this.itemType]
},
click(e) {
if (!this.canDownload) {
if (this.itemType === 'download') {
this.$stopPropagation(e)
} else {
this.$notice('作者已关闭下载功能')
this.$emit('copy')
}
return
}
if (this.needDown) this.$stopPropagation(e)
else return
if (this.progress === 100) {
this.$notice('未实现分享跳转到其他App')
} else { } else {
this.loading = true this.$notice('作者已关闭下载功能')
let interval = setInterval(() => { this.$emit('copy')
if (this.progress < 100) {
this.progress++
} else {
clearInterval(interval)
this.loading = false
this.$emit('click')
this.$emit('click')
this.$notice('未实现分享跳转到其他App')
}
}, 10)
} }
}, return
}, }
render() { if (this.needDown) this.$stopPropagation(e)
return ( else return
<div if (this.progress === 100) {
className='to' this.$notice('未实现分享跳转到其他App')
onClick={this.click} } else {
style={{ opacity: this.styleCanDownload ? '1' : '0.5' }} this.loading = true
> let interval = setInterval(() => {
<div className='wrapper'> if (this.progress < 100) {
{this.loading ? ( this.progress++
<div } else {
className='loading-wrapper' clearInterval(interval)
style='width: 80%;height: 80%;' this.loading = false
> this.$emit('click')
<LoadingCircle v-model={this.progress} /> this.$emit('click')
</div> this.$notice('未实现分享跳转到其他App')
) : ( }
<img }, 10)
src={`/src/assets/img/icon/components/share/${this.itemType}.png`}
alt=''
/>
)}
</div>
<span>{this.displayText()}</span>
</div>
)
},
},
},
props: {
modelValue: false,
videoId: {
type: String,
default: null,
},
pageId: {
type: String,
default: 'home-index',
},
canDownload: {
type: Boolean,
default: false,
},
},
computed: {
...mapState(useBaseStore, ['friends']),
},
watch: {
modelValue(newVal) {
if (!newVal) {
this.loading = {
weChat: false,
weChatZone: false,
} }
this.progress = 0
this.isShowMore = false
} }
}, },
}, render() {
data() { return (
return { <div
isCollect: false, className="to"
isShowMore: false, onClick={this.click}
loading: { style={{ opacity: this.styleCanDownload ? '1' : '0.5' }}
weChat: false, >
weChatZone: false, <div className="wrapper">
}, {this.loading ? (
text: { <div className="loading-wrapper" style="width: 80%;height: 80%;">
weChat: '微信', <LoadingCircle v-model={this.progress} />
weChatZone: '朋友圈', </div>
}, ) : (
progress: 0, <img src={`/src/assets/img/icon/components/share/${this.itemType}.png`} alt="" />
)}
</div>
<span>{this.displayText()}</span>
</div>
)
} }
}
},
props: {
modelValue: false,
videoId: {
type: String,
default: null
}, },
methods: { pageId: {
displayText(type) { type: String,
if (this.loading[type]) { default: 'home-index'
return this.progress !== 100 ? '下载中' : this.text[type]
}
return this.text[type]
},
async copyLink() {
this.closeShare()
this.$showLoading()
await this.$sleep(500)
this.$hideLoading()
this.$notice('复制成功')
},
toggleCollect() {
this.closeShare()
if (this.isCollect) {
this.$notice('取消收藏成功')
} else {
this.$notice('收藏成功')
}
this.isCollect = !this.isCollect
},
toggleCall(item) {
item.select = !item.select
},
closeShare() {
this.$emit('update:modelValue', false)
},
closeShare1() {
this.$emit('update:modelValue', false)
},
}, },
canDownload: {
type: Boolean,
default: false
}
},
computed: {
...mapState(useBaseStore, ['friends'])
},
watch: {
modelValue(newVal) {
if (!newVal) {
this.loading = {
weChat: false,
weChatZone: false
}
this.progress = 0
this.isShowMore = false
}
}
},
data() {
return {
isCollect: false,
isShowMore: false,
loading: {
weChat: false,
weChatZone: false
},
text: {
weChat: '微信',
weChatZone: '朋友圈'
},
progress: 0
}
},
methods: {
displayText(type) {
if (this.loading[type]) {
return this.progress !== 100 ? '下载中' : this.text[type]
}
return this.text[type]
},
async copyLink() {
this.closeShare()
this.$showLoading()
await this.$sleep(500)
this.$hideLoading()
this.$notice('复制成功')
},
toggleCollect() {
this.closeShare()
if (this.isCollect) {
this.$notice('取消收藏成功')
} else {
this.$notice('收藏成功')
}
this.isCollect = !this.isCollect
},
toggleCall(item) {
item.select = !item.select
},
closeShare() {
this.$emit('update:modelValue', false)
},
closeShare1() {
this.$emit('update:modelValue', false)
}
} }
}
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.video-share { .video-share {
height: 60vh; height: 60vh;
width: 100%; width: 100%;
border-radius: 10rem 10rem 0 0; border-radius: 10rem 10rem 0 0;
color: white; color: white;
box-sizing: border-box; box-sizing: border-box;
.friends { .friends {
border-radius: 10rem; border-radius: 10rem;
margin: 10rem; margin: 10rem;
padding: 0 var(--page-padding); padding: 0 var(--page-padding);
@avatar-width: 38rem; @avatar-width: 38rem;
font-size: 14rem; font-size: 14rem;
background: white; background: white;
@item-width: 55rem; @item-width: 55rem;
.item { .item {
height: @item-width; height: @item-width;
color: black; color: black;
display: flex;
align-items: center;
border-bottom: 1px solid #f3f3f3;
.left {
width: @avatar-width;
height: @avatar-width;
border-radius: 50%;
margin-right: 15rem;
}
.right {
font-size: 14rem;
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
img {
height: 20rem;
}
}
}
.more {
height: @item-width;
color: black;
background: white;
display: flex;
align-items: center;
border-bottom: 1px solid #f3f3f3;
.left {
width: 20rem;
height: 20rem;
border-radius: 50%;
margin-left: 10rem;
margin-right: 20rem;
}
}
}
@icon-width: 58rem;
:deep(.shares) {
@space-width: 15rem;
overflow-x: scroll;
display: flex; display: flex;
padding-right: @space-width * 2; align-items: center;
border-bottom: 1px solid #f3f3f3;
.to { .left {
margin-left: @space-width; width: @avatar-width;
margin-bottom: @space-width; height: @avatar-width;
border-radius: 50%;
margin-right: 15rem;
}
.wrapper { .right {
box-sizing: border-box; font-size: 14rem;
background: white; flex: 1;
width: @icon-width; display: flex;
height: @icon-width; align-items: center;
padding: 12rem; justify-content: space-between;
border-radius: 15rem;
display: flex;
align-items: center;
justify-content: center;
img { img {
width: 100%; height: 20rem;
//height: 100%;
}
}
span {
margin-top: 7rem;
color: black;
font-size: 10rem;
display: block;
text-align: center;
} }
} }
} }
.loading { .more {
width: 60%; height: @item-width;
height: 60%; color: black;
position: relative; background: white;
display: flex;
align-items: center;
border-bottom: 1px solid #f3f3f3;
@border-width: 3.1px; .left {
width: 20rem;
.quan1 { height: 20rem;
position: absolute;
box-sizing: border-box;
width: 100%;
height: 100%;
border: @border-width solid darkgrey;
border-radius: 50%;
}
.quan2 {
position: absolute;
box-sizing: border-box;
width: 100%;
height: 100%;
border: @border-width solid #514f56;
border-radius: 50%; border-radius: 50%;
margin-left: 10rem;
margin-right: 20rem;
} }
} }
} }
@icon-width: 58rem;
:deep(.shares) {
@space-width: 15rem;
overflow-x: scroll;
display: flex;
padding-right: @space-width * 2;
.to {
margin-left: @space-width;
margin-bottom: @space-width;
.wrapper {
box-sizing: border-box;
background: white;
width: @icon-width;
height: @icon-width;
padding: 12rem;
border-radius: 15rem;
display: flex;
align-items: center;
justify-content: center;
img {
width: 100%;
//height: 100%;
}
}
span {
margin-top: 7rem;
color: black;
font-size: 10rem;
display: block;
text-align: center;
}
}
}
.loading {
width: 60%;
height: 60%;
position: relative;
@border-width: 3.1px;
.quan1 {
position: absolute;
box-sizing: border-box;
width: 100%;
height: 100%;
border: @border-width solid darkgrey;
border-radius: 50%;
}
.quan2 {
position: absolute;
box-sizing: border-box;
width: 100%;
height: 100%;
border: @border-width solid #514f56;
border-radius: 50%;
}
}
}
</style> </style>

View File

@@ -113,16 +113,12 @@
<!-- <SlideItem></SlideItem>--> <!-- <SlideItem></SlideItem>-->
<Slide0 :active="state.navIndex === 0 && state.baseIndex === 1" /> <Slide0 :active="state.navIndex === 0 && state.baseIndex === 1" />
<SlideItem> <SlideItem>
<LongVideo <LongVideo :active="state.navIndex === 1 && state.baseIndex === 1" />
:active="state.navIndex === 1 && state.baseIndex === 1"
/>
</SlideItem> </SlideItem>
<!-- <SlideItem></SlideItem>--> <!-- <SlideItem></SlideItem>-->
<Slide2 :active="state.navIndex === 2 && state.baseIndex === 1" /> <Slide2 :active="state.navIndex === 2 && state.baseIndex === 1" />
<SlideItem> <SlideItem>
<Community <Community :active="state.navIndex === 3 && state.baseIndex === 1" />
:active="state.navIndex === 3 && state.baseIndex === 1"
/>
</SlideItem> </SlideItem>
<Slide4 :active="state.navIndex === 4 && state.baseIndex === 1" /> <Slide4 :active="state.navIndex === 4 && state.baseIndex === 1" />
</SlideHorizontal> </SlideHorizontal>
@@ -195,11 +191,7 @@
<BlockDialog v-model="state.showBlockDialog" /> <BlockDialog v-model="state.showBlockDialog" />
<ConfirmDialog <ConfirmDialog title="设置备注名" ok-text="确认" v-model:visible="state.showChangeNote">
title="设置备注名"
ok-text="确认"
v-model:visible="state.showChangeNote"
>
<Search mode="light" v-model="state.test" :isShowSearchIcon="false" /> <Search mode="light" v-model="state.test" :isShowSearchIcon="false" />
</ConfirmDialog> </ConfirmDialog>
@@ -208,261 +200,255 @@
</template> </template>
<script setup lang="jsx"> <script setup lang="jsx">
import SlideHorizontal from '@/components/slide/SlideHorizontal.vue' import SlideHorizontal from '@/components/slide/SlideHorizontal.vue'
import SlideItem from '@/components/slide/SlideItem.vue' import SlideItem from '@/components/slide/SlideItem.vue'
import Comment from '../../components/Comment.vue' import Comment from '../../components/Comment.vue'
import Share from '../../components/Share.vue' import Share from '../../components/Share.vue'
import IndicatorHome from './components/IndicatorHome.vue' import IndicatorHome from './components/IndicatorHome.vue'
import { import { onActivated, onDeactivated, onMounted, onUnmounted, reactive } from 'vue'
onActivated, import bus, { EVENT_KEY } from '../../utils/bus'
onDeactivated, import { useNav } from '@/utils/hooks/useNav'
onMounted, import PlayFeedback from '@/pages/home/components/PlayFeedback.vue'
onUnmounted, import ShareTo from '@/pages/home/components/ShareTo.vue'
reactive, import DouyinCode from '../../components/DouyinCode.vue'
} from 'vue' import FollowSetting from '@/pages/home/components/FollowSetting.vue'
import bus, { EVENT_KEY } from '../../utils/bus' import BlockDialog from '../message/components/BlockDialog.vue'
import { useNav } from '@/utils/hooks/useNav' import Search from '../../components/Search.vue'
import PlayFeedback from '@/pages/home/components/PlayFeedback.vue' import ConfirmDialog from '../../components/dialog/ConfirmDialog.vue'
import ShareTo from '@/pages/home/components/ShareTo.vue' import FollowSetting2 from '@/pages/home/components/FollowSetting2.vue'
import DouyinCode from '../../components/DouyinCode.vue' import ShareToFriend from '@/pages/home/components/ShareToFriend.vue'
import FollowSetting from '@/pages/home/components/FollowSetting.vue' import UserPanel from '@/components/UserPanel.vue'
import BlockDialog from '../message/components/BlockDialog.vue' import Community from '@/pages/home/slide/Community.vue'
import Search from '../../components/Search.vue' import Slide0 from '@/pages/home/slide/Slide0.vue'
import ConfirmDialog from '../../components/dialog/ConfirmDialog.vue' import Slide2 from '@/pages/home/slide/Slide2.vue'
import FollowSetting2 from '@/pages/home/components/FollowSetting2.vue' import Slide4 from '@/pages/home/slide/Slide4.vue'
import ShareToFriend from '@/pages/home/components/ShareToFriend.vue' import { DefaultUser } from '@/utils/const_var'
import UserPanel from '@/components/UserPanel.vue' import { $no } from '@/utils'
import Community from '@/pages/home/slide/Community.vue' import LongVideo from '@/pages/home/slide/LongVideo.vue'
import Slide0 from '@/pages/home/slide/Slide0.vue' import { useBaseStore } from '@/store/pinia'
import Slide2 from '@/pages/home/slide/Slide2.vue'
import Slide4 from '@/pages/home/slide/Slide4.vue'
import { DefaultUser } from '@/utils/const_var'
import { $no } from '@/utils'
import LongVideo from '@/pages/home/slide/LongVideo.vue'
import { useBaseStore } from '@/store/pinia'
const nav = useNav() const nav = useNav()
const baseStore = useBaseStore() const baseStore = useBaseStore()
const state = reactive({ const state = reactive({
active: true, active: true,
baseIndex: 1, baseIndex: 1,
navIndex: 4, navIndex: 4,
test: '', test: '',
recommendList: [], recommendList: [],
isSharing: false, isSharing: false,
canMove: true, canMove: true,
shareType: -1, shareType: -1,
showPlayFeedback: false, showPlayFeedback: false,
showShareDuoshan: false, showShareDuoshan: false,
showShareDialog: false, showShareDialog: false,
showShare2WeChatZone: false, showShare2WeChatZone: false,
showDouyinCode: false, showDouyinCode: false,
showFollowSetting: false, showFollowSetting: false,
showFollowSetting2: false, showFollowSetting2: false,
showBlockDialog: false, showBlockDialog: false,
showChangeNote: false, showChangeNote: false,
shareToFriend: false, shareToFriend: false,
commentVisible: false, commentVisible: false,
fullScreen: false, fullScreen: false,
currentItem: { currentItem: {
author: DefaultUser, author: DefaultUser,
isRequest: false,
aweme_list: []
}
})
function delayShowDialog(cb) {
setTimeout(cb, 400)
}
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) {
state.currentItem = {
...item,
isRequest: false, isRequest: false,
aweme_list: [], aweme_list: []
},
})
function delayShowDialog(cb) {
setTimeout(cb, 400)
}
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) {
state.currentItem = {
...item,
isRequest: false,
aweme_list: [],
}
} }
// console.log('item', item)
} }
// console.log('item', item)
}
onMounted(() => { onMounted(() => {
bus.on(EVENT_KEY.ENTER_FULLSCREEN, (e) => { bus.on(EVENT_KEY.ENTER_FULLSCREEN, (e) => {
if (!state.active) return if (!state.active) return
state.fullScreen = true 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 }) => {
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)
}) })
bus.on(EVENT_KEY.EXIT_FULLSCREEN, (e) => {
onUnmounted(() => { if (!state.active) return
bus.offAll() state.fullScreen = false
}) })
bus.on(EVENT_KEY.OPEN_COMMENTS, (e) => {
onActivated(() => { if (!state.active) return
state.active = true bus.emit(EVENT_KEY.ENTER_FULLSCREEN)
state.commentVisible = true
}) })
bus.on(EVENT_KEY.CLOSE_COMMENTS, (e) => {
onDeactivated(() => { if (!state.active) return
state.active = false 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 }) => {
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)
})
function closeComments() { onUnmounted(() => {
bus.emit(EVENT_KEY.CLOSE_COMMENTS) bus.offAll()
} })
function dislike() { onActivated(() => {
// listRef.value.dislike(state.list[1]) state.active = true
// state.list[state.index] = state.list[1] })
// Utils.$notice('操作成功,将减少此类视频的推荐')
} onDeactivated(() => {
state.active = false
})
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> </script>
<style scoped lang="less"> <style scoped lang="less">
.test-slide-wrapper { .test-slide-wrapper {
font-size: 14rem; font-size: 14rem;
width: 100%; width: 100%;
height: 100%; height: 100%;
background: black; background: black;
overflow: hidden; overflow: hidden;
.sidebar { .sidebar {
width: 80vw; width: 80vw;
height: calc(var(--vh, 1vh) * 100); height: calc(var(--vh, 1vh) * 100);
overflow: auto; overflow: auto;
background: rgb(22, 22, 22); background: rgb(22, 22, 22);
padding: 10rem; padding: 10rem;
padding-bottom: 20rem; padding-bottom: 20rem;
box-sizing: border-box; box-sizing: border-box;
& > .header { & > .header {
font-size: 16rem; font-size: 16rem;
display: flex;
color: white;
justify-content: space-between;
align-items: center;
.right {
border-radius: 20rem;
padding: 8rem 15rem;
background: rgb(36, 36, 36);
display: flex;
align-items: center;
font-size: 14rem;
gap: 10rem;
svg {
font-size: 18rem;
}
}
}
.card {
margin-top: 10rem;
border-radius: 12rem;
padding: 15rem;
background: rgb(29, 29, 29);
.header {
margin-bottom: 8rem;
font-size: 14rem;
display: flex; display: flex;
color: white; color: white;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
.right { .right {
border-radius: 20rem;
padding: 8rem 15rem;
background: rgb(36, 36, 36);
display: flex; display: flex;
align-items: center; align-items: center;
font-size: 14rem; font-size: 12rem;
gap: 10rem; gap: 4rem;
color: gray;
svg { svg {
font-size: 18rem; font-size: 16rem;
} }
} }
} }
.card { .content {
margin-top: 10rem; color: white;
border-radius: 12rem; display: grid;
padding: 15rem; grid-template-columns: 1fr 1fr 1fr;
background: rgb(29, 29, 29);
.header { .item {
margin-bottom: 8rem; min-height: 20vw;
font-size: 14rem;
display: flex; display: flex;
color: white; flex-direction: column;
justify-content: space-between; justify-content: center;
align-items: center; align-items: center;
font-size: 14rem;
gap: 8rem;
.right { svg {
display: flex; font-size: 28rem;
align-items: center; }
font-size: 12rem;
gap: 4rem;
color: gray;
svg { .xcx {
font-size: 16rem; border-radius: 12rem;
} width: 50rem;
height: 50rem;
} }
} }
.content { .avatar {
color: white; height: 25vw;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
.item { img {
min-height: 20vw; border-radius: 50%;
display: flex; width: 50rem;
flex-direction: column;
justify-content: center;
align-items: center;
font-size: 14rem;
gap: 8rem;
svg {
font-size: 28rem;
}
.xcx {
border-radius: 12rem;
width: 50rem;
height: 50rem;
}
}
.avatar {
height: 25vw;
img {
border-radius: 50%;
width: 50rem;
}
} }
} }
} }
} }
.slide-content {
width: 100%;
height: 100%;
}
} }
.first-horizontal-item { .slide-content {
//width: 90vw; width: 100%;
//height: 80vh; height: 100%;
width: 100vw;
height: calc(var(--vh, 1vh) * 100 - var(--footer-height)) !important;
overflow: hidden;
border-radius: 10rem;
} }
}
.first-horizontal-item {
//width: 90vw;
//height: 80vh;
width: 100vw;
height: calc(var(--vh, 1vh) * 100 - var(--footer-height)) !important;
overflow: hidden;
border-radius: 10rem;
}
</style> </style>

View File

@@ -12,20 +12,14 @@
<WaterfallList :list="list" class="list"> <WaterfallList :list="list" class="list">
<template v-slot="{ item }"> <template v-slot="{ item }">
<div class="card" @click="(e) => test(e, item)"> <div class="card" @click="(e) => test(e, item)">
<img <img class="poster" v-lazy="_checkImgUrl(item.note_card?.cover?.url_default)" />
class="poster"
v-lazy="_checkImgUrl(item.note_card?.cover?.url_default)"
/>
<div class="bottom"> <div class="bottom">
<div class="title"> <div class="title">
{{ item.note_card?.display_title }} {{ item.note_card?.display_title }}
</div> </div>
<div class="b2"> <div class="b2">
<div class="user"> <div class="user">
<img <img class="avatar" :src="_checkImgUrl(item.note_card?.user?.avatar)" />
class="avatar"
:src="_checkImgUrl(item.note_card?.user?.avatar)"
/>
<div class="name">{{ item.note_card?.user?.nickname }}</div> <div class="name">{{ item.note_card?.user?.nickname }}</div>
</div> </div>
<div class="star"> <div class="star">
@@ -52,266 +46,266 @@
</template> </template>
<script setup> <script setup>
import { reactive, ref, watch } from 'vue' import { reactive, ref, watch } from 'vue'
import { $no, _checkImgUrl, cloneDeep } from '@/utils' import { $no, _checkImgUrl, cloneDeep } from '@/utils'
import { recommendedPost } from '@/api/user' import { recommendedPost } from '@/api/user'
import { useNav } from '@/utils/hooks/useNav' import { useNav } from '@/utils/hooks/useNav'
import { Icon } from '@iconify/vue' import { Icon } from '@iconify/vue'
import WaterfallList from '@/components/WaterfallList.vue' import WaterfallList from '@/components/WaterfallList.vue'
import ScrollList from '@/components/ScrollList.vue' import ScrollList from '@/components/ScrollList.vue'
import { useBaseStore } from '@/store/pinia' import { useBaseStore } from '@/store/pinia'
import AlbumDetail from '@/pages/other/AlbumDetail.vue' import AlbumDetail from '@/pages/other/AlbumDetail.vue'
import Mock from 'mockjs' import Mock from 'mockjs'
//@click="nav('album-detail',{},item)" //@click="nav('album-detail',{},item)"
const nav = useNav() const nav = useNav()
const baseStore = useBaseStore() const baseStore = useBaseStore()
const props = defineProps({ const props = defineProps({
active: { active: {
type: Boolean, type: Boolean,
default: false, default: false
}, }
}) })
const state = reactive({ const state = reactive({
show: false, show: false,
current: { current: {
id: '', id: '',
note_card: { note_card: {
interact_info: {}, interact_info: {},
cover: {}, cover: {},
image_list: [], image_list: [],
display_title: '', display_title: '',
user: {}, user: {},
comment_list: [], comment_list: [],
createTime: '', createTime: ''
}, }
}, },
d: false, d: false
}) })
let rect = ref({}) let rect = ref({})
watch( watch(
() => props.active, () => props.active,
(n) => { (n) => {
if (n && !state.show) { if (n && !state.show) {
state.show = true state.show = true
}
},
{ immediate: true }
)
function close() {
let s = $('.shadow ')
let domRect = rect.value
let t = '.3'
s.css('transition', `all ${t}s`)
s.css('top', domRect.top)
s.css('left', domRect.left)
s.css('width', domRect.width)
s.css('height', domRect.height)
let a = $('.goods-detail')
a.css('transition', `all ${t}s`)
a.css('opacity', '0')
a.css('width', '100vw')
a.css('height', '100vh')
a.css('transform', `scale(${domRect.sw},${domRect.sh})`)
a.css('transform-origin', `0 0`)
let d = $('.shadow .wrap')
d.css('transition', `all ${t}s`)
d.css('opacity', '1')
// state.d = false
setTimeout(() => {
s.css('z-index', '-100')
s.css('transition', 'all 0s')
s.css('top', '-200vh')
}, 300)
}
function test(e, item) {
let data = Mock.mock({
'comment_list|3-50': [
{
name: '@cname',
text: '@cparagraph(3)'
} }
}, ]
{ immediate: true }, })
) item.note_card.comment_list = data.comment_list
item.note_card.createTime = Mock.Random.date('MM-dd')
item.note_card.interact_info.collect_count = Mock.Random.integer(60, 3000)
item.note_card.interact_info.share_count = Mock.Random.integer(60, 3000)
state.current = cloneDeep(item)
// console.log(state.current)
function close() { state.d = true
let s = $('.shadow ') let domRect = e.currentTarget.getBoundingClientRect()
let domRect = rect.value // console.log('e', domRect)
let t = '.3' let s = $('.shadow ')
s.css('z-index', '1')
s.css('transition', '0s')
s.css('top', domRect.top)
s.css('left', domRect.left)
s.css('width', domRect.width)
s.css('height', domRect.height)
let t = '.3'
let d = $('.shadow .wrap')
d.empty()
d.show()
d.append($(e.currentTarget).clone())
d.css('transition', `all ${t}s`)
d.css('opacity', '1')
let sw = domRect.width / baseStore.bodyWidth
let sh = domRect.height / baseStore.bodyHeight
domRect.sw = sw
domRect.sh = sh
let a = $('.goods-detail')
a.css('opacity', '0')
a.css('width', '100vw')
a.css('height', '100vh')
a.css('transform', `scale(${domRect.sw},${domRect.sh})`)
a.css('transform-origin', `0 0`)
rect.value = domRect
setTimeout(() => {
s.css('transition', `all ${t}s`) s.css('transition', `all ${t}s`)
s.css('top', domRect.top) s.css('top', 0)
s.css('left', domRect.left) s.css('left', 0)
s.css('width', domRect.width) s.css('width', '100vw')
s.css('height', domRect.height) s.css('height', '100vh')
d.css('opacity', '0')
d.css('z-index', '-1')
let a = $('.goods-detail')
a.css('transition', `all ${t}s`) a.css('transition', `all ${t}s`)
a.css('opacity', '0') a.css('opacity', '1')
a.css('width', '100vw') a.css('transform', `scale(1,1)`)
a.css('height', '100vh')
a.css('transform', `scale(${domRect.sw},${domRect.sh})`)
a.css('transform-origin', `0 0`) a.css('transform-origin', `0 0`)
})
let d = $('.shadow .wrap') }
d.css('transition', `all ${t}s`)
d.css('opacity', '1')
// state.d = false
setTimeout(() => {
s.css('z-index', '-100')
s.css('transition', 'all 0s')
s.css('top', '-200vh')
}, 300)
}
function test(e, item) {
let data = Mock.mock({
'comment_list|3-50': [
{
name: '@cname',
text: '@cparagraph(3)',
},
],
})
item.note_card.comment_list = data.comment_list
item.note_card.createTime = Mock.Random.date('MM-dd')
item.note_card.interact_info.collect_count = Mock.Random.integer(60, 3000)
item.note_card.interact_info.share_count = Mock.Random.integer(60, 3000)
state.current = cloneDeep(item)
// console.log(state.current)
state.d = true
let domRect = e.currentTarget.getBoundingClientRect()
// console.log('e', domRect)
let s = $('.shadow ')
s.css('z-index', '1')
s.css('transition', '0s')
s.css('top', domRect.top)
s.css('left', domRect.left)
s.css('width', domRect.width)
s.css('height', domRect.height)
let t = '.3'
let d = $('.shadow .wrap')
d.empty()
d.show()
d.append($(e.currentTarget).clone())
d.css('transition', `all ${t}s`)
d.css('opacity', '1')
let sw = domRect.width / baseStore.bodyWidth
let sh = domRect.height / baseStore.bodyHeight
domRect.sw = sw
domRect.sh = sh
let a = $('.goods-detail')
a.css('opacity', '0')
a.css('width', '100vw')
a.css('height', '100vh')
a.css('transform', `scale(${domRect.sw},${domRect.sh})`)
a.css('transform-origin', `0 0`)
rect.value = domRect
setTimeout(() => {
s.css('transition', `all ${t}s`)
s.css('top', 0)
s.css('left', 0)
s.css('width', '100vw')
s.css('height', '100vh')
d.css('opacity', '0')
d.css('z-index', '-1')
a.css('transition', `all ${t}s`)
a.css('opacity', '1')
a.css('transform', `scale(1,1)`)
a.css('transform-origin', `0 0`)
})
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
#Community { #Community {
font-size: 14rem; font-size: 14rem;
color: white; color: white;
padding-top: var(--home-header-height); padding-top: var(--home-header-height);
background: rgb(21, 23, 36); background: rgb(21, 23, 36);
.Scroll { .Scroll {
height: calc( height: calc(
var(--vh, 1vh) * 100 - var(--home-header-height) - var(--footer-height) var(--vh, 1vh) * 100 - var(--home-header-height) - var(--footer-height)
) !important; ) !important;
}
@p: 1rem;
.search {
margin-left: 2vw;
width: 96vw;
box-sizing: border-box;
padding: 10rem;
border: 1px solid #646464;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 16rem;
margin-bottom: 10rem;
border-radius: 8rem;
.left {
display: flex;
align-items: center;
gap: 5rem;
color: gray;
svg {
font-size: 16rem;
}
}
}
.list {
margin-left: 2vw;
width: 96vw;
}
}
.card {
border-radius: 4rem;
overflow: hidden;
background: var(--main-bg);
.poster {
display: block;
width: 100%;
object-fit: cover;
//height: 33vh;
}
.bottom {
color: gainsboro;
padding: 10rem;
.title {
font-size: 14rem;
margin-bottom: 8rem;
} }
@p: 1rem; .b2 {
.search {
margin-left: 2vw;
width: 96vw;
box-sizing: border-box;
padding: 10rem;
border: 1px solid #646464;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
font-size: 16rem;
margin-bottom: 10rem;
border-radius: 8rem;
.left { .user {
display: flex;
font-size: 12rem;
img {
width: 15rem;
border-radius: 50%;
margin-right: 5rem;
}
}
.star {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 5rem; gap: 3rem;
color: gray;
svg { svg {
font-size: 16rem; font-size: 15rem;
} }
}
}
.list { .num {
margin-left: 2vw;
width: 96vw;
}
}
.card {
border-radius: 4rem;
overflow: hidden;
background: var(--main-bg);
.poster {
display: block;
width: 100%;
object-fit: cover;
//height: 33vh;
}
.bottom {
color: gainsboro;
padding: 10rem;
.title {
font-size: 14rem;
margin-bottom: 8rem;
}
.b2 {
display: flex;
justify-content: space-between;
align-items: center;
.user {
display: flex;
font-size: 12rem; font-size: 12rem;
img {
width: 15rem;
border-radius: 50%;
margin-right: 5rem;
}
}
.star {
display: flex;
align-items: center;
gap: 3rem;
svg {
font-size: 15rem;
}
.num {
font-size: 12rem;
}
} }
} }
} }
} }
}
.shadow { .shadow {
background: var(--color-message); background: var(--color-message);
position: absolute;
left: 0;
top: -200vh;
width: 100vw;
transition: all 0.3s;
overflow: hidden;
z-index: -100;
.wrap {
position: absolute; position: absolute;
left: 0; z-index: 9999;
top: -200vh;
width: 100vw;
transition: all 0.3s;
overflow: hidden;
z-index: -100;
.wrap {
position: absolute;
z-index: 9999;
}
} }
}
</style> </style>

View File

@@ -1,89 +1,89 @@
<script setup> <script setup>
import { onMounted, reactive, ref, watch } from 'vue' import { onMounted, reactive, ref, watch } from 'vue'
import { _checkImgUrl, _duration, _formatNumber } from '@/utils' import { _checkImgUrl, _duration, _formatNumber } from '@/utils'
import { recommendedVideo } from '@/api/videos' import { recommendedVideo } from '@/api/videos'
import { useBaseStore } from '@/store/pinia' import { useBaseStore } from '@/store/pinia'
import ScrollList from '@/components/ScrollList.vue' import ScrollList from '@/components/ScrollList.vue'
import { useNav } from '@/utils/hooks/useNav' import { useNav } from '@/utils/hooks/useNav'
const baseStore = useBaseStore() const baseStore = useBaseStore()
const props = defineProps({ const props = defineProps({
active: Boolean, active: Boolean
}) })
const p = { const p = {
onShowComments() { onShowComments() {
console.log('onShowComments') console.log('onShowComments')
},
} }
}
const playingEl = ref() const playingEl = ref()
const state = reactive({ const state = reactive({
show: false, show: false,
muted: true, muted: true,
danmu: false, danmu: false
}) })
watch( watch(
() => props.active, () => props.active,
(n) => { (n) => {
if (n) { if (n) {
if (state.show) { if (state.show) {
let el = playingEl.value
if (el) {
el.parentNode.parentNode.classList.remove('pause')
el.play()
}
} else {
state.show = true
}
} else {
let el = playingEl.value let el = playingEl.value
if (el) { if (el) {
el.parentNode.parentNode.classList.remove('pause')
el.play()
}
} else {
state.show = true
}
} else {
let el = playingEl.value
if (el) {
el.parentNode.parentNode.classList.add('pause')
el.pause()
}
}
},
{ immediate: true }
)
const obList = []
const vIsCanPlay = {
mounted(el, binding, vnode, prevVnode) {
const observer = new IntersectionObserver(
(entries) => {
if (entries[0].isIntersecting) {
let videoEls = document.querySelectorAll('.long-video video')
videoEls.forEach((item) => {
item.pause()
if (item.parentNode?.parentNode) {
item.parentNode.parentNode.classList.add('pause')
}
})
el.parentNode.parentNode.classList.remove('pause')
el.play()
playingEl.value = el
} else {
el.parentNode.parentNode.classList.add('pause') el.parentNode.parentNode.classList.add('pause')
el.pause() el.pause()
} }
} },
}, { threshold: 0.5 }
{ immediate: true }, )
) observer.observe(el)
obList.push(observer)
const obList = [] },
unmounted(el, binding, vnode, prevVnode) {
const vIsCanPlay = { obList.map((v) => {
mounted(el, binding, vnode, prevVnode) { v.disconnect()
const observer = new IntersectionObserver( })
(entries) => {
if (entries[0].isIntersecting) {
let videoEls = document.querySelectorAll('.long-video video')
videoEls.forEach((item) => {
item.pause()
if (item.parentNode?.parentNode) {
item.parentNode.parentNode.classList.add('pause')
}
})
el.parentNode.parentNode.classList.remove('pause')
el.play()
playingEl.value = el
} else {
el.parentNode.parentNode.classList.add('pause')
el.pause()
}
},
{ threshold: 0.5 },
)
observer.observe(el)
obList.push(observer)
},
unmounted(el, binding, vnode, prevVnode) {
obList.map((v) => {
v.disconnect()
})
},
} }
}
const nav = useNav() const nav = useNav()
</script> </script>
<template> <template>
@@ -97,7 +97,7 @@
:class="[ :class="[
i % 9 === 0 && 'big', i % 9 === 0 && 'big',
i % 9 === 0 ? '' : i % 2 === 1 && 'l', i % 9 === 0 ? '' : i % 2 === 1 && 'l',
i % 9 === 0 ? '' : i % 2 === 0 && 'r', i % 9 === 0 ? '' : i % 2 === 0 && 'r'
]" ]"
v-for="(item, i) in list" v-for="(item, i) in list"
> >
@@ -120,10 +120,7 @@
<div class="left"></div> <div class="left"></div>
<div class="right"> <div class="right">
<div class="option" @click.stop="state.danmu = !state.danmu"> <div class="option" @click.stop="state.danmu = !state.danmu">
<img <img v-if="state.danmu" src="@/assets/img/icon/danmu-open.svg" />
v-if="state.danmu"
src="@/assets/img/icon/danmu-open.svg"
/>
<img v-else src="@/assets/img/icon/danmu-close.svg" /> <img v-else src="@/assets/img/icon/danmu-close.svg" />
</div> </div>
<div class="option" @click.stop="state.muted = !state.muted"> <div class="option" @click.stop="state.muted = !state.muted">
@@ -136,12 +133,7 @@
</div> </div>
</div> </div>
</div> </div>
<img <img v-else v-lazy="_checkImgUrl(item.video.cover.url_list[0])" alt="" class="poster" />
v-else
v-lazy="_checkImgUrl(item.video.cover.url_list[0])"
alt=""
class="poster"
/>
<div class="duration">{{ _duration(item.duration / 1000) }}</div> <div class="duration">{{ _duration(item.duration / 1000) }}</div>
<div class="title"> <div class="title">
{{ item.desc }} {{ item.desc }}
@@ -170,176 +162,176 @@
</template> </template>
<style scoped lang="less"> <style scoped lang="less">
.long-video { .long-video {
font-size: 14rem; font-size: 14rem;
color: white; color: white;
padding-top: var(--home-header-height); padding-top: var(--home-header-height);
background: rgb(21, 23, 36); background: rgb(21, 23, 36);
.Scroll { .Scroll {
height: calc( height: calc(
var(--vh, 1vh) * 100 - var(--home-header-height) - var(--footer-height) var(--vh, 1vh) * 100 - var(--home-header-height) - var(--footer-height)
) !important; ) !important;
}
} }
}
.list { .list {
display: grid; display: grid;
grid-template-columns: repeat(2, 1fr); grid-template-columns: repeat(2, 1fr);
row-gap: 15rem; row-gap: 15rem;
box-sizing: border-box; box-sizing: border-box;
.item { .item {
margin: 0 10rem; margin: 0 10rem;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 8rem; gap: 8rem;
position: relative;
.poster {
border-radius: 12rem;
width: 100%;
height: 140rem;
object-fit: cover;
}
.video-wrapper {
height: 220rem;
position: relative; position: relative;
.poster { video {
border-radius: 12rem;
width: 100%; width: 100%;
height: 140rem; height: 100%;
object-fit: cover; object-fit: cover;
} }
.video-wrapper { .options {
height: 220rem; width: 100%;
position: relative; box-sizing: border-box;
padding: 0 12rem;
display: flex;
position: absolute;
bottom: 8rem;
justify-content: space-between;
align-items: center;
color: white;
video { .right {
width: 100%; display: flex;
height: 100%; align-items: center;
gap: 10rem;
}
img {
width: 20rem;
}
svg {
font-size: 20rem;
}
}
}
.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; 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;
&.pause {
.duration {
display: block;
} }
.options { .options {
width: 100%; display: none;
box-sizing: border-box;
padding: 0 12rem;
display: flex;
position: absolute;
bottom: 8rem;
justify-content: space-between;
align-items: center;
color: white;
.right {
display: flex;
align-items: center;
gap: 10rem;
}
img {
width: 20rem;
}
svg {
font-size: 20rem;
}
} }
} }
.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 { .duration {
color: white; display: none;
position: absolute; bottom: 67rem;
bottom: 80rem;
right: 10rem;
font-size: 13rem;
} }
.title {
height: unset;
-webkit-line-clamp: 1;
}
.title,
.bottom { .bottom {
color: gray; padding: 0 10rem;
.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;
&.pause {
.duration {
display: block;
}
.options {
display: none;
}
}
.duration {
display: none;
bottom: 67rem;
}
.title {
height: unset;
-webkit-line-clamp: 1;
}
.title,
.bottom {
padding: 0 10rem;
}
}
&.l {
margin-right: 5rem;
}
&.r {
margin-left: 5rem;
} }
} }
&.l {
margin-right: 5rem;
}
&.r {
margin-left: 5rem;
}
} }
}
</style> </style>

View File

@@ -1,10 +1,6 @@
<template> <template>
<SlideItem class="slide-item-class"> <SlideItem class="slide-item-class">
<div <div class="sub-type" :class="state.subTypeIsTop ? 'top' : ''" ref="subTypeRef">
class="sub-type"
:class="state.subTypeIsTop ? 'top' : ''"
ref="subTypeRef"
>
<div class="local"> <div class="local">
<div class="card" @touchmove.capture="stop"> <div class="card" @touchmove.capture="stop">
<div class="nav-item"> <div class="nav-item">
@@ -53,7 +49,7 @@
:active="props.active" :active="props.active"
:style="{ :style="{
background: 'black', background: 'black',
marginTop: state.subTypeVisible ? state.subTypeHeight : 0, marginTop: state.subTypeVisible ? state.subTypeHeight : 0
}" }"
:api="recommendedVideo" :api="recommendedVideo"
@touchstart="pageClick" @touchstart="pageClick"
@@ -62,148 +58,138 @@
</template> </template>
<script setup lang="jsx"> <script setup lang="jsx">
import SlideItem from '@/components/slide/SlideItem.vue' import SlideItem from '@/components/slide/SlideItem.vue'
import { onMounted, onUnmounted, reactive, ref } from 'vue' import { onMounted, onUnmounted, reactive, ref } from 'vue'
import bus, { EVENT_KEY } from '@/utils/bus' import bus, { EVENT_KEY } from '@/utils/bus'
import Utils from '@/utils' import Utils from '@/utils'
import SlideList from './SlideList.vue' import SlideList from './SlideList.vue'
import { recommendedVideo } from '@/api/videos' import { recommendedVideo } from '@/api/videos'
const props = defineProps({ const props = defineProps({
cbs: { cbs: {
type: Object, type: Object,
default() { default() {
return {} return {}
},
},
active: {
type: Boolean,
default: false,
},
})
const emit = defineEmits([
'update:item',
'goUserInfo',
'showComments',
'showShare',
'goMusic',
])
function stop(e) {
e.stopPropagation()
}
const p = {
onShowComments() {
console.log('onShowComments')
},
}
const subTypeRef = ref(null)
const state = reactive({
index: 0,
subType: -1,
subTypeVisible: false,
subTypeHeight: '0',
//用于改变zindex的层级到上层反正比slide高就行。不然摸不到subType.
subTypeIsTop: false,
})
function showSubType(e) {
Utils.$stopPropagation(e)
console.log('subTypeRef')
state.subTypeHeight = subTypeRef.value.getBoundingClientRect().height + 'px'
state.subTypeVisible = true
setTimeout(() => (state.subTypeIsTop = true), 300)
bus.emit(EVENT_KEY.OPEN_SUB_TYPE)
}
function pageClick(e) {
// console.log('pageClick')
if (state.subTypeVisible) {
state.subTypeIsTop = state.subTypeVisible = false
bus.emit(EVENT_KEY.CLOSE_SUB_TYPE)
Utils.$stopPropagation(e)
} }
},
active: {
type: Boolean,
default: false
} }
})
const emit = defineEmits(['update:item', 'goUserInfo', 'showComments', 'showShare', 'goMusic'])
onMounted(() => { function stop(e) {
// getData() e.stopPropagation()
}) }
onUnmounted(() => {})
const p = {
onShowComments() {
console.log('onShowComments')
}
}
const subTypeRef = ref(null)
const state = reactive({
index: 0,
subType: -1,
subTypeVisible: false,
subTypeHeight: '0',
//用于改变zindex的层级到上层反正比slide高就行。不然摸不到subType.
subTypeIsTop: false
})
function showSubType(e) {
Utils.$stopPropagation(e)
console.log('subTypeRef')
state.subTypeHeight = subTypeRef.value.getBoundingClientRect().height + 'px'
state.subTypeVisible = true
setTimeout(() => (state.subTypeIsTop = true), 300)
bus.emit(EVENT_KEY.OPEN_SUB_TYPE)
}
function pageClick(e) {
// console.log('pageClick')
if (state.subTypeVisible) {
state.subTypeIsTop = state.subTypeVisible = false
bus.emit(EVENT_KEY.CLOSE_SUB_TYPE)
Utils.$stopPropagation(e)
}
}
onMounted(() => {
// getData()
})
onUnmounted(() => {})
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
.slide-item-class { .slide-item-class {
position: relative; position: relative;
.sub-type { .sub-type {
width: 100%; width: 100%;
position: absolute; position: absolute;
top: 0; top: 0;
&.top { &.top {
z-index: 2; z-index: 2;
}
.local {
transition: all 0.3s;
font-size: 14rem;
color: gray;
//background: #f9f9f9;
background: linear-gradient(to right, rgb(36, 34, 84), rgb(7, 5, 16));
display: flex;
justify-content: center;
align-items: center;
.card {
margin: 20rem;
margin-top: var(--common-header-height);
padding: 20rem;
border-radius: 8rem;
width: 100%;
//background: white;
background: linear-gradient(
to right,
rgb(53, 51, 110),
rgb(29, 21, 66)
);
box-sizing: border-box;
display: flex;
align-items: flex-end;
justify-content: space-between;
overflow: auto;
}
.nav-item {
@width: 35rem;
display: flex;
align-items: center;
flex-direction: column;
flex-shrink: 0;
width: 17vw;
img {
width: @width;
height: @width;
margin-bottom: 5rem;
}
}
}
} }
.sub-type-notice { .local {
position: absolute; transition: all 0.3s;
background: rgba(black, 0.4); font-size: 14rem;
top: 100rem; color: gray;
left: 50%; //background: #f9f9f9;
transform: translateX(-50%); background: linear-gradient(to right, rgb(36, 34, 84), rgb(7, 5, 16));
padding: 3rem 12rem;
border-radius: 10rem; display: flex;
z-index: 3; justify-content: center;
font-size: 12rem; align-items: center;
color: white;
.card {
margin: 20rem;
margin-top: var(--common-header-height);
padding: 20rem;
border-radius: 8rem;
width: 100%;
//background: white;
background: linear-gradient(to right, rgb(53, 51, 110), rgb(29, 21, 66));
box-sizing: border-box;
display: flex;
align-items: flex-end;
justify-content: space-between;
overflow: auto;
}
.nav-item {
@width: 35rem;
display: flex;
align-items: center;
flex-direction: column;
flex-shrink: 0;
width: 17vw;
img {
width: @width;
height: @width;
margin-bottom: 5rem;
}
}
} }
} }
.sub-type-notice {
position: absolute;
background: rgba(black, 0.4);
top: 100rem;
left: 50%;
transform: translateX(-50%);
padding: 3rem 12rem;
border-radius: 10rem;
z-index: 3;
font-size: 12rem;
color: white;
}
}
</style> </style>

View File

@@ -1,10 +1,6 @@
<template> <template>
<SlideItem class="slide-item-class"> <SlideItem class="slide-item-class">
<div <div class="sub-type" :class="state.subTypeIsTop ? 'top' : ''" ref="subTypeRef">
class="sub-type"
:class="state.subTypeIsTop ? 'top' : ''"
ref="subTypeRef"
>
<div class="card" @touchmove.capture="stop"> <div class="card" @touchmove.capture="stop">
<div class="nav-item" v-for="i in store.users"> <div class="nav-item" v-for="i in store.users">
<img :src="_checkImgUrl(i.avatar_168x168.url_list[0])" alt="" /> <img :src="_checkImgUrl(i.avatar_168x168.url_list[0])" alt="" />
@@ -24,7 +20,7 @@
:active="props.active" :active="props.active"
:style="{ :style="{
background: 'black', background: 'black',
marginTop: state.subTypeVisible ? state.subTypeHeight : 0, marginTop: state.subTypeVisible ? state.subTypeHeight : 0
}" }"
:api="recommendedVideo" :api="recommendedVideo"
@touchstart="pageClick" @touchstart="pageClick"
@@ -33,123 +29,123 @@
</template> </template>
<script setup lang="jsx"> <script setup lang="jsx">
import SlideItem from '@/components/slide/SlideItem.vue' import SlideItem from '@/components/slide/SlideItem.vue'
import { onMounted, onUnmounted, reactive, ref } from 'vue' import { onMounted, onUnmounted, reactive, ref } from 'vue'
import bus, { EVENT_KEY } from '@/utils/bus' import bus, { EVENT_KEY } from '@/utils/bus'
import Utils, { _checkImgUrl } from '@/utils' import Utils, { _checkImgUrl } from '@/utils'
import SlideList from './SlideList.vue' import SlideList from './SlideList.vue'
import { recommendedVideo } from '@/api/videos' import { recommendedVideo } from '@/api/videos'
import { useBaseStore } from '@/store/pinia' import { useBaseStore } from '@/store/pinia'
const store = useBaseStore() const store = useBaseStore()
const props = defineProps({ const props = defineProps({
active: { active: {
type: Boolean, type: Boolean,
default: false, default: false
},
})
function stop(e) {
e.stopPropagation()
} }
})
const subTypeRef = ref(null) function stop(e) {
const state = reactive({ e.stopPropagation()
index: 0, }
subType: -1,
subTypeVisible: false,
subTypeHeight: '0',
//用于改变zindex的层级到上层反正比slide高就行。不然摸不到subType.
subTypeIsTop: false,
})
function showSubType(e) { const subTypeRef = ref(null)
const state = reactive({
index: 0,
subType: -1,
subTypeVisible: false,
subTypeHeight: '0',
//用于改变zindex的层级到上层反正比slide高就行。不然摸不到subType.
subTypeIsTop: false
})
function showSubType(e) {
Utils.$stopPropagation(e)
console.log('subTypeRef')
state.subTypeHeight = subTypeRef.value.getBoundingClientRect().height + 'px'
state.subTypeVisible = true
setTimeout(() => (state.subTypeIsTop = true), 300)
bus.emit(EVENT_KEY.OPEN_SUB_TYPE)
}
function pageClick(e) {
// console.log('pageClick')
if (state.subTypeVisible) {
state.subTypeIsTop = state.subTypeVisible = false
bus.emit(EVENT_KEY.CLOSE_SUB_TYPE)
Utils.$stopPropagation(e) Utils.$stopPropagation(e)
console.log('subTypeRef')
state.subTypeHeight = subTypeRef.value.getBoundingClientRect().height + 'px'
state.subTypeVisible = true
setTimeout(() => (state.subTypeIsTop = true), 300)
bus.emit(EVENT_KEY.OPEN_SUB_TYPE)
} }
}
function pageClick(e) { onMounted(() => {
// console.log('pageClick') // getData()
if (state.subTypeVisible) { })
state.subTypeIsTop = state.subTypeVisible = false onUnmounted(() => {})
bus.emit(EVENT_KEY.CLOSE_SUB_TYPE)
Utils.$stopPropagation(e)
}
}
onMounted(() => {
// getData()
})
onUnmounted(() => {})
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
.slide-item-class { .slide-item-class {
position: relative; position: relative;
.sub-type { .sub-type {
width: 100%; width: 100%;
position: absolute; position: absolute;
top: 0; top: 0;
font-size: 12rem; font-size: 12rem;
color: white; color: white;
&.top { &.top {
z-index: 2; z-index: 2;
}
.card {
margin-top: var(--common-header-height);
padding: 20rem 5rem;
width: 100%;
background: rgba(black, 0.4);
box-sizing: border-box;
display: flex;
overflow: auto;
gap: 10rem;
padding-left: 20rem;
}
.nav-item {
@width: 50rem;
width: @width + 5rem;
margin: 0 5rem;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
flex-shrink: 0;
span {
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
img {
width: @width;
height: @width;
border-radius: 50%;
}
}
} }
.sub-type-notice { .card {
position: absolute; margin-top: var(--common-header-height);
padding: 20rem 5rem;
width: 100%;
background: rgba(black, 0.4); background: rgba(black, 0.4);
top: 100rem; box-sizing: border-box;
left: 50%; display: flex;
transform: translateX(-50%); overflow: auto;
padding: 3rem 12rem; gap: 10rem;
border-radius: 10rem; padding-left: 20rem;
z-index: 3; }
font-size: 12rem;
color: white; .nav-item {
@width: 50rem;
width: @width + 5rem;
margin: 0 5rem;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
flex-shrink: 0;
span {
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
img {
width: @width;
height: @width;
border-radius: 50%;
}
} }
} }
.sub-type-notice {
position: absolute;
background: rgba(black, 0.4);
top: 100rem;
left: 50%;
transform: translateX(-50%);
padding: 3rem 12rem;
border-radius: 10rem;
z-index: 3;
font-size: 12rem;
color: white;
}
}
</style> </style>

View File

@@ -1,22 +1,18 @@
<template> <template>
<SlideItem> <SlideItem>
<SlideList <SlideList style="background: #000" :active="props.active" :api="recommendedVideo" />
style="background: #000"
:active="props.active"
:api="recommendedVideo"
/>
</SlideItem> </SlideItem>
</template> </template>
<script setup lang="jsx"> <script setup lang="jsx">
import SlideItem from '@/components/slide/SlideItem.vue' import SlideItem from '@/components/slide/SlideItem.vue'
import SlideList from './SlideList.vue' import SlideList from './SlideList.vue'
import { recommendedVideo } from '@/api/videos' import { recommendedVideo } from '@/api/videos'
const props = defineProps({ const props = defineProps({
active: { active: {
type: Boolean, type: Boolean,
default: false, default: false
}, }
}) })
</script> </script>

View File

@@ -16,115 +16,115 @@
</template> </template>
<script setup lang="jsx"> <script setup lang="jsx">
import SlideVerticalInfinite from '@/components/slide/SlideVerticalInfinite.vue' import SlideVerticalInfinite from '@/components/slide/SlideVerticalInfinite.vue'
import { onMounted, onUnmounted, reactive, ref } from 'vue' import { onMounted, onUnmounted, reactive, ref } from 'vue'
import bus, { EVENT_KEY } from '@/utils/bus' import bus, { EVENT_KEY } from '@/utils/bus'
import { $notice } from '@/utils' import { $notice } from '@/utils'
import { useSlideListItemRender } from '@/utils/hooks/useSlideListItemRender' import { useSlideListItemRender } from '@/utils/hooks/useSlideListItemRender'
import { useBaseStore } from '@/store/pinia' import { useBaseStore } from '@/store/pinia'
const props = defineProps({ const props = defineProps({
cbs: { cbs: {
type: Object, type: Object,
default() { default() {
return {} return {}
},
},
active: {
type: Boolean,
default: false,
},
api: {
type: Function,
default: void 0,
},
index: {
type: Number,
default: 0,
},
list: {
type: Array,
default: [],
},
})
const baseStore = useBaseStore()
const p = {
onShowComments() {
console.log('onShowComments')
},
}
const render = useSlideListItemRender({ ...props.cbs, ...p })
const listRef = ref(null)
const state = reactive({
index: props.index,
list: props.list,
uniqueId: 'uniqueId1',
totalSize: 0,
pageSize: 10,
pageNo: 0,
})
function loadMore() {
if (!baseStore.loading) {
state.pageNo++
getData()
} }
},
active: {
type: Boolean,
default: false
},
api: {
type: Function,
default: void 0
},
index: {
type: Number,
default: 0
},
list: {
type: Array,
default: []
} }
})
async function getData(refresh = false) { const baseStore = useBaseStore()
if (baseStore.loading) return
baseStore.loading = true const p = {
let res = await props.api({ onShowComments() {
pageNo: refresh ? 0 : state.pageNo, console.log('onShowComments')
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--
}
} }
}
function dislike() { const render = useSlideListItemRender({ ...props.cbs, ...p })
listRef.value.dislike(state.list[1]) const listRef = ref(null)
state.list[state.index] = state.list[1] const state = reactive({
$notice('操作成功,将减少此类视频的推荐') index: props.index,
list: props.list,
uniqueId: 'uniqueId1',
totalSize: 0,
pageSize: 10,
pageNo: 0
})
function loadMore() {
if (!baseStore.loading) {
state.pageNo++
getData()
} }
}
function end() { async function getData(refresh = false) {
// this.$notice('暂时没有更多了') if (baseStore.loading) return
} baseStore.loading = true
let res = await props.api({
function click(uniqueId) { pageNo: refresh ? 0 : state.pageNo,
if (uniqueId !== state.uniqueId) return pageSize: state.pageSize
bus.emit(EVENT_KEY.SINGLE_CLICK_BROADCAST, {
uniqueId,
index: state.index,
type: EVENT_KEY.ITEM_TOGGLE,
})
}
function updateItem({ position, item }) {
if (position.uniqueId === state.uniqueId) {
state.list[position.index] = item
}
}
onMounted(() => {
bus.on(EVENT_KEY.SINGLE_CLICK, click)
bus.on(EVENT_KEY.UPDATE_ITEM, updateItem)
}) })
onUnmounted(() => { // console.log('getSlide4Data-', 'refresh', refresh, res)
bus.off(EVENT_KEY.SINGLE_CLICK, click) baseStore.loading = false
bus.on(EVENT_KEY.UPDATE_ITEM, updateItem) if (res.code === 200) {
state.totalSize = res.data.total
if (refresh) {
state.list = []
}
state.list = state.list.concat(res.data.list)
} else {
state.pageNo--
}
}
function dislike() {
listRef.value.dislike(state.list[1])
state.list[state.index] = state.list[1]
$notice('操作成功,将减少此类视频的推荐')
}
function end() {
// this.$notice('暂时没有更多了')
}
function click(uniqueId) {
if (uniqueId !== state.uniqueId) return
bus.emit(EVENT_KEY.SINGLE_CLICK_BROADCAST, {
uniqueId,
index: state.index,
type: EVENT_KEY.ITEM_TOGGLE
}) })
}
function updateItem({ position, item }) {
if (position.uniqueId === state.uniqueId) {
state.list[position.index] = item
}
}
onMounted(() => {
bus.on(EVENT_KEY.SINGLE_CLICK, click)
bus.on(EVENT_KEY.UPDATE_ITEM, updateItem)
})
onUnmounted(() => {
bus.off(EVENT_KEY.SINGLE_CLICK, click)
bus.on(EVENT_KEY.UPDATE_ITEM, updateItem)
})
</script> </script>

View File

@@ -7,7 +7,7 @@ export default {
isOtherLogin: false, isOtherLogin: false,
showAnim: false, showAnim: false,
showTooltip: false, showTooltip: false,
loading: false, loading: false
} }
}, },
computed: {}, computed: {},
@@ -30,6 +30,6 @@ export default {
} }
} }
}) })
}, }
}, }
} }

View File

@@ -14,42 +14,42 @@
</div> </div>
</template> </template>
<script> <script>
export default { export default {
name: 'Help', name: 'Help',
props: {}, props: {},
data() { data() {
return {} return {}
}, },
computed: {}, computed: {},
created() {}, created() {},
methods: {}, methods: {}
} }
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '../../assets/less/index'; @import '../../assets/less/index';
.Help { .Help {
position: fixed; position: fixed;
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
top: 0; top: 0;
overflow: auto; overflow: auto;
color: white; color: white;
font-size: 14rem; font-size: 14rem;
.content { .content {
margin-top: 60rem; margin-top: 60rem;
height: calc(var(--vh, 1vh) * 100 - 60rem); height: calc(var(--vh, 1vh) * 100 - 60rem);
iframe { iframe {
padding: 0; padding: 0;
margin: 0; margin: 0;
border: none; border: none;
width: 100%; width: 100%;
height: 100%; height: 100%;
}
} }
} }
}
</style> </style>

View File

@@ -33,24 +33,16 @@
</div> </div>
<div class="right"> <div class="right">
我已阅读并同意 我已阅读并同意
<span <span class="link" @click="$nav('/service-protocol', { type: '“抖音”用户服务协议' })"
class="link"
@click="$nav('/service-protocol', { type: '“抖音”用户服务协议' })"
>用户协议</span >用户协议</span
> >
<span <span class="link" @click="$nav('/service-protocol', { type: '“抖音”隐私政策' })"
class="link"
@click="$nav('/service-protocol', { type: '“抖音”隐私政策' })"
>隐私政策</span >隐私政策</span
> >
<div> <div>
以及 以及
<span <span class="link" @click="$nav('/service-protocol', { type: '中国移动认证服务协议' })"
class="link"
@click="
$nav('/service-protocol', { type: '中国移动认证服务协议' })
"
>中国移动认证服务条款</span >中国移动认证服务条款</span
> >
同时登录并使用抖音火山版火山小视频和抖音 同时登录并使用抖音火山版火山小视频和抖音
@@ -61,26 +53,10 @@
<div class="other-login"> <div class="other-login">
<transition name="fade"> <transition name="fade">
<div v-if="isOtherLogin" class="icons"> <div v-if="isOtherLogin" class="icons">
<img <img @click="$no" src="../../assets/img/icon/login/toutiao-round.png" alt="" />
@click="$no" <img @click="$no" src="../../assets/img/icon/login/qq-round.webp" alt="" />
src="../../assets/img/icon/login/toutiao-round.png" <img @click="$no" src="../../assets/img/icon/login/wechat-round.png" alt="" />
alt="" <img @click="$no" src="../../assets/img/icon/login/weibo-round.webp" alt="" />
/>
<img
@click="$no"
src="../../assets/img/icon/login/qq-round.webp"
alt=""
/>
<img
@click="$no"
src="../../assets/img/icon/login/wechat-round.png"
alt=""
/>
<img
@click="$no"
src="../../assets/img/icon/login/weibo-round.webp"
alt=""
/>
</div> </div>
</transition> </transition>
</div> </div>
@@ -96,146 +72,146 @@
</div> </div>
</template> </template>
<script> <script>
import Check from '../../components/Check' import Check from '../../components/Check'
import Tooltip from './components/Tooltip' import Tooltip from './components/Tooltip'
import Loading from '../../components/Loading' import Loading from '../../components/Loading'
export default { export default {
name: 'login', name: 'login',
components: { components: {
Check, Check,
Tooltip, Tooltip,
Loading, Loading
},
data() {
return {
isAgree: false,
isOtherLogin: false,
showAnim: false,
showTooltip: false,
loading: {
login: false,
getPhone: false
}
}
},
computed: {},
created() {
this.getPhone()
},
methods: {
async getPhone() {
this.loading.getPhone = true
await this.$sleep(1000)
this.loading.getPhone = false
}, },
data() { login() {
return { if (this.isAgree) {
isAgree: false, this.loading.login = true
isOtherLogin: false, } else {
showAnim: false, if (!this.showAnim && !this.showTooltip) {
showTooltip: false, this.showAnim = true
loading: { setTimeout(() => {
login: false, this.showAnim = false
getPhone: false, this.showTooltip = true
}, }, 500)
} setTimeout(() => {
}, this.showTooltip = false
computed: {}, }, 3000)
created() {
this.getPhone()
},
methods: {
async getPhone() {
this.loading.getPhone = true
await this.$sleep(1000)
this.loading.getPhone = false
},
login() {
if (this.isAgree) {
this.loading.login = true
} else {
if (!this.showAnim && !this.showTooltip) {
this.showAnim = true
setTimeout(() => {
this.showAnim = false
this.showTooltip = true
}, 500)
setTimeout(() => {
this.showTooltip = false
}, 3000)
}
} }
},
},
}
</script>
<style scoped lang="less">
@import '../../assets/less/index';
.login {
position: fixed;
left: 0;
right: 0;
bottom: 0;
top: 0;
overflow: auto;
color: black;
font-size: 14rem;
background: white;
.content {
padding: 60rem 30rem;
.desc {
margin-bottom: 60rem;
margin-top: 120rem;
display: flex;
align-items: center;
flex-direction: column;
.title {
margin-bottom: 20rem;
}
.phone-number {
letter-spacing: 3rem;
font-size: 30rem;
margin-bottom: 10rem;
}
.sub-title {
font-size: 12rem;
color: var(--second-text-color);
}
}
.button {
width: 100%;
margin-bottom: 5rem;
}
.protocol {
position: relative;
color: gray;
margin-top: 20rem;
font-size: 12rem;
display: flex;
.left {
padding-top: 1rem;
margin-right: 5rem;
}
}
.other-login {
position: absolute;
bottom: 40rem;
font-size: 12rem;
display: flex;
justify-content: center;
width: calc(100vw - 60rem);
transform: translateX(-50%);
left: 50%;
.icons {
img {
width: 40rem;
margin-right: 15rem;
&:nth-last-child(1) {
margin-right: 0;
}
}
}
}
.other-login-text {
position: absolute;
bottom: 55rem;
font-size: 12rem;
transform: translateX(-50%);
left: 50%;
} }
} }
} }
}
</script>
<style scoped lang="less">
@import '../../assets/less/index';
.login {
position: fixed;
left: 0;
right: 0;
bottom: 0;
top: 0;
overflow: auto;
color: black;
font-size: 14rem;
background: white;
.content {
padding: 60rem 30rem;
.desc {
margin-bottom: 60rem;
margin-top: 120rem;
display: flex;
align-items: center;
flex-direction: column;
.title {
margin-bottom: 20rem;
}
.phone-number {
letter-spacing: 3rem;
font-size: 30rem;
margin-bottom: 10rem;
}
.sub-title {
font-size: 12rem;
color: var(--second-text-color);
}
}
.button {
width: 100%;
margin-bottom: 5rem;
}
.protocol {
position: relative;
color: gray;
margin-top: 20rem;
font-size: 12rem;
display: flex;
.left {
padding-top: 1rem;
margin-right: 5rem;
}
}
.other-login {
position: absolute;
bottom: 40rem;
font-size: 12rem;
display: flex;
justify-content: center;
width: calc(100vw - 60rem);
transform: translateX(-50%);
left: 50%;
.icons {
img {
width: 40rem;
margin-right: 15rem;
&:nth-last-child(1) {
margin-right: 0;
}
}
}
}
.other-login-text {
position: absolute;
bottom: 55rem;
font-size: 12rem;
transform: translateX(-50%);
left: 50%;
}
}
}
</style> </style>

View File

@@ -11,12 +11,7 @@
<div class="sub-title">未注册的手机号验证通过后将自动注册</div> <div class="sub-title">未注册的手机号验证通过后将自动注册</div>
</div> </div>
<LoginInput <LoginInput autofocus type="phone" v-model="phone" placeholder="请输入手机号" />
autofocus
type="phone"
v-model="phone"
placeholder="请输入手机号"
/>
<div class="notice" v-if="notice"> <div class="notice" v-if="notice">
{{ notice }} {{ notice }}
@@ -29,15 +24,11 @@
</div> </div>
<div class="right"> <div class="right">
已阅读并同意 已阅读并同意
<span <span class="link" @click="$nav('/service-protocol', { type: '“抖音”用户服务协议' })"
class="link"
@click="$nav('/service-protocol', { type: '“抖音”用户服务协议' })"
>用户协议</span >用户协议</span
> >
<span <span class="link" @click="$nav('/service-protocol', { type: '“抖音”隐私政策' })"
class="link"
@click="$nav('/service-protocol', { type: '“抖音”隐私政策' })"
>隐私政策</span >隐私政策</span
> >
同时登录并使用抖音火山版火山小视频和抖音 同时登录并使用抖音火山版火山小视频和抖音
@@ -91,88 +82,88 @@
</div> </div>
</template> </template>
<script> <script>
import Check from '../../components/Check' import Check from '../../components/Check'
import Tooltip from './components/Tooltip' import Tooltip from './components/Tooltip'
import LoginInput from './components/LoginInput' import LoginInput from './components/LoginInput'
import Base from './Base.js' import Base from './Base.js'
import FromBottomDialog from '../../components/dialog/FromBottomDialog' import FromBottomDialog from '../../components/dialog/FromBottomDialog'
export default { export default {
name: 'OtherLogin', name: 'OtherLogin',
extends: Base, extends: Base,
components: { components: {
Check, Check,
Tooltip, Tooltip,
LoginInput, LoginInput,
FromBottomDialog, FromBottomDialog
}, },
data() { data() {
return { return {
phone: '', phone: '',
notice: '', notice: ''
}
},
computed: {},
created() {},
methods: {
async getCode() {
let res = await this.check()
if (res) {
this.loading = true
setTimeout(() => {
this.$nav('/login/verification-code')
}, 2000)
} }
}, },
computed: {}, async otherLogin() {
created() {}, let res = await this.check()
methods: { if (res) {
async getCode() { this.isOtherLogin = true
let res = await this.check()
if (res) {
this.loading = true
setTimeout(() => {
this.$nav('/login/verification-code')
}, 2000)
}
},
async otherLogin() {
let res = await this.check()
if (res) {
this.isOtherLogin = true
}
},
},
}
</script>
<style scoped lang="less">
@import '../../assets/less/index';
@import 'Base.less';
.other-login {
position: fixed;
left: 0;
right: 0;
bottom: 0;
top: 0;
overflow: auto;
color: black;
font-size: 14rem;
background: white;
.block-dialog {
color: black;
.item {
height: 50rem;
display: flex;
justify-content: center;
align-items: center;
border-top: 1px solid gainsboro;
img {
height: 25rem;
margin-right: 10rem;
}
&:nth-last-child(1) {
border-top: none;
}
}
.space {
height: 10rem;
background: whitesmoke;
} }
} }
} }
}
</script>
<style scoped lang="less">
@import '../../assets/less/index';
@import 'Base.less';
.other-login {
position: fixed;
left: 0;
right: 0;
bottom: 0;
top: 0;
overflow: auto;
color: black;
font-size: 14rem;
background: white;
.block-dialog {
color: black;
.item {
height: 50rem;
display: flex;
justify-content: center;
align-items: center;
border-top: 1px solid gainsboro;
img {
height: 25rem;
margin-right: 10rem;
}
&:nth-last-child(1) {
border-top: none;
}
}
.space {
height: 10rem;
background: whitesmoke;
}
}
}
</style> </style>

View File

@@ -10,12 +10,7 @@
<div class="title">手机号密码登录</div> <div class="title">手机号密码登录</div>
</div> </div>
<LoginInput <LoginInput autofocus type="phone" v-model="phone" placeholder="请输入手机号" />
autofocus
type="phone"
v-model="phone"
placeholder="请输入手机号"
/>
<LoginInput <LoginInput
autofocus autofocus
class="mt1r" class="mt1r"
@@ -31,15 +26,11 @@
</div> </div>
<div class="right"> <div class="right">
已阅读并同意 已阅读并同意
<span <span class="link" @click="$nav('/service-protocol', { type: '“抖音”用户服务协议' })"
class="link"
@click="$nav('/service-protocol', { type: '“抖音”用户服务协议' })"
>用户协议</span >用户协议</span
> >
<span <span class="link" @click="$nav('/service-protocol', { type: '“抖音”隐私政策' })"
class="link"
@click="$nav('/service-protocol', { type: '“抖音”隐私政策' })"
>隐私政策</span >隐私政策</span
> >
同时登录并使用抖音火山版火山小视频和抖音 同时登录并使用抖音火山版火山小视频和抖音
@@ -62,66 +53,64 @@
<div class="options"> <div class="options">
<span> <span>
忘记了<span class="link" @click="$nav('/login/retrieve-password')" 忘记了<span class="link" @click="$nav('/login/retrieve-password')">找回密码</span>
>找回密码</span
>
</span> </span>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import Check from '../../components/Check' import Check from '../../components/Check'
import LoginInput from './components/LoginInput' import LoginInput from './components/LoginInput'
import Tooltip from './components/Tooltip' import Tooltip from './components/Tooltip'
import Base from './Base' import Base from './Base'
export default { export default {
name: 'PasswordLogin', name: 'PasswordLogin',
extends: Base, extends: Base,
components: { components: {
Check, Check,
Tooltip, Tooltip,
LoginInput, LoginInput
}, },
data() { data() {
return { return {
phone: '', phone: '',
password: '', password: '',
code: '', code: '',
notice: '', notice: ''
}
},
computed: {
disabled() {
return !(this.phone && this.password)
}
},
created() {},
methods: {
async login() {
let res = await this.check()
if (res) {
this.loading = true
} }
}, }
computed: {
disabled() {
return !(this.phone && this.password)
},
},
created() {},
methods: {
async login() {
let res = await this.check()
if (res) {
this.loading = true
}
},
},
} }
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '../../assets/less/index'; @import '../../assets/less/index';
@import 'Base.less'; @import 'Base.less';
.PasswordLogin { .PasswordLogin {
position: fixed; position: fixed;
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
top: 0; top: 0;
overflow: auto; overflow: auto;
color: black; color: black;
font-size: 14rem; font-size: 14rem;
background: white; background: white;
} }
</style> </style>

View File

@@ -5,8 +5,7 @@
<div class="desc"> <div class="desc">
<div class="title">找回密码</div> <div class="title">找回密码</div>
<div class="sub-title"> <div class="sub-title">
验证码已通过短信发送到+86 13800138000 密码为8 - 验证码已通过短信发送到+86 13800138000 密码为8 - 20至少包含字母数字符号2种组合
20至少包含字母数字符号2种组合
</div> </div>
</div> </div>
@@ -33,15 +32,11 @@
</div> </div>
<div class="right"> <div class="right">
已阅读并同意 已阅读并同意
<span <span class="link" @click="$nav('/service-protocol', { type: '“抖音”用户服务协议' })"
class="link"
@click="$nav('/service-protocol', { type: '“抖音”用户服务协议' })"
>用户协议</span >用户协议</span
> >
<span <span class="link" @click="$nav('/service-protocol', { type: '“抖音”隐私政策' })"
class="link"
@click="$nav('/service-protocol', { type: '“抖音”隐私政策' })"
>隐私政策</span >隐私政策</span
> >
同时登录并使用抖音火山版火山小视频和抖音 同时登录并使用抖音火山版火山小视频和抖音
@@ -64,103 +59,99 @@
</dy-button> </dy-button>
<div class="options" v-if="showVoiceCode"> <div class="options" v-if="showVoiceCode">
<span> <span> 收不到短信<span class="link" @click="getVoiceCode">获取语音验证码</span> </span>
收不到短信<span class="link" @click="getVoiceCode"
>获取语音验证码</span
>
</span>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import Check from '../../components/Check' import Check from '../../components/Check'
import LoginInput from './components/LoginInput' import LoginInput from './components/LoginInput'
import Tooltip from './components/Tooltip' import Tooltip from './components/Tooltip'
import Base from './Base' import Base from './Base'
export default { export default {
name: 'RetrievePassword', name: 'RetrievePassword',
extends: Base, extends: Base,
components: { components: {
Check, Check,
Tooltip, Tooltip,
LoginInput, LoginInput
},
data() {
return {
phone: '',
password: '',
code: '',
notice: '',
isSendVerificationCode: true,
showVoiceCode: false
}
},
computed: {
disabled() {
return !(this.code && this.password)
}
},
created() {
setTimeout(() => {
this.showVoiceCode = true
}, 3000)
},
methods: {
getVoiceCode() {
return this.$showNoticeDialog(
'语音验证码',
'我们将以电话的方式告知你验证码,请注意接听',
'',
() => {
setTimeout(() => {
this.$showConfirmDialog(
'',
'您的手机可能由于空号/欠费/停机无法收到验证码,请恢复手机号状态,如果' +
'您因为换号无法收到验证码,可以尝试找回账号',
'',
() => {},
null,
'找回账号',
'返回',
''
)
}, 2000)
},
'知道了'
)
}, },
data() { //TODO loading样式不对
return { async sendCode() {
phone: '', this.$showLoading()
password: '', await this.$sleep(500)
code: '', this.$hideLoading()
notice: '', this.isSendVerificationCode = true
isSendVerificationCode: true, },
showVoiceCode: false, async login() {
let res = await this.check()
if (res) {
this.loading = true
} }
}, }
computed: {
disabled() {
return !(this.code && this.password)
},
},
created() {
setTimeout(() => {
this.showVoiceCode = true
}, 3000)
},
methods: {
getVoiceCode() {
return this.$showNoticeDialog(
'语音验证码',
'我们将以电话的方式告知你验证码,请注意接听',
'',
() => {
setTimeout(() => {
this.$showConfirmDialog(
'',
'您的手机可能由于空号/欠费/停机无法收到验证码,请恢复手机号状态,如果' +
'您因为换号无法收到验证码,可以尝试找回账号',
'',
() => {},
null,
'找回账号',
'返回',
'',
)
}, 2000)
},
'知道了',
)
},
//TODO loading样式不对
async sendCode() {
this.$showLoading()
await this.$sleep(500)
this.$hideLoading()
this.isSendVerificationCode = true
},
async login() {
let res = await this.check()
if (res) {
this.loading = true
}
},
},
} }
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '../../assets/less/index'; @import '../../assets/less/index';
@import 'Base.less'; @import 'Base.less';
.RetrievePassword { .RetrievePassword {
position: fixed; position: fixed;
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
top: 0; top: 0;
overflow: auto; overflow: auto;
color: black; color: black;
font-size: 14rem; font-size: 14rem;
background: white; background: white;
} }
</style> </style>

View File

@@ -20,11 +20,7 @@
@send="sendCode" @send="sendCode"
/> />
<div class="options" v-if="showVoiceCode"> <div class="options" v-if="showVoiceCode">
<span> <span> 收不到短信<span class="link" @click="getVoiceCode">获取语音验证码</span> </span>
收不到短信<span class="link" @click="getVoiceCode"
>获取语音验证码</span
>
</span>
</div> </div>
<dy-button <dy-button
@@ -40,95 +36,95 @@
</div> </div>
</template> </template>
<script> <script>
import Check from '../../components/Check' import Check from '../../components/Check'
import LoginInput from './components/LoginInput' import LoginInput from './components/LoginInput'
export default { export default {
name: 'VerificationCode', name: 'VerificationCode',
components: { components: {
Check, Check,
LoginInput, LoginInput
},
data() {
return {
showAnim: false,
showTooltip: false,
loading: false,
phone: '',
password: '',
code: '',
isSendVerificationCode: true,
showVoiceCode: false
}
},
created() {
setTimeout(() => {
this.showVoiceCode = true
}, 3000)
},
methods: {
getVoiceCode() {
return this.$showNoticeDialog(
'语音验证码',
'我们将以电话的方式告知你验证码,请注意接听',
'',
() => {
setTimeout(() => {
this.$showConfirmDialog(
'',
'您的手机可能由于空号/欠费/停机无法收到验证码,请恢复手机号状态,如果' +
'您因为换号无法收到验证码,可以尝试找回账号',
'',
() => {},
null,
'找回账号',
'返回',
''
)
}, 2000)
},
'知道了'
)
}, },
data() { //TODO loading样式不对
return { async sendCode() {
showAnim: false, this.$showLoading()
showTooltip: false, await this.$sleep(500)
loading: false, this.$hideLoading()
phone: '', this.isSendVerificationCode = true
password: '',
code: '',
isSendVerificationCode: true,
showVoiceCode: false,
}
}, },
created() { login() {
this.loading = true
setTimeout(() => { setTimeout(() => {
this.showVoiceCode = true
}, 3000)
},
methods: {
getVoiceCode() {
return this.$showNoticeDialog(
'语音验证码',
'我们将以电话的方式告知你验证码,请注意接听',
'',
() => {
setTimeout(() => {
this.$showConfirmDialog(
'',
'您的手机可能由于空号/欠费/停机无法收到验证码,请恢复手机号状态,如果' +
'您因为换号无法收到验证码,可以尝试找回账号',
'',
() => {},
null,
'找回账号',
'返回',
'',
)
}, 2000)
},
'知道了',
)
},
//TODO loading样式不对
async sendCode() {
this.$showLoading()
await this.$sleep(500)
this.$hideLoading()
this.isSendVerificationCode = true this.isSendVerificationCode = true
}, this.loading = false
login() { }, 1000)
this.loading = true }
setTimeout(() => {
this.isSendVerificationCode = true
this.loading = false
}, 1000)
},
},
} }
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '../../assets/less/index'; @import '../../assets/less/index';
@import 'Base.less'; @import 'Base.less';
.VerificationCode { .VerificationCode {
position: fixed; position: fixed;
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
top: 0; top: 0;
overflow: auto; overflow: auto;
color: black; color: black;
font-size: 14rem; font-size: 14rem;
background: white; background: white;
.options { .options {
margin-top: 10rem; margin-top: 10rem;
}
.button {
margin-top: 20rem;
}
} }
.button {
margin-top: 20rem;
}
}
</style> </style>

View File

@@ -59,170 +59,168 @@
/> />
</div> </div>
<div class="right" @click="send"> <div class="right" @click="send">
<span :class="isSendVerificationCode && 'disabled'">{{ <span :class="isSendVerificationCode && 'disabled'">{{ verificationCodeBtnText }}</span>
verificationCodeBtnText
}}</span>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
export default { export default {
name: 'LoginInput', name: 'LoginInput',
props: { props: {
modelValue: '', modelValue: '',
placeholder: '', placeholder: '',
type: { type: {
type: String, type: String,
default: 'phone', default: 'phone'
},
autofocus: {
type: Boolean,
default: false,
},
isSendVerificationCode: {
type: Boolean,
default: false,
},
}, },
data() { autofocus: {
return { type: Boolean,
isTyping: false, default: false
verificationCodeBtnText: 60, },
isSendVerificationCode: {
type: Boolean,
default: false
}
},
data() {
return {
isTyping: false,
verificationCodeBtnText: 60
}
},
computed: {
value: {
get() {
return this.modelValue
},
set(e) {
this.$emit('update:modelValue', e)
} }
}, }
computed: { },
value: { watch: {
get() { isSendVerificationCode: {
return this.modelValue immediate: true,
}, handler(newVal, oldVal) {
set(e) { if (newVal) {
this.$emit('update:modelValue', e) this.verificationCodeBtnText = 60
}, let ticker = setInterval(() => {
}, if (this.verificationCodeBtnText > 0) {
}, this.verificationCodeBtnText--
watch: { } else {
isSendVerificationCode: { this.verificationCodeBtnText = '重新发送'
immediate: true, this.$emit('update:isSendVerificationCode', false)
handler(newVal, oldVal) { clearInterval(ticker)
if (newVal) { }
this.verificationCodeBtnText = 60 }, 1000)
let ticker = setInterval(() => {
if (this.verificationCodeBtnText > 0) {
this.verificationCodeBtnText--
} else {
this.verificationCodeBtnText = '重新发送'
this.$emit('update:isSendVerificationCode', false)
clearInterval(ticker)
}
}, 1000)
}
},
},
},
methods: {
delaySetTypingFalse() {
setTimeout(() => {
this.isTyping = false
})
},
send() {
if (!this.isSendVerificationCode) {
this.$emit('send')
} }
}, }
}
},
methods: {
delaySetTypingFalse() {
setTimeout(() => {
this.isTyping = false
})
}, },
send() {
if (!this.isSendVerificationCode) {
this.$emit('send')
}
}
} }
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '../../../assets/less/index'; @import '../../../assets/less/index';
.input-number { .input-number {
display: flex;
background: whitesmoke;
padding: 15rem 10rem;
font-size: 14rem;
.left {
display: flex; display: flex;
background: whitesmoke; align-items: center;
padding: 15rem 10rem; margin-right: 10rem;
font-size: 14rem; padding-right: 10rem;
position: relative;
.left {
display: flex;
align-items: center;
margin-right: 10rem;
padding-right: 10rem;
position: relative;
&.no-border {
&::before {
content: '';
display: none;
}
}
&.flex1 {
flex: 1;
margin-right: 0;
padding-right: 0;
}
img {
top: 50%;
transform: translateY(-50%);
right: 10rem;
position: absolute;
height: 15rem;
}
.arrow {
margin-top: 4rem;
margin-left: 5rem;
width: 0;
height: 0;
border: 4rem solid transparent;
border-top: 5rem solid black;
}
&.no-border {
&::before { &::before {
content: ' '; content: '';
position: absolute; display: none;
width: 1px;
height: 8rem;
top: 4px;
right: 0;
background: gainsboro;
} }
} }
.right { &.flex1 {
//background: red; flex: 1;
position: relative; margin-right: 0;
padding-right: 0;
&.flex1 {
flex: 1;
}
img {
top: 50%;
transform: translateY(-50%);
right: 10rem;
position: absolute;
height: 15rem;
}
.disabled {
color: var(--second-text-color);
}
} }
input { img {
width: 90%; top: 50%;
outline: none; transform: translateY(-50%);
border: none; right: 10rem;
background: whitesmoke; position: absolute;
caret-color: red; height: 15rem;
}
&[type='password'] { .arrow {
//letter-spacing: 10rem; margin-top: 4rem;
} margin-left: 5rem;
width: 0;
height: 0;
border: 4rem solid transparent;
border-top: 5rem solid black;
}
&::before {
content: ' ';
position: absolute;
width: 1px;
height: 8rem;
top: 4px;
right: 0;
background: gainsboro;
} }
} }
.right {
//background: red;
position: relative;
&.flex1 {
flex: 1;
}
img {
top: 50%;
transform: translateY(-50%);
right: 10rem;
position: absolute;
height: 15rem;
}
.disabled {
color: var(--second-text-color);
}
}
input {
width: 90%;
outline: none;
border: none;
background: whitesmoke;
caret-color: red;
&[type='password'] {
//letter-spacing: 10rem;
}
}
}
</style> </style>

View File

@@ -7,54 +7,54 @@
</transition> </transition>
</template> </template>
<script> <script>
export default { export default {
name: 'Popover', name: 'Popover',
props: { props: {
modelValue: { modelValue: {
type: Boolean, type: Boolean,
default: false, default: false
}, }
}, },
data() { data() {
return {} return {}
}, },
computed: {}, computed: {},
created() {}, created() {},
methods: {}, methods: {}
} }
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '../../../assets/less/index'; @import '../../../assets/less/index';
.scale-enter-active, .scale-enter-active,
.scale-leave-active { .scale-leave-active {
transition: all 0.3s ease; transition: all 0.3s ease;
} }
.scale-enter-from, .scale-enter-from,
.scale-leave-to { .scale-leave-to {
//transform: scale(0); //transform: scale(0);
opacity: 0; opacity: 0;
} }
.Tooltip { .Tooltip {
z-index: 2; z-index: 2;
position: absolute;
font-size: 12rem;
color: white;
padding: 10rem;
border-radius: 8rem;
background: black;
.arrow {
width: 0;
height: 0;
border: 7rem solid transparent;
border-top: 7rem solid black;
position: absolute; position: absolute;
font-size: 12rem; left: 10rem;
color: white; bottom: -14rem;
padding: 10rem;
border-radius: 8rem;
background: black;
.arrow {
width: 0;
height: 0;
border: 7rem solid transparent;
border-top: 7rem solid black;
position: absolute;
left: 10rem;
bottom: -14rem;
}
} }
}
</style> </style>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -3,24 +3,12 @@
<div class="header"> <div class="header">
<dy-back mode="light" @click="$back" /> <dy-back mode="light" @click="$back" />
<!-- todo 差一--> <!-- todo 差一-->
<img <img class="share" src="../../assets/img/icon/share-white.png" @click="isSharing = true" />
class="share"
src="../../assets/img/icon/share-white.png"
@click="isSharing = true"
/>
</div> </div>
<div class="content"> <div class="content">
<div class="qrcode"> <div class="qrcode">
<img <img class="qrcode-bg" src="../../assets/img/icon/me/code-bg.png" alt="" />
class="qrcode-bg" <img class="avatar" :src="_checkImgUrl(userinfo.cover_url[0].url_list[0])" alt="" />
src="../../assets/img/icon/me/code-bg.png"
alt=""
/>
<img
class="avatar"
:src="_checkImgUrl(userinfo.cover_url[0].url_list[0])"
alt=""
/>
</div> </div>
<span class="name">ZZZZZZZZZZ</span> <span class="name">ZZZZZZZZZZ</span>
@@ -46,159 +34,159 @@
</div> </div>
</template> </template>
<script> <script>
import Share from '../../components/Share' import Share from '../../components/Share'
import { mapState } from 'pinia' import { mapState } from 'pinia'
import { useBaseStore } from '@/store/pinia' import { useBaseStore } from '@/store/pinia'
import { _checkImgUrl } from '@/utils' import { _checkImgUrl } from '@/utils'
export default { export default {
name: 'MyCard', name: 'MyCard',
components: { components: {
Share, Share
}, },
data() { data() {
return { return {
isSharing: false, isSharing: false,
okText: '', okText: '',
showSharePassword: false, showSharePassword: false,
shareToFriend: false, shareToFriend: false,
shareType: -1, shareType: -1,
showDouyinCode: false, showDouyinCode: false
}
},
watch: {
shareType(newVal, oldVal) {
if (newVal === -1) return
this.showSharePassword = true
switch (newVal) {
case 2:
case 3:
return (this.okText = '去微信粘贴')
case 4:
case 5:
return (this.okText = '去QQ粘贴')
case 8:
return (this.okText = '去微博粘贴')
} }
}, }
watch: { },
shareType(newVal, oldVal) { created() {},
if (newVal === -1) return computed: {
this.showSharePassword = true ...mapState(useBaseStore, ['userinfo'])
switch (newVal) { },
case 2: methods: {
case 3: _checkImgUrl,
return (this.okText = '去微信粘贴') delayShowDialog(cb) {
case 4: setTimeout(() => {
case 5: cb()
return (this.okText = '去QQ粘贴') }, 100)
case 8: }
return (this.okText = '去微博粘贴')
}
},
},
created() {},
computed: {
...mapState(useBaseStore, ['userinfo']),
},
methods: {
_checkImgUrl,
delayShowDialog(cb) {
setTimeout(() => {
cb()
}, 100)
},
},
} }
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '../../assets/less/index'; @import '../../assets/less/index';
#MyCard { #MyCard {
background: rgb(136, 132, 133); background: rgb(136, 132, 133);
position: fixed;
left: 0;
right: 0;
bottom: 0;
top: 0;
overflow: auto;
font-size: 14rem;
.header {
position: fixed; position: fixed;
left: 0; z-index: 9;
right: 0;
bottom: 0;
top: 0; top: 0;
overflow: auto; width: 100%;
font-size: 14rem; box-sizing: border-box;
padding: 0 15rem;
height: 60rem;
display: flex;
justify-content: space-between;
align-items: center;
.header { .share {
position: fixed; width: 24rem;
z-index: 9; height: 24rem;
top: 0; margin-left: 15rem;
width: 100%; }
box-sizing: border-box; }
padding: 0 15rem;
height: 60rem; .content {
padding-top: var(--common-header-height);
display: flex;
flex-direction: column;
align-items: center;
.qrcode {
margin-top: 12vh;
display: flex; display: flex;
justify-content: space-between;
align-items: center; align-items: center;
justify-content: center;
position: relative;
.share { .qrcode-bg {
width: 24rem; width: 60vw;
height: 24rem; }
margin-left: 15rem;
.avatar {
border-radius: 50%;
position: absolute;
width: 25vw;
} }
} }
.content { .name {
padding-top: var(--common-header-height); font-weight: bold;
margin-top: 20rem;
font-size: 16rem;
color: white;
}
.notice {
color: white;
font-size: 14rem;
margin-top: 20rem;
opacity: 0.4;
}
}
.footer {
position: absolute;
bottom: 30rem;
display: flex;
justify-content: space-around;
width: 100%;
.btn {
color: white;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
font-size: 12rem;
.qrcode { .wrapper {
margin-top: 12vh; background: rgba(252, 250, 250, 0.3);
border-radius: 50%;
display: flex; display: flex;
padding: 18rem;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
position: relative; margin-bottom: 10rem;
.qrcode-bg {
width: 60vw;
}
.avatar {
border-radius: 50%;
position: absolute;
width: 25vw;
}
} }
.name { img {
font-weight: bold; width: 26rem;
margin-top: 20rem;
font-size: 16rem;
color: white;
}
.notice {
color: white;
font-size: 14rem;
margin-top: 20rem;
opacity: 0.4;
}
}
.footer {
position: absolute;
bottom: 30rem;
display: flex;
justify-content: space-around;
width: 100%;
.btn {
color: white;
display: flex;
flex-direction: column;
align-items: center;
font-size: 12rem;
.wrapper {
background: rgba(252, 250, 250, 0.3);
border-radius: 50%;
display: flex;
padding: 18rem;
align-items: center;
justify-content: center;
margin-bottom: 10rem;
}
img {
width: 26rem;
}
} }
} }
} }
}
</style> </style>

View File

@@ -24,25 +24,13 @@
<span>播放全部</span> <span>播放全部</span>
<span class="num">(2)</span> <span class="num">(2)</span>
</div> </div>
<img <img class="menu" src="../../assets/img/icon/menu-white.png" alt="" />
class="menu"
src="../../assets/img/icon/menu-white.png"
alt=""
/>
</div> </div>
<div class="collect-list"> <div class="collect-list">
<div <div class="item" v-for="(item, index) in collectMusic" @click="page2PlayMusic(item)">
class="item"
v-for="(item, index) in collectMusic"
@click="page2PlayMusic(item)"
>
<div class="left"> <div class="left">
<div class="cover-wrapper"> <div class="cover-wrapper">
<img <img v-lazy="$imgPreview(item.cover)" alt="" class="cover" />
v-lazy="$imgPreview(item.cover)"
alt=""
class="cover"
/>
</div> </div>
<div class="desc"> <div class="desc">
<span class="name">{{ item.name }}</span> <span class="name">{{ item.name }}</span>
@@ -66,11 +54,7 @@
<span>推荐收藏</span> <span>推荐收藏</span>
<div class="right"> <div class="right">
<span class="auto-play">自动播放</span> <span class="auto-play">自动播放</span>
<switches <switches v-model="isAutoPlay" theme="bootstrap" color="success"></switches>
v-model="isAutoPlay"
theme="bootstrap"
color="success"
></switches>
</div> </div>
</div> </div>
<div class="recommend-list"> <div class="recommend-list">
@@ -81,11 +65,7 @@
> >
<div class="left"> <div class="left">
<div class="cover-wrapper"> <div class="cover-wrapper">
<img <img v-lazy="$imgPreview(item.cover)" alt="" class="cover" />
v-lazy="$imgPreview(item.cover)"
alt=""
class="cover"
/>
</div> </div>
<div class="desc"> <div class="desc">
<span class="name">{{ item.name }}</span> <span class="name">{{ item.name }}</span>
@@ -119,18 +99,10 @@
</div> </div>
</div> </div>
<transition name="float-play"> <transition name="float-play">
<div <div v-if="isShowFloatPlay" class="playing" @click="isShowCollectDialog = true">
v-if="isShowFloatPlay"
class="playing"
@click="isShowCollectDialog = true"
>
<div class="playing-wrapper"> <div class="playing-wrapper">
<div class="cover-wrapper"> <div class="cover-wrapper">
<img <img v-lazy="$imgPreview(currentMusic.cover)" alt="" class="cover" />
v-lazy="$imgPreview(currentMusic.cover)"
alt=""
class="cover"
/>
</div> </div>
<div class="name">{{ currentMusic.name }}</div> <div class="name">{{ currentMusic.name }}</div>
<img <img
@@ -162,12 +134,7 @@
<transition name="my-collect-dialog"> <transition name="my-collect-dialog">
<div class="my-collect-dialog" v-show="isShowCollectDialog"> <div class="my-collect-dialog" v-show="isShowCollectDialog">
<div class="dialog-header"> <div class="dialog-header">
<dy-back <dy-back class="close" mode="light" img="back" @click="isShowCollectDialog = false" />
class="close"
mode="light"
img="back"
@click="isShowCollectDialog = false"
/>
<span>我的收藏</span> <span>我的收藏</span>
<dy-back style="opacity: 0" mode="light" img="back" /> <dy-back style="opacity: 0" mode="light" img="back" />
</div> </div>
@@ -181,376 +148,370 @@
</div> </div>
</template> </template>
<script> <script>
import { mapState } from 'pinia' import { mapState } from 'pinia'
import Switches from '../message/components/swtich/switches' import Switches from '../message/components/swtich/switches'
import SlideItemMusic from './components/SlideItemMusic' import SlideItemMusic from './components/SlideItemMusic'
import IndicatorLight from '../../components/slide/IndicatorLight' import IndicatorLight from '../../components/slide/IndicatorLight'
import FromBottomDialog from '../../components/dialog/FromBottomDialog' import FromBottomDialog from '../../components/dialog/FromBottomDialog'
import GuessMusic from './components/GuessMusic' import GuessMusic from './components/GuessMusic'
import CollectMusic from './components/CollectMusic' import CollectMusic from './components/CollectMusic'
import Loading from '../../components/Loading' import Loading from '../../components/Loading'
import { userCollect } from '@/api/user' import { userCollect } from '@/api/user'
import { useBaseStore } from '@/store/pinia' import { useBaseStore } from '@/store/pinia'
//TODO 两个page页面的播放冲突未做 //TODO 两个page页面的播放冲突未做
export default { export default {
name: 'MyMusic', name: 'MyMusic',
components: { components: {
FromBottomDialog, FromBottomDialog,
Switches, Switches,
SlideItemMusic, SlideItemMusic,
IndicatorLight, IndicatorLight,
GuessMusic, GuessMusic,
CollectMusic, CollectMusic,
Loading, Loading
}, },
data() { data() {
return { return {
loading: false, loading: false,
slideIndex: 1, slideIndex: 1,
currentMusic: { currentMusic: {
name: '告白气球', name: '告白气球',
mp3: 'https://mp32.9ku.com/upload/128/2017/02/05/858423.mp3', mp3: 'https://mp32.9ku.com/upload/128/2017/02/05/858423.mp3',
cover: new URL('../../assets/img/music-cover/7.jpg', import.meta.url) cover: new URL('../../assets/img/music-cover/7.jpg', import.meta.url).href,
.href, author: '周杰伦',
author: '周杰伦', duration: 60,
duration: 60, use_count: 37441000,
use_count: 37441000, is_collect: false,
is_collect: false, is_play: false
is_play: false, },
}, collectMusic: [],
collectMusic: [], recommendMusic: [],
recommendMusic: [], guessMusic: [],
guessMusic: [],
isShowCollectDialog: false, isShowCollectDialog: false,
isShowFloatPlay: false, isShowFloatPlay: false,
isAutoPlay: true, isAutoPlay: true,
isCollect: false, isCollect: false,
page2SlideIndex: -1, page2SlideIndex: -1,
page2IsPlay: false, page2IsPlay: false
}
},
computed: {
...mapState(useBaseStore, ['bodyWidth']),
page2Music() {
return this.collectMusic.concat(this.recommendMusic)
}
},
created() {
this.getCollectMusic()
},
methods: {
togglePage2Play() {
this.page2IsPlay = !this.page2IsPlay
if (this.page2IsPlay) {
this.$refs.CollectMusic.play(this.page2SlideIndex)
} else {
this.$refs.CollectMusic.pause()
} }
}, },
computed: { page2PlayMusic(item) {
...mapState(useBaseStore, ['bodyWidth']), this.currentMusic = item
page2Music() { this.isShowFloatPlay = true
return this.collectMusic.concat(this.recommendMusic) this.page2IsPlay = true
}, this.page2SlideIndex = this.page2Music.findIndex((v) => v.name === item.name)
}, this.isShowCollectDialog = true
created() { this.$refs.CollectMusic.play(this.page2SlideIndex)
this.getCollectMusic()
},
methods: {
togglePage2Play() {
this.page2IsPlay = !this.page2IsPlay
if (this.page2IsPlay) {
this.$refs.CollectMusic.play(this.page2SlideIndex)
} else {
this.$refs.CollectMusic.pause()
}
},
page2PlayMusic(item) {
this.currentMusic = item
this.isShowFloatPlay = true
this.page2IsPlay = true
this.page2SlideIndex = this.page2Music.findIndex(
(v) => v.name === item.name,
)
this.isShowCollectDialog = true
this.$refs.CollectMusic.play(this.page2SlideIndex)
},
async getCollectMusic() {
this.loading = true
let res = await userCollect()
this.loading = false
if (res.code === this.SUCCESS) {
this.collectMusic = res.data.music.list.slice(0, 2)
this.guessMusic = this.recommendMusic = res.data.music.list.slice(
2,
-1,
)
}
},
}, },
async getCollectMusic() {
this.loading = true
let res = await userCollect()
this.loading = false
if (res.code === this.SUCCESS) {
this.collectMusic = res.data.music.list.slice(0, 2)
this.guessMusic = this.recommendMusic = res.data.music.list.slice(2, -1)
}
}
} }
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '../../assets/less/index'; @import '../../assets/less/index';
.MyMusic { .MyMusic {
position: fixed;
left: 0;
right: 0;
bottom: 0;
top: 0;
overflow: auto;
color: white;
font-size: 14rem;
.header {
z-index: 9;
position: fixed; position: fixed;
left: 0; width: 100vw;
right: 0;
bottom: 0;
top: 0; top: 0;
overflow: auto; height: 50rem;
color: white; display: flex;
font-size: 14rem; align-items: center;
justify-content: space-between;
padding: 0 var(--page-padding);
box-sizing: border-box;
.header { .back {
z-index: 9; z-index: 10;
position: fixed; }
width: 100vw;
top: 0; .indicator-ctn {
height: 50rem; width: 60vw;
}
}
.my-collect {
margin-top: 50rem;
color: rgba(88, 88, 96);
position: relative;
.wrapper {
padding: var(--page-padding);
padding-bottom: 80rem;
}
.play-all {
margin-bottom: 20rem;
display: flex; display: flex;
align-items: center;
justify-content: space-between; justify-content: space-between;
padding: 0 var(--page-padding); align-items: center;
box-sizing: border-box; color: white;
.back { .left {
z-index: 10; display: flex;
align-items: center;
img {
width: 30rem;
margin-right: 10rem;
}
.num {
font-size: 13rem;
color: gray;
margin-left: 5rem;
}
} }
.indicator-ctn { .menu {
width: 60vw; height: 20rem;
} }
} }
.my-collect { .collect-list,
margin-top: 50rem; .recommend-list {
color: rgba(88, 88, 96); .item {
position: relative; color: white;
.wrapper {
padding: var(--page-padding);
padding-bottom: 80rem;
}
.play-all {
margin-bottom: 20rem;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; margin-bottom: 15rem;
color: white;
.left { .left {
display: flex; display: flex;
align-items: center;
img { .cover-wrapper {
width: 30rem;
margin-right: 10rem; margin-right: 10rem;
} position: relative;
.num {
font-size: 13rem;
color: gray;
margin-left: 5rem;
}
}
.menu {
height: 20rem;
}
}
.collect-list,
.recommend-list {
.item {
color: white;
display: flex;
justify-content: space-between;
margin-bottom: 15rem;
.left {
display: flex;
.cover-wrapper {
margin-right: 10rem;
position: relative;
display: flex;
align-items: center;
justify-content: center;
.cover {
border-radius: 2rem;
@width: 60rem;
width: @width;
object-fit: cover;
height: @width;
}
}
.desc {
display: flex;
flex-direction: column;
justify-content: space-between;
.name {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
max-width: 40vw;
}
.author,
.desc-bottom {
font-size: 12rem;
color: var(--second-text-color);
}
.desc-bottom {
display: flex;
align-items: center;
.tag {
font-size: 10rem;
background: var(--second-btn-color-tran);
padding: 2rem 5rem;
margin-right: 5rem;
}
.duration {
margin-right: 14rem;
position: relative;
}
}
}
}
.right {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center;
.playing-icon { .cover {
width: 24rem; border-radius: 2rem;
@width: 60rem;
width: @width;
object-fit: cover;
height: @width;
}
}
.desc {
display: flex;
flex-direction: column;
justify-content: space-between;
.name {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
max-width: 40vw;
} }
.collect-icon { .author,
margin-left: 30rem; .desc-bottom {
font-size: 12rem;
color: var(--second-text-color);
}
img { .desc-bottom {
width: 24rem; display: flex;
align-items: center;
.tag {
font-size: 10rem;
background: var(--second-btn-color-tran);
padding: 2rem 5rem;
margin-right: 5rem;
}
.duration {
margin-right: 14rem;
position: relative;
} }
} }
} }
} }
}
.recommend {
color: white;
margin: 30rem 0;
display: flex;
align-items: center;
justify-content: space-between;
.right { .right {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between;
.auto-play { .playing-icon {
font-size: 13rem; width: 24rem;
color: var(--second-text-color);
margin-right: 10rem;
} }
}
}
.playing { .collect-icon {
padding: 0 var(--page-padding); margin-left: 30rem;
box-sizing: border-box;
position: fixed;
bottom: 0;
width: 100vw;
color: white;
background: rgba(56, 59, 68);
.playing-wrapper { img {
transform: translateY(-10rem); width: 24rem;
display: flex; }
justify-content: space-between;
align-items: center;
}
.cover-wrapper {
background: rgba(56, 59, 68);
padding: 7rem;
border-radius: 50%;
.cover {
background: rgba(97, 98, 103);
padding: 3rem;
@width: 50rem;
height: @width;
width: @width;
object-fit: cover;
border-radius: 50%;
} }
} }
.name {
margin: 0 10rem;
flex: 1;
}
.option {
width: 38rem;
height: 38rem;
margin-right: 20rem;
}
.menu-list {
width: 28rem;
height: 28rem;
}
} }
} }
.my-collect-dialog { .recommend {
position: fixed; color: white;
z-index: 11; margin: 30rem 0;
width: 100vw; display: flex;
height: calc(var(--vh, 1vh) * 100); align-items: center;
top: 0; justify-content: space-between;
background: rgb(136, 132, 133);
.dialog-header { .right {
z-index: 9;
font-size: 16rem;
position: fixed;
top: 0;
width: 100vw;
padding: var(--page-padding);
box-sizing: border-box;
height: 50rem;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
.close { .auto-play {
transform: rotate(-90deg) !important; font-size: 13rem;
color: var(--second-text-color);
margin-right: 10rem;
} }
} }
} }
.my-collect-dialog-enter-active, .playing {
.my-collect-dialog-leave-active { padding: 0 var(--page-padding);
transition-duration: 300ms; box-sizing: border-box;
transform: translateY(0); position: fixed;
} bottom: 0;
width: 100vw;
color: white;
background: rgba(56, 59, 68);
.my-collect-dialog-enter-from, .playing-wrapper {
.my-collect-dialog-leave-to { transform: translateY(-10rem);
transition-duration: 300ms; display: flex;
transform: translateY(calc(var(--vh, 1vh) * 100)); justify-content: space-between;
} align-items: center;
}
.float-play-enter-active, .cover-wrapper {
.float-play-leave-active { background: rgba(56, 59, 68);
transition-duration: 200ms; padding: 7rem;
transform: translateY(0); border-radius: 50%;
}
.float-play-enter-from, .cover {
.float-play-leave-to { background: rgba(97, 98, 103);
transition-duration: 200ms; padding: 3rem;
transform: translateY(100%); @width: 50rem;
height: @width;
width: @width;
object-fit: cover;
border-radius: 50%;
}
}
.name {
margin: 0 10rem;
flex: 1;
}
.option {
width: 38rem;
height: 38rem;
margin-right: 20rem;
}
.menu-list {
width: 28rem;
height: 28rem;
}
} }
} }
.my-collect-dialog {
position: fixed;
z-index: 11;
width: 100vw;
height: calc(var(--vh, 1vh) * 100);
top: 0;
background: rgb(136, 132, 133);
.dialog-header {
z-index: 9;
font-size: 16rem;
position: fixed;
top: 0;
width: 100vw;
padding: var(--page-padding);
box-sizing: border-box;
height: 50rem;
display: flex;
align-items: center;
justify-content: space-between;
.close {
transform: rotate(-90deg) !important;
}
}
}
.my-collect-dialog-enter-active,
.my-collect-dialog-leave-active {
transition-duration: 300ms;
transform: translateY(0);
}
.my-collect-dialog-enter-from,
.my-collect-dialog-leave-to {
transition-duration: 300ms;
transform: translateY(calc(var(--vh, 1vh) * 100));
}
.float-play-enter-active,
.float-play-leave-active {
transition-duration: 200ms;
transform: translateY(0);
}
.float-play-enter-from,
.float-play-leave-to {
transition-duration: 200ms;
transform: translateY(100%);
}
}
</style> </style>

View File

@@ -21,69 +21,69 @@
</div> </div>
</template> </template>
<script> <script>
import { mapState } from 'pinia' import { mapState } from 'pinia'
import FromBottomDialog from '../../components/dialog/FromBottomDialog' import FromBottomDialog from '../../components/dialog/FromBottomDialog'
import { useBaseStore } from '@/store/pinia' import { useBaseStore } from '@/store/pinia'
export default { export default {
name: 'MyRequestUpdate', name: 'MyRequestUpdate',
components: { FromBottomDialog }, components: { FromBottomDialog },
data() { data() {
return {} return {}
}, },
computed: { computed: {
...mapState(useBaseStore, ['friends']), ...mapState(useBaseStore, ['friends'])
}, },
created() {}, created() {},
methods: {}, methods: {}
} }
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '../../assets/less/index'; @import '../../assets/less/index';
.RequestUpdate { .RequestUpdate {
position: fixed; position: fixed;
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
top: 0; top: 0;
overflow: auto; overflow: auto;
color: white; color: white;
font-size: 14rem; font-size: 14rem;
.content { .content {
padding: 60rem 15rem 60rem 15rem; padding: 60rem 15rem 60rem 15rem;
.request { .request {
.list { .list {
.item { .item {
padding: 10rem 0; padding: 10rem 0;
display: flex;
justify-content: space-between;
align-items: center;
.left {
display: flex; display: flex;
justify-content: space-between;
align-items: center; align-items: center;
@width: 42rem;
.left { img {
display: flex; width: @width;
align-items: center; height: @width;
@width: 42rem; border-radius: 50%;
margin-right: 10rem;
img {
width: @width;
height: @width;
border-radius: 50%;
margin-right: 10rem;
}
} }
}
.time { .time {
font-size: 12rem; font-size: 12rem;
color: var(--second-text-color); color: var(--second-text-color);
}
} }
} }
} }
} }
} }
}
</style> </style>

View File

@@ -24,9 +24,7 @@
<div class="request"> <div class="request">
<!-- <div class="title">近7天收到1次求更新</div>--> <!-- <div class="title">近7天收到1次求更新</div>-->
<!-- <div class="subtitle f12">上次发布作品2020-08-01 上次开播昨天23:12</div>--> <!-- <div class="subtitle f12">上次发布作品2020-08-01 上次开播昨天23:12</div>-->
<div class="subtitle f12"> <div class="subtitle f12">历史求更新粉丝送礼后7天未开播则退还礼物</div>
历史求更新粉丝送礼后7天未开播则退还礼物
</div>
<div class="list"> <div class="list">
<div class="item" v-for="item in friends.all"> <div class="item" v-for="item in friends.all">
<div class="left"> <div class="left">
@@ -40,11 +38,7 @@
</div> </div>
</div> </div>
<div class="buttons"> <div class="buttons">
<dy-button <dy-button type="white" :border="false" :active="false" @click="$nav('/publish')"
type="white"
:border="false"
:active="false"
@click="$nav('/publish')"
>发布作品</dy-button >发布作品</dy-button
> >
<dy-button type="primary" :active="false" @click="$no">去直播</dy-button> <dy-button type="primary" :active="false" @click="$no">去直播</dy-button>
@@ -60,161 +54,159 @@
<div class="l-row" @click="toggleRequestUpdate"> <div class="l-row" @click="toggleRequestUpdate">
{{ openRequestUpdate ? '关闭' : '开启' }}求更新提醒 {{ openRequestUpdate ? '关闭' : '开启' }}求更新提醒
</div> </div>
<div class="l-row" @click="$nav('/me/my-request-update')"> <div class="l-row" @click="$nav('/me/my-request-update')">我的求更新提醒</div>
我的求更新提醒
</div>
<div class="space"></div> <div class="space"></div>
<div class="l-row" @click="isShowOption = false">取消</div> <div class="l-row" @click="isShowOption = false">取消</div>
</from-bottom-dialog> </from-bottom-dialog>
</div> </div>
</template> </template>
<script> <script>
import { mapState } from 'pinia' import { mapState } from 'pinia'
import FromBottomDialog from '../../components/dialog/FromBottomDialog' import FromBottomDialog from '../../components/dialog/FromBottomDialog'
import { useBaseStore } from '@/store/pinia' import { useBaseStore } from '@/store/pinia'
export default { export default {
name: 'RequestUpdate', name: 'RequestUpdate',
components: { FromBottomDialog }, components: { FromBottomDialog },
data() { data() {
return { return {
isShowOption: false, isShowOption: false,
loading: false, loading: false,
openRequestUpdate: true, openRequestUpdate: true
}
},
computed: {
...mapState(useBaseStore, ['friends'])
},
created() {
this.getData()
},
methods: {
async getData() {
this.loading = true
await this.$sleep(700)
this.loading = false
},
toggleRequestUpdate() {
this.openRequestUpdate = !this.openRequestUpdate
this.isShowOption = false
if (this.openRequestUpdate) {
this.$notice('提醒已开启,再次点击可关闭')
} else {
this.$notice('提醒已关闭,再次点击可开启')
} }
}, }
computed: {
...mapState(useBaseStore, ['friends']),
},
created() {
this.getData()
},
methods: {
async getData() {
this.loading = true
await this.$sleep(700)
this.loading = false
},
toggleRequestUpdate() {
this.openRequestUpdate = !this.openRequestUpdate
this.isShowOption = false
if (this.openRequestUpdate) {
this.$notice('提醒已开启,再次点击可关闭')
} else {
this.$notice('提醒已关闭,再次点击可开启')
}
},
},
} }
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '../../assets/less/index'; @import '../../assets/less/index';
.RequestUpdate { .RequestUpdate {
position: fixed; position: fixed;
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
top: 0; top: 0;
overflow: auto; overflow: auto;
color: white; color: white;
font-size: 14rem; font-size: 14rem;
.content { .content {
padding: 60rem 15rem 60rem 15rem; padding: 60rem 15rem 60rem 15rem;
.none { .none {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
img { img {
margin-top: 100rem; margin-top: 100rem;
height: 120rem; height: 120rem;
}
} }
}
.request { .request {
.list { .list {
margin-top: var(--page-padding); margin-top: var(--page-padding);
.item { .item {
padding: 10rem 0; padding: 10rem 0;
display: flex;
justify-content: space-between;
align-items: center;
.left {
display: flex; display: flex;
justify-content: space-between;
align-items: center; align-items: center;
@width: 42rem;
.left { img {
display: flex; width: @width;
align-items: center; height: @width;
@width: 42rem; border-radius: 50%;
margin-right: 10rem;
img {
width: @width;
height: @width;
border-radius: 50%;
margin-right: 10rem;
}
} }
}
.time { .time {
font-size: 12rem; font-size: 12rem;
color: var(--second-text-color); color: var(--second-text-color);
}
} }
} }
} }
.title {
margin-top: 10rem;
font-size: 16rem;
}
.subtitle {
margin-top: 10rem;
font-size: 14rem;
color: var(--second-text-color);
}
} }
.l-row { .title {
padding: 15rem; margin-top: 10rem;
color: black; font-size: 16rem;
text-align: center; }
.subtitle {
margin-top: 10rem;
font-size: 14rem;
color: var(--second-text-color);
}
}
.l-row {
padding: 15rem;
color: black;
text-align: center;
&:nth-child(2) {
border-bottom: 1px solid gainsboro;
}
}
.space {
height: 10rem;
background: whitesmoke;
}
.buttons {
position: fixed;
padding: 0 15rem 15rem 15rem;
bottom: 0;
left: 0;
right: 0;
display: flex;
align-items: center;
background: var(--main-bg);
.button {
flex: 1;
&:nth-child(1) {
margin-right: 5rem;
}
&:nth-child(2) { &:nth-child(2) {
border-bottom: 1px solid gainsboro; margin-left: 5rem;
}
}
.space {
height: 10rem;
background: whitesmoke;
}
.buttons {
position: fixed;
padding: 0 15rem 15rem 15rem;
bottom: 0;
left: 0;
right: 0;
display: flex;
align-items: center;
background: var(--main-bg);
.button {
flex: 1;
&:nth-child(1) {
margin-right: 5rem;
}
&:nth-child(2) {
margin-left: 5rem;
}
} }
} }
} }
}
</style> </style>

View File

@@ -7,11 +7,7 @@
</BaseHeader> </BaseHeader>
<div class="content"> <div class="content">
<div class="list"> <div class="list">
<div <div class="item" v-for="(item, index) in list" @click="togglePlay(item, list)">
class="item"
v-for="(item, index) in list"
@click="togglePlay(item, list)"
>
<div class="music"> <div class="music">
<div class="cover-wrapper"> <div class="cover-wrapper">
<img v-lazy="$imgPreview(item.cover)" alt="" class="cover" /> <img v-lazy="$imgPreview(item.cover)" alt="" class="cover" />
@@ -82,195 +78,104 @@
</div> </div>
</template> </template>
<script> <script>
import { mapState } from 'pinia' import { mapState } from 'pinia'
import { userCollect } from '@/api/user' import { userCollect } from '@/api/user'
import { useBaseStore } from '@/store/pinia' import { useBaseStore } from '@/store/pinia'
export default { export default {
name: 'MusicCollect', name: 'MusicCollect',
components: {}, components: {},
props: {}, props: {},
data() { data() {
return { return {
loading: false, loading: false,
list: [], list: [],
audio: new Audio(), audio: new Audio(),
currentItem: null, currentItem: null,
step: null, step: null,
process: 0, process: 0
}
},
computed: {
...mapState(useBaseStore, ['bodyWidth'])
},
created() {
this.getData()
},
mounted() {
this.audio.addEventListener('loadedmetadata', (e) => {
this.currentItem.duration = this.audio.duration
this.step = this.bodyWidth / Math.floor(this.audio.duration)
})
this.audio.addEventListener('timeupdate', (e) => {
this.process = Math.ceil(e.target.currentTime) * this.step
})
},
methods: {
async getData() {
this.loading = true
let res = await userCollect()
this.loading = false
if (res.code === this.SUCCESS) {
this.list = res.data.music.list
} }
}, },
computed: { togglePlay(item, list) {
...mapState(useBaseStore, ['bodyWidth']), list.map((v) => {
}, if (v.name !== item.name) {
created() { v.is_play = false
this.getData()
},
mounted() {
this.audio.addEventListener('loadedmetadata', (e) => {
this.currentItem.duration = this.audio.duration
this.step = this.bodyWidth / Math.floor(this.audio.duration)
})
this.audio.addEventListener('timeupdate', (e) => {
this.process = Math.ceil(e.target.currentTime) * this.step
})
},
methods: {
async getData() {
this.loading = true
let res = await userCollect()
this.loading = false
if (res.code === this.SUCCESS) {
this.list = res.data.music.list
} }
}, })
togglePlay(item, list) { item.is_play = !item.is_play
list.map((v) => { if (item.is_play) {
if (v.name !== item.name) { if (this.currentItem) {
v.is_play = false if (this.currentItem.name !== item.name) {
}
})
item.is_play = !item.is_play
if (item.is_play) {
if (this.currentItem) {
if (this.currentItem.name !== item.name) {
this.audio.pause()
this.audio.src = item.mp3
this.audio.currentTime = 0
}
} else {
this.audio.pause() this.audio.pause()
this.audio.src = item.mp3 this.audio.src = item.mp3
this.audio.currentTime = 0 this.audio.currentTime = 0
} }
this.audio.play()
this.audio.addEventListener('ended', () => (item.is_play = false))
} else { } else {
this.stopPlay() this.audio.pause()
this.audio.src = item.mp3
this.audio.currentTime = 0
} }
this.currentItem = item this.audio.play()
}, this.audio.addEventListener('ended', () => (item.is_play = false))
stopPlay() { } else {
this.audio.pause() this.stopPlay()
// this.audio.currentTime = 0 }
this.audio.removeEventListener('ended', null) this.currentItem = item
},
},
unmounted() {
this.stopPlay()
}, },
stopPlay() {
this.audio.pause()
// this.audio.currentTime = 0
this.audio.removeEventListener('ended', null)
}
},
unmounted() {
this.stopPlay()
} }
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
.MusicCollect { .MusicCollect {
position: fixed; position: fixed;
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
top: 0; top: 0;
overflow: auto; overflow: auto;
color: white; color: white;
font-size: 14rem; font-size: 14rem;
.content { .content {
padding-top: 60rem; padding-top: 60rem;
.list { .list {
.item { .item {
padding: 20rem 15rem; padding: 20rem 15rem;
padding-bottom: 0; padding-bottom: 0;
display: flex;
align-items: center;
justify-content: space-between;
.music {
display: flex;
.cover-wrapper {
margin-right: 10rem;
position: relative;
display: flex;
align-items: center;
justify-content: center;
.play {
width: 30rem;
height: 30rem;
position: absolute;
}
.cover {
border-radius: 2rem;
@width: 60rem;
width: @width;
object-fit: cover;
height: @width;
}
}
.desc {
display: flex;
flex-direction: column;
justify-content: space-between;
.name {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
max-width: 40vw;
}
.author,
.desc-bottom {
font-size: 12rem;
color: var(--second-text-color);
}
.desc-bottom {
display: flex;
.duration {
margin-right: 14rem;
position: relative;
}
}
}
}
.option {
img {
width: 20rem;
height: 20rem;
margin-left: 20rem;
}
}
}
}
}
.float-play-music {
position: fixed;
bottom: 0;
width: 100vw;
background: var(--main-bg);
display: flex;
align-items: center;
justify-content: space-between;
.process {
position: absolute;
top: 0;
z-index: 2;
height: 1px;
width: 50vw;
background: yellow;
}
.music-wrapper {
width: 100vw;
border-top: 1px solid #414141;
padding: 10rem 15rem;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
@@ -293,9 +198,9 @@
.cover { .cover {
border-radius: 2rem; border-radius: 2rem;
object-fit: cover; @width: 60rem;
@width: 50rem;
width: @width; width: @width;
object-fit: cover;
height: @width; height: @width;
} }
} }
@@ -330,10 +235,101 @@
} }
.option { .option {
.button { img {
width: 20rem;
height: 20rem;
margin-left: 20rem;
} }
} }
} }
} }
} }
.float-play-music {
position: fixed;
bottom: 0;
width: 100vw;
background: var(--main-bg);
display: flex;
align-items: center;
justify-content: space-between;
.process {
position: absolute;
top: 0;
z-index: 2;
height: 1px;
width: 50vw;
background: yellow;
}
.music-wrapper {
width: 100vw;
border-top: 1px solid #414141;
padding: 10rem 15rem;
display: flex;
align-items: center;
justify-content: space-between;
.music {
display: flex;
.cover-wrapper {
margin-right: 10rem;
position: relative;
display: flex;
align-items: center;
justify-content: center;
.play {
width: 30rem;
height: 30rem;
position: absolute;
}
.cover {
border-radius: 2rem;
object-fit: cover;
@width: 50rem;
width: @width;
height: @width;
}
}
.desc {
display: flex;
flex-direction: column;
justify-content: space-between;
.name {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
max-width: 40vw;
}
.author,
.desc-bottom {
font-size: 12rem;
color: var(--second-text-color);
}
.desc-bottom {
display: flex;
.duration {
margin-right: 14rem;
position: relative;
}
}
}
}
.option {
.button {
}
}
}
}
}
</style> </style>

View File

@@ -15,75 +15,73 @@
</div> </div>
</template> </template>
<script> <script>
import resource from '../../../assets/data/resource' import resource from '../../../assets/data/resource'
import Posters from '../../../components/Posters' import Posters from '../../../components/Posters'
import Scroll from '../../../components/Scroll' import Scroll from '../../../components/Scroll'
import { myVideo } from '@/api/videos' import { myVideo } from '@/api/videos'
export default { export default {
name: 'VideoCollect', name: 'VideoCollect',
components: { components: {
Posters, Posters,
Scroll, Scroll
}, },
data() { data() {
return { return {
loading: false, loading: false,
total: 0, total: 0,
pageNo: 0, pageNo: 0,
pageSize: 15, pageSize: 15,
videos: [], videos: []
}
},
computed: {},
created() {
this.loadData(true)
},
methods: {
async loadData(init = false) {
if (this.loading) return
if (!init) {
if (this.total <= this.videos.length) {
return
}
this.pageNo++
} }
}, this.loading = true
computed: {}, let res = await myVideo({
created() { pageNo: this.pageNo,
this.loadData(true) pageSize: this.pageSize
}, })
methods: { this.loading = false
async loadData(init = false) { if (res.code === this.SUCCESS) {
if (this.loading) return this.videos = this.videos.concat(res.data.list)
if (!init) { this.total = res.data.total
if (this.total <= this.videos.length) {
return
}
this.pageNo++
}
this.loading = true
let res = await myVideo({
pageNo: this.pageNo,
pageSize: this.pageSize,
})
this.loading = false
if (res.code === this.SUCCESS) {
this.videos = this.videos.concat(res.data.list)
this.total = res.data.total
}
},
},
}
</script>
<style scoped lang="less">
@import '../../../assets/less/index';
.VideoCollect {
position: fixed;
left: 0;
right: 0;
bottom: 0;
top: 0;
overflow: auto;
color: white;
font-size: 14rem;
.content {
padding-top: var(--common-header-height);
.Scroll {
height: calc(
var(--vh, 1vh) * 100 - var(--common-header-height)
) !important;
} }
} }
} }
}
</script>
<style scoped lang="less">
@import '../../../assets/less/index';
.VideoCollect {
position: fixed;
left: 0;
right: 0;
bottom: 0;
top: 0;
overflow: auto;
color: white;
font-size: 14rem;
.content {
padding-top: var(--common-header-height);
.Scroll {
height: calc(var(--vh, 1vh) * 100 - var(--common-header-height)) !important;
}
}
}
</style> </style>

View File

@@ -30,11 +30,7 @@
<div class="left">待播清单</div> <div class="left">待播清单</div>
<div class="right" @click="isLoop = !isLoop"> <div class="right" @click="isLoop = !isLoop">
<img v-show="isLoop" src="@/assets/img/icon/me/loop.png" alt="" /> <img v-show="isLoop" src="@/assets/img/icon/me/loop.png" alt="" />
<img <img v-show="!isLoop" src="@/assets/img/icon/me/play-normal.png" alt="" />
v-show="!isLoop"
src="@/assets/img/icon/me/play-normal.png"
alt=""
/>
<span>{{ isLoop ? '单曲循环' : '顺序播放' }}</span> <span>{{ isLoop ? '单曲循环' : '顺序播放' }}</span>
</div> </div>
</div> </div>
@@ -74,207 +70,207 @@
</div> </div>
</template> </template>
<script> <script>
import FromBottomDialog from '../../../components/dialog/FromBottomDialog' import FromBottomDialog from '../../../components/dialog/FromBottomDialog'
import Switches from '../../message/components/swtich/switches' import Switches from '../../message/components/swtich/switches'
import SlideItemMusic from './SlideItemMusic' import SlideItemMusic from './SlideItemMusic'
import IndicatorLight from '../../../components/slide/IndicatorLight' import IndicatorLight from '../../../components/slide/IndicatorLight'
import Share from '../../../components/Share' import Share from '../../../components/Share'
import ShareToFriend from '../../home/components/ShareToFriend' import ShareToFriend from '../../home/components/ShareToFriend'
import SlideVertical from '@/components/slide/SlideVertical.vue' import SlideVertical from '@/components/slide/SlideVertical.vue'
export default { export default {
name: 'GuessMusic', name: 'GuessMusic',
components: { components: {
SlideVertical, SlideVertical,
FromBottomDialog, FromBottomDialog,
Switches, Switches,
SlideItemMusic, SlideItemMusic,
IndicatorLight, IndicatorLight,
Share, Share,
ShareToFriend, ShareToFriend
},
props: {
list: {
type: Array,
default: []
}, },
props: { page2SlideIndex: {
list: { type: Number,
type: Array, default: 0
default: [], }
},
data() {
return {
slideCanMove: true,
isShowShareToFriend: false,
isShowList: false,
isSharing: false,
isLoop: false,
collectSlideIndex: 0,
isShowCollectDialog: false,
itemRefs: []
}
},
computed: {
activeIndex: {
get() {
return this.page2SlideIndex
}, },
page2SlideIndex: { set(val) {
type: Number, this.$emit('update:page2SlideIndex', val)
default: 0, }
}, }
}, },
data() { created() {},
return { watch: {
slideCanMove: true, activeIndex(newVal, oldVal) {
isShowShareToFriend: false, this.itemRefs.map((ref) => {
isShowList: false, ref.togglePlay(false)
isSharing: false, })
isLoop: false, this.itemRefs[newVal].togglePlay(true, true)
collectSlideIndex: 0, }
isShowCollectDialog: false, },
itemRefs: [], methods: {
previous() {
if (this.activeIndex > 0) {
this.play(this.activeIndex - 1)
} }
}, },
computed: { next() {
activeIndex: { if (this.activeIndex < this.list.length - 1) {
get() { this.play(this.activeIndex + 1)
return this.page2SlideIndex }
},
set(val) {
this.$emit('update:page2SlideIndex', val)
},
},
}, },
created() {}, delayShowDialog(cb) {
watch: { setTimeout(() => {
activeIndex(newVal, oldVal) { cb()
this.itemRefs.map((ref) => { }, 100)
ref.togglePlay(false)
})
this.itemRefs[newVal].togglePlay(true, true)
},
}, },
methods: { setItemRef(el) {
previous() { if (el) {
if (this.activeIndex > 0) { this.itemRefs.push(el)
this.play(this.activeIndex - 1) }
}
},
next() {
if (this.activeIndex < this.list.length - 1) {
this.play(this.activeIndex + 1)
}
},
delayShowDialog(cb) {
setTimeout(() => {
cb()
}, 100)
},
setItemRef(el) {
if (el) {
this.itemRefs.push(el)
}
},
play(index) {
this.activeIndex = index
this.itemRefs.map((ref) => {
ref.togglePlay(false)
})
this.itemRefs[index].togglePlay(true, true)
},
pause() {
this.itemRefs.map((ref) => {
ref.togglePlay(false)
})
},
}, },
play(index) {
this.activeIndex = index
this.itemRefs.map((ref) => {
ref.togglePlay(false)
})
this.itemRefs[index].togglePlay(true, true)
},
pause() {
this.itemRefs.map((ref) => {
ref.togglePlay(false)
})
}
} }
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
#CollectMusic { #CollectMusic {
//width: 100vw; //width: 100vw;
//height: calc(var(--vh, 1vh) * 100); //height: calc(var(--vh, 1vh) * 100);
position: fixed;
left: 0;
right: 0;
bottom: 0;
top: 0;
overflow: auto;
color: white;
font-size: 14rem;
}
.music-list-dialog {
height: 70vh;
@bg-color: #1e1d1d;
background: @bg-color;
.music-list-header {
position: fixed; position: fixed;
left: 0; width: 100vw;
right: 0;
bottom: 0;
top: 0;
overflow: auto;
color: white;
font-size: 14rem;
}
.music-list-dialog {
height: 70vh;
@bg-color: #1e1d1d;
background: @bg-color; background: @bg-color;
box-sizing: border-box;
border-bottom: 1px solid #2a2828;
display: flex;
justify-content: space-between;
align-items: center;
height: 50rem;
padding: 0 var(--page-padding);
border-radius: 15rem 15rem 0 0;
z-index: 9;
.music-list-header { .left {
position: fixed; font-size: 16rem;
width: 100vw;
background: @bg-color;
box-sizing: border-box;
border-bottom: 1px solid #2a2828;
display: flex;
justify-content: space-between;
align-items: center;
height: 50rem;
padding: 0 var(--page-padding);
border-radius: 15rem 15rem 0 0;
z-index: 9;
.left {
font-size: 16rem;
}
.right {
display: flex;
align-items: center;
font-size: 12rem;
img {
width: 20rem;
margin-right: 5rem;
}
}
} }
.wrapper { .right {
padding-top: 50rem;
}
.l-row {
background: @bg-color;
height: 50rem;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 var(--page-padding);
&.active {
color: var(--primary-btn-color);
}
.left {
display: flex;
align-items: center;
.author {
font-size: 12rem;
color: var(--second-text-color);
margin-left: 20rem;
position: relative;
display: flex;
align-items: center;
&:after {
content: '';
width: 6rem;
height: 0.5px;
background: var(--second-text-color);
position: absolute;
left: -12rem;
}
}
.play-icon {
width: 15rem;
margin-right: 10rem;
}
}
.right {
width: 15rem;
}
}
.footer {
background: @bg-color;
border-top: 1px solid #2a2828;
height: 60rem;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; font-size: 12rem;
img {
width: 20rem;
margin-right: 5rem;
}
} }
} }
.wrapper {
padding-top: 50rem;
}
.l-row {
background: @bg-color;
height: 50rem;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 var(--page-padding);
&.active {
color: var(--primary-btn-color);
}
.left {
display: flex;
align-items: center;
.author {
font-size: 12rem;
color: var(--second-text-color);
margin-left: 20rem;
position: relative;
display: flex;
align-items: center;
&:after {
content: '';
width: 6rem;
height: 0.5px;
background: var(--second-text-color);
position: absolute;
left: -12rem;
}
}
.play-icon {
width: 15rem;
margin-right: 10rem;
}
}
.right {
width: 15rem;
}
}
.footer {
background: @bg-color;
border-top: 1px solid #2a2828;
height: 60rem;
display: flex;
align-items: center;
justify-content: center;
}
}
</style> </style>

View File

@@ -30,11 +30,7 @@
<div class="left">待播清单</div> <div class="left">待播清单</div>
<div class="right" @click="isLoop = !isLoop"> <div class="right" @click="isLoop = !isLoop">
<img v-show="isLoop" src="@/assets/img/icon/me/loop.png" alt="" /> <img v-show="isLoop" src="@/assets/img/icon/me/loop.png" alt="" />
<img <img v-show="!isLoop" src="@/assets/img/icon/me/play-normal.png" alt="" />
v-show="!isLoop"
src="@/assets/img/icon/me/play-normal.png"
alt=""
/>
<span>{{ isLoop ? '单曲循环' : '顺序播放' }}</span> <span>{{ isLoop ? '单曲循环' : '顺序播放' }}</span>
</div> </div>
</div> </div>
@@ -74,189 +70,189 @@
</div> </div>
</template> </template>
<script> <script>
import FromBottomDialog from '../../../components/dialog/FromBottomDialog' import FromBottomDialog from '../../../components/dialog/FromBottomDialog'
import Switches from '../../message/components/swtich/switches' import Switches from '../../message/components/swtich/switches'
import SlideItemMusic from './SlideItemMusic' import SlideItemMusic from './SlideItemMusic'
import IndicatorLight from '../../../components/slide/IndicatorLight' import IndicatorLight from '../../../components/slide/IndicatorLight'
import Share from '../../../components/Share' import Share from '../../../components/Share'
import ShareToFriend from '../../home/components/ShareToFriend' import ShareToFriend from '../../home/components/ShareToFriend'
import SlideVertical from '@/components/slide/SlideVertical.vue' import SlideVertical from '@/components/slide/SlideVertical.vue'
export default { export default {
name: 'GuessMusic', name: 'GuessMusic',
components: { components: {
SlideVertical, SlideVertical,
FromBottomDialog, FromBottomDialog,
Switches, Switches,
SlideItemMusic, SlideItemMusic,
IndicatorLight, IndicatorLight,
Share, Share,
ShareToFriend, ShareToFriend
}, },
props: { props: {
list: { list: {
type: Array, type: Array,
default: [], default: []
}, }
}, },
data() { data() {
return { return {
slideCanMove: true, slideCanMove: true,
isShowShareToFriend: false, isShowShareToFriend: false,
isShowList: false, isShowList: false,
isSharing: false, isSharing: false,
isLoop: false, isLoop: false,
guessSlideIndex: 0, guessSlideIndex: 0,
isShowCollectDialog: false, isShowCollectDialog: false,
itemRefs: [], itemRefs: []
}
},
watch: {
guessSlideIndex(newVal, oldVal) {
this.itemRefs.map((ref) => {
ref.togglePlay(false)
})
this.itemRefs[newVal].togglePlay(true, true)
}
},
computed: {},
created() {},
methods: {
previous() {
if (this.guessSlideIndex > 0) {
this.play(this.guessSlideIndex - 1)
} }
}, },
watch: { next() {
guessSlideIndex(newVal, oldVal) { if (this.guessSlideIndex < this.list.length - 1) {
this.itemRefs.map((ref) => { this.play(this.guessSlideIndex + 1)
ref.togglePlay(false) }
})
this.itemRefs[newVal].togglePlay(true, true)
},
}, },
computed: {}, delayShowDialog(cb) {
created() {}, setTimeout(() => {
methods: { cb()
previous() { }, 100)
if (this.guessSlideIndex > 0) {
this.play(this.guessSlideIndex - 1)
}
},
next() {
if (this.guessSlideIndex < this.list.length - 1) {
this.play(this.guessSlideIndex + 1)
}
},
delayShowDialog(cb) {
setTimeout(() => {
cb()
}, 100)
},
setItemRef(el) {
if (el) {
this.itemRefs.push(el)
}
},
play(index) {
this.guessSlideIndex = index
this.itemRefs.map((ref) => {
ref.togglePlay(false)
})
this.itemRefs[index].togglePlay(true, true)
},
}, },
setItemRef(el) {
if (el) {
this.itemRefs.push(el)
}
},
play(index) {
this.guessSlideIndex = index
this.itemRefs.map((ref) => {
ref.togglePlay(false)
})
this.itemRefs[index].togglePlay(true, true)
}
} }
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
#GuessMusic { #GuessMusic {
//width: 100vw; //width: 100vw;
//height: calc(var(--vh, 1vh) * 100); //height: calc(var(--vh, 1vh) * 100);
position: fixed;
left: 0;
right: 0;
bottom: 0;
top: 0;
overflow: auto;
color: white;
font-size: 14rem;
}
.music-list-dialog {
height: 70vh;
@bg-color: #1e1d1d;
background: @bg-color;
.music-list-header {
position: fixed; position: fixed;
left: 0; width: 100vw;
right: 0;
bottom: 0;
top: 0;
overflow: auto;
color: white;
font-size: 14rem;
}
.music-list-dialog {
height: 70vh;
@bg-color: #1e1d1d;
background: @bg-color; background: @bg-color;
box-sizing: border-box;
border-bottom: 1px solid #2a2828;
display: flex;
justify-content: space-between;
align-items: center;
height: 50rem;
padding: 0 var(--page-padding);
border-radius: 15rem 15rem 0 0;
z-index: 9;
.music-list-header { .left {
position: fixed; font-size: 16rem;
width: 100vw;
background: @bg-color;
box-sizing: border-box;
border-bottom: 1px solid #2a2828;
display: flex;
justify-content: space-between;
align-items: center;
height: 50rem;
padding: 0 var(--page-padding);
border-radius: 15rem 15rem 0 0;
z-index: 9;
.left {
font-size: 16rem;
}
.right {
display: flex;
align-items: center;
font-size: 12rem;
img {
width: 20rem;
margin-right: 5rem;
}
}
} }
.wrapper { .right {
padding-top: 50rem;
}
.l-row {
background: @bg-color;
height: 50rem;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 var(--page-padding);
&.active {
color: var(--primary-btn-color);
}
.left {
display: flex;
align-items: center;
.author {
font-size: 12rem;
color: var(--second-text-color);
margin-left: 20rem;
position: relative;
display: flex;
align-items: center;
&:after {
content: '';
width: 6rem;
height: 0.5px;
background: var(--second-text-color);
position: absolute;
left: -12rem;
}
}
.play-icon {
width: 15rem;
margin-right: 10rem;
}
}
.right {
width: 15rem;
}
}
.footer {
background: @bg-color;
border-top: 1px solid #2a2828;
height: 60rem;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; font-size: 12rem;
img {
width: 20rem;
margin-right: 5rem;
}
} }
} }
.wrapper {
padding-top: 50rem;
}
.l-row {
background: @bg-color;
height: 50rem;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 var(--page-padding);
&.active {
color: var(--primary-btn-color);
}
.left {
display: flex;
align-items: center;
.author {
font-size: 12rem;
color: var(--second-text-color);
margin-left: 20rem;
position: relative;
display: flex;
align-items: center;
&:after {
content: '';
width: 6rem;
height: 0.5px;
background: var(--second-text-color);
position: absolute;
left: -12rem;
}
}
.play-icon {
width: 15rem;
margin-right: 10rem;
}
}
.right {
width: 15rem;
}
}
.footer {
background: @bg-color;
border-top: 1px solid #2a2828;
height: 60rem;
display: flex;
align-items: center;
justify-content: center;
}
}
</style> </style>

View File

@@ -4,22 +4,14 @@
<div class="cover"> <div class="cover">
<img v-lazy="$imgPreview(modelValue.cover)" alt="" /> <img v-lazy="$imgPreview(modelValue.cover)" alt="" />
</div> </div>
<div <div class="lyrics-wrapper" ref="lyrics-wrapper" @click="isFullLyrics = true">
class="lyrics-wrapper"
ref="lyrics-wrapper"
@click="isFullLyrics = true"
>
<div class="container"> <div class="container">
<div class="lyrics" v-for="item in lyricsFullTexts">{{ item.c }}</div> <div class="lyrics" v-for="item in lyricsFullTexts">{{ item.c }}</div>
</div> </div>
</div> </div>
<!-- <div class="lyrics-mask" @click="isFullLyrics = true"></div>--> <!-- <div class="lyrics-mask" @click="isFullLyrics = true"></div>-->
</div> </div>
<div <div class="lyrics-full" v-show="isFullLyrics" @click="isFullLyrics = false">
class="lyrics-full"
v-show="isFullLyrics"
@click="isFullLyrics = false"
>
<div <div
class="list" class="list"
style="overflow: auto" style="overflow: auto"
@@ -82,10 +74,7 @@
@click="$emit('update:isLoop', true)" @click="$emit('update:isLoop', true)"
/> />
<div class="center"> <div class="center">
<img <img src="@/assets/img/icon/me/previous.png" @click="slide('previous')" />
src="@/assets/img/icon/me/previous.png"
@click="slide('previous')"
/>
<img <img
v-show="isPlay" v-show="isPlay"
class="control" class="control"
@@ -100,445 +89,429 @@
/> />
<img src="@/assets/img/icon/me/next.png" @click="slide('next')" /> <img src="@/assets/img/icon/me/next.png" @click="slide('next')" />
</div> </div>
<img <img src="@/assets/img/icon/me/music-list.png" @click="$emit('showList')" />
src="@/assets/img/icon/me/music-list.png"
@click="$emit('showList')"
/>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import { nextTick } from 'vue' import { nextTick } from 'vue'
import globalMethods from '../../../utils' import globalMethods from '../../../utils'
import gaobaiqiqiu from '../../../assets/data/lyrics/gaobaiqiqiu.lrc?raw' import gaobaiqiqiu from '../../../assets/data/lyrics/gaobaiqiqiu.lrc?raw'
import { userCollect } from '@/api/user' import { userCollect } from '@/api/user'
export default { export default {
name: 'SlideItemMusic', name: 'SlideItemMusic',
components: {}, components: {},
props: { props: {
modelValue: { modelValue: {
type: Object, type: Object,
default: function () { default: function () {
return {} return {}
},
},
isLoop: {
type: Boolean,
default: false,
},
},
data() {
return {
slideIndex: 1,
lyricsTexts: [],
lyricsFullTexts: [],
isPlay: false,
isAutoPlay: true,
isMove: false,
isCollect: false,
isFullLyrics: false,
lastPageX: 0,
pageX: 0,
audio: new Audio(),
duration: 0,
currentTime: 0,
step: 0,
startX: 0,
slideBarWidth: 0,
} }
}, },
computed: {}, isLoop: {
created() {}, type: Boolean,
mounted() { default: false
this.audio.src = this.modelValue.mp3 }
if (process.env.NODE_ENV === 'development') { },
this.audio.volume = 0.2 data() {
return {
slideIndex: 1,
lyricsTexts: [],
lyricsFullTexts: [],
isPlay: false,
isAutoPlay: true,
isMove: false,
isCollect: false,
isFullLyrics: false,
lastPageX: 0,
pageX: 0,
audio: new Audio(),
duration: 0,
currentTime: 0,
step: 0,
startX: 0,
slideBarWidth: 0
}
},
computed: {},
created() {},
mounted() {
this.audio.src = this.modelValue.mp3
if (process.env.NODE_ENV === 'development') {
this.audio.volume = 0.2
}
this.audio.addEventListener('loadedmetadata', (e) => {
this.duration = this.audio.duration
this.slideBarWidth = this.$refs.slideBar.clientWidth
this.step = this.slideBarWidth / Math.floor(this.duration)
})
let lrcObj = this.createLrcObj(gaobaiqiqiu)
this.lyricsTexts.push(lrcObj.ms[0])
this.lyricsTexts.push(lrcObj.ms[1])
lrcObj.ms.map((v) => {
if (v.c) this.lyricsFullTexts.push(v)
})
// console.log(lrcObj.ms)
this.audio.addEventListener('timeupdate', (e) => {
let currentTime = Math.ceil(e.target.currentTime)
// let lastLyricsText = this.lyricsTexts[this.lyricsTexts.length - 1]
// if (Number(lastLyricsText.t) < currentTime) {
// for (let i = 0; i < lrcObj.ms.length; i++) {
// let item = lrcObj.ms[i]
// if (Number(item.t) > currentTime) {
// if (item.c) {
// console.log(item)
// this.t(item)
// break
// }
// }
// }
// }
if (!this.isMove) {
this.currentTime = currentTime
if (Math.ceil(e.target.currentTime) * this.step > this.slideBarWidth - 5) {
this.pageX = this.slideBarWidth - 5
} else {
this.pageX = Math.ceil(e.target.currentTime) * this.step
}
} }
this.audio.addEventListener('loadedmetadata', (e) => { })
this.duration = this.audio.duration this.audio.addEventListener('play', (e) => (this.isPlay = true))
this.slideBarWidth = this.$refs.slideBar.clientWidth this.audio.addEventListener('ended', (e) => {
this.step = this.slideBarWidth / Math.floor(this.duration) if (this.isLoop) {
}) this.lastPageX = 0
this.audio.currentTime = 0
let lrcObj = this.createLrcObj(gaobaiqiqiu) this.audio.play()
this.lyricsTexts.push(lrcObj.ms[0]) } else {
this.lyricsTexts.push(lrcObj.ms[1]) this.isPlay = false
lrcObj.ms.map((v) => { }
if (v.c) this.lyricsFullTexts.push(v) })
}) },
methods: {
// console.log(lrcObj.ms) slide(state) {
this.audio.addEventListener('timeupdate', (e) => { this.togglePlay(false)
let currentTime = Math.ceil(e.target.currentTime) this.$emit(state)
// let lastLyricsText = this.lyricsTexts[this.lyricsTexts.length - 1]
// if (Number(lastLyricsText.t) < currentTime) {
// for (let i = 0; i < lrcObj.ms.length; i++) {
// let item = lrcObj.ms[i]
// if (Number(item.t) > currentTime) {
// if (item.c) {
// console.log(item)
// this.t(item)
// break
// }
// }
// }
// }
if (!this.isMove) {
this.currentTime = currentTime
if (
Math.ceil(e.target.currentTime) * this.step >
this.slideBarWidth - 5
) {
this.pageX = this.slideBarWidth - 5
} else {
this.pageX = Math.ceil(e.target.currentTime) * this.step
}
}
})
this.audio.addEventListener('play', (e) => (this.isPlay = true))
this.audio.addEventListener('ended', (e) => {
if (this.isLoop) {
this.lastPageX = 0
this.audio.currentTime = 0
this.audio.play()
} else {
this.isPlay = false
}
})
}, },
methods: { //TODO DOMException: The play() request was interrupted by a call to pause()
slide(state) { //TODO page2会报错能放歌但是进度条不动
this.togglePlay(false) async togglePlay(state, reStart = false) {
this.$emit(state) this.isPlay = state !== undefined ? state : !this.isPlay
}, if (reStart) {
//TODO DOMException: The play() request was interrupted by a call to pause() this.audio.currentTime = 0
//TODO page2会报错能放歌但是进度条不动 }
async togglePlay(state, reStart = false) { if (this.isPlay) {
this.isPlay = state !== undefined ? state : !this.isPlay await this.audio.play()
if (reStart) { } else {
this.audio.currentTime = 0 this.audio.pause()
} }
if (this.isPlay) { },
await this.audio.play() async getCollectMusic() {
} else { this.loading = true
this.audio.pause() let res = await userCollect()
} this.loading = false
}, if (res.code === this.SUCCESS) {
async getCollectMusic() { this.collectMusic = res.data.music.list.slice(0, 2)
this.loading = true this.guessMusic = this.recommendMusic = res.data.music.list.slice(2, -1)
let res = await userCollect() }
this.loading = false },
if (res.code === this.SUCCESS) { createLrcObj(lrc) {
this.collectMusic = res.data.music.list.slice(0, 2) let oLRC = {
this.guessMusic = this.recommendMusic = res.data.music.list.slice( ti: '', //歌曲名
2, ar: '', //演唱者
-1, al: '', //专辑名
) by: '', //歌词制作人
} offset: 0, //时间补偿值,单位毫秒,用于调整歌词整体位置
}, ms: [] //歌词数组{t:时间,c:歌词}
createLrcObj(lrc) { }
let oLRC = { if (lrc.length === 0) return
ti: '', //歌曲名 let lrcs = lrc.split('\n') //用回车拆分成数组
ar: '', //演唱者 for (let i in lrcs) {
al: '', //专辑名 //遍历歌词数组
by: '', //歌词制作人 lrcs[i] = lrcs[i].replace(/(^\s*)|(\s*$)/g, '') //去除前后空格
offset: 0, //时间补偿值,单位毫秒,用于调整歌词整体位置 let t = lrcs[i].substring(lrcs[i].indexOf('[') + 1, lrcs[i].indexOf(']')) //取[]间的内容
ms: [], //歌词数组{t:时间,c:歌词} let s = t.split(':') //分离:前后文字
} if (isNaN(parseInt(s[0]))) {
if (lrc.length === 0) return //不是数值
let lrcs = lrc.split('\n') //用回车拆分成数组 for (let i in oLRC) {
for (let i in lrcs) { if (i != 'ms' && i == s[0].toLowerCase()) {
//遍历歌词数组 oLRC[i] = s[1]
lrcs[i] = lrcs[i].replace(/(^\s*)|(\s*$)/g, '') //去除前后空格
let t = lrcs[i].substring(
lrcs[i].indexOf('[') + 1,
lrcs[i].indexOf(']'),
) //取[]间的内容
let s = t.split(':') //分离:前后文字
if (isNaN(parseInt(s[0]))) {
//不是数值
for (let i in oLRC) {
if (i != 'ms' && i == s[0].toLowerCase()) {
oLRC[i] = s[1]
}
}
} else {
//是数值
let arr = lrcs[i].match(/\[(\d+:.+?)\]/g) //提取时间字段,可能有多个
let start = 0
for (let k in arr) {
start += arr[k].length //计算歌词位置
}
let content = lrcs[i].substring(start) //获取歌词内容
for (let k in arr) {
let t = arr[k].substring(1, arr[k].length - 1) //取[]间的内容
let s = t.split(':') //分离:前后文字
oLRC.ms.push({
//对象{t:时间,c:歌词}加入ms数组
t: (parseFloat(s[0]) * 60 + parseFloat(s[1])).toFixed(3),
c: content,
})
} }
} }
} else {
//是数值
let arr = lrcs[i].match(/\[(\d+:.+?)\]/g) //提取时间字段,可能有多个
let start = 0
for (let k in arr) {
start += arr[k].length //计算歌词位置
}
let content = lrcs[i].substring(start) //获取歌词内容
for (let k in arr) {
let t = arr[k].substring(1, arr[k].length - 1) //取[]间的内容
let s = t.split(':') //分离:前后文字
oLRC.ms.push({
//对象{t:时间,c:歌词}加入ms数组
t: (parseFloat(s[0]) * 60 + parseFloat(s[1])).toFixed(3),
c: content
})
}
} }
oLRC.ms.sort(function (a, b) { }
//按时间顺序排序 oLRC.ms.sort(function (a, b) {
return a.t - b.t //按时间顺序排序
}) return a.t - b.t
return oLRC })
/* return oLRC
/*
for(let i in oLRC){ //查看解析结果 for(let i in oLRC){ //查看解析结果
console.log(i,":",oLRC[i]); console.log(i,":",oLRC[i]);
}*/ }*/
},
t(txt) {
// if (this.test.length === 2) return
this.lyricsTexts.push(txt)
nextTick(() => {
let comments = this.$refs['lyrics-wrapper']
comments.scrollTo({
top: comments.scrollHeight - comments.clientHeight,
behavior: 'smooth',
})
})
},
start(e) {
this.startX = e.touches[0].pageX
},
move(e) {
this.isMove = true
this.pageX = this.lastPageX + (e.touches[0].pageX - this.startX)
if (this.pageX < 0) this.pageX = 0
if (this.pageX > this.slideBarWidth) this.pageX = this.slideBarWidth - 5
this.currentTime = Math.ceil(this.pageX / this.step)
globalMethods.$stopPropagation(e)
},
end(e) {
this.lastPageX = this.pageX
this.currentTime = Math.ceil(this.pageX / this.step)
this.audio.currentTime = this.currentTime
this.audio.play()
this.isMove = false
globalMethods.$stopPropagation(e)
},
$durationTime(time) {
if (time === 0) return '00:00'
else {
return this.$duration(time)
}
},
durationStyle(type) {
// return {}
if (type === 1) {
return { width: this.pageX + 'px' }
}
return { left: this.pageX + 'px' }
},
}, },
t(txt) {
// if (this.test.length === 2) return
this.lyricsTexts.push(txt)
nextTick(() => {
let comments = this.$refs['lyrics-wrapper']
comments.scrollTo({
top: comments.scrollHeight - comments.clientHeight,
behavior: 'smooth'
})
})
},
start(e) {
this.startX = e.touches[0].pageX
},
move(e) {
this.isMove = true
this.pageX = this.lastPageX + (e.touches[0].pageX - this.startX)
if (this.pageX < 0) this.pageX = 0
if (this.pageX > this.slideBarWidth) this.pageX = this.slideBarWidth - 5
this.currentTime = Math.ceil(this.pageX / this.step)
globalMethods.$stopPropagation(e)
},
end(e) {
this.lastPageX = this.pageX
this.currentTime = Math.ceil(this.pageX / this.step)
this.audio.currentTime = this.currentTime
this.audio.play()
this.isMove = false
globalMethods.$stopPropagation(e)
},
$durationTime(time) {
if (time === 0) return '00:00'
else {
return this.$duration(time)
}
},
durationStyle(type) {
// return {}
if (type === 1) {
return { width: this.pageX + 'px' }
}
return { left: this.pageX + 'px' }
}
} }
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '@/assets/less/index.less'; @import '@/assets/less/index.less';
.SlideItemMusic { .SlideItemMusic {
color: white; color: white;
font-size: 14rem; font-size: 14rem;
min-width: 100vw; min-width: 100vw;
min-height: 100%; min-height: 100%;
display: flex;
flex-direction: column;
align-items: center;
position: relative;
background: linear-gradient(to bottom right, rgba(136, 132, 133, 1), rgba(136, 132, 133, 0.7));
.cover {
margin-top: 80rem;
width: 80vw;
height: 80vw;
img {
border-radius: 25rem;
object-fit: cover;
width: 100%;
height: 100%;
box-shadow: 0 0 15rem 5rem #514f4f;
}
}
.lyrics-wrapper {
margin-top: 30rem;
overflow: auto;
height: 80rem;
.container {
min-height: 80rem;
display: flex;
flex-direction: column;
justify-content: flex-end;
}
.lyrics {
height: 40rem;
display: flex;
align-items: center;
justify-content: center;
}
}
.lyrics-mask {
top: calc(80vw + 70rem);
height: 80rem;
width: 100vw;
position: absolute;
}
.lyrics-full {
margin-top: 80rem;
width: 100vw;
height: 60vh;
display: flex; display: flex;
flex-direction: column; //align-items: center;
align-items: center; justify-content: center;
position: relative; overflow: hidden;
background: linear-gradient(
to bottom right,
rgba(136, 132, 133, 1),
rgba(136, 132, 133, 0.7)
);
.cover { .list {
margin-top: 80rem; .item {
width: 80vw; display: flex;
height: 80vw; justify-content: center;
height: 40rem;
}
}
}
.bottom {
position: absolute;
bottom: 0;
width: 100vw;
.desc {
width: 100vw;
padding: var(--page-padding);
box-sizing: border-box;
display: flex;
justify-content: space-between;
align-items: flex-end;
img { img {
border-radius: 25rem; width: 35rem;
object-fit: cover;
width: 100%;
height: 100%;
box-shadow: 0 0 15rem 5rem #514f4f;
}
}
.lyrics-wrapper {
margin-top: 30rem;
overflow: auto;
height: 80rem;
.container {
min-height: 80rem;
display: flex;
flex-direction: column;
justify-content: flex-end;
} }
.lyrics { .left {
height: 40rem; .name {
display: flex; font-size: 18rem;
align-items: center; margin-bottom: 4rem;
justify-content: center;
}
}
.lyrics-mask {
top: calc(80vw + 70rem);
height: 80rem;
width: 100vw;
position: absolute;
}
.lyrics-full {
margin-top: 80rem;
width: 100vw;
height: 60vh;
display: flex;
//align-items: center;
justify-content: center;
overflow: hidden;
.list {
.item {
display: flex;
justify-content: center;
height: 40rem;
}
}
}
.bottom {
position: absolute;
bottom: 0;
width: 100vw;
.desc {
width: 100vw;
padding: var(--page-padding);
box-sizing: border-box;
display: flex;
justify-content: space-between;
align-items: flex-end;
img {
width: 35rem;
} }
.left { .author {
.name { font-size: 14rem;
font-size: 18rem;
margin-bottom: 4rem;
}
.author {
font-size: 14rem;
}
}
.right {
.btn {
display: flex;
align-items: center;
flex-direction: column;
margin-top: 20rem;
font-size: 12rem;
}
} }
} }
.progress { .right {
width: 100vw; .btn {
font-size: 12rem;
padding: 0 var(--page-padding);
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: space-between;
color: gainsboro;
.bar {
margin: 0 6rem;
flex: 1;
position: relative;
.slide-bar {
position: absolute;
height: 20rem;
width: 100%;
top: -10rem;
z-index: 9;
}
&:before {
z-index: 8;
content: ' ';
height: 1.5px;
width: 100%;
background: gray;
position: absolute;
top: 0;
}
.bar-line {
z-index: 9;
content: '';
position: absolute;
top: 0;
height: 1.5px;
width: 50vw;
background: white;
}
.bar-point {
z-index: 9;
position: absolute;
left: 50vw;
top: -3px;
height: 8rem;
width: 8rem;
border-radius: 50%;
background: white;
}
}
}
.options {
width: 100vw;
padding: var(--page-padding);
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: space-between;
img {
width: 38rem;
height: 38rem;
}
.center {
display: flex; display: flex;
align-items: center; align-items: center;
flex-direction: column;
margin-top: 20rem;
font-size: 12rem;
}
}
}
img { .progress {
margin: 0 10rem; width: 100vw;
} font-size: 12rem;
padding: 0 var(--page-padding);
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: space-between;
color: gainsboro;
.control { .bar {
width: 55rem; margin: 0 6rem;
height: 55rem; flex: 1;
} position: relative;
.slide-bar {
position: absolute;
height: 20rem;
width: 100%;
top: -10rem;
z-index: 9;
}
&:before {
z-index: 8;
content: ' ';
height: 1.5px;
width: 100%;
background: gray;
position: absolute;
top: 0;
}
.bar-line {
z-index: 9;
content: '';
position: absolute;
top: 0;
height: 1.5px;
width: 50vw;
background: white;
}
.bar-point {
z-index: 9;
position: absolute;
left: 50vw;
top: -3px;
height: 8rem;
width: 8rem;
border-radius: 50%;
background: white;
}
}
}
.options {
width: 100vw;
padding: var(--page-padding);
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: space-between;
img {
width: 38rem;
height: 38rem;
}
.center {
display: flex;
align-items: center;
img {
margin: 0 10rem;
}
.control {
width: 55rem;
height: 55rem;
} }
} }
} }
} }
}
</style> </style>

View File

@@ -16,16 +16,10 @@
v-model:active-index="currentSlideItemIndex" v-model:active-index="currentSlideItemIndex"
> >
</Indicator> </Indicator>
<SlideHorizontal <SlideHorizontal v-model:index="currentSlideItemIndex" class="SlideRowList">
v-model:index="currentSlideItemIndex"
class="SlideRowList"
>
<SlideItem class="tab1" style="overflow: auto"> <SlideItem class="tab1" style="overflow: auto">
<Scroll class="Scroll" @pulldown="getHistoryVideo"> <Scroll class="Scroll" @pulldown="getHistoryVideo">
<Posters <Posters :list="historyVideo.list" v-if="historyVideo.total"></Posters>
:list="historyVideo.list"
v-if="historyVideo.total"
></Posters>
<Loading :is-full-screen="false" v-if="loadingVideo" /> <Loading :is-full-screen="false" v-if="loadingVideo" />
<template v-else> <template v-else>
<NoMore v-if="historyVideo.list.length" /> <NoMore v-if="historyVideo.list.length" />
@@ -47,148 +41,142 @@
</div> </div>
</template> </template>
<script> <script>
import Posters from '../../../components/Posters' import Posters from '../../../components/Posters'
import Scroll from '../../../components/Scroll' import Scroll from '../../../components/Scroll'
import NoMore from '../../../components/NoMore' import NoMore from '../../../components/NoMore'
import { historyOther, historyVideo } from '@/api/videos' import { historyOther, historyVideo } from '@/api/videos'
export default { export default {
name: 'lookHistory', name: 'lookHistory',
components: { components: {
NoMore, NoMore,
Posters, Posters,
Scroll, Scroll
}, },
data() { data() {
return { return {
loadingVideo: false, loadingVideo: false,
loadingOther: false, loadingOther: false,
isClearHistoryVideo: false, isClearHistoryVideo: false,
isClearHistoryOther: false, isClearHistoryOther: false,
currentSlideItemIndex: 0, currentSlideItemIndex: 0,
pageSize: 15, pageSize: 15,
historyVideo: { historyVideo: {
total: 0, total: 0,
pageNo: 0, pageNo: 0,
list: [], list: []
}, },
historyOther: { historyOther: {
total: 0, total: 0,
pageNo: 0, pageNo: 0,
list: [], list: []
}, }
}
},
computed: {
isClear() {
if (this.currentSlideItemIndex === 0) {
return this.historyVideo.list.length
}
return this.historyOther.list.length
}
},
created() {
this.getHistoryVideo(true)
this.getHistoryOther(true)
},
methods: {
async getHistoryVideo(init = false) {
if (this.loadingVideo) return
if (this.isClearHistoryVideo) return
if (!init) {
if (this.historyVideo.total <= this.historyVideo.list.length) return
this.historyVideo.pageNo++
}
this.loadingVideo = true
let res = await historyVideo({
pageNo: this.historyVideo.pageNo,
pageSize: this.pageSize
})
console.log(res)
this.loadingVideo = false
if (res.code === this.SUCCESS) {
this.historyVideo.list = this.historyVideo.list.concat(res.data.list)
this.historyVideo.total = res.data.total
} }
}, },
computed: { async getHistoryOther(init = false) {
isClear() { if (this.loadingOther) return
if (this.isClearHistoryOther) return
this.loadingOther = true
if (!init) {
this.historyOther.pageNo++
}
let res = await historyOther({
pageNo: this.historyOther.pageNo,
pageSize: this.pageSize
})
this.loadingOther = false
if (res.code === this.SUCCESS) {
this.historyOther.list = this.historyOther.list.concat(res.data.list)
this.historyOther.total = res.data.total
}
},
clear() {
this.$showConfirmDialog('确定清空?', '清空后,以往观看记录不再展示', 'gray', () => {
if (this.currentSlideItemIndex === 0) { if (this.currentSlideItemIndex === 0) {
return this.historyVideo.list.length this.historyVideo.list = []
this.isClearHistoryVideo = true
return
} }
return this.historyOther.list.length this.historyOther.list = []
}, this.isClearHistoryVideo = true
}, })
created() { }
this.getHistoryVideo(true)
this.getHistoryOther(true)
},
methods: {
async getHistoryVideo(init = false) {
if (this.loadingVideo) return
if (this.isClearHistoryVideo) return
if (!init) {
if (this.historyVideo.total <= this.historyVideo.list.length) return
this.historyVideo.pageNo++
}
this.loadingVideo = true
let res = await historyVideo({
pageNo: this.historyVideo.pageNo,
pageSize: this.pageSize,
})
console.log(res)
this.loadingVideo = false
if (res.code === this.SUCCESS) {
this.historyVideo.list = this.historyVideo.list.concat(res.data.list)
this.historyVideo.total = res.data.total
}
},
async getHistoryOther(init = false) {
if (this.loadingOther) return
if (this.isClearHistoryOther) return
this.loadingOther = true
if (!init) {
this.historyOther.pageNo++
}
let res = await historyOther({
pageNo: this.historyOther.pageNo,
pageSize: this.pageSize,
})
this.loadingOther = false
if (res.code === this.SUCCESS) {
this.historyOther.list = this.historyOther.list.concat(res.data.list)
this.historyOther.total = res.data.total
}
},
clear() {
this.$showConfirmDialog(
'确定清空?',
'清空后,以往观看记录不再展示',
'gray',
() => {
if (this.currentSlideItemIndex === 0) {
this.historyVideo.list = []
this.isClearHistoryVideo = true
return
}
this.historyOther.list = []
this.isClearHistoryVideo = true
},
)
},
},
} }
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '../../../assets/less/index'; @import '../../../assets/less/index';
.lookHistory { .lookHistory {
position: fixed; position: fixed;
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
top: 0; top: 0;
overflow: auto; overflow: auto;
color: white; color: white;
font-size: 14rem; font-size: 14rem;
.content { .content {
padding-top: 60rem; padding-top: 60rem;
.SlideRowList, .SlideRowList,
.Scroll { .Scroll {
height: calc( height: calc(
var(--vh, 1vh) * 100 - var(--indicator-height) - var(--vh, 1vh) * 100 - var(--indicator-height) - var(--common-header-height)
var(--common-header-height) ) !important;
) !important; }
.empty {
height: 70vh;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
img {
height: 120rem;
} }
.empty { .title {
height: 70vh; font-size: 13rem;
display: flex; margin-top: 10rem;
align-items: center; color: var(--second-text-color);
justify-content: center;
flex-direction: column;
img {
height: 120rem;
}
.title {
font-size: 13rem;
margin-top: 10rem;
color: var(--second-text-color);
}
} }
} }
} }
}
</style> </style>

View File

@@ -3,41 +3,25 @@
<BaseHeader /> <BaseHeader />
<div class="content type1" v-if="type === 0"> <div class="content type1" v-if="type === 0">
<div class="notice"> <div class="notice">
<img <img src="../../../../assets/img/icon/newicon/left_menu/lock.png" alt="" />
src="../../../../assets/img/icon/newicon/left_menu/lock.png"
alt=""
/>
<span>时间锁已关闭</span> <span>时间锁已关闭</span>
</div> </div>
<div class="row mt1r no-active"> <div class="row mt1r no-active">
<div class="left"> <div class="left">
<img <img src="../../../../assets/img/icon/newicon/left_menu/hourglass.png" alt="" />
src="../../../../assets/img/icon/newicon/left_menu/hourglass.png"
alt=""
/>
<span>可为时间锁设置一个触发时间</span> <span>可为时间锁设置一个触发时间</span>
</div> </div>
</div> </div>
<div class="row mt1r no-active"> <div class="row mt1r no-active">
<div class="left"> <div class="left">
<img <img src="../../../../assets/img/icon/newicon/left_menu/clock.png" alt="" />
src="../../../../assets/img/icon/newicon/left_menu/clock.png" <span>开启时间锁后单日使用时长超过触发时间需输入密码才能继续使用</span>
alt=""
/>
<span
>开启时间锁后单日使用时长超过触发时间需输入密码才能继续使用</span
>
</div> </div>
</div> </div>
<div class="row mt1r mb1r no-active"> <div class="row mt1r mb1r no-active">
<div class="left"> <div class="left">
<img <img src="../../../../assets/img/icon/newicon/left_menu/lock.png" alt="" />
src="../../../../assets/img/icon/newicon/left_menu/lock.png" <span>开启时间锁需先设置独立密码忘记密码后可通过申诉重置密码</span>
alt=""
/>
<span
>开启时间锁需先设置独立密码忘记密码后可通过申诉重置密码</span
>
</div> </div>
</div> </div>
<div class="row mt1r mb1r" @click="$nav('trigger-time', { triggerTime })"> <div class="row mt1r mb1r" @click="$nav('trigger-time', { triggerTime })">
@@ -72,11 +56,7 @@
</div> </div>
</div> </div>
<div class="content type2" v-if="type === 2"> <div class="content type2" v-if="type === 2">
<img <img class="desc" src="../../../../assets/img/icon/newicon/left_menu/img-type3.png" alt="" />
class="desc"
src="../../../../assets/img/icon/newicon/left_menu/img-type3.png"
alt=""
/>
<div class="footer"> <div class="footer">
<div class="notice"> <div class="notice">
<!-- TODO 有个勾选没做--> <!-- TODO 有个勾选没做-->
@@ -94,78 +74,78 @@
</div> </div>
</template> </template>
<script> <script>
import enums from '../../../../utils/enums' import enums from '../../../../utils/enums'
export default { export default {
name: 'DetailSetting', name: 'DetailSetting',
data() { data() {
return { return {
type: 0, type: 0,
enums, enums,
triggerTime: enums.TRIGGER_TIME.TIME60, triggerTime: enums.TRIGGER_TIME.TIME60
} }
}, },
computed: {}, computed: {},
created() { created() {
this.type = ~~this.$route.query.type this.type = ~~this.$route.query.type
let triggerTime = localStorage.getItem('changeTriggerTime') let triggerTime = localStorage.getItem('changeTriggerTime')
if (triggerTime !== null) this.triggerTime = triggerTime if (triggerTime !== null) this.triggerTime = triggerTime
}, },
methods: {}, methods: {}
} }
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '../../../../assets/less/index'; @import '../../../../assets/less/index';
.DetailSetting { .DetailSetting {
position: fixed;
left: 0;
right: 0;
bottom: 0;
top: 0;
overflow: auto;
color: white;
font-size: 14rem;
.content {
padding-top: var(--common-header-height);
}
.footer {
position: fixed; position: fixed;
left: 0; bottom: 15rem;
right: 0; left: 10rem;
bottom: 0; right: 10rem;
top: 0;
overflow: auto;
color: white;
font-size: 14rem;
.content { .notice {
padding-top: var(--common-header-height); font-size: 13rem;
margin-bottom: 15rem;
} }
}
.footer { .type1 {
position: fixed; .notice {
bottom: 15rem; margin: 60rem 0;
left: 10rem; display: flex;
right: 10rem; justify-content: center;
align-items: center;
flex-direction: column;
font-size: 16rem;
color: var(--second-text-color);
.notice { img {
font-size: 13rem; width: 15rem;
margin-bottom: 15rem; margin-bottom: 15rem;
} }
} }
}
.type1 { .type2 {
.notice { .desc {
margin: 60rem 0; margin-top: 40rem;
display: flex; width: 100%;
justify-content: center;
align-items: center;
flex-direction: column;
font-size: 16rem;
color: var(--second-text-color);
img {
width: 15rem;
margin-bottom: 15rem;
}
}
}
.type2 {
.desc {
margin-top: 40rem;
width: 100%;
}
} }
} }
}
</style> </style>

View File

@@ -31,32 +31,32 @@
</div> </div>
</template> </template>
<script> <script>
export default { export default {
name: 'index', name: 'index',
data() { data() {
return {} return {}
}, },
computed: {}, computed: {},
created() {}, created() {},
methods: {}, methods: {}
} }
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '../../../../assets/less/index'; @import '../../../../assets/less/index';
.index { .index {
position: fixed; position: fixed;
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
top: 0; top: 0;
overflow: auto; overflow: auto;
color: white; color: white;
font-size: 14rem; font-size: 14rem;
.content { .content {
padding-top: 60rem; padding-top: 60rem;
}
} }
}
</style> </style>

View File

@@ -34,41 +34,41 @@
</div> </div>
</template> </template>
<script> <script>
import enums from '../../../../utils/enums' import enums from '../../../../utils/enums'
export default { export default {
name: 'TriggerTime', name: 'TriggerTime',
data() { data() {
return { return {
enums, enums,
triggerTime: enums.TRIGGER_TIME.TIME60, triggerTime: enums.TRIGGER_TIME.TIME60
} }
}, },
created() { created() {
this.triggerTime = ~~this.$route.query.triggerTime this.triggerTime = ~~this.$route.query.triggerTime
}, },
methods: { methods: {
setTriggerTime(type) { setTriggerTime(type) {
this.triggerTime = type this.triggerTime = type
localStorage.setItem('changeTriggerTime', type) localStorage.setItem('changeTriggerTime', type)
}, }
},
} }
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
@import '../../../../assets/less/index'; @import '../../../../assets/less/index';
.TriggerTime { .TriggerTime {
position: fixed; position: fixed;
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
top: 0; top: 0;
color: white; color: white;
.content { .content {
padding-top: 60rem; padding-top: 60rem;
}
} }
}
</style> </style>

Some files were not shown because too many files have changed in this diff Show More