| | |
| | | </el-tab-pane> |
| | | <el-tab-pane label="发票文件" :name="2"> |
| | | <div class="pdfimg"> |
| | | <div class="box-pdf"> |
| | | <div class="box-pdf box-pdf--invoice"> |
| | | <div> |
| | | <div class="invoice-select-bar"> |
| | | <el-button type="primary" size="mini" icon="el-icon-plus" |
| | | :disabled="operationType == 'detail'" @click="openInvoiceSelect">引用发票</el-button> |
| | | <span class="invoice-select-bar__tip">引用后自动标记为已报销,删除后恢复未报销</span> |
| | | </div> |
| | | <el-upload size="mini" class="upload-demo" :action="uploadFileUrl" :file-list="invoicefileList" |
| | | :show-file-list="false" multiple drag :headers="headers" :on-success="(response, file, fileList) => |
| | | uploadSccess(response, file, fileList) |
| | |
| | | </div> |
| | | </el-upload> |
| | | <el-table :data="invoicefileListto" @row-click="downFile" style="width: 100%" height="400"> |
| | | <el-table-column prop="name" :show-overflow-tooltip="true" label="名称"> |
| | | <el-table-column prop="name" :show-overflow-tooltip="true" label="文件名称"> |
| | | <template slot-scope="scope"> |
| | | <i style="color:#409EFF" class=" el-icon-s-order" />{{ |
| | | scope.row.name |
| | | }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="invoiceType" width="90" align="center" :show-overflow-tooltip="true" |
| | | label="发票类型"> |
| | | <template slot-scope="scope"> |
| | | {{ scope.row.invoiceType || "-" }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="invoiceName" width="120" :show-overflow-tooltip="true" label="发票名称"> |
| | | <template slot-scope="scope"> |
| | | {{ scope.row.invoiceName || "-" }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="invoiceAmount" width="95" align="center" label="发票金额"> |
| | | <template slot-scope="scope"> |
| | | {{ scope.row.invoiceAmount || "-" }} |
| | | </template> |
| | | </el-table-column> |
| | | |
| | | <el-table-column prop="name" width="180" :show-overflow-tooltip="true" label="功能"> |
| | | <el-table-column prop="name" width="140" :show-overflow-tooltip="true" label="功能"> |
| | | <template slot-scope="scope"> |
| | | <el-button type="primary" size="mini" |
| | | @click.native.prevent.stop="deletedowfile(scope.row)">删除</el-button> |
| | |
| | | </div> |
| | | </el-tab-pane> |
| | | </el-tabs> |
| | | </el-dialog> |
| | | <el-dialog title="选择发票" :visible.sync="invoiceSelectOpen" width="1100px" append-to-body |
| | | :fullscreen="isMobile" :close-on-click-modal="false"> |
| | | <invoice-index v-if="invoiceSelectOpen" select-mode @confirm="handleInvoiceSelected" |
| | | @cancel="invoiceSelectOpen = false" /> |
| | | </el-dialog> |
| | | <el-dialog title="提示" :visible.sync="Savereminder" width="30%"> |
| | | <el-alert :title="'您已添加' + |
| | |
| | | import { treeselect } from "@/api/system/dept"; |
| | | import { getSubsidy } from "@/api/project/travelcity"; |
| | | import { listReportname, listUser } from "@/api/project/organization"; |
| | | import { updateInvoice } from "@/api/project/invoice"; |
| | | import InvoiceIndex from "@/views/project/invoice/index.vue"; |
| | | import { getToken } from "@/utils/auth"; |
| | | import debounce from "lodash/debounce"; |
| | | import { moneySum, moneyAdd, moneyRound } from "@/utils/money"; |
| | | import { moneySum, moneyAdd, moneySub, moneyRound } from "@/utils/money"; |
| | | import { checkFileName, checkDetails } from "@/utils/fileNameCheck"; |
| | | export default { |
| | | components: { |
| | | Treeselect, |
| | | Li_area_select, |
| | | CustomImageViewer, |
| | | InvoiceIndex, |
| | | pdf |
| | | }, |
| | | name: "Funddetail", |
| | |
| | | initialIndex: 0, // 初始索引 |
| | | viewerVisible: false, // 控制预览组件显示 |
| | | invoiceviewerVisible: false, // 控制预览组件显示 |
| | | // 发票管理引用弹窗 |
| | | invoiceSelectOpen: false, |
| | | invoiceSelecting: false, |
| | | |
| | | //人员类别 |
| | | persontype: null, |
| | |
| | | //保存按钮控制 |
| | | idisabled: false |
| | | }; |
| | | }, |
| | | |
| | | computed: { |
| | | isMobile() { |
| | | return this.$store.state.app.device === "mobile"; |
| | | } |
| | | }, |
| | | |
| | | created() { |
| | |
| | | console.log("图片加载成功"); |
| | | }, |
| | | handleUploadError() { }, |
| | | // 打开发票管理引用弹窗(多选未报销发票) |
| | | openInvoiceSelect() { |
| | | if (this.operationType == "detail") { |
| | | return; |
| | | } |
| | | if (!this.rbDetails[this.atpresent]) { |
| | | this.$modal.msgWarning("请先选择费用明细行"); |
| | | return; |
| | | } |
| | | this.invoiceSelectOpen = true; |
| | | }, |
| | | // 引用发票:写入当前明细的发票集合,并把发票标记为已报销 |
| | | handleInvoiceSelected(rows) { |
| | | if (this.invoiceSelecting) { |
| | | return; |
| | | } |
| | | const detail = this.rbDetails[this.atpresent]; |
| | | if (!detail) { |
| | | this.$modal.msgWarning("请先选择费用明细行"); |
| | | return; |
| | | } |
| | | const existed = (detail.invoicefilesList || []) |
| | | .map(item => item && item.invoiceId) |
| | | .filter(id => id !== null && id !== undefined && id !== "") |
| | | .map(id => String(id)); |
| | | const selected = (rows || []).filter( |
| | | row => !existed.includes(String(row.id)) |
| | | ); |
| | | if (!selected.length) { |
| | | this.$modal.msgWarning("所选发票已引用,请勿重复添加"); |
| | | return; |
| | | } |
| | | this.invoiceSelecting = true; |
| | | Promise.all( |
| | | selected.map(row => |
| | | updateInvoice({ id: row.id, reimburseState: "1" }) |
| | | ) |
| | | ) |
| | | .then(() => { |
| | | if (!detail.invoicefilesList) { |
| | | this.$set(detail, "invoicefilesList", []); |
| | | } |
| | | selected.forEach(row => { |
| | | const file = this.buildInvoiceFile(row); |
| | | // 按发票类型把金额计入对应费用科目 |
| | | const applied = this.applyInvoiceExpense(detail, file, 1); |
| | | // 记录实际计入金额,负数发票被0截断时删除不会反向增加 |
| | | file.expenseAmount = moneyRound(applied).toFixed(2); |
| | | // 明细内保存服务端地址,列表内保存同一份数据供展示/删除 |
| | | detail.invoicefilesList.push(Object.assign({}, file)); |
| | | this.invoicefileListto.push(file); |
| | | }); |
| | | this.sumRowFee(detail); |
| | | this.invoicepdfimgsrcList = this.invoicefileListto.map( |
| | | item => item.url |
| | | ); |
| | | this.pdftitle = "共" + this.invoicefileListto.length + "项"; |
| | | this.invoiceSelectOpen = false; |
| | | this.$modal.msgSuccess( |
| | | "已引用 " + selected.length + " 张发票,费用已按类型计入" |
| | | ); |
| | | }) |
| | | .catch(() => { |
| | | this.$modal.msgError("发票标记已报销失败,请稍后重试"); |
| | | }) |
| | | .finally(() => { |
| | | this.invoiceSelecting = false; |
| | | }); |
| | | }, |
| | | // 发票管理记录 -> 发票附件(保留发票业务字段,随明细一起保存) |
| | | buildInvoiceFile(row) { |
| | | const fileUrl = this.toRelativeFileUrl(row.invoiceUrl); |
| | | const ext = this.getFileExt(fileUrl); |
| | | return { |
| | | name: this.buildInvoiceFileName(row, ext), |
| | | url: fileUrl, |
| | | invoiceId: row.id, |
| | | invoiceNo: row.invoiceNo, |
| | | invoiceType: row.invoiceType, |
| | | invoiceName: row.invoiceName, |
| | | invoiceAmount: row.invoiceAmount, |
| | | // 记录计入的费用科目和金额,删除发票时按同一口径扣减 |
| | | expenseField: this.resolveInvoiceExpenseField(row), |
| | | expenseAmount: moneyRound( |
| | | this.invoiceAmountValue(row.invoiceAmount) |
| | | ).toFixed(2), |
| | | reimburseState: "1" |
| | | }; |
| | | }, |
| | | // 发票类型 -> 报销明细费用科目 |
| | | resolveInvoiceExpenseField(invoice) { |
| | | const type = String(invoice.invoiceType || ""); |
| | | let ext = {}; |
| | | try { |
| | | ext = invoice.extContent ? JSON.parse(invoice.extContent) : {}; |
| | | if (!ext || typeof ext !== "object") { |
| | | ext = {}; |
| | | } |
| | | } catch (e) { |
| | | ext = {}; |
| | | } |
| | | const text = [ |
| | | type, |
| | | invoice.invoiceName, |
| | | invoice.sellerName, |
| | | ext["销售方名称"], |
| | | ext["项目名称"], |
| | | ext["货物或应税劳务名称"] |
| | | ] |
| | | .filter(Boolean) |
| | | .join(" "); |
| | | // 优先识别发票类型里直接写明的费用科目 |
| | | if (type.includes("市内交通")) return "cityfee"; |
| | | if (type.includes("交通")) return "trafficexpense"; |
| | | if (type.includes("住宿")) return "hotelexpense"; |
| | | if (type.includes("伙食")) return "foodallowance"; |
| | | if (type.includes("公杂")) return "otherexpense"; |
| | | if (type.includes("其他费用")) return "otherfeeamount"; |
| | | // OCR 类型通常是发票种类,再结合发票名称/销售方/项目名称识别 |
| | | if (/出租|网约|滴滴|地铁|公交|停车|过路|通行费/.test(text)) { |
| | | return "cityfee"; |
| | | } |
| | | if ( |
| | | /火车|高铁|动车|铁路|飞机|航空|机票|行程单|汽车票|客运|船票|运输/.test( |
| | | text |
| | | ) |
| | | ) { |
| | | return "trafficexpense"; |
| | | } |
| | | if (/住宿|酒店|宾馆|旅馆/.test(text)) return "hotelexpense"; |
| | | if (/伙食|餐饮|餐费|饭店|食品/.test(text)) return "foodallowance"; |
| | | if (/公杂|办公|日用品|通讯|电话费|快递/.test(text)) { |
| | | return "otherexpense"; |
| | | } |
| | | // 无法归类的发票统一计入其他费用 |
| | | return "otherfeeamount"; |
| | | }, |
| | | // 发票金额可能是带千分位/货币符号的文本,抽出可计算部分 |
| | | invoiceAmountValue(value) { |
| | | const text = String(value === null || value === undefined ? "" : value) |
| | | .replace(/,/g, "") |
| | | .trim(); |
| | | const match = text.match(/-?\d*\.?\d+/); |
| | | return match ? match[0] : 0; |
| | | }, |
| | | // sign=1 计入,sign=-1 扣减,金额统一走精确运算 |
| | | applyInvoiceExpense(detail, invoiceFile, sign) { |
| | | const field = invoiceFile.expenseField; |
| | | if (!detail || !field) { |
| | | return 0; |
| | | } |
| | | const amount = moneyRound( |
| | | this.invoiceAmountValue( |
| | | invoiceFile.expenseAmount !== undefined |
| | | ? invoiceFile.expenseAmount |
| | | : invoiceFile.invoiceAmount |
| | | ) |
| | | ); |
| | | if (!amount) { |
| | | return 0; |
| | | } |
| | | const before = moneyRound(detail[field]); |
| | | const next = |
| | | sign > 0 |
| | | ? moneyAdd(before, amount) |
| | | : moneySub(before, amount); |
| | | const after = moneyRound(Math.max(0, next)); |
| | | detail[field] = after.toFixed(2); |
| | | return moneyRound(after - before); |
| | | }, |
| | | // 汇总一行明细中计入指定费用科目的发票金额 |
| | | sumInvoiceExpenseByField(row, field) { |
| | | const list = (row && row.invoicefilesList) || []; |
| | | return moneySum( |
| | | list.filter(item => item && item.expenseField === field), |
| | | item => |
| | | item.expenseAmount !== undefined |
| | | ? item.expenseAmount |
| | | : item.invoiceAmount |
| | | ); |
| | | }, |
| | | // 附件名校验不允许空格/特殊字符且主干≤20字,用发票号码生成安全文件名 |
| | | buildInvoiceFileName(row, ext) { |
| | | const raw = String(row.invoiceNo || "").replace(/[\s/\\:*?"<>|#%]/g, ""); |
| | | const main = [...(raw || "发票" + row.id)].slice(0, 20).join(""); |
| | | return main + ext; |
| | | }, |
| | | // 发票地址入库时统一成接口相对路径,避免服务器地址变更后预览失效 |
| | | toRelativeFileUrl(url) { |
| | | const text = String(url || ""); |
| | | const index = text.indexOf("/profile/upload"); |
| | | return index > -1 ? text.slice(index) : text; |
| | | }, |
| | | getFileExt(url) { |
| | | const path = String(url || "").split("?")[0]; |
| | | const index = path.lastIndexOf("."); |
| | | return index > -1 ? path.slice(index) : ""; |
| | | }, |
| | | // 预览框依赖文件名后缀判断文件类型,缺少后缀时用地址补齐 |
| | | withFileExt(name, url) { |
| | | const text = String(name || ""); |
| | | if (/\.[a-z0-9]{2,5}$/i.test(text)) { |
| | | return text; |
| | | } |
| | | const ext = this.getFileExt(url); |
| | | return ext ? text + ext : text; |
| | | }, |
| | | // 获取请求头 |
| | | Getnetworkheader() { |
| | | // 以当前页面 origin 为准,兼容 80/8032/9091 及后续端口调整 |
| | |
| | | //发票 |
| | | if (this.rbDetails[index].invoicefilesList) { |
| | | const fetchPromises = this.rbDetails[index].invoicefilesList.map( |
| | | (value, indexson) => { |
| | | const pdfimg = this.Networkheader + process.env.VUE_APP_BASE_API + value.url; |
| | | value => { |
| | | // 保留发票业务字段(invoiceId/类型/名称/金额),重新打开时仍可展示和删除 |
| | | const kept = Object.assign({}, value); |
| | | // 发票管理中的地址是完整 URL,不能再拼接口前缀 |
| | | if (/^https?:\/\//i.test(value.url)) { |
| | | return Promise.resolve(kept); |
| | | } |
| | | const pdfimg = |
| | | this.Networkheader + process.env.VUE_APP_BASE_API + value.url; |
| | | return fetch(pdfimg, config) |
| | | .then(response => response.blob()) |
| | | .then(blob => { |
| | | return { |
| | | name: value.name, |
| | | url: URL.createObjectURL(blob) |
| | | }; |
| | | kept.url = URL.createObjectURL(blob); |
| | | return kept; |
| | | }) |
| | | .catch(error => { |
| | | console.error("Error loading image", error); |
| | | return null; |
| | | return kept; |
| | | }); |
| | | } |
| | | ); |
| | |
| | | this.invoicefileListto = invoicefileListto.filter( |
| | | item => item !== null |
| | | ); |
| | | this.invoicepdfimg = this.invoicefileListto[0].url; |
| | | this.invoicepdfimg = this.invoicefileListto.length |
| | | ? this.invoicefileListto[0].url |
| | | : ""; |
| | | console.log(this.invoicepdfimg, "invoicepdfimg"); |
| | | this.invoicepdfimgsrcList = this.invoicefileListto.map( |
| | | item => item.url |
| | |
| | | downFile(item) { |
| | | const source = |
| | | this.activeName == 1 ? this.fileListto : this.invoicefileListto; |
| | | let list = (source || []).map(f => ({ name: f.name, url: f.url })); |
| | | let list = (source || []).map(f => ({ |
| | | name: this.withFileExt(f.name, f.url), |
| | | url: f.url |
| | | })); |
| | | let index = list.findIndex(f => f.url === item.url); |
| | | if (index < 0 && item && item.url) { |
| | | list = [{ name: item.name, url: item.url }]; |
| | | list = [{ name: this.withFileExt(item.name, item.url), url: item.url }]; |
| | | index = 0; |
| | | } |
| | | this.$previewFile(list, index > -1 ? index : 0); |
| | |
| | | this.invoicepdfimgsrcList, |
| | | row.url |
| | | ); |
| | | this.invoicepdfimgsrcList.splice(indexlist, 1); |
| | | if (indexlist > -1) { |
| | | this.invoicepdfimgsrcList.splice(indexlist, 1); |
| | | } |
| | | const index = this.getIndexInArray(this.invoicefileListto, row); |
| | | this.invoicefileListto.splice(index, 1); |
| | | console.log(this.rbDetails[this.atpresent].invoicefilesList); |
| | | const targetIndex = this.rbDetails[ |
| | | this.atpresent |
| | | ].invoicefilesList.findIndex(item => { |
| | | return item.name === row.name; // 建议使用严格相等 === |
| | | if (index > -1) { |
| | | this.invoicefileListto.splice(index, 1); |
| | | } |
| | | const invoiceFiles = |
| | | this.rbDetails[this.atpresent].invoicefilesList || []; |
| | | // 引用发票按发票ID匹配,避免同名发票删错;上传文件按名称兼容旧数据 |
| | | const targetIndex = invoiceFiles.findIndex(item => { |
| | | return row.invoiceId |
| | | ? String(item.invoiceId) === String(row.invoiceId) |
| | | : item.name === row.name; |
| | | }); |
| | | console.log(targetIndex, "删除索引"); // 现在打印的是索引号,例如 0, 1, 2... |
| | | console.log(targetIndex, "删除索引"); |
| | | |
| | | let removed = null; |
| | | if (targetIndex > -1) { |
| | | // 确保找到了元素 |
| | | this.rbDetails[this.atpresent].invoicefilesList.splice( |
| | | targetIndex, |
| | | 1 |
| | | ); |
| | | removed = invoiceFiles.splice(targetIndex, 1)[0]; |
| | | console.log("删除成功"); |
| | | } else { |
| | | console.log("未找到对应项目,无法删除"); |
| | | } |
| | | // 删除已引用发票时,按引用时计入的科目和金额扣减 |
| | | if (removed && removed.expenseField) { |
| | | this.applyInvoiceExpense( |
| | | this.rbDetails[this.atpresent], |
| | | removed, |
| | | -1 |
| | | ); |
| | | this.sumRowFee(this.rbDetails[this.atpresent]); |
| | | } |
| | | // 删除已引用的发票后,把发票恢复为未报销 |
| | | const invoiceId = row.invoiceId || (removed && removed.invoiceId); |
| | | if (invoiceId) { |
| | | updateInvoice({ id: invoiceId, reimburseState: "0" }) |
| | | .then(() => { |
| | | this.$modal.msgSuccess( |
| | | "发票已删除,费用已扣减并恢复为未报销" |
| | | ); |
| | | }) |
| | | .catch(() => { |
| | | this.$modal.msgError( |
| | | "发票状态恢复失败,请到发票管理中手动标记为未报销" |
| | | ); |
| | | }); |
| | | } |
| | | } |
| | | }, |
| | |
| | | ); // 将itemann插入到索引位置的前一位 |
| | | } else { |
| | | const index = this.getIndexInArray(this.invoicefileListto, row); |
| | | if (index < 1) { |
| | | return; |
| | | } |
| | | const item = this.invoicefileListto.splice(index, 1)[0]; // 移除指定索引处的元素,并保存到item变量中 |
| | | this.invoicefileListto.splice(index - 1, 0, item); // 将item插入到索引位置的前一位 |
| | | |
| | | const indexinvo = this.rbDetails[ |
| | | this.atpresent |
| | | ].invoicefilesList.findIndex(item => item.name == row.name); |
| | | const iteminvo = this.rbDetails[this.atpresent].invoicefilesList.splice( |
| | | indexinvo, |
| | | 1 |
| | | )[0]; // 移除指定索引处的元素,并保存到item变量中 |
| | | this.rbDetails[this.atpresent].invoicefilesList.splice( |
| | | indexinvo - 1, |
| | | 0, |
| | | iteminvo |
| | | ); // 将iteminvo插入到索引位置的前一位 |
| | | const invoiceFiles = |
| | | this.rbDetails[this.atpresent].invoicefilesList || []; |
| | | const indexinvo = invoiceFiles.findIndex(file => |
| | | row.invoiceId |
| | | ? String(file.invoiceId) === String(row.invoiceId) |
| | | : file.name == row.name |
| | | ); |
| | | if (indexinvo < 1) { |
| | | return; |
| | | } |
| | | const iteminvo = invoiceFiles.splice(indexinvo, 1)[0]; |
| | | invoiceFiles.splice(indexinvo - 1, 0, iteminvo); |
| | | } |
| | | }, |
| | | |
| | |
| | | row.persontype == "管理人员" |
| | | ) { |
| | | //公杂费补助:杭州桐庐,建德,淳安60,杭州其他地区0,非杭州地区80 |
| | | const otherInvoice = this.sumInvoiceExpenseByField( |
| | | row, |
| | | "otherexpense" |
| | | ); |
| | | const foodInvoice = this.sumInvoiceExpenseByField( |
| | | row, |
| | | "foodallowance" |
| | | ); |
| | | // 先算补助基数,再叠加餐饮/办公类发票,避免补助重算把发票金额覆盖 |
| | | let baseOther = row.otherexpense; |
| | | if (otherInvoice) { |
| | | baseOther = moneySub(row.otherexpense, otherInvoice); |
| | | } |
| | | if (row.destination != "") { |
| | | var tempStr = row.destination; |
| | | |
| | | //验证城市 |
| | | if (tempStr == "杭州") { |
| | | row.otherexpense = ""; |
| | | baseOther = ""; |
| | | } else if ( |
| | | tempStr.includes("桐庐") || |
| | | tempStr.includes("建德") || |
| | | tempStr.includes("淳安") |
| | | ) { |
| | | row.otherexpense = (parseInt(row.days) * 60).toString(); |
| | | baseOther = (parseInt(row.days) * 60).toString(); |
| | | } else { |
| | | row.otherexpense = (parseInt(row.days) * 80).toString(); |
| | | baseOther = (parseInt(row.days) * 80).toString(); |
| | | } |
| | | } |
| | | |
| | | //伙食费补助:城市(西藏,新疆,青海.120)(其他100) |
| | | let baseFood = ""; |
| | | if (tempStr == "杭州") { |
| | | row.foodallowance = ""; |
| | | baseFood = ""; |
| | | } else if ( |
| | | tempStr == "西藏" || |
| | | tempStr == "新疆" || |
| | | tempStr == "青海" |
| | | ) { |
| | | row.foodallowance = (parseInt(row.days) * 120).toString(); |
| | | baseFood = (parseInt(row.days) * 120).toString(); |
| | | } else { |
| | | row.foodallowance = (parseInt(row.days) * 100).toString(); |
| | | baseFood = (parseInt(row.days) * 100).toString(); |
| | | } |
| | | |
| | | row.otherexpense = |
| | | baseOther === "" && !otherInvoice |
| | | ? "" |
| | | : moneyAdd(baseOther, otherInvoice).toFixed(2); |
| | | row.foodallowance = |
| | | baseFood === "" && !foodInvoice |
| | | ? "" |
| | | : moneyAdd(baseFood, foodInvoice).toFixed(2); |
| | | |
| | | //计算合计 |
| | | this.sumRowFee(row); |
| | |
| | | for (let i = 0; i < response.data.length; i++) { |
| | | fee += response.data[i].reimbursementamout; |
| | | } |
| | | row.hotelexpense = fee; |
| | | const hotelInvoice = this.sumInvoiceExpenseByField( |
| | | row, |
| | | "hotelexpense" |
| | | ); |
| | | row.hotelexpense = moneyAdd(fee, hotelInvoice).toFixed(2); |
| | | }) |
| | | .finally(() => { |
| | | this.sumTotalFee(); |
| | | this.sumRowFee(row); |
| | | }); |
| | | } |
| | | }, |
| | |
| | | text-align: center; |
| | | } |
| | | |
| | | .invoice-select-bar { |
| | | display: flex; |
| | | align-items: center; |
| | | flex-wrap: wrap; |
| | | margin-bottom: 10px; |
| | | |
| | | &__tip { |
| | | margin-left: 10px; |
| | | font-size: 12px; |
| | | color: #909399; |
| | | } |
| | | } |
| | | |
| | | .pdfimg { |
| | | display: flex; // text-align: center; |
| | | width: 100%; |
| | |
| | | box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.1); // <- Add this to fix. |
| | | } |
| | | |
| | | // 发票页多出类型/名称/金额三列,给表格留出横向空间 |
| | | .box-pdf--invoice { |
| | | width: 560px; |
| | | } |
| | | |
| | | .pdftit { |
| | | width: 200px; |
| | | padding: 20px; |