zouyu
2 天以前 90ca0729f929a19d720412a5fab7aa0395ec54ef
Merge branch 'dev_tide_gybjyhglxt' into dev_tide_gybjyhglxt_xindao
已添加2个文件
已修改8个文件
1303 ■■■■■ 文件已修改
index.html 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/inventoryManagement/stockIn.js 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/inventoryManagement/stockManage.js 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/inventoryManagement/stockOut.js 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/inventoryManagement/stockReport.js 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/inventoryManagement/stockWarning.js 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/lavorissce/ledger.js 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/productionManagement/productionOrder.js 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/index.js 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/index.vue 1026 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
index.html
@@ -7,7 +7,7 @@
  <meta name="renderer" content="webkit">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
  <link rel="icon" href="/favicon.ico">
  <title>MIS(管理信息系统)</title>
  <title>%VITE_APP_TITLE%</title>
  <!--[if lt IE 11]><script>window.location.href='/html/ie.html';</script><![endif]-->
  <style>
    html,
src/api/inventoryManagement/stockIn.js
@@ -9,6 +9,41 @@
    });
};
// æŸ¥è¯¢ç”Ÿäº§å…¥åº“信息列表
export const getStockInPageByProduction = (params) => {
    return request({
        url: "/stockin/listPageByProduction",
        method: "get",
        params,
    });
};
// å‡ºåº“台账-查询自定义入库信息列表
export const getStockInPageByCustom = (params) => {
    return request({
        url: "/stockmanagement/listPageByCustom",
        method: "get",
        params,
    });
};
// å…¥åº“管理-查询自定义入库信息列表
export const getInPageByCustom = (params) => {
    return request({
        url: "/stockin/listPageByCustom",
        method: "get",
        params,
    });
};
// å‡ºåº“台账-查询生产出库信息列表
export const getStockInPageByProduct = (params) => {
    return request({
        url: "/stockmanagement/listPageByProduct",
        method: "get",
        params,
    });
};
// ä¿®æ”¹å…¥åº“存信息
export const updateStockIn = (data) => {
    return request({
@@ -26,6 +61,14 @@
        data,
    });
};
// ä¿®æ”¹ææ–™åº“存信息
export const updateManagementByCustom = (data) => {
    return request({
        url: "/stockin/updateManagementByCustom ",
        method: "post",
        data,
    });
};
// æ–°å¢žå•†å“å…¥åº“信息
export function addSutockIn(data) {
@@ -36,6 +79,32 @@
    })
}
// æ–°å¢žè‡ªå®šä¹‰å…¥åº“信息
export function addStockInCustom(data) {
    return request({
        url: '/stockin/addCustom',
        method: 'post',
        data: data
    })
}
// ç¼–辑自定义入库信息
export function updateStockInCustom(data) {
    return request({
        url: '/stockin/updateCustom',
        method: 'post',
        data: data
    })
}
// ç¼–辑成品入库信息
export function updateProduct(data) {
    return request({
        url: '/stockin/update',
        method: 'post',
        data: data
    })
}
// åˆ é™¤å…¥åº“信息
export function delStockIn(ids) {
    return request({
@@ -45,6 +114,15 @@
    })
}
// åˆ é™¤è‡ªå®šä¹‰å…¥åº“信息
export function delStockInCustom(ids) {
    return request({
        url: '/stockin/delteCustom',
        method: 'post',
        data: ids
    })
}
// å¯¼å‡ºå…¥åº“信息
export function exportStockIn(query) {
    return request({
src/api/inventoryManagement/stockManage.js
@@ -9,6 +9,24 @@
    });
};
// æŸ¥è¯¢ç”Ÿäº§å…¥åº“库存信息列表
export const getStockManagePageByProduction = (params) => {
    return request({
        url: "/stockin/listPageCopyByProduction",
        method: "get",
        params,
    });
};
// æŸ¥è¯¢è‡ªå®šä¹‰å…¥åº“库存信息列表
export const getStockManagePageByCustom = (params) => {
    return request({
        url: "/stockin/listPageCopyByCustom",
        method: "get",
        params,
    });
};
// ä¿®æ”¹åº“存信息
export const updateStockManage = (data) => {
@@ -38,7 +56,7 @@
    })
}
//出库接口
// å‡ºåº“管理-领用接口
export const stockOut = (data) => {
    return request({
        url: '/stockmanagement/stockout',
src/api/inventoryManagement/stockOut.js
@@ -1,6 +1,6 @@
import request from "@/utils/request";
//查询出库列表
// å‡ºåº“台账-采购出库查询出库列表
export const getStockOutPage = (params) => {
    return request({
        url: "/stockmanagement/listPage",
@@ -33,15 +33,5 @@
        url: '/stockmanagement/del',
        method: 'post',
        data: ids
    })
}
//导出出库信息
export const exportStockOut = (query) => {
    return request({
        url: '/stockmanagement/export',
        method: 'get',
        params: query,
        responseType: 'blob'
    })
}
src/api/inventoryManagement/stockReport.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,55 @@
import request from "@/utils/request";
// èŽ·å–åº“å­˜æ—¥æŠ¥ç»Ÿè®¡
export const getStockDailyReport = (params) => {
    return request({
        url: "/stockin/getReportList",
        method: "get",
        params,
    });
};
// èŽ·å–åº“å­˜æœˆæŠ¥ç»Ÿè®¡
export const getStockMonthlyReport = (params) => {
    return request({
        url: "/stockin/getReportList",
        method: "get",
        params,
    });
};
// èŽ·å–ä½œä¸šæŠ¥è¡¨ç»Ÿè®¡
export const getWorkReport = (params) => {
    return request({
        url: "/stockin/getReportList",
        method: "get",
        params,
    });
};
// èŽ·å–åº“å­˜è¿›å‡ºå­˜ç»Ÿè®¡
export const getStockInOutReport = (params) => {
    return request({
        url: "/stockin/getReportList",
        method: "get",
        params,
    });
};
// å¯¼å‡ºåº“存报表
export const exportStockReport = (params) => {
    return request({
        url: "/stockin/exportCopy",
        method: "post",
        params,
        responseType: 'blob'
    });
};
// èŽ·å–åº“å­˜è¶‹åŠ¿æ•°æ®
export const getStockTrendData = (params) => {
    return request({
        url: "/stockreport/trend",
        method: "get",
        params,
    });
};
src/api/inventoryManagement/stockWarning.js
@@ -1,11 +1,14 @@
import request from "@/utils/request";
// æŸ¥è¯¢å‚¨æ°”罐预警列表
export const getStockWarningPage = (params) => {
export const getStockWarningPage = (page, params) => {
    return request({
        url: "/gasTankWarning/listPage",
        method: "get",
        params,
        params: {
            ...page,
            ...params
        },
    });
};
@@ -14,7 +17,7 @@
    return request({
        url: "/gasTankWarning/add",
        method: "post",
        data,
        data: data,
    });
};
@@ -22,8 +25,8 @@
export const updateStockWarning = (data) => {
    return request({
        url: "/gasTankWarning/update",
        method: "put",
        data,
        method: "post",
        data: data,
    });
};
@@ -32,7 +35,7 @@
    return request({
        url: "/gasTankWarning/delete",
        method: "delete",
        data: { ids },
        data: ids,
    });
};
src/api/lavorissce/ledger.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,55 @@
import request from '@/utils/request'
// åˆ†é¡µæŸ¥è¯¢
export function listPage(query) {
    return request({
        url: '/lavorIssue/listPage',
        method: 'get',
        params: query
    })
}
// åˆ†é¡µæŸ¥è¯¢
export function statistics(params) {
    return request({
        url: '/lavorIssue/statistics',
        method: 'get',
        params
    })
}
export function statisticsList(params) {
    return request({
        url: '/lavorIssue/statisticsList',
        method: 'get',
        params
    })
}
// æ·»åŠ 
export function add(data) {
    return request({
        url: '/lavorIssue/add',
        method: 'post',
        data
    })
}
// ä¿®æ”¹
export function update(data) {
    return request({
        url: '/lavorIssue/update',
        method: 'post',
        data
    })
}
// åˆ é™¤
export function deleteLedger(data) {
    return request({
        url: '/lavorIssue/delete',
        method: 'delete',
        data
    })
}
src/api/productionManagement/productionOrder.js
@@ -4,7 +4,7 @@
// åˆ†é¡µæŸ¥è¯¢
export function schedulingListPage(query) {
  return request({
    url: "/salesLedger/scheduling/listPage",
    url: "/productionOrder/listPage",
    method: "get",
    params: query,
  });
@@ -17,3 +17,28 @@
    data: query,
  });
}
// æ–°å¢žç”Ÿäº§è®¢å•
export function addProductionOrder(query) {
  return request({
    url: "/productionOrder/addProductionOrder",
    method: "post",
    data: query,
  });
}
// ä¿®æ”¹ç”Ÿäº§è®¢å•
export function updateProductionOrder(query) {
  return request({
    url: "/productionOrder/updateProductionOrder",
    method: "post",
    data: query,
  });
}
// åˆ é™¤ç”Ÿäº§è®¢å•
export function deleteProductionOrder(query) {
  return request({
    url: "/productionOrder/deleteProductionOrder",
    method: "delete",
    data: query,
  });
}
src/utils/index.js
@@ -396,3 +396,16 @@
export function isEqual(obj1, obj2) {
  return JSON.stringify(obj1) === JSON.stringify(obj2);
}
/**
 * èŽ·å–å½“å‰æ—¥æœŸå¹¶æ ¼å¼åŒ–ä¸º YYYY-MM-DD
 * @returns {string} æ ¼å¼åŒ–的日期字符串
 */
