@@ -1,3 +1,10 @@ | |||
### | |||
# @Author: zhp | |||
# @Date: 2024-04-28 13:42:51 | |||
# @LastEditTime: 2024-05-08 08:57:33 | |||
# @LastEditors: zhp | |||
# @Description: | |||
### | |||
# 开发环境配置 | |||
ENV = 'development' | |||
@@ -0,0 +1,32 @@ | |||
/* | |||
* @Author: zhp | |||
* @Date: 2024-04-26 14:53:45 | |||
* @LastEditTime: 2024-05-06 14:55:33 | |||
* @LastEditors: zhp | |||
* @Description: | |||
*/ | |||
import request from '@/utils/request' | |||
// 查询部门列表 | |||
export function getOrderList(data) { | |||
return request({ | |||
url: 'ip/prod-order/prodOrderList', | |||
method: 'post', | |||
data: data | |||
}) | |||
} | |||
export function getCostPage(data) { | |||
return request({ | |||
url: 'ip/cost/costPage', | |||
method: 'post', | |||
data: data | |||
}) | |||
} | |||
export function getCostList(data) { | |||
return request({ | |||
url: 'ip/cost/costList', | |||
method: 'post', | |||
data: data | |||
}) | |||
} |
@@ -0,0 +1,15 @@ | |||
/* | |||
* @Author: zhp | |||
* @Date: 2024-04-28 09:28:12 | |||
* @LastEditTime: 2024-04-28 09:43:40 | |||
* @LastEditors: zhp | |||
* @Description: | |||
*/ | |||
import request from '@/utils/request' | |||
export function getEnergyPage(data) { | |||
return request({ | |||
url: 'ip/energy/page', | |||
method: 'post', | |||
data: data | |||
}) | |||
} |
@@ -0,0 +1,32 @@ | |||
/* | |||
* @Author: zhp | |||
* @Date: 2024-04-26 14:53:45 | |||
* @LastEditTime: 2024-05-06 14:53:04 | |||
* @LastEditors: zhp | |||
* @Description: | |||
*/ | |||
import request from '@/utils/request' | |||
// 查询部门列表 | |||
export function getOrderList(data) { | |||
return request({ | |||
url: 'ip/prod-order/prodOrderList', | |||
method: 'post', | |||
data: data | |||
}) | |||
} | |||
export function getEpPage(data) { | |||
return request({ | |||
url: 'ip/environment-protection/environmentPage', | |||
method: 'post', | |||
data: data | |||
}) | |||
} | |||
export function getCostList(data) { | |||
return request({ | |||
url: 'ip/cost/costList', | |||
method: 'post', | |||
data: data | |||
}) | |||
} |
@@ -0,0 +1,32 @@ | |||
/* | |||
* @Author: zhp | |||
* @Date: 2024-05-07 08:54:59 | |||
* @LastEditTime: 2024-05-07 09:34:17 | |||
* @LastEditors: zhp | |||
* @Description: | |||
*/ | |||
/* | |||
* @Author: zhp | |||
* @Date: 2024-04-26 14:53:45 | |||
* @LastEditTime: 2024-05-06 14:53:04 | |||
* @LastEditors: zhp | |||
* @Description: | |||
*/ | |||
import request from '@/utils/request' | |||
// 查询部门列表 | |||
export function getProduceDataPage(data) { | |||
return request({ | |||
url: 'ip/prod-output/prodOutputDataPage', | |||
method: 'post', | |||
data: data | |||
}) | |||
} | |||
export function getProduceDataDetail(data){ | |||
return request({ | |||
url: '/ip/prod-output/get=' + id, | |||
method: 'get', | |||
query: data | |||
}) | |||
} |
@@ -0,0 +1,15 @@ | |||
/* | |||
* @Author: zhp | |||
* @Date: 2024-04-28 09:28:12 | |||
* @LastEditTime: 2024-04-28 15:52:36 | |||
* @LastEditors: zhp | |||
* @Description: | |||
*/ | |||
import request from '@/utils/request' | |||
export function getStockPage(data) { | |||
return request({ | |||
url: 'ip/stock/page', | |||
method: 'post', | |||
data: data | |||
}) | |||
} |
@@ -1,7 +1,7 @@ | |||
<!-- | |||
* @Author: zhp | |||
* @Date: 2024-04-12 11:13:06 | |||
* @LastEditTime: 2024-04-15 13:52:16 | |||
* @LastEditTime: 2024-05-08 13:37:05 | |||
* @LastEditors: zhp | |||
* @Description: | |||
--> | |||
@@ -0,0 +1,87 @@ | |||
/* | |||
* @Author: zhp | |||
* @Date: 2024-04-28 15:18:21 | |||
* @LastEditTime: 2024-04-28 15:18:21 | |||
* @LastEditors: zhp | |||
* @Description: | |||
*/ | |||
/* | |||
* @Date: 2020-12-29 16:49:28 | |||
* @LastEditors: DY | |||
* @LastEditTime: 2024-02-23 14:50:22 | |||
* @FilePath: \basic-admin\src\filters\basicData\index.js | |||
* @Description: | |||
*/ | |||
const table = { | |||
lineStatus: { | |||
1: '生产中', | |||
2: '停止', | |||
3: '未知', | |||
}, | |||
reportType: { | |||
1: '日', | |||
2: '周', | |||
3: '月' | |||
} | |||
} | |||
// 日期格式化 | |||
export function parseTime(time, pattern) { | |||
if (arguments.length === 0 || !time) { | |||
return null | |||
} | |||
const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}' | |||
let date | |||
if (typeof time === 'object') { | |||
date = time | |||
} else { | |||
if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) { | |||
time = parseInt(time) | |||
} else if (typeof time === 'string') { | |||
time = time.replace(new RegExp(/-/gm), '/').replace('T', ' ').replace(new RegExp(/\.\d{3}/gm),''); | |||
} | |||
if ((typeof time === 'number') && (time.toString().length === 10)) { | |||
time = time * 1000 | |||
} | |||
date = new Date(time) | |||
} | |||
const formatObj = { | |||
y: date.getFullYear(), | |||
m: date.getMonth() + 1, | |||
d: date.getDate(), | |||
h: date.getHours(), | |||
i: date.getMinutes(), | |||
s: date.getSeconds(), | |||
a: date.getDay() | |||
} | |||
const time_str = format.replace(/{([ymdhisa])+}/g, (result, key) => { | |||
let value = formatObj[key] | |||
// Note: getDay() returns 0 on Sunday | |||
if (key === 'a') { | |||
return ['日', '一', '二', '三', '四', '五', '六'][value] | |||
} | |||
if (result.length > 0 && value < 10) { | |||
value = '0' + value | |||
} | |||
return value || 0 | |||
}) | |||
return time_str | |||
} | |||
export function toDay(time) { | |||
if (time < 24) { | |||
return time + '小时' | |||
} else { | |||
const day = ~~(time / 24) | |||
const hour = time % 24 | |||
return day + '天' + hour + '小时' | |||
} | |||
} | |||
export default function (dictTable) { | |||
return function (val) { | |||
return table?.[dictTable]?.[val] | |||
} | |||
} |
@@ -1,3 +1,4 @@ | |||
import axios from "@/utils/request"; | |||
import { deepClone } from "../../utils"; | |||
@@ -15,7 +16,25 @@ const state = { | |||
/* 能源驾驶舱 */ | |||
energy: {}, | |||
/* 效率驾驶舱 */ | |||
efficiency: {}, | |||
efficiency: { | |||
chipOee: { | |||
current: [], | |||
previous: [], | |||
}, | |||
transformRate: { | |||
current: [], | |||
previous: [], | |||
}, | |||
chipRate: { | |||
target: [], | |||
current: [], | |||
previous: [], | |||
}, | |||
stdRate: { | |||
target: [], | |||
current: [], | |||
}, | |||
}, | |||
}, | |||
home: { | |||
/** 主页状态 */ | |||
@@ -48,7 +67,11 @@ const mutations = { | |||
state.copilot.energy = payload.data; | |||
break; | |||
case "efficiency": | |||
state.copilot.efficiency = payload.data; | |||
console.log('222222', payload.chipOee) | |||
state.copilot.efficiency.chipOee = payload.chipOee; | |||
state.copilot.efficiency.transformRate = payload.transformRate; | |||
state.copilot.efficiency.chipRate = payload.chipRate; | |||
state.copilot.efficiency.stdRate = payload.stdRate; | |||
break; | |||
} | |||
}, | |||
@@ -64,20 +87,29 @@ const actions = { | |||
}, | |||
/** 初始化驾驶舱数据 */ | |||
async initCopilot({ commit }, { period, source }) { | |||
if (source == "comprehensive") return; | |||
const fetcher = { | |||
yield: getCopilotYield, | |||
energy: getCopilotEnergy, | |||
comprehensive: getCopilotEnergy, | |||
efficiency: getCopilotEfficiency, | |||
}[source]; | |||
const handler = { | |||
yield: splitCurrentAndPrevious, | |||
comprehensive: () => null, | |||
efficiency: splitCurrentAndPreviousA, | |||
}[source]; | |||
// 获取产量数据 | |||
// console.log('qqqqqq',handler) | |||
let { data: factoryList, type } = await fetcher(period); | |||
let targetList = null; | |||
if (source === "yield" || source === "efficiency") { | |||
// 获取目标数据 | |||
let { data } = await fetcher(period, true); | |||
let { data } = await fetcher(period, true) | |||
console.log('11111',data) | |||
targetList = data; | |||
} | |||
const payload = splitCurrentAndPrevious(factoryList, targetList); | |||
const payload = handler(factoryList, targetList); | |||
commit("SET_COPILOT_INFO", { type, payload }); | |||
}, | |||
}; | |||
@@ -89,8 +121,104 @@ export default { | |||
actions, | |||
}; | |||
function splitCurrentAndPreviousA(factoryListResponse, targetListResponse) { | |||
console.log('工厂',factoryListResponse); | |||
// console.log('工厂',factoryListResponse); | |||
// 初始数据 | |||
const { chipOee, transformRate, chipRate, stdRate } = initA(); | |||
factoryListResponse = [ | |||
{ | |||
factory: 0, | |||
oee: 0.8, | |||
previousYearOee: 0.7, | |||
componentConversionEfficiency: 0.8, | |||
previousYearComponentConversionEfficiency: 0.7, | |||
glassType: 0, | |||
yieldRate: 0.8, | |||
previousYearYieldRate: 0.7, | |||
chipYieldRate: 0.38, | |||
componentYieldRate: 0.73, | |||
}, | |||
{ | |||
factory: 1, | |||
oee: 0.8, | |||
previousYearOee: 0.7, | |||
componentConversionEfficiency: 0.8, | |||
previousYearComponentConversionEfficiency: 0.7, | |||
glassType: 1, | |||
yieldRate: 0.8, | |||
previousYearYieldRate: 0.7, | |||
chipYieldRate: 0.38, | |||
componentYieldRate: 0.73, | |||
}, | |||
{ | |||
factory: 2, | |||
oee: 0.8, | |||
previousYearOee: 0.7, | |||
componentConversionEfficiency: 0.8, | |||
previousYearComponentConversionEfficiency: 0.7, | |||
glassType: 1, | |||
yieldRate: 0.8, | |||
previousYearYieldRate: 0.7, | |||
chipYieldRate: 0.38, | |||
componentYieldRate: 0.73, | |||
}, | |||
{ | |||
factory: 3, | |||
oee: 0.8, | |||
previousYearOee: 0.7, | |||
componentConversionEfficiency: 0.8, | |||
previousYearComponentConversionEfficiency: 0.7, | |||
glassType: 0, | |||
yieldRate: 0.8, | |||
previousYearYieldRate: 0.7, | |||
chipYieldRate: 0.38, | |||
componentYieldRate: 0.73, | |||
}, | |||
]; | |||
if (factoryListResponse) { | |||
for (const factory of factoryListResponse) { | |||
const fId = getFactoryId(factory); | |||
// 获取目标值 | |||
if (targetListResponse) { | |||
const { | |||
chipYieldRate, | |||
componentYieldRate, | |||
chipOee, | |||
componentConversionEfficiency, | |||
} = getFactoryTargetValueA(targetListResponse, fId); | |||
stdRate.target[fId] = chipYieldRate; | |||
chipRate.target[fId] = componentYieldRate; | |||
} | |||
// 芯片OEE | |||
chipOee.current[fId] = factory.oee * 100 || random_default(); | |||
chipOee.previous[fId] = factory.previousYearOee * 100 || random_default(); | |||
// 转化效率 | |||
transformRate.current[fId] = | |||
factory.componentConversionEfficiency * 100 || random_default(); | |||
transformRate.previous[fId] = | |||
factory.previousYearComponentConversionEfficiency * 100 || random_default(); | |||
// 芯片良率 与 标准组件良率 | |||
if (![0, 1].includes(factory.glassType)) continue; | |||
const _t = [chipRate, stdRate][factory.glassType]; | |||
_t.current[fId] = factory.yieldRate || random_default(); | |||
_t.previous[fId] = factory.previousYearYieldRate || random_default(); | |||
} | |||
return { | |||
chipOee, | |||
transformRate, | |||
chipRate, | |||
stdRate, | |||
}; | |||
} | |||
} | |||
function splitCurrentAndPrevious(factoryListResponse, targetListResponse) { | |||
// 初始数据 | |||
console.log('工厂',factoryListResponse); | |||
// 初始数据 | |||
const { chipInvest, ftoInvest, chipOutput, stdOutput, bipvOutput } = init(); | |||
if (factoryListResponse) { | |||
for (const factory of factoryListResponse) { | |||
@@ -150,8 +278,57 @@ function getFactoryTargetValue(targetList, factoryId) { | |||
} | |||
/** | |||
* | |||
* @returns 初始化状态值 | |||
* 获取 芯片良率目标值 和 标准组件良率目标值 | |||
* @param {*} targetList 目标值列表 | |||
* @param {*} factoryId 工厂ID | |||
* @returns | |||
*/ | |||
function getFactoryTargetValueA(targetList, factoryId) { | |||
const target = targetList.find((item) => item.factory === factoryId); | |||
if (target) { | |||
return { | |||
chipYieldRate: target.chipYieldRate ?? random_default(), | |||
componentYieldRate: target.componentYieldRate ?? random_default(), | |||
}; | |||
} | |||
return { | |||
chipYieldRate: random_default(), | |||
componentYieldRate: random_default(), | |||
}; | |||
} | |||
/** | |||
* | |||
* @returns 初始化 效率模块里 初始状态值 | |||
*/ | |||
function initA() { | |||
const t_ = { | |||
current: Array(7).fill(0), | |||
previous: Array(7).fill(0), | |||
}; | |||
// 芯片OEE | |||
const chipOee = deepClone(t_); | |||
// 转化效率 | |||
const transformRate = deepClone(t_); | |||
// 标准组件良率 | |||
const stdRate = { | |||
...deepClone(t_), | |||
target: Array(7).fill(0), | |||
}; | |||
// 芯片良率 | |||
const chipRate = deepClone(stdRate); | |||
return { | |||
chipOee, | |||
transformRate, | |||
chipRate, | |||
stdRate, | |||
}; | |||
} | |||
/** | |||
* | |||
* @returns 初始化 产量模块里 初始状态值 | |||
*/ | |||
function init() { | |||
const t_ = { | |||
@@ -181,11 +358,11 @@ function init() { | |||
}; | |||
} | |||
function random_default() { | |||
return 0; | |||
let a = Math.floor(Math.random() * 1000); | |||
while (a < 600) { | |||
a = Math.floor(Math.random() * 1000); | |||
function random_default(min = 0, max = 1) { | |||
// return 0; | |||
let a = Math.floor(Math.random() * max); | |||
while (a < min) { | |||
a = Math.floor(Math.random() * max); | |||
} | |||
return a; | |||
} | |||
@@ -254,10 +431,10 @@ async function doFetch(copilot_module = "yield", fetch_target, params) { | |||
} | |||
/** | |||
* | |||
* | |||
* @param {*} period 日周月年1,2,3,4 | |||
* @param {*} target 是否获取目标数据 | |||
* @returns | |||
* @returns | |||
*/ | |||
function getCopilotYield(period, target = false) { | |||
return getCopilotData("yield", period, target); | |||
@@ -0,0 +1,258 @@ | |||
<!-- | |||
filename: BarChartBase.vue | |||
author: liubin | |||
date: 2024-04-10 08:59:28 | |||
description: | |||
--> | |||
<template> | |||
<chart-container class="bar-chart-base"> | |||
<div class="legend"> | |||
<span | |||
v-for="item in legend" | |||
:key="item.label" | |||
class="legend-item" | |||
:style="{ fontSize: isFullscreen ? '0.58vw' : '0.54vw' }" | |||
>{{ item.label }}</span | |||
> | |||
</div> | |||
<div | |||
ref="chart" | |||
style="max-width: 40vw" | |||
:style="{ height: vHeight + 'vh' }" | |||
></div> | |||
</chart-container> | |||
</template> | |||
<script> | |||
import screenfull from "screenfull"; | |||
import ChartContainer from "./ChartContainer.vue"; | |||
import chartMixin from "@/mixins/chart.js"; | |||
export default { | |||
name: "BarChartBase", | |||
components: { | |||
ChartContainer, | |||
}, | |||
mixins: [chartMixin], | |||
props: { | |||
vHeight: { | |||
type: Number, | |||
default: 34, | |||
}, | |||
legend: { | |||
type: Array, | |||
required: true, | |||
}, | |||
xAxis: { | |||
type: Array, | |||
required: true, | |||
}, | |||
series: { | |||
type: Array, | |||
required: true, | |||
}, | |||
in: { | |||
type: String, | |||
default: "", | |||
}, | |||
}, | |||
data() { | |||
return { | |||
isFullscreen: false, | |||
actualOptions: null, | |||
options: { | |||
grid: { | |||
left: "5%", | |||
right: "4%", | |||
bottom: "3%", | |||
top: "15%", | |||
containLabel: true, | |||
}, | |||
tooltip: {}, | |||
xAxis: { | |||
axisTick: { | |||
show: false, | |||
}, | |||
axisLine: { | |||
lineStyle: { | |||
color: "#4561AE", | |||
}, | |||
}, | |||
axisLabel: { | |||
color: "#fff", | |||
fontSize: 12, | |||
}, | |||
data: this.xAxis, | |||
}, | |||
yAxis: { | |||
name: "单位/片", | |||
nameTextStyle: { | |||
color: "#fff", | |||
fontSize: 12, | |||
}, | |||
axisTick: { | |||
show: false, | |||
}, | |||
axisLabel: { | |||
color: "#fff", | |||
fontSize: 12, | |||
}, | |||
axisLine: { | |||
show: true, | |||
lineStyle: { | |||
color: "#4561AE", | |||
}, | |||
}, | |||
splitLine: { | |||
lineStyle: { | |||
color: "#4561AE", | |||
}, | |||
}, | |||
}, | |||
series: [ | |||
{ | |||
name: "", // this.series[0].name, | |||
type: "bar", | |||
barWidth: 12, | |||
itemStyle: { | |||
borderRadius: [10, 10, 0, 0], | |||
color: { | |||
type: "linear", | |||
x: 0, | |||
y: 0, | |||
x2: 0, | |||
y2: 1, | |||
colorStops: [ | |||
{ | |||
offset: 0, | |||
color: "#12f7f1", // 0% 处的颜色 | |||
}, | |||
{ | |||
offset: 0.35, | |||
color: "#12f7f177", // 100% 处的颜色 | |||
}, | |||
{ | |||
offset: 0.75, | |||
color: "#12f7f133", // 100% 处的颜色 | |||
}, | |||
{ | |||
offset: 1, | |||
color: "transparent", // 100% 处的颜色 | |||
}, | |||
], | |||
global: false, // 缺省为 false | |||
}, | |||
}, | |||
data: [], // this.series[0].data, | |||
}, | |||
{ | |||
name: "", // this.series[1].name, | |||
type: "bar", | |||
barWidth: 12, | |||
// tooltip: { | |||
// valueFormatter: function (value) { | |||
// return value + " ml"; | |||
// }, | |||
// }, | |||
itemStyle: { | |||
borderRadius: [10, 10, 0, 0], | |||
color: { | |||
type: "linear", | |||
x: 0, | |||
y: 0, | |||
x2: 0, | |||
y2: 1, | |||
colorStops: [ | |||
{ | |||
offset: 0, | |||
color: "#57abf8", // 0% 处的颜色 | |||
}, | |||
{ | |||
offset: 1, | |||
color: "#364BFE66", // 100% 处的颜色 | |||
}, | |||
], | |||
global: false, // 缺省为 false | |||
}, | |||
}, | |||
data: [], // this.series[1].data, | |||
}, | |||
], | |||
}, | |||
}; | |||
}, | |||
watch: { | |||
/** 全屏状态切换时,对柱子粗细和字体大小进行相应调整 */ | |||
isFullscreen(val) { | |||
this.actualOptions.series.map((item) => { | |||
item.barWidth = val ? 18 : 12; | |||
}); | |||
this.actualOptions.xAxis.axisLabel.fontSize = val ? 18 : 12; | |||
this.actualOptions.yAxis.axisLabel.fontSize = val ? 18 : 12; | |||
this.actualOptions.yAxis.nameTextStyle.fontSize = val ? 18 : 12; | |||
this.initOptions(this.actualOptions); | |||
}, | |||
series(val) { | |||
if (!val) { | |||
this.initOptions(this.options); | |||
return; | |||
} | |||
const actualOptions = JSON.parse(JSON.stringify(this.options)); | |||
console.log('actualOptions', this.options) | |||
actualOptions.series[0].data = val[0].data; | |||
actualOptions.series[0].name = val[0].name; | |||
actualOptions.series[1].data = val?.[1]?.data || []; | |||
actualOptions.series[1].name = val?.[1]?.name || ""; | |||
this.actualOptions = actualOptions; | |||
this.initOptions(actualOptions); | |||
}, | |||
}, | |||
mounted() { | |||
this.actualOptions = this.options; | |||
this.initOptions(this.options); | |||
if (screenfull.isEnabled) { | |||
screenfull.on("change", () => { | |||
this.isFullscreen = screenfull.isFullscreen; | |||
}); | |||
} | |||
}, | |||
}; | |||
</script> | |||
<style scoped lang="scss"> | |||
.bar-chart-base { | |||
// position: relative; | |||
.legend { | |||
position: absolute; | |||
top: 5.2vh; | |||
right: 1vw; | |||
} | |||
.legend-item { | |||
position: relative; | |||
// font-size: 12px; | |||
margin-right: 0.67vw; | |||
&::before { | |||
content: ""; | |||
display: inline-block; | |||
width: 0.531vw; | |||
height: 0.531vw; | |||
background-color: #ccc; | |||
border-radius: 2px; | |||
margin-right: 0.22vw; | |||
} | |||
} | |||
.legend-item:nth-child(1):before { | |||
background-color: #12f7f1; | |||
} | |||
.legend-item:nth-child(2):before { | |||
background-color: #58adfa; | |||
} | |||
} | |||
</style> |
@@ -1,14 +1,15 @@ | |||
<!-- | |||
<!-- | |||
filename: Container.vue | |||
author: liubin | |||
date: 2024-04-09 10:44:09 | |||
description: | |||
description: | |||
--> | |||
<template> | |||
<div class="copilot-container"> | |||
<!-- refresh btn --> | |||
<button | |||
v-if="0" | |||
style=" | |||
appearance: none; | |||
outline: none; | |||
@@ -109,7 +110,12 @@ export default { | |||
border-radius: 2px; | |||
top: 0%; | |||
left: 0; | |||
background: radial-gradient(circle at center , #024798 2%, #024798 30%, transparent); | |||
background: radial-gradient( | |||
circle at center, | |||
#024798 2%, | |||
#024798 30%, | |||
transparent | |||
); | |||
z-index: 1; | |||
} | |||
@@ -1,8 +1,9 @@ | |||
<!-- | |||
filename: ContainerIcon.vue | |||
author: liubin | |||
date: 2024-04-09 16:41:36 | |||
description: | |||
<!-- | |||
* @Author: zhp | |||
* @Date: 2024-04-28 13:42:51 | |||
* @LastEditTime: 2024-05-07 16:54:54 | |||
* @LastEditors: zhp | |||
* @Description: | |||
--> | |||
<template> | |||
@@ -14,8 +15,13 @@ import cube from "@/assets/images/homeindex/fto-icon.png"; | |||
import chip from "@/assets/images/homeindex/chip-icon.png"; | |||
import chip2 from "@/assets/images/homeindex/chip-icon-2.png"; | |||
import bipv from "@/assets/images/homeindex/bipv-icon.png"; | |||
import water from "@/assets/images/homeindex/water-icon.png"; | |||
import gas from "@/assets/images/homeindex/gas-icon.png"; | |||
import ware from "@/assets/images/homeindex/ware-icon.png"; | |||
import flash from "@/assets/images/homeindex/flash-icon.png"; | |||
import std from "@/assets/images/homeindex/std-icon.png"; | |||
export default { | |||
name: "ContainerIcon", | |||
components: {}, | |||
@@ -40,6 +46,10 @@ export default { | |||
bipv: | |||
"background: url(" + bipv + ") no-repeat center center / 100% 100%", | |||
std: "background: url(" + std + ") no-repeat center center / 100% 100%", | |||
water: "background: url(" + water + ") no-repeat center center / 100% 100%", | |||
gas: "background: url(" + gas + ") no-repeat center center / 100% 100%", | |||
flash: "background: url(" + flash + ") no-repeat center center / 100% 100%", | |||
ware: "background: url(" + ware + ") no-repeat center center / 100% 100%", | |||
}[this.icon]; | |||
}, | |||
}, | |||
@@ -1,15 +1,15 @@ | |||
<!-- | |||
<!-- | |||
filename: CopilotHeader.vue | |||
author: liubin | |||
date: 2024-04-16 15:14:01 | |||
description: | |||
description: | |||
--> | |||
<template> | |||
<div class="copilot-header"> | |||
<section class="menu"> | |||
<CopilotButton | |||
v-for="i in ['产量', '效率', '能源']" | |||
v-for="i in ['产量', '效率', '综合']" | |||
:key="i" | |||
:label="i" | |||
:active="i === active" | |||
@@ -63,7 +63,7 @@ export default { | |||
toggleFullScreen() { | |||
this.isFullscreen = !this.isFullscreen; | |||
screenfull.toggle(document.querySelector(".copilot-layout")); | |||
screenfull.toggle(document.querySelector(".copilot-layout")) | |||
// 矫正宽度 | |||
// const el = document.querySelector(".copilot-layout"); | |||
// el.style.width = this.isFullscreen ? "100vw" : "calc(100vw - 54px)"; | |||
@@ -0,0 +1,296 @@ | |||
<!-- | |||
filename: LineChartBase.vue | |||
author: liubin | |||
date: 2024-04-30 08:59:28 | |||
description: | |||
--> | |||
<template> | |||
<chart-container class="line-chart-base"> | |||
<div class="legend"> | |||
<span | |||
v-for="item in legend" | |||
:key="item.label" | |||
class="legend-item" | |||
:style="{ fontSize: isFullscreen ? '0.58vw' : '0.54vw' }" | |||
>{{ item.label }}</span | |||
> | |||
</div> | |||
<div | |||
ref="chart" | |||
style="max-width: 50vw" | |||
:style="{ height: vHeight + 'vh' }" | |||
></div> | |||
</chart-container> | |||
</template> | |||
<script> | |||
import screenfull from "screenfull"; | |||
import ChartContainer from "./ChartContainer.vue"; | |||
import chartMixin from "@/mixins/chart.js"; | |||
export default { | |||
name: "LineChartBase", | |||
components: { | |||
ChartContainer, | |||
}, | |||
mixins: [chartMixin], | |||
props: { | |||
vHeight: { | |||
type: Number, | |||
default: 34, | |||
}, | |||
legend: { | |||
type: Array, | |||
required: true, | |||
}, | |||
xAxis: { | |||
type: Array, | |||
required: true, | |||
}, | |||
series: { | |||
type: Array, | |||
required: true, | |||
}, | |||
in: { | |||
type: String, | |||
default: "", | |||
}, | |||
}, | |||
data() { | |||
return { | |||
isFullscreen: false, | |||
actualOptions: null, | |||
options: { | |||
grid: { | |||
left: "5%", | |||
right: "4%", | |||
bottom: "3%", | |||
top: "15%", | |||
containLabel: true, | |||
}, | |||
tooltip: {}, | |||
xAxis: { | |||
axisTick: { | |||
show: false, | |||
}, | |||
axisLine: { | |||
lineStyle: { | |||
color: "#4561AE", | |||
}, | |||
}, | |||
axisLabel: { | |||
color: "#fff", | |||
fontSize: 12, | |||
}, | |||
data: this.xAxis, | |||
}, | |||
yAxis: { | |||
name: "单位/片", | |||
nameTextStyle: { | |||
color: "#fff", | |||
fontSize: 12, | |||
}, | |||
axisTick: { | |||
show: false, | |||
}, | |||
axisLabel: { | |||
color: "#fff", | |||
fontSize: 12, | |||
}, | |||
axisLine: { | |||
show: true, | |||
lineStyle: { | |||
color: "#4561AE", | |||
}, | |||
}, | |||
splitLine: { | |||
lineStyle: { | |||
color: "#4561AE", | |||
}, | |||
}, | |||
}, | |||
series: [ | |||
{ | |||
name: "", // this.series[0].name, | |||
type: "bar", | |||
barWidth: 12, | |||
itemStyle: { | |||
borderRadius: [10, 10, 0, 0], | |||
color: { | |||
type: "linear", | |||
x: 0, | |||
y: 0, | |||
x2: 0, | |||
y2: 1, | |||
colorStops: [ | |||
{ | |||
offset: 0, | |||
color: "#12f7f1", // 0% 处的颜色 | |||
}, | |||
{ | |||
offset: 0.35, | |||
color: "#12f7f177", // 100% 处的颜色 | |||
}, | |||
{ | |||
offset: 0.75, | |||
color: "#12f7f133", // 100% 处的颜色 | |||
}, | |||
{ | |||
offset: 1, | |||
color: "transparent", // 100% 处的颜色 | |||
}, | |||
], | |||
global: false, // 缺省为 false | |||
}, | |||
}, | |||
data: [], // this.series[0].data, | |||
}, | |||
{ | |||
name: "", // this.series[1].name, | |||
type: "bar", | |||
barWidth: 12, | |||
// tooltip: { | |||
// valueFormatter: function (value) { | |||
// return value + " ml"; | |||
// }, | |||
// }, | |||
itemStyle: { | |||
borderRadius: [10, 10, 0, 0], | |||
color: { | |||
type: "linear", | |||
x: 0, | |||
y: 0, | |||
x2: 0, | |||
y2: 1, | |||
colorStops: [ | |||
{ | |||
offset: 0, | |||
color: "#57abf8", // 0% 处的颜色 | |||
}, | |||
{ | |||
offset: 1, | |||
color: "#364BFE66", // 100% 处的颜色 | |||
}, | |||
], | |||
global: false, // 缺省为 false | |||
}, | |||
}, | |||
data: [], // this.series[1].data, | |||
}, | |||
], | |||
}, | |||
}; | |||
}, | |||
watch: { | |||
/** 全屏状态切换时,对柱子粗细和字体大小进行相应调整 */ | |||
isFullscreen(val) { | |||
this.actualOptions.series.map((item) => { | |||
item.barWidth = val ? 18 : 12; | |||
}); | |||
this.actualOptions.xAxis.axisLabel.fontSize = val ? 18 : 12; | |||
this.actualOptions.yAxis.axisLabel.fontSize = val ? 18 : 12; | |||
this.actualOptions.yAxis.nameTextStyle.fontSize = val ? 18 : 12; | |||
this.initOptions(this.actualOptions); | |||
}, | |||
series(val) { | |||
if (!val) { | |||
this.initOptions(this.options); | |||
return; | |||
} | |||
const actualOptions = JSON.parse(JSON.stringify(this.options)); | |||
actualOptions.series[0].data = val[0].data; | |||
actualOptions.series[0].name = val[0].name; | |||
actualOptions.series[1].data = val?.[1]?.data || []; | |||
actualOptions.series[1].name = val?.[1]?.name || ""; | |||
this.actualOptions = actualOptions; | |||
this.initOptions(actualOptions); | |||
}, | |||
}, | |||
mounted() { | |||
this.actualOptions = this.options; | |||
this.initOptions(this.options); | |||
if (screenfull.isEnabled) { | |||
screenfull.on("change", () => { | |||
this.isFullscreen = screenfull.isFullscreen; | |||
}); | |||
} | |||
}, | |||
}; | |||
</script> | |||
<style scoped lang="scss"> | |||
.line-chart-base { | |||
// position: relative; | |||
.legend { | |||
position: absolute; | |||
top: 5.2vh; | |||
right: 1vw; | |||
} | |||
.legend-item { | |||
position: relative; | |||
// font-size: 12px; | |||
margin-right: 0.67vw; | |||
&::before { | |||
content: ""; | |||
display: inline-block; | |||
width: 0.432vw; | |||
height: 0.432vw; | |||
border-radius: 100%; | |||
margin-right: 0.4vw; | |||
} | |||
&::after { | |||
content: ""; | |||
display: inline-block; | |||
width: 1vw; | |||
height: 0.125vw; | |||
position: absolute; | |||
top: 54%; | |||
left: -15%; | |||
transform: translateY(-50%); | |||
border-radius: 100; | |||
margin-right: 0.22vw; | |||
} | |||
} | |||
.legend-item:nth-child(1):after, | |||
.legend-item:nth-child(1):before { | |||
background-color: #fad162; | |||
} | |||
.legend-item:nth-child(2):after, | |||
.legend-item:nth-child(2):before { | |||
background-color: #2160f3; | |||
} | |||
.legend-item:nth-child(3):after, | |||
.legend-item:nth-child(3):before { | |||
background-color: #13dbf3; | |||
} | |||
.legend-item:nth-child(4):after, | |||
.legend-item:nth-child(4):before { | |||
background-color: #88ca67; | |||
} | |||
.legend-item:nth-child(5):after, | |||
.legend-item:nth-child(5):before { | |||
background-color: #5c97fc; | |||
} | |||
.legend-item:nth-child(6):after, | |||
.legend-item:nth-child(6):before { | |||
background-color: #f48900; | |||
} | |||
.legend-item:nth-child(7):after, | |||
.legend-item:nth-child(7):before { | |||
background-color: #776bf0; | |||
} | |||
} | |||
</style> |
@@ -1,21 +1,17 @@ | |||
<!-- | |||
<!-- | |||
filename: container.vue | |||
author: liubin | |||
date: 2024-04-16 14:51:25 | |||
description: | |||
description: | |||
--> | |||
<template> | |||
<div class="copilot-layout"> | |||
<CopilotHeaderVue | |||
:active="page" | |||
:period="period" | |||
@update:active="page = $event" | |||
@update:period="period = $event" | |||
/> | |||
<div class="copilot-layout" ref="copilot-layout"> | |||
<CopilotHeaderVue :active="page" :period="period" @update:active="page = $event" @update:period="period = $event" /> | |||
<YieldCopilot v-if="page == '产量'" :period="period" /> | |||
<EnergyCopilot v-if="page == '能源'" :period="period" /> | |||
<EnergyCopilot v-if="page == '综合'" :period="period" /> | |||
<EfficiencyCopilot v-if="page == '效率'" :period="period" /> | |||
<div class="copilot-footer">© 中建材智能自动化研究院有限公司</div> | |||
@@ -52,8 +48,8 @@ export default { | |||
// }, | |||
}; | |||
</script> | |||
<style> | |||
.copilot-layout { | |||
padding: 16px; | |||
background: url(../../assets/images/copilot-bg.png) 0 0 / 100% 100% no-repeat; | |||
@@ -0,0 +1,38 @@ | |||
<!-- | |||
filename: BipvOutput.vue | |||
author: liubin | |||
date: 2024-04-17 09:55:12 | |||
description: | |||
--> | |||
<template> | |||
<DoubleRingWrapperVue data-source="BIPV产出" :period="period" /> | |||
</template> | |||
<script> | |||
import DoubleRingWrapperVue from "./sub/ring/DoubleRingWrapper.vue"; | |||
export default { | |||
name: "BipvOutput", | |||
components: { DoubleRingWrapperVue }, | |||
props: { | |||
period: { | |||
type: String, | |||
default: "日", | |||
}, | |||
}, | |||
data() { | |||
return {}; | |||
}, | |||
}; | |||
</script> | |||
<style scoped lang="scss"> | |||
.flex-1 { | |||
flex: 1; | |||
} | |||
.stretch { | |||
align-self: stretch; | |||
} | |||
</style> |
@@ -0,0 +1,106 @@ | |||
<!-- | |||
filename: FtoInvest.vue | |||
author: liubin | |||
date: 2024-04-10 08:59:28 | |||
description: | |||
--> | |||
<template> | |||
<BarChartBase | |||
:legend="legend" | |||
:series="series" | |||
:xAxis="xAxis" | |||
in="ChipInvest" | |||
class="chip-invest-chart" | |||
/> | |||
</template> | |||
<script> | |||
import BarChartBase from "./sub/bar/BarChartBase.vue"; | |||
export default { | |||
name: "ChipInvest", | |||
components: { BarChartBase }, | |||
data() { | |||
// 城市数组的顺序必须是固定的 | |||
const cities = ["瑞昌", "邯郸", "株洲", "佳木斯", "成都", "凯盛", "蚌埠"]; | |||
return { | |||
xAxis: cities, | |||
}; | |||
}, | |||
props: { | |||
period: { | |||
type: String, | |||
default: "日", | |||
}, | |||
}, | |||
computed: { | |||
legend() { | |||
switch (this.period) { | |||
case "日": | |||
return [{ label: "昨日", color: "#12f7f1" }]; | |||
case "周": | |||
return [{ label: "本周", color: "#12f7f1" }]; | |||
case "月": { | |||
const year = new Date().getFullYear(); | |||
const month = new Date().getMonth() + 1; | |||
return [ | |||
{ label: `${year - 1}年${month}月`, color: "#12f7f1" }, | |||
{ label: `${year}年${month}月`, color: "#58adfa" }, | |||
]; | |||
} | |||
case "年": { | |||
const year = new Date().getFullYear(); | |||
return [ | |||
{ label: `${year - 1}年`, color: "#12f7f1" }, | |||
{ label: `${year}年`, color: "#58adfa" }, | |||
]; | |||
} | |||
default: | |||
return [ | |||
{ label: `${year - 1}年`, color: "#12f7f1" }, | |||
{ label: `${year}年`, color: "#58adfa" }, | |||
]; | |||
} | |||
}, | |||
series() { | |||
const { chipInvest } = this.$store.getters.copilot.yield; | |||
let dataList = null; | |||
switch (this.period) { | |||
case "日": | |||
case "周": | |||
dataList = chipInvest?.current; | |||
break; | |||
default: | |||
dataList = []; | |||
dataList[0] = chipInvest?.pervious; | |||
dataList[1] = chipInvest?.current; | |||
} | |||
return getTemplate(this.period, dataList); | |||
}, | |||
}, | |||
}; | |||
function getTemplate(period, dataList) { | |||
const year = new Date().getFullYear(); | |||
const month = new Date().getMonth() + 1; | |||
return period == "日" || period == "周" | |||
? [ | |||
{ | |||
name: period == "日" ? "昨日" : "本周", | |||
data: dataList ?? [], | |||
}, | |||
] | |||
: [ | |||
{ | |||
name: period == "年" ? `${year - 1}年` : `${year - 1}年${month}月`, | |||
data: dataList ? dataList[0] : [], | |||
}, | |||
{ | |||
name: period == "年" ? `${year}年` : `${year}年${month}月`, | |||
data: dataList ? dataList[1] : [], | |||
// : Array.from({ length: 7 }, () => Math.floor(Math.random() * 1000)), | |||
}, | |||
]; | |||
} | |||
</script> |
@@ -0,0 +1,113 @@ | |||
<!-- | |||
filename: ChipOee.vue | |||
author: liubin | |||
date: 2024-04-29 08:51:04 | |||
description: 芯片OEE | |||
--> | |||
<template> | |||
<BarChartBase | |||
:legend="legend" | |||
:series="series" | |||
:xAxis="xAxis" | |||
in="chipOEE" | |||
class="chip-oee" | |||
/> | |||
</template> | |||
<script> | |||
import BarChartBase from "@/views/copilot/efficiency/components/sub/bar/BarChartChipOEE.vue"; | |||
export default { | |||
name: "ChipOEE", | |||
components: { BarChartBase }, | |||
props: { | |||
period: { | |||
type: String, | |||
default: "日", | |||
}, | |||
}, | |||
data() { | |||
// 城市数组的顺序必须是固定的 | |||
const cities = ["瑞昌", "邯郸", "株洲", "佳木斯", "成都", "凯盛", "蚌埠"]; | |||
return { | |||
xAxis: cities, | |||
}; | |||
}, | |||
computed: { | |||
legend() { | |||
switch (this.period) { | |||
case "日": | |||
return [{ label: "昨日", color: "#12f7f1" }]; | |||
case "周": | |||
return [{ label: "本周", color: "#12f7f1" }]; | |||
case "月": { | |||
const year = new Date().getFullYear(); | |||
const month = new Date().getMonth() + 1; | |||
return [ | |||
{ label: `${year - 1}年${month}月`, color: "#12f7f1" }, | |||
{ label: `${year}年${month}月`, color: "#58adfa" }, | |||
]; | |||
} | |||
case "年": { | |||
const year = new Date().getFullYear(); | |||
return [ | |||
{ label: `${year - 1}年`, color: "#12f7f1" }, | |||
{ label: `${year}年`, color: "#58adfa" }, | |||
]; | |||
} | |||
default: | |||
return [ | |||
{ label: `${year - 1}年`, color: "#12f7f1" }, | |||
{ label: `${year}年`, color: "#58adfa" }, | |||
]; | |||
} | |||
}, | |||
series() { | |||
// console.log('aaaaaaaa', this.$store.getters.copilot.efficiency.chipOee); | |||
const { chipOee } = this.$store.getters.copilot.efficiency; | |||
let dataList = null; | |||
switch (this.period) { | |||
case "日": | |||
case "周": | |||
dataList = chipOee?.current; | |||
case "周": | |||
dataList = chipOee?.current; | |||
break; | |||
default: | |||
dataList = []; | |||
dataList[0] = chipOee?.previous; | |||
dataList[1] = chipOee?.current; | |||
} | |||
// console.log(dataList) | |||
return getTemplate(this.period, dataList); | |||
}, | |||
}, | |||
methods: {}, | |||
}; | |||
function getTemplate(period, dataList) { | |||
const year = new Date().getFullYear(); | |||
const month = new Date().getMonth() + 1; | |||
console.log('11111', dataList); | |||
return period == "日" || period == "周" | |||
? [ | |||
{ | |||
name: period == "日" ? "昨日" : "本周", | |||
data: dataList ?? [], | |||
}, | |||
] | |||
: [ | |||
{ | |||
name: period == "年" ? `${year - 1}年` : `${year - 1}年${month}月`, | |||
data: dataList ? dataList[0] : [], | |||
}, | |||
{ | |||
name: period == "年" ? `${year}年` : `${year}年${month}月`, | |||
data: dataList ? dataList[1] : [], | |||
// : Array.from({ length: 7 }, () => Math.floor(Math.random() * 1000)), | |||
}, | |||
]; | |||
} | |||
</script> | |||
<style scoped lang="scss"></style> |
@@ -0,0 +1,38 @@ | |||
<!-- | |||
filename: ChipOutput.vue | |||
author: liubin | |||
date: 2024-04-17 09:55:12 | |||
description: | |||
--> | |||
<template> | |||
<DoubleRingWrapperVue data-source="芯片产出" :period="period" /> | |||
</template> | |||
<script> | |||
import DoubleRingWrapperVue from "./sub/ring/DoubleRingWrapper.vue"; | |||
export default { | |||
name: "ChipOutput", | |||
components: { DoubleRingWrapperVue }, | |||
props: { | |||
period: { | |||
type: String, | |||
default: "日", | |||
}, | |||
}, | |||
data() { | |||
return {}; | |||
}, | |||
}; | |||
</script> | |||
<style scoped lang="scss"> | |||
.flex-1 { | |||
flex: 1; | |||
} | |||
.stretch { | |||
align-self: stretch; | |||
} | |||
</style> |
@@ -0,0 +1,60 @@ | |||
<!-- | |||
filename: ChipRate.vue | |||
author: liubin | |||
date: 2024-04-29 08:50:54 | |||
description: 芯片良率 | |||
--> | |||
<template> | |||
<div class="chip-rate"> | |||
<ChipRateItem | |||
:period="period" | |||
:cities="['成都', '邯郸', '株洲', '瑞昌']" | |||
:color="1" | |||
/> | |||
<ChipRateItem | |||
:period="period" | |||
:cities="['佳木斯', '凯盛光伏', '蚌埠兴科']" | |||
:color="2" | |||
/> | |||
</div> | |||
</template> | |||
<script> | |||
import ChipRateItemVue from "./sub/chip/ChipRateItem.vue"; | |||
export default { | |||
name: "ChipRate", | |||
components: { ChipRateItem: ChipRateItemVue }, | |||
props: { | |||
period: { | |||
type: String, | |||
default: "日", | |||
}, | |||
}, | |||
data() { | |||
return {}; | |||
}, | |||
computed: {}, | |||
methods: {}, | |||
}; | |||
</script> | |||
<style scoped lang="scss"> | |||
.chip-rate { | |||
flex: 1; | |||
display: flex; | |||
gap: 5px; | |||
position: relative; | |||
&:after { | |||
content: ""; | |||
position: absolute; | |||
left: 50%; | |||
top: 0; | |||
width: 3px; | |||
height: 100%; | |||
transform: translateX(-50%); | |||
background: linear-gradient(to bottom, transparent, #00f2ff, transparent); | |||
} | |||
} | |||
</style> |
@@ -0,0 +1,108 @@ | |||
<!-- | |||
filename: FtoInvest.vue | |||
author: liubin | |||
date: 2024-04-10 08:59:28 | |||
description: | |||
--> | |||
<template> | |||
<BarChartBase | |||
:legend="legend" | |||
:series="series" | |||
:xAxis="xAxis" | |||
in="ftoInvest" | |||
class="fto-chart" | |||
/> | |||
</template> | |||
<script> | |||
import BarChartBase from "./sub/bar/BarChartBase.vue"; | |||
export default { | |||
name: "FtoInvest", | |||
components: { BarChartBase }, | |||
data() { | |||
// 城市数组的顺序必须是固定的 | |||
const cities = ["瑞昌", "邯郸", "株洲", "佳木斯", "成都", "凯盛", "蚌埠"]; | |||
return { | |||
xAxis: cities, | |||
}; | |||
}, | |||
props: { | |||
period: { | |||
type: String, | |||
default: "日", | |||
}, | |||
}, | |||
computed: { | |||
legend() { | |||
switch (this.period) { | |||
case "日": | |||
return [{ label: "昨日", color: "#12f7f1" }]; | |||
case "周": | |||
return [{ label: "本周", color: "#12f7f1" }]; | |||
case "月": { | |||
const year = new Date().getFullYear(); | |||
const month = new Date().getMonth() + 1; | |||
return [ | |||
{ label: `${year - 1}年${month}月`, color: "#12f7f1" }, | |||
{ label: `${year}年${month}月`, color: "#58adfa" }, | |||
]; | |||
} | |||
case "年": { | |||
const year = new Date().getFullYear(); | |||
return [ | |||
{ label: `${year - 1}年`, color: "#12f7f1" }, | |||
{ label: `${year}年`, color: "#58adfa" }, | |||
]; | |||
} | |||
default: | |||
return [ | |||
{ label: `${year - 1}年`, color: "#12f7f1" }, | |||
{ label: `${year}年`, color: "#58adfa" }, | |||
]; | |||
} | |||
}, | |||
series() { | |||
const { ftoInvest } = this.$store.getters.copilot.yield; | |||
let dataList = null; | |||
switch (this.period) { | |||
case "日": | |||
case "周": | |||
dataList = ftoInvest?.current; | |||
break; | |||
default: | |||
dataList = []; | |||
dataList[0] = ftoInvest?.pervious; | |||
dataList[1] = ftoInvest?.current; | |||
} | |||
return getTemplate(this.period, dataList); | |||
}, | |||
}, | |||
}; | |||
function getTemplate(period, dataList) { | |||
const year = new Date().getFullYear(); | |||
const month = new Date().getMonth() + 1; | |||
return period == "日" || period == "周" | |||
? [ | |||
{ | |||
name: period == "日" ? "昨日" : "本周", | |||
data: dataList ?? [], | |||
}, | |||
] | |||
: [ | |||
{ | |||
name: period == "年" ? `${year - 1}年` : `${year - 1}年${month}月`, | |||
data: dataList ? dataList[0] : [], | |||
}, | |||
{ | |||
name: period == "年" ? `${year}年` : `${year}年${month}月`, | |||
data: dataList ? dataList[1] : [], | |||
// : Array.from({ length: 7 }, () => Math.floor(Math.random() * 1000)), | |||
}, | |||
]; | |||
} | |||
</script> |
@@ -0,0 +1,38 @@ | |||
<!-- | |||
filename: StdOutput.vue | |||
author: liubin | |||
date: 2024-04-17 09:55:12 | |||
description: | |||
--> | |||
<template> | |||
<DoubleRingWrapperVue data-source="标准组件产出" :period="period" /> | |||
</template> | |||
<script> | |||
import DoubleRingWrapperVue from "./sub/ring/DoubleRingWrapper.vue"; | |||
export default { | |||
name: "StdOutput", | |||
components: { DoubleRingWrapperVue }, | |||
props: { | |||
period: { | |||
type: String, | |||
default: "日", | |||
}, | |||
}, | |||
data() { | |||
return {}; | |||
}, | |||
}; | |||
</script> | |||
<style scoped lang="scss"> | |||
.flex-1 { | |||
flex: 1; | |||
} | |||
.stretch { | |||
align-self: stretch; | |||
} | |||
</style> |
@@ -0,0 +1,62 @@ | |||
<!-- | |||
* @Author: zhp | |||
* @Date: 2024-05-07 10:25:10 | |||
* @LastEditTime: 2024-05-08 15:55:24 | |||
* @LastEditors: zhp | |||
* @Description: | |||
--> | |||
<template> | |||
<div class="std-rate"> | |||
<div class="span-2"> | |||
<StdRateItem :period="period" :city="cities[5]" /> | |||
</div> | |||
<div v-for="item in cities.filter((val, index) => index != 5)" :key="item.name"> | |||
<StdRateItem :period="period" :city="item" /> | |||
</div> | |||
</div> | |||
</template> | |||
<script> | |||
import StdRateItem from "./sub/std/StdRateItem.vue"; | |||
export default { | |||
name: "StdRate", | |||
components: { StdRateItem }, | |||
props: { | |||
period: { | |||
type: String, | |||
default: "日", | |||
}, | |||
}, | |||
data() { | |||
return { | |||
cities: [ | |||
{ name: "瑞昌", target: 100, total: 200, thisYear: 20 }, | |||
{ name: "邯郸", target: 200, total: 300, thisYear: 20 }, | |||
{ name: "株洲", target: 300, total: 400, thisYear: 20 }, | |||
{ name: "佳木斯", target: 400, total: 500, thisYear: 20 }, | |||
{ name: "成都", target: 500, total: 600, thisYear: 20 }, | |||
{ name: "凯盛光伏", target: 400, total: 500, thisYear: 20 }, | |||
{ name: "蚌埠", target: 500, total: 600, thisYear: 20 }, | |||
], | |||
}; | |||
}, | |||
computed: { | |||
}, | |||
methods: {}, | |||
}; | |||
</script> | |||
<style scoped lang="scss"> | |||
.std-rate { | |||
display: grid; | |||
gap: 8px; | |||
grid-template-columns: repeat(2, 1fr); | |||
grid-template-rows: repeat(1, 1fr); | |||
} | |||
.span-2 { | |||
grid-column: span 2; | |||
} | |||
</style> |
@@ -0,0 +1,110 @@ | |||
<!-- | |||
filename: TransformRate.vue | |||
author: liubin | |||
date: 2024-04-29 08:50:34 | |||
description: 转化效率 | |||
--> | |||
<template> | |||
<BarChartBase | |||
:legend="legend" | |||
:series="series" | |||
:xAxis="xAxis" | |||
in="chipOEE" | |||
class="chip-oee" | |||
/> | |||
</template> | |||
<script> | |||
import BarChartBase from "@/views/copilot/efficiency/components/sub/bar/BarChartChipOEE.vue"; | |||
export default { | |||
name: "TransformRate", | |||
components: { BarChartBase }, | |||
props: { | |||
period: { | |||
type: String, | |||
default: "日", | |||
}, | |||
}, | |||
data() { | |||
// 城市数组的顺序必须是固定的 | |||
const cities = ["瑞昌", "邯郸", "株洲", "佳木斯", "成都", "凯盛", "蚌埠"]; | |||
return { | |||
xAxis: cities, | |||
}; | |||
}, | |||
computed: { | |||
legend() { | |||
switch (this.period) { | |||
case "日": | |||
return [{ label: "昨日", color: "#12f7f1" }]; | |||
case "周": | |||
return [{ label: "本周", color: "#12f7f1" }]; | |||
case "月": { | |||
const year = new Date().getFullYear(); | |||
const month = new Date().getMonth() + 1; | |||
return [ | |||
{ label: `${year - 1}年${month}月`, color: "#12f7f1" }, | |||
{ label: `${year}年${month}月`, color: "#58adfa" }, | |||
]; | |||
} | |||
case "年": { | |||
const year = new Date().getFullYear(); | |||
return [ | |||
{ label: `${year - 1}年`, color: "#12f7f1" }, | |||
{ label: `${year}年`, color: "#58adfa" }, | |||
]; | |||
} | |||
default: | |||
return [ | |||
{ label: `${year - 1}年`, color: "#12f7f1" }, | |||
{ label: `${year}年`, color: "#58adfa" }, | |||
]; | |||
} | |||
}, | |||
series() { | |||
const { transformRate } = this.$store.getters.copilot.efficiency; | |||
let dataList = null; | |||
switch (this.period) { | |||
case "日": | |||
case "周": | |||
dataList = transformRate?.current; | |||
break; | |||
default: | |||
dataList = []; | |||
dataList[0] = transformRate?.previous; | |||
dataList[1] = transformRate?.current; | |||
} | |||
return getTemplate(this.period, dataList); | |||
}, | |||
}, | |||
methods: {}, | |||
}; | |||
function getTemplate(period, dataList) { | |||
const year = new Date().getFullYear(); | |||
const month = new Date().getMonth() + 1; | |||
return period == "日" || period == "周" | |||
? [ | |||
{ | |||
name: period == "日" ? "昨日" : "本周", | |||
data: dataList ?? [], | |||
}, | |||
] | |||
: [ | |||
{ | |||
name: period == "年" ? `${year - 1}年` : `${year - 1}年${month}月`, | |||
data: dataList ? dataList[0] : [], | |||
}, | |||
{ | |||
name: period == "年" ? `${year}年` : `${year}年${month}月`, | |||
data: dataList ? dataList[1] : [], | |||
// : Array.from({ length: 7 }, () => Math.floor(Math.random() * 1000)), | |||
}, | |||
]; | |||
} | |||
</script> | |||
<style scoped lang="scss"></style> |
@@ -0,0 +1,258 @@ | |||
<!-- | |||
* @Author: zhp | |||
* @Date: 2024-05-07 13:22:43 | |||
* @LastEditTime: 2024-05-08 15:52:09 | |||
* @LastEditors: zhp | |||
* @Description: | |||
--> | |||
<template> | |||
<chart-container class="bar-chart-base"> | |||
<div class="legend"> | |||
<span | |||
v-for="item in legend" | |||
:key="item.label" | |||
class="legend-item" | |||
:style="{ fontSize: isFullscreen ? '0.58vw' : '0.54vw' }" | |||
>{{ item.label }}</span | |||
> | |||
</div> | |||
<div | |||
ref="chart" | |||
style="max-width: 40vw" | |||
:style="{ height: vHeight + 'vh' }" | |||
></div> | |||
</chart-container> | |||
</template> | |||
<script> | |||
import screenfull from "screenfull"; | |||
import ChartContainer from "../../../../components/ChartContainer.vue"; | |||
import chartMixin from "@/mixins/chart.js"; | |||
export default { | |||
name: "BarChartBase", | |||
components: { | |||
ChartContainer, | |||
}, | |||
mixins: [chartMixin], | |||
props: { | |||
vHeight: { | |||
type: Number, | |||
default: 34, | |||
}, | |||
legend: { | |||
type: Array, | |||
required: true, | |||
}, | |||
xAxis: { | |||
type: Array, | |||
required: true, | |||
}, | |||
series: { | |||
type: Array, | |||
required: true, | |||
}, | |||
in: { | |||
type: String, | |||
default: "", | |||
}, | |||
}, | |||
data() { | |||
return { | |||
isFullscreen: false, | |||
actualOptions: null, | |||
options: { | |||
grid: { | |||
left: "5%", | |||
right: "4%", | |||
bottom: "3%", | |||
top: "15%", | |||
containLabel: true, | |||
}, | |||
tooltip: {}, | |||
xAxis: { | |||
axisTick: { | |||
show: false, | |||
}, | |||
axisLine: { | |||
lineStyle: { | |||
color: "#4561AE", | |||
}, | |||
}, | |||
axisLabel: { | |||
color: "#fff", | |||
fontSize: 12, | |||
}, | |||
data: this.xAxis, | |||
}, | |||
yAxis: { | |||
name: "单位/%", | |||
nameTextStyle: { | |||
color: "#fff", | |||
fontSize: 12, | |||
}, | |||
axisTick: { | |||
show: false, | |||
}, | |||
axisLabel: { | |||
color: "#fff", | |||
fontSize: 12, | |||
}, | |||
axisLine: { | |||
show: true, | |||
lineStyle: { | |||
color: "#4561AE", | |||
}, | |||
}, | |||
splitLine: { | |||
lineStyle: { | |||
color: "#4561AE", | |||
}, | |||
}, | |||
}, | |||
series: [ | |||
{ | |||
name: "", // this.series[0].name, | |||
type: "bar", | |||
barWidth: 12, | |||
itemStyle: { | |||
borderRadius: [10, 10, 0, 0], | |||
color: { | |||
type: "linear", | |||
x: 0, | |||
y: 0, | |||
x2: 0, | |||
y2: 1, | |||
colorStops: [ | |||
{ | |||
offset: 0, | |||
color: "#12f7f1", // 0% 处的颜色 | |||
}, | |||
{ | |||
offset: 0.35, | |||
color: "#12f7f177", // 100% 处的颜色 | |||
}, | |||
{ | |||
offset: 0.75, | |||
color: "#12f7f133", // 100% 处的颜色 | |||
}, | |||
{ | |||
offset: 1, | |||
color: "transparent", // 100% 处的颜色 | |||
}, | |||
], | |||
global: false, // 缺省为 false | |||
}, | |||
}, | |||
data: [], // this.series[0].data, | |||
}, | |||
{ | |||
name: "", // this.series[1].name, | |||
type: "bar", | |||
barWidth: 12, | |||
// tooltip: { | |||
// valueFormatter: function (value) { | |||
// return value + " ml"; | |||
// }, | |||
// }, | |||
itemStyle: { | |||
borderRadius: [10, 10, 0, 0], | |||
color: { | |||
type: "linear", | |||
x: 0, | |||
y: 0, | |||
x2: 0, | |||
y2: 1, | |||
colorStops: [ | |||
{ | |||
offset: 0, | |||
color: "#57abf8", // 0% 处的颜色 | |||
}, | |||
{ | |||
offset: 1, | |||
color: "#364BFE66", // 100% 处的颜色 | |||
}, | |||
], | |||
global: false, // 缺省为 false | |||
}, | |||
}, | |||
data: [], // this.series[1].data, | |||
}, | |||
], | |||
}, | |||
}; | |||
}, | |||
watch: { | |||
/** 全屏状态切换时,对柱子粗细和字体大小进行相应调整 */ | |||
isFullscreen(val) { | |||
this.actualOptions.series.map((item) => { | |||
item.barWidth = val ? 18 : 12; | |||
}); | |||
this.actualOptions.xAxis.axisLabel.fontSize = val ? 18 : 12; | |||
this.actualOptions.yAxis.axisLabel.fontSize = val ? 18 : 12; | |||
this.actualOptions.yAxis.nameTextStyle.fontSize = val ? 18 : 12; | |||
this.initOptions(this.actualOptions); | |||
}, | |||
series(val) { | |||
if (!val) { | |||
this.initOptions(this.options); | |||
return; | |||
} | |||
console.log(val) | |||
const actualOptions = JSON.parse(JSON.stringify(this.options)) | |||
actualOptions.series[0].data = val[0].data; | |||
actualOptions.series[0].name = val[0].name; | |||
actualOptions.series[1].data = val?.[1]?.data || []; | |||
actualOptions.series[1].name = val?.[1]?.name || ""; | |||
this.actualOptions = actualOptions; | |||
this.initOptions(actualOptions); | |||
}, | |||
}, | |||
mounted() { | |||
this.actualOptions = this.options; | |||
this.initOptions(this.options); | |||
if (screenfull.isEnabled) { | |||
screenfull.on("change", () => { | |||
this.isFullscreen = screenfull.isFullscreen; | |||
}); | |||
} | |||
}, | |||
}; | |||
</script> | |||
<style scoped lang="scss"> | |||
.bar-chart-base { | |||
// position: relative; | |||
.legend { | |||
position: absolute; | |||
top: 5.2vh; | |||
right: 1vw; | |||
} | |||
.legend-item { | |||
position: relative; | |||
// font-size: 12px; | |||
margin-right: 0.67vw; | |||
&::before { | |||
content: ""; | |||
display: inline-block; | |||
width: 0.531vw; | |||
height: 0.531vw; | |||
background-color: #ccc; | |||
border-radius: 2px; | |||
margin-right: 0.22vw; | |||
} | |||
} | |||
.legend-item:nth-child(1):before { | |||
background-color: #12f7f1; | |||
} | |||
.legend-item:nth-child(2):before { | |||
background-color: #58adfa; | |||
} | |||
} | |||
</style> |
@@ -0,0 +1,195 @@ | |||
<!-- | |||
filename: ChipRateItem.vue | |||
author: liubin | |||
date: 2024-04-29 14:25:18 | |||
description: | |||
--> | |||
<template> | |||
<div class="chip-rate-item"> | |||
<div class="cities"> | |||
<CopilotButtons :options="cities" @update:active="handleCityUpdate" /> | |||
</div> | |||
<div class="chart" ref="chart"></div> | |||
<div class="legend" v-if="period == '月' || period == '年'"> | |||
<div class="legend-item" v-for="lgd in legend" :key="lgd.label"> | |||
<span class="legend-item__value">{{ lgd.value }}</span> | |||
<span class="legend-item__label">{{ lgd.label }}</span> | |||
</div> | |||
</div> | |||
</div> | |||
</template> | |||
<script> | |||
import CopilotButtons from "@/views/copilot/components/select.vue"; | |||
import chartMixin from "@/mixins/chart.js"; | |||
import fullscreenMixin from "@/mixins/fullscreen.js"; | |||
import getOptions from "../../../options/chipOptions.js"; | |||
import { mapGetters } from "vuex"; | |||
export default { | |||
name: "ChipRateItem", | |||
components: { CopilotButtons }, | |||
mixins: [chartMixin, fullscreenMixin], | |||
props: { | |||
cities: { | |||
type: Array, | |||
default: () => [], | |||
}, | |||
color: { | |||
type: Number, | |||
default: 1, | |||
}, | |||
period: { | |||
type: String, | |||
default: "日", | |||
}, | |||
}, | |||
data() { | |||
return { | |||
factoryId: 0, | |||
count: 1, | |||
}; | |||
}, | |||
computed: { | |||
chipRate() { | |||
return this.$store.getters.copilot.efficiency.chipRate; | |||
}, | |||
valueTuple() { | |||
const getter = this.chipRate; | |||
console.log(getter) | |||
if (this.period === "日" || this.period === "周") { | |||
return [ | |||
getter.previous[this.factoryId], | |||
getter.current[this.factoryId], | |||
0, | |||
]; | |||
} | |||
// [100, 200, 200] | |||
return [ | |||
getter.previous[this.factoryId], | |||
getter.current[this.factoryId], | |||
getter.target[this.factoryId], | |||
]; | |||
}, | |||
options() { | |||
const single = this.period === "日" || this.period === "周"; | |||
const year = new Date().getFullYear(); | |||
const month = new Date().getMonth() + 1; | |||
const vt = this.valueTuple; | |||
let titleValue = single | |||
? (vt[1] != null && `${vt[1] * 100}%`) || "0%" | |||
: vt[0] != null && vt[2] != null && vt[2] !== 0 | |||
? `${((vt[1] / vt[2]) * 100).toFixed(0)}%` | |||
: "0%", | |||
subtitle = { | |||
日: "本日良率", | |||
周: "本周良率", | |||
月: `${month}月良率`, | |||
年: `${year}良率`, | |||
}[this.period]; | |||
const t = getOptions({ | |||
single, | |||
color: this.color == 1 ? "#4CF0E8" : "#1065ff", | |||
titleValue, | |||
subtitle, | |||
previousSum: vt[0], | |||
currentSum: vt[1], | |||
targetSum: vt[2], | |||
}); | |||
return t; | |||
}, | |||
legend() { | |||
const year = new Date().getFullYear(); | |||
const month = new Date().getMonth() + 1; | |||
return [ | |||
{ | |||
label: | |||
this.period == "月" | |||
? `${year - 1}年${month}月良率` | |||
: `${year - 1}年良率`, | |||
value: (this.valueTuple[0] * 100).toFixed(0) + "%", | |||
}, | |||
{ | |||
label: this.period == "月" ? `${month}月良率` : `${year}年良率`, | |||
value: (this.valueTuple[1] * 100).toFixed(0) + "%", | |||
}, | |||
]; | |||
}, | |||
}, | |||
mounted() { | |||
this.initOptions(this.options); | |||
}, | |||
watch: { | |||
period() { | |||
this.initOptions(this.options); | |||
}, | |||
factoryId() { | |||
this.initOptions(this.options); | |||
}, | |||
chipRate() { | |||
this.initOptions(this.options); | |||
}, | |||
}, | |||
methods: { | |||
handleCityUpdate(id) { | |||
this.factoryId = id; | |||
}, | |||
fullscreenCallback(isFullscreen) {}, | |||
}, | |||
}; | |||
</script> | |||
<style scoped lang="scss"> | |||
.chip-rate-item { | |||
flex: 1; | |||
display: flex; | |||
flex-direction: column; | |||
align-items: center; | |||
justify-content: center; | |||
gap: 3px; | |||
backdrop-filter: blur(24px); | |||
.cities { | |||
height: 40px; | |||
} | |||
.chart { | |||
align-self: stretch; | |||
height: 280px; | |||
} | |||
.legend { | |||
height: 80px; | |||
display: flex; | |||
gap: 40px; | |||
justify-content: space-around; | |||
} | |||
.legend-item { | |||
display: flex; | |||
flex-direction: column; | |||
align-items: center; | |||
gap: 3px; | |||
&:first-child { | |||
.legend-item__value { | |||
color: #0e61f5; | |||
} | |||
} | |||
&:nth-child(2) { | |||
.legend-item__value { | |||
color: #0fd5d1; | |||
} | |||
} | |||
} | |||
.legend-item__value { | |||
font-size: 24px; | |||
font-weight: 600; | |||
} | |||
} | |||
</style> | |||
@@ -0,0 +1,149 @@ | |||
<!-- | |||
filename: CityData.vue | |||
author: liubin | |||
date: 2024-04-17 09:55:12 | |||
description: | |||
--> | |||
<template> | |||
<div class="city-data"> | |||
<div class="headquarter"> | |||
<div class="inner-shadow w-1"></div> | |||
<div class="inner-shadow flex-1 flex"> | |||
<CityName value="凯盛光伏" /> | |||
<CityValue :value="headquarterValue" horizontal :period="period" /> | |||
</div> | |||
<div class="inner-shadow w-1"></div> | |||
</div> | |||
<div class="city-item-container"> | |||
<CityItem | |||
v-for="city in cities" | |||
:key="city.name" | |||
:location="city.name" | |||
:value="city.value" | |||
:period="period" | |||
/> | |||
</div> | |||
</div> | |||
</template> | |||
<script> | |||
import CityItemVue from "./CityItem.vue"; | |||
import CityNameVue from "./CityName.vue"; | |||
import CityValueVue from "./CityValue.vue"; | |||
export default { | |||
name: "CityData", | |||
components: { | |||
CityItem: CityItemVue, | |||
CityName: CityNameVue, | |||
CityValue: CityValueVue, | |||
}, | |||
props: { | |||
dataSource: { | |||
type: String, | |||
default: null, | |||
}, | |||
period: { | |||
type: String, | |||
default: "日", | |||
}, | |||
}, | |||
data() { | |||
return {}; | |||
}, | |||
computed: { | |||
headquarterValue() { | |||
let getterName = ""; | |||
switch (this.dataSource) { | |||
case "标准组件产出": | |||
getterName = "stdOutput"; | |||
break; | |||
case "芯片产出": | |||
getterName = "chipOutput"; | |||
break; | |||
case "BIPV产出": | |||
getterName = "bipvOutput"; | |||
break; | |||
} | |||
return ( | |||
"" + (this.$store.getters.copilot.yield[getterName]?.current?.[5] ?? 0) | |||
); | |||
}, | |||
cities() { | |||
let getterName = ""; | |||
switch (this.dataSource) { | |||
case "标准组件产出": | |||
getterName = "stdOutput"; | |||
break; | |||
case "芯片产出": | |||
getterName = "chipOutput"; | |||
break; | |||
case "BIPV产出": | |||
getterName = "bipvOutput"; | |||
break; | |||
} | |||
const _cities = [ | |||
{ name: "瑞昌", value: 0 }, | |||
{ name: "邯郸", value: 0 }, | |||
{ name: "株洲", value: 0 }, | |||
{ name: "佳木斯", value: 0 }, | |||
{ name: "成都", value: 0 }, | |||
{ name: "凯盛光伏", value: 0 }, | |||
{ name: "蚌埠兴科", value: 0 }, | |||
]; | |||
this.$store.getters.copilot.yield[getterName]?.current?.forEach( | |||
(v, idx) => { | |||
_cities[idx].value = v ?? 0; | |||
} | |||
); | |||
// 删掉凯盛光伏 | |||
_cities.splice(4, 1); | |||
return _cities; | |||
}, | |||
}, | |||
mounted() {}, | |||
methods: {}, | |||
}; | |||
</script> | |||
<style scoped lang="scss"> | |||
.city-data { | |||
width: 100%; | |||
flex: 1; | |||
display: flex; | |||
flex-direction: column; | |||
gap: 8px; | |||
} | |||
.headquarter { | |||
flex: 1; | |||
display: flex; | |||
gap: 8px; | |||
} | |||
.w-1 { | |||
width: 70px; | |||
} | |||
.flex { | |||
display: flex; | |||
} | |||
.flex-1 { | |||
flex: 1; | |||
} | |||
.inner-shadow { | |||
box-shadow: inset 0 0 12px 2px #fff3; | |||
border-radius: 4px; | |||
} | |||
.city-item-container { | |||
flex: 3; | |||
display: grid; | |||
grid-template-columns: repeat(2, 1fr); | |||
gap: 8px; | |||
} | |||
</style> |
@@ -0,0 +1,59 @@ | |||
<!-- | |||
filename: CityItem.vue | |||
author: liubin | |||
date: 2024-04-17 09:55:12 | |||
description: | |||
--> | |||
<template> | |||
<div class="city-item inner-shadow"> | |||
<CityName :value="location" /> | |||
<CityValue :value="value + ''" :period="period" /> | |||
</div> | |||
</template> | |||
<script> | |||
import CityNameVue from "./CityName.vue"; | |||
import CityValueVue from "./CityValue.vue"; | |||
import GradientTextVue from "../gradient/GradientText.vue"; | |||
export default { | |||
name: "CityItem", | |||
components: { | |||
GradientTextVue, | |||
CityName: CityNameVue, | |||
CityValue: CityValueVue, | |||
}, | |||
props: { | |||
location: { | |||
type: String, | |||
default: "", | |||
}, | |||
value: { | |||
type: Number, | |||
default: 0, | |||
}, | |||
period: { | |||
type: String, | |||
default: "日", | |||
}, | |||
}, | |||
data() { | |||
return {}; | |||
}, | |||
computed: {}, | |||
mounted() {}, | |||
methods: {}, | |||
}; | |||
</script> | |||
<style scoped lang="scss"> | |||
.city-item { | |||
display: flex; | |||
} | |||
.inner-shadow { | |||
box-shadow: inset 0 0 12px 2px #fff3; | |||
border-radius: 4px; | |||
} | |||
</style> |
@@ -0,0 +1,55 @@ | |||
<!-- | |||
filename: CityName.vue | |||
author: liubin | |||
date: 2024-04-10 08:59:28 | |||
description: | |||
--> | |||
<template> | |||
<div class="city-name"> | |||
<img :src="Icon" alt="city icon" /> | |||
<span>{{ value }}</span> | |||
</div> | |||
</template> | |||
<script> | |||
import Icon from "../../../assets/icon.png"; | |||
export default { | |||
name: "CityName", | |||
props: { | |||
value: { | |||
type: String, | |||
default: "", | |||
}, | |||
}, | |||
data() { | |||
return { Icon }; | |||
}, | |||
}; | |||
</script> | |||
<style scoped> | |||
.city-name { | |||
min-width: 80px; | |||
margin: auto; | |||
display: flex; | |||
flex-direction: column; | |||
align-items: center; | |||
justify-content: center; | |||
padding: 0 8px; | |||
flex: 1; | |||
} | |||
img { | |||
/* width: 32px; */ | |||
width: 1.543vw; | |||
} | |||
span { | |||
/* font-size: 12px; */ | |||
font-size: 0.77vw; | |||
letter-spacing: 2px; | |||
text-align: center; | |||
} | |||
</style> |
@@ -0,0 +1,127 @@ | |||
<!-- | |||
filename: CityValue.vue | |||
author: liubin | |||
date: 2024-04-10 08:59:28 | |||
description: | |||
--> | |||
<template> | |||
<div class="city-value" :class="[horizontal ? 'horizontal' : '']"> | |||
<span class="hint" :class="[horizontal ? 'horizontal' : '']">{{ | |||
period == "周" ? "本周产出" : "今日产出" | |||
}}</span> | |||
<span class="value" :class="[horizontal ? 'horizontal' : '']">{{ | |||
value | numberFilter | |||
}}</span> | |||
<!-- <GradientTextVue :text="value" :size="horizontal ? 32 : 26" /> --> | |||
</div> | |||
</template> | |||
<script> | |||
import GradientTextVue from "../gradient/GradientText.vue"; | |||
export default { | |||
name: "CityValue", | |||
components: { GradientTextVue }, | |||
props: { | |||
period: { | |||
type: String, | |||
default: "日", | |||
}, | |||
value: { | |||
type: String, | |||
default: "", | |||
}, | |||
horizontal: { | |||
type: Boolean, | |||
default: false, | |||
}, | |||
}, | |||
filters: { | |||
numberFilter(value) { | |||
if (value != null && !isNaN(parseInt(value))) { | |||
return parseInt(value).toLocaleString(); | |||
} else { | |||
return value; | |||
} | |||
}, | |||
}, | |||
data() { | |||
return {}; | |||
}, | |||
}; | |||
</script> | |||
<style scoped> | |||
.city-value { | |||
display: flex; | |||
flex-direction: column; | |||
align-items: center; | |||
justify-content: center; | |||
padding: 0 8px; | |||
flex: 2; | |||
position: relative; | |||
} | |||
.city-value.horizontal { | |||
flex-direction: row; | |||
} | |||
.city-value::after { | |||
content: ""; | |||
position: absolute; | |||
top: 0; | |||
left: 0; | |||
width: 1px; | |||
height: 100%; | |||
background: linear-gradient( | |||
to bottom, | |||
transparent 20%, | |||
#fff 50%, | |||
transparent 80% | |||
); | |||
} | |||
span.hint { | |||
margin: 0 0.77vw; | |||
font-size: 0.77vw; | |||
order: 2; | |||
/* margin: 0 12px; | |||
width: 32px; | |||
font-size: 12px; */ | |||
} | |||
span.hint.horizontal { | |||
margin: 0 1.235vw; | |||
width: 1.543vw; | |||
order: 1; | |||
font-size: 0.77vw; | |||
/* margin: 0 12px; | |||
width: 32px; | |||
font-size: 12px; */ | |||
} | |||
.value { | |||
color: #4dd2fe; | |||
text-align: center; | |||
font-size: 1.132vw; | |||
order: 1; | |||
} | |||
.value.horizontal { | |||
text-align: left; | |||
flex: 1; | |||
font-size: 1.543vw; | |||
order: 2; | |||
} | |||
svg, | |||
.value { | |||
width: 100px; | |||
order: 1; | |||
} | |||
.value.horizontal, | |||
svg.horizontal { | |||
order: 2; | |||
} | |||
</style> |
@@ -0,0 +1,64 @@ | |||
<!-- | |||
filename: GradientText.vue | |||
author: liubin | |||
date: 2024-04-24 16:33:25 | |||
description: | |||
--> | |||
<template> | |||
<svg :height="size + 8" width="100%"> | |||
<defs> | |||
<linearGradient id="smoke-text" x1="0%" y1="0%" x2="0%" y2="100%"> | |||
<stop offset="0%" style="stop-color: #00fff4; stop-opacity: 1" /> | |||
<stop offset="100%" style="stop-color: #37bdfe; stop-opacity: 1" /> | |||
</linearGradient> | |||
</defs> | |||
<text | |||
x="0" | |||
:y="size" | |||
fill="url(#smoke-text)" | |||
:style="{ | |||
fontSize: `${size}px`, | |||
letterSpacing: spacing || '2px', | |||
fontFamily: 'Calibri, Verdana, sans-serif', | |||
}" | |||
> | |||
{{ text | numberFilter }} | |||
</text> | |||
</svg> | |||
</template> | |||
<script> | |||
export default { | |||
name: "GradientText", | |||
components: {}, | |||
props: { | |||
text: { | |||
type: String, | |||
default: "Test", | |||
}, | |||
spacing: { | |||
type: String, | |||
default: "1px", | |||
}, | |||
size: { | |||
type: Number, | |||
default: 24, | |||
}, | |||
}, | |||
filters: { | |||
numberFilter(value) { | |||
if (value != null && !isNaN(parseInt(value))) { | |||
return parseInt(value).toLocaleString(); | |||
} else { | |||
return value; | |||
} | |||
}, | |||
}, | |||
data() { | |||
return {}; | |||
}, | |||
}; | |||
</script> | |||
<style scoped lang="scss"></style> |
@@ -0,0 +1,221 @@ | |||
<!-- | |||
filename: DoubleRingChart.vue | |||
author: liubin | |||
date: 2024-04-17 11:01:55 | |||
description: | |||
--> | |||
<template> | |||
<div class="double-ring-chart"> | |||
<div ref="chart" class="double-ring-chart__container"></div> | |||
<!-- style="{ height: vHeight + 'vh' }" --> | |||
<div class="double-ring-chart__legend"> | |||
<div v-for="item in legendItems" :key="item.label" class="legend-item"> | |||
<span class="legend-item__label">{{ item.label }}</span> | |||
<span class="legend-item__value">{{ item.value | numberFilter }}</span> | |||
</div> | |||
</div> | |||
</div> | |||
</template> | |||
<script> | |||
import chartMixin from "@/mixins/chart.js"; | |||
import fullscreenMixin from "@/mixins/fullscreen.js"; | |||
import getOptions from "../../../options/double-ring-chart-options"; | |||
export default { | |||
name: "DoubleRingChart", | |||
mixins: [chartMixin, fullscreenMixin], | |||
props: { | |||
vHeight: { | |||
type: Number, | |||
default: 24, | |||
}, | |||
factoryId: { | |||
type: Number, | |||
required: true, | |||
}, | |||
period: { | |||
type: String, | |||
default: "日", | |||
}, | |||
dataSource: { | |||
type: String, | |||
default: null, | |||
}, | |||
}, | |||
data() { | |||
return {}; | |||
}, | |||
filters: { | |||
numberFilter(val) { | |||
if (!isNaN(val)) { | |||
return (+val).toLocaleString(); | |||
} | |||
return 0; | |||
}, | |||
}, | |||
computed: { | |||
dataSourceField() { | |||
switch (this.dataSource) { | |||
case "标准组件产出": | |||
return "stdOutput"; | |||
case "芯片产出": | |||
return "chipOutput"; | |||
case "BIPV产出": | |||
return "bipvOutput"; | |||
} | |||
}, | |||
valueTuple() { | |||
// [previousValue, currentValue, sumValue?] | |||
const getter = this.$store.getters.copilot.yield[this.dataSourceField]; | |||
if (this.period === "日" || this.period === "周") { | |||
return [ | |||
getter.previous[this.factoryId], | |||
getter.current[this.factoryId], | |||
]; | |||
} | |||
// [100, 200, 200] | |||
return [ | |||
getter.previous[this.factoryId], | |||
getter.current[this.factoryId], | |||
getter.target[this.factoryId], | |||
]; | |||
}, | |||
options() { | |||
const year = new Date().getFullYear(); | |||
const month = new Date().getMonth() + 1; | |||
const vt = this.valueTuple; | |||
let titleValue = | |||
vt[0] != null && vt[2] != null && vt[2] !== 0 | |||
? `${vt[1] / vt[2]}%` | |||
: "0%", | |||
subtitle = | |||
this.period == "月" ? `${month}月累计产出` : `${year}年累计产出`; | |||
return getOptions({ | |||
titleValue, | |||
subtitle, | |||
previousSum: this.valueTuple[0], | |||
currentSum: this.valueTuple[1], | |||
targetSum: this.valueTuple[2], | |||
}); | |||
}, | |||
legendItems() { | |||
return calculateItems(this.period, this.valueTuple); | |||
}, | |||
}, | |||
watch: { | |||
legendItems() { | |||
this.initOptions(this.options); | |||
}, | |||
}, | |||
mounted() { | |||
this.initOptions(this.options); | |||
}, | |||
methods: { | |||
// fullscreen mixin 需要的回调 | |||
fullscreenCallback(isFullscreen) { | |||
console.log("isFullscreen--->", isFullscreen); | |||
}, | |||
}, | |||
}; | |||
function calculateItems(period, valueTuple) { | |||
let items = []; | |||
const today = new Date().getDate(); | |||
const month = new Date().getMonth() + 1; | |||
const year = new Date().getFullYear(); | |||
switch (period) { | |||
case "日": | |||
items = [ | |||
{ label: `${month}月${today}日累计`, value: valueTuple[1] }, | |||
{ label: `去年${month}月${today}日累计`, value: valueTuple[0] }, | |||
]; | |||
break; | |||
case "周": | |||
items = [ | |||
{ label: `本周累计`, value: valueTuple[1] }, | |||
{ label: `去年本周累计`, value: valueTuple[0] }, | |||
]; | |||
break; | |||
case "月": | |||
items = [ | |||
{ label: `${month}月累计`, value: valueTuple[1] }, | |||
{ label: `去年${month}月累计`, value: valueTuple[0] }, | |||
{ label: `${month}月目标`, value: valueTuple[2] }, | |||
]; | |||
break; | |||
case "年": | |||
items = [ | |||
{ label: `${year}年累计`, value: valueTuple[1] }, | |||
{ label: `${year - 1}年累计`, value: valueTuple[0] }, | |||
{ label: `${year}年目标`, value: valueTuple[2] }, | |||
]; | |||
break; | |||
} | |||
return items; | |||
} | |||
</script> | |||
<style scoped> | |||
.double-ring-chart { | |||
height: 100%; | |||
display: flex; | |||
flex-direction: column; | |||
} | |||
.double-ring-chart__container { | |||
flex: 1; | |||
height: 0; | |||
} | |||
.double-ring-chart__legend { | |||
padding: 12px; | |||
color: #fff; | |||
display: flex; | |||
justify-content: center; | |||
gap: 32px; | |||
} | |||
.legend-item { | |||
display: flex; | |||
flex-direction: column; | |||
align-items: flex-start; | |||
} | |||
.legend-item__label { | |||
position: relative; | |||
} | |||
.legend-item__label::before { | |||
content: ""; | |||
position: absolute; | |||
width: 12px; | |||
height: 12px; | |||
background: #ccc; | |||
border-radius: 2px; | |||
top: 6px; | |||
left: -18px; | |||
} | |||
.legend-item:nth-child(1) .legend-item__label::before { | |||
background: #12fff5; | |||
} | |||
.legend-item:nth-child(1) .legend-item__value { | |||
color: #12fff5; | |||
} | |||
.legend-item:nth-child(2) .legend-item__label::before { | |||
background: #0f65ff; | |||
} | |||
.legend-item:nth-child(2) .legend-item__value { | |||
color: #0f65ff; | |||
} | |||
.legend-item:nth-child(3) .legend-item__label::before { | |||
background: #003982; | |||
} | |||
</style> |
@@ -0,0 +1,86 @@ | |||
<!-- | |||
filename: DoubleRingWrapper.vue | |||
author: liubin | |||
date: 2024-04-17 09:55:12 | |||
description: | |||
--> | |||
<template> | |||
<div class="double-ring-wrapper"> | |||
<template v-if="period == '月' || period == '年'"> | |||
<copilot-select | |||
@update:active="handleActiveUpdate" | |||
:options="cityOptions" | |||
/> | |||
<div class="flex-1 stretch"> | |||
<DoubleRingChartVue | |||
:data-source="dataSource" | |||
:period="period" | |||
:factoryId="factoryId" | |||
/> | |||
</div> | |||
</template> | |||
<template v-else> | |||
<CityData :data-source="dataSource" :period="period" /> | |||
</template> | |||
</div> | |||
</template> | |||
<script> | |||
import CopilotSelect from "@/views/copilot/components/select.vue"; | |||
import DoubleRingChartVue from "./DoubleRingChart.vue"; | |||
import CityData from "../city/CityData.vue"; | |||
export default { | |||
name: "DoubleRingWrapper", | |||
components: { CopilotSelect, DoubleRingChartVue, CityData }, | |||
props: { | |||
dataSource: { | |||
type: String, | |||
default: null, | |||
}, | |||
period: { | |||
type: String, | |||
default: "日", | |||
}, | |||
}, | |||
data() { | |||
return { | |||
factoryId: 4, // 默认成都 | |||
cityOptions: [ | |||
"成都", | |||
"邯郸", | |||
"株洲", | |||
"瑞昌", | |||
"佳木斯", | |||
"凯盛光伏", | |||
"蚌埠兴科", | |||
], | |||
}; | |||
}, | |||
methods: { | |||
handleActiveUpdate(index) { | |||
this.factoryId = index; | |||
}, | |||
}, | |||
}; | |||
</script> | |||
<style scoped lang="scss"> | |||
.double-ring-wrapper { | |||
height: 100%; | |||
padding: 12px 24px; | |||
display: flex; | |||
gap: 12px; | |||
flex-direction: column; | |||
align-items: center; | |||
} | |||
.flex-1 { | |||
flex: 1; | |||
} | |||
.stretch { | |||
align-self: stretch; | |||
} | |||
</style> |
@@ -0,0 +1,66 @@ | |||
<!-- | |||
filename: CityName.vue | |||
author: liubin | |||
date: 2024-04-10 08:59:28 | |||
description: | |||
--> | |||
<template> | |||
<div class="city-name"> | |||
<img :src="Icon" alt="city icon" /> | |||
<span>{{ value }}</span> | |||
</div> | |||
</template> | |||
<script> | |||
import Icon from "@/views/copilot/assets/icon.png"; | |||
export default { | |||
name: "CityName", | |||
props: { | |||
value: { | |||
type: String, | |||
default: "", | |||
}, | |||
}, | |||
data() { | |||
return { Icon }; | |||
}, | |||
}; | |||
</script> | |||
<style scoped> | |||
.city-name { | |||
min-width: 80px; | |||
margin: auto; | |||
display: flex; | |||
flex-direction: column; | |||
align-items: center; | |||
justify-content: center; | |||
padding: 0 8px; | |||
position: relative; | |||
} | |||
.city-name::after { | |||
content: ""; | |||
position: absolute; | |||
top: 50%; | |||
right: 0; | |||
width: 2px; | |||
background: linear-gradient(to top, transparent, #0b5be1ee, transparent); | |||
height: 100%; | |||
transform: translateY(-50%); | |||
} | |||
img { | |||
/* width: 32px; */ | |||
width: 1.543vw; | |||
} | |||
span { | |||
/* font-size: 12px; */ | |||
font-size: 0.77vw; | |||
letter-spacing: 2px; | |||
text-align: center; | |||
} | |||
</style> |
@@ -0,0 +1,113 @@ | |||
<!-- | |||
filename: ProgressBar.vue | |||
author: liubin | |||
date: 2024-04-29 09:18:30 | |||
description: | |||
--> | |||
<template> | |||
<div class="progress-bar" :data-title="title" :data-rate="dataRate"> | |||
<div | |||
class="progress-bar__rate" | |||
:style="{ width: dataRate == '-' ? 0 : dataRate }" | |||
></div> | |||
</div> | |||
</template> | |||
<script> | |||
export default { | |||
name: "ProgressBar", | |||
components: {}, | |||
props: { | |||
value: { | |||
type: Number, | |||
default: 0, | |||
}, | |||
total: { | |||
type: Number, | |||
default: 0, | |||
}, | |||
title: { | |||
type: String, | |||
default: "", | |||
}, | |||
}, | |||
data() { | |||
return {}; | |||
}, | |||
computed: { | |||
dataRate() { | |||
return this.total == 0 | |||
? "-" | |||
: `${(parseFloat(this.value / this.total) * 100).toFixed(0)}%`; | |||
}, | |||
}, | |||
methods: {}, | |||
}; | |||
</script> | |||
<style scoped lang="scss"> | |||
.progress-bar { | |||
height: 10px; | |||
background-color: #002f6b; | |||
border-radius: 4px; | |||
margin-bottom: 12px; | |||
position: relative; | |||
&:before { | |||
content: attr(data-title); | |||
display: inline-block; | |||
color: #fff; | |||
position: absolute; | |||
bottom: -200%; | |||
font-size: 12px; | |||
} | |||
&:after { | |||
content: attr(data-rate); | |||
display: inline-block; | |||
color: #fff; | |||
position: absolute; | |||
bottom: -200%; | |||
right: 0; | |||
font-size: 12px; | |||
} | |||
&:first-child { | |||
&:after { | |||
color: #11eae3; | |||
} | |||
} | |||
&:nth-child(2) { | |||
&:after { | |||
color: #0e65fd; | |||
} | |||
} | |||
.progress-bar__rate { | |||
position: absolute; | |||
display: inline-block; | |||
height: 100%; | |||
width: 0; | |||
border-radius: 4px; | |||
} | |||
&:first-child { | |||
.progress-bar__rate { | |||
background: linear-gradient( | |||
to right, | |||
#004c5e11 10%, | |||
#004c5e, | |||
#0ac0c0, | |||
#11eae3 | |||
); | |||
} | |||
} | |||
&:nth-child(2) { | |||
.progress-bar__rate { | |||
background: linear-gradient(to right, #0048a811, #0048a8, #0e65fd); | |||
} | |||
} | |||
} | |||
</style> |
@@ -0,0 +1,124 @@ | |||
<!-- | |||
* @Author: zhp | |||
* @Date: 2024-05-07 10:25:10 | |||
* @LastEditTime: 2024-05-08 14:54:24 | |||
* @LastEditors: zhp | |||
* @Description: | |||
--> | |||
<template> | |||
<div v-if="period == '日'" class="std-rate-item"> | |||
<CityName :value="city.name" /> | |||
<div class="std-rate-item__value"> | |||
<ProgressBar :title="title" :total="city.target" :value="city.target" /> | |||
<!-- <ProgressBar title="24年累计" :total="city.target" :value="city.thisYear" /> --> | |||
</div> | |||
</div> | |||
<div v-else-if="period == '周'" class="std-rate-item"> | |||
<CityName :value="city.name" /> | |||
<div class="std-rate-item__value"> | |||
<ProgressBar :title="title" :total="city.target" :value="city.target" /> | |||
<!-- <ProgressBar title="24年累计" :total="city.target" :value="city.thisYear" /> --> | |||
</div> | |||
</div> | |||
<div v-else-if="period == '月'" class="std-rate-item"> | |||
<CityName :value="city.name" /> | |||
<div class="std-rate-item__value"> | |||
<ProgressBar :title="titleEnd" :total="city.target" :value="city.target" /> | |||
<ProgressBar :title="title" :total="city.target" :value="city.thisYear" /> | |||
</div> | |||
</div> | |||
<div v-else="period == '年'" class="std-rate-item"> | |||
<CityName :value="city.name" /> | |||
<div class="std-rate-item__value"> | |||
<ProgressBar :title="titleEnd" :total="city.target" :value="city.target" /> | |||
<ProgressBar :title="title" :total="city.target" :value="city.thisYear" /> | |||
</div> | |||
</div> | |||
</template> | |||
<script> | |||
import CityName from "./CityName.vue"; | |||
import ProgressBar from "./ProgressBar.vue"; | |||
export default { | |||
name: "StdRateItem", | |||
components: { CityName, ProgressBar }, | |||
props: { | |||
city: { | |||
type: Object, | |||
required: true, | |||
}, | |||
period: { | |||
type: String, | |||
default: "日", | |||
} | |||
}, | |||
data() { | |||
return { | |||
showDay:true, | |||
}; | |||
}, | |||
computed: { | |||
title() { | |||
switch (this.period) { | |||
case "日": | |||
return "今日" | |||
case "周": | |||
return "本周" | |||
case "月": | |||
const year = new Date().getFullYear(); | |||
const month = new Date().getMonth() + 1; | |||
return `${year - 1}年${month}月累计` | |||
case "年": { | |||
const year = new Date().getFullYear(); | |||
// return [ | |||
return `${year - 1}年累计` | |||
// ]; | |||
} | |||
default: | |||
return "今日" | |||
} | |||
}, | |||
titleEnd() { | |||
switch (this.period) { | |||
// case "日": | |||
// return "今日" | |||
// case "周": | |||
// return "本周" | |||
case "月": | |||
const year = new Date().getFullYear(); | |||
const month = new Date().getMonth() + 1; | |||
return `${year}年${month}月目标` | |||
case "年": { | |||
const year = new Date().getFullYear(); | |||
// return [ | |||
return `${year}年目标` | |||
// ]; | |||
} | |||
} | |||
} | |||
}, | |||
}; | |||
</script> | |||
<style scoped lang="scss"> | |||
.std-rate-item { | |||
box-shadow: inset 0 0 12px 2px #fff3; | |||
border-radius: 4px; | |||
display: flex; | |||
align-items: center; | |||
gap: 8px; | |||
padding: 12px; | |||
} | |||
.std-rate-item__value { | |||
flex: 1; | |||
margin: 6px; | |||
display: flex; | |||
gap: 12px; | |||
height: 60px; | |||
flex-direction: column; | |||
justify-content: center; | |||
} | |||
</style> |
@@ -1,24 +1,44 @@ | |||
<!-- | |||
filename: index.vue | |||
author: liubin | |||
date: 2024-04-16 14:40:15 | |||
description: 效率驾驶舱 | |||
<!-- | |||
* @Author: zhp | |||
* @Date: 2024-05-07 10:04:53 | |||
* @LastEditTime: 2024-05-08 15:58:14 | |||
* @LastEditors: zhp | |||
* @Description: | |||
--> | |||
<template> | |||
<div class="efficiency-copilot"> | |||
<Container title="芯片良率" icon="chip2"></Container> | |||
<Container title="标准组件良率" icon="std"></Container> | |||
<Container title="芯片OEE" icon="chip"></Container> | |||
<Container title="转化效率" icon="cube"></Container> | |||
<Container title="芯片良率" icon="chip2"> | |||
<ChipRate :period="period" /> | |||
</Container> | |||
<Container title="标准组件良率" icon="std"> | |||
<StdRate :period="period" /> | |||
</Container> | |||
<Container title="芯片OEE" icon="chip"> | |||
<ChipOee :period="period" /> | |||
</Container> | |||
<Container title="转化效率" icon="cube"> | |||
<TransformRate :period="period" /> | |||
</Container> | |||
</div> | |||
</template> | |||
<script> | |||
import Container from "@/views/copilot/components/Container.vue"; | |||
import ChipOeeVue from "./components/ChipOee.vue"; | |||
import ChipRateVue from "./components/ChipRate.vue"; | |||
import StdRateVue from "./components/StdRate.vue"; | |||
import TransformRateVue from "./components/TransformRate.vue"; | |||
export default { | |||
name: "EfficiencyCopilot", | |||
components: { Container }, | |||
components: { | |||
Container, | |||
ChipOee: ChipOeeVue, | |||
ChipRate: ChipRateVue, | |||
StdRate: StdRateVue, | |||
TransformRate: TransformRateVue, | |||
}, | |||
props: { | |||
period: { | |||
type: String, | |||
@@ -39,7 +59,10 @@ export default { | |||
methods: { | |||
fetchData(period = "日") { | |||
console.log(`效率驾驶舱,获取${period}数据`); | |||
this.$store.dispatch("copilot/initCopilot", { period, source: "efficiency" }); | |||
this.$store.dispatch("copilot/initCopilot", { | |||
period, | |||
source: "efficiency", | |||
}); | |||
}, | |||
}, | |||
}; | |||
@@ -51,7 +74,7 @@ export default { | |||
display: grid; | |||
gap: 16px; | |||
grid-template-columns: 1fr 1fr; | |||
grid-template-rows: 1fr 1fr; | |||
grid-template-rows: .5fr .5fr; | |||
} | |||
.efficiency-copilot > div { | |||
@@ -0,0 +1,163 @@ | |||
export default function ({ | |||
single = false, | |||
color, | |||
titleValue, | |||
subtitle, | |||
previousSum, | |||
currentSum, | |||
targetSum, | |||
}) { | |||
return { | |||
grid: { | |||
left: 0, | |||
right: 0, | |||
bottom: 0, | |||
top: 0, | |||
containLabel: true, | |||
}, | |||
tooltip: { | |||
// formatter(params) { | |||
// return `${params.name}: ${(params.value * 100).toFixed(0)}%`; | |||
// } | |||
}, | |||
title: { | |||
text: titleValue, | |||
left: "49%", | |||
top: "39%", | |||
textAlign: "center", | |||
textStyle: { | |||
fontWeight: 600, | |||
fontSize: 32, | |||
color: "#fffd", | |||
}, | |||
subtext: `\u2002${subtitle}\u2002`, | |||
subtextStyle: { | |||
fontSize: 14, | |||
fontWeight: 100, | |||
color: "#fffd", | |||
align: "right", | |||
}, | |||
}, | |||
series: [ | |||
// 背景 series | |||
{ | |||
type: "pie", | |||
name: "当前目标", | |||
radius: ["70%", "85%"], | |||
center: ["50%", "52%"], | |||
emptyCircleStyle: { | |||
color: "#040c5f45", | |||
}, | |||
}, | |||
// 数据 series | |||
{ | |||
type: "pie", | |||
radius: ["70%", "85%"], | |||
center: ["50%", "52%"], | |||
avoidLabelOvervlap: false, | |||
label: { | |||
show: false, | |||
}, | |||
labelLine: { | |||
show: false, | |||
}, | |||
data: [ | |||
{ | |||
value: currentSum, | |||
name: "当前良率", | |||
selected: false, | |||
itemStyle: { | |||
borderJoin: "round", | |||
borderCap: "round", | |||
borderWidth: 12, | |||
borderRadius: "50%", | |||
color: { | |||
type: "linear", | |||
x: 1, | |||
y: 0, | |||
x2: 0, | |||
y2: 1, | |||
colorStops: single | |||
? [ | |||
{ offset: 0, color: `${color}11` }, | |||
{ offset: 1, color: `${color}` }, | |||
] | |||
: [ | |||
{ offset: 0, color: "#4CF0E811" }, | |||
{ offset: 1, color: "#4CF0E8" }, | |||
], | |||
}, | |||
}, | |||
}, | |||
{ | |||
value: | |||
targetSum > currentSum | |||
? targetSum - currentSum | |||
: targetSum == 0 | |||
? currentSum == 0 | |||
? 1 | |||
: 0 | |||
: targetSum, | |||
name: "未达成", | |||
itemStyle: { color: "transparent" }, | |||
label: { show: false }, | |||
}, | |||
], | |||
}, | |||
// 数据 series2 - 2023累计 | |||
single | |||
? null | |||
: { | |||
type: "pie", | |||
radius: ["55%", "70%"], | |||
center: ["50%", "52%"], | |||
avoidLabelOvervlap: false, | |||
label: { | |||
show: false, | |||
}, | |||
labelLine: { | |||
show: false, | |||
}, | |||
data: [ | |||
{ | |||
value: previousSum, | |||
name: "上期良率", | |||
selected: false, | |||
itemStyle: { | |||
borderJoin: "round", | |||
borderCap: "round", | |||
borderWidth: 12, | |||
borderRadius: "50%", | |||
color: { | |||
type: "linear", | |||
x: 1, | |||
y: 0, | |||
x2: 0, | |||
y2: 1, | |||
colorStops: [ | |||
{ offset: 0, color: "#1065ff66" }, | |||
{ offset: 1, color: "#1065ff" }, | |||
], | |||
}, | |||
}, | |||
}, | |||
{ | |||
value: | |||
targetSum > previousSum | |||
? targetSum - previousSum | |||
: previousSum == 0 | |||
? 1 | |||
: 0, | |||
name: "-", | |||
formatter: { | |||
show: false | |||
}, | |||
itemStyle: { color: "transparent" }, | |||
label: { show: false }, | |||
}, | |||
], | |||
}, | |||
], | |||
}; | |||
} |
@@ -0,0 +1,145 @@ | |||
export default ({ | |||
titleValue, | |||
subtitle, | |||
previousSum, | |||
currentSum, | |||
targetSum, | |||
}) => ({ | |||
grid: { | |||
left: 0, | |||
right: 0, | |||
bottom: 0, | |||
top: 0, | |||
containLabel: true, | |||
}, | |||
tooltip: {}, | |||
title: { | |||
text: titleValue, | |||
left: "49%", | |||
top: "39%", | |||
textAlign: "center", | |||
textStyle: { | |||
fontWeight: 600, | |||
fontSize: 32, | |||
color: "#fffd", | |||
}, | |||
subtext: `\u2002${subtitle}\u2002`, | |||
subtextStyle: { | |||
fontSize: 14, | |||
fontWeight: 100, | |||
color: "#fffd", | |||
align: "right", | |||
}, | |||
}, | |||
series: [ | |||
// 背景 series | |||
{ | |||
type: "pie", | |||
name: "当前目标", | |||
radius: ["70%", "85%"], | |||
center: ["50%", "52%"], | |||
emptyCircleStyle: { | |||
color: "#042c5f33", | |||
}, | |||
}, | |||
// 数据 series | |||
{ | |||
type: "pie", | |||
radius: ["70%", "85%"], | |||
center: ["50%", "52%"], | |||
avoidLabelOvervlap: false, | |||
label: { | |||
show: false, | |||
}, | |||
labelLine: { | |||
show: false, | |||
}, | |||
data: [ | |||
{ | |||
value: currentSum, | |||
name: "当前累计产出", | |||
selected: false, | |||
itemStyle: { | |||
borderJoin: "round", | |||
borderCap: "round", | |||
borderWidth: 12, | |||
borderRadius: "50%", | |||
color: { | |||
type: "linear", | |||
x: 1, | |||
y: 0, | |||
x2: 0, | |||
y2: 1, | |||
colorStops: [ | |||
{ offset: 0, color: "#4CF0E811" }, | |||
{ offset: 1, color: "#4CF0E8" }, | |||
], | |||
}, | |||
}, | |||
}, | |||
{ | |||
value: | |||
targetSum > currentSum | |||
? targetSum - currentSum | |||
: targetSum == 0 | |||
? currentSum == 0 | |||
? 1 | |||
: 0 | |||
: 0, | |||
name: "未达成累计", | |||
itemStyle: { color: "transparent" }, | |||
label: { show: false }, | |||
}, | |||
], | |||
}, | |||
// 数据 series2 - 2023累计 | |||
{ | |||
type: "pie", | |||
radius: ["55%", "70%"], | |||
center: ["50%", "52%"], | |||
avoidLabelOvervlap: false, | |||
label: { | |||
show: false, | |||
}, | |||
labelLine: { | |||
show: false, | |||
}, | |||
data: [ | |||
{ | |||
value: previousSum, | |||
name: "上期累计产出", | |||
selected: false, | |||
itemStyle: { | |||
borderJoin: "round", | |||
borderCap: "round", | |||
borderWidth: 12, | |||
borderRadius: "50%", | |||
color: { | |||
type: "linear", | |||
x: 1, | |||
y: 0, | |||
x2: 0, | |||
y2: 1, | |||
colorStops: [ | |||
{ offset: 0, color: "#1065ff66" }, | |||
{ offset: 1, color: "#1065ff" }, | |||
], | |||
}, | |||
}, | |||
}, | |||
{ | |||
value: | |||
targetSum > previousSum | |||
? targetSum - previousSum | |||
: previousSum == 0 | |||
? 1 | |||
: 0, | |||
name: "-", | |||
itemStyle: { color: "transparent" }, | |||
label: { show: false }, | |||
}, | |||
], | |||
}, | |||
], | |||
}); |
@@ -0,0 +1,128 @@ | |||
<!-- | |||
filename: ElecCost.vue | |||
author: liubin | |||
date: 2024-04-29 16:37:01 | |||
description: 电能耗 | |||
--> | |||
<template> | |||
<LineChartBase | |||
v-if="1" | |||
:legend="legend" | |||
:series="series" | |||
:xAxis="xAxis" | |||
in="elecCost" | |||
class="elec-cost" | |||
/> | |||
<BarChartBase | |||
v-else | |||
:legend="legend" | |||
:series="series" | |||
:xAxis="xAxis" | |||
in="elecCost" | |||
class="elec-cost" | |||
/> | |||
</template> | |||
<script> | |||
import BarChartBaseVue from "@/views/copilot/components/BarChartBase.vue"; | |||
import LineChartBaseVue from "@/views/copilot/components/LineChartBase.vue"; | |||
export default { | |||
name: "ElecCost", | |||
components: { | |||
BarChartBase: BarChartBaseVue, | |||
LineChartBase: LineChartBaseVue, | |||
}, | |||
props: { | |||
period: { | |||
type: String, | |||
default: "日", | |||
}, | |||
}, | |||
data() { | |||
// 城市数组的顺序必须是固定的 | |||
const cities = ["瑞昌", "邯郸", "株洲", "佳木斯", "成都", "凯盛", "蚌埠"]; | |||
return { | |||
xAxis: cities, | |||
}; | |||
}, | |||
computed: { | |||
legend() { | |||
switch (this.period) { | |||
case "日": | |||
return [{ label: "昨日", color: "#12f7f1" }]; | |||
case "周": | |||
return [{ label: "本周", color: "#12f7f1" }]; | |||
case "月": { | |||
const year = new Date().getFullYear(); | |||
const month = new Date().getMonth() + 1; | |||
return [ | |||
{ label: `${year - 1}年${month}月`, color: "#12f7f1" }, | |||
{ label: `${year}年${month}月`, color: "#58adfa" }, | |||
]; | |||
} | |||
case "年": { | |||
const year = new Date().getFullYear(); | |||
return [ | |||
{ label: `${year - 1}年`, color: "#12f7f1" }, | |||
{ label: `${year}年`, color: "#58adfa" }, | |||
]; | |||
} | |||
default: | |||
return [ | |||
{ label: `${year - 1}年`, color: "#12f7f1" }, | |||
{ label: `${year}年`, color: "#58adfa" }, | |||
]; | |||
} | |||
}, | |||
series() { | |||
const { ftoInvest } = this.$store.getters.copilot.yield; | |||
let dataList = null; | |||
switch (this.period) { | |||
case "日": | |||
case "周": | |||
dataList = ftoInvest?.current; | |||
break; | |||
default: | |||
dataList = []; | |||
dataList[0] = ftoInvest?.pervious; | |||
dataList[1] = ftoInvest?.current; | |||
} | |||
return getTemplate(this.period, dataList); | |||
}, | |||
}, | |||
methods: {}, | |||
}; | |||
function getTemplate(period, dataList) { | |||
const year = new Date().getFullYear(); | |||
const month = new Date().getMonth() + 1; | |||
return period == "日" || period == "周" | |||
? [ | |||
{ | |||
name: period == "日" ? "昨日" : "本周", | |||
data: dataList ?? [], | |||
}, | |||
] | |||
: [ | |||
{ | |||
name: period == "年" ? `${year - 1}年` : `${year - 1}年${month}月`, | |||
data: dataList ? dataList[0] : [], | |||
}, | |||
{ | |||
name: period == "年" ? `${year}年` : `${year}年${month}月`, | |||
data: dataList ? dataList[1] : [], | |||
// : Array.from({ length: 7 }, () => Math.floor(Math.random() * 1000)), | |||
}, | |||
]; | |||
} | |||
</script> | |||
<style scoped lang="scss"> | |||
.elec-cost { | |||
flex: 1; | |||
} | |||
</style> |
@@ -0,0 +1,115 @@ | |||
<!-- | |||
filename: NatGas.vue | |||
author: liubin | |||
date: 2024-04-29 16:36:27 | |||
description: 天然气能耗 | |||
--> | |||
<template> | |||
<BarChartBase | |||
:legend="legend" | |||
:series="series" | |||
:xAxis="xAxis" | |||
in="nat-gas" | |||
class="nat-gas" | |||
/> | |||
</template> | |||
<script> | |||
import BarChartBase from "@/views/copilot/components/BarChartBase.vue"; | |||
export default { | |||
name: "NatGasCost", | |||
components: { BarChartBase }, | |||
props: { | |||
period: { | |||
type: String, | |||
default: "日", | |||
}, | |||
}, | |||
data() { | |||
// 城市数组的顺序必须是固定的 | |||
const cities = ["瑞昌", "邯郸", "株洲", "佳木斯", "成都", "凯盛", "蚌埠"]; | |||
return { | |||
xAxis: cities, | |||
}; | |||
}, | |||
computed: { | |||
legend() { | |||
switch (this.period) { | |||
case "日": | |||
return [{ label: "昨日", color: "#12f7f1" }]; | |||
case "周": | |||
return [{ label: "本周", color: "#12f7f1" }]; | |||
case "月": { | |||
const year = new Date().getFullYear(); | |||
const month = new Date().getMonth() + 1; | |||
return [ | |||
{ label: `${year - 1}年${month}月`, color: "#12f7f1" }, | |||
{ label: `${year}年${month}月`, color: "#58adfa" }, | |||
]; | |||
} | |||
case "年": { | |||
const year = new Date().getFullYear(); | |||
return [ | |||
{ label: `${year - 1}年`, color: "#12f7f1" }, | |||
{ label: `${year}年`, color: "#58adfa" }, | |||
]; | |||
} | |||
default: | |||
return [ | |||
{ label: `${year - 1}年`, color: "#12f7f1" }, | |||
{ label: `${year}年`, color: "#58adfa" }, | |||
]; | |||
} | |||
}, | |||
series() { | |||
const { ftoInvest } = this.$store.getters.copilot.yield; | |||
let dataList = null; | |||
switch (this.period) { | |||
case "日": | |||
case "周": | |||
dataList = ftoInvest?.current; | |||
break; | |||
default: | |||
dataList = []; | |||
dataList[0] = ftoInvest?.pervious; | |||
dataList[1] = ftoInvest?.current; | |||
} | |||
return getTemplate(this.period, dataList); | |||
}, | |||
}, | |||
methods: {}, | |||
}; | |||
function getTemplate(period, dataList) { | |||
const year = new Date().getFullYear(); | |||
const month = new Date().getMonth() + 1; | |||
return period == "日" || period == "周" | |||
? [ | |||
{ | |||
name: period == "日" ? "昨日" : "本周", | |||
data: dataList ?? [], | |||
}, | |||
] | |||
: [ | |||
{ | |||
name: period == "年" ? `${year - 1}年` : `${year - 1}年${month}月`, | |||
data: dataList ? dataList[0] : [], | |||
}, | |||
{ | |||
name: period == "年" ? `${year}年` : `${year}年${month}月`, | |||
data: dataList ? dataList[1] : [], | |||
// : Array.from({ length: 7 }, () => Math.floor(Math.random() * 1000)), | |||
}, | |||
]; | |||
} | |||
</script> | |||
<style scoped lang="scss"> | |||
.nat-gas { | |||
flex: 1; | |||
} | |||
</style> |
@@ -0,0 +1,64 @@ | |||
<!-- | |||
* @Author: zhp | |||
* @Date: 2024-05-07 10:25:10 | |||
* @LastEditTime: 2024-05-08 09:39:15 | |||
* @LastEditors: zhp | |||
* @Description: | |||
--> | |||
<template> | |||
<div class="stock-monitor"> | |||
<MonitorItem | |||
:cities="['成都', '邯郸', '株洲', '瑞昌', '佳木斯']" | |||
:legendList="dhgList" | |||
/> | |||
<MonitorItem :cities="['凯盛光伏', '蚌埠兴科']" :legendList="otherList" /> | |||
</div> | |||
</template> | |||
<script> | |||
import MonitorItemVue from "./sub/monitor/MonitorItem.vue"; | |||
export default { | |||
name: "StockMonitor", | |||
components: { MonitorItem: MonitorItemVue }, | |||
props: {}, | |||
data() { | |||
return { | |||
dhgList: [ | |||
{ name: "总库存", value: 1000 }, | |||
{ name: "已用库存", value: 500 }, | |||
{ name: "剩余库存", value: 500 }, | |||
], | |||
otherList: [ | |||
{ name: "分类1", value: 1000 }, | |||
{ name: "分类2", value: 1000 }, | |||
{ name: "分类3", value: 1000 }, | |||
{ name: "分类4", value: 1000 }, | |||
], | |||
}; | |||
}, | |||
computed: {}, | |||
methods: {}, | |||
}; | |||
</script> | |||
<style scoped lang="scss"> | |||
.stock-monitor { | |||
flex: 1; | |||
display: flex; | |||
gap: 5px; | |||
position: relative; | |||
&:after { | |||
content: ""; | |||
position: absolute; | |||
left: 50%; | |||
top: 0; | |||
width: 3px; | |||
height: 100%; | |||
transform: translateX(-50%); | |||
background: linear-gradient(to bottom, transparent, #00f2ff, transparent); | |||
} | |||
} | |||
</style> |
@@ -0,0 +1,128 @@ | |||
<!-- | |||
filename: WaterCost.vue | |||
author: liubin | |||
date: 2024-04-29 16:37:34 | |||
description: 水能耗 | |||
--> | |||
<template> | |||
<LineChartBase | |||
v-if="0" | |||
:legend="legend" | |||
:series="series" | |||
:xAxis="xAxis" | |||
in="waterCost" | |||
class="water-cost" | |||
/> | |||
<BarChartBase | |||
v-else | |||
:legend="legend" | |||
:series="series" | |||
:xAxis="xAxis" | |||
in="waterCost" | |||
class="water-cost" | |||
/> | |||
</template> | |||
<script> | |||
import BarChartBaseVue from "@/views/copilot/components/BarChartBase.vue"; | |||
import LineChartBaseVue from "@/views/copilot/components/LineChartBase.vue"; | |||
export default { | |||
name: "WaterCost", | |||
components: { | |||
BarChartBase: BarChartBaseVue, | |||
LineChartBase: LineChartBaseVue, | |||
}, | |||
props: { | |||
period: { | |||
type: String, | |||
default: "日", | |||
}, | |||
}, | |||
data() { | |||
// 城市数组的顺序必须是固定的 | |||
const cities = ["瑞昌", "邯郸", "株洲", "佳木斯", "成都", "凯盛", "蚌埠"]; | |||
return { | |||
xAxis: cities, | |||
}; | |||
}, | |||
computed: { | |||
legend() { | |||
switch (this.period) { | |||
case "日": | |||
return [{ label: "昨日", color: "#12f7f1" }]; | |||
case "周": | |||
return [{ label: "本周", color: "#12f7f1" }]; | |||
case "月": { | |||
const year = new Date().getFullYear(); | |||
const month = new Date().getMonth() + 1; | |||
return [ | |||
{ label: `${year - 1}年${month}月`, color: "#12f7f1" }, | |||
{ label: `${year}年${month}月`, color: "#58adfa" }, | |||
]; | |||
} | |||
case "年": { | |||
const year = new Date().getFullYear(); | |||
return [ | |||
{ label: `${year - 1}年`, color: "#12f7f1" }, | |||
{ label: `${year}年`, color: "#58adfa" }, | |||
]; | |||
} | |||
default: | |||
return [ | |||
{ label: `${year - 1}年`, color: "#12f7f1" }, | |||
{ label: `${year}年`, color: "#58adfa" }, | |||
]; | |||
} | |||
}, | |||
series() { | |||
const { ftoInvest } = this.$store.getters.copilot.yield; | |||
let dataList = null; | |||
switch (this.period) { | |||
case "日": | |||
case "周": | |||
dataList = ftoInvest?.current; | |||
break; | |||
default: | |||
dataList = []; | |||
dataList[0] = ftoInvest?.pervious; | |||
dataList[1] = ftoInvest?.current; | |||
} | |||
return getTemplate(this.period, dataList); | |||
}, | |||
}, | |||
methods: {}, | |||
}; | |||
function getTemplate(period, dataList) { | |||
const year = new Date().getFullYear(); | |||
const month = new Date().getMonth() + 1; | |||
return period == "日" || period == "周" | |||
? [ | |||
{ | |||
name: period == "日" ? "昨日" : "本周", | |||
data: dataList ?? [], | |||
}, | |||
] | |||
: [ | |||
{ | |||
name: period == "年" ? `${year - 1}年` : `${year - 1}年${month}月`, | |||
data: dataList ? dataList[0] : [], | |||
}, | |||
{ | |||
name: period == "年" ? `${year}年` : `${year}年${month}月`, | |||
data: dataList ? dataList[1] : [], | |||
// : Array.from({ length: 7 }, () => Math.floor(Math.random() * 1000)), | |||
}, | |||
]; | |||
} | |||
</script> | |||
<style scoped lang="scss"> | |||
.water-cost { | |||
flex: 1; | |||
} | |||
</style> |
@@ -0,0 +1,151 @@ | |||
<!-- | |||
filename: ChipRateItem.vue | |||
author: liubin | |||
date: 2024-04-29 14:25:18 | |||
description: | |||
--> | |||
<template> | |||
<div class="monitor-item"> | |||
<div class="cities"> | |||
<CopilotButtons :options="cities" @update:active="handleCityUpdate" /> | |||
</div> | |||
<div class="chart" ref="chart"></div> | |||
<div class="legend" v-if="1"> | |||
<div class="legend-item" v-for="(lgd,index) in legendList" :key="lgd.name"> | |||
<div > | |||
<span :style="'backgroundColor:' + colors[index%5]" class="legend-item__chart"></span> | |||
<span :style="'color:' + colors[index%5]" class="legend-item__label">{{ lgd.name }}</span> | |||
</div> | |||
<div :style="'color:' + colors[index%5]" class="legend-item__value">{{ lgd.value }}</div> | |||
</div> | |||
</div> | |||
</div> | |||
</template> | |||
<script> | |||
import CopilotButtons from "@/views/copilot/components/select.vue"; | |||
import chartMixin from "@/mixins/chart.js"; | |||
import fullscreenMixin from "@/mixins/fullscreen.js"; | |||
import getOptions from "../../../options/monitorOptions.js"; | |||
export default { | |||
name: "ChipRateItem", | |||
components: { CopilotButtons }, | |||
mixins: [chartMixin, fullscreenMixin], | |||
props: { | |||
cities: { | |||
type: Array, | |||
default: () => [], | |||
}, | |||
legendList: { | |||
type: Array, | |||
default: () => [], | |||
}, | |||
color: { | |||
type: Number, | |||
default: 1, | |||
}, | |||
}, | |||
data() { | |||
return { | |||
period: "月", | |||
colors:['#2760FF', '#5996F7', '#8BC566', '#11FAF0', '#F3C000'], | |||
valueTuple: [100, 100, 200], | |||
}; | |||
}, | |||
computed: { | |||
options() { | |||
const year = new Date().getFullYear(); | |||
const month = new Date().getMonth() + 1; | |||
let arr = [] | |||
this.legendList.forEach(ele => { | |||
arr.push(ele.value) | |||
}); | |||
let vt = arr | |||
console.log(arr) | |||
let titleValue = vt.reduce(function (prev, cur, index, arr) { | |||
return prev + cur | |||
}) | |||
let subtitle = `总计/片`; | |||
return getOptions({ | |||
single: true, | |||
color: this.color == 1 ? "#4CF0E8" : "#1065ff", | |||
titleValue, | |||
subtitle, | |||
dataList:this.legendList, | |||
previousSum: this.valueTuple[0], | |||
currentSum: this.valueTuple[1], | |||
targetSum: this.valueTuple[2], | |||
}); | |||
}, | |||
}, | |||
mounted() { | |||
this.initOptions(this.options); | |||
}, | |||
methods: { | |||
handleCityUpdate() {}, | |||
fullscreenCallback(isFullscreen) { | |||
console.log("isFullscreen--->", isFullscreen); | |||
}, | |||
}, | |||
}; | |||
</script> | |||
<style scoped lang="scss"> | |||
.monitor-item { | |||
flex: 1; | |||
display: flex; | |||
flex-direction: column; | |||
align-items: center; | |||
justify-content: center; | |||
gap: 3px; | |||
backdrop-filter: blur(24px); | |||
.cities { | |||
height: 40px; | |||
} | |||
.chart { | |||
align-self: stretch; | |||
height: 280px; | |||
} | |||
.legend { | |||
height: 80px; | |||
display: flex; | |||
gap: 20px; | |||
justify-content: space-around; | |||
} | |||
.legend-item { | |||
display: flex; | |||
// width: 90px; | |||
flex-direction: column; | |||
// justify-content: space-around; | |||
// justify-content: space-between; | |||
align-items: center; | |||
flex-wrap: wrap; | |||
gap: 3px; | |||
.legend-item__chart{ | |||
display: inline-block; | |||
width: 14px; | |||
height: 14px; | |||
background: #2760FF; | |||
border-radius: 2px; | |||
// margin-right: 8px; | |||
} | |||
.legend-item__label { | |||
margin-left: 8px; | |||
} | |||
// } | |||
} | |||
.legend-item__value { | |||
font-size: 24px; | |||
font-weight: 600; | |||
} | |||
} | |||
</style> | |||
l |
@@ -1,25 +1,83 @@ | |||
<!-- | |||
filename: index.vue | |||
author: liubin | |||
date: 2024-04-16 14:40:15 | |||
description: 能源驾驶舱 | |||
<!-- | |||
* @Author: zhp | |||
* @Date: 2024-05-07 10:25:10 | |||
* @LastEditTime: 2024-05-08 15:29:28 | |||
* @LastEditors: zhp | |||
* @Description: | |||
--> | |||
<template> | |||
<div class="energy-copilot">能源驾驶舱</div> | |||
<div class="energy-copilot"> | |||
<Container title="仓库监控·当前" icon="ware"> | |||
<StockMonitorVue :period="period" /> | |||
</Container> | |||
<Container title="天然气能耗" icon="gas"> | |||
<NatGasVue :period="period" /> | |||
</Container> | |||
<Container title="电能耗" icon="flash"> | |||
<ElecCostVue :period="period" /> | |||
</Container> | |||
<Container title="水能耗" icon="water"> | |||
<WaterCostVue :period="period" /> | |||
</Container> | |||
</div> | |||
</template> | |||
<script> | |||
import Container from "@/views/copilot/components/Container.vue"; | |||
import StockMonitorVue from "./components/StockMonitor.vue"; | |||
import ElecCostVue from "./components/ElecCost.vue"; | |||
import NatGasVue from "./components/NatGas.vue"; | |||
import WaterCostVue from "./components/WaterCost.vue"; | |||
export default { | |||
name: "EnergyCopilot", | |||
components: {}, | |||
props: {}, | |||
components: { | |||
Container, | |||
StockMonitorVue, | |||
ElecCostVue, | |||
NatGasVue, | |||
WaterCostVue, | |||
}, | |||
props: { | |||
period: { | |||
type: String, | |||
default: "日", | |||
}, | |||
}, | |||
data() { | |||
return {}; | |||
}, | |||
computed: {}, | |||
methods: {}, | |||
watch: { | |||
period: { | |||
handler(val) { | |||
val && this.fetchData(val); | |||
}, | |||
immediate: true, | |||
}, | |||
}, | |||
methods: { | |||
fetchData(period = "日") { | |||
console.log(`效率驾驶舱,获取${period}数据`); | |||
this.$store.dispatch("copilot/initCopilot", { | |||
period, | |||
source: "comprehensive", | |||
}); | |||
}, | |||
}, | |||
}; | |||
</script> | |||
<style scoped></style> | |||
<style scoped> | |||
.energy-copilot { | |||
flex: 1; | |||
display: grid; | |||
gap: 16px; | |||
grid-template-columns: 1fr 1fr; | |||
/* grid-template-rows: 1fr 1fr; */ | |||
} | |||
.energy-copilot > div { | |||
height: 100%; | |||
} | |||
</style> |
@@ -0,0 +1,84 @@ | |||
/* | |||
* @Author: zhp | |||
* @Date: 2024-05-07 10:25:10 | |||
* @LastEditTime: 2024-05-08 10:30:06 | |||
* @LastEditors: zhp | |||
* @Description: | |||
*/ | |||
export default function ({ | |||
single = false, | |||
colors = ['#2760FF', '#5996F7', '#8BC566', '#11FAF0','#F3C000'], | |||
titleValue, | |||
subtitle, | |||
dataList, | |||
previousSum, | |||
currentSum, | |||
targetSum, | |||
}) { | |||
return { | |||
grid: { | |||
left: 0, | |||
right: 0, | |||
bottom: 0, | |||
top: 0, | |||
containLabel: true, | |||
}, | |||
// tooltip: {}, | |||
title: { | |||
text: titleValue, | |||
left: "49%", | |||
top: "39%", | |||
textAlign: "center", | |||
textStyle: { | |||
fontWeight: 600, | |||
fontSize: 32, | |||
color: "#fffd", | |||
}, | |||
subtext: `\u2002${subtitle}\u2002`, | |||
subtextStyle: { | |||
fontSize: 14, | |||
fontWeight: 100, | |||
color: "#fffd", | |||
align: "right", | |||
}, | |||
}, | |||
// legend: { | |||
// top: '5%', | |||
// left: 'center' | |||
// }, | |||
series: [ | |||
{ | |||
name: 'Access From', | |||
type: 'pie', | |||
// center: ['50%', '40%'], | |||
radius: ['60%', '90%'], | |||
avoidLabelOverlap: false, | |||
labelLine: { | |||
show: false | |||
}, | |||
label: { | |||
show: false | |||
}, | |||
data: dataList && dataList.length > 0 && dataList.map((item, index) => ({ | |||
name:item.name, | |||
value: item.value, | |||
itemStyle:{ | |||
color:{ | |||
type: 'linear', | |||
x: 0, | |||
y: 0, | |||
x2: 0, | |||
y2: 1, | |||
global: false, | |||
colorStops:[ | |||
{offset: 0,color:colors[index%5]}, | |||
{offset: 1,color:colors[index%5]+'33'} | |||
] | |||
} | |||
} | |||
})) | |||
} | |||
] | |||
}; | |||
} |
@@ -1,8 +1,8 @@ | |||
<!-- | |||
<!-- | |||
filename: FtoInvest.vue | |||
author: liubin | |||
date: 2024-04-10 08:59:28 | |||
description: | |||
description: | |||
--> | |||
<template> | |||
@@ -16,7 +16,7 @@ | |||
</template> | |||
<script> | |||
import BarChartBase from "./sub/bar/BarChartBase.vue"; | |||
import BarChartBase from "@/views/copilot/components/BarChartBase.vue"; | |||
export default { | |||
name: "ChipInvest", | |||
@@ -73,7 +73,7 @@ export default { | |||
break; | |||
default: | |||
dataList = []; | |||
dataList[0] = chipInvest?.pervious; | |||
dataList[0] = chipInvest?.previous; | |||
dataList[1] = chipInvest?.current; | |||
} | |||
return getTemplate(this.period, dataList); | |||
@@ -1,8 +1,8 @@ | |||
<!-- | |||
<!-- | |||
filename: FtoInvest.vue | |||
author: liubin | |||
date: 2024-04-10 08:59:28 | |||
description: | |||
description: | |||
--> | |||
<template> | |||
@@ -16,7 +16,7 @@ | |||
</template> | |||
<script> | |||
import BarChartBase from "./sub/bar/BarChartBase.vue"; | |||
import BarChartBase from "@/views/copilot/components/BarChartBase.vue"; | |||
export default { | |||
name: "FtoInvest", | |||
@@ -74,7 +74,7 @@ export default { | |||
break; | |||
default: | |||
dataList = []; | |||
dataList[0] = ftoInvest?.pervious; | |||
dataList[0] = ftoInvest?.previous; | |||
dataList[1] = ftoInvest?.current; | |||
} | |||
@@ -13,7 +13,7 @@ | |||
</template> | |||
<script> | |||
import Icon from "../../../assets/icon.png"; | |||
import Icon from "@/views/copilot/assets/icon.png"; | |||
export default { | |||
name: "CityName", | |||
@@ -1,8 +1,8 @@ | |||
<!-- | |||
<!-- | |||
filename: DoubleRingChart.vue | |||
author: liubin | |||
date: 2024-04-17 11:01:55 | |||
description: | |||
description: | |||
--> | |||
<template> | |||
@@ -70,6 +70,7 @@ export default { | |||
// [previousValue, currentValue, sumValue?] | |||
const getter = this.$store.getters.copilot.yield[this.dataSourceField]; | |||
if (this.period === "日" || this.period === "周") { | |||
console.log(this.period) | |||
return [ | |||
getter.previous[this.factoryId], | |||
getter.current[this.factoryId], | |||
@@ -1,4 +1,4 @@ | |||
<!-- | |||
<!-- | |||
filename: index.vue | |||
author: liubin | |||
date: 2024-04-16 14:40:15 | |||
@@ -1,7 +1,7 @@ | |||
<!-- | |||
* @Author: zhp | |||
* @Date: 2024-04-15 10:49:13 | |||
* @LastEditTime: 2024-04-17 16:14:51 | |||
* @LastEditTime: 2024-05-06 14:55:56 | |||
* @LastEditors: zhp | |||
* @Description: | |||
--> | |||
@@ -36,7 +36,7 @@ | |||
<script> | |||
// import { parseTime } from '../../core/mixins/code-filter'; | |||
// import { getGlassPage, exportGlasscExcel } from '@/api/report/glass'; | |||
import { getOrderList, getCostPage } from '@/api/cost/index'; | |||
// import inputTable from './inputTable.vue'; | |||
import lineChart from './lineChart'; | |||
import moment from 'moment' | |||
@@ -47,11 +47,11 @@ export default { | |||
data() { | |||
return { | |||
listQuery: { | |||
pageSize: 10, | |||
pageNo: 1, | |||
factoryId: null, | |||
total: 0, | |||
type: null, | |||
current: 1, | |||
size: 10, | |||
// factoryId: null, | |||
// total: 0, | |||
// type: null, | |||
// reportType: 2, | |||
reportTime: [] | |||
}, | |||
@@ -230,7 +230,7 @@ export default { | |||
mounted() { | |||
this.getDict() | |||
// this.getCurrentYearFirst() | |||
// this.getDataList() | |||
this.getDataList() | |||
}, | |||
methods: { | |||
buttonClick() { | |||
@@ -264,10 +264,14 @@ export default { | |||
} | |||
}, | |||
async getDict() { | |||
this.$refs.lineChart.initChart() | |||
// this.$refs.lineChart.initChart() | |||
// 产线列表 | |||
// const res = await getCorePLList(); | |||
// this.proLineList = res.data; | |||
const res = await getOrderList({ | |||
current:1, | |||
size:999, | |||
}); | |||
console.log(res) | |||
this.mainFormConfig[0].selectOptions = res.data; | |||
}, | |||
// 获取数据列表 | |||
multipliedByHundred(str) { | |||
@@ -293,6 +297,10 @@ export default { | |||
}, | |||
async getDataList() { | |||
const res = await getCostPage({ | |||
current: 1, | |||
size: 999, | |||
}); | |||
}, | |||
add0(m) { | |||
return m < 10 ? '0' + m : m | |||
@@ -1,7 +1,7 @@ | |||
<!-- | |||
* @Author: zhp | |||
* @Date: 2024-04-15 10:49:13 | |||
* @LastEditTime: 2024-04-17 16:14:31 | |||
* @LastEditTime: 2024-05-06 09:24:02 | |||
* @LastEditors: zhp | |||
* @Description: | |||
--> | |||
@@ -9,7 +9,7 @@ | |||
<div style="display: flex; flex-direction: column; min-height: calc(100vh - 96px - 31px)"> | |||
<div class="app-container" style="padding: 16px 24px 0;height: auto; flex-grow: 1;"> | |||
<div style="background: #fff; height: 70px; width:100%"> | |||
<ButtonNav :menus="['水', '电', '气']" :button-mode="true" @change="currentMenu = $event"> | |||
<ButtonNav :menus="['水', '电', '气']" :button-mode="true" @change="handleChange"> | |||
</ButtonNav> | |||
</div> | |||
<el-form :model="listQuery" :inline="true" ref="dataForm" class="blueTip"> | |||
@@ -93,8 +93,8 @@ | |||
</template> | |||
<script> | |||
// import { parseTime } from '../../core/mixins/code-filter'; | |||
// import { getGlassPage, exportGlasscExcel } from '@/api/report/glass'; | |||
import { parseTime } from '@/mixins/code-filter'; | |||
import { getEnergyPage } from '@/api/energy'; | |||
// import inputTable from './inputTable.vue'; | |||
import lineChart from './lineChart'; | |||
import moment from 'moment' | |||
@@ -116,27 +116,6 @@ export default { | |||
}, | |||
date1: undefined, | |||
date2: undefined, | |||
// weekNum: undefined, | |||
dataList: [ | |||
{ | |||
id:'first', | |||
}, | |||
{ | |||
id: 'second', | |||
}, | |||
{ | |||
id: 'third', | |||
}, | |||
{ | |||
id: 'fourth', | |||
}, | |||
{ | |||
id: 'fifth', | |||
}, | |||
{ | |||
id: 'sixth', | |||
}, | |||
], | |||
urlOptions: { | |||
// getDataListURL: getGlassPage, | |||
// exportURL: exportGlasscExcel | |||
@@ -216,13 +195,14 @@ export default { | |||
type:'button', | |||
btnName: '导出', | |||
name: 'export', | |||
color: 'warning', | |||
plain: true, | |||
color: 'primary', | |||
}, | |||
], | |||
formConfig: [ | |||
{ | |||
type: 'title', | |||
label: '成本管理', | |||
label: '能源管理', | |||
}, | |||
], | |||
timeList: [ | |||
@@ -258,8 +238,9 @@ export default { | |||
// filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'), | |||
// }, | |||
{ | |||
prop: 'userName', | |||
prop: 'createTime', | |||
label: '日期', | |||
filter: parseTime, | |||
}, | |||
{ | |||
prop: 'nickName', | |||
@@ -303,9 +284,12 @@ export default { | |||
mounted() { | |||
this.getDict() | |||
// this.getCurrentYearFirst() | |||
// this.getDataList() | |||
this.getDataList() | |||
}, | |||
methods: { | |||
handleChange(e) { | |||
console.log(e); | |||
}, | |||
buttonClick() { | |||
}, | |||
@@ -461,6 +445,9 @@ export default { | |||
}, | |||
async getDataList() { | |||
const res = await getEnergyPage(this.listQuery) | |||
this.tableData = res.data.list | |||
// this.dataProps = res.data.list.map() | |||
}, | |||
add0(m) { | |||
return m < 10 ? '0' + m : m | |||
@@ -1,7 +1,7 @@ | |||
<!-- | |||
* @Author: zhp | |||
* @Date: 2024-04-15 10:49:13 | |||
* @LastEditTime: 2024-04-17 16:14:01 | |||
* @LastEditTime: 2024-05-07 08:40:58 | |||
* @LastEditors: zhp | |||
* @Description: | |||
--> | |||
@@ -11,18 +11,18 @@ | |||
<!-- <el-alert title="自定义 close-text" type="warning" close-text="知道了"> | |||
</el-alert> --> | |||
<el-form :model="listQuery" :inline="true" ref="dataForm" class="blueTip"> | |||
<el-form-item label="时间维度" prop="reportTime"> | |||
<el-select clearable v-model="timeSelect" placeholder="请选择"> | |||
<el-form-item label="时间维度" prop="mode"> | |||
<el-select clearable v-model="listQuery.mode" placeholder="请选择"> | |||
<el-option v-for="item in timeList" :key="item.value" :label="item.label" :value="item.value"> | |||
</el-option> | |||
</el-select> | |||
</el-form-item> | |||
<el-form-item v-show="timeSelect === 'month'" label="时间范围" prop="reportTime"> | |||
<el-form-item v-show="listQuery.mode === 2" label="时间范围" prop="reportTime"> | |||
<el-date-picker clearable v-model="listQuery.reportTime" type="monthrange" range-separator="至" | |||
start-placeholder="开始月份" end-placeholder="结束月份" @change="changeTime"> | |||
</el-date-picker> | |||
</el-form-item> | |||
<el-form-item v-show="timeSelect === 'year'" label="时间范围" prop="reportTime"> | |||
<el-form-item v-show="listQuery.mode === 3" label="时间范围" prop="reportTime"> | |||
<el-date-picker clearable v-model="listQuery.reportTime[0]" value-format="yyyy" type="year" | |||
placeholder="开始时间"> | |||
</el-date-picker> | |||
@@ -31,8 +31,8 @@ | |||
@change="getYear"> | |||
</el-date-picker> | |||
</el-form-item> | |||
<el-form-item label="工厂名称" prop="factoryId"> | |||
<el-select clearable v-model="listQuery.factoryId" placeholder="请选择工厂名称"> | |||
<el-form-item label="工厂名称" prop="factorys"> | |||
<el-select clearable v-model="listQuery.factorys" placeholder="请选择工厂名称" multiple> | |||
<el-option v-for="item in factoryList" :key="item.id" :label="item.name" :value="item.id"> | |||
</el-option> | |||
</el-select> | |||
@@ -56,8 +56,7 @@ | |||
</div> | |||
<div class="app-container" style="margin-top: 18px;flex-grow: 1; padding: 16px;"> | |||
<search-bar :formConfigs="formConfig" ref="searchBarForm" @headBtnClick="buttonClick" /> | |||
<base-table :table-props="tableProps" :page="listQuery.pageNo" :limit="listQuery.pageSize" | |||
:table-data="tableData"> | |||
<base-table :table-props="tableProps" :page="listQuery.current" :limit="listQuery.size" :table-data="tableData"> | |||
</base-table> | |||
</div> | |||
<!-- <inputTable :date="date" :data="tableData" :time="[startTimeStamp, endTimeStamp]" :sum="all" | |||
@@ -71,8 +70,8 @@ | |||
</template> | |||
<script> | |||
// import { parseTime } from '../../core/mixins/code-filter'; | |||
// import { getGlassPage, exportGlasscExcel } from '@/api/report/glass'; | |||
import { parseTime } from '@/mixins/code-filter'; | |||
import { getEpPage } from '@/api/greenest/index'; | |||
// import inputTable from './inputTable.vue'; | |||
import lineChart from './lineChart'; | |||
import moment from 'moment' | |||
@@ -83,14 +82,18 @@ export default { | |||
data() { | |||
return { | |||
listQuery: { | |||
pageSize: 10, | |||
pageNo: 1, | |||
factoryId: null, | |||
total: 0, | |||
type: null, | |||
current: 1, | |||
size: 10, | |||
factorys: [], | |||
mode: 2, | |||
beginTime: undefined, | |||
endTime: undefined, | |||
// total: 0, | |||
// type: null, | |||
// reportType: 2, | |||
reportTime: [] | |||
}, | |||
dynamicProps: [], | |||
urlOptions: { | |||
// getDataListURL: getGlassPage, | |||
// exportURL: exportGlasscExcel | |||
@@ -103,96 +106,66 @@ export default { | |||
], | |||
timeList: [ | |||
{ | |||
value: 'month', | |||
value: 2, | |||
label:'月' | |||
}, | |||
{ | |||
value: 'year', | |||
value: 3, | |||
label: '年' | |||
} | |||
], | |||
factoryList: [ | |||
{ | |||
name: '测试', | |||
id:1 | |||
} | |||
], | |||
typeList: [ | |||
{ | |||
name: '芯片', | |||
id:0, | |||
id: 0, | |||
name: '瑞昌中建材光电材料有限公司' | |||
}, | |||
{ | |||
name: '标准组件', | |||
id: 1, | |||
name: '邯郸中建材光电材料有限公司' | |||
}, | |||
{ | |||
name: 'BIPV产品', | |||
id: 2, | |||
}, | |||
], | |||
tableProps: [ | |||
// { | |||
// prop: 'createTime', | |||
// label: '添加时间', | |||
// fixed: true, | |||
// width: 180, | |||
// filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'), | |||
// }, | |||
{ | |||
prop: 'userName', | |||
label: '日期', | |||
name: '中建材株洲光电材料有限公司' | |||
}, | |||
{ | |||
prop: 'nickName', | |||
label: '工厂名称', | |||
id: 3, | |||
name: '佳木斯中建材光电材料有限公司' | |||
}, | |||
{ | |||
prop: 'datas', | |||
label: '废水(t)', | |||
// subcomponent: row | |||
id: 4, | |||
name: '成都中建材光电材料有限公司' | |||
}, | |||
{ | |||
prop: 'unit', | |||
label: '废气(m³)', | |||
// subcomponent: row | |||
id: 5, | |||
name: '凯盛光伏材料有限公司' | |||
}, | |||
{ | |||
prop: 'remark', | |||
label: 'VOC(g/L)', | |||
// subcomponent: row | |||
id: 6, | |||
name: '蚌埠兴科玻璃有限公司' | |||
}, | |||
{ | |||
prop: 'kg', | |||
label: '固体废弃物-可回收(kg)', | |||
// subcomponent: row | |||
} | |||
], | |||
timeSelect:'month', | |||
startTimeStamp:null, //开始时间 | |||
endTimeStamp:null, //结束时间 | |||
date:'凯盛玻璃控股成员企业2024生产数据', | |||
// reportTime: '', | |||
startTimeStamp: '', | |||
endTimeStamp: '', | |||
tableData: [ | |||
typeList: [ | |||
{ | |||
userName: 'userName', | |||
nickName: '用户名', | |||
datas:'111111' | |||
name: '芯片', | |||
id:0, | |||
}, | |||
{ | |||
userName: 'userName', | |||
nickName: '用户名', | |||
datas: '111111' | |||
name: '标准组件', | |||
id: 1, | |||
}, | |||
{ | |||
userName: 'userName', | |||
nickName: '用户名', | |||
datas: '111111' | |||
// subcomponent: row | |||
} | |||
name: 'BIPV产品', | |||
id: 2, | |||
}, | |||
], | |||
tableProps: [], | |||
// startTimeStamp:null, //开始时间 | |||
// endTimeStamp:null, //结束时间 | |||
// date:'凯盛玻璃控股成员企业2024生产数据', | |||
// reportTime: '', | |||
// startTimeStamp: '', | |||
// endTimeStamp: '', | |||
tableData: [], | |||
// proLineList: [], | |||
// all: {} | |||
}; | |||
@@ -201,12 +174,26 @@ export default { | |||
this.getDict() | |||
// this.getCurrentYearFirst() | |||
// this.getDataList() | |||
}, | |||
}, | |||
// computed: { | |||
// tableProps() { | |||
// return [ | |||
// { | |||
// prop: 'createTime', | |||
// label: '日期', | |||
// filter: parseTime | |||
// }, | |||
// ...this.dynamicProps, | |||
// ]; | |||
// }, | |||
// }, | |||
methods: { | |||
buttonClick() { | |||
}, | |||
getYear(e) { | |||
this.listQuery.beginTime = this.listQuery.reportTime ? new Date(new Date(new Date(this.listQuery.reportTime[0]).setMonth(0, 1)).setHours(0, 0, 0)).getTime() : undefined | |||
this.listQuery.endTime = this.listQuery.reportTime ? new Date(new Date(new Date(this.listQuery.reportTime[1]).setMonth(11, 31)).setHours(23,59,59)).getTime() : undefined | |||
if (this.listQuery.reportTime[0] && e - this.listQuery.reportTime[0] > 10) { | |||
this.$message({ | |||
message: '年份起止时间不能超过十年', | |||
@@ -218,20 +205,22 @@ export default { | |||
}, | |||
changeTime() { | |||
if (this.listQuery.reportTime) { | |||
this.createStartDate = moment(new Date(this.listQuery.reportTime[0]), 'yyyy-MM-dd hh:mm:ss'); | |||
this.createEndDate = moment(new Date(this.listQuery.reportTime[1]), 'yyyy-MM-dd hh:mm:ss'); | |||
this.listQuery.beginTime = this.listQuery.reportTime ? new Date(this.listQuery.reportTime[0]).getTime() : undefined | |||
this.listQuery.endTime = this.listQuery.reportTime ? new Date(this.listQuery.reportTime[1]).getTime() : undefined | |||
// this.createStartDate = moment(new Date(this.listQuery.reportTime[0]), 'yyyy-MM-dd hh:mm:ss'); | |||
// this.createEndDate = moment(new Date(this.listQuery.reportTime[1]), 'yyyy-MM-dd hh:mm:ss'); | |||
const numDays = (new Date(this.listQuery.reportTime[1]).getTime() - new Date(this.listQuery.reportTime[0]).getTime()) / (24 * 3600 * 1000); if (numDays > 730) { | |||
this.$message({ | |||
message: '时间范围不能超过24个月', | |||
type: 'warning' | |||
}); | |||
this.listQuery.reportTime = []; | |||
this.createStartDate = ''; | |||
this.createEndDate = ''; | |||
// this.createStartDate = ''; | |||
// this.createEndDate = ''; | |||
} | |||
} else { | |||
this.createStartDate = ''; | |||
this.createEndDate = ''; | |||
// this.createStartDate = ''; | |||
// this.createEndDate = ''; | |||
} | |||
}, | |||
async getDict() { | |||
@@ -264,61 +253,109 @@ export default { | |||
}, | |||
async getDataList() { | |||
// this.tableData = [] | |||
// this.tabl | |||
const res = await getEpPage(this.listQuery) | |||
let arr =[ | |||
{ | |||
prop: 'createTime', | |||
label: '日期', | |||
// filter: parseTime | |||
}, | |||
{ | |||
prop: 'factory', | |||
label: '工厂名称', | |||
filter: (val) => ['瑞昌中建材光电材料有限公司', '邯郸中建材光电材料有限公司', '中建材株洲光电材料有限公司', '佳木斯中建材光电材料有限公司', '成都中建材光电材料有限公司', '凯盛光伏材料有限公司', '蚌埠兴科玻璃有限公司'][val] | |||
} | |||
] | |||
// console.log(dataArr); | |||
// for (let i = 0; i < res.data.list.length-1; i++) { | |||
// if (r[i].createTime != r[i + 1].createTime ) { | |||
// this.data.a.push(r[i]) | |||
// } | |||
// } | |||
// console.log(res.data); | |||
// this.dynamicProps = [] | |||
const dateList = [] | |||
const processList = [] | |||
const factoryList = [] | |||
res.data.records.forEach(ele => { | |||
// 表头 | |||
dateList.push(ele.environmentalProtectionName) | |||
// 列数 | |||
processList.push(ele.createTime) | |||
factoryList.push(ele.factory) | |||
}) | |||
this.dateProps = Array.from(new Set(dateList)) | |||
// this.processArray = Array.from(new Set(processList)) | |||
// this.factoryArray = Array.from(new Set(factoryList)) | |||
// this.factoryArray.forEach(item => { | |||
// const props = | |||
// arr.push(props) | |||
// }) | |||
// res.data.records.forEach(ele => { | |||
// if (this.factoryArray.some(ele.factory) && this.factoryArray.some(ele.createTime)) { | |||
// arr.push({ | |||
// }) | |||
// } | |||
// // 表头 | |||
// // dateList.push(ele.environmentalProtectionName) | |||
// // 列数 | |||
// // processList.push(ele.createTime) | |||
// // factoryList.push(ele.factory) | |||
// }) | |||
this.dateProps.forEach(item => { | |||
const props = { | |||
'prop': item, | |||
'label': item | |||
} | |||
arr.push(props) | |||
}) | |||
this.tableProps = arr | |||
this.tableData = this.mergeGrade(res.data.records) | |||
console.log(this.tableData) | |||
// // 构造表格数据 | |||
// this.total = this.processArray.length | |||
// this.processArray.forEach(process => { | |||
// const listData = { | |||
// 'createTime': process, | |||
// 'factory':null | |||
// } | |||
// res.data.records.forEach((r,index) => { | |||
// if (process === r.createTime) { | |||
// // const temp = Object.keys(r).filter(keys => keys !== 'reportDate' && keys !== 'factory' && keys !== 'environmentalProtectionName' && keys !== 'id' && keys !== 'createTime') | |||
// // const item = Object.keys(r).filter(keys => keys !== 'reportDate' && keys !== 'environmentalProtectionValue' && keys !== 'environmentalProtectionName' && keys !== 'id' && keys !== 'createTime') | |||
// // console.log(r[item[0]]); | |||
// listData[r.environmentalProtectionName] = r.environmentalProtectionValue | |||
// listData.factory = r.factory | |||
// } | |||
// }) | |||
// console.log(listData); | |||
// this.tableData.push(listData) | |||
// }) | |||
}, | |||
add0(m) { | |||
return m < 10 ? '0' + m : m | |||
}, | |||
format(shijianchuo) { | |||
//shijianchuo是整数,否则要parseInt转换 | |||
var time = moment(new Date(shijianchuo)).format('YYYY-MM-DD HH:mm:ss') | |||
// console.log(time) | |||
// var y = time.getFullYear(); | |||
// var m = time.getMonth() + 1; | |||
// var d = time.getDate(); | |||
// var h = time.getHours(); | |||
// var mm = time.getMinutes(); | |||
// var s = time.getSeconds(); | |||
return time | |||
mergeGrade(grade) { | |||
if (!Array.isArray(grade)) return [] | |||
const newGrade = [] | |||
grade.forEach(item => { | |||
const index = newGrade.findIndex(subItem => subItem.factory === item.factory && subItem.createTime === item.createTime) | |||
if (index > -1) { | |||
newGrade[index][item.environmentalProtectionName] = item.environmentalProtectionValue | |||
} else { | |||
newGrade.push({ | |||
factory: item.factory, | |||
createTime: item.groupTime, | |||
[item.environmentalProtectionName]: item.environmentalProtectionValue | |||
// grades: { [item.class]: item.grade } | |||
}) | |||
} | |||
}) | |||
return newGrade | |||
}, | |||
// changeTime(val) { | |||
// if (val) { | |||
// // console.log(val) | |||
// // console.log(val.setHours(7, 0, 0)) | |||
// // console.log(val.setHours(7, 0, 0) + 24 * 60 * 60 * 1000) | |||
// // let time = this.format(val.setHours(7, 0, 0)) | |||
// this.endTimeStamp = this.format(val.setHours(7, 0, 0)) //+ ' 00:00:00' //new Date(this.startTimeStamp + ' 00:00:00').getTime() / 1000 | |||
// this.startTimeStamp = this.format(val.setHours(7, 0, 1) - 24 * 60 * 60 * 1000) //+ ' 23:59:59' //new Date(this.endTimeStamp + ' 23:59:59').getTime() / 1000 | |||
// // console.log(this.listQuery.reportTime); | |||
// this.listQuery.reportTime[0] = this.format(val.setHours(7, 0, 1)) //+ ' 00:00:00' //new Date(this.startTimeStamp + ' 00:00:00').getTime() / 1000 | |||
// this.listQuery.reportTime[1] = this.format(val.setHours(7, 0, 0) + 24 * 60 * 60 * 1000) //+ ' 23:59:59' //new Date(this.endTimeStamp + ' 23:59:59').getTime() / 1000 | |||
// console.log(this.listQuery.reportTime); | |||
// } else { | |||
// this.listQuery.reportTime = [] | |||
// } | |||
// }, | |||
//时间戳转为yy-mm-dd hh:mm:ss | |||
timeFun(unixtimestamp) { | |||
var unixtimestamp = new Date(unixtimestamp); | |||
var year = 1900 + unixtimestamp.getYear(); | |||
var month = "0" + (unixtimestamp.getMonth() + 1); | |||
var date = "0" + unixtimestamp.getDate(); | |||
return year + "-" + month.substring(month.length - 2, month.length) + "-" + date.substring(date.length - 2, date.length) | |||
}, | |||
buttonClick(val) { | |||
this.listQuery.reportTime = val.reportTime ? val.reportTime : undefined; | |||
switch (val.btnName) { | |||
case 'search': | |||
this.listQuery.pageNo = 1; | |||
this.listQuery.pageSize = 10; | |||
this.getDataList(); | |||
break; | |||
case 'export': | |||
this.handleExport(); | |||
break; | |||
default: | |||
console.log(val); | |||
} | |||
}, | |||
/** 导出按钮操作 */ | |||
handleExport() { | |||
// 处理查询参数 | |||
@@ -210,14 +210,6 @@ export default { | |||
}, | |||
}; | |||
</script> | |||
<style> | |||
.hideSidebar.mobile .dashboard-factory-all { | |||
left: 0 !important; | |||
width: 100vw !important; | |||
} | |||
</style> | |||
<style lang="scss" scoped> | |||
.dashboard-factory-all { | |||
background: #151516; | |||
@@ -271,9 +263,9 @@ export default { | |||
z-index: 9998; | |||
width: 1.702vw; | |||
height: 1.702vw; | |||
/* | |||
/* | |||
width: 32px; | |||
height: 32px; | |||
height: 32px; | |||
*/ | |||
background: url(../assets/pinicon.png) no-repeat 0 0 / 100% 100%; | |||
transition: transform 0.1s linear; | |||
@@ -1,4 +1,4 @@ | |||
<!-- | |||
<!-- | |||
filename: playground.vue | |||
author: liubin | |||
date: 2024-04-02 09:42:43 | |||
@@ -1,7 +1,7 @@ | |||
<!-- | |||
* @Author: zhp | |||
* @Date: 2023-11-06 15:15:30 | |||
* @LastEditTime: 2024-04-17 15:37:39 | |||
* @LastEditTime: 2024-05-07 09:31:54 | |||
* @LastEditors: zhp | |||
* @Description: | |||
--> | |||
@@ -156,10 +156,9 @@ | |||
<script> | |||
// import basicAdd from './basic-add'; | |||
// import { | |||
// createQualityScrapLog, updateQualityScrapLog, getQualityScrapLog, getWorkOrderList, | |||
// getTeamList, getDetList, getLineList | |||
// } from "@/api/base/qualityScrapLog"; | |||
import { | |||
getProduceDataDetail | |||
} from "@/api/produceData"; | |||
// import { getList, } from "@/api/base/qualityScrapType"; | |||
import SmallTitle from './SmallTitle'; | |||
export default { | |||
@@ -223,8 +222,11 @@ export default { | |||
// this.getCurrentTime() | |||
}, | |||
methods: { | |||
init() { | |||
init(id) { | |||
this.visible = true | |||
if (id) { | |||
getProduceDataDetail() | |||
} | |||
}, | |||
// getCurrentTime() { | |||
// // new Date().Format("yyyy-MM-dd HH:mm:ss") | |||
@@ -1,7 +1,7 @@ | |||
<!-- | |||
* @Author: zhp | |||
* @Date: 2024-04-15 10:49:13 | |||
* @LastEditTime: 2024-04-17 16:13:47 | |||
* @LastEditTime: 2024-05-07 09:18:01 | |||
* @LastEditors: zhp | |||
* @Description: | |||
--> | |||
@@ -10,17 +10,17 @@ | |||
<div class="app-container" style="padding: 16px 24px 0;height: auto; flex-grow: 1;"> | |||
<el-form :model="listQuery" :inline="true" ref="dataForm" class="blueTip"> | |||
<el-form-item label="时间维度" prop="reportTime"> | |||
<el-select clearable v-model="timeSelect" placeholder="请选择"> | |||
<el-select clearable v-model="listQuery.date" placeholder="请选择"> | |||
<el-option v-for="item in timeList" :key="item.value" :label="item.label" :value="item.value"> | |||
</el-option> | |||
</el-select> | |||
</el-form-item> | |||
<el-form-item v-show="timeSelect === 'day'" label="时间范围" prop="reportTime"> | |||
<el-form-item v-show="listQuery.date === 0" label="时间范围" prop="reportTime"> | |||
<el-date-picker clearable v-model="listQuery.reportTime" type="datetimerange" range-separator="至" | |||
start-placeholder="开始日期" value-format="yyyy-MM-dd HH:mm:ss" @change="changeDayTime" end-placeholder="结束日期"> | |||
</el-date-picker> | |||
</el-form-item> | |||
<el-form-item v-show="timeSelect === 'week'" label="时间范围" prop="reportTime"> | |||
<el-form-item v-show="listQuery.date === 1" label="时间范围" prop="reportTime"> | |||
<el-date-picker clearable v-model="listQuery.reportTime[0]" type="week" format="yyyy 第 WW 周" placeholder="选择周" | |||
style="width: 180px" @change="onValueChange"> | |||
</el-date-picker> | |||
@@ -32,12 +32,12 @@ | |||
{{ date1 }} 至 {{ date2 }},共 {{ weekNum }} 周 | |||
</span> | |||
</el-form-item> | |||
<el-form-item v-show="timeSelect === 'month'" label="时间范围" prop="reportTime"> | |||
<el-form-item v-show="listQuery.date === 2" label="时间范围" prop="reportTime"> | |||
<el-date-picker clearable v-model="listQuery.reportTime" type="monthrange" range-separator="至" | |||
start-placeholder="开始月份" end-placeholder="结束月份" @change="changeTime"> | |||
</el-date-picker> | |||
</el-form-item> | |||
<el-form-item v-show="timeSelect === 'year'" label="时间范围" prop="reportTime"> | |||
<el-form-item v-show="listQuery.date === 3" label="时间范围" prop="reportTime"> | |||
<el-date-picker clearable v-model="listQuery.reportTime[0]" value-format="yyyy" type="year" | |||
placeholder="开始时间"> | |||
</el-date-picker> | |||
@@ -46,8 +46,8 @@ | |||
@change="getYear"> | |||
</el-date-picker> | |||
</el-form-item> | |||
<el-form-item label="工厂名称" prop="factoryId"> | |||
<el-select clearable v-model="listQuery.factoryId" placeholder="请选择工厂名称"> | |||
<el-form-item label="工厂名称" prop="factorys"> | |||
<el-select clearable v-model="listQuery.factorys" placeholder="请选择工厂名称" multiple > | |||
<el-option v-for="item in factoryList" :key="item.id" :label="item.name" :value="item.id"> | |||
</el-option> | |||
</el-select> | |||
@@ -76,7 +76,6 @@ | |||
<!-- <el-col :span="12"> | |||
<line-chart :id=" 'second' " class="yearChart" ref="lineChart" style="height: 40vh;width: 100%"></line-chart> | |||
</el-col> --> | |||
</el-row> | |||
</div> | |||
<div class="app-container" style="margin-top: 18px;flex-grow: 1; height: auto; padding: 16px;"> | |||
<search-bar :formConfigs="formConfig" ref="searchBarForm" @headBtnClick="buttonClick" /> | |||
@@ -99,7 +98,7 @@ | |||
<script> | |||
// import { parseTime } from '../../core/mixins/code-filter'; | |||
// import { getGlassPage, exportGlasscExcel } from '@/api/report/glass'; | |||
import { getProduceDataPage } from '@/api/produceData'; | |||
// import inputTable from './inputTable.vue'; | |||
import lineChart from './lineChart'; | |||
import moment from 'moment' | |||
@@ -115,12 +114,15 @@ export default { | |||
data() { | |||
return { | |||
listQuery: { | |||
pageSize: 10, | |||
pageNo: 1, | |||
factoryId: null, | |||
size: 10, | |||
current: 1, | |||
factorys: [], | |||
total: 0, | |||
type: null, | |||
date: 1, | |||
type:undefined, | |||
// reportType: 2, | |||
beginTime: undefined, | |||
endTime:undefined, | |||
reportTime: [] | |||
}, | |||
detailOrUpdateVisible:false, | |||
@@ -256,24 +258,24 @@ export default { | |||
formConfig: [ | |||
{ | |||
type: 'title', | |||
label: '成本管理', | |||
label: '生产数据管理', | |||
}, | |||
], | |||
timeList: [ | |||
{ | |||
value: 'day', | |||
value: 0, | |||
label: '日' | |||
}, | |||
{ | |||
value: 'week', | |||
value: 1, | |||
label: '周' | |||
}, | |||
{ | |||
value: 'month', | |||
value: 2, | |||
label:'月' | |||
}, | |||
{ | |||
value: 'year', | |||
value: 3, | |||
label: '年' | |||
} | |||
], | |||
@@ -284,67 +286,38 @@ export default { | |||
} | |||
], | |||
tableProps: [ | |||
// { | |||
// prop: 'createTime', | |||
// label: '添加时间', | |||
// fixed: true, | |||
// width: 180, | |||
// filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'), | |||
// }, | |||
{ | |||
prop: 'userName', | |||
prop: 'createTime', | |||
label: '日期', | |||
}, | |||
{ | |||
prop: 'nickName', | |||
prop: 'factory', | |||
label: '工厂名称', | |||
filter: (val) => ['瑞昌中建材光电材料有限公司', '邯郸中建材光电材料有限公司', '中建材株洲光电材料有限公司', '佳木斯中建材光电材料有限公司', '成都中建材光电材料有限公司', '凯盛光伏材料有限公司', '蚌埠兴科玻璃有限公司'][val] | |||
}, | |||
{ | |||
prop: 'type', | |||
prop: 'glassType', | |||
label: '玻璃类型', | |||
filter: (val) => ['玻璃芯片', '标准组件', 'BIPV'][val] | |||
}, | |||
{ | |||
prop: 'inNum', | |||
prop: 'inputNumber', | |||
label: '投入数量', | |||
}, | |||
{ | |||
prop: 'putNum', | |||
prop: 'outputNumber', | |||
label: '产出数量', | |||
}, | |||
{ | |||
prop: 'goodNum', | |||
prop: 'goodNumber', | |||
label: '良品数量', | |||
}, | |||
{ | |||
prop: 'goodYelid', | |||
prop: 'yieldRate', | |||
label: '良品率%', | |||
}, | |||
], | |||
timeSelect:'day', | |||
startTimeStamp:null, //开始时间 | |||
endTimeStamp:null, //结束时间 | |||
// date:'凯盛玻璃控股成员企业2024生产数据', | |||
// reportTime: '', | |||
startTimeStamp: '', | |||
endTimeStamp: '', | |||
tableData: [ | |||
{ | |||
userName: 'userName', | |||
nickName: '用户名', | |||
datas:'111111' | |||
}, | |||
{ | |||
userName: 'userName', | |||
nickName: '用户名', | |||
datas: '111111' | |||
}, | |||
{ | |||
userName: 'userName', | |||
nickName: '用户名', | |||
datas: '111111' | |||
// subcomponent: row | |||
} | |||
], | |||
tableData: [], | |||
// proLineList: [], | |||
// all: {} | |||
}; | |||
@@ -522,6 +495,9 @@ export default { | |||
}, | |||
async getDataList() { | |||
const res = await getProduceDataPage(this.listQuery) | |||
console.log(res) | |||
this.tableData = res.data.records | |||
}, | |||
add0(m) { | |||
return m < 10 ? '0' + m : m | |||
@@ -1,154 +1,202 @@ | |||
<!-- | |||
* @Author: zhp | |||
* @Date: 2023-11-06 15:15:30 | |||
* @LastEditTime: 2024-04-17 15:37:39 | |||
* @Date: 2024-04-17 16:31:51 | |||
* @LastEditTime: 2024-04-17 17:01:14 | |||
* @LastEditors: zhp | |||
* @Description: | |||
--> | |||
<template> | |||
<el-drawer class="drawer" :visible.sync="visible" size="50%"> | |||
<small-title slot="title" :no-padding="true"> | |||
{{ '碲化镉工厂生产数据详情' }} | |||
{{ '新增' }} | |||
</small-title> | |||
<div class="detailBox"> | |||
<el-row :gutter="24"> | |||
<el-col :span="8"> | |||
<p class="title">工厂名称</p> | |||
<p class="text">{{ }}</p> | |||
</el-col> | |||
<el-col :span="8"> | |||
<p class="title">时间维度</p> | |||
<p class="text">{{ dataForm.code }}</p> | |||
</el-col> | |||
<el-col :span="8"> | |||
<p class="title">时间</p> | |||
<p class="text">{{ dataForm.productName }}</p> | |||
</el-col> | |||
</el-row> | |||
<el-divider></el-divider> | |||
<small-title style=" margin: 0;padding: 26px 32px 24px;margin-bottom: 22px;" :no-padding="false"> | |||
{{ '芯片' }} | |||
</small-title> | |||
<el-row :gutter="24"> | |||
<el-col :span="6"> | |||
<p class="title">芯片产量</p> | |||
<p class="text">{{ }}</p> | |||
</el-col> | |||
<el-col :span="6"> | |||
<p class="title">芯片良率</p> | |||
<p class="text">{{ dataForm.code }}</p> | |||
</el-col> | |||
<el-col :span="6"> | |||
<p class="title">芯片良率</p> | |||
<p class="text">{{ dataForm.productName }}</p> | |||
</el-col> | |||
<el-col :span="6"> | |||
<p class="title">芯片总功率</p> | |||
<p class="text">{{ dataForm.productName }}</p> | |||
</el-col> | |||
</el-row> | |||
<el-row :gutter="24"> | |||
<el-col :span="6"> | |||
<p class="title">FTO投入量</p> | |||
<p class="text">{{ }}</p> | |||
</el-col> | |||
<el-col :span="6"> | |||
<p class="title">CSS稼动率</p> | |||
<p class="text">{{ dataForm.code }}</p> | |||
</el-col> | |||
<el-col :span="6"> | |||
<p class="title">芯片段OEE</p> | |||
<p class="text">{{ dataForm.productName }}</p> | |||
</el-col> | |||
<el-col :span="6"> | |||
<p class="title">芯片平均功率</p> | |||
<p class="text">{{ dataForm.productName }}</p> | |||
</el-col> | |||
</el-row> | |||
<el-row :gutter="24"> | |||
<el-col :span="6"> | |||
<p class="title">芯片人均产量</p> | |||
<p class="text">{{ }}</p> | |||
</el-col> | |||
<el-col :span="6"> | |||
<p class="title">芯片产能利用率</p> | |||
<p class="text">{{ dataForm.code }}</p> | |||
</el-col> | |||
</el-row> | |||
<small-title style=" margin: 0;padding: 26px 32px 24px;margin-bottom: 22px;" :no-padding="false"> | |||
{{ '标准组件' }} | |||
</small-title> | |||
<el-row :gutter="24"> | |||
<el-col :span="6"> | |||
<p class="title">封装BOM</p> | |||
<p class="text">{{ }}</p> | |||
</el-col> | |||
<el-col :span="6"> | |||
<p class="title">封装线OEE</p> | |||
<p class="text">{{ dataForm.code }}</p> | |||
</el-col> | |||
<el-col :span="6"> | |||
<p class="title">标准组件良率</p> | |||
<p class="text">{{ dataForm.productName }}</p> | |||
</el-col> | |||
<el-col :span="6"> | |||
<p class="title">标准组件产量</p> | |||
<p class="text">{{ dataForm.productName }}</p> | |||
</el-col> | |||
</el-row> | |||
<el-row :gutter="24"> | |||
<el-col :span="6"> | |||
<p class="title">标准组件总功率</p> | |||
<p class="text">{{ }}</p> | |||
</el-col> | |||
<el-col :span="6"> | |||
<p class="title">封装产能利用率</p> | |||
<p class="text">{{ dataForm.code }}</p> | |||
</el-col> | |||
<el-col :span="6"> | |||
<p class="title">标准组件人均产量</p> | |||
<p class="text">{{ dataForm.productName }}</p> | |||
</el-col> | |||
<el-col :span="6"> | |||
<p class="title">标准组件人均产量</p> | |||
<p class="text">{{ dataForm.productName }}</p> | |||
</el-col> | |||
</el-row> | |||
<small-title style=" margin: 0;padding: 26px 32px 24px;margin-bottom: 22px;" :no-padding="false"> | |||
{{ 'BIPV产品' }} | |||
</small-title> | |||
<el-row :gutter="24"> | |||
<el-col :span="6"> | |||
<p class="title">产品产量</p> | |||
<p class="text">{{ }}</p> | |||
</el-col> | |||
<el-col :span="6"> | |||
<p class="title">人均产量</p> | |||
<p class="text">{{ dataForm.code }}</p> | |||
</el-col> | |||
<el-col :span="6"> | |||
<p class="title">芯片使用量</p> | |||
<p class="text">{{ dataForm.productName }}</p> | |||
</el-col> | |||
<el-col :span="6"> | |||
<p class="title">芯片使用量</p> | |||
<p class="text">{{ dataForm.productName }}</p> | |||
</el-col> | |||
</el-row> | |||
<el-row :gutter="24"> | |||
<el-col :span="6"> | |||
<p class="title">内部材料成本</p> | |||
<p class="text">{{ }}</p> | |||
</el-col> | |||
<el-col :span="6"> | |||
<p class="title">内部材料成本</p> | |||
<p class="text">{{ dataForm.code }}</p> | |||
</el-col> | |||
<el-col :span="6"> | |||
<p class="title">内部材料成本</p> | |||
<p class="text">{{ dataForm.productName }}</p> | |||
</el-col> | |||
</el-row> | |||
<el-form ref="form" :model="dataForm" label-width="80px" label-position="top"> | |||
<el-row :gutter="24" style="padding: 0 32px;"> | |||
<el-col :span="8"> | |||
<el-form-item label="工厂名称" prop="factoryId"> | |||
<el-select v-model="dataForm.factoryId" placeholder="请选择工厂名称" multiple="true" clearable> | |||
<el-option v-for="item in factoryList" :key="item.id" :label="item.name" :value="item.id"> | |||
</el-option> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="工厂名称" prop="factoryId"> | |||
<el-select v-model="dataForm.factoryId" placeholder="请选择工厂名称" multiple="true" clearable> | |||
<el-option v-for="item in factoryList" :key="item.id" :label="item.name" :value="item.id"> | |||
</el-option> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="8"> | |||
<el-form-item label="工厂名称" prop="factoryId"> | |||
<el-select v-model="dataForm.factoryId" placeholder="请选择工厂名称" multiple="true" clearable> | |||
<el-option v-for="item in factoryList" :key="item.id" :label="item.name" :value="item.id"> | |||
</el-option> | |||
</el-select> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
<el-divider></el-divider> | |||
<small-title style=" margin: 0;padding: 26px 32px 24px;margin-bottom: 22px;" :no-padding="false"> | |||
{{ '芯片' }} | |||
</small-title> | |||
<el-row :gutter="24" style="padding: 0 32px;"> | |||
<el-col :span="6"> | |||
<el-form-item label="芯片产量" prop="factoryId"> | |||
<el-input v-model="dataForm.factoryId" placeholder="请输入芯片产量"></el-input> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="芯片良率" prop="factoryId"> | |||
<el-input v-model="dataForm.factoryId" placeholder="请输入芯片良率"></el-input> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="芯片BOM" prop="factoryId"> | |||
<el-input v-model="dataForm.factoryId" placeholder="请输入芯片BOM"></el-input> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="芯片总功率" prop="factoryId"> | |||
<el-input v-model="dataForm.factoryId" placeholder="请输入芯片总功率"></el-input> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
<el-row :gutter="24" style="padding: 0 32px;"> | |||
<el-col :span="6"> | |||
<el-form-item label="FTO投入量" prop="factoryId"> | |||
<el-input v-model="dataForm.factoryId" placeholder="请输入FTO投入量"></el-input> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="CSS稼动率" prop="factoryId"> | |||
<el-input v-model="dataForm.factoryId" placeholder="请输入CSS稼动率"></el-input> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="芯片段OEE" prop="factoryId"> | |||
<el-input v-model="dataForm.factoryId" placeholder="请输入芯片段OEE"></el-input> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="芯片平均功率" prop="factoryId"> | |||
<el-input v-model="dataForm.factoryId" placeholder="请输入芯片平均功率"></el-input> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
<el-row :gutter="24" style="padding: 0 32px;"> | |||
<el-col :span="6"> | |||
<el-form-item label="芯片人均产量" prop="factoryId"> | |||
<el-input v-model="dataForm.factoryId" placeholder="请输入芯片人均产量"></el-input> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="芯片人均产量" prop="factoryId"> | |||
<el-input v-model="dataForm.factoryId" placeholder="请输入芯片人均产量"></el-input> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
<el-divider></el-divider> | |||
<small-title style=" margin: 0;padding: 26px 32px 24px;margin-bottom: 22px;" :no-padding="false"> | |||
{{ '标准组件' }} | |||
</small-title> | |||
<el-row :gutter="24" style="padding: 0 32px;"> | |||
<el-col :span="6"> | |||
<el-form-item label="封装BOM" prop="factoryId"> | |||
<el-input v-model="dataForm.factoryId" placeholder="请输入封装BOM"></el-input> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="封装线OEE" prop="factoryId"> | |||
<el-input v-model="dataForm.factoryId" placeholder="请输入封装线OEE"></el-input> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="标准组件良率" prop="factoryId"> | |||
<el-input v-model="dataForm.factoryId" placeholder="请输入标准组件良率"></el-input> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="标准组件良率" prop="factoryId"> | |||
<el-input v-model="dataForm.factoryId" placeholder="请输入标准组件良率"></el-input> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
<el-row :gutter="24" style="padding: 0 32px;"> | |||
<el-col :span="6"> | |||
<el-form-item label="标准组件总功率" prop="factoryId"> | |||
<el-input v-model="dataForm.factoryId" placeholder="请输入标准组件总功率"></el-input> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="标准组件总功率" prop="factoryId"> | |||
<el-input v-model="dataForm.factoryId" placeholder="请输入标准组件总功率"></el-input> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="标准组件人均产量" prop="factoryId"> | |||
<el-input v-model="dataForm.factoryId" placeholder="请输入标准组件人均产量"></el-input> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="标准组件平均功率" prop="factoryId"> | |||
<el-input v-model="dataForm.factoryId" placeholder="请输入标准组件平均功率"></el-input> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
<el-divider></el-divider> | |||
<small-title style=" margin: 0;padding: 26px 32px 24px;margin-bottom: 22px;" :no-padding="false"> | |||
{{ 'BIPV产品' }} | |||
</small-title> | |||
<el-row :gutter="24" style="padding: 0 32px;"> | |||
<el-col :span="6"> | |||
<el-form-item label="产品产量" prop="factoryId"> | |||
<el-input v-model="dataForm.factoryId" placeholder="请输入产品产量"></el-input> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="人均产量" prop="factoryId"> | |||
<el-input v-model="dataForm.factoryId" placeholder="请输入人均产量"></el-input> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="芯片使用量" prop="factoryId"> | |||
<el-input v-model="dataForm.factoryId" placeholder="请输入芯片使用量"></el-input> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="芯片利用率" prop="factoryId"> | |||
<el-input v-model="dataForm.factoryId" placeholder="请输入芯片利用率"></el-input> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
<el-row :gutter="24" style="padding: 0 32px;"> | |||
<el-col :span="6"> | |||
<el-form-item label="内部材料成本" prop="factoryId"> | |||
<el-input v-model="dataForm.factoryId" placeholder="请输入内部材料成本"></el-input> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="OEM及委外材料成本" prop="factoryId"> | |||
<el-input v-model="dataForm.factoryId" placeholder="请输入OEM及委外材料成本"></el-input> | |||
</el-form-item> | |||
</el-col> | |||
<el-col :span="6"> | |||
<el-form-item label="综合材料成本" prop="factoryId"> | |||
<el-input v-model="dataForm.factoryId" placeholder="请输入综合材料成本"></el-input> | |||
</el-form-item> | |||
</el-col> | |||
</el-row> | |||
</el-form> | |||
</div> | |||
<div class="footer"> | |||
<el-button @click="cancelForm">取 消</el-button> | |||
<el-button type="primary" @click="handleClose()">确 定</el-button> | |||
</div> | |||
</el-drawer> | |||
@@ -191,6 +239,7 @@ export default { | |||
name: '自动', | |||
} | |||
], | |||
factoryList:[], | |||
sectionList: [], | |||
visible: false, | |||
dataForm: { | |||
@@ -325,6 +374,22 @@ export default { | |||
}; | |||
</script> | |||
<style scoped> | |||
.footer { | |||
position: absolute; | |||
bottom: 1%; | |||
right: 2%; | |||
} | |||
.drawer-footer { | |||
width: 100%; | |||
margin-top: 50px; | |||
border-top: 1px solid #e8e8e8; | |||
padding: 10px 50px; | |||
text-align: left; | |||
background: #fff; | |||
} | |||
.el-divider--horizontal{ | |||
margin: 0; | |||
} | |||
.drawer >>> .el-drawer { | |||
border-radius: 8px 0 0 8px; | |||
} | |||
@@ -0,0 +1,365 @@ | |||
<!-- | |||
* @Author: zhp | |||
* @Date: 2023-11-06 15:15:30 | |||
* @LastEditTime: 2024-04-17 16:40:01 | |||
* @LastEditors: zhp | |||
* @Description: | |||
--> | |||
<template> | |||
<el-drawer class="drawer" :visible.sync="visible" size="50%"> | |||
<small-title slot="title" :no-padding="true"> | |||
{{ '碲化镉工厂生产数据详情' }} | |||
</small-title> | |||
<div class="detailBox"> | |||
<el-row :gutter="24"> | |||
<el-col :span="8"> | |||
<p class="title">工厂名称</p> | |||
<p class="text">{{ }}</p> | |||
</el-col> | |||
<el-col :span="8"> | |||
<p class="title">时间维度</p> | |||
<p class="text">{{ dataForm.code }}</p> | |||
</el-col> | |||
<el-col :span="8"> | |||
<p class="title">时间</p> | |||
<p class="text">{{ dataForm.productName }}</p> | |||
</el-col> | |||
</el-row> | |||
<el-divider></el-divider> | |||
<small-title style=" margin: 0;padding: 26px 32px 24px;margin-bottom: 22px;" :no-padding="false"> | |||
{{ '芯片' }} | |||
</small-title> | |||
<el-row :gutter="24"> | |||
<el-col :span="6"> | |||
<p class="title">芯片产量</p> | |||
<p class="text">{{ }}</p> | |||
</el-col> | |||
<el-col :span="6"> | |||
<p class="title">芯片良率</p> | |||
<p class="text">{{ dataForm.code }}</p> | |||
</el-col> | |||
<el-col :span="6"> | |||
<p class="title">芯片良率</p> | |||
<p class="text">{{ dataForm.productName }}</p> | |||
</el-col> | |||
<el-col :span="6"> | |||
<p class="title">芯片总功率</p> | |||
<p class="text">{{ dataForm.productName }}</p> | |||
</el-col> | |||
</el-row> | |||
<el-row :gutter="24"> | |||
<el-col :span="6"> | |||
<p class="title">FTO投入量</p> | |||
<p class="text">{{ }}</p> | |||
</el-col> | |||
<el-col :span="6"> | |||
<p class="title">CSS稼动率</p> | |||
<p class="text">{{ dataForm.code }}</p> | |||
</el-col> | |||
<el-col :span="6"> | |||
<p class="title">芯片段OEE</p> | |||
<p class="text">{{ dataForm.productName }}</p> | |||
</el-col> | |||
<el-col :span="6"> | |||
<p class="title">芯片平均功率</p> | |||
<p class="text">{{ dataForm.productName }}</p> | |||
</el-col> | |||
</el-row> | |||
<el-row :gutter="24"> | |||
<el-col :span="6"> | |||
<p class="title">芯片人均产量</p> | |||
<p class="text">{{ }}</p> | |||
</el-col> | |||
<el-col :span="6"> | |||
<p class="title">芯片产能利用率</p> | |||
<p class="text">{{ dataForm.code }}</p> | |||
</el-col> | |||
</el-row> | |||
<small-title style=" margin: 0;padding: 26px 32px 24px;margin-bottom: 22px;" :no-padding="false"> | |||
{{ '标准组件' }} | |||
</small-title> | |||
<el-row :gutter="24"> | |||
<el-col :span="6"> | |||
<p class="title">封装BOM</p> | |||
<p class="text">{{ }}</p> | |||
</el-col> | |||
<el-col :span="6"> | |||
<p class="title">封装线OEE</p> | |||
<p class="text">{{ dataForm.code }}</p> | |||
</el-col> | |||
<el-col :span="6"> | |||
<p class="title">标准组件良率</p> | |||
<p class="text">{{ dataForm.productName }}</p> | |||
</el-col> | |||
<el-col :span="6"> | |||
<p class="title">标准组件产量</p> | |||
<p class="text">{{ dataForm.productName }}</p> | |||
</el-col> | |||
</el-row> | |||
<el-row :gutter="24"> | |||
<el-col :span="6"> | |||
<p class="title">标准组件总功率</p> | |||
<p class="text">{{ }}</p> | |||
</el-col> | |||
<el-col :span="6"> | |||
<p class="title">封装产能利用率</p> | |||
<p class="text">{{ dataForm.code }}</p> | |||
</el-col> | |||
<el-col :span="6"> | |||
<p class="title">标准组件人均产量</p> | |||
<p class="text">{{ dataForm.productName }}</p> | |||
</el-col> | |||
<el-col :span="6"> | |||
<p class="title">标准组件人均产量</p> | |||
<p class="text">{{ dataForm.productName }}</p> | |||
</el-col> | |||
</el-row> | |||
<small-title style=" margin: 0;padding: 26px 32px 24px;margin-bottom: 22px;" :no-padding="false"> | |||
{{ 'BIPV产品' }} | |||
</small-title> | |||
<el-row :gutter="24"> | |||
<el-col :span="6"> | |||
<p class="title">产品产量</p> | |||
<p class="text">{{ }}</p> | |||
</el-col> | |||
<el-col :span="6"> | |||
<p class="title">人均产量</p> | |||
<p class="text">{{ dataForm.code }}</p> | |||
</el-col> | |||
<el-col :span="6"> | |||
<p class="title">芯片使用量</p> | |||
<p class="text">{{ dataForm.productName }}</p> | |||
</el-col> | |||
<el-col :span="6"> | |||
<p class="title">芯片使用量</p> | |||
<p class="text">{{ dataForm.productName }}</p> | |||
</el-col> | |||
</el-row> | |||
<el-row :gutter="24"> | |||
<el-col :span="6"> | |||
<p class="title">内部材料成本</p> | |||
<p class="text">{{ }}</p> | |||
</el-col> | |||
<el-col :span="6"> | |||
<p class="title">内部材料成本</p> | |||
<p class="text">{{ dataForm.code }}</p> | |||
</el-col> | |||
<el-col :span="6"> | |||
<p class="title">内部材料成本</p> | |||
<p class="text">{{ dataForm.productName }}</p> | |||
</el-col> | |||
</el-row> | |||
</div> | |||
</el-drawer> | |||
</template> | |||
<script> | |||
// import basicAdd from './basic-add'; | |||
// import { | |||
// createQualityScrapLog, updateQualityScrapLog, getQualityScrapLog, getWorkOrderList, | |||
// getTeamList, getDetList, getLineList | |||
// } from "@/api/base/qualityScrapLog"; | |||
// import { getList, } from "@/api/base/qualityScrapType"; | |||
import SmallTitle from './SmallTitle'; | |||
export default { | |||
components: { | |||
SmallTitle, | |||
}, | |||
// mixins: [basicAdd], | |||
data() { | |||
return { | |||
urlOptions: { | |||
isGetCode: false, | |||
// codeURL: getCode, | |||
// createURL: createQualityScrapLog, | |||
// updateURL: updateQualityScrapLog, | |||
// infoURL: getQualityScrapLog, | |||
}, | |||
lineList: [], | |||
typeList: [], | |||
workOrderList: [], | |||
detList: [], | |||
teamList: [], | |||
sourceList: [ | |||
{ | |||
id: 1, | |||
name: '手动', | |||
}, | |||
{ | |||
id: 2, | |||
name: '自动', | |||
} | |||
], | |||
sectionList: [], | |||
visible: false, | |||
dataForm: { | |||
id: undefined, | |||
logTime: undefined, | |||
source: 1, | |||
detId: undefined, | |||
workOrderId: null, | |||
teamId: undefined, | |||
num: undefined, | |||
lineId: undefined, | |||
description: undefined, | |||
// description: undefined, | |||
remark: undefined, | |||
}, | |||
// materialList: [], | |||
dataRule: { | |||
// materialId: [{ required: true, message: "", trigger: "blur" }], | |||
workOrderId: [{ required: true, message: "工单号不能为空", trigger: "change" }], | |||
num: [{ required: true, message: "数量不能为空", trigger: "blur" }], | |||
detId: [{ required: true, message: "报废原因不能为空", trigger: "change" }], | |||
logTime: [{ required: true, message: "报废时间不能为空", trigger: "change" }], | |||
} | |||
}; | |||
}, | |||
mounted() { | |||
this.getDict() | |||
console.log('我看看', this.dataForm) | |||
// this.getCurrentTime() | |||
}, | |||
methods: { | |||
init() { | |||
this.visible = true | |||
}, | |||
// getCurrentTime() { | |||
// // new Date().Format("yyyy-MM-dd HH:mm:ss") | |||
// this.dataForm.logTime = new Date() | |||
// // this.dataForm.logTime = year + "-" + month + "-" + day; | |||
// console.log(this.dataForm.logTime); | |||
// }, | |||
async getDict() { | |||
// // 物料列表 | |||
// const res = await getList() | |||
// this.typeList = res.data | |||
// getWorkOrderList().then((res) => { | |||
// console.log(res); | |||
// // console.log(response); | |||
// this.workOrderList = res.data.map((item) => { | |||
// return { | |||
// name: item.name, | |||
// id: item.id | |||
// } | |||
// }) | |||
// // console.log(this.formConfig[0].selectOptions); | |||
// // this.listQuery.total = response.data.total; | |||
// }) | |||
// getLineList().then((res) => { | |||
// console.log(res); | |||
// // console.log(response); | |||
// this.lineList = res.data.map((item) => { | |||
// return { | |||
// name: item.name, | |||
// id: item.id | |||
// } | |||
// }) | |||
// // console.log(this.formConfig[0].selectOptions); | |||
// // this.listQuery.total = response.data.total; | |||
// }) | |||
// getDetList().then((res) => { | |||
// console.log(res); | |||
// // console.log(response); | |||
// this.detList = res.data.map((item) => { | |||
// return { | |||
// name: item.content, | |||
// id: item.id | |||
// } | |||
// }) | |||
// // console.log(this.formConfig[0].selectOptions); | |||
// // this.listQuery.total = response.data.total; | |||
// }) | |||
// getTeamList().then((res) => { | |||
// console.log(res); | |||
// // console.log(response); | |||
// this.teamList = res.data.map((item) => { | |||
// return { | |||
// name: item.name, | |||
// id: item.id | |||
// } | |||
// }) | |||
// // console.log(this.formConfig[0].selectOptions); | |||
// // this.listQuery.total = response.data.total; | |||
// }) | |||
// }, | |||
// async getWorksectionById(lineId) { | |||
// if (lineId) { | |||
// const { code, data } = await this.$axios({ | |||
// url: '/base/core-workshop-section/listByParentId', | |||
// method: 'get', | |||
// params: { | |||
// id: lineId, | |||
// }, | |||
// }); | |||
// if (code == 0) { | |||
// console.log(data) | |||
// this.sectionList = data.map((item) => { | |||
// return { | |||
// name: item.name, | |||
// id: item.id, | |||
// }; | |||
// }); | |||
// } | |||
// } else { | |||
// this.$axios({ | |||
// url: '/base/core-workshop-section/listAll', | |||
// method: 'get', | |||
// // params: { | |||
// // id: lineId, | |||
// // }, | |||
// }).then((res) => { | |||
// // console.log(data) | |||
// this.sectionList = res.data.map((item) => { | |||
// return { | |||
// name: item.name, | |||
// id: item.id, | |||
// }; | |||
// }); | |||
// }) | |||
// } | |||
}, | |||
}, | |||
}; | |||
</script> | |||
<style scoped> | |||
.drawer >>> .el-drawer { | |||
border-radius: 8px 0 0 8px; | |||
} | |||
.drawer >>> .el-form-item__label { | |||
padding: 0; | |||
} | |||
.drawer >>> .el-drawer__header { | |||
margin: 0; | |||
padding: 32px 32px 24px; | |||
border-bottom: 1px solid #dcdfe6; | |||
margin-bottom: 30px; | |||
} | |||
.detailBox p { | |||
margin: 0; | |||
padding: 0 32px; | |||
} | |||
.detailBox .title { | |||
/* width: 56px; */ | |||
/* height: 14px; */ | |||
font-family: Source Han Sans CN, Source Han Sans CN; | |||
font-weight: 400; | |||
font-size: 14px; | |||
color: rgba(0, 0, 0, 0.85); | |||
line-height: 16px; | |||
text-align: left; | |||
font-style: normal; | |||
text-transform: none; | |||
} | |||
.detailBox .text { | |||
font-size: 14px; | |||
font-weight: 400; | |||
color: rgba(102,102,102,0.75); | |||
padding-bottom: 20px; | |||
} | |||
</style> |
@@ -1,7 +1,7 @@ | |||
<!-- | |||
* @Author: zhp | |||
* @Date: 2024-04-15 10:49:13 | |||
* @LastEditTime: 2024-04-17 16:12:20 | |||
* @LastEditTime: 2024-04-17 16:37:35 | |||
* @LastEditors: zhp | |||
* @Description: | |||
--> | |||
@@ -77,7 +77,8 @@ | |||
<method-btn v-if="tableBtn.length" slot="handleBtn" label="操作" :width="120" fixed="right" | |||
:method-list="tableBtn" @clickBtn="handleClick" /> | |||
</base-table> | |||
<add-or-update v-if="detailOrUpdateVisible" ref="detailOrUpdate" @refreshDataList="successSubmit" /> | |||
<detail-or-update v-if="detailOrUpdateVisible" ref="detailOrUpdate" @refreshDataList="successSubmit" /> | |||
<add-or-update v-if="addOrUpdateVisible" ref="addOrUpdate" @refreshDataList="successSubmit" /> | |||
<!-- <el-row :gutter="24"> --> | |||
<!-- <el-col :span="12" v-for="item in dataList" :key="item.id"> --> | |||
@@ -86,7 +87,7 @@ | |||
<!-- <el-col :span="12"> | |||
<line-chart :id=" 'second' " class="yearChart" ref="lineChart" style="height: 40vh;width: 100%"></line-chart> | |||
</el-col> --> | |||
</el-row> | |||
</div> | |||
<!-- <inputTable :date="date" :data="tableData" :time="[startTimeStamp, endTimeStamp]" :sum="all" | |||
@@ -107,12 +108,14 @@ import lineChart from './lineChart'; | |||
import moment from 'moment' | |||
import ButtonNav from '@/components/ButtonNav' | |||
import basicPage from '@/mixins/basic-page' | |||
import AddOrUpdate from './add-or-updata'; | |||
import detailOrUpdate from './detail-or-updata'; | |||
import addOrUpdate from './add-or-updata'; | |||
// import FileSaver from 'file-saver' | |||
// import * as XLSX from 'xlsx' | |||
export default { | |||
components: { lineChart, ButtonNav, AddOrUpdate }, | |||
components: { lineChart, ButtonNav, detailOrUpdate,addOrUpdate }, | |||
mixins: [basicPage], | |||
data() { | |||
return { | |||
@@ -125,18 +128,23 @@ export default { | |||
// reportType: 2, | |||
reportTime: [] | |||
}, | |||
detailOrUpdateVisible:false, | |||
detailOrUpdateVisible: false, | |||
addOrUpdateVisible:false, | |||
date1: undefined, | |||
date2: undefined, | |||
tableBtn: [ | |||
{ | |||
{ | |||
type: 'detail', | |||
btnName: '详情', | |||
}, | |||
// { | |||
// type: 'delete', | |||
// btnName: '删除', | |||
// }, | |||
{ | |||
type: 'edit', | |||
btnName: '修改', | |||
}, | |||
{ | |||
type: 'delete', | |||
btnName: '删除', | |||
}, | |||
].filter((v) => v), | |||
typeList: [ | |||
{ | |||
@@ -297,33 +305,58 @@ export default { | |||
// width: 180, | |||
// filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'), | |||
// }, | |||
{ | |||
prop: 'userName', | |||
label: '日期', | |||
}, | |||
{ | |||
prop: 'nickName', | |||
label: '工厂名称', | |||
}, | |||
{ | |||
prop: 'userName', | |||
label: '目标时间', | |||
}, | |||
{ | |||
prop: 'type', | |||
label: '玻璃类型', | |||
label: '提交时间', | |||
}, | |||
{ | |||
prop: 'inNum', | |||
label: '投入数量', | |||
label: '钼电极投入量(片)', | |||
}, | |||
{ | |||
prop: 'putNum', | |||
label: '产出数量', | |||
label: '芯片产量(片)', | |||
}, | |||
{ | |||
prop: 'goodNum', | |||
label: '良品数量', | |||
label: '芯片平均功率(W)', | |||
}, | |||
{ | |||
prop: 'goodYelid', | |||
label: '芯片良率(%)', | |||
}, | |||
{ | |||
prop: 'goodYelid', | |||
label: '芯片总功率(KW)', | |||
}, | |||
{ | |||
prop: 'goodYelid', | |||
label: 'PID6稼动率(%)', | |||
}, | |||
{ | |||
prop: 'goodYelid', | |||
label: '芯片段OEE(%)', | |||
}, | |||
{ | |||
prop: 'goodYelid', | |||
label: '芯片产能利用率(%)', | |||
}, | |||
{ | |||
prop: 'goodYelid', | |||
label: '芯片人均产量(片/人)', | |||
}, | |||
{ | |||
prop: 'goodYelid', | |||
label: '良品率%', | |||
label: '芯片BOM', | |||
}, | |||
], | |||
timeSelect:'month', | |||
@@ -366,6 +399,19 @@ export default { | |||
// this.getDataList() | |||
}, | |||
methods: { | |||
handleClick(val) { | |||
if (val.type === "edit") { | |||
this.addOrUpdateVisible = true; | |||
// this.addOrEditTitle = "编辑"; | |||
this.$nextTick(() => { | |||
this.$refs.addOrUpdate.init(val.data.id); | |||
}); | |||
} else if (val.type === "delete") { | |||
this.deleteHandle(val.data.id, val.data.name, val.data._pageIndex) | |||
} else { | |||
this.otherMethods(val) | |||
} | |||
}, | |||
otherMethods(val) { | |||
this.detailOrUpdateVisible = true; | |||
this.addOrEditTitle = "详情"; | |||
@@ -1,22 +1,24 @@ | |||
<!-- | |||
* @Author: zhp | |||
* @Date: 2024-04-15 10:49:13 | |||
* @LastEditTime: 2024-04-17 16:15:42 | |||
* @LastEditTime: 2024-04-29 16:10:36 | |||
* @LastEditors: zhp | |||
* @Description: | |||
--> | |||
<template> | |||
<div style="display: flex; flex-direction: column; min-height: calc(100vh - 96px - 31px)"> | |||
<div class="app-container" style="padding: 16px 24px 0;height: auto; flex-grow: 1;"> | |||
<div class="app-container" style="padding: 16px 24px 0;height: 400px; flex-grow: 1;"> | |||
<search-bar :formConfigs="mainFormConfig" ref="searchBarForm" @headBtnClick="buttonClick" /> | |||
<el-row :gutter="24"> | |||
<el-col :span="12" v-for="item in dataList" :key="item.id"> | |||
<line-chart :id="item.id" class="yearChart" ref="lineChart" style="height: 40vh;width: 100%"></line-chart> | |||
</el-col> | |||
<!-- <el-col :span="12"> | |||
<line-chart :id=" 'second' " class="yearChart" ref="lineChart" style="height: 40vh;width: 100%"></line-chart> | |||
</el-col> --> | |||
</el-row> | |||
<div class="content"> | |||
<!-- v-for 遍历父级div--> | |||
<div class="main" :span="12" v-for="(item,index) in chartData" :key="index"> | |||
<line-chart :data="item" ref="lineChart" style="height: 600px;width: 100%" /> | |||
</div> | |||
</div> | |||
<!-- <el-row :gutter="24"> | |||
<el-col> | |||
</el-col> | |||
</el-row> --> | |||
</div> | |||
<div class="app-container" style="margin-top: 18px;flex-grow: 1; height: auto; padding: 16px;"> | |||
<search-bar :formConfigs="formConfig" ref="searchBarForm" @headBtnClick="buttonClick" /> | |||
@@ -24,19 +26,12 @@ | |||
:table-data="tableData"> | |||
</base-table> | |||
</div> | |||
<!-- <inputTable :date="date" :data="tableData" :time="[startTimeStamp, endTimeStamp]" :sum="all" | |||
:type="listQuery.reportType" @refreshDataList="getDataList" /> --> | |||
<!-- <pagination | |||
:limit.sync="listQuery.pageSize" | |||
:page.sync="listQuery.pageNo" | |||
:total="listQuery.total" | |||
@pagination="getDataList" /> --> | |||
</div> | |||
</template> | |||
<script> | |||
// import { parseTime } from '../../core/mixins/code-filter'; | |||
// import { getGlassPage, exportGlasscExcel } from '@/api/report/glass'; | |||
import { getStockPage } from '@/api/wareHouse'; | |||
// import inputTable from './inputTable.vue'; | |||
import lineChart from './lineChart'; | |||
import moment from 'moment' | |||
@@ -46,35 +41,12 @@ export default { | |||
components: { lineChart }, | |||
data() { | |||
return { | |||
chartData:[], | |||
listQuery: { | |||
pageSize: 10, | |||
pageNo: 1, | |||
factoryId: null, | |||
total: 0, | |||
type: null, | |||
// reportType: 2, | |||
reportTime: [] | |||
factory:undefined, | |||
}, | |||
dataList: [ | |||
{ | |||
id:'first', | |||
}, | |||
{ | |||
id: 'second', | |||
}, | |||
{ | |||
id: 'third', | |||
}, | |||
{ | |||
id: 'fourth', | |||
}, | |||
{ | |||
id: 'fifth', | |||
}, | |||
{ | |||
id: 'sixth', | |||
}, | |||
], | |||
urlOptions: { | |||
// getDataListURL: getGlassPage, | |||
// exportURL: exportGlasscExcel | |||
@@ -84,8 +56,37 @@ export default { | |||
type: 'select', | |||
label: '工厂名称', | |||
placeholder: '请选择工厂名称', | |||
param: 'factoryId', | |||
selectOptions: [], | |||
param: 'factory', | |||
selectOptions: [ | |||
{ | |||
id: 0, | |||
name: '瑞昌中建材光电材料有限公司' | |||
}, | |||
{ | |||
id: 1, | |||
name: '邯郸中建材光电材料有限公司' | |||
}, | |||
{ | |||
id: 2, | |||
name: '中建材株洲光电材料有限公司' | |||
}, | |||
{ | |||
id: 3, | |||
name: '佳木斯中建材光电材料有限公司' | |||
}, | |||
{ | |||
id: 4, | |||
name: '成都中建材光电材料有限公司' | |||
}, | |||
{ | |||
id: 5, | |||
name: '凯盛光伏材料有限公司' | |||
}, | |||
{ | |||
id: 6, | |||
name: '蚌埠兴科玻璃有限公司' | |||
}, | |||
], | |||
clearable:true, | |||
}, | |||
// { | |||
@@ -155,7 +156,8 @@ export default { | |||
type:'button', | |||
btnName: '导出', | |||
name: 'export', | |||
color: 'warning', | |||
plain: true, | |||
color: 'primary', | |||
}, | |||
], | |||
formConfig: [ | |||
@@ -189,23 +191,25 @@ export default { | |||
// filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'), | |||
// }, | |||
{ | |||
prop: 'userName', | |||
prop: 'factory', | |||
label: '工厂名称', | |||
filter: (val) => ['瑞昌中建材光电材料有限公司', '邯郸中建材光电材料有限公司', '中建材株洲光电材料有限公司', '佳木斯中建材光电材料有限公司', '成都中建材光电材料有限公司', '凯盛光伏材料有限公司', '蚌埠兴科玻璃有限公司'][val] | |||
}, | |||
{ | |||
prop: 'nickName', | |||
prop: 'glassType', | |||
label: '玻璃类型', | |||
filter: (val) => ['玻璃芯片', '标准组件', 'BIPV'][val] | |||
}, | |||
{ | |||
prop: 'product', | |||
prop: 'productSpecification', | |||
label: '产品规格', | |||
}, | |||
{ | |||
prop: 'num', | |||
prop: 'stockNumber', | |||
label: '库存数量', | |||
}, | |||
{ | |||
prop: 'yeild', | |||
prop: 'specificationProportion', | |||
label: '规格占比', | |||
}, | |||
], | |||
@@ -216,69 +220,27 @@ export default { | |||
// reportTime: '', | |||
startTimeStamp: '', | |||
endTimeStamp: '', | |||
tableData: [ | |||
{ | |||
userName: 'userName', | |||
nickName: '用户名', | |||
datas:'111111' | |||
}, | |||
{ | |||
userName: 'userName', | |||
nickName: '用户名', | |||
datas: '111111' | |||
}, | |||
{ | |||
userName: 'userName', | |||
nickName: '用户名', | |||
datas: '111111' | |||
// subcomponent: row | |||
} | |||
], | |||
tableData: [], | |||
// proLineList: [], | |||
// all: {} | |||
}; | |||
}, | |||
mounted() { | |||
this.getDict() | |||
console.log(this.$refs.lineChart) | |||
// this.getCurrentYearFirst() | |||
// this.getDataList() | |||
this.getDataList() | |||
}, | |||
methods: { | |||
buttonClick() { | |||
}, | |||
// handleTime() { | |||
// this.$forceUpdate() | |||
// // this.$nextTick(() => [ | |||
// // ]) | |||
// }, | |||
// getCurrentYearFirst() { | |||
// let date = new Date(); | |||
// date.setDate(1); | |||
// date.setMonth(0); | |||
// this.reportTime = date; | |||
// this.startTimeStamp = this.timeFun(new Date(new Date().getFullYear(), 0, 1, 7, 0, 1).getTime()); //开始时间 | |||
// this.endTimeStamp = this.timeFun(new Date(new Date().getFullYear(), 11, 31, 7, 0, 0).getTime()); //结束时间 | |||
// this.listQuery.reportTime[0] = parseTime(new Date(new Date().getFullYear(), 0, 1, 7, 0, 1).getTime()) //+ ' 00:00:00' //new Date(this.startTimeStamp + ' 00:00:00').getTime() / 1000 | |||
// this.listQuery.reportTime[1] = parseTime(new Date(new Date().getFullYear(), 11, 31, 7, 0, 0).getTime()) //+ ' 23:59:59' //new Date(this.endTimeStamp + ' 23:59:59').getTime() / 100 | |||
// }, | |||
changeTime(val) { | |||
if (val) { | |||
// let timeStamp = val.getTime(); //标准时间转为时间戳,毫秒级别 | |||
// this.endTimeStamp = this.timeFun(new Date(val.getFullYear(), 11, 31, 7, 0, 0).getTime()); //开始时间 | |||
// this.startTimeStamp = this.timeFun(new Date(val.getFullYear(), 0, 1, 7, 0, 1).getTime()); //结束时间 | |||
// this.listQuery.reportTime[0] = parseTime(new Date(val.getFullYear(), 0, 1, 7, 0, 1).getTime()) //+ ' 00:00:00' //new Date(this.startTimeStamp + ' 00:00:00').getTime() / 1000 | |||
// this.listQuery.reportTime[1] = parseTime(new Date(val.getFullYear(), 11, 31, 7, 0, 0).getTime()) //+ ' 23:59:59' //new Date(this.endTimeStamp + ' 23:59:59').getTime() / 1000 | |||
} else { | |||
this.listQuery.reportTime = [] | |||
} | |||
}, | |||
async getDict() { | |||
this.$refs.lineChart.initChart() | |||
// 产线列表 | |||
// const res = await getCorePLList(); | |||
// this.proLineList = res.data; | |||
}, | |||
// 获取数据列表 | |||
multipliedByHundred(str) { | |||
@@ -304,6 +266,35 @@ export default { | |||
}, | |||
async getDataList() { | |||
getStockPage(this.listQuery).then((res) => { | |||
this.tableData = res.data.list | |||
let arr = res.data.list.map((ele) => { | |||
return { | |||
factory: ele.factory === 0 ? '瑞昌中建材光电材料有限公司' : ele.factory === 1 ? '邯郸中建材光电材料有限公司' : ele.factory === 2 ? '中建材株洲光电材料有限公司' : ele.factory === 3 ? '佳木斯中建材光电材料有限公司' : ele.factory === 4 ? '成都中建材光电材料有限公司' : ele.factory === 5 ? '凯盛光伏材料有限公司' : '蚌埠兴科玻璃有限公司', | |||
name: ele.glassType === 0 ? '玻璃芯片' : ele.glassType === 1 ? '标准组件' : 'BIPV', | |||
num: ele.stockNumber | |||
} | |||
}) | |||
this.checkSameData(arr) | |||
this, this.$nextTick(() => [ | |||
this.$refs.lineChart.initChart() | |||
]) | |||
}) | |||
}, | |||
checkSameData(data) { | |||
let dataInfo = {} | |||
data.forEach((item, index) => { | |||
let { factory } = item; | |||
if (!dataInfo[factory]) { | |||
dataInfo[factory] = { | |||
factory, | |||
child: [] | |||
} | |||
} | |||
dataInfo[factory].child.push(item) | |||
}) | |||
this.chartData = Object.values(dataInfo); // list 转换成功的数据 | |||
// console.log(this.chartData[0]) | |||
}, | |||
add0(m) { | |||
return m < 10 ? '0' + m : m | |||
@@ -311,21 +302,10 @@ export default { | |||
format(shijianchuo) { | |||
//shijianchuo是整数,否则要parseInt转换 | |||
var time = moment(new Date(shijianchuo)).format('YYYY-MM-DD HH:mm:ss') | |||
// console.log(time) | |||
// var y = time.getFullYear(); | |||
// var m = time.getMonth() + 1; | |||
// var d = time.getDate(); | |||
// var h = time.getHours(); | |||
// var mm = time.getMinutes(); | |||
// var s = time.getSeconds(); | |||
return time | |||
}, | |||
changeTime(val) { | |||
if (val) { | |||
// console.log(val) | |||
// console.log(val.setHours(7, 0, 0)) | |||
// console.log(val.setHours(7, 0, 0) + 24 * 60 * 60 * 1000) | |||
// let time = this.format(val.setHours(7, 0, 0)) | |||
this.endTimeStamp = this.format(val.setHours(7, 0, 0)) //+ ' 00:00:00' //new Date(this.startTimeStamp + ' 00:00:00').getTime() / 1000 | |||
this.startTimeStamp = this.format(val.setHours(7, 0, 1) - 24 * 60 * 60 * 1000) //+ ' 23:59:59' //new Date(this.endTimeStamp + ' 23:59:59').getTime() / 1000 | |||
// console.log(this.listQuery.reportTime); | |||
@@ -336,7 +316,6 @@ export default { | |||
this.listQuery.reportTime = [] | |||
} | |||
}, | |||
//时间戳转为yy-mm-dd hh:mm:ss | |||
timeFun(unixtimestamp) { | |||
var unixtimestamp = new Date(unixtimestamp); | |||
@@ -346,11 +325,13 @@ export default { | |||
return year + "-" + month.substring(month.length - 2, month.length) + "-" + date.substring(date.length - 2, date.length) | |||
}, | |||
buttonClick(val) { | |||
this.listQuery.reportTime = val.reportTime ? val.reportTime : undefined; | |||
// this.listQuery.reportTime = val.reportTime ? val.reportTime : undefined; | |||
console.log(val) | |||
switch (val.btnName) { | |||
case 'search': | |||
this.listQuery.pageNo = 1; | |||
this.listQuery.pageSize = 10; | |||
this.listQuery.pageNo = 1 | |||
this.listQuery.pageSize = 10 | |||
this.listQuery.factory = val.factory ? val.factory : undefined | |||
this.getDataList(); | |||
break; | |||
case 'export': | |||
@@ -421,4 +402,18 @@ export default { | |||
height: calc(100vh - 134px); | |||
overflow: auto; | |||
} | |||
.content { | |||
display: flex; | |||
/* grid-template-columns: 1fr 1fr 1fr; */ | |||
gap: 20px; | |||
flex-wrap: wrap; | |||
} | |||
.main { | |||
width: calc((100% - 46px)/2); | |||
/* border: 1px solid #D0D0D0; */ | |||
height: 400px; | |||
/* background-color: #FFFFFF; */ | |||
position: relative; | |||
} | |||
</style> |
@@ -2,7 +2,7 @@ | |||
* @Author: zwq | |||
* @Date: 2022-01-21 14:43:06 | |||
* @LastEditors: zhp | |||
* @LastEditTime: 2024-04-16 14:16:17 | |||
* @LastEditTime: 2024-04-29 16:00:13 | |||
* @Description: | |||
--> | |||
<template> | |||
@@ -25,6 +25,10 @@ export default { | |||
type: String, | |||
default: 'OverviewLine' | |||
}, | |||
data:{ | |||
type: Object, | |||
default: () => {} | |||
}, | |||
// className: { | |||
// type: String, | |||
// default: 'epChart' | |||
@@ -39,7 +43,7 @@ export default { | |||
}, | |||
height: { | |||
type: String, | |||
default: '35vh' | |||
default: '400px' | |||
}, | |||
legendPosition: { | |||
type: String, | |||
@@ -117,7 +121,7 @@ export default { | |||
initChart() { | |||
console.log(1111) | |||
let num = 0 | |||
this.chartData && this.chartData.length > 0 && this.chartData.map(i => { | |||
this.data.child && this.data.child.length > 0 && this.data.child.map(i => { | |||
num += i.num | |||
}) | |||
if ( | |||
@@ -154,7 +158,7 @@ export default { | |||
textStyle: { | |||
color: 'rgba(140, 140, 140, 1)' | |||
}, | |||
data: this.chartData && this.chartData.length > 0 && this.chartData.map((item, index) => ({ | |||
data: this.data.child && this.data.child.length > 0 && this.data.child.map((item, index) => ({ | |||
name: item.name, | |||
itemStyle: { | |||
color: this.colors[index % 4] | |||
@@ -162,7 +166,7 @@ export default { | |||
})) | |||
}, | |||
series: [{ | |||
name: 'ISRA缺陷检测', | |||
name: this.data.factory, | |||
type: 'pie', | |||
// position:outerHeight, | |||
center: ['50%', '40%'], | |||
@@ -183,7 +187,7 @@ export default { | |||
}, | |||
formatter: (params) => { | |||
//调用自定义显示格式 | |||
return this.getEqualNewlineString(params.value + " | " + params.percent.toFixed(0) + "%" + "\n" + params.name, 10); | |||
return this.getEqualNewlineString(params.value + " | " + params.percent.toFixed(0) + "%" + "\n\n" + params.name, 10); | |||
}, | |||
textStyle: { // 提示文字的样式 | |||
// color: 'rgba(0, 0, 0, 0.65)', | |||
@@ -196,7 +200,7 @@ export default { | |||
length: 25, | |||
length2: 100, | |||
}, | |||
data: this.chartData && this.chartData.length > 0 && this.chartData.map((item, index) => ({ | |||
data: this.data.child && this.data.child.length > 0 && this.data.child.map((item, index) => ({ | |||
name: item.name, | |||
value: item.num, | |||
label: { | |||