Toggle navigation
Toggle navigation
This project
Loading...
Sign in
Hooke
/
tswj
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Snippets
Network
Create a new issue
Builds
Commits
Issue Boards
Authored by
hookehuyr
2022-05-05 19:06:57 +0800
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
a99dfd57cc1844d441a461d59c5fc916aa3390e2
a99dfd57
1 parent
4e251a20
✨ feat(幼儿园选择页,幼儿园书籍列表,书籍详情页): API数据联调
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
253 additions
and
136 deletions
src/components/BookCard/index.vue
src/components/VideoCard/index.vue
src/composables/useVideoList.js
src/utils/axios.js
src/views/client/bookDetail.vue
src/views/client/chooseBook.vue
src/views/client/chooseSchool.vue
tsconfig.json
vite.config.js
src/components/BookCard/index.vue
View file @
a99dfd5
...
...
@@ -2,15 +2,13 @@
<div class="book-item van-hairline--bottom" @click="handle">
<van-row>
<van-col span="8">
<van-image width="7rem" height="7rem" :src="item.
avata
r" style="text-align: center;" />
<van-image width="7rem" height="7rem" :src="item.
cove
r" style="text-align: center;" />
</van-col>
<van-col class="wrapper" span="16">
<p class="title van-multi-ellipsis--l2">逃家小兔绘本</p>
<div v-if="type === 'C'" class="van-multi-ellipsis--l2 content">
从前有一只小兔子,总是想要离家出走。有一天,他对妈妈说如果有大灰狼怎么办,不要把门打开
</div>
<p class="title van-multi-ellipsis--l2">{{ item.name }}</p>
<div v-if="type === 'C'" class="van-multi-ellipsis--l2 content">{{ item.note }}</div>
<div class="sub">
<van-icon :name="icon_video" /> <span>
54
个作品</span>
<van-icon :name="icon_video" /> <span>
{{ item.prod_num }}
个作品</span>
</div>
<div v-if="type === 'B'" class="upload" @click="onUpload(item)">上传视频</div>
</van-col>
...
...
src/components/VideoCard/index.vue
View file @
a99dfd5
<template>
<div class="video-wrapper">
<div class="video-div" :id="'mui-player-' + item.
case_
id"></div>
<div class="video-div" :id="'mui-player-' + item.id"></div>
<div class="video-bar">
<van-row>
<van-col span="12" @click="goTo">
<van-image round width="2rem" height="2rem" style="vertical-align: bottom;"
src="https://cdn.jsdelivr.net/npm/@vant/assets/cat.jpeg" />
<span style="font-size: 1.05rem;">王忆慈</span>
<van-image round width="2rem" height="2rem" style="vertical-align: middle;" :src="item.avatar" />
<span style="font-size: 1.05rem;vertical-align: middle;">{{ item.name }}</span>
</van-col>
<van-col span="12">
<div style="padding: 0.25rem; padding-top: 0.75rem; text-align: right;">
<span @click="setComment">
<van-icon :name="icon_liuyan" size="1.2rem" style="vertical-align: bottom;" />
67
{{ item.comment_num }}
</span>
<span @click="setLike()">
<van-icon v-if="!detail.
liked
" :name="icon_dianzan1" size="1.2rem" style="vertical-align: bottom;" />
<van-icon v-if="!detail.
is_like
" :name="icon_dianzan1" size="1.2rem" style="vertical-align: bottom;" />
<van-icon v-else :name="icon_dianzan2" size="1.2rem" style="vertical-align: bottom;" />
10086
{{ item.favor_num }}
</span>
</div>
</van-col>
</van-row>
</div>
<div @click="goTo" style="color: #999999; padding: 0px 1rem 0.5rem;">杨浦民办科技幼稚园 | 藏语</div>
<div @click="goTo" style="color: #999999; padding: 0px 1rem 0.5rem;">{{ item.kg_name }} | {{ item.localism_type }}
</div>
</div>
</template>
...
...
@@ -65,26 +65,26 @@ export default {
},
mounted() {
var mp = new MuiPlayer({
container: '#mui-player-' + this.item.
case_
id,
container: '#mui-player-' + this.item.id,
title: this.item.title,
src: this.item.video
.url
,
poster: this.item.cover
.url
,
src: this.item.video,
poster: this.item.cover,
autoFit: false,
videoAttribute: [ // 声明启用同层播放, 不让会自动全屏播放
{
attrKey:'webkit-playsinline',attrValue:'webkit-playsinline'
},
{
attrKey:'playsinline',attrValue:'playsinline'
},
{
attrKey:'x5-video-player-type',attrValue:'h5-page'
},
{
attrKey: 'webkit-playsinline', attrValue: 'webkit-playsinline'
},
{
attrKey: 'playsinline', attrValue: 'playsinline'
},
{
attrKey: 'x5-video-player-type', attrValue: 'h5-page'
},
]
})
this.detail = _.cloneDeep(this.item)
},
methods: {
setLike() {
this.detail.
liked = !this.detail.liked
this.detail.
is_like = !this.detail.is_like
},
setComment() {
console.warn('跳转详情页,移动到留言页');
console.warn(this.detail.
case_
id);
console.warn(this.detail.id);
}
}
}
...
...
@@ -96,14 +96,19 @@ export default {
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
box-shadow: 0px 4px 8px 0px rgba(0, 0, 0, 0.13);
.video-div {
border-top-left-radius: 5px;
border-top-right-radius: 5px;
}
.video-bar {
color: #713610;
padding: 1rem;
padding-bottom: 0.5rem;
.avatar {
}
}
}
</style>
\ No newline at end of file
...
...
src/composables/useVideoList.js
0 → 100644
View file @
a99dfd5
import
{
ref
}
from
'vue'
import
axios
from
'@/utils/axios'
;
import
_
from
'lodash'
import
{
Toast
}
from
'vant'
;
export
const
useVideoList
=
(
$route
)
=>
{
// 切换视频语言
const
checkMandarin
=
ref
(
true
);
// 普通话选项卡
const
checkLocalism
=
ref
(
false
);
// 方言选项卡
const
chooseLanguage
=
ref
({
text
:
'普通话'
,
val
:
'普通话'
});
// 默认选中普通话
const
toggleLanguage
=
()
=>
{
checkMandarin
.
value
=
!
checkMandarin
.
value
;
checkLocalism
.
value
=
!
checkLocalism
.
value
;
// 修改默认语言绑定数据
if
(
checkLocalism
.
value
)
{
// tslint:disable-next-line:no-string-literal
chooseLanguage
.
value
=
{
text
:
columns
[
0
][
'text'
],
val
:
columns
[
0
][
'val'
]
}
}
else
{
chooseLanguage
.
value
=
{
text
:
'普通话'
,
val
:
'普通话'
};
}
// 切换语言需要更新列表数据
offset
.
value
=
0
prod_list
.
value
=
[]
loading
.
value
=
true
;
finished
.
value
=
false
;
onLoad
()
}
// 方言选择项
const
columns
=
[
{
text
:
'所有方言'
,
val
:
'所有方言'
},
{
text
:
'沪语'
,
val
:
'沪语'
},
{
text
:
'粤语'
,
val
:
'粤语'
},
];
const
showPicker
=
ref
(
false
);
const
onConfirm
=
({
selectedOptions
})
=>
{
showPicker
.
value
=
false
;
chooseLanguage
.
value
=
{
text
:
selectedOptions
[
0
].
text
,
val
:
selectedOptions
[
0
].
val
}
};
// 绑定页面数据
const
bookInfo
=
ref
(
''
);
// tslint:disable-next-line: variable-name
const
prod_list
=
ref
([]);
const
limit
=
ref
(
1
)
const
offset
=
ref
(
0
)
// 处理书籍下作品列表
const
loading
=
ref
(
false
);
const
finished
=
ref
(
false
);
const
onLoad
=
()
=>
{
// 异步更新数据
axios
.
get
(
'/srv/?a=book_info'
,
{
params
:
{
book_id
:
$route
.
query
.
id
,
localism_type
:
chooseLanguage
.
value
.
text
,
limit
:
limit
.
value
,
offset
:
offset
.
value
}
})
.
then
(
res
=>
{
if
(
res
.
data
.
code
===
1
)
{
bookInfo
.
value
=
res
.
data
.
data
;
prod_list
.
value
=
_
.
concat
(
prod_list
.
value
,
res
.
data
.
data
.
prod_list
);
offset
.
value
=
prod_list
.
value
.
length
;
loading
.
value
=
false
;
// 数据全部加载完成
if
(
!
res
.
data
.
data
.
prod_list
.
length
)
{
// 加载状态结束
finished
.
value
=
true
;
}
}
else
{
// tslint:disable-next-line: no-console
console
.
warn
(
res
);
Toast
({
icon
:
'close'
,
message
:
res
.
data
.
msg
});
}
})
.
catch
(
err
=>
{
// tslint:disable-next-line: no-console
console
.
error
(
err
);
})
};
return
{
toggleLanguage
,
onLoad
,
columns
,
prod_list
,
finished
,
loading
,
bookInfo
,
showPicker
,
checkLocalism
,
checkMandarin
,
onConfirm
,
chooseLanguage
}
}
src/utils/axios.js
View file @
a99dfd5
import
axios
from
'axios'
;
import
router
from
'../router'
;
import
_
from
'lodash'
// 请求拦截器
axios
.
interceptors
.
request
.
use
(
config
=>
{
// 发送请求前
if
(
config
.
method
===
'get'
)
{
// 绑定默认请求头
config
.
params
=
_
.
merge
(
config
.
params
,
{
f
:
'voice'
,
client_id
:
'313939'
,
})
}
return
config
;
},
error
=>
{
...
...
src/views/client/bookDetail.vue
View file @
a99dfd5
...
...
@@ -3,15 +3,11 @@
<div class="modify-top"></div>
<div class="book-detail">
<div style="text-align: center;">
<van-image width="220" height="220"
src="https://lanhu.oss-cn-beijing.aliyuncs.com/SketchPngc434046fdf1f9499d251b280af2568ddbe64839799d00a9aee226edbeb710aed" />
<van-image width="220" height="220" :src="bookInfo.cover" />
</div>
<div class="book-intro">
<p class="book-post">逃家小兔绘本</p>
<div id="book-intro" :class="{ 'van-multi-ellipsis--l3': isToggle }">
从前有一只小兔子,总是想要离家出走。有一天他对妈妈说:“我要跑走啦!”“如果你跑走了我就去追你,因为你是我的小宝贝呀!”妈妈说。
一场爱的捉迷藏就此展开了
</div>
<p class="book-post">{{ bookInfo.name }}</p>
<div id="book-intro" :class="{ 'van-multi-ellipsis--l3': isToggle }">{{ bookInfo.note }}</div>
<div v-if="hasToggle">
<div v-if="isToggle" @click="onToggle(false)" class="book-toggle-icon">展开
<van-icon style="vertical-align: middle;" size="0.9rem" :name="icon_down" />
...
...
@@ -32,7 +28,7 @@
<van-col span="12">
<div style="font-size: 1rem; color: #999999; text-align: right;">
<van-icon :name="icon_video" />
54
个作品
{{ bookInfo.total }}
个作品
</div>
</van-col>
</van-row>
...
...
@@ -40,12 +36,12 @@
<div class="book-video-language">
<van-row>
<van-col span="6">
<div @click="toggleLanguage" :class="[check
_m
andarin ? 'checked' : 'uncheck']">普通话</div>
<div @click="toggleLanguage" :class="[check
M
andarin ? 'checked' : 'uncheck']">普通话</div>
</van-col>
<van-col span="6">
<div @click="toggleLanguage" :class="[check
_l
ocalism ? 'checked' : 'uncheck']">方言</div>
<div @click="toggleLanguage" :class="[check
L
ocalism ? 'checked' : 'uncheck']">方言</div>
</van-col>
<van-col span="12" v-if="check
_l
ocalism" @click="showPicker = true">
<van-col span="12" v-if="check
L
ocalism" @click="showPicker = true">
<div class="choose-wrapper">
<div class="text">
{{ chooseLanguage.text }}
...
...
@@ -65,7 +61,7 @@
<div class="book-video-list">
<van-list v-model:loading="loading" :finished="finished" finished-text="没有更多了" @load="onLoad">
<template v-for="item in
dataL
ist" :key="item" style="height: 3rem;">
<template v-for="item in
prod_l
ist" :key="item" style="height: 3rem;">
<video-card :item="item"></video-card>
</template>
</van-list>
...
...
@@ -92,14 +88,18 @@
<van-overlay :show="showNotice" z-index="1000">
<div class="wrapper" @click.stop>
<div class="block">
<div style="position: absolute; top: -2rem; right: 1rem; font-size: 1.5rem;"><van-icon name="close" color="#FFFFFF" @click="closeNotice" /></div>
<div style="position: absolute; top: -2rem; right: 1rem; font-size: 1.5rem;">
<van-icon name="close" color="#FFFFFF" @click="closeNotice" />
</div>
<div>
<van-image width="100" height="100" :src="icon_notice" />
<p style="margin: 1rem; font-size: 1.15rem; font-weight: bold; color: #222222;">温馨提示</p>
</div>
<div style="color: #333333;">
<p>您还没有实名认证</p>
<p>请点击 <van-icon :name="icon_me" /> 进行实名认证</p>
<p>请点击
<van-icon :name="icon_me" /> 进行实名认证
</p>
<p>实名认证之后再上传</p>
</div>
<div style="margin: 3rem 0;">
...
...
@@ -111,7 +111,7 @@
</template>
<script setup>
import
dataList from '@/mock/video_list
'
import
{ useVideoList } from '@/composables/useVideoList.js
'
import MyButton from '@/components/MyButton/index.vue'
import VideoCard from '@/components/VideoCard/index.vue'
...
...
@@ -135,7 +135,7 @@ import { Toast } from 'vant';
const $route = useRoute();
const $router = useRouter();
const
items = reactive([])
const
{ toggleLanguage, onLoad, columns, prod_list, finished, loading, bookInfo, showPicker, checkLocalism, checkMandarin, onConfirm, chooseLanguage } = useVideoList($route);
const gotoMe = () => {
console.warn('跳转我的地址');
...
...
@@ -149,73 +149,13 @@ const onToggle = (v) => { // 展开/折叠
isToggle.value = v
}
// 切换视频语言
const check_mandarin = ref(true);
const check_localism = ref(false);
const chooseLanguage = ref({ text: '普通话', val: '00' }); // 默认选中普通话
const toggleLanguage = () => {
check_mandarin.value = !check_mandarin.value;
check_localism.value = !check_localism.value;
// 修改默认语言绑定数据
if (check_localism.value) {
chooseLanguage.value = { text: columns[0]['text'], val: columns[0]['val'] }
} else {
chooseLanguage.value = { text: '普通话', val: '00' };
}
}
// 方言选择项
const columns = [
{ text: '所有方言', val: '00' },
{ text: '沪语', val: '01' },
{ text: '粤语', val: '02' },
];
const showPicker = ref(false);
const onConfirm = ({ selectedOptions }) => {
showPicker.value = false;
chooseLanguage.value = {
text: selectedOptions[0].text,
val: selectedOptions[0].val
}
};
onMounted(() => {
// 判断是否显示简介的展开图标
nextTick(() => {
hasToggle.value = tools.hasEllipsis('book-intro');
})
for (let index = 0; index < 20; index++) {
items.push({
id: index,
avatar: 'https://cdn.jsdelivr.net/npm/@vant/assets/cat.jpeg'
})
}
})
// 处理书籍下作品列表
const list = ref([]);
const loading = ref(false);
const finished = ref(false);
const onLoad = () => {
// 异步更新数据
// setTimeout 仅做示例,真实场景中一般为 ajax 请求
setTimeout(() => {
for (let i = 0; i < 20; i++) {
list.value.push(list.value.length + 1);
}
// 加载状态结束
loading.value = false;
// 数据全部加载完成
if (list.value.length >= 100) {
finished.value = true;
}
}, 1000);
};
// 书籍订阅
let is_subscribe = ref(false);
const onSubscribe = () => {
...
...
@@ -250,20 +190,11 @@ export default {
mixins: [mixin.init],
data() {
return {
}
},
created() {
this.getList()
},
methods: {
getList() {
_.each(this.dataList, item => {
let video = item.video && item.video.url ? item.video.url : 'http://static.smartisanos.cn/common/video/t1-ui.mp4';
let cover = item.cover && item.cover.url ? item.cover.url : 'http://static.smartisanos.cn/pr/img/video/video_03_cc87ce5bdb.jpg';
item.options = { video: transCaseList(video, cover), autoplay: false, preload: 'none' }
})
}
}
}
</script>
...
...
src/views/client/chooseBook.vue
View file @
a99dfd5
...
...
@@ -2,10 +2,13 @@
<div class="choose-book-page content-bg">
<div class="modify-top"></div>
<div class="belong-school">
<van-image round width="2rem" height="2rem" lazy-load src="https://cdn.jsdelivr.net/npm/@vant/assets/cat.jpeg" style="vertical-align: text-bottom;" >
<template v-if="kg_id">
<van-image round width="2rem" height="2rem" lazy-load :src="kindergartenInfo.logo"
style="vertical-align: text-bottom;">
<template v-slot:error>加载失败</template>
</van-image>
<p class="title">杨浦民办科技幼稚园</p>
<p class="title">{{ kindergartenInfo.name }}</p>
</template>
</div>
<div style="position: relative;">
<div class="ding left"></div>
...
...
@@ -21,7 +24,7 @@
<div class="ding right"></div>
</div>
<div class="book-list">
<template v-for="(item, key) in
items
" :key="key">
<template v-for="(item, key) in
kindergartenInfo.book_list
" :key="key">
<book-card type="C" :item="item" @on-click="onClick(item)"></book-card>
</template>
</div>
...
...
@@ -34,23 +37,74 @@
import MyButton from '@/components/MyButton/index.vue'
import BookCard from '@/components/BookCard/index.vue'
import ShortcutFixed from '@/components/ShortcutFixed/index.vue'
import { ref, reactive, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import axios from '@/utils/axios';
import _ from 'lodash'
import $ from 'jquery'
import { Toast } from 'vant';
const $route = useRoute();
const $router = useRouter();
// 自定义按钮颜色样式
const styleObject = reactive({
backgroundColor: '#F4675A',
color: '#FFFFFF',
borderColor: '#F4675A'
})
const items = reactive([])
// 页面数据绑定
const kg_id = $route.query.kg_id ? $route.query.kg_id : '';
const kindergartenInfo = ref({
id: '',
logo: '',
name: '',
book_list: []
});
onMounted(() => {
if (kg_id) { // 从学校列表进入
axios.get('/srv/?a=kg_book_list', {
params: {
kg_id
}
})
.then(res => {
if (res.data.code === 1) {
kindergartenInfo.value = res.data.data;
} else {
console.warn(res);
Toast({
icon: 'close',
message: res.data.msg
});
}
})
.catch(err => {
console.error(err);
})
} else { // 从访客进入
axios.get('/srv/?a=book_list')
.then(res => {
if (res.data.code === 1) {
kindergartenInfo.value = {
book_list: res.data.data
}
} else {
console.warn(res);
Toast({
icon: 'close',
message: res.data.msg
});
}
})
.catch(err => {
console.error(err);
})
}
})
// 跳转书籍详情页
const onClick = (item) => {
// 调整书籍详情页
$router.push({
path: '/client/bookDetail',
query: {
...
...
@@ -58,17 +112,10 @@ const onClick = (item) => {
}
});
}
const gotoMe = () => {
console.warn('跳转我的地址');
}
onMounted(() => {
for (let index = 0; index < 20; index++) {
items.push({
id: index,
avatar: 'https://cdn.jsdelivr.net/npm/@vant/assets/cat.jpeg'
})
}
})
</script>
<script>
...
...
@@ -76,12 +123,12 @@ import mixin from 'common/mixin';
export default {
mixins: [mixin.init],
data
() {
data() {
return {
}
},
mounted
() {
mounted() {
},
methods: {
...
...
@@ -92,9 +139,11 @@ export default {
<style lang="less" scoped>
@import url('@css/content-bg.less');
.choose-book-page {
.choose-book-page {
.belong-school {
padding: 1.5rem;
.title {
color: #222222;
display: inline-block;
...
...
@@ -103,6 +152,7 @@ export default {
}
}
.book-list {
margin: 1rem;
margin-top: 1.25rem;
...
...
@@ -111,6 +161,7 @@ export default {
background-color: rgba(255, 255, 255, 1);
box-shadow: 0px 4px 8px 0px rgba(0, 0, 0, 0.13);
}
.ding {
z-index: 69;
position: absolute;
...
...
@@ -120,12 +171,14 @@ export default {
background-image: url('@images/ding-left@2x.png');
background-size: contain;
background-repeat: no-repeat;
&.left {
left: 8rem;
}
&.right {
right: 8rem;
}
}
}
}
</style>
\ No newline at end of file
...
...
src/views/client/chooseSchool.vue
View file @
a99dfd5
...
...
@@ -5,7 +5,7 @@
<template v-for="(item, key) in schoolList" :key="key">
<right-side-list
@on-click="onClick(item)"
:avatar="item.
avatar
">
:avatar="item.
logo
">
{{ item.name }}
</right-side-list>
</template>
...
...
@@ -15,26 +15,41 @@
<script setup>
import RightSideList from '@/components/RightSideList/index.vue'
import { reactive, onMounted } from 'vue';
import { ref, onMounted } from 'vue';
import axios from '@/utils/axios';
import $ from 'jquery'
import { useRoute, useRouter } from 'vue-router'
import { Toast } from 'vant';
const $route = useRoute();
const $router = useRouter();
const schoolList = reactive([])
const schoolList = ref([])
onMounted(() => {
for (let index = 0; index < 20; index++) {
schoolList.push({
id: index,
avatar: 'https://cdn.jsdelivr.net/npm/@vant/assets/cat.jpeg',
name: '中国福利会托儿所'
})
// 获取幼儿园列表页
axios.get('/srv/?a=kg_list')
.then(res => {
if (res.data.code === 1) {
schoolList.value = res.data.data;
} else {
console.warn(res);
Toast({
icon: 'close',
message: res.data.msg
});
}
})
.catch(err => {
console.error(err);
})
})
// 跳转幼儿园爱心书籍列表页
const onClick = (item) => {
$router.push({
path: '/client/chooseBook'
path: '/client/chooseBook',
query: {
kg_id: item.id
}
});
}
</script>
...
...
tsconfig.json
View file @
a99dfd5
...
...
@@ -34,7 +34,7 @@
"src/**/*.vue"
,
"tests/**/*.ts"
,
"tests/**/*.tsx"
,
"src/store/index.ts"
],
,
"src/store/index.ts"
,
"src/composables/useVideoList.js"
],
"exclude"
:
[
"node_modules"
]
...
...
vite.config.js
View file @
a99dfd5
...
...
@@ -23,6 +23,7 @@ export default({ command, mode }) => {
alias
:
{
// 将会被传递到 @rollup/plugin-alias 作为 entries 的选项。也可以是一个对象,或一个 { find, replacement } 的数组. 当使用文件系统路径的别名时,请始终使用绝对路径。相对路径的别名值会被原封不动地使用,因此无法被正常解析。 更高级的自定义解析方法可以通过 插件 实现。
"@"
:
path
.
resolve
(
__dirname
,
"src"
),
"@components"
:
path
.
resolve
(
__dirname
,
"src/components"
),
"@composables"
:
path
.
resolve
(
__dirname
,
"src/composables"
),
"@utils"
:
path
.
resolve
(
__dirname
,
"src/utils"
),
"@images"
:
path
.
resolve
(
__dirname
,
"src/assets/images"
),
"@css"
:
path
.
resolve
(
__dirname
,
"src/assets/css"
),
...
...
Please
register
or
login
to post a comment