export function getCurrentDate() {
  const today = new Date();
  const year = today.getFullYear();
  const month = String(today.getMonth() + 1).padStart(2, '0'); // æœˆä»½ä»Ž0开始
  const day = String(today.getDate()).padStart(2, '0');
  return `${year}-${month}-${day}`;
}
src/views/index.vue
@@ -2,259 +2,299 @@
    <div class="dashboard">
        <!-- é¡¶éƒ¨æ¨ªå‘两栏 -->
        <div class="dashboard-top">
            <!-- å·¦ï¼šç³»ç»Ÿæ¦‚览+数据卡片 -->
            <!-- å·¦ï¼šä¼ä¸šä¿¡æ¯+三大数据卡片(上下排列) -->
            <div class="top-left">
                <div class="system-info">
                    <div class="section-title">工艺报警优化管理系统</div>
                <div class="company-info">
                    <div class="section-title">登陆信息</div>
                    <div style="display: flex;align-items: center;gap: 20px">
                        <div class="system-card">
                            <div class="system-name">工艺报警优化管理系统</div>
                            <div class="system-meta">实时监控 Â· æ™ºèƒ½åˆ†æž Â· é«˜æ•ˆå¤„理</div>
                        <img :src="userStore.avatar" class="avatar" alt=""/>
                        <div class="company-card">
                            <div class="company-name">{{userStore.name}}</div>
                            <div class="company-meta">{{userStore.roleName}}</div>
                        </div>
                        <div style="display: flex;align-items: center;gap: 8px">
                            <el-icon color="#5053B5" size="22"><Clock /></el-icon>
                            <span>当前时间:{{ currentTime }}</span>
                            <span>登陆日期:{{userStore.currentLoginTime}}</span>
                        </div>
                    </div>
                </div>
                <div class="data-cards">
                    <div class="data-card total">
                        <div class="data-title">总报警数</div>
                        <div class="data-value">{{ alarmStats.total }}</div>
                        <div class="data-desc">已处理 {{ alarmStats.handled }} | æœªå¤„理 {{ alarmStats.pending }}</div>
