|
|
@@ -1,116 +1,861 @@
|
|
|
<template>
|
|
|
<div class="home">
|
|
|
- <div class="home-top">
|
|
|
- <el-button class="create" size="medium" @click="jump('/create_project')">
|
|
|
- 教材创建 <i class="el-icon-plus"> </i>
|
|
|
- </el-button>
|
|
|
- </div>
|
|
|
- <div class="home-content">
|
|
|
- <div
|
|
|
- v-for="{ color, title, path, icon } in itemList"
|
|
|
- :key="title"
|
|
|
- class="item"
|
|
|
- :style="{ backgroundColor: color }"
|
|
|
- @click="jump(path)"
|
|
|
- >
|
|
|
- <span class="title">{{ title }}</span>
|
|
|
- <span class="icon" :style="{ backgroundColor: color }">
|
|
|
- <SvgIcon :icon-class="icon" size="36" />
|
|
|
- </span>
|
|
|
+ <div class="home-main">
|
|
|
+ <div class="home-content">
|
|
|
+ <div
|
|
|
+ v-for="({ title, path, icon, desc, iconBg, bg }, index) in itemList"
|
|
|
+ :key="title"
|
|
|
+ class="item"
|
|
|
+ :style="{ background: bg }"
|
|
|
+ :class="`item--${index + 1}`"
|
|
|
+ @click="onItemClick(path, index)"
|
|
|
+ >
|
|
|
+ <span class="icon" :style="{ backgroundColor: iconBg }">
|
|
|
+ <SvgIcon :icon-class="icon" size="30" />
|
|
|
+ </span>
|
|
|
+ <span class="title">{{ title }}</span>
|
|
|
+ <span class="desc">
|
|
|
+ {{ desc }}
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="overview-row">
|
|
|
+ <div
|
|
|
+ v-for="{ label, key, dotColor } in overviewList"
|
|
|
+ :key="label"
|
|
|
+ class="stat-card"
|
|
|
+ :class="{ active: currentOverview === key }"
|
|
|
+ @click="changeOverview(key)"
|
|
|
+ >
|
|
|
+ <span class="stat-label"><span class="dot" :style="{ backgroundColor: dotColor }"></span>{{ label }}</span>
|
|
|
+ <strong class="stat-value">{{ stateInfo[key] }}</strong>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="list-section">
|
|
|
+ <el-table
|
|
|
+ v-if="currentOverview === overviewList[0].key"
|
|
|
+ class="project-list"
|
|
|
+ :data="projectList"
|
|
|
+ height="calc(100vh - 630px)"
|
|
|
+ >
|
|
|
+ <el-table-column prop="sn" width="150" align="center" header-align="center" label="编号" />
|
|
|
+ <el-table-column prop="name" label="教材名称" width="460" header-align="left" />
|
|
|
+ <el-table-column prop="version" label="版本" width="120" align="center" header-align="center" />
|
|
|
+ <el-table-column prop="leader_name_desc" label="项目组长" width="220" align="center" header-align="center" />
|
|
|
+
|
|
|
+ <el-table-column prop="progress_percent" label="进度" width="180" align="center" header-align="center">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <div class="progress">
|
|
|
+ <span class="progress-bar"><i :style="{ width: `${row.progress_percent}%` }"></i></span>
|
|
|
+ <em>{{ row.progress_percent }}%</em>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="create_date" label="创建日期" width="150" align="center" header-align="center" />
|
|
|
+ <el-table-column prop="status_name" label="状态" min-width="120" align="center" header-align="center">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <span
|
|
|
+ class="status"
|
|
|
+ :style="{
|
|
|
+ color: stateColorList[row.status].color,
|
|
|
+ backgroundColor: stateColorList[row.status].bc,
|
|
|
+ }"
|
|
|
+ >
|
|
|
+ {{ row.status_name }}
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column fixed="right" label="操作" align="center" header-align="center">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <el-button type="text" @click="previewProject(row.id)">进入</el-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+
|
|
|
+ <el-table
|
|
|
+ v-else-if="currentOverview === overviewList[1].key"
|
|
|
+ class="project-list"
|
|
|
+ :data="projectList"
|
|
|
+ height="calc(100vh - 630px)"
|
|
|
+ >
|
|
|
+ <el-table-column prop="sn" width="150" align="center" header-align="center" label="编号" />
|
|
|
+ <el-table-column prop="name" label="教材名称" width="460" header-align="left" />
|
|
|
+ <el-table-column prop="version" label="版本" width="120" align="center" header-align="center" />
|
|
|
+ <el-table-column prop="leader_name_desc" label="项目组长" width="220" align="center" header-align="center" />
|
|
|
+
|
|
|
+ <el-table-column prop="progress_percent" label="进度" width="180" align="center" header-align="center">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <div class="progress">
|
|
|
+ <span class="progress-bar"><i :style="{ width: `${row.progress_percent}%` }"></i></span>
|
|
|
+ <em>{{ row.progress_percent }}%</em>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ prop="plan_publish_date"
|
|
|
+ label="预计完成时间"
|
|
|
+ width="150"
|
|
|
+ align="center"
|
|
|
+ header-align="center"
|
|
|
+ />
|
|
|
+ <el-table-column prop="status_name" label="状态" min-width="120" align="center" header-align="center">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <span
|
|
|
+ class="status"
|
|
|
+ :style="{
|
|
|
+ color: stateColorList[row.status].color,
|
|
|
+ backgroundColor: stateColorList[row.status].bc,
|
|
|
+ }"
|
|
|
+ >
|
|
|
+ {{ row.status_name }}
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column fixed="right" label="操作" align="center" header-align="center">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <el-button type="text" @click="previewProject(row.id)">进入</el-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+
|
|
|
+ <el-table
|
|
|
+ v-else-if="currentOverview === overviewList[2].key"
|
|
|
+ class="project-list"
|
|
|
+ :data="projectList"
|
|
|
+ height="calc(100vh - 630px)"
|
|
|
+ >
|
|
|
+ <el-table-column prop="sn" width="150" align="center" header-align="center" label="编号" />
|
|
|
+ <el-table-column prop="name" label="教材名称" width="460" header-align="left" />
|
|
|
+ <el-table-column prop="version" label="版本" width="120" align="center" header-align="center" />
|
|
|
+ <el-table-column prop="leader_name_desc" label="项目组长" width="220" align="center" header-align="center" />
|
|
|
+
|
|
|
+ <el-table-column prop="progress_percent" label="进度" width="180" align="center" header-align="center">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <div class="progress">
|
|
|
+ <span class="progress-bar"><i :style="{ width: `${row.progress_percent}%` }"></i></span>
|
|
|
+ <em>{{ row.progress_percent }}%</em>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="edit_end_date" label="交稿时间" width="150" align="center" header-align="center" />
|
|
|
+ <el-table-column prop="status_name" label="状态" min-width="120" align="center" header-align="center">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <span
|
|
|
+ class="status"
|
|
|
+ :style="{
|
|
|
+ color: stateColorList[row.status].color,
|
|
|
+ backgroundColor: stateColorList[row.status].bc,
|
|
|
+ }"
|
|
|
+ >
|
|
|
+ {{ row.status_name }}
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column fixed="right" label="操作" align="center" header-align="center">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <el-button type="text" @click="previewProject(row.id)">进入</el-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+
|
|
|
+ <el-table
|
|
|
+ v-else-if="currentOverview === overviewList[3].key"
|
|
|
+ class="project-list"
|
|
|
+ :data="projectList"
|
|
|
+ height="calc(100vh - 630px)"
|
|
|
+ >
|
|
|
+ <el-table-column prop="sn" width="150" align="center" header-align="center" label="编号" />
|
|
|
+ <el-table-column prop="name" label="教材名称" width="460" header-align="left" />
|
|
|
+ <el-table-column prop="version" label="版本" width="120" align="center" header-align="center" />
|
|
|
+ <el-table-column prop="leader_name_desc" label="项目组长" width="220" align="center" header-align="center" />
|
|
|
+
|
|
|
+ <el-table-column prop="progress_percent" label="进度" width="180" align="center" header-align="center">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <div class="progress">
|
|
|
+ <span class="progress-bar"><i :style="{ width: `${row.progress_percent}%` }"></i></span>
|
|
|
+ <em>{{ row.progress_percent }}%</em>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ prop="plan_publish_date"
|
|
|
+ label="预计完成时间"
|
|
|
+ width="150"
|
|
|
+ align="center"
|
|
|
+ header-align="center"
|
|
|
+ />
|
|
|
+ <el-table-column prop="status_name" label="状态" min-width="120" align="center" header-align="center">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <span
|
|
|
+ class="status"
|
|
|
+ :style="{
|
|
|
+ color: stateColorList[row.status].color,
|
|
|
+ backgroundColor: stateColorList[row.status].bc,
|
|
|
+ }"
|
|
|
+ >
|
|
|
+ {{ row.status_name }}
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column fixed="right" label="操作" align="center" header-align="center">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <el-button type="text" @click="previewProject(row.id)">进入</el-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+
|
|
|
+ <el-table
|
|
|
+ v-else-if="currentOverview === overviewList[4].key"
|
|
|
+ class="project-list"
|
|
|
+ :data="projectList"
|
|
|
+ height="calc(100vh - 630px)"
|
|
|
+ >
|
|
|
+ <el-table-column prop="sn" width="150" align="center" header-align="center" label="编号" />
|
|
|
+ <el-table-column prop="name" label="教材名称" width="460" header-align="left" />
|
|
|
+ <el-table-column prop="version" label="版本" width="120" align="center" header-align="center" />
|
|
|
+ <el-table-column prop="member_name_desc" label="作者" width="220" align="center" header-align="center" />
|
|
|
+ <el-table-column prop="shangjia_date" label="上架时间" width="150" align="center" header-align="center" />
|
|
|
+ <el-table-column prop="revise_count" label="修订次数" align="center" header-align="center" />
|
|
|
+ <el-table-column fixed="right" label="操作" align="center" header-align="center">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <el-button type="text" @click="previewProject(row.id)">进入</el-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ <PaginationPage :total="total" @getList="getList" />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div v-if="toolModalVisible" class="tool-modal" @click.self="closeToolModal">
|
|
|
+ <div class="tool-modal-box">
|
|
|
+ <SvgIcon class="tool-modal-close" icon-class="home-close" size="12" @click="closeToolModal" />
|
|
|
+ <h3>扩展工具</h3>
|
|
|
+
|
|
|
+ <button class="tool-item t1" type="button" @click="openToolPage('template')">
|
|
|
+ <span class="ti-icon"><SvgIcon icon-class="home-template" size="24" /></span>
|
|
|
+ <span class="ti-label">模板库</span>
|
|
|
+ </button>
|
|
|
+
|
|
|
+ <button class="tool-item t2" type="button" @click="openToolPage('pinyin')">
|
|
|
+ <span class="ti-icon">
|
|
|
+ <SvgIcon icon-class="home-pinyin" size="24" />
|
|
|
+ </span>
|
|
|
+ <span class="ti-label">拼音校正库</span>
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
+import { GetMyProjectStatInfo } from '@/api/user';
|
|
|
+import { PageQueryMyProjectList } from '@/api/list';
|
|
|
+
|
|
|
+import PaginationPage from '@/components/PaginationPage.vue';
|
|
|
+
|
|
|
export default {
|
|
|
name: 'HomePage',
|
|
|
+ components: {
|
|
|
+ PaginationPage,
|
|
|
+ },
|
|
|
data() {
|
|
|
return {
|
|
|
itemList: [
|
|
|
{
|
|
|
+ color: '#F5B131',
|
|
|
+ title: '新建',
|
|
|
+ path: '/create_project',
|
|
|
+ desc: '创建教材项目',
|
|
|
+ bg: 'linear-gradient(135deg, #EEF2FF 0%, #fff 100%)',
|
|
|
+ icon: 'home-new',
|
|
|
+ iconBg: '#DBEAFE',
|
|
|
+ },
|
|
|
+ {
|
|
|
color: '#667EE5',
|
|
|
- title: '教材管理',
|
|
|
+ title: '管理',
|
|
|
path: '/personal_workbench/project',
|
|
|
- icon: 'manage',
|
|
|
+ desc: '统筹项目资源与进度',
|
|
|
+ bg: 'linear-gradient(135deg,#FEFCE8 0%,#fff 100%)',
|
|
|
+ icon: 'home-manage',
|
|
|
+ iconBg: '#FEF3C7',
|
|
|
},
|
|
|
{
|
|
|
color: '#F5B131',
|
|
|
- title: '教材制作',
|
|
|
+ title: '制作',
|
|
|
path: '/personal_workbench/edit_task',
|
|
|
- icon: 'make',
|
|
|
+ desc: '编辑教材内容',
|
|
|
+ bg: 'linear-gradient(135deg,#EFF6FF 0%,#fff 100%)',
|
|
|
+ icon: 'home-make',
|
|
|
+ iconBg: '#DBEAFE',
|
|
|
},
|
|
|
{
|
|
|
color: '#E25E5C',
|
|
|
- title: '教材审核',
|
|
|
+ title: '审核',
|
|
|
path: '/personal_workbench/check_task',
|
|
|
- icon: 'audit',
|
|
|
+ desc: '审核并上架教材',
|
|
|
+ bg: 'linear-gradient(135deg,#F5F3FF 0%,#fff 100%)',
|
|
|
+ icon: 'home-review',
|
|
|
+ iconBg: '#EDE9FE',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ color: '#D1FAE5',
|
|
|
+ title: '扩展',
|
|
|
+ path: '',
|
|
|
+ desc: '使用资源库和工具库',
|
|
|
+ bg: 'linear-gradient(135deg,#ECFDF5 0%,#fff 100%)',
|
|
|
+ icon: 'home-tools',
|
|
|
+ iconBg: '#D1FAE5',
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ currentOverview: 'count_QB',
|
|
|
+ overviewList: [
|
|
|
+ {
|
|
|
+ label: '全部教材',
|
|
|
+ key: 'count_QB',
|
|
|
+ color: '#3B82F6',
|
|
|
+ dotColor: '#2D3E8F',
|
|
|
+ type: 0,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '我管理的教材',
|
|
|
+ key: 'count_GL',
|
|
|
+ color: '#F59E0B',
|
|
|
+ dotColor: '#F59E0B',
|
|
|
+ type: 1,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '我制作的教材',
|
|
|
+ key: 'count_ZZ',
|
|
|
+ color: '#8B5CF6',
|
|
|
+ dotColor: '#3B82F6',
|
|
|
+ type: 2,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '我审核的教材',
|
|
|
+ key: 'count_SH',
|
|
|
+ color: '#7C3AED',
|
|
|
+ dotColor: '#7C3AED',
|
|
|
+ type: 3,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '已上架教材',
|
|
|
+ key: 'count_YSJ',
|
|
|
+ color: '#10B981',
|
|
|
+ dotColor: '#10B981',
|
|
|
+ type: 4,
|
|
|
},
|
|
|
],
|
|
|
+ stateColorList: [
|
|
|
+ {
|
|
|
+ color: '#F59E0B',
|
|
|
+ bc: '#FEF3C7',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ color: '#8B5CF6',
|
|
|
+ bc: '#EDE9FE',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ color: '#3B82F6',
|
|
|
+ bc: '#DBEAFE',
|
|
|
+ },
|
|
|
+ { color: '#10B981', bc: '#D1FAE5' },
|
|
|
+ { color: '#FF4757', bc: '#FFE5E5' },
|
|
|
+ ],
|
|
|
+ // 项目统计信息
|
|
|
+ stateInfo: {
|
|
|
+ count_QB: 0, // 全部
|
|
|
+ count_GL: 0, // 管理
|
|
|
+ count_ZZ: 0, // 制作
|
|
|
+ count_SH: 0, // 审核
|
|
|
+ count_YSJ: 0, // 已上架
|
|
|
+ },
|
|
|
+ total: 0,
|
|
|
+ page_capacity: 10,
|
|
|
+ cur_page: 1,
|
|
|
+ projectList: [], // 项目列表
|
|
|
+ toolModalVisible: false,
|
|
|
};
|
|
|
},
|
|
|
+ created() {
|
|
|
+ this.getMyProjectStatInfo();
|
|
|
+ this.getList();
|
|
|
+ },
|
|
|
+ mounted() {
|
|
|
+ document.addEventListener('keydown', this.handleKeydown);
|
|
|
+ },
|
|
|
+ beforeDestroy() {
|
|
|
+ document.removeEventListener('keydown', this.handleKeydown);
|
|
|
+ },
|
|
|
methods: {
|
|
|
+ async getMyProjectStatInfo() {
|
|
|
+ this.stateInfo = await GetMyProjectStatInfo();
|
|
|
+ },
|
|
|
+ getList(data) {
|
|
|
+ const params = {
|
|
|
+ page_capacity: this.page_capacity,
|
|
|
+ cur_page: this.cur_page,
|
|
|
+ type: this.overviewList.find((item) => item.key === this.currentOverview)?.type,
|
|
|
+ };
|
|
|
+ PageQueryMyProjectList({ ...params, ...data }).then(({ project_list, total_count, cur_page }) => {
|
|
|
+ this.projectList = project_list;
|
|
|
+ this.total = total_count;
|
|
|
+ this.page_capacity = data?.page_capacity || this.page_capacity;
|
|
|
+ this.cur_page = cur_page;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * @description 切换概览后重置页码并获取列表数据
|
|
|
+ * @param {string} key - 选中的概览key
|
|
|
+ */
|
|
|
+ changeOverview(key) {
|
|
|
+ this.currentOverview = key;
|
|
|
+ this.getList({ cur_page: 1 });
|
|
|
+ },
|
|
|
+ onItemClick(path, index) {
|
|
|
+ if (index === 4) {
|
|
|
+ this.openToolModal();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.jump(path);
|
|
|
+ },
|
|
|
+ openToolModal() {
|
|
|
+ this.toolModalVisible = true;
|
|
|
+ },
|
|
|
+ closeToolModal() {
|
|
|
+ this.toolModalVisible = false;
|
|
|
+ },
|
|
|
+ handleKeydown(e) {
|
|
|
+ if (e.key === 'Escape') {
|
|
|
+ this.closeToolModal();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ openToolPage(type) {
|
|
|
+ this.closeToolModal();
|
|
|
+ if (type === 'template') {
|
|
|
+ this.$router.push({ name: 'PersonalWorkbenchTemplate' });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (type === 'pinyin') {
|
|
|
+ this.$router.push({ name: 'PersonalWorkbenchPinyinCorrectionList' });
|
|
|
+ }
|
|
|
+ },
|
|
|
jump(path) {
|
|
|
this.$router.push({ path });
|
|
|
},
|
|
|
+ previewProject(projectId) {
|
|
|
+ this.$router.push({ path: `/project_manage/org/project/preview/${projectId}` });
|
|
|
+ },
|
|
|
},
|
|
|
};
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
.home {
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- height: 100%;
|
|
|
- padding: 12px;
|
|
|
- background-color: #f1f1f1;
|
|
|
+ min-height: 100%;
|
|
|
+ padding: 0;
|
|
|
+ overflow: auto;
|
|
|
+ background: #f7f9fe;
|
|
|
|
|
|
- &-top {
|
|
|
+ &-main {
|
|
|
display: flex;
|
|
|
- justify-content: flex-end;
|
|
|
- margin: 40px 20px 8%;
|
|
|
-
|
|
|
- .create {
|
|
|
- color: #f5f5f5;
|
|
|
- background-color: #46bc84;
|
|
|
- }
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 24px;
|
|
|
+ max-width: 80vw;
|
|
|
+ padding: 24px 28px 28px;
|
|
|
+ margin: 0 auto;
|
|
|
}
|
|
|
|
|
|
&-content {
|
|
|
- display: flex;
|
|
|
- flex: 1;
|
|
|
- align-items: flex-start;
|
|
|
- justify-content: space-evenly;
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: repeat(5, minmax(0, 1fr));
|
|
|
+ gap: 20px;
|
|
|
|
|
|
.item {
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
+ gap: 14px;
|
|
|
align-items: center;
|
|
|
- justify-content: space-between;
|
|
|
- width: 15%;
|
|
|
- min-width: 300px;
|
|
|
- aspect-ratio: 3 / 4;
|
|
|
- padding: 4% 0 2%;
|
|
|
+ min-height: 200px;
|
|
|
+ padding: 26px 24px 24px;
|
|
|
cursor: pointer;
|
|
|
- border-radius: 8px;
|
|
|
+ border: 1px solid rgba(226, 232, 240, 68%);
|
|
|
+ border-radius: 20px;
|
|
|
+ box-shadow: 0 16px 36px rgba(15, 23, 42, 5%);
|
|
|
+ transition:
|
|
|
+ transform 0.25s ease,
|
|
|
+ box-shadow 0.25s ease,
|
|
|
+ border-color 0.25s ease;
|
|
|
|
|
|
- .title {
|
|
|
- font-size: 36px;
|
|
|
- font-weight: bold;
|
|
|
- color: #fff;
|
|
|
- text-align: center;
|
|
|
+ &:hover {
|
|
|
+ box-shadow: 0 24px 40px rgba(15, 23, 42, 9%);
|
|
|
+ transform: translateY(-4px);
|
|
|
+ }
|
|
|
+
|
|
|
+ &.item--1:hover,
|
|
|
+ &.item--3:hover {
|
|
|
+ border-color: #3b82f6;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.item--2:hover {
|
|
|
+ border-color: #f59e0b;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.item--4:hover {
|
|
|
+ border-color: #8b5cf6;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.item--5:hover {
|
|
|
+ border-color: #10b981;
|
|
|
}
|
|
|
|
|
|
.icon {
|
|
|
- width: 64px;
|
|
|
- height: 64px;
|
|
|
- overflow: hidden;
|
|
|
- line-height: 84px;
|
|
|
- text-align: center;
|
|
|
- filter: brightness(1.15) saturate(1.1);
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ width: 56px;
|
|
|
+ height: 56px;
|
|
|
+ background-repeat: no-repeat;
|
|
|
+ background-position: center;
|
|
|
+ border-radius: 18px;
|
|
|
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 65%);
|
|
|
+ }
|
|
|
+
|
|
|
+ .title {
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: 700;
|
|
|
+ color: #1f2937;
|
|
|
+ }
|
|
|
+
|
|
|
+ .desc {
|
|
|
+ max-width: 260px;
|
|
|
+ font-size: 11px;
|
|
|
+ color: #94a3b8;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .overview-row {
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: repeat(5, minmax(0, 1fr));
|
|
|
+ gap: 16px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .stat-card {
|
|
|
+ position: relative;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 8px;
|
|
|
+ min-height: 108px;
|
|
|
+ padding: 22px 24px;
|
|
|
+ background: #fff;
|
|
|
+ border: 1px solid rgba(226, 232, 240, 76%);
|
|
|
+ border-radius: 18px;
|
|
|
+ box-shadow: 0 10px 28px rgba(15, 23, 42, 4%);
|
|
|
+
|
|
|
+ &.active {
|
|
|
+ border-color: #2d3e8f;
|
|
|
+ }
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ box-shadow: 0 24px 40px rgba(15, 23, 42, 9%);
|
|
|
+ transform: translateY(-4px);
|
|
|
+ }
|
|
|
+
|
|
|
+ &.active::after {
|
|
|
+ position: absolute;
|
|
|
+ right: calc(50% - 20px);
|
|
|
+ bottom: 0;
|
|
|
+ width: 40px;
|
|
|
+ height: 3px;
|
|
|
+ content: '';
|
|
|
+ background-color: #2d3e8f;
|
|
|
+ border-radius: 4px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .stat-label {
|
|
|
+ font-size: 13px;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #64748b;
|
|
|
+
|
|
|
+ .dot {
|
|
|
+ display: inline-block;
|
|
|
+ width: 10px;
|
|
|
+ height: 10px;
|
|
|
+ margin-right: 6px;
|
|
|
border-radius: 50%;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ .stat-value {
|
|
|
+ font-size: 32px;
|
|
|
+ font-weight: 700;
|
|
|
+ line-height: 1.2;
|
|
|
+ color: #1f2937;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .list-section {
|
|
|
+ height: calc(100vh - 530px);
|
|
|
+ padding: 22px 24px 12px;
|
|
|
+ overflow: hidden;
|
|
|
+ background: rgba(255, 255, 255, 96%);
|
|
|
+ border: 1px solid rgba(226, 232, 240, 82%);
|
|
|
+ border-radius: 20px;
|
|
|
+ box-shadow: 0 16px 32px rgba(15, 23, 42, 4%);
|
|
|
+ }
|
|
|
+
|
|
|
+ .project-list {
|
|
|
+ overflow: hidden;
|
|
|
+ border: 1px solid #eef2f7;
|
|
|
+ border-radius: 14px;
|
|
|
+
|
|
|
+ :deep(.el-table__header-wrapper th) {
|
|
|
+ height: 48px;
|
|
|
+ padding: 0;
|
|
|
+ font-size: 12px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #64748b;
|
|
|
+ background: #f8fafc;
|
|
|
+ border-bottom: 1px solid #eef2f7;
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep(.el-table__row td) {
|
|
|
+ height: 78px;
|
|
|
+ padding: 0;
|
|
|
+ border-bottom: 1px solid #f1f5f9;
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep(.el-table::before) {
|
|
|
+ display: none;
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep(.el-table__row:last-child td) {
|
|
|
+ border-bottom: none;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .book-info {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 6px;
|
|
|
+
|
|
|
+ strong {
|
|
|
+ font-size: 15px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #1f2937;
|
|
|
+ }
|
|
|
+
|
|
|
+ span {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #94a3b8;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .status {
|
|
|
+ display: inline-flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ min-width: 72px;
|
|
|
+ height: 28px;
|
|
|
+ padding: 0 10px;
|
|
|
+ font-size: 12px;
|
|
|
+ font-weight: 600;
|
|
|
+ border-radius: 999px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .owner,
|
|
|
+ .time {
|
|
|
+ font-size: 13px;
|
|
|
+ color: #475569;
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep(.el-table .cell) {
|
|
|
+ font-size: 13px;
|
|
|
+ color: #475569;
|
|
|
+ }
|
|
|
+
|
|
|
+ .progress {
|
|
|
+ display: flex;
|
|
|
+ gap: 10px;
|
|
|
+ align-items: center;
|
|
|
+
|
|
|
+ em {
|
|
|
+ font-size: 12px;
|
|
|
+ font-style: normal;
|
|
|
+ color: #64748b;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .progress-bar {
|
|
|
+ position: relative;
|
|
|
+ width: 88px;
|
|
|
+ height: 8px;
|
|
|
+ overflow: hidden;
|
|
|
+ background: #e2e8f0;
|
|
|
+ border-radius: 999px;
|
|
|
+
|
|
|
+ i {
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ display: block;
|
|
|
+ height: 100%;
|
|
|
+ background: linear-gradient(90deg, #2d3e8f 0%, #4dc9f6 100%);
|
|
|
+ border-radius: inherit;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @media (width <= 1280px) {
|
|
|
+ &-content,
|
|
|
+ .overview-row {
|
|
|
+ grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @media (width <= 960px) {
|
|
|
+ &-hero,
|
|
|
+ .section-head {
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: flex-start;
|
|
|
+ }
|
|
|
+
|
|
|
+ &-content,
|
|
|
+ .overview-row {
|
|
|
+ grid-template-columns: 1fr;
|
|
|
+ }
|
|
|
+
|
|
|
+ .project-list {
|
|
|
+ :deep(.el-table__header-wrapper) {
|
|
|
+ display: none;
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep(.el-table__row td) {
|
|
|
+ height: auto;
|
|
|
+ padding: 12px 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .tool-modal {
|
|
|
+ position: fixed;
|
|
|
+ inset: 0;
|
|
|
+ z-index: 1000;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ background: rgba(0, 0, 0, 40%);
|
|
|
+ }
|
|
|
+
|
|
|
+ .tool-modal-box {
|
|
|
+ position: relative;
|
|
|
+ width: 320px;
|
|
|
+ padding: 28px 32px 24px;
|
|
|
+ background: #fff;
|
|
|
+ border-radius: 16px;
|
|
|
+ box-shadow: 0 12px 48px rgba(0, 0, 0, 15%);
|
|
|
+ animation: fade-up 0.3s ease;
|
|
|
+
|
|
|
+ h3 {
|
|
|
+ margin-bottom: 18px;
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: 700;
|
|
|
+ color: #1f2937;
|
|
|
+ text-align: center;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .tool-modal-close {
|
|
|
+ position: absolute;
|
|
|
+ top: 10px;
|
|
|
+ right: 10px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ width: 24px;
|
|
|
+ height: 24px;
|
|
|
+ color: #94a3b8;
|
|
|
+ cursor: pointer;
|
|
|
+ background: #f7f9fe;
|
|
|
+ border: none;
|
|
|
+ border-radius: 50%;
|
|
|
+ transition: all 0.25s ease;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ color: #1f2937;
|
|
|
+ background: #e2e8f0;
|
|
|
+ }
|
|
|
+
|
|
|
+ svg {
|
|
|
+ width: 14px;
|
|
|
+ height: 14px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .tool-item {
|
|
|
+ display: flex;
|
|
|
+ gap: 12px;
|
|
|
+ align-items: center;
|
|
|
+ width: 100%;
|
|
|
+ padding: 12px;
|
|
|
+ margin-bottom: 8px;
|
|
|
+ cursor: pointer;
|
|
|
+ background: transparent;
|
|
|
+ border: none;
|
|
|
+ border-radius: 10px;
|
|
|
+ transition: all 0.25s ease;
|
|
|
+
|
|
|
+ &:last-child {
|
|
|
+ margin-bottom: 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ background: #f7f9fe;
|
|
|
+ }
|
|
|
+
|
|
|
+ .ti-icon {
|
|
|
+ display: flex;
|
|
|
+ flex-shrink: 0;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ width: 36px;
|
|
|
+ height: 36px;
|
|
|
+ border-radius: 10px;
|
|
|
+
|
|
|
+ svg {
|
|
|
+ width: 18px;
|
|
|
+ height: 18px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .ti-label {
|
|
|
+ font-size: 14px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #1f2937;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.t1 .ti-icon {
|
|
|
+ color: #3b82f6;
|
|
|
+ background: #dbeafe;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.t2 .ti-icon {
|
|
|
+ color: #10b981;
|
|
|
+ background: #d1fae5;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @keyframes fade-up {
|
|
|
+ from {
|
|
|
+ opacity: 0;
|
|
|
+ transform: translateY(12px);
|
|
|
+ }
|
|
|
+
|
|
|
+ to {
|
|
|
+ opacity: 1;
|
|
|
+ transform: translateY(0);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
</style>
|