Merge pull request 'dev' (#1) from integrated_whb/integrated_whb_vue:dev into dev

Reviewed-on: #1
dev
wangpeng 2024-02-27 14:21:32 +08:00
commit 348f673286
450 changed files with 11823 additions and 2222 deletions

4
.env
View File

@ -1,5 +1,7 @@
VITE_BASE_URL=http://192.168.0.79:8091/
VITE_BASE_URL=http://192.168.0.42:8099/
VITE_PROXY=/api/
VITE_PROXY_QAAQ=/qaaq_api/
VITE_QAAQ_URL=https://gateway.qhdsafety.com/
VITE_FILE_URL=https://file.zcloudchina.com/YTHFile
VITE_TEMPLATE_URL=https://qaaq.qhdsafety.com/file/
VITE_ON_LINE_WEB_SOCKET_URL=wss://qaaq.qhdsafety.com/zxwebsocket/

View File

@ -5,7 +5,7 @@ module.exports = {
node: true
},
extends: [
"plugin:vue/vue3-essential",
"plugin:vue/vue3-recommended",
"standard",
"@vue/prettier",
"eslint:recommended"
@ -18,10 +18,23 @@ module.exports = {
rules: {
"no-console": "warn",
"vue/multi-word-component-names": "off",
camelcase: "off",
eqeqeq: "error",
"vue/eqeqeq": "error",
"vue/no-v-html": "off",
"vue/require-default-prop": "off",
"camelcase": "off",
"eqeqeq": "error",
"vue/no-template-shadow": "error",
"vue/attribute-hyphenation": "error",
"vue/html-end-tags": "error",
"vue/eqeqeq": "error",
"vue/component-name-in-template-casing": ["error", "kebab-case"],
"vue/enforce-style-attribute": [
"error",
{ "allow": ["scoped", "module"] }
],
"vue/v-on-event-hyphenation": ["error", "always",{
"autofix": true,
}],
"vue/require-explicit-emits": "error",
"no-unused-vars": [
"error",
{ vars: "all", args: "after-used", ignoreRestSiblings: false }

View File

@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no" />
<title>管理平台</title>
<title>危化安全生产管理平台</title>
</head>
<body>

289
node_modules/vue-esign/src/index.vue generated vendored Normal file
View File

@ -0,0 +1,289 @@
<template>
<canvas ref="canvas" @mousedown="mouseDown" @mousemove="mouseMove" @mouseup="mouseUp"
@touchstart="touchStart" @touchmove="touchMove" @touchend="touchEnd"></canvas>
</template>
<script>
export default {
props: {
width: {
type: Number,
default: 800
},
height: {
type: Number,
default: 300
},
lineWidth: {
type: Number,
default: 4
},
lineColor: {
type: String,
default: '#000000'
},
bgColor: {
type: String,
default: '#FFFFFF'
},
isCrop: {
type: Boolean,
default: false
},
isClearBgColor: {
type: Boolean,
default: true
},
format: {
type: String,
default: 'image/png'
},
quality: {
type: Number,
default: 1
}
},
data () {
return {
hasDrew: false,
resultImg: '',
points: [],
canvasTxt: null,
startX: 0,
startY: 0,
isDrawing: false,
sratio: 1
}
},
computed: {
ratio () {
return this.height / this.width
},
stageInfo () {
return this.$refs.canvas.getBoundingClientRect()
},
myBg () {
return this.bgColor ? this.bgColor : 'rgba(255, 255, 255, 0)'
}
},
watch: {
'myBg': function (newVal) {
this.$refs.canvas.style.background = newVal
}
},
beforeMount () {
window.addEventListener('resize', this.$_resizeHandler)
},
beforeDestroy () {
window.removeEventListener('resize', this.$_resizeHandler)
},
mounted () {
const canvas = this.$refs.canvas
canvas.height = this.height
canvas.width = this.width
canvas.style.background = this.myBg
this.$_resizeHandler()
//
document.onmouseup = () => {
this.isDrawing = false
}
},
methods: {
$_resizeHandler () {
const canvas = this.$refs.canvas
canvas.style.width = this.width + "px"
const realw = parseFloat(window.getComputedStyle(canvas).width)
canvas.style.height = this.ratio * realw + "px";
this.canvasTxt = canvas.getContext('2d')
this.canvasTxt.scale(1 * this.sratio, 1 * this.sratio)
this.sratio = realw / this.width
this.canvasTxt.scale(1 / this.sratio, 1 / this.sratio)
},
// pc
mouseDown (e) {
e = e || event
e.preventDefault()
this.isDrawing = true
this.hasDrew = true
let obj = {
x: e.offsetX,
y: e.offsetY
}
this.drawStart(obj)
},
mouseMove (e) {
e = e || event
e.preventDefault()
if (this.isDrawing) {
let obj = {
x: e.offsetX,
y: e.offsetY
}
this.drawMove(obj)
}
},
mouseUp (e) {
e = e || event
e.preventDefault()
let obj = {
x: e.offsetX,
y: e.offsetY
}
this.drawEnd(obj)
this.isDrawing = false
},
// mobile
touchStart (e) {
e = e || event
e.preventDefault()
this.hasDrew = true
if (e.touches.length === 1) {
let obj = {
x: e.targetTouches[0].clientX - this.$refs.canvas.getBoundingClientRect().left,
y: e.targetTouches[0].clientY - this.$refs.canvas.getBoundingClientRect().top
}
this.drawStart(obj)
}
},
touchMove (e) {
e = e || event
e.preventDefault()
if (e.touches.length === 1) {
let obj = {
x: e.targetTouches[0].clientX - this.$refs.canvas.getBoundingClientRect().left,
y: e.targetTouches[0].clientY - this.$refs.canvas.getBoundingClientRect().top
}
this.drawMove(obj)
}
},
touchEnd (e) {
e = e || event
e.preventDefault()
if (e.touches.length === 1) {
let obj = {
x: e.targetTouches[0].clientX - this.$refs.canvas.getBoundingClientRect().left,
y: e.targetTouches[0].clientY - this.$refs.canvas.getBoundingClientRect().top
}
this.drawEnd(obj)
}
},
//
drawStart (obj) {
this.startX = obj.x
this.startY = obj.y
this.canvasTxt.beginPath()
this.canvasTxt.moveTo(this.startX, this.startY)
this.canvasTxt.lineTo(obj.x, obj.y)
this.canvasTxt.lineCap = 'round'
this.canvasTxt.lineJoin = 'round'
this.canvasTxt.lineWidth = this.lineWidth * this.sratio
this.canvasTxt.stroke()
this.canvasTxt.closePath()
this.points.push(obj)
},
drawMove (obj) {
this.canvasTxt.beginPath()
this.canvasTxt.moveTo(this.startX, this.startY)
this.canvasTxt.lineTo(obj.x, obj.y)
this.canvasTxt.strokeStyle = this.lineColor
this.canvasTxt.lineWidth = this.lineWidth * this.sratio
this.canvasTxt.lineCap = 'round'
this.canvasTxt.lineJoin = 'round'
this.canvasTxt.stroke()
this.canvasTxt.closePath()
this.startY = obj.y
this.startX = obj.x
this.points.push(obj)
},
drawEnd (obj) {
this.canvasTxt.beginPath()
this.canvasTxt.moveTo(this.startX, this.startY)
this.canvasTxt.lineTo(obj.x, obj.y)
this.canvasTxt.lineCap = 'round'
this.canvasTxt.lineJoin = 'round'
this.canvasTxt.stroke()
this.canvasTxt.closePath()
this.points.push(obj)
this.points.push({x: -1, y: -1})
},
//
generate (options) {
let imgFormat = options && options.format ? options.format: this.format
let imgQuality = options && options.quality ? options.quality: this.quality
const pm = new Promise((resolve, reject) => {
if (!this.hasDrew) {
reject(`Warning: Not Signned!`)
return
}
var resImgData = this.canvasTxt.getImageData(0, 0, this.$refs.canvas.width, this.$refs.canvas.height)
this.canvasTxt.globalCompositeOperation = "destination-over"
this.canvasTxt.fillStyle = this.myBg
this.canvasTxt.fillRect(0,0,this.$refs.canvas.width ,this.$refs.canvas.height)
this.resultImg = this.$refs.canvas.toDataURL(imgFormat, imgQuality)
var resultImg = this.resultImg
this.canvasTxt.clearRect(0, 0, this.$refs.canvas.width ,this.$refs.canvas.height)
this.canvasTxt.putImageData(resImgData, 0, 0)
this.canvasTxt.globalCompositeOperation = "source-over"
if (this.isCrop) {
const crop_area = this.getCropArea(resImgData.data)
var crop_canvas = document.createElement('canvas')
const crop_ctx = crop_canvas.getContext('2d')
crop_canvas.width = crop_area[2] - crop_area[0]
crop_canvas.height = crop_area[3] - crop_area[1]
const crop_imgData = this.canvasTxt.getImageData(...crop_area)
crop_ctx.globalCompositeOperation = "destination-over"
crop_ctx.putImageData(crop_imgData, 0, 0)
crop_ctx.fillStyle = this.myBg
crop_ctx.fillRect(0, 0, crop_canvas.width , crop_canvas.height)
resultImg = crop_canvas.toDataURL(imgFormat, imgQuality)
crop_canvas = null
}
resolve(resultImg)
})
return pm
},
reset () {
this.canvasTxt.clearRect(
0,
0,
this.$refs.canvas.width,
this.$refs.canvas.height
)
if (this.isClearBgColor) {
this.$emit('update:bgColor', '')
this.$refs.canvas.style.background = 'rgba(255, 255, 255, 0)'
}
this.points = []
this.hasDrew = false
this.resultImg = ''
},
getCropArea (imgData) {
var topX = this.$refs.canvas.width; var btmX = 0; var topY = this.$refs.canvas.height; var btnY = 0
for (var i = 0; i < this.$refs.canvas.width; i++) {
for (var j = 0; j < this.$refs.canvas.height; j++) {
var pos = (i + this.$refs.canvas.width * j) * 4
if (imgData[pos] > 0 || imgData[pos + 1] > 0 || imgData[pos + 2] || imgData[pos + 3] > 0) {
btnY = Math.max(j, btnY)
btmX = Math.max(i, btmX)
topY = Math.min(j, topY)
topX = Math.min(i, topX)
}
}
}
topX++
btmX++
topY++
btnY++
const data = [topX, topY, btmX, btnY]
return data
}
}
}
</script>
<style scoped>
canvas {
max-width: 100%;
display: block;
}
</style>

11
package-lock.json generated
View File

@ -41,7 +41,8 @@
"vue-router": "^4.2.5",
"vue3-pdfjs": "^0.1.6",
"vue3-print-nb": "^0.1.4",
"vue3-puzzle-vcode": "^1.1.5"
"vue3-puzzle-vcode": "^1.1.5",
"vue3-seamless-scroll": "^2.0.1"
},
"devDependencies": {
"@our-patches/postcss-px-to-viewport": "^1.2.0",
@ -6018,6 +6019,14 @@
"resolved": "https://registry.npmmirror.com/vue3-puzzle-vcode/-/vue3-puzzle-vcode-1.1.7.tgz",
"integrity": "sha512-mW780dz7HKjrElnE60CeYSeHGidKBKHoMjTDYfqF21330rTkFOsfDK1FQKZ22MktgMtTEoS/imfpEDlM1cxY/g=="
},
"node_modules/vue3-seamless-scroll": {
"version": "2.0.1",
"resolved": "https://registry.npmmirror.com/vue3-seamless-scroll/-/vue3-seamless-scroll-2.0.1.tgz",
"integrity": "sha512-mI3BaDU3pjcPUhVSw3/xNKdfPBDABTi/OdZaZqKysx4cSdNfGRbVvGNDzzptBbJ5S7imv5T55l6x/SqgnxKreg==",
"dependencies": {
"throttle-debounce": "5.0.0"
}
},
"node_modules/web-streams-polyfill": {
"version": "3.3.2",
"resolved": "https://registry.npmmirror.com/web-streams-polyfill/-/web-streams-polyfill-3.3.2.tgz",

View File

@ -43,7 +43,8 @@
"vue-router": "^4.2.5",
"vue3-pdfjs": "^0.1.6",
"vue3-print-nb": "^0.1.4",
"vue3-puzzle-vcode": "^1.1.5"
"vue3-puzzle-vcode": "^1.1.5",
"vue3-seamless-scroll": "^2.0.1"
},
"devDependencies": {
"@our-patches/postcss-px-to-viewport": "^1.2.0",

File diff suppressed because one or more lines are too long

View File

@ -15,4 +15,4 @@
import zhCn from "element-plus/dist/locale/zh-cn.mjs";
</script>
<style lang="scss"></style>
<style scoped lang="scss"></style>

View File

@ -8,7 +8,6 @@ import children from "@/components/children/index";
import { MODEL } from "@/assets/js/constant";
// import asyncRouter from "@/assets/js/asyncRouter";
import { getAsyncRouter } from "@/request/api";
// import { getRouteTreeAll } from "@/request/system_management.js";
const modules = import.meta.glob([
"./views/**/*.vue",
@ -31,7 +30,6 @@ router.beforeEach(async (to, from, next) => {
// pinia里没有储存路由去后台获取路由
if (routerStore.getRouters.length === 0) {
const resData = await getAsyncRouter();
// const resData = await getRouteTreeAll();
storageRouter = resData.routeList; // 后台请求得到的路由数据
// storageRouter = asyncRouter; // 死路由
routerStore.setRouters(storageRouter); // 存储路由

View File

@ -1,7 +1,7 @@
:root {
--el-header-height: 69px;
--el-aside-scrollbar-height: calc(100vh - var(--el-header-height));
--el-main-scrollbar-height: calc(100vh - var(--el-header-height) - 60px);
--el-main-scrollbar-height: calc(100vh - var(--el-header-height) - 40px);
--el-border-color: #273868 !important; //
--el-text-color-regular: #fff !important;
--el-fill-color-light: #0e1d44 !important; //hover
@ -251,6 +251,14 @@
color: var(--el-text-color-regular) !important;
}
.el-date-table.is-week-mode .el-date-table__row {
&.current, &:hover {
.el-date-table-cell {
--el-datepicker-inrange-bg-color: var(--el-fill-color-light) !important;
}
}
}
.el-input.is-disabled .el-input__wrapper {
box-shadow: 0 0 0 1px var(--el-border-color) inset !important;
}
@ -398,3 +406,15 @@
font-size: 12px !important;
}
}
.el-notification {
--el-notification-title-color: #000 !important;
.el-notification__closeBtn:hover {
--el-notification-close-hover-color: #000 !important;
}
}
.el-color-predefine__color-selector.selected {
--el-color-primary: #fff !important;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 424 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 423 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
src/assets/images/bi/bg.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
src/assets/images/bi/ri.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -7,6 +7,7 @@ export const MODEL = {
3: "prevention",
4: "educationAndTraining",
5: "comprehensive",
6: "positioning",
};
// 头部导航条
export const MENU = [
@ -15,8 +16,8 @@ export const MENU = [
{ title: "双重预防", model: MODEL["3"] },
{ title: "教育培训", model: MODEL["4"] },
{ title: "综合管理", model: MODEL["5"] },
{ title: "定位管理", model: MODEL["6"] },
];
export const PRINT_STYLE =
'<style type="text/css" media="print">\n' +
" @page { size: landscape; }\n" +

View File

@ -7,6 +7,7 @@ import {
getLevelsCorp,
getElectronicFenceTree,
getListSelectTree,
getDepartmentzTree,
} from "@/request/data_dictionary.js";
import { ref } from "vue";
@ -384,6 +385,11 @@ export const layoutFnGetDepartmentTree = async (params) => {
const resData = await getDepartmentTree(params);
return ref(JSON.parse(resData.zTreeNodes));
};
// 部门树2
export const layoutFnGetDepartmentzTree = async (params) => {
const resData = await getDepartmentzTree(params);
return ref(JSON.parse(resData.zTreeNodes));
};
// 电子围栏树
export const layoutFnGetElectronicFenceTree = async (params) => {
const resData = await getElectronicFenceTree(params);

View File

@ -33,9 +33,9 @@ export default function useAliYunUpload({
Title: uploadInfo.file.name,
FileName: uploadInfo.file.name,
});
uploadAddress = resData.body.uploadAddress;
uploadAuth = resData.body.uploadAuth;
videoId = resData.body.videoId;
uploadAddress = resData.data.uploadAddress;
uploadAuth = resData.data.uploadAuth;
videoId = resData.data.videoId;
} else {
const resData = await setVideoRefresh({
Title: uploadInfo.file.name,

View File

@ -4,6 +4,6 @@
<script setup>
defineOptions({
name: "children",
name: "Children",
});
</script>

View File

@ -18,7 +18,7 @@
</template>
<script setup>
import { layoutFnGetDepartmentTree } from "@/assets/js/data_dictionary";
import { layoutFnGetDepartmentzTree } from "@/assets/js/data_dictionary";
import { useVModel } from "@vueuse/core";
defineOptions({
@ -57,7 +57,7 @@ const props = defineProps({
});
const emits = defineEmits(["update:modelValue"]);
const modelValue = useVModel(props, "modelValue", emits);
const departmentTree = await layoutFnGetDepartmentTree({
const departmentTree = await layoutFnGetDepartmentzTree({
rootDisabled: props.rootDisabled,
});
</script>

View File

@ -1,8 +1,8 @@
<template>
<layout-tree
:api="layoutFnGetDepartmentTree"
v-model:refresh="refresh"
:id="departmentId"
v-model:refresh="refresh"
:api="layoutFnGetDepartmentTree"
@throw-data="emits('throw-data', $event)"
@node-click="emits('node-click', $event)"
/>

View File

@ -1,8 +1,8 @@
<template>
<layout-cascader
id="688d2cf1c6cd4dab999a0106e09aec83"
v-model="modelValue"
ref="cascaderRef"
v-model="modelValue"
:check-strictly="false"
:show-all-levels="false"
/>

View File

@ -1,10 +1,10 @@
<template>
<div>
<Toolbar :editor="editorRef" :default-config="toolbarConfig" />
<Editor
:style="{ height, 'overflow-y': 'hidden' }"
<div style="flex: 1">
<toolbar :editor="editorRef" :default-config="toolbarConfig" />
<editor
v-model="modelValue"
@onCreated="fnEditorCreated"
:style="{ height, 'overflow-y': 'hidden' }"
@on-created="fnEditorCreated"
/>
</div>
</template>

View File

@ -29,20 +29,20 @@
<layout-card>
<layout-table
ref="tableRef"
:data="list"
v-model:pagination="pagination"
:data="list"
@get-data="fnGetData"
>
<el-table-column reserve-selection type="selection" width="55" />
<el-table-column label="序号" width="70">
<template v-slot="{ $index }">
<template #default="{ $index }">
{{ serialNumber(pagination, $index) }}
</template>
</el-table-column>
<el-table-column property="layName" label="所属图层" width="150" />
<el-table-column property="regName" label="名称" />
<el-table-column label="操作" width="200">
<template v-slot="{ row }">
<template #default="{ row }">
<el-button type="primary" text link @click="handleJoin(row)"
>绑定</el-button
>

View File

@ -1,8 +1,8 @@
<template>
<layout-tree
:api="layoutFnGetElectronicFenceTree"
v-model:refresh="refresh"
:id="electronicFenceAreaId"
v-model:refresh="refresh"
:api="layoutFnGetElectronicFenceTree"
@throw-data="emits('throw-data', $event)"
@node-click="emits('node-click', $event)"
/>

View File

@ -7,7 +7,7 @@
>
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
<el-row>
<el-col :span="24" v-if="hiddenType === 'unqualified'">
<el-col v-if="hiddenType === 'unqualified'" :span="24">
<el-form-item label="检查内容" prop="CHECK_CONTENT">
<el-input
:model-value="info.CHECK_CONTENT"
@ -55,7 +55,7 @@
</el-select>
</el-form-item>
</el-col>
<el-col :span="24" v-if="info.BAO_BAO_TYPE === '1'">
<el-col v-if="info.BAO_BAO_TYPE === '1'" :span="24">
<el-form-item label="隐患类别" prop="HIDDEN_CATEGORY">
<el-select v-model="form.HIDDEN_CATEGORY">
<el-option
@ -70,8 +70,8 @@
<el-col :span="24">
<el-form-item label="隐患类型" prop="HIDDENTYPE">
<layout-hidden-danger-type
v-model="form.HIDDENTYPE"
ref="hiddenDangerTypeRef"
v-model="form.HIDDENTYPE"
/>
</el-form-item>
</el-col>
@ -170,8 +170,8 @@
</el-form>
</el-col>
<el-col
:span="12"
v-if="hiddenType === 'unqualified' || hiddenType === 'otherHidden'"
:span="12"
>
<div
v-for="item in data.list"

View File

@ -79,19 +79,19 @@
<span v-else-if="data.info.RECTIFICATIONTYPE === '2'"> 限期整改 </span>
</el-descriptions-item>
<el-descriptions-item
label="整改期限"
v-if="data.info.RECTIFICATIONTYPE === '2'"
label="整改期限"
>
{{ data.info.RECTIFICATIONDEADLINE }}
</el-descriptions-item>
<el-descriptions-item label="隐患类别" v-if="data.info.HIDDEN_CATEGORY">
<el-descriptions-item v-if="data.info.HIDDEN_CATEGORY" label="隐患类别">
{{ data.info.HIDDEN_CATEGORY_NAME }}
</el-descriptions-item>
<el-descriptions-item label="隐患图片">
<img
v-viewer
v-for="item in data.hImgs"
:key="item.IMGFILES_ID"
v-viewer
:src="VITE_FILE_URL + item.FILEPATH"
alt=""
width="100"
@ -100,15 +100,15 @@
/>
</el-descriptions-item>
<el-descriptions-item
label="隐患视频"
v-if="data.videoDialog.src"
label="隐患视频"
class-name="print_no_use"
label-class-name="print_no_use"
>
<el-icon
size="30px"
@click="data.videoDialog.visible = true"
style="cursor: pointer"
@click="data.videoDialog.visible = true"
>
<video-play />
</el-icon>
@ -135,9 +135,9 @@
</el-descriptions-item>
<el-descriptions-item label="整改后图片">
<img
v-viewer
v-for="item in data.rImgs"
:key="item.IMGFILES_ID"
v-viewer
:src="VITE_FILE_URL + item.FILEPATH"
alt=""
width="100"
@ -150,13 +150,13 @@
{{ data.info.HAVEPLAN === "1" ? "有" : "" }}
</el-descriptions-item>
<el-descriptions-item
label="计划图片"
v-if="data.info.HAVEPLAN === '1'"
label="计划图片"
>
<img
v-viewer
v-for="item in data.pImgs"
:key="item.IMGFILES_ID"
v-viewer
:src="VITE_FILE_URL + item.FILEPATH"
alt=""
width="100"
@ -165,8 +165,8 @@
/>
</el-descriptions-item>
<el-descriptions-item
label="整改方案"
v-if="data.info.RECTIFICATIONTYPE === '2'"
label="整改方案"
>
{{ data.info.HAVESCHEME === "0" ? "无" : "" }}
{{ data.info.HAVESCHEME === "1" ? "有" : "" }}
@ -204,9 +204,9 @@
</el-descriptions-item>
<el-descriptions-item label="方案图片">
<img
v-viewer
v-for="item in data.sImgs"
:key="item.IMGFILES_ID"
v-viewer
:src="VITE_FILE_URL + item.FILEPATH"
alt=""
width="100"
@ -217,7 +217,7 @@
</template>
</el-descriptions>
</template>
<template v-if="data.checkList.length > 0">
<template v-if="data.checkList.length > 0 && data.info.STATE >= '4'">
<el-divider content-position="left">验收信息</el-divider>
<template v-for="(item, index) in data.checkList" :key="index">
<el-descriptions :column="1" border class="mt-10">
@ -239,9 +239,9 @@
</el-descriptions-item>
<el-descriptions-item label="验收图片">
<img
v-viewer
v-for="item1 in item.cImgs"
:key="item1.IMGFILES_ID"
v-viewer
:src="VITE_FILE_URL + item1.FILEPATH"
alt=""
width="100"
@ -277,8 +277,7 @@ const props = defineProps({
},
listType: {
type: String,
required: true,
default: "",
default: "1",
},
});
const emits = defineEmits(["throw-data"]);
@ -297,11 +296,11 @@ const data = reactive({
});
const fnGetData = async () => {
const resData =
props.listType === "1"
? await getHiddenDangerView({
props.listType === "2"
? await getCustomHiddenDangerView({ HIDDEN_ID: props.hiddenId })
: await getHiddenDangerView({
HIDDEN_ID: props.hiddenId,
})
: await getCustomHiddenDangerView({ HIDDEN_ID: props.hiddenId });
});
data.info = resData.pd;
data.hs = resData.hs;
data.checkList = resData.checkList;

View File

@ -1,8 +1,8 @@
<template>
<layout-cascader
id="f2598ba72e864eadabf0ca4b664d26b9"
v-model="modelValue"
ref="cascaderRef"
v-model="modelValue"
:check-strictly="false"
:show-all-levels="false"
/>

View File

@ -0,0 +1,144 @@
<template>
<div id="bi_container">
<div id="map" class="map_bg"></div>
<div class="options">
<template v-if="type === 1">
<div class="option" @click="confrim">
<div>
<img src="/src/assets/images/map_tools/icon1.png" alt="" />
</div>
<div class="label">完成绘制</div>
</div>
<div class="option" @click="clear">
<div>
<img src="/src/assets/images/map_tools/icon2.png" alt="" />
</div>
<div class="label">清除绘制</div>
</div>
<div class="option" @click="reduction">
<div>
<img src="/src/assets/images/map_tools/icon3.png" alt="" />
</div>
<div class="label">还原建筑</div>
</div>
</template>
<div class="id">当前选中楼层id{{ model_id }}</div>
</div>
</div>
</template>
<script setup>
import { useVModels } from "@vueuse/core";
import { onBeforeUnmount, onMounted, ref } from "vue";
import {
clearEnclosure,
handleEnclosure,
handleMouseClick,
handlePut,
initMap,
reduction,
showEnclosure,
} from "./map";
import { useUserStore } from "@/pinia/user.js";
import { getEnterpriseInfo } from "@/request/enterprise_management.js";
const props = defineProps({
type: {
type: Number,
default: 1,
},
positions: {
type: Array,
default: () => [],
},
position: {
type: Array,
default: () => [],
},
modUuid: {
type: String,
default: "",
},
});
const userStore = useUserStore();
const CORPINFO_ID = userStore.getUserInfo.CORPINFO_ID;
const data = [];
const model_id = ref(0);
const emits = defineEmits([
"update:positions",
"update:position",
"update:modUuid",
]);
const { positions, position, modUuid } = useVModels(props, emits);
const confrim = () => {
showEnclosure(data);
positions.value = [...data];
modUuid.value = model_id.value;
};
const clear = () => {
clearEnclosure(data);
data.length = 0;
positions.value = [];
};
onMounted(async () => {
const corp = await getEnterpriseInfo({ CORPINFO_ID });
initMap(corp.pd);
handleMouseClick(model_id);
if (props.type === 1) {
handleEnclosure(data);
} else {
handlePut(position);
}
});
onBeforeUnmount(() => {
window.$scene = null;
window.$icy = null;
window.$carmer = null;
});
</script>
<style scoped lang="scss">
#bi_container {
width: 100%;
height: 600px;
color: #ffffff;
position: relative;
font-size: 14px;
.map_bg {
width: 100%;
height: 540px;
}
.options {
margin-top: 10px;
display: flex;
align-items: center;
padding: 10px;
.option {
margin-right: 20px;
cursor: pointer;
text-align: center;
img {
width: 46px;
height: 46px;
}
.label {
margin-top: 10px;
font-size: 12px;
}
}
.id {
background-color: #1b284a;
padding: 10px;
border-radius: 4px;
height: 37px;
}
}
}
</style>

View File

@ -0,0 +1,167 @@
import axios from "axios";
import { useUserStore } from "@/pinia/user";
import pinia from "@/pinia";
const userStore = useUserStore(pinia);
const pls_ip = userStore.getUserInfo.POST_URL;
const url = pls_ip.replace("8084", "9000") + "/buildr/public/models/glb/";
export class Loadglb {
static modelMap = {};
constructor(icy) {
this.icy = icy;
this.model_def_group = null;
this.scene = null;
this.idList = [];
this.entityList = [];
this.number = 0;
this.building_group = null;
this.groundHeight = 0.2; // 设置地面的高度
}
async fetchData() {
try {
const response = await axios.get(
pls_ip.replace("8084", "9000") +
"/buildr/public/models/scene_000001.json"
);
// 将获取的数据保存到实例的属性中
this.scene = response.data.scene;
this.model_def_group = response.data.scene.model_def_group;
const map = new Map();
this.model_def_group.forEach((i) => {
map.set(i.guid.split("-")[3], { name: i.name, id: i.guid });
});
this.scene.building_group.forEach((i) => {
i.layer_group.forEach((a) => {
a.modelName = map.get(a.guid[0].split("-")[3]);
});
});
this.building_group = this.scene.building_group;
// console.log(this.building_group);
} catch (error) {
// 处理可能错误
console.error(error);
}
}
async model(Model) {
try {
// 执行 axios 请求并等待 fetchData 函数的异步操作完成
await this.fetchData();
const modelList = {};
this.scene.model_def_group.forEach((item) => {
modelList[item.guid] = item.name;
});
const modelTotal = this.scene.building_group.length;
this.createModel(Model, modelList, modelTotal);
this.scene.ground_group.forEach((ground) => {
const lon = ground.transform.translate.x;
const lat = ground.transform.translate.y;
const scale = ground.transform.scale;
ground.model_ref_group.forEach((layer) => {
// console.log(layer,'111');
const height = this.groundHeight;
const unit = {
lon,
lat,
scale,
id: layer.model_def_guid,
};
this.logNum([layer], height, unit, modelList, Model);
});
});
} catch (error) {
// 处理可能的错误
console.error(error);
}
}
createModel(Model, modelList, modelTotal) {
this.scene.building_group.forEach((building, index) => {
if (
Number(this.number * 2) <= index &&
index < Number((this.number + 1) * 2)
) {
const lon = building.transform.translate.x;
const lat = building.transform.translate.y;
const scale = building.transform.scale;
building.layer_group.forEach((layer) => {
// console.log(layer,'111');
const height = Number(layer.height[0] + this.groundHeight);
const unit = {
lon,
lat,
scale,
id: layer.guid[0],
};
this.logNum(layer.model_ref_group, height, unit, modelList, Model);
});
}
});
if (this.number * 2 < modelTotal) {
const throttle = setTimeout(() => {
this.number++;
this.createModel(Model, modelList, modelTotal);
sessionStorage.setItem("loading", (this.number * 2) / modelTotal);
clearTimeout(throttle);
}, 20);
if (
(this.number * 2) / modelTotal >= 0.5 &&
(this.number * 2) / modelTotal < 0.8
) {
sessionStorage.setItem("loadModel", "过半");
} else if ((this.number * 2) / modelTotal >= 0.8) {
sessionStorage.setItem("loadModel", "临底");
}
} else {
console.log(
"加载完成 ,此次加载:" +
modelTotal +
"栋建筑,共:" +
this.model_def_group.length +
"个模型"
);
sessionStorage.setItem("loadModel", "完成");
}
}
logNum(red, height, unit, modelList, Model) {
red.forEach((item) => {
if (this.idList.indexOf(item.model_def_guid) !== -1) {
return;
}
this.idList.push(item.model_def_guid);
if (
Object.prototype.hasOwnProperty.call(
Loadglb.modelMap,
`${unit.id.split("-")[3].slice(0, unit.id.split("-")[3].length - 2)}`
)
) {
Loadglb.modelMap[
`${unit.id.split("-")[3].slice(0, unit.id.split("-")[3].length - 2)}`
].push(item.model_def_guid);
} else {
Loadglb.modelMap[
`${unit.id.split("-")[3].slice(0, unit.id.split("-")[3].length - 2)}`
] = [item.model_def_guid];
}
const m = new Model(this.icy, {
id: item.model_def_guid,
name: "建筑",
url: `${url}${modelList[item.model_def_guid]}.gltf`,
height,
lon: unit.lon,
lat: unit.lat,
scale: unit.scale,
angle: [90, 0, 0],
// angle: [97.4843053, 0, 0]
});
this.entityList.push(m);
});
}
getArr() {
return this.building_group;
}
}

View File

@ -0,0 +1,335 @@
import { Loadglb } from "./loadglb.js";
const loadMap = 3;
let $entityTransparent = [];
const clickModel = new Map();
let enclosure = null;
let entities = null;
export const initMap = (corp) => {
window.$scene = new window.CustomCesium.Scene(
"map",
corp.CORP_NAME,
Number(loadMap)
);
window.$icy = window.$scene.getIcy();
window.$carmer = new window.CustomCesium.Carmer(window.$icy);
window.$icy.viewer.targetFrameRate = "30";
window.$icy.viewer.scene.light = new window.Cesium.DirectionalLight({
// 去除时间原因影响模型颜色
direction: new window.Cesium.Cartesian3(
0.35492591601301104,
-0.8909182691839401,
-0.2833588392420772
),
});
const [wgsLat, wgsLon] = bd09ToWgs84(corp.LATITUDE, corp.LONGITUDE);
flyTo(wgsLon, wgsLat);
// 亮度设置
const stages = window.$icy.viewer.scene.postProcessStages;
window.$icy.viewer.scene.brightness =
window.$icy.viewer.scene.brightness ||
stages.add(window.Cesium.PostProcessStageLibrary.createBrightnessStage());
window.$icy.viewer.scene.brightness.enabled = true;
window.$icy.viewer.scene.brightness.uniforms.brightness = Number(1.05); // 此处亮度值为倍数
createGlb(); // 加载glb
};
const bd09ToWgs84 = (bdLat, bdLon) => {
const x_pi = (Math.PI * 3000.0) / 180.0;
const x = bdLon - 0.0065;
const y = bdLat - 0.006;
const z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
const theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
const gcjLon = z * Math.cos(theta);
const gcjLat = z * Math.sin(theta);
let dlat = transformlat(gcjLon - 105.0, gcjLat - 35.0);
let dlng = transformlng(gcjLon - 105.0, gcjLat - 35.0);
const radlat = (gcjLat / 180.0) * Math.PI;
let magic = Math.sin(radlat);
magic = 1 - 0.006693421622965943 * magic * magic;
const sqrtmagic = Math.sqrt(magic);
dlat =
(dlat * 180.0) /
(((6378245.0 * (1 - 0.006693421622965943)) / (magic * sqrtmagic)) *
Math.PI);
dlng =
(dlng * 180.0) / ((6378245.0 / sqrtmagic) * Math.cos(radlat) * Math.PI);
const mglat = gcjLat + dlat;
const mglng = gcjLon + dlng;
const wgsLon = gcjLon * 2 - mglng;
const wgsLat = gcjLat * 2 - mglat;
return [wgsLat, wgsLon];
};
const transformlat = (lng, lat) => {
let ret =
-100.0 +
2.0 * lng +
3.0 * lat +
0.2 * lat * lat +
0.1 * lng * lat +
0.2 * Math.sqrt(Math.abs(lng));
ret +=
((20.0 * Math.sin(6.0 * lng * Math.PI) +
20.0 * Math.sin(2.0 * lng * Math.PI)) *
2.0) /
3.0;
ret +=
((20.0 * Math.sin(lat * Math.PI) + 40.0 * Math.sin((lat / 3.0) * Math.PI)) *
2.0) /
3.0;
ret +=
((160.0 * Math.sin((lat / 12.0) * Math.PI) +
320 * Math.sin((lat * Math.PI) / 30.0)) *
2.0) /
3.0;
return ret;
};
// 纬度转换
const transformlng = (lng, lat) => {
let ret =
300.0 +
lng +
2.0 * lat +
0.1 * lng * lng +
0.1 * lng * lat +
0.1 * Math.sqrt(Math.abs(lng));
ret +=
((20.0 * Math.sin(6.0 * lng * Math.PI) +
20.0 * Math.sin(2.0 * lng * Math.PI)) *
2.0) /
3.0;
ret +=
((20.0 * Math.sin(lng * Math.PI) + 40.0 * Math.sin((lng / 3.0) * Math.PI)) *
2.0) /
3.0;
ret +=
((150.0 * Math.sin((lng / 12.0) * Math.PI) +
300.0 * Math.sin((lng / 30.0) * Math.PI)) *
2.0) /
3.0;
return ret;
};
// eslint-disable-next-line no-unused-vars
const flyTo = (lng, lat) => {
window.$carmer.flyTo({
// 视角飞入
maxHeight: 1500,
time: 1,
position: [lng, lat, 200],
angle: [0, -60, 0],
});
};
const createGlb = () => {
// 加载glb建筑模型
const loadGlb = new Loadglb(window.$icy);
loadGlb.model(window.CustomCesium.Model);
};
// eslint-disable-next-line no-unused-vars
export const handleMouseClick = (model_id) => {
// 加载鼠标拾取
const $mouse = new window.CustomCesium.Mouse(window.$icy);
// 隐藏逻辑
$mouse.mouseLeft((model) => {
if (model._name === "建筑") {
model_id.value = model._id;
clickBuilding(model);
}
});
};
const clickBuilding = (model) => {
if (
Loadglb.modelMap[
`${model._id.split("-")[3].slice(0, model._id.split("-")[3].length - 2)}`
]
) {
if (
clickModel.get(
`${model._id
.split("-")[3]
.slice(0, model._id.split("-")[3].length - 2)}`
) === undefined
) {
// 如果这个模型是第一次点击
const m =
Loadglb.modelMap[
`${model._id
.split("-")[3]
.slice(0, model._id.split("-")[3].length - 2)}`
]; // 整栋楼的id集合
// console.log(m, '整栋楼id');
if (m.length > 1) {
// 当前点击这建筑是否有多层
m.forEach((id) => {
const entity = window.$icy.viewer.entities.getById(id);
if (model.id !== id) {
// 排除当前点击楼层
if (entity._icy.height > model._icy.height) {
if (
$entityTransparent.map((a) => a._id).indexOf(entity._id) === -1
) {
$entityTransparent.push(entity);
}
// console.log(this.$entityTransparent, '被隐藏的模型楼层集合');
entity.model.show = false;
}
} else {
clickModel.set(
`${model._id
.split("-")[3]
.slice(0, model._id.split("-")[3].length - 2)}`,
model._icy.height
); // 存储这个模型数据
}
});
}
} else {
// 如果点击过这个模型
const m =
Loadglb.modelMap[
`${model._id
.split("-")[3]
.slice(0, model._id.split("-")[3].length - 2)}`
]; // 整栋楼的id集合
// console.log(m, '整栋楼id');
if (m.length > 1) {
// 当前点击这建筑是否有多层
if (
model._icy.height ===
clickModel.get(
`${model._id
.split("-")[3]
.slice(0, model._id.split("-")[3].length - 2)}`
)
) {
m.forEach((id) => {
const entity = window.$icy.viewer.entities.getById(id);
entity.model.show = true;
clickModel.delete(
`${model._id
.split("-")[3]
.slice(0, model._id.split("-")[3].length - 2)}`
);
});
} else {
m.forEach((id) => {
const entity = window.$icy.viewer.entities.getById(id);
if (model.id !== id) {
// 排除当前点击楼层
if (entity._icy.height > model._icy.height) {
if (
$entityTransparent.map((a) => a._id).indexOf(entity._id) ===
-1
) {
$entityTransparent.push(entity);
}
// console.log(this.$entityTransparent, '被隐藏的模型楼层集合');
entity.model.show = false;
}
} else {
clickModel.set(
`${model._id
.split("-")[3]
.slice(0, model._id.split("-")[3].length - 2)}`,
model._icy.height
); // 存储这个模型数据
}
});
}
}
}
// model.model.color = new Cesium.Color(1, 1, 1, 0.6);
}
};
// 还原建筑物
export const reduction = () => {
// 揭盖一键还原
if ($entityTransparent.length !== 0) {
$entityTransparent = $entityTransparent.forEach((item) => {
item.model.color = new window.Cesium.Color(1, 1, 1, 1);
item.model.show = true;
});
$entityTransparent = [];
}
};
export const handleEnclosure = (positions) => {
const $mouse = new window.CustomCesium.Mouse(window.$icy);
enclosure = new window.CustomCesium.Enclosure(window.$icy);
// 编辑围栏使用鼠标控件参照demo.html
enclosure.start();
$mouse.mouseRight((e) => {
enclosure.add(e.lng, e.lat, e.alt);
positions.push([e.lng, e.lat, e.alt]);
});
};
export const clearEnclosure = () => {
if (enclosure) {
try {
enclosure.show(false);
} catch (e) {}
enclosure.clear();
enclosure = new window.CustomCesium.Enclosure(window.$icy);
enclosure.start();
}
};
export const showEnclosure = (positions) => {
enclosure.finish();
enclosure.showDataSource(
positions, // 数据
30, // 高度
"yellow" // 颜色默认黄色
);
enclosure.show(true);
};
export const handlePut = (pos) => {
const $mouse = new window.CustomCesium.Mouse(window.$icy);
$mouse.mouseRight((e) => {
if (entities && entities.children) {
entities.children.forEach((e) => {
e.destroy();
});
entities = null;
}
entities = new window.CustomCesium.GroupModel("摆放地图实例");
addEntity("put_entity_00001", "put_entity_00001", e.lng, e.lat, e.alt);
pos.value = [e.lng, e.lat, e.alt];
});
};
const addEntity = (id, name, lon, lat, height) => {
const obj = {};
obj.entity = window.$icy.viewer.entities.add(
new window.Cesium.Entity({
id,
name,
position: window.Cesium.Cartesian3.fromDegrees(lon, lat, height),
billboard: {
image: "src/assets/images/map/peoIcon_green.png",
height: 36,
width: 30,
verticalOrigin: window.Cesium.VerticalOrigin.BOTTOM,
horizontalOrigin: window.Cesium.HorizontalOrigin.CENTER,
disableDepthTestDistance: Number.POSITIVE_INFINITY,
},
})
);
obj.show = (e) => {
obj.entity.show = e;
};
obj.destroy = () => {
window.$icy.viewer.entities.remove(obj.entity);
};
entities.add(obj);
};

View File

@ -1,38 +1,38 @@
<template>
<div style="display: inline-block">
<el-button
v-if="interceptTheSuffix(filePath, '.txt')"
link
type="primary"
v-if="interceptTheSuffix(filePath, '.txt')"
@click="fnPreviewTxt(filePath)"
>
[预览]
</el-button>
<el-button
v-if="interceptTheSuffix(filePath, '.pdf')"
text
link
type="primary"
v-if="interceptTheSuffix(filePath, '.pdf')"
@click="fnPreviewPdf(filePath)"
>
[预览]
</el-button>
<el-button
v-if="interceptTheSuffix(filePath, '.mp4')"
link
type="primary"
v-if="interceptTheSuffix(filePath, '.mp4')"
@click="fnPreviewVideo(filePath)"
>
[预览]
</el-button>
<el-button
link
type="primary"
v-if="
interceptTheSuffix(filePath, '.jpg') ||
interceptTheSuffix(filePath, '.png') ||
interceptTheSuffix(filePath, '.jpeg')
"
link
type="primary"
@click="fnPreviewImage(filePath)"
>
[预览]
@ -56,18 +56,18 @@
[预览]
</a>
<layout-pdf
:src="data.pdfDialog.src"
v-model:visible="data.pdfDialog.visible"
:src="data.pdfDialog.src"
append-to-body
/>
<layout-txt
:src="data.txtDialog.src"
v-model:visible="data.txtDialog.visible"
:src="data.txtDialog.src"
append-to-body
/>
<layout-video
:src="data.videoDialog.src"
v-model:visible="data.videoDialog.visible"
:src="data.videoDialog.src"
append-to-body
/>
<el-dialog v-model="data.imageDialog.visible" title="图片" append-to-body>

View File

@ -2,8 +2,8 @@
<el-dialog
title="文档"
:model-value="visible && model === 'dialog'"
@update:model-value="visible = false"
:append-to-body="appendToBody"
@update:model-value="visible = false"
>
<div v-if="visible" style="height: 690px; overflow-y: auto">
<vue-pdf

View File

@ -1,20 +1,20 @@
<template>
<layout-card>
<div v-for="item in 2" :key="item" :id="item === 2 ? 'printContent' : ''">
<div v-for="item in 2" :id="item === 2 ? 'printContent' : ''" :key="item">
<slot></slot>
</div>
<div class="tc mt-10" v-if="print">
<div v-if="print" class="tc mt-10">
<el-button
type="primary"
v-print="printObj"
v-show="false"
ref="buttonRef"
v-print="printObj"
type="primary"
>
打印
</el-button>
<el-button type="primary" @click="fnPrint"></el-button>
</div>
<div v-html="PRINT_STYLE" v-if="direction === 'horizontal'" />
<div v-if="direction === 'horizontal'" v-html="PRINT_STYLE" />
</layout-card>
</template>

View File

@ -1,12 +1,12 @@
<template>
<el-form ref="formRef" :rules="defineRules" :model="form" label-width="240px">
<el-row>
<el-col :span="24" v-if="!infoIsEmpty">
<el-col v-if="!infoIsEmpty" :span="24">
<el-form-item label="管控部门" prop="DEPTNAME">
<el-input :model-value="info.DEPTNAME" disabled />
</el-form-item>
</el-col>
<el-col :span="24" v-if="infoIsEmpty">
<el-col v-if="infoIsEmpty" :span="24">
<el-form-item label="管控部门" prop="DEPARTMENT_ID">
<layout-department
v-model="form.DEPARTMENT_ID"

View File

@ -3,7 +3,7 @@
<div>
<el-button type="primary" @click="fnOpen"></el-button>
</div>
<div style="border: 1px dashed #ccc" class="mt-10" v-if="modelValue">
<div v-if="modelValue" style="border: 1px dashed #ccc" class="mt-10">
<img :src="modelValue" alt="" style="width: 100%" />
</div>
</div>
@ -13,8 +13,10 @@
:width="800"
:height="300"
:is-crop="false"
:is-clear-bg-color="false"
:line-width="6"
line-color="#000"
bg-color="#fff"
/>
<template #footer>
<el-button @click="fnReset"></el-button>

View File

@ -15,6 +15,7 @@
:summary-method="summaryMethod"
:span-method="spanMethod"
:default-expand-all="defaultExpandAll"
:tree-props="treeProps"
@row-click="rowClick"
@row-dblclick="rowDblclick"
>
@ -102,6 +103,10 @@ const props = defineProps({
spanMethod: {
type: Function,
},
treeProps: {
type: Object,
default: () => ({ hasChildren: "hasChildren", children: "children" }),
},
});
const emits = defineEmits([
"update:pagination",

View File

@ -1,8 +1,8 @@
<template>
<layout-cascader
id="e725d2a91b8248f4b8f49889038df7de"
v-model="modelValue"
ref="cascaderRef"
v-model="modelValue"
:check-strictly="checkStrictly"
:level="level"
value="BIANMA"

View File

@ -3,10 +3,12 @@
<template #content>
<template v-if="imgs.length > 0">
<img
v-viewer
v-for="item in imgs"
:key="item.IMGFILES_ID"
:src="VITE_FILE_URL + item.FILEPATH"
v-viewer
:src="
item.FILEPATH ? VITE_FILE_URL + item.FILEPATH : VITE_FILE_URL + item
"
width="100"
height="100"
alt=""

View File

@ -1,5 +1,6 @@
<template>
<el-cascader
v-model="modelValue"
:options="options"
:props="{
multiple: true,
@ -7,7 +8,6 @@
children: 'nodes',
label: 'name',
}"
v-model="modelValue"
/>
</template>

View File

@ -14,8 +14,8 @@
accordion
:data="treeData"
:filter-node-method="fnFilterNode"
@node-click="nodeClick"
:default-expanded-keys="[id]"
@node-click="nodeClick"
/>
</template>

View File

@ -1,5 +1,5 @@
<template>
<el-dialog title="文本文档" v-model="visible" :append-to-body="appendToBody">
<el-dialog v-model="visible" title="文本文档" :append-to-body="appendToBody">
<el-input autosize :model-value="value" readonly type="textarea" />
</el-dialog>
</template>

View File

@ -1,7 +1,7 @@
<template>
<el-upload
style="width: 100%"
ref="uploadRef"
style="width: 100%"
:file-list="fileList"
:action="action"
multiple

View File

@ -3,8 +3,8 @@
<div class="mi-captcha-content">
<!-- 没有进行验证-->
<div
class="mi-captcha-radar"
v-if="!verificationPass"
class="mi-captcha-radar"
@click="verificationShow = true"
>
<div class="mi-captcha-radar-ready">
@ -15,8 +15,8 @@
</div>
<!-- 验证通过-->
<div
class="mi-captcha-radar mi-captcha-radar-pass"
v-if="verificationPass"
class="mi-captcha-radar mi-captcha-radar-pass"
>
<div class="mi-captcha-radar-success mi-captcha-radar-success-icon">
<span role="img" aria-label="verified">

View File

@ -1,10 +1,10 @@
<template>
<el-dialog title="视频" v-model="visible" :append-to-body="appendToBody">
<el-dialog v-model="visible" title="视频" :append-to-body="appendToBody">
<ali-player
ref="playerRef"
:source="fnSrc(src)"
:vid="vid"
:play-auth="playAuth"
ref="playerRef"
:visible="visible"
/>
</el-dialog>

View File

@ -3,14 +3,35 @@
style="display: flex; justify-content: space-between; align-items: center"
>
<div class="breadcrumb">
<icon-local theme="filled" size="22" fill="#10a7e5" :stroke-width="3" />
<el-tooltip
v-if="isDEV"
placement="top"
:content="
route.matched
.at(-1)
.components.default.__file.substring(
route.matched
.at(-1)
.components.default.__file.indexOf('src/views')
)
"
>
<icon-local theme="filled" size="22" fill="#10a7e5" :stroke-width="3" />
</el-tooltip>
<icon-local
v-else
theme="filled"
size="22"
fill="#10a7e5"
:stroke-width="3"
/>
<el-breadcrumb class="app-breadcrumb" separator=">">
<transition-group name="breadcrumb">
<el-breadcrumb-item
v-for="(item, index) in data.breadcrumbList"
:key="item.path"
>
<router-link v-if="index === 0" :to="item.path">
<router-link v-if="index === 0" to="/index">
{{ item.meta.title }}
</router-link>
<span v-else-if="index !== data.breadcrumbList.length - 1">
@ -23,15 +44,15 @@
</div>
<div class="return">
<el-button
type="primary"
text
link
@click="$router.back()"
v-if="
route.meta?.activeMenu &&
route.path &&
route.meta?.activeMenu !== route.path
"
type="primary"
text
link
@click="$router.back()"
>
返回上一页
</el-button>
@ -46,6 +67,7 @@ import { useRoute } from "vue-router";
defineOptions({
name: "LayoutBreadcrumb",
});
const isDEV = import.meta.env.DEV;
const route = useRoute();
const data = reactive({
breadcrumbList: [],

View File

@ -5,7 +5,7 @@
width="600px"
:before-close="fnClose"
>
<el-form :model="form" :rules="rules" label-width="100px" ref="formRef">
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
<el-form-item label="头像" prop="file">
<layout-upload
v-model:file-list="form.file"

View File

@ -5,7 +5,7 @@
width="600px"
:before-close="fnClose"
>
<el-form :model="form" :rules="rules" label-width="100px" ref="formRef">
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
<el-form-item label="用户名" prop="USERNAME">
<el-input
v-model="form.USERNAME"
@ -31,8 +31,8 @@
</el-form-item>
<el-form-item label="备注" prop="BZ">
<el-input
:rows="3"
v-model="form.BZ"
:rows="3"
type="textarea"
placeholder="这里输入备注..."
/>

View File

@ -1,19 +1,17 @@
<template>
<div class="header">
<div class="left">
<div class="logo">管理平台</div>
<div class="logo" />
<div class="menu">
<ul>
<li @click="router.push({ path: '/BI' })">
<!-- <div v-for="item1 in 4" :key="item1" :class="'horn' + item1" />-->
<li @click="router.push({ path: '/large_screen_data_display' })">
<div class="title">BI</div>
</li>
<template v-for="(item, index) in MENU" :key="index">
<li
@click="switchMenu(item.model)"
:class="{ active: item.model === menuStore.getModel }"
@click="switchMenu(item.model)"
>
<!-- <div v-for="item1 in 4" :key="item1" :class="'horn' + item1" />-->
<div class="title">{{ item.title }}</div>
</li>
</template>
@ -69,11 +67,13 @@ import { useMenuStore } from "@/pinia/menu";
import { useUserStore } from "@/pinia/user";
import { MENU } from "@/assets/js/constant";
import { getInfo, getUserInfo, logout } from "@/request/api";
import { getSpecialOperationsWarnAmount } from "@/request/special_operations";
import UpdateInfo from "./components/update_info.vue";
import UpdateAvatar from "./components/update_avatar.vue";
import { checkImgExists, addingPrefixToFile } from "@/assets/js/utils.js";
import { useWebSocket } from "@vueuse/core";
import { nanoid } from "nanoid";
import { ElNotification } from "element-plus";
defineOptions({
name: "LayoutHeader",
@ -153,6 +153,19 @@ const fnSignOut = async () => {
userStore.$reset();
await router.replace("/login");
};
const fnSpecialOperationsWarnAmount = async () => {
const resData = await getSpecialOperationsWarnAmount();
if (resData.message) {
ElNotification({
title: "温馨提示",
dangerouslyUseHTMLString: true,
message: resData.message,
duration: 0,
type: "warning",
});
}
};
fnSpecialOperationsWarnAmount();
</script>
<style lang="scss" scoped>
@ -172,14 +185,11 @@ const fnSignOut = async () => {
width: max-content;
.logo {
background-image: url("/src/assets/images/public/logo.png");
width: 500px;
height: var(--el-header-height);
line-height: var(--el-header-height);
padding-left: 20px;
color: #fff;
font-size: 20px;
font-weight: 700;
font-family: cursive;
height: 69px;
background-repeat: no-repeat;
background-size: 100% 100%;
}
.menu {
@ -208,6 +218,7 @@ const fnSignOut = async () => {
background-size: 100% 100%;
border: 1px solid #2870bb;
}
.title {
padding-left: 3px;
font-size: 14px;

View File

@ -40,7 +40,7 @@ import { useMenuStore } from "@/pinia/menu";
import { useRoute } from "vue-router";
defineOptions({
name: "layout",
name: "Layout",
});
const menuStore = useMenuStore();
const route = useRoute();

View File

@ -7,8 +7,8 @@
:route="{ path: menu.path }"
>
<component
v-if="menu.meta?.icon"
:is="'icon-' + menu.meta.icon"
v-if="menu.meta?.icon"
theme="outline"
fill="#fff"
size="18"
@ -21,8 +21,8 @@
<el-sub-menu v-else-if="fnIsShowSubmenu(menu)" :index="menu.path">
<template #title>
<component
v-if="menu.meta?.icon"
:is="'icon-' + menu.meta.icon"
v-if="menu.meta?.icon"
theme="outline"
fill="#fff"
size="18"

View File

@ -25,8 +25,8 @@ import ElDialog from "element-plus/es/components/dialog/index";
ElDialog.props.closeOnClickModal.default = false;
ElDialog.props.closeOnPressEscape.default = false;
const app = createApp(App);
app.component("layout-table", LayoutTable);
app.component("layout-card", LayoutCard);
app.component("LayoutTable", LayoutTable);
app.component("LayoutCard", LayoutCard);
install(app, "icon");
app
.use(pinia)

View File

@ -78,7 +78,7 @@
{{ data.info.HAVEPLAN === "1" ? "有" : "" }}
</template>
</van-cell>
<van-cell title="计划图片" v-if="data.info.HAVEPLAN === '1'">
<van-cell v-if="data.info.HAVEPLAN === '1'" title="计划图片">
<template #label>
<img
v-for="(item, index) in data.pImgs"
@ -92,7 +92,7 @@
/>
</template>
</van-cell>
<van-cell title="整改方案" v-if="data.info.RECTIFICATIONTYPE === '2'">
<van-cell v-if="data.info.RECTIFICATIONTYPE === '2'" title="整改方案">
<template #value>
{{ data.info.HAVESCHEME === "0" ? "无" : "" }}
{{ data.info.HAVESCHEME === "1" ? "有" : "" }}

View File

@ -12,9 +12,9 @@
<van-checkbox :name="0">合格</van-checkbox>
<van-checkbox :name="1" checked-color="red"> 不合格 </van-checkbox>
<van-icon
v-if="item.ISNORMAL.includes(1)"
name="info-o"
color="blue"
v-if="item.ISNORMAL.includes(1)"
@click="
$router.push({
path,

View File

@ -23,11 +23,9 @@
<van-cell title="资产总额(万元)" :value="info.TOTALASSETS" />
<van-cell title="隶属关系" :value="info.SUBORDINATIONNAME" />
<van-cell title="企业类型">
<template>
{{ info.CORP_OF_TYPE_NAME ? info.CORP_OF_TYPE_NAME : "" }}
{{ info.CORP_OF_TYPE_NAME && info.CORP_OF_TYPE_NAME2 ? "/" : "" }}
{{ info.CORP_OF_TYPE_NAME2 ? info.CORP_OF_TYPE_NAME2 : "" }}
</template>
{{ info.CORP_OF_TYPE_NAME ? info.CORP_OF_TYPE_NAME : "" }}
{{ info.CORP_OF_TYPE_NAME && info.CORP_OF_TYPE_NAME2 ? "/" : "" }}
{{ info.CORP_OF_TYPE_NAME2 ? info.CORP_OF_TYPE_NAME2 : "" }}
</van-cell>
<van-cell
title="市行业监管部门"
@ -35,22 +33,20 @@
/>
<van-cell title="规模" :value="info.SCALE_NAME" />
<van-cell title="是否规模以上">
<template>
{{ info.SCALE_TYPE === "0" ? "否" : "" }}
{{ info.SCALE_TYPE === "1" ? "是" : "" }}
</template>
{{ info.SCALE_TYPE === "0" ? "否" : "" }}
{{ info.SCALE_TYPE === "1" ? "是" : "" }}
</van-cell>
<van-cell title="培训行业类型" :value="info.TRAINTYPE_NAME" />
<van-cell title="企业可新建用户数量" :value="info.USERS_NUM" />
<van-cell title="单位经营地址" :value="info.ADDRESS_BUSINESS" />
<van-cell title="四色图" v-if="info.FOURTYPE === '1'">
<van-cell v-if="info.FOURTYPE === '1'" title="四色图">
<template #label>
<van-image
v-for="(item, index) in four_images"
:key="item"
width="100"
height="100"
v-for="(item, index) in four_images"
:src="item"
:key="item"
@click="fnImagePreview(four_images, index)"
/>
</template>
@ -58,11 +54,11 @@
<van-cell title="营业执照">
<template #label>
<van-image
v-for="(item, index) in bus_images"
:key="item"
width="100"
height="100"
v-for="(item, index) in bus_images"
:src="item"
:key="item"
@click="fnImagePreview(bus_images, index)"
/>
</template>

View File

@ -0,0 +1,10 @@
import { post } from "@/request/axios.js";
export const getGatheringAlarmRecordsList = (params) =>
post("/positAlarm/getAlarmRecordList", params); // 聚集告警记录列表
export const getAggregationAlarmTrend = (params) =>
post("/positAlarm/aggregateAlarmTrends", params); // 聚集报警趋势
export const getAggregatedDataStatistics = (params) =>
post("/positAlarm/aggregateDataStatistics", params); // 聚集区域统计
export const getAggregationAreaStatistics = (params) =>
post("/positAlarm/aggregateDataStatisticsByGroup", params); // 聚集数据统计

View File

@ -0,0 +1,26 @@
import { post } from "@/request/axios.js";
export const getOtherAlarmConfigurationsList = (params) =>
post("/positAlarm/electronicFence/list", params); // 其他告警配置列表
export const getOtherAlarmConfigurationsView = (params) =>
post("/positAlarm/electronicFenceGoEdit", params); // 其他告警配置查看
export const setOtherAlarmConfigurationsDelete = (params) =>
post("/positAlarm/electronicFenceDelete", params); // 其他告警配置删除
export const setOtherAlarmConfigurationsDeactivateOrEnable = (params) =>
post("/positAlarm/electronicFenceStatus", params); // 其他告警配置停用启用
export const setOtherAlarmConfigurationsAdd = (params) =>
post("/positAlarm/electronicFenceSave", params); // 其他告警配置新增
export const setOtherAlarmConfigurationsEdit = (params) =>
post("/positAlarm/electronicFenceEdit", params); // 其他告警配置修改
export const getPsnInformationList = (params) =>
post("/positAlarm/getPsnInfo", params); // 其他告警配置新增
export const getDeptInformationList = (params) =>
post("/positAlarm/getDeptList", params); // 其他告警配置修改
export const getAlarmInformationList = (params) =>
post("/positAlarm/getAlArmDataList", params); // 告警信息列表
export const setAlarmInformationBatchProcessing = (params) =>
post("/positAlarm/alarmHandling", params); // 告警信息批量处理
export const setAlarmInformationOneClickProcessing = (params) =>
post("/positAlarm/alarmHandlingAll", params); // 告警信息一键处理

View File

@ -58,6 +58,9 @@ axios.interceptors.response.use(
error.message = `连接错误${error.response.status}`;
import.meta.env.DEV &&
ElMessage.error(`连接错误${error.response.status}`);
endLoading();
ElMessage.error("登录失效,请重新登陆");
router.push("/login").then();
}
} else {
error.message = "连接到服务器失败";
@ -78,14 +81,14 @@ export function post(url, params) {
},
})
.then((res) => {
if (
res.config.url === "/app/audioOrVideo/createUploadVideo" ||
res.config.url === "/app/audioOrVideo/refreshUploadVideo"
) {
res.data.result = "success";
}
if (res.data.result === "success") {
resolve(res.data);
if (res.config.url.split("/")[1] === "positAlarm") {
if (res.data.code === 200 || res.data.code === 0) resolve(res.data);
else {
ElMessage.error(res.data.msg || "系统开小差了");
reject(res.data);
}
} else resolve(res.data);
} else {
ElMessage.error(
res.data.msg ||

View File

@ -4,6 +4,10 @@ export const getPersonnelTypeCount = (params) =>
post("/map/getPersonnelTypeCount", params); // 人员类型统计
export const getAlarmTypeCount = (params) =>
post("/map/getAlarmTypeCount", params); // 告警类型统计
export const getAlArmDataList = (params) =>
post("/map/getAlArmDataList", params); // 告警类型统计
export const getPersonnelPositioningCount = (params) =>
post("/map/getPersonnelPositioningCount", params); // 人员定位情况
// 八项作业

View File

@ -39,12 +39,18 @@ export const getUserListAllByCorp = (params) =>
loading: false,
...params,
});
// 部门树
// 部门树 有限制只有主账号能选子集
export const getDepartmentTree = (params) =>
post("/department/listTree", {
loading: false,
...params,
});
// 部门树
export const getDepartmentzTree = (params) =>
post("/department/listzTree", {
loading: false,
...params,
});
// 电子围栏树
export const getElectronicFenceTree = (params) =>
post("/electronicfence/listTree", {

View File

@ -95,6 +95,8 @@ export const setCheckStandardSupplementaryRecordingSubmit = (params) =>
post("/customCheckrecord/recording", params); // 隐患排查清单检查情况检查记录补录提交
export const setCheckStandardSubmit = (params) =>
post("/customCheckrecord/add", params); // 清单排查提交
export const getCustomCheckRecordMap = (params) =>
post("/customCheckrecord/goMap", params); // 清单检查情况检查记录查看地图
export const setCommonItemEdit = (params) =>
post("/hiddenstandardCommon/edit", params); // 隐患排查检查标准修改
export const setCustomImport = (params) =>

View File

@ -1,6 +1,8 @@
import { post, upload } from "@/request/axios.js";
export const getHiddenDangerList = (params) => post("/hidden/list", params); // 隐患列表
export const getHiddenDangerListAll = (params) =>
post("/hidden/hiddenListAll", params); // 隐患列表
export const getHiddenDangerRectificationWhy = (params) =>
post("/app/corpinfo/goqyzzh", params); // 隐患整改不知道在获取什么
export const setHiddenDangerRectificationNormalSubmit = (params) =>
@ -8,10 +10,18 @@ export const setHiddenDangerRectificationNormalSubmit = (params) =>
export const setHiddenDangerRectificationAbnormalSubmit = (params) =>
post("/hidden/editRec", params); // 隐患整改不正常整改提交
export const setHiddenDangerAcceptSubmit = (params) =>
post("/hidden/check", params); // 隐患验提交
post("/hidden/check", params); // 隐患验提交
export const setHiddenDangerCancelMajorHazards = (params) =>
post("/hidden/editHIDDENLEVEL", params); // 重大隐患管理取消重大隐患
export const setHiddenDangerConfirmMajorHazards = (params) =>
post("/hidden/editISCONFIRM", params); // 重大隐患管理确认重大隐患
export const getHiddenDangerPrintList = (params) =>
post("/hidden/listAllToPrint", params); // 隐患打印列表
export const setCustomHiddenDangerRectificationNormalSubmit = (params) =>
upload("/customHidden/rectify", params); // 隐患整改正常整改提交 *隐患排查
export const setCustomHiddenDangerRectificationAbnormalSubmit = (params) =>
post("/customHidden/editRec", params); // 隐患整改不正常整改提交*隐患排查
export const setCustomHiddenDangerAcceptSubmit = (params) =>
post("/customHidden/check", params); // 隐患验证提交*隐患排查
export const setCustomHiddenDangerConfirmMajorHazards = (params) =>
post("/customHidden/editISCONFIRM", params); // 重大隐患管理确认重大隐患*隐患排查

23
src/request/index.js Normal file
View File

@ -0,0 +1,23 @@
import { post } from "@/request/axios.js";
export const getHiddenCount = (params) =>
post("/hidden/getCountByUserId", params); // 隐患数量
export const getMemoryUsage = (params) =>
post("/service/notice/getMemoryUsage", params); // 储存空间
export const getListCheckType = (params) =>
post("/listmanager/goIndexCount", params); // 清单检查类型统计
export const getChecklistCheck = (params) =>
post("/checkrecord/goIndexCount", params); // 清单检查完成率统计
export const getPlatformAnnouncement = (params) =>
post("/service/notice/listByIndex", params); // 平台公告
export const getCorporateAnnouncement = (params) =>
post("/noticecorp/listByIndex", params); // 企业公告
export const getPlatformAnnouncementView = (params) =>
post("/service/notice/goEdit", params); // 平台公告查看
export const getCorporateAnnouncementView = (params) =>
post("/noticecorp/goEdit", params); // 企业公告查看
export const getCalendar = (params) => post("/schedule/getData", params); // 日历
export const getCalendarAdd = (params) => post("/schedule/add", params); // 日历添加
export const getCalendarEdit = (params) => post("/schedule/edit", params); // 日历修改
export const getWorkReminder = (params) =>
post("/listmanager/checkListIndex", params); // 工作提醒

View File

@ -36,8 +36,8 @@ export const setOutsourcedGoEdit = (params) =>
post("/outsourced/goEdit", params); // 重点工程修改获取
export const setOutsourcedDelete = (params) =>
post("/outsourced/delete", params); // 重点工程修改获取
export const getOutsourcedJie = (params) => post("/outsourced/jie", params); // 结束工程
export const getOutsourcedStart = (params) => post("/outsourced/start", params); // 结束工程
export const getOutsourcedUpdateState = (params) =>
post("/outsourced/updateState", params); // 结束工程
export const getKeyprojectcheckList = (params) =>
post("/keyprojectcheck/list", params); // 安全环保检查列表

View File

@ -0,0 +1,23 @@
import { post } from "@/request/axios.js";
export const getRiskManagement = (params) =>
post("/riskpoint/statistic", params); // 风险管控统计分析
export const getTroubleshootingTypeNumber = (params) =>
post("/listmanager/countNumBi", params); // 排查类型
export const getTroubleshootingTypeEcharts = (params) =>
post("/checkrecord/listTypeBi", params); // 排查类型
export const getUserUsage = (params) => post("/checkrecord/countNumBi", params); // 企业排查情况
export const getTaskProcessingHidden = (params) =>
post("/hidden/getBICount", params); // 任务处理情况隐患处理
export const getTaskProcessingCheck = (params) =>
post("/checkrecord/goBiListCount", params); // 任务处理情况日常检查
export const getHiddenCount = (params) => post("/hidden/hiddenSta", params); // 隐患数量
export const getAssignmentType = (params) =>
post("/eightWork/eightWorkBI", params); // 作业类型
export const getVideo = (params) => post("/video/getObjectForBiLogin", params); // 视频中心
export const getFullStaffTraining = (params) =>
post("/studytask/BIstatistics", params); // 全员培训统计
export const getExamStatisticsUser = (params) =>
post("/performanceexamine_user/list", params); // 考核情况统计用户
export const getExamStatisticsDepartment = (params) =>
post("/performanceexamine_dept/list", params); // 考核情况统计部门

Some files were not shown because too many files have changed in this diff Show More