<!--                <div class="data-cards">-->
<!--                    <div class="data-card sales">-->
<!--                        <div class="data-title">销售数据</div>-->
<!--                        <div class="data-num">-->
<!--                            <div>-->
<!--                                <div class="data-desc">本月销售额/元</div>-->
<!--                                <div class="data-value">{{businessInfo.monthSaleMoney}}</div>-->
<!--                            </div>-->
<!--                            <div>-->
<!--                                <div class="data-desc">未开票金额/元</div>-->
<!--                                <div class="data-value">{{businessInfo.monthSaleHaveMoney}}</div>-->
<!--                            </div>-->
<!--                        </div>-->
<!--                        -->
<!--                    </div>-->
<!--                    <div class="data-card purchase">-->
<!--                        <div class="data-title">采购数据</div>-->
<!--                        <div class="data-num">-->
<!--                            <div>-->
<!--                                <div class="data-desc">本月采购额/元</div>-->
<!--                                <div class="data-value">{{businessInfo.monthPurchaseMoney}}</div>-->
<!--                            </div>-->
<!--                            <div>-->
<!--                                <div class="data-desc">待付款金额/元</div>-->
<!--                                <div class="data-value">{{businessInfo.monthPurchaseHaveMoney}}</div>-->
<!--                            </div>-->
<!--                        </div>-->
<!--                    </div>-->
<!--                    <div class="data-card inventory">-->
<!--                        <div class="data-title">库存数据</div>-->
<!--                        <div class="data-num">-->
<!--                            <div>-->
<!--                                <div class="data-desc">当前库存总量/ä»¶</div>-->
<!--                                <div class="data-value">{{businessInfo.inventoryNum}}</div>-->
<!--                            </div>-->
<!--                            <div>-->
<!--                                <div class="data-desc">今日入库/ä»¶</div>-->
<!--                                <div class="data-value">{{businessInfo.todayInventoryNum}}</div>-->
<!--                            </div>-->
<!--                        </div>-->
<!--                    </div>-->
<!--                </div>-->
                    </div>
                    <div class="data-card pending">
                        <div class="data-title">未处理报警</div>
                        <div class="data-value">{{ alarmStats.pending }}</div>
                        <div class="data-desc">严重 {{ alarmStats.severePending }} | ä¸­ç­‰ {{ alarmStats.moderatePending }} | è½»å¾® {{ alarmStats.minorPending }}</div>
                    </div>
                    <div class="data-card today">
                        <div class="data-title">今日报警</div>
                        <div class="data-value">{{ alarmStats.today }}</div>
                        <div class="data-desc">同比 {{ alarmStats.today同比 }}% | çŽ¯æ¯” {{ alarmStats.today环比 }}%</div>
                    </div>
                </div>
            </div>
            <!-- å³ï¼šå¾…处理报警列表 -->
            <div class="alarm-panel">
                <div class="section-title">待处理报警</div>
                <ul class="alarm-list" v-if="pendingAlarms.length > 0">
                    <li v-for="item in pendingAlarms" :key="item.id">
                        <div style="display: flex;flex-direction: column;justify-content: space-between;width: 100%;gap: 10px">
                            <div style="display: flex;justify-content: space-between;align-items: center;">
                                <div class="alarm-title">{{ item.equipmentName }} - {{ item.parameter }}</div>
                                <el-tag :type="getAlarmLevelType(item.alarmLevel)">{{ item.alarmLevel }}</el-tag>
                            </div>
                            <div style="display: flex;justify-content: space-between;align-items: center;">
                                <div class="alarm-value">报警值: {{ item.alarmValue }} | é˜ˆå€¼: {{ item.threshold }}</div>
                                <div class="alarm-time">{{ item.alarmTime }}</div>
                            </div>
                        </div>
                    </li>
                </ul>
                <div v-else style="text-align: center; color: #909399; padding: 20px;">
                    æš‚无待处理报警
                </div>
            </div>
        </div>
        <!-- ä¸­éƒ¨æ¨ªå‘两栏 -->
        <div class="dashboard-row">
            <div class="main-panel">
                <div class="section-title">报警趋势分析</div>
                <Echarts ref="chart" :chartStyle="chartStyle" :grid="grid" :legend="lineLegend" :series="lineSeries" :tooltip="tooltipLine" :xAxis="xAxis" :yAxis="yAxis" style="height: 300px;"></Echarts>
            </div>
            <div class="main-panel">
                <div class="section-title">报警级别分布</div>
                <div style="display: flex;align-items: center;gap: 20px;justify-content: space-evenly;height: 300px;">
                    <div style="width: 50%;">
                        <Echarts ref="chart" :legend="pieLegend" :chartStyle="chartStylePie" :series="levelPieSeries" :tooltip="pieTooltip"></Echarts>
                    </div>
                    <ul class="level-list" style="width: 50%;">
                        <li v-for="item in levelPieSeries[0].data" :key="item.name">
                            <div style="display: flex;align-items: center;justify-content: space-between;width: 100%">
                                <div class="line" :style="{color: item.itemStyle.color}">●{{ item.name }}</div>
                                <div style="width: 60px;">{{ item.value }}次</div>
                                <div style="width: 60px;">{{ item.rate }}%</div>
                            </div>
                        </li>
                    </ul>
                </div>
            </div>
        </div>
            <!-- å³ï¼šå¾…办事项 -->
