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.
751 lines
20 KiB
751 lines
20 KiB
<template>
|
|
<el-dialog
|
|
v-model="visible"
|
|
title="课程安排详情"
|
|
width="90%"
|
|
class="course-arrangement-dialog"
|
|
:destroy-on-close="true"
|
|
@open="handleDialogOpen"
|
|
>
|
|
<div class="course-arrangement-container">
|
|
<!-- 课程信息区域 -->
|
|
<course-info-section
|
|
:schedule-info="scheduleInfo"
|
|
:loading="loading"
|
|
/>
|
|
|
|
<!-- 学员区域 -->
|
|
<student-section
|
|
:formal-students="formalStudents"
|
|
:waiting-students="waitingStudents"
|
|
:formal-empty-seats="formalEmptySeats"
|
|
:waiting-empty-seats="waitingEmptySeats"
|
|
:loading="loading"
|
|
@add-student="handleAddStudent"
|
|
@view-student="handleViewStudent"
|
|
@remove-student="handleRemoveStudent"
|
|
@upgrade-student="handleUpgradeStudent"
|
|
/>
|
|
</div>
|
|
|
|
<!-- 学员搜索弹窗 -->
|
|
<student-search-modal
|
|
v-model:visible="showSearchModal"
|
|
:current-slot="currentSlot"
|
|
:preset-student="presetStudent"
|
|
@confirm="handleConfirmAddStudent"
|
|
/>
|
|
|
|
<!-- 学员操作菜单 -->
|
|
<student-action-menu
|
|
v-model:visible="showActionMenu"
|
|
:student="currentStudent"
|
|
:formal-has-empty="formalEmptySeats.length > 0"
|
|
@confirm-action="handleConfirmAction"
|
|
/>
|
|
|
|
<!-- 学员详情弹窗 -->
|
|
<student-detail-modal ref="studentDetailModalRef" />
|
|
</el-dialog>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import { ref, reactive, computed, nextTick } from 'vue'
|
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
|
import {
|
|
getScheduleDetail,
|
|
removeStudent,
|
|
upgradeStudent,
|
|
addSchedule,
|
|
updateStudentStatus,
|
|
restoreStudent
|
|
} from '@/app/api/course_schedule'
|
|
import CourseInfoSection from './course-info-section.vue'
|
|
import StudentSection from './student-section.vue'
|
|
import StudentSearchModal from './student-search-modal.vue'
|
|
import StudentActionMenu from './student-action-menu.vue'
|
|
import StudentDetailModal from './student-detail-modal.vue'
|
|
|
|
import type {
|
|
StudentInfo,
|
|
ScheduleInfo,
|
|
SlotInfo,
|
|
ScheduleDetailResponse,
|
|
AddStudentParams,
|
|
RemoveStudentParams,
|
|
UpgradeStudentParams,
|
|
ApiResponse
|
|
} from '@/app/types/course-schedule'
|
|
|
|
// Props 定义
|
|
interface Props {
|
|
scheduleId?: number
|
|
resourceId?: number
|
|
studentId?: number
|
|
}
|
|
|
|
const props = withDefaults(defineProps<Props>(), {
|
|
scheduleId: 0,
|
|
resourceId: 0,
|
|
studentId: 0
|
|
})
|
|
|
|
// 响应式数据
|
|
const visible = ref(false)
|
|
const loading = ref(false)
|
|
const showSearchModal = ref(false)
|
|
const showActionMenu = ref(false)
|
|
|
|
// 课程安排数据
|
|
const scheduleInfo = ref<ScheduleInfo>({} as ScheduleInfo)
|
|
const formalStudents = ref<StudentInfo[]>([])
|
|
const waitingStudents = ref<StudentInfo[]>([])
|
|
const formalEmptySeats = ref<number[]>([])
|
|
const waitingEmptySeats = ref<number[]>([])
|
|
|
|
// 操作相关数据
|
|
const currentSlot = ref<SlotInfo>({ type: 'formal', index: 1 })
|
|
const currentStudent = ref<StudentInfo | null>(null)
|
|
const presetStudent = ref<StudentInfo | null>(null)
|
|
|
|
// 学员详情弹窗引用
|
|
const studentDetailModalRef = ref()
|
|
|
|
// 暴露给父组件的方法
|
|
const open = (scheduleId: number, resourceId?: number, studentId?: number) => {
|
|
if (scheduleId) {
|
|
scheduleInfo.value.id = scheduleId
|
|
}
|
|
if (resourceId) {
|
|
presetStudent.value = {
|
|
id: resourceId,
|
|
resource_id: resourceId,
|
|
student_id: studentId
|
|
} as StudentInfo
|
|
}
|
|
visible.value = true
|
|
}
|
|
|
|
// 对话框打开时的处理
|
|
const handleDialogOpen = async () => {
|
|
if (scheduleInfo.value.id) {
|
|
await loadScheduleDetail()
|
|
}
|
|
}
|
|
|
|
// 加载课程安排详情
|
|
const loadScheduleDetail = async () => {
|
|
try {
|
|
loading.value = true
|
|
|
|
if (!scheduleInfo.value.id) {
|
|
ElMessage.warning('课程安排ID不能为空')
|
|
return
|
|
}
|
|
|
|
const response: ApiResponse<ScheduleDetailResponse> = await getScheduleDetail({
|
|
schedule_id: scheduleInfo.value.id
|
|
})
|
|
|
|
if (response.code === 1 && response.data) {
|
|
// 处理嵌套的data结构
|
|
const data = response.data.data || response.data
|
|
|
|
// 更新课程信息
|
|
scheduleInfo.value = {
|
|
...scheduleInfo.value,
|
|
...data.schedule_info
|
|
}
|
|
|
|
// 更新学员数据
|
|
formalStudents.value = data.formal_students || []
|
|
waitingStudents.value = data.waiting_students || []
|
|
|
|
// 计算空位数组
|
|
formalEmptySeats.value = data.formal_empty_seats || []
|
|
waitingEmptySeats.value = data.waiting_empty_seats || []
|
|
|
|
console.log('课程安排详情加载成功:', {
|
|
scheduleInfo: scheduleInfo.value,
|
|
formalCount: formalStudents.value.length,
|
|
waitingCount: waitingStudents.value.length,
|
|
formalEmpty: formalEmptySeats.value.length,
|
|
waitingEmpty: waitingEmptySeats.value.length
|
|
})
|
|
|
|
// 成功反馈
|
|
nextTick(() => {
|
|
ElMessage.success({
|
|
message: '课程详情加载成功',
|
|
duration: 1500,
|
|
showClose: false
|
|
})
|
|
})
|
|
} else {
|
|
const errorMsg = response.msg || '获取课程安排详情失败'
|
|
ElMessage.error({
|
|
message: errorMsg,
|
|
duration: 3000,
|
|
showClose: true
|
|
})
|
|
console.error('加载课程详情失败:', response)
|
|
}
|
|
} catch (error) {
|
|
console.error('加载课程安排详情失败:', error)
|
|
|
|
let errorMessage = '网络异常,获取课程详情失败'
|
|
|
|
if (error instanceof Error) {
|
|
if (error.message.includes('timeout')) {
|
|
errorMessage = '请求超时,请检查网络连接'
|
|
} else if (error.message.includes('Network')) {
|
|
errorMessage = '网络连接失败,请检查网络设置'
|
|
}
|
|
}
|
|
|
|
ElMessage.error({
|
|
message: errorMessage,
|
|
duration: 5000,
|
|
showClose: true
|
|
})
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
// 添加学员
|
|
const handleAddStudent = (slotInfo: SlotInfo) => {
|
|
currentSlot.value = slotInfo
|
|
showSearchModal.value = true
|
|
}
|
|
|
|
// 查看学员详情
|
|
const handleViewStudent = (student: StudentInfo) => {
|
|
currentStudent.value = student
|
|
showActionMenu.value = true
|
|
}
|
|
|
|
// 确认添加学员
|
|
const handleConfirmAddStudent = async (student: StudentInfo, slot: SlotInfo) => {
|
|
try {
|
|
// 数据验证
|
|
if (!scheduleInfo.value.id) {
|
|
ElMessage.warning('课程安排ID不能为空')
|
|
return
|
|
}
|
|
|
|
if (!student.person_type) {
|
|
ElMessage.warning('学员类型不能为空')
|
|
return
|
|
}
|
|
|
|
const addData: AddStudentParams = {
|
|
schedule_id: scheduleInfo.value.id,
|
|
person_type: student.person_type,
|
|
schedule_type: slot.type === 'formal' ? 1 : 2,
|
|
course_date: scheduleInfo.value.course_date || '',
|
|
time_slot: scheduleInfo.value.time_slot || ''
|
|
}
|
|
|
|
// 根据学员类型添加对应的ID
|
|
if (student.person_type === 'student') {
|
|
addData.student_id = student.student_id || student.id
|
|
if (!addData.student_id) {
|
|
ElMessage.warning('学员ID不能为空')
|
|
return
|
|
}
|
|
} else {
|
|
addData.resources_id = student.resources_id || student.resource_id || student.id
|
|
if (!addData.resources_id) {
|
|
ElMessage.warning('客户资源ID不能为空')
|
|
return
|
|
}
|
|
}
|
|
|
|
console.log('添加学员数据:', addData)
|
|
|
|
// 显示加载状态
|
|
const loadingMessage = ElMessage({
|
|
message: '正在添加学员...',
|
|
type: 'info',
|
|
duration: 0,
|
|
showClose: false
|
|
})
|
|
|
|
const response = await addSchedule(addData)
|
|
|
|
// 关闭加载状态
|
|
loadingMessage.close()
|
|
|
|
if (response.code === 1) {
|
|
ElMessage.success({
|
|
message: `成功将学员 ${student.name} 添加到${slot.type === 'formal' ? '正式位' : '等待位'}`,
|
|
duration: 3000,
|
|
showClose: true
|
|
})
|
|
await loadScheduleDetail() // 刷新数据
|
|
} else {
|
|
ElMessage.error({
|
|
message: response.msg || '添加学员失败',
|
|
duration: 5000,
|
|
showClose: true
|
|
})
|
|
}
|
|
} catch (error) {
|
|
console.error('添加学员失败:', error)
|
|
|
|
let errorMessage = '添加学员失败'
|
|
if (error instanceof Error) {
|
|
if (error.message.includes('timeout')) {
|
|
errorMessage = '添加学员超时,请重试'
|
|
} else if (error.message.includes('Network')) {
|
|
errorMessage = '网络异常,请检查网络连接'
|
|
}
|
|
}
|
|
|
|
ElMessage.error({
|
|
message: errorMessage,
|
|
duration: 5000,
|
|
showClose: true
|
|
})
|
|
}
|
|
}
|
|
|
|
// 确认学员操作
|
|
const handleConfirmAction = async (action: string) => {
|
|
if (!currentStudent.value) return
|
|
|
|
try {
|
|
switch (action) {
|
|
case 'remove':
|
|
await handleRemoveStudent(currentStudent.value)
|
|
break
|
|
case 'upgrade':
|
|
await handleUpgradeStudent(currentStudent.value)
|
|
break
|
|
case 'leave':
|
|
await handleStudentLeave(currentStudent.value)
|
|
break
|
|
case 'cancel_leave':
|
|
await handleCancelLeave(currentStudent.value)
|
|
break
|
|
case 'checkin':
|
|
await handleStudentCheckin(currentStudent.value)
|
|
break
|
|
case 'view':
|
|
await handleViewStudentDetails(currentStudent.value)
|
|
break
|
|
default:
|
|
ElMessage.warning('未知操作类型')
|
|
break
|
|
}
|
|
await loadScheduleDetail() // 刷新数据
|
|
} catch (error) {
|
|
console.error('操作失败:', error)
|
|
}
|
|
}
|
|
|
|
// 删除学员
|
|
const handleRemoveStudent = async (student: StudentInfo) => {
|
|
try {
|
|
// 检查学员状态
|
|
if (student.status === 1) {
|
|
const confirmResult = await ElMessageBox.confirm(
|
|
`学员 ${student.name} 已经签到上课,确定要删除吗?\n\n此操作将影响考勤记录,请谨慎操作。`,
|
|
'重要提示',
|
|
{
|
|
confirmButtonText: '仍要删除',
|
|
cancelButtonText: '取消',
|
|
type: 'error',
|
|
showCancelButton: true
|
|
}
|
|
)
|
|
if (confirmResult !== 'confirm') return
|
|
}
|
|
|
|
const { value: reason } = await ElMessageBox.prompt(
|
|
`请输入删除学员 ${student.name} 的原因:`,
|
|
'删除学员',
|
|
{
|
|
confirmButtonText: '确定删除',
|
|
cancelButtonText: '取消',
|
|
inputPlaceholder: '请输入删除原因(必填)',
|
|
inputValue: '',
|
|
inputType: 'textarea',
|
|
inputValidator: (value) => {
|
|
if (!value || value.trim().length === 0) {
|
|
return '请输入删除原因'
|
|
}
|
|
if (value.length > 200) {
|
|
return '删除原因不能超过200个字符'
|
|
}
|
|
return true
|
|
},
|
|
showCancelButton: true,
|
|
closeOnClickModal: false,
|
|
closeOnPressEscape: false
|
|
}
|
|
)
|
|
|
|
if (reason) {
|
|
// 显示加载状态
|
|
const loadingMessage = ElMessage({
|
|
message: '正在删除学员...',
|
|
type: 'info',
|
|
duration: 0,
|
|
showClose: false
|
|
})
|
|
|
|
const response = await removeStudent({
|
|
schedule_id: scheduleInfo.value.id,
|
|
person_id: student.person_id || student.id,
|
|
person_type: student.person_type,
|
|
reason: `管理员删除:${reason.trim()}`
|
|
})
|
|
|
|
loadingMessage.close()
|
|
|
|
if (response.code === 1) {
|
|
ElMessage.success({
|
|
message: `学员 ${student.name} 删除成功`,
|
|
duration: 3000,
|
|
showClose: true
|
|
})
|
|
} else {
|
|
ElMessage.error({
|
|
message: response.msg || '删除学员失败',
|
|
duration: 5000,
|
|
showClose: true
|
|
})
|
|
}
|
|
}
|
|
} catch (error) {
|
|
if (error !== 'cancel') {
|
|
console.error('删除学员失败:', error)
|
|
|
|
let errorMessage = '删除学员失败'
|
|
if (error instanceof Error && error.message.includes('Network')) {
|
|
errorMessage = '网络异常,请检查网络连接'
|
|
}
|
|
|
|
ElMessage.error({
|
|
message: errorMessage,
|
|
duration: 5000,
|
|
showClose: true
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
// 升级学员
|
|
const handleUpgradeStudent = async (student: StudentInfo) => {
|
|
// 验证正式位是否有空位
|
|
if (formalEmptySeats.value.length === 0) {
|
|
ElMessage.warning({
|
|
message: '正式位已满,无法升级。请先移除部分正式位学员或联系管理员扩容。',
|
|
duration: 5000,
|
|
showClose: true
|
|
})
|
|
return
|
|
}
|
|
|
|
// 验证学员是否在等待位
|
|
if (student.schedule_type !== 2) {
|
|
ElMessage.warning('只有等待位学员才能升级为正式位')
|
|
return
|
|
}
|
|
|
|
try {
|
|
const result = await ElMessageBox.confirm(
|
|
`确定要将等待位学员 ${student.name} 升级为正式学员吗?\n\n升级后将占用一个正式位名额,且操作不可撤销。`,
|
|
'确认升级',
|
|
{
|
|
confirmButtonText: '确定升级',
|
|
cancelButtonText: '取消',
|
|
type: 'warning',
|
|
showCancelButton: true,
|
|
closeOnClickModal: false,
|
|
closeOnPressEscape: false
|
|
}
|
|
)
|
|
|
|
if (result === 'confirm') {
|
|
// 显示加载状态
|
|
const loadingMessage = ElMessage({
|
|
message: '正在升级学员...',
|
|
type: 'info',
|
|
duration: 0,
|
|
showClose: false
|
|
})
|
|
|
|
const response = await upgradeStudent({
|
|
schedule_id: scheduleInfo.value.id,
|
|
person_id: student.person_id || student.id,
|
|
from_type: 2, // 从等待位
|
|
to_type: 1 // 到正式位
|
|
})
|
|
|
|
loadingMessage.close()
|
|
|
|
if (response.code === 1) {
|
|
ElMessage.success({
|
|
message: `学员 ${student.name} 升级成功!已移至正式位`,
|
|
duration: 3000,
|
|
showClose: true
|
|
})
|
|
} else {
|
|
ElMessage.error({
|
|
message: response.msg || '升级失败',
|
|
duration: 5000,
|
|
showClose: true
|
|
})
|
|
}
|
|
}
|
|
} catch (error) {
|
|
if (error !== 'cancel') {
|
|
console.error('升级学员失败:', error)
|
|
|
|
let errorMessage = '升级学员失败'
|
|
if (error instanceof Error) {
|
|
if (error.message.includes('timeout')) {
|
|
errorMessage = '升级超时,请重试'
|
|
} else if (error.message.includes('Network')) {
|
|
errorMessage = '网络异常,请检查网络连接'
|
|
}
|
|
}
|
|
|
|
ElMessage.error({
|
|
message: errorMessage,
|
|
duration: 5000,
|
|
showClose: true
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
// 学员请假
|
|
const handleStudentLeave = async (student: StudentInfo) => {
|
|
try {
|
|
// 验证学员状态
|
|
if (student.status === 2) {
|
|
ElMessage.warning(`学员 ${student.name} 已经在请假状态了`)
|
|
return
|
|
}
|
|
|
|
const { value: reason } = await ElMessageBox.prompt(
|
|
`请输入学员 ${student.name} 的请假原因:`,
|
|
'学员请假',
|
|
{
|
|
confirmButtonText: '确定请假',
|
|
cancelButtonText: '取消',
|
|
inputPlaceholder: '请输入请假原因(可选)',
|
|
inputValue: '',
|
|
inputType: 'textarea',
|
|
inputValidator: (value) => {
|
|
if (value && value.length > 200) {
|
|
return '请假原因不能超过200个字符'
|
|
}
|
|
return true
|
|
},
|
|
showCancelButton: true,
|
|
closeOnClickModal: false,
|
|
closeOnPressEscape: false
|
|
}
|
|
)
|
|
|
|
// 显示加载状态
|
|
const loadingMessage = ElMessage({
|
|
message: '正在处理请假...',
|
|
type: 'info',
|
|
duration: 0,
|
|
showClose: false
|
|
})
|
|
|
|
const response = await removeStudent({
|
|
schedule_id: scheduleInfo.value.id,
|
|
person_id: student.person_id || student.id,
|
|
person_type: student.person_type,
|
|
reason: `请假:${reason || '无原因'}`
|
|
})
|
|
|
|
loadingMessage.close()
|
|
|
|
if (response.code === 1) {
|
|
ElMessage.success({
|
|
message: `学员 ${student.name} 请假处理成功`,
|
|
duration: 3000,
|
|
showClose: true
|
|
})
|
|
} else {
|
|
ElMessage.error({
|
|
message: response.msg || '请假处理失败',
|
|
duration: 5000,
|
|
showClose: true
|
|
})
|
|
}
|
|
} catch (error) {
|
|
if (error !== 'cancel') {
|
|
console.error('学员请假失败:', error)
|
|
|
|
let errorMessage = '请假处理失败'
|
|
if (error instanceof Error && error.message.includes('Network')) {
|
|
errorMessage = '网络异常,请检查网络连接'
|
|
}
|
|
|
|
ElMessage.error({
|
|
message: errorMessage,
|
|
duration: 5000,
|
|
showClose: true
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
// 取消请假
|
|
const handleCancelLeave = async (student: StudentInfo) => {
|
|
try {
|
|
const result = await ElMessageBox.confirm(
|
|
`确定要取消学员 ${student.name} 的请假状态吗?`,
|
|
'取消请假',
|
|
{
|
|
confirmButtonText: '确定',
|
|
cancelButtonText: '取消',
|
|
type: 'info'
|
|
}
|
|
)
|
|
|
|
if (result === 'confirm') {
|
|
const response = await restoreStudent({
|
|
schedule_id: scheduleInfo.value.id,
|
|
person_id: student.person_id || student.id
|
|
})
|
|
|
|
if (response.code === 1) {
|
|
ElMessage.success('取消请假成功')
|
|
} else {
|
|
ElMessage.error(response.msg || '取消请假失败')
|
|
}
|
|
}
|
|
} catch (error) {
|
|
if (error !== 'cancel') {
|
|
console.error('取消请假失败:', error)
|
|
ElMessage.error('取消请假失败')
|
|
}
|
|
}
|
|
}
|
|
|
|
// 学员签到
|
|
const handleStudentCheckin = async (student: StudentInfo) => {
|
|
try {
|
|
const currentStatus = student.status === 1 ? '已签到' : student.status === 2 ? '请假' : '待上课'
|
|
|
|
// 如果已经签到,询问是否取消签到
|
|
if (student.status === 1) {
|
|
const result = await ElMessageBox.confirm(
|
|
`学员 ${student.name} 当前状态:${currentStatus}\n\n确定要取消签到吗?`,
|
|
'取消签到确认',
|
|
{
|
|
confirmButtonText: '取消签到',
|
|
cancelButtonText: '保持现状',
|
|
type: 'warning'
|
|
}
|
|
)
|
|
|
|
if (result === 'confirm') {
|
|
const response = await updateStudentStatus({
|
|
schedule_id: scheduleInfo.value.id,
|
|
person_id: student.person_id || student.id,
|
|
status: 0, // 改为待上课
|
|
reason: '管理员取消签到'
|
|
})
|
|
|
|
if (response.code === 1) {
|
|
ElMessage.success('已取消签到状态')
|
|
} else {
|
|
ElMessage.error(response.msg || '取消签到失败')
|
|
}
|
|
}
|
|
} else {
|
|
// 其他状态,询问是否签到
|
|
const result = await ElMessageBox.confirm(
|
|
`学员 ${student.name} 当前状态:${currentStatus}\n\n确定要标记为已签到吗?`,
|
|
'签到确认',
|
|
{
|
|
confirmButtonText: '确认签到',
|
|
cancelButtonText: '取消',
|
|
type: 'info'
|
|
}
|
|
)
|
|
|
|
if (result === 'confirm') {
|
|
const response = await updateStudentStatus({
|
|
schedule_id: scheduleInfo.value.id,
|
|
person_id: student.person_id || student.id,
|
|
status: 1, // 标记为已签到
|
|
reason: '管理员确认签到'
|
|
})
|
|
|
|
if (response.code === 1) {
|
|
ElMessage.success('签到成功')
|
|
} else {
|
|
ElMessage.error(response.msg || '签到失败')
|
|
}
|
|
}
|
|
}
|
|
} catch (error) {
|
|
if (error !== 'cancel') {
|
|
console.error('更新签到状态失败:', error)
|
|
ElMessage.error('更新签到状态失败')
|
|
}
|
|
}
|
|
}
|
|
|
|
// 查看学员详情
|
|
const handleViewStudentDetails = async (student: StudentInfo) => {
|
|
try {
|
|
// 从StudentInfo中获取student_id或person_id作为学员ID
|
|
const studentId = student.student_id || student.person_id || student.id
|
|
|
|
if (!studentId) {
|
|
ElMessage.warning('无法获取学员ID')
|
|
return
|
|
}
|
|
|
|
// 打开学员详情弹窗
|
|
if (studentDetailModalRef.value) {
|
|
await studentDetailModalRef.value.open(studentId)
|
|
} else {
|
|
ElMessage.error('学员详情组件未正确加载')
|
|
}
|
|
} catch (error) {
|
|
console.error('查看学员详情失败:', error)
|
|
ElMessage.error('查看学员详情失败')
|
|
}
|
|
}
|
|
|
|
// 暴露给父组件的方法
|
|
defineExpose({
|
|
open
|
|
})
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.course-arrangement-dialog {
|
|
.course-arrangement-container {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 24px;
|
|
max-height: 70vh;
|
|
overflow-y: auto;
|
|
}
|
|
}
|
|
|
|
:deep(.el-dialog__body) {
|
|
padding: 20px;
|
|
}
|
|
|
|
:deep(.el-dialog__header) {
|
|
padding: 20px 20px 10px 20px;
|
|
margin-right: 0;
|
|
}
|
|
</style>
|