1 Star 0 Fork 2

Java案例 / 智慧工厂_1

forked from 清婉苏苏 / 智慧工厂 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README

晨晖智能智慧工厂

一、项目功能需求

项目文件结构

├─chenhui(项目主文件)
 ├─public(存放3D模型,json-server文件)
 │  ├─model(模型文件)
 │  ├─server(json-server相关文件)
 │  │  ├─js(json-server数据模拟函数)
 │  │  └─json
 │  └─texture(模型贴图文件)
 └─src(存放试图、工具类、image等)
     ├─API(与服务端对接的接口函数定义)
     ├─assets(本地静态资源)
     │  ├─avatar(静态头像资源)
     │  ├─img(本地图片)
     │  └─video(本地视频示例)
     ├─components(全局组件)
     ├─hooks(自定义钩子)
     ├─layout(框架布局视图)
     ├─mock(暂无他用,文件内容忽略)
     ├─router(路由信息文件)
     ├─static(静态资源文件)
     │  ├─css(全局静态css)
     │  ├─iconfont(iconfont图标)
     ├─store(全局状态文件)
     ├─utils(工具类函数)
     └─views(页面视图)
         ├─front(前台页面视图)
         │  ├─components(局部组件)
         │  └─data(前台数据文件)
         └─manager(中台页面视图)
             ├─dashboard(主页)
             │  ├─analysis(分析页)
             │  │  └─components(分析页局部组件)
             │  └─workbench(工作台)
             │      └─components(工作台局部组件)
             ├─employeeInfo(用户管理)
             ├─permissionInfo(权限管理)
             └─system(系统管理)
                 ├─account(用户)
                 ├─menu(菜单)
                 └─role(角色)
   
 ├─.eslintrc.cjs(eslint配置)
 ├─.gitignore(git提交忽略配置)
 ├─db.json(json-server数据文件)
 ├─index.html(用户页面访问入口)
 ├─jsconfig.json(js配置文件)
 ├─package.json(依赖包管理配置文件)
 ├─package-lock.json(npm锁定安装时的依赖包的版本号)
 ├─postcss.config.js(postcss配置)
 ├─READEME.md(介绍文件)
 ├─routes.json(json-server路由修改文件)
 ├─tailwind.config.js(tailwindcss配置文件)
 └─vite.config.js(vite配置文件)

二、前端项目构建

1、主要框架:vue3组合式api

2、搭建方式:$ npm create vite@latest

3、开发语言:JavaScript,css-->sass,vue

4、开发工具:vscode

5、依赖包

  • axios --请求响应、 -->npm install axios

  • elementPlus --manager页面搭建、 -->npm install element-plus --save

  • pinia --状态持久化、 -->npm install pinia

  • vue-router --路由控制、 -->npm install vue-router@4

  • web-storage-cache --数据缓存、 -->npm install web-storage-cache --save-dev

  • postcss --css代码转换、 -->npm install postcss --save-dev

    ==postcss.config.js配置==

    export default {
      plugins: {
        tailwindcss: {},
        autoprefixer: {},
      },
    }
  • sass --css扩展语言、 -->npm install sass --save-dev

  • tailwindcss --css样式、 -->npm install -D tailwindcss

    ==1、配置tailwind.config.js文件==

    /** @type {import('tailwindcss').Config} */
    export default {
        content: ["./index.html", "./src/*.{vue,js}", "./src/**/*.{vue,js}"],
        theme: {
            extend: {},
        },
        plugins: [],
    }

    ==2、配置index.css文件引入tailwindcss==

    @charset "utf-8";
    
    * {
        margin: 0;
        padding: 0;
        list-style-type: none;
    }
    
    @tailwind base;
    @tailwind components;
    @tailwind utilities;
  • echarts --图形图表库、 -->npm install echarts --save

  • threejs --三维模型视图、 -->npm install three --save

  • vite --项目构建、

    ==vite.config.js配置==

    import {
     defineConfig
    } from 'vite'
    import vue from '@vitejs/plugin-vue'
    import AutoImport from 'unplugin-auto-import/vite'
    import Components from 'unplugin-vue-components/vite'
    import {
     ElementPlusResolver
    } from 'unplugin-vue-components/resolvers'
    import path from 'path';
    
    // https://vitejs.dev/config/
    export default defineConfig({
     plugins: [
      vue(),
      AutoImport({
       resolvers: [ElementPlusResolver()],
      }),
      Components({
       resolvers: [ElementPlusResolver()],
      }),
     ],
     resolve: {
      extensions: [".js", ".json", ".vue", ".mjs", ".wasm"],
      alias: [{
       find: "@",
       replacement: path.join(__dirname, "./src")
      }],
     },
     base: "./",
    })
  • md5 --加密方式、 -->npm install md5 --save

  • video.js --网络视频播放器 -->npm install --save-dev video.js

  • dayjs --时间日期处理 -->npm install dayjs --save

  • unplugin-auto-import --按需自动导入api -->npm install unplugin-auto-import --save-dev

  • unplugin-vue-components --组件自动引入 -->npm install unplugin-vue-components --save-dev

  • autoprefixer --自动补齐css浏览器前缀 -->npm install autoprefixer --save-dev

  • pinia-plugin-persistedstate --状态持久化 -->npm install pinia-plugin-persistedstate --save

  • datav-vue

  • ant-design-vue

