zhangwencui
7 天以前 8a22c10dd6a1a635e44b97056efb6f5627b395e4
src/pages/index.vue
@@ -18,7 +18,7 @@
    <view class="hero-section">
      <view class="bg-img">
        <view class="hero-content">
          <text class="hero-title">海川开心食品</text>
          <text class="hero-title">军泰伟业</text>
        </view>
        <view class="hero-wave"></view>
      </view>
@@ -38,54 +38,54 @@
    <!--         </view>-->
    <!--      </view>-->
    <!-- 营销管理模块 -->
    <view class="common-module marketing-module">
      <view class="module-header">
        <view class="module-title-container">
          <text class="module-title">营销管理</text>
        </view>
      </view>
      <view class="module-content">
        <up-grid :border="false"
                 col="4">
          <up-grid-item v-for="(item, index) in marketingItems"
                        :key="index"
                        @click="handleCommonItemClick(item)">
            <view class="icon-container"
                  :style="{ background: item.bgColor }">
              <up-icon :name="item.icon"
                       :size="58"
                       color="#ffffff"></up-icon>
            </view>
            <text class="item-label">{{item.label}}</text>
          </up-grid-item>
        </up-grid>
      </view>
    </view>
    <!-- 采购管理模块 -->
    <view class="common-module purchase-module">
      <view class="module-header">
        <view class="module-title-container">
          <text class="module-title">采购管理</text>
        </view>
      </view>
      <view class="module-content">
        <up-grid :border="false"
                 col="4">
          <up-grid-item v-for="(item, index) in purchaseItems"
                        :key="index"
                        @click="handleCommonItemClick(item)">
            <view class="icon-container"
                  :style="{ background: item.bgColor }">
              <up-icon :name="item.icon"
                       :size="58"
                       color="#ffffff"></up-icon>
            </view>
            <text class="item-label">{{item.label}}</text>
          </up-grid-item>
        </up-grid>
      </view>
    </view>
    <!-- 协同办公模块 -->
    <!--    <view class="common-module marketing-module">-->
    <!--      <view class="module-header">-->
    <!--        <view class="module-title-container">-->
    <!--          <text class="module-title">营销管理</text>-->
    <!--        </view>-->
    <!--      </view>-->
    <!--      <view class="module-content">-->
    <!--        <up-grid :border="false"-->
    <!--                 col="4">-->
    <!--          <up-grid-item v-for="(item, index) in marketingItems"-->
    <!--                        :key="index"-->
    <!--                        @click="handleCommonItemClick(item)">-->
    <!--            <view class="icon-container"-->
    <!--                  :style="{ background: item.bgColor }">-->
    <!--              <up-icon :name="item.icon"-->
    <!--                       :size="58"-->
    <!--                       color="#ffffff"></up-icon>-->
    <!--            </view>-->
    <!--            <text class="item-label">{{item.label}}</text>-->
    <!--          </up-grid-item>-->
    <!--        </up-grid>-->
    <!--      </view>-->
    <!--    </view>-->
    <!--    &lt;!&ndash; 采购管理模块 &ndash;&gt;-->
    <!--    <view class="common-module purchase-module">-->
    <!--      <view class="module-header">-->
    <!--        <view class="module-title-container">-->
    <!--          <text class="module-title">采购管理</text>-->
    <!--        </view>-->
    <!--      </view>-->
    <!--      <view class="module-content">-->
    <!--        <up-grid :border="false"-->
    <!--                 col="4">-->
    <!--          <up-grid-item v-for="(item, index) in purchaseItems"-->
    <!--                        :key="index"-->
    <!--                        @click="handleCommonItemClick(item)">-->
    <!--            <view class="icon-container"-->
    <!--                  :style="{ background: item.bgColor }">-->
    <!--              <up-icon :name="item.icon"-->
    <!--                       :size="58"-->
    <!--                       color="#ffffff"></up-icon>-->
    <!--            </view>-->
    <!--            <text class="item-label">{{item.label}}</text>-->
    <!--          </up-grid-item>-->
    <!--        </up-grid>-->
    <!--      </view>-->
    <!--    </view>-->
    <!--    &lt;!&ndash; 协同办公模块 &ndash;&gt;-->
    <view class="common-module collaboration-module">
      <view class="module-header">
        <view class="module-title-container">
