init: 德州大陆架TV看板项目首次入库

This commit is contained in:
XingCheng3
2026-06-08 17:35:47 +08:00
commit df90e259c5
177 changed files with 36482 additions and 0 deletions

24
src/App.vue Normal file
View File

@@ -0,0 +1,24 @@
<template>
<div id="app">
<keep-alive>
<router-view v-if="this.$route.meta.keepAlive"/>
</keep-alive>
<router-view v-if="!this.$route.meta.keepAlive"/>
</div>
</template>
<style>
#app {
font-family: MiSans Bold, serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #2c3e50;
/*font-family: Microsoft YaHei!important;*/
}
.el-dialog__wrapper {
pointer-events: none;
}
.el-dialog {
pointer-events: auto;
}
</style>

View File

@@ -0,0 +1,70 @@
@font-face {
font-family: MiSans Demibold;
src: url("MiSans-Demibold.ttf");
font-weight: normal;
font-style: normal;
font-display: block;
}
@font-face {
font-family: MiSans Bold;
src: url("MiSans-Bold.ttf");
font-weight: normal;
font-style: normal;
font-display: block;
}
@font-face {
font-family: MiSans ExtraLight;
src: url("MiSans-ExtraLight.ttf");
font-weight: normal;
font-style: normal;
font-display: block;
}
@font-face {
font-family: MiSans Heavy;
src: url("MiSans-Heavy.ttf");
font-weight: normal;
font-style: normal;
font-display: block;
}
@font-face {
font-family: MiSans Light;
src: url("MiSans-Light.ttf");
font-weight: normal;
font-style: normal;
font-display: block;
}
@font-face {
font-family: MiSans Medium;
src: url("MiSans-Medium.ttf");
font-weight: normal;
font-style: normal;
font-display: block;
}
@font-face {
font-family: MiSans Normal;
src: url("MiSans-Normal.ttf");
font-weight: normal;
font-style: normal;
font-display: block;
}
@font-face {
font-family: MiSans Regular;
src: url("MiSans-Regular.ttf");
font-weight: normal;
font-style: normal;
font-display: block;
}
@font-face {
font-family: MiSans Semibold;
src: url("MiSans-Semibold.ttf");
font-weight: normal;
font-style: normal;
font-display: block;
}
@font-face {
font-family: MiSans Thin;
src: url("MiSans-Thin.ttf");
font-weight: normal;
font-style: normal;
font-display: block;
}

BIN
src/assets/img/jiegang1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@@ -0,0 +1,155 @@
class VRButton {
static createButton(renderer, options) {
if (options) {
console.error('THREE.VRButton: The "options" parameter has been removed. Please set the reference space type via renderer.xr.setReferenceSpaceType() instead.')
}
const button = document.createElement('button')
function showEnterVR(/* device*/) {
let currentSession = null
async function onSessionStarted(session) {
session.addEventListener('end', onSessionEnded)
await renderer.xr.setSession(session)
button.textContent = 'EXIT VR'
currentSession = session
}
function onSessionEnded(/* event*/) {
currentSession.removeEventListener('end', onSessionEnded)
button.textContent = 'ENTER VR'
currentSession = null
}
//
button.style.display = ''
button.style.cursor = 'pointer'
button.style.left = 'calc(50% - 50px)'
button.style.width = '100px'
button.textContent = 'ENTER VR'
button.onmouseenter = function() {
button.style.opacity = '1.0'
}
button.onmouseleave = function() {
button.style.opacity = '0.5'
}
button.onclick = function() {
if (currentSession === null) {
// WebXR's requestReferenceSpace only works if the corresponding feature
// was requested at session creation time. For simplicity, just ask for
// the interesting ones as optional features, but be aware that the
// requestReferenceSpace call will fail if it turns out to be unavailable.
// ('local' is always available for immersive sessions and doesn't need to
// be requested separately.)
const sessionInit = { optionalFeatures: ['local-floor', 'bounded-floor', 'hand-tracking', 'layers'] }
navigator.xr.requestSession('immersive-vr', sessionInit).then(onSessionStarted)
} else {
currentSession.end()
}
}
}
function disableButton() {
button.style.display = ''
button.style.cursor = 'auto'
button.style.left = 'calc(50% - 75px)'
button.style.width = '150px'
button.onmouseenter = null
button.onmouseleave = null
button.onclick = null
}
function showWebXRNotFound() {
disableButton()
button.textContent = 'VR NOT SUPPORTED'
}
function showVRNotAllowed(exception) {
disableButton()
console.warn('Exception when trying to call xr.isSessionSupported', exception)
button.textContent = 'VR NOT ALLOWED'
}
function stylizeElement(element) {
element.style.position = 'absolute'
element.style.bottom = '20px'
element.style.padding = '12px 6px'
element.style.border = '1px solid #fff'
element.style.borderRadius = '4px'
element.style.background = 'rgba(0,0,0,0.1)'
element.style.color = '#fff'
element.style.font = 'normal 13px sans-serif'
element.style.textAlign = 'center'
element.style.opacity = '0.5'
element.style.outline = 'none'
element.style.zIndex = '999'
}
if ('xr' in navigator) {
button.id = 'VRButton'
button.style.display = 'none'
stylizeElement(button)
navigator.xr.isSessionSupported('immersive-vr').then(function(supported) {
supported ? showEnterVR() : showWebXRNotFound()
if (supported && VRButton.xrSessionIsGranted) {
button.click()
}
}).catch(showVRNotAllowed)
return button
} else {
const message = document.createElement('a')
if (window.isSecureContext === false) {
message.href = document.location.href.replace(/^http:/, 'https:')
message.innerHTML = 'WEBXR NEEDS HTTPS' // TODO Improve message
} else {
message.href = 'https://immersiveweb.dev/'
message.innerHTML = 'WEBXR NOT AVAILABLE'
}
message.style.left = 'calc(50% - 90px)'
message.style.width = '180px'
message.style.textDecoration = 'none'
stylizeElement(message)
return message
}
}
static xrSessionIsGranted = false;
static registerSessionGrantedListener() {
if ('xr' in navigator) {
navigator.xr.addEventListener('sessiongranted', () => {
VRButton.xrSessionIsGranted = true
})
}
}
}
VRButton.registerSessionGrantedListener()
export { VRButton }

View File

@@ -0,0 +1,327 @@
<template>
<div style="pointer-events: none">
<el-dialog title="修改配置文件" :visible.sync="dialogFormVisible" width="1000px" class="myDia" :modal="false" :close-on-press-escape="false" v-el-drag-dialog>
<el-collapse v-model="activeNames">
<el-collapse-item title="通讯配置" name="1">
<el-row class="row-Show">
<span class="title-show">标题</span>
<el-input size="mini" style="width: 300px" v-model="configInfo['title']"></el-input>
<span class="title-show">工位和协议</span>
<el-input size="mini" style="width: 120px" v-model="configInfo['webSocketOpName']"></el-input>
<el-input size="mini" style="width: 180px" v-model="configInfo['webSocketBSport']"></el-input>
</el-row>
<el-row class="row-Show">
<span class="title-show">通讯类型</span>
<el-radio-group size="mini" v-model="configInfo['connectType']">
<el-radio :label="1">WebSocket</el-radio>
<el-radio :label="2">MQTT</el-radio>
<el-radio :label="3">其他</el-radio>
</el-radio-group>
</el-row>
<el-row class="row-Show">
<span class="title-show">Socket_IP&Port</span>
<el-input size="mini" style="width: 300px" v-model="configInfo['webSocketIp']"></el-input>
<span class="title-show">MQTT_IP&Port</span>
<el-input size="mini" style="width: 200px" v-model="configInfo['MQTTHost']"></el-input>
<el-input size="mini" style="width: 100px" v-model="configInfo['MQTTPort']"></el-input>
</el-row>
<el-row class="row-Show">
<span class="title-show">数据服务器</span>
<el-input size="mini" style="width: 300px" v-model="configInfo['dataBaseURL']"></el-input>
<span class="title-show">node服务</span>
<el-input size="mini" style="width: 300px" v-model="configInfo['NodeRootIp']"></el-input>
</el-row>
</el-collapse-item>
<el-collapse-item name="2">
<template slot="title">
机器人/设备配置
<el-button size="mini" type="warning" style="margin-left: 10px" @click.stop.prevent="dialogFormVisible = false">重置配置文件</el-button>
<el-button size="mini" type="primary" style="margin-left: 10px" @click.stop.prevent="exportConfig">导出配置文件</el-button>
{{ currentUUid }}
</template>
<el-col :span="6">
<el-table
:data="tableDataRobot"
:highlight-current-row="false"
element-loading-text="数据加载中"
element-loading-spinner="el-icon-loading"
element-loading-background="rgba(0, 0, 0, 0.2)"
style="width: 100%"
max-height="300"
border
size="mini"
class="my-table-show"
@cell-dblclick="showEdit"
@row-click="rowClick">
<el-table-column type="index" label=" " align="center" width="40"/>
<!-- <el-table-column align="center" label="name">-->
<!-- <template slot-scope="scope">-->
<!-- {{ scope.row.name }}-->
<!-- </template>-->
<!-- </el-table-column>-->
<el-table-column align="center" label="机器人模型id">
<template slot-scope="scope">
<el-input v-if="scope.row.edit" size="mini" v-model="scope.row.uuid"></el-input>
<span v-else>{{ scope.row.uuid }}</span>
</template>
</el-table-column>
<el-table-column align="center" width="50px" label="操作">
<template slot-scope="scope">
<el-button size="mini" type="text" style="color: #00893d" @click="applyRobotConfig(scope.row)">应用</el-button>
<br>
<el-button size="mini" type="text" style="color: red">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-col>
<el-col :span="18">
<el-table
:data="RobotChildrenData"
:highlight-current-row="false"
element-loading-text="数据加载中"
element-loading-spinner="el-icon-loading"
element-loading-background="rgba(0, 0, 0, 0.2)"
style="width: 100%"
max-height="300"
border
size="mini">
<el-table-column type="index" label=" " align="center" width="50"/>
<!-- <el-table-column align="center" label="关节名字">-->
<!-- <template slot-scope="scope">-->
<!-- {{ scope.row.name }}-->
<!-- </template>-->
<!-- </el-table-column>-->
<el-table-column align="center" label="关节ID" width="150">
<template slot-scope="scope">
<el-input size="mini" v-model="scope.row.ModelId "></el-input>
</template>
</el-table-column>
<el-table-column align="center" label="type" width="110">
<template slot-scope="scope">
<el-select v-model="scope.row.type" size="mini">
<el-option
v-for="item in robotJointType"
:key="item.value"
:label="item.label"
:value="item.value"/>
</el-select>
</template>
</el-table-column>
<el-table-column align="center" label="axis" width="80">
<template slot-scope="scope">
<el-select v-model="scope.row.axis" size="mini">
<el-option
v-for="item in robotJointAxis"
:key="item.value"
:label="item.label"
:value="item.value"/>
</el-select>
</template>
</el-table-column>
<el-table-column align="center" label="flip" width="80">
<template slot-scope="scope">
<el-select v-model="scope.row.flip" size="mini">
<el-option
v-for="item in robotJointFlip"
:key="item.value"
:label="item.label"
:value="item.value"/>
</el-select>
</template>
</el-table-column>
<el-table-column align="center" label="delta" width="80">
<template slot-scope="scope">
<el-input size="mini" v-model="scope.row.delta "></el-input>
</template>
</el-table-column>
<el-table-column align="center" label="multiple" width="120">
<template slot-scope="scope">
<el-input size="mini" v-model="scope.row.multiple "></el-input>
</template>
</el-table-column>
<el-table-column align="center" width="50px" label="操作">
<template slot-scope="scope">
<el-button size="mini" type="text" style="color: #00893d" @click="applyRobotConfig(scope.row, scope.$index)">应用</el-button>
</template>
</el-table-column>
</el-table>
</el-col>
</el-collapse-item>
</el-collapse>
</el-dialog>
</div>
</template>
<script>
import Mousetrap from './js/mousetrap.js'
import axios from 'axios'
export default {
name: 'ConfigVue',
data() {
return {
currentUUid: '',
activeNames: '2',
configInfo: {},
tableDataRobot: [],
tableDataRobotChildren: {},
RobotChildrenData: [],
dialogFormVisible: false,
robotJointType: [
{
label: 'position',
value: 'position'
},
{
label: 'rotation',
value: 'rotation'
}
],
robotJointFlip: [
{
label: 1,
value: 1
},
{
label: -1,
value: -1
}
],
robotJointAxis: [
{
label: 'x',
value: 'x'
},
{
label: 'y',
value: 'y'
},
{
label: 'z',
value: 'z'
}
],
form: {
name: '',
region: '',
date1: '',
date2: '',
delivery: false,
type: [],
resource: '',
desc: ''
},
formLabelWidth: '120px'
}
},
mounted() {
this.getConfig().then(res => {
this.configInfo = res
console.log(res)
this.solveRobotInfoFirst()
})
const scope = this
Mousetrap.bind('ctrl+c', function() {
// scope.solveConfig()
// return false
})
},
methods: {
solveConfig() {
console.log('ctrl + c')
this.dialogFormVisible = !this.dialogFormVisible
},
getConfig() {
return new Promise((resolve, reject) => {
axios.get('./DMT_WEB/config/config.json').then(res => {
const configData = res.data
resolve(configData)
}).catch(err => {
reject(err)
})
})
},
solveRobotInfoFirst() {
this.tableDataRobot = []
this.tableDataRobotChildren = {}
for (const argumentsKey in this.configInfo.robotList) {
this.tableDataRobot.push({
name: '',
uuid: argumentsKey,
edit: false
})
this.tableDataRobotChildren[argumentsKey] = []
for (let i = 0; i < this.configInfo.robotList[argumentsKey].length; i++) {
this.tableDataRobotChildren[argumentsKey].push(this.configInfo.robotList[argumentsKey][i])
}
}
},
showEdit(row) {
row.edit = !row.edit
},
rowClick(row) {
this.currentUUid = row.uuid
this.RobotChildrenData = this.tableDataRobotChildren[row.uuid]
},
exportConfig() {
this.configInfo['robotList'] = this.tableDataRobotChildren
const saveJsonStr = JSON.stringify(this.configInfo)
const blob = new Blob([saveJsonStr], {
type: 'application/json'
})
const objectUrl = URL.createObjectURL(blob)
const aa = document.createElement('a')
aa.href = objectUrl
aa.download = 'config.json'
aa.click()
URL.revokeObjectURL(objectUrl)
},
applyRobotConfig(row, index) {
const rootRobotJoint = window.editor.robotList[this.currentUUid][index]
if (row.ModelId === rootRobotJoint.ModelId) {
window.editor.robotList[this.currentUUid][index].axis = row.axis
window.editor.robotList[this.currentUUid][index].delta = row.delta
window.editor.robotList[this.currentUUid][index].flip = row.flip
window.editor.robotList[this.currentUUid][index].type = row.type
}
}
}
}
</script>
<style scoped>
.row-Show {
margin: 10px 0
}
.title-show {
font-weight: bolder;
font-size: 16px;
margin: 0 10px;
width: 130px;
display: inline-block;
text-align: right;
}
</style>
<style>
.myDia .el-dialog {
pointer-events: auto;
}
.myDia .el-dialog__body {
padding: 5px 15px;
}
.myDia .el-dialog--center .el-dialog__body {
padding: 15px;
}
.myDia .el-dialog__title {
font-size: 22px;
color: #000000;
}
.myDia .el-dialog__header {
padding: 15px;
}
.myDia .el-dialog__wrapper{
pointer-events:none;
}
.myDia .el-dialog{
pointer-events:auto;
}
</style>

View File

@@ -0,0 +1,46 @@
export default{
bind(el, binding) {
const dialogHeaderEl = el.querySelector('.el-dialog__header')
const dragDom = el.querySelector('.el-dialog')
dialogHeaderEl.style = 'cursor:move;'
// 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
const sty = dragDom.currentStyle || window.getComputedStyle(dragDom, null)
dialogHeaderEl.onmousedown = (e) => {
// 鼠标按下,计算当前元素距离可视区的距离
const disX = e.clientX - dialogHeaderEl.offsetLeft
const disY = e.clientY - dialogHeaderEl.offsetTop
// 获取到的值带px 正则匹配替换
let styL, styT
// 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
if (sty.left.includes('%')) {
styL = +document.body.clientWidth * (+sty.left.replace(/\%/g, '') / 100)
styT = +document.body.clientHeight * (+sty.top.replace(/\%/g, '') / 100)
} else {
styL = +sty.left.replace(/\px/g, '')
styT = +sty.top.replace(/\px/g, '')
}
document.onmousemove = function(e) {
// 通过事件委托,计算移动的距离
const l = e.clientX - disX
const t = e.clientY - disY
// 移动当前元素
dragDom.style.left = `${l + styL}px`
dragDom.style.top = `${t + styT}px`
// 将此时的位置传出去
// binding.value({x:e.pageX,y:e.pageY})
}
document.onmouseup = function(e) {
document.onmousemove = null
document.onmouseup = null
}
}
}
}

View File

@@ -0,0 +1,13 @@
import drag from './drag'
const install = function(Vue) {
Vue.directive('el-drag-dialog', drag)
}
if (window.Vue) {
window['el-drag-dialog'] = drag
Vue.use(install); // eslint-disable-line
}
drag.install = install
export default drag

