Compare commits

...

11 Commits

Author SHA1 Message Date
04a8c08904 up 2024-05-19 15:34:54 +08:00
ef313b9399 增加设备保养 2024-05-07 19:37:20 +08:00
162ef0ef26 修改设备工单 2024-04-30 16:08:07 +08:00
2b8797a1ac 调整项目框架 2024-04-23 11:48:55 +08:00
01ea333978 提交代码 2024-04-11 18:54:43 +08:00
e37d0e4112 提交代码 2024-03-13 16:07:11 +08:00
d022e33da9 代码提交 2024-02-19 16:53:38 +08:00
a93b95e814 冲突 2024-01-16 19:00:14 +08:00
d64dc3c4d6 生产工单 2024-01-16 18:58:20 +08:00
09db3c322f Merge branch 'master' of ssh://git.tool.dwoodauto.com:2221/long/mes_mobile 2024-01-16 18:52:52 +08:00
54d1b52fb8 自定义tabbar 2024-01-16 18:52:23 +08:00
71 changed files with 6714 additions and 440 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

252
App.vue
View File

@ -3,7 +3,10 @@
onLaunch: function() { onLaunch: function() {
console.warn('当前组件仅支持 uni_modules 目录结构 ,请升级 HBuilderX 到 3.1.0 版本以上!') console.warn('当前组件仅支持 uni_modules 目录结构 ,请升级 HBuilderX 到 3.1.0 版本以上!')
console.log('App Launch') console.log('App Launch')
// plus.navigator.setFullscreen(true);//隐藏状态栏 // #ifndef MP-WEIXIN
uni.hideTabBar();
// #endif
}, },
onShow: function() { onShow: function() {
console.log('App Show') console.log('App Show')
@ -15,35 +18,238 @@
</script> </script>
<style lang="scss"> <style lang="scss">
/*每个页面公共css */ /* 每个页面公共css */
@import '@/uni_modules/uni-scss/index.scss'; @import '@/uni_modules/uni-scss/index.scss';
/* #ifndef APP-NVUE */ /* #ifndef APP-NVUE */
@import '@/static/customicons.css'; @import '@/static/customicons.css';
// 设置整个项目的背景色 @import 'uni.scss';
page {
background-color: #060B26;
color: #fff;
}
/* #endif */ /* #endif */
/* 设置整个项目的背景色 */
page {
background-color: $uni-bg-color-default !important;
color: $uni-text-color-inverse;
}
.example-info { .example-info {
font-size: 14px; font-size: 14px;
color: #333; color: $uni-text-color;
padding: 10px; padding: 10px;
} }
.pagepaddings{padding: 14px;} .page_padding{padding: 14px;}
//内容框 .page_content{padding: 0 12px 10px;}
.contentboxsty{border-radius: 8px;background: #1C2755;} /* 内容框 */
//没有底部边框 .contentboxsty{border-radius: 8px;background: $uni-bg-color-primary;}
/* 没有底部边框 */
.noborbot{border-bottom:none !important} .noborbot{border-bottom:none !important}
.t-icon{background-repeat: no-repeat;}
.icon22{width: 22px;height: 22px;}
.paddrigth5{padding-right: 5px;}
//字体大小
.font12{font-size: $uni-font-size-sm;}
.font13{font-size:13px;}
.font14{font-size: $uni-font-size-base;}
.font_bold{font-weight: bold;}
//文字颜色
.text_color_black{color: #000;}
.t-icon{background-repeat: no-repeat;}
.icon22{width: 22px;height: 22px;}
/* 字体大小 */
.font12{font-size: 12px;}
.font13{font-size: 13px;}
.font14{font-size: 14px;}
.font15{font-size: 15px;}
.font18{font-size: 18px;}
.font20{font-size: 20px;}
.font22{font-size: 22px;}
.font24{font-size: 24px;}
.font35{font-size: 35px;}
.font_bold{font-weight: bold;}
/* 文字颜色 */
.text_color_black{color: $uni-text-color-default;}
.theme_color{color: $uni-text-color-primary } //主题绿
/* 按钮颜色 */
.but_color{background: $uni-color-primary !important;}
/* 布局 */
.flex_layout{display: flex;}
.flex1{flex: 1;}
.comView{flex: 1;overflow: hidden;}
/* paddind */
.padd_rigth5{padding-right: 5px;}
.padd_bot6{padding-bottom: 6px;}
.padd_top12{padding-top:12px;}
.padd_rigth12{padding-right: 12px;}
.padd_bot12{padding-bottom: 12px;}
.padd_left12{padding-left:12px;}
.padd12{padding: 12px;}
/* margin */
.mar_top12{margin-top: 12px;}
.mar_bot12{margin-bottom: 12px;}
.page_list{margin-bottom: 12px;padding:0 12px;}
/* 有详情的列表 */
.detail_list{
margin-bottom: 12px;
.list_top{
display: flex;
padding:12px;
font-size: 14px;
border-radius: 8px 8px 0px 0px;
background: linear-gradient(90deg, rgba(61, 84, 176, 0.70) 5.83%, rgba(58, 77, 158, 0.00) 73.76%);
.top_left{flex: 1;display: flex;align-items: center; font-weight: bold;}
.top_right{display: flex;align-items: center;font-weight: bold;}
.top_right .arrow{margin-left: 5px;font-weight: normal;}
}
.list_content{padding:12px;position: relative;}
.list_content .card_right{position: absolute;top: 12px;right: 12px;}
}
.page_list .card_right, .detail_list .card_right{
display: flex;
flex-direction: column;
.status{
background: $uni-bg-color-success-dark;
color: $uni-text-color-success;
padding: 3px 10px;
border-radius: 4px;
font-size: 12px;
}
.success{
background: $uni-bg-color-success-dark;
color: $uni-text-color-success;
padding: 3px 10px;
border-radius: 4px;
font-size: 12px;
}
.warning{
background: $uni-bg-color-warning-dark;
color: $uni-text-color-warning;
padding: 3px 10px;
border-radius: 4px;
font-size: 12px;
}
.error{
background: $uni-bg-color-error-dark;
color: $uni-text-color-danger;
padding: 3px 10px;
border-radius: 4px;
font-size: 12px;
}
}
.flexBox .detail_list:first-child{
margin-top: 2px;
}
/* 检索固定 */
.headerViewFixed{
background: $uni-bg-color-default;
}
/* 页面固定按钮 */
.bottom_but{
width: 100%;
position: fixed;
bottom: 0px;
z-index: 90;
background-color: #060B26;
border-top: 1px solid #2E3249;
height: 80px;
view{width: 50%;text-align: center;margin: 0 20px;border-radius: 19px;background: #DDD;line-height: 38px;height: 38px;margin-top: 6px;}
}
/* 底部固定添加按钮 */
.page_bottom_button{
width: 100%;position: fixed;bottom: 0px;background-color: #060B26;border-top: 1px solid #2E3249;height: 80px;
.page_add{display:flex;justify-content:center;align-items: center;margin: 7px 20px;border-radius: 17.5px;background: #1C2755;height: 38px;}
.page_add .icon{margin-right: 4px;}
}
.bot_padding{padding-bottom: 100px;}
.placeholderStyle{
color: $uni-text-color-placeholder;
font-size: 14px;
}
/* 圆形进度条 */
.progressBg{
position: absolute;
left: 2px;
top: 2px;
z-index: 20;
background: $uni-bg-color-primary;
width: 98px;
height: 98px;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
border-radius: 50%;
}
.progressBox{
background: $uni-bg-color-default-dark;
width: 90px;
height: 90px;
border-radius: 50%;
margin: 0 auto;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.circle-progress {
width: 102px;
height: 102px;
position: relative;
overflow: hidden;
border-radius: 50%;
background: $uni-bg-color-primary;
}
.circle-progress__bar {
position: absolute;
z-index: 10;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 100%;
height: 100%;
border-radius: 50%;
background-image: conic-gradient($uni-color-primary 0%, $uni-color-primary var(--progress), transparent 0);
}
/* 选择日期时间颜色的配置 */
.input_date .uni-date-x .uni-date__x-input{
color: $uni-text-color-tip;
}
.haveTime .uni-date-x .uni-date__x-input{
color: $uni-text-color-inverse;
}
/* 修改 日期时间选择组件 */
.input_date ::v-deep .uni-date-changed .uni-datetime-picker--btn{
background: $uni-color-primary !important;
}
.input_date ::v-deep .uni-calendar-item--checked{
background: $uni-color-primary !important;
}
/* 自定义 复选框-背景颜色 */
checkbox.checkbox-custom[checked] .wx-checkbox-input , checkbox.checkbox-custom.checked .uni-checkbox-input{
background-color: $uni-color-primary;
border-color: $uni-color-primary;
color: $uni-text-color-inverse;
}
::v-deep .checkbox_indeterminate::before{
content: '';
position: absolute;
top: 50%;
left: calc(50% - 2px);
z-index: 80;
transform: translate(-50%,-50%);
width: 12px;
height: 2px;
border-radius: 4px;
background: $uni-bg-color-whith;
}
::v-deep .checkbox_indeterminate::after {
content: "";
position: absolute;
top: 0;
left: 0;
z-index: 10;
width: calc(100% - 5px);
height: 100%;
border-radius: 3px;
background-color: $uni-color-primary;
}
</style> </style>

Binary file not shown.

Binary file not shown.

BIN
components/.DS_Store vendored Normal file

Binary file not shown.

View File

@ -0,0 +1,400 @@
<template>
<view class="calendarBox">
<view class="content-top">
<view class="content-left" @click="prveClick">
<text class="iconfont icon-gengduo more_icon"></text>
</view>
<view class="content-scroll">
<view class="center-cut-menu">
<scroll-view scroll-x="true" show-scrollbar="false" scroll-with-animation="true" :scroll-left="scrollLeft" class="scroll-view horizontalScrollView" :class="{'monthScroll':params.date!=='day'}" >
<view class="scroll-item" :style="'width:'+itemWidth+'px'" v-for="(item, index) in titleList" :key="index" @click="changeMenu(index)">
<view class="viewItem" :class="{'active':curIndex == index,'monthViewItem':params.date !=='day','todoayView':item.todoay}">
<text class="item-text">{{item.name}}</text>
<text class="item-date" v-if="params.date == 'day'">{{item.text}}</text>
<text class="todoay" v-if="item.todoay"></text>
</view>
</view>
</scroll-view>
</view>
</view>
<view class="content-right" @click="nextClick">
<text class="iconfont icon-gengduo"></text>
</view>
</view>
<swiper v-if="params.date!='day'" class="swiper-box-list" circular="true" easing-function="linear" :current="curIndex" @change="swiperChange" :style="'height:'+swiperHeight+'px'">
<swiper-item class="swiper-topic-list" v-for="(item,index) in titleList" :key="index">
<view :style="'height:'+swiperHeight+'px'" v-if="curIndex == index">
<view class="swiper-item padd_top12 font14">
<view class="device_row" v-for="(em,inde) in item.data" :key="inde">
<view class="rowView" :class="{'active':inde==0,'todoayView':em.todoay}">
<text class="name font_bold">{{em.text}}</text>
<text class="text">{{em.name}}</text>
<text v-if="em.todoay" class="todoay"></text>
</view>
</view>
</view>
</view>
</swiper-item>
</swiper>
</view>
</template>
<script>
export default{
data(){
return{
params:this.params,
curIndex:0,
scrollLeft:0,
swiperHeight:0,
itemWidth:53,
itemColumn:5,
titleList:[
{name:'日',date:11,text:''},
{name:'一',date:12,text:''},
{name:'二',date:13,text:''},
{name:'三',date:14,text:''},
{name:'四',date:15,text:''},
{name:'五',date:16,text:''},
{name:'六',date:17,text:''},
],
}
},
inject:['params','changeDateText'],
watch:{
'params.date':{
handler(val){
this.params.date = val;
this.itemColumn = val=='day'?5:4
this.setTitle();
this.getScrollW();
this.getSwiperH();
},
immediate:false,
}
},
mounted() {
this.setTitle();
},
methods:{
getScrollW() {
let itemWidth = 0;
let query = uni.createSelectorQuery().in(this);
query.select('.scroll-view').boundingClientRect(data => {
this.itemWidth = (data.width/this.itemColumn).toFixed(0);
itemWidth = (data.width/this.itemColumn).toFixed(0);
this.getItemWidth(itemWidth);
}).exec();
},
getSwiperH(){
if(this.params.date!='day'){
setTimeout(()=>{
let query = uni.createSelectorQuery().in(this);
query.select('.swiper-item').boundingClientRect(data => {
if(data){
this.swiperHeight = data.height;
}else{
this.getSwiperH();
}
}).exec();
},100)
}
},
getItemWidth(num){
let query = uni.createSelectorQuery().in(this);
query.selectAll('.scroll-item').boundingClientRect(data => {
let dataLen = data.length;
for (let i = 0; i < dataLen; i++) {
this.titleList[i].width = Number(num);
this.titleList[i].left = Number(num) + Number(data[i].left);
}
}).exec();
},
// 获取数据
setTitle(){
if(this.params.date == 'day'){
let list = this.$wf.getDatesOfWeek();
let todoay = this.$wf.getToday();
list.forEach(item=>{
if(item.date == todoay){
item.todoay = true;
}
item.text = item.date.split('-')[2];
})
if(this.curIndex >= list.length){
this.curIndex = list.length - 1;
}
this.titleList = list;
}
if(this.params.date == 'week'){
let list = [];
let arr = this.$wf.getWeeksOfMonth();
arr.forEach((item,index)=>{
let date = item.find(em=> em!==null && em!==undefined);
let todoay = this.$wf.getToday();
item.forEach(em=>{
if(em){
if(em.date == todoay){
em.todoay = true;
}
em.text = em.date.split('-')[2];
em.name = '星期'+em.name;
}
})
list.push({
name:'第'+this.$wf.numberToChineseLower(Number(index+1))+'周',
date:date.date,
data:item.filter(em=> em!==null),
})
})
if(this.curIndex >= list.length){
this.curIndex = list.length - 1;
}
this.titleList = list;
}
if(this.params.date == 'month'){
let list = [];
let arr = this.$wf.getCurrentYearData();
arr.forEach((item,index)=>{
let weeks = [];
item.weeks.forEach((em,ind)=>{
let dateList = em.filter(em=> em!==null);
weeks.push({
data:dateList,
text:dateList[0].date.split('-')[2],
name:'第'+Number(ind+1)+'周',
date:dateList[0].date,
})
})
list.push({
name:this.$wf.numberToChineseLower(Number(item.month))+'月',
date:weeks[0].date,
data:weeks,
})
})
this.titleList = list;
}
this.getScrollW();
this.changeDate();
},
// 选择标题
changeMenu(index) {
this.curIndex = index;
this.scrollLeft = 0;
for (let i = 0; i < index - 1; i++) {
this.scrollLeft += this.titleList[i].width;
};
this.changeDate(this.titleList[index].date);
if(this.params.date!='day'){
this.getSwiperH();
}
},
swiperChange(e) {
let index = e.detail.current;
this.changeMenu(index);
},
prveClick(){
if(this.params.date == 'day'){
let date = String(this.titleList[0].date);
let list = this.$wf.getPreviousWeekDatesWithDays(date);
list.forEach(item=>{
item.text = item.date.split('-')[2];
})
this.titleList = list;
}
if(this.params.date == 'week'){
// 获取本月的选中周日期
let date = this.titleList[this.curIndex];
let countNum = this.$wf.getPreviousMonthWeekCount(String(date.date));
if(this.curIndex >= countNum){
this.curIndex = countNum-1;
}
let list = [];
let arr = this.$wf.getPreviousMonthGroupedByWeek(String(date.date));
arr.forEach((item,index)=>{
let date = item.find(em=> em!==null && em!==undefined);
item.forEach(em=>{
if(em){
em.text = em.date.split('-')[2];
em.name = '星期'+em.name;
}
})
list.push({
name:'第'+this.$wf.numberToChineseLower(Number(index+1))+'周',
date:date.date,
data:item.filter(em=> em!==null),
})
})
this.titleList = list;
}
if(this.params.date == 'month'){
// 获取本年的选中周日期
let date = this.titleList[this.curIndex];
let list = [];
let arr = this.$wf.getPreviousYearData(String(date.date));
arr.forEach((item,index)=>{
let weeks = [];
item.weeks.forEach((em,ind)=>{
let dateList = em.filter(em=> em!==null);
weeks.push({
data:dateList,
text:dateList[0].date.split('-')[2],
name:'第'+Number(ind+1)+'周',
date:dateList[0].date,
})
})
list.push({
name:this.$wf.numberToChineseLower(Number(item.month))+'月',
date:weeks[0].date,
data:weeks,
})
})
this.titleList = list;
}
this.getScrollW();
this.changeDate();
if(this.params.date!='day'){
this.getSwiperH();
}
},
nextClick(){
if(this.params.date == 'day'){
let date = String(this.titleList[this.titleList.length -1].date);
let list = this.$wf.getNextWeekDatesWithDays(date);
list.forEach(item=>{
item.text = item.date.split('-')[2];
})
this.titleList = list;
}
// 获取下一个月所有周
if(this.params.date == 'week'){
// 获取本月的选中周日期
let date = this.titleList[this.curIndex];
let countNum = this.$wf.getNextMonthWeekCount(String(date.date));
if(this.curIndex >= countNum){
this.curIndex = countNum-1;
}
let list = [];
let arr = this.$wf.getNextMonthGroupedByWeek(String(date.date));
arr.forEach((item,index)=>{
let date = item.find(em=> em!==null && em!==undefined);
item.forEach(em=>{
if(em){
em.text = em.date.split('-')[2];
em.name = '星期'+em.name;
}
})
list.push({
name:'第'+this.$wf.numberToChineseLower(Number(index+1))+'周',
date:date.date,
data:item.filter(em=> em!==null),
})
})
this.titleList = list;
}
// 获取下一年的日期
if(this.params.date == 'month'){
let date = this.titleList[this.curIndex];
let list = [];
let arr = this.$wf.getNextYearData(String(date.date));
arr.forEach((item,index)=>{
let weeks = [];
item.weeks.forEach((em,ind)=>{
let dateList = em.filter(em=> em!==null);
weeks.push({
data:dateList,
text:dateList[0].date.split('-')[2],
name:'第'+Number(ind+1)+'周',
date:dateList[0].date,
})
})
list.push({
name:this.$wf.numberToChineseLower(Number(item.month))+'月',
date:weeks[0].date,
data:weeks,
})
})
this.titleList = list;
}
this.getScrollW();
this.changeDate();
if(this.params.date!='day'){
this.getSwiperH();
}
},
// 修改时间的阶段
changeDate(item){
let text = null;
if(this.titleList[this.curIndex] == undefined){
text = this.titleList[this.titleList.length -1].date;
this.current = this.titleList.length -1;
}else{
text = this.titleList[this.curIndex].date;
}
if(item){
text = item
}
let month = text.split('-')[0] + '-' + text.split('-')[1]
this.changeDateText(month);
}
}
}
</script>
<style scoped lang="scss">
.content-top{
display: flex;
align-items: center;
.content-left{flex-basis: 30px;text-align: center;
.more_icon{display: inline-block;transform: scaleX(-1);}
}
.content-scroll{flex: 1;overflow: hidden;}
.center-cut-menu {width: 100%;height: 50px;display: flex;align-items: center;
.scroll-view {height: 50px;white-space: nowrap;
.scroll-item {height: 100%;padding: 0 5px;display: inline-block;text-align: center;box-sizing: border-box;
.viewItem{
position: relative;
font-size: 14px;height: 100%;display: flex;flex-direction: column;align-items: center;justify-content: center;
border: 1px solid $uni-color-primary;box-sizing: border-box;border-radius: 8px;
}
.monthViewItem{
border: none;
border-radius: 40px;
}
.active {
background: $uni-color-primary;
}
.todoay{
display: flex;align-items: center;justify-content: center;background: $uni-bg-color-success;
position: absolute;top: 2px;right: 2px;z-index: 20;
border-radius: 2px;width: 12px;height: 12px;font-size: 8px;
}
}
}
.monthScroll{height: 27px;}
}
.content-right{flex-basis: 30px;text-align: center;}
}
.swiper-box-list{height: 240px;padding:0 12px;
.swiper-item{display: flex;flex-direction: row;flex-wrap: wrap;}
.device_row{display: flex;flex-direction: column;width: 33%;justify-content: center;align-items: center;margin-bottom: 12px;height: 70px;box-sizing: border-box;padding: 0 8px;position: relative;
.name{margin-bottom: 6px;}
.rowView{display: flex;flex-direction: column;justify-content: center;align-items: center;height: 100%;width: 100%;padding: 12px 0;box-sizing: border-box;position: relative;}
.todoayView{padding: 0 8px; background: $uni-bg-color-default-dark; box-sizing: border-box;border-radius: 8px;}
.active{background: $uni-bg-color-info;border-radius: 8px;}
.todoay{position: absolute;top: -5px;right: -5px;z-index: 20;display: flex;align-items: center;justify-content: center;background: $uni-bg-color-success;width: 16px;height: 16px;border-radius: 3px;font-size: 10px;}
}
}
</style>

Binary file not shown.

View File

@ -0,0 +1,123 @@
<template>
<view class="progress_box">
<canvas class="progress_bg" canvas-id="cpbg"></canvas>
<canvas class="progress_bar" canvas-id="cpbar"></canvas>
<view class="progress_txt">
<view class="progress_info">{{ progress_txt }}%</view>
<text class="progress_title">{{title}}</text>
</view>
</view>
</template>
<script>
export default {
props:{
progress_txt:{
type: Number,
default:0
},
title:{
type:String,
default: ''
},
width:{
type:Number,
defauit:''
},
height:{
type:Number,
defauit:''
}
},
mounted: function() {
this.drawProgressbg();
this.drawCircle(this.progress_txt); //参数为1-100
this.style(this.width,this.height);
},
methods: {
style:function(width,height){
// console.log(width,height)
// document.getElementById("cpbg").style.width = width+"px";
// cpbgA.style.width = width+"px";
// cpbgA.style.height = height+"px";
// var cpbarA = document.getElementById("cpbar");
// cpbarA.style.width = width+"px";
// cpbarA.style.height = height+"px";
},
drawProgressbg: function() {
// 自定义组件实例 this ,表示在这个自定义组件下查找拥有 canvas-id 的 <canvas/>
var ctx = uni.createCanvasContext('cpbg', this);
ctx.setLineWidth(6); // 设置圆环的宽度
ctx.setStrokeStyle('#E9E9E9'); // 设置圆环的颜色
ctx.setLineCap('round'); // 设置圆环端点的形状
ctx.beginPath(); //开始一个新的路径
ctx.arc(110, 110, 70, 0.75 * Math.PI, 0.25 * Math.PI, false);
//设置一个原点(110,110)半径为100的圆的路径到当前路径
ctx.stroke(); //对当前路径进行描边
ctx.draw();
},
drawCircle: function(step) {
var ctx = uni.createCanvasContext('cpbar', this);
// 进度条的渐变(中心x坐标-半径-边宽中心Y坐标中心x坐标+半径+边宽中心Y坐标)
var gradient = ctx.createLinearGradient(28, 55, 192, 55);
gradient.addColorStop('0', '#009688');
// gradient.addColorStop('1.0', '#FF3B1D');
ctx.setLineWidth(6);
ctx.setStrokeStyle(gradient);
ctx.setLineCap('round');
ctx.beginPath();
// 参数step 为绘制的百分比
step = 0.015 * step + 0.75;
if (step >= 2) {
step = step % 2;
}
ctx.arc(110, 110, 70, 0.75 * Math.PI, step * Math.PI, false);
ctx.stroke();
ctx.draw();
},
}
};
</script>
<style>
.progress_box {
position: relative;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
}
.progress_bg {
position: absolute;
width: 220px;
height: 220px;
}
.progress_bar {
width: 220px;
height: 220px;
}
.progress_txt {
position: absolute;
font-size: 28upx;
color: #999999;
}
.progress_info {
font-size: 36upx;
padding-left: 16upx;
letter-spacing: 2upx;
font-size: 52upx;
color: #fff;
}
.progress_titleP{
color: #BFBFBF;
}
.progress_dot {
width: 16upx;
height: 16upx;
border-radius: 50%;
background-color: #fb9126;
}
</style>

View File

@ -4,7 +4,7 @@
<!-- 针对中间的导航栏 通过true来判断控制类名和样式 --> <!-- 针对中间的导航栏 通过true来判断控制类名和样式 -->
<view class="tabbar-item" v-for="(item, index) in tabbarList" :class="[item.centerItem ? 'center-item' : '']" @click="changeItem(item)" :key="index"> <view class="tabbar-item" v-for="(item, index) in tabbarList" :class="[item.centerItem ? 'center-item' : '']" @click="changeItem(item)" :key="index">
<view class="item-top"> <view class="item-top">
<image :src="currentItem == item.id ? item.selectIcon : item.icon"></image> <image class="img" :src="currentItem == item.id ? item.selectIcon:item.icon"></image>
</view> </view>
<!-- 通过三元判断控制类名 达到控制选中和未选中的样式 --> <!-- 通过三元判断控制类名 达到控制选中和未选中的样式 -->
<view class="item-bottom" :class="[currentItem == item.id ? 'item-active' : '']"> <view class="item-bottom" :class="[currentItem == item.id ? 'item-active' : '']">
@ -31,25 +31,25 @@ export default {
{ {
id: 0, id: 0,
path: '/pages/index/index', path: '/pages/index/index',
// icon: '/static/template.png', icon: '/static/indexA.png',
// selectIcon: '/static/templateHL.png', selectIcon: '/static/indexB.png',
text: '首页', text: '首页',
centerItem: false centerItem: false
}, },
{ {
id: 1, id: 1,
path: '/pages/midell/index', path: '',
// icon: '/static/api.png', icon: '/static/sweep.png',
// selectIcon: '/static/apiHL.png', selectIcon: '',
text: '中间', text: '扫一扫',
// 通过类名class控制样式大小 // 通过类名class控制样式大小
centerItem: true centerItem: true
}, },
{ {
id: 2, id: 2,
path: '/pages/mine/index', path: '/pages/person/person',
// icon: '/static/component.png', icon: '/static/personB.png',
// selectIcon: '/static/componentHL.png', selectIcon: '/static/personA.png',
text: '我的', text: '我的',
centerItem: false centerItem: false
} }
@ -58,38 +58,71 @@ export default {
}, },
mounted () { mounted () {
this.currentItem = this.currentPage this.currentItem = this.currentPage
// 隐藏原来的tabBar导航栏
uni.hideTabBar()
}, },
methods: { methods: {
changeItem (item) { changeItem (item) {
let _this = this if(item.centerItem){
//_this.currentItem = item.id; this.scanQRCode();
uni.switchTab({ return
url: item.path }
}) uni.switchTab({
} url: item.path
})
},
scanQRCode(){
uni.scanCode({
success: (res) => {
console.log('扫码结果:' + res.result);
uni.showModal({
title: '扫码结果',
content: res.result,
showCancel: false
});
},
fail: (err) => {
console.error('扫码失败:' + err);
uni.showToast({
title: '扫码失败',
icon: 'none'
});
}
});
}
} }
}; };
</script> </script>
<style lang="less" scope> <style lang="scss" scope>
view { view {
padding: 0; padding: 0;
margin: 0; margin: 0;
box-sizing: border-box; box-sizing: border-box;
} }
.tabbar-container::before{
content: '';
position: absolute;
left: 10%;
top: 0;
z-index: 10;
height: 1px;
width: 80%;
background-image: linear-gradient(90deg, $uni-border-color-default, $uni-color-primary 50%, $uni-border-color-default);
background-size: 100% 1px;
background-repeat:no-repeat;
z-index: 1;
}
.tabbar-container { .tabbar-container {
position: fixed; position: fixed;
bottom: 0rpx; bottom: 0rpx;
left: 0rpx; left: 0rpx;
width: 100%; width: 100%;
height: 110rpx; height: 110rpx;
box-shadow: 0 0 5px #999;
display: flex; display: flex;
align-items: center; align-items: center;
padding: 5rpx 0; padding: 5rpx 0;
color: #999999; color: $uni-text-color-grey;
background: $uni-border-color-default;
box-shadow: 0 2px 4px $uni-border-shadow-color-default;
/* 针对tabbar的统一处理 */ /* 针对tabbar的统一处理 */
.tabbar-item { .tabbar-item {
width: 33.33%; width: 33.33%;
@ -110,12 +143,12 @@ view {
} }
// 未被选中的导航栏字体 // 未被选中的导航栏字体
.item-bottom { .item-bottom {
font-size: 28rpx; font-size: 12px;
width: 100%; width: 100%;
} }
// 被选中的导航栏字体 // 被选中的导航栏字体
.item-active { .item-active {
color: #f00; color: $uni-text-color-inverse;
} }
} }
@ -123,16 +156,26 @@ view {
.center-item { .center-item {
display: block; display: block;
position: relative; position: relative;
z-index: 20;
.item-top { .item-top {
flex-shrink: 0; flex-shrink: 0;
width: 100rpx; width: 100rpx;
height: 100rpx; height: 100rpx;
position: absolute; position: absolute;
top: -50rpx; top: -60rpx;
left: calc(50% - 50rpx); left: calc(50% - 50rpx);
border-radius: 50%; border-radius: 50%;
box-shadow: 0 0 5px #999; box-shadow: 0 2px 4px $uni-border-shadow-color-default;
background-color: rgb(240, 63, 131); padding: 0;
display: flex;
align-items: center;
justify-content: center;
border: 2px solid $uni-text-color-inverse;
.img{
width: 100%;
height: 100%;
border-radius: 50%;
}
} }
.item-bottom { .item-bottom {
position: absolute; position: absolute;
@ -141,7 +184,7 @@ view {
.item-active { .item-active {
position: absolute; position: absolute;
bottom: 5rpx; bottom: 5rpx;
color: #1fff; color: $uni-text-color-inverse;
} }
} }
} }

View File

@ -1,86 +0,0 @@
<template>
<view class="tab-bar">
<view class="content">
<view class="one-tab" v-for="(item, index) in tabBarList" :key="index" @click="selectTabBar(item.pagePath)">
<view>
<view class="tab-img">
<image v-if="routePath === item.pagePath" class="img" :src="item.selectedIconPath"></image>
<image v-else class="img" :src="item.iconPath"></image>
</view>
</view>
<view v-if="routePath === item.pagePath" class="tit selectTexts">{{ item.text }}</view>
<view v-else class="tit texts">{{ item.text }}</view>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
// 底部导航栏数据
tabBarList: {
type: Array,
required: true
},
// 当前页面路径
routePath: {
type: String,
required: true
}
},
data() {
return {};
},
methods: {
selectTabBar(path) {
this.$emit('onTabBar', path)
}
}
};
</script>
<style lang="scss">
.tab-bar {
position: fixed;
bottom: 0;
left: 0;
width: 100vw;
padding-top: 10rpx;
padding-bottom: calc(10rpx + constant(safe-area-inset-bottom));
padding-bottom: calc(10rpx + env(safe-area-inset-bottom));
background-color: #fff;
.content {
display: flex;
.one-tab {
display: flex;
flex-direction: column;
align-items: center;
width: 50%;
.tab-img {
width: 50rpx;
height: 50rpx;
.img {
width: 100%;
height: 100%;
}
}
.tit {
font-size: 30rpx;
transform: scale(0.7);
}
.selectTexts{
color:#1890e1;
}
.texts{
color: block;
}
}
}
}
</style>

View File

@ -0,0 +1,70 @@
<template>
<view class="loadMore">
<!-- 无数据 -->
<view class="noData" v-if="noData">
<view class="imgView">
<image class="img" src="https://dm-auto.oss-cn-shanghai.aliyuncs.com/mes_wechat/noData.png" lazy-load="true"></image>
</view>
<view class="text font14">暂无数据...</view>
</view>
<view class="loadView" v-if="loading">
<view class="loadBox">
<text class="icon iconfont icon-loading"></text>
<text class="text font14">加载中...</text>
</view>
</view>
<view class="loadCompleted" v-if="loadEnd && !loading">
<view class="loadBox">
<text class="iconfont icon-meiyougengduo"></text>
<text class="text font14">没有更多数据了</text>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
}
},
props: {
noData:{
type:[Boolean],
default(){
return false
}
},
loading:{
type:[Boolean],
default(){
return false
}
},
loadEnd:{
type:[Boolean],
default(){
return false
}
}
},
computed: {
},
methods: {
}
}
</script>
<style scoped lang="scss">
.noData{
.text{
color: $uni-text-color-grey;
}
}
.loadBox{
color: $uni-text-color-loading;
}
</style>

View File

@ -0,0 +1,128 @@
<template>
<view class="selectView">
<picker mode="selector" @change="bindPickerChange" @cancel="pickerHide" :value="value" range-key="name" :range="list" >
<view class="pickerBom" @click="pickerClick">
<input class="input" type="text" :value="text" :placeholder="placeholder" disabled />
<text class="iconfont icon-gengduo" :class="selectShow?'selectOpen':'selectHide'"></text>
</view>
</picker>
</view>
</template>
<script>
export default {
data() {
return {
selectShow:false,
value:'',
text:'',
id:this.id,
array:this.list,
}
},
props: {
placeholder:{
type:[String],
default:'请选择'
},
list:{
type:[Array],
default:[]
},
id:{
type:[String,Number],
default:''
}
},
watch:{
id:{
handler(val){
if(val){
this.array.forEach((item,index)=>{
if(item.value == val){
this.value = index;
this.text = item.name;
this.id = val;
}
})
}else{
this.value = '';
this.text = '';
this.id = '';
}
},
immediate:true,
deep:true
},
list:{
handler(val){
this.array = val;
this.array.forEach((item,index)=>{
if(item.value == this.id){
this.value = index;
this.text = item.name;
this.id = item.value;
}
})
},
immediate:true,
deep:true
}
},
computed: {
},
methods: {
pickerClick(){
this.selectShow = true;
},
bindPickerChange(e){
this.value = e.detail.value;
this.text = this.array[e.detail.value].name;
this.id = this.array[e.detail.value].value;
this.selectShow = false;
this.$emit('change',{name:this.array[e.detail.value].name,value:this.array[e.detail.value].value,item:this.array[e.detail.value]});
},
pickerHide(){
this.selectShow = false;
}
}
}
</script>
<style scoped lang="scss">
.selectView{
width: 100%;
}
.pickerBom{
width: 100%;
.input{
width: 100%;
}
}
.selectOpen{
animation: rotate 0.6s;
animation-fill-mode: forwards;
}
.selectHide{
animation: rotate180 0.6s ;
animation-fill-mode: forwards;
}
@keyframes rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(90deg);
}
}
@keyframes rotate180 {
from {
transform: rotate(90deg);
}
to {
transform: rotate(0deg);
}
}
</style>

View File

@ -0,0 +1,91 @@
<template>
<view>
<view class="line-total" :style="'width: ' + (val / total * 100) + '%'">
<text class="line-data">
{{val}}%
</text>
</view>
<view style="position: relative;bottom: 13px;">
<view class="line-base"></view>
<view class="line-blue" :style="'width: ' + (val / total * 100) + '%'"></view>
</view>
</view>
</template>
<script>
export default {
name: 'progressBar',
data() {
return {
}
},
props: {
// 标题
title: {
type: [String, Number],
default: ''
},
total: {
type: [Number],
default: 0
},
val: {
type: [Number],
default: 0
}
},
computed: {
},
methods: {
}
}
</script>
<style scoped lang="scss">
.line-total {
color: #67C23A;
text-align: right;
font-size: 25rpx;
font-style: normal;
font-weight: 700;
line-height: normal;
position: relative;
z-index: 99;
}
.line-data{
color: $uni-text-color-inverse;
padding: 1px 5px;
border-radius: 9px;
border: 1px solid $uni-text-color-inverse;
background: var(--color-warning, #67C23A);
width: 30px;
display: inline-block;
text-align: center;
font-size: 11px;
}
.line-base {
position: absolute;
width: 100%;
height: 6px;
border-radius: 8px;
background: rgba(128, 136, 142, 0.40);
}
.line-blue {
position: absolute;
width: 50%;
height: 6px;
border-radius: 10px;
background: #67C23A;
}
.line-val {
display: flex;
justify-content: space-between;
color: #7e7e7e;
font-size: 25rpx;
font-weight: 50px;
margin-top: 12rpx;
}
</style>

View File

@ -0,0 +1,40 @@
<template>
<view class="searchBox">
<view class="searchView">
<view class="searchInput">
<input class="input font14" confirm-type="search" placeholder-class="placeholderStyle placeholderClass iconfont icon-a-Vector6-copy" :placeholder="placeholder" />
<view class="filter">
<text class="iconfont icon-a-shaixuan2 font22"></text>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
}
},
props: {
placeholder:{
type:[String],
default:' 请输入关键字'
}
},
computed: {
},
methods: {
}
}
</script>
<style scoped lang="scss">
.searchBox .searchInput .input{
background: $uni-bg-color-primary;
}
</style>

