Files
gjt_mini/pages/returnCar/cost.vue
2025-12-30 09:44:46 +08:00

1918 lines
55 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view>
<scroll-view scroll-y="true" style="height: 95vh">
<view class="container">
<u-collapse :value="['basic', 'cost']" :border="false">
<u-collapse-item title="基本信息" name="basic">
<view class="item">
<view class="title">车牌号</view>
<u--input
border="surround"
v-model="datas.plateNumber"
disabled
fontSize="26"
></u--input>
</view>
<view class="item">
<view class="title">客户名称</view>
<u--input
border="surround"
v-model="datas.customerName"
disabled
fontSize="26"
></u--input>
</view>
<view class="item">
<view class="title">交车时间</view>
<u--input
border="surround"
:disabledColor="'#f5f7fa'"
disabled
fontSize="26"
:value="formatDateTime(datas.handoverDate, 'hour')"
>
</u--input>
</view>
<view class="item">
<view class="title">还车时间</view>
<u--input
border="surround"
:disabledColor="'#f5f7fa'"
disabled
fontSize="26"
:value="formatDateTime(datas.returnDate, 'hour')"
>
</u--input>
</view>
</u-collapse-item>
<u-collapse-item ref="costCollapse" title="费用明细" name="cost">
<view
class="item department"
v-for="(t, k) in departmentList"
:key="t.id"
>
<view class="item">
<u-row customStyle="margin-bottom: 10px;align-items: baseline;">
<u-col span="3">
<view
class="title"
style="font-size: 30rpx; font-weight: bold"
>
{{ t.depName }}
</view>
</u-col>
<u-col span="5">
<view class="demo-layout">
<view class="title" style="margin-right: 10px">金额</view>
<u--input
border="surround"
v-model="t.amount"
disabled
fontSize="26"
></u--input>
</view>
</u-col>
<u-col span="4">
<view
class="demo-layout"
style="justify-content: space-around"
>
<view
class="title isRed"
:class="{ isGreen: t.costStatus == 1 }"
>
{{ t.costStatus == 1 ? "已提交" : "未提交" }}
</view>
<view
class="title"
v-if="t.costStatus == 1 && isBussinessRole"
><u-button
type="primary"
size="mini"
plain
@tap="withdrawal(k)"
text="撤回"
></u-button>
</view>
<view class="title twoBtn">
<u-button
v-if="
t.depCode === userInfo.depCode && t.costStatus == 0
"
type="primary"
size="mini"
plain
@tap="commitConfirm(k)"
text="提交"
></u-button>
<u-button
v-if="
t.depCode === userInfo.depCode && t.costStatus == 0
"
type="primary"
size="mini"
plain
@tap="addForm(k)"
text="添加"
></u-button>
</view>
</view>
</u-col>
</u-row>
<u-row customStyle="margin-bottom: 10px">
<u-col span="3"> </u-col>
<u-col span="9">
<view class="demo-layout">
<view class="title" style="margin-right: 10px">说明</view>
<u--input
border="surround"
v-model="t.remark"
:disabled="t.depCode !== userInfo.depCode"
fontSize="26"
></u--input>
</view>
</u-col>
</u-row>
</view>
<!-- <u-collapse :value="[`xxx${k}`]" :border="false">
<u-collapse-item
:ref="`xxx${k}`"
:title="`xxx${k}`"
:name="`xxx${k}`"
>
<view>aaaa</view>
</u-collapse-item>
</u-collapse> -->
<view
class="truckItem"
v-for="(item, index) in t.depDetailCostVoList"
:key="item.id"
>
<!-- @cancel="() => $set(showSubjectPicker, index, false)" -->
<view class="item">
<view class="title">项目</view>
<!-- <picker
bindchange="confirmSubject"
:value="index"
:range="subjectList"
range-key="name"
>
<view class="picker">
当前选择:{{ subjectList[index] }}
</view>
</picker> -->
<picker
@change="confirmSubject($event, index, k)"
:range="subjectList"
:disabled="
t.depCode !== userInfo.depCode ||
disabled ||
t.costStatus == 1
"
range-key="name"
>
<u--input
border="surround"
:disabledColor="disabled ? '#f5f7fa' : '#ffffff'"
:value="item.subjectName"
:disabled="true"
fontSize="26"
>
</u--input>
</picker>
<!-- <u-picker
:show="showSubjectPicker[index]"
:columns="[subjectList]"
keyName="name"
:immediateChange="true"
@confirm="(e) => confirmSubject(e, index, k)"
>
</u-picker>
<u--input
border="surround"
:value="item.subjectName"
:disabledColor="disabled ? '#f5f7fa' : '#ffffff'"
disabled
fontSize="26"
@tap="() => $set(showSubjectPicker, index, true)"
>
</u--input> -->
</view>
<view class="item">
<view class="title required">金额</view>
<u-input
border="surround"
:value="item.amount"
@change="amountChange($event, index, k)"
fontSize="26"
type="digit"
:disabled="
t.depCode !== userInfo.depCode ||
disabled ||
t.costStatus == 1
"
>
</u-input>
<!-- @change="
(value) =>
(departmentList[k].depDetailCostVoList[index].amount = value)
" @change="amountChange($event, index, k)" department[k].depDetailCostVoList[index] -->
</view>
<view class="item">
<view class="title">备注</view>
<u--textarea
border="surround"
v-model="item.remark"
fontSize="26"
:disabled="
t.depCode !== userInfo.depCode ||
disabled ||
t.costStatus == 1
"
></u--textarea>
</view>
<view class="item">
<view class="title">照片</view>
<u-upload
:fileList="item.pictureList"
@afterRead="afterRead"
:width="155"
:height="155"
multiple
@delete="deletePic"
:name="index + '-' + k"
:deletable="
!(
t.depCode !== userInfo.depCode ||
disabled ||
t.costStatus == 1
)
"
:disabled="
t.depCode !== userInfo.depCode ||
disabled ||
t.costStatus == 1
"
></u-upload>
<!-- :disabled="disabled"
:deletable="!disabled" -->
</view>
<view class="item">
<view class="title">附件</view>
<view class="block">
<view class="item">
<u-upload
:fileList="item.attachmentList"
:disabled="
t.depCode !== userInfo.depCode ||
disabled ||
t.costStatus == 1
"
@afterRead="afterReadPdf"
uploadIcon="plus"
accept="all"
multiple
:name="index + '-' + k"
@delete="deletePdf"
:deletable="
!(
t.depCode !== userInfo.depCode ||
disabled ||
t.costStatus == 1
)
"
:width="155"
:height="155"
></u-upload>
</view>
<view
class="item"
v-for="t in item.attachmentList"
:key="t.url"
>
<view class="line" style="justify-content: space-between">
<view class="text-small left">{{ t.fileName }}</view>
<view class="text-small" @tap="previewYyPdf(t)"
>预览</view
>
</view>
</view>
</view>
</view>
<view class="item">
<view class="depDetailCostVoListBtns">
<button
:class="{ disabled: isRead }"
v-if="t.depCode === userInfo.depCode && t.costStatus == 0"
class="del"
@tap="delForm(index, k)"
>
删除
</button>
</view>
</view>
</view>
</view>
</u-collapse-item>
</u-collapse>
<view
><view class="item">
<view class="title">保证金</view>
<u--input
border="surround"
:disabled="true"
v-model="datas.earnestMoney"
fontSize="26"
type="digit"
></u--input>
</view>
<view class="item">
<view class="title">待结算费用</view>
<u--input
border="surround"
:disabled="true"
v-model="_watiBond"
fontSize="26"
type="digit"
></u--input>
</view>
<view class="item">
<view class="title">总计</view>
<u--input
border="surround"
:disabled="true"
v-model="_total"
fontSize="26"
type="digit"
></u--input>
</view>
<view class="item" v-if="isFinanceRole && datas.isSubmit">
<view class="title">评论</view>
<u--textarea
:disabled="disabled"
border="surround"
v-model="datas.discuss"
fontSize="26"
></u--textarea>
</view>
</view>
<!-- <view v-else
><view class="item">
<view class="title">费用总计</view>
<u--input
border="surround"
:disabled="true"
v-model="_bill"
fontSize="26"
type="digit"
></u--input>
</view>
<view class="item">
<view class="title">说明</view>
<u--textarea
border="surround"
v-model="datas.remark"
fontSize="26"
:disabled="disabled"
></u--textarea> </view
></view> -->
<u-loading-page
bg-color="#ffffff"
color="#7ba746"
font-size="24"
:loading="loading"
:loading-text="loadingText"
></u-loading-page>
<view class="btns">
<button
v-if="isBussinessRole"
class="done"
:class="{ disabled: isRead }"
:disabled="isRead"
@tap="submitConfirm"
>
提交
</button>
<button
v-if="!(isFinanceRole && datas.isSubmit)"
class="done"
:class="{ disabled: isRead }"
:disabled="isRead"
@tap="save"
>
保存
</button>
<button
v-if="isFinanceRole && datas.isSubmit"
class="done"
:class="{ disabled: isRead }"
:disabled="isRead"
@tap="costConfirm"
>
结算
</button>
<button
v-if="isFinanceRole && datas.isSubmit"
class="done"
:class="{ disabled: isRead }"
:disabled="isRead"
@tap="notPassConfirm"
>
驳回
</button>
<button class="cancel" @tap="navigateBack">取消</button>
</view>
<view style="width: 0px; height: 0px; overflow: hidden">
<canvas
:style="
'width: ' +
canvasWidth +
'px; height:' +
canvasHeight +
'px;left:8888px'
"
canvas-id="myCanvas"
></canvas>
</view>
</view>
</scroll-view>
</view>
</template>
<script>
import { getUser } from "@/utils/auth.js";
export default {
options: {
styleIsolation: "shared", // 解除样式隔离
},
data() {
return {
value: null,
checkListShow: false, // 检查单弹窗
datas: {
contractNo: "合同编号",
projectName: "项目名称",
isDrivingTraining: 0,
dataList: [], // 交车单数据
hydrogenUnit: null,
earnestMoney: 0,
isSubmit: false,
discuss: "",
},
id: "",
brands: [], // 车辆品牌字典列表
truckType: [], // 车辆型号字典列表,
salesManagerDic: [], // 销售经理字典列表
yesNoDic: [],
userInfo: {}, // 用户信息
contractAuthorizerInformationList: [], // 授权人列表
inStoreList: [], // 在库状态车辆列表
showIsDrivingTrainingPicker: false,
showHandoverDatePicker: false,
platNumberDisabled: true,
showPlateNumberPicker: false,
fileList1: [], // 仪表盘照片
fileList2: [], // 正面照片
fileList3: [], // 左前方照片
fileList4: [], // 右前方照片
fileList5: [], // 左后方照片
fileList6: [], // 右后方照片
fileList7: [], // 瑕疵照片
fileList8: [], // 轮胎照片
fileList9: [], // 其它
fileList10: [], // 司机证件
fileList11: [], // 电子文档
fileList12: [], // 相关材料
canvasWidth: 0,
canvasHeight: 0,
isRead: false, // 页面是否处于阅读模式
formDataList: [], // 交车检查单数据副本
loading: false,
loadingText: "加载中...",
hasSign: false, // 已完成签名,签署文件已生成
hasSaveCheckList: false, // 是否保存过还车检查单
compressPicMap: new Map(), // 缩略图映射key为原图value为缩略图
showSubjectPicker: [false], // 显示项目选择器
subjectList: [], // 项目列表
gpsLocation: "", // GPS定位用在水印上 以前的datas.returnLocation已经改做他用了
departmentList: [
// {
// id: "1123123",
// name: "业务管理部",
// amount: "",
// remark: "备注",
// depIndex: 0,
// depDetailCostVoList: [
// {
// depIndex: 0,
// id: "111",
// subjectName: "",
// amount: "10002",
// remark: "ccc",
// pictureList: [],
// showSubjectPicker: false,
// attachmentList: [],
// },
// ],
// },
// {
// id: "1231232",
// depIndex: 1,
// name: "运维部",
// amount: "",
// remark: "备注",
// depDetailCostVoList: [
// {
// depIndex: 1,
// id: "45555",
// subjectName: "",
// remark: "ccc",
// amount: "10001",
// pictureList: [],
// showSubjectPicker: false,
// attachmentList: [],
// },
// ],
// },
// { id: "3", name: "能源部" },
// { id: "4", name: "财务部" },
], // 部门列表
};
},
methods: {
amountChange(value, index, k) {
console.log(value);
console.log(index);
console.log(k);
this.departmentList[k].depDetailCostVoList[index].amount = value;
let total = 0;
total = this.departmentList[k].depDetailCostVoList.reduce(
(countedamount, item) => countedamount + (Number(item.amount) || 0),
0
);
this.departmentList[k].amount = total;
},
notPassConfirm() {
uni.showModal({
title: "提示",
content: "确认驳回吗?",
success: (res) => {
if (res.confirm) {
this.notPassAudit();
}
},
});
},
//结算不通过
notPassAudit() {
let params = { ...this.datas };
params.depCostVoList = Object.assign(
params.depCostVoList,
this.departmentList
);
params.type = 2;
params.isSubmit = true;
params.pendingExpenses = this._watiBond;
params.feeAmountTotal = this._total;
this.$api.returnCar.financeCost(params).then((res) => {
if (res) {
uni.showToast({
title: "驳回成功",
icon: "success",
duration: 1500,
success() {},
});
setTimeout(() => {
uni.navigateBack();
}, 1500);
}
});
},
getCostInfo() {
this.$api.returnCar.getCostInfo({ id: this.id }).then((res) => {
this.datas = res.data;
this.departmentList =
this.datas.depCostVoList.map((item) => {
item.depDetailCostVoList = item.depDetailCostVoList.map((t) => {
t.subjectName = this.subjectList.filter(
(s) => s.id == t.costSubjectId
)[0]?.name;
t.pictureList = t.pictureList.map((p) => {
p.url = p.path;
p.thumb = p.compressedImagePath || p.path;
return p;
});
t.attachmentList = t.attachmentList.map((p) => {
p.url = p.path;
return p;
});
return t;
});
return item;
}) || [];
this.datas.earnestMoney = this.datas.earnestMoney || 0;
this.datas.isSubmit = [10, 30].includes(res.data.costApprovalStatus)
? true
: false;
this.$nextTick(() => {
this.$refs.costCollapse.init();
});
// this.parseFileListBack();
});
},
// getData() {
// this.$api.returnCar.getTakeId({ id: this.id }).then((res) => {
// res.truckRentTaskId = this.id;
// // 避免出现额外的小数,"100.00" => 100
// res.takeMileage = res.takeMileage ? Number(res.takeMileage) : null;
// res.electricity = res.electricity ? Number(res.electricity) : null;
// res.hydrogenMeasure = res.hydrogenMeasure
// ? Number(res.hydrogenMeasure)
// : null;
// this.datas = res;
// this.datas.earnestMoney = 100000;
// // this.datas.depDetailCostVoList = [
// // {
// // id: "111",
// // subjectName: "",
// // remark: "ccc",
// // pictureList: [],
// // amount: "",
// // showSubjectPicker: false,
// // attachmentList: [],
// // },
// // ];
// this.datas.hydrogenUnit = this.datas.take.hydrogenUnit; // 沿用交车单单位
// const authorizerList = res.contractAuthorizerInformationList;
// this.contractAuthorizerInformationList = authorizerList;
// // 如果授权人列表只有一个授权人,默认填入
// if (authorizerList && authorizerList.length == 1) {
// this.datas.takeName = authorizerList[0].authorizer;
// this.datas.takeIdNo = authorizerList[0].authorizerIdentityCard;
// this.datas.takePhone = authorizerList[0].authorizerTelephone;
// }
// // 根据后端相应的相关图片字段重新得到fileList用于前端图片预览
// this.parseFileListBack();
// // 自动获取用户当前位置,填入 "交车地点" 字段中
// if (!this.isRead) {
// this.getLocation();
// }
// // formDataList为深度拷贝的一个对象并不会直接影响到该车辆的交车检查单单信息
// this.formDataList = this.processFormDataList(
// this.deepClone(this.datas.dataList)
// );
// });
// },
goto(e) {
uni.navigateTo({ url: e.target.dataset.url });
},
navigateBack() {
setTimeout(() => {
uni.navigateBack();
}, 100);
},
formatDateTime(obj, type = "date") {
if (obj == null) {
return "";
}
// 精确到日
if (type == "date") {
let date = new Date(obj);
let y = 1900 + date.getYear();
let m = "0" + (date.getMonth() + 1);
let d = "0" + date.getDate();
return (
y +
"-" +
m.substring(m.length - 2, m.length) +
"-" +
d.substring(d.length - 2, d.length)
);
}
// 精确到小时
else if (type == "hour") {
const date = new Date(obj); // 将时间戳转换为毫秒
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, "0"); // 月份从0开始
const day = String(date.getDate()).padStart(2, "0");
const hour = String(date.getHours()).padStart(2, "0");
return `${year}-${month}-${day} ${hour}:00`;
}
},
getNowDateTime() {
let currentTime = new Date();
let year = currentTime.getFullYear();
let month = currentTime.getMonth() + 1;
let day = currentTime.getDate();
let hours = currentTime.getHours();
let minutes = currentTime.getMinutes();
month = month < 10 ? "0" + month : month;
day = day < 10 ? "0" + day : day;
hours = hours < 10 ? "0" + hours : hours;
minutes = minutes < 10 ? "0" + minutes : minutes;
return `${year}-${month}-${day} ${hours}:${minutes}`;
},
async getsubjectTowId() {
await this.$api.returnCar
.getQuerySubjectTowNames()
.then((res) => {
console.log("getsubject");
console.log(res);
this.subjectList = res;
})
.catch((err) => {
console.log("error");
this.subjectList = [];
});
},
// showSubjectPickerFunc(index) {
// console.log(index);
// this.$nextTick(() => {
// this.showSubjectPicker[index] = true;
// });
// },
getDicValue(dic, dicCode) {
if (dic.length == 0) {
return "";
}
return dic.find((x) => x.dicCode == dicCode)?.dicName ?? "";
},
confirmSubject(e, index, depIndex) {
console.log(e);
const selecItem = this.subjectList[Number(e.detail.value)];
console.log(index);
console.log(depIndex);
this.departmentList[depIndex].depDetailCostVoList[index].subjectName =
selecItem.name;
this.departmentList[depIndex].depDetailCostVoList[index].costSubjectId =
selecItem.id;
},
confirmIsDrivingTraining(e) {
this.datas.isDrivingTraining = e.indexs[0];
this.showIsDrivingTrainingPicker = false;
},
confirmHandoverDate(e) {
this.datas.returnDate = e.value;
this.showHandoverDatePicker = false;
},
confirmPlateNumber(e) {
const truckId = e.value[0].id;
this.$api.returnCar
.validateTruckByIds({ contractId: this.datas.id, ids: truckId })
.then((res) => {
// 该车辆已被占用
if (!res) {
return;
}
this.datas.truckSimple = { ...e.value[0], truckId };
this.datas.changeTruckId = truckId; // 指示后端换了车辆id
this.showPlateNumberPicker = false;
// 换车后更新交车检查单
this.$api.returnCar
.getFormDataTemplate({
tireNumber: this.datas.truckSimple.tireNumber,
})
.then((res) => {
this.datas.dataList = res;
this.formDataList = this.processFormDataList(
this.deepClone(this.datas.dataList)
);
});
});
},
enbalbeChangeTruck() {
this.platNumberDisabled = false;
this.showPlateNumberPicker = true;
},
getLocation() {
uni.getLocation({
type: "wgs84",
success: (res) => {
const longitude = res.longitude;
const latitude = res.latitude;
this.$api.returnCar
.getAddress({ longitude, latitude })
.then((res) => {
this.gpsLocation = res?.data ?? "浙江省嘉兴市";
});
},
fail: (res) => {
console.log(res);
},
});
},
switchTakeTruck(index) {
this.formDataList[index].returnTruck =
!this.formDataList[index].returnTruck;
},
inputQuality(value, index) {
if (
["证件信息", "工具信息"].includes(this.formDataList[index].dataCategory)
) {
if (value) {
this.formDataList[index].returnTruck = true;
} else {
this.formDataList[index].returnTruck = false;
}
}
this.formDataList[index].remark = value;
},
inputTakeTruck(value, index) {
this.formDataList[index].returnTruck = value;
},
cancelFormDataChange() {
this.formDataList = this.processFormDataList(
this.deepClone(this.datas.dataList)
);
this.checkListShow = false;
uni.setNavigationBarTitle({
title: "还车信息",
});
},
deepClone(obj) {
if (obj === null) return null;
if (typeof obj !== "object") return obj;
if (obj instanceof Date) {
let date = new Date();
date.setTime(obj.getTime());
return date;
}
if (obj instanceof RegExp) {
let re = new RegExp(obj.source);
re.lastIndex = obj.lastIndex;
return re;
}
let newObj = new obj.constructor();
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = this.deepClone(obj[key]);
}
}
return newObj;
},
processFormDataList(dataList) {
dataList = dataList.filter((x) => x.dataName != "检查项目");
for (let item of dataList) {
if (item.dataType === 3) {
// 当 dataType == 3 时,只显示非 "true"、非 "false" 和非空字符串的值
if (
item.returnTruck !== "true" &&
item.returnTruck !== "false" &&
item.returnTruck !== ""
) {
// 保留并显示该值
item.returnTruck = item.returnTruck;
} else {
// 显示空字符串
item.returnTruck = ""; // 或者 item.returnTruck = null;
}
} else if (item.dataType === 1) {
// 当 dataType == 1 时,处理 returnTruck 的值
if (item.returnTruck === "true") {
item.returnTruck = true;
} else {
item.returnTruck = false;
}
}
}
return dataList;
},
change(e) {
this.datas.hydrogenUnit = e;
},
checkCameraPermission() {
console.log("checkCameraPermission");
uni.getSetting({
success(res) {
if (!res.authSetting["scope.camera"]) {
console.log(`有相机权限`);
return;
} else {
console.log(`没有相机权限! 开始申请获取`);
this.requestCameraPermission();
}
},
fail(e) {
console.log(`获取setting失败:\n`, e);
},
});
},
withdrawal(k) {
let params = { ...this.datas };
let obj = Object.assign(params.depCostVoList[k], this.departmentList[k]);
obj.submitType = 2;
params.depCostVoList = [obj];
params.isSubmit = false;
params.pendingExpenses = this._watiBond;
params.feeAmountTotal = this._total;
this.$api.returnCar.editCostInfo(params).then((res) => {
if (res) {
uni.showToast({
title: "撤回成功",
icon: "success",
duration: 1500,
success() {},
});
this.getCostInfo();
}
});
},
addForm(depIndex) {
this.departmentList[depIndex].depDetailCostVoList.push({
subjectName: "",
costSubjectId: null,
remark: "",
amount: "",
pictureList: [],
attachmentList: [],
});
this.$nextTick(() => {
this.$refs.costCollapse.init();
});
},
delForm(index, depIndex) {
// if (this.departmentList[depIndex].depDetailCostVoList.length <= 1) {
// this.alert(`至少保留一条数据`);
// return;
// }
this.departmentList[depIndex].depDetailCostVoList.splice(index, 1);
this.$nextTick(() => {
this.$refs.costCollapse.init();
});
},
requestCameraPermission() {
uni.authorize({
scope: "scope.camera",
success() {
console.log(`相机权限授权成功`);
},
fail() {
console.log(`相机权限授权失败`);
},
});
},
// 保存备车检查单
saveFormDataList() {
if (!this.checkFormData()) {
return false;
}
this.hasSaveCheckList = true;
this.checkListShow = false;
this.datas.dataList = this.deepClone(this.formDataList);
uni.setNavigationBarTitle({
title: "还车信息",
});
},
// 检查备车检查单是否正确填写
checkFormData(alert = true) {
const targets = this.formDataList.filter(
(x) => x.dataCategory == "外观检查" && x.dataName != "其他"
);
const target = targets?.find(
(x) => (!x.returnTruck || x.returnTruck === "false") && !x.remark
);
if (target) {
alert && this.alert(`${target.dataName} 未勾选,需填写备注!`);
return false;
}
return true;
},
// 删除图片
deletePic(event) {
let parts = event.name.split("-");
const index = parts[0];
const depIndex = parts[1];
const fileList =
this.departmentList[depIndex].depDetailCostVoList[index].pictureList;
if (fileList.some((x) => x.status == "uploading")) {
this.alert(`请等待现有图片上传完成后再操作`);
return;
}
this.departmentList[depIndex].depDetailCostVoList[
index
].pictureList.splice(event.index, 1);
},
// 删除附件
deletePdf(event) {
let parts = event.name.split("-");
const index = parts[0];
const depIndex = parts[1];
const fileList =
this.departmentList[depIndex].depDetailCostVoList[index].attachmentList;
if (fileList.some((x) => x.status == "uploading")) {
this.alert(`请等待现有图片上传完成后再操作`);
return;
}
this.departmentList[depIndex].depDetailCostVoList[
index
].attachmentList.splice(event.index, 1);
},
// 新增图片
async afterRead(event) {
let parts = event.name.split("-");
const index = parts[0];
const depIndex = parts[1];
console.log(event);
console.log(index);
console.log(depIndex);
// 当设置 multiple 为 true 时, file 为数组格式,否则为对象格式
let lists = [].concat(event.file);
let fileListLen =
this.departmentList[depIndex].depDetailCostVoList[index].pictureList
.length;
lists.map((item) => {
this.departmentList[depIndex].depDetailCostVoList[
index
].pictureList.push({
...item,
status: "uploading",
message: "上传中",
});
});
console.log(`event.file:\n`, event.file);
for (let i = 0; i < lists.length; i++) {
this.loading = true;
this.loadingText = "添加水印中...";
const fileSize = event.file.size / 1024 ** 2; // 图片多少MB
let waterUrl = "";
try {
waterUrl = await this.addWatermark(lists[i].url, fileSize);
} catch (e) {
this.alert(e.toString());
this.departmentList[depIndex].depDetailCostVoList[
index
].pictureList.splice(fileListLen, 1);
return;
}
const result = await this.uploadFilePromise(waterUrl);
console.log(`result:\n`, result);
// let result = { data: { url: waterUrl }}
let item =
this.departmentList[depIndex].depDetailCostVoList[index].pictureList[
fileListLen
];
this.departmentList[depIndex].depDetailCostVoList[
index
].pictureList.splice(
fileListLen,
1,
Object.assign(item, {
status: "success",
message: "",
path: result.data?.url ?? "",
thumb: waterUrl,
url: result.data?.url ?? "",
compressedImagePath: result.data?.compressedImageUrl ?? "",
})
);
fileListLen++;
//const imgUrl = result.data?.url ?? "";
// // 司机证件
// if (event.name == "13") {
// this.datas.documents.push(imgUrl);
// }
this.$nextTick(() => {
// 解决折叠collapse高度无法动态更新的问题
this.$refs.costCollapse.init();
});
}
},
// 新增附件
async afterReadPdf(event) {
let parts = event.name.split("-");
const index = parts[0];
const depIndex = parts[1];
// 当设置 multiple 为 true 时, file 为数组格式,否则为对象格式
let lists = [].concat(event.file);
let fileListLen =
this.departmentList[depIndex].depDetailCostVoList[index].attachmentList
.length;
lists.map((item) => {
this.departmentList[depIndex].depDetailCostVoList[
index
].attachmentList.push({
...item,
status: "uploading",
message: "上传中",
});
});
//const fileSize = event.file.size / 1024 ** 2; // 图片多少MB
console.log(`event.file:\n`, event.file);
for (let i = 0; i < lists.length; i++) {
const result = await this.uploadFilePromise(lists[i].url);
// let result = { data: { url: waterUrl }}
let item =
this.departmentList[depIndex].depDetailCostVoList[index]
.attachmentList[fileListLen];
const imgUrl = result.data?.url ?? item.url ?? "";
const fileName = event.file[0]?.name ?? "";
this.departmentList[depIndex].depDetailCostVoList[
index
].attachmentList.splice(
fileListLen,
1,
Object.assign(item, {
status: "success",
message: "",
fileName: fileName,
path: imgUrl,
url: result.data?.url ?? "",
thumb: item.type === "file" ? "/static/pdf.png" : "",
})
);
fileListLen++;
console.log("fileList");
console.log(result.data);
// const imgUrl = result.data?.url ?? "";
// const fileName = event.file[0]?.name ?? "";
// this.datas.safetyTrainingAttachment.push({
// path: imgUrl,
// fileName: fileName,
// thumb: "/static/pdf.png",
// });
this.$nextTick(() => {
// 解决折叠collapse高度无法动态更新的问题
this.$refs.costCollapse.init();
});
}
},
uploadFilePromise(url) {
return new Promise((resolve, reject) => {
let a = uni.uploadFile({
url: "/attachment/upload",
filePath: url,
name: "file",
success: (res) => {
resolve(JSON.parse(res.data || {}));
},
fail: (e) => {
reject(e);
},
});
});
},
// 图片添加水印
async addWatermark(img, fileSize) {
const image = img;
let res1 = await new Promise((resolve, reject) => {
uni.getImageInfo({
src: img,
success: (res) => {
// 设置canvas宽高等于原图片宽高
this.canvasWidth = res.width;
this.canvasHeight = res.height;
// 创建 canvas 的绘图上下文
const ctx = uni.createCanvasContext("myCanvas", this);
// 绘制图片
ctx.drawImage(image, 0, 0, res.width, res.height);
//先加logo
// const watermarkImg = this.$refs.logo;
ctx.drawImage("/static/logo3.png", 10, res.height - 150, 200, 40.8);
//再加时间
ctx.font = "25px 黑体";
ctx.fillStyle = "#fff";
ctx.textAlign = "left";
ctx.fillText(this.getNowDateTime(), 10, res.height - 70);
//最后加地址
ctx.font = "25px 黑体";
ctx.fillStyle = "#fff";
ctx.textAlign = "left";
ctx.fillText(this.gpsLocation, 10, res.height - 30);
// 画到 canvas 中
ctx.draw(false, () => {
// 将画布转化为图片
// 设置延时,延时的秒数和图片体积正相关,越大的图片,延时越长
// 如果不延时,导出的图片可能存在有黑边、只显示部分 等问题
let timeout = 0;
if (fileSize <= 3) {
timeout = 1000;
} else {
timeout = 1000 * (fileSize / 3);
}
setTimeout(() => {
uni.canvasToTempFilePath(
{
canvasId: "myCanvas",
fileType: "jpg",
quality: fileSize <= 3 ? 1 : 0.75, // 如果不到3MB则不压缩否则压缩
success: (res) => {
console.log(res);
this.loading = false;
resolve(res.tempFilePath);
},
fail: (err) => {
this.loading = false;
reject(err);
},
},
this
);
}, timeout);
});
},
});
});
return res1;
},
// 保存
save() {
let params = { ...this.datas };
params.depCostVoList = Object.assign(
params.depCostVoList,
this.departmentList
);
// params.submitType = 1;
params.isSubmit = false;
params.pendingExpenses = this._watiBond;
params.feeAmountTotal = this._total;
this.$api.returnCar.editCostInfo(params).then((res) => {
if (res) {
uni.showToast({
title: "保存成功",
icon: "success",
duration: 1500,
success() {},
});
setTimeout(() => {
uni.navigateBack();
}, 1500);
}
});
},
submitConfirm() {
uni.showModal({
title: "提示",
content: "确认提交?",
success: (res) => {
if (res.confirm) {
this.submit();
}
},
});
},
costConfirm() {
uni.showModal({
title: "提示",
content: "确认结算?",
success: (res) => {
if (res.confirm) {
this.costFunc();
}
},
});
},
//费用结算-财务负责人
costFunc() {
let params = { ...this.datas };
params.depCostVoList = Object.assign(
params.depCostVoList,
this.departmentList
);
params.type = 1;
params.isSubmit = true;
params.pendingExpenses = this._watiBond;
params.feeAmountTotal = this._total;
this.$api.returnCar.financeCost(params).then((res) => {
if (res) {
uni.showToast({
title: "结算成功",
icon: "success",
duration: 1500,
success() {},
});
setTimeout(() => {
uni.navigateBack();
}, 1500);
}
});
},
commitConfirm(k) {
const _this = this;
uni.showModal({
title: "提示",
content: "确认提交吗?",
success: (res) => {
if (res.confirm) {
_this.commit(k);
}
},
});
},
commit(k) {
let params = { ...this.datas };
let obj = Object.assign(params.depCostVoList[k], this.departmentList[k]);
obj.submitType = 1;
params.depCostVoList = [obj];
params.isSubmit = false;
params.pendingExpenses = this._watiBond;
params.feeAmountTotal = this._total;
this.$api.returnCar.editCostInfo(params).then((res) => {
if (res) {
uni.showToast({
title: "提交成功",
icon: "success",
duration: 1500,
success() {},
});
this.getCostInfo();
}
});
},
submit() {
if (
this.departmentList?.filter((item) => item.costStatus == 0).length > 0
) {
uni.showToast({
title: "请先确认各部门费用已提交",
duration: 1500,
icon: "none",
});
return;
}
let params = { ...this.datas };
params.depCostVoList = Object.assign(
params.depCostVoList,
this.departmentList
);
params.submitType = 1;
params.isSubmit = true;
params.pendingExpenses = this._watiBond;
params.feeAmountTotal = this._total;
this.$api.returnCar.editCostInfo(params).then((res) => {
if (res) {
uni.showToast({
title: "提交成功",
icon: "success",
duration: 1500,
success() {},
});
setTimeout(() => {
uni.navigateBack();
}, 1500);
}
});
},
// 在提交前检查,是否有必填字段未填写
check() {
if (!this.datas.leftRearPic) {
this.alert("请上传左后方照片");
return false;
}
if (!this.datas.rightRearPic) {
this.alert("请上传右后方照片");
return false;
}
if (!this.datas.tirePic || this.datas.tirePic.length == 0) {
this.alert("请上传轮胎照片");
return false;
}
if (this.datas.tirePic.length < this.datas.take.truckSimple.tireNumber) {
this.alert("轮胎照片上传数量不小于车辆轮胎数量");
return false;
}
return true;
},
alert(msg) {
uni.showToast({
title: msg,
icon: "none",
duration: 1500,
});
},
// 预览附件
previewYyPdf(data) {
if (!data || !data.path) {
this.alert(`文件上传异常`);
return;
}
console.log(data);
const path = data.path;
this.loading = true;
this.loadingText = "加载中...";
const that = this;
uni.downloadFile({
url: path,
success: function (res) {
var filePath = res.tempFilePath;
that.loading = false;
uni.openDocument({
filePath: filePath,
success: function (res) {
that.loading = false;
},
fail() {
that.loading = false;
},
});
},
fail() {
that.alert("预览文件失败");
that.loading = false;
},
});
},
// 提交给生成签署文档接口的参数,其中的图片全部替换为缩略图
},
computed: {
// 大部分组件的禁用直接用 disabled查看模式或者已完成签署
disabled() {
return this.isRead;
},
// _bill() {
// let total = 0;
// total = this.departmentList[0].depDetailCostVoList.reduce(
// (countedamount, item) => countedamount + (Number(item.amount) || 0),
// 0
// );
// console.log(total);
// return total;
// },
_watiBond() {
console.log("------------------");
let total = 0;
this.departmentList.forEach((t) => {
let amount = 0;
console.log(t.depDetailCostVoList);
amount =
t.depDetailCostVoList?.reduce(
(amount, item) => amount + (Number(item.amount) || 0),
0
) || 0;
console.log(amount);
total = total + amount;
});
console.log(total);
return total;
},
_total() {
console.log("this.datas.earnestMoney", this.datas.earnestMoney);
console.log(this._watiBond);
console.log(this.datas.earnestMoney - this._watiBond);
return this.datas.earnestMoney - this._watiBond;
},
isFinanceRole() {
//const ids = this.userInfo?.roles?.map((item) => item.id) || [];
if (this.userInfo.depCode === "02") {
console.log("财务部");
return true; //财务部
} else {
return false; //其他
}
},
isBussinessRole() {
console.log(this.userInfo);
if (this.userInfo.depCode === "0501") {
console.log("业务服务组-业务助理");
return true; //业务服务组-业务助理
} else {
return false; //其他
}
// const ids = this.userInfo?.roles?.map((item) => item.id) || [];
// if (ids.includes("1066262176854999040")) {
},
},
async onLoad(options) {
if (options.id) {
this.id = options.id;
}
// uni.enableAlertBeforeUnload({
// message: "签署文件已",
// success: function (res) {
// console.log("成功:", res);
// },
// fail: function (err) {
// console.log("失败:", err);
// },
// });
if (options.isRead) {
this.isRead = Number(options.isRead);
}
console.log(this.isRead);
console.log(!!this.isRead);
// this.$nextTick(() => {
// console.log(this.isBussinessRole);
// if (!this.isBussinessRole) {
// this.departmentList.splice(1, 3);
// }
// });
this.userInfo = getUser() || {};
this.checkCameraPermission(); // 检测拍照权限
await this.getsubjectTowId();
//this.getData();
this.getCostInfo();
if (!this.isRead) {
this.getLocation();
}
},
onPullDownRefresh() {
// this.getData()
uni.stopPullDownRefresh(); //刷新数据之后停止刷新效果
},
onShow() {
if (this.loadingText != "添加水印中...") {
this.loading = false;
}
},
onHide() {},
destroyed() {},
};
</script>
<!-- <style>
page {
position: relative !important;
top: 0px !important;
}
</style> -->
<style lang="less" scoped>
.container {
// background-color: #d7d7d7;
padding: 30rpx;
.line {
display: flex;
align-items: center;
margin-bottom: 15rpx;
font-size: 14px;
.left {
margin-right: 50rpx;
width: 300rpx;
}
.text-small {
font-size: x-small;
}
.text-normal {
font-size: small;
}
}
.truckItem {
margin-top: 30rpx;
padding: 30rpx;
border: #7ba746 solid 4rpx;
}
.demo-layout {
display: flex;
.title {
text-align: center;
}
}
.depDetailCostVoListBtns {
display: flex;
justify-content: flex-end;
align-items: center;
button {
background-color: transparent;
font-size: 26rpx;
width: 100rpx;
height: 50rpx;
line-height: 50rpx;
margin-left: 30rpx;
margin-right: 0;
padding: 0;
&.add {
background-color: #7ba746;
color: white;
}
&.del {
background-color: white;
color: #7ba746;
border: 1rpx #7ba746 solid;
}
&.disabled {
opacity: 0.6;
}
}
}
.btns {
display: flex;
align-items: center;
justify-content: space-around;
margin-top: 20rpx;
button {
width: 200rpx;
height: 60rpx;
font-size: 26rpx;
line-height: 26rpx;
padding: 17rpx 0;
text-align: center;
}
.cancel {
background-color: white;
color: #7ba746;
border: 1rpx #7ba746 solid;
}
.save {
background-color: #7ba746;
color: white;
}
.done {
background-color: #7ba746;
color: white;
}
.disabled {
opacity: 0.6;
}
}
.item {
margin-top: 30rpx;
.title {
font-size: 26rpx;
margin-bottom: 15rpx;
&.required::before {
content: "*";
color: red;
margin-right: 3rpx;
}
}
.title.isRed {
color: #f00909;
}
.title.isGreen {
color: #017143;
}
.input {
width: 100%;
height: 60rpx;
font-size: 26rpx;
line-height: 26rpx;
padding: 17rpx 0;
border-bottom: 1rpx solid #e5e5e5;
}
.tip {
font-size: 26rpx;
margin-bottom: 15rpx;
color: #aaaaaa;
position: relative;
}
.btn.checkList {
width: 200rpx;
height: 60rpx;
font-size: 26rpx;
line-height: 26rpx;
padding: 17rpx 0;
text-align: center;
background-color: #7ba746;
color: white;
margin-left: 0;
&.required::before {
content: "*";
color: red;
margin-right: 3rpx;
}
}
.unit {
font-size: 26rpx;
}
.btn {
width: 200rpx;
height: 80rpx;
margin-left: 0;
font-size: 26rpx;
line-height: 26rpx;
padding: 27rpx 0;
text-align: center;
color: white;
&.sign {
background-color: #7ba746;
}
&.genDocument {
background-color: #1e98d7;
}
&.disabled {
opacity: 0.6;
}
}
}
.btns {
display: flex;
align-items: center;
justify-content: space-around;
margin-top: 20rpx;
button {
width: 200rpx;
height: 60rpx;
font-size: 26rpx;
line-height: 26rpx;
padding: 17rpx 0;
text-align: center;
}
.cancel {
background-color: white;
color: #7ba746;
border: 1rpx #7ba746 solid;
}
.save {
background-color: #7ba746;
color: white;
}
.done {
background-color: #7ba746;
color: white;
}
.disabled {
opacity: 0.6;
}
}
}
/deep/ .twoBtn button:first-child {
margin-bottom: 5px;
}
/deep/ .u-textarea textarea {
min-height: 100rpx !important;
font-size: 26rpx !important;
}
/deep/ .u-border {
border-width: 1rpx !important;
border-color: gray !important;
border-style: solid;
}
/deep/ .u-collapse-item__content__text {
padding: unset !important;
color: unset !important;
font-size: unset !important;
}
/deep/ .u-cell__title-text {
font-size: unset !important;
line-height: unset !important;
color: unset !important;
}
/deep/ .u-cell__body {
padding: unset !important;
font-size: unset !important;
color: unset !important;
}
/deep/ .u-cell__right-icon-wrap text {
font-size: 32rpx !important;
}
/deep/ .u-cell--clickable {
background-color: unset !important;
}
/deep/ .u-collapse-item {
margin-bottom: 30rpx;
}
/deep/ .uni-select {
width: 100rpx !important;
}
/deep/ .u-upload__button text {
font-size: 48rpx !important;
}
/deep/ .u-upload__deletable {
height: 42rpx !important;
width: 42rpx !important;
}
/deep/ .u-upload__deletable text {
font-size: 32rpx !important;
line-height: 32rpx !important;
}
/deep/ picker-view {
height: 450rpx !important;
}
/deep/ .uni-select__input-text {
font-size: 26rpx !important;
text-align: right !important;
}
/deep/ .uni-select__selector-item text {
font-size: 26rpx !important;
}
/deep/ .uni-select {
padding-right: 18rpx !important;
border-width: 1rpx !important;
border-color: gray !important;
border-style: solid !important;
border-top-width: 0 !important;
border-right-width: 0 !important;
border-bottom-width: 0 !important;
}
/deep/ picker-view picker-view-column:nth-of-type(5) {
display: none;
}
.changeCarBtn {
height: 76rpx;
font-size: 26rpx;
line-height: 76rpx;
border-width: 1rpx !important;
border-color: gray !important;
border-style: solid !important;
border-top-width: 0 !important;
border-right-width: 0 !important;
border-bottom-width: 0 !important;
}
/* 检查单样式开始 */
/deep/ .td_wrap {
height: auto !important;
}
/deep/ checkbox-group view.td {
width: 186rpx !important;
}
/deep/ checkbox-group view.td_wrap {
width: 186rpx !important;
}
/deep/ .no-bad-table-wrap .td.rowspan {
display: flex;
align-items: center;
justify-content: center;
}
/deep/ .div-table-head .thead .tr view {
width: 186rpx !important;
}
/deep/ no-bad-table {
overflow-x: hidden;
}
/deep/ .no-bad-table-wrap .thead .tr .td {
background-color: #7ba746;
color: white;
}
/deep/ .no-bad-table-wrap .thead .tr .td .td_wrap {
background-color: #7ba746;
color: white;
}
/* 检查单样式结束 */
/* loading 置于顶层 */
/deep/ .u-fade-enter-to.u-fade-enter-active {
z-index: 10074 !important;
}
</style>