1402
src/components/DMT/index.vue Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,900 @@
<template>
<div style="height: 100%">
<div id="viewPort" style="width: 100%;height: 100%;display: flex;align-items: center;justify-content: center;"></div>
<div ref="modelProcess" style="position: absolute;top: 10px;left: 2px;color: white">正在加载模型0%</div>
<div style="display: none">
<audio controls loop id="alarm">
<source src="./libs/alarm.mp3" type="audio/mpeg">
</audio>
<audio controls id="clash">
<source src="./libs/alarm.mp3" type="audio/mpeg">
</audio>
</div>
</div>
</template>
<script>
import * as THREE from 'three'
import axios from 'axios'
import $ from 'jquery'
import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader.js'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js'
import * as TWEEN from 'three/examples/jsm/libs/tween.module.js'
import { DmtControl } from './libs/DmtControl.js'
import { connect } from './js/websocketConnect.js'
import { connectMqtt } from './js/MqttConnect.js'
import { PlaySoundCommand } from './js/PlaySoundCommand.js'
import SpriteText from './js/three-spritetext.module.js'
// eslint-disable-next-line no-unused-vars
let container, clock, scene, camera, axesHelper, renderer, Plane
let modelCount = 0
const editor = {
cameraStateZoom: 25,
addEventListener: THREE.EventDispatcher.prototype.addEventListener,
removeEventListener: THREE.EventDispatcher.prototype.removeEventListener,
dispatchEvent: THREE.EventDispatcher.prototype.dispatchEvent,
hasEventListener: THREE.EventDispatcher.prototype.hasEventListener,
showTagList: [{
title: '工件QY16KC',
ModelId: 'A113AD62-9CE7-4ACF-8D0C-8E8A597A8768',
object: null
}],
ip: '',
WeldLight1: '',
WeldLightVisible1: false,
WeldLight2: '',
WeldLightVisible2: false,
scene: null,
objectIdUUidMap: new Map(),
opname: '',
connectType: 1,
BSport: '',
IsAllowConnect: true,
service: axios.create({
baseURL: './submit/MESCommonBase.ashx',
timeout: 1500000 // 请求超时时间
}),
selected: null,
socket: null,
mqttClient: {
connected: false
},
ProjectCode: null,
sceneConfig: null,
resourcesTree: null,
attachments: null,
resources: null,
cameraState: null,
cameraStateAll: [],
isOk: false,
objectIdSet: new Map(),
animOperations: null,
CraftList: {},
moveTrigger: null,
camera: null,
cameraPosition: 10,
currentButton: 1,
cameraControls: null,
TagActList: {}, // 存放tag对应的类型
worker: {}, // 播放工艺的线程
RotationWorker: {}, // 自传工艺的线程
ModelRotateWorker: {}, // 自传工艺的的状态数据
rotateSpeed: 5 * Math.PI / 180,
getObjectById: null, // 方法 根据ModelId获取模型
solveAttachModel: null, // 方法 处理attach问题
removeObject: null, // 方法 移除模型
setModelWireFrame: null, // 方法 设置线框
setTransparent: null, // 方法 设置透明
showMessage: null, // 方法 显示消息
drawPartTextInfo: null, // 方法 模型上显示文字
ModelLabelList: new Map(), // 模型上显示列表
playSoundCommand: new PlaySoundCommand(), // 方法 警告
attachList: new Map(), // 记录attach列表
objMaterial: new Map(),
WareHouseList: [],
WareHouse: new Map(), // 立库库存表
WareHouseBasicModel: new Map(), // 立库库存基础 零件模型需要命名为warehousepart1-100 立库定位模型需要命名为warehouse1000-1009
ProtocolIdentifiers: {
Robot_7: 'Robot_7',
Device_3: 'Device_3',
Agv_3: 'Agv_3',
Device_1: 'Device_1',
FirstPosition: 'FirstPosition',
WareHousePart: 'WareHousePart',
Robot_6: 'Robot_6',
RobotTcp: 'RobotTcp',
DrawPath: 'DrawPath',
ReLoadData: 'ReLoadData',
PlayAct: 'PlayAct',
CraftCurrOperation: 'CraftCurrOperation',
Position: 'Position',
Select: 'Select',
DragMove: 'DragMove',
ModelTransparent: 'ModelTransparent',
Visible: 'Visible',
Frames: 'Frames',
ModelRotation: 'ModelRotation',
GoHome: 'GoHome',
GetJointAxisInfo: 'GetJointAxisInfo',
GetDeviceBaseTool: 'GetDeviceBaseTool',
GetJointValue: 'GetJointValue',
C_B_ImportModel: 'C_B_ImportModel',
SendURDF: 'SendURDF',
SendDeviceJson: 'SendDeviceJson',
GetDeviceJson: 'GetDeviceJson',
SendMotionInfo: 'SendMotionInfo',
C_B_ImportLayout: 'C_B_ImportLayout',
GetPoseLocation: 'GetPoseLocation',
C_B_SetProjectCode: 'C_B_SetProjectCode',
C_B_TagIDTrigger: 'C_B_TagIDTrigger',
C_B_ReLoad_TagIDHandler: 'C_B_ReLoad_TagIDHandler',
C_B_SetCurrSignalList: 'C_B_SetCurrSignalList',
SendClearModelInfo: 'SendClearModelInfo',
C_B_SaveProjectSimulationData: 'C_B_SaveProjectSimulationData',
C_B_GetProjectSimulationData: 'C_B_GetProjectSimulationData',
C_B_KinematicsEditing: 'C_B_KinematicsEditing',
C_B_SaveModel: 'C_B_SaveModel',
C_B_ObjectAlarm: 'C_B_ObjectAlarm',
C_B_JointMoveTo: 'C_B_JointMoveTo',
JointMoveTo: 'JointMoveTo' // DT|JointMoveTo|modelCode|{"J1":"1","J2":"2","J3":"3","J4":"4","J5":"5","J6":"6","J7":"7","J8":"8","J9":"9"}
},
craftPlaySolveType: {
visible: 'visible',
rotation: 'rotation',
craft: 'craft',
signalwrite: 'signalwrite',
wait: 'wait',
FrameData: 'FrameData',
attach: 'attach',
warning: 'warning'
},
FrameOperation: {
playCraft: true,
visibleObject: true,
rotationObject: true,
writeSignal: true,
waitSignal: true,
attach: true,
warning: true
},
signalSolveType: {
visible: 'visible',
rotation: 'rotation',
craft: 'craft',
targetLocation: 'targetlocation',
attach: 'attach',
warning: 'warning'
}
}
// eslint-disable-next-line no-unused-vars
let ModelListTransParentList = []
const ModelList = []
const ModelListId = []
// eslint-disable-next-line no-unused-vars
const timer = null
// eslint-disable-next-line no-unused-vars
const lastIntersectModel = null
// eslint-disable-next-line no-unused-vars
const onUpPosition = new THREE.Vector2()
var raycaster = new THREE.Raycaster()
var mouse = new THREE.Vector2()
export default {
components: {
},
name: 'DMT',
props: {
containerHeight: {
type: String,
default: '100vh'
},
containerWidth: {
type: String,
default: '100vw'
}
},
data() {
return {
checked: false,
cameraData: [],
object: null,
s: null
}
},
mounted() {
const scope = this
editor.objectIdSet = new Map()
editor.objMaterial = new Map()
editor.attachList = new Map()
this.getConfig().then(res => {
if (Object.hasOwnProperty.call(res, 'robotList')) {
editor.robotList = res.robotList
}
if (Object.hasOwnProperty.call(res, 'WareHouseList')) {
editor.WareHouseList = res.WareHouseList
}
if (Object.hasOwnProperty.call(res, 'transParentList')) {
ModelListTransParentList = res.transParentList
}
if (Object.hasOwnProperty.call(res, 'connectType')) {
editor.connectType = res.connectType
}
editor.mqttHost = res.MQTTHost
editor.mqttPort = res.MQTTPort
editor.ip = res.webSocketIp
editor.opname = res.webSocketOpName
editor.BSport = res.webSocketBSport
editor.rootIp = res.NodeRootIp
this.getProjectConfig()
})
editor.showMessage = function(message, type, time = 2000) {
scope.$message({
message: message,
type: type,
duration: time,
center: true
})
}
editor.addEventListener('dmtModelDBClick', function(event) {
console.log('dmtModelDBClick', event)
})
},
created() {
},
methods: {
getConfig() {
return new Promise((resolve, reject) => {
axios.get('./DMT_WEB/config/config.json').then(res => {
const configData = res.data
resolve(configData)
}).catch(err => {
reject(err)
})
})
},
/**
* 获取项目配置文件,用于初始隐藏模型
*/
getProjectConfig() {
const P1 = new Promise(function(resolve, reject) {
axios({
method: 'get',
url: './DMT_WEB/models/DTDATA.json'
}).then((res) => {
editor.animOperations = {}
editor.moveTrigger = {}
res.data.forEach(n => {
Object.keys(n).forEach(function(key) {
/**
* 获取播放数据并解析数据
*/
if (key === 'OperationTree') {
n[key].forEach(CraftData => {
editor.CraftList[CraftData.CraftCode] = {}
editor.CraftList[CraftData.CraftCode]['CraftName'] = CraftData.CraftName
editor.CraftList[CraftData.CraftCode]['Varieties'] = CraftData.Varieties
editor.CraftList[CraftData.CraftCode]['CurrPlay'] = CraftData.CurrPlay
if (CraftData.CraftPlayData.length < 2) {
editor.animOperations[CraftData.CraftCode] = ''
} else {
editor.animOperations[CraftData.CraftCode] = JSON.parse(CraftData.CraftPlayData)
}
editor.moveTrigger[CraftData.CraftCode] = {
moveStatus: 0,
myVarSetInterval: null,
doAnimation: false,
currentFrame: 0,
pausedFrame: 0,
animOperations: editor.animOperations[CraftData.CraftCode],
simPaceTime: 20,
moveStatusPosition: 0
}
})
}
/**
* HandlerType: 1:显隐,2:自转,3行为
* HandlerCode: 模型或者工艺代码
* HandlerValue: 显隐0/1 ,自传:正负转速&axis,行为暂停播放0/1
* TagValue:信号值
*/
if (key === 'TagTriggerHandler') {
n[key].forEach(TagActListValue => {
if (editor.TagActList[TagActListValue.TagID]) {
editor.TagActList[TagActListValue.TagID].push({
HandlerType: TagActListValue.HandlerType,
HandlerCode: TagActListValue.HandlerCode,
HandlerValue: TagActListValue.HandlerValue,
TagValue: TagActListValue.TagValue,
JointType: TagActListValue.JointType,
Axis: TagActListValue.Axis,
Flip: TagActListValue.Flip,
Value: TagActListValue.Value,
ValueFactor: TagActListValue.ValueFactor
})
} else {
editor.TagActList[TagActListValue.TagID] = []
editor.TagActList[TagActListValue.TagID].push({
HandlerType: TagActListValue.HandlerType,
HandlerCode: TagActListValue.HandlerCode,
HandlerValue: TagActListValue.HandlerValue,
TagValue: TagActListValue.TagValue,
JointType: TagActListValue.JointType,
Axis: TagActListValue.Axis,
Flip: TagActListValue.Flip,
Value: TagActListValue.Value,
ValueFactor: TagActListValue.ValueFactor
})
}
})
}
})
})
resolve(1)
})
})
const P2 = new Promise(function(resolve, reject) {
axios({
method: 'get',
url: './DMT_WEB/models/RobotPlan_Process.json'
}).then((res) => {
editor.sceneConfig = res.data.sceneConfig // 场景配置
editor.attachments = res.data.attachments // 附加物体
editor.resources = res.data.resources // 场景模型资源
editor.resourcesTree = res.data.resourcesTree // 模型树
editor.cameraState = res.data.cameraState // 场景相机位置
editor.ProjectCode = res.data.ProjectCode // 项目代码
editor.resourcesTree.forEach(res => {
if (res.treeType === 'OriginModel') {
ModelList.push(res.name)
}
})
editor.resources.forEach(res => {
editor.objectIdUUidMap.set(res.id, res)
})
editor.attachments.forEach(res => {
editor.attachList.set(res.RootId, res.attachList)
})
resolve(1)
}).catch((error) => { console.log(error) })
})
Promise.all([P1, P2]).then(res => {
this.init()
// this.getCameraData()
})
},
/**
* 设定模型初始状态
*/
setModelSates() {
// 模型的显示隐藏
editor.resourcesTree.forEach(res => {
if (res.visible === '0') {
if (editor.getObjectById(res.id)) {
editor.getObjectById(res.id).visible = !!(parseInt(res.visible))
}
}
})
const treeRes = editor.resourcesTree
for (const treeResValue of treeRes) {
if (treeResValue.treeType !== 'folder') {
const currentModel = editor.getObjectById(treeResValue.id)
if (Object.hasOwnProperty.call(treeResValue, 'WireFrame') && treeResValue.WireFrame) {
editor.setModelWireFrame(currentModel, true)
}
if (Object.hasOwnProperty.call(treeResValue, 'transParent') && treeResValue.transParent) {
editor.setTransparent(treeResValue.id, 0.3)
}
if (currentModel) currentModel.visible = !!parseInt(treeResValue.visible)
}
}
},
/**
* 设定场景初始状态
* @param type
*/
setSceneStates(type) {
switch (type) {
case '0':
scene.background = new THREE.Color('#dcdcdc')
break
case '1':
scene.background = new THREE.Color(editor.sceneConfig.RenderColorModel.color)
break
case '2':
if (editor.sceneConfig.RenderColorModel.image === '') {
editor.scene.background = new THREE.Color(editor.sceneConfig.RenderColorModel.color)
return
}
new THREE.TextureLoader().load(editor.sceneConfig.RenderColorModel.image === '', function(texture) {
scene.background = texture
texture.dispose()
})
break
default:
scene.background = new THREE.Color('#dcdcdc')
break
}
},
/**
* 初始化场景信息
*/
init() {
const scope = this
container = document.getElementById('viewPort')
clock = new THREE.Clock()
scene = new THREE.Scene()
editor.scene = scene
const width = container.clientWidth
const height = container.clientHeight
const k = width / height
const s = 100
camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 0, 2000)
camera.position.set(editor.cameraPosition, editor.cameraPosition, editor.cameraPosition)
camera.lookAt(scene.position)
camera.up.x = 0
camera.up.y = 0
camera.up.z = 1
scene.add(camera)
editor.camera = camera
axesHelper = new THREE.AxesHelper(1)
scene.add(axesHelper)
renderer = new THREE.WebGLRenderer({ antialias: true })
renderer.setPixelRatio(window.devicePixelRatio)
renderer.setSize(container.clientWidth, container.clientHeight)
renderer.setClearColor(0x666666, 0)
renderer.toneMapping = THREE.ACESFilmicToneMapping
renderer.toneMappingExposure = 0.8
renderer.shadowMap.enabled = true
renderer.hadowMapEnabled = true
renderer.shadowMap.type = THREE.PCFSoftShadowMap
renderer.outputColorSpace = THREE.SRGBColorSpace
renderer.textureEncoding = THREE.sRGBEncoding
// editor.WeldLight1 = this.drawWeldLight()
// editor.WeldLight2 = this.drawWeldLight()
const pmremGenerator = new THREE.PMREMGenerator(renderer)
pmremGenerator.compileEquirectangularShader()
const loader = new GLTFLoader().setPath('./DMT_WEB/models/')
const dracoLoader = new DRACOLoader()
new RGBELoader().setDataType(THREE.FloatType)
.load('./DMT_WEB/assets/venice_sunset_1k.hdr', function(texture) {
const envMap = pmremGenerator.fromEquirectangular(texture).texture
scene.environment = envMap
scene.background = new THREE.Color('#081f48')
texture.dispose()
pmremGenerator.dispose()
})
this.setSceneStates(editor.sceneConfig.RenderColorModel.model)
dracoLoader.setDecoderPath('./DMT_WEB/draco/')
loader.setDRACOLoader(dracoLoader)
editor.getObjectById = function(ModelId) {
let currentModel = null
const currentModelData = editor.objectIdSet.get(ModelId)
if (currentModelData) currentModel = currentModelData.object
return currentModel
}
editor.solveAttachModel = function(ModelId, attach = true) {
}
editor.removeObject = function(object) {
if (object === null) return
if (object.parent === null) return
object.parent.remove(object)
}
/**
* 设置模型线框
* @param currentObject
* @param WireframeValue
*/
editor.setModelWireFrame = function(currentObject, WireframeValue) {
currentObject.traverse(obj => {
if (obj instanceof THREE.Mesh) {
obj.material = editor.objMaterial.get(obj.id).clone()
obj.material['wireframe'] = WireframeValue
obj.material.needsUpdate = true
}
})
}
/**
* 模型透明
* @param ModelId
* @param Opacity 透明度
*/
editor.setTransparent = function(ModelId, Opacity = 0.3) {
new Promise((resolve, reject) => {
const TransModel = editor.getObjectById(ModelId)
if (!TransModel) {
console.warn('模型不存在setTransparent')
reject(false)
} else {
TransModel.traverse(obj => {
if (obj.material) {
const material_yuan = editor.objMaterial.get(obj.id).clone()
obj.material = material_yuan
if (Opacity !== 1) {
obj.material = new THREE.MeshStandardMaterial({
color: material_yuan.color,
side: 2,
transparent: true,
opacity: Opacity
})
}
}
})
resolve(true)
}
})
}
editor.drawPartTextInfo = function(ModelId, TagValue) {
new Promise((resolve, reject) => {
let LabelInfo = editor.ModelLabelList.get(ModelId)
const TransModel = editor.getObjectById(ModelId)
if (TransModel) {
if (!LabelInfo) {
LabelInfo = {
position: scope.getDeltaPosition(new THREE.Vector3(), { x: 0, y: 0, z: 0.5 }),
label: TagValue,
object: null
}
editor.ModelLabelList.set(ModelId, LabelInfo)
}
if (LabelInfo.object) editor.removeObject(LabelInfo.object)
if (TransModel.visible) {
LabelInfo.label = TagValue.replaceAll('\\n', '\n')
const spriteLabel = new SpriteText(LabelInfo.label, 0.2, '#000000')
// spriteLabel.borderColor = '#30ff00'
// spriteLabel.borderWidth = [0.3, 0.2]
spriteLabel.backgroundColor = 'rgb(255,183,0)'
spriteLabel.position.copy(LabelInfo.position)
LabelInfo.object = spriteLabel
TransModel.add(spriteLabel)
}
}
})
}
container.appendChild(renderer.domElement)
container.addEventListener('dblclick', this.ondblclick, false)
editor.cameraControls = new DmtControl(editor.camera, renderer.domElement)
editor.cameraControls.listenToKeyEvents(window) // optional
editor.cameraControls.update()
const light1 = new THREE.AmbientLight(new THREE.Color('#ffffff'), 1)
light1.name = 'ambient_light'
editor.cameraControls.object.add(light1)
const light2 = new THREE.DirectionalLight(new THREE.Color('#ffffff'), 1)
light2.position.set(0.5, 0, 0.866) // ~60º
light2.name = 'main_light'
editor.cameraControls.object.add(light2)
// document.getElementById('orientCubeWrapperDiv').style.display = 'none'
window.addEventListener('resize', this.onWindowResize, false)
const encoding = THREE.sRGBEncoding
editor.cameraControls.resetState(editor.cameraState.target, editor.cameraState.position, editor.cameraState.zoom0)
// 加载模型
for (let i = 0; i < ModelList.length; i++) {
loader.load(ModelList[i] + '.glb', function(gltf) {
const currentModel = gltf.scene.children[0]
if (currentModel.name === 'Plane') {
Plane = currentModel
}
currentModel.traverse(child => {
if (child['material']) {
child['material'].metalness = 1
if (child['material'].map) child['material'].map.encoding = encoding
if (child['material'].emissiveMap) child['material'].emissiveMap.encoding = encoding
if (child['material'].map || child['material'].emissiveMap) child['material'].needsUpdate = true
editor.objMaterial.set(child.id, child['material'])
}
})
scene.add(currentModel)
scope.setObjectByConfig(currentModel)
ModelListId.push(gltf.scene.id)
modelCount += 1
scope.$refs.modelProcess.innerText = '正在加载模型' + (modelCount / ModelList.length * 100).toFixed(2) + '%'
if (modelCount === ModelList.length) {
scope.$refs.modelProcess.style.display = 'none'
scope.lookObject(scene)
scope.setModelSates()
scope.connectService()
}
}, (xhr) => {
// eslint-disable-next-line handle-callback-err
}, (error) => {
modelCount += 1
console.log(`加载模型${ModelList[i].ModelName}出错!`)
if (modelCount === ModelList.length) {
scope.$refs.modelProcess.style.display = 'none'
scope.lookObject(scene)
scope.setModelSates()
scope.connectService()
}
})
}
this.animate()
},
/**
* 自适应窗口尺寸
*/
onWindowResize() {
renderer.setSize(container.clientWidth, container.clientHeight)
const s = 100; const k = container.clientWidth / container.clientHeight // 窗口宽高比
camera.left = -s * k
camera.right = s * k
camera.top = s
camera.bottom = -s
camera.updateProjectionMatrix()
this.render()
},
/**
* 根据有配置文件设置模型初始化属性
* @param object
*/
setObjectByConfig(object) {
const objectId = object.userData['ModelId']
const objectResource = editor.objectIdUUidMap.get(objectId)
if (objectResource) {
object.position.copy(
new THREE.Vector3(parseFloat(objectResource.location.position.x),
parseFloat(objectResource.location.position.y),
parseFloat(objectResource.location.position.z)
))
object.quaternion.copy(
new THREE.Quaternion(parseFloat(objectResource.location.quaternion.x),
parseFloat(objectResource.location.quaternion.y),
parseFloat(objectResource.location.quaternion.z),
parseFloat(objectResource.location.quaternion.w)
))
object.visible = Boolean(parseInt(objectResource.visible))
}
},
/**
* 渲染
*/
animate() {
this.render()
requestAnimationFrame(this.animate)
editor.attachList.forEach((attackList, ModelId) => {
const ModelAttachParent = editor.getObjectById(ModelId)
if (ModelAttachParent) {
if (!ModelAttachParent.lastMatrixWorld.equals(ModelAttachParent.matrixWorld)) {
for (const attackListElement of attackList) {
const attachModel = editor.getObjectById(attackListElement.ModelId)
if (attachModel) {
const newMatrixWord = ModelAttachParent.matrixWorld.clone()
const cubeTransWorld = newMatrixWord.clone().multiply(ModelAttachParent.lastMatrixWorld.clone().invert()).clone()
const cube2OldWorld = attachModel.matrixWorld.clone()
const cube2NewWorld = cubeTransWorld.clone().multiply(cube2OldWorld)
const cube2ParentWorld = attachModel.parent.matrixWorld.clone()
const cube2ParentNew = (cube2ParentWorld.invert()).multiply(cube2NewWorld)
const position = new THREE.Vector3()
const quaternion = new THREE.Quaternion()
const scale = new THREE.Vector3()
cube2ParentNew.decompose(position, quaternion, scale)
attachModel.quaternion.copy(quaternion)
attachModel.position.copy(position)
attachModel.updateMatrixWorld()
}
}
ModelAttachParent.lastMatrixWorld = ModelAttachParent.matrixWorld.clone()
}
}
})
TWEEN.update()
},
/**
* 渲染
*/
render() {
renderer.render(scene, camera)
this.sendCameraState(camera.zoom < editor.cameraStateZoom)
this.updatePosition(editor.selected)
},
connectService() {
switch (editor.connectType) {
case 1:
connect(editor)
break
case 2:
connectMqtt(editor)
break
default:
break
}
},
// drawWeldLight() {
// const geometry = new THREE.BufferGeometry()
// const vertices = []
// const textureLoader = new THREE.TextureLoader()
// const sprite1 = textureLoader.load('./css/lensflare0.png')
// const x = 0
// const y = 0.3
// const z = -0.07
// const materials = []
// vertices.push(x, y, z)
// geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3))
// const parameters = [
// [[1.0, 1, 1], sprite1, 50]
// ]
// const sprite = parameters[ 0 ][ 1 ]
// const size = parameters[ 0 ][ 2 ]
//
// materials[ 0 ] = new THREE.PointsMaterial({ size: size, map: sprite, blending: THREE.AdditiveBlending, depthTest: false, transparent: true })
// return new THREE.Points(geometry, materials[0])
// },
/**
* 解析模型
* @param object
*/
lookObject(object) {
object.traverse(function(child) {
if (!child) return
// 避免modelId重复
if (Object.hasOwnProperty.call(child.userData, 'ModelId')) {
if (editor.objectIdSet.has(child.userData['ModelId'])) {
child.userData['ModelId'] = child.uuid
editor.objectIdSet.set(child.uuid, {
ModelId: child.id,
Name: child.name,
position: JSON.parse(JSON.stringify(child.position)),
rotation: JSON.parse(JSON.stringify(child.rotation)),
quaternion: JSON.parse(JSON.stringify(child.quaternion)),
object: child,
matrix: child.matrix.clone(),
lastValue: null
})
} else {
editor.objectIdSet.set(child.userData['ModelId'], {
ModelId: child.id,
Name: child.name,
position: JSON.parse(JSON.stringify(child.position)),
rotation: JSON.parse(JSON.stringify(child.rotation)),
quaternion: JSON.parse(JSON.stringify(child.quaternion)),
object: child,
matrix: child.matrix.clone(),
lastValue: null
})
}
}
})
for (const robotListInfo in editor.robotList) {
for (const info of editor.robotList[robotListInfo]) {
info.object = editor.getObjectById(info.ModelId)
info.matrix = info.object ? info.object.matrix.clone() : null
info.lastValue = null
}
}
object.traverse(function(child) {
child.lastMatrixWorld = child.matrixWorld.clone()
})
window.editor = editor
},
/**
* 获取预置焦点
*/
getCameraData() {
var param = []
param[0] = ['ProjectCode', editor.ProjectCode]
var Data = this.CreateData('3', 'select * from dbo.[基础数据_焦点预置]', param)
this.ExecDatabase(Data).then(response => {
this.cameraData = response.data
})
},
/**
* 点击后 到达预置焦点
*/
setViewCamera() {
if (this.cameraData.length === 0) return
const scope = this
const viewOperation = document.getElementById('viewOperationParent')
const viewOperationChild = document.getElementById('viewOperationChild')
viewOperation.onmouseover = function() {
viewOperationChild.style.display = 'block'
}
viewOperation.onmouseout = function() {
viewOperationChild.style.display = 'none'
}
setTimeout(() => {
for (const info of this.cameraData) {
$('#cameraViewBtn' + info.焦点代码).on('click', function(e) {
const data = JSON.parse(info.焦点位置)
const target = data.target
const position = data.position
const zoom0 = data.zoom0
const id = info.焦点代码
$('#cameraViewBtn' + info.焦点代码).css({ 'background': '#00893d', 'color': '#fff' })
editor.cameraControls.resetState(target, position, zoom0)
for (const infoColor of scope.cameraData) {
if (id !== infoColor.焦点代码) {
$('#cameraViewBtn' + infoColor.焦点代码).css({ 'background': '#fff', 'color': '#606266' })
}
}
})
}
}, 1000)
},
getMousePosition(dom, x, y) {
const rect = dom.getBoundingClientRect()
return [(x - rect.left) / rect.width, (y - rect.top) / rect.height]
},
ondblclick(event) {
try {
const array = this.getMousePosition(container, event.clientX, event.clientY)
onUpPosition.fromArray(array)
let intersects = this.getIntersects(onUpPosition, editor.scene.children)
intersects = intersects.filter(res => {
return res.object.visible
})
if (intersects.length > 0) {
const rootObjId = intersects[0].object.userData['RootId']
editor.selected = editor.getObjectById(rootObjId)
editor.dispatchEvent({
type: 'dmtModelDBClick',
ModelId: editor.selected.userData['ModelId'],
ModelName: editor.selected.userData['name']
})
} else {
editor.selected = null
editor.dispatchEvent({
type: 'dmtModelDBClick',
ModelId: '',
ModelName: ''
})
}
} catch (e) {
editor.selected = null
editor.dispatchEvent({
type: 'dmtModelDBClick',
ModelId: '',
ModelName: ''
})
}
},
getIntersects(point, objects) {
mouse.set((point.x * 2) - 1, -(point.y * 2) + 1)
raycaster.setFromCamera(mouse, camera)
return raycaster.intersectObjects(objects, true)
},
sendCameraState(state) {
this.$emit('changeCameraState', state)// 自定义事件 传递值“子向父组件传值”
},
updatePosition() {
if (editor.selected) {
const targetPosition = editor.selected.getWorldPosition(new THREE.Vector3()).clone().project(camera)
const halfWidth = window.innerWidth / 2
const halfHeight = window.innerHeight / 2
const position = {
left: targetPosition.x * halfWidth + halfWidth - 200,
top: -targetPosition.y * halfHeight + halfHeight - 500
}
this.$emit('clickModel', editor.selected, position)// 自定义事件 传递值“子向父组件传值”
}
},
getDeltaPosition(positionModel, positionLabel) {
return new THREE.Vector3((positionLabel.x - positionModel.x), (positionLabel.y - positionModel.y), (positionLabel.z - positionModel.z))
}
}
}
</script>
<style>
html{
height: 99%;
}
body {
height: 100%;
}
#app {
height: 100%;
}
</style>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,139 @@
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import * as TWEEN from 'three/examples/jsm/libs/tween.module.js'
// import { viewCubeUpdate } from './DmtViewCube'
const _changeEvent = { type: 'change' }
class DmtControl extends OrbitControls {
constructor(object, domElement) {
super(object, domElement)
this.cubeControlDirection = {
'TOP': 'TOP',
'BOTTOM': 'BOTTOM',
'FRONT': 'FRONT',
'BACK': 'BACK',
'LEFT': 'LEFT',
'RIGHT': 'RIGHT',
'BACK-LEFT': 'BACK-LEFT',
'FRONT-LEFT': 'FRONT-LEFT',
'TOP-LEFT': 'TOP-LEFT',
'TOP-RIGHT': 'TOP-RIGHT',
'RIGHT-BOTTOM': 'RIGHT-BOTTOM',
'LEFT-BOTTOM': 'LEFT-BOTTOM',
'BACK-BOTTOM': 'BACK-BOTTOM',
'TOP-FRONT': 'TOP-FRONT',
'FRONT-BOTTOM': 'FRONT-BOTTOM',
'TOP-BACK': 'TOP-BACK',
'RIGHT-FRONT': 'RIGHT-FRONT',
'BACK-RIGHT': 'BACK-RIGHT',
'BACK-RIGHT-BOTTOM': 'BACK-RIGHT-BOTTOM',
'TOP-RIGHT-BACK': 'TOP-RIGHT-BACK',
'TOP-LEFT-BACK': 'TOP-LEFT-BACK',
'TOP-LEFT-FRONT': 'TOP-LEFT-FRONT',
'FRONT-BOTTOM-RIGHT': 'FRONT-BOTTOM-RIGHT',
'TOP-RIGHT-FRONT': 'TOP-RIGHT-FRONT',
'BACK-BOTTOM-LEFT': 'BACK-BOTTOM-LEFT',
'FRONT-BOTTOM-LEFT': 'FRONT-BOTTOM-LEFT'
}
const scope = this
const STATE = {
NONE: -1,
ROTATE: 0,
DOLLY: 1,
PAN: 2,
TOUCH_ROTATE: 3,
TOUCH_PAN: 4,
TOUCH_DOLLY_PAN: 5,
TOUCH_DOLLY_ROTATE: 6
}
// eslint-disable-next-line no-unused-vars
let state = STATE.NONE
this.resetState = function(target0, position0, zoom0) {
scope.target.copy(target0)
scope.object.position.copy(position0)
if (scope.object.isOrthographicCamera) {
scope.object.zoom = zoom0
} else {
scope.object.zoom = 1
}
scope.object.updateProjectionMatrix()
scope.dispatchEvent(_changeEvent)
scope.update()
state = STATE.NONE
// viewCubeUpdate()
}
this.resetStateTween = function(target1, current1, target2, current2, duration) {
const scope = this
const positionVar = {
x1: current1.x,
y1: current1.y,
z1: current1.z,
x2: target1.x,
y2: target1.y,
z2: target1.z
}
// 关闭控制器
scope.enabled = false
var tween = new TWEEN.Tween(positionVar)
tween.to({
x1: current2.x,
y1: current2.y,
z1: current2.z,
x2: target2.x,
y2: target2.y,
z2: target2.z
}, duration)
tween.onUpdate(function() {
scope.object.position.x = positionVar.x1
scope.object.position.y = positionVar.y1
scope.object.position.z = positionVar.z1
scope.target.x = positionVar.x2
scope.target.y = positionVar.y2
scope.target.z = positionVar.z2
scope.object.updateProjectionMatrix()
scope.update()
})
tween.start()
tween.onComplete(function() {
// /开启控制器
scope.enabled = true
})
tween.easing(TWEEN.Easing.Cubic.InOut)
}
this.setLookAt = function(position0, target0, zoom0) {
scope.target.copy(target0)
scope.object.position.copy(position0)
scope.object.zoom = zoom0
scope.object.updateProjectionMatrix()
scope.dispatchEvent(_changeEvent)
scope.update()
state = STATE.NONE
}
this.setLookAt1 = function(target0, rotation) {
scope.target.copy(this.target)
scope.object.rotation.copy(rotation)
scope.object.updateProjectionMatrix()
scope.dispatchEvent(_changeEvent)
scope.update()
state = STATE.NONE
}
this.moveTo = function(x, y, z) {
scope.target.set(x, y, z)
}
this.getState = function() {
return {
target: scope.target.clone(),
position: scope.object.position.clone(),
zoom: parseFloat(scope.object.zoom.toString())
}
}
}
}
export {
DmtControl
}

View File

@@ -0,0 +1,78 @@
import { WebsocketMessageReceive } from './WebSocketMessage.js'
import mqtt from 'mqtt'
function connectMqtt(editor) {
const connection = {
host: editor.mqttHost,
port: editor.mqttPort,
endpoint: '/mqtt',
clean: true, // 保留会话
connectTimeout: 4000, // 超时时间
reconnectPeriod: 4000, // 重连时间间隔
// 认证信息
clientId: 'mqttjs_3be2c321' + new Date().getTime(), // 同一个ID 无法二次连接
username: '',
password: ''
}
const subscription = {
topic: editor.opname,
qos: 0
}
const websocketMessageReceive = new WebsocketMessageReceive(editor)
const { host, port, endpoint, ...options } = connection
const wsHeaderString = location.protocol === 'https:' ? 'wss' : 'ws'
// const connectUrl = `${wsHeaderString}://${location.host}${endpoint}`
const connectUrl = `${wsHeaderString}://${host}:${port}${endpoint}`
console.log(connectUrl)
try {
editor.mqttClient = mqtt.connect(connectUrl, options)
} catch (error) {
console.log('MQTT connect error', error)
}
editor.mqttClient.on('connect', () => {
editor.showMessage('加载完成连接MQTT服务器成功', 'success', 2000)
console.log('MQTT Connection succeeded!')
editor.isOk = true
const { topic, qos } = subscription
editor.mqttClient.subscribe(topic, { qos }, (error, res) => {
if (error) {
console.log('Subscribe to topics error', error)
return
}
websocketMessageReceive.getOriginTagValue()
})
})
editor.mqttClient.on('error', error => {
console.log('MQTT Connection failed', error)
try {
editor.showMessage('MQTT服务器连接失败', 'error', 2000)
editor.socket.close()
if (editor.IsAllowConnect) {
// 显示一下
editor.showMessage('重新连接MQTT服务器', 'warning', 2000)
console.log('重新连接MQTT服务器')
// 重新连接,打开计时器
setTimeout(function() {
connectMqtt(editor)
}, 5000)
}
} catch (exception) {
const error = exception.toString()
editor.showMessage.error('MQTT服务器出现错误,关闭连接' + error, 'error', 2000)
}
})
// 接收消息
editor.mqttClient.on('message', (topic, message) => {
try {
websocketMessageReceive.websocketMessage({ data: message.toString() })
} catch (exception) {
console.log(exception.toString())
}
})
editor.mqttClient.on('close', () => {
editor.mqttClient.end()
})
}
export { connectMqtt }

