feat: 当前志愿表编写中
parent
e3977c7e89
commit
7c0357b67d
|
|
@ -7,7 +7,7 @@
|
|||
}
|
||||
</route>
|
||||
<template>
|
||||
<view class="bg-[#FAFAFA]">
|
||||
<view class="bg-[#FAFAFA] h-screen flex flex-col">
|
||||
<view class="text-[#000] text-[24rpx] p-[32rpx]">
|
||||
{{ userInfo.estimatedAchievement.expectedScore }}分{{
|
||||
userInfo.estimatedAchievement.subjectGroup.split(',').join('/')
|
||||
|
|
@ -47,7 +47,9 @@
|
|||
</view>
|
||||
</view>
|
||||
|
||||
<view class="mt-[32rpx] bg-[#fff] rounded-[16rpx] p-[32rpx] box-shadow px-[32rpx] pt-[32rpx]">
|
||||
<view
|
||||
class="mt-auto bg-[#fff] rounded-[16rpx] p-[32rpx] box-shadow px-[32rpx] pt-[32rpx] pb-safe"
|
||||
>
|
||||
<view
|
||||
class="text-[#fff] text-[32rpx] rounded-[8rpx] bg-[#1580FF] text-center py-[26rpx]"
|
||||
@click="navigatorTo"
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
defineProps<{
|
||||
const props = defineProps<{
|
||||
show: boolean
|
||||
title?: string
|
||||
lazyRender?: boolean
|
||||
|
|
|
|||
|
|
@ -0,0 +1,70 @@
|
|||
<template>
|
||||
<div class="collapse-container">
|
||||
<div class="collapse-header" @click="toggleCollapse">
|
||||
<slot name="header"></slot>
|
||||
<div class="collapse-icon" :class="{ 'is-active': isCollapsed }">
|
||||
<i class="el-icon-arrow-down"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="collapse-content" :class="{ 'is-collapsed': isCollapsed }">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Collapse',
|
||||
props: {
|
||||
defaultCollapsed: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isCollapsed: this.defaultCollapsed,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggleCollapse() {
|
||||
this.isCollapsed = !this.isCollapsed
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.collapse-container {
|
||||
display: grid;
|
||||
grid-template-rows: auto 1fr;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.collapse-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
cursor: pointer;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.collapse-icon {
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.collapse-icon.is-active {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.collapse-content {
|
||||
overflow: hidden;
|
||||
transition: grid-template-rows 0.3s ease;
|
||||
grid-template-rows: 1fr;
|
||||
}
|
||||
|
||||
.collapse-content.is-collapsed {
|
||||
grid-template-rows: 0fr;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,754 @@
|
|||
<template>
|
||||
<view
|
||||
class="leo-drag"
|
||||
id="leo-drag"
|
||||
ref="leoDragView"
|
||||
:style="[{ 'touch-action': isStopPropagation ? 'none' : 'auto' }]"
|
||||
>
|
||||
<!-- touch-action: 阻止滚动 -->
|
||||
<movable-area :style="[getAreaStyle]" v-if="showArea">
|
||||
<movable-view
|
||||
v-if="isStopPropagation"
|
||||
v-for="(item, index) in showList"
|
||||
:animation="animation"
|
||||
:direction="direction"
|
||||
:key="item.key"
|
||||
:damping="damping"
|
||||
:x="item.x"
|
||||
:y="item.y"
|
||||
:disabled="longpress ? disabled : false"
|
||||
@longpress="controlLongpress(index)"
|
||||
@touchstart.stop="handleDragStart($event, index)"
|
||||
@change="handleMoving"
|
||||
@touchend="handleDragEnd"
|
||||
:style="[
|
||||
{ 'z-index': activeIndex === index ? 9 : 1 },
|
||||
{ top: activeIndex === index ? scrollInfo.y + 'px' : 0 },
|
||||
getItemStyle,
|
||||
isList ? { height: item.height + 'px' } : {},
|
||||
]"
|
||||
class="base-drag-wrapper"
|
||||
>
|
||||
<view class="slotContent" ref="slotContent" :style="[slotContentStyle]">
|
||||
<slot :data="{ ...item, index, activeIndex, moveToIndex }" name="content"></slot>
|
||||
</view>
|
||||
<view
|
||||
v-if="showPlaceholder(index)"
|
||||
class="placeholder"
|
||||
:style="{ height: showList[activeIndex]?.height + 'px', top: placeholderTopValue + 'px' }"
|
||||
>
|
||||
<slot name="placeholder"></slot>
|
||||
</view>
|
||||
</movable-view>
|
||||
<movable-view
|
||||
v-else
|
||||
v-for="(item, index) in showList"
|
||||
:animation="animation"
|
||||
:direction="direction"
|
||||
:key="`${item.key}-${index}`"
|
||||
:damping="damping"
|
||||
:x="item.x"
|
||||
:y="item.y"
|
||||
:disabled="longpress ? disabled : false"
|
||||
@longpress="controlLongpress(index)"
|
||||
@touchstart="handleDragStart($event, index)"
|
||||
@change="handleMoving"
|
||||
@touchend="handleDragEnd"
|
||||
:style="[
|
||||
{ 'z-index': activeIndex === index ? 9 : 1 },
|
||||
{ top: activeIndex === index ? scrollInfo.y + 'px' : 0 },
|
||||
getItemStyle,
|
||||
isList ? { height: item.height + 'px' } : {},
|
||||
]"
|
||||
class="base-drag-wrapper"
|
||||
>
|
||||
<view class="slotContent" ref="slotContent" :style="[slotContentStyle]">
|
||||
<slot :data="{ ...item, index, activeIndex, moveToIndex }" name="content"></slot>
|
||||
</view>
|
||||
<view
|
||||
v-if="showPlaceholder(index)"
|
||||
class="placeholder"
|
||||
:style="{ height: showList[activeIndex]?.height + 'px', top: placeholderTopValue + 'px' }"
|
||||
>
|
||||
<slot name="placeholder"></slot>
|
||||
</view>
|
||||
</movable-view>
|
||||
</movable-area>
|
||||
<!-- 可用于遮罩指引提示,考虑定位的zindex问题,所以使用插槽插进来 -->
|
||||
<slot name="custom"></slot>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch, nextTick, onMounted, getCurrentInstance } from 'vue'
|
||||
import { deepCopy } from './useSort'
|
||||
|
||||
// #ifdef APP-NVUE
|
||||
const dom = uni.requireNativePlugin('dom') // 引入原生插件
|
||||
// #endif
|
||||
|
||||
// 定义MovableViewDirection类型,匹配期望的字面量联合类型
|
||||
type MovableViewDirection = 'all' | 'vertical' | 'horizontal' | 'none'
|
||||
|
||||
interface ItemType {
|
||||
key?: string
|
||||
x?: number
|
||||
y?: number
|
||||
height?: number
|
||||
dropId?: number
|
||||
[key: string]: any // 添加索引签名,允许访问任何属性
|
||||
}
|
||||
|
||||
interface ScrollInfoType {
|
||||
x: number
|
||||
y: number
|
||||
}
|
||||
|
||||
interface PositionType {
|
||||
y: number
|
||||
}
|
||||
|
||||
const props = defineProps({
|
||||
slotContentStyle: {
|
||||
// 自定义slotContent的样式,列表的每个父级样式
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
list: {
|
||||
// 列表
|
||||
type: Array as () => ItemType[],
|
||||
default: () => [],
|
||||
},
|
||||
column: {
|
||||
// 每行显示多少数量,如果是单项(column:1),可根据自定义高度动态变化,并且可拖拽滚动列表;
|
||||
type: Number,
|
||||
default: 1,
|
||||
},
|
||||
height: {
|
||||
// 可拖拽的区域宽度,auto 为根据子级高度(itemHeight)计算
|
||||
type: String,
|
||||
default: 'auto',
|
||||
},
|
||||
itemHeight: {
|
||||
// 每个子元素的高度,为auto时,计算最高元素
|
||||
type: String,
|
||||
default: 'auto',
|
||||
},
|
||||
direction: {
|
||||
// 可拖动方向
|
||||
type: String as () => MovableViewDirection,
|
||||
default: 'all',
|
||||
validator: (value: string) => {
|
||||
return ['all', 'vertical', 'horizontal', 'none'].includes(value)
|
||||
},
|
||||
},
|
||||
dragDirection: {
|
||||
// 目前拖动方向 upward-向上, down-向下
|
||||
type: String,
|
||||
default: 'down',
|
||||
},
|
||||
animation: {
|
||||
// 拖动时开启动画
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
damping: {
|
||||
// 用于控制x或y改变时的动画和过界回弹的动画
|
||||
type: Number,
|
||||
default: 20,
|
||||
},
|
||||
swapMode: {
|
||||
// 替换模式:true:位置后排,false:两位替换
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
longpress: {
|
||||
// 是否禁用
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
supportLongpress: {
|
||||
// 是否支持长按
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
isStopPropagation: {
|
||||
// 是否阻止事件冒泡: 可用于判断是否拖拽状态
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
})
|
||||
|
||||
const emit = defineEmits([
|
||||
'getAreaStyle',
|
||||
'getItemStyle',
|
||||
'pressStart',
|
||||
'handleDragStart',
|
||||
'handleMoving',
|
||||
'handleDragEnd',
|
||||
'getList',
|
||||
'update:list',
|
||||
'getItemHeight',
|
||||
])
|
||||
|
||||
// 状态变量
|
||||
const showList = ref<ItemType[]>([]) // 显示的数据;最终都会根据cloneList赋值
|
||||
const cloneList = ref<ItemType[]>([]) // 为了不影响视图突兀变化,使用cloneList代替showList的数据下标变化;cloneList的数据会比showList优先变化
|
||||
const disabled = ref(true) // 是否允许拖动
|
||||
const activeIndex = ref(-1) // 当前拖动的item
|
||||
const moveToIndex = ref(-1) // 当前拖动的item > 拖动到那一块: 也就是下一块item
|
||||
const oldIndex = ref(-1) // 上一块item的位置
|
||||
const tempDragInfo = ref({
|
||||
// 计算拖动的值
|
||||
x: '',
|
||||
y: '',
|
||||
})
|
||||
const oldPosition = ref<PositionType>({ y: 0 }) // 触边时滚动位置
|
||||
const itemMaxHeight = ref('80px')
|
||||
const width = ref('100%')
|
||||
const showArea = ref(false) // 在nvue,会出现空白或者部分元素不显示的问题
|
||||
const viewMaxHeight = ref(80) // 全部视图高度,仅在isList === true时,使用
|
||||
const activeY = ref(0) // 获得下标的y轴
|
||||
const scrollInfo = ref<ScrollInfoType>({ x: 0, y: 0 }) // 滚动产生的信息
|
||||
|
||||
// refs
|
||||
const leoDragView = ref<any>(null)
|
||||
const slotContent = ref<any[]>([])
|
||||
|
||||
const instance = getCurrentInstance()
|
||||
|
||||
// 拿到活动下标的高度
|
||||
const placeholderTopValue = computed(() => {
|
||||
let height = 0
|
||||
try {
|
||||
if (showList.value && showList.value[activeIndex.value]) {
|
||||
height = -showList.value[activeIndex.value].height!
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('eee', e)
|
||||
}
|
||||
return height
|
||||
})
|
||||
|
||||
// 单独一排: 则不需要计算
|
||||
const isList = computed(() => {
|
||||
let is = false
|
||||
// #ifndef APP-NVUE
|
||||
is = props.column === 1 // 说明是列表
|
||||
// #endif
|
||||
return is
|
||||
})
|
||||
|
||||
// 设置每个item的高度。如果是列表(isList === true)则忽略 --- 默认获取最高的item
|
||||
const getItemHeight = computed(() => {
|
||||
// 获取item的高度
|
||||
let value =
|
||||
props.itemHeight === 'auto' ? parseFloat(itemMaxHeight.value) : parseFloat(props.itemHeight)
|
||||
emit('getItemHeight', value)
|
||||
return value
|
||||
})
|
||||
|
||||
// 设置item的宽度。
|
||||
const getItemWidth = computed(() => {
|
||||
// 获取item的宽度
|
||||
const w = getRealWidth(width.value)
|
||||
return (parseFloat(w) / props.column).toFixed(2)
|
||||
})
|
||||
|
||||
// 给拖动区域设置宽高
|
||||
const getAreaStyle = computed(() => {
|
||||
// 给可拖动区域设置宽高
|
||||
const w = getRealWidth(width.value)
|
||||
let h: string | number = props.height
|
||||
if (h === 'auto') {
|
||||
// 长度/横排的数量 * 高度 = 总高度; 不能使用viewMaxHeight的高度,因为这是根据每个item的高度分别增加的,而不是根据 最高的item增加的。
|
||||
h = isList.value
|
||||
? viewMaxHeight.value
|
||||
: Math.ceil(showList.value.length / props.column) * getItemHeight.value
|
||||
}
|
||||
let style = {
|
||||
width: w + 'px',
|
||||
height: typeof h === 'number' ? h + 'px' : h,
|
||||
}
|
||||
emit('getAreaStyle', style)
|
||||
return style
|
||||
})
|
||||
|
||||
// 给item设置高度和宽度
|
||||
const getItemStyle = computed(() => {
|
||||
let itemHeightWidth = {
|
||||
width: getItemWidth.value + 'px',
|
||||
height: getItemHeight.value + 'px',
|
||||
}
|
||||
emit('getItemStyle', itemHeightWidth)
|
||||
return itemHeightWidth
|
||||
})
|
||||
|
||||
// 获取实际的宽度
|
||||
const getRealWidth = (w: string | number): string => {
|
||||
let width = w + ''
|
||||
if (width.includes('%')) {
|
||||
const windowWidth = uni.getSystemInfoSync().windowWidth
|
||||
width = (windowWidth * (parseFloat(width) / 100)).toString()
|
||||
}
|
||||
return width
|
||||
}
|
||||
|
||||
// 省略初始化时添加的 x,y和key等参数
|
||||
const omit = (obj: any, args: string[] = ['x', 'y', 'key', 'dropId', 'height']) => {
|
||||
if (!args) return obj
|
||||
const newObj: any = {}
|
||||
const isString = typeof args === 'string'
|
||||
const keys = Object.keys(obj).filter((item) => {
|
||||
if (isString) {
|
||||
return item !== args
|
||||
}
|
||||
return !args.includes(item)
|
||||
})
|
||||
|
||||
keys.forEach((key) => {
|
||||
if (obj[key] !== undefined) newObj[key] = obj[key]
|
||||
})
|
||||
return newObj
|
||||
}
|
||||
|
||||
// 获取当前的位置
|
||||
const getPosition = (index: number, list = cloneList.value): [number, number] => {
|
||||
// 通过计算重新算换 偏移单位。
|
||||
let x = (index % props.column) * Number(getItemWidth.value)
|
||||
let y = 0
|
||||
if (isList.value) {
|
||||
// 如果是 单项数据时,不需要通过getItemHeight来排,而是需要根据每个item的高度自动填充
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
if (index === i) break
|
||||
y += list[i].height!
|
||||
}
|
||||
} else {
|
||||
// 根据最高的item来决定整体的高度
|
||||
y = Math.floor(index / props.column) * getItemHeight.value
|
||||
}
|
||||
return [x, y]
|
||||
}
|
||||
|
||||
// 初始化
|
||||
const initList = (list: ItemType[] = [], changeheight: boolean = false) => {
|
||||
const newList = deepCopy(list)
|
||||
// 给每个item添加一x,y和key
|
||||
showList.value = newList.map((item, index) => {
|
||||
const [x, y] = getPosition(index)
|
||||
let data = {
|
||||
...item,
|
||||
x,
|
||||
y,
|
||||
dropId: index + 1,
|
||||
}
|
||||
let key = 'slot' + Math.random() + index
|
||||
// 如果x轴和y轴没变,那么不用更新key来刷新状态
|
||||
if (x === item?.x && y === item?.y) {
|
||||
if (activeIndex.value !== index) {
|
||||
// 非当前点击的下标和目标下标的下标不需要生成新的key
|
||||
key = item.key
|
||||
}
|
||||
}
|
||||
// 判断拖动位置的元素是那个
|
||||
data.key = key
|
||||
return data
|
||||
})
|
||||
cloneList.value = deepCopy(showList.value)
|
||||
nextTick(() => {
|
||||
showArea.value = true
|
||||
})
|
||||
|
||||
if (changeheight && props.itemHeight === 'auto') {
|
||||
// 获取到最高的item
|
||||
nextTick(() => {
|
||||
setTimeout(async () => {
|
||||
// #ifdef APP-NVUE
|
||||
showArea.value = false
|
||||
let max = 0
|
||||
for (let i = 0; i < slotContent.value.length; i++) {
|
||||
// 循环 需要异步处理
|
||||
await new Promise<void>((resolve) => {
|
||||
let viewMaxHeightVal = 0
|
||||
dom.getComponentRect(slotContent.value[i], (res: any) => {
|
||||
let size = res.size
|
||||
if (isList.value) {
|
||||
cloneList.value[i].height = size.height
|
||||
}
|
||||
viewMaxHeightVal += size.height
|
||||
if (size.height > max) {
|
||||
max = size.height
|
||||
}
|
||||
resolve()
|
||||
})
|
||||
viewMaxHeight.value = viewMaxHeightVal
|
||||
})
|
||||
}
|
||||
itemMaxHeight.value = max + 'px'
|
||||
nextTick(() => {
|
||||
initList(cloneList.value)
|
||||
})
|
||||
// #endif
|
||||
|
||||
// #ifndef APP-NVUE
|
||||
|
||||
const query = uni.createSelectorQuery().in(instance.proxy)
|
||||
query
|
||||
.selectAll('.slotContent')
|
||||
.boundingClientRect((data) => {
|
||||
let domList = JSON.parse(JSON.stringify(data))
|
||||
let max = 0
|
||||
let viewMaxHeightVal = 0
|
||||
|
||||
for (let i = 0; i < domList.length; i++) {
|
||||
let height = domList[i].height
|
||||
if (isList.value) {
|
||||
cloneList.value[i].height = height
|
||||
}
|
||||
viewMaxHeightVal += height
|
||||
if (height > max) {
|
||||
max = height
|
||||
}
|
||||
}
|
||||
viewMaxHeight.value = viewMaxHeightVal // 内容区域总高度
|
||||
itemMaxHeight.value = max + 'px'
|
||||
initList(cloneList.value)
|
||||
})
|
||||
.exec()
|
||||
// #endif
|
||||
}, 0)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 方法
|
||||
// 显示占位
|
||||
const showPlaceholder = (i: number): boolean => {
|
||||
// 位于底部或者指定位置等于活动位置时,都不会显示占位
|
||||
let isShow = false
|
||||
if (moveToIndex.value > activeIndex.value) {
|
||||
// 指定下标位置大于活动下标,i-1; 目的是为了用指定位置的下一级判断占位
|
||||
if (moveToIndex.value === i - 1) {
|
||||
isShow = true
|
||||
}
|
||||
} else if (moveToIndex.value === activeIndex.value) {
|
||||
return false // 位置不变时
|
||||
} else if (moveToIndex.value < activeIndex.value) {
|
||||
if (moveToIndex.value === i) {
|
||||
isShow = true
|
||||
}
|
||||
}
|
||||
return isShow
|
||||
}
|
||||
|
||||
// 长按事件
|
||||
const controlLongpress = (i: number) => {
|
||||
if (props.supportLongpress) {
|
||||
handleLongpress(i)
|
||||
}
|
||||
}
|
||||
|
||||
// 长按事件或者在外部直接调用,才允许拖动
|
||||
const handleDragStart = (event: any, index: number) => {
|
||||
emit('pressStart', { event, data: cloneList.value[index] })
|
||||
}
|
||||
|
||||
// 允许拖动状态
|
||||
const handleLongpress = (index: number) => {
|
||||
disabled.value = false
|
||||
// 哪个开始活动
|
||||
activeIndex.value = index
|
||||
// 记录一下旧的下标
|
||||
oldIndex.value = index
|
||||
emit('handleDragStart', index)
|
||||
}
|
||||
|
||||
// 滚动时,改动列表的y轴
|
||||
const changeScrollInfo = (detail: { y: number }) => {
|
||||
// 滚动触碰边缘触发
|
||||
scrollInfo.value.y += detail.y
|
||||
}
|
||||
|
||||
// 拖拽中
|
||||
const handleMoving = (e: any) => {
|
||||
if (e.detail.source !== 'touch') return
|
||||
let { x, y } = e.detail
|
||||
|
||||
if (isList.value) {
|
||||
// 如果是列表需要添加滚动产生的边距
|
||||
y = y + scrollInfo.value.y
|
||||
|
||||
oldPosition.value.y = y
|
||||
}
|
||||
changeListPosition({ x, y })
|
||||
}
|
||||
|
||||
// 改变列表位置
|
||||
const changeListPosition = ({ x = 0, y = 0, type }: { x: number; y: number; type?: string }) => {
|
||||
// x 手指按下拖动,产生的位置,超出了item的宽度,那么就改变下标,包括y轴。
|
||||
let currentX = Math.floor((x + Number(getItemWidth.value) / 2) / Number(getItemWidth.value))
|
||||
let currentY = Math.floor((y + getItemHeight.value / 2) / getItemHeight.value)
|
||||
// moveToIndex:通过计算横排数量,偏移量( x,y ),得出下标位置
|
||||
moveToIndex.value = Math.min(currentY * props.column + currentX, cloneList.value.length - 1) // 滑到了哪个位置
|
||||
// 如果是列表的情况 -- 触碰元素的边缘就检测到下标
|
||||
if (isList.value) {
|
||||
// 列表的情况, 无需考虑x轴; 通过y轴和列表的高度来判断;
|
||||
let currentH = 0
|
||||
for (let i = 0; i < cloneList.value.length; i++) {
|
||||
currentH += cloneList.value[i].height!
|
||||
if (props.dragDirection === 'down') {
|
||||
// 往下的情况下 ---- 当前活动的下标的高度( 也就是拖动的底部 )碰到下一个元素时; 赋值下标
|
||||
/*
|
||||
下一个下标的5/1;位置触发
|
||||
如果到了最后一个时,让下一个触发的高度变成当前拖动到指定位置的高度,避免照成到达了底部后下标位置有差异的问题;
|
||||
**/
|
||||
let nextH = cloneList.value[i + 1] ? cloneList.value[i + 1].height! / 5 : currentH
|
||||
if (currentH > y + cloneList.value[activeIndex.value].height! - nextH) {
|
||||
moveToIndex.value = i
|
||||
break
|
||||
}
|
||||
} else {
|
||||
// 往上拖拽时 ---- 当前活动的下标( 也就是拖动的顶部 )碰到上一个元素时; 赋值下标
|
||||
let theH = cloneList.value[i - 1] ? cloneList.value[i - 1].height! / 5 : 0 // 下一个下标的5/1;位置触发
|
||||
if (currentH > y + theH) {
|
||||
moveToIndex.value = i
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (oldIndex.value !== moveToIndex.value && oldIndex.value !== -1 && moveToIndex.value !== -1) {
|
||||
// 排序替换
|
||||
const newList = deepCopy(cloneList.value) // cloneList的数据会比showList优先变化
|
||||
const replaceList = deepCopy(cloneList.value) // cloneList的数据会比showList优先变化
|
||||
let splicItem = newList.splice(activeIndex.value, 1)[0] // 删除指定下标,并且返回删除的数据
|
||||
newList.splice(moveToIndex.value, 0, splicItem) // 被移入的下标数据替换成刚刚删除的下标数据
|
||||
if (props.swapMode) {
|
||||
if (isList.value) {
|
||||
// 需要先吧高度先替换掉---
|
||||
replaceList.splice(moveToIndex.value, 0, ...replaceList.splice(activeIndex.value, 1))
|
||||
}
|
||||
// 替换位置
|
||||
showList.value.forEach((item, index) => {
|
||||
if (index !== activeIndex.value) {
|
||||
let itemIndex = newList.findIndex((val) => val.dropId === item.dropId)
|
||||
// 在修改轴和y轴时,需要先吧height改变,因为列表的y轴就是根据height赋值的。
|
||||
let position = getPosition(itemIndex, replaceList)
|
||||
item.x = position[0]
|
||||
item.y = position[1]
|
||||
}
|
||||
})
|
||||
} else {
|
||||
// 两点换位
|
||||
replaceList[activeIndex.value].height = showList.value[moveToIndex.value].height
|
||||
replaceList[moveToIndex.value].height = showList.value[activeIndex.value].height
|
||||
|
||||
showList.value.forEach((item, index) => {
|
||||
if (isList.value) {
|
||||
if (props.dragDirection === 'down') {
|
||||
if (index > activeIndex.value && index < moveToIndex.value) {
|
||||
// 在这个期间的高度和y都需要变化
|
||||
;[item.x, item.y] = getPosition(index, replaceList)
|
||||
}
|
||||
} else if (index < activeIndex.value && index > moveToIndex.value) {
|
||||
// 在这个期间的高度和y都需要变化
|
||||
;[item.x, item.y] = getPosition(index, replaceList)
|
||||
}
|
||||
}
|
||||
// 说明需要把不需要换位的下标替回来
|
||||
if (index === oldIndex.value) {
|
||||
;[item.x, item.y] = getPosition(oldIndex.value, replaceList)
|
||||
}
|
||||
// 当前移动的下标和目标下标互换位置
|
||||
if (index === moveToIndex.value) {
|
||||
;[item.x, item.y] = getPosition(activeIndex.value, replaceList)
|
||||
}
|
||||
})
|
||||
}
|
||||
oldIndex.value = moveToIndex.value
|
||||
}
|
||||
|
||||
let list = deepCopy(showList.value)
|
||||
emit('handleMoving', { list, x, y })
|
||||
}
|
||||
|
||||
// 拖拽结束
|
||||
const handleDragEnd = (e: any) => {
|
||||
setTimeout(() => {
|
||||
scrollInfo.value = { x: 0, y: 0 }
|
||||
if (disabled.value) return // 为点击不能出发
|
||||
if (
|
||||
moveToIndex.value !== -1 &&
|
||||
activeIndex.value !== -1 &&
|
||||
moveToIndex.value !== activeIndex.value
|
||||
) {
|
||||
// 拖动了的话,并且目标位置和活动位置不一样,才来这里
|
||||
if (props.swapMode) {
|
||||
cloneList.value.splice(
|
||||
moveToIndex.value,
|
||||
0,
|
||||
...cloneList.value.splice(activeIndex.value, 1),
|
||||
)
|
||||
} else {
|
||||
let active = cloneList.value[activeIndex.value] // 当前下标
|
||||
let move = cloneList.value[moveToIndex.value] // 目标下标
|
||||
// 替换
|
||||
cloneList.value[activeIndex.value] = move
|
||||
cloneList.value[moveToIndex.value] = active
|
||||
}
|
||||
}
|
||||
initList(cloneList.value)
|
||||
const endList = showList.value.map((item) => omit(item))
|
||||
const list = deepCopy(cloneList.value)
|
||||
emit('update:list', endList) // vue3 的更新方法
|
||||
emit('getList', endList) // 更新列表
|
||||
emit('handleDragEnd', { list }) // 结束拖拽
|
||||
|
||||
activeIndex.value = -1
|
||||
oldIndex.value = -1
|
||||
moveToIndex.value = -1
|
||||
disabled.value = true
|
||||
})
|
||||
}
|
||||
|
||||
// 数据的长度不变的情况下-更新数据-减少加载带来的画面卡顿
|
||||
const updataList = (list: ItemType[]) => {
|
||||
// 注意做好拖拽时规避 更新
|
||||
if (props.isStopPropagation) return // 拖拽中状态不可更新数据
|
||||
const newList = deepCopy(list)
|
||||
for (let i = 0; i < newList.length; i++) {
|
||||
showList.value[i] = { ...showList.value[i], ...newList[i] }
|
||||
}
|
||||
cloneList.value = deepCopy(showList.value)
|
||||
}
|
||||
|
||||
// 因为可能获取的宽度是0,需要需要重调
|
||||
const setLeoDrag = (size: number = 5) => {
|
||||
if (size < 0) return
|
||||
|
||||
// #ifdef APP-NVUE
|
||||
dom.getComponentRect(leoDragView.value, (res: any) => {
|
||||
let data = res.size
|
||||
getViewCallback(data, size)
|
||||
})
|
||||
// #endif
|
||||
|
||||
// #ifndef APP-NVUE
|
||||
nextTick(() => {
|
||||
const query = uni.createSelectorQuery().in(instance.proxy)
|
||||
query
|
||||
.select('.leo-drag')
|
||||
.boundingClientRect((data) => {
|
||||
getViewCallback(data, size)
|
||||
})
|
||||
.exec()
|
||||
})
|
||||
// #endif
|
||||
}
|
||||
|
||||
// 初次获取元素宽高后
|
||||
const getViewCallback = (data: any, size: number) => {
|
||||
if (!data || data.width < 50) {
|
||||
setTimeout(() => {
|
||||
size = size - 1
|
||||
setLeoDrag(size)
|
||||
}, 300)
|
||||
return
|
||||
}
|
||||
width.value = data.width
|
||||
nextTick(() => {
|
||||
initList(showList.value, true) // 初始化 dom
|
||||
})
|
||||
}
|
||||
|
||||
// 监听列表变化
|
||||
watch(
|
||||
() => props.list,
|
||||
(newList) => {
|
||||
let list = deepCopy(newList) || []
|
||||
// 先拿到新增数据,因为是从父级侦听获取数据,并且是向后添加数据,所以需要使用剪切
|
||||
if (list.length > showList.value.length) {
|
||||
list.splice(0, showList.value.length)
|
||||
list = [...showList.value, ...list]
|
||||
initList(list, true)
|
||||
} else {
|
||||
// 如果小于显示长度 说明刷新或者删除了说明元素,这个时候应该更新列表
|
||||
nextTick(() => {
|
||||
initList(list, true)
|
||||
})
|
||||
}
|
||||
},
|
||||
{ deep: true, immediate: true },
|
||||
)
|
||||
|
||||
// 创建时初始化数据
|
||||
showList.value = deepCopy(props.list) || []
|
||||
|
||||
// 组件挂载后初始化
|
||||
onMounted(() => {
|
||||
setLeoDrag()
|
||||
})
|
||||
|
||||
// 暴露方法给父组件调用
|
||||
defineExpose({
|
||||
initList,
|
||||
updataList,
|
||||
handleLongpress,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.base-drag-wrapper {
|
||||
opacity: 1;
|
||||
z-index: 1;
|
||||
color: #212121;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
transition: top 0.4s;
|
||||
|
||||
flex-wrap: wrap;
|
||||
/* #ifndef APP-NVUE */
|
||||
width: 100%;
|
||||
/* #endif */
|
||||
}
|
||||
.slotContent {
|
||||
display: flex;
|
||||
/* #ifndef APP-NVUE */
|
||||
width: 100%;
|
||||
/* #endif */
|
||||
|
||||
:deep() {
|
||||
// 微信小程序会多嵌一层view--综合一起设置
|
||||
& > view {
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
.placeholder {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
animation: animationShows 0.51s linear;
|
||||
}
|
||||
@keyframes animationShows {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
20% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.leo-drag {
|
||||
/* #ifndef APP-NVUE */
|
||||
width: 100%;
|
||||
/* #endif */
|
||||
}
|
||||
.loading {
|
||||
color: pink;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
export const deepCopy = <T>(source: T): T => {
|
||||
return JSON.parse(JSON.stringify(source))
|
||||
}
|
||||
|
|
@ -36,7 +36,7 @@
|
|||
universityBaseInfo?.universityResult.level === 0 ? '本科' : '专科'
|
||||
}}·{{ universityBaseInfo?.universityResult.nature }}
|
||||
</text>
|
||||
<text class="mt-[14rpx] text-[22rpx] font-normal text-[#303030]">
|
||||
<text class="mt-[14rpx] text-[22rpx] font-normal text-[#303030] max-w-[400rpx] truncate">
|
||||
{{ universityBaseInfo?.universityResult.features.slice(0, 4).join('/ ') }}
|
||||
</text>
|
||||
</view>
|
||||
|
|
|
|||
|
|
@ -1,23 +0,0 @@
|
|||
<template>
|
||||
<view
|
||||
class="bg-[#E2EDF9] text-[#1580FF] text-[22rpx] flex justify-between items-center px-[32rpx] py-[10rpx]"
|
||||
>
|
||||
<view class="flex gap-[16rpx]">
|
||||
<text>{{ userInfo.estimatedAchievement.expectedScore }}分</text>
|
||||
<text>
|
||||
{{ userInfo.estimatedAchievement.subjectGroup.split(',').join('/') }}
|
||||
</text>
|
||||
<text>{{ userInfo.batchName }}</text>
|
||||
</view>
|
||||
<view>
|
||||
<text>重要提示</text>
|
||||
<text class="i-carbon-help"></text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
defineProps<{
|
||||
userInfo: any
|
||||
}>()
|
||||
</script>
|
||||
|
|
@ -1,120 +0,0 @@
|
|||
<template>
|
||||
<view class="h-[16rpx] bg-[#F5F5F5]"></view>
|
||||
<view class="flex items-start p-[32rpx]">
|
||||
<view class="flex flex-col items-center gap-[16rpx]">
|
||||
<image :src="item.logo" mode="scaleToFill" class="w-[112rpx] h-[112rpx]" />
|
||||
<view
|
||||
class="w-[52rpx] h-[52rpx] rounded-[8rpx] font-semibold text-[28rpx] flex items-center justify-center"
|
||||
:style="calcTypeName(item.type).style"
|
||||
>
|
||||
{{ calcTypeName(item.type).text }}
|
||||
</view>
|
||||
<text class="text-[32rpx] font-semibold">
|
||||
{{
|
||||
Math.round(
|
||||
item.items.reduce((a, b) => a + Number(b.percentAge.replace('%', '')), 0) /
|
||||
item.items.length,
|
||||
)
|
||||
}}
|
||||
%
|
||||
</text>
|
||||
</view>
|
||||
<view class="flex flex-col ml-[24rpx] justify-between flex-1">
|
||||
<view class="flex justify-between mb-[14rpx]">
|
||||
<view class="flex justify-between flex-col gap-[6rpx]">
|
||||
<text class="text-[32rpx] font-semibold">{{ item.name }}</text>
|
||||
<text class="text-[22rpx] text-[#505050]">
|
||||
{{ item.city }}·{{ item.educationCategory }}
|
||||
</text>
|
||||
<view class="text-[22rpx] text-[#8F959E] flex items-center">
|
||||
<text class="truncate max-w-[300rpx]" v-show="item.features.length > 0">
|
||||
{{ item.features.slice(0, 3).join('/') }}/
|
||||
</text>
|
||||
<text>排名{{ item.rank }}</text>
|
||||
</view>
|
||||
<view class="text-[22rpx] text-[#1F2329] mt-[8rpx] flex gap-[10rpx]">
|
||||
<text class="">代码{{ item.collegeCode }}</text>
|
||||
<text>{{ item.year }}计划{{ item.items.reduce((a, b) => a + b.planCount, 0) }}人</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="flex flex-col gap-[8rpx] items-center">
|
||||
<view
|
||||
class="text-[24rpx] px-[16rpx] py-[12rpx] rounded-[8rpx] border-[2rpx] border-[#1580FF] border-solid"
|
||||
@click.stop="handleShow"
|
||||
>
|
||||
专业{{ item.items.length }}
|
||||
</view>
|
||||
<text class="text-[20rpx] text-[#8F959E]" v-if="collegeMajorCount > 0">
|
||||
已填 {{ collegeMajorCount }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<DataTable :data="item.childItems" v-bind="$attrs" />
|
||||
</view>
|
||||
</view>
|
||||
<ActionSheet v-model:show="show" :lazy-render="true">
|
||||
<template #title>
|
||||
<view class="flex items-center justify-between px-[32rpx] pt-[32rpx] pb-[24rpx]">
|
||||
<view class="flex flex-col gap-[14rpx]">
|
||||
<text class="text-[36rpx] text-[#303030] font-bold">{{ item.name }}</text>
|
||||
<text class="text-[22rpx] text-[#505050]">
|
||||
{{ item.city }}·{{ item.educationCategory }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="flex flex-col items-end gap-[40rpx]">
|
||||
<view class="i-carbon-close-large w-[40rpx] h-[40rpx]" @click.stop="show = false"></view>
|
||||
<view class="text-[22rpx]">
|
||||
<text>已填</text>
|
||||
<text class="text-[#1580FF]">{{ majorCount }}</text>
|
||||
<text>个</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<CollegeMajor :item="item" v-bind="$attrs" />
|
||||
|
||||
<template #footer>
|
||||
<view class="flex items-center justify-between gap-[30rpx]">
|
||||
<view class="cancel-btn" @click.stop="show = false">取消</view>
|
||||
<view class="submit-btn" @click.stop="handleConfirm">确认</view>
|
||||
</view>
|
||||
</template>
|
||||
</ActionSheet>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import DataTable from './DataTable.vue'
|
||||
import { useUserStore } from '@/store/user'
|
||||
import ActionSheet from '@/pages-sub/components/ActionSheet.vue'
|
||||
import CollegeMajor from './CollegeMajor.vue'
|
||||
import { calcTypeName } from './useWisheList'
|
||||
|
||||
const userStore = useUserStore()
|
||||
|
||||
const props = defineProps({
|
||||
item: Object,
|
||||
majorCount: Number,
|
||||
})
|
||||
|
||||
const show = ref(false)
|
||||
const handleConfirm = () => {
|
||||
show.value = false
|
||||
}
|
||||
|
||||
const handleShow = () => {
|
||||
show.value = true
|
||||
}
|
||||
|
||||
const collegeMajorCount = computed(() => {
|
||||
return (
|
||||
userStore.userInfo.wishList.find((item) => item.unId === props.item.uId)?.vItems.length || 0
|
||||
)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@/pages-sub/home/styles/picker-view-btn.scss';
|
||||
</style>
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
<template>
|
||||
<view
|
||||
v-for="major in item.items"
|
||||
v-for="major in college.items"
|
||||
:key="major.planId"
|
||||
class="pt-[32rpx] pl-[58rpx] pr-[32rpx] pb-[30rpx] custom-background flex gap-[58rpx]"
|
||||
:style="`--background-color:${calcTypeName(major.type).style.backgroundColor}`"
|
||||
>
|
||||
|
|
@ -23,7 +24,7 @@
|
|||
<view class="flex justify-between text-[22rpx] text-[#1F2329] mt-[14rpx]">
|
||||
<view class="flex flex-col gap-[6rpx]">
|
||||
<text>代码{{ major.majorCode }}</text>
|
||||
<text>{{ item.year }}计划{{ major.planCount }}人</text>
|
||||
<text>{{ college.year }}计划{{ major.planCount }}人</text>
|
||||
</view>
|
||||
<view class="flex flex-col gap-[6rpx]">
|
||||
<text>选科:{{ major.subjectClam }}</text>
|
||||
|
|
@ -45,51 +46,40 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { calcTypeName } from './useWisheList'
|
||||
import { calcTypeName } from '../composable/useWishesList'
|
||||
import DataTable from './DataTable.vue'
|
||||
import { useUserStore } from '@/store/user'
|
||||
|
||||
const userStore = useUserStore()
|
||||
|
||||
const props = defineProps<{
|
||||
item: any
|
||||
college: any
|
||||
score?: number
|
||||
}>()
|
||||
|
||||
const handleClick = (major: any) => {
|
||||
let exitMajorUnList = userStore.userInfo.wishList.find((item) => item.unId === props.item.uId)
|
||||
let exitMajor = exitMajorUnList?.vItems.find((item) => item._pId === major.planId)
|
||||
let exitMajorUnList = userStore.userInfo.wishList.find((item) => item.uId === props.college.uId)
|
||||
let exitMajor = exitMajorUnList?.vItems.find((item) => item.planId === major.planId)
|
||||
if (exitMajor) {
|
||||
userStore.deleteWishListMajor({ unId: props.item.uId, _pId: major.planId })
|
||||
userStore.deleteWishListMajor({ uId: props.college.uId, planId: major.planId })
|
||||
} else if (exitMajorUnList) {
|
||||
userStore.setWishListMajor({
|
||||
val: {
|
||||
_pId: major.planId,
|
||||
major: major.major,
|
||||
majorCode: major.majorCode,
|
||||
majorGroup: major.majorGroup,
|
||||
percentAge: major.percentAge,
|
||||
...major,
|
||||
},
|
||||
unId: props.item.uId,
|
||||
uId: props.college.uId,
|
||||
})
|
||||
} else {
|
||||
let _major = {
|
||||
unId: props.item.uId,
|
||||
unName: props.item.name,
|
||||
unCode: props.item.collegeCode,
|
||||
type: props.item.type,
|
||||
...props.college,
|
||||
vItems: [
|
||||
{
|
||||
_pId: major.planId,
|
||||
major: major.major,
|
||||
majorCode: major.majorCode,
|
||||
majorGroup: major.majorGroup,
|
||||
percentAge: major.percentAge,
|
||||
...major,
|
||||
sort: 1,
|
||||
type: major.type,
|
||||
},
|
||||
],
|
||||
}
|
||||
delete _major.items
|
||||
userStore.setWishListMajorWithUn(_major)
|
||||
}
|
||||
}
|
||||
|
|
@ -97,9 +87,9 @@ const handleClick = (major: any) => {
|
|||
const checkActive = (major: unknown) => {
|
||||
const _major = major as { planId: string }
|
||||
return userStore.userInfo.wishList.find((item) => {
|
||||
if (item.unId !== props.item.uId) {
|
||||
if (item.uId !== props.college.uId) {
|
||||
return false
|
||||
} else if (item.vItems.find((vItem) => vItem._pId === _major.planId)) {
|
||||
} else if (item.vItems.find((vItem) => vItem.planId === _major.planId)) {
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
|
@ -4,7 +4,8 @@
|
|||
<!-- 头部 -->
|
||||
<view class="flex items-center gap-[16rpx]">
|
||||
<view
|
||||
v-for="headItem in columns"
|
||||
v-for="(headItem, index) in columns"
|
||||
:key="index"
|
||||
class="text-[22rpx] text-[#505050]"
|
||||
:style="{ width: headItem.width }"
|
||||
>
|
||||
|
|
@ -18,11 +19,16 @@
|
|||
|
||||
<!-- 表格内容 -->
|
||||
<view>
|
||||
<view v-for="(item, index) in recompileData" class="flex items-center gap-[16rpx]">
|
||||
<view
|
||||
v-for="col in columns"
|
||||
v-for="(item, index) in recompileData"
|
||||
class="flex items-center gap-[16rpx]"
|
||||
:key="index"
|
||||
>
|
||||
<view
|
||||
v-for="(col, colIndex) in columns"
|
||||
class="text-[22rpx] text-[#505050]"
|
||||
:style="{ width: col.width }"
|
||||
:key="colIndex"
|
||||
>
|
||||
<view v-if="col.key === 'lineDiff'">
|
||||
{{ item['lineDiff'] }}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
<template>
|
||||
<view
|
||||
class="bg-[#E2EDF9] text-[#1580FF] text-[22rpx] flex justify-between items-center px-[32rpx] py-[10rpx]"
|
||||
>
|
||||
<view class="flex gap-[16rpx]">
|
||||
<text>{{ userInfo.estimatedAchievement.expectedScore }}分</text>
|
||||
<text>
|
||||
{{ userInfo.estimatedAchievement.subjectGroup.split(',').join('/') }}
|
||||
</text>
|
||||
<text>{{ userInfo.batchName }}</text>
|
||||
</view>
|
||||
<view v-if="type === 0" class="flex items-center">
|
||||
<text>重要提示</text>
|
||||
<text class="i-carbon-help"></text>
|
||||
</view>
|
||||
|
||||
<view v-if="type === 1" class="flex items-center gap-[26rpx] text-[22rpx] text-[#000]">
|
||||
<view v-for="(model, index) of tModel" :key="model.type" class="flex items-center gap-[6rpx]">
|
||||
<view
|
||||
class="w-[16rpx] h-[16rpx] rounded-full"
|
||||
:style="{ backgroundColor: calcTypeName(model.type).roundedBgColor }"
|
||||
></view>
|
||||
<text class="text-[22rpx]">{{ calcTypeName(model.type)?.text }}({{ model.count }})</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useUserStore } from '@/store/user'
|
||||
import { countModel, calcTypeName } from '../composable/useWishesList'
|
||||
|
||||
const userStore = useUserStore()
|
||||
|
||||
defineProps({
|
||||
userInfo: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
type: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
})
|
||||
|
||||
const userWhishList = computed(() => userStore.userInfo.wishList)
|
||||
const { tModel } = countModel(userWhishList.value)
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.t-model-base {
|
||||
font-weight: 400;
|
||||
font-size: 22rpx;
|
||||
color: #000000;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
<template>
|
||||
<view class="h-[16rpx] bg-[#F5F5F5]"></view>
|
||||
<view class="flex items-start p-[32rpx]">
|
||||
<view class="flex flex-col items-center gap-[16rpx]">
|
||||
<image :src="college.logo" mode="scaleToFill" class="w-[112rpx] h-[112rpx]" />
|
||||
<view
|
||||
class="w-[52rpx] h-[52rpx] rounded-[8rpx] font-semibold text-[28rpx] flex items-center justify-center"
|
||||
:style="calcTypeName(college.type).style"
|
||||
>
|
||||
{{ calcTypeName(college.type).text }}
|
||||
</view>
|
||||
<text class="text-[32rpx] font-semibold">
|
||||
{{
|
||||
Math.round(
|
||||
college.items.reduce((a, b) => a + Number(b.percentAge.replace('%', '')), 0) /
|
||||
college.items.length,
|
||||
)
|
||||
}}
|
||||
%
|
||||
</text>
|
||||
</view>
|
||||
<view class="flex flex-col ml-[24rpx] justify-between flex-1">
|
||||
<view class="flex justify-between mb-[14rpx]">
|
||||
<view class="flex justify-between flex-col gap-[6rpx]">
|
||||
<text class="text-[32rpx] font-semibold">{{ college.name }}</text>
|
||||
<text class="text-[22rpx] text-[#505050]">
|
||||
{{ college.city }}·{{ college.educationCategory }}
|
||||
</text>
|
||||
<view class="text-[22rpx] text-[#8F959E] flex items-center">
|
||||
<text class="truncate max-w-[300rpx]" v-show="college.features.length > 0">
|
||||
{{ college.features.slice(0, 3).join('/') }}/
|
||||
</text>
|
||||
<text>排名{{ college.rank }}</text>
|
||||
</view>
|
||||
<view class="text-[22rpx] text-[#1F2329] mt-[8rpx] flex gap-[10rpx]">
|
||||
<text class="">代码{{ college.collegeCode }}</text>
|
||||
<text>
|
||||
{{ college.year }}计划{{ college.items.reduce((a, b) => a + b.planCount, 0) }}人
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="flex flex-col gap-[8rpx] items-center">
|
||||
<view
|
||||
class="text-[24rpx] px-[16rpx] py-[12rpx] rounded-[8rpx] border-[2rpx] border-[#1580FF] border-solid"
|
||||
@click.stop="handleShow"
|
||||
>
|
||||
专业{{ college.items.length }}
|
||||
</view>
|
||||
<text class="text-[20rpx] text-[#8F959E]" v-if="collegeMajorCount > 0">
|
||||
已填 {{ collegeMajorCount }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<DataTable :data="college.childItems" v-bind="$attrs" />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import DataTable from './DataTable.vue'
|
||||
import { useUserStore } from '@/store/user'
|
||||
|
||||
import { calcTypeName } from '../composable/useWishesList'
|
||||
|
||||
const userStore = useUserStore()
|
||||
|
||||
const props = defineProps({
|
||||
college: Object,
|
||||
})
|
||||
|
||||
const emit = defineEmits(['showAction'])
|
||||
const handleShow = () => {
|
||||
emit('showAction', props.college)
|
||||
}
|
||||
|
||||
const collegeMajorCount = computed(() => {
|
||||
return (
|
||||
userStore.userInfo.wishList.find((item) => item.uId === props.college.uId)?.vItems.length || 0
|
||||
)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
<template>
|
||||
<ActionSheet v-model:show="innerShowFlag" :lazy-render="true">
|
||||
<template #title>
|
||||
<view class="flex items-center justify-between px-[32rpx] pt-[32rpx] pb-[24rpx]">
|
||||
<view class="flex flex-col gap-[14rpx]">
|
||||
<text class="text-[36rpx] text-[#303030] font-bold">{{ college?.name }}</text>
|
||||
<text class="text-[22rpx] text-[#505050]">
|
||||
{{ college?.city }}·{{ college?.educationCategory }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="flex flex-col items-end gap-[40rpx]">
|
||||
<view class="i-carbon-close-large w-[40rpx] h-[40rpx]" @click.stop="handleConfirm"></view>
|
||||
<view class="text-[22rpx]">
|
||||
<text>已填</text>
|
||||
<text class="text-[#1580FF]">{{ majorCount }}</text>
|
||||
<text>个</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<CollegeMajor :college="college" v-bind="$attrs" v-if="college" />
|
||||
|
||||
<template #footer>
|
||||
<view class="flex items-center justify-between gap-[30rpx]">
|
||||
<view class="cancel-btn" @click="handleConfirm">取消</view>
|
||||
<view class="submit-btn" @click="handleConfirm">确认</view>
|
||||
</view>
|
||||
</template>
|
||||
</ActionSheet>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import ActionSheet from '@/pages-sub/components/ActionSheet.vue'
|
||||
import CollegeMajor from './CollegeMajor.vue'
|
||||
|
||||
const props = defineProps({
|
||||
college: Object,
|
||||
majorCount: Number,
|
||||
show: Boolean,
|
||||
})
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:show', value: boolean): void
|
||||
}>()
|
||||
|
||||
const innerShowFlag = computed({
|
||||
get: () => {
|
||||
return props.show
|
||||
},
|
||||
set: (value) => {
|
||||
emit('update:show', value)
|
||||
},
|
||||
})
|
||||
|
||||
const handleConfirm = () => {
|
||||
emit('update:show', false)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@/pages-sub/home/styles/picker-view-btn.scss';
|
||||
</style>
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
<template>
|
||||
<view class="h-[16rpx] bg-[#f8f8f8]"></view>
|
||||
|
||||
<Collapse
|
||||
:default-collapsed="false"
|
||||
class="flex flex-col items-center gap-[16rpx] custom-background px-[32rpx]"
|
||||
:style="`--background-color:${calcTypeName(college.type).style.backgroundColor}`"
|
||||
>
|
||||
<template #header>
|
||||
<view class="flex py-[32rpx] gap-[30rpx]">
|
||||
<view class="flex flex-col items-center gap-[16rpx]">
|
||||
<view class="flex items-center gap-[8rpx] text-[#303030] text-[28rpx]">
|
||||
{{ collegeIndex }}
|
||||
<view class="i-carbon-chevron-down text-[16rpx]"></view>
|
||||
</view>
|
||||
<view
|
||||
class="w-[52rpx] h-[52rpx] rounded-[8rpx] font-semibold text-[28rpx] flex items-center justify-center"
|
||||
:style="calcTypeName(college.type).style"
|
||||
>
|
||||
{{ calcTypeName(college.type).text }}
|
||||
</view>
|
||||
<text class="text-[32rpx] font-semibold">
|
||||
{{
|
||||
Math.round(
|
||||
college.vItems.reduce((a, b) => a + Number(b.percentAge.replace('%', '')), 0) /
|
||||
college.vItems.length,
|
||||
)
|
||||
}}%
|
||||
</text>
|
||||
</view>
|
||||
<view class="flex flex-col justify-between flex-1">
|
||||
<view class="flex justify-between mb-[14rpx]">
|
||||
<view class="flex justify-between flex-col gap-[6rpx]">
|
||||
<text class="text-[32rpx] font-semibold">{{ college.name }}</text>
|
||||
<text class="text-[22rpx] text-[#505050]">
|
||||
{{ college.city }}·{{ college.educationCategory }}
|
||||
</text>
|
||||
<view class="text-[22rpx] text-[#8F959E] flex items-center">
|
||||
<text class="truncate max-w-[300rpx]" v-show="college.features.length > 0">
|
||||
{{ college.features.slice(0, 3).join('/') }}/
|
||||
</text>
|
||||
<text>排名{{ college.rank }}</text>
|
||||
</view>
|
||||
<view class="text-[22rpx] text-[#1F2329] mt-[8rpx] flex gap-[10rpx]">
|
||||
<text class="">代码{{ college.collegeCode }}</text>
|
||||
<text>
|
||||
{{ college.year }}计划{{ college.vItems.reduce((a, b) => a + b.planCount, 0) }}人
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<DataTable :data="college.childItems" v-bind="$attrs" />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<view class="h-[2rpx] bg-[#EDEDED] w-full"></view>
|
||||
<view
|
||||
v-for="major in college.vItems"
|
||||
:key="major.planId"
|
||||
class="pt-[32rpx] pb-[30rpx] flex gap-[30rpx] not-last:border-b border-[#EDEDED]"
|
||||
>
|
||||
<view class="flex flex-col gap-[16rpx]">
|
||||
<text class="text-[32rpx] font-semibold text-[#000]">{{ major.percentAge || '0%' }}</text>
|
||||
</view>
|
||||
<view class="flex flex-col gap-[16rpx]">
|
||||
<view class="flex justify-between flex-auto">
|
||||
<view class="flex flex-col">
|
||||
<text class="text-[32rpx] text-[#000] font-semibold truncate max-w-[400rpx]">
|
||||
{{ major.major.replace(/(\r\n|\n|\r)/g, '') }}
|
||||
</text>
|
||||
<text class="text-[22rpx] text-[#1F2329] mt-[14rpx]">{{ major.remark }}</text>
|
||||
<view class="flex justify-between text-[22rpx] text-[#1F2329] mt-[14rpx]">
|
||||
<view class="flex flex-col gap-[6rpx]">
|
||||
<text>代码{{ major.majorCode }}</text>
|
||||
<text>{{ college.year }}计划{{ major.planCount }}人</text>
|
||||
</view>
|
||||
<view class="flex flex-col gap-[6rpx]">
|
||||
<text>选科:{{ major.subjectClam }}</text>
|
||||
<text>学费/学制:{{ major.fee }}/{{ major.academic }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<DataTable :data="major.items" :score="score" />
|
||||
</view>
|
||||
</view>
|
||||
</Collapse>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { calcTypeName } from '../composable/useWishesList'
|
||||
import DataTable from './DataTable.vue'
|
||||
import Collapse from '@/pages-sub/components/collapse/Collapse.vue'
|
||||
|
||||
defineProps<{
|
||||
college: any
|
||||
score: number
|
||||
collegeIndex: number
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.custom-background {
|
||||
background: linear-gradient(180deg, var(--background-color) 0%, #fff 30%, #fff 100%);
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
import { getBatchBase } from '@/service/index/api'
|
||||
|
||||
export const calcTypeName = (type: number) => {
|
||||
const style = {
|
||||
2: {
|
||||
text: '冲',
|
||||
color: '#EB5241',
|
||||
bgColor: 'rgba(235,82,65,0.15)',
|
||||
roundedBgColor: '#E75859',
|
||||
},
|
||||
1: {
|
||||
text: '稳',
|
||||
color: '#FA8E23',
|
||||
bgColor: 'rgba(250,142,35,0.15)',
|
||||
roundedBgColor: '#FF8800',
|
||||
},
|
||||
0: {
|
||||
text: '保',
|
||||
color: '#15C496',
|
||||
bgColor: 'rgba(21,196,150,0.15)',
|
||||
roundedBgColor: '#34C724',
|
||||
},
|
||||
}[type] || { text: '保', color: '#15C496', bgColor: 'rgba(21,196,150,0.15)' }
|
||||
|
||||
return {
|
||||
text: style.text,
|
||||
style: {
|
||||
color: style.color,
|
||||
backgroundColor: style.bgColor,
|
||||
},
|
||||
roundedBgColor: style.roundedBgColor,
|
||||
}
|
||||
}
|
||||
export const coverTypeModel = (tModel: Record<keyof typeof TYPE_LABELS, number>, total: number) => {
|
||||
const TYPE_LABELS = {
|
||||
c: '冲',
|
||||
w: '稳',
|
||||
b: '保',
|
||||
} as const
|
||||
|
||||
let _result = Object.entries(TYPE_LABELS).map(([key, label]) => ({
|
||||
name: `${label}(${tModel[key]})`,
|
||||
value: key === 'b' ? '0' : key === 'w' ? '1' : '2',
|
||||
}))
|
||||
_result.unshift({
|
||||
name: `全部${total}`,
|
||||
value: '-1',
|
||||
})
|
||||
return _result
|
||||
}
|
||||
|
||||
export const countModel = (list: any[]) => {
|
||||
const tModel = ref([
|
||||
{ type: 2, count: 0 },
|
||||
{ type: 1, count: 0 },
|
||||
{ type: 0, count: 0 },
|
||||
])
|
||||
|
||||
list.forEach((item) => {
|
||||
item.vItems.forEach((vItem) => {
|
||||
const target = tModel.value.find((t) => t.type === vItem.type)
|
||||
if (target) target.count++
|
||||
})
|
||||
})
|
||||
|
||||
return { tModel }
|
||||
}
|
||||
|
||||
export const useScore = (provinceCode, batchName) => {
|
||||
const score = ref(0)
|
||||
const minScore = ref(0)
|
||||
const maxScore = ref(0)
|
||||
getBatchBase({ locationCode: provinceCode }).then((resp) => {
|
||||
if (resp.code === 200) {
|
||||
const _result = resp.result as { batches: any[]; maxScore: number; minScore: number }
|
||||
if (_result.batches.length > 0) {
|
||||
const _score = _result.batches.find((item) => item.batch === batchName)?.score || 0
|
||||
score.value = _score
|
||||
}
|
||||
|
||||
minScore.value = _result.minScore
|
||||
maxScore.value = _result.maxScore
|
||||
}
|
||||
})
|
||||
return { score, minScore, maxScore }
|
||||
}
|
||||
|
|
@ -69,7 +69,12 @@
|
|||
v-for="(item, index) in schoolList"
|
||||
@click="itemClick(item, index)"
|
||||
>
|
||||
<ScrollListItem :item="item" :score="score" :major-count="majorCount" />
|
||||
<ScrollListItem
|
||||
:college="item"
|
||||
:score="score"
|
||||
:major-count="majorCount"
|
||||
@show-action="handleShowAction"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<template #bottom>
|
||||
|
|
@ -109,6 +114,12 @@
|
|||
</view>
|
||||
</template>
|
||||
</ActionSheet>
|
||||
|
||||
<ScrollListItemAction
|
||||
v-model:show="collegeShow"
|
||||
:college="showCollegeItem"
|
||||
:major-count="majorCount"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
|
@ -118,15 +129,16 @@ import Region from '@/pages-sub/home/components/Region.vue'
|
|||
import FilterMenu from '@/pages-sub/home/components/FilterMenu.vue'
|
||||
import Slider from '@/pages-sub/components/Slider.vue'
|
||||
import CustomPickerView from '@/pages-sub/components/CustomPickerView.vue'
|
||||
import { getBatchBase } from '@/service/index/api'
|
||||
|
||||
import ScrollListItem from './ScrollListItem.vue'
|
||||
import HeaderTip from './HeaderTip.vue'
|
||||
import ScrollListItemAction from './components/ScrollListItemAction.vue'
|
||||
|
||||
import ScrollListItem from './components/ScrollListItem.vue'
|
||||
import HeaderTip from './components/HeaderTip.vue'
|
||||
|
||||
import { getPlanProListByFilter } from '@/service/index/api'
|
||||
|
||||
import { useUserStore } from '@/store/user'
|
||||
import { coverTypeModel } from './useWisheList'
|
||||
import { coverTypeModel, useScore } from './composable/useWishesList'
|
||||
|
||||
const userStore = useUserStore()
|
||||
|
||||
|
|
@ -136,6 +148,13 @@ const filterMenuRef = ref(null)
|
|||
|
||||
const location = ref(userStore.userInfo.estimatedAchievement.provinceCode)
|
||||
|
||||
const showCollegeItem = ref(null)
|
||||
const collegeShow = ref(false)
|
||||
const handleShowAction = (item) => {
|
||||
showCollegeItem.value = item
|
||||
collegeShow.value = true
|
||||
}
|
||||
|
||||
const total = ref(0)
|
||||
const typeModelList = ref([])
|
||||
const handleTypeModelChange = ({ item }) => {
|
||||
|
|
@ -233,28 +252,15 @@ const handleSliderChange = (val) => {
|
|||
paging.value.reload()
|
||||
}
|
||||
|
||||
const score = ref(0)
|
||||
const minScore = ref(0)
|
||||
const maxScore = ref(0)
|
||||
onLoad(() => {
|
||||
getBatchBase({ locationCode: userStore.userInfo.estimatedAchievement.provinceCode }).then(
|
||||
(resp) => {
|
||||
if (resp.code === 200) {
|
||||
const _result = resp.result as { batches: any[]; maxScore: number; minScore: number }
|
||||
if (_result.batches.length > 0) {
|
||||
const _score =
|
||||
_result.batches.find((item) => item.batch === userStore.userInfo.batchName)?.score || 0
|
||||
score.value = _score
|
||||
}
|
||||
|
||||
minScore.value = _result.minScore
|
||||
maxScore.value = _result.maxScore
|
||||
}
|
||||
},
|
||||
const { score, minScore, maxScore } = useScore(
|
||||
userStore.userInfo.estimatedAchievement.provinceCode,
|
||||
userStore.userInfo.batchName,
|
||||
)
|
||||
})
|
||||
|
||||
const handlePreview = () => {
|
||||
if (majorCount.value === 0) {
|
||||
return
|
||||
}
|
||||
uni.navigateTo({ url: '/pages-sub/home/wishesList/wishesList' })
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,44 +0,0 @@
|
|||
export const calcTypeName = (type: number) => {
|
||||
const style = {
|
||||
2: {
|
||||
text: '冲',
|
||||
color: '#EB5241',
|
||||
bgColor: 'rgba(235,82,65,0.15)',
|
||||
},
|
||||
1: {
|
||||
text: '稳',
|
||||
color: '#FA8E23',
|
||||
bgColor: 'rgba(250,142,35,0.15)',
|
||||
},
|
||||
0: {
|
||||
text: '保',
|
||||
color: '#15C496',
|
||||
bgColor: 'rgba(21,196,150,0.15)',
|
||||
},
|
||||
}[type] || { text: '保', color: '#15C496', bgColor: 'rgba(21,196,150,0.15)' }
|
||||
|
||||
return {
|
||||
text: style.text,
|
||||
style: {
|
||||
color: style.color,
|
||||
backgroundColor: style.bgColor,
|
||||
},
|
||||
}
|
||||
}
|
||||
export const coverTypeModel = (tModel: Record<keyof typeof TYPE_LABELS, number>, total: number) => {
|
||||
const TYPE_LABELS = {
|
||||
c: '冲',
|
||||
w: '稳',
|
||||
b: '保',
|
||||
} as const
|
||||
|
||||
let _result = Object.entries(TYPE_LABELS).map(([key, label]) => ({
|
||||
name: `${label}(${tModel[key]})`,
|
||||
value: key === 'b' ? '0' : key === 'w' ? '1' : '2',
|
||||
}))
|
||||
_result.unshift({
|
||||
name: `全部${total}`,
|
||||
value: '-1',
|
||||
})
|
||||
return _result
|
||||
}
|
||||
|
|
@ -1,11 +1,58 @@
|
|||
<route lang="json5" type="page">
|
||||
{
|
||||
style: {
|
||||
navigationBarTitleText: '当前志愿表',
|
||||
},
|
||||
}
|
||||
</route>
|
||||
|
||||
<template>
|
||||
<view class="">
|
||||
<HeaderTip :user-info="userStore.userInfo" />
|
||||
<view class="h-screen flex flex-col">
|
||||
<HeaderTip :user-info="userStore.userInfo" :type="1" />
|
||||
<DragSortList v-model:list="wishList" class="flex-auto pb-safe overflow-auto" ref="myDrop">
|
||||
<template #content="{ data }">
|
||||
<view
|
||||
class="drop"
|
||||
:style="[{ transform: data.index === data.activeIndex ? 'scale(1.05)' : 'scale(1)' }]"
|
||||
>
|
||||
<SortCollege :college="data" :score="score" :college-index="data.index + 1" />
|
||||
</view>
|
||||
</template>
|
||||
</DragSortList>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useUserStore } from '@/store/user'
|
||||
import HeaderTip from './components/HeaderTip.vue'
|
||||
import DragSortList from '@/pages-sub/components/dragSort/DragSort.vue'
|
||||
import SortCollege from './components/SortCollege.vue'
|
||||
|
||||
import { useUserStore } from '@/store/user'
|
||||
import { useScore } from './composable/useWishesList'
|
||||
const userStore = useUserStore()
|
||||
|
||||
const { score } = useScore(
|
||||
userStore.userInfo.estimatedAchievement.provinceCode,
|
||||
userStore.userInfo.batchName,
|
||||
)
|
||||
|
||||
const wishList = ref(userStore.userInfo.wishList)
|
||||
|
||||
const myDrop = ref()
|
||||
|
||||
const getDropList = (list) => {
|
||||
// 拖拽完毕后获取到的数据
|
||||
console.log(list, 'eeee')
|
||||
}
|
||||
const touchstart = (i) => {
|
||||
// 默认是长按才能拖动,可根据需求,通过触摸拖动元素
|
||||
console.log(myDrop.value)
|
||||
|
||||
myDrop.value.handleLongpress(i)
|
||||
}
|
||||
const changeList = () => {
|
||||
// 如果新增或者删除了数据,请调用此函数
|
||||
let list = wishList
|
||||
myDrop.value.initList(list, true)
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -239,18 +239,6 @@
|
|||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "home/wishesList/CollegeMajor",
|
||||
"type": "page"
|
||||
},
|
||||
{
|
||||
"path": "home/wishesList/DataTable",
|
||||
"type": "page"
|
||||
},
|
||||
{
|
||||
"path": "home/wishesList/HeaderTip",
|
||||
"type": "page"
|
||||
},
|
||||
{
|
||||
"path": "home/wishesList/index",
|
||||
"type": "page",
|
||||
|
|
@ -258,13 +246,12 @@
|
|||
"navigationBarTitleText": "我的志愿表"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "home/wishesList/ScrollListItem",
|
||||
"type": "page"
|
||||
},
|
||||
{
|
||||
"path": "home/wishesList/wishesList",
|
||||
"type": "page"
|
||||
"type": "page",
|
||||
"style": {
|
||||
"navigationBarTitleText": "当前志愿表"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
|||
|
|
@ -118,9 +118,9 @@ export const useUserStore = defineStore(
|
|||
userInfo.value.batchName = val
|
||||
}
|
||||
|
||||
const setWishListMajor = ({ val, unId }: { val: any; unId: string }) => {
|
||||
const setWishListMajor = ({ val, uId }: { val: any; uId: string }) => {
|
||||
try {
|
||||
const targetItem = userInfo.value.wishList.find((item) => item.unId === unId)
|
||||
const targetItem = userInfo.value.wishList.find((item) => item.uId === uId)
|
||||
if (!targetItem) {
|
||||
console.error('未找到对应的志愿清单项')
|
||||
return
|
||||
|
|
@ -129,7 +129,7 @@ export const useUserStore = defineStore(
|
|||
userInfo.value = {
|
||||
...userInfo.value,
|
||||
wishList: userInfo.value.wishList.map((item) => {
|
||||
if (item.unId === unId) {
|
||||
if (item.uId === uId) {
|
||||
return {
|
||||
...item,
|
||||
vItems: [...item.vItems, { ...val, sort: item.vItems.length + 1 }],
|
||||
|
|
@ -143,10 +143,10 @@ export const useUserStore = defineStore(
|
|||
}
|
||||
}
|
||||
|
||||
const deleteWishListMajor = ({ unId, _pId }: { unId: string; _pId: string }) => {
|
||||
const deleteWishListMajor = ({ uId, planId }: { uId: string; planId: string }) => {
|
||||
userInfo.value.wishList = userInfo.value.wishList.map((item) => {
|
||||
if (item.unId === unId) {
|
||||
item.vItems = item.vItems.filter((vItem) => vItem._pId !== _pId)
|
||||
if (item.uId === uId) {
|
||||
item.vItems = item.vItems.filter((vItem) => vItem.planId !== planId)
|
||||
return item
|
||||
}
|
||||
return item
|
||||
|
|
|
|||
|
|
@ -27,11 +27,7 @@ interface NavigateToOptions {
|
|||
"/pages-sub/home/news/index" |
|
||||
"/pages-sub/home/news/newsList" |
|
||||
"/pages-sub/home/schoolRank/index" |
|
||||
"/pages-sub/home/wishesList/CollegeMajor" |
|
||||
"/pages-sub/home/wishesList/DataTable" |
|
||||
"/pages-sub/home/wishesList/HeaderTip" |
|
||||
"/pages-sub/home/wishesList/index" |
|
||||
"/pages-sub/home/wishesList/ScrollListItem" |
|
||||
"/pages-sub/home/wishesList/wishesList" |
|
||||
"/login-sub/index" |
|
||||
"/pages-evaluation-sub/index" |
|
||||
|
|
|
|||
Loading…
Reference in New Issue