fix: 页面优化
|
|
@ -92,6 +92,7 @@ export default defineManifestConfig({
|
||||||
},
|
},
|
||||||
requiredPrivateInfos: ['getLocation'],
|
requiredPrivateInfos: ['getLocation'],
|
||||||
requiredBackgroundModes: ['audio'],
|
requiredBackgroundModes: ['audio'],
|
||||||
|
lazyCodeLoading: 'requiredComponents',
|
||||||
// __usePrivacyCheck__: true,
|
// __usePrivacyCheck__: true,
|
||||||
},
|
},
|
||||||
uniStatistics: {
|
uniStatistics: {
|
||||||
|
|
|
||||||
|
|
@ -100,8 +100,7 @@
|
||||||
"pinyin-pro": "^3.26.0",
|
"pinyin-pro": "^3.26.0",
|
||||||
"qs": "6.5.3",
|
"qs": "6.5.3",
|
||||||
"vue": "3.4.21",
|
"vue": "3.4.21",
|
||||||
"wot-design-uni": "^1.4.0",
|
"wot-design-uni": "^1.4.0"
|
||||||
"z-paging": "^2.8.5"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@commitlint/cli": "^18.6.1",
|
"@commitlint/cli": "^18.6.1",
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ export default defineUniPages({
|
||||||
preloadRule: {
|
preloadRule: {
|
||||||
'pages/home/index/index': {
|
'pages/home/index/index': {
|
||||||
network: 'all',
|
network: 'all',
|
||||||
packages: ['pages-evaluation-sub'],
|
packages: ['pages-evaluation-sub', 'aiService-sub'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
condition: {
|
condition: {
|
||||||
|
|
|
||||||
|
|
@ -53,9 +53,6 @@ importers:
|
||||||
wot-design-uni:
|
wot-design-uni:
|
||||||
specifier: ^1.4.0
|
specifier: ^1.4.0
|
||||||
version: 1.4.0(vue@3.4.21(typescript@5.7.2))
|
version: 1.4.0(vue@3.4.21(typescript@5.7.2))
|
||||||
z-paging:
|
|
||||||
specifier: ^2.8.5
|
|
||||||
version: 2.8.5
|
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@commitlint/cli':
|
'@commitlint/cli':
|
||||||
specifier: ^18.6.1
|
specifier: ^18.6.1
|
||||||
|
|
@ -6593,10 +6590,6 @@ packages:
|
||||||
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
z-paging@2.8.5:
|
|
||||||
resolution: {integrity: sha512-tvMnwo1zudiFATbKYOEzejf9pI94UMXbK7A5tfq9khIJy8YBOLiexLNEJF/s+I7vqyLYwhALoI0cIarEe13kgw==}
|
|
||||||
engines: {HBuilderX: ^3.0.7}
|
|
||||||
|
|
||||||
snapshots:
|
snapshots:
|
||||||
|
|
||||||
'@ampproject/remapping@2.3.0':
|
'@ampproject/remapping@2.3.0':
|
||||||
|
|
@ -14564,5 +14557,3 @@ snapshots:
|
||||||
yargs-parser: 21.1.1
|
yargs-parser: 21.1.1
|
||||||
|
|
||||||
yocto-queue@0.1.0: {}
|
yocto-queue@0.1.0: {}
|
||||||
|
|
||||||
z-paging@2.8.5: {}
|
|
||||||
|
|
|
||||||
|
|
@ -1,39 +1,33 @@
|
||||||
<route lang="json5" type="page">
|
<route lang="json5" type="page">
|
||||||
{
|
{
|
||||||
style: {
|
style: {
|
||||||
navigationBarTitleText: '小纬',
|
navigationBarTitleText: '六纬AI小助手',
|
||||||
},
|
},
|
||||||
|
needLogin: true,
|
||||||
}
|
}
|
||||||
</route>
|
</route>
|
||||||
<template>
|
<template>
|
||||||
<web-view src="http://localhost:3001/sort-college" @message="handleChildMessage" />
|
<web-view :src="url" @message="handleChildMessage" :update-title="false" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { useUserStore } from '@/store'
|
||||||
|
|
||||||
|
const userStore = useUserStore()
|
||||||
|
|
||||||
|
//chat.ycymedu.com
|
||||||
|
const url = ref(
|
||||||
|
`https://chat.ycymedu.com?userId=${userStore.userInfo.estimatedAchievement.wxId}&subjectGroup=${userStore.userInfo.estimatedAchievement.subjectGroup}&expectedScore=${userStore.userInfo.estimatedAchievement.expectedScore}&provinceName=${userStore.userInfo.estimatedAchievement.provinceName}`,
|
||||||
|
)
|
||||||
|
|
||||||
const handleChildMessage = (event) => {
|
const handleChildMessage = (event) => {
|
||||||
console.log('子应用传递的消息', event)
|
console.log('子应用传递的消息', event)
|
||||||
}
|
}
|
||||||
|
|
||||||
const callback = ({
|
|
||||||
// 接收页面B回传的参数
|
|
||||||
response,
|
|
||||||
method,
|
|
||||||
}) => {
|
|
||||||
console.log('callback.response: ', response) // 显示 {name: "张三"}
|
|
||||||
console.log('callback.method: ', method) // 显示 passToA
|
|
||||||
}
|
|
||||||
|
|
||||||
onLoad(() => {
|
onLoad(() => {
|
||||||
const manager = uni.getRecorderManager()
|
uni.getRecorderManager()
|
||||||
manager.start({
|
uni.getBackgroundAudioManager()
|
||||||
format: 'mp3',
|
|
||||||
})
|
})
|
||||||
manager.onStop((e) => {
|
|
||||||
console.log('录音结束')
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
defineExpose({ callback })
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
<style lang="scss" scoped></style>
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,10 @@
|
||||||
@touchend.stop="endDrag"
|
@touchend.stop="endDrag"
|
||||||
:style="{ right: position.x + 'px', bottom: position.y + 'px' }"
|
:style="{ right: position.x + 'px', bottom: position.y + 'px' }"
|
||||||
>
|
>
|
||||||
<image class="w-full h-full rounded-full" src="/static/images/home/customerService.svg"></image>
|
<image
|
||||||
|
class="w-full h-full rounded-full"
|
||||||
|
src="https://api.static.ycymedu.com/src/images/home/customerService.svg"
|
||||||
|
></image>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,21 @@
|
||||||
<template>
|
<template>
|
||||||
<view class="mx-5 rounded-lg bg-white px-[32rpx] py-[56rpx]">
|
<view class="mx-5 rounded-lg bg-white px-[32rpx] py-[56rpx]">
|
||||||
<view
|
<view
|
||||||
class="flex items-center justify-between mx-[34rpx] py-[30rpx]"
|
class="flex items-center justify-between mx-[34rpx] py-[26rpx]"
|
||||||
style="border-bottom: 2rpx solid #ededed"
|
style="border-bottom: 2rpx solid #ededed"
|
||||||
@click="handleChange"
|
@click="handleChange"
|
||||||
>
|
>
|
||||||
<text class="text-[40rpx] text-[#636363]">输入模考/高考成绩</text>
|
<text class="text-[44rpx] text-[#333]">
|
||||||
<image class="w-[42rpx] h-[39rpx]" src="/static/images/home/pen.svg"></image>
|
{{
|
||||||
|
userStore.userInfo.estimatedAchievement.expectedScore
|
||||||
|
? userStore.userInfo.estimatedAchievement.expectedScore
|
||||||
|
: '输入模考/高考成绩'
|
||||||
|
}}
|
||||||
|
</text>
|
||||||
|
<image
|
||||||
|
class="w-[42rpx] h-[39rpx]"
|
||||||
|
src="https://api.static.ycymedu.com/src/images/home/pen.svg"
|
||||||
|
></image>
|
||||||
</view>
|
</view>
|
||||||
<view class="mt-[56rpx] flex items-center justify-between">
|
<view class="mt-[56rpx] flex items-center justify-between">
|
||||||
<button
|
<button
|
||||||
|
|
@ -27,7 +36,9 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
const value = ref('')
|
import { useUserStore } from '@/store/user'
|
||||||
|
|
||||||
|
const userStore = useUserStore()
|
||||||
|
|
||||||
const handleChange = () => {
|
const handleChange = () => {
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
<text class="text-[32rpx] text-[#333333] font-semibold">高考资讯</text>
|
<text class="text-[32rpx] text-[#333333] font-semibold">高考资讯</text>
|
||||||
<image
|
<image
|
||||||
class="w-[40rpx] h-[40rpx]"
|
class="w-[40rpx] h-[40rpx]"
|
||||||
src="/static/images/home/right.svg"
|
src="https://api.static.ycymedu.com/src/images/home/right.svg"
|
||||||
@click="toNewsPage"
|
@click="toNewsPage"
|
||||||
></image>
|
></image>
|
||||||
</view>
|
</view>
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
<text class="text-[32rpx] text-[#333333] font-semibold">热门排行榜</text>
|
<text class="text-[32rpx] text-[#333333] font-semibold">热门排行榜</text>
|
||||||
<image
|
<image
|
||||||
class="w-[40rpx] h-[40rpx]"
|
class="w-[40rpx] h-[40rpx]"
|
||||||
src="/static/images/home/right.svg"
|
src="https://api.static.ycymedu.com/src/images/home/right.svg"
|
||||||
@click="toSchool('0')"
|
@click="toSchool('0')"
|
||||||
></image>
|
></image>
|
||||||
</view>
|
</view>
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
@click="goPath(item.path, item.isTab)"
|
@click="goPath(item.path, item.isTab)"
|
||||||
>
|
>
|
||||||
<image :src="item.icon" class="w-[88rpx] h-[88rpx]" mode="widthFix"></image>
|
<image :src="item.icon" class="w-[88rpx] h-[88rpx]" mode="widthFix"></image>
|
||||||
<view class="text-[22rpx] text-[#303030] mt-[8rpx]">{{ item.name }}</view>
|
<view class="text-[24rpx] text-[#303030] mt-[8rpx]">{{ item.name }}</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -18,14 +18,14 @@ const subMenus = [
|
||||||
id: 1,
|
id: 1,
|
||||||
name: '找大学',
|
name: '找大学',
|
||||||
path: '/pages-sub/home/college/index',
|
path: '/pages-sub/home/college/index',
|
||||||
icon: '/static/images/home/college.svg',
|
icon: 'https://api.static.ycymedu.com/src/images/home/college.svg',
|
||||||
isTab: false,
|
isTab: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 2,
|
id: 2,
|
||||||
name: '查专业',
|
name: '查专业',
|
||||||
path: '/pages-sub/home/major/index',
|
path: '/pages-sub/home/major/index',
|
||||||
icon: '/static/images/home/major.svg',
|
icon: 'https://api.static.ycymedu.com/src/images/home/major.svg',
|
||||||
isTab: false,
|
isTab: false,
|
||||||
},
|
},
|
||||||
// 看职业
|
// 看职业
|
||||||
|
|
@ -33,7 +33,7 @@ const subMenus = [
|
||||||
id: 3,
|
id: 3,
|
||||||
name: '看职业',
|
name: '看职业',
|
||||||
path: '/pages-sub/home/career/index',
|
path: '/pages-sub/home/career/index',
|
||||||
icon: '/static/images/home/career.svg',
|
icon: 'https://api.static.ycymedu.com/src/images/home/career.svg',
|
||||||
isTab: false,
|
isTab: false,
|
||||||
},
|
},
|
||||||
// 批次线
|
// 批次线
|
||||||
|
|
@ -41,14 +41,14 @@ const subMenus = [
|
||||||
id: 4,
|
id: 4,
|
||||||
name: '批次线',
|
name: '批次线',
|
||||||
path: '/pages-sub/home/line/index',
|
path: '/pages-sub/home/line/index',
|
||||||
icon: '/static/images/home/line.svg',
|
icon: 'https://api.static.ycymedu.com/src/images/home/line.svg',
|
||||||
},
|
},
|
||||||
// 查位次
|
// 查位次
|
||||||
{
|
{
|
||||||
id: 5,
|
id: 5,
|
||||||
name: '查位次',
|
name: '查位次',
|
||||||
path: '/pages-evaluation-sub/rank/index',
|
path: '/pages-evaluation-sub/rank/index',
|
||||||
icon: '/static/images/home/rank.svg',
|
icon: 'https://api.static.ycymedu.com/src/images/home/rank.svg',
|
||||||
isTab: false,
|
isTab: false,
|
||||||
},
|
},
|
||||||
// 查扩缩招
|
// 查扩缩招
|
||||||
|
|
@ -56,7 +56,7 @@ const subMenus = [
|
||||||
id: 6,
|
id: 6,
|
||||||
name: '查扩缩招',
|
name: '查扩缩招',
|
||||||
path: '/pages-sub/home/expand/index',
|
path: '/pages-sub/home/expand/index',
|
||||||
icon: '/static/images/home/expand.svg',
|
icon: 'https://api.static.ycymedu.com/src/images/home/expand.svg',
|
||||||
isTab: false,
|
isTab: false,
|
||||||
},
|
},
|
||||||
// 专业测评
|
// 专业测评
|
||||||
|
|
@ -64,7 +64,7 @@ const subMenus = [
|
||||||
id: 7,
|
id: 7,
|
||||||
name: '专业测评',
|
name: '专业测评',
|
||||||
path: '/pages/evaluation/index/index',
|
path: '/pages/evaluation/index/index',
|
||||||
icon: '/static/images/home/evaluation.svg',
|
icon: 'https://api.static.ycymedu.com/src/images/home/evaluation.svg',
|
||||||
isTab: true,
|
isTab: true,
|
||||||
},
|
},
|
||||||
// 大学甄别
|
// 大学甄别
|
||||||
|
|
@ -72,7 +72,7 @@ const subMenus = [
|
||||||
id: 8,
|
id: 8,
|
||||||
name: '大学甄别',
|
name: '大学甄别',
|
||||||
path: '/pages-sub/home/distinguish/index',
|
path: '/pages-sub/home/distinguish/index',
|
||||||
icon: '/static/images/home/distinguish.svg',
|
icon: 'https://api.static.ycymedu.com/src/images/home/distinguish.svg',
|
||||||
isTab: false,
|
isTab: false,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
|
|
||||||
const props = defineProps({
|
defineProps({
|
||||||
title: {
|
title: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '',
|
default: '',
|
||||||
|
|
@ -155,6 +155,7 @@ const handleClickLeft = () => {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
min-width: 100rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.back-icon {
|
.back-icon {
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
{{ phone ? '申请使用您的手机号' : '申请获取您的个人信息' }}
|
{{ phone ? '申请使用您的手机号' : '申请获取您的个人信息' }}
|
||||||
</text>
|
</text>
|
||||||
<button
|
<button
|
||||||
class="w-[493rpx] mb-[40rpx] h-[88rpx] rounded-[44rpx] text-[32rpx] text-white"
|
class="w-[493rpx]! mb-[40rpx] h-[88rpx]! rounded-[44rpx] text-[32rpx] text-white flex items-center justify-center"
|
||||||
:class="checked ? 'bg-[#1580FF]' : 'bg-[#BFBFBF]'"
|
:class="checked ? 'bg-[#1580FF]' : 'bg-[#BFBFBF]'"
|
||||||
@click.stop="handleClick"
|
@click.stop="handleClick"
|
||||||
open-type="getPhoneNumber"
|
open-type="getPhoneNumber"
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,21 @@
|
||||||
<template>
|
<template>
|
||||||
<view
|
<label
|
||||||
class="radio"
|
class="radio-wrapper"
|
||||||
:class="{
|
:class="{ 'radio-wrapper--disabled': isDisabled }"
|
||||||
'radio--disabled': isDisabled,
|
@click.stop="handleClick"
|
||||||
'radio-active': isChecked,
|
|
||||||
}"
|
|
||||||
@click="handleClick"
|
|
||||||
>
|
>
|
||||||
<view class="radio__icon" :class="{ 'radio__icon--checked': isChecked }">
|
<radio
|
||||||
<view v-if="isChecked" class="radio__icon-dot"></view>
|
class="radio"
|
||||||
</view>
|
:value="String(name)"
|
||||||
<view class="radio__label">
|
:checked="isChecked"
|
||||||
|
:disabled="isDisabled"
|
||||||
|
:color="isChecked ? '#0083ff' : ''"
|
||||||
|
:name="String(name)"
|
||||||
|
/>
|
||||||
|
<view class="radio-label" :class="{ 'radio-label--active': isChecked }">
|
||||||
<slot>{{ label }}</slot>
|
<slot>{{ label }}</slot>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</label>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
|
@ -65,49 +67,23 @@ const handleClick = () => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.radio {
|
.radio-wrapper {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
cursor: pointer;
|
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
width: 100%;
|
padding: 8rpx 0;
|
||||||
height: 100%;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
&--disabled {
|
&--disabled {
|
||||||
cursor: not-allowed;
|
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__icon {
|
|
||||||
width: 40rpx;
|
|
||||||
height: 40rpx;
|
|
||||||
border: 2rpx solid #dcdfe6;
|
|
||||||
border-radius: 50%;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
margin-right: 8rpx;
|
|
||||||
transition: all 0.2s;
|
|
||||||
|
|
||||||
&--checked {
|
|
||||||
border-color: #0083ff;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&__icon-dot {
|
.radio-label {
|
||||||
width: 20rpx;
|
margin-left: 10rpx;
|
||||||
height: 20rpx;
|
|
||||||
background-color: #0083ff;
|
|
||||||
border-radius: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__label {
|
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.radio-active {
|
&--active {
|
||||||
color: #0083ff;
|
color: #0083ff;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<view class="radio-group">
|
<radio-group class="radio-group" :value="modelValue" @change="handleChange">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</view>
|
</radio-group>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
|
@ -20,6 +20,13 @@ const props = defineProps({
|
||||||
|
|
||||||
const emit = defineEmits(['update:modelValue', 'change'])
|
const emit = defineEmits(['update:modelValue', 'change'])
|
||||||
|
|
||||||
|
// 处理变更
|
||||||
|
const handleChange = (e: any) => {
|
||||||
|
const value = e.detail.value
|
||||||
|
emit('update:modelValue', value)
|
||||||
|
emit('change', value)
|
||||||
|
}
|
||||||
|
|
||||||
// 切换选项
|
// 切换选项
|
||||||
const toggleOption = (value: string | number) => {
|
const toggleOption = (value: string | number) => {
|
||||||
emit('update:modelValue', value)
|
emit('update:modelValue', value)
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,8 @@
|
||||||
],
|
],
|
||||||
"requiredBackgroundModes": [
|
"requiredBackgroundModes": [
|
||||||
"audio"
|
"audio"
|
||||||
]
|
],
|
||||||
|
"lazyCodeLoading": "requiredComponents"
|
||||||
},
|
},
|
||||||
"mp-alipay": {
|
"mp-alipay": {
|
||||||
"usingComponents": true
|
"usingComponents": true
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@
|
||||||
<view class="flex-1 overflow-auto pb-[30rpx] relative">
|
<view class="flex-1 overflow-auto pb-[30rpx] relative">
|
||||||
<!-- 顶部卡片 -->
|
<!-- 顶部卡片 -->
|
||||||
<view class="flex flex-col pt-[32rpx] px-[84rpx] h-[244rpx] mb-[-148rpx]">
|
<view class="flex flex-col pt-[32rpx] px-[84rpx] h-[244rpx] mb-[-148rpx]">
|
||||||
<image src="/static/images/evaluate/bg.png" class="header-bg" />
|
<image src="https://api.static.ycymedu.com/src/images/evaluate/bg.png" class="header-bg" />
|
||||||
<text class="text-[#333] text-[28rpx] mb-[14rpx] z-2">您的兴趣类型为</text>
|
<text class="text-[#333] text-[28rpx] mb-[14rpx] z-2">您的兴趣类型为</text>
|
||||||
<text class="text-[#117CFC] text-[36rpx] z-2">{{ studyRecord.title }}</text>
|
<text class="text-[#117CFC] text-[36rpx] z-2">{{ studyRecord.title }}</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@
|
||||||
<view class="flex-1 overflow-auto pb-[30rpx] relative">
|
<view class="flex-1 overflow-auto pb-[30rpx] relative">
|
||||||
<!-- 顶部卡片 -->
|
<!-- 顶部卡片 -->
|
||||||
<view class="flex flex-col pt-[32rpx] px-[84rpx] h-[244rpx] mb-[-148rpx]">
|
<view class="flex flex-col pt-[32rpx] px-[84rpx] h-[244rpx] mb-[-148rpx]">
|
||||||
<image src="/static/images/evaluate/bg.png" class="header-bg" />
|
<image src="https://api.static.ycymedu.com/src/images/evaluate/bg.png" class="header-bg" />
|
||||||
<text class="text-[#333] text-[28rpx] mb-[14rpx] z-2">您的兴趣类型为</text>
|
<text class="text-[#333] text-[28rpx] mb-[14rpx] z-2">您的兴趣类型为</text>
|
||||||
<text class="text-[#117CFC] text-[36rpx] z-2">{{ studyRecord.title }}</text>
|
<text class="text-[#117CFC] text-[36rpx] z-2">{{ studyRecord.title }}</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@
|
||||||
<view class="flex-1 overflow-auto pb-[30rpx] relative">
|
<view class="flex-1 overflow-auto pb-[30rpx] relative">
|
||||||
<!-- 顶部卡片 -->
|
<!-- 顶部卡片 -->
|
||||||
<view class="flex flex-col pt-[32rpx] px-[84rpx] h-[244rpx] mb-[-148rpx]">
|
<view class="flex flex-col pt-[32rpx] px-[84rpx] h-[244rpx] mb-[-148rpx]">
|
||||||
<image src="/static/images/evaluate/bg.png" class="header-bg" />
|
<image src="https://api.static.ycymedu.com/src/images/evaluate/bg.png" class="header-bg" />
|
||||||
<text class="text-[#333] text-[28rpx] mb-[14rpx] z-2">您的职业价值观</text>
|
<text class="text-[#333] text-[28rpx] mb-[14rpx] z-2">您的职业价值观</text>
|
||||||
<text class="text-[#117CFC] text-[36rpx] z-2">{{ studyRecord.tag }}</text>
|
<text class="text-[#117CFC] text-[36rpx] z-2">{{ studyRecord.tag }}</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
<template>
|
||||||
|
<view class="rounded-full p-[14rpx] w-max bg-[#fff]">
|
||||||
|
<view class="w-[162rpx] h-[162rpx] custom-style"></view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup></script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.custom-style {
|
||||||
|
border: 10rpx dashed #00b281;
|
||||||
|
border-radius: 50%;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-style::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
blur: filter(10px);
|
||||||
|
width: 162rpx;
|
||||||
|
height: 162rpx;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
<route lang="json5" type="page">
|
||||||
|
{
|
||||||
|
style: {
|
||||||
|
navigationStyle: 'custom',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</route>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<scroll-view :scroll-y="true" class="flex flex-col h-screen relative custom-bg">
|
||||||
|
<Navbar
|
||||||
|
safeAreaInsetTop
|
||||||
|
:bordered="false"
|
||||||
|
leftArrow
|
||||||
|
@clickLeft="handleBack"
|
||||||
|
bg-color="transparent"
|
||||||
|
>
|
||||||
|
<template #title>
|
||||||
|
<text class="text-[#1F2329] text-[36rpx] font-medium text-[#fff]">SAS焦虑测评报告</text>
|
||||||
|
</template>
|
||||||
|
</Navbar>
|
||||||
|
|
||||||
|
<view class="flex-1 overflow-auto pb-[30rpx] relative">
|
||||||
|
<!-- 顶部卡片 -->
|
||||||
|
<view class="h-[772rpx] relative">
|
||||||
|
<Dashboard />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import Navbar from '@/pages-evaluation-sub/components/navbar/Navbar.vue'
|
||||||
|
import Dashboard from '@/pages-evaluation-sub/evaluate/components/Dashboard.vue'
|
||||||
|
|
||||||
|
import { getAbilityDimension } from '@/service/index/api'
|
||||||
|
|
||||||
|
const pageType = ref(0)
|
||||||
|
const pageId = ref(0)
|
||||||
|
|
||||||
|
const handleBack = () => {
|
||||||
|
uni.navigateBack()
|
||||||
|
}
|
||||||
|
|
||||||
|
const studyRecord = ref({
|
||||||
|
description: '',
|
||||||
|
title: '',
|
||||||
|
linChart: [],
|
||||||
|
reportItems: [],
|
||||||
|
hTag: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
onLoad((options) => {
|
||||||
|
pageType.value = +options.type
|
||||||
|
pageId.value = options.id
|
||||||
|
|
||||||
|
getAbilityDimension({ ScaleId: pageId.value }).then((resp) => {
|
||||||
|
if (resp.code === 200) {
|
||||||
|
studyRecord.value = resp.result as {
|
||||||
|
description: string
|
||||||
|
title: string
|
||||||
|
linChart: any[]
|
||||||
|
reportItems: any[]
|
||||||
|
hTag: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.custom-bg {
|
||||||
|
background: linear-gradient(184deg, #0d79fc 0%, #2186fc 100%);
|
||||||
|
}
|
||||||
|
:deep(.icon-class) {
|
||||||
|
color: #fff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-border {
|
||||||
|
width: 162rpx;
|
||||||
|
height: 162rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 6rpx dashed;
|
||||||
|
border-color: #05d69c transparent transparent transparent;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -94,7 +94,7 @@
|
||||||
<LEchart ref="echart" class="h-[300rpx]" v-show="!noData"></LEchart>
|
<LEchart ref="echart" class="h-[300rpx]" v-show="!noData"></LEchart>
|
||||||
<view class="flex items-center justify-center flex-col my-[80rpx] relative" v-show="noData">
|
<view class="flex items-center justify-center flex-col my-[80rpx] relative" v-show="noData">
|
||||||
<image
|
<image
|
||||||
src="../static/images/no-data.jpg"
|
src="https://api.static.ycymedu.com/evaluation/sub/no-data.jpg"
|
||||||
mode="scaleToFill"
|
mode="scaleToFill"
|
||||||
class="w-[300rpx] h-[300rpx]"
|
class="w-[300rpx] h-[300rpx]"
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 14 KiB |
|
|
@ -2,6 +2,7 @@
|
||||||
<view class="custom-picker">
|
<view class="custom-picker">
|
||||||
<view class="picker-mask" @touchmove.stop.prevent></view>
|
<view class="picker-mask" @touchmove.stop.prevent></view>
|
||||||
<picker-view
|
<picker-view
|
||||||
|
v-if="visible"
|
||||||
:value="currentIndex"
|
:value="currentIndex"
|
||||||
:indicator-style="indicatorStyle"
|
:indicator-style="indicatorStyle"
|
||||||
:style="{
|
:style="{
|
||||||
|
|
@ -12,25 +13,18 @@
|
||||||
@change="handleChange"
|
@change="handleChange"
|
||||||
class="picker-view"
|
class="picker-view"
|
||||||
:mask-class="'picker-mask'"
|
:mask-class="'picker-mask'"
|
||||||
:indicator-class="'picker-indicator'"
|
|
||||||
>
|
>
|
||||||
<picker-view-column class="border-none">
|
<picker-view-column class="border-none">
|
||||||
<view
|
<view v-for="(item, index) in formattedList" :key="index" class="picker-item">
|
||||||
v-for="(item, index) in formattedList"
|
|
||||||
:key="index"
|
|
||||||
class="picker-item"
|
|
||||||
:class="{ 'picker-item-selected': currentIndex[0] === index }"
|
|
||||||
>
|
|
||||||
{{ item }}
|
{{ item }}
|
||||||
</view>
|
</view>
|
||||||
</picker-view-column>
|
</picker-view-column>
|
||||||
</picker-view>
|
</picker-view>
|
||||||
<!-- <view class="picker-indicator-line"></view> -->
|
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed } from 'vue'
|
import { computed, ref, watch, onMounted } from 'vue'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
modelValue: {
|
modelValue: {
|
||||||
|
|
@ -57,6 +51,11 @@ const props = defineProps({
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['update:modelValue', 'change'])
|
const emit = defineEmits(['update:modelValue', 'change'])
|
||||||
|
const visible = ref(false)
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
visible.value = true
|
||||||
|
})
|
||||||
|
|
||||||
// 格式化列表数据
|
// 格式化列表数据
|
||||||
const formattedList = computed(() => {
|
const formattedList = computed(() => {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<page-head :title="title"></page-head>
|
||||||
|
<view class="uni-padding-wrap">
|
||||||
|
<view class="uni-title">{{ value }}</view>
|
||||||
|
</view>
|
||||||
|
<picker-view
|
||||||
|
v-if="visible"
|
||||||
|
:indicator-style="indicatorStyle"
|
||||||
|
:mask-style="maskStyle"
|
||||||
|
:value="value"
|
||||||
|
@change="bindChange"
|
||||||
|
>
|
||||||
|
<picker-view-column>
|
||||||
|
<view class="item" v-for="(item, index) in months" :key="index">{{ item }}月</view>
|
||||||
|
</picker-view-column>
|
||||||
|
<picker-view-column>
|
||||||
|
<view class="item" v-for="(item, index) in days" :key="index">{{ item }}日</view>
|
||||||
|
</picker-view-column>
|
||||||
|
</picker-view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
const date = new Date()
|
||||||
|
const years = []
|
||||||
|
const year = date.getFullYear()
|
||||||
|
const months = []
|
||||||
|
const month = date.getMonth() + 1
|
||||||
|
const days = []
|
||||||
|
const day = date.getDate()
|
||||||
|
|
||||||
|
for (let i = 1990; i <= date.getFullYear(); i++) {
|
||||||
|
years.push(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 1; i <= 12; i++) {
|
||||||
|
months.push(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 1; i <= 31; i++) {
|
||||||
|
days.push(i)
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
title: 'picker-view',
|
||||||
|
years,
|
||||||
|
year,
|
||||||
|
months,
|
||||||
|
month,
|
||||||
|
days,
|
||||||
|
day,
|
||||||
|
value: [month, day - 1],
|
||||||
|
/**
|
||||||
|
* 解决动态设置indicator-style不生效的问题
|
||||||
|
*/
|
||||||
|
visible: true,
|
||||||
|
// indicatorStyle: `height: ${Math.round(uni.getSystemInfoSync().screenWidth/(750/100))}px;`
|
||||||
|
indicatorStyle: `height: 50px;`,
|
||||||
|
// #ifdef MP-KUAISHOU
|
||||||
|
maskStyle: 'padding:10px 0',
|
||||||
|
// #endif
|
||||||
|
// #ifndef MP-KUAISHOU
|
||||||
|
maskStyle: '',
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
bindChange(e) {
|
||||||
|
const val = e.detail.value
|
||||||
|
this.year = this.years[val[0]]
|
||||||
|
this.month = this.months[val[1]]
|
||||||
|
this.day = this.days[val[2]]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
picker-view {
|
||||||
|
width: 100%;
|
||||||
|
height: 600rpx;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item {
|
||||||
|
line-height: 100rpx;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
:key="index"
|
:key="index"
|
||||||
class="drop-menu__item"
|
class="drop-menu__item"
|
||||||
:class="{ 'drop-menu__item--active': index === activeIndex }"
|
:class="{ 'drop-menu__item--active': index === activeIndex }"
|
||||||
@click="handleTitleClick(index)"
|
@click.self.stop="handleTitleClick(index)"
|
||||||
>
|
>
|
||||||
<text class="drop-menu__title">{{ item }}</text>
|
<text class="drop-menu__title">{{ item }}</text>
|
||||||
<text
|
<text
|
||||||
|
|
@ -22,7 +22,7 @@
|
||||||
v-if="activeIndex !== -1"
|
v-if="activeIndex !== -1"
|
||||||
class="drop-menu__mask"
|
class="drop-menu__mask"
|
||||||
:style="{ top: maskTop }"
|
:style="{ top: maskTop }"
|
||||||
@click="closeDropMenu"
|
@click.self.stop="closeDropMenu"
|
||||||
></view>
|
></view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -52,7 +52,6 @@ const activeIndex = ref(-1)
|
||||||
|
|
||||||
const maskTop = ref('88px')
|
const maskTop = ref('88px')
|
||||||
|
|
||||||
// 添加标题
|
|
||||||
const addTitle = (title: string) => {
|
const addTitle = (title: string) => {
|
||||||
titles.value.push(title)
|
titles.value.push(title)
|
||||||
}
|
}
|
||||||
|
|
@ -60,13 +59,10 @@ const addTitle = (title: string) => {
|
||||||
const instance = getCurrentInstance()
|
const instance = getCurrentInstance()
|
||||||
|
|
||||||
const dropMenuRef = ref()
|
const dropMenuRef = ref()
|
||||||
// 处理标题点击
|
|
||||||
const handleTitleClick = (index: number) => {
|
const handleTitleClick = (index: number) => {
|
||||||
// 如果点击的是当前打开的菜单,则关闭
|
|
||||||
if (activeIndex.value === index) {
|
if (activeIndex.value === index) {
|
||||||
activeIndex.value = -1
|
activeIndex.value = -1
|
||||||
} else {
|
} else {
|
||||||
// 否则打开点击的菜单
|
|
||||||
activeIndex.value = index
|
activeIndex.value = index
|
||||||
}
|
}
|
||||||
const query = uni.createSelectorQuery().in(instance.proxy)
|
const query = uni.createSelectorQuery().in(instance.proxy)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<view
|
<view
|
||||||
|
v-if="mounted"
|
||||||
class="drop-menu-item"
|
class="drop-menu-item"
|
||||||
:class="[customClass, { 'drop-menu-item--show': isShow }]"
|
:class="[customClass, { 'drop-menu-item--show': isShow }]"
|
||||||
:style="{
|
:style="{
|
||||||
|
|
@ -9,14 +10,14 @@
|
||||||
>
|
>
|
||||||
<view class="drop-menu-item__wrapper" :class="{ 'drop-menu-item__wrapper--show': isShow }">
|
<view class="drop-menu-item__wrapper" :class="{ 'drop-menu-item__wrapper--show': isShow }">
|
||||||
<!-- 默认选项列表 -->
|
<!-- 默认选项列表 -->
|
||||||
<scroll-view v-if="!$slots.default" scroll-y class="drop-menu-item__content">
|
<scroll-view v-if="isShow && !$slots.default" scroll-y class="drop-menu-item__content">
|
||||||
<view class="drop-menu-item__option-list">
|
<view class="drop-menu-item__option-list">
|
||||||
<view
|
<view
|
||||||
v-for="(option, index) in options"
|
v-for="(option, index) in options"
|
||||||
:key="index"
|
:key="index"
|
||||||
class="drop-menu-item__option"
|
class="drop-menu-item__option"
|
||||||
:class="{ 'drop-menu-item__option--active': isOptionActive(option) }"
|
:class="{ 'drop-menu-item__option--active': isOptionActive(option) }"
|
||||||
@click="handleOptionClick(option)"
|
@click.self.stop="handleOptionClick(option)"
|
||||||
>
|
>
|
||||||
<text class="drop-menu-item__text">{{ getOptionText(option) }}</text>
|
<text class="drop-menu-item__text">{{ getOptionText(option) }}</text>
|
||||||
<text v-if="isOptionActive(option)" class="drop-menu-item__icon">✓</text>
|
<text v-if="isOptionActive(option)" class="drop-menu-item__icon">✓</text>
|
||||||
|
|
@ -24,7 +25,7 @@
|
||||||
</view>
|
</view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
<!-- 自定义内容插槽 -->
|
<!-- 自定义内容插槽 -->
|
||||||
<view v-else class="drop-menu-item__custom-content">
|
<view v-if="isShow && $slots.default" class="drop-menu-item__custom-content">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
@ -32,7 +33,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, inject, onMounted, computed, watch } from 'vue'
|
import { ref, inject, onMounted, computed, watch, nextTick } from 'vue'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
modelValue: {
|
modelValue: {
|
||||||
|
|
@ -64,12 +65,12 @@ const props = defineProps({
|
||||||
const emit = defineEmits(['update:modelValue', 'change', 'open'])
|
const emit = defineEmits(['update:modelValue', 'change', 'open'])
|
||||||
|
|
||||||
// 注入父组件提供的数据和方法
|
// 注入父组件提供的数据和方法
|
||||||
const { activeIndex, addTitle, closeDropMenu, zIndex, duration, direction, titles } = inject(
|
const { activeIndex, addTitle, closeDropMenu, zIndex, duration, titles } = inject('dropMenu') as any
|
||||||
'dropMenu',
|
|
||||||
) as any
|
|
||||||
|
|
||||||
// 当前组件的索引
|
// 当前组件的索引
|
||||||
const itemIndex = ref(-1)
|
const itemIndex = ref(-1)
|
||||||
|
// 是否已挂载
|
||||||
|
const mounted = ref(false)
|
||||||
|
|
||||||
// 是否显示下拉内容
|
// 是否显示下拉内容
|
||||||
const isShow = computed(() => activeIndex.value === itemIndex.value)
|
const isShow = computed(() => activeIndex.value === itemIndex.value)
|
||||||
|
|
@ -117,6 +118,11 @@ onMounted(() => {
|
||||||
itemIndex.value = titles.value.length
|
itemIndex.value = titles.value.length
|
||||||
// 再添加标题
|
// 再添加标题
|
||||||
addTitle(props.title)
|
addTitle(props.title)
|
||||||
|
|
||||||
|
// 确保在下一个渲染周期后才显示组件
|
||||||
|
nextTick(() => {
|
||||||
|
mounted.value = true
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// 监听标题变化
|
// 监听标题变化
|
||||||
|
|
@ -148,15 +154,17 @@ watch(
|
||||||
transition: all 0.25s ease;
|
transition: all 0.25s ease;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);
|
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.1);
|
||||||
opacity: 0;
|
display: none;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
|
opacity: 0;
|
||||||
z-index: 11;
|
z-index: 11;
|
||||||
}
|
}
|
||||||
|
|
||||||
.drop-menu-item__wrapper--show {
|
.drop-menu-item__wrapper--show {
|
||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
opacity: 1;
|
display: inline-block;
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.drop-menu-item__content {
|
.drop-menu-item__content {
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@
|
||||||
<view class="i-carbon-search text-[#d9d9d9]"></view>
|
<view class="i-carbon-search text-[#d9d9d9]"></view>
|
||||||
<input
|
<input
|
||||||
v-model="searchValue"
|
v-model="searchValue"
|
||||||
type="number"
|
|
||||||
:placeholder="placeholder"
|
:placeholder="placeholder"
|
||||||
confirm-type="done"
|
confirm-type="done"
|
||||||
class="text-start ml-20rpx"
|
class="text-start ml-20rpx"
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
<view class="py-[48rpx] mx-[48rpx] avatar-border flex justify-center items-center">
|
<view class="py-[48rpx] mx-[48rpx] avatar-border flex justify-center items-center">
|
||||||
<image
|
<image
|
||||||
class="w-[144rpx] h-[144rpx] rounded-full"
|
class="w-[144rpx] h-[144rpx] rounded-full"
|
||||||
src="@/pages-sub/static/images/customerService/avatar.jpg"
|
src="https://api.static.ycymedu.com/sub/images/customerService/avatar.jpg"
|
||||||
></image>
|
></image>
|
||||||
<view class="flex flex-col text-[#000] ml-[32rpx]">
|
<view class="flex flex-col text-[#000] ml-[32rpx]">
|
||||||
<text class="mb-[12rpx] font-normal text-[28rpx]">专属客服为您服务</text>
|
<text class="mb-[12rpx] font-normal text-[28rpx]">专属客服为您服务</text>
|
||||||
|
|
|
||||||
|
|
@ -21,11 +21,12 @@
|
||||||
</Navbar>
|
</Navbar>
|
||||||
<view class="h-full w-full custom-bg absolute top-0 left-0 -z-1"></view>
|
<view class="h-full w-full custom-bg absolute top-0 left-0 -z-1"></view>
|
||||||
|
|
||||||
<view class="question-container flex-1 overflow-hidden mt-[30rpx]">
|
<view class="question-container flex-1 overflow-hidden mt-[30rpx] flex">
|
||||||
|
<view class="flex-1 h-0 relative">
|
||||||
<view
|
<view
|
||||||
v-for="(question, index) in questions"
|
v-for="(question, index) in questions"
|
||||||
:key="index"
|
:key="index"
|
||||||
:class="`card-container ${currentIndex === index ? 'current-card' : ''}`"
|
:class="`h-full overflow-y-auto card-container ${currentIndex === index ? 'current-card' : ''}`"
|
||||||
>
|
>
|
||||||
<view class="px-[30rpx] py-[40rpx] flex flex-col card-content">
|
<view class="px-[30rpx] py-[40rpx] flex flex-col card-content">
|
||||||
<text class="mb-[30rpx] text-[34rpx] font-semibold">
|
<text class="mb-[30rpx] text-[34rpx] font-semibold">
|
||||||
|
|
@ -50,8 +51,9 @@
|
||||||
</CheckboxGroup>
|
</CheckboxGroup>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
<view class="pb-safe mt-auto px-[30rpx]">
|
<view class="mt-[86rpx] px-[30rpx]">
|
||||||
<button class="next-question" :disabled="disableBtn" @click="handleNextQuestion">
|
<button class="next-question" :disabled="disableBtn" @click="handleNextQuestion">
|
||||||
{{ currentIndex === questions.length - 1 ? '提交' : '下一题' }}
|
{{ currentIndex === questions.length - 1 ? '提交' : '下一题' }}
|
||||||
({{ currentIndex + 1 }}/{{ questions.length }})
|
({{ currentIndex + 1 }}/{{ questions.length }})
|
||||||
|
|
@ -241,11 +243,13 @@ const handleSubmit = () => {
|
||||||
|
|
||||||
.next-question {
|
.next-question {
|
||||||
background: #1580ff;
|
background: #1580ff;
|
||||||
border-radius: 16rpx 16rpx 16rpx 16rpx;
|
border-radius: 16rpx;
|
||||||
padding: 22rpx 0;
|
height: 88rpx;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
text-align: center;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.custom-checkbox) {
|
:deep(.custom-checkbox) {
|
||||||
|
|
@ -289,6 +293,12 @@ const handleSubmit = () => {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
padding-bottom: calc(env(safe-area-inset-bottom) + 20rpx);
|
||||||
|
|
||||||
|
// 如果 safe-area-inset-bottom 为 0,则 padding-bottom 为 20rpx
|
||||||
|
@if env(safe-area-inset-bottom) == 0 {
|
||||||
|
padding-bottom: 20rpx;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-container {
|
.card-container {
|
||||||
|
|
@ -298,6 +308,7 @@ const handleSubmit = () => {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
transform: translate3d(100vw, 0, 0);
|
transform: translate3d(100vw, 0, 0);
|
||||||
margin: 0 30rpx;
|
margin: 0 30rpx;
|
||||||
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.current-card {
|
.current-card {
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
|
|
||||||
<image
|
<image
|
||||||
class="w-[286rpx] h-[286rpx] mt-[134rpx] mix-blend-multiply"
|
class="w-[286rpx] h-[286rpx] mt-[134rpx] mix-blend-multiply"
|
||||||
src="@/pages-sub/static/images/autoFill/auto-fill.jpg"
|
src="https://api.static.ycymedu.com/sub/images/autoFill/auto-fill.jpg"
|
||||||
mode="widthFix"
|
mode="widthFix"
|
||||||
@click="show = true"
|
@click="show = true"
|
||||||
></image>
|
></image>
|
||||||
|
|
|
||||||
|
|
@ -11,14 +11,6 @@
|
||||||
<wd-index-bar sticky class="overflow-y h-0 flex-auto">
|
<wd-index-bar sticky class="overflow-y h-0 flex-auto">
|
||||||
<view v-for="item in cities" :key="item.letter">
|
<view v-for="item in cities" :key="item.letter">
|
||||||
<wd-index-anchor :index="item.letter" />
|
<wd-index-anchor :index="item.letter" />
|
||||||
<!-- <wd-cell
|
|
||||||
border
|
|
||||||
clickable
|
|
||||||
v-for="city in item.provinces"
|
|
||||||
:key="city.id"
|
|
||||||
:title="city.provincename"
|
|
||||||
@click="chooseCity(city)"
|
|
||||||
></wd-cell> -->
|
|
||||||
<view
|
<view
|
||||||
v-for="city in item.provinces"
|
v-for="city in item.provinces"
|
||||||
:key="city.id"
|
:key="city.id"
|
||||||
|
|
@ -55,6 +47,7 @@ const chooseCity = (city: City) => {
|
||||||
userStore.userInfo.estimatedAchievement.provinceCode !== city.code
|
userStore.userInfo.estimatedAchievement.provinceCode !== city.code
|
||||||
) {
|
) {
|
||||||
userStore.clearUserEstimatedAchievement()
|
userStore.clearUserEstimatedAchievement()
|
||||||
|
// userStore.setEstimatedAchievement({ provinceName: city.provincename, provinceCode: city.code })
|
||||||
}
|
}
|
||||||
navigatorBack()
|
navigatorBack()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
</route>
|
</route>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<view class="">
|
<view class="h-screen flex flex-col">
|
||||||
<z-paging
|
<z-paging
|
||||||
ref="paging"
|
ref="paging"
|
||||||
use-virtual-list
|
use-virtual-list
|
||||||
|
|
@ -55,7 +55,7 @@
|
||||||
class="item-wrapper"
|
class="item-wrapper"
|
||||||
:id="`zp-id-${item.zp_index}`"
|
:id="`zp-id-${item.zp_index}`"
|
||||||
:key="item.zp_index"
|
:key="item.zp_index"
|
||||||
v-for="(item, index) in schoolList"
|
v-for="item in schoolList"
|
||||||
@click="itemClick(item, item.zp_index)"
|
@click="itemClick(item, item.zp_index)"
|
||||||
>
|
>
|
||||||
<view class="flex items-center p-[32rpx] w-full">
|
<view class="flex items-center p-[32rpx] w-full">
|
||||||
|
|
@ -98,6 +98,7 @@ import SearchInput from '@/pages-sub/components/input/SearchInput.vue'
|
||||||
import { getUniversityList } from '@/service/index/api'
|
import { getUniversityList } from '@/service/index/api'
|
||||||
|
|
||||||
const searchValue = ref('')
|
const searchValue = ref('')
|
||||||
|
const isLoading = ref(false)
|
||||||
|
|
||||||
const handleChange = (e: any) => {
|
const handleChange = (e: any) => {
|
||||||
paging.value.reload()
|
paging.value.reload()
|
||||||
|
|
@ -160,6 +161,10 @@ const handleNatureChange = (val) => {
|
||||||
natureInfo.value = val
|
natureInfo.value = val
|
||||||
paging.value.reload()
|
paging.value.reload()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onShow(() => {
|
||||||
|
isLoading.value = true
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
<!-- 专业测评 -->
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<text>专业测评</text>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup></script>
|
|
||||||
|
|
@ -87,7 +87,7 @@
|
||||||
</view>
|
</view>
|
||||||
<button
|
<button
|
||||||
block
|
block
|
||||||
class="mt-auto mb-[32rpx] rounded-[8rpx]! bg-[#1580FF]! mx-[32rpx]! text-[32rpx]! text-[#fff]! font-normal"
|
:class="`mt-auto mb-[32rpx] rounded-[8rpx] mx-[32rpx] text-[32rpx] text-[#fff]! font-normal ${btnFlag < 3 ? 'bg-[#BFBFBF]!' : 'bg-[#1580FF]!'}`"
|
||||||
@click="saveScore"
|
@click="saveScore"
|
||||||
:disabled="btnFlag < 3"
|
:disabled="btnFlag < 3"
|
||||||
>
|
>
|
||||||
|
|
@ -103,6 +103,7 @@
|
||||||
value-key="code"
|
value-key="code"
|
||||||
label-key="name"
|
label-key="name"
|
||||||
/>
|
/>
|
||||||
|
<!-- <PickerView /> -->
|
||||||
</view>
|
</view>
|
||||||
<view class="flex items-center justify-between px-[32rpx]">
|
<view class="flex items-center justify-between px-[32rpx]">
|
||||||
<view class="cancel-btn" @click="show = false">取消</view>
|
<view class="cancel-btn" @click="show = false">取消</view>
|
||||||
|
|
@ -121,6 +122,7 @@ import RadioGroup from '@/pages-sub/components/radio-group/RadioGroup.vue'
|
||||||
import Radio from '@/pages-sub/components/radio-group/Radio.vue'
|
import Radio from '@/pages-sub/components/radio-group/Radio.vue'
|
||||||
import CustomPickerView from '@/pages-sub/components/CustomPickerView.vue'
|
import CustomPickerView from '@/pages-sub/components/CustomPickerView.vue'
|
||||||
import ActionSheet from '@/pages-sub/components/ActionSheet.vue'
|
import ActionSheet from '@/pages-sub/components/ActionSheet.vue'
|
||||||
|
import PickerView from '@/pages-sub/components/TestPickerView.vue'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
useRules,
|
useRules,
|
||||||
|
|
@ -171,8 +173,8 @@ const btnFlag = computed(() => {
|
||||||
return num
|
return num
|
||||||
})
|
})
|
||||||
|
|
||||||
onLoad(() => {
|
onShow(() => {
|
||||||
userStore.$subscribe((mutation, state) => {
|
userStore.$subscribe(() => {
|
||||||
requireSubject.value = userStore.userInfo.estimatedAchievement.requireSubject.code || ''
|
requireSubject.value = userStore.userInfo.estimatedAchievement.requireSubject.code || ''
|
||||||
optionalSubject.value = userStore.userInfo.estimatedAchievement.optionalSubject.map(
|
optionalSubject.value = userStore.userInfo.estimatedAchievement.optionalSubject.map(
|
||||||
(item) => item.code,
|
(item) => item.code,
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,9 @@ export const useRules = () => {
|
||||||
requireSubjectList.value = matchRules.filter((item) => item?.isfirst === 'true')
|
requireSubjectList.value = matchRules.filter((item) => item?.isfirst === 'true')
|
||||||
optionalSubjectList.value = matchRules.filter((item) => !(item?.isfirst === 'true'))
|
optionalSubjectList.value = matchRules.filter((item) => !(item?.isfirst === 'true'))
|
||||||
|
|
||||||
|
if (userStore.userInfo.city.code !== userStore.userInfo.estimatedAchievement.provinceCode) {
|
||||||
|
return
|
||||||
|
}
|
||||||
splitSubject(requireSubjectList.value, optionalSubjectList.value)
|
splitSubject(requireSubjectList.value, optionalSubjectList.value)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -28,15 +28,15 @@
|
||||||
/>
|
/>
|
||||||
<image
|
<image
|
||||||
class="absolute top-0 z-[-1]"
|
class="absolute top-0 z-[-1]"
|
||||||
src="@/pages-sub/static/images/schoolRank/background.svg"
|
src="https://api.static.ycymedu.com/sub/images/schoolRank/background.svg"
|
||||||
/>
|
/>
|
||||||
<image
|
<image
|
||||||
class="h-[78rpx] w-[270rpx] absolute top-[249rpx] left-[102rpx] z-[-1]"
|
class="h-[78rpx] w-[270rpx] absolute top-[249rpx] left-[102rpx] z-[-1]"
|
||||||
src="@/pages-sub/static/images/schoolRank/title.svg"
|
src="https://api.static.ycymedu.com/sub/images/schoolRank/title.svg"
|
||||||
/>
|
/>
|
||||||
<image
|
<image
|
||||||
class="h-[190rpx] w-[190rpx] absolute top-[194rpx] left-[460rpx] mix-blend-multiply z-[-1]"
|
class="h-[190rpx] w-[190rpx] absolute top-[194rpx] left-[460rpx] mix-blend-multiply z-[-1]"
|
||||||
src="@/pages-sub/static/images/schoolRank/trophy.jpg"
|
src="https://api.static.ycymedu.com/sub/images/schoolRank/trophy.jpg"
|
||||||
/>
|
/>
|
||||||
</view>
|
</view>
|
||||||
<view class="px-[32rpx] my-[24rpx]">
|
<view class="px-[32rpx] my-[24rpx]">
|
||||||
|
|
@ -69,8 +69,8 @@
|
||||||
class="item-wrapper"
|
class="item-wrapper"
|
||||||
:id="`zp-id-${item.zp_index}`"
|
:id="`zp-id-${item.zp_index}`"
|
||||||
:key="item.zp_index"
|
:key="item.zp_index"
|
||||||
v-for="(item, index) in schoolList"
|
v-for="item in schoolList"
|
||||||
@click="itemClick(item, item.zp_index)"
|
@click="itemClick(item)"
|
||||||
>
|
>
|
||||||
<view class="flex items-center py-[32rpx] w-full">
|
<view class="flex items-center py-[32rpx] w-full">
|
||||||
<text class="text-[28rpx] text-[#999] font-normal">{{ item.rank }}</text>
|
<text class="text-[28rpx] text-[#999] font-normal">{{ item.rank }}</text>
|
||||||
|
|
@ -115,7 +115,7 @@ const navigatorBack = () => {
|
||||||
const tabIndex = ref<number>(0)
|
const tabIndex = ref<number>(0)
|
||||||
const tabsRef = ref(null)
|
const tabsRef = ref(null)
|
||||||
|
|
||||||
const itemClick = (item, index) => {
|
const itemClick = (item) => {
|
||||||
console.log('点击了', item)
|
console.log('点击了', item)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
<template></template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
onShow(() => {
|
|
||||||
uni.navigateBack()
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
@ -118,7 +118,7 @@ let editType = ''
|
||||||
let vTbId = ref(0)
|
let vTbId = ref(0)
|
||||||
let webUrl = computed(() => {
|
let webUrl = computed(() => {
|
||||||
if (vTbId.value !== 0) {
|
if (vTbId.value !== 0) {
|
||||||
return `http://localhost:3001/sort-college?id=${vTbId.value}&token=${userStore.userInfo.token}&score=${userStore.userInfo.estimatedAchievement.expectedScore}&batchName=${userStore.userInfo.batchName}&subjectGroup=${userStore.userInfo.estimatedAchievement.subjectGroup}&location=${userStore.userInfo.estimatedAchievement.provinceCode}`
|
return `https://sort.ycymedu.com/sort-college?id=${vTbId.value}&token=${userStore.userInfo.token}&score=${userStore.userInfo.estimatedAchievement.expectedScore}&batchName=${userStore.userInfo.batchName}&subjectGroup=${userStore.userInfo.estimatedAchievement.subjectGroup}&location=${userStore.userInfo.estimatedAchievement.provinceCode}`
|
||||||
}
|
}
|
||||||
return ''
|
return ''
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 8.9 KiB |
|
|
@ -1,3 +0,0 @@
|
||||||
<svg width="176" height="176" viewBox="0 0 176 176" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M8.31747 7.79883H79.1685V22.4068H8.31747V7.79883ZM97.1865 7.79883H138.205V22.4068H97.1865V7.79883ZM153.242 7.79883H168.147V22.7038H153.242V7.79883ZM8.31747 64.3498H79.1685V78.9688H8.31747V64.3498ZM7.85547 7.79883H22.4635V78.6498H7.85547V7.79883ZM64.5605 7.79883H79.1685V78.6498H64.5605V7.79883ZM32.5505 34.5178H52.4385V54.4058H32.5505V34.5178ZM97.1865 22.4068H111.409V37.3998H97.1865V22.4068ZM138.194 22.4068H153.792V49.9948H138.194V22.4068ZM153.242 37.3998H168.147V63.5028H153.242V37.3998ZM111.948 48.5868H138.205V67.3748H111.948V48.5868ZM126.644 63.4918H153.352V78.6388H126.644V63.4918ZM97.2745 63.9648H111.948V78.6388H97.2745V63.9648ZM7.85547 93.2908H22.4635V126.39H7.85547V93.2908ZM22.4965 123.277H38.3035V139.095H22.4965V123.277ZM7.85547 138.468H22.4965V168.212H7.85547V138.468ZM37.4125 93.2908H82.3915V111.463H37.4125V93.2908ZM48.3575 109.846H67.1235V127.116H48.3575V109.846ZM63.6255 123.277H82.3915V153.329H63.6255V123.277ZM49.0615 138.468H67.1235V168.212H49.0615V138.468ZM34.0245 149.38H51.5585V168.212H34.0245V149.38ZM108.142 93.2908H141.703V123.277H108.142V93.2908ZM149.733 93.2908H168.147V111.705H149.733V93.2908ZM93.6885 108.284H112.102V141.68H93.6885V108.284ZM123.179 119.075H141.703V138.303H123.179V119.075ZM93.6885 149.38H112.102V168.212H93.6885V149.38ZM137.985 153.329H168.147V168.212H137.985V153.329ZM153.066 138.303H168.147V156.475H153.066V138.303Z" fill="#272636"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 592 B |
|
|
@ -27,14 +27,14 @@
|
||||||
/>
|
/>
|
||||||
<text class="text-[#000] text-[36rpx] font-bold">{{ userStore.userInfo?.nickname }}</text>
|
<text class="text-[#000] text-[36rpx] font-bold">{{ userStore.userInfo?.nickname }}</text>
|
||||||
<image
|
<image
|
||||||
src="@/pages-sub/static/images/ucenter/vip-flag.png"
|
src="https://api.static.ycymedu.com/sub/images/ucenter/vip-flag.png"
|
||||||
mode="scaleToFill"
|
mode="scaleToFill"
|
||||||
class="w-[120rpx] h-[28rpx]"
|
class="w-[120rpx] h-[28rpx]"
|
||||||
v-if="isVIP"
|
v-if="isVIP"
|
||||||
/>
|
/>
|
||||||
<image
|
<image
|
||||||
v-else
|
v-else
|
||||||
src="@/pages-sub/static/images/ucenter/no-vip.png"
|
src="https://api.static.ycymedu.com/sub/images/ucenter/no-vip.png"
|
||||||
mode="scaleToFill"
|
mode="scaleToFill"
|
||||||
class="w-[120rpx] h-[28rpx]"
|
class="w-[120rpx] h-[28rpx]"
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,14 @@ const toDetail = (item: any) => {
|
||||||
url = `/pages-evaluation-sub/evaluate/academicReport/capabilityReport?id=${item.reportsId}&type=${item.type}`
|
url = `/pages-evaluation-sub/evaluate/academicReport/capabilityReport?id=${item.reportsId}&type=${item.type}`
|
||||||
} else if (item.type === -1) {
|
} else if (item.type === -1) {
|
||||||
url = `/pages-evaluation-sub/evaluate/academicReport/opinionAboutReport?id=${item.reportsId}&type=${item.type}`
|
url = `/pages-evaluation-sub/evaluate/academicReport/opinionAboutReport?id=${item.reportsId}&type=${item.type}`
|
||||||
|
} else if (item.type === 6) {
|
||||||
|
url = `/pages-evaluation-sub/evaluate/psychologicalReport/sasReport?id=${item.reportsId}&type=${item.type}`
|
||||||
|
} else {
|
||||||
|
uni.showToast({
|
||||||
|
title: '开发中....',
|
||||||
|
icon: 'none',
|
||||||
|
})
|
||||||
|
return
|
||||||
}
|
}
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url,
|
url,
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,10 @@
|
||||||
<view class="vip-table-header">
|
<view class="vip-table-header">
|
||||||
<view class="feature-column">功能</view>
|
<view class="feature-column">功能</view>
|
||||||
<view class="vip-column vip-header">
|
<view class="vip-column vip-header">
|
||||||
<image src="@/pages-sub/static/images/ucenter/vip-crown.png" class="vip-icon"></image>
|
<image
|
||||||
|
src="https://api.static.ycymedu.com/sub/images/ucenter/vip-crown.png"
|
||||||
|
class="vip-icon"
|
||||||
|
></image>
|
||||||
</view>
|
</view>
|
||||||
<view class="normal-column">普通用户</view>
|
<view class="normal-column">普通用户</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
<view class="h-screen flex flex-col bg-[#f8f8f8]">
|
<view class="h-screen flex flex-col bg-[#f8f8f8]">
|
||||||
<view class="px-[32rpx]">
|
<view class="px-[32rpx]">
|
||||||
<image
|
<image
|
||||||
src="@/pages-sub/static/images/ucenter/vip-back.png"
|
src="https://api.static.ycymedu.com/sub/images/ucenter/vip-back.png"
|
||||||
class="mt-[32rpx] h-[400rpx]"
|
class="mt-[32rpx] h-[400rpx]"
|
||||||
mode="aspectFit"
|
mode="aspectFit"
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { deleteWishList, getWishList } from '@/service/index/api'
|
import { deleteWishList, getWishList } from '@/service/index/api'
|
||||||
import { useUserStore } from '@/store'
|
import { useUserStore } from '@/store'
|
||||||
|
import { downloadPDF } from '@/service/index/api'
|
||||||
|
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
|
|
||||||
|
|
@ -65,16 +66,22 @@ const handleDelete = (item, index) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleDownload = (item) => {
|
const handleDownload = (item) => {
|
||||||
|
downloadPDF({
|
||||||
|
id: item.vId,
|
||||||
|
location: userStore.userInfo.estimatedAchievement.provinceCode,
|
||||||
|
}).then((res) => {
|
||||||
|
if (res.code === 200) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '下载中...',
|
||||||
|
})
|
||||||
uni.downloadFile({
|
uni.downloadFile({
|
||||||
url: '',
|
url: res.result as string,
|
||||||
|
filePath: '',
|
||||||
success: function (res) {
|
success: function (res) {
|
||||||
console.log(res)
|
if (res.statusCode === 200) {
|
||||||
let filepathss = res.tempFilePath
|
|
||||||
setTimeout(
|
|
||||||
() =>
|
|
||||||
uni.openDocument({
|
uni.openDocument({
|
||||||
filePath: filepathss,
|
filePath: res.tempFilePath,
|
||||||
showMenu: false,
|
showMenu: true,
|
||||||
success: function () {
|
success: function () {
|
||||||
console.log('打开文档成功')
|
console.log('打开文档成功')
|
||||||
uni.hideLoading()
|
uni.hideLoading()
|
||||||
|
|
@ -87,15 +94,16 @@ const handleDownload = (item) => {
|
||||||
})
|
})
|
||||||
uni.hideLoading()
|
uni.hideLoading()
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
1000,
|
}
|
||||||
)
|
|
||||||
},
|
},
|
||||||
fail: function (res) {
|
fail: function (res) {
|
||||||
console.log(res) //失败
|
console.log(res) //失败
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const toWishPage = (item: any) => {
|
const toWishPage = (item: any) => {
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,8 @@
|
||||||
"pages/home/index/index": {
|
"pages/home/index/index": {
|
||||||
"network": "all",
|
"network": "all",
|
||||||
"packages": [
|
"packages": [
|
||||||
"pages-evaluation-sub"
|
"pages-evaluation-sub",
|
||||||
|
"aiService-sub"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -185,10 +186,6 @@
|
||||||
"navigationStyle": "custom"
|
"navigationStyle": "custom"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "home/evaluation/index",
|
|
||||||
"type": "page"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "home/expand/index",
|
"path": "home/expand/index",
|
||||||
"type": "page",
|
"type": "page",
|
||||||
|
|
@ -254,10 +251,6 @@
|
||||||
"navigationBarTitleText": "我的志愿表"
|
"navigationBarTitleText": "我的志愿表"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "home/wishesList/temp",
|
|
||||||
"type": "page"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "home/wishesList/wishesList",
|
"path": "home/wishesList/wishesList",
|
||||||
"type": "page",
|
"type": "page",
|
||||||
|
|
@ -378,6 +371,13 @@
|
||||||
"style": {
|
"style": {
|
||||||
"navigationStyle": "custom"
|
"navigationStyle": "custom"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "evaluate/psychologicalReport/sasReport",
|
||||||
|
"type": "page",
|
||||||
|
"style": {
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
@ -388,8 +388,9 @@
|
||||||
"path": "index/index",
|
"path": "index/index",
|
||||||
"type": "page",
|
"type": "page",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "小纬"
|
"navigationBarTitleText": "六纬AI小助手"
|
||||||
}
|
},
|
||||||
|
"needLogin": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -61,9 +61,8 @@ import { useUserStore } from '@/store/user'
|
||||||
|
|
||||||
const list = ref<any[]>([])
|
const list = ref<any[]>([])
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
const show = ref(true)
|
|
||||||
|
|
||||||
onLoad(() => {
|
onShow(() => {
|
||||||
getMySpecialList({
|
getMySpecialList({
|
||||||
openId: userStore.userInfo?.estimatedAchievement.wxId.toString(),
|
openId: userStore.userInfo?.estimatedAchievement.wxId.toString(),
|
||||||
}).then((_res) => {
|
}).then((_res) => {
|
||||||
|
|
@ -94,6 +93,7 @@ const handleAppointment = (
|
||||||
deleteMyAppointment({ id: item.appointId }).then((res) => {
|
deleteMyAppointment({ id: item.appointId }).then((res) => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
list.value[index].isAppointment = !item.isAppointment
|
list.value[index].isAppointment = !item.isAppointment
|
||||||
|
delete list.value[index].appointId
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -105,6 +105,7 @@ const handleAppointment = (
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
list.value[index].isAppointment = !item.isAppointment
|
list.value[index].isAppointment = !item.isAppointment
|
||||||
|
list.value[index].appointId = res.result
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
title: item.isAppointment ? '预约成功' : '取消预约成功',
|
title: item.isAppointment ? '预约成功' : '取消预约成功',
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<scroll-view class="" :scroll-y="true">
|
<scroll-view class="flex flex-col" :scroll-y="true">
|
||||||
<view class="gradient-background relative">
|
<view class="relative">
|
||||||
<Navbar safeAreaInsetTop bg-color="transparent" placeholder :bordered="false">
|
<Navbar safeAreaInsetTop :fixed="true" bg-color="transparent" placeholder :bordered="false">
|
||||||
<template #left>
|
<template #left>
|
||||||
<navigator open-type="navigate" class="left-icon" url="/pages-sub/home/city/index">
|
<navigator open-type="navigate" class="left-icon" url="/pages-sub/home/city/index">
|
||||||
<text
|
<text
|
||||||
|
|
@ -15,13 +15,16 @@
|
||||||
</template>
|
</template>
|
||||||
<template #title>
|
<template #title>
|
||||||
<view class="title">
|
<view class="title">
|
||||||
<image class="w-[198rpx] h-[28rpx]" src="/static/images/home/app-logo.svg"></image>
|
<image
|
||||||
|
class="w-[198rpx] h-[28rpx]"
|
||||||
|
src="https://api.static.ycymedu.com/src/images/home/app-logo.svg"
|
||||||
|
></image>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
</Navbar>
|
</Navbar>
|
||||||
<view class="h-[700rpx] w-full custom-background absolute top-0 left-0 z-[-1]"></view>
|
<view class="h-[700rpx] w-full custom-background absolute top-0 left-0 z-[-1]"></view>
|
||||||
</view>
|
</view>
|
||||||
<view class="h-full mt-[48rpx]">
|
<view class="h-full mt-[38rpx]">
|
||||||
<Banner />
|
<Banner />
|
||||||
<HomeSubMenu />
|
<HomeSubMenu />
|
||||||
<HotRank />
|
<HotRank />
|
||||||
|
|
@ -44,22 +47,23 @@ import HotRank from '@/components/home/HotRank.vue'
|
||||||
import Consultation from '@/components/home/Consultation.vue'
|
import Consultation from '@/components/home/Consultation.vue'
|
||||||
import FabButton from '@/components/fab/FabButton.vue'
|
import FabButton from '@/components/fab/FabButton.vue'
|
||||||
|
|
||||||
|
import { getWxUserInfo } from '@/service/index/api'
|
||||||
|
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
|
|
||||||
useCityInfo()
|
useCityInfo()
|
||||||
|
|
||||||
// 当前下拉刷新状态
|
onShow(() => {
|
||||||
const isTriggered = ref(false)
|
getWxUserInfo().then((resp) => {
|
||||||
// 自定义下拉刷新被触发
|
const infoData = resp.result as unknown as {
|
||||||
const onRefresherRefresh = async () => {
|
userExtend: { provinceCode: string }
|
||||||
// 开始动画
|
|
||||||
isTriggered.value = true
|
|
||||||
setTimeout(function fn() {
|
|
||||||
console.log('refresh - onRefresherRefresh')
|
|
||||||
// 关闭动画
|
|
||||||
isTriggered.value = false
|
|
||||||
}, 1000)
|
|
||||||
}
|
}
|
||||||
|
if (userStore.userInfo.city.code === infoData.userExtend.provinceCode) {
|
||||||
|
userStore.setEstimatedAchievement(infoData.userExtend)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
@ -87,8 +91,8 @@ const onRefresherRefresh = async () => {
|
||||||
background-image: linear-gradient(
|
background-image: linear-gradient(
|
||||||
173deg,
|
173deg,
|
||||||
rgb(177, 221, 250) 0,
|
rgb(177, 221, 250) 0,
|
||||||
rgb(177, 221, 250) 13%,
|
rgb(177, 221, 250) 23%,
|
||||||
rgba(255, 255, 255, 1) 80%,
|
rgba(255, 255, 255, 1) 90%,
|
||||||
rgba(255, 255, 255, 1) 100%
|
rgba(255, 255, 255, 1) 100%
|
||||||
);
|
);
|
||||||
background-position: 50% 50%;
|
background-position: 50% 50%;
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@
|
||||||
v-if="!userStore.userInfo.estimatedAchievement.isVIP"
|
v-if="!userStore.userInfo.estimatedAchievement.isVIP"
|
||||||
>
|
>
|
||||||
<image
|
<image
|
||||||
src="/static/images/ucenter/vip.png"
|
src="https://api.static.ycymedu.com/src/images/ucenter/vip.png"
|
||||||
mode="scaleToFill"
|
mode="scaleToFill"
|
||||||
class="w-[64rpx] h-[64rpx]"
|
class="w-[64rpx] h-[64rpx]"
|
||||||
/>
|
/>
|
||||||
|
|
@ -53,7 +53,7 @@
|
||||||
>
|
>
|
||||||
<view class="flex flex-col items-center gap-[16rpx]" @click="goWishList">
|
<view class="flex flex-col items-center gap-[16rpx]" @click="goWishList">
|
||||||
<image
|
<image
|
||||||
src="/static/images/ucenter/wish-list.png"
|
src="https://api.static.ycymedu.com/src/images/ucenter/wish-list.png"
|
||||||
class="w-[51rpx] h-[51rpx]"
|
class="w-[51rpx] h-[51rpx]"
|
||||||
mode="scaleToFill"
|
mode="scaleToFill"
|
||||||
/>
|
/>
|
||||||
|
|
@ -61,7 +61,7 @@
|
||||||
</view>
|
</view>
|
||||||
<view class="flex flex-col items-center gap-[16rpx]" @click="goEvaluate">
|
<view class="flex flex-col items-center gap-[16rpx]" @click="goEvaluate">
|
||||||
<image
|
<image
|
||||||
src="/static/images/ucenter/evaluation-list.png"
|
src="https://api.static.ycymedu.com/src/images/ucenter/evaluation-list.png"
|
||||||
class="w-[51rpx] h-[51rpx]"
|
class="w-[51rpx] h-[51rpx]"
|
||||||
mode="scaleToFill"
|
mode="scaleToFill"
|
||||||
/>
|
/>
|
||||||
|
|
@ -69,7 +69,7 @@
|
||||||
</view>
|
</view>
|
||||||
<view class="flex flex-col items-center gap-[16rpx]" @click="goStar">
|
<view class="flex flex-col items-center gap-[16rpx]" @click="goStar">
|
||||||
<image
|
<image
|
||||||
src="/static/images/ucenter/star.png"
|
src="https://api.static.ycymedu.com/src/images/ucenter/star.png"
|
||||||
class="w-[51rpx] h-[51rpx]"
|
class="w-[51rpx] h-[51rpx]"
|
||||||
mode="scaleToFill"
|
mode="scaleToFill"
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -437,3 +437,7 @@ export const getAbilityDimension = (params: { ScaleId: number }) => {
|
||||||
export const getOpinionAbout = (params: { ScaleId: number }) => {
|
export const getOpinionAbout = (params: { ScaleId: number }) => {
|
||||||
return http.get('/api/busScale/GetOpinionAbout', params)
|
return http.get('/api/busScale/GetOpinionAbout', params)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const downloadPDF = (params: { id: number; location: string }) => {
|
||||||
|
return http.get('/api/volunTb/downloadpdfUrl', params)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 53 KiB |
|
|
@ -1,21 +0,0 @@
|
||||||
<svg width="99" height="16" viewBox="0 0 99 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M72.3668 0.5625H74.415V1.70659H80.4203V2.76068H74.415V4.68968H79.8098V5.74378H66.9503V4.68968H72.3668V2.76068H66.3199V1.70659H72.3668V0.5625ZM55.5289 0.607253H57.577V1.72869H62.8743V2.78278H57.577V4.17353H62.8743V5.22763H57.577V6.61839H61.0822C62.0867 6.61839 62.8942 7.53812 62.8942 8.68188V12.3831C62.8942 13.5269 62.0867 14.4466 61.0822 14.4466H59.0539V13.3699H59.4871C60.2355 13.3699 60.846 12.6745 60.846 11.8221V9.2429C60.846 8.39051 60.2355 7.69513 59.4871 7.69513H57.577V14.4466H55.5289V7.69513H51.5508L51.866 6.64074H55.5289V5.25028H51.7674V4.19588H55.5289V2.80542H51.5508V1.75103H55.5289V0.607253ZM37.7466 0.67452L38.3964 4.08409L36.2695 4.10643L35.6197 0.67452H37.7466ZM29.6914 5.00378H44.7369V6.05787H29.6914V5.00378ZM32.055 14.5364H29.7902L33.2366 6.9548H35.4817L32.055 14.5364ZM39.2812 6.9548L42.4126 14.514H44.6771L41.546 6.9548H39.2812ZM51.7276 13.5269H47.395V14.5813H51.7276V13.5269ZM51.7275 5.63163H50.467C50.1521 5.63163 49.9355 5.27261 50.0534 4.93625L51.5306 0.719274H49.4628L47.6312 6.01268C47.5132 6.34935 47.7298 6.70807 48.0448 6.70807H48.36C48.8128 6.70807 49.1476 7.22409 48.9705 7.71747L47.6116 11.9344C47.5132 12.2708 47.7099 12.6072 48.0252 12.6072H51.7275V11.5531H50.467C50.1521 11.5531 49.9355 11.1941 50.0534 10.8577L51.7275 5.63163ZM66.9321 7.42595H69.1576L67.9365 12.9887H65.6522L66.9321 7.42595ZM75.6362 11.2616H73.3911L72.4656 7.42595H74.75L75.6362 11.2616ZM78.1762 12.8543H80.4017L79.2989 7.42595H77.0145L78.1762 12.8543ZM70.5753 10.6562V7.42595H69.63V12.473C69.63 13.6167 70.4375 14.5365 71.4419 14.5365H75.3214C76.3259 14.5365 77.1331 13.6167 77.1331 12.473V10.8355H76.188C76.188 11.6879 75.5775 12.2036 74.8291 12.2036H71.9342C71.1859 12.2036 70.5753 11.5083 70.5753 10.6562ZM92.4536 3.99442H94.3637C94.8689 3.99442 95.3113 4.31135 95.5454 4.77947H89.3612C89.5954 4.31135 90.0378 3.99442 90.543 3.99442H92.4533V3.29878H92.4536V3.99442ZM89.3727 6.03556H95.534C95.297 6.49131 94.8608 6.79798 94.3637 6.79798H93.9305H90.543C90.0459 6.79798 89.6096 6.49131 89.3727 6.03556ZM93.1201 2.91767H95.9588C96.9632 2.91767 97.7707 3.83741 97.7707 4.98118V5.81122C97.7707 6.95499 96.9632 7.87472 95.9588 7.87472H94.5211H93.9305H91.5669H88.9479C87.9434 7.87472 87.1359 6.95499 87.1359 5.81122V4.98118C87.1359 3.83741 87.9434 2.91767 88.9479 2.91767H91.1713L91.3803 2.33438H86.4667V9.53428C86.4667 9.79143 86.4634 10.0411 86.4567 10.2833L88.5152 8.07666H90.465L88.1016 10.5888H86.4465C86.4369 10.8284 86.4239 11.0601 86.4076 11.2841C86.3681 11.8221 86.2697 12.4728 86.1515 12.8989L85.7774 13.5046C85.5609 13.8186 85.3048 14.0653 84.9503 14.2446C84.6155 14.4243 84.1823 14.514 83.6702 14.514H83.1779V12.5625H83.7097C83.8671 12.5625 83.9854 12.4952 84.0837 12.3381C84.1823 12.1811 84.2611 11.9791 84.3398 11.6878C84.3989 11.4184 84.458 11.0821 84.4777 10.7007C84.4973 10.3193 84.5169 9.89329 84.5169 9.42225V0.719274H86.4667V1.27999H98.5386V2.33438H93.2977L93.1201 2.91767ZM87.0569 11.2841H88.9869L87.9235 14.2446H85.974L87.0569 11.2841ZM91.8432 12.4502H93.7731L93.2217 10.8354H91.2719L91.8432 12.4502ZM96.215 10.5888L98.1253 10.6112L96.1363 8.07666H94.1669L96.215 10.5888ZM98.6169 14.2446H96.6869L95.722 11.2841H97.6715L98.6169 14.2446ZM90.032 10.8354V11.3511C90.032 12.0915 90.5442 12.6746 91.1939 12.6746H93.6952C94.3449 12.6746 94.8568 12.2485 94.8568 11.5082H95.6643V12.9213C95.6643 13.886 94.9751 14.6934 94.1087 14.6934H90.7804C89.9337 14.6934 89.2248 13.9083 89.2248 12.9213V10.8354H90.032ZM91.5669 7.91956V7.89692H93.5361C93.8118 9.87104 91.8228 10.5888 91.8228 10.5888L90.602 10.6111L90.6216 9.31003C91.7835 9.08598 91.5669 7.91956 91.5669 7.91956Z" fill="black"/>
|
|
||||||
<g clip-path="url(#clip0_8135_1215)">
|
|
||||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.8973 2.08927L17.2217 1.73129L15.1473 6.29709L15.5404 6.93331L18.0065 1.51976L19.2149 1.19433L16.1454 7.93727L16.5356 8.57511L19.9881 0.976294L21.2183 0.650862L17.1565 9.5807L17.551 10.2169L21.9929 0.437705L23.6147 0L17.6265 13.0579L13.6343 6.49235L15.8973 2.08927ZM12.4375 14.0277L14.5671 9.99887L17.1608 14.1026L16.4355 15.7444H13.3035L12.4375 14.0277Z" fill="url(#paint0_linear_8135_1215)"/>
|
|
||||||
<path d="M6.7194 2.08927L3.9211 8.59138L0 0L6.7194 2.08927Z" fill="#8ACEFF"/>
|
|
||||||
<path d="M3.89062 8.58122L6.71794 2.08887L10.6419 8.20697L3.89062 8.58122Z" fill="#76C1FF"/>
|
|
||||||
<path d="M3.89062 8.58128L7.18359 15.7408L10.6419 8.20703L3.89062 8.58128Z" fill="#5CA3FF"/>
|
|
||||||
<path d="M10.3789 15.744H7.1875L10.6444 8.20703L10.3789 15.744Z" fill="#3E91FF"/>
|
|
||||||
<path d="M10.3789 15.744L13.9707 9.02875L10.6444 8.20703L10.3789 15.744Z" fill="#2A80FF"/>
|
|
||||||
<path d="M12.8408 7.15918L13.9709 9.02878L10.6445 8.20707L12.8408 7.15918Z" fill="#5CA3FF"/>
|
|
||||||
</g>
|
|
||||||
<defs>
|
|
||||||
<linearGradient id="paint0_linear_8135_1215" x1="18.0268" y1="0" x2="18.0268" y2="15.7444" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#FFF5A7"/>
|
|
||||||
<stop offset="1" stop-color="#FB976D"/>
|
|
||||||
</linearGradient>
|
|
||||||
<clipPath id="clip0_8135_1215">
|
|
||||||
<rect width="23.6165" height="15.7444" fill="white"/>
|
|
||||||
</clipPath>
|
|
||||||
</defs>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 28 KiB |
|
|
@ -1,3 +0,0 @@
|
||||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M16.0875 5.2498C15.9375 5.0998 15.9375 4.8748 16.0875 4.7248L17.6813 3.13105C17.8313 2.98105 18.0562 2.98105 18.2062 3.13105L20.85 5.7748C21 5.9248 21 6.1498 20.85 6.2998L19.2562 7.89355C19.1062 8.04355 18.8813 8.04355 18.7313 7.89355L16.0875 5.2498ZM9 18.1873L17.7188 9.46855C17.85 9.3373 17.8313 9.1123 17.6813 8.98105L15.0375 6.31855C14.8875 6.16855 14.6625 6.1498 14.55 6.28105L5.8125 14.9998L4.5 19.4998L9 18.1873ZM1.5 20.9998V22.4998H22.5V20.9998H1.5Z" fill="black"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 586 B |
|
Before Width: | Height: | Size: 42 KiB |
|
|
@ -1,4 +0,0 @@
|
||||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<circle cx="10" cy="10" r="10" fill="#F8F8F8"/>
|
|
||||||
<path d="M9 7L12 10L9 13" stroke="#343434" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 260 B |
|
Before Width: | Height: | Size: 666 B |
|
Before Width: | Height: | Size: 835 B |
|
Before Width: | Height: | Size: 983 B |
|
Before Width: | Height: | Size: 829 B |
|
|
@ -104,6 +104,7 @@ export const useUserStore = defineStore(
|
||||||
requireSubject: { code: 0, name: '', simplename: '' },
|
requireSubject: { code: 0, name: '', simplename: '' },
|
||||||
optionalSubject: [],
|
optionalSubject: [],
|
||||||
provinceCode: '',
|
provinceCode: '',
|
||||||
|
subjectGroup: '',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@ interface NavigateToOptions {
|
||||||
"/pages-sub/home/college/index" |
|
"/pages-sub/home/college/index" |
|
||||||
"/pages-sub/home/college/info" |
|
"/pages-sub/home/college/info" |
|
||||||
"/pages-sub/home/distinguish/index" |
|
"/pages-sub/home/distinguish/index" |
|
||||||
"/pages-sub/home/evaluation/index" |
|
|
||||||
"/pages-sub/home/expand/index" |
|
"/pages-sub/home/expand/index" |
|
||||||
"/pages-sub/home/inputScore/index" |
|
"/pages-sub/home/inputScore/index" |
|
||||||
"/pages-sub/home/line/index" |
|
"/pages-sub/home/line/index" |
|
||||||
|
|
@ -28,7 +27,6 @@ interface NavigateToOptions {
|
||||||
"/pages-sub/home/news/newsList" |
|
"/pages-sub/home/news/newsList" |
|
||||||
"/pages-sub/home/schoolRank/index" |
|
"/pages-sub/home/schoolRank/index" |
|
||||||
"/pages-sub/home/wishesList/index" |
|
"/pages-sub/home/wishesList/index" |
|
||||||
"/pages-sub/home/wishesList/temp" |
|
|
||||||
"/pages-sub/home/wishesList/wishesList" |
|
"/pages-sub/home/wishesList/wishesList" |
|
||||||
"/pages-sub/ucenter/active/activePage" |
|
"/pages-sub/ucenter/active/activePage" |
|
||||||
"/pages-sub/ucenter/appointment/appointment" |
|
"/pages-sub/ucenter/appointment/appointment" |
|
||||||
|
|
@ -45,6 +43,7 @@ interface NavigateToOptions {
|
||||||
"/pages-evaluation-sub/evaluate/academicReport/characterReport" |
|
"/pages-evaluation-sub/evaluate/academicReport/characterReport" |
|
||||||
"/pages-evaluation-sub/evaluate/academicReport/interestReport" |
|
"/pages-evaluation-sub/evaluate/academicReport/interestReport" |
|
||||||
"/pages-evaluation-sub/evaluate/academicReport/opinionAboutReport" |
|
"/pages-evaluation-sub/evaluate/academicReport/opinionAboutReport" |
|
||||||
|
"/pages-evaluation-sub/evaluate/psychologicalReport/sasReport" |
|
||||||
"/aiService-sub/index/index";
|
"/aiService-sub/index/index";
|
||||||
}
|
}
|
||||||
interface RedirectToOptions extends NavigateToOptions {}
|
interface RedirectToOptions extends NavigateToOptions {}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
## 2.8.6(2025-03-17)
|
||||||
|
1.`新增` 聊天记录模式流式输出(类似chatGPT回答)演示demo。
|
||||||
|
2.`新增` z-paging及其公共子组件支持`HBuilderX`代码文档提示。
|
||||||
|
3.`新增` props:`virtual-in-swiper-slot`,用以解决vue3+(微信小程序或QQ小程序)中,使用非内置列表写法时,若z-paging在`swiper-item`中存在的无法获取slot插入的cell高度进而导致虚拟列表失败的问题。
|
||||||
|
4.`新增` `@scrolltolower`和@`scrolltoupper`支持nvue。
|
||||||
|
5.`修复` 由`v2.8.1`引出的方法`scrollIntoViewById`在微信小程序+vue3中无效的问题。
|
||||||
|
6.`修复` 由`v2.8.1`引出的在子组件内使用z-paging虚拟列表无效的问题。
|
||||||
|
7.`修复` 在微信小程序中基础库版本较高时`wx.getSystemInfoSync is deprecated`警告。
|
||||||
|
8.`优化` 提升下拉刷新在鸿蒙Next中的性能。
|
||||||
|
9.`优化` `@scrolltolower`和`@scrolltoupper`在倒置的聊天记录模式下的触发逻辑。
|
||||||
|
10.`优化` 其他细节调整。
|
||||||
|
## 2.8.5(2025-02-09)
|
||||||
|
1.`新增` 方法`scrollToX`,支持控制x轴滚动到指定位置。
|
||||||
|
2.`修复` 快手小程序中报错`await isn't allowed in non-async function`的问题。
|
||||||
|
3.`修复` 在iOS+nvue中,设置了`:loading-more-enabled="false"`后,调用`scrollToBottom`无法滚动到底部的问题。
|
||||||
|
4.`修复` 在支付宝小程序+页面滚动中,数据为空时空数据图未居中的问题。
|
||||||
|
5.`优化` fetch types修改。
|
||||||
|
## 2.8.4(2024-12-02)
|
||||||
|
1.`修复` 在虚拟列表+vue2中,顶部占位采用transformY方案;在虚拟列表+vue3中,顶部占位采用view占位方案。以解决在vue2+微信小程序+安卓+兼容模式中,可能出现的虚拟列表闪动的问题。
|
||||||
|
2.`修复` 在列表渲染时(尤其是在虚拟列表中)偶现的【点击加载更多】闪现的问题。
|
||||||
|
3.`优化` 统一在RefresherStatus枚举中Loading取值。
|
||||||
|
4.`优化` `defaultPageNo`&`defaultPageSize`修改为只允许number类型。
|
||||||
|
5.`优化` 提升兼容性&细节优化。
|
||||||
|
## 2.8.3(2024-11-27)
|
||||||
|
1.`修复` `doInsertVirtualListItem`插入数据无效的问题。
|
||||||
|
2.`优化` 提升兼容性&细节优化。
|
||||||
|
## 2.8.2(2024-11-25)
|
||||||
|
1.`优化` types中`ZPagingRef`和`ZPagingInstance`支持泛型。
|
||||||
|
## 2.8.1(2024-11-24)
|
||||||
|
1.`新增` 完整的`props`、`slots`、`methods`、`events`的typescript types声明,可在ts中获得绝佳的代码提示体验。
|
||||||
|
2.`新增` `virtual-cell-id-prefix`:虚拟列表cell id的前缀,适用于一个页面有多个虚拟列表的情况,用以区分不同虚拟列表cell的id。
|
||||||
|
3.`修复` 在vue3+(微信小程序或QQ小程序)中,使用非内置列表写法时,若`z-paging`在`swiper-item`标签内的情况下存在的无法获取slot插入的cell高度的问题。
|
||||||
|
4.`修复` 在虚拟列表中分页数据小于1页时插入新数据,虚拟列表未生效的问题。
|
||||||
|
5.`修复` 在虚拟列表中调用`refresh`时,cell的index计算不正确的问题。
|
||||||
|
6.`修复` 在快手小程序中内容较少或空数据时`z-paging`未能铺满全屏的问题。
|
||||||
|
7.`优化` `events`中的参数涉及枚举的部分,统一由之前的number类型修改为string类型,展示更直观!涉及的events:`@query`中的`from`参数;`@refresherStatusChange`中的`status`参数;`@loadingStatusChange`中的`status`参数;`slot=refresher`中的`refresherStatus`参数;`slot=chatLoading`中的`loadingMoreStatus`参数。更新版本请特别留意!
|
||||||
|
## 2.8.0(2024-10-21)
|
||||||
|
1.`新增` 全面支持鸿蒙Next。
|
||||||
|
2.`修复` 设置了`refresher-complete-delay`后,在下拉刷新期间调用reload导致的无法再次下拉刷新的问题。
|
||||||
|
3.`优化` 废弃虚拟列表transformY顶部占位方案,修改为空view占位。解决因使用旧方案导致的vue3中可能出现的虚拟列表闪动问题。提升虚拟列表的兼容性。
|
||||||
|
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
<!-- z-paging -->
|
||||||
|
<!-- github地址:https://github.com/SmileZXLee/uni-z-paging -->
|
||||||
|
<!-- dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935 -->
|
||||||
|
<!-- 反馈QQ群:790460711 -->
|
||||||
|
|
||||||
|
<!-- z-paging-cell,用于在nvue中使用cell包裹,vue中使用view包裹 -->
|
||||||
|
<template>
|
||||||
|
<!-- #ifdef APP-NVUE -->
|
||||||
|
<cell :style="[cellStyle]" @touchstart="onTouchstart">
|
||||||
|
<slot />
|
||||||
|
</cell>
|
||||||
|
<!-- #endif -->
|
||||||
|
<!-- #ifndef APP-NVUE -->
|
||||||
|
<view :style="[cellStyle]" @touchstart="onTouchstart">
|
||||||
|
<slot />
|
||||||
|
</view>
|
||||||
|
<!-- #endif -->
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
/**
|
||||||
|
* z-paging-cell 组件
|
||||||
|
* @description 用于兼容 nvue 和 vue 中的 cell 渲染。因为在 nvue 中 z-paging 内置的是 list,因此列表 item 必须使用 cell 包住;在 vue 中不能使用 cell,否则会报组件找不到的错误。此子组件为了兼容这两种情况,内部作了条件编译处理。
|
||||||
|
* @tutorial https://z-paging.zxlee.cn/api/sub-components/main.html#z-paging-cell配置
|
||||||
|
* @notice 以下为 z-paging-cell 的配置项
|
||||||
|
* @property {Object} cellStyle cell 样式,默认为 {}
|
||||||
|
* @example <z-paging-cell :cellStyle="{ backgroundColor: '#f0f0f0' }"></z-paging-cell>
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
name: "z-paging-cell",
|
||||||
|
props: {
|
||||||
|
//cellStyle
|
||||||
|
cellStyle: {
|
||||||
|
type: Object,
|
||||||
|
default: function() {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onTouchstart(e) {
|
||||||
|
this.$emit('touchstart', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
@ -0,0 +1,209 @@
|
||||||
|
<!-- z-paging -->
|
||||||
|
<!-- github地址:https://github.com/SmileZXLee/uni-z-paging -->
|
||||||
|
<!-- dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935 -->
|
||||||
|
<!-- 反馈QQ群:790460711 -->
|
||||||
|
|
||||||
|
<!-- 空数据占位view,此组件支持easycom规范,可以在项目中直接引用 -->
|
||||||
|
<template>
|
||||||
|
<view :class="{'zp-container':true,'zp-container-fixed':emptyViewFixed}" :style="[finalEmptyViewStyle]" @click="emptyViewClick">
|
||||||
|
<view class="zp-main">
|
||||||
|
<image v-if="!emptyViewImg.length" :class="{'zp-main-image-rpx':unit==='rpx','zp-main-image-px':unit==='px'}" :style="[emptyViewImgStyle]" :src="emptyImg" />
|
||||||
|
<image v-else :class="{'zp-main-image-rpx':unit==='rpx','zp-main-image-px':unit==='px'}" mode="aspectFit" :style="[emptyViewImgStyle]" :src="emptyViewImg" />
|
||||||
|
<text class="zp-main-title" :class="{'zp-main-title-rpx':unit==='rpx','zp-main-title-px':unit==='px'}" :style="[emptyViewTitleStyle]">{{emptyViewText}}</text>
|
||||||
|
<text v-if="showEmptyViewReload" :class="{'zp-main-error-btn':true,'zp-main-error-btn-rpx':unit==='rpx','zp-main-error-btn-px':unit==='px'}" :style="[emptyViewReloadStyle]" @click.stop="reloadClick">{{emptyViewReloadText}}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import zStatic from '../z-paging/js/z-paging-static'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* z-paging-empty-view 空数据组件
|
||||||
|
* @description 通用的 z-paging 空数据组件
|
||||||
|
* @tutorial https://z-paging.zxlee.cn/api/sub-components/main.html#z-paging-empty-view配置
|
||||||
|
* @property {Boolean} emptyViewFixed 空数据图片是否铺满 z-paging,默认为 false。若设置为 true,则为填充满 z-paging 的剩余部分
|
||||||
|
* @property {String} emptyViewText 空数据图描述文字,默认为 '没有数据哦~'
|
||||||
|
* @property {String} emptyViewImg 空数据图图片,默认使用 z-paging 内置的图片 (建议使用绝对路径,开头不要添加 "@",请以 "/" 开头)
|
||||||
|
* @property {String} emptyViewReloadText 空数据图点击重新加载文字,默认为 '重新加载'
|
||||||
|
* @property {Object} emptyViewStyle 空数据图样式,可设置空数据 view 的 top 等,如: empty-view-style="{'top':'100rpx'}" (如果空数据图不是 fixed 布局,则此处是 margin-top),默认为 {}
|
||||||
|
* @property {Object} emptyViewImgStyle 空数据图 img 样式,默认为 {}
|
||||||
|
* @property {Object} emptyViewTitleStyle 空数据图描述文字样式,默认为 {}
|
||||||
|
* @property {Object} emptyViewReloadStyle 空数据图重新加载按钮样式,默认为 {}
|
||||||
|
* @property {Boolean} showEmptyViewReload 是否显示空数据图重新加载按钮(无数据时),默认为 false
|
||||||
|
* @property {Boolean} isLoadFailed 是否是加载失败,默认为 false
|
||||||
|
* @property {String} unit 空数据图中布局的单位,默认为 'rpx'
|
||||||
|
* @event {Function} reload 点击了重新加载按钮
|
||||||
|
* @event {Function} viewClick 点击了空数据图 view
|
||||||
|
* @example <z-paging-empty-view empty-view-text="暂无数据" />
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
name: "z-paging-empty-view",
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
|
||||||
|
};
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
// 空数据描述文字
|
||||||
|
emptyViewText: {
|
||||||
|
type: String,
|
||||||
|
default: '没有数据哦~'
|
||||||
|
},
|
||||||
|
// 空数据图片
|
||||||
|
emptyViewImg: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
// 是否显示空数据图重新加载按钮
|
||||||
|
showEmptyViewReload: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
// 空数据点击重新加载文字
|
||||||
|
emptyViewReloadText: {
|
||||||
|
type: String,
|
||||||
|
default: '重新加载'
|
||||||
|
},
|
||||||
|
// 是否是加载失败
|
||||||
|
isLoadFailed: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
// 空数据图样式
|
||||||
|
emptyViewStyle: {
|
||||||
|
type: Object,
|
||||||
|
default: function() {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 空数据图img样式
|
||||||
|
emptyViewImgStyle: {
|
||||||
|
type: Object,
|
||||||
|
default: function() {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 空数据图描述文字样式
|
||||||
|
emptyViewTitleStyle: {
|
||||||
|
type: Object,
|
||||||
|
default: function() {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 空数据图重新加载按钮样式
|
||||||
|
emptyViewReloadStyle: {
|
||||||
|
type: Object,
|
||||||
|
default: function() {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 空数据图z-index
|
||||||
|
emptyViewZIndex: {
|
||||||
|
type: Number,
|
||||||
|
default: 9
|
||||||
|
},
|
||||||
|
// 空数据图片是否使用fixed布局并铺满z-paging
|
||||||
|
emptyViewFixed: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
// 空数据图中布局的单位,默认为rpx
|
||||||
|
unit: {
|
||||||
|
type: String,
|
||||||
|
default: 'rpx'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
emptyImg() {
|
||||||
|
return this.isLoadFailed ? zStatic.base64Error : zStatic.base64Empty;
|
||||||
|
},
|
||||||
|
finalEmptyViewStyle(){
|
||||||
|
this.emptyViewStyle['z-index'] = this.emptyViewZIndex;
|
||||||
|
return this.emptyViewStyle;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 点击了reload按钮
|
||||||
|
reloadClick() {
|
||||||
|
this.$emit('reload');
|
||||||
|
},
|
||||||
|
// 点击了空数据view
|
||||||
|
emptyViewClick() {
|
||||||
|
this.$emit('viewClick');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.zp-container{
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.zp-container-fixed {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
/* #endif */
|
||||||
|
/* #ifdef APP-NVUE */
|
||||||
|
flex: 1;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-main{
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
padding: 50rpx 0rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-main-image-rpx {
|
||||||
|
width: 240rpx;
|
||||||
|
height: 240rpx;
|
||||||
|
}
|
||||||
|
.zp-main-image-px {
|
||||||
|
width: 120px;
|
||||||
|
height: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-main-title {
|
||||||
|
color: #aaaaaa;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.zp-main-title-rpx {
|
||||||
|
font-size: 28rpx;
|
||||||
|
margin-top: 10rpx;
|
||||||
|
padding: 0rpx 20rpx;
|
||||||
|
}
|
||||||
|
.zp-main-title-px {
|
||||||
|
font-size: 14px;
|
||||||
|
margin-top: 5px;
|
||||||
|
padding: 0px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-main-error-btn {
|
||||||
|
border: solid 1px #dddddd;
|
||||||
|
color: #aaaaaa;
|
||||||
|
}
|
||||||
|
.zp-main-error-btn-rpx {
|
||||||
|
font-size: 28rpx;
|
||||||
|
padding: 8rpx 24rpx;
|
||||||
|
border-radius: 6rpx;
|
||||||
|
margin-top: 50rpx;
|
||||||
|
}
|
||||||
|
.zp-main-error-btn-px {
|
||||||
|
font-size: 14px;
|
||||||
|
padding: 4px 12px;
|
||||||
|
border-radius: 3px;
|
||||||
|
margin-top: 25px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,160 @@
|
||||||
|
<!-- z-paging -->
|
||||||
|
<!-- github地址:https://github.com/SmileZXLee/uni-z-paging -->
|
||||||
|
<!-- dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935 -->
|
||||||
|
<!-- 反馈QQ群:790460711 -->
|
||||||
|
|
||||||
|
<!-- 滑动切换选项卡swiper-item,此组件支持easycom规范,可以在项目中直接引用 -->
|
||||||
|
<template>
|
||||||
|
<view class="zp-swiper-item-container">
|
||||||
|
<z-paging ref="paging" :fixed="false"
|
||||||
|
:auto="false" :useVirtualList="useVirtualList" :useInnerList="useInnerList" :cellKeyName="cellKeyName" :innerListStyle="innerListStyle"
|
||||||
|
:preloadPage="preloadPage" :cellHeightMode="cellHeightMode" :virtualScrollFps="virtualScrollFps" :virtualListCol="virtualListCol"
|
||||||
|
@query="_queryList" @listChange="_updateList">
|
||||||
|
<slot />
|
||||||
|
<template #header>
|
||||||
|
<slot name="header"/>
|
||||||
|
</template>
|
||||||
|
<template #cell="{item,index}">
|
||||||
|
<slot name="cell" :item="item" :index="index"/>
|
||||||
|
</template>
|
||||||
|
<template #footer>
|
||||||
|
<slot name="footer"/>
|
||||||
|
</template>
|
||||||
|
</z-paging>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import zPaging from '../z-paging/z-paging'
|
||||||
|
/**
|
||||||
|
* z-paging-swiper-item 组件
|
||||||
|
* @description swiper+list极简写法中使用到,实际上就是对普通的swiper+list中swiper-item的包装封装,用以简化写法,但个性化配置局限较多
|
||||||
|
* @tutorial https://z-paging.zxlee.cn/api/sub-components/main.html#z-paging-swiper-item配置
|
||||||
|
* @notice 以下为 z-paging-swiper-item 的配置项
|
||||||
|
* @property {Number} tabIndex 当前组件的 index,也就是当前组件是 swiper 中的第几个,默认为 0
|
||||||
|
* @property {Number} currentIndex 当前 swiper 切换到第几个 index,默认为 0
|
||||||
|
* @property {Boolean} useVirtualList 是否使用虚拟列表,默认为 false
|
||||||
|
* @property {Boolean} useInnerList 是否在 z-paging 内部循环渲染列表(内置列表),默认为 false。若 useVirtualList 为 true,则此项恒为 true
|
||||||
|
* @property {String} cellKeyName 内置列表 cell 的 key 名称,仅 nvue 有效,在 nvue 中开启 useInnerList 时必须填此项,默认为 ''
|
||||||
|
* @property {Object} innerListStyle innerList 样式,默认为 {}
|
||||||
|
* @property {Number|String} preloadPage 预加载的列表可视范围(列表高度)页数,默认为 12。此数值越大,则虚拟列表中加载的 dom 越多,内存消耗越大(会维持在一个稳定值),但增加预加载页面数量可缓解快速滚动短暂白屏问题
|
||||||
|
* @property {String} cellHeightMode 虚拟列表 cell 高度模式,默认为 'fixed',也就是每个 cell 高度完全相同,将以第一个 cell 高度为准进行计算。可选值【dynamic】,即代表高度是动态非固定的,【dynamic】性能低于【fixed】
|
||||||
|
* @property {Number|String} virtualListCol 虚拟列表列数,默认为 1。常用于每行有多列的情况,例如每行有 2 列数据,需要将此值设置为 2
|
||||||
|
* @property {Number|String} virtualScrollFps 虚拟列表 scroll 取样帧率,默认为 60,过高可能出现卡顿等问题
|
||||||
|
* @example <z-paging-swiper-item ref="swiperItem" :tabIndex="index" :currentIndex="current" @query="queryList" @updateList="updateList"></z-paging-swiper-item>
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
name: "z-paging-swiper-item",
|
||||||
|
components: { zPaging },
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
firstLoaded: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
// 当前组件的index,也就是当前组件是swiper中的第几个
|
||||||
|
tabIndex: {
|
||||||
|
type: Number,
|
||||||
|
default: function() {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 当前swiper切换到第几个index
|
||||||
|
currentIndex: {
|
||||||
|
type: Number,
|
||||||
|
default: function() {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 是否使用虚拟列表,默认为否
|
||||||
|
useVirtualList: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
// 是否在z-paging内部循环渲染列表(内置列表),默认为否。若use-virtual-list为true,则此项恒为true
|
||||||
|
useInnerList: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
// 内置列表cell的key名称,仅nvue有效,在nvue中开启use-inner-list时必须填此项
|
||||||
|
cellKeyName: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
// innerList样式
|
||||||
|
innerListStyle: {
|
||||||
|
type: Object,
|
||||||
|
default: function() {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 预加载的列表可视范围(列表高度)页数,默认为12,即预加载当前页及上下各12页的cell。此数值越大,则虚拟列表中加载的dom越多,内存消耗越大(会维持在一个稳定值),但增加预加载页面数量可缓解快速滚动短暂白屏问题
|
||||||
|
preloadPage: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: 12
|
||||||
|
},
|
||||||
|
// 虚拟列表cell高度模式,默认为fixed,也就是每个cell高度完全相同,将以第一个cell高度为准进行计算。可选值【dynamic】,即代表高度是动态非固定的,【dynamic】性能低于【fixed】。
|
||||||
|
cellHeightMode: {
|
||||||
|
type: String,
|
||||||
|
default: 'fixed'
|
||||||
|
},
|
||||||
|
// 虚拟列表列数,默认为1。常用于每行有多列的情况,例如每行有2列数据,需要将此值设置为2
|
||||||
|
virtualListCol: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: 1
|
||||||
|
},
|
||||||
|
// 虚拟列表scroll取样帧率,默认为60,过高可能出现卡顿等问题
|
||||||
|
virtualScrollFps: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: 60
|
||||||
|
},
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
currentIndex: {
|
||||||
|
handler(newVal, oldVal) {
|
||||||
|
if (newVal === this.tabIndex) {
|
||||||
|
// 懒加载,当滑动到当前的item时,才去加载
|
||||||
|
if (!this.firstLoaded) {
|
||||||
|
this.$nextTick(()=>{
|
||||||
|
let delay = 5;
|
||||||
|
// #ifdef MP-TOUTIAO
|
||||||
|
delay = 100;
|
||||||
|
// #endif
|
||||||
|
setTimeout(() => {
|
||||||
|
this.$refs.paging.reload().catch(() => {});
|
||||||
|
}, delay);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
reload(data) {
|
||||||
|
return this.$refs.paging.reload(data);
|
||||||
|
},
|
||||||
|
complete(data) {
|
||||||
|
this.firstLoaded = true;
|
||||||
|
return this.$refs.paging.complete(data);
|
||||||
|
},
|
||||||
|
_queryList(pageNo, pageSize, from) {
|
||||||
|
this.$emit('query', pageNo, pageSize, from);
|
||||||
|
},
|
||||||
|
_updateList(list) {
|
||||||
|
this.$emit('updateList', list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.zp-swiper-item-container {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
height: 100%;
|
||||||
|
/* #endif */
|
||||||
|
/* #ifdef APP-NVUE */
|
||||||
|
flex: 1;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,176 @@
|
||||||
|
<!-- z-paging -->
|
||||||
|
<!-- github地址:https://github.com/SmileZXLee/uni-z-paging -->
|
||||||
|
<!-- dcloud地址:https://ext.dcloud.net.cn/plugin?id=3935 -->
|
||||||
|
<!-- 反馈QQ群:790460711 -->
|
||||||
|
|
||||||
|
<!-- 滑动切换选项卡swiper容器,此组件支持easycom规范,可以在项目中直接引用 -->
|
||||||
|
<template>
|
||||||
|
<view :class="fixed?'zp-swiper-container zp-swiper-container-fixed':'zp-swiper-container'" :style="[finalSwiperStyle]">
|
||||||
|
<!-- #ifndef APP-PLUS -->
|
||||||
|
<view v-if="cssSafeAreaInsetBottom===-1" class="zp-safe-area-inset-bottom"></view>
|
||||||
|
<!-- #endif -->
|
||||||
|
<slot v-if="zSlots.top" name="top" />
|
||||||
|
<view class="zp-swiper-super">
|
||||||
|
<view v-if="zSlots.left" :class="{'zp-swiper-left':true,'zp-absoulte':isOldWebView}">
|
||||||
|
<slot name="left" />
|
||||||
|
</view>
|
||||||
|
<view :class="{'zp-swiper':true,'zp-absoulte':isOldWebView}" :style="[swiperContentStyle]">
|
||||||
|
<slot />
|
||||||
|
</view>
|
||||||
|
<view v-if="zSlots.right" :class="{'zp-swiper-right':true,'zp-absoulte zp-right':isOldWebView}">
|
||||||
|
<slot name="right" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<slot v-if="zSlots.bottom" name="bottom" />
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import commonLayoutModule from '../z-paging/js/modules/common-layout'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* z-paging-swiper 组件
|
||||||
|
* @description 在 swiper 中使用 z-paging 时(左右滑动切换列表),在根节点使用 z-paging-swiper,其相当于一个 view 容器,默认铺满全屏,可免计算高度直接插入 swiper 的视图容器。
|
||||||
|
* @tutorial https://z-paging.zxlee.cn/api/sub-components/main.html#z-paging-swiper配置
|
||||||
|
* @property {Boolean} fixed 是否使用 fixed 布局,默认为 true
|
||||||
|
* @property {Boolean} safeAreaInsetBottom 是否开启底部安全区域适配,默认为 false
|
||||||
|
* @property {Object} swiperStyle z-paging-swiper 样式,默认为 {}
|
||||||
|
* @example <z-paging-swiper :safeAreaInsetBottom="true"></z-paging-swiper>
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
name: "z-paging-swiper",
|
||||||
|
mixins: [commonLayoutModule],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
swiperContentStyle: {}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
// 是否使用fixed布局,默认为是
|
||||||
|
fixed: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
// 是否开启底部安全区域适配
|
||||||
|
safeAreaInsetBottom: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
// z-paging-swiper样式
|
||||||
|
swiperStyle: {
|
||||||
|
type: Object,
|
||||||
|
default: function() {
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.systemInfo = this._getSystemInfoSync();
|
||||||
|
setTimeout(this.updateFixedLayout, 100)
|
||||||
|
})
|
||||||
|
// #ifndef APP-PLUS
|
||||||
|
this._getCssSafeAreaInsetBottom();
|
||||||
|
// #endif
|
||||||
|
this.updateLeftAndRightWidth();
|
||||||
|
|
||||||
|
this.swiperContentStyle = { 'flex': '1' };
|
||||||
|
// #ifndef APP-NVUE
|
||||||
|
this.swiperContentStyle = { width: '100%',height: '100%' };
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
finalSwiperStyle() {
|
||||||
|
const swiperStyle = { ...this.swiperStyle };
|
||||||
|
if (!this.systemInfo) return swiperStyle;
|
||||||
|
const windowTop = this.windowTop;
|
||||||
|
const windowBottom = this.systemInfo.windowBottom;
|
||||||
|
if (this.fixed) {
|
||||||
|
if (windowTop && !swiperStyle.top) {
|
||||||
|
swiperStyle.top = windowTop + 'px';
|
||||||
|
}
|
||||||
|
if (!swiperStyle.bottom) {
|
||||||
|
let bottom = windowBottom || 0;
|
||||||
|
bottom += this.safeAreaInsetBottom ? this.safeAreaBottom : 0;
|
||||||
|
if (bottom > 0) {
|
||||||
|
swiperStyle.bottom = bottom + 'px';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return swiperStyle;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 更新slot="left"和slot="right"宽度,当slot="left"或slot="right"宽度动态改变时调用
|
||||||
|
updateLeftAndRightWidth() {
|
||||||
|
if (!this.isOldWebView) return;
|
||||||
|
this.$nextTick(() => this._updateLeftAndRightWidth(this.swiperContentStyle, 'zp-swiper'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.zp-swiper-container {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-swiper-container-fixed {
|
||||||
|
position: fixed;
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
height: auto;
|
||||||
|
width: auto;
|
||||||
|
/* #endif */
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-safe-area-inset-bottom {
|
||||||
|
position: absolute;
|
||||||
|
/* #ifndef APP-PLUS */
|
||||||
|
height: env(safe-area-inset-bottom);
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-swiper-super {
|
||||||
|
flex: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-swiper-left,.zp-swiper-right{
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
height: 100%;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-swiper {
|
||||||
|
flex: 1;
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-absoulte {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
width: auto;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-swiper-item {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,182 @@
|
||||||
|
<!-- [z-paging]上拉加载更多view -->
|
||||||
|
<template>
|
||||||
|
<view class="zp-l-container" :class="{'zp-l-container-rpx':c.unit==='rpx','zp-l-container-px':c.unit==='px'}" :style="[c.customStyle]" @click="doClick">
|
||||||
|
<template v-if="!c.hideContent">
|
||||||
|
<!-- 底部加载更多没有更多数据分割线 -->
|
||||||
|
<text v-if="c.showNoMoreLine&&finalStatus===M.NoMore" :class="{'zp-l-line-rpx':c.unit==='rpx','zp-l-line-px':c.unit==='px'}" :style="[{backgroundColor:zTheme.line[ts]},c.noMoreLineCustomStyle]" />
|
||||||
|
<!-- 底部加载更多loading -->
|
||||||
|
<!-- #ifndef APP-NVUE -->
|
||||||
|
<image v-if="finalStatus===M.Loading&&!!c.loadingIconCustomImage"
|
||||||
|
:src="c.loadingIconCustomImage" :style="[c.iconCustomStyle]" :class="{'zp-l-line-loading-custom-image':true,'zp-l-line-loading-custom-image-animated':c.loadingAnimated,'zp-l-line-loading-custom-image-rpx':c.unit==='rpx','zp-l-line-loading-custom-image-px':c.unit==='px'}" />
|
||||||
|
<image v-if="finalStatus===M.Loading&&finalLoadingIconType==='flower'&&!c.loadingIconCustomImage.length"
|
||||||
|
:class="{'zp-line-loading-image':true,'zp-line-loading-image-rpx':c.unit==='rpx','zp-line-loading-image-px':c.unit==='px'}" :style="[c.iconCustomStyle]" :src="zTheme.flower[ts]" />
|
||||||
|
<!-- #endif -->
|
||||||
|
<!-- #ifdef APP-NVUE -->
|
||||||
|
<!-- 在nvue中底部加载更多loading使用系统自带的 -->
|
||||||
|
<view>
|
||||||
|
<loading-indicator v-if="finalStatus===M.Loading&&finalLoadingIconType!=='circle'" :class="{'zp-line-loading-image-rpx':c.unit==='rpx','zp-line-loading-image-px':c.unit==='px'}" :style="[{color:zTheme.indicator[ts]}]" :animating="true" />
|
||||||
|
</view>
|
||||||
|
<!-- #endif -->
|
||||||
|
<!-- 底部加载更多文字 -->
|
||||||
|
<text v-if="finalStatus===M.Loading&&finalLoadingIconType==='circle'&&!c.loadingIconCustomImage.length"
|
||||||
|
class="zp-l-circle-loading-view" :class="{'zp-l-circle-loading-view-rpx':c.unit==='rpx','zp-l-circle-loading-view-px':c.unit==='px'}" :style="[{borderColor:zTheme.circleBorder[ts],borderTopColor:zTheme.circleBorderTop[ts]},c.iconCustomStyle]" />
|
||||||
|
<text v-if="!c.isChat||(!c.chatDefaultAsLoading&&finalStatus===M.Default)||finalStatus===M.Fail" :class="{'zp-l-text-rpx':c.unit==='rpx','zp-l-text-px':c.unit==='px'}" :style="[{color:zTheme.title[ts]},c.titleCustomStyle]">{{ownLoadingMoreText}}</text>
|
||||||
|
<!-- 底部加载更多没有更多数据分割线 -->
|
||||||
|
<text v-if="c.showNoMoreLine&&finalStatus===M.NoMore" :class="{'zp-l-line-rpx':c.unit==='rpx','zp-l-line-px':c.unit==='px'}" :style="[{backgroundColor:zTheme.line[ts]},c.noMoreLineCustomStyle]" />
|
||||||
|
</template>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import zStatic from '../js/z-paging-static'
|
||||||
|
import Enum from '../js/z-paging-enum'
|
||||||
|
export default {
|
||||||
|
name: 'z-paging-load-more',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
M: Enum.More,
|
||||||
|
zTheme: {
|
||||||
|
title: { white: '#efefef', black: '#a4a4a4' },
|
||||||
|
line: { white: '#efefef', black: '#eeeeee' },
|
||||||
|
circleBorder: { white: '#aaaaaa', black: '#c8c8c8' },
|
||||||
|
circleBorderTop: { white: '#ffffff', black: '#444444' },
|
||||||
|
flower: { white: zStatic.base64FlowerWhite, black: zStatic.base64Flower },
|
||||||
|
indicator: { white: '#eeeeee', black: '#777777' }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
props: ['zConfig'],
|
||||||
|
computed: {
|
||||||
|
ts() {
|
||||||
|
return this.c.defaultThemeStyle;
|
||||||
|
},
|
||||||
|
// 底部加载更多配置
|
||||||
|
c() {
|
||||||
|
return this.zConfig || {};
|
||||||
|
},
|
||||||
|
// 底部加载更多文字
|
||||||
|
ownLoadingMoreText() {
|
||||||
|
return {
|
||||||
|
[this.M.Default]: this.c.defaultText,
|
||||||
|
[this.M.Loading]: this.c.loadingText,
|
||||||
|
[this.M.NoMore]: this.c.noMoreText,
|
||||||
|
[this.M.Fail]: this.c.failText,
|
||||||
|
}[this.finalStatus];
|
||||||
|
},
|
||||||
|
// 底部加载更多状态
|
||||||
|
finalStatus() {
|
||||||
|
if (this.c.defaultAsLoading && this.c.status === this.M.Default) return this.M.Loading;
|
||||||
|
return this.c.status;
|
||||||
|
},
|
||||||
|
// 加载更多icon类型
|
||||||
|
finalLoadingIconType() {
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
return 'flower';
|
||||||
|
// #endif
|
||||||
|
return this.c.loadingIconType;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 点击了加载更多
|
||||||
|
doClick() {
|
||||||
|
this.$emit('doClick');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
@import "../css/z-paging-static.css";
|
||||||
|
|
||||||
|
.zp-l-container {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
clear: both;
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.zp-l-container-rpx {
|
||||||
|
height: 80rpx;
|
||||||
|
font-size: 27rpx;
|
||||||
|
}
|
||||||
|
.zp-l-container-px {
|
||||||
|
height: 40px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-l-line-loading-custom-image {
|
||||||
|
color: #a4a4a4;
|
||||||
|
}
|
||||||
|
.zp-l-line-loading-custom-image-rpx {
|
||||||
|
margin-right: 8rpx;
|
||||||
|
width: 28rpx;
|
||||||
|
height: 28rpx;
|
||||||
|
}
|
||||||
|
.zp-l-line-loading-custom-image-px {
|
||||||
|
margin-right: 4px;
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-l-line-loading-custom-image-animated{
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
animation: loading-circle 1s linear infinite;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-l-circle-loading-view {
|
||||||
|
border: 3rpx solid #dddddd;
|
||||||
|
border-radius: 50%;
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
animation: loading-circle 1s linear infinite;
|
||||||
|
/* #endif */
|
||||||
|
/* #ifdef APP-NVUE */
|
||||||
|
width: 30rpx;
|
||||||
|
height: 30rpx;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
.zp-l-circle-loading-view-rpx {
|
||||||
|
margin-right: 8rpx;
|
||||||
|
width: 23rpx;
|
||||||
|
height: 23rpx;
|
||||||
|
}
|
||||||
|
.zp-l-circle-loading-view-px {
|
||||||
|
margin-right: 4px;
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-l-text-rpx {
|
||||||
|
font-size: 30rpx;
|
||||||
|
margin: 0rpx 6rpx;
|
||||||
|
}
|
||||||
|
.zp-l-text-px {
|
||||||
|
font-size: 15px;
|
||||||
|
margin: 0px 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-l-line-rpx {
|
||||||
|
height: 1px;
|
||||||
|
width: 100rpx;
|
||||||
|
margin: 0rpx 10rpx;
|
||||||
|
}
|
||||||
|
.zp-l-line-px {
|
||||||
|
height: 1px;
|
||||||
|
width: 50px;
|
||||||
|
margin: 0rpx 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
@keyframes loading-circle {
|
||||||
|
0% {
|
||||||
|
-webkit-transform: rotate(0deg);
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
-webkit-transform: rotate(360deg);
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* #endif */
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,214 @@
|
||||||
|
<!-- [z-paging]下拉刷新view -->
|
||||||
|
<template>
|
||||||
|
<view style="height: 100%;">
|
||||||
|
<view :class="showUpdateTime?'zp-r-container zp-r-container-padding':'zp-r-container'">
|
||||||
|
<view class="zp-r-left">
|
||||||
|
<!-- 非加载中(继续下拉刷新、松手立即刷新状态图片) -->
|
||||||
|
<image v-if="status!==R.Loading" :class="leftImageClass" :style="[leftImageStyle,imgStyle]" :src="leftImageSrc" />
|
||||||
|
<!-- 加载状态图片 -->
|
||||||
|
<!-- #ifndef APP-NVUE -->
|
||||||
|
<image v-else :class="{'zp-line-loading-image':refreshingAnimated,'zp-r-left-image':true,'zp-r-left-image-pre-size-rpx':unit==='rpx','zp-r-left-image-pre-size-px':unit==='px'}" :style="[leftImageStyle,imgStyle]" :src="leftImageSrc" />
|
||||||
|
<!-- #endif -->
|
||||||
|
<!-- 在nvue中,加载状态loading使用系统loading -->
|
||||||
|
<!-- #ifdef APP-NVUE -->
|
||||||
|
<view v-else :style="[{'margin-right':showUpdateTime?addUnit(18,unit):addUnit(12, unit)}]">
|
||||||
|
<loading-indicator :class="isIos?{'zp-loading-image-ios-rpx':unit==='rpx','zp-loading-image-ios-px':unit==='px'}:{'zp-loading-image-android-rpx':unit==='rpx','zp-loading-image-android-px':unit==='px'}"
|
||||||
|
:style="[{color:zTheme.indicator[ts]},imgStyle]" :animating="true" />
|
||||||
|
</view>
|
||||||
|
<!-- #endif -->
|
||||||
|
</view>
|
||||||
|
<!-- 右侧文字内容 -->
|
||||||
|
<view class="zp-r-right">
|
||||||
|
<!-- 右侧下拉刷新状态文字 -->
|
||||||
|
<text class="zp-r-right-text" :style="[rightTextStyle,titleStyle]">{{currentTitle}}</text>
|
||||||
|
<!-- 右侧下拉刷新时间文字 -->
|
||||||
|
<text v-if="showUpdateTime&&refresherTimeText.length" class="zp-r-right-text" :class="{'zp-r-right-time-text-rpx':unit==='rpx','zp-r-right-time-text-px':unit==='px'}" :style="[{color:zTheme.title[ts]},updateTimeStyle]">
|
||||||
|
{{refresherTimeText}}
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import zStatic from '../js/z-paging-static'
|
||||||
|
import u from '../js/z-paging-utils'
|
||||||
|
import Enum from '../js/z-paging-enum'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'z-paging-refresh',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
R: Enum.Refresher,
|
||||||
|
refresherTimeText: '',
|
||||||
|
zTheme: {
|
||||||
|
title: { white: '#efefef', black: '#555555' },
|
||||||
|
arrow: { white: zStatic.base64ArrowWhite, black: zStatic.base64Arrow },
|
||||||
|
flower: { white: zStatic.base64FlowerWhite, black: zStatic.base64Flower },
|
||||||
|
success: { white: zStatic.base64SuccessWhite, black: zStatic.base64Success },
|
||||||
|
indicator: { white: '#eeeeee', black: '#777777' }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
props: ['status', 'defaultThemeStyle', 'defaultText', 'pullingText', 'refreshingText', 'completeText', 'goF2Text', 'defaultImg', 'pullingImg',
|
||||||
|
'refreshingImg', 'completeImg', 'refreshingAnimated', 'showUpdateTime', 'updateTimeKey', 'imgStyle', 'titleStyle', 'updateTimeStyle', 'updateTimeTextMap', 'unit', 'isIos'
|
||||||
|
],
|
||||||
|
computed: {
|
||||||
|
ts() {
|
||||||
|
return this.defaultThemeStyle;
|
||||||
|
},
|
||||||
|
// 当前状态Map
|
||||||
|
statusTextMap() {
|
||||||
|
this.updateTime();
|
||||||
|
const { R, defaultText, pullingText, refreshingText, completeText, goF2Text } = this;
|
||||||
|
return {
|
||||||
|
[R.Default]: defaultText,
|
||||||
|
[R.ReleaseToRefresh]: pullingText,
|
||||||
|
[R.Loading]: refreshingText,
|
||||||
|
[R.Complete]: completeText,
|
||||||
|
[R.GoF2]: goF2Text,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
// 当前状态文字
|
||||||
|
currentTitle() {
|
||||||
|
return this.statusTextMap[this.status] || this.defaultText;
|
||||||
|
},
|
||||||
|
// 左侧图片class
|
||||||
|
leftImageClass() {
|
||||||
|
const preSizeClass = `zp-r-left-image-pre-size-${this.unit}`;
|
||||||
|
if (this.status === this.R.Complete) return preSizeClass;
|
||||||
|
return `zp-r-left-image ${preSizeClass} ${this.status === this.R.Default ? 'zp-r-arrow-down' : 'zp-r-arrow-top'}`;
|
||||||
|
},
|
||||||
|
// 左侧图片style
|
||||||
|
leftImageStyle() {
|
||||||
|
const showUpdateTime = this.showUpdateTime;
|
||||||
|
const size = showUpdateTime ? u.addUnit(36, this.unit) : u.addUnit(34, this.unit);
|
||||||
|
return {width: size,height: size,'margin-right': showUpdateTime ? u.addUnit(20, this.unit) : u.addUnit(9, this.unit)};
|
||||||
|
},
|
||||||
|
// 左侧图片src
|
||||||
|
leftImageSrc() {
|
||||||
|
const R = this.R;
|
||||||
|
const status = this.status;
|
||||||
|
if (status === R.Default) {
|
||||||
|
if (!!this.defaultImg) return this.defaultImg;
|
||||||
|
return this.zTheme.arrow[this.ts];
|
||||||
|
} else if (status === R.ReleaseToRefresh) {
|
||||||
|
if (!!this.pullingImg) return this.pullingImg;
|
||||||
|
if (!!this.defaultImg) return this.defaultImg;
|
||||||
|
return this.zTheme.arrow[this.ts];
|
||||||
|
} else if (status === R.Loading) {
|
||||||
|
if (!!this.refreshingImg) return this.refreshingImg;
|
||||||
|
return this.zTheme.flower[this.ts];;
|
||||||
|
} else if (status === R.Complete) {
|
||||||
|
if (!!this.completeImg) return this.completeImg;
|
||||||
|
return this.zTheme.success[this.ts];;
|
||||||
|
} else if (status === R.GoF2) {
|
||||||
|
return this.zTheme.arrow[this.ts];
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
},
|
||||||
|
// 右侧文字style
|
||||||
|
rightTextStyle() {
|
||||||
|
let stl = {};
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
const textHeight = this.showUpdateTime ? u.addUnit(40, this.unit) : u.addUnit(80, this.unit);
|
||||||
|
stl = {'height': textHeight, 'line-height': textHeight}
|
||||||
|
// #endif
|
||||||
|
stl['color'] = this.zTheme.title[this.ts];
|
||||||
|
stl['font-size'] = u.addUnit(30, this.unit);
|
||||||
|
return stl;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 添加单位
|
||||||
|
addUnit(value, unit) {
|
||||||
|
return u.addUnit(value, unit);
|
||||||
|
},
|
||||||
|
// 更新下拉刷新时间
|
||||||
|
updateTime() {
|
||||||
|
if (this.showUpdateTime) {
|
||||||
|
this.refresherTimeText = u.getRefesrherFormatTimeByKey(this.updateTimeKey, this.updateTimeTextMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
@import "../css/z-paging-static.css";
|
||||||
|
|
||||||
|
.zp-r-container {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-r-container-padding {
|
||||||
|
/* #ifdef APP-NVUE */
|
||||||
|
padding: 7px 0rpx;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-r-left {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
overflow: hidden;
|
||||||
|
/* #ifdef MP-ALIPAY */
|
||||||
|
margin-top: -4rpx;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-r-left-image {
|
||||||
|
transition-duration: .2s;
|
||||||
|
transition-property: transform;
|
||||||
|
color: #666666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-r-left-image-pre-size-rpx {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
width: 34rpx;
|
||||||
|
height: 34rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-r-left-image-pre-size-px {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
width: 17px;
|
||||||
|
height: 17px;
|
||||||
|
overflow: hidden;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-r-arrow-top {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-r-arrow-down {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-r-right {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-r-right-time-text-rpx {
|
||||||
|
margin-top: 10rpx;
|
||||||
|
font-size: 26rpx;
|
||||||
|
}
|
||||||
|
.zp-r-right-time-text-px {
|
||||||
|
margin-top: 5px;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
// z-paging全局配置文件,注意避免更新时此文件被覆盖,若被覆盖,可在此文件中右键->点击本地历史记录,找回覆盖前的配置
|
||||||
|
|
||||||
|
export default {}
|
||||||
|
|
@ -0,0 +1,241 @@
|
||||||
|
/* [z-paging]公共css*/
|
||||||
|
|
||||||
|
.z-paging-content {
|
||||||
|
position: relative;
|
||||||
|
flex-direction: column;
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
overflow: hidden;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
.z-paging-content-full {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
.z-paging-content-fixed, .zp-loading-fixed {
|
||||||
|
position: fixed;
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
height: auto;
|
||||||
|
width: auto;
|
||||||
|
/* #endif */
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-f2-content {
|
||||||
|
width: 100%;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-page-top, .zp-page-bottom {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
width: auto;
|
||||||
|
/* #endif */
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-page-left, .zp-page-right {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
height: 100%;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-scroll-view-super {
|
||||||
|
flex: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-view-super {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-scroll-view-container, .zp-scroll-view {
|
||||||
|
position: relative;
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-absoulte {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
width: auto;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-scroll-view-absolute {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
.zp-scroll-view-hide-scrollbar ::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
width: 0 !important;
|
||||||
|
height: 0 !important;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
/* #endif */
|
||||||
|
|
||||||
|
.zp-paging-touch-view {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-fixed-bac-view {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-paging-main {
|
||||||
|
height: 100%;
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-paging-container {
|
||||||
|
flex: 1;
|
||||||
|
position: relative;
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-chat-record-loading-custom-image {
|
||||||
|
width: 35rpx;
|
||||||
|
height: 35rpx;
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
animation: loading-flower 1s linear infinite;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-page-bottom-keyboard-placeholder-animate {
|
||||||
|
transition-property: height;
|
||||||
|
transition-duration: 0.15s;
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
will-change: height;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-custom-refresher-container {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-custom-refresher-refresh {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: block;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-back-to-top {
|
||||||
|
z-index: 999;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0rpx;
|
||||||
|
transition-duration: .3s;
|
||||||
|
transition-property: opacity;
|
||||||
|
}
|
||||||
|
.zp-back-to-top-rpx {
|
||||||
|
width: 76rpx;
|
||||||
|
height: 76rpx;
|
||||||
|
bottom: 0rpx;
|
||||||
|
right: 25rpx;
|
||||||
|
}
|
||||||
|
.zp-back-to-top-px {
|
||||||
|
width: 38px;
|
||||||
|
height: 38px;
|
||||||
|
bottom: 0px;
|
||||||
|
right: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-back-to-top-show {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-back-to-top-hide {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-back-to-top-img {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
/* #endif */
|
||||||
|
/* #ifdef APP-NVUE */
|
||||||
|
flex: 1;
|
||||||
|
/* #endif */
|
||||||
|
z-index: 999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-back-to-top-img-inversion {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-empty-view {
|
||||||
|
/* #ifdef APP-NVUE */
|
||||||
|
height: 100%;
|
||||||
|
/* #endif */
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-empty-view-center {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-loading-fixed {
|
||||||
|
z-index: 9999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-safe-area-inset-bottom {
|
||||||
|
position: absolute;
|
||||||
|
/* #ifndef APP-PLUS */
|
||||||
|
height: env(safe-area-inset-bottom);
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-n-refresh-container {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
justify-content: center;
|
||||||
|
width: 750rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-n-list-container{
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: row;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
/* [z-paging]公用的静态css资源 */
|
||||||
|
|
||||||
|
.zp-line-loading-image {
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
animation: loading-flower 1s steps(12) infinite;
|
||||||
|
/* #endif */
|
||||||
|
color: #666666;
|
||||||
|
}
|
||||||
|
.zp-line-loading-image-rpx {
|
||||||
|
margin-right: 8rpx;
|
||||||
|
width: 34rpx;
|
||||||
|
height: 34rpx;
|
||||||
|
}
|
||||||
|
.zp-line-loading-image-px {
|
||||||
|
margin-right: 4px;
|
||||||
|
width: 17px;
|
||||||
|
height: 17px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-loading-image-ios-rpx {
|
||||||
|
width: 40rpx;
|
||||||
|
height: 40rpx;
|
||||||
|
}
|
||||||
|
.zp-loading-image-ios-px {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zp-loading-image-android-rpx {
|
||||||
|
width: 34rpx;
|
||||||
|
height: 34rpx;
|
||||||
|
}
|
||||||
|
.zp-loading-image-android-px {
|
||||||
|
width: 17px;
|
||||||
|
height: 17px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
@keyframes loading-flower {
|
||||||
|
0% {
|
||||||
|
-webkit-transform: rotate(0deg);
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
-webkit-transform: rotate(1turn);
|
||||||
|
transform: rotate(1turn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* #endif */
|
||||||
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
{
|
||||||
|
"zp.refresher.default": "Pull down to refresh",
|
||||||
|
"zp.refresher.pulling": "Release to refresh",
|
||||||
|
"zp.refresher.refreshing": "Refreshing...",
|
||||||
|
"zp.refresher.complete": "Refresh succeeded",
|
||||||
|
"zp.refresher.f2": "Refresh to enter 2f",
|
||||||
|
|
||||||
|
"zp.loadingMore.default": "Click to load more",
|
||||||
|
"zp.loadingMore.loading": "Loading...",
|
||||||
|
"zp.loadingMore.noMore": "No more data",
|
||||||
|
"zp.loadingMore.fail": "Load failed,click to reload",
|
||||||
|
|
||||||
|
"zp.emptyView.title": "No data",
|
||||||
|
"zp.emptyView.reload": "Reload",
|
||||||
|
"zp.emptyView.error": "Sorry,load failed",
|
||||||
|
|
||||||
|
"zp.refresherUpdateTime.title": "Last update: ",
|
||||||
|
"zp.refresherUpdateTime.none": "None",
|
||||||
|
"zp.refresherUpdateTime.today": "Today",
|
||||||
|
"zp.refresherUpdateTime.yesterday": "Yesterday",
|
||||||
|
|
||||||
|
"zp.systemLoading.title": "Loading..."
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
import en from './en.json'
|
||||||
|
import zhHans from './zh-Hans.json'
|
||||||
|
import zhHant from './zh-Hant.json'
|
||||||
|
export default {
|
||||||
|
en,
|
||||||
|
'zh-Hans': zhHans,
|
||||||
|
'zh-Hant': zhHant
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
{
|
||||||
|
"zp.refresher.default": "继续下拉刷新",
|
||||||
|
"zp.refresher.pulling": "松开立即刷新",
|
||||||
|
"zp.refresher.refreshing": "正在刷新...",
|
||||||
|
"zp.refresher.complete": "刷新成功",
|
||||||
|
"zp.refresher.f2": "松手进入二楼",
|
||||||
|
|
||||||
|
"zp.loadingMore.default": "点击加载更多",
|
||||||
|
"zp.loadingMore.loading": "正在加载...",
|
||||||
|
"zp.loadingMore.noMore": "没有更多了",
|
||||||
|
"zp.loadingMore.fail": "加载失败,点击重新加载",
|
||||||
|
|
||||||
|
"zp.emptyView.title": "没有数据哦~",
|
||||||
|
"zp.emptyView.reload": "重新加载",
|
||||||
|
"zp.emptyView.error": "很抱歉,加载失败",
|
||||||
|
|
||||||
|
"zp.refresherUpdateTime.title": "最后更新:",
|
||||||
|
"zp.refresherUpdateTime.none": "无",
|
||||||
|
"zp.refresherUpdateTime.today": "今天",
|
||||||
|
"zp.refresherUpdateTime.yesterday": "昨天",
|
||||||
|
|
||||||
|
"zp.systemLoading.title": "加载中..."
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
{
|
||||||
|
"zp.refresher.default": "繼續下拉重繪",
|
||||||
|
"zp.refresher.pulling": "鬆開立即重繪",
|
||||||
|
"zp.refresher.refreshing": "正在重繪...",
|
||||||
|
"zp.refresher.complete": "重繪成功",
|
||||||
|
"zp.refresher.f2": "鬆手進入二樓",
|
||||||
|
|
||||||
|
"zp.loadingMore.default": "點擊加載更多",
|
||||||
|
"zp.loadingMore.loading": "正在加載...",
|
||||||
|
"zp.loadingMore.noMore": "沒有更多了",
|
||||||
|
"zp.loadingMore.fail": "加載失敗,點擊重新加載",
|
||||||
|
|
||||||
|
"zp.emptyView.title": "沒有數據哦~",
|
||||||
|
"zp.emptyView.reload": "重新加載",
|
||||||
|
"zp.emptyView.error": "很抱歉,加載失敗",
|
||||||
|
|
||||||
|
"zp.refresherUpdateTime.title": "最後更新:",
|
||||||
|
"zp.refresherUpdateTime.none": "無",
|
||||||
|
"zp.refresherUpdateTime.today": "今天",
|
||||||
|
"zp.refresherUpdateTime.yesterday": "昨天",
|
||||||
|
|
||||||
|
"zp.systemLoading.title": "加載中..."
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
// [z-paging]useZPaging hooks
|
||||||
|
|
||||||
|
import { onPageScroll, onReachBottom, onPullDownRefresh } from '@dcloudio/uni-app';
|
||||||
|
|
||||||
|
function useZPaging(paging) {
|
||||||
|
const cPaging = !!paging ? paging.value || paging : null;
|
||||||
|
|
||||||
|
onPullDownRefresh(() => {
|
||||||
|
if (!cPaging || !cPaging.value) return;
|
||||||
|
cPaging.value.reload().catch(() => {});
|
||||||
|
})
|
||||||
|
|
||||||
|
onPageScroll(e => {
|
||||||
|
if (!cPaging || !cPaging.value) return;
|
||||||
|
cPaging.value.updatePageScrollTop(e.scrollTop);
|
||||||
|
e.scrollTop < 10 && cPaging.value.doChatRecordLoadMore();
|
||||||
|
})
|
||||||
|
|
||||||
|
onReachBottom(() => {
|
||||||
|
if (!cPaging || !cPaging.value) return;
|
||||||
|
cPaging.value.pageReachBottom();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useZPaging
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
// [z-paging]useZPagingComp hooks
|
||||||
|
|
||||||
|
function useZPagingComp(paging) {
|
||||||
|
const cPaging = !!paging ? paging.value || paging : null;
|
||||||
|
|
||||||
|
const reload = () => {
|
||||||
|
if (!cPaging || !cPaging.value) return;
|
||||||
|
cPaging.value.reload().catch(() => {});
|
||||||
|
}
|
||||||
|
const updatePageScrollTop = scrollTop => {
|
||||||
|
if (!cPaging || !cPaging.value) return;
|
||||||
|
cPaging.value.updatePageScrollTop(scrollTop);
|
||||||
|
}
|
||||||
|
const doChatRecordLoadMore = () => {
|
||||||
|
if (!cPaging || !cPaging.value) return;
|
||||||
|
cPaging.value.doChatRecordLoadMore();
|
||||||
|
}
|
||||||
|
const pageReachBottom = () => {
|
||||||
|
if (!cPaging || !cPaging.value) return;
|
||||||
|
cPaging.value.pageReachBottom();
|
||||||
|
}
|
||||||
|
return { reload, updatePageScrollTop, doChatRecordLoadMore, pageReachBottom };
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useZPagingComp
|
||||||
|
|
@ -0,0 +1,125 @@
|
||||||
|
// [z-paging]点击返回顶部view模块
|
||||||
|
import u from '.././z-paging-utils'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
// 自动显示点击返回顶部按钮,默认为否
|
||||||
|
autoShowBackToTop: {
|
||||||
|
type: Boolean,
|
||||||
|
default: u.gc('autoShowBackToTop', false)
|
||||||
|
},
|
||||||
|
// 点击返回顶部按钮显示/隐藏的阈值(滚动距离),单位为px,默认为400rpx
|
||||||
|
backToTopThreshold: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: u.gc('backToTopThreshold', '400rpx')
|
||||||
|
},
|
||||||
|
// 点击返回顶部按钮的自定义图片地址,默认使用z-paging内置的图片
|
||||||
|
backToTopImg: {
|
||||||
|
type: String,
|
||||||
|
default: u.gc('backToTopImg', '')
|
||||||
|
},
|
||||||
|
// 点击返回顶部按钮返回到顶部时是否展示过渡动画,默认为是
|
||||||
|
backToTopWithAnimate: {
|
||||||
|
type: Boolean,
|
||||||
|
default: u.gc('backToTopWithAnimate', true)
|
||||||
|
},
|
||||||
|
// 点击返回顶部按钮与底部的距离,注意添加单位px或rpx,默认为160rpx
|
||||||
|
backToTopBottom: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: u.gc('backToTopBottom', '160rpx')
|
||||||
|
},
|
||||||
|
// 点击返回顶部按钮的自定义样式
|
||||||
|
backToTopStyle: {
|
||||||
|
type: Object,
|
||||||
|
default: u.gc('backToTopStyle', {}),
|
||||||
|
},
|
||||||
|
// iOS点击顶部状态栏、安卓双击标题栏时,滚动条返回顶部,只支持竖向,默认为是
|
||||||
|
enableBackToTop: {
|
||||||
|
type: Boolean,
|
||||||
|
default: u.gc('enableBackToTop', true)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 点击返回顶部的class
|
||||||
|
backToTopClass: 'zp-back-to-top zp-back-to-top-hide',
|
||||||
|
// 上次点击返回顶部的时间
|
||||||
|
lastBackToTopShowTime: 0,
|
||||||
|
// 点击返回顶部显示的class是否在展示中,使得按钮展示/隐藏过度效果更自然
|
||||||
|
showBackToTopClass: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
backToTopThresholdUnitConverted() {
|
||||||
|
return u.addUnit(this.backToTopThreshold, this.unit);
|
||||||
|
},
|
||||||
|
backToTopBottomUnitConverted() {
|
||||||
|
return u.addUnit(this.backToTopBottom, this.unit);
|
||||||
|
},
|
||||||
|
finalEnableBackToTop() {
|
||||||
|
return this.usePageScroll ? false : this.enableBackToTop;
|
||||||
|
},
|
||||||
|
finalBackToTopThreshold() {
|
||||||
|
return u.convertToPx(this.backToTopThresholdUnitConverted);
|
||||||
|
},
|
||||||
|
finalBackToTopStyle() {
|
||||||
|
const backToTopStyle = this.backToTopStyle;
|
||||||
|
if (!backToTopStyle.bottom) {
|
||||||
|
backToTopStyle.bottom = this.windowBottom + u.convertToPx(this.backToTopBottomUnitConverted) + 'px';
|
||||||
|
}
|
||||||
|
if(!backToTopStyle.position){
|
||||||
|
backToTopStyle.position = this.usePageScroll ? 'fixed': 'absolute';
|
||||||
|
}
|
||||||
|
return backToTopStyle;
|
||||||
|
},
|
||||||
|
finalBackToTopClass() {
|
||||||
|
return `${this.backToTopClass} zp-back-to-top-${this.unit}`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 点击了返回顶部
|
||||||
|
_backToTopClick() {
|
||||||
|
let callbacked = false;
|
||||||
|
this.$emit('backToTopClick', toTop => {
|
||||||
|
(toTop === undefined || toTop === true) && this._handleToTop();
|
||||||
|
callbacked = true;
|
||||||
|
});
|
||||||
|
// 如果用户没有禁止默认的返回顶部事件,则触发滚动到顶部
|
||||||
|
this.$nextTick(() => {
|
||||||
|
!callbacked && this._handleToTop();
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 处理滚动到顶部(聊天记录模式中为滚动到底部)
|
||||||
|
_handleToTop() {
|
||||||
|
!this.backToTopWithAnimate && this._checkShouldShowBackToTop(0);
|
||||||
|
!this.useChatRecordMode ? this.scrollToTop(this.backToTopWithAnimate) : this.scrollToBottom(this.backToTopWithAnimate);
|
||||||
|
},
|
||||||
|
// 判断是否要显示返回顶部按钮
|
||||||
|
_checkShouldShowBackToTop(scrollTop) {
|
||||||
|
if (!this.autoShowBackToTop) {
|
||||||
|
this.showBackToTopClass = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (scrollTop > this.finalBackToTopThreshold) {
|
||||||
|
if (!this.showBackToTopClass) {
|
||||||
|
// 记录当前点击返回顶部按钮显示的class生效了
|
||||||
|
this.showBackToTopClass = true;
|
||||||
|
this.lastBackToTopShowTime = new Date().getTime();
|
||||||
|
// 当滚动到需要展示返回顶部的阈值内,则延迟300毫秒展示返回到顶部按钮
|
||||||
|
u.delay(() => {
|
||||||
|
this.backToTopClass = 'zp-back-to-top zp-back-to-top-show';
|
||||||
|
}, 300)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 如果当前点击返回顶部按钮显示的class是生效状态并且滚动小于触发阈值,则隐藏返回顶部按钮
|
||||||
|
if (this.showBackToTopClass) {
|
||||||
|
this.backToTopClass = 'zp-back-to-top zp-back-to-top-hide';
|
||||||
|
u.delay(() => {
|
||||||
|
this.showBackToTopClass = false;
|
||||||
|
}, new Date().getTime() - this.lastBackToTopShowTime < 500 ? 0 : 300)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,149 @@
|
||||||
|
// [z-paging]聊天记录模式模块
|
||||||
|
import u from '.././z-paging-utils'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
// 使用聊天记录模式,默认为否
|
||||||
|
useChatRecordMode: {
|
||||||
|
type: Boolean,
|
||||||
|
default: u.gc('useChatRecordMode', false)
|
||||||
|
},
|
||||||
|
// 使用聊天记录模式时滚动到顶部后,列表垂直移动偏移距离。默认0rpx。单位px(暂时无效)
|
||||||
|
chatRecordMoreOffset: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: u.gc('chatRecordMoreOffset', '0rpx')
|
||||||
|
},
|
||||||
|
// 使用聊天记录模式时是否自动隐藏键盘:在用户触摸列表时候自动隐藏键盘,默认为是
|
||||||
|
autoHideKeyboardWhenChat: {
|
||||||
|
type: Boolean,
|
||||||
|
default: u.gc('autoHideKeyboardWhenChat', true)
|
||||||
|
},
|
||||||
|
// 使用聊天记录模式中键盘弹出时是否自动调整slot="bottom"高度,默认为是
|
||||||
|
autoAdjustPositionWhenChat: {
|
||||||
|
type: Boolean,
|
||||||
|
default: u.gc('autoAdjustPositionWhenChat', true)
|
||||||
|
},
|
||||||
|
// 使用聊天记录模式中键盘弹出时占位高度偏移距离。默认0rpx。单位px
|
||||||
|
chatAdjustPositionOffset: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: u.gc('chatAdjustPositionOffset', '0rpx')
|
||||||
|
},
|
||||||
|
// 使用聊天记录模式中键盘弹出时是否自动滚动到底部,默认为否
|
||||||
|
autoToBottomWhenChat: {
|
||||||
|
type: Boolean,
|
||||||
|
default: u.gc('autoToBottomWhenChat', false)
|
||||||
|
},
|
||||||
|
// 使用聊天记录模式中reload时是否显示chatLoading,默认为否
|
||||||
|
showChatLoadingWhenReload: {
|
||||||
|
type: Boolean,
|
||||||
|
default: u.gc('showChatLoadingWhenReload', false)
|
||||||
|
},
|
||||||
|
// 在聊天记录模式中滑动到顶部状态为默认状态时,以加载中的状态展示,默认为是。若设置为否,则默认会显示【点击加载更多】,然后才会显示loading
|
||||||
|
chatLoadingMoreDefaultAsLoading: {
|
||||||
|
type: Boolean,
|
||||||
|
default: u.gc('chatLoadingMoreDefaultAsLoading', true)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 键盘高度
|
||||||
|
keyboardHeight: 0,
|
||||||
|
// 键盘高度是否未改变,此时占位高度变化不需要动画效果
|
||||||
|
isKeyboardHeightChanged: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
finalChatRecordMoreOffset() {
|
||||||
|
return u.convertToPx(this.chatRecordMoreOffset);
|
||||||
|
},
|
||||||
|
finalChatAdjustPositionOffset() {
|
||||||
|
return u.convertToPx(this.chatAdjustPositionOffset);
|
||||||
|
},
|
||||||
|
// 聊天记录模式旋转180度style
|
||||||
|
chatRecordRotateStyle() {
|
||||||
|
let cellStyle;
|
||||||
|
// 在vue中,直接将列表倒置,因此在vue的cell中,也直接写style="transform: scaleY(-1)"转回来即可。
|
||||||
|
// #ifndef APP-NVUE
|
||||||
|
cellStyle = this.useChatRecordMode ? { transform: 'scaleY(-1)' } : {};
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// 在nvue中,需要考虑数据量不满一页的情况,因为nvue中的list无法通过flex-end修改不满一页的起始位置,会导致不满一页时列表数据从底部开始,因此需要特别判断
|
||||||
|
// 当数据不满一屏的时候,不进行列表倒置
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
cellStyle = this.useChatRecordMode ? { transform: this.isFirstPageAndNoMore ? 'scaleY(1)' : 'scaleY(-1)' } : {};
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
this.$emit('update:cellStyle', cellStyle);
|
||||||
|
this.$emit('cellStyleChange', cellStyle);
|
||||||
|
|
||||||
|
// 在聊天记录模式中,如果列表没有倒置并且当前是第一页,则需要自动滚动到最底部
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (this.isFirstPage && this.isChatRecordModeAndNotInversion) {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
// 这里多次触发滚动到底部是为了避免在某些情况下,即使是在nextTick但是cell未渲染完毕导致滚动到底部位置不正确的问题
|
||||||
|
this._scrollToBottom(false);
|
||||||
|
u.delay(() => {
|
||||||
|
this._scrollToBottom(false);
|
||||||
|
u.delay(() => {
|
||||||
|
this._scrollToBottom(false);
|
||||||
|
}, 50)
|
||||||
|
}, 50)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return cellStyle;
|
||||||
|
},
|
||||||
|
// 是否是聊天记录列表并且有配置transform
|
||||||
|
isChatRecordModeHasTransform() {
|
||||||
|
return this.useChatRecordMode && this.chatRecordRotateStyle && this.chatRecordRotateStyle.transform;
|
||||||
|
},
|
||||||
|
// 是否是聊天记录列表并且列表未倒置
|
||||||
|
isChatRecordModeAndNotInversion() {
|
||||||
|
return this.isChatRecordModeHasTransform && this.chatRecordRotateStyle.transform === 'scaleY(1)';
|
||||||
|
},
|
||||||
|
// 是否是聊天记录列表并且列表倒置
|
||||||
|
isChatRecordModeAndInversion() {
|
||||||
|
return this.isChatRecordModeHasTransform && this.chatRecordRotateStyle.transform === 'scaleY(-1)';
|
||||||
|
},
|
||||||
|
// 最终的聊天记录模式中底部安全区域的高度,如果开启了底部安全区域并且键盘未弹出,则添加底部区域高度
|
||||||
|
chatRecordModeSafeAreaBottom() {
|
||||||
|
return this.safeAreaInsetBottom && !this.keyboardHeight ? this.safeAreaBottom : 0;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
// 监听键盘高度变化(H5、百度小程序、抖音小程序、飞书小程序不支持)
|
||||||
|
// #ifndef H5 || MP-BAIDU || MP-TOUTIAO
|
||||||
|
if (this.useChatRecordMode) {
|
||||||
|
uni.onKeyboardHeightChange(this._handleKeyboardHeightChange);
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 添加聊天记录
|
||||||
|
addChatRecordData(data, toBottom = true, toBottomWithAnimate = true) {
|
||||||
|
if (!this.useChatRecordMode) return;
|
||||||
|
this.isTotalChangeFromAddData = true;
|
||||||
|
this.addDataFromTop(data, toBottom, toBottomWithAnimate);
|
||||||
|
},
|
||||||
|
// 手动触发滚动到顶部加载更多,聊天记录模式时有效
|
||||||
|
doChatRecordLoadMore() {
|
||||||
|
this.useChatRecordMode && this._onLoadingMore('click');
|
||||||
|
},
|
||||||
|
// 处理键盘高度变化
|
||||||
|
_handleKeyboardHeightChange(res) {
|
||||||
|
this.$emit('keyboardHeightChange', res);
|
||||||
|
if (this.autoAdjustPositionWhenChat) {
|
||||||
|
this.isKeyboardHeightChanged = true;
|
||||||
|
this.keyboardHeight = res.height > 0 ? res.height + this.finalChatAdjustPositionOffset : res.height;
|
||||||
|
}
|
||||||
|
if (this.autoToBottomWhenChat && this.keyboardHeight > 0) {
|
||||||
|
u.delay(() => {
|
||||||
|
this.scrollToBottom(false);
|
||||||
|
u.delay(() => {
|
||||||
|
this.scrollToBottom(false);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,152 @@
|
||||||
|
// [z-paging]通用布局相关模块
|
||||||
|
import u from '.././z-paging-utils'
|
||||||
|
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
const weexDom = weex.requireModule('dom');
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
systemInfo: null,
|
||||||
|
cssSafeAreaInsetBottom: -1,
|
||||||
|
isReadyDestroy: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
// 顶部可用距离
|
||||||
|
windowTop() {
|
||||||
|
if (!this.systemInfo) return 0;
|
||||||
|
// 暂时修复vue3中隐藏系统导航栏后windowTop获取不正确的问题,具体bug详见https://ask.dcloud.net.cn/question/141634
|
||||||
|
// 感谢litangyu!!https://github.com/SmileZXLee/uni-z-paging/issues/25
|
||||||
|
// #ifdef VUE3 && H5
|
||||||
|
const pageHeadNode = document.getElementsByTagName("uni-page-head");
|
||||||
|
if (!pageHeadNode.length) return 0;
|
||||||
|
// #endif
|
||||||
|
return this.systemInfo.windowTop || 0;
|
||||||
|
},
|
||||||
|
// 底部安全区域高度
|
||||||
|
safeAreaBottom() {
|
||||||
|
if (!this.systemInfo) return 0;
|
||||||
|
let safeAreaBottom = 0;
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
safeAreaBottom = this.systemInfo.safeAreaInsets.bottom || 0 ;
|
||||||
|
// #endif
|
||||||
|
// #ifndef APP-PLUS
|
||||||
|
safeAreaBottom = Math.max(this.cssSafeAreaInsetBottom, 0);
|
||||||
|
// #endif
|
||||||
|
return safeAreaBottom;
|
||||||
|
},
|
||||||
|
// 是否是比较老的webview,在一些老的webview中,需要进行一些特殊处理
|
||||||
|
isOldWebView() {
|
||||||
|
// #ifndef APP-NVUE || MP-KUAISHOU
|
||||||
|
try {
|
||||||
|
const systemInfos = u.getSystemInfoSync(true).system.split(' ');
|
||||||
|
const deviceType = systemInfos[0];
|
||||||
|
const version = parseInt(systemInfos[1]);
|
||||||
|
if ((deviceType === 'iOS' && version <= 10) || (deviceType === 'Android' && version <= 6)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
// 当前组件的$slots,兼容不同平台
|
||||||
|
zSlots() {
|
||||||
|
// #ifdef VUE2
|
||||||
|
|
||||||
|
// #ifdef MP-ALIPAY
|
||||||
|
return this.$slots;
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
return this.$scopedSlots || this.$slots;
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
return this.$slots;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
this.isReadyDestroy = true;
|
||||||
|
},
|
||||||
|
// #ifdef VUE3
|
||||||
|
unmounted() {
|
||||||
|
this.isReadyDestroy = true;
|
||||||
|
},
|
||||||
|
// #endif
|
||||||
|
methods: {
|
||||||
|
// 更新fixed模式下z-paging的布局
|
||||||
|
updateFixedLayout() {
|
||||||
|
this.fixed && this.$nextTick(() => {
|
||||||
|
this.systemInfo = u.getSystemInfoSync();
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 获取节点尺寸
|
||||||
|
_getNodeClientRect(select, inDom = true, scrollOffset = false) {
|
||||||
|
if (this.isReadyDestroy) {
|
||||||
|
return Promise.resolve(false);
|
||||||
|
};
|
||||||
|
// nvue中获取节点信息
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
select = select.replace(/[.|#]/g, '');
|
||||||
|
const ref = this.$refs[select];
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (ref) {
|
||||||
|
weexDom.getComponentRect(ref, option => {
|
||||||
|
resolve(option && option.result ? [option.size] : false);
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
resolve(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// vue中获取节点信息
|
||||||
|
//#ifdef MP-ALIPAY
|
||||||
|
inDom = false;
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
inDom可能是true、false,也可能是具体的dom节点
|
||||||
|
如果inDom不为false,则使用uni.createSelectorQuery().in()进行查询,如果inDom为true,则in中的是this,否则in中的为具体的dom
|
||||||
|
如果inDom为false,则使用uni.createSelectorQuery()进行查询
|
||||||
|
*/
|
||||||
|
let res = !!inDom ? uni.createSelectorQuery().in(inDom === true ? this : inDom) : uni.createSelectorQuery();
|
||||||
|
scrollOffset ? res.select(select).scrollOffset() : res.select(select).boundingClientRect();
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
res.exec(data => {
|
||||||
|
resolve((data && data != '' && data != undefined && data.length) ? data : false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 获取slot="left"和slot="right"宽度并且更新布局
|
||||||
|
_updateLeftAndRightWidth(targetStyle, parentNodePrefix) {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
let delayTime = 0;
|
||||||
|
// #ifdef MP-BAIDU
|
||||||
|
delayTime = 10;
|
||||||
|
// #endif
|
||||||
|
setTimeout(() => {
|
||||||
|
['left','right'].map(position => {
|
||||||
|
this._getNodeClientRect(`.${parentNodePrefix}-${position}`).then(res => {
|
||||||
|
this.$set(targetStyle, position, res ? res[0].width + 'px' : '0px');
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}, delayTime)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 通过获取css设置的底部安全区域占位view高度设置bottom距离(直接通过systemInfo在部分平台上无法获取到底部安全区域)
|
||||||
|
_getCssSafeAreaInsetBottom(success) {
|
||||||
|
this._getNodeClientRect('.zp-safe-area-inset-bottom').then(res => {
|
||||||
|
this.cssSafeAreaInsetBottom = res ? res[0].height : -1;
|
||||||
|
res && success && success();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 同步获取系统信息,兼容不同平台(供z-paging-swiper使用)
|
||||||
|
_getSystemInfoSync(useCache = false) {
|
||||||
|
return u.getSystemInfoSync(useCache);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,736 @@
|
||||||
|
// [z-paging]数据处理模块
|
||||||
|
import u from '.././z-paging-utils'
|
||||||
|
import c from '.././z-paging-constant'
|
||||||
|
import Enum from '.././z-paging-enum'
|
||||||
|
import interceptor from '../z-paging-interceptor'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
// 自定义初始的pageNo,默认为1
|
||||||
|
defaultPageNo: {
|
||||||
|
type: Number,
|
||||||
|
default: u.gc('defaultPageNo', 1),
|
||||||
|
observer: function(newVal) {
|
||||||
|
this.pageNo = newVal;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// 自定义pageSize,默认为10
|
||||||
|
defaultPageSize: {
|
||||||
|
type: Number,
|
||||||
|
default: u.gc('defaultPageSize', 10),
|
||||||
|
validator: (value) => {
|
||||||
|
if (value <= 0) u.consoleErr('default-page-size必须大于0!');
|
||||||
|
return value > 0;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 为保证数据一致,设置当前tab切换时的标识key,并在complete中传递相同key,若二者不一致,则complete将不会生效
|
||||||
|
dataKey: {
|
||||||
|
type: [Number, String, Object],
|
||||||
|
default: u.gc('dataKey', null),
|
||||||
|
},
|
||||||
|
// 使用缓存,若开启将自动缓存第一页的数据,默认为否。请注意,因考虑到切换tab时不同tab数据不同的情况,默认仅会缓存组件首次加载时第一次请求到的数据,后续的下拉刷新操作不会更新缓存。
|
||||||
|
useCache: {
|
||||||
|
type: Boolean,
|
||||||
|
default: u.gc('useCache', false)
|
||||||
|
},
|
||||||
|
// 使用缓存时缓存的key,用于区分不同列表的缓存数据,useCache为true时必须设置,否则缓存无效
|
||||||
|
cacheKey: {
|
||||||
|
type: String,
|
||||||
|
default: u.gc('cacheKey', null)
|
||||||
|
},
|
||||||
|
// 缓存模式,默认仅会缓存组件首次加载时第一次请求到的数据,可设置为always,即代表总是缓存,每次列表刷新(下拉刷新、调用reload等)都会更新缓存
|
||||||
|
cacheMode: {
|
||||||
|
type: String,
|
||||||
|
default: u.gc('cacheMode', Enum.CacheMode.Default)
|
||||||
|
},
|
||||||
|
// 自动注入的list名,可自动修改父view(包含ref="paging")中对应name的list值
|
||||||
|
autowireListName: {
|
||||||
|
type: String,
|
||||||
|
default: u.gc('autowireListName', '')
|
||||||
|
},
|
||||||
|
// 自动注入的query名,可自动调用父view(包含ref="paging")中的query方法
|
||||||
|
autowireQueryName: {
|
||||||
|
type: String,
|
||||||
|
default: u.gc('autowireQueryName', '')
|
||||||
|
},
|
||||||
|
// 获取分页数据Function,功能与@query类似。若设置了fetch则@query将不再触发
|
||||||
|
fetch: {
|
||||||
|
type: Function,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
// fetch的附加参数,fetch配置后有效
|
||||||
|
fetchParams: {
|
||||||
|
type: Object,
|
||||||
|
default: u.gc('fetchParams', null)
|
||||||
|
},
|
||||||
|
// z-paging mounted后自动调用reload方法(mounted后自动调用接口),默认为是
|
||||||
|
auto: {
|
||||||
|
type: Boolean,
|
||||||
|
default: u.gc('auto', true)
|
||||||
|
},
|
||||||
|
// 用户下拉刷新时是否触发reload方法,默认为是
|
||||||
|
reloadWhenRefresh: {
|
||||||
|
type: Boolean,
|
||||||
|
default: u.gc('reloadWhenRefresh', true)
|
||||||
|
},
|
||||||
|
// reload时自动滚动到顶部,默认为是
|
||||||
|
autoScrollToTopWhenReload: {
|
||||||
|
type: Boolean,
|
||||||
|
default: u.gc('autoScrollToTopWhenReload', true)
|
||||||
|
},
|
||||||
|
// reload时立即自动清空原list,默认为是,若立即自动清空,则在reload之后、请求回调之前页面是空白的
|
||||||
|
autoCleanListWhenReload: {
|
||||||
|
type: Boolean,
|
||||||
|
default: u.gc('autoCleanListWhenReload', true)
|
||||||
|
},
|
||||||
|
// 列表刷新时自动显示下拉刷新view,默认为否
|
||||||
|
showRefresherWhenReload: {
|
||||||
|
type: Boolean,
|
||||||
|
default: u.gc('showRefresherWhenReload', false)
|
||||||
|
},
|
||||||
|
// 列表刷新时自动显示加载更多view,且为加载中状态,默认为否
|
||||||
|
showLoadingMoreWhenReload: {
|
||||||
|
type: Boolean,
|
||||||
|
default: u.gc('showLoadingMoreWhenReload', false)
|
||||||
|
},
|
||||||
|
// 组件created时立即触发reload(可解决一些情况下先看到页面再看到loading的问题),auto为true时有效。为否时将在mounted+nextTick后触发reload,默认为否
|
||||||
|
createdReload: {
|
||||||
|
type: Boolean,
|
||||||
|
default: u.gc('createdReload', false)
|
||||||
|
},
|
||||||
|
// 本地分页时上拉加载更多延迟时间,单位为毫秒,默认200毫秒
|
||||||
|
localPagingLoadingTime: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: u.gc('localPagingLoadingTime', 200)
|
||||||
|
},
|
||||||
|
// 自动拼接complete中传过来的数组(使用聊天记录模式时无效)
|
||||||
|
concat: {
|
||||||
|
type: Boolean,
|
||||||
|
default: u.gc('concat', true)
|
||||||
|
},
|
||||||
|
// 请求失败是否触发reject,默认为是
|
||||||
|
callNetworkReject: {
|
||||||
|
type: Boolean,
|
||||||
|
default: u.gc('callNetworkReject', true)
|
||||||
|
},
|
||||||
|
// 父组件v-model所绑定的list的值
|
||||||
|
value: {
|
||||||
|
type: Array,
|
||||||
|
default: function() {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// #ifdef VUE3
|
||||||
|
modelValue: {
|
||||||
|
type: Array,
|
||||||
|
default: function() {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
data (){
|
||||||
|
return {
|
||||||
|
currentData: [],
|
||||||
|
totalData: [],
|
||||||
|
realTotalData: [],
|
||||||
|
totalLocalPagingList: [],
|
||||||
|
dataPromiseResultMap: {
|
||||||
|
reload: null,
|
||||||
|
complete: null,
|
||||||
|
localPaging: null
|
||||||
|
},
|
||||||
|
isSettingCacheList: false,
|
||||||
|
pageNo: 1,
|
||||||
|
currentRefreshPageSize: 0,
|
||||||
|
isLocalPaging: false,
|
||||||
|
isAddedData: false,
|
||||||
|
isTotalChangeFromAddData: false,
|
||||||
|
privateConcat: true,
|
||||||
|
myParentQuery: -1,
|
||||||
|
firstPageLoaded: false,
|
||||||
|
pagingLoaded: false,
|
||||||
|
loaded: false,
|
||||||
|
isUserReload: true,
|
||||||
|
fromEmptyViewReload: false,
|
||||||
|
queryFrom: '',
|
||||||
|
listRendering: false,
|
||||||
|
isHandlingRefreshToPage: false,
|
||||||
|
isFirstPageAndNoMore: false,
|
||||||
|
totalDataChangeThrow: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
pageSize() {
|
||||||
|
return this.defaultPageSize;
|
||||||
|
},
|
||||||
|
finalConcat() {
|
||||||
|
return this.concat && this.privateConcat;
|
||||||
|
},
|
||||||
|
finalUseCache() {
|
||||||
|
if (this.useCache && !this.cacheKey) {
|
||||||
|
u.consoleErr('use-cache为true时,必须设置cache-key,否则缓存无效!');
|
||||||
|
}
|
||||||
|
return this.useCache && !!this.cacheKey;
|
||||||
|
},
|
||||||
|
finalCacheKey() {
|
||||||
|
return this.cacheKey ? `${c.cachePrefixKey}-${this.cacheKey}` : null;
|
||||||
|
},
|
||||||
|
isFirstPage() {
|
||||||
|
return this.pageNo === this.defaultPageNo;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
totalData(newVal, oldVal) {
|
||||||
|
this._totalDataChange(newVal, oldVal, this.totalDataChangeThrow);
|
||||||
|
this.totalDataChangeThrow = true;
|
||||||
|
},
|
||||||
|
currentData(newVal, oldVal) {
|
||||||
|
this._currentDataChange(newVal, oldVal);
|
||||||
|
},
|
||||||
|
useChatRecordMode(newVal, oldVal) {
|
||||||
|
if (newVal) {
|
||||||
|
this.nLoadingMoreFixedHeight = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
handler(newVal) {
|
||||||
|
// 当v-model绑定的数据源被更改时,此时数据源改变不emit input事件,避免循环调用
|
||||||
|
if (newVal !== this.totalData) {
|
||||||
|
this.totalDataChangeThrow = false;
|
||||||
|
this.totalData = newVal;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
},
|
||||||
|
// #ifdef VUE3
|
||||||
|
modelValue: {
|
||||||
|
handler(newVal) {
|
||||||
|
// 当v-model绑定的数据源被更改时,此时数据源改变不emit input事件,避免循环调用
|
||||||
|
if (newVal !== this.totalData) {
|
||||||
|
this.totalDataChangeThrow = false;
|
||||||
|
this.totalData = newVal;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 请求结束(成功或者失败)调用此方法,将请求的结果传递给z-paging处理,第一个参数为请求结果数组,第二个参数为是否成功(默认为是)
|
||||||
|
complete(data, success = true) {
|
||||||
|
this.customNoMore = -1;
|
||||||
|
return this.addData(data, success);
|
||||||
|
},
|
||||||
|
//【保证数据一致】请求结束(成功或者失败)调用此方法,将请求的结果传递给z-paging处理,第一个参数为请求结果数组,第二个参数为dataKey,需与:data-key绑定的一致,第三个参数为是否成功(默认为是)
|
||||||
|
completeByKey(data, dataKey = null, success = true) {
|
||||||
|
if (dataKey !== null && this.dataKey !== null && dataKey !== this.dataKey) {
|
||||||
|
this.isFirstPage && this.endRefresh();
|
||||||
|
return new Promise(resolve => resolve());
|
||||||
|
}
|
||||||
|
this.customNoMore = -1;
|
||||||
|
return this.addData(data, success);
|
||||||
|
},
|
||||||
|
//【通过total判断是否有更多数据】请求结束(成功或者失败)调用此方法,将请求的结果传递给z-paging处理,第一个参数为请求结果数组,第二个参数为total(列表总数),第三个参数为是否成功(默认为是)
|
||||||
|
completeByTotal(data, total, success = true) {
|
||||||
|
if (total == 'undefined') {
|
||||||
|
this.customNoMore = -1;
|
||||||
|
} else {
|
||||||
|
const dataTypeRes = this._checkDataType(data, success, false);
|
||||||
|
data = dataTypeRes.data;
|
||||||
|
success = dataTypeRes.success;
|
||||||
|
if (total >= 0 && success) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
let nomore = false;
|
||||||
|
const realTotalDataCount = this.pageNo == this.defaultPageNo ? 0 : this.realTotalData.length;
|
||||||
|
const dataLength = this.privateConcat ? data.length : 0;
|
||||||
|
let exceedCount = realTotalDataCount + dataLength - total;
|
||||||
|
// 没有更多数据了
|
||||||
|
if (exceedCount >= 0) {
|
||||||
|
nomore = true;
|
||||||
|
// 仅截取total内部分的数据
|
||||||
|
exceedCount = this.defaultPageSize - exceedCount;
|
||||||
|
if (this.privateConcat && exceedCount > 0 && exceedCount < data.length) {
|
||||||
|
data = data.splice(0, exceedCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.completeByNoMore(data, nomore, success).then(res => resolve(res)).catch(() => reject());
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this.addData(data, success);
|
||||||
|
},
|
||||||
|
//【自行判断是否有更多数据】请求结束(成功或者失败)调用此方法,将请求的结果传递给z-paging处理,第一个参数为请求结果数组,第二个参数为是否没有更多数据,第三个参数为是否成功(默认是是)
|
||||||
|
completeByNoMore(data, nomore, success = true) {
|
||||||
|
if (nomore != 'undefined') {
|
||||||
|
this.customNoMore = nomore == true ? 1 : 0;
|
||||||
|
}
|
||||||
|
return this.addData(data, success);
|
||||||
|
},
|
||||||
|
// 请求结束且请求失败时调用,支持传入请求失败原因
|
||||||
|
completeByError(errorMsg) {
|
||||||
|
this.customerEmptyViewErrorText = errorMsg;
|
||||||
|
return this.complete(false);
|
||||||
|
},
|
||||||
|
// 与上方complete方法功能一致,新版本中设置服务端回调数组请使用complete方法
|
||||||
|
addData(data, success = true) {
|
||||||
|
if (!this.fromCompleteEmit) {
|
||||||
|
this.disabledCompleteEmit = true;
|
||||||
|
this.fromCompleteEmit = false;
|
||||||
|
}
|
||||||
|
const currentTimeStamp = u.getTime();
|
||||||
|
const disTime = currentTimeStamp - this.requestTimeStamp;
|
||||||
|
let minDelay = this.minDelay;
|
||||||
|
if (this.isFirstPage && this.finalShowRefresherWhenReload) {
|
||||||
|
minDelay = Math.max(400, minDelay);
|
||||||
|
}
|
||||||
|
const addDataDalay = (this.requestTimeStamp > 0 && disTime < minDelay) ? minDelay - disTime : 0;
|
||||||
|
this.$nextTick(() => {
|
||||||
|
u.delay(() => {
|
||||||
|
this._addData(data, success, false);
|
||||||
|
}, this.delay > 0 ? this.delay : addDataDalay)
|
||||||
|
})
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.dataPromiseResultMap.complete = { resolve, reject };
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 从顶部添加数据,不会影响分页的pageNo和pageSize
|
||||||
|
addDataFromTop(data, toTop = true, toTopWithAnimate = true) {
|
||||||
|
// 数据是否拼接到顶部,如果是聊天记录模式并且列表没有倒置,则应该拼接在底部
|
||||||
|
let addFromTop = !this.isChatRecordModeAndNotInversion;
|
||||||
|
data = Object.prototype.toString.call(data) !== '[object Array]' ? [data] : (addFromTop ? data.reverse() : data);
|
||||||
|
// #ifndef APP-NVUE
|
||||||
|
this.finalUseVirtualList && this._setCellIndex(data, 'top')
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
this.totalData = addFromTop ? [...data, ...this.totalData] : [...this.totalData, ...data];
|
||||||
|
if (toTop) {
|
||||||
|
u.delay(() => this.useChatRecordMode ? this.scrollToBottom(toTopWithAnimate) : this.scrollToTop(toTopWithAnimate));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 重新设置列表数据,调用此方法不会影响pageNo和pageSize,也不会触发请求。适用场景:当需要删除列表中某一项时,将删除对应项后的数组通过此方法传递给z-paging。(当出现类似的需要修改列表数组的场景时,请使用此方法,请勿直接修改page中:list.sync绑定的数组)
|
||||||
|
resetTotalData(data) {
|
||||||
|
this.isTotalChangeFromAddData = true;
|
||||||
|
data = Object.prototype.toString.call(data) !== '[object Array]' ? [data] : data;
|
||||||
|
this.totalData = data;
|
||||||
|
},
|
||||||
|
// 设置本地分页数据,请求结束(成功或者失败)调用此方法,将请求的结果传递给z-paging作分页处理(若调用了此方法,则上拉加载更多时内部会自动分页,不会触发@query所绑定的事件)
|
||||||
|
setLocalPaging(data, success = true) {
|
||||||
|
this.isLocalPaging = true;
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this._addData(data, success, true);
|
||||||
|
})
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.dataPromiseResultMap.localPaging = { resolve, reject };
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 重新加载分页数据,pageNo会恢复为默认值,相当于下拉刷新的效果(animate为true时会展示下拉刷新动画,默认为false)
|
||||||
|
reload(animate = this.showRefresherWhenReload) {
|
||||||
|
if (animate) {
|
||||||
|
this.privateShowRefresherWhenReload = animate;
|
||||||
|
this.isUserPullDown = true;
|
||||||
|
}
|
||||||
|
if (!this.showLoadingMoreWhenReload) {
|
||||||
|
this.listRendering = true;
|
||||||
|
}
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this._preReload(animate, false);
|
||||||
|
})
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.dataPromiseResultMap.reload = { resolve, reject };
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 刷新列表数据,pageNo和pageSize不会重置,列表数据会重新从服务端获取。必须保证@query绑定的方法中的pageNo和pageSize和传给服务端的一致
|
||||||
|
refresh() {
|
||||||
|
return this._handleRefreshWithDisPageNo(this.pageNo - this.defaultPageNo + 1);
|
||||||
|
},
|
||||||
|
// 刷新列表数据至指定页,例如pageNo=5时则代表刷新列表至第5页,此时pageNo会变为5,列表会展示前5页的数据。必须保证@query绑定的方法中的pageNo和pageSize和传给服务端的一致
|
||||||
|
refreshToPage(pageNo) {
|
||||||
|
this.isHandlingRefreshToPage = true;
|
||||||
|
return this._handleRefreshWithDisPageNo(pageNo + this.defaultPageNo - 1);
|
||||||
|
},
|
||||||
|
// 手动更新列表缓存数据,将自动截取v-model绑定的list中的前pageSize条覆盖缓存,请确保在list数据更新到预期结果后再调用此方法
|
||||||
|
updateCache() {
|
||||||
|
if (this.finalUseCache && this.totalData.length) {
|
||||||
|
this._saveLocalCache(this.totalData.slice(0, Math.min(this.totalData.length, this.pageSize)));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 清空分页数据
|
||||||
|
clean() {
|
||||||
|
this._reload(true);
|
||||||
|
this._addData([], true, false);
|
||||||
|
},
|
||||||
|
// 清空分页数据
|
||||||
|
clear() {
|
||||||
|
this.clean();
|
||||||
|
},
|
||||||
|
// reload之前的一些处理
|
||||||
|
_preReload(animate = this.showRefresherWhenReload, isFromMounted = true, retryCount = 0) {
|
||||||
|
const showRefresher = this.finalRefresherEnabled && this.useCustomRefresher;
|
||||||
|
// #ifndef APP-NVUE
|
||||||
|
// 如果获取slot="refresher"高度失败,则不触发reload,直到获取slot="refresher"高度成功
|
||||||
|
if (this.customRefresherHeight === -1 && showRefresher) {
|
||||||
|
u.delay(() => {
|
||||||
|
retryCount ++;
|
||||||
|
// 如果重试次数是10的倍数(也就是每500毫秒),尝试重新获取一下slot="refresher"高度
|
||||||
|
// 此举是为了解决在某些特殊情况下,z-paging组件mounted了,但是未展示在用户面前,(比如在tabbar页面中,未切换到对应tabbar但是通过代码让z-paging展示了,此时控制台会报Error: Not Found:Page,因为这时候去获取dom节点信息获取不到)
|
||||||
|
// 当用户在某个时刻让此z-paging展示在面前时,即可顺利获取到slot="refresher"高度,递归停止
|
||||||
|
if (retryCount % 10 === 0) {
|
||||||
|
this._updateCustomRefresherHeight();
|
||||||
|
}
|
||||||
|
this._preReload(animate, isFromMounted, retryCount);
|
||||||
|
}, c.delayTime / 2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
this.isUserReload = true;
|
||||||
|
this.loadingType = Enum.LoadingType.Refresher;
|
||||||
|
if (animate) {
|
||||||
|
this.privateShowRefresherWhenReload = animate;
|
||||||
|
// #ifndef APP-NVUE
|
||||||
|
if (this.useCustomRefresher) {
|
||||||
|
this._doRefresherRefreshAnimate();
|
||||||
|
} else {
|
||||||
|
this.refresherTriggered = true;
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
this.refresherStatus = Enum.Refresher.Loading;
|
||||||
|
this.refresherRevealStackCount ++;
|
||||||
|
u.delay(() => {
|
||||||
|
this._getNodeClientRect('zp-n-refresh-container', false).then((node) => {
|
||||||
|
if (node) {
|
||||||
|
let nodeHeight = node[0].height;
|
||||||
|
this.nShowRefresherReveal = true;
|
||||||
|
this.nShowRefresherRevealHeight = nodeHeight;
|
||||||
|
u.delay(() => {
|
||||||
|
this._nDoRefresherEndAnimation(0, -nodeHeight, false, false);
|
||||||
|
u.delay(() => {
|
||||||
|
this._nDoRefresherEndAnimation(nodeHeight, 0);
|
||||||
|
}, 10)
|
||||||
|
}, 10)
|
||||||
|
}
|
||||||
|
this._reload(false, isFromMounted);
|
||||||
|
this._doRefresherLoad(false);
|
||||||
|
});
|
||||||
|
}, this.pagingLoaded ? 10 : 100)
|
||||||
|
return;
|
||||||
|
// #endif
|
||||||
|
} else {
|
||||||
|
this._refresherEnd(false, false, false, false);
|
||||||
|
}
|
||||||
|
this._reload(false, isFromMounted);
|
||||||
|
},
|
||||||
|
// 重新加载分页数据
|
||||||
|
_reload(isClean = false, isFromMounted = false, isUserPullDown = false) {
|
||||||
|
this.isAddedData = false;
|
||||||
|
this.insideOfPaging = -1;
|
||||||
|
this.cacheScrollNodeHeight = -1;
|
||||||
|
this.pageNo = this.defaultPageNo;
|
||||||
|
this._cleanRefresherEndTimeout();
|
||||||
|
!this.privateShowRefresherWhenReload && !isClean && this._startLoading(true);
|
||||||
|
this.firstPageLoaded = true;
|
||||||
|
this.isTotalChangeFromAddData = false;
|
||||||
|
if (!this.isSettingCacheList) {
|
||||||
|
this.totalData = [];
|
||||||
|
}
|
||||||
|
if (!isClean) {
|
||||||
|
this._emitQuery(this.pageNo, this.defaultPageSize, isUserPullDown ? Enum.QueryFrom.UserPullDown : Enum.QueryFrom.Reload);
|
||||||
|
let delay = 0;
|
||||||
|
// #ifdef MP-TOUTIAO
|
||||||
|
delay = 5;
|
||||||
|
// #endif
|
||||||
|
u.delay(this._callMyParentQuery, delay);
|
||||||
|
if (!isFromMounted && this.autoScrollToTopWhenReload) {
|
||||||
|
let checkedNRefresherLoading = true;
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
checkedNRefresherLoading = !this.nRefresherLoading;
|
||||||
|
// #endif
|
||||||
|
checkedNRefresherLoading && this._scrollToTop(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.nShowBottom = this.realTotalData.length > 0;
|
||||||
|
})
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
// 处理服务端返回的数组
|
||||||
|
_addData(data, success, isLocal) {
|
||||||
|
this.isAddedData = true;
|
||||||
|
this.fromEmptyViewReload = false;
|
||||||
|
this.isTotalChangeFromAddData = true;
|
||||||
|
this.refresherTriggered = false;
|
||||||
|
this._endSystemLoadingAndRefresh();
|
||||||
|
const tempIsUserPullDown = this.isUserPullDown;
|
||||||
|
if (this.showRefresherUpdateTime && this.isFirstPage) {
|
||||||
|
u.setRefesrherTime(u.getTime(), this.refresherUpdateTimeKey);
|
||||||
|
this.$refs.refresh && this.$refs.refresh.updateTime();
|
||||||
|
}
|
||||||
|
if (!isLocal && tempIsUserPullDown && this.isFirstPage) {
|
||||||
|
this.isUserPullDown = false;
|
||||||
|
}
|
||||||
|
this.listRendering = true;
|
||||||
|
this.$nextTick(() => {
|
||||||
|
u.delay(() => this.listRendering = false);
|
||||||
|
})
|
||||||
|
let dataTypeRes = this._checkDataType(data, success, isLocal);
|
||||||
|
data = dataTypeRes.data;
|
||||||
|
success = dataTypeRes.success;
|
||||||
|
let delayTime = c.delayTime;
|
||||||
|
if (this.useChatRecordMode) delayTime = 0;
|
||||||
|
this.loadingForNow = false;
|
||||||
|
u.delay(() => {
|
||||||
|
this.pagingLoaded = true;
|
||||||
|
this.$nextTick(()=>{
|
||||||
|
!isLocal && this._refresherEnd(delayTime > 0, true, tempIsUserPullDown);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
if (this.isFirstPage) {
|
||||||
|
this.isLoadFailed = !success;
|
||||||
|
this.$emit('isLoadFailedChange', this.isLoadFailed);
|
||||||
|
if (this.finalUseCache && success && (this.cacheMode === Enum.CacheMode.Always ? true : this.isSettingCacheList)) {
|
||||||
|
this._saveLocalCache(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.isSettingCacheList = false;
|
||||||
|
if (success) {
|
||||||
|
if (!(this.privateConcat === false && !this.isHandlingRefreshToPage && this.loadingStatus === Enum.More.NoMore)) {
|
||||||
|
this.loadingStatus = Enum.More.Default;
|
||||||
|
}
|
||||||
|
if (isLocal) {
|
||||||
|
// 如果当前是本地分页,则必然是由setLocalPaging方法触发,此时直接本地加载第一页数据即可。后续本地分页加载更多方法由滚动到底部加载更多事件处理
|
||||||
|
this.totalLocalPagingList = data;
|
||||||
|
const localPageNo = this.defaultPageNo;
|
||||||
|
const localPageSize = this.queryFrom !== Enum.QueryFrom.Refresh ? this.defaultPageSize : this.currentRefreshPageSize;
|
||||||
|
this._localPagingQueryList(localPageNo, localPageSize, 0, res => {
|
||||||
|
u.delay(() => {
|
||||||
|
this.completeByTotal(res, this.totalLocalPagingList.length);;
|
||||||
|
}, 0)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// 如果当前不是本地分页,则按照正常分页逻辑进行数据处理&emit数据
|
||||||
|
let dataChangeDelayTime = 0;
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
if (this.privateShowRefresherWhenReload && this.finalNvueListIs === 'waterfall') {
|
||||||
|
dataChangeDelayTime = 150;
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
u.delay(() => {
|
||||||
|
this._currentDataChange(data, this.currentData);
|
||||||
|
this._callDataPromise(true, this.totalData);
|
||||||
|
}, dataChangeDelayTime)
|
||||||
|
}
|
||||||
|
if (this.isHandlingRefreshToPage) {
|
||||||
|
this.isHandlingRefreshToPage = false;
|
||||||
|
this.pageNo = this.defaultPageNo + Math.ceil(data.length / this.pageSize) - 1;
|
||||||
|
if (data.length % this.pageSize !== 0) {
|
||||||
|
this.customNoMore = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this._currentDataChange(data, this.currentData);
|
||||||
|
this._callDataPromise(false);
|
||||||
|
this.loadingStatus = Enum.More.Fail;
|
||||||
|
this.isHandlingRefreshToPage = false;
|
||||||
|
if (this.loadingType === Enum.LoadingType.LoadMore) {
|
||||||
|
this.pageNo --;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 所有数据改变时调用
|
||||||
|
_totalDataChange(newVal, oldVal, eventThrow=true) {
|
||||||
|
if ((!this.isUserReload || !this.autoCleanListWhenReload) && this.firstPageLoaded && !newVal.length && oldVal.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._doCheckScrollViewShouldFullHeight(newVal);
|
||||||
|
if(!this.realTotalData.length && !newVal.length){
|
||||||
|
eventThrow = false;
|
||||||
|
}
|
||||||
|
this.realTotalData = newVal;
|
||||||
|
// emit列表更新事件
|
||||||
|
if (eventThrow) {
|
||||||
|
this.$emit('input', newVal);
|
||||||
|
// #ifdef VUE3
|
||||||
|
this.$emit('update:modelValue', newVal);
|
||||||
|
// #endif
|
||||||
|
this.$emit('update:list', newVal);
|
||||||
|
this.$emit('listChange', newVal);
|
||||||
|
this._callMyParentList(newVal);
|
||||||
|
}
|
||||||
|
this.firstPageLoaded = false;
|
||||||
|
this.isTotalChangeFromAddData = false;
|
||||||
|
this.$nextTick(() => {
|
||||||
|
u.delay(()=>{
|
||||||
|
// emit z-paging内容区域高度改变事件
|
||||||
|
this._getNodeClientRect('.zp-paging-container-content').then(res => {
|
||||||
|
res && this.$emit('contentHeightChanged', res[0].height);
|
||||||
|
});
|
||||||
|
}, c.delayTime * (this.isIos ? 1 : 3))
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
// 在nvue中延时600毫秒展示底部加载更多,避免底部加载更多太早加载闪一下的问题
|
||||||
|
u.delay(() => {
|
||||||
|
this.nShowBottom = true;
|
||||||
|
}, c.delayTime * 6, 'nShowBottomDelay');
|
||||||
|
// #endif
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 当前数据改变时调用
|
||||||
|
_currentDataChange(newVal, oldVal) {
|
||||||
|
newVal = [...newVal];
|
||||||
|
// #ifndef APP-NVUE
|
||||||
|
this.finalUseVirtualList && this._setCellIndex(newVal, 'bottom');
|
||||||
|
// #endif
|
||||||
|
if (this.isFirstPage && this.finalConcat) {
|
||||||
|
this.totalData = [];
|
||||||
|
}
|
||||||
|
// customNoMore:-1代表交由z-paging自行判断;1代表没有更多了;0代表还有更多数据
|
||||||
|
if (this.customNoMore !== -1) {
|
||||||
|
// 如果customNoMore等于1 或者 customNoMore不是0并且新增数组长度为0(也就是不是明确的还有更多数据并且新增的数组长度为0),则没有更多数据了
|
||||||
|
if (this.customNoMore === 1 || (this.customNoMore !== 0 && !newVal.length)) {
|
||||||
|
this.loadingStatus = Enum.More.NoMore;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 如果新增的数据数组长度为0 或者 新增的数组长度小于默认的pageSize,则没有更多数据了
|
||||||
|
if (!newVal.length || (newVal.length && newVal.length < this.defaultPageSize)) {
|
||||||
|
this.loadingStatus = Enum.More.NoMore;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!this.totalData.length) {
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
// 如果在聊天记录模式+nvue中,并且数据不满一页时需要将列表倒序,因为此时没有将列表旋转180度,数组中第0条数据应当在最底下显示
|
||||||
|
if (this.useChatRecordMode && this.finalConcat && this.isFirstPage && this.loadingStatus === Enum.More.NoMore) {
|
||||||
|
newVal.reverse();
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
this.totalData = newVal;
|
||||||
|
} else {
|
||||||
|
if (this.finalConcat) {
|
||||||
|
const currentScrollTop = this.oldScrollTop;
|
||||||
|
this.totalData = [...this.totalData, ...newVal];
|
||||||
|
// 此处是为了解决在微信小程序中,在某些情况下滚动到底部加载更多后滚动位置直接变为最底部的问题,因此需要通过代码强制滚动回加载更多前的位置
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
if (!this.isIos && !this.refresherOnly && !this.usePageScroll && newVal.length) {
|
||||||
|
this.loadingMoreTimeStamp = u.getTime();
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.scrollToY(currentScrollTop);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
} else {
|
||||||
|
this.totalData = newVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.privateConcat = true;
|
||||||
|
},
|
||||||
|
// 根据pageNo处理refresh操作
|
||||||
|
_handleRefreshWithDisPageNo(pageNo) {
|
||||||
|
if (!this.isHandlingRefreshToPage && !this.realTotalData.length) return this.reload();
|
||||||
|
if (pageNo >= 1) {
|
||||||
|
this.loading = true;
|
||||||
|
this.privateConcat = false;
|
||||||
|
const totalPageSize = pageNo * this.pageSize;
|
||||||
|
this.currentRefreshPageSize = totalPageSize;
|
||||||
|
// 如果调用refresh时是本地分页,则在组件内部自己处理分页逻辑,不emit query相关事件
|
||||||
|
if (this.isLocalPaging && this.isHandlingRefreshToPage) {
|
||||||
|
this._localPagingQueryList(this.defaultPageNo, totalPageSize, 0, res => {
|
||||||
|
this.complete(res);
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// emit query相关事件
|
||||||
|
this._emitQuery(this.defaultPageNo, totalPageSize, Enum.QueryFrom.Refresh);
|
||||||
|
this._callMyParentQuery(this.defaultPageNo, totalPageSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.dataPromiseResultMap.reload = { resolve, reject };
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 本地分页请求
|
||||||
|
_localPagingQueryList(pageNo, pageSize, localPagingLoadingTime, callback) {
|
||||||
|
pageNo = Math.max(1, pageNo);
|
||||||
|
pageSize = Math.max(1, pageSize);
|
||||||
|
const totalPagingList = [...this.totalLocalPagingList];
|
||||||
|
const pageNoIndex = (pageNo - 1) * pageSize;
|
||||||
|
const finalPageNoIndex = Math.min(totalPagingList.length, pageNoIndex + pageSize);
|
||||||
|
const resultPagingList = totalPagingList.splice(pageNoIndex, finalPageNoIndex - pageNoIndex);
|
||||||
|
u.delay(() => callback(resultPagingList), localPagingLoadingTime)
|
||||||
|
},
|
||||||
|
// 存储列表缓存数据
|
||||||
|
_saveLocalCache(data) {
|
||||||
|
uni.setStorageSync(this.finalCacheKey, data);
|
||||||
|
},
|
||||||
|
// 通过缓存数据填充列表数据
|
||||||
|
_setListByLocalCache() {
|
||||||
|
this.totalData = uni.getStorageSync(this.finalCacheKey) || [];
|
||||||
|
this.isSettingCacheList = true;
|
||||||
|
},
|
||||||
|
// 修改父view的list
|
||||||
|
_callMyParentList(newVal) {
|
||||||
|
if (this.autowireListName.length) {
|
||||||
|
const myParent = u.getParent(this.$parent);
|
||||||
|
if (myParent && myParent[this.autowireListName]) {
|
||||||
|
myParent[this.autowireListName] = newVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 调用父view的query
|
||||||
|
_callMyParentQuery(customPageNo = 0, customPageSize = 0) {
|
||||||
|
if (this.autowireQueryName) {
|
||||||
|
if (this.myParentQuery === -1) {
|
||||||
|
const myParent = u.getParent(this.$parent);
|
||||||
|
if (myParent && myParent[this.autowireQueryName]) {
|
||||||
|
this.myParentQuery = myParent[this.autowireQueryName];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.myParentQuery !== -1) {
|
||||||
|
customPageSize > 0 ? this.myParentQuery(customPageNo, customPageSize) : this.myParentQuery(this.pageNo, this.defaultPageSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// emit query事件
|
||||||
|
_emitQuery(pageNo, pageSize, from){
|
||||||
|
this.queryFrom = from;
|
||||||
|
this.requestTimeStamp = u.getTime();
|
||||||
|
const [lastItem] = this.realTotalData.slice(-1);
|
||||||
|
if (this.fetch) {
|
||||||
|
const fetchParams = interceptor._handleFetchParams({pageNo, pageSize, from, lastItem: lastItem || null}, this.fetchParams);
|
||||||
|
const fetchResult = this.fetch(fetchParams);
|
||||||
|
if (!interceptor._handleFetchResult(fetchResult, this, fetchParams)) {
|
||||||
|
u.isPromise(fetchResult) ? fetchResult.then(res => {
|
||||||
|
this.complete(res);
|
||||||
|
}).catch(err => {
|
||||||
|
this.complete(false);
|
||||||
|
}) : this.complete(fetchResult)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.$emit('query', ...interceptor._handleQuery(pageNo, pageSize, from, lastItem || null));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 触发数据改变promise
|
||||||
|
_callDataPromise(success, totalList) {
|
||||||
|
for (const key in this.dataPromiseResultMap) {
|
||||||
|
const obj = this.dataPromiseResultMap[key];
|
||||||
|
if (!obj) continue;
|
||||||
|
success ? obj.resolve({ totalList, noMore: this.loadingStatus === Enum.More.NoMore }) : this.callNetworkReject && obj.reject(`z-paging-${key}-error`);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 检查complete data的类型
|
||||||
|
_checkDataType(data, success, isLocal) {
|
||||||
|
const dataType = Object.prototype.toString.call(data);
|
||||||
|
if (dataType === '[object Boolean]') {
|
||||||
|
success = data;
|
||||||
|
data = [];
|
||||||
|
} else if (dataType !== '[object Array]') {
|
||||||
|
data = [];
|
||||||
|
if (dataType !== '[object Undefined]' && dataType !== '[object Null]') {
|
||||||
|
u.consoleErr(`${isLocal ? 'setLocalPaging' : 'complete'}参数类型不正确,第一个参数类型必须为Array!`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { data, success };
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,144 @@
|
||||||
|
// [z-paging]空数据图view模块
|
||||||
|
import u from '.././z-paging-utils'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
// 是否强制隐藏空数据图,默认为否
|
||||||
|
hideEmptyView: {
|
||||||
|
type: Boolean,
|
||||||
|
default: u.gc('hideEmptyView', false)
|
||||||
|
},
|
||||||
|
// 空数据图描述文字,默认为“没有数据哦~”
|
||||||
|
emptyViewText: {
|
||||||
|
type: [String, Object],
|
||||||
|
default: u.gc('emptyViewText', null)
|
||||||
|
},
|
||||||
|
// 是否显示空数据图重新加载按钮(无数据时),默认为否
|
||||||
|
showEmptyViewReload: {
|
||||||
|
type: Boolean,
|
||||||
|
default: u.gc('showEmptyViewReload', false)
|
||||||
|
},
|
||||||
|
// 加载失败时是否显示空数据图重新加载按钮,默认为是
|
||||||
|
showEmptyViewReloadWhenError: {
|
||||||
|
type: Boolean,
|
||||||
|
default: u.gc('showEmptyViewReloadWhenError', true)
|
||||||
|
},
|
||||||
|
// 空数据图点击重新加载文字,默认为“重新加载”
|
||||||
|
emptyViewReloadText: {
|
||||||
|
type: [String, Object],
|
||||||
|
default: u.gc('emptyViewReloadText', null)
|
||||||
|
},
|
||||||
|
// 空数据图图片,默认使用z-paging内置的图片
|
||||||
|
emptyViewImg: {
|
||||||
|
type: String,
|
||||||
|
default: u.gc('emptyViewImg', '')
|
||||||
|
},
|
||||||
|
// 空数据图“加载失败”描述文字,默认为“很抱歉,加载失败”
|
||||||
|
emptyViewErrorText: {
|
||||||
|
type: [String, Object],
|
||||||
|
default: u.gc('emptyViewErrorText', null)
|
||||||
|
},
|
||||||
|
// 空数据图“加载失败”图片,默认使用z-paging内置的图片
|
||||||
|
emptyViewErrorImg: {
|
||||||
|
type: String,
|
||||||
|
default: u.gc('emptyViewErrorImg', '')
|
||||||
|
},
|
||||||
|
// 空数据图样式
|
||||||
|
emptyViewStyle: {
|
||||||
|
type: Object,
|
||||||
|
default: u.gc('emptyViewStyle', {})
|
||||||
|
},
|
||||||
|
// 空数据图容器样式
|
||||||
|
emptyViewSuperStyle: {
|
||||||
|
type: Object,
|
||||||
|
default: u.gc('emptyViewSuperStyle', {})
|
||||||
|
},
|
||||||
|
// 空数据图img样式
|
||||||
|
emptyViewImgStyle: {
|
||||||
|
type: Object,
|
||||||
|
default: u.gc('emptyViewImgStyle', {})
|
||||||
|
},
|
||||||
|
// 空数据图描述文字样式
|
||||||
|
emptyViewTitleStyle: {
|
||||||
|
type: Object,
|
||||||
|
default: u.gc('emptyViewTitleStyle', {})
|
||||||
|
},
|
||||||
|
// 空数据图重新加载按钮样式
|
||||||
|
emptyViewReloadStyle: {
|
||||||
|
type: Object,
|
||||||
|
default: u.gc('emptyViewReloadStyle', {})
|
||||||
|
},
|
||||||
|
// 空数据图片是否铺满z-paging,默认为否,即填充满z-paging内列表(滚动区域)部分。若设置为否,则为填铺满整个z-paging
|
||||||
|
emptyViewFixed: {
|
||||||
|
type: Boolean,
|
||||||
|
default: u.gc('emptyViewFixed', false)
|
||||||
|
},
|
||||||
|
// 空数据图片是否垂直居中,默认为是,若设置为否即为从空数据容器顶部开始显示。emptyViewFixed为false时有效
|
||||||
|
emptyViewCenter: {
|
||||||
|
type: Boolean,
|
||||||
|
default: u.gc('emptyViewCenter', true)
|
||||||
|
},
|
||||||
|
// 加载中时是否自动隐藏空数据图,默认为是
|
||||||
|
autoHideEmptyViewWhenLoading: {
|
||||||
|
type: Boolean,
|
||||||
|
default: u.gc('autoHideEmptyViewWhenLoading', true)
|
||||||
|
},
|
||||||
|
// 用户下拉列表触发下拉刷新加载中时是否自动隐藏空数据图,默认为是
|
||||||
|
autoHideEmptyViewWhenPull: {
|
||||||
|
type: Boolean,
|
||||||
|
default: u.gc('autoHideEmptyViewWhenPull', true)
|
||||||
|
},
|
||||||
|
// 空数据view的z-index,默认为9
|
||||||
|
emptyViewZIndex: {
|
||||||
|
type: Number,
|
||||||
|
default: u.gc('emptyViewZIndex', 9)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
customerEmptyViewErrorText: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
finalEmptyViewImg() {
|
||||||
|
return this.isLoadFailed ? this.emptyViewErrorImg : this.emptyViewImg;
|
||||||
|
},
|
||||||
|
finalShowEmptyViewReload() {
|
||||||
|
return this.isLoadFailed ? this.showEmptyViewReloadWhenError : this.showEmptyViewReload;
|
||||||
|
},
|
||||||
|
// 是否展示空数据图
|
||||||
|
showEmpty() {
|
||||||
|
if (this.refresherOnly || this.hideEmptyView || this.realTotalData.length) return false;
|
||||||
|
if (this.autoHideEmptyViewWhenLoading) {
|
||||||
|
if (this.isAddedData && !this.firstPageLoaded && !this.loading) return true;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return !this.autoHideEmptyViewWhenPull && !this.isUserReload;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 点击了空数据view重新加载按钮
|
||||||
|
_emptyViewReload() {
|
||||||
|
let callbacked = false;
|
||||||
|
this.$emit('emptyViewReload', reload => {
|
||||||
|
if (reload === undefined || reload === true) {
|
||||||
|
this.fromEmptyViewReload = true;
|
||||||
|
this.reload().catch(() => {});
|
||||||
|
}
|
||||||
|
callbacked = true;
|
||||||
|
});
|
||||||
|
// 如果用户没有禁止默认的点击重新加载刷新列表事件,则触发列表重新刷新
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (!callbacked) {
|
||||||
|
this.fromEmptyViewReload = true;
|
||||||
|
this.reload().catch(() => {});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 点击了空数据view
|
||||||
|
_emptyViewClick() {
|
||||||
|
this.$emit('emptyViewClick');
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||