diff --git a/src/request/safety_production_related.js b/src/request/safety_production_related.js index 10ef43d..d3a3a77 100644 --- a/src/request/safety_production_related.js +++ b/src/request/safety_production_related.js @@ -1,18 +1,35 @@ -import { post,upload } from "@/request/axios.js"; -import {getLevelsByParentId} from "@/request/data_dictionary.js"; -import {ref} from "vue"; +import { post, upload } from "@/request/axios.js"; +import { getLevelsByParentId } from "@/request/data_dictionary.js"; +import { ref } from "vue"; -export const getSecurityNoticeList = (params) => post("/securitynotice/listForSecurityNotice", params); // 安全通知列表 -export const getSecurityNotice = (params) => post("/securitynotice/getAllReadDetail", params); // 阅读详情 -export const dateteSecurityNotice = (params) => post("/securitynotice/delete", params); // 安全通知删除 -export const getSecurityNoticeInfo = (params) => post("/securitynotice/goEdit", params); // 安全通知详情 -export const addSecurityNotice = (params) => upload("/securitynotice/add", params); // 添加安全通知 +export const getSecurityNoticeList = (params) => + post("/securitynotice/listForSecurityNotice", params); // 安全通知列表 +export const getSecurityNotice = (params) => + post("/securitynotice/getAllReadDetail", params); // 阅读详情 +export const dateteSecurityNotice = (params) => + post("/securitynotice/delete", params); // 安全通知删除 +export const getSecurityNoticeInfo = (params) => + post("/securitynotice/goEdit", params); // 安全通知详情 +export const addSecurityNotice = (params) => + upload("/securitynotice/add", params); // 添加安全通知 export const getUserListAll = (params) => post("/user/listUserByCorp", params); export const layoutFnGetNotificationsClassification = async () => { - const resData = await getLevelsByParentId({ - parentId: "aaecb47d95524b84904809671e48a777", - }); - return ref(resData); + const resData = await getLevelsByParentId({ + parentId: "aaecb47d95524b84904809671e48a777", + }); + return ref(resData); }; +export const layoutFnGetSIGNEDSTATUSClassification = async () => { + const resData = await getLevelsByParentId({ + parentId: "bbecb47d95524b84904809671e48a777", + }); + return ref(resData); +}; +export const layoutFnGetMEETINGTYPEClassification = async () => { + const resData = await getLevelsByParentId({ + parentId: "eeeec1cbabe7406083994447d00d0d4a", + }); + return ref(resData); +}; diff --git a/src/request/traffic_driving_log.js b/src/request/traffic_driving_log.js new file mode 100644 index 0000000..9493712 --- /dev/null +++ b/src/request/traffic_driving_log.js @@ -0,0 +1,9 @@ +import { post } from "@/request/axios.js"; +export const getSafetyDrivingLogList = (params) => + post("/drivinglog/listForSafetyDrivingLog", params); // 行车日志列表 + +export const setDrivingLogDelete = (params) => + post("/drivinglog/delete", params); // 行车日志删除 + +export const getSafetyDrivingLogView = (params) => + post("/drivinglog/goEdit", params); // 安全例会详情 diff --git a/src/request/traffic_safety_meeting.js b/src/request/traffic_safety_meeting.js new file mode 100644 index 0000000..421704b --- /dev/null +++ b/src/request/traffic_safety_meeting.js @@ -0,0 +1,14 @@ +import { post, upload } from "@/request/axios.js"; +export const getSafetyMeetingList = (params) => + post("/safetymeeting/listForSafetyMeeting", params); // 安全例会列表 + +export const setSafetyMeetingDelete = (params) => + post("/safetymeeting/delete", params); // 安全例会删除 + +export const getSafetyMeetingView = (params) => + post("/safetymeeting/goEdit", params); // 安全例会详情 + +export const addSafetyMeetingView = (params) => + upload("/safetymeeting/add", params); // 添加安全通知 +export const getSafetyMeetingRecipient = (params) => + post("/safetymeeting/getAllRecipient", params); // 参会人员 diff --git a/src/views/safety_production_related/driving_log/add.vue b/src/views/safety_production_related/driving_log/add.vue new file mode 100644 index 0000000..a93807e --- /dev/null +++ b/src/views/safety_production_related/driving_log/add.vue @@ -0,0 +1,229 @@ +<template> + <layout-card> + <el-form + ref="formRef" + :model="data.form" + :rules="rules" + label-width="175px" + > + <el-divider content-position="left">添加</el-divider> + <el-row> + <el-col :span="8"> + <el-form-item label="会议标题" prop="MEETING_TITLE"> + <el-input + v-model="data.form.MEETING_TITLE" + placeholder="请输入会议标题" + /> + </el-form-item> + </el-col> + <el-col :span="5"> + <el-form-item label="会议类型" prop="MEETING_TYPE"> + <el-select + v-model="data.form.MEETING_TYPE" + placeholder="请选择会议类型" + @change="handleMeetingTypeChange" + > + <el-option + v-for="item in relatedClassificationList" + :key="item.BIANMA" + :label="item.NAME" + :value="item.BIANMA" + /> + </el-select> + </el-form-item> + </el-col> + <el-col :span="8"> + <el-form-item label="运输企业" prop="TRANSPORTATIONCOMPANY"> + <el-input + v-model="data.form.TRANSPORTATIONCOMPANY" + placeholder="请输入运输企业" + /> + </el-form-item> + </el-col> + <el-col :span="8"> + <el-form-item label="会议地点" prop="MEETING_ADDRESS"> + <el-input + v-model="data.form.MEETING_ADDRESS" + placeholder="请输入会议地点" + /> + </el-form-item> + </el-col> + <el-col :span="10"> + <el-form-item prop="MEETING_DATE" label="会议时间"> + <el-date-picker + type="daterange" + v-model="data.form.MEETING_DATE" + format="YYYY-MM-DD" + value-format="YYYY-MM-DD" + start-placeholder="开始时间" + end-placeholder="结束时间" + /> + </el-form-item> + </el-col> + <el-col :span="8"> + <el-form-item label="主持人" prop="HOST_PERSON"> + <el-input + v-model="data.form.HOST_PERSON" + placeholder="请输入主持人" + /> + </el-form-item> + </el-col> + <el-col :span="8"> + <el-form-item label="记录人" prop="RECORDER"> + <el-input v-model="data.form.RECORDER" placeholder="请输入记录人" /> + </el-form-item> + </el-col> + <el-col :span="8"> + <el-form-item label="从业身份" prop="PRACTITIONER_TYPE"> + <el-checkbox-group + v-model="data.form.PRACTITIONER_TYPE" + @change="handleCheckedCitiesChange" + > + <el-checkbox v-for="city in cities" :key="city" :label="city">{{ + city + }}</el-checkbox> + </el-checkbox-group> + </el-form-item> + </el-col> + + <el-col :span="24"> + <el-form-item label="会议附件" prop="fileList"> + <layout-upload + v-model:file-list="data.form.fileList" + accept=".pdf,.mp4" + delete-to-server + :limit="9" + /> + </el-form-item> + </el-col> + <el-col :span="50"> + <el-form-item label="会议记要" prop="MEETING_CONTENT"> + <layout-editor + v-model="data.form.MEETING_CONTENT" + placeholder="请输入内容" + /> + </el-form-item> + </el-col> + </el-row> + </el-form> + <div class="tc mt-10"> + <el-button type="primary" @click="fnSubmit"> 确定 </el-button> + </div> + </layout-card> +</template> + +<script setup> +import { + layoutFnGetMEETINGTYPEClassification, + getUserListAll, +} from "@/request/safety_production_related.js"; +import { addSafetyMeetingView } from "@/request/traffic_safety_meeting.js"; +import { reactive, ref } from "vue"; +import LayoutUpload from "@/components/upload/index.vue"; +import LayoutEditor from "@/components/editor/index.vue"; +import useFormValidate from "@/assets/js/useFormValidate.js"; +import { ElMessage } from "element-plus"; +const formRef = ref(null); +const cities = [ + "驾驶员", + "押运员", + "安全管理员", + "装卸员", + "安全负责人", + "其他", + "监控员", +]; +const handleCheckedCitiesChange = () => {}; +const rules = { + MEETING_TITLE: [ + { required: true, message: "请输入会议标题", trigger: "blur" }, + ], + MEETING_TYPE: [ + { required: true, message: "请选择会议类型", trigger: "change" }, + ], + TRANSPORTATIONCOMPANY: [ + { required: true, message: "请输入运输企业", trigger: "blur" }, + ], + MEETING_ADDRESS: [ + { required: true, message: "请输入会议地点", trigger: "blur" }, + ], + MEETING_DATE: [ + { required: true, message: "请选择会议时间", trigger: "change" }, + ], + HOST_PERSON: [{ required: true, message: "请输入主持人", trigger: "blur" }], + RECORDER: [{ required: true, message: "请输入记录人", trigger: "blur" }], + MEETING_CONTENT: [ + { required: true, message: "请输入会议记要", trigger: "blur" }, + ], +}; + +const fnGetUnitsList = async () => { + const resData = await getUserListAll({}); + data.unitsList = resData.varList; +}; +fnGetUnitsList(); +const relatedClassificationTempList = + await layoutFnGetMEETINGTYPEClassification(); +const relatedClassificationList = []; +JSON.parse(relatedClassificationTempList.value.zTreeNodes).forEach((e) => { + relatedClassificationList.push({ name: e.id, BIANMA: e.name }); +}); + +const data = reactive({ + form: { + MEETING_TITLE: "", + MEETING_TYPE: "", + TRANSPORTATIONCOMPANY: "", + MEETING_ADDRESS: "", + MEETING_DATE: "", + HOST_PERSON: "", + RECORDER: "", + fileList: [], + PRACTITIONER_TYPE: [], + NOTIFICATIONCONTENT: "", + }, +}); +const handleMeetingTypeChange = (value) => { + data.form.MEETING_TYPE = value; +}; +const fnSubmit = async () => { + await useFormValidate(formRef); + const formData = new FormData(); + + Object.keys(data.form).forEach((key) => { + formData.append(key, data.form[key]); + }); + + formData.delete("fileList"); + + for (let i = 0; i < data.form.fileList.length; i++) { + if (data.form.fileList[i].raw) + formData.append("FFILE", data.form.fileList[i].raw); + } + + try { + await addSafetyMeetingView(formData); + ElMessage.success("添加成功"); + Object.keys(data.form).forEach((key) => { + if (Array.isArray(data.form[key])) { + data.form[key] = []; + } else { + data.form[key] = ""; + } + }); + } catch (error) { + ElMessage.error("添加失败"); + } +}; +</script> + +<style scoped lang="scss"> +.flexBox { + display: flex; + align-items: flex-end; + + .addBtn { + margin-left: 12px; + } +} +</style> diff --git a/src/views/safety_production_related/driving_log/drivingLog_info.vue b/src/views/safety_production_related/driving_log/drivingLog_info.vue new file mode 100644 index 0000000..2d3e7c5 --- /dev/null +++ b/src/views/safety_production_related/driving_log/drivingLog_info.vue @@ -0,0 +1,340 @@ +<template> + <div> + <layout-card> + <el-row :gutter="20"> + <el-col :span="24"> + <el-descriptions :column="2" border> + <el-descriptions-item label="会议标题"> + {{ detailItems.WAYBILLNUMBER }} + </el-descriptions-item> + <el-descriptions-item label="运输企业"> + {{ detailItems.TRANSPORTATIONCOMPANY }} + </el-descriptions-item> + <el-descriptions-item label="运输任务"> + <el-row :gutter="20"> + <el-col :span="6"> + <el-descriptions :column="1" border> + <el-descriptions-item label="运输车辆"> + {{ detailItems.TRANSPORTVEHICLE }} + </el-descriptions-item> + </el-descriptions> + </el-col> + <el-col :span="6"> + <el-descriptions :column="1" border> + <el-descriptions-item label="运输性能"> + {{ detailItems.TRANSPORTNATURE }} + </el-descriptions-item> + </el-descriptions> + </el-col> + <el-col :span="6"> + <el-descriptions :column="1" border> + <el-descriptions-item label="发车时间"> + {{ detailItems.DEPARTURETIME }} + </el-descriptions-item> + </el-descriptions> + </el-col> + <el-col :span="6"> + <el-descriptions :column="1" border> + <el-descriptions-item label="发车地点"> + {{ detailItems.DEPARTUREPLACE }} + </el-descriptions-item> + </el-descriptions> + </el-col> + <el-col :span="6"> + <el-descriptions :column="1" border> + <el-descriptions-item label="车架号"> + {{ detailItems.FRAMENUMBER }} + </el-descriptions-item> + </el-descriptions> + </el-col> + <el-col :span="6"> + <el-descriptions :column="1" border> + <el-descriptions-item label="从业人员"> + {{ detailItems.EMPLOYEES }} + </el-descriptions-item> + </el-descriptions> + </el-col> + <el-col :span="6"> + <el-descriptions :column="1" border> + <el-descriptions-item label="收车时间"> + {{ detailItems.ARRIVALTIME }} + </el-descriptions-item> + </el-descriptions> + </el-col> + <el-col :span="6"> + <el-descriptions :column="1" border> + <el-descriptions-item label="收车地点"> + {{ detailItems.ARRIVALPLACE }} + </el-descriptions-item> + </el-descriptions> + </el-col> + <el-col :span="6"> + <el-descriptions :column="1" border> + <el-descriptions-item label="天气情况"> + {{ detailItems.WEATHERCONDITION }} + </el-descriptions-item> + </el-descriptions> + </el-col> + <el-col :span="6"> + <el-descriptions :column="1" border> + <el-descriptions-item label="联系电话"> + {{ detailItems.CONTACTPHONE }} + </el-descriptions-item> + </el-descriptions> + </el-col> + <el-col :span="6"> + <el-descriptions :column="1" border> + <el-descriptions-item label="额定载荷"> + {{ detailItems.RATEDLOAD }} + </el-descriptions-item> + </el-descriptions> + </el-col> + <el-col :span="6"> + <el-descriptions :column="1" border> + <el-descriptions-item label="实际载荷"> + {{ detailItems.ACTUALLOAD }} + </el-descriptions-item> + </el-descriptions> + </el-col> + </el-row> + </el-descriptions-item> + </el-descriptions> + <el-descriptions :column="1" border> + <el-descriptions-item label="行车安全问询"> + {{ detailItems.DRIVINGSAFETYINQUIRY }} + </el-descriptions-item> + </el-descriptions> + <el-descriptions :column="1" border> + <el-descriptions-item label="出车前检查"> + <el-row :gutter="20"> + <el-col :span="6"> + <el-descriptions :column="1" border> + <el-descriptions-item label="检查人"> + {{ detailItems.PREDEPARTUREINSPECTOR }} + </el-descriptions-item> + </el-descriptions> + </el-col> + <el-col :span="6"> + <el-descriptions :column="1" border> + <el-descriptions-item label="检查时间"> + {{ detailItems.PREDEPARTUREINSPECTIONTIME }} + </el-descriptions-item> + </el-descriptions> + </el-col> + <el-col :span="6"> + <el-descriptions :column="1" border> + <el-descriptions-item label="故障处理"> + {{ detailItems.PREDEPARTUREFAULTTREATMENT }} + </el-descriptions-item> + </el-descriptions> + </el-col> + <el-col :span="6"> + <el-descriptions :column="1" border> + <el-descriptions-item label="出车结论"> + {{ detailItems.DEPARTURECONCLUSION }} + </el-descriptions-item> + </el-descriptions> + </el-col> + <el-col :span="6"> + <el-descriptions :column="1" border> + <el-descriptions-item label="出车前照片"> + {{ detailItems.PREDEPARTUREPHOTO }} + </el-descriptions-item> + </el-descriptions> + </el-col> + <el-col :span="6"> + <el-descriptions :column="1" border> + <el-descriptions-item label="出车前签字"> + {{ detailItems.PREDEPARTURESIGNATURE }} + </el-descriptions-item> + </el-descriptions> + </el-col> + </el-row> + </el-descriptions-item> + </el-descriptions> + <el-descriptions :column="1" border> + <el-descriptions-item label="行车中检查"> + <el-row :gutter="20"> + <el-col :span="6"> + <el-descriptions :column="1" border> + <el-descriptions-item label="检查人"> + {{ detailItems.INDRIVINGINSPECTOR }} + </el-descriptions-item> + </el-descriptions> + </el-col> + <el-col :span="6"> + <el-descriptions :column="1" border> + <el-descriptions-item label="检查时间"> + {{ detailItems.INSPECTIONTIMEWHILEDRIVING }} + </el-descriptions-item> + </el-descriptions> + </el-col> + <el-col :span="6"> + <el-descriptions :column="1" border> + <el-descriptions-item label="故障处理"> + {{ detailItems.INDRIVINGFAULTTREATMENT }} + </el-descriptions-item> + </el-descriptions> + </el-col> + <el-col :span="6"> + <el-descriptions :column="1" border> + <el-descriptions-item label="行车中照片"> + {{ detailItems.PHOTOSWHILEDRIVING }} + </el-descriptions-item> + </el-descriptions> + </el-col> + <el-col :span="6"> + <el-descriptions :column="1" border> + <el-descriptions-item label="行车中签字"> + {{ detailItems.SIGNINGWHILEDRIVING }} + </el-descriptions-item> + </el-descriptions> + </el-col> + </el-row> + </el-descriptions-item> + </el-descriptions> + <el-descriptions :column="1" border> + <el-descriptions-item label="收车后检查"> + <el-row :gutter="20"> + <el-col :span="6"> + <el-descriptions :column="1" border> + <el-descriptions-item label="检查人"> + {{ detailItems.POSTARRIVALINSPECTOR }} + </el-descriptions-item> + </el-descriptions> + </el-col> + <el-col :span="6"> + <el-descriptions :column="1" border> + <el-descriptions-item label="检查时间"> + {{ detailItems.POSTARRIVALINSPECTIONTIME }} + </el-descriptions-item> + </el-descriptions> + </el-col> + <el-col :span="6"> + <el-descriptions :column="1" border> + <el-descriptions-item label="故障处理"> + {{ detailItems.POSTARRIVALFAULTTREATMENT }} + </el-descriptions-item> + </el-descriptions> + </el-col> + <el-col :span="6"> + <el-descriptions :column="1" border> + <el-descriptions-item label="收车后照片"> + {{ detailItems.CHECKPHOTOS }} + </el-descriptions-item> + </el-descriptions> + </el-col> + <el-col :span="6"> + <el-descriptions :column="1" border> + <el-descriptions-item label="收车后签字"> + {{ detailItems.CHECKSIGNATURE }} + </el-descriptions-item> + </el-descriptions> + </el-col> + </el-row> + </el-descriptions-item> + </el-descriptions> + <el-descriptions :column="1" border> + <el-descriptions-item label="交接班记录"> + <el-row :gutter="20"> + <el-col :span="6"> + <el-descriptions :column="1" border> + <el-descriptions-item label="驾驶时长"> + {{ detailItems.DRIVINGDURATION }} + </el-descriptions-item> + </el-descriptions> + </el-col> + <el-col :span="6"> + <el-descriptions :column="1" border> + <el-descriptions-item label="时间区间"> + {{ detailItems.TIMEINTERVAL }} + </el-descriptions-item> + </el-descriptions> + </el-col> + <el-col :span="6"> + <el-descriptions :column="1" border> + <el-descriptions-item label="交接地点"> + {{ detailItems.HANDOVERPLACE }} + </el-descriptions-item> + </el-descriptions> + </el-col> + <el-col :span="6"> + <el-descriptions :column="1" border> + <el-descriptions-item label="交接班人"> + {{ detailItems.HANDOVERPERSON }} + </el-descriptions-item> + </el-descriptions> + </el-col> + <el-col :span="6"> + <el-descriptions :column="1" border> + <el-descriptions-item label="接班图片"> + {{ detailItems.RELIEFPICTURE }} + </el-descriptions-item> + </el-descriptions> + </el-col> + </el-row> + </el-descriptions-item> + </el-descriptions> + <el-descriptions :column="1" border> + <el-descriptions-item label="安全负责人"> + {{ detailItems.SAFETYOFFICER }} + </el-descriptions-item> + </el-descriptions> + </el-col> + </el-row> + </layout-card> + </div> +</template> + +<script setup> +import { onMounted, reactive } from "vue"; +import { getSafetyDrivingLogView } from "@/request/traffic_driving_log.js"; +import { useRoute } from "vue-router"; +const route = useRoute(); +const { DRIVING_LOG_ID } = route.query; +const detailItems = reactive({ + WAYBILLNUMBER: "", + TRANSPORTATIONCOMPANY: "", + TRANSPORTVEHICLE: "", + TRANSPORTNATURE: "", + DEPARTURETIME: "", + DEPARTUREPLACE: "", + FRAMENUMBER: "", + EMPLOYEES: "", + ARRIVALTIME: "", + ARRIVALPLACE: "", + WEATHERCONDITION: "", + CONTACTPHONE: "", + ACTUALLOAD: "", + DRIVINGSAFETYINQUIRY: "", + DEPARTURECONCLUSION: "", + PREDEPARTUREINSPECTOR: "", + PREDEPARTUREINSPECTIONTIME: "", + PREDEPARTUREFAULTTREATMENT: "", + INDRIVINGINSPECTOR: "", + INSPECTIONTIMEWHILEDRIVING: "", + INDRIVINGFAULTTREATMENT: "", + POSTARRIVALINSPECTOR: "", + POSTARRIVALINSPECTIONTIME: "", + POSTARRIVALFAULTTREATMENT: "", + DRIVINGDURATION: "", + TIMEINTERVAL: "", + HANDOVERPLACE: "", + HANDOVERPERSON: "", + RELIEFPICTURE: "", + SAFETYOFFICER: "", + PREDEPARTUREPHOTO: "", + PREDEPARTURESIGNATURE: "", + PHOTOSWHILEDRIVING: "", + SIGNINGWHILEDRIVING: "", + CHECKPHOTOS: "", + CHECKSIGNATURE: "", +}); + +onMounted(async () => { + const response = await getSafetyDrivingLogView({ DRIVING_LOG_ID }); + Object.assign(detailItems, response.pd); +}); +</script> + +<style scoped></style> diff --git a/src/views/safety_production_related/driving_log/index.vue b/src/views/safety_production_related/driving_log/index.vue new file mode 100644 index 0000000..8ebaf79 --- /dev/null +++ b/src/views/safety_production_related/driving_log/index.vue @@ -0,0 +1,137 @@ +<template> + <div> + <el-card> + <el-form + :model="searchForm" + label-width="100px" + @submit.prevent="fnResetPagination" + > + <el-row> + <el-col :span="6"> + <el-form-item label="运输企业" prop="TRANSPORTCOMPANY"> + <el-input v-model="searchForm.TRANSPORTCOMPANY" /> + </el-form-item> + </el-col> + <el-col :span="6"> + <el-form-item label="运输车辆" prop="TRANSPORTVEHICLE"> + <el-input v-model="searchForm.TRANSPORTVEHICLE" /> + </el-form-item> + </el-col> + <el-col :span="6"> + <el-form-item label-width="10px"> + <el-button type="primary" native-type="submit">搜索</el-button> + <el-button native-type="reset" @click="fnResetPagination"> + 重置 + </el-button> + </el-form-item> + </el-col> + </el-row> + </el-form> + </el-card> + <layout-card> + <layout-table + :data="list" + @get-data="fnGetData" + v-model:pagination="pagination" + > + <el-table-column label="序号" width="60"> + <template #default="{ $index }"> + {{ serialNumber(pagination, $index) }} + </template> + </el-table-column> + <el-table-column + prop="REGISTRATIONNUMBER" + label="登记编号" + width="130" + /> + <el-table-column prop="DEPARTURESTATUS" label="出车状态" width="130" /> + <el-table-column prop="DRIVINGCONDITION" label="行车状态" width="130" /> + <el-table-column prop="TRANSPORTVEHICLE" label="运输车辆" width="130" /> + <el-table-column prop="EMPLOYEES" label="从业人员" width="130" /> + <el-table-column prop="CONTACTPHONE" label="联系电话" width="130" /> + <el-table-column prop="WEATHERCONDITION" label="天气预报" width="130" /> + <el-table-column prop="TRANSPORTNATURE" label="运输性质" width="130" /> + <el-table-column prop="DEPARTURETIME" label="发车时间" /> + <el-table-column prop="ARRIVALTIME" label="收车时间" /> + <el-table-column prop="TRANSPORTCOMPANY" label="运输企业" /> + <el-table-column label="操作" width="180"> + <template v-slot:default="{ row }"> + <el-button + type="primary" + text + link + @click=" + router.push({ + path: '/safety_production_related/driving_log/drivingLog_info', + query: { + DRIVING_LOG_ID: row.DRIVING_LOG_ID, + }, + }) + " + > + 查看 + </el-button> + <el-button + type="primary" + text + link + @click=" + router.push({ + path: '/safety_production_related/safety_meeting/add', + }) + " + > + 添加 + </el-button> + <el-button + type="danger" + text + link + @click="deleteItem(row.DRIVING_LOG_ID)" + > + 删除 + </el-button> + </template> + </el-table-column> + </layout-table> + </layout-card> + <edit + v-model:visible="data.analysisDialog.visible" + :info="data.analysisDialog.info" + @get-data="fnResetPagination" + /> + </div> +</template> + +<script setup> +import { serialNumber } from "@/assets/js/utils"; +import useListData from "@/assets/js/useListData.js"; +import { reactive } from "vue"; +import { + getSafetyDrivingLogList, + setDrivingLogDelete, +} from "@/request/traffic_driving_log.js"; +import router from "@/router/index.js"; +import { ElMessage, ElMessageBox } from "element-plus"; + +const { list, pagination, searchForm, fnGetData, fnResetPagination } = + useListData(getSafetyDrivingLogList); +const data = reactive({ + analysisDialog: { + visible: false, + info: {}, + }, +}); +// 删除事件 +const deleteItem = async (value) => { + await ElMessageBox.confirm(`确定要删除吗?`, { + type: "warning", + }); + console.log("Sent to backend:", { DRIVING_LOG_ID: value }); + await setDrivingLogDelete({ DRIVING_LOG_ID: value }); + ElMessage.success("删除成功"); + fnGetData(); +}; +</script> + +<style scoped></style> diff --git a/src/views/safety_production_related/safety_meeting/add.vue b/src/views/safety_production_related/safety_meeting/add.vue new file mode 100644 index 0000000..a93807e --- /dev/null +++ b/src/views/safety_production_related/safety_meeting/add.vue @@ -0,0 +1,229 @@ +<template> + <layout-card> + <el-form + ref="formRef" + :model="data.form" + :rules="rules" + label-width="175px" + > + <el-divider content-position="left">添加</el-divider> + <el-row> + <el-col :span="8"> + <el-form-item label="会议标题" prop="MEETING_TITLE"> + <el-input + v-model="data.form.MEETING_TITLE" + placeholder="请输入会议标题" + /> + </el-form-item> + </el-col> + <el-col :span="5"> + <el-form-item label="会议类型" prop="MEETING_TYPE"> + <el-select + v-model="data.form.MEETING_TYPE" + placeholder="请选择会议类型" + @change="handleMeetingTypeChange" + > + <el-option + v-for="item in relatedClassificationList" + :key="item.BIANMA" + :label="item.NAME" + :value="item.BIANMA" + /> + </el-select> + </el-form-item> + </el-col> + <el-col :span="8"> + <el-form-item label="运输企业" prop="TRANSPORTATIONCOMPANY"> + <el-input + v-model="data.form.TRANSPORTATIONCOMPANY" + placeholder="请输入运输企业" + /> + </el-form-item> + </el-col> + <el-col :span="8"> + <el-form-item label="会议地点" prop="MEETING_ADDRESS"> + <el-input + v-model="data.form.MEETING_ADDRESS" + placeholder="请输入会议地点" + /> + </el-form-item> + </el-col> + <el-col :span="10"> + <el-form-item prop="MEETING_DATE" label="会议时间"> + <el-date-picker + type="daterange" + v-model="data.form.MEETING_DATE" + format="YYYY-MM-DD" + value-format="YYYY-MM-DD" + start-placeholder="开始时间" + end-placeholder="结束时间" + /> + </el-form-item> + </el-col> + <el-col :span="8"> + <el-form-item label="主持人" prop="HOST_PERSON"> + <el-input + v-model="data.form.HOST_PERSON" + placeholder="请输入主持人" + /> + </el-form-item> + </el-col> + <el-col :span="8"> + <el-form-item label="记录人" prop="RECORDER"> + <el-input v-model="data.form.RECORDER" placeholder="请输入记录人" /> + </el-form-item> + </el-col> + <el-col :span="8"> + <el-form-item label="从业身份" prop="PRACTITIONER_TYPE"> + <el-checkbox-group + v-model="data.form.PRACTITIONER_TYPE" + @change="handleCheckedCitiesChange" + > + <el-checkbox v-for="city in cities" :key="city" :label="city">{{ + city + }}</el-checkbox> + </el-checkbox-group> + </el-form-item> + </el-col> + + <el-col :span="24"> + <el-form-item label="会议附件" prop="fileList"> + <layout-upload + v-model:file-list="data.form.fileList" + accept=".pdf,.mp4" + delete-to-server + :limit="9" + /> + </el-form-item> + </el-col> + <el-col :span="50"> + <el-form-item label="会议记要" prop="MEETING_CONTENT"> + <layout-editor + v-model="data.form.MEETING_CONTENT" + placeholder="请输入内容" + /> + </el-form-item> + </el-col> + </el-row> + </el-form> + <div class="tc mt-10"> + <el-button type="primary" @click="fnSubmit"> 确定 </el-button> + </div> + </layout-card> +</template> + +<script setup> +import { + layoutFnGetMEETINGTYPEClassification, + getUserListAll, +} from "@/request/safety_production_related.js"; +import { addSafetyMeetingView } from "@/request/traffic_safety_meeting.js"; +import { reactive, ref } from "vue"; +import LayoutUpload from "@/components/upload/index.vue"; +import LayoutEditor from "@/components/editor/index.vue"; +import useFormValidate from "@/assets/js/useFormValidate.js"; +import { ElMessage } from "element-plus"; +const formRef = ref(null); +const cities = [ + "驾驶员", + "押运员", + "安全管理员", + "装卸员", + "安全负责人", + "其他", + "监控员", +]; +const handleCheckedCitiesChange = () => {}; +const rules = { + MEETING_TITLE: [ + { required: true, message: "请输入会议标题", trigger: "blur" }, + ], + MEETING_TYPE: [ + { required: true, message: "请选择会议类型", trigger: "change" }, + ], + TRANSPORTATIONCOMPANY: [ + { required: true, message: "请输入运输企业", trigger: "blur" }, + ], + MEETING_ADDRESS: [ + { required: true, message: "请输入会议地点", trigger: "blur" }, + ], + MEETING_DATE: [ + { required: true, message: "请选择会议时间", trigger: "change" }, + ], + HOST_PERSON: [{ required: true, message: "请输入主持人", trigger: "blur" }], + RECORDER: [{ required: true, message: "请输入记录人", trigger: "blur" }], + MEETING_CONTENT: [ + { required: true, message: "请输入会议记要", trigger: "blur" }, + ], +}; + +const fnGetUnitsList = async () => { + const resData = await getUserListAll({}); + data.unitsList = resData.varList; +}; +fnGetUnitsList(); +const relatedClassificationTempList = + await layoutFnGetMEETINGTYPEClassification(); +const relatedClassificationList = []; +JSON.parse(relatedClassificationTempList.value.zTreeNodes).forEach((e) => { + relatedClassificationList.push({ name: e.id, BIANMA: e.name }); +}); + +const data = reactive({ + form: { + MEETING_TITLE: "", + MEETING_TYPE: "", + TRANSPORTATIONCOMPANY: "", + MEETING_ADDRESS: "", + MEETING_DATE: "", + HOST_PERSON: "", + RECORDER: "", + fileList: [], + PRACTITIONER_TYPE: [], + NOTIFICATIONCONTENT: "", + }, +}); +const handleMeetingTypeChange = (value) => { + data.form.MEETING_TYPE = value; +}; +const fnSubmit = async () => { + await useFormValidate(formRef); + const formData = new FormData(); + + Object.keys(data.form).forEach((key) => { + formData.append(key, data.form[key]); + }); + + formData.delete("fileList"); + + for (let i = 0; i < data.form.fileList.length; i++) { + if (data.form.fileList[i].raw) + formData.append("FFILE", data.form.fileList[i].raw); + } + + try { + await addSafetyMeetingView(formData); + ElMessage.success("添加成功"); + Object.keys(data.form).forEach((key) => { + if (Array.isArray(data.form[key])) { + data.form[key] = []; + } else { + data.form[key] = ""; + } + }); + } catch (error) { + ElMessage.error("添加失败"); + } +}; +</script> + +<style scoped lang="scss"> +.flexBox { + display: flex; + align-items: flex-end; + + .addBtn { + margin-left: 12px; + } +} +</style> diff --git a/src/views/safety_production_related/safety_meeting/details.vue b/src/views/safety_production_related/safety_meeting/details.vue new file mode 100644 index 0000000..75fd07d --- /dev/null +++ b/src/views/safety_production_related/safety_meeting/details.vue @@ -0,0 +1,140 @@ +<template> + <div> + <el-card> + <el-form + :model="searchForm" + label-width="100px" + @submit.prevent="searchNotifications" + > + <el-row> + <el-col :span="8"> + <el-form-item label="从业人员" prop="PRACTITIONER"> + <el-input v-model="searchForm.PRACTITIONER" /> + </el-form-item> + </el-col> + <el-col :span="8"> + <el-form-item label="从业类型" prop="PRACTITIONER_TYPE"> + <el-select v-model="searchForm.PRACTITIONER_TYPE"> + <el-option + v-for="item in relatedClassificationList" + :key="item.BIANMA" + :label="item.name" + :value="item.BIANMA" + /> + </el-select> + </el-form-item> + </el-col> + <el-col :span="8"> + <el-form-item label="联系电话" prop="CONTACT_PHONE"> + <el-input v-model="searchForm.CONTACT_PHONE" /> + </el-form-item> + </el-col> + <el-col :span="8"> + <el-form-item label="参会状态" prop="ATTENDANCE_STATUS"> + <el-select v-model="searchForm.ATTENDANCE_STATUS"> + <el-option label="已参会" :value="1" /> + <!-- 1代表已签收 --> + <el-option label="未参会" :value="0" /> + <!-- 0代表未签收 --> + </el-select> + </el-form-item> + </el-col> + <el-col :span="8"> + <el-form-item label="身份证号" prop="IDENTITY_NUMBER"> + <el-input v-model="searchForm.IDENTITY_NUMBER" /> + </el-form-item> + </el-col> + <el-col :span="8"> + <el-form-item> + <el-button type="primary" native-type="submit">搜索</el-button> + <el-button native-type="reset" @click="resetSearchForm" + >重置</el-button + > + </el-form-item> + </el-col> + </el-row> + </el-form> + </el-card> + <layout-card> + <layout-table + :data="list" + @get-data="fnGetData" + v-model:pagination="pagination" + stripe + border + show-header + > + <el-table-column label="序号" width="60"> + <template #default="{ $index }"> + {{ serialNumber(pagination, $index) }} + </template> + </el-table-column> + <el-table-column label="从业人员" prop="PRACTITIONER" /> + <el-table-column label="从业类型" prop="PRACTITIONER_TYPE" /> + <el-table-column label="身份证号" prop="IDENTITY_NUMBER" /> + <el-table-column label="联系电话" prop="CONTACT_PHONE" /> + <el-table-column label="参会状态" prop="ATTENDANCE_STATUS"> + <template #default="{ row }"> + <el-tag v-if="row.ATTENDANCE_STATUS === '1'">{{ "已参会" }}</el-tag> + <el-tag v-else>未参会</el-tag> + </template> + </el-table-column> + </layout-table> + </layout-card> + </div> +</template> + +<script setup> +import { reactive, onMounted, ref } from "vue"; +import { useRoute } from "vue-router"; +import { layoutFnGetSIGNEDSTATUSClassification } from "@/request/safety_production_related.js"; +import { getSafetyMeetingRecipient } from "@/request/traffic_safety_meeting.js"; +import { serialNumber } from "@/assets/js/utils"; +import useListData from "@/assets/js/useListData"; + +const route = useRoute(); +const SAFETY_MEETING_ID = route.query.SAFETY_MEETING_ID; + +const searchForm = reactive({ + PERSON: "", + PRACTITIONERTYPE: "", + SIGNEDSTATUS: null, + REPLYSTATUS: null, +}); + +const { list, pagination, fnGetData, fnResetPagination } = useListData( + getSafetyMeetingRecipient, + { + searchForm, + otherParams: { SAFETY_MEETING_ID }, + usePagination: true, + } +); + +async function searchNotifications() { + const params = Object.keys(searchForm).reduce((acc, key) => { + acc[key] = searchForm[key]; + return acc; + }, {}); + + params.SAFETY_MEETING_ID = SAFETY_MEETING_ID; + await fnGetData(params); +} + +// 重置表单时,也确保重置为初始值 +function resetSearchForm() { + Object.keys(searchForm).forEach((key) => { + searchForm[key] = ""; + }); + fnResetPagination({ SAFETY_MEETING_ID }); +} + +const relatedClassificationList = ref(null); + +onMounted(async () => { + const data = await layoutFnGetSIGNEDSTATUSClassification(); + relatedClassificationList.value = JSON.parse(data.value.zTreeNodes); +}); +</script> + +<style scoped></style> diff --git a/src/views/safety_production_related/safety_meeting/index.vue b/src/views/safety_production_related/safety_meeting/index.vue new file mode 100644 index 0000000..1e7a25c --- /dev/null +++ b/src/views/safety_production_related/safety_meeting/index.vue @@ -0,0 +1,168 @@ +<template> + <div> + <el-card> + <el-form + :model="searchForm" + label-width="100px" + @submit.prevent="fnResetPagination" + > + <el-row> + <el-col :span="6"> + <el-form-item label="会议标题" prop="MEETING_TITLE"> + <el-input v-model="searchForm.MEETING_TITLE" /> + </el-form-item> + </el-col> + <el-col :span="6"> + <el-form-item label="会议类型" prop="MEETING_TYPE"> + <el-select v-model="searchForm.MEETING_TYPE"> + <el-option + v-for="item in relatedClassificationList" + :key="item.BIANMA" + :label="item.name" + :value="item.name" + /> + </el-select> + </el-form-item> + </el-col> + <el-col :span="6"> + <el-form-item label-width="10px"> + <el-button type="primary" native-type="submit">搜索</el-button> + <el-button native-type="reset" @click="fnResetPagination"> + 重置 + </el-button> + </el-form-item> + </el-col> + </el-row> + </el-form> + </el-card> + <layout-card> + <layout-table + :data="list" + @get-data="fnGetData" + v-model:pagination="pagination" + > + <el-table-column label="序号" width="60"> + <template #default="{ $index }"> + {{ serialNumber(pagination, $index) }} + </template> + </el-table-column> + <el-table-column prop="MEETING_TITLE" label="会议标题" width="250" /> + <el-table-column prop="MEETING_TYPE" label="会议类型" width="250" /> + <el-table-column label="会议状态" prop="SIGNEDDATE"> + <template #default="{ row }"> + <el-tag v-if="row.MEETING_STATUS === 1">{{ "进行中" }}</el-tag> + <el-tag v-else>未开始</el-tag> + </template> + </el-table-column> + <el-table-column prop="MEETING_DATE" label="会议时间" /> + <el-table-column label="参会人数" width="100"> + <template #default="{ row }"> + {{ row.MEETING_PERSONS + "/" + row.TOTALPERSONNUM }}人 + </template> + </el-table-column> + <el-table-column prop="HOST_PERSON" label="主持人" /> + <el-table-column prop="MEETING_ADDRESS" label="会议地点" /> + <el-table-column prop="TRANSPORTATIONCOMPANY" label="运输企业" /> + <el-table-column label="操作" width="180"> + <template v-slot:default="{ row }"> + <el-button + type="primary" + text + link + @click=" + router.push({ + path: '/safety_production_related/safety_meeting/meeting_info', + query: { + SAFETY_MEETING_ID: row.SAFETY_MEETING_ID, + }, + }) + " + > + 查看 + </el-button> + <el-button + type="primary" + text + link + @click=" + router.push({ + path: '/safety_production_related/safety_meeting/add', + }) + " + > + 添加 + </el-button> + <el-button + type="danger" + text + link + @click="deleteItem(row.SAFETY_MEETING_ID)" + > + 删除 + </el-button> + <!-- 阅读详情按钮 --> + <el-button + type="primary" + text + link + @click=" + router.push({ + path: '/safety_production_related/safety_meeting/details', + query: { + SAFETY_MEETING_ID: row.SAFETY_MEETING_ID, + }, + }) + " + > + 参会人员 + </el-button> + </template> + </el-table-column> + </layout-table> + </layout-card> + <edit + v-model:visible="data.analysisDialog.visible" + :info="data.analysisDialog.info" + @get-data="fnResetPagination" + /> + </div> +</template> + +<script setup> +import { serialNumber } from "@/assets/js/utils"; +import useListData from "@/assets/js/useListData.js"; +import { onMounted, reactive, ref } from "vue"; +import { + getSafetyMeetingList, + setSafetyMeetingDelete, +} from "@/request/traffic_safety_meeting.js"; +import router from "@/router/index.js"; +import { layoutFnGetMEETINGTYPEClassification } from "@/request/safety_production_related.js"; +import { ElMessage, ElMessageBox } from "element-plus"; + +const { list, pagination, searchForm, fnGetData, fnResetPagination } = + useListData(getSafetyMeetingList); +const data = reactive({ + analysisDialog: { + visible: false, + info: {}, + }, +}); +// 删除事件 +const deleteItem = async (value) => { + await ElMessageBox.confirm(`确定要删除吗?`, { + type: "warning", + }); + await setSafetyMeetingDelete({ SAFETY_MEETING_ID: value }); + ElMessage.success("删除成功"); + fnGetData(); +}; +const relatedClassificationList = ref(null); + +onMounted(async () => { + const data = await layoutFnGetMEETINGTYPEClassification(); + relatedClassificationList.value = JSON.parse(data.value.zTreeNodes); +}); +</script> + +<style scoped></style> diff --git a/src/views/safety_production_related/safety_meeting/meeting_info.vue b/src/views/safety_production_related/safety_meeting/meeting_info.vue new file mode 100644 index 0000000..89afb86 --- /dev/null +++ b/src/views/safety_production_related/safety_meeting/meeting_info.vue @@ -0,0 +1,91 @@ +<template> + <div> + <layout-card> + <el-descriptions :column="1" border> + <el-descriptions-item label="会议标题"> + {{ detailItems.MEETING_TITLE }} + </el-descriptions-item> + <el-descriptions-item label="运输企业"> + {{ detailItems.TRANSPORTATIONCOMPANY }} + </el-descriptions-item> + <el-descriptions-item label="主持人"> + {{ detailItems.HOST_PERSON }} + </el-descriptions-item> + <el-descriptions-item label="记录人"> + {{ detailItems.RECORDER }} + </el-descriptions-item> + <el-descriptions-item label="会议时间"> + {{ detailItems.MEETING_DATE_START }} + </el-descriptions-item> + <el-descriptions-item label="截止时间"> + {{ detailItems.MEETING_DATE_END }} + </el-descriptions-item> + <el-descriptions-item label="会议类型"> + {{ detailItems.MEETING_TYPE }} + </el-descriptions-item> + <el-descriptions-item label="会议内容"> + {{ detailItems.MEETING_CONTENT }} + </el-descriptions-item> + <el-descriptions-item label="备注"> + {{ detailItems.NOTES }} + </el-descriptions-item> + <el-descriptions-item label="远程参会人员"> + 应参会{{ detailItems.totalPersonNum }}/人,实参人数{{ + detailItems.realPersonNum + }}/人 + </el-descriptions-item> + </el-descriptions> + <el-table + :border="true" + :data="detailItems.recipientsList" + :show-header="false" + > + <el-table-column label="NAME1" align="center"> + <template #default="{ row }"> + <img :src="row.AVATAR" alt="Avatar" /> + </template> + </el-table-column> + <el-table-column label="NAME2" align="center"> + <template #default="{ row }"> + {{ row.PRACTITIONER }}<br /> + {{ row.CONTACT_PHONE }}<br /> + {{ row.HOME_ADDRESS }} + </template> + </el-table-column> + <el-table-column label="NAME3" align="center"> + <template #default="{ row }"> + <img :src="row.SIGNATUREPICTURE" alt="Signature" /> + </template> + </el-table-column> + </el-table> + </layout-card> + </div> +</template> + +<script setup> +import { onMounted, reactive } from "vue"; +import { getSafetyMeetingView } from "@/request/traffic_safety_meeting.js"; +import { useRoute } from "vue-router"; +const route = useRoute(); +const { SAFETY_MEETING_ID } = route.query; +const detailItems = reactive({ + MEETING_TITLE: "", + TRANSPORTATIONCOMPANY: "", + HOST_PERSON: "", + RECORDER: "", + MEETING_DATE_START: "", + MEETING_DATE_END: "", + MEETING_TYPE: "", + MEETING_CONTENT: "", + recipientsInfo: "", + totalPersonNum: "", + realPersonNum: "", +}); + +onMounted(async () => { + const response = await getSafetyMeetingView({ SAFETY_MEETING_ID }); + Object.assign(detailItems, response.pd); +}); +</script> + +<style scoped></style> diff --git a/src/views/safety_production_related/security_notice/add.vue b/src/views/safety_production_related/security_notice/add.vue index a4c433a..2b0b69f 100644 --- a/src/views/safety_production_related/security_notice/add.vue +++ b/src/views/safety_production_related/security_notice/add.vue @@ -81,7 +81,6 @@ <div class="tc mt-10"> <el-button type="primary" @click="fnSubmit"> 确定 </el-button> </div> - <select-risk v-model:visible="data.selectRiskDialogVisible" :list-data="data.listAll" @@ -138,14 +137,18 @@ const data = reactive({ const fnSubmit = async () => { await useFormValidate(formRef); const formData = new FormData(); + Object.keys(data.form).forEach((key) => { formData.append(key, data.form[key]); }); + formData.delete("fileList"); + for (let i = 0; i < data.form.fileList.length; i++) { if (data.form.fileList[i].raw) formData.append("FFILE", data.form.fileList[i].raw); } + await addSecurityNotice(formData); }; const fnSelectRiskSubmit = (list) => { diff --git a/src/views/safety_production_related/security_notice/details.vue b/src/views/safety_production_related/security_notice/details.vue index 14279ca..2f7c82a 100644 --- a/src/views/safety_production_related/security_notice/details.vue +++ b/src/views/safety_production_related/security_notice/details.vue @@ -14,7 +14,14 @@ </el-col> <el-col :span="8"> <el-form-item label="从业类型" prop="PRACTITIONERTYPE"> - <el-input v-model="searchForm.PRACTITIONERTYPE" /> + <el-select v-model="searchForm.PRACTITIONERTYPE"> + <el-option + v-for="item in relatedClassificationList" + :key="item.BIANMA" + :label="item.name" + :value="item.BIANMA" + /> + </el-select> </el-form-item> </el-col> <el-col :span="8"> @@ -51,9 +58,8 @@ <layout-card> <layout-table :data="list" - :pagination="pagination" @get-data="fnGetData" - @update:pagination="updatePagination" + v-model:pagination="pagination" stripe border show-header @@ -89,9 +95,12 @@ </template> <script setup> -import { reactive, onMounted } from "vue"; +import { reactive, onMounted, ref } from "vue"; import { useRoute } from "vue-router"; -import { getSecurityNotice } from "@/request/safety_production_related.js"; +import { + getSecurityNotice, + layoutFnGetSIGNEDSTATUSClassification, +} from "@/request/safety_production_related.js"; import { serialNumber } from "@/assets/js/utils"; import useListData from "@/assets/js/useListData"; @@ -132,9 +141,15 @@ function resetSearchForm() { fnResetPagination({ NOTIFICATION_ID }); } -onMounted(() => { - fnGetData({ NOTIFICATION_ID }); +const relatedClassificationList = ref(null); + +onMounted(async () => { + const data = await layoutFnGetSIGNEDSTATUSClassification(); + relatedClassificationList.value = JSON.parse(data.value.zTreeNodes); }); +// onMounted(() => { +// fnGetData({ NOTIFICATION_ID }); +// }); </script> <style scoped></style> diff --git a/src/views/safety_production_related/security_notice/index.vue b/src/views/safety_production_related/security_notice/index.vue index 18f0713..7982b69 100644 --- a/src/views/safety_production_related/security_notice/index.vue +++ b/src/views/safety_production_related/security_notice/index.vue @@ -28,7 +28,7 @@ <el-option v-for="item in relatedClassificationList" :key="item.BIANMA" - :label="item.NAME" + :label="item.name" :value="item.BIANMA" /> </el-select> @@ -140,7 +140,7 @@ <script setup> import { serialNumber } from "@/assets/js/utils"; import useListData from "@/assets/js/useListData.js"; -import { reactive } from "vue"; +import { onMounted, reactive, ref } from "vue"; import { getSecurityNoticeList, layoutFnGetNotificationsClassification, @@ -166,8 +166,12 @@ const deleteItem = async (value) => { ElMessage.success("删除成功"); fnGetData(); }; -const relatedClassificationList = - await layoutFnGetNotificationsClassification(); +const relatedClassificationList = ref(null); + +onMounted(async () => { + const data = await layoutFnGetNotificationsClassification(); + relatedClassificationList.value = JSON.parse(data.value.zTreeNodes); +}); </script> <style scoped></style>