From 465c8711c348e2a33800a31157131ab4640a5668 Mon Sep 17 00:00:00 2001
From: spring <2396852758@qq.com>
Date: 星期五, 15 八月 2025 10:52:02 +0800
Subject: [PATCH] 行政管理
---
src/views/collaborativeApproval/notificationManagement/index.vue | 1187 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 1,187 insertions(+), 0 deletions(-)
diff --git a/src/views/collaborativeApproval/notificationManagement/index.vue b/src/views/collaborativeApproval/notificationManagement/index.vue
new file mode 100644
index 0000000..288acf1
--- /dev/null
+++ b/src/views/collaborativeApproval/notificationManagement/index.vue
@@ -0,0 +1,1187 @@
+<template>
+ <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="'holiday'" />
+ <el-option label="澶勭綒閫氱煡" :value="'penalty'" />
+ <el-option label="寮�浼氶�氱煡" :value="'meeting'" />
+ <el-option label="涓存椂閫氱煡" :value="'temporary'" />
+ <el-option label="姝e紡閫氱煡" :value="'formal'" />
+ </el-select>
+ <el-button type="primary" @click="handleQuery" style="margin-left: 10px">
+ 鎼滅储
+ </el-button>
+ </div>
+ <div>
+ <el-button type="primary" @click="openForm('add')">鏂板閫氱煡</el-button>
+ <el-button type="success" @click="openMeetingDialog">鍦ㄧ嚎浼氳</el-button>
+ <el-button type="warning" @click="openFileShareDialog">鏂囦欢鍏变韩</el-button>
+ <!-- <el-button type="info" @click="refreshEmployees">鍒锋柊鍛樺伐</el-button> -->
+ <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
+ </div>
+ </div>
+ <div class="table_list">
+ <PIMTable
+ rowKey="id"
+ :column="tableColumn"
+ :tableData="tableData"
+ :page="page"
+ :isSelection="true"
+ @selection-change="handleSelectionChange"
+ :tableLoading="tableLoading"
+ @pagination="pagination"
+ :total="page.total"
+ ></PIMTable>
+ </div>
+
+ <!-- 鏂板/缂栬緫閫氱煡寮圭獥 -->
+ <el-dialog
+ v-model="dialogVisible"
+ :title="dialogTitle"
+ width="800px"
+ :close-on-click-modal="false"
+ >
+ <el-form ref="formRef" :model="form" :rules="rules" label-width="120px">
+ <el-row :gutter="20">
+ <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 label="鏀惧亣閫氱煡" value="holiday" />
+ <el-option label="澶勭綒閫氱煡" value="penalty" />
+ <el-option label="寮�浼氶�氱煡" value="meeting" />
+ <el-option label="涓存椂閫氱煡" value="temporary" />
+ <el-option label="姝e紡閫氱煡" value="formal" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="浼樺厛绾�" prop="priority">
+ <el-select v-model="form.priority" placeholder="璇烽�夋嫨浼樺厛绾�" style="width: 100%">
+ <el-option label="鏅��" value="low" />
+ <el-option label="閲嶈" value="medium" />
+ <el-option label="绱ф��" value="high" />
+ </el-select>
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="鏈夋晥鏈熻嚦" prop="expireDate">
+ <el-date-picker
+ v-model="form.expireDate"
+ type="date"
+ placeholder="璇烽�夋嫨鏈夋晥鏈�"
+ style="width: 100%"
+ />
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-form-item label="鎺ユ敹閮ㄩ棬" prop="departments">
+ <el-select
+ v-model="form.departments"
+ multiple
+ placeholder="璇烽�夋嫨鎺ユ敹閮ㄩ棬"
+ style="width: 100%"
+ >
+ <el-option
+ v-for="dept in departments"
+ :key="dept"
+ :label="dept"
+ :value="dept"
+ />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="鍚屾鏂瑰紡" prop="syncMethods">
+ <el-checkbox-group v-model="form.syncMethods">
+ <el-checkbox
+ v-for="method in syncMethods"
+ :key="method.value"
+ :label="method.value"
+ >
+ {{ method.label }}
+ </el-checkbox>
+ </el-checkbox-group>
+ </el-form-item>
+ <el-form-item label="閫氱煡鍐呭" prop="content">
+ <el-input
+ v-model="form.content"
+ type="textarea"
+ :rows="4"
+ placeholder="璇疯緭鍏ラ�氱煡鍐呭"
+ />
+ </el-form-item>
+ </el-form>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="dialogVisible = false">鍙栨秷</el-button>
+ <el-button type="primary" @click="submitForm">纭畾</el-button>
+ </span>
+ </template>
+ </el-dialog>
+
+ <!-- 鍦ㄧ嚎浼氳寮圭獥 -->
+ <el-dialog
+ v-model="meetingDialogVisible"
+ title="鍒涘缓鍦ㄧ嚎浼氳"
+ width="700px"
+ :close-on-click-modal="false"
+ >
+ <el-form ref="meetingFormRef" :model="meetingForm" :rules="meetingRules" label-width="120px">
+ <el-form-item label="浼氳鏍囬" prop="title">
+ <el-input v-model="meetingForm.title" placeholder="璇疯緭鍏ヤ細璁爣棰�" />
+ </el-form-item>
+ <el-row :gutter="20">
+ <el-col :span="12">
+ <el-form-item label="寮�濮嬫椂闂�" prop="startTime">
+ <el-date-picker
+ v-model="meetingForm.startTime"
+ type="datetime"
+ placeholder="璇烽�夋嫨寮�濮嬫椂闂�"
+ style="width: 100%"
+ />
+ </el-form-item>
+ </el-col>
+ <el-col :span="12">
+ <el-form-item label="浼氳鏃堕暱" prop="duration">
+ <el-input-number
+ v-model="meetingForm.duration"
+ :min="15"
+ :max="480"
+ :step="15"
+ style="width: 100%"
+ />
+ <span style="margin-left: 10px">鍒嗛挓</span>
+ </el-form-item>
+ </el-col>
+ </el-row>
+ <el-form-item label="浼氳骞冲彴" prop="platform">
+ <el-select v-model="meetingForm.platform" placeholder="璇烽�夋嫨浼氳骞冲彴" style="width: 100%">
+ <el-option
+ v-for="platform in meetingPlatforms"
+ :key="platform.value"
+ :label="platform.label"
+ :value="platform.value"
+ />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="鍙備細浜哄憳" prop="participants">
+ <el-select
+ v-model="meetingForm.participants"
+ multiple
+ filterable
+ remote
+ :remote-method="filterEmployees"
+ :loading="employeesLoading"
+ placeholder="璇烽�夋嫨鍙備細浜哄憳"
+ style="width: 100%"
+ >
+ <el-option-group
+ v-for="group in employeeGroups"
+ :key="group.label"
+ :label="group.label"
+ >
+ <el-option
+ v-for="employee in group.options"
+ :key="employee.value"
+ :label="`${employee.label} (${employee.dept})`"
+ :value="employee.value"
+ >
+ <div style="display: flex; justify-content: space-between; align-items: center;">
+ <div>
+ <div style="font-weight: 500;">{{ employee.label }}</div>
+ <div style="color: #909399; font-size: 12px;">{{ employee.dept }}</div>
+ </div>
+ <div style="text-align: right; font-size: 12px; color: #909399;">
+ <div v-if="employee.phone">{{ employee.phone }}</div>
+ <div v-if="employee.email">{{ employee.email }}</div>
+ </div>
+ </div>
+ </el-option>
+ </el-option-group>
+ </el-select>
+ <div style="margin-top: 8px; color: #909399; font-size: 12px;">
+ 宸查�夋嫨 {{ meetingForm.participants.length }} 浜�
+ </div>
+ <!-- 宸查�夋嫨浜哄憳璇︽儏 -->
+ <div v-if="meetingForm.participants.length > 0" style="margin-top: 10px;">
+ <el-tag
+ v-for="participantId in meetingForm.participants"
+ :key="participantId"
+ closable
+ @close="removeParticipant(participantId)"
+ style="margin-right: 8px; margin-bottom: 8px;"
+ >
+ {{ getEmployeeName(participantId) }}
+ </el-tag>
+ </div>
+ </el-form-item>
+ <el-form-item label="浼氳鎻忚堪" prop="description">
+ <el-input
+ v-model="meetingForm.description"
+ type="textarea"
+ :rows="3"
+ placeholder="璇疯緭鍏ヤ細璁弿杩�"
+ />
+ </el-form-item>
+ </el-form>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="meetingDialogVisible = false">鍙栨秷</el-button>
+ <el-button type="primary" @click="createMeeting">鍒涘缓浼氳</el-button>
+ </span>
+ </template>
+ </el-dialog>
+
+ <!-- 鏂囦欢鍏变韩寮圭獥 -->
+ <el-dialog
+ v-model="fileShareDialogVisible"
+ title="鏂囦欢鍏变韩"
+ width="700px"
+ :close-on-click-modal="false"
+ >
+ <el-form ref="fileShareFormRef" :model="fileShareForm" :rules="fileShareRules" label-width="120px">
+ <el-form-item label="鍏变韩鏍囬" prop="title">
+ <el-input v-model="fileShareForm.title" placeholder="璇疯緭鍏ュ叡浜爣棰�" />
+ </el-form-item>
+ <el-form-item label="鍏变韩鎻忚堪" prop="description">
+ <el-input
+ v-model="fileShareForm.description"
+ type="textarea"
+ :rows="3"
+ placeholder="璇疯緭鍏ュ叡浜弿杩�"
+ />
+ </el-form-item>
+ <el-form-item label="鎺ユ敹閮ㄩ棬" prop="departments">
+ <el-select
+ v-model="fileShareForm.departments"
+ multiple
+ placeholder="璇烽�夋嫨鎺ユ敹閮ㄩ棬"
+ style="width: 100%"
+ >
+ <el-option
+ v-for="dept in departments"
+ :key="dept"
+ :label="dept"
+ :value="dept"
+ />
+ </el-select>
+ </el-form-item>
+ <el-form-item label="涓婁紶鏂囦欢" prop="files">
+ <el-upload
+ ref="uploadRef"
+ :auto-upload="false"
+ :on-change="handleFileChange"
+ :on-remove="removeFile"
+ :file-list="fileList"
+ multiple
+ :limit="10"
+ accept=".doc,.docx,.pdf,.xls,.xlsx,.ppt,.pptx,.txt,.jpg,.jpeg,.png,.gif"
+ >
+ <el-button type="primary">閫夋嫨鏂囦欢</el-button>
+ <template #tip>
+ <div class="el-upload__tip">
+ 鏀寔涓婁紶鏂囨。銆佸浘鐗囩瓑鏍煎紡锛屽崟涓枃浠朵笉瓒呰繃10MB锛屾渶澶�10涓枃浠�
+ </div>
+ </template>
+ </el-upload>
+ </el-form-item>
+ </el-form>
+ <template #footer>
+ <span class="dialog-footer">
+ <el-button @click="fileShareDialogVisible = false">鍙栨秷</el-button>
+ <el-button type="primary" @click="shareFiles">鍏变韩鏂囦欢</el-button>
+ </span>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup>
+import { Search } from "@element-plus/icons-vue";
+import { onMounted, ref, reactive, toRefs, computed } from "vue";
+import { ElMessage, ElMessageBox } from "element-plus";
+import PIMTable from "@/components/PIMTable/PIMTable.vue";
+import { userListNoPageByTenantId } from "@/api/system/user.js";
+import { staffOnJobListPage } from "@/api/personnelManagement/employeeRecord.js";
+
+// 琛ㄥ崟楠岃瘉瑙勫垯
+const rules = {
+ title: [
+ { required: true, message: "璇疯緭鍏ラ�氱煡鏍囬", trigger: "blur" }
+ ],
+ type: [
+ { required: true, message: "璇烽�夋嫨閫氱煡绫诲瀷", trigger: "change" }
+ ],
+ content: [
+ { required: true, message: "璇疯緭鍏ラ�氱煡鍐呭", trigger: "blur" }
+ ]
+};
+
+const meetingRules = {
+ title: [
+ { required: true, message: "璇疯緭鍏ヤ細璁爣棰�", trigger: "blur" }
+ ],
+ startTime: [
+ { required: true, message: "璇烽�夋嫨浼氳寮�濮嬫椂闂�", trigger: "change" }
+ ],
+ participants: [
+ { required: true, message: "璇烽�夋嫨鍙備細浜哄憳", trigger: "change" }
+ ]
+};
+
+const fileShareRules = {
+ title: [
+ { required: true, message: "璇疯緭鍏ュ叡浜爣棰�", trigger: "blur" }
+ ],
+ description: [
+ { required: true, message: "璇疯緭鍏ュ叡浜弿杩�", trigger: "blur" }
+ ]
+};
+
+// 鍝嶅簲寮忔暟鎹�
+const data = reactive({
+ searchForm: {
+ title: "",
+ type: "",
+ status: "",
+ },
+ tableLoading: false,
+ page: {
+ current: 1,
+ size: 100,
+ total: 0,
+ },
+ tableData: [],
+ selectedIds: [],
+ // 鏂板閫氱煡鐩稿叧
+ form: {
+ title: "",
+ type: "",
+ priority: "medium",
+ content: "",
+ departments: [],
+ expireDate: "",
+ syncMethods: []
+ },
+ dialogVisible: false,
+ dialogTitle: "",
+ dialogType: "add",
+ // 鍦ㄧ嚎浼氳鐩稿叧
+ meetingDialogVisible: false,
+ meetingForm: {
+ title: "",
+ startTime: "",
+ duration: 60,
+ participants: [],
+ description: "",
+ platform: "wechat"
+ },
+ // 鏂囦欢鍏变韩鐩稿叧
+ fileShareDialogVisible: false,
+ fileShareForm: {
+ title: "",
+ description: "",
+ departments: [],
+ files: []
+ },
+ fileList: []
+});
+
+const {
+ searchForm,
+ tableLoading,
+ page,
+ tableData,
+ selectedIds,
+ form,
+ dialogVisible,
+ dialogTitle,
+ dialogType,
+ meetingDialogVisible,
+ meetingForm,
+ fileShareDialogVisible,
+ fileShareForm,
+ fileList
+} = toRefs(data);
+
+// 琛ㄥ崟寮曠敤
+const formRef = ref();
+const meetingFormRef = ref();
+const fileShareFormRef = ref();
+
+// 琛ㄦ牸鍒楅厤缃�
+const tableColumn = ref([
+ {
+ label: "閫氱煡鏍囬",
+ prop: "title",
+ showOverflowTooltip: true,
+ },
+ {
+ label: "閫氱煡绫诲瀷",
+ prop: "type",
+ dataType: "tag",
+ formatData: (params) => {
+ const typeMap = {
+ holiday: "鏀惧亣閫氱煡",
+ penalty: "澶勭綒閫氱煡",
+ meeting: "寮�浼氶�氱煡",
+ temporary: "涓存椂閫氱煡",
+ formal: "姝e紡閫氱煡"
+ };
+ return typeMap[params] || params;
+ },
+ formatType: (params) => {
+ const typeMap = {
+ holiday: "success",
+ penalty: "danger",
+ meeting: "warning",
+ temporary: "info",
+ formal: "primary"
+ };
+ return typeMap[params] || "info";
+ }
+ },
+ {
+ label: "浼樺厛绾�",
+ prop: "priority",
+ dataType: "tag",
+ formatData: (params) => {
+ const priorityMap = {
+ low: "鏅��",
+ medium: "閲嶈",
+ high: "绱ф��"
+ };
+ return priorityMap[params] || params;
+ },
+ formatType: (params) => {
+ const typeMap = {
+ low: "info",
+ medium: "warning",
+ high: "danger"
+ };
+ return typeMap[params] || "info";
+ }
+ },
+ {
+ label: "鐘舵��",
+ prop: "status",
+ dataType: "tag",
+ formatData: (params) => {
+ const statusMap = {
+ draft: "鑽夌",
+ published: "宸插彂甯�",
+ expired: "宸茶繃鏈�"
+ };
+ return statusMap[params] || params;
+ },
+ formatType: (params) => {
+ const typeMap = {
+ draft: "info",
+ published: "success",
+ expired: "danger"
+ };
+ return typeMap[params] || "info";
+ }
+ },
+ {
+ label: "鎺ユ敹閮ㄩ棬",
+ prop: "departments",
+ width: 150,
+ showOverflowTooltip: true,
+ formatData: (params) => {
+ if (!params || params.length === 0) return "鍏ㄩ儴閮ㄩ棬";
+ return params.join(", ");
+ }
+ },
+ {
+ label: "鏈夋晥鏈熻嚦",
+ prop: "expireDate",
+ width: 150,
+ formatData: (params) => {
+ if (!params) return "姘镐箙鏈夋晥";
+ return params;
+ }
+ },
+ {
+ label: "鍒涘缓鏃堕棿",
+ prop: "createTime",
+ width: 180,
+ },
+ {
+ dataType: "action",
+ label: "鎿嶄綔",
+ align: "center",
+ fixed: "right",
+ width: 280,
+ operation: [
+ {
+ name: "缂栬緫",
+ type: "text",
+ clickFun: (row) => {
+ openForm("edit", row);
+ }
+ },
+ {
+ name: "鍙戝竷",
+ type: "text",
+ clickFun: (row) => {
+ publishNotification(row);
+ },
+ // disabled: (row) => row.status === "published"
+ },
+ {
+ name: "鎾ゅ洖",
+ type: "text",
+ clickFun: (row) => {
+ revokeNotification(row);
+ },
+ // disabled: (row) => row.status !== "published"
+ }
+ ]
+ }
+]);
+
+// 妯℃嫙鏁版嵁
+let mockData = [
+ {
+ id: "1",
+ title: "2024骞存槬鑺傛斁鍋囬�氱煡",
+ type: "holiday",
+ priority: "high",
+ status: "published",
+ content: "鏍规嵁鍥藉瑙勫畾锛岀粨鍚堝叕鍙稿疄闄呮儏鍐碉紝鐜板皢2024骞存槬鑺傛斁鍋囧畨鎺掗�氱煡濡備笅...",
+ departments: ["鎶�鏈儴", "閿�鍞儴", "浜轰簨閮�", "璐㈠姟閮�", "杩愯惀閮�", "甯傚満閮�", "瀹㈡湇閮�"],
+ expireDate: "2024-02-15",
+ syncMethods: ["wechat", "dingtalk", "email"],
+ createTime: "2024-01-15 10:30:00"
+ },
+ {
+ id: "2",
+ title: "鎶�鏈儴鍛ㄤ緥浼氶�氱煡",
+ type: "meeting",
+ priority: "medium",
+ status: "published",
+ content: "鎶�鏈儴瀹氫簬姣忓懆浜斾笅鍗�2鐐瑰彫寮�鍛ㄤ緥浼氾紝璇峰悇浣嶅悓浜嬪噯鏃跺弬鍔�...",
+ departments: ["鎶�鏈儴"],
+ expireDate: "2024-01-20",
+ syncMethods: ["wechat", "dingtalk"],
+ createTime: "2024-01-14 15:20:00"
+ },
+ {
+ id: "3",
+ title: "鍛樺伐琛屼负瑙勮寖澶勭綒閫氱煡",
+ type: "penalty",
+ priority: "high",
+ status: "draft",
+ content: "涓虹淮鎶ゅ叕鍙告甯哥З搴忥紝瑙勮寖鍛樺伐琛屼负锛岀幇瀵硅繚鍙嶅叕鍙歌瀹氱殑琛屼负杩涜澶勭綒...",
+ departments: ["浜轰簨閮�", "鎶�鏈儴", "閿�鍞儴"],
+ expireDate: "2024-02-13",
+ syncMethods: ["wechat", "email"],
+ createTime: "2024-01-13 09:15:00"
+ }
+];
+
+// 閫氱煡鏍囬妯℃澘
+const titleTemplates = [
+ "鍏充簬{year}骞磠holiday}鏀惧亣瀹夋帓鐨勯�氱煡",
+ "{dept}閮ㄩ棬{meeting}浼氳閫氱煡",
+ "鍛樺伐{behavior}琛屼负瑙勮寖鎻愰啋",
+ "{company}閲嶈浜嬮」閫氱煡",
+ "{dept}閮ㄩ棬宸ヤ綔瀹夋帓閫氱煡",
+ "鍏充簬{project}椤圭洰杩涘害鐨勯�氱煡",
+ "{dept}閮ㄩ棬浜哄憳璋冩暣閫氱煡",
+ "鍏徃{policy}鏀跨瓥鏇存柊閫氱煡"
+];
+
+// 閫氱煡绫诲瀷閰嶇疆
+const notificationTypes = [
+ { type: "holiday", label: "鏀惧亣閫氱煡", priority: "high" },
+ { type: "meeting", label: "寮�浼氶�氱煡", priority: "medium" },
+ { type: "penalty", label: "澶勭綒閫氱煡", priority: "high" },
+ { type: "temporary", label: "涓存椂閫氱煡", priority: "low" },
+ { type: "formal", label: "姝e紡閫氱煡", priority: "medium" }
+];
+
+// 閮ㄩ棬鍒楄〃
+const departments = ["鎶�鏈儴", "閿�鍞儴", "浜轰簨閮�", "璐㈠姟閮�", "杩愯惀閮�", "甯傚満閮�", "瀹㈡湇閮�"];
+
+// 浜哄憳鍒楄〃
+const employees = ref([]);
+const employeesLoading = ref(false);
+
+// 鑾峰彇鍦ㄨ亴鍛樺伐鍒楄〃
+const getEmployeesList = async () => {
+ try {
+ employeesLoading.value = true;
+ // 浼樺厛浣跨敤绯荤粺鐢ㄦ埛鎺ュ彛锛堟寜绉熸埛鑾峰彇锛�
+ const userResponse = await userListNoPageByTenantId();
+
+ if (userResponse.data) {
+ employees.value = userResponse.data.map(user => ({
+ label: user.nickName || user.userName || '鏈煡濮撳悕',
+ value: user.userId || user.id,
+ dept: user.dept?.deptName || '鏈煡閮ㄩ棬',
+ phone: user.phonenumber || '',
+ email: user.email || '',
+ status: user.status || '0'
+ })).filter(user => user.status === '0'); // 鍙樉绀烘甯哥姸鎬佺殑鐢ㄦ埛
+ } else {
+ // 濡傛灉绯荤粺鐢ㄦ埛鎺ュ彛澶辫触锛屼娇鐢ㄥ憳宸ュ彴璐︽帴鍙�
+ const response = await staffOnJobListPage({
+ pageNum: 1,
+ pageSize: 1000,
+ staffState: 1 // 鍦ㄨ亴鐘舵��
+ });
+
+ if (response.data && response.data.records) {
+ employees.value = response.data.records.map(employee => ({
+ label: employee.staffName || employee.name || '鏈煡濮撳悕',
+ value: employee.staffNo || employee.id || employee.staffId,
+ dept: employee.deptName || employee.department || '鏈煡閮ㄩ棬',
+ phone: employee.phone || employee.mobile || '',
+ email: employee.email || '',
+ status: '0'
+ }));
+ }
+ }
+ } catch (error) {
+ console.error('鑾峰彇鍛樺伐鍒楄〃澶辫触:', error);
+ // 濡傛灉鎺ュ彛閮藉け璐ワ紝浣跨敤榛樿鏁版嵁
+ employees.value = [
+ { label: "寮犱笁", value: "001", dept: "鎶�鏈儴", phone: "13800138001", email: "zhangsan@company.com", status: "0" },
+ { label: "鏉庡洓", value: "002", dept: "閿�鍞儴", phone: "13800138002", email: "lisi@company.com", status: "0" },
+ { label: "鐜嬩簲", value: "003", dept: "浜轰簨閮�", phone: "13800138003", email: "wangwu@company.com", status: "0" }
+ ];
+ } finally {
+ employeesLoading.value = false;
+ }
+};
+
+// 鍛樺伐鍒嗙粍
+const employeeGroups = computed(() => {
+ const groups = {};
+ employees.value.forEach(employee => {
+ const dept = employee.dept || '鍏朵粬閮ㄩ棬';
+ if (!groups[dept]) {
+ groups[dept] = [];
+ }
+ groups[dept].push(employee);
+ });
+
+ // 鎸夐儴闂ㄥ悕绉版帓搴忥紝纭繚鏄剧ず椤哄簭涓�鑷�
+ return Object.keys(groups)
+ .sort()
+ .map(dept => ({
+ label: dept,
+ options: groups[dept].sort((a, b) => a.label.localeCompare(b.label, 'zh-CN'))
+ }));
+});
+
+// 杩囨护鍛樺伐锛堣繙绋嬫悳绱級
+const filterEmployees = (query) => {
+ if (query !== '') {
+ const lowerQuery = query.toLowerCase();
+ return employees.value.filter(employee =>
+ employee.label.toLowerCase().includes(lowerQuery) ||
+ employee.dept.toLowerCase().includes(lowerQuery) ||
+ (employee.phone && employee.phone.includes(query)) ||
+ (employee.email && employee.email.toLowerCase().includes(lowerQuery))
+ );
+ } else {
+ return employees.value;
+ }
+};
+
+// 鍒锋柊鍛樺伐鍒楄〃
+const refreshEmployees = async () => {
+ ElMessage.info("姝e湪鍒锋柊鍛樺伐鍒楄〃...");
+ await getEmployeesList();
+
+ // 缁熻鍚勯儴闂ㄤ汉鏁�
+ const deptStats = {};
+ employees.value.forEach(emp => {
+ const dept = emp.dept || '鍏朵粬閮ㄩ棬';
+ deptStats[dept] = (deptStats[dept] || 0) + 1;
+ });
+
+ const deptInfo = Object.entries(deptStats)
+ .map(([dept, count]) => `${dept}: ${count}浜篳)
+ .join(', ');
+
+ ElMessage.success(`鍛樺伐鍒楄〃鍒锋柊瀹屾垚锛屽叡 ${employees.value.length} 浜� (${deptInfo})`);
+};
+
+// 鑾峰彇鍛樺伐濮撳悕
+const getEmployeeName = (employeeId) => {
+ const employee = employees.value.find(emp => emp.value === employeeId);
+ return employee ? employee.label : '鏈煡浜哄憳';
+};
+
+// 鑾峰彇鍛樺伐璇︾粏淇℃伅
+const getEmployeeInfo = (employeeId) => {
+ const employee = employees.value.find(emp => emp.value === employeeId);
+ if (!employee) return null;
+
+ return {
+ name: employee.label,
+ dept: employee.dept,
+ phone: employee.phone,
+ email: employee.email
+ };
+};
+
+// 绉婚櫎鍙備細浜哄憳
+const removeParticipant = (participantId) => {
+ const index = meetingForm.value.participants.indexOf(participantId);
+ if (index > -1) {
+ meetingForm.value.participants.splice(index, 1);
+ }
+};
+
+// 鍚屾鏂瑰紡閫夐」
+const syncMethods = [
+ { label: "浼佷笟寰俊", value: "wechat" },
+ { label: "閽夐拤", value: "dingtalk" },
+ { label: "閭欢", value: "email" },
+ { label: "鐭俊", value: "sms" }
+];
+
+// 浼氳骞冲彴閫夐」
+const meetingPlatforms = [
+ { label: "浼佷笟寰俊浼氳", value: "wechat" },
+ { label: "閽夐拤浼氳", value: "dingtalk" },
+ { label: "鑵捐浼氳", value: "tencent" },
+ { label: "Zoom", value: "zoom" }
+];
+
+// 鑷姩鐢熸垚鏂版暟鎹�
+const generateNewData = () => {
+ const newId = (mockData.length + 1).toString();
+ const now = new Date();
+ const randomType = notificationTypes[Math.floor(Math.random() * notificationTypes.length)];
+ const randomDept = departments[Math.floor(Math.random() * departments.length)];
+
+ // 鐢熸垚闅忔満鏍囬
+ let title = titleTemplates[Math.floor(Math.random() * titleTemplates.length)];
+ title = title
+ .replace('{year}', now.getFullYear())
+ .replace('{holiday}', ['鏄ヨ妭', '鍥藉簡', '涓', '鍏冩棪'][Math.floor(Math.random() * 4)])
+ .replace('{dept}', randomDept)
+ .replace('{meeting}', ['鍛ㄤ緥浼�', '鏈堝害鎬荤粨', '椤圭洰璇勫', '鍩硅浼氳'][Math.floor(Math.random() * 4)])
+ .replace('{behavior}', ['鑰冨嫟', '鐫�瑁�', '宸ヤ綔鎬佸害', '鍥㈤槦鍗忎綔'][Math.floor(Math.random() * 4)])
+ .replace('{company}', ['鍏徃', '闆嗗洟', '鎬婚儴'][Math.floor(Math.random() * 4)])
+ .replace('{project}', ['鏁板瓧鍖栬浆鍨�', '浜у搧鍗囩骇', '甯傚満鎷撳睍', '浜烘墠鍩瑰吇'][Math.floor(Math.random() * 4)])
+ .replace('{policy}', ['鑰冨嫟', '钖叕', '绂忓埄', '鏅嬪崌'][Math.floor(Math.random() * 4)]);
+
+ // 闅忔満鐘舵��
+ const statuses = ['draft', 'published'];
+ const randomStatus = statuses[Math.floor(Math.random() * statuses.length)];
+
+ // 闅忔満浼樺厛绾�
+ const priorities = ['low', 'medium', 'high'];
+ const randomPriority = priorities[Math.floor(Math.random() * priorities.length)];
+
+ const newNotification = {
+ id: newId,
+ title: title,
+ type: randomType.type,
+ priority: randomPriority,
+ status: randomStatus,
+ content: `杩欐槸${title}鐨勮缁嗗唴瀹癸紝璇风浉鍏充汉鍛樻敞鎰忔煡鐪�...`,
+ departments: [randomDept],
+ expireDate: new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000).toISOString().split('T')[0], // 30澶╁悗杩囨湡
+ syncMethods: ["wechat", "dingtalk"],
+ createTime: now.toLocaleString()
+ };
+
+ // 娣诲姞鍒版暟鎹紑澶�
+ mockData.unshift(newNotification);
+
+ // 淇濇寔鏁版嵁閲忓湪鍚堢悊鑼冨洿鍐咃紙鏈�澶氫繚鐣�20鏉★級
+ if (mockData.length > 20) {
+ mockData = mockData.slice(0, 20);
+ }
+
+ console.log(`[${new Date().toLocaleString()}] 鑷姩鐢熸垚鏂伴�氱煡: ${title}`);
+};
+
+// 鐢熷懡鍛ㄦ湡
+onMounted(() => {
+ getList();
+ getEmployeesList(); // 鑾峰彇鍛樺伐鍒楄〃
+ startAutoRefresh();
+});
+
+// 寮�濮嬭嚜鍔ㄥ埛鏂�
+const startAutoRefresh = () => {
+ setInterval(() => {
+ generateNewData();
+ getList();
+ }, 600000); // 10鍒嗛挓鍒锋柊涓�娆� (10 * 60 * 1000 = 600000ms)
+};
+
+// 鏌ヨ鏁版嵁
+const handleQuery = () => {
+ page.value.current = 1;
+ getList();
+};
+
+const getList = () => {
+ tableLoading.value = true;
+
+ setTimeout(() => {
+ let filteredData = [...mockData];
+
+ if (searchForm.value.title) {
+ filteredData = filteredData.filter(item =>
+ item.title.toLowerCase().includes(searchForm.value.title.toLowerCase())
+ );
+ }
+
+ if (searchForm.value.type) {
+ filteredData = filteredData.filter(item => item.type === searchForm.value.type);
+ }
+
+ tableData.value = filteredData;
+ page.value.total = filteredData.length;
+ tableLoading.value = false;
+ }, 500);
+};
+
+// 鍒嗛〉澶勭悊
+const pagination = (obj) => {
+ page.value.current = obj.page;
+ page.value.size = obj.limit;
+ handleQuery();
+};
+
+// 閫夋嫨鍙樺寲澶勭悊
+const handleSelectionChange = (selection) => {
+ selectedIds.value = selection.map(item => item.id);
+};
+
+// 鎵撳紑琛ㄥ崟
+const openForm = (type, row = null) => {
+ dialogType.value = type;
+ if (type === "add") {
+ dialogTitle.value = "鏂板閫氱煡";
+ // 閲嶇疆琛ㄥ崟
+ Object.assign(form.value, {
+ title: "",
+ type: "",
+ priority: "medium",
+ content: "",
+ departments: [],
+ expireDate: "",
+ syncMethods: []
+ });
+ } else if (type === "edit" && row) {
+ dialogTitle.value = "缂栬緫閫氱煡";
+ Object.assign(form.value, {
+ title: row.title,
+ type: row.type,
+ priority: row.priority,
+ content: row.content || "",
+ departments: row.departments || [],
+ expireDate: row.expireDate || "",
+ syncMethods: row.syncMethods || []
+ });
+ }
+ dialogVisible.value = true;
+};
+
+// 鎵撳紑鍦ㄧ嚎浼氳寮圭獥
+const openMeetingDialog = () => {
+ // 閲嶇疆琛ㄥ崟
+ Object.assign(meetingForm.value, {
+ title: "",
+ startTime: "",
+ duration: 60,
+ participants: [],
+ description: "",
+ platform: "wechat"
+ });
+ meetingDialogVisible.value = true;
+};
+
+// 鎵撳紑鏂囦欢鍏变韩寮圭獥
+const openFileShareDialog = () => {
+ // 閲嶇疆琛ㄥ崟
+ Object.assign(fileShareForm.value, {
+ title: "",
+ description: "",
+ departments: [],
+ files: []
+ });
+ fileList.value = [];
+ fileShareDialogVisible.value = true;
+};
+
+// 鎵嬪姩鍒锋柊鏁版嵁
+const manualRefresh = () => {
+ generateNewData();
+ getList();
+ ElMessage.success("鎵嬪姩鍒锋柊瀹屾垚锛屽凡鐢熸垚鏂伴�氱煡");
+};
+
+// 鎻愪氦閫氱煡琛ㄥ崟
+const submitForm = async () => {
+ try {
+ await formRef.value.validate();
+
+ if (dialogType.value === "add") {
+ // 鏂板閫氱煡
+ const newNotification = {
+ id: (mockData.length + 1).toString(),
+ title: form.value.title,
+ type: form.value.type,
+ priority: form.value.priority,
+ status: "draft",
+ content: form.value.content,
+ departments: form.value.departments,
+ expireDate: form.value.expireDate,
+ syncMethods: form.value.syncMethods,
+ createTime: new Date().toLocaleString()
+ };
+
+ mockData.unshift(newNotification);
+ ElMessage.success("閫氱煡鍒涘缓鎴愬姛");
+ } else {
+ // 缂栬緫閫氱煡
+ const index = mockData.findIndex(item => item.id === selectedIds.value[0]);
+ if (index !== -1) {
+ Object.assign(mockData[index], {
+ title: form.value.title,
+ type: form.value.type,
+ priority: form.value.priority,
+ content: form.value.content,
+ departments: form.value.departments,
+ expireDate: form.value.expireDate,
+ syncMethods: form.value.syncMethods
+ });
+ ElMessage.success("閫氱煡鏇存柊鎴愬姛");
+ }
+ }
+
+ dialogVisible.value = false;
+ getList();
+ } catch (error) {
+ console.error("琛ㄥ崟楠岃瘉澶辫触:", error);
+ }
+};
+
+// 鍒涘缓浼氳
+const createMeeting = async () => {
+ try {
+ await meetingFormRef.value.validate();
+
+ // 妯℃嫙鍒涘缓浼氳
+ const meetingInfo = {
+ title: meetingForm.value.title,
+ startTime: meetingForm.value.startTime,
+ duration: meetingForm.value.duration,
+ participants: meetingForm.value.participants,
+ description: meetingForm.value.description,
+ platform: meetingForm.value.platform,
+ meetingId: `MTG${Date.now()}`
+ };
+
+ // 妯℃嫙鍙戦�佸埌浼佷笟寰俊/閽夐拤
+ const platformName = meetingPlatforms.find(p => p.value === meetingForm.value.platform)?.label || "鏈煡骞冲彴";
+
+ ElMessage.success(`浼氳鍒涘缓鎴愬姛锛佷細璁甀D: ${meetingInfo.meetingId}锛屽皢閫氳繃${platformName}鍙戦�侀�氱煡`);
+ meetingDialogVisible.value = false;
+
+ // 鑾峰彇鍙備細浜哄憳淇℃伅
+ const participantNames = meetingForm.value.participants.map(participantId => {
+ const employee = employees.value.find(emp => emp.value === participantId);
+ return employee ? employee.label : '鏈煡浜哄憳';
+ }).join('銆�');
+
+ // 鑾峰彇鍙備細浜哄憳璇︾粏淇℃伅
+ const participantDetails = meetingForm.value.participants.map(participantId => {
+ const employee = employees.value.find(emp => emp.value === participantId);
+ return employee ? {
+ name: employee.label,
+ dept: employee.dept,
+ phone: employee.phone,
+ email: employee.email
+ } : null;
+ }).filter(Boolean);
+
+ // 灏嗕細璁俊鎭坊鍔犲埌閫氱煡鍒楄〃
+ const meetingNotification = {
+ id: (mockData.length + 1).toString(),
+ title: `[浼氳閫氱煡] ${meetingInfo.title}`,
+ type: "meeting",
+ priority: "high",
+ status: "published",
+ content: `浼氳鏃堕棿: ${meetingInfo.startTime}锛屾椂闀�: ${meetingInfo.duration}鍒嗛挓锛屽钩鍙�: ${meetingPlatforms.find(p => p.value === meetingForm.value.platform)?.label || "鏈煡骞冲彴"}锛屽弬浼氫汉鍛�: ${participantNames}锛屽叡${participantDetails.length}浜篳,
+ departments: [],
+ expireDate: "",
+ syncMethods: [meetingForm.value.platform],
+ createTime: new Date().toLocaleString()
+ };
+
+ mockData.unshift(meetingNotification);
+ getList();
+ } catch (error) {
+ console.error("浼氳琛ㄥ崟楠岃瘉澶辫触:", error);
+ }
+};
+
+// 鏂囦欢涓婁紶澶勭悊
+const handleFileChange = (file) => {
+ const isLt10M = file.size / 1024 / 1024 < 10;
+ if (!isLt10M) {
+ ElMessage.error("涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃 10MB!");
+ return false;
+ }
+
+ const fileInfo = {
+ name: file.name,
+ size: file.size,
+ type: file.type,
+ uid: file.uid
+ };
+
+ fileList.value.push(fileInfo);
+ fileShareForm.value.files.push(fileInfo);
+ return false; // 闃绘鑷姩涓婁紶
+};
+
+// 绉婚櫎鏂囦欢
+const removeFile = (file) => {
+ const index = fileList.value.findIndex(item => item.uid === file.uid);
+ if (index !== -1) {
+ const index2 = fileShareForm.value.files.findIndex(item => item.uid === file.uid);
+ if (index2 !== -1) {
+ fileShareForm.value.files.splice(index2, 1);
+ }
+ fileList.value.splice(index, 1);
+ }
+};
+
+// 鍏变韩鏂囦欢
+const shareFiles = async () => {
+ try {
+ await fileShareFormRef.value.validate();
+
+ if (fileShareForm.value.files.length === 0) {
+ ElMessage.warning("璇疯嚦灏戦�夋嫨涓�涓枃浠�");
+ return;
+ }
+
+ // 妯℃嫙鏂囦欢鍏变韩
+ const shareInfo = {
+ title: fileShareForm.value.title,
+ description: fileShareForm.value.description,
+ departments: fileShareForm.value.departments,
+ files: fileShareForm.value.files,
+ shareId: `FILE${Date.now()}`
+ };
+
+ ElMessage.success(`鏂囦欢鍏变韩鎴愬姛锛佸叡浜獻D: ${shareInfo.shareId}锛屽凡閫氱煡鐩稿叧閮ㄩ棬`);
+ fileShareDialogVisible.value = false;
+
+ // 灏嗘枃浠跺叡浜俊鎭坊鍔犲埌閫氱煡鍒楄〃
+ const fileShareNotification = {
+ id: (mockData.length + 1).toString(),
+ title: `[鏂囦欢鍏变韩] ${shareInfo.title}`,
+ type: "temporary",
+ priority: "medium",
+ status: "published",
+ content: `鍏变韩鎻忚堪: ${shareInfo.description}锛屾枃浠舵暟閲�: ${shareInfo.files.length}涓猔,
+ departments: shareInfo.departments,
+ expireDate: "",
+ syncMethods: ["wechat", "dingtalk"],
+ createTime: new Date().toLocaleString()
+ };
+
+ mockData.unshift(fileShareNotification);
+ getList();
+ } catch (error) {
+ console.error("鏂囦欢鍏变韩琛ㄥ崟楠岃瘉澶辫触:", error);
+ }
+};
+
+// 鍙戝竷閫氱煡
+const publishNotification = (row) => {
+ row.status = "published";
+ ElMessage.success("閫氱煡鍙戝竷鎴愬姛");
+ getList();
+};
+
+// 鎾ゅ洖閫氱煡
+const revokeNotification = (row) => {
+ row.status = "draft";
+ ElMessage.success("閫氱煡宸叉挙鍥�");
+ getList();
+};
+
+// 鍒犻櫎閫氱煡
+const handleDelete = () => {
+ if (selectedIds.value.length === 0) {
+ ElMessage.warning("璇烽�夋嫨瑕佸垹闄ょ殑閫氱煡");
+ return;
+ }
+
+ ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎", {
+ confirmButtonText: "纭",
+ cancelButtonText: "鍙栨秷",
+ type: "warning",
+ }).then(() => {
+ ElMessage.success("鍒犻櫎鎴愬姛");
+ selectedIds.value = [];
+ getList();
+ }).catch(() => {
+ // 鐢ㄦ埛鍙栨秷
+ });
+};
+</script>
+
+<style scoped>
+.auto-refresh-info {
+ margin-bottom: 15px;
+}
+
+.auto-refresh-info .el-alert {
+ border-radius: 8px;
+}
+
+.dialog-footer {
+ text-align: right;
+}
+
+.el-upload__tip {
+ color: #909399;
+ font-size: 12px;
+ margin-top: 8px;
+}
+
+.el-checkbox-group {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 10px;
+}
+
+.el-checkbox {
+ margin-right: 0;
+}
+</style>
--
Gitblit v1.9.3