From 457cc6cf166d3b6c22be4f78c1db8802a7fbb4c7 Mon Sep 17 00:00:00 2001 From: wujingjing <gersonwu@qq.com> Date: 星期一, 07 四月 2025 17:53:19 +0800 Subject: [PATCH] DigitalHuman --- src/views/project/ch/workspace/situation/index.vue | 495 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 485 insertions(+), 10 deletions(-) diff --git a/src/views/project/ch/workspace/situation/index.vue b/src/views/project/ch/workspace/situation/index.vue index c7b6c7a..daf9ca0 100644 --- a/src/views/project/ch/workspace/situation/index.vue +++ b/src/views/project/ch/workspace/situation/index.vue @@ -1,16 +1,491 @@ <template> - <div class="workspace-situation"> - <div class="workspace-situation-header"> - <div class="workspace-situation-header-title"> - <span>涓汉宸ヤ綔鍙版鍐�</span> - </div> - </div> - </div> + <div class="workspace-container h-full"> + <!-- 宸︿晶涓昏鍐呭鍖� --> + <div class="flex flex-col h-full overflow-hidden" :style="{ gap: layoutGap }"> + <!-- 宸ヤ綔姒傝 --> + <div class="overview-section flex-0 bg-white border border-solid border-white rounded-lg p-[20px] h-[150px]"> + <div class="section-header mb-4"> + <h3 class="font-bold">宸ヤ綔姒傝</h3> + </div> + <div class="overview-cards"> + <!-- 绠$悊浜烘暟 --> + <div class="overview-card bg-[#dee8ff] rounded-lg p-4 flex items-center"> + <i class="i-carbon:user-multiple text-3xl text-blue-500 mr-4"></i> + <div> + <div class="text-3xl font-bold text-[#4f85f6]">3</div> + <div class="text-gray-600">绠$悊浜烘暟</div> + </div> + </div> + <!-- 寰呭姙浜嬮」 --> + <div class="overview-card bg-[#faeaed] rounded-lg p-4 flex items-center"> + <i class="i-carbon:task text-3xl text-red-500 mr-4"></i> + <div> + <div class="text-3xl font-bold text-red-500">3</div> + <div class="text-gray-600">寰呭姙浜嬮」</div> + </div> + </div> + <!-- 棰勮浜嬮」 --> + <div class="overview-card bg-[#dbf2f8] rounded-lg p-4 flex items-center"> + <i class="i-carbon:warning text-3xl text-cyan-500 mr-4"></i> + <div> + <div class="text-3xl font-bold text-cyan-500">3</div> + <div class="text-gray-600">棰勮浜嬮」</div> + </div> + </div> + </div> + </div> + + <div class="flex flex-col flex-auto" :style="{ gap: layoutGap }"> + <!-- 寰呭姙浜嬮」鍜屾垜鍙戣捣鐨勮〃鏍� --> + <div class="flex h-1/2" :style="{ gap: layoutGap }"> + <!-- 寰呭姙浜嬮」 --> + <div class="bg-white rounded-lg p-4 shadow-sm flex flex-col w-1/2"> + <div class="flex justify-between items-center mb-4 flex-0"> + <div class="text-lg font-bold">寰呭姙浜嬮」</div> + <el-tabs v-model="todoType" class="todo-tabs"> + <el-tab-pane label="寰呭姙浜嬮」" name="todo" /> + <el-tab-pane label="宸插姙浜嬮」" name="done" /> + </el-tabs> + </div> + <el-table class="flex-auto" :data="todoList" style="width: 100%" size="small"> + <el-table-column prop="name" label="浜嬩欢绫诲瀷" min-width="120"> + <template #default="{ row }"> + <span :class="getEventTypeClass(row.type)">{{ row.name }}</span> + </template> + </el-table-column> + <el-table-column prop="sender" label="鍙戣捣浜�" width="100" /> + <el-table-column prop="time" label="鍙戣捣鏃堕棿" width="100" /> + <el-table-column prop="status" label="鐘舵��" width="80"> + <template #default="{ row }"> + <el-tag :type="getStatusType(row.status)" size="small"> + {{ row.status }} + </el-tag> + </template> + </el-table-column> + <el-table-column label="鎿嶄綔" width="80" fixed="right"> + <template #default> + <el-button type="primary" size="small" class="custom-button">鍔炵悊</el-button> + </template> + </el-table-column> + </el-table> + </div> + + <!-- 鎴戝彂璧风殑 --> + <div class="bg-white rounded-lg p-4 shadow-sm flex flex-col h-full w-1/2"> + <div class="flex justify-between items-center mb-4 flex-0"> + <div class="text-lg font-bold">鎴戝彂璧风殑</div> + <el-tabs v-model="initiatedType" class="todo-tabs"> + <el-tab-pane label="鎴戝彂璧�" name="initiated" /> + <el-tab-pane label="鎴戞敹鍒�" name="received" /> + </el-tabs> + </div> + + <el-table :data="initiatedList" class="flex-auto" style="width: 100%" size="small"> + <el-table-column prop="type" label="绫诲瀷" min-width="120"> + <template #default="{ row }"> + <span :class="getEventTypeClass(row.type)">{{ row.type }}</span> + </template> + </el-table-column> + <el-table-column prop="sender" label="鍙戣捣浜�" width="100" /> + <el-table-column prop="time" label="鍙戣捣鏃堕棿" width="100" /> + <el-table-column prop="status" label="鐘舵��" width="80"> + <template #default="{ row }"> + <el-tag :type="getStatusType(row.status)" size="small"> + {{ row.status }} + </el-tag> + </template> + </el-table-column> + <el-table-column label="鎿嶄綔" width="80" fixed="right"> + <template #default> + <el-button type="primary" size="small" class="custom-button">璇︽儏</el-button> + </template> + </el-table-column> + </el-table> + </div> + </div> + + <!-- 棰勮琛ㄦ牸 --> + <div class="bg-white rounded-lg p-4 shadow-sm h-1/2"> + <div class="text-lg font-bold mb-4">棰勮</div> + <el-table :data="warningList" style="width: 100%" size="small"> + <el-table-column prop="studentId" label="瀛﹀彿" min-width="120" /> + <el-table-column prop="name" label="濮撳悕" width="100" /> + <el-table-column prop="type" label="瀛︾敓绫诲瀷" width="100" /> + <el-table-column prop="guardianId" label="鎶ょ収鍙�" min-width="150" /> + <el-table-column prop="warningType" label="棰勮绫诲瀷" width="120"> + <template #default="{ row }"> + <el-tag :type="getWarningType(row.warningType)" size="small"> + {{ row.warningType }} + </el-tag> + </template> + </el-table-column> + <el-table-column label="鎿嶄綔" width="100" fixed="right"> + <template #default> + <el-button type="primary" size="small" class="custom-button">鎻愪氦棰勮</el-button> + </template> + </el-table-column> + </el-table> + </div> + </div> + </div> + <!-- 鍙充晶杈规爮 --> + <div class="sidebar h-full overflow-hidden flex flex-col" :style="{ gap: layoutGap }"> + <!-- 涓汉淇℃伅 --> + <div class="profile-card p-[20px] bg-white border border-solid border-white rounded-lg h-[150px] flex-0"> + <div class="section-header mb-4"> + <h3>涓汉淇℃伅</h3> + </div> + <div class="profile-header flex gap-4"> + <!-- <div class="avatar-placeholder"> + <i class="i-carbon:user text-3xl text-gray-400"></i> + </div> --> + <div class="profile-info flex flex-col gap-2"> + <div class="flex items-center" v-for="item in 3" :key="item"> + <span class="mr-1">鐢ㄦ埛鍚嶏細</span> + <span>wjj</span> + </div> + </div> + <div class="profile-info flex flex-col gap-2"> + <div class="flex items-center" v-for="item in 3" :key="item"> + <span class="mr-1">鐢ㄦ埛鍚嶏細</span> + <span>wjj</span> + </div> + </div> + </div> + </div> + + <!-- 缁熻鍥捐〃 --> + <div class="chart-container p-[20px] h-1/2 overflow-hidden"> + <div class="chart-header"> + <h3>缁熻鍥捐〃</h3> + <span class="subtitle">鍥藉埆</span> + </div> + <div class="chart" ref="chartRef"></div> + </div> + + <!-- 鏃ュ巻 --> + <div class="calendar-container p-[20px] h-1/2 overflow-hidden"> + <div class="calendar-header"> + <h3>鏃堕棿</h3> + <div class="flex items-center gap-2"> + <el-date-picker v-model="currentMonth" type="month" format="YYYY骞碝M鏈�" :placeholder="'閫夋嫨鏈堜唤'" size="small" /> + </div> + </div> + <div class="calendar-notice mb-0.5">鎮ㄤ粖鏃ユ棤寰呭姙</div> + <el-calendar v-model="currentDate"> + <template #dateCell="{ data }"> + <div class="custom-calendar-cell"> + <span class="date-text">{{ data.day.split('-')[2] }}</span> + <div v-if="hasEvent(data)" class="event-dot"></div> + </div> + </template> + </el-calendar> + </div> + </div> + </div> </template> -<script setup lang="ts" name="WorkspaceSituation"> -import { ref } from 'vue'; +<script setup lang="ts"> +import * as echarts from 'echarts'; +import { computed, onMounted, ref } from 'vue'; +const layoutGap = '10px'; +interface CalendarData { + day: string; + [key: string]: any; +} +// 鐘舵�佸彉閲� +const todoType = ref('todo'); +const initiatedType = ref('initiated'); +const currentDate = ref(new Date('2025-04-06')); +const currentMonth = computed(() => { + const date = currentDate.value; + return date instanceof Date ? date : new Date(date); +}); +const chartRef = ref<HTMLElement>(); + +// 绀轰緥鏁版嵁 - 澧炲姞鏇村鏁版嵁 +const todoList = ref([ + { name: '瀹為獙瀹ゆ洿鏂�', type: 'update', sender: '鐜嬬編涓�', time: '2021.12.06', status: '寰呯‘璁�' }, + { name: '鏂扮敓鎸囧', type: 'guide', sender: '鏉庢槑', time: '2021.12.06', status: '鏈' }, + { name: '娲诲姩鎶ュ悕', type: 'activity', sender: '寮犱笁', time: '2021.12.06', status: '宸茶' }, + { name: '璇剧▼鍙樻洿', type: 'update', sender: '鏉庡洓', time: '2021.12.06', status: '寰呯‘璁�' }, + { name: '浼氳閫氱煡', type: 'notice', sender: '鐜嬩簲', time: '2021.12.06', status: '鏈' }, + { name: '鏁欐潗璁㈣喘', type: 'order', sender: '璧靛叚', time: '2021.12.06', status: '宸插鐞�' }, + { name: '鎴愮哗褰曞叆', type: 'grade', sender: '瀛欎竷', time: '2021.12.06', status: '寰呯‘璁�' }, + { name: '璇峰亣瀹℃壒', type: 'leave', sender: '鍛ㄥ叓', time: '2021.12.06', status: '宸茶' }, + { name: '璇峰亣瀹℃壒', type: 'leave', sender: '鍛ㄥ叓', time: '2021.12.06', status: '宸茶' }, + { name: '璇峰亣瀹℃壒', type: 'leave', sender: '鍛ㄥ叓', time: '2021.12.06', status: '宸茶' }, + { name: '璇峰亣瀹℃壒', type: 'leave', sender: '鍛ㄥ叓', time: '2021.12.06', status: '宸茶' }, + { name: '璇峰亣瀹℃壒', type: 'leave', sender: '鍛ㄥ叓', time: '2021.12.06', status: '宸茶' }, +]); + +const initiatedList = ref([ + { type: '娲诲姩', sender: '鐜嬬編涓�', time: '2021.12.06', status: '杩涜涓�' }, + { type: '鎶ュ埌娉ㄥ唽', sender: '鏉庢槑', time: '2021.12.06', status: '鍏抽棴' }, + { type: '璇剧▼鍙樻洿', sender: '寮犱笁', time: '2021.12.06', status: '寰呭鏍�' }, + { type: '浼氳閫氱煡', sender: '鏉庡洓', time: '2021.12.06', status: '宸插畬鎴�' }, + { type: '鏁欐潗璁㈣喘', sender: '鐜嬩簲', time: '2021.12.06', status: '杩涜涓�' }, + { type: '鎴愮哗褰曞叆', sender: '璧靛叚', time: '2021.12.06', status: '寰呭鏍�' }, + { type: '璇峰亣瀹℃壒', sender: '瀛欎竷', time: '2021.12.06', status: '宸叉嫆缁�' }, + { type: '娲诲姩绛栧垝', sender: '鍛ㄥ叓', time: '2021.12.06', status: '杩涜涓�' }, + { type: '娲诲姩绛栧垝', sender: '鍛ㄥ叓', time: '2021.12.06', status: '杩涜涓�' }, + { type: '娲诲姩绛栧垝', sender: '鍛ㄥ叓', time: '2021.12.06', status: '杩涜涓�' }, + { type: '娲诲姩绛栧垝', sender: '鍛ㄥ叓', time: '2021.12.06', status: '杩涜涓�' }, + { type: '娲诲姩绛栧垝', sender: '鍛ㄥ叓', time: '2021.12.06', status: '杩涜涓�' }, + { type: '娲诲姩绛栧垝', sender: '鍛ㄥ叓', time: '2021.12.06', status: '杩涜涓�' }, + { type: '娲诲姩绛栧垝', sender: '鍛ㄥ叓', time: '2021.12.06', status: '杩涜涓�' }, + { type: '娲诲姩绛栧垝', sender: '鍛ㄥ叓', time: '2021.12.06', status: '杩涜涓�' }, +]); + +const warningList = ref([ + { studentId: 'N20930498594', name: '鐜嬬編涓�', type: '楂樹腑', guardianId: '309209382903943', warningType: '杩熷埌棰勮' }, + { studentId: 'N20930498595', name: '鏉庢槑', type: '楂樹腑', guardianId: '309209382903944', warningType: '缂哄嫟棰勮' }, + { studentId: 'N20930498596', name: '寮犱笁', type: '鍒濅腑', guardianId: '309209382903945', warningType: '鎴愮哗棰勮' }, + { studentId: 'N20930498597', name: '鏉庡洓', type: '楂樹腑', guardianId: '309209382903946', warningType: '琛屼负棰勮' }, + { studentId: 'N20930498598', name: '鐜嬩簲', type: '鍒濅腑', guardianId: '309209382903947', warningType: '杩熷埌棰勮' }, +]); + +// 宸ュ叿鍑芥暟 +const getEventTypeClass = (type: string) => { + const classes = { + update: 'text-green-500', + guide: 'text-blue-500', + activity: 'text-orange-500', + notice: 'text-purple-500', + order: 'text-cyan-500', + grade: 'text-pink-500', + leave: 'text-indigo-500', + }; + return classes[type] || ''; +}; + +const getStatusType = (status: string) => { + const types = { + 寰呯‘璁�: 'warning', + 鏈: 'danger', + 宸茶: 'info', + 宸插鐞�: 'success', + 杩涜涓�: 'primary', + 鍏抽棴: 'info', + 寰呭鏍�: 'warning', + 宸插畬鎴�: 'success', + 宸叉嫆缁�: 'danger', + }; + return types[status] || 'default'; +}; + +const getWarningType = (type: string) => { + const types = { + 杩熷埌棰勮: 'danger', + 缂哄嫟棰勮: 'warning', + 鎴愮哗棰勮: 'info', + 琛屼负棰勮: 'warning', + }; + return types[type] || 'default'; +}; + +const hasEvent = (date: CalendarData) => { + // 瀹炵幇鍒ゆ柇鏃ユ湡鏄惁鏈変簨浠剁殑閫昏緫 + return Math.random() > 0.8; +}; + +// 鍥捐〃鍒濆鍖� +onMounted(() => { + if (chartRef.value) { + const chart = echarts.init(chartRef.value); + chart.setOption({ + xAxis: { + type: 'category', + data: ['涓浗', '寰峰浗', '娉曞浗', '鑻卞浗', '鏂拌タ鍏�', '缇庡浗', '鐟炲+'], + }, + yAxis: { + type: 'value', + }, + series: [ + { + data: [80, 50, 100, 30, 70, 80, 60], + type: 'bar', + barWidth: '30%', + itemStyle: { + color: '#409EFF', + }, + }, + ], + }); + } +}); </script> -<style scoped lang="scss"></style> + +<style scoped lang="scss"> +.workspace-container { + display: grid; + grid-template-columns: 1fr 300px; + gap: v-bind(layoutGap); + padding: 20px; + background-color: #f5f7fa; +} + +.overview-cards { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 20px; +} + +// 鑷畾涔夋寜閽牱寮� +.custom-button { + --el-button-bg-color: var(--color-btn-base); + --el-button-border-color: var(--color-btn-base); + --el-button-hover-bg-color: var(--color-btn-hover); + --el-button-hover-border-color: var(--color-btn-hover); +} + +// 鑷畾涔� tabs 鏍峰紡 +:deep(.todo-tabs) { + .el-tabs__header { + margin: 0; + } + + .el-tabs__nav-wrap::after { + display: none; + } + + .el-tabs__item { + padding: 0 10px; + height: 32px; + line-height: 32px; + font-size: 14px; + + &.is-active { + color: var(--color-btn-base); + } + } + + .el-tabs__active-bar { + background-color: var(--color-btn-base); + } +} + +// 鑷畾涔夋棩鍘嗘牱寮� +:deep(.el-calendar) { + --el-calendar-border: none; + --el-calendar-header-border-bottom: none; + background: none; + + .el-calendar__header { + display: none; + } + + .el-calendar__body { + padding: 12px 0; + } + + .el-calendar-table { + td { + border: none; + padding: 4px; + } + + .current { + background: none; + } + } +} + +.custom-calendar-cell { + height: 32px; + display: flex; + align-items: center; + justify-content: center; + position: relative; + + .date-text { + font-size: 14px; + } + + .event-dot { + position: absolute; + top: 2px; + right: 2px; + width: 6px; + height: 6px; + border-radius: 50%; + background-color: var(--el-color-primary); + } +} + +.calendar-notice { + background-color: #fff7e6; + color: #fa8c16; + padding: 8px 12px; + border-radius: 4px; + font-size: 14px; +} + +.avatar-placeholder { + width: 64px; + height: 64px; + border-radius: 50%; + background-color: #f5f7fa; + display: flex; + align-items: center; + justify-content: center; +} + +:deep(.el-calendar-table .el-calendar-day) { + --el-calendar-cell-width: 10px; +} + +.chart-container { + background: white; + border-radius: 8px; + + .chart { + height: 300px; + } + + .chart-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 16px; + + .subtitle { + color: var(--el-text-color-secondary); + font-size: 14px; + } + } +} + +.calendar-container { + background: white; + border-radius: 8px; + + .calendar-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 16px; + + h3 { + font-size: 16px; + font-weight: 500; + margin: 0; + } + } +} + +:deep(.el-date-picker) { + --el-input-width: 120px; +} + +.section-header { + h3 { + font-size: 16px; + // font-weight: 500; + // margin: 0; + // color: var(--el-text-color-primary); + } +} +</style> -- Gitblit v1.9.3