调整完善教师端关于选课点名相关界面

This commit is contained in:
ywyonui 2025-08-19 01:48:06 +08:00
parent 44e789f595
commit 526cdc1075
11 changed files with 1151 additions and 551 deletions

View File

@ -35,11 +35,16 @@ export const getXkDmXsPageApi = async (params: any) => {
return await get('/api/xkDmXs/findPage', params)
}
// 选课学生列表
// 选课待点名学生列表
export const getWaitDmXsListApi = async (params: any) => {
return await get("/api/xkDmXs/getWaitDmXsList", params);
};
// 选课点名学生列表
export const getDmXsListApi = async (params: any) => {
return await get("/api/xkDmXs/getDmXsList", params);
};
/**
*
*/

View File

@ -527,16 +527,16 @@
}
},
{
"path": "pages/view/routine/xk/dmRecord",
"path": "pages/view/routine/xk/dmList",
"style": {
"navigationBarTitleText": "点名记录",
"navigationBarTitleText": "点名列表",
"enablePullDownRefresh": false
}
},
{
"path": "pages/view/routine/xk/dmXsRecord",
"path": "pages/view/routine/xk/dmXsList",
"style": {
"navigationBarTitleText": "点名学生记录",
"navigationBarTitleText": "点名学生列表",
"enablePullDownRefresh": false
}
},

View File

@ -54,7 +54,7 @@
</view>
</view>
<view class="video-upload" @click="recordVideo">
<u-icon name="videocam" size="32" color="#999"></u-icon>
<u-icon name="camera" size="32" color="#999"></u-icon>
<text class="upload-text">{{ videoUploadText || '点击录制' }}</text>
</view>
</view>

View File