6、package.json配置

{
  "name": "chenhui",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview",
    "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore",
    "json-server": "json-server ./public/server/js/index.cjs --routes routes.json"
  },
  "dependencies": {
    "@ant-design/icons-vue": "^7.0.1",
    "@kjgl77/datav-vue3": "^1.7.1",
    "ant-design-vue": "^4.0.6",
    "axios": "^1.6.0",
    "d3": "^7.8.5",
    "dayjs": "^1.11.10",
    "echarts": "^5.4.3",
    "element-plus": "^2.4.1",
    "json-server": "^0.17.4",
    "md5": "^2.3.0",
    "pinia": "^2.1.7",
    "pinia-plugin-persistedstate": "^3.2.0",
    "three": "^0.158.0",
    "vue": "^3.3.7",
    "vue-router": "^4.2.5"
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^4.4.0",
    "autoprefixer": "^10.4.16",
    "eslint": "^8.52.0",
    "eslint-plugin-vue": "^9.18.1",
    "mockjs": "^1.1.0",
    "postcss": "^8.4.31",
    "sass": "^1.69.5",
    "tailwindcss": "^3.3.5",
    "unplugin-auto-import": "^0.16.7",
    "unplugin-vue-components": "^0.25.2",
    "video.js": "^8.6.1",
    "vite": "^4.5.0",
    "vite-plugin-mock": "^3.0.0",
    "web-storage-cache": "^1.1.1"
  },
  "browserslist": [
    "defaults",
    "not ie < 11",
    "last 2 versions",
    "> 1%"
  ],
  "engines": {
    "node": ">=16.5.0",
    "npm": ">=6.14.6"
  }
}

7、store >index.js配置状态持久化

/**
 * pinia的存储区域
 */

import {
    defineStore
} from "pinia";
import WebStorageCache from "web-storage-cache";

const cache = new WebStorageCache({
    storage: window.localStorage
})

export const mainStore = defineStore("main", {
    state() {
        return {
            token: null,
            loginClientInfo: null,
            isCollapse: false,
            historyList: [],
        }
    },
    actions: {
        setToken(token) {
            this.token = token
        },
        setLoginClientInfo(loginClientInfo) {
            this.loginClientInfo = loginClientInfo
        },
        setIsCollapse(flag) {
            this.isCollapse = flag;
        },
        logOut() {
            this.token = null
            this.loginClientInfo = null
        },
        addHistory(item) {
            let index = this.historyList.findIndex(_item => _item.routeName === item.routeName);
            if (index === -1) {
                this.historyList.push(item);
            }
        },
        removeHistoryByRouterName(routeName) {
            let index = this.historyList.findIndex(item => item.routeName === routeName);
            if (index != -1) {
                this.historyList.splice(index, 1);
            }
        }
    },
    // 配置状态的持久化
    persist: {
        key: "chenhui_store",
        storage: {
            getItem: key => cache.get(key),
            // 到期时间默认以秒为单位
            setItem: (key, value) => cache.set(key, value, {
                exp: 60 * 60 * 24
            }),
            removeItem: key => cache.delete(key),
            clear: () => cache.clear()
        },
        //指定需要持久化的字段
        paths: ["token", "loginClientInfo"]
    }
});

8、utils >axiosInstance.js

import axios from "axios";
import router from "@/router";
import {
    mainStore
} from "@/store";

const axiosInstance = axios.create({
    baseURL: "http://localhost:3000"
});

axiosInstance.interceptors.request.use(config => {
    const store = mainStore();
    config.headers["Authorization"] = store.token;
    return config;
})

