面试综合指南
中际旭创 · 制造业数据可视化工程师 — 从12篇教程到拿到Offer的最后一步。
涵盖岗位分析、技术全景、项目话术、高频考题、手写代码、薪资谈判和面试前检查清单。
01 · 岗位职责拆解
中际旭创是一家专注于光模块研发与制造的高科技企业(上市公司,代码 300308)。这个"制造业数据可视化工程师"岗位的核心是:用全栈技术搭建工厂的数据可视化平台。
基于 ECharts / Vue 开发车间大屏看板,实时展示产量、良率、设备状态等关键指标。
ECharts Vue 3 HTML/CSS/JS Vite WebSocket
01-ECharts图表教程 · 02-Vue3核心教程 · 10-HTML-CSS-JS前端基础 · 11-Vite构建工具
使用 Java / Spring Boot 开发 REST API,从 SQL Server 数据库查询数据,提供给前端展示。
Java Spring Boot RESTful API SQL Server
03-Java后端开发 · 07-Java数据处理与报表 · 12-数据库设计与SQL优化
开发 ETL 流程,将 MES/ERP 等系统的数据抽取、清洗、转换后加载到数据仓库,生成自动化报表。
ETL Java SQL Redis
09-ETL数据工程 · 07-Java数据处理与报表 · 12-数据库设计与SQL优化 · 06-Redis缓存数据库
使用 Docker 容器化部署前端/后端服务,配合 Git 进行版本管理,在 Linux 服务器上运行和维护。
Docker Git Linux Vite
04-Docker容器化部署 · 05-Git版本控制 · 08-Linux基础命令 · 11-Vite构建工具
02 · 任职要求映射
| 编号 | 岗位要求 | 核心技能点 | 对应教程 |
|---|---|---|---|
| R1 | 本科及以上学历,计算机/软件工程/信息管理相关专业 | 学历背景 — 非技术要求,但需准备自我介绍中的教育经历 | - |
| R2 | 熟练掌握 Vue/React 等前端框架,有数据可视化开发经验 | Vue 3 · ECharts · 组件化开发 · 响应式原理 · 大屏适配 | 02-Vue3 01-ECharts 10-HTML/CSS/JS |
| R3 | 熟悉 Node.js / Python 后端开发,能独立开发 RESTful API | Express/Koa · FastAPI/Flask · RESTful 设计 · 中间件 · WebSocket | 03-Node.js 07-Python |
| R4 | 熟悉 SQL Server / MySQL 等关系型数据库,了解 Redis | SQL 查询优化 · 窗口函数 · 索引设计 · Redis 缓存策略 | 12-SQL 06-Redis |
| R5 | 了解 Docker / Linux / Git 等DevOps工具,有项目部署经验 | Dockerfile · docker-compose · Linux常用命令 · Git工作流 | 04-Docker 05-Git 08-Linux |
这个岗位不是招"纯前端"或"纯后端",而是全栈 + 制造业领域知识。面试官最看重的是你能不能把前后端串起来,从数据库取数据 → 后端处理 → 前端展示,形成完整的数据流。
03 · 技能→教程对照表
以下是每个岗位要求所对应的具体技能点,以及你已经学完的教程编号。你已经完成了全部12篇教程,基础扎实!
| 岗位要求 | 具体技能 | 熟练度自评 | 教程来源 |
|---|---|---|---|
| 前端可视化 | |||
| R2 前端框架 | Vue 3 组合式API、生命周期、组件通信 | 02-Vue3 | |
| R2 数据可视化 | ECharts 柱/折/饼/仪表盘/地图配置 | 01-ECharts | |
| R2 页面布局 | Flexbox、Grid、响应式设计、CSS变量 | 10-HTML/CSS/JS | |
| R2 构建工具 | Vite配置、打包优化、代理配置 | 11-Vite | |
| 后端服务 | |||
| R3 Node.js | Express路由、中间件、错误处理 | 03-Node.js | |
| R3 Python | 数据处理、Flask/FastAPI、pandas | 07-Python | |
| 数据库 | |||
| R4 SQL | 窗口函数、索引优化、查询计划分析 | 12-SQL | |
| R4 Redis | 数据类型、缓存策略、过期机制 | 06-Redis | |
| DevOps | |||
| R5 Docker | Dockerfile、docker-compose、镜像管理 | 04-Docker | |
| R5 Git | 分支策略、冲突解决、rebase/merge | 05-Git | |
| R5 Linux | 常用命令、日志排查、进程管理 | 08-Linux | |
| 数据工程 | |||
| R3 ETL | 数据抽取、清洗、转换、加载流程 | 09-ETL | |
04 · 技术栈全景图
以下是你需要掌握的完整技术栈,以及它们之间的调用关系。面试时如果能画出这个图,面试官会认为你对全栈架构有清晰认知。
SQL Server · CSV · API
定时任务 · 数据质量校验
Redis (缓存/实时)
RESTful API · WebSocket · 鉴权
ECharts 大屏 · Element UI
Git 版本管理 · Linux 部署
05 · 数据流架构(面试必背)
面试中极大概率会问:"请描述你设计的系统架构"或"数据从哪里来,怎么展示到屏幕上"。以下是标准答案模板:
/* 面试回答模板 — 大约2分钟说完 */
"我们的系统分为四个层次:"
1. 数据源层
"MES系统产生生产数据,存储在SQL Server数据库中。"
"有些设备数据通过OPC UA协议实时采集。"
2. ETL/数据处理层
"用Python编写ETL脚本,定时从MES库抽取数据,"
"经过清洗、聚合后写入数据仓库。"
"关键指标缓存到Redis,保证查询速度。"
3. 后端服务层
"Node.js + Express提供RESTful API,前端调用获取图表数据。"
"实时数据用WebSocket推送,确保大屏秒级刷新。"
"复杂的数据计算逻辑放在Python微服务中处理。"
4. 前端展示层
"Vue 3 + Vite构建SPA应用,ECharts渲染各类图表。"
"组件化开发,一个图表一个组件,便于复用和维护。"
"部署在Docker容器中,Nginx做反向代理。"
提到以下关键词会让面试官眼前一亮:"数据血缘"、"增量同步"、"WebSocket推送"、"Redis缓存穿透防护"、"Docker Compose一键部署"、"Git Flow分支策略"。
06 · STAR法则:如何描述项目经验
面试中描述项目时,永远使用 STAR 法则:
业务需求是什么?
团队规模?
要解决什么问题?
目标是什么?
具体怎么实现的?
遇到什么困难?
用户反馈?
性能提升?
错误:"我用 Vue 做了一个看板系统。" — 太笼统,没有体现你的价值。
正确:"车间的生产数据之前靠人工每小时抄表,我开发了实时可视化看板,用 ECharts 展示 6 个核心 KPI,数据通过 WebSocket 秒级刷新,将异常响应时间从 30 分钟缩短到 2 分钟。"
07 · 项目范例一:生产可视化看板项目
② ECharts 配置仪表盘、折线图、柱状图,使用 dataZoom 实现时间范围筛选
③ Node.js + Express 开发后端 API,从 SQL Server 查询 MES 数据,WebSocket 实时推送异常告警
④ Redis 缓存最近 1 小时的聚合数据,API 响应时间从 800ms 降到 50ms
⑤ 使用 Docker + docker-compose 一键部署前后端 + Redis
08 · 项目范例二:报表自动化项目
② 数据经过清洗(去重、空值处理)→ 转换(聚合计算)→ 加载(写入数据仓库)
③ SQL 窗口函数实现同比环比计算、产线排名、累计产量等复杂统计
④ Node.js 提供 RESTful API,前端 Vue 3 + ECharts 实现在线预览和交互式筛选
⑤ 使用 Redis 缓存报表数据,避免重复查询数据库
09 · 项目范例三:ETL数据平台项目
② Python 实现核心 ETL 逻辑,使用 SQL Server 作为数据仓库,Redis 记录增量同步位点
③ 开发数据质量监控模块:空值率、重复率、异常值检测,问题数据写入告警表
④ Docker 容器化部署 ETL 服务,Linux crontab 管理定时调度
⑤ Git 管理代码版本,使用 feature 分支开发、PR review 合并
10 · 高频面试题 — 前端 (10题)
11 · 高频面试题 — 后端 (8题)
12 · 高频面试题 — 数据库 (8题)
13 · 高频面试题 — DevOps (6题)
14 · 高频面试题 — 项目/场景 (6题)
15 · 手写代码 — ECharts 仪表盘配置
题目:请在 HTML 页面中实现一个"良率仪表盘",范围 0-100%,分为三个颜色区间(红 0-60、黄 60-85、绿 85-100),当前值 92.5%。
<div id="gauge" style="width:400px;height:400px"></div>
<script>
var chart = echarts.init(document.getElementById('gauge'));
chart.setOption({
series: [{
type: 'gauge',
min: 0,
max: 100,
splitNumber: 10,
axisLine: {
lineStyle: {
width: 20,
color: [
[0.6, '#ff6b6b'], // 0-60 红色
[0.85, '#ffd93d'], // 60-85 黄色
[1, '#6bcb77'] // 85-100 绿色
]
}
},
pointer: { width: 5 },
axisTick: { distance: -20, length: 6 },
splitLine: { distance: -20, length: 14 },
axisLabel: { distance: -25, fontSize: 11 },
detail: {
valueAnimation: true,
formatter: '{value}%',
fontSize: 24,
offsetCenter: [0, '70%']
},
title: {
offsetCenter: [0, '90%'],
fontSize: 14
},
data: [{ value: 92.5, name: '良率' }]
}]
});
// 窗口自适应
window.addEventListener('resize', () => chart.resize());
</script>
① 提到 window.addEventListener('resize', chart.resize()) 做响应式 ② 提到 chart.dispose() 在组件销毁时清理 ③ 提到 setOption 的 notMerge 参数控制是否合并配置 ④ 提到可以用 setInterval 定时更新 data 实现实时刷新。
16 · 手写代码 — Vue 3 组件
题目:写一个 YieldGauge.vue 组件,接收 lineName 和 yieldValue 两个 props,点击按钮时 emit 一个 refresh 事件。
<template>
<div class="gauge-card">
<h3>{{ lineName }} 产线良率</h3>
<div ref="chartRef" style="width:100%;height:300px"></div>
<button @click="handleRefresh">刷新数据</button>
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted, watch } from 'vue'
import * as echarts from 'echarts'
// Props 定义
const props = defineProps({
lineName: { type: String, required: true },
yieldValue: { type: Number, required: true }
})
// Emit 定义
const emit = defineEmits(['refresh'])
const chartRef = ref(null)
let chartInstance = null
function renderChart() {
if (!chartInstance) return
chartInstance.setOption({
series: [{
type: 'gauge',
detail: { formatter: '{value}%' },
data: [{ value: props.yieldValue }]
}]
})
}
function handleRefresh() {
emit('refresh', props.lineName)
}
onMounted(() => {
chartInstance = echarts.init(chartRef.value)
renderChart()
})
watch(() => props.yieldValue, () => renderChart())
onUnmounted(() => {
chartInstance?.dispose()
})
</script>
17 · 手写代码 — Express API 端点
题目:用 Express 写一个 API 端点,查询指定产线的生产数据,支持日期范围筛选,返回 JSON 格式。
const express = require('express')
const sql = require('mssql')
const app = express()
// 数据库配置
const dbConfig = {
server: '192.168.1.100',
database: 'MES_DB',
user: 'sa',
password: '******',
options: { encrypt: false }
}
// GET /api/production/:lineId — 查询产线生产数据
app.get('/api/production/:lineId', async (req, res) => {
try {
const { lineId } = req.params
const { startDate, endDate } = req.query
// 参数校验
if (!startDate || !endDate) {
return res.status(400).json({
code: 400,
message: '缺少 startDate 或 endDate 参数'
})
}
// 连接数据库(参数化查询防 SQL 注入)
const pool = await sql.connect(dbConfig)
const result = await pool.request()
.input('lineId', sql.Int, parseInt(lineId))
.input('start', sql.DateTime, new Date(startDate))
.input('end', sql.DateTime, new Date(endDate))
.query(`
SELECT ProductionDate, Output, Yield, DefectCount
FROM ProductionRecords
WHERE LineId = @lineId
AND ProductionDate BETWEEN @start AND @end
ORDER BY ProductionDate
`)
res.json({
code: 200,
data: result.recordset,
message: 'ok'
})
} catch (err) {
console.error('查询失败:', err)
res.status(500).json({
code: 500,
message: '服务器内部错误'
})
}
})
app.listen(3000, () => console.log('Server running on :3000'))
18 · 手写代码 — SQL 窗口函数
题目:查询各产线每月的产量,并计算环比增长率(与上月对比),按产线分组,按月份排序。
-- 产线月度产量 + 环比增长率
WITH MonthlyOutput AS (
SELECT
LineName,
FORMAT(ProductionDate, 'yyyy-MM') AS Month,
SUM(Output) AS TotalOutput,
AVG(Yield) AS AvgYield
FROM ProductionRecords
WHERE ProductionDate >= '2025-01-01'
GROUP BY LineName, FORMAT(ProductionDate, 'yyyy-MM')
)
SELECT
LineName,
Month,
TotalOutput,
AvgYield,
-- 上月产量(LAG 向下偏移一行)
LAG(TotalOutput, 1) OVER (
PARTITION BY LineName ORDER BY Month
) AS PrevOutput,
-- 环比增长率
CAST(
(CAST(TotalOutput AS FLOAT) -
LAG(TotalOutput, 1) OVER (PARTITION BY LineName ORDER BY Month))
/ NULLIF(LAG(TotalOutput, 1) OVER (PARTITION BY LineName ORDER BY Month), 0)
* 100 AS DECIMAL(5,2)
) AS GrowthRate,
-- 产线内排名
RANK() OVER (PARTITION BY Month ORDER BY TotalOutput DESC) AS RankInMonth
FROM MonthlyOutput
ORDER BY LineName, Month;
LAG(col, n):获取当前行前 n 行的值 → 算环比。 LEAD(col, n):获取后 n 行 → 算同比。 ROW_NUMBER():连续编号。 RANK():并列跳号。 SUM(col) OVER():累计求和。关键语法:FUNCTION() OVER (PARTITION BY ... ORDER BY ...)
19 · 手写代码 — Dockerfile
题目:为 Vue 3 前端应用编写 Dockerfile,使用多阶段构建,最终用 Nginx 提供静态文件服务。
# ===== 阶段1:构建 =====
FROM node:18-alpine AS builder
WORKDIR /app
# 先复制依赖文件(利用 Docker 缓存层)
COPY package.json package-lock.json ./
RUN npm ci
# 复制源代码并构建
COPY . .
RUN npm run build
# ===== 阶段2:运行 =====
FROM nginx:alpine
# 复制构建产物到 Nginx 目录
COPY --from=builder /app/dist /usr/share/nginx/html
# 复制 Nginx 配置(支持 Vue Router history 模式)
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ /index.html; # Vue Router history 模式
}
# API 反向代理到后端服务
location /api/ {
proxy_pass http://backend:3000/;
}
}
① 提到多阶段构建的好处:最终镜像只有 Nginx + 静态文件(~20MB),不含 Node.js 和源码 ② .dockerignore 排除 node_modules、.git 等 ③ 提到 docker-compose 配合后端 + 数据库一起启动 ④ EXPOSE 只是声明,实际映射靠 -p 参数。
20 · 薪资谈判指南
| 城市/级别 | 应届/0-1年 | 1-3年 | 3-5年 | 5年+ |
|---|---|---|---|---|
| 烟台(中际旭创总部) | 6K-9K | 8K-14K | 13K-20K | 18K-28K |
| 一线城市(北上广深)同岗 | 8K-13K | 12K-20K | 18K-30K | 25K-40K |
| 制造业 IT 岗位(全国均) | 5K-8K | 7K-12K | 10K-18K | 15K-25K |
注:以上为参考范围,具体受学历、项目经验、面试表现、公司当期预算等因素影响。中际旭创作为上市公司,薪资通常高于同地区制造业平均水平。
谈判策略
面试前确定三个数:最低可接受薪资(底线)、合理期望薪资(目标)、理想薪资(争取值)。目标值 = 底线 + 20%~30%。
/* 当 HR 问"你的期望薪资是多少?" */
"根据我对这个岗位的了解,结合我的全栈技术能力
(Vue + ECharts + Node.js + SQL Server + Docker),
以及制造业数据可视化的项目经验,
我的期望薪资范围是 [目标值] 左右。
但我更看重这个岗位的学习成长空间和团队氛围,
薪资方面是可以在合理范围内商量的。"
/* 关键点:
① 给范围,不给死数
② 强调你的技术栈匹配度
③ 表达灵活性,不显得死板
*/
| 评估维度 | 关注点 | 权重 |
|---|---|---|
| 基本薪资 | 税前月薪、绩效比例 | 高 |
| 年终奖 | 几个月?是否有保底? | 高 |
| 五险一金 | 缴纳基数和比例(按全额还是最低?) | 高 |
| 加班情况 | 是否 996?加班费?调休? | 中 |
| 技术成长 | 团队规模、技术氛围、学习机会 | 中 |
| 通勤距离 | 单程时间、是否有班车 | 中 |
| 福利补贴 | 餐补、交通补、年度体检、股票期权 | 低 |
① 不要先报数字,让对方先给范围 ② 不要拿别的 Offer 压价(除非你真的不想要这个)③ 年终奖问清楚是"保底几个月"还是"视绩效" ④ 试用期薪资一般是转正的 80%,确认清楚 ⑤ 确认五险一金的缴纳基数——差很多。
21 · 面试前检查清单
面试前一天晚上,按照以下清单逐项检查。每完成一项,在前面打个勾。
① 不会的就说不会,但要说出你的思考方向 — 面试官更看重解决问题的思路 ② 用制造业的例子回答,而不是泛泛而谈 — 比如说"车间的良率看板"而不是"一个图表" ③ 放慢语速,想清楚再回答 — 不急 ④ 表达热情 — "我对制造业数字化转型很感兴趣"比"我需要一份工作"强 100 倍。
你已经完成了12篇教程的系统学习,技术基础扎实。
现在只需要把知识点串起来,自信地展示你的全栈能力。
全栈技术 + 制造业领域理解 = 你的核心竞争力