@@ -109,32 +109,37 @@
        </up-grid>
      </view>
    </view>
    <!-- 入库管理 -->
    <view class="common-module collaboration-module">
      <view class="module-header">
        <view class="module-title-container">
          <text class="module-title">仓储物流</text>
        </view>
      </view>
      <view class="module-content">
        <up-grid :border="false"
                 col="4">
          <up-grid-item v-for="(item, index) in inventoryManagement"
                        :key="index"
                        @click="handleCommonItemClick(item)">
            <view class="icon-container"
                  :style="{ background: item.bgColor }">
              <up-icon :name="item.icon"
                       :size="58"
                       color="#ffffff"></up-icon>
            </view>
            <text class="item-label">{{item.label}}</text>
          </up-grid-item>
        </up-grid>
      </view>
    </view>
    <!-- 生产管控模块 -->
    <view class="common-module production-module">
    <!--      <view class="common-module production-module">-->
    <!--         <view class="module-header">-->
    <!--            <view class="module-title-container">-->
    <!--               <text class="module-title">生产管控</text>-->
    <!--            </view>-->
    <!--         </view>-->
    <!--         <view class="module-content">-->
    <!--            <up-grid-->
    <!--               :border="false"-->
    <!--               col="4"-->
    <!--            >-->
    <!--               <up-grid-item-->
    <!--                  v-for="(item, index) in productionItems"-->
    <!--                  :key="index"-->
    <!--                  @click="handleCommonItemClick(item)"-->
    <!--               >-->
    <!--                  <view class="icon-container" :style="{ background: item.bgColor }">-->
    <!--                     <up-icon-->
    <!--                        :name="item.icon"-->
    <!--                        :size="58"-->
    <!--                        color="#ffffff"-->
    <!--                     ></up-icon>-->
    <!--                  </view>-->
    <!--                  <text class="item-label">{{item.label}}</text>-->
    <!--               </up-grid-item>-->
    <!--            </up-grid>-->
    <!--         </view>-->
    <!--      </view>-->
    <!-- 生产管控模块 -->
    <view class="common-module equipment-module">
      <view class="module-header">
        <view class="module-title-container">
          <text class="module-title">生产管控</text>
@@ -158,39 +163,38 @@
      </view>
    </view>
    <!-- 设备管理模块 -->
    <view class="common-module equipment-module">
      <view class="module-header">
        <view class="module-title-container">
          <text class="module-title">设备管理</text>
        </view>
      </view>
      <view class="module-content">
        <up-grid :border="false"
                 col="4">
          <up-grid-item v-for="(item, index) in equipmentItems"
                        :key="index"
                        @click="handleCommonItemClick(item)">
            <view class="icon-container"
                  :style="{ background: item.bgColor }">
              <up-icon :name="item.icon"
                       :size="58"
                       color="#ffffff"></up-icon>
            </view>
            <text class="item-label">{{item.label}}</text>
          </up-grid-item>
        </up-grid>
      </view>
    </view>
    <!--    <view class="common-module equipment-module">-->
    <!--      <view class="module-header">-->
    <!--        <view class="module-title-container">-->
    <!--          <text class="module-title">设备管理</text>-->
    <!--        </view>-->
    <!--      </view>-->
    <!--      <view class="module-content">-->
    <!--        <up-grid :border="false"-->
    <!--                 col="4">-->
    <!--          <up-grid-item v-for="(item, index) in equipmentItems"-->
    <!--                        :key="index"-->
    <!--                        @click="handleCommonItemClick(item)">-->
    <!--            <view class="icon-container"-->
    <!--                  :style="{ background: item.bgColor }">-->
    <!--              <up-icon :name="item.icon"-->
    <!--                       :size="58"-->
    <!--                       color="#ffffff"></up-icon>-->
    <!--            </view>-->
    <!--            <text class="item-label">{{item.label}}</text>-->
    <!--          </up-grid-item>-->
    <!--        </up-grid>-->
    <!--      </view>-->
    <!--    </view>-->
  </view>