<!--            <div class="todo-panel">-->
<!--                <div class="section-title">待办事项</div>-->
<!--                <ul class="todo-list" v-if="todoList.length > 0">-->
<!--                    <li v-for="item in todoList" :key="item.id">-->
<!--                        <div style="display: flex;flex-direction: column;justify-content: space-between;width: 100%;gap: 20px">-->
<!--                            <div style="display: flex;justify-content: space-between;align-items: center;">-->
<!--                                <div class="todo-title">流程编号:{{item.approveId}}</div>-->
<!--                                <div class="todo-division">申请部门:{{item.approveDeptName}}</div>-->
<!--                                <div class="todo-time">{{item.approveTime}}</div>-->
<!--                            </div>-->
<!--                            <div class="todo-division">审批事由:{{item.approveReason}}</div>-->
<!--                        </div>-->
<!--                    </li>-->
<!--                </ul>-->
<!--                <div v-else style="text-align: center">-->
<!--                    æš‚无数据-->
<!--                </div>-->
<!--            </div>-->
<!--        </div>-->
<!--        -->
<!--        &lt;!&ndash; ä¸­éƒ¨æ¨ªå‘两栏 &ndash;&gt;-->
<!--        <div class="dashboard-row">-->
<!--            <div class="main-panel">-->
<!--                <div class="section-title">客户合同金额分析</div>-->
<!--                <div class="contract-summary">-->
<!--                    <div class="contract-info">-->
<!--                        <img src="../assets/images/khtitle.png" alt="" style="width: 42px"/>-->
<!--                        <div class="contract-card">-->
<!--                            <div class="contract-name">总合同金额(元)</div>-->
<!--                            <div class="contract-meta">-->
<!--                                <div class="main-amount">{{sum}}</div>-->
<!--                                <div>周同比: <span class="up">{{yny}}% </span> æ—¥çŽ¯æ¯”: <span class="up">{{chain}}% </span></div>-->
<!--                            </div>-->
<!--                        </div>-->
<!--                    </div>-->
<!--                </div>-->
<!--                <div style="display: flex;align-items: center;gap: 20px;justify-content: space-evenly;height: 180px;margin-top: 20px">-->
<!--                    <div>-->
<!--                        <Echarts ref="chart" :legend="pieLegend" :chartStyle="chartStylePie"-->
<!--                                         :series="materialPieSeries"-->
<!--                                         :tooltip="pieTooltip"></Echarts>-->
<!--                    </div>-->
<!--                    <ul class="contract-list">-->
<!--                        <li v-for="item in materialPieSeries[0].data" :key="item.name">-->
<!--                            <div style="display: flex;align-items: center;justify-content: space-between;width: 100%">-->
<!--                                <div class="line" :style="{color: item.itemStyle.color}">●{{item.name}}</div>-->
<!--                                <div style="width: 70px">{{item.rate}}%</div>-->
<!--                                <div>ï¿¥{{item.value}}</div>-->
<!--                            </div>-->
<!--                        </li>-->
<!--                    </ul>-->
<!--                </div>-->
<!--            </div>-->
<!--            <div class="main-panel">-->
<!--                <div style="display: flex;justify-content: space-between;">-->
<!--                    <div class="section-title">应收应付统计</div>-->
<!--&lt;!&ndash;                    <el-radio-group v-model="radio1" size="large" @change="statisticsReceivable">&ndash;&gt;-->
<!--&lt;!&ndash;                        <el-radio-button label="按周" :value="1" />&ndash;&gt;-->
<!--&lt;!&ndash;                        <el-radio-button label="按月" :value="2" />&ndash;&gt;-->
<!--&lt;!&ndash;                        <el-radio-button label="按季度" :value="3" />&ndash;&gt;-->
<!--&lt;!&ndash;                    </el-radio-group>&ndash;&gt;-->
<!--                </div>-->
<!--                <Echarts ref="chart"-->
<!--                                 :color="barColors2"-->
<!--                                 :chartStyle="chartStyle"-->
<!--                                 :grid="grid"-->
<!--                                 :series="barSeries"-->
<!--                                 :tooltip="tooltip"-->
<!--                                 :xAxis="xAxis"-->
<!--                                 :yAxis="yAxis"-->
<!--                                 style="height: 260px"></Echarts>-->
<!--            </div>-->
<!--        </div>-->
        
        <!-- åº•部横向两栏 -->
        <div class="dashboard-row">
            <div class="main-panel">
                <div class="section-title">设备报警统计</div>
                <Echarts ref="chart" :color="barColors" :chartStyle="chartStyle" :grid="grid" :series="equipmentBarSeries" :tooltip="tooltip" :xAxis="equipmentXAxis" :yAxis="yAxis" style="height: 300px;"></Echarts>
            </div>
            <div class="main-panel">
                <div class="section-title">报警处理时效分析</div>
                <Echarts ref="chart" :color="barColors" :chartStyle="chartStyle" :grid="grid" :series="handlingTimeSeries" :tooltip="tooltip" :xAxis="handlingTimeXAxis" :yAxis="yAxis" style="height: 300px;"></Echarts>
            </div>
