feat: 完善运动记录展示、体测导出与列表布局
AI运动站展示成绩值及课目单位,保留未知课目编号的可识别名称;AI阳光跑列表隐藏有效里程和有效用时列。 体测数据记录增加年级-班级级联筛选,800/1000 米成绩按分秒展示;导出时带上当前筛选条件并下载完整 Excel 数据。 公共管理列表与报表列表根据筛选区域和视口动态调整表格高度,使分页保持可见;体测汇总页两个标签单独采用弹性布局,弹窗表格不受影响。 登录表单支持回车聚焦密码与提交,并增加提交中的防重复处理。
This commit is contained in:
parent
4e77cfeed2
commit
765b7c545c
@ -164,6 +164,13 @@ export function GetSportsTestResultPageList(a, b, c, d, e, f, g, h) {
|
||||
return http.get(`/api/SportsTestResult/GetSportsTestCategoryPageList?TeacherId=${a}&GradeId=${b}&ClassId=${c}&StudentNo=${d}&Sex=${e}&CategoryId=${f}&PageIndex=${g}&PageSize=${h}`)
|
||||
}
|
||||
|
||||
export function ExportSummaryOfGradesTestRecords(params) {
|
||||
return http.get('/api/SportsTestResult/ExportSummaryOfGrades', null, false, {
|
||||
params,
|
||||
responseType: 'blob'
|
||||
})
|
||||
}
|
||||
|
||||
export function AddSportsTestResult(params) {
|
||||
return http.post(`/api/SportsTestResult/Add`, params)
|
||||
}
|
||||
|
||||
@ -1,11 +1,26 @@
|
||||
<template>
|
||||
<div class="commonManage">
|
||||
<div ref="containerRef" class="commonManage" :class="{ 'fitted-list': fitsViewport }">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import { useViewportTableFit } from '@/utils/useViewportTableFit';
|
||||
|
||||
const containerRef = ref<HTMLElement | null>(null);
|
||||
const { fitsViewport } = useViewportTableFit(containerRef, ':scope > .cont');
|
||||
</script>
|
||||
<style lang="less">
|
||||
.commonManage.fitted-list > .cont {
|
||||
height: auto !important;
|
||||
min-height: 0 !important;
|
||||
}
|
||||
|
||||
.commonManage.fitted-list > .cont > .el-table {
|
||||
height: var(--fitted-table-height) !important;
|
||||
max-height: var(--fitted-table-height) !important;
|
||||
}
|
||||
</style>
|
||||
<style lang="less" scoped>
|
||||
.commonManage {
|
||||
// width: calc(100% - 32px);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="commonTable">
|
||||
<div ref="containerRef" class="commonTable" :class="{ 'fitted-table': fitsViewport }">
|
||||
<el-table v-loading="Boolean(propsTableNeed.loading) || paginationLoading" element-loading-text="数据加载中..."
|
||||
element-loading-background="rgba(255, 255, 255, 0.76)" :data="propsChannel" highlight-current-row stripe
|
||||
style="width: calc(100% - 40px) ;height: calc(100vh - 330px); margin:0 20px ;" fit="true"
|
||||
@ -29,8 +29,11 @@
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { computed, ref } from 'vue'
|
||||
import { useTablePaginationLoading } from '@/utils/tablePaginationLoading'
|
||||
import { useViewportTableFit } from '@/utils/useViewportTableFit'
|
||||
const containerRef = ref<HTMLElement | null>(null)
|
||||
const { fitsViewport } = useViewportTableFit(containerRef)
|
||||
const props = defineProps<{
|
||||
tableNeed: any,
|
||||
operationPermissions?: Record<string, boolean>
|
||||
@ -96,6 +99,13 @@ function goUp(row) {
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
.commonTable.fitted-table > .el-table {
|
||||
height: var(--fitted-table-height) !important;
|
||||
max-height: var(--fitted-table-height) !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
||||
.commonTable {
|
||||
|
||||
59
src/utils/useViewportTableFit.ts
Normal file
59
src/utils/useViewportTableFit.ts
Normal file
@ -0,0 +1,59 @@
|
||||
import { nextTick, onBeforeUnmount, onMounted, onUpdated, ref, type Ref } from 'vue'
|
||||
|
||||
export function useViewportTableFit(rootRef: Ref<HTMLElement | null>, contentSelector?: string) {
|
||||
const fitsViewport = ref(false)
|
||||
let frame = 0
|
||||
let observer: ResizeObserver | undefined
|
||||
let observedHeader: Element | null = null
|
||||
|
||||
function fit() {
|
||||
const root = rootRef.value
|
||||
if (!root?.closest('#vol-main') || root.closest('.el-dialog, .el-drawer')) {
|
||||
fitsViewport.value = false
|
||||
return
|
||||
}
|
||||
const content = contentSelector ? root?.querySelector<HTMLElement>(contentSelector) : root
|
||||
const table = content?.querySelector<HTMLElement>(':scope > .el-table')
|
||||
const pagination = content?.querySelector<HTMLElement>(':scope > .el-pagination')
|
||||
fitsViewport.value = !!(table && pagination)
|
||||
if (!root || !content || !table || !pagination) return
|
||||
|
||||
const header = contentSelector ? content.previousElementSibling : root.previousElementSibling
|
||||
if (header !== observedHeader) {
|
||||
observer?.disconnect()
|
||||
if (header) observer?.observe(header)
|
||||
observedHeader = header
|
||||
}
|
||||
|
||||
const scrollView = root.closest('.el-scrollbar__view')
|
||||
const scrollTop = scrollView?.parentElement?.scrollTop || 0
|
||||
const bottom = document.querySelector('#vol-main')?.getBoundingClientRect().bottom || window.innerHeight
|
||||
const paginationStyle = getComputedStyle(pagination)
|
||||
const contentStyle = getComputedStyle(content)
|
||||
const reserved = pagination.getBoundingClientRect().height
|
||||
+ (parseFloat(paginationStyle.marginTop) || 0) + (parseFloat(paginationStyle.marginBottom) || 0)
|
||||
+ (parseFloat(contentStyle.paddingBottom) || 0) + 16
|
||||
const height = Math.max(180, Math.floor(bottom - table.getBoundingClientRect().top - scrollTop - reserved))
|
||||
root.style.setProperty('--fitted-table-height', `${height}px`)
|
||||
}
|
||||
|
||||
function scheduleFit() {
|
||||
cancelAnimationFrame(frame)
|
||||
frame = requestAnimationFrame(fit)
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
observer = new ResizeObserver(scheduleFit)
|
||||
window.addEventListener('resize', scheduleFit)
|
||||
await nextTick()
|
||||
scheduleFit()
|
||||
})
|
||||
onUpdated(scheduleFit)
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener('resize', scheduleFit)
|
||||
observer?.disconnect()
|
||||
cancelAnimationFrame(frame)
|
||||
})
|
||||
|
||||
return { fitsViewport }
|
||||
}
|
||||
@ -56,10 +56,13 @@
|
||||
<el-table-column fixed prop="ind" label="序号" width="60" />
|
||||
<el-table-column prop="studentName" label="姓名" />
|
||||
<el-table-column prop="sex" label="性别" />
|
||||
<el-table-column prop="className" label="班级" />
|
||||
<el-table-column prop="projectName" label="项目" />
|
||||
<el-table-column prop="startTime" label="运动开始时间" />
|
||||
<el-table-column prop="endTime" label="运动结束时间" />
|
||||
<el-table-column prop="className" label="班级" min-width="120" />
|
||||
<el-table-column prop="projectName" label="项目" min-width="150" />
|
||||
<el-table-column prop="score" label="成绩值" min-width="95">
|
||||
<template #default="{ row }">{{ formatScore(row) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="startTime" label="运动开始时间" min-width="170" />
|
||||
<el-table-column prop="endTime" label="运动结束时间" min-width="170" />
|
||||
</el-table>
|
||||
<el-pagination
|
||||
class="pagination"
|
||||
@ -124,6 +127,7 @@
|
||||
});
|
||||
|
||||
const projectList = [
|
||||
{ label: "待确认课目(编号2)", value: "待确认课目(编号2)" },
|
||||
{ label: "引体向上", value: "引体向上" },
|
||||
{ label: "立定跳远", value: "立定跳远" },
|
||||
{ label: "跳绳", value: "跳绳" },
|
||||
@ -143,6 +147,18 @@
|
||||
{ label: "体重系数(BMI)", value: "体重系数(BMI)" },
|
||||
{ label: "肺活量", value: "肺活量" },
|
||||
];
|
||||
|
||||
const scoreUnits: Record<number, string> = {
|
||||
3: "次", 7: "米", 8: "次", 9: "次", 10: "次", 11: "次",
|
||||
23: "厘米", 24: "次", 25: "次", 26: "次", 27: "次",
|
||||
28: "次", 29: "次", 30: "次", 31: "次", 32: "次",
|
||||
1001: "kg/m²", 1002: "毫升"
|
||||
};
|
||||
|
||||
function formatScore(row: { score?: number | null; courseId?: number }) {
|
||||
if (row.score === null || row.score === undefined) return "-";
|
||||
return `${row.score}${scoreUnits[row.courseId ?? 0] ?? "(单位待确认)"}`;
|
||||
}
|
||||
const data = ref({
|
||||
classList: [] as any[],
|
||||
tableNeed: {
|
||||
|
||||
@ -19,6 +19,12 @@
|
||||
:value="item.id" />
|
||||
</el-select>
|
||||
</div>
|
||||
<div v-if="props.embeddedInSummary" class="one grade-class-filter">
|
||||
<p class="desctipt">年级-班级:</p>
|
||||
<el-cascader v-model="gradeClassSelection" class="m-2" :options="gradeClassOptions"
|
||||
:props="{ checkStrictly: true }" clearable filterable placeholder="全部"
|
||||
@change="onGradeClassChange" />
|
||||
</div>
|
||||
<!-- <div class="one">
|
||||
<p class="desctipt">年级:</p>
|
||||
<el-select v-model="data.GradeId" class="m-2" clearable>
|
||||
@ -46,6 +52,8 @@
|
||||
<p v-for="(item, index) in toolbarButtons" :key="index" :class="item.className"
|
||||
@click="btnClick(item.engName)">
|
||||
{{ item.chinName }}</p>
|
||||
<el-button v-if="props.embeddedInSummary" class="Export" :icon="Download"
|
||||
:loading="exporting" @click="exportData">导出成绩</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cont" :class="{ 'summary-cont': props.embeddedInSummary }">
|
||||
@ -56,26 +64,30 @@
|
||||
: { width: 'calc(100% - 40px)', minHeight: '420px', height: 'calc(100vh - 430px)', margin: '0 20px' }" fit="true"
|
||||
:header-cell-style="{ 'text-align': 'center', 'font-size': '12px', 'color': '#3F404A', padding: '3px', background: '#F8F8FA', height: '50px' }"
|
||||
:cell-style="getCellStyles" :row-style="{ height: '0px' }">
|
||||
<el-table-column fixed prop="ind" label="序号" />
|
||||
<el-table-column fixed prop="ind" label="序号" width="120"/>
|
||||
<!-- <el-table-column prop="teacherId" label="老师" width="100" /> -->
|
||||
<!-- <el-table-column prop="gradeId" label="年级" width="120" /> -->
|
||||
<!-- <el-table-column prop="categoryId" label="测试类别" width="120" /> -->
|
||||
<el-table-column prop="gradeNameAndClassName" label="年级-班级" width="160" />
|
||||
<el-table-column prop="studentName" label="学生姓名" width="120" />
|
||||
<el-table-column prop="studentName" label="学生姓名" width="160" />
|
||||
<el-table-column prop="studentNo" label="学生学号" width="120" />
|
||||
<el-table-column prop="sex" label="性别" width="80" />
|
||||
<el-table-column prop="categoryName" label="测试类别" width="120" />
|
||||
<el-table-column prop="value" label="测试结果" width="120" />
|
||||
<el-table-column prop="motionDuration" label="运动时长/分钟" width="120" />
|
||||
<el-table-column prop="consumption" label="运动消耗" width="120" />
|
||||
<el-table-column prop="strength" label="运动强度" width="120" />
|
||||
<el-table-column prop="categoryName" label="测试类别" width="160" />
|
||||
<el-table-column prop="value" label="测试结果" width="120">
|
||||
<template #default="{ row }">
|
||||
{{ props.embeddedInSummary ? formatTestResult(row) : row.value }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-if="!props.embeddedInSummary" prop="motionDuration" label="运动时长/分钟" width="120" />
|
||||
<el-table-column v-if="!props.embeddedInSummary" prop="consumption" label="运动消耗" width="120" />
|
||||
<el-table-column v-if="!props.embeddedInSummary" prop="strength" label="运动强度" width="120" />
|
||||
<el-table-column prop="score" label="得分" width="120" />
|
||||
<el-table-column prop="rank" label="等级" width="120" />
|
||||
<el-table-column prop="classRank" label="班级排名" width="120" />
|
||||
<el-table-column prop="scoreTime" label="测试时间" width="160" />
|
||||
|
||||
<!-- <el-table-column prop="remarks" label="备注" /> -->
|
||||
<el-table-column v-if="showRowOperate" label="操作" width="140" fixed="right">
|
||||
<el-table-column v-if="showRowOperate" label="操作" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<div class="operate">
|
||||
<p class="edit" @click="editTable(row)">编辑</p>
|
||||
@ -145,6 +157,7 @@ import * as _api from '@/api/grade';
|
||||
import eventBus from '@/eventBus.js'; // 导入事件总线
|
||||
import { ElMessage } from 'element-plus';
|
||||
import axios from 'axios';
|
||||
import { Download } from '@element-plus/icons-vue';
|
||||
const props = withDefaults(defineProps<{
|
||||
embeddedInSummary?: boolean
|
||||
}>(), {
|
||||
@ -204,6 +217,13 @@ handelData.value.sort((a, b) => {
|
||||
});
|
||||
const toolbarButtons = computed(() => handelData.value.filter((item) => item.engName !== 'Export' && item.engName !== 'Import' && item.engName !== 'Update' && item.engName !== 'Delete'))
|
||||
const showRowOperate = computed(() => true)
|
||||
const gradeClassSelection = ref<number[]>([])
|
||||
const gradeClassOptions = computed(() => data.value.GradeData.map((grade: any) => ({
|
||||
value: grade.id,
|
||||
label: grade.gradeName,
|
||||
children: (grade.class || []).map((cls: any) => ({ value: cls.id, label: cls.className }))
|
||||
})))
|
||||
const exporting = ref(false)
|
||||
const ruleForm = ref({
|
||||
studentNo: '',
|
||||
categoryEnum: '',
|
||||
@ -419,7 +439,7 @@ function btnClick(val) {
|
||||
console.log(val, 'vallll')
|
||||
switch (val) {
|
||||
case 'Search':
|
||||
// data.value.tableNeed.refresh = false
|
||||
data.value.tableNeed.pageIndex = 1
|
||||
initApi(data.value)
|
||||
break
|
||||
case 'Add':
|
||||
@ -462,10 +482,36 @@ onMounted(() => {
|
||||
getGrade()
|
||||
getCategoryList()
|
||||
})
|
||||
function onGradeClassChange(selection: number[] | null) {
|
||||
data.value.GradeId = selection?.[0] ?? 0
|
||||
data.value.ClassId = selection?.[1] ?? 0
|
||||
}
|
||||
|
||||
function getQueryParams() {
|
||||
return {
|
||||
TeacherId: data.value.TeacherId || 0,
|
||||
GradeId: data.value.GradeId || 0,
|
||||
ClassId: data.value.ClassId || 0,
|
||||
StudentNo: data.value.StudentNo || '',
|
||||
Sex: data.value.Sex || 0,
|
||||
CategoryId: data.value.CategoryId || 0
|
||||
}
|
||||
}
|
||||
|
||||
function formatTestResult(row: any) {
|
||||
if (Number(row.categoryValue) !== 10 && Number(row.categoryValue) !== 11) return row.value
|
||||
const value = Number(row.value)
|
||||
if (!Number.isFinite(value)) return '-'
|
||||
// Historical imported values above this range are milliseconds; normal results are seconds.
|
||||
const totalSeconds = Math.round(Math.max(0, value >= 10000 ? value / 1000 : value))
|
||||
return `${Math.floor(totalSeconds / 60)}分${String(totalSeconds % 60).padStart(2, '0')}秒`
|
||||
}
|
||||
//列表接口
|
||||
async function initApi(val) {
|
||||
try {
|
||||
const res = await _api.GetSportsTestResultPageList(val.TeacherId, val.GradeId, val.ClassId, val.StudentNo, val.Sex, val.CategoryId, val.tableNeed.pageIndex, val.tableNeed.pageSize);
|
||||
const filters = getQueryParams()
|
||||
const res = await _api.GetSportsTestResultPageList(filters.TeacherId, filters.GradeId, filters.ClassId,
|
||||
filters.StudentNo, filters.Sex, filters.CategoryId, val.tableNeed.pageIndex, val.tableNeed.pageSize);
|
||||
if (res.code == 200) {
|
||||
val.tableNeed.tableData = res.data.datas;
|
||||
val.tableNeed.tableData.map((i, index) => {
|
||||
@ -595,27 +641,25 @@ async function DeleteList(val) {
|
||||
console.error('Error occurred while calling API:', error);
|
||||
}
|
||||
}
|
||||
function exportData(val) {
|
||||
axios({
|
||||
method: 'get',
|
||||
url: `/api/SportsTestResult/Export?TeacherId=${val.TeacherId}&GradeId=${val.GradeId}&ClassId=${val.ClassId}&StudentNo=${val.StudentNo}&Sex=${val.Sex}&CategoryId=${val.CategoryId}&PageIndex=${val.tableNeed.pageIndex}&PageSize=${val.tableNeed.pageSize}`,
|
||||
// data: data,
|
||||
responseType: 'blob'
|
||||
})
|
||||
.then((res) => {
|
||||
const blob = new Blob([res.data])
|
||||
const fileName = `体测数据.xlsx`
|
||||
if ('download' in document.createElement('a')) {
|
||||
const elink = document.createElement('a')
|
||||
elink.download = fileName
|
||||
elink.style.display = 'none'
|
||||
elink.href = URL.createObjectURL(blob)
|
||||
document.body.appendChild(elink)
|
||||
elink.click()
|
||||
URL.revokeObjectURL(elink.href)
|
||||
document.body.removeChild(elink)
|
||||
}
|
||||
})
|
||||
async function exportData() {
|
||||
if (exporting.value) return
|
||||
exporting.value = true
|
||||
try {
|
||||
const blob = await _api.ExportSummaryOfGradesTestRecords(getQueryParams())
|
||||
if (!(blob instanceof Blob) || blob.type.includes('json')) throw new Error('导出失败')
|
||||
const url = URL.createObjectURL(blob)
|
||||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
link.download = `体测数据记录${new Date().toISOString().slice(0, 10)}.xlsx`
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
link.remove()
|
||||
setTimeout(() => URL.revokeObjectURL(url), 1000)
|
||||
} catch (error) {
|
||||
ElMessage.error('导出失败,请重试')
|
||||
} finally {
|
||||
exporting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
//导入
|
||||
@ -916,6 +960,9 @@ async function AddList() {
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
overflow: visible;
|
||||
height: calc(100dvh - 180px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.head {
|
||||
width: calc(100% - 32px) !important;
|
||||
@ -957,6 +1004,22 @@ async function AddList() {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.one.grade-class-filter {
|
||||
width: 320px !important;
|
||||
max-width: 100%;
|
||||
|
||||
p {
|
||||
width: 104px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.m-2 {
|
||||
flex: 1;
|
||||
width: auto;
|
||||
min-width: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.right.btn {
|
||||
@ -990,10 +1053,18 @@ async function AddList() {
|
||||
margin: 0 auto;
|
||||
padding: 0 0 16px;
|
||||
box-sizing: border-box;
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.summary-table-card {
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
border: 1px solid #e7eef8;
|
||||
border-radius: 10px;
|
||||
@ -1005,6 +1076,9 @@ async function AddList() {
|
||||
}
|
||||
|
||||
:deep(.el-table) {
|
||||
flex: 1;
|
||||
min-height: 0 !important;
|
||||
height: 0 !important;
|
||||
width: 100% !important;
|
||||
margin: 0 !important;
|
||||
border-radius: 0;
|
||||
@ -1016,6 +1090,7 @@ async function AddList() {
|
||||
}
|
||||
|
||||
:deep(.el-pagination) {
|
||||
flex-shrink: 0;
|
||||
margin: 14px 18px 18px !important;
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,21 +29,24 @@
|
||||
|
||||
<div class="card-subtitle">智慧运动平台</div>
|
||||
<el-form ref="ruleFormRef" :model="loginAllData.loginData.ruleForm"
|
||||
:rules="loginAllData.loginData.rules" class="login-form">
|
||||
:rules="loginAllData.loginData.rules" class="login-form"
|
||||
@submit.prevent="submitForm(ruleFormRef)">
|
||||
<el-form-item prop="userName">
|
||||
<el-input v-model="loginAllData.loginData.ruleForm.userName" placeholder="请输入用户名" clearable
|
||||
autocomplete="off" :prefix-icon="UserFilled">
|
||||
autocomplete="username" :prefix-icon="UserFilled" @keydown.enter.prevent="focusPassword">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="password">
|
||||
<el-input v-model="loginAllData.loginData.ruleForm.password" type="password"
|
||||
placeholder="请输入密码" clearable autocomplete="off" show-password :prefix-icon="Lock">
|
||||
<el-input ref="passwordInputRef" v-model="loginAllData.loginData.ruleForm.password"
|
||||
type="password" placeholder="请输入密码" clearable autocomplete="current-password"
|
||||
show-password :prefix-icon="Lock">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<button class="submit-btn" :class="{ 'is-loading': loginLoading }" type="submit"
|
||||
:disabled="loginLoading">
|
||||
<span>{{ loginLoading ? '登录中' : '登录' }}</span>
|
||||
</button>
|
||||
</el-form>
|
||||
<div class="submit-btn" :class="{ 'is-loading': loginLoading }" @click="submitForm(ruleFormRef)">
|
||||
<span>{{ loginLoading ? '登录中' : '登录' }}</span>
|
||||
</div>
|
||||
<!-- <p class="card-footer">加油,同学!运动让你更棒 ⭐</p> -->
|
||||
</div>
|
||||
</div>
|
||||
@ -168,6 +171,7 @@ const imageUrls = [
|
||||
const preloadedImages = ref({});
|
||||
let router = useRouter();
|
||||
const ruleFormRef = ref()
|
||||
const passwordInputRef = ref()
|
||||
const registerRef = ref()
|
||||
const ModifyPwdRef1 = ref()
|
||||
let appContext = getCurrentInstance().appContext;
|
||||
@ -289,12 +293,7 @@ const cancle = () => {
|
||||
loginAllData.value.ModifyPwd.ModifyPwdDialog = false
|
||||
resetForm(ModifyPwdRef1.value)
|
||||
}
|
||||
const loginPress = (e) => {
|
||||
console.log(e, 'eeeee')
|
||||
if (e.keyCode == 13) {
|
||||
submitForm(ruleFormRef.value)
|
||||
}
|
||||
};
|
||||
const focusPassword = () => passwordInputRef.value?.focus()
|
||||
const getPasswordStrengthPercentage = (password) => {
|
||||
const result = zxcvbn(password);
|
||||
return (result.score / 4) * 100;
|
||||
@ -381,18 +380,19 @@ let loginAllData = ref({
|
||||
}
|
||||
})
|
||||
//点击登录
|
||||
const submitForm = (formEl) => {
|
||||
if (loginLoading.value) return
|
||||
let submitPending = false
|
||||
const submitForm = async (formEl) => {
|
||||
if (submitPending || loginLoading.value) return
|
||||
if (!formEl) return
|
||||
formEl.validate((valid) => {
|
||||
console.log(valid, 'valid')
|
||||
submitPending = true
|
||||
try {
|
||||
const valid = await formEl.validate().catch(() => false)
|
||||
if (valid) {
|
||||
loginApi(loginAllData.value.loginData.ruleForm)
|
||||
} else {
|
||||
console.log('error submit!')
|
||||
return false
|
||||
await loginApi(loginAllData.value.loginData.ruleForm)
|
||||
}
|
||||
})
|
||||
} finally {
|
||||
submitPending = false
|
||||
}
|
||||
}
|
||||
//清空输入框内容
|
||||
const resetForm = (formEl) => {
|
||||
@ -476,7 +476,6 @@ onMounted(() => {
|
||||
// handleScreenAuto()
|
||||
preloadImages()
|
||||
store.commit('clearUserInfo', '');
|
||||
window.addEventListener('keydown', handleKeyDown)
|
||||
})
|
||||
const handleScreenAuto = () => {
|
||||
const designWidth = 1920;
|
||||
@ -507,13 +506,6 @@ const handleScreenAuto = () => {
|
||||
document.getElementById('login').style.marginLeft = `${offsetX}px`;
|
||||
document.getElementById('login').style.marginTop = `${offsetY}px`;
|
||||
};
|
||||
//按下回车
|
||||
const handleKeyDown = (event) => {
|
||||
const keyCode = event.keyCode || event.which
|
||||
if (keyCode == 13) {
|
||||
submitForm(ruleFormRef.value)
|
||||
}
|
||||
}
|
||||
function encryptAES(encryptString, encryptKey) {
|
||||
let key = CryptoJS.enc.Utf8.parse(encryptKey.substring(0, 16));
|
||||
let iv = CryptoJS.enc.Utf8.parse("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F");
|
||||
@ -932,6 +924,9 @@ async function ModifyPwdApi(val) {
|
||||
.submit-btn {
|
||||
width: 100%;
|
||||
height: 54px;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
font-family: inherit;
|
||||
background: linear-gradient(135deg, #00aaff 0%, #005ce6 100%);
|
||||
border-radius: 14px;
|
||||
display: flex;
|
||||
@ -968,6 +963,11 @@ async function ModifyPwdApi(val) {
|
||||
box-shadow: 0 6px 18px rgba(0, 120, 255, 0.28);
|
||||
transform: none;
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
outline: 3px solid #005ce6;
|
||||
outline-offset: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
.card-footer {
|
||||
|
||||
@ -491,13 +491,14 @@ onMounted(() => {
|
||||
|
||||
.summary-score-manage {
|
||||
width: 100%;
|
||||
min-height: calc(100vh - 166px);
|
||||
height: calc(100dvh - 180px);
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
|
||||
.sport-hall-report {
|
||||
width: 100%;
|
||||
min-height: calc(100vh - 166px);
|
||||
min-height: 0;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@ -743,11 +744,16 @@ onMounted(() => {
|
||||
padding-bottom: 0;
|
||||
box-shadow: 0 8px 22px rgba(29, 68, 130, 0.06);
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
|
||||
:deep(.el-table) {
|
||||
height: calc(100vh - 370px) !important;
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
height: 0 !important;
|
||||
border: 1px solid #e7eef8;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
@ -786,6 +792,7 @@ onMounted(() => {
|
||||
|
||||
.pagination-wrap {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
// justify-content: flex-start;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
|
||||
@ -33,8 +33,6 @@
|
||||
<el-table-column prop="studentName" label="姓名" min-width="115" />
|
||||
<el-table-column prop="sexName" label="性别" width="75" />
|
||||
<el-table-column prop="className" label="班级" min-width="150" />
|
||||
<el-table-column prop="effectiveDistance" label="有效里程" min-width="110" />
|
||||
<el-table-column prop="effectiveTime" label="有效用时" min-width="110" />
|
||||
<el-table-column prop="totalDistance" label="总里程" min-width="105" />
|
||||
<el-table-column prop="totalTime" label="总用时" min-width="105" />
|
||||
<el-table-column prop="startTime" label="开始时间" min-width="160" />
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user