View File

@@ -0,0 +1,40 @@
import * as THREE from 'three'
/**
* @param editor Editor
* @param object THREE.Object3D
* @constructor
*/
class ObjectAlarmCommand {
constructor(editor, ModelId) {
this.type = 'ObjectAlarmCommand'
this.ModelId = ModelId
this.editor = editor
this.object = editor.getObjectById(ModelId)
}
exec(isAlarm = true) {
if (!this.object) return
if (isAlarm) {
this.object.traverse(object => {
if (object instanceof THREE.Mesh && !Object.hasOwnProperty.call(object.userData, 'isAxis')) {
object.material.color = new THREE.Color('#ff0000')
object.material.side = 2
object.material.transparent = true
object.material.opacity = 0.8
}
})
// this.editor.playSoundCommand.exec('Alarm', true, this.ModelId)
} else {
this.object.traverse(object => {
if (object instanceof THREE.Mesh) {
const m = this.editor.objMaterial.get(object.id)
if (m)object.material = m.clone()
}
})
// this.editor.playSoundCommand.exec('Alarm', false, this.ModelId)
}
}
}
export { ObjectAlarmCommand }

View File

@@ -0,0 +1,58 @@
/**
* @param editor Editor
* @param object THREE.Object3D
* @constructor
*/
class PlaySoundCommand {
constructor() {
this.type = 'PlaySoundCommand'
this.PlayType = {
Alarm: 'Alarm',
Clash: 'Clash'
}
this.AlarmList = []
this.isAlarm = false
}
/**
* 系统声音
* @param type 报警Alarm 碰撞Clash 。。。。。。。
* @param state 报警/解除报警
* @param ModelId 模型ID
*/
exec(type, state = true, ModelId) {
switch (type) {
case this.PlayType.Alarm:
if (state) {
if (!this.isAlarm) this.playAlarmSound(true)
if (this.AlarmList.indexOf(ModelId) === -1) this.AlarmList.push(ModelId)
this.isAlarm = true
} else {
this.AlarmList = this.AlarmList.filter(res => { return res !== ModelId })
if (this.AlarmList.length === 0) {
this.playAlarmSound(false)
this.isAlarm = false
}
}
break
case this.PlayType.Clash:
break
default:
break
}
}
/**
*
*/
playAlarmSound(play = true) {
// const audio = document.getElementById('alarm')
// play ? audio.play() : audio.pause()
}
playClashSound(play) {
const audio = document.getElementById('clash')
play ? audio.play() : audio.pause()
}
}
export { PlaySoundCommand }

View File

@@ -0,0 +1,629 @@
import * as THREE from 'three'
import { ObjectAlarmCommand } from './ObjectAlarmCommand.js'
import * as TWEEN from 'three/examples/jsm/libs/tween.module.js'
const WebsocketMessageReceive = function(editor) {
const scope = this
this.websocketMessage = (msg) => {
new Promise((resolve, reject) => {
let returnMes
const arrays_signal = msg.data.split('|')
const m_SourceType = arrays_signal[0] // 数据类型DT数字孪生数据
const m_DeviceType = arrays_signal[1] // 设备类型Robot机器人类型的设备Device普通设备
const m_DeviceName = arrays_signal[2] // 设备名称
const m_DevicePartName = arrays_signal[3] // 设备运动部件
const m_DevicePartDate = arrays_signal[4] // 设备运动部件数据
switch (m_SourceType) {
case 'DT':
switch (m_DeviceType) {
case editor.ProtocolIdentifiers.Robot_7: // 接受机器人运动数据进行播放 --------------------------现场用----------------
returnMes = scope.deviceMoveEvent.RobotTranslation7(m_DeviceName, m_DevicePartName, m_DevicePartDate)
break
case editor.ProtocolIdentifiers.Device_3:
console.log('设备运行')// --------------------------现场用----------------
returnMes = scope.deviceMoveEvent.DeviceThreeAxis(m_DeviceName, m_DevicePartName, m_DevicePartDate)
break
case editor.ProtocolIdentifiers.Agv_3:// --------------------------现场用----------------
console.log('AGV运行')
returnMes = scope.deviceMoveEvent.AGVThreeAxis(m_DeviceName, m_DevicePartName, m_DevicePartDate)
break
case editor.ProtocolIdentifiers.Device_1: // 接受设备运动数据进行播放,已更新
break
case editor.ProtocolIdentifiers.FirstPosition: // 接受第一个点的数据,瞬间跳到该点,已更新
break
case editor.ProtocolIdentifiers.WareHousePart: //
returnMes = scope.drawWareHousePartOne(m_DeviceName)
break
case editor.ProtocolIdentifiers.Robot_6: // 接受机器人运动数据进行播放
returnMes = scope.deviceMoveEvent.RobotTranslation(m_DeviceName, m_DevicePartName, m_DevicePartDate)
break
case editor.ProtocolIdentifiers.ReLoadData: // 加载所有要播放的数据,避免资源浪费 ***********************UUID测试好用了******************************
break
case editor.ProtocolIdentifiers.PlayAct: // 根据ID 播放数据 状态为1 0暂停 ***********************UUID测试好用了******************************
scope.playActData(m_DeviceName, parseInt(m_DevicePartName))
break
// case editor.ProtocolIdentifiers.ModelTransparent: // 根据传过来的模型名字和透明度 改变模型的透明度 ***********************UUID测试好用了******************************
// returnMes = scope.robotPlan_ModelOperation.modelTrans(m_DeviceName, m_DevicePartName)
// break
case editor.ProtocolIdentifiers.Visible: // 接受CS指令显示、隐藏模型 ***********************UUID测试好用了******************************
returnMes = scope.visibleObjectToBS(m_DeviceName, m_DevicePartName)
break
case 'JointMoveTo':
if (!JSON.parse(m_DevicePartName)) console.log('JointMoveTo数据不对' + m_DevicePartName)
this.JointMoveTo(m_DeviceName, JSON.parse(m_DevicePartName))
break
case editor.ProtocolIdentifiers.C_B_TagIDTrigger:
{
const tag = JSON.parse(m_DeviceName)
scope.solveTagValue(tag.TagID, tag.TagValue)
}
break
case editor.ProtocolIdentifiers.C_B_ObjectAlarm:
{
const Info = JSON.parse(m_DeviceName)
console.log(Info)
for (const infoElement of Info) {
new ObjectAlarmCommand(editor, infoElement.ModelId).exec(!!parseInt(infoElement.value))
}
}
break
case editor.ProtocolIdentifiers.C_B_JointMoveTo:
{
const MoveValueList = JSON.parse(m_DeviceName)
scope.ModelJointMoveTo(MoveValueList)
}
break
case 'showWeld':
this.showWeld(m_DeviceName, m_DevicePartName)
break
case 'showCheckOk':
this.showCheckOk(m_DeviceName, m_DevicePartName)
break
default:
returnMes = '不存在协议:' + msg
break
}
break
default:
returnMes = '不存在协议:' + msg
break
}
resolve(returnMes)
})
}
/**
* HandlerType: 1:显隐,2:自转,3:行为,4:私服位置5:附加拆离指令
* HandlerCode: 模型或者工艺代码
* HandlerValue: 显隐0/1 ,自传:正负转速&axis,行为暂停播放0/1
* TagValueTagValue: 信号值
* @param tagId
* @param tagValue
*/
this.solveTagValue = (tagId, tagValue) => {
const scope = this
const actionInfo = editor.TagActList[tagId]
if (!actionInfo) return
for (const actionInfoElement of actionInfo) {
switch (actionInfoElement.HandlerType) {
case editor.signalSolveType.warning: // 报警
if (tagValue === actionInfoElement.TagValue) {
new ObjectAlarmCommand(editor, actionInfoElement.HandlerCode).exec(!!parseInt(actionInfoElement.HandlerValue))
}
break
case editor.signalSolveType.visible: // 显隐
if (tagValue === actionInfoElement.TagValue) {
scope.visibleObjectToBS(actionInfoElement.HandlerCode, parseInt(actionInfoElement.HandlerValue))
}
break
case editor.signalSolveType.rotation: // 自转
if (tagValue === actionInfoElement.TagValue) {
const ValueFactor = actionInfoElement.ValueFactor
const Axis = actionInfoElement.Axis
// const JointType = actionInfoElement.JointType
const Flip = actionInfoElement.Flip
const ModelCode = actionInfoElement.HandlerCode
scope.modelRotation(ModelCode, Axis, Flip * parseFloat(ValueFactor))
}
break
case editor.signalSolveType.craft: // 行为
if (tagValue === actionInfoElement.TagValue) {
scope.playActData(actionInfoElement.HandlerCode, parseInt(actionInfoElement.HandlerValue))
}
break
case editor.signalSolveType.targetLocation: // 伺服位置
scope.solveServoSignal(actionInfoElement, tagValue)
break
case editor.signalSolveType.attach: // 附加功能
console.log('这个地方的附加功能没用写')
break
default:
break
}
}
}
/**
* 根据ACTid播放动作开启线程
* @param actID
* @param state
*/
this.playActData = (actID, state) => {
const scope = this
if (!editor.isOk) return
if (!editor.worker[actID]) editor.worker[actID] = new Worker('./DMT_WEB/webWorker/playFunction.js')
if (editor.moveTrigger[actID].moveStatus !== state) {
editor.worker[actID].postMessage({
ActID: actID,
State: state,
isOk: editor.isOk,
craftPlaySolveType: editor.craftPlaySolveType,
moveTrigger: JSON.stringify(editor.moveTrigger[actID])
})
editor.moveTrigger[actID].moveStatus = state
}
editor.worker[actID].onmessage = function(event) {
editor.moveTrigger[actID].myVarSetInterval = event.data.myVarSetInterval
editor.moveTrigger[actID].currentFrame = event.data.pausedFrame
const currentFrameData = event.data.currentFrameData
const frameType = event.data.frameType
editor.solveAttachModel('', true)
switch (frameType) {
case editor.craftPlaySolveType.attach:
if (editor.FrameOperation.attach) {
const position = currentFrameData['AttachToModelCode']
const List_AttachModel = currentFrameData['List_AttachModel']
const IsTwoWay = currentFrameData['IsTwoWay']
const IsAttach = currentFrameData['IsAttach']
if (IsAttach) {
const attachData = []
for (const editorElement of List_AttachModel) {
attachData.push({
ModelId: editorElement.ModelCode,
ModelName: editorElement.ModelName,
RootId: position,
IsTwoWay: IsTwoWay
})
}
editor.attachList.set(position, attachData)
} else {
for (const detachData of List_AttachModel) {
const detachModelCode = detachData.ModelCode
editor.scene.attach(editor.getObjectById(detachModelCode))
editor.attachList.forEach((value, key) => {
const attachList = value.filter(res => { return res.ModelId !== detachModelCode })
editor.attachList.set(key, attachList)
})
}
}
}
break
case editor.craftPlaySolveType.visible:
if (editor.FrameOperation.visibleObject) {
const position = currentFrameData['ModelCode']
const Visible = parseInt(currentFrameData['Visible'])
scope.visibleObjectToBS(position, Visible)
}
break
case editor.craftPlaySolveType.rotation:
if (editor.FrameOperation.rotationObject) {
const position = currentFrameData['ModelCode']
const Axis = currentFrameData['Axis']
const Rate = currentFrameData['Rate']
scope.modelRotation(position, Axis, Rate)
}
break
case editor.craftPlaySolveType.craft:
if (editor.FrameOperation.playCraft) {
const position = currentFrameData['CraftCode']
const craftState = parseInt(currentFrameData['CraftValue'])
scope.playActData(position, craftState)
}
break
case editor.craftPlaySolveType.FrameData:
{
const position = currentFrameData['i']
const objectToMove = editor.getObjectById(position)
if (objectToMove) {
if (currentFrameData.tx === 'NaN' || currentFrameData.ty === 'NaN' || currentFrameData.tz === 'NaN' || currentFrameData.qx === 'NaN' || currentFrameData.qy === 'NaN' || currentFrameData.qz === 'NaN' || currentFrameData.qw === 'NaN') {
console.log('craftDataError')
// editor.robotPlan_MessageList.execute(position, 'craftDataError')
} else {
const movePosition = new THREE.Vector3(parseFloat(currentFrameData.tx), parseFloat(currentFrameData.ty), parseFloat(currentFrameData.tz))
const nq = new THREE.Quaternion(parseFloat(currentFrameData.qx), parseFloat(currentFrameData.qy), parseFloat(currentFrameData.qz), parseFloat(currentFrameData.qw))
objectToMove.quaternion.copy(nq)
objectToMove.position.copy(movePosition)
}
}
}
break
case editor.craftPlaySolveType.warning: // 报警
if (editor.FrameOperation.warning) {
new ObjectAlarmCommand(scope.editor, currentFrameData['ModelCode']).exec(!!parseInt(currentFrameData['Visible']))
}
break
default:
delete editor.worker[event.data.ActID]
editor.moveTrigger[actID].moveStatus = 0
editor.moveTrigger[actID].myVarSetInterval = null
editor.moveTrigger[actID].currentFrame = 0
editor.moveTrigger[actID].pausedFrame = 0
break
}
editor.solveAttachModel('', false)
}
}
/**
* 接受CS模型自转的指令
* 接受CS模型自转的指令
* @param objectNames
* @param values
* @param axis
*/
this.modelRotation = (objectNames, axis, values) => {
const scope = this
const EP = 0.000001
let dir = 0
if (!editor.getObjectById(objectNames)) return
const currentModel = editor.getObjectById(objectNames)
if ((parseFloat(values) >= -EP) && (parseFloat(values) <= EP)) {
if (editor.RotationWorker[objectNames]) {
editor.RotationWorker[objectNames].terminate()
delete editor.RotationWorker[objectNames]
delete editor.ModelRotateWorker[objectNames]
}
return
} else {
dir = 1
if (editor.RotationWorker[objectNames]) {
editor.RotationWorker[objectNames].terminate()
delete editor.RotationWorker[objectNames]
delete editor.ModelRotateWorker[objectNames]
}
}
editor.RotationWorker[objectNames] = new Worker('webWorker/modelRotation.js')
if (!editor.ModelRotateWorker[objectNames]) {
editor.ModelRotateWorker[objectNames] = {
state: 0,
myVarSetInterval: null,
doAnimation: false,
ModelCode: objectNames
}
}
editor.RotationWorker[objectNames].postMessage({
ObjectNames: objectNames,
Values: values,
Dir: dir,
ModelRotateWorker: editor.ModelRotateWorker[objectNames],
RotateSpeed: editor.rotateSpeed,
RotationValue: currentModel.rotation[axis]
})
editor.RotationWorker[objectNames].onmessage = (event) => {
scope.modelSelfRotation(currentModel, event.data.rotation, axis)
}
}
this.modelSelfRotation = (currentModel, rotation, axis) => {
currentModel.rotation[axis] = rotation
}
this.ModelJointMoveTo = (MoveValueList) => {
// TOBS?WEB?SCADAMain?DT|C_B_JointMoveTo|[{"ModelCode":"5E6D91B8-B44D-4C44-AAEF-10492E548A1A","JointType":"rotation","Axis":"x","Flip":1,"Value":0,"ValueFactor":0.017453292519943295,"Delta":0}]
// TOBS?WEB?SCADAMain?DT|C_B_JointMoveTo|[{"ModelCode":"644506B1-A05A-4E57-BBA2-C63635586C63","JointType":"position","Axis":"y","Flip":-1,"Value":-15.0,"ValueFactor":0.001,"Delta":-655.0}]
new Promise(resolve => {
for (const MoveValue of MoveValueList) {
const ModelCode = MoveValue.ModelCode
const ValueFactor = parseFloat(MoveValue.ValueFactor)
const type = MoveValue.JointType
const Value = parseFloat(MoveValue.Value)
const Flip = parseFloat(MoveValue.Flip)
const axis = MoveValue.Axis
const Delta = parseFloat(MoveValue.Delta)
const object = editor.getObjectById(ModelCode)
const originInfo = editor.objectIdSet.get(ModelCode)
if (!originInfo) return
const matrix = originInfo['matrix']
const originValue = type === 'rotation' ? originInfo[type]['_' + axis] : originInfo[type][axis]
const lastValue = originInfo['lastValue'] === null ? originValue : originInfo['lastValue']
const moveValue = Flip * (Value - Delta) * ValueFactor
if (object) {
editor.solveAttachModel('', true)
const JointValue = originValue + moveValue
new TWEEN.Tween({
moveValue: lastValue
}).to({ moveValue: JointValue }, 100)
.onStart(function() {
originInfo['lastValue'] = JointValue
}).onUpdate(function() {
switch (type) {
case 'position':
object[type][axis] = this._object.moveValue
break
case 'rotation':
{
const moveAxis = {
x: new THREE.Vector3(1, 1, 1),
y: new THREE.Vector3(1, 1, 1),
z: new THREE.Vector3(1, 1, 1)
}
matrix.extractBasis(moveAxis.x, moveAxis.y, moveAxis.z)
const nM = new THREE.Matrix4()
nM.makeRotationAxis(moveAxis[axis], this._object.moveValue)
nM.multiply(matrix)
object.rotation.setFromRotationMatrix(nM)
object.updateWorldMatrix()
}
break
}
}).start()
editor.solveAttachModel('', false)
} else {
console.log('模型不存在')
}
}
})
}
/**
* 接伺服类的数据
* @param ModelInfo
* @param tagValue
*/
this.solveServoSignal = (ModelInfo, tagValue) => {
try {
const type = ModelInfo.JointType
const axis = ModelInfo.Axis
const flip = ModelInfo.Flip
const Value = ModelInfo.Value
const ValueFactor = ModelInfo.ValueFactor // 倍率
const ModelId = ModelInfo.HandlerCode // 模型代码
const object = editor.getObjectById(ModelId)
const originInfo = editor.objectIdSet.get(ModelId)
if (!originInfo) return
const matrix = originInfo['matrix']
const originValue = type === 'rotation' ? originInfo[type]['_' + axis] : originInfo[type][axis]
const lastValue = originInfo['lastValue'] === null ? originValue : originInfo['lastValue']
const moveValue = flip * (parseFloat(tagValue) - Value) * ValueFactor
if (object) {
editor.solveAttachModel('', true)
const JointValue = originValue + moveValue
new TWEEN.Tween({
moveValue: lastValue
}).to({ moveValue: JointValue }, 100)
.onStart(function() {
originInfo['lastValue'] = JointValue
})
.onUpdate(function() {
switch (type) {
case 'position':
object[type][axis] = this._object.moveValue
break
case 'rotation':
{
const moveAxis = {
x: new THREE.Vector3(1, 1, 1),
y: new THREE.Vector3(1, 1, 1),
z: new THREE.Vector3(1, 1, 1)
}
matrix.extractBasis(moveAxis.x, moveAxis.y, moveAxis.z)
const nM = new THREE.Matrix4()
nM.makeRotationAxis(moveAxis[axis], this._object.moveValue)
// nM.makeRotationAxis(moveAxis[axis], JointValue)
nM.multiply(matrix)
object.rotation.setFromRotationMatrix(nM)
object.updateWorldMatrix()
}
break
}
}).start()
editor.solveAttachModel('', false)
}
//
// if (object) {
// editor.solveAttachModel('', true)
// object[type][axis] = originValue + (ValueFactor * flip * parseFloat(tagValue) + Value)
// editor.solveAttachModel('', false)
// }
} catch (e) {
console.log('solveServoSignal错误')
}
}
/**
* 接受机器人类的数据
* @param ModelId
* @param JointData
* @constructor
*/
this.JointMoveTo = (ModelId, JointData = {}) => {
if (editor.robotList[ModelId]) {
const ModelList = editor.robotList[ModelId]
// window.updateRobotData(ModelId, JointData)
// window.updateLabelInfoJoint(ModelId, JointData)
for (let i = 0; i < ModelList.length; i++) {
if (ModelList[i].ModelId === '') return
this.jointMoveToPromise(JointData, ModelList[i], i, ModelId)
}
}
}
this.jointMoveToPromise = (JointData, ModelListData, i, ModelId) => {
new Promise(resolve => {
const ModelIdJoint = ModelListData.ModelId
const object = ModelListData.object
const type = ModelListData.type
const axis = ModelListData.axis
const matrix = ModelListData.matrix
const flip = ModelListData.flip
const delta = parseFloat(ModelListData.delta)
const multiple = ModelListData.multiple
const originInfo = editor.objectIdSet.get(ModelIdJoint)
if (!originInfo) return
const originValue = type === 'rotation' ? originInfo[type]['_' + axis] : originInfo[type][axis]
const lastValue = ModelListData.lastValue === null ? originValue : ModelListData.lastValue
const moveValue = flip * (parseFloat(JointData['J' + (i + 1)]) - delta) * multiple
if (object) {
const JointValue = originValue + moveValue
new TWEEN.Tween({
moveValue: lastValue
}).to({ moveValue: JointValue }, 200)
.onStart(function() {
editor.robotList[ModelId][i]['lastValue'] = JointValue
})
.onUpdate(function() {
switch (type) {
case 'position':
object[type][axis] = this._object.moveValue
break
case 'rotation':
{
const moveAxis = {
x: new THREE.Vector3(1, 1, 1),
y: new THREE.Vector3(1, 1, 1),
z: new THREE.Vector3(1, 1, 1)
}
matrix.extractBasis(moveAxis.x, moveAxis.y, moveAxis.z)
const nM = new THREE.Matrix4()
nM.makeRotationAxis(moveAxis[axis], this._object.moveValue)
// nM.makeRotationAxis(moveAxis[axis], JointValue)
nM.multiply(matrix)
object.rotation.setFromRotationMatrix(nM)
object.updateWorldMatrix()
}
break
}
}).start()
}
})
}
this.getAxisValue = (axis, value) => {
return JSON.parse('{"' + axis + '":' + value + '}')
}
this.getAxisValue = (axis, value) => {
return JSON.parse('{"' + axis + '":' + value + '}')
}
this.showWeld = (ModelId, Welding) => {
// 徐工专用
if (ModelId === '46DDBCD8-D775-49A4-BB14-30015FF87595') editor.WeldLightVisible1 = !!parseInt(Welding)
if (ModelId === '1E96DED2-6EEF-469F-BFE6-8F52FB62C2B0') editor.WeldLightVisible2 = !!parseInt(Welding)
}
this.showCheckOk = (check) => {
// 徐工专用
if (parseInt(check)) {
editor.showTagList[3].title = '工件QY16KC, 检测OK'
} else {
editor.showTagList[3].title = '工件QY16KC'
}
}
/**
* 显示隐藏物体
* @param m_DeviceName
* @param isVisible
*/
this.visibleObjectToBS = (m_DeviceName, isVisible) => {
const currentModel = editor.getObjectById(m_DeviceName)
if (currentModel) {
currentModel.visible = !!parseInt(isVisible)
currentModel.traverse(res => {
res.visible = !!parseInt(isVisible)
})
currentModel.userData['visible'] = !!parseInt(isVisible)
}
}
/**
* 初始化获取TagValue
*/
this.getOriginTagValue = () => {
let msg = ''
let socketMsg = ''
const keyWord = 'B_C_DT_WebLoaded'
msg = 'DT|' + keyWord
socketMsg = editor.BSport + msg
const topic = editor.BSport.split('?')[2]
switch (editor.connectType) {
case 1:
editor.socket.send(socketMsg)
break
case 2:
editor.mqttClient.publish(topic, msg, 0, error => {
if (error) {
console.log('Publish error', error)
}
})
break
default:
break
}
}
/**
* 更新库存状态
* @param dataInfo
*/
this.drawWareHousePartOne = (dataInfo) => {
const scope = this
try {
const whInfo = JSON.parse(dataInfo)
for (const whStoreInfo of whInfo) {
const whStoreNum = whStoreInfo.Key // 库位号 唯一值
const whStoreState = whStoreInfo.Value // 立库状态
const whNum = whStoreNum.toString().substring(0, 4) // 立库号 1000一期立库 1003刀具库 1002三坐标测量库 1001机床线旁库
const currentStoreInfo = editor.WareHouse.get(whStoreNum)
if (currentStoreInfo) {
if (parseInt(whStoreState) === 0) {
// 0的时候直接移除库存
editor.removeObject(currentStoreInfo.object)
editor.WareHouse.delete(whStoreNum)
} else {
// 不一样的状态 更新
if (currentStoreInfo.whStoreState !== whStoreState) {
// 移除零件,更新库存信息信息
editor.removeObject(currentStoreInfo.object)
scope.updateStoreModel(whNum, whStoreNum, whStoreState)
currentStoreInfo.whStoreState = whStoreState
currentStoreInfo.object = null
}
}
} else {
editor.WareHouse.set(whStoreNum, {
whNum: whNum,
whStoreNum: whStoreNum,
whStoreState: whStoreState,
object: null
})
scope.updateStoreModel(whNum, whStoreNum, whStoreState)
}
}
} catch (e) {
console.log('库存解析错误')
}
}
/**
* 更新零件
* @param whNum
* @param whStoreNum
* @param whStoreState
*/
this.updateStoreModel = (whNum, whStoreNum, whStoreState) => {
try {
const basicPartModel = editor.WareHouseBasicModel.get('warehousepart' + whStoreState)
const basicWareHouseModelData = editor.WareHouseBasicModel.get('warehouse' + whNum)
if (basicPartModel && basicWareHouseModelData) {
const basicPartModelClone = basicPartModel.clone()
const basicPartModelPosition = basicWareHouseModelData[whStoreNum]
basicPartModelClone.position.copy(basicPartModelPosition.getWorldPosition(new THREE.Vector3()))
editor.scene.add(basicPartModelClone)
editor.WareHouse.get(whStoreNum).object = basicPartModelClone
}
} catch (e) {
console.log('库存模型解析错误')
}
}
}
export {
WebsocketMessageReceive
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,535 @@
import { LinearFilter, Sprite, SpriteMaterial, Texture } from 'three'
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError('Cannot call a class as a function')
}
}
function _defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i]
descriptor.enumerable = descriptor.enumerable || false
descriptor.configurable = true
if ('value' in descriptor) descriptor.writable = true
Object.defineProperty(target, descriptor.key, descriptor)
}
}
function _createClass(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties(Constructor.prototype, protoProps)
if (staticProps) _defineProperties(Constructor, staticProps)
Object.defineProperty(Constructor, 'prototype', {
writable: false
})
return Constructor
}
function _inherits(subClass, superClass) {
if (typeof superClass !== 'function' && superClass !== null) {
throw new TypeError('Super expression must either be null or a function')
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
writable: true,
configurable: true
}
})
Object.defineProperty(subClass, 'prototype', {
writable: false
})
if (superClass) _setPrototypeOf(subClass, superClass)
}
function _getPrototypeOf(o) {
_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
return o.__proto__ || Object.getPrototypeOf(o)
}
return _getPrototypeOf(o)
}
function _setPrototypeOf(o, p) {
_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
o.__proto__ = p
return o
}
return _setPrototypeOf(o, p)
}
function _isNativeReflectConstruct() {
if (typeof Reflect === 'undefined' || !Reflect.construct) return false
if (Reflect.construct.sham) return false
if (typeof Proxy === 'function') return true
try {
Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function() {}))
return true
} catch (e) {
return false
}
}
function _assertThisInitialized(self) {
if (self === void 0) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called")
}
return self
}
function _possibleConstructorReturn(self, call) {
if (call && (typeof call === 'object' || typeof call === 'function')) {
return call
} else if (call !== void 0) {
throw new TypeError('Derived constructors may only return object or undefined')
}
return _assertThisInitialized(self)
}
function _createSuper(Derived) {
var hasNativeReflectConstruct = _isNativeReflectConstruct()
return function _createSuperInternal() {
var Super = _getPrototypeOf(Derived)
var result
if (hasNativeReflectConstruct) {
var NewTarget = _getPrototypeOf(this).constructor
result = Reflect.construct(Super, arguments, NewTarget)
} else {
result = Super.apply(this, arguments)
}
return _possibleConstructorReturn(this, result)
}
}
function _slicedToArray(arr, i) {
return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest()
}
function _toConsumableArray(arr) {
return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread()
}
function _arrayWithoutHoles(arr) {
if (Array.isArray(arr)) return _arrayLikeToArray(arr)
}
function _arrayWithHoles(arr) {
if (Array.isArray(arr)) return arr
}
function _iterableToArray(iter) {
if (typeof Symbol !== 'undefined' && iter[Symbol.iterator] != null || iter['@@iterator'] != null) return Array.from(iter)
}
function _iterableToArrayLimit(arr, i) {
var _i = arr == null ? null : typeof Symbol !== 'undefined' && arr[Symbol.iterator] || arr['@@iterator']
if (_i == null) return
var _arr = []
var _n = true
var _d = false
var _s, _e
try {
for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) {
_arr.push(_s.value)
if (i && _arr.length === i) break
}
} catch (err) {
_d = true
_e = err
} finally {
try {
if (!_n && _i['return'] != null) _i['return']()
} finally {
if (_d) throw _e
}
}
return _arr
}
function _unsupportedIterableToArray(o, minLen) {
if (!o) return
if (typeof o === 'string') return _arrayLikeToArray(o, minLen)
var n = Object.prototype.toString.call(o).slice(8, -1)
if (n === 'Object' && o.constructor) n = o.constructor.name
if (n === 'Map' || n === 'Set') return Array.from(o)
if (n === 'Arguments' || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen)
}
function _arrayLikeToArray(arr, len) {
if (len == null || len > arr.length) len = arr.length
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]
return arr2
}
function _nonIterableSpread() {
throw new TypeError('Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.')
}
function _nonIterableRest() {
throw new TypeError('Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.')
}
var three = typeof window !== 'undefined' && window.THREE ? window.THREE // Prefer consumption from global THREE, if exists
: {
LinearFilter: LinearFilter,
Sprite: Sprite,
SpriteMaterial: SpriteMaterial,
Texture: Texture
}
var _default = /* #__PURE__*/(function(_three$Sprite) {
_inherits(_default, _three$Sprite)
var _super = _createSuper(_default)
function _default() {
var _this
var text = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''
var textHeight = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 10
var color = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'rgba(255, 255, 255, 1)'
_classCallCheck(this, _default)
_this = _super.call(this, new three.SpriteMaterial())
_this._text = ''.concat(text)
_this._textHeight = textHeight
_this._color = color
_this._backgroundColor = false // no background color
_this._padding = 0
_this._borderWidth = 0
_this._borderRadius = 0
_this._borderColor = 'white'
_this._strokeWidth = 0
_this._strokeColor = 'white'
_this._fontFace = 'Arial'
_this._fontSize = 90 // defines text resolution
_this._fontWeight = 'normal'
_this._canvas = document.createElement('canvas')
_this.material.depthTest = false
_this._genCanvas()
return _this
}
_createClass(_default, [{
key: 'text',
get: function get() {
return this._text
},
set: function set(text) {
this._text = text
this._genCanvas()
}
}, {
key: 'textHeight',
get: function get() {
return this._textHeight
},
set: function set(textHeight) {
this._textHeight = textHeight
this._genCanvas()
}
}, {
key: 'color',
get: function get() {
return this._color
},
set: function set(color) {
this._color = color
this._genCanvas()
}
}, {
key: 'backgroundColor',
get: function get() {
return this._backgroundColor
},
set: function set(color) {
this._backgroundColor = color
this._genCanvas()
}
}, {
key: 'padding',
get: function get() {
return this._padding
},
set: function set(padding) {
this._padding = padding
this._genCanvas()
}
}, {
key: 'borderWidth',
get: function get() {
return this._borderWidth
},
set: function set(borderWidth) {
this._borderWidth = borderWidth
this._genCanvas()
}
}, {
key: 'borderRadius',
get: function get() {
return this._borderRadius
},
set: function set(borderRadius) {
this._borderRadius = borderRadius
this._genCanvas()
}
}, {
key: 'borderColor',
get: function get() {
return this._borderColor
},
set: function set(borderColor) {
this._borderColor = borderColor
this._genCanvas()
}
}, {
key: 'fontFace',
get: function get() {
return this._fontFace
},
set: function set(fontFace) {
this._fontFace = fontFace
this._genCanvas()
}
}, {
key: 'fontSize',
get: function get() {
return this._fontSize
},
set: function set(fontSize) {
this._fontSize = fontSize
this._genCanvas()
}
}, {
key: 'fontWeight',
get: function get() {
return this._fontWeight
},
set: function set(fontWeight) {
this._fontWeight = fontWeight
this._genCanvas()
}
}, {
key: 'strokeWidth',
get: function get() {
return this._strokeWidth
},
set: function set(strokeWidth) {
this._strokeWidth = strokeWidth
this._genCanvas()
}
}, {
key: 'strokeColor',
get: function get() {
return this._strokeColor
},
set: function set(strokeColor) {
this._strokeColor = strokeColor
this._genCanvas()
}
}, {
key: '_genCanvas',
value: function _genCanvas() {
var _this2 = this
var canvas = this._canvas
var ctx = canvas.getContext('2d')
var border = Array.isArray(this.borderWidth) ? this.borderWidth : [this.borderWidth, this.borderWidth] // x,y border
var relBorder = border.map(function(b) {
return b * _this2.fontSize * 0.1
}) // border in canvas units
var borderRadius = Array.isArray(this.borderRadius) ? this.borderRadius : [this.borderRadius, this.borderRadius, this.borderRadius, this.borderRadius] // tl tr br bl corners
var relBorderRadius = borderRadius.map(function(b) {
return b * _this2.fontSize * 0.1
}) // border radius in canvas units
var padding = Array.isArray(this.padding) ? this.padding : [this.padding, this.padding] // x,y padding
var relPadding = padding.map(function(p) {
return p * _this2.fontSize * 0.1
}) // padding in canvas units
var lines = this.text.split('\n')
var font = ''.concat(this.fontWeight, ' ').concat(this.fontSize, 'px ').concat(this.fontFace)
ctx.font = font // measure canvas with appropriate font
var innerWidth = Math.max.apply(Math, _toConsumableArray(lines.map(function(line) {
return ctx.measureText(line).width
})))
var innerHeight = this.fontSize * lines.length
canvas.width = innerWidth + relBorder[0] * 2 + relPadding[0] * 2
canvas.height = innerHeight + relBorder[1] * 2 + relPadding[1] * 2 // paint border
if (this.borderWidth) {
ctx.strokeStyle = this.borderColor
if (relBorder[0]) {
// left + right borders
var hb = relBorder[0] / 2
ctx.lineWidth = relBorder[0]
ctx.beginPath()
ctx.moveTo(hb, relBorderRadius[0])
ctx.lineTo(hb, canvas.height - relBorderRadius[3])
ctx.moveTo(canvas.width - hb, relBorderRadius[1])
ctx.lineTo(canvas.width - hb, canvas.height - relBorderRadius[2])
ctx.stroke()
}
if (relBorder[1]) {
// top + bottom borders
var _hb = relBorder[1] / 2
ctx.lineWidth = relBorder[1]
ctx.beginPath()
ctx.moveTo(Math.max(relBorder[0], relBorderRadius[0]), _hb)
ctx.lineTo(canvas.width - Math.max(relBorder[0], relBorderRadius[1]), _hb)
ctx.moveTo(Math.max(relBorder[0], relBorderRadius[3]), canvas.height - _hb)
ctx.lineTo(canvas.width - Math.max(relBorder[0], relBorderRadius[2]), canvas.height - _hb)
ctx.stroke()
}
if (this.borderRadius) {
// strike rounded corners
var cornerWidth = Math.max.apply(Math, _toConsumableArray(relBorder))
var _hb2 = cornerWidth / 2
ctx.lineWidth = cornerWidth
ctx.beginPath();
[!!relBorderRadius[0] && [relBorderRadius[0], _hb2, _hb2, relBorderRadius[0]], !!relBorderRadius[1] && [canvas.width - relBorderRadius[1], canvas.width - _hb2, _hb2, relBorderRadius[1]], !!relBorderRadius[2] && [canvas.width - relBorderRadius[2], canvas.width - _hb2, canvas.height - _hb2, canvas.height - relBorderRadius[2]], !!relBorderRadius[3] && [relBorderRadius[3], _hb2, canvas.height - _hb2, canvas.height - relBorderRadius[3]]].filter(function(d) {
return d
}).forEach(function(_ref) {
var _ref2 = _slicedToArray(_ref, 4)
var x0 = _ref2[0]
var x1 = _ref2[1]
var y0 = _ref2[2]
var y1 = _ref2[3]
ctx.moveTo(x0, y0)
ctx.quadraticCurveTo(x1, y0, x1, y1)
})
ctx.stroke()
}
} // paint background
if (this.backgroundColor) {
ctx.fillStyle = this.backgroundColor
if (!this.borderRadius) {
ctx.fillRect(relBorder[0], relBorder[1], canvas.width - relBorder[0] * 2, canvas.height - relBorder[1] * 2)
} else {
// fill with rounded corners
ctx.beginPath()
ctx.moveTo(relBorder[0], relBorderRadius[0]);
[[relBorder[0], relBorderRadius[0], canvas.width - relBorderRadius[1], relBorder[1], relBorder[1], relBorder[1]], // t
[canvas.width - relBorder[0], canvas.width - relBorder[0], canvas.width - relBorder[0], relBorder[1], relBorderRadius[1], canvas.height - relBorderRadius[2]], // r
[canvas.width - relBorder[0], canvas.width - relBorderRadius[2], relBorderRadius[3], canvas.height - relBorder[1], canvas.height - relBorder[1], canvas.height - relBorder[1]], // b
[relBorder[0], relBorder[0], relBorder[0], canvas.height - relBorder[1], canvas.height - relBorderRadius[3], relBorderRadius[0]] // t
].forEach(function(_ref3) {
var _ref4 = _slicedToArray(_ref3, 6)
var x0 = _ref4[0]
var x1 = _ref4[1]
var x2 = _ref4[2]
var y0 = _ref4[3]
var y1 = _ref4[4]
var y2 = _ref4[5]
ctx.quadraticCurveTo(x0, y0, x1, y1)
ctx.lineTo(x2, y2)
})
ctx.closePath()
ctx.fill()
}
}
ctx.translate.apply(ctx, _toConsumableArray(relBorder))
ctx.translate.apply(ctx, _toConsumableArray(relPadding)) // paint text
ctx.font = font // Set font again after canvas is resized, as context properties are reset
ctx.fillStyle = this.color
ctx.textBaseline = 'bottom'
var drawTextStroke = this.strokeWidth > 0
if (drawTextStroke) {
ctx.lineWidth = this.strokeWidth * this.fontSize / 10
ctx.strokeStyle = this.strokeColor
}
lines.forEach(function(line, index) {
var lineX = (innerWidth - ctx.measureText(line).width) / 2
var lineY = (index + 1) * _this2.fontSize
drawTextStroke && ctx.strokeText(line, lineX, lineY)
ctx.fillText(line, lineX, lineY)
}) // Inject canvas into sprite
if (this.material.map) this.material.map.dispose() // gc previous texture
var texture = this.material.map = new three.Texture(canvas)
texture.minFilter = three.LinearFilter
texture.needsUpdate = true
var yScale = this.textHeight * lines.length + border[1] * 2 + padding[1] * 2
this.scale.set(yScale * canvas.width / canvas.height, yScale, 0.001)
}
}, {
key: 'clone',
value: function clone() {
return new this.constructor(this.text, this.textHeight, this.color).copy(this)
}
}, {
key: 'copy',
value: function copy(source) {
three.Sprite.prototype.copy.call(this, source)
this.color = source.color
this.backgroundColor = source.backgroundColor
this.padding = source.padding
this.borderWidth = source.borderWidth
this.borderColor = source.borderColor
this.fontFace = source.fontFace
this.fontSize = source.fontSize
this.fontWeight = source.fontWeight
this.strokeWidth = source.strokeWidth
this.strokeColor = source.strokeColor
return this
}
}])
return _default
}(three.Sprite))
export { _default as default }

