main
cc 2024-03-26 07:43:00 +00:00
parent 9dfe0ea3f0
commit 4762eeab6d
7 changed files with 336 additions and 297 deletions

View File

@ -1,59 +1,30 @@
<template>
<div class="common-layout">
<el-container>
<el-header v-if="state.showMenu">INNcom </el-header>
<el-main><router-view /></el-main>
</el-container>
</div>
<router-view />
</template>
<script>
import { onUnmounted, reactive } from 'vue'
import { onUnmounted } from 'vue'
import { useRouter } from 'vue-router'
import { pathMap, localGet } from '@/utils';
export default {
name: 'App',
setup() {
const noMenu = ['/login']
const router = useRouter();
const state = reactive({
showMenu: true,
currentPath: '/dashboard'
})
// 退
if (window.history && window.history.pushState) {
history.pushState(null, null, document.URL);
window.addEventListener('popstate', () => {
if (!localGet('token')) {
state.showMenu = false
}
}, false);
}
const unwatch = router.beforeEach((to, from, next) => {
if (to.path == '/login') {
// /login
next()
} else {
// /login token
if (!localGet('token')) {
//
if (!localGet('token') || !localGet('name')) {
next({ path: '/login' })
} else {
//
next()
}
}
state.showMenu = !noMenu.includes(to.path)
state.currentPath = to.path
document.title = pathMap[to.name]
})
onUnmounted(() => {
unwatch();
})
return {
state
}
}
}
</script>

View File

@ -1,9 +1,8 @@
import axios from "axios";
import { pathMap, localGet, localRemove } from '@/utils';
import { localGet, localRemove } from '@/utils';
axios.defaults.withCredentials = true;
import { ElMessage } from "element-plus";
import router from "@/router/index";
// 请求头headers 信息
axios.defaults.headers["X-Requested-With"] = "XMLHttpRequest";
axios.defaults.headers = {
name: localGet('name'),
@ -15,8 +14,7 @@ axios.defaults.headers = {
// 请求拦截器,内部根据返回值,重新组装,统一管理。
axios.interceptors.response.use(
(res) => {
console.log(111,res);
if(res.data.code === 2001) {
if(res.data.code === 2001||res.data.code === 2002) {
ElMessage.error(res.data.message || "401 Unauthorized");
router.push({ path: "/login" });
localRemove('token');
@ -37,17 +35,26 @@ export function postJsonRequest(url, params) {
method: "post",
url: url,
data: params,
// responseType: 'arraybuffer',
headers: {
"Content-Type": "application/json",
},
});
}
export function downloadRequest(url, params) {
return axios({
method: "post",
url: url,
data: params,
responseType: 'blob',
headers: {
"Content-Type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
},
});
}
// get请求
export function getRequest(url, params) {
return axios({
method: "get",
// responseType: 'arraybuffer',
params: {
...params,
},

View File

@ -1,13 +1,14 @@
import {
getRequest,
postJsonRequest,
deleteRequest,
putRequest
postJsonRequest,downloadRequest
} from './api.js';
const myApi = {
getProjects(params) {
return postJsonRequest('/api/honeywell/inncon/list/project', params);
},
download(params) {
return downloadRequest('/api/honeywell/inncon/list/project', params);
}
}
export default myApi;

View File

@ -17,8 +17,6 @@ export function localRemove(key) {
export const pathMap = {
login: '登录',
home: 'INNcom 清单生成器',
project: 'INNcom 清单生成器',
room: 'INNcom 清单生成器',
weather: 'INNcom 清单生成器',
home: '项目管理',
room: '房型管理',
}

View File

@ -1,7 +1,15 @@
<template>
<el-container>
<el-header>
<el-card>
项目管理
<el-button type="danger" @click="logout">退</el-button>
</el-card>
</el-header>
<el-main>
<el-card class="home-div">
<el-card class="card-div">
<el-button :icon="Plus" circle size="large" @click="open_project" />
<el-button class="button_plus" :icon="Plus" circle size="large" @click="open_project" />
</el-card>
<el-card class="card-div" v-for="(item, index) in projects" :key="index">
<p class="project-title">{{ item.name }}</p>
@ -12,6 +20,9 @@
<el-button type="danger" @click="openRemove(item)"></el-button>
</el-card>
</el-card>
</el-main>
</el-container>
<el-dialog v-model="add_project_info.enable" title="新增项目" width="500" center>
<el-form :model="add_project_info">
<el-form-item label="项目名称">
@ -54,11 +65,16 @@ import { Plus } from "@element-plus/icons-vue";
import { ElMessage, ElMessageBox } from "element-plus";
import myApi from "@/api/myApi.js";
import { useRouter } from 'vue-router'
import { localRemove } from '@/utils';
const router = useRouter()
const projects = ref([]);
const logout = () => {
localRemove("name");
localRemove("token");
router.push('login');
}
const projects = ref([]);
const open_project = () => {
add_project_info.name = '';
@ -85,7 +101,6 @@ const openUpdateDialog = (item) => {
update_project_info.name = item.name;
update_project_info.new_name = item.name;
update_project_info.description = item.description;
update_project_info.content = item.content || null;
update_project_info.enable = true;
}
@ -121,7 +136,6 @@ const update_project_info = reactive({
name: "",
new_name: "",
description: "",
content: null,
});
const update_project = async () => {
@ -219,5 +233,11 @@ onMounted(() => {
font-weight: 500;
}
.button_plus {
width: 150px;
height: 150px;
font-size: 72px;
}
}
</style>

View File

@ -6,7 +6,8 @@
<div class="title">登录</div>
</div>
</div>
<el-form label-position="top" :rules="rules" :model="ruleForm" ref="loginForm" class="login-form">
<el-form label-position="top" :rules="rules" :model="ruleForm" ref="loginForm" class="login-form" @keydown.enter.native="submitForm"
>
<el-form-item label="账号" prop="username">
<el-input type="text" v-model.trim="ruleForm.username" autocomplete="off"></el-input>
</el-form-item>
@ -23,9 +24,7 @@
<script>
import { reactive, ref, toRefs } from 'vue'
import myApi from "@/api/myApi.js";
import { localSet } from '@/utils';
// const bcryptjs = require('bcryptjs')
import bcrypt from 'bcryptjs'
export default {
name: 'Login',
@ -49,7 +48,6 @@
const submitForm = async () => {
loginForm.value.validate(async (valid) => {
if (valid) {
// const res = await myApi.login(param);
const encryptedPassword = await bcrypt.hash(state.ruleForm.password, 10);
localSet('name', state.ruleForm.username);
localSet('token', encryptedPassword);

View File

@ -3,7 +3,8 @@
<el-card>
<div>
<el-button type="primary" @click="goHome"></el-button>
<el-button type="success" @click="save_room"></el-button>
<el-button type="success" @click="save_room"></el-button>
<el-button type="success" @click="exc"></el-button>
</div>
<div class="ptoject-info">
<div class="title">{{ project.name }}</div>
@ -14,8 +15,12 @@
<el-button type="primary" class="add-btn" :icon="Plus" @click="add_room"></el-button>
</div>
<div class="room-list">
<div v-for="(item, index) in project.content" :key="index" class="room-span" @click="select_room(item)"
:class="{ 'selectDiv': item.base_info.room_name === current_room_info.base_info.room_name }">
<div v-for="item in project.content" :key="item.base_info.room_name" class="room-span"
@click="select_room(item)" :class="{
selectDiv:
item.base_info.room_name ===
current_room_info.base_info.room_name,
}">
<span>{{ item.base_info.room_name }}</span>
<span>{{ item.base_info.room_count }}</span>
<el-button :icon="Delete" circle @click="delet_room(item)" />
@ -32,7 +37,7 @@
</div>
<div class="div300">
<span>房型数量</span>
<el-input-number v-model="current_room_info.base_info.room_count" :min="1" :max="1000"
<el-input-number v-model="current_room_info.base_info.room_count" :min="1" :max="99999"
label="描述文字"></el-input-number>
</div>
</div>
@ -40,33 +45,13 @@
<div class="div-2">
<span class="name name2">灯光信息</span>
<div class="flex-center bar">
<p>开关回路</p>
<div v-for="item in lightArr" :key="item.label">
<p>{{ item.label }}</p>
<p>
<el-input-number v-model="current_room_info.light_info.switching_circuit" :min="1"
:max="100"></el-input-number>
<el-input-number v-model="current_room_info.light_info[item.key]" :min="0"
:max="999"></el-input-number>
</p>
<p>0-10V调光</p>
<p>
<el-input-number v-model="current_room_info.light_info.dimming_10v" :min="1"
:max="100"></el-input-number>
</p>
<p>前沿调光</p>
<p>
<el-input-number v-model="current_room_info.light_info.dimming_leading_edge" :min="1"
:max="100"></el-input-number>
</p>
<p>后沿调光</p>
<p>
<el-input-number v-model="current_room_info.light_info.dimming_trailing_edge" :min="1"
:max="100"></el-input-number>
</p>
<p>DALI灯</p>
<p>
<el-input-number v-model="current_room_info.light_info.DALI" :min="1"
:max="100"></el-input-number>
</p>
</div>
</div>
</div>
<div class="div-3">
@ -74,30 +59,29 @@
<div class="flex-center bar">
<div>盘管类型</div>
<el-radio-group v-model="current_room_info.fcu_info.fcu_type">
<el-radio :value="item.value" :key="item.value" v-for="(item, index) in radioGroup1">{{
item.label
<el-radio :value="item.value" :key="item.value" v-for="item in radioGroup1">{{ item.label
}}</el-radio>
</el-radio-group>
<el-radio-group v-model="current_room_info.fcu_info.pipe_type">
<el-radio :value="item.value" :key="item.value" v-for="(item, index) in radioGroup2">{{
item.label
<el-radio :value="item.value" :key="item.value" v-for="item in radioGroup2">{{ item.label
}}</el-radio>
</el-radio-group>
<el-radio-group v-model="current_room_info.fcu_info.valve_type">
<el-radio :value="item.value" :key="item.value" v-for="(item, index) in radioGroup3">{{
item.label
<el-radio :value="item.value" :key="item.value" v-for="item in radioGroup3">{{ item.label
}}</el-radio>
</el-radio-group>
<div>
<p>风机盘管数量</p>
<p>
<el-input-number v-model="current_room_info.fcu_info.fcu_count" :min="1" :max="100"></el-input-number>
<el-input-number v-model="current_room_info.fcu_info.fcu_count" :min="0"
:max="999"></el-input-number>
</p>
</div>
<div>
<p>温控器数量</p>
<p>
<el-input-number v-model="current_room_info.fcu_info.thermostat_count" :min="1" :max="100"></el-input-number>
<el-input-number v-model="current_room_info.fcu_info.thermostat_count" :min="0"
:max="999"></el-input-number>
</p>
</div>
</div>
@ -107,20 +91,21 @@
<div class="flex-center bar">
<div>面板类型</div>
<el-radio-group v-model="current_room_info.panel_info.panel_type">
<el-radio :value="item.value" :key="item.value" v-for="(item, index) in radioGroup4">{{
item.label
<el-radio :value="item.value" :key="item.value" v-for="item in radioGroup4">{{ item.label
}}</el-radio>
</el-radio-group>
<div>
<p>面板数量</p>
<p>
<el-input-number v-model="current_room_info.panel_info.panel_count" :min="1" :max="100"></el-input-number>
<el-input-number v-model="current_room_info.panel_info.panel_count" :min="0"
:max="999"></el-input-number>
</p>
</div>
<div>
<p>按钮数量</p>
<p>
<el-input-number v-model="current_room_info.panel_info.panel_button_count" :min="1" :max="100"></el-input-number>
<el-input-number v-model="current_room_info.panel_info.panel_button_count" :min="0"
:max="999"></el-input-number>
</p>
</div>
</div>
@ -130,20 +115,21 @@
<div class="flex-center bar">
<div>窗帘类型</div>
<el-radio-group v-model="current_room_info.curtain_info.curtain_type">
<el-radio :value="item.value" :key="item.value" v-for="(item, index) in radioGroup5">{{
item.label
<el-radio :value="item.value" :key="item.value" v-for="item in radioGroup5">{{ item.label
}}</el-radio>
</el-radio-group>
<div>
<p>窗帘数量</p>
<p>
<el-input-number v-model="current_room_info.curtain_info.curtain_count" :min="1" :max="100"></el-input-number>
<el-input-number v-model="current_room_info.curtain_info.curtain_count" :min="0"
:max="999"></el-input-number>
</p>
</div>
<div>
<p>窗纱数量</p>
<p>
<el-input-number v-model="current_room_info.curtain_info.sheer_curtain_count" :min="1" :max="100"></el-input-number>
<el-input-number v-model="current_room_info.curtain_info.sheer_curtain_count" :min="0"
:max="999"></el-input-number>
</p>
</div>
</div>
@ -152,23 +138,15 @@
<span class="name name6">其他信息</span>
<div class="con-div">
<div class="flex-center bar">
<div v-for="(item, i) in otherArr" :key="item.label">
<div v-for="item in otherArr" :key="item.label">
<p>{{ item.label }}</p>
<p>
<el-input-number v-model="current_room_info.other[item.key]" :min="1"
:max="100"></el-input-number>
<el-input-number v-model="current_room_info.other[item.key]" :min="0"
:max="999"></el-input-number>
</p>
</div>
</div>
<el-checkbox-group v-model="current_room_info.other.Housekeeping" class="rules-label">
<el-checkbox v-for="(item, i) in checkList" :label="item.label" :key="item.value"
:value="item.value">
{{ item.label }}
</el-checkbox>
</el-checkbox-group>
</div>
</div>
<div class="div-7">
<span class="name name7">备注</span>
@ -182,18 +160,14 @@
</div>
</template>
<script setup>
import { Delete } from '@element-plus/icons-vue'
import { onMounted, reactive,ref } from 'vue'
import { Plus } from '@element-plus/icons-vue'
import { Delete } from "@element-plus/icons-vue";
import { onMounted, reactive } from "vue";
import { Plus } from "@element-plus/icons-vue";
import myApi from "@/api/myApi.js";
import { useRoute, useRouter } from 'vue-router'
import { useRoute, useRouter } from "vue-router";
import { ElMessage } from "element-plus";
import bcrypt from 'bcryptjs'
console.log(bcrypt.hashSync("aaa"))
const router = useRouter()
const route = useRoute()
const router = useRouter();
const route = useRoute();
const project = reactive({
name: "",
@ -203,102 +177,112 @@ const project = reactive({
const addData = reactive({
base_info: {
room_name: '',
room_name: "",
room_count: 1,
desc: ''
desc: "",
},
light_info: {//
light_info: {
//
switching_circuit: 0,
dimming_10v: 0,
dimming_leading_edge: 0,
dimming_trailing_edge: 0,
DALI: 0,
},
fcu_info: {//
fcu_info: {
//
fcu_type: 0,
pipe_type: 0,
valve_type: 0,
fcu_count: 0,
thermostat_count: 0,
},
panel_info: {//
panel_info: {
//
panel_type: 0,
panel_count: 0,
panel_button_count: 0,
},
curtain_info: {//
curtain_info: {
//
curtain_type: 0,
curtain_count: 0,
sheer_curtain_count: 0,
},
other: {//
PIR: 1,
PIR2: 1,
Gate: 1,
Window: 1,
doorbell: 1,
Housekeeping: ['DND', 'MUR'],
other: {
//
PIR: 0,
PIR2: 0,
Gate: 0,
Window: 0,
doorbell: 0,
Housekeeping: 0,
},
})
});
const current_room_info = reactive({
base_info: {
room_name: '',
room_name: "",
room_count: 1,
desc: ''
desc: "",
},
light_info: {//
light_info: {
//
switching_circuit: 0,
dimming_10v: 0,
dimming_leading_edge: 0,
dimming_trailing_edge: 0,
DALI: 0,
},
fcu_info: {//
fcu_info: {
//
fcu_type: 0,
pipe_type: 0,
valve_type: 0,
fcu_count: 0,
thermostat_count: 0,
},
panel_info: {//
panel_info: {
//
panel_type: 0,
panel_count: 0,
panel_button_count: 0,
},
curtain_info: {//
curtain_info: {
//
curtain_type: 0,
curtain_count: 0,
sheer_curtain_count: 0,
},
other: {//
PIR: 1,
PIR2: 1,
Gate: 1,
Window: 1,
doorbell: 1,
Housekeeping: ['DND', 'MUR'],
other: {
//
PIR: 0,
PIR2: 0,
Gate: 0,
Window: 0,
doorbell: 0,
Housekeeping: 0,
},
})
});
const get_project = async () => {
const param = {
action: 100,
data: {
name: route.query.project_name,
}
}
},
};
const res = await myApi.getProjects(param);
if (res.code === 0) {
project.name = res.data.name;
project.description = res.data.description;
if (res.data.content && Array.isArray(res.data.content) && res.data.content.length > 0) {
if (
res.data.content &&
Array.isArray(res.data.content) &&
res.data.content.length > 0
) {
project.content = res.data.content;
} else {
add_room();
@ -310,62 +294,97 @@ const get_project = async () => {
type: "warning",
});
}
}
};
const delet_room = (item) => {
if (project.content.length === 1) {
ElMessage.warning('至少保留一个。。')
ElMessage.warning("至少保留一个。。");
return;
}
project.content = project.content.filter(ele => {
project.content = project.content.filter((ele) => {
return ele.base_info.room_name !== item.base_info.room_name;
})
save_room();
}
});
};
onMounted(() => {
get_project();
});
const select_room = (item) => {
for (const key in item) {
console.log(key);
current_room_info[key] = item[key];
}
}
};
const add_room = () => {
if (!Array.isArray(project.content)) {
project.content = []
project.content = [];
}
let target = JSON.parse(JSON.stringify(addData));
target.base_info.room_name = "房型" + generateShortUUID();
project.content.push(target);
}
};
const save_room = async () => {
const param = {
action: 1021,
data: project
}
debugger;
data: project,
};
const res = await myApi.getProjects(param);
console.log(res);
if (res.code === 0) {
ElMessage({
message: "更新成功",
message: "保存成功",
type: "success",
});
get_project();
} else {
ElMessage({
message: res.message + '[' + res.data + ']',
message: res.message + "[" + res.data + "]",
type: "warning",
});
}
}
};
const exc = async () => {
const param = {
action: 90001,
data: project,
};
try {
const res = await myApi.download(param);
console.log(res);
if (1) {
//
const blob = new Blob([res.data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
const url = window.URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.download = 'xx.xlsx'; //
document.body.appendChild(link);
link.click();
link.remove();
window.URL.revokeObjectURL(url);
ElMessage({
message: "保存成功",
type: "success",
});
} else {
//
ElMessage({
message: res.message + "[" + res.data + "]",
type: "warning",
});
}
} catch (error) {
//
console.error("Error downloading file:", error);
ElMessage({
message: "下载文件时发生错误",
type: "error",
});
}
};
function generateShortUUID() {
let uuid = '';
const possible = '0123456789ABCDEF';
let uuid = "";
const possible = "0123456789ABCDEF";
for (let i = 0; i < 8; i++) {
uuid += possible.charAt(Math.floor(Math.random() * possible.length));
@ -374,101 +393,128 @@ function generateShortUUID() {
return uuid;
}
const goHome = () => {
save_room();
router.push('home');
}
router.push("home");
};
const lightArr = reactive([{
label: '开关回路',
const lightArr = reactive([
{
label: "开关回路",
value: 0,
}, {
label: '0-10V调光',
key: "switching_circuit",
},
{
label: "0-10V调光",
value: 1,
}, {
label: '前沿调光',
key: "dimming_10v",
},
{
label: "前沿调光",
value: 2,
}, {
label: '后沿调光',
key: "dimming_leading_edge",
},
{
label: "后沿调光",
value: 3,
}, {
label: 'DALI灯',
key: "dimming_trailing_edge",
},
{
label: "DALI灯",
value: 4,
}])
const otherArr = reactive([{
label: '红外',
key: "DALI",
},
]);
const otherArr = reactive([
{
label: "红外",
value: 0,
key: 'PIR'
}, {
label: '双鉴红外',
key: "PIR",
},
{
label: "双鉴红外",
value: 1,
key: 'PIR2'
}, {
label: '门磁',
key: "PIR2",
},
{
label: "门磁",
value: 2,
key: 'Gate'
}, {
label: '窗磁',
key: "Gate",
},
{
label: "窗磁",
value: 3,
key: 'Window'
}, {
label: '门铃',
key: "Window",
},
{
label: "门铃",
value: 4,
key: 'doorbell'
}])
const radioGroup1 = reactive([{
label: '普通三速风机',
key: "doorbell",
},
{
label: "房务",
value: 5,
key: "Housekeeping",
},
]);
const radioGroup1 = reactive([
{
label: "普通三速风机",
value: 0,
}, {
label: '直流无刷风机',
},
{
label: "直流无刷风机",
value: 1,
}, {
label: '三方协议风机',
},
{
label: "三方协议风机",
value: 2,
}])
const radioGroup2 = reactive([{
label: '两管制',
},
]);
const radioGroup2 = reactive([
{
label: "两管制",
value: 0,
}, {
label: '四管制',
},
{
label: "四管制",
value: 1,
}])
const radioGroup3 = reactive([{
label: '两通阀',
},
]);
const radioGroup3 = reactive([
{
label: "两通阀",
value: 0,
}, {
label: '调节阀',
},
{
label: "调节阀",
value: 1,
}])
const radioGroup4 = reactive([{
label: '普通面板(无背光)',
},
]);
const radioGroup4 = reactive([
{
label: "普通面板(无背光)",
value: 0,
}, {
label: '普通面板(带背光)',
},
{
label: "普通面板(带背光)",
value: 1,
}, {
label: '协议面板',
},
{
label: "协议面板",
value: 10,
}])
const radioGroup5 = reactive([{
label: '干接点电机',
},
]);
const radioGroup5 = reactive([
{
label: "干接点电机",
value: 0,
}, {
label: '485电机',
},
{
label: "485电机",
value: 1,
}])
const checkList = reactive([{
label: 'DND',
value: 'DND',
}, {
label: 'MUR',
value: 'MUR',
}, {
label: 'SOS',
value: 'SOS',
}])
},
]);
</script>
<style lang="scss" scoped>
.room-div {
@ -517,7 +563,6 @@ const checkList = reactive([{
background-color: #409eff;
}
}
}
>div:nth-child(2) {
@ -654,6 +699,5 @@ const checkList = reactive([{
background: #409eff;
color: #fff;
}
}
</style>