Bläddra i källkod

考试列表更新

wangxy 10 månader sedan
förälder
incheckning
59b1a10f69

+ 12 - 0
api/exam.js

@@ -0,0 +1,12 @@
+import request from '@/utils/request'
+export function getExamList(data = {}) {
+  return request({
+    'url': '/app/kaoshi/list',
+    headers: {
+      isToken: true
+    },
+    method: 'post',
+    data,
+    timeout: 20000
+  })
+}

+ 183 - 0
components/custom-scroll-list/custom-scroll-list.vue

@@ -0,0 +1,183 @@
+<template>
+	<!-- 查询区域 -->
+	<uni-search-bar class="uni-mt-10" v-model="name" radius="100" v-if="hasSearcBar" :placeholder="placeholder"
+		:bgColor="searchBarColor" clearButton="auto" cancelButton="none" @confirm="onSearch" @blur="onSearch" />
+	<!-- tab选择区域 -->
+	<view class="lli-status-box" v-if="hasTab">
+		<text :class="['status-item', activeTab === item.value? 'click':'' ]" v-for="item in tabList" :key="item.value"
+			@click="onTavChange(item)">{{item.label}}</text>
+	</view>
+	<!-- 无限滚动区域 -->
+	<scroll-view class="scroll-container" :scroll-y="true" :refresher-enabled="true" :refresher-triggered="triggered"
+		:refresher-threshold="100" refresher-background="lightgreen" @refresherrefresh="onRefresh"
+		@scrolltolower="onReachBottom" @refresherrestore="onRestore">
+		<slot :list="list"></slot>
+		<view style="width: 100%;text-align: center;font-size: 14px;color:#ccc;" v-if="isComplete">没有更多啦~</view>
+	</scroll-view>
+</template>
+
+<script setup>
+	import {
+		ref,
+		onMounted,
+		computed
+	} from "vue";
+
+	import {
+		onLoad
+	} from "@dcloudio/uni-app"
+
+	const props = defineProps({
+		refreshFn: {
+			type: Function,
+			required: true
+		},
+		tabData: {
+			type: Object
+		},
+		size: {
+			type: Number,
+			default: 2
+		},
+		hasSearcBar: {
+			type: Boolean,
+			default: true,
+		},
+		searchBarKey: {
+			type: String,
+			default: 'name'
+		},
+		hasTab: {
+			type: Boolean,
+			default: true,
+		},
+		defaultTab: {
+			type: [String, Number]
+		},
+		tabList: {
+			type: Array,
+			default: () => [],
+		},
+		tabKey: {
+			type: String,
+			default: 'status'
+		},
+		placeholder: {
+			type: String,
+			default: '请输入考试名称'
+		},
+		searchBarColor: {
+			type: String,
+			default: "#F3F3F4"
+		},
+		tabData: {
+			type: Object,
+		}
+
+	})
+
+	const page = ref(1);
+	const list = ref([]); // 项目列表
+	const triggered = ref(false); // 是否触发下拉刷新
+	const freshing = ref(false); // 是否加载中
+	const total = ref(0); // 项目总数
+	const name = ref(''); // 查询名
+	const activeTab = ref(props.defaultTab);
+
+	/**
+	 * 是否已完全加载
+	 */
+	const isComplete = computed(() => {
+		if (total.value === 0) {
+			return false;
+		}
+		return total.value === list.value.length
+	})
+
+	// 重置
+	function reset() {
+		list.value = [];
+		page.value = 1;
+		triggered.value = false;
+		freshing.value = false;
+		total.value = 0;
+	}
+
+	// 切换tab
+	function onTavChange(item) {
+		activeTab.value = item.value;
+		name.value = "";
+		reset();
+		getData("do-search");
+	}
+
+	// 查询
+	function onSearch({
+		value
+	}) {
+		name.value = value;
+		reset();
+		getData("do-search");
+	}
+
+	// 获取数据
+	function getData(action) {
+		const options = Object.assign({}, {
+			page: page.value,
+			size: props.size,
+		});
+
+		if (props.hasTab) {
+			options[props.tabKey] = activeTab.value;
+		}
+
+		if (props.hasSearcBar) {
+			options[props.searchBarKey] = name.value;
+		}
+		props.refreshFn(options).then(res => {
+			total.value = res.data.total;
+			action === "do-search" && (list.value = res.data.data); // 查询更新
+			action === "pull-down-refresh" && (list.value = res.data.data); // 下拉更新数据
+			action === "reach-buttom" && (list.value = [...list.value, ...res.data.data]); // 无限滚动更新数据
+		}).finally(() => {
+			triggered.value = false;
+			freshing.value = false;
+		})
+	}
+
+	onLoad(() => {
+		freshing.value = false;
+		setTimeout(() => {
+			triggered.value = true
+		}, 50)
+	})
+
+	// 下拉刷新触发
+	function onRefresh() {
+		if (freshing.value) return;
+		freshing.value = true;
+		triggered.value = true;
+		page.value = 1;
+		getData('pull-down-refresh');
+	}
+
+	// 下拉刷新复位
+	function onRestore() {
+		triggered.value = 'restore'; // 需要重置
+	}
+
+	// 无限滚动
+	function onReachBottom() {
+		if (freshing.value) return;
+		if (isComplete.value) return;
+		freshing.value = true;
+		page.value++;
+		getData('reach-buttom')
+	}
+</script>
+
+<style lang="scss">
+	.scroll-container {
+		height: calc(100vh - 220rpx)
+	}
+</style>

+ 162 - 0
components/scroll-list-card/scroll-list-card.vue