<!--        <div class="dashboard-row">-->
<!--            <div class="main-panel">-->
<!--                <div class="section-title">质量统计</div>-->
<!--                <div class="quality-cards">-->
<!--                    <div class="quality-card one">原材料已检测数 <span>{{qualityStatisticsObject.supplierNum}}ä»¶</span></div>-->
<!--                    <div class="quality-card two">过程检验数量 <span>{{qualityStatisticsObject.processNum}}ä»¶</span></div>-->
<!--                    <div class="quality-card three">出厂已检数量 <span>{{qualityStatisticsObject.factoryNum}}ä»¶</span></div>-->
<!--                </div>-->
<!--                <Echarts ref="chart"-->
<!--                                 :chartStyle="chartStyle"-->
<!--                                 :grid="grid"-->
<!--                                 :legend="barLegend"-->
<!--                                 :series="barSeries1"-->
<!--                                 :tooltip="tooltip"-->
<!--                                 :xAxis="xAxis1"-->
<!--                                 :yAxis="yAxis1"-->
<!--                                 style="height: 260px"></Echarts>-->
<!--            </div>-->
<!--            <div class="main-panel">-->
<!--                <div class="section-title">回款与开票分析</div>-->
<!--                <Echarts ref="chart" :chartStyle="chartStyle" :grid="grid" :legend="lineLegend" :series="lineSeries"-->
<!--                                 :tooltip="tooltipLine" :xAxis="xAxis2" :yAxis="yAxis2" style="height: 270px;"></Echarts>-->
<!--            </div>-->
        </div>
    </div>