View File

@@ -0,0 +1,74 @@
import { WebsocketMessageReceive } from './WebSocketMessage.js'
function connect(editor) {
const host = 'ws://' + editor.ip + '//WebModule//websocket'
let timeout = null
const websocketMessageReceive = new WebsocketMessageReceive(editor)
// 尝试连接至服务器
try {
if ('WebSocket' in window) {
editor.socket = new WebSocket(host)
} else {
editor.showMessage('浏览器不支持WebSocket', 'error', 2000)
}
} catch (exception) {
editor.showMessage('与服务器断开连接', 'error', 2000)
return
}
// 连接成功
editor.socket.onopen = function() {
// 关闭timer
try {
clearInterval(timeout)
} catch (exception) {
console.log(exception)
}
const name = editor.opname
editor.socket.send('LIN,' + name)
editor.showMessage('加载完成,连接服务器成功!', 'success', 2000)
editor.isOk = true
websocketMessageReceive.getOriginTagValue()
// let a = 0
// setInterval(() => {
// a += 0.5
// const message = `DT|JointMoveTo|0f26fc6e-1caf-4f57-beb3-d8a65872fbdd|{"J1":"${a}","J2":"0","J3":"0","J4":"0","J5":"0","J6":"0","J7":"0","J8":"0","J9":"0","J10":"0","J11":"0","J12":"0"}`
// websocketMessageReceive.websocketMessage({ data: message })
// }, 10)
}
// 收到消息
editor.socket.onmessage = function(msg) {
try {
websocketMessageReceive.websocketMessage(msg)
} catch (exception) {
const error = exception.toString()
console.log(error)
}
}
// 连接断开
editor.socket.onclose = function(event) {
try {
editor.showMessage('onclose' + '服务器连接失败', 'error', 2000)
editor.socket.close()
if (editor.IsAllowConnect) {
// 显示一下
editor.showMessage('重新连接服务器', 'warning', 2000)
console.log('onclose' + '重新连接服务器')
// 重新连接,打开计时器
timeout = setTimeout(function() {
connect(editor)
}, 5000)
}
} catch (exception) {
const error = exception.toString()
editor.showMessage.error('服务器出现错误,关闭连接' + error, 'error', 2000)
}
}
// 出现错误
editor.socket.onerror = function(event) {
console.log('onerror_' + '服务器连接失败')
editor.showMessage.error('服务器连接失败', 'error', 2000)
}
}
export { connect }

View File

@@ -0,0 +1,49 @@
// Inspired by https://github.com/Inndy/vue-clipboard2
const Clipboard = require('clipboard')
if (!Clipboard) {
throw new Error('you shold npm install `clipboard` --save at first ')
}
export default {
bind(el, binding) {
if (binding.arg === 'success') {
el._v_clipboard_success = binding.value
} else if (binding.arg === 'error') {
el._v_clipboard_error = binding.value
} else {
const clipboard = new Clipboard(el, {
text() { return binding.value },
action() { return binding.arg === 'cut' ? 'cut' : 'copy' }
})
clipboard.on('success', e => {
const callback = el._v_clipboard_success
callback && callback(e) // eslint-disable-line
})
clipboard.on('error', e => {
const callback = el._v_clipboard_error
callback && callback(e) // eslint-disable-line
})
el._v_clipboard = clipboard
}
},
update(el, binding) {
if (binding.arg === 'success') {
el._v_clipboard_success = binding.value
} else if (binding.arg === 'error') {
el._v_clipboard_error = binding.value
} else {
el._v_clipboard.text = function() { return binding.value }
el._v_clipboard.action = function() { return binding.arg === 'cut' ? 'cut' : 'copy' }
}
},
unbind(el, binding) {
if (binding.arg === 'success') {
delete el._v_clipboard_success
} else if (binding.arg === 'error') {
delete el._v_clipboard_error
} else {
el._v_clipboard.destroy()
delete el._v_clipboard
}
}
}

View File

@@ -0,0 +1,13 @@
import Clipboard from './clipboard'
const install = function(Vue) {
Vue.directive('Clipboard', Clipboard)
}
if (window.Vue) {
window.clipboard = Clipboard
Vue.use(install); // eslint-disable-line
}
Clipboard.install = install
export default Clipboard

View File

@@ -0,0 +1,46 @@
export default{
bind(el, binding) {
const dialogHeaderEl = el.querySelector('.el-dialog__header')
const dragDom = el.querySelector('.el-dialog')
dialogHeaderEl.style = 'cursor:move;'
// 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
const sty = dragDom.currentStyle || window.getComputedStyle(dragDom, null)
dialogHeaderEl.onmousedown = (e) => {
// 鼠标按下,计算当前元素距离可视区的距离
const disX = e.clientX - dialogHeaderEl.offsetLeft
const disY = e.clientY - dialogHeaderEl.offsetTop
// 获取到的值带px 正则匹配替换
let styL, styT
// 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
if (sty.left.includes('%')) {
styL = +document.body.clientWidth * (+sty.left.replace(/\%/g, '') / 100)
styT = +document.body.clientHeight * (+sty.top.replace(/\%/g, '') / 100)
} else {
styL = +sty.left.replace(/\px/g, '')
styT = +sty.top.replace(/\px/g, '')
}
document.onmousemove = function(e) {
// 通过事件委托,计算移动的距离
const l = e.clientX - disX
const t = e.clientY - disY
// 移动当前元素
dragDom.style.left = `${l + styL}px`
dragDom.style.top = `${t + styT}px`
// 将此时的位置传出去
// binding.value({x:e.pageX,y:e.pageY})
}
document.onmouseup = function(e) {
document.onmousemove = null
document.onmouseup = null
}
}
}
}

View File

@@ -0,0 +1,13 @@
import drag from './drag'
const install = function(Vue) {
Vue.directive('el-drag-dialog', drag)
}
if (window.Vue) {
window['el-drag-dialog'] = drag
Vue.use(install); // eslint-disable-line
}
drag.install = install
export default drag

91
src/directive/sticky.js Normal file
View File

@@ -0,0 +1,91 @@
const vueSticky = {}
let listenAction
vueSticky.install = Vue => {
Vue.directive('sticky', {
inserted(el, binding) {
const params = binding.value || {}
const stickyTop = params.stickyTop || 0
const zIndex = params.zIndex || 1000
const elStyle = el.style
elStyle.position = '-webkit-sticky'
elStyle.position = 'sticky'
// if the browser support css stickyCurrently Safari, Firefox and Chrome Canary
// if (~elStyle.position.indexOf('sticky')) {
// elStyle.top = `${stickyTop}px`;
// elStyle.zIndex = zIndex;
// return
// }
const elHeight = el.getBoundingClientRect().height
const elWidth = el.getBoundingClientRect().width
elStyle.cssText = `top: ${stickyTop}px; z-index: ${zIndex}`
const parentElm = el.parentNode || document.documentElement
const placeholder = document.createElement('div')
placeholder.style.display = 'none'
placeholder.style.width = `${elWidth}px`
placeholder.style.height = `${elHeight}px`
parentElm.insertBefore(placeholder, el)
let active = false
const getScroll = (target, top) => {
const prop = top ? 'pageYOffset' : 'pageXOffset'
const method = top ? 'scrollTop' : 'scrollLeft'
let ret = target[prop]
if (typeof ret !== 'number') {
ret = window.document.documentElement[method]
}
return ret
}
const sticky = () => {
if (active) {
return
}
if (!elStyle.height) {
elStyle.height = `${el.offsetHeight}px`
}
elStyle.position = 'fixed'
elStyle.width = `${elWidth}px`
placeholder.style.display = 'inline-block'
active = true
}
const reset = () => {
if (!active) {
return
}
elStyle.position = ''
placeholder.style.display = 'none'
active = false
}
const check = () => {
const scrollTop = getScroll(window, true)
const offsetTop = el.getBoundingClientRect().top
if (offsetTop < stickyTop) {
sticky()
} else {
if (scrollTop < elHeight + stickyTop) {
reset()
}
}
}
listenAction = () => {
check()
}
window.addEventListener('scroll', listenAction)
},
unbind() {
window.removeEventListener('scroll', listenAction)
}
})
}
export default vueSticky

View File

@@ -0,0 +1,13 @@
import waves from './waves'
const install = function(Vue) {
Vue.directive('waves', waves)
}
if (window.Vue) {
window.waves = waves
Vue.use(install); // eslint-disable-line
}
waves.install = install
export default waves

View File

@@ -0,0 +1,26 @@
.waves-ripple {
position: absolute;
border-radius: 100%;
background-color: rgba(0, 0, 0, 0.15);
background-clip: padding-box;
pointer-events: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-transform: scale(0);
-ms-transform: scale(0);
transform: scale(0);
opacity: 1;
}
.waves-ripple.z-active {
opacity: 0;
-webkit-transform: scale(2);
-ms-transform: scale(2);
transform: scale(2);
-webkit-transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out;
transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out;
transition: opacity 1.2s ease-out, transform 0.6s ease-out;
transition: opacity 1.2s ease-out, transform 0.6s ease-out, -webkit-transform 0.6s ease-out;
}

View File

@@ -0,0 +1,42 @@
import './waves.css'
export default{
bind(el, binding) {
el.addEventListener('click', e => {
const customOpts = Object.assign({}, binding.value)
const opts = Object.assign({
ele: el, // 波纹作用元素
type: 'hit', // hit点击位置扩散center中心点扩展
color: 'rgba(0, 0, 0, 0.15)' // 波纹颜色
}, customOpts)
const target = opts.ele
if (target) {
target.style.position = 'relative'
target.style.overflow = 'hidden'
const rect = target.getBoundingClientRect()
let ripple = target.querySelector('.waves-ripple')
if (!ripple) {
ripple = document.createElement('span')
ripple.className = 'waves-ripple'
ripple.style.height = ripple.style.width = Math.max(rect.width, rect.height) + 'px'
target.appendChild(ripple)
} else {
ripple.className = 'waves-ripple'
}
switch (opts.type) {
case 'center':
ripple.style.top = (rect.height / 2 - ripple.offsetHeight / 2) + 'px'
ripple.style.left = (rect.width / 2 - ripple.offsetWidth / 2) + 'px'
break
default:
ripple.style.top = (e.pageY - rect.top - ripple.offsetHeight / 2 - document.body.scrollTop) + 'px'
ripple.style.left = (e.pageX - rect.left - ripple.offsetWidth / 2 - document.body.scrollLeft) + 'px'
}
ripple.style.backgroundColor = opts.color
ripple.className = 'waves-ripple z-active'
return false
}
}, false)
}
}

370
src/icon/demo.css Normal file
View File

