Browse Source

报表

master
zhang_li 11 months ago
parent
commit
d31fe083e8
  1. 2
      .env.development
  2. 31
      src/api/board.js
  3. 2
      src/permission.js
  4. 2
      src/views/board/productShippingBoard.vue
  5. 252
      src/views/board/productionMaterialBoard.vue
  6. 2
      src/views/board/productionPlanBoard.vue
  7. 250
      src/views/board/purchaseArrivalBoard.vue

2
.env.development

@ -5,7 +5,7 @@ VUE_APP_TITLE = 若依管理系统
ENV = 'development' ENV = 'development'
# 若依管理系统/开发环境 # 若依管理系统/开发环境
VUE_APP_BASE_API = 'http://192.168.0.170:12080/admin-api' VUE_APP_BASE_API = 'http://localhost:12080/admin-api'
# 路由懒加载 # 路由懒加载
VUE_CLI_BABEL_TRANSPILE_MODULES = true VUE_CLI_BABEL_TRANSPILE_MODULES = true

31
src/api/board.js

@ -0,0 +1,31 @@
import request from '@/utils/request'
// 查询采购到货看板
export function Purchasereceipt() {
return request({
url: '/wms/board/purchasereceipt',
method: 'get'
})
}
// 查询生产叫料看板
export function Issue() {
return request({
url: '/wms/board/issue',
method: 'get'
})
}
// 查询生产计划看板
export function Production() {
return request({
url: '/wms/board/production',
method: 'get'
})
}
// 查询成品发运看板
export function Deliver() {
return request({
url: '/wms/board/deliver',
method: 'get'
})
}

2
src/permission.js

