wangzs 4 mesi fa
parent
commit
246fb5ccec

+ 0 - 0
src/views/system/home/IndexRight/index.vue → src/views/system/home-old/IndexRight/index.vue


+ 116 - 0
src/views/system/home-old/components/show-card/home-show-card.vue

@@ -0,0 +1,116 @@
+<!--
+  * 首页
+  *
+  * @Author:    DCCloud
+  * @Date:      2022-09-14 14:13:00
+  *
+-->
+<template>
+    <div class="card-page">
+        <div class="card-header">
+            <div class="card-header-left">
+                <div class="card-header-left-text">
+                    <span v-if="$props.title" class="title" :title="$props.title">{{
+                        $props.title }}</span>
+                </div>
+            </div>
+            <div v-if="$props.moreLink" class="card-header-right-more">
+                <span title="查看更多">查看更多</span>
+            </div>
+        </div>
+        <div class="card-container">
+            <slot name="default">
+                使用插槽添加内容
+            </slot>
+        </div>
+    </div>
+</template>
+<script setup>
+import { theme } from 'ant-design-vue';
+
+const $props = defineProps({
+    height: {
+        type: String,
+        default: () => '230px'
+    },
+    title: {
+        type: String,
+        default: () => ''
+    },
+    hasMore: {
+        type: Boolean,
+        default: () => false
+    },
+    moreLink: {
+        type: String,
+        default: () => ''
+    }
+});
+
+const { useToken } = theme;
+const { token } = useToken();
+const borderRadius = token.value.borderRadius + 'px';
+</script>
+<style lang="less" scoped>
+.card-page {
+    height: v-bind('$props.height');
+    background-color: #fff;
+    display: flex;
+    flex-direction: column;
+    border-radius: v-bind(borderRadius);
+
+    .card-header {
+        height: 54px;
+
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        padding: 0px 20px;
+        gap: 10px;
+
+        .card-header-left {
+            display: flex;
+            align-items: center;
+            gap: 10px;
+
+            .card-header-left-text {
+
+                display: flex;
+                align-items: baseline;
+                gap: 10px;
+
+                .title {
+                    line-height: 30px;
+                    font-size: 16px;
+                    font-weight: 500;
+                    color: #1D2129;
+
+                    max-width: 160px;
+                    white-space: nowrap;
+                    overflow: hidden;
+                    text-overflow: ellipsis;
+                }
+            }
+        }
+
+        .card-header-right-more {
+            color: v-bind("token.colorPrimary");
+            font-weight: 400;
+            font-size: 14px;
+            cursor: pointer;
+
+            width: 56px;
+            white-space: nowrap;
+            overflow: hidden;
+            text-overflow: ellipsis;
+        }
+    }
+
+    .card-container {
+        flex: 1;
+        // background-color: aqua;
+        padding: 10px 20px;
+        overflow: auto;
+    }
+}
+</style>

+ 232 - 0
src/views/system/home-old/components/to-be-done-card/home-to-be-done.vue

@@ -0,0 +1,232 @@
+<!--
+  * 首页
+  *
+  * @Author:    DCCloud
+  * @Date:      2022-09-14 14:13:00
+  *
+-->
+<template>
+    <div class="card-page">
+        <div :class="{ 'card-header': true, 'card-header-divider': $props.cardInfo.divider }">
+            <div class="card-header-left">
+                <div v-if="$props.cardInfo.icon" class="card-header-left-icon">
+                    <img class="icon" :src="$props.cardInfo.icon">
+                </div>
+                <div class="card-header-left-text">
+                    <span v-if="$props.cardInfo.title" class="title" :title="$props.cardInfo.title">{{
+                        $props.cardInfo.title }}</span>
+                    <span v-if="$props.cardInfo.total || $props.cardInfo.total === 0" class="total" :title="$props.cardInfo.total">{{
+                        $props.cardInfo.total }}</span>
+                </div>
+            </div>
+            <div v-if="$props.cardInfo.hasOwnProperty('moreLink')" class="card-header-right-more">
+                <span title="查看更多" @click="clickMore($props.cardInfo.moreLink)">查看更多</span>
+            </div>
+        </div>
+        <div class="card-container">
+            <div class="card-container-item" v-for="(item, index) in $props.cardInfo.list" :key="index">
+                <div
+                    :class="{ 'card-container-item-left': true, 'card-container-item-left-noDate': !item.receive_time }">
+                    <div :class="{ 'card-container-item-type': true, inform: item.type === '通知', notice: item.type === '公告' }"
+                        v-if="item.type">{{ item.type }}</div>
+                    <div class="card-container-item-info">
+                        <span :title="item.instance_name">{{ item.instance_name }}</span>
+                    </div>
+                </div>
+                <div class="card-container-item-right">
+                    <div class="card-container-item-date" v-if="item.receive_time">{{ parseTime(item.receive_time,
+                        '{y}-{m}-{d}') }}</div>
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+<script setup>
+import { parseTime } from '/@/utils/aidex.js';
+import { useRouter } from 'vue-router';
+import { message, theme } from 'ant-design-vue';
+const $props = defineProps({
+    height: {
+        type: String,
+        default: () => '230px'
+    },
+    cardInfo: {
+        type: Object,
+        required: true,
+        default: () => ({
+            icon: '',
+            title: '',
+            total: 0,
+            totalColor: '#1D2129',
+            hasMore: '',
+            divider: false,
+            list: []
+        })
+    }
+});
+
+// 点击查看更多按钮
+const router = useRouter();
+function clickMore(link) {
+    if (link) {
+        router.push(link);
+    } else {
+        message.warning('未配置链接');
+    }
+}
+
+const { useToken } = theme;
+const { token } = useToken();
+const borderRadius = token.value.borderRadius + 'px';
+</script>
+<style lang="less" scoped>
+.card-page {
+    height: v-bind('$props.height');
+    background-color: #fff;
+    display: flex;
+    flex-direction: column;
+    border-radius: v-bind(borderRadius);
+
+    .card-header {
+        height: 54px;
+
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        padding: 0px 20px;
+        gap: 10px;
+
+        .card-header-left {
+            display: flex;
+            align-items: center;
+            gap: 10px;
+
+            // .card-header-left-icon {}
+
+            .card-header-left-text {
+
+                display: flex;
+                align-items: baseline;
+                gap: 10px;
+
+                .title {
+                    line-height: 30px;
+                    font-size: 16px;
+                    font-weight: 500;
+                    color: #1D2129;
+
+                    max-width: 160px;
+                    white-space: nowrap;
+                    overflow: hidden;
+                    text-overflow: ellipsis;
+                }
+
+                .total {
+                    font-size: 24px;
+                    font-weight: 700;
+                    color: v-bind('$props.cardInfo.totalColor');
+                }
+
+            }
+        }
+
+        .card-header-right-more {
+            color: v-bind("token.colorPrimary");
+            font-weight: 400;
+            font-size: 14px;
+            cursor: pointer;
+
+            width: 56px;
+            white-space: nowrap;
+            overflow: hidden;
+            text-overflow: ellipsis;
+        }
+    }
+
+    .card-header-divider {
+        padding: 30px 20px;
+        border-bottom: 1px solid #F2F3F5;
+    }
+
+    .card-container {
+        padding: 10px 16px;
+        flex: 1;
+        overflow-y: auto;
+
+        display: flex;
+        flex-direction: column;
+        gap: 10px;
+
+        .card-container-item {
+            // padding: 10px 0;
+            display: flex;
+            align-items: center;
+            justify-content: space-between;
+            gap: 10px;
+
+            .card-container-item-left {
+                width: 60%;
+                display: flex;
+                align-items: center;
+                justify-content: space-between;
+                gap: 8px;
+
+                .card-container-item-type {
+                    padding: 2px 4px;
+                    font-size: 12px;
+                    border-radius: 2px;
+                    white-space: nowrap;
+                }
+
+                .inform {
+                    // 通知
+                    color: #165DFF;
+                    background-color: #E8F3FF;
+                }
+
+                .notice {
+                    // 公告
+                    color: #F77234;
+                    background-color: #FFF3E8;
+                }
+
+
+                .card-container-item-info {
+                    width: 100%;
+                    font-size: 14px;
+                    color: #4E5969;
+
+                    white-space: nowrap;
+                    overflow: hidden;
+                    text-overflow: ellipsis;
+
+                    cursor: pointer;
+
+                    &:hover {
+                        color: #165DFF;
+                        text-decoration: underline;
+                    }
+
+                    span {
+                        white-space: nowrap;
+                        overflow: hidden;
+                        text-overflow: ellipsis;
+                    }
+                }
+            }
+
+            .card-container-item-left-noDate {
+                width: 100%;
+            }
+
+            .card-container-item-right {
+                .card-container-item-date {
+                    width: 62px;
+                    white-space: nowrap;
+                    font-size: 12px;
+                }
+            }
+        }
+    }
+}
+</style>

+ 199 - 0
src/views/system/home-old/home-header.vue