View File

@ -0,0 +1,20 @@
<template>
<view>
</view>
</template>
<script>
export default {
name:"switchDefine",
data() {
return {
};
}
}
</script>
<style>
</style>

View File

@ -0,0 +1,245 @@
<template>
<view class="uploadImgView">
<view class="uploadTitle" v-if="name && name!=''">
<view class="name font_bold">{{name}}</view>
<view class="limit">{{newList.length}}/{{limit}}</view>
</view>
<view class="imgList">
<view class="uploadFlex itemBox" v-for="(item,index) in newList" :key="index">
<view class="imgItem">
<view class="itemImg">
<image class="img" :src="item" mode="scaleToFill"></image>
</view>
<view class="deleteBox" @click="deleteImg(index)">
<text class="icon iconfont icon-a-shanchu21"></text>
</view>
</view>
</view>
<view class="uploadFlex itemBox" v-for="(item,index) in uploadList" :key="index">
<view class="imgItem">
<view class="itemImg">
<image class="img" :src="item.path" mode="scaleToFill"></image>
</view>
<view class="progressView">
<view class="progressWidth" :style="'width:'+item.progress+'%'"></view>
</view>
</view>
</view>
<view class="uploadBut itemBox" @click="upload()" v-if="newList.length<limit">
<view class="img_but">
<view class="icon iconfont icon-a-shangchuanzhaopian2 font35"></view>
<view class="text font12">
上传图片
</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default{
data(){
return{
newList:this.list,
uploadList:[],
oss:{},
}
},
props:{
name:{
type:[String],
default:''
},
limit:{
type:[Number,String],
default:1
},
list:{
type:[Array,Object],
default: () => []
},
},
watch:{
list:{
handler(val){
this.newList = val;
},
immediate:true,
deep:true
}
},
mounted() {
this.getOss();
},
onShow() {
},
methods:{
// 获取图片oss 服务地址
getOss(){
this.$api.getOss('/oss.sign',{dir:'mes'}).then(res=>{
this.oss = res.data;
}).catch(err=>{})
},
deleteImg(num){
this.newList.forEach((item,index)=>{
if(num == index){
this.newList.splice(index,1);
}
})
this.$emit('input',this.newList);
},
upload(){
uni.chooseImage({
count:9,
success: (chooseImageRes) => {
const tempFilePaths = chooseImageRes.tempFilePaths;
tempFilePaths.forEach((item,index)=>{
let num = item.length;
let nameStr = item.toString();
let name = Date.parse(new Date())+'/'+nameStr.substring(nameStr-8);
let fileName = this.oss.dir+'/'+ name;
let text = Date.parse(new Date())+'_'+index;
let obj = {
path:nameStr,
text:text,
progress:0,
}
this.uploadList.push(obj)
this.uploadOss(item,name,fileName,text);
})
},
fail:(errUpload)=> {
}
});
},
uploadOss(url,name,fileName,text){
const uploadTask = uni.uploadFile({
url:this.oss.host,
header:{
'Content-Type':'application/x-www-form-urlencoded',
},
filePath: url,
name: 'file',
formData: {
'name':name,
'key': fileName,
'policy': this.oss.policy,
'OSSAccessKeyId': this.oss.accessid,
'success_action_status':200,
'Signature': this.oss.signature,
},
success: (uploadFileRes)=>{
this.newList.push(this.oss.host+fileName);
this.uploadList = [];
this.$emit('input',this.newList);
},
fail:(err)=>{
uni.showModal({
content: err.errMsg,
showCancel: false
});
}
});
uploadTask.onProgressUpdate((res) => {
this.uploadList.forEach((item,index)=>{
if(item.text == text){
item.progress = res.progress;
}
})
});
}
}
}
</script>
<style scoped lang="scss">
.uploadTitle{
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 6px;
.limit{
color: $uni-text-color-info;
}
}
.imgList{
height: 100%;
width: 100%;
display: flex;
flex-wrap: wrap;
.uploadFlex{
display: flex;
}
.itemBox{
width: 32%;
height: 100px;
margin-right: 2%;
padding: 7px 0 0 0;
box-sizing: border-box;
.imgItem{
width: 100%;
height: 100%;
position: relative;
.itemImg{
width: 100%;
height: 100%;
}
.img{
width: 100%;
height: 100%;
border-radius: 4px;
}
.deleteBox{
position: absolute;
top: 3px;
right: 3px;
z-index: 20;
width: 26px;
height: 26px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
background: $uni-bg-color-delete;
.icon{font-size: 14px;}
}
}
}
.itemBox:nth-child(3n){
margin-right: 0;
}
.uploadBut{
height: 93px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background: $uni-bg-color-placeholder;
border-radius: 4px;
margin: 7px 0 0 0;
padding: 0;
box-sizing: border-box;
}
}
.img_but{
display: flex;flex-direction: column;align-items: center;
.icon{color: $uni-text-color-inverse;}
.text{margin-top: 5px;}
}
.progressView{
position: absolute;bottom: 0;left: 0;z-index: 2;
width: 100%;height: 6px;background: $uni-bg-color-placeholder;border-radius: 8px;
.progressWidth{
height: 6px;background: $uni-color-primary;
border-radius: 8px;
}
}
</style>

21
env.js Normal file
View File

@ -0,0 +1,21 @@
// 不同的环境变量配置
const development = {
requestBaseUrl: 'http://development',
appid: '',
}
const test = {
requestBaseUrl: 'https://api.dev.dwoodauto.com/api',
appid: 'wxd5xxxxee0fce1c81',
}
const production = {
requestBaseUrl: 'http://production',
appid: 'wx3xxxx1ce403cab3',
}
export default {
development,
test,
production
}

45
main.js
View File

@ -1,13 +1,29 @@
import "./static/iconfont/iconfont.css" import "./static/iconfont/iconfont.css"
import "./static/iconfont/iconfont-weapp/iconfont-weapp-icon.css" import './static/css/app.css';
import "./static/iconfont/iconfont-weapp/iconfont-weapp-icon.css"
// 全局组件
import searchView from './components/searchView/index'
import loadMore from './components/loadMore/index'
import progressBar from './components/progressBar'
import pickerSelect from './components/pickerSelect/index'
import calendar from './components/calendar/index'
import uploadImg from './components/upload/uploadImg'
// #ifndef VUE3 // #ifndef VUE3
import Vue from 'vue' import Vue from 'vue'
import App from './App' import App from './App'
import svg from './static/iconfont/svg.js' import svg from './static/iconfont/svg.js'
Vue.use(svg);
Vue.component('search-view', searchView);
Vue.component('load-more', loadMore);
Vue.component('progress-bar', progressBar);
Vue.component('picker-select', pickerSelect);
Vue.component('calendar', calendar);
Vue.component('upload-img', uploadImg);
Vue.use(svg);
Vue.config.productionTip = false; Vue.config.productionTip = false;
App.mpType = 'app'; App.mpType = 'app';
@ -21,10 +37,25 @@ app.$mount()
// #ifdef VUE3 // #ifdef VUE3
import { createSSRApp } from 'vue' import { createSSRApp } from 'vue'
import App from './App.vue' import App from './App.vue'
import request from "./utils/api.js"
import publicMethods from "./utils/public.js"
export function createApp() { export function createApp() {
const app = createSSRApp(App) const app = createSSRApp(App)
// 全局注册组件
app.component('searchView', searchView);
app.component('loadMore', loadMore);
app.component('progressBar', progressBar);
app.component('pickerSelect', pickerSelect);
app.component('calendar', calendar);
app.component('uploadImg', uploadImg);
app.config.globalProperties.$api = request;
app.config.globalProperties.$wf = publicMethods;
return { return {
app app
} }
} }
// #endif // #endif

View File

@ -1,5 +1,5 @@
{ {
"name" : "mes-mobile01", "name" : "mes-mobile",
"appid" : "__UNI__41DB0F2", "appid" : "__UNI__41DB0F2",
"description" : "", "description" : "",
"versionName" : "1.0.0", "versionName" : "1.0.0",
@ -50,11 +50,16 @@
/* */ /* */
"mp-weixin" : { "mp-weixin" : {
/* */ /* */
"appid" : "wx62bd7b72516b9017", "appid" : "wx38dc81b0eef130a3",
"setting" : { "setting" : {
"urlCheck" : false "urlCheck" : false,
"postcss" : true,
"es6" : true,
"minified" : true
}, },
"usingComponents" : true "usingComponents" : true,
"libVersion":"latest"
}, },
"vueVersion" : "3" "vueVersion" : "3",
"locale" : "zh-Hans"
} }

View File

@ -1,16 +1,22 @@
{ {
"name": "mes_mobile", "uni-app": {
"version": "1.0.0", "scripts": {
"description": "", "dev": {
"main": "main.js", "title": "微信小程序——开发版",
"scripts": { "env": {
"test": "echo \"Error: no test specified\" && exit 1" "ENV_TYPE": "dev",
}, "UNI_PLATFORM": "mp-weixin",
"repository": { "VITE_BASE_API": "https://api.dev.dwoodauto.com"
"type": "git", }
"url": "https://git.tool.dwoodauto.com/long/mes_mobile.git" },
}, "pro": {
"keywords": [], "title": "微信小程序——正式版",
"author": "", "env": {
"license": "ISC" "ENV_TYPE": "pro",
} "UNI_PLATFORM": "mp-weixin",
"VITE_BASE_API": "http://pro.domain/"
}
}
}
}
}

View File