axiosInstance.interceptors.response.use(resp => {
    if (resp.data.status === "success") {
        return Promise.resolve(resp.data);
    } else {
        console.log("请求成功,服务器响应错误", resp.data);
        return Promise.reject(resp.data);
    }
}, error => {
    console.log("服务器请求失败", error);
    if (error.response.status === 403) {
        router.replace({
            name: "Login",
        })
    }
    return Promise.reject(error);
})

export default axiosInstance;

9、日期格式处理 utils > DateTimeUtils.js

/**
 * 处理日期或时间的工具类
 */
import dayjs from "dayjs";

/**
 * 格式化日期
 * @param {string|Date|Number} _d 
 * @param {string} 格式化的参数
 */
export const formatDateTime = (_d, split = "YYYY-MM-DD HH:mm:ss") => {
    let d = dayjs(_d);
    // 判断一下,是否是一个合法的日期
    if (d.isValid()) {
        return d.format(split);
    } else {
        return "";
    }
}

10、eslint配置

/* eslint-env node */
module.exports = {
    root: true,
    'extends': [
      'plugin:vue/vue3-essential',
      'eslint:recommended'
    ],
    parserOptions: {
      ecmaVersion: 'latest'
    },
    rules: {
      'vue/multi-word-component-names': 0,//取消强制组件命名
    }
  }

三、前后端页面书写

1、前台页面PageView.vue

<template>
    <div class="relative page-view">
        <div id="scene" class="scene"></div>
        <slot></slot>
    </div>
</template>
<script setup>
import { reactive, onMounted } from 'vue';
import CanvasBase from '../utils/CanvasBase';

const data = reactive({
    CanvasBase: {}
})

onMounted(() => {
    data.CanvasBase = new CanvasBase('#scene')
})
</script>
<style lang="scss" scoped>
.page-view {
    width: 100vw;
    height: 100vh;
    overflow: auto;

    .scene {
        width: 100%;
        height: 100%;
        position: absolute !important;
        top: 0;
        bottom: 0;
        left: 0;
        right: 0;
        z-index: 1;

    }
}
</style>

全局组件注册需在main.js文件中添加:app.component("page-view", PageView)

添加完成以后在所有页面都可以通过====标签使用组件。

2、全局组件FrontNav.vue

<template>
    <div class="top flex flex-row h-[64px] w-full bg-[#070b1a]">
        <Header>
            <template #left>
                <div class="box h-[64px] flex flex-row justify-end items-center">
                    <router-link :to="{ name: 'Home' }" custom #default="{ navigate, isActive }">
                        <div @click="navigate" :class="{ selected: isActive }">
                            <span>主界面</span>
                        </div>
                    </router-link>
                    <router-link :to="{ name: 'Blanking' }" custom #default="{ navigate, isActive }">
                        <div @click="navigate" :class="{ selected: isActive }">
                            <span>落料监测</span>
                        </div>
                    </router-link>
                </div>
            </template>
            <template #center>
                <div class="flex flex-col justify-center center text-2xl text-[#fff] h-[75px] relative">
                    <span class="text-center">晨晖智慧工厂系统</span>
                    <dv-decoration5 :dur="4" style="width: 100%;height:100%;position:absolute;top:25px" />
                </div>
            </template>
            <template #right>
                <div class="h-[64px] flex flex-row justify-between items-center">
                    <div class="flex flex-row box">
                        <router-link :to="{ name: 'Staff' }" custom #default="{ navigate, isActive }">
                            <div @click="navigate" :class="{ selected: isActive }">
                                <span>人员监测</span>
                            </div>
                        </router-link>
                        <router-link :to="{ name: 'Equipment' }" custom #default="{ navigate, isActive }">
                            <div @click="navigate" :class="{ selected: isActive }">
                                <span>设备监测</span>
                            </div>
                        </router-link>
                    </div>
                    <div class="login-btn flex flex-row items-center w-[120px]">
                        <template v-if="!loginClientInfo">
                            <a-button type="primary" ghost class="w-[80px] h-[35px]" @click="login">登录</a-button>
                        </template>
                        <template v-else>
                            <div id="components-dropdown-demo-placement">
                                <template v-for="(placement) in placements" :key="placement">
                                    <a-dropdown :placement="placement">
                                        <a-button type="primary" ghost
                                            class="w-[120px] h-[45px] border-none">您好,admin</a-button>
                                        <template #overlay>
                                            <a-menu theme="dark">
                                                <a-menu-item>
                                                    <a rel="noopener noreferrer" @click="toManager">
                                                        后台管理
                                                    </a>
                                                </a-menu-item>
                                                <a-menu-item>
                                                    <a rel="noopener noreferrer" @click="logOut">
                                                        退出登录
                                                    </a>
                                                </a-menu-item>
                                            </a-menu>
                                        </template>
                                    </a-dropdown>
                                </template>
                            </div>
                        </template>
                    </div>
                </div>
            </template>
        </Header>
    </div>