@@ -0,0 +1,162 @@
+<template>
+	<view class="scroll-list-card mobile-card-box">
+		<!--   title     -->
+		<text class="mobile-card-title">{{data.ksName === null ? '':data.ksName}}</text>
+		<!--   content   -->
+		<view class="mobile-card-row">
+			时间:{{data.ksStartTime === null ? '':data.ksStartTime}}-{{data.ksEndTime === null ? '':data.ksEndTime}}
+		</view>
+		<view class="mobile-card-row">
+			<text>总分:{{data.ksScore === null ? '':data.ksScore}}</text>
+			<text class="card-score-box">学分:{{data.credit === null ? '':data.credit}}</text>
+		</view>
+		<view class="mobile-card-row">
+			<text>及格分:{{data.okScore === null ? '':data.okScore}}</text>
+			<text class="card-score-box">考试时长:{{data.totalTm === null ? '':data.totalTm}}分钟</text>
+		</view>
+		<!--    button    -->
+		<template v-for="item in btns">
+			<button class="lli-btn" @click="btnClick(item)" v-if="item.show" :key="item.code"
+				:disabled="data.disabled">{{item.text}}</button>
+		</template>
+	</view>
+</template>
+
+<script setup>
+	import {
+		toRefs,
+		ref,
+		computed
+	} from "vue";
+
+	const props = defineProps({
+		data: {
+			type: Object
+		}
+	})
+	const {
+		data
+	} = toRefs(props)
+
+	const btns = computed(() => [{
+			status: 0,
+			btnType: 'kaoshi',
+			text: '未开始',
+			show: data.value.status === 0,
+		},
+		{
+			status: 1,
+			btnType: 'kaoshi',
+			text: '开始考试',
+			show: data.value.status === 1,
+		},
+		{
+			status: 3,
+			btnType: 'kaoshi',
+			text: '考试中',
+			show: data.value.status === 3,
+		},
+		{
+			status: 2,
+			btnType: 'kaoshi',
+			text: '再次考试',
+			show: data.value.status === 2,
+		},
+		{
+			code: 4,
+			btnType: 'kaoshi',
+			text: '已结束',
+			show: data.value.status === 4,
+		},
+		{
+			status: 5,
+			btnType: 'kaoshi',
+			text: '报名',
+			show: data.value.status === 5,
+		},
+		{
+			status: 6,
+			btnType: 'kaoshi',
+			text: '报名审核中',
+			show: data.value.status === 6,
+		},
+		{
+			status: 7,
+			btnType: 'kaoshi',
+			text: '审核未通过',
+			show: data.value.status === 7,
+		},
+		{
+			status: 8,
+			btnType: 'kaoshi',
+			text: '等待人工评分',
+			show: data.value.status === 8,
+		},
+	])
+
+
+
+	console.log(btns)
+</script>
+
+<style lang="scss" scoped>
+	.mobile-card-box {
+		box-sizing: border-box;
+		margin: 0 30rpx 10rpx;
+		border-bottom: 2rpx solid #f2f1f2;
+	}
+
+	.mobile-card-title {
+		color: #333;
+		font-size: 32rpx;
+		font-weight: 500;
+		margin: 24rpx 0 24rpx 0;
+		text-overflow: ellipsis;
+		-o-text-overflow: ellipsis;
+		overflow: hidden;
+		word-wrap: break-word;
+		display: -webkit-box;
+		white-space: normal;
+		-webkit-box-orient: vertical;
+		text-align: justify;
+		-webkit-line-clamp: 2;
+		line-clamp: 2;
+		line-height: 48rpx;
+	}
+
+	// 行
+	.mobile-card-row {
+		margin-bottom: 32rpx;
+		display: flex;
+		justify-content: space-between;
+		align-items: flex-end;
+
+		text {
+			font-size: 28rpx;
+			line-height: 40rpx
+		}
+
+		// 得分
+		.mobile-card-score {
+			font-size: 40rpx;
+			color: #F10A0A;
+		}
+
+		// 分数(有最小宽度)
+		.card-score-box {
+			min-width: 240rpx;
+			text-align: left;
+		}
+	}
+
+	// 按钮
+	.mobile-card-btn {
+		width: 60%;
+		height: 80rpx;
+		line-height: 80rpx;
+		margin: 50rpx auto;
+		background: linear-gradient(0deg, #436aff 0%, #234ff7 100%);
+		border-radius: 80rpx;
+		display: block;
+	}
+</style>

+ 30 - 14
pages/exam/index.vue

@@ -1,20 +1,36 @@
 <template>
-	<mta-scroll-list @pull-down-refresh="onPulldownRefresh" @reach-buttom="onReachButtom" refreshUrl="/api/admin/config">
-		<card-item v-for="(item,index) in list" :key="index"></card-item>
-	</mta-scroll-list>
+	<custom-scroll-list :refreshFn="getExamList" :tabList="tabData" :defaultTab="1">
+		<template #default="{list}">
+			<scroll-list-card  v-for="item in list" :data="item" :key="item.ksId"></scroll-list-card>
+		</template>
+	</custom-scroll-list>
 </template>
 
 <script setup>
-	import {ref} from "vue";
-	const list = ref([]);
-	function onPulldownRefresh(data) {
-		list.value = data;
-	}
-	function onReachButtom(data) {
-		list.value.concat(data);
-	}
+	import {
+		getExamList
+	} from "@/api/exam.js";
+	import {
+		// onLoad,
+		onReady,
+		
+	} from "@dcloudio/uni-app"
+	import {
+		reactive,
+		ref
+	} from "vue";
+
+	const tabData = [{
+			label: "可以考试",
+			value: 1,
+		},
+		{
+			label: "已结束",
+			value: 4,
+		}
+	]
 </script>
 
-<style>
-	       
-</style>
+<style lang="scss">
+
+</style>