@@ -0,0 +1,370 @@
*{margin: 0;padding: 0;list-style: none;}
/*
KISSY CSS Reset
理念1. reset 的目的不是清除浏览器的默认样式,这仅是部分工作。清除和重置是紧密不可分的。
2. reset 的目的不是让默认样式在所有浏览器下一致,而是减少默认样式有可能带来的问题。
3. reset 期望提供一套普适通用的基础样式。但没有银弹,推荐根据具体需求,裁剪和修改后再使用。
特色1. 适应中文2. 基于最新主流浏览器。
维护:玉伯<lifesinger@gmail.com>, 正淳<ragecarrier@gmail.com>
*/
/** 清除内外边距 **/
body, h1, h2, h3, h4, h5, h6, hr, p, blockquote, /* structural elements 结构元素 */
dl, dt, dd, ul, ol, li, /* list elements 列表元素 */
pre, /* text formatting elements 文本格式元素 */
form, fieldset, legend, button, input, textarea, /* form elements 表单元素 */
th, td /* table elements 表格元素 */ {
margin: 0;
padding: 0;
}
/** 设置默认字体 **/
body,
button, input, select, textarea /* for ie */ {
font: 12px/1.5 tahoma, arial, \5b8b\4f53, sans-serif;
}
h1, h2, h3, h4, h5, h6 { font-size: 100%; }
address, cite, dfn, em, var { font-style: normal; } /* 将斜体扶正 */
code, kbd, pre, samp { font-family: courier new, courier, monospace; } /* 统一等宽字体 */
small { font-size: 12px; } /* 小于 12px 的中文很难阅读,让 small 正常化 */
/** 重置列表元素 **/
ul, ol { list-style: none; }
/** 重置文本格式元素 **/
a { text-decoration: none; }
a:hover { text-decoration: underline; }
/** 重置表单元素 **/
legend { color: #000; } /* for ie6 */
fieldset, img { border: 0; } /* img 搭车:让链接里的 img 无边框 */
button, input, select, textarea { font-size: 100%; } /* 使得表单元素在 ie 下能继承字体大小 */
/* 注optgroup 无法扶正 */
/** 重置表格元素 **/
table { border-collapse: collapse; border-spacing: 0; }
/* 清除浮动 */
.ks-clear:after, .clear:after {
content: '\20';
display: block;
height: 0;
clear: both;
}
.ks-clear, .clear {
*zoom: 1;
}
.main {
padding: 30px 100px;
width: 960px;
margin: 0 auto;
}
.main h1{font-size:36px; color:#333; text-align:left;margin-bottom:30px; border-bottom: 1px solid #eee;}
.helps{margin-top:40px;}
.helps pre{
padding:20px;
margin:10px 0;
border:solid 1px #e7e1cd;
background-color: #fffdef;
overflow: auto;
}
.icon_lists{
width: 100% !important;
}
.icon_lists li{
float:left;
width: 100px;
height:180px;
text-align: center;
list-style: none !important;
}
.icon_lists .icon{
font-size: 42px;
line-height: 100px;
margin: 10px 0;
color:#333;
-webkit-transition: font-size 0.25s ease-out 0s;
-moz-transition: font-size 0.25s ease-out 0s;
transition: font-size 0.25s ease-out 0s;
}
.icon_lists .icon:hover{
font-size: 100px;
}
.markdown {
color: #666;
font-size: 14px;
line-height: 1.8;
}
.highlight {
line-height: 1.5;
}
.markdown img {
vertical-align: middle;
max-width: 100%;
}
.markdown h1 {
color: #404040;
font-weight: 500;
line-height: 40px;
margin-bottom: 24px;
}
.markdown h2,
.markdown h3,
.markdown h4,
.markdown h5,
.markdown h6 {
color: #404040;
margin: 1.6em 0 0.6em 0;
font-weight: 500;
clear: both;
}
.markdown h1 {
font-size: 28px;
}
.markdown h2 {
font-size: 22px;
}
.markdown h3 {
font-size: 16px;
}
.markdown h4 {
font-size: 14px;
}
.markdown h5 {
font-size: 12px;
}
.markdown h6 {
font-size: 12px;
}
.markdown hr {
height: 1px;
border: 0;
background: #e9e9e9;
margin: 16px 0;
clear: both;
}
.markdown p,
.markdown pre {
margin: 1em 0;
}
.markdown > p,
.markdown > blockquote,
.markdown > .highlight,
.markdown > ol,
.markdown > ul {
width: 80%;
}
.markdown ul > li {
list-style: circle;
}
.markdown > ul li,
.markdown blockquote ul > li {
margin-left: 20px;
padding-left: 4px;
}
.markdown > ul li p,
.markdown > ol li p {
margin: 0.6em 0;
}
.markdown ol > li {
list-style: decimal;
}
.markdown > ol li,
.markdown blockquote ol > li {
margin-left: 20px;
padding-left: 4px;
}
.markdown code {
margin: 0 3px;
padding: 0 5px;
background: #eee;
border-radius: 3px;
}
.markdown pre {
border-radius: 6px;
background: #f7f7f7;
padding: 20px;
}
.markdown pre code {
border: none;
background: #f7f7f7;
margin: 0;
}
.markdown strong,
.markdown b {
font-weight: 600;
}
.markdown > table {
border-collapse: collapse;
border-spacing: 0px;
empty-cells: show;
border: 1px solid #e9e9e9;
width: 95%;
margin-bottom: 24px;
}
.markdown > table th {
white-space: nowrap;
color: #333;
font-weight: 600;
}
.markdown > table th,
.markdown > table td {
border: 1px solid #e9e9e9;
padding: 8px 16px;
text-align: left;
}
.markdown > table th {
background: #F7F7F7;
}
.markdown blockquote {
font-size: 90%;
color: #999;
border-left: 4px solid #e9e9e9;
padding-left: 0.8em;
margin: 1em 0;
font-style: italic;
}
.markdown blockquote p {
margin: 0;
}
.markdown .anchor {
opacity: 0;
transition: opacity 0.3s ease;
margin-left: 8px;
}
.markdown .waiting {
color: #ccc;
}
.markdown h1:hover .anchor,
.markdown h2:hover .anchor,
.markdown h3:hover .anchor,
.markdown h4:hover .anchor,
.markdown h5:hover .anchor,
.markdown h6:hover .anchor {
opacity: 1;
display: inline-block;
}
.markdown > br,
.markdown > p > br {
clear: both;
}
.hljs {
display: block;
background: white;
padding: 0.5em;
color: #333333;
overflow-x: auto;
}
.hljs-comment,
.hljs-meta {
color: #969896;
}
.hljs-string,
.hljs-variable,
.hljs-template-variable,
.hljs-strong,
.hljs-emphasis,
.hljs-quote {
color: #df5000;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-type {
color: #a71d5d;
}
.hljs-literal,
.hljs-symbol,
.hljs-bullet,
.hljs-attribute {
color: #0086b3;
}
.hljs-section,
.hljs-name {
color: #63a35c;
}
.hljs-tag {
color: #333333;
}
.hljs-title,
.hljs-attr,
.hljs-selector-id,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo {
color: #795da3;
}
.hljs-addition {
color: #55a532;
background-color: #eaffea;
}
.hljs-deletion {
color: #bd2c00;
background-color: #ffecec;
}
.hljs-link {
text-decoration: underline;
}
pre{
background: #fff;
}

30
src/icon/iconfont.css Normal file
View File

@@ -0,0 +1,30 @@
@font-face {font-family: "fontFamily";
src: url('iconfont.eot?t=1527493375212'); /* IE9*/
src: url('iconfont.eot?t=1527493375212#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('data:application/x-font-woff;charset=utf-8;base64,d09GRgABAAAAAAXoAAsAAAAACHwAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABHU1VCAAABCAAAADMAAABCsP6z7U9TLzIAAAE8AAAARAAAAFZW7kf3Y21hcAAAAYAAAABjAAABnM7GacRnbHlmAAAB5AAAAfsAAAIsdf0weGhlYWQAAAPgAAAALwAAADYRguv+aGhlYQAABBAAAAAcAAAAJAfeA4VobXR4AAAELAAAABAAAAAQD+kAAGxvY2EAAAQ8AAAACgAAAAoBjAC6bWF4cAAABEgAAAAfAAAAIAEaAF1uYW1lAAAEaAAAAVMAAAKFV8s9R3Bvc3QAAAW8AAAAKgAAADsY6RIYeJxjYGRgYOBikGPQYWB0cfMJYeBgYGGAAJAMY05meiJQDMoDyrGAaQ4gZoOIAgCKIwNPAHicY2Bk/sU4gYGVgYOpk+kMAwNDP4RmfM1gxMjBwMDEwMrMgBUEpLmmMDgwVDzjZm7438AQw9zA0AAUZgTJAQAk0wx5eJzFkNENgCAMRK+ChIij+GkcyC9HYOKugdfCDxNw5JX2ckkJAHYAgVwkAvJBYHrpivsBh/sRD+fMs/GumrS0NnUm8UT2LlhSEpZJ1q2edXq9x2T/XQd8oqaO+Vo62H4fLw+3AHicLZC/b9NAFMffu6udpM0PbMdx4jQ/LhfXoDRBtpN2IGkXkArNgNQpKkiNYlSBRNd2YKiQEB0YWFDFCkiIiYEfytAJVbDTv6CFjYXSFhbsckE53dP3fZ/e6X3egQRwfkj3aBY0uAgOXIWbACjXsJIkBWR2s0FqqDNJN9JJanObRXilQTtoVOR0xp1rzhhyRE5hEovoMXfObhAbW80FcgXdTAExlzdXVGtapU9xMmsXH4U3yAvUS3w6tVAPr88upt2yFt2Mq2pOVZ9EZUmKEjKRSuJ9IxOTYpNy+EpKmfpe6RIpYTxnm91eopxX+zvNjYJlxBC3t1HLl5OvFxVTEfeBmdHUXORCIpo1E7yaxs3vU1ktXpj5BuJExK7P6A/agwmIQhxyUAAGltiXKUyxmM5GicaF4Yqns5ZnoCjqns5RBK0GlO4Hy7gTbuFRcESKu6vBvdVdAurL4DF2w/cHB1jvdGjvb5uy9Q/B3VFt1E27x8cPw2vtdpt83QIxGc6f0190A6hgmoKU+HsD8lACDpfBg3kAQ4AYo5ljRcFEecuTRG6NeSzeEpj/QTkVfl5EFofh0trp6dpY8RMOBycnwbLrkpLjBIdC3w1+zvaxduez73/x/XUc3jrDjzi8/RtXwiXx7u2Z7zhOmHbq+8JXB3/CN/1+H+AfnVR/vQB4nGNgZGBgAOLuWSW34/ltvjJwszCAwHXDy/8R9P+pLAzMeUAuBwMTSBQAWOoL7AB4nGNgZGBgbvjfwBDDwgACQJKRARWwAABHCgJtBAAAAAPpAAAEAAAABAAAAAAAAAAAdgC6ARYAAHicY2BkYGBgYQhk4GEAASYg5gJCBob/YD4DABGzAXgAeJxtkk1uwjAQhZ/LT9UgddHSdlmvWBQp/CzZooZlJRbsQ3AgKIkjxyDRXQ/Q8/QQPUE3vUHv0EcwQkIk8uibN2/GthIAd/iFwOF54DqwgMfswFe4xrPjGvWO4zq577iBFkaOm9RfHXvo4s1xC/d45wRRv2H2gk/HAm18Ob7CLb4d16j/OK6T/xw38CiE4yba4smxh5noOm6hIz68sVGhVQs538kk0nmsc+vtQxBmSbqbquUmDc1JONFMmTLRuRz4/ZM4Ubkyx3nldjm0Npax0ZkM6FFpqmVh9FpF1l9ZW4x6vdjpfqQzHm8MA4UQlnEBiTl2jAkiaOSIq2jpO1JAb8Z6St+UPUtsyCGnXHJc0mbsMiiZ7WsSA/j8ZJecEzrzyn1+vhJb7jykatkpuQz7M1Lg5ihOSMkSRVVbU4mo+1hVXQV/jR7f+MzvVzfP/gHCFnRdAHicY2BigAAuBuyAhZGJkZmRhZGVgbGCycCSI7WoPDUzN9GQgQEAJkQEKgAA') format('woff'),
url('iconfont.ttf?t=1527493375212') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/
url('iconfont.svg?t=1527493375212#fontFamily') format('svg'); /* iOS 4.1- */
}
.fontFamily {
font-family:"fontFamily" !important;
font-size:16px;
font-style:normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
[class^="el-icon-cjn"], [class*=" el-icon-cjn"] {
font-family:"fontFamily" !important;
/* 以下内容参照第三方图标库本身的规则 */
font-size: 13px;
font-style:normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.el-icon-cjn-09:before { content: "\e60b"; }
.el-icon-cjn-erweima1:before { content: "\e606"; }

BIN
src/icon/iconfont.eot Normal file

Binary file not shown.

1
src/icon/iconfont.js Normal file
View File

@@ -0,0 +1 @@
(function(window) { var svgSprite = '<svg><symbol id="el-icon-cjn-09" viewBox="0 0 1024 1024"><path d="M804.141176 39.152941H39.152941v963.764706h963.764706V201.788235l-198.776471-162.635294z m-493.929411 60.235294h391.529411v180.705883h-391.529411v-180.705883z m481.882353 843.294118h-542.117647v-331.294118h542.117647v331.294118z m150.588235 0h-90.352941v-391.529412h-662.588236v391.529412h-90.352941v-843.294118h150.588236v240.941177h512v-240.941177h18.070588l162.635294 129.505883v713.788235z" fill="#2c2c2c" ></path><path d="M310.211765 671.623529h331.294117v60.235295h-331.294117zM310.211765 792.094118h210.823529v60.235294h-210.823529zM611.388235 129.505882h60.235294v120.470589h-60.235294z" fill="#2c2c2c" ></path></symbol><symbol id="el-icon-cjn-erweima1" viewBox="0 0 1024 1024"><path d="M23.92225303 998.84837371l439.58598408 0L463.50823711 559.26238962 23.92225303 559.26238962 23.92225303 998.84837371zM119.78212494 651.01398129l243.75796004 0 0 245.12738674L119.78212494 896.14136803 119.78212494 651.01398129z" ></path><path d="M23.92225303 457.92481072l439.58598408 0 0-439.58598412L23.92225303 18.33882658 23.92225303 457.92481072zM119.78212494 111.45984508l243.75796004 0 0 245.12738672L119.78212494 356.5872318 119.78212494 111.45984508z" ></path><path d="M570.32352297 18.33882658l0 439.58598414L1009.90950704 457.92481072l0-439.58598412L570.32352297 18.33882658zM911.31078166 355.21780509L667.55282162 355.21780509l0-245.12738681 243.75796004 0L911.31078166 355.21780509z" ></path><path d="M218.38085034 210.05857039l49.29936273 0 0 49.29936276-49.29936273 0 0-49.29936276Z" ></path><path d="M760.67384005 210.05857039l49.29936271 0 0 49.29936276-49.29936273 0 0-49.29936276Z" ></path><path d="M218.38085034 750.98213347l49.29936273 0 0 49.29936266-49.29936273 0 0-49.29936266Z" ></path><path d="M908.57192818 755.09041369L809.97320276 755.09041369 809.97320276 559.26238962 570.32352297 559.26238962 570.32352297 998.84837371 614.14517874 998.84837371 614.14517874 707.16047766 711.37447735 707.16047766 711.37447735 805.75920314 1009.90950704 805.75920314 1009.90950704 559.26238962 908.57192818 559.26238962Z" ></path><path d="M711.37447735 901.61907503l99.96815218 0 0 97.22929868-99.96815218 0 0-97.22929868Z" ></path><path d="M909.94135491 901.61907503l99.96815213 0 0 97.22929868-99.96815213 0 0-97.22929868Z" ></path></symbol></svg>'; var script = (function() { var scripts = document.getElementsByTagName('script'); return scripts[scripts.length - 1] }()); var shouldInjectCss = script.getAttribute('data-injectcss'); var ready = function(fn) { if (document.addEventListener) { if (~['complete', 'loaded', 'interactive'].indexOf(document.readyState)) { setTimeout(fn, 0) } else { var loadFn = function() { document.removeEventListener('DOMContentLoaded', loadFn, false); fn() }; document.addEventListener('DOMContentLoaded', loadFn, false) } } else if (document.attachEvent) { IEContentLoaded(window, fn) } function IEContentLoaded(w, fn) { var d = w.document, done = false, init = function() { if (!done) { done = true; fn() } }; var polling = function() { try { d.documentElement.doScroll('left') } catch (e) { setTimeout(polling, 50); return }init() }; polling(); d.onreadystatechange = function() { if (d.readyState == 'complete') { d.onreadystatechange = null; init() } } } }; var before = function(el, target) { target.parentNode.insertBefore(el, target) }; var prepend = function(el, target) { if (target.firstChild) { before(el, target.firstChild) } else { target.appendChild(el) } }; function appendSvg() { var div, svg; div = document.createElement('div'); div.innerHTML = svgSprite; svgSprite = null; svg = div.getElementsByTagName('svg')[0]; if (svg) { svg.setAttribute('aria-hidden', 'true'); svg.style.position = 'absolute'; svg.style.width = 0; svg.style.height = 0; svg.style.overflow = 'hidden'; prepend(svg, document.body) } } if (shouldInjectCss && !window.__iconfont__svg__cssinject__) { window.__iconfont__svg__cssinject__ = true; try { document.write('<style>.svgfont {display: inline-block;width: 1em;height: 1em;fill: currentColor;vertical-align: -0.1em;font-size:16px;}</style>') } catch (e) { console && console.log(e) } }ready(appendSvg) })(window)

39
src/icon/iconfont.svg Normal file
View File

@@ -0,0 +1,39 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<!--
2013-9-30: Created.
-->
<svg>
<metadata>
Created by iconfont
</metadata>
<defs>
<font id="fontFamily" horiz-adv-x="1024" >
<font-face
font-family="fontFamily"
font-weight="500"
font-stretch="normal"
units-per-em="1024"
ascent="896"
descent="-128"
/>
<missing-glyph />
<glyph glyph-name="x" unicode="x" horiz-adv-x="1001"
d="M281 543q-27 -1 -53 -1h-83q-18 0 -36.5 -6t-32.5 -18.5t-23 -32t-9 -45.5v-76h912v41q0 16 -0.5 30t-0.5 18q0 13 -5 29t-17 29.5t-31.5 22.5t-49.5 9h-133v-97h-438v97zM955 310v-52q0 -23 0.5 -52t0.5 -58t-10.5 -47.5t-26 -30t-33 -16t-31.5 -4.5q-14 -1 -29.5 -0.5
t-29.5 0.5h-32l-45 128h-439l-44 -128h-29h-34q-20 0 -45 1q-25 0 -41 9.5t-25.5 23t-13.5 29.5t-4 30v167h911zM163 247q-12 0 -21 -8.5t-9 -21.5t9 -21.5t21 -8.5q13 0 22 8.5t9 21.5t-9 21.5t-22 8.5zM316 123q-8 -26 -14 -48q-5 -19 -10.5 -37t-7.5 -25t-3 -15t1 -14.5
t9.5 -10.5t21.5 -4h37h67h81h80h64h36q23 0 34 12t2 38q-5 13 -9.5 30.5t-9.5 34.5q-5 19 -11 39h-368zM336 498v228q0 11 2.5 23t10 21.5t20.5 15.5t34 6h188q31 0 51.5 -14.5t20.5 -52.5v-227h-327z" />
<glyph glyph-name="09" unicode="&#58891;" d="M804.141 856.847h-764.988v-963.765h963.765v801.129l-198.776 162.635zM310.212 796.612h391.529v-180.706h-391.529v180.706zM792.094-46.682h-542.118v331.294h542.118v-331.294zM942.682-46.682h-90.353v391.529h-662.588v-391.529h-90.353v843.294h150.588v-240.941h512v240.941h18.071l162.635-129.506v-713.788zM310.212 224.376h331.294v-60.235h-331.294zM310.212 103.906h210.824v-60.235h-210.824zM611.388 766.494h60.235v-120.471h-60.235z" horiz-adv-x="1024" />
<glyph glyph-name="erweima1" unicode="&#58886;" d="M23.92225303-102.84837371000003l439.58598408 0L463.50823711 336.73761038 23.92225303 336.73761038 23.92225303-102.84837371000003zM119.78212494 244.98601871000005l243.75796004 0 0-245.12738674L119.78212494-0.1413680299999669 119.78212494 244.98601871000005zM23.92225303 438.07518928l439.58598408 0 0 439.58598412L23.92225303 877.66117342 23.92225303 438.07518928zM119.78212494 784.54015492l243.75796004 0 0-245.12738672L119.78212494 539.4127682000001 119.78212494 784.54015492zM570.32352297 877.66117342l0-439.58598414L1009.90950704 438.07518928l0 439.58598412L570.32352297 877.66117342zM911.31078166 540.78219491L667.55282162 540.78219491l0 245.12738681 243.75796004 0L911.31078166 540.78219491zM218.38085034 685.94142961l49.29936273 0 0-49.29936276-49.29936273 0 0 49.29936276ZM760.67384005 685.94142961l49.29936271 0 0-49.29936276-49.29936273 0 0 49.29936276ZM218.38085034 145.01786653l49.29936273 0 0-49.29936266-49.29936273 0 0 49.29936266ZM908.57192818 140.90958631L809.97320276 140.90958631 809.97320276 336.73761038 570.32352297 336.73761038 570.32352297-102.84837371000003 614.14517874-102.84837371000003 614.14517874 188.83952234000003 711.37447735 188.83952234000003 711.37447735 90.24079686000005 1009.90950704 90.24079686000005 1009.90950704 336.73761038 908.57192818 336.73761038ZM711.37447735-5.619075029999976l99.96815218 0 0-97.22929868-99.96815218 0 0 97.22929868ZM909.94135491-5.619075029999976l99.96815213 0 0-97.22929868-99.96815213 0 0 97.22929868Z" horiz-adv-x="1024" />
</font>
</defs></svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
src/icon/iconfont.ttf Normal file

Binary file not shown.

BIN
src/icon/iconfont.woff Normal file

Binary file not shown.

22
src/icons/svgo.yml Normal file
View File

@@ -0,0 +1,22 @@
# replace default config
# multipass: true
# full: true
plugins:
# - name
#
# or:
# - name: false
# - name: true
#
# or:
# - name:
# param1: 1
# param2: 2
- removeAttrs:
attrs:
- 'fill'
- 'fill-rule'

BIN
src/img/ActualOutput.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
src/img/FaultsTime.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
src/img/NumberFaults.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1006 B

BIN
src/img/OEEAnalysis.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
src/img/ProductionPlan.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
src/img/rhythm.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

68
src/main.js Normal file
View File

@@ -0,0 +1,68 @@
import Vue from 'vue'
import 'element-ui/lib/theme-chalk/index.css'
import App from './App.vue'
import store from './store/index'
import ElementUI from 'element-ui'
import router from './router'
import * as echarts from 'echarts'
import curd from '@/utils/curd'
// import '@/styles/index.scss' // global css
import VueParticles from 'vue-particles'
import jsonp from 'vue-jsonp'
import { Guid } from '@/utils/tool'
import service from '@/utils/request'
import scroll from 'vue-seamless-scroll'
import mqtt from 'mqtt'
import elDragDialog from '@/directive/el-dragDialog'
Vue.use(elDragDialog)
// 关闭点弹窗周围关闭功能 -- 20200218
ElementUI.Dialog.props.closeOnClickModal.default = false
Vue.prototype.Guid = Guid
Vue.prototype.ExecDatabase = function(num) {
return service({
url: '',
method: 'post',
data: num
})
}
Vue.use(scroll)
Vue.use(VueParticles)
Vue.use(curd)
Vue.use(jsonp)
Vue.use(ElementUI)
Vue.prototype.echarts = echarts
Vue.prototype.mqtt = mqtt
Vue.config.productionTip = true
Vue.directive('loadmore', {
bind(el, binding) {
var p = 0
var t = 0
var down = true
var selectWrap = el.querySelector('.el-table__body-wrapper')
selectWrap.addEventListener('scroll', function() {
// 判断是否向下滚动
p = this.scrollTop
// if ( t < p){down=true}else{down=false}
if (t < p) {
down = true
} else {
down = false
}
t = p
// 判断是否到底
const sign = 10
const scrollDistance = this.scrollHeight - this.scrollTop - this.clientHeight
if (scrollDistance <= sign && down) {
binding.value()
}
})
} })
new Vue({
store,
router,
render: h => h(App)
}).$mount('#app')
import $ from 'jquery'

25
src/router/index.js Normal file
View File

@@ -0,0 +1,25 @@
import Vue from 'vue'
import Router from 'vue-router'
// import index from '@/views/index.vue'
// import indexDemo from '@/views/indexDemo.vue'
// import QX409 from '@/views/QX409.vue'
// import QX436 from '@/views/QX436.vue'
import DaLuJia from '@/views/DaLuJia.vue'
Vue.use(Router)
export const constantRouterMap = [
{
path: '/',
name: 'DaLuJia',
component: DaLuJia,
meta: {
keepAlive: true
}
}
]
export default new Router({
scrollBehavior: () => ({ y: 0 }),
routes: constantRouterMap
})

15
src/store/getters.js Normal file
View File

@@ -0,0 +1,15 @@
const getters = {
sidebar: state => state.app.sidebar,
device: state => state.app.device,
token: state => state.user.token,
avatar: state => state.user.avatar,
name: state => state.user.name,
roles: state => state.user.roles,
visitedViews: state => state.tagsView.visitedViews,
cachedViews: state => state.tagsView.cachedViews,
permission_routers: state => state.permission.routers,
addRouters: state => state.permission.addRouters,
id: state => state.user.id,
account: state => state.user.account
}
export default getters

21
src/store/index.js Normal file
View File

@@ -0,0 +1,21 @@
import Vue from 'vue'
import Vuex from 'vuex'
import app from './modules/app'
import tagsView from './modules/tagsView'
import user from './modules/user'
import permission from './modules/permission'
import getters from './getters'
Vue.use(Vuex)
const store = new Vuex.Store({
modules: {
app,
user,
tagsView,
permission
},
getters
})
export default store

43
src/store/modules/app.js Normal file
View File

@@ -0,0 +1,43 @@
import Cookies from 'js-cookie'
const app = {
state: {
sidebar: {
opened: !+Cookies.get('sidebarStatus'),
withoutAnimation: false
},
device: 'desktop'
},
mutations: {
TOGGLE_SIDEBAR: state => {
if (state.sidebar.opened) {
Cookies.set('sidebarStatus', 1)
} else {
Cookies.set('sidebarStatus', 0)
}
state.sidebar.opened = !state.sidebar.opened
state.sidebar.withoutAnimation = false
},
CLOSE_SIDEBAR: (state, withoutAnimation) => {
Cookies.set('sidebarStatus', 1)
state.sidebar.opened = false
state.sidebar.withoutAnimation = withoutAnimation
},
TOGGLE_DEVICE: (state, device) => {
state.device = device
}
},
actions: {
ToggleSideBar: ({ commit }) => {
commit('TOGGLE_SIDEBAR')
},
CloseSideBar({ commit }, { withoutAnimation }) {
commit('CLOSE_SIDEBAR', withoutAnimation)
},
ToggleDevice({ commit }, device) {
commit('TOGGLE_DEVICE', device)
}
}
}
export default app

View File

@@ -0,0 +1,87 @@
import { getToken, setToken, removeToken } from '@/utils/auth'
import Cookies from 'js-cookie'
import { Message } from 'element-ui'
import axios from 'axios'
import { getPayToken } from '@/utils/request'
const user = {
state: {
token: getToken(),
name: Cookies.get('name'),
roles: [],
id: Cookies.get('id')
},
mutations: {
SET_TOKEN: (state, token) => {
state.token = token
},
SET_NAME: (state, name) => {
state.name = name
},
SET_ROLES: (state, roles) => {
state.roles = roles
},
SET_ID: (state, id) => {
state.id = id
}
},
actions: {
// 登录
Login({ commit }, userInfo) {
console.log(userInfo.username)
const username = userInfo.username.trim()
const password = userInfo.password.trim()
return new Promise((resolve, reject) => {
var url = getPayToken + '?userName=' + username + '&passWord=' + password
axios.get(url).then(response => {
console.log(response)
const data = response.data
if (data.IsSuccess === false) {
// const h = this.$createElement
// this.$message({
// message: h('p', null, [
// h('span', null, '错误代码: '),
// h('i', { style: 'color: teal' }, `${{ data.ErrorCode }}`)
// ])
// })
// Message.error(`错误代码`+`${{ data.ErrorCode }}`+`,`+`${{ data.ErrorDesc }}`)
var a = '错误' + response.data.ErrorCode + ',' + data.ErrorDesc
Message({
showClose: true,
message: a,
type: 'error'
})
this.$router.push({ path: '/login' })
}
if (data.token === '' || data.$id === '' || data === '') {
Message.error('账号或密码错误,请重新登录')
this.$router.push({ path: '/login' })
} else { // 只有一个角色
setToken(data.token)
Cookies.set('id', data.$id, { expires: 1 })
Cookies.set('name', username, { expires: 1 })
commit('SET_TOKEN', data.token)
commit('SET_NAME', username)
commit('SET_ID', data.$id)
resolve({ data, commit })
}
}).catch(error => {
reject(error)
})
})
},
// 登出
FedLogOut({ commit }) {
return new Promise(resolve => {
commit('SET_TOKEN', '')
Cookies.remove('name')
Cookies.remove('id')
removeToken()
resolve()
})
}
}
}
export default user

View File

@@ -0,0 +1,23 @@
import { constantRouterMap } from '@/router'
const permission = {
state: {
routers: constantRouterMap,
addRouters: []
},
mutations: {
SET_ROUTERS: (state, routers) => {
state.addRouters = routers
state.routers = constantRouterMap.concat(routers)
}
},
actions: {
GenerateRoutes({ commit }, data) {
return new Promise(resolve => {
const accessedRouters = data
commit('SET_ROUTERS', accessedRouters)
resolve()
})
}
}
}
export default permission

View File

@@ -0,0 +1,78 @@
const tagsView = {
state: {
visitedViews: [],
cachedViews: []
},
mutations: {
ADD_VISITED_VIEWS: (state, view) => {
if (state.visitedViews.some(v => v.path === view.path)) return
state.visitedViews.push({
name: view.name,
path: view.path,
title: view.meta.title || 'no-name'
})
if (!view.meta.noCache) {
state.cachedViews.push(view.name)
}
},
DEL_VISITED_VIEWS: (state, view) => {
for (const [i, v] of state.visitedViews.entries()) {
if (v.path === view.path) {
state.visitedViews.splice(i, 1)
break
}
}
for (const i of state.cachedViews) {
if (i === view.name) {
const index = state.cachedViews.indexOf(i)
state.cachedViews.splice(index, 1)
break
}
}
},
DEL_OTHERS_VIEWS: (state, view) => {
for (const [i, v] of state.visitedViews.entries()) {
if (v.path === view.path) {
state.visitedViews = state.visitedViews.slice(i, i + 1)
break
}
}
for (const i of state.cachedViews) {
if (i === view.name) {
const index = state.cachedViews.indexOf(i)
state.cachedViews = state.cachedViews.slice(index, i + 1)
break
}
}
},
DEL_ALL_VIEWS: (state) => {
state.visitedViews = []
state.cachedViews = []
}
},
actions: {
addVisitedViews({ commit }, view) {
commit('ADD_VISITED_VIEWS', view)
},
delVisitedViews({ commit, state }, view) {
return new Promise((resolve) => {
commit('DEL_VISITED_VIEWS', view)
resolve([...state.visitedViews])
})
},
delOthersViews({ commit, state }, view) {
return new Promise((resolve) => {
commit('DEL_OTHERS_VIEWS', view)
resolve([...state.visitedViews])
})
},
delAllViews({ commit, state }) {
return new Promise((resolve) => {
commit('DEL_ALL_VIEWS')
resolve([...state.visitedViews])
})
}
}
}
export default tagsView

85
src/store/modules/user.js Normal file
View File

@@ -0,0 +1,85 @@
import { getToken, setToken, removeToken } from '@/utils/auth'
import Cookies from 'js-cookie'
import { Message } from 'element-ui'
import axios from 'axios'
import { getPayToken } from '@/utils/request'
const user = {
state: {
token: getToken(),
name: Cookies.get('name'),
roles: [],
id: Cookies.get('id')
},
mutations: {
SET_TOKEN: (state, token) => {
state.token = token
},
SET_NAME: (state, name) => {
state.name = name
},
SET_ROLES: (state, roles) => {
state.roles = roles
},
SET_ID: (state, id) => {
state.id = id
}
},
actions: {
// 登录
Login({ commit }, userInfo) {
const username = userInfo.username.trim()
const password = userInfo.password.trim()
return new Promise((resolve, reject) => {
var url = getPayToken + '?userName=' + username + '&passWord=' + password
axios.get(url).then(response => {
const data = response.data
if (data.IsSuccess === false) {
// const h = this.$createElement
// this.$message({
// message: h('p', null, [
// h('span', null, '错误代码: '),
// h('i', { style: 'color: teal' }, `${{ data.ErrorCode }}`)
// ])
// })
// Message.error(`错误代码`+`${{ data.ErrorCode }}`+`,`+`${{ data.ErrorDesc }}`)
var a = '错误' + response.data.ErrorCode + ',' + data.ErrorDesc
Message({
showClose: true,
message: a,
type: 'error'
})
this.$router.push({ path: '/login' })
}
if (data.token === '' || data.$id === '' || data === '') {
Message.error('账号或密码错误,请重新登录')
this.$router.push({ path: '/login' })
} else { // 只有一个角色
setToken(data.token)
Cookies.set('id', data.$id, { expires: 1 })
Cookies.set('name', username, { expires: 1 })
commit('SET_TOKEN', data.token)
commit('SET_NAME', username)
commit('SET_ID', data.$id)
resolve({ data, commit })
}
}).catch(error => {
reject(error)
})
})
},
// 登出
FedLogOut({ commit }) {
return new Promise(resolve => {
commit('SET_TOKEN', '')
Cookies.remove('name')
Cookies.remove('id')
removeToken()
resolve()
})
}
}
}
export default user

View File

@@ -0,0 +1,30 @@
//to reset element-ui default css
.el-upload {
input[type="file"] {
display: none !important;
}
}
.el-upload__input {
display: none;
}
//暂时性解决diolag 问题 https://github.com/ElemeFE/element/issues/2461
.el-dialog {
transform: none;
left: 0;
position: relative;
margin: 0 auto;
}
//element ui upload
.upload-container {
.el-upload {
width: 100%;
.el-upload-dragger {
width: 100%;
height: 200px;
}
}
}

143
src/styles/index.scss Normal file
View File

@@ -0,0 +1,143 @@
@import './variables.scss';
@import './mixin.scss';
@import './transition.scss';
@import './element-ui.scss';
@import './sidebar.scss';
@import '../assets/font/Misans.css';
HTML{
overflow: auto;
}
body {
height: 100%;
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
font-family: MiSans Demibold, serif;
}
label {
font-weight: 700;
}
html {
height: 100%;
box-sizing: border-box;
}
#app{
height: 100%;
.sidebar-container{
background-color: #2e296a;
}
}
*,
*:before,
*:after {
box-sizing: inherit;
}
a,
a:focus,
a:hover {
cursor: pointer;
color: inherit;
outline: none;
text-decoration: none;
}
div:focus{
outline: none;
}
a:focus,
a:active {
outline: none;
}
a,
a:focus,
a:hover {
cursor: pointer;
color: inherit;
text-decoration: none;
}
.clearfix {
&:after {
visibility: hidden;
display: block;
font-size: 0;
content: " ";
clear: both;
height: 0;
}
}
//main-container全局样式
.app-main{
min-height: 100%;
}
.app-container {
//background-color: #ebf1ee;
}
.navbar{
background-color: #2D3C67!important;
}
.submenu-title-noDropdown{
background-color: black!important;
color: #00893D!important;
}
.el-menu-item.is-active{
color:#2456E6!important;
}
el-form-item__content{
background-color: #00893D!important;
}
.el-menu-item:hover{
background-color: #00893D !important;
color: #fff!important;
}
.el-menu-item, .el-submenu__title{
line-height: 42px;
height: 42px;
background-color: #F5F5F5!important;
color: #000000!important;
}
.el-scrollbar{
height: 100%;
}
.el-submenu__title{
color: #000000!important;
background-color: #F5F5F5!important;
}
.el-button--success {
color: #fff;
background-color: #67c23a ;
border-color: #67c23a ;
}
.el-button--success.is-plain {
color: #67c23a!important;
background: #FAFAFA!important;
border-color: #67c23a!important;
}
.el-button--success:hover {
color: #FAFAFA!important;
background-color: #67c23a!important;
border-color: #67c23a!important;
}
.el-button--success:focus {
color: #FAFAFA!important;
background-color: #67c23a!important;
border-color: #67c23a!important;
}
.el-dialog__wrapper {
pointer-events: none;
}
.el-dialog {
pointer-events: auto;
}

27
src/styles/mixin.scss Normal file
View File

@@ -0,0 +1,27 @@
@mixin clearfix {
&:after {
content: "";
display: table;
clear: both;
}
}
@mixin scrollBar {
&::-webkit-scrollbar-track-piece {
background: #d3dce6;
}
&::-webkit-scrollbar {
width: 6px;
}
&::-webkit-scrollbar-thumb {
background: #99a9bf;
border-radius: 20px;
}
}
@mixin relative {
position: relative;
width: 100%;
height: 100%;
}

123
src/styles/sidebar.scss Normal file
View File

@@ -0,0 +1,123 @@
#app {
// 主体区域
.main-container {
min-height: 100%;
transition: margin-left .28s;
margin-left: 200px;
position: relative;
}
// 侧边栏
.sidebar-container {
transition: width 0.28s;
width: 200px !important;
height: 100%;
position: fixed;
font-size: 0px;
top: 0;
bottom: 0;
left: 0;
z-index: 1001;
overflow: hidden;
//reset element-ui css
.horizontal-collapse-transition {
transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
}
.el-scrollbar__bar.is-vertical{
right: 0px;
}
.scrollbar-wrapper {
overflow-x: hidden!important;
.el-scrollbar__view {
height: 100%;
}
}
.is-horizontal {
display: none;
}
a {
display: inline-block;
width: 100%;
overflow: hidden;
}
.svg-icon {
margin-right: 16px;
}
.el-menu {
border: none;
height: 100%;
background: #F5F5F5!important;
width: 100% !important;
}
}
.hideSidebar {
.sidebar-container {
width: 36px !important;
}
.main-container {
margin-left: 36px;
}
.submenu-title-noDropdown {
padding-left: 10px !important;
position: relative;
.el-tooltip {
padding: 0 10px !important;
}
}
.el-submenu {
overflow: hidden;
&>.el-submenu__title {
padding-left: 10px !important;
.el-submenu__icon-arrow {
display: none;
}
}
}
.el-menu--collapse {
.el-submenu {
&>.el-submenu__title {
&>span {
height: 0;
width: 0;
overflow: hidden;
visibility: hidden;
display: inline-block;
}
}
}
}
}
.sidebar-container .nest-menu .el-submenu>.el-submenu__title,
.sidebar-container .el-submenu .el-menu-item {
min-width: 200px !important;
background-color: $subMenuBg !important;
&:hover {
background-color: $menuHover !important;
}
}
.el-menu--collapse .el-menu .el-submenu {
min-width: 180px !important;
}
//适配移动端
.mobile {
.main-container {
margin-left: 0px;
}
.sidebar-container {
transition: transform .28s;
width: 180px !important;
}
&.hideSidebar {
.sidebar-container {
transition-duration: 0.3s;
transform: translate3d(-180px, 0, 0);
}
}
}
.withoutAnimation {
.main-container,
.sidebar-container {
transition: none;
}
}
}

View File

@@ -0,0 +1,46 @@
//globl transition css
/*fade*/
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.28s;
}
.fade-enter,
.fade-leave-active {
opacity: 0;
}
/*fade-transform*/
.fade-transform-leave-active,
.fade-transform-enter-active {
transition: all .5s;
}
.fade-transform-enter {
opacity: 0;
transform: translateX(-30px);
}
.fade-transform-leave-to {
opacity: 0;
transform: translateX(30px);
}
/*fade*/
.breadcrumb-enter-active,
.breadcrumb-leave-active {
transition: all .5s;
}
.breadcrumb-enter,
.breadcrumb-leave-active {
opacity: 0;
transform: translateX(20px);
}
.breadcrumb-move {
transition: all .5s;
}
.breadcrumb-leave-active {
position: absolute;
}

View File

@@ -0,0 +1,4 @@
//sidebar
$menuBg:#2D3C67;
$subMenuBg:#F8F8FF;
$menuHover:#2D3C67;

View File

@@ -0,0 +1,21 @@
import axios from 'axios'
class HttpRequestCreate {
constructor(config) {
this.config = config
}
createRequest() {
const service = axios.create({
baseURL: this.config.baseURL,
method: this.config.method,
responseType: this.config.responseType,
timeout: this.config.timeout
})
service.defaults.headers[this.config.method]['Content-Type'] = this.config['Content-Type']
return service
}
}
export {
HttpRequestCreate
}

15
src/utils/auth.js Normal file
View File

@@ -0,0 +1,15 @@
import Cookies from 'js-cookie'
const TokenKey = 'Admin-Token'
export function getToken() {
return Cookies.get(TokenKey)
}
export function setToken(token) {
return Cookies.set(TokenKey, token)
}
export function removeToken() {
return Cookies.remove(TokenKey)
}

387
src/utils/curd.js Normal file
View File

@@ -0,0 +1,387 @@
import { type } from './tool' // type判断传入值的类型比typeof更详细
// import axios from 'axios'
// import { url } from '../main'
import { ExcelDownLoad, serviceDT_Process } from '@/utils/request'
export default {
install(Vue) {
Vue.prototype.exportExcel_NPOI = function(param, blob) {
download(`${ExcelDownLoad}?param=${param}`, blob)
}
// 用于生成传通讯服务器参数。
// 传入参数
// 1type11查询12增删改必须
// 2name存储过程名必须
// 3data存储过程参数名和对应值例如
// this.param[0] = ['设备类型编码', '3', 'string', '0']
// this.param[1] = ['output', '3', 'int', '1'],必须
// 数组里四个分别对应存储过程参数名必须存储过程参数值必须参数类型若是output必须参数是否为output0否1是
// 4pageSizepageCurrent分页使用可选
// 读写数字孪生GET
Vue.prototype.ExecDT_Process_Get = function(URL, params) {
return serviceDT_Process({
url: URL,
method: 'get',
params: params
})
}
Vue.prototype.CreateData = function(type, name, data, pageSize, pageList) {
var param_Str = ''
var param_array = []
if (type === '7') {
data.map(v => {
pageSize.map(h => {
const val = h.toString()
if (!v[val]) {
this.$set(v, val, '')
}
})
})
param_Str = data
} else {
if (data !== undefined) {
for (let i = 0; i < data.length; i++) {
param_array.push({
name: data[i][0],
value: data[i][1],
type: data[i][2],
output: data[i][3]
})
}
param_Str = JSON.stringify(param_array)
}
}
var obj = []
obj[0] = {}
obj[0].type = type
obj[0].name = name
obj[0].param = param_Str
obj[0].pageSize = pageSize
obj[0].pageList = pageList
obj[0].pageList = pageList
obj[0].UserID = this.id
// obj[0].ModularID = this.$router.currentRoute.path
return JSON.stringify(obj[0])
}
Vue.prototype.CreateData1 = function(type, name, data, pageSize, pageList) {
var param_Str = ''
var param_array = []
if (data !== undefined) {
for (let i = 0; i < data.length; i++) {
param_array.push({
name: data[i][0],
value: data[i][1],
type: data[i][2],
output: data[i][3]
})
}
param_Str = JSON.stringify(param_array)
}
var obj = []
obj[0] = {}
obj[0].type = type
obj[0].name = name
obj[0].param = param_Str
obj[0].pageSize = pageSize
obj[0].pageList = pageList
var numn = JSON.stringify(obj[0])
return numn
}
// 生成
Vue.prototype.CreatePost = function(data) {
var param_Str = ''
var param_array = []
if (data !== undefined) {
for (let i = 0; i < data.length; i++) {
param_array.push({
name: data[i][0],
value: data[i][1]
})
}
param_Str = JSON.stringify(param_array)
}
var obj = []
obj[0] = {}
obj[0].param = param_Str
var numn = JSON.stringify(obj[0])
return numn
}
// 用于打开增加框,方法能重置表单,并使表单内容回到初始化状态。
// 传入参数
// 1表单名称字符串形式如'form',必须
// 2) 打开表单后需要做什么,可以传数组[this.dialogvisiale = false fetchData],也可以传回调函数function() { this.dialogvisiale = false } 可选
Vue.prototype.addForm = function(form, callback) {
if (type(form) === 'string') {
if (this.$refs[form]) { // 判断是否需要重置表单,如果需要重置表单
this.$refs[form].resetFields()
}
if (type(callback) === 'array') { // 判断传入是否为数组,如果是遍历数组,遇到函数将函数体变成函数执行,其余正常执行
if (callback && callback.length !== 0) {
for (let i = 0, len = callback.length; i < len; i++) {
typeof callback[i] === 'function' ? callback[i]() : callback[i]
}
}
} else if (type(callback) === 'function') { // 判断传入是否为回调函数
callback.call(this) // 回调函数执行需将this改为该组件
}
this[form] = Object.assign(this.$data[form], this.$options.data()[form]) // 将表单中的数据变为初始状态。其中,this.$options.data是所有初始化的数据this.$data是目前的数据
} else {
console.error('传入参数错误')
}
}
// 用于打开编辑框,方法能自动传入行的数据到对应的表单中,并将表单中所有纯数字转成int。前提是行的名称需跟表单名称一样。
// 传入参数
// 1) 编辑这一行的row
// 2表单名称字符串形式如'form'
// 3) 打开编辑需要做什么,同样是[] 和 function
Vue.prototype.editForm = function(row, form, callback) {
if (type(row) === 'object' && type(form) === 'string') {
if (this.$refs[form]) { // 判断是否需要重置表单
this.$refs[form].resetFields()
}
const isNum = /^[0-9]+$/ // 正则表达式,是否全都为纯数字
for (const prop in this[form]) { // 遍历表单当表单和row中属性名一样时表单row中的属性赋值给form
isNum.lastIndex = 0 // 正则每一次匹配后的索引归0否则循环会造成问题
isNum.exec(row[prop]) ? this[form][prop] = parseInt(row[prop]) : this[form][prop] = row[prop] // 通过正则匹配数字当匹配成功后将字符串转为int。当然你也不用担心空转成NaN,因为''匹配通不过!
}
if (type(callback) === 'array') { // 这部分处理与打开表单相同
if (callback && callback.length !== 0) {
for (let i = 0, len = callback.length; i < len; i++) {
typeof callback[i] === 'function' ? callback[i]() : callback[i]
}
}
} else if (type(callback) === 'function') {
callback.call(this)
}
} else {
console.error('传入参数错误')
}
}
// 用于获取下拉框中的数据
// 传入参数
// 1请求数据函数引用如getXXX必须
// 2数组的实行名称['XXXX名称', 'XXXX代码'],必须
// 3需要用哪个数组接收这个结果字符串形式。如在组件也需要用this.select,传入值就为'select',必须
// 4) 请求函数传入的参数,可选
Vue.prototype.getSelect = function(requestData, select, carrier, param) {
if (type(requestData) === 'function' && type(select) === 'array' && type(carrier) === 'string') {
if (type(param) === 'array') {
requestData(...param).then(response => { // 这个方法没什么难度,不注释了
this[carrier] = []
for (let i = 0, len = response.data.length; i < len; i++) {
if (select.length === 2) {
this[carrier].push({
label: response.data[i][select[0]],
value: response.data[i][select[1]]
})
} else {
this[carrier].push({
value: response.data[i][select[0]]
})
}
}
})
} else {
requestData(param).then(response => { // 这个方法没什么难度,不注释了
this[carrier] = []
for (let i = 0, len = response.data.length; i < len; i++) {
if (select.length === 2) {
this[carrier].push({
label: response.data[i][select[0]],
value: response.data[i][select[1]]
})
} else {
this[carrier].push({
value: response.data[i][select[0]]
})
}
}
})
}
} else {
console.error('参数传递错误')
}
}
// 普通获取数据
// 传入参数
// 1) 请求数据函数引用如getXXX必须
// 2) 需要用哪个数组接收这个结果字符串形式。如在组件也需要用this.select,传入值就为'select',必须
// 3) 请求函数传入的参数,可选
Vue.prototype.getData = function(requestData, carrier, param) {
if (type(requestData) === 'function' && type(carrier) === 'string') {
if (type(param) === 'undefined') {
requestData(param).then(response => {
const data = response.data
this[carrier] = data
})
} else {
let Param = []
if (type(param) !== 'array') {
Param.push(param)
} else {
Param = param
}
requestData(...Param).then(response => {
const data = response.data
this[carrier] = data
})
}
} else {
console.error('传入参数错误')
}
}
// 获取表格数据,将表格中的年月日时分秒,转换成年月日
// 传入参数
// 1请求数据函数引用如getXXX必须
// 2请求的参数可选
// 3接受值数组一般是['table','total','loading']顺序不能变
Vue.prototype.getTable = function(requestData, param, e) {
requestData(...param).then(response => {
const data = response.data.rows
this[e[0]] = []
this[e[1]] = 0
if (data && data.length > 0) {
const isTime = /^\d{4}([-\/.])\d{1,2}\1\d{1,2}/ // 判断是否是时间的正则表达式
for (let i = 0, len = data.length; i < len; i++) { // 循环得到每一条数据
for (const prop in data[i]) { // 循环每一条的每一项
isTime.lastIndex = 0 // 正则每一次指针复位
if (isTime.test(data[i][prop])) { // 判断是否是时间,如果是切割
data[i][prop] = data[i][prop].split(' ')[0]
}
}
}
this[e[0]] = data
this[e[1]] = parseInt(response.data.total)
} else {
this[e[0]] = []
// console.log('暂无数据')
}
}).then(() => {
this[e[2]] = false
})
}
// 添加表格数据
// 传入参数
// 1) 请求数据函数引用如getXXX必须
// 2) 请求的参数,可选
// 3) 验证的表单名称,必须
// 4) 回调函数,必须
Vue.prototype.addTable = function(requestData, param, form, callback) {
if (type(callback) === 'function' && type(requestData) === 'function' && type(form) === 'string') {
console.log(this.$refs[form])
this.$refs[form].validate((valid) => {
console.log(valid)
if (valid) {
requestData(...param).then(response => {
if (response.data[0].result === '1') {
this.$message.success('增加成功')
callback.call(this)
} else { this.$message.error('增加失败') }
})
} else {
console.error('error submit!!')
return false
}
})
} else {
console.error('参数传递错误')
}
}
// 编辑表格数据
// 传入参数
// 1) 请求数据函数引用如getXXX必须
// 2) 请求的参数,可选
// 3) 验证的表单名称,必须
// 4) 回调函数,必须
Vue.prototype.editTable = function(requestData, param, form, callback) {
if (type(callback) === 'function' && type(requestData) === 'function' && type(form) === 'string') {
this.$refs[form].validate((valid) => {
if (valid) {
requestData(...param).then(response => {
if (response.data[0].result === '1') {
this.$message.success('修改成功')
callback.call(this) // 回调函数修正this指向组件本身
} else { this.$message.error('修改失败') }
})
} else {
console.error('error submit!!')
return false
}
})
} else {
console.error('参数传递错误')
}
}
// 删除表格数据
// 传入参数
// 1) 请求数据函数引用如getXXX必须
// 2) id传入删除条件必须
// 3) 回调函数,必须
Vue.prototype.deleteRow = function(requestData, id, callback) {
if (type(callback) === 'function' && type(requestData) === 'function') {
if (this.tableData && this.tableData.length === 1 && this.pageCurrent > 1) { // 判断删除的是否是最后一页最后一行,如果是且不是第一页,页数减一
this.pageCurrent--
}
this.$confirm('此操作将永久删除该行, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
requestData(id).then(response => {
if (response.data[0].result === '1') {
this.$message.success('删除成功')
callback.call(this) // 回调函数修正this指向组件本身
} else { this.$message.error('数据占用') }
})
}).catch(() => {
this.$message({
type: 'info',
message: '已取消删除'
})
})
} else {
console.error('参数传递错误')
}
}
}
}
function download(url, imgblob) {
getBlob(url, function(blob, filename) {
saveAs(blob, filename)
}, imgblob)
}
function getBlob(url, cb, imgblob) {
var xhr = new XMLHttpRequest()
var fromData = new FormData()
fromData.append('base64', imgblob)
xhr.open('POST', url, true)
xhr.responseType = 'blob'
xhr.onload = function() {
if (xhr.status === 200) {
const name = xhr.getResponseHeader('content-disposition').split('=')[1]
var filename = decodeURIComponent(name)
cb(xhr.response, filename)
}
}
// xhr.send()
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
xhr.send(fromData)
}
function saveAs(blob, filename) {
if (window.navigator.msSaveOrOpenBlob) {
navigator.msSaveBlob(blob, filename)
} else {
var link = document.createElement('a')
var body = document.querySelector('body')
link.href = window.URL.createObjectURL(blob)
link.download = filename
// fix Firefox
link.style.display = 'none'
body.appendChild(link)
link.click()
body.removeChild(link)
window.URL.revokeObjectURL(link.href)
}
}

27
src/utils/request.js Normal file
View File

@@ -0,0 +1,27 @@
import axios from 'axios'
export const wsuri = 'ws://localhost:8247//WebMoudule//websocket'
export const opname = 'SCADAMain' // TOBS??SCADAMain?MES|Current|opName|电流^电压
export const getPayToken = 'http://192.168.199.237:8001/submit/MESgetToken.ashx' // token地址
const service = axios.create({
baseURL: window.dt_Config.serverAddress,
// baseURL: 'http://localhost:8402/submit/MESCommonBase.ashx',
// baseURL: 'http://localhost:8403/submit/MESCommonBase.ashx',
timeout: 1500000 // 请求超时时间
})
export default service
axios.defaults.headers.post['Content-Type'] = 'application/json'
export const ExcelDownLoad = window.dt_Config.serverAddress // 导出excel
// export const ExcelDownLoad = 'http://localhost:8402/submit/MESCommonBase.ashx' // 导出excel
// export const ExcelDownLoad = 'http://localhost:8403/submit/MESCommonBase.ashx' // 导出excel
// export const ExcelDownLoad = 'http://124.220.32.217:8001/submit/MESCommonBase.ashx' // 导出excel
export const serviceDT_Process = axios.create({
baseURL: `http://127.0.0.1:41181/api/GetPositionData`,
// baseURL: `http://192.168.192.62:41181/api/GetPositionData`,
// baseURL: `http://124.220.32.217:41181/api/GetPositionData`,
timeout: 1500000, // 请求超时间 default service,
method: 'GET'
})

264
src/utils/tool.js Normal file
View File

@@ -0,0 +1,264 @@
// 数组去重
export function arrayUnique(arr) {
arr.filter((element, index, arr) => {
return arr.indexOf(element) === index
})
}
// 数组去重,数组中值是对象
export function arrayUnique2(arr, name) {
const hash = {}
return arr.reduce(function(item, next) {
hash[next[name]] ? '' : hash[next[name]] = true && item.push(next)
return item
}, [])
}
// 时间转时间戳
export function timeToStamp(time) {
const date = new Date(time)
return date.getTime()
}
// 数组的深度拷贝
export function arrDeepCopy(arr) {
const newArr = []
for (const prop in arr) newArr[prop] = typeof arr[prop] === 'object' ? arrDeepCopy(arr[prop]) : arr[prop]
return newArr
}
// 对象的深度拷贝
export function objDeepCopy(obj) {
const newObj = {}
for (const prop in obj) newObj[prop] = typeof obj[prop] === 'object' ? objDeepCopy(obj[prop]) : obj[prop]
return newObj
}
function zeroFill(i) {
if (i >= 0 && i <= 9) {
return '0' + i
} else {
return i
}
}
// 获取当前时间
export function getNowTime() {
const date = new Date()
const month = zeroFill(date.getMonth() + 1)
const day = zeroFill(date.getDate())
const hour = zeroFill(date.getHours())
const minute = zeroFill(date.getMinutes())
const second = zeroFill(date.getSeconds())
const time = date.getFullYear() + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + second
return time
}
export function getNowTime2() {
const date = new Date()
const month = zeroFill2(date.getMonth())
const day = zeroFill(date.getDate())
const time = date.getFullYear() + '-' + month + '-' + day
return time
}
function zeroFill2(i) {
if (i >= 0 && i <= 9) {
if (i === 0) {
return '01'
} else {
return '0' + i
}
} else {
return i
}
}
// 判断类型
export function type(target) {
const ret = typeof (target)
const template = {
'[object Array]': 'array',
'[object Object]': 'object',
'[object String]': 'string - object',
'[object Number]': 'Number - object',
'[object Boolean]': 'Boolean - object'
}
if (target === null) {
return 'null'
}
if (ret === 'object') {
const str = Object.prototype.toString.call(target)
return template[str]
} else {
return ret
}
}
export function SectionToChinese(section) {
const chnNumChar = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九']
const chnUnitChar = ['', '十', '百', '千']
let strIns = ''
let chnStr = ''
let unitPos = 0
let zero = true
while (section > 0) {
const v = section % 10
if (v === 0) {
if (!zero) {
zero = true
chnStr = chnNumChar[v] + chnStr
}
} else {
zero = false
strIns = chnNumChar[v]
strIns += chnUnitChar[unitPos]
chnStr = strIns + chnStr
}
unitPos++
section = Math.floor(section / 10)
}
return chnStr
}
export function sleep(time) {
return new Promise(resolve => {
setTimeout(resolve, time)
})
}
export function formatTime(time) {
const h = parseInt(time / 60 / 60 % 24)
const m = parseInt(time / 60 % 60)
const s = parseInt(time % 60)
return h + 'H ' + m + 'M ' + s + 'S'
}
export function getDay2() {
const days = []
for (let i = 0; i <= 24 * 6; i += 24) { // 今天加上前6天
const dateItem = new Date(new Date().getTime() - i * 60 * 60 * 1000) // 使用当天时间戳减去以前的时间毫秒(小时*分*秒*毫秒)
// const y = dateItem.getFullYear() // 获取年份
let m = dateItem.getMonth() + 1 // 获取月份js月份从0开始需要+1
let d = dateItem.getDate() // 获取日期
m = addDate0(m) // 给为单数的月份补零
d = addDate0(d) // 给为单数的日期补零
const valueItem = m + '-' + d // 组合
days.push(valueItem) // 添加至数组
}
return days
}
// 给日期加0
function addDate0(time) {
if (time.toString().length === 1) {
time = '0' + time.toString()
}
return time
}
// 表示全局唯一标识符(GUID).
function GetGuid(g) {
const arr = [] // 存放32位数值的数组
if (typeof (g) === 'string') { // 如果构造函数的参数为字符串
InitByString(arr, g)
} else {
InitByOther(arr)
}
// 返回一个值,该值指示 Guid 的两个实例是否表示同一个值。
this.Equals = function(o) {
if (o && o.IsGuid) {
return this.ToString() === o.ToString()
} else {
return false
}
}
// Guid对象的标记
this.IsGuid = function() {}
// 返回 Guid 类的此实例值的 String 表示形式。
this.ToString = function(format) {
if (typeof (format) === 'string') {
if (format === 'N' || format === 'D' || format === 'B' || format === 'P') {
return ToStringWithFormat(arr, format)
} else {
return ToStringWithFormat(arr, 'D')
}
} else {
return ToStringWithFormat(arr, 'D')
}
}
// 由字符串加载
function InitByString(arr, g) {
g = g.replace(/[{()}\-]/g, '')
g = g.toLowerCase()
if (g.length !== 32 || g.search(/[^0-9,a-f]/i) !== -1) {
InitByOther(arr)
} else {
for (let i = 0; i < g.length; i++) {
arr.push(g[i])
}
}
}
// 由其他类型加载
function InitByOther(arr) {
let i = 32
while (i--) {
arr.push('0')
}
}
/*
根据所提供的格式说明符,返回此 Guid 实例值的 String 表示形式。
N 32 位: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
D 由连字符分隔的 32 位数字 xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
B 括在大括号中、由连字符分隔的 32 位数字:{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
P 括在圆括号中、由连字符分隔的 32 位数字:(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
*/
function ToStringWithFormat(arr, format) {
let str = ''
switch (format) {
case 'N':
return arr.toString().replace(/,/g, '')
case 'D':
str = arr.slice(0, 8) + '-' + arr.slice(8, 12) + '-' + arr.slice(12, 16) + '-' + arr.slice(16, 20) + '-' + arr.slice(20, 32)
str = str.replace(/,/g, '')
return str
case 'B':
str = ToStringWithFormat(arr, 'D')
str = '{' + str + '}'
return str
case 'P':
str = ToStringWithFormat(arr, 'D')
str = '(' + str + ')'
return str
default:
return new Guid()
}
}
}
// Guid 类的默认实例,其值保证均为零。
GetGuid.Empty = new GetGuid()
/**
* @param format N D B P
* @returns {string}
* @constructor
*/
export function Guid(format = 'D') {
let g = ''
let i = 32
while (i--) {
g += Math.floor(Math.random() * 16.0).toString(16)
}
return new GetGuid(g).ToString(format)
}

32
src/utils/validate.js Normal file
View File

@@ -0,0 +1,32 @@
/**
* Created by jiachenpan on 16/11/18.
*/
export function isvalidUsername(str) {
const user = /^[0-9]{4,5}$/
return user.test(str)
}
/* 合法uri*/
export function validateURL(textval) {
const urlregex = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/
return urlregex.test(textval)
}
/* 小写字母*/
export function validateLowerCase(str) {
const reg = /^[a-z]+$/
return reg.test(str)
}
/* 大写字母*/
export function validateUpperCase(str) {
const reg = /^[A-Z]+$/
return reg.test(str)
}
/* 大小写字母*/
export function validatAlphabets(str) {
const reg = /^[A-Za-z]+$/
return reg.test(str)
}

179
src/vendor/Blob.js vendored Normal file
View File

@@ -0,0 +1,179 @@
/* eslint-disable */
/* Blob.js
* A Blob implementation.
* 2014-05-27
*
* By Eli Grey, http://eligrey.com
* By Devin Samarin, https://github.com/eboyjr
* License: X11/MIT
* See LICENSE.md
*/
/*global self, unescape */
/*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true,
plusplus: true */
/*! @source http://purl.eligrey.com/github/Blob.js/blob/master/Blob.js */
(function (view) {
"use strict";
view.URL = view.URL || view.webkitURL;
if (view.Blob && view.URL) {
try {
new Blob;
return;
} catch (e) {}
}
// Internally we use a BlobBuilder implementation to base Blob off of
// in order to support older browsers that only have BlobBuilder
var BlobBuilder = view.BlobBuilder || view.WebKitBlobBuilder || view.MozBlobBuilder || (function(view) {
var
get_class = function(object) {
return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1];
}
, FakeBlobBuilder = function BlobBuilder() {
this.data = [];
}
, FakeBlob = function Blob(data, type, encoding) {
this.data = data;
this.size = data.length;
this.type = type;
this.encoding = encoding;
}
, FBB_proto = FakeBlobBuilder.prototype
, FB_proto = FakeBlob.prototype
, FileReaderSync = view.FileReaderSync
, FileException = function(type) {
this.code = this[this.name = type];
}
, file_ex_codes = (
"NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR "
+ "NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR"
).split(" ")
, file_ex_code = file_ex_codes.length
, real_URL = view.URL || view.webkitURL || view
, real_create_object_URL = real_URL.createObjectURL
, real_revoke_object_URL = real_URL.revokeObjectURL
, URL = real_URL
, btoa = view.btoa
, atob = view.atob
, ArrayBuffer = view.ArrayBuffer
, Uint8Array = view.Uint8Array
;
FakeBlob.fake = FB_proto.fake = true;
while (file_ex_code--) {
FileException.prototype[file_ex_codes[file_ex_code]] = file_ex_code + 1;
}
if (!real_URL.createObjectURL) {
URL = view.URL = {};
}
URL.createObjectURL = function(blob) {
var
type = blob.type
, data_URI_header
;
if (type === null) {
type = "application/octet-stream";
}
if (blob instanceof FakeBlob) {
data_URI_header = "data:" + type;
if (blob.encoding === "base64") {
return data_URI_header + ";base64," + blob.data;
} else if (blob.encoding === "URI") {
return data_URI_header + "," + decodeURIComponent(blob.data);
} if (btoa) {
return data_URI_header + ";base64," + btoa(blob.data);
} else {
return data_URI_header + "," + encodeURIComponent(blob.data);
}
} else if (real_create_object_URL) {
return real_create_object_URL.call(real_URL, blob);
}
};
URL.revokeObjectURL = function(object_URL) {
if (object_URL.substring(0, 5) !== "data:" && real_revoke_object_URL) {
real_revoke_object_URL.call(real_URL, object_URL);
}
};
FBB_proto.append = function(data/*, endings*/) {
var bb = this.data;
// decode data to a binary string
if (Uint8Array && (data instanceof ArrayBuffer || data instanceof Uint8Array)) {
var
str = ""
, buf = new Uint8Array(data)
, i = 0
, buf_len = buf.length
;
for (; i < buf_len; i++) {
str += String.fromCharCode(buf[i]);
}
bb.push(str);
} else if (get_class(data) === "Blob" || get_class(data) === "File") {
if (FileReaderSync) {
var fr = new FileReaderSync;
bb.push(fr.readAsBinaryString(data));
} else {
// async FileReader won't work as BlobBuilder is sync
throw new FileException("NOT_READABLE_ERR");
}
} else if (data instanceof FakeBlob) {
if (data.encoding === "base64" && atob) {
bb.push(atob(data.data));
} else if (data.encoding === "URI") {
bb.push(decodeURIComponent(data.data));
} else if (data.encoding === "raw") {
bb.push(data.data);
}
} else {
if (typeof data !== "string") {
data += ""; // convert unsupported types to strings
}
// decode UTF-16 to binary string
bb.push(unescape(encodeURIComponent(data)));
}
};
FBB_proto.getBlob = function(type) {
if (!arguments.length) {
type = null;
}
return new FakeBlob(this.data.join(""), type, "raw");
};
FBB_proto.toString = function() {
return "[object BlobBuilder]";
};
FB_proto.slice = function(start, end, type) {
var args = arguments.length;
if (args < 3) {
type = null;
}
return new FakeBlob(
this.data.slice(start, args > 1 ? end : this.data.length)
, type
, this.encoding
);
};
FB_proto.toString = function() {
return "[object Blob]";
};
FB_proto.close = function() {
this.size = this.data.length = 0;
};
return FakeBlobBuilder;
}(view));
view.Blob = function Blob(blobParts, options) {
var type = options ? (options.type || "") : "";
var builder = new BlobBuilder();
if (blobParts) {
for (var i = 0, len = blobParts.length; i < len; i++) {
builder.append(blobParts[i]);
}
}
return builder.getBlob(type);
};
}(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this.content || this));