</template>
<script setup>
  import { ref, onMounted, nextTick, reactive } from "vue";
  import dayjs from "dayjs";
  import { userLoginFacotryList, noticesList } from "@/api/login";
  import { userLoginFacotryList } from "@/api/login";
  import { getProductWorkOrderById } from "@/api/productionManagement/productionReporting";
  import modal from "@/plugins/modal";
  import useUserStore from "@/store/modules/user";
  import { onShow } from "@dcloudio/uni-app";
  const userStore = useUserStore();
  const factoryId = ref("");
@@ -287,6 +291,54 @@
      label: "出差管理",
    },
    {
      icon: "/static/images/icon/chuchaiguanli@2x.png",
      label: "报销管理",
    },
    {
      icon: "/static/images/icon/chuchaiguanli@2x.png",
      label: "采购管理",
    },
    {
      icon: "/static/images/icon/chuchaiguanli@2x.png",
      label: "报价管理",
    },
    {
      icon: "/static/images/icon/chuchaiguanli@2x.png",
      label: "出库管理",
    },
    {
      icon: "/static/images/icon/qingjiaguanli@2x.png",
      label: "会议设置",
    },
    {
      icon: "/static/images/icon/qingjiaguanli@2x.png",
      label: "会议列表",
    },
    {
      icon: "/static/images/icon/qingjiaguanli@2x.png",
      label: "会议申请",
    },
    {
      icon: "/static/images/icon/qingjiaguanli@2x.png",
      label: "会议审批",
    },
    {
      icon: "/static/images/icon/qingjiaguanli@2x.png",
      label: "会议发布",
    },
    {
      icon: "/static/images/icon/qingjiaguanli@2x.png",
      label: "会议总结",
    },
    {
      icon: "/static/images/icon/qingjiaguanli@2x.png",
      label: "会议看板",
    },
    {
      icon: "/static/images/icon/qingjiaguanli@2x.png",
      label: "通知公告",
    },
    {
      icon: "/static/images/icon/xietongshenpi@2x.png",
      label: "协同审批",
    },