@ -35,26 +35,187 @@
"path" : "pages/login/login", "path" : "pages/login/login",
"style" : "style" :
{ {
// "navigationBarTitleText" : "登录",
"enablePullDownRefresh" : false, "enablePullDownRefresh" : false,
"navigationStyle": "custom" "navigationStyle": "custom"
} }
}, },
{ {
"path" : "pages/index/productionOrder", "path" : "pages/production/productionOrder",
"style" : "style" :
{ {
"navigationBarTitleText" : "生产工单管理", "navigationBarTitleText" : "生产工单管理",
"enablePullDownRefresh" : true,
"pullToRefresh":{
}
}
},
{
"path" : "pages/schedul/list",
"style" :
{
"navigationBarTitleText" : "工单排程",
"enablePullDownRefresh" : false
}
},
{
"path" : "pages/index/schedule",
"style" :
{
"navigationBarTitleText" : "工单进度",
"enablePullDownRefresh" : false
}
},
{
"path" : "pages/index/materialYield",
"style" :
{
"navigationBarTitleText" : "工单出材率",
"enablePullDownRefresh" : false
}
},
{
"path" : "pages/equipmentManage/equipmentManage",
"style" :
{
"navigationBarTitleText" : "设备管理",
"enablePullDownRefresh" : true
}
},
{
"path" : "pages/equipmentManage/editDevice",
"style" :
{
"navigationBarTitleText" : "添加设备",
"enablePullDownRefresh" : false
}
},
{
"path" : "pages/equipmentManage/bindingDevice",
"style" :
{
"navigationBarTitleText" : "设备管理",
"enablePullDownRefresh" : false
}
},
{
"path" : "pages/production/productionDetail",
"style" :
{
"navigationBarTitleText" : "工单详情",
"enablePullDownRefresh" : false
}
},
{
"path" : "pages/deviceRepair/deviceRepair",
"style" :
{
"navigationBarTitleText" : "硬件设备报修",
"enablePullDownRefresh" : true
}
},
{
"path" : "pages/deviceRepair/repairReport",
"style" :
{
"navigationBarTitleText" : "设备报修",
"enablePullDownRefresh" : false
}
},
{
"path":"pages/deviceRepair/deviceDetail",
"style" :{
"navigationBarTitleText" : "设备报修详情",
"enablePullDownRefresh" : false
}
},
{
"path" : "pages/deviceStatus/deviceStatus",
"style" :
{
"navigationBarTitleText" : "设备状态",
"enablePullDownRefresh" : false
}
},
{
"path" : "pages/equipmentManage/deviceDetail",
"style" :
{
"navigationBarTitleText" : "设备信息",
"enablePullDownRefresh" : false
}
},
{
"path" : "pages/person/faceAuthentication",
"style" :
{
"navigationBarTitleText" : "人脸认证",
"enablePullDownRefresh" : false
}
},
{
"path" : "pages/person/myAuthority",
"style" :
{
"navigationBarTitleText" : "我的权限",
"enablePullDownRefresh" : false
}
},
{
"path" : "pages/person/alarm",
"style" :
{
"navigationBarTitleText" : "设备报警",
"enablePullDownRefresh" : false
}
},
{
"path" : "pages/person/safetyAccidents",
"style" :
{
"navigationBarTitleText" : "安全事故",
"enablePullDownRefresh" : false
}
},
{
"path" : "pages/deviceStatus/deviceCamera",
"style" :
{
"navigationBarTitleText" : "设备状态",
"enablePullDownRefresh" : false
}
},
{
"path" : "pages/deviceStatus/detectionEventList",
"style" :
{
"navigationBarTitleText" : "设备状态",
"enablePullDownRefresh" : false
}
},
{
"path" : "pages/deviceRepair/repairOrder",
"style" :
{
"navigationBarTitleText" : "设备维修",
"enablePullDownRefresh" : false "enablePullDownRefresh" : false
} }
}], }],
"globalStyle": { "globalStyle": {
"navigationBarTextStyle": "white", "navigationBarTextStyle": "white",
"navigationBarTitleText": "德木自动化系统", "navigationBarTitleText": "德木自动化系统",
"navigationBarBackgroundColor": "#060B26", "navigationBarBackgroundColor": "#060B26",
"backgroundColor":"#060B26",
"backgroundTextStyle":"light",
"app-plus": { "app-plus": {
"background": "#efeff4" "background": "#060B26"
} },
"mp-weixin":{
"background":"#060B26",
"pullToRefresh":{
"color":"#060B26"
}
}
}, },
"condition" : { //模式配置,仅开发期间生效 "condition" : { //模式配置,仅开发期间生效
"current": 0, //当前激活的模式(list 的索引项) "current": 0, //当前激活的模式(list 的索引项)

View File

@ -0,0 +1,178 @@
<template>
<!-- 设备报修 -->
<view class="page_padding">
<view class="page_content contentboxsty font14">
<view class="content_row">
<view class="name font_bold">值班工程师</view>
<view class="flex1">
<pickerSelect class="comView" @change="bindOperatorChange" :list="setMap.operatorList" :id="form.operator_id" placeholder="请选择工程师" />
</view>
</view>
<view class="content_row">
<view class="name font_bold">故障时间</view>
<view class="flex1">
<view class='input_date' :class="[form.failure_at && form.failure_at!=''? 'haveTime' : '']">
<uni-datetime-picker placeholder="请选择时间" type="datetime" v-model="form.failure_at" />
</view>
</view>
</view>
<view class="content_row">
<view class="name font_bold">报修时间</view>
<view class="flex1">
<view class='input_date' :class="[form.report_at && form.report_at!=''? 'haveTime' : '']">
<uni-datetime-picker placeholder="请选择时间" type="datetime" v-model="form.report_at" />
</view>
</view>
</view>
<view class="content_row">
<view class="name font_bold">报修人</view>
<view class="flex1">
<pickerSelect class="comView" @change="bindRepairChange" :list="setMap.operatorList" :id="form.report_id" placeholder="请选择报修人" />
</view>
</view>
<view class="content_row">
<view class="name font_bold">报修设备</view>
<view class="flex1">
<pickerSelect class="comView" @change="bindeQuipmentChange" :list="setMap.equipmentList" :id="form.equipment_id" placeholder="请选择报修设备" />
</view>
</view>
<view class="textarea_row">
<view class="name font_bold">故障描述</view>
<textarea class="textarea" placeholder="请输入故障描述..." v-model="form.remark" cursor-spacing="180px" :auto-blur="true" placeholder-class="placeholderStyle"/>
</view>
<view class="img_row">
<uploadImg limit="3" name="故障图片" :list="form.failure_photo" />
</view>
</view>
<view class="bottom_but flex_layout">
<view class="font13 but_color" @click="save">保存</view>
<view class="font13" @click="cancel">取消</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
setMap:{
operatorList:[],
equipmentList:[],
},
form:{
id:'',
operator_id:'',
failure_at:'',
report_at:'',
report_id:'',
equipment_id:'',
remark:'',
failure_photo:[],
},
id:0,
oss:{},
}
},
onLoad(option) {
if(option.id != undefined){
this.getInfo(Number(option.id));
}
},
mounted() {
this.userList();
this.equipment();
},
methods: {
getInfo(id){
this.$api.request('/equipment.repair.info',{id:id}).then(res=>{
this.form = {
id:id,
operator_id:res.data.operator_id,
failure_at:res.data.failure_at,
report_at:res.data.report_at,
report_id:res.data.report_id,
equipment_id:res.data.equipment_id,
remark:res.data.remark,
failure_photo:res.data.failure_photo,
}
}).catch(err=>{})
},
userList(){
this.$api.request('/user.options','').then(res=>{
res.data.forEach(item=>{
item.value = item.id;
})
this.setMap['operatorList'] = res.data;
}).catch(err=>{})
},
equipment(){
this.$api.request('/device.options','').then(res=>{
res.data.forEach(item=>{
item.name = item.name;
item.value = item.id;
})
this.setMap['equipmentList'] = res.data;
}).catch(err=>{})
},
bindOperatorChange(e){
this.form.operator_id = e.value;
},
bindRepairChange(e){
this.form.report_id = e.value;
},
bindeQuipmentChange(e){
this.form.equipment_id = e.value;
},
save(){
this.$api.postFuncLoading('/create.repair.notice',this.form).then(res=>{
this.parentClick();
this.reset();
this.$wf.toast({type:'success',text:'保存成功'});
}).catch(err=>{})
},
cancel(){
this.reset();
},
reset(){
this.form = {
id:'',
operator_id:'',
failure_at:'',
report_at:'',
report_id:'',
equipment_id:'',
remark:'',
failure_photo:[],
}
},
parentClick(){
const pages = getCurrentPages();
if (pages.length >= 2) {
const prevPage = pages[pages.length - 2];
prevPage.$vm.getList();
}
}
}
}
</script>
<style scoped lang="scss">
.page_padding{padding-bottom: 100px;}
.page_content{padding: 0 12px 10px;}
.content_row{display: flex;border-bottom: 1px solid #2D3A6F;height: 44px;align-items: center;
.name{flex-basis: 96px;}
.flex_layout{
.contenticon{width: 20px;height: 20px;}
.text{padding: 0 20px 0 5px;}
}
}
.textarea_row{
.name{padding: 12px 0;}
.textarea{border-radius: 4px;background: $uni-bg-color-placeholder;padding: 10px;width: 100%;box-sizing: border-box;}
}
.img_row{
padding: 12px 0 6px 0;
height: 100%;
}
</style>

View File

@ -0,0 +1,117 @@
<template>
<view class="page_padding">
<view class="padd_bot12 font14 flex_layout">
<text>{{type==1?'硬件设备报修详情':'硬件设备维修详情'}}</text>
</view>
<view class="detail_list padd_top12 contentboxsty page_content font13">
<template v-if="type==2">
<view class="row flex_layout">
<view class="name font_bold">维修工程师</view>
<view class="text">{{info.repair_name}}</view>
</view>
<view class="row flex_layout">
<view class="name font_bold">故障解除时间</view>
<view class="text">{{info.repair_at_label}}</view>
</view>
<view class="row">
<view class="name font_bold">维修描述</view>
<view class="text remarkText padd_top12">{{info.repair_remark}}</view>
</view>
<view class="row">
<view class="name font_bold">维修照片</view>
<view class="text imgList">
<view class="imgView" v-for="(em,ind) in info.repair_photo" :key="ind">
<image class="img" :src="em" mode="aspectFill" @click="imgPreview(info.repair_photo,em)"></image>
</view>
</view>
</view>
</template>
<template v-if="type ==1">
<view class="row flex_layout">
<view class="name font_bold">值班工程师</view>
<view class="text">{{info.operator_name}}</view>
</view>
<view class="row flex_layout">
<view class="name font_bold">故障时间</view>
<view class="text">{{info.failure_at}}</view>
</view>
<view class="row flex_layout">
<view class="name font_bold">报修时间</view>
<view class="text">{{info.report_at}}</view>
</view>
<view class="row flex_layout">
<view class="name font_bold">报修人</view>
<view class="text">{{info.repair_name}}</view>
</view>
<view class="row flex_layout">
<view class="name font_bold">报修设备</view>
<view class="text">{{info.eq_name}}</view>
</view>
<view class="row">
<view class="name font_bold">故障描述</view>
<view class="text remarkText padd_top12">{{info.remark}}</view>
</view>
<view class="row">
<view class="name font_bold">故障照片</view>
<view class="text imgList">
<view class="imgView" v-for="(em,ind) in info.failure_photo" :key="ind">
<image class="img" :src="em" mode="aspectFill" @click="imgPreview(info.failure_photo,em)"></image>
</view>
</view>
</view>
</template>
</view>
</view>
</template>
<script>
export default{
data(){
return{
type:1,
id:0,
info:{}
}
},
onLoad(option) {
this.type = option.type;
this.id = option.id;
},
mounted() {
this.getData();
},
methods:{
getData(){
this.$api.postFuncLoading('/equipment.repair.info',{id:this.id}).then(res=>{
this.info = res.data;
}).catch(err=>{})
},
imgPreview(list,url){
uni.previewImage({
urls: list,
current:url,
});
}
}
}
</script>
<style scoped lang="scss">
.row{
padding-bottom: 12px;
.name{flex-basis: 90px;}
.text{flex: 1;}
}
.row:last-child{
padding-bottom: 0;
}
.imgList{
display: flex;flex-direction: row;flex-wrap: wrap;padding: 6px 0;
.imgView{width: 32%;height: 100px;margin-right: 2%;box-sizing: border-box;padding: 6px 0 0 0;}
.imgView:nth-child(3n){
margin-right: 0;
}
.img{width: 100%;height: 100%;border-radius:4px;}
}
</style>

View File

@ -0,0 +1,191 @@
<template>
<!-- 设备报修 -->
<view class="page_padding bot_padding">
<view v-for="(item,index) in list" :key="index">
<view class="page_list contentboxsty font13" @click="toDetail(item)">
<view class="list_top flex_layout">
<view class="top_left flex_layout">
<view class="icon iconfont icon-daiju"></view>
<view class="font_bold">{{item.eq_name}}</view>
</view>
<view class="card_right top_right">
<text class="status error">故障中</text>
</view>
</view>
<view class="list_centre padd_bot12">
<view class="row_data">
<view class="name font_bold">值班工程师</view>
<view class="text">{{item.operator_name}}</view>
</view>
<view class="row_data">
<view class="name font_bold">故障时间</view>
<view class="text">{{item.failure_at}}</view>
</view>
<view class="row_data">
<view class="name font_bold">报修人</view>
<view class="text">{{item.repair_name}}</view>
</view>
<view class="row_data">
<view class="name font_bold">报修时间</view>
<view class="text">{{item.report_at}}</view>
</view>
<view class="row_data">
<view class="name font_bold">处理状态</view>
<view class="text">{{item.status_label}}</view>
</view>
<view class="row_data">
<view class="name font_bold">故障解除时间</view>
<view class="text">{{item.repair_at_label}}</view>
</view>
</view>
<view class="list_below flex_layout">
<view class="below_left btn" @click.stop="toRepairOrder(item)">
<text class="icon iconfont icon-bianji font16"></text>
维修单
</view>
<view class="below_right btn" @click.stop="editRepairOrder(item)">
<text class="icon iconfont icon-bianji font16"></text>
修改
</view>
</view>
</view>
</view>
</view>
<view class="page_bottom_button">
<view class="page_add" @click="toAddRepairReport()">
<view class="icon iconfont icon-tianjia font20"></view>
<text class="font14">添加</text>
</view>
</view>
</template>
<script>
export default {
data() {
return {
params:{
page:1,
pageSize:10,
},
loadParams:{
noData:false,
loading:false,
loadEnd:false
},
list:[],
}
},
mounted() {
this.getList();
},
// 上拉刷新
onPullDownRefresh(){
this.params.page = 1;
this.loadParams = {
noData:false,
loading:false,
loadEnd:false
};
this.getList(2);
},
// 加载下一页
onReachBottom(){
if(!(this.loadParams.loadEnd || this.loadParams.noData)){
this.loadParams.loading = true;
this.params.page ++;
this.getList();
}
},
methods: {
getList(type=1){
if(this.params.page == 1){
uni.showLoading({
title: '加载中',
mask: true
})
}
this.$api.request('/equipment.repair.list',this.params).then(res=>{
if(type ==2){
uni.stopPullDownRefresh();
}
setTimeout( ()=> {
uni.hideLoading();
}, 200);
this.loadParams.loading = false;
if(res.data.rows.length ==0 && this.params.page == 1){
this.loadParams.noData = true;
}
if(res.data.rows.length>0 && res.data.rows.length < this.params.pageSize){
this.loadParams.loadEnd = true;
}
if(this.params.page == 1){
this.list = res.data.rows;
}else{
this.list = this.list.concat(res.data.rows);
}
}).catch(err=>{
setTimeout(()=> {
uni.hideLoading();
}, 200);
})
},
//新增报修页面
toAddRepairReport(){
uni.navigateTo({
url:'/pages/deviceRepair/repairReport'
})
},
//维修页面
toRepairOrder(item){
// if(item.repair_id && item.repair_id>0){
// uni.navigateTo({
// url:'./deviceDetail?id='+item.id+'&type='+2
// })
// }else{
// uni.navigateTo({
// url:'/pages/deviceRepair/repairOrder?id='+item.id
// })
// }
uni.navigateTo({
url:'/pages/deviceRepair/repairOrder?id='+item.id
})
},
editRepairOrder(item){
uni.navigateTo({
url:'/pages/deviceRepair/repairReport?id='+item.id
})
},
toDetail(item){
uni.navigateTo({
url:'./deviceDetail?id='+item.id+'&type='+1
})
}
}
}
</script>
<style scoped lang="scss">
.page_list{
.list_top{height: 44px;align-items: center;border-bottom: 1px solid $uni-border-color-primary;
.top_left{flex: 1;display: flex;align-items: center;
.icon{margin-right: 5px;color: $uni-text-color-primary;}
}
}
.list_centre{
.row_data{
display: flex;align-items: center;padding-top: 12px;
.name{flex-basis: 95px;}
.text{display: flex;display: flex;}
}
}
.list_below{height: 49px;align-items: center;border-top: 1px solid $uni-border-color-primary;
.btn{width: 50%;display: flex;align-items: center;justify-content: center;height: 100%;
.icon{margin-right: 5px;}
}
.below_left{border-right: 1px solid $uni-border-color-primary;}
}
}
</style>

View File

@ -0,0 +1,135 @@
<template>
<!-- 维修单 -->
<view class="page_padding">
<view class="page_content contentboxsty font14">
<view class="content_row">
<view class="name font_bold">维修工程师</view>
<view class="flex1">
<pickerSelect class="comView" @change="bindPickerChange" :list="setMap.operatorList" :id="form.repair_id" placeholder="请选择工程师" />
</view>
</view>
<view class="content_row">
<view class="name font_bold">故障解除时间</view>
<view class="flex1">
<view class='input_date' :class="[form.repair_at && form.repair_at!=''? 'haveTime' : '']">
<uni-datetime-picker placeholder="请选择时间" type="datetime" v-model="form.repair_at" />
</view>
</view>
</view>
<view class="textarea_row">
<view class="name font_bold">维修描述</view>
<textarea class="textarea" v-model="form.repair_remark" placeholder="请输入维修描述..." cursor-spacing="180px" :auto-blur="true" placeholder-class="placeholderStyle" />
</view>
<view class="img_row">
<uploadImg limit="3" name="维修照片" :list="form.repair_photo" />
</view>
</view>
<view class="bottom_but flex_layout">
<view class="font13 but_color" @click="save">保存</view>
<view class="font13" @click="cancel">取消</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
setMap:{
operatorList:[],
},
form:{
id:'',
repair_id:'',
repair_at:'',
repair_remark:'',
repair_photo:[]
},
array: ['中国', '美国', '巴西', '日本'],
downtime:'',
}
},
onLoad(option) {
if(option.id !=undefined){
// this.form.id = Number(option.id);
this.getInfo(Number(option.id));
}
},
mounted() {
this.userList();
},
methods: {
getInfo(id){
this.$api.request('/equipment.repair.info',{id:id}).then(res=>{
this.form = {
id:id,
repair_id:res.data.repair_id,
repair_at:res.data.repair_at,
repair_remark:res.data.repair_remark,
repair_photo:res.data.repair_photo,
}
}).catch(err=>{})
},
userList(){
this.$api.request('/user.options','').then(res=>{
res.data.forEach(item=>{
item.value = item.id;
})
this.setMap['operatorList'] = res.data;
}).catch(err=>{})
},
bindPickerChange(e){
this.form.repair_id = e.value;
},
save(){
this.$api.postFuncLoading('/create.equipment.repair',this.form).then(res=>{
this.parentClick();
this.$wf.toast({type:'success',text:'保存成功'});
}).catch(err=>{})
},
cancel(){
this.reset();
},
reset(){
this.form = {
id:'',
repair_id:'',
repair_at:'',
repair_remark:'',
repair_photo:[]
}
},
parentClick(){
const pages = getCurrentPages();
if (pages.length >= 2) {
const prevPage = pages[pages.length - 2];
prevPage.$vm.getList();
}
}
}
}
</script>
<style scoped lang="scss">
.page_content{padding: 0 12px 10px;}
.content_row{display: flex;border-bottom: 1px solid #2D3A6F;height: 44px;align-items: center;
.name{flex-basis: 100px;}
.flex_layout{
.contenticon{width: 20px;height: 20px;}
.text{padding: 0 20px 0 5px;}
}
}
.textarea_row{
.name{padding: 12px 0;}
.textarea{border-radius: 4px;background: $uni-bg-color-placeholder;padding: 10px;width: 100%;box-sizing: border-box;}
}
.img_row{
padding: 12px 0 6px 0;
.img_but{
display: flex;flex-direction: column;align-items: center;
.icon{color: $uni-text-color-inverse;}
.text{margin-top: 5px;}
}
}
</style>

View File

@ -0,0 +1,49 @@
<template>
<!-- 检测事件列表 -->
<view class="page_padding">
<view class="padd_bot12 font14">
<text>安全生产监控设备检测事件列表</text>
</view>
<view class="page_list contentboxsty flex_layout">
<view class="content_left padd_rigth12">
<image class="img" src="http://dm-auto.oss-cn-shanghai.aliyuncs.com/mes_wechat/background.png" mode=""></image>
</view>
<view class="content_right">
<view class="content_row font13">
2024-01-11 19:09:56
</view>
<view class="content_row tip font_bold font14">
穿越警戒线
</view>
<view class="content_row font12">
(检测到指定区域内有目标越过警戒线请注意安全)
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
}
},
methods: {
}
}
</script>
<style lang="scss">
.page_list{padding: 12px;}
.content_left{
flex-basis: 126px;height: 96px;
.img{width: 100%;height: 100%;border-radius: 8px;}
}
.content_right{
flex:1;
.tip{color: #FA3758;padding: 6px 0 5px 0;}
}
</style>

View File

@ -0,0 +1,89 @@
<template>
<view class="page_padding font14">
<view class="padd_bot12 font14 flex_layout">
<text>硬件设备状态</text>
<view class="status font12"><text class="drop"></text>在线</view>
</view>
<view class="body-view contentboxsty">
<view class="content-top flex_layout padd_bot12">
<view class="flex1 theme_color">
<text class="drop"></text>相机工作中
</view>
<view class="top_right" @click="toList()">
更多安全事件
<text class="iconfont icon-gengduo"></text>
</view>
</view>
<view class="content_monitor" style="width: 100%;">
<image style="width: 100%;" src="http://dm-auto.oss-cn-shanghai.aliyuncs.com/mes_wechat/background.png" mode=""></image>
</view>
<view class="content_data">
<view class="device_row">
<text class="name font_bold">设备名称</text>
<text class="text">安全监控相机</text>
</view>
<view class="device_row">
<text class="name font_bold">开机时间</text>
<text class="text">2024-02-11 08:00:45</text>
</view>
<view class="device_row">
<text class="name font_bold">安全事件</text>
<text class="text">检测到指定区域内有目标越过警戒线</text>
</view>
<view class="device_row">
<text class="name font_bold">检测时间</text>
<text class="text">2024-01-11 19:09:56</text>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
}
},
methods: {
toList(){
uni.navigateTo({
url:'/pages/deviceStatus/detectionEventList'
})
},
}
}
</script>
<style scoped lang="scss">
.body-view{padding: 12px 13px;}
.theme_color{
display: flex;align-items: center;
.drop{width: 4px;height: 4px;background: $uni-text-color-primary;display: inline-block;margin-right: 6px;border-radius: 50%;}
.top_right{color: $uni-text-color-primary;}
}
.device_row{padding: 6px 0;display: flex;align-items: center;
.name {flex-basis: 70px;}
}
.flex_layout{
align-items: center;
}
.status{
background: $uni-bg-color-success;
margin-left: 8px;
border-radius: 20px;
padding: 3px 10px;
display: flex;
align-items: center;
.drop{
width: 4px;
height: 4px;
border-radius: 50%;
background: $uni-bg-color-whith;
display: inline-block;
margin-right: 6px;
}
}
</style>

