复制代码
<!-- src/components/DynamicField/index.vue -->
<template>
<el-form-item
:label="fieldLabel"
:prop="prop"
:required="isRequired"
:rules="fieldRules"
>
<component
:is="currentComponent"
v-model="internalValue"
v-bind="dynamicProps"
v-on="dynamicEvents"
:class="noplus?'noplus':''"
>
<i slot="default" v-show="currentComponent=='ElUpload'&&!disabled" class="el-icon-plus"></i>
</component>
</el-form-item>
</template>
<script>
// 导入实际的 Element UI 组件
import { Input, InputNumber, DatePicker, Upload } from 'element-ui';
import { getToken } from '@/utils/auth';
// 组件映射表
const COMPONENT_MAP = {
TEXT: 'ElInput',
NUMBER: 'ElInputNumber',
DATE: 'ElDatePicker',
IMAGE: 'ElUpload'
};
export default {
name: 'DynamicField',
components: {
ElInput: Input,
ElInputNumber: InputNumber,
ElDatePicker: DatePicker,
ElUpload: Upload
},
props: {
// 数据类型:TEXT/NUMBER/DATE/IMAGE
lx: {
type: String,
required: true
},
// 字段值
value: {
type: [String, Number, Date, Array],
default: ''
},
// 字段配置
config: {
type: Object,
default: () => ({})
},
// 是否显示标签
showLabel: {
type: Boolean,
default: true
},
// 标签名称(覆盖config中的sjxmc)
label: {
type: String,
default: ''
},
// 是否必填
required: {
type: Boolean,
default: false
},
// 表单验证规则路径
prop: {
type: String,
default: ''
},
// 是否禁用
disabled: {
type: Boolean,
default: false
},
// 占位符
placeholder: {
type: String,
default: ''
},
// 其他属性透传
otherProps: {
type: Object,
default: () => ({})
},
// 是否显示错误信息
showMessage: {
type: Boolean,
default: true
}
},
data() {
return {
noplus:false,
internalValue: this.formatValue(this.value),
// 上传相关状态
uploadLoading: false,
uploadHeaders: {
Authorization: 'Bearer ' + getToken()
}
};
},
computed: {
// 根据类型选择组件
currentComponent() {
const type = this.lx.toUpperCase();
return COMPONENT_MAP[type] || 'ElInput';
},
// 字段标签(包含必填星号)
fieldLabel() {
const label = this.label || this.config.sjxmc || '';
return label;
},
isRequired() {
if (this.required !== undefined) {
return this.required;
}
return this.config.sfbt === '1';
},
// 字段验证规则
fieldRules() {
const rules = [];
if (this.isRequired) {
const message = (this.label || this.config.sjxmc || '该字段') + '不能为空';
if (this.lx.toUpperCase() === 'IMAGE') {
// 图片类型特殊验证
rules.push({
required: true,
message: message,
trigger: 'change',
validator: (rule, value, callback) => {
if (!value || (typeof value === 'string' && !value.trim())) {
callback(new Error(message));
} else {
callback();
}
}
});
} else {
rules.push({
required: true,
message: message,
trigger: 'blur'
});
}
}
return rules;
},
// 动态属性
dynamicProps() {
const baseProps = {
disabled: this.disabled,
placeholder: this.getPlaceholder(),
...this.otherProps
};
const type = this.lx.toUpperCase();
// 根据不同的数据类型添加特定的属性
switch (type) {
case 'TEXT':
const isTextarea = this.config.zdkdxs === '2';
return {
...baseProps,
type: 'textarea',
rows: isTextarea ? (this.config.hs || 3) : undefined,
maxlength: this.config.zdcd,
'show-word-limit': !!this.config.zdcd,
clearable: this.config.clearable !== false
};
case 'NUMBER':
return {
...baseProps,
step: this.config.bdz || 1,
precision: this.config.decimal || 2,
controls: this.config.controls !== false,
'controls-position': this.config.controlsPosition || 'right',
style: { width: this.config.width || '100%' }
};
case 'DATE':
// 根据配置确定日期类型
let dateType = 'datetime';
let format = 'yyyy-MM-dd HH:mm:ss';
let valueFormat = 'yyyy-MM-dd HH:mm:ss';
switch (String(this.config.zdlx)) {
case '1': // 日期
dateType = 'date';
format = 'yyyy-MM-dd';
valueFormat = 'yyyy-MM-dd';
break;
case '2': // 日期时间
dateType = 'datetime';
format = 'yyyy-MM-dd HH:mm:ss';
valueFormat = 'yyyy-MM-dd HH:mm:ss';
break;
case '3': // 年
dateType = 'year';
format = 'yyyy';
valueFormat = 'yyyy';
break;
case '4': // 月
dateType = 'month';
format = 'yyyy-MM';
valueFormat = 'yyyy-MM';
break;
}
return {
...baseProps,
type: dateType,
format: format,
'value-format': valueFormat,
clearable: this.config.clearable !== false,
editable: this.config.editable !== false,
style: { width: this.config.width || '100%' }
};
case 'IMAGE':
const fileList = this.getFileList();
const hasFile = fileList && fileList.length > 0;
return {
...baseProps,
action: this.config.action || process.env.VUE_APP_BASE_API + '/common/upload',
'list-type': 'picture-card',
headers: { Authorization: 'Bearer ' + getToken() },
multiple: false, // 单文件上传
limit: 1, // 限制1个文件
accept: this.config.accept || 'image/jpeg,image/png,image/gif',
'file-list': this.getFileList(),
'on-success': this.handleUploadSuccess,
'on-remove': this.handleRemove,
'on-exceed': this.handleExceed,
'on-preview': this.handlePreview,
'before-upload': this.beforeUpload,
'on-error': this.handleUploadError,
};
default:
return baseProps;
}
},
// 动态事件
dynamicEvents() {
const events = {
input: (value) => {
this.internalValue = value;
this.$emit('input', value);
}
};
// 添加其他事件
['focus', 'blur', 'clear','change'].forEach(event => {
events[event] = (e) => {
if(event==='change'||event==='blur'){
this.$emit('my'+event, {
field: this.config.sjxdm,
value: this.internalValue,
config: this.config
});
}else {
this.$emit(event, {
field: this.config.sjxdm,
value: this.internalValue,
config: this.config
});
}
};
});
return events;
}
},
watch: {
// 监听外部 value 变化,实现回显
value: {
immediate: true,
handler(newVal) {
this.internalValue = this.formatValue(newVal);
this.noplus=newVal?true:false
}
},
// 监听内部值变化
internalValue(newVal) {
console.log('newVal',newVal)
this.$emit('input', newVal);
this.noplus=newVal?true:false
}
},
methods: {
// 格式化值
formatValue(value) {
if (value === null || value === undefined) {
// 如果有默认值,使用默认值
return this.config.mrz || '';
}
return value;
},
// 获取占位符
getPlaceholder() {
if (this.placeholder) {
return this.placeholder;
}
if (this.config.cjts) {
return this.config.cjts;
}
const placeholderMap = {
TEXT: '请输入',
NUMBER: '请输入',
DATE: '请选择',
IMAGE: '请上传'
};
return placeholderMap[this.lx.toUpperCase()] || '';
},
// 获取文件列表(图片上传用)
getFileList() {
if (this.lx.toUpperCase() !== 'IMAGE') return [];
if (!this.internalValue) return [];
// 单文件上传,直接返回文件信息
return [{
name: this.getFileNameFromUrl(this.internalValue),
url: this.internalValue
}];
},
// 从URL中提取文件名
getFileNameFromUrl(url) {
if (!url) return '图片';
const parts = url.split('/');
return parts[parts.length - 1] || '图片';
},
// 上传前的校验
beforeUpload(file) {
// 检查文件类型
const isImage = ['image/jpeg', 'image/png', 'image/gif', 'image/jpg'].includes(file.type.toLowerCase());
if (!isImage) {
this.$message.error('只能上传图片格式!');
return false;
}
// 检查文件大小(限制5MB)
const isLt5M = file.size / 1024 / 1024 < 5;
if (!isLt5M) {
this.$message.error('图片大小不能超过5MB!');
return false;
}
this.uploadLoading = true;
return true;
},
// 上传成功处理
handleUploadSuccess(response, file) {
this.uploadLoading = false;
console.log('handleUploadSuccess',response)
if (response.code === 200) {
const fileUrl = response.fileName;
if (fileUrl) {
// 单文件上传,直接赋值
this.internalValue = fileUrl;
this.$emit('input', fileUrl);
this.$emit('mychange', {
field: this.config.sjxdm,
value: fileUrl,
config: this.config
});
console.log('更新url',fileUrl)
this.$message.success('上传成功');
} else {
this.$message.error('上传失败:未获取到文件地址');
}
} else {
this.$message.error(response.msg || '上传失败');
}
},
// 上传错误处理
handleUploadError(err, file) {
this.uploadLoading = false;
this.$message.error('上传失败');
console.error('上传错误:', err, file);
},
// 文件移除处理
handleRemove(file, fileList) {
// 清空值
this.internalValue = '';
this.$emit('mychange', {
field: this.config.sjxdm,
value: null,
config: this.config
});
this.$message.success('已移除图片');
},
// 图片预览
handlePreview(file) {
if (file.url) {
window.open(file.url);
}
},
// 超出限制处理
handleExceed(files, fileList) {
this.$message.warning('只能上传一个文件,如需更换请先删除当前文件');
},
// 清空字段
clear() {
this.internalValue = '';
this.$emit('clear', {
field: this.config.sjxdm,
config: this.config
});
},
// 获取当前值
getValue() {
return this.internalValue;
},
// 设置值
setValue(value) {
this.internalValue = this.formatValue(value);
},
// 重置为默认值
reset() {
this.internalValue = this.config.mrz || '';
},
// 手动触发上传
submitUpload() {
this.$refs.upload && this.$refs.upload.submit();
},
// 清空已上传文件
clearFiles() {
this.internalValue = '';
}
},
};
</script>
<style scoped>
/* 图片上传样式优化 */
:deep(.el-upload--picture-card) {
width: 100px;
height: 100px;
line-height: 100px;
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
background-color: #fafafa;
}
:deep(.el-upload--picture-card:hover) {
border-color: #409eff;
}
:deep(.el-upload-list--picture-card .el-upload-list__item) {
width: 100px;
height: 100px;
border: 1px solid #d9d9d9;
border-radius: 6px;
}
/* 上传按钮中的图标样式 */
:deep(.el-upload--picture-card .el-icon-plus) {
font-size: 28px;
color: #8c939d;
margin-top: 20px;
}
/* 上传组件容器 */
:deep(.el-upload-list) {
margin: 0;
padding: 0;
list-style: none;
}
/* 文件列表项样式 */
:deep(.el-upload-list__item) {
transition: all 0.3s ease;
}
:deep(.el-upload-list__item:hover) {
background-color: #f5f7fa;
}
/* 上传提示信息 */
:deep(.el-upload__tip) {
font-size: 12px;
color: #909399;
margin-top: 5px;
line-height: 1.2;
}
body > div.el-dialog__wrapper > div > div.el-dialog__body > form > div:nth-child(4) > div.el-col.el-col-12 > div > div > div{
display: flex;
}
::v-deep .noplus .el-upload--picture-card{
display: none;
}
</style>
复制代码
<template>
<div class="app-container">
<!-- 如果没有选择应急信息,显示提示 -->
<div v-if="!zbid" style="text-align: center; padding: 50px; color: #909399;">
<i class="el-icon-warning" style="font-size: 48px; margin-bottom: 20px;"></i>
<p>请先在应急事件列表中选择一条记录,然后切换到"应急处置"步骤</p>
</div>
<!-- 已选择应急信息时显示内容 -->
<div v-else>
<el-table :data="CZZBList" border style="margin-bottom: 16px">
<el-table-column type="index" width="50" align="center" label="序号" />
<el-table-column label="出发时间" align="center" prop="czsj" width="150">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.cfsj, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
</template>
</el-table-column>
<el-table-column label="到达时间" align="center" prop="czsj" width="150">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.ddsj, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
</template>
</el-table-column>
<el-table-column label="现场情况" align="center" prop="xcqk"/>
<el-table-column label="汇报时间" align="center" prop="czsj" width="150">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.hbsj, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
</template>
</el-table-column>
<el-table-column label="汇报人员" align="center" prop="hbry" width="180"/>
<el-table-column label="处置内容" align="center" prop="cznr"/>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="280">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon=""
@click="fjck(scope.row)"
v-hasPermi="['yjzh:yjcz:fjck']"
>附件查看
</el-button>
<el-button
size="mini"
type="text"
icon=""
@click="ryqkck(scope.row)"
>人员情况
</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-edit"
v-hasPermi="['yjzh:yjcz:ryqkbj']"
@click="ryqkEdit(scope.row)"
>人员编辑
</el-button>
</template>
</el-table-column>
</el-table>
<el-table v-loading="loading" :data="CZMXList" border>
<el-table-column type="index" width="50" align="center" label="序号">
</el-table-column>
<el-table-column label="处置项目名称" align="center" prop="czmxmc" width="100"/>
<el-table-column label="处置项目内容" align="left" prop="czmxnr"/>
<el-table-column label="是否处置" align="center" prop="czzt">
<template slot-scope="scope">
<el-radio-group v-model="scope.row.czzt" @change="handleChange(scope.row)">
<el-radio v-for="dict in zdsfcz" :key="dict.value" :label="dict.value">{{ dict.label }}</el-radio>
</el-radio-group>
</template>
</el-table-column>
<el-table-column label="处置时间" align="center" prop="czsj" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.czsj, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
</template>
</el-table-column>
<el-table-column prop="bz" label="备注" show-overflow-tooltip>
<template slot-scope="scope">
<el-input v-model="scope.row.bz" placeholder="请输入备注"></el-input>
</template>
</el-table-column>
<el-table-column label="操作" >
<template slot-scope="scope">
<el-button
icon="el-icon-edit"
size="mini"
type="primary"
@click="sjxopen_m(scope.row,'pc')"
v-hasPermi="['yjzh:yjcz:sjxcj']"
>采集
</el-button>
<el-button
icon="el-icon-edit"
size="mini"
type="primary"
@click="sjxopen_m(scope.row,'ck')"
v-hasPermi="['yjzh:yjcz:sjxck']"
>查看
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 添加或修改问题明细对话框 -->
<el-dialog title="附件列表" :visible.sync="fjopen" width="1200px" append-to-body>
<el-table :data="fjlist" @row-click="click">
<el-table-column type="index" width="55" align="center" label="序号"/>
<el-table-column label="图片类型" align="center" prop="fjlx"/>
<el-table-column label="附件预览" align="center">
<template slot-scope="scope">
<!-- 如果是图片,则显示图片;否则显示默认文本 -->
<span v-if="!isImage(scope.row.fjlj)"></span>
<img v-else :src="scope.row.fjlj" style="max-width: 50px; max-height: 50px;">
</template>
</el-table-column>
<el-table-column label="附件类型" align="center" prop="fjlx"/>
</el-table>
<div slot="footer" class="dialog-footer">
<el-button @click="fjcancel">关 闭</el-button>
</div>
</el-dialog>
<!-- 人员情况弹窗 -->
<el-dialog :title="ryqkDialogTitle" :visible.sync="ryqkOpen" width="1600px" append-to-body>
<div class="ryqk-container">
<!-- 基本信息 -->
<el-card class="info-card">
<div slot="header" class="card-header">
<span>基本信息</span>
<el-button
type="text"
icon="el-icon-edit"
@click="toggleEditMode"
v-if="!ryqkEditMode"
>编辑</el-button>
<el-button
type="text"
icon="el-icon-check"
@click="saveRyqkData"
v-if="ryqkEditMode"
>保存</el-button>
<el-button
type="text"
icon="el-icon-close"
@click="toggleEditMode"
v-if="ryqkEditMode"
>取消</el-button>
</div>
<div class="info-content">
<div class="info-row">
<div class="info-item">
<label>交通方式:</label>
<el-select
v-model="ryqkData.jtfs"
placeholder="请选择交通方式"
style="width: 200px;"
:disabled="!ryqkEditMode">
<el-option
v-for="item in jtfsOptions"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</div>
<div class="info-item">
<label>车号:</label>
<el-input
v-model="ryqkData.czch"
placeholder="请输入车号"
style="width: 200px;"
:disabled="!ryqkEditMode"></el-input>
</div>
</div>
<div class="info-row">
<div class="info-item">
<label>实际开始动员时间:</label>
<el-date-picker
v-model="ryqkData.sjksdysj"
type="datetime"
placeholder="选择日期时间"
style="width: 200px;"
:disabled="!ryqkEditMode">
</el-date-picker>
</div>
<div class="info-item">
<label>到达时间:</label>
<el-date-picker
v-model="ryqkData.ddsj"
type="datetime"
placeholder="选择日期时间"
style="width: 200px;"
:disabled="!ryqkEditMode">
</el-date-picker>
</div>
</div>
<div class="info-row">
<div class="info-item">
<label>开始工作:</label>
<el-date-picker
v-model="ryqkData.ksgzsj"
type="datetime"
placeholder="选择日期时间"
style="width: 200px;"
:disabled="!ryqkEditMode">
</el-date-picker>
</div>
<div class="info-item">
<label>结束时间:</label>
<el-date-picker
v-model="ryqkData.qyjssj"
type="datetime"
placeholder="选择日期时间"
style="width: 200px;"
:disabled="!ryqkEditMode">
</el-date-picker>
</div>
</div>
<div class="info-row">
<div class="info-item">
<label>填报人:</label>
<el-input
v-model="ryqkData.ddldXm"
placeholder="请输入填报人"
style="width: 200px;"
:disabled="!ryqkEditMode"></el-input>
</div>
<div class="info-item">
<label>手机号:</label>
<el-input
v-model="ryqkData.ddldSj"
placeholder="请输入手机号"
style="width: 200px;"
:disabled="!ryqkEditMode"></el-input>
</div>
</div>
<div class="info-row">
<div class="info-item">
<label>整体状态:</label>
<el-select
v-model="ryqkData.dqzt"
placeholder="请选择状态"
style="width: 200px;"
:disabled="!ryqkEditMode">
<el-option
v-for="item in dqztOptions"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</div>
</div>
<div class="info-row">
<div class="info-item">
<label>备注:</label>
<el-input
v-model="ryqkData.bz"
type="textarea"
:rows="2"
placeholder="请输入备注信息"
style="width: 500px;"
:disabled="!ryqkEditMode"></el-input>
</div>
</div>
</div>
</el-card>
<!-- 队伍人员信息 -->
<el-card class="list-card">
<div slot="header" class="card-header">
<span>队伍人员信息</span>
<el-button
style="float: right;"
type="primary"
size="small"
@click="addPerson"
:disabled="!ryqkEditMode">新增人员</el-button>
</div>
<el-table :data="ryqkList" border>
<el-table-column type="index" width="50" align="center" label="序号" />
<el-table-column label="姓名" align="center" prop="ryxm" width="120">
<template slot-scope="scope">
<el-input
v-model="scope.row.ryxm"
placeholder="请输入姓名"
:disabled="!ryqkEditMode"></el-input>
</template>
</el-table-column>
<el-table-column label="联系电话" align="center" prop="lxdh" width="150">
<template slot-scope="scope">
<el-input
v-model="scope.row.lxdh"
placeholder="请输入联系电话"
:disabled="!ryqkEditMode"></el-input>
</template>
</el-table-column>
<el-table-column label="状态" align="center" prop="ryzt" width="100">
<template slot-scope="scope">
<el-select
v-model="scope.row.ryzt"
placeholder="请选择状态"
style="width: 100%;"
:disabled="!ryqkEditMode">
<el-option
v-for="item in ryztOptions"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="bz">
<template slot-scope="scope">
<el-input
v-model="scope.row.bz"
placeholder="请输入备注"
:disabled="!ryqkEditMode"></el-input>
</template>
</el-table-column>
</el-table>
</el-card>
</div>
<div slot="footer" class="dialog-footer">
<el-button @click="ryqkcancel">关 闭</el-button>
</div>
</el-dialog>
<!-- 添加或修改问题明细对话框 -->
<el-dialog title="图片" :visible.sync="tpopen" width="1600px" append-to-body>
<img :src="fjform.fjlj" width="1500px">
<div slot="footer" class="dialog-footer">
<el-button @click="tpcancel">关 闭</el-button>
</div>
</el-dialog>
<!-- 添加或修改问题明细对话框 -->
<el-dialog title="视频" :visible.sync="spopen" width="1200px" append-to-body>
<video-player
ref="videoPlayer"
class="video-player vjs-custom-skin"
:playsinline="true"
:options="playerOptions"/>
<div slot="footer" class="dialog-footer">
<el-button @click="spcancel">关 闭</el-button>
</div>
</el-dialog>
<el-dialog title="数据项采集" :visible.sync="sjxopen" width="900px" append-to-body>
<el-form
ref="dynamicForm"
label-width="80px"
:model="formData"
>
<el-row>
<el-divider>文本类型采集</el-divider>
<el-col :span="8" v-for="item in sjxlist.filter(item => item.sjlx === 'text')">
<dynamic-field
:key="item.id"
lx="TEXT"
:config="item"
:placeholder="item.cjts"
:label="item.sjxmc"
v-model="item.zdz"
:prop="item.sjxdm"
:required="item.sfbt === '1'"
@myblur="blurInput"
:disabled="item.disabled"
/>
</el-col>
</el-row>
<el-row>
<el-divider>数字类型采集</el-divider>
<el-col :span="6" v-for="item in sjxlist.filter(item => item.sjlx === 'number')">
<dynamic-field
:prop="item.sjxdm"
:key="item.id"
lx="NUMBER"
:config="item"
v-model="item.zdz"
:placeholder="item.cjts"
:label="item.sjxmc"
:required="item.sfbt === '1'"
@myblur="blurInput"
:disabled="item.disabled"
/>
</el-col>
</el-row>
<el-row>
<el-divider>日期类型采集</el-divider>
<el-col :span="8" v-for="item in sjxlist.filter(item => item.sjlx === 'date')">
<dynamic-field
:prop="item.sjxdm"
:key="item.id"
lx="DATE"
:config="item"
v-model="item.zdz"
:placeholder="item.cjts"
:label="item.sjxmc"
:required="item.sfbt === '1'"
@myblur="blurInput"
:disabled="item.disabled"
/>
</el-col>
</el-row>
<el-row>
<el-divider>图片类型采集</el-divider>
<el-col :span="12" v-for="item in sjxlist.filter(item => item.sjlx === 'image')">
<dynamic-field
:key="item.id"
lx="IMAGE"
:prop="item.sjxdm"
:config="item"
:placeholder="item.cjts"
:label="item.sjxmc"
v-model="item.zdz"
:required="item.sfbt === '1'"
@mychange="blurInput"
:disabled="item.disabled"
/>
</el-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="updateSjx">保存</el-button>
<el-button @click="sjxopen=false">关 闭</el-button>
</div>
</el-dialog>
<div style="float: right;margin-top: 15px;margin-right: 5px;">
<el-button type="primary" plain size="small" v-hasPermi="['yjzh:yjcz:czbc']" @click="submitForm">处置保存</el-button>
</div>
</div>
</div>
</template>
<script>
import {listCZMX, updataAll, listCzmxzd, updataYjzhYjxxZt, listCZZB, listFj, getRyqkZb, listRyqkMx, saveRyqkZb, saveRyqkMx,getsjxlist,updataAllSjx} from "@/api/yjcz/czmx";
import DynamicField from "@/views/yjzh/yjcz/czmx/DynamicField.vue";
export default {
name: "czmx",
props: {
zbid: '',
},
data() {
return {
// 遮罩层
loading: true,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
CZZBList:[],
// 处置明细表格数据
CZMXList: [],
zdCzmxList: {},
zdsfcz: [{
label: "未处置",
value: "0",
raw: {},
}, {
label: "已处置",
value: "1",
raw: {},
},
],
// 弹出层标题
title: "",
// 是否显示弹出层
open: false,
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 1000,
zbid: null,
},
sjxopen:false,
fjopen: false,
tpopen:false,
spopen:false,
playerOptions: {
playbackRates: [0.7, 1.0, 1.5, 2.0], //播放速度
autoplay: false, //如果true,浏览器准备好时开始回放。
muted: false, // 默认情况下将会消除任何音频。
loop: false, // 导致视频一结束就重新开始。
preload: "auto", // 建议浏览器在<video>加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频(如果浏览器支持)
language: "zh-CN",
aspectRatio: "16:9", // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")
fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。
sources: [],
//poster: require("/profile/upload/2023/11/21/1700552582344_20231121154319A002.mp4"), //你的封面地址
notSupportedMessage: "此视频暂无法播放,请稍后再试", //允许覆盖Video.js无法播放媒体源时显示的默认信息。
controlBar: {
timeDivider: true,
durationDisplay: true,
remainingTimeDisplay: false,
fullscreenToggle: true, //全屏按钮
},
},
fjform: {},
fjlist:[],
sjxlist:[],
formData: {},
formRules: {
},
saveable: true,
currentZbid: '', // 当前选择的应急信息ID
// 人员情况弹窗相关
ryqkOpen: false,
ryqkEditMode: false, // 编辑模式状态
ryqkDialogTitle: '人员状态实时情况', // 弹窗标题
ryqkData: {},
ryqkList: [],
jtfsOptions: [
{ label: '自驾', value: '自驾' },
{ label: '公司车辆', value: '公司车辆' },
{ label: '公共交通', value: '公共交通' }
],
dqztOptions: [
{ label: '已出发', value: '0' },
{ label: '已到达', value: '1' },
{ label: '工作中', value: '2' },
{ label: '已结束', value: '3' }
],
ryztOptions: [
{ label: '正常', value: '0' },
{ label: '异常', value: '1' }
]
};
},
components: {
DynamicField: DynamicField
},
created() {
listCzmxzd(null).then(response => {
var rows = response;
for (var key in rows) {
var data = rows[key];
this.zdCzmxList[data.czmxdm + "czmxmc"] = data.czmxmc;
this.zdCzmxList[data.czmxdm + "czmxnr"] = data.czmxnr;
}
this.getData();
this.getzbData()
});
},
methods: {
blurInput(e){
console.log("e触发",e)
if(e.value==null||e.value==""){
this.formData[e.field]= null;
}else {
this.formData[e.field]=e.value.toString()
this.$nextTick(() => {
this.$refs.dynamicForm.clearValidate(e.field);
});
}
},
updateSjx(){
let find1=this.sjxlist.find(item=> {
return (item.zdz==''|| item.zdz==null)&&item.sfbt=="1";
});
if(find1==null){
this.saveable = true;
}else {
this.saveable = false;
}
if (!this.saveable) {
this.$message.error('请填写必填项');
return;
}else {
console.log("this.sjxlist",this.sjxlist)
updataAllSjx(this.sjxlist).then(response=>{
this.sjxopen = false;
this.$message.success("保存成功");
})
}
},
sjxopen_m(row,type="pc"){
console.log("row",row)
getsjxlist(row.zbid,row.czmxdm,type).then(response=>{
this.sjxlist = response.rows;
this.sjxlist.forEach(item=>{
item.disabled=(type=="pc"?false:true);
})
this.sjxopen = true;
})
},
getzbData(){
listCZZB({zbid:this.zbid}).then(response=>{
this.CZZBList = response.rows;
})
},
/** 查询处置明细列表 */
getData() {
if (this.zbid == null) {
this.loading = false;
} else {
this.loading = true;
this.queryParams.zbid = this.zbid;
listCZMX(this.queryParams).then(response => {
var rows = response.rows;
for (var key in rows) {
var data = rows[key];
data.czmxmc = this.zdCzmxList[data.czmxdm + "czmxmc"];
data.czmxnr = this.zdCzmxList[data.czmxdm + "czmxnr"];
if (data.czzt == null || data.czzt != "1") {
data.czzt = "0";
data.czsj = null;
}
}
this.CZMXList = rows;
this.total = response.total;
this.loading = false;
});
}
},
handleChange(val) {
if (val.czzt == "1") {
val.czsj = new Date();
} else {
val.czsj = null;
}
},
/** 提交按钮 */
submitForm() {
var rows = this.CZMXList;
for (const key in rows) {
var row = rows[key];
console.log(row);
if (row.czsj != null && Object.prototype.toString.call(row.czsj) === '[object Date]') {
row.czsj = this.formatDate(row.czsj, "yyyy-MM-dd hh:mm:ss");
}
}
updataAll(rows).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
});
},
/**
* 格式化函数 , 给日期格式化
* date为 new Date()对象, fmt为 'yyyy-MM-dd hh:mm:ss'的格式
*/
formatDate(date, fmt) {
//获取年份
if (/(y+)/.test(fmt)) {
// 把数字变成字符串
let dateY = date.getFullYear() + "";
//RegExp.$1 在判断中出现过,且是括号括起来的,所以 RegExp.$1 就是 "yyyy"
fmt = fmt.replace(RegExp.$1, dateY.substr(4 - RegExp.$1.length));
}
//获取其他
let o = {
"M+": date.getMonth() + 1,
"d+": date.getDate(),
"h+": date.getHours(),
"m+": date.getMinutes(),
"s+": date.getSeconds(),
};
for (const k in o) {
if (new RegExp(`(${k})`).test(fmt)) {
let str = o[k] + "";
fmt = fmt.replace(
RegExp.$1,
RegExp.$1.length == 1 ? str : this.padLeftZero(str)
);
}
}
return fmt;
},
padLeftZero(str) {
return ("00" + str).substr(str.length);
},
isImage(url) {
// 检查文件扩展名是否为常见的图片格式
return /\.(gif|jpg|jpeg|png|bmp|GIF|JPG|PNG)$/.test(url);
},
fjck(row){
console.log(row)
listFj(this.queryParams).then(response=>{
this.fjlist = response.rows;
})
this.fjopen=true;
},
fjcancel(){
this.fjopen=false;
},
// 取消按钮
tpcancel() {
this.tpopen = false;
},
// 取消按钮
spcancel() {
this.spopen = false;
},
click(row) {
this.fjform = row;
if(row.fjlx == 'SP'){
this.playerOptions.sources = [
{
type: "video/mp4",
src: row.fjlj, //视频url地址
},
];
this.spopen = true;
}else if(row.fjlx == 'TP') {
this.tpopen = true;
}
},
// 人员情况查看
ryqkck(row) {
console.log('=== 人员情况查看 ===');
console.log('传入的row:', row);
// 如果传入的是行对象,说明是从按钮点击触发的
if (row && row.zbid) {
this.currentZbid = row.zbid;
} else {
// 如果没有传入行对象,使用当前zbid
this.currentZbid = this.zbid;
}
console.log('当前应急信息ID (currentZbid):', this.currentZbid);
if (!this.currentZbid) {
this.$modal.msgError("请先选择应急信息");
return;
}
// 重置编辑模式
this.ryqkEditMode = false;
this.ryqkDialogTitle = '人员状态实时情况';
// 获取人员情况主表数据
getRyqkZb(this.currentZbid).then(response => {
console.log('主表查询响应:', response);
this.ryqkData = response.data && response.data.length > 0 ? response.data[0] : {};
console.log('主表数据 (ryqkData):', this.ryqkData);
// 如果没有数据,设置默认的填报人信息
if (!this.ryqkData.ddldXm) {
// 获取当前登录用户信息
const username = this.$store.state.user.name || '当前用户';
const phonenumber = this.$store.state.user.phonenumber || '';
this.ryqkData.ddldXm = username;
this.ryqkData.ddldSj = phonenumber;
console.log('设置默认填报人信息:', { username, phonenumber });
}
// 如果有主表数据且有ID,则用主表ID查询明细
if (this.ryqkData && this.ryqkData.id) {
console.log('使用主表ID查询明细,主表ID:', this.ryqkData.id);
listRyqkMx(this.ryqkData.id).then(response => {
console.log('明细查询响应:', response);
this.ryqkList = response.data || [];
console.log('明细数据 (ryqkList):', this.ryqkList);
this.ryqkOpen = true;
});
} else {
// 如果没有主表数据,则明细为空
console.log('没有主表数据,明细为空');
this.ryqkList = [];
this.ryqkOpen = true;
}
});
},
// 重新获取人员数据(用于取消编辑时恢复)
getPersonnelData() {
if (!this.currentZbid) return;
getRyqkZb(this.currentZbid).then(response => {
this.ryqkData = response.data && response.data.length > 0 ? response.data[0] : {};
// 如果有主表数据且有ID,则用主表ID查询明细
if (this.ryqkData && this.ryqkData.id) {
listRyqkMx(this.ryqkData.id).then(response => {
this.ryqkList = response.data || [];
});
} else {
this.ryqkList = [];
}
});
},
// 关闭人员情况弹窗
ryqkcancel() {
this.ryqkOpen = false;
this.ryqkData = {};
this.ryqkList = [];
this.currentZbid = '';
this.ryqkEditMode = false;
this.ryqkDialogTitle = '人员状态实时情况';
},
// 切换编辑模式
toggleEditMode() {
if (this.ryqkEditMode) {
// 取消编辑,恢复原始数据
this.getPersonnelData();
}
this.ryqkEditMode = !this.ryqkEditMode;
this.ryqkDialogTitle = this.ryqkEditMode ? '编辑人员状态实时情况' : '人员状态实时情况';
},
// 保存人员情况数据
saveRyqkData() {
console.log('=== 开始保存人员情况数据 ===');
console.log('当前应急信息ID (currentZbid):', this.currentZbid);
console.log('主表数据 (ryqkData):', this.ryqkData);
console.log('明细数据 (ryqkList):', this.ryqkList);
// 验证必填字段
if (!this.ryqkData.jtfs) {
this.$modal.msgError('请选择交通方式');
return;
}
if (!this.ryqkData.ddldXm) {
this.$modal.msgError('填报人不能为空');
return;
}
// 验证人员明细必填字段
for (let i = 0; i < this.ryqkList.length; i++) {
const person = this.ryqkList[i];
if (!person.ryxm || person.ryxm.trim() === '') {
this.$modal.msgError(`第${i + 1}行人员姓名不能为空`);
return;
}
if (!person.lxdh || person.lxdh.trim() === '') {
this.$modal.msgError(`第${i + 1}行联系电话不能为空`);
return;
}
if (!person.ryzt) {
this.$modal.msgError(`第${i + 1}行人员状态不能为空`);
return;
}
}
// 格式化日期字段
const formatDateTime = (date) => {
if (!date) return null;
if (typeof date === 'string') {
// 如果已经是字符串格式,尝试转换
date = new Date(date);
}
if (date instanceof Date && !isNaN(date)) {
return this.formatDate(date, 'yyyy-MM-dd hh:mm:ss');
}
return null;
};
// 保存主表数据
const mainData = {
...this.ryqkData,
yjzbid: this.currentZbid,
ddldSj: this.ryqkData.ddldSj || '', // 联系电话(驼峰命名)
ddldXm: this.ryqkData.ddldXm || '', // 填报人(驼峰命名)
dqzt: this.ryqkData.dqzt || '0', // 默认状态
// 格式化所有日期字段
sjksdysj: formatDateTime(this.ryqkData.sjksdysj),
ddsj: formatDateTime(this.ryqkData.ddsj),
ksgzsj: formatDateTime(this.ryqkData.ksgzsj),
qyjssj: formatDateTime(this.ryqkData.qyjssj)
};
console.log('准备保存的主表数据:', mainData);
saveRyqkZb(mainData).then(response => {
// 获取主表保存后返回的ID(这是YJCZ_RYQK_ZB的主键ID)
const ryqkZbId = response.data;
console.log('主表保存成功,完整响应:', response);
console.log('主表保存成功,返回ID:', ryqkZbId);
// 验证返回的ID是否有效
if (!ryqkZbId) {
console.error('主表保存成功但返回的ID为空!');
this.$modal.msgError('保存失败:未获取到主表ID');
return;
}
// 只有当有人员数据时才保存明细表
if (this.ryqkList && this.ryqkList.length > 0) {
// 保存明细表数据,使用主表返回的ID作为zbid
const detailData = this.ryqkList.map((item, index) => ({
zbid: ryqkZbId, // 使用人员情况主表的ID,而不是应急信息ID
pxh: index + 1, // 设置排序号
ryxm: item.ryxm || '', // 确保姓名不为空
lxdh: item.lxdh || '', // 确保电话不为空
ryzt: item.ryzt || '0', // 确保状态不为空
bz: item.bz || '' // 备注可以为空
}));
console.log('准备保存的人员明细数据:', detailData);
saveRyqkMx(detailData).then(response => {
console.log('明细保存成功,响应:', response);
this.$modal.msgSuccess('保存成功');
// 退出编辑模式
this.toggleEditMode();
}).catch(error => {
console.error('保存明细数据失败,完整错误:', error);
console.error('错误响应:', error.response);
const errorMsg = error.response && error.response.data && error.response.data.msg
? error.response.data.msg
: '保存人员信息失败';
this.$modal.msgError(errorMsg);
});
} else {
// 没有人员数据时,只保存主表,直接显示成功
console.log('无人员明细数据,仅保存主表');
this.$modal.msgSuccess('保存成功');
// 退出编辑模式
this.toggleEditMode();
}
}).catch(error => {
console.error('保存主表数据失败:', error);
this.$modal.msgError('保存基本信息失败');
});
},
// 新增人员
addPerson() {
this.ryqkList.push({
ryxm: '',
lxdh: '',
ryzt: '0',
bz: ''
});
},
// 人员编辑(直接进入编辑模式)
ryqkEdit(row) {
// 如果传入的是行对象,说明是从按钮点击触发的
if (row && row.zbid) {
this.currentZbid = row.zbid;
} else {
// 如果没有传入行对象,使用当前zbid
this.currentZbid = this.zbid;
}
if (!this.currentZbid) {
this.$modal.msgError("请先选择应急信息");
return;
}
// 设置为编辑模式
this.ryqkEditMode = true;
this.ryqkDialogTitle = '编辑人员状态实时情况';
// 获取人员情况主表数据
getRyqkZb(this.currentZbid).then(response => {
this.ryqkData = response.data && response.data.length > 0 ? response.data[0] : {};
// 如果没有数据,设置默认的填报人信息
if (!this.ryqkData.ddldXm) {
// 获取当前登录用户信息
const username = this.$store.state.user.name || '当前用户';
const phonenumber = this.$store.state.user.phonenumber || '';
this.ryqkData.ddldXm = username;
this.ryqkData.ddldSj = phonenumber;
}
// 如果有主表数据且有ID,则用主表ID查询明细
if (this.ryqkData && this.ryqkData.id) {
listRyqkMx(this.ryqkData.id).then(response => {
this.ryqkList = response.data || [];
this.ryqkOpen = true;
});
} else {
// 如果没有主表数据,则明细为空
this.ryqkList = [];
this.ryqkOpen = true;
}
});
}
}
};
</script>
<style scoped>
.ryqk-container {
padding: 20px;
}
.info-card, .list-card {
margin-bottom: 20px;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.card-header span {
font-size: 16px;
font-weight: bold;
}
.info-content {
display: flex;
flex-direction: column;
gap: 15px;
}
.info-row {
display: flex;
gap: 20px;
}
.info-item {
display: flex;
align-items: center;
min-width: 300px;
}
.info-item label {
width: 120px;
text-align: right;
margin-right: 10px;
font-weight: normal;
color: #606266;
}
.info-item .el-input,
.info-item .el-select,
.info-item .el-date-picker {
flex: 1;
}
@media (max-width: 1600px) {
.info-row {
flex-direction: column;
}
.info-item {
min-width: 100%;
}
.info-item label {
text-align: left;
margin-right: 0;
margin-bottom: 5px;
}
}
</style>