| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <!-- æç´¢è¡¨å --> |
| | | <div class="search_form"> |
| | | <div> |
| | | <el-button type="primary" @click="openForm('add')">æ°å¢å
Œ</el-button> |
| | | <el-button type="info" @click="openNoticeTypeDialog">å
¬åç±»åé
ç½®</el-button> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- éç¥å
¬åæ¿ --> |
| | | <div class="notice-board"> |
| | | <el-tabs v-model="activeNoticeTypeTab" @tab-change="handleNoticeTypeTabChange"> |
| | | <el-tab-pane |
| | | v-for="noticeType in noticeTypeList" |
| | | :key="noticeType.id" |
| | | :label="noticeType.noticeType" |
| | | :name="String(noticeType.id)" |
| | | > |
| | | <template #label> |
| | | <span>{{ noticeType.noticeType }} |
| | | <span class="tab-count" v-if="getNoticeCountByType(noticeType.id) > 0"> |
| | | ({{ getNoticeCountByType(noticeType.id) }}) |
| | | </span> |
| | | </span> |
| | | </template> |
| | | |
| | | <div class="notice-section"> |
| | | <div class="notice-cards"> |
| | | <div |
| | | v-for="notice in getNoticesByType(noticeType.id)" |
| | | :key="notice.id" |
| | | class="notice-card" |
| | | :class="{ 'urgent': notice.priority === '3' }" |
| | | > |
| | | <div class="card-header"> |
| | | <div class="card-title"> |
| | | <el-icon class="notice-icon"> |
| | | <Calendar/> |
| | | </el-icon> |
| | | {{ notice.title }} |
| | | </div> |
| | | <div class="card-actions"> |
| | | <el-button link type="primary" @click="handleEdit(notice)" :disabled="isNoticeExpired(notice)" v-if="notice.status !== 1">ç¼è¾</el-button> |
| | | <el-button link type="success" @click="handlePublish(notice)" v-if="notice.status === 0">åå¸</el-button> |
| | | <el-button link type="danger" @click="handleDelete(notice.id)" v-if="notice.status !== 1">å é¤</el-button> |
| | | </div> |
| | | </div> |
| | | <div class="card-content"> |
| | | <p>{{ notice.content }}</p> |
| | | </div> |
| | | <div class="card-footer"> |
| | | <div class="card-meta"> |
| | | <span class="priority" :class="'priority-' + notice.priority"> |
| | | {{ getPriorityText(notice.priority) }} |
| | | </span> |
| | | <span class="status" :class="'status-' + getNoticeStatus(notice)"> |
| | | {{ getStatusText(getNoticeStatus(notice)) }} |
| | | </span> |
| | | </div> |
| | | <div class="card-info"> |
| | | <span class="creator">{{ notice.createUserName }}</span> |
| | | <span class="expiration" v-if="notice.expirationDate">æªæ¢æ¥æï¼{{ notice.expirationDate }}</span> |
| | | </div> |
| | | </div> |
| | | <div class="card-remark" v-if="notice.remark"> |
| | | <el-icon> |
| | | <InfoFilled/> |
| | | </el-icon> |
| | | <span>{{ notice.remark }}</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <pagination |
| | | v-if="getNoticePageByType(noticeType.id).total > 0" |
| | | :total="getNoticePageByType(noticeType.id).total" |
| | | :page="getNoticePageByType(noticeType.id).current" |
| | | :limit="getNoticePageByType(noticeType.id).size" |
| | | @pagination="(val) => handleNoticeCurrentChange(noticeType.id, val)" |
| | | /> |
| | | |
| | | <!-- ç©ºç¶æ --> |
| | | <div class="empty-state" v-if="getNoticesByType(noticeType.id).length === 0"> |
| | | <el-empty description="ææ éç¥å
Œ"/> |
| | | </div> |
| | | </div> |
| | | </el-tab-pane> |
| | | </el-tabs> |
| | | </div> |
| | | |
| | | <!-- æ°å¢/ç¼è¾å¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | :title="dialogTitle" |
| | | v-model="dialogVisible" |
| | | width="800px" |
| | | append-to-body |
| | | @close="resetForm" |
| | | > |
| | | <el-form ref="formRef" :model="form" :rules="rules" label-width="100px"> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å
¬åæ é¢" prop="title"> |
| | | <el-input v-model="form.title" placeholder="请è¾å
¥å
¬åæ é¢"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å
¬åç±»å" prop="type"> |
| | | <el-select v-model="form.type" placeholder="è¯·éæ©å
¬åç±»å" style="width: 100%"> |
| | | <el-option |
| | | v-for="item in noticeTypeList" |
| | | :key="item.id" |
| | | :label="item.noticeType" |
| | | :value="item.id" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <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-group> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä¼å
级"> |
| | | <el-select v-model="form.priority" placeholder="è¯·éæ©ä¼å
级" style="width: 100%"> |
| | | <el-option label="æ®é" :value="1"/> |
| | | <el-option label="éè¦" :value="2"/> |
| | | <el-option label="ç´§æ¥" :value="3"/> |
| | | </el-select> |
| | | </el-form-item> |
| | | </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="content"> |
| | | <el-input |
| | | v-model="form.content" |
| | | type="textarea" |
| | | :rows="6" |
| | | placeholder="请è¾å
¥å
¬åå
容" |
| | | maxlength="500" |
| | | show-word-limit |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item label="夿³¨"> |
| | | <el-input |
| | | v-model="form.remark" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请è¾å
¥å¤æ³¨ä¿¡æ¯" |
| | | maxlength="200" |
| | | show-word-limit |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitForm">ç¡® å®</el-button> |
| | | <el-button @click="dialogVisible = false">å æ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- å
¬åç±»åé
ç½®å¼¹æ¡ --> |
| | | <el-dialog |
| | | v-model="noticeTypeDialogVisible" |
| | | title="å
¬åç±»åé
ç½®" |
| | | width="800px" |
| | | @close="handleNoticeTypeDialogClose" |
| | | > |
| | | <div class="notice-type-container"> |
| | | <div class="notice-type-header"> |
| | | <el-button type="primary" @click="handleAddNoticeType">æ°å¢ç±»å</el-button> |
| | | </div> |
| | | <el-table :data="noticeTypeList" border style="width: 100%"> |
| | | <el-table-column prop="id" label="ID" width="80" align="center"/> |
| | | <el-table-column prop="noticeType" label="å
¬åç±»å" align="center"> |
| | | <template #default="scope"> |
| | | <el-input |
| | | v-if="scope.row.editing" |
| | | v-model="scope.row.noticeType" |
| | | placeholder="请è¾å
¥å
¬åç±»å" |
| | | /> |
| | | <span v-else>{{ scope.row.noticeType }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æä½" width="200" align="center"> |
| | | <template #default="scope"> |
| | | <el-button |
| | | v-if="scope.row.editing" |
| | | link |
| | | type="primary" |
| | | @click="handleSaveNoticeType(scope.row)" |
| | | > |
| | | ä¿å |
| | | </el-button> |
| | | <el-button |
| | | v-if="scope.row.editing" |
| | | link |
| | | type="info" |
| | | @click="handleCancelEdit(scope.row)" |
| | | > |
| | | åæ¶ |
| | | </el-button> |
| | | <el-button |
| | | v-if="!scope.row.editing" |
| | | link |
| | | type="primary" |
| | | @click="handleEditNoticeType(scope.row)" |
| | | > |
| | | ç¼è¾ |
| | | </el-button> |
| | | <el-button |
| | | v-if="!scope.row.editing" |
| | | link |
| | | type="danger" |
| | | @click="handleDeleteNoticeType(scope.row)" |
| | | > |
| | | å é¤ |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {Calendar, InfoFilled} from "@element-plus/icons-vue"; |
| | | import {onMounted, ref, reactive, toRefs, computed} from "vue"; |
| | | import {ElMessage, ElMessageBox} from "element-plus"; |
| | | import {useRoute} from "vue-router"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { |
| | | addNotice, |
| | | delNotice, |
| | | getCount, |
| | | listNotice, |
| | | updateNotice, |
| | | listNoticeType, |
| | | addNoticeType, |
| | | delNoticeType |
| | | } from "../../../api/collaborativeApproval/noticeManagement.js"; |
| | | import pagination from "../../../components/PIMTable/Pagination.vue"; |
| | | |
| | | const userStore = useUserStore(); |
| | | const route = useRoute(); |
| | | |
| | | // ååºå¼æ°æ® |
| | | const data = reactive({ |
| | | searchForm: { |
| | | title: "", |
| | | type: undefined, |
| | | status: undefined, |
| | | }, |
| | | form: { |
| | | id: undefined, |
| | | title: "", |
| | | type: null, |
| | | content: "", |
| | | status: 0, |
| | | priority: 1, |
| | | remark: "", |
| | | expirationDate: "", |
| | | }, |
| | | rules: { |
| | | title: [ |
| | | {required: true, message: "å
¬åæ é¢ä¸è½ä¸ºç©º", trigger: "blur"} |
| | | ], |
| | | type: [ |
| | | {required: true, message: "è¯·éæ©å
¬åç±»å", trigger: "change"} |
| | | ], |
| | | content: [ |
| | | {required: true, message: "å
¬åå
容ä¸è½ä¸ºç©º", trigger: "blur"} |
| | | ], |
| | | expirationDate: [ |
| | | {required: true, message: "è¯·éæ©æ¥æ", trigger: "change"} |
| | | ] |
| | | } |
| | | }); |
| | | |
| | | const {searchForm, form, rules} = toRefs(data); |
| | | |
| | | // 页é¢ç¶æ |
| | | const dialogVisible = ref(false); |
| | | const dialogTitle = ref(""); |
| | | const formRef = ref(); |
| | | |
| | | // å
¬åç±»åé
ç½®ç¸å
³ |
| | | const noticeTypeDialogVisible = ref(false); |
| | | const noticeTypeList = ref([]); |
| | | const activeNoticeTypeTab = ref(''); |
| | | |
| | | // éç¥æ°æ® - ä½¿ç¨ Map åå¨ï¼key 为类å id |
| | | const noticesMap = ref({}); |
| | | const noticePagesMap = ref({}); |
| | | |
| | | |
| | | // 计ç®å±æ§ |
| | | const filteredNotices = computed(() => { |
| | | let filtered = [...mockData]; |
| | | |
| | | if (searchForm.value.noticeTitle) { |
| | | filtered = filtered.filter(item => |
| | | item.noticeTitle.includes(searchForm.value.noticeTitle) |
| | | ); |
| | | } |
| | | if (searchForm.value.noticeType) { |
| | | filtered = filtered.filter(item => |
| | | item.noticeType === searchForm.value.noticeType |
| | | ); |
| | | } |
| | | if (searchForm.value.status !== "") { |
| | | filtered = filtered.filter(item => |
| | | item.status === searchForm.value.status |
| | | ); |
| | | } |
| | | |
| | | return filtered; |
| | | }); |
| | | |
| | | // æ¹æ³å®ä¹ |
| | | const handleQuery = () => { |
| | | // æç´¢åè½ä¿æä¸åï¼ä½æ°æ®éè¿è®¡ç®å±æ§èªå¨è¿æ»¤ |
| | | }; |
| | | |
| | | const resetQuery = () => { |
| | | searchForm.value = { |
| | | title: "", |
| | | type: "", |
| | | status: "" |
| | | }; |
| | | }; |
| | | |
| | | const getPriorityText = (priority) => { |
| | | const priorityMap = {"1": "æ®é", "2": "éè¦", "3": "ç´§æ¥"}; |
| | | return priorityMap[priority] || "æ®é"; |
| | | }; |
| | | |
| | | const getStatusText = (status) => { |
| | | 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) => { |
| | | if (type === 'add') { |
| | | dialogTitle.value = "æ°å¢å
Œ"; |
| | | form.value = { |
| | | id: undefined, |
| | | title: "", |
| | | type: undefined, |
| | | content: "", |
| | | 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 handleDelete = (id) => { |
| | | ElMessageBox.confirm( |
| | | "确认å é¤è¿æ¡å
¬ååï¼", |
| | | "æç¤º", |
| | | { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning" |
| | | } |
| | | ).then(() => { |
| | | delNotice(id).then(res => { |
| | | ElMessage.success("å 餿å"); |
| | | resetTable() |
| | | }) |
| | | }); |
| | | }; |
| | | |
| | | const handlePublish = (notice) => { |
| | | ElMessageBox.confirm( |
| | | "确认åå¸è¿æ¡å
¬ååï¼", |
| | | "æç¤º", |
| | | { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "info" |
| | | } |
| | | ).then(() => { |
| | | updateNotice({ |
| | | ...notice, |
| | | status: 1 |
| | | }).then(res => { |
| | | if (res.code === 200) { |
| | | ElMessage.success("å叿å"); |
| | | resetTable() |
| | | } |
| | | }) |
| | | }); |
| | | }; |
| | | |
| | | const submitForm = () => { |
| | | formRef.value.validate((valid) => { |
| | | if (valid) { |
| | | if (form.value.id) { |
| | | // ç¼è¾æ¨¡å¼ |
| | | updateNotice(form.value).then(res => { |
| | | ElMessage.success("ä¿®æ¹æå"); |
| | | resetTable() |
| | | }) |
| | | } else { |
| | | // æ°å¢æ¨¡å¼ |
| | | addNotice(form.value).then(res => { |
| | | ElMessage.success("æ°å¢æå"); |
| | | resetTable() |
| | | }) |
| | | } |
| | | dialogVisible.value = false; |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | // åå§åæä¸ªç±»åçåé¡µæ°æ® |
| | | const initNoticePage = (typeId) => { |
| | | if (!noticePagesMap.value[typeId]) { |
| | | noticePagesMap.value[typeId] = { |
| | | total: 0, |
| | | current: 1, |
| | | size: 10 |
| | | }; |
| | | } |
| | | if (!noticesMap.value[typeId]) { |
| | | noticesMap.value[typeId] = []; |
| | | } |
| | | }; |
| | | |
| | | // è·åæä¸ªç±»åçéç¥å表 |
| | | const getNoticesByType = (typeId) => { |
| | | return noticesMap.value[typeId] || []; |
| | | }; |
| | | |
| | | // è·åæä¸ªç±»åçåé¡µæ°æ® |
| | | const getNoticePageByType = (typeId) => { |
| | | return noticePagesMap.value[typeId] || { total: 0, current: 1, size: 10 }; |
| | | }; |
| | | |
| | | // è·åæä¸ªç±»åçæ°é |
| | | const getNoticeCountByType = (typeId) => { |
| | | return getNoticePageByType(typeId).total || 0; |
| | | }; |
| | | |
| | | // è·åæä¸ªç±»åçéç¥æ°æ® |
| | | const fetchNoticesByType = (typeId) => { |
| | | initNoticePage(typeId); |
| | | const pageData = noticePagesMap.value[typeId]; |
| | | listNotice({...pageData, type: typeId}).then(res => { |
| | | if (res.code === 200) { |
| | | noticesMap.value[typeId] = res.data.records || []; |
| | | noticePagesMap.value[typeId].total = res.data.total || 0; |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | // å¤çå页åå |
| | | const handleNoticeCurrentChange = (typeId, val) => { |
| | | initNoticePage(typeId); |
| | | noticePagesMap.value[typeId].size = val.limit; |
| | | noticePagesMap.value[typeId].current = val.page; |
| | | fetchNoticesByType(typeId); |
| | | }; |
| | | |
| | | // å¤ç tab 忢 |
| | | const handleNoticeTypeTabChange = (tabName) => { |
| | | activeNoticeTypeTab.value = tabName; |
| | | const typeId = Number(tabName); |
| | | fetchNoticesByType(typeId); |
| | | }; |
| | | |
| | | const resetTable = () => { |
| | | // éç½®ææç±»åçå页并鿰è·åæ°æ® |
| | | noticeTypeList.value.forEach(type => { |
| | | initNoticePage(type.id); |
| | | noticePagesMap.value[type.id].current = 1; |
| | | noticePagesMap.value[type.id].size = 10; |
| | | fetchNoticesByType(type.id); |
| | | }); |
| | | }; |
| | | |
| | | const resetForm = () => { |
| | | formRef.value?.resetFields(); |
| | | }; |
| | | |
| | | // å
¬åç±»åé
ç½®ç¸å
³æ¹æ³ |
| | | const openNoticeTypeDialog = () => { |
| | | noticeTypeDialogVisible.value = true; |
| | | fetchNoticeTypeList(); |
| | | }; |
| | | |
| | | const fetchNoticeTypeList = () => { |
| | | return listNoticeType().then(res => { |
| | | if (res.code === 200) { |
| | | noticeTypeList.value = res.data.map(item => ({ |
| | | ...item, |
| | | editing: false |
| | | })); |
| | | |
| | | // æ£æ¥è·¯ç±åæ°ä¸ç type |
| | | const routeType = route.query.type; |
| | | let targetTypeId = null; |
| | | |
| | | if (routeType) { |
| | | // å¦æè·¯ç±åæ°ä¸æ typeï¼æ¥æ¾å¯¹åºçç±»å |
| | | const typeId = Number(routeType); |
| | | const foundType = noticeTypeList.value.find(item => item.id === typeId); |
| | | if (foundType) { |
| | | targetTypeId = typeId; |
| | | } |
| | | } |
| | | |
| | | // 妿æç±»åæ°æ® |
| | | if (noticeTypeList.value.length > 0) { |
| | | // å¦æè·¯ç±åæ°æå®äºç±»åä¸åå¨ï¼ä½¿ç¨è·¯ç±åæ°çç±»å |
| | | // å¦åå¦ææ²¡æéä¸ tabï¼é»è®¤éä¸ç¬¬ä¸ä¸ª |
| | | if (targetTypeId !== null) { |
| | | activeNoticeTypeTab.value = String(targetTypeId); |
| | | fetchNoticesByType(targetTypeId); |
| | | } else if (!activeNoticeTypeTab.value) { |
| | | activeNoticeTypeTab.value = String(noticeTypeList.value[0].id); |
| | | fetchNoticesByType(noticeTypeList.value[0].id); |
| | | } |
| | | } |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | const handleAddNoticeType = () => { |
| | | const newItem = { |
| | | id: undefined, |
| | | noticeType: '', |
| | | editing: true |
| | | }; |
| | | noticeTypeList.value.push(newItem); |
| | | }; |
| | | |
| | | const handleEditNoticeType = (row) => { |
| | | // ä¿ååå§å¼ |
| | | row.originalNoticeType = row.noticeType; |
| | | row.editing = true; |
| | | }; |
| | | |
| | | const handleSaveNoticeType = (row) => { |
| | | if (!row.noticeType || row.noticeType.trim() === '') { |
| | | ElMessage.warning('å
¬åç±»åä¸è½ä¸ºç©º'); |
| | | return; |
| | | } |
| | | |
| | | const data = { |
| | | noticeType: row.noticeType.trim() |
| | | }; |
| | | |
| | | if (row.id) { |
| | | // ç¼è¾æ¨¡å¼ - ä¼ å
¥id |
| | | data.id = row.id; |
| | | } |
| | | |
| | | addNoticeType(data).then(res => { |
| | | if (res.code === 200) { |
| | | ElMessage.success(row.id ? 'ç¼è¾æå' : 'æ°å¢æå'); |
| | | row.editing = false; |
| | | delete row.originalNoticeType; |
| | | fetchNoticeTypeList().then(() => { |
| | | // 妿å½åéä¸çç±»å被ç¼è¾ï¼éè¦éæ°è·åæ°æ® |
| | | if (row.id && activeNoticeTypeTab.value === String(row.id)) { |
| | | fetchNoticesByType(res.data?.id || row.id); |
| | | } |
| | | }); |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | const handleDeleteNoticeType = (row) => { |
| | | // å¦ææ²¡æidï¼è¯´ææ¯æ°å¢ä½æªä¿åçè¡ï¼ç´æ¥ä»å端å é¤ |
| | | if (!row.id) { |
| | | const index = noticeTypeList.value.indexOf(row); |
| | | if (index > -1) { |
| | | noticeTypeList.value.splice(index, 1); |
| | | } |
| | | return; |
| | | } |
| | | |
| | | // 妿æidï¼è°ç¨å端æ¥å£å é¤ |
| | | ElMessageBox.confirm( |
| | | "确认å é¤è¿ä¸ªå
¬åç±»ååï¼", |
| | | "æç¤º", |
| | | { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning" |
| | | } |
| | | ).then(() => { |
| | | delNoticeType(row.id).then(res => { |
| | | if (res.code === 200) { |
| | | ElMessage.success("å 餿å"); |
| | | // 妿å é¤çæ¯å½åéä¸çç±»åï¼åæ¢å°ç¬¬ä¸ä¸ªç±»å |
| | | if (activeNoticeTypeTab.value === String(row.id)) { |
| | | fetchNoticeTypeList().then(() => { |
| | | if (noticeTypeList.value.length > 0) { |
| | | activeNoticeTypeTab.value = String(noticeTypeList.value[0].id); |
| | | fetchNoticesByType(noticeTypeList.value[0].id); |
| | | } else { |
| | | activeNoticeTypeTab.value = ''; |
| | | } |
| | | }); |
| | | } else { |
| | | fetchNoticeTypeList(); |
| | | } |
| | | } |
| | | }); |
| | | }); |
| | | }; |
| | | |
| | | const handleCancelEdit = (row) => { |
| | | if (!row.id) { |
| | | // å¦ææ¯æ°å¢ä½æªä¿åçè¡ï¼ç§»é¤å® |
| | | const index = noticeTypeList.value.indexOf(row); |
| | | if (index > -1) { |
| | | noticeTypeList.value.splice(index, 1); |
| | | } |
| | | } else { |
| | | // 妿æ¯ç¼è¾ä¸çè¡ï¼åæ¶ç¼è¾ç¶æå¹¶æ¢å¤åå¼ |
| | | row.editing = false; |
| | | if (row.originalNoticeType !== undefined) { |
| | | row.noticeType = row.originalNoticeType; |
| | | delete row.originalNoticeType; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | const handleNoticeTypeDialogClose = () => { |
| | | // å
³éå¼¹æ¡æ¶ï¼åæ¶ææç¼è¾ç¶æ |
| | | noticeTypeList.value.forEach(item => { |
| | | if (item.editing && !item.id) { |
| | | // å¦ææ¯æ°å¢ä½æªä¿åçè¡ï¼ç§»é¤å® |
| | | const index = noticeTypeList.value.indexOf(item); |
| | | if (index > -1) { |
| | | noticeTypeList.value.splice(index, 1); |
| | | } |
| | | } else if (item.editing) { |
| | | // 妿æ¯ç¼è¾ä¸çè¡ï¼åæ¶ç¼è¾ç¶æå¹¶æ¢å¤åå¼ |
| | | item.editing = false; |
| | | if (item.originalNoticeType !== undefined) { |
| | | item.noticeType = item.originalNoticeType; |
| | | delete item.originalNoticeType; |
| | | } |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | // çå½å¨æ |
| | | onMounted(() => { |
| | | // å
è·åå
¬åç±»åå表ï¼ç¶åæ ¹æ®ç±»åè·åéç¥æ°æ® |
| | | fetchNoticeTypeList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .search_form { |
| | | background: #fff; |
| | | padding: 20px; |
| | | margin-bottom: 20px; |
| | | border-radius: 8px; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | } |
| | | |
| | | .search_title { |
| | | font-weight: 500; |
| | | color: #333; |
| | | margin-right: 8px; |
| | | } |
| | | |
| | | .ml10 { |
| | | margin-left: 10px; |
| | | } |
| | | |
| | | .notice-board { |
| | | background: #f5f7fa; |
| | | padding: 20px; |
| | | border-radius: 8px; |
| | | } |
| | | |
| | | .notice-section { |
| | | margin-bottom: 30px; |
| | | } |
| | | |
| | | .section-header { |
| | | display: flex; |
| | | align-items: center; |
| | | margin-bottom: 20px; |
| | | padding: 0 10px; |
| | | } |
| | | |
| | | .section-header h3 { |
| | | margin: 0; |
| | | color: #303133; |
| | | font-size: 18px; |
| | | font-weight: 600; |
| | | } |
| | | |
| | | .section-count { |
| | | margin-left: 10px; |
| | | background: #409eff; |
| | | color: white; |
| | | padding: 2px 8px; |
| | | border-radius: 12px; |
| | | font-size: 12px; |
| | | } |
| | | |
| | | .notice-cards { |
| | | display: grid; |
| | | grid-template-columns: repeat(auto-fill, minmax(400px, 1fr)); |
| | | gap: 20px; |
| | | } |
| | | |
| | | .notice-card { |
| | | background: white; |
| | | border-radius: 12px; |
| | | padding: 20px; |
| | | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); |
| | | transition: all 0.3s ease; |
| | | border-left: 4px solid transparent; |
| | | } |
| | | |
| | | .notice-card:hover { |
| | | transform: translateY(-2px); |
| | | box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15); |
| | | } |
| | | |
| | | .notice-icon { |
| | | color: #409eff; |
| | | margin-right: 8px; |
| | | font-size: 18px; |
| | | } |
| | | |
| | | .tab-count { |
| | | color: #909399; |
| | | font-size: 12px; |
| | | margin-left: 4px; |
| | | } |
| | | |
| | | .urgent { |
| | | border-left-color: #f56c6c; |
| | | background: linear-gradient(135deg, #fff5f5 0%, #ffffff 100%); |
| | | } |
| | | |
| | | .card-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: flex-start; |
| | | margin-bottom: 15px; |
| | | } |
| | | |
| | | .card-title { |
| | | display: flex; |
| | | align-items: center; |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | flex: 1; |
| | | } |
| | | |
| | | |
| | | .card-actions { |
| | | display: flex; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .card-content { |
| | | margin-bottom: 15px; |
| | | } |
| | | |
| | | .card-content p { |
| | | margin: 0; |
| | | color: #606266; |
| | | line-height: 1.6; |
| | | font-size: 14px; |
| | | word-break: break-all; |
| | | white-space: pre-wrap; |
| | | overflow-wrap: break-word; |
| | | } |
| | | |
| | | .card-footer { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .card-meta { |
| | | display: flex; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .priority, .status { |
| | | padding: 2px 8px; |
| | | border-radius: 12px; |
| | | font-size: 12px; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .priority-1 { |
| | | background: #f0f9ff; |
| | | color: #0369a1; |
| | | } |
| | | |
| | | .priority-2 { |
| | | background: #fef3c7; |
| | | color: #d97706; |
| | | } |
| | | |
| | | .priority-3 { |
| | | background: #fef2f2; |
| | | color: #dc2626; |
| | | } |
| | | |
| | | .status-0 { |
| | | background: #f3f4f6; |
| | | color: #6b7280; |
| | | } |
| | | |
| | | .status-1 { |
| | | background: #d1fae5; |
| | | color: #059669; |
| | | } |
| | | |
| | | .status-2 { |
| | | background: #fef3c7; |
| | | color: #d97706; |
| | | } |
| | | |
| | | .card-info { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: flex-end; |
| | | font-size: 12px; |
| | | color: #909399; |
| | | } |
| | | |
| | | .creator { |
| | | font-weight: 500; |
| | | margin-bottom: 2px; |
| | | } |
| | | |
| | | .expiration { |
| | | margin-top: 2px; |
| | | } |
| | | |
| | | .card-remark { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 6px; |
| | | padding: 8px 12px; |
| | | background: #f8f9fa; |
| | | border-radius: 6px; |
| | | font-size: 12px; |
| | | color: #606266; |
| | | border-left: 3px solid #409eff; |
| | | } |
| | | |
| | | .empty-state { |
| | | text-align: center; |
| | | padding: 60px 20px; |
| | | } |
| | | |
| | | .dialog-footer { |
| | | text-align: center; |
| | | } |
| | | |
| | | .notice-type-container { |
| | | padding: 10px 0; |
| | | } |
| | | |
| | | .notice-type-header { |
| | | margin-bottom: 15px; |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | } |
| | | |
| | | /* ååºå¼è®¾è®¡ */ |
| | | @media (max-width: 768px) { |
| | | .notice-cards { |
| | | grid-template-columns: 1fr; |
| | | } |
| | | |
| | | .search_form { |
| | | flex-direction: column; |
| | | gap: 15px; |
| | | } |
| | | |
| | | .search_form > div { |
| | | width: 100%; |
| | | } |
| | | } |
| | | </style> |