View File

@ -0,0 +1,230 @@
<template>
<view class="page_padding">
<view class="padd_bot12 font14 flex_layout">
<text>硬件设备状态</text>
<view class="status font12"><text class="drop"></text>在线</view>
</view>
<view class="body-view contentboxsty">
<view class="content-top">
<view class="content-left" @click="prveClick">
<text class="iconfont icon-gengduo more_icon"></text>
</view>
<view class="content-scroll">
<view class="center-cut-menu">
<scroll-view scroll-x="true" show-scrollbar="false" scroll-with-animation="true" :scroll-left="scrollLeft" class="scroll-view horizontalScrollView" >
<view class="scroll-item" :style="'width:'+itemWidth+'px'" v-for="(item, index) in list" :key="index" @click="changeMenu(index)">
<text class="item-text" :class="curIndex == index? 'active' : ''">{{item.name}}</text>
</view>
</scroll-view>
</view>
</view>
<view class="content-right" @click="nextClick">
<text class="iconfont icon-gengduo"></text>
</view>
</view>
<swiper class="swiper-box-list" circular="true" easing-function="linear" :current="curIndex" @change="swiperChange">
<swiper-item class="swiper-topic-list" v-for="item in swiperDateList" :key="item.id">
<view class="swiper-item">
<view class="img">
<image style="width: 100%;height: 100%;" :src="item.img"></image>
</view>
<view class="font14">
<view class="device_row">
<text class="name font_bold">设备名称</text>
<text class="text">双头立锯</text>
<view @click="toCamera()" class="videoIcon text" style="position: absolute;right: 0;">
<text class="iconfont icon-a-shexiangtou_shiti1"></text>
</view>
</view>
<view class="device_row">
<text class="name font_bold">开机时间</text>
<text class="text">2024-02-11 08:00:45</text>
</view>
<view class="device_row">
<text class="name font_bold">保养到期日</text>
<text class="text">2024-02-11 08:00:45</text>
</view>
<view class="device_row">
<text class="name font_bold">今日停机</text>
<text class="text">5</text>
</view>
</view>
</view>
</swiper-item>
</swiper>
</view>
</view>
</template>
<script>
export default {
data() {
return {
list: [{
id: 1,
name: '多片锯',
},
{
id: 2,
name: '双头带锯',
},
{
id: 3,
name: '视觉分析',
},
{
id: 4,
name: '卧锯带锯',
},
{
id: 5,
name: '上料机架',
},
],
// Tab切换内容
swiperDateList: [
{
id: 1,
content: '1',
img:'http://dm-auto.oss-cn-shanghai.aliyuncs.com/mes_wechat/duopian.png'
},
{
id: 2,
content: '2',
img:'http://dm-auto.oss-cn-shanghai.aliyuncs.com/mes_wechat/liju.png'
},
{
id: 3,
content: '3',
img:'http://dm-auto.oss-cn-shanghai.aliyuncs.com/mes_wechat/shijue.png'
},
{
id: 4,
content: '4',
img:'http://dm-auto.oss-cn-shanghai.aliyuncs.com/mes_wechat/woshi.png'
},
{
id: 5,
content: '5',
img:'http://dm-auto.oss-cn-shanghai.aliyuncs.com/mes_wechat/shang.png'
},
],
itemWidth: 90,
curIndex: 0,
scrollLeft: 0,
}
},
mounted() {
},
onReady() {
this.getScrollW();
},
methods: {
toCamera(){
uni.navigateTo({
url:'/pages/deviceStatus/deviceCamera'
})
},
// 区域宽度,子元素的宽度以及距离左边栏的距离
getScrollW() {
let itemWidth = 0;
let query = uni.createSelectorQuery().in(this);
query.select('.scroll-view').boundingClientRect(data => {
this.itemWidth = (data.width/3).toFixed(0);
itemWidth = (data.width/3).toFixed(0);
this.getItemWidth(itemWidth);
}).exec();
},
getItemWidth(num){
let query = uni.createSelectorQuery().in(this);
query.selectAll('.scroll-item').boundingClientRect(data => {
let dataLen = data.length;
for (let i = 0; i < dataLen; i++) {
this.list[i].width = Number(num);
this.list[i].left = Number(num) + Number(data[i].left);
}
}).exec()
},
// 选择标题
changeMenu(index) {
this.curIndex = index;
this.scrollLeft = 0;
for (let i = 0; i < index - 1; i++) {
this.scrollLeft += this.list[i].width;
};
},
swiperChange(e) {
let index = e.detail.current;
this.changeMenu(index);
},
prveClick(){
this.curIndex = this.curIndex==0? 0 : this.curIndex-1;
},
nextClick(){
this.curIndex = this.curIndex < this.list.length-1? this.curIndex+1 : this.curIndex;
}
}
}
</script>
<style scoped lang="scss">
.body-view{
height: 450px;
.content-top{
display: flex;
align-items: center;
.content-left{flex-basis: 30px;text-align: center;
.more_icon{display: inline-block;transform: scaleX(-1);}
}
.content-scroll{flex: 1;overflow: hidden;}
.center-cut-menu {width: 100%;height: 100rpx;
.scroll-view {height: 100rpx;white-space: nowrap;
.scroll-item {height: 100rpx;padding: 0 20rpx;display: inline-block;text-align: center;box-sizing: border-box;
.item-text {font-size: 14px;line-height: 100rpx;
&.active {
font-size: 17px;
}
}
}
}
}
.content-right{flex-basis: 30px;text-align: center;}
}
.swiper-box-list{height: 400px;padding:0 12px;
.device_row:first-child{margin-top: 6px;}
.device_row{padding: 6px 0;display: flex;
.name{flex-basis: 82px;}
}
}
}
.flex_layout{
align-items: center;
}
.swiper-item{
.img{
width: 100%;
height: 250px;
}
.videoIcon{
color: $uni-color-primary;
}
}
.status{
background: $uni-bg-color-success;
margin-left: 8px;
border-radius: 20px;
padding: 3px 10px;
display: flex;
align-items: center;
.drop{
width: 4px;
height: 4px;
border-radius: 50%;
background: $uni-bg-color-whith;
display: inline-block;
margin-right: 6px;
}
}
</style>

View File

@ -0,0 +1,169 @@
<template>
<!-- 绑定安全生产监控相机 -->
<view>
<view class="page_padding">
<view class="page_content contentboxsty font13">
<view class="content_row">
<view class="name font_bold">串流推流Url</view>
<view class="text">
<input v-model="form.stream_url" placeholder="请输入串流推流Url" disabled/>
</view>
</view>
<view class="content_row">
<view class="name font_bold">AppName</view>
<view class="text">
<input v-model="form.app_name" placeholder="请输入APP名称"/>
</view>
</view>
<view class="content_row noborbot">
<view class="name"></view>
<view class="tip">
不超过256字符支持数字大小写字母短划线-下划线_等号=
</view>
</view>
<view class="content_row">
<view class="name font_bold">StreamName</view>
<view class="text">
<input v-model="form.stream_name" placeholder="请输入StreamName"/>
</view>
</view>
<view class="content_row noborbot">
<view class="name"></view>
<view class="tip">
不超过256字符支持数字大小写字母短划线-下划线_等号=
</view>
</view>
<view class="content_row">
<view class="name font_bold">设备IP</view>
<view class="text">
<input v-model="form.monitor_ip" placeholder="请输入设备IP"/>
</view>
</view>
<view class="content_row">
<view class="name font_bold">端口</view>
<view class="text">
<input v-model="form.monitor_port" placeholder="请输入设备端口"/>
</view>
</view>
<view class="content_row">
<view class="name font_bold">用户名</view>
<view class="text">
<input v-model="form.monitor_account" placeholder="请输入您的用户名"/>
</view>
</view>
<view class="content_row">
<view class="name font_bold">密码</view>
<view class="text">
<input password type="safe-password" v-model="form.monitor_password" placeholder="请输入密码"/>
</view>
</view>
<view class="content_row">
<view class="name font_bold">监控推流权限</view>
<view class="text flex_layout">
<view class="switch" @click="form.stream_type=1">
<view v-if="form.stream_type ==1" class="t-icon t-icon-qiyong1 contenticon"></view>
<view v-else class="t-icon t-icon-jinyong1 contenticon"></view>
<text class="text">Token验证</text>
</view>
<view class="switch" @click="form.stream_type=2">
<view v-if="form.stream_type ==2" class="t-icon t-icon-qiyong1 contenticon"></view>
<view v-else class="t-icon t-icon-jinyong1 contenticon"></view>
<text class="text">禁用</text>
</view>
</view>
</view>
</view>
</view>
<view class="bottom_but flex_layout">
<view class="but_color font13" @click="save">保存</view>
<view class="font13" @click="cancel">取消</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
form:{
id:'',
stream_url:'',
app_name:'',
stream_name:'',
stream_type:1,
monitor_ip:'',
monitor_port:'',
monitor_account:'',
monitor_password:''
}
}
},
onLoad(option) {
this.form.id = option.id;
this.getVideo(option.id);
},
onReady() {
},
methods: {
getVideo(id){
this.$api.request('/get.video.config',{id:id}).then(res=>{
this.form.stream_url = res.data.stream_url;
if(res.data.app_name && res.data.eq_name){
this.form.app_name = res.data.app_name;
this.form.stream_name = res.data.stream_name;
this.form.stream_type = res.data.stream_type;
this.form.monitor_ip = res.data.monitor_ip;
this.form.monitor_port = res.data.monitor_port;
this.form.monitor_account = res.data.monitor_account;
this.form.monitor_password = res.data.monitor_password;
}
}).catch(err=>{
})
},
save(){
this.$api.postFuncLoading('/bind.video.config',this.form).then(res=>{
this.parentClick();
this.reset();
this.$wf.toast({type:'success',text:'保存成功'});
}).catch(err=>{
})
},
cancel(){
this.reset();
},
reset(){
this.form.app_name = '';
this.form.stream_name = '';
this.form.stream_type = 1;
this.form.monitor_ip = '';
this.form.monitor_port = '';
this.form.monitor_account = '';
this.form.monitor_password = '';
},
parentClick(){
const pages = getCurrentPages();
if (pages.length >= 2) {
const prevPage = pages[pages.length - 2];
prevPage.$vm.getList();
}
}
}
}
</script>
<style scoped lang="scss">
.page_content{padding: 0 12px;}
.content_row{display: flex;border-bottom: 1px solid #2D3A6F;height: 44px;align-items: center;
.name{flex-basis: 96px;}
.text{flex: 1;}
.tip{width: 70%;font-size: 10px;color: #666;}
.flex_layout{
.contenticon{width: 16px;height: 16px;}
.text{padding: 0 20px 0 5px;}
}
}
.switch{display: flex;align-items: center;}
</style>

View File

@ -0,0 +1,71 @@
<template>
<view class="page_padding">
<view class="detail_list contentboxsty page_content font13">
<view class="content_row">
<view class="name font_bold">设备</view>
<view class="text">{{form.eq_name}}</view>
</view>
<view class="content_row">
<view class="name font_bold">设备名称</view>
<view class="text">{{form.name}}</view>
</view>
<view class="content_row">
<view class="name font_bold">设备功率</view>
<view class="text">{{form.power}}</view>
</view>
<view class="content_row">
<view class="name font_bold">设备IP</view>
<view class="text">{{form.equipment_configs.length>0? form.equipment_configs[0].ip:''}}</view>
</view>
<view class="content_row">
<view class="name font_bold">端口</view>
<view class="text">{{form.equipment_configs.length>0? form.equipment_configs[0].port:''}}</view>
</view>
<view class="content_row">
<view class="name font_bold">状态</view>
<view class="text">{{form.active_status==true?'启用':'禁用'}}</view>
</view>
<view class="textarea_row">
<view class="name font_bold font13">备注</view>
<view class="text textareaText">
{{form.remark}}
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
form:{
equipment_configs:[
{ip:'',port:''}
]
}
}
},
onLoad(options){
this.getDetail(options.id);
},
methods: {
getDetail(id){
this.$api.postFuncLoading('/device.info',{id:id}).then(res=>{
this.form = res.data
})
},
}
}
</script>
<style scoped lang="scss">
.content_row{display: flex;align-items: center;padding-top: 17px;
.name{flex-basis: 80px;}
.text{flex: 1;}
}
.textarea_row{
.name{padding: 17px 0;}
.textareaText{min-height: 80px;}
}
</style>

View File

@ -0,0 +1,229 @@
<template>
<page-meta>
<navigation-bar :title="this.form.id && this.form.id > 0?'编辑设备':'添加设备'"></navigation-bar>
</page-meta>
<view class="page_padding bot_padding">
<view class="page_content contentboxsty font13">
<view class="content_row">
<view class="name font_bold">选择设备</view>
<pickerSelect class="comView" @change="equipmentChange" :list="setMap.equipment" :id="form.eq_no" placeholder="请选择设备" />
</view>
<view class="content_row">
<view class="name font_bold">设备自定义名称</view>
<view class="comView">
<input v-model="form.name" placeholder="请输入设备名称"/>
</view>
</view>
<view class="content_row">
<view class="name font_bold">设备编号</view>
<view class="comView">
<input v-model="form.code" placeholder="请输入设备编号"/>
</view>
</view>
<view class="content_row">
<view class="name font_bold">设备功率</view>
<view class="comView">
<input v-model="form.power" placeholder="请输入设备功率"/>
</view>
</view>
<view class="content_row">
<view class="name font_bold">设备IP</view>
<view class="comView">
<input v-model="form.config[0].ip" placeholder="请输入设备IP"/>
</view>
</view>
<view class="content_row">
<view class="name font_bold">端口</view>
<view class="comView">
<input v-model="form.config[0].port" placeholder="请输入设备端口"/>
</view>
</view>
<view class="content_row">
<view class="name font_bold">型号</view>
<view class="flex_layout comView">
<view class="switch" @click="form.config[0].plc_model = 'H3U'">
<view v-if="form.config[0].plc_model=='H3U'" class="t-icon t-icon-qiyong1 contenticon"></view>
<view v-else class="t-icon t-icon-jinyong1 contenticon"></view>
<text class="text">H3U</text>
</view>
<view class="switch" @click="form.config[0].plc_model = 'H5U'">
<view v-if="form.config[0].plc_model=='H5U'" class="t-icon t-icon-qiyong1 contenticon"></view>
<view v-else class="t-icon t-icon-jinyong1 contenticon"></view>
<text class="text">H5U</text>
</view>
</view>
</view>
<view class="content_row">
<view class="name font_bold">逻辑控制器(PLC)</view>
<pickerSelect class="comView" :list="setMap.plc" :id="form.plc_lj" placeholder="请选择设备" />
</view>
<view class="content_row">
<view class="name font_bold">状态</view>
<view class="flex_layout comView">
<view class="switch" @click="form.active_status=true">
<view v-if="form.active_status" class="t-icon t-icon-qiyong1 contenticon"></view>
<view v-else class="t-icon t-icon-jinyong1 contenticon"></view>
<text class="text">启用</text>
</view>
<view class="switch" @click="form.active_status=false">
<view v-if="!form.active_status" class="t-icon t-icon-qiyong1 contenticon"></view>
<view v-else class="t-icon t-icon-jinyong1 contenticon"></view>
<text class="text">禁用</text>
</view>
</view>
</view>
<view class="textarea_row">
<view class="name font_bold">设置备注</view>
<view class="textarea">
<textarea placeholder="请输入备注..." v-model="form.remark" cursor-spacing="180px" :auto-blur="true" placeholder-class="placeholderStyle" />
</view>
</view>
</view>
</view>
<view class="bottom_but flex_layout">
<view class="font13 but_color" @click="save">保存</view>
<view class="font13" @click="cancel">取消</view>
</view>
</template>
<script>
export default {
data() {
return {
setMap:{
equipment:[],
plc:[
{name:'汇川',value:1}
]
},
form:{
id:'',
eq_no:'',
name:'',
code:'',
power:'',
remark:'',
active_status:true,
plc_lj:1,
config:[
{
eq_type:'',
ip:'',
port:'',
plc_model:'H3U'
}
]
}
}
},
mounted() {
},
onLoad(option) {
this.form.id = option.id;
if(option.id!='undefined'){
this.getOrderInfo(option.id);
}
},
onReady() {
this.getEquipment();
},
methods: {
getOrderInfo(id){
this.$api.postFuncLoading('/device.info',{id:id}).then(res=>{
this.form = {
id:res.data.id,
eq_no:res.data.eq_no,
name:res.data.name,
code:res.data.code,
power:res.data.power,
remark:res.data.remark,
active_status:res.data.active_status,
plc_lj:1,
config:[
{
eq_type:res.data.equipment_configs[0].eq_type,
ip:res.data.equipment_configs[0].ip,
port:res.data.equipment_configs[0].port,
plc_model:res.data.equipment_configs[0].plc_model
}
]
}
}).catch(err=>{
})
},
getEquipment(){
this.$api.request('/equipment.select',{}).then(res=>{
res.data.forEach(item=>{
item.name = item.eq_name;
item.value = item.eq_no;
})
this.setMap['equipment'] = res.data;
})
},
equipmentChange(e){
this.form.eq_no = e.value;
this.form.name = e.name;
},
save(){
if(!(this.form.id && this.form.id>0)){
delete this.form.id
}
this.$api.postFuncLoading('/equipment.add',this.form).then(res=>{
this.parentClick();
this.reset();
this.$wf.toast({type:'success',text:'保存成功'});
})
},
cancel(){
this.reset();
},
reset(){
this.form = {
id:'',
eq_no:'',
name:'',
code:'',
power:'',
remark:'',
active_status:true,
plc_lj:1,
config:[
{
eq_type:'',
ip:'',
port:'',
plc_model:'H3U'
}
]
};
},
parentClick(){
const pages = getCurrentPages();
if (pages.length >= 2) {
const prevPage = pages[pages.length - 2];
prevPage.$vm.getList();
}
}
}
}
</script>
<style scoped lang="scss">
.page_name{margin-bottom: 10px;}
.page_content{padding: 0 12px 13px;}
.content_row{display: flex;border-bottom: 1px solid #2D3A6F;height: 44px;align-items: center;
.name{flex-basis: 110px;}
.switch{display: flex;align-items: center;
.contenticon{font-size: 15px;}
.text{padding: 0 20px 0 5px;}
}
}
.textarea_row{
.name{padding: 12px 0;}
.textarea{border-radius: 4px;background: $uni-bg-color-placeholder;padding:10px 12px;}
}
</style>

View File

@ -0,0 +1,138 @@
<template>
<!-- 设备管理 -->
<view class="page_padding bot_padding columnFlex">
<view class="flexBox">
<view v-for="(item,index) in list" :key="index" >
<view class="page_list contentboxsty font13" @click="toDeviceDetail(item.id)">
<view class="list_row">
<view class="name font_bold">设备名称</view>
<view class="text">
{{item.name}}
</view>
</view>
<view class="list_row padd_top12">
<view class="name font_bold">设备IP/端口</view>
<view class="text">{{item.equipment_monitor_config?item.equipment_monitor_config.monitor_ip+'/'+item.equipment_monitor_config.monitor_port:'-'}}</view>
</view>
<view class="list_row padd_top12">
<view class="name font_bold">已绑定设备</view>
<view class="text">
{{item.equipment_monitor_config && item.equipment_monitor_config.eq_name?item.equipment_monitor_config.eq_name:'-'}}
</view>
</view>
<view class="rightBtnView">
<view class="iconfont icon-bianji font18" @click.stop="toAddDevice(item.id)"></view>
<view class="iconfont icon-bangding font18" @click.stop="toBindingDevice(item.id)"></view>
</view>
</view>
</view>
<loadMore :noData="loadParams.noData" :loading="loadParams.loading" :loadEnd="loadParams.loadEnd" />
</view>
</view>
<view class="page_bottom_button">
<view class="page_add" @click="toAddDevice()">
<view class="icon iconfont icon-tianjia font20"></view>
<text class="font14">添加</text>
</view>
</view>
</template>
<script>
export default {
data() {
return {
params:{
page:1,
pageSize:10,
},
loadParams:{
noData:false,
loading:false,
loadEnd:false
},
list:[],
}
},
onReady() {
this.getList();
},
// 上拉刷新
onPullDownRefresh(){
this.params.page = 1;
this.loadParams = {
noData:false,
loading:false,
loadEnd:false
};
this.getList(2);
},
// 加载下一页
onReachBottom(){
if(!(this.loadParams.loadEnd || this.loadParams.noData)){
this.loadParams.loading = true;
this.params.page ++;
this.getList();
}
},
methods: {
getList(type=1){
if(this.params.page == 1){
uni.showLoading({
title: '加载中',
mask: true
})
}
this.$api.request('/equipment.mag',this.params).then(res=>{
if(type ==2){
uni.stopPullDownRefresh();
}
setTimeout( ()=> {
uni.hideLoading();
}, 200);
this.loadParams.loading = false;
if(res.data.rows.length ==0 && this.params.page == 1){
this.loadParams.noData = true;
}
if(res.data.rows.length>0 && res.data.rows.length < this.params.pageSize){
this.loadParams.loadEnd = true;
}
if(this.params.page == 1){
this.list = res.data.rows;
}else{
this.list = this.list.concat(res.data.rows);
}
}).catch(err=>{
setTimeout(()=> {
uni.hideLoading();
}, 200);
})
},
//详情
toDeviceDetail(id){
uni.navigateTo({
url:'/pages/equipmentManage/deviceDetail?id='+id
})
},
toAddDevice(params){
uni.navigateTo({
url:'/pages/equipmentManage/editDevice?id='+params
})
},
toBindingDevice(id){
uni.navigateTo({
url:'/pages/equipmentManage/bindingDevice?id='+id
})
}
}
}
</script>
<style scoped lang="scss">
.page_list{padding: 12px;position: relative;}
.list_row{display: flex;align-items: center;}
.list_row .name{flex-basis: 84px;text-align: right;padding-right: 12px;box-sizing: border-box;}
.list_row .text{flex: 1;display: flex;justify-content: space-between;align-items: center;}
.rightBtnView{position: absolute;right: 12px;top: 12px;height: calc(100% - 24px);display: flex;flex-direction: column;justify-content: space-between;}
</style>

View File

