This commit is contained in:
=
2020-06-11 18:28:50 +02:00
parent ccf8cd265e
commit 8324bcf297
17 changed files with 502 additions and 157 deletions
@@ -65,4 +65,32 @@
}
}
.warmers {
position: relative;
svg {
width: 100%;
height: 100%;
rect {
fill: none;
stroke: 1px solid blue;
}
.resistance {
width: calc(100% - 4px);
height: calc(100% - 4px);
background-color: #f40000;
margin: 2px;
border-radius: 4px;
}
}
.controls {
position: absolute;
bottom: 1rem;
right: 1rem;
}
}
}
@@ -4643,6 +4643,36 @@
font-size: 24px;
font-weight: 500;
}
.modal.riscaldi-info .warmers {
position: relative;
}
.modal.riscaldi-info .warmers svg {
width: 100%;
height: 100%;
}
.modal.riscaldi-info .warmers svg rect {
fill: none;
stroke: 1px solid blue;
}
.modal.riscaldi-info .warmers svg .resistance {
width: calc(100% - 4px);
height: calc(100% - 4px);
background-color: #f40000;
margin: 2px;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
font-size: 28px;
font-weight: bold;
color: #fff;
border: 1px solid #c6d5dd;
}
.modal.riscaldi-info .warmers .controls {
position: absolute;
bottom: 1rem;
right: 1rem;
}
.modal.formato-info section .tast {
margin-left: -300px;
}
+5
View File
@@ -15821,6 +15821,11 @@
"resolved": "https://registry.npmjs.org/svg-gauge/-/svg-gauge-1.0.6.tgz",
"integrity": "sha512-gRkznVhtS18eOM/GMPDXAvrLZOpqzNVDg4bFAPAEjiDKd1tZHFIe8Bwt3G6TFg/H+pFboetPPI+zoV+bOL26QQ=="
},
"svg-pan-zoom": {
"version": "3.6.1",
"resolved": "https://registry.npmjs.org/svg-pan-zoom/-/svg-pan-zoom-3.6.1.tgz",
"integrity": "sha512-JaKkGHHfGvRrcMPdJWkssLBeWqM+Isg/a09H7kgNNajT1cX5AztDTNs+C8UzpCxjCTRrG34WbquwaovZbmSk9g=="
},
"svg-tags": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz",
+71 -71
View File
@@ -1,73 +1,73 @@
{
"name": "step",
"version": "1.0.0",
"description": "step",
"author": "Paolo Possanzini <paolo@teamdev.it>",
"private": true,
"scripts": {
"build": "webpack",
"buildprod": "webpack --progress --config webpack.config.js --env production",
"dev": "webpack --watch",
"serve": "webpack-dev-server --inline --progress --config webpack.config.js"
},
"dependencies": {
"axios": "0.19.2",
"brace": "0.11.1",
"chart.js": "^2.9.3",
"core-js": "^3.4.4",
"izitoast": "1.2.0",
"moment": "2.24.0",
"qrcode": "^1.4.4",
"raphael": "^2.3.0",
"sprintf-js": "1.1.2",
"svg-gauge": "^1.0.6",
"v-tooltip": "^2.0.3",
"vee-validate": "2.1.1",
"vue": "^2.6.11",
"vue-chartjs": "^3.5.0",
"vue-class-component": "7.2.3",
"vue-drag-drop": "1.1.4",
"vue-property-decorator": "8.4.0",
"vue-router": "^3.1.6",
"vue-smooth-dnd": "0.8.1",
"vue2-ace-editor": "0.0.15",
"vue2-datepicker": "3.4.1",
"vuex": "3.1.3",
"svg-gauge": "1.0.6"
},
"devDependencies": {
"@babel/plugin-proposal-export-default-from": "7.8.3",
"@types/es6-promise": "3.3.0",
"@vue/cli-plugin-babel": "^4.1.0",
"@vue/cli-plugin-eslint": "^4.1.0",
"@vue/cli-plugin-router": "^4.1.0",
"@vue/cli-plugin-typescript": "^4.1.0",
"@vue/cli-plugin-vuex": "^4.1.0",
"@vue/cli-service": "^4.2.3",
"autoprefixer": "^7.1.2",
"babel-loader": "8.0.6",
"chalk": "^2.0.1",
"copy-webpack-plugin": "^4.0.1",
"css-loader": "^0.28.0",
"eventsource-polyfill": "^0.9.6",
"file-loader": "^1.1.4",
"terser-webpack-plugin": "1.3.0",
"ts-loader": "6.2.1",
"typescript": "3.8.3",
"url-loader": "^3.0.0",
"vue-loader": "^15.9.0",
"vue-template-compiler": "^2.6.11",
"webpack": "^4.42.0",
"webpack-cli": "3.2.3",
"webpack-dev-server": "3.2.1"
},
"engines": {
"node": ">= 4.0.0",
"npm": ">= 3.0.0"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
"name": "step",
"version": "1.0.0",
"description": "step",
"author": "Paolo Possanzini <paolo@teamdev.it>",
"private": true,
"scripts": {
"build": "webpack",
"buildprod": "webpack --progress --config webpack.config.js --env production",
"dev": "webpack --watch",
"serve": "webpack-dev-server --inline --progress --config webpack.config.js"
},
"dependencies": {
"axios": "0.19.2",
"brace": "0.11.1",
"chart.js": "^2.9.3",
"core-js": "^3.4.4",
"izitoast": "1.2.0",
"moment": "2.24.0",
"qrcode": "^1.4.4",
"raphael": "^2.3.0",
"sprintf-js": "1.1.2",
"svg-gauge": "^1.0.6",
"v-tooltip": "^2.0.3",
"vee-validate": "2.1.1",
"vue": "^2.6.11",
"vue-chartjs": "^3.5.0",
"vue-class-component": "7.2.3",
"vue-drag-drop": "1.1.4",
"vue-property-decorator": "8.4.0",
"vue-router": "^3.1.6",
"vue-smooth-dnd": "0.8.1",
"vue2-ace-editor": "0.0.15",
"vue2-datepicker": "3.4.1",
"vuex": "3.1.3",
"svg-pan-zoom": "3.6.1"
},
"devDependencies": {
"@babel/plugin-proposal-export-default-from": "7.8.3",
"@types/es6-promise": "3.3.0",
"@vue/cli-plugin-babel": "^4.1.0",
"@vue/cli-plugin-eslint": "^4.1.0",
"@vue/cli-plugin-router": "^4.1.0",
"@vue/cli-plugin-typescript": "^4.1.0",
"@vue/cli-plugin-vuex": "^4.1.0",
"@vue/cli-service": "^4.2.3",
"autoprefixer": "^7.1.2",
"babel-loader": "8.0.6",
"chalk": "^2.0.1",
"copy-webpack-plugin": "^4.0.1",
"css-loader": "^0.28.0",
"eventsource-polyfill": "^0.9.6",
"file-loader": "^1.1.4",
"terser-webpack-plugin": "1.3.0",
"ts-loader": "6.2.1",
"typescript": "3.8.3",
"url-loader": "^3.0.0",
"vue-loader": "^15.9.0",
"vue-template-compiler": "^2.6.11",
"webpack": "^4.42.0",
"webpack-cli": "3.2.3",
"webpack-dev-server": "3.2.1"
},
"engines": {
"node": ">= 4.0.0",
"npm": ">= 3.0.0"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
}
@@ -24,7 +24,7 @@
></setup-button>
<setup-button
@click="sshowModalAtStep(3);"
@click="showModalAtStep(3);"
:phase="4"
title="Riscaldi"
statusImage="fa fa-check-circle undone-step"
@@ -0,0 +1,46 @@
import Component from "vue-class-component";
import Vue from "vue";
import { Prop } from "vue-property-decorator";
import Warmers from "./warmers";
@Component({})
export default class Resistance extends Vue {
@Prop()
res: Warmers.IResistance;
@Prop()
channel: Warmers.IChannel;
@Prop({ default: false })
selected: boolean;
@Prop({ default: function () { return [253, 216, 53] } })
colorFrom: number[];
@Prop({ default: function () { return [244, 0, 0] } })
colorTo: number[];
@Prop({ default: function () { return [253, 216, 53] } })
selectedColorFrom: number[];
@Prop({ default: function () { return [244, 0, 0] } })
selectedColorTo: number[];
get currentStandardColor() {
return [this.colorFrom[0] - (this.colorFrom[0] - this.colorTo[0]) * this.channel.setpointPLC / 100,
this.colorFrom[1] - (this.colorFrom[1] - this.colorTo[1]) * this.channel.setpointPLC / 100,
this.colorFrom[2] - (this.colorFrom[2] - this.colorTo[2]) * this.channel.setpointPLC / 100];
}
get currentColor() {
if (this.selected) return this.currentSelectedColor;
return this.currentStandardColor;
}
get currentSelectedColor() {
return [this.colorFrom[0] - (this.colorFrom[0] - this.colorTo[0]) * this.channel.setpointPLC / 100,
this.colorFrom[1] - (this.colorFrom[1] - this.colorTo[1]) * this.channel.setpointPLC / 100,
this.colorFrom[2] - (this.colorFrom[2] - this.colorTo[2]) * this.channel.setpointPLC / 100];
}
}
@@ -0,0 +1,4 @@
<template>
<div class="resistance" :style="{backgroundColor:`rgb(${currentColor})`}">{{channel.setpointPLC}} %</div>
</template>
<script src="./resistance.ts" lang="ts"></script>
@@ -0,0 +1,25 @@
import Vue from 'vue';
import Component from 'vue-class-component';
import { Prop } from 'vue-property-decorator';
import toggleButton from "@/components/toggleButton.vue";
import warmers from "./warmers.vue";
@Component({
name: "riscaldisup", components: {
toggleButton,
warmers
}
})
export default class RiscaldiInferiori extends Vue {
@Prop()
recipe: Recipe.IRecipe;
zoomIn() {
}
zoomOut() {
}
}
@@ -0,0 +1,83 @@
<template>
<section>
<aside class="scrollable auto" v-if="recipe">
<div class="input-area">
<label>{{'heats_upperheaters_enabled'|localize('Abilitazione')}}</label>
<toggle-button v-model="recipe.heats_upperheaters_enabled.status.enabled"></toggle-button>
</div>
<div class="input-area">
<label>{{'heats_upperheaters_max_time'|localize('Durata massima')}}</label>
<numeric v-model="recipe.heats_upperheaters_max_time" />
</div>
<slider v-model="recipe.heats_upperheaters_max_time"></slider>
<div class="input-area">
<label>{{'mock_setpoint'|localize('Setpoint ceramica')}}</label>
<numeric v-model="mock_setpoint" />
</div>
<slider v-model="mock_setpoint"></slider>
<div class="specific">
<label>Selezione</label>
<div>
<button>
<img src="assets/icons/png/rett.png" />
</button>
<button>
<img src="assets/icons/png/libera.png" />
</button>
<button>
<label>Tutti</label>
</button>
<button>
<label>Nessuno</label>
</button>
</div>
</div>
<div class="specific">
<label>Gestione potenza (25kW)</label>
<div>
<button>
<img src="assets/icons/png/meno5.png" />
</button>
<button>
<img src="assets/icons/png/piu5.png" />
</button>
<select>
<option value="0">0%</option>
<option value="25">25%</option>
<option value="50">50%</option>
<option value="100">100%</option>
</select>
</div>
<button class="btn btn-success">Autocomposizione</button>
</div>
<div class="input-area">
<div>
<label>Oscillatore</label>
<toggle-button v-model="recipe.heats_upperheaters_oscillation.status.enabled"></toggle-button>
</div>
<div>
<label>Movimento</label>
<toggle-button v-model="recipe.heats_upperheaters_movement_enabled.status.enabled"></toggle-button>
</div>
</div>
</aside>
<hr />
<div class="warmers specific">
<warmers :id-reflector="1"></warmers>
<div class="controls">
<button>
<img src="assets/icons/png/zoomIn.png" />
</button>
<button>
<img src="assets/icons/png/zoomOutOp.png" />
</button>
</div>
</div>
</section>
</template>
<script lang="ts" src="./riscaldi-inferiori.ts"></script>
@@ -1,22 +1,25 @@
import Vue from 'vue';
import Component from 'vue-class-component';
import { Prop } from 'vue-property-decorator';
import Slider from "@/app_modules_thermo/components/slider.vue"
import toggleButton from "@/components/toggleButton.vue";
import warmers from "./warmers.vue";
@Component({
name: "riscaldisup", components: {
slider: Slider, toggleButton
toggleButton,
warmers
}
})
export default class RiscaldiSuperiori extends Vue {
@Prop({})
setpoint:number;
mock_setpoint:number=this.setpoint;
@Prop()
recipe:Recipe.IRecipe;
recipe: Recipe.IRecipe;
zoomIn() {
(this.$refs.warmers as any).zoomIn();
}
zoomOut() {
(this.$refs.warmers as any).zoomOut();
}
}
@@ -1,6 +1,6 @@
<template>
<section>
<aside class="scrollable auto">
<aside class="scrollable auto" v-if="recipe">
<div class="input-area">
<label>{{'heats_upperheaters_enabled'|localize('Abilitazione')}}</label>
<toggle-button v-model="recipe.heats_upperheaters_enabled.status.enabled"></toggle-button>
@@ -10,17 +10,13 @@
<label>{{'heats_upperheaters_max_time'|localize('Durata massima')}}</label>
<numeric v-model="recipe.heats_upperheaters_max_time" />
</div>
<slider
v-model="recipe.heats_upperheaters_max_time"
></slider>
<slider v-model="recipe.heats_upperheaters_max_time"></slider>
<div class="input-area">
<label>{{'mock_setpoint'|localize('Setpoint ceramica')}}</label>
<numeric v-model="mock_setpoint" />
</div>
<slider
v-model="mock_setpoint"
></slider>
<slider v-model="mock_setpoint"></slider>
<div class="specific">
<label>Selezione</label>
@@ -69,19 +65,11 @@
</div>
</aside>
<hr />
<div class="specific">
<div>
<div>
<button>
<img src="assets/icons/png/zoomIn.png" />
</button>
<button>
<img src="assets/icons/png/zoomOutOp.png" />
</button>
</div>
</div>
<div class="warmers specific">
<warmers ref="warmers"></warmers>
</div>
</section>
</template>
<script lang="ts" src="./riscaldi-superiori.ts"></script>
@@ -0,0 +1,106 @@
import Component from "vue-class-component";
import Vue from "vue";
import { store } from "@/store";
import { warmersService } from "@/services/warmersService";
import { Prop, Watch } from "vue-property-decorator";
import resistance from "./resistance.vue";
import svgPanZoom from "svg-pan-zoom";
@Component({
components: {
resistance
}
})
export default class Warmers extends Vue {
width = 180;
height = 48;
@Prop({ default: 0 })
idReflector: number;
selectedChannels: number[] = []
get channels() {
return store.state.warmers.channels.filter(i => i.idReflector == this.idReflector);
}
get resistances() {
let cc = this.channels.map(i => i.idChannel);
return store.state.warmers.resistances.filter(r => cc.findIndex(i => i == r.idChannel) >= 0);
}
get rows() {
let result = this.resistances.reduce((p, c) => {
p.add(c.row);
return p;
}, new Set<number>());
return Array.from(result.values());
}
getChannel(id: number) {
return this.channels.find(i => i.idChannel == id);
}
// Ottengo le resistenze per ogni riga
resistancesPerRow(row: number) {
return this.resistances.filter(i => i.row == row);
}
// Calcolo la posizione di ogni resitenza in base alla dimensione delle resistenze precedenti.
resistanceXPosition(row, col) {
let cells = this.resistancesPerRow(row).filter(i => i.column < col);
let result = cells.reduce((p, c) => p + c.dimension, 0);
return result;
}
maxWidth: number = 0;
maxHeight: number = 0;
currentViewBoxX: number = 0;
currentViewBoxY: number = 0;
currentZoomX: number = 0;
currentZoomY: number = 0;
calcSizes() {
this.maxWidth = Math.max(...this.rows.map(r => this.resistancesPerRow(r).reduce((p, c) => p + c.dimension, 0))) * this.width;
this.maxHeight = this.rows.length * this.height;
this.currentViewBoxX = this.maxWidth / 2;
this.currentViewBoxY = this.maxHeight / 2;
this.currentZoomX = this.maxWidth / 2;
this.currentZoomY = this.maxHeight / 2;
}
get viewBox() {
return [this.currentViewBoxX - this.currentZoomX, this.currentViewBoxY - this.currentZoomY,
this.currentZoomX * 2, this.currentZoomY * 2];
}
zoomIn() {
this.currentZoomY /= 2;
this.currentZoomX /= 2;
}
zoomOut() {
this.currentZoomY *= 2;
this.currentZoomX *= 2;
}
mounted() {
this.calcSizes();
setTimeout(() => {
svgPanZoom('#warmer', {
zoomEnabled: true,
controlIconsEnabled: true,
fit: true,
center: true,
});
}, 2000)
}
}
@@ -0,0 +1,18 @@
<template>
<svg id="warmer" :viewBox="viewBox">
<g v-for="row in rows" :key="row">
<foreignObject
v-for="cell in resistancesPerRow(row)"
:key="`cell-${cell.id}`"
:x="resistanceXPosition(row, cell.column) * width"
:y="row * height"
:width="width * cell.dimension"
:height="height"
:rx="4"
>
<resistance :res="cell" :channel="getChannel(cell.idChannel)" />
</foreignObject>
</g>
</svg>
</template>
<script src="./warmers.ts" lang="ts"></script>
+4
View File
@@ -29,6 +29,9 @@ import { recipeService } from "@/services/recipeService";
recipeService.GetCurrent();
recipeService.GetOverview();
warmersService.GetChannels();
warmersService.GetResistances();
// import VueDragDrop from 'vue-drag-drop';
// Vue.use(VueDragDrop);
@@ -115,6 +118,7 @@ import "./filters/isValidMixin";
// registrazione componenti generali
import components from "@/app_modules_thermo/components";
import { warmersService } from "./services/warmersService";
for (let name in components) {
Vue.component(name, components[name]);
}
@@ -1,43 +1,44 @@
import { baseRestService } from "../_base/baseRestService";
import {CONFIGURATION} from "@/config";
import { CONFIGURATION } from "@/config";
import { warmersActions } from "@/store/warmers.store";
import { store } from "@/store";
import Warmers from "@/app_modules_thermo/setup/riscaldi/components/base-components/warmers";
export class WarmersService extends baseRestService {
BASE_URL = async () => (await CONFIGURATION).api.apiServerUrl + "/api/warmers/";
BASE_URL = async () => (await CONFIGURATION).api.apiServerUrl + "api/warmers/";
async GetChannels(){
let result = await this.Get((await this.BASE_URL()) + "channels");
warmersActions.setChannels(store, result as Warmers.IChannels);
return result;
}
async GetChannels() {
let result = await this.Get((await this.BASE_URL()) + "channels");
warmersActions.setChannels(store, result as { [id: number]: Warmers.IChannel });
return result;
}
async GetResistances(){
let result = await this.Get((await this.BASE_URL()) + "resistances");
warmersActions.setResistances(store, result as Warmers.IResistances);
return result;
}
async GetResistances() {
let result = await this.Get((await this.BASE_URL()) + "resistances");
warmersActions.setResistances(store, result as { [id: number]: Warmers.IResistance });
return result;
}
async Update(model:any){
let result = await this.Put<any>((await this.BASE_URL()) + "update", model, true);
return result;
}
async Update(model: any) {
let result = await this.Put<any>((await this.BASE_URL()) + "update", model, true);
return result;
}
async Confirm(){
let result = await this.Put<any>((await this.BASE_URL()) + "confirm", true);
return result;
}
async Confirm() {
let result = await this.Put<any>((await this.BASE_URL()) + "confirm", true);
return result;
}
async Cancel(){
let result = await this.Put<any>((await this.BASE_URL()) + "cancel", true);
return result;
}
async Cancel() {
let result = await this.Put<any>((await this.BASE_URL()) + "cancel", true);
return result;
}
async SetConfig(){
let result = await this.Put<any>((await this.BASE_URL()) + "setConfig", true);
return result;
}
async SetConfig() {
let result = await this.Put<any>((await this.BASE_URL()) + "setConfig", true);
return result;
}
}
export const warmersService = new WarmersService();
+11 -9
View File
@@ -15,9 +15,10 @@ import { LocalizationService, localizationService } from "@/services/localizatio
import { ProductionStoreModel, productionStore } from "./production.store";
import { jobEditorStore } from "./jobEditor.store";
import { scadaStore, ScadaModel } from "./scada";
import { reportStore, ReportStoreModel} from "./report.store";
import { recipeStore, RecipeStoreModel} from "./recipe.store";
import { usersStore,UsersStoreModel } from "./users.store";
import { reportStore, ReportStoreModel } from "./report.store";
import { recipeStore, RecipeStoreModel } from "./recipe.store";
import { usersStore, UsersStoreModel } from "./users.store";
import { warmersStore, WarmersStoreModel } from "./warmers.store";
Vue.use(Vuex);
@@ -44,7 +45,7 @@ export interface AppModel {
report: ReportStoreModel;
recipe: RecipeStoreModel;
users: UsersStoreModel;
warmers: WarmersStoreModel;
}
// Mutations Name
@@ -92,7 +93,8 @@ const _store = {
scada: scadaStore,
report: reportStore,
recipe: recipeStore,
users: usersStore
users: usersStore,
warmers: warmersStore,
},
mutations: {
@@ -114,7 +116,7 @@ const _store = {
state.isShowDashboard = !state.isShowDashboard;
},
setShowPreDashboard(state) {
state.isShowPreDashboard = !state.isShowPreDashboard;
}
},
@@ -136,11 +138,11 @@ const _store = {
FavSoftkeyStop(context) {
context.commit("favSoftkey", false);
},
ShowDashboard(context){
ShowDashboard(context) {
context.commit("setShowDashboard");
},
ShowPreDashboard(context){
ShowPreDashboard(context) {
context.commit("setShowPreDashboard");
},
SetCurrentUser(context, userinfo) {
+24 -22
View File
@@ -6,28 +6,30 @@ import { AlarmsModel, alarmsModelActions, alarmsStore, AlarmModel } from "./alar
import { processModelActions, processStore, RunningProcessModel } from "./runningProcess.store";
import { LocalizationModel, languageModel, localizationModelActions } from "./localization.store";
import { jobEditorStoreActions } from "./jobEditor.store";
import { UsersStoreModel,UsersActions } from "./users.store";
import { UsersStoreModel, UsersActions } from "./users.store";
import { WarmersStoreModel, warmersActions } from "./warmers.store";
export {
store,
AppModel,
appModelActions,
machineInfoActions,
MachineInfoModel,
machineStatusActions,
paddleActions,
PaddleModel,
MachineStatusModel,
AlarmsModel,
alarmsModelActions,
processModelActions,
RunningProcessModel,
LocalizationModel,
languageModel,
localizationModelActions,
AlarmModel,
buttonStatus,
jobEditorStoreActions,
UsersActions,
UsersStoreModel
store,
AppModel,
appModelActions,
machineInfoActions,
MachineInfoModel,
machineStatusActions,
paddleActions,
PaddleModel,
MachineStatusModel,
AlarmsModel,
alarmsModelActions,
processModelActions,
RunningProcessModel,
LocalizationModel,
languageModel,
localizationModelActions,
AlarmModel,
buttonStatus,
jobEditorStoreActions,
UsersActions,
UsersStoreModel,
WarmersStoreModel, warmersActions
}