</template>
<script setup>
import { ref, onMounted, reactive, computed } from 'vue'
import { ref, onMounted } from 'vue'
import Echarts from "@/components/Echarts/echarts.vue";
import { Clock } from '@element-plus/icons-vue';
import * as echarts from 'echarts';
import useUserStore from "@/store/modules/user.js";
import {
    analysisCustomerContractAmounts, getAmountHalfYear,
    getBusiness,
    homeTodos,
    qualityStatistics,
    statisticsReceivablePayable
} from "@/api/viewIndex.js";
// å½“前时间
const currentTime = computed(() => {
    const now = new Date();
    return now.toLocaleString('zh-CN');
});
const userStore = useUserStore()
// æŠ¥è­¦ç»Ÿè®¡æ•°æ®
const alarmStats = reactive({
    total: 425,
    handled: 398,
    pending: 27,
    severePending: 8,
    moderatePending: 12,
    minorPending: 7,
    today: 35,
    today同比: '+12.5',
    today环比: '-8.3'
});
const businessInfo = ref({
    inventoryNum: 0,
    monthPurchaseHaveMoney: 0,
    monthPurchaseMoney: 0,
    monthSaleHaveMoney: 0,
    monthSaleMoney: 0,
    todayInventoryNum: 0,
})
const qualityStatisticsObject = ref({
    supplierNum: 0,
    processNum: 0,
    factoryNum: 0,
})
const sum = ref(0)
const yny = ref(0)
const chain = ref(0)
// å¾…处理报警列表
const pendingAlarms = ref([
const pieLegend = reactive({
    show: false,
})
const barSeries = ref([
    {
        id: 1,
        equipmentName: '反应釜A',
        parameter: '温度',
        alarmValue: '185°C',
        threshold: '≤180°C',
        alarmLevel: '严重',
        alarmTime: '2025-12-16 14:30:23'
    },
    {
        id: 2,
        equipmentName: '离心机B',
        parameter: '振动',
        alarmValue: '0.8mm/s',
        threshold: '≤0.5mm/s',
        alarmLevel: '中等',
        alarmTime: '2025-12-16 14:28:15'
    },
    {
        id: 3,
        equipmentName: '反应釜D',
        parameter: 'pH值',
        alarmValue: '4.2',
        threshold: '5.0-7.0',
        alarmLevel: '中等',
        alarmTime: '2025-12-16 14:22:18'
    },
    {
        id: 4,
        equipmentName: '干燥机E',
        parameter: '湿度',
        alarmValue: '15%',
        threshold: '≤10%',
        alarmLevel: '轻微',
        alarmTime: '2025-12-16 14:18:55'
        type: 'bar',
        data: [],
        label: {
            show: true,
    }
]);
// å›¾è¡¨æ ·å¼
    },
])
const barSeries1 = ref([
    {
        name: '原材料不合格数',
        type: 'bar',
        barGap: 0,
        emphasis: {
            focus: 'series'
        },
        data: []
    },
    {
        name: '过程不合格数',
        type: 'bar',
        emphasis: {
            focus: 'series'
        },
        data: []
    },
    {
        name: '出厂不合格数',
        type: 'bar',
        emphasis: {
            focus: 'series'
        },
        data: []
    },
])
const chartStyle = {
    width: '100%',
    height: '100%'
};
    height: '100%' // è®¾ç½®å›¾è¡¨å®¹å™¨çš„高度
}
const chartStylePie = {
    width: '100%',
    height: '100%'
};
    width: '140%',
    height: '140%' // è®¾ç½®å›¾è¡¨å®¹å™¨çš„高度
}
const grid = {
    left: '3%',
    right: '4%',
    bottom: '3%',
    containLabel: true
};
// æŠ¥è­¦è¶‹åŠ¿åˆ†æž - æŠ˜çº¿å›¾
}
const barLegend = {
    show: true,
    data: ['原材料不合格数', '过程不合格数', '出厂不合格数']
}
const barLegend1 = {
    show: true,
    data: ['预付账款', '应付账款', '预收账款', '应收账款']
}
const lineLegend = {
    show: true,
    data: ['严重', '中等', '轻微']
};
const tooltipLine = {
    data: ['开票', '回款']
}
const tooltip = {
    trigger: 'axis',
    axisPointer: {
        type: 'cross'
        type: 'shadow'
    }
};
const xAxis = ref({
    type: 'category',
    data: ['12-01', '12-02', '12-03', '12-04', '12-05', '12-06', '12-07']
});
const yAxis = ref({
}
const xAxis = [{
    type: 'value',
    name: '报警数量'
});
const lineSeries = ref([
    {
        name: '严重',
        type: 'line',
        data: [8, 12, 9, 15, 11, 13, 10],
        itemStyle: {
            color: '#f56c6c'
        },
        lineStyle: {
            width: 2
        },
        showSymbol: true
    },
    {
        name: '中等',
        type: 'line',
        data: [22, 25, 20, 28, 24, 26, 23],
        itemStyle: {
            color: '#e6a23c'
        },
        lineStyle: {
            width: 2
        },
        showSymbol: true
    },
    {
        name: '轻微',
        type: 'line',
        data: [35, 38, 32, 40, 36, 39, 34],
        itemStyle: {
            color: '#67c23a'
        },
        lineStyle: {
            width: 2
        },
        showSymbol: true
    }
]);
// æŠ¥è­¦çº§åˆ«åˆ†å¸ƒ - é¥¼å›¾
const pieLegend = {
    show: false
};
const pieTooltip = {
}]
const xAxis1 = ref([{
    type: 'category',
    axisTick: { show: false },
    data: []
}])
const yAxis = [{
    type: 'category',
    data: [ '应付账款', '应收账款',]
}]
const yAxis1 = [{
    type: 'value'
}]
const pieTooltip = reactive({
    trigger: 'item',
    formatter: '{b}: {c}次 ({d}%)'
};
const levelPieSeries = ref([
    formatter: function (params) {
        // åŠ¨æ€ç”Ÿæˆæç¤ºä¿¡æ¯ï¼ŒåŸºäºŽæ•°æ®é¡¹çš„ name å±žæ€§
        const description = params.name === '本月回款金额' ? '本月回款金额' : '应收款金额';
        return `${description} ${formatNumber(params.value)}元 ${params.percent}%`;
    },
    position: 'right'
})
const materialPieSeries = ref([
    {
        type: 'pie',
        radius: ['60%', '80%'],
        radius: ['66%', '90%'],
        avoidLabelOverlap: false,
        itemStyle: {
            borderColor: '#fff',
@@ -263,97 +303,188 @@
        label: {
            show: false
        },
        data: [
        data: []
    }
])
const lineSeries = ref([
            {
                name: '严重',
                value: 78,
                rate: 18.35,
                itemStyle: { color: '#f56c6c' }
        type: 'line',
        data: [],
        label: {
            show: true
        },
    showSymbol: true, // æ˜¾ç¤ºåœ†ç‚¹
    },
])
const tooltipLine = {
    trigger: 'axis',
}
const yAxis2 = ref([
    {
        type: 'value',
    }
])
const xAxis2 = ref([
    {
        type: 'category',
        data: [],
        axisLabel: {
            interval: 0,
            formatter: function(value) {
                return value.replace(/~/g, '\n');
            },
        }
    }
])
// å¾…办事项
const todoList = ref([])
const radio1 = ref(1)
// å›¾è¡¨å¼•用
const barChart = ref(null)
const lineChart = ref(null)
const barColors2 = ['#5181DB', '#D369E0', '#F2CA6D', '#60CCA8']
// éšæœºé¢œè‰²ç”Ÿæˆå‡½æ•°
const getRandomColor = () => {
  return '#' + Math.floor(Math.random() * 0xffffff).toString(16).padStart(6, '0');
}
onMounted(() => {
    getBusinessData()
    analysisCustomer()
    todoInfoS()
    statisticsReceivable()
    qualityStatisticsInfo()
    getAmountHalfYearNum()
})
// æ•°æ®ç»Ÿè®¡
const getBusinessData = () => {
    getBusiness().then((res) => {
        businessInfo.value = {...res.data}
    })
}
// åˆåŒé‡‘额
const analysisCustomer = () => {
    analysisCustomerContractAmounts().then((res) => {
        sum.value = res.data.sum
        yny.value = res.data.yny
        chain.value = res.data.chain
    // ä¸ºæ¯ä¸ªæ•°æ®é¡¹åˆ†é…éšæœºé¢œè‰²
    materialPieSeries.value[0].data = res.data.item.map(item => ({
      ...item,
      itemStyle: { color: getRandomColor() }
    }))
    })
}
// å¾…办事项
const todoInfoS = () => {
    homeTodos().then((res) => {
        todoList.value = res.data
    })
}
// åº”付应收统计
const statisticsReceivable = (type) => {
    console.log(type)
    statisticsReceivablePayable({type: radio1.value}).then((res) => {
        barSeries.value[0].data = [
            // { value: res.data.prepayMoney, itemStyle: { color: barColors2[0] } },
            { value: res.data.payableMoney, itemStyle: { color: barColors2[0] } },
            // { value: res.data.advanceMoney, itemStyle: { color: barColors2[2] } },
            { value: res.data.receivableMoney, itemStyle: { color: barColors2[1] } }
        ]
    })
}
// è´¨æ£€ç»Ÿè®¡
const qualityStatisticsInfo = () => {
    qualityStatistics().then((res) => {
        res.data.item.forEach(item => {
            xAxis1.value[0].data.push(item.date)
            barSeries1.value[0].data.push(item.supplierNum)
            barSeries1.value[1].data.push(item.processNum)
            barSeries1.value[2].data.push(item.factoryNum)
        })
        qualityStatisticsObject.value.supplierNum = res.data.supplierNum
        qualityStatisticsObject.value.processNum = res.data.processNum
        qualityStatisticsObject.value.factoryNum = res.data.factoryNum
    })
}
const getAmountHalfYearNum = async () => {
    const res = await getAmountHalfYear()
    console.log(res)
    const monthName = []
    const receiptAmount = []
    const invoiceAmount = []
    res.data.forEach(item => {
        monthName.push(item.month)
        receiptAmount.push(item.receiptAmount)
        invoiceAmount.push(item.invoiceAmount)
    })
    // æ­£ç¡®å“åº”式赋值:创建新的 xAxis å’Œ series å¯¹è±¡
    xAxis2.value[0].data = monthName
    xAxis2.value[0].data = monthName.map(item => item.replace(/~/g, '\n~'));
    lineSeries.value = [
        {
            name: '开票',
            type: 'line',
            data: receiptAmount,
            stack: 'Total',
            areaStyle: {
                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                    {
                        offset: 0,
                        color: 'rgba(131, 207, 255, 1)'
            },
            {
                name: '中等',
                value: 178,
                rate: 41.88,
                itemStyle: { color: '#e6a23c' }
                        offset: 1,
                        color: 'rgba(186, 228, 255, 1)'
                    }
                ])
            },
            itemStyle: {
                color: '#2D99FF',
                borderColor: '#2D99FF'
            },
            emphasis: {
                focus: 'series'
            },
            lineStyle: {
                width: 0
            },
            showSymbol: true,
            },
            {
                name: '轻微',
                value: 169,
                rate: 39.76,
                itemStyle: { color: '#67c23a' }
            name: '回款',
            type: 'line',
            data: invoiceAmount,
            stack: 'Total',
            lineStyle: {
                width: 0
            },
            itemStyle: {
                color: '#83CFFF',
                borderColor: '#83CFFF'
            },
            showSymbol: true,
            areaStyle: {
                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                    {
                        offset: 0,
                        color: 'rgba(54, 153, 255, 1)'
                    },
                    {
                        offset: 1,
                        color: 'rgba(89, 169, 254, 1)'
                    }
                ])
            },
            emphasis: {
                focus: 'series'
            },
            }
        ]
    }
]);
// è®¾å¤‡æŠ¥è­¦ç»Ÿè®¡ - æŸ±çж图
const barColors = ['#409eff', '#67c23a', '#e6a23c', '#f56c6c', '#909399'];
const tooltip = {
    trigger: 'axis',
    axisPointer: {
        type: 'shadow'
    }
};
const equipmentXAxis = ref({
    type: 'category',
    data: ['反应釜', '离心机', '输送泵', '干燥机', '压缩机']
});
const equipmentBarSeries = ref([
    {
        name: '报警数量',
        type: 'bar',
        data: [125, 85, 78, 65, 72],
        itemStyle: {
            color: function(params) {
                return barColors[params.dataIndex % barColors.length];
            }
        },
        label: {
            show: true,
            position: 'top'
        }
    }
]);
// æŠ¥è­¦å¤„理时效分析 - æŸ±çж图
const handlingTimeXAxis = ref({
    type: 'category',
    data: ['0-30分钟', '30-60分钟', '1-2小时', '2小时以上']
});
const handlingTimeSeries = ref([
    {
        name: '处理数量',
        type: 'bar',
        data: [280, 75, 45, 25],
        itemStyle: {
            color: function(params) {
                return barColors[params.dataIndex % barColors.length];
            }
        },
        label: {
            show: true,
            position: 'top'
        }
    }
]);
// èŽ·å–æŠ¥è­¦çº§åˆ«æ ·å¼
const getAlarmLevelType = (level) => {
    switch(level) {
        case '严重': return 'danger';
        case '中等': return 'warning';
        case '轻微': return 'info';
        default: return 'info';
    }
};
onMounted(() => {
    // é¡µé¢åŠ è½½å®ŒæˆåŽçš„åˆå§‹åŒ–æ“ä½œ
});
</script>
<style scoped>
@@ -363,25 +494,34 @@
    padding: 20px;
    box-sizing: border-box;
}
.dashboard-top {
    display: flex;
    gap: 20px;
    margin-bottom: 20px;
}
.system-info {
.company-info {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 20px;
    min-width: 0;
    background-color: #EFF2FB;
    background-color: #EFF2FB; /* ä½¿ç”¨æŒ‡å®šçš„背景颜色 */
    background-image: url("../assets/images/denglu.png");
    background-size: 100% 260%;
    background-position: center;
    background-repeat: no-repeat;
    border-radius: 12px;
    height: 138px;
}
.system-card {
.avatar {
    width: 60px;
    height: 60px;
    border-radius: 50%;
    object-fit: contain;
    background: #fff;
    border: 1px solid #eee;
}
.company-card {
    display: flex;
    flex-direction: column;
    gap: 10px;
@@ -389,18 +529,26 @@
    padding-right: 15px;
}
.system-name {
    font-weight: 600;
    font-size: 18px;
.company-card::after {
    content: '';
    position: absolute;
    right: 0;
    top: 0;
    bottom: 0;
    width: 1px;
    background-color: #C9C5C5;
    border-radius: 2px;
}
.company-name {
    font-weight: 400;
    font-size: 16px;
    color: #161A9A;
}
.system-meta {
.company-meta {
    font-weight: 400;
    font-size: 12px;
    color: #818185;
}
.data-cards {
    display: flex;
    gap: 16px;
@@ -409,121 +557,123 @@
    border-radius: 12px;
    padding: 20px;
}
.data-title {
    font-weight: 700;
    font-size: 26px;
    color: #FFFFFF;
}
.data-num {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-top: 20px;
}
.data-card {
    background: #fff;
    border-radius: 12px;
    padding: 16px;
    padding: 14px 10px 10px 10px;
    min-width: 160px;
    box-shadow: 0 2px 8px #eee;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    width: 32%;
    height: 140px;
    transition: all 0.3s ease;
}
.data-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
.data-card.sales {
    background-image: url("../assets/images/xioashoushuju.png");
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
}
.data-card.total {
    background: linear-gradient(135deg, #409eff 0%, #66b1ff 100%);
    color: #fff;
.data-card.purchase {
    background-image: url("../assets/images/caigou.png");
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
}
.data-card.pending {
    background: linear-gradient(135deg, #f56c6c 0%, #f78989 100%);
    color: #fff;
.data-card.inventory {
    background-image: url("../assets/images/kucun.png");
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
}
.data-card.today {
    background: linear-gradient(135deg, #67c23a 0%, #85ce61 100%);
    color: #fff;
}
.data-title {
    font-weight: 600;
    font-size: 16px;
    margin-bottom: 12px;
}
.data-value {
    font-size: 32px;
    font-weight: bold;
    margin-bottom: 8px;
}
.data-desc {
    font-size: 12px;
    opacity: 0.9;
    font-weight: 500;
    font-size: 13px;
    color: #FFFFFF;
}
.data-value {
    font-size: 18px;
    font-weight: 500;
    margin: 10px 0;
    color: #FFFFFF;
}
.top-left {
    display: flex;
    flex-direction: column;
    gap: 20px;
    width: 60%;
    width: 50%;
}
.alarm-panel {
.todo-panel {
    background: #fff;
    border-radius: 12px;
    padding: 20px;
    width: 40%;
    width: 50%;
}
.alarm-list {
.todo-list {
    list-style: none;
    padding: 0;
    margin: 0;
    font-size: 14px;
    font-size: 15px;
    overflow-y: auto;
    height: 260px;
}
.alarm-list li {
.todo-list li {
    border-radius: 8px;
    margin-bottom: 12px;
    padding: 12px 20px;
    padding: 8px 20px;
    height: 74px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    background: #f8f9fa;
    border-left: 4px solid #409eff;
    transition: all 0.3s ease;
    background: rgba(225,227,250,0.62);
}
.alarm-list li:hover {
    background: #e9ecef;
    transform: translateX(4px);
}
.alarm-title {
    font-weight: 600;
    font-size: 14px;
    color: #303133;
}
.alarm-value {
.todo-title {
    font-weight: 400;
    font-size: 12px;
    color: #606266;
    color: #000000;
    position: relative;
}
.alarm-time {
.todo-title::before {
    content: ''; /* å¿…需,表示这里有一个内容 */
    position: absolute;
    left: -10px; /* å®šä½åˆ°å·¦ä¾§ */
    top: 50%; /* åž‚直居中 */
    transform: translateY(-50%); /* å¾®è°ƒåž‚直居中 */
    width: 6px; /* åœ†çš„直径 */
    height: 6px; /* åœ†çš„直径 */
    background: #498CEB;
    border-radius: 50%; /* è®©å…¶å˜æˆåœ†å½¢ */
}
.todo-division {
    font-weight: 400;
    font-size: 12px;
    color: #909399;
    color: #000000;
}
.todo-time {
    font-weight: 400;
    font-size: 12px;
    color: #000000;
}
.todo-meta {
    color: #888;
    font-size: 13px;
}
.dashboard-row {
    display: flex;
    gap: 20px;
    margin-bottom: 20px;
}
.main-panel {
    background: #fff;
    border-radius: 12px;
@@ -533,13 +683,12 @@
    display: flex;
    flex-direction: column;
}
.section-title {
    position: relative;
    font-size: 18px;
    color: #333;
    padding-left: 10px;
    margin-bottom: 20px;
    margin-bottom: 10px;
    font-weight: 700;
}
@@ -550,34 +699,107 @@
    content: '';
    width: 4px;
    height: 18px;
    background-color: #409eff;
    background-color: #002FA7;
    border-radius: 2px;
}
.level-list {
    margin: 0;
    padding: 0;
    list-style: none;
    height: 200px;
    overflow-y: auto;
.contract-info {
    display: flex;
    align-items: center;
    gap: 20px;
    height: 90px;
    background: rgba(245,245,245,0.59);
    width: 100%;
    border-radius: 10px;
    padding: 10px 30px;
}
.level-list li {
    margin-bottom: 15px;
    padding: 10px;
    background: #f8f9fa;
    border-radius: 6px;
    transition: all 0.3s ease;
.contract-summary {
    display: flex;
    align-items: center;
    gap: 30px;
}
.level-list li:hover {
    background: #e9ecef;
.contract-card {
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.contract-name {
    font-weight: 400;
    font-size: 14px;
    color: #050505;
}
.contract-meta {
    display: flex;
    align-items: center;
    width: 100%;
    gap: 80px;
}
.main-amount {
    font-size: 24px;
    color: rgba(51,50,50,0.85);
}
.up { color: #e57373; }
.contract-list {
    margin-top: 16px;
    font-size: 14px;
    color: #666;
    list-style: none;
    padding: 0;
    height: 190px;
    overflow-y: auto;
    width: 460px;
}
.line {
    position: relative;
    width: 80px;
    font-weight: 500;
    width: 230px;
}
.line::after {
    content: '';
    position: absolute;
    right: 2px;
    top: 0;
    bottom: 0;
    width: 1px;
    background-color: #C9C5C5;
    border-radius: 2px;
}
.contract-list li {
    margin-top: 10px;
}
.quality-cards {
    display: flex;
    gap: 12px;
    margin-bottom: 12px;
}
.quality-card {
    border-radius: 8px;
    padding: 15px 10px 10px 50px;
    font-weight: 400;
    font-size: 12px;
    color: rgba(0,0,0,0.67);
    width: 236px;
    height: 49px;
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
}
.quality-card.one {
    background-image: url("../assets/images/yuancailiao.png");
}
.quality-card.two {
    background-image: url("../assets/images/guocheng.png");
}
.quality-card.three {
    background-image: url("../assets/images/chuchang.png");
}
.quality-card span {
    color: #4fc3f7;
    font-weight: bold;
    margin-left: 6px;
}
.chart {
    width: 100%;
    height: 220px;
    margin-top: 10px;
}
</style>