@ -8,7 +8,7 @@ import { isRelogin } from '@/utils/request'
NProgress.configure({ showSpinner: false }) NProgress.configure({ showSpinner: false })
const whiteList = ['/login', '/register','/PurchaseArrivalBoard','/ProductShippingBoard','/ProductionPlanBoard','/ProductionMaterialBoard'] const whiteList = ['/login', '/register','/PurchaseArrivalBoard','/productShippingBoard','/productionPlanBoard','/productionMaterialBoard']
router.beforeEach((to, from, next) => { router.beforeEach((to, from, next) => {
NProgress.start() NProgress.start()

2
src/views/board/productShippingBoard.vue

@ -46,7 +46,7 @@
<script> <script>
export default { export default {
name: "Index", name: "ProductShippingBoard",
data() { data() {
return { return {
// //

252
src/views/board/productionMaterialBoard.vue

@ -1,7 +1,7 @@
<!-- 生产叫料看板 --> <!-- 生产叫料看板 -->
<template> <template>
<div class="box"> <div class="box">
<div class="title">采购到货看版</div> <div class="title">生产叫料看板</div>
<div class="table"> <div class="table">
<ul class="time"> <ul class="time">
<li <li
@ -22,7 +22,7 @@
</ul> </ul>
<div class="table-list"> <div class="table-list">
<ul v-for="(item, index) in tableList" :key="index"> <ul v-for="(item, index) in tableList" :key="index">
<li class="first-col">{{ item.dock }}</li> <li class="first-col">{{ item.toDockCode }}</li>
<li <li
v-for="index in 24" v-for="index in 24"
:key="index" :key="index"
@ -45,8 +45,9 @@
</template> </template>
<script> <script>
import { Purchasereceipt } from "@/api/board.js";
export default { export default {
name: "Index", name: "PurchaseArrivalBoard",
data() { data() {
return { return {
// //
@ -59,181 +60,31 @@ export default {
color: [ color: [
{ {
status: 1, status: 1,
color: "#529b2f",
},
{
status: 2,
color: "#f46c6c",
},
{
status: 3,
color: "#e6a23d",
},
{
status: 4,
color: "#3275b9", color: "#3275b9",
text: "待处理",
}, },
{ {
status: 5,
color: "#90939a",
},
],
tableData: [
{
dock: "Dock1",
startTime: "2023-12-22 11:30",
endTime: "2023-12-22 12:00",
status: 1,
dockCode: "月台1",
suppier: "供应商1",
fahuo: "3333",
code: "3333",
liushui: "55555",
chepai: "9999",
jihua: "2023-12-12",
shiji: "2023-12-12",
},
{
dock: "Dock1",
startTime: "2023-12-22 13:20",
endTime: "2023-12-22 15:10",
status: 2, status: 2,
dockCode: "月台1", color: "#e6a23d",
suppier: "供应商1", text: "进行中",
fahuo: "3333",
code: "3333",
liushui: "55555",
chepai: "9999",
jihua: "2023-12-12",
shiji: "2023-12-12",
},
{
dock: "Dock1",
startTime: "2023-12-22 16:20",
endTime: "2023-12-22 17:30",
status: 3,
dockCode: "月台1",
suppier: "供应商1",
fahuo: "3333",
code: "3333",
liushui: "55555",
chepai: "9999",
jihua: "2023-12-12",
shiji: "2023-12-12",
}, },
{ {
dock: "Dock1",
startTime: "2023-12-22 21:10",
endTime: "2023-12-23 1:00",
status: 3, status: 3,
dockCode: "月台1", color: "#529b2f",
suppier: "供应商1", text: "完成",
fahuo: "3333",
code: "3333",
liushui: "55555",
chepai: "9999",
jihua: "2023-12-12",
shiji: "2023-12-12",
},
{
dock: "Dock1",
startTime: "2023-12-23 2:50",
endTime: "2023-12-23 4:50",
status: 4,
dockCode: "月台1",
suppier: "供应商1",
fahuo: "3333",
code: "3333",
liushui: "55555",
chepai: "9999",
jihua: "2023-12-12",
shiji: "2023-12-12",
},
{
dock: "Dock1",
startTime: "2023-12-23 5:00",
endTime: "2023-12-23 6:59",
status: 4,
dockCode: "月台1",
suppier: "供应商1",
fahuo: "3333",
code: "3333",
liushui: "55555",
chepai: "9999",
jihua: "2023-12-12",
shiji: "2023-12-12",
},
{
dock: "Dock1",
startTime: "2023-12-23 8:20",
endTime: "2023-12-23 10:50",
status: 4,
dockCode: "月台1",
suppier: "供应商1",
fahuo: "3333",
code: "3333",
liushui: "55555",
chepai: "9999",
jihua: "2023-12-12",
shiji: "2023-12-12",
},
{
dock: "Dock2",
startTime: "2023-12-22 10:20",
endTime: "2023-12-22 10:50",
status: 4,
dockCode: "月台2",
suppier: "供应商2",
fahuo: "3333",
code: "3333",
liushui: "55555",
chepai: "9999",
jihua: "2023-12-12",
shiji: "2023-12-12",
}, },
{ {
dock: "Dock2",
startTime: "2023-12-22 12:00",
endTime: "2023-12-22 14:50",
status: 5, status: 5,
dockCode: "月台2", color: "#f46c6c",
suppier: "供应商2", text: "延误",
fahuo: "3333",
code: "3333",
liushui: "55555",
chepai: "9999",
jihua: "2023-12-12",
shiji: "2023-12-12",
},
{
dock: "Dock2",
startTime: "2023-12-22 16:00",
endTime: "2023-12-22 17:50",
status: 1,
dockCode: "月台2",
suppier: "供应商2",
fahuo: "3333",
code: "3333",
liushui: "55555",
chepai: "9999",
jihua: "2023-12-12",
shiji: "2023-12-12",
}, },
{ {
dock: "Dock2", status: 4,
startTime: "2023-12-22 19:00", color: "#90939a",
endTime: "2023-12-22 21:00", text: "作废",
status: 2,
dockCode: "月台2",
suppier: "供应商2",
fahuo: "3333",
code: "3333",
liushui: "55555",
chepai: "9999",
jihua: "2023-12-12",
shiji: "2023-12-12",
}, },
], ],
tableData: [],
config: {}, config: {},
}; };
}, },
@ -274,19 +125,34 @@ export default {
}); });
}, },
// //
getTableList() { async getTableList() {
await Purchasereceipt().then((res) => {
this.tableData = res.data;
this.tableData.forEach((item, index) => { this.tableData.forEach((item, index) => {
if((!item.completeTime&&item.requestDueTime < new Date().getTime()) || item.completeTime > item.requestDueTime){
item.status = 5
}
item.requestDueTime1 = this.parseTime(
item.requestDueTime,
"{y}-{m}-{d} {h}:{i}:{s}"
);
item.completeTime1 = this.parseTime(
item.completeTime,
"{y}-{m}-{d} {h}:{i}:{s}"
);
item.timeDifference = this.getTimeDifference( item.timeDifference = this.getTimeDifference(
item.startTime, item.requestTime,
item.endTime item.requestDueTime
); );
}); });
});
}, },
getTimeDifference(time1, time2) { getTimeDifference(time1, time2) {
var date1 = new Date(time1); // var date1 = new Date(time1);
var date2 = new Date(time2); // var date2 = new Date(time2);
var difference = date2.getTime() - date1.getTime(); // // var difference = date2.getTime() - date1.getTime(); //
var difference = time2 - time1; //
// //
var seconds = Math.floor(difference / 1000); var seconds = Math.floor(difference / 1000);
@ -297,15 +163,15 @@ export default {
setTableList() { setTableList() {
let tempArr = []; let tempArr = [];
for (let i = 0; i < this.tableData.length; i++) { for (let i = 0; i < this.tableData.length; i++) {
if (tempArr.indexOf(this.tableData[i].dock) === -1) { if (tempArr.indexOf(this.tableData[i].toDockCode) === -1) {
this.tableList.push({ this.tableList.push({
dock: this.tableData[i].dock, toDockCode: this.tableData[i].toDockCode,
jobList: [this.tableData[i]], jobList: [this.tableData[i]],
}); });
tempArr.push(this.tableData[i].dock); tempArr.push(this.tableData[i].toDockCode);
} else { } else {
for (let j = 0; j < this.tableList.length; j++) { for (let j = 0; j < this.tableList.length; j++) {
if (this.tableList[j].dock == this.tableData[i].dock) { if (this.tableList[j].toDockCode == this.tableData[i].toDockCode) {
this.tableList[j].jobList.push(this.tableData[i]); this.tableList[j].jobList.push(this.tableData[i]);
break; break;
} }
@ -317,21 +183,22 @@ export default {
}, },
// //
setScrollTable() { setScrollTable() {
console.log("tableData", this.tableData);
let data2 = []; let data2 = [];
this.tableData.forEach((item) => { this.tableData.forEach((item) => {
let data1 = []; let data1 = [];
data1.push( data1.push(
`<span style="background:${this.forrmerColor( `<span style="background:${this.forrmerColor(
item.status item.status
)};display:block">${item.status}</span>` )};display:block">${this.forrmerText(item.status)}</span>`
); );
data1.push(item.liushui); data1.push(item.number);
data1.push(item.dockCode); data1.push(item.toDockCode);
data1.push(item.suppier); data1.push(item.supplierCode);
data1.push(item.fahuo); data1.push(item.asnNumber);
data1.push(item.chepai); data1.push(item.vehiclePlateNumber);
data1.push(item.jihua); data1.push(item.requestDueTime1);
data1.push(item.shiji); data1.push(item.completeTime1);
data2.push(data1); data2.push(data1);
}); });
this.config = { this.config = {
@ -365,11 +232,16 @@ export default {
evenRowBGC: "#303133", evenRowBGC: "#303133",
}; };
}, },
// //
forrmerColor(status) { forrmerColor(status) {
let color = this.color.filter((item) => item.status == status)[0].color; let color = this.color.filter((item) => item.status == status)[0].color;
return color; return color;
}, },
//
forrmerText(status) {
let text = this.color.filter((item) => item.status == status)[0].text;
return text;
},
// //
draw() { draw() {
let cells = 60 * 24; let cells = 60 * 24;
@ -383,15 +255,10 @@ export default {
item.element.innerHTML = `${item.jobList item.element.innerHTML = `${item.jobList
.map((cur) => { .map((cur) => {
cur.startPoint = cur.startPoint =
(new Date(cur.startTime).getTime() - (cur.requestTime - new Date(this.startTimePoint).getTime()) /
new Date(this.startTimePoint).getTime()) /
1000 /
60;
cur.width =
(new Date(cur.endTime).getTime() -
new Date(cur.startTime).getTime()) /
1000 / 1000 /
60; 60;
cur.width = (cur.requestDueTime - cur.requestTime) / 1000 / 60;
return `<div style='position:absolute;left:${ return `<div style='position:absolute;left:${
(cur.startPoint * width) / cells (cur.startPoint * width) / cells
}px;top:5px;height:26px;background:${this.forrmerColor( }px;top:5px;height:26px;background:${this.forrmerColor(
@ -499,10 +366,15 @@ export default {
border-right: 1px solid rgba(255, 255, 255, 0.5); border-right: 1px solid rgba(255, 255, 255, 0.5);
padding: 0px !important; padding: 0px !important;
} }
.dv-scroll-board .rows .row-item .ceil:last-of-type(1) {
border-right: 1px solid rgba(255, 255, 255, 0) !important;
padding: 0px !important;
}
.dv-scroll-board { .dv-scroll-board {
border-top: 1px solid rgba(255, 255, 255, 0.5); border-top: 1px solid rgba(255, 255, 255, 0.5);
border-left: 1px solid rgba(255, 255, 255, 0.5); border-left: 1px solid rgba(255, 255, 255, 0.5);
border-bottom: 1px solid rgba(255, 255, 255, 0.5); border-bottom: 1px solid rgba(255, 255, 255, 0.5);
border-right: 1px solid rgba(255, 255, 255, 0.5);
} }
.dv-scroll-board .header-item { .dv-scroll-board .header-item {
border-right: 1px solid rgba(255, 255, 255, 0.5); border-right: 1px solid rgba(255, 255, 255, 0.5);

2
src/views/board/productionPlanBoard.vue

@ -46,7 +46,7 @@
<script> <script>
export default { export default {
name: "Index", name: "ProductionPlanBoard",
data() { data() {
return { return {
// //

250
src/views/board/purchaseArrivalBoard.vue

@ -22,7 +22,7 @@
</ul> </ul>
<div class="table-list"> <div class="table-list">
<ul v-for="(item, index) in tableList" :key="index"> <ul v-for="(item, index) in tableList" :key="index">
<li class="first-col">{{ item.dock }}</li> <li class="first-col">{{ item.toDockCode }}</li>
<li <li
v-for="index in 24" v-for="index in 24"
:key="index" :key="index"
@ -45,8 +45,9 @@
</template> </template>
<script> <script>
import { Purchasereceipt } from "@/api/board.js";
export default { export default {
name: "Index", name: "PurchaseArrivalBoard",
data() { data() {
return { return {
// //
@ -59,181 +60,31 @@ export default {
color: [ color: [
{ {
status: 1, status: 1,
color: "#529b2f",
},
{
status: 2,
color: "#f46c6c",
},
{
status: 3,
color: "#e6a23d",
},
{
status: 4,
color: "#3275b9", color: "#3275b9",
text: "待处理",
}, },
{ {
status: 5,
color: "#90939a",
},
],
tableData: [
{
dock: "Dock1",
startTime: "2023-12-22 11:30",
endTime: "2023-12-22 12:00",
status: 1,
dockCode: "月台1",
suppier: "供应商1",
fahuo: "3333",
code: "3333",
liushui: "55555",
chepai: "9999",
jihua: "2023-12-12",
shiji: "2023-12-12",
},
{
dock: "Dock1",
startTime: "2023-12-22 13:20",
endTime: "2023-12-22 15:10",
status: 2, status: 2,
dockCode: "月台1", color: "#e6a23d",
suppier: "供应商1", text: "进行中",
fahuo: "3333",
code: "3333",
liushui: "55555",
chepai: "9999",
jihua: "2023-12-12",
shiji: "2023-12-12",
},
{
dock: "Dock1",
startTime: "2023-12-22 16:20",
endTime: "2023-12-22 17:30",
status: 3,
dockCode: "月台1",
suppier: "供应商1",
fahuo: "3333",
code: "3333",
liushui: "55555",
chepai: "9999",
jihua: "2023-12-12",
shiji: "2023-12-12",
}, },
{ {
dock: "Dock1",
startTime: "2023-12-22 21:10",
endTime: "2023-12-23 1:00",
status: 3, status: 3,
dockCode: "月台1", color: "#529b2f",
suppier: "供应商1", text: "完成",
fahuo: "3333",
code: "3333",
liushui: "55555",
chepai: "9999",
jihua: "2023-12-12",
shiji: "2023-12-12",
},
{
dock: "Dock1",
startTime: "2023-12-23 2:50",
endTime: "2023-12-23 4:50",
status: 4,
dockCode: "月台1",
suppier: "供应商1",
fahuo: "3333",
code: "3333",
liushui: "55555",
chepai: "9999",
jihua: "2023-12-12",
shiji: "2023-12-12",
},
{
dock: "Dock1",
startTime: "2023-12-23 5:00",
endTime: "2023-12-23 6:59",
status: 4,
dockCode: "月台1",
suppier: "供应商1",
fahuo: "3333",
code: "3333",
liushui: "55555",
chepai: "9999",
jihua: "2023-12-12",
shiji: "2023-12-12",
},
{
dock: "Dock1",
startTime: "2023-12-23 8:20",
endTime: "2023-12-23 10:50",
status: 4,
dockCode: "月台1",
suppier: "供应商1",
fahuo: "3333",
code: "3333",
liushui: "55555",
chepai: "9999",
jihua: "2023-12-12",
shiji: "2023-12-12",
},
{
dock: "Dock2",
startTime: "2023-12-22 10:20",
endTime: "2023-12-22 10:50",
status: 4,
dockCode: "月台2",
suppier: "供应商2",
fahuo: "3333",
code: "3333",
liushui: "55555",
chepai: "9999",
jihua: "2023-12-12",
shiji: "2023-12-12",
}, },
{ {
dock: "Dock2",
startTime: "2023-12-22 12:00",
endTime: "2023-12-22 14:50",
status: 5, status: 5,
dockCode: "月台2", color: "#f46c6c",
suppier: "供应商2", text: "延误",
fahuo: "3333",
code: "3333",
liushui: "55555",
chepai: "9999",
jihua: "2023-12-12",
shiji: "2023-12-12",
},
{
dock: "Dock2",
startTime: "2023-12-22 16:00",
endTime: "2023-12-22 17:50",
status: 1,
dockCode: "月台2",
suppier: "供应商2",
fahuo: "3333",
code: "3333",
liushui: "55555",
chepai: "9999",
jihua: "2023-12-12",
shiji: "2023-12-12",
}, },
{ {
dock: "Dock2", status: 4,
startTime: "2023-12-22 19:00", color: "#90939a",
endTime: "2023-12-22 21:00", text: "作废",
status: 2,
dockCode: "月台2",
suppier: "供应商2",
fahuo: "3333",
code: "3333",
liushui: "55555",
chepai: "9999",
jihua: "2023-12-12",
shiji: "2023-12-12",
}, },
], ],
tableData: [],
config: {}, config: {},
}; };
}, },
@ -274,19 +125,34 @@ export default {
}); });
}, },
// //
getTableList() { async getTableList() {
await Purchasereceipt().then((res) => {
this.tableData = res.data;
this.tableData.forEach((item, index) => { this.tableData.forEach((item, index) => {
if((!item.completeTime&&item.requestDueTime < new Date().getTime()) || item.completeTime > item.requestDueTime){
item.status = 5
}
item.requestDueTime1 = this.parseTime(
item.requestDueTime,
"{y}-{m}-{d} {h}:{i}:{s}"
);
item.completeTime1 = this.parseTime(
item.completeTime,
"{y}-{m}-{d} {h}:{i}:{s}"
);
item.timeDifference = this.getTimeDifference( item.timeDifference = this.getTimeDifference(
item.startTime, item.requestTime,
item.endTime item.requestDueTime
); );
}); });
});
}, },
getTimeDifference(time1, time2) { getTimeDifference(time1, time2) {
var date1 = new Date(time1); // var date1 = new Date(time1);
var date2 = new Date(time2); // var date2 = new Date(time2);
var difference = date2.getTime() - date1.getTime(); // // var difference = date2.getTime() - date1.getTime(); //
var difference = time2 - time1; //
// //
var seconds = Math.floor(difference / 1000); var seconds = Math.floor(difference / 1000);
@ -297,15 +163,15 @@ export default {
setTableList() { setTableList() {
let tempArr = []; let tempArr = [];
for (let i = 0; i < this.tableData.length; i++) { for (let i = 0; i < this.tableData.length; i++) {
if (tempArr.indexOf(this.tableData[i].dock) === -1) { if (tempArr.indexOf(this.tableData[i].toDockCode) === -1) {
this.tableList.push({ this.tableList.push({
dock: this.tableData[i].dock, toDockCode: this.tableData[i].toDockCode,
jobList: [this.tableData[i]], jobList: [this.tableData[i]],
}); });
tempArr.push(this.tableData[i].dock); tempArr.push(this.tableData[i].toDockCode);
} else { } else {
for (let j = 0; j < this.tableList.length; j++) { for (let j = 0; j < this.tableList.length; j++) {
if (this.tableList[j].dock == this.tableData[i].dock) { if (this.tableList[j].toDockCode == this.tableData[i].toDockCode) {
this.tableList[j].jobList.push(this.tableData[i]); this.tableList[j].jobList.push(this.tableData[i]);
break; break;
} }
@ -317,21 +183,22 @@ export default {
}, },
// //
setScrollTable() { setScrollTable() {
console.log("tableData", this.tableData);
let data2 = []; let data2 = [];
this.tableData.forEach((item) => { this.tableData.forEach((item) => {
let data1 = []; let data1 = [];
data1.push( data1.push(
`<span style="background:${this.forrmerColor( `<span style="background:${this.forrmerColor(
item.status item.status
)};display:block">${item.status}</span>` )};display:block">${this.forrmerText(item.status)}</span>`
); );
data1.push(item.liushui); data1.push(item.number);
data1.push(item.dockCode); data1.push(item.toDockCode);
data1.push(item.suppier); data1.push(item.supplierCode);
data1.push(item.fahuo); data1.push(item.asnNumber);
data1.push(item.chepai); data1.push(item.vehiclePlateNumber);
data1.push(item.jihua); data1.push(item.requestDueTime1);
data1.push(item.shiji); data1.push(item.completeTime1);
data2.push(data1); data2.push(data1);
}); });
this.config = { this.config = {
@ -365,11 +232,16 @@ export default {
evenRowBGC: "#303133", evenRowBGC: "#303133",
}; };
}, },
// //
forrmerColor(status) { forrmerColor(status) {
let color = this.color.filter((item) => item.status == status)[0].color; let color = this.color.filter((item) => item.status == status)[0].color;
return color; return color;
}, },
//
forrmerText(status) {
let text = this.color.filter((item) => item.status == status)[0].text;
return text;
},
// //
draw() { draw() {
let cells = 60 * 24; let cells = 60 * 24;
@ -383,15 +255,10 @@ export default {
item.element.innerHTML = `${item.jobList item.element.innerHTML = `${item.jobList
.map((cur) => { .map((cur) => {
cur.startPoint = cur.startPoint =
(new Date(cur.startTime).getTime() - (cur.requestTime - new Date(this.startTimePoint).getTime()) /
new Date(this.startTimePoint).getTime()) /
1000 /
60;
cur.width =
(new Date(cur.endTime).getTime() -
new Date(cur.startTime).getTime()) /
1000 / 1000 /
60; 60;
cur.width = (cur.requestDueTime - cur.requestTime) / 1000 / 60;
return `<div style='position:absolute;left:${ return `<div style='position:absolute;left:${
(cur.startPoint * width) / cells (cur.startPoint * width) / cells
}px;top:5px;height:26px;background:${this.forrmerColor( }px;top:5px;height:26px;background:${this.forrmerColor(
@ -499,10 +366,15 @@ export default {
border-right: 1px solid rgba(255, 255, 255, 0.5); border-right: 1px solid rgba(255, 255, 255, 0.5);
padding: 0px !important; padding: 0px !important;
} }
.dv-scroll-board .rows .row-item .ceil:last-of-type(1) {
border-right: 1px solid rgba(255, 255, 255, 0) !important;
padding: 0px !important;
}
.dv-scroll-board { .dv-scroll-board {
border-top: 1px solid rgba(255, 255, 255, 0.5); border-top: 1px solid rgba(255, 255, 255, 0.5);
border-left: 1px solid rgba(255, 255, 255, 0.5); border-left: 1px solid rgba(255, 255, 255, 0.5);
border-bottom: 1px solid rgba(255, 255, 255, 0.5); border-bottom: 1px solid rgba(255, 255, 255, 0.5);
border-right: 1px solid rgba(255, 255, 255, 0.5);
} }
.dv-scroll-board .header-item { .dv-scroll-board .header-item {
border-right: 1px solid rgba(255, 255, 255, 0.5); border-right: 1px solid rgba(255, 255, 255, 0.5);

Loading…
Cancel
Save