@ -1,12 +1,164 @@
<template> <template>
<view class="home">
<view class="container home">
<view class="home_head"> <view class="home_head">
<view class="iconfont icon-chaojiguanliyuan accounticon"></view> <view class="iconfont icon-chaojiguanliyuan accounticon"></view>
<view class="name">Ykxiao 超级管理员</view> <view class="name" v-if="userName==''" @click="toLogin()">未登录</view>
<view class="name" v-else>{{userName}} </view>
<view class="iconfont icon-xiaoxitongzhi notifyicon" @click="toMessage()"></view> <view class="iconfont icon-xiaoxitongzhi notifyicon" @click="toMessage()"></view>
<view class="iconfont icon-shezhi setupicon"></view> <view class="iconfont icon-shezhi setupicon"></view>
</view> </view>
<view class="home_content"> <view class="home_content">
<view class="content_box">
<view class="content_title">设备信息</view>
<view class="device_data">
<view class="device_module">
<view class="module_left">
<view class="icon_background">
<view class="iconfont icon-WIFI_on contenticon"></view>
</view>
<view class="font13">
在线设备
</view>
</view>
<view class="module_right">
<view class="top">
2.89%
</view>
<view class="num font22">
1,567
</view>
</view>
</view>
<view class="device_module">
<view class="module_left">
<view class="icon_background">
<view class="iconfont icon-WIFI_off contenticon"></view>
</view>
<view class="font13">
离线设备
</view>
</view>
<view class="module_right">
<view class="top">
2.89%
</view>
<view class="num font22">
1,567
</view>
</view>
</view>
<view class="device_module">
<view class="module_left">
<view class="icon_background">
<view class="iconfont icon-setting contenticon"></view>
</view>
<view class="font13">
维修保养
</view>
</view>
<view class="module_right">
<view class="top">
2.89%
</view>
<view class="num font22">
1,567
</view>
</view>
</view>
<view class="device_module">
<view class="module_left">
<view class="icon_background">
<view class="iconfont icon-broken contenticon"></view>
</view>
<view class="font13">
故障频次
</view>
</view>
<view class="module_right">
<view class="top">
2.89%
</view>
<view class="num font22">
1,567
</view>
</view>
</view>
<view class="device_module">
<view class="module_left">
<view class="icon_background">
<view class="iconfont icon-brokenrate contenticon"></view>
</view>
<view class="font13">
设备故障率
</view>
</view>
<view class="module_right">
<view class="top">
2.89%
</view>
<view class="num font22">
1,567
</view>
</view>
</view>
<view class="device_module">
<view class="module_left">
<view class="icon_background">
<view class="iconfont icon-weixiubaoyangpinshuai contenticon"></view>
</view>
<view class="font13">
维修保养频率
</view>
</view>
<view class="module_right">
<view class="top">
2.89%
</view>
<view class="num font22">
1,567
</view>
</view>
</view>
</view>
</view>
<view class="content_box">
<view class="content_title">能耗信息</view>
<view class="energy_data">
<view class="iconfont icon-dianliang energy_icon"></view>
<view class="energy_name">
<view class="font13">
用电量
</view>
<view class="font14">
345.00
</view>
</view>
<view class="energy_image">
<image src="http://dm-auto.oss-cn-shanghai.aliyuncs.com/mes_wechat/yongdian.png" alt="" />
</view>
<view class="energy_number font20">
41.443
</view>
</view>
<view class="energy_data mar_top12">
<view class="iconfont icon-yasuokongqi energy_icon"></view>
<view class="energy_name">
<view class="font13">
用气量
</view>
<view class="font14">
345.00
</view>
</view>
<view class="energy_image">
<image src="http://dm-auto.oss-cn-shanghai.aliyuncs.com/mes_wechat/yongqi.png" alt="" />
</view>
<view class="energy_number font20">
41.443
</view>
</view>
</view>
<view class="content_box"> <view class="content_box">
<view class="content_title">工单管理</view> <view class="content_title">工单管理</view>
<view class="content_data"> <view class="content_data">
@ -14,122 +166,198 @@
<view class="t-icon t-icon-shengchangongdan contenticon"></view> <view class="t-icon t-icon-shengchangongdan contenticon"></view>
<view class="contentname">生产工单</view> <view class="contentname">生产工单</view>
</view> </view>
<view class="content_module">
<view class="t-icon t-icon-gongdanjindu contenticon"></view>
<view class="contentname">工单进度</view>
</view>
<view class="content_module">
<view class="t-icon t-icon-gongdanchucaishuai contenticon"></view>
<view class="contentname">工单出材率</view>
</view>
<view class="content_module"> <view class="content_module">
<view class="t-icon t-icon-shengchanbaobiao contenticon"></view> <view class="t-icon t-icon-shengchanbaobiao contenticon"></view>
<view class="contentname">生产报表</view> <view class="contentname">生产报表</view>
</view> </view>
</view> </view>
</view> </view>
<view class="content_box"> <view class="content_box">
<view class="content_title">生产排程</view> <view class="content_title">生产排程</view>
<view class="content_data"> <view class="content_data">
<view class="content_module"> <view class="content_module" @click="toSchedul()">
<view class="t-icon t-icon-paichengguanli contenticon"></view> <view class="t-icon t-icon-paichengguanli contenticon"></view>
<view class="contentname">排程管理</view> <view class="contentname">排程管理</view>
</view>
<view class="content_module" @click="toSchedule()">
<view class="t-icon t-icon-gongdanjindu contenticon"></view>
<view class="contentname">工单进度</view>
</view>
<view class="content_module" @click="toMaterialYield()">
<view class="t-icon t-icon-gongdanchucaishuai contenticon"></view>
<view class="contentname">工单出材率</view>
</view> </view>
<view class="content_module"> <!-- <view class="content_module">
<view class="t-icon t-icon-paichengshichang contenticon"></view> <view class="t-icon t-icon-paichengshichang contenticon"></view>
<view class="contentname">排程时长</view> <view class="contentname">排程时长</view>
</view> </view> -->
</view> </view>
</view> </view>
<view class="content_box"> <view class="content_box">
<view class="content_title">设备管理</view> <view class="content_title">设备管理</view>
<view class="content_data"> <view class="content_data">
<view class="content_module"> <view class="content_module" @click="toEquipmentManage()">
<view class="t-icon t-icon-shebeiguanli contenticon"></view> <view class="t-icon t-icon-shebeiguanli contenticon"></view>
<view class="contentname">设备设置</view> <view class="contentname">设备管理</view>
</view> </view>
<view class="content_module"> <view class="content_module" @click="toDeviceStatus()">
<view class="t-icon t-icon-shebeizhuangtai contenticon"></view> <view class="t-icon t-icon-shebeizhuangtai contenticon"></view>
<view class="contentname">设备状态</view> <view class="contentname">设备状态</view>
</view> </view>
<view class="content_module"> <view class="content_module" @click="toDeviceRepair()">
<view class="t-icon t-icon-shebeibaoxiu contenticon"></view> <view class="t-icon t-icon-shebeibaoxiu contenticon"></view>
<view class="contentname">设备</view> <view class="contentname">设备</view>
</view> </view>
</view> </view>
</view> </view>
</view> </view>
<tab-bar :current-page="0"></tab-bar>
</view> </view>
</template> </template>
<script> <script>
export default { import tabBar from "@/components/customTabBar/index"
export default {
components:{
tabBar
},
data() { data() {
return { return {
userName: '',
} }
}, },
// onLoad() {
// this.userName = uni.getStorageSync('demu_mes_user_name')
// },
onShow(){
this.userName = uni.getStorageSync('demu_mes_user_name')
},
// created() {
// },
mounted() {
this.userName = uni.getStorageSync('demu_mes_user_name')
},
methods: { methods: {
//
toLogin(){
uni.navigateTo({
url:'/pages/login/login'
})
},
//跳转消息页 //跳转消息页
toMessage(){ toMessage(){
uni.navigateTo({ uni.navigateTo({
url: '/pages/index/message' url: '/pages/index/message'
}) })
}, },
//跳转生产工单页 //跳转生产工单页
toProductionOrder(){ toProductionOrder(){
uni.navigateTo({ uni.navigateTo({
url:'/pages/index/productionOrder' url:'/pages/production/productionOrder'
})
},
// 工单排程
toSchedul(){
uni.navigateTo({
url:'/pages/schedul/list'
})
},
//跳转工单进度页
toSchedule(){
uni.navigateTo({
url:'/pages/index/schedule'
})
},
//跳转工单出材率页
toMaterialYield(){
uni.navigateTo({
url:'/pages/index/materialYield'
})
},
//跳转设备管理页面
toEquipmentManage(){
uni.navigateTo({
url:'/pages/equipmentManage/equipmentManage'
})
},
//跳转设备报修页
toDeviceRepair(){
uni.navigateTo({
url:'/pages/deviceRepair/deviceRepair'
})
},
//跳转设备状态
toDeviceStatus(){
uni.navigateTo({
url:'/pages/deviceStatus/deviceStatus'
}) })
}, },
} }
} }
</script> </script>
<style> <style lang="scss">
/* .icon { .home {padding: 0 10px;font-size: 14px;
width: 80upx; .home_head{height: 40px;display: flex;position: relative;align-items: center;padding-bottom: 5px;
height: 80upx; .name{flex:1;}
vertical-align: -0.15em; .accounticon{
fill: currentColor; margin-right: 5px;
overflow: hidden; color: $uni-text-color-inverse;
} */ font-size: 20px;
.home { }
height: 100vh; .notifyicon{font-size: 20px;padding-right: 20px;}
/* background-color: #060B26; */ .setupicon{font-size: 20px;}
padding: 0 10px; }
font-size: 14px;
} }
.home_head{height: 40px;display: flex;position: relative;align-items: center;padding-bottom: 5px;}
.home_head .name{flex:1;} .home_content{padding-bottom: 100px;
.accounticon{ .content_title{line-height: 25px;font-size: 16px;padding: 15px 0;}
/* width: 20px; .device_data{display: flex;flex-wrap: wrap;
height: 20px; */ .device_module{
margin-right: 5px; width: calc(50% - 6px); /* 计算每个块的宽度(根据需要调整)*/
color: #fff; // background-color: #ccc; /* 设置背景色(根据需要调整)*/
font-size: 20px; background: $uni-bg-color-primary;
margin:6px;
padding: 10px 14px;
border-radius: 8px;
display: flex;
.module_left{width: 60%;
.icon_background{width: 32px;height: 32px;background: $uni-bg-color-info;border-radius: 8px; display: flex;align-items: center;justify-content: center;margin-bottom: 4px;}
}
.module_right{width: 40%;
.top{
display: flex;flex-direction: column; font-size: 10px;padding: 2px 4px;background: rgba(103,194,58,0.3);border-radius: 4px;color: $uni-text-color-success;
}
.num{
margin-top: 6px;
}
}
}
.device_module:nth-child(even){
margin-right: 0;
}
.device_module:nth-child(odd){
margin-left: 0;
}
}
.energy_data{padding: 12px; height: 64px; display: flex;align-items: center;background: $uni-bg-color-primary;border-radius: 8px;
.energy_icon{color: $uni-text-color-primary;font-size: 24px;margin-right: 8px;}
.energy_image{flex: 1;text-align: center;
image{width: 86px;height: 32px;}
}
.energy_number{color: $uni-text-color-danger;}
}
.content_data{
padding: 10px 0;display: flex;position: relative;align-items: center;justify-content:flex-start;height: 98px;
.content_module{
width: calc(25% - 7px);margin: 10px 4px;height: 98px;display: flex;align-items: center;justify-content: center;flex-direction: column;background-color: $uni-color-primary;border-radius: 8px;
.contenticon{font-size: 24px;width: 32px;height: 32px;background-repeat: no-repeat;}
.contentname{padding-top: 2px;font-size: 12px;}
}
}
} }
.notifyicon{font-size: 20px;padding-right: 20px;}
.setupicon{font-size: 20px;}
.home_content{
}
.content_title{
line-height: 25px;
font-size: 16px;
}
.content_data{padding: 10px 0;display: flex;position: relative;align-items: center;text-align: center;height: 98px;}
.content_module{
width: 25%;
margin: 10px 1%;
height: 98px;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
background-color: #009688;
border-radius: 8px;
}
.contenticon{font-size: 24px;width: 32px;height: 32px;background-repeat: no-repeat;}
.contentname{padding-top: 2px;font-size: 12px;}
</style> </style>

View File

@ -0,0 +1,121 @@
<template>
<!-- 工单出材率 -->
<view class="page_padding font13">
<view v-for="(item,index) in list" :key="index" class="detail_list contentboxsty" @click="toDetail(498)">
<view class="list_top">
<view class="top_left">
工单号{{item.name}}
</view>
<view class="top_right">
工单详情 <text class="arrow iconfont icon-gengduo"></text>
</view>
</view>
<view class="list_content font13">
<view class="list_centre">
<view class="list_row">
<view class="centre_left">
<text class="name">加工规格</text>
<text class="text">{{item.specs}}</text>
</view>
</view>
<view class="list_row">
<view class="centre_left">
<text class="name">算法出材率</text>
<text class="text">{{item.algorithm}}%</text>
</view>
</view>
</view>
<view class="list_below">
<view class="below_left">
<view class="circle-progress">
<view class="progressBg">
<view class="progressBox">
<view class="percentage font22">
{{item.algorithm}}%
</view>
<view class="title font12">
出材率
</view>
</view>
</view>
<view class="circle-progress__bar" :style="'--progress:'+item.algorithm+'%'"></view>
</view>
</view>
</view>
<view class="card_right">
<view class="status">生产中</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
list:[{
name:'SO202401111004',
algorithm:'51.5',
reality:'81.4',
state:'生产中',
specs:'4*9*3.66',
time:'jan-11 10:05',
timeConsuming:'3.5H',
number:'12.66m³'
},{
name:'SO202401111004',
algorithm:'81.5',
reality:'81.4',
state:'生产中',
specs:'4*9*3.66',
time:'jan-11 10:05',
timeConsuming:'3.5H',
number:'12.66m³'
},{
name:'SO202401111004',
algorithm:'61.5',
reality:'81.4',
state:'生产中',
specs:'4*9*3.66',
time:'jan-11 10:05',
timeConsuming:'3.5H',
number:'12.66m³'
},{
name:'SO202401111004',
algorithm:'81.5',
reality:'81.4',
state:'生产中',
specs:'4*9*3.66',
time:'jan-11 10:05',
timeConsuming:'3.5H',
number:'12.66m³'
}]
}
},
methods: {
toDetail(id){
uni.navigateTo({
url:'/pages/production/productionDetail?id='+id
})
},
}
}
</script>
<style scoped lang="scss">
.detail_list{
.list_centre{
.list_row{display: flex;padding-bottom: 12px;
.centre_left{
flex: 1;
.name{width:80px;display: inline-block;font-weight: bold;}
}
}
}
.list_below{display: flex;text-align: center;padding: 10px 0;
.below_left{flex: 1;display: flex;align-items: center;justify-content: center;}
.percentage{color: $uni-text-color-inverse;}
}
}
</style>

View File

@ -24,7 +24,7 @@
</view> </view>
<view class="con_but"> <view class="con_but">
<view class="but_rat"><view class="t-icon t-icon-shenpizhida icon22"></view>审批</view> <view class="but_rat"><view class="t-icon t-icon-shenpizhida icon22"></view>审批</view>
<view class="but_del"><view class="t-icon t-icon-shezhi icon22 paddrigth5"></view>删除</view> <view class="but_del"><view class="t-icon t-icon-shezhi icon22 padd_rigth5"></view>删除</view>
</view> </view>
</view> </view>
</view> </view>

View File

@ -1,42 +0,0 @@
<template>
<!-- 生产工单 -->
<view class="pagepaddings">
<view v-for="(item,index) in list" :key="index" class="page_list">
<view class="list_top">
<view class="top_left">
工单号:{{item.name}}
</view>
<view class="top_right">
工单详情
</view>
</view>
<view class="list_centre">
</view>
<view class="list_below">
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
list:[{
name:'SO202401111004',
}]
}
},
methods: {
}
}
</script>
<style>
</style>

78
pages/index/schedule.vue Normal file
View File

@ -0,0 +1,78 @@
<template>
<!-- 工单进度管理 -->
<view class="page_padding columnFlex">
<view class="headerView" :class="headerFixed?'headerViewFixed':''">
<searchView placeholder=" 搜索工单" />
</view>
<view class="flexBox">
<view class="detail_list contentboxsty font13" v-for="(item,index) in list" :key="index">
<view @click="toDetail(497)">
<view class="list_top">
<view class="top_left">
工单号{{item.sn}}
</view>
<view class="top_right">
工单详情<text class="arrow iconfont icon-gengduo"></text>
</view>
</view>
<view class="list_content">
<view class="list_row">
<text class="name">开始时间</text>
<text class="text">24-01-12 08:00</text>
</view>
<view class="list_row padd_top12">
<text class="name">计划完成</text>
<text class="text">24-01-12 08:00</text>
</view>
<view class="padd_top12">
<progressBar :total="100" :val="item.num" title="" />
</view>
<view class="card_right">
<view class="status">生产中</view>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
components: {
},
data() {
return {
list:[
{name:'',sn:"SO20240422000002",num:20},{name:'',sn:"SO20240422000002",num:70},{name:'',sn:"SO20240422000002",num:90},
{name:'',sn:"SO20240422000002",num:20},{name:'',sn:"SO20240422000002",num:70},{name:'',sn:"SO20240422000002",num:90}
]
}
},
methods: {
toDetail(id){
uni.navigateTo({
url:'/pages/production/productionDetail?id='+id
})
},
}
}
</script>
<style scoped lang="scss">
.page_padding{
padding-top: 0;
}
.detail_list{
.list_content{
.list_row{
.name{
width: 65px;
display: inline-block;
font-weight: bold;
}
}
}
}
</style>

View File