@ -0,0 +1,281 @@
<template>
<view class="media-preview">
<!-- 照片预览 -->
<view v-if="photoList.length > 0" class="media-section">
<view class="section-title">
<u-icon name="photo" color="#4080ff" size="16"></u-icon>
<text class="title-text">现场照片 ({{ photoList.length }})</text>
</view>
<view class="photo-grid">
<view
v-for="(photo, index) in photoList"
:key="index"
class="photo-item"
@click="previewPhoto(index)"
>
<image
:src="getImageUrl(photo)"
mode="aspectFill"
class="photo-img"
/>
<view class="photo-overlay">
<u-icon name="eye" color="white" size="16"></u-icon>
</view>
</view>
</view>
</view>
<!-- 视频预览 -->
<view v-if="videoList.length > 0" class="media-section">
<view class="section-title">
<u-icon name="camera" color="#4080ff" size="16"></u-icon>
<text class="title-text">现场视频 ({{ videoList.length }})</text>
</view>
<view class="video-list">
<view
v-for="(video, index) in videoList"
:key="index"
class="video-item"
@click="playVideo(video)"
>
<view class="video-thumbnail">
<image
:src="getVideoThumbnail(video)"
mode="aspectFill"
class="video-img"
/>
<view class="video-play-btn">
<u-icon name="play-right" color="white" size="20"></u-icon>
</view>
</view>
<view class="video-info">
<text class="video-title">视频 {{ index + 1 }}</text>
<text class="video-duration">{{ getVideoDuration(video) }}</text>
</view>
</view>
</view>
</view>
<!-- 无媒体文件提示 -->
<view v-if="photoList.length === 0 && videoList.length === 0" class="empty-tip">
<u-icon name="photo" color="#ccc" size="32"></u-icon>
<text class="empty-text">暂无媒体文件</text>
</view>
</view>
</template>
<script setup lang="ts">
import { computed } from "vue";
// BASE_IMAGE_URL使
const BASE_IMAGE_URL = import.meta.env.VITE_BASE_IMAGE_URL || '';
//
interface Props {
zp?: string; //
sp?: string; //
}
const props = withDefaults(defineProps<Props>(), {
zp: '',
sp: ''
});
//
const photoList = computed(() => {
if (!props.zp) return [];
return props.zp.split(',').filter(path => path.trim());
});
//
const videoList = computed(() => {
if (!props.sp) return [];
return props.sp.split(',').filter(path => path.trim());
});
// URL
const getImageUrl = (path: string) => {
if (!path) return '';
if (path.startsWith('http')) return path;
return BASE_IMAGE_URL + path;
};
//
const getVideoThumbnail = (videoPath: string) => {
//
//
return '/static/images/video-thumbnail.png';
};
//
const getVideoDuration = (videoPath: string) => {
//
return '00:00';
};
//
const previewPhoto = (index: number) => {
const urls = photoList.value.map(photo => getImageUrl(photo));
// @ts-ignore
uni.previewImage({
current: index,
urls: urls
});
};
//
const playVideo = (videoPath: string) => {
const videoUrl = getImageUrl(videoPath);
// 使uni-app
// @ts-ignore
uni.navigateTo({
url: `/pages/components/videoPlayer/index?url=${encodeURIComponent(videoUrl)}`
});
};
</script>
<style scoped lang="scss">
.media-preview {
padding: 15px;
}
.media-section {
margin-bottom: 20px;
&:last-child {
margin-bottom: 0;
}
}
.section-title {
display: flex;
align-items: center;
margin-bottom: 12px;
padding: 8px 0;
.title-text {
margin-left: 8px;
font-size: 16px;
font-weight: 500;
color: #333;
}
}
.photo-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 8px;
}
.photo-item {
position: relative;
aspect-ratio: 1;
border-radius: 8px;
overflow: hidden;
cursor: pointer;
&:hover .photo-overlay {
opacity: 1;
}
}
.photo-img {
width: 100%;
height: 100%;
object-fit: cover;
}
.photo-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.3);
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity 0.3s ease;
}
.video-list {
display: flex;
flex-direction: column;
gap: 12px;
}
.video-item {
display: flex;
align-items: center;
padding: 12px;
background: #f8f9fa;
border-radius: 8px;
cursor: pointer;
transition: background-color 0.2s ease;
&:hover {
background: #e9ecef;
}
}
.video-thumbnail {
position: relative;
width: 80px;
height: 60px;
border-radius: 6px;
overflow: hidden;
margin-right: 12px;
}
.video-img {
width: 100%;
height: 100%;
object-fit: cover;
}
.video-play-btn {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 32px;
height: 32px;
background: rgba(0, 0, 0, 0.6);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
.video-info {
flex: 1;
display: flex;
flex-direction: column;
gap: 4px;
}
.video-title {
font-size: 14px;
font-weight: 500;
color: #333;
}
.video-duration {
font-size: 12px;
color: #666;
}
.empty-tip {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 40px 20px;
color: #999;
.empty-text {
margin-top: 12px;
font-size: 14px;
}
}
</style>

View File

@ -94,10 +94,10 @@ import { imagUrl } from "@/utils";
import { onLoad } from "@dcloudio/uni-app";
import { xsJzListByXsIdApi } from "@/api/base/server";
import { useDataStore } from "@/store/modules/data";
const { getData } = useDataStore();
const { getXs } = useDataStore();
const xsInfo = computed(() => {
const xs = getData || {};
const xs = getXs || {};
//
const studentInfo = {
id: xs.xsId || xs.id, //
@ -159,7 +159,7 @@ onLoad(async (options) => {
if (xsInfo.value && xsInfo.value.id) {
try {
uni.showLoading({ title: "加载中..." });
const res = await xsJzListByXsIdApi({ xsId: xsInfo.value.id });
const res:any = await xsJzListByXsIdApi({ xsId: xsInfo.value.id });
if (res && res.resultCode === 1) {
jzList.value = res.result || [];
} else {

View File

@ -56,7 +56,7 @@ import NjBjPicker from "@/pages/components/NjBjPicker/index.vue";
import { imagUrl } from "@/utils";
import { xsFindList } from "@/api/base/server";
import { useDataStore } from "@/store/modules/data";
const { setData } = useDataStore();
const { setXs } = useDataStore();
const xsList = ref<any>([]);
const xsTotal = ref(0);
@ -114,7 +114,7 @@ const getXsList = async () => {
//
const goToDetail = (xs: any) => {
setData(xs);
setXs(xs);
uni.navigateTo({
url: `/pages/view/homeSchool/parentAddressBook/detail`
});

View File

@ -32,35 +32,40 @@
</view>
<!-- 学生列表 -->
<view class="student-list mb-30 white-bg-color">
<view class="student-list mb-15 white-bg-color">
<view class="student-grid">
<view
v-for="(xs, index) in xsList"
:key="index"
class="student-item bg-white r-md p-12"
>
<view class="flex-row items-center">
<view class="avatar-container mr-8">
<image
class="student-avatar"
:src="getImageUrl(xs.tx || xs.xstx)"
mode="aspectFill"
></image>
</view>
<view class="flex-1 overflow-hidden">
<view class="flex-row items-center mb-3">
<text class="font-14 font-bold mr-5 text-ellipsis">{{ xs.xsXm || xs.xsxm }}</text>
<view
class="status-tag"
:class="getStatusClass(xs.xsZt || xs.xszt)"
@click="openStatusPicker(xs)"
>
{{ getStatusText(xs.xsZt || xs.xszt) }}
<u-icon name="arrow-down" size="10"></u-icon>
</view>
<view class="student-content">
<!-- 第一行头像和学生信息 -->
<view class="top-row">
<view class="avatar-container">
<image
class="student-avatar"
:src="getImageUrl(xs.tx || xs.xstx)"
mode="aspectFill"
></image>
</view>
<text class="font-12 cor-666">{{ xs.bjmc }}</text>
<view class="contact-parent mt-8 flex-center" @click="contactParent(xs)">
<view class="student-info">
<text class="student-name">{{ xs.xsXm || xs.xsxm }}</text>
<text class="student-class">{{ xs.bjmc }}</text>
</view>
</view>
<!-- 第二行状态和联系家长 -->
<view class="bottom-row">
<view
class="status-tag"
:class="getStatusClass(xs.xsZt || xs.xszt)"
@click="openStatusPicker(xs)"
>
{{ getStatusText(xs.xsZt || xs.xszt) }}
<u-icon name="arrow-down" size="12"></u-icon>
</view>
<view class="contact-parent" @click="contactParent(xs)">
<text class="font-12 cor-primary">联系家长</text>
<u-icon
name="phone"
@ -75,15 +80,17 @@
</view>
</view>
<DmPsComponent
v-model="mediaData"
:photo-title="'现场拍照'"
:video-title="'现场视频'"
:max-photo-count="9"
:max-video-count="3"
:max-video-duration="60"
ref="dmPsRef"
/>
<view class="mx-15">
<DmPsComponent
v-model="mediaData"
:photo-title="'现场拍照'"
:video-title="'现场视频'"
:max-photo-count="9"
:max-video-count="3"
:max-video-duration="60"
ref="dmPsRef"
/>
</view>
<!-- 状态选择弹窗 -->
<u-picker
@ -131,7 +138,7 @@ const { findByPid } = useDicStore();
import dayjs from "dayjs";
const { getJs } = useUserStore();
const { getData, setData } = useDataStore();
const { getData, setData, setXs } = useDataStore();
const js = computed(() => getJs)
const xkkc = computed(() => getData)
@ -355,7 +362,7 @@ const contactParent = (dmXs: any) => {
};
// store使
setData(completeStudent);
setXs(completeStudent);
//
uni.navigateTo({
@ -538,13 +545,25 @@ onMounted(async () => {
.student-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20rpx;
gap: 10px;
}
.student-item {
position: relative;
}
.student-content {
display: flex;
flex-direction: column;
gap: 12px;
}
.top-row {
display: flex;
align-items: center;
gap: 12px;
}
.avatar-container {
width: 46px;
height: 46px;
@ -555,6 +574,7 @@ onMounted(async () => {
align-items: center;
justify-content: center;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
flex-shrink: 0;
}
.student-avatar {
@ -564,13 +584,51 @@ onMounted(async () => {
background-color: #f5f5f5;
}
.student-info {
flex: 1;
display: flex;
flex-direction: column;
gap: 4px;
}
.student-name {
font-size: 14px;
font-weight: bold;
color: #333;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.student-class {
font-size: 12px;
color: #666;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.bottom-row {
display: flex;
justify-content: space-between;
align-items: center;
gap: 5px;
}
.status-tag {
font-size: 10px;
padding: 1px 5px;
font-size: 12px;
padding: 3px 8px;
border-radius: 4px;
display: flex;
align-items: center;
cursor: pointer;
background-color: rgba(64, 128, 255, 0.1);
border: 1px solid transparent;
transition: all 0.2s ease;
&:active {
transform: scale(0.95);
}
}
.status-normal {
@ -589,7 +647,7 @@ onMounted(async () => {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 60px;
max-width: 100%;
}
.contact-parent {
@ -597,11 +655,14 @@ onMounted(async () => {
border-radius: 4px;
border: 1px solid #4080ff;
display: inline-flex;
align-items: center;
cursor: pointer;
transition: all 0.2s ease;
white-space: nowrap;
background-color: rgba(64, 128, 255, 0.05);
&:active {
background-color: rgba(64, 128, 255, 0.1);
background-color: rgba(64, 128, 255, 0.15);
transform: scale(0.95);
}
}

View File

@ -240,6 +240,7 @@ const goDm = (xkkc: any) => {
} else {
msg = "上课时间未到,无法点名";
}
dmFlag = true;
if (dmFlag) {
setData(xkkc);
uni.navigateTo({
@ -259,57 +260,10 @@ const goDm = (xkkc: any) => {
//
const goRecord = (xkkc: any) => {
const now = dayjs();
let wDay = now.day();
if (wDay === 0) {
wDay = 7;
}
let mDay = now.date();
const strDate = now.format('YYYY-MM-DD') + ' ';
let recordFlag = false;
let msg = "";
//
switch (xkkc.skzqlx) {
case '每天':
recordFlag = true;
break;
case '每周':
const daysOfWeek = xkkc.skzq.split(',').map(Number);
recordFlag = daysOfWeek.includes(wDay);
// wdNameListdaysOfWeek
xkkc.skzqmc = daysOfWeek.map((day: number) => wdNameList[day - 1]).join(',');
break;
case '每月':
const daysOfMonth = xkkc.skzq.split(',').map(Number);
recordFlag = daysOfMonth.includes(mDay);
//
xkkc.skzqmc = daysOfMonth.map((day: number) => day + "号").join(',');
break;
}
//
if (recordFlag) {
// xkkc.skkstimedmBeforeMinute
const startTime = dayjs(strDate + xkkc.skkstime).subtract(dmBeforeMinute.value, 'minute').format('YYYY-MM-DD HH:mm:ss');
const endTime = dayjs(strDate + xkkc.skjstime, 'YYYY-MM-DD HH:mm:ss');
recordFlag = now.isBefore(endTime) && now.isAfter(startTime)
} else {
msg = "上课时间未到,无法查看点名记录";
}
if (recordFlag) {
setData(xkkc);
uni.navigateTo({
url: `/pages/view/routine/xk/dmXkkcRecord`,
});
} else {
if (msg === "") {
msg = "上课时间未到,无法查看点名记录";
}
uni.showToast({
title: msg,
icon: 'none',
duration: 2000
});
}
setData(xkkc);
uni.navigateTo({
url: `/pages/view/routine/xk/dmList`,
});
};
//

View File

@ -1,89 +1,107 @@
<template>
<BasicLayout>
<!-- 课程信息卡片 -->
<view class="course-card mx-15 my-15 bg-white white-bg-color r-md p-15">
<view class="flex-row items-center mb-15">
<view class="course-icon flex-center mr-10">
<u-icon name="calendar" color="#4080ff" size="20"></u-icon>
<!-- 使用 BasicListLayout 包裹记录列表 -->
<BasicListLayout @register="register" :fixed="false" class="flex-1">
<template #top>
<!-- 课程信息卡片 -->
<view class="course-card">
<view class="flex-row items-center mb-15">
<view class="course-icon flex-center mr-10">
<u-icon name="calendar" color="#4080ff" size="20"></u-icon>
</view>
<text class="font-16 font-bold">{{ xkkc.xkkcMc || xkkc.kcmc }}</text>
<text class="font-14 cor-999 ml-10">{{ todayInfo.date }} ({{ todayInfo.weekName }})</text>
</view>
<text class="font-16 font-bold">{{ xkkc.xkkcMc || xkkc.kcmc }}</text>
<text class="font-14 cor-999 ml-10">{{ todayInfo.date }} ({{ todayInfo.weekName }})</text>
</view>
</view>
<!-- 点名记录统计 -->
<view class="record-stats mx-15 mb-15">
<view class="section-title">点名记录</view>
<view class="records-grid">
<view
v-for="(record, index) in dmRecords"
:key="record.id"
class="record-card"
@click="viewRecordDetail(record)"
>
<view class="record-header">
<view class="record-time">
<u-icon name="clock" color="#666" size="14"></u-icon>
<text class="time-text">{{ formatDateTime(record.dmTime) }}</text>
</view>
<view class="record-status" :class="getRecordStatusClass(record.status)">
{{ getRecordStatusText(record.status) }}
</view>
</view>
<view class="record-stats">
<view class="stat-item">
<text class="stat-number">{{ record.zrs || 0 }}</text>
<text class="stat-label">总人数</text>
</view>
<view class="stat-item present">
<text class="stat-number">{{ record.sdRs || 0 }}</text>
<text class="stat-label">实到</text>
</view>
<view class="stat-item leave">
<text class="stat-number">{{ record.qjRs || 0 }}</text>
<text class="stat-label">请假</text>
</view>
<view class="stat-item absent">
<text class="stat-number">{{ record.qqRs || 0 }}</text>
<text class="stat-label">缺勤</text>
</view>
</view>
<view class="record-footer">
<text class="teacher-name">教师{{ record.jsMc || '未知' }}</text>
<view class="view-detail">
<text class="detail-text">查看详情</text>
<u-icon name="arrow-right" color="#4080ff" size="12"></u-icon>
</view>
<!-- 搜索筛选区域 -->
<view class="search-section">
<view class="search-row">
<view class="search-item">
<text class="label">时间范围</text>
<uni-datetime-picker
type="daterange"
:value="[startTime, endTime]"
@change="onTimeRangeChange"
class="date-picker"
>
<view class="picker-text">{{ getTimeRangeText() }}</view>
</uni-datetime-picker>
</view>
</view>
<view class="search-row">
<button class="search-btn" @click="searchRecords">搜索</button>
<button class="reset-btn" @click="resetSearch">重置</button>
</view>
</view>
<!-- 空状态 -->
<view v-if="dmRecords.length === 0" class="empty-state">
<u-icon name="info-circle" color="#ccc" size="48"></u-icon>
<text class="empty-text">暂无点名记录</text>
<!-- 记录头部信息 -->
<view class="records-header" v-if="dmRecords && dmRecords.length > 0">
<view class="section-title">点名记录 ({{ totalCount }})</view>
</view>
</view>
<!-- 返回按钮 -->
<view class="bottom-actions mx-15 mb-30">
<button class="back-btn" @click="goBack">返回</button>
</view>
</BasicLayout>
<!-- 初始提示 -->
<view v-if="!hasSearched" class="initial-tip">
<view class="tip-icon">🔍</view>
<text class="tip-text">请选择时间范围开始搜索</text>
</view>
</template>
<template #default="{ data }">
<view class="record-card" @click="viewRecordDetail(data)">
<view class="record-header">
<view class="record-time">
<u-icon name="clock" color="#666" size="14"></u-icon>
<text class="time-text">{{ formatDateTime(data.dmTime) }}</text>
</view>
</view>
<view class="record-stats">
<view class="stat-item">
<text class="stat-number">{{ data.zrs || 0 }}</text>
<text class="stat-label">总人数</text>
</view>
<view class="stat-item present">
<text class="stat-number">{{ data.sdRs || 0 }}</text>
<text class="stat-label">实到</text>
</view>
<view class="stat-item leave">
<text class="stat-number">{{ data.qjRs || 0 }}</text>
<text class="stat-label">请假</text>
</view>
<view class="stat-item absent">
<text class="stat-number">{{ data.qqRs || 0 }}</text>
<text class="stat-label">缺勤</text>
</view>
</view>
<view class="record-footer">
<text class="teacher-name">教师{{ data.createdUserName || '未知' }}</text>
<view class="view-detail">
<text class="detail-text">查看详情</text>
<u-icon name="arrow-right" color="#4080ff" size="12"></u-icon>
</view>
</view>
</view>
</template>
<template #bottom>
<!-- 返回按钮 -->
<view class="bottom-actions mx-15 mb-15">
<button class="back-btn" @click="goBack">返回</button>
</view>
</template>
</BasicListLayout>
</template>
<script setup lang="ts">
import { ref, computed, onMounted } from "vue";
import { useUserStore } from "@/store/modules/user";
import { useDataStore } from "@/store/modules/data";
import BasicLayout from "@/components/BasicLayout/Layout.vue";
import { useLayout } from "@/components/BasicListLayout/hooks/useLayout";
import { getXkDmPageApi } from "@/api/base/xkApi";
import dayjs from "dayjs";
const { getJs } = useUserStore();
const { getData } = useDataStore();
const { getData, setData } = useDataStore();
const js = computed(() => getJs);
const xkkc = computed(() => getData);
@ -100,8 +118,110 @@ const todayInfo = ref({
weekName: wdNameList[wDay - 1],
});
//
const dmRecords = ref<any[]>([]);
//
const loading = ref(false);
const startTime = ref("");
const endTime = ref("");
const dmRecords = ref<any>([]);
const totalCount = ref<any>(0);
const hasSearched = ref(false);
// 使 BasicListLayout
const [register, { reload, setParam }] = useLayout({
api: async (params: any) => {
try {
const res = await getXkDmPageApi({
...params,
xkkcId: xkkc.value.id,
jsId: js.value.id,
sidx: 'dmTime',
sord: 'desc'
});
console.log("API返回数据:", res, xkkc.value);
if (res) {
dmRecords.value = res?.rows || [];
totalCount.value = res?.total || 0;
return res;
} else {
dmRecords.value = [];
totalCount.value = 0;
return { rows: [], total: 0, page: 1, pageSize: 10 };
}
} catch (error) {
console.error("获取数据失败:", error);
dmRecords.value = [];
totalCount.value = 0;
return { rows: [], total: 0, page: 1, pageSize: 10 };
}
},
componentProps: {
auto: false,
},
});
//
const onTimeRangeChange = (e: any) => {
if (e && Array.isArray(e)) {
const [start, end] = e;
startTime.value = start;
endTime.value = end;
} else if (e && typeof e === "string") {
startTime.value = e;
endTime.value = e;
}
};
const getTimeRangeText = () => {
if (!startTime.value || !endTime.value) return "选择时间范围";
if (startTime.value === endTime.value) {
return formatDate(startTime.value);
}
return `${formatDate(startTime.value)} - ${formatDate(endTime.value)}`;
};
const searchRecords = async () => {
if (!startTime.value || !endTime.value) {
uni.showToast({
title: "请选择时间范围",
icon: "none",
});
return;
}
//
if (startTime.value > endTime.value) {
uni.showToast({
title: "开始时间不能大于结束时间",
icon: "none",
});
return;
}
hasSearched.value = true;
console.log("搜索参数:", {
startTime: startTime.value + " 00:00:00",
endTime: endTime.value + " 23:59:59",
pageNo: 1,
});
//
setParam({
startTime: startTime.value + " 00:00:00",
endTime: endTime.value + " 23:59:59",
pageNo: 1,
});
reload();
};
const resetSearch = () => {
startTime.value = "";
endTime.value = "";
dmRecords.value = [];
totalCount.value = 0;
hasSearched.value = false;
};
//
const formatDateTime = (dateTime: string | Date) => {
@ -109,6 +229,15 @@ const formatDateTime = (dateTime: string | Date) => {
return dayjs(dateTime).format('MM-DD HH:mm');
};
const formatDate = (dateStr: string) => {
if (!dateStr) return "";
const date = new Date(dateStr);
return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(
2,
"0"
)}-${String(date.getDate()).padStart(2, "0")}`;
};
//
const getRecordStatusClass = (status: string) => {
switch (status) {
@ -132,7 +261,6 @@ const getRecordStatusText = (status: string) => {
//
const viewRecordDetail = (record: any) => {
// store
const { setData } = useDataStore();
setData({
...xkkc.value,
dmRecord: record
@ -149,50 +277,33 @@ const goBack = () => {
uni.navigateBack();
};
//
const loadStudentList = async () => {
try {
uni.showLoading({ title: '加载中...' });
const res = await getXkDmPageApi({
xkkcId: xkkc.value.id,
jsId: js.value.id,
pageNum: 1,
pageSize: 50,
sidx: 'dmTime',
sord: 'desc'
});
if (res && res.resultCode === 1) {
dmRecords.value = res.result?.rows || [];
} else {
dmRecords.value = [];
uni.showToast({
title: (res as any)?.resultMessage || '获取点名记录失败',
icon: 'none'
});
}
} catch (error) {
console.error('加载点名记录失败:', error);
dmRecords.value = [];
uni.showToast({
title: '加载点名记录失败',
icon: 'none'
});
} finally {
uni.hideLoading();
}
};
//
onMounted(() => {
loadStudentList();
//
const today = new Date();
const oneWeekAgo = new Date(today.getTime() - 7 * 24 * 60 * 60 * 1000);
startTime.value = oneWeekAgo.toISOString().split("T")[0];
endTime.value = today.toISOString().split("T")[0];
console.log("组件初始化完成:", {
startTime: startTime.value,
endTime: endTime.value,
dmRecords: dmRecords.value,
totalCount: totalCount.value,
});
//
});
</script>
<style scoped lang="scss">
.course-card {
border-radius: 8px;
background-color: #fff;
border-radius: 16rpx;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
margin: 30rpx;
padding: 30rpx;
}
.course-icon {
@ -202,153 +313,244 @@ onMounted(() => {
background-color: rgba(64, 128, 255, 0.1);
}
.record-stats {
.search-section {
background-color: #fff;
border-radius: 16rpx;
padding: 30rpx;
margin-left: 30rpx;
margin-right: 30rpx;
margin-bottom: 20rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
}
.search-row {
display: flex;
gap: 20rpx;
margin-bottom: 20rpx;
&:last-child {
margin-bottom: 0;
}
}
.search-item {
flex: 1;
display: flex;
align-items: center;
}
.label {
font-size: 28rpx;
color: #333;
white-space: nowrap;
flex: 0 0 160rpx;
}
.date-picker {
flex: 1;
}
.picker-text {
padding: 16rpx 20rpx;
background-color: #f5f5f5;
border-radius: 8rpx;
font-size: 28rpx;
color: #333;
border: 1px solid #e5e5e5;
}
.search-btn,
.reset-btn {
flex: 1;
height: 70rpx;
border-radius: 35rpx;
font-size: 28rpx;
border: none;
}
.search-btn {
background-color: #007aff;
color: #fff;
}
.reset-btn {
background-color: #f5f5f5;
color: #666;
}
.records-header {
padding: 0 30rpx;
margin-bottom: 20rpx;
.section-title {
font-size: 16px;
font-size: 32rpx;
font-weight: bold;
color: #333;
margin-bottom: 15px;
padding-left: 10px;
border-left: 4px solid #4080ff;
}
.records-grid {
display: flex;
flex-direction: column;
gap: 15px;
justify-content: space-between;
align-items: center;
}
}
.record-card {
background: white;
border-radius: 12px;
padding: 20px;
margin-bottom: 30rpx;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
transition: all 0.3s ease;
cursor: pointer;
&:hover {
transform: translateY(-2px);
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
}
.record-card {
background: white;
border-radius: 12px;
padding: 20px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
transition: all 0.3s ease;
cursor: pointer;
.record-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
&:hover {
transform: translateY(-2px);
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
}
.record-header {
.record-time {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
gap: 5px;
.record-time {
display: flex;
align-items: center;
gap: 5px;
.time-text {
font-size: 14px;
color: #666;
}
}
.record-status {
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
font-weight: 500;
&.status-active {
background: rgba(40, 121, 255, 0.1);
color: #2879ff;
}
&.status-pending {
background: rgba(255, 153, 0, 0.1);
color: #ff9900;
}
&.status-cancelled {
background: rgba(255, 77, 79, 0.1);
color: #ff4d4f;
}
}
}
.record-stats {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 10px;
margin-bottom: 15px;
.stat-item {
text-align: center;
padding: 10px 5px;
border-radius: 8px;
background: #f8f9fa;
&.present {
background: rgba(40, 121, 255, 0.1);
.stat-number { color: #2879ff; }
}
&.leave {
background: rgba(255, 153, 0, 0.1);
.stat-number { color: #ff9900; }
}
&.absent {
background: rgba(255, 77, 79, 0.1);
.stat-number { color: #ff4d4f; }
}
.stat-number {
font-size: 18px;
font-weight: bold;
color: #333;
display: block;
margin-bottom: 4px;
}
.stat-label {
font-size: 12px;
color: #666;
}
}
}
.record-footer {
display: flex;
justify-content: space-between;
align-items: center;
padding-top: 15px;
border-top: 1px solid #f0f0f0;
.teacher-name {
.time-text {
font-size: 14px;
color: #666;
}
}
.view-detail {
display: flex;
align-items: center;
gap: 5px;
.record-status {
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
font-weight: 500;
.detail-text {
font-size: 14px;
color: #4080ff;
}
&.status-active {
background: rgba(40, 121, 255, 0.1);
color: #2879ff;
}
&.status-pending {
background: rgba(255, 153, 0, 0.1);
color: #ff9900;
}
&.status-cancelled {
background: rgba(255, 77, 79, 0.1);
color: #ff4d4f;
}
}
}
.empty-state {
text-align: center;
padding: 60px 20px;
color: #ccc;
.record-stats {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 10px;
margin-bottom: 15px;
.empty-text {
display: block;
margin-top: 15px;
font-size: 16px;
.stat-item {
text-align: center;
padding: 10px 5px;
border-radius: 8px;
background: #f8f9fa;
&.present {
background: rgba(40, 121, 255, 0.1);
.stat-number { color: #2879ff; }
}
&.leave {
background: rgba(255, 153, 0, 0.1);
.stat-number { color: #ff9900; }
}
&.absent {
background: rgba(255, 77, 79, 0.1);
.stat-number { color: #ff4d4f; }
}
.stat-number {
font-size: 18px;
font-weight: bold;
color: #333;
display: block;
margin-bottom: 4px;
}
.stat-label {
font-size: 12px;
color: #666;
}
}
}
.record-footer {
display: flex;
justify-content: space-between;
align-items: center;
padding-top: 15px;
border-top: 1px solid #f0f0f0;
.teacher-name {
font-size: 14px;
color: #666;
}
.view-detail {
display: flex;
align-items: center;
gap: 5px;
.detail-text {
font-size: 14px;
color: #4080ff;
}
}
}
}
.empty-state {
text-align: center;
padding: 100rpx 0;
}
.empty-icon {
font-size: 80rpx;
margin-bottom: 20rpx;
}
.empty-text {
display: block;
font-size: 32rpx;
color: #333;
margin-bottom: 16rpx;
}
.empty-tip {
font-size: 26rpx;
color: #999;
}
.initial-tip {
text-align: center;
padding: 50rpx 0;
color: #999;
font-size: 28rpx;
}
.tip-icon {
font-size: 60rpx;
margin-bottom: 20rpx;
}
.tip-text {
display: block;
font-size: 32rpx;
color: #333;
margin-bottom: 16rpx;
}
.bottom-actions {
@ -382,3 +584,4 @@ onMounted(() => {
.font-bold { font-weight: bold; }
.cor-999 { color: #999; }
</style>

View File

@ -11,27 +11,43 @@
</view>
<view class="dm-time">
<u-icon name="clock" color="#666" size="14"></u-icon>
<text class="time-text">{{ formatDateTime(dmRecord.dmTime) }}</text>
<text class="time-text">{{ formatDateTime(safeDmRecord.dmTime) }}</text>
</view>
</view>
<!-- 考勤统计 -->
<view class="attendance-stats">
<view class="stats-grid">
<view class="stat-item total">
<view class="stat-number">{{ dmRecord.zrs || 0 }}</view>
<view
class="stat-item total"
:class="{ active: currentFilter === 'all' }"
@click="setFilter('all')"
>
<view class="stat-number">{{ safeDmRecord.zrs || 0 }}</view>
<view class="stat-label">总人数</view>
</view>
<view class="stat-item present">
<view class="stat-number">{{ dmRecord.sdRs || 0 }}</view>
<view
class="stat-item present"
:class="{ active: currentFilter === 'A' }"
@click="setFilter('A')"
>
<view class="stat-number">{{ safeDmRecord.sdRs || 0 }}</view>
<view class="stat-label">实到</view>
</view>
<view class="stat-item leave">
<view class="stat-number">{{ dmRecord.qjRs || 0 }}</view>
<view
class="stat-item leave"
:class="{ active: currentFilter === 'B' }"
@click="setFilter('B')"
>
<view class="stat-number">{{ safeDmRecord.qjRs || 0 }}</view>
<view class="stat-label">请假</view>
</view>
<view class="stat-item absent">
<view class="stat-number">{{ dmRecord.qqRs || 0 }}</view>
<view
class="stat-item absent"
:class="{ active: currentFilter === 'C' }"
@click="setFilter('C')"
>
<view class="stat-number">{{ safeDmRecord.qqRs || 0 }}</view>
<view class="stat-label">缺勤</view>
</view>
</view>
@ -39,97 +55,95 @@
</view>
<!-- 学生列表 -->
<view class="student-section mx-15 mb-15">
<view class="section-header">
<text class="section-title">学生列表</text>
<view class="filter-tabs">
<view
v-for="tab in filterTabs"
:key="tab.value"
class="filter-tab"
:class="{ active: currentFilter === tab.value }"
@click="setFilter(tab.value)"
>
{{ tab.label }}
</view>
</view>
</view>
<view class="student-list">
<view class="student-list mb-15 white-bg-color">
<view class="student-grid">
<view
v-for="(student, index) in filteredStudents"
:key="student.id"
class="student-item"
v-for="(xs, index) in filteredStudentList"
:key="index"
class="student-item bg-white r-md p-12"
>
<view class="student-avatar">
<image
v-if="student.tx || student.xstx"
:src="getImageUrl(student.tx || student.xstx)"
mode="aspectFill"
class="avatar-img"
/>
<view v-else class="avatar-text">{{ (student.xsXm || student.xsxm)?.charAt(0) || '学' }}</view>
</view>
<view class="student-info">
<view class="student-name">{{ student.xsXm || student.xsxm }}</view>
<view class="student-class">{{ student.njmc }} {{ student.bjmc }}</view>
</view>
<view class="student-status">
<text :class="getStatusClass(student.xsZt || student.xszt)">
{{ getStatusText(student.xsZt || student.xszt) }}
</text>
<view class="student-content">
<!-- 第一行头像和学生信息 -->
<view class="top-row">
<view class="avatar-container">
<image
class="student-avatar"
:src="getImageUrl(xs.tx || xs.xstx)"
mode="aspectFill"
></image>
</view>
<view class="student-info">
<text class="student-name">{{ xs.xsXm || xs.xsxm }}</text>
<text class="student-class">{{ xs.bjmc }}</text>
</view>
</view>
<!-- 第二行状态和联系家长 -->
<view class="bottom-row">
<view class="status-tag" :class="getStatusClass(xs.xsZt || xs.xszt)">
{{ getStatusText(xs.xsZt || xs.xszt) }}
</view>
<view class="contact-parent" @click="contactParent(xs)">
<text class="font-12 cor-primary">联系家长</text>
<u-icon
name="phone"
color="#4080ff"
size="14"
class="ml-2"
></u-icon>
</view>
</view>
</view>
</view>
</view>
</view>
<!-- 空状态 -->
<view v-if="filteredStudents.length === 0" class="empty-state">
<u-icon name="info-circle" color="#ccc" size="48"></u-icon>
<text class="empty-text">暂无学生数据</text>
<!-- 媒体预览 -->
<view v-if="safeDmRecord.zp || safeDmRecord.sp" class="media-section mx-15 mb-15">
<DmPsPreview
:zp="safeDmRecord.zp"
:sp="safeDmRecord.sp"
/>
</view>
<template #bottom>
<!-- 返回按钮 -->
<view class="bottom-actions mx-15 mb-15">
<button class="back-btn" @click="goBack">返回</button>
</view>
</view>
<!-- 返回按钮 -->
<view class="bottom-actions mx-15 mb-30">
<button class="back-btn" @click="goBack">返回</button>
</view>
</template>
</BasicLayout>
</template>
<script setup lang="ts">
import { ref, computed, onMounted } from "vue";
import { useUserStore } from "@/store/modules/user";
import { useDataStore } from "@/store/modules/data";
import BasicLayout from "@/components/BasicLayout/Layout.vue";
import { getXkDmXsPageApi } from "@/api/base/xkApi";
import DmPsPreview from "@/pages/components/dmPs/preview.vue";
import { useDataStore } from "@/store/modules/data";
import { getDmXsListApi } from "@/api/base/xkApi";
import { BASE_IMAGE_URL } from "@/config";
import dayjs from "dayjs";
const { getJs } = useUserStore();
const { getData } = useDataStore();
const { getData, setXs } = useDataStore();
const js = computed(() => getJs);
const xkkc = computed(() => getData);
const dmRecord = computed(() => getData?.dmRecord || {});
//
const studentList = ref<any[]>([]);
const currentFilter = ref<string>('all');
// dmRecord undefined
const safeDmRecord = computed(() => {
return dmRecord.value || {};
});
//
const filterTabs = ref([
{ label: '全部', value: 'all' },
{ label: '正常', value: 'A' },
{ label: '请假', value: 'B' },
{ label: '缺勤', value: 'C' }
]);
//
const allStudentList = ref<any[]>([]); //
const currentFilter = ref<string>('all'); //
//
const filteredStudents = computed(() => {
const filteredStudentList = computed(() => {
if (currentFilter.value === 'all') {
return studentList.value;
return allStudentList.value;
}
return studentList.value.filter(student =>
return allStudentList.value.filter(student =>
(student.xsZt || student.xszt) === currentFilter.value
);
});
@ -137,14 +151,24 @@ const filteredStudents = computed(() => {
//
const formatDateTime = (dateTime: string | Date) => {
if (!dateTime) return '';
return dayjs(dateTime).format('MM-DD HH:mm');
try {
return dayjs(dateTime).format('MM-DD HH:mm');
} catch (error) {
console.error('日期格式化错误:', error);
return '';
}
};
// URL
const getImageUrl = (path: string) => {
if (!path) return '';
if (path.startsWith('http')) return path;
return BASE_IMAGE_URL + path;
try {
if (path.startsWith('http')) return path;
return BASE_IMAGE_URL + path;
} catch (error) {
console.error('图片URL处理错误:', error);
return '';
}
};
//
@ -175,46 +199,65 @@ const setFilter = (filter: string) => {
currentFilter.value = filter;
};
//
const contactParent = (dmXs: any) => {
//
const completeStudent = {
...dmXs,
//
id: dmXs.xsId || dmXs.id,
xsxm: dmXs.xsXm || dmXs.xsxm || dmXs.xm,
xstx: dmXs.tx || dmXs.xstx || dmXs.avatar,
xb: dmXs.xb || dmXs.gender,
sfzh: dmXs.sfzh,
cstime: dmXs.cstime,
njmc: dmXs.njmcName || dmXs.njmc,
bjmc: dmXs.bjmc,
// njIdbjId
njId: dmXs.njId,
bjId: dmXs.bjId
};
// store使
setXs(completeStudent);
//
// @ts-ignore
uni.navigateTo({
url: "/pages/view/homeSchool/parentAddressBook/detail"
});
};
//
const goBack = () => {
// @ts-ignore
uni.navigateBack();
};
//
const loadStudentList = async () => {
try {
uni.showLoading({ title: '加载中...' });
const res = await getXkDmXsPageApi({
dmId: dmRecord.value.id,
pageNum: 1,
pageSize: 100,
sidx: 'xsXm',
sord: 'asc'
const res = await getDmXsListApi({
dmId: safeDmRecord.value.id
});
if (res && res.resultCode === 1) {
studentList.value = res.result?.rows || [];
} else {
studentList.value = [];
uni.showToast({
title: (res as any)?.resultMessage || '获取学生列表失败',
icon: 'none'
});
if (res) {
allStudentList.value = res?.result || [];
}
} catch (error) {
console.error('加载学生列表失败:', error);
studentList.value = [];
uni.showToast({
title: '加载学生列表失败',
icon: 'none'
});
} finally {
uni.hideLoading();
console.error("获取数据失败:", error);
allStudentList.value = [];
}
};
//
onMounted(() => {
console.log("dmXsList 组件初始化:", {
xkkc: xkkc.value,
dmRecord: safeDmRecord.value,
hasData: !!getData
});
//
loadStudentList();
});
</script>
@ -250,34 +293,80 @@ onMounted(() => {
.stats-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 15px;
gap: 20rpx;
}
.stat-item {
background: white;
border-radius: 12px;
padding: 20px 15px;
padding: 20rpx 0;
text-align: center;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
cursor: pointer;
transition: all 0.3s ease;
position: relative;
&:hover {
transform: translateY(-2px);
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
}
&.active {
transform: translateY(-2px);
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.15);
&::after {
content: '';
position: absolute;
bottom: -2px;
left: 50%;
transform: translateX(-50%);
width: 50rpx;
height: 20rpx;
background: #4080ff;
border-top-left-radius: 50rpx;
border-top-right-radius: 50rpx;
}
}
&.total {
border: 2px solid #666;
.stat-number { color: #333; }
&.active {
border-color: #4080ff;
background: rgba(64, 128, 255, 0.05);
}
}
&.present {
border: 2px solid #2879ff;
.stat-number { color: #2879ff; }
border: 2px solid #52c41a;
.stat-number { color: #52c41a; }
&.active {
border-color: #4080ff;
background: rgba(64, 128, 255, 0.05);
}
}
&.leave {
border: 2px solid #ff9900;
.stat-number { color: #ff9900; }
&.active {
border-color: #4080ff;
background: rgba(64, 128, 255, 0.05);
}
}
&.absent {
border: 2px solid #ff4d4f;
.stat-number { color: #ff4d4f; }
&.active {
border-color: #4080ff;
background: rgba(64, 128, 255, 0.05);
}
}
.stat-number {
@ -293,135 +382,127 @@ onMounted(() => {
}
}
.student-section {
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
.media-section {
background: white;
border-radius: 8px;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
overflow: hidden;
}
.section-title {
font-size: 16px;
font-weight: bold;
color: #333;
padding-left: 10px;
border-left: 4px solid #4080ff;
}
.student-list {
padding: 0 15px;
}
.filter-tabs {
display: flex;
gap: 10px;
.student-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 10px;
}
.filter-tab {
padding: 6px 12px;
border-radius: 16px;
font-size: 12px;
background: #f5f5f5;
color: #666;
cursor: pointer;
transition: all 0.3s ease;
.student-item {
position: relative;
}
&.active {
background: #4080ff;
color: white;
}
}
}
}
.student-content {
display: flex;
flex-direction: column;
gap: 12px;
}
.student-list {
display: flex;
flex-direction: column;
gap: 10px;
.top-row {
display: flex;
align-items: center;
gap: 12px;
}
.student-item {
display: flex;
align-items: center;
padding: 15px;
background: white;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
.avatar-container {
width: 46px;
height: 46px;
border-radius: 50%;
padding: 3px;
background-color: #fff;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
flex-shrink: 0;
}
.student-avatar {
width: 40px;
height: 40px;
border-radius: 50%;
overflow: hidden;
margin-right: 15px;
.student-avatar {
width: 40px;
height: 40px;
border-radius: 50%;
background-color: #f5f5f5;
}
.avatar-img {
width: 100%;
height: 100%;
object-fit: cover;
}
.student-info {
flex: 1;
display: flex;
flex-direction: column;
gap: 4px;
}
.avatar-text {
width: 100%;
height: 100%;
background: #4080ff;
color: white;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
font-weight: bold;
}
}
.student-name {
font-size: 14px;
font-weight: bold;
color: #333;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.student-info {
flex: 1;
.student-class {
font-size: 12px;
color: #666;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.student-name {
font-size: 16px;
font-weight: 500;
color: #333;
margin-bottom: 4px;
}
.bottom-row {
display: flex;
justify-content: space-between;
align-items: center;
gap: 5px;
}
.student-class {
font-size: 14px;
color: #666;
}
}
.status-tag {
font-size: 12px;
padding: 3px 12px;
border-radius: 4px;
display: flex;
align-items: center;
background-color: rgba(64, 128, 255, 0.1);
border: 1px solid transparent;
transition: all 0.2s ease;
}
.student-status {
.status-normal {
color: #2879ff;
background: rgba(40, 121, 255, 0.1);
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
}
.status-normal {
color: #4080ff;
}
.status-leave {
color: #ff9900;
background: rgba(255, 153, 0, 0.1);
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
}
.status-leave {
color: #ff9900;
}
.status-absent {
color: #ff4d4f;
background: rgba(255, 77, 79, 0.1);
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
}
}
}
}
.status-absent {
color: #ff4d4f;
}
.empty-state {
text-align: center;
padding: 60px 20px;
color: #ccc;
.contact-parent {
padding: 3px 8px;
border-radius: 4px;
border: 1px solid #4080ff;
display: inline-flex;
align-items: center;
cursor: pointer;
transition: all 0.2s ease;
white-space: nowrap;
background-color: rgba(64, 128, 255, 0.05);
.empty-text {
display: block;
margin-top: 15px;
font-size: 16px;
}
&:active {
background-color: rgba(64, 128, 255, 0.15);
transform: scale(0.95);
}
}
@ -449,10 +530,18 @@ onMounted(() => {
.white-bg-color { background-color: white; }
.r-md { border-radius: 8px; }
.p-15 { padding: 15px; }
.p-12 { padding: 12px; }
.flex-row { display: flex; flex-direction: row; }
.flex-center { display: flex; align-items: center; justify-content: center; }
.items-center { align-items: center; }
.font-16 { font-size: 16px; }
.font-14 { font-size: 14px; }
.font-12 { font-size: 12px; }
.font-bold { font-weight: bold; }
.cor-999 { color: #999; }
.cor-primary { color: #4080ff; }
.cor-warning { color: #ff9900; }
.cor-danger { color: #ff4d4f; }
.cor-666 { color: #666; }
.ml-2 { margin-left: 2px; }
</style>

View File

@ -8,6 +8,7 @@ export const useDataStore = defineStore({
xxts: {}, // 添加xxts字段
global: {},
file: {},
xs: {}, // 学生专用
}),
getters: {
getData(): any {
@ -25,6 +26,9 @@ export const useDataStore = defineStore({
getFile(): any {
return this.file;
},
getXs(): any {
return this.xs;
}
},
actions: {
setData(data: any) {
@ -42,6 +46,9 @@ export const useDataStore = defineStore({
setFile(data: any) {
this.file = data;
},
setXs(data: any) {
this.xs = data;
}
},
persist: {
enabled: true,