224
src/vendor/Export2Excel.js vendored Normal file
View File

@@ -0,0 +1,224 @@
/* eslint-disable */
require('script-loader!file-saver');
// import XLSX from 'xlsx'
import XLSX from 'xlsx-style'
function generateArray(table) {
var out = [];
var rows = table.querySelectorAll('tr');
var ranges = [];
for (var R = 0; R < rows.length; ++R) {
var outRow = [];
var row = rows[R];
var columns = row.querySelectorAll('td');
for (var C = 0; C < columns.length; ++C) {
var cell = columns[C];
var colspan = cell.getAttribute('colspan');
var rowspan = cell.getAttribute('rowspan');
var cellValue = cell.innerText;
if (cellValue !== "" && cellValue == +cellValue) cellValue = +cellValue;
//Skip ranges
ranges.forEach(function (range) {
if (R >= range.s.r && R <= range.e.r && outRow.length >= range.s.c && outRow.length <= range.e.c) {
for (var i = 0; i <= range.e.c - range.s.c; ++i) outRow.push(null);
}
});
//Handle Row Span
if (rowspan || colspan) {
rowspan = rowspan || 1;
colspan = colspan || 1;
ranges.push({
s: {
r: R,
c: outRow.length
},
e: {
r: R + rowspan - 1,
c: outRow.length + colspan - 1
}
});
};
//Handle Value
outRow.push(cellValue !== "" ? cellValue : null);
//Handle Colspan
if (colspan)
for (var k = 0; k < colspan - 1; ++k) outRow.push(null);
}
out.push(outRow);
}
return [out, ranges];
};
function datenum(v, date1904) {
if (date1904) v += 1462;
var epoch = Date.parse(v);
return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
}
function sheet_from_array_of_arrays(data, opts) {
var ws = {};
var range = {
s: {
c: 10000000,
r: 10000000
},
e: {
c: 0,
r: 0
}
};
for (var R = 0; R != data.length; ++R) {
for (var C = 0; C != data[R].length; ++C) {
if (range.s.r > R) range.s.r = R;
if (range.s.c > C) range.s.c = C;
if (range.e.r < R) range.e.r = R;
if (range.e.c < C) range.e.c = C;
var cell = {
v: data[R][C]
};
if (cell.v == null) continue;
var cell_ref = XLSX.utils.encode_cell({
c: C,
r: R
});
if (typeof cell.v === 'number') cell.t = 'n';
else if (typeof cell.v === 'boolean') cell.t = 'b';
else if (cell.v instanceof Date) {
cell.t = 'n';
cell.z = XLSX.SSF._table[14];
cell.v = datenum(cell.v);
} else cell.t = 's';
ws[cell_ref] = cell;
}
}
if (range.s.c < 10000000) ws['!ref'] = XLSX.utils.encode_range(range);
return ws;
}
function Workbook() {
if (!(this instanceof Workbook)) return new Workbook();
this.SheetNames = [];
this.Sheets = {};
}
function s2ab(s) {
var buf = new ArrayBuffer(s.length);
var view = new Uint8Array(buf);
for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
return buf;
}
export function export_table_to_excel(id) {
var theTable = document.getElementById(id);
var oo = generateArray(theTable);
var ranges = oo[1];
/* original data */
var data = oo[0];
var ws_name = "SheetJS";
var wb = new Workbook(),
ws = sheet_from_array_of_arrays(data);
/* add ranges to worksheet */
// ws['!cols'] = ['apple', 'banan'];
ws['!merges'] = ranges;
/* add worksheet to workbook */
wb.SheetNames.push(ws_name);
wb.Sheets[ws_name] = ws;
var wbout = XLSX.write(wb, {
bookType: 'xlsx',
bookSST: false,
type: 'binary'
});
saveAs(new Blob([s2ab(wbout)], {
type: "application/octet-stream"
}), "test.xlsx")
}
export function export_json_to_excel({
headerGroup,
dataGroup,
sheetGroup,
filename,
autoWidth = true,
bookType= 'xlsx'
} = {}) {
var wb = new Workbook()
for (let i = 0; i < dataGroup.length; i++) {
/* original data */
let data = dataGroup[i]
filename = filename || 'excel-list'
data = [...data]
data.unshift(headerGroup[i]);
var ws_name = sheetGroup[i];
var ws = sheet_from_array_of_arrays(data);
if (autoWidth) {
/*设置worksheet每列的最大宽度*/
const colWidth = data.map(row => row.map(val => {
/*先判断是否为null/undefined*/
if (val == null) {
return {
'wch': 10
};
}
/*再判断是否为中文*/
else if (val.toString().charCodeAt(0) > 255) {
return {
'wch': val.toString().length * 2
};
} else {
return {
'wch': val.toString().length
};
}
}))
/*以第一行为初始值*/
let result = colWidth[0];
for (let i = 1; i < colWidth.length; i++) {
for (let j = 0; j < colWidth[i].length; j++) {
if (result[j]['wch'] < colWidth[i][j]['wch']) {
result[j]['wch'] = colWidth[i][j]['wch'];
}
}
}
ws['!cols'] = result;
}
let R = 0;
data.map(item => {
let C = 0;
item.map(itm => {
var cell_ref = XLSX.utils.encode_cell({c:C,r:R});
var cell = {v: itm }
cell.s= {
alignment: {
horizontal: "center"
}
}
ws[cell_ref] = cell;
C++;
})
R++;
})
/* add worksheet to workbook */
wb.SheetNames.push(ws_name);
wb.Sheets[ws_name] = ws;
}
var wbout = XLSX.write(wb, {
bookType: bookType,
bookSST: false,
type: 'binary'
});
saveAs(new Blob([s2ab(wbout)], {
type: "application/octet-stream"
}), `${filename}.${bookType}`);
}

