指令管理任务管理

This commit is contained in:
蔡玲
2024-12-05 16:07:24 +08:00
commit c0218507f5
160 changed files with 17325 additions and 0 deletions

128
pages/home/home.vue Normal file
View File

@@ -0,0 +1,128 @@
<template>
<view class="home_content">
<view class="zd-row header">
<view class="zd-col-8 home_title">首页</view>
<view class="zd-col-8 zd-row jcflexend home_userinfo">
<view class="user_icon"></view>
<view class="user_name">{{userName}}</view>
<view class="exit_text" @tap="Quit">退出</view>
</view>
</view>
<view class="welcome_text_wraper">
<view class="welcome_text">{{userName}}, 欢迎进入特克拉ACS系统</view>
</view>
<view class="zd_wrapper">
<view class="zd-row menu-wrap">
<view class="menu-item" v-for="e in menuList" :key="e.id" @tap="toPage(e)">
<image class="menu-img" :src="require('../../static/images/menu/' + e.icon + '.png')" alt="">
<view class="menu-name">{{e.title}}</view>
</view>
</view>
</view>
<view class="left_bg"></view>
<view class="left_bg right_bg"></view>
</view>
</template>
<script>
export default {
data() {
return {
userName: this.$store.getters.userInfo !== '' ? JSON.parse(this.$store.getters.userInfo).person_name : '',
menuList: [
{id: 1, title: '指令管理', icon: 'RF01', path: '/pages/management/inst-manage'},
{id: 2, title: '任务管理', icon: 'RF02', path: '/pages/management/task-manage'},
]
};
},
methods: {
toPage (e) {
let url = e.path + '?title=' + e.title
uni.redirectTo({
url: url
})
},
Quit () {
this.$store.dispatch('delUserInfo', '')
uni.redirectTo({
url: '/pages/login/login'
})
}
}
}
</script>
<style lang="stylus">
@import '../../common/style/mixin.styl';
.home_content
position relative
_wh(100%, 100%)
_bis(,'../../static/images/home_bg.jpg', 100%, 100%,bottom)
.header
height 60px
padding 0 15px
align-items flex-start
justify-content flex-end
_bis(,'../../static/images/header_bg.png', 100%, 100%,bottom)
.home_title
_font(25px,35px,#F6F9FE,,center)
font-family: YouSheBiaoTiHei;
.home_userinfo
height 35px
.user_icon
_wh(25px, 25px)
margin-right 5px
_bis(,'../../static/images/user_icon.png', 100%, 100%,center)
.user_name
_font(17px,17px,#fff,,center)
padding-right 5px
margin 9px 10px 9px 0
border-right 1px solid #AECAF5
.exit_text
height 30px
_font(14px,30px,#fff,,center)
padding 0 10px
margin 2.5px 0
_bis(,'../../static/images/state-item_bg.png', 100%, 100%,center)
.welcome_text_wraper
height 70px
margin 5% 50px 0 50px
.welcome_text
_font(26px, 70px, #F6F9FE,,)
padding-left 20px
font-family: YouSheBiaoTiHei
background: linear-gradient(180deg, rgba(255,255,255,1) 0%, rgba(49,190,255,0.9) 0%, rgba(239,252,254,1) 40%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
.zd_wrapper
_wh(calc(100% - 100px),calc(80% - 130px))
margin 0px 50px 0 50px
_bis(,'../../static/images/bg-task-r2.png', 100%, 100%,center)
.menu-wrap
flex-wrap wrap
justify-content center
align-content center
height 100%
.left_bg
position absolute
left 0
top 0
_wh(25px, 100%)
_bis(,'../../static/images/hud_left.png', 100%, ,center)
.right_bg
left auto
right 0
background-image url('../../static/images/hud_right.png')
.menu-item
width 25%
::v-deep .menu-img
_wh(100%, auto)
img
position relative
opacity 1
_wh(55%, auto)
max-width 90px
margin 0 auto
.menu-name
_font(20px, 40px, #fff,,center)
</style>

239
pages/login/login.vue Normal file
View File

@@ -0,0 +1,239 @@
<template>
<view class="login-bg relative">
<view class="login_wrap">
<view class="login_w">
<view class="zd-row jcflexstart login_tab">
<view class="login_tab_item" :class="{'login_tab_active': drift === 0}" @tap="_tabChange(0)">登录</view>
<view class="login_tab_item" :class="{'login_tab_active': drift === 50}" @tap="_tabChange(50)">配置</view>
</view>
<view class="login_cnt drift" :style="{'left': '-'+drift*2+'%'}">
<view class="login_card">
<view class="card_wrap">
<view class="zd-row mgb20">
<view class="zd-col-4 login_label">账号</view>
<view class="zd-col-20">
<input type="text" placeholder="用户名" v-model="loginname" class="inputStyle">
</view>
</view>
<view class="zd-row mgb20">
<view class="zd-col-4 login_label">密码</view>
<view class="zd-col-20 relative">
<input :type="inputType" placeholder="密码" v-model="password" class="inputStyle">
<text class="iconfont login_icon" :class="eyeOpen ? 'eye_colse_icon' : 'eye_open_icon'" @click="passwordShow"></text>
</view>
</view>
</view>
<view class="zd-row mgt20 mgb20">
<button class="primary-button" :disabled="disabled" @click="toLogin">&nbsp;&nbsp;</button>
</view>
<view class="zd-row">
<text class="zd-col-24 san_text" @tap="isUpdate">升级版本</text>
</view>
</view>
<view class="login_card">
<view class="card_wrap">
<view class="zd-row mgb20">
<view class="zd-col-4 login_label">域名</view>
<view class="zd-col-20">
<input type="text" placeholder="域名地址" v-model.trim="baseUrl" class="inputStyle">
</view>
</view>
</view>
<view class="zd-row mgt20 mgb20">
<button class="primary-button" @tap="toConfig">&nbsp;&nbsp;</button>
</view>
</view>
</view>
</view>
<view class="daoying_bg"></view>
</view>
<view v-if="version !== ''" class="version-name">v{{version}}</view>
<Up-grade v-if="grade === true" @closeUpdate="closeUpdate" :androidUrl="androidUrl"></up-grade>
</view>
</template>
<script>
import { RSAencrypt } from '@/utils/jsencrypt.js'
import {handLogin, pdaUpdate} from '@/utils/getData2.js'
import permision from "@/utils/permission.js"
import UpGrade from './upgrade.vue'
export default {
components: {
UpGrade
},
data() {
return {
loginname: this.$store.getters.loginName,
password: '',
baseUrl: this.$store.getters.baseUrl,
setTime: this.$store.getters.setTime / 1000,
inputType: 'password',
eyeOpen: true,
drift: 0,
disabled: false,
jobnum: '',
qrcode: '',
logintype: '',
version: '',
versionCode: '',
grade: false,
androidUrl: ''
};
},
mounted () {
// alert(window.screen.availWidth)
// alert(window.screen.availHeight)
},
methods: {
_tabChange (num) {
this.drift = num
},
passwordShow () {
this.eyeOpen = !this.eyeOpen
if (this.eyeOpen) {
this.inputType = 'password'
} else {
this.inputType = 'text'
}
},
toConfig () {
let obj = {
baseUrl: this.baseUrl,
setTime: this.setTime * 1000
}
this.$store.dispatch('setConfig', obj)
this._tabChange(0)
},
async toLogin() {
// uni.redirectTo({
// url: '/pages/home/home'
// })
this.disabled = true
if (this.loginname === '') {
uni.showToast({
title: '用户名不能为空',
icon: 'none'
})
this.disabled = false
return
}
if (this.password === '') {
uni.showToast({
title: '密码不能为空',
icon: 'none'
})
this.disabled = false
return
}
try {
let res = await handLogin(this.loginname, RSAencrypt(this.password))
this.$store.dispatch('saveUserInfo', JSON.stringify(res.user.user))
this.$store.dispatch('saveToken', res.token)
this.$store.dispatch('saveLoginName', this.loginname)
uni.redirectTo({
url: '/pages/home/home'
})
this.disabled = false
} catch (e) {
this.disabled = false
}
},
isUpdate () {
this._pdaUpdate()
},
async _pdaUpdate () {
let res = await pdaUpdate()
if (res.code === 1) {
this.grade = true
this.androidUrl = res.result[0].url
console.log(this.androidUrl)
} else {
uni.showToast({
title: desc,
icon: 'none'
})
}
},
closeUpdate () {
this.grade = false
}
}
}
</script>
<style lang="stylus" scoped>
@import '../../common/style/mixin.styl';
.login-bg
_wh(100%, 100%)
_bis(#fff,'../../static/images/login_bg.jpg', 100%, 100%,bottom)
.login_wrap
position fixed
left 50%
top 50%
width 60%
padding 5% 8%
transform translate3d(-50%, -50%, 0)
_bis(,'../../static/images/form_bg.png', 100%, 100%,bottom)
.login_w
_wh(100%, 100%)
overflow hidden
.login_tab
height 50px
padding 0 5px 25px 10%
margin-bottom 15px
_bis(,'../../static/images/login_tabs_bg.png', 100%, 100%,bottom)
.login_tab_item
cursor pointer
_font(25px,33px,#99B1DD,,center)
font-family: YouSheBiaoTiHei;
padding 0 25px 0 5px
.login_tab_active
color #fff
_bis(,'../../static/images/login_tab_active.png', 100%, 100%,bottom)
.login_cnt
position relative
width 200%
overflow hidden
.login_card
width 50%
float left
.card_wrap
min-height 130px
overflow hidden
.login_label
_font(18px, 45px, #AFBED8,,)
.inputStyle
_font(18px, 45px, #fff,,)
_wh(100%, 45px)
background: rgba(45,88,184,0.1);
border: 1px solid #4980BD;
padding 0 11px
.inputStyle[focus]
background: rgba(45,88,184,0.25);
border: 1px solid #21D0F2;
line-height 45px
.login_icon
position absolute
top 5px
right 10px
.primary-button
_wh(auto, 50px)
padding 0 50px
_font(25px,50px,#fff,,center)
_bis(,'../../static/images/button.png', 100%, 100%,bottom)
.san_text
_font(18px,36px,#fff,,center)
.drift
transition left .3s linear
.version-name
width 100%
position: absolute
bottom 3%
_font(15px, 30px, #fff,,center)
.daoying_bg
position: absolute
bottom -30%
left 0
_wh(100%, 30%)
_bis(,'../../static/images/daoy.png', 100%, 100%,bottom)
</style>

229
pages/login/upgrade.vue Normal file
View File

@@ -0,0 +1,229 @@
<template>
<view class="mask flex-center">
<view class="content-update botton-radius">
<view class="content-top">
<text class="content-top-text">发现新版本</text>
<image class="content-top" style="top: 0;" width="100%" height="100%" src="../../static/images/bg_top.png">
</image>
</view>
<view class="content-header"></view>
<view class="content-body">
<view class="title">
<text>特克拉ACS系统又有新版本了升级到最新版本享受更丰富稳定快速的功能和体验</text>
</view>
<view class="footer flex-center">
<template>
<template v-if="!downloadSuccess">
<view class="progress-box flex-column" v-if="downloading">
<progress class="progress" border-radius="35" :percent="downLoadPercent" activeColor="#3DA7FF" show-info stroke-width="10" />
<view style="width:100%;font-size: 14px;display: flex;justify-content: space-around;">
<text>安装包下载中请稍后</text>
<text>({{downloadedSize}}/{{packageFileSize}}M)</text>
</view>
</view>
<button v-else class="content-button" style="border: none;color: #fff;" plain @click="updateApp">立即升级</button>
</template>
</template>
</view>
</view>
<image v-if="is_mandatory" class="close-img" src="../../static/images/app_update_close.png" @click.stop="closeUpdate"></image>
</view>
</view>
</template>
<script>
export default {
data () {
return {
downloadSuccess: false,
downloading: false,
downLoadPercent: 0,
downloadedSize: 0,
packageFileSize: 0,
is_mandatory: true
}
},
props: {
androidUrl: String
},
methods: {
updateApp() {
this.is_mandatory = false
this.downloading = true
this.doUpData(this.androidUrl);
},
doUpData(Url) {
const downloadTask = uni.downloadFile({
url: Url,
success: downloadResult => {
if (downloadResult.statusCode == 200) {
this.downloadSuccess = true;
plus.runtime.install(
//安装软件
downloadResult.tempFilePath,
{
force: true
},
function(res) {
plus.runtime.restart();
}
);
}
},
complete: () => {
this.downloading = false;
this.downLoadPercent = 0
this.downloadedSize = 0
this.packageFileSize = 0
}
});
// 下载进度
downloadTask.onProgressUpdate(res => {
this.downLoadPercent = res.progress;
this.downloadedSize = (res.totalBytesWritten / Math.pow(1024, 2)).toFixed(2);
this.packageFileSize = (res.totalBytesExpectedToWrite / Math.pow(1024, 2)).toFixed(2);
});
},
closeUpdate () {
this.$emit('closeUpdate')
}
}
}
</script>
<style>
page {
background: transparent;
}
.flex-center {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
justify-content: center;
align-items: center;
}
.mask {
position: fixed;
left: 0;
top: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, .65);
}
.botton-radius {
border-bottom-left-radius: 15px;
border-bottom-right-radius: 15px;
}
.content-update {
position: relative;
top: 0;
width: 300px;
background-color: #fff;
box-sizing: border-box;
padding: 0 20px;
font-family: Source Han Sans CN;
}
.text {
/* #ifndef APP-NVUE */
display: block;
/* #endif */
line-height: 200px;
text-align: center;
color: #FFFFFF;
}
.content-top {
position: absolute;
top: -97.5px;
left: 0;
width: 300px;
height: 135px;
}
.content-top-text {
font-size: 22px;
font-weight: bold;
color: #F8F8FA;
position: absolute;
top: 60px;
left: 25px;
z-index: 1;
}
.content-header {
height: 40px;
}
.title {
font-size: 16px;
font-weight: bold;
color: #3DA7FF;
line-height: 20px;
color: #333;
}
.footer {
height: 75px;
display: flex;
align-items: center;
justify-content: space-around;
}
.box-des-scroll {
box-sizing: border-box;
padding: 0 20px;
height: 25px;
text-align: left;
}
.box-des {
font-size: 13px;
color: #000000;
line-height: 50px;
}
.progress-box {
width: 100%;
}
.progress {
width: 90%;
height: 20px;
border-radius: 13px;
}
.close-img {
width: 35px;
height: 35px;
z-index: 1000;
position: absolute;
bottom: -60px;
left: calc(50% - 35px / 2);
}
.content-button {
text-align: center;
flex: 1;
font-size: 15px;
font-weight: 400;
color: #FFFFFF;
border-radius: 20px;
margin: 0 10px;
height: 40px;
line-height: 40px;
background: linear-gradient(to right, #1785ff, #3DA7FF);
}
.flex-column {
display: flex;
flex-direction: column;
align-items: center;
}
</style>

View File

@@ -0,0 +1,182 @@
<template>
<view class="zd_container">
<nav-bar :title="title" :searchActive="true" @toSearch="toSearch"></nav-bar>
<view class="zd_content">
<view class="tab_wrapper">
<view class="zd-row">
<view class="zd-col-8 font-style-1" v-for="e in state" :key="e.id" @tap="changeTab(e)">
<view class="font-style-1" :class="{'font-style-2': e.id === tab, 'border-r': e.id !== '3'}">{{e.text}}</view>
</view>
</view>
</view>
<view class="item-wrapper">
<view class="slide_new">
<table>
<thead>
<tr>
<th>任务号</th>
<th>指令号</th>
<th>起始设备</th>
<th>目标设备</th>
<th>状态</th>
<th>载具号</th>
<th>agv车号</th>
<th>指令执行步骤</th>
<th>优先级</th>
<th>时间</th>
</tr>
</thead>
<tbody>
<tr v-for="(e, i) in dataList" :key="i" @click="toCheck(e)" :class="{'checked': e.inst_uuid === pkId}">
<td>{{e.task_no}}</td>
<td>{{e.instruction_code}}</td>
<td>{{e.start_devicecode}}</td>
<td>{{e.next_devicecode}}</td>
<td>{{['就绪', '执行中', '完成', '取消'][Number(e.inst_status)]}}</td>
<td>{{e.carrier}}</td>
<td>{{e.carno}}</td>
<td>{{e.inst_step}}</td>
<td>{{e.priority}}</td>
<td>{{e.create_time}}</td>
</tr>
</tbody>
</table>
</view>
<view class="zd-row jcenter submit-bar">
<button class="button-primary" :class="{'button-info': !pkId}" :disabled="disabled" @tap="_handInst('1')">指令撤销</button>
<button class="button-primary" :class="{'button-info': !pkId}" :disabled="disabled" @tap="_handInst('2')">重新下发</button>
<button class="button-primary" :class="{'button-info': !pkId}" :disabled="disabled" @tap="_handInst('3')">强制完成</button>
</view>
</view>
</view>
<view class="msg_wrapper" :class="show ? 'popshow' : 'pophide'">
<view class="msg_content">
<view class="zd-row border-bottom">
<view class="zd-col-6">
<span class="filter_label">关键字</span>
</view>
<view class="zd-col-17">
<input type="text" class="filter_input" v-model="val1">
</view>
</view>
<view class="zd-row border-bottom">
<view class="zd-col-6">
<span class="filter_label">起始设备</span>
</view>
<view class="zd-col-17">
<search-box
v-model="val2"
/>
</view>
</view>
<view class="zd-row border-bottom">
<view class="zd-col-6">
<span class="filter_label">目标设备</span>
</view>
<view class="zd-col-17">
<search-box
v-model="val3"
/>
</view>
</view>
</view>
<view class="zd-row jcenter submit-bar">
<button class="button-primary" @tap.stop="show = false">取消</button>
<button class="button-primary" @tap.stop="clearUp">清空</button>
<button class="button-primary" @tap="_handInsts">查询</button>
</view>
</view>
<view v-if="show" class="msg_mask"></view>
</view>
</template>
<script>
import NavBar from '@/components/NavBar.vue'
import SearchBox from '@/components/SearchBox.vue'
import {handInsts, handInst} from '@/utils/getData2.js'
export default {
components: {
NavBar,
SearchBox
},
data() {
return {
show: false,
state: [{id:'-1', text: '全部'}, {id:'0', text: '就绪'}, {id:'1', text: '执行中'}, {id:'2', text: '完成'}, {id:'3', text: '取消'}],
tab: '-1',
title: '',
val1: '',
val2: '',
val3: '',
data: [],
dataList: [],
pkId: '',
disabled: false
};
},
onLoad (options) {
this.title = options.title
},
created () {
this._handInsts()
},
methods: {
toSearch () {
this.show = true
this.tab = '-1'
},
async _handInsts () {
this.show = false
try {
let res = await handInsts(this.val1, this.val2, this.val3)
this.data = [...res.data]
this.dataList = [...this.data]
} catch (e) {
console.log(e)
}
},
changeTab (e) {
this.tab = e.id
if (e.id !== '-1') {
let arr = this.data.filter(el => {return el.inst_status === e.id})
this.dataList = [...arr]
} else {
this.dataList = [...this.data]
}
},
async _handInst (type) {
this.disabled = true
if (!this.pkId) {
this.disabled = false
return
}
try {
let res = await handInst(type, this.pkId)
this.disabled = false
this.tab = '-1'
this._handInsts()
uni.showToast({
title: res.message,
icon: 'none'
})
} catch (e) {
this.disabled = false
}
},
clearUp () {
this.val1 = ''
this.val2 = ''
this.val3 = ''
this.pkId = ''
this.disabled = false
},
toCheck (e) {
this.pkId = this.pkId === e.inst_uuid ? '' : e.inst_uuid
}
}
}
</script>
<style lang="stylus">
</style>

View File

@@ -0,0 +1,179 @@
<template>
<view class="zd_container">
<nav-bar :title="title" :searchActive="true" @toSearch="toSearch"></nav-bar>
<view class="zd_content pdt0">
<view class="tab_wrapper">
<view class="zd-row">
<view class="zd-col-8 font-style-1" v-for="e in state" :key="e.id" @tap="changeTab(e)">
<view class="font-style-1" :class="{'font-style-2': e.id === tab}">{{e.text}}</view>
<view class="tab-line" :class="{'tab-line_active': e.id === tab}"></view>
</view>
</view>
</view>
<view class="item-wrapper">
<view class="slide_new">
<table>
<thead>
<tr>
<th>任务号</th>
<th>起始设备</th>
<th>目标设备</th>
<th>状态</th>
<th>载具号</th>
<th>优先级</th>
<th>时间</th>
</tr>
</thead>
<tbody>
<tr v-for="(e, i) in dataList" :key="i" @click="toCheck(e)" :class="{'checked': e.task_uuid === pkId}">
<td>{{e.task_no}}</td>
<td>{{e.start_devicecode}}</td>
<td>{{e.next_devicecode}}</td>
<td>{{['就绪', '执行中', '完成'][Number(e.task_status)]}}</td>
<td>{{e.carrier}}</td>
<td>{{e.priority}}</td>
<td>{{e.create_time}}</td>
</tr>
</tbody>
</table>
</view>
<view class="zd-row jcenter submit-bar">
<button class="button-primary" :class="{'button-info': !pkId}" :disabled="disabled" @tap="_handTaskoperation('1')">重新生成</button>
<button class="button-primary" :class="{'button-info': !pkId}" :disabled="disabled" @tap="_handTaskoperation('2')">强制完成</button>
</view>
</view>
</view>
<view class="msg_wrapper" :class="show ? 'popshow' : 'pophide'">
<view class="msg_content">
<view class="zd-row border-bottom">
<view class="zd-col-6">
<span class="filter_label">关键字</span>
</view>
<view class="zd-col-17">
<input type="text" class="filter_input" v-model="val1">
</view>
</view>
<view class="zd-row border-bottom">
<view class="zd-col-6">
<span class="filter_label">起始设备</span>
</view>
<view class="zd-col-17">
<search-box
v-model="val2"
/>
</view>
</view>
<view class="zd-row border-bottom">
<view class="zd-col-6">
<span class="filter_label">目标设备</span>
</view>
<view class="zd-col-17">
<search-box
v-model="val3"
/>
</view>
</view>
</view>
<view class="zd-row jcenter submit-bar">
<button class="button-primary" @tap.stop="show = false">取消</button>
<button class="button-primary" @tap.stop="clearUp">清空</button>
<button class="button-primary" @tap="_handTasks">查询</button>
</view>
</view>
<view v-if="show" class="msg_mask"></view>
</view>
</template>
<script>
import NavBar from '@/components/NavBar.vue'
import SearchBox from '@/components/SearchBox.vue'
import {handTasks, handTaskoperation} from '@/utils/getData2.js'
export default {
components: {
NavBar,
SearchBox
},
data() {
return {
show: false,
state: [{id:'-1', text: '全部'}, {id:'0', text: '就绪'}, {id:'1', text: '执行中'}, {id:'2', text: '完成'}],
tab: '-1',
title: '',
val1: '',
val2: '',
val3: '',
data: [],
dataList: [],
pkId: '',
disabled: false
};
},
onLoad (options) {
this.title = options.title
},
created () {
this._handTasks()
},
methods: {
toSearch () {
this.show = true
this.tab = '-1'
},
async _handTasks () {
this.show = false
try {
let res = await handTasks(this.val1, this.val2, this.val3)
this.data = [...res.data]
this.dataList = [...this.data]
} catch (e) {
uni.showToast({
title: res.message,
icon: 'none'
})
}
},
changeTab (e) {
this.tab = e.id
if (e.id !== '-1') {
let arr = this.data.filter(el => {return el.task_status === e.id})
this.dataList = [...arr]
} else {
this.dataList = [...this.data]
}
},
async _handTaskoperation (type) {
this.disabled = true
if (!this.pkId) {
this.disabled = false
return
}
try {
let res = await handTaskoperation(type, this.pkId)
this.disabled = false
this.tab = '-1'
this._handTasks()
uni.showToast({
title: res.message,
icon: 'none'
})
} catch (e) {
this.disabled = false
}
},
clearUp () {
this.val1 = ''
this.val2 = ''
this.val3 = ''
this.pkId = ''
this.disabled = false
},
toCheck (e) {
this.pkId = this.pkId === e.task_uuid ? '' : e.task_uuid
}
}
}
</script>
<style lang="stylus">
</style>