feat: 查专业
parent
8f176e3201
commit
c3b1d6e40c
|
|
@ -58,5 +58,9 @@
|
||||||
"explorer.fileNesting.patterns": {
|
"explorer.fileNesting.patterns": {
|
||||||
"package.json": "pnpm-lock.yaml,pnpm-workspace.yaml,LICENSE,.gitattributes,.gitignore,.gitpod.yml,CNAME,.npmrc,.browserslistrc",
|
"package.json": "pnpm-lock.yaml,pnpm-workspace.yaml,LICENSE,.gitattributes,.gitignore,.gitpod.yml,CNAME,.npmrc,.browserslistrc",
|
||||||
".eslintrc.cjs": ".eslintignore,.prettierignore,.stylelintignore,.commitlintrc.*,.prettierrc.*,.stylelintrc.*,.eslintrc-auto-import.json,.editorconfig,.commitlint.cjs"
|
".eslintrc.cjs": ".eslintignore,.prettierignore,.stylelintignore,.commitlintrc.*,.prettierrc.*,.stylelintrc.*,.eslintrc-auto-import.json,.editorconfig,.commitlint.cjs"
|
||||||
}
|
},
|
||||||
|
"vetur.validation.template": false,
|
||||||
|
"vetur.validation.script": false,
|
||||||
|
"vetur.validation.style": false,
|
||||||
|
"vetur.experimental.templateInterpolationService": true
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
<template>
|
||||||
|
<view
|
||||||
|
class="fab-button"
|
||||||
|
@touchstart.stop="startDrag"
|
||||||
|
@touchmove.stop="onDrag"
|
||||||
|
@touchend.stop="endDrag"
|
||||||
|
:style="{ right: position.x + 'px', bottom: position.y + 'px' }"
|
||||||
|
>
|
||||||
|
<image
|
||||||
|
@click="handleClick"
|
||||||
|
class="w-full h-full rounded-full"
|
||||||
|
src="/static/images/home/customerService.svg"
|
||||||
|
></image>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
initialX: {
|
||||||
|
type: Number,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
initialY: {
|
||||||
|
type: Number,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const systemInfo = uni.getSystemInfoSync()
|
||||||
|
const position = ref({ x: props.initialX, y: props.initialY })
|
||||||
|
const startPosition = ref({ x: 0, y: 0 })
|
||||||
|
|
||||||
|
const startDrag = (event: TouchEvent) => {
|
||||||
|
startPosition.value = { x: event.touches[0].clientX, y: event.touches[0].clientY }
|
||||||
|
}
|
||||||
|
|
||||||
|
const onDrag = (event: TouchEvent) => {
|
||||||
|
const deltaX = event.touches[0].clientX - startPosition.value.x
|
||||||
|
const deltaY = event.touches[0].clientY - startPosition.value.y
|
||||||
|
position.value = { x: position.value.x - deltaX, y: position.value.y - deltaY }
|
||||||
|
startPosition.value = { x: event.touches[0].clientX, y: event.touches[0].clientY }
|
||||||
|
}
|
||||||
|
|
||||||
|
const endDrag = () => {
|
||||||
|
const windowWidth = systemInfo.windowWidth
|
||||||
|
const windowHeight = systemInfo.windowHeight
|
||||||
|
const buttonWidth = 128 // 按钮宽度
|
||||||
|
const buttonHeight = 128 // 按钮高度
|
||||||
|
|
||||||
|
if (position.value.x < 0) position.value.x = 0
|
||||||
|
if (position.value.y < 0) position.value.y = 0
|
||||||
|
if (position.value.x + buttonWidth > windowWidth) position.value.x = windowWidth - buttonWidth
|
||||||
|
if (position.value.y + buttonHeight > windowHeight) position.value.y = windowHeight - buttonHeight
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleClick = () => {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages-sub/customerService/index/index',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.fab-button {
|
||||||
|
position: fixed;
|
||||||
|
width: 128rpx;
|
||||||
|
height: 128rpx;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { getUniversityInfo, setWxInfo } from '@/service/index/api'
|
import { setWxInfo } from '@/service/index/api'
|
||||||
|
|
||||||
//uniapp 登陆获取用户信息
|
//uniapp 登陆获取用户信息
|
||||||
export const useLogin = () => {
|
export const useLogin = () => {
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,12 @@
|
||||||
src="https://api.static.ycymedu.com/images/logo.png"
|
src="https://api.static.ycymedu.com/images/logo.png"
|
||||||
mode="aspectFit"
|
mode="aspectFit"
|
||||||
></image>
|
></image>
|
||||||
<wd-button @click="handleLogin">立即登陆</wd-button>
|
<view
|
||||||
|
class="px-[32rpx] py-[16rpx] bg-[#3370FF] rounded-[40rpx] text-white text-[32rpx] font-medium flex items-center justify-center"
|
||||||
|
@click="handleLogin"
|
||||||
|
>
|
||||||
|
立即登陆
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<LoginMask v-model:show="show" @auth-ready="handleAuthReady" />
|
<LoginMask v-model:show="show" @auth-ready="handleAuthReady" />
|
||||||
</view>
|
</view>
|
||||||
|
|
@ -28,10 +33,6 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import LoginMask from './components/LoginMask.vue'
|
import LoginMask from './components/LoginMask.vue'
|
||||||
// import { useUserStore } from '@/store/user'
|
|
||||||
|
|
||||||
// const userStore = useUserStore()
|
|
||||||
// const { token } = userStore.userInfo as unknown as IUserInfo
|
|
||||||
const show = ref(false)
|
const show = ref(false)
|
||||||
|
|
||||||
const handleLogin = () => {
|
const handleLogin = () => {
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import MessageBox from './MessageBox.vue'
|
import MessageBox from '../../components/MessageBox.vue'
|
||||||
import WXXTable from '@/pages-sub/home/components/Table.vue'
|
import WXXTable from '@/pages-sub/home/components/Table.vue'
|
||||||
import { getUniversityListByProvince } from '@/service/index/api'
|
import { getUniversityListByProvince } from '@/service/index/api'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { getSubjectIntroduceList } from '@/service/index/api'
|
import { getSubjectIntroduceList } from '@/service/index/api'
|
||||||
import MessageBox from './MessageBox.vue'
|
import MessageBox from '../../components/MessageBox.vue'
|
||||||
|
|
||||||
const subjectIntroduceList = ref([])
|
const subjectIntroduceList = ref([])
|
||||||
const assessmentSubjectList = ref([])
|
const assessmentSubjectList = ref([])
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { UniversityResult } from '@/types/app-type'
|
import { UniversityResult } from '@/types/app-type'
|
||||||
import wdButton from 'wot-design-uni/components/wd-button/wd-button.vue'
|
import wdButton from 'wot-design-uni/components/wd-button/wd-button.vue'
|
||||||
import MessageBox from './MessageBox.vue'
|
import MessageBox from '../../components/MessageBox.vue'
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
universityResult: {
|
universityResult: {
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
</route>
|
</route>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<view class="h-screen flex flex-col">
|
<view class="pb-safe flex flex-col">
|
||||||
<view class="relative">
|
<view class="relative">
|
||||||
<wd-navbar
|
<wd-navbar
|
||||||
safeAreaInsetTop
|
safeAreaInsetTop
|
||||||
|
|
@ -64,42 +64,29 @@
|
||||||
:indicator="false"
|
:indicator="false"
|
||||||
></wd-swiper>
|
></wd-swiper>
|
||||||
</view>
|
</view>
|
||||||
<wd-tabs
|
|
||||||
sticky
|
<z-tabs
|
||||||
v-model="tabIndex"
|
:current="currentTab"
|
||||||
color="#303030"
|
:list="tabsList"
|
||||||
inactiveColor="#BFBFBF"
|
:scrollCount="4"
|
||||||
custom-class="tabs-wrapper"
|
inactive-color="#BFBFBF"
|
||||||
swipeable
|
active-color="#303030"
|
||||||
slidable="auto"
|
:bar-style="{ backgroundColor: '#1580FF' }"
|
||||||
:slidable-num="4"
|
:tabsStyle="{ position: 'sticky', top: '0', zIndex: '9' }"
|
||||||
:offset-top="90"
|
@change="handleTabChange"
|
||||||
>
|
v-bind="{} as any"
|
||||||
<wd-tab title="院校简介" :name="0">
|
/>
|
||||||
<view class="bg-[#f8f8f8]">
|
<view class="bg-[#f8f8f8]" v-show="currentTab === 0">
|
||||||
<Profile :university-result="universityBaseInfo?.universityResult" />
|
<Profile :university-result="universityBaseInfo?.universityResult" />
|
||||||
<FirstClass :id="collegeId" />
|
<FirstClass :id="collegeId" />
|
||||||
<Colleges :id="collegeId" />
|
<Colleges :id="collegeId" />
|
||||||
</view>
|
</view>
|
||||||
<!-- 招生计划 -->
|
<view class="bg-[#f8f8f8]" v-show="currentTab === 1">
|
||||||
</wd-tab>
|
|
||||||
<wd-tab title="招生计划" :name="1">
|
|
||||||
<view class="bg-[#f8f8f8]">
|
|
||||||
<EnrollmentPlan :id="collegeId"></EnrollmentPlan>
|
<EnrollmentPlan :id="collegeId"></EnrollmentPlan>
|
||||||
</view>
|
</view>
|
||||||
</wd-tab>
|
<EnrollmentIntro :id="collegeId" v-show="currentTab === 2" />
|
||||||
|
<EnrollmentMark :id="collegeId" v-show="currentTab === 3" />
|
||||||
<wd-tab title="招生简章" :name="2">
|
<Situation :id="collegeId" v-show="currentTab === 4" />
|
||||||
<!-- 招生简章 -->
|
|
||||||
<EnrollmentIntro :id="collegeId" />
|
|
||||||
</wd-tab>
|
|
||||||
<wd-tab title="录取分数线" :name="3">
|
|
||||||
<EnrollmentMark :id="collegeId" />
|
|
||||||
</wd-tab>
|
|
||||||
<wd-tab title="查扩缩招" :name="4">
|
|
||||||
<Situation :id="collegeId" />
|
|
||||||
</wd-tab>
|
|
||||||
</wd-tabs>
|
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -112,6 +99,7 @@ import EnrollmentPlan from './components/EnrollmentPlan.vue'
|
||||||
import EnrollmentIntro from './components/EnrollmentIntro.vue'
|
import EnrollmentIntro from './components/EnrollmentIntro.vue'
|
||||||
import EnrollmentMark from './components/EnrollmentMark.vue'
|
import EnrollmentMark from './components/EnrollmentMark.vue'
|
||||||
import Situation from './components/Situation.vue'
|
import Situation from './components/Situation.vue'
|
||||||
|
import zTabs from '@/pages-sub/uni_modules/z-tabs/components/z-tabs/z-tabs.vue'
|
||||||
import {
|
import {
|
||||||
getUniversityInfo,
|
getUniversityInfo,
|
||||||
getUnCollectionList,
|
getUnCollectionList,
|
||||||
|
|
@ -147,7 +135,12 @@ onLoad((options) => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
const tabIndex = ref<number>(0)
|
const tabsList = ['院校简介', '招生计划', '招生简章', '录取分数线', '查扩缩招']
|
||||||
|
const currentTab = ref(0)
|
||||||
|
|
||||||
|
const handleTabChange = (index: number) => {
|
||||||
|
currentTab.value = index
|
||||||
|
}
|
||||||
|
|
||||||
const startFlag = ref(false)
|
const startFlag = ref(false)
|
||||||
const handleStar = () => {
|
const handleStar = () => {
|
||||||
|
|
@ -239,9 +232,7 @@ const handleStar = () => {
|
||||||
:deep(.wd-tabs__line) {
|
:deep(.wd-tabs__line) {
|
||||||
bottom: 0 !important;
|
bottom: 0 !important;
|
||||||
}
|
}
|
||||||
:deep(.wd-tabs.is-slide .wd-tabs__nav-item) {
|
|
||||||
padding: 0 20rpx !important;
|
|
||||||
}
|
|
||||||
:deep(.wd-tabs__nav--wrap) {
|
:deep(.wd-tabs__nav--wrap) {
|
||||||
border-bottom: 2rpx solid #f7f7f7;
|
border-bottom: 2rpx solid #f7f7f7;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
<template>
|
||||||
|
<view class="progress-bar">
|
||||||
|
<view class="progress" :style="{ width: progress + '%' }"></view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { defineComponent } from 'vue'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'ProgressBar',
|
||||||
|
props: {
|
||||||
|
progress: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.progress-bar {
|
||||||
|
width: 100%;
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
border-radius: 5px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress {
|
||||||
|
height: 10px;
|
||||||
|
background-color: #1580ff;
|
||||||
|
transition: width 0.3s;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,112 @@
|
||||||
|
<template>
|
||||||
|
<view class="flex flex-col py-[32rpx] px-[24rpx] bg-[#fff] mt-16rpx">
|
||||||
|
<text class="text-[32rpx] font-semibold text-[#333]">就业方向</text>
|
||||||
|
<text class="text-[22rpx] font-normal text-[#636363] my-[24rpx] line-clamp-3">
|
||||||
|
{{ careerInfo.jobs || '暂无' }}
|
||||||
|
</text>
|
||||||
|
<wd-button
|
||||||
|
block
|
||||||
|
custom-class="mt-[24rpx] rounded-[8rpx]! bg-[#f8f8f8]! w-full text-[#303030]!"
|
||||||
|
@click="handleFullFun(1)"
|
||||||
|
>
|
||||||
|
查看全部
|
||||||
|
<wd-icon name="arrow-right"></wd-icon>
|
||||||
|
</wd-button>
|
||||||
|
</view>
|
||||||
|
<view class="h-[16rpx] bg-[#f8f8f8]"></view>
|
||||||
|
<view class="flex flex-col py-[32rpx] px-[24rpx] bg-[#fff]">
|
||||||
|
<text class="text-[32rpx] font-semibold text-[#333]">具体职位</text>
|
||||||
|
<text class="text-[22rpx] font-normal text-[#636363] my-[24rpx] line-clamp-3">
|
||||||
|
{{ careerInfo.profession || '暂无' }}
|
||||||
|
</text>
|
||||||
|
<wd-button
|
||||||
|
block
|
||||||
|
custom-class="mt-[24rpx] rounded-[8rpx]! bg-[#f8f8f8]! w-full text-[#303030]!"
|
||||||
|
@click="handleFullFun(2)"
|
||||||
|
>
|
||||||
|
查看全部
|
||||||
|
<wd-icon name="arrow-right"></wd-icon>
|
||||||
|
</wd-button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="h-[16rpx] bg-[#f8f8f8]"></view>
|
||||||
|
|
||||||
|
<view class="flex flex-col py-[32rpx] px-[24rpx] bg-[#fff]">
|
||||||
|
<text class="text-[32rpx] font-semibold text-[#333]">从事行业</text>
|
||||||
|
<view class="my-[24rpx] flex flex-col gap-[30rpx]">
|
||||||
|
<view
|
||||||
|
v-for="item in careerInfo.rates"
|
||||||
|
:key="item.key"
|
||||||
|
class="grid grid-cols-12 gap-[16rpx] items-center"
|
||||||
|
>
|
||||||
|
<text class="col-span-4">{{ item.key }}</text>
|
||||||
|
<ProgressBar :progress="item.value" class="flex-1 col-span-7 h-[16rpx]" />
|
||||||
|
<text class="col-span-1">{{ item.value }}%</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<MessageBox v-model:show="show" :title="title">
|
||||||
|
<template>
|
||||||
|
<view class="text-[22rpx] text-[#636363] max-h-600rpx mb-[32rpx]" v-show="showType !== 3">
|
||||||
|
{{ innerContent }}
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
</MessageBox>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import MessageBox from '@/pages-sub/home/components/MessageBox.vue'
|
||||||
|
import { getCareerProspects } from '@/service/index/api'
|
||||||
|
import ProgressBar from '../../components/ProgressBar.vue'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
zydm: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const careerInfo = ref<{
|
||||||
|
jobs: string
|
||||||
|
profession: string
|
||||||
|
rates: { key: string; value: string }[]
|
||||||
|
}>({
|
||||||
|
jobs: '',
|
||||||
|
profession: '',
|
||||||
|
rates: [],
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.zydm,
|
||||||
|
(newV) => {
|
||||||
|
getCareerProspects({ zydm: newV }).then((resp) => {
|
||||||
|
if (resp.code === 200) {
|
||||||
|
careerInfo.value = resp.result as {
|
||||||
|
jobs: string
|
||||||
|
profession: string
|
||||||
|
rates: { key: string; value: string }[]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
const show = ref(false)
|
||||||
|
const title = ref('')
|
||||||
|
const innerContent = ref('')
|
||||||
|
const showType = ref(1)
|
||||||
|
|
||||||
|
const handleFullFun = (type: number) => {
|
||||||
|
show.value = true
|
||||||
|
showType.value = type
|
||||||
|
if (type === 1) {
|
||||||
|
innerContent.value = careerInfo.value.jobs
|
||||||
|
title.value = '就业方向'
|
||||||
|
} else if (type === 2) {
|
||||||
|
innerContent.value = careerInfo.value.profession
|
||||||
|
title.value = '具体职位'
|
||||||
|
} else if (type === 3) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,126 @@
|
||||||
|
<template>
|
||||||
|
<view class="flex flex-col py-[32rpx] px-[24rpx] bg-[#fff] mt-16rpx">
|
||||||
|
<text class="text-[32rpx] font-semibold text-[#333]">专业介绍</text>
|
||||||
|
<text class="text-[24rpx] font-semibold text-[#333] mt-[32rpx] mb-[26rpx]">专业简介</text>
|
||||||
|
<text class="text-[22rpx] font-normal text-[#636363] my-[24rpx] line-clamp-3">
|
||||||
|
{{ zyjx || '暂无' }}
|
||||||
|
</text>
|
||||||
|
<wd-button
|
||||||
|
block
|
||||||
|
custom-class="mt-[24rpx] rounded-[8rpx]! bg-[#f8f8f8]! w-full text-[#303030]!"
|
||||||
|
@click="handleFullFun(1)"
|
||||||
|
>
|
||||||
|
查看全部
|
||||||
|
<wd-icon name="arrow-right"></wd-icon>
|
||||||
|
</wd-button>
|
||||||
|
</view>
|
||||||
|
<view class="h-[16rpx] bg-[#f8f8f8]"></view>
|
||||||
|
<view class="flex flex-col py-[32rpx] px-[24rpx] bg-[#fff]">
|
||||||
|
<text class="text-[32rpx] font-semibold text-[#333]">课程要求</text>
|
||||||
|
<text class="text-[24rpx] font-semibold text-[#333] mt-[32rpx] mb-[26rpx]">主干课程</text>
|
||||||
|
<text class="text-[22rpx] font-normal text-[#636363] my-[24rpx] line-clamp-3">
|
||||||
|
{{ kyfx.map((item) => item.zymc).join(',') || '暂无' }}
|
||||||
|
</text>
|
||||||
|
<wd-button
|
||||||
|
block
|
||||||
|
custom-class="mt-[24rpx] rounded-[8rpx]! bg-[#f8f8f8]! w-full text-[#303030]!"
|
||||||
|
@click="handleFullFun(2)"
|
||||||
|
>
|
||||||
|
查看全部
|
||||||
|
<wd-icon name="arrow-right"></wd-icon>
|
||||||
|
</wd-button>
|
||||||
|
</view>
|
||||||
|
<view class="h-[16rpx] bg-[#f8f8f8]"></view>
|
||||||
|
<view class="flex flex-col py-[32rpx] px-[24rpx] bg-[#fff]">
|
||||||
|
<text class="text-[32rpx] font-semibold text-[#333]">课程列表</text>
|
||||||
|
<view class="my-[24rpx]">
|
||||||
|
<WXXTable
|
||||||
|
:columns="columns"
|
||||||
|
:tableData="courseInfo.slice(0, 4)"
|
||||||
|
class="my-[24rpx]"
|
||||||
|
></WXXTable>
|
||||||
|
</view>
|
||||||
|
<wd-button
|
||||||
|
block
|
||||||
|
custom-class="mt-[24rpx] rounded-[8rpx]! bg-[#f8f8f8]! w-full text-[#303030]!"
|
||||||
|
@click="handleFullFun(3)"
|
||||||
|
>
|
||||||
|
查看全部
|
||||||
|
<wd-icon name="arrow-right"></wd-icon>
|
||||||
|
</wd-button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<MessageBox v-model:show="show" :title="title">
|
||||||
|
<template>
|
||||||
|
<view class="text-[22rpx] text-[#636363] max-h-600rpx mb-[32rpx]" v-show="showType !== 3">
|
||||||
|
{{ innerContent }}
|
||||||
|
</view>
|
||||||
|
<WXXTable
|
||||||
|
:columns="columns"
|
||||||
|
:tableData="courseInfo"
|
||||||
|
class="my-[24rpx]"
|
||||||
|
v-show="showType === 3"
|
||||||
|
></WXXTable>
|
||||||
|
</template>
|
||||||
|
</MessageBox>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import MessageBox from '@/pages-sub/home/components/MessageBox.vue'
|
||||||
|
import WXXTable from '@/pages-sub/home/components/Table.vue'
|
||||||
|
import { getMajorCourse } from '@/service/index/api'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
zyjx: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
specId: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
kyfx: {
|
||||||
|
type: Array<{ zymc: string }>,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{ name: '课程名称', key: 'kcmc', width: '50%' },
|
||||||
|
{ name: '课程难易度', key: 'difficulty', width: '25%' },
|
||||||
|
{ name: '课程实用度', key: 'practicality', width: '25%' },
|
||||||
|
]
|
||||||
|
|
||||||
|
const courseInfo = ref<any[]>([])
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.specId,
|
||||||
|
(newV) => {
|
||||||
|
getMajorCourse({ SpecId: newV }).then((resp) => {
|
||||||
|
if (resp.code === 200) {
|
||||||
|
courseInfo.value = (resp.result as { kskcList: any[] }).kskcList
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
const show = ref(false)
|
||||||
|
const title = ref('')
|
||||||
|
const innerContent = ref('')
|
||||||
|
const showType = ref(1)
|
||||||
|
|
||||||
|
const handleFullFun = (type: number) => {
|
||||||
|
show.value = true
|
||||||
|
showType.value = type
|
||||||
|
if (type === 1) {
|
||||||
|
innerContent.value = props.zyjx
|
||||||
|
title.value = '专业介绍'
|
||||||
|
} else if (type === 2) {
|
||||||
|
innerContent.value = props.kyfx.map((item) => item.zymc).join(',')
|
||||||
|
title.value = '主干课程'
|
||||||
|
} else if (type === 3) {
|
||||||
|
innerContent.value = courseInfo.value.map((item) => item.kcmc).join(',')
|
||||||
|
title.value = '课程列表'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
@ -9,8 +9,9 @@
|
||||||
:name="item.key"
|
:name="item.key"
|
||||||
custom-class="custom-collapse-item"
|
custom-class="custom-collapse-item"
|
||||||
v-for="item in subMajorList.items"
|
v-for="item in subMajorList.items"
|
||||||
|
:key="item.key"
|
||||||
>
|
>
|
||||||
<template #title="{ expanded, disabled, isFirst }">
|
<template #title="{ expanded }">
|
||||||
<view class="header">
|
<view class="header">
|
||||||
<text :class="`text-[24rpx] text-[#303030] ${expanded ? 'text-[#1580FF]!' : ''}`">
|
<text :class="`text-[24rpx] text-[#303030] ${expanded ? 'text-[#1580FF]!' : ''}`">
|
||||||
{{ item.name }}
|
{{ item.name }}
|
||||||
|
|
@ -30,7 +31,8 @@
|
||||||
<view
|
<view
|
||||||
class="text-[24rpx] text-[#303030] ml-[26rpx]"
|
class="text-[24rpx] text-[#303030] ml-[26rpx]"
|
||||||
v-for="childMajor in item.childMajors"
|
v-for="childMajor in item.childMajors"
|
||||||
:key="item"
|
:key="childMajor.zymc"
|
||||||
|
@click="navigatorToMajorInfo(childMajor)"
|
||||||
>
|
>
|
||||||
{{ childMajor.zymc }}
|
{{ childMajor.zymc }}
|
||||||
</view>
|
</view>
|
||||||
|
|
@ -68,6 +70,13 @@ watch(
|
||||||
value.value = newV.items[0].key.toString()
|
value.value = newV.items[0].key.toString()
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const navigatorToMajorInfo = (item: unknown) => {
|
||||||
|
const _item = item as { specId: string }
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/pages-sub/home/major/info?specId=${_item.specId}`,
|
||||||
|
})
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,105 @@
|
||||||
|
<template>
|
||||||
|
<view class="">
|
||||||
|
<view class="mt-[24rpx] px-[32rpx]">
|
||||||
|
<view class="flex mb-[30rpx] items-center">
|
||||||
|
<text class="text-[32rpx] font-semibold text-[#303030]">专业点分布</text>
|
||||||
|
<text class="text-[22rpx] text-[#636363]">
|
||||||
|
(全国针对{{ userStore.userInfo.estimatedAchievement.provinceName }}招生情况)
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
<view
|
||||||
|
class="flex items-center gap-[16rpx] text-[24rpx] text-[#303030] mb-[30rpx]"
|
||||||
|
v-for="item in provinceList"
|
||||||
|
:key="item.code"
|
||||||
|
>
|
||||||
|
<text class="">{{ item.ssmc }}</text>
|
||||||
|
<ProgressBar
|
||||||
|
class="flex-1 h-[16rpx]"
|
||||||
|
:progress="Math.floor((item.count / provinceTotal) * 100)"
|
||||||
|
/>
|
||||||
|
<text>{{ item.count }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="h-[16rpx] bg-[#f8f8f8]"></view>
|
||||||
|
<view class="flex flex-col px-[32rpx] mt-[40rpx]">
|
||||||
|
<text class="text-[32rpx] font-semibold text-[#303030]">专业院校分布</text>
|
||||||
|
<view
|
||||||
|
@click="handleShow(2)"
|
||||||
|
class="px-[24rpx] py-[8rpx] bg-[#f8f8f8] rounded-[8rpx] flex justify-between items-center text-[24rpx] w-[144rpx] mt-[30rpx]"
|
||||||
|
>
|
||||||
|
{{ provinceName || '不限' }}
|
||||||
|
<wd-icon name="arrow-down" size="16rpx" custom-class="ml-[80rpx]"></wd-icon>
|
||||||
|
</view>
|
||||||
|
<scroll-view :scroll-x="true" class="">
|
||||||
|
<view
|
||||||
|
class="flex gap-[24rpx] py-[40rpx] border-bt"
|
||||||
|
v-for="item in universityList"
|
||||||
|
:key="item"
|
||||||
|
>
|
||||||
|
<image class="w-[112rpx] h-[112rpx]" :src="item.logo" mode="scaleToFill" />
|
||||||
|
<view class="flex flex-col">
|
||||||
|
<text class="text-[32rpx] font-semibold">[{{ item.yxdm }}]{{ item.yxmc }}</text>
|
||||||
|
<text class="text-[22rpx] text-[#505050]">{{ item.cityname }}·{{ item.ulevel }}</text>
|
||||||
|
<text class="text-[#8F959E] text-[22rpx] my-[6rpx]">
|
||||||
|
{{ item.featuretag.split('/').slice(0, 4).join('/') }}/ 排名68
|
||||||
|
</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { getMajorUniversityList } from '@/service/index/api'
|
||||||
|
import ProgressBar from '../../components/ProgressBar.vue'
|
||||||
|
import { useUserStore } from '@/store'
|
||||||
|
|
||||||
|
const userStore = useUserStore()
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
specId: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.specId,
|
||||||
|
(newV) => {
|
||||||
|
getMajorUniversityList({ SpecId: newV }).then((resp) => {
|
||||||
|
if (resp.code === 200) {
|
||||||
|
let result = resp.result as {
|
||||||
|
schSpecList: { yxmc; string }[]
|
||||||
|
ssdmList: { ssmc: string; code: string; count: number }[]
|
||||||
|
}
|
||||||
|
provinceList.value = result.ssdmList.filter((item) => {
|
||||||
|
if (item.code) {
|
||||||
|
return item
|
||||||
|
} else {
|
||||||
|
provinceTotal.value = item.count
|
||||||
|
}
|
||||||
|
})
|
||||||
|
universityList.value = result.schSpecList
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
const provinceName = ref('')
|
||||||
|
const provinceList = ref([])
|
||||||
|
const provinceTotal = ref(0)
|
||||||
|
|
||||||
|
const universityList = ref([])
|
||||||
|
|
||||||
|
const handleShow = (type: number) => {
|
||||||
|
console.log(type)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.border-bt {
|
||||||
|
border-bottom: 1rpx solid #f8f8f8;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -4,10 +4,11 @@
|
||||||
style: {
|
style: {
|
||||||
navigationStyle: 'custom',
|
navigationStyle: 'custom',
|
||||||
},
|
},
|
||||||
|
needLogin: true,
|
||||||
}
|
}
|
||||||
</route>
|
</route>
|
||||||
<template>
|
<template>
|
||||||
<scroll-view :scroll-y="true" class="h-screen flex flex-col">
|
<scroll-view :scroll-y="true" class="flex flex-col pb-safe">
|
||||||
<wd-navbar
|
<wd-navbar
|
||||||
safeAreaInsetTop
|
safeAreaInsetTop
|
||||||
custom-class="bg-white!"
|
custom-class="bg-white!"
|
||||||
|
|
@ -30,32 +31,29 @@
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</wd-navbar>
|
</wd-navbar>
|
||||||
<wd-tabs
|
|
||||||
sticky
|
<z-tabs
|
||||||
color="#303030"
|
:current="currentTab"
|
||||||
inactiveColor="#BFBFBF"
|
:list="tabsList"
|
||||||
custom-class="tabs-wrapper"
|
:scrollCount="4"
|
||||||
swipeable
|
inactive-color="#BFBFBF"
|
||||||
slidable="auto"
|
active-color="#303030"
|
||||||
:slidable-num="4"
|
:bar-style="{ backgroundColor: '#1580FF' }"
|
||||||
:offset-top="98"
|
:tabsStyle="{ position: 'sticky', top: '98px', zIndex: '99' }"
|
||||||
animated
|
@change="handleTabChange"
|
||||||
>
|
v-bind="{} as any"
|
||||||
<wd-tab title="普通本科" :name="1050">
|
/>
|
||||||
<MajorList :type="1050" :keyword="searchValue"></MajorList>
|
<view class="">
|
||||||
</wd-tab>
|
<MajorList :type="1050" :keyword="searchValue" v-show="currentTab === 0"></MajorList>
|
||||||
<wd-tab title="职教本科" :name="1070">
|
<MajorList :type="1070" :keyword="searchValue" v-show="currentTab === 1"></MajorList>
|
||||||
<MajorList :type="1070" :keyword="searchValue"></MajorList>
|
<MajorList :type="1060" :keyword="searchValue" v-show="currentTab === 2"></MajorList>
|
||||||
</wd-tab>
|
</view>
|
||||||
<wd-tab title="高职专科" :name="1060">
|
|
||||||
<MajorList :type="1060" :keyword="searchValue"></MajorList>
|
|
||||||
</wd-tab>
|
|
||||||
</wd-tabs>
|
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import MajorList from './components/MajorList.vue'
|
import MajorList from './components/MajorList.vue'
|
||||||
|
import zTabs from '@/pages-sub/uni_modules/z-tabs/components/z-tabs/z-tabs.vue'
|
||||||
|
|
||||||
const searchValue = ref('')
|
const searchValue = ref('')
|
||||||
|
|
||||||
|
|
@ -64,6 +62,13 @@ const navigatorBack = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleChange = () => {}
|
const handleChange = () => {}
|
||||||
|
|
||||||
|
const tabsList = ['普通本科', '职教本科', '高职专科']
|
||||||
|
const currentTab = ref(0)
|
||||||
|
|
||||||
|
const handleTabChange = (index: number) => {
|
||||||
|
currentTab.value = index
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,196 @@
|
||||||
|
<route lang="json5" type="page">
|
||||||
|
{
|
||||||
|
layout: 'page',
|
||||||
|
style: {
|
||||||
|
navigationStyle: 'custom',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</route>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<view class="pb-safe flex flex-col">
|
||||||
|
<view class="relative">
|
||||||
|
<wd-navbar
|
||||||
|
safeAreaInsetTop
|
||||||
|
custom-class="bg-transparent! custom-background"
|
||||||
|
:bordered="false"
|
||||||
|
left-arrow
|
||||||
|
fixed
|
||||||
|
placeholder
|
||||||
|
title="专业详情"
|
||||||
|
@click-left="navigatorBack"
|
||||||
|
></wd-navbar>
|
||||||
|
<view class="custom-background h-[200rpx] w-full absolute top-0 left-0 z-[1]"></view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<scroll-view class="flex-1 flex flex-col" :scroll-y="true">
|
||||||
|
<view class="flex items-start p-[32rpx]" hover-class="none">
|
||||||
|
<view class="flex flex-col">
|
||||||
|
<text class="text-[40rpx] text-[#303030] font-semibold">{{ majorDetail.zymc }}</text>
|
||||||
|
<text class="text-[#303030] text-[22rpx] mt-[6rpx]">{{ majorDetail.xlcc }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex items-center justify-between gap-[50rpx] px-[32rpx]">
|
||||||
|
<view class="flex flex-col items-center">
|
||||||
|
<text class="name">{{ majorDetail.ml }}</text>
|
||||||
|
<text class="title">类别</text>
|
||||||
|
</view>
|
||||||
|
<view class="flex flex-col items-center">
|
||||||
|
<text class="name">{{ majorDetail.zydm }}</text>
|
||||||
|
<text class="title">专业代码</text>
|
||||||
|
</view>
|
||||||
|
<view class="flex flex-col items-center">
|
||||||
|
<text class="name">--</text>
|
||||||
|
<text class="title">授予学位</text>
|
||||||
|
</view>
|
||||||
|
<view class="flex flex-col items-center">
|
||||||
|
<text class="name">{{ majorDetail.boyPercent }}:{{ majorDetail.girlPercent }}</text>
|
||||||
|
<text class="title">男女比例</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="h-[16rpx] bg-[#f8f8f8] mt-[30rpx]"></view>
|
||||||
|
|
||||||
|
<z-tabs
|
||||||
|
:current="currentTab"
|
||||||
|
:list="tabsList"
|
||||||
|
:scrollCount="4"
|
||||||
|
inactive-color="#BFBFBF"
|
||||||
|
active-color="#303030"
|
||||||
|
:bar-style="{ backgroundColor: '#1580FF' }"
|
||||||
|
:tabsStyle="{ position: 'sticky', top: '0', zIndex: '9' }"
|
||||||
|
@change="handleTabChange"
|
||||||
|
v-bind="{} as any"
|
||||||
|
/>
|
||||||
|
<MajorBaseInfo
|
||||||
|
:zyjx="majorDetail.zyjs"
|
||||||
|
:spec-id="specId"
|
||||||
|
:kyfx="majorDetail.kyfx"
|
||||||
|
v-show="currentTab === 0"
|
||||||
|
/>
|
||||||
|
<MajorUniversity :spec-id="specId" v-show="currentTab === 1" />
|
||||||
|
<EmploymentProspects :zydm="majorDetail.zydm" v-show="currentTab === 2" />
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import MajorBaseInfo from './components/MajorBaseInfo.vue'
|
||||||
|
import MajorUniversity from './components/MajorUniversity.vue'
|
||||||
|
import zTabs from '@/pages-sub/uni_modules/z-tabs/components/z-tabs/z-tabs.vue'
|
||||||
|
import EmploymentProspects from './components/EmploymentProspects.vue'
|
||||||
|
|
||||||
|
import { getMajorDetail } from '@/service/index/api'
|
||||||
|
|
||||||
|
interface CollegeInfo {
|
||||||
|
boyPercent: number
|
||||||
|
girlPercent: number
|
||||||
|
jyfx: string[]
|
||||||
|
kyfx: []
|
||||||
|
ml: string
|
||||||
|
simileZyList: []
|
||||||
|
specId: string
|
||||||
|
xcspImgUrl: null | string
|
||||||
|
xk: string
|
||||||
|
xlcc: string
|
||||||
|
xsgm: string
|
||||||
|
year: string
|
||||||
|
zydm: string
|
||||||
|
zyjs: string
|
||||||
|
zymyd: []
|
||||||
|
zytjzsList: []
|
||||||
|
_id: string
|
||||||
|
zymc: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const navigatorBack = () => {
|
||||||
|
uni.navigateBack()
|
||||||
|
}
|
||||||
|
|
||||||
|
const starFlag = ref(false)
|
||||||
|
const handleStar = () => {}
|
||||||
|
const majorDetail = ref<CollegeInfo>({
|
||||||
|
xk: '',
|
||||||
|
zydm: '',
|
||||||
|
specId: '',
|
||||||
|
_id: '',
|
||||||
|
boyPercent: 0,
|
||||||
|
girlPercent: 0,
|
||||||
|
year: '',
|
||||||
|
xsgm: '',
|
||||||
|
xlcc: '',
|
||||||
|
ml: '',
|
||||||
|
zyjs: '',
|
||||||
|
jyfx: [],
|
||||||
|
zytjzsList: [],
|
||||||
|
zymyd: [],
|
||||||
|
kyfx: [],
|
||||||
|
simileZyList: [],
|
||||||
|
xcspImgUrl: '',
|
||||||
|
zymc: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
const specId = ref('')
|
||||||
|
onLoad((options) => {
|
||||||
|
specId.value = options.specId || '0'
|
||||||
|
getMajorDetail({ SpecId: specId.value }).then((resp) => {
|
||||||
|
if (resp.code === 200) {
|
||||||
|
majorDetail.value = resp.result as CollegeInfo
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const tabsList = ['基本信息', '开设院校', '就业前景']
|
||||||
|
const currentTab = ref(0)
|
||||||
|
|
||||||
|
const handleTabChange = (index: number) => {
|
||||||
|
currentTab.value = index
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
:deep(.custom-background) {
|
||||||
|
background-image: linear-gradient(
|
||||||
|
180deg,
|
||||||
|
rgb(177, 221, 250) 0,
|
||||||
|
rgb(177, 221, 250) 14%,
|
||||||
|
rgb(232, 244, 252) 68%,
|
||||||
|
rgba(255, 255, 255, 1) 86%,
|
||||||
|
rgba(255, 255, 255, 1) 100%,
|
||||||
|
rgba(255, 255, 255, 1) 100%
|
||||||
|
);
|
||||||
|
background-position: 50% 50%;
|
||||||
|
background-origin: padding-box;
|
||||||
|
background-clip: border-box;
|
||||||
|
background-size: auto auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.collect-btn) {
|
||||||
|
border: 2rpx solid #eee !important;
|
||||||
|
color: #636363 !important;
|
||||||
|
|
||||||
|
width: unset !important;
|
||||||
|
min-width: unset !important;
|
||||||
|
border-radius: 12rpx !important;
|
||||||
|
margin-right: 0 !important;
|
||||||
|
padding: 12rpx !important;
|
||||||
|
line-height: 1 !important;
|
||||||
|
|
||||||
|
display: flex !important;
|
||||||
|
justify-content: space-between !important;
|
||||||
|
align-items: center !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 22rpx;
|
||||||
|
color: #86909c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.name {
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #333333;
|
||||||
|
margin-bottom: 6rpx;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -38,18 +38,29 @@
|
||||||
/>
|
/>
|
||||||
</view>
|
</view>
|
||||||
<view class="px-[32rpx] my-[24rpx]">
|
<view class="px-[32rpx] my-[24rpx]">
|
||||||
<wd-tabs
|
<z-tabs
|
||||||
v-model="tabIndex"
|
:current="tabIndex"
|
||||||
custom-class="tab-custom"
|
:list="unSortTypeList"
|
||||||
slidable="always"
|
:scrollCount="4"
|
||||||
swipeable
|
value-key="code"
|
||||||
@change="tabsChange"
|
inactive-color="#A28C6C"
|
||||||
ref="tabsRef"
|
active-color="#684817"
|
||||||
>
|
:bar-style="{
|
||||||
<block v-for="item in unSortTypeList" :key="item.type">
|
display: 'none',
|
||||||
<wd-tab :title="`${item.name}`" :name="item.type"></wd-tab>
|
}"
|
||||||
</block>
|
:tabsStyle="{
|
||||||
</wd-tabs>
|
position: 'sticky',
|
||||||
|
top: '0',
|
||||||
|
zIndex: '99',
|
||||||
|
height: '52rpx',
|
||||||
|
gap: '16rpx',
|
||||||
|
}"
|
||||||
|
:active-style="{
|
||||||
|
background: 'linear-gradient( 270deg, #F2CE95 0%, #F8DEBA 100%)',
|
||||||
|
}"
|
||||||
|
@change="handleTabChange"
|
||||||
|
v-bind="{} as any"
|
||||||
|
/>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
<view
|
<view
|
||||||
|
|
@ -85,7 +96,7 @@
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { getUniversityRank, getUnSortType } from '@/service/index/api'
|
import { getUniversityRank, getUnSortType } from '@/service/index/api'
|
||||||
// import { useUnSortType } from '@/hooks/useUnSortType'
|
import zTabs from '@/pages-sub/uni_modules/z-tabs/components/z-tabs/z-tabs.vue'
|
||||||
|
|
||||||
type UnSortType = { type: number; name: string }[]
|
type UnSortType = { type: number; name: string }[]
|
||||||
|
|
||||||
|
|
@ -104,10 +115,6 @@ const tabsRef = ref(null)
|
||||||
const itemClick = (item, index) => {
|
const itemClick = (item, index) => {
|
||||||
console.log('点击了', item)
|
console.log('点击了', item)
|
||||||
}
|
}
|
||||||
const tabsChange = (index, name) => {
|
|
||||||
tabIndex.value = name
|
|
||||||
paging.value.reload()
|
|
||||||
}
|
|
||||||
|
|
||||||
onLoad((option) => {
|
onLoad((option) => {
|
||||||
tabIndex.value = Number(option?.type) || 0
|
tabIndex.value = Number(option?.type) || 0
|
||||||
|
|
@ -127,6 +134,11 @@ const queryList = (page: number, pageSize: number) => {
|
||||||
const virtualListChange = (_vList) => {
|
const virtualListChange = (_vList) => {
|
||||||
schoolList.value = _vList
|
schoolList.value = _vList
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleTabChange = (index: number) => {
|
||||||
|
tabIndex.value = index
|
||||||
|
paging.value.reload()
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
@ -171,12 +183,9 @@ const virtualListChange = (_vList) => {
|
||||||
}
|
}
|
||||||
/* #endif */
|
/* #endif */
|
||||||
|
|
||||||
:deep(.wd-tabs__nav-container) {
|
:deep(.z-tabs-item) {
|
||||||
gap: 16rpx;
|
|
||||||
align-items: center;
|
|
||||||
.wd-tabs__nav-item {
|
|
||||||
width: 160rpx;
|
width: 160rpx;
|
||||||
height: 52rpx;
|
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
|
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
|
@ -186,18 +195,23 @@ const virtualListChange = (_vList) => {
|
||||||
|
|
||||||
padding: 0 !important;
|
padding: 0 !important;
|
||||||
}
|
}
|
||||||
|
:deep(.z-tabs-list.tabs--z-tabs-list) {
|
||||||
.wd-tabs__nav-item.is-active {
|
margin-top: 0 !important;
|
||||||
color: #684817;
|
display: flex;
|
||||||
background: linear-gradient(270deg, #f2ce95 0%, #f8deba 100%);
|
gap: 16rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wd-tabs__line {
|
:deep(.z-tabs-item-title-container) {
|
||||||
display: none;
|
height: 100%;
|
||||||
}
|
flex: 1 1 auto;
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.tab-custom) {
|
.z-tabs-item-title-rpx {
|
||||||
--wot-tabs-nav-height: 52rpx;
|
height: 100%;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
## 0.3.0(2024-10-21)
|
||||||
|
支持鸿蒙Next
|
||||||
|
## 0.2.7(2024-07-18)
|
||||||
|
1.`新增` 支持切换rpx&px
|
||||||
|
2.`修复` 宽度小于屏幕时底部tabs位置不正确的问题
|
||||||
|
3.`修复` 偶现的Cannot read property 'left' of undefind的问题
|
||||||
|
|
||||||
|
## 0.2.5(2023-01-09)
|
||||||
|
修复可能出现的可能出现的与swiper联动时报错node不存在的bug
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
// z-tabs全局配置文件,注意避免更新时此文件被覆盖,若被覆盖,可在此文件中右键->点击本地历史记录,找回覆盖前的配置
|
||||||
|
export default {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,791 @@
|
||||||
|
<!-- z-tabs v0.3.0 by-ZXLee -->
|
||||||
|
<!-- github地址:https://github.com/SmileZXLee/uni-z-tabs -->
|
||||||
|
<!-- dcloud地址:https://ext.dcloud.net.cn/plugin?name=z-tabs -->
|
||||||
|
<!-- 反馈QQ群:371624008 -->
|
||||||
|
|
||||||
|
<template name="z-tabs">
|
||||||
|
<view class="z-tabs-conatiner" :style="[{background:bgColor}, {height: unit==='rpx' ? '80rpx' : '40px'}, tabsStyle]">
|
||||||
|
<view class="z-tabs-left">
|
||||||
|
<slot name="left" />
|
||||||
|
</view>
|
||||||
|
<view ref="z-tabs-scroll-view-conatiner" class="z-tabs-scroll-view-conatiner">
|
||||||
|
<scroll-view ref="z-tabs-scroll-view" class="z-tabs-scroll-view" :scroll-x="true" :scroll-left="scrollLeft" :show-scrollbar="false" :scroll-with-animation="isFirstLoaded" @scroll="scroll">
|
||||||
|
<view class="z-tabs-list-container" :style="[tabsListStyle]">
|
||||||
|
<view class="z-tabs-list" :style="[tabsListStyle, {marginTop: -finalBottomSpace+'px'}]">
|
||||||
|
<view :ref="`z-tabs-item-${index}`" :id="`z-tabs-item-${index}`" class="z-tabs-item" :style="[tabStyle]" v-for="(item,index) in list" :key="index" @click="tabsClick(index,item)">
|
||||||
|
<view class="z-tabs-item-title-container">
|
||||||
|
<text :class="{'z-tabs-item-title-rpx':unit==='rpx','z-tabs-item-title-px':unit==='px','z-tabs-item-title-disabled':item.disabled}"
|
||||||
|
:style="[{color:item.disabled?disabledColor:(currentIndex===index?activeColor:inactiveColor)},item.disabled?disabledStyle:(currentIndex===index?activeStyle:inactiveStyle)]">
|
||||||
|
{{item[nameKey]||item}}
|
||||||
|
</text>
|
||||||
|
<text v-if="item.badge&&_formatCount(item.badge.count).length" class="z-tabs-item-badge" :class="{'z-tabs-item-badge-rpx':unit==='rpx','z-tabs-item-badge-px':unit==='px'}" :style="[badgeStyle]">{{_formatCount(item.badge.count)}}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="z-tabs-bottom" :style="[{width: tabsContainerWidth+'px', bottom: finalBottomSpace+'px'}]">
|
||||||
|
<view ref="z-tabs-bottom-dot" class="z-tabs-bottom-dot"
|
||||||
|
<!-- #ifndef APP-NVUE -->
|
||||||
|
:style="[{transform:`translateX(${bottomDotX}px)`,transition:dotTransition,background:activeColor},finalDotStyle]"
|
||||||
|
<!-- #endif -->
|
||||||
|
<!-- #ifdef APP-NVUE -->
|
||||||
|
:style="[{background:activeColor},finalDotStyle]"
|
||||||
|
<!-- #endif -->
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
<view class="z-tabs-right">
|
||||||
|
<slot name="right" />
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
const weexDom = weex.requireModule('dom');
|
||||||
|
const weexAnimation = weex.requireModule('animation');
|
||||||
|
// #endif
|
||||||
|
import zTabsConfig from './config/index'
|
||||||
|
|
||||||
|
// #ifdef APP-HARMONY
|
||||||
|
let screenWidth = 0;
|
||||||
|
// #endif
|
||||||
|
// 获取默认配置信息
|
||||||
|
function _gc(key, defaultValue) {
|
||||||
|
let config = null;
|
||||||
|
if (zTabsConfig && Object.keys(zTabsConfig).length) {
|
||||||
|
config = zTabsConfig;
|
||||||
|
} else {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
const value = config[_toKebab(key)];
|
||||||
|
return value === undefined ? defaultValue : value;
|
||||||
|
}
|
||||||
|
// 驼峰转短横线
|
||||||
|
function _toKebab(value) {
|
||||||
|
return value.replace(/([A-Z])/g, "-$1").toLowerCase();
|
||||||
|
}
|
||||||
|
// rpx => px,兼容鸿蒙
|
||||||
|
function rpx2px(rpx) {
|
||||||
|
// #ifdef APP-HARMONY
|
||||||
|
if (!screenWidth) {
|
||||||
|
screenWidth = uni.getSystemInfoSync().screenWidth;
|
||||||
|
}
|
||||||
|
return (screenWidth * Number.parseFloat(rpx)) / 750;
|
||||||
|
// #endif
|
||||||
|
// #ifndef APP-HARMONY
|
||||||
|
return uni.upx2px(rpx);
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* z-tabs 标签
|
||||||
|
* @description 一个简单轻量的tabs标签,全平台兼容,支持nvue、vue3
|
||||||
|
* @tutorial https://ext.dcloud.net.cn/plugin?name=z-tabs
|
||||||
|
* @property {Array} list 数据源数组,支持形如['tab1','tab2']的格式或[{name:'tab1',value:1}]的格式
|
||||||
|
* @property {Number|String} current 当前选中的index,默认为0
|
||||||
|
* @property {Number|String} scroll-count list数组长度超过scrollCount时滚动显示(不自动铺满全屏),默认为5
|
||||||
|
* @property {Number|String} tab-width 自定义每个tab的宽度,默认为0,即代表根据内容自动撑开,单位rpx,支持传100、"100px"或"100rpx"
|
||||||
|
* @property {Number|String} bar-width 滑块宽度,单位rpx,支持传100、"100px"或"100rpx"
|
||||||
|
* @property {Number|String} bar-height 滑块高度,单位rpx,支持传100、"100px"或"100rpx"
|
||||||
|
* @property {Object} bar-style 滑块样式,其中的width和height将被bar-width和bar-height覆盖
|
||||||
|
* @property {Number|String} bottom-space tabs与底部的间距,单位rpx,支持传100、"100px"或"100rpx"
|
||||||
|
* @property {String} bar-animate-mode 切换tab时滑块动画模式,与swiper联动时有效,点击切换tab时无效,必须调用setDx。默认为line,即切换tab时滑块宽度保持不变,线性运动。可选值为worm,即为类似毛毛虫蠕动效果
|
||||||
|
* @property {String} name-key list中item的name(标题)的key,默认为name
|
||||||
|
* @property {String} value-key list中item的value的key,默认为value
|
||||||
|
* @property {String} active-color 激活状态tab的颜色
|
||||||
|
* @property {String} inactive-color 未激活状态tab的颜色
|
||||||
|
* @property {String} disabled-color 禁用状态tab的颜色
|
||||||
|
* @property {Object} active-style 激活状态tab的样式
|
||||||
|
* @property {Object} inactive-style 未激活状态tab的样式
|
||||||
|
* @property {Object} disabled-style 禁用状态tab的样式
|
||||||
|
* @property {Number|String} badge-max-count 徽标数最大数字限制,超过这个数字将变成badge-max-count+,默认为99
|
||||||
|
* @property {Object} badge-style 徽标样式,例如可自定义背景色,字体等等
|
||||||
|
* @property {String} bg-color z-tabs背景色
|
||||||
|
* @property {Object} tabs-style z-tabs样式
|
||||||
|
* @property {Boolean} init-trigger-change 初始化时是否自动触发change事件
|
||||||
|
* @property {String} unit z-tabs中布局的单位,默认为rpx
|
||||||
|
* @event {Function(index,value)} change tabs改变时触发,index:当前切换到的index;value:当前切换到的value
|
||||||
|
* @example <z-tabs :list="list"></z-tabs>
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
name: 'z-tabs',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
currentIndex: 0,
|
||||||
|
currentSwiperIndex: 0,
|
||||||
|
bottomDotX: -1,
|
||||||
|
bottomDotXForIndex: 0,
|
||||||
|
showBottomDot: false,
|
||||||
|
shouldSetDx: true,
|
||||||
|
|
||||||
|
barCalcedWidth: 0,
|
||||||
|
pxBarWidth: 0,
|
||||||
|
scrollLeft: 0,
|
||||||
|
tabsSuperWidth: rpx2px(750),
|
||||||
|
tabsWidth: rpx2px(750),
|
||||||
|
tabsHeight: rpx2px(80),
|
||||||
|
tabsLeft: 0,
|
||||||
|
tabsContainerWidth: 0,
|
||||||
|
itemNodeInfos: [],
|
||||||
|
isFirstLoaded: false,
|
||||||
|
currentScrollLeft: 0,
|
||||||
|
changeTriggerFailed: false,
|
||||||
|
currentChanged: false
|
||||||
|
};
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
//数据源数组,支持形如['tab1','tab2']的格式或[{name:'tab1',value:1}]的格式
|
||||||
|
list: {
|
||||||
|
type: Array,
|
||||||
|
default: function() {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
//当前选中的index
|
||||||
|
current: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: _gc('current',0)
|
||||||
|
},
|
||||||
|
//list数组长度超过scrollCount时滚动显示(不自动铺满全屏)
|
||||||
|
scrollCount: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: _gc('scrollCount',5)
|
||||||
|
},
|
||||||
|
//z-tabs样式
|
||||||
|
tabsStyle: {
|
||||||
|
type: Object,
|
||||||
|
default: function() {
|
||||||
|
return _gc('tabsStyle',{})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
//自定义每个tab的宽度,默认为0,即代表根据内容自动撑开,单位rpx,支持传100、"100px"或"100rpx"
|
||||||
|
tabWidth: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: _gc('tabWidth',0)
|
||||||
|
},
|
||||||
|
//滑块宽度,单位rpx,支持传100、"100px"或"100rpx"
|
||||||
|
barWidth: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: _gc('barWidth',45)
|
||||||
|
},
|
||||||
|
//滑块高度,单位rpx,支持传100、"100px"或"100rpx"
|
||||||
|
barHeight: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: _gc('barHeight',8)
|
||||||
|
},
|
||||||
|
//swiper的宽度,单位rpx,支持传100、"100px"或"100rpx",默认为"750rpx"
|
||||||
|
swiperWidth: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: _gc('swiperWidth',750)
|
||||||
|
},
|
||||||
|
//滑块样式,其中的width和height将被barWidth和barHeight覆盖
|
||||||
|
barStyle: {
|
||||||
|
type: Object,
|
||||||
|
default: function() {
|
||||||
|
return _gc('barStyle',{});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
//tabs与底部的间距,单位rpx,支持传100、"100px"或"100rpx"
|
||||||
|
bottomSpace: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: _gc('bottomSpace',8)
|
||||||
|
},
|
||||||
|
//切换tab时滑块动画模式,与swiper联动时有效,点击切换tab时无效,必须调用setDx。默认为line,即切换tab时滑块宽度保持不变,线性运动。可选值为worm,即为类似毛毛虫蠕动效果
|
||||||
|
barAnimateMode: {
|
||||||
|
type: String,
|
||||||
|
default: _gc('barAnimateMode','line')
|
||||||
|
},
|
||||||
|
//list中item的name(标题)的key
|
||||||
|
nameKey: {
|
||||||
|
type: String,
|
||||||
|
default: _gc('nameKey','name')
|
||||||
|
},
|
||||||
|
//list中item的value的key
|
||||||
|
valueKey: {
|
||||||
|
type: String,
|
||||||
|
default: _gc('valueKey','value')
|
||||||
|
},
|
||||||
|
//激活状态tab的颜色
|
||||||
|
activeColor: {
|
||||||
|
type: String,
|
||||||
|
default: _gc('activeColor','#007AFF')
|
||||||
|
},
|
||||||
|
//未激活状态tab的颜色
|
||||||
|
inactiveColor: {
|
||||||
|
type: String,
|
||||||
|
default: _gc('inactiveColor','#666666')
|
||||||
|
},
|
||||||
|
//禁用状态tab的颜色
|
||||||
|
disabledColor: {
|
||||||
|
type: String,
|
||||||
|
default: _gc('disabledColor','#bbbbbb')
|
||||||
|
},
|
||||||
|
//激活状态tab的样式
|
||||||
|
activeStyle: {
|
||||||
|
type: Object,
|
||||||
|
default: function() {
|
||||||
|
return _gc('activeStyle',{});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
//未激活状态tab的样式
|
||||||
|
inactiveStyle: {
|
||||||
|
type: Object,
|
||||||
|
default: function() {
|
||||||
|
return _gc('inactiveStyle',{});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
//禁用状态tab的样式
|
||||||
|
disabledStyle: {
|
||||||
|
type: Object,
|
||||||
|
default: function() {
|
||||||
|
return _gc('disabledStyle',{});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
//z-tabs背景色
|
||||||
|
bgColor: {
|
||||||
|
type: String,
|
||||||
|
default: _gc('bgColor','white')
|
||||||
|
},
|
||||||
|
//徽标数最大数字限制,超过这个数字将变成badgeMaxCount+
|
||||||
|
badgeMaxCount: {
|
||||||
|
type: [Number, String],
|
||||||
|
default: _gc('badgeMaxCount',99)
|
||||||
|
},
|
||||||
|
//徽标样式,例如可自定义背景色,字体等等
|
||||||
|
badgeStyle: {
|
||||||
|
type: Object,
|
||||||
|
default: function() {
|
||||||
|
return _gc('badgeStyle',{})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
//初始化时是否自动触发change事件
|
||||||
|
initTriggerChange: {
|
||||||
|
type: Boolean,
|
||||||
|
default: _gc('initTriggerChange',false)
|
||||||
|
},
|
||||||
|
//z-tabs中布局的单位,默认为rpx
|
||||||
|
unit: {
|
||||||
|
type: String,
|
||||||
|
default: _gc('unit', 'rpx')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.updateSubviewLayout();
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
current: {
|
||||||
|
handler(newVal) {
|
||||||
|
this.currentChanged && this._lockDx();
|
||||||
|
this.currentIndex = newVal;
|
||||||
|
this._preUpdateDotPosition(this.currentIndex);
|
||||||
|
if (this.initTriggerChange) {
|
||||||
|
if (newVal < this.list.length) {
|
||||||
|
this.$emit('change', newVal, this.list[newVal][this.valueKey]);
|
||||||
|
}else {
|
||||||
|
this.changeTriggerFailed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.currentChanged = true;
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
},
|
||||||
|
list: {
|
||||||
|
handler(newVal) {
|
||||||
|
this._handleListChange(newVal);
|
||||||
|
},
|
||||||
|
immediate: false
|
||||||
|
},
|
||||||
|
bottomDotX(newVal) {
|
||||||
|
if(newVal >= 0){
|
||||||
|
// #ifndef APP-NVUE
|
||||||
|
this.showBottomDot = true;
|
||||||
|
// #endif
|
||||||
|
this.$nextTick(() => {
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
weexAnimation.transition(this.$refs['z-tabs-bottom-dot'], {
|
||||||
|
styles: {
|
||||||
|
transform: `translateX(${newVal}px)`
|
||||||
|
},
|
||||||
|
duration: this.showAnimate ? 200 : 0,
|
||||||
|
delay: 0
|
||||||
|
})
|
||||||
|
setTimeout(() => {
|
||||||
|
this.showBottomDot = true;
|
||||||
|
},10)
|
||||||
|
// #endif
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
finalBarWidth: {
|
||||||
|
handler(newVal) {
|
||||||
|
this.barCalcedWidth = newVal;
|
||||||
|
this.pxBarWidth = this.barCalcedWidth;
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
},
|
||||||
|
currentIndex: {
|
||||||
|
handler(newVal) {
|
||||||
|
this.currentSwiperIndex = newVal;
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
shouldScroll(){
|
||||||
|
return this.list.length > this.scrollCount;
|
||||||
|
},
|
||||||
|
finalTabsHeight(){
|
||||||
|
return this.tabsHeight;
|
||||||
|
},
|
||||||
|
tabStyle(){
|
||||||
|
const stl = this.shouldScroll ? {'flex-shrink': 0} : {'flex': 1};
|
||||||
|
if(this.finalTabWidth > 0){
|
||||||
|
stl['width'] = this.finalTabWidth + 'px';
|
||||||
|
}else{
|
||||||
|
delete stl.width;
|
||||||
|
}
|
||||||
|
return stl;
|
||||||
|
},
|
||||||
|
tabsListStyle(){
|
||||||
|
return this.shouldScroll ? {} : {'flex':1};
|
||||||
|
},
|
||||||
|
showAnimate(){
|
||||||
|
return this.isFirstLoaded && !this.shouldSetDx;
|
||||||
|
},
|
||||||
|
dotTransition(){
|
||||||
|
return this.showAnimate ? 'transform .2s linear':'none';
|
||||||
|
},
|
||||||
|
finalDotStyle(){
|
||||||
|
return {...this.barStyle, width: this.barCalcedWidth + 'px', height: this.finalBarHeight + 'px', opacity: this.showBottomDot ? 1 : 0};
|
||||||
|
},
|
||||||
|
finalTabWidth(){
|
||||||
|
return this._convertTextToPx(this.tabWidth);
|
||||||
|
},
|
||||||
|
finalBarWidth(){
|
||||||
|
return this._convertTextToPx(this._addUnit(this.barWidth, this.unit));
|
||||||
|
},
|
||||||
|
finalBarHeight(){
|
||||||
|
return this._convertTextToPx(this._addUnit(this.barHeight, this.unit));
|
||||||
|
},
|
||||||
|
finalSwiperWidth(){
|
||||||
|
return this._convertTextToPx(this.swiperWidth);
|
||||||
|
},
|
||||||
|
finalBottomSpace(){
|
||||||
|
return this._convertTextToPx(this._addUnit(this.bottomSpace, this.unit));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
//根据swiper的@transition实时更新底部dot位置
|
||||||
|
setDx(dx) {
|
||||||
|
if (!this.shouldSetDx) return;
|
||||||
|
const isLineMode = this.barAnimateMode === 'line';
|
||||||
|
const isWormMode = this.barAnimateMode === 'worm';
|
||||||
|
let dxRate = dx / this.finalSwiperWidth;
|
||||||
|
this.currentSwiperIndex = this.currentIndex + parseInt(dxRate);
|
||||||
|
const isRight = dxRate > 0;
|
||||||
|
const barWidth = this.pxBarWidth;
|
||||||
|
if(this.currentSwiperIndex !== this.currentIndex){
|
||||||
|
dxRate = dxRate - (this.currentSwiperIndex - this.currentIndex);
|
||||||
|
const currentNode = this.itemNodeInfos[this.currentSwiperIndex];
|
||||||
|
if (!!currentNode){
|
||||||
|
this.bottomDotXForIndex = this._getBottomDotX(currentNode, barWidth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const currentIndex = this.currentSwiperIndex;
|
||||||
|
let nextIndex = currentIndex + (isRight ? 1 : -1);
|
||||||
|
nextIndex = Math.max(0, nextIndex);
|
||||||
|
nextIndex = Math.min(nextIndex, this.itemNodeInfos.length - 1);
|
||||||
|
const currentNodeInfo = this.itemNodeInfos[currentIndex];
|
||||||
|
const nextNodeInfo = this.itemNodeInfos[nextIndex];
|
||||||
|
const nextBottomX = this._getBottomDotX(nextNodeInfo, barWidth);
|
||||||
|
if (isLineMode){
|
||||||
|
this.bottomDotX = this.bottomDotXForIndex + (nextBottomX - this.bottomDotXForIndex) * Math.abs(dxRate);
|
||||||
|
} else if (isWormMode) {
|
||||||
|
if ((isRight && currentIndex >= this.itemNodeInfos.length - 1) || (!isRight && currentIndex <= 0)) return;
|
||||||
|
const spaceOffset = isRight ? nextNodeInfo.right - currentNodeInfo.left : currentNodeInfo.right - nextNodeInfo.left;
|
||||||
|
let barCalcedWidth = barWidth + spaceOffset * Math.abs(dxRate);
|
||||||
|
if (isRight) {
|
||||||
|
if (barCalcedWidth > nextBottomX - this.bottomDotX + barWidth) {
|
||||||
|
const barMinusWidth = barWidth + spaceOffset * (1 - dxRate);
|
||||||
|
this.bottomDotX = this.bottomDotXForIndex + (barCalcedWidth - barMinusWidth) / 2;
|
||||||
|
barCalcedWidth = barMinusWidth;
|
||||||
|
}
|
||||||
|
}else if (!isRight) {
|
||||||
|
if (barCalcedWidth > this.bottomDotXForIndex + barWidth - nextBottomX){
|
||||||
|
const barMinusWidth = barWidth + spaceOffset * (1 + dxRate);
|
||||||
|
barCalcedWidth = barMinusWidth;
|
||||||
|
this.bottomDotX = nextBottomX;
|
||||||
|
} else{
|
||||||
|
this.bottomDotX = this.bottomDotXForIndex - (barCalcedWidth - barWidth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
barCalcedWidth = Math.max(barCalcedWidth, barWidth);
|
||||||
|
this.barCalcedWidth = barCalcedWidth;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
//在swiper的@animationfinish中通知z-tabs结束多setDx的锁定,若在父组件中调用了setDx,则必须调用unlockDx
|
||||||
|
unlockDx() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.shouldSetDx = true;
|
||||||
|
})
|
||||||
|
},
|
||||||
|
//更新z-tabs内部布局
|
||||||
|
updateSubviewLayout(tryCount = 0) {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
let delayTime = 10;
|
||||||
|
// #ifdef APP-NVUE || MP-BAIDU
|
||||||
|
delayTime = 50;
|
||||||
|
// #endif
|
||||||
|
setTimeout(() => {
|
||||||
|
this._getNodeClientRect('.z-tabs-scroll-view-conatiner').then(res=>{
|
||||||
|
if (res){
|
||||||
|
if (!res[0].width && tryCount < 10) {
|
||||||
|
setTimeout(() => {
|
||||||
|
tryCount ++;
|
||||||
|
this.updateSubviewLayout(tryCount);
|
||||||
|
}, 50);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.tabsWidth = res[0].width;
|
||||||
|
this.tabsHeight = res[0].height;
|
||||||
|
this.tabsLeft = res[0].left;
|
||||||
|
this._handleListChange(this.list);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this._getNodeClientRect('.z-tabs-conatiner').then(res=>{
|
||||||
|
if(res && res[0].width){
|
||||||
|
this.tabsSuperWidth = res[0].width;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},delayTime)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
//点击了tabs
|
||||||
|
tabsClick(index,item) {
|
||||||
|
if (item.disabled) return;
|
||||||
|
if (this.currentIndex != index) {
|
||||||
|
this.shouldSetDx = false;
|
||||||
|
this.$emit('change', index, item[this.valueKey]);
|
||||||
|
this.currentIndex = index;
|
||||||
|
this._preUpdateDotPosition(index);
|
||||||
|
} else {
|
||||||
|
this.$emit('secondClick',index, item[this.valueKey]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
//scroll-view滚动
|
||||||
|
scroll(e){
|
||||||
|
this.currentScrollLeft = e.detail.scrollLeft;
|
||||||
|
},
|
||||||
|
//锁定dx,用于避免在swiper被动触发滚动时候执行setDx中的代码
|
||||||
|
_lockDx() {
|
||||||
|
this.shouldSetDx = false;
|
||||||
|
},
|
||||||
|
//更新底部dot位置之前的预处理
|
||||||
|
_preUpdateDotPosition(index) {
|
||||||
|
// #ifndef APP-NVUE
|
||||||
|
this.$nextTick(() => {
|
||||||
|
uni.createSelectorQuery().in(this).select(".z-tabs-scroll-view").fields({
|
||||||
|
scrollOffset: true
|
||||||
|
}, data => {
|
||||||
|
if (data) {
|
||||||
|
this.currentScrollLeft = data.scrollLeft;
|
||||||
|
this._updateDotPosition(index);
|
||||||
|
} else {
|
||||||
|
this._updateDotPosition(index);
|
||||||
|
}
|
||||||
|
}).exec();
|
||||||
|
})
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
this._updateDotPosition(index);
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
//更新底部dot位置
|
||||||
|
_updateDotPosition(index){
|
||||||
|
if(index >= this.itemNodeInfos.length) return;
|
||||||
|
this.$nextTick(async ()=>{
|
||||||
|
let node = this.itemNodeInfos[index];
|
||||||
|
let offset = 0;
|
||||||
|
let tabsContainerWidth = this.tabsContainerWidth;
|
||||||
|
if (JSON.stringify(this.activeStyle) !== '{}') {
|
||||||
|
const nodeRes = await this._getNodeClientRect(`#z-tabs-item-${index}`,true);
|
||||||
|
if (nodeRes) {
|
||||||
|
node = nodeRes[0];
|
||||||
|
offset = this.currentScrollLeft;
|
||||||
|
this.tabsHeight = Math.max(node.height + rpx2px(28), this.tabsHeight);
|
||||||
|
tabsContainerWidth = 0;
|
||||||
|
for(let i = 0;i < this.itemNodeInfos.length;i++){
|
||||||
|
let oldNode = this.itemNodeInfos[i];
|
||||||
|
tabsContainerWidth += i === index ? node.width : oldNode.width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (node) {
|
||||||
|
this.bottomDotX = this._getBottomDotX(node, this.finalBarWidth, offset);
|
||||||
|
}
|
||||||
|
this.bottomDotXForIndex = this.bottomDotX;
|
||||||
|
if (this.tabsWidth) {
|
||||||
|
setTimeout(()=>{
|
||||||
|
let scrollLeft = this.bottomDotX - this.tabsWidth / 2 + this.finalBarWidth / 2;
|
||||||
|
scrollLeft = Math.max(0,scrollLeft);
|
||||||
|
if (tabsContainerWidth) {
|
||||||
|
scrollLeft = Math.min(scrollLeft,tabsContainerWidth - this.tabsWidth + 10);
|
||||||
|
}
|
||||||
|
if (this.shouldScroll && tabsContainerWidth > this.tabsWidth) {
|
||||||
|
this.scrollLeft = scrollLeft;
|
||||||
|
}
|
||||||
|
this.$nextTick(()=>{
|
||||||
|
this.isFirstLoaded = true;
|
||||||
|
})
|
||||||
|
},200)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 处理list改变
|
||||||
|
_handleListChange(newVal) {
|
||||||
|
this.$nextTick(async ()=>{
|
||||||
|
if(newVal.length){
|
||||||
|
let itemNodeInfos = [];
|
||||||
|
let tabsContainerWidth = 0;
|
||||||
|
let delayTime = 0;
|
||||||
|
// #ifdef MP-BAIDU
|
||||||
|
delayTime = 100;
|
||||||
|
// #endif
|
||||||
|
setTimeout(async()=>{
|
||||||
|
for(let i = 0;i < newVal.length;i++){
|
||||||
|
const nodeRes = await this._getNodeClientRect(`#z-tabs-item-${i}`,true);
|
||||||
|
if(nodeRes){
|
||||||
|
const node = nodeRes[0];
|
||||||
|
node.left += this.currentScrollLeft;
|
||||||
|
itemNodeInfos.push(node);
|
||||||
|
tabsContainerWidth += node.width;
|
||||||
|
}
|
||||||
|
if (i === this.currentIndex){
|
||||||
|
this.itemNodeInfos = itemNodeInfos;
|
||||||
|
this.tabsContainerWidth = tabsContainerWidth;
|
||||||
|
this._updateDotPosition(this.currentIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.itemNodeInfos = itemNodeInfos;
|
||||||
|
this.tabsContainerWidth = tabsContainerWidth;
|
||||||
|
this._updateDotPosition(this.currentIndex);
|
||||||
|
},delayTime)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (this.initTriggerChange && this.changeTriggerFailed && newVal.length) {
|
||||||
|
if (this.current < newVal.length) {
|
||||||
|
this.$emit('change', this.current, newVal[this.current][this.valueKey]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
//根据node获取bottomX
|
||||||
|
_getBottomDotX(node, barWidth = this.finalBarWidth, offset = 0){
|
||||||
|
return node.left + node.width / 2 - barWidth / 2 + offset - this.tabsLeft;
|
||||||
|
},
|
||||||
|
//获取节点信息
|
||||||
|
_getNodeClientRect(select, withRefArr = false) {
|
||||||
|
// #ifdef APP-NVUE
|
||||||
|
select = select.replace('.', '').replace('#', '');
|
||||||
|
const ref = withRefArr ? this.$refs[select][0] : this.$refs[select];
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (ref) {
|
||||||
|
weexDom.getComponentRect(ref, option => {
|
||||||
|
if (option && option.result) {
|
||||||
|
resolve([option.size]);
|
||||||
|
} else resolve(false);
|
||||||
|
})
|
||||||
|
} else resolve(false);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
// #endif
|
||||||
|
const res = uni.createSelectorQuery().in(this);
|
||||||
|
res.select(select).boundingClientRect();
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
res.exec(data => {
|
||||||
|
resolve((data && data != '' && data != undefined && data.length) ? data : false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
//格式化badge中的count
|
||||||
|
_formatCount(count) {
|
||||||
|
if (!count) return '';
|
||||||
|
if (count > this.badgeMaxCount) {
|
||||||
|
return this.badgeMaxCount + '+';
|
||||||
|
}
|
||||||
|
return count.toString();
|
||||||
|
},
|
||||||
|
//将文本的px或者rpx转为px的值
|
||||||
|
_convertTextToPx(text) {
|
||||||
|
const dataType = Object.prototype.toString.call(text);
|
||||||
|
if (dataType === '[object Number]') {
|
||||||
|
return rpx2px(text);
|
||||||
|
}
|
||||||
|
let isRpx = false;
|
||||||
|
if (text.indexOf('rpx') !== -1 || text.indexOf('upx') !== -1) {
|
||||||
|
text = text.replace('rpx', '').replace('upx', '');
|
||||||
|
isRpx = true;
|
||||||
|
} else if (text.indexOf('px') !== -1) {
|
||||||
|
text = text.replace('px', '');
|
||||||
|
} else {
|
||||||
|
text = rpx2px(text);
|
||||||
|
}
|
||||||
|
if (!isNaN(text)) {
|
||||||
|
if (isRpx) return Number(rpx2px(text));
|
||||||
|
return Number(text);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
},
|
||||||
|
// 添加单位
|
||||||
|
_addUnit(value, unit) {
|
||||||
|
if (Object.prototype.toString.call(value) === '[object String]') {
|
||||||
|
let tempValue = value;
|
||||||
|
tempValue = tempValue.replace('rpx', '').replace('upx', '').replace('px', '');
|
||||||
|
if (value.indexOf('rpx') === -1 && value.indexOf('upx') === -1 && value.indexOf('px') !== -1) {
|
||||||
|
tempValue = parseFloat(tempValue) * 2;
|
||||||
|
}
|
||||||
|
value = tempValue;
|
||||||
|
}
|
||||||
|
return unit === 'rpx' ? value + 'rpx' : (value / 2) + 'px';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.z-tabs-conatiner{
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
/* #endif */
|
||||||
|
/* #ifdef APP-NVUE */
|
||||||
|
width: 750rpx;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.z-tabs-scroll-view-conatiner{
|
||||||
|
flex: 1;
|
||||||
|
position: relative;
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
.z-tabs-scroll-view ::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
width: 0 !important;
|
||||||
|
height: 0 !important;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
/* #endif */
|
||||||
|
|
||||||
|
.z-tabs-scroll-view{
|
||||||
|
flex-direction: row;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
/* #endif */
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.z-tabs-list-container{
|
||||||
|
position: relative;
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
height: 100%;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
.z-tabs-list,.z-tabs-list-container{
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.z-tabs-item{
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0px 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.z-tabs-item-title-container{
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.z-tabs-item-title-rpx{
|
||||||
|
font-size: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.z-tabs-item-title-px{
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.z-tabs-item-title-disabled{
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
cursor: not-allowed;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
.z-tabs-item-badge{
|
||||||
|
background-color: #ec5b56;
|
||||||
|
color: white;
|
||||||
|
border-radius: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.z-tabs-item-badge-rpx{
|
||||||
|
margin-left: 8rpx;
|
||||||
|
font-size: 22rpx;
|
||||||
|
padding: 0rpx 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.z-tabs-item-badge-px{
|
||||||
|
margin-left: 4px;
|
||||||
|
font-size: 11px;
|
||||||
|
padding: 0px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.z-tabs-bottom{
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.z-tabs-bottom-dot{
|
||||||
|
border-radius: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.z-tabs-left,.z-tabs-right{
|
||||||
|
/* #ifndef APP-NVUE */
|
||||||
|
display: flex;
|
||||||
|
/* #endif */
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
{
|
||||||
|
"id": "z-tabs",
|
||||||
|
"name": "z-tabs",
|
||||||
|
"displayName": "【z-tabs】一个简单轻量的tabs组件",
|
||||||
|
"version": "0.3.0",
|
||||||
|
"description": "全平台兼容,支持nvue、vue3",
|
||||||
|
"keywords": [
|
||||||
|
"tabs"
|
||||||
|
],
|
||||||
|
"repository": "https://github.com/SmileZXLee/uni-z-tabs",
|
||||||
|
"engines": {
|
||||||
|
"HBuilderX": "^3.0.7"
|
||||||
|
},
|
||||||
|
"dcloudext": {
|
||||||
|
"sale": {
|
||||||
|
"regular": {
|
||||||
|
"price": "0.00"
|
||||||
|
},
|
||||||
|
"sourcecode": {
|
||||||
|
"price": "0.00"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"contact": {
|
||||||
|
"qq": "393727164"
|
||||||
|
},
|
||||||
|
"declaration": {
|
||||||
|
"ads": "无",
|
||||||
|
"data": "无",
|
||||||
|
"permissions": "无"
|
||||||
|
},
|
||||||
|
"npmurl": "https://www.npmjs.com/package/@zxlee/z-tabs",
|
||||||
|
"type": "component-vue"
|
||||||
|
},
|
||||||
|
"uni_modules": {
|
||||||
|
"dependencies": [],
|
||||||
|
"encrypt": [],
|
||||||
|
"platforms": {
|
||||||
|
"cloud": {
|
||||||
|
"tcb": "y",
|
||||||
|
"aliyun": "y",
|
||||||
|
"alipay": "n"
|
||||||
|
},
|
||||||
|
"client": {
|
||||||
|
"App": {
|
||||||
|
"app-vue": "y",
|
||||||
|
"app-nvue": "y"
|
||||||
|
},
|
||||||
|
"H5-mobile": {
|
||||||
|
"Safari": "y",
|
||||||
|
"Android Browser": "y",
|
||||||
|
"微信浏览器(Android)": "y",
|
||||||
|
"QQ浏览器(Android)": "y"
|
||||||
|
},
|
||||||
|
"H5-pc": {
|
||||||
|
"Chrome": "y",
|
||||||
|
"IE": "y",
|
||||||
|
"Edge": "y",
|
||||||
|
"Firefox": "y",
|
||||||
|
"Safari": "y"
|
||||||
|
},
|
||||||
|
"小程序": {
|
||||||
|
"微信": "y",
|
||||||
|
"阿里": "y",
|
||||||
|
"百度": "y",
|
||||||
|
"字节跳动": "y",
|
||||||
|
"QQ": "y",
|
||||||
|
"钉钉": "y",
|
||||||
|
"快手": "y",
|
||||||
|
"飞书": "y",
|
||||||
|
"京东": "y"
|
||||||
|
},
|
||||||
|
"快应用": {
|
||||||
|
"华为": "y",
|
||||||
|
"联盟": "y"
|
||||||
|
},
|
||||||
|
"Vue": {
|
||||||
|
"vue2": "y",
|
||||||
|
"vue3": "y"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,177 @@
|
||||||
|
# z-tabs
|
||||||
|
|
||||||
|
[](https://github.com/SmileZXLee/uni-z-tabs)
|
||||||
|
[](https://en.wikipedia.org/wiki/MIT_License)
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
### 反馈qq群(点击加群):[371624008](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=avPmibADf2TNi4LxkIwjCE5vbfXpa-r1&authKey=dQ%2FVDAR87ONxI4b32Py%2BvmXbhnopjHN7%2FJPtdsqJdsCPFZB6zDQ17L06Uh0kITUZ&noverify=0&group_code=371624008)
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
## z-tabs文档
|
||||||
|
|
||||||
|
### 安装
|
||||||
|
|
||||||
|
#### 方式1(推荐):通过uni_modules安装,在插件市场中点击右上角【使用HbuilderX导入插件】即可。
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
#### 方式2:通过npm安装
|
||||||
|
|
||||||
|
```bash
|
||||||
|
//若项目之前未使用npm管理依赖(项目根目录下无package.json文件),先在项目根目录执行命令初始化npm工程
|
||||||
|
npm init -y
|
||||||
|
|
||||||
|
//安装
|
||||||
|
npm install @zxlee/z-tabs --save
|
||||||
|
//更新
|
||||||
|
npm update @zxlee/z-tabs
|
||||||
|
```
|
||||||
|
|
||||||
|
然后在`pages.json`中配置`easycom`(注意:下方配置只有在使用npm安装时才需要配置!!!!!)
|
||||||
|
|
||||||
|
```json
|
||||||
|
"easycom": {
|
||||||
|
"^z-tabs": "@zxlee/z-tabs/components/z-tabs/z-tabs.vue"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 基本使用
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<z-tabs :list="list"></z-tabs>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
list: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLoad() {
|
||||||
|
const list = [];
|
||||||
|
for(let i = 0;i < 10;i++) {
|
||||||
|
// list内item支持字符串或对象,下方这个是字符串
|
||||||
|
list.push('tab标题');
|
||||||
|
|
||||||
|
// 如果要展示徽标数,则list中item的数据结构应为:
|
||||||
|
list.push({
|
||||||
|
name: 'tab标题',
|
||||||
|
badge: {
|
||||||
|
// 设置徽标数为6
|
||||||
|
count: 6
|
||||||
|
},
|
||||||
|
// 可以禁用某个item
|
||||||
|
disabled: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.list = list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### props
|
||||||
|
|
||||||
|
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|
||||||
|
| :------------------ | :----------------------------------------------------------- | :------------- | :------ | :----- |
|
||||||
|
| list | 数据源数组,支持形如`['tab1','tab2']`的格式或`[{name:'tab1',value:1}]`的格式 | Array | [] | - |
|
||||||
|
| current | 当前选中的index | Number\|String | 0 | - |
|
||||||
|
| scroll-count | list数组长度超过scrollCount时滚动显示(不自动铺满全屏) | Number\|String | 5 | - |
|
||||||
|
| tab-width | 自定义每个tab的宽度,默认为0,即代表根据内容自动撑开,单位rpx,支持传100、"100px"或"100rpx" | Number\|String | 0 | 0 |
|
||||||
|
| bar-width | 滑块宽度,单位rpx,支持传100、"100px"或"100rpx" | Number\|String | 45rpx | - |
|
||||||
|
| bar-height | 滑块高度,单位rpx,支持传100、"100px"或"100rpx" | Number\|String | 8rpx | - |
|
||||||
|
| bar-style | 滑块样式,其中的`width`和`height`将被`bar-width`和`bar-height`覆盖 | Object | {} | - |
|
||||||
|
| bottom-space | tabs与底部的间距,单位rpx,支持传100、"100px"或"100rpx" | Number\|String | 8rpx | - |
|
||||||
|
| bar-animate-mode | 【v0.1.5起支持】切换tab时滑块动画模式,与`swiper`联动时有效,点击切换tab时无效,必须调用`setDx`。默认为`line`,即切换tab时滑块宽度保持不变,线性运动。可选值为`worm`,即为类似毛毛虫蠕动效果 | String | line | worm |
|
||||||
|
| name-key | list中item的name(标题)的key | String | name | - |
|
||||||
|
| value-key | list中item的value的key | String | value | - |
|
||||||
|
| active-color | 激活状态tab的颜色 | String | #007AFF | - |
|
||||||
|
| inactive-color | 未激活状态tab的颜色 | String | #666666 | - |
|
||||||
|
| disabled-color | 禁用状态tab的颜色 | String | #bbbbbb | - |
|
||||||
|
| active-style | 激活状态tab的样式 | Object | {} | - |
|
||||||
|
| inactive-style | 未激活状态tab的样式 | Object | {} | - |
|
||||||
|
| disabled-style | 禁用状态tab的样式 | Object | {} | - |
|
||||||
|
| badge-max-count | 徽标数最大数字限制,超过这个数字将变成`badge-max-count`+ | Number\|String | 99 | - |
|
||||||
|
| badge-style | 徽标样式,例如可自定义背景色,字体等等 | Object | {} | - |
|
||||||
|
| bg-color | z-tabs背景色 | String | white | - |
|
||||||
|
| tabs-style | z-tabs样式 | Object | {} | - |
|
||||||
|
| init-trigger-change | 初始化时是否自动触发change事件 | Boolean | true | false |
|
||||||
|
| unit | z-tabs中布局的单位,默认为rpx | String | rpx | px |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### events
|
||||||
|
|
||||||
|
| 事件名 | 说明 | 回调参数 |
|
||||||
|
| ------------ | -------------------- | ------------------------------------------------------------ |
|
||||||
|
| @change | tabs改变(点击)时触发 | `参数1`:index(当前切换到的index);<br/>`参数2`:value(当前切换到的value) |
|
||||||
|
| @secondClick | tabs二次点击时触发 | `参数1`:index(当前切换到的index);<br/>`参数2`:value(当前切换到的value) |
|
||||||
|
|
||||||
|
### methods
|
||||||
|
|
||||||
|
| 方法名 | 说明 | 参数 |
|
||||||
|
| ------------------- | ------------------------------------------------------------ | -------------------------------------- |
|
||||||
|
| setDx | 根据swiper的`@transition`实时更新底部dot位置 | swiper的`@transition`中的`e.detail.dx` |
|
||||||
|
| unlockDx | 在swiper的`@animationfinish`中通知`z-tabs`结束多`setDx`的锁定,若在父组件中调用了`setDx`,则必须调用`unlockDx` | - |
|
||||||
|
| updateSubviewLayout | 在nvue+安卓中,若在cell中使用`z-tabs`,且页面加载时cell在屏幕之外,因cell的复用机制,可能导致`z-tabs`内部的布局失效:例如底部bar无法显示,此时可在list滚动到一定区域内(例如快显示`z-tabs`)的时候调用此方法以更新其内部布局。其他情况无需调用! | - |
|
||||||
|
|
||||||
|
### slots
|
||||||
|
|
||||||
|
| 名称 | 说明 |
|
||||||
|
| :---- | ------------ |
|
||||||
|
| left | tabs左侧插槽 |
|
||||||
|
| right | tabs右侧插槽 |
|
||||||
|
|
||||||
|
### 支持全局配置
|
||||||
|
|
||||||
|
* 在`/z-tabs/components/z-tabs/config/index.js`文件中进行配置
|
||||||
|
|
||||||
|
```js
|
||||||
|
export default {
|
||||||
|
'active-color': 'red'
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 【v0.1.4起支持】底部dot与swiper联动演示
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<z-tabs ref="tabs" :list="tabList" :current="current" @change="tabsChange" />
|
||||||
|
<swiper :current="current" @transition="swiperTransition" @animationfinish="swiperAnimationfinish">
|
||||||
|
<swiper-item class="swiper-item" v-for="(item, index) in tabList" :key="index">
|
||||||
|
xxx
|
||||||
|
</swiper-item>
|
||||||
|
</swiper>
|
||||||
|
<template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
tabList: ['测试1','测试2','测试3','测试4'],
|
||||||
|
current: 0, // tabs组件的current值,表示当前活动的tab选项
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
//tabs通知swiper切换
|
||||||
|
tabsChange(index) {
|
||||||
|
this.current = index;
|
||||||
|
},
|
||||||
|
//swiper滑动中
|
||||||
|
swiperTransition(e) {
|
||||||
|
this.$refs.tabs.setDx(e.detail.dx);
|
||||||
|
},
|
||||||
|
//swiper滑动结束
|
||||||
|
swiperAnimationfinish(e) {
|
||||||
|
this.current = e.detail.current;
|
||||||
|
this.$refs.tabs.unlockDx();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
@ -204,6 +204,15 @@
|
||||||
"path": "home/major/index",
|
"path": "home/major/index",
|
||||||
"type": "page",
|
"type": "page",
|
||||||
"layout": "page",
|
"layout": "page",
|
||||||
|
"style": {
|
||||||
|
"navigationStyle": "custom"
|
||||||
|
},
|
||||||
|
"needLogin": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "home/major/info",
|
||||||
|
"type": "page",
|
||||||
|
"layout": "page",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationStyle": "custom"
|
"navigationStyle": "custom"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
<HomeSubMenu />
|
<HomeSubMenu />
|
||||||
<HotRank />
|
<HotRank />
|
||||||
<Consultation />
|
<Consultation />
|
||||||
<Fab />
|
<FabButton :initial-x="0" :initial-y="100" />
|
||||||
</view>
|
</view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
<TabBar :current-page="0"></TabBar>
|
<TabBar :current-page="0"></TabBar>
|
||||||
|
|
@ -41,7 +41,7 @@ import Banner from '@/components/home/Banner.vue'
|
||||||
import HomeSubMenu from '@/components/home/SubMenu.vue'
|
import HomeSubMenu from '@/components/home/SubMenu.vue'
|
||||||
import HotRank from '@/components/home/HotRank.vue'
|
import HotRank from '@/components/home/HotRank.vue'
|
||||||
import Consultation from '@/components/home/Consultation.vue'
|
import Consultation from '@/components/home/Consultation.vue'
|
||||||
import Fab from '@/components/fab/Fab.vue'
|
import FabButton from '@/components/fab/FabButton.vue'
|
||||||
|
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -153,3 +153,20 @@ export const getAdmissionMark = (params: {
|
||||||
export const deleteUnCollection = (params: { wxId: number; uId: number }) => {
|
export const deleteUnCollection = (params: { wxId: number; uId: number }) => {
|
||||||
return http.post('/api/unCollection/delete', params)
|
return http.post('/api/unCollection/delete', params)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const getMajorDetail = (params: { SpecId: string }) => {
|
||||||
|
return http.get('/api/zhiYuan/majorDetail', params)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getMajorCourse = (params: { SpecId: string }) => {
|
||||||
|
return http.get('/api/zhiYuan/zkskcMajor', params)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 专业关联院校
|
||||||
|
export const getMajorUniversityList = (params: { SpecId: string }) => {
|
||||||
|
return http.get('/api/zhiYuan/zksyxMajor', params)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getCareerProspects = (params: { zydm: string }) => {
|
||||||
|
return http.get('/api/zhiYuan/careerProspects', params)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ interface NavigateToOptions {
|
||||||
"/pages-sub/home/inputScore/index" |
|
"/pages-sub/home/inputScore/index" |
|
||||||
"/pages-sub/home/line/index" |
|
"/pages-sub/home/line/index" |
|
||||||
"/pages-sub/home/major/index" |
|
"/pages-sub/home/major/index" |
|
||||||
|
"/pages-sub/home/major/info" |
|
||||||
"/pages-sub/home/news/index" |
|
"/pages-sub/home/news/index" |
|
||||||
"/pages-sub/home/news/newsList" |
|
"/pages-sub/home/news/newsList" |
|
||||||
"/pages-sub/home/rank/index" |
|
"/pages-sub/home/rank/index" |
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue