Browse Source

拍照、视频

master
han\hanst 1 week ago
parent
commit
03021782c5
  1. 1
      src/api/longchuang/productionPlan.js
  2. 765
      src/views/modules/longtron/production-work-report.vue
  3. 4
      src/views/modules/longtron/screen-cable-cop-progress.vue
  4. 2
      src/views/modules/longtron/screen-machining-progress.vue
  5. 4
      src/views/modules/longtron/screen-renovation-progress.vue
  6. 4
      src/views/modules/longtron/screen-whole-lift-progress.vue

1
src/api/longchuang/productionPlan.js

@ -38,3 +38,4 @@ export const cancelReportLog = data => createAPI(`/longchuang/productionPlan/rep
// ================= 生产报工 =================
export const getWorkReportOrderList = data => createAPI(`/longchuang/productionPlan/workReport/list`, 'post', data)
export const reportWorkNodeWithMedia = data => createAPI(`/longchuang/productionPlan/workReport/reportNodeWithMedia`, 'post', data)

765
src/views/modules/longtron/production-work-report.vue

@ -170,12 +170,14 @@
</div>
<el-dialog
title="节点报工"
:title="reportDialogTitle"
:visible.sync="reportDialogVisible"
width="400px"
:width="requiresMediaUpload(reportData.orderType, reportData.nodeCode, reportData.nodeName) ? '80%' : '400px'"
:close-on-click-modal="false"
:before-close="handleReportDialogClose"
:custom-class="reportDialogClass"
v-drag>
<el-form :model="reportData" label-position="top">
<el-form :model="reportData" label-position="top" class="report-dialog-form">
<el-row :gutter="12">
<el-col :span="12">
<el-form-item label="项目号">
@ -188,21 +190,98 @@
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-row :gutter="24" v-if="isQtyRequired(reportData.orderType)">
<el-col :span="24">
<el-form-item label="报工数量" required>
<el-input v-model="reportData.reportQty" style="width: 100%"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24" v-if="requiresMediaUpload(reportData.orderType, reportData.nodeCode, reportData.nodeName)">
<el-col :span="24">
<el-form-item label="报工影像(支持拍照和录像,可多次采集)">
<div class="media-layout">
<div class="media-layout-left">
<div class="camera-preview-wrap">
<video ref="cameraPreview" class="camera-preview" autoplay playsinline muted></video>
<div v-if="!cameraActive" class="camera-placeholder">摄像头未开启</div>
</div>
<div class="camera-action-bar">
<!-- <el-button size="mini" type="primary" plain icon="el-icon-video-camera" @click="startCamera" :disabled="reportLoading">
开启摄像头
</el-button>
<el-button size="mini" plain icon="el-icon-camera" @click="capturePhoto" :disabled="!cameraActive || reportLoading || recording">
拍照
</el-button>
<el-button
size="mini"
:type="recording ? 'danger' : 'warning'"
plain
icon="el-icon-video-play"
@click="toggleVideoRecording"
:disabled="!cameraActive || reportLoading">
{{ recording ? '停止录像' : '开始录像' }}
</el-button>-->
<el-button class="camera-btn" plain icon="el-icon-camera" @click="triggerSystemCamera('image')" :disabled="reportLoading">
拍照
</el-button>
<el-button class="video-btn" plain icon="el-icon-video-camera" @click="triggerSystemCamera('video')" :disabled="reportLoading">
录像
</el-button>
<!-- <el-button size="mini" plain icon="el-icon-switch-button" @click="stopCamera" :disabled="!cameraActive || reportLoading">
关闭摄像头
</el-button>-->
</div>
<input
ref="cameraImageInput"
class="camera-file-input"
type="file"
accept="image/*"
capture="environment"
multiple
@change="handleSystemCameraChange($event, 'image')">
<input
ref="cameraVideoInput"
class="camera-file-input"
type="file"
accept="video/*"
capture="environment"
multiple
@change="handleSystemCameraChange($event, 'video')">
</div>
<div class="media-layout-right">
<div class="capture-list-title">已采集 {{ capturedMediaList.length }} 个文件</div>
<div class="capture-list-panel">
<div v-if="capturedMediaList.length > 0" class="capture-list">
<div v-for="(item, index) in capturedMediaList" :key="item.uid" class="capture-item">
<img v-if="isImageFile(item)" :src="item.previewUrl" class="capture-thumb" alt="capture-image">
<video v-else class="capture-thumb" controls preload="metadata">
<source :src="item.previewUrl" :type="item.mimeType || 'video/webm'">
</video>
<div class="capture-meta">
<span class="capture-name">{{ item.name }}</span>
<el-tag size="mini" :type="item.kind === 'video' ? 'warning' : 'success'">
{{ item.kind === 'video' ? '视频' : '照片' }}
</el-tag>
</div>
<el-button type="danger" @click="removeCapturedMedia(index)">删除</el-button>
</div>
</div>
<div v-else class="empty-capture-list">
<i class="el-icon-camera"></i>
<p>暂无采集文件请先拍照或录像</p>
</div>
</div>
</div>
</div>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button size="mini" class="reset-btn"
plain @click="reportDialogVisible = false">取消</el-button>
<el-button size="mini"
type="primary"
plain :loading="reportLoading" @click="submitNodeReport">
{{ reportLoading ? '提交中...' : '确认报工' }}
<el-button size="mini" class="reset-btn" plain @click="closeReportDialog">取消</el-button>
<el-button size="mini" type="primary" plain :loading="reportLoading" @click="submitNodeReport">
{{ reportLoading ? (requiresMediaUpload(reportData.orderType, reportData.nodeCode, reportData.nodeName) ? '上传中...' : '提交中...') : (requiresMediaUpload(reportData.orderType, reportData.nodeCode, reportData.nodeName) ? '上传并报工' : '确认报工') }}
</el-button>
</div>
</el-dialog>
@ -239,7 +318,7 @@
</template>
<script>
import { getWorkReportOrderList, reportCableCopTaskNode, reportHomeLiftOrderNode, reportMachiningTaskNode, reportRenovationOrderNode } from '@/api/longchuang/productionPlan'
import { getWorkReportOrderList, reportCableCopTaskNode, reportHomeLiftOrderNode, reportMachiningTaskNode, reportRenovationOrderNode, reportWorkNodeWithMedia } from '@/api/longchuang/productionPlan'
export default {
name: 'ProductionWorkReport',
@ -272,7 +351,14 @@ export default {
reportQty: 1,
reportBy: '',
remark: ''
}
},
cameraActive: false,
cameraStream: null,
mediaRecorder: null,
recording: false,
recordedChunks: [],
captureIndex: 1,
capturedMediaList: []
}
},
computed: {
@ -281,11 +367,27 @@ export default {
},
pendingNodeCount () {
return this.dataList.reduce((sum, item) => sum + (item.visibleNodeList || []).filter(node => node.status !== '已完成').length, 0)
},
reportDialogTitle () {
return this.requiresMediaUpload(this.reportData.orderType, this.reportData.nodeCode, this.reportData.nodeName) ? '节点报工与影像上传' : '节点报工'
},
reportDialogClass () {
const classList = ['report-node-dialog']
if (this.requiresMediaUpload(this.reportData.orderType, this.reportData.nodeCode, this.reportData.nodeName)) {
classList.push('report-node-dialog--media')
}
return classList.join(' ')
}
},
activated () {
this.getDataList('Y')
},
deactivated () {
this.releaseMediaResources()
},
beforeDestroy () {
this.releaseMediaResources()
},
methods: {
getDataList (flag) {
if (flag === 'Y') {
@ -400,12 +502,49 @@ export default {
return !!order.currentNodeCode && order.currentNodeCode === node.nodeCode
},
handleReportNode (order, node) {
if (order && order.orderType === 'MACHINING') {
if (!order || !node) {
return
}
if (order.orderType === 'MACHINING') {
this.openReportDialog(order, node, true)
return
}
if (this.requiresMediaUpload(order.orderType, node.nodeCode, node.nodeName)) {
this.openReportDialog(order, node, false)
return
}
this.directReportNode(order, node)
},
isQtyRequired (orderType) {
return ['CABLE_COP', 'MACHINING'].includes(orderType)
},
requiresMediaUpload (orderType, nodeCode, nodeName) {
if (!orderType) {
return false
}
const requiredMap = {
HOME_LIFT: {
codeList: ['platformDebug', 'bgCeiling', 'doorAssy', 'pack'],
nameList: ['平台组装/调试', '背景墙/吊顶组装', '门组装', '打包']
},
RENOVATION: {
codeList: ['inspect', 'pack'],
nameList: ['检验', '打包']
}
}
const config = requiredMap[orderType]
if (!config) {
return false
}
if (nodeCode && config.codeList.includes(nodeCode)) {
return true
}
if (!nodeName) {
return false
}
const normalizedName = String(nodeName).replace(/\s+/g, '')
return config.nameList.some(name => name.replace(/\s+/g, '') === normalizedName)
},
directReportNode (order, node) {
this.reportData = {
orderNo: order.orderNo,
@ -431,19 +570,35 @@ export default {
remark: ''
}
this.reportDialogVisible = true
this.releaseMediaResources()
this.captureIndex = 1
},
closeReportDialog () {
this.reportDialogVisible = false
this.releaseMediaResources()
},
handleReportDialogClose (done) {
this.closeReportDialog()
if (typeof done === 'function') {
done()
}
},
submitNodeReport () {
if (!this.reportData.nodeCode) {
this.$message.warning('请选择报工节点')
return
}
if (['CABLE_COP', 'MACHINING'].includes(this.reportData.orderType)) {
if (this.isQtyRequired(this.reportData.orderType)) {
const qty = Number(this.reportData.reportQty)
if (!Number.isFinite(qty) || qty <= 0) {
this.$message.warning('请填写大于0的实际生产数量')
return
}
}
if (this.requiresMediaUpload(this.reportData.orderType, this.reportData.nodeCode, this.reportData.nodeName)) {
this.submitNodeReportWithMedia()
return
}
const apiMap = {
HOME_LIFT: reportHomeLiftOrderNode,
CABLE_COP: reportCableCopTaskNode,
@ -456,16 +611,11 @@ export default {
return
}
this.reportLoading = true
apiFn({
orderNo: this.reportData.orderNo,
nodeCode: this.reportData.nodeCode,
reportQty: this.reportData.reportQty,
remark: this.reportData.remark
}).then(({ data }) => {
apiFn(this.buildNodeReportPayload()).then(({ data }) => {
this.reportLoading = false
if (data && data.code === 0) {
this.$message.success(data.msg || '报工成功')
this.reportDialogVisible = false
this.closeReportDialog()
this.getDataList()
} else {
this.$message.error((data && data.msg) || '报工失败')
@ -475,6 +625,291 @@ export default {
this.$message.error('报工失败')
})
},
submitNodeReportWithMedia () {
if (!this.capturedMediaList.length) {
this.$message.warning('请先上传检验照片或视频')
return
}
const formData = new FormData()
const payload = this.buildNodeReportPayload()
formData.append('orderNo', payload.orderNo)
formData.append('orderType', this.reportData.orderType || '')
formData.append('nodeCode', payload.nodeCode)
formData.append('reportQty', String(payload.reportQty || 1))
formData.append('remark', payload.remark || '')
this.capturedMediaList.forEach(item => {
formData.append('file', item.raw, item.name)
})
this.reportLoading = true
reportWorkNodeWithMedia(formData).then(({ data }) => {
this.reportLoading = false
if (data && data.code === 0) {
this.$message.success(data.msg || '上传并报工成功')
this.closeReportDialog()
this.getDataList()
} else {
this.$message.error((data && data.msg) || '上传失败')
}
}).catch(() => {
this.reportLoading = false
this.$message.error('上传失败')
})
},
buildNodeReportPayload () {
const reportQty = this.isQtyRequired(this.reportData.orderType) ? this.reportData.reportQty : 1
return {
orderNo: this.reportData.orderNo,
nodeCode: this.reportData.nodeCode,
reportQty: reportQty,
remark: this.reportData.remark || ''
}
},
async startCamera () {
if (!this.requiresMediaUpload(this.reportData.orderType, this.reportData.nodeCode, this.reportData.nodeName)) {
return
}
if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
this.$message.error('当前设备不支持摄像头调用,请使用“系统相机”')
return
}
this.stopCamera(true)
try {
const stream = await navigator.mediaDevices.getUserMedia({
video: {
facingMode: { ideal: 'environment' },
width: { ideal: 1280 },
height: { ideal: 720 }
},
audio: false
})
this.cameraStream = stream
this.cameraActive = true
const videoEl = this.$refs.cameraPreview
if (videoEl) {
videoEl.srcObject = stream
const playPromise = videoEl.play()
if (playPromise && typeof playPromise.then === 'function') {
playPromise.catch(() => {})
}
}
} catch (e) {
this.cameraActive = false
this.$message.error('摄像头打开失败,请检查权限或改用“系统相机”')
}
},
stopCamera (discardRecording = false) {
if (this.mediaRecorder && this.mediaRecorder.state !== 'inactive') {
if (discardRecording) {
this.mediaRecorder.ondataavailable = null
this.mediaRecorder.onstop = null
this.mediaRecorder.stop()
this.resetRecordingState()
} else {
this.stopVideoRecording(false)
}
}
if (this.cameraStream && this.cameraStream.getTracks) {
this.cameraStream.getTracks().forEach(track => track.stop())
}
this.cameraStream = null
this.cameraActive = false
const videoEl = this.$refs.cameraPreview
if (videoEl) {
videoEl.srcObject = null
}
},
capturePhoto () {
if (!this.cameraActive || !this.cameraStream) {
this.$message.warning('请先开启摄像头')
return
}
const videoEl = this.$refs.cameraPreview
if (!videoEl || !videoEl.videoWidth || !videoEl.videoHeight) {
this.$message.warning('摄像头画面尚未准备完成')
return
}
const canvas = document.createElement('canvas')
canvas.width = videoEl.videoWidth
canvas.height = videoEl.videoHeight
const ctx = canvas.getContext('2d')
if (!ctx) {
this.$message.error('无法采集照片,请稍后重试')
return
}
ctx.drawImage(videoEl, 0, 0, canvas.width, canvas.height)
canvas.toBlob(blob => {
if (!blob) {
this.$message.error('照片生成失败,请重试')
return
}
this.appendCapturedFile(blob, 'image', 'image/jpeg')
}, 'image/jpeg', 0.92)
},
toggleVideoRecording () {
if (this.recording) {
this.stopVideoRecording(true)
} else {
this.startVideoRecording()
}
},
startVideoRecording () {
if (!this.cameraActive || !this.cameraStream) {
this.$message.warning('请先开启摄像头')
return
}
if (typeof MediaRecorder === 'undefined') {
this.$message.warning('当前浏览器不支持录像,请使用“系统相机”')
return
}
const recorderOptions = this.resolveMediaRecorderOptions()
this.recordedChunks = []
try {
this.mediaRecorder = new MediaRecorder(this.cameraStream, recorderOptions)
} catch (e) {
this.$message.warning('当前设备录像能力受限,请使用“系统相机”')
return
}
this.mediaRecorder.ondataavailable = event => {
if (event.data && event.data.size > 0) {
this.recordedChunks.push(event.data)
}
}
this.mediaRecorder.onstop = () => {
if (!this.recordedChunks.length) {
this.resetRecordingState()
return
}
const mimeType = this.mediaRecorder && this.mediaRecorder.mimeType ? this.mediaRecorder.mimeType : 'video/webm'
const blob = new Blob(this.recordedChunks, { type: mimeType })
this.appendCapturedFile(blob, 'video', mimeType)
this.resetRecordingState()
}
this.mediaRecorder.start()
this.recording = true
this.$message.success('开始录像')
},
stopVideoRecording (showMessage) {
if (!this.mediaRecorder || this.mediaRecorder.state === 'inactive') {
return
}
this.mediaRecorder.stop()
this.recording = false
if (showMessage) {
this.$message.success('录像已结束')
}
},
resolveMediaRecorderOptions () {
if (typeof MediaRecorder === 'undefined' || typeof MediaRecorder.isTypeSupported !== 'function') {
return {}
}
const mimeTypeList = [
'video/webm;codecs=vp9',
'video/webm;codecs=vp8',
'video/webm',
'video/mp4'
]
for (let i = 0; i < mimeTypeList.length; i++) {
const mimeType = mimeTypeList[i]
if (MediaRecorder.isTypeSupported(mimeType)) {
return { mimeType: mimeType }
}
}
return {}
},
appendCapturedFile (blob, kind, mimeType) {
const name = this.createCaptureName(kind, mimeType)
const file = new File([blob], name, { type: mimeType || blob.type || '' })
const previewUrl = URL.createObjectURL(file)
this.capturedMediaList.push({
uid: `${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,
name: name,
kind: kind,
mimeType: file.type,
raw: file,
previewUrl: previewUrl
})
},
createCaptureName (kind, mimeType) {
const extMap = {
'image/jpeg': 'jpg',
'image/png': 'png',
'video/webm': 'webm',
'video/mp4': 'mp4'
}
const fallbackExt = kind === 'video' ? 'webm' : 'jpg'
const extension = extMap[mimeType] || fallbackExt
const now = new Date()
const dateText = `${now.getFullYear()}${String(now.getMonth() + 1).padStart(2, '0')}${String(now.getDate()).padStart(2, '0')}${String(now.getHours()).padStart(2, '0')}${String(now.getMinutes()).padStart(2, '0')}${String(now.getSeconds()).padStart(2, '0')}`
const nodeCode = this.reportData.nodeCode || 'node'
const seq = String(this.captureIndex++).padStart(3, '0')
return `${nodeCode}_${kind}_${dateText}_${seq}.${extension}`
},
removeCapturedMedia (index) {
const target = this.capturedMediaList[index]
if (target && target.previewUrl) {
URL.revokeObjectURL(target.previewUrl)
}
this.capturedMediaList.splice(index, 1)
},
resetCapturedMedia () {
this.capturedMediaList.forEach(item => {
if (item && item.previewUrl) {
URL.revokeObjectURL(item.previewUrl)
}
})
this.capturedMediaList = []
},
resetRecordingState () {
this.mediaRecorder = null
this.recording = false
this.recordedChunks = []
},
triggerSystemCamera (mode) {
const refName = mode === 'video' ? 'cameraVideoInput' : 'cameraImageInput'
const inputEl = this.$refs[refName]
if (!inputEl) {
return
}
inputEl.value = ''
inputEl.click()
},
handleSystemCameraChange (event, expectedKind) {
const files = (event && event.target && event.target.files) ? Array.from(event.target.files) : []
if (!files.length) {
return
}
files.forEach(file => {
const previewUrl = URL.createObjectURL(file)
const fileKind = expectedKind || (file.type && file.type.indexOf('video/') === 0 ? 'video' : 'image')
const fileName = file.name || this.createCaptureName(fileKind, file.type || '')
this.capturedMediaList.push({
uid: `${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,
name: fileName,
kind: fileKind,
mimeType: file.type || '',
raw: file,
previewUrl: previewUrl
})
})
if (event && event.target) {
event.target.value = ''
}
},
isImageFile (item) {
return !!(item && item.mimeType && item.mimeType.indexOf('image/') === 0)
},
releaseMediaResources () {
this.stopCamera(true)
this.resetCapturedMedia()
this.resetRecordingState()
const inputRefList = ['cameraImageInput', 'cameraVideoInput']
inputRefList.forEach(refName => {
const inputEl = this.$refs[refName]
if (inputEl) {
inputEl.value = ''
}
})
},
openHistoryDialog (item) {
this.historyOrder = item
this.historyDialogVisible = true
@ -622,8 +1057,9 @@ export default {
.cards-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(390px, 1fr));
grid-template-columns: repeat(auto-fill, 320px);
gap: 15px;
justify-content: start;
}
.report-card {
@ -831,6 +1267,210 @@ export default {
font-size: 42px;
}
.media-capture-tip {
font-size: 12px;
color: #909399;
margin-bottom: 8px;
}
.report-container >>> .report-node-dialog--media {
margin-top: 4vh !important;
width: min(1080px, 96vw) !important;
max-width: calc(100vw - 12px);
height: 85vh;
max-height: 85vh;
display: flex;
flex-direction: column;
}
.report-container >>> .report-node-dialog--media .el-dialog__header,
.report-container >>> .report-node-dialog--media .el-dialog__footer {
flex: 0 0 auto;
padding-left: 16px;
padding-right: 16px;
}
.report-container >>> .report-node-dialog--media .el-dialog__body {
flex: 1 1 auto;
min-height: 0;
overflow: hidden;
padding: 8px 16px 10px;
display: flex;
flex-direction: column;
}
.report-dialog-form {
width: 100%;
}
.report-container >>> .report-node-dialog--media .report-dialog-form {
flex: 1 1 auto;
min-height: 0;
display: flex;
flex-direction: column;
}
.report-container >>> .report-node-dialog--media .report-dialog-form > .el-row:last-child {
flex: 1 1 auto;
min-height: 0;
margin-bottom: 0;
}
.report-container >>> .report-node-dialog--media .report-dialog-form .el-form-item {
margin-bottom: 8px;
}
.media-layout {
display: grid;
grid-template-columns: minmax(0, 2.1fr) minmax(300px, 1fr);
gap: 12px;
align-items: stretch;
height: 100%;
min-height: 0;
}
.media-layout-left {
min-width: 0;
min-height: 0;
display: flex;
flex-direction: column;
}
.media-layout-right {
min-width: 0;
min-height: 0;
display: flex;
flex-direction: column;
}
.camera-preview-wrap {
position: relative;
width: 100%;
flex: 1 1 auto;
min-height: 480px;
height: auto;
border: 1px solid #dcdfe6;
border-radius: 4px;
overflow: hidden;
background: #000;
}
.camera-preview {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
}
.camera-placeholder {
position: absolute;
inset: 0;
color: #e5e9f2;
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
letter-spacing: 0.5px;
}
.camera-action-bar {
display: flex;
flex-wrap: wrap;
gap: 6px;
margin-top: 8px;
}
.camera-action-bar .el-button {
margin-left: 0 !important;
}
.camera-file-input {
display: none;
}
.capture-list-title {
margin: 0 0 8px 0;
font-size: 12px;
color: #606266;
}
.capture-list-panel {
flex: 1 1 auto;
min-height: 480px;
border: 1px solid #ebeef5;
border-radius: 4px;
padding: 8px;
overflow: hidden;
background: #fafbfc;
}
.capture-list {
display: grid;
grid-template-columns: 1fr;
grid-auto-rows: 168px;
gap: 8px;
height: 100%;
align-content: start;
overflow-y: auto;
}
.capture-item {
height: 168px;
min-height: 168px;
display: flex;
flex-direction: column;
border: 1px solid #ebeef5;
border-radius: 4px;
overflow: hidden;
background: #fff;
}
.capture-thumb {
width: 100%;
height: 100px;
display: block;
object-fit: cover;
background: #000;
}
.capture-meta {
display: flex;
align-items: center;
justify-content: space-between;
gap: 6px;
padding: 6px 8px 2px;
}
.capture-name {
font-size: 12px;
color: #606266;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.capture-remove {
margin-top: 2px;
padding: 4px 8px 2px 4px;
line-height: 1;
text-align: left;
}
.empty-capture-list {
text-align: center;
color: #909399;
padding: 36px 12px;
}
.empty-capture-list i {
font-size: 34px;
}
.empty-capture-list p {
margin: 8px 0 0 0;
font-size: 12px;
}
.history-table >>> .el-table__header-wrapper th,
.history-table >>> .el-table__header-wrapper .el-table__cell {
background-color: #F5F7FA !important;
@ -868,6 +1508,46 @@ export default {
.cards-grid {
grid-template-columns: 1fr;
}
.report-container >>> .report-node-dialog--media {
width: 98% !important;
margin-top: 1vh !important;
height: 95vh;
max-height: 95vh;
}
.report-container >>> .report-node-dialog--media .el-dialog__header,
.report-container >>> .report-node-dialog--media .el-dialog__footer {
padding-left: 10px;
padding-right: 10px;
}
.report-container >>> .report-node-dialog--media .el-dialog__body {
padding: 8px 10px;
}
.report-container >>> .report-node-dialog--media .report-dialog-form > .el-row:first-child .el-col {
width: 100%;
}
.media-layout {
grid-template-columns: 1fr;
gap: 8px;
}
.media-layout-right {
margin-top: 0;
}
.capture-list-panel {
min-height: 340px;
}
.camera-preview-wrap {
flex: 0 0 auto;
height: 400px;
min-height: 340px;
}
}
.status-info {
@ -892,4 +1572,45 @@ export default {
border-color: #909399;
color: #fff;
}
/* 拍照按钮 */
.camera-btn {
font-size: 16px !important;
padding: 10px 16px !important;
border-radius: 6px;
color: #409EFF !important;
border-color: #409EFF !important;
background-color: #ecf5ff !important;
}
.camera-btn i {
font-size: 18px !important;
}
/* 悬停效果 */
.camera-btn:hover {
background-color: #409EFF !important;
color: #fff !important;
}
/* 录像按钮 */
.video-btn {
font-size: 16px !important;
padding: 10px 16px !important;
border-radius: 6px;
color: #F56C6C !important;
border-color: #F56C6C !important;
background-color: #fef0f0 !important;
}
.video-btn i {
font-size: 18px !important;
}
/* 悬停效果 */
.video-btn:hover {
background-color: #F56C6C !important;
color: #fff !important;
}
</style>

4
src/views/modules/longtron/screen-cable-cop-progress.vue

@ -55,10 +55,10 @@ export default {
return { loading: false, boardTimerId: null,tableHeight: 640, currentTime: '', timerId: null, boardList: [], kpi: { total: 0, processing: 0, finished: 0, finishRate: 0 } }
},
mounted() { this.setTableHeight(); this.loadBoardData(); this.updateTime(); this.timerId = setInterval(this.updateTime, 1000);
// 10
// 60
this.boardTimerId = setInterval(() => {
this.loadBoardData()
}, 10000)
}, 60000)
window.addEventListener('resize', this.setTableHeight) },
beforeDestroy() { if (this.timerId) clearInterval(this.timerId);

2
src/views/modules/longtron/screen-machining-progress.vue

@ -53,7 +53,7 @@ export default {
this.timerId = setInterval(this.updateTime, 1000)
this.boardTimerId = setInterval(() => {
this.loadBoardData()
}, 10000)
}, 60000)
window.addEventListener('resize', this.setTableHeight)
},
beforeDestroy() {

4
src/views/modules/longtron/screen-renovation-progress.vue

@ -46,10 +46,10 @@ export default {
return { loading: false, boardTimerId: null, tableHeight: 640, currentTime: '', timerId: null, boardList: [], kpi: { total: 0, processing: 0, finished: 0, finishRate: 0 } }
},
mounted() { this.setTableHeight(); this.loadBoardData(); this.updateTime(); this.timerId = setInterval(this.updateTime, 1000);
// 10
// 60
this.boardTimerId = setInterval(() => {
this.loadBoardData()
}, 10000)
}, 60000)
window.addEventListener('resize', this.setTableHeight) },
beforeDestroy() { if (this.timerId) clearInterval(this.timerId);

4
src/views/modules/longtron/screen-whole-lift-progress.vue

@ -65,10 +65,10 @@ export default {
this.updateTime()
this.timerId = setInterval(this.updateTime, 1000)
// 10
// 60
this.boardTimerId = setInterval(() => {
this.loadBoardData()
}, 10000)
}, 60000)
window.addEventListener('resize', this.setTableHeight)
},

Loading…
Cancel
Save