Commit 326e9d6a by pangchong

feat: 收费单收尾

parent 474be6a7
......@@ -29,6 +29,7 @@ declare module 'vue' {
GlobalPicker: typeof import('./src/mocp/components/global-picker/global-picker.vue')['default']
GlobalPopup: typeof import('./src/mocp/components/global-popup/global-popup.vue')['default']
GlobalRadio: typeof import('./src/mocp/components/global-radio/global-radio.vue')['default']
GlobalSwitch: typeof import('./src/mocp/components/global-switch/global-switch.vue')['default']
GlobalTabs: typeof import('./src/mocp/components/global-tabs/global-tabs.vue')['default']
GlobalTag: typeof import('./src/mocp/components/global-tag/global-tag.vue')['default']
GlobalTextStatus: typeof import('./src/mocp/components/global-text-status/global-text-status.vue')['default']
......
import { http, post } from 'mocp/utils/http'
//查询所有机号
export const getAllAcApi = (data, config) => {
return http({
method: 'POST',
url: '/workbench/electronicBill/allAc',
data,
config
})
}
//查询所有机型
export const getAllAcTypeApi = (data, config) => {
return http({
method: 'POST',
url: '/workbench/electronicBill/allAcType',
data,
config
})
}
//查询所有航司
export const getAllAirlineApi = (data, config) => {
return http({
method: 'POST',
url: '/workbench/electronicBill/allAirline',
data,
config
})
}
//根据机号查询机型航司信息
export const getAirlineAcregApi = (data, config) => {
return http({
method: 'POST',
url: '/workbench/electronicBill/getAirlineAcreg',
data,
config
})
}
//新增例行维护工作单
export const addRoutineWorkApi = (data, config) => {
return post({
method: 'POST',
url: '/workbench/electronicBill/addRoutineWork',
data,
config
})
}
//例行维护工作单列表
export const routineWorkListApi = (data, config) => {
return http({
method: 'POST',
url: '/workbench/electronicBill/routineWorkList',
data,
config
})
}
//新增非例行维护工作单
export const addNonRoutineWorkApi = (data, config) => {
return post({
method: 'POST',
url: '/workbench/electronicBill/addNonRoutineWork',
data,
config
})
}
//非例行维护工作单列表
export const noRoutineWorkListApi = (data, config) => {
return http({
method: 'POST',
url: '/workbench/electronicBill/noRoutineWorkList',
data,
config
})
}
//新增除防冰工作单
export const addDeicingApi = (data, config) => {
return post({
method: 'POST',
url: '/workbench/electronicBill/addDeicing',
data,
config
})
}
//除防冰工作单列表
export const deicingListApi = (data, config) => {
return http({
method: 'POST',
url: '/workbench/electronicBill/deicingList',
data,
config
})
}
import { http } from 'mocp/utils/http'
//根据指定目录获取目录下的文件夹和文件列表
export const getFileListApi = (data, config) => {
return http({
method: 'POST',
url: '/workbench/electronicBill/fileList',
data,
config
})
}
//根据文件路径读取文件,文件流字符串
export const downuploadApi = (data, config) => {
return http({
method: 'POST',
url: '/workbench/electronicBill/downupload',
data,
config
})
}
......@@ -92,5 +92,8 @@ const getRadius = computed(() => {
.icon {
margin-right: 8rpx;
}
&[disabled] {
opacity: 0.75;
}
}
</style>
......@@ -48,6 +48,10 @@ const ps = defineProps({
type: String,
default: ''
},
rightWidth: {
type: [Number, String],
default: 280
},
//是否显示内容
showContent: {
type: Boolean,
......@@ -69,6 +73,9 @@ const getContentStyle = computed(() => {
}
return _style
})
const getRightWidth = computed(() => {
return ps.rightWidth + 'rpx'
})
const handleTitleClick = () => {
es('handleTitleClick')
}
......@@ -84,13 +91,13 @@ const handleTitleClick = () => {
align-items: center;
justify-content: space-between;
.left {
font-size: 34rpx;
font-size: 33rpx;
.txt {
color: $mocp-text-5;
}
}
.right {
flex-basis: 280rpx;
flex-basis: v-bind(getRightWidth);
margin-left: 16rpx;
display: flex;
align-items: center;
......
......@@ -47,6 +47,11 @@ const ps = defineProps({
type: [String, Number],
default: ''
},
//是否默认今天
defaultToday: {
type: Boolean,
default: false
},
modelValue: {
type: [String, Number],
default: ''
......@@ -108,7 +113,11 @@ const getStyle = computed(() => {
const labelValue = ref('')
const getLabelValue = computed(() => {
if (labelValue.value) {
return Day(labelValue.value).format(ps.format)
if (ps.mode == 'date') {
return Day(labelValue.value).format(ps.format)
} else {
return labelValue.value
}
} else {
return ps.placeholder
}
......@@ -143,16 +152,21 @@ watch(
} else {
defaultValue.value = Day().format(ps.valueFormat)
}
//默认今天
if (ps.defaultToday) {
es('update:modelValue', defaultValue.value)
es('change', defaultValue.value)
}
}
},
{immediate: true}
{ immediate: true }
)
//点击确定按钮
const confirm = (e) => {
show.value = false
labelValue.value = e.value
defaultValue.value = e.value
if (ps.timestamp) {
if (ps.timestamp || ps.mode != 'date') {
es('update:modelValue', defaultValue.value)
es('change', defaultValue.value)
} else {
......
......@@ -390,7 +390,8 @@ defineExpose({
updateCache: () => {
chooseValue.value = []
paging.value?.updateCache()
}
},
element: paging
})
</script>
<script>
......@@ -405,19 +406,15 @@ export default {
// 表单内容
:deep(.u-form-item__body) {
padding: 24rpx 0 !important;
.u-form-item__body__left__content__label {
color: $mocp-text-5 !important;
font-size: 28rpx !important;
}
.u-input__content__field-wrapper__field {
color: $mocp-text-4 !important;
}
.u-textarea {
margin-top: 8rpx;
.u-textarea__field {
font-size: 28rpx !important;
color: $mocp-text-4 !important;
......@@ -429,11 +426,9 @@ export default {
min-width: 18px;
}
}
.cancel {
font-size: 28rpx;
}
.footer-btn {
padding: 24rpx 32rpx;
background-color: #fff;
......
<template>
<view class="switch" :style="getStyle">
<up-switch
v-model="switchValue"
:loading="loading"
:activeColor="activeColor"
:activeValue="activeValue"
:inactiveValue="inactiveValue"
:disabled="disabled"
@change="switchChange"
></up-switch>
</view>
</template>
<script setup>
import { computed, ref, watch } from 'vue'
const es = defineEmits(['update:modelValue', 'change'])
const ps = defineProps({
modelValue: {
type: [Boolean, String, Number],
default: 0
},
switchAlign: {
type: String,
default: 'left'
},
loading: {
type: Boolean,
default: false
},
disabled: {
type: Boolean,
default: false
},
activeColor: {
type: String,
default: '#165dff'
},
activeValue: {
type: [Boolean, String, Number],
default: 1
},
inactiveValue: {
type: [Boolean, String, Number],
default: 0
}
})
const switchValue = ref(0)
watch(
() => ps.modelValue,
(value) => {
switchValue.value = value
},
{ immediate: true }
)
//获取复选框样式
const getStyle = computed(() => {
let switchAlign = 'flex-start'
if (ps.switchAlign == 'center') {
switchAlign = 'center'
} else if (ps.switchAlign == 'right') {
switchAlign = 'flex-end'
}
return {
justifyContent: switchAlign
}
})
const switchChange = (value) => {
es('update:modelValue', value)
es('change', value)
}
</script>
<style lang="scss" scoped>
.switch {
display: flex;
}
</style>
......@@ -11,9 +11,15 @@
<template v-else-if="['video', 'mp4'].includes(item[typeField].toLowerCase())">
<image src="/static/mocp/image/common/video.png" mode="widthFix" />
</template>
<template v-else>
<template v-else-if="['pdf'].includes(item[typeField].toLowerCase())">
<image src="/static/mocp/image/common/pdf.png" mode="widthFix" />
</template>
<template v-else-if="['ppt', 'txt'].includes(item[typeField].toLowerCase())">
<image src="/static/mocp/image/common/ppt.png" mode="widthFix" />
</template>
<template v-else>
<image src="/static/mocp/image/common/unknown.png" mode="widthFix" />
</template>
<view class="u-line-1">{{ item[nameField] }}</view>
</view>
<view class="tool" @tap="previewFile(item.fileUrl)">
......@@ -108,7 +114,6 @@ const ps = defineProps({
type: Boolean,
default: true
}
})
const fileList = ref([])
watch(
......@@ -122,15 +127,15 @@ watch(
}
}
},
{immediate: true}
{ immediate: true }
)
const getFileList = computed(() => {
return fileList.value?.map((item) => {
return {...item, url: item.fileUrl}
return { ...item, url: item.fileUrl }
})
})
const getOptions = computed(() => {
return httpInterceptor({url: ps.url, name: 'file'})
return httpInterceptor({ url: ps.url, name: 'file' })
})
// 删除文件
const show = ref(false)
......@@ -152,22 +157,22 @@ const previewFile = (fileUrl) => {
})
uni.downloadFile({
url: fileUrl,
success: function(res) {
success: function (res) {
var filePath = res.tempFilePath
uni.openDocument({
filePath: filePath,
showMenu: true,
success: function(res) {
success: function (res) {
uni.hideLoading()
console.log('打开文件成功')
},
fail: function() {
fail: function () {
uni.hideLoading()
uni.$mocpMessage.error('打开文件失败,请重新打开')
}
})
},
fail: function() {
fail: function () {
uni.hideLoading()
uni.$mocpMessage.error('打开文件失败,请重新打开')
}
......@@ -204,7 +209,7 @@ watch(
es('change', files)
es('getFileList', cloneDeep(value))
},
{deep: true, immediate: true}
{ deep: true, immediate: true }
)
onBeforeUnmount(() => {
uni.$emit('$upload-hide', {})
......
// 建议以文件名首字母作为前缀eb_
export const eb_deicingType = [
{ label: 'cleansurface I-BIO', value: 'cleansurface I-BIO' },
{ label: 'FCY-1A', value: 'FCY-1A' },
{ label: 'Cleanwing', value: 'Cleanwing' },
{ label: 'FCY-9311', value: 'FCY-9311' },
{ label: 'FCY-1Bio', value: 'FCY-1Bio' }
]
export const eb_antiicingMix = [
{ label: '30:70', value: '25:75' },
{ label: '30:70', value: '30:70' },
{ label: '40:60', value: '40:60' },
{ label: '50:50', value: '50:50' },
{ label: '60:40', value: '60:40' },
{ label: '70:30', value: '70:30' },
{ label: '75:25', value: '75:25' },
{ label: '100:0', value: '100:0' },
{ label: 'Other', value: 'Other' }
]
export const eb_antiicingUnit = [
{ label: 'USG', value: 'USG' },
{ label: 'L', value: 'L' },
{ label: 'KG', value: 'KG' }
]
export const eb_antiicingType = [
{ label: 'Cleansurface1-B10', value: 'Cleansurface1-B10' },
{ label: 'FCY-1A', value: 'FCY-1A' },
{ label: 'Cleanwing', value: 'Cleanwing' },
{ label: 'FCY-9311', value: 'FCY-9311' },
{ label: 'FCY-2', value: 'FCY-2' }
]
......@@ -7,3 +7,4 @@ export * from './aog'
export * from './support-application'
export * from './mco'
export * from './fleet'
export * from './electronicBill'
import { ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
export const useDrawSignature = (canvasId) => {
let ctx = null
let isButtonDown = false
let points = []
let isSigned = ref(false)
onLoad(() => {
ctx = uni.createCanvasContext(canvasId)
// 设置画笔样式
ctx.lineWidth = 4
ctx.lineCap = 'round'
ctx.lineJoin = 'round'
})
// 触摸开始,获取到起点
const touchStart = (e) => {
let startPoint = { X: e.changedTouches[0].x, Y: e.changedTouches[0].y }
points.push(startPoint) // 把起点存起来
ctx.beginPath() // 每次触摸开始,开启新的路径
isButtonDown = true
}
// 触摸移动,获取到路径点
const touchMove = (e) => {
if (isButtonDown) {
let movePoint = { X: e.changedTouches[0].x, Y: e.changedTouches[0].y }
points.push(movePoint) // 存点
let len = points.length
if (len >= 2) {
draw() // 绘制路径
}
}
}
// 触摸结束,将未绘制的点清空防止对后续路径产生干扰
const touchEnd = () => {
points = []
isButtonDown = false
}
// 绘画
const draw = () => {
let point1 = points[0]
let point2 = points[1]
points.shift()
ctx.moveTo(point1.X, point1.Y)
ctx.lineTo(point2.X, point2.Y)
ctx.stroke()
ctx.draw(true)
isSigned.value = true
}
const clear = () => {
ctx.clearRect(0, 0, 1000, 1000)
ctx.draw(true)
isSigned.value = false
}
const getPath = (canvasId) => {
uni.showLoading({
title: '保存中...',
mask: true
})
return new Promise((resolve, reject) => {
uni.canvasToTempFilePath({
canvasId,
success(data) {
resolve(data.tempFilePath)
},
fail(err) {
reject(err)
},
complete() {
uni.hideLoading()
}
})
})
}
return {
isSigned,
touchStart,
touchMove,
touchEnd,
clear,
getPath
}
}
import { defineStore } from 'pinia'
import { getAllAcApi, getAllAcTypeApi, getAllAirlineApi } from 'mocp/api/electronicBill'
const useElectronicBillStore = defineStore('electronicBill', {
state: () => {
return {
selectList: {
allAc: [], //机号列表
allAcType: [], //机型列表
allAirline: [] //航司列表
}
}
},
getters: {},
actions: {
async init() {
uni.showLoading({
mask: true,
title: '加载中...'
})
try {
await Promise.all([this.getAllAc(), this.getAllAcType(), this.getAllAirline()])
} catch (error) {
console.log(error)
} finally {
uni.hideLoading()
}
},
async getAllAc() {
const res = await getAllAcApi({})
if (res.code == 200) {
this.selectList.allAc = res.data
} else {
uni.$mocpMessage.error(res.message)
}
},
async getAllAcType() {
const res = await getAllAcTypeApi({})
if (res.code == 200) {
this.selectList.allAcType = res.data
} else {
uni.$mocpMessage.error(res.message)
}
},
async getAllAirline() {
const res = await getAllAirlineApi({})
if (res.code == 200) {
this.selectList.allAirline = res.data
} else {
uni.$mocpMessage.error(res.message)
}
},
setState(...args) {
this.$patch({ [args[0]]: args[1] })
}
},
// 配置持久化
persist: false
})
export default useElectronicBillStore
......@@ -25,7 +25,7 @@ const useFleetStore = defineStore('fleet', {
},
getters: {},
actions: {
resetForm () {
resetForm() {
this.searchData = {
aviation: '',
machineNumber: '',
......@@ -40,22 +40,11 @@ const useFleetStore = defineStore('fleet', {
dateEnd
}
},
setState (...args) {
this.$patch({[args[0]]: args[1]})
setState(...args) {
this.$patch({ [args[0]]: args[1] })
}
},
// 配置持久化
persist: false
/*persist: {
// 调整为兼容多端的API
storage: {
setItem (key, value) {
uni.setStorageSync(key, value)
},
getItem (key) {
return uni.getStorageSync(key)
}
}
}*/
})
export default useFleetStore
......@@ -3,19 +3,19 @@ import useUserStore from 'mocp/store/user'
import { decideTimeRange, listTab, listScreen } from 'mocp/utils/getFlightList'
import Day from 'mocp/utils/dayjs'
const {startT, stopT} = decideTimeRange(new Date().getTime())
const { startT, stopT } = decideTimeRange(new Date().getTime())
const useFlightSupportStore = defineStore('flightSupport', {
state: () => {
return {
searchData: {
isOut: 0,//0-进港 1-出港 2-无航班
isOut: 0, //0-进港 1-出港 2-无航班
startT,
stopT,
isInbound: 1,
ac: '',//机号
flightNo: '',//航班号
ac: '', //机号
flightNo: '', //航班号
acOwns2: '',
acTerminals1: '',
......@@ -23,9 +23,9 @@ const useFlightSupportStore = defineStore('flightSupport', {
acs1: ''
},
screenData: {
terminal: 'WUH',//航站
acType: '',//机型
acOwn: ''//航司
terminal: 'WUH', //航站
acType: '', //机型
acOwn: '' //航司
},
listTab,
listScreen,
......@@ -36,23 +36,23 @@ const useFlightSupportStore = defineStore('flightSupport', {
}
},
getters: {
getSearchData (state) {
getSearchData(state) {
const userStore = useUserStore()
return {...state.searchData, ...state.screenData, terminal: userStore.userInfo?.terminal || 'WUH'}
return { ...state.searchData, ...state.screenData, terminal: userStore.userInfo?.terminal || 'WUH' }
},
getSelectedList (state) {
return state.listTab.filter(item => item.selected)
getSelectedList(state) {
return state.listTab.filter((item) => item.selected)
},
getTerminal () {
getTerminal() {
const userStore = useUserStore()
return userStore.userInfo?.terminal || 'WUH'
},
getDetailsCurrentMsg (state) {
getDetailsCurrentMsg(state) {
return state.filterDetailsList[state.filterDetailsCurrentIndex]
}
},
actions: {
resetScreenForm () {
resetScreenForm() {
const userStore = useUserStore()
this.screenData = {
terminal: userStore.userInfo?.terminal || 'WUH',
......@@ -60,7 +60,7 @@ const useFlightSupportStore = defineStore('flightSupport', {
acOwn: ''
}
},
setStateScreen (state) {
setStateScreen(state) {
const userStore = useUserStore()
this.screenData = {
terminal: state.terminal || userStore.userInfo?.terminal || 'WUH',
......@@ -69,9 +69,9 @@ const useFlightSupportStore = defineStore('flightSupport', {
}
},
// 设置列表tab筛选数据
setListTabSelected (args) {
this.listTab = this.listTab.map(item => {
const that = args.find(args => args == item.label)
setListTabSelected(args) {
this.listTab = this.listTab.map((item) => {
const that = args.find((args) => args == item.label)
return {
...item,
selected: !!that
......@@ -81,17 +81,6 @@ const useFlightSupportStore = defineStore('flightSupport', {
},
// 配置持久化
persist: false
/*persist: {
// 调整为兼容多端的API
storage: {
setItem (key, value) {
uni.setStorageSync(key, value)
},
getItem (key) {
return uni.getStorageSync(key)
}
}
}*/
})
export default useFlightSupportStore
import { defineStore } from 'pinia'
import { ref } from 'vue'
//默认default最多显示15个
//默认default最多显示15个,id唯一标识
const menuList = ref([
{ id: 1, name: '信息通报', icon: 'xxtb', group: '技术支援', default: true, count: 0, url: '/panel/inforDisclosure/search' },
{ id: 2, name: '机队状态', icon: 'jdzt', group: '技术支援', default: true, count: 0, url: '/panel/fleet/search' },
{ id: 3, name: '支援申请', icon: 'zysq', group: '技术支援', default: false, count: 0, url: '/panel/support-application/search' },
{ id: 4, name: '工作指令', icon: 'gzzl', group: '技术支援', default: false, count: 0, url: '/panel/work-assignment/search' },
{ id: 5, name: '技术评估', icon: 'jspg', group: '技术支援', default: false, count: 0, url: '/panel/technology-evaluation/list' },
{ id: 6, name: '运行调查', icon: 'yxdc', group: '维修控制', default: false, count: 0 },
{ id: 7, name: '运行决策', icon: 'yxjc', group: '维修控制', default: false, count: 0, url: '/panel/move-decision/list' },
{ id: 8, name: '布置工作', icon: 'bzgz', group: '维修控制', default: false, count: 0, url: '/panel/assign-work/search' },
{ id: 9, name: '航站管理', icon: 'hzgl', group: '航站管理', default: false, count: 0 },
{ id: 10, name: '协议单位', icon: 'xydw', group: '航站管理', default: false, count: 0 },
{ id: 11, name: '不正常事件', icon: 'bzcsj', group: '运行品质', default: false, count: 0 },
{ id: 12, name: '考核记录', icon: 'khjl', group: '运行品质', default: false, count: 0, url: '/panel/appraisal-record/list' },
{ id: 13, name: 'AOG任务', icon: 'AOG', group: '运行品质', default: true, count: 0, url: '/panel/aog/search' },
{ id: 14, name: 'MCO', icon: 'MCO', group: '运行品质', default: true, count: 0, url: '/panel/mco/search' },
{ id: 15, name: '航班保障', icon: 'hbbz', group: '运行品质', default: true, count: 0, url: '/panel/flight-support/list' },
{ id: 16, name: '我的跟机', icon: 'wdgj', group: '运行品质', default: true, count: 0, url: '/panel/supported-task/list' }
{ id: 'xxtb', name: '信息通报', icon: 'xxtb', group: '生产保障', default: true, count: 0, url: '/panel/inforDisclosure/search' },
{ id: 'hbbz', name: '航班保障', icon: 'hbbz', group: '生产保障', default: true, count: 0, url: '/panel/flight-support/list' },
{ id: 'AOG', name: 'AOG任务', icon: 'AOG', group: '生产保障', default: true, count: 0, url: '/panel/aog/search' },
{ id: 'wdgj', name: '我的跟机', icon: 'wdgj', group: '生产保障', default: true, count: 0, url: '/panel/supported-task/list' },
{ id: 'sfd', name: '收费单', icon: 'sfd', group: '生产保障', default: true, count: 0, url: '/panel/electronicBill/list' },
{ id: 'bzcsj', name: '不正常事件', icon: 'bzcsj', group: '维修控制', default: false, count: 0 },
{ id: 'yxdc', name: '运行调查', icon: 'yxdc', group: '维修控制', default: false, count: 0 },
{ id: 'yxjc', name: '运行决策', icon: 'yxjc', group: '维修控制', default: false, count: 0, url: '/panel/move-decision/list' },
{ id: 'bzgz', name: '布置工作', icon: 'bzgz', group: '维修控制', default: false, count: 0, url: '/panel/assign-work/search' },
{ id: 'jdzt', name: '机队状态', icon: 'jdzt', group: '技术支援', default: true, count: 0, url: '/panel/fleet/search' },
{ id: 'zysq', name: '支援申请', icon: 'zysq', group: '技术支援', default: false, count: 0, url: '/panel/support-application/search' },
{ id: 'gzzl', name: '工作指令', icon: 'gzzl', group: '技术支援', default: false, count: 0, url: '/panel/work-assignment/search' },
{ id: 'jspg', name: '技术评估', icon: 'jspg', group: '技术支援', default: false, count: 0, url: '/panel/technology-evaluation/list' },
{ id: 'wjll', name: '文件浏览', icon: 'wjll', group: '技术支援', default: false, count: 0, url: '/panel/fileList/index' },
// { id: 'jsfx', name: '技术分析', icon: 'jsfx', group: '技术支援', default: false, count: 0 },
{ id: 'MCO', name: 'MCO', icon: 'MCO', group: '技术支援', default: true, count: 0, url: '/panel/mco/search' },
// { id: 'pzfx', name: '品质分析', icon: 'pzfx', group: '运行品质', default: false, count: 0 },
{ id: 'khjl', name: '考核记录', icon: 'khjl', group: '运行品质', default: false, count: 0, url: '/panel/appraisal-record/list' },
// { id: 'gcfx', name: '工程分析', icon: 'gcfx', group: '运行品质', default: false, count: 0 },
{ id: 'hzgl', name: '航站管理', icon: 'hzgl', group: '航站管理', default: false, count: 0 },
{ id: 'xydw', name: '协议单位', icon: 'xydw', group: '航站管理', default: false, count: 0 }
])
const useUserStore = defineStore('user', {
const useUserStore = defineStore('mocpUser', {
state: () => {
return {
token: '',
......
......@@ -2,6 +2,7 @@ import useUserStore from 'mocp/store/user'
const baseURL = 'https://hna-platform.anyremote.cn' //测试
// const baseURL = 'https://moc.hnatechnic.com/api' //生产
// const baseURL = "http://10.123.48.67/api" //Amms内网
// const baseURL = 'https://hnaelbtest.hnatechnic.com/mocptest/api' //内网
class ServiceLoading {
......@@ -48,7 +49,6 @@ export const httpInterceptor = (options) => {
apiPwd: 'Ifar$2_0160_525_Mocp',
requestFrom: '1',
realUserId: userStore.userInfo?.id
// 1806609951173058561 1806609983825715202 1806609992679890946
}
}
}
......@@ -73,7 +73,7 @@ export const httpInterceptor = (options) => {
if (application == 'json') {
options.header = {
'Content-Type': 'application/json',
Requestfrom: '6',
Requestfrom: '1',
Realuserid: userStore.userInfo?.id,
...options.header
}
......
......@@ -42,3 +42,31 @@ export const uniqueArray = (arr) => {
}
return uniqueArr
}
// base64转临时文件
export function base64ToTempFilePath(base64Data) {
return new Promise((resolve, reject) => {
const fs = uni.getFileSystemManager()
// 生成临时文件名,并构建临时文件路径
const fileName = `temp_file_${Date.now()}.png`
const tempFilePath = `${uni.env.USER_DATA_PATH}/${fileName}`
// 移除Base64数据前缀(如果存在)
const base64WithoutPrefix = base64Data.split(',')[1]
// 将Base64字符串转换为ArrayBuffer
const arrayBuffer = uni.base64ToArrayBuffer(base64WithoutPrefix)
// 将ArrayBuffer写入临时文件
fs.writeFile({
filePath: tempFilePath,
data: arrayBuffer,
encoding: 'binary',
success: () => {
// 文件写入成功,返回临时文件路径
resolve(tempFilePath)
},
fail: (err) => {
// 文件写入失败,返回错误信息
reject(err)
}
})
})
}
......@@ -452,6 +452,72 @@
"style": {
"navigationBarTitleText": "反馈详情"
}
},
{
"path": "pages/modules/mocp/panel/electronicBill/list",
"style": {
"navigationBarTitleText": "收费单"
}
},
{
"path": "pages/modules/mocp/panel/electronicBill/routineWork/add",
"style": {
"navigationBarTitleText": "新增例行维护工作单"
}
},
{
"path": "pages/modules/mocp/panel/electronicBill/routineWork/sign",
"style": {
"navigationBarTitleText": "签名"
}
},
{
"path": "pages/modules/mocp/panel/electronicBill/routineWork/list",
"style": {
"navigationBarTitleText": "我的今天签单"
}
},
{
"path": "pages/modules/mocp/panel/electronicBill/nonRoutineWork/add",
"style": {
"navigationBarTitleText": "新增非例行维护工作单"
}
},
{
"path": "pages/modules/mocp/panel/electronicBill/nonRoutineWork/sign",
"style": {
"navigationBarTitleText": "签名"
}
},
{
"path": "pages/modules/mocp/panel/electronicBill/nonRoutineWork/list",
"style": {
"navigationBarTitleText": "我的今天签单"
}
},
{
"path": "pages/modules/mocp/panel/electronicBill/deicing/add",
"style": {
"navigationBarTitleText": "新建除防冰收费单"
}
},
{
"path": "pages/modules/mocp/panel/electronicBill/deicing/sign",
"style": {
"navigationBarTitleText": "签名"
}
},
{
"path": "pages/modules/mocp/panel/electronicBill/deicing/list",
"style": {
"navigationBarTitleText": "我的今天签单"
}
},
{
"path": "pages/modules/mocp/panel/fileList/index",
"style": {
"navigationBarTitleText": "文件浏览"
}
}
],
"globalStyle": {
......
......@@ -2,8 +2,8 @@ import { ref, reactive } from 'vue'
export const loginFormRef = ref()
//表单数据
export const loginForm = reactive({
username: '', //devzj3
password: '', //Ifar_9527008
username: 'devzj3', //devzj3
password: 'Ifar_9527008', //Ifar_9527008
verifyCode: ''
})
export const showLoad = ref(false)
......
......@@ -90,7 +90,7 @@ const loginAmms = () => {
})
.then(function (res) {
if (res.username) {
loginForm.username = res.username
loginForm.username = res.data.username
loginForm.verifyCode = 'Mocp_DebuG_9527_8341'
loginForm.password = 'Ifar2016_0525'
handleLogin()
......
export const list = [
{ title: '海航技术例行维护工作单', desc: '适用于所有海航例行工作项目', url: '/panel/electronicBill/routineWork/add' },
{ title: '海航技术飞机非例行维护工作单', desc: '海航技术飞机非例行维护工作项目单', url: '/panel/electronicBill/nonRoutineWork/add' },
{ title: '海航技术除防冰收费单', desc: '海航技术除冰收费单', url: '/panel/electronicBill/deicing/add' }
]
import { reactive, ref } from 'vue'
export const formData = reactive({
acreg: '',
aircaraftoperator: '',
antiicingCartNo1: '',
antiicingCartNo2: '',
antiicingCartNo3: '',
antiicingCartNo4: '',
antiicingDuration: '',
antiicingEndTime: '',
antiicingMix: '',
antiicingPersion1: '',
antiicingPersion2: '',
antiicingPersion3: '',
antiicingPersion4: '',
antiicingQuantity1: undefined,
antiicingQuantity2: undefined,
antiicingQuantity3: undefined,
antiicingQuantity4: undefined,
antiicingQuantityTotal: undefined,
antiicingStartTime: '',
antiicingType: '',
antiicingUnit1: '',
antiicingUnit2: '',
antiicingUnit3: '',
antiicingUnit4: '',
customerSignImg: '',
date: '',
deicingCartNo1: '',
deicingCartNo2: '',
deicingCartNo3: '',
deicingCartNo4: '',
deicingEndTime: '',
deicingMix: '',
deicingPersion1: '',
deicingPersion2: '',
deicingPersion3: '',
deicingPersion4: '',
deicingQuantity1: undefined,
deicingQuantity2: undefined,
deicingQuantity3: undefined,
deicingQuantity4: undefined,
deicingQuantityTotal: undefined,
deicingStartTime: '',
deicingType: '',
deicingUnit1: '',
deicingUnit2: '',
deicingUnit3: '',
deicingUnit4: '',
expectDeicing: 0,
fixedPointDeicing: 0,
flightNoIn: '',
flightNoOut: '',
id: undefined,
legs: '',
model: '',
nickname: '',
originalAircraftPositionDeicing: 0,
station: '',
username: ''
})
export const rules = reactive({
station: [
{
required: true,
message: '请选择航站',
trigger: ['blur', 'change']
}
],
date: [
{
type: 'number',
required: true,
message: '请选择日期',
trigger: ['blur', 'change']
}
],
acreg: [
{
required: true,
message: '请选择机号',
trigger: ['blur', 'change']
}
],
aircaraftoperator: [
{
required: true,
message: '请选择飞机所属单位',
trigger: ['blur', 'change']
}
],
model: [
{
required: true,
message: '请选择机型',
trigger: ['blur', 'change']
}
],
flightNo: [
{
required: true,
message: '请选择航班号',
trigger: ['blur', 'change']
}
]
})
import { getAirlineAcregApi } from 'mocp/api/electronicBill'
import { formData } from './add.compositions'
export const changeAcreg = async (acreg) => {
const res = await getAirlineAcregApi({ acreg }, { loading: true })
if (res.code == 200) {
if (res.data?.aircaraftoperator) {
formData.aircaraftoperator = res.data.aircaraftoperator
}
if (res.data?.actype) {
formData.model = res.data.actype
}
if (res.data?.flightNo) {
formData.flightNoIn = res.data.flightNo
formData.flightNoOut = res.data.flightNo
}
} else {
uni.$mocpMessage.error(res.message)
}
}
import { ref } from 'vue'
export const canvasImage = ref('')
import { upload } from 'mocp/utils/http'
import { canvasImage } from './sign.compositions'
import { formData } from './add.compositions'
import { addDeicingApi } from 'mocp/api/electronicBill'
export const handleSubmit = async () => {
uni.showLoading({
title: '保存中...',
mask: true
})
try {
await uploadFile()
await addDeicing()
} catch (error) {
console.error(error)
} finally {
uni.hideLoading()
}
}
export const uploadFile = async () => {
const res = await upload({ url: '/resource/uploadFile', filePath: canvasImage.value, name: 'file' })
if (res.code == 200) {
formData.customerSignImg = res.data.fileUrl
} else {
uni.$mocpMessage.error(res.message)
}
}
export const addDeicing = async () => {
const res = await addDeicingApi(formData, { loading: true })
if (res.code == 200) {
uni.$mocpJump.navigateBack()
Object.assign(formData, {
acreg: '',
aircaraftoperator: '',
antiicingCartNo1: '',
antiicingCartNo2: '',
antiicingCartNo3: '',
antiicingCartNo4: '',
antiicingDuration: '',
antiicingEndTime: '',
antiicingMix: '',
antiicingPersion1: '',
antiicingPersion2: '',
antiicingPersion3: '',
antiicingPersion4: '',
antiicingQuantity1: undefined,
antiicingQuantity2: undefined,
antiicingQuantity3: undefined,
antiicingQuantity4: undefined,
antiicingQuantityTotal: undefined,
antiicingStartTime: '',
antiicingType: '',
antiicingUnit1: '',
antiicingUnit2: '',
antiicingUnit3: '',
antiicingUnit4: '',
customerSignImg: '',
date: '',
deicingCartNo1: '',
deicingCartNo2: '',
deicingCartNo3: '',
deicingCartNo4: '',
deicingEndTime: '',
deicingMix: '',
deicingPersion1: '',
deicingPersion2: '',
deicingPersion3: '',
deicingPersion4: '',
deicingQuantity1: undefined,
deicingQuantity2: undefined,
deicingQuantity3: undefined,
deicingQuantity4: undefined,
deicingQuantityTotal: undefined,
deicingStartTime: '',
deicingType: '',
deicingUnit1: '',
deicingUnit2: '',
deicingUnit3: '',
deicingUnit4: '',
expectDeicing: 0,
fixedPointDeicing: 0,
flightNoIn: '',
flightNoOut: '',
id: undefined,
legs: '',
model: '',
nickname: '',
originalAircraftPositionDeicing: 0,
station: '',
username: ''
})
uni.$mocpMessage.success(res.message)
} else {
uni.$mocpMessage.error(res.message)
}
}
<template>
<global-page
ref="paging"
:api="deicingListApi"
:padding="24"
auto
isDataList
loadingMoreEnabled
refresherEnabled
title="我的今天签单"
:params="{
tody: 1,
userId: userStore.userInfo?.id
}"
>
<template #default="{ item }">
<view class="item">
<view class="item-title">
<view class="left">
<text class="txt">{{ item.acreg }}</text>
</view>
<view class="right">
<text class="txt">{{ baseStore.getTerminalObject[item.station] }}</text>
</view>
</view>
<view class="item-content u-line-3">
<text class="txt">{{ item.aircaraftoperator }}</text>
<text class="txt">{{ item.model }}</text>
</view>
<view class="item-footer">
<view class="label">
<global-icon icon="calendar"></global-icon>
<text class="txt">
{{ timeStampFormat(item.createTime, { format: 'YYYY/MM/DD' }) }}
</text>
</view>
</view>
</view>
</template>
</global-page>
</template>
<script setup>
import { deicingListApi } from 'mocp/api/electronicBill'
import { timeStampFormat } from 'mocp/utils/tool'
import useBaseStore from 'mocp/store/base'
import useUserStore from 'mocp/store/user'
const baseStore = useBaseStore()
const userStore = useUserStore()
</script>
<style lang="scss" scoped>
@import 'mocpStatic/css/list.scss';
</style>
<template>
<global-page :padding="24" title="签名">
<view class="mocp-title">客户方代表签字</view>
<view class="mocp-sign">
<canvas
canvas-id="canvas"
class="canvas-inner"
disable-scroll="true"
@touchstart="touchStart"
@touchmove="touchMove"
@touchend="touchEnd"
/>
</view>
<view class="footer-btns">
<view class="footer-btn">
<global-button type="primary" size="large" :radius="5" @tap="handleSave">保存签名</global-button>
</view>
<view class="footer-btn">
<global-button type="primary" size="large" :radius="5" @tap="handleSubmit" :disabled="!canvasImage">保存单据</global-button>
</view>
<view class="footer-btn">
<global-button type="primary" plain size="large" :radius="5" @tap="handleClear">重新签名</global-button>
</view>
</view>
<view class="mocp-title">用户签名预览</view>
<view class="mocp-preview">
<up-image :src="canvasImage" mode="widthFix" :show-loading="true" width="100%" height="100%" v-if="canvasImage"></up-image>
</view>
</global-page>
</template>
<script setup>
import { useDrawSignature } from 'mocp/hooks/use-sign/useSign'
import { canvasImage } from './constants/sign.compositions'
import { handleSubmit } from './constants/sign.functionals'
import { formData } from './constants/add.compositions'
import { onBeforeUnmount } from 'vue'
const { isSigned, touchStart, touchMove, touchEnd, clear, getPath } = useDrawSignature('canvas')
//保存签名
const handleSave = () => {
console.log(formData)
if (isSigned.value) {
canvasImage.value = ''
getPath('canvas').then((path) => {
canvasImage.value = path
})
} else {
uni.$mocpMessage.warning('请客户方代表签字')
}
}
//重新签名
const handleClear = () => {
canvasImage.value = ''
clear()
}
onBeforeUnmount(() => {
handleClear()
formData.customerSignImg = ''
})
</script>
<style lang="scss" scoped>
.mocp-sign,
.mocp-preview {
background: #fff;
margin-bottom: 24rpx;
}
.canvas-inner,
.mocp-preview {
width: 100%;
height: 300rpx;
}
.mocp-title {
padding: 24rpx 0;
}
.footer-btn {
margin-bottom: 24rpx;
}
</style>
<template>
<global-page padding="0 24rpx" title="收费单" auto :localData="list">
<template #default="{ item }">
<global-card :title="item.title" titleSuffix="查看详情" :rightWidth="160" @handleTitleClick="navigateTo(item.url)">
描述:{{ item.desc }}
</global-card>
</template>
</global-page>
</template>
<script setup>
import { navigateTo } from 'mocp/utils/jump'
import { list } from './constants/list.compositions'
import useElectronicBillStore from 'mocp/store/electronicBill'
import { onLoad } from '@dcloudio/uni-app'
const electronicBillStore = useElectronicBillStore()
onLoad(() => {
electronicBillStore.init()
})
</script>
<style lang="scss" scoped></style>
import { reactive, ref } from 'vue'
export const formData = reactive({
acreg: '',
acu: undefined,
aircaraftoperator: '',
asu: undefined,
charger: undefined,
cherryPicker: undefined,
customerSignImg: '',
date: '',
flightNo: '',
gpu: undefined,
hanger: undefined,
id: 0,
jackscrew: undefined,
ladder: undefined,
legs: '',
material1: '',
material2: '',
material3: '',
model: '',
nickname: '',
number1: undefined,
number2: undefined,
number3: undefined,
oxygenCharging: undefined,
powerTool: undefined,
shockStrutCharging: undefined,
station: '',
tails: undefined,
tireCharging: undefined,
tools: undefined,
tractor: undefined,
username: '',
work1: '',
work2: '',
work3: '',
workingHours1: undefined,
workingHours2: undefined,
workingHours3: undefined
})
export const rules = reactive({
station: [
{
required: true,
message: '请选择航站',
trigger: ['blur', 'change']
}
],
date: [
{
type: 'number',
required: true,
message: '请选择日期',
trigger: ['blur', 'change']
}
],
acreg: [
{
required: true,
message: '请选择机号',
trigger: ['blur', 'change']
}
],
aircaraftoperator: [
{
required: true,
message: '请选择飞机所属单位',
trigger: ['blur', 'change']
}
],
model: [
{
required: true,
message: '请选择机型',
trigger: ['blur', 'change']
}
],
flightNo: [
{
required: true,
message: '请选择航班号',
trigger: ['blur', 'change']
}
]
})
import { getAirlineAcregApi } from 'mocp/api/electronicBill'
import { formData } from './add.compositions'
export const changeAcreg = async (acreg) => {
const res = await getAirlineAcregApi({ acreg }, { loading: true })
if (res.code == 200) {
if (res.data?.aircaraftoperator) {
formData.aircaraftoperator = res.data.aircaraftoperator
}
if (res.data?.actype) {
formData.model = res.data.actype
}
if (res.data?.flightNo) {
formData.flightNo = res.data.flightNo
}
} else {
uni.$mocpMessage.error(res.message)
}
}
import { upload } from 'mocp/utils/http'
import { canvasImage } from './sign.compositions'
import { formData } from './add.compositions'
import { addNonRoutineWorkApi } from 'mocp/api/electronicBill'
export const handleSubmit = async () => {
uni.showLoading({
title: '保存中...',
mask: true
})
try {
await uploadFile()
await addNonRoutineWork()
} catch (error) {
console.error(error)
} finally {
uni.hideLoading()
}
}
export const uploadFile = async () => {
const res = await upload({ url: '/resource/uploadFile', filePath: canvasImage.value, name: 'file' })
if (res.code == 200) {
formData.customerSignImg = res.data.fileUrl
} else {
uni.$mocpMessage.error(res.message)
}
}
export const addNonRoutineWork = async () => {
const res = await addNonRoutineWorkApi(formData, { loading: true })
if (res.code == 200) {
uni.$mocpJump.navigateBack()
Object.assign(formData, {
acreg: '',
acu: undefined,
aircaraftoperator: '',
asu: undefined,
charger: undefined,
cherryPicker: undefined,
customerSignImg: '',
date: '',
flightNo: '',
gpu: undefined,
hanger: undefined,
id: 0,
jackscrew: undefined,
ladder: undefined,
legs: '',
material1: '',
material2: '',
material3: '',
model: '',
nickname: '',
number1: undefined,
number2: undefined,
number3: undefined,
oxygenCharging: undefined,
powerTool: undefined,
shockStrutCharging: undefined,
station: '',
tails: undefined,
tireCharging: undefined,
tools: undefined,
tractor: undefined,
username: '',
work1: '',
work2: '',
work3: '',
workingHours1: undefined,
workingHours2: undefined,
workingHours3: undefined
})
uni.$mocpMessage.success(res.message)
} else {
uni.$mocpMessage.error(res.message)
}
}
<template>
<global-page
ref="paging"
:api="noRoutineWorkListApi"
:padding="24"
auto
isDataList
loadingMoreEnabled
refresherEnabled
title="我的今天签单"
:params="{
tody: 1,
userId: userStore.userInfo?.id
}"
>
<template #default="{ item }">
<view class="item">
<view class="item-title">
<view class="left">
<text class="txt">{{ item.acreg }}</text>
</view>
<view class="right">
<text class="txt">{{ baseStore.getTerminalObject[item.station] }}</text>
</view>
</view>
<view class="item-content u-line-3">
<text class="txt">{{ item.aircaraftoperator }}</text>
<text class="txt">{{ item.model }}</text>
</view>
<view class="item-footer">
<view class="label">
<global-icon icon="calendar"></global-icon>
<text class="txt">
{{ timeStampFormat(item.createTime, { format: 'YYYY/MM/DD' }) }}
</text>
</view>
</view>
</view>
</template>
</global-page>
</template>
<script setup>
import { noRoutineWorkListApi } from 'mocp/api/electronicBill'
import { timeStampFormat } from 'mocp/utils/tool'
import useBaseStore from 'mocp/store/base'
import useUserStore from 'mocp/store/user'
const baseStore = useBaseStore()
const userStore = useUserStore()
</script>
<style lang="scss" scoped>
@import 'mocpStatic/css/list.scss';
</style>
<template>
<global-page :padding="24" title="签名">
<view class="mocp-title">客户方代表签字</view>
<view class="mocp-sign">
<canvas
canvas-id="canvas"
class="canvas-inner"
disable-scroll="true"
@touchstart="touchStart"
@touchmove="touchMove"
@touchend="touchEnd"
/>
</view>
<view class="footer-btns">
<view class="footer-btn">
<global-button type="primary" size="large" :radius="5" @tap="handleSave">保存签名</global-button>
</view>
<view class="footer-btn">
<global-button type="primary" size="large" :radius="5" @tap="handleSubmit" :disabled="!canvasImage">保存单据</global-button>
</view>
<view class="footer-btn">
<global-button type="primary" plain size="large" :radius="5" @tap="handleClear">重新签名</global-button>
</view>
</view>
<view class="mocp-title">用户签名预览</view>
<view class="mocp-preview">
<up-image :src="canvasImage" mode="widthFix" :show-loading="true" width="100%" height="100%" v-if="canvasImage"></up-image>
</view>
</global-page>
</template>
<script setup>
import { useDrawSignature } from 'mocp/hooks/use-sign/useSign'
import { canvasImage } from './constants/sign.compositions'
import { handleSubmit } from './constants/sign.functionals'
import { formData } from './constants/add.compositions'
import { onBeforeUnmount } from 'vue'
const { isSigned, touchStart, touchMove, touchEnd, clear, getPath } = useDrawSignature('canvas')
//保存签名
const handleSave = () => {
if (isSigned.value) {
canvasImage.value = ''
getPath('canvas').then((path) => {
canvasImage.value = path
})
} else {
uni.$mocpMessage.warning('请客户方代表签字')
}
}
//重新签名
const handleClear = () => {
canvasImage.value = ''
clear()
}
onBeforeUnmount(() => {
handleClear()
formData.customerSignImg = ''
})
</script>
<style lang="scss" scoped>
.mocp-sign,
.mocp-preview {
background: #fff;
margin-bottom: 24rpx;
}
.canvas-inner,
.mocp-preview {
width: 100%;
height: 300rpx;
}
.mocp-title {
padding: 24rpx 0;
}
.footer-btn {
margin-bottom: 24rpx;
}
</style>
<template>
<global-page
title="新建例行维护工作单"
:showNavRight="true"
navRightText="今天签单"
@handleRightClick="navigateTo('/panel/electronicBill/routineWork/list')"
showFooterBtn
footerBtnText="客户方代表签字"
@handleFooterClick="handleFooterClick"
>
<up-form ref="formRef" labelPosition="left" labelWidth="auto" :model="formData" :rules="rules" errorType="toast">
<view class="mocp-title">基本信息</view>
<view class="mocp-form">
<up-form-item label="航站" prop="station" :borderBottom="true" required>
<global-picker
pickAlign="right"
v-model="formData.station"
clearable
:options="baseStore.getTerminalSelect"
filter
></global-picker>
</up-form-item>
<up-form-item label="日期" prop="date" :borderBottom="true" required>
<global-date pickAlign="right" clearable v-model="formData.date" defaultToday></global-date>
</up-form-item>
<up-form-item label="机号" prop="acreg" :borderBottom="true" required>
<global-picker pickAlign="right" v-model="formData.acreg" :options="allAc" clearable filter @change="changeAcreg"></global-picker>
</up-form-item>
<up-form-item label="飞机所属单位" prop="aircaraftoperator" :borderBottom="true" required>
<global-picker pickAlign="right" v-model="formData.aircaraftoperator" :options="allAirline" clearable filter></global-picker>
</up-form-item>
<up-form-item label="机型" prop="model" :borderBottom="true" required>
<global-picker v-model="formData.model" pickAlign="right" :options="allAcType" clearable filter></global-picker>
</up-form-item>
<up-form-item label="进港航班号" prop="flightNoIn" :borderBottom="true" required>
<up-input v-model="formData.flightNoIn" inputAlign="right" border="none" placeholder="请输入" clearable></up-input>
</up-form-item>
<up-form-item label="出港航班号" prop="flightNoOut" :borderBottom="true">
<up-input v-model="formData.flightNoOut" inputAlign="right" border="none" placeholder="请输入" clearable></up-input>
</up-form-item>
<up-form-item label="航段" prop="legs" :borderBottom="true">
<up-input v-model="formData.legs" inputAlign="right" border="none" placeholder="请输入" clearable></up-input>
</up-form-item>
</view>
<view class="mocp-title">过站维护TR</view>
<view class="mocp-form">
<up-form-item label="过站TR" prop="tr" :borderBottom="true">
<global-switch v-model="formData.tr" switchAlign="right"></global-switch>
</up-form-item>
<up-form-item label="一般勤务" prop="serviceTr" :borderBottom="true">
<global-switch v-model="formData.serviceTr" switchAlign="right"></global-switch>
</up-form-item>
</view>
<view class="mocp-title">航前维护PF</view>
<view class="mocp-form">
<up-form-item label="航前PR" prop="pf" :borderBottom="true">
<global-switch v-model="formData.pf" switchAlign="right"></global-switch>
</up-form-item>
<up-form-item label="一般勤务" prop="servicePf" :borderBottom="true">
<global-switch v-model="formData.servicePf" switchAlign="right"></global-switch>
</up-form-item>
</view>
<view class="mocp-title">航后维护AF</view>
<view class="mocp-form">
<up-form-item label="航后AF" prop="af" :borderBottom="true">
<global-switch v-model="formData.af" switchAlign="right"></global-switch>
</up-form-item>
<up-form-item label="一般勤务" prop="serviceAf" :borderBottom="true">
<global-switch v-model="formData.serviceAf" switchAlign="right"></global-switch>
</up-form-item>
</view>
<view class="mocp-title">设备使用记录</view>
<view class="mocp-form">
<up-form-item label="电源车(单位/小时)" prop="groundPower" :borderBottom="true">
<up-input type="number" v-model="formData.groundPower" inputAlign="right" border="none" placeholder="请输入" clearable></up-input>
</up-form-item>
<up-form-item label="气源车(单位/次)" prop="airStarter" :borderBottom="true">
<up-input type="number" v-model="formData.airStarter" inputAlign="right" border="none" placeholder="请输入" clearable></up-input>
</up-form-item>
<up-form-item label="牵引车(单位/次)" prop="towPus" :borderBottom="true">
<up-input type="number" v-model="formData.towPus" inputAlign="right" border="none" placeholder="请输入" clearable></up-input>
</up-form-item>
<up-form-item label="空调车(单位/小时)" prop="airConditioning" :borderBottom="true">
<up-input
type="number"
v-model="formData.airConditioning"
inputAlign="right"
border="none"
placeholder="请输入"
clearable
></up-input>
</up-form-item>
<up-form-item label="其他" prop="others1" :borderBottom="true">
<up-input v-model="formData.others1" inputAlign="right" border="none" placeholder="请输入" clearable></up-input>
</up-form-item>
<up-form-item label="其他" prop="others2" :borderBottom="true">
<up-input v-model="formData.others2" inputAlign="right" border="none" placeholder="请输入" clearable></up-input>
</up-form-item>
</view>
<view class="mocp-title">辅助信息</view>
<view class="mocp-form">
<up-form-item label="备降" prop="diversion" :borderBottom="true">
<global-switch v-model="formData.diversion" switchAlign="right"></global-switch>
</up-form-item>
<up-form-item label="返航" prop="returnFlight" :borderBottom="true">
<global-switch v-model="formData.returnFlight" switchAlign="right"></global-switch>
</up-form-item>
<up-form-item label="无故障过站待命" prop="onCall" :borderBottom="true">
<global-switch v-model="formData.onCall" switchAlign="right"></global-switch>
</up-form-item>
<up-form-item label="备注" prop="remark" :borderBottom="true">
<up-input v-model="formData.remark" inputAlign="right" border="none" placeholder="请输入" clearable></up-input>
</up-form-item>
</view>
</up-form>
</global-page>
</template>
<script setup>
import useBaseStore from 'mocp/store/base'
import useElectronicBillStore from 'mocp/store/electronicBill'
import { formData, rules } from './constants/add.compositions'
import { navigateTo } from 'mocp/utils/jump'
import { ref } from 'vue'
import { changeAcreg } from './constants/add.functionals'
const baseStore = useBaseStore()
const electronicBillStore = useElectronicBillStore()
const {
selectList: { allAc, allAcType, allAirline }
} = electronicBillStore
//提交
const formRef = ref()
const handleFooterClick = async () => {
await formRef.value?.validate()
navigateTo('/panel/electronicBill/routineWork/sign')
}
</script>
<style lang="scss" scoped>
.mocp-form {
background: #fff;
margin-bottom: 24rpx;
padding: 0 32rpx;
}
.mocp-title {
padding: 0 32rpx 24rpx 32rpx;
background-color: #f7f8fa;
}
</style>
import { reactive } from 'vue'
export const formData = reactive({
acreg: '',
af: 0,
airConditioning: undefined,
airStarter: undefined,
aircaraftoperator: '',
customerSignImg: '',
date: '',
diversion: 0,
flightNoIn: '',
flightNoOut: '',
groundPower: undefined,
id: 0,
legs: '',
model: '',
nickname: '',
onCall: 0,
others1: '',
others2: '',
pf: 0,
remark: '',
returnFlight: 0,
serviceAf: 0,
servicePf: 0,
serviceTr: 0,
station: '',
towPus: undefined,
tr: 1,
username: ''
})
export const rules = reactive({
station: [
{
required: true,
message: '请选择航站',
trigger: ['blur', 'change']
}
],
date: [
{
type: 'number',
required: true,
message: '请选择日期',
trigger: ['blur', 'change']
}
],
acreg: [
{
required: true,
message: '请选择机号',
trigger: ['blur', 'change']
}
],
aircaraftoperator: [
{
required: true,
message: '请选择飞机所属单位',
trigger: ['blur', 'change']
}
],
model: [
{
required: true,
message: '请选择机型',
trigger: ['blur', 'change']
}
],
flightNoIn: [
{
required: true,
message: '请选择进港航班号',
trigger: ['blur', 'change']
}
]
})
import { getAirlineAcregApi } from 'mocp/api/electronicBill'
import { formData } from './add.compositions'
export const changeAcreg = async (acreg) => {
const res = await getAirlineAcregApi({ acreg }, { loading: true })
if (res.code == 200) {
if (res.data?.aircaraftoperator) {
formData.aircaraftoperator = res.data.aircaraftoperator
}
if (res.data?.actype) {
formData.model = res.data.actype
}
if (res.data?.flightNo) {
formData.flightNoIn = res.data.flightNo
}
} else {
uni.$mocpMessage.error(res.message)
}
}
import { ref } from 'vue'
export const canvasImage = ref('')
import { upload } from 'mocp/utils/http'
import { canvasImage } from './sign.compositions'
import { formData } from './add.compositions'
import { addRoutineWorkApi } from 'mocp/api/electronicBill'
export const handleSubmit = async () => {
uni.showLoading({
title: '保存中...',
mask: true
})
try {
await uploadFile()
await addRoutineWork()
} catch (error) {
console.error(error)
} finally {
uni.hideLoading()
}
}
export const uploadFile = async () => {
const res = await upload({ url: '/resource/uploadFile', filePath: canvasImage.value, name: 'file' })
if (res.code == 200) {
formData.customerSignImg = res.data.fileUrl
} else {
uni.$mocpMessage.error(res.message)
}
}
export const addRoutineWork = async () => {
const res = await addRoutineWorkApi(formData, { loading: true })
if (res.code == 200) {
uni.$mocpJump.navigateBack()
Object.assign(formData, {
acreg: '',
af: 0,
airConditioning: undefined,
airStarter: undefined,
aircaraftoperator: '',
customerSignImg: '',
date: '',
diversion: 0,
flightNoIn: '',
flightNoOut: '',
groundPower: undefined,
id: 0,
legs: '',
model: '',
nickname: '',
onCall: 0,
others1: '',
others2: '',
pf: 0,
remark: '',
returnFlight: 0,
serviceAf: 0,
servicePf: 0,
serviceTr: 0,
station: '',
towPus: undefined,
tr: 1,
username: ''
})
uni.$mocpMessage.success(res.message)
} else {
uni.$mocpMessage.error(res.message)
}
}
<template>
<global-page
ref="paging"
:api="routineWorkListApi"
:padding="24"
auto
isDataList
loadingMoreEnabled
refresherEnabled
title="我的今天签单"
:params="{
tody: 1,
userId: userStore.userInfo?.id
}"
>
<template #default="{ item }">
<view class="item">
<view class="item-title">
<view class="left">
<text class="txt">{{ item.acreg }}</text>
</view>
<view class="right">
<text class="txt">{{ baseStore.getTerminalObject[item.station] }}</text>
</view>
</view>
<view class="item-content u-line-3">
<text class="txt">{{ item.aircaraftoperator }}</text>
<text class="txt">{{ item.model }}</text>
</view>
<view class="item-footer">
<view class="label">
<global-icon icon="calendar"></global-icon>
<text class="txt">
{{ timeStampFormat(item.createTime, { format: 'YYYY/MM/DD' }) }}
</text>
</view>
</view>
</view>
</template>
</global-page>
</template>
<script setup>
import { routineWorkListApi } from 'mocp/api/electronicBill'
import { timeStampFormat } from 'mocp/utils/tool'
import useBaseStore from 'mocp/store/base'
import useUserStore from 'mocp/store/user'
const baseStore = useBaseStore()
const userStore = useUserStore()
</script>
<style lang="scss" scoped>
@import 'mocpStatic/css/list.scss';
</style>
<template>
<global-page :padding="24" title="签名">
<view class="mocp-title">客户方代表签字</view>
<view class="mocp-sign">
<canvas
canvas-id="canvas"
class="canvas-inner"
disable-scroll="true"
@touchstart="touchStart"
@touchmove="touchMove"
@touchend="touchEnd"
/>
</view>
<view class="footer-btns">
<view class="footer-btn">
<global-button type="primary" size="large" :radius="5" @tap="handleSave">保存签名</global-button>
</view>
<view class="footer-btn">
<global-button type="primary" size="large" :radius="5" @tap="handleSubmit" :disabled="!canvasImage">保存单据</global-button>
</view>
<view class="footer-btn">
<global-button type="primary" plain size="large" :radius="5" @tap="handleClear">重新签名</global-button>
</view>
</view>
<view class="mocp-title">用户签名预览</view>
<view class="mocp-preview">
<up-image :src="canvasImage" mode="widthFix" :show-loading="true" width="100%" height="100%" v-if="canvasImage"></up-image>
</view>
</global-page>
</template>
<script setup>
import { useDrawSignature } from 'mocp/hooks/use-sign/useSign'
import { canvasImage } from './constants/sign.compositions'
import { handleSubmit } from './constants/sign.functionals'
import { formData } from './constants/add.compositions'
import { onBeforeUnmount } from 'vue'
const { isSigned, touchStart, touchMove, touchEnd, clear, getPath } = useDrawSignature('canvas')
//保存签名
const handleSave = () => {
if (isSigned.value) {
canvasImage.value = ''
getPath('canvas').then((path) => {
canvasImage.value = path
})
} else {
uni.$mocpMessage.warning('请客户方代表签字')
}
}
//重新签名
const handleClear = () => {
canvasImage.value = ''
clear()
}
onBeforeUnmount(() => {
handleClear()
formData.customerSignImg = ''
})
</script>
<style lang="scss" scoped>
.mocp-sign,
.mocp-preview {
background: #fff;
margin-bottom: 24rpx;
}
.canvas-inner,
.mocp-preview {
width: 100%;
height: 300rpx;
}
.mocp-title {
padding: 24rpx 0;
}
.footer-btn {
margin-bottom: 24rpx;
}
</style>
import { downuploadApi } from 'mocp/api/fileList'
import { base64ToTempFilePath } from 'mocp/utils/tool'
export const transformData = (data) => {
return data.map((item) => {
let type = item.name?.split('.')[1]?.toLowerCase() || 'unknown'
if (item.directory) {
type = 'folder'
}
return {
...item,
type
}
})
}
export const handleClick = (item) => {
if (item.directory) {
uni.$mocpJump.navigateTo(`${'/panel/fileList/index?path=' + item.path}`)
} else {
downupload(item.path)
}
}
export const downupload = async (path) => {
uni.showLoading({
title: '正在打开文件',
mask: true
})
const res = await downuploadApi({ path })
if (res.code == 200) {
base64ToTempFilePath(res.data)
.then((filePath) => {
uni.openDocument({
filePath,
showMenu: true,
success: function () {
uni.hideLoading()
console.log('文件打开成功')
},
fail: function () {
uni.hideLoading()
uni.$mocpMessage.error('打开文件失败,请重新打开')
}
})
})
.catch(() => {
uni.hideLoading()
uni.$mocpMessage.error('打开文件失败,请重新打开')
})
} else {
uni.hideLoading()
uni.$mocpMessage.error(res.message)
}
}
<template>
<global-page
title="文件预览"
isDataList
refresherEnabled
loadingMoreEnabled
localPaging
auto
:pageSize="20"
:params="{ path: query.path }"
:api="getFileListApi"
:padding="24"
:transformData="transformData"
>
<template #default="{ item }">
<view class="file" @tap="handleClick(item)">
<view class="file-left">
<template v-if="['image', 'png', 'jpg', 'jpeg', 'gif'].includes(item.type)">
<image src="/static/mocp/image/common/image.png" mode="widthFix" />
</template>
<template v-else-if="['video', 'mp4'].includes(item.type)">
<image src="/static/mocp/image/common/video.png" mode="widthFix" />
</template>
<template v-else-if="['pdf'].includes(item.type)">
<image src="/static/mocp/image/common/pdf.png" mode="widthFix" />
</template>
<template v-else-if="['ppt', 'txt'].includes(item.type)">
<image src="/static/mocp/image/common/ppt.png" mode="widthFix" />
</template>
<template v-else-if="['folder'].includes(item.type)">
<image src="/static/mocp/image/common/folder.png" mode="widthFix" style="width: 60rpx" />
</template>
<template v-else-if="['mel'].includes(item.type)">
<image src="/static/mocp/image/common/mel.png" mode="widthFix" />
</template>
<template v-else>
<image src="/static/mocp/image/common/unknown.png" mode="widthFix" />
</template>
<text class="txt">{{ item.name }}</text>
</view>
<view class="file-right">
<view class="circle">
<up-icon name="arrow-right" :size="10" color="#86909C"></up-icon>
</view>
</view>
</view>
</template>
</global-page>
</template>
<script setup>
import { getFileListApi } from 'mocp/api/fileList'
import { handleClick, transformData } from './constants/index.functionals'
const query = defineProps(['path'])
</script>
<style lang="scss" scoped>
.file {
display: flex;
justify-content: space-between;
align-items: center;
padding: 32rpx;
margin-bottom: 24rpx;
border: 1px solid rgba(0, 0, 0, 0.06);
&-left {
display: flex;
justify-content: space-between;
align-items: center;
image {
width: 40rpx;
}
.txt {
font-size: 34rpx;
color: $mocp-text-5;
margin-left: 24rpx;
}
}
&-right {
.circle {
border-radius: 50%;
background-color: #e5e5e5;
width: 32rpx;
height: 32rpx;
display: flex;
justify-content: center;
align-items: center;
}
}
}
</style>
......@@ -15,7 +15,10 @@
.txt {
color: $mocp-text-5;
font-size: 34rpx;
margin: 0 16rpx;
margin-left: 16rpx;
&:first-child {
margin-left: 0;
}
}
.place {
font-size: 28rpx;
......@@ -28,7 +31,10 @@
.txt {
color: $mocp-text-5;
font-size: 34rpx;
margin: 0 16rpx;
margin-left: 16rpx;
&:first-child {
margin-left: 0;
}
}
}
.right {
......@@ -39,6 +45,9 @@
.txt {
font-size: 28rpx;
margin-left: 16rpx;
&:first-child {
margin-left: 0;
}
}
}
}
......@@ -48,6 +57,14 @@
color: $mocp-text-4;
line-height: 40rpx;
word-break: break-all;
.txt {
color: $mocp-text-5;
font-size: 34rpx;
margin: 0 16rpx;
&:first-child {
margin-left: 0;
}
}
}
&-footer {
display: flex;
......
src/static/mocp/image/common/pdf.png

1006 Bytes | W: | H:

src/static/mocp/image/common/pdf.png

1.37 KB | W: | H:

src/static/mocp/image/common/pdf.png
src/static/mocp/image/common/pdf.png
src/static/mocp/image/common/pdf.png
src/static/mocp/image/common/pdf.png
  • 2-up
  • Swipe
  • Onion skin
src/static/mocp/image/common/video.png

1.03 KB | W: | H:

src/static/mocp/image/common/video.png

1.12 KB | W: | H:

src/static/mocp/image/common/video.png
src/static/mocp/image/common/video.png
src/static/mocp/image/common/video.png
src/static/mocp/image/common/video.png
  • 2-up
  • Swipe
  • Onion skin
......@@ -3,6 +3,7 @@ import uni from '@dcloudio/vite-plugin-uni'
import path from 'node:path'
// https://vitejs.dev/config/
export default defineConfig({
base: './', // 打包的静态资源引用路径
plugins: [uni()],
resolve: {
alias: {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment