| | |
| | | clearable |
| | | style="width: 100%" |
| | | v-model="form.createTime" |
| | | type="date" |
| | | type="date" format="yyyy-MM-dd" |
| | | value-format="yyyy-MM-dd HH:mm:ss" |
| | | placeholder="申请日期" |
| | | > |
| | |
| | | |
| | | <!-- |
| | | <el-col :span="5"> |
| | | <el-form-item label="应缴税" prop="taxcost" v-if="businessType == '1' || businessType == '2'"> |
| | | <el-input v-model="form.taxcost" placeholder="应缴税金额合计" :disabled="true" /> |
| | | <el-form-item label="劳务个税" prop="taxcost" v-if="businessType == '1' || businessType == '2'"> |
| | | <el-input v-model="form.taxcost" placeholder="劳务个税合计" :disabled="true" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="5"> |
| | | <el-form-item label="税后金额" prop="pretaxcost"> |
| | | <el-input v-model="form.taxedcost" placeholder="税后金额合计" :disabled="true" /> |
| | | <el-form-item label="劳务税后" prop="pretaxcost"> |
| | | <el-input v-model="form.taxedcost" placeholder="劳务税后合计" :disabled="true" /> |
| | | </el-form-item> |
| | | </el-col>--> |
| | | <el-col :span="10"> |
| | |
| | | <el-table-column |
| | | prop="taxedamount" |
| | | align="center" |
| | | label="税后金额" |
| | | label="劳务税后" |
| | | width="120" |
| | | v-if=" |
| | | (this.ismanager == true) & |
| | |
| | | <template slot-scope="scope"> |
| | | <el-input |
| | | v-model="scope.row.taxedamount" |
| | | placeholder="税后金额" |
| | | placeholder="劳务税后" |
| | | @blur=" |
| | | val => { |
| | | calculateTax(scope.row, 'B'); |
| | |
| | | :close-on-click-modal="false" |
| | | :title="pdftitle" |
| | | :visible.sync="pdfVisible" |
| | | :fullscreen="pdfFullscreen" |
| | | width="60%" |
| | | custom-class="pdf-resize-dialog" |
| | | @closed="pdfFullscreen = false" |
| | | > |
| | | <template slot="title"> |
| | | <span>{{ pdftitle }}</span> |
| | | <el-button |
| | | class="pdf-fullscreen-btn" |
| | | size="mini" |
| | | :icon="pdfFullscreen ? 'el-icon-close' : 'el-icon-full-screen'" |
| | | @click="pdfFullscreen = !pdfFullscreen" |
| | | >{{ pdfFullscreen ? "还原" : "全屏" }}</el-button |
| | | > |
| | | </template> |
| | | <div class="pdfimg"> |
| | | <div class="box-pdf"> |
| | | <div> |
| | |
| | | </div> --> |
| | | </div> |
| | | |
| | | <div v-if="this.previewpdf" class="pdfimgmin"> |
| | | <!-- <img :src="pdfimg" /> --> |
| | | <el-image |
| | | style="width: 95%; height: 90%" |
| | | :src="pdfimg" |
| | | :preview-src-list="pdfimgsrcList" |
| | | > |
| | | </el-image> |
| | | </div> |
| | | <div v-else class="pdfimgmins">{{ hintitle }}</div> |
| | | <attachment-preview-pane :file="embeddedFile" style="flex: 1; min-width: 0;" /> |
| | | </div> |
| | | </el-dialog> |
| | | <el-dialog title="提示" :visible.sync="Savereminder" width="30%"> |
| | |
| | | import OrgSelecter from "@/views/project/components/orgselect"; |
| | | import { getToken } from "@/utils/auth"; |
| | | import { moneySum, moneyAdd, moneySub, moneyMul, moneyRound } from "@/utils/money"; |
| | | import { checkFileName, checkDetails } from "@/utils/fileNameCheck"; |
| | | |
| | | export default { |
| | | //import引入的组件需要注入到对象中才能使用 |
| | |
| | | }, |
| | | // 获取请求头 |
| | | Getnetworkheader() { |
| | | let string = window.location.href; |
| | | if (string.includes("9091")) { |
| | | const index = string.indexOf("9091"); |
| | | this.Networkheader = string.slice(0, index + 4); // 截取9091及其前部字符 |
| | | // console.log(this.Networkheader); |
| | | } else { |
| | | const index = string.indexOf("8032"); |
| | | this.Networkheader = string.slice(0, index + 4); // 截取8032及其前部字符 |
| | | } |
| | | // 以当前页面 origin 为准,兼容 80/8032/9091 及后续端口调整 |
| | | this.Networkheader = window.location.origin; |
| | | }, |
| | | /** 通过参数获取业务类型 */ |
| | | getroute() { |
| | |
| | | }, |
| | | /** 提交按钮 */ |
| | | submitForm: debounce(function() { |
| | | // 2026-10-15:保存前附件文件名规范校验(仅新增单据;老单据的历史附件由后端按"只校验本次变更"放行) |
| | | if (!this.checkDetailFileNames()) { |
| | | return; |
| | | } |
| | | |
| | | if (!this.randomnumber) { |
| | | this.randomnumber = this.generateRandomString(9); |
| | | this.form.randomnumber = this.randomnumber; |
| | |
| | | //获取参数 |
| | | this.taxParam.beneficiaryNo = tempDetail.beneficiaryno; |
| | | this.taxParam.startTime = this.form.createTime.substring(0, 10); |
| | | // 计算税后金额 |
| | | // 计算劳务税后 |
| | | if (tempDetail.taxedamount == undefined || tempDetail.taxedamount == null || tempDetail.taxedamount == 0 || tempDetail.taxedamount == '') { |
| | | //获取参数 |
| | | this.taxParam.money = tempDetail.amount.toString(); |
| | |
| | | }); |
| | | } |
| | | |
| | | // 计算税前、税费、税后金额 |
| | | // 计算税前、税费、劳务税后 |
| | | if (tempDetail.amount == undefined || tempDetail.amount == null || tempDetail.amount == 0 || tempDetail.amount == '') { |
| | | //获取参数 |
| | | this.taxParam.money = tempDetail.taxedamount.toString(); |
| | |
| | | } |
| | | */ |
| | | } |
| | | //计算当前行报销内容费用合计,税前金额(amount)、扣税金额(taxamount)、税后金额(taxedamount) |
| | | //计算当前行报销内容费用合计,税前金额(amount)、劳务个税(taxamount)、劳务税后(taxedamount) |
| | | if (this.businessType == "2") { |
| | | for (let j = 0; j < this.rbDetails.length; j++) { |
| | | let tempDetail = this.rbDetails[j]; |
| | |
| | | this.$store.dispatch("tagsView/delView", this.$route); |
| | | this.$router.go(-1); |
| | | } else { |
| | | if (res.msg) { |
| | | this.$modal.msgError("操作失误"); |
| | | } else { |
| | | this.$modal.msgError(res.msg); |
| | | } |
| | | this.$modal.msgError(res.msg || "操作失败"); |
| | | } |
| | | }); |
| | | }, |
| | |
| | | row.taxamount = 0.0; |
| | | row.taxedamount = 0.0; |
| | | |
| | | //计算税后金额 |
| | | //计算劳务税后 |
| | | // this.calculateTax(row, "A"); |
| | | } |
| | | |
| | |
| | | }); |
| | | }, |
| | | |
| | | //计算个税:type(A:已知税前金额,计算税后金额;B:已知税后金额,计算税前金额) |
| | | //计算个税:type(A:已知税前金额,计算劳务税后;B:已知劳务税后,计算税前金额) |
| | | calculateTax(row, type) { |
| | | //if (isNaN(parseFloat(tempDetail.taxedamount))) |
| | | //获取参数 |
| | |
| | | this.taxParam.startTime = this.form.createTime.substring(0, 10); |
| | | |
| | | if (type == "A") { |
| | | // 计算个税、税后金额 |
| | | // 计算个税、劳务税后 |
| | | this.taxParam.money = row.amount.toString(); |
| | | getTaxByBeneFiciaryNo(this.taxParam).then(res => { |
| | | if (res.code == 200) { |
| | |
| | | }, |
| | | // 接受提醒立刻保存 |
| | | Savenow() { |
| | | // 2026-10-15:保存前附件文件名规范校验(仅新增单据;老单据的历史附件由后端按"只校验本次变更"放行) |
| | | if (!this.checkDetailFileNames()) { |
| | | return; |
| | | } |
| | | |
| | | if (!this.randomnumber) { |
| | | this.randomnumber = this.generateRandomString(9); |
| | | this.form.randomnumber = this.randomnumber; |
| | |
| | | //获取参数 |
| | | this.taxParam.beneficiaryNo = tempDetail.beneficiaryno; |
| | | this.taxParam.startTime = this.form.createTime.substring(0, 10); |
| | | // 计算税后金额 |
| | | // 计算劳务税后 |
| | | if (tempDetail.taxedamount == undefined || tempDetail.taxedamount == null || tempDetail.taxedamount == 0 || tempDetail.taxedamount == '') { |
| | | //获取参数 |
| | | this.taxParam.money = tempDetail.amount.toString(); |
| | |
| | | }); |
| | | } |
| | | |
| | | // 计算税前、税费、税后金额 |
| | | // 计算税前、税费、劳务税后 |
| | | if (tempDetail.amount == undefined || tempDetail.amount == null || tempDetail.amount == 0 || tempDetail.amount == '') { |
| | | //获取参数 |
| | | this.taxParam.money = tempDetail.taxedamount.toString(); |
| | |
| | | } |
| | | */ |
| | | } |
| | | //计算当前行报销内容费用合计,税前金额(amount)、扣税金额(taxamount)、税后金额(taxedamount) |
| | | //计算当前行报销内容费用合计,税前金额(amount)、劳务个税(taxamount)、劳务税后(taxedamount) |
| | | if (this.businessType == "2") { |
| | | for (let j = 0; j < this.rbDetails.length; j++) { |
| | | let tempDetail = this.rbDetails[j]; |
| | |
| | | // console.log(response.msg); |
| | | // } |
| | | // }, |
| | | /** |
| | | * 2026-10-15:上传时校验附件文件名(业务要求:不合格立即提示且不加入列表)。 |
| | | * 规则与后端 AttachmentNameValidator 同口径:不强制含中文 / 去掉扩展名后主干 ≤20 字 / |
| | | * 不含空格及 / \ : * ? " < > | # % 等特殊字符。 |
| | | */ |
| | | checkUploadFileName(file) { |
| | | const raw = file && file.raw ? file.raw.name : file && file.name; |
| | | const r = checkFileName(raw); |
| | | if (!r.ok) { |
| | | this.$modal.msgError(r.msg); |
| | | return false; |
| | | } |
| | | return true; |
| | | }, |
| | | |
| | | /** |
| | | * 2026-10-15:保存前校验整单明细附件文件名(含同一行内重名)。 |
| | | * 口径(业务确认):只校验"本次变更"的附件——老单据里已存在的不合规附件名不能把保存卡死 |
| | | * (否则老单据改一个金额都存不进去)。后端按 id 读旧记录放行历史附件;前端拿不到"哪些是历史" |
| | | * 的权威信息,因此**仅新增单据**做保存前拦截,编辑老单据时新增的不合规附件由后端二次校验拦下。 |
| | | */ |
| | | checkDetailFileNames() { |
| | | if (this.form && this.form.id) { |
| | | return true; |
| | | } |
| | | const c = checkDetails(this.rbDetails); |
| | | if (!c.ok) { |
| | | this.$modal.msgError(c.msg); |
| | | return false; |
| | | } |
| | | return true; |
| | | }, |
| | | |
| | | uploadSccess(response, file, fileList) { |
| | | if (!this.checkUploadFileName(file)) { |
| | | return; |
| | | } |
| | | this.rbDetails; |
| | | |
| | | //获取票据信息位置 |
| | |
| | | this.fileListto.push({ name: file.name, url: response.fileName }); |
| | | // this.fileListto.push({ name: file.name, url: response.url }); |
| | | this.pdfimgsrcList.push( |
| | | this.Networkheader + "/prod-api" + response.fileName |
| | | this.Networkheader + process.env.VUE_APP_BASE_API + response.fileName |
| | | ); |
| | | this.pdfimg = this.Networkheader + "/prod-api" + response.fileName; |
| | | this.pdfimg = this.Networkheader + process.env.VUE_APP_BASE_API + response.fileName; |
| | | const localUrl = URL.createObjectURL(file.raw); |
| | | this.embeddedFile = { |
| | | name: file.name, |
| | | url: localUrl, |
| | | type: /\.pdf$/i.test(file.name) ? "pdf" : "image" |
| | | }; |
| | | |
| | | this.rbDetails[this.atpresent].annexfilesList = this.fileListto; |
| | | } else { |
| | |
| | | if (this.rbDetails[index].annexfilesList) { |
| | | this.previewpdf = true; |
| | | this.fileListto = this.rbDetails[index].annexfilesList; |
| | | this.pdfimg = this.Networkheader + "/prod-api" + this.fileListto[0].url; |
| | | this.pdfimg = this.Networkheader + process.env.VUE_APP_BASE_API + this.fileListto[0].url; |
| | | // this.pdfimg = this.fileListto[0].url; |
| | | this.pdfimgsrcList = []; |
| | | this.fileListto.forEach(item => { |
| | | this.pdfimgsrcList.push(this.Networkheader + "/prod-api" + item.url); |
| | | this.pdfimgsrcList.push(this.Networkheader + process.env.VUE_APP_BASE_API + item.url); |
| | | }); |
| | | console.log(this.pdfimgsrcList); |
| | | console.log(this.pdfimg); |
| | |
| | | } |
| | | }, |
| | | |
| | | // 点击已上传文件 |
| | | // 点击已上传文件:在附件弹窗右侧内嵌预览 |
| | | downFile(item) { |
| | | console.log(item); |
| | | this.pdftitle = item.name; |
| | | let name = item.name.split("."); |
| | | if (name[1] == "pdf") { |
| | | this.$modal.msgWarning("当前文件暂不支持预览"); |
| | | this.previewpdf = false; |
| | | this.hintitle = "当前文件暂不支持预览"; |
| | | } else if (name[1] == "jpg" || "png") { |
| | | this.previewpdf = true; |
| | | if (item.url) { |
| | | this.pdfimg = this.Networkheader + "/prod-api" + item.url; |
| | | |
| | | // if (!this.pdfimgsrcList.includes(this.pdfimg)) { |
| | | // this.pdfimgsrcList.push(this.pdfimg); |
| | | // console.log("加入"); |
| | | // } |
| | | console.log(this.pdfimg); |
| | | console.log(this.pdfimgsrcList, "imglist"); |
| | | } else { |
| | | this.pdfimg = this.Networkheader + "/prod-api" + item.url; |
| | | } |
| | | } else { |
| | | this.hintitle = "当前文件暂不支持预览"; |
| | | this.$modal.msgWarning("当前文件暂不支持预览"); |
| | | this.previewpdf = false; |
| | | if (this.operationType == "detail") { |
| | | const list = (this.fileListto || []).map(f => ({ |
| | | name: f.name, |
| | | url: f.url |
| | | })); |
| | | const index = list.findIndex(f => f.url === item.url); |
| | | this.$previewFile(list, index > -1 ? index : 0); |
| | | return; |
| | | } |
| | | const ext = String(item.name || "").toLowerCase().split(".").pop(); |
| | | const isImage = ["jpg", "jpeg", "png", "gif", "bmp", "webp"].includes(ext); |
| | | if (ext !== "pdf" && !isImage) { |
| | | this.hintitle = "当前文件暂不支持预览"; |
| | | this.$modal.msgWarning("当前文件暂不支持预览"); |
| | | return; |
| | | } |
| | | this.embeddedFile = { |
| | | name: item.name, |
| | | url: item.url, |
| | | type: ext === "pdf" ? "pdf" : "image" |
| | | }; |
| | | this.pdftitle = item.name; |
| | | this.pdfVisible = true; |
| | | }, |
| | | getIndexInArray(arr, obj) { |
| | | return arr.indexOf(obj); |
| | |
| | | console.log(row); |
| | | const indexlist = this.getIndexInArray( |
| | | this.pdfimgsrcList, |
| | | this.Networkheader + "/prod-api" + row.url |
| | | this.Networkheader + process.env.VUE_APP_BASE_API + row.url |
| | | ); |
| | | console.log(indexlist); |
| | | this.pdfimgsrcList.splice(indexlist, 1); |