1443
src/vendor/Export2Excel1.js vendored Normal file

File diff suppressed because it is too large Load Diff

1445
src/vendor/Export2Excel2.js vendored Normal file

File diff suppressed because it is too large Load Diff

206
src/vendor/Export2Excelcjn.js vendored Normal file
View File

@@ -0,0 +1,206 @@
/* eslint-disable */
require('script-loader!file-saver');
import XLSX from 'xlsx'
function generateArray(table) {
var out = [];
var rows = table.querySelectorAll('tr');
var ranges = [];
for (var R = 0; R < rows.length; ++R) {
var outRow = [];
var row = rows[R];
var columns = row.querySelectorAll('td');
for (var C = 0; C < columns.length; ++C) {
var cell = columns[C];
var colspan = cell.getAttribute('colspan');
var rowspan = cell.getAttribute('rowspan');
var cellValue = cell.innerText;
if (cellValue !== "" && cellValue == +cellValue) cellValue = +cellValue;
//Skip ranges
ranges.forEach(function (range) {
if (R >= range.s.r && R <= range.e.r && outRow.length >= range.s.c && outRow.length <= range.e.c) {
for (var i = 0; i <= range.e.c - range.s.c; ++i) outRow.push(null);
}
});
//Handle Row Span
if (rowspan || colspan) {
rowspan = rowspan || 1;
colspan = colspan || 1;
ranges.push({
s: {
r: R,
c: outRow.length
},
e: {
r: R + rowspan - 1,
c: outRow.length + colspan - 1
}
});
};
//Handle Value
outRow.push(cellValue !== "" ? cellValue : null);
//Handle Colspan
if (colspan)
for (var k = 0; k < colspan - 1; ++k) outRow.push(null);
}
out.push(outRow);
}
return [out, ranges];
};
function datenum(v, date1904) {
if (date1904) v += 1462;
var epoch = Date.parse(v);
return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
}
function sheet_from_array_of_arrays(data, opts) {
var ws = {};
var range = {
s: {
c: 10000000,
r: 10000000
},
e: {
c: 0,
r: 0
}
};
for (var R = 0; R != data.length; ++R) {
for (var C = 0; C != data[R].length; ++C) {
if (range.s.r > R) range.s.r = R;
if (range.s.c > C) range.s.c = C;
if (range.e.r < R) range.e.r = R;
if (range.e.c < C) range.e.c = C;
var cell = {
v: data[R][C]
};
if (cell.v == null) continue;
var cell_ref = XLSX.utils.encode_cell({
c: C,
r: R
});
if (typeof cell.v === 'number') cell.t = 'n';
else if (typeof cell.v === 'boolean') cell.t = 'b';
else if (cell.v instanceof Date) {
cell.t = 'n';
cell.z = XLSX.SSF._table[14];
cell.v = datenum(cell.v);
} else cell.t = 's';
ws[cell_ref] = cell;
}
}
if (range.s.c < 10000000) ws['!ref'] = XLSX.utils.encode_range(range);
return ws;
}
function Workbook() {
if (!(this instanceof Workbook)) return new Workbook();
this.SheetNames = [];
this.Sheets = {};
}
function s2ab(s) {
var buf = new ArrayBuffer(s.length);
var view = new Uint8Array(buf);
for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
return buf;
}
export function export_table_to_excel(id) {
var theTable = document.getElementById(id);
var oo = generateArray(theTable);
var ranges = oo[1];
/* original data */
var data = oo[0];
var ws_name = "SheetJS";
var wb = new Workbook(),
ws = sheet_from_array_of_arrays(data);
/* add ranges to worksheet */
// ws['!cols'] = ['apple', 'banan'];
ws['!merges'] = ranges;
/* add worksheet to workbook */
wb.SheetNames.push(ws_name);
wb.Sheets[ws_name] = ws;
var wbout = XLSX.write(wb, {
bookType: 'xlsx',
bookSST: false,
type: 'binary'
});
saveAs(new Blob([s2ab(wbout)], {
type: "application/octet-stream"
}), "test.xlsx")
}
export function export_json_to_excel({
header,
data,
filename,
autoWidth = true,
bookType= 'xlsx'
} = {}) {
/* original data */
filename = filename || 'excel-list'
data = [...data]
data.unshift(header);
var ws_name = filename || 'excel-list';
var wb = new Workbook(),
ws = sheet_from_array_of_arrays(data);
if (autoWidth) {
/*设置worksheet每列的最大宽度*/
const colWidth = data.map(row => row.map(val => {
/*先判断是否为null/undefined*/
if (val == null) {
return {
'wch': 10
};
}
/*再判断是否为中文*/
else if (val.toString().charCodeAt(0) > 255) {
return {
'wch': val.toString().length * 2
};
} else {
return {
'wch': val.toString().length
};
}
}))
/*以第一行为初始值*/
let result = colWidth[0];
for (let i = 1; i < colWidth.length; i++) {
for (let j = 0; j < colWidth[i].length; j++) {
if (result[j]['wch'] < colWidth[i][j]['wch']) {
result[j]['wch'] = colWidth[i][j]['wch'];
}
}
}
ws['!cols'] = result;
}
/* add worksheet to workbook */
wb.SheetNames.push(ws_name);
wb.Sheets[ws_name] = ws;
var wbout = XLSX.write(wb, {
bookType: bookType,
bookSST: false,
type: 'binary'
});
saveAs(new Blob([s2ab(wbout)], {
type: "application/octet-stream"
}), `${filename}.${bookType}`);
}

0
src/vendor/_system~.ini vendored Normal file
View File

1322
src/vendor/cpexcel.js vendored Normal file

File diff suppressed because it is too large Load Diff

19
src/vendor/exportExcel.js vendored Normal file
View File

@@ -0,0 +1,19 @@
// 导出Excel方法表格id不加扩展名的文件名sheet名
export function exportExcelMethod(tableId, fileName, sheetName) {
tableToExcel(tableId, fileName, sheetName)
}
const tableToExcel = (function() {
const uri = 'data:application/vnd.ms-excel;base64,'
// 设置导出表格的单元格默认高度/宽度/边框样式/字体颜色/背景颜色/居中网页显示表格宽度建议1240tr/td视情况而定
const template = `<html xmlns:x="urn:schemas-microsoft-com:office:excel"><head><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Name>{worksheet}</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml><meta charset="UTF-8"><style type="text/css">table td {border: 1px solid #000000;width:100px;text-align: center;color: #000000;}</style></head><body><table>{table}</table></body></html>`
const base64 = function(s) { return window.btoa(unescape(encodeURIComponent(s))) }
const format = function(s, c) { return s.replace(/{(\w+)}/g, function(m, p) { return c[p] }) }
return function(table, filename, sheetname) {
if (!table.nodeType) table = document.getElementById(table)
const ctx = { worksheet: sheetname || 'Worksheet', table: table.innerHTML }
const aTag = document.createElement('a')
aTag.href = uri + base64(format(template, ctx))
aTag.download = filename
aTag.click()
}
})()

35
src/vendor/htmlToPdf.js vendored Normal file
View File

@@ -0,0 +1,35 @@
import html2Canvas from 'html2canvas'
import JsPDF from 'jspdf'
export default {
install(Vue, options) {
Vue.prototype.getPdf = function(id, title) {
html2Canvas(document.querySelector(`#${id}`), {
allowTaint: true
}).then(function(canvas) {
const contentWidth = canvas.width
const contentHeight = canvas.height
const pageHeight = contentWidth / 592.28 * 841.89
let leftHeight = contentHeight
let position = 0
const imgWidth = 595.28
const imgHeight = 592.28 / contentWidth * contentHeight
const pageData = canvas.toDataURL('image/jpeg', 1.0)
const PDF = new JsPDF('', 'pt', 'a4')
if (leftHeight < pageHeight) {
PDF.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight)
} else {
while (leftHeight > 0) {
PDF.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
leftHeight -= pageHeight
position -= 841.89
if (leftHeight > 0) {
PDF.addPage()
}
}
}
PDF.save(title + '.pdf')
}
)
}
}
}

85
src/vendor/int2Chinese.js vendored Normal file
View File

@@ -0,0 +1,85 @@
export function convertCurrency(money) {
// 汉字的数字
const cnNums = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']
// 基本单位
const cnIntRadice = ['', '拾', '佰', '仟']
// 对应整数部分扩展单位
const cnIntUnits = ['', '万', '亿', '兆']
// 对应小数部分单位
const cnDecUnits = ['角', '分', '毫', '厘']
// 整数金额时后面跟的字符
const cnInteger = '整'
// 整型完以后的单位
const cnIntLast = '元'
// 最大处理的数字
const maxNum = 999999999999999.9999
// 金额整数部分
let integerNum
// 金额小数部分
let decimalNum
// 输出的中文金额字符串
let chineseStr = ''
// 分离金额后用的数组,预定义
let parts
if (money === '') { return '' }
money = parseFloat(money)
if (money >= maxNum) {
// 超出最大处理数字
return ''
}
if (money === 0) {
chineseStr = cnNums[0] + cnIntLast + cnInteger
return chineseStr
}
// 转换为字符串
money = money.toString()
if (money.indexOf('.') === -1) {
integerNum = money
decimalNum = ''
} else {
parts = money.split('.')
integerNum = parts[0]
decimalNum = parts[1].substr(0, 4)
}
// 获取整型部分转换
if (parseInt(integerNum, 10) > 0) {
let zeroCount = 0
const IntLen = integerNum.length
for (let i = 0; i < IntLen; i++) {
const n = integerNum.substr(i, 1)
const p = IntLen - i - 1
const q = p / 4
const m = p % 4
if (n === '0') {
zeroCount++
} else {
if (zeroCount > 0) {
chineseStr += cnNums[0]
}
// 归零
zeroCount = 0
chineseStr += cnNums[parseInt(n)] + cnIntRadice[m]
}
if (m === 0 && zeroCount < 4) {
chineseStr += cnIntUnits[q]
}
}
chineseStr += cnIntLast
}
// 小数部分
if (decimalNum !== '') {
const decLen = decimalNum.length
for (let i = 0; i < decLen; i++) {
const n = decimalNum.substr(i, 1)
if (n !== '0') {
chineseStr += cnNums[Number(n)] + cnDecUnits[i]
}
}
}
if (chineseStr === '') {
chineseStr += cnNums[0] + cnIntLast + cnInteger
} else if (decimalNum === '') {
chineseStr += cnInteger
}
return chineseStr
}