@ -1,49 +1,56 @@
<template> <template>
<view class="login_page "> <view class="login_page ">
<view class="iconfont icon-shouye" @click="toIndex()" style="height: 25px;position: absolute;top: 60px;width: 30px;"></view>
<view class="login_top"> <view class="login_top">
<view class="login_logo"> <view class="login_logo">
<image src="https://dm-auto.oss-cn-shanghai.aliyuncs.com/mes_wechat/meslogo.png" class="logopng"></image> <image src="https://dm-auto.oss-cn-shanghai.aliyuncs.com/mes_wechat/loginLogo.png" class="demupng"></image>
<image src="https://dm-auto.oss-cn-shanghai.aliyuncs.com/mes_wechat/demu.png" class="demupng"></image>
</view> </view>
<view class=""> <view class="name">
自动化MES管理系统 自动化MES管理系统
</view> </view>
</view> </view>
<view class="login_centre"> <view class="login_centre">
<view class="login_switch text_color_black font14"> <view class="login_switch text_color_black font14">
<view class="login_name font_bold" > <view :class="['login_name', tab==1?'font_bold':'']" @click="changeTab(1)">
账号登录 账号登录
</view> </view>
<view class="login_name"> <view :class="['login_name', tab==2?'font_bold':'']" @click="changeTab(2)">
手机号登录 手机号登录
</view> </view>
</view> </view>
<view class="font12 text_color_black" v-if="type==1"> <view class="font12 text_color_black" v-if="tab==1">
<view class="login_input"> <view class="login_input">
<input placeholder="请输入账号" /> <input placeholder="请输入账号" v-model="accountValue"/>
</view> </view>
<view class="login_input"> <view class="login_input">
<input password type="text" placeholder="请输入密码" /> <input password type="text" v-model="passValue" placeholder="请输入密码" />
</view> </view>
</view> </view>
<view class="font12" v-if="type==2"> <view class="font12 text_color_black" v-if="tab==2">
<view class="login_input"> <view class="login_input">
<input placeholder="请输入手机号"/> <input placeholder="请输入手机号"/>
</view> </view>
<view class=""> <view class="flex_layout">
<input placeholder="请输入手机号"/> <input class="login_input login_code" placeholder="请输入验证码"/>
<view class="getCaptcha">{{codename}}</view> <view class="getCaptcha">{{codename}}</view>
</view> </view>
</view> </view>
<view class="" style="color: #C4C4C4;font-size: 11px; padding-top: 14px;"> <view class="" v-if="tab==1" style="color: #C4C4C4;font-size: 12px;padding-top: 14px;">
记住密码 记住密码
</view> </view>
<view class="loginbut"> <view class="loginbut" @click="login()">
登录 登录
</view> </view>
<view class="" style="color: #009688;text-align: center;font-size: 13px;"> <button class="persontc " type="default" open-type="getPhoneNumber" @getphonenumber="getPhone">
手机号一键登录 <view class="" style="color: #009688;text-align: center;font-size: 13px;">
</view> 手机号快捷登录
</view>
</button>
<!-- <button class="persontc" open-type="getPhoneNumber" @getphonenumber="getPhoneNumber">
<view class="" style="color: #009688;text-align: center;font-size: 13px;">
手机号快捷登录
</view>
</button> -->
</view> </view>
<view class="login_below"> <view class="login_below">
<view class=""> <view class="">
@ -52,46 +59,99 @@
<view class=""> <view class="">
</view> </view>
</view> </view>
</view> </view>
</template> </template>
<script> <script>
export default { export default {
data() { data() {
return { return {
codename:'获取验证码', codename:'获取验证码',
type:1, tab:1,
} accountValue:'long',
}, passValue:'123456',
methods: { }
},
} methods: {
} //切换登录方式
</script> changeTab(tab){
this.$set(this,"tab",tab);
},
toIndex(){
uni.reLaunch({
url:'/pages/index/index'
});
},
login(){
this.$api.postFuncLoading('/user.login',{login_name:this.accountValue,password:this.passValue}).then(res=>{
let obj = new Object();
obj.mes_user_name=res.data.user.name;
obj.mes_token=res.data.token;
this.$wf.setLoginData(obj)
uni.switchTab({
url:'/pages/index/index'
})
})
},
}
}
</script>
<style> <style>
.login_page{ .login_page{
padding: 0 32px; padding: 0 32px;
background: url('https://dm-auto.oss-cn-shanghai.aliyuncs.com/mes_wechat/background.png') no-repeat; background: url('https://dm-auto.oss-cn-shanghai.aliyuncs.com/mes_wechat/background.png') no-repeat;
background-position: center center; background-position: center;
background-size: cover; background-size: cover;
height: 100vh; height: 100vh;
} }
.login_top{padding-top: 160px;padding-bottom: 32px;}
.login_top{padding-top: 160px;padding-bottom: 32px;} .login_top .name{letter-spacing: 1.2px;background: linear-gradient(to right, #fff, rgba(255,255,255,0.1));
.login_logo{display: flex;align-items: center;margin-bottom: 17px;} -webkit-background-clip: text;
.logopng{width: 53px;height: 44px;} -webkit-text-fill-color: transparent;
.demupng{width: 60px;height: 36px;} }
.login_logo{display: flex;align-items: center;margin-bottom: 17px;}
.demupng{width: 117px;height: 43px;}
.login_centre{border-radius: 16px;background: #FFF;padding: 20px 24px 40px;} .login_centre{border-radius: 16px;background: #FFF;padding: 20px 24px 40px;}
.login_switch{display: flex;} .login_switch{display: flex;}
.login_name{flex: 1;text-align: center;} .login_name{flex: 1;text-align: center;
.login_input{border-radius: 21.5px;background: #F3F5F9; margin-top: 12px; padding: 5px 15px;} padding-bottom: 5px;
.loginbut{ margin-bottom: 10px;
background: #009688; }
text-align: center; .login_name:focus {
margin-top: 60px; outline: none; /* 去除默认的外边框效果 */
margin-bottom: 18px; border-width: 3px; /* 当元素被点击或者获得焦点时将边框宽度修改为3像素 */
padding: 9px; }
border-radius: 66rpx;} .font_bold{
</style> position: relative;
}
.font_bold::after{
content: '';
position: absolute;
left: calc(50% - 15px);
bottom: -4px;
z-index: 10;
width: 30px;
border-bottom: 3px solid #009688;
}
.login_input{border-radius: 21.5px;background: #F3F5F9;margin-top: 12px;padding: 9px 15px;font-size: 14px;}
.getCaptcha{border-radius: 21.5px;background: #009688;height: auto;color: white;display: flex;align-items: center;width: 40%;justify-content: center;}
.flex_layout{display: flex;margin-top: 12px;}
.login_code{margin-top: unset;width:60%;margin-right: 12px;}
.loginbut{background: #009688;text-align: center;margin-top: 40px;margin-bottom: 18px;padding: 9px;border-radius: 66rpx;}
.persontc{
border: none;
margin: 0;
padding: 0;
outline: none;
border-radius: 0;
background: none!important;
line-height: normal;
}
.persontc::after {
border: none;
}
</style>

View File

@ -1,16 +1,18 @@
<template> <template>
<view class="person_page pagepaddings font13"> <view class="person_page page_padding font13">
<view class="person_dataA contentboxsty"> <view class="person_dataA contentboxsty">
<view class="content_box"> <view class="content_box logo_box">
<view class="data_name">头像</view> <view class="data_name">头像</view>
<view class=""> <view class="">
> <button class="person_button" open-type="chooseAvatar" @chooseavatar='onChooseAvatar'>
<image class="person_logo" :src="avatarUrl" mode="aspectFill"></image>
</button>
</view> </view>
</view> </view>
<view class="content_box"> <view class="content_box">
<view class="data_name">真实姓名</view> <view class="data_name">真实姓名</view>
<view class=""> <view class="">
> <text class="iconfont icon-gengduo"></text>
</view> </view>
</view> </view>
<view class="content_box noborbot"> <view class="content_box noborbot">
@ -33,7 +35,9 @@
<view class="person_dataC contentboxsty"> <view class="person_dataC contentboxsty">
<view class="content_box"> <view class="content_box">
<view class="data_name">设备故障通知</view> <view class="data_name">设备故障通知</view>
<view class=""></view> <view class="">
</view>
</view> </view>
<view class="content_box"> <view class="content_box">
<view class="data_name">出材率预警通知</view> <view class="data_name">出材率预警通知</view>
@ -49,28 +53,38 @@
<view class="data_name">清除缓存</view> <view class="data_name">清除缓存</view>
<view class=""></view> <view class=""></view>
</view> </view>
</view> </view>
</view> </view>
</template> </template>
<script> <script>
export default { const defaultAvatarUrl = 'https://dm-auto.oss-cn-shanghai.aliyuncs.com/mes_wechat/avatar.png';
data() {
return { export default {
data() {
} return {
}, avatarUrl:defaultAvatarUrl
}
},
methods: { methods: {
//跳转更改手机号页面 onChooseAvatar(e) {
uni.showToast({
title:'成功',
duration:1000
})
this.avatarUrl = e.detail.avatarUrl
},
//跳转更改手机号页面
toChangPhone(){ toChangPhone(){
uni.navigateTo({ uni.navigateTo({
url: '/pages/person/changePhone' url: '/pages/person/changePhone'
}) })
} }
} }
} }
</script> </script>
<style lang="scss" > <style lang="scss" >
.person_page{ .person_page{
.person_dataA{ .person_dataA{
@ -80,7 +94,15 @@
.person_dataB{padding: 0 14px;margin-bottom: 12px;} .person_dataB{padding: 0 14px;margin-bottom: 12px;}
.person_dataC{padding: 0 14px;margin-bottom: 12px;} .person_dataC{padding: 0 14px;margin-bottom: 12px;}
.person_dataD{padding: 0 14px;} .person_dataD{padding: 0 14px;}
.content_box{display: flex;align-items: center;height: 44px;border-bottom: 1px solid #2D3A6F;} .content_box{
display: flex;align-items: center;height: 44px;border-bottom: 1px solid #2D3A6F;
}
.logo_box{height: 64px;
.person_button{width: 40px;height: 40px;border-radius: 50%;padding: 0;}
.person_logo{width: 40px;height: 40px;}
}
.data_name{flex: 1;} .data_name{flex: 1;}
} }
</style>
</style>

60
pages/person/alarm.vue Normal file
View File

@ -0,0 +1,60 @@
<template>
<!-- 设备报警 -->
<view class="page_padding">
<view class="content_layout" @click="cancelLongpress">
<view class="item_layout" v-for="(item, index) in list" :key="index">
<view :class="islongpress?'longpress_style':''" @longpress="longpress" @click="deleteAlarm">
<image :src="item.url" class="img_style" mode=""></image>
</view>
<view class="font13 flex_layout">
<text class="flex1">{{item.name}}</text>
<text>{{item.time}}</text>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
islongpress:false,
list:[
{name:'周边侵入警报',time:'2023-09-01',url:'../../static/logo.png'},
{name:'周边侵入警报',time:'2023-09-01',url:'../../static/logo.png'},
{name:'周边侵入警报',time:'2023-09-01',url:'../../static/logo.png'},
]
}
},
methods: {
longpress(){
console.log('长按事件')
this.islongpress = true
},
//取消
cancelLongpress(){
this.islongpress = false
},
//删除警告
deleteAlarm(){
if(this.islongpress){
console.log('删除')
}
},
}
}
</script>
<style>
/* .content_layout{display: flex;flex-flow: wrap;}
.item_layout{width: 50%;} */
.content_layout{
display: grid;
grid-template-columns: 1fr 1fr;/* 每一列占一行的一半 */
grid-gap: 10px; /* 可选的间距 */
}
.img_style{height: 110px;width: 100%;}
.longpress_style{background-color: #000;
opacity: 0.2;}
</style>

View File

@ -1,22 +1,32 @@
<template> <template>
<view> <view class="page_padding font13">
<view class="phone_page contentboxsty">
</view> <view class="content_row">
</template> <input placeholder="请输入要更换的手机号码" />
</view>
<script> <view class="content_row noborbot">
export default { <input placeholder="请输入短信验证码" />
data() { <view class="theme_color">获取验证码</view>
return { </view>
</view>
} </view>
}, </template>
methods: {
<script>
} export default {
} data() {
</script> return {
<style> }
},
</style> methods: {
}
}
</script>
<style>
.phone_page{padding: 0 12px;}
.content_row{display: flex;height: 49px;align-items: center;border-bottom: 1px solid #2D3A6F;}
.content_row input{flex: 1;}
</style>

View File

@ -0,0 +1,464 @@
<template>
<view v-if="step==1">
<view class="scan_box">
<image class="avatar_frame" src="http://dm-auto.oss-cn-shanghai.aliyuncs.com/mes_wechat/morentouxiang.png" mode=""></image>
<image class="scan_img" src="http://dm-auto.oss-cn-shanghai.aliyuncs.com/mes_wechat/saomiao.png"></image>
</view>
<view class="start_view" @click="startAttestation(2)">
<view class="start_but">
开始认证
</view>
</view>
</view>
<view class="page-content" v-else-if="step==2">
<view class="containerV">
<view class="headerV">
<view class="top-tips1 font15">
<view>请把脸移入圈内保持不动</view>
</view>
<!-- <view class="top-tips2">
为了便于识别认证请拍摄本人头像
</view> -->
</view>
<view class="contentV">
<view class="mark"></view>
<image v-if="tempImg" mode="widthFix" :src="tempImg" />
<camera v-if='isAuthCamera' :device-position="devicePosition ?'front': 'back'" class="camera"
flash="off" resolution='high' />
<view v-show="!tempImg && tipsText" class="tipV">{{ tipsText }}</view>
</view>
<view class="footerV">
<view style="width: 100%;">
<view v-if="!tempImg" style="width: 100%;">
<!-- <view class="privacyV">
<view class="icon"></view>
<view class="text">
照片隐私<text @click="handleJumpSecurityClick">安全保障</text>
</view>
</view>
<view class="bottom-tips-2">该照片仅作为你认证的凭证</view> -->
<view class="take-photo-bgV">
<!-- 图片上传 -->
<!-- <view v-show="true" class="btn-change-upload" @click="handleChooseImage" ></view> -->
<!--拍照-->
<view class="btn-take-photo" @click="handleTakePhotoClick" ></view>
<!-- 切换镜头 -->
<view class="btn-change-camera" @click="handleChangeCameraClick" ></view>
</view>
</view>
<view class="confirmV" v-else>
<view class="btn-cancel" @click="handleCancelClick">
取消
</view>
<view class="btn-ok" @click="handleOkClick">
确定
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
name: 'index',
components: {
},
data() {
return {
step:1,
tipsText: '', // 错误文案提示
tempImg: '', // 本地图片路径
// BASE_API,
cameraEngine: null, // 相机引擎
devicePosition: false, // 摄像头朝向
isAuthCamera: true, // 是否拥有相机权限
}
},
onLoad(options) {
this.initData()
},
mounted(){
},
methods: {
//
startAttestation(type){
this.step=type;
},
// 初始化相机引擎
initData() {
this.handleChangeCameraClick();
// console.log(1111)
// const session = wx.createVKSession({
// track: {
// face: { mode: 1 } // mode: 1 - 使用摄像头2 - 手动传入图像
// },
// })
// console.log(222)
// // 摄像头实时检测模式下监测到人脸时updateAnchors 事件会连续触发 (每帧触发一次)
// session.on('updateAnchors', anchors => {
// anchors.forEach(anchor => {
// console.log('anchor.points', anchor.points)
// console.log('anchor.origin', anchor.origin)
// console.log('anchor.size', anchor.size)
// console.log('anchor.angle', anchor.angle)
// })
// })
// console.log(333)
// // 当人脸从相机中离开时,会触发 removeAnchors 事件
// session.on('removeAnchors', () => {
// console.log('removeAnchors')
// })
// // 需要调用一次 start 以启动
// session.start(errno => {
// if (errno) {
// // 如果失败,将返回 errno
// } else {
// // 否则返回null表示成功
// }
// })
// console.log(444)
this.cameraEngine = wx.createCameraContext()
const listener = this.cameraEngine.onCameraFrame((frame) => {
if (this.tempImg) {
return;
}
wx.createVKSession({
track: {
plane: {mode: 3},
},
version: 'v2',
// gl, // WebGLRenderingContext
})
})
// // #ifdef MP-WEIXIN
// // 1、初始化人脸识别
// wx.initFaceDetect()
// // 2、创建 camera 上下文 CameraContext 对象
// this.cameraEngine = wx.createCameraContext()
// // 3、获取 Camera 实时帧数据
// const listener = this.cameraEngine.onCameraFrame((frame) => {
// if (this.tempImg) {
// return;
// }
// // 4、人脸识别使用前需要通过 wx.initFaceDetect 进行一次初始化,推荐使用相机接口返回的帧数据
// wx.faceDetect({
// frameBuffer: frame.data,
// width: frame.width,
// height: frame.height,
// enablePoint: true,
// enableConf: true,
// enableAngle: true,
// enableMultiFace: true,
// success: (faceData) => {
// let face = faceData.faceInfo[0]
// if (faceData.x == -1 || faceData.y == -1) {
// this.tipsText = '检测不到人'
// }
// if (faceData.faceInfo.length > 1) {
// this.tipsText = '请保证只有一个人'
// } else {
// const {
// pitch,
// roll,
// yaw
// } = face.angleArray;
// const standard = 0.5
// if (Math.abs(pitch) >= standard || Math.abs(roll) >= standard ||
// Math.abs(yaw) >= standard) {
// this.tipsText = '请平视摄像头'
// } else if (face.confArray.global <= 0.8 || face.confArray.leftEye <=
// 0.8 || face.confArray.mouth <= 0.8 || face.confArray.nose <= 0.8 ||
// face.confArray.rightEye <= 0.8) {
// this.tipsText = '请勿遮挡五官'
// } else {
// this.tipsText = '请拍照'
// // 这里可以写自己的逻辑了
// }
// }
// },
// fail: (err) => {
// if (err.x == -1 || err.y == -1) {
// this.tipsText = '检测不到人'
// } else {
// this.tipsText = err.errMsg || '网络错误,请退出页面重试'
// }
// },
// })
// })
// 5、开始监听帧数据
// listener.start()
// #endif
},
// 切换设备镜头
handleChangeCameraClick() {
this.devicePosition = !this.devicePosition;
},
// 图片上传
handleChooseImage() {
uni.chooseImage({
count: 1,
sizeType: ['original', 'compressed'],
sourceType: ['album','camera'],
success: (res) => {
console.log(res,'打印res哈哈哈哈哈')
if (res.errMsg === 'chooseImage:ok') {
uni.showLoading({
title: '照片上传中...'
})
const tempFilePaths = res.tempFilePaths[0]
this.upLoad(res.tempFilePaths);
}
},
fail: (res) => {
},
});
},
// 拍照点击
handleTakePhotoClick() {
if (this.tipsText != "" && this.tipsText != "请拍照") {
return;
}
uni.getSetting({
success: (res) => {
if (!res.authSetting['scope.camera']) {
this.isAuthCamera = false
uni.openSetting({
success: (res) => {
if (res.authSetting['scope.camera']) {
this.isAuthCamera = true;
}
}
})
}
}
})
this.cameraEngine.takePhoto({
quality: "high",
success: ({
tempImagePath
}) => {
this.tempImg = tempImagePath
}
})
console.log(this.tempImg,2121)
},
// 点击确定上传
handleOkClick() {
// 这里的 this.tempImg 是经过人脸检测后 拍照拿到的路径
this.upLoadOne(this.tempImg)
uni.navigateBack({
delta: 1
});
},
upLoad(tempFilePaths) {
// # 注意 这里上传图片拿到的tempFilePaths是一个数组啊
// 图片上传
uni.showLoading({
title: "上传中,请稍后...",
});
let proAll = [];
tempFilePaths.forEach((item) => {
console.log(item,'打印item')
proAll.push(this.upLoadOne(item));
});
Promise.all(proAll).then((res) => {
// 上传完成
uni.hideLoading();
});
},
upLoadOne(imgPath) {
// 然后这里imgPath 传过来的是 要上传的临时本地图片的路径
// 具体上传方法根据自己的请求方式 请求自己的接口
},
// 点击 - 取消上传
handleCancelClick() {
this.tempImg = ''
},
// 点击 - 人脸安全保障按钮
handleJumpSecurityClick() {
uni.showToast({
icon: "none",
title: "假装跳转人脸安全保障",
duration: 2000,
})
},
}
}
</script>
<style lang="scss" scoped>
.scan_box{width: 200px;height: 200px;margin: 70px auto;border: 3px solid #009688;border-radius: 50%;background-color: #EEEEEE;
display: flex;justify-content: center;
}
.avatar_frame{width: 100%;height: 100%;}
.scan_img{height: 98px;padding-top: 14px; position: absolute;width: 200px;}
.start_view{display: flex;justify-content: center;padding-top: 20px;}
.start_but{width: 116px;height: 34px;border-radius: 29px;background: #009688;align-items: center;justify-content: center;display: flex;}
.page-content {
width: 100%;
height: 100%;
.containerV {
width: 100%;
height: 100%;
.headerV {
.top-tips1 {
margin-top: 60rpx;
color: #FFFFFF;
font-size: 36rpx;
text-align: center;
}
.top-tips2 {
margin-top: 20rpx;
color: #00AAFF;
font-size: 28rpx;
text-align: center;
}
}
.contentV {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 400rpx;
margin-top: 30rpx;
.tipV {
bottom: 30rpx;
position: absolute;
line-height: 90rpx;
padding-left: 24rpx;
padding-right: 24rpx;
max-width: calc(100vw - 50rpx * 2);
text-align: center;
font-size: 30rpx;
background: #000000;
opacity: 0.75;
color: #FFFFFF;
border-radius: 16rpx;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
z-index: 5;
}
.camera {
width: 400upx;
height: 400upx;
border-radius: 50%;
border: 3px solid #009688;
}
.mark {
position: absolute;
left: 0;
top: 0;
z-index: 2;
width: 750rpx;
height: 100%;
// background:deeppink;
background-size: 750rpx 661rpx;
}
image {
position: absolute;
width: 100%;
height: 100%;
z-index: 3;
}
}
.footerV {
width: 100%;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
.privacyV {
padding-top: 30rpx;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
.text {
font-size: 30rpx;
color: #1C1C1C;
text-align: center;
line-height: 42rpx;
margin-left: 15rpx;
text {
font-size: 30rpx;
color: #00AAFF;
text-align: center;
line-height: 42rpx;
}
}
.icon {
width: 40rpx;
height: 47rpx;
background:green;
background-size: 100% auto;
}
}
.bottom-tips-2 {
margin-top: 20rpx;
color: #999999;
text-align: center;
font-size: 26rpx;
}
.take-photo-bgV {
width: 100%;
margin-top: 300rpx;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
.btn-take-photo {
margin: 0rpx 80rpx 0rpx 80rpx;
width: 196rpx;
height: 196rpx;
background: yellow;
background-size: 100% auto;
}
.btn-change-upload {
left: 130rpx;
width: 80rpx;
height: 80rpx;
background: blue;
background-size: 100% auto;
}
.btn-change-camera {
right: 130rpx;
width: 80rpx;
height: 80rpx;
background:red;
background-size: 100% auto;
}
}
.confirmV {
margin: 200rpx 100rpx 0rpx 100rpx;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
.btn-cancel {
font-size: 32rpx;
color: #1C1C1C;
}
.btn-ok {
font-size: 32rpx;
color: #00AAFF;
}
}
}
}
}
</style>

View File

@ -0,0 +1,133 @@
<template>
<view class="page_padding checkbox-container">
<view class="contentboxsty" v-for="(item, index) in list" :key="index.id">
<view class="list_name listItem">
<checkbox-group @change="changeCheckbox">
<label>
<checkbox class="checkbox-custom" :class="{ 'checkbox_indeterminate': item.indeterminate }" :value="item.id" :checked="item.checked" style="transform:scale(0.6)" />
<text class="font14">{{item.name}}</text>
</label>
</checkbox-group>
</view>
<view class="list_content listItem padd_bot12" v-for="(i, ind) in item.child" :key="ind">
<view class="content_name">
<checkbox-group @change="selectPath(item,i)">
<label>
<checkbox class="checkbox-custom" :class="{ 'checkbox_indeterminate': i.indeterminate }" :value="i.id" :checked="i.checked" style="transform:scale(0.6)" />
<text class="font14">{{i.name}}</text>
</label>
</checkbox-group>
</view>
<view class="content_item">
<view class="content_data" v-for="(btn, inx) in i.child" :key="inx">
<checkbox-group @change="selectPath(item,i,inx)">
<label>
<checkbox class="checkbox-custom" :class="{ 'checkbox_indeterminate': btn.indeterminate }" :value="btn.id" :checked="btn.checked" style="transform:scale(0.6)" />
<text class="font14">{{btn.name}}</text>
</label>
</checkbox-group>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
list:[
{
id:1,name:'首页',checked:true,indeterminate:true,
child:[
{
id: 2,name:'控制台',checked:true,indeterminate:true,
child:[
{id:121,name:'设备信息',checked:true,},
{id:122,name:'生产加工信息',checked:true,},
{id:123,name:'设备能耗信息',},
],
},
{
id:124,name:'账号信息',
child:[
{id:125,name:'通知设置',},
{id:126,name:'升级角色'},
]
}
],
},
{
id:11,name:'生产工单',
child:[
{
id: 3,name:'待生产工单',
child:[
{name:'添加工单',id:31},
{name:'审核工单',id:32},
{name:'删除工单',id:33},
{name:'撤回工单',id:34},
],
},
{
id:4,name:'已排产工单',
child:[],
},
],
},
{
id:12,name:'生产排程',
child:[
{
id: 4,name:'工单排程表',
child:[
{name:'创建生产计划',id:41},
{name:'修改生产计划',id:42},
{name:'拆分生产计划',id:43},
{name:'删除生产计划',id:44},
{name:'创建计划依赖',id:45},
{name:'删除计划依赖',id:46},
],
},
]
}
],
arr:[]
}
},
methods: {
checkboxChange: function (e) {
var items = this.items,
values = e.detail.value;
for (var i = 0, lenI = items.length; i < lenI; ++i) {
const item = items[i]
if(values.includes(item.value)){
this.$set(item,'checked',true)
}else{
this.$set(item,'checked',false)
}
}
// console.log(items)
},
changeCheckbox(e){
// console.log(e)
},
selectPath(e,item){
// console.log(e,item,222)
},
}
}
</script>
<style scoped lang="scss">
.contentboxsty{padding: 14px 12px;margin-bottom: 12px;}
.contentboxsty .listItem:last-child{padding-bottom: 0;}
.list_name{display: flex;align-items: center;padding-bottom: 7px;border-bottom: 1px solid $uni-border-color-primary;}
.content_name{padding:8px 0 ;display: flex;align-items: center;}
.content_item{display: flex;align-items: center;flex-wrap: wrap;}
.content_data{padding: 4px 15px 4px 0;display: flex;align-items: center;}
</style>

View File

@ -1,8 +1,21 @@
<template> <template>
<view class="person_page "> <view class="person_page ">
<view class="person_top"> <view class="person_top">
<view class="logo"> <view class="person_data">
<view class="person_logo">
<!-- <button class="avatar-wrapper" open-type="chooseAvatar" bind:chooseavatar="onChooseAvatar"> -->
<image class="img" :src="avatarUrl"></image>
<!-- </button> -->
</view>
<view class="person_name">
<view class="name">
<text class="font15">肖银奎</text>
<image src="http://dm-auto.oss-cn-shanghai.aliyuncs.com/mes_wechat/chaojihuiyuan.png" mode=""></image>
</view>
<view class="account font12">
登录账号ykxiao
</view>
</view>
</view> </view>
</view> </view>
<view class="person_content"> <view class="person_content">
@ -19,7 +32,7 @@
<view class="t-icon t-icon-shengchangongdan backlogicon"></view> <view class="t-icon t-icon-shengchangongdan backlogicon"></view>
<view class="backlogname">流程审批</view> <view class="backlogname">流程审批</view>
</view> </view>
<view class="backlog_module"> <view class="backlog_module" @click="toAlarm">
<view class="t-icon t-icon-shengchangongdan backlogicon"></view> <view class="t-icon t-icon-shengchangongdan backlogicon"></view>
<view class="backlogname">设备报警</view> <view class="backlogname">设备报警</view>
</view> </view>
@ -27,7 +40,7 @@
<view class="t-icon t-icon-shengchangongdan backlogicon"></view> <view class="t-icon t-icon-shengchangongdan backlogicon"></view>
<view class="backlogname">权限审批</view> <view class="backlogname">权限审批</view>
</view> </view>
<view class="backlog_module"> <view class="backlog_module" @click="toSafetyAccidents()">
<view class="t-icon t-icon-shengchangongdan backlogicon"></view> <view class="t-icon t-icon-shengchangongdan backlogicon"></view>
<view class="backlogname">安全事故</view> <view class="backlogname">安全事故</view>
</view> </view>
@ -38,82 +51,170 @@
<view class="font14">账户中心</view> <view class="font14">账户中心</view>
</view> </view>
<view class="con_data"> <view class="con_data">
<view class="con_module"> <view class="con_module" @click="toMessage">
<view class="t-icon t-icon-xiaoxitongzhi-gerenzhongxin personicon"></view> <view class="t-icon t-icon-xiaoxitongzhi-gerenzhongxin personicon"></view>
<view class="font13">消息管理</view> <view class="font13">消息管理</view>
<view class=""></view> <view class=""></view>
</view> </view>
<view class="con_module"> <!-- <view class="con_module">
<view class="t-icon t-icon-shenpizhida personicon"></view> <view class="t-icon t-icon-shenpizhida personicon"></view>
<view class="font13">审批直达</view> <view class="font13">审批直达</view>
<view class=""></view> <view class=""></view>
</view> </view> -->
<view class="con_module noborbot"> <view class="con_module" @click="toMyAuthority()">
<view class="t-icon t-icon-wodequanxian personicon"></view> <view class="t-icon t-icon-wodequanxian personicon"></view>
<view class="font13">我的权限</view> <view class="font13">我的权限</view>
<view class=""></view> <view class=""></view>
</view> </view>
<view class="con_module noborbot" @click="toFaceAuthentication()">
<view class="t-icon t-icon-renlianrenzheng personicon"></view>
<view class="font13">人脸认证</view>
<view class=""></view>
</view>
</view> </view>
<view class="con_set"> <view class="con_set">
<view class="t-icon t-icon-xitongshezhi-gerenzhongxin personicon"></view> <view class="t-icon t-icon-xitongshezhi-gerenzhongxin personicon"></view>
<view class="font13">系统设置</view> <view class="font13">系统设置</view>
</view>
<view class="login_out">
<view class="font13">退出登录</view>
</view> </view>
</view> </view>
<tab-bar :current-page="2"></tab-bar>
</view> </view>
</template> </template>
<script> <script>
export default { import tabBar from "@/components/customTabBar/index";
const defaultAvatarUrl = 'https://dm-auto.oss-cn-shanghai.aliyuncs.com/mes_wechat/avatar.png';
export default {
components:{
tabBar
},
data() { data() {
return { return {
avatarUrl:defaultAvatarUrl,
} }
}, },
methods: { methods: {
//跳转设备报警
toAlarm(){
uni.navigateTo({
url:'/pages/person/alarm'
})
},
toSafetyAccidents(){
uni.navigateTo({
url:'/pages/person/safetyAccidents'
})
},
//跳转账户中心页 //跳转账户中心页
toAccountCenter(){ toAccountCenter(){
uni.navigateTo({ uni.navigateTo({
url: '/pages/person/accountCenter' url: '/pages/person/accountCenter'
}) })
}, },
//跳转人脸认证页
toFaceAuthentication(){
uni.navigateTo({
url:'/pages/person/faceAuthentication'
})
},
toMyAuthority(){
uni.navigateTo({
url:'/pages/person/myAuthority'
})
},
//跳转消息页
toMessage(){
uni.navigateTo({
url: '/pages/index/message'
})
},
} }
} }
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.person_page{ padding: 14px; .person_page{ padding: 14px;
.con_backlog{padding: 14px 10px 14px 15px;background: #1C2755;border-radius: 8px;margin-bottom: 12px; .person_top{margin-bottom:33px ;
.backlog_data{display: flex; flex-wrap: wrap; .person_data{display: flex;align-items: center;
.backlog_module{width: 93px;height: 76px;display: flex;justify-content: center;flex-direction: column;align-items: center;border-radius: 8px; .person_logo{
background: #6576B7;margin: 5px 6px;} border-radius: 50%;width: 54px;height: 54px;margin:0 6px 0 4px;position: relative;
.backlogicon{width: 32px;height: 32px;} .img{
.backlogname{ height: 100%;width: 100%;
font-size: $uni-font-size-sm; }
padding-top: 5px;} }
} .person_logo::before{
} content: '';position: absolute;right: 2px;bottom: 1px;z-index: 10;border: 1px solid $uni-bg-color-default; background: $uni-bg-color-whith;width: 10px;height: 10px;border-radius: 50%;
.con_account{ }
border-radius: 8px; .person_logo::after{
background: #1C2755; content: '';position: absolute;right: 4px;bottom: 3px;z-index: 20;background: $uni-bg-color-success;width: 8px;height: 8px;border-radius: 50%;
display: flex; }
height: 52px;
align-items: center;
padding: 0 14px;
margin-bottom: 10px;
} .person_name{
.personicon{width: 24px;height: 24px;padding-right: 15px;} .name{display: flex;align-items: center;margin-bottom: 2px;
.con_data{border-radius: 8px; image{width: 50px;height: 16px;margin-left: 4px;}
background: #1C2755; }
padding: 0 14px; .account{margin-top: 2px;}
margin-bottom: 12px; }
.con_module{display: flex;height: 49px;align-items: center;border-bottom: 1px solid #2D3A6F;}
}
.con_set{border-radius: 8px;
background: #1C2755;
display: flex;
height: 48px;
align-items: center;
padding: 0 14px;
} }
}
.person_content{
padding-bottom: 100px;
.con_backlog{padding: 14px 10px;background: $uni-bg-color-primary;border-radius: 8px;margin-bottom: 12px;
.backlog_data{
display: flex;flex-wrap:wrap;margin-top:7px;
.backlog_module{
width: calc(33.33% - 12px);height: 76px;display: flex;justify-content: center;flex-direction: column;align-items: center;border-radius: 8px;
background: $uni-color-info;margin: 5px 6px;
box-sizing: border-box;
}
.backlogicon{width: 32px;height: 32px;}
.backlogname{
font-size: $uni-font-size-sm;
padding-top: 5px;
}
}
}
.con_account{
border-radius: 8px;
background: $uni-bg-color-primary;
display: flex;
height: 52px;
align-items: center;
padding: 0 14px;
margin-bottom: 10px;
}
.personicon{width: 24px;height: 24px;margin-right: 15px;}
.con_data{
border-radius: 8px;
background: $uni-bg-color-primary;
padding: 0 14px;
margin-bottom: 12px;
.con_module{display: flex;height: 49px;align-items: center;border-bottom: 1px solid $uni-border-color-primary;}
}
.con_set{
border-radius: 8px;
background: $uni-bg-color-primary;
display: flex;
height: 48px;
align-items: center;
padding: 0 14px;
margin-bottom: 12px;
}
.login_out{
border-radius: 8px;
background: $uni-bg-color-primary;
display: flex;
height: 48px;
align-items: center;
justify-content: center;
padding: 0 14px;
color: $uni-text-color-danger;
}
}
} }
</style> </style>

View File

@ -0,0 +1,43 @@
<template>
<!-- 安全事故 -->
<view class="page_padding">
<view class="contentboxsty font13" v-for="(item, index) in list" :key="index">
<view class="name font_bold font14">
{{item.name}}
</view>
<view class="img_style">
<image :src="item.url"></image>
</view>
<view class="flex_layout padd_bot6">
<view class="flex1">员工安全行为</view>
<view class="">2023-09-01</view>
</view>
<view class="">
事件描述事件描述事件描述事件描述事件描述事件描述
事件描述事件描述事件描述事件描述事件描述事件描述
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
list:[
{name:'设备一',url:'../../static/logo.png'},
{name:'设备一',url:'../../static/logo.png'},
]
}
},
methods: {
}
}
</script>
<style>
.contentboxsty{padding: 14px 12px;margin-bottom: 12px;}
.img_style{padding: 12px 0 14px 0;}
</style>

View File

@ -0,0 +1,116 @@
<template>
<view class="page_padding">
<view class="detail_list contentboxsty">
<view class="list_top">
<view class="top_left">
工单号 <text class="padd_left12">{{form.order_sn}}</text>
</view>
<view class="top_right font12">
{{form.active_status_label}}
</view>
</view>
<view class="list_content">
<view class="content_left font13">
<view class="content_row">
<text class="name">生产开始时间</text>
<text class="data">{{form.time_start==''?'-':form.time_start}}</text>
</view>
<view class="content_row">
<text class="name">生产结束时间</text>
<text class="data">{{form.time_end==''?'-':form.time_end}}</text>
</view>
<view class="content_row">
<text class="name">工单耗时</text>
<text class="data">{{form.processing_time}}</text>
</view>
<view class="content_row">
<text class="name">加工规格</text>
<text class="data">{{form.order_spec}}</text>
</view>
<view class="content_row">
<text class="name">规格料</text>
<text class="data">{{form.cube}}</text>
</view>
<view class="content_row">
<text class="name">生产负责</text>
<text class="data">{{form.creator_name}}</text>
</view>
<view class="content_row">
<text class="name">加工等级</text>
<text class="data">全齐边</text>
</view>
<view class="content_row">
<text class="name">辅料</text>
<text class="data">0.61</text>
</view>
<view class="content_row">
<text class="name">电话</text>
<text class="data">13712279001</text>
</view>
</view>
<view class="content_right">
<progressBar :total="100" :val="form.progress_rate" title="" />
</view>
<view class="progressView">
<view class="circle-progress">
<view class="progressBg">
<view class="progressBox">
<view class="percentage font22">
{{form.yield_rate}}%
</view>
<view class="title font12">
出材率
</view>
</view>
</view>
<view class="circle-progress__bar" :style="'--progress:'+form.yield_rate+'%'"></view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
form:{}
}
},
onLoad(option){
this.detailData(option.id)
},
onShow(){
},
onReady() {
},
methods: {
detailData(id){
this.$api.postFuncLoading('/order.info',{id:id}).then(res=>{
this.form = res.data
})
},
}
}
</script>
<style lang="scss">
.list_top{
.top_right{background: #243168;border-radius: 4px;padding: 3px 10px; text-align: center;display: inline-block;}
}
.list_content{
.content_row{display: flex;padding:6px 0;
.name{width: 90px;font-weight: bold;}
}
.content_right{padding: 6px 0;}
.progressView{
position: absolute;
top: 12px;
right:12px;
z-index: 20;
}
}
</style>

View File

@ -0,0 +1,200 @@
<template>
<!-- 生产工单 -->
<view class="page_padding columnFlex">
<view class="headerView" :class="headerFixed?'headerViewFixed':''">
<searchView placeholder=" 搜索工单" />
</view>
<view class="flexBox">
<view v-for="(item,index) in list" :key="index" class="detail_list contentboxsty font13">
<view @click="toDetail(item.id)">
<view class="list_top">
<view class="top_left">
工单号{{item.order_sn}}
</view>
<view class="top_right">
工单详情 <text class="arrow iconfont icon-gengduo"></text>
</view>
</view>
<view class="list_content font13">
<view class="list_centre">
<view class="centre_left">
<view class="name font_bold">
算法出材率
</view>
<view class="percentage font24">
{{item.algorithm && item.algorithm!=''?item.algorithm+'':'0'}}%
</view>
</view>
<view class="centre_left">
<view class="name font_bold">
实际出材率
</view>
<view class="percentage font24">
{{item.reality && item.reality!=''?item.reality:'0'}}%
</view>
</view>
</view>
<view class="list_below">
<view class="row">
<view class="row_left">
<text class="name">状态</text>
<text class="text status">{{item.active_status_label}}</text>
</view>
<view class="row_right">
<text class="name">加工规格</text>
<text class="text">{{item.order_spec}}</text>
</view>
</view>
<view class="row">
<view class="row_left">
<text class="name">生产开始</text>
<text class="text">{{item.plan_date}}</text>
</view>
<view class="row_right">
<text class="name">工单耗时</text>
<text class="text">{{item.progress_rate}}</text>
</view>
</view>
<view class="row">
<view class="row_left">
<text class="name">工单数量</text>
<text class="text">{{item.order_number}}</text>
</view>
</view>
</view>
</view>
</view>
</view>
<loadMore :noData="loadParams.noData" :loading="loadParams.loading" :loadEnd="loadParams.loadEnd" />
</view>
</view>
</template>
<script>
export default {
components:{
},
data() {
return {
headerFixed:false,
list:[],
params:{
page:1,
pageSize:10,
},
loadParams:{
noData:false,
loading:false,
loadEnd:false
}
}
},
onShow(){
},
onReady() {
this.listData();
},
onPageScroll(e){
if(e.scrollTop>30){
this.headerFixed = true;
}else{
this.headerFixed = false;
}
},
// 上拉刷新
onPullDownRefresh(){
this.params.page = 1;
this.loadParams = {
noData:false,
loading:false,
loadEnd:false
};
this.listData(2);
},
// 加载下一页
onReachBottom(){
if(!(this.loadParams.loadEnd || this.loadParams.noData)){
this.loadParams.loading = true;
this.params.page ++;
this.listData();
}
},
methods: {
listData(type=1){
if(this.params.page == 1){
uni.showLoading({
title: '加载中',
mask: true
})
}
this.$api.request('/order.list',this.params).then(res=>{
if(type ==2){
uni.stopPullDownRefresh();
}
setTimeout( ()=> {
uni.hideLoading();
}, 200);
this.loadParams.loading = false;
if(res.data.rows.length ==0 && this.params.page == 1){
this.loadParams.noData = true;
}
if(res.data.rows.length>0 && res.data.rows.length < this.params.pageSize){
this.loadParams.loadEnd = true;
}
if(this.params.page == 1){
this.list = res.data.rows;
}else{
this.list = this.list.concat(res.data.rows);
}
}).catch(err=>{
setTimeout( ()=> {
uni.hideLoading();
}, 200);
})
},
//跳转工单详情
toDetail(id){
uni.navigateTo({
url:'/pages/production/productionDetail?id='+id
})
},
}
}
</script>
<style scoped lang="scss">
.page_padding{
padding-top: 0;
}
.detail_list{
.list_centre{display: flex;text-align: center;padding-bottom: 10px;
view{flex: 1;}
.percentage{color: $uni-text-color-primary;margin: 10px 0 0 0;}
}
.list_below{padding-bottom: 12px;
.row{display: flex;padding-top: 12px;
.row_left{
white-space: nowrap;overflow: hidden;text-overflow: ellipsis;
padding-right: 4px;
}
.row_right{
white-space: nowrap;overflow: hidden;text-overflow: ellipsis;
padding-left: 4px;
}
view{flex: 1;}
.row_left .name,.row_right .name{
display: inline-block;
width: 65px;
font-weight: bold;
}
.status{
color: $uni-text-color-warning;
}
}
}
}
</style>

267
pages/schedul/list.vue Normal file
View File

@ -0,0 +1,267 @@
<template>
<view class="page_padding columnFlex">
<view class="statistics" v-if="form.date == 'day'">
<view class="title font14">排程日统计</view>
<view class="boxView contentboxsty">
<view class="item">
<view class="name font13">待生产</view>
<view class="font_bold">32</view>
</view>
<view class="item">
<view class="name font13">生产中</view>
<view class="font_bold">12</view>
</view>
<view class="item">
<view class="name font13">生产完成</view>
<view class="font_bold">102</view>
</view>
</view>
</view>
<view class="comView font13" :class="form.date == 'day'?'padd12 contentboxsty':''">
<view class="dateView">
<view class="dateTitle">
<view class="title font14">排程视图 <text class="month">{{dateText}}</text></view>
<view class="dateSwitch">
<div class="item" :class="form.date == item.value?'dateActive':''" @click="form.date = item.value" v-for="(item,index) in dateList" :key="index">{{item.name}}</div>
</view>
</view>
<view :class="form.date !='day'?'contentboxsty mar_top12 mar_bot12 padd12':'calendarView'">
<calendar></calendar>
</view>
</view>
<view class="speedView contentboxsty" :class="form.date!='day'?'padd12':''">
<view class="left">
<view class="line"></view>
</view>
<view class="right detail_list">
<view class="boxItem padd12" v-for="(item,index) in list" :key="index">
<view class="time">{{item.time}}</view>
<view class="boxView card_right" :class="item.type==1?'success':item.type==2?'warning':item.type==3?'status':item.type==4?'error':''">
<view class="cardStatus" :class="item.type==1?'success':item.type==2?'warning':item.type==3?'status':item.type==4?'error':''">{{item.status}}</view>
<view class="row font_bold">
<view class="name">工单号</view>
<view class="text">{{item.sn}}</view>
</view>
<view class="row">
<view class="name">规格</view>
<view class="text">4*9*63</view>
</view>
<view class="row rowDate">
<view class="date">
<text class="name">开始时间</text>
<text class="text color">00:00</text>
</view>
<view class="date">
<text class="name">剩余时间</text>
<text class="text">00:30</text>
</view>
</view>
</view>
<view class="yieldView">
<view class="box">
<view class="num font18 font_bold">74.3<text class="symbol font12">%</text></view>
<view class="name">出材率</view>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
components: {
},
data() {
return {
list:[
{name:'',sn:"SO20240426000001",num:20,status:'待生产',type:1,time:'00:00'},
{name:'',sn:"SO20240426000001",num:70,status:'生产中',type:2,time:'00:30'},
{name:'',sn:"SO20240426000001",num:90,status:'生产完成',type:3},
{name:'',sn:"SO20240422000002",num:20,status:'生产暂停',type:4,time:'01:00'},
{name:'',sn:"SO20240426000001",num:70,status:'待生产',type:1},
{name:'',sn:"SO20240426000001",num:90,status:'待生产',type:1,time:'03:00'},
{name:'',sn:"SO20240426000001",num:90,status:'待生产',type:1},
],
dateList:[
{name:'日',id:'',value:'day'},
{name:'周',id:'',value:'week'},
{name:'月',id:'',value:'month'},
],
dateText:'',
form:{
date:'day'
}
}
},
provide(){
return{
params:this.form,
changeDateText:this.changeDate
}
},
methods: {
changeDate(val){
this.dateText = val;
}
}
}
</script>
<style scoped lang="scss">
.statistics{
.boxView{
display: flex;flex-direction: row;align-items: center;margin-top: 12px;
.item{
flex: 1;display: flex;align-items: center;justify-content:center;flex-direction: column;padding: 12px 0;
.name{padding-bottom: 10px;}
}
}
}
.comView{margin-top: 12px;}
.dateView{width: 100%;}
.dateTitle{
width: 100%;display: flex;align-items: center;justify-content: space-between;
.dateSwitch{
display: flex;align-items: center;background: $uni-bg-color-whith;border-radius: 20px;padding: 2px 3px;
.item{
padding: 5px 18px;
color: $uni-text-color-default;
}
.dateActive{
border-radius: 20px;
background: $uni-color-primary;
color: $uni-text-color-inverse;
}
}
}
.calendarView{
margin: 20px 0;
}
.speedView{
width: 100%;display: flex;box-sizing: border-box;
.left{
flex-basis: 45px;
display: flex;align-items: flex-start;flex-direction: column;padding: 12px 0 12px 18px;box-sizing: border-box;
.line{
position: relative;width: 1px;height: 100%;background: $uni-text-color-info;
}
.line::after{
content: '';
position: absolute;
z-index: 20;
bottom: 0;
left: -4px;
width: 8px;
height: 8px;
border-radius: 50%;
background: $uni-text-color-info;
}
}
.right{
flex: 1;margin: 0;
.boxItem:first-child{
margin-top: 6px;
}
.boxItem:last-child{
margin-bottom: 6px;
}
.boxItem{
background: $uni-bg-color-schedule;
margin: 12px 0;
padding-left: 20px;
border-radius: 8px;
position: relative;
z-index: 10;
.boxView{
display: block;
}
}
.time{
position: absolute;
left: -45px;
top: 0;
background: $uni-bg-color-primary;
padding: 4px 2px;
}
.yieldView{
position: absolute;
right: 12px;
top: 12px;
z-index: 20;
height: calc(100% - 30px);
display: flex;
align-items: center;
justify-content: center;
.box{
display: flex;flex-direction: column;align-items: center;
.num{color: $uni-text-color-warning;}
.name{color: $uni-text-color-warning;}
}
}
.cardStatus{
display: inline-block;
}
.row{
display: flex;align-items: center;
margin-top: 12px;
.date{
display: flex;align-items: center;
}
}
.rowDate{
justify-content: space-between;
.color{
color: $uni-text-color-primary;
}
}
.status::after{
content: '';
position: absolute;
left: 0;
top: 0;
height: 100%;
width: 12px;
border-top-left-radius: 8px;
border-bottom-left-radius: 8px;
background: $uni-bg-color-success;
}
.success::after{
content: '';
position: absolute;
left: 0;
top: 0;
height: 100%;
width: 12px;
border-top-left-radius: 8px;
border-bottom-left-radius: 8px;
background: $uni-bg-color-success;
}
.warning::after{
content: '';
position: absolute;
left: 0;
top: 0;
height: 100%;
width: 12px;
border-top-left-radius: 8px;
border-bottom-left-radius: 8px;
background: $uni-bg-color-warning;
}
.error::after{
content: '';
position: absolute;
left: 0;
top: 0;
height: 100%;
width: 12px;
border-top-left-radius: 8px;
border-bottom-left-radius: 8px;
background: $uni-bg-color-error;
}
}
}
</style>