@@ -0,0 +1,199 @@
+<!--
+  * 首页 用户头部信息
+  *
+  * @Author:    DCCloud
+  * @Date:      2022-09-12 22:34:00
+  *
+-->
+<template>
+  <div class="user-header">
+    <a-page-header :title="welcomeSentence">
+      <template #subTitle>
+        <div class="user-header-subTitle">
+          <img style="height: 12px; height: 12px;" :src="paperAirplane">
+          <span style="width: 100%; overflow: hidden; text-overflow: ellipsis;">{{ departmentName }}</span>
+        </div>
+      </template>
+      <template #extra>
+        <p style="color: #333">{{ dayInfo }}</p>
+      </template>
+      <a-row class="content">
+        <span class="left-content">
+          <p class="last-login-info">
+            上次登录:
+            <template v-for="(item, index) in lastLoginInfo.split(';')">
+              <div>
+                <ClockCircleOutlined v-if="index === 0" />
+                <DesktopOutlined v-if="index === 1" />
+                <EnvironmentOutlined v-if="index === 2" />
+                <GlobalOutlined v-if="index === 3" />
+                <span>{{ item }}</span>
+              </div>
+            </template>
+          </p>
+        </span>
+        <!-- <div class="weather">
+          <iframe
+            width="100%"
+            scrolling="no"
+            height="50"
+            frameborder="0"
+            allowtransparency="true"
+            src="//i.tianqi.com/index.php?c=code&id=12&icon=1&num=3&site=12"
+          ></iframe>
+        </div> -->
+      </a-row>
+    </a-page-header>
+  </div>
+</template>
+<script setup>
+import paperAirplane from '/@/assets/images/home/paper-airplane.png';
+
+import { computed } from 'vue';
+import { useUserStore } from '/@/store/modules/system/user';
+import uaparser from 'ua-parser-js';
+import { Solar, Lunar } from 'lunar-javascript';
+import _ from 'lodash';
+import { theme } from 'ant-design-vue';
+const userStore = useUserStore();
+
+const departmentName = computed(() => userStore.departmentName);
+
+// 欢迎语
+const welcomeSentence = computed(() => {
+  let sentence = '';
+  let now = new Date().getHours();
+  if (now > 0 && now <= 6) {
+    sentence = '午夜好,';
+  } else if (now > 6 && now <= 11) {
+    sentence = '早上好,';
+  } else if (now > 11 && now <= 14) {
+    sentence = '中午好,';
+  } else if (now > 14 && now <= 18) {
+    sentence = '下午好,';
+  } else {
+    sentence = '晚上好,';
+  }
+  return sentence + userStore.$state.actualName;
+});
+
+//上次登录信息
+const lastLoginInfo = computed(() => {
+  let info = '';
+  if (userStore.$state.lastLoginTime) {
+    info = info + ' ' + userStore.$state.lastLoginTime;
+  }
+
+  if (userStore.$state.lastLoginUserAgent) {
+    let ua = uaparser(userStore.$state.lastLoginUserAgent);
+    info = info + '; ';
+    if (ua.browser.name) {
+      info = info + ' ' + ua.browser.name;
+    }
+    if (ua.os.name) {
+      info = info + ' ' + ua.os.name;
+    }
+    let device = ua.device.vendor ? ua.device.vendor + ua.device.model : null;
+    if (device) {
+      info = info + ' ' + device + ';';
+    }
+  }
+
+  if (userStore.$state.lastLoginIpRegion) {
+    info = info + '; ' + userStore.$state.lastLoginIpRegion;
+  }
+  if (userStore.$state.lastLoginIp) {
+    info = info + '; ' + userStore.$state.lastLoginIp;
+  }
+  return info;
+});
+
+//日期、节日、节气
+const dayInfo = computed(() => {
+  //阳历
+  let solar = Solar.fromDate(new Date());
+  let day = solar.toString();
+  let week = solar.getWeekInChinese();
+  //阴历
+  let lunar = Lunar.fromDate(new Date());
+  let lunarMonth = lunar.getMonthInChinese();
+  let lunarDay = lunar.getDayInChinese();
+  //节气
+  let jieqi = lunar.getPrevJieQi().getName();
+  let next = lunar.getNextJieQi();
+  let nextJieqi = next.getName() + ' ' + next.getSolar().toYmd();
+
+  return `${day} 星期${week},农历${lunarMonth}${lunarDay}(当前${jieqi},${nextJieqi} )`;
+});
+
+const { useToken } = theme;
+const { token } = useToken();
+const borderRadius = token.value.borderRadius + 'px';
+
+</script>
+<style scoped lang="less">
+.user-header {
+  width: 100%;
+  // #dcefff 30% #ffffff 100%
+  background: linear-gradient(180deg, v-bind('token.colorPrimaryBg') 0%, #ffffff 30%);
+  margin-bottom: 10px;
+  border-radius: v-bind(borderRadius);
+
+  .user-header-subTitle {
+    display: flex;
+    align-items: center;
+    gap: 6px;
+
+    color: v-bind("token.colorPrimary");
+    margin-left: 10px;
+    border-radius: 12px;
+    padding: 0 12px;
+    background: v-bind("token.colorPrimaryBg");
+  }
+
+  .left-content {
+    width: calc(100% - 420px);
+
+    h3 {
+      color: rgba(0, 0, 0, 0.75);
+    }
+  }
+
+  .content {
+    display: flex;
+    justify-content: space-between;
+
+    .weather {
+      width: 400px;
+    }
+  }
+
+  .last-login-info {
+    font-size: 13px;
+    color: #86909c;
+    overflow-wrap: break-word;
+    padding: 0;
+    margin: 1px 0 0 0;
+
+    display: flex;
+    align-items: center;
+    gap: 8px;
+    flex-wrap: wrap;
+    min-width: 200px;
+  }
+
+  .sentence {
+    display: block;
+    font-size: 12px;
+    color: #acacac;
+    overflow-wrap: break-word;
+    padding: 5px 0 0 0;
+    margin: 6px 0 0 0;
+  }
+
+  .sentence:hover {
+    cursor: pointer;
+    text-decoration: underline;
+  }
+}
+</style>

+ 656 - 0
src/views/system/home-old/index.less

@@ -0,0 +1,656 @@
+<template>
+    <a-card>
+        <div class="approval-steps">
+            <a-steps :current="current" :items="items"></a-steps>
+            <div class="steps-content">
+                <a-form class="smart-query-form" ref="stepFormRef" :label-col="labelCol" :model="formModel"
+                    :rules="formRules">
+                    <div v-if="current == 0">
+                        <a-row class="smart-query-form-row">
+                            <a-col :span="12">
+                                <a-form-item label="项目模板" name="projectTemplateId" class="smart-query-form-item">
+                                    <DictSelect key-code="BL_PROJECT_TEMPLATE"
+                                        v-model:value="formModel.projectTemplateId" placeholder="请选择项目模板"
+                                        width="100%" />
+                                </a-form-item>
+                            </a-col>
+                            <a-col :span="12">
+                                <a-form-item label="项目编号" name="projectCode" class="smart-query-form-item">
+                                    <a-input v-model:value="formModel.projectCode" placeholder="" disabled />
+                                </a-form-item>
+                            </a-col>
+                        </a-row>
+                        <a-row class="smart-query-form-row">
+                            <a-col :span="24">
+                                <a-form-item label="项目名称" name="projectName" class="smart-query-form-item">
+                                    <a-input v-model:value="formModel.projectName" placeholder="请输入项目名称" />
+                                </a-form-item>
+                            </a-col>
+                        </a-row>
+                        <a-row class="smart-query-form-row">
+                            <a-col :span="12">
+                                <a-form-item label="项目等级" name="projectLevel" class="smart-query-form-item">
+                                    <DictSelect key-code="BL_PROJECT_LEVEL" v-model:value="formModel.projectLevel"
+                                        placeholder="请选择项目等级" width="100%" />
+                                </a-form-item>
+                            </a-col>
+                            <a-col :span="12">
+                                <a-form-item label="项目类型" name="projectType" class="smart-query-form-item">
+                                    <DictSelect key-code="BL_PROJECT_TYPE" v-model:value="formModel.projectType"
+                                        placeholder="请选择项目类型" width="100%" />
+                                </a-form-item>
+                            </a-col>
+                        </a-row>
+                        <a-row class="smart-query-form-row">
+                            <a-col :span="12">
+                                <a-form-item label="交付经理" name="deliveryManager" class="smart-query-form-item">
+                                    <a-input v-model:value="formModel.deliveryManager" placeholder="请选择交付经理"
+                                        @click="showSelectUser('deliveryManager')" readonly />
+                                </a-form-item>
+                                <EmployeeTableSelectModal ref="selectDeliveryManagerRef" type="radio"
+                                    @selectDataList="selectedUser('deliveryManager', $event)" />
+                            </a-col>
+                            <a-col :span="12">
+                                <a-form-item label="客户经理" name="accountManager" class="smart-query-form-item">
+                                    <a-input v-model:value="formModel.accountManager" placeholder="请选择客户经理"
+                                        @click="showSelectUser('accountManager')" readonly />
+                                </a-form-item>
+                                <EmployeeTableSelectModal ref="selectAccountManagerRef" type="radio"
+                                    @selectDataList="selectedUser('accountManager', $event)" />
+                            </a-col>
+                        </a-row>
+                        <a-row class="smart-query-form-row">
+                            <a-col :span="24">
+                                <a-form-item label="成本构成模板" name="templateName" class="smart-query-form-item">
+                                    <a-input v-model:value="formModel.templateName" placeholder="请选择成本构成模板"
+                                        @click="showSelectTemplate" />
+                                </a-form-item>
+                                <SelectModal ref="TemplateSelectModalRef" @selectedRowList="templateSelectedRowList"
+                                    :modalTableCondition="templateCondition" v-bind="attrs" />
+                            </a-col>
+                        </a-row>
+                        <a-row class="smart-query-form-row">
+                            <a-col :span="24">
+                                <a-form-item label="合同签订状态" name="contractStatus" class="smart-query-form-item">
+                                    <DictSelect key-code="BL_CONTRACT_STATUS" v-model:value="formModel.contractStatus"
+                                        placeholder="请输入合同签订状态" width="100%" mode="" />
+                                </a-form-item>
+                            </a-col>
+                        </a-row>
+                        <template v-if="formModel.contractStatus.includes(CONTRACT_STATUS_ENUM.SIGNED.value)">
+                            <a-row class="smart-query-form-row">
+                                <a-col :span="12">
+                                    <a-form-item label="关联合同" name="contractName" class="smart-query-form-item">
+                                        <a-input v-model:value="formModel.contractName" placeholder="关联合同"
+                                            @click="showSelectContract" />
+                                    </a-form-item>
+                                    <SelectModal ref="ContractSelectModalRef" @selectedRowList="contractSelectedRowList"
+                                        :modalTableCondition="contractCondition" v-bind="attrs" />
+                                </a-col>
+                                <a-col :span="12">
+                                    <a-form-item label="客户名称" name="supplierName" class="smart-query-form-item">
+                                        <a-input v-model:value="formModel.supplierName" placeholder="客户名称" disabled />
+                                    </a-form-item>
+                                </a-col>
+                            </a-row>
+                            <a-row class="smart-query-form-row">
+                                <a-col :span="12">
+                                    <a-form-item label="签约主体" name="signingParty" class="smart-query-form-item">
+                                        <a-input v-model:value="formModel.signingParty" placeholder="签约主体" disabled />
+                                    </a-form-item>
+                                </a-col>
+                                <a-col :span="12">
+                                    <a-form-item label="合同含税金额" name="taxAmount" class="smart-query-form-item">
+                                        <a-input-number v-model:value="formModel.taxAmount" placeholder="合同含税金额"
+                                            style="width: 100%" disabled />
+                                    </a-form-item>
+                                </a-col>
+                            </a-row>
+                            <a-row class="smart-query-form-row">
+                                <a-col :span="12">
+                                    <a-form-item label="税率" name="taxRate" class="smart-query-form-item">
+                                        <a-input-number v-model:value="formModel.taxRate" placeholder="税率" :min="0"
+                                            :max="100" :formatter="value => `${value}%`"
+                                            :parser="value => value.replace('%', '')" style="width: 100%" disabled />
+                                    </a-form-item>
+                                </a-col>
+                                <a-col :span="12">
+                                    <a-form-item label="合同约定进场日期" name="contractStartDate" class="smart-query-form-item"
+                                        :label-col="{ width: '130px' }">
+                                        <a-date-picker v-model:value="formModel.contractStartDate"
+                                            placeholder="合同约定进场日期" value-format="YYYY-MM-DD" style="width: 100%"
+                                            disabled />
+                                    </a-form-item>
+                                </a-col>
+                            </a-row>
+                            <a-row class="smart-query-form-row">
+                                <a-col :span="12">
+                                    <a-form-item label="合同约定验收日期" name="contractEndDate" class="smart-query-form-item"
+                                        :label-col="{ width: '130px' }">
+                                        <a-date-picker v-model:value="formModel.contractEndDate" placeholder="合同约定验收日期"
+                                            value-format="YYYY-MM-DD" style="width: 100%" disabled />
+                                    </a-form-item>
+                                </a-col>
+                                <a-col :span="12">
+                                    <a-form-item label="计划完工日期" name="planCompleteDate" class="smart-query-form-item"
+                                        :label-col="{ width: '130px' }">
+                                        <a-date-picker v-model:value="formModel.planCompleteDate" placeholder="计划完工日期"
+                                            value-format="YYYY-MM-DD" style="width: 100%" />
+                                    </a-form-item>
+                                </a-col>
+                            </a-row>
+                        </template>
+                    </div>
+                    <div v-if="current == 1">
+                        <a-table size="small" :pagination="false" bordered :dataSource="formModel.projectStageVOList"
+                            :columns="columns">
+                            <template #bodyCell="{ column, index }">
+                                <template v-if="column.dataIndex === 'stageDate'">
+                                    <a-form-item :name="['projectStageVOList', index, column.dataIndex]"
+                                        class="smart-query-form-item"
+                                        :rules="[{ required: true, message: '请选择阶段日期', trigger: 'blur' }]">
+                                        <a-date-picker
+                                            v-model:value="formModel['projectStageVOList'][index][column.dataIndex]"
+                                            value-format="YYYY-MM-DD" style="width: 100%" />
+                                    </a-form-item>
+                                </template>
+                            </template>
+                        </a-table>
+                    </div>
+                    <div v-if="current == 2">
+                        <a-row :gutter="16" class="smart-query-form-row">
+                            <a-col :span="12">
+                                <a-form-item label="基准工时" name="baseManHours" class="smart-query-form-item">
+                                    <a-input v-model:value="formModel.baseManHours" placeholder="请输入基准工时" />
+                                </a-form-item>
+                            </a-col>
+                            <a-col :span="12">
+                                <a-form-item label="基准人工成本" name="baseLaborCost" class="smart-query-form-item">
+                                    <a-input v-model:value="formModel.baseLaborCost" placeholder="请输入基准人工成本" />
+                                </a-form-item>
+                            </a-col>
+                        </a-row>
+                        <a-row :gutter="16" class="smart-query-form-row">
+                            <a-col :span="12">
+                                <a-form-item label="基准费用成本" name="baseExpenseCost" class="smart-query-form-item">
+                                    <a-input v-model:value="formModel.baseExpenseCost" placeholder="请输入基准费用成本" />
+                                </a-form-item>
+                            </a-col>
+                            <a-col :span="12">
+                                <a-form-item label="基准总成本" name="baseTotalCost" class="smart-query-form-item">
+                                    <a-input v-model:value="formModel.baseTotalCost" placeholder="请输入基准总成本" />
+                                </a-form-item>
+                            </a-col>
+                        </a-row>
+                    </div>
+                    <div v-if="current == 3">
+                        <a-row :gutter="16" class="smart-query-form-row">
+                            <a-col :span="12">
+                                <a-form-item label="省市区" name="provinceCityDistrict" class="smart-query-form-item">
+                                    <AreaCascader type="province_city_district" style="width: 100%"
+                                        v-model:value="provinceCityDistrict" placeholder="请选择省市区"
+                                        @change="changeArea" />
+                                </a-form-item>
+                            </a-col>
+                            <a-col :span="12">
+                                <a-form-item label="详细地址" name="specificAddress" class="smart-query-form-item">
+                                    <a-input v-model:value="formModel.specificAddress" placeholder="请输入详细地址" />
+                                </a-form-item>
+                            </a-col>
+                        </a-row>
+                        <a-row :gutter="16" class="smart-query-form-row">
+                            <a-col :span="12">
+                                <a-form-item label="创建日期" name="createDate" class="smart-query-form-item">
+                                    <a-date-picker v-model:value="formModel.createDate" placeholder="创建日期"
+                                        value-format="YYYY-MM-DD" style="width: 100%" disabled />
+                                </a-form-item>
+                            </a-col>
+                            <a-col :span="12">
+                                <a-form-item label="创建人" name="creator" class="smart-query-form-item">
+                                    <a-input v-model:value="formModel.creator" placeholder="请输入创建人" disabled />
+                                </a-form-item>
+                            </a-col>
+                        </a-row>
+                        <a-row :gutter="16" class="smart-query-form-row">
+                            <a-col :span="24">
+                                <a-form-item label="项目描述" name="projectDescription" class="smart-query-form-item">
+                                    <a-textarea v-model:value="formModel.projectDescription" placeholder="请输入创建人"
+                                        :rows="4" :showCount="true" :allowClear="true" />
+                                </a-form-item>
+                            </a-col>
+                        </a-row>
+                    </div>
+                </a-form>
+            </div>
+            <div class="steps-action">
+                <a-button v-if="current > 0" style="margin-right: 8px" @click="prev">上一步</a-button>
+                <a-button v-if="current < steps.length - 1" type="primary" @click="next">下一步</a-button>
+                <a-button v-if="current == steps.length - 1" type="primary" @click="submit">
+                    提交
+                </a-button>
+            </div>
+        </div>
+    </a-card>
+</template>
+<script setup>
+import dayjs from 'dayjs';
+import { onMounted, reactive, ref, useAttrs } from 'vue';
+import { useRouter } from 'vue-router';
+import { message, Modal } from 'ant-design-vue';
+import _ from 'lodash';
+import DictSelect from '/@/components/support/dict-select/index.vue';
+import AreaCascader from '/@/components/framework/area-cascader/index.vue';
+import { CONTRACT_STATUS_ENUM } from '/@/constants/teamwork/project-approval-const';
+import EmployeeTableSelectModal from '/@/components/system/employee-table-select-modal/index.vue';
+import { useUserStore } from '/@/store/modules/system/user';
+import { projectApi } from '/@/api/teamwork/project/project-api';
+
+import SelectModal from "/@/components/common/table-select-modal/components/modal.vue";
+
+const stepFormRef = ref(null);
+const selectDeliveryManagerRef = ref(null);
+const selectAccountManagerRef = ref(null);
+const attrs = useAttrs();
+const TemplateSelectModalRef = ref(null);
+const ContractSelectModalRef = ref(null);
+const router = useRouter();
+const templateCondition = ref({
+    url: '/blProjectCost/template/queryPage',
+    search: [
+        {
+            label: '模板编码',
+            field: 'templateCode',
+            type: 'input',
+            width: '200px',
+        },
+        {
+            label: '模板名称',
+            field: 'templateName',
+            type: 'input',
+            width: '200px',
+        },
+    ],
+    tableAttrs: {
+        rowKey: 'id',
+        columns: [
+            {
+                title: '模板编码',
+                dataIndex: 'templateCode',
+            },
+            {
+                title: '模板名称',
+                dataIndex: 'templateName',
+            },
+            {
+                title: '模板类型',
+                dataIndex: 'templateType',
+            },
+            {
+                title: '创建人',
+                dataIndex: 'createUserId',
+            },
+            {
+                title: '创建日期',
+                dataIndex: 'createTime',
+            },
+        ],
+    },
+});
+const contractCondition = ref({
+    url: '/blContractMaster/queryPage',
+    search: [
+        {
+            label: '合同编码',
+            field: 'contractCode',
+            type: 'input',
+            width: '200px',
+        },
+        {
+            label: '合同名称',
+            field: 'contractName',
+            type: 'input',
+            width: '200px',
+        },
+    ],
+    tableAttrs: {
+        rowKey: 'id',
+        columns: [
+            {
+                title: '合同编码',
+                dataIndex: 'contractCode',
+            },
+            {
+                title: '合同名称',
+                dataIndex: 'contractName',
+            },
+            {
+                title: '合同类型',
+                dataIndex: 'contractType',
+            },
+            {
+                title: '合同状态',
+                dataIndex: 'contractStatus',
+            },
+            {
+                title: '签约单位',
+                dataIndex: 'signingParty',
+            },
+            {
+                title: '合同金额',
+                dataIndex: 'txAmount',
+            },
+        ],
+    },
+});
+
+function templateShowModal(selectedRowKey) {
+    TemplateSelectModalRef.value.showModal(selectedRowKey);
+}
+function contractShowModal(selectedRowKey) {
+    ContractSelectModalRef.value.showModal(selectedRowKey);
+}
+
+function showSelectUser(type) {
+    if (type === 'deliveryManager') {
+        selectDeliveryManagerRef.value.showModal();
+    } else if (type === 'accountManager') {
+        selectAccountManagerRef.value.showModal();
+    }
+};
+
+function selectedUser(field, list) {
+    // console.log('selectedUser', field, list);
+    formModel[field] = list[0].actualName;
+};
+
+function changeArea(value, selectedOptions) {
+    formModel.provinceCityDistrict = value;
+}
+
+// --------------------- 数据 ---------------------
+const formModel = reactive({
+    projectTemplateId: [], // 项目模板
+    projectCode: undefined, // 项目编号
+    projectName: undefined, // 项目名称
+    projectLevel: [], // 项目等级
+    projectType: [], // 项目类型
+    deliveryManager: undefined, // 交付经理
+    accountManager: undefined, // 客户经理
+    templateName: undefined, // 成本构成模板
+    costTemplateId: undefined, // 成本构成模板id --不展示
+    contractStatus: [], // 合同签订状态
+    contactId: undefined, // 合同id --不展示
+    supplierName: undefined, // 客户名称
+    signingParty: undefined, // 签约主体
+    contractName: undefined, // 关联合同
+    taxAmount: undefined, // 合同含税金额
+    taxRate: undefined, // 税率
+    contractStartDate: undefined, // 合同约定进场日期
+    contractEndDate: undefined, // 合同约定验收日期
+    planCompleteDate: undefined, // 计划完工日期
+    baseManHours: undefined, // 基准工时
+    baseLaborCost: undefined, // 基准人工成本
+    baseExpenseCost: undefined, // 基准费用成本
+    baseTotalCost: undefined, // 基准总成本
+
+    projectStageVOList: [
+        {
+            stageId: '1',
+            stageName: '项目启动(0)',
+            stageDate: undefined,
+            duration: '1',
+        },
+        {
+            stageId: '2',
+            stageName: '项目策划(0~20)',
+            stageDate: undefined,
+            duration: '32',
+        },
+        {
+            stageId: '3',
+            stageName: '项目前期(20~30)',
+            stageDate: undefined,
+            duration: '83',
+        },
+        {
+            stageId: '4',
+            stageName: '项目中期(30~50)',
+            stageDate: undefined,
+            duration: '265',
+        },
+        {
+            stageId: '5',
+            stageName: '项目后期(50~70)',
+            stageDate: undefined,
+            duration: '327',
+        },
+        {
+            stageId: '6',
+            stageName: '竣前筹备(70~90)',
+            stageDate: undefined,
+            duration: '388',
+        },
+        {
+            stageId: '7',
+            stageName: '竣工管理(100)',
+            stageDate: undefined,
+            duration: '432',
+        },
+    ],
+
+    // province: undefined, // 省
+    // city: undefined, // 市
+    // district: undefined, // 区
+    provinceCityDistrict: undefined, // 省市区
+
+    specificAddress: undefined, // 详细地址
+    projectDescription: undefined, // 项目描述
+
+    createDate: dayjs().format('YYYY-MM-DD'), // 创建日期 --不传后端
+    creator: useUserStore().actualName, // 创建人 --不传后端
+});
+
+// --------------------- 校验规则 ---------------------
+const formRules = {
+    // 第一步
+    projectTemplateId: [{ required: true, message: '请选择项目模板', trigger: 'change' }],
+    // projectCode: [{ required: true, message: '请输入项目编号', trigger: 'change' }],
+    projectName: [{ required: true, message: '请输入项目名称', trigger: 'change' }],
+    projectLevel: [{ required: true, message: '请选择项目等级', trigger: 'change' }],
+    projectType: [{ required: true, message: '请选择项目类型', trigger: 'change' }],
+    deliveryManager: [{ required: true, message: '请选择交付经理', trigger: 'change' }],
+    accountManager: [{ required: true, message: '请选择客户经理', trigger: 'change' }],
+    templateName: [{ required: true, message: '请选择成本构成模板', trigger: 'change' }],
+    // costTemplateId: [{ required: true, message: '请选择成本构成模板', trigger: 'change' }],
+    contractStatus: [{ required: true, message: '请选择合同签订状态', trigger: 'change' }],
+
+    // 合同签订状态-已签约-> 自动带出
+    // contractName: [{ required: true, message: '请选择关联合同', trigger: 'change' }],
+    // contractId: [{ required: true, message: '请选择关联合同', trigger: 'change' }],
+    // supplierName: [{ required: true, message: '请选择客户名称', trigger: 'change' }],
+    // signingParty: [{ required: true, message: '请选择签约主体', trigger: 'change' }],
+    // taxAmount: [{ required: true, message: '请输入合同含税金额', trigger: 'change' }],
+    // taxRate: [{ required: true, message: '请输入税率', trigger: 'change' }],
+    // contractStartDate: [{ required: true, message: '请选择合同约定进场日期', trigger: 'change' }],
+    // contractEndDate: [{ required: true, message: '请选择合同约定验收日期', trigger: 'change' }],
+    // planCompleteDate: [{ required: true, message: '请选择计划完工日期', trigger: 'change' }],
+
+    // 第二步
+    // 'projectStageVOList.stageDate': [{ required: true, message: '请选择阶段日期', trigger: 'change' }],
+
+    // 第三步
+    baseManHours: [{ required: true, message: '请输入基准工时', trigger: 'change' }],
+    baseLaborCost: [{ required: true, message: '请输入基准人工成本', trigger: 'change' }],
+    baseExpenseCost: [{ required: true, message: '请输入基准费用成本', trigger: 'change' }],
+    baseTotalCost: [{ required: true, message: '请输入基准总成本', trigger: 'change' }],
+
+    // 第四步
+    // province: [{ required: true, message: '请选择省', trigger: 'change' }],
+    // city: [{ required: true, message: '请选择市', trigger: 'change' }],
+    // district: [{ required: true, message: '请选择区', trigger: 'change' }],
+    provinceCityDistrict: [{ required: true, message: '请选择省市区', trigger: 'change' }],
+    specificAddress: [{ required: true, message: '请输入详细地址', trigger: 'change' }],
+    projectDescription: [{ required: true, message: '请输入项目描述', trigger: 'change' }],
+};
+
+// --------------------- 配置 ---------------------
+const columns = [
+    // { //  隐藏
+    //     title: '阶段Id',
+    //     dataIndex: 'stageId',
+    //     key: 'stageId',
+    // },
+    {
+        title: '项目阶段',
+        dataIndex: 'stageName',
+        key: 'stageName',
+    },
+    {
+        title: '阶段周期',
+        dataIndex: 'stageDate',
+        key: 'stageDate',
+    },
+    {
+        title: '周期(天)',
+        dataIndex: 'duration',
+        key: 'duration',
+    },
+
+];
+
+const labelCol = { style: { width: '120px' } };
+
+// -------------------- 步骤相关 --------------------
+const current = ref(0);
+
+const next = () => {
+    stepFormRef.value.validateFields().then((values) => {
+        current.value++;
+    }).catch((error) => {
+        console.log('step1_error', error);
+    });
+
+    if (current.value === 0) {
+        const validateFiledList = ['projectTemplateId', 'projectName', 'projectLevel', 'projectType', 'deliveryManager',
+            'accountManager', 'templateName', 'contractStatus'];
+        stepFormRef.value.validateFields(validateFiledList).then((values) => {
+            current.value++;
+        }).catch((error) => {
+            console.log('step0_error', error);
+        });
+    } else if (current.value === 1) {
+        const filedList = ['stageDate'];
+        const validateFiledList = formModel.projectStageVOList.map((_, index) => {
+            return filedList.map((filed) => ['projectStageVOList', index, filed]);
+        }).flat();
+        stepFormRef.value.validateFields(validateFiledList).then((values) => {
+            current.value++;
+        }).catch((error) => {
+            console.log('step1_error', error);
+        });
+    } else if (current.value === 2) {
+        const validateFiledList = ['baseManHours', 'baseLaborCost', 'baseExpenseCost', 'baseTotalCost'];
+        stepFormRef.value.validateFields(validateFiledList).then((values) => {
+            current.value++;
+        }).catch((error) => {
+            console.log('step2_error', error);
+        });
+    } else if (current.value === 3) {
+    }
+};
+
+const prev = () => {
+    current.value--;
+};
+
+const submit = () => {
+    Modal.confirm({
+        title: '提示',
+        content: '确定要提交吗?',
+        okText: '确认',
+        onOk() {
+            postFormData();
+        },
+        cancelText: '取消',
+        onCancel() { },
+    });
+}
+
+const postFormData = () => {
+    stepFormRef.value.validateFields().then((values) => {
+        projectApi.submitProjectApproval(formModel).then((res) => {
+            message.success('提交成功');
+            router.push({ path: '/teamwork/project-manage' });
+        })
+    }).catch((error) => {
+        console.log('step1_error', error);
+    });
+}
+
+const steps = [
+    {
+        title: '填写基本信息',
+        content: 'First-content',
+    },
+    {
+        title: '填写节点信息',
+        content: 'Second-content',
+    },
+    {
+        title: '填写基准成本',
+        content: 'Last-content',
+    },
+    {
+        title: '填写其他信息',
+        content: 'Last-content',
+    },
+];
+const items = steps.map(item => ({
+    key: item.title,
+    title: item.title,
+}));
+
+function showSelectTemplate() {
+    templateShowModal()
+};
+function showSelectContract() {
+    contractShowModal()
+};
+
+function templateSelectedRowList(selectedRowList = {}) {
+    formModel.costTemplateId = selectedRowList.id;
+    formModel.templateName = selectedRowList.templateName;
+};
+function contractSelectedRowList(selectedRowList = {}) {
+    formModel.contactId = selectedRowList.id;
+    formModel.contractName = selectedRowList.contractName;
+    formModel.supplierName = selectedRowList.customName;
+    formModel.signingParty = selectedRowList.signingParty;
+    formModel.taxAmount = selectedRowList.taxAmount;
+    formModel.taxRate = selectedRowList.taxRate;
+    formModel.contractStartDate = selectedRowList.contractStartDate;
+    formModel.contractEndDate = selectedRowList.contractEndDate;
+    // formModel.planCompleteDate = selectedRowList.planCompleteDate;
+};
+
+onMounted(() => {
+});
+</script>
+
+<style scoped lang="less">
+.approval-steps {
+    width: 850px;
+    margin: 0 auto;
+
+    .steps-content {
+        min-height: 150px;
+        margin-top: 20px;
+    }
+
+    .steps-action {
+        display: flex;
+        justify-content: center;
+        margin-top: 18px;
+    }
+}
+</style>

+ 628 - 0
src/views/system/home-old/index.vue

@@ -0,0 +1,628 @@
+<template>
+  <div class="home-container" ref="rootRef">
+    <div class="content">
+      <div class="main-left">
+        <div class="slogan">
+          <span>独立</span>
+          <span class="dot">·</span>
+          <span>科学</span>
+          <span class="dot">·</span>
+          <span>公正</span>
+        </div>
+        <img class="bg" :src="bgIcon" />
+        <img class="move1" :src="Icon" alt="" @click="goLink('/agent-construction/home')" />
+        <img class="move2" :src="Icon1" alt="" @click="goLink('/government-entrusted/home')" />
+        <div class="main1 move3">行政事务管理</div>
+        <div class="main1 move4">人事管理</div>
+        <div class="main1 move5">财务管理</div>
+        <div class="main1 move6">课题研究</div>
+        <div class="main1 move7">党建事务管理</div>
+        <div class="main1 move8">资产管理</div>
+        <div class="main1 move9">档案管理</div>
+        <div class="main1 move9">档案管理</div>
+        <div class="main1 move10">知识管理</div>
+        <div class="main2 move11" @click="goLink('/market-manage/home')">
+          <img class="arrow" :src="Arrow" alt="" />
+          <span>市场管理</span>
+          <img style="transform: rotate(180deg)" class="arrow" :src="Arrow" alt="" />
+        </div>
+        <div class="main2 move12" @click="goLink('/pundit/home')">
+          <img class="arrow" :src="Arrow" alt="" />
+          <span>专家库</span>
+          <img style="transform: rotate(180deg)" class="arrow" :src="Arrow" alt="" />
+        </div>
+      </div>
+      <div class="main-right">
+        <div class="task-box">
+          <span class="task-title">任务中心</span>
+          <div class="task-content">
+            <div class="task-item">
+              <img class="task-icon" :src="Icon9" />
+              <span class="task-name">待办任务</span>
+              <span class="task-num">20</span>
+            </div>
+            <div class="task-item">
+              <img class="task-icon" :src="Icon10" />
+              <span class="task-name">待审批流程</span>
+              <span class="task-num">20</span>
+            </div>
+            <div class="task-item">
+              <img class="task-icon" :src="Icon11" />
+              <span class="task-name">传阅流程</span>
+              <span class="task-num">20</span>
+            </div>
+            <div class="task-item">
+              <img class="task-icon" :src="Icon12" />
+              <span class="task-name">已办流程</span>
+              <span class="task-num">20</span>
+            </div>
+            <div class="task-item">
+              <img class="task-icon" :src="Icon13" />
+              <span class="task-name">集团通知</span>
+              <span class="task-num">20</span>
+            </div>
+            <div class="task-item">
+              <img class="task-icon" :src="Icon14" />
+              <span class="task-name">奖罚通知</span>
+              <span class="task-num">20</span>
+            </div>
+          </div>
+        </div>
+        <div class="notice-box">
+          <div class="notice-banner">
+            <div class="notice-title">
+              <span class="notice-title-name">通知公告</span>
+              <div class="notice-title-num">99+</div>
+            </div>
+            <span class="notice-more">查看更多</span>
+          </div>
+          <div class="notice-content" v-for="i in 15">
+            <div class="notice-item-box">
+              <div class="notice-item">院内通知-内控系统优化升级计划通知-2024年12月</div>
+              <span>11-22</span>
+            </div>
+            <div class="notice-line"></div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <div class="bottom">
+      <span class="bottom-title">常用功能</span>
+      <div class="bottom-content">
+        <div class="bottom-item" v-for="(item, index) in bottomList" :key="index" @click="goLink(item.link)">
+          <img :src="item.iconPath" alt="" />
+          <span>{{ item.name }}</span>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+<script setup>
+// 中心-back---------------------------------------------------------------
+import bgIcon from '/@/assets/images/home/bg.svg';
+import Arrow from '/@/assets/images/home/arrow.svg';
+import Icon from '/@/assets/images/home/dj.png';
+import Icon1 from '/@/assets/images/home/wt.png';
+import Icon2 from '/@/assets/images/home/icon2.svg';
+import Icon3 from '/@/assets/images/home/icon3.svg';
+import Icon4 from '/@/assets/images/home/icon4.svg';
+// 底部-icon---------------------------------------------------------------
+import Icon5 from '/@/assets/images/home/icon5.svg';
+import Icon6 from '/@/assets/images/home/icon6.svg';
+import Icon7 from '/@/assets/images/home/icon7.svg';
+import Icon8 from '/@/assets/images/home/icon8.svg';
+// 任务-icon---------------------------------------------------------------
+import Icon9 from '/@/assets/images/home/icon9.svg';
+import Icon10 from '/@/assets/images/home/icon10.svg';
+import Icon11 from '/@/assets/images/home/icon11.svg';
+import Icon12 from '/@/assets/images/home/icon12.svg';
+import Icon13 from '/@/assets/images/home/icon13.svg';
+import Icon14 from '/@/assets/images/home/icon14.svg';
+// ------------------------------------------------------------------------
+import { ref, onMounted, onUnmounted } from 'vue';
+import { useRouter } from 'vue-router';
+
+import { theme, message } from 'ant-design-vue';
+
+const bottomList = [
+  { name: '数据驾驶舱', iconPath: Icon2, link: '' },
+  { name: '费用报销', iconPath: Icon3, link: '' },
+  { name: '任务日历', iconPath: Icon4, link: '' },
+  { name: '加班申请', iconPath: Icon5, link: '' },
+  { name: '出差审批', iconPath: Icon6, link: '' },
+  { name: '报告管理', iconPath: Icon7, link: '' },
+  { name: '个人中心', iconPath: Icon8, link: '' },
+];
+
+const router = useRouter();
+function goLink(link) {
+  if (!link) {
+    message.warning('暂未开放');
+    return;
+  }
+  router.push({
+    path: link,
+  });
+}
+
+// ---------------- 适配屏幕缩放 ----------------
+const rootRef = ref(null);
+
+function reduceRatio() {
+  handleResize();
+  window.addEventListener('resize', handleResize);
+}
+
+function handleResize() {
+  const ratio = window.innerWidth / 1920;
+  rootRef.value.style.setProperty('--fitWidthRatio', ratio);
+}
+
+onMounted(() => {
+  reduceRatio();
+});
+
+onUnmounted(() => {
+  window.removeEventListener('resize', handleResize);
+});
+</script>
+
+<style lang="less" scoped>
+.home-container {
+  --fitWidthRatio: 1; // 1920px
+  font-size: calc(var(--fitWidthRatio) * 16px); // 页面默认字体大小
+
+  display: grid;
+  grid-template-rows: 1fr auto;
+  width: 100%;
+  height: calc(100vh - 102px);
+
+  .content {
+    display: flex;
+    position: relative;
+    width: 100%;
+    gap: calc(var(--fitWidthRatio) * 10px);
+    min-height: calc(var(--fitWidthRatio) * 670px);
+
+    .main-left {
+      flex: 7.5;
+      background: #ffffff;
+      position: relative;
+      width: 100%;
+      border-radius: calc(var(--fitWidthRatio) * 8px);
+
+      .slogan {
+        position: absolute;
+        top: 3%;
+        left: 3%;
+        writing-mode: vertical-lr;
+        font-family: PingFang SC;
+        font-weight: 400;
+        font-size: calc(var(--fitWidthRatio) * 20px);
+        color: #f95555;
+        letter-spacing: calc(var(--fitWidthRatio) * 10px);
+
+        .dot {
+          margin: calc(var(--fitWidthRatio) * 10px) 0;
+        }
+      }
+
+      .bg {
+        position: absolute;
+        top: 9%;
+        width: 100%;
+        height: calc(var(--fitWidthRatio) * 600px);
+      }
+
+      .main1 {
+        cursor: pointer;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        border-radius: calc(var(--fitWidthRatio) * 20px);
+        border: calc(var(--fitWidthRatio) * 1px) solid #a4c1ff;
+        box-shadow: 0px 1px 2px 0px #e3e3e399;
+        background: #edf3ff;
+
+        font-family: Noto Sans SC;
+        font-size: calc(var(--fitWidthRatio) * 22px);
+        font-weight: 500;
+        color: #3676f7;
+      }
+
+      .main2 {
+        cursor: pointer;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        border: 1.5px solid #4482ff;
+        box-shadow: 0px 0px calc(var(--fitWidthRatio) * 14px) 0px #fdfeffcc inset;
+        width: calc(var(--fitWidthRatio) * 200px);
+        height: calc(var(--fitWidthRatio) * 57px);
+        border-radius: calc(var(--fitWidthRatio) * 8px);
+        background: #ffffff;
+
+        font-family: Noto Sans SC;
+        font-weight: 500;
+        font-size: calc(var(--fitWidthRatio) * 26px);
+        color: #165dff;
+
+        .arrow {
+          width: calc(var(--fitWidthRatio) * 20px);
+          height: calc(var(--fitWidthRatio) * 13px);
+        }
+
+        span {
+          margin: 0 calc(var(--fitWidthRatio) * 12px);
+        }
+      }
+
+      .main3 {
+        cursor: pointer;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        width: calc(var(--fitWidthRatio) * 130px);
+        height: calc(var(--fitWidthRatio) * 53px);
+        border-radius: calc(var(--fitWidthRatio) * 8px);
+        background: #ffffff;
+        border: 1.4px solid #1f72ed33;
+        box-shadow: 0px calc(var(--fitWidthRatio) * 7px) calc(var(--fitWidthRatio) * 16px) 0px #1f72ed1f;
+
+        font-family: Noto Sans SC;
+        font-size: calc(var(--fitWidthRatio) * 20px);
+        font-weight: 500;
+        color: #000000;
+      }
+
+      .box1 {
+        display: flex;
+        flex-wrap: wrap;
+        justify-content: center;
+        align-items: center;
+        gap: calc(var(--fitWidthRatio) * 8px);
+        border-radius: calc(var(--fitWidthRatio) * 8px);
+        border: 1px dashed #80a6fe;
+        padding: calc(var(--fitWidthRatio) * 10px) 0;
+      }
+
+      .move1 {
+        cursor: pointer;
+        position: absolute;
+        top: 59%;
+        left: 4.5%;
+        width: calc(var(--fitWidthRatio) * 174px);
+        height: calc(var(--fitWidthRatio) * 174px);
+      }
+
+      .move2 {
+        cursor: pointer;
+        position: absolute;
+        top: 18%;
+        left: 80.5%;
+        width: calc(var(--fitWidthRatio) * 174px);
+        height: calc(var(--fitWidthRatio) * 174px);
+      }
+
+      .move3 {
+        position: absolute;
+        top: 42%;
+        left: 1.5%;
+        width: calc(var(--fitWidthRatio) * 170px);
+        height: calc(var(--fitWidthRatio) * 50px);
+      }
+
+      .move4 {
+        position: absolute;
+        top: 24%;
+        left: 8%;
+        width: calc(var(--fitWidthRatio) * 170px);
+        height: calc(var(--fitWidthRatio) * 50px);
+      }
+
+      .move5 {
+        position: absolute;
+        top: 10%;
+        left: 22%;
+        width: calc(var(--fitWidthRatio) * 170px);
+        height: calc(var(--fitWidthRatio) * 50px);
+      }
+
+      .move6 {
+        position: absolute;
+        top: 5%;
+        left: 44%;
+        width: calc(var(--fitWidthRatio) * 170px);
+        height: calc(var(--fitWidthRatio) * 50px);
+      }
+
+      .move7 {
+        position: absolute;
+        top: 88%;
+        left: 44%;
+        width: calc(var(--fitWidthRatio) * 170px);
+        height: calc(var(--fitWidthRatio) * 50px);
+      }
+
+      .move8 {
+        position: absolute;
+        top: 83%;
+        left: 62%;
+        width: calc(var(--fitWidthRatio) * 170px);
+        height: calc(var(--fitWidthRatio) * 50px);
+      }
+
+      .move9 {
+        position: absolute;
+        top: 71%;
+        left: 77%;
+        width: calc(var(--fitWidthRatio) * 170px);
+        height: calc(var(--fitWidthRatio) * 50px);
+      }
+
+      .move10 {
+        position: absolute;
+        top: 56%;
+        left: 85%;
+        width: calc(var(--fitWidthRatio) * 170px);
+        height: calc(var(--fitWidthRatio) * 50px);
+      }
+
+      .move11 {
+        position: absolute;
+        top: 25.7%;
+        left: 49.8%;
+      }
+
+      .move12 {
+        position: absolute;
+        top: 74.5%;
+        left: 33.8%;
+      }
+
+      .move13 {
+        position: absolute;
+        top: 71%;
+        left: 69%;
+        width: calc(var(--fitWidthRatio) * 105px);
+        height: calc(var(--fitWidthRatio) * 45px);
+      }
+
+      .move14 {
+        position: absolute;
+        top: 71%;
+        left: 6.7%;
+        width: calc(var(--fitWidthRatio) * 300px);
+        height: calc(var(--fitWidthRatio) * 146px);
+      }
+
+      .move15 {
+        position: absolute;
+        top: 71%;
+        left: 27.7%;
+        width: calc(var(--fitWidthRatio) * 576px);
+        height: calc(var(--fitWidthRatio) * 146px);
+      }
+
+      .text1 {
+        position: absolute;
+        top: 43%;
+        left: 3%;
+        font-family: Noto Sans SC;
+        font-size: calc(var(--fitWidthRatio) * 20px);
+        font-weight: 500;
+        color: #2b69f8;
+      }
+
+      .text2 {
+        position: absolute;
+        top: 44%;
+        left: 13%;
+        font-family: Noto Sans SC;
+        font-size: calc(var(--fitWidthRatio) * 24px);
+        font-weight: 700;
+        color: #2b69f8;
+      }
+
+      .text3 {
+        display: flex;
+        flex-direction: column;
+        position: absolute;
+        top: 40%;
+        left: 43.4%;
+
+        font-family: Noto Sans SC;
+        font-size: calc(var(--fitWidthRatio) * 32px);
+        font-weight: 500;
+        color: #ffffff;
+      }
+
+      .text3:hover {
+        cursor: pointer;
+      }
+    }
+
+    .main-right {
+      overflow: hidden;
+      display: flex;
+      flex-direction: column;
+      gap: calc(var(--fitWidthRatio) * 10px);
+      flex: 2.5;
+
+      .task-box {
+        flex: 3;
+        padding: calc(var(--fitWidthRatio) * 26px);
+        background: #ffffff;
+        border-radius: calc(var(--fitWidthRatio) * 8px);
+
+        .task-title {
+          font-family: Noto Sans SC;
+          font-weight: 400;
+          font-size: calc(var(--fitWidthRatio) * 20px);
+          color: #000000;
+        }
+
+        .task-content {
+          display: flex;
+          flex-wrap: wrap;
+          margin-top: calc(var(--fitWidthRatio) * 30px);
+          row-gap: calc(var(--fitWidthRatio) * 28px);
+
+          .task-item {
+            display: flex;
+            flex-direction: column;
+            align-items: center;
+            width: calc(var(--fitWidthRatio) * 115px);
+
+            .task-icon {
+              width: calc(var(--fitWidthRatio) * 16px);
+              height: calc(var(--fitWidthRatio) * 16px);
+            }
+
+            .task-name {
+              font-family: Microsoft YaHei UI;
+              font-weight: 400;
+              font-size: calc(var(--fitWidthRatio) * 14px);
+              color: #000000e5;
+              margin-top: calc(var(--fitWidthRatio) * 10px);
+              margin-bottom: calc(var(--fitWidthRatio) * 3px);
+            }
+
+            .task-num {
+              font-family: Microsoft YaHei UI;
+              font-weight: 400;
+              font-size: calc(var(--fitWidthRatio) * 20px);
+              color: #2b69f8;
+            }
+          }
+        }
+      }
+
+      .notice-box {
+        padding: calc(var(--fitWidthRatio) * 26px);
+        flex: 7;
+        background: #ffffff;
+        border-radius: calc(var(--fitWidthRatio) * 8px);
+
+        .notice-banner {
+          display: flex;
+          justify-content: space-between;
+          align-items: center;
+
+          .notice-title {
+            display: flex;
+            align-items: center;
+
+            .notice-title-name {
+              font-family: Noto Sans SC;
+              font-weight: 400;
+              font-size: calc(var(--fitWidthRatio) * 20px);
+              color: #000000;
+              margin-right: calc(var(--fitWidthRatio) * 4px);
+            }
+
+            .notice-title-num {
+              display: flex;
+              justify-content: center;
+              align-items: center;
+              padding: 0 calc(var(--fitWidthRatio) * 4px);
+              // width: calc(var(--fitWidthRatio) * 35px);
+              height: calc(var(--fitWidthRatio) * 19px);
+              border-radius: calc(var(--fitWidthRatio) * 10px);
+              border: 1px solid #4174f5;
+              margin-top: calc(var(--fitWidthRatio) * 3px);
+              font-family: Noto Sans SC;
+              font-weight: 700;
+              font-size: calc(var(--fitWidthRatio) * 14px);
+              color: #3676f7;
+            }
+          }
+
+          .notice-more {
+            cursor: pointer;
+            font-family: Noto Sans SC;
+            font-weight: 700;
+            font-size: calc(var(--fitWidthRatio) * 14px);
+            color: #165dff;
+          }
+        }
+
+        .notice-content {
+          margin-top: calc(var(--fitWidthRatio) * 20px);
+
+          .notice-item-box {
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+
+            .notice-item {
+              width: 75%;
+              display: -webkit-box;
+              -webkit-box-orient: vertical;
+              -webkit-line-clamp: 1;
+              /* 限制显示两行 */
+              overflow: hidden;
+            }
+          }
+
+          .notice-line {
+            margin-top: calc(var(--fitWidthRatio) * 15px);
+            width: 100%;
+            height: 0.5px;
+            background: #4174f566;
+          }
+        }
+      }
+    }
+  }
+
+  .bottom {
+    display: flex;
+    flex-direction: column;
+    justify-content: space-between;
+    width: 100%;
+    height: calc(var(--fitWidthRatio) * 130px);
+    border-radius: calc(var(--fitWidthRatio) * 6px);
+    background: #ffffff;
+    margin-top: calc(var(--fitWidthRatio) * 10px);
+    padding: calc(var(--fitWidthRatio) * 14px) calc(var(--fitWidthRatio) * 30px);
+
+    .bottom-title {
+      font-family: Noto Sans SC;
+      font-size: calc(var(--fitWidthRatio) * 24px);
+      font-weight: 500;
+      color: #000000;
+    }
+
+    .bottom-content {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+
+      .bottom-item {
+        cursor: pointer;
+        gap: 2px;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        width: calc(var(--fitWidthRatio) * 186px);
+        height: calc(var(--fitWidthRatio) * 66px);
+        border-radius: calc(var(--fitWidthRatio) * 8px);
+        background: linear-gradient(90.68deg, #ebf1fa 0.59%, rgba(235, 241, 251, 0) 174.75%), linear-gradient(0deg, #e9f2ff, #e9f2ff);
+
+        img {
+          width: calc(var(--fitWidthRatio) * 24px);
+          height: calc(var(--fitWidthRatio) * 24px);
+        }
+
+        span {
+          font-family: Noto Sans SC;
+          font-size: calc(var(--fitWidthRatio) * 20px);
+          font-weight: 500;
+          color: #000000;
+        }
+      }
+    }
+  }
+}
+</style>

+ 1 - 1
src/views/system/home/home-header.vue

@@ -1,7 +1,7 @@
 <!--
   * 首页 用户头部信息
   *
-  * @Author:    DCCloud
+  * @Author:    BoundLink
   * @Date:      2022-09-12 22:34:00
   *
 -->

+ 132 - 645
src/views/system/home/index.less

@@ -1,656 +1,143 @@
-<template>
-    <a-card>
-        <div class="approval-steps">
-            <a-steps :current="current" :items="items"></a-steps>
-            <div class="steps-content">
-                <a-form class="smart-query-form" ref="stepFormRef" :label-col="labelCol" :model="formModel"
-                    :rules="formRules">
-                    <div v-if="current == 0">
-                        <a-row class="smart-query-form-row">
-                            <a-col :span="12">
-                                <a-form-item label="项目模板" name="projectTemplateId" class="smart-query-form-item">
-                                    <DictSelect key-code="BL_PROJECT_TEMPLATE"
-                                        v-model:value="formModel.projectTemplateId" placeholder="请选择项目模板"
-                                        width="100%" />
-                                </a-form-item>
-                            </a-col>
-                            <a-col :span="12">
-                                <a-form-item label="项目编号" name="projectCode" class="smart-query-form-item">
-                                    <a-input v-model:value="formModel.projectCode" placeholder="" disabled />
-                                </a-form-item>
-                            </a-col>
-                        </a-row>
-                        <a-row class="smart-query-form-row">
-                            <a-col :span="24">
-                                <a-form-item label="项目名称" name="projectName" class="smart-query-form-item">
-                                    <a-input v-model:value="formModel.projectName" placeholder="请输入项目名称" />
-                                </a-form-item>
-                            </a-col>
-                        </a-row>
-                        <a-row class="smart-query-form-row">
-                            <a-col :span="12">
-                                <a-form-item label="项目等级" name="projectLevel" class="smart-query-form-item">
-                                    <DictSelect key-code="BL_PROJECT_LEVEL" v-model:value="formModel.projectLevel"
-                                        placeholder="请选择项目等级" width="100%" />
-                                </a-form-item>
-                            </a-col>
-                            <a-col :span="12">
-                                <a-form-item label="项目类型" name="projectType" class="smart-query-form-item">
-                                    <DictSelect key-code="BL_PROJECT_TYPE" v-model:value="formModel.projectType"
-                                        placeholder="请选择项目类型" width="100%" />
-                                </a-form-item>
-                            </a-col>
-                        </a-row>
-                        <a-row class="smart-query-form-row">
-                            <a-col :span="12">
-                                <a-form-item label="交付经理" name="deliveryManager" class="smart-query-form-item">
-                                    <a-input v-model:value="formModel.deliveryManager" placeholder="请选择交付经理"
-                                        @click="showSelectUser('deliveryManager')" readonly />
-                                </a-form-item>
-                                <EmployeeTableSelectModal ref="selectDeliveryManagerRef" type="radio"
-                                    @selectDataList="selectedUser('deliveryManager', $event)" />
-                            </a-col>
-                            <a-col :span="12">
-                                <a-form-item label="客户经理" name="accountManager" class="smart-query-form-item">
-                                    <a-input v-model:value="formModel.accountManager" placeholder="请选择客户经理"
-                                        @click="showSelectUser('accountManager')" readonly />
-                                </a-form-item>
-                                <EmployeeTableSelectModal ref="selectAccountManagerRef" type="radio"
-                                    @selectDataList="selectedUser('accountManager', $event)" />
-                            </a-col>
-                        </a-row>
-                        <a-row class="smart-query-form-row">
-                            <a-col :span="24">
-                                <a-form-item label="成本构成模板" name="templateName" class="smart-query-form-item">
-                                    <a-input v-model:value="formModel.templateName" placeholder="请选择成本构成模板"
-                                        @click="showSelectTemplate" />
-                                </a-form-item>
-                                <SelectModal ref="TemplateSelectModalRef" @selectedRowList="templateSelectedRowList"
-                                    :modalTableCondition="templateCondition" v-bind="attrs" />
-                            </a-col>
-                        </a-row>
-                        <a-row class="smart-query-form-row">
-                            <a-col :span="24">
-                                <a-form-item label="合同签订状态" name="contractStatus" class="smart-query-form-item">
-                                    <DictSelect key-code="BL_CONTRACT_STATUS" v-model:value="formModel.contractStatus"
-                                        placeholder="请输入合同签订状态" width="100%" mode="" />
-                                </a-form-item>
-                            </a-col>
-                        </a-row>
-                        <template v-if="formModel.contractStatus.includes(CONTRACT_STATUS_ENUM.SIGNED.value)">
-                            <a-row class="smart-query-form-row">
-                                <a-col :span="12">
-                                    <a-form-item label="关联合同" name="contractName" class="smart-query-form-item">
-                                        <a-input v-model:value="formModel.contractName" placeholder="关联合同"
-                                            @click="showSelectContract" />
-                                    </a-form-item>
-                                    <SelectModal ref="ContractSelectModalRef" @selectedRowList="contractSelectedRowList"
-                                        :modalTableCondition="contractCondition" v-bind="attrs" />
-                                </a-col>
-                                <a-col :span="12">
-                                    <a-form-item label="客户名称" name="supplierName" class="smart-query-form-item">
-                                        <a-input v-model:value="formModel.supplierName" placeholder="客户名称" disabled />
-                                    </a-form-item>
-                                </a-col>
-                            </a-row>
-                            <a-row class="smart-query-form-row">
-                                <a-col :span="12">
-                                    <a-form-item label="签约主体" name="signingParty" class="smart-query-form-item">
-                                        <a-input v-model:value="formModel.signingParty" placeholder="签约主体" disabled />
-                                    </a-form-item>
-                                </a-col>
-                                <a-col :span="12">
-                                    <a-form-item label="合同含税金额" name="taxAmount" class="smart-query-form-item">
-                                        <a-input-number v-model:value="formModel.taxAmount" placeholder="合同含税金额"
-                                            style="width: 100%" disabled />
-                                    </a-form-item>
-                                </a-col>
-                            </a-row>
-                            <a-row class="smart-query-form-row">
-                                <a-col :span="12">
-                                    <a-form-item label="税率" name="taxRate" class="smart-query-form-item">
-                                        <a-input-number v-model:value="formModel.taxRate" placeholder="税率" :min="0"
-                                            :max="100" :formatter="value => `${value}%`"
-                                            :parser="value => value.replace('%', '')" style="width: 100%" disabled />
-                                    </a-form-item>
-                                </a-col>
-                                <a-col :span="12">
-                                    <a-form-item label="合同约定进场日期" name="contractStartDate" class="smart-query-form-item"
-                                        :label-col="{ width: '130px' }">
-                                        <a-date-picker v-model:value="formModel.contractStartDate"
-                                            placeholder="合同约定进场日期" value-format="YYYY-MM-DD" style="width: 100%"
-                                            disabled />
-                                    </a-form-item>
-                                </a-col>
-                            </a-row>
-                            <a-row class="smart-query-form-row">
-                                <a-col :span="12">
-                                    <a-form-item label="合同约定验收日期" name="contractEndDate" class="smart-query-form-item"
-                                        :label-col="{ width: '130px' }">
-                                        <a-date-picker v-model:value="formModel.contractEndDate" placeholder="合同约定验收日期"
-                                            value-format="YYYY-MM-DD" style="width: 100%" disabled />
-                                    </a-form-item>
-                                </a-col>
-                                <a-col :span="12">
-                                    <a-form-item label="计划完工日期" name="planCompleteDate" class="smart-query-form-item"
-                                        :label-col="{ width: '130px' }">
-                                        <a-date-picker v-model:value="formModel.planCompleteDate" placeholder="计划完工日期"
-                                            value-format="YYYY-MM-DD" style="width: 100%" />
-                                    </a-form-item>
-                                </a-col>
-                            </a-row>
-                        </template>
-                    </div>
-                    <div v-if="current == 1">
-                        <a-table size="small" :pagination="false" bordered :dataSource="formModel.projectStageVOList"
-                            :columns="columns">
-                            <template #bodyCell="{ column, index }">
-                                <template v-if="column.dataIndex === 'stageDate'">
-                                    <a-form-item :name="['projectStageVOList', index, column.dataIndex]"
-                                        class="smart-query-form-item"
-                                        :rules="[{ required: true, message: '请选择阶段日期', trigger: 'blur' }]">
-                                        <a-date-picker
-                                            v-model:value="formModel['projectStageVOList'][index][column.dataIndex]"
-                                            value-format="YYYY-MM-DD" style="width: 100%" />
-                                    </a-form-item>
-                                </template>
-                            </template>
-                        </a-table>
-                    </div>
-                    <div v-if="current == 2">
-                        <a-row :gutter="16" class="smart-query-form-row">
-                            <a-col :span="12">
-                                <a-form-item label="基准工时" name="baseManHours" class="smart-query-form-item">
-                                    <a-input v-model:value="formModel.baseManHours" placeholder="请输入基准工时" />
-                                </a-form-item>
-                            </a-col>
-                            <a-col :span="12">
-                                <a-form-item label="基准人工成本" name="baseLaborCost" class="smart-query-form-item">
-                                    <a-input v-model:value="formModel.baseLaborCost" placeholder="请输入基准人工成本" />
-                                </a-form-item>
-                            </a-col>
-                        </a-row>
-                        <a-row :gutter="16" class="smart-query-form-row">
-                            <a-col :span="12">
-                                <a-form-item label="基准费用成本" name="baseExpenseCost" class="smart-query-form-item">
-                                    <a-input v-model:value="formModel.baseExpenseCost" placeholder="请输入基准费用成本" />
-                                </a-form-item>
-                            </a-col>
-                            <a-col :span="12">
-                                <a-form-item label="基准总成本" name="baseTotalCost" class="smart-query-form-item">
-                                    <a-input v-model:value="formModel.baseTotalCost" placeholder="请输入基准总成本" />
-                                </a-form-item>
-                            </a-col>
-                        </a-row>
-                    </div>
-                    <div v-if="current == 3">
-                        <a-row :gutter="16" class="smart-query-form-row">
-                            <a-col :span="12">
-                                <a-form-item label="省市区" name="provinceCityDistrict" class="smart-query-form-item">
-                                    <AreaCascader type="province_city_district" style="width: 100%"
-                                        v-model:value="provinceCityDistrict" placeholder="请选择省市区"
-                                        @change="changeArea" />
-                                </a-form-item>
-                            </a-col>
-                            <a-col :span="12">
-                                <a-form-item label="详细地址" name="specificAddress" class="smart-query-form-item">
-                                    <a-input v-model:value="formModel.specificAddress" placeholder="请输入详细地址" />
-                                </a-form-item>
-                            </a-col>
-                        </a-row>
-                        <a-row :gutter="16" class="smart-query-form-row">
-                            <a-col :span="12">
-                                <a-form-item label="创建日期" name="createDate" class="smart-query-form-item">
-                                    <a-date-picker v-model:value="formModel.createDate" placeholder="创建日期"
-                                        value-format="YYYY-MM-DD" style="width: 100%" disabled />
-                                </a-form-item>
-                            </a-col>
-                            <a-col :span="12">
-                                <a-form-item label="创建人" name="creator" class="smart-query-form-item">
-                                    <a-input v-model:value="formModel.creator" placeholder="请输入创建人" disabled />
-                                </a-form-item>
-                            </a-col>
-                        </a-row>
-                        <a-row :gutter="16" class="smart-query-form-row">
-                            <a-col :span="24">
-                                <a-form-item label="项目描述" name="projectDescription" class="smart-query-form-item">
-                                    <a-textarea v-model:value="formModel.projectDescription" placeholder="请输入创建人"
-                                        :rows="4" :showCount="true" :allowClear="true" />
-                                </a-form-item>
-                            </a-col>
-                        </a-row>
-                    </div>
-                </a-form>
-            </div>
-            <div class="steps-action">
-                <a-button v-if="current > 0" style="margin-right: 8px" @click="prev">上一步</a-button>
-                <a-button v-if="current < steps.length - 1" type="primary" @click="next">下一步</a-button>
-                <a-button v-if="current == steps.length - 1" type="primary" @click="submit">
-                    提交
-                </a-button>
-            </div>
-        </div>
-    </a-card>
-</template>
-<script setup>
-import dayjs from 'dayjs';
-import { onMounted, reactive, ref, useAttrs } from 'vue';
-import { useRouter } from 'vue-router';
-import { message, Modal } from 'ant-design-vue';
-import _ from 'lodash';
-import DictSelect from '/@/components/support/dict-select/index.vue';
-import AreaCascader from '/@/components/framework/area-cascader/index.vue';
-import { CONTRACT_STATUS_ENUM } from '/@/constants/teamwork/project-approval-const';
-import EmployeeTableSelectModal from '/@/components/system/employee-table-select-modal/index.vue';
-import { useUserStore } from '/@/store/modules/system/user';
-import { projectApi } from '/@/api/teamwork/project/project-api';
-
-import SelectModal from "/@/components/common/table-select-modal/components/modal.vue";
-
-const stepFormRef = ref(null);
-const selectDeliveryManagerRef = ref(null);
-const selectAccountManagerRef = ref(null);
-const attrs = useAttrs();
-const TemplateSelectModalRef = ref(null);
-const ContractSelectModalRef = ref(null);
-const router = useRouter();
-const templateCondition = ref({
-    url: '/blProjectCost/template/queryPage',
-    search: [
-        {
-            label: '模板编码',
-            field: 'templateCode',
-            type: 'input',
-            width: '200px',
-        },
-        {
-            label: '模板名称',
-            field: 'templateName',
-            type: 'input',
-            width: '200px',
-        },
-    ],
-    tableAttrs: {
-        rowKey: 'id',
-        columns: [
-            {
-                title: '模板编码',
-                dataIndex: 'templateCode',
-            },
-            {
-                title: '模板名称',
-                dataIndex: 'templateName',
-            },
-            {
-                title: '模板类型',
-                dataIndex: 'templateType',
-            },
-            {
-                title: '创建人',
-                dataIndex: 'createUserId',
-            },
-            {
-                title: '创建日期',
-                dataIndex: 'createTime',
-            },
-        ],
-    },
-});
-const contractCondition = ref({
-    url: '/blContractMaster/queryPage',
-    search: [
-        {
-            label: '合同编码',
-            field: 'contractCode',
-            type: 'input',
-            width: '200px',
-        },
-        {
-            label: '合同名称',
-            field: 'contractName',
-            type: 'input',
-            width: '200px',
-        },
-    ],
-    tableAttrs: {
-        rowKey: 'id',
-        columns: [
-            {
-                title: '合同编码',
-                dataIndex: 'contractCode',
-            },
-            {
-                title: '合同名称',
-                dataIndex: 'contractName',
-            },
-            {
-                title: '合同类型',
-                dataIndex: 'contractType',
-            },
-            {
-                title: '合同状态',
-                dataIndex: 'contractStatus',
-            },
-            {
-                title: '签约单位',
-                dataIndex: 'signingParty',
-            },
-            {
-                title: '合同金额',
-                dataIndex: 'txAmount',
-            },
-        ],
-    },
-});
-
-function templateShowModal(selectedRowKey) {
-    TemplateSelectModalRef.value.showModal(selectedRowKey);
-}
-function contractShowModal(selectedRowKey) {
-    ContractSelectModalRef.value.showModal(selectedRowKey);
-}
-
-function showSelectUser(type) {
-    if (type === 'deliveryManager') {
-        selectDeliveryManagerRef.value.showModal();
-    } else if (type === 'accountManager') {
-        selectAccountManagerRef.value.showModal();
-    }
-};
-
-function selectedUser(field, list) {
-    // console.log('selectedUser', field, list);
-    formModel[field] = list[0].actualName;
-};
-
-function changeArea(value, selectedOptions) {
-    formModel.provinceCityDistrict = value;
+.data-management {
+  height: 100%;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  gap: 20px;
+
+  .data-management-item {
+    flex: 1;
+    align-self: stretch;
+  }
+
+  &:deep(.data-item1) {
+    background: url('/@/assets/images/home/data-mana/data-mana1.svg') no-repeat center;
+    background-size: contain;
+  }
+  &:deep(.data-item2) {
+    background: url('/@/assets/images/home/data-mana/data-mana2.svg') no-repeat center;
+    background-size: contain;
+  }
+  &:deep(.data-item3) {
+    background: url('/@/assets/images/home/data-mana/data-mana3.svg') no-repeat center;
+    background-size: contain;
+  }
+  &:deep(.data-item4) {
+    background: url('/@/assets/images/home/data-mana/data-mana4.svg') no-repeat center;
+    background-size: contain;
+  }
+  &:deep(.data-item5) {
+    background: url('/@/assets/images/home/data-mana/data-mana5.svg') no-repeat center;
+    background-size: contain;
+  }
 }
 
-// --------------------- 数据 ---------------------
-const formModel = reactive({
-    projectTemplateId: [], // 项目模板
-    projectCode: undefined, // 项目编号
-    projectName: undefined, // 项目名称
-    projectLevel: [], // 项目等级
-    projectType: [], // 项目类型
-    deliveryManager: undefined, // 交付经理
-    accountManager: undefined, // 客户经理
-    templateName: undefined, // 成本构成模板
-    costTemplateId: undefined, // 成本构成模板id --不展示
-    contractStatus: [], // 合同签订状态
-    contactId: undefined, // 合同id --不展示
-    supplierName: undefined, // 客户名称
-    signingParty: undefined, // 签约主体
-    contractName: undefined, // 关联合同
-    taxAmount: undefined, // 合同含税金额
-    taxRate: undefined, // 税率
-    contractStartDate: undefined, // 合同约定进场日期
-    contractEndDate: undefined, // 合同约定验收日期
-    planCompleteDate: undefined, // 计划完工日期
-    baseManHours: undefined, // 基准工时
-    baseLaborCost: undefined, // 基准人工成本
-    baseExpenseCost: undefined, // 基准费用成本
-    baseTotalCost: undefined, // 基准总成本
-
-    projectStageVOList: [
-        {
-            stageId: '1',
-            stageName: '项目启动(0)',
-            stageDate: undefined,
-            duration: '1',
-        },
-        {
-            stageId: '2',
-            stageName: '项目策划(0~20)',
-            stageDate: undefined,
-            duration: '32',
-        },
-        {
-            stageId: '3',
-            stageName: '项目前期(20~30)',
-            stageDate: undefined,
-            duration: '83',
-        },
-        {
-            stageId: '4',
-            stageName: '项目中期(30~50)',
-            stageDate: undefined,
-            duration: '265',
-        },
-        {
-            stageId: '5',
-            stageName: '项目后期(50~70)',
-            stageDate: undefined,
-            duration: '327',
-        },
-        {
-            stageId: '6',
-            stageName: '竣前筹备(70~90)',
-            stageDate: undefined,
-            duration: '388',
-        },
-        {
-            stageId: '7',
-            stageName: '竣工管理(100)',
-            stageDate: undefined,
-            duration: '432',
-        },
-    ],
-
-    // province: undefined, // 省
-    // city: undefined, // 市
-    // district: undefined, // 区
-    provinceCityDistrict: undefined, // 省市区
-
-    specificAddress: undefined, // 详细地址
-    projectDescription: undefined, // 项目描述
-
-    createDate: dayjs().format('YYYY-MM-DD'), // 创建日期 --不传后端
-    creator: useUserStore().actualName, // 创建人 --不传后端
-});
-
-// --------------------- 校验规则 ---------------------
-const formRules = {
-    // 第一步
-    projectTemplateId: [{ required: true, message: '请选择项目模板', trigger: 'change' }],
-    // projectCode: [{ required: true, message: '请输入项目编号', trigger: 'change' }],
-    projectName: [{ required: true, message: '请输入项目名称', trigger: 'change' }],
-    projectLevel: [{ required: true, message: '请选择项目等级', trigger: 'change' }],
-    projectType: [{ required: true, message: '请选择项目类型', trigger: 'change' }],
-    deliveryManager: [{ required: true, message: '请选择交付经理', trigger: 'change' }],
-    accountManager: [{ required: true, message: '请选择客户经理', trigger: 'change' }],
-    templateName: [{ required: true, message: '请选择成本构成模板', trigger: 'change' }],
-    // costTemplateId: [{ required: true, message: '请选择成本构成模板', trigger: 'change' }],
-    contractStatus: [{ required: true, message: '请选择合同签订状态', trigger: 'change' }],
-
-    // 合同签订状态-已签约-> 自动带出
-    // contractName: [{ required: true, message: '请选择关联合同', trigger: 'change' }],
-    // contractId: [{ required: true, message: '请选择关联合同', trigger: 'change' }],
-    // supplierName: [{ required: true, message: '请选择客户名称', trigger: 'change' }],
-    // signingParty: [{ required: true, message: '请选择签约主体', trigger: 'change' }],
-    // taxAmount: [{ required: true, message: '请输入合同含税金额', trigger: 'change' }],
-    // taxRate: [{ required: true, message: '请输入税率', trigger: 'change' }],
-    // contractStartDate: [{ required: true, message: '请选择合同约定进场日期', trigger: 'change' }],
-    // contractEndDate: [{ required: true, message: '请选择合同约定验收日期', trigger: 'change' }],
-    // planCompleteDate: [{ required: true, message: '请选择计划完工日期', trigger: 'change' }],
-
-    // 第二步
-    // 'projectStageVOList.stageDate': [{ required: true, message: '请选择阶段日期', trigger: 'change' }],
-
-    // 第三步
-    baseManHours: [{ required: true, message: '请输入基准工时', trigger: 'change' }],
-    baseLaborCost: [{ required: true, message: '请输入基准人工成本', trigger: 'change' }],
-    baseExpenseCost: [{ required: true, message: '请输入基准费用成本', trigger: 'change' }],
-    baseTotalCost: [{ required: true, message: '请输入基准总成本', trigger: 'change' }],
-
-    // 第四步
-    // province: [{ required: true, message: '请选择省', trigger: 'change' }],
-    // city: [{ required: true, message: '请选择市', trigger: 'change' }],
-    // district: [{ required: true, message: '请选择区', trigger: 'change' }],
-    provinceCityDistrict: [{ required: true, message: '请选择省市区', trigger: 'change' }],
-    specificAddress: [{ required: true, message: '请输入详细地址', trigger: 'change' }],
-    projectDescription: [{ required: true, message: '请输入项目描述', trigger: 'change' }],
-};
+.process-management-item {
+  flex: 1;
 
-// --------------------- 配置 ---------------------
-const columns = [
-    // { //  隐藏
-    //     title: '阶段Id',
-    //     dataIndex: 'stageId',
-    //     key: 'stageId',
-    // },
-    {
-        title: '项目阶段',
-        dataIndex: 'stageName',
-        key: 'stageName',
-    },
-    {
-        title: '阶段周期',
-        dataIndex: 'stageDate',
-        key: 'stageDate',
-    },
-    {
-        title: '周期(天)',
-        dataIndex: 'duration',
-        key: 'duration',
-    },
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  cursor: pointer;
 
-];
-
-const labelCol = { style: { width: '120px' } };
-
-// -------------------- 步骤相关 --------------------
-const current = ref(0);
-
-const next = () => {
-    stepFormRef.value.validateFields().then((values) => {
-        current.value++;
-    }).catch((error) => {
-        console.log('step1_error', error);
-    });
-
-    if (current.value === 0) {
-        const validateFiledList = ['projectTemplateId', 'projectName', 'projectLevel', 'projectType', 'deliveryManager',
-            'accountManager', 'templateName', 'contractStatus'];
-        stepFormRef.value.validateFields(validateFiledList).then((values) => {
-            current.value++;
-        }).catch((error) => {
-            console.log('step0_error', error);
-        });
-    } else if (current.value === 1) {
-        const filedList = ['stageDate'];
-        const validateFiledList = formModel.projectStageVOList.map((_, index) => {
-            return filedList.map((filed) => ['projectStageVOList', index, filed]);
-        }).flat();
-        stepFormRef.value.validateFields(validateFiledList).then((values) => {
-            current.value++;
-        }).catch((error) => {
-            console.log('step1_error', error);
-        });
-    } else if (current.value === 2) {
-        const validateFiledList = ['baseManHours', 'baseLaborCost', 'baseExpenseCost', 'baseTotalCost'];
-        stepFormRef.value.validateFields(validateFiledList).then((values) => {
-            current.value++;
-        }).catch((error) => {
-            console.log('step2_error', error);
-        });
-    } else if (current.value === 3) {
+  &:hover {
+    box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
+    & .process-item-icon img {
+      transform: scale(1.1);
     }
-};
-
-const prev = () => {
-    current.value--;
-};
-
-const submit = () => {
-    Modal.confirm({
-        title: '提示',
-        content: '确定要提交吗?',
-        okText: '确认',
-        onOk() {
-            postFormData();
-        },
-        cancelText: '取消',
-        onCancel() { },
-    });
+  }
+  
+  .process-item-icon {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    transform: translateY(-10%);
+    img {
+      width: 88%;
+      height: 88%;
+      transition: transform 0.3s;
+      
+    }
+  }
+
+  .process-item-text {
+    font-size: 14px;
+    color: #1d2129;
+    font-weight: 500;
+    transform: translateY(-140%);
+    position: relative;
+
+    &::after {
+      position: absolute;
+      top: -66%;
+      right: -30%;
+      content: '→';
+      display: block;
+      color: #86909c;
+      margin-top: 10px;
+    }
+  }
 }
 
-const postFormData = () => {
-    stepFormRef.value.validateFields().then((values) => {
-        projectApi.submitProjectApproval(formModel).then((res) => {
-            message.success('提交成功');
-            router.push({ path: '/teamwork/project-manage' });
-        })
-    }).catch((error) => {
-        console.log('step1_error', error);
-    });
+&:deep(.process-item1) {
+  background: url('/@/assets/images/home/process-mana/process-bg.svg') no-repeat center;
+  background-size: contain;
+}
+&:deep(.process-item2) {
+  background: url('/@/assets/images/home/process-mana/process-bg.svg') no-repeat center;
+  background-size: contain;
+}
+&:deep(.process-item3) {
+  background: url('/@/assets/images/home/process-mana/process-bg.svg') no-repeat center;
+  background-size: contain;
+}
+&:deep(.process-item4) {
+  background: url('/@/assets/images/home/process-mana/process-bg.svg') no-repeat center;
+  background-size: contain;
 }
 
-const steps = [
-    {
-        title: '填写基本信息',
-        content: 'First-content',
-    },
-    {
-        title: '填写节点信息',
-        content: 'Second-content',
-    },
-    {
-        title: '填写基准成本',
-        content: 'Last-content',
-    },
-    {
-        title: '填写其他信息',
-        content: 'Last-content',
-    },
-];
-const items = steps.map(item => ({
-    key: item.title,
-    title: item.title,
-}));
-
-function showSelectTemplate() {
-    templateShowModal()
-};
-function showSelectContract() {
-    contractShowModal()
-};
-
-function templateSelectedRowList(selectedRowList = {}) {
-    formModel.costTemplateId = selectedRowList.id;
-    formModel.templateName = selectedRowList.templateName;
-};
-function contractSelectedRowList(selectedRowList = {}) {
-    formModel.contactId = selectedRowList.id;
-    formModel.contractName = selectedRowList.contractName;
-    formModel.supplierName = selectedRowList.customName;
-    formModel.signingParty = selectedRowList.signingParty;
-    formModel.taxAmount = selectedRowList.taxAmount;
-    formModel.taxRate = selectedRowList.taxRate;
-    formModel.contractStartDate = selectedRowList.contractStartDate;
-    formModel.contractEndDate = selectedRowList.contractEndDate;
-    // formModel.planCompleteDate = selectedRowList.planCompleteDate;
-};
-
-onMounted(() => {
-});
-</script>
-
-<style scoped lang="less">
-.approval-steps {
-    width: 850px;
-    margin: 0 auto;
-
-    .steps-content {
-        min-height: 150px;
-        margin-top: 20px;
-    }
-
-    .steps-action {
-        display: flex;
-        justify-content: center;
-        margin-top: 18px;
+.integration {
+  display: grid;
+  grid-template-columns: repeat(5, 1fr);
+  row-gap: 14px;
+
+  .integration-item {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+
+    .integration-item-box {
+      display: flex;
+      flex-direction: column;
+      justify-content: center;
+      align-items: center;
+      row-gap: 6px;
+      cursor: pointer;
+
+      .integration-item-icon {
+        img {
+          width: 40px;
+          height: 40px;
+        }
+      }
+
+      .integration-item-text {
+        font-size: 14px;
+        color: #4e5969;
+        font-weight: 400;
+      }
+
+      &:hover {
+        .integration-item-icon {
+          img {
+            transform: scale(1.1);
+          }
+        }
+        .integration-item-text {
+          color: #1d2129;
+          text-decoration: underline;
+        }
+      }
     }
+  }
 }
-</style>

+ 229 - 616
src/views/system/home/index.vue

@@ -1,628 +1,241 @@
+<!--
+  * 首页
+  * 
+  * @Author:    BoundLink 
+  * @Date:      2022-09-12 22:34:00 
+  *
+-->
 <template>
-  <div class="home-container" ref="rootRef">
-    <div class="content">
-      <div class="main-left">
-        <div class="slogan">
-          <span>独立</span>
-          <span class="dot">·</span>
-          <span>科学</span>
-          <span class="dot">·</span>
-          <span>公正</span>
-        </div>
-        <img class="bg" :src="bgIcon" />
-        <img class="move1" :src="Icon" alt="" @click="goLink('/agent-construction/home')" />
-        <img class="move2" :src="Icon1" alt="" @click="goLink('/government-entrusted/home')" />
-        <div class="main1 move3">行政事务管理</div>
-        <div class="main1 move4">人事管理</div>
-        <div class="main1 move5">财务管理</div>
-        <div class="main1 move6">课题研究</div>
-        <div class="main1 move7">党建事务管理</div>
-        <div class="main1 move8">资产管理</div>
-        <div class="main1 move9">档案管理</div>
-        <div class="main1 move9">档案管理</div>
-        <div class="main1 move10">知识管理</div>
-        <div class="main2 move11" @click="goLink('/market-manage/home')">
-          <img class="arrow" :src="Arrow" alt="" />
-          <span>市场管理</span>
-          <img style="transform: rotate(180deg)" class="arrow" :src="Arrow" alt="" />
-        </div>
-        <div class="main2 move12" @click="goLink('/pundit/home')">
-          <img class="arrow" :src="Arrow" alt="" />
-          <span>专家库</span>
-          <img style="transform: rotate(180deg)" class="arrow" :src="Arrow" alt="" />
-        </div>
-      </div>
-      <div class="main-right">
-        <div class="task-box">
-          <span class="task-title">任务中心</span>
-          <div class="task-content">
-            <div class="task-item">
-              <img class="task-icon" :src="Icon9" />
-              <span class="task-name">待办任务</span>
-              <span class="task-num">20</span>
-            </div>
-            <div class="task-item">
-              <img class="task-icon" :src="Icon10" />
-              <span class="task-name">待审批流程</span>
-              <span class="task-num">20</span>
-            </div>
-            <div class="task-item">
-              <img class="task-icon" :src="Icon11" />
-              <span class="task-name">传阅流程</span>
-              <span class="task-num">20</span>
-            </div>
-            <div class="task-item">
-              <img class="task-icon" :src="Icon12" />
-              <span class="task-name">已办流程</span>
-              <span class="task-num">20</span>
-            </div>
-            <div class="task-item">
-              <img class="task-icon" :src="Icon13" />
-              <span class="task-name">集团通知</span>
-              <span class="task-num">20</span>
-            </div>
-            <div class="task-item">
-              <img class="task-icon" :src="Icon14" />
-              <span class="task-name">奖罚通知</span>
-              <span class="task-num">20</span>
-            </div>
-          </div>
-        </div>
-        <div class="notice-box">
-          <div class="notice-banner">
-            <div class="notice-title">
-              <span class="notice-title-name">通知公告</span>
-              <div class="notice-title-num">99+</div>
-            </div>
-            <span class="notice-more">查看更多</span>
-          </div>
-          <div class="notice-content" v-for="i in 15">
-            <div class="notice-item-box">
-              <div class="notice-item">院内通知-内控系统优化升级计划通知-2024年12月</div>
-              <span>11-22</span>
-            </div>
-            <div class="notice-line"></div>
-          </div>
-        </div>
-      </div>
-    </div>
-    <div class="bottom">
-      <span class="bottom-title">常用功能</span>
-      <div class="bottom-content">
-        <div class="bottom-item" v-for="(item, index) in bottomList" :key="index" @click="goLink(item.link)">
-          <img :src="item.iconPath" alt="" />
-          <span>{{ item.name }}</span>
-        </div>
-      </div>
-    </div>
-  </div>
+  <!--  顶部用户信息-->
+  <a-row>
+    <HomeHeader />
+  </a-row>
+  <!--第二排卡片布局-->
+  <a-row :gutter="[10, 10]" style="margin-bottom: 10px">
+    <a-col :span="24">
+      <a-row :gutter="[10, 10]">
+        <!--待办任务-->
+        <a-col :span="6" :xs="24" :sm="24" :md="12" :lg="12" :xl="6">
+          <ToBeDoneCard :cardInfo="cardConfigLine1[0]" />
+        </a-col>
+        <!--平台预警-->
+        <a-col :span="6" :xs="24" :sm="24" :md="12" :lg="12" :xl="6">
+          <ToBeDoneCard :cardInfo="cardConfigLine1[1]" />
+        </a-col>
+        <!--审批流程-->
+        <a-col :span="6" :xs="24" :sm="24" :md="12" :lg="12" :xl="6">
+          <ToBeDoneCard :cardInfo="cardConfigLine1[2]" />
+        </a-col>
+        <!-- 消息提醒 -->
+        <a-col :span="6" :xs="24" :sm="24" :md="12" :lg="12" :xl="6">
+          <ToBeDoneCard :cardInfo="cardConfigLine1[3]" />
+        </a-col>
+      </a-row>
+    </a-col>
+  </a-row>
+  <!--第三排卡片布局-->
+  <a-row :gutter="[10, 10]" style="margin-bottom: 10px">
+    <a-col :span="24">
+      <a-row :gutter="[10, 10]">
+        <!--通知公告-->
+        <a-col :span="8" :xs="24" :sm="24" :md="24" :lg="24" :xl="8">
+          <ToBeDoneCard :cardInfo="cardConfigLine2[0]" />
+        </a-col>
+        <!--数据化管理-->
+        <a-col :span="16" :xs="24" :sm="24" :md="24" :lg="24" :xl="16">
+          <HomeShowCard title="数据化管理">
+            <template #default>
+              <div class="data-management">
+                <div class="data-management-item data-item1"></div>
+                <div class="data-management-item data-item2"></div>
+                <div class="data-management-item data-item3"></div>
+                <div class="data-management-item data-item4"></div>
+                <div class="data-management-item data-item5"></div>
+              </div>
+            </template>
+          </HomeShowCard>
+        </a-col>
+      </a-row>
+    </a-col>
+  </a-row>
 </template>
 <script setup>
-// 中心-back---------------------------------------------------------------
-import bgIcon from '/@/assets/images/home/bg.svg';
-import Arrow from '/@/assets/images/home/arrow.svg';
-import Icon from '/@/assets/images/home/dj.png';
-import Icon1 from '/@/assets/images/home/wt.png';
-import Icon2 from '/@/assets/images/home/icon2.svg';
-import Icon3 from '/@/assets/images/home/icon3.svg';
-import Icon4 from '/@/assets/images/home/icon4.svg';
-// 底部-icon---------------------------------------------------------------
-import Icon5 from '/@/assets/images/home/icon5.svg';
-import Icon6 from '/@/assets/images/home/icon6.svg';
-import Icon7 from '/@/assets/images/home/icon7.svg';
-import Icon8 from '/@/assets/images/home/icon8.svg';
-// 任务-icon---------------------------------------------------------------
-import Icon9 from '/@/assets/images/home/icon9.svg';
-import Icon10 from '/@/assets/images/home/icon10.svg';
-import Icon11 from '/@/assets/images/home/icon11.svg';
-import Icon12 from '/@/assets/images/home/icon12.svg';
-import Icon13 from '/@/assets/images/home/icon13.svg';
-import Icon14 from '/@/assets/images/home/icon14.svg';
-// ------------------------------------------------------------------------
-import { ref, onMounted, onUnmounted } from 'vue';
-import { useRouter } from 'vue-router';
-
-import { theme, message } from 'ant-design-vue';
-
-const bottomList = [
-  { name: '数据驾驶舱', iconPath: Icon2, link: '' },
-  { name: '费用报销', iconPath: Icon3, link: '' },
-  { name: '任务日历', iconPath: Icon4, link: '' },
-  { name: '加班申请', iconPath: Icon5, link: '' },
-  { name: '出差审批', iconPath: Icon6, link: '' },
-  { name: '报告管理', iconPath: Icon7, link: '' },
-  { name: '个人中心', iconPath: Icon8, link: '' },
-];
-
-const router = useRouter();
-function goLink(link) {
-  if (!link) {
-    message.warning('暂未开放');
-    return;
-  }
-  router.push({
-    path: link,
+  import { ref, onMounted } from 'vue';
+  import HomeHeader from './home-header.vue';
+  import ToBeDoneCard from './components/to-be-done-card/home-to-be-done.vue';
+  import HomeShowCard from './components/show-card/home-show-card.vue';
+  import { homeApi } from '/@/api/system/home-api';
+  import { theme } from 'ant-design-vue';
+
+  // 卡片icon
+  import dbrw from '/@/assets/images/home/card/card-dbrw.svg';
+  import ptyj from '/@/assets/images/home/card/card-ptyj.svg';
+  import splc from '/@/assets/images/home/card/card-splc.svg';
+  import xxtx from '/@/assets/images/home/card/card-xxtx.svg';
+
+  // 数据化管理
+  import Mana1Icon from '/@/assets/images/home/process-mana/process-mana1-icon.svg';
+  import Mana2Icon from '/@/assets/images/home/process-mana/process-mana2-icon.svg';
+  import Mana3Icon from '/@/assets/images/home/process-mana/process-mana3-icon.svg';
+  import Mana4Icon from '/@/assets/images/home/process-mana/process-mana4-icon.svg';
+
+  // 系统集成
+  import EPROS from '/@/assets/images/home/integration/EPROS.svg';
+  import BPM from '/@/assets/images/home/integration/BPM.svg';
+  import FR from '/@/assets/images/home/integration/FR.svg';
+  import ZB from '/@/assets/images/home/integration/ZB.svg';
+  import CW from '/@/assets/images/home/integration/CW.svg';
+  import SRM from '/@/assets/images/home/integration/SRM.svg';
+  import ZS from '/@/assets/images/home/integration/ZS.svg';
+
+  const cardConfigLine1 = ref([
+    {
+      icon: dbrw,
+      title: '待办任务',
+      total: 0,
+      totalColor: '#1D2129',
+      moreLink: '/process/todo-task',
+      divider: true,
+      list: [
+        // {
+        //   instance_name: '建筑工程、市政工程的设计与施工',
+        //   receive_time: '2025-09-12',
+        // },
+      ],
+    },
+    {
+      icon: ptyj,
+      title: '平台预警',
+      total: 0,
+      totalColor: '#F53F3F',
+      moreLink: '',
+      divider: true,
+      list: [],
+    },
+    {
+      icon: splc,
+      title: '审批流程',
+      total: 0,
+      totalColor: '#1D2129',
+      moreLink: '/process/done-task',
+      divider: true,
+      list: [
+        {
+          instance_name: '建筑工程、市政工程的设计与施工3',
+          receive_time: '2025-09-14',
+        },
+      ],
+    },
+    {
+      icon: xxtx,
+      title: '消息提醒',
+      total: 0,
+      totalColor: '#1D2129',
+      moreLink: '',
+      divider: true,
+      list: [],
+    },
+  ]);
+  const cardConfigLine2 = ref([
+    {
+      title: '通知公告',
+      moreLink: '',
+      list: [
+        // {
+        //   type: '公告',
+        //   instance_name: '建筑工程、市政工程的设计与施工',
+        //   receive_time: '2025-09-14',
+        // },
+        // {
+        //   type: '通知',
+        //   instance_name: '建筑工程、市政工程的设计与施工',
+        //   receive_time: '2025-09-14',
+        // },
+        // {
+        //   type: '通知',
+        //   instance_name: '建筑工程、市政工程的设计与施工',
+        //   receive_time: '2025-09-14',
+        // },
+        // {
+        //   type: '公告',
+        //   instance_name: '建筑工程、市政工程的设计与施工',
+        //   receive_time: '2025-09-14',
+        // },
+        // {
+        //   type: '通知',
+        //   instance_name: '建筑工程、市政工程的设计与施工',
+        //   receive_time: '2025-09-14',
+        // },
+      ],
+    },
+  ]);
+  const integrationConfig = ref([
+    {
+      title: 'EPROS',
+      icon: EPROS,
+    },
+    {
+      title: 'BPM',
+      icon: BPM,
+    },
+    {
+      title: '帆软',
+      icon: FR,
+    },
+    {
+      title: '指标管理',
+      icon: ZB,
+    },
+    {
+      title: '财务共享',
+      icon: CW,
+    },
+    {
+      title: 'SRM',
+      icon: SRM,
+    },
+    {
+      title: '知识中心',
+      icon: ZS,
+    },
+  ]);
+
+  onMounted(() => {
+    // 获取首页待办任务
+    homeApi.homeToDoTask().then((res) => {
+      Object.assign(cardConfigLine1.value[0], res.data);
+    });
+
+    // // 获取首页平台预警
+    // homeApi.homePlatformWarning().then((res) => {
+    //   console.log(res.data);
+    //   Object.assign(cardConfigLine1.value[1], res.data);
+    // });
+
+    // 获取首页审批流程
+    homeApi.homeApprovalProcess().then((res) => {
+      Object.assign(cardConfigLine1.value[2], res.data);
+    });
+
+    // // 获取首页消息提醒
+    // homeApi.homeMessageReminder().then((res) => {
+    //   console.log(res.data);
+    //   Object.assign(cardConfigLine1.value[3], res.data);
+    // });
   });
-}
-
-// ---------------- 适配屏幕缩放 ----------------
-const rootRef = ref(null);
 
-function reduceRatio() {
-  handleResize();
-  window.addEventListener('resize', handleResize);
-}
-
-function handleResize() {
-  const ratio = window.innerWidth / 1920;
-  rootRef.value.style.setProperty('--fitWidthRatio', ratio);
-}
-
-onMounted(() => {
-  reduceRatio();
-});
-
-onUnmounted(() => {
-  window.removeEventListener('resize', handleResize);
-});
+  const { useToken } = theme;
+  const { token } = useToken();
+  const borderRadius = token.value.borderRadius + 'px';
 </script>
-
 <style lang="less" scoped>
-.home-container {
-  --fitWidthRatio: 1; // 1920px
-  font-size: calc(var(--fitWidthRatio) * 16px); // 页面默认字体大小
-
-  display: grid;
-  grid-template-rows: 1fr auto;
-  width: 100%;
-  height: calc(100vh - 102px);
-
-  .content {
-    display: flex;
-    position: relative;
-    width: 100%;
-    gap: calc(var(--fitWidthRatio) * 10px);
-    min-height: calc(var(--fitWidthRatio) * 670px);
-
-    .main-left {
-      flex: 7.5;
-      background: #ffffff;
-      position: relative;
-      width: 100%;
-      border-radius: calc(var(--fitWidthRatio) * 8px);
-
-      .slogan {
-        position: absolute;
-        top: 3%;
-        left: 3%;
-        writing-mode: vertical-lr;
-        font-family: PingFang SC;
-        font-weight: 400;
-        font-size: calc(var(--fitWidthRatio) * 20px);
-        color: #f95555;
-        letter-spacing: calc(var(--fitWidthRatio) * 10px);
-
-        .dot {
-          margin: calc(var(--fitWidthRatio) * 10px) 0;
-        }
-      }
-
-      .bg {
-        position: absolute;
-        top: 9%;
-        width: 100%;
-        height: calc(var(--fitWidthRatio) * 600px);
-      }
-
-      .main1 {
-        cursor: pointer;
-        display: flex;
-        justify-content: center;
-        align-items: center;
-        border-radius: calc(var(--fitWidthRatio) * 20px);
-        border: calc(var(--fitWidthRatio) * 1px) solid #a4c1ff;
-        box-shadow: 0px 1px 2px 0px #e3e3e399;
-        background: #edf3ff;
-
-        font-family: Noto Sans SC;
-        font-size: calc(var(--fitWidthRatio) * 22px);
-        font-weight: 500;
-        color: #3676f7;
-      }
-
-      .main2 {
-        cursor: pointer;
-        display: flex;
-        justify-content: center;
-        align-items: center;
-        border: 1.5px solid #4482ff;
-        box-shadow: 0px 0px calc(var(--fitWidthRatio) * 14px) 0px #fdfeffcc inset;
-        width: calc(var(--fitWidthRatio) * 200px);
-        height: calc(var(--fitWidthRatio) * 57px);
-        border-radius: calc(var(--fitWidthRatio) * 8px);
-        background: #ffffff;
-
-        font-family: Noto Sans SC;
-        font-weight: 500;
-        font-size: calc(var(--fitWidthRatio) * 26px);
-        color: #165dff;
-
-        .arrow {
-          width: calc(var(--fitWidthRatio) * 20px);
-          height: calc(var(--fitWidthRatio) * 13px);
-        }
-
-        span {
-          margin: 0 calc(var(--fitWidthRatio) * 12px);
-        }
-      }
-
-      .main3 {
-        cursor: pointer;
-        display: flex;
-        justify-content: center;
-        align-items: center;
-        width: calc(var(--fitWidthRatio) * 130px);
-        height: calc(var(--fitWidthRatio) * 53px);
-        border-radius: calc(var(--fitWidthRatio) * 8px);
-        background: #ffffff;
-        border: 1.4px solid #1f72ed33;
-        box-shadow: 0px calc(var(--fitWidthRatio) * 7px) calc(var(--fitWidthRatio) * 16px) 0px #1f72ed1f;
-
-        font-family: Noto Sans SC;
-        font-size: calc(var(--fitWidthRatio) * 20px);
-        font-weight: 500;
-        color: #000000;
-      }
-
-      .box1 {
-        display: flex;
-        flex-wrap: wrap;
-        justify-content: center;
-        align-items: center;
-        gap: calc(var(--fitWidthRatio) * 8px);
-        border-radius: calc(var(--fitWidthRatio) * 8px);
-        border: 1px dashed #80a6fe;
-        padding: calc(var(--fitWidthRatio) * 10px) 0;
-      }
-
-      .move1 {
-        cursor: pointer;
-        position: absolute;
-        top: 59%;
-        left: 4.5%;
-        width: calc(var(--fitWidthRatio) * 174px);
-        height: calc(var(--fitWidthRatio) * 174px);
-      }
-
-      .move2 {
-        cursor: pointer;
-        position: absolute;
-        top: 18%;
-        left: 80.5%;
-        width: calc(var(--fitWidthRatio) * 174px);
-        height: calc(var(--fitWidthRatio) * 174px);
-      }
-
-      .move3 {
-        position: absolute;
-        top: 42%;
-        left: 1.5%;
-        width: calc(var(--fitWidthRatio) * 170px);
-        height: calc(var(--fitWidthRatio) * 50px);
-      }
-
-      .move4 {
-        position: absolute;
-        top: 24%;
-        left: 8%;
-        width: calc(var(--fitWidthRatio) * 170px);
-        height: calc(var(--fitWidthRatio) * 50px);
-      }
-
-      .move5 {
-        position: absolute;
-        top: 10%;
-        left: 22%;
-        width: calc(var(--fitWidthRatio) * 170px);
-        height: calc(var(--fitWidthRatio) * 50px);
-      }
-
-      .move6 {
-        position: absolute;
-        top: 5%;
-        left: 44%;
-        width: calc(var(--fitWidthRatio) * 170px);
-        height: calc(var(--fitWidthRatio) * 50px);
-      }
-
-      .move7 {
-        position: absolute;
-        top: 88%;
-        left: 44%;
-        width: calc(var(--fitWidthRatio) * 170px);
-        height: calc(var(--fitWidthRatio) * 50px);
-      }
-
-      .move8 {
-        position: absolute;
-        top: 83%;
-        left: 62%;
-        width: calc(var(--fitWidthRatio) * 170px);
-        height: calc(var(--fitWidthRatio) * 50px);
-      }
-
-      .move9 {
-        position: absolute;
-        top: 71%;
-        left: 77%;
-        width: calc(var(--fitWidthRatio) * 170px);
-        height: calc(var(--fitWidthRatio) * 50px);
-      }
+  @import './index.less';
 
-      .move10 {
-        position: absolute;
-        top: 56%;
-        left: 85%;
-        width: calc(var(--fitWidthRatio) * 170px);
-        height: calc(var(--fitWidthRatio) * 50px);
-      }
-
-      .move11 {
-        position: absolute;
-        top: 25.7%;
-        left: 49.8%;
-      }
-
-      .move12 {
-        position: absolute;
-        top: 74.5%;
-        left: 33.8%;
-      }
-
-      .move13 {
-        position: absolute;
-        top: 71%;
-        left: 69%;
-        width: calc(var(--fitWidthRatio) * 105px);
-        height: calc(var(--fitWidthRatio) * 45px);
-      }
-
-      .move14 {
-        position: absolute;
-        top: 71%;
-        left: 6.7%;
-        width: calc(var(--fitWidthRatio) * 300px);
-        height: calc(var(--fitWidthRatio) * 146px);
-      }
-
-      .move15 {
-        position: absolute;
-        top: 71%;
-        left: 27.7%;
-        width: calc(var(--fitWidthRatio) * 576px);
-        height: calc(var(--fitWidthRatio) * 146px);
-      }
-
-      .text1 {
-        position: absolute;
-        top: 43%;
-        left: 3%;
-        font-family: Noto Sans SC;
-        font-size: calc(var(--fitWidthRatio) * 20px);
-        font-weight: 500;
-        color: #2b69f8;
-      }
-
-      .text2 {
-        position: absolute;
-        top: 44%;
-        left: 13%;
-        font-family: Noto Sans SC;
-        font-size: calc(var(--fitWidthRatio) * 24px);
-        font-weight: 700;
-        color: #2b69f8;
-      }
-
-      .text3 {
-        display: flex;
-        flex-direction: column;
-        position: absolute;
-        top: 40%;
-        left: 43.4%;
-
-        font-family: Noto Sans SC;
-        font-size: calc(var(--fitWidthRatio) * 32px);
-        font-weight: 500;
-        color: #ffffff;
-      }
-
-      .text3:hover {
-        cursor: pointer;
-      }
-    }
-
-    .main-right {
-      overflow: hidden;
-      display: flex;
-      flex-direction: column;
-      gap: calc(var(--fitWidthRatio) * 10px);
-      flex: 2.5;
-
-      .task-box {
-        flex: 3;
-        padding: calc(var(--fitWidthRatio) * 26px);
-        background: #ffffff;
-        border-radius: calc(var(--fitWidthRatio) * 8px);
-
-        .task-title {
-          font-family: Noto Sans SC;
-          font-weight: 400;
-          font-size: calc(var(--fitWidthRatio) * 20px);
-          color: #000000;
-        }
-
-        .task-content {
-          display: flex;
-          flex-wrap: wrap;
-          margin-top: calc(var(--fitWidthRatio) * 30px);
-          row-gap: calc(var(--fitWidthRatio) * 28px);
-
-          .task-item {
-            display: flex;
-            flex-direction: column;
-            align-items: center;
-            width: calc(var(--fitWidthRatio) * 115px);
-
-            .task-icon {
-              width: calc(var(--fitWidthRatio) * 16px);
-              height: calc(var(--fitWidthRatio) * 16px);
-            }
-
-            .task-name {
-              font-family: Microsoft YaHei UI;
-              font-weight: 400;
-              font-size: calc(var(--fitWidthRatio) * 14px);
-              color: #000000e5;
-              margin-top: calc(var(--fitWidthRatio) * 10px);
-              margin-bottom: calc(var(--fitWidthRatio) * 3px);
-            }
-
-            .task-num {
-              font-family: Microsoft YaHei UI;
-              font-weight: 400;
-              font-size: calc(var(--fitWidthRatio) * 20px);
-              color: #2b69f8;
-            }
-          }
-        }
-      }
-
-      .notice-box {
-        padding: calc(var(--fitWidthRatio) * 26px);
-        flex: 7;
-        background: #ffffff;
-        border-radius: calc(var(--fitWidthRatio) * 8px);
-
-        .notice-banner {
-          display: flex;
-          justify-content: space-between;
-          align-items: center;
-
-          .notice-title {
-            display: flex;
-            align-items: center;
-
-            .notice-title-name {
-              font-family: Noto Sans SC;
-              font-weight: 400;
-              font-size: calc(var(--fitWidthRatio) * 20px);
-              color: #000000;
-              margin-right: calc(var(--fitWidthRatio) * 4px);
-            }
-
-            .notice-title-num {
-              display: flex;
-              justify-content: center;
-              align-items: center;
-              padding: 0 calc(var(--fitWidthRatio) * 4px);
-              // width: calc(var(--fitWidthRatio) * 35px);
-              height: calc(var(--fitWidthRatio) * 19px);
-              border-radius: calc(var(--fitWidthRatio) * 10px);
-              border: 1px solid #4174f5;
-              margin-top: calc(var(--fitWidthRatio) * 3px);
-              font-family: Noto Sans SC;
-              font-weight: 700;
-              font-size: calc(var(--fitWidthRatio) * 14px);
-              color: #3676f7;
-            }
-          }
-
-          .notice-more {
-            cursor: pointer;
-            font-family: Noto Sans SC;
-            font-weight: 700;
-            font-size: calc(var(--fitWidthRatio) * 14px);
-            color: #165dff;
-          }
-        }
-
-        .notice-content {
-          margin-top: calc(var(--fitWidthRatio) * 20px);
-
-          .notice-item-box {
-            display: flex;
-            justify-content: space-between;
-            align-items: center;
-
-            .notice-item {
-              width: 75%;
-              display: -webkit-box;
-              -webkit-box-orient: vertical;
-              -webkit-line-clamp: 1;
-              /* 限制显示两行 */
-              overflow: hidden;
-            }
-          }
-
-          .notice-line {
-            margin-top: calc(var(--fitWidthRatio) * 15px);
-            width: 100%;
-            height: 0.5px;
-            background: #4174f566;
-          }
-        }
-      }
-    }
+  .data-management-item {
+    border-radius: v-bind(borderRadius);
   }
 
-  .bottom {
-    display: flex;
-    flex-direction: column;
-    justify-content: space-between;
-    width: 100%;
-    height: calc(var(--fitWidthRatio) * 130px);
-    border-radius: calc(var(--fitWidthRatio) * 6px);
-    background: #ffffff;
-    margin-top: calc(var(--fitWidthRatio) * 10px);
-    padding: calc(var(--fitWidthRatio) * 14px) calc(var(--fitWidthRatio) * 30px);
-
-    .bottom-title {
-      font-family: Noto Sans SC;
-      font-size: calc(var(--fitWidthRatio) * 24px);
-      font-weight: 500;
-      color: #000000;
-    }
-
-    .bottom-content {
-      display: flex;
-      justify-content: space-between;
-      align-items: center;
-
-      .bottom-item {
-        cursor: pointer;
-        gap: 2px;
-        display: flex;
-        justify-content: center;
-        align-items: center;
-        width: calc(var(--fitWidthRatio) * 186px);
-        height: calc(var(--fitWidthRatio) * 66px);
-        border-radius: calc(var(--fitWidthRatio) * 8px);
-        background: linear-gradient(90.68deg, #ebf1fa 0.59%, rgba(235, 241, 251, 0) 174.75%), linear-gradient(0deg, #e9f2ff, #e9f2ff);
-
-        img {
-          width: calc(var(--fitWidthRatio) * 24px);
-          height: calc(var(--fitWidthRatio) * 24px);
-        }
-
-        span {
-          font-family: Noto Sans SC;
-          font-size: calc(var(--fitWidthRatio) * 20px);
-          font-weight: 500;
-          color: #000000;
-        }
-      }
-    }
+  .process-management-item {
+    border-radius: v-bind(borderRadius);
   }
-}
 </style>