117
src/vendor/print.js vendored Normal file
View File

@@ -0,0 +1,117 @@
/* eslint-disable */
let Print = function(dom, options) {
if (!(this instanceof Print)) return new Print(dom, options)
this.options = this.extend({
'noPrint': '.no-print'
}, options)
if ((typeof dom) === 'string') {
this.dom = document.querySelector(dom)
} else {
this.dom = dom
}
this.init()
}
Print.prototype = {
init: function() {
let content = this.getStyle() + this.getHtml()
this.writeIframe(content)
},
extend: function(obj, obj2) {
for (let k in obj2) {
obj[k] = obj2[k]
}
return obj
},
getStyle: function() {
let str = '',
styles = document.querySelectorAll('style,link')
for (let i = 0; i < styles.length; i++) {
str += styles[i].outerHTML
}
str += '<style>' + (this.options.noPrint ? this.options.noPrint : '.no-print') + '{display:none}</style>'
return str
},
getHtml: function() {
let inputs = document.querySelectorAll('input')
let textareas = document.querySelectorAll('textarea')
let selects = document.querySelectorAll('select')
for (let k in inputs) {
if (inputs[k].type === 'checkbox' || inputs[k].type === 'radio') {
if (inputs[k].checked === true) {
inputs[k].setAttribute('checked', 'checked')
} else {
inputs[k].removeAttribute('checked')
}
} else if (inputs[k].type === 'text') {
inputs[k].setAttribute('value', inputs[k].value)
}
}
for (let k2 in textareas) {
if (textareas[k2].type === 'textarea') {
textareas[k2].innerHTML = textareas[k2].value
}
}
for (let k3 in selects) {
if (selects[k3].type === 'select-one') {
let child = selects[k3].children
for (let i in child) {
if (child[i].tagName === 'OPTION') {
if (child[i].selected === true) {
child[i].setAttribute('selected', 'selected')
} else {
child[i].removeAttribute('selected')
}
}
}
}
}
return this.dom.outerHTML
},
writeIframe: function(content) {
let w, doc, iframe = document.createElement('iframe'),
f = document.body.appendChild(iframe)
iframe.id = 'myIframe'
iframe.style = 'position:absolutewidth:0height:0top:-10pxleft:-10px'
w = f.contentWindow || f.contentDocument
doc = f.contentDocument || f.contentWindow.document
doc.open()
doc.write(content)
doc.close()
this.toPrint(w)
setTimeout(function() {
document.body.removeChild(iframe)
}, 100)
},
toPrint: function(frameWindow) {
try {
setTimeout(function() {
frameWindow.focus()
try {
if (!frameWindow.document.execCommand('print', false, null)) {
frameWindow.print()
}
} catch (e) {
frameWindow.print()
}
frameWindow.close()
}, 10)
} catch (err) {
console.log('err', err)
}
}
}
export default Print

3027
src/views/DaLuJia.vue Normal file

File diff suppressed because it is too large Load Diff

320
src/views/page/QX_EMS.vue Normal file
View File

@@ -0,0 +1,320 @@
<template>
<div>
<el-card>
<el-col :span="7">
<div class="show-text">动作节拍设定</div>
<el-input v-model="TagName" clearable style="width: 280px;margin-right: 26px" placeholder="请输入动作名称"/>
<el-button :disabled="loading" icon="el-icon-search" type="primary" @click="searchTable()">查询</el-button>
<el-table
v-loading="loading"
:data="tableData"
:header-row-style= "{fontSize: '18px',fontFamily:'MiSans Demibold',height: '64px',backgroundColor:'#fff'}"
:row-style="{fontSize: '16px',fontFamily:'MiSans Regular',height: '64px'}"
element-loading-text="数据加载中"
element-loading-spinner="el-icon-loading"
element-loading-background="rgba(0, 0, 0, 0.2)"
tooltip-effect="dark"
style="width: 100%"
height="875"
border
size="mini"
@row-click="table1RowClick">
<el-table-column type="index" label=" " align="center" width="80"/>
<el-table-column align="center" label="设备动作">
<template slot-scope="scope">
{{ scope.row.名称 }}
</template>
</el-table-column>
<el-table-column align="center" label="节拍(s)" >
<template slot-scope="scope">
<el-input-number v-model="scope.row.节拍" :min="0" :step="1" @change="setBeat(scope.row)"></el-input-number>
</template>
</el-table-column>
</el-table>
</el-col>
<el-col :span="17">
<div class="show-text">零部件寿命预测设定</div>
<el-row>
<el-col :span="16">
<el-table
v-loading="loading"
:data="tableData1"
:header-row-style= "{fontSize: '18px',fontFamily:'MiSans Demibold',height: '64px',backgroundColor:'#fff'}"
:row-style="{fontSize: '16px',fontFamily:'MiSans Regular',height: '64px'}"
element-loading-text="数据加载中"
element-loading-spinner="el-icon-loading"
element-loading-background="rgba(0, 0, 0, 0.2)"
tooltip-effect="dark"
style="width: 100%"
height="330"
border
size="mini"
@row-click="table2RowClick">
<el-table-column type="index" label=" " align="center" width="60"/>
<el-table-column align="center" label="部件名称">
<template slot-scope="scope">
{{ scope.row.部件名称 }}
</template>
</el-table-column>
<el-table-column align="center" label="额定(H)" width="120">
<template slot-scope="scope">
{{ scope.row.更换时间 }}
</template>
</el-table-column>
<el-table-column align="center" label="已用(H)" width="120">
<template slot-scope="scope">
{{ scope.row.报警时间 }}
</template>
</el-table-column>
<el-table-column align="center" label="上次更换" width="200">
<template slot-scope="scope">
{{ scope.row.上次维修时间 }}
</template>
</el-table-column>
<el-table-column align="center" label="更换/看板展示">
<template slot-scope="scope">
<el-button v-if="scope.row['是否展示']" type="text" icon="el-icon-s-flag" style="color: #00893d"></el-button>
<el-button size="mini" type="warning" @click="updateDeviceInfo(scope.row)">更换</el-button>
</template>
</el-table-column>
</el-table>
</el-col>
<el-col :span="8">
<el-row>
<el-table
v-loading="loading"
:data="tableData2"
:header-row-style= "{fontSize: '18px',fontFamily:'MiSans Demibold',height: '64px',backgroundColor:'#fff'}"
:row-style="{fontSize: '16px',fontFamily:'MiSans Regular',height: '64px'}"
element-loading-text="数据加载中"
element-loading-spinner="el-icon-loading"
element-loading-background="rgba(0, 0, 0, 0.2)"
tooltip-effect="dark"
style="width: 100%"
height="330"
border
size="mini">
<el-table-column align="center" label="关联动作">
<template slot-scope="scope">
{{ scope.row.名称 }}
</template>
</el-table-column>
<el-table-column align="center" label="操作" width="100">
<template slot-scope="scope">
<el-button type="text" icon="el-icon-delete" @click="UnlinkDeviceTagId(scope.row)" style="color: #ff0000"></el-button>
</template>
</el-table-column>
</el-table>
</el-row>
</el-col>
</el-row>
<el-row>
<span style="margin-left: 20px">动作</span>
<el-input v-model="TagNameDongZuo" readonly style="width: 280px;margin-right: 26px" placeholder="请选择关联动作"/>
<span>部件</span>
<el-input v-model="TagNameBuJian" readonly style="width: 280px;margin-right: 26px" placeholder="请选择部件"/>
<el-button icon="el-icon-link" type="warning" @click="linkDeviceTagId()">关联</el-button>
</el-row>
</el-col>
</el-card>
<el-dialog :visible.sync="dialogFormVisible1" :append-to-body="true" title="编辑部件信息" center width="440px">
<el-form ref="form" :model="form" label-position="right" label-width="100px">
<el-form-item label="部件名称" prop="部件名称">
<el-input v-model="form.部件名称" readonly style="width: 240px" />
</el-form-item>
<el-form-item label="额定时间(H)" prop="planData">
<el-input-number v-model="form.更换时间" style="width: 240px;border-radius: 4px" :min="0" :step="1" />
</el-form-item>
<el-form-item label="上次更换时间" prop="planData">
<el-date-picker type="datetime" v-model="form.上次维修时间" :clearable="false" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" />
</el-form-item>
<el-form-item label="是否展示" prop="planData">
<el-checkbox v-model="form.是否展示"></el-checkbox>
</el-form-item>
<el-row>
<el-form-item >
<el-button style="width: 80px;height: 40px" type="primary" @click="submitAdd1('form')"> </el-button>
<el-button style="width: 80px;height: 40px" @click="callOff1('form')">取消</el-button>
</el-form-item>
</el-row>
</el-form>
</el-dialog>
</div>
</template>
<script>
export default {
data() {
return {
TagName: '',
TagNameBuJian: '',
TagNameBuJianID: '',
TagNameDongZuo: '',
TagNameDongZuoID: '',
collectionTime: [],
tableDataExcel: [],
loading: false,
tableData: [],
tableData1: [],
tableData2: [],
dialogFormVisible1: false,
form: {
部件代码: '',
部件名称: '',
更换时间: '',
上次维修时间: '',
是否展示: ''
},
total: 0, // 总条数
pageSize: 50, // 每页显示条数
pageList: 1 // 后台获取页
}
},
created() {
this.searchTable()
this.searchTable1()
},
methods: {
// 查询
searchTable() {
this.loading = true
this.tableData = []
var param = []
param[0] = ['动作名称', this.TagName]
var Data = this.CreateData('11', '部件寿命_动作节拍_查询', param)
this.ExecDatabase(Data).then(response => {
if (response.data.length !== 0) {
this.tableData = response.data
}
this.loading = false
})
},
// 查询
searchTable1() {
this.tableData1 = []
var param = []
var Data = this.CreateData('11', '部件寿命_部件_查询', param)
this.ExecDatabase(Data).then(response => {
if (response.data.length !== 0) {
this.tableData1 = response.data
}
})
},
// 查询
table2RowClick(row) {
this.TagNameBuJian = row['部件名称']
this.TagNameBuJianID = row['部件代码']
this.tableData2 = []
var param = []
param[0] = ['部件代码', row['部件代码']]
var Data = this.CreateData('11', '部件寿命_部件动作_查询', param)
this.ExecDatabase(Data).then(response => {
if (response.data.length !== 0) {
this.tableData2 = response.data
}
})
},
table1RowClick(row) {
this.TagNameDongZuo = row['名称']
this.TagNameDongZuoID = row['TagID']
},
// 查询
searchTable2() {
this.tableData1 = []
var param = []
var Data = this.CreateData('11', '部件寿命_部件_查询', param)
this.ExecDatabase(Data).then(response => {
if (response.data.length !== 0) {
this.tableData1 = response.data
}
})
},
linkDeviceTagId() {
var param = []
if (this.TagNameBuJianID === '' || this.TagNameDongZuoID === '') {
this.$message.warning('请选择部件和关联动作!')
return
}
param[0] = ['部件代码', this.TagNameBuJianID]
param[1] = ['TagID', this.TagNameDongZuoID]
var Data = this.CreateData('11', '部件寿命_部件动作_绑定', param)
this.ExecDatabase(Data).then(response => {
this.$message.success('关联成功!')
this.table2RowClick({
部件名称: this.TagNameBuJian,
部件代码: this.TagNameBuJianID
})
})
},
UnlinkDeviceTagId(row) {
var param = []
param[0] = ['部件代码', row.部件代码]
param[1] = ['TagID', row.tagID]
var Data = this.CreateData('11', '部件寿命_部件动作_解除绑定', param)
this.ExecDatabase(Data).then(response => {
this.$message.success('解除成功!')
this.table2RowClick({
部件名称: this.TagNameBuJian,
部件代码: this.TagNameBuJianID
})
this.TagNameDongZuoID = ''
this.TagNameDongZuo = ''
})
},
setBeat(row) {
var param = []
param[0] = ['节拍', row.节拍]
param[1] = ['TagID', row.TagID]
var Data = this.CreateData('11', '部件寿命_部件动作节拍_设定', param)
this.ExecDatabase(Data).then(response => {
this.$message.success('设定成功!')
})
},
updateDeviceInfo(row) {
this.form.部件代码 = row['部件代码']
this.form.是否展示 = row['是否展示']
this.form.部件名称 = row['部件名称']
this.form.更换时间 = row['更换时间']
this.form.上次维修时间 = row['上次维修时间']
this.dialogFormVisible1 = true
},
submitAdd1() {
var param = []
param[0] = ['部件代码', this.form.部件代码]
param[1] = ['更换时间', this.form.更换时间]
param[2] = ['上次维修时间', this.form.上次维修时间]
param[3] = ['是否展示', this.form.是否展示]
var Data = this.CreateData('12', '部件寿命_部件_更换', param)
this.ExecDatabase(Data).then(response => {
if (response.data[0].result === '1') {
this.$message.success('编辑成功')
this.searchTable1()
this.dialogFormVisible1 = false
} else {
this.$message.error('编辑失败')
}
})
},
callOff1() {},
// 分页
handleSizeChange(val) {
this.pageList = 1
this.pageSize = val
this.searchTable()
},
handleCurrentChange(val) {
this.pageList = val
this.searchTable()
}
}
}
</script>
<style>
.show-text {
font-family: "MiSans Regular",serif ;
margin-right: 20px;
font-size: 20px;
color: #595959;
}
</style>

160
src/views/page/QX_part.vue Normal file
View File

@@ -0,0 +1,160 @@
<template>
<div>
<el-card>
<span class="show-text">二维码信息:</span>
<el-input v-model="TagName" clearable style="width: 280px;margin-right: 26px" placeholder="请输入二维码信息"/>
<span class="show-text">扫描时间:</span>
<el-date-picker
v-model="collectionTime"
:clearable="false"
popper-class="virtual-cell-time-picker"
value-format="yyyy-MM-dd HH:mm:ss"
format="yyyy-MM-dd HH:mm:ss"
type="datetimerange"
range-separator="-"
style="width: 360px;margin-right: 16px;vertical-align: top"
start-placeholder="开始时间"
end-placeholder="结束时间" />
<el-button :disabled="loading" icon="el-icon-search" type="primary" @click="searchTable()">查询</el-button>
<el-button style="margin-left: 14px" type="warning" icon="el-icon-download" @click="searchTableALL()">导出</el-button>
<div style="margin-top: 26px">
<el-table
v-loading="loading"
:data="tableData"
:header-row-style= "{fontSize: '18px',fontFamily:'MiSans Demibold',height: '64px',backgroundColor:'#fff'}"
:row-style="{fontSize: '16px',fontFamily:'MiSans Regular',height: '64px'}"
element-loading-text="数据加载中"
element-loading-spinner="el-icon-loading"
element-loading-background="rgba(0, 0, 0, 0.2)"
tooltip-effect="dark"
style="width: 100%"
height="788"
border
size="mini">
<el-table-column type="index" label=" " align="center" width="100"/>
<el-table-column align="center" label="工件类型">
<template slot-scope="scope">
{{ scope.row.TypeName }}
</template>
</el-table-column>
<el-table-column align="center" label="二维码信息">
<template slot-scope="scope">
{{ scope.row.PartNum }}
</template>
</el-table-column>
<el-table-column align="center" label="扫描时间">
<template slot-scope="scope">
{{ scope.row.ScanTime }}
</template>
</el-table-column>
</el-table>
<div class="block" style="margin-top: 32px;">
<el-pagination
v-if="!loading"
:current-page="pageList"
:page-sizes="[50, 100, 200, 300]"
:page-size="pageSize"
:total="total"
background
layout="total, sizes, prev, pager, next, jumper"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"/>
</div>
</div>
</el-card>
</div>
</template>
<script>
export default {
data() {
return {
TagName: '',
collectionTime: [],
tableDataExcel: [],
loading: false,
tableData: [],
total: 0, // 总条数
pageSize: 50, // 每页显示条数
pageList: 1 // 后台获取页
}
},
created() {
},
methods: {
// 查询
searchTable() {
if (this.collectionTime.length === 0) {
this.$message.error('请选择需要查询的时间段!')
return
}
this.loading = true
this.tableData = []
var param = []
param[0] = ['PartNum', this.TagName]
param[1] = ['开始时间', this.collectionTime[0]]
param[2] = ['结束时间', this.collectionTime[1]]
param[3] = ['PageCurrent', this.pageList]
param[4] = ['PageSize', this.pageSize]
param[5] = ['PageCount', '1111', 'int', '1']
param[6] = ['ItemCount', '1111', 'int', '1']
var Data = this.CreateData('11', '工件数据_查询_查询', param)
this.ExecDatabase(Data).then(response => {
if (response.data.length !== 0) {
const str = '\u0000'
for (let i = 0; i < response.data.result.length; i++) {
response.data.result[i].PartNum = response.data.result[i].PartNum.replaceAll(str, '')
this.tableData.push(response.data.result[i])
}
}
this.total = parseInt(response.data.output[0].ItemCount)
this.loading = false
})
},
// 导出数据
searchTableALL() {
if (this.collectionTime.length === 0) {
this.$message.error('请选择需要查询的时间段!')
return
}
if (this.tableData.length === 0) {
this.$message.error('请查询需要导出的数据!')
return
}
var param = []
if (this.tableData.length === 0) {
this.$message.warning('请查询要导出的数据')
return
}
param[0] = ['PartNum', this.TagName]
param[1] = ['开始时间', this.collectionTime[0]]
param[2] = ['结束时间', this.collectionTime[1]]
var Data = this.CreateData('2003', '工件数据_查询_导出', param)
const blob = 'data:image/gif;base64,R0lGODlhCQACAIAAAMzMzP///yH5BAEAAAEALAAAAAAJAAIAAAIEjI9pUAA7'
this.exportExcel_NPOI(Data, blob)
},
closePage() {
window.location.href = 'about:blank'
window.close()
},
// 分页
handleSizeChange(val) {
this.pageList = 1
this.pageSize = val
this.searchTable()
},
handleCurrentChange(val) {
this.pageList = val
this.searchTable()
}
}
}
</script>
<style>
.show-text {
font-family: "MiSans Regular",serif ;
margin-right: 20px;
font-size: 20px;
color: #595959;
}
</style>

258
src/views/page/index.vue Normal file
View File

@@ -0,0 +1,258 @@
<template>
<div id="screen" class="allShow" :style="{ 'width': `${style.width}px`, 'height': `${style.height}px`, 'transform': `${style.transform}` }">
<el-row style="box-shadow: inset 0 0 30px rgb(24, 78, 135);">
<div style="height: 80px; width: 1918px;">
<el-col :span="5">
<div style="font-size: 1.5rem;margin-top: 10px;margin-left: 10px">
<el-col :span="12">
<img style="height: 60px;cursor: pointer" :src="titlePng"/>
</el-col>
<el-col :span="12">
<div style="font-weight: bolder;line-height: 50px"></div>
</el-col>
</div>
</el-col>
<el-col :span="13">
<div style="font-size: 3rem;color: white;text-align: center;margin-top: 15px">
<span style="letter-spacing: 5px;font-weight: bolder">基于虚拟调试的智能机器人清洗工厂平台</span>
</div>
</el-col>
<el-col :span="6">
<el-col :span="13">
<div style="color: white;font-size: 3.2rem;margin-top: 10px;float: right">
</div>
</el-col>
<el-col :span="11">
<div style="color: white;font-size: 1.7rem;margin-top: 10px;margin-right: 2%;float: right">
<img style="height: 60px;" :src="titlePng1"/>
</div>
</el-col>
</el-col>
</div>
</el-row>
<el-row style="box-shadow: inset 0 0 30px rgb(24, 78, 135);height: 1000px;padding: 10px 20px">
<el-col :span="2" style="height: 960px;background-color: rgb(219 219 219)">
<div style="display: flex;flex-direction: column">
<div id="menu_1" class="show-label-title" @click="selectPage(1)">设备信息</div>
<div id="menu_2" class="show-label-title" @click="selectPage(2)">维护设定</div>
<div id="menu_999" class="show-label-title-out" @click="selectPage(999)">退出</div>
</div>
</el-col>
<el-col :span="22" style="height: 960px;background-color: rgb(179 179 179)">
<div style="background-color: #fff;margin: 0;">
<q-x_part ref="q-x_partPage" v-if="pageIndexShow === 1"/>
<q-x_-e-m-s ref="q-x_-e-m-sPage" v-if="pageIndexShow === 2"/>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import QX_part from '@/views/page/QX_part.vue'
import QX_EMS from '@/views/page/QX_EMS.vue'
import axios from 'axios'
import $ from 'jquery'
export default {
components: {
'QX_part': QX_part,
'QX_EMS': QX_EMS
},
data() {
return {
style: {
width: '1920',
height: '1080',
transform: 'scaleY(1) scaleX(1) translate(-50%, -50%)'
},
titlePng: '',
titlePng1: '',
activeName: 'first1',
title: '',
loading: false,
tableData: [],
tableData1: [],
ID: '',
station: '',
stationOutput: '',
stationNumberID: '',
partID: '',
titleEdit: '',
date: new Date(),
month: '',
day: '',
minute: '',
hour: '',
year: '',
second: '',
week: '',
timer: null,
timerInit: null,
notifyPromise: Promise.resolve(),
pageIndexShow: 1,
pageIndexShow_Last: 1
}
},
// 通过路由把index3中 点击的工位号 和 是否存在订单 值传进本页
watch: {
},
computed: {},
mounted() {
document.getElementById(`menu_1`).style.backgroundColor = '#fff'
document.getElementById(`menu_1`).style.color = '#000000'
this.setScale()
/* 窗口改变事件*/
$(window).resize(() => {
this.setScale()
})
},
created() {
this.getLogo()
},
beforeDestroy() {
},
methods: {
getScale() {
const w = window.innerWidth / this.style.width
const h = window.innerHeight / this.style.height
return { x: w, y: h }
},
setScale() {
const scale = this.getScale()
this.style.transform = 'scaleY(' + scale.y + ') scaleX(' + scale.x + ') translate(-50%, -50%)'
},
selectPage(pageIndex) {
if (pageIndex === 999) {
window.location.href = 'about:blank'
window.close()
return
}
document.getElementById(`menu_${pageIndex}`).style.backgroundColor = '#fff'
document.getElementById(`menu_${pageIndex}`).style.color = '#000000'
if (this.pageIndexShow_Last !== pageIndex) {
document.getElementById(`menu_${this.pageIndexShow_Last}`).style.backgroundColor = '#ffaa13'
document.getElementById(`menu_${this.pageIndexShow_Last}`).style.color = '#fff'
}
this.pageIndexShow = pageIndex
this.pageIndexShow_Last = pageIndex
},
closePage() {
window.location.href = 'about:blank'
window.close()
},
getLogo() {
axios.get('../../JFDL_logo.png', {
responseType: 'arraybuffer'
}).then(res => {
this.titlePng = 'data:image/jpeg;base64,' + btoa(new Uint8Array(res.data).reduce((data, byte) => data + String.fromCharCode(byte), ''))
})
axios.get('../../DAMLOGO.png', {
responseType: 'arraybuffer'
}).then(res => {
this.titlePng1 = 'data:image/jpeg;base64,' + btoa(new Uint8Array(res.data).reduce((data, byte) => data + String.fromCharCode(byte), ''))
})
}
}
}
</script>
<style>
HTML{
overflow: hidden;
}
body{
margin:0;
padding:0;
width: 1920px;
height: 1080px;
overflow: hidden;
position: relative;
font-family: MiSans Bold, serif;
}
/*css主要部分的样式*/
/*定义滚动条宽高及背景,宽高分别对应横竖滚动条的尺寸*/
::-webkit-scrollbar {
width: 5px; /*对垂直流动条有效*/
height: 5px; /*对水平流动条有效*/
}
/*定义滚动条的轨道颜色、内阴影及圆角*/
::-webkit-scrollbar-track {
-webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, .3);
background-color: rgb(14, 50, 97);
/*background-color: #ffffff;*/
border-radius: 2px;
}
/*定义滑块颜色、内阴影及圆角*/
::-webkit-scrollbar-thumb {
border-radius: 5px;
-webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, .3);
background-color: rgb(10, 35, 82);
}
/*定义两端按钮的样式*/
::-webkit-scrollbar-button {
display: none;
}
/*定义右下角汇合处的样式*/
::-webkit-scrollbar-corner {
background: #dedede;
}
</style>
<style scoped="scoped">
.allShow {
overflow-y: hidden;
z-index: 100;
transform-origin: 0 0;
position: fixed;
left: 50%;
top: 50%;
transition: 0.3s;
background-color: rgb(8, 31, 72);
color: white;
}
.show-label-title{
cursor: pointer;
border-radius: 5px;
font-size: 28px;
margin: 10px 5px;
background-color: #ffad1b;
height: 60px;
text-align: center;
line-height: 60px;
border: 1px solid #00893d;
}
.show-label-title-out{
cursor: pointer;
border-radius: 5px;
font-size: 28px;
margin: 10px 5px;
background-color: #ff4444;
height: 60px;
text-align: center;
line-height: 60px;
border: 1px solid #00893d;
}
.allShow {
overflow-y: hidden;
z-index: 100;
transform-origin: 0 0;
position: fixed;
left: 50%;
top: 50%;
transition: 0.3s;
background-color: rgb(8, 31, 72);
color: white;
}
.title-date>p {
color: #fff;
/* background: linear-gradient(to bottom, #043768, #000c3b,#043768); */
box-shadow: inset 0 0 30px #07417a;
border: solid 2px #032d60;
border-radius: 10px;
/* box-shadow: 4px 2px 6px #033579, -4px -2px 6px #033579, 0px 0px 12px 5px #033579 inset; */
font-size: 1.5rem;
margin: 0px 390px;
padding: 5px 10px;
}
</style>