@@ -294,58 +346,43 @@
      icon: "/static/images/icon/kehubaifang@2x.png",
      label: "客户拜访",
    },
    {
      icon: "/static/images/icon/qingjiaguanli@2x.png",
      label: "通知公告",
    },
  ]);
  // 协同办公功能数据inventoryManagement/receiptManagement
  const inventoryManagement = reactive([
    {
      icon: "/static/images/icon/rukuguanli@2x.png",
      label: "自定义入库",
    },
    {
      icon: "/static/images/icon/zidingyichuku.png",
      label: "自定义出库",
    },
  ]);
  // 生产管控功能数据
  const productionItems = reactive([
    {
      icon: "/static/images/icon/shengchandingdan@2x.png",
      label: "生产订单",
      bgColor: "#FF9800",
    },
    {
      icon: "/static/images/icon/shengchanpaigong@2x.png",
      label: "生产派工",
      bgColor: "#FF6B35",
    },
    {
      icon: "/static/images/icon/shengchanpaichan@2x.png",
      label: "工序排产",
      bgColor: "#E91E63",
    },
    // {
    //   icon: "/static/images/icon/shengchandingdan@2x.png",
    //   label: "生产订单",
    //   bgColor: "#FF9800",
    // },
    // {
    //   icon: "/static/images/icon/shengchanpaigong@2x.png",
    //   label: "生产派工",
    //   bgColor: "#FF6B35",
    // },
    // {
    //   icon: "/static/images/icon/shengchanpaichan@2x.png",
    //   label: "工序排产",
    //   bgColor: "#E91E63",
    // },
    {
      icon: "/static/images/icon/shengchanbaogong@2x.png",
      label: "生产报工",
      bgColor: "#673AB7",
    },
    {
      icon: "/static/images/icon/shengchanhesuan@2x.png",
      label: "生产核算",
      bgColor: "#3F51B5",
    },
    // {
    //   icon: "/static/images/icon/shengchanhesuan@2x.png",
    //   label: "生产核算",
    //   bgColor: "#3F51B5",
    // },
  ]);
  // 设备管理功能数据
  const equipmentItems = reactive([
    {
      icon: "/static/images/icon/shebeitaizhang@2x.png",
      label: "设备台账",
    },
    // {
    //    icon: '/static/images/icon/shebeitaizhang@2x.png',
    //    label: '设备台账',
    // },
    {
      icon: "/static/images/icon/shbeibaoxiu@2x.png",
      label: "设备报修",
@@ -358,26 +395,26 @@
      icon: "/static/images/icon/xunjianshangchuan@2x.png",
      label: "巡检上传",
    },
    // {
    //    icon: '/static/images/icon/guzhangfenxi@2x.png',
    //    label: '分析追溯',
    //    bgColor: '#ff9800'
    // },
    // {
    //    icon: '/static/images/icon/zhinengpaidan@2x.png',
    //    label: '智能派单',
    //    bgColor: '#ff6b35'
    // },
    // {
    //    icon: '/static/images/icon/zuoyezhidao@2x.png',
    //    label: '作业指导',
    //    bgColor: '#4caf50'
    // },
    // {
    //    icon: '/static/images/icon/jieguoyanzheng@2x.png',
    //    label: '结果验证',
    //    bgColor: '#9c27b0'
    // }
    {
      icon: "/static/images/icon/guzhangfenxi@2x.png",
      label: "分析追溯",
      bgColor: "#ff9800",
    },
    {
      icon: "/static/images/icon/zhinengpaidan@2x.png",
      label: "智能派单",
      bgColor: "#ff6b35",
    },
    {
      icon: "/static/images/icon/zuoyezhidao@2x.png",
      label: "作业指导",
      bgColor: "#4caf50",
    },
    {
      icon: "/static/images/icon/jieguoyanzheng@2x.png",
      label: "结果验证",
      bgColor: "#9c27b0",
    },
  ]);
  // 处理常用功能点击
