| | |
| | | <div class="app-container"> |
| | | <!-- 搜索表单 --> |
| | | <div class="search_form"> |
| | | <!-- <div>--> |
| | | <!-- <span class="search_title">公告标题:</span>--> |
| | | <!-- <el-input--> |
| | | <!-- v-model="searchForm.title"--> |
| | | <!-- style="width: 240px"--> |
| | | <!-- placeholder="请输入公告标题搜索"--> |
| | | <!-- @change="handleQuery"--> |
| | | <!-- clearable--> |
| | | <!-- :prefix-icon="Search"--> |
| | | <!-- />--> |
| | | <!-- <span class="search_title ml10">公告类型:</span>--> |
| | | <!-- <el-select v-model="searchForm.type" clearable @change="handleQuery" style="width: 240px">--> |
| | | <!-- <el-option label="放假通知" :value="1"/>--> |
| | | <!-- <el-option label="设备维修通知" :value="2"/>--> |
| | | <!-- </el-select>--> |
| | | <!-- <span class="search_title ml10">状态:</span>--> |
| | | <!-- <el-select v-model="searchForm.status" clearable @change="handleQuery" style="width: 240px">--> |
| | | <!-- <el-option label="草稿" :value="0"/>--> |
| | | <!-- <el-option label="已发布" :value="1"/>--> |
| | | <!-- <el-option label="已下线" :value="2"/>--> |
| | | <!-- </el-select>--> |
| | | <!-- <el-button type="primary" @click="handleQuery" style="margin-left: 10px">搜索</el-button>--> |
| | | <!-- <el-button @click="resetQuery" style="margin-left: 10px">重置</el-button>--> |
| | | <!-- </div>--> |
| | | <div> |
| | | <el-button type="primary" @click="openForm('add')">新增公告</el-button> |
| | | <el-button type="danger" plain @click="handleDelete" :disabled="!selectedIds.length">删除</el-button> |
| | |
| | | |
| | | <!-- 通知公告板 --> |
| | | <div class="notice-board"> |
| | | <!-- 放假通知区域 --> |
| | | <div class="notice-section" v-if="holidayNoticeCount > 0"> |
| | | <!-- 统一通知区域 --> |
| | | <div class="notice-section" v-if="totalNoticeCount > 0"> |
| | | <div class="section-header"> |
| | | <h3>📅 放假通知</h3> |
| | | <span class="section-count">{{ holidayNoticeCount }}条</span> |
| | | <h3>� 通知公告</h3> |
| | | <span class="section-count">{{ totalNoticeCount }}条</span> |
| | | </div> |
| | | <div class="notice-cards"> |
| | | <!-- 放假通知 --> |
| | | <div |
| | | v-for="notice in holidayNotices" |
| | | :key="notice.id" |
| | | :key="'holiday-' + notice.id" |
| | | class="notice-card holiday-card" |
| | | :class="{ 'urgent': notice.priority === '3' }" |
| | | > |
| | |
| | | {{ notice.title }} |
| | | </div> |
| | | <div class="card-actions"> |
| | | <el-button link type="primary" @click="handleEdit(notice)">编辑</el-button> |
| | | <el-button link type="primary" @click="handleEdit(notice)" :disabled="isNoticeExpired(notice)">编辑</el-button> |
| | | <el-button link type="danger" @click="handleDelete(notice.id)">删除</el-button> |
| | | </div> |
| | | </div> |
| | |
| | | </div> |
| | | <div class="card-footer"> |
| | | <div class="card-meta"> |
| | | <span class="type" :class="'type-' + notice.type"> |
| | | {{ notice.type }} |
| | | </span> |
| | | <span class="priority" :class="'priority-' + notice.priority"> |
| | | {{ getPriorityText(notice.priority) }} |
| | | </span> |
| | | <span class="status" :class="'status-' + notice.status"> |
| | | {{ getStatusText(notice.status) }} |
| | | <span class="status" :class="'status-' + getNoticeStatus(notice)"> |
| | | {{ getStatusText(getNoticeStatus(notice)) }} |
| | | </span> |
| | | </div> |
| | | <div class="card-info"> |
| | | <span class="creator">{{ notice.createUserName }}</span> |
| | | <span class="time">{{ notice.createTime }}</span> |
| | | <span class="expiration" v-if="notice.expirationDate">截止日期:{{ notice.expirationDate }}</span> |
| | | </div> |
| | | </div> |
| | | <div class="card-remark" v-if="notice.remark"> |
| | |
| | | <span>{{ notice.remark }}</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <pagination |
| | | v-if="holidayNoticePage.total > 0" |
| | | :total="holidayNoticePage.total" |
| | | :page="holidayNoticePage.current" |
| | | :limit="holidayNoticePage.size" |
| | | @pagination="handleHolidayNoticeCurrentChange" |
| | | /> |
| | | |
| | | <!-- 设备维修通知区域 --> |
| | | <div class="notice-section" v-if="maintenanceNoticeCount > 0"> |
| | | <div class="section-header"> |
| | | <h3>🔧 设备维修通知</h3> |
| | | <span class="section-count">{{ maintenanceNoticeCount }}条</span> |
| | | </div> |
| | | <div class="notice-cards"> |
| | | |
| | | <!-- 设备维修通知 --> |
| | | <div |
| | | v-for="notice in maintenanceNotices" |
| | | :key="notice.id" |
| | | :key="'maintenance-' + notice.id" |
| | | class="notice-card maintenance-card" |
| | | :class="{ 'urgent': notice.priority === '3' }" |
| | | > |
| | |
| | | {{ notice.title }} |
| | | </div> |
| | | <div class="card-actions"> |
| | | <el-button link type="primary" @click="handleEdit(notice)">编辑</el-button> |
| | | <el-button link type="primary" @click="handleEdit(notice)" :disabled="isNoticeExpired(notice)">编辑</el-button> |
| | | <el-button link type="danger" @click="handleDelete(notice.id)">删除</el-button> |
| | | </div> |
| | | </div> |
| | |
| | | <span class="priority" :class="'priority-' + notice.priority"> |
| | | {{ getPriorityText(notice.priority) }} |
| | | </span> |
| | | <span class="status" :class="'status-' + notice.status"> |
| | | {{ getStatusText(notice.status) }} |
| | | <span class="status" :class="'status-' + getNoticeStatus(notice)"> |
| | | {{ getStatusText(getNoticeStatus(notice)) }} |
| | | </span> |
| | | </div> |
| | | <div class="card-info"> |
| | | <span class="creator">{{ notice.createUserName }}</span> |
| | | <span class="time">{{ notice.createTime }}</span> |
| | | <span class="expiration" v-if="notice.expirationDate">截止日期:{{ notice.expirationDate }}</span> |
| | | </div> |
| | | </div> |
| | | <div class="card-remark" v-if="notice.remark"> |
| | |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 统一分页 --> |
| | | <pagination |
| | | v-if="maintenanceNoticePage.total > 0" |
| | | :total="maintenanceNoticePage.total" |
| | | :page="maintenanceNoticePage.current" |
| | | :limit="maintenanceNoticePage.size" |
| | | @pagination="handleMaintenanceNoticeCurrentChange" |
| | | v-if="(holidayNoticePage.total + maintenanceNoticePage.total) > 0" |
| | | :total="holidayNoticePage.total + maintenanceNoticePage.total" |
| | | :page="Math.max(holidayNoticePage.current, maintenanceNoticePage.current)" |
| | | :limit="Math.max(holidayNoticePage.size, maintenanceNoticePage.size)" |
| | | @pagination="handleCurrentChange" |
| | | /> |
| | | |
| | | <!-- 空状态 --> |
| | |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="公告类型" prop="type"> |
| | | <el-select v-model="form.type" placeholder="请选择公告类型" style="width: 100%"> |
| | | <el-option label="放假通知" :value="1"/> |
| | | <el-option label="设备维修通知" :value="2"/> |
| | | </el-select> |
| | | <el-input v-model="form.type" placeholder="请输入公告标题"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | <el-form-item label="状态"> |
| | | <el-radio-group v-model="form.status"> |
| | | <el-radio :value="0">草稿</el-radio> |
| | | <el-radio :value="1">已发布</el-radio> |
| | | <el-radio :value="2">已下线</el-radio> |
| | | <el-radio :value="1">正式发布</el-radio> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="过期时间" prop="expirationDate"> |
| | | <el-date-picker v-model="form.expirationDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="date" |
| | | placeholder="请选择" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item label="公告内容" prop="noticeContent"> |
| | | <el-form-item label="公告内容" prop="content"> |
| | | <el-input |
| | | v-model="form.content" |
| | | type="textarea" |
| | |
| | | status: 0, |
| | | priority: 1, |
| | | remark: "", |
| | | expirationDate: "", |
| | | }, |
| | | rules: { |
| | | title: [ |
| | |
| | | ], |
| | | content: [ |
| | | {required: true, message: "公告内容不能为空", trigger: "blur"} |
| | | ], |
| | | expirationDate: [ |
| | | {required: true, message: "请选择日期", trigger: "change"} |
| | | ] |
| | | } |
| | | }); |
| | |
| | | }; |
| | | |
| | | const getStatusText = (status) => { |
| | | const statusMap = {"0": "草稿", "1": "已发布", "2": "已下线"}; |
| | | const statusMap = {"0": "草稿", "1": "已发布", "2": "已过期"}; |
| | | return statusMap[status] || "未知"; |
| | | }; |
| | | |
| | | const isNoticeExpired = (notice) => { |
| | | if (!notice || !notice.expirationDate) { |
| | | return false; |
| | | } |
| | | |
| | | const expiration = new Date(notice.expirationDate); |
| | | |
| | | if (Number.isNaN(expiration.getTime())) { |
| | | return false; |
| | | } |
| | | |
| | | expiration.setHours(23, 59, 59, 999); |
| | | |
| | | return new Date() > expiration; |
| | | }; |
| | | |
| | | const getNoticeStatus = (notice) => { |
| | | const normalizedStatus = notice && notice.status !== undefined && notice.status !== null |
| | | ? String(notice.status) |
| | | : "0"; |
| | | |
| | | return isNoticeExpired(notice) ? "2" : normalizedStatus; |
| | | }; |
| | | |
| | | const openForm = (type) => { |
| | |
| | | status: 0, |
| | | priority: 1, |
| | | remark: "", |
| | | expirationDate: "", |
| | | }; |
| | | } |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | | const handleEdit = (row) => { |
| | | if (isNoticeExpired(row)) { |
| | | ElMessage.warning("已过期的公告不可编辑"); |
| | | return; |
| | | } |
| | | dialogTitle.value = "编辑公告"; |
| | | form.value = {...row}; |
| | | dialogVisible.value = true; |
| | |
| | | }); |
| | | }; |
| | | |
| | | const holidayNoticeCount = ref() |
| | | const maintenanceNoticeCount = ref() |
| | | const totalNoticeCount = ref(0) |
| | | const fetchCount = () => { |
| | | getCount().then(res => { |
| | | holidayNoticeCount.value = res.data.filter(item => { |
| | | return item.type === 1 |
| | | })[0].count; |
| | | maintenanceNoticeCount.value = res.data.filter(item => { |
| | | return item.type === 2 |
| | | })[0].count; |
| | | totalNoticeCount.value = res.data.reduce((total, item) => total + item.count, 0); |
| | | }); |
| | | } |
| | | |
| | |
| | | const holidayNoticePage = ref({ |
| | | total: 0, |
| | | current: 1, |
| | | size: 6 |
| | | size: 9 |
| | | }) |
| | | |
| | | const maintenanceNoticePage = ref({ |
| | | total: 0, |
| | | current: 1, |
| | | size: 6 |
| | | size: 9 |
| | | }) |
| | | |
| | | const fetchHolidayNotices = () => { |
| | | listNotice({...holidayNoticePage.value, type: 1}).then(res => { |
| | | listNotice({...holidayNoticePage.value}).then(res => { |
| | | holidayNotices.value = res.data.records |
| | | holidayNoticePage.value.total = res.data.total |
| | | }); |
| | |
| | | }); |
| | | }; |
| | | |
| | | const handleHolidayNoticeCurrentChange = (val) => { |
| | | const handleCurrentChange = (val) => { |
| | | holidayNoticePage.value.size = val.limit |
| | | holidayNoticePage.value.current = val.page |
| | | fetchHolidayNotices() |
| | | }; |
| | | |
| | | const handleMaintenanceNoticeCurrentChange = (val) => { |
| | | maintenanceNoticePage.value.size = val.limit |
| | | maintenanceNoticePage.value.current = val.page |
| | | fetchHolidayNotices() |
| | | fetchMaintenanceNotices() |
| | | }; |
| | | |
| | | const resetTable = () => { |
| | | holidayNoticePage.value.current = 1 |
| | | holidayNoticePage.value.size = 6 |
| | | holidayNoticePage.value.size = 9 |
| | | maintenanceNoticePage.value.current = 1 |
| | | maintenanceNoticePage.value.size = 6 |
| | | maintenanceNoticePage.value.size = 9 |
| | | fetchHolidayNotices() |
| | | fetchMaintenanceNotices() |
| | | fetchCount() |
| | |
| | | gap: 8px; |
| | | } |
| | | |
| | | .priority, .status { |
| | | .type, .priority, .status { |
| | | padding: 2px 8px; |
| | | border-radius: 12px; |
| | | font-size: 12px; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .type-1 { |
| | | background: #f0f9ff; |
| | | color: #0369a1; |
| | | } |
| | | |
| | | .type-2 { |
| | | background: #fef3c7; |
| | | color: #d97706; |
| | | } |
| | | |
| | | .priority-1 { |
| | |
| | | margin-bottom: 2px; |
| | | } |
| | | |
| | | .expiration { |
| | | margin-top: 2px; |
| | | } |
| | | |
| | | .card-remark { |
| | | display: flex; |
| | | align-items: center; |