<!--OA模块:NoticeAnnouncement 通知公告-->
|
<template>
|
<div class="app-container notice-announcement-page">
|
<div class="search_form mb20">
|
<div class="search_fields">
|
<span class="search_title">关键词:</span>
|
<el-input
|
v-model="searchForm.keyword"
|
style="width: 200px"
|
placeholder="标题 / 编号"
|
clearable
|
:prefix-icon="Search"
|
@keyup.enter="handleQuery"
|
/>
|
<span class="search_title" style="margin-left: 12px">类型:</span>
|
<el-select v-model="searchForm.noticeType" placeholder="全部" clearable style="width: 130px">
|
<el-option v-for="opt in NOTICE_TYPE_OPTIONS" :key="opt.value" :label="opt.label" :value="opt.value" />
|
</el-select>
|
<span class="search_title" style="margin-left: 12px">优先级:</span>
|
<el-select v-model="searchForm.priority" placeholder="全部" clearable style="width: 110px">
|
<el-option v-for="opt in PRIORITY_OPTIONS" :key="opt.value" :label="opt.label" :value="opt.value" />
|
</el-select>
|
<span class="search_title" style="margin-left: 12px">状态:</span>
|
<el-select v-model="searchForm.publishStatus" placeholder="全部" clearable style="width: 110px">
|
<el-option v-for="opt in PUBLISH_STATUS_OPTIONS" :key="opt.value" :label="opt.label" :value="opt.value" />
|
</el-select>
|
<span class="search_title" style="margin-left: 12px">发布日期:</span>
|
<el-date-picker
|
v-model="searchForm.publishDateRange"
|
type="daterange"
|
range-separator="-"
|
start-placeholder="开始"
|
end-placeholder="结束"
|
format="YYYY-MM-DD"
|
value-format="YYYY-MM-DD"
|
style="width: 260px"
|
clearable
|
/>
|
<el-button type="primary" :icon="Search" class="ml10" @click="handleQuery">搜索</el-button>
|
<el-button :icon="RefreshRight" @click="resetSearch">重置</el-button>
|
</div>
|
<div class="search_actions">
|
<el-button type="primary" :icon="Plus" @click="openFormDialog('add')">添加公告</el-button>
|
</div>
|
</div>
|
|
<div class="table_list">
|
<PIMTable
|
rowKey="id"
|
:column="tableColumn"
|
:tableData="tableData"
|
:page="page"
|
:isSelection="false"
|
:tableLoading="tableLoading"
|
:total="page.total"
|
@pagination="pagination"
|
>
|
<template #noticeType="{ row }">
|
<span class="notice-type-tag" :style="{ color: noticeTypeColor(row.noticeType) }">
|
{{ noticeTypeLabel(row.noticeType) }}
|
</span>
|
</template>
|
</PIMTable>
|
</div>
|
|
<!-- 添加 / 修改 -->
|
<el-dialog
|
v-model="formDialog.visible"
|
:title="formDialog.title"
|
width="800px"
|
append-to-body
|
destroy-on-close
|
class="notice-form-dialog"
|
@closed="formRef?.resetFields?.()"
|
>
|
<el-form
|
ref="formRef"
|
:model="form"
|
:rules="formRules"
|
label-width="100px"
|
:disabled="formDialog.readonly"
|
>
|
<el-form-item label="标题" prop="title">
|
<el-input v-model="form.title" placeholder="请输入公告标题" maxlength="100" show-word-limit />
|
</el-form-item>
|
<el-row :gutter="20">
|
<el-col :span="12">
|
<el-form-item label="公告类型" prop="noticeType">
|
<el-select v-model="form.noticeType" placeholder="请选择" style="width: 100%" @change="onNoticeTypeChange">
|
<el-option v-for="opt in NOTICE_TYPE_OPTIONS" :key="opt.value" :label="opt.label" :value="opt.value" />
|
</el-select>
|
</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 v-for="opt in PRIORITY_OPTIONS" :key="opt.value" :label="opt.label" :value="opt.value" />
|
</el-select>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
<el-row :gutter="20">
|
<el-col :span="12">
|
<el-form-item label="发布日期" prop="publishDate">
|
<el-date-picker
|
v-model="form.publishDate"
|
type="date"
|
placeholder="发布日期"
|
format="YYYY-MM-DD"
|
value-format="YYYY-MM-DD"
|
style="width: 100%"
|
/>
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="过期日期">
|
<el-date-picker
|
v-model="form.expireDate"
|
type="date"
|
placeholder="可选,留空为长期有效"
|
format="YYYY-MM-DD"
|
value-format="YYYY-MM-DD"
|
style="width: 100%"
|
clearable
|
/>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
<el-form-item label="阅读范围">
|
<el-radio-group v-model="form.readScope">
|
<el-radio v-for="opt in READ_SCOPE_OPTIONS" :key="opt.value" :value="opt.value">
|
{{ opt.label }}
|
</el-radio>
|
</el-radio-group>
|
</el-form-item>
|
<el-form-item v-if="form.readScope === 'department'" label="可见部门">
|
<el-select v-model="form.targetDeptIds" multiple placeholder="选择部门" style="width: 100%">
|
<el-option v-for="d in DEPT_OPTIONS" :key="d.value" :label="d.label" :value="d.value" />
|
</el-select>
|
</el-form-item>
|
<el-form-item v-if="form.noticeType === 'emergency'" label="必读确认">
|
<el-switch v-model="form.requireReadConfirm" active-text="紧急通知需员工确认已读" />
|
</el-form-item>
|
<el-form-item label="内容" prop="contentHtml">
|
<Editor v-model="form.contentHtml" :min-height="280" placeholder="请输入内容" />
|
</el-form-item>
|
<el-form-item label="发布人">
|
<el-input v-model="form.publisherName" placeholder="如:行政部" maxlength="50" />
|
</el-form-item>
|
</el-form>
|
<template v-if="!formDialog.readonly" #footer>
|
<el-button @click="formDialog.visible = false">取 消</el-button>
|
<el-button @click="onSave(false)">存草稿</el-button>
|
<el-button type="primary" @click="onSave(true)">确 定</el-button>
|
</template>
|
</el-dialog>
|
|
<!-- 详情 -->
|
<el-dialog v-model="detailDialog.visible" title="公告详情" width="800px" append-to-body destroy-on-close>
|
<NoticeDetailPanel :row="detailRow" />
|
<template #footer>
|
<el-button @click="detailDialog.visible = false">关 闭</el-button>
|
</template>
|
</el-dialog>
|
</div>
|
</template>
|
|
<script setup>
|
import { Plus, RefreshRight } from "@element-plus/icons-vue";
|
import { ElMessage } from "element-plus";
|
import { onMounted } from "vue";
|
import Editor from "@/components/Editor/index.vue";
|
import { noticeTypeColor } from "./noticeAnnouncementUtils.js";
|
import NoticeDetailPanel from "./components/NoticeDetailPanel.vue";
|
import { useNoticeAnnouncement } from "./useNoticeAnnouncement.js";
|
|
const {
|
Search,
|
NOTICE_TYPE_OPTIONS,
|
PRIORITY_OPTIONS,
|
PUBLISH_STATUS_OPTIONS,
|
READ_SCOPE_OPTIONS,
|
DEPT_OPTIONS,
|
noticeTypeLabel,
|
searchForm,
|
tableLoading,
|
page,
|
tableData,
|
tableColumn,
|
formDialog,
|
form,
|
formRef,
|
formRules,
|
detailDialog,
|
detailRow,
|
handleQuery,
|
resetSearch,
|
pagination,
|
openFormDialog,
|
saveForm,
|
} = useNoticeAnnouncement();
|
|
function onNoticeTypeChange(type) {
|
if (type === "emergency") {
|
form.priority = "urgent";
|
form.requireReadConfirm = true;
|
}
|
}
|
|
function onSave(publish) {
|
const ret = saveForm(publish);
|
if (ret?.message) {
|
ElMessage.warning(ret.message);
|
return;
|
}
|
if (ret?.ok) {
|
ElMessage.success(publish ? "公告已发布" : "已保存草稿");
|
}
|
}
|
|
onMounted(() => {
|
handleQuery();
|
});
|
</script>
|
|
<style scoped>
|
.notice-announcement-page .search_form {
|
display: flex;
|
flex-wrap: wrap;
|
justify-content: space-between;
|
align-items: flex-start;
|
gap: 12px;
|
}
|
.search_fields {
|
display: flex;
|
flex-wrap: wrap;
|
align-items: center;
|
gap: 4px;
|
}
|
.search_actions {
|
flex-shrink: 0;
|
}
|
.notice-type-tag {
|
font-weight: 600;
|
font-size: 13px;
|
}
|
.ml10 {
|
margin-left: 10px;
|
}
|
.mb20 {
|
margin-bottom: 20px;
|
}
|
</style>
|