@@ -459,6 +496,66 @@
          url: "/pages/cooperativeOffice/collaborativeApproval/index3",
        });
        break;
      case "报销管理":
        uni.navigateTo({
          url: "/pages/cooperativeOffice/collaborativeApproval/index4",
        });
        break;
      case "采购管理":
        uni.navigateTo({
          url: "/pages/cooperativeOffice/collaborativeApproval/index5",
        });
        break;
      case "报价管理":
        uni.navigateTo({
          url: "/pages/cooperativeOffice/collaborativeApproval/index6",
        });
        break;
      case "出库管理":
        uni.navigateTo({
          url: "/pages/cooperativeOffice/collaborativeApproval/index7",
        });
        break;
      case "会议设置":
        uni.navigateTo({
          url: "/pages/managementMeetings/meetingSettings/index",
        });
        break;
      case "会议列表":
        uni.navigateTo({
          url: "/pages/managementMeetings/meetingList/index",
        });
        break;
      case "会议申请":
        uni.navigateTo({
          url: "/pages/managementMeetings/meetApplication/index",
        });
        break;
      case "会议审批":
        uni.navigateTo({
          url: "/pages/managementMeetings/meetExamine/index",
        });
        break;
      case "会议发布":
        uni.navigateTo({
          url: "/pages/managementMeetings/meetPublish/index",
        });
        break;
      case "会议总结":
        uni.navigateTo({
          url: "/pages/managementMeetings/meetSummary/index",
        });
        break;
      case "会议看板":
        uni.navigateTo({
          url: "/pages/managementMeetings/meetingBoard/index",
        });
        break;
      case "通知公告":
        uni.navigateTo({
          url: "/pages/cooperativeOffice/noticeManagement/index",
        });
        break;
      case "协同审批":
        uni.navigateTo({
          url: "/pages/cooperativeOffice/collaborativeApproval/index",
@@ -467,21 +564,6 @@
      case "客户拜访":
        uni.navigateTo({
          url: "/pages/cooperativeOffice/clientVisit/index",
        });
        break;
      case "通知公告":
        uni.navigateTo({
          url: "/pages/cooperativeOffice/noticeManagement/index",
        });
        break;
      case "自定义入库":
        uni.navigateTo({
          url: "/pages/inventoryManagement/receiptManagement/index",
        });
        break;
      case "自定义出库":
        uni.navigateTo({
          url: "/pages/inventoryManagement/issueManagement/index",
        });
        break;
      case "生产订单":
@@ -496,18 +578,15 @@
        break;
      case "工序排产":
        uni.navigateTo({
          url: "/pages/productionManagement/operationScheduling/index",
          url: "/pages/productionManagement/processScheduling/index",
        });
        break;
      case "生产报工":
        getcode();
        // uni.navigateTo({
        //    url: '/pages/productionManagement/productionReporting/index'
        // });
        break;
      case "生产核算":
        uni.navigateTo({
          url: "/pages/productionManagement/productionCosting/index",
          url: "/pages/productionManagement/productionAccounting/index",
        });
        break;
      case "设备台账":
@@ -557,53 +636,12 @@
        });
    }
  };
  const getcode = () => {
    uni.scanCode({
      success: res => {
        // 解析二维码内容
        const scanResult = res.result;
        let orderRow = "";
        // 尝试从扫码结果中提取orderRow参数
        try {
          // 处理混合格式: http://...?orderRow={...}
          const orderRowStart = scanResult.indexOf("orderRow={");
          // 提取从orderRow={开始的JSON内容
          const jsonPart = scanResult.substring(orderRowStart + 9); // 9是"orderRow=".length
          // 尝试直接使用这个JSON部分
          orderRow = jsonPart;
        } catch (e) {
          orderRow = "";
        }
        try {
          JSON.parse(orderRow);
        } catch (error) {
          modal.msgError("订单解析失败");
          return;
        }
        // 扫码成功后跳转到生产报工页面,并传递orderRow参数
        uni.navigateTo({
          url: `/pages/productionManagement/productionReporting/index?orderRow=${orderRow}`,
        });
      },
      fail: err => {
        uni.showToast({
          title: "扫码失败",
          icon: "none",
        });
        // uni.navigateTo({
        //   url: `/pages/productionManagement/productionReporting/index`,
        // });
      },
    });
  };
  // 创建对子组件的引用
  const uToastRef = ref(null);
  function getUserLoginFacotryList() {
    userLoginFacotryList({
      userName: userStore.nickName,
    })
    userLoginFacotryList({ userName: userStore.nickName })
      .then(res => {
        // 检查res.data是否为数组
        factoryList.value[0] = [];
@@ -623,6 +661,92 @@
        factoryList.value = [];
      });
  }
  const getcode = () => {
    uni.scanCode({
      success: async res => {
        // 解析二维码内容
        const scanResult = res.result;
        let orderRow = "";
        // 判断扫描结果是否为纯数字(id)
        const isNumericId = /^\d+$/.test(scanResult.trim());
        if (isNumericId) {
          // 如果是纯数字,根据 id 获取工单数据
          const workOrderId = scanResult.trim();
          modal.loading("正在获取工单信息...");
          try {
            const workRes = await getProductWorkOrderById({ id: workOrderId });
            modal.closeLoading();
            console.log("工单查询结果:", workRes);
            if (workRes.code === 200 && workRes.data) {
              // 新接口返回的是单个对象,不是数组
              const workData = workRes.data;
              console.log("工单数据:", workData);
              orderRow = JSON.stringify({
                id: workData.id || workOrderId,
                planQuantity: workData.planQuantity - workData.completeQuantity,
                productProcessRouteItemId:
                  workData.productProcessRouteItemId ||
                  workData.产品工艺路线项ID ||
                  "",
              });
              console.log("构造的orderRow:", orderRow);
            } else {
              modal.msgError("未找到对应的工单信息");
              return;
            }
          } catch (error) {
            modal.closeLoading();
            console.error("获取工单信息失败:", error);
            modal.msgError("获取工单信息失败: " + (error.message || "未知错误"));
            return;
          }
        } else {
          // 如果不是纯数字,尝试从扫码结果中提取orderRow参数
          try {
            // 处理混合格式: http://...?orderRow={...}
            const orderRowStart = scanResult.indexOf("orderRow={");
            if (orderRowStart !== -1) {
              // 提取从orderRow={开始的JSON内容
              const jsonPart = scanResult.substring(orderRowStart + 9); // 9是"orderRow=".length
              orderRow = jsonPart;
            } else {
              // 如果直接是JSON字符串,尝试解析
              orderRow = scanResult;
            }
          } catch (e) {
            console.error(e, "解析失败====????=====");
            orderRow = "";
          }
          // 验证是否为有效的JSON
          try {
            JSON.parse(orderRow);
          } catch (error) {
            modal.msgError("订单解析失败,请检查二维码格式");
            return;
          }
        }
        console.log(orderRow, "orderRow======@@@@@@@@");
        // 扫码成功后跳转到生产报工页面,并传递orderRow参数
        uni.navigateTo({
          url: `/pages/productionManagement/productionReport/index?orderRow=${orderRow}`,
        });
      },
      fail: err => {
        uni.showToast({
          title: "扫码失败",
          icon: "none",
        });
      },
    });
  };
  const changeFactory = async arr => {
    show.value = false;
    const factoryId = factoryListTem.value[arr.indexs[0]].deptId;
@@ -644,7 +768,6 @@
        modal.closeLoading();
      });
  };
  function loginSuccess(result) {
    uni.reLaunch({
      url: "/pages/index",
@@ -657,68 +780,6 @@
      uToastRef.value.success(`点击了第${name + 1}个`); // 注意:这里加1是因为通常我们是从第1个开始计数的
    }
  };
  const isShowNoticesList = ref(true);
  // 获取公告数量
  const getNoticesList = () => {
    if (!isShowNoticesList.value) {
      return;
    }
    const current_date = dayjs().format("YYYY-MM-DD");
    noticesList({
      current: -1,
      size: -1,
      status: 1,
      current_date,
    })
      .then(resp => {
        console.log("noticesList", resp);
        if (
          resp.code != 200 ||
          !resp.data ||
          !resp.data.records ||
          !resp.data.records.length
        ) {
          return;
        }
        const res = uni.getAppAuthorizeSetting();
        if (res.notificationAuthorized == "denied") {
          uni.showModal({
            title: "提示",
            content: "请在设置中开启通知权限",
            success: res => {
              if (res.confirm) {
                uni.openAppAuthorizeSetting({
                  success: res => {},
                });
              } else {
                isShowNoticesList.value = false;
              }
            },
          });
          return;
        }
        resp.data.records.map(item => {
          createPushMessage(item.title);
        });
      })
      .catch(error => {
        modal.msgError("获取公告数量:", error);
      });
  };
  const createPushMessage = text => {
    uni.createPushMessage({
      title: "公告通知",
      content: text || "",
      success: resp => {
        console.log("success", resp);
        isShowNoticesList.value = false;
      },
      fail: resp => {
        console.log("fail", resp);
      },
    });
  };
  onMounted(() => {
    // 设置用户信息
@@ -727,10 +788,8 @@
    // 启动通知状态定时器
    startStatusTimer();
  });
  onShow(() => {
    getNoticesList();
  });
</script>
<style scoped lang="scss">
  .content {
@@ -880,12 +939,10 @@
    letter-spacing: 0.03125rem;
    text-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.5);
  }
  .hero-subtitle {
    font-size: 0.8125rem;
    margin-top: 0.375rem;
  }
  .hero-wave {
    height: 2.75rem;
  }
