根据代码生成帮助说明模板系统界面说明文档规范
一、目的:
软件系统界面帮助说明是用户与系统之间重要的沟通桥梁,帮助用户快速了解该菜单的功能以及数据来源、数据逻辑,后续可自行操作或者核查信息。
二、编制和适用范围:
e-ONE一体化系统全部界面菜单
三、定义和分类:
由于系统界面菜单主要分操作及查询两大类,界面帮助说明相应进行标准化。
四、职责和更新要求:
界面帮助说明由开发人员按要求整理,发布流程时上传Word文档,正式库发布24小时更新到正式库界面帮助说明中。
五 操作类界面文档内容:
1、菜单总体功能描述。
Ex: 按项目、材质进行各工序周期统计,求平均数。
2、按钮功能。
每个按钮功能及对应的角色
Ex:预制地设置按钮:选中小票设置小票的预制地,根据设置的预制地进行排产派工,该按钮对应的角色是管-内场角色
Ex:导入按钮:导入该菜单中的材质和厂家日期信息,同时日期格式必须是日日-月月-年年)
有的功能当前只是适用某个基地或者项目或者特殊业务场景等,都要进行说明。
3、字段说明。(除常规字段例如:项目、基地、车间、班组、姓名、工号、图纸号、图纸名、备注等,其他字段都需说明)
说明每个字段含义、数据来源、相关计算逻辑(如果数据有定时任务,请标明定时任务的名称、时间点以及是否有手动刷新的按钮)
Ex:小票号:小票的标识,项目号+小票号+版本确定唯一一条数据。
小票版本:从0版开始,图纸修改会升级版本,版本连续增长,由技术做升版操作
如定时任务同步,标明执行时间与任务名称。
Ex:数据来源于技术和导入操作,每天凌晨一点,技术推送数据。
4、与此菜单关联的基础配置信息。
Ex: MES基地配置(配置后的项目及基地才能进行MES作业下达)
5、更新日志与版本说明
更新日志:统一放到系统更新日志里,在帮助页面放更新日志编号,附加链接即可
版本说明:针对有特殊浏览器版本需求的菜单,提供详细的版本说明和兼容性信息,该菜单需要使用谷歌100以上版本等
Ex:20240329:新增作业区字段(需求提出人:王跳跳;需求负责人: 王建国;开发人员: 王富贵);。
Ex:20240320:新增属地展示。(需求提出人:王跳跳;需求负责人: 王建国;开发人员: 王富贵)
6、负责人及开发人员。
遇到问题方便查找相关人。
Ex: (需求负责人: 王翠花 开发人员: 王富贵)
如果当前需求或者开发人员和前期不一致,请一起写上
六、报表看板查询类文档内容:
1、报表或者看板总体功能介绍。
Ex: 按项目、材质进行各工序周期统计,求平均数。数据为实时查询。
2、报表适用的场景和范围以及适用角色。
该看板或者报表给哪个场景或者角色使用,方便后期权限维护。
Ex:项目计划员角色需要查询该报表或者该报表当前只是烟台基地开放使用等
3、界面布局:
如果该报表或者看板比较复杂,需要介绍报表界面布局包括上方工具栏、左面板、报表内容区域、分页等信息
4、字段说明。(除常规字段例如:项目、基地、车间、班组、姓名、工号、图纸号、图纸名、备注等,其他字段都需说明)
说明每个字段含义、数据来源、相关计算逻辑(如果数据有定时任务,请标明定时任务的名称、时间点以及手动刷新的按钮)
Ex:小票号:小票的标识,项目号+小票号+版本确定唯一一条数据。
小票版本:从0版开始,图纸修改会升级版本,版本连续增长,由技术做升版操作
如定时任务同步,标明执行时间与任务名称。
Ex:数据来源于技术和导入操作,每天凌晨一点,技术推送数据。
5、更新日志与版本说明
更新日志:统一放到系统更新日志里,在帮助页面放更新日志编号,附加链接即可
版本说明:针对有特殊浏览器版本需求的菜单,提供详细的版本说明和兼容性信息,该菜单需要使用谷歌100以上版本等。
Ex:20240329:新增作业区字段(需求提出人:王跳跳;需求负责人: 王建国;开发人员: 王富贵);。
Ex:20240320:新增属地展示。(需求提出人:王跳跳;需求负责人: 王建国;开发人员: 王富贵)
6、负责人及开发人员。
遇到问题方便查找相关人。
Ex: (需求负责人: 王翠花 开发人员: 王富贵)
帮助说明更新时间:2025-01-01
标准模版:
一、菜单总体功能描述
[菜单总体功能描述内容]
二、按钮功能
三、字段说明
四、关联的基础配置信息
关联基础配置信息列表项,每项一个说明,如:
五、更新日志与版本说明
版本说明
[版本说明内容,如浏览器兼容性等]
更新日志
[更新日志行数据,每行一个标签包裹,如: ]
六、负责人及开发人员
●需求负责人:[具体需求负责人姓名]
●开发人员:[具体开发人员姓名]
(若当前需求/开发人员与前期不一致,补充说明:前期需求负责人为[前期姓名]、开发人员为[前期姓名],当前迭代由[现姓名]负责)
代码<template>
<c-search-panel :columns="searchColumns" @search="onSearch"> </c-search-panel>
<section class="stat-container">
<div style="display: flex; justify-content: space-between; align-items: center;">
<!-- <div style="display: flex; justify-content: space-between; align-items: center;">-->
<div style="flex: 1; text-align: center;">
<span class="glot-title" style="white-space: nowrap; display: inline-block; width: 100%;">{{ title }}</span>
</div>
<div>
<a-button type="primary" @click="exportToExcel">导出数据</a-button>
</div>
</div>
<div ref="chartContainer" class="mcc-chart"></div>
</section>
</template>
<script setup>
import * as server from "@/packages/hx/api/pdcs/projectManagement/mcMccPlan"
import { ref } from "vue"
import { DualAxes } from '@antv/g2plot';
import ExcelJS from 'exceljs';
import dayjs from "dayjs";
import {useI18n} from "vue-i18n";
const { t } = useI18n()
const title = ref('')
const conditionData = ref({})
const chartContainer = ref(null);
let dualAxesPlot = null;
const searchColumns = ref([
{
title: t("pdcs.projectManagement.project"),
dataIndex: "projectId",
width: 80,
decorator: { rules: [{ required: true, message: t("plan.remind.required") }] },
options: {
parameter: { isLimitByUser: 1 },
fieldNames: { label: "projId", value: "projNo" }
},
condition: true,
type: "project"
},
{
title: "截至日期",
dataIndex: "endDate",
width: 90,
type: "date",
condition: true,
decorator: { initialValue: dayjs().format("YYYY-MM-DD") }
}
])
// onMounted(() => {
// onSearch()
// })
//搜索
const onSearch = (values) => {
console.log('values',values)
conditionData.value = values
getCount()
}
// 模拟数据(按周统计)
// const generateData = () => {
// return [
// { week: 'W1', target: 15, actual: 10, planRemain: 100, actualRemain: 100, catchupRemain: 100 },
// { week: 'W2', target: 20, actual: 18, planRemain: 85, actualRemain: 90, catchupRemain: 95 },
// { week: 'W3', target: 25, actual: 20, planRemain: 65, actualRemain: 75, catchupRemain: 85 },
// { week: 'W4', target: 30, actual: 25, planRemain: 40, actualRemain: 55, catchupRemain: 70 },
// { week: 'W5', target: 35, actual: 30, planRemain: 10, actualRemain: 30, catchupRemain: 50 },
// { week: 'W6', target: 40, actual: 35, planRemain: 0, actualRemain: 0, catchupRemain: 25 },
// { week: 'W7', target: 45, actual: 40, planRemain: 0, actualRemain: 0, catchupRemain: 0 }
// ]
// };
// 转换数据用于柱状图
const transformColumnData = (data) => {
const result = [];
if (!Array.isArray(data)) return result;
data.forEach(item => {
// 保持原来的结构,但增加一个小的偏移量来分离柱子
if (item && Object.prototype.hasOwnProperty.call(item, 'week') && Object.prototype.hasOwnProperty.call(item, 'target')) {
result.push({ week: item.week, type: 'target', value: Number(item.target) || 0 });
}
if (item && Object.prototype.hasOwnProperty.call(item, 'week') && Object.prototype.hasOwnProperty.call(item, 'actual')) {
result.push({ week: item.week, type: 'actual', value: Number(item.actual) || 0 });
}
});
return result;
};
// 转换数据用于折线图
const transformLineData = (data) => {
const result = [];
if (!Array.isArray(data)) return result;
data.forEach(item => {
if (item && Object.prototype.hasOwnProperty.call(item, 'week') && Object.prototype.hasOwnProperty.call(item, 'planRemain')) {
result.push({ week: item.week, type: 'planRemain', value: Number(item.planRemain) || 0 });
}
if (item && Object.prototype.hasOwnProperty.call(item, 'week') && Object.prototype.hasOwnProperty.call(item, 'actualRemain')) {
result.push({ week: item.week, type: 'actualRemain', value: Number(item.actualRemain) || 0 });
}
if (item && Object.prototype.hasOwnProperty.call(item, 'week') && Object.prototype.hasOwnProperty.call(item, 'catchupRemain')) {
result.push({ week: item.week, type: 'catchupRemain', value: Number(item.catchupRemain) || 0 });
}
});
return result;
};
const getCount = async () => {
// console.log('conditionData',conditionData)
const res = await server.getRundownList(conditionData.value)
// 确保返回的数据是有效的数组格式
if (!res || !res.data || !Array.isArray(res.data)) {
console.error('Invalid data format received from server');
return;
}
title.value = res.data[0]?.projectNo ? res.data[0].projectNo + 'MCC Rundown Curve' : 'MCC Rundown Curve'
// const columnData = res.data || []
// const container = document.getElementById("cont.ainer-count")
// container.innerHTML = ""
// const columnPlot = new Column(container, {
// data: columnData,
// xField: "month",
// yField: "count",
// seriesField: "resultStr",
// label: {
// position: "top",
// layout: [
// // 数据标签防遮挡
// { type: "interval-hide-overlap" }
// ]
// }
// })
//
// columnPlot.render()
const rawData = Array.isArray(res.data) ? res.data : [];
const columnData = transformColumnData(rawData);
const lineData = transformLineData(rawData);
// 计算所有数据中最大的5个数值,然后取其中的最大值作为Y轴最大刻度
const allValues = [...columnData, ...lineData].map(item => item.value).filter(val => typeof val === 'number' && !isNaN(val));
const sortedValues = allValues.sort((a, b) => b - a);
const top5Values = sortedValues.slice(0, 5);
const maxValue = top5Values.length > 0 ? Math.max(...top5Values) : 100;
if (dualAxesPlot) dualAxesPlot.destroy();
dualAxesPlot = new DualAxes(chartContainer.value, {
// title: {
// text: res.data[0].projectNo+'MCC Rundown Curve', // 替换为实际标题文本
// style: {
// fontSize: 16, // 标题字体大小
// fontWeight: 'bold' // 标题字体粗细
// }
// },
// padding: [40, 20, 20, 20],
data: [columnData, lineData],
xField: 'week',
yField: ['value', 'value'],
geometryOptions: [
// 柱状图配置
{
geometry: 'column',
isStack: false,
seriesField: 'type',
isGroup: true,
columnWidthRatio: 0.6,
marginRatio: 0.1,
color: ({ type }) => type === 'target' ? '#C09B00' : '#0e4470',
label: {
position: 'top',
formatter: (datum) => datum.value
}
},
// 曲线图配置
{
geometry: 'line',
seriesField: 'type',
smooth: true,
color: ({ type }) => {
if (type === 'planRemain') return '#2ca8ff';
if (type === 'actualRemain') return '#77e84a';
return '#b45378'; // catchupRemain
},
lineStyle: ({ type }) => {
return type === 'catchupRemain'
? { lineDash: [4, 4], lineWidth: 2 }
: { lineWidth: 2 };
},
point: {
size: 3,
shape: 'circle'
},
label: {
position: 'top',
formatter: (datum) => datum.value
}
}
],
legend: {
position: 'bottom',
itemName: {
formatter: (text) => {
const mapping = {
'target': 'Period Plan Count',
'actual': 'Period Actual Count',
'planRemain': 'Plan Remaining Count',
'actualRemain': 'Actual Remaining Count',
'catchupRemain': 'Pursue Remaining Count'
};
return mapping[text];
}
},
flipPage: false,
maxWidth: 1200,
marker: { spacing: 8 },
itemValue: { formatter: () => {return ''} },
layout: 'horizontal',
itemWidth: null,
itemSpacing: 80
},
tooltip: {
shared: true,
showCrosshairs: true,
crosshairs: { type: 'xy' },
formatter: (datum) => {
const nameMap = {
target: 'Period Plan Count',
actual: 'Period Actual Count',
planRemain: 'Plan Remaining Count',
actualRemain: 'Actual Remaining Count',
catchupRemain: 'Pursue Remaining Count'
};
return { name: nameMap[datum.type], value: datum.value };
}
},
interactions: [],
xAxis: {
// 使用默认配置
},
yAxis: [
{
name: '完成数量',
grid: null,
nice: true,
tickCount: 10,
max: maxValue,
min: 0
},
{
name: '剩余数量',
grid: null,
nice: true,
tickCount: 10,
max: maxValue,
min: 0
}
]
});
dualAxesPlot.render();
}
// 导出图表为图片
const exportChartToImage = () => {
return new Promise((resolve) => {
try {
// 创建一个临时的canvas用于绘制包含标题的完整图表
const tempCanvas = document.createElement('canvas');
const tempCtx = tempCanvas.getContext('2d');
// 获取图表容器中的 canvas 元素
const chartCanvas = chartContainer.value.querySelector('canvas');
if (!chartCanvas) {
console.error('找不到图表 canvas 元素');
resolve(null);
return;
}
// 设置临时canvas的尺寸,留出空间给标题
const titleHeight = 60;
tempCanvas.width = chartCanvas.width;
tempCanvas.height = chartCanvas.height + titleHeight;
// 绘制标题背景
tempCtx.fillStyle = '#ffffff';
tempCtx.fillRect(0, 0, tempCanvas.width, titleHeight);
// 绘制标题
tempCtx.font = 'bold 24px Arial';
tempCtx.fillStyle = '#000000';
tempCtx.textAlign = 'center';
tempCtx.fillText(title.value, tempCanvas.width / 2, titleHeight / 2 + 8);
// 绘制原图表
tempCtx.drawImage(chartCanvas, 0, titleHeight);
resolve(tempCanvas.toDataURL('image/png'));
} catch (error) {
console.error('导出图表图片时出错:', error);
resolve(null);
}
});
};
// 添加导出到Excel的功能(包含数据和图表)
const exportToExcel = async () => {
// 创建工作簿
const workbook = new ExcelJS.Workbook();
// 如果能获取到图表,则添加图表到Excel
try {
const chartImageData = await exportChartToImage();
if (chartImageData) {
// 将图片数据转换为buffer
const imageBase64 = chartImageData.split(',')[1];
// 添加图像到工作簿
const imageId = workbook.addImage({
base64: imageBase64,
extension: 'png',
});
// 添加一个新的工作表用于存放图表
const chartWorksheet = workbook.addWorksheet('MCC Rundown Chart');
// 在图表工作表中插入图像
chartWorksheet.addImage(imageId, {
tl: { col: 1, row: 1 },
br: { col: 9, row: 25 }
});
// 设置图表工作表的列宽
chartWorksheet.columns = Array(10).fill({ width: 15 });
}
} catch (error) {
console.error('添加图表到Excel时出错:', error);
}
// 生成 Excel 文件
const buffer = await workbook.xlsx.writeBuffer();
// 创建下载链接
const blob = new Blob([buffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = 'MCC_Rundown_Report.xlsx';
link.click();
};
</script>
<style scoped lang="less">
.mcc-chart {
width: 100%;
height: 750px;
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
padding: 16px;
}
.glot-title{
font-size: 32px;
align-self: center;
text-align: center;
}
</style>
最新发布