From 42a1a434f77154746038c476ef70ca9be0b8e4e0 Mon Sep 17 00:00:00 2001
From: spring <2396852758@qq.com>
Date: 星期一, 19 一月 2026 18:02:46 +0800
Subject: [PATCH] fix: 完成资金管理,财务对账

---
 src/views/collaborativeApproval/planTemplate/index.vue |  867 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 867 insertions(+), 0 deletions(-)

diff --git a/src/views/collaborativeApproval/planTemplate/index.vue b/src/views/collaborativeApproval/planTemplate/index.vue
new file mode 100644
index 0000000..0af6d8b
--- /dev/null
+++ b/src/views/collaborativeApproval/planTemplate/index.vue
@@ -0,0 +1,867 @@
+<template>
+  <div class="app-container">
+    <!-- 椤堕儴鎿嶄綔鏍� -->
+    <div class="header-actions">
+      <div class="left-actions">
+        <el-select v-model="currentLevel" placeholder="閫夋嫨璁″垝绾у埆" style="width: 150px" @change="handleLevelChange">
+          <el-option label="涓汉璁″垝" value="personal" />
+          <el-option label="灏忕粍璁″垝" value="group" />
+          <el-option label="閮ㄩ棬璁″垝" value="department" />
+          <el-option label="鍏徃璁″垝" value="company" />
+        </el-select>
+        <el-select v-model="currentPeriod" placeholder="閫夋嫨鏃堕棿鍛ㄦ湡" style="width: 120px; margin-left: 10px" @change="handlePeriodChange">
+          <el-option label="鍛ㄨ鍒�" value="week" />
+          <el-option label="鏈堣鍒�" value="month" />
+          <el-option label="骞磋鍒�" value="year" />
+        </el-select>
+        <el-date-picker
+          v-model="currentDate"
+          :type="datePickerType"
+          placeholder="閫夋嫨鏃ユ湡"
+          format="YYYY-MM-DD"
+          value-format="YYYY-MM-DD"
+          style="width: 180px; margin-left: 10px"
+          @change="handleDateChange"
+        />
+      </div>
+      <div class="right-actions">
+        <el-button type="primary" @click="handleAddPlan">鏂板璁″垝</el-button>
+        <el-button @click="handleExport">瀵煎嚭璁″垝</el-button>
+        <!-- <el-button @click="handleShare">鍏变韩璁″垝@</el-button> -->
+      </div>
+    </div>
+
+    <!-- 璁″垝姒傝鍗$墖 -->
+    <div class="overview-cards">
+      <el-row :gutter="20">
+        <el-col :span="6">
+          <el-card class="overview-card">
+            <div class="card-content">
+              <div class="card-icon personal">
+                <el-icon><User /></el-icon>
+              </div>
+              <div class="card-info">
+                <div class="card-title">涓汉璁″垝</div>
+                <div class="card-number">{{ overviewData.personal.total }}</div>
+                <div class="card-progress">
+                  <el-progress :percentage="overviewData.personal.completion" :stroke-width="6" />
+                </div>
+              </div>
+            </div>
+          </el-card>
+        </el-col>
+        <el-col :span="6">
+          <el-card class="overview-card">
+            <div class="card-content">
+              <div class="card-icon group">
+                <el-icon><UserFilled /></el-icon>
+              </div>
+              <div class="card-info">
+                <div class="card-title">灏忕粍璁″垝</div>
+                <div class="card-number">{{ overviewData.group.total }}</div>
+                <div class="card-progress">
+                  <el-progress :percentage="overviewData.group.completion" :stroke-width="6" />
+                </div>
+              </div>
+            </div>
+          </el-card>
+        </el-col>
+        <el-col :span="6">
+          <el-card class="overview-card">
+            <div class="card-content">
+              <div class="card-icon department">
+                <el-icon><OfficeBuilding /></el-icon>
+              </div>
+              <div class="card-info">
+                <div class="card-title">閮ㄩ棬璁″垝</div>
+                <div class="card-number">{{ overviewData.department.total }}</div>
+                <div class="card-progress">
+                  <el-progress :percentage="overviewData.department.completion" :stroke-width="6" />
+                </div>
+              </div>
+            </div>
+          </el-card>
+        </el-col>
+        <el-col :span="6">
+          <el-card class="overview-card">
+            <div class="card-content">
+              <div class="card-icon company">
+                <el-icon><House /></el-icon>
+              </div>
+              <div class="card-info">
+                <div class="card-title">鍏徃璁″垝</div>
+                <div class="card-number">{{ overviewData.company.total }}</div>
+                <div class="card-progress">
+                  <el-progress :percentage="overviewData.company.completion" :stroke-width="6" />
+                </div>
+              </div>
+            </div>
+          </el-card>
+        </el-col>
+      </el-row>
+    </div>
+
+    <!-- 璁″垝鍒楄〃 -->
+    <div class="plan-content">
+      <el-card>
+        <template #header>
+          <div class="card-header">
+            <span>{{ getCurrentLevelText() }} - {{ getCurrentPeriodText() }}</span>
+            <div>
+              <el-button size="small" @click="handleRefresh">鍒锋柊</el-button>
+              <!-- <el-button size="small" @click="handleFilter">绛涢�堾</el-button> -->
+            </div>
+          </div>
+        </template>
+        
+        <div class="plan-list">
+          <div v-for="plan in planList" :key="plan.id" class="plan-item">
+            <div class="plan-header">
+              <div class="plan-title">
+                <el-tag :type="getPriorityType(plan.priority)" size="small">{{ getPriorityText(plan.priority) }}</el-tag>
+                <span class="title-text">{{ plan.title }}</span>
+              </div>
+              <div class="plan-actions">
+                <el-button size="small" @click="handleEditPlan(plan)">缂栬緫</el-button>
+                <el-button size="small" @click="handleViewDetail(plan)">璇︽儏</el-button>
+                <el-dropdown @command="(command) => handleMoreAction(plan, command)">
+                  <el-button size="small">
+                    鏇村<el-icon class="el-icon--right"><ArrowDown /></el-icon>
+                  </el-button>
+                  <template #dropdown>
+                    <el-dropdown-menu>
+                      <!-- <el-dropdown-item command="share">鍏变韩@</el-dropdown-item> -->
+                      <el-dropdown-item command="copy">澶嶅埗</el-dropdown-item>
+                      <el-dropdown-item command="delete" divided>鍒犻櫎</el-dropdown-item>
+                    </el-dropdown-menu>
+                  </template>
+                </el-dropdown>
+              </div>
+            </div>
+            
+            <div class="plan-content">
+              <div class="plan-description">{{ plan.description }}</div>
+              <div class="plan-meta">
+                <div class="meta-item">
+                  <el-icon><Calendar /></el-icon>
+                  <span>{{ plan.startDate }} - {{ plan.endDate }}</span>
+                </div>
+                <div class="meta-item">
+                  <el-icon><User /></el-icon>
+                  <span>{{ plan.assignee }}</span>
+                </div>
+                <div class="meta-item">
+                  <el-icon><Clock /></el-icon>
+                  <span>杩涘害: {{ plan.progress }}%</span>
+                </div>
+                <div class="meta-item">
+                  <el-icon><Flag /></el-icon>
+                  <span>{{ getStatusText(plan.status) }}</span>
+                </div>
+              </div>
+              
+              <div class="plan-progress">
+                <el-progress 
+                  :percentage="plan.progress" 
+                  :color="getProgressColor(plan.progress)"
+                  :stroke-width="8"
+                />
+              </div>
+              
+              <div class="plan-tags">
+                <el-tag v-for="tag in plan.tags" :key="tag" size="small" style="margin-right: 5px">
+                  {{ tag }}
+                </el-tag>
+              </div>
+            </div>
+          </div>
+        </div>
+      </el-card>
+    </div>
+
+    <!-- 鏂板/缂栬緫璁″垝瀵硅瘽妗� -->
+    <el-dialog
+      v-model="planDialogVisible"
+      :title="operationType === 'add' ? '鍙戝竷璁″垝' : '缂栬緫璁″垝'"
+      width="600px"
+      @close="handleDialogClose"
+    >
+      <el-form :model="planForm" :rules="planRules" ref="planFormRef" label-width="100px">
+        <el-form-item label="璁″垝鏍囬" prop="title">
+          <el-input v-model="planForm.title" placeholder="璇疯緭鍏ヨ鍒掓爣棰�" />
+        </el-form-item>
+        <el-form-item label="璁″垝鎻忚堪" prop="description">
+          <el-input
+            v-model="planForm.description"
+            type="textarea"
+            :rows="3"
+            placeholder="璇疯緭鍏ヨ鍒掓弿杩�"
+          />
+        </el-form-item>
+        <el-form-item label="璁″垝绾у埆" prop="level">
+          <el-select v-model="planForm.level" placeholder="閫夋嫨璁″垝绾у埆" style="width: 100%">
+            <el-option label="涓汉璁″垝" value="personal" />
+            <el-option label="灏忕粍璁″垝" value="group" />
+            <el-option label="閮ㄩ棬璁″垝" value="department" />
+            <el-option label="鍏徃璁″垝" value="company" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="鏃堕棿鍛ㄦ湡" prop="period">
+          <el-select v-model="planForm.period" placeholder="閫夋嫨鏃堕棿鍛ㄦ湡" style="width: 100%">
+            <el-option label="鍛ㄨ鍒�" value="week" />
+            <el-option label="鏈堣鍒�" value="month" />
+            <el-option label="骞磋鍒�" value="year" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="寮�濮嬫椂闂�" prop="startDate">
+          <el-date-picker
+            v-model="planForm.startDate"
+            type="date"
+            value-format="YYYY-MM-DD"
+            format="YYYY-MM-DD"
+            placeholder="閫夋嫨寮�濮嬫椂闂�"
+            style="width: 100%"
+          />
+        </el-form-item>
+        <el-form-item label="缁撴潫鏃堕棿" prop="endDate">
+          <el-date-picker
+            v-model="planForm.endDate"
+            type="date"
+            value-format="YYYY-MM-DD"
+            format="YYYY-MM-DD"
+            placeholder="閫夋嫨缁撴潫鏃堕棿"
+            style="width: 100%"
+          />
+        </el-form-item>
+        <el-form-item label="璐熻矗浜�" prop="assignee">
+          <el-input v-model="planForm.assignee" placeholder="璇疯緭鍏ヨ礋璐d汉" />
+        </el-form-item>
+        <el-form-item label="浼樺厛绾�" prop="priority">
+          <el-select v-model="planForm.priority" placeholder="閫夋嫨浼樺厛绾�" style="width: 100%">
+            <el-option label="楂�" value="high" />
+            <el-option label="涓�" value="medium" />
+            <el-option label="浣�" value="low" />
+          </el-select>
+        </el-form-item>
+        <!-- <el-form-item label="鏍囩">
+          <el-input v-model="planForm.tags" placeholder="璇疯緭鍏ユ爣绛撅紝鐢ㄩ�楀彿鍒嗛殧" />
+        </el-form-item> -->
+        <el-form-item label="鏍囩" prop="tags">
+          <!-- <el-checkbox-group v-model="planForm.tags">
+            <el-checkbox label="all"></el-checkbox>
+            <el-checkbox label="manager">绠$悊灞�</el-checkbox>
+            <el-checkbox label="hr">浜轰簨閮ㄩ棬</el-checkbox>
+            <el-checkbox label="finance">璐㈠姟閮ㄩ棬</el-checkbox>
+            <el-checkbox label="tech">鎶�鏈儴闂�</el-checkbox>
+          </el-checkbox-group> -->
+          <el-select
+            v-model="planForm.tags"
+            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="status">
+          <el-select v-model="planForm.status" placeholder="閫夋嫨鐘舵��" style="width: 100%">
+            <el-option label="鏈紑濮�" value="not_started" />
+            <el-option label="杩涜涓�" value="in_progress" />
+            <el-option label="宸插畬鎴�" value="completed" />
+            <el-option label="宸叉殏鍋�" value="paused" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="杩涘害" prop="progress">
+          <el-input-number
+            v-model="planForm.progress"
+            min="0"
+            max="100"
+            step="1"
+            placeholder="璇疯緭鍏ヨ繘搴�"
+            style="width: 100%"
+          />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="planDialogVisible = false">鍙栨秷</el-button>
+          <el-button type="primary" @click="handleSavePlan">淇濆瓨</el-button>
+        </span>
+      </template>
+    </el-dialog>
+    <!-- 璁″垝璇︽儏瀵硅瘽妗� -->
+    <el-dialog v-model="showPlanDetailDialog" title="璁″垝璇︽儏" width="700px">
+      <div v-if="currentPlanDetail" class="mb10">
+        <el-descriptions :column="2" border>
+          <el-descriptions-item label="璁″垝鏍囬">{{ currentPlanDetail.title }}</el-descriptions-item>
+          <el-descriptions-item label="璁″垝鎻忚堪">{{ currentPlanDetail.description }}</el-descriptions-item>
+          <el-descriptions-item label="璁″垝绾у埆">{{ getCurrentLevelText(currentPlanDetail.level) }}</el-descriptions-item>
+          <el-descriptions-item label="鏃堕棿鍛ㄦ湡">{{ getCurrentPeriodText(currentPlanDetail.period) }}</el-descriptions-item>
+          <el-descriptions-item label="寮�濮嬫椂闂�">{{ currentPlanDetail.startDate }}</el-descriptions-item>
+          <el-descriptions-item label="缁撴潫鏃堕棿">{{ currentPlanDetail.endDate }}</el-descriptions-item>
+          <el-descriptions-item label="璐熻矗浜�">{{ currentPlanDetail.assignee }}</el-descriptions-item>
+          <el-descriptions-item label="浼樺厛绾�">{{ getPriorityText(currentPlanDetail.priority) }}</el-descriptions-item>
+          <el-descriptions-item label="鏍囩">{{ currentPlanDetail.tags.join(', ') }}</el-descriptions-item>
+          <el-descriptions-item label="鐘舵��">{{ getStatusText(currentPlanDetail.status) }}</el-descriptions-item>
+          <el-descriptions-item label="杩涘害">{{ currentPlanDetail.progress }}%</el-descriptions-item>
+        </el-descriptions>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, computed, onMounted } from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+const { proxy } = getCurrentInstance();
+import {
+  User,
+  UserFilled,
+  OfficeBuilding,
+  House,
+  Calendar,
+  Clock,
+  Flag,
+  ArrowDown
+} from '@element-plus/icons-vue'
+import { listDutyPlan, addDutyPlan, updateDutyPlan, delDutyPlan,NumDutyPlan,exportDutyPlan } from '@/api/collaborativeApproval/planTemplate.js'
+
+// 鍝嶅簲寮忔暟鎹�
+const operationType = ref('add')
+const currentLevel = ref('personal')
+const currentPeriod = ref('week')
+const currentDate = ref(new Date())
+const planDialogVisible = ref(false)
+const dialogTitle = ref('鏂板璁″垝')
+const planFormRef = ref()
+const showPlanDetailDialog = ref(false)
+const currentPlanDetail = ref(null)
+
+// 琛ㄥ崟鏁版嵁
+const planForm = reactive({
+  id: '',
+  title: '',
+  description: '',
+  level: 'personal',
+  period: 'week',
+  startDate: '',
+  endDate: '',
+  assignee: '',
+  priority: 'medium',
+  tags: [],
+  status: '',
+  progress: 0
+})
+
+// 琛ㄥ崟楠岃瘉瑙勫垯
+const planRules = {
+  title: [{ required: true, message: '璇疯緭鍏ヨ鍒掓爣棰�', trigger: 'blur' }],
+  description: [{ required: true, message: '璇疯緭鍏ヨ鍒掓弿杩�', trigger: 'blur' }],
+  level: [{ required: true, message: '璇烽�夋嫨璁″垝绾у埆', trigger: 'change' }],
+  period: [{ required: true, message: '璇烽�夋嫨鏃堕棿鍛ㄦ湡', trigger: 'change' }],
+  startDate: [{ required: true, message: '璇烽�夋嫨寮�濮嬫椂闂�', trigger: 'change' }],
+  endDate: [{ required: true, message: '璇烽�夋嫨缁撴潫鏃堕棿', trigger: 'change' }],
+  assignee: [{ required: true, message: '璇疯緭鍏ヨ礋璐d汉', trigger: 'blur' }],
+  priority: [{ required: true, message: '璇烽�夋嫨浼樺厛绾�', trigger: 'change' }]
+}
+const departments = ["浜у搧", "鍒嗘瀽", "璋冪爺",'鎶�鏈�', '鏋舵瀯', '璁捐','甯傚満', '鎺ㄥ箍', '钀ラ攢'];
+// 姒傝鏁版嵁
+const overviewData = reactive({
+  personal: { total: 0, completion: 0 },
+  group: { total: 0, completion: 0 },
+  department: { total: 0, completion: 0 },
+  company: { total: 0, completion: 0 }
+})
+
+// 璁″垝鍒楄〃鏁版嵁
+const planList = ref([])
+
+// 璁$畻灞炴��
+const datePickerType = computed(() => {
+  switch (currentPeriod.value) {
+    case 'week':
+      return 'week'
+    case 'month':
+      return 'month'
+    case 'year':
+      return 'year'
+    default:
+      return 'date'
+  }
+})
+
+// 鏂规硶
+const handleLevelChange = (value) => {
+  console.log('璁″垝绾у埆鍙樻洿:', value)
+  getPlanList()
+  // 杩欓噷鍙互鏍规嵁绾у埆绛涢�夋暟鎹�
+}
+
+const handlePeriodChange = (value) => {
+  console.log('鏃堕棿鍛ㄦ湡鍙樻洿:', value)
+  getPlanList()
+  // 杩欓噷鍙互鏍规嵁鍛ㄦ湡绛涢�夋暟鎹�
+}
+
+const handleDateChange = (value) => {
+  console.log('鏃ユ湡鍙樻洿:', value)
+  getPlanList()
+  // 杩欓噷鍙互鏍规嵁鏃ユ湡绛涢�夋暟鎹�
+}
+
+const handleAddPlan = () => {
+  operationType.value = 'add'
+  dialogTitle.value = '鏂板璁″垝'
+  planDialogVisible.value = true
+  // 閲嶇疆琛ㄥ崟
+  Object.keys(planForm).forEach(key => {
+    planForm[key] = ''
+  })
+  planForm.level = 'personal'
+  planForm.period = 'week'
+  planForm.priority = 'medium'
+  planForm.status = 'not_started'
+  planForm.progress = 0
+}
+
+const handleEditPlan = (plan) => {
+  operationType.value = 'edit'
+  dialogTitle.value = '缂栬緫璁″垝'
+  planDialogVisible.value = true
+  Object.assign(planForm, plan)
+  // // 濉厖琛ㄥ崟鏁版嵁
+  // Object.keys(planForm).forEach(key => {
+  //   if (key === 'tags') {
+  //     planForm[key] = plan[key].join(', ')
+  //   } else {
+  //     planForm[key] = plan[key]
+  //   }
+  // })
+}
+
+const handleViewDetail = (plan) => {
+  currentPlanDetail.value = plan
+  showPlanDetailDialog.value = true
+  // ElMessage.info(`鏌ョ湅璁″垝璇︽儏: ${plan.title}`)
+}
+
+const handleMoreAction = async(plan,command) => {
+  let ids = [];
+  ids.push(plan.id);
+  console.log("ids",ids)
+  switch (command) {
+    case 'share':
+      ElMessage.success('璁″垝宸插叡浜�')
+      break
+    case 'copy':
+      const knowledgeText = `
+        璁″垝鏍囬锛�${plan.title}
+        璁″垝鎻忚堪锛�${plan.description}
+        璁″垝绾у埆锛�${getCurrentLevelText(plan.level)}
+        鏃堕棿鍛ㄦ湡锛�${getCurrentPeriodText(plan.period)}
+        寮�濮嬫椂闂达細${plan.startDate}
+        缁撴潫鏃堕棿锛�${plan.endDate}
+        璐熻矗浜猴細${plan.assignee}
+        浼樺厛绾э細${getPriorityText(plan.priority)}
+        鏍囩锛�${plan.tags.join(', ')}
+        鐘舵�侊細${getStatusText(plan.status)}
+        杩涘害锛�${plan.progress}%
+      `.trim();
+
+        // 澶嶅埗鍒板壀璐存澘
+        navigator.clipboard.writeText(knowledgeText).then(() => {
+          ElMessage.success("鐭ヨ瘑鍐呭宸插鍒跺埌鍓创鏉�");
+        }).catch(() => {
+          ElMessage.error("澶嶅埗澶辫触锛岃鎵嬪姩澶嶅埗");
+        });
+      // ElMessage.success('璁″垝宸插鍒�')
+      break
+    case 'delete':
+      ElMessageBox.confirm('纭畾瑕佸垹闄よ繖涓鍒掑悧锛�', '鎻愮ず', {
+        confirmButtonText: '纭畾',
+        cancelButtonText: '鍙栨秷',
+        type: 'warning'
+      }).then(() => {
+
+        delDutyPlan(ids).then(res => {
+          if (res.code === 200) {
+            ElMessage.success('璁″垝宸插垹闄�')
+            ids.value = [];
+            getPlanList()
+          }
+        })
+      })
+      break
+  }
+}
+//
+const handleSavePlan = async () => {
+  try {
+    await planFormRef.value.validate()
+    if (operationType.value === 'add') {
+      addDutyPlan(planForm).then(res => {
+        if (res.code === 200) {
+          ElMessage.success('璁″垝淇濆瓨鎴愬姛')
+          planDialogVisible.value = false
+        }
+        getPlanList()
+      })
+    } else {
+
+      updateDutyPlan(planForm).then(res => {
+        if (res.code === 200) {
+          ElMessage.success('璁″垝淇濆瓨鎴愬姛')
+          planDialogVisible.value = false
+        }
+        getPlanList()
+      })
+    }
+  } catch (error) {
+    console.log('琛ㄥ崟楠岃瘉澶辫触:', error)
+  }
+}
+
+const handleDialogClose = () => {
+  planFormRef.value?.resetFields()
+}
+
+const handleRefresh = () => {
+  getPlanList()
+  // ElMessage.success('鏁版嵁宸插埛鏂�')
+}
+
+const handleFilter = () => {
+  ElMessage.info('鎵撳紑绛涢�夐潰鏉�')
+}
+
+const handleExport = () => {
+  ElMessageBox.confirm("鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+    confirmButtonText: "纭",
+    cancelButtonText: "鍙栨秷",
+    type: "warning",
+  })
+    .then(() => {
+      // exportDutyPlan().then(res => {
+        
+      // })
+      proxy.download("/dutyPlan/export", {}, "璁″垝绠$悊.xlsx");
+    })
+    .catch(() => {
+      proxy.$modal.msg("宸插彇娑�");
+    });
+};
+const handleShare = () => {
+  ElMessage.success('璁″垝宸插叡浜�')
+}
+
+const getCurrentLevelText = () => {
+  const levelMap = {
+    personal: '涓汉璁″垝',
+    group: '灏忕粍璁″垝',
+    department: '閮ㄩ棬璁″垝',
+    company: '鍏徃璁″垝'
+  }
+  return levelMap[currentLevel.value] || '涓汉璁″垝'
+}
+
+const getCurrentPeriodText = () => {
+  const periodMap = {
+    week: '鍛ㄨ鍒�',
+    month: '鏈堣鍒�',
+    year: '骞磋鍒�'
+  }
+  return periodMap[currentPeriod.value] || '鍛ㄨ鍒�'
+}
+
+const getPriorityType = (priority) => {
+  const typeMap = {
+    high: 'danger',
+    medium: 'warning',
+    low: 'info'
+  }
+  return typeMap[priority] || 'info'
+}
+
+const getPriorityText = (priority) => {
+  const textMap = {
+    high: '楂�',
+    medium: '涓�',
+    low: '浣�'
+  }
+  return textMap[priority] || '涓�'
+}
+
+const getStatusText = (status) => {
+  const statusMap = {
+    not_started: '鏈紑濮�',
+    in_progress: '杩涜涓�',
+    completed: '宸插畬鎴�',
+    paused: '宸叉殏鍋�'
+  }
+  return statusMap[status] || '鏈煡'
+}
+
+const getProgressColor = (progress) => {
+  if (progress >= 80) return '#67C23A'
+  if (progress >= 50) return '#E6A23C'
+  return '#F56C6C'
+}
+//鑾峰彇鏁版嵁鍒楄〃
+const getPlanList = async () => {
+  const params = {
+    level: currentLevel.value,
+    period: currentPeriod.value,
+    queryDate:currentDate.value
+  }
+  listDutyPlan(params).then(res => {
+    if (res.code === 200) {
+      planList.value = res.data.records
+    }
+  }).catch(err => {
+    console.log(err)
+  })
+}
+//鑾峰彇鏁版嵁
+const getPlanNum = async () => {
+  NumDutyPlan().then(res => {
+    if (res.code === 200) {
+      // console.log(res.data)
+      //璁茬粨鏋滈噷闈㈢殑鏁版嵁鏍规嵁level 璧嬪�肩粰overviewData
+      res.data.forEach(item => {
+        overviewData[item.level].total = item.num
+        overviewData[item.level].completion = item.completion
+      })
+      
+    }
+  }).catch(err => {
+    console.log(err)
+  })
+}
+
+onMounted(() => {
+  getPlanList()
+  getPlanNum()
+  console.log('澶氱骇璁″垝妯℃澘椤甸潰宸插姞杞�')
+})
+</script>
+
+<style scoped>
+.app-container {
+  padding: 20px;
+  background-color: #f5f5f5;
+  min-height: 100vh;
+}
+
+.header-actions {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 20px;
+  background: white;
+  padding: 20px;
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+.left-actions {
+  display: flex;
+  align-items: center;
+}
+
+.right-actions {
+  display: flex;
+  gap: 10px;
+}
+
+.overview-cards {
+  margin-bottom: 20px;
+}
+
+.overview-card {
+  height: 120px;
+}
+
+.card-content {
+  display: flex;
+  align-items: center;
+  height: 100%;
+}
+
+.card-icon {
+  width: 60px;
+  height: 60px;
+  border-radius: 50%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  margin-right: 15px;
+  font-size: 24px;
+  color: white;
+}
+
+.card-icon.personal {
+  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+}
+
+.card-icon.group {
+  background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
+}
+
+.card-icon.department {
+  background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
+}
+
+.card-icon.company {
+  background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);
+}
+
+.card-info {
+  flex: 1;
+}
+
+.card-title {
+  font-size: 14px;
+  color: #666;
+  margin-bottom: 5px;
+}
+
+.card-number {
+  font-size: 24px;
+  font-weight: bold;
+  color: #333;
+  margin-bottom: 10px;
+}
+
+.card-progress {
+  width: 100%;
+}
+
+.plan-content {
+  background: white;
+  border-radius: 8px;
+  overflow: hidden;
+}
+
+.card-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  font-weight: bold;
+  color: #333;
+}
+
+.header-actions {
+  display: flex;
+  gap: 10px;
+}
+
+.plan-list {
+  padding: 20px 0;
+}
+
+.plan-item {
+  border: 1px solid #e4e7ed;
+  border-radius: 8px;
+  margin-bottom: 15px;
+  padding: 20px;
+  transition: all 0.3s ease;
+}
+
+.plan-item:hover {
+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+  transform: translateY(-2px);
+}
+
+.plan-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 15px;
+}
+
+.plan-title {
+  display: flex;
+  align-items: center;
+  gap: 10px;
+}
+
+.title-text {
+  font-size: 16px;
+  font-weight: bold;
+  color: #333;
+}
+
+.plan-actions {
+  display: flex;
+  gap: 10px;
+}
+
+.plan-content {
+  margin-bottom: 15px;
+}
+
+.plan-description {
+  color: #666;
+  margin-bottom: 15px;
+  line-height: 1.6;
+}
+
+.plan-meta {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 20px;
+  margin-bottom: 15px;
+}
+
+.meta-item {
+  display: flex;
+  align-items: center;
+  gap: 5px;
+  color: #666;
+  font-size: 14px;
+}
+
+.plan-progress {
+  margin-bottom: 15px;
+}
+
+.plan-tags {
+  display: flex;
+  flex-wrap: wrap;
+  gap: 5px;
+}
+
+.dialog-footer {
+  display: flex;
+  justify-content: flex-end;
+  gap: 10px;
+}
+
+/* 鍝嶅簲寮忚璁� */
+@media (max-width: 768px) {
+  .header-actions {
+    flex-direction: column;
+    gap: 15px;
+  }
+  
+  .left-actions {
+    flex-wrap: wrap;
+    gap: 10px;
+  }
+  
+  .plan-meta {
+    flex-direction: column;
+    gap: 10px;
+  }
+  
+  .plan-header {
+    flex-direction: column;
+    align-items: flex-start;
+    gap: 10px;
+  }
+}
+</style>

--
Gitblit v1.9.3