</template>
<script setup>
import { useRouter } from "vue-router"
import { ref } from 'vue'
import Header from '@/layout/header.vue'
import { ElMessage, ElMessageBox } from "element-plus";
// import { mainStore } from "@/store";
// import { storeToRefs } from "pinia";

const placements = ['bottom'];

const router = useRouter();
// const store = mainStore();

// const { loginClientInfo } = storeToRefs(store);

const loginClientInfo = ref(true)

const toManager = () => {
    router.push({ name: 'workbench' })
}

const login = () => {
    router.push({ name: 'Login' })
}

const logOut = () => {
    ElMessageBox.confirm('确定要退出登录吗?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
    }).then(() => {
        // 退出登录
        router.push({ name: 'Login' })
    }).catch(() => {
        ElMessage({
            message: '取消退出登录',
            type: 'warning',
            duration: 1000
        })
    })
}

</script>
<style lang="scss" scoped>
.top {
    width: 100%;
    height: 64px;
    //background-image: url(../assets/img/top2.png) center 3px no-repeat;
    padding: 0 48px;
    box-sizing: border-box;
    z-index: 2;

    .box {
        >div {
            width: 140px;
            height: 58px;
            line-height: 64px;
            font-size: 18px;
            cursor: pointer;
            text-align: center;
            color: #fff;

            &.selected {
                background: linear-gradient(to bottom, #061625, #037C8D);
                border-bottom: 6px solid #00F7FF;
                border-radius: 0 0 6px 6px;
            }
        }
    }
}

</style>

3、管理中台页面ManagerView.vue

<template>
    <div class="manager-view">
        <slot></slot>
    </div>
</template>

<script setup>

</script>

<style lang="scss" scoped>
.manager-view {
    width: 100vw;
    height: 100vh;
    overflow: auto;
}
</style>

4、管理中台全局组件ManagerMenu.vue

<template>
    <el-menu background-color="#031529" active-text-color="#409eff" default-color="#304156" text-color="#fff"
        class="el-menu-vertical-demo w-[220px]" :unique-opened="false" :collapse-transition="false" :router="true"
        :collapse="isCollapse">
        <el-menu-item>
            <el-icon size="28px">
                <img src="@/assets/img/logo.svg" />
            </el-icon>
            <span class="ml-[5px]" v-show="!isCollapse" @click="$router.replace({ name: 'workbench' })">晨晖智慧工厂管理后台</span>
        </el-menu-item>
        <el-sub-menu index="a">
            <template #title>
                <svg-icon class="icon" iconName="icon-workbench"></svg-icon>
                <span>DashBorad</span>
            </template>
            <el-menu-item index="/ManagerHome/workbench">
                <template #title>
                    <svg-icon class="icon" iconName="icon-gongzuotai"></svg-icon>
                    <span>工作台</span>
                </template>
            </el-menu-item>
            <el-menu-item index="/ManagerHome/analysis">
                <template #title>
                    <svg-icon class="icon" iconName="icon-analysis"></svg-icon>
                    <span>分析页</span>
                </template>
            </el-menu-item>
        </el-sub-menu>
        <el-sub-menu index="b">
            <template #title>
                <svg-icon class="icon" iconName="icon-renyuanguanli"></svg-icon>
                <span>用户管理</span>
            </template>
            <el-menu-item index="/ManagerHome/EmployeeInfoList">
                <svg-icon class="icon" iconName="icon-renyuanxinxi"></svg-icon>
                <template #title>用户信息</template>
            </el-menu-item>
            <el-menu-item index="/ManagerHome/EditEmployee">
                <svg-icon class="icon" iconName="icon-xiugairenyuanxinxi"></svg-icon>
                <template #title>修改用户信息</template>
            </el-menu-item>
            <el-menu-item index="/ManagerHome/AddEmployee">
                <svg-icon class="icon" iconName="icon-xinzengrenyuan-"></svg-icon>
                <template #title>新增用户</template>
            </el-menu-item>
        </el-sub-menu>
        <!-- 后面在这里要加权限判断和角色判断 -->
        <el-sub-menu index="c">
            <template #title>
                <svg-icon class="icon" iconName="icon-shezhi01"></svg-icon>
                <span>系统管理</span>
            </template>
            <el-menu-item index="/ManagerHome/account">
                <svg-icon class="icon" iconName="icon-account"></svg-icon>
                <template #title>账号管理</template>
            </el-menu-item>
            <el-menu-item index="/ManagerHome/role">
                <svg-icon class="icon" iconName="icon-role"></svg-icon>
                <template #title>角色管理</template>
            </el-menu-item>
            <el-menu-item index="/ManagerHome/menu">
                <svg-icon class="icon" iconName="icon-menu"></svg-icon>
                <template #title>菜单管理</template>
            </el-menu-item>
            <el-menu-item index="/ManagerHome/updatePwd">
                <svg-icon class="icon" iconName="icon-updatePwd"></svg-icon>
                <template #title>修改密码</template>
            </el-menu-item>
            <el-menu-item index="/ManagerHome/sysLogs">
                <svg-icon class="icon" iconName="icon-sysLogs"></svg-icon>
                <template #title>系统日志</template>
            </el-menu-item>
        </el-sub-menu>
        <el-sub-menu index="d">
            <template #title>
                <svg-icon class="icon" iconName="icon-quanxiankongzhi"></svg-icon>
                <span>权限管理</span>
            </template>
            <el-menu-item index="/ManagerHome/PermissionList">
                <svg-icon class="icon" iconName="icon-quanxianxinxi"></svg-icon>
                <template #title>权限信息</template>
            </el-menu-item>
            <el-menu-item index="/ManagerHome/AddPermission">
                <svg-icon class="icon" iconName="icon-xinzengquanxian"></svg-icon>
                <template #title>新增权限</template>
            </el-menu-item>
            <el-menu-item index="/ManagerHome/EditPermission">
                <svg-icon class="icon" iconName="icon-bianjiquanxian"></svg-icon>
                <template #title>编辑权限</template>
            </el-menu-item>
        </el-sub-menu>
    </el-menu>
</template>
<script setup>
import { ref } from "vue";
import { mainStore } from "../store";
import { useRouter } from "vue-router";
import { storeToRefs } from "pinia";

const isActive = ref(true);
const router = useRouter();

const store = mainStore();

const { isCollapse, loginClientInfo } = storeToRefs(store);

</script>
<style lang="scss" scoped>
:deep(.el-menu-vertical-demo:not(.el-menu--collapse)) {
    width: 240px;
    min-height: 600px;
}

:deep(.el-menu) {
    border-right: none !important;
}

.icon {
    font-size: 16px;
    margin-right: 8px;
}

:deep(.el-menu-item.is-active){
    //background-color: #121010 !important;
}
</style>

5、iconfont图标组件

<template>
    <svg :class="svgClass" aria-hidden="true">
        <use :xlink:href="iconClassName" :fill="color" />
    </svg>
</template>
<script setup lang="ts">
import { computed } from 'vue';
const props = defineProps({
    iconName: {
        type: String,
        required: true
    },
    className: {
        type: String,
        default: ''
    },
    color: {
        type: String,
        default: '#409eff'
    },
});
// 图标在 iconfont 中的名字
const iconClassName = computed(() => {
    return `#${props.iconName}`;
})
// 给图标添加上类名
const svgClass = computed(() => {
    if (props.className) {
        return `svg-icon ${props.className}`;
    }
    return 'svg-icon';
});
</script>
<style scoped>
.svg-icon {
    width: 1em;
    height: 1em;
    position: relative;
    fill: currentColor;
    vertical-align: -2px;
}
</style>

四、数据接口文档

1、前台页面数据请求

1.1 home页面数据请求

(1) 双目视频数据

(2) 红外视频数据

(3) 环境参数

(4) 实时趋势

(5) 高清视频

1.2 blanking页面数据请求

(1) 实时监控视频数据

(2) 历史信息数据

(3) 落料信息图片数据

(4) 落料信息描述数据

1.3 staff页面数据请求

(1) 双目视频数据

(2) 安全帽佩戴图片数据

(3) 工装正确穿着图片数据

(4) 人员行为图片数据

(5) 信息总计表格数据

1.4 equipment页面数据请求

(1) 设备红外图视频数据

(2) 设备温度表格数据

(3) 声音波形音频文件

(4) 声音信息甄别数据

2、管理中台页面数据请求

空文件

简介

vue3+threejs+ant design+elementplus 展开 收起
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
1
https://gitee.com/hean11/smart-factory_1.git
git@gitee.com:hean11/smart-factory_1.git
hean11
smart-factory_1
智慧工厂_1
master

搜索帮助