@@ -966,7 +1023,6 @@
    0% {
      transform: translateX(-100%) translateY(-100%) rotate(45deg);
    }
    100% {
      transform: translateX(100%) translateY(100%) rotate(45deg);
    }
@@ -977,7 +1033,6 @@
      opacity: 0;
      transform: translateY(-1.25rem);
    }
    to {
      opacity: 1;
      transform: translateY(0);
@@ -989,7 +1044,6 @@
      opacity: 0;
      transform: translateY(1.25rem);
    }
    to {
      opacity: 1;
      transform: translateY(0);
@@ -1001,7 +1055,6 @@
      opacity: 0;
      transform: translateY(0.5rem) scale(0.96);
    }
    100% {
      opacity: 1;
      transform: translateY(0) scale(1);
@@ -1061,9 +1114,10 @@
  }
  .notice-unit {
    color: #666666;
    font-size: 0.875rem;
    margin-left: 0.125rem;
    font-weight: 600;
    font-size: 1rem;
    color: #1976d2;
    margin-left: 0.25rem;
  }
  /* 功能模块样式 */
@@ -1237,20 +1291,16 @@
    .content {
      background: linear-gradient(135deg, #121317 0%, #161a20 100%);
    }
    .content::before {
      background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="dots" width="20" height="20" patternUnits="userSpaceOnUse"><circle cx="10" cy="10" r="1" fill="rgba(255, 255, 255, 0.05)"/></pattern></defs><rect width="100" height="100" fill="url(%23dots)"/></svg>');
    }
    .common-module {
      background: linear-gradient(135deg, #1e1f24 0%, #23252b 100%);
      box-shadow: 0 0.375rem 1.5rem rgba(0, 0, 0, 0.35);
    }
    .module-title {
      color: #e9edf3;
    }
    .module-subtitle,
    .item-label,
    .notice-text,
@@ -1258,18 +1308,15 @@
    .notice-label {
      color: #c7cbd3;
    }
    .notice {
      background: linear-gradient(135deg, #1b2330 0%, #1a2432 100%);
      border-color: rgba(255, 255, 255, 0.06);
      box-shadow: 0 0.375rem 1.25rem rgba(0, 0, 0, 0.4);
    }
    .notice-status,
    .notice-number {
      color: #8ab4ff;
    }
    .bg-img {
      background: linear-gradient(135deg, #1f4fb9 0%, #0e3a8a 100%);
    }
@@ -1279,7 +1326,6 @@
    from {
      transform: rotate(0deg);
    }
    to {
      transform: rotate(360deg);
    }
@@ -1290,7 +1336,6 @@
      opacity: 0;
      transform: translateY(-1.25rem);
    }
    to {
      opacity: 1;
      transform: translateY(0);
@@ -1302,7 +1347,6 @@
      opacity: 0;
      transform: translateY(1.25rem);
    }
    to {
      opacity: 1;
      transform: translateY(0);
@@ -1314,7 +1358,6 @@
      opacity: 0;
      transform: translateY(0.5rem) scale(0.96);
    }
    100% {
      opacity: 1;
      transform: translateY(0) scale(1);
@@ -1324,31 +1367,25 @@
  .notice-left {
    margin-right: 1rem;
  }
  .notice-status {
    font-size: 1rem;
  }
  .notice-separator {
    width: 0.0625rem;
    height: 1.5rem;
    margin-right: 1rem;
  }
  .notice-label {
    font-size: 0.875rem;
    margin-right: 0.75rem;
  }
  .notice-text {
    font-size: 0.875rem;
  }
  .notice-number {
    font-size: 1rem;
    margin-left: 0.25rem;
  }
  .notice-unit {
    font-size: 0.875rem;
    margin-left: 0.125rem;
@@ -1464,7 +1501,6 @@
    margin-top: 0.25rem;
    margin-bottom: 0.625rem;
  }
  .grid-text {
    font-size: 0.875rem;
  }
@@ -1473,7 +1509,6 @@
    .common-module {
      box-shadow: 0 0.375rem 1.5rem rgba(0, 0, 0, 0.35);
    }
    .notice {
      box-shadow: 0 0.375rem 1.25rem rgba(0, 0, 0, 0.4);
    }