BIN
static/.DS_Store vendored Normal file

Binary file not shown.

117
static/css/app.css Normal file
View File

@ -0,0 +1,117 @@
/* 横向滚动条 */
.horizontalScrollView ::-webkit-scrollbar{
display: none;
width: 0;
height: 0;
}
/* 检索部分 */
.columnFlex{
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
box-sizing: border-box;
}
.headerView{
padding: 10px 0;
flex-basis: 40px;
}
.searchBox .searchView{
position: relative;
}
.searchBox .searchInput{
display: flex;
flex-direction: row;
}
.searchBox .searchInput .input{
border-radius: 20px;
padding: 7px 13px 7px 13px;
flex: 1;
}
.searchBox .searchInput .filter{
flex-basis: 32px;
display: flex;
align-items: center;
justify-content: flex-end;
}
.headerViewFixed{
position: fixed;
left: 14px;
top: 0;
z-index: 100;
width: calc(100% - 28px);
}
.flexBox{
flex: 1;
}
.scrollView{
height: 100%;
}
/* 加载更多部分 */
.noData{
margin: 50% auto;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.noData .imgView .img{
width: 180px;
height: 138px;
}
.noData .text{
margin-top: 10px;
}
.loadBox{
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 20px;
}
.loadBox .text{
margin-left: 8px;
}
.loadBox .icon{
animation: spin 0.6s linear infinite;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
/* picker 下拉选择 */
.pickerBom{
display: flex;
align-items: center;
justify-content: space-between;
}
/* 上传组件的自定义优化 */
.img_row .file-picker__box-content{
border: none !important;
background: rgba(255, 255, 255, 0.5);
border-radius: 4px !important;
}
.img_row .uni-file-picker__header .file-title{
color: #fff;
font-weight: bold;
}
/* 选择日期时间组件自定义优化 */
.input_date .uni-date-x--border{
border: 0;
}
.input_date .uni-date-x{
background: none;
}
.input_date .uni-date-x .icon-calendar{
padding: 0;
}
.input_date .uni-date-x .uni-icons{
display: none;
}

BIN
static/disable.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
static/enable.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
static/iconfont/.DS_Store vendored Normal file

Binary file not shown.

BIN
static/iconfont/iconfont-weapp/.DS_Store vendored Normal file

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,17 +1,190 @@
@font-face { @font-face {
font-family: "iconfont"; /* Project id 4403683 */ font-family: "iconfont"; /* Project id 4403683 */
src: url('//at.alicdn.com/t/c/font_4403683_jzx1hwbdok.woff2?t=1704766027171') format('woff2'), src: url('//at.alicdn.com/t/c/font_4403683_vv40jcno6w9.woff2?t=1714724942805') format('woff2'),
url('//at.alicdn.com/t/c/font_4403683_jzx1hwbdok.woff?t=1704766027171') format('woff'), url('//at.alicdn.com/t/c/font_4403683_vv40jcno6w9.woff?t=1714724942805') format('woff'),
url('//at.alicdn.com/t/c/font_4403683_jzx1hwbdok.ttf?t=1704766027171') format('truetype'); url('//at.alicdn.com/t/c/font_4403683_vv40jcno6w9.ttf?t=1714724942805') format('truetype');
} }
.iconfont { .iconfont {
font-family: "iconfont" !important; font-family: "iconfont" !important;
font-size: 16px;
font-style: normal; font-style: normal;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
.icon-daiju:before {
content: "\e63a";
}
.icon-a-shexiangtou_shiti1:before {
content: "\e639";
}
.icon-meiyougengduo:before {
content: "\e638";
}
.icon-loading:before {
content: "\e891";
}
.icon-bianji1:before {
content: "\e601";
}
.icon-bangding1:before {
content: "\e602";
}
.icon-a-shaixuan2:before {
content: "\e636";
}
.icon-a-Vector6:before {
content: "\e637";
}
.icon-a-Vector6-copy:before {
content: "\e655";
}
.icon-saoyisao:before {
content: "\e600";
}
.icon-a-shengchanshijian1:before {
content: "\e63b";
}
.icon-weixuanzhong:before {
content: "\e635";
}
.icon-paizhao:before {
content: "\e633";
}
.icon-qiehuanjingtou:before {
content: "\e634";
}
.icon-renlianrenzheng:before {
content: "\e632";
}
.icon-xuanzhong:before {
content: "\e631";
}
.icon-renzhengshibai:before {
content: "\e62f";
}
.icon-renzhengchenggong:before {
content: "\e630";
}
.icon-shenpi:before {
content: "\e62d";
}
.icon-a-shanchu21:before {
content: "\e62e";
}
.icon-weixiubaoyangpinshuai:before {
content: "\e62a";
}
.icon-brokenrate:before {
content: "\e652";
}
.icon-setting:before {
content: "\e651";
}
.icon-broken:before {
content: "\e650";
}
.icon-WIFI_off:before {
content: "\e654";
}
.icon-WIFI_on:before {
content: "\e653";
}
.icon-yasuokongqi:before {
content: "\e62b";
}
.icon-dianliang:before {
content: "\e62c";
}
.icon-tianjia1:before {
content: "\e629";
}
.icon-jinyong2:before {
content: "\e627";
}
.icon-qiyong1:before {
content: "\e628";
}
.icon-jinyong1:before {
content: "\e626";
}
.icon-a-Group10234:before {
content: "\e625";
}
.icon-a-sousuo41:before {
content: "\e624";
}
.icon-tianjia:before {
content: "\e623";
}
.icon-qiyong:before {
content: "\e620";
}
.icon-gengduo:before {
content: "\e61c";
}
.icon-a-shangchuanzhaopian2:before {
content: "\e61d";
}
.icon-bangding:before {
content: "\e61e";
}
.icon-jinyong:before {
content: "\e61f";
}
.icon-gengduo-1:before {
content: "\e621";
}
.icon-bianji:before {
content: "\e622";
}
.icon-xiala:before {
content: "\e61b";
}
.icon-xitongshezhi-gerenzhongxin:before { .icon-xitongshezhi-gerenzhongxin:before {
content: "\e611"; content: "\e611";
} }

BIN
static/indexA.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 978 B

BIN
static/indexB.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 940 B

BIN
static/personA.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 884 B

BIN
static/personB.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 949 B

BIN
static/sweep.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

@ -1,10 +1,59 @@
@import '@/uni_modules/uni-scss/variables.scss'; /* 行为基本色 */
$uni-color-primary: #009688;
$uni-color-success: #67C23A;
$uni-color-warning: #F5AC3F;
$uni-color-error: #F84545;
$uni-color-info: #6576B7;
/* 文字基本色 */
$uni-text-color-primary: #009688;
$uni-text-color-success: #67C23A;
$uni-text-color-info: #909398;
$uni-text-color-warning: #F5AC3F;
$uni-text-color-danger: #FA3758;
$uni-text-color: #333;
$uni-text-color-tip: #6E6E6E;
$uni-text-color-inverse: #fff;
$uni-text-color-grey: #999999;
$uni-text-color-placeholder: rgba(255,255,255,0.7);
$uni-text-color-default: #000000;
$uni-text-color-loading: #5D71A3;
/* 文字尺寸 */ /* 文字尺寸 */
$uni-font-size-sm:24rpx; $uni-font-size-sm:24rpx;
$uni-font-size-base:28rpx; $uni-font-size-base:28rpx;
$uni-font-size-lg:32rpx; $uni-font-size-lg:32rpx;
/* 背景色 */
$uni-bg-color-default:#060B26;
$uni-bg-color-primary:#1C2755;
$uni-bg-color-success:#67C23A;
$uni-bg-color-warning:#F5AC3F;
$uni-bg-color-error:#F84545;
$uni-bg-color-info:#6576B7;
$uni-bg-color-grey:#CCCCCC;
$uni-bg-color-whith:#FFFFFF;
$uni-bg-color-schedule:#45538C;
$uni-bg-color-default-dark:rgba(0, 150, 136, 0.5);
$uni-bg-color-success-dark:rgba(103, 194, 58, 0.25);
$uni-bg-color-warning-dark:rgba(230, 162, 60, 0.25);
$uni-bg-color-error-dark:rgba(248, 69, 69, 0.25);
$uni-bg-color-placeholder:rgba(255, 255, 255, 0.5);
$uni-bg-color-delete:rgba(0, 0, 0, 0.5);
/* 边框的颜色 */
$uni-border-color-primary:#2D3A6F;
$uni-border-color-default:#131E3B;
/* 边框阴影 */
$uni-border-shadow-color-default:#999999;
$uni-border-shadow-color-white:#ffffff;
$uni-border-shadow-color-black:#000000;
/* 透明度 */ /* 透明度 */
$uni-opacity-disabled: 0.3; // 组件禁用态的透明度 $uni-opacity-disabled: 0.3; // 组件禁用态的透明度

156
utils/api.js Normal file
View File

@ -0,0 +1,156 @@
import config from './envConfig.js';
import wf from './public.js';
const request = (url = '', data = {}, header = {
'Authorization': 'Bearer '+uni.getStorageSync('mes_token') ? 'Bearer '+uni.getStorageSync('mes_token') : '',
}) => {
return new Promise((resolve, reject) => {
uni.request({
url: config.dev.VITE_BASE_API + url,
method: "POST",
dataType: "json",
data: data,
header: header,
success: (res) => {
if (res.data.code == 401){
setTimeout( ()=> {
uni.hideLoading();
}, 200);
uni.showModal({
showCancel: false,
title: '温馨提示',
confirmColor:'#009688',
content: res.data.message,
success: (result)=> {
if (result.confirm) {
uni.reLaunch({
url: '/pages/login/login'
});
wf.removeLoginData();
}
}
});
return
}
if(res.header.Authorization){
uni.removeStorageSync('mes_token');
let obj = new Object();
let str = String(res.header.Authorization)
let newStr = str.slice(0, 0) + str.slice(7)
obj.mes_token = newStr;
uni.setStorageSync("mes_token",obj.mes_token);
}
// 成功的回调
if(res.data.code == 200){
resolve(res.data);
}else{
uni.showToast({
icon:'none',
title:res.data.message
})
}
},
fail: (err) => {
uni.showToast({
title: "" + err.msg,
icon: 'none'
});
reject(err)
}
})
})
}
const postFuncLoading = (url = '', data = {}, header = {
'Authorization': 'Bearer '+uni.getStorageSync('mes_token') ? 'Bearer '+uni.getStorageSync('mes_token') : '',
}) => {
uni.showLoading({
title: '加载中',
mask: true
})
return new Promise((resolve, reject) => {
uni.request({
url: config.dev.VITE_BASE_API + url, //接口地址:前缀+方法中传入的地址
method: "POST", //请求方法
dataType: "json",
data: data, //传递参数
header: header, //自定义头部,和后端商同后编写
success: (res) => {
setTimeout( ()=> {
uni.hideLoading();
}, 200);
if (res.data.code == 401){
wf.removeLoginData();
uni.showModal({
showCancel: false,
title: '温馨提示',
confirmColor:'#009688',
content: res.data.message,
success: (result)=> {
if (result.confirm) {
uni.reLaunch({
url: '/pages/login/login'
});
}
}
});
return
}
if(res.header.Authorization){
uni.removeStorageSync('mes_token');
let obj = new Object();
let str = String(res.header.Authorization)
let newStr = str.slice(0, 0) + str.slice(7)
obj.mes_token = newStr;
uni.setStorageSync("mes_token",obj.mes_token);
}
// 成功的回调
if(res.data.code == 200){
resolve(res.data)
}else{
uni.showToast({
icon:'none',
title:res.data.message
})
}
},
fail: (err) => {
uni.showToast({
title: "" + err.msg,
icon: 'none'
});
reject(err)
}
})
})
}
const getOss = (url = '', data = {}, header = {
'content-type':'application/json; charset=UTF-8',
'Authorization':''
})=>{
return new Promise((resolve, reject) => {
uni.request({
url: config.dev.VITE_OSS_URL + url, //接口地址:前缀+方法中传入的地址
method: "POST",
dataType: "json",
data: data,
header: header,
success:(res)=>{
if(res.data.code == 200){
resolve(res.data);
}
},
fail:(err)=>{
reject(err);
}
})
})
}
export default {
request,
postFuncLoading,
getOss
};

16
utils/envConfig.js Normal file
View File

@ -0,0 +1,16 @@
//本地环境
const dev = {
ENV: "dev",
VITE_BASE_API: "https://api.dev.dwoodauto.com/mobile/v1",
VITE_OSS_URL: "https://cloud-wh-dev.dwood365.com/mobile/v1",
};
//正式环境
const pro = {
ENV: "pro",
VITE_BASE_API: "https://api.dev.dwoodauto.com",
VITE_OSS_URL: "https://wf-api.dwood168.com/wh-mobile/v1",
};
export default {
dev,
pro,
};

421
utils/public.js Normal file
View File

@ -0,0 +1,421 @@
//登录存储信息
const setLoginData=function(obj){
uni.setStorageSync("demu_mes_user_name",obj.mes_user_name);
uni.setStorageSync("mes_token",obj.mes_token);
}
const removeLoginData=function(){
uni.removeStorageSync("demu_mes_user_name");
uni.removeStorageSync("mes_token");
}
// 重定义 弹窗
const toast = function(params){
uni.showToast({
title:params.text,
icon:params.type,
duration:1000
})
}
// 0~9 对应小数转换
const numberToChineseLower = function(num) {
const chineseMonths = {
'1': '一',
'2': '二',
'3': '三',
'4': '四',
'5': '五',
'6': '六',
'7': '七',
'8': '八',
'9': '九',
'10': '十',
'11': '十一',
'12': '十二'
};
return chineseMonths[num] || '';
}
const getToday = function() {
let today = new Date();
let year = today.getFullYear();
let month = today.getMonth() + 1;
let day = today.getDate();
let formattedMonth = month < 10 ? '0' + month : month;
let formattedDay = day < 10 ? '0' + day : day;
// 返回格式化后的日期字符串,格式为 yyyy-mm-dd
return year + '-' + formattedMonth + '-' + formattedDay;
}
const getDatesOfWeek = function() {
var now = new Date();
// 获取当前日期是周几0表示周日1表示周一以此类推
var dayOfWeek = now.getDay();
var monday = new Date(now.setDate(now.getDate() - dayOfWeek + (dayOfWeek === 0 ? 0 : 1)));
var datesOfWeek = [];
for (var i = 0; i < 7; i++) {
var currentDate = new Date(monday.getTime() + i * 24 * 60 * 60 * 1000);
var weekdays = ['日', '一', '二', '三', '四', '五', '六'];
var weekday = weekdays[currentDate.getDay()];
var dateInfo = {
date: currentDate.toISOString().split('T')[0],
name: weekday
};
datesOfWeek.push(dateInfo);
}
return datesOfWeek;
}
// 往前一周
const getPreviousWeekDatesWithDays = function(date=null) {
var now = new Date(date);
var lastMonday = new Date(now);
lastMonday.setDate(lastMonday.getDate() - 7);
var datesAndDays = [];
for (var i = 0; i < 7; i++) {
var currentDate = new Date(lastMonday.getTime() + i * 24 * 60 * 60 * 1000);
var weekdays = ['日', '一', '二', '三', '四', '五', '六'];
datesAndDays.push({
date: currentDate.toISOString().split('T')[0],
name: weekdays[currentDate.getDay()]
});
}
return datesAndDays;
}
// 往后一周
const getNextWeekDatesWithDays = function(date = null) {
var now = new Date(date);
var nextMonday = new Date(now);
nextMonday.setDate(nextMonday.getDate() + (8 - now.getDay()) % 7);
var datesAndDays = [];
for (var i = 0; i < 7; i++) {
var currentDate = new Date(nextMonday.getTime() + i * 24 * 60 * 60 * 1000);
var weekdays = ['日', '一', '二', '三', '四', '五', '六'];
datesAndDays.push({
date: currentDate.toISOString().split('T')[0],
name: weekdays[currentDate.getDay()]
});
}
return datesAndDays;
}
// 获取本月日期
// year, month
const getWeeksOfMonth = function() {
var now = new Date();
var year = now.getFullYear();
var month = now.getMonth() + 1;
const startDate = new Date(year, month - 1, 1);
const endDate = new Date(year, month, 0);
const startDateDayOfWeek = startDate.getDay(); // 获取本月第一天是周几
const totalDays = endDate.getDate(); // 获取本月总天数
let weeks = [];
let currentWeek = [];
let currentDate = new Date(startDate);
// 填充到本周开始
for (let i = 0; i < startDateDayOfWeek; i++) {
currentWeek.push(null);
}
while (currentDate <= endDate) {
let textMonth = month<10?'0'+month:month;
let textDate = currentDate.getDate()<10?'0'+currentDate.getDate():currentDate.getDate();
currentWeek.push({
date: year +'-'+ textMonth +'-'+ textDate,
name: ['一', '二', '三', '四', '五', '六','日'][currentDate.getDay()]
});
currentDate.setDate(currentDate.getDate() + 1);
// 当前周已满,开始新周
if (currentWeek.length === 7) {
weeks.push(currentWeek);
currentWeek = [];
}
}
// 处理最后不满一周的情况
if (currentWeek.length > 0) {
while (currentWeek.length < 7) {
currentWeek.push(null);
}
weeks.push(currentWeek);
}
return weeks;
}
// 往前推一个月
const getPreviousMonthGroupedByWeek = function(date = null) {
let now = new Date(date);
var year = now.getFullYear();
var month = now.getMonth();
// 如果当前月份是1月则年份减1月份变成12月
if (month === 0) {
year--;
month = 11;
} else {
month--;
}
let prevMonthFirstDay = new Date(year, month, 1); // 获取上一个月的第一天
let prevMonthLastDay = new Date(year, month + 1, 0); // 获取上一个月的最后一天
let currentDate = new Date(prevMonthFirstDay); // 从上一个月的第一天开始
let weeksData = [];
let currentWeek = [];
const weekdays = ['一', '二', '三', '四', '五', '六', '日'];
while (currentDate <= prevMonthLastDay) {
// 获取当前日期和星期几
let date = currentDate.getDate();
let weekdayIndex = currentDate.getDay();
let textMonth = month<9?'0'+(month+1):(month+1);
let textDate = date<10?'0'+date:date;
currentWeek.push({
date: year + '-' + textMonth + '-' + textDate,
name: weekdays[weekdayIndex]
});
// 如果到达了周日或者已经是最后一日将当前周添加到weeksData并重置currentWeek
if (weekdayIndex === 6 || currentDate.getTime() === prevMonthLastDay.getTime()) {
weeksData.push(currentWeek);
currentWeek = [];
}
// 前往下一天
currentDate.setDate(currentDate.getDate() + 1);
}
return weeksData;
}
const getNextMonthGroupedByWeek = function(date = null) {
let now = new Date(date);
var year = now.getFullYear();
var month = now.getMonth();
if (month === 11) {
year++;
month = 0;
} else {
month++;
}
let nextMonthFirstDay = new Date(year, month, 1); // 获取下一个月的第一天
let nextMonthLastDay = new Date(year, month + 1, 0); // 获取下一个月的最后一天
let currentDate = new Date(nextMonthFirstDay); // 从下一个月的第一天开始
let weeksData = [];
let currentWeek = [];
const weekdays = ['一', '二', '三', '四', '五', '六', '日'];
while (currentDate <= nextMonthLastDay) {
let date = currentDate.getDate();
let weekdayIndex = currentDate.getDay();
let textMonth = month<9?'0'+(month+1):(month+1);
let textDate = date<10?'0'+date:date;
currentWeek.push({
date: year + '-' + textMonth + '-' + textDate,
name: weekdays[weekdayIndex]
});
if (weekdayIndex === 6 || currentDate.getTime() === nextMonthLastDay.getTime()) {
weeksData.push(currentWeek);
currentWeek = [];
}
// 前往下一天
currentDate.setDate(currentDate.getDate() + 1);
}
return weeksData;
}
// 上一个月有几周
const getPreviousMonthWeekCount = function(date = null) {
let now = new Date(date);
var year = now.getFullYear();
var month = now.getMonth();
if (month === 0) {
year--;
month = 11;
} else {
month--;
}
let prevMonthFirstDay = new Date(year, month, 1); // 获取上一个月的第一天
let prevMonthLastDay = new Date(year, month + 1, 0); // 获取上一个月的最后一天
let totalWeeks = 0;
// 计算上一个月有几周
let currentDate = new Date(prevMonthFirstDay);
while (currentDate <= prevMonthLastDay) {
let weekdayIndex = currentDate.getDay();
if (weekdayIndex === 6 || currentDate.getTime() === prevMonthLastDay.getTime()) {
totalWeeks++;
}
currentDate.setDate(currentDate.getDate() + 1);
}
return totalWeeks;
}
// 下个月有几周
const getNextMonthWeekCount = function(date = null) {
let now = new Date(date);
var year = now.getFullYear();
var month = now.getMonth();
if (month === 11) {
year++;
month = 0;
} else {
month++;
}
let nextMonthFirstDay = new Date(year, month, 1); // 获取下一个月的第一天
let nextMonthLastDay = new Date(year, month + 1, 0); // 获取下一个月的最后一天
let totalWeeks = 0;
let currentDate = new Date(nextMonthFirstDay);
while (currentDate <= nextMonthLastDay) {
let weekdayIndex = currentDate.getDay();
if (weekdayIndex === 6 || currentDate.getTime() === nextMonthLastDay.getTime()) {
totalWeeks++;
}
// 前往下一天
currentDate.setDate(currentDate.getDate() + 1);
}
return totalWeeks;
}
// 获取当前的日期
const getCurrentYearData = function() {
let today = new Date(); // 获取当前日期
let year = today.getFullYear(); // 获取年份
let yearData = []; // 存储当前年份的数据
// 循环遍历每个月份
for (let month = 0; month < 12; month++) {
let list = getCurrentMonthData(year,month+1);
let monthData = {
month: month + 1, // 月份从 1 开始
weeks: list, // 存储该月份的所有周数据
};
// 将该月份的数据添加到当前年份的数据中
yearData.push(monthData);
}
return yearData;
}
// 获取上一年的日期
const getPreviousYearData = function(date = null) {
let currentDate = new Date(date); // 获取指定日期或者当前日期
currentDate.setFullYear(currentDate.getFullYear() - 1); // 获取指定日期的上一年日期
let year = currentDate.getFullYear(); // 获取年份
let yearData = []; // 存储指定日期的上一年的数据
for (let month = 0; month < 12; month++) {
let list = getCurrentMonthData(year, month + 1);
let monthData = {
month: month + 1,
weeks: list,
};
yearData.push(monthData);
}
return yearData;
}
// 获取下一年的日期
const getNextYearData = function(date = null) {
let currentDate = new Date(date); // 获取指定日期或者当前日期
currentDate.setFullYear(currentDate.getFullYear() + 1); // 获取指定日期的上一年日期
let year = currentDate.getFullYear(); // 获取年份
let yearData = []; // 存储指定日期的上一年的数据
for (let month = 0; month < 12; month++) {
let list = getCurrentMonthData(year, month + 1);
let monthData = {
month: month + 1,
weeks: list,
};
yearData.push(monthData);
}
return yearData;
}
// 获取当前月的所有周
const getCurrentMonthData = function(year,month) {
const startDate = new Date(year, month - 1, 1);
const endDate = new Date(year, month, 0);
const startDateDayOfWeek = startDate.getDay(); // 获取本月第一天是周几
const totalDays = endDate.getDate(); // 获取本月总天数
let weeks = [];
let currentWeek = [];
let currentDate = new Date(startDate);
// 填充到本周开始
for (let i = 0; i < startDateDayOfWeek; i++) {
currentWeek.push(null);
}
while (currentDate <= endDate) {
let textMonth = month<10?'0'+month:month;
let textDate = currentDate.getDate()<10?'0'+currentDate.getDate():currentDate.getDate();
currentWeek.push({
date: year +'-'+ textMonth +'-'+ textDate,
name: ['一', '二', '三', '四', '五', '六','日'][currentDate.getDay()]
});
currentDate.setDate(currentDate.getDate() + 1);
// 当前周已满,开始新周
if (currentWeek.length === 7) {
weeks.push(currentWeek);
currentWeek = [];
}
}
// 处理最后不满一周的情况
if (currentWeek.length > 0) {
while (currentWeek.length < 7) {
currentWeek.push(null);
}
weeks.push(currentWeek);
}
return weeks;
}
export default {
setLoginData,
removeLoginData,
toast,
numberToChineseLower,
getToday,
getDatesOfWeek,
getPreviousWeekDatesWithDays,
getNextWeekDatesWithDays,
getWeeksOfMonth,
getPreviousMonthGroupedByWeek,
getNextMonthGroupedByWeek,
getPreviousMonthWeekCount,
getNextMonthWeekCount,
getCurrentYearData,
getPreviousYearData,
getNextYearData,
};

21
vite.config.js Normal file
View File

@ -0,0 +1,21 @@
import { defineConfig } from "vite";
import uni from "@dcloudio/vite-plugin-uni";
import ENV_CONFIG from "./utils/envConfig.js";
import { resolve } from "path"; // 导入 path 模块,帮助我们解析路径
export default defineConfig(() => {
return {
server: {
port: "3002",
},
resolve: {
alias: {
"@": resolve(__dirname, "/src"),
},
},
plugins: [uni()],
define: {
"process.env.config": ENV_CONFIG, //配置一
'process.env': process.env, //配置二
},
};
});