You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
742 lines
20 KiB
742 lines
20 KiB
<template>
|
|
<el-card class="box-card !border-none" shadow="never">
|
|
<div class="header-control-panel mb-4">
|
|
<div class="flex items-center flex-wrap">
|
|
<el-select
|
|
v-model="selectedCampus"
|
|
placeholder="请选择校区"
|
|
clearable
|
|
size="default"
|
|
class="mr-2 mb-2"
|
|
style="width: 160px;"
|
|
@change="handleCampusChange"
|
|
>
|
|
<el-option
|
|
v-for="item in campusList"
|
|
:key="item.id"
|
|
:label="item.campus_name"
|
|
:value="item.id"
|
|
/>
|
|
</el-select>
|
|
<el-button size="default" @click="prevWeek" icon="el-icon-arrow-left" class="mb-2">上一周</el-button>
|
|
<div class="mx-2 mb-2">
|
|
<el-date-picker
|
|
v-model="weekDate"
|
|
type="week"
|
|
format="YYYY 第 ww 周"
|
|
placeholder="选择周"
|
|
size="default"
|
|
style="width: 180px;"
|
|
@change="handleWeekChange"
|
|
/>
|
|
</div>
|
|
<el-button size="default" @click="nextWeek" icon="el-icon-arrow-right" class="mb-2">下一周</el-button>
|
|
<el-button type="primary" size="default" class="ml-2 mb-2" @click="fetchData">查询</el-button>
|
|
</div>
|
|
<div>
|
|
<el-button size="default" type="primary" plain @click="addSchedule">添加课程</el-button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="schedule-container">
|
|
<!-- 周一到周日的布局 -->
|
|
<div v-for="(day, index) in days" :key="index" class="day-column">
|
|
<div class="day-header">{{ day.date }}</div>
|
|
<el-table
|
|
:data="day.timeSlots"
|
|
border
|
|
:span-method="(data) => objectSpanMethod(day.timeSlots, data)"
|
|
style="width: 100%; height: 100%;"
|
|
max-height="100%"
|
|
:header-cell-style="{ background: '#f5f7fa', color: '#606266' }"
|
|
:cell-style="{ padding: '4px' }"
|
|
@cell-click="handleCellClick"
|
|
>
|
|
<!-- 时间列 -->
|
|
<el-table-column
|
|
prop="timeRange"
|
|
label="时间"
|
|
width="80"
|
|
align="center"
|
|
>
|
|
</el-table-column>
|
|
|
|
<!-- 教室列 -->
|
|
<el-table-column
|
|
v-for="(classroom, idx) in day.classrooms"
|
|
:key="idx"
|
|
:label="`${classroom.venue_name}`"
|
|
:prop="`classroom${classroom.id}`"
|
|
align="center"
|
|
width="280"
|
|
>
|
|
<template #default="{ row }">
|
|
<div v-if="row.course && row.course.classroom[0].id == classroom.id" class="course-cell" :style="{ backgroundColor: row.backgroundColor || '#f0f9eb', color: row.color ? '#fff' : '#000' }">
|
|
<div class="teacher-name">
|
|
{{ row.course.teacher[0].name }}
|
|
</div>
|
|
<div class="student-list" :style="{ backgroundColor: row.backgroundColor || '#f0f9eb', color: row.color ? '#fff' : '#000' }">
|
|
<div
|
|
v-for="student in row.course.students"
|
|
:key="student.id"
|
|
class="custom-student-tag"
|
|
>
|
|
<div class="tag-content">
|
|
<span class="tag-label">家长:</span>
|
|
<span class="tag-value">{{ student.resources?.name || '未知' }}</span>
|
|
<template v-if="student.student && student.student?.name">
|
|
<span class="tag-divider">|</span>
|
|
<span class="tag-label">学员:</span>
|
|
<span class="tag-value">{{ student.student?.name }}</span>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="classroom-name" :style="{ backgroundColor: row.backgroundColor || '#f0f9eb', color: row.color ? '#fff' : '#000' }">
|
|
剩余空位:{{ row.course.hasnumber }}
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
</div>
|
|
|
|
<!-- 详情弹窗 -->
|
|
<el-dialog v-model="dialogVisible" title="课程安排" width="600px" @open="handleDialogOpen">
|
|
<!-- 人员类型选择 -->
|
|
<div class="my-3">
|
|
<el-radio-group v-model="personType" @change="handlePersonTypeChange">
|
|
<el-radio :label="'course'">课程人员</el-radio>
|
|
<el-radio :label="'trial'">试课人员</el-radio>
|
|
</el-radio-group>
|
|
</div>
|
|
|
|
<!-- 试课人员搜索框 -->
|
|
<div v-if="personType === 'trial'" class="search-box mb-3">
|
|
<el-input
|
|
v-model="searchKeyword"
|
|
placeholder="请输入姓名或手机号"
|
|
class="mr-2"
|
|
style="width: 220px;"
|
|
>
|
|
<template #append>
|
|
<el-button @click="searchPerson">
|
|
<el-icon><Search /></el-icon>
|
|
</el-button>
|
|
</template>
|
|
</el-input>
|
|
</div>
|
|
|
|
<!-- 人员列表多选区域 -->
|
|
<div class="student-checkbox-container">
|
|
<el-checkbox-group v-model="selectedStudentIds">
|
|
<el-checkbox
|
|
v-for="student in students"
|
|
:key="student.id"
|
|
:label="student.id"
|
|
class="student-checkbox-item"
|
|
:checked="student.checked === true"
|
|
@change="(val) => handleStudentCheck(student, val)"
|
|
>
|
|
<div class="student-info">
|
|
<span class="student-name">{{ student.name }}</span>
|
|
<span v-if="student.student_name" class="student-school">
|
|
({{ student.student_name }})
|
|
</span>
|
|
</div>
|
|
</el-checkbox>
|
|
</el-checkbox-group>
|
|
<div v-if="students.length === 0" class="text-center py-3 text-gray-500">
|
|
暂无人员数据
|
|
</div>
|
|
</div>
|
|
|
|
<template #footer>
|
|
<span class="dialog-footer">
|
|
<el-button @click="dialogVisible = false">取消</el-button>
|
|
<el-button type="primary" @click="saveStudents">保存</el-button>
|
|
</span>
|
|
</template>
|
|
</el-dialog>
|
|
|
|
<!-- 添加课程弹窗组件 -->
|
|
<ScheduleAdd
|
|
v-model:visible="addDialogVisible"
|
|
:campusList="campusList"
|
|
@success="fetchData"
|
|
/>
|
|
</div>
|
|
</el-card>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, onMounted, computed } from 'vue'
|
|
import { getTimetables, getCourseStudents, getResourceByNameOrPhone } from '@/app/api/course_schedule'
|
|
import { addPersonCourseSchedule,getTryCoursePerson } from '@/app/api/person_course_schedule'
|
|
import { getWithCampusList } from '@/app/api/venue'
|
|
import ScheduleAdd from './components/schedule-add.vue'
|
|
import { ElMessage } from 'element-plus'
|
|
import { Search } from '@element-plus/icons-vue'
|
|
|
|
// 校区列表
|
|
const campusList = ref([])
|
|
const selectedCampus = ref('')
|
|
|
|
// 添加课程弹窗
|
|
const addDialogVisible = ref(false)
|
|
|
|
// 周日期选择
|
|
const weekDate = ref(new Date())
|
|
// 日期范围(根据周计算)
|
|
const dateRange = computed(() => {
|
|
if (!weekDate.value) return [null, null]
|
|
|
|
// 获取选择的周一和周日
|
|
const date = new Date(weekDate.value)
|
|
const day = date.getDay() || 7
|
|
// 设置为该周的周一
|
|
date.setDate(date.getDate() - day + 1)
|
|
const monday = new Date(date)
|
|
// 设置为该周的周日
|
|
date.setDate(date.getDate() + 6)
|
|
const sunday = new Date(date)
|
|
|
|
return [
|
|
monday.toISOString().split('T')[0],
|
|
sunday.toISOString().split('T')[0]
|
|
]
|
|
})
|
|
|
|
// 课程表数据
|
|
const days = ref([])
|
|
const dialogVisible = ref(false)
|
|
const selectedCourse = ref(null)
|
|
|
|
// 人员相关
|
|
const personType = ref('course') // 默认课程人员
|
|
const searchKeyword = ref('') // 搜索关键词
|
|
const students = ref([]) // 人员列表
|
|
const selectedStudentIds = ref([]) // 已选择的人员ID列表
|
|
const selectedStudents = ref([]) // 已选择的人员完整信息列表
|
|
const courseStudents = ref([]) // 课程人员列表缓存
|
|
const trialStudents = ref([]) // 试课人员列表缓存
|
|
|
|
// 上一周
|
|
const prevWeek = () => {
|
|
const date = new Date(weekDate.value)
|
|
date.setDate(date.getDate() - 7)
|
|
weekDate.value = date
|
|
fetchData()
|
|
}
|
|
|
|
// 下一周
|
|
const nextWeek = () => {
|
|
const date = new Date(weekDate.value)
|
|
date.setDate(date.getDate() + 7)
|
|
weekDate.value = date
|
|
fetchData()
|
|
}
|
|
|
|
// 周变化事件
|
|
const handleWeekChange = () => {
|
|
fetchData()
|
|
}
|
|
|
|
// 校区变化事件
|
|
const handleCampusChange = () => {
|
|
fetchData()
|
|
}
|
|
|
|
// 获取校区列表
|
|
const fetchCampusList = async () => {
|
|
try {
|
|
const response = await getWithCampusList({})
|
|
if (response.data) {
|
|
campusList.value = response.data
|
|
// 如果有校区数据,默认选择第一个
|
|
if (campusList.value.length > 0) {
|
|
selectedCampus.value = campusList.value[0].id
|
|
}
|
|
}
|
|
return Promise.resolve()
|
|
} catch (error) {
|
|
console.error('获取校区列表失败:', error)
|
|
return Promise.reject(error)
|
|
}
|
|
}
|
|
|
|
// 从服务器获取数据
|
|
const fetchData = async () => {
|
|
try {
|
|
const params = {}
|
|
if (dateRange.value && dateRange.value.length === 2) {
|
|
params.start_date = dateRange.value[0]
|
|
params.end_date = dateRange.value[1]
|
|
}
|
|
|
|
if (selectedCampus.value) {
|
|
params.campus_id = selectedCampus.value
|
|
}
|
|
|
|
const response = await getTimetables(params)
|
|
if (response.data) {
|
|
days.value = response.data
|
|
}
|
|
} catch (error) {
|
|
console.error('获取课程表数据失败:', error)
|
|
}
|
|
}
|
|
|
|
// 添加课程
|
|
const addSchedule = () => {
|
|
addDialogVisible.value = true
|
|
}
|
|
|
|
// 合并单元格方法
|
|
const objectSpanMethod = (timeSlots, { row, column, rowIndex }) => {
|
|
if (column.property === 'timeRange') {
|
|
// 获取当前时间段
|
|
const current = timeSlots[rowIndex]
|
|
|
|
// 如果当前行没有时间范围,不合并
|
|
if (!current || !current.timeRange) return { rowspan: 0, colspan: 0 }
|
|
|
|
let spanCount = 1
|
|
|
|
// 向下查找相同时间段的行数
|
|
while (timeSlots[rowIndex + spanCount]?.timeRange === current.timeRange) {
|
|
spanCount++
|
|
}
|
|
|
|
// 如果是重复的,隐藏该行
|
|
if (
|
|
spanCount > 1 &&
|
|
rowIndex > 0 &&
|
|
timeSlots[rowIndex - 1]?.timeRange === current.timeRange
|
|
) {
|
|
return { rowspan: 0, colspan: 0 }
|
|
}
|
|
|
|
return { rowspan: spanCount, colspan: 1 }
|
|
}
|
|
|
|
return { rowspan: 1, colspan: 1 }
|
|
}
|
|
|
|
// 单元格点击事件
|
|
const handleCellClick = (row, column, cell, event) => {
|
|
if (column.property.startsWith('classroom') && row.course) {
|
|
console.log(row.course.schedule)
|
|
selectedCourse.value = row.course.schedule.id
|
|
dialogVisible.value = true
|
|
} else {
|
|
ElMessage.warning('当天该时间段没有课程')
|
|
}
|
|
}
|
|
|
|
// 弹窗打开事件
|
|
const handleDialogOpen = async () => {
|
|
if (!selectedCourse.value) {
|
|
ElMessage.warning('未选择有效课程')
|
|
return
|
|
}
|
|
|
|
// 重置状态
|
|
personType.value = 'course'
|
|
searchKeyword.value = ''
|
|
courseStudents.value = []
|
|
trialStudents.value = []
|
|
students.value = []
|
|
selectedStudentIds.value = []
|
|
selectedStudents.value = []
|
|
|
|
// 加载课程人员列表
|
|
await fetchCourseStudents()
|
|
}
|
|
|
|
// 获取课程人员列表
|
|
const fetchCourseStudents = async () => {
|
|
try {
|
|
if (!selectedCourse.value) return
|
|
|
|
const response = await getCourseStudents(selectedCourse.value)
|
|
|
|
if (response.data) {
|
|
courseStudents.value = response.data || []
|
|
students.value = courseStudents.value
|
|
|
|
// 设置默认选中的学员 - 根据checked属性
|
|
const checkedStudents = students.value.filter(student => student.checked === true)
|
|
selectedStudentIds.value = checkedStudents.map(student => student.id)
|
|
|
|
// 同时记录完整的学员信息
|
|
selectedStudents.value = checkedStudents.map(student => ({
|
|
id: student.id,
|
|
student_id: student.student_id || null,
|
|
name: student.name,
|
|
student_name: student.student_name || null
|
|
}))
|
|
}
|
|
} catch (error) {
|
|
console.error('获取课程人员列表失败:', error)
|
|
ElMessage.error('获取课程人员列表失败')
|
|
courseStudents.value = []
|
|
students.value = []
|
|
selectedStudentIds.value = []
|
|
selectedStudents.value = []
|
|
}
|
|
}
|
|
|
|
// 处理学员选择变更
|
|
const handleStudentCheck = (student, checked) => {
|
|
if (checked) {
|
|
// 添加到已选学员列表
|
|
if (!selectedStudents.value.some(item => item.id === student.id)) {
|
|
selectedStudents.value.push({
|
|
id: student.id,
|
|
student_id: student.student_id || null,
|
|
name: student.name,
|
|
student_name: student.student_name || null
|
|
})
|
|
}
|
|
} else {
|
|
// 从已选学员列表移除
|
|
const index = selectedStudents.value.findIndex(item => item.id === student.id)
|
|
if (index !== -1) {
|
|
selectedStudents.value.splice(index, 1)
|
|
}
|
|
}
|
|
}
|
|
|
|
// 人员类型变更
|
|
const handlePersonTypeChange = async () => {
|
|
// 清空搜索框
|
|
searchKeyword.value = ''
|
|
|
|
if (personType.value === 'course') {
|
|
// 切换到课程人员时,显示已缓存的课程人员列表
|
|
students.value = courseStudents.value
|
|
} else {
|
|
// 切换到试课人员时,调用getTryCoursePerson获取已选中的人员
|
|
try {
|
|
if (selectedCourse.value) {
|
|
const response = await getTryCoursePerson(selectedCourse.value)
|
|
|
|
if (response.data) {
|
|
trialStudents.value = response.data || []
|
|
students.value = trialStudents.value
|
|
|
|
// 根据返回数据标记已选中的人员
|
|
const checkedStudents = students.value.filter(student => student.checked === true)
|
|
if (checkedStudents.length > 0) {
|
|
checkedStudents.forEach(student => {
|
|
if (!selectedStudentIds.value.includes(student.id)) {
|
|
selectedStudentIds.value.push(student.id)
|
|
|
|
// 同时添加到完整信息列表
|
|
if (!selectedStudents.value.some(item => item.id === student.id)) {
|
|
selectedStudents.value.push({
|
|
id: student.id,
|
|
student_id: student.student_id || null,
|
|
name: student.name,
|
|
student_name: student.student_name || null
|
|
})
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
} else {
|
|
// 如果没有选中课程,显示空列表
|
|
trialStudents.value = []
|
|
students.value = trialStudents.value
|
|
}
|
|
} catch (error) {
|
|
console.error('获取试课人员失败:', error)
|
|
ElMessage.error('获取试课人员失败')
|
|
trialStudents.value = []
|
|
students.value = trialStudents.value
|
|
}
|
|
}
|
|
}
|
|
|
|
// 搜索人员
|
|
const searchPerson = async () => {
|
|
if (!searchKeyword.value.trim()) {
|
|
ElMessage.warning('请输入搜索关键词')
|
|
return
|
|
}
|
|
|
|
try {
|
|
const response = await getResourceByNameOrPhone({
|
|
name: searchKeyword.value.trim()
|
|
})
|
|
|
|
if (response.data) {
|
|
// 保存当前已选学员ID列表
|
|
const currentSelectedIds = [...selectedStudentIds.value]
|
|
|
|
trialStudents.value = response.data || []
|
|
students.value = trialStudents.value
|
|
|
|
// 只有当学员的checked属性明确为true时才添加到已选列表中
|
|
// 不再默认选中第一个学员
|
|
const checkedStudents = students.value.filter(student => student.checked === true)
|
|
|
|
// 重置选中列表,使用之前保存的选择
|
|
selectedStudentIds.value = currentSelectedIds
|
|
|
|
// 添加有checked标记但未选中的项
|
|
if (checkedStudents.length > 0) {
|
|
checkedStudents.forEach(student => {
|
|
if (!selectedStudentIds.value.includes(student.id)) {
|
|
selectedStudentIds.value.push(student.id)
|
|
|
|
// 同时添加到完整信息列表
|
|
if (!selectedStudents.value.some(item => item.id === student.id)) {
|
|
selectedStudents.value.push({
|
|
id: student.id,
|
|
student_id: student.student_id || null,
|
|
name: student.name,
|
|
student_name: student.student_name || null
|
|
})
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error('搜索人员失败:', error)
|
|
ElMessage.error('搜索人员失败')
|
|
}
|
|
}
|
|
|
|
// 保存选择的人员
|
|
const saveStudents = async () => {
|
|
if (selectedStudentIds.value.length === 0) {
|
|
ElMessage.warning('请至少选择一名人员')
|
|
return
|
|
}
|
|
|
|
try {
|
|
// 调用添加人员接口
|
|
await addPersonCourseSchedule({
|
|
schedule_id: selectedCourse.value,
|
|
resources_id: selectedStudentIds.value,
|
|
// 添加student_id数据
|
|
student_ids: selectedStudents.value
|
|
.filter(student => student.student_id)
|
|
.map(student => student.student_id)
|
|
})
|
|
|
|
ElMessage.success('保存成功')
|
|
dialogVisible.value = false
|
|
|
|
// 刷新课程表数据
|
|
fetchData()
|
|
} catch (error) {
|
|
console.error('保存人员失败:', error)
|
|
ElMessage.error('保存人员失败')
|
|
}
|
|
}
|
|
|
|
// 页面加载时获取数据
|
|
onMounted(() => {
|
|
fetchCampusList().then(() => {
|
|
fetchData()
|
|
})
|
|
})
|
|
</script>
|
|
|
|
<style scoped>
|
|
.header-control-panel {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: flex-start;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.schedule-container {
|
|
display: flex;
|
|
gap: 5px;
|
|
overflow-x: auto;
|
|
background-color: #fff;
|
|
padding: 0;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.day-column {
|
|
flex: 1;
|
|
min-width: 180px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.day-header {
|
|
text-align: center;
|
|
font-weight: bold;
|
|
padding: 8px 0;
|
|
background-color: #f5f7fa;
|
|
border-top: 1px solid #ebeef5;
|
|
border-left: 1px solid #ebeef5;
|
|
border-right: 1px solid #ebeef5;
|
|
color: #606266;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.teacher-name {
|
|
font-weight: bold;
|
|
margin-bottom: 3px;
|
|
font-size: 13px;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
.student-list {
|
|
margin: 3px 0;
|
|
max-height: 60px;
|
|
overflow-y: auto;
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.el-table {
|
|
height: calc(100vh - 220px);
|
|
overflow-y: auto;
|
|
font-size: 13px;
|
|
border-collapse: collapse;
|
|
}
|
|
|
|
.el-table__cell {
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
|
|
.classroom-name {
|
|
margin-top: 3px;
|
|
font-size: 12px;
|
|
color: #606266;
|
|
}
|
|
|
|
.course-cell {
|
|
padding: 4px;
|
|
height: 100%;
|
|
width: 100%;
|
|
display: flex;
|
|
flex-direction: column;
|
|
overflow: hidden;
|
|
border-radius: 3px;
|
|
}
|
|
|
|
.custom-student-tag {
|
|
background-color: #ecf5ff;
|
|
color: #409eff;
|
|
border: 1px solid #d9ecff;
|
|
border-radius: 4px;
|
|
padding: 0 8px;
|
|
margin: 2px;
|
|
font-size: 12px;
|
|
display: inline-block;
|
|
max-width: 260px;
|
|
overflow: hidden;
|
|
white-space: nowrap;
|
|
text-overflow: ellipsis;
|
|
box-sizing: border-box;
|
|
height: 24px;
|
|
line-height: 22px;
|
|
transition: all .2s;
|
|
}
|
|
|
|
.custom-student-tag:hover {
|
|
background-color: #d9ecff;
|
|
color: #3a8ee6;
|
|
cursor: default;
|
|
}
|
|
|
|
.tag-content {
|
|
display: flex;
|
|
flex-wrap: nowrap;
|
|
align-items: center;
|
|
max-width: 100%;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.tag-label {
|
|
font-weight: bold;
|
|
font-size: 11px;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.tag-value {
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
flex: 1;
|
|
}
|
|
|
|
.tag-divider {
|
|
margin: 0 2px;
|
|
color: #99c2ff;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
:deep(.el-table__body-wrapper) {
|
|
overflow-y: auto;
|
|
height: 100%;
|
|
}
|
|
|
|
:deep(.el-table__header-wrapper) {
|
|
position: sticky;
|
|
top: 0;
|
|
z-index: 2;
|
|
}
|
|
|
|
:deep(.el-table--border) {
|
|
border-color: #ebeef5;
|
|
}
|
|
|
|
:deep(.el-table td), :deep(.el-table th) {
|
|
padding: 4px 0;
|
|
}
|
|
|
|
:deep(.el-table--enable-row-hover .el-table__body tr:hover > td) {
|
|
background-color: #f5f7fa;
|
|
}
|
|
|
|
.student-checkbox-container {
|
|
max-height: 300px;
|
|
overflow-y: auto;
|
|
border: 1px solid #ebeef5;
|
|
border-radius: 4px;
|
|
padding: 10px;
|
|
margin-bottom: 15px;
|
|
}
|
|
|
|
.student-checkbox-item {
|
|
margin-right: 10px;
|
|
margin-bottom: 8px;
|
|
display: inline-block;
|
|
}
|
|
|
|
.student-info {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.student-name {
|
|
font-weight: 500;
|
|
}
|
|
|
|
.student-school {
|
|
color: #666;
|
|
margin-left: 4px;
|
|
font-size: 0.9em;
|
|
}
|
|
|
|
.search-box {
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
</style>
|
|
|