Compare commits
No commits in common. "frontend_1.0.0" and "master" have entirely different histories.
frontend_1
...
master
|
|
@ -35,8 +35,6 @@ nbbuild/
|
||||||
dist/
|
dist/
|
||||||
nbdist/
|
nbdist/
|
||||||
.nb-gradle/
|
.nb-gradle/
|
||||||
.DS_Store
|
|
||||||
*.png
|
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# Others
|
# Others
|
||||||
|
|
|
||||||
|
|
@ -1,52 +0,0 @@
|
||||||
# 2026-09-08
|
|
||||||
|
|
||||||
## 代码 review(两轮)
|
|
||||||
|
|
||||||
用户要求只 review 不改代码。范围:工作区 53 个改动文件(Java 后端 + Vue 前端)。
|
|
||||||
|
|
||||||
### 改动主体
|
|
||||||
- Excel 注解新增 `decimalFormat` 字段(Excel.java + ExcelUtil.java),21 个 domain 的 BigDecimal 字段加 `@Excel(scale=2, decimalFormat="#,##0.00")`,仅影响导出显示,安全。
|
|
||||||
- 前端多处 `toFixed(2)` → 全局 `formatCurrency`(main.js 已注册 Vue.prototype),安全。
|
|
||||||
- ProductInfo/Mapper/前端新增 `pre_system_type`(预装系统类型)字段,前后端配套完整,配套 SQL:`sql/20290904update.sql`(文件名年份疑为笔误,写的是 2029)。
|
|
||||||
- `OmsInventoryInnerServiceImpl.insertOmsInventoryInner` 应付单生成逻辑重构(核心风险点)。
|
|
||||||
|
|
||||||
### 第一轮发现的问题 → 用户修复后第二轮复核结果
|
|
||||||
1. NPE(quantity/price 为 null 时直接 multiply)→ 已修:`usePurchaseOrder` 条件含 null 检查,null 时回退原公式 ✓
|
|
||||||
2. 重复 setTaxAmount(新旧两行并存)→ 已清理,只留正确行(含税-未税)✓
|
|
||||||
3. vendorInfo 为 null 时 getPayConfigDay() NPE → 已修,传 0 ✓
|
|
||||||
4. 遗留:`vendorInfo != null ? vendorInfo.getPayConfigDay() : 0` 三元混合 Integer/int,payConfigDay 为 null 时仍会拆箱 NPE(原代码同样会炸,非回归)
|
|
||||||
5. 遗留:ExcelUtil 每单元格 createCellStyle,POI 上限 64000 样式,大数据量导出会失败
|
|
||||||
6. 遗留:OrderList.java 文件末尾无换行;oms_web/.DS_Store 未跟踪垃圾文件
|
|
||||||
|
|
||||||
### 业务逻辑一致性结论(H3C 判定)
|
|
||||||
- 新华三(isH3C=true,startsWith("新华三")):条件退化为原条件,金额公式走原逻辑,与原 100% 一致
|
|
||||||
- 非新华三无采购单:innerComplete 默认 true,与原一致
|
|
||||||
### 第三轮复核(用户又修复了一批)
|
|
||||||
1. 三元拆箱 NPE → 已修:`vendorInfo != null && vendorInfo.getPayConfigDay() != null ? ... : 0` ✓
|
|
||||||
2. ExcelUtil CellStyle → 已修:新增 `moneyStyles` Map 缓存(按 decimalFormat 键),HashMap 已导入,ExcelUtil 每次 export 新建实例,缓存作用域正确 ✓
|
|
||||||
3. OrderList.java 末尾换行 → 已补 ✓
|
|
||||||
仍遗留(非代码 bug,提交时注意):isH3C 口径需业务确认(startsWith("新华三"),基于 ProductInfo.vendorName);sql/20290904update.sql 文件名年份笔误(2029);oms_web/.DS_Store 与 ruoyi-admin/.DS_Store 垃圾文件。
|
|
||||||
至此所有代码级问题均已修复,H3C/无采购单场景与原逻辑一致,非新华三+有采购单为有意业务变更。
|
|
||||||
|
|
||||||
### 金额格式统一专项检查(第四轮,只查不改)
|
|
||||||
**统一现状**:全局 formatCurrency(utils/index.js:17,main.js:46 注册,null→'0.00',toLocaleString en-US 2位小数);本次 diff 新增 72 处 formatCurrency(27 个文件);后端 21 个 domain 106 个 @Excel 字段加 decimalFormat。
|
|
||||||
|
|
||||||
**后端 Excel 遗漏**:OmsTicketBill.java:70 taxAmount(税额,活动注解,其余单据均已加)。比率类(taxRate×4、planRate×2、invoiceRate、receiptRate)未加属合理;折扣类(OrderList.discount、ProjectOrderConfigInfo.guidanceDiscount/discount)需确认语义。
|
|
||||||
|
|
||||||
**前端遗漏**:ApplyInvoice.vue:122/129/143 v-else 分支裸显示 unitPrice/amount/taxAmount;writeoff 两 index 的 $modal 提示文案 5 处无千分位(轻微);formatCurrency(x.toFixed(2)) 双重格式化 ~12 处(冗余无害)。
|
|
||||||
|
|
||||||
**体系性发现**:项目存在 7+ 处组件局部 formatAmount/formatAmountNumber 副本(均为存量,非本次新增):purchaseorder/index.vue:589、orderFinance.vue:377(filters)、base/quotation/index.vue:535、ProductConfig.vue:497、approve/all/index.vue:1295(用zh-CN)、projectTransfer.vue:293、project/info/index.vue:491 等。差异:局部版 null→'',全局版 null→'0.00'。后续统一建议收敛到全局 formatCurrency,先定 null 显示口径。
|
|
||||||
|
|
||||||
**formatCurrency 边界**:非数字字符串入参会显示 "NaN"(Number('abc').toLocaleString → "NaN"),建议加 Number.isNaN 保护。convertCurrency(大写金额)依赖 toFixed 字符串,InvoiceInfoView:115 / ApplyInvoice:278 / invoiceExcelUtils.js:147 的 toFixed(2) 必须保留,不是遗漏。
|
|
||||||
|
|
||||||
### 第五轮:全量改动集成测试(mvn 编译 + vue 解析)
|
|
||||||
**Maven 全量编译**(JAVA_HOME=Corretto 8):7 模块 SUCCESS,0 ERROR。Lombok、@Excel 注解、mapper SQL、Service 实现全部对齐。
|
|
||||||
**前端 31 文件 SFC/JS 解析**:用 @vue/compiler-sfc 批量 parse,0 失败(PaymentRefundDetail、ReceiptDetail、ReceivableInvoiceDetail、ApplyInvoice、InvoiceInfoView、EditForm×2、AddForm、receipt/index、writeoff 6 个文件、inventory/inner、ProductConfig、ProjectForm、project/info/index、OrderDetail、PurchaseOrderDetail、PurchaseOrderDetailView、PurchaseOrderSelectDialog、vendorConfirm、system/product、approve/purchaase×2、selectQuotation、projectTransfer、invoiceExcelUtils.js)。
|
|
||||||
|
|
||||||
**本轮新增发现的位置**(前几轮未深查):
|
|
||||||
- ruoyi-admin/logback.xml:把 jiliu 路径换成 kangwenjing 个人本地路径,纯个人配置切换,不影响代码(提交前建议恢复或加 .gitignore 排除)。
|
|
||||||
- dto/InventoryInfoExcelDto.java、dto/warehouse/WarehouseInnerExcelDto.java:innerPrice 加 decimalFormat,已正确 ✓
|
|
||||||
- approve/purchaase/{approve,approved}/index.vue:含税总金额列加 formatter ✓
|
|
||||||
- base/quotation/selectQuotation.vue:discountAmount 加 formatter,字段名语义为"报价金额"(QuotationInfo 表的折扣后金额),没问题 ✓
|
|
||||||
- system/product/index.vue:queryParams 已在 data() 初始声明 preSystemType: null ✓;resetForm 依赖表单模板自动重置 ✓;handleTypeChange 在切换非硬件时清空 preSystemType ✓
|
|
||||||
- OmsTicketBill.java:70 税额仍**漏** decimalFormat(连续两轮没修)。
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
# 2026-09-09 工作日志
|
|
||||||
|
|
||||||
## 全量改动复核 + 集成测试(不动代码)
|
|
||||||
|
|
||||||
**改动规模**:65 文件、+427 / -283 行
|
|
||||||
|
|
||||||
**集成测试结果**:
|
|
||||||
- 后端:`mvn compile -DskipTests`(JAVA_HOME=Corretto 1.8.0_442) → **BUILD SUCCESS**,7 模块 0 ERROR
|
|
||||||
- 前端:31 个 Vue/JS 文件用 `@vue/compiler-sfc` 解析 → **31 ok, 0 fail**
|
|
||||||
|
|
||||||
**本轮发现**:
|
|
||||||
1. `OmsTicketBill.java:70` 税额已加 `decimalFormat = "#,##0.00"`(用户修复)
|
|
||||||
2. SQL 文件名 `20290904` → `20260904`(已改),但文件内注释仍写 `2029-09-04`
|
|
||||||
3. `.gitignore` 已加 `.DS_Store`(用户修复)
|
|
||||||
4. `ruoyi-admin/.DS_Store` 仍被 `git ls-files` 跟踪,需 `git rm --cached` 才能彻底忽略
|
|
||||||
|
|
||||||
**确认正确的覆盖**:
|
|
||||||
- `inventory/inner/index.vue`、`vendorConfirm.vue` — 本次新加 formatter 没问题
|
|
||||||
- `InventoryInfoExcelDto.java`、`WarehouseInnerExcelDto.java` — 入库价已加 decimalFormat
|
|
||||||
- `ProductInfo.java` + `ProductInfoMapper.xml` — preSystemType 字段前后端完整配套
|
|
||||||
- `OmsInventoryInnerServiceImpl.java` — 三处修复(NPE、payConfigDay 拆箱、税金额)均正确
|
|
||||||
|
|
||||||
**仍未修的小遗留**:
|
|
||||||
- `ApplyInvoice.vue:122/129/143` v-else 裸显示(用户上一轮已知,影响小)
|
|
||||||
- 14 处 `formatCurrency(x.toFixed(2))` 双重格式化(冗余但正确)
|
|
||||||
- 7+ 处局部 `formatAmount/formatAmountNumber` 副本(存量代码,本次未改)
|
|
||||||
|
|
||||||
**体系性问题(与本次改动范围无关)**:
|
|
||||||
- 项目里 7+ 处组件局部的 `formatAmount` 副本,行为与全局 `formatCurrency` 略有差异(null 显示空 vs '0.00'),建议后续收敛
|
|
||||||
- `formatCurrency('abc')` 会显示 "NaN",建议加 `Number.isNaN` 保护
|
|
||||||
|
|
||||||
**提交前清单**:
|
|
||||||
- [ ] 修 `sql/20260904update.sql` 注释里的 `2029-09-04` → `2026-09-04`
|
|
||||||
- [ ] `git rm --cached ruoyi-admin/.DS_Store`(.gitignore 已加,但已跟踪文件需手动移除)
|
|
||||||
- [ ] 可选:`git checkout ruoyi-admin/src/main/resources/logback.xml` 恢复个人本地路径
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,70 +0,0 @@
|
||||||
-- =====================================================================
|
|
||||||
-- MCP 只读数据工具 —— 索引脚本(对应方案第 6 章 / 16.4)
|
|
||||||
-- 适用:MySQL 8.0+
|
|
||||||
--
|
|
||||||
-- 【2026-09-23 实测更新】在 oms_test 上核对 information_schema 后发现:
|
|
||||||
-- • P0-1 oms_inventory_outer.idx_outer_code(outer_code) —— 已存在,无需执行
|
|
||||||
-- • P0-2 oms_inventory_outer_detail.idx_outer_code(outer_code) —— 已存在,无需执行
|
|
||||||
-- • P1-1 oms_inventory_inner.idx_order_code(order_code) —— 已存在,无需执行
|
|
||||||
-- • P1-2 oms_purchase_order.idx_vendor_id(vendor_id) —— 已存在,无需执行
|
|
||||||
-- • P1-3 oms_inventory_info 覆盖索引 —— 缺失,已在 oms_test 执行并实测收益
|
|
||||||
-- (建索引耗时 1.3s;按产品聚合 141.8ms → 66.6ms;EXPLAIN 显示 Using index,免回表)
|
|
||||||
--
|
|
||||||
-- 因此本脚本默认全部注释,仅作为「生产执行前的核对与补建」清单使用。
|
|
||||||
-- 执行前请先跑文末的核对语句,确认目标索引是否缺失。
|
|
||||||
-- =====================================================================
|
|
||||||
|
|
||||||
-- ---------------------------------------------------------------------
|
|
||||||
-- P0 必加(inventory_flow 出库链路依赖;若缺失将导致按出库单号全表扫描)
|
|
||||||
-- 实测:oms_test 已存在
|
|
||||||
-- ---------------------------------------------------------------------
|
|
||||||
-- ALTER TABLE oms_inventory_outer ADD INDEX idx_outer_code (outer_code), ALGORITHM=INPLACE, LOCK=NONE;
|
|
||||||
-- ALTER TABLE oms_inventory_outer_detail ADD INDEX idx_outer_code (outer_code), ALGORITHM=INPLACE, LOCK=NONE;
|
|
||||||
|
|
||||||
-- ---------------------------------------------------------------------
|
|
||||||
-- P1 建议
|
|
||||||
-- 实测:P1-1 / P1-2 在 oms_test 已存在
|
|
||||||
-- ---------------------------------------------------------------------
|
|
||||||
-- ALTER TABLE oms_inventory_inner ADD INDEX idx_order_code (order_code), ALGORITHM=INPLACE, LOCK=NONE;
|
|
||||||
-- ALTER TABLE oms_purchase_order ADD INDEX idx_vendor_id (vendor_id), ALGORITHM=INPLACE, LOCK=NONE;
|
|
||||||
|
|
||||||
-- ---------------------------------------------------------------------
|
|
||||||
-- P1-3 覆盖索引(库存聚合免回表)
|
|
||||||
-- 实测收益显著;但存在写入放大(每次 insert/update 需维护 4 列索引),
|
|
||||||
-- 生产库请由 DBA 结合写入量评估后再执行;回滚语句见文末。
|
|
||||||
-- oms_test 已于 2026-09-23 执行。
|
|
||||||
-- ---------------------------------------------------------------------
|
|
||||||
-- ALTER TABLE oms_inventory_info
|
|
||||||
-- ADD INDEX idx_pc_status_amt (product_code, inventory_status, inner_price, outer_price),
|
|
||||||
-- ALGORITHM=INPLACE, LOCK=NONE;
|
|
||||||
|
|
||||||
-- ---------------------------------------------------------------------
|
|
||||||
-- P2 按表规模触发(当前数据量下无需执行;表增长到 10 万+ 或成为热点时再补)
|
|
||||||
-- 完整编号清单见方案 6.3 节(P2-1 ~ P2-26,其中 P2-3/P2-4/P2-19 已作废)
|
|
||||||
-- ---------------------------------------------------------------------
|
|
||||||
-- ALTER TABLE oms_purchase_order_map ADD INDEX idx_order_id (order_id), ALGORITHM=INPLACE, LOCK=NONE;
|
|
||||||
-- ALTER TABLE oms_purchase_order_map ADD INDEX idx_purchase_id (purchase_id), ALGORITHM=INPLACE, LOCK=NONE;
|
|
||||||
-- ALTER TABLE oms_inventory_info ADD INDEX idx_warehouse_id (warehouse_id), ALGORITHM=INPLACE, LOCK=NONE;
|
|
||||||
-- ALTER TABLE oms_stock_info ADD INDEX idx_order_code (order_code), ALGORITHM=INPLACE, LOCK=NONE;
|
|
||||||
-- ALTER TABLE oms_receivable_receipt_detail ADD INDEX idx_write_off_id (write_off_id), ALGORITHM=INPLACE, LOCK=NONE;
|
|
||||||
-- ALTER TABLE oms_payable_payment_detail ADD INDEX idx_write_off_id (write_off_id), ALGORITHM=INPLACE, LOCK=NONE;
|
|
||||||
-- ALTER TABLE bu_todo_completed ADD INDEX idx_approve_user_time (approve_user, approve_time), ALGORITHM=INPLACE, LOCK=NONE;
|
|
||||||
|
|
||||||
-- =====================================================================
|
|
||||||
-- 执行前核对:列出目标表当前索引(若目标索引已出现则无需再建)
|
|
||||||
-- =====================================================================
|
|
||||||
-- SELECT table_name, index_name, GROUP_CONCAT(column_name ORDER BY seq_in_index) AS cols
|
|
||||||
-- FROM information_schema.statistics
|
|
||||||
-- WHERE table_schema = DATABASE()
|
|
||||||
-- AND table_name IN ('oms_inventory_outer','oms_inventory_outer_detail','oms_inventory_inner',
|
|
||||||
-- 'oms_purchase_order','oms_inventory_info')
|
|
||||||
-- GROUP BY table_name, index_name;
|
|
||||||
|
|
||||||
-- =====================================================================
|
|
||||||
-- 回滚(仅在需要撤销新增索引时执行)
|
|
||||||
-- =====================================================================
|
|
||||||
-- ALTER TABLE oms_inventory_outer DROP INDEX idx_outer_code, ALGORITHM=INPLACE, LOCK=NONE;
|
|
||||||
-- ALTER TABLE oms_inventory_outer_detail DROP INDEX idx_outer_code, ALGORITHM=INPLACE, LOCK=NONE;
|
|
||||||
-- ALTER TABLE oms_inventory_inner DROP INDEX idx_order_code, ALGORITHM=INPLACE, LOCK=NONE;
|
|
||||||
-- ALTER TABLE oms_purchase_order DROP INDEX idx_vendor_id, ALGORITHM=INPLACE, LOCK=NONE;
|
|
||||||
-- ALTER TABLE oms_inventory_info DROP INDEX idx_pc_status_amt, ALGORITHM=INPLACE, LOCK=NONE;
|
|
||||||
139
docx/prompt.md
139
docx/prompt.md
|
|
@ -1,139 +0,0 @@
|
||||||
你是一个资深 Java 后端工程师,请在当前 Spring Boot(Java8)项目中实现一个完整的 MCP Server,并加入“AI 自动选 Tool(RAG + Tool Routing)”能力。
|
|
||||||
|
|
||||||
# 一、基础 MCP 能力(必须实现)
|
|
||||||
|
|
||||||
1. 提供统一入口:
|
|
||||||
POST /mcp
|
|
||||||
|
|
||||||
2. 实现 JSON-RPC 2.0:
|
|
||||||
|
|
||||||
* initialize
|
|
||||||
* tools/list
|
|
||||||
* tools/call
|
|
||||||
|
|
||||||
3. 返回格式:
|
|
||||||
{
|
|
||||||
"jsonrpc": "2.0",
|
|
||||||
"id": "...",
|
|
||||||
"result": ...
|
|
||||||
}
|
|
||||||
|
|
||||||
# 二、流式能力(必须)
|
|
||||||
|
|
||||||
1. 禁止使用 SseEmitter
|
|
||||||
2. 使用 HttpServletResponse + OutputStream
|
|
||||||
3. 实现 chunked streaming(write + flush)
|
|
||||||
|
|
||||||
# 三、Tool 注册中心(必须)
|
|
||||||
|
|
||||||
实现:
|
|
||||||
|
|
||||||
* McpToolRegistry
|
|
||||||
* register / get / list
|
|
||||||
|
|
||||||
Tool结构:
|
|
||||||
|
|
||||||
* name
|
|
||||||
* description(非常重要,用于向量检索)
|
|
||||||
* inputSchema
|
|
||||||
* handler
|
|
||||||
|
|
||||||
# 四、RAG Tool 检索模块(新增重点)
|
|
||||||
|
|
||||||
实现一个 ToolRetriever 组件:
|
|
||||||
|
|
||||||
1. 构建向量索引(简化实现):
|
|
||||||
|
|
||||||
* 使用内存存储 List<ToolEmbedding>
|
|
||||||
* ToolEmbedding:
|
|
||||||
|
|
||||||
* toolName
|
|
||||||
* description
|
|
||||||
* embedding(double[])
|
|
||||||
|
|
||||||
2. 提供方法:
|
|
||||||
List<McpTool> retrieve(String query, int topK)
|
|
||||||
|
|
||||||
3. embedding 实现(简化):
|
|
||||||
|
|
||||||
* 可使用:
|
|
||||||
|
|
||||||
* 简单 TF-IDF
|
|
||||||
* 或 mock embedding(字符串相似度)
|
|
||||||
* 不依赖外部服务(保证可运行)
|
|
||||||
|
|
||||||
# 五、Tool Router(核心)
|
|
||||||
|
|
||||||
实现 ToolRouter:
|
|
||||||
|
|
||||||
流程:
|
|
||||||
|
|
||||||
1. 接收用户问题 query
|
|
||||||
2. 调用 ToolRetriever → 获取 topK tools
|
|
||||||
3. 构建 prompt(只包含候选 tools)
|
|
||||||
4. 返回候选 tools 给上层(或直接选)
|
|
||||||
|
|
||||||
要求:
|
|
||||||
|
|
||||||
* 不允许返回全部 tools
|
|
||||||
* 默认 topK = 3~5
|
|
||||||
|
|
||||||
# 六、tools/call 升级(关键)
|
|
||||||
|
|
||||||
当 method = tools/call 时:
|
|
||||||
|
|
||||||
1. 如果请求未指定 tool:
|
|
||||||
|
|
||||||
* 自动触发 ToolRouter
|
|
||||||
* 选出最优 tool
|
|
||||||
|
|
||||||
2. 如果指定 tool:
|
|
||||||
|
|
||||||
* 直接执行
|
|
||||||
|
|
||||||
# 七、默认内置工具
|
|
||||||
|
|
||||||
实现:
|
|
||||||
|
|
||||||
1. hello
|
|
||||||
输入:name
|
|
||||||
输出:hello xxx
|
|
||||||
|
|
||||||
2. meeting.summary
|
|
||||||
输入:text
|
|
||||||
输出:模拟总结
|
|
||||||
|
|
||||||
# 八、架构分层(必须)
|
|
||||||
|
|
||||||
* controller
|
|
||||||
* service
|
|
||||||
* registry
|
|
||||||
* retriever(新增)
|
|
||||||
* router(新增)
|
|
||||||
|
|
||||||
# 九、扩展能力(必须预留)
|
|
||||||
|
|
||||||
1. 支持替换为真实向量数据库(如 Milvus / ES)
|
|
||||||
2. 支持 embedding API(OpenAI / 本地模型)
|
|
||||||
3. 支持多 MCP Server(未来扩展)
|
|
||||||
|
|
||||||
# 十、输出要求
|
|
||||||
|
|
||||||
1. 输出完整代码:
|
|
||||||
|
|
||||||
* McpController
|
|
||||||
* McpService
|
|
||||||
* McpToolRegistry
|
|
||||||
* ToolRetriever
|
|
||||||
* ToolRouter
|
|
||||||
* ToolEmbedding
|
|
||||||
* ToolInitializer
|
|
||||||
* McpRequest
|
|
||||||
|
|
||||||
2. 代码必须:
|
|
||||||
|
|
||||||
* 可运行
|
|
||||||
* 无伪代码
|
|
||||||
* 包含必要注释
|
|
||||||
* 代码生成目录在ruoyi-sip/src/main/java/com/ruoyi/sip/llm
|
|
||||||
3. 不要解释,只输出代码
|
|
||||||
|
|
@ -6,4 +6,3 @@ ENV = 'production'
|
||||||
|
|
||||||
# 若依管理系统/生产环境
|
# 若依管理系统/生产环境
|
||||||
VUE_APP_BASE_API = '/prod-api'
|
VUE_APP_BASE_API = '/prod-api'
|
||||||
VUE_APP_SERVICE_HOST = 'wb.oms.unisspace.com'
|
|
||||||
|
|
|
||||||
|
|
@ -28,20 +28,18 @@
|
||||||
"axios": "0.28.1",
|
"axios": "0.28.1",
|
||||||
"clipboard": "2.0.8",
|
"clipboard": "2.0.8",
|
||||||
"core-js": "3.37.1",
|
"core-js": "3.37.1",
|
||||||
"decimal.js": "10.4.2",
|
|
||||||
"echarts": "5.4.0",
|
"echarts": "5.4.0",
|
||||||
"element-ui": "2.15.14",
|
"element-ui": "2.15.14",
|
||||||
"file-saver": "2.0.5",
|
"file-saver": "2.0.5",
|
||||||
"fuse.js": "6.4.3",
|
"fuse.js": "6.4.3",
|
||||||
"highlight.js": "9.18.5",
|
"highlight.js": "9.18.5",
|
||||||
"html2canvas": "^1.4.1",
|
|
||||||
"js-beautify": "1.13.0",
|
"js-beautify": "1.13.0",
|
||||||
"js-cookie": "3.0.1",
|
"js-cookie": "3.0.1",
|
||||||
"jsencrypt": "3.0.0-rc.1",
|
"jsencrypt": "3.0.0-rc.1",
|
||||||
"jspdf": "^2.5.1",
|
|
||||||
"jszip": "^3.10.1",
|
|
||||||
"nprogress": "0.2.0",
|
"nprogress": "0.2.0",
|
||||||
"quill": "2.0.2",
|
"quill": "2.0.2",
|
||||||
|
"html2canvas": "^1.4.1",
|
||||||
|
"jspdf": "^2.5.1",
|
||||||
"screenfull": "5.0.2",
|
"screenfull": "5.0.2",
|
||||||
"sortablejs": "1.10.2",
|
"sortablejs": "1.10.2",
|
||||||
"splitpanes": "2.4.1",
|
"splitpanes": "2.4.1",
|
||||||
|
|
@ -50,7 +48,8 @@
|
||||||
"vue-cropper": "0.5.5",
|
"vue-cropper": "0.5.5",
|
||||||
"vue-router": "3.4.9",
|
"vue-router": "3.4.9",
|
||||||
"vuedraggable": "2.24.3",
|
"vuedraggable": "2.24.3",
|
||||||
"vuex": "3.6.0"
|
"vuex": "3.6.0",
|
||||||
|
"decimal.js": "10.4.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vue/cli-plugin-babel": "4.4.6",
|
"@vue/cli-plugin-babel": "4.4.6",
|
||||||
|
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
// 查询审批任务列表
|
|
||||||
export function listApprovalTask(query) {
|
|
||||||
const { pageNum, pageSize, orderByColumn, isAsc, ...body } = query
|
|
||||||
return request({
|
|
||||||
url: '/approve/task/vue/list',
|
|
||||||
method: 'post',
|
|
||||||
params: { pageNum, pageSize, orderByColumn, isAsc },
|
|
||||||
data: body
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取审批任务数量统计
|
|
||||||
export function getApprovalTaskTotal() {
|
|
||||||
return request({
|
|
||||||
url: '/approve/task/vue/total',
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 新增流程确认记录
|
|
||||||
export function addTodoConfirm(data) {
|
|
||||||
return request({
|
|
||||||
url: '/approve/task/vue/confirm',
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
// 查询报价单列表
|
|
||||||
export function listQuotation(query) {
|
|
||||||
return request({
|
|
||||||
url: '/quotation/list',
|
|
||||||
method: 'get',
|
|
||||||
params: query
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询报价单详细
|
|
||||||
export function getQuotation(id) {
|
|
||||||
return request({
|
|
||||||
url: '/quotation/' + id,
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 新增报价单
|
|
||||||
export function addQuotation(data) {
|
|
||||||
return request({
|
|
||||||
url: '/quotation/insert',
|
|
||||||
method: 'post',
|
|
||||||
data: data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 修改报价单
|
|
||||||
export function updateQuotation(data) {
|
|
||||||
return request({
|
|
||||||
url: '/quotation/update',
|
|
||||||
method: 'put',
|
|
||||||
data: data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除报价单
|
|
||||||
export function delQuotation(id) {
|
|
||||||
return request({
|
|
||||||
url: '/quotation/remove/batch/' + id,
|
|
||||||
method: 'delete'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
export function exportSingleQuotation(id) {
|
|
||||||
return request({
|
|
||||||
url: '/quotation/export/single/' + id,
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import request from '@/utils/request'
|
import request from '@/utils/request'
|
||||||
import { tansParams } from '@/utils/ruoyi'
|
|
||||||
|
|
||||||
// 查询制造商信息列表
|
// 查询制造商信息列表
|
||||||
export function listVendor(query) {
|
export function listVendor(query) {
|
||||||
|
|
@ -49,9 +48,7 @@ export function exportVendor(query) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/vendor/export',
|
url: '/system/vendor/export',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: query,
|
params: query
|
||||||
transformRequest: [(params) => tansParams(params)],
|
|
||||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
// 按SN码查询库存数据
|
|
||||||
export function listInventoryInfoByProductSn(query) {
|
|
||||||
return request({
|
|
||||||
url: '/sip/dataProcess/inventoryInfoByProductSn',
|
|
||||||
method: 'get',
|
|
||||||
params: query
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
// 查询项目管理列表
|
|
||||||
export function listProject(query) {
|
|
||||||
return request({
|
|
||||||
url: '/sip/project/vue/list',
|
|
||||||
method: 'post',
|
|
||||||
data: query,
|
|
||||||
headers: { 'Content-Type': 'multipart/form-data' },
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 项目转移负责人
|
|
||||||
export function transferProject(data) {
|
|
||||||
return request({
|
|
||||||
url: '/sip/dataProcess/projectTransfer',
|
|
||||||
method: 'post',
|
|
||||||
data: data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,72 +0,0 @@
|
||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
// 查询财务计收列表
|
|
||||||
export function listCharge(query) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/charge/list',
|
|
||||||
method: 'get',
|
|
||||||
params: query
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询财务计收详细
|
|
||||||
export function getCharge(id) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/charge/' + id,
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 新增财务计收
|
|
||||||
export function addCharge(data) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/charge',
|
|
||||||
method: 'post',
|
|
||||||
data: data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 修改财务计收
|
|
||||||
export function updateCharge(data) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/charge',
|
|
||||||
method: 'put',
|
|
||||||
data: data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
export function revokeCharge(data) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/charge/revoke',
|
|
||||||
method: 'put',
|
|
||||||
data: data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除财务计收
|
|
||||||
export function delCharge(id) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/charge/' + id,
|
|
||||||
method: 'delete'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
export function applyChargeBiz(data) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/charge/applyBiz' ,
|
|
||||||
method: 'put',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
export function returnApplyBiz(data) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/charge/returnApplyBiz' ,
|
|
||||||
method: 'put',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
export function applyCharge(data) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/charge/apply' ,
|
|
||||||
method: 'put',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -1,136 +0,0 @@
|
||||||
import request from '@/utils/request'
|
|
||||||
import {tansParams} from "@/utils/ruoyi"
|
|
||||||
|
|
||||||
// 查询销售收票单列表
|
|
||||||
export function listInvoice(query) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/invoice/list',
|
|
||||||
method: 'post',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/x-www-form-urlencoded'
|
|
||||||
},
|
|
||||||
params: query
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询销售收票单详细
|
|
||||||
export function getInvoice(id) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/invoice/' + id,
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询销售收票单附件
|
|
||||||
export function getInvoiceAttachments(id, params) {
|
|
||||||
return request({
|
|
||||||
url: `/finance/invoice/attachment/${id}`,
|
|
||||||
method: 'get',
|
|
||||||
params
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 上传销售收票单附件
|
|
||||||
export function uploadInvoiceAttachment(data) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/invoice/uploadReceipt',
|
|
||||||
method: 'post',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'multipart/form-data'
|
|
||||||
},
|
|
||||||
data: data,
|
|
||||||
needLoading: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 申请红冲
|
|
||||||
export function redRush(id) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/invoice/applyRefund/' + id,
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 申请红冲 (提交表单)
|
|
||||||
export function applyRefund(data) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/invoice/applyRefund',
|
|
||||||
method: 'post',
|
|
||||||
data: data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 退回销售收票单
|
|
||||||
export function returnInvoice(id) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/invoice/return/' + id,
|
|
||||||
method: 'delete'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 新增销售收票单
|
|
||||||
export function addInvoice(data) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/receivable/mergeAndInitiateInvoice',
|
|
||||||
method: 'post',
|
|
||||||
data: data,
|
|
||||||
needLoading: true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询销售收票单产品明细
|
|
||||||
export function getInvoiceProducts(code) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/invoice/product/' + code,
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 申请开票
|
|
||||||
export function applyInvoice(data) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/invoice/apply',
|
|
||||||
method: 'post',
|
|
||||||
data: data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 撤销销售收票单
|
|
||||||
export function revokeInvoice(id) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/invoice/revoke/' + id,
|
|
||||||
method: 'delete'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询开票审批列表
|
|
||||||
export function listInvoiceApprove(query) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/invoice/approve/list',
|
|
||||||
method: 'post',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/x-www-form-urlencoded'
|
|
||||||
},
|
|
||||||
data: query
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询已审批开票列表
|
|
||||||
export function listInvoiceApproved(query) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/invoice/approved/list',
|
|
||||||
method: 'post',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/x-www-form-urlencoded'
|
|
||||||
},
|
|
||||||
data: query
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询开票单详细
|
|
||||||
export function getInvoiceDetail(id) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/invoice/' + id,
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
// 查询收票待审批列表
|
|
||||||
export function listInvoiceReceiptApprove(query) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/ticket/approve/list',
|
|
||||||
method: 'post',
|
|
||||||
data: query
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询收票已审批列表
|
|
||||||
export function listInvoiceReceiptApproved(query) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/ticket/approved/list',
|
|
||||||
method: 'post',
|
|
||||||
data: query
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询收票详情
|
|
||||||
export function getInvoiceReceipt(id) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/ticket/' + id,
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询收票附件
|
|
||||||
export function getInvoiceReceiptAttachments(id,params) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/ticket/attachment/' + id,
|
|
||||||
method: 'get',
|
|
||||||
params
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
// 查询核销记录列表
|
|
||||||
export function listInvoiceWriteOff(query) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/invoice/writeoff/list',
|
|
||||||
method: 'get',
|
|
||||||
params: query
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询核销详情
|
|
||||||
export function getInvoiceWriteoff(id) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/invoice/writeoff/' + id,
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除核销记录
|
|
||||||
export function delInvoiceWriteoff(ids) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/invoice/writeoff/' + ids,
|
|
||||||
method: 'delete'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -1,81 +0,0 @@
|
||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
// 查询采购应付单列表
|
|
||||||
export function listPayable(query) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/payable/list',
|
|
||||||
method: 'post',
|
|
||||||
headers: { 'Content-Type': 'multipart/form-data' },
|
|
||||||
data: query
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询采购应付单详情
|
|
||||||
export function getPayable(id) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/payable/' + id,
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询付款计划列表
|
|
||||||
export function getPaymentPlan(payableBillId) {
|
|
||||||
return request({
|
|
||||||
url: `/finance/payable/plan/${payableBillId}`,
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新付款计划
|
|
||||||
export function updatePaymentPlan(payableBillId, data) {
|
|
||||||
return request({
|
|
||||||
url: `/finance/payable/plan/${payableBillId}`,
|
|
||||||
method: 'post',
|
|
||||||
data: data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 合并并发起付款
|
|
||||||
export function mergeAndInitiatePayment(data) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/payable/mergeAndInitiatePayment',
|
|
||||||
method: 'post',
|
|
||||||
data: data,
|
|
||||||
needLoading: true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 合并并发起收票
|
|
||||||
export function mergeAndInitiateReceipt(data) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/payable/mergeAndInitiateReceipt',
|
|
||||||
method: 'post',
|
|
||||||
data: data,
|
|
||||||
needLoading: true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// [PLACEHOLDER] 查询收票计划列表 - Endpoint to be confirmed by user
|
|
||||||
export function getReceivingTicketPlan(payableBillId) {
|
|
||||||
return request({
|
|
||||||
url: `/finance/ticket/plan/${payableBillId}`,
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// [PLACEHOLDER] 更新收票计划 - Endpoint to be confirmed by user
|
|
||||||
export function updateReceivingTicketPlan(payableBillId, data) {
|
|
||||||
return request({
|
|
||||||
url: `/finance/ticket/plan/${payableBillId}`,
|
|
||||||
method: 'post',
|
|
||||||
data: data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 同步付款计划至发票计划
|
|
||||||
export function syncToTicketPlan(payableBillId) {
|
|
||||||
return request({
|
|
||||||
url: `/finance/payable/plan/sync/${payableBillId}`,
|
|
||||||
method: 'post'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -1,210 +0,0 @@
|
||||||
import request from '@/utils/request'
|
|
||||||
import { tansParams } from "@/utils/ruoyi"
|
|
||||||
|
|
||||||
// 查询付款单列表
|
|
||||||
export function listPayment(query) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/payment/list',
|
|
||||||
method: 'post',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/x-www-form-urlencoded'
|
|
||||||
},
|
|
||||||
data: tansParams(query)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
export function exportPayment(query) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/payment/export',
|
|
||||||
method: 'post',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/x-www-form-urlencoded'
|
|
||||||
},
|
|
||||||
data: tansParams(query)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询付款单详细
|
|
||||||
export function getPayment(id) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/payment/' + id,
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询付款单附件
|
|
||||||
export function getPaymentAttachments(id, params) {
|
|
||||||
return request({
|
|
||||||
url: `/finance/payment/attachment/${id}`,
|
|
||||||
method: 'get',
|
|
||||||
params
|
|
||||||
})
|
|
||||||
}
|
|
||||||
export function deleteFile(id) {
|
|
||||||
return request({
|
|
||||||
url: `/finance/payment/attachment/${id}`,
|
|
||||||
method: 'delete'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 上传付款单附件
|
|
||||||
export function uploadPaymentAttachment(data) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/payment/uploadReceipt',
|
|
||||||
method: 'post',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'multipart/form-data'
|
|
||||||
},
|
|
||||||
data: data
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 退回付款单
|
|
||||||
export function returnPayment(id) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/payment/returnPayment/' + id,
|
|
||||||
method: 'delete'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 新增付款单
|
|
||||||
export function addPaymentFromPayable(data) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/payable/mergeAndInitiatePayment',
|
|
||||||
method: 'post',
|
|
||||||
data: data,
|
|
||||||
needLoading: true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
export function addPayment(data) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/payment/add',
|
|
||||||
method: 'post',
|
|
||||||
data: data,
|
|
||||||
needLoading: true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function handleRevoke(id) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/payment/revoke',
|
|
||||||
method: 'post',
|
|
||||||
data: {id: id},
|
|
||||||
needLoading: true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 申请付款
|
|
||||||
export function applyPaymentApi(data) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/payment/applyPayment',
|
|
||||||
method: 'post',
|
|
||||||
data: data,
|
|
||||||
needLoading: true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 申请退款
|
|
||||||
export function applyRefund(data) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/payment/applyRefund',
|
|
||||||
method: 'post',
|
|
||||||
data: data,
|
|
||||||
needLoading: true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
export function deletePayment(id) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/payment/remove',
|
|
||||||
method: 'post',
|
|
||||||
params:{ids:id},
|
|
||||||
needLoading: true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function applyRefundApprove(id) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/payment/applyRefundApprove',
|
|
||||||
method: 'post',
|
|
||||||
data: {id: id},
|
|
||||||
needLoading: true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询应付单列表 (用于新增付款单-非预付)
|
|
||||||
export function listPayableBills(query) {
|
|
||||||
return request({
|
|
||||||
url: 'finance/payable/list',
|
|
||||||
method: 'post',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/x-www-form-urlencoded'
|
|
||||||
},
|
|
||||||
data: query
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询采购订单列表 (用于新增付款单-预付)
|
|
||||||
export function listOrders(query) {
|
|
||||||
return request({
|
|
||||||
url: '/project/order/list',
|
|
||||||
method: 'post',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/x-www-form-urlencoded'
|
|
||||||
},
|
|
||||||
data: query
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询付款审批列表
|
|
||||||
export function listPaymentApprove(query) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/payment/approve/list',
|
|
||||||
method: 'post',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/x-www-form-urlencoded'
|
|
||||||
},
|
|
||||||
data: tansParams(query)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询已审批付款列表
|
|
||||||
export function listPaymentApproved(query) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/payment/approved/list',
|
|
||||||
method: 'post',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/x-www-form-urlencoded'
|
|
||||||
},
|
|
||||||
data: tansParams(query)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询付款单列表 (核销专用)
|
|
||||||
export function listPaymentForWriteOff(query) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/payment/write-off/list',
|
|
||||||
method: 'post',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/x-www-form-urlencoded'
|
|
||||||
},
|
|
||||||
data: tansParams(query)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 手工匹配核销
|
|
||||||
export function manualWriteOff(data) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/writeoff',
|
|
||||||
method: 'post',
|
|
||||||
data: data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 新增付款单
|
|
||||||
export function updatePaymentBill(data) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/payment/updatePaymentBill',
|
|
||||||
method: 'post',
|
|
||||||
data: data,
|
|
||||||
needLoading: true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
import request from '@/utils/request'
|
|
||||||
import {tansParams} from "@/utils/ruoyi";
|
|
||||||
|
|
||||||
// 查询付款退款待审批列表
|
|
||||||
export function listPaymentRefundApprove(query) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/payment/approve/list',
|
|
||||||
method: 'post',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/x-www-form-urlencoded'
|
|
||||||
},
|
|
||||||
data: query
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询付款退款已审批列表
|
|
||||||
export function listPaymentRefundApproved(query) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/payment/approved/list',
|
|
||||||
method: 'post',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/x-www-form-urlencoded'
|
|
||||||
},
|
|
||||||
params: query
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询付款退款详情
|
|
||||||
export function getPaymentRefund(id) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/paymentRefund/' + id,
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -1,122 +0,0 @@
|
||||||
import request from '@/utils/request'
|
|
||||||
import {tansParams} from "@/utils/ruoyi"
|
|
||||||
|
|
||||||
// 查询收票单列表
|
|
||||||
export function listReceipt(query) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/ticket/list',
|
|
||||||
method: 'post',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/x-www-form-urlencoded'
|
|
||||||
},
|
|
||||||
data: query
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询收票单详细
|
|
||||||
export function getReceipt(id) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/ticket/' + id,
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询收票单附件
|
|
||||||
export function getReceiptAttachments(id, params) {
|
|
||||||
return request({
|
|
||||||
url: `/finance/ticket/attachment/${id}`,
|
|
||||||
method: 'get',
|
|
||||||
params
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 上传收票单附件
|
|
||||||
export function uploadReceiptAttachment(data) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/ticket/uploadReceipt',
|
|
||||||
method: 'post',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'multipart/form-data'
|
|
||||||
},
|
|
||||||
data: data,
|
|
||||||
needLoading: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 退回收票单
|
|
||||||
export function redRush(id) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/ticket/applyRefund/' + id,
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function returnReceipt(id) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/ticket/return/' + id,
|
|
||||||
method: 'delete'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 新增收票单
|
|
||||||
export function addReceipt(data) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/payable/mergeAndInitiateReceipt',
|
|
||||||
method: 'post',
|
|
||||||
data: data,
|
|
||||||
needLoading: true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 撤销收票单
|
|
||||||
export function revokeReceipt(id) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/ticket/revoke/' + id,
|
|
||||||
method: 'put'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 申请红冲(带附件)
|
|
||||||
export function applyRedRush(data) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/ticket/applyRefund',
|
|
||||||
method: 'post',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'multipart/form-data'
|
|
||||||
},
|
|
||||||
data: data,
|
|
||||||
needLoading: true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// 查询收款审批列表
|
|
||||||
export function listReceiptApprove(query) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/receipt/approve/list',
|
|
||||||
method: 'post',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/x-www-form-urlencoded'
|
|
||||||
},
|
|
||||||
data: query
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询已审批收款列表
|
|
||||||
export function listReceiptApproved(query) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/receipt/approved/list',
|
|
||||||
method: 'post',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/x-www-form-urlencoded'
|
|
||||||
},
|
|
||||||
data: query
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询收款单详细
|
|
||||||
export function getReceiptDetail(id) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/receipt/' + id,
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,81 +0,0 @@
|
||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
// 查询销售应收单列表
|
|
||||||
export function listReceivable(query) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/receivable/list',
|
|
||||||
method: 'post',
|
|
||||||
headers: { 'Content-Type': 'multipart/form-data' },
|
|
||||||
data: query
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询销售应收单详情
|
|
||||||
export function getReceivable(id) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/receivable/' + id,
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询收款计划列表
|
|
||||||
export function getReceiptPlan(receivableBillId) {
|
|
||||||
return request({
|
|
||||||
url: `/finance/receivable/plan/${receivableBillId}`,
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新收款计划
|
|
||||||
export function updateReceiptPlan(receivableBillId, data) {
|
|
||||||
return request({
|
|
||||||
url: `/finance/receivable/plan/${receivableBillId}`,
|
|
||||||
method: 'post',
|
|
||||||
data: data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 合并并发起收款
|
|
||||||
export function mergeAndInitiateReceipt(data) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/receivable/mergeAndInitiateReceipt',
|
|
||||||
method: 'post',
|
|
||||||
data: data,
|
|
||||||
needLoading:true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 合并并发起开票
|
|
||||||
export function mergeAndInitiateInvoice(data) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/receivable/mergeAndInitiateInvoice',
|
|
||||||
method: 'post',
|
|
||||||
data: data,
|
|
||||||
needLoading:true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询开票计划列表
|
|
||||||
export function getInvoicePlan(receivableBillId) {
|
|
||||||
return request({
|
|
||||||
url: `/finance/receivable/invoice/plan/${receivableBillId}`,
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新开票计划
|
|
||||||
export function updateInvoicePlan(receivableBillId, data) {
|
|
||||||
return request({
|
|
||||||
url: `/finance/receivable/invoice/plan/${receivableBillId}`,
|
|
||||||
method: 'post',
|
|
||||||
data: data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 同步收款计划至开票计划
|
|
||||||
export function syncToInvoicePlan(receivableBillId) {
|
|
||||||
return request({
|
|
||||||
url: `/finance/receivable/plan/sync/${receivableBillId}`,
|
|
||||||
method: 'post'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
// 查询销售核销记录列表
|
|
||||||
export function listReceivableWriteOff(query) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/receivable/writeoff/list',
|
|
||||||
method: 'get',
|
|
||||||
params: query
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询销售核销详情
|
|
||||||
export function getReceivableWriteOff(id) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/receivable/writeoff/' + id,
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除销售核销记录
|
|
||||||
export function delReceivableWriteOff(ids) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/receivable/writeoff/' + ids,
|
|
||||||
method: 'delete'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -1,130 +0,0 @@
|
||||||
import request from '@/utils/request'
|
|
||||||
import {tansParams} from "@/utils/ruoyi"
|
|
||||||
|
|
||||||
// 查询收款单列表
|
|
||||||
export function listReceive(query) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/receipt/list',
|
|
||||||
method: 'post',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/x-www-form-urlencoded'
|
|
||||||
},
|
|
||||||
data: query
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询收款单详细
|
|
||||||
export function getReceive(id) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/receipt/' + id,
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询收款单附件
|
|
||||||
export function getReceiveAttachments(id, params) {
|
|
||||||
return request({
|
|
||||||
url: `/finance/receipt/attachment/${id}`,
|
|
||||||
method: 'get',
|
|
||||||
params
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 上传收款单附件
|
|
||||||
export function uploadReceiveAttachment(data) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/receipt/uploadReceipt',
|
|
||||||
method: 'post',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'multipart/form-data'
|
|
||||||
},
|
|
||||||
data: data,
|
|
||||||
needLoading: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 申请红冲
|
|
||||||
export function redRush(id) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/receipt/applyRefund/' + id,
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 退回收款单
|
|
||||||
export function returnReceive(id) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/receipt/returnReceivable/' + id,
|
|
||||||
method: 'delete'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 新增收款单 (Calls Receivable Merge Logic)
|
|
||||||
export function mergeReceivable(data) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/receivable/mergeAndInitiateReceipt',
|
|
||||||
method: 'post',
|
|
||||||
data: data,
|
|
||||||
needLoading: true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
export function addReceipt(data) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/receipt/insert',
|
|
||||||
method: 'post',
|
|
||||||
data: data,
|
|
||||||
needLoading: true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
export function applyReceipt(data) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/receipt/applyReceipt',
|
|
||||||
method: 'post',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/x-www-form-urlencoded'
|
|
||||||
},
|
|
||||||
data: data,
|
|
||||||
needLoading: true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 申请退款
|
|
||||||
export function submitRefund(data) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/receipt/applyRefund',
|
|
||||||
method: 'post',
|
|
||||||
data: data,
|
|
||||||
needLoading: true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询收款单列表 (核销专用)
|
|
||||||
export function listReceiptForWriteOff(query) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/receipt/write-off/list',
|
|
||||||
method: 'post',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/x-www-form-urlencoded'
|
|
||||||
},
|
|
||||||
data: tansParams(query)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 手工匹配核销
|
|
||||||
export function manualReceiptWriteOff(data) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/receivable/writeoff',
|
|
||||||
method: 'post',
|
|
||||||
data: data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 撤销收款单
|
|
||||||
export function revokeReceipt(id) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/receipt/revoke',
|
|
||||||
method: 'post',
|
|
||||||
data: {id: id},
|
|
||||||
needLoading: true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
// 查询项目报表列表
|
|
||||||
export function listReport(query) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/report/list',
|
|
||||||
method: 'post',
|
|
||||||
headers: { 'Content-Type': 'multipart/form-data' },
|
|
||||||
data: query
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询供货商维度报表列表
|
|
||||||
export function listSupplierReport(query) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/report/listSupplier',
|
|
||||||
method: 'post',
|
|
||||||
headers: { 'Content-Type': 'multipart/form-data' },
|
|
||||||
data: query
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
// 查询核销记录列表
|
|
||||||
export function listWriteOff(query) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/writeoff/list',
|
|
||||||
method: 'get',
|
|
||||||
params: query
|
|
||||||
})
|
|
||||||
}
|
|
||||||
export function listTicketWriteOff(query) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/ticketWriteoff/list',
|
|
||||||
method: 'get',
|
|
||||||
params: query
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询核销详情
|
|
||||||
export function getWriteOff(id) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/writeoff/' + id,
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
export function getTicketWriteoff(id) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/ticketWriteoff/' + id,
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除核销记录
|
|
||||||
export function delWriteOff(ids) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/writeoff/' + ids,
|
|
||||||
method: 'delete'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
export function delTicketWriteoff(ids) {
|
|
||||||
return request({
|
|
||||||
url: '/finance/ticketWriteoff/' + ids,
|
|
||||||
method: 'delete'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -17,14 +17,6 @@ export function listCompletedFlows(data) {
|
||||||
data: data
|
data: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// 按业务单号查询待办记录(查看申请详情用)
|
|
||||||
export function listApplyFlows(data) {
|
|
||||||
return request({
|
|
||||||
url: '/flow/todo/apply-list',
|
|
||||||
method: 'post',
|
|
||||||
data: data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// 通用审批
|
// 通用审批
|
||||||
export function approveTask(data) {
|
export function approveTask(data) {
|
||||||
return request({
|
return request({
|
||||||
|
|
|
||||||
|
|
@ -52,23 +52,6 @@ export function recallDelivery(id) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 提交出库撤回审批(跨天发货记录)
|
|
||||||
export function recallApply(id, reason, amountChanged) {
|
|
||||||
return request({
|
|
||||||
url: '/inventory/delivery/vue/recall/apply',
|
|
||||||
method: 'post',
|
|
||||||
data: {id, reason, amountChanged}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 按发货记录 id 检查关联财务单据的审批状态(撤回/作废按钮前置校验)
|
|
||||||
export function checkRecallByDelivery(deliveryId) {
|
|
||||||
return request({
|
|
||||||
url: '/inventory/delivery/vue/recall/check-by-delivery/' + deliveryId,
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 导出采购合同
|
// 导出采购合同
|
||||||
export function exportDelivery(query) {
|
export function exportDelivery(query) {
|
||||||
return request({
|
return request({
|
||||||
|
|
@ -97,15 +80,6 @@ export function listProductSn(query) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询仅维保订单发货可续用的SN(关联项目同产品编码的已发货SN)
|
|
||||||
export function maintenanceSn(query) {
|
|
||||||
return request({
|
|
||||||
url: '/inventory/delivery/vue/maintenanceSn',
|
|
||||||
method: 'get',
|
|
||||||
params: query
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function removeDelivery(id) {
|
export function removeDelivery(id) {
|
||||||
return request({
|
return request({
|
||||||
url: '/inventory/delivery/vue/' + id,
|
url: '/inventory/delivery/vue/' + id,
|
||||||
|
|
|
||||||
|
|
@ -71,23 +71,6 @@ export function recallExecution(id) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 提交撤单审批申请
|
|
||||||
export function recallExecutionApply(id, reason, amountChanged) {
|
|
||||||
return request({
|
|
||||||
url: '/inventory/execution/vue/recall/apply',
|
|
||||||
method: 'post',
|
|
||||||
data: { id, reason, amountChanged }
|
|
||||||
})
|
|
||||||
}
|
|
||||||
export function exportExecution(data) {
|
|
||||||
return request({
|
|
||||||
url: `/inventory/execution/vue/export`,
|
|
||||||
method: 'post',
|
|
||||||
data: { data },
|
|
||||||
headers: { 'Content-Type': 'multipart/form-data' },
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询出库预览信息
|
// 查询出库预览信息
|
||||||
export function getCheckOutPreview(data) {
|
export function getCheckOutPreview(data) {
|
||||||
return request({
|
return request({
|
||||||
|
|
|
||||||
|
|
@ -85,30 +85,3 @@ export function getOuterLog(query) {
|
||||||
params: query
|
params: query
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询在途库存
|
|
||||||
export function getPurchaseStock(query) {
|
|
||||||
return request({
|
|
||||||
url: '/inventory/info/vue/purchase-stock',
|
|
||||||
method: 'get',
|
|
||||||
params: query
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询锁单
|
|
||||||
export function getBindOrder(query) {
|
|
||||||
return request({
|
|
||||||
url: '/inventory/info/vue/bind-order',
|
|
||||||
method: 'get',
|
|
||||||
params: query
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询在库现存
|
|
||||||
export function getInventoryInner(query) {
|
|
||||||
return request({
|
|
||||||
url: '/inventory/info/vue/inventory-inner',
|
|
||||||
method: 'get',
|
|
||||||
params: query
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -19,15 +19,6 @@ export function getInner(id) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询入库单产品信息列表
|
|
||||||
export function listInnerInventoryInfo(id, query) {
|
|
||||||
return request({
|
|
||||||
url: `${VUE_APP_API_URL}/${id}/inventory-info/list`,
|
|
||||||
method: 'get',
|
|
||||||
params: query
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 新增入库单信息
|
// 新增入库单信息
|
||||||
export function addInner(data) {
|
export function addInner(data) {
|
||||||
return request({
|
return request({
|
||||||
|
|
|
||||||
|
|
@ -79,14 +79,6 @@ export function exportDownloadTemplate() {
|
||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// 下载带列表数据的发货导入模板
|
|
||||||
export function exportDownloadTemplateData(data) {
|
|
||||||
return request({
|
|
||||||
url: '/inventory/outer/importTemplateData',
|
|
||||||
method: 'post',
|
|
||||||
data: data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
export function importSnData(formData) {
|
export function importSnData(formData) {
|
||||||
return request({
|
return request({
|
||||||
url: '/inventory/outer/vue/importData',
|
url: '/inventory/outer/vue/importData',
|
||||||
|
|
@ -97,13 +89,3 @@ export function importSnData(formData) {
|
||||||
data: formData
|
data: formData
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
export function assignDeliverySnData(formData) {
|
|
||||||
return request({
|
|
||||||
url: '/inventory/outer/vue/assignDeliveryData',
|
|
||||||
method: 'post',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'multipart/form-data'
|
|
||||||
},
|
|
||||||
data: formData
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,5 @@
|
||||||
import request from '@/utils/request'
|
import request from '@/utils/request'
|
||||||
|
|
||||||
function createLoginFormData(data) {
|
|
||||||
const formData = new FormData()
|
|
||||||
Object.keys(data).forEach(key => formData.append(key, data[key]))
|
|
||||||
return formData
|
|
||||||
}
|
|
||||||
|
|
||||||
// 登录方法 - 基于 Session 认证,使用 FormData 格式
|
// 登录方法 - 基于 Session 认证,使用 FormData 格式
|
||||||
export function login(username, password, code, rememberMe) {
|
export function login(username, password, code, rememberMe) {
|
||||||
const formData = new FormData()
|
const formData = new FormData()
|
||||||
|
|
@ -15,40 +9,6 @@ export function login(username, password, code, rememberMe) {
|
||||||
formData.append('rememberMe', rememberMe || false)
|
formData.append('rememberMe', rememberMe || false)
|
||||||
return request({
|
return request({
|
||||||
url: '/login',
|
url: '/login',
|
||||||
headers: {
|
|
||||||
isToken: false,
|
|
||||||
'Content-Type': 'multipart/form-data',
|
|
||||||
repeatSubmit: false,
|
|
||||||
allowWarning: true
|
|
||||||
},
|
|
||||||
method: 'post',
|
|
||||||
data: formData
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function resetLoginPwd(data) {
|
|
||||||
const formData = createLoginFormData({
|
|
||||||
username: data.username,
|
|
||||||
newPassword: data.newPassword,
|
|
||||||
confirmPassword: data.confirmPassword,
|
|
||||||
emailCode: data.emailCode
|
|
||||||
})
|
|
||||||
return request({
|
|
||||||
url: '/login/resetPwd',
|
|
||||||
headers: {
|
|
||||||
isToken: false,
|
|
||||||
'Content-Type': 'multipart/form-data',
|
|
||||||
repeatSubmit: false
|
|
||||||
},
|
|
||||||
method: 'post',
|
|
||||||
data: formData
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function sendResetPwdEmailCode(username) {
|
|
||||||
const formData = createLoginFormData({ username })
|
|
||||||
return request({
|
|
||||||
url: '/login/sendResetPwdEmailCode',
|
|
||||||
headers: {
|
headers: {
|
||||||
isToken: false,
|
isToken: false,
|
||||||
'Content-Type': 'multipart/form-data',
|
'Content-Type': 'multipart/form-data',
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ export function delOrder(id) {
|
||||||
export function exportOrder(query) {
|
export function exportOrder(query) {
|
||||||
return request({
|
return request({
|
||||||
url: `${baseURL}/export`,
|
url: `${baseURL}/export`,
|
||||||
method: 'get',
|
method: 'post',
|
||||||
params: query
|
params: query
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,40 +1,28 @@
|
||||||
import request from '@/utils/request'
|
import request from '@/utils/request'
|
||||||
|
|
||||||
function normalizeSerialNumbers(input) {
|
// 查询产品信息
|
||||||
const values = Array.isArray(input) ? input : [input]
|
export function getProductInfo(serialNumber) {
|
||||||
return [...new Set(values
|
|
||||||
.map(item => (item || '').toString().trim())
|
|
||||||
.filter(Boolean))]
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildQueryPayload(input) {
|
|
||||||
const serialNumbers = normalizeSerialNumbers(input)
|
|
||||||
return {
|
|
||||||
serialNumber: serialNumbers[0] || '',
|
|
||||||
serialNumbers
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getProductInfo(serialNumberOrNumbers) {
|
|
||||||
return request({
|
return request({
|
||||||
url: '/manage/service/product',
|
url: '/manage/service/product',
|
||||||
method: 'post',
|
method: 'get',
|
||||||
data: buildQueryPayload(serialNumberOrNumbers)
|
params: { serialNumber }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getOrderInfo(serialNumberOrNumbers) {
|
// 查询相关合同信息
|
||||||
|
export function getOrderInfo(serialNumber) {
|
||||||
return request({
|
return request({
|
||||||
url: '/manage/service/order',
|
url: '/manage/service/order',
|
||||||
method: 'post',
|
method: 'get',
|
||||||
data: buildQueryPayload(serialNumberOrNumbers)
|
params: { serialNumber }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getWarrantyInfo(serialNumberOrNumbers) {
|
// 查询标准保修信息
|
||||||
|
export function getWarrantyInfo(serialNumber) {
|
||||||
return request({
|
return request({
|
||||||
url: '/manage/service/query',
|
url: '/manage/service/query',
|
||||||
method: 'post',
|
method: 'get',
|
||||||
data: buildQueryPayload(serialNumberOrNumbers)
|
params: { serialNumber }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -1,14 +1,11 @@
|
||||||
import request from '@/utils/request'
|
import request from '@/utils/request'
|
||||||
import { tansParams } from '@/utils/ruoyi'
|
|
||||||
|
|
||||||
// 查询项目管理列表
|
// 查询项目管理列表
|
||||||
export function listProject(query) {
|
export function listProject(query) {
|
||||||
return request({
|
return request({
|
||||||
url: '/sip/project/vue/list',
|
url: '/sip/project/vue/list',
|
||||||
method: 'post',
|
method: 'get',
|
||||||
data: query,
|
params: query
|
||||||
headers: { 'Content-Type': 'multipart/form-data' },
|
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -52,34 +49,6 @@ export function exportProject(query) {
|
||||||
return request({
|
return request({
|
||||||
url: '/sip/project/vue/export',
|
url: '/sip/project/vue/export',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: query,
|
params: query
|
||||||
transformRequest: [(params) => tansParams(params)],
|
|
||||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 项目收藏
|
|
||||||
export function addCollect(data) {
|
|
||||||
return request({
|
|
||||||
url: '/project/collect/add',
|
|
||||||
method: 'post',
|
|
||||||
data: data,
|
|
||||||
needLoading:true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
export function editJoinTrial(data) {
|
|
||||||
return request({
|
|
||||||
url: '/sip/project/vue/joinTrial',
|
|
||||||
method: 'put',
|
|
||||||
data: data,
|
|
||||||
needLoading:true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
export function exportSingle(id) {
|
|
||||||
return request({
|
|
||||||
url: `/sip/project/vue/joinTrial/export/${id}`,
|
|
||||||
method: 'get',
|
|
||||||
needLoading:true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -85,57 +85,3 @@ export function updateFinanceStatus(id, status) {
|
||||||
data: data
|
data: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询仅维保订单可关联的项目订单(仅正常订单且审批完成)
|
|
||||||
export function relatedCandidateList(query) {
|
|
||||||
return request({
|
|
||||||
url: '/project/order/vue/relatedCandidateList',
|
|
||||||
method: 'get',
|
|
||||||
params: query
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询产品配货备货明细
|
|
||||||
export function productMatchList(orderCode) {
|
|
||||||
return request({
|
|
||||||
url: '/project/order/vue/productMatchList',
|
|
||||||
method: 'get',
|
|
||||||
params: { orderCode }
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询产品配备货绑定信息
|
|
||||||
export function productMatchBindList(orderCode, productCode, params = {}) {
|
|
||||||
return request({
|
|
||||||
url: '/project/order/vue/productMatchBindList',
|
|
||||||
method: 'get',
|
|
||||||
params: { orderCode, productCode, ...params }
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 保存订单关联采购单
|
|
||||||
export function savePurchaseOrderMap(data) {
|
|
||||||
return request({
|
|
||||||
url: '/project/order/vue/purchaseOrderMap',
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询采购单SN码列表
|
|
||||||
export function purchaseSnList(purchaseNo, orderCode, productCode) {
|
|
||||||
return request({
|
|
||||||
url: '/project/order/vue/purchaseSnList',
|
|
||||||
method: 'get',
|
|
||||||
params: { purchaseNo, orderCode, productCode }
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 订单绑定SN码
|
|
||||||
export function bindOrderSnCodes(orderCode, productCode, purchaseNo, orderId, purchaseId, productSnList) {
|
|
||||||
return request({
|
|
||||||
url: '/project/order/vue/bindOrderSnCodes',
|
|
||||||
method: 'post',
|
|
||||||
data: { orderCode, productCode, purchaseNo, orderId, purchaseId, productSnList }
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -106,16 +106,6 @@ export function recallPurchaseorder(id) {
|
||||||
method: 'put'
|
method: 'put'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
export function exportPurchaseorder(data) {
|
|
||||||
return request({
|
|
||||||
url: '/sip/purchaseorder/export',
|
|
||||||
method: 'get',
|
|
||||||
params: data,
|
|
||||||
// headers: { 'Content-Type': 'multipart/form-data' },
|
|
||||||
needLoading: true
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询已审批采购单主表列表
|
// 查询已审批采购单主表列表
|
||||||
export function listApprovedPurchaseorder(query) {
|
export function listApprovedPurchaseorder(query) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import request from '@/utils/request'
|
import request from '@/utils/request'
|
||||||
import { tansParams } from '@/utils/ruoyi'
|
|
||||||
|
|
||||||
// 查询办事处信息列表
|
// 查询办事处信息列表
|
||||||
export function listAgent(query) {
|
export function listAgent(query) {
|
||||||
|
|
@ -49,8 +48,6 @@ export function exportAgent(query) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/agent/vue/export',
|
url: '/system/agent/vue/export',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: query,
|
params: query
|
||||||
transformRequest: [(params) => tansParams(params)],
|
|
||||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
// 查询公司信息列表
|
|
||||||
export function listCompanyInfo(query) {
|
|
||||||
return request({
|
|
||||||
url: '/sip/companyInfo/list',
|
|
||||||
method: 'get',
|
|
||||||
params: query
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询公司信息详细
|
|
||||||
export function getCompanyInfo(id) {
|
|
||||||
return request({
|
|
||||||
url: '/sip/companyInfo/' + id,
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 新增公司信息
|
|
||||||
export function addCompanyInfo(data) {
|
|
||||||
return request({
|
|
||||||
url: '/sip/companyInfo',
|
|
||||||
method: 'post',
|
|
||||||
data: data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 修改公司信息
|
|
||||||
export function updateCompanyInfo(data) {
|
|
||||||
return request({
|
|
||||||
url: '/sip/companyInfo',
|
|
||||||
method: 'put',
|
|
||||||
data: data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除公司信息
|
|
||||||
export function delCompanyInfo(id) {
|
|
||||||
return request({
|
|
||||||
url: '/sip/companyInfo/' + id,
|
|
||||||
method: 'delete'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import request from '@/utils/request'
|
import request from '@/utils/request'
|
||||||
import { tansParams } from '@/utils/ruoyi'
|
|
||||||
|
|
||||||
// 查询客户信息列表
|
// 查询客户信息列表
|
||||||
export function listCustomer(query) {
|
export function listCustomer(query) {
|
||||||
|
|
@ -49,8 +48,6 @@ export function exportCustomer(query) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/customer/vue/export',
|
url: '/system/customer/vue/export',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: query,
|
params: query
|
||||||
transformRequest: [(params) => tansParams(params)],
|
|
||||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import request from '@/utils/request'
|
import request from '@/utils/request'
|
||||||
import { tansParams } from '@/utils/ruoyi'
|
|
||||||
|
|
||||||
// 查询产品管理列表
|
// 查询产品管理列表
|
||||||
export function listProduct(query) {
|
export function listProduct(query) {
|
||||||
|
|
@ -49,9 +48,7 @@ export function exportProduct(query) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/product/export',
|
url: '/system/product/export',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: query,
|
params: query
|
||||||
transformRequest: [(params) => tansParams(params)],
|
|
||||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import request from '@/utils/request'
|
import request from '@/utils/request'
|
||||||
import { parseStrEmpty } from "@/utils/ruoyi";
|
import { parseStrEmpty } from "@/utils/ruoyi";
|
||||||
|
|
||||||
// 鏌ヨ鐢ㄦ埛鍒楄〃
|
// 查询用户列表
|
||||||
export function listUser(query) {
|
export function listUser(query) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/user/list',
|
url: '/system/user/list',
|
||||||
|
|
@ -10,7 +10,7 @@ export function listUser(query) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 鏌ヨ鐢ㄦ埛璇︾粏
|
// 查询用户详细
|
||||||
export function getUser(userId) {
|
export function getUser(userId) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/user/' + parseStrEmpty(userId),
|
url: '/system/user/' + parseStrEmpty(userId),
|
||||||
|
|
@ -18,7 +18,7 @@ export function getUser(userId) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 鏂板鐢ㄦ埛
|
// 新增用户
|
||||||
export function addUser(data) {
|
export function addUser(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/user/add',
|
url: '/system/user/add',
|
||||||
|
|
@ -30,7 +30,7 @@ export function addUser(data) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 淇敼鐢ㄦ埛
|
// 修改用户
|
||||||
export function updateUser(data) {
|
export function updateUser(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/user',
|
url: '/system/user',
|
||||||
|
|
@ -39,7 +39,7 @@ export function updateUser(data) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 鍒犻櫎鐢ㄦ埛
|
// 删除用户
|
||||||
export function delUser(userId) {
|
export function delUser(userId) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/user/' + userId,
|
url: '/system/user/' + userId,
|
||||||
|
|
@ -47,7 +47,7 @@ export function delUser(userId) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 鐢ㄦ埛瀵嗙爜閲嶇疆
|
// 用户密码重置
|
||||||
export function resetUserPwd(data) {
|
export function resetUserPwd(data) {
|
||||||
|
|
||||||
return request({
|
return request({
|
||||||
|
|
@ -60,7 +60,7 @@ export function resetUserPwd(data) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 鐢ㄦ埛鐘舵€佷慨鏀?
|
// 用户状态修改
|
||||||
export function changeUserStatus(userId, status) {
|
export function changeUserStatus(userId, status) {
|
||||||
const data = {
|
const data = {
|
||||||
userId,
|
userId,
|
||||||
|
|
@ -76,7 +76,7 @@ export function changeUserStatus(userId, status) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 鏌ヨ鐢ㄦ埛涓汉淇℃伅
|
// 查询用户个人信息
|
||||||
export function getUserProfile() {
|
export function getUserProfile() {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/user/profile/vue',
|
url: '/system/user/profile/vue',
|
||||||
|
|
@ -84,7 +84,7 @@ export function getUserProfile() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 淇敼鐢ㄦ埛涓汉淇℃伅
|
// 修改用户个人信息
|
||||||
export function updateUserProfile(data) {
|
export function updateUserProfile(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/user/profile',
|
url: '/system/user/profile',
|
||||||
|
|
@ -93,7 +93,7 @@ export function updateUserProfile(data) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 鐢ㄦ埛瀵嗙爜閲嶇疆
|
// 用户密码重置
|
||||||
export function updateUserPwd(data) {
|
export function updateUserPwd(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/user/profile/resetPwd',
|
url: '/system/user/profile/resetPwd',
|
||||||
|
|
@ -103,7 +103,7 @@ export function updateUserPwd(data) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 鐢ㄦ埛澶村儚涓婁紶
|
// 用户头像上传
|
||||||
export function uploadAvatar(data) {
|
export function uploadAvatar(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/user/profile/updateAvatar',
|
url: '/system/user/profile/updateAvatar',
|
||||||
|
|
@ -113,20 +113,7 @@ export function uploadAvatar(data) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getUserBotProfile() {
|
// 查询授权角色
|
||||||
return request({
|
|
||||||
url: '/system/user/profile/bot',
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function generateUserBotProfile() {
|
|
||||||
return request({
|
|
||||||
url: '/system/user/profile/bot/generate',
|
|
||||||
method: 'post'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// 鏌ヨ鎺堟潈瑙掕壊
|
|
||||||
export function getAuthRole(userId) {
|
export function getAuthRole(userId) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/user/vue/authRole/' + userId,
|
url: '/system/user/vue/authRole/' + userId,
|
||||||
|
|
@ -134,7 +121,7 @@ export function getAuthRole(userId) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 淇濆瓨鎺堟潈瑙掕壊
|
// 保存授权角色
|
||||||
export function updateAuthRole(data) {
|
export function updateAuthRole(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/user/authRole',
|
url: '/system/user/authRole',
|
||||||
|
|
@ -143,7 +130,7 @@ export function updateAuthRole(data) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 鏌ヨ閮ㄩ棬涓嬫媺鏍戠粨鏋?
|
// 查询部门下拉树结构
|
||||||
export function deptTreeSelect() {
|
export function deptTreeSelect() {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/user/deptTree',
|
url: '/system/user/deptTree',
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import request from '@/utils/request'
|
import request from '@/utils/request'
|
||||||
import { tansParams } from '@/utils/ruoyi'
|
|
||||||
|
|
||||||
// 查询仓库基础信息列表
|
// 查询仓库基础信息列表
|
||||||
export function listInfo(query) {
|
export function listInfo(query) {
|
||||||
|
|
@ -49,8 +48,6 @@ export function exportInfo(query) {
|
||||||
return request({
|
return request({
|
||||||
url: '/warehouse/info/export',
|
url: '/warehouse/info/export',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: query,
|
params: query
|
||||||
transformRequest: [(params) => tansParams(params)],
|
|
||||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 17 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 14 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 8.6 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 7.5 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 152 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 17 KiB |
|
|
@ -104,18 +104,6 @@
|
||||||
margin-left: 1px;
|
margin-left: 1px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 固定列覆盖层:强制不透明背景 + 提升层级,防止横向滚动时内容穿透固定列
|
|
||||||
.el-table__fixed,
|
|
||||||
.el-table__fixed-right {
|
|
||||||
background-color: #fff;
|
|
||||||
z-index: 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-table__fixed .el-table__cell,
|
|
||||||
.el-table__fixed-right .el-table__cell {
|
|
||||||
background-color: #fff;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 表单布局 **/
|
/** 表单布局 **/
|
||||||
|
|
|
||||||
|
|
@ -1,69 +0,0 @@
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<el-dialog :visible.sync="pdfPreviewVisible" width="80%" append-to-body top="5vh" title="PDF预览">
|
|
||||||
<iframe :src="currentPdfUrl" width="100%" height="600px" frameborder="0"></iframe>
|
|
||||||
</el-dialog>
|
|
||||||
|
|
||||||
<el-dialog :visible.sync="imagePreviewVisible" width="60%" append-to-body top="5vh" title="图片预览">
|
|
||||||
<img :src="currentImageUrl" style="width: 100%;max-height: 60vh" />
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: "GlobalFilePreview",
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
pdfPreviewVisible: false,
|
|
||||||
currentPdfUrl: '',
|
|
||||||
imagePreviewVisible: false,
|
|
||||||
currentImageUrl: ''
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
isPdf(filePath) {
|
|
||||||
return filePath && filePath.toLowerCase().endsWith('.pdf');
|
|
||||||
},
|
|
||||||
getFileBaseName(filePath) {
|
|
||||||
if (!filePath) return '';
|
|
||||||
const parts = filePath.split('/');
|
|
||||||
return parts[parts.length - 1] || '';
|
|
||||||
},
|
|
||||||
// 在线查看地址:后端以 inline 方式返回文件(图片/PDF 可直接在浏览器渲染)
|
|
||||||
getViewUrl(filePath, fileName) {
|
|
||||||
const resource = encodeURIComponent(filePath || '');
|
|
||||||
const name = encodeURIComponent(fileName || this.getFileBaseName(filePath));
|
|
||||||
return `${process.env.VUE_APP_BASE_API}/project/order/file/view?filePath=${resource}&fileName=${name}`;
|
|
||||||
},
|
|
||||||
handlePreview(attachment) {
|
|
||||||
if (!attachment || !attachment.filePath) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const filePath = attachment.filePath.toLowerCase();
|
|
||||||
const isImage = /\.(png|jpg|jpeg|gif)$/.test(filePath);
|
|
||||||
if (this.isPdf(filePath)) {
|
|
||||||
this.currentPdfUrl = this.getViewUrl(attachment.filePath, attachment.fileName);
|
|
||||||
this.pdfPreviewVisible = true;
|
|
||||||
} else if (isImage) {
|
|
||||||
this.currentImageUrl = this.getViewUrl(attachment.filePath, attachment.fileName);
|
|
||||||
this.imagePreviewVisible = true;
|
|
||||||
} else {
|
|
||||||
// 浏览器无法直接渲染的格式,改为新窗口打开(由浏览器决定预览或下载)
|
|
||||||
window.open(this.getViewUrl(attachment.filePath, attachment.fileName), '_blank');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
downloadFile(attachment){
|
|
||||||
if (attachment){
|
|
||||||
const link = document.createElement('a');
|
|
||||||
link.href = process.env.VUE_APP_BASE_API + "/common/download/resource?resource=" +attachment.filePath;
|
|
||||||
link.download = attachment.fileName || 'file';
|
|
||||||
link.style.display = 'none';
|
|
||||||
document.body.appendChild(link);
|
|
||||||
link.click();
|
|
||||||
document.body.removeChild(link);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
@ -183,8 +183,4 @@ export default {
|
||||||
background-color: #ccc;
|
background-color: #ccc;
|
||||||
margin: 3px auto;
|
margin: 3px auto;
|
||||||
}
|
}
|
||||||
.el-dropdown-menu{
|
|
||||||
max-height: 400px;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
<logo v-if="showLogo" :collapse="isCollapse" />
|
<logo v-if="showLogo" :collapse="isCollapse" />
|
||||||
<el-scrollbar :class="settings.sideTheme" wrap-class="scrollbar-wrapper">
|
<el-scrollbar :class="settings.sideTheme" wrap-class="scrollbar-wrapper">
|
||||||
<el-menu
|
<el-menu
|
||||||
ref="sideMenu"
|
|
||||||
:default-active="activeMenu"
|
:default-active="activeMenu"
|
||||||
:collapse="isCollapse"
|
:collapse="isCollapse"
|
||||||
:background-color="settings.sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground"
|
:background-color="settings.sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground"
|
||||||
|
|
@ -12,8 +11,6 @@
|
||||||
:active-text-color="settings.theme"
|
:active-text-color="settings.theme"
|
||||||
:collapse-transition="false"
|
:collapse-transition="false"
|
||||||
mode="vertical"
|
mode="vertical"
|
||||||
@open="handleMenuOpen"
|
|
||||||
@close="handleMenuClose"
|
|
||||||
>
|
>
|
||||||
<sidebar-item
|
<sidebar-item
|
||||||
v-for="(route, index) in sidebarRouters"
|
v-for="(route, index) in sidebarRouters"
|
||||||
|
|
@ -27,7 +24,6 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import pathLib from 'path'
|
|
||||||
import { mapGetters, mapState } from "vuex"
|
import { mapGetters, mapState } from "vuex"
|
||||||
import Logo from "./Logo"
|
import Logo from "./Logo"
|
||||||
import SidebarItem from "./SidebarItem"
|
import SidebarItem from "./SidebarItem"
|
||||||
|
|
@ -56,55 +52,6 @@ export default {
|
||||||
isCollapse() {
|
isCollapse() {
|
||||||
return !this.sidebar.opened
|
return !this.sidebar.opened
|
||||||
}
|
}
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
// 监听菜单折叠事件:当折叠"进销存管理"时同步折叠"出库管理"子菜单
|
|
||||||
handleMenuClose(index) {
|
|
||||||
// 在一级路由中找到当前折叠的菜单
|
|
||||||
const closedRoute = this.sidebarRouters.find(route => route.path === index)
|
|
||||||
if (!closedRoute || !closedRoute.children || !closedRoute.children.length) return
|
|
||||||
|
|
||||||
// 找到直属子级中名为"出库管理"的子菜单
|
|
||||||
const outerRoute = closedRoute.children.find(
|
|
||||||
child => !child.hidden && child.meta && child.meta.title === '出库管理'
|
|
||||||
)
|
|
||||||
if (!outerRoute) return
|
|
||||||
|
|
||||||
// 计算"出库管理"在 el-menu 中注册的 index(与展开逻辑保持一致)
|
|
||||||
const outerBasePath = pathLib.resolve(index, outerRoute.path)
|
|
||||||
const outerIndex = pathLib.resolve(outerBasePath, outerRoute.path)
|
|
||||||
|
|
||||||
if (this.$refs.sideMenu) {
|
|
||||||
this.$refs.sideMenu.close(outerIndex)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// 监听菜单展开事件:当展开的菜单含有"出库管理"子菜单时同步将其展开
|
|
||||||
handleMenuOpen(index) {
|
|
||||||
// 在一级路由中找到当前展开的菜单
|
|
||||||
const openedRoute = this.sidebarRouters.find(route => route.path === index)
|
|
||||||
if (!openedRoute || !openedRoute.children || !openedRoute.children.length) return
|
|
||||||
|
|
||||||
// 找到直属子级中名为"出库管理"且自身含子项的子菜单
|
|
||||||
const outerRoute = openedRoute.children.find(
|
|
||||||
child => !child.hidden && child.meta && child.meta.title === '出库管理'
|
|
||||||
)
|
|
||||||
if (!outerRoute) return
|
|
||||||
|
|
||||||
// 计算"出库管理"对应的 el-menu index
|
|
||||||
// SidebarItem 渲染嵌套菜单时:
|
|
||||||
// 先将 basePath 设为 path.resolve(parentPath, child.path)
|
|
||||||
// 再以新 basePath 计算 el-submenu :index = path.resolve(basePath, child.path)
|
|
||||||
// 因此需要对 child.path 做两次 resolve 才能与注册 index 对齐
|
|
||||||
const outerBasePath = pathLib.resolve(index, outerRoute.path)
|
|
||||||
const outerIndex = pathLib.resolve(outerBasePath, outerRoute.path)
|
|
||||||
|
|
||||||
// 延迟 300ms 展开,确保 el-submenu 子组件已完成挂载并向 el-menu 注册
|
|
||||||
setTimeout(() => {
|
|
||||||
if (this.$refs.sideMenu) {
|
|
||||||
this.$refs.sideMenu.open(outerIndex)
|
|
||||||
}
|
|
||||||
}, 300)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@ import './permission' // permission control
|
||||||
import { getDicts } from "@/api/system/dict/data"
|
import { getDicts } from "@/api/system/dict/data"
|
||||||
import { getConfigKey } from "@/api/system/config"
|
import { getConfigKey } from "@/api/system/config"
|
||||||
import { parseTime, resetForm, addDateRange, selectDictLabel, selectDictLabels, handleTree } from "@/utils/ruoyi"
|
import { parseTime, resetForm, addDateRange, selectDictLabel, selectDictLabels, handleTree } from "@/utils/ruoyi"
|
||||||
import { formatCurrency } from "@/utils"
|
|
||||||
// 分页组件
|
// 分页组件
|
||||||
import Pagination from "@/components/Pagination"
|
import Pagination from "@/components/Pagination"
|
||||||
// 自定义表格工具组件
|
// 自定义表格工具组件
|
||||||
|
|
@ -43,7 +42,6 @@ import DictData from '@/components/DictData'
|
||||||
Vue.prototype.getDicts = getDicts
|
Vue.prototype.getDicts = getDicts
|
||||||
Vue.prototype.getConfigKey = getConfigKey
|
Vue.prototype.getConfigKey = getConfigKey
|
||||||
Vue.prototype.parseTime = parseTime
|
Vue.prototype.parseTime = parseTime
|
||||||
Vue.prototype.formatCurrency = formatCurrency
|
|
||||||
Vue.prototype.resetForm = resetForm
|
Vue.prototype.resetForm = resetForm
|
||||||
Vue.prototype.addDateRange = addDateRange
|
Vue.prototype.addDateRange = addDateRange
|
||||||
Vue.prototype.selectDictLabel = selectDictLabel
|
Vue.prototype.selectDictLabel = selectDictLabel
|
||||||
|
|
|
||||||
|
|
@ -5,16 +5,12 @@ import NProgress from 'nprogress'
|
||||||
import 'nprogress/nprogress.css'
|
import 'nprogress/nprogress.css'
|
||||||
import { isPathMatch } from '@/utils/validate'
|
import { isPathMatch } from '@/utils/validate'
|
||||||
import { isRelogin } from '@/utils/request'
|
import { isRelogin } from '@/utils/request'
|
||||||
import { isServiceHost } from '@/utils/serviceHost'
|
|
||||||
|
|
||||||
NProgress.configure({ showSpinner: false })
|
NProgress.configure({ showSpinner: false })
|
||||||
|
|
||||||
const whiteList = ['/login', '/register', '/manage/service','/system/vendor/query','/system/partner/query']
|
const whiteList = ['/login', '/register', '/manage/service','/system/vendor/query','/system/partner/query']
|
||||||
|
|
||||||
const isWhiteList = (path) => {
|
const isWhiteList = (path) => {
|
||||||
if (path === '/' && isServiceHost()) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return whiteList.some(pattern => isPathMatch(pattern, path))
|
return whiteList.some(pattern => isPathMatch(pattern, path))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,12 +9,13 @@ const baseURL = process.env.VUE_APP_BASE_API
|
||||||
let downloadLoadingInstance
|
let downloadLoadingInstance
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
download(name, isDelete = true) {
|
name(name, isDelete = true) {
|
||||||
var url = baseURL + "/common/download?fileName=" + encodeURIComponent(name) + "&delete=" + isDelete
|
var url = baseURL + "/common/download?fileName=" + encodeURIComponent(name) + "&delete=" + isDelete
|
||||||
axios({
|
axios({
|
||||||
method: 'get',
|
method: 'get',
|
||||||
url: url,
|
url: url,
|
||||||
responseType: 'blob',
|
responseType: 'blob',
|
||||||
|
headers: { 'Authorization': 'Bearer ' + getToken() }
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
const isBlob = blobValidate(res.data)
|
const isBlob = blobValidate(res.data)
|
||||||
if (isBlob) {
|
if (isBlob) {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import Router from 'vue-router'
|
import Router from 'vue-router'
|
||||||
import { isServiceHost } from '@/utils/serviceHost'
|
|
||||||
|
|
||||||
Vue.use(Router)
|
Vue.use(Router)
|
||||||
|
|
||||||
|
|
@ -63,10 +62,10 @@ export const constantRoutes = [
|
||||||
hidden: true
|
hidden: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: isServiceHost() ? '/admin-root' : '',
|
path: '',
|
||||||
component: Layout,
|
component: Layout,
|
||||||
redirect: isServiceHost() ? undefined : 'index',
|
redirect: 'index',
|
||||||
children: isServiceHost() ? [] : [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'index',
|
path: 'index',
|
||||||
component: () => import('@/views/index'),
|
component: () => import('@/views/index'),
|
||||||
|
|
@ -95,46 +94,6 @@ export const constantRoutes = [
|
||||||
component: () => import('@/views/approve/approved_order/index'),
|
component: () => import('@/views/approve/approved_order/index'),
|
||||||
hidden: true
|
hidden: true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: 'paymentLog',
|
|
||||||
component: () => import('@/views/approve/finance/payment/approved/index'),
|
|
||||||
hidden: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'paymentRedLog',
|
|
||||||
component: () => import('@/views/approve/finance/paymentRefund/approved/index'),
|
|
||||||
hidden: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'invoiceRedLog',
|
|
||||||
component: () => import('@/views/approve/finance/invoiceRed/approved/index'),
|
|
||||||
hidden: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'invoiceLog',
|
|
||||||
component: () => import('@/views/approve/finance/invoiceReceipt/approved/index'),
|
|
||||||
hidden: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'receiptLog',
|
|
||||||
component: () => import('@/views/approve/finance/receipt/approved/index.vue'),
|
|
||||||
hidden: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'receiptRefoundLog',
|
|
||||||
component: () => import('@/views/approve/finance/receiptRefound/approved/index.vue'),
|
|
||||||
hidden: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'receivableInvoiceLog',
|
|
||||||
component: () => import('@/views/approve/finance/receivableInvoice/approved/index.vue'),
|
|
||||||
hidden: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'receivableInvoiceRefundLog',
|
|
||||||
component: () => import('@/views/approve/finance/receivableInvoiceRefund/approved/index.vue'),
|
|
||||||
hidden: true
|
|
||||||
},
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -153,11 +112,6 @@ export const constantRoutes = [
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
{
|
|
||||||
path: isServiceHost() ? '/' : '/service-host-root',
|
|
||||||
component: () => import('@/views/manage/service/index'),
|
|
||||||
hidden: true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: '/manage/service',
|
path: '/manage/service',
|
||||||
component: () => import('@/views/manage/service/index'),
|
component: () => import('@/views/manage/service/index'),
|
||||||
|
|
@ -210,31 +164,6 @@ export const dynamicRoutes = [
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: '/finance',
|
|
||||||
component: Layout,
|
|
||||||
redirect: 'noRedirect',
|
|
||||||
name: 'Finance',
|
|
||||||
meta: {
|
|
||||||
title: '财务管理',
|
|
||||||
icon: 'money'
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: 'payment',
|
|
||||||
component: () => import('@/views/finance/payment/index'),
|
|
||||||
name: 'Payment',
|
|
||||||
meta: { title: '付款单', icon: 'form' }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'charge',
|
|
||||||
component: () => import('@/views/finance/charge/index'),
|
|
||||||
name: 'Charge',
|
|
||||||
meta: { title: '财务计收', icon: 'money' },
|
|
||||||
permissions: ['finance:charge:list']
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: '/inventory/execution',
|
path: '/inventory/execution',
|
||||||
component: Layout,
|
component: Layout,
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ const user = {
|
||||||
const rememberMe = userInfo.rememberMe
|
const rememberMe = userInfo.rememberMe
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
login(username, password, code, rememberMe).then(res => {
|
login(username, password, code, rememberMe).then(res => {
|
||||||
resolve(res)
|
resolve()
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
reject(error)
|
reject(error)
|
||||||
})
|
})
|
||||||
|
|
@ -60,16 +60,17 @@ const user = {
|
||||||
},
|
},
|
||||||
|
|
||||||
// 获取用户信息
|
// 获取用户信息
|
||||||
GetInfo({ commit }) {
|
GetInfo({ commit, state }) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
getInfo().then(res => {
|
getInfo().then(res => {
|
||||||
|
// 后端返回的数据在 res.data 中
|
||||||
const data = res.data || res
|
const data = res.data || res
|
||||||
const user = data.user
|
const user = data.user
|
||||||
let avatar = user.avatar? '/common/download/resource?resource='+encodeURIComponent(user.avatar) : ""
|
let avatar = user.avatar? '/common/download/resource?resource='+encodeURIComponent(user.avatar) : ""
|
||||||
if (!isHttp(avatar)) {
|
if (!isHttp(avatar)) {
|
||||||
avatar = (isEmpty(avatar)) ? defAva : process.env.VUE_APP_BASE_API + avatar
|
avatar = (isEmpty(avatar)) ? defAva : process.env.VUE_APP_BASE_API + avatar
|
||||||
}
|
}
|
||||||
if (data.roles && data.roles.length > 0) {
|
if (data.roles && data.roles.length > 0) { // 验证返回的roles是否是一个非空数组
|
||||||
commit('SET_ROLES', data.roles)
|
commit('SET_ROLES', data.roles)
|
||||||
commit('SET_PERMISSIONS', data.permissions)
|
commit('SET_PERMISSIONS', data.permissions)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -81,11 +82,13 @@ const user = {
|
||||||
commit('SET_NAME', user.loginName)
|
commit('SET_NAME', user.loginName)
|
||||||
commit('SET_NICK_NAME', user.userName)
|
commit('SET_NICK_NAME', user.userName)
|
||||||
commit('SET_AVATAR', avatar)
|
commit('SET_AVATAR', avatar)
|
||||||
|
/* 初始密码提示 */
|
||||||
if(data.isDefaultModifyPwd) {
|
if(data.isDefaultModifyPwd) {
|
||||||
MessageBox.confirm('您的密码还是初始密码,请修改密码!', '安全提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => {
|
MessageBox.confirm('您的密码还是初始密码,请修改密码!', '安全提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => {
|
||||||
router.push({ name: 'Profile', params: { activeTab: 'resetPwd' } })
|
router.push({ name: 'Profile', params: { activeTab: 'resetPwd' } })
|
||||||
}).catch(() => {})
|
}).catch(() => {})
|
||||||
}
|
}
|
||||||
|
/* 过期密码提示 */
|
||||||
if(!data.isDefaultModifyPwd && data.isPasswordExpired) {
|
if(!data.isDefaultModifyPwd && data.isPasswordExpired) {
|
||||||
MessageBox.confirm('您的密码已过期,请尽快修改密码!', '安全提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => {
|
MessageBox.confirm('您的密码已过期,请尽快修改密码!', '安全提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => {
|
||||||
router.push({ name: 'Profile', params: { activeTab: 'resetPwd' } })
|
router.push({ name: 'Profile', params: { activeTab: 'resetPwd' } })
|
||||||
|
|
@ -99,7 +102,7 @@ const user = {
|
||||||
},
|
},
|
||||||
|
|
||||||
// 退出系统 - 基于 Session 认证
|
// 退出系统 - 基于 Session 认证
|
||||||
LogOut({ commit }) {
|
LogOut({ commit, state }) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
logout().then(() => {
|
logout().then(() => {
|
||||||
commit('SET_ROLES', [])
|
commit('SET_ROLES', [])
|
||||||
|
|
|
||||||
|
|
@ -19,17 +19,17 @@ export function toFixed(value, dp = DEFAULT_DP) {
|
||||||
|
|
||||||
// 加法
|
// 加法
|
||||||
export function add(a, b, dp = DEFAULT_DP) {
|
export function add(a, b, dp = DEFAULT_DP) {
|
||||||
return D(a).plus(D(b)).toDecimalPlaces(dp).toNumber()
|
return D(a).plus(b).toDecimalPlaces(dp).toNumber()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 减法
|
// 减法
|
||||||
export function sub(a, b, dp = DEFAULT_DP) {
|
export function sub(a, b, dp = DEFAULT_DP) {
|
||||||
return D(a).minus(D(b)).toDecimalPlaces(dp).toNumber()
|
return D(a).minus(b).toDecimalPlaces(dp).toNumber()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 乘法
|
// 乘法
|
||||||
export function mul(a, b, dp = DEFAULT_DP) {
|
export function mul(a, b, dp = DEFAULT_DP) {
|
||||||
return D(a).times(D(b)).toDecimalPlaces(dp).toNumber()
|
return D(a).times(b).toDecimalPlaces(dp).toNumber()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 除法
|
// 除法
|
||||||
|
|
|
||||||
|
|
@ -14,10 +14,7 @@ export function formatDate(cellValue) {
|
||||||
var seconds = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()
|
var seconds = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()
|
||||||
return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds
|
return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds
|
||||||
}
|
}
|
||||||
export function formatCurrency(value) {
|
|
||||||
if (value == null) return '0.00';
|
|
||||||
return Number(value).toLocaleString('en-US', {minimumFractionDigits: 2, maximumFractionDigits: 2});
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* @param {number} time
|
* @param {number} time
|
||||||
* @param {string} option
|
* @param {string} option
|
||||||
|
|
|
||||||
|
|
@ -110,8 +110,6 @@ service.interceptors.response.use(res => {
|
||||||
} else if (code === 601) {
|
} else if (code === 601) {
|
||||||
Message({ message: msg, type: 'warning' })
|
Message({ message: msg, type: 'warning' })
|
||||||
return Promise.reject('error')
|
return Promise.reject('error')
|
||||||
} else if (code === 301 && res.config.headers && res.config.headers.allowWarning) {
|
|
||||||
return res.data
|
|
||||||
} else if (code !== 200) {
|
} else if (code !== 200) {
|
||||||
Notification.error({ title: msg })
|
Notification.error({ title: msg })
|
||||||
return Promise.reject('error')
|
return Promise.reject('error')
|
||||||
|
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
const serviceHosts = (process.env.VUE_APP_SERVICE_HOST || '')
|
|
||||||
.split(',')
|
|
||||||
.map(host => host.trim().toLowerCase())
|
|
||||||
.filter(Boolean)
|
|
||||||
|
|
||||||
export function isServiceHost(hostname) {
|
|
||||||
const currentHost = (hostname || (typeof window !== 'undefined' ? window.location.hostname : '') || '')
|
|
||||||
.trim()
|
|
||||||
.toLowerCase()
|
|
||||||
|
|
||||||
return currentHost !== '' && serviceHosts.includes(currentHost)
|
|
||||||
}
|
|
||||||
|
|
@ -1,359 +0,0 @@
|
||||||
<template>
|
|
||||||
<el-dialog
|
|
||||||
title="订单撤回审批"
|
|
||||||
:visible="dialogVisible"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
width="80%"
|
|
||||||
top="5vh"
|
|
||||||
append-to-body
|
|
||||||
@update:visible="handleVisibleChange"
|
|
||||||
>
|
|
||||||
<div v-loading="loading" style="max-height: 70vh; overflow-y: auto;">
|
|
||||||
<div class="approve-container">
|
|
||||||
<ApproveLayout ref="approveLayout" title="紫光汇智信息技术有限公司">
|
|
||||||
<template #default>
|
|
||||||
<div style="display: flex;align-items: center;justify-content: center;">
|
|
||||||
<span style="margin-left: 10px;color: black;font-size: 30px">
|
|
||||||
紫光汇智信息技术有限公司订单撤回审批
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<el-form ref="orderForm" :model="order" label-width="120px" class="mb20">
|
|
||||||
<h3 class="section-title">订单信息</h3>
|
|
||||||
<order-info-display
|
|
||||||
:order-data.sync="order"
|
|
||||||
/>
|
|
||||||
</el-form>
|
|
||||||
|
|
||||||
<h3 class="section-title">配置信息</h3>
|
|
||||||
<config-info
|
|
||||||
:order-data="order"
|
|
||||||
class="mb20"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<template #footer>
|
|
||||||
<p>{{ order.projectCode }}-{{ order.orderCode }}-Rev.{{ order.versionCode }}</p>
|
|
||||||
</template>
|
|
||||||
</ApproveLayout>
|
|
||||||
|
|
||||||
<!-- 撤单信息 -->
|
|
||||||
<el-form label-width="120px" class="mb20">
|
|
||||||
<h3 class="section-title">撤单信息</h3>
|
|
||||||
<el-form-item label="撤单原因:">
|
|
||||||
<el-input :value="reason" readonly type="textarea" :rows="2" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="金额是否变化:">
|
|
||||||
<el-input :value="amountChanged || '—'" readonly />
|
|
||||||
</el-form-item>
|
|
||||||
<el-row>
|
|
||||||
<el-col :span="8">
|
|
||||||
<el-form-item label="出库状态:">
|
|
||||||
<dict-tag :options="dict.type.execution_outer_status" :value="order.outerStatus"/>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="8">
|
|
||||||
<el-form-item label="发货状态:">
|
|
||||||
<dict-tag :options="dict.type.execution_delivery_status" :value="order.deliveryStatus"/>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="8">
|
|
||||||
<el-form-item label="签收状态:">
|
|
||||||
<dict-tag :options="dict.type.execution_sign_status" :value="order.signStatus"/>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</el-form>
|
|
||||||
|
|
||||||
<!-- 流转过程 -->
|
|
||||||
<el-tabs v-model="activeTab" class="approve-tabs">
|
|
||||||
<el-tab-pane label="流转过程" name="process">
|
|
||||||
<div class="process-container">
|
|
||||||
<el-tabs :value="activeVersionTab" @input="handleVersionTabChange" type="card" v-if="uniqueVersions.length > 0">
|
|
||||||
<el-tab-pane
|
|
||||||
v-for="version in uniqueVersions"
|
|
||||||
:key="version"
|
|
||||||
:label="'版本号Rev.' + version"
|
|
||||||
:name="version">
|
|
||||||
<el-timeline>
|
|
||||||
<el-timeline-item
|
|
||||||
v-for="log in groupedApproveLogs[version]"
|
|
||||||
:key="log.id"
|
|
||||||
:timestamp="log.approveTime"
|
|
||||||
placement="top">
|
|
||||||
<el-card>
|
|
||||||
<h4>{{ log.approveOpinion }}</h4>
|
|
||||||
<p><b>操作人:</b> {{ log.approveUserName }}</p>
|
|
||||||
<p><b>审批状态:</b> <el-tag :type="getStatusTagType(log.approveStatus)" size="small">{{ getStatusText(log.approveStatus) }}</el-tag></p>
|
|
||||||
</el-card>
|
|
||||||
</el-timeline-item>
|
|
||||||
</el-timeline>
|
|
||||||
</el-tab-pane>
|
|
||||||
</el-tabs>
|
|
||||||
<div v-else>暂无流转过程数据。</div>
|
|
||||||
</div>
|
|
||||||
</el-tab-pane>
|
|
||||||
</el-tabs>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<span slot="footer" class="dialog-footer" v-if="showApprove && taskId">
|
|
||||||
<el-button @click="handleVisibleChange(false)">取 消</el-button>
|
|
||||||
<el-button type="danger" @click="openOpinionDialog('reject')">驳 回</el-button>
|
|
||||||
<el-button type="primary" @click="openOpinionDialog('approve')">同 意</el-button>
|
|
||||||
</span>
|
|
||||||
<span slot="footer" class="dialog-footer" v-else>
|
|
||||||
<el-button @click="handleVisibleChange(false)">关 闭</el-button>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<!-- 审批意见对话框 -->
|
|
||||||
<el-dialog :title="confirmDialogTitle" :visible.sync="opinionDialogVisible" width="500px" append-to-body :close-on-click-modal="false" :close-on-press-escape="false">
|
|
||||||
<el-form ref="opinionForm" :model="opinionForm" :rules="opinionRules" label-width="100px">
|
|
||||||
<el-form-item label="审批意见" prop="approveOpinion">
|
|
||||||
<el-input v-model="opinionForm.approveOpinion" type="textarea" :rows="4" placeholder="请输入审批意见" :disabled="submitLoading"/>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<span slot="footer" class="dialog-footer">
|
|
||||||
<el-button @click="opinionDialogVisible = false" :disabled="submitLoading">取 消</el-button>
|
|
||||||
<el-button type="primary" @click="showConfirmDialog" :loading="submitLoading">确 定</el-button>
|
|
||||||
</span>
|
|
||||||
</el-dialog>
|
|
||||||
</el-dialog>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { getOrder } from '@/api/approve/order/index'
|
|
||||||
import { listCompletedFlows, listApplyFlows, approveTask } from '@/api/flow'
|
|
||||||
import ConfigInfo from '@/views/approve/order/ConfigInfo.vue'
|
|
||||||
import ApproveLayout from '@/views/approve/ApproveLayout.vue'
|
|
||||||
import OrderInfoDisplay from '@/views/project/order/components/OrderInfoDisplay.vue'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'OrderRebackDetail',
|
|
||||||
dicts: ['execution_outer_status', 'execution_delivery_status', 'execution_sign_status'],
|
|
||||||
components: {
|
|
||||||
ApproveLayout,
|
|
||||||
OrderInfoDisplay,
|
|
||||||
ConfigInfo
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
visible: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
// 订单id,用于获取订单详情
|
|
||||||
orderId: {
|
|
||||||
type: [Number, String],
|
|
||||||
default: null
|
|
||||||
},
|
|
||||||
// 合同编号(流程businessKey),用于查询审批流转记录
|
|
||||||
orderCode: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
},
|
|
||||||
processKey: {
|
|
||||||
type: String,
|
|
||||||
default: 'order_reback'
|
|
||||||
},
|
|
||||||
// 当前审批任务id,为空表示仅查看
|
|
||||||
taskId: {
|
|
||||||
type: [Number, String],
|
|
||||||
default: null
|
|
||||||
},
|
|
||||||
// 是否显示审批按钮(由父组件控制,如当前用户是否为审批人)
|
|
||||||
showApprove: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
dialogVisible: false,
|
|
||||||
loading: false,
|
|
||||||
order: {},
|
|
||||||
logs: [],
|
|
||||||
reason: '',
|
|
||||||
amountChanged: '',
|
|
||||||
activeTab: 'process',
|
|
||||||
activeVersionTab: null,
|
|
||||||
confirmDialogTitle: '',
|
|
||||||
opinionDialogVisible: false,
|
|
||||||
currentApproveType: null,
|
|
||||||
submitLoading: false,
|
|
||||||
opinionForm: { approveOpinion: '' },
|
|
||||||
opinionRules: {
|
|
||||||
approveOpinion: [{ required: true, message: '审批意见不能为空', trigger: 'blur' }]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
// 获取所有唯一的版本号
|
|
||||||
uniqueVersions() {
|
|
||||||
if (!this.logs || this.logs.length === 0) return []
|
|
||||||
const versions = [...new Set(this.logs.map(log => log.extendField1))].filter(v => v !== null && v !== undefined && v !== '')
|
|
||||||
return versions.sort((a, b) => b - a) // 降序排列
|
|
||||||
},
|
|
||||||
// 按版本号分组的审批记录
|
|
||||||
groupedApproveLogs() {
|
|
||||||
if (!this.logs || this.logs.length === 0) return {}
|
|
||||||
return this.logs.reduce((acc, log) => {
|
|
||||||
const version = log.extendField1
|
|
||||||
if (!acc[version]) acc[version] = []
|
|
||||||
acc[version].push(log)
|
|
||||||
return acc
|
|
||||||
}, {})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
visible(val) {
|
|
||||||
this.dialogVisible = val
|
|
||||||
if (val) {
|
|
||||||
this.loadDetail()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
// 同步弹窗显隐到父组件,避免直接修改 prop
|
|
||||||
handleVisibleChange(val) {
|
|
||||||
this.dialogVisible = val
|
|
||||||
this.$emit('update:visible', val)
|
|
||||||
},
|
|
||||||
// 加载订单详情、撤单原因、流转意见
|
|
||||||
loadDetail() {
|
|
||||||
this.loading = true
|
|
||||||
this.order = {}
|
|
||||||
this.logs = []
|
|
||||||
this.reason = ''
|
|
||||||
this.amountChanged = ''
|
|
||||||
this.activeVersionTab = null
|
|
||||||
if (!this.orderId) {
|
|
||||||
this.loading = false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
getOrder(this.orderId).then(response => {
|
|
||||||
const data = response.data || {}
|
|
||||||
this.order = data.projectOrderInfo || {}
|
|
||||||
const businessKey = this.order.orderCode || this.orderCode
|
|
||||||
this.loadFlows(businessKey)
|
|
||||||
}).catch(error => {
|
|
||||||
console.error('获取订单详情失败: ', error)
|
|
||||||
this.$modal.msgError('获取订单详情失败!')
|
|
||||||
this.loading = false
|
|
||||||
})
|
|
||||||
},
|
|
||||||
loadFlows(businessKey) {
|
|
||||||
const processKeyList = this.processKey ? [this.processKey] : ['order_reback']
|
|
||||||
listCompletedFlows({ businessKey: businessKey, processKeyList }).then(res => {
|
|
||||||
this.logs = res.data || []
|
|
||||||
// 撤单原因存储于流程记录的扩展字段 extendField2,金额是否变化存储于 extendField3(extendField1 为订单版本号)
|
|
||||||
const applyLog = this.logs.find(log => log.extendField2)
|
|
||||||
if (applyLog) {
|
|
||||||
this.reason = applyLog.extendField2
|
|
||||||
this.amountChanged = applyLog.extendField3 || ''
|
|
||||||
} else {
|
|
||||||
// 审批中首节点已办表可能无记录,从待办表补充查询
|
|
||||||
listApplyFlows({ businessKey: businessKey, processKey: this.processKey }).then(todoRes => {
|
|
||||||
const todoList = todoRes.data || []
|
|
||||||
const apply = todoList.find(item => item.extendField2)
|
|
||||||
this.reason = apply ? apply.extendField2 : ''
|
|
||||||
this.amountChanged = apply ? (apply.extendField3 || '') : ''
|
|
||||||
}).catch(() => {})
|
|
||||||
}
|
|
||||||
if (this.uniqueVersions.length > 0) {
|
|
||||||
this.activeVersionTab = String(this.uniqueVersions[0])
|
|
||||||
}
|
|
||||||
this.loading = false
|
|
||||||
}).catch(() => {
|
|
||||||
this.logs = []
|
|
||||||
this.loading = false
|
|
||||||
})
|
|
||||||
},
|
|
||||||
openOpinionDialog(type) {
|
|
||||||
this.currentApproveType = type
|
|
||||||
this.confirmDialogTitle = type === 'approve' ? '同意审批' : '驳回审批'
|
|
||||||
this.opinionForm.approveOpinion = ''
|
|
||||||
this.opinionDialogVisible = true
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.$refs.opinionForm && this.$refs.opinionForm.clearValidate()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
showConfirmDialog() {
|
|
||||||
this.$refs.opinionForm.validate(valid => {
|
|
||||||
if (valid) {
|
|
||||||
this.opinionDialogVisible = false
|
|
||||||
this.submitApproval()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
submitApproval() {
|
|
||||||
this.submitLoading = true
|
|
||||||
const approveBtn = this.currentApproveType === 'approve' ? 1 : 0
|
|
||||||
const params = {
|
|
||||||
businessKey: this.order.orderCode || this.orderCode,
|
|
||||||
processKey: this.processKey,
|
|
||||||
taskId: this.taskId,
|
|
||||||
variables: {
|
|
||||||
comment: this.opinionForm.approveOpinion,
|
|
||||||
approveBtn: approveBtn
|
|
||||||
}
|
|
||||||
}
|
|
||||||
approveTask(params).then(() => {
|
|
||||||
this.submitLoading = false
|
|
||||||
this.$modal.msgSuccess(this.confirmDialogTitle + '成功')
|
|
||||||
this.handleVisibleChange(false)
|
|
||||||
this.$emit('success')
|
|
||||||
}).catch(error => {
|
|
||||||
this.submitLoading = false
|
|
||||||
console.error('审批失败: ', error)
|
|
||||||
this.$modal.msgError('审批失败!' + (error.msg || error.message))
|
|
||||||
})
|
|
||||||
},
|
|
||||||
getStatusTagType(status) {
|
|
||||||
const typeMap = {
|
|
||||||
'1': 'info', // 提交审批
|
|
||||||
'2': 'danger', // 驳回
|
|
||||||
'3': 'success' // 批准
|
|
||||||
}
|
|
||||||
return typeMap[String(status)] || 'info'
|
|
||||||
},
|
|
||||||
// 内层版本Tab切换:仅接受日志中存在的版本号,避免空值/非法值回写造成渲染循环
|
|
||||||
handleVersionTabChange(val) {
|
|
||||||
if (val !== null && val !== undefined && val !== '' && this.uniqueVersions.includes(val)) {
|
|
||||||
this.activeVersionTab = val
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getStatusText(status) {
|
|
||||||
const textMap = { '1': '提交审批', '2': '驳回', '3': '批准' }
|
|
||||||
return textMap[String(status)] || '提交审批'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.section-title {
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: bold;
|
|
||||||
color: #303133;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
border-bottom: 1px solid #eee;
|
|
||||||
padding-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mb20 {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tab样式 */
|
|
||||||
.approve-tabs {
|
|
||||||
margin-top: 20px;
|
|
||||||
margin-left: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 流转过程容器 */
|
|
||||||
.process-container {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 审批意见弹窗样式 */
|
|
||||||
::v-deep .el-dialog__body {
|
|
||||||
padding-top: 10px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,312 +0,0 @@
|
||||||
<template>
|
|
||||||
<el-dialog
|
|
||||||
title="出库撤回审批"
|
|
||||||
:visible="dialogVisible"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
width="80%"
|
|
||||||
top="5vh"
|
|
||||||
append-to-body
|
|
||||||
destroy-on-close
|
|
||||||
@update:visible="handleVisibleChange"
|
|
||||||
>
|
|
||||||
<div v-loading="loading" style="max-height: 70vh; overflow-y: auto; padding: 20px;">
|
|
||||||
<el-form label-width="110px">
|
|
||||||
<el-row>
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item label="出库单号:">
|
|
||||||
<el-input :value="form.outerCode" readonly />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item label="物流单号:">
|
|
||||||
<el-input :value="form.logisticsCode" readonly />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
<el-row>
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item label="物流公司:">
|
|
||||||
<el-input :value="form.logisticsCompany" readonly />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item label="仓库:">
|
|
||||||
<el-input :value="form.warehouseName" readonly />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
<el-row>
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item label="发货时间:">
|
|
||||||
<el-input :value="form.deliveryTime" readonly />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item label="发货数量:">
|
|
||||||
<el-input :value="form.quantity" readonly />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
<el-row>
|
|
||||||
<el-col :span="24">
|
|
||||||
<el-form-item label="收货地址:">
|
|
||||||
<el-input :value="form.notifierAddress" readonly />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
<el-row>
|
|
||||||
<el-col :span="24">
|
|
||||||
<el-form-item label="撤回原因:">
|
|
||||||
<el-input :value="reason" readonly type="textarea" :rows="2" />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
<el-row>
|
|
||||||
<el-col :span="24">
|
|
||||||
<el-form-item label="金额是否变化:">
|
|
||||||
<el-input :value="amountChanged || '—'" readonly />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</el-form>
|
|
||||||
|
|
||||||
<el-divider content-position="left">SN码列表</el-divider>
|
|
||||||
<el-table v-loading="snLoading" :data="snList" border size="mini">
|
|
||||||
<el-table-column type="index" label="序号" align="center" width="60" />
|
|
||||||
<el-table-column label="SN码" align="center" prop="productSn"/>
|
|
||||||
<el-table-column label="授权码" align="center" prop="licenseKey"/>
|
|
||||||
<el-table-column label="产品编码" align="center" prop="productCode"/>
|
|
||||||
<el-table-column label="产品型号" align="center" prop="model"/>
|
|
||||||
<el-table-column label="描述" align="center" prop="productDesc"/>
|
|
||||||
<el-table-column label="仓库" align="center" prop="warehouseName"/>
|
|
||||||
</el-table>
|
|
||||||
<pagination v-show="snTotal>0" :total="snTotal" :page.sync="snQueryParams.pageNum" :limit.sync="snQueryParams.pageSize" @pagination="getSnList"/>
|
|
||||||
|
|
||||||
<el-divider content-position="left">流转意见</el-divider>
|
|
||||||
<div class="process-container">
|
|
||||||
<el-timeline>
|
|
||||||
<el-timeline-item v-for="log in logs" :key="log.id" :timestamp="log.approveTime" placement="top">
|
|
||||||
<el-card>
|
|
||||||
<h4>{{ log.approveOpinion }}</h4>
|
|
||||||
<p><b>操作人:</b> {{ log.approveUserName }}</p>
|
|
||||||
<p><b>审批状态:</b>
|
|
||||||
<el-tag :type="log.approveStatus == '3' ? 'success' : log.approveStatus == '2' ? 'danger' : 'info'">{{ getStatusText(log.approveStatus) }}</el-tag>
|
|
||||||
</p>
|
|
||||||
</el-card>
|
|
||||||
</el-timeline-item>
|
|
||||||
</el-timeline>
|
|
||||||
<div v-if="!logs || logs.length === 0">暂无流转过程数据。</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<span slot="footer" class="dialog-footer" v-if="showApprove && taskId">
|
|
||||||
<el-button @click="handleVisibleChange(false)">取 消</el-button>
|
|
||||||
<el-button type="danger" @click="openOpinionDialog('reject')">驳 回</el-button>
|
|
||||||
<el-button type="primary" @click="openOpinionDialog('approve')">同 意</el-button>
|
|
||||||
</span>
|
|
||||||
<span slot="footer" class="dialog-footer" v-else>
|
|
||||||
<el-button @click="handleVisibleChange(false)">关 闭</el-button>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<!-- 审批意见对话框 -->
|
|
||||||
<el-dialog :title="confirmDialogTitle" :visible.sync="opinionDialogVisible" width="30%" append-to-body>
|
|
||||||
<el-form ref="opinionForm" :model="opinionForm" :rules="opinionRules" label-width="100px">
|
|
||||||
<el-form-item label="审批意见" prop="approveOpinion">
|
|
||||||
<el-input v-model="opinionForm.approveOpinion" type="textarea" :rows="4" placeholder="请输入审批意见"/>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<span slot="footer" class="dialog-footer">
|
|
||||||
<el-button @click="opinionDialogVisible = false">取 消</el-button>
|
|
||||||
<el-button type="primary" @click="showConfirmDialog()">确 定</el-button>
|
|
||||||
</span>
|
|
||||||
</el-dialog>
|
|
||||||
</el-dialog>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { getDelivery, listProductSn } from '@/api/inventory/delivery'
|
|
||||||
import { listCompletedFlows, listApplyFlows, approveTask } from '@/api/flow'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'OuterRebackDetail',
|
|
||||||
props: {
|
|
||||||
visible: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
// 发货记录id,用于获取发货详情与SN码列表
|
|
||||||
deliveryId: {
|
|
||||||
type: [Number, String],
|
|
||||||
default: null
|
|
||||||
},
|
|
||||||
// 出库单号,用于查询审批流转记录
|
|
||||||
outerCode: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
},
|
|
||||||
processKey: {
|
|
||||||
type: String,
|
|
||||||
default: 'outer_reback'
|
|
||||||
},
|
|
||||||
// 当前审批任务id,为空表示仅查看
|
|
||||||
taskId: {
|
|
||||||
type: [Number, String],
|
|
||||||
default: null
|
|
||||||
},
|
|
||||||
// 是否显示审批按钮(由父组件控制,如当前用户是否为审批人)
|
|
||||||
showApprove: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
dialogVisible: false,
|
|
||||||
loading: false,
|
|
||||||
form: {},
|
|
||||||
logs: [],
|
|
||||||
reason: '',
|
|
||||||
amountChanged: '',
|
|
||||||
// SN码列表
|
|
||||||
snLoading: false,
|
|
||||||
snList: [],
|
|
||||||
snTotal: 0,
|
|
||||||
snQueryParams: {
|
|
||||||
pageNum: 1,
|
|
||||||
pageSize: 10,
|
|
||||||
deliveryId: null,
|
|
||||||
// 不按状态/出库单过滤:撤回后的SN已还原为入库状态且outer_code被清空
|
|
||||||
inventoryStatus: null,
|
|
||||||
outerCode: null,
|
|
||||||
warehouseId: null,
|
|
||||||
productSnList: []
|
|
||||||
},
|
|
||||||
confirmDialogTitle: '',
|
|
||||||
opinionDialogVisible: false,
|
|
||||||
currentApproveType: null,
|
|
||||||
opinionForm: { approveOpinion: '' },
|
|
||||||
opinionRules: {
|
|
||||||
approveOpinion: [{ required: true, message: '审批意见不能为空', trigger: 'blur' }]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
visible(val) {
|
|
||||||
this.dialogVisible = val
|
|
||||||
if (val) {
|
|
||||||
this.loadDetail()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
// 同步弹窗显隐到父组件,避免直接修改 prop
|
|
||||||
handleVisibleChange(val) {
|
|
||||||
this.dialogVisible = val
|
|
||||||
this.$emit('update:visible', val)
|
|
||||||
},
|
|
||||||
// 加载发货详情、撤回原因、流转意见、SN码列表
|
|
||||||
loadDetail() {
|
|
||||||
this.loading = true
|
|
||||||
this.form = {}
|
|
||||||
this.logs = []
|
|
||||||
this.reason = ''
|
|
||||||
this.amountChanged = ''
|
|
||||||
this.snList = []
|
|
||||||
this.snTotal = 0
|
|
||||||
if (!this.deliveryId) {
|
|
||||||
this.loading = false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
getDelivery(this.deliveryId).then(response => {
|
|
||||||
this.form = response.data || {}
|
|
||||||
// SN码列表查询参数(与发货单详情一致:不传 outer_code)
|
|
||||||
this.snQueryParams.deliveryId = this.deliveryId
|
|
||||||
this.snQueryParams.warehouseId = this.form.warehouseId
|
|
||||||
this.snQueryParams.productSnList = this.form.productSnList
|
|
||||||
this.getSnList()
|
|
||||||
const businessKey = this.form.outerCode || this.outerCode
|
|
||||||
this.loadFlows(businessKey)
|
|
||||||
}).catch(error => {
|
|
||||||
console.error('获取发货记录详情失败: ', error)
|
|
||||||
this.$modal.msgError('获取发货记录详情失败!')
|
|
||||||
this.loading = false
|
|
||||||
})
|
|
||||||
},
|
|
||||||
// 查询关联SN码列表
|
|
||||||
getSnList() {
|
|
||||||
this.snLoading = true
|
|
||||||
listProductSn(this.snQueryParams).then(res => {
|
|
||||||
this.snList = res.rows
|
|
||||||
this.snTotal = res.total
|
|
||||||
this.snLoading = false
|
|
||||||
}).catch(() => {
|
|
||||||
this.snLoading = false
|
|
||||||
})
|
|
||||||
},
|
|
||||||
loadFlows(businessKey) {
|
|
||||||
const processKeyList = this.processKey ? [this.processKey] : ['outer_reback']
|
|
||||||
listCompletedFlows({ businessKey: businessKey, processKeyList }).then(res => {
|
|
||||||
this.logs = res.data || []
|
|
||||||
// 申请说明存储于流程发起记录的扩展字段 extend_field1,金额是否变化存储于 extend_field3
|
|
||||||
const applyLog = this.logs.find(log => log.extendField1)
|
|
||||||
if (applyLog) {
|
|
||||||
this.reason = applyLog.extendField1
|
|
||||||
this.amountChanged = applyLog.extendField3 || ''
|
|
||||||
} else {
|
|
||||||
// 审批中首节点已办表可能无记录,从待办表补充查询
|
|
||||||
listApplyFlows({ businessKey: businessKey, processKey: this.processKey }).then(todoRes => {
|
|
||||||
const todoList = todoRes.data || []
|
|
||||||
const apply = todoList.find(item => item.extendField1)
|
|
||||||
this.reason = apply ? apply.extendField1 : ''
|
|
||||||
this.amountChanged = apply ? (apply.extendField3 || '') : ''
|
|
||||||
}).catch(() => {})
|
|
||||||
}
|
|
||||||
this.loading = false
|
|
||||||
}).catch(() => {
|
|
||||||
this.logs = []
|
|
||||||
this.loading = false
|
|
||||||
})
|
|
||||||
},
|
|
||||||
openOpinionDialog(type) {
|
|
||||||
this.currentApproveType = type
|
|
||||||
this.confirmDialogTitle = type === 'approve' ? '同意审批' : '驳回审批'
|
|
||||||
this.opinionForm.approveOpinion = ''
|
|
||||||
this.opinionDialogVisible = true
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.$refs.opinionForm && this.$refs.opinionForm.clearValidate()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
showConfirmDialog() {
|
|
||||||
this.$refs.opinionForm.validate(valid => {
|
|
||||||
if (valid) {
|
|
||||||
this.opinionDialogVisible = false
|
|
||||||
this.submitApproval()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
submitApproval() {
|
|
||||||
const approveBtn = this.currentApproveType === 'approve' ? 1 : 0
|
|
||||||
const params = {
|
|
||||||
businessKey: this.form.outerCode || this.outerCode,
|
|
||||||
processKey: this.processKey,
|
|
||||||
taskId: this.taskId,
|
|
||||||
variables: {
|
|
||||||
comment: this.opinionForm.approveOpinion,
|
|
||||||
approveBtn: approveBtn
|
|
||||||
}
|
|
||||||
}
|
|
||||||
approveTask(params).then(() => {
|
|
||||||
this.$modal.msgSuccess(this.confirmDialogTitle + '成功')
|
|
||||||
this.handleVisibleChange(false)
|
|
||||||
this.$emit('success')
|
|
||||||
}).catch(error => {
|
|
||||||
console.error('审批失败: ', error)
|
|
||||||
this.$modal.msgError('审批失败!' + (error.msg || error.message))
|
|
||||||
})
|
|
||||||
},
|
|
||||||
getStatusText(status) {
|
|
||||||
const textMap = { '1': '提交审批', '2': '驳回', '3': '批准' }
|
|
||||||
return textMap[String(status)] || '提交审批'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -49,22 +49,6 @@
|
||||||
@keyup.enter.native="handleQuery"
|
@keyup.enter.native="handleQuery"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="产品编码" prop="productCode">
|
|
||||||
<el-input
|
|
||||||
v-model="queryParams.productCode"
|
|
||||||
placeholder="请输入产品编码"
|
|
||||||
clearable
|
|
||||||
@keyup.enter.native="handleQuery"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="产品型号" prop="productModel">
|
|
||||||
<el-input
|
|
||||||
v-model="queryParams.productModel"
|
|
||||||
placeholder="请输入产品型号"
|
|
||||||
clearable
|
|
||||||
@keyup.enter.native="handleQuery"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||||
|
|
@ -88,18 +72,13 @@
|
||||||
<el-table-column label="项目名称" align="center" prop="projectName" />
|
<el-table-column label="项目名称" align="center" prop="projectName" />
|
||||||
<el-table-column label="项目编号" align="center" prop="projectCode" />
|
<el-table-column label="项目编号" align="center" prop="projectCode" />
|
||||||
<el-table-column label="客户名称" align="center" prop="customerName" />
|
<el-table-column label="客户名称" align="center" prop="customerName" />
|
||||||
<el-table-column label="订单金额" align="center" prop="actualPurchaseAmount" >
|
<el-table-column label="订单金额" align="center" prop="actualPurchaseAmount" />
|
||||||
<template slot-scope="scope">
|
|
||||||
<span>{{ formatCurrency(scope.row.actualPurchaseAmount || scope.row.shipmentAmount) }}</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="汇智负责人" align="center" prop="dutyName" />
|
<el-table-column label="汇智负责人" align="center" prop="dutyName" />
|
||||||
<el-table-column label="审批节点" align="center" prop="approveNode">
|
<el-table-column label="审批节点" align="center" prop="approveNode">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<span>{{ scope.row.approveNode || '-' }}</span>
|
<span>{{ scope.row.approveNode || '-' }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="提交时间" align="center" prop="approveTime" />
|
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button
|
<el-button
|
||||||
|
|
@ -148,7 +127,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { listOrder } from "@/api/approve/order/orderLog";
|
import { listOrder } from "@/api/approve/order/orderLog";
|
||||||
import ApproveDialog from '../order/Approve.vue';
|
import ApproveDialog from '../order/Approve.vue';
|
||||||
import {formatCurrency} from "../../../utils";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "ApprovedOrder",
|
name: "ApprovedOrder",
|
||||||
|
|
@ -175,12 +153,10 @@ export default {
|
||||||
orderCode: null,
|
orderCode: null,
|
||||||
projectName: null,
|
projectName: null,
|
||||||
projectCode: null,
|
projectCode: null,
|
||||||
productCode: null,
|
|
||||||
productModel: null,
|
|
||||||
customerName: null,
|
customerName: null,
|
||||||
dutyName: null,
|
dutyName: null,
|
||||||
approveNode: null,
|
approveNode: null,
|
||||||
orderByColumn:'t1.approveTime desc, t1.id',
|
orderByColumn:'t7.todo_approve_time',
|
||||||
isAsc: 'desc'
|
isAsc: 'desc'
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
@ -189,7 +165,6 @@ export default {
|
||||||
this.getList();
|
this.getList();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
formatCurrency,
|
|
||||||
/** 查询订单列表 */
|
/** 查询订单列表 */
|
||||||
getList() {
|
getList() {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
|
|
|
||||||
|
|
@ -1,259 +0,0 @@
|
||||||
function escapeHtml(value) {
|
|
||||||
return String(value == null ? "" : value)
|
|
||||||
.replace(/&/g, "&")
|
|
||||||
.replace(/</g, "<")
|
|
||||||
.replace(/>/g, ">")
|
|
||||||
.replace(/"/g, """)
|
|
||||||
.replace(/'/g, "'");
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatCurrency(value) {
|
|
||||||
const num = Number(value);
|
|
||||||
if (Number.isNaN(num)) {
|
|
||||||
return "0.00";
|
|
||||||
}
|
|
||||||
return num.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
|
|
||||||
}
|
|
||||||
|
|
||||||
function getProductTypeLabel(value) {
|
|
||||||
const map = {
|
|
||||||
"1": "软件",
|
|
||||||
"2": "电子计算机",
|
|
||||||
"3": "信息系统服务"
|
|
||||||
};
|
|
||||||
return map[String(value)] || "";
|
|
||||||
}
|
|
||||||
|
|
||||||
function convertCurrency(money) {
|
|
||||||
const cnNums = ["零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"];
|
|
||||||
const cnIntRadice = ["", "拾", "佰", "仟"];
|
|
||||||
const cnIntUnits = ["", "万", "亿", "兆"];
|
|
||||||
const cnDecUnits = ["角", "分", "毫", "厘"];
|
|
||||||
const cnInteger = "整";
|
|
||||||
const cnIntLast = "元";
|
|
||||||
|
|
||||||
let integerNum;
|
|
||||||
let decimalNum;
|
|
||||||
let chineseStr = "";
|
|
||||||
let parts;
|
|
||||||
|
|
||||||
if (money === "") return "";
|
|
||||||
money = parseFloat(money);
|
|
||||||
if (money >= 999999999999) return "";
|
|
||||||
if (money === 0) return cnNums[0] + cnIntLast + cnInteger;
|
|
||||||
|
|
||||||
let prefix = "";
|
|
||||||
if (money < 0) {
|
|
||||||
prefix = "(负数)";
|
|
||||||
money = Math.abs(money);
|
|
||||||
}
|
|
||||||
|
|
||||||
money = money.toString();
|
|
||||||
if (money.indexOf(".") === -1) {
|
|
||||||
integerNum = money;
|
|
||||||
decimalNum = "";
|
|
||||||
} else {
|
|
||||||
parts = money.split(".");
|
|
||||||
integerNum = parts[0];
|
|
||||||
decimalNum = parts[1].substr(0, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parseInt(integerNum, 10) > 0) {
|
|
||||||
let zeroCount = 0;
|
|
||||||
const intLen = integerNum.length;
|
|
||||||
for (let i = 0; i < intLen; i++) {
|
|
||||||
const n = integerNum.substr(i, 1);
|
|
||||||
const p = intLen - i - 1;
|
|
||||||
const q = Math.floor(p / 4);
|
|
||||||
const m = p % 4;
|
|
||||||
if (n === "0") {
|
|
||||||
zeroCount++;
|
|
||||||
} else {
|
|
||||||
if (zeroCount > 0) chineseStr += cnNums[0];
|
|
||||||
zeroCount = 0;
|
|
||||||
chineseStr += cnNums[parseInt(n, 10)] + cnIntRadice[m];
|
|
||||||
}
|
|
||||||
if (m === 0 && zeroCount < 4) chineseStr += cnIntUnits[q];
|
|
||||||
}
|
|
||||||
chineseStr += cnIntLast;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (decimalNum !== "") {
|
|
||||||
const decLen = decimalNum.length;
|
|
||||||
for (let i = 0; i < decLen; i++) {
|
|
||||||
const n = decimalNum.substr(i, 1);
|
|
||||||
if (n !== "0") chineseStr += cnNums[Number(n)] + cnDecUnits[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chineseStr === "") chineseStr += cnNums[0] + cnIntLast + cnInteger;
|
|
||||||
else if (decimalNum === "") chineseStr += cnInteger;
|
|
||||||
return prefix + chineseStr;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getInvoiceTypeLabel(invoiceType) {
|
|
||||||
const map = {
|
|
||||||
"1": "增值税专用发票",
|
|
||||||
"2": "增值税普通发票",
|
|
||||||
"3": "电子发票"
|
|
||||||
};
|
|
||||||
return map[String(invoiceType)] || (invoiceType || "");
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildItemRows(items) {
|
|
||||||
if (!items || items.length === 0) {
|
|
||||||
return `
|
|
||||||
<tr>
|
|
||||||
<td class="cell center" colspan="12" style="height: 28px;">暂无明细</td>
|
|
||||||
</tr>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return items.map((item) => `
|
|
||||||
<tr>
|
|
||||||
<td class="cell center" align="center" style="text-align: center; mso-horizontal-align: center;" colspan="2">${escapeHtml(getProductTypeLabel(item.productType))}</td>
|
|
||||||
<td class="cell center" align="center" style="text-align: center; mso-horizontal-align: center;" colspan="2">${escapeHtml(item.productName)}</td>
|
|
||||||
<td class="cell center" align="center" style="text-align: center; mso-horizontal-align: center;">${escapeHtml(item.productModel)}</td>
|
|
||||||
<td class="cell center" align="center" style="text-align: center; mso-horizontal-align: center;">${escapeHtml(item.unit)}</td>
|
|
||||||
<td class="cell center" align="center" style="text-align: center; mso-horizontal-align: center;">${escapeHtml(item.quantity)}</td>
|
|
||||||
<td class="cell center" align="center" style="text-align: center; mso-horizontal-align: center;">${formatCurrency(item.price)}</td>
|
|
||||||
<td class="cell center" align="center" style="text-align: center; mso-horizontal-align: center;" colspan="2">${formatCurrency(item.allPrice)}</td>
|
|
||||||
<td class="cell center" align="center" style="text-align: center; mso-horizontal-align: center;">${escapeHtml(item.taxRate)}</td>
|
|
||||||
<td class="cell center" align="center" style="text-align: center; mso-horizontal-align: center;">${formatCurrency(item.taxAmount)}</td>
|
|
||||||
</tr>
|
|
||||||
`).join("");
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildSummaryRow(items) {
|
|
||||||
let allPriceTotal = 0;
|
|
||||||
let taxTotal = 0;
|
|
||||||
(items || []).forEach((item) => {
|
|
||||||
allPriceTotal += Number(item.allPrice) || 0;
|
|
||||||
taxTotal += Number(item.taxAmount) || 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
return `
|
|
||||||
<tr>
|
|
||||||
<td class="cell center bold" align="center" style="text-align: center; mso-horizontal-align: center;" colspan="8">合计</td>
|
|
||||||
<td class="cell center bold" align="center" style="text-align: center; mso-horizontal-align: center;" colspan="2">¥${formatCurrency(allPriceTotal)}</td>
|
|
||||||
<td class="cell center bold" align="center" style="text-align: center; mso-horizontal-align: center;">-</td>
|
|
||||||
<td class="cell center bold" align="center" style="text-align: center; mso-horizontal-align: center;">¥${formatCurrency(taxTotal)}</td>
|
|
||||||
</tr>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildInvoiceExcelHtml(invoice) {
|
|
||||||
const detailItems = invoice.detailItemList || [];
|
|
||||||
const totalAmountNumber = detailItems.reduce((sum, item) => sum + (Number(item.allPrice) || 0), 0).toFixed(2);
|
|
||||||
const totalAmountChinese = convertCurrency(totalAmountNumber);
|
|
||||||
const invoiceTypeLabel = getInvoiceTypeLabel(invoice.invoiceType);
|
|
||||||
|
|
||||||
return `<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<meta http-equiv="content-type" content="application/vnd.ms-excel; charset=UTF-8" />
|
|
||||||
<!--[if gte mso 9]><xml>
|
|
||||||
<x:ExcelWorkbook>
|
|
||||||
<x:ExcelWorksheets>
|
|
||||||
<x:ExcelWorksheet>
|
|
||||||
<x:Name>开票信息</x:Name>
|
|
||||||
<x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions>
|
|
||||||
</x:ExcelWorksheet>
|
|
||||||
</x:ExcelWorksheets>
|
|
||||||
</x:ExcelWorkbook>
|
|
||||||
</xml><![endif]-->
|
|
||||||
<style>
|
|
||||||
table { border-collapse: collapse; width: 1200px; font-family: "Microsoft YaHei", Arial, sans-serif; color: #8B4513; }
|
|
||||||
td { border: 1px solid #8B4513; padding: 6px; font-size: 12px; vertical-align: middle; mso-vertical-align: middle; mso-wrap-style: none; }
|
|
||||||
.no-border { border: none !important; }
|
|
||||||
.title { font-size: 26px; font-weight: bold; text-align: center; border: none !important; padding: 12px 0; }
|
|
||||||
.sub-title { font-size: 18px; font-weight: bold; text-align: center; border: none !important; padding-bottom: 8px; }
|
|
||||||
.label { width: 120px; font-weight: bold; text-align: center; }
|
|
||||||
.center { text-align: center; mso-horizontal-align: center; }
|
|
||||||
.right { text-align: right; mso-horizontal-align: right; }
|
|
||||||
.bold { font-weight: bold; }
|
|
||||||
.section-head { font-weight: bold; text-align: center; background: #f8f5f0; }
|
|
||||||
.cell { height: 26px; }
|
|
||||||
.total-main { font-weight: bold; }
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<table>
|
|
||||||
<colgroup>
|
|
||||||
<col style="width:100px;" />
|
|
||||||
<col style="width:100px;" />
|
|
||||||
<col style="width:100px;" />
|
|
||||||
<col style="width:100px;" />
|
|
||||||
<col style="width:80px;" />
|
|
||||||
<col style="width:80px;" />
|
|
||||||
<col style="width:80px;" />
|
|
||||||
<col style="width:100px;" />
|
|
||||||
<col style="width:100px;" />
|
|
||||||
<col style="width:100px;" />
|
|
||||||
<col style="width:80px;" />
|
|
||||||
<col style="width:100px;" />
|
|
||||||
</colgroup>
|
|
||||||
<tr>
|
|
||||||
<td class="no-border" colspan="2"></td>
|
|
||||||
<td class="title" colspan="8">电子发票(${escapeHtml(invoiceTypeLabel)})</td>
|
|
||||||
<td class="no-border" colspan="2" style="text-align: left; vertical-align: middle;">
|
|
||||||
<div><span class="bold">发票号码:</span>----------</div>
|
|
||||||
<div><span class="bold">开票日期:</span>----------</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="section-head" colspan="2" rowspan="2">购买方信息</td>
|
|
||||||
<td class="label" colspan="4">名称:${escapeHtml(invoice.buyerName)}</td>
|
|
||||||
<td class="section-head" colspan="2" rowspan="2">销售方信息</td>
|
|
||||||
<td class="label" colspan="4">名称:${escapeHtml(invoice.sellerName)}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="label" colspan="4">纳税人识别号:${escapeHtml(invoice.buyerCreditCode)}</td>
|
|
||||||
<td class="label" colspan="4">纳税人识别号:${escapeHtml(invoice.sellerCreditCode)}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="section-head" colspan="2">税收大类</td>
|
|
||||||
<td class="section-head" colspan="2">项目名称</td>
|
|
||||||
<td class="section-head">规格型号</td>
|
|
||||||
<td class="section-head">单位</td>
|
|
||||||
<td class="section-head">数量</td>
|
|
||||||
<td class="section-head">单价</td>
|
|
||||||
<td class="section-head" colspan="2">金额</td>
|
|
||||||
<td class="section-head">税率%</td>
|
|
||||||
<td class="section-head">税额</td>
|
|
||||||
</tr>
|
|
||||||
${buildItemRows(detailItems)}
|
|
||||||
${buildSummaryRow(detailItems)}
|
|
||||||
<tr>
|
|
||||||
<td class="label total-main" align="center" style="text-align: center; mso-horizontal-align: center;" colspan="2">价税合计(大写)</td>
|
|
||||||
<td class="total-main center" align="center" style="text-align: center; mso-horizontal-align: center;" colspan="6">⊗ ${escapeHtml(totalAmountChinese)}</td>
|
|
||||||
<td class="label total-main" align="center" style="text-align: center; mso-horizontal-align: center;" colspan="2">(小写)</td>
|
|
||||||
<td class="total-main center" align="center" style="text-align: center; mso-horizontal-align: center;" colspan="2">¥${formatCurrency(totalAmountNumber)}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="label" colspan="2">备注</td>
|
|
||||||
<td colspan="10">${escapeHtml(invoice.remark)}</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="label" colspan="2">信息说明</td>
|
|
||||||
<td colspan="10">${escapeHtml(invoice.informationNote)}</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</body>
|
|
||||||
</html>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function exportInvoiceInfoToExcel(invoiceData, fileName) {
|
|
||||||
const content = buildInvoiceExcelHtml(invoiceData || {});
|
|
||||||
const blob = new Blob(["\ufeff", content], {
|
|
||||||
type: "application/vnd.ms-excel;charset=utf-8;"
|
|
||||||
});
|
|
||||||
const url = URL.createObjectURL(blob);
|
|
||||||
const link = document.createElement("a");
|
|
||||||
link.href = url;
|
|
||||||
link.download = fileName || "开票单.xls";
|
|
||||||
document.body.appendChild(link);
|
|
||||||
link.click();
|
|
||||||
document.body.removeChild(link);
|
|
||||||
URL.revokeObjectURL(url);
|
|
||||||
}
|
|
||||||
|
|
@ -1,213 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="app-container">
|
|
||||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="120px">
|
|
||||||
<el-form-item label="收票编号" prop="receiptNo">
|
|
||||||
<el-input v-model="queryParams.receiptNo" placeholder="请输入收票编号" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="供应商" prop="vendorName">
|
|
||||||
<el-input v-model="queryParams.vendorName" placeholder="请输入供应商" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="项目名称" prop="projectName">
|
|
||||||
<el-input v-model="queryParams.projectName" placeholder="请输入项目名称" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="提交日期">
|
|
||||||
<el-date-picker
|
|
||||||
v-model="dateRange"
|
|
||||||
style="width: 240px"
|
|
||||||
value-format="yyyy-MM-dd"
|
|
||||||
type="daterange"
|
|
||||||
range-separator="-"
|
|
||||||
start-placeholder="开始日期"
|
|
||||||
end-placeholder="结束日期"
|
|
||||||
></el-date-picker>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
|
||||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
|
|
||||||
<el-table v-loading="loading" :data="invoiceReceiptList">
|
|
||||||
<el-table-column label="序号" type="index" width="50" align="center" />
|
|
||||||
<el-table-column label="收票编号" align="center" prop="ticketBillCode" />
|
|
||||||
<el-table-column label="供应商" align="center" prop="vendorName" />
|
|
||||||
<el-table-column label="金额" align="center" prop="totalPriceWithTax" :formatter="(row, column, cellValue)=>formatCurrency(cellValue)"/>
|
|
||||||
<el-table-column label="提交日期" align="center" prop="applyTime" width="180">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<span>{{ parseTime(scope.row.applyTime) }}</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="审批节点" align="center" prop="approveNode" />
|
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="200">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<el-button size="mini" type="text" icon="el-icon-view" @click="handleView(scope.row)">详情</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
|
|
||||||
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList"/>
|
|
||||||
|
|
||||||
<!-- 详情对话框 -->
|
|
||||||
<el-dialog title="收票单详情" :visible.sync="detailDialogVisible" width="80%" append-to-body>
|
|
||||||
<div v-loading="detailLoading" style="max-height: 70vh; overflow-y: auto; padding: 20px;">
|
|
||||||
<div style="display: flex;flex-direction: row-reverse; margin-bottom: 10px;">
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
size="small"
|
|
||||||
icon="el-icon-download"
|
|
||||||
@click="exportPDF"
|
|
||||||
:loading="pdfExporting"
|
|
||||||
>导出PDF</el-button>
|
|
||||||
</div>
|
|
||||||
<div class="approve-container" :class="{ 'exporting-pdf': pdfExporting }">
|
|
||||||
<ApproveLayout ref="approveLayout" title="收票单详情">
|
|
||||||
<invoice-receipt-detail :data="form"></invoice-receipt-detail>
|
|
||||||
<template #footer>
|
|
||||||
<span> {{ form.ticketBillCode }}</span>
|
|
||||||
</template>
|
|
||||||
</ApproveLayout>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-divider content-position="left">流转意见</el-divider>
|
|
||||||
<div class="process-container">
|
|
||||||
<el-timeline>
|
|
||||||
<el-timeline-item v-for="(log, index) in approveLogs" :key="index" :timestamp="log.approveTime" placement="top">
|
|
||||||
<el-card>
|
|
||||||
<h4>{{ log.approveOpinion }}</h4>
|
|
||||||
<p><b>操作人:</b> {{ log.approveUserName }} </p>
|
|
||||||
<p><b>审批状态:</b> <el-tag :type="log.approveStatus == '3' ? 'success' : log.approveStatus == '2' ? 'danger' : 'info'">{{ getStatusText(log.approveStatus) }}</el-tag></p>
|
|
||||||
</el-card>
|
|
||||||
</el-timeline-item>
|
|
||||||
</el-timeline>
|
|
||||||
<div v-if="!approveLogs || approveLogs.length === 0">暂无流转过程数据。</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<span slot="footer" class="dialog-footer">
|
|
||||||
<el-button @click="detailDialogVisible = false">关 闭</el-button>
|
|
||||||
</span>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { listInvoiceReceiptApproved, getInvoiceReceipt } from "@/api/finance/invoiceReceipt";
|
|
||||||
import { listCompletedFlows } from "@/api/flow";
|
|
||||||
import InvoiceReceiptDetail from "../components/InvoiceReceiptDetail";
|
|
||||||
import ApproveLayout from "@/views/approve/ApproveLayout";
|
|
||||||
import { exportElementToPDF } from "@/views/approve/finance/pdfUtils";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "InvoiceReceiptApproved",
|
|
||||||
components: { InvoiceReceiptDetail, ApproveLayout },
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
loading: true,
|
|
||||||
showSearch: true,
|
|
||||||
total: 0,
|
|
||||||
invoiceReceiptList: [],
|
|
||||||
queryParams: {
|
|
||||||
pageNum: 1,
|
|
||||||
pageSize: 10,
|
|
||||||
receiptNo: null,
|
|
||||||
vendorName: null,
|
|
||||||
processKey: 'fianance_ticket',
|
|
||||||
projectName: null,
|
|
||||||
orderByColumn: 'applyTime',
|
|
||||||
isAsc: 'desc'
|
|
||||||
},
|
|
||||||
dateRange: [],
|
|
||||||
detailDialogVisible: false,
|
|
||||||
detailLoading: false,
|
|
||||||
form: {},
|
|
||||||
approveLogs: [],
|
|
||||||
currentInvoiceReceiptId: null,
|
|
||||||
pdfExporting: false
|
|
||||||
};
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.getList();
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getList() {
|
|
||||||
this.loading = true;
|
|
||||||
listInvoiceReceiptApproved(this.addDateRange(this.queryParams, this.dateRange, 'ApplyTime')).then(response => {
|
|
||||||
this.invoiceReceiptList = response.rows;
|
|
||||||
this.total = response.total;
|
|
||||||
this.loading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
handleQuery() {
|
|
||||||
this.queryParams.pageNum = 1;
|
|
||||||
this.getList();
|
|
||||||
},
|
|
||||||
resetQuery() {
|
|
||||||
this.dateRange = [];
|
|
||||||
this.resetForm("queryForm");
|
|
||||||
this.handleQuery();
|
|
||||||
},
|
|
||||||
handleView(row) {
|
|
||||||
this.form = {};
|
|
||||||
this.approveLogs = [];
|
|
||||||
this.currentInvoiceReceiptId = row.id;
|
|
||||||
this.detailLoading = true;
|
|
||||||
this.detailDialogVisible = true;
|
|
||||||
|
|
||||||
getInvoiceReceipt(this.currentInvoiceReceiptId).then(response => {
|
|
||||||
this.form = response.data;
|
|
||||||
this.loadApproveHistory(this.form.ticketBillCode);
|
|
||||||
this.detailLoading = false;
|
|
||||||
}).catch(() => {
|
|
||||||
this.detailLoading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
loadApproveHistory(businessKey) {
|
|
||||||
if (businessKey) {
|
|
||||||
listCompletedFlows({ businessKey: businessKey }).then(response => {
|
|
||||||
this.approveLogs = response.data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getStatusText(status) {
|
|
||||||
const map = { '1': '提交审批', '2': '驳回', '3': '批准' };
|
|
||||||
return map[status] || '提交审批';
|
|
||||||
},
|
|
||||||
async exportPDF() {
|
|
||||||
this.pdfExporting = true;
|
|
||||||
try {
|
|
||||||
const element = this.$refs.approveLayout.$el;
|
|
||||||
const fileName = `收票单-${this.form.receiptBillCode || ''}.pdf`;
|
|
||||||
await exportElementToPDF(element, fileName);
|
|
||||||
this.$modal.msgSuccess('PDF导出成功');
|
|
||||||
} catch (error) {
|
|
||||||
console.error('PDF导出失败:', error);
|
|
||||||
this.$modal.msgError('PDF导出失败,请稍后重试');
|
|
||||||
} finally {
|
|
||||||
this.pdfExporting = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.process-container {
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 导出PDF时的特殊样式 */
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-button--primary,
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-button--text {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-input__inner,
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-textarea__inner {
|
|
||||||
border: none !important;
|
|
||||||
box-shadow: none !important;
|
|
||||||
background-color: transparent !important;
|
|
||||||
resize: none !important;
|
|
||||||
padding: 0 !important;
|
|
||||||
}
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-input__suffix {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,138 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="invoice-receipt-detail">
|
|
||||||
<div style="text-align: center;font-weight:bold;font-size: 25px;">收票申请单</div>
|
|
||||||
<el-descriptions title="收票单信息" :column="3" border>
|
|
||||||
<el-descriptions-item label="采购-收票单编号">{{ data.ticketBillCode }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="制造商名称">{{ data.vendorName }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="票据类型">
|
|
||||||
<dict-tag :options="dict.type.finance_invoice_type" :value="data.ticketType"/>
|
|
||||||
</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="含税总价(元)">{{ formatCurrency(data.totalPriceWithTax) }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="未税总价(元)">{{ formatCurrency(data.totalPriceWithoutTax) }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="税额(元)">{{ formatCurrency(data.taxAmount) }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="预计收票时间">{{ data.ticketTime }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="制造商开票时间">{{ data.vendorTicketTime }}</el-descriptions-item>
|
|
||||||
<!-- <el-descriptions-item label="备注" :span="3">{{ data.remark }}</el-descriptions-item>-->
|
|
||||||
</el-descriptions>
|
|
||||||
|
|
||||||
<div class="section" style="margin-top: 20px;" v-show="data.detailList && data.detailList.length>0">
|
|
||||||
<div class="el-descriptions__title">发票明细列表</div>
|
|
||||||
<el-table :data="data.detailList" border style="width: 100%; margin-top: 10px;">
|
|
||||||
<el-table-column type="index" label="序号" width="50" align="center"></el-table-column>
|
|
||||||
<el-table-column prop="payableBillCode" label="采购-应付单编号" align="center"></el-table-column>
|
|
||||||
<el-table-column prop="projectName" label="项目名称" align="center"></el-table-column>
|
|
||||||
<el-table-column prop="productType" label="产品类型" align="center">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<dict-tag :options="dict.type.product_type" :value="scope.row.productType"/>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="totalPriceWithTax" label="含税总价" align="center" :formatter="(row, column, cellValue)=>formatCurrency(cellValue)"></el-table-column>
|
|
||||||
<el-table-column prop="paymentAmount" label="本次收票金额" align="center" :formatter="(row, column, cellValue)=>formatCurrency(cellValue)"></el-table-column>
|
|
||||||
</el-table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="section" style="margin-top: 20px;" v-if="attachments && attachments.length > 0">
|
|
||||||
<div class="el-descriptions__title">附件信息</div>
|
|
||||||
<el-table :data="attachments" border style="width: 100%; margin-top: 10px;">
|
|
||||||
<el-table-column prop="fileName" label="附件名称" align="center"></el-table-column>
|
|
||||||
<el-table-column prop="createByName" label="上传人" align="center"></el-table-column>
|
|
||||||
<el-table-column prop="createTime" label="上传时间" align="center"></el-table-column>
|
|
||||||
<el-table-column label="操作" align="center">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<el-button size="mini" type="text" icon="el-icon-view" @click="handlePreview(scope.row)">预览</el-button>
|
|
||||||
<el-button size="mini" type="text" icon="el-icon-download" @click="handleDownload(scope.row)">下载</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-dialog :visible.sync="pdfPreviewVisible" width="80%" append-to-body top="5vh" title="PDF预览">
|
|
||||||
<iframe :src="currentPdfUrl" width="100%" height="600px" frameborder="0"></iframe>
|
|
||||||
</el-dialog>
|
|
||||||
|
|
||||||
<el-dialog :visible.sync="imagePreviewVisible" width="60%" append-to-body top="5vh" title="图片预览">
|
|
||||||
<img :src="currentImageUrl" style="width: 100%;" />
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { getInvoiceReceiptAttachments } from "@/api/finance/invoiceReceipt";
|
|
||||||
import request from '@/utils/request';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "InvoiceReceiptDetail",
|
|
||||||
props: {
|
|
||||||
data: {
|
|
||||||
type: Object,
|
|
||||||
required: true,
|
|
||||||
default: () => ({})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
dicts: ['finance_invoice_type', 'product_type'],
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
attachments: [],
|
|
||||||
pdfPreviewVisible: false,
|
|
||||||
currentPdfUrl: '',
|
|
||||||
imagePreviewVisible: false,
|
|
||||||
currentImageUrl: ''
|
|
||||||
};
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
'data.id': {
|
|
||||||
handler(val) {
|
|
||||||
if (val) {
|
|
||||||
this.fetchAttachments(val);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
immediate: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
fetchAttachments(id) {
|
|
||||||
getInvoiceReceiptAttachments(id,{ type: 'ticket' }).then(response => {
|
|
||||||
this.attachments = (response.data || []).filter(item => item.delFlag !== '2');
|
|
||||||
});
|
|
||||||
},
|
|
||||||
isPdf(filePath) {
|
|
||||||
return filePath && filePath.toLowerCase().endsWith('.pdf');
|
|
||||||
},
|
|
||||||
getImageUrl(resource) {
|
|
||||||
return process.env.VUE_APP_BASE_API + "/common/download/resource?resource=" + resource;
|
|
||||||
},
|
|
||||||
handlePreview(row) {
|
|
||||||
if (this.isPdf(row.filePath)) {
|
|
||||||
request({
|
|
||||||
url: '/common/download/resource',
|
|
||||||
method: 'get',
|
|
||||||
params: { resource: row.filePath },
|
|
||||||
responseType: 'blob'
|
|
||||||
}).then(res => {
|
|
||||||
const blob = new Blob([res.data], { type: 'application/pdf' });
|
|
||||||
this.currentPdfUrl = URL.createObjectURL(blob);
|
|
||||||
this.pdfPreviewVisible = true;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.currentImageUrl = this.getImageUrl(row.filePath);
|
|
||||||
this.imagePreviewVisible = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleDownload(row) {
|
|
||||||
const link = document.createElement('a');
|
|
||||||
link.href = this.getImageUrl(row.filePath);
|
|
||||||
link.download = row.fileName || 'attachment';
|
|
||||||
link.style.display = 'none';
|
|
||||||
document.body.appendChild(link);
|
|
||||||
link.click();
|
|
||||||
document.body.removeChild(link);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.invoice-receipt-detail {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,302 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="app-container">
|
|
||||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="120px">
|
|
||||||
<el-form-item label="收票编号" prop="receiptNo">
|
|
||||||
<el-input v-model="queryParams.receiptNo" placeholder="请输入收票编号" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="供应商" prop="vendorName">
|
|
||||||
<el-input v-model="queryParams.vendorName" placeholder="请输入供应商" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="项目名称" prop="projectName">
|
|
||||||
<el-input v-model="queryParams.projectName" placeholder="请输入项目名称" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="提交日期">
|
|
||||||
<el-date-picker
|
|
||||||
v-model="dateRange"
|
|
||||||
style="width: 240px"
|
|
||||||
value-format="yyyy-MM-dd"
|
|
||||||
type="daterange"
|
|
||||||
range-separator="-"
|
|
||||||
start-placeholder="开始日期"
|
|
||||||
end-placeholder="结束日期"
|
|
||||||
></el-date-picker>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
|
||||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
|
|
||||||
<el-row :gutter="10" class="mb8">
|
|
||||||
<el-col :span="1.5">
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
plain
|
|
||||||
size="mini"
|
|
||||||
@click="toApproved()"
|
|
||||||
>审批历史</el-button>
|
|
||||||
</el-col>
|
|
||||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
|
||||||
</el-row>
|
|
||||||
|
|
||||||
<el-table v-loading="loading" :data="invoiceReceiptList">
|
|
||||||
<el-table-column label="序号" type="index" width="50" align="center" />
|
|
||||||
<el-table-column label="收票编号" align="center" prop="ticketBillCode" />
|
|
||||||
<el-table-column label="制造商" align="center" prop="vendorName" />
|
|
||||||
<!-- <el-table-column label="项目名称" align="center" prop="projectName" />-->
|
|
||||||
<el-table-column label="金额" align="center" prop="totalPriceWithTax" :formatter="(row, column, cellValue)=>formatCurrency(cellValue)"/>
|
|
||||||
<!-- <el-table-column label="登记人" align="center" prop="createUserName" />-->
|
|
||||||
<el-table-column label="提交日期" align="center" prop="applyTime" width="180">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<span>{{ parseTime(scope.row.applyTime) }}</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="审批节点" align="center" prop="approveNode" />
|
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="200">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleApprove(scope.row)">审批</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
|
|
||||||
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList"/>
|
|
||||||
|
|
||||||
<!-- 审批详情主对话框 -->
|
|
||||||
<el-dialog title="收票单审批" :visible.sync="detailDialogVisible" width="80%" append-to-body>
|
|
||||||
<div v-loading="detailLoading" style="max-height: 70vh; overflow-y: auto; padding: 20px;">
|
|
||||||
<div style="display: flex;flex-direction: row-reverse; margin-bottom: 10px;">
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
size="small"
|
|
||||||
icon="el-icon-download"
|
|
||||||
@click="exportPDF"
|
|
||||||
:loading="pdfExporting"
|
|
||||||
>导出PDF</el-button>
|
|
||||||
</div>
|
|
||||||
<div class="approve-container" :class="{ 'exporting-pdf': pdfExporting }">
|
|
||||||
<ApproveLayout ref="approveLayout" title="收票单详情">
|
|
||||||
<invoice-receipt-detail :data="form"></invoice-receipt-detail>
|
|
||||||
<template #footer>
|
|
||||||
<span>{{ form.ticketBillCode }}</span>
|
|
||||||
</template>
|
|
||||||
</ApproveLayout>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-divider content-position="left">流转意见</el-divider>
|
|
||||||
<div class="process-container">
|
|
||||||
<el-timeline>
|
|
||||||
<el-timeline-item v-for="(log, index) in approveLogs" :key="index" :timestamp="log.approveTime" placement="top">
|
|
||||||
<el-card>
|
|
||||||
<h4>{{ log.approveOpinion }}</h4>
|
|
||||||
<p><b>操作人:</b> {{ log.approveUserName }} </p>
|
|
||||||
<p><b>审批状态:</b><el-tag :type="log.approveStatus == '3' ? 'success' : log.approveStatus == '2' ? 'danger' : 'info'">{{ getStatusText(log.approveStatus) }}</el-tag></p>
|
|
||||||
</el-card>
|
|
||||||
</el-timeline-item>
|
|
||||||
</el-timeline>
|
|
||||||
<div v-if="!approveLogs || approveLogs.length === 0">暂无流转过程数据。</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<span slot="footer" class="dialog-footer">
|
|
||||||
<el-button type="primary" @click="openOpinionDialog('approve')">同意</el-button>
|
|
||||||
<el-button type="danger" @click="openOpinionDialog('reject')">驳回</el-button>
|
|
||||||
<el-button @click="detailDialogVisible = false">取 消</el-button>
|
|
||||||
</span>
|
|
||||||
</el-dialog>
|
|
||||||
|
|
||||||
<!-- 审批意见对话框 -->
|
|
||||||
<el-dialog :title="confirmDialogTitle" :visible.sync="opinionDialogVisible" width="30%" append-to-body>
|
|
||||||
<el-form ref="opinionForm" :model="opinionForm" :rules="opinionRules" label-width="100px">
|
|
||||||
<el-form-item label="审批意见" prop="approveOpinion">
|
|
||||||
<el-input v-model="opinionForm.approveOpinion" type="textarea" :rows="4" placeholder="请输入审批意见"/>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<span slot="footer" class="dialog-footer">
|
|
||||||
<el-button @click="opinionDialogVisible = false">取 消</el-button>
|
|
||||||
<el-button type="primary" @click="showConfirmDialog()">确 定</el-button>
|
|
||||||
</span>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { listInvoiceReceiptApprove, getInvoiceReceipt } from "@/api/finance/invoiceReceipt";
|
|
||||||
import { approveTask, listCompletedFlows } from "@/api/flow";
|
|
||||||
import InvoiceReceiptDetail from "./components/InvoiceReceiptDetail";
|
|
||||||
import ApproveLayout from "@/views/approve/ApproveLayout";
|
|
||||||
import { exportElementToPDF } from "@/views/approve/finance/pdfUtils";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "InvoiceReceiptApprove",
|
|
||||||
components: { InvoiceReceiptDetail, ApproveLayout },
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
loading: true,
|
|
||||||
showSearch: true,
|
|
||||||
total: 0,
|
|
||||||
invoiceReceiptList: [],
|
|
||||||
queryParams: {
|
|
||||||
pageNum: 1,
|
|
||||||
pageSize: 10,
|
|
||||||
receiptNo: null,
|
|
||||||
vendorName: null,
|
|
||||||
processKey: 'fianance_ticket',
|
|
||||||
projectName: null,
|
|
||||||
orderByColumn: 'applyTime',
|
|
||||||
isAsc: 'desc'
|
|
||||||
},
|
|
||||||
dateRange: [],
|
|
||||||
detailDialogVisible: false,
|
|
||||||
detailLoading: false,
|
|
||||||
form: {},
|
|
||||||
approveLogs: [],
|
|
||||||
opinionDialogVisible: false,
|
|
||||||
confirmDialogTitle: '',
|
|
||||||
currentApproveType: '',
|
|
||||||
opinionForm: {
|
|
||||||
approveOpinion: ''
|
|
||||||
},
|
|
||||||
opinionRules: {
|
|
||||||
approveOpinion: [{ required: true, message: '审批意见不能为空', trigger: 'blur' }],
|
|
||||||
},
|
|
||||||
processKey: 'fianance_ticket',
|
|
||||||
taskId: null,
|
|
||||||
currentInvoiceReceiptId: null,
|
|
||||||
pdfExporting: false
|
|
||||||
};
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.getList();
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getList() {
|
|
||||||
this.loading = true;
|
|
||||||
listInvoiceReceiptApprove(this.addDateRange(this.queryParams, this.dateRange, 'ApplyTime')).then(response => {
|
|
||||||
this.invoiceReceiptList = response.rows;
|
|
||||||
this.total = response.total;
|
|
||||||
this.loading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
handleQuery() {
|
|
||||||
this.queryParams.pageNum = 1;
|
|
||||||
this.getList();
|
|
||||||
},
|
|
||||||
resetQuery() {
|
|
||||||
this.dateRange = [];
|
|
||||||
this.resetForm("queryForm");
|
|
||||||
this.handleQuery();
|
|
||||||
},
|
|
||||||
toApproved() {
|
|
||||||
this.$router.push( '/approve/invoiceLog' )
|
|
||||||
},
|
|
||||||
handleApprove(row) {
|
|
||||||
this.resetDetailForm();
|
|
||||||
this.currentInvoiceReceiptId = row.id;
|
|
||||||
this.taskId = row.taskId;
|
|
||||||
this.detailLoading = true;
|
|
||||||
this.detailDialogVisible = true;
|
|
||||||
|
|
||||||
getInvoiceReceipt(this.currentInvoiceReceiptId).then(response => {
|
|
||||||
this.form = response.data;
|
|
||||||
this.loadApproveHistory(this.form.ticketBillCode);
|
|
||||||
this.detailLoading = false;
|
|
||||||
}).catch(() => {
|
|
||||||
this.detailLoading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
resetDetailForm() {
|
|
||||||
this.form = {};
|
|
||||||
this.approveLogs = [];
|
|
||||||
this.opinionForm.approveOpinion = '';
|
|
||||||
},
|
|
||||||
loadApproveHistory(businessKey) {
|
|
||||||
if (businessKey) {
|
|
||||||
let keys = [];
|
|
||||||
if(this.processKey) keys.push(this.processKey);
|
|
||||||
|
|
||||||
listCompletedFlows({ businessKey: businessKey, processKeyList: keys }).then(response => {
|
|
||||||
this.approveLogs = response.data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
openOpinionDialog(type) {
|
|
||||||
this.currentApproveType = type;
|
|
||||||
this.confirmDialogTitle = type === 'approve' ? '同意审批' : '驳回审批';
|
|
||||||
this.opinionDialogVisible = true;
|
|
||||||
this.opinionForm.approveOpinion = '';
|
|
||||||
this.$nextTick(() => {
|
|
||||||
if(this.$refs.opinionForm) this.$refs.opinionForm.clearValidate();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
showConfirmDialog() {
|
|
||||||
this.$refs.opinionForm.validate(valid => {
|
|
||||||
if (valid) {
|
|
||||||
this.opinionDialogVisible = false;
|
|
||||||
this.submitApproval();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
submitApproval() {
|
|
||||||
const approveBtn = this.currentApproveType === 'approve' ? 1 : 0;
|
|
||||||
const params = {
|
|
||||||
businessKey: this.form.ticketBillCode,
|
|
||||||
processKey: this.processKey,
|
|
||||||
taskId: this.taskId,
|
|
||||||
variables: {
|
|
||||||
comment: this.opinionForm.approveOpinion,
|
|
||||||
approveBtn: approveBtn
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
approveTask(params).then(() => {
|
|
||||||
this.$modal.msgSuccess(this.confirmDialogTitle + "成功");
|
|
||||||
this.detailDialogVisible = false;
|
|
||||||
this.getList();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
getStatusText(status) {
|
|
||||||
if (!status) {
|
|
||||||
return '提交审批'
|
|
||||||
}
|
|
||||||
const map = { '1': '提交审批', '2': '驳回', '3': '批准' };
|
|
||||||
return map[status] || '提交审批';
|
|
||||||
},
|
|
||||||
async exportPDF() {
|
|
||||||
this.pdfExporting = true;
|
|
||||||
try {
|
|
||||||
const element = this.$refs.approveLayout.$el;
|
|
||||||
const fileName = `收票单-${this.form.ticketBillCode || ''}.pdf`;
|
|
||||||
await exportElementToPDF(element, fileName);
|
|
||||||
this.$modal.msgSuccess('PDF导出成功');
|
|
||||||
} catch (error) {
|
|
||||||
console.error('PDF导出失败:', error);
|
|
||||||
this.$modal.msgError('PDF导出失败,请稍后重试');
|
|
||||||
} finally {
|
|
||||||
this.pdfExporting = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.process-container {
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 导出PDF时的特殊样式 */
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-button--primary,
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-button--text {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-input__inner,
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-textarea__inner {
|
|
||||||
border: none !important;
|
|
||||||
box-shadow: none !important;
|
|
||||||
background-color: transparent !important;
|
|
||||||
resize: none !important;
|
|
||||||
padding: 0 !important;
|
|
||||||
}
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-input__suffix {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,214 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="app-container">
|
|
||||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="120px">
|
|
||||||
<el-form-item label="收票编号" prop="receiptNo">
|
|
||||||
<el-input v-model="queryParams.receiptNo" placeholder="请输入收票编号" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="供应商" prop="vendorName">
|
|
||||||
<el-input v-model="queryParams.vendorName" placeholder="请输入供应商" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="项目名称" prop="projectName">
|
|
||||||
<el-input v-model="queryParams.projectName" placeholder="请输入项目名称" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="提交日期">
|
|
||||||
<el-date-picker
|
|
||||||
v-model="dateRange"
|
|
||||||
style="width: 240px"
|
|
||||||
value-format="yyyy-MM-dd"
|
|
||||||
type="daterange"
|
|
||||||
range-separator="-"
|
|
||||||
start-placeholder="开始日期"
|
|
||||||
end-placeholder="结束日期"
|
|
||||||
></el-date-picker>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
|
||||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
|
|
||||||
<el-table v-loading="loading" :data="invoiceReceiptList">
|
|
||||||
<el-table-column label="序号" type="index" width="50" align="center" />
|
|
||||||
<el-table-column label="收票编号" align="center" prop="ticketBillCode" />
|
|
||||||
<el-table-column label="供应商" align="center" prop="vendorName" />
|
|
||||||
|
|
||||||
<el-table-column label="金额" align="center" prop="totalPriceWithTax" :formatter="(row, column, cellValue)=>formatCurrency(cellValue)"/>
|
|
||||||
<el-table-column label="提交日期" align="center" prop="applyTime" width="180">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<span>{{ parseTime(scope.row.applyTime) }}</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="审批节点" align="center" prop="approveNode" />
|
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="200">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<el-button size="mini" type="text" icon="el-icon-view" @click="handleView(scope.row)">详情</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
|
|
||||||
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList"/>
|
|
||||||
|
|
||||||
<!-- 详情对话框 -->
|
|
||||||
<el-dialog title="红冲发票详情" :visible.sync="detailDialogVisible" width="80%" append-to-body>
|
|
||||||
<div v-loading="detailLoading" style="max-height: 70vh; overflow-y: auto; padding: 20px;">
|
|
||||||
<div style="display: flex;flex-direction: row-reverse; margin-bottom: 10px;">
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
size="small"
|
|
||||||
icon="el-icon-download"
|
|
||||||
@click="exportPDF"
|
|
||||||
:loading="pdfExporting"
|
|
||||||
>导出PDF</el-button>
|
|
||||||
</div>
|
|
||||||
<div class="approve-container" :class="{ 'exporting-pdf': pdfExporting }">
|
|
||||||
<ApproveLayout ref="approveLayout" title="红冲发票详情">
|
|
||||||
<invoice-red-detail :data="form"></invoice-red-detail>
|
|
||||||
<template #footer>
|
|
||||||
<span> {{ form.ticketBillCode }}</span>
|
|
||||||
</template>
|
|
||||||
</ApproveLayout>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-divider content-position="left">流转意见</el-divider>
|
|
||||||
<div class="process-container">
|
|
||||||
<el-timeline>
|
|
||||||
<el-timeline-item v-for="(log, index) in approveLogs" :key="index" :timestamp="log.approveTime" placement="top">
|
|
||||||
<el-card>
|
|
||||||
<h4>{{ log.approveOpinion }}</h4>
|
|
||||||
<p><b>操作人:</b> {{ log.approveUserName }} </p>
|
|
||||||
<p><b>审批状态:</b> <el-tag :type="log.approveStatus == '3' ? 'success' : log.approveStatus == '2' ? 'danger' : 'info'">{{ getStatusText(log.approveStatus) }}</el-tag></p>
|
|
||||||
</el-card>
|
|
||||||
</el-timeline-item>
|
|
||||||
</el-timeline>
|
|
||||||
<div v-if="!approveLogs || approveLogs.length === 0">暂无流转过程数据。</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<span slot="footer" class="dialog-footer">
|
|
||||||
<el-button @click="detailDialogVisible = false">关 闭</el-button>
|
|
||||||
</span>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { listInvoiceReceiptApproved, getInvoiceReceipt } from "@/api/finance/invoiceReceipt";
|
|
||||||
import { listCompletedFlows } from "@/api/flow";
|
|
||||||
import InvoiceRedDetail from "../components/InvoiceRedDetail";
|
|
||||||
import ApproveLayout from "@/views/approve/ApproveLayout";
|
|
||||||
import { exportElementToPDF } from "@/views/approve/finance/pdfUtils";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "InvoiceRedApproved",
|
|
||||||
components: { InvoiceRedDetail, ApproveLayout },
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
loading: true,
|
|
||||||
showSearch: true,
|
|
||||||
total: 0,
|
|
||||||
invoiceReceiptList: [],
|
|
||||||
queryParams: {
|
|
||||||
pageNum: 1,
|
|
||||||
pageSize: 10,
|
|
||||||
receiptNo: null,
|
|
||||||
vendorName: null,
|
|
||||||
processKey: 'finance_ticket_refound',
|
|
||||||
projectName: null,
|
|
||||||
orderByColumn: 'applyTime',
|
|
||||||
isAsc: 'desc'
|
|
||||||
},
|
|
||||||
dateRange: [],
|
|
||||||
detailDialogVisible: false,
|
|
||||||
detailLoading: false,
|
|
||||||
form: {},
|
|
||||||
approveLogs: [],
|
|
||||||
currentInvoiceReceiptId: null,
|
|
||||||
pdfExporting: false
|
|
||||||
};
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.getList();
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getList() {
|
|
||||||
this.loading = true;
|
|
||||||
listInvoiceReceiptApproved(this.addDateRange(this.queryParams, this.dateRange, 'ApplyTime')).then(response => {
|
|
||||||
this.invoiceReceiptList = response.rows;
|
|
||||||
this.total = response.total;
|
|
||||||
this.loading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
handleQuery() {
|
|
||||||
this.queryParams.pageNum = 1;
|
|
||||||
this.getList();
|
|
||||||
},
|
|
||||||
resetQuery() {
|
|
||||||
this.dateRange = [];
|
|
||||||
this.resetForm("queryForm");
|
|
||||||
this.handleQuery();
|
|
||||||
},
|
|
||||||
handleView(row) {
|
|
||||||
this.form = {};
|
|
||||||
this.approveLogs = [];
|
|
||||||
this.currentInvoiceReceiptId = row.id;
|
|
||||||
this.detailLoading = true;
|
|
||||||
this.detailDialogVisible = true;
|
|
||||||
|
|
||||||
getInvoiceReceipt(this.currentInvoiceReceiptId).then(response => {
|
|
||||||
this.form = response.data;
|
|
||||||
this.loadApproveHistory(this.form.ticketBillCode);
|
|
||||||
this.detailLoading = false;
|
|
||||||
}).catch(() => {
|
|
||||||
this.detailLoading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
loadApproveHistory(businessKey) {
|
|
||||||
if (businessKey) {
|
|
||||||
listCompletedFlows({ businessKey: businessKey }).then(response => {
|
|
||||||
this.approveLogs = response.data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getStatusText(status) {
|
|
||||||
const map = { '1': '提交审批', '2': '驳回', '3': '批准' };
|
|
||||||
return map[status] || '提交审批';
|
|
||||||
},
|
|
||||||
async exportPDF() {
|
|
||||||
this.pdfExporting = true;
|
|
||||||
try {
|
|
||||||
const element = this.$refs.approveLayout.$el;
|
|
||||||
const fileName = `红冲发票-${this.form.receiptBillCode || ''}.pdf`;
|
|
||||||
await exportElementToPDF(element, fileName);
|
|
||||||
this.$modal.msgSuccess('PDF导出成功');
|
|
||||||
} catch (error) {
|
|
||||||
console.error('PDF导出失败:', error);
|
|
||||||
this.$modal.msgError('PDF导出失败,请稍后重试');
|
|
||||||
} finally {
|
|
||||||
this.pdfExporting = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.process-container {
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 导出PDF时的特殊样式 */
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-button--primary,
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-button--text {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-input__inner,
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-textarea__inner {
|
|
||||||
border: none !important;
|
|
||||||
box-shadow: none !important;
|
|
||||||
background-color: transparent !important;
|
|
||||||
resize: none !important;
|
|
||||||
padding: 0 !important;
|
|
||||||
}
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-input__suffix {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,139 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="invoice-red-detail">
|
|
||||||
<div style="text-align: center;font-weight:bold;font-size: 25px;">红冲收票申请单</div>
|
|
||||||
<el-descriptions title="红冲发票信息" :column="3" border>
|
|
||||||
<el-descriptions-item label="采购-收票单编号">{{ data.ticketBillCode }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="制造商名称">{{ data.vendorName }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="票据类型">
|
|
||||||
<dict-tag :options="dict.type.finance_invoice_type" :value="data.ticketType"/>
|
|
||||||
</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="含税总价(元)"><span style="color: red">{{ formatCurrency(data.totalPriceWithTax) }} </span></el-descriptions-item>
|
|
||||||
<el-descriptions-item label="未税总价(元)"><span style="color: red">{{ formatCurrency(data.totalPriceWithTax) }}</span></el-descriptions-item>
|
|
||||||
<el-descriptions-item label="税额(元)"><span style="color: red">{{ formatCurrency(data.taxAmount) }} </span></el-descriptions-item>
|
|
||||||
<el-descriptions-item label="收票时间">{{ data.ticketTime }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="制造商开票时间">{{ data.vendorTicketTime }}</el-descriptions-item>
|
|
||||||
<!-- <el-descriptions-item label="备注" :span="3">{{ data.remark }}</el-descriptions-item>-->
|
|
||||||
</el-descriptions>
|
|
||||||
|
|
||||||
<div class="section" style="margin-top: 20px;" v-show="data.detailList && data.detailList.length>0">
|
|
||||||
<div class="el-descriptions__title">发票明细列表</div>
|
|
||||||
<el-table :data="data.detailList" border style="width: 100%; margin-top: 10px;">
|
|
||||||
<el-table-column type="index" label="序号" width="50" align="center"></el-table-column>
|
|
||||||
<el-table-column prop="payableBillCode" label="采购-应付单编号" align="center"></el-table-column>
|
|
||||||
<el-table-column prop="projectName" label="项目名称" align="center"></el-table-column>
|
|
||||||
<el-table-column prop="productType" label="产品类型" align="center">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<dict-tag :options="dict.type.product_type" :value="scope.row.productType"/>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="totalPriceWithTax" label="含税总价" align="center" :formatter="(row, column, cellValue)=>formatCurrency(cellValue)"></el-table-column>
|
|
||||||
<el-table-column prop="paymentAmount" label="本次红冲金额" align="center" :formatter="(row, column, cellValue)=>formatCurrency(cellValue)"></el-table-column>
|
|
||||||
</el-table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="section" style="margin-top: 20px;" v-if="attachments && attachments.length > 0">
|
|
||||||
<div class="el-descriptions__title">附件信息</div>
|
|
||||||
<el-table :data="attachments" border style="width: 100%; margin-top: 10px;">
|
|
||||||
<el-table-column prop="fileName" label="附件名称" align="center"></el-table-column>
|
|
||||||
<el-table-column prop="createByName" label="上传人" align="center"></el-table-column>
|
|
||||||
<el-table-column prop="createTime" label="上传时间" align="center"></el-table-column>
|
|
||||||
<el-table-column label="操作" align="center">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<el-button size="mini" type="text" icon="el-icon-view" @click="handlePreview(scope.row)">预览</el-button>
|
|
||||||
<el-button size="mini" type="text" icon="el-icon-download" @click="handleDownload(scope.row)">下载</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-dialog :visible.sync="pdfPreviewVisible" width="80%" append-to-body top="5vh" title="PDF预览">
|
|
||||||
<iframe :src="currentPdfUrl" width="100%" height="600px" frameborder="0"></iframe>
|
|
||||||
</el-dialog>
|
|
||||||
|
|
||||||
<el-dialog :visible.sync="imagePreviewVisible" width="60%" append-to-body top="5vh" title="图片预览">
|
|
||||||
<img :src="currentImageUrl" style="width: 100%;" />
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { getInvoiceReceiptAttachments } from "@/api/finance/invoiceReceipt";
|
|
||||||
import request from '@/utils/request';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "InvoiceRedDetail",
|
|
||||||
props: {
|
|
||||||
data: {
|
|
||||||
type: Object,
|
|
||||||
required: true,
|
|
||||||
default: () => ({})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
dicts: ['finance_invoice_type', 'product_type'],
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
attachments: [],
|
|
||||||
pdfPreviewVisible: false,
|
|
||||||
currentPdfUrl: '',
|
|
||||||
imagePreviewVisible: false,
|
|
||||||
currentImageUrl: ''
|
|
||||||
};
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
'data.id': {
|
|
||||||
handler(val) {
|
|
||||||
if (val) {
|
|
||||||
this.fetchAttachments(val);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
immediate: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
fetchAttachments(id) {
|
|
||||||
// 保持调用 invoiceReceipt 的附件接口,因为接口一致
|
|
||||||
getInvoiceReceiptAttachments(id,{ type: 'ticket' }).then(response => {
|
|
||||||
this.attachments = (response.data || []).filter(item => item.delFlag !== '2');
|
|
||||||
});
|
|
||||||
},
|
|
||||||
isPdf(filePath) {
|
|
||||||
return filePath && filePath.toLowerCase().endsWith('.pdf');
|
|
||||||
},
|
|
||||||
getImageUrl(resource) {
|
|
||||||
return process.env.VUE_APP_BASE_API + "/common/download/resource?resource=" + resource;
|
|
||||||
},
|
|
||||||
handlePreview(row) {
|
|
||||||
if (this.isPdf(row.filePath)) {
|
|
||||||
request({
|
|
||||||
url: '/common/download/resource',
|
|
||||||
method: 'get',
|
|
||||||
params: { resource: row.filePath },
|
|
||||||
responseType: 'blob'
|
|
||||||
}).then(res => {
|
|
||||||
const blob = new Blob([res.data], { type: 'application/pdf' });
|
|
||||||
this.currentPdfUrl = URL.createObjectURL(blob);
|
|
||||||
this.pdfPreviewVisible = true;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.currentImageUrl = this.getImageUrl(row.filePath);
|
|
||||||
this.imagePreviewVisible = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleDownload(row) {
|
|
||||||
const link = document.createElement('a');
|
|
||||||
link.href = this.getImageUrl(row.filePath);
|
|
||||||
link.download = row.fileName || 'attachment';
|
|
||||||
link.style.display = 'none';
|
|
||||||
document.body.appendChild(link);
|
|
||||||
link.click();
|
|
||||||
document.body.removeChild(link);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.invoice-red-detail {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,304 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="app-container">
|
|
||||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="120px">
|
|
||||||
<el-form-item label="收票编号" prop="receiptNo">
|
|
||||||
<el-input v-model="queryParams.receiptNo" placeholder="请输入收票编号" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="供应商" prop="vendorName">
|
|
||||||
<el-input v-model="queryParams.vendorName" placeholder="请输入供应商" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="项目名称" prop="projectName">
|
|
||||||
<el-input v-model="queryParams.projectName" placeholder="请输入项目名称" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="提交日期">
|
|
||||||
<el-date-picker
|
|
||||||
v-model="dateRange"
|
|
||||||
style="width: 240px"
|
|
||||||
value-format="yyyy-MM-dd"
|
|
||||||
type="daterange"
|
|
||||||
range-separator="-"
|
|
||||||
start-placeholder="开始日期"
|
|
||||||
end-placeholder="结束日期"
|
|
||||||
></el-date-picker>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
|
||||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
|
|
||||||
<el-row :gutter="10" class="mb8">
|
|
||||||
<el-col :span="1.5">
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
plain
|
|
||||||
size="mini"
|
|
||||||
@click="toApproved()"
|
|
||||||
>审批历史</el-button>
|
|
||||||
</el-col>
|
|
||||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
|
||||||
</el-row>
|
|
||||||
|
|
||||||
<el-table v-loading="loading" :data="invoiceReceiptList">
|
|
||||||
<el-table-column label="序号" type="index" width="50" align="center" />
|
|
||||||
<el-table-column label="收票编号" align="center" prop="ticketBillCode" />
|
|
||||||
<el-table-column label="供应商" align="center" prop="vendorName" />
|
|
||||||
<!-- <el-table-column label="项目名称" align="center" prop="projectName" />-->
|
|
||||||
<el-table-column label="金额" align="center" prop="totalPriceWithTax" :formatter="(row, column, cellValue)=>formatCurrency(cellValue)">
|
|
||||||
|
|
||||||
</el-table-column>
|
|
||||||
<!-- <el-table-column label="登记人" align="center" prop="createUserName" />-->
|
|
||||||
<el-table-column label="提交日期" align="center" prop="applyTime" width="180">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<span>{{ parseTime(scope.row.applyTime) }}</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="审批节点" align="center" prop="approveNode" />
|
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="200">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleApprove(scope.row)">审批</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
|
|
||||||
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList"/>
|
|
||||||
|
|
||||||
<!-- 审批详情主对话框 -->
|
|
||||||
<el-dialog title="红冲发票审批" :visible.sync="detailDialogVisible" width="80%" append-to-body>
|
|
||||||
<div v-loading="detailLoading" style="max-height: 70vh; overflow-y: auto; padding: 20px;">
|
|
||||||
<div style="display: flex;flex-direction: row-reverse; margin-bottom: 10px;">
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
size="small"
|
|
||||||
icon="el-icon-download"
|
|
||||||
@click="exportPDF"
|
|
||||||
:loading="pdfExporting"
|
|
||||||
>导出PDF</el-button>
|
|
||||||
</div>
|
|
||||||
<div class="approve-container" :class="{ 'exporting-pdf': pdfExporting }">
|
|
||||||
<ApproveLayout ref="approveLayout" title="红冲发票详情">
|
|
||||||
<invoice-red-detail :data="form"></invoice-red-detail>
|
|
||||||
<template #footer>
|
|
||||||
<span> {{ form.ticketBillCode }}</span>
|
|
||||||
</template>
|
|
||||||
</ApproveLayout>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-divider content-position="left">流转意见</el-divider>
|
|
||||||
<div class="process-container">
|
|
||||||
<el-timeline>
|
|
||||||
<el-timeline-item v-for="(log, index) in approveLogs" :key="index" :timestamp="log.approveTime" placement="top">
|
|
||||||
<el-card>
|
|
||||||
<h4>{{ log.approveOpinion }}</h4>
|
|
||||||
<p><b>操作人:</b> {{ log.approveUserName }} </p>
|
|
||||||
<p><b>审批状态:</b> <el-tag :type="log.approveStatus == '3' ? 'success' : log.approveStatus == '2' ? 'danger' : 'info'">{{ getStatusText(log.approveStatus) }}</el-tag></p>
|
|
||||||
</el-card>
|
|
||||||
</el-timeline-item>
|
|
||||||
</el-timeline>
|
|
||||||
<div v-if="!approveLogs || approveLogs.length === 0">暂无流转过程数据。</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<span slot="footer" class="dialog-footer">
|
|
||||||
<el-button type="primary" @click="openOpinionDialog('approve')">同意</el-button>
|
|
||||||
<el-button type="danger" @click="openOpinionDialog('reject')">驳回</el-button>
|
|
||||||
<el-button @click="detailDialogVisible = false">取 消</el-button>
|
|
||||||
</span>
|
|
||||||
</el-dialog>
|
|
||||||
|
|
||||||
<!-- 审批意见对话框 -->
|
|
||||||
<el-dialog :title="confirmDialogTitle" :visible.sync="opinionDialogVisible" width="30%" append-to-body>
|
|
||||||
<el-form ref="opinionForm" :model="opinionForm" :rules="opinionRules" label-width="100px">
|
|
||||||
<el-form-item label="审批意见" prop="approveOpinion">
|
|
||||||
<el-input v-model="opinionForm.approveOpinion" type="textarea" :rows="4" placeholder="请输入审批意见"/>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<span slot="footer" class="dialog-footer">
|
|
||||||
<el-button @click="opinionDialogVisible = false">取 消</el-button>
|
|
||||||
<el-button type="primary" @click="showConfirmDialog()">确 定</el-button>
|
|
||||||
</span>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { listInvoiceReceiptApprove, getInvoiceReceipt } from "@/api/finance/invoiceReceipt";
|
|
||||||
import { approveTask, listCompletedFlows } from "@/api/flow";
|
|
||||||
import InvoiceRedDetail from "./components/InvoiceRedDetail";
|
|
||||||
import ApproveLayout from "@/views/approve/ApproveLayout";
|
|
||||||
import { exportElementToPDF } from "@/views/approve/finance/pdfUtils";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "InvoiceRedApprove",
|
|
||||||
components: { InvoiceRedDetail, ApproveLayout },
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
loading: true,
|
|
||||||
showSearch: true,
|
|
||||||
total: 0,
|
|
||||||
invoiceReceiptList: [],
|
|
||||||
queryParams: {
|
|
||||||
pageNum: 1,
|
|
||||||
pageSize: 10,
|
|
||||||
receiptNo: null,
|
|
||||||
vendorName: null,
|
|
||||||
processKey: 'finance_ticket_refound',
|
|
||||||
projectName: null,
|
|
||||||
orderByColumn: 'applyTime',
|
|
||||||
isAsc: 'desc'
|
|
||||||
},
|
|
||||||
dateRange: [],
|
|
||||||
detailDialogVisible: false,
|
|
||||||
detailLoading: false,
|
|
||||||
form: {},
|
|
||||||
approveLogs: [],
|
|
||||||
opinionDialogVisible: false,
|
|
||||||
confirmDialogTitle: '',
|
|
||||||
currentApproveType: '',
|
|
||||||
opinionForm: {
|
|
||||||
approveOpinion: ''
|
|
||||||
},
|
|
||||||
opinionRules: {
|
|
||||||
approveOpinion: [{ required: true, message: '审批意见不能为空', trigger: 'blur' }],
|
|
||||||
},
|
|
||||||
processKey: 'finance_ticket_refound',
|
|
||||||
taskId: null,
|
|
||||||
currentInvoiceReceiptId: null,
|
|
||||||
pdfExporting: false
|
|
||||||
};
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.getList();
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getList() {
|
|
||||||
this.loading = true;
|
|
||||||
listInvoiceReceiptApprove(this.addDateRange(this.queryParams, this.dateRange, 'ApplyTime')).then(response => {
|
|
||||||
this.invoiceReceiptList = response.rows;
|
|
||||||
this.total = response.total;
|
|
||||||
this.loading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
handleQuery() {
|
|
||||||
this.queryParams.pageNum = 1;
|
|
||||||
this.getList();
|
|
||||||
},
|
|
||||||
resetQuery() {
|
|
||||||
this.dateRange = [];
|
|
||||||
this.resetForm("queryForm");
|
|
||||||
this.handleQuery();
|
|
||||||
},
|
|
||||||
toApproved() {
|
|
||||||
this.$router.push( '/approve/invoiceRedLog' )
|
|
||||||
},
|
|
||||||
handleApprove(row) {
|
|
||||||
this.resetDetailForm();
|
|
||||||
this.currentInvoiceReceiptId = row.id;
|
|
||||||
this.taskId = row.taskId;
|
|
||||||
this.detailLoading = true;
|
|
||||||
this.detailDialogVisible = true;
|
|
||||||
|
|
||||||
getInvoiceReceipt(this.currentInvoiceReceiptId).then(response => {
|
|
||||||
this.form = response.data;
|
|
||||||
this.loadApproveHistory(this.form.ticketBillCode);
|
|
||||||
this.detailLoading = false;
|
|
||||||
}).catch(() => {
|
|
||||||
this.detailLoading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
resetDetailForm() {
|
|
||||||
this.form = {};
|
|
||||||
this.approveLogs = [];
|
|
||||||
this.opinionForm.approveOpinion = '';
|
|
||||||
},
|
|
||||||
loadApproveHistory(businessKey) {
|
|
||||||
if (businessKey) {
|
|
||||||
let keys = [];
|
|
||||||
if(this.processKey) keys.push(this.processKey);
|
|
||||||
|
|
||||||
listCompletedFlows({ businessKey: businessKey, processKeyList: keys }).then(response => {
|
|
||||||
this.approveLogs = response.data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
openOpinionDialog(type) {
|
|
||||||
this.currentApproveType = type;
|
|
||||||
this.confirmDialogTitle = type === 'approve' ? '同意审批' : '驳回审批';
|
|
||||||
this.opinionDialogVisible = true;
|
|
||||||
this.opinionForm.approveOpinion = '';
|
|
||||||
this.$nextTick(() => {
|
|
||||||
if(this.$refs.opinionForm) this.$refs.opinionForm.clearValidate();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
showConfirmDialog() {
|
|
||||||
this.$refs.opinionForm.validate(valid => {
|
|
||||||
if (valid) {
|
|
||||||
this.opinionDialogVisible = false;
|
|
||||||
this.submitApproval();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
submitApproval() {
|
|
||||||
const approveBtn = this.currentApproveType === 'approve' ? 1 : 0;
|
|
||||||
const params = {
|
|
||||||
businessKey: this.form.ticketBillCode,
|
|
||||||
processKey: this.processKey,
|
|
||||||
taskId: this.taskId,
|
|
||||||
variables: {
|
|
||||||
comment: this.opinionForm.approveOpinion,
|
|
||||||
approveBtn: approveBtn
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
approveTask(params).then(() => {
|
|
||||||
this.$modal.msgSuccess(this.confirmDialogTitle + "成功");
|
|
||||||
this.detailDialogVisible = false;
|
|
||||||
this.getList();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
getStatusText(status) {
|
|
||||||
if (!status) {
|
|
||||||
return '提交审批'
|
|
||||||
}
|
|
||||||
const map = { '1': '提交审批', '2': '驳回', '3': '批准' };
|
|
||||||
return map[status] || '提交审批';
|
|
||||||
},
|
|
||||||
async exportPDF() {
|
|
||||||
this.pdfExporting = true;
|
|
||||||
try {
|
|
||||||
const element = this.$refs.approveLayout.$el;
|
|
||||||
const fileName = `红冲发票-${this.form.ticketBillCode || ''}.pdf`;
|
|
||||||
await exportElementToPDF(element, fileName);
|
|
||||||
this.$modal.msgSuccess('PDF导出成功');
|
|
||||||
} catch (error) {
|
|
||||||
console.error('PDF导出失败:', error);
|
|
||||||
this.$modal.msgError('PDF导出失败,请稍后重试');
|
|
||||||
} finally {
|
|
||||||
this.pdfExporting = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.process-container {
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 导出PDF时的特殊样式 */
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-button--primary,
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-button--text {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-input__inner,
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-textarea__inner {
|
|
||||||
border: none !important;
|
|
||||||
box-shadow: none !important;
|
|
||||||
background-color: transparent !important;
|
|
||||||
resize: none !important;
|
|
||||||
padding: 0 !important;
|
|
||||||
}
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-input__suffix {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,215 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="app-container">
|
|
||||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="120px">
|
|
||||||
<el-form-item label="付款编号" prop="paymentNo">
|
|
||||||
<el-input v-model="queryParams.paymentNo" placeholder="请输入付款编号" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="制造商" prop="manufacturer">
|
|
||||||
<el-input v-model="queryParams.manufacturer" placeholder="请输入制造商" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="项目名称" prop="projectName">
|
|
||||||
<el-input v-model="queryParams.projectName" placeholder="请输入项目名称" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="提交日期">
|
|
||||||
<el-date-picker
|
|
||||||
v-model="dateRange"
|
|
||||||
style="width: 240px"
|
|
||||||
value-format="yyyy-MM-dd"
|
|
||||||
type="daterange"
|
|
||||||
range-separator="-"
|
|
||||||
start-placeholder="开始日期"
|
|
||||||
end-placeholder="结束日期"
|
|
||||||
></el-date-picker>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
|
||||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
|
|
||||||
<el-table v-loading="loading" :data="paymentList">
|
|
||||||
<el-table-column label="序号" type="index" width="50" align="center" />
|
|
||||||
<el-table-column label="付款编号" align="center" prop="paymentBillCode" />
|
|
||||||
<el-table-column label="制造商" align="center" prop="vendorName" />
|
|
||||||
<!-- <el-table-column label="项目名称" align="center" prop="projectName" />-->
|
|
||||||
<el-table-column label="金额" align="center" prop="totalPriceWithTax" :formatter="(row, column, cellValue)=>formatCurrency(cellValue)"/>
|
|
||||||
<!-- <el-table-column label="汇智负责人" align="center" prop="hzUserName" />-->
|
|
||||||
<el-table-column label="提交日期" align="center" prop="applyTime" width="180">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<span>{{ parseTime(scope.row.applyTime) }}</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="审批节点" align="center" prop="approveNode" />
|
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="200">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<el-button size="mini" type="text" icon="el-icon-view" @click="handleView(scope.row)">详情</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
|
|
||||||
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList"/>
|
|
||||||
|
|
||||||
<!-- 详情对话框 -->
|
|
||||||
<el-dialog title="付款单详情" :visible.sync="detailDialogVisible" width="80%" append-to-body>
|
|
||||||
<div v-loading="detailLoading" style="max-height: 70vh; overflow-y: auto; padding: 20px;">
|
|
||||||
<div style="display: flex;flex-direction: row-reverse; margin-bottom: 10px;">
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
size="small"
|
|
||||||
icon="el-icon-download"
|
|
||||||
@click="exportPDF"
|
|
||||||
:loading="pdfExporting"
|
|
||||||
>导出PDF</el-button>
|
|
||||||
</div>
|
|
||||||
<div class="approve-container" :class="{ 'exporting-pdf': pdfExporting }">
|
|
||||||
<ApproveLayout ref="approveLayout" title="付款单详情">
|
|
||||||
<payment-detail :data="form"></payment-detail>
|
|
||||||
<template #footer>
|
|
||||||
<span> {{ form.paymentBillCode }}</span>
|
|
||||||
</template>
|
|
||||||
</ApproveLayout>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-divider content-position="left">流转意见</el-divider>
|
|
||||||
<div class="process-container">
|
|
||||||
<el-timeline>
|
|
||||||
<el-timeline-item v-for="(log, index) in approveLogs" :key="index" :timestamp="log.approveTime" placement="top">
|
|
||||||
<el-card>
|
|
||||||
<h4>{{ log.approveOpinion }}</h4>
|
|
||||||
<p><b>操作人:</b> {{ log.approveUserName }} </p>
|
|
||||||
<p><b>审批状态:</b><el-tag :type="log.approveStatus == '3' ? 'success' : log.approveStatus == '2' ? 'danger' : 'info'">{{ getStatusText(log.approveStatus) }}</el-tag></p>
|
|
||||||
</el-card>
|
|
||||||
</el-timeline-item>
|
|
||||||
</el-timeline>
|
|
||||||
<div v-if="!approveLogs || approveLogs.length === 0">暂无流转过程数据。</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<span slot="footer" class="dialog-footer">
|
|
||||||
<el-button @click="detailDialogVisible = false">关 闭</el-button>
|
|
||||||
</span>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { listPaymentApproved, getPayment } from "@/api/finance/payment";
|
|
||||||
import { listCompletedFlows } from "@/api/flow";
|
|
||||||
import PaymentDetail from "../components/PaymentDetail"; // Relative path adjustment
|
|
||||||
import ApproveLayout from "@/views/approve/ApproveLayout";
|
|
||||||
import { exportElementToPDF } from "@/views/approve/finance/pdfUtils";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "PaymentApproved",
|
|
||||||
components: { PaymentDetail, ApproveLayout },
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
loading: true,
|
|
||||||
showSearch: true,
|
|
||||||
total: 0,
|
|
||||||
paymentList: [],
|
|
||||||
queryParams: {
|
|
||||||
pageNum: 1,
|
|
||||||
pageSize: 10,
|
|
||||||
paymentNo: null,
|
|
||||||
manufacturer: null,
|
|
||||||
projectName: null,
|
|
||||||
processKey: 'finance_payment',
|
|
||||||
orderByColumn: 'applyTime',
|
|
||||||
isAsc: 'desc'
|
|
||||||
},
|
|
||||||
dateRange: [],
|
|
||||||
detailDialogVisible: false,
|
|
||||||
detailLoading: false,
|
|
||||||
form: {},
|
|
||||||
approveLogs: [],
|
|
||||||
currentPaymentId: null,
|
|
||||||
pdfExporting: false
|
|
||||||
};
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.getList();
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getList() {
|
|
||||||
this.loading = true;
|
|
||||||
listPaymentApproved(this.addDateRange(this.queryParams, this.dateRange, 'ApplyTime')).then(response => {
|
|
||||||
this.paymentList = response.rows;
|
|
||||||
this.total = response.total;
|
|
||||||
this.loading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
handleQuery() {
|
|
||||||
this.queryParams.pageNum = 1;
|
|
||||||
this.getList();
|
|
||||||
},
|
|
||||||
resetQuery() {
|
|
||||||
this.dateRange = [];
|
|
||||||
this.resetForm("queryForm");
|
|
||||||
this.handleQuery();
|
|
||||||
},
|
|
||||||
handleView(row) {
|
|
||||||
this.form = {};
|
|
||||||
this.approveLogs = [];
|
|
||||||
this.currentPaymentId = row.id;
|
|
||||||
this.detailLoading = true;
|
|
||||||
this.detailDialogVisible = true;
|
|
||||||
|
|
||||||
getPayment(this.currentPaymentId).then(response => {
|
|
||||||
this.form = response.data;
|
|
||||||
this.loadApproveHistory(this.form.paymentBillCode);
|
|
||||||
this.detailLoading = false;
|
|
||||||
}).catch(() => {
|
|
||||||
this.detailLoading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
loadApproveHistory(businessKey) {
|
|
||||||
if (businessKey) {
|
|
||||||
listCompletedFlows({ businessKey: businessKey }).then(response => {
|
|
||||||
this.approveLogs = response.data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getStatusText(status) {
|
|
||||||
const map = { '1': '提交审批', '2': '驳回', '3': '批准' };
|
|
||||||
return map[status] || '提交审批';
|
|
||||||
},
|
|
||||||
async exportPDF() {
|
|
||||||
this.pdfExporting = true;
|
|
||||||
try {
|
|
||||||
const element = this.$refs.approveLayout.$el;
|
|
||||||
const fileName = `付款单-${this.form.paymentBillCode || ''}.pdf`;
|
|
||||||
await exportElementToPDF(element, fileName);
|
|
||||||
this.$modal.msgSuccess('PDF导出成功');
|
|
||||||
} catch (error) {
|
|
||||||
console.error('PDF导出失败:', error);
|
|
||||||
this.$modal.msgError('PDF导出失败,请稍后重试');
|
|
||||||
} finally {
|
|
||||||
this.pdfExporting = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.process-container {
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 导出PDF时的特殊样式 */
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-button--primary,
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-button--text {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-input__inner,
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-textarea__inner {
|
|
||||||
border: none !important;
|
|
||||||
box-shadow: none !important;
|
|
||||||
background-color: transparent !important;
|
|
||||||
resize: none !important;
|
|
||||||
padding: 0 !important;
|
|
||||||
}
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-input__suffix {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,284 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="payment-detail">
|
|
||||||
<div style="text-align: center;font-weight:bold;font-size: 25px;">付款申请单</div>
|
|
||||||
<el-descriptions title="付款单信息" :column="3" border>
|
|
||||||
<el-descriptions-item label="采购-付款单编号">{{ data.paymentBillCode }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="制造商名称">{{ data.vendorName }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="付款条件">
|
|
||||||
{{data.payType==='0'?'入库付款':'出库付款'}}
|
|
||||||
</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="付款周期">
|
|
||||||
{{data.payConfigDay}}天
|
|
||||||
</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="含税总价(元)">{{ formatCurrency(data.totalPriceWithTax) }}</el-descriptions-item>
|
|
||||||
<!-- <el-descriptions-item label="未税总价(元)">{{ data.totalPriceWithoutTax }}</el-descriptions-item>-->
|
|
||||||
<!-- <el-descriptions-item label="税额(元)">{{ data.taxAmount }}</el-descriptions-item>-->
|
|
||||||
<el-descriptions-item label="支付方式">
|
|
||||||
<dict-tag :options="dict.type.payment_method" :value="data.paymentMethod"/>
|
|
||||||
</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="银行账号">{{ data.payBankNumber }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="账户名称">{{ data.payName }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="银行开户行">{{ data.payBankOpenAddress }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="银行行号">{{ data.bankNumber }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item span="2"></el-descriptions-item>
|
|
||||||
<el-descriptions-item label="其它特别说明" :span="3">{{ data.remark }}</el-descriptions-item>
|
|
||||||
</el-descriptions>
|
|
||||||
|
|
||||||
<div class="section" style="margin-top: 20px;" >
|
|
||||||
<div class="el-descriptions__title">应付单信息</div>
|
|
||||||
<el-table :data="data.payableDetails" border style="width: 100%; margin-top: 10px;">
|
|
||||||
<el-table-column type="index" label="序号" width="50" align="center"></el-table-column>
|
|
||||||
<el-table-column label="采购单号" align="center">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<div class="purchase-no-cell">
|
|
||||||
<el-link
|
|
||||||
v-for="(purchaseItem, index) in getPurchaseNoList(scope.row.purchaseNo)"
|
|
||||||
:key="`${scope.$index}-${purchaseItem.purchaseNo}-${purchaseItem.purchaseId || ''}-${index}`"
|
|
||||||
type="primary"
|
|
||||||
:underline="false"
|
|
||||||
class="purchase-no-link"
|
|
||||||
@click="handleViewPruchaseDetail(scope.row, purchaseItem)"
|
|
||||||
>
|
|
||||||
{{ purchaseItem.purchaseNo }}
|
|
||||||
</el-link>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="采购-应付单编号" align="center">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<el-button type="text" @click="handleViewPayable(scope.row)">{{ scope.row.payableBillCode }}</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="项目名称" align="center">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<a @click="handleViewProject(scope.row)" class="link-type">{{ scope.row.projectName }}</a>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="productCode" label="产品编码" align="center"></el-table-column>
|
|
||||||
<el-table-column prop="model" label="产品型号" align="center"></el-table-column>
|
|
||||||
<el-table-column prop="productName" label="产品名称" align="center"></el-table-column>
|
|
||||||
</el-table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="section" style="margin-top: 20px;">
|
|
||||||
<div style="display: flex; justify-content: space-between; align-items: center;">
|
|
||||||
<div class="el-descriptions__title">附件信息</div>
|
|
||||||
<el-button type="success" size="mini" icon="el-icon-download" :loading="zipDownloading" @click="handleDownloadAllAttachments">一键下载附件</el-button>
|
|
||||||
</div>
|
|
||||||
<el-table :data="data.fileList" border style="width: 100%; margin-top: 10px;">
|
|
||||||
<el-table-column prop="fileName" label="附件名称" align="center"></el-table-column>
|
|
||||||
<el-table-column prop="createTime" label="上传时间" align="center"></el-table-column>
|
|
||||||
<el-table-column label="操作" align="center">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<el-button size="mini" type="text" icon="el-icon-view" @click="handlePreview(scope.row)">预览</el-button>
|
|
||||||
<el-button size="mini" type="text" icon="el-icon-download" @click="handleDownload(scope.row)">下载</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-dialog :visible.sync="pdfPreviewVisible" width="80%" append-to-body top="5vh" title="PDF预览">
|
|
||||||
<iframe :src="currentPdfUrl" width="100%" height="600px" frameborder="0"></iframe>
|
|
||||||
</el-dialog>
|
|
||||||
|
|
||||||
<el-dialog :visible.sync="imagePreviewVisible" width="60%" append-to-body top="5vh" title="图片预览">
|
|
||||||
<img :src="currentImageUrl" style="width: 100%;" />
|
|
||||||
</el-dialog>
|
|
||||||
|
|
||||||
<edit-form :visible.sync="payableVisible" :data="selectedPayableRow" :z-index="2000" @close="payableVisible = false" />
|
|
||||||
<project-detail-drawer :visible.sync="projectDrawerVisible" :project-id="currentProjectId" />
|
|
||||||
|
|
||||||
<el-drawer
|
|
||||||
title="采购单详情"
|
|
||||||
:visible.sync="showPruchaseDetailDrawer"
|
|
||||||
direction="rtl"
|
|
||||||
size="80%"
|
|
||||||
append-to-body
|
|
||||||
:modal-append-to-body="true"
|
|
||||||
:z-index="pruchaseDrawerZIndex"
|
|
||||||
>
|
|
||||||
<ApproveLayout title="采购单详情" v-if="showPruchaseDetailDrawer">
|
|
||||||
<purchase-order-detail-view
|
|
||||||
ref="pruchaseDetailView"
|
|
||||||
:order-data="pruchaseDetailOrderData"
|
|
||||||
@close="showPruchaseDetailDrawer = false"
|
|
||||||
>
|
|
||||||
</purchase-order-detail-view>
|
|
||||||
<template #footer>
|
|
||||||
<span>采购单编号: {{ pruchaseDetailOrderData ? pruchaseDetailOrderData.purchaseNo : '' }}</span>
|
|
||||||
<span v-if="pruchaseDetailOrderData"> | 版本号: {{ pruchaseDetailOrderData.version }}</span>
|
|
||||||
</template>
|
|
||||||
</ApproveLayout>
|
|
||||||
</el-drawer>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
import request from '@/utils/request';
|
|
||||||
import JSZip from 'jszip';
|
|
||||||
import { saveAs } from 'file-saver';
|
|
||||||
import { getPurchaseorder } from "@/api/sip/purchaseorder";
|
|
||||||
import {formatCurrency} from "@/utils";
|
|
||||||
import EditForm from "@/views/finance/payable/components/EditForm.vue";
|
|
||||||
import ProjectDetailDrawer from "@/views/project/info/ProjectDetailDrawer.vue";
|
|
||||||
import ApproveLayout from "@/views/approve/ApproveLayout.vue";
|
|
||||||
import PurchaseOrderDetailView from "@/views/purchaseorder/components/PurchaseOrderDetailView.vue";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "PaymentDetail",
|
|
||||||
components: { EditForm, ProjectDetailDrawer, ApproveLayout, PurchaseOrderDetailView },
|
|
||||||
props: {
|
|
||||||
data: {
|
|
||||||
type: Object,
|
|
||||||
required: true,
|
|
||||||
default: () => ({})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
dicts: ['payment_bill_type', 'product_type','payment_method'],
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
attachments: [],
|
|
||||||
zipDownloading: false,
|
|
||||||
pdfPreviewVisible: false,
|
|
||||||
currentPdfUrl: '',
|
|
||||||
imagePreviewVisible: false,
|
|
||||||
currentImageUrl: '',
|
|
||||||
payableVisible: false,
|
|
||||||
selectedPayableRow: {},
|
|
||||||
projectDrawerVisible: false,
|
|
||||||
currentProjectId: null,
|
|
||||||
showPruchaseDetailDrawer: false,
|
|
||||||
pruchaseDetailOrderData: null,
|
|
||||||
pruchaseDrawerZIndex: 5000
|
|
||||||
};
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
formatCurrency,
|
|
||||||
|
|
||||||
isPdf(filePath) {
|
|
||||||
return filePath && filePath.toLowerCase().endsWith('.pdf');
|
|
||||||
},
|
|
||||||
getImageUrl(resource) {
|
|
||||||
return process.env.VUE_APP_BASE_API + "/common/download/resource?resource=" + resource;
|
|
||||||
},
|
|
||||||
handlePreview(row) {
|
|
||||||
if (this.isPdf(row.filePath)) {
|
|
||||||
// PDF Preview logic
|
|
||||||
request({
|
|
||||||
url: '/common/download/resource',
|
|
||||||
method: 'get',
|
|
||||||
params: { resource: row.filePath },
|
|
||||||
responseType: 'blob'
|
|
||||||
}).then(res => {
|
|
||||||
const blob = new Blob([res.data], { type: 'application/pdf' });
|
|
||||||
this.currentPdfUrl = URL.createObjectURL(blob);
|
|
||||||
this.pdfPreviewVisible = true;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// Image Preview
|
|
||||||
this.currentImageUrl = this.getImageUrl(row.filePath);
|
|
||||||
this.imagePreviewVisible = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleDownload(row) {
|
|
||||||
const link = document.createElement('a');
|
|
||||||
link.href = this.getImageUrl(row.filePath);
|
|
||||||
link.download = row.fileName || 'attachment';
|
|
||||||
link.style.display = 'none';
|
|
||||||
document.body.appendChild(link);
|
|
||||||
link.click();
|
|
||||||
document.body.removeChild(link);
|
|
||||||
},
|
|
||||||
async handleDownloadAllAttachments() {
|
|
||||||
const files = Array.isArray(this.data.fileList) ? this.data.fileList : [];
|
|
||||||
if (files.length === 0) {
|
|
||||||
this.$modal.msgWarning('暂无可下载的附件');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.zipDownloading = true;
|
|
||||||
this.$modal.loading('正在打包附件,请稍候...');
|
|
||||||
try {
|
|
||||||
const zip = new JSZip();
|
|
||||||
for (const row of files) {
|
|
||||||
const blob = await request({
|
|
||||||
url: '/common/download/resource',
|
|
||||||
method: 'get',
|
|
||||||
params: { resource: row.filePath },
|
|
||||||
responseType: 'blob',
|
|
||||||
timeout: 0
|
|
||||||
}).then(res => res.data);
|
|
||||||
zip.file(row.fileName || 'file', blob);
|
|
||||||
}
|
|
||||||
const content = await zip.generateAsync({ type: 'blob' });
|
|
||||||
saveAs(content, (this.data.paymentBillCode || '付款申请单附件') + '.zip');
|
|
||||||
this.$modal.msgSuccess('下载成功');
|
|
||||||
} catch (error) {
|
|
||||||
console.error('附件打包下载失败', error);
|
|
||||||
this.$modal.msgError('附件下载失败,请稍后重试');
|
|
||||||
} finally {
|
|
||||||
this.zipDownloading = false;
|
|
||||||
this.$modal.closeLoading();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleViewPayable(row) {
|
|
||||||
row.id = row.payableBillId;
|
|
||||||
this.selectedPayableRow = row;
|
|
||||||
this.payableVisible = true;
|
|
||||||
},
|
|
||||||
handleViewProject(row) {
|
|
||||||
this.currentProjectId = row.projectId;
|
|
||||||
this.projectDrawerVisible = true;
|
|
||||||
},
|
|
||||||
getPurchaseNoList(purchaseNo) {
|
|
||||||
return (purchaseNo || '')
|
|
||||||
.split(',')
|
|
||||||
.map(item => item.trim())
|
|
||||||
.filter(Boolean)
|
|
||||||
.map(item => {
|
|
||||||
const splitIndex = item.lastIndexOf('__');
|
|
||||||
if (splitIndex === -1) {
|
|
||||||
return { purchaseNo: item, purchaseId: null };
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
purchaseNo: item.substring(0, splitIndex),
|
|
||||||
purchaseId: item.substring(splitIndex + 2)
|
|
||||||
};
|
|
||||||
});
|
|
||||||
},
|
|
||||||
handleViewPruchaseDetail(row, purchaseItem) {
|
|
||||||
this.pruchaseDrawerZIndex += 2;
|
|
||||||
const purchaseId = purchaseItem && purchaseItem.purchaseId ? purchaseItem.purchaseId : (row.purchaseId || row.purchaseOrderId);
|
|
||||||
if (purchaseId) {
|
|
||||||
getPurchaseorder(purchaseId).then(response => {
|
|
||||||
this.pruchaseDetailOrderData = response.data;
|
|
||||||
this.showPruchaseDetailDrawer = true;
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.pruchaseDetailOrderData = {
|
|
||||||
purchaseNo: (purchaseItem && purchaseItem.purchaseNo) || row.purchaseNo || '',
|
|
||||||
version: row.version || ''
|
|
||||||
};
|
|
||||||
this.showPruchaseDetailDrawer = true;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.payment-detail {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.purchase-no-cell {
|
|
||||||
word-break: break-all;
|
|
||||||
}
|
|
||||||
|
|
||||||
.purchase-no-link {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,314 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="app-container">
|
|
||||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="120px">
|
|
||||||
<el-form-item label="付款编号" prop="paymentNo">
|
|
||||||
<el-input v-model="queryParams.paymentNo" placeholder="请输入付款编号" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="制造商" prop="manufacturer">
|
|
||||||
<el-input v-model="queryParams.manufacturer" placeholder="请输入制造商" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="项目名称" prop="projectName">
|
|
||||||
<el-input v-model="queryParams.projectName" placeholder="请输入项目名称" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="提交日期">
|
|
||||||
<el-date-picker
|
|
||||||
v-model="dateRange"
|
|
||||||
style="width: 240px"
|
|
||||||
value-format="yyyy-MM-dd"
|
|
||||||
type="daterange"
|
|
||||||
range-separator="-"
|
|
||||||
start-placeholder="开始日期"
|
|
||||||
end-placeholder="结束日期"
|
|
||||||
></el-date-picker>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
|
||||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
|
|
||||||
<el-row :gutter="10" class="mb8">
|
|
||||||
<el-col :span="1.5">
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
plain
|
|
||||||
size="mini"
|
|
||||||
@click="toApproved()"
|
|
||||||
>审批历史</el-button>
|
|
||||||
</el-col>
|
|
||||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
|
||||||
</el-row>
|
|
||||||
|
|
||||||
<el-table v-loading="loading" :data="paymentList">
|
|
||||||
<el-table-column label="序号" type="index" width="50" align="center" />
|
|
||||||
<el-table-column label="付款编号" align="center" prop="paymentBillCode" />
|
|
||||||
<el-table-column label="制造商" align="center" prop="vendorName" />
|
|
||||||
<!-- <el-table-column label="项目名称" align="center" prop="projectName" />-->
|
|
||||||
<el-table-column label="金额" align="center" prop="totalPriceWithTax" :formatter="(row, column, cellValue)=>formatCurrency(cellValue)" />
|
|
||||||
<!-- <el-table-column label="汇智负责人" align="center" prop="hzUserName" />-->
|
|
||||||
<el-table-column label="提交日期" align="center" prop="applyTime" width="180">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<span>{{ parseTime(scope.row.applyTime) }}</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="审批节点" align="center" prop="approveNode" />
|
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="200">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleApprove(scope.row)">审批</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
|
|
||||||
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList"/>
|
|
||||||
|
|
||||||
<!-- 审批详情主对话框 -->
|
|
||||||
<el-dialog title="付款单审批" :visible.sync="detailDialogVisible" width="80%" append-to-body>
|
|
||||||
<div v-loading="detailLoading" style="max-height: 70vh; overflow-y: auto; padding: 20px;">
|
|
||||||
<div style="display: flex;flex-direction: row-reverse; margin-bottom: 10px;">
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
size="small"
|
|
||||||
icon="el-icon-download"
|
|
||||||
@click="exportPDF"
|
|
||||||
:loading="pdfExporting"
|
|
||||||
>导出PDF</el-button>
|
|
||||||
</div>
|
|
||||||
<div class="approve-container" :class="{ 'exporting-pdf': pdfExporting }">
|
|
||||||
<ApproveLayout ref="approveLayout" title="付款单详情">
|
|
||||||
<payment-detail :data="form"></payment-detail>
|
|
||||||
<template #footer>
|
|
||||||
<span>付款编号: {{ form.paymentBillCode }}</span>
|
|
||||||
</template>
|
|
||||||
</ApproveLayout>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-divider content-position="left">流转意见</el-divider>
|
|
||||||
<div class="process-container">
|
|
||||||
<el-timeline>
|
|
||||||
<el-timeline-item v-for="(log, index) in approveLogs" :key="index" :timestamp="log.approveTime" placement="top">
|
|
||||||
<el-card>
|
|
||||||
<h4>{{ log.approveOpinion }}</h4>
|
|
||||||
<p><b>操作人:</b> {{ log.approveUserName }} </p>
|
|
||||||
<p><b>审批状态:</b>
|
|
||||||
|
|
||||||
<el-tag :type="log.approveStatus == '3' ? 'success' : log.approveStatus == '2' ? 'danger' : 'info'">{{ getStatusText(log.approveStatus) }}</el-tag></p>
|
|
||||||
|
|
||||||
</el-card>
|
|
||||||
</el-timeline-item>
|
|
||||||
</el-timeline>
|
|
||||||
<div v-if="!approveLogs || approveLogs.length === 0">暂无流转过程数据。</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<span slot="footer" class="dialog-footer">
|
|
||||||
<el-button type="primary" @click="openOpinionDialog('approve')">同意</el-button>
|
|
||||||
<el-button type="danger" @click="openOpinionDialog('reject')">驳回</el-button>
|
|
||||||
<el-button @click="detailDialogVisible = false">取 消</el-button>
|
|
||||||
</span>
|
|
||||||
</el-dialog>
|
|
||||||
|
|
||||||
<!-- 审批意见对话框 -->
|
|
||||||
<el-dialog :title="confirmDialogTitle" :visible.sync="opinionDialogVisible" width="30%" append-to-body>
|
|
||||||
<el-form ref="opinionForm" :model="opinionForm" :rules="opinionRules" label-width="100px">
|
|
||||||
<el-form-item label="审批意见" prop="approveOpinion">
|
|
||||||
<el-input v-model="opinionForm.approveOpinion" type="textarea" :rows="4" placeholder="请输入审批意见"/>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<span slot="footer" class="dialog-footer">
|
|
||||||
<el-button @click="opinionDialogVisible = false">取 消</el-button>
|
|
||||||
<el-button type="primary" @click="showConfirmDialog()">确 定</el-button>
|
|
||||||
</span>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { listPaymentApprove, getPayment } from "@/api/finance/payment";
|
|
||||||
import { approveTask, listCompletedFlows } from "@/api/flow";
|
|
||||||
import PaymentDetail from "./components/PaymentDetail";
|
|
||||||
import ApproveLayout from "@/views/approve/ApproveLayout";
|
|
||||||
import { exportElementToPDF } from "@/views/approve/finance/pdfUtils";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "PaymentApprove",
|
|
||||||
components: { PaymentDetail, ApproveLayout },
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
loading: true,
|
|
||||||
showSearch: true,
|
|
||||||
total: 0,
|
|
||||||
paymentList: [],
|
|
||||||
queryParams: {
|
|
||||||
pageNum: 1,
|
|
||||||
pageSize: 10,
|
|
||||||
paymentNo: null,
|
|
||||||
manufacturer: null,
|
|
||||||
projectName: null,
|
|
||||||
processKey: 'finance_payment',
|
|
||||||
orderByColumn: 'applyTime',
|
|
||||||
isAsc: 'desc'
|
|
||||||
},
|
|
||||||
dateRange: [],
|
|
||||||
detailDialogVisible: false,
|
|
||||||
detailLoading: false,
|
|
||||||
form: {},
|
|
||||||
approveLogs: [],
|
|
||||||
opinionDialogVisible: false,
|
|
||||||
confirmDialogTitle: '',
|
|
||||||
currentApproveType: '',
|
|
||||||
opinionForm: {
|
|
||||||
approveOpinion: ''
|
|
||||||
},
|
|
||||||
opinionRules: {
|
|
||||||
approveOpinion: [{ required: true, message: '审批意见不能为空', trigger: 'blur' }],
|
|
||||||
},
|
|
||||||
processKey: 'finance_payment',
|
|
||||||
taskId: null,
|
|
||||||
currentPaymentId: null,
|
|
||||||
pdfExporting: false
|
|
||||||
};
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.getList();
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getList() {
|
|
||||||
this.loading = true;
|
|
||||||
listPaymentApprove(this.addDateRange(this.queryParams, this.dateRange, 'ApplyTime')).then(response => {
|
|
||||||
this.paymentList = response.rows;
|
|
||||||
this.total = response.total;
|
|
||||||
this.loading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
handleQuery() {
|
|
||||||
this.queryParams.pageNum = 1;
|
|
||||||
this.getList();
|
|
||||||
},
|
|
||||||
resetQuery() {
|
|
||||||
this.dateRange = [];
|
|
||||||
this.resetForm("queryForm");
|
|
||||||
this.handleQuery();
|
|
||||||
},
|
|
||||||
toApproved() {
|
|
||||||
this.$router.push( '/approve/paymentLog' )
|
|
||||||
},
|
|
||||||
handleApprove(row) {
|
|
||||||
this.resetDetailForm();
|
|
||||||
this.currentPaymentId = row.id;
|
|
||||||
this.taskId = row.taskId;
|
|
||||||
this.detailLoading = true;
|
|
||||||
this.detailDialogVisible = true;
|
|
||||||
|
|
||||||
getPayment(this.currentPaymentId).then(response => {
|
|
||||||
this.form = response.data;
|
|
||||||
this.loadApproveHistory(this.form.paymentBillCode);
|
|
||||||
this.detailLoading = false;
|
|
||||||
}).catch(() => {
|
|
||||||
this.detailLoading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
resetDetailForm() {
|
|
||||||
this.form = {};
|
|
||||||
this.approveLogs = [];
|
|
||||||
this.opinionForm.approveOpinion = '';
|
|
||||||
},
|
|
||||||
loadApproveHistory(businessKey) {
|
|
||||||
if (businessKey) {
|
|
||||||
// Assuming processKeyList might be generic or specific, using generic fetch for now
|
|
||||||
// Usually need to know the specific process key. For payment, it might be 'payment_approval' etc.
|
|
||||||
// However, listCompletedFlows logic in reference used specific keys.
|
|
||||||
// If I don't know the key, maybe I can omit it or guess.
|
|
||||||
// The reference used `processKeyList: ['purchase_order_online']`.
|
|
||||||
// I will use a generic one or try to find it.
|
|
||||||
// If row.processKey is available I can use that.
|
|
||||||
let keys = [];
|
|
||||||
console.log(this.processKey)
|
|
||||||
if(this.processKey) keys.push(this.processKey);
|
|
||||||
|
|
||||||
listCompletedFlows({ businessKey: businessKey, processKeyList: keys }).then(response => {
|
|
||||||
this.approveLogs = response.data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
openOpinionDialog(type) {
|
|
||||||
this.currentApproveType = type;
|
|
||||||
this.confirmDialogTitle = type === 'approve' ? '同意审批' : '驳回审批';
|
|
||||||
this.opinionDialogVisible = true;
|
|
||||||
this.opinionForm.approveOpinion = '';
|
|
||||||
this.$nextTick(() => {
|
|
||||||
if(this.$refs.opinionForm) this.$refs.opinionForm.clearValidate();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
showConfirmDialog() {
|
|
||||||
this.$refs.opinionForm.validate(valid => {
|
|
||||||
if (valid) {
|
|
||||||
this.opinionDialogVisible = false;
|
|
||||||
this.submitApproval();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
submitApproval() {
|
|
||||||
const approveBtn = this.currentApproveType === 'approve' ? 1 : 0;
|
|
||||||
const params = {
|
|
||||||
businessKey: this.form.paymentBillCode,
|
|
||||||
processKey: this.processKey,
|
|
||||||
taskId: this.taskId,
|
|
||||||
variables: {
|
|
||||||
comment: this.opinionForm.approveOpinion,
|
|
||||||
approveBtn: approveBtn
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
approveTask(params).then(() => {
|
|
||||||
this.$modal.msgSuccess(this.confirmDialogTitle + "成功");
|
|
||||||
this.detailDialogVisible = false;
|
|
||||||
this.getList();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
getStatusText(status) {
|
|
||||||
if (!status) {
|
|
||||||
return '提交审批'
|
|
||||||
}
|
|
||||||
// Map status codes to text
|
|
||||||
const map = { '1': '提交审批', '2': '驳回', '3': '批准' };
|
|
||||||
return map[status] || '提交审批';
|
|
||||||
},
|
|
||||||
async exportPDF() {
|
|
||||||
this.pdfExporting = true;
|
|
||||||
try {
|
|
||||||
const element = this.$refs.approveLayout.$el;
|
|
||||||
const fileName = `付款单-${this.form.paymentBillCode || ''}.pdf`;
|
|
||||||
await exportElementToPDF(element, fileName);
|
|
||||||
this.$modal.msgSuccess('PDF导出成功');
|
|
||||||
} catch (error) {
|
|
||||||
console.error('PDF导出失败:', error);
|
|
||||||
this.$modal.msgError('PDF导出失败,请稍后重试');
|
|
||||||
} finally {
|
|
||||||
this.pdfExporting = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.process-container {
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 导出PDF时的特殊样式 */
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-button--primary,
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-button--text {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-input__inner,
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-textarea__inner {
|
|
||||||
border: none !important;
|
|
||||||
box-shadow: none !important;
|
|
||||||
background-color: transparent !important;
|
|
||||||
resize: none !important;
|
|
||||||
padding: 0 !important;
|
|
||||||
}
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-input__suffix {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,219 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="app-container">
|
|
||||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="120px">
|
|
||||||
<el-form-item label="付款编号" prop="paymentNo">
|
|
||||||
<el-input v-model="queryParams.paymentNo" placeholder="请输入付款编号" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="制造商" prop="manufacturer">
|
|
||||||
<el-input v-model="queryParams.manufacturer" placeholder="请输入制造商" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="项目名称" prop="projectName">
|
|
||||||
<el-input v-model="queryParams.projectName" placeholder="请输入项目名称" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="提交日期">
|
|
||||||
<el-date-picker
|
|
||||||
v-model="dateRange"
|
|
||||||
style="width: 240px"
|
|
||||||
value-format="yyyy-MM-dd"
|
|
||||||
type="daterange"
|
|
||||||
range-separator="-"
|
|
||||||
start-placeholder="开始日期"
|
|
||||||
end-placeholder="结束日期"
|
|
||||||
></el-date-picker>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
|
||||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
|
|
||||||
<el-table v-loading="loading" :data="paymentList">
|
|
||||||
<el-table-column label="序号" type="index" width="50" align="center" />
|
|
||||||
<el-table-column label="付款编号" align="center" prop="paymentBillCode" />
|
|
||||||
<el-table-column label="制造商" align="center" prop="vendorName" />
|
|
||||||
<!-- <el-table-column label="项目名称" align="center" prop="projectName" />-->
|
|
||||||
<el-table-column label="金额" align="center" prop="totalPriceWithTax" >
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<span style="color: red">{{ formatCurrency(scope.row.totalPriceWithTax) }}</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<!-- <el-table-column label="汇智负责人" align="center" prop="hzUserName" />-->
|
|
||||||
<el-table-column label="提交日期" align="center" prop="applyTime" width="180">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<span>{{ parseTime(scope.row.applyTime) }}</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="审批节点" align="center" prop="approveNode" />
|
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="200">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<el-button size="mini" type="text" icon="el-icon-view" @click="handleView(scope.row)">详情</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
|
|
||||||
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList"/>
|
|
||||||
|
|
||||||
<!-- 详情对话框 -->
|
|
||||||
<el-dialog title="付款单详情" :visible.sync="detailDialogVisible" width="80%" append-to-body>
|
|
||||||
<div v-loading="detailLoading" style="max-height: 70vh; overflow-y: auto; padding: 20px;">
|
|
||||||
<div style="display: flex;flex-direction: row-reverse; margin-bottom: 10px;">
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
size="small"
|
|
||||||
icon="el-icon-download"
|
|
||||||
@click="exportPDF"
|
|
||||||
:loading="pdfExporting"
|
|
||||||
>导出PDF</el-button>
|
|
||||||
</div>
|
|
||||||
<div class="approve-container" :class="{ 'exporting-pdf': pdfExporting }">
|
|
||||||
<ApproveLayout ref="approveLayout" title="付款单详情">
|
|
||||||
<payment-detail :data="form"></payment-detail>
|
|
||||||
<template #footer>
|
|
||||||
<span> {{ form.paymentBillCode }}</span>
|
|
||||||
</template>
|
|
||||||
</ApproveLayout>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-divider content-position="left">流转意见</el-divider>
|
|
||||||
<div class="process-container">
|
|
||||||
<el-timeline>
|
|
||||||
<el-timeline-item v-for="(log, index) in approveLogs" :key="index" :timestamp="log.approveTime" placement="top">
|
|
||||||
<el-card>
|
|
||||||
<h4>{{ log.approveOpinion }}</h4>
|
|
||||||
<p><b>操作人:</b> {{ log.approveUserName }} </p>
|
|
||||||
<p><b>审批状态:</b> <el-tag :type="log.approveStatus == '3' ? 'success' : log.approveStatus == '2' ? 'danger' : 'info'">{{ getStatusText(log.approveStatus) }}</el-tag></p>
|
|
||||||
</el-card>
|
|
||||||
</el-timeline-item>
|
|
||||||
</el-timeline>
|
|
||||||
<div v-if="!approveLogs || approveLogs.length === 0">暂无流转过程数据。</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<span slot="footer" class="dialog-footer">
|
|
||||||
<el-button @click="detailDialogVisible = false">关 闭</el-button>
|
|
||||||
</span>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { listPaymentApproved, getPayment } from "@/api/finance/payment";
|
|
||||||
import { listCompletedFlows } from "@/api/flow";
|
|
||||||
import PaymentDetail from "../components/PaymentRefundDetail.vue"; // Relative path adjustment
|
|
||||||
import ApproveLayout from "@/views/approve/ApproveLayout";
|
|
||||||
import { exportElementToPDF } from "@/views/approve/finance/pdfUtils";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "PaymentApproved",
|
|
||||||
components: { PaymentDetail, ApproveLayout },
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
loading: true,
|
|
||||||
showSearch: true,
|
|
||||||
total: 0,
|
|
||||||
paymentList: [],
|
|
||||||
queryParams: {
|
|
||||||
pageNum: 1,
|
|
||||||
pageSize: 10,
|
|
||||||
paymentNo: null,
|
|
||||||
manufacturer: null,
|
|
||||||
projectName: null,
|
|
||||||
processKey: 'finance_refund',
|
|
||||||
orderByColumn: 'applyTime',
|
|
||||||
isAsc: 'desc'
|
|
||||||
},
|
|
||||||
dateRange: [],
|
|
||||||
detailDialogVisible: false,
|
|
||||||
detailLoading: false,
|
|
||||||
form: {},
|
|
||||||
approveLogs: [],
|
|
||||||
currentPaymentId: null,
|
|
||||||
pdfExporting: false
|
|
||||||
};
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.getList();
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getList() {
|
|
||||||
this.loading = true;
|
|
||||||
listPaymentApproved(this.addDateRange(this.queryParams, this.dateRange, 'ApplyTime')).then(response => {
|
|
||||||
this.paymentList = response.rows;
|
|
||||||
this.total = response.total;
|
|
||||||
this.loading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
handleQuery() {
|
|
||||||
this.queryParams.pageNum = 1;
|
|
||||||
this.getList();
|
|
||||||
},
|
|
||||||
resetQuery() {
|
|
||||||
this.dateRange = [];
|
|
||||||
this.resetForm("queryForm");
|
|
||||||
this.handleQuery();
|
|
||||||
},
|
|
||||||
handleView(row) {
|
|
||||||
this.form = {};
|
|
||||||
this.approveLogs = [];
|
|
||||||
this.currentPaymentId = row.id;
|
|
||||||
this.detailLoading = true;
|
|
||||||
this.detailDialogVisible = true;
|
|
||||||
|
|
||||||
getPayment(this.currentPaymentId).then(response => {
|
|
||||||
this.form = response.data;
|
|
||||||
this.loadApproveHistory(this.form.paymentBillCode);
|
|
||||||
this.detailLoading = false;
|
|
||||||
}).catch(() => {
|
|
||||||
this.detailLoading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
loadApproveHistory(businessKey) {
|
|
||||||
if (businessKey) {
|
|
||||||
listCompletedFlows({ businessKey: businessKey }).then(response => {
|
|
||||||
this.approveLogs = response.data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getStatusText(status) {
|
|
||||||
const map = { '1': '提交审批', '2': '驳回', '3': '批准' };
|
|
||||||
return map[status] || '提交审批';
|
|
||||||
},
|
|
||||||
async exportPDF() {
|
|
||||||
this.pdfExporting = true;
|
|
||||||
try {
|
|
||||||
const element = this.$refs.approveLayout.$el;
|
|
||||||
const fileName = `付款单-${this.form.paymentBillCode || ''}.pdf`;
|
|
||||||
await exportElementToPDF(element, fileName);
|
|
||||||
this.$modal.msgSuccess('PDF导出成功');
|
|
||||||
} catch (error) {
|
|
||||||
console.error('PDF导出失败:', error);
|
|
||||||
this.$modal.msgError('PDF导出失败,请稍后重试');
|
|
||||||
} finally {
|
|
||||||
this.pdfExporting = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.process-container {
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 导出PDF时的特殊样式 */
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-button--primary,
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-button--text {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-input__inner,
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-textarea__inner {
|
|
||||||
border: none !important;
|
|
||||||
box-shadow: none !important;
|
|
||||||
background-color: transparent !important;
|
|
||||||
resize: none !important;
|
|
||||||
padding: 0 !important;
|
|
||||||
}
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-input__suffix {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,67 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="payment-refund-detail">
|
|
||||||
<div style="text-align: center;font-weight:bold;font-size: 25px;">退款申请单</div>
|
|
||||||
<el-descriptions title="付款单信息" :column="3" border>
|
|
||||||
<el-descriptions-item label="采购付款单编号">{{ data.paymentBillCode }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="制造商名称">{{ data.vendorName }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="付款条件">
|
|
||||||
{{data.payType==='0'?'入库付款':'出库付款'}}
|
|
||||||
</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="付款周期">
|
|
||||||
{{data.payConfigDay}}天
|
|
||||||
</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="含税总价(元)"><span style="color: red">{{ formatCurrency(data.totalPriceWithTax) }}</span></el-descriptions-item>
|
|
||||||
<!-- <el-descriptions-item label="未税总价(元)"><span style="color: red">{{ data.totalPriceWithoutTax }}</span></el-descriptions-item>-->
|
|
||||||
<!-- <el-descriptions-item label="税额(元)"><span style="color: red">{{ data.taxAmount }}</span></el-descriptions-item>-->
|
|
||||||
<el-descriptions-item label="支付方式">
|
|
||||||
<dict-tag :options="dict.type.payment_method" :value="data.paymentMethod"/>
|
|
||||||
</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="银行账号">{{ data.payBankNumber }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="账户名称">{{ data.payName }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="银行开户行">{{ data.payBankOpenAddress }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="银行行号" span="1">{{ data.bankNumber }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item span="2"></el-descriptions-item>
|
|
||||||
<el-descriptions-item label="其它特别说明" span="3">{{ data.remark }}</el-descriptions-item>
|
|
||||||
</el-descriptions>
|
|
||||||
|
|
||||||
<div class="section" style="margin-top: 20px;" >
|
|
||||||
<div class="el-descriptions__title">应付单信息</div>
|
|
||||||
<el-table :data="data.payableDetails" border style="width: 100%; margin-top: 10px;">
|
|
||||||
<el-table-column type="index" label="序号" width="50" align="center"></el-table-column>
|
|
||||||
<el-table-column prop="payableBillCode" label="采购应付单编号" align="center"></el-table-column>
|
|
||||||
<el-table-column prop="projectName" label="项目名称" align="center"></el-table-column>
|
|
||||||
<el-table-column prop="productType" label="产品类型" align="center">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<dict-tag :options="dict.type.product_type" :value="scope.row.productType"/>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<!-- Note: Product Type is requested but not present in reference DetailDrawer.vue. Omitting for safety or need to ask. -->
|
|
||||||
<el-table-column prop="totalPriceWithTax" label="含税总价" align="center" :formatter="(row, column, cellValue)=>formatCurrency(cellValue)"></el-table-column>
|
|
||||||
<el-table-column prop="paymentAmount" label="本次付款金额" align="center" :formatter="(row, column, cellValue)=>formatCurrency(cellValue)"></el-table-column>
|
|
||||||
</el-table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import {formatCurrency} from "@/utils";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "PaymentRefundDetail",
|
|
||||||
methods: {formatCurrency},
|
|
||||||
props: {
|
|
||||||
data: {
|
|
||||||
type: Object,
|
|
||||||
required: true,
|
|
||||||
default: () => ({})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
dicts: ['payment_bill_type', 'payment_method','product_type']
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.payment-refund-detail {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,315 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="app-container">
|
|
||||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="120px">
|
|
||||||
<el-form-item label="付款编号" prop="paymentNo">
|
|
||||||
<el-input v-model="queryParams.paymentNo" placeholder="请输入付款编号" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="制造商" prop="manufacturer">
|
|
||||||
<el-input v-model="queryParams.manufacturer" placeholder="请输入制造商" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="项目名称" prop="projectName">
|
|
||||||
<el-input v-model="queryParams.projectName" placeholder="请输入项目名称" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="提交日期">
|
|
||||||
<el-date-picker
|
|
||||||
v-model="dateRange"
|
|
||||||
style="width: 240px"
|
|
||||||
value-format="yyyy-MM-dd"
|
|
||||||
type="daterange"
|
|
||||||
range-separator="-"
|
|
||||||
start-placeholder="开始日期"
|
|
||||||
end-placeholder="结束日期"
|
|
||||||
></el-date-picker>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
|
||||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
|
|
||||||
<el-row :gutter="10" class="mb8">
|
|
||||||
<el-col :span="1.5">
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
plain
|
|
||||||
size="mini"
|
|
||||||
@click="toApproved()"
|
|
||||||
>审批历史</el-button>
|
|
||||||
</el-col>
|
|
||||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
|
||||||
</el-row>
|
|
||||||
|
|
||||||
<el-table v-loading="loading" :data="paymentList">
|
|
||||||
<el-table-column label="序号" type="index" width="50" align="center" />
|
|
||||||
<el-table-column label="付款编号" align="center" prop="paymentBillCode" />
|
|
||||||
<el-table-column label="制造商" align="center" prop="vendorName" />
|
|
||||||
<!-- <el-table-column label="项目名称" align="center" prop="projectName" />-->
|
|
||||||
<el-table-column label="金额" align="center" prop="totalPriceWithTax" >
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<span style="color: red">{{ formatCurrency(scope.row.totalPriceWithTax) }}</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<!-- <el-table-column label="汇智负责人" align="center" prop="hzUserName" />-->
|
|
||||||
<el-table-column label="提交日期" align="center" prop="applyTime" width="180">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<span>{{ parseTime(scope.row.applyTime) }}</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="审批节点" align="center" prop="approveNode" />
|
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="200">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleApprove(scope.row)">审批</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
|
|
||||||
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList"/>
|
|
||||||
|
|
||||||
<!-- 审批详情主对话框 -->
|
|
||||||
<el-dialog title="付款单审批" :visible.sync="detailDialogVisible" width="80%" append-to-body>
|
|
||||||
<div v-loading="detailLoading" style="max-height: 70vh; overflow-y: auto; padding: 20px;">
|
|
||||||
<div style="display: flex;flex-direction: row-reverse; margin-bottom: 10px;">
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
size="small"
|
|
||||||
icon="el-icon-download"
|
|
||||||
@click="exportPDF"
|
|
||||||
:loading="pdfExporting"
|
|
||||||
>导出PDF</el-button>
|
|
||||||
</div>
|
|
||||||
<div class="approve-container" :class="{ 'exporting-pdf': pdfExporting }">
|
|
||||||
<ApproveLayout ref="approveLayout" title="付款单详情">
|
|
||||||
<payment-detail :data="form"></payment-detail>
|
|
||||||
<template #footer>
|
|
||||||
<span>付款编号: {{ form.paymentBillCode }}</span>
|
|
||||||
</template>
|
|
||||||
</ApproveLayout>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-divider content-position="left">流转意见</el-divider>
|
|
||||||
<div class="process-container">
|
|
||||||
<el-timeline>
|
|
||||||
<el-timeline-item v-for="(log, index) in approveLogs" :key="index" :timestamp="log.approveTime" placement="top">
|
|
||||||
<el-card>
|
|
||||||
<h4>{{ log.approveOpinion }}</h4>
|
|
||||||
<p><b>操作人:</b> {{ log.approveUserName }} </p>
|
|
||||||
<p><b>审批状态:</b> <el-tag :type="log.approveStatus == '3' ? 'success' : log.approveStatus == '2' ? 'danger' : 'info'">{{ getStatusText(log.approveStatus) }}</el-tag></p>
|
|
||||||
</el-card>
|
|
||||||
</el-timeline-item>
|
|
||||||
</el-timeline>
|
|
||||||
<div v-if="!approveLogs || approveLogs.length === 0">暂无流转过程数据。</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<span slot="footer" class="dialog-footer">
|
|
||||||
<el-button type="primary" @click="openOpinionDialog('approve')">同意</el-button>
|
|
||||||
<el-button type="danger" @click="openOpinionDialog('reject')">驳回</el-button>
|
|
||||||
<el-button @click="detailDialogVisible = false">取 消</el-button>
|
|
||||||
</span>
|
|
||||||
</el-dialog>
|
|
||||||
|
|
||||||
<!-- 审批意见对话框 -->
|
|
||||||
<el-dialog :title="confirmDialogTitle" :visible.sync="opinionDialogVisible" width="30%" append-to-body>
|
|
||||||
<el-form ref="opinionForm" :model="opinionForm" :rules="opinionRules" label-width="100px">
|
|
||||||
<el-form-item label="审批意见" prop="approveOpinion">
|
|
||||||
<el-input v-model="opinionForm.approveOpinion" type="textarea" :rows="4" placeholder="请输入审批意见"/>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<span slot="footer" class="dialog-footer">
|
|
||||||
<el-button @click="opinionDialogVisible = false">取 消</el-button>
|
|
||||||
<el-button type="primary" @click="showConfirmDialog()">确 定</el-button>
|
|
||||||
</span>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { listPaymentApprove, getPayment } from "@/api/finance/payment";
|
|
||||||
import { approveTask, listCompletedFlows } from "@/api/flow";
|
|
||||||
import PaymentDetail from "./components/PaymentRefundDetail.vue";
|
|
||||||
import ApproveLayout from "@/views/approve/ApproveLayout";
|
|
||||||
import { exportElementToPDF } from "@/views/approve/finance/pdfUtils";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "PaymentApprove",
|
|
||||||
components: { PaymentDetail, ApproveLayout },
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
loading: true,
|
|
||||||
showSearch: true,
|
|
||||||
total: 0,
|
|
||||||
paymentList: [],
|
|
||||||
queryParams: {
|
|
||||||
pageNum: 1,
|
|
||||||
pageSize: 10,
|
|
||||||
paymentNo: null,
|
|
||||||
manufacturer: null,
|
|
||||||
projectName: null,
|
|
||||||
processKey: 'finance_refund',
|
|
||||||
orderByColumn: 'applyTime',
|
|
||||||
isAsc: 'desc'
|
|
||||||
},
|
|
||||||
dateRange: [],
|
|
||||||
detailDialogVisible: false,
|
|
||||||
detailLoading: false,
|
|
||||||
form: {},
|
|
||||||
approveLogs: [],
|
|
||||||
opinionDialogVisible: false,
|
|
||||||
confirmDialogTitle: '',
|
|
||||||
currentApproveType: '',
|
|
||||||
opinionForm: {
|
|
||||||
approveOpinion: ''
|
|
||||||
},
|
|
||||||
opinionRules: {
|
|
||||||
approveOpinion: [{ required: true, message: '审批意见不能为空', trigger: 'blur' }],
|
|
||||||
},
|
|
||||||
processKey: 'finance_refund',
|
|
||||||
taskId: null,
|
|
||||||
currentPaymentId: null,
|
|
||||||
pdfExporting: false
|
|
||||||
};
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.getList();
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getList() {
|
|
||||||
this.loading = true;
|
|
||||||
listPaymentApprove(this.addDateRange(this.queryParams, this.dateRange, 'ApplyTime')).then(response => {
|
|
||||||
this.paymentList = response.rows;
|
|
||||||
this.total = response.total;
|
|
||||||
this.loading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
handleQuery() {
|
|
||||||
this.queryParams.pageNum = 1;
|
|
||||||
this.getList();
|
|
||||||
},
|
|
||||||
resetQuery() {
|
|
||||||
this.dateRange = [];
|
|
||||||
this.resetForm("queryForm");
|
|
||||||
this.handleQuery();
|
|
||||||
},
|
|
||||||
toApproved() {
|
|
||||||
this.$router.push( '/approve/paymentRedLog' )
|
|
||||||
},
|
|
||||||
handleApprove(row) {
|
|
||||||
this.resetDetailForm();
|
|
||||||
this.currentPaymentId = row.id;
|
|
||||||
this.taskId = row.taskId;
|
|
||||||
this.detailLoading = true;
|
|
||||||
this.detailDialogVisible = true;
|
|
||||||
|
|
||||||
getPayment(this.currentPaymentId).then(response => {
|
|
||||||
this.form = response.data;
|
|
||||||
this.loadApproveHistory(this.form.paymentBillCode);
|
|
||||||
this.detailLoading = false;
|
|
||||||
}).catch(() => {
|
|
||||||
this.detailLoading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
resetDetailForm() {
|
|
||||||
this.form = {};
|
|
||||||
this.approveLogs = [];
|
|
||||||
this.opinionForm.approveOpinion = '';
|
|
||||||
},
|
|
||||||
loadApproveHistory(businessKey) {
|
|
||||||
if (businessKey) {
|
|
||||||
// Assuming processKeyList might be generic or specific, using generic fetch for now
|
|
||||||
// Usually need to know the specific process key. For payment, it might be 'payment_approval' etc.
|
|
||||||
// However, listCompletedFlows logic in reference used specific keys.
|
|
||||||
// If I don't know the key, maybe I can omit it or guess.
|
|
||||||
// The reference used `processKeyList: ['purchase_order_online']`.
|
|
||||||
// I will use a generic one or try to find it.
|
|
||||||
// If row.processKey is available I can use that.
|
|
||||||
let keys = [];
|
|
||||||
console.log(this.processKey)
|
|
||||||
if(this.processKey) keys.push(this.processKey);
|
|
||||||
|
|
||||||
listCompletedFlows({ businessKey: businessKey, processKeyList: keys }).then(response => {
|
|
||||||
this.approveLogs = response.data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
openOpinionDialog(type) {
|
|
||||||
this.currentApproveType = type;
|
|
||||||
this.confirmDialogTitle = type === 'approve' ? '同意审批' : '驳回审批';
|
|
||||||
this.opinionDialogVisible = true;
|
|
||||||
this.opinionForm.approveOpinion = '';
|
|
||||||
this.$nextTick(() => {
|
|
||||||
if(this.$refs.opinionForm) this.$refs.opinionForm.clearValidate();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
showConfirmDialog() {
|
|
||||||
this.$refs.opinionForm.validate(valid => {
|
|
||||||
if (valid) {
|
|
||||||
this.opinionDialogVisible = false;
|
|
||||||
this.submitApproval();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
submitApproval() {
|
|
||||||
const approveBtn = this.currentApproveType === 'approve' ? 1 : 0;
|
|
||||||
const params = {
|
|
||||||
businessKey: this.form.paymentBillCode,
|
|
||||||
processKey: this.processKey,
|
|
||||||
taskId: this.taskId,
|
|
||||||
variables: {
|
|
||||||
comment: this.opinionForm.approveOpinion,
|
|
||||||
approveBtn: approveBtn
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
approveTask(params).then(() => {
|
|
||||||
this.$modal.msgSuccess(this.confirmDialogTitle + "成功");
|
|
||||||
this.detailDialogVisible = false;
|
|
||||||
this.getList();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
getStatusText(status) {
|
|
||||||
if (!status) {
|
|
||||||
return '提交审批'
|
|
||||||
}
|
|
||||||
// Map status codes to text
|
|
||||||
const map = { '1': '提交审批', '2': '驳回', '3': '批准' };
|
|
||||||
return map[status] || '提交审批';
|
|
||||||
},
|
|
||||||
async exportPDF() {
|
|
||||||
this.pdfExporting = true;
|
|
||||||
try {
|
|
||||||
const element = this.$refs.approveLayout.$el;
|
|
||||||
const fileName = `付款单-${this.form.paymentBillCode || ''}.pdf`;
|
|
||||||
await exportElementToPDF(element, fileName);
|
|
||||||
this.$modal.msgSuccess('PDF导出成功');
|
|
||||||
} catch (error) {
|
|
||||||
console.error('PDF导出失败:', error);
|
|
||||||
this.$modal.msgError('PDF导出失败,请稍后重试');
|
|
||||||
} finally {
|
|
||||||
this.pdfExporting = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.process-container {
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 导出PDF时的特殊样式 */
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-button--primary,
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-button--text {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-input__inner,
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-textarea__inner {
|
|
||||||
border: none !important;
|
|
||||||
box-shadow: none !important;
|
|
||||||
background-color: transparent !important;
|
|
||||||
resize: none !important;
|
|
||||||
padding: 0 !important;
|
|
||||||
}
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-input__suffix {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
import html2canvas from 'html2canvas';
|
|
||||||
import jsPDF from 'jspdf';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 导出指定DOM元素为PDF
|
|
||||||
* @param {HTMLElement} element - 要导出的DOM元素
|
|
||||||
* @param {string} fileName - 导出的文件名
|
|
||||||
* @returns {Promise<void>}
|
|
||||||
*/
|
|
||||||
export async function exportElementToPDF(element, fileName) {
|
|
||||||
const disabledElements = [];
|
|
||||||
try {
|
|
||||||
// 移除所有输入框的 disabled 属性,以便在PDF中正确显示
|
|
||||||
element.querySelectorAll('input:disabled, textarea:disabled').forEach(el => {
|
|
||||||
disabledElements.push(el);
|
|
||||||
el.disabled = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
// 使用html2canvas捕获内容
|
|
||||||
const canvas = await html2canvas(element, {
|
|
||||||
scale: 2, // 提高清晰度
|
|
||||||
useCORS: true, // 允许跨域图片
|
|
||||||
logging: false, // 关闭日志
|
|
||||||
backgroundColor: '#F8F5F0' // 设置背景色
|
|
||||||
});
|
|
||||||
|
|
||||||
// 计算PDF页面尺寸
|
|
||||||
const imgWidth = 210; // A4纸宽度(mm)
|
|
||||||
const pageHeight = 297; // A4纸高度(mm)
|
|
||||||
const imgHeight = (canvas.height * imgWidth) / canvas.width;
|
|
||||||
let heightLeft = imgHeight;
|
|
||||||
|
|
||||||
// 创建PDF
|
|
||||||
const pdf = new jsPDF('p', 'mm', 'a4');
|
|
||||||
let position = 0;
|
|
||||||
|
|
||||||
// 将canvas转换为图片
|
|
||||||
const imgData = canvas.toDataURL('image/jpeg');
|
|
||||||
|
|
||||||
// 添加第一页
|
|
||||||
pdf.addImage(imgData, 'JPEG', 0, position, imgWidth, imgHeight);
|
|
||||||
heightLeft -= pageHeight;
|
|
||||||
|
|
||||||
// 如果内容超过一页,添加更多页
|
|
||||||
while (heightLeft > 0) {
|
|
||||||
position = heightLeft - imgHeight;
|
|
||||||
pdf.addPage();
|
|
||||||
pdf.addImage(imgData, 'JPEG', 0, position, imgWidth, imgHeight);
|
|
||||||
heightLeft -= pageHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 保存PDF
|
|
||||||
pdf.save(fileName);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('PDF导出失败:', error);
|
|
||||||
throw error;
|
|
||||||
} finally {
|
|
||||||
// 恢复之前移除的 disabled 属性
|
|
||||||
disabledElements.forEach(el => {
|
|
||||||
el.disabled = true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,215 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="app-container">
|
|
||||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="120px">
|
|
||||||
<el-form-item label="收款编号" prop="receiptBillCode">
|
|
||||||
<el-input v-model="queryParams.receiptBillCode" placeholder="请输入收款编号" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="进货商" prop="partnerName">
|
|
||||||
<el-input v-model="queryParams.partnerName" placeholder="请输入进货商" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="项目名称" prop="projectName">
|
|
||||||
<el-input v-model="queryParams.projectName" placeholder="请输入项目名称" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="提交日期">
|
|
||||||
<el-date-picker
|
|
||||||
v-model="dateRange"
|
|
||||||
style="width: 240px"
|
|
||||||
value-format="yyyy-MM-dd"
|
|
||||||
type="daterange"
|
|
||||||
range-separator="-"
|
|
||||||
start-placeholder="开始日期"
|
|
||||||
end-placeholder="结束日期"
|
|
||||||
></el-date-picker>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
|
||||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
|
|
||||||
<el-table v-loading="loading" :data="receiptList">
|
|
||||||
<el-table-column label="序号" type="index" width="50" align="center" />
|
|
||||||
<el-table-column label="收款编号" align="center" prop="receiptBillCode" />
|
|
||||||
<el-table-column label="客户" align="center" prop="partnerName" />
|
|
||||||
<!-- <el-table-column label="项目名称" align="center" prop="projectName" />-->
|
|
||||||
<el-table-column label="金额" align="center" prop="totalPriceWithTax" :formatter="(row, column, cellValue)=>formatCurrency(cellValue)"/>
|
|
||||||
<!-- <el-table-column label="汇智负责人" align="center" prop="hzUserName" />-->
|
|
||||||
<el-table-column label="提交日期" align="center" prop="applyTime" width="180">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<span>{{ parseTime(scope.row.applyTime) }}</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="审批节点" align="center" prop="approveNode" />
|
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="200">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<el-button size="mini" type="text" icon="el-icon-view" @click="handleView(scope.row)">详情</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
|
|
||||||
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList"/>
|
|
||||||
|
|
||||||
<!-- 详情对话框 -->
|
|
||||||
<el-dialog title="收款单详情" :visible.sync="detailDialogVisible" width="80%" append-to-body>
|
|
||||||
<div v-loading="detailLoading" style="max-height: 70vh; overflow-y: auto; padding: 20px;">
|
|
||||||
<div style="display: flex;flex-direction: row-reverse; margin-bottom: 10px;">
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
size="small"
|
|
||||||
icon="el-icon-download"
|
|
||||||
@click="exportPDF"
|
|
||||||
:loading="pdfExporting"
|
|
||||||
>导出PDF</el-button>
|
|
||||||
</div>
|
|
||||||
<div class="approve-container" :class="{ 'exporting-pdf': pdfExporting }">
|
|
||||||
<ApproveLayout ref="approveLayout" title="收款单详情">
|
|
||||||
<receipt-detail :data="form"></receipt-detail>
|
|
||||||
<template #footer>
|
|
||||||
<span>{{ form.receiptBillCode }}</span>
|
|
||||||
</template>
|
|
||||||
</ApproveLayout>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-divider content-position="left">流转意见</el-divider>
|
|
||||||
<div class="process-container">
|
|
||||||
<el-timeline>
|
|
||||||
<el-timeline-item v-for="(log, index) in approveLogs" :key="index" :timestamp="log.approveTime" placement="top">
|
|
||||||
<el-card>
|
|
||||||
<h4>{{ log.approveOpinion }}</h4>
|
|
||||||
<p><b>操作人:</b> {{ log.approveUserName }} </p>
|
|
||||||
<p><b>审批状态:</b> <el-tag :type="log.approveStatus == '3' ? 'success' : log.approveStatus == '2' ? 'danger' : 'info'">{{ getStatusText(log.approveStatus) }}</el-tag></p>
|
|
||||||
</el-card>
|
|
||||||
</el-timeline-item>
|
|
||||||
</el-timeline>
|
|
||||||
<div v-if="!approveLogs || approveLogs.length === 0">暂无流转过程数据。</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<span slot="footer" class="dialog-footer">
|
|
||||||
<el-button @click="detailDialogVisible = false">关 闭</el-button>
|
|
||||||
</span>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { listReceiptApproved, getReceiptDetail } from "@/api/finance/receipt";
|
|
||||||
import { listCompletedFlows } from "@/api/flow";
|
|
||||||
import ReceiptDetail from "../components/ReceiptDetail";
|
|
||||||
import ApproveLayout from "@/views/approve/ApproveLayout";
|
|
||||||
import { exportElementToPDF } from "@/views/approve/finance/pdfUtils";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "ReceiptApproved",
|
|
||||||
components: { ReceiptDetail, ApproveLayout },
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
loading: true,
|
|
||||||
showSearch: true,
|
|
||||||
total: 0,
|
|
||||||
receiptList: [],
|
|
||||||
queryParams: {
|
|
||||||
pageNum: 1,
|
|
||||||
pageSize: 10,
|
|
||||||
receiptBillCode: null,
|
|
||||||
partnerName: null,
|
|
||||||
projectName: null,
|
|
||||||
processKey: 'finance_receipt_approve',
|
|
||||||
orderByColumn: 'applyTime',
|
|
||||||
isAsc: 'desc'
|
|
||||||
},
|
|
||||||
dateRange: [],
|
|
||||||
detailDialogVisible: false,
|
|
||||||
detailLoading: false,
|
|
||||||
form: {},
|
|
||||||
approveLogs: [],
|
|
||||||
currentReceiptId: null,
|
|
||||||
pdfExporting: false
|
|
||||||
};
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.getList();
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getList() {
|
|
||||||
this.loading = true;
|
|
||||||
listReceiptApproved(this.addDateRange(this.queryParams, this.dateRange, 'ApplyTime')).then(response => {
|
|
||||||
this.receiptList = response.rows;
|
|
||||||
this.total = response.total;
|
|
||||||
this.loading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
handleQuery() {
|
|
||||||
this.queryParams.pageNum = 1;
|
|
||||||
this.getList();
|
|
||||||
},
|
|
||||||
resetQuery() {
|
|
||||||
this.dateRange = [];
|
|
||||||
this.resetForm("queryForm");
|
|
||||||
this.handleQuery();
|
|
||||||
},
|
|
||||||
handleView(row) {
|
|
||||||
this.form = {};
|
|
||||||
this.approveLogs = [];
|
|
||||||
this.currentReceiptId = row.id;
|
|
||||||
this.detailLoading = true;
|
|
||||||
this.detailDialogVisible = true;
|
|
||||||
|
|
||||||
getReceiptDetail(this.currentReceiptId).then(response => {
|
|
||||||
this.form = response.data;
|
|
||||||
this.loadApproveHistory(this.form.receiptBillCode);
|
|
||||||
this.detailLoading = false;
|
|
||||||
}).catch(() => {
|
|
||||||
this.detailLoading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
loadApproveHistory(businessKey) {
|
|
||||||
if (businessKey) {
|
|
||||||
listCompletedFlows({ businessKey: businessKey }).then(response => {
|
|
||||||
this.approveLogs = response.data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getStatusText(status) {
|
|
||||||
const map = { '1': '提交审批', '2': '驳回', '3': '批准' };
|
|
||||||
return map[status] || '提交审批';
|
|
||||||
},
|
|
||||||
async exportPDF() {
|
|
||||||
this.pdfExporting = true;
|
|
||||||
try {
|
|
||||||
const element = this.$refs.approveLayout.$el;
|
|
||||||
const fileName = `收款单-${this.form.receiptBillCode || ''}.pdf`;
|
|
||||||
await exportElementToPDF(element, fileName);
|
|
||||||
this.$modal.msgSuccess('PDF导出成功');
|
|
||||||
} catch (error) {
|
|
||||||
console.error('PDF导出失败:', error);
|
|
||||||
this.$modal.msgError('PDF导出失败,请稍后重试');
|
|
||||||
} finally {
|
|
||||||
this.pdfExporting = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.process-container {
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 导出PDF时的特殊样式 */
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-button--primary,
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-button--text {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-input__inner,
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-textarea__inner {
|
|
||||||
border: none !important;
|
|
||||||
box-shadow: none !important;
|
|
||||||
background-color: transparent !important;
|
|
||||||
resize: none !important;
|
|
||||||
padding: 0 !important;
|
|
||||||
}
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-input__suffix {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,147 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="receipt-detail">
|
|
||||||
<div style="text-align: center;font-weight:bold;font-size: 25px;">收款申请单</div>
|
|
||||||
<el-descriptions title="收款单信息" :column="3" border>
|
|
||||||
<el-descriptions-item label="销售-收款单编号">{{ data.receiptBillCode }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item :span="2" label="进货商名称">{{ data.partnerName }}</el-descriptions-item>
|
|
||||||
<!-- <el-descriptions-item label="收款单类型">-->
|
|
||||||
<!-- <dict-tag :options="dict.type.receipt_bill_type" :value="data.receiptBillType"/>-->
|
|
||||||
<!-- </el-descriptions-item>-->
|
|
||||||
<el-descriptions-item label="含税总价(元)">{{ formatCurrency(data.totalPriceWithTax) }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="未税总价(元)">{{ formatCurrency(data.totalPriceWithoutTax) }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="税额(元)">{{ formatCurrency(data.taxAmount) }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="支付方式">
|
|
||||||
<dict-tag :options="dict.type.payment_method" :value="data.receiptMethod"/>
|
|
||||||
</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="银行账号">{{ data.receiptBankNumber }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="账户名称">{{ data.receiptAccountName }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="银行开户行">{{ data.receiptBankOpenAddress }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="银行行号">{{ data.bankNumber }}</el-descriptions-item>
|
|
||||||
<!-- <el-descriptions-item label="备注" :span="3">{{ data.remark }}</el-descriptions-item>-->
|
|
||||||
</el-descriptions>
|
|
||||||
|
|
||||||
<div class="section" style="margin-top: 20px;" v-show="data.detailDTOList && data.detailDTOList.length>0">
|
|
||||||
<div class="el-descriptions__title">应收单列表</div>
|
|
||||||
<el-table :data="data.detailDTOList" border style="width: 100%; margin-top: 10px;">
|
|
||||||
<el-table-column type="index" label="序号" width="50" align="center"></el-table-column>
|
|
||||||
<el-table-column prop="receivableBillCode" label="销售-应收单编号" align="center"></el-table-column>
|
|
||||||
<el-table-column prop="projectName" label="项目名称" align="center"></el-table-column>
|
|
||||||
<el-table-column prop="productType" label="产品类型" align="center">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<dict-tag :options="dict.type.product_type" :value="scope.row.productType"/>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="totalPriceWithTax" label="含税总价" align="center" :formatter="(row, column, cellValue)=>formatCurrency(cellValue)"></el-table-column>
|
|
||||||
<el-table-column prop="receiptAmount" label="本次收款金额" align="center" :formatter="(row, column, cellValue)=>formatCurrency(cellValue)"></el-table-column>
|
|
||||||
</el-table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="section" style="margin-top: 20px;" v-if="attachments && attachments.length > 0">
|
|
||||||
<div class="el-descriptions__title">附件信息</div>
|
|
||||||
<el-table :data="attachments" border style="width: 100%; margin-top: 10px;">
|
|
||||||
<el-table-column prop="fileName" label="附件名称" align="center"></el-table-column>
|
|
||||||
<el-table-column prop="createByName" label="上传人" align="center"></el-table-column>
|
|
||||||
<el-table-column prop="createTime" label="上传时间" align="center"></el-table-column>
|
|
||||||
<el-table-column label="操作" align="center">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<el-button size="mini" type="text" icon="el-icon-view" @click="handlePreview(scope.row)">预览</el-button>
|
|
||||||
<el-button size="mini" type="text" icon="el-icon-download" @click="handleDownload(scope.row)">下载</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-dialog :visible.sync="pdfPreviewVisible" width="80%" append-to-body top="5vh" title="PDF预览">
|
|
||||||
<iframe :src="currentPdfUrl" width="100%" height="600px" frameborder="0"></iframe>
|
|
||||||
</el-dialog>
|
|
||||||
|
|
||||||
<el-dialog :visible.sync="imagePreviewVisible" width="60%" append-to-body top="5vh" title="图片预览">
|
|
||||||
<img :src="currentImageUrl" style="width: 100%;" />
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
import request from '@/utils/request';
|
|
||||||
import {getInvoiceAttachments} from "@/api/finance/invoice";
|
|
||||||
import {getReceiptAttachments} from "@/api/finance/receipt";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "ReceiptDetail",
|
|
||||||
props: {
|
|
||||||
data: {
|
|
||||||
type: Object,
|
|
||||||
required: true,
|
|
||||||
default: () => ({})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
dicts: ['receipt_bill_type', 'product_type','payment_method'],
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
attachments: [],
|
|
||||||
pdfPreviewVisible: false,
|
|
||||||
currentPdfUrl: '',
|
|
||||||
imagePreviewVisible: false,
|
|
||||||
currentImageUrl: ''
|
|
||||||
};
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
'data.id': {
|
|
||||||
handler(val) {
|
|
||||||
if (val) {
|
|
||||||
this.fetchAttachments(val);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
immediate: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
fetchAttachments(id) {
|
|
||||||
getReceiptAttachments(id,{type: "receipt"}).then(response => {
|
|
||||||
this.attachments = (response.data || []).filter(item => item.delFlag !== '2');
|
|
||||||
});
|
|
||||||
},
|
|
||||||
isPdf(filePath) {
|
|
||||||
return filePath && filePath.toLowerCase().endsWith('.pdf');
|
|
||||||
},
|
|
||||||
getImageUrl(resource) {
|
|
||||||
return process.env.VUE_APP_BASE_API + "/common/download/resource?resource=" + resource;
|
|
||||||
},
|
|
||||||
handlePreview(row) {
|
|
||||||
if (this.isPdf(row.filePath)) {
|
|
||||||
// PDF Preview logic
|
|
||||||
request({
|
|
||||||
url: '/common/download/resource',
|
|
||||||
method: 'get',
|
|
||||||
params: { resource: row.filePath },
|
|
||||||
responseType: 'blob'
|
|
||||||
}).then(res => {
|
|
||||||
const blob = new Blob([res.data], { type: 'application/pdf' });
|
|
||||||
this.currentPdfUrl = URL.createObjectURL(blob);
|
|
||||||
this.pdfPreviewVisible = true;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// Image Preview
|
|
||||||
this.currentImageUrl = this.getImageUrl(row.filePath);
|
|
||||||
this.imagePreviewVisible = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleDownload(row) {
|
|
||||||
const link = document.createElement('a');
|
|
||||||
link.href = this.getImageUrl(row.filePath);
|
|
||||||
link.download = row.fileName || 'attachment';
|
|
||||||
link.style.display = 'none';
|
|
||||||
document.body.appendChild(link);
|
|
||||||
link.click();
|
|
||||||
document.body.removeChild(link);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.receipt-detail {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,302 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="app-container">
|
|
||||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="120px">
|
|
||||||
<el-form-item label="收款编号" prop="receiptBillCode">
|
|
||||||
<el-input v-model="queryParams.receiptBillCode" placeholder="请输入收款编号" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="进货商" prop="partnerName">
|
|
||||||
<el-input v-model="queryParams.partnerName" placeholder="请输入进货商名称" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="项目名称" prop="projectName">
|
|
||||||
<el-input v-model="queryParams.projectName" placeholder="请输入项目名称" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="提交日期">
|
|
||||||
<el-date-picker
|
|
||||||
v-model="dateRange"
|
|
||||||
style="width: 240px"
|
|
||||||
value-format="yyyy-MM-dd HH:mm:ss"
|
|
||||||
type="daterange"
|
|
||||||
range-separator="-"
|
|
||||||
start-placeholder="开始日期"
|
|
||||||
end-placeholder="结束日期"
|
|
||||||
></el-date-picker>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
|
||||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
|
|
||||||
<el-row :gutter="10" class="mb8">
|
|
||||||
<el-col :span="1.5">
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
plain
|
|
||||||
size="mini"
|
|
||||||
@click="toApproved()"
|
|
||||||
>审批历史</el-button>
|
|
||||||
</el-col>
|
|
||||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
|
||||||
</el-row>
|
|
||||||
|
|
||||||
<el-table v-loading="loading" :data="receiptList">
|
|
||||||
<el-table-column label="序号" type="index" width="50" align="center" />
|
|
||||||
<el-table-column label="收款编号" align="center" prop="receiptBillCode" />
|
|
||||||
<el-table-column label="进货商" align="center" prop="partnerName" />
|
|
||||||
<!-- <el-table-column label="项目名称" align="center" prop="projectName" />-->
|
|
||||||
<el-table-column label="金额" align="center" prop="totalPriceWithTax" :formatter="(row, column, cellValue)=>formatCurrency(cellValue)"/>
|
|
||||||
<!-- <el-table-column label="汇智负责人" align="center" prop="hzUserName" />-->
|
|
||||||
<el-table-column label="提交日期" align="center" prop="applyTime" width="180">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<span>{{ parseTime(scope.row.applyTime, '{y}-{m}-{d}') }}</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="审批节点" align="center" prop="approveNode" />
|
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="200">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleApprove(scope.row)">审批</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
|
|
||||||
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList"/>
|
|
||||||
|
|
||||||
<!-- 审批详情主对话框 -->
|
|
||||||
<el-dialog title="收款单审批" :visible.sync="detailDialogVisible" width="80%" append-to-body>
|
|
||||||
<div v-loading="detailLoading" style="max-height: 70vh; overflow-y: auto; padding: 20px;">
|
|
||||||
<div style="display: flex;flex-direction: row-reverse; margin-bottom: 10px;">
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
size="small"
|
|
||||||
icon="el-icon-download"
|
|
||||||
@click="exportPDF"
|
|
||||||
:loading="pdfExporting"
|
|
||||||
>导出PDF</el-button>
|
|
||||||
</div>
|
|
||||||
<div class="approve-container" :class="{ 'exporting-pdf': pdfExporting }">
|
|
||||||
<ApproveLayout ref="approveLayout" title="收款单详情">
|
|
||||||
<receipt-detail :data="form"></receipt-detail>
|
|
||||||
<template #footer>
|
|
||||||
<span>{{ form.receiptBillCode }}</span>
|
|
||||||
</template>
|
|
||||||
</ApproveLayout>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-divider content-position="left">流转意见</el-divider>
|
|
||||||
<div class="process-container">
|
|
||||||
<el-timeline>
|
|
||||||
<el-timeline-item v-for="(log, index) in approveLogs" :key="index" :timestamp="log.approveTime" placement="top">
|
|
||||||
<el-card>
|
|
||||||
<h4>{{ log.approveOpinion }}</h4>
|
|
||||||
<p><b>操作人:</b> {{ log.approveUserName }} </p>
|
|
||||||
<p><b>审批状态:</b> <el-tag :type="log.approveStatus == '3' ? 'success' : log.approveStatus == '2' ? 'danger' : 'info'">{{ getStatusText(log.approveStatus) }}</el-tag></p>
|
|
||||||
</el-card>
|
|
||||||
</el-timeline-item>
|
|
||||||
</el-timeline>
|
|
||||||
<div v-if="!approveLogs || approveLogs.length === 0">暂无流转过程数据。</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<span slot="footer" class="dialog-footer">
|
|
||||||
<el-button type="primary" @click="openOpinionDialog('approve')">同意</el-button>
|
|
||||||
<el-button type="danger" @click="openOpinionDialog('reject')">驳回</el-button>
|
|
||||||
<el-button @click="detailDialogVisible = false">取 消</el-button>
|
|
||||||
</span>
|
|
||||||
</el-dialog>
|
|
||||||
|
|
||||||
<!-- 审批意见对话框 -->
|
|
||||||
<el-dialog :title="confirmDialogTitle" :visible.sync="opinionDialogVisible" width="30%" append-to-body>
|
|
||||||
<el-form ref="opinionForm" :model="opinionForm" :rules="opinionRules" label-width="100px">
|
|
||||||
<el-form-item label="审批意见" prop="approveOpinion">
|
|
||||||
<el-input v-model="opinionForm.approveOpinion" type="textarea" :rows="4" placeholder="请输入审批意见"/>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<span slot="footer" class="dialog-footer">
|
|
||||||
<el-button @click="opinionDialogVisible = false">取 消</el-button>
|
|
||||||
<el-button type="primary" @click="showConfirmDialog()">确 定</el-button>
|
|
||||||
</span>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { listReceiptApprove, getReceiptDetail } from "@/api/finance/receipt";
|
|
||||||
import { approveTask, listCompletedFlows } from "@/api/flow";
|
|
||||||
import ReceiptDetail from "./components/ReceiptDetail";
|
|
||||||
import ApproveLayout from "@/views/approve/ApproveLayout";
|
|
||||||
import { exportElementToPDF } from "@/views/approve/finance/pdfUtils";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "ReceiptApprove",
|
|
||||||
components: { ReceiptDetail, ApproveLayout },
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
loading: true,
|
|
||||||
showSearch: true,
|
|
||||||
total: 0,
|
|
||||||
receiptList: [],
|
|
||||||
queryParams: {
|
|
||||||
pageNum: 1,
|
|
||||||
pageSize: 10,
|
|
||||||
receiptBillCode: null,
|
|
||||||
partnerName: null,
|
|
||||||
projectName: null,
|
|
||||||
processKey: 'finance_receipt_approve',
|
|
||||||
orderByColumn: 'applyTime',
|
|
||||||
isAsc: 'desc'
|
|
||||||
},
|
|
||||||
dateRange: [],
|
|
||||||
detailDialogVisible: false,
|
|
||||||
detailLoading: false,
|
|
||||||
form: {},
|
|
||||||
approveLogs: [],
|
|
||||||
opinionDialogVisible: false,
|
|
||||||
confirmDialogTitle: '',
|
|
||||||
currentApproveType: '',
|
|
||||||
opinionForm: {
|
|
||||||
approveOpinion: ''
|
|
||||||
},
|
|
||||||
opinionRules: {
|
|
||||||
approveOpinion: [{ required: true, message: '审批意见不能为空', trigger: 'blur' }],
|
|
||||||
},
|
|
||||||
processKey: 'finance_receipt_approve',
|
|
||||||
taskId: null,
|
|
||||||
currentReceiptId: null,
|
|
||||||
pdfExporting: false
|
|
||||||
};
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.getList();
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getList() {
|
|
||||||
this.loading = true;
|
|
||||||
listReceiptApprove(this.addDateRange(this.queryParams, this.dateRange, 'ApplyTime')).then(response => {
|
|
||||||
this.receiptList = response.rows;
|
|
||||||
this.total = response.total;
|
|
||||||
this.loading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
handleQuery() {
|
|
||||||
this.queryParams.pageNum = 1;
|
|
||||||
this.getList();
|
|
||||||
},
|
|
||||||
resetQuery() {
|
|
||||||
this.dateRange = [];
|
|
||||||
this.resetForm("queryForm");
|
|
||||||
this.handleQuery();
|
|
||||||
},
|
|
||||||
toApproved() {
|
|
||||||
this.$router.push( '/approve/receiptLog' )
|
|
||||||
},
|
|
||||||
handleApprove(row) {
|
|
||||||
this.resetDetailForm();
|
|
||||||
this.currentReceiptId = row.id;
|
|
||||||
this.taskId = row.taskId;
|
|
||||||
this.detailLoading = true;
|
|
||||||
this.detailDialogVisible = true;
|
|
||||||
|
|
||||||
getReceiptDetail(this.currentReceiptId).then(response => {
|
|
||||||
this.form = response.data;
|
|
||||||
this.loadApproveHistory(this.form.receiptBillCode);
|
|
||||||
this.detailLoading = false;
|
|
||||||
}).catch(() => {
|
|
||||||
this.detailLoading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
resetDetailForm() {
|
|
||||||
this.form = {};
|
|
||||||
this.approveLogs = [];
|
|
||||||
this.opinionForm.approveOpinion = '';
|
|
||||||
},
|
|
||||||
loadApproveHistory(businessKey) {
|
|
||||||
if (businessKey) {
|
|
||||||
let keys = [];
|
|
||||||
if(this.processKey) keys.push(this.processKey);
|
|
||||||
|
|
||||||
listCompletedFlows({ businessKey: businessKey, processKeyList: keys }).then(response => {
|
|
||||||
this.approveLogs = response.data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
openOpinionDialog(type) {
|
|
||||||
this.currentApproveType = type;
|
|
||||||
this.confirmDialogTitle = type === 'approve' ? '同意审批' : '驳回审批';
|
|
||||||
this.opinionDialogVisible = true;
|
|
||||||
this.opinionForm.approveOpinion = '';
|
|
||||||
this.$nextTick(() => {
|
|
||||||
if(this.$refs.opinionForm) this.$refs.opinionForm.clearValidate();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
showConfirmDialog() {
|
|
||||||
this.$refs.opinionForm.validate(valid => {
|
|
||||||
if (valid) {
|
|
||||||
this.opinionDialogVisible = false;
|
|
||||||
this.submitApproval();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
submitApproval() {
|
|
||||||
const approveBtn = this.currentApproveType === 'approve' ? 1 : 0;
|
|
||||||
const params = {
|
|
||||||
businessKey: this.form.receiptBillCode,
|
|
||||||
processKey: this.processKey,
|
|
||||||
taskId: this.taskId,
|
|
||||||
variables: {
|
|
||||||
comment: this.opinionForm.approveOpinion,
|
|
||||||
approveBtn: approveBtn
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
approveTask(params).then(() => {
|
|
||||||
this.$modal.msgSuccess(this.confirmDialogTitle + "成功");
|
|
||||||
this.detailDialogVisible = false;
|
|
||||||
this.getList();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
getStatusText(status) {
|
|
||||||
if (!status) {
|
|
||||||
return '提交审批'
|
|
||||||
}
|
|
||||||
const map = { '1': '提交审批', '2': '驳回', '3': '批准' };
|
|
||||||
return map[status] || '提交审批';
|
|
||||||
},
|
|
||||||
async exportPDF() {
|
|
||||||
this.pdfExporting = true;
|
|
||||||
try {
|
|
||||||
const element = this.$refs.approveLayout.$el;
|
|
||||||
const fileName = `收款单-${this.form.receiptBillCode || ''}.pdf`;
|
|
||||||
await exportElementToPDF(element, fileName);
|
|
||||||
this.$modal.msgSuccess('PDF导出成功');
|
|
||||||
} catch (error) {
|
|
||||||
console.error('PDF导出失败:', error);
|
|
||||||
this.$modal.msgError('PDF导出失败,请稍后重试');
|
|
||||||
} finally {
|
|
||||||
this.pdfExporting = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.process-container {
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 导出PDF时的特殊样式 */
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-button--primary,
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-button--text {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-input__inner,
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-textarea__inner {
|
|
||||||
border: none !important;
|
|
||||||
box-shadow: none !important;
|
|
||||||
background-color: transparent !important;
|
|
||||||
resize: none !important;
|
|
||||||
padding: 0 !important;
|
|
||||||
}
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-input__suffix {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,215 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="app-container">
|
|
||||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="120px">
|
|
||||||
<el-form-item label="收款编号" prop="receiptBillCode">
|
|
||||||
<el-input v-model="queryParams.receiptBillCode" placeholder="请输入收款编号" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="进货商" prop="partnerName">
|
|
||||||
<el-input v-model="queryParams.partnerName" placeholder="请输入进货商" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="项目名称" prop="projectName">
|
|
||||||
<el-input v-model="queryParams.projectName" placeholder="请输入项目名称" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="提交日期">
|
|
||||||
<el-date-picker
|
|
||||||
v-model="dateRange"
|
|
||||||
style="width: 240px"
|
|
||||||
value-format="yyyy-MM-dd"
|
|
||||||
type="daterange"
|
|
||||||
range-separator="-"
|
|
||||||
start-placeholder="开始日期"
|
|
||||||
end-placeholder="结束日期"
|
|
||||||
></el-date-picker>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
|
||||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
|
|
||||||
<el-table v-loading="loading" :data="receiptList">
|
|
||||||
<el-table-column label="序号" type="index" width="50" align="center" />
|
|
||||||
<el-table-column label="收款编号" align="center" prop="receiptBillCode" />
|
|
||||||
<el-table-column label="客户" align="center" prop="partnerName" />
|
|
||||||
<!-- <el-table-column label="项目名称" align="center" prop="projectName" />-->
|
|
||||||
<el-table-column label="金额" align="center" prop="totalPriceWithTax" :formatter="(row, column, cellValue)=>formatCurrency(cellValue)" />
|
|
||||||
<!-- <el-table-column label="汇智负责人" align="center" prop="hzUserName" />-->
|
|
||||||
<el-table-column label="提交日期" align="center" prop="applyTime" width="180">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<span>{{ parseTime(scope.row.applyTime) }}</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="审批节点" align="center" prop="approveNode" />
|
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="200">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<el-button size="mini" type="text" icon="el-icon-view" @click="handleView(scope.row)">详情</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
|
|
||||||
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList"/>
|
|
||||||
|
|
||||||
<!-- 详情对话框 -->
|
|
||||||
<el-dialog title="收款单详情" :visible.sync="detailDialogVisible" width="80%" append-to-body>
|
|
||||||
<div v-loading="detailLoading" style="max-height: 70vh; overflow-y: auto; padding: 20px;">
|
|
||||||
<div style="display: flex;flex-direction: row-reverse; margin-bottom: 10px;">
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
size="small"
|
|
||||||
icon="el-icon-download"
|
|
||||||
@click="exportPDF"
|
|
||||||
:loading="pdfExporting"
|
|
||||||
>导出PDF</el-button>
|
|
||||||
</div>
|
|
||||||
<div class="approve-container" :class="{ 'exporting-pdf': pdfExporting }">
|
|
||||||
<ApproveLayout ref="approveLayout" title="收款单详情">
|
|
||||||
<receipt-detail :data="form"></receipt-detail>
|
|
||||||
<template #footer>
|
|
||||||
<span> {{ form.receiptBillCode }}</span>
|
|
||||||
</template>
|
|
||||||
</ApproveLayout>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-divider content-position="left">流转意见</el-divider>
|
|
||||||
<div class="process-container">
|
|
||||||
<el-timeline>
|
|
||||||
<el-timeline-item v-for="(log, index) in approveLogs" :key="index" :timestamp="log.approveTime" placement="top">
|
|
||||||
<el-card>
|
|
||||||
<h4>{{ log.approveOpinion }}</h4>
|
|
||||||
<p><b>操作人:</b> {{ log.approveUserName }} </p>
|
|
||||||
<p><b>审批状态:</b> <el-tag :type="log.approveStatus == '3' ? 'success' : log.approveStatus == '2' ? 'danger' : 'info'">{{ getStatusText(log.approveStatus) }}</el-tag></p>
|
|
||||||
</el-card>
|
|
||||||
</el-timeline-item>
|
|
||||||
</el-timeline>
|
|
||||||
<div v-if="!approveLogs || approveLogs.length === 0">暂无流转过程数据。</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<span slot="footer" class="dialog-footer">
|
|
||||||
<el-button @click="detailDialogVisible = false">关 闭</el-button>
|
|
||||||
</span>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { listReceiptApproved, getReceiptDetail } from "@/api/finance/receipt";
|
|
||||||
import { listCompletedFlows } from "@/api/flow";
|
|
||||||
import ReceiptDetail from "../components/ReceiptDetail";
|
|
||||||
import ApproveLayout from "@/views/approve/ApproveLayout";
|
|
||||||
import { exportElementToPDF } from "@/views/approve/finance/pdfUtils";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "ReceiptRefoundApproved",
|
|
||||||
components: { ReceiptDetail, ApproveLayout },
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
loading: true,
|
|
||||||
showSearch: true,
|
|
||||||
total: 0,
|
|
||||||
receiptList: [],
|
|
||||||
queryParams: {
|
|
||||||
pageNum: 1,
|
|
||||||
pageSize: 10,
|
|
||||||
receiptBillCode: null,
|
|
||||||
partnerName: null,
|
|
||||||
projectName: null,
|
|
||||||
processKey: 'finance_receipt_refound',
|
|
||||||
orderByColumn: 'applyTime',
|
|
||||||
isAsc: 'desc'
|
|
||||||
},
|
|
||||||
dateRange: [],
|
|
||||||
detailDialogVisible: false,
|
|
||||||
detailLoading: false,
|
|
||||||
form: {},
|
|
||||||
approveLogs: [],
|
|
||||||
currentReceiptId: null,
|
|
||||||
pdfExporting: false
|
|
||||||
};
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.getList();
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getList() {
|
|
||||||
this.loading = true;
|
|
||||||
listReceiptApproved(this.addDateRange(this.queryParams, this.dateRange, 'ApplyTime')).then(response => {
|
|
||||||
this.receiptList = response.rows;
|
|
||||||
this.total = response.total;
|
|
||||||
this.loading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
handleQuery() {
|
|
||||||
this.queryParams.pageNum = 1;
|
|
||||||
this.getList();
|
|
||||||
},
|
|
||||||
resetQuery() {
|
|
||||||
this.dateRange = [];
|
|
||||||
this.resetForm("queryForm");
|
|
||||||
this.handleQuery();
|
|
||||||
},
|
|
||||||
handleView(row) {
|
|
||||||
this.form = {};
|
|
||||||
this.approveLogs = [];
|
|
||||||
this.currentReceiptId = row.id;
|
|
||||||
this.detailLoading = true;
|
|
||||||
this.detailDialogVisible = true;
|
|
||||||
|
|
||||||
getReceiptDetail(this.currentReceiptId).then(response => {
|
|
||||||
this.form = response.data;
|
|
||||||
this.loadApproveHistory(this.form.receiptBillCode);
|
|
||||||
this.detailLoading = false;
|
|
||||||
}).catch(() => {
|
|
||||||
this.detailLoading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
loadApproveHistory(businessKey) {
|
|
||||||
if (businessKey) {
|
|
||||||
listCompletedFlows({ businessKey: businessKey }).then(response => {
|
|
||||||
this.approveLogs = response.data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getStatusText(status) {
|
|
||||||
const map = { '1': '提交审批', '2': '驳回', '3': '批准' };
|
|
||||||
return map[status] || '提交审批';
|
|
||||||
},
|
|
||||||
async exportPDF() {
|
|
||||||
this.pdfExporting = true;
|
|
||||||
try {
|
|
||||||
const element = this.$refs.approveLayout.$el;
|
|
||||||
const fileName = `收款单-${this.form.receiptBillCode || ''}.pdf`;
|
|
||||||
await exportElementToPDF(element, fileName);
|
|
||||||
this.$modal.msgSuccess('PDF导出成功');
|
|
||||||
} catch (error) {
|
|
||||||
console.error('PDF导出失败:', error);
|
|
||||||
this.$modal.msgError('PDF导出失败,请稍后重试');
|
|
||||||
} finally {
|
|
||||||
this.pdfExporting = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.process-container {
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 导出PDF时的特殊样式 */
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-button--primary,
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-button--text {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-input__inner,
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-textarea__inner {
|
|
||||||
border: none !important;
|
|
||||||
box-shadow: none !important;
|
|
||||||
background-color: transparent !important;
|
|
||||||
resize: none !important;
|
|
||||||
padding: 0 !important;
|
|
||||||
}
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-input__suffix {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,134 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="receipt-detail">
|
|
||||||
<div style="text-align: center;font-weight:bold;font-size: 25px;">退款申请单</div>
|
|
||||||
<el-descriptions title="收款单信息" :column="3" border>
|
|
||||||
<el-descriptions-item label="销售-收款单编号">{{ data.receiptBillCode }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item :span="2" label="进货商名称">{{ data.partnerName }}</el-descriptions-item>
|
|
||||||
<!-- <el-descriptions-item label="收款单类型">-->
|
|
||||||
<!-- <dict-tag :options="dict.type.receipt_bill_type" :value="data.receiptBillType"/>-->
|
|
||||||
<!-- </el-descriptions-item>-->
|
|
||||||
<el-descriptions-item label="含税总价(元)"><span style="color: red">{{ formatCurrency(data.totalPriceWithTax) }}</span></el-descriptions-item>
|
|
||||||
<el-descriptions-item label="未税总价(元)"><span style="color: red">{{ formatCurrency(data.totalPriceWithoutTax) }}</span></el-descriptions-item>
|
|
||||||
<el-descriptions-item label="税额(元)"><span style="color: red">{{ formatCurrency(data.taxAmount) }}</span></el-descriptions-item>
|
|
||||||
<el-descriptions-item label="支付方式">
|
|
||||||
<dict-tag :options="dict.type.payment_method" :value="data.receiptMethod"/>
|
|
||||||
</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="银行账号">{{ data.receiptBankNumber }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="账户名称">{{ data.receiptAccountName }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="银行开户行">{{ data.receiptBankOpenAddress }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="银行行号">{{ data.bankNumber }}</el-descriptions-item>
|
|
||||||
<!-- <el-descriptions-item label="备注" :span="3">{{ data.remark }}</el-descriptions-item>-->
|
|
||||||
</el-descriptions>
|
|
||||||
|
|
||||||
<div class="section" style="margin-top: 20px;" v-show="data.detailDTOList && data.detailDTOList.length>0">
|
|
||||||
<div class="el-descriptions__title">应收单列表</div>
|
|
||||||
<el-table :data="data.detailDTOList" border style="width: 100%; margin-top: 10px;">
|
|
||||||
<el-table-column type="index" label="序号" width="50" align="center"></el-table-column>
|
|
||||||
<el-table-column prop="receivableBillCode" label="销售-应收单编号" align="center"></el-table-column>
|
|
||||||
<el-table-column prop="projectName" label="项目名称" align="center"></el-table-column>
|
|
||||||
<el-table-column prop="productType" label="产品类型" align="center">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<dict-tag :options="dict.type.product_type" :value="scope.row.productType"/>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="totalPriceWithTax" label="含税总价" align="center" :formatter="(row, column, cellValue)=>formatCurrency(cellValue)"></el-table-column>
|
|
||||||
<el-table-column prop="receiptAmount" label="本次收款金额" align="center" :formatter="(row, column, cellValue)=>formatCurrency(cellValue)"></el-table-column>
|
|
||||||
</el-table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="section" style="margin-top: 20px;" v-if="attachments && attachments.length > 0">
|
|
||||||
<div class="el-descriptions__title">附件信息</div>
|
|
||||||
<el-table :data="attachments" border style="width: 100%; margin-top: 10px;">
|
|
||||||
<el-table-column prop="fileName" label="附件名称" align="center"></el-table-column>
|
|
||||||
<el-table-column prop="createByName" label="上传人" align="center"></el-table-column>
|
|
||||||
<el-table-column prop="createTime" label="上传时间" align="center"></el-table-column>
|
|
||||||
<el-table-column label="操作" align="center">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<el-button size="mini" type="text" icon="el-icon-view" @click="handlePreview(scope.row)">预览</el-button>
|
|
||||||
<el-button size="mini" type="text" icon="el-icon-download" @click="handleDownload(scope.row)">下载</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-dialog :visible.sync="pdfPreviewVisible" width="80%" append-to-body top="5vh" title="PDF预览">
|
|
||||||
<iframe :src="currentPdfUrl" width="100%" height="600px" frameborder="0"></iframe>
|
|
||||||
</el-dialog>
|
|
||||||
|
|
||||||
<el-dialog :visible.sync="imagePreviewVisible" width="60%" append-to-body top="5vh" title="图片预览">
|
|
||||||
<img :src="currentImageUrl" style="width: 100%;" />
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
import request from '@/utils/request';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "ReceiptRefoundDetail",
|
|
||||||
props: {
|
|
||||||
data: {
|
|
||||||
type: Object,
|
|
||||||
required: true,
|
|
||||||
default: () => ({})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
dicts: ['receipt_bill_type', 'product_type','payment_method'],
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
attachments: [],
|
|
||||||
pdfPreviewVisible: false,
|
|
||||||
currentPdfUrl: '',
|
|
||||||
imagePreviewVisible: false,
|
|
||||||
currentImageUrl: ''
|
|
||||||
};
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
|
|
||||||
isPdf(filePath) {
|
|
||||||
return filePath && filePath.toLowerCase().endsWith('.pdf');
|
|
||||||
},
|
|
||||||
getImageUrl(resource) {
|
|
||||||
return process.env.VUE_APP_BASE_API + "/common/download/resource?resource=" + resource;
|
|
||||||
},
|
|
||||||
handlePreview(row) {
|
|
||||||
if (this.isPdf(row.filePath)) {
|
|
||||||
// PDF Preview logic
|
|
||||||
request({
|
|
||||||
url: '/common/download/resource',
|
|
||||||
method: 'get',
|
|
||||||
params: { resource: row.filePath },
|
|
||||||
responseType: 'blob'
|
|
||||||
}).then(res => {
|
|
||||||
const blob = new Blob([res.data], { type: 'application/pdf' });
|
|
||||||
this.currentPdfUrl = URL.createObjectURL(blob);
|
|
||||||
this.pdfPreviewVisible = true;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// Image Preview
|
|
||||||
this.currentImageUrl = this.getImageUrl(row.filePath);
|
|
||||||
this.imagePreviewVisible = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleDownload(row) {
|
|
||||||
const link = document.createElement('a');
|
|
||||||
link.href = this.getImageUrl(row.filePath);
|
|
||||||
link.download = row.fileName || 'attachment';
|
|
||||||
link.style.display = 'none';
|
|
||||||
document.body.appendChild(link);
|
|
||||||
link.click();
|
|
||||||
document.body.removeChild(link);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.receipt-detail {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,306 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="app-container">
|
|
||||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="120px">
|
|
||||||
<el-form-item label="收款编号" prop="receiptBillCode">
|
|
||||||
<el-input v-model="queryParams.receiptBillCode" placeholder="请输入收款编号" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="进货商" prop="partnerName">
|
|
||||||
<el-input v-model="queryParams.partnerName" placeholder="请输入进货商名称" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="项目名称" prop="projectName">
|
|
||||||
<el-input v-model="queryParams.projectName" placeholder="请输入项目名称" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="提交日期">
|
|
||||||
<el-date-picker
|
|
||||||
v-model="dateRange"
|
|
||||||
style="width: 240px"
|
|
||||||
value-format="yyyy-MM-dd HH:mm:ss"
|
|
||||||
type="daterange"
|
|
||||||
range-separator="-"
|
|
||||||
start-placeholder="开始日期"
|
|
||||||
end-placeholder="结束日期"
|
|
||||||
></el-date-picker>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
|
||||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
|
|
||||||
<el-row :gutter="10" class="mb8">
|
|
||||||
<el-col :span="1.5">
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
plain
|
|
||||||
size="mini"
|
|
||||||
@click="toApproved()"
|
|
||||||
>审批历史</el-button>
|
|
||||||
</el-col>
|
|
||||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
|
||||||
</el-row>
|
|
||||||
|
|
||||||
<el-table v-loading="loading" :data="receiptList">
|
|
||||||
<el-table-column label="序号" type="index" width="50" align="center" />
|
|
||||||
<el-table-column label="收款编号" align="center" prop="receiptBillCode" />
|
|
||||||
<el-table-column label="进货商" align="center" prop="partnerName" />
|
|
||||||
<!-- <el-table-column label="项目名称" align="center" prop="projectName" />-->
|
|
||||||
<el-table-column label="金额" align="center" prop="totalPriceWithTax" >
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<span style="color: red">{{ formatCurrency(scope.row.totalPriceWithTax) }}</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<!-- <el-table-column label="汇智负责人" align="center" prop="hzUserName" />-->
|
|
||||||
<el-table-column label="提交日期" align="center" prop="applyTime" width="180">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<span>{{ parseTime(scope.row.applyTime, '{y}-{m}-{d}') }}</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="审批节点" align="center" prop="approveNode" />
|
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="200">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleApprove(scope.row)">审批</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
|
|
||||||
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList"/>
|
|
||||||
|
|
||||||
<!-- 审批详情主对话框 -->
|
|
||||||
<el-dialog title="收款单审批" :visible.sync="detailDialogVisible" width="80%" append-to-body>
|
|
||||||
<div v-loading="detailLoading" style="max-height: 70vh; overflow-y: auto; padding: 20px;">
|
|
||||||
<div style="display: flex;flex-direction: row-reverse; margin-bottom: 10px;">
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
size="small"
|
|
||||||
icon="el-icon-download"
|
|
||||||
@click="exportPDF"
|
|
||||||
:loading="pdfExporting"
|
|
||||||
>导出PDF</el-button>
|
|
||||||
</div>
|
|
||||||
<div class="approve-container" :class="{ 'exporting-pdf': pdfExporting }">
|
|
||||||
<ApproveLayout ref="approveLayout" title="收款单详情">
|
|
||||||
<receipt-detail :data="form"></receipt-detail>
|
|
||||||
<template #footer>
|
|
||||||
<span>{{ form.receiptBillCode }}</span>
|
|
||||||
</template>
|
|
||||||
</ApproveLayout>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-divider content-position="left">流转意见</el-divider>
|
|
||||||
<div class="process-container">
|
|
||||||
<el-timeline>
|
|
||||||
<el-timeline-item v-for="(log, index) in approveLogs" :key="index" :timestamp="log.approveTime" placement="top">
|
|
||||||
<el-card>
|
|
||||||
<h4>{{ log.approveOpinion }}</h4>
|
|
||||||
<p><b>操作人:</b> {{ log.approveUserName }} </p>
|
|
||||||
<p><b>审批状态:</b><el-tag :type="log.approveStatus == '3' ? 'success' : log.approveStatus == '2' ? 'danger' : 'info'">{{ getStatusText(log.approveStatus) }}</el-tag></p>
|
|
||||||
</el-card>
|
|
||||||
</el-timeline-item>
|
|
||||||
</el-timeline>
|
|
||||||
<div v-if="!approveLogs || approveLogs.length === 0">暂无流转过程数据。</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<span slot="footer" class="dialog-footer">
|
|
||||||
<el-button type="primary" @click="openOpinionDialog('approve')">同意</el-button>
|
|
||||||
<el-button type="danger" @click="openOpinionDialog('reject')">驳回</el-button>
|
|
||||||
<el-button @click="detailDialogVisible = false">取 消</el-button>
|
|
||||||
</span>
|
|
||||||
</el-dialog>
|
|
||||||
|
|
||||||
<!-- 审批意见对话框 -->
|
|
||||||
<el-dialog :title="confirmDialogTitle" :visible.sync="opinionDialogVisible" width="30%" append-to-body>
|
|
||||||
<el-form ref="opinionForm" :model="opinionForm" :rules="opinionRules" label-width="100px">
|
|
||||||
<el-form-item label="审批意见" prop="approveOpinion">
|
|
||||||
<el-input v-model="opinionForm.approveOpinion" type="textarea" :rows="4" placeholder="请输入审批意见"/>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<span slot="footer" class="dialog-footer">
|
|
||||||
<el-button @click="opinionDialogVisible = false">取 消</el-button>
|
|
||||||
<el-button type="primary" @click="showConfirmDialog()">确 定</el-button>
|
|
||||||
</span>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { listReceiptApprove, getReceiptDetail } from "@/api/finance/receipt";
|
|
||||||
import { approveTask, listCompletedFlows } from "@/api/flow";
|
|
||||||
import ReceiptDetail from "./components/ReceiptDetail";
|
|
||||||
import ApproveLayout from "@/views/approve/ApproveLayout";
|
|
||||||
import { exportElementToPDF } from "@/views/approve/finance/pdfUtils";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "ReceiptRefoundApprove",
|
|
||||||
components: { ReceiptDetail, ApproveLayout },
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
loading: true,
|
|
||||||
showSearch: true,
|
|
||||||
total: 0,
|
|
||||||
receiptList: [],
|
|
||||||
queryParams: {
|
|
||||||
pageNum: 1,
|
|
||||||
pageSize: 10,
|
|
||||||
receiptBillCode: null,
|
|
||||||
partnerName: null,
|
|
||||||
projectName: null,
|
|
||||||
processKey: 'finance_receipt_refound',
|
|
||||||
orderByColumn: 'applyTime',
|
|
||||||
isAsc: 'desc'
|
|
||||||
},
|
|
||||||
dateRange: [],
|
|
||||||
detailDialogVisible: false,
|
|
||||||
detailLoading: false,
|
|
||||||
form: {},
|
|
||||||
approveLogs: [],
|
|
||||||
opinionDialogVisible: false,
|
|
||||||
confirmDialogTitle: '',
|
|
||||||
currentApproveType: '',
|
|
||||||
opinionForm: {
|
|
||||||
approveOpinion: ''
|
|
||||||
},
|
|
||||||
opinionRules: {
|
|
||||||
approveOpinion: [{ required: true, message: '审批意见不能为空', trigger: 'blur' }],
|
|
||||||
},
|
|
||||||
processKey: 'finance_receipt_refound',
|
|
||||||
taskId: null,
|
|
||||||
currentReceiptId: null,
|
|
||||||
pdfExporting: false
|
|
||||||
};
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.getList();
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getList() {
|
|
||||||
this.loading = true;
|
|
||||||
listReceiptApprove(this.addDateRange(this.queryParams, this.dateRange, 'ApplyTime')).then(response => {
|
|
||||||
this.receiptList = response.rows;
|
|
||||||
this.total = response.total;
|
|
||||||
this.loading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
handleQuery() {
|
|
||||||
this.queryParams.pageNum = 1;
|
|
||||||
this.getList();
|
|
||||||
},
|
|
||||||
resetQuery() {
|
|
||||||
this.dateRange = [];
|
|
||||||
this.resetForm("queryForm");
|
|
||||||
this.handleQuery();
|
|
||||||
},
|
|
||||||
toApproved() {
|
|
||||||
this.$router.push( '/approve/receiptRefoundLog' )
|
|
||||||
},
|
|
||||||
handleApprove(row) {
|
|
||||||
this.resetDetailForm();
|
|
||||||
this.currentReceiptId = row.id;
|
|
||||||
this.taskId = row.taskId;
|
|
||||||
this.detailLoading = true;
|
|
||||||
this.detailDialogVisible = true;
|
|
||||||
|
|
||||||
getReceiptDetail(this.currentReceiptId).then(response => {
|
|
||||||
this.form = response.data;
|
|
||||||
this.loadApproveHistory(this.form.receiptBillCode);
|
|
||||||
this.detailLoading = false;
|
|
||||||
}).catch(() => {
|
|
||||||
this.detailLoading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
resetDetailForm() {
|
|
||||||
this.form = {};
|
|
||||||
this.approveLogs = [];
|
|
||||||
this.opinionForm.approveOpinion = '';
|
|
||||||
},
|
|
||||||
loadApproveHistory(businessKey) {
|
|
||||||
if (businessKey) {
|
|
||||||
let keys = [];
|
|
||||||
if(this.processKey) keys.push(this.processKey);
|
|
||||||
|
|
||||||
listCompletedFlows({ businessKey: businessKey, processKeyList: keys }).then(response => {
|
|
||||||
this.approveLogs = response.data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
openOpinionDialog(type) {
|
|
||||||
this.currentApproveType = type;
|
|
||||||
this.confirmDialogTitle = type === 'approve' ? '同意审批' : '驳回审批';
|
|
||||||
this.opinionDialogVisible = true;
|
|
||||||
this.opinionForm.approveOpinion = '';
|
|
||||||
this.$nextTick(() => {
|
|
||||||
if(this.$refs.opinionForm) this.$refs.opinionForm.clearValidate();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
showConfirmDialog() {
|
|
||||||
this.$refs.opinionForm.validate(valid => {
|
|
||||||
if (valid) {
|
|
||||||
this.opinionDialogVisible = false;
|
|
||||||
this.submitApproval();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
submitApproval() {
|
|
||||||
const approveBtn = this.currentApproveType === 'approve' ? 1 : 0;
|
|
||||||
const params = {
|
|
||||||
businessKey: this.form.receiptBillCode,
|
|
||||||
processKey: this.processKey,
|
|
||||||
taskId: this.taskId,
|
|
||||||
variables: {
|
|
||||||
comment: this.opinionForm.approveOpinion,
|
|
||||||
approveBtn: approveBtn
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
approveTask(params).then(() => {
|
|
||||||
this.$modal.msgSuccess(this.confirmDialogTitle + "成功");
|
|
||||||
this.detailDialogVisible = false;
|
|
||||||
this.getList();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
getStatusText(status) {
|
|
||||||
if (!status) {
|
|
||||||
return '提交审批'
|
|
||||||
}
|
|
||||||
const map = { '1': '提交审批', '2': '驳回', '3': '批准' };
|
|
||||||
return map[status] || '提交审批';
|
|
||||||
},
|
|
||||||
async exportPDF() {
|
|
||||||
this.pdfExporting = true;
|
|
||||||
try {
|
|
||||||
const element = this.$refs.approveLayout.$el;
|
|
||||||
const fileName = `收款单-${this.form.receiptBillCode || ''}.pdf`;
|
|
||||||
await exportElementToPDF(element, fileName);
|
|
||||||
this.$modal.msgSuccess('PDF导出成功');
|
|
||||||
} catch (error) {
|
|
||||||
console.error('PDF导出失败:', error);
|
|
||||||
this.$modal.msgError('PDF导出失败,请稍后重试');
|
|
||||||
} finally {
|
|
||||||
this.pdfExporting = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.process-container {
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 导出PDF时的特殊样式 */
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-button--primary,
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-button--text {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-input__inner,
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-textarea__inner {
|
|
||||||
border: none !important;
|
|
||||||
box-shadow: none !important;
|
|
||||||
background-color: transparent !important;
|
|
||||||
resize: none !important;
|
|
||||||
padding: 0 !important;
|
|
||||||
}
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-input__suffix {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,240 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="app-container">
|
|
||||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="120px">
|
|
||||||
<el-form-item label="开票编号" prop="invoiceBillCode">
|
|
||||||
<el-input v-model="queryParams.invoiceBillCode" placeholder="请输入开票编号" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="客户" prop="partnerName">
|
|
||||||
<el-input v-model="queryParams.partnerName" placeholder="请输入客户" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="项目名称" prop="projectName">
|
|
||||||
<el-input v-model="queryParams.projectName" placeholder="请输入项目名称" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="提交日期">
|
|
||||||
<el-date-picker
|
|
||||||
v-model="dateRange"
|
|
||||||
style="width: 240px"
|
|
||||||
value-format="yyyy-MM-dd"
|
|
||||||
type="daterange"
|
|
||||||
range-separator="-"
|
|
||||||
start-placeholder="开始日期"
|
|
||||||
end-placeholder="结束日期"
|
|
||||||
></el-date-picker>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
|
||||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
|
|
||||||
<el-table v-loading="loading" :data="invoiceList">
|
|
||||||
<el-table-column label="序号" type="index" width="50" align="center" />
|
|
||||||
<el-table-column label="开票编号" align="center" prop="invoiceBillCode" />
|
|
||||||
<el-table-column label="客户" align="center" prop="partnerName" />
|
|
||||||
<el-table-column label="金额" align="center" prop="totalPriceWithTax" :formatter="(row, column, cellValue)=>formatCurrency(cellValue)" />
|
|
||||||
<el-table-column label="提交日期" align="center" prop="applyTime" width="180">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<span>{{ parseTime(scope.row.applyTime) }}</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="审批节点" align="center" prop="approveNode" />
|
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="200">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<el-button size="mini" type="text" icon="el-icon-view" @click="handleView(scope.row)">详情</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
|
|
||||||
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList"/>
|
|
||||||
|
|
||||||
<!-- 详情对话框 -->
|
|
||||||
<el-dialog title="开票单详情" :visible.sync="detailDialogVisible" width="80%" append-to-body>
|
|
||||||
<div v-loading="detailLoading" style="max-height: 70vh; overflow-y: auto; padding: 20px;">
|
|
||||||
<div style="display: flex;flex-direction: row-reverse; margin-bottom: 10px;">
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
size="small"
|
|
||||||
icon="el-icon-download"
|
|
||||||
@click="exportPDF"
|
|
||||||
:loading="pdfExporting"
|
|
||||||
>导出PDF</el-button>
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
size="small"
|
|
||||||
icon="el-icon-document"
|
|
||||||
style="margin-right: 10px;"
|
|
||||||
@click="exportExcel"
|
|
||||||
:loading="excelExporting"
|
|
||||||
>导出Excel</el-button>
|
|
||||||
</div>
|
|
||||||
<div class="approve-container" :class="{ 'exporting-pdf': pdfExporting }">
|
|
||||||
<ApproveLayout ref="approveLayout" title="开票单详情">
|
|
||||||
<receivable-invoice-detail :data="form"></receivable-invoice-detail>
|
|
||||||
<template #footer>
|
|
||||||
<span>{{ form.invoiceBillCode }}</span>
|
|
||||||
</template>
|
|
||||||
</ApproveLayout>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-divider content-position="left">流转意见</el-divider>
|
|
||||||
<div class="process-container">
|
|
||||||
<el-timeline>
|
|
||||||
<el-timeline-item v-for="(log, index) in approveLogs" :key="index" :timestamp="log.approveTime" placement="top">
|
|
||||||
<el-card>
|
|
||||||
<h4>{{ log.approveOpinion }}</h4>
|
|
||||||
<p><b>操作人:</b> {{ log.approveUserName }} </p>
|
|
||||||
<p><b>审批状态:</b> <el-tag :type="log.approveStatus == '3' ? 'success' : log.approveStatus == '2' ? 'danger' : 'info'">{{ getStatusText(log.approveStatus) }}</el-tag></p>
|
|
||||||
</el-card>
|
|
||||||
</el-timeline-item>
|
|
||||||
</el-timeline>
|
|
||||||
<div v-if="!approveLogs || approveLogs.length === 0">暂无流转过程数据。</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<span slot="footer" class="dialog-footer">
|
|
||||||
<el-button @click="detailDialogVisible = false">关 闭</el-button>
|
|
||||||
</span>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { listInvoiceApproved, getInvoiceDetail } from "@/api/finance/invoice";
|
|
||||||
import { listCompletedFlows } from "@/api/flow";
|
|
||||||
import ReceivableInvoiceDetail from "../components/ReceivableInvoiceDetail";
|
|
||||||
import ApproveLayout from "@/views/approve/ApproveLayout";
|
|
||||||
import { exportElementToPDF } from "@/views/approve/finance/pdfUtils";
|
|
||||||
import { exportInvoiceInfoToExcel } from "@/views/approve/finance/invoiceExcelUtils";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "ReceivableInvoiceApproved",
|
|
||||||
components: { ReceivableInvoiceDetail, ApproveLayout },
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
loading: true,
|
|
||||||
showSearch: true,
|
|
||||||
total: 0,
|
|
||||||
invoiceList: [],
|
|
||||||
queryParams: {
|
|
||||||
pageNum: 1,
|
|
||||||
pageSize: 10,
|
|
||||||
invoiceBillCode: null,
|
|
||||||
partnerName: null,
|
|
||||||
projectName: null,
|
|
||||||
processKey: 'finance_invoice_approve',
|
|
||||||
orderByColumn: 'applyTime',
|
|
||||||
isAsc: 'desc'
|
|
||||||
},
|
|
||||||
dateRange: [],
|
|
||||||
detailDialogVisible: false,
|
|
||||||
detailLoading: false,
|
|
||||||
form: {},
|
|
||||||
approveLogs: [],
|
|
||||||
currentInvoiceId: null,
|
|
||||||
pdfExporting: false,
|
|
||||||
excelExporting: false
|
|
||||||
};
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.getList();
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getList() {
|
|
||||||
this.loading = true;
|
|
||||||
listInvoiceApproved(this.addDateRange(this.queryParams, this.dateRange, 'ApplyTime')).then(response => {
|
|
||||||
this.invoiceList = response.rows;
|
|
||||||
this.total = response.total;
|
|
||||||
this.loading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
handleQuery() {
|
|
||||||
this.queryParams.pageNum = 1;
|
|
||||||
this.getList();
|
|
||||||
},
|
|
||||||
resetQuery() {
|
|
||||||
this.dateRange = [];
|
|
||||||
this.resetForm("queryForm");
|
|
||||||
this.handleQuery();
|
|
||||||
},
|
|
||||||
handleView(row) {
|
|
||||||
this.form = {};
|
|
||||||
this.approveLogs = [];
|
|
||||||
this.currentInvoiceId = row.id;
|
|
||||||
this.detailLoading = true;
|
|
||||||
this.detailDialogVisible = true;
|
|
||||||
|
|
||||||
getInvoiceDetail(this.currentInvoiceId).then(response => {
|
|
||||||
this.form = response.data;
|
|
||||||
this.loadApproveHistory(this.form.invoiceBillCode);
|
|
||||||
this.detailLoading = false;
|
|
||||||
}).catch(() => {
|
|
||||||
this.detailLoading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
loadApproveHistory(businessKey) {
|
|
||||||
if (businessKey) {
|
|
||||||
listCompletedFlows({ businessKey: businessKey }).then(response => {
|
|
||||||
this.approveLogs = response.data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getStatusText(status) {
|
|
||||||
const map = { '1': '提交审批', '2': '驳回', '3': '批准' };
|
|
||||||
return map[status] || '提交审批';
|
|
||||||
},
|
|
||||||
async exportPDF() {
|
|
||||||
this.pdfExporting = true;
|
|
||||||
try {
|
|
||||||
const element = this.$refs.approveLayout.$el;
|
|
||||||
const fileName = `开票单-${this.form.invoiceBillCode || ''}.pdf`;
|
|
||||||
await exportElementToPDF(element, fileName);
|
|
||||||
this.$modal.msgSuccess('PDF导出成功');
|
|
||||||
} catch (error) {
|
|
||||||
console.error('PDF导出失败:', error);
|
|
||||||
this.$modal.msgError('PDF导出失败,请稍后重试');
|
|
||||||
} finally {
|
|
||||||
this.pdfExporting = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
exportExcel() {
|
|
||||||
if (!this.form || !this.form.invoiceBillCode) {
|
|
||||||
this.$modal.msgWarning("暂无可导出的开票信息");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.excelExporting = true;
|
|
||||||
try {
|
|
||||||
const fileName = `开票单-${this.form.invoiceBillCode || ""}.xls`;
|
|
||||||
exportInvoiceInfoToExcel(this.form, fileName);
|
|
||||||
this.$modal.msgSuccess("Excel导出成功");
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Excel导出失败:", error);
|
|
||||||
this.$modal.msgError("Excel导出失败,请稍后重试");
|
|
||||||
} finally {
|
|
||||||
this.excelExporting = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.process-container {
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 导出PDF时的特殊样式 */
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-button--primary,
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-button--text {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-input__inner,
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-textarea__inner {
|
|
||||||
border: none !important;
|
|
||||||
box-shadow: none !important;
|
|
||||||
background-color: transparent !important;
|
|
||||||
resize: none !important;
|
|
||||||
padding: 0 !important;
|
|
||||||
}
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-input__suffix {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,170 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="invoice-detail">
|
|
||||||
<div style="text-align: center;font-weight:bold;font-size: 25px;">开票申请单</div>
|
|
||||||
<el-descriptions title="开票单信息" :column="3" border>
|
|
||||||
<el-descriptions-item label="销售-开票单编号">{{ data.invoiceBillCode }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item :span="2" label="进货商">{{ data.partnerName }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="含税总价(元)">{{ formatCurrency(data.totalPriceWithTax) }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="未税总价(元)">{{ formatCurrency(data.totalPriceWithoutTax) }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="税额(元)">{{ formatCurrency(data.taxAmount) }}</el-descriptions-item>
|
|
||||||
<!-- <el-descriptions-item label="银行账号">{{ data.buyerBankAccount }}</el-descriptions-item>-->
|
|
||||||
<!-- <el-descriptions-item label="账户名称">{{ data.buyerName }}</el-descriptions-item>-->
|
|
||||||
<!-- <el-descriptions-item label="银行开户行">{{ data.buyerBank }}</el-descriptions-item>-->
|
|
||||||
<!-- <el-descriptions-item label="银行行号">{{ data.bankNumber }}</el-descriptions-item> -->
|
|
||||||
</el-descriptions>
|
|
||||||
|
|
||||||
<div class="section" style="margin-top: 20px;">
|
|
||||||
<div class="el-descriptions__title">发票信息</div>
|
|
||||||
<invoice-info-view :data="data" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="section" style="margin-top: 20px;" v-show="data.detailDTOList && data.detailDTOList.length>0">
|
|
||||||
<div class="el-descriptions__title">应收单列表</div>
|
|
||||||
<el-table :data="data.detailDTOList" border style="width: 100%; margin-top: 10px;">
|
|
||||||
<el-table-column type="index" label="序号" width="50" align="center"></el-table-column>
|
|
||||||
<el-table-column prop="receivableBillCode" label="销售-应收单编号" align="center"></el-table-column>
|
|
||||||
<el-table-column prop="projectName" label="项目名称" align="center"></el-table-column>
|
|
||||||
<el-table-column prop="productType" label="产品类型" align="center">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<dict-tag :options="dict.type.product_type" :value="scope.row.productType"/>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="totalPriceWithTax" label="含税总价" align="center" :formatter="(row, column, cellValue)=>formatCurrency(cellValue)"></el-table-column>
|
|
||||||
<el-table-column prop="receiptAmount" label="本次开票金额" align="center" :formatter="(row, column, cellValue)=>formatCurrency(cellValue)"></el-table-column>
|
|
||||||
</el-table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="section" style="margin-top: 20px;" v-if="excelList && excelList.length > 0">
|
|
||||||
<div class="el-descriptions__title">附件信息</div>
|
|
||||||
<el-table :data="excelList" border style="width: 100%; margin-top: 10px;">
|
|
||||||
<el-table-column prop="fileName" label="附件名称" align="center"></el-table-column>
|
|
||||||
<el-table-column prop="createUserName" label="上传信息" align="center"></el-table-column>
|
|
||||||
<el-table-column prop="createTime" label="生成时间" align="center"></el-table-column>
|
|
||||||
<el-table-column label="操作" align="center">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<el-button size="mini" type="text" icon="el-icon-download" @click="handleDownload(scope.row)">下载</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- <div class="section" style="margin-top: 20px;" v-if="attachments && attachments.length > 0">-->
|
|
||||||
<!-- <div class="el-descriptions__title">附件信息</div>-->
|
|
||||||
<!-- <el-table :data="attachments" border style="width: 100%; margin-top: 10px;">-->
|
|
||||||
<!-- <el-table-column prop="fileName" label="附件名称" align="center"></el-table-column>-->
|
|
||||||
<!-- <el-table-column prop="createUserName" label="上传人" align="center"></el-table-column>-->
|
|
||||||
<!-- <el-table-column prop="createTime" label="上传时间" align="center"></el-table-column>-->
|
|
||||||
<!-- <el-table-column label="操作" align="center">-->
|
|
||||||
<!-- <template slot-scope="scope">-->
|
|
||||||
<!-- <el-button size="mini" type="text" icon="el-icon-view" @click="handlePreview(scope.row)">预览</el-button>-->
|
|
||||||
<!-- <el-button size="mini" type="text" icon="el-icon-download" @click="handleDownload(scope.row)">下载</el-button>-->
|
|
||||||
<!-- </template>-->
|
|
||||||
<!-- </el-table-column>-->
|
|
||||||
<!-- </el-table>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
|
|
||||||
<!-- <el-dialog :visible.sync="pdfPreviewVisible" width="80%" append-to-body top="5vh" title="PDF预览">-->
|
|
||||||
<!-- <iframe :src="currentPdfUrl" width="100%" height="600px" frameborder="0"></iframe>-->
|
|
||||||
<!-- </el-dialog>-->
|
|
||||||
|
|
||||||
<!-- <el-dialog :visible.sync="imagePreviewVisible" width="60%" append-to-body top="5vh" title="图片预览">-->
|
|
||||||
<!-- <img :src="currentImageUrl" style="width: 100%;" />-->
|
|
||||||
<!-- </el-dialog>-->
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { getInvoiceAttachments } from "@/api/finance/invoice";
|
|
||||||
import request from '@/utils/request';
|
|
||||||
import InvoiceInfoView from '@/views/finance/invoice/components/InvoiceInfoView';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "ReceivableInvoiceDetail",
|
|
||||||
components: { InvoiceInfoView },
|
|
||||||
props: {
|
|
||||||
data: {
|
|
||||||
type: Object,
|
|
||||||
required: true,
|
|
||||||
default: () => ({})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
dicts: ['product_type'],
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
attachments: [],
|
|
||||||
excelList: [],
|
|
||||||
pdfPreviewVisible: false,
|
|
||||||
currentPdfUrl: '',
|
|
||||||
imagePreviewVisible: false,
|
|
||||||
currentImageUrl: ''
|
|
||||||
};
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
data: {
|
|
||||||
handler(val) {
|
|
||||||
if (val && val.updateTime) {
|
|
||||||
this.excelList = [{
|
|
||||||
fileName: '电子发票--购买方公司信息.xlsx',
|
|
||||||
createUserName: '系统生成',
|
|
||||||
createTime: val.updateTime,
|
|
||||||
isSystemGenerated: true
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
immediate: true,
|
|
||||||
deep: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
|
|
||||||
isPdf(filePath) {
|
|
||||||
return filePath && filePath.toLowerCase().endsWith('.pdf');
|
|
||||||
},
|
|
||||||
getImageUrl(resource) {
|
|
||||||
return process.env.VUE_APP_BASE_API + "/common/download/resource?resource=" + resource;
|
|
||||||
},
|
|
||||||
handlePreview(row) {
|
|
||||||
if (this.isPdf(row.filePath)) {
|
|
||||||
request({
|
|
||||||
url: '/common/download/resource',
|
|
||||||
method: 'get',
|
|
||||||
params: { resource: row.filePath },
|
|
||||||
responseType: 'blob'
|
|
||||||
}).then(res => {
|
|
||||||
const blob = new Blob([res.data], { type: 'application/pdf' });
|
|
||||||
this.currentPdfUrl = URL.createObjectURL(blob);
|
|
||||||
this.pdfPreviewVisible = true;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.currentImageUrl = this.getImageUrl(row.filePath);
|
|
||||||
this.imagePreviewVisible = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleDownload(row) {
|
|
||||||
if (row.isSystemGenerated) {
|
|
||||||
request({
|
|
||||||
url: '/finance/invoice/export/' + this.data.invoiceBillCode,
|
|
||||||
method: 'get'
|
|
||||||
}).then(res => {
|
|
||||||
window.location.href = process.env.VUE_APP_BASE_API + "/common/download?fileName=" + encodeURIComponent(res.msg) + "&delete=true";
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const link = document.createElement('a');
|
|
||||||
link.href = this.getImageUrl(row.filePath);
|
|
||||||
link.download = row.fileName || 'attachment';
|
|
||||||
link.style.display = 'none';
|
|
||||||
document.body.appendChild(link);
|
|
||||||
link.click();
|
|
||||||
document.body.removeChild(link);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.invoice-detail {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,327 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="app-container">
|
|
||||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="120px">
|
|
||||||
<el-form-item label="开票编号" prop="invoiceBillCode">
|
|
||||||
<el-input v-model="queryParams.invoiceBillCode" placeholder="请输入开票编号" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="进货商" prop="partnerName">
|
|
||||||
<el-input v-model="queryParams.partnerName" placeholder="请输入进货商" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="项目名称" prop="projectName">
|
|
||||||
<el-input v-model="queryParams.projectName" placeholder="请输入项目名称" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="提交日期">
|
|
||||||
<el-date-picker
|
|
||||||
v-model="dateRange"
|
|
||||||
style="width: 240px"
|
|
||||||
value-format="yyyy-MM-dd HH:mm:ss"
|
|
||||||
type="daterange"
|
|
||||||
range-separator="-"
|
|
||||||
start-placeholder="开始日期"
|
|
||||||
end-placeholder="结束日期"
|
|
||||||
></el-date-picker>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
|
||||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
|
|
||||||
<el-row :gutter="10" class="mb8">
|
|
||||||
<el-col :span="1.5">
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
plain
|
|
||||||
size="mini"
|
|
||||||
@click="toApproved()"
|
|
||||||
>审批历史</el-button>
|
|
||||||
</el-col>
|
|
||||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
|
||||||
</el-row>
|
|
||||||
|
|
||||||
<el-table v-loading="loading" :data="invoiceList">
|
|
||||||
<el-table-column label="序号" type="index" width="50" align="center" />
|
|
||||||
<el-table-column label="开票编号" align="center" prop="invoiceBillCode" />
|
|
||||||
<el-table-column label="进货商" align="center" prop="partnerName" />
|
|
||||||
<el-table-column label="金额" align="center" prop="totalPriceWithTax" :formatter="(row, column, cellValue)=>formatCurrency(cellValue)"/>
|
|
||||||
<el-table-column label="提交日期" align="center" prop="applyTime" width="180">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<span>{{ parseTime(scope.row.applyTime, '{y}-{m}-{d}') }}</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="审批节点" align="center" prop="approveNode" />
|
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="200">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleApprove(scope.row)">审批</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
|
|
||||||
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList"/>
|
|
||||||
|
|
||||||
<!-- 审批详情主对话框 -->
|
|
||||||
<el-dialog title="开票单审批" :visible.sync="detailDialogVisible" width="80%" append-to-body>
|
|
||||||
<div v-loading="detailLoading" style="max-height: 70vh; overflow-y: auto; padding: 20px;">
|
|
||||||
<div style="display: flex;flex-direction: row-reverse; margin-bottom: 10px;">
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
size="small"
|
|
||||||
icon="el-icon-download"
|
|
||||||
@click="exportPDF"
|
|
||||||
:loading="pdfExporting"
|
|
||||||
>导出PDF</el-button>
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
size="small"
|
|
||||||
icon="el-icon-document"
|
|
||||||
style="margin-right: 10px;"
|
|
||||||
@click="exportExcel"
|
|
||||||
:loading="excelExporting"
|
|
||||||
>导出Excel</el-button>
|
|
||||||
</div>
|
|
||||||
<div class="approve-container" :class="{ 'exporting-pdf': pdfExporting }">
|
|
||||||
<ApproveLayout ref="approveLayout" title="开票单详情">
|
|
||||||
<receivable-invoice-detail :data="form"></receivable-invoice-detail>
|
|
||||||
<template #footer>
|
|
||||||
<span>{{ form.invoiceBillCode }}</span>
|
|
||||||
</template>
|
|
||||||
</ApproveLayout>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-divider content-position="left">流转意见</el-divider>
|
|
||||||
<div class="process-container">
|
|
||||||
<el-timeline>
|
|
||||||
<el-timeline-item v-for="(log, index) in approveLogs" :key="index" :timestamp="log.approveTime" placement="top">
|
|
||||||
<el-card>
|
|
||||||
<h4>{{ log.approveOpinion }}</h4>
|
|
||||||
<p><b>操作人:</b> {{ log.approveUserName }} </p>
|
|
||||||
<p><b>审批状态:</b> <el-tag :type="log.approveStatus == '3' ? 'success' : log.approveStatus == '2' ? 'danger' : 'info'">{{ getStatusText(log.approveStatus) }}</el-tag></p>
|
|
||||||
</el-card>
|
|
||||||
</el-timeline-item>
|
|
||||||
</el-timeline>
|
|
||||||
<div v-if="!approveLogs || approveLogs.length === 0">暂无流转过程数据。</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<span slot="footer" class="dialog-footer">
|
|
||||||
<el-button type="primary" @click="openOpinionDialog('approve')">同意</el-button>
|
|
||||||
<el-button type="danger" @click="openOpinionDialog('reject')">驳回</el-button>
|
|
||||||
<el-button @click="detailDialogVisible = false">取 消</el-button>
|
|
||||||
</span>
|
|
||||||
</el-dialog>
|
|
||||||
|
|
||||||
<!-- 审批意见对话框 -->
|
|
||||||
<el-dialog :title="confirmDialogTitle" :visible.sync="opinionDialogVisible" width="30%" append-to-body>
|
|
||||||
<el-form ref="opinionForm" :model="opinionForm" :rules="opinionRules" label-width="100px">
|
|
||||||
<el-form-item label="审批意见" prop="approveOpinion">
|
|
||||||
<el-input v-model="opinionForm.approveOpinion" type="textarea" :rows="4" placeholder="请输入审批意见"/>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<span slot="footer" class="dialog-footer">
|
|
||||||
<el-button @click="opinionDialogVisible = false">取 消</el-button>
|
|
||||||
<el-button type="primary" @click="showConfirmDialog()">确 定</el-button>
|
|
||||||
</span>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { listInvoiceApprove, getInvoiceDetail } from "@/api/finance/invoice";
|
|
||||||
import { approveTask, listCompletedFlows } from "@/api/flow";
|
|
||||||
import ReceivableInvoiceDetail from "./components/ReceivableInvoiceDetail";
|
|
||||||
import ApproveLayout from "@/views/approve/ApproveLayout";
|
|
||||||
import { exportElementToPDF } from "@/views/approve/finance/pdfUtils";
|
|
||||||
import { exportInvoiceInfoToExcel } from "@/views/approve/finance/invoiceExcelUtils";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "ReceivableInvoiceApprove",
|
|
||||||
components: { ReceivableInvoiceDetail, ApproveLayout },
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
loading: true,
|
|
||||||
showSearch: true,
|
|
||||||
total: 0,
|
|
||||||
invoiceList: [],
|
|
||||||
queryParams: {
|
|
||||||
pageNum: 1,
|
|
||||||
pageSize: 10,
|
|
||||||
invoiceBillCode: null,
|
|
||||||
partnerName: null,
|
|
||||||
projectName: null,
|
|
||||||
processKey: 'finance_invoice_approve',
|
|
||||||
orderByColumn: 'applyTime',
|
|
||||||
isAsc: 'desc'
|
|
||||||
},
|
|
||||||
dateRange: [],
|
|
||||||
detailDialogVisible: false,
|
|
||||||
detailLoading: false,
|
|
||||||
form: {},
|
|
||||||
approveLogs: [],
|
|
||||||
opinionDialogVisible: false,
|
|
||||||
confirmDialogTitle: '',
|
|
||||||
currentApproveType: '',
|
|
||||||
opinionForm: {
|
|
||||||
approveOpinion: ''
|
|
||||||
},
|
|
||||||
opinionRules: {
|
|
||||||
approveOpinion: [{ required: true, message: '审批意见不能为空', trigger: 'blur' }],
|
|
||||||
},
|
|
||||||
processKey: 'finance_invoice_approve',
|
|
||||||
taskId: null,
|
|
||||||
currentInvoiceId: null,
|
|
||||||
pdfExporting: false,
|
|
||||||
excelExporting: false
|
|
||||||
};
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.getList();
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getList() {
|
|
||||||
this.loading = true;
|
|
||||||
listInvoiceApprove(this.addDateRange(this.queryParams, this.dateRange, 'ApplyTime')).then(response => {
|
|
||||||
this.invoiceList = response.rows;
|
|
||||||
this.total = response.total;
|
|
||||||
this.loading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
handleQuery() {
|
|
||||||
this.queryParams.pageNum = 1;
|
|
||||||
this.getList();
|
|
||||||
},
|
|
||||||
resetQuery() {
|
|
||||||
this.dateRange = [];
|
|
||||||
this.resetForm("queryForm");
|
|
||||||
this.handleQuery();
|
|
||||||
},
|
|
||||||
toApproved() {
|
|
||||||
this.$router.push('/approve/receivableInvoiceLog')
|
|
||||||
},
|
|
||||||
handleApprove(row) {
|
|
||||||
this.resetDetailForm();
|
|
||||||
this.currentInvoiceId = row.id;
|
|
||||||
this.taskId = row.taskId;
|
|
||||||
this.detailLoading = true;
|
|
||||||
this.detailDialogVisible = true;
|
|
||||||
|
|
||||||
getInvoiceDetail(this.currentInvoiceId).then(response => {
|
|
||||||
this.form = response.data;
|
|
||||||
this.loadApproveHistory(this.form.invoiceBillCode);
|
|
||||||
this.detailLoading = false;
|
|
||||||
}).catch(() => {
|
|
||||||
this.detailLoading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
resetDetailForm() {
|
|
||||||
this.form = {};
|
|
||||||
this.approveLogs = [];
|
|
||||||
this.opinionForm.approveOpinion = '';
|
|
||||||
},
|
|
||||||
loadApproveHistory(businessKey) {
|
|
||||||
if (businessKey) {
|
|
||||||
let keys = [];
|
|
||||||
if(this.processKey) keys.push(this.processKey);
|
|
||||||
|
|
||||||
listCompletedFlows({ businessKey: businessKey, processKeyList: keys }).then(response => {
|
|
||||||
this.approveLogs = response.data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
openOpinionDialog(type) {
|
|
||||||
this.currentApproveType = type;
|
|
||||||
this.confirmDialogTitle = type === 'approve' ? '同意审批' : '驳回审批';
|
|
||||||
this.opinionDialogVisible = true;
|
|
||||||
this.opinionForm.approveOpinion = '';
|
|
||||||
this.$nextTick(() => {
|
|
||||||
if(this.$refs.opinionForm) this.$refs.opinionForm.clearValidate();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
showConfirmDialog() {
|
|
||||||
this.$refs.opinionForm.validate(valid => {
|
|
||||||
if (valid) {
|
|
||||||
this.opinionDialogVisible = false;
|
|
||||||
this.submitApproval();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
submitApproval() {
|
|
||||||
const approveBtn = this.currentApproveType === 'approve' ? 1 : 0;
|
|
||||||
const params = {
|
|
||||||
businessKey: this.form.invoiceBillCode,
|
|
||||||
processKey: this.processKey,
|
|
||||||
taskId: this.taskId,
|
|
||||||
variables: {
|
|
||||||
comment: this.opinionForm.approveOpinion,
|
|
||||||
approveBtn: approveBtn
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
approveTask(params).then(() => {
|
|
||||||
this.$modal.msgSuccess(this.confirmDialogTitle + "成功");
|
|
||||||
this.detailDialogVisible = false;
|
|
||||||
this.getList();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
getStatusText(status) {
|
|
||||||
if (!status) {
|
|
||||||
return '提交审批'
|
|
||||||
}
|
|
||||||
const map = { '1': '提交审批', '2': '驳回', '3': '批准' };
|
|
||||||
return map[status] || '提交审批';
|
|
||||||
},
|
|
||||||
async exportPDF() {
|
|
||||||
this.pdfExporting = true;
|
|
||||||
try {
|
|
||||||
const element = this.$refs.approveLayout.$el;
|
|
||||||
const fileName = `开票单-${this.form.invoiceBillCode || ''}.pdf`;
|
|
||||||
await exportElementToPDF(element, fileName);
|
|
||||||
this.$modal.msgSuccess('PDF导出成功');
|
|
||||||
} catch (error) {
|
|
||||||
console.error('PDF导出失败:', error);
|
|
||||||
this.$modal.msgError('PDF导出失败,请稍后重试');
|
|
||||||
} finally {
|
|
||||||
this.pdfExporting = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
exportExcel() {
|
|
||||||
if (!this.form || !this.form.invoiceBillCode) {
|
|
||||||
this.$modal.msgWarning("暂无可导出的开票信息");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.excelExporting = true;
|
|
||||||
try {
|
|
||||||
const fileName = `开票单-${this.form.invoiceBillCode || ""}.xls`;
|
|
||||||
exportInvoiceInfoToExcel(this.form, fileName);
|
|
||||||
this.$modal.msgSuccess("Excel导出成功");
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Excel导出失败:", error);
|
|
||||||
this.$modal.msgError("Excel导出失败,请稍后重试");
|
|
||||||
} finally {
|
|
||||||
this.excelExporting = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.process-container {
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 导出PDF时的特殊样式 */
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-button--primary,
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-button--text {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-input__inner,
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-textarea__inner {
|
|
||||||
border: none !important;
|
|
||||||
box-shadow: none !important;
|
|
||||||
background-color: transparent !important;
|
|
||||||
resize: none !important;
|
|
||||||
padding: 0 !important;
|
|
||||||
}
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-input__suffix {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,217 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="app-container">
|
|
||||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="120px">
|
|
||||||
<el-form-item label="开票编号" prop="invoiceBillCode">
|
|
||||||
<el-input v-model="queryParams.invoiceBillCode" placeholder="请输入开票编号" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="客户" prop="partnerName">
|
|
||||||
<el-input v-model="queryParams.partnerName" placeholder="请输入客户" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="项目名称" prop="projectName">
|
|
||||||
<el-input v-model="queryParams.projectName" placeholder="请输入项目名称" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="提交日期">
|
|
||||||
<el-date-picker
|
|
||||||
v-model="dateRange"
|
|
||||||
style="width: 240px"
|
|
||||||
value-format="yyyy-MM-dd"
|
|
||||||
type="daterange"
|
|
||||||
range-separator="-"
|
|
||||||
start-placeholder="开始日期"
|
|
||||||
end-placeholder="结束日期"
|
|
||||||
></el-date-picker>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
|
||||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
|
|
||||||
<el-table v-loading="loading" :data="invoiceList">
|
|
||||||
<el-table-column label="序号" type="index" width="50" align="center" />
|
|
||||||
<el-table-column label="开票编号" align="center" prop="invoiceBillCode" />
|
|
||||||
<el-table-column label="客户" align="center" prop="partnerName" />
|
|
||||||
<el-table-column label="金额" align="center" prop="totalPriceWithTax">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<span :style="scope.row.totalPriceWithTax < 0 ? 'color: red' : ''">{{ formatCurrency(scope.row.totalPriceWithTax) }}</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="提交日期" align="center" prop="applyTime" width="180">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<span>{{ parseTime(scope.row.applyTime) }}</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="审批节点" align="center" prop="approveNode" />
|
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="200">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<el-button size="mini" type="text" icon="el-icon-view" @click="handleView(scope.row)">详情</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
|
|
||||||
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList"/>
|
|
||||||
|
|
||||||
<!-- 详情对话框 -->
|
|
||||||
<el-dialog title="开票单详情" :visible.sync="detailDialogVisible" width="80%" append-to-body>
|
|
||||||
<div v-loading="detailLoading" style="max-height: 70vh; overflow-y: auto; padding: 20px;">
|
|
||||||
<div style="display: flex;flex-direction: row-reverse; margin-bottom: 10px;">
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
size="small"
|
|
||||||
icon="el-icon-download"
|
|
||||||
@click="exportPDF"
|
|
||||||
:loading="pdfExporting"
|
|
||||||
>导出PDF</el-button>
|
|
||||||
</div>
|
|
||||||
<div class="approve-container" :class="{ 'exporting-pdf': pdfExporting }">
|
|
||||||
<ApproveLayout ref="approveLayout" title="开票单详情">
|
|
||||||
<receivable-invoice-detail :data="form"></receivable-invoice-detail>
|
|
||||||
<template #footer>
|
|
||||||
<span>{{ form.invoiceBillCode }}</span>
|
|
||||||
</template>
|
|
||||||
</ApproveLayout>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-divider content-position="left">流转意见</el-divider>
|
|
||||||
<div class="process-container">
|
|
||||||
<el-timeline>
|
|
||||||
<el-timeline-item v-for="(log, index) in approveLogs" :key="index" :timestamp="log.approveTime" placement="top">
|
|
||||||
<el-card>
|
|
||||||
<h4>{{ log.approveOpinion }}</h4>
|
|
||||||
<p><b>操作人:</b> {{ log.approveUserName }} </p>
|
|
||||||
<p><b>审批状态:</b> <el-tag :type="log.approveStatus == '3' ? 'success' : log.approveStatus == '2' ? 'danger' : 'info'">{{ getStatusText(log.approveStatus) }}</el-tag></p>
|
|
||||||
</el-card>
|
|
||||||
</el-timeline-item>
|
|
||||||
</el-timeline>
|
|
||||||
<div v-if="!approveLogs || approveLogs.length === 0">暂无流转过程数据。</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<span slot="footer" class="dialog-footer">
|
|
||||||
<el-button @click="detailDialogVisible = false">关 闭</el-button>
|
|
||||||
</span>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { listInvoiceApproved, getInvoiceDetail } from "@/api/finance/invoice";
|
|
||||||
import { listCompletedFlows } from "@/api/flow";
|
|
||||||
import ReceivableInvoiceDetail from "../components/ReceivableInvoiceDetail";
|
|
||||||
import ApproveLayout from "@/views/approve/ApproveLayout";
|
|
||||||
import { exportElementToPDF } from "@/views/approve/finance/pdfUtils";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "ReceivableInvoiceRefundApproved",
|
|
||||||
components: { ReceivableInvoiceDetail, ApproveLayout },
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
loading: true,
|
|
||||||
showSearch: true,
|
|
||||||
total: 0,
|
|
||||||
invoiceList: [],
|
|
||||||
queryParams: {
|
|
||||||
pageNum: 1,
|
|
||||||
pageSize: 10,
|
|
||||||
invoiceBillCode: null,
|
|
||||||
partnerName: null,
|
|
||||||
projectName: null,
|
|
||||||
processKey: 'finance_invoice_refound',
|
|
||||||
orderByColumn: 'applyTime',
|
|
||||||
isAsc: 'desc'
|
|
||||||
},
|
|
||||||
dateRange: [],
|
|
||||||
detailDialogVisible: false,
|
|
||||||
detailLoading: false,
|
|
||||||
form: {},
|
|
||||||
approveLogs: [],
|
|
||||||
currentInvoiceId: null,
|
|
||||||
pdfExporting: false
|
|
||||||
};
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.getList();
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getList() {
|
|
||||||
this.loading = true;
|
|
||||||
listInvoiceApproved(this.addDateRange(this.queryParams, this.dateRange, 'ApplyTime')).then(response => {
|
|
||||||
this.invoiceList = response.rows;
|
|
||||||
this.total = response.total;
|
|
||||||
this.loading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
handleQuery() {
|
|
||||||
this.queryParams.pageNum = 1;
|
|
||||||
this.getList();
|
|
||||||
},
|
|
||||||
resetQuery() {
|
|
||||||
this.dateRange = [];
|
|
||||||
this.resetForm("queryForm");
|
|
||||||
this.handleQuery();
|
|
||||||
},
|
|
||||||
handleView(row) {
|
|
||||||
this.form = {};
|
|
||||||
this.approveLogs = [];
|
|
||||||
this.currentInvoiceId = row.id;
|
|
||||||
this.detailLoading = true;
|
|
||||||
this.detailDialogVisible = true;
|
|
||||||
|
|
||||||
getInvoiceDetail(this.currentInvoiceId).then(response => {
|
|
||||||
this.form = response.data;
|
|
||||||
this.loadApproveHistory(this.form.invoiceBillCode);
|
|
||||||
this.detailLoading = false;
|
|
||||||
}).catch(() => {
|
|
||||||
this.detailLoading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
loadApproveHistory(businessKey) {
|
|
||||||
if (businessKey) {
|
|
||||||
listCompletedFlows({ businessKey: businessKey }).then(response => {
|
|
||||||
this.approveLogs = response.data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getStatusText(status) {
|
|
||||||
const map = { '1': '提交审批', '2': '驳回', '3': '批准' };
|
|
||||||
return map[status] || '提交审批';
|
|
||||||
},
|
|
||||||
async exportPDF() {
|
|
||||||
this.pdfExporting = true;
|
|
||||||
try {
|
|
||||||
const element = this.$refs.approveLayout.$el;
|
|
||||||
const fileName = `开票单-${this.form.invoiceBillCode || ''}.pdf`;
|
|
||||||
await exportElementToPDF(element, fileName);
|
|
||||||
this.$modal.msgSuccess('PDF导出成功');
|
|
||||||
} catch (error) {
|
|
||||||
console.error('PDF导出失败:', error);
|
|
||||||
this.$modal.msgError('PDF导出失败,请稍后重试');
|
|
||||||
} finally {
|
|
||||||
this.pdfExporting = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.process-container {
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 导出PDF时的特殊样式 */
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-button--primary,
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-button--text {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-input__inner,
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-textarea__inner {
|
|
||||||
border: none !important;
|
|
||||||
box-shadow: none !important;
|
|
||||||
background-color: transparent !important;
|
|
||||||
resize: none !important;
|
|
||||||
padding: 0 !important;
|
|
||||||
}
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-input__suffix {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,183 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="invoice-detail">
|
|
||||||
<div style="text-align: center;font-weight:bold;font-size: 25px;">红冲开票申请单</div>
|
|
||||||
<el-descriptions title="开票单信息" :column="3" border>
|
|
||||||
<el-descriptions-item label="销售-开票单编号">{{ data.invoiceBillCode }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item :span="2" label="进货商">{{ data.partnerName }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="含税总价(元)">
|
|
||||||
<span :style="data.totalPriceWithTax < 0 ? 'color: red' : ''">{{ formatCurrency(data.totalPriceWithTax) }}</span>
|
|
||||||
</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="未税总价(元)">
|
|
||||||
<span :style="data.totalPriceWithoutTax < 0 ? 'color: red' : ''">{{ formatCurrency(data.totalPriceWithoutTax) }}</span>
|
|
||||||
</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="税额(元)">
|
|
||||||
<span :style="data.taxAmount < 0 ? 'color: red' : ''">{{ formatCurrency(data.taxAmount) }}</span>
|
|
||||||
</el-descriptions-item>
|
|
||||||
<!-- <el-descriptions-item label="银行账号">{{ data.buyerBankAccount }}</el-descriptions-item>-->
|
|
||||||
<!-- <el-descriptions-item label="账户名称">{{ data.buyerName }}</el-descriptions-item>-->
|
|
||||||
<!-- <el-descriptions-item label="银行开户行">{{ data.buyerBank }}</el-descriptions-item>-->
|
|
||||||
<!-- <el-descriptions-item label="银行行号">{{ data.bankNumber }}</el-descriptions-item> -->
|
|
||||||
</el-descriptions>
|
|
||||||
|
|
||||||
<div class="section" style="margin-top: 20px;">
|
|
||||||
<div class="el-descriptions__title">发票信息</div>
|
|
||||||
<invoice-info-view :data="data" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="section" style="margin-top: 20px;" v-show="data.detailDTOList && data.detailDTOList.length>0">
|
|
||||||
<div class="el-descriptions__title">应收单列表</div>
|
|
||||||
<el-table :data="data.detailDTOList" border style="width: 100%; margin-top: 10px;">
|
|
||||||
<el-table-column type="index" label="序号" width="50" align="center"></el-table-column>
|
|
||||||
<el-table-column prop="receivableBillCode" label="销售-应收单编号" align="center"></el-table-column>
|
|
||||||
<el-table-column prop="projectName" label="项目名称" align="center"></el-table-column>
|
|
||||||
<el-table-column prop="productType" label="产品类型" align="center">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<dict-tag :options="dict.type.product_type" :value="scope.row.productType"/>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="totalPriceWithTax" label="含税总价" align="center">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<span :style="scope.row.totalPriceWithTax < 0 ? 'color: red' : ''">{{ formatCurrency(scope.row.totalPriceWithTax) }}</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="receiptAmount" label="本次开票金额" align="center">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<span :style="scope.row.receiptAmount < 0 ? 'color: red' : ''">{{ formatCurrency(scope.row.receiptAmount) }}</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="section" style="margin-top: 20px;" v-if="excelList && excelList.length > 0">
|
|
||||||
<div class="el-descriptions__title">附件信息</div>
|
|
||||||
<el-table :data="excelList" border style="width: 100%; margin-top: 10px;">
|
|
||||||
<el-table-column prop="fileName" label="附件名称" align="center"></el-table-column>
|
|
||||||
<el-table-column prop="createUserName" label="上传信息" align="center"></el-table-column>
|
|
||||||
<el-table-column prop="createTime" label="生成时间" align="center"></el-table-column>
|
|
||||||
<el-table-column label="操作" align="center">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<el-button size="mini" type="text" icon="el-icon-download" @click="handleDownload(scope.row)">下载</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="section" style="margin-top: 20px;" v-if="attachments && attachments.length > 0">
|
|
||||||
<div class="el-descriptions__title">附件信息</div>
|
|
||||||
<el-table :data="attachments" border style="width: 100%; margin-top: 10px;">
|
|
||||||
<el-table-column prop="fileName" label="附件名称" align="center"></el-table-column>
|
|
||||||
<el-table-column prop="createUserName" label="上传人" align="center"></el-table-column>
|
|
||||||
<el-table-column prop="createTime" label="上传时间" align="center"></el-table-column>
|
|
||||||
<el-table-column label="操作" align="center">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<el-button size="mini" type="text" icon="el-icon-view" @click="handlePreview(scope.row)">预览</el-button>
|
|
||||||
<el-button size="mini" type="text" icon="el-icon-download" @click="handleDownload(scope.row)">下载</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-dialog :visible.sync="pdfPreviewVisible" width="80%" append-to-body top="5vh" title="PDF预览">
|
|
||||||
<iframe :src="currentPdfUrl" width="100%" height="600px" frameborder="0"></iframe>
|
|
||||||
</el-dialog>
|
|
||||||
|
|
||||||
<el-dialog :visible.sync="imagePreviewVisible" width="60%" append-to-body top="5vh" title="图片预览">
|
|
||||||
<img :src="currentImageUrl" style="width: 100%;" />
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { getInvoiceAttachments } from "@/api/finance/invoice";
|
|
||||||
import request from '@/utils/request';
|
|
||||||
import InvoiceInfoView from '@/views/finance/invoice/components/InvoiceInfoView';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "ReceivableInvoiceDetail",
|
|
||||||
components: { InvoiceInfoView },
|
|
||||||
props: {
|
|
||||||
data: {
|
|
||||||
type: Object,
|
|
||||||
required: true,
|
|
||||||
default: () => ({})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
dicts: ['product_type'],
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
attachments: [],
|
|
||||||
excelList: [],
|
|
||||||
pdfPreviewVisible: false,
|
|
||||||
currentPdfUrl: '',
|
|
||||||
imagePreviewVisible: false,
|
|
||||||
currentImageUrl: ''
|
|
||||||
};
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
data: {
|
|
||||||
handler(val) {
|
|
||||||
if (val && val.updateTime) {
|
|
||||||
this.excelList = [{
|
|
||||||
fileName: '电子发票--购买方公司信息.xlsx',
|
|
||||||
createUserName: '系统生成',
|
|
||||||
createTime: val.updateTime,
|
|
||||||
isSystemGenerated: true
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
immediate: true,
|
|
||||||
deep: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
|
|
||||||
isPdf(filePath) {
|
|
||||||
return filePath && filePath.toLowerCase().endsWith('.pdf');
|
|
||||||
},
|
|
||||||
getImageUrl(resource) {
|
|
||||||
return process.env.VUE_APP_BASE_API + "/common/download/resource?resource=" + resource;
|
|
||||||
},
|
|
||||||
handlePreview(row) {
|
|
||||||
if (this.isPdf(row.filePath)) {
|
|
||||||
request({
|
|
||||||
url: '/common/download/resource',
|
|
||||||
method: 'get',
|
|
||||||
params: { resource: row.filePath },
|
|
||||||
responseType: 'blob'
|
|
||||||
}).then(res => {
|
|
||||||
const blob = new Blob([res.data], { type: 'application/pdf' });
|
|
||||||
this.currentPdfUrl = URL.createObjectURL(blob);
|
|
||||||
this.pdfPreviewVisible = true;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.currentImageUrl = this.getImageUrl(row.filePath);
|
|
||||||
this.imagePreviewVisible = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleDownload(row) {
|
|
||||||
if (row.isSystemGenerated) {
|
|
||||||
request({
|
|
||||||
url: '/finance/invoice/export/' + this.data.invoiceBillCode,
|
|
||||||
method: 'get'
|
|
||||||
}).then(res => {
|
|
||||||
window.location.href = process.env.VUE_APP_BASE_API + "/common/download?fileName=" + encodeURIComponent(res.msg) + "&delete=true";
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const link = document.createElement('a');
|
|
||||||
link.href = this.getImageUrl(row.filePath);
|
|
||||||
link.download = row.fileName || 'attachment';
|
|
||||||
link.style.display = 'none';
|
|
||||||
document.body.appendChild(link);
|
|
||||||
link.click();
|
|
||||||
document.body.removeChild(link);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.invoice-detail {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,304 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="app-container">
|
|
||||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="120px">
|
|
||||||
<el-form-item label="开票编号" prop="invoiceBillCode">
|
|
||||||
<el-input v-model="queryParams.invoiceBillCode" placeholder="请输入开票编号" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="进货商" prop="partnerName">
|
|
||||||
<el-input v-model="queryParams.partnerName" placeholder="请输入进货商" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="项目名称" prop="projectName">
|
|
||||||
<el-input v-model="queryParams.projectName" placeholder="请输入项目名称" clearable @keyup.enter.native="handleQuery"/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="提交日期">
|
|
||||||
<el-date-picker
|
|
||||||
v-model="dateRange"
|
|
||||||
style="width: 240px"
|
|
||||||
value-format="yyyy-MM-dd HH:mm:ss"
|
|
||||||
type="daterange"
|
|
||||||
range-separator="-"
|
|
||||||
start-placeholder="开始日期"
|
|
||||||
end-placeholder="结束日期"
|
|
||||||
></el-date-picker>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
|
||||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
|
|
||||||
<el-row :gutter="10" class="mb8">
|
|
||||||
<el-col :span="1.5">
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
plain
|
|
||||||
size="mini"
|
|
||||||
@click="toApproved()"
|
|
||||||
>审批历史</el-button>
|
|
||||||
</el-col>
|
|
||||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
|
||||||
</el-row>
|
|
||||||
|
|
||||||
<el-table v-loading="loading" :data="invoiceList">
|
|
||||||
<el-table-column label="序号" type="index" width="50" align="center" />
|
|
||||||
<el-table-column label="开票编号" align="center" prop="invoiceBillCode" />
|
|
||||||
<el-table-column label="进货商" align="center" prop="partnerName" />
|
|
||||||
<el-table-column label="金额" align="center" prop="totalPriceWithTax">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<span :style="scope.row.totalPriceWithTax < 0 ? 'color: red' : ''">{{ formatCurrency(scope.row.totalPriceWithTax) }}</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="提交日期" align="center" prop="applyTime" width="180">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<span>{{ parseTime(scope.row.applyTime, '{y}-{m}-{d}') }}</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="审批节点" align="center" prop="approveNode" />
|
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="200">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleApprove(scope.row)">审批</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
|
|
||||||
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList"/>
|
|
||||||
|
|
||||||
<!-- 审批详情主对话框 -->
|
|
||||||
<el-dialog title="开票单审批" :visible.sync="detailDialogVisible" width="80%" append-to-body>
|
|
||||||
<div v-loading="detailLoading" style="max-height: 70vh; overflow-y: auto; padding: 20px;">
|
|
||||||
<div style="display: flex;flex-direction: row-reverse; margin-bottom: 10px;">
|
|
||||||
<el-button
|
|
||||||
type="primary"
|
|
||||||
size="small"
|
|
||||||
icon="el-icon-download"
|
|
||||||
@click="exportPDF"
|
|
||||||
:loading="pdfExporting"
|
|
||||||
>导出PDF</el-button>
|
|
||||||
</div>
|
|
||||||
<div class="approve-container" :class="{ 'exporting-pdf': pdfExporting }">
|
|
||||||
<ApproveLayout ref="approveLayout" title="开票单详情">
|
|
||||||
<receivable-invoice-detail :data="form"></receivable-invoice-detail>
|
|
||||||
<template #footer>
|
|
||||||
<span>{{ form.invoiceBillCode }}</span>
|
|
||||||
</template>
|
|
||||||
</ApproveLayout>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-divider content-position="left">流转意见</el-divider>
|
|
||||||
<div class="process-container">
|
|
||||||
<el-timeline>
|
|
||||||
<el-timeline-item v-for="(log, index) in approveLogs" :key="index" :timestamp="log.approveTime" placement="top">
|
|
||||||
<el-card>
|
|
||||||
<h4>{{ log.approveOpinion }}</h4>
|
|
||||||
<p><b>操作人:</b> {{ log.approveUserName }} </p>
|
|
||||||
<p><b>审批状态:</b> <el-tag :type="log.approveStatus == '3' ? 'success' : log.approveStatus == '2' ? 'danger' : 'info'">{{ getStatusText(log.approveStatus) }}</el-tag></p>
|
|
||||||
</el-card>
|
|
||||||
</el-timeline-item>
|
|
||||||
</el-timeline>
|
|
||||||
<div v-if="!approveLogs || approveLogs.length === 0">暂无流转过程数据。</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<span slot="footer" class="dialog-footer">
|
|
||||||
<el-button type="primary" @click="openOpinionDialog('approve')">同意</el-button>
|
|
||||||
<el-button type="danger" @click="openOpinionDialog('reject')">驳回</el-button>
|
|
||||||
<el-button @click="detailDialogVisible = false">取 消</el-button>
|
|
||||||
</span>
|
|
||||||
</el-dialog>
|
|
||||||
|
|
||||||
<!-- 审批意见对话框 -->
|
|
||||||
<el-dialog :title="confirmDialogTitle" :visible.sync="opinionDialogVisible" width="30%" append-to-body>
|
|
||||||
<el-form ref="opinionForm" :model="opinionForm" :rules="opinionRules" label-width="100px">
|
|
||||||
<el-form-item label="审批意见" prop="approveOpinion">
|
|
||||||
<el-input v-model="opinionForm.approveOpinion" type="textarea" :rows="4" placeholder="请输入审批意见"/>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<span slot="footer" class="dialog-footer">
|
|
||||||
<el-button @click="opinionDialogVisible = false">取 消</el-button>
|
|
||||||
<el-button type="primary" @click="showConfirmDialog()">确 定</el-button>
|
|
||||||
</span>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { listInvoiceApprove, getInvoiceDetail } from "@/api/finance/invoice";
|
|
||||||
import { approveTask, listCompletedFlows } from "@/api/flow";
|
|
||||||
import ReceivableInvoiceDetail from "./components/ReceivableInvoiceDetail";
|
|
||||||
import ApproveLayout from "@/views/approve/ApproveLayout";
|
|
||||||
import { exportElementToPDF } from "@/views/approve/finance/pdfUtils";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "ReceivableInvoiceRefundApprove",
|
|
||||||
components: { ReceivableInvoiceDetail, ApproveLayout },
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
loading: true,
|
|
||||||
showSearch: true,
|
|
||||||
total: 0,
|
|
||||||
invoiceList: [],
|
|
||||||
queryParams: {
|
|
||||||
pageNum: 1,
|
|
||||||
pageSize: 10,
|
|
||||||
invoiceBillCode: null,
|
|
||||||
partnerName: null,
|
|
||||||
projectName: null,
|
|
||||||
processKey: 'finance_invoice_refound',
|
|
||||||
orderByColumn: 'applyTime',
|
|
||||||
isAsc: 'desc'
|
|
||||||
},
|
|
||||||
dateRange: [],
|
|
||||||
detailDialogVisible: false,
|
|
||||||
detailLoading: false,
|
|
||||||
form: {},
|
|
||||||
approveLogs: [],
|
|
||||||
opinionDialogVisible: false,
|
|
||||||
confirmDialogTitle: '',
|
|
||||||
currentApproveType: '',
|
|
||||||
opinionForm: {
|
|
||||||
approveOpinion: ''
|
|
||||||
},
|
|
||||||
opinionRules: {
|
|
||||||
approveOpinion: [{ required: true, message: '审批意见不能为空', trigger: 'blur' }],
|
|
||||||
},
|
|
||||||
processKey: 'finance_invoice_refound',
|
|
||||||
taskId: null,
|
|
||||||
currentInvoiceId: null,
|
|
||||||
pdfExporting: false
|
|
||||||
};
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.getList();
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getList() {
|
|
||||||
this.loading = true;
|
|
||||||
listInvoiceApprove(this.addDateRange(this.queryParams, this.dateRange, 'ApplyTime')).then(response => {
|
|
||||||
this.invoiceList = response.rows;
|
|
||||||
this.total = response.total;
|
|
||||||
this.loading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
handleQuery() {
|
|
||||||
this.queryParams.pageNum = 1;
|
|
||||||
this.getList();
|
|
||||||
},
|
|
||||||
resetQuery() {
|
|
||||||
this.dateRange = [];
|
|
||||||
this.resetForm("queryForm");
|
|
||||||
this.handleQuery();
|
|
||||||
},
|
|
||||||
toApproved() {
|
|
||||||
this.$router.push('/approve/receivableInvoiceRefundLog')
|
|
||||||
},
|
|
||||||
handleApprove(row) {
|
|
||||||
this.resetDetailForm();
|
|
||||||
this.currentInvoiceId = row.id;
|
|
||||||
this.taskId = row.taskId;
|
|
||||||
this.detailLoading = true;
|
|
||||||
this.detailDialogVisible = true;
|
|
||||||
|
|
||||||
getInvoiceDetail(this.currentInvoiceId).then(response => {
|
|
||||||
this.form = response.data;
|
|
||||||
this.loadApproveHistory(this.form.invoiceBillCode);
|
|
||||||
this.detailLoading = false;
|
|
||||||
}).catch(() => {
|
|
||||||
this.detailLoading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
resetDetailForm() {
|
|
||||||
this.form = {};
|
|
||||||
this.approveLogs = [];
|
|
||||||
this.opinionForm.approveOpinion = '';
|
|
||||||
},
|
|
||||||
loadApproveHistory(businessKey) {
|
|
||||||
if (businessKey) {
|
|
||||||
let keys = [];
|
|
||||||
if(this.processKey) keys.push(this.processKey);
|
|
||||||
|
|
||||||
listCompletedFlows({ businessKey: businessKey, processKeyList: keys }).then(response => {
|
|
||||||
this.approveLogs = response.data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
openOpinionDialog(type) {
|
|
||||||
this.currentApproveType = type;
|
|
||||||
this.confirmDialogTitle = type === 'approve' ? '同意审批' : '驳回审批';
|
|
||||||
this.opinionDialogVisible = true;
|
|
||||||
this.opinionForm.approveOpinion = '';
|
|
||||||
this.$nextTick(() => {
|
|
||||||
if(this.$refs.opinionForm) this.$refs.opinionForm.clearValidate();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
showConfirmDialog() {
|
|
||||||
this.$refs.opinionForm.validate(valid => {
|
|
||||||
if (valid) {
|
|
||||||
this.opinionDialogVisible = false;
|
|
||||||
this.submitApproval();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
submitApproval() {
|
|
||||||
const approveBtn = this.currentApproveType === 'approve' ? 1 : 0;
|
|
||||||
const params = {
|
|
||||||
businessKey: this.form.invoiceBillCode,
|
|
||||||
processKey: this.processKey,
|
|
||||||
taskId: this.taskId,
|
|
||||||
variables: {
|
|
||||||
comment: this.opinionForm.approveOpinion,
|
|
||||||
approveBtn: approveBtn
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
approveTask(params).then(() => {
|
|
||||||
this.$modal.msgSuccess(this.confirmDialogTitle + "成功");
|
|
||||||
this.detailDialogVisible = false;
|
|
||||||
this.getList();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
getStatusText(status) {
|
|
||||||
if (!status) {
|
|
||||||
return '提交审批'
|
|
||||||
}
|
|
||||||
const map = { '1': '提交审批', '2': '驳回', '3': '批准' };
|
|
||||||
return map[status] || '提交审批';
|
|
||||||
},
|
|
||||||
async exportPDF() {
|
|
||||||
this.pdfExporting = true;
|
|
||||||
try {
|
|
||||||
const element = this.$refs.approveLayout.$el;
|
|
||||||
const fileName = `开票单-${this.form.invoiceBillCode || ''}.pdf`;
|
|
||||||
await exportElementToPDF(element, fileName);
|
|
||||||
this.$modal.msgSuccess('PDF导出成功');
|
|
||||||
} catch (error) {
|
|
||||||
console.error('PDF导出失败:', error);
|
|
||||||
this.$modal.msgError('PDF导出失败,请稍后重试');
|
|
||||||
} finally {
|
|
||||||
this.pdfExporting = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.process-container {
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 导出PDF时的特殊样式 */
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-button--primary,
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-button--text {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-input__inner,
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-textarea__inner {
|
|
||||||
border: none !important;
|
|
||||||
box-shadow: none !important;
|
|
||||||
background-color: transparent !important;
|
|
||||||
resize: none !important;
|
|
||||||
padding: 0 !important;
|
|
||||||
}
|
|
||||||
.approve-container.exporting-pdf ::v-deep .el-input__suffix {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -135,7 +135,8 @@
|
||||||
import { approveOrder,getOrder } from "@/api/approve/order";
|
import { approveOrder,getOrder } from "@/api/approve/order";
|
||||||
import ConfigInfo from './ConfigInfo.vue';
|
import ConfigInfo from './ConfigInfo.vue';
|
||||||
import ApproveLayout from '@/views/approve/ApproveLayout.vue';
|
import ApproveLayout from '@/views/approve/ApproveLayout.vue';
|
||||||
import { exportElementToPDF } from "@/views/approve/finance/pdfUtils";
|
import html2canvas from 'html2canvas';
|
||||||
|
import jsPDF from 'jspdf';
|
||||||
|
|
||||||
import OrderInfoDisplay from '@/views/project/order/components/OrderInfoDisplay.vue';
|
import OrderInfoDisplay from '@/views/project/order/components/OrderInfoDisplay.vue';
|
||||||
|
|
||||||
|
|
@ -467,21 +468,65 @@ export default {
|
||||||
// 导出PDF
|
// 导出PDF
|
||||||
async exportPDF() {
|
async exportPDF() {
|
||||||
this.pdfExporting = true;
|
this.pdfExporting = true;
|
||||||
|
const disabledElements = [];
|
||||||
try {
|
try {
|
||||||
// 获取ApproveLayout组件的DOM元素
|
// 获取ApproveLayout组件的DOM元素
|
||||||
const element = this.$refs.approveLayout.$el;
|
const element = this.$refs.approveLayout.$el;
|
||||||
|
|
||||||
|
// 移除所有输入框的 disabled 属性,以便在PDF中正确显示
|
||||||
|
element.querySelectorAll('input:disabled, textarea:disabled').forEach(el => {
|
||||||
|
disabledElements.push(el);
|
||||||
|
el.disabled = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 使用html2canvas捕获内容
|
||||||
|
const canvas = await html2canvas(element, {
|
||||||
|
scale: 2, // 提高清晰度
|
||||||
|
useCORS: true, // 允许跨域图片
|
||||||
|
logging: false, // 关闭日志
|
||||||
|
backgroundColor: '#F8F5F0' // 设置背景色
|
||||||
|
});
|
||||||
|
|
||||||
|
// 计算PDF页面尺寸
|
||||||
|
const imgWidth = 210; // A4纸宽度(mm)
|
||||||
|
const pageHeight = 297; // A4纸高度(mm)
|
||||||
|
const imgHeight = (canvas.height * imgWidth) / canvas.width;
|
||||||
|
let heightLeft = imgHeight;
|
||||||
|
|
||||||
|
// 创建PDF
|
||||||
|
const pdf = new jsPDF('p', 'mm', 'a4');
|
||||||
|
let position = 0;
|
||||||
|
|
||||||
|
// 将canvas转换为图片
|
||||||
|
const imgData = canvas.toDataURL('image/jpeg');
|
||||||
|
|
||||||
|
// 添加第一页
|
||||||
|
pdf.addImage(imgData, 'JPEG', 0, position, imgWidth, imgHeight);
|
||||||
|
heightLeft -= pageHeight;
|
||||||
|
|
||||||
|
// 如果内容超过一页,添加更多页
|
||||||
|
while (heightLeft > 0) {
|
||||||
|
position = heightLeft - imgHeight;
|
||||||
|
pdf.addPage();
|
||||||
|
pdf.addImage(imgData, 'JPEG', 0, position, imgWidth, imgHeight);
|
||||||
|
heightLeft -= pageHeight;
|
||||||
|
}
|
||||||
|
|
||||||
// 生成文件名
|
// 生成文件名
|
||||||
const fileName = `${this.order.projectCode || '订单'}-${this.order.orderCode || ''}-Rev.${this.order.versionCode || '1'}.pdf`;
|
const fileName = `${this.order.projectCode || '订单'}-${this.order.orderCode || ''}-Rev.${this.order.versionCode || '1'}.pdf`;
|
||||||
|
|
||||||
// 调用通用方法导出PDF
|
// 保存PDF
|
||||||
await exportElementToPDF(element, fileName);
|
pdf.save(fileName);
|
||||||
|
|
||||||
this.$modal.msgSuccess('PDF导出成功');
|
this.$modal.msgSuccess('PDF导出成功');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('PDF导出失败:', error);
|
console.error('PDF导出失败:', error);
|
||||||
this.$modal.msgError('PDF导出失败,请稍后重试');
|
this.$modal.msgError('PDF导出失败,请稍后重试');
|
||||||
} finally {
|
} finally {
|
||||||
|
// 恢复之前移除的 disabled 属性
|
||||||
|
disabledElements.forEach(el => {
|
||||||
|
el.disabled = true;
|
||||||
|
});
|
||||||
this.pdfExporting = false;
|
this.pdfExporting = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
<td v-if="!hidePrice">{{ product.discount ? (product.discount * 100).toFixed(2) + '%' : '-' }}</td>
|
<td v-if="!hidePrice">{{ product.discount ? (product.discount * 100).toFixed(2) + '%' : '-' }}</td>
|
||||||
<td>{{ formatCurrency(product.price) }}</td>
|
<td>{{ formatCurrency(product.price) }}</td>
|
||||||
<td>{{ selectedDiscountLabel }}</td>
|
<td>{{ selectedDiscountLabel }}</td>
|
||||||
<td>{{ formatCurrency(getDisplayAllPrice(product, selectedDiscount)) }}</td>
|
<td>{{ formatCurrency(product.allPrice) }}</td>
|
||||||
<td>{{ formatCurrency(getDiscountedAllPrice(product, selectedDiscount)) }}</td>
|
<td>{{ formatCurrency(getDiscountedAllPrice(product, selectedDiscount)) }}</td>
|
||||||
<td>
|
<td>
|
||||||
<el-input
|
<el-input
|
||||||
|
|
@ -86,7 +86,7 @@
|
||||||
<td v-if="!hidePrice">{{ product.discount ? (product.discount * 100).toFixed(2) + '%' : '-' }}</td>
|
<td v-if="!hidePrice">{{ product.discount ? (product.discount * 100).toFixed(2) + '%' : '-' }}</td>
|
||||||
<td>{{ formatCurrency(product.price) }}</td>
|
<td>{{ formatCurrency(product.price) }}</td>
|
||||||
<td>{{ selectedDiscountLabel }}</td>
|
<td>{{ selectedDiscountLabel }}</td>
|
||||||
<td>{{ formatCurrency(getDisplayAllPrice(product, selectedDiscount)) }}</td>
|
<td>{{ formatCurrency(product.allPrice) }}</td>
|
||||||
<td>{{ formatCurrency(getDiscountedAllPrice(product, selectedDiscount)) }}</td>
|
<td>{{ formatCurrency(getDiscountedAllPrice(product, selectedDiscount)) }}</td>
|
||||||
<td>
|
<td>
|
||||||
<el-input
|
<el-input
|
||||||
|
|
@ -142,7 +142,7 @@
|
||||||
<td v-if="!hidePrice">{{ product.discount ? (product.discount * 100).toFixed(2) + '%' : '-' }}</td>
|
<td v-if="!hidePrice">{{ product.discount ? (product.discount * 100).toFixed(2) + '%' : '-' }}</td>
|
||||||
<td>{{ formatCurrency(product.price) }}</td>
|
<td>{{ formatCurrency(product.price) }}</td>
|
||||||
<td>{{ selectedDiscountLabel }}</td>
|
<td>{{ selectedDiscountLabel }}</td>
|
||||||
<td>{{ formatCurrency(getDisplayAllPrice(product, selectedDiscount)) }}</td>
|
<td>{{ formatCurrency(product.allPrice) }}</td>
|
||||||
<td>{{ formatCurrency(getDiscountedAllPrice(product, selectedDiscount)) }}</td>
|
<td>{{ formatCurrency(getDiscountedAllPrice(product, selectedDiscount)) }}</td>
|
||||||
<td>
|
<td>
|
||||||
<el-input
|
<el-input
|
||||||
|
|
@ -178,7 +178,7 @@
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row type="flex" justify="end" align="middle" class="summary-row">
|
<el-row type="flex" justify="end" align="middle" class="summary-row">
|
||||||
<el-col :span="orderData.orderStatus==='1'?18:24" style="text-align: center;">
|
<el-col :span="18" style="text-align: center;">
|
||||||
<span style="margin-right: 5px;">商业折扣</span>
|
<span style="margin-right: 5px;">商业折扣</span>
|
||||||
<el-select
|
<el-select
|
||||||
v-model="selectedDiscount"
|
v-model="selectedDiscount"
|
||||||
|
|
@ -195,7 +195,7 @@
|
||||||
</el-option>
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6" v-if="orderData.orderStatus==='1'">
|
<el-col :span="6">
|
||||||
<span class="summary-label"> 折后总价合计</span> <span
|
<span class="summary-label"> 折后总价合计</span> <span
|
||||||
class="summary-value-right"> {{ formatCurrency(finalTotal) }}</span>
|
class="summary-value-right"> {{ formatCurrency(finalTotal) }}</span>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
@ -278,12 +278,7 @@ export default {
|
||||||
return this.calculateTotal(this.order.maintenanceProjectProductInfoList, this.selectedDiscount);
|
return this.calculateTotal(this.order.maintenanceProjectProductInfoList, this.selectedDiscount);
|
||||||
},
|
},
|
||||||
grandTotal() {
|
grandTotal() {
|
||||||
if (this.orderData.orderStatus === '1'){
|
|
||||||
|
|
||||||
return this.softwareTotal + this.hardwareTotal + this.maintenanceTotal;
|
return this.softwareTotal + this.hardwareTotal + this.maintenanceTotal;
|
||||||
}else{
|
|
||||||
return this.finalTotal;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
finalTotal() {
|
finalTotal() {
|
||||||
return this.softwareDiscountedTotal + this.hardwareDiscountedTotal + this.maintenanceDiscountedTotal;
|
return this.softwareDiscountedTotal + this.hardwareDiscountedTotal + this.maintenanceDiscountedTotal;
|
||||||
|
|
@ -302,20 +297,13 @@ export default {
|
||||||
// 税率变化时通知父组件
|
// 税率变化时通知父组件
|
||||||
this.$emit('tax-rate-change', product);
|
this.$emit('tax-rate-change', product);
|
||||||
},
|
},
|
||||||
getDisplayAllPrice(product, discount) {
|
|
||||||
const allPrice = product.allPrice || 0;
|
|
||||||
if (this.order.orderStatus === '2' || this.order.orderStatus === 2) {
|
|
||||||
return this.$calc.div(allPrice, discount || 1);
|
|
||||||
}
|
|
||||||
return allPrice;
|
|
||||||
},
|
|
||||||
getDiscountedAllPrice(product, discount) {
|
getDiscountedAllPrice(product, discount) {
|
||||||
const allPrice = product.allPrice || 0;
|
if (discount === 1) {
|
||||||
if (this.order.orderStatus === '2' || this.order.orderStatus === 2) {
|
return product.allPrice;
|
||||||
return allPrice;
|
|
||||||
}
|
}
|
||||||
const discountedPrice = this.$calc.mul(product.price || 0, discount == null ? 1 : discount, 2);
|
const roundedDiscountedUnitPrice = this.$calc.mul( product.price,discount);
|
||||||
return this.$calc.mul(discountedPrice, product.quantity || 0, 2);
|
|
||||||
|
return this.$calc.mul(roundedDiscountedUnitPrice , product.quantity);
|
||||||
},
|
},
|
||||||
calculateTotal(productList, discount) {
|
calculateTotal(productList, discount) {
|
||||||
if (!productList) return 0;
|
if (!productList) return 0;
|
||||||
|
|
|
||||||
|
|
@ -49,28 +49,15 @@
|
||||||
@keyup.enter.native="handleQuery"
|
@keyup.enter.native="handleQuery"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="产品编码" prop="productCode">
|
|
||||||
<el-input
|
|
||||||
v-model="queryParams.productCode"
|
|
||||||
placeholder="请输入产品编码"
|
|
||||||
clearable
|
|
||||||
@keyup.enter.native="handleQuery"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="产品型号" prop="productModel">
|
|
||||||
<el-input
|
|
||||||
v-model="queryParams.productModel"
|
|
||||||
placeholder="请输入产品型号"
|
|
||||||
clearable
|
|
||||||
@keyup.enter.native="handleQuery"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
|
<el-row :gutter="10" class="mb8">
|
||||||
|
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
|
</el-row>
|
||||||
<el-row :gutter="10" class="mb8">
|
<el-row :gutter="10" class="mb8">
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
<el-button
|
<el-button
|
||||||
|
|
@ -88,12 +75,7 @@
|
||||||
<el-table-column label="项目名称" align="center" prop="projectName" />
|
<el-table-column label="项目名称" align="center" prop="projectName" />
|
||||||
<el-table-column label="项目编号" align="center" prop="projectCode" />
|
<el-table-column label="项目编号" align="center" prop="projectCode" />
|
||||||
<el-table-column label="客户名称" align="center" prop="customerName" />
|
<el-table-column label="客户名称" align="center" prop="customerName" />
|
||||||
|
<el-table-column label="订单金额" align="center" prop="actualPurchaseAmount" />
|
||||||
<el-table-column label="订单金额" align="center" prop="actualPurchaseAmount" >
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<span>{{ formatCurrency(scope.row.actualPurchaseAmount || scope.row.shipmentAmount) }}</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="汇智负责人" align="center" prop="dutyName" />
|
<el-table-column label="汇智负责人" align="center" prop="dutyName" />
|
||||||
<el-table-column label="审批节点" align="center" prop="approveNode">
|
<el-table-column label="审批节点" align="center" prop="approveNode">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
|
|
@ -124,7 +106,6 @@
|
||||||
<el-dialog
|
<el-dialog
|
||||||
title="订单审批"
|
title="订单审批"
|
||||||
:visible.sync="approveDialogVisible"
|
:visible.sync="approveDialogVisible"
|
||||||
:close-on-click-modal="false"
|
|
||||||
custom-class="approve-dialog"
|
custom-class="approve-dialog"
|
||||||
width="80%"
|
width="80%"
|
||||||
top="5vh"
|
top="5vh"
|
||||||
|
|
@ -149,7 +130,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { listOrder } from "@/api/approve/order";
|
import { listOrder } from "@/api/approve/order";
|
||||||
import ApproveDialog from './Approve.vue';
|
import ApproveDialog from './Approve.vue';
|
||||||
import {formatCurrency} from "../../../utils";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "Order",
|
name: "Order",
|
||||||
|
|
@ -176,14 +156,9 @@ export default {
|
||||||
orderCode: null,
|
orderCode: null,
|
||||||
projectName: null,
|
projectName: null,
|
||||||
projectCode: null,
|
projectCode: null,
|
||||||
productCode: null,
|
|
||||||
productModel: null,
|
|
||||||
customerName: null,
|
customerName: null,
|
||||||
dutyName: null,
|
dutyName: null,
|
||||||
approveNode: null,
|
approveNode: null,
|
||||||
orderStatus: '1',
|
|
||||||
orderByColumn: 't2.id',
|
|
||||||
isAsc: 'desc',
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
@ -191,7 +166,6 @@ export default {
|
||||||
this.getList();
|
this.getList();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
formatCurrency,
|
|
||||||
toApproved(){
|
toApproved(){
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
path: '/approve/orderLog',
|
path: '/approve/orderLog',
|
||||||
|
|
|
||||||
|
|
@ -23,22 +23,7 @@
|
||||||
end-placeholder="结束日期"
|
end-placeholder="结束日期"
|
||||||
></el-date-picker>
|
></el-date-picker>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="产品编码" prop="productCode">
|
|
||||||
<el-input
|
|
||||||
v-model="queryParams.productCode"
|
|
||||||
placeholder="请输入产品编码"
|
|
||||||
clearable
|
|
||||||
@keyup.enter.native="handleQuery"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="产品型号" prop="productModel">
|
|
||||||
<el-input
|
|
||||||
v-model="queryParams.productModel"
|
|
||||||
placeholder="请输入产品型号"
|
|
||||||
clearable
|
|
||||||
@keyup.enter.native="handleQuery"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||||
|
|
@ -62,7 +47,7 @@
|
||||||
<el-table-column label="采购单号" align="center" prop="purchaseNo" />
|
<el-table-column label="采购单号" align="center" prop="purchaseNo" />
|
||||||
<el-table-column label="制造商名称" align="center" prop="vendorName"/>
|
<el-table-column label="制造商名称" align="center" prop="vendorName"/>
|
||||||
<el-table-column label="联系人" align="center" prop="vendorUser" />
|
<el-table-column label="联系人" align="center" prop="vendorUser" />
|
||||||
<el-table-column label="含税总金额" align="center" prop="totalAmount" :formatter="(row, column, cellValue)=>formatCurrency(cellValue)" />
|
<el-table-column label="含税总金额" align="center" prop="totalAmount" />
|
||||||
<el-table-column label="提交日期" align="center" prop="applyTime" >
|
<el-table-column label="提交日期" align="center" prop="applyTime" >
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<span>{{ parseTime(scope.row.applyTime, '{y}-{m}-{d}') }}</span>
|
<span>{{ parseTime(scope.row.applyTime, '{y}-{m}-{d}') }}</span>
|
||||||
|
|
@ -157,15 +142,12 @@ export default {
|
||||||
buyerName: null,
|
buyerName: null,
|
||||||
vendorName: null,
|
vendorName: null,
|
||||||
ownerName: null,
|
ownerName: null,
|
||||||
productCode: null,
|
|
||||||
productModel: null,
|
|
||||||
approveStatus: '1',
|
approveStatus: '1',
|
||||||
params:{
|
params:{
|
||||||
applyTimeStart: null,
|
applyTimeStart: null,
|
||||||
applyTimeEnd: null,
|
applyTimeEnd: null,
|
||||||
},
|
}
|
||||||
orderByColumn: 'applyTime',
|
|
||||||
isAsc: 'desc'
|
|
||||||
},
|
},
|
||||||
// 时间范围选择器
|
// 时间范围选择器
|
||||||
dateRangeApplyTime: [],
|
dateRangeApplyTime: [],
|
||||||
|
|
|
||||||
|
|
@ -23,22 +23,7 @@
|
||||||
end-placeholder="结束日期"
|
end-placeholder="结束日期"
|
||||||
></el-date-picker>
|
></el-date-picker>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="产品编码" prop="productCode">
|
|
||||||
<el-input
|
|
||||||
v-model="queryParams.productCode"
|
|
||||||
placeholder="请输入产品编码"
|
|
||||||
clearable
|
|
||||||
@keyup.enter.native="handleQuery"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="产品型号" prop="productModel">
|
|
||||||
<el-input
|
|
||||||
v-model="queryParams.productModel"
|
|
||||||
placeholder="请输入产品型号"
|
|
||||||
clearable
|
|
||||||
@keyup.enter.native="handleQuery"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||||
|
|
@ -62,7 +47,7 @@
|
||||||
<el-table-column label="采购单号" align="center" prop="purchaseNo" />
|
<el-table-column label="采购单号" align="center" prop="purchaseNo" />
|
||||||
<el-table-column label="制造商名称" align="center" prop="vendorName"/>
|
<el-table-column label="制造商名称" align="center" prop="vendorName"/>
|
||||||
<el-table-column label="联系人" align="center" prop="vendorUser" />
|
<el-table-column label="联系人" align="center" prop="vendorUser" />
|
||||||
<el-table-column label="含税总金额" align="center" prop="totalAmount" :formatter="(row, column, cellValue)=>formatCurrency(cellValue)" />
|
<el-table-column label="含税总金额" align="center" prop="totalAmount" />
|
||||||
<el-table-column label="提交日期" align="center" prop="applyTime" >
|
<el-table-column label="提交日期" align="center" prop="applyTime" >
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<span>{{ parseTime(scope.row.applyTime, '{y}-{m}-{d}') }}</span>
|
<span>{{ parseTime(scope.row.applyTime, '{y}-{m}-{d}') }}</span>
|
||||||
|
|
@ -149,16 +134,12 @@ export default {
|
||||||
purchaseNo: null,
|
purchaseNo: null,
|
||||||
buyerName: null,
|
buyerName: null,
|
||||||
vendorName: null,
|
vendorName: null,
|
||||||
productCode: null,
|
|
||||||
productModel: null,
|
|
||||||
ownerName: null,
|
ownerName: null,
|
||||||
approveStatus: '3', // 已审批状态通常为3
|
approveStatus: '3', // 已审批状态通常为3
|
||||||
params:{
|
params:{
|
||||||
applyTimeStart: null,
|
applyTimeStart: null,
|
||||||
applyTimeEnd: null,
|
applyTimeEnd: null,
|
||||||
},
|
}
|
||||||
orderByColumn: 'applyTime',
|
|
||||||
isAsc: 'desc'
|
|
||||||
},
|
},
|
||||||
// 时间范围选择器
|
// 时间范围选择器
|
||||||
dateRangeApplyTime: [],
|
dateRangeApplyTime: [],
|
||||||
|
|
|
||||||
|
|
@ -1,143 +0,0 @@
|
||||||
<template>
|
|
||||||
<el-drawer
|
|
||||||
title="报价单详情"
|
|
||||||
:visible.sync="visible"
|
|
||||||
direction="rtl"
|
|
||||||
size="80%"
|
|
||||||
:before-close="handleClose"
|
|
||||||
append-to-body
|
|
||||||
>
|
|
||||||
<div class="detail-container" v-loading="loading">
|
|
||||||
<!-- Basic Info -->
|
|
||||||
<el-divider content-position="left">基本信息</el-divider>
|
|
||||||
<el-descriptions :column="2" border size="medium">
|
|
||||||
<el-descriptions-item label="报价单号">{{ form.quotationCode }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="报价单名称">{{ form.quotationName }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="币种">
|
|
||||||
<dict-tag :options="dict.type.currency_type" :value="form.amountType"/>
|
|
||||||
</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="代表处">{{ agentName }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="客户名称">{{ form.customerName }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="状态">{{ form.quotationStatus }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="创建时间">{{ parseTime(form.createTime) }}</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="备注" :span="2">{{ form.remark }}</el-descriptions-item>
|
|
||||||
</el-descriptions>
|
|
||||||
|
|
||||||
<div v-if="form.quotationCode || catalogueTotalPrice > 0 || discountedTotalPrice > 0" style="margin-top: 20px;">
|
|
||||||
<el-row type="flex" justify="space-between" style="margin-bottom: 20px; font-size: 14px;">
|
|
||||||
<el-col :span="24" style="text-align: right;">
|
|
||||||
<span v-if="catalogueTotalPrice > 0" style="margin-right: 20px;">
|
|
||||||
<span style="font-weight: bold;">目录总价:</span>{{ formatAmount(catalogueTotalPrice) }}
|
|
||||||
</span>
|
|
||||||
<span v-if="discountedTotalPrice > 0">
|
|
||||||
<span style="font-weight: bold;">折后总价:</span>{{ formatAmount(discountedTotalPrice) }}
|
|
||||||
</span>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Config Info -->
|
|
||||||
<product-config :value="form" readonly />
|
|
||||||
</div>
|
|
||||||
</el-drawer>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { getQuotation } from "@/api/base/quotation";
|
|
||||||
import ProductConfig from "@/views/project/info/ProductConfig";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "QuotationDetail",
|
|
||||||
components: { ProductConfig },
|
|
||||||
dicts: ['currency_type'],
|
|
||||||
props: {
|
|
||||||
agentOptions: {
|
|
||||||
type: Array,
|
|
||||||
default: () => []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
visible: false,
|
|
||||||
loading: false,
|
|
||||||
form: {
|
|
||||||
softwareProjectProductInfoList: [],
|
|
||||||
hardwareProjectProductInfoList: [],
|
|
||||||
maintenanceProjectProductInfoList: []
|
|
||||||
}
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
agentName() {
|
|
||||||
if (!this.form.agentCode || !this.agentOptions) return this.form.agentCode;
|
|
||||||
const agent = this.agentOptions.find(item => item.agentCode === this.form.agentCode);
|
|
||||||
return agent ? agent.agentName : this.form.agentCode;
|
|
||||||
},
|
|
||||||
catalogueTotalPrice() {
|
|
||||||
let total = 0;
|
|
||||||
const lists = [
|
|
||||||
this.form.softwareProjectProductInfoList,
|
|
||||||
this.form.hardwareProjectProductInfoList,
|
|
||||||
this.form.maintenanceProjectProductInfoList
|
|
||||||
];
|
|
||||||
lists.forEach(list => {
|
|
||||||
if (list && list.length > 0) {
|
|
||||||
list.forEach(item => {
|
|
||||||
total += Number(item.catalogueAllPrice) || 0;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return total;
|
|
||||||
},
|
|
||||||
discountedTotalPrice() {
|
|
||||||
let total = 0;
|
|
||||||
const lists = [
|
|
||||||
this.form.softwareProjectProductInfoList,
|
|
||||||
this.form.hardwareProjectProductInfoList,
|
|
||||||
this.form.maintenanceProjectProductInfoList
|
|
||||||
];
|
|
||||||
lists.forEach(list => {
|
|
||||||
if (list && list.length > 0) {
|
|
||||||
list.forEach(item => {
|
|
||||||
total += Number(item.allPrice) || 0;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return total;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
open(id) {
|
|
||||||
this.visible = true;
|
|
||||||
this.getDetail(id);
|
|
||||||
},
|
|
||||||
getDetail(id) {
|
|
||||||
this.loading = true;
|
|
||||||
getQuotation(id).then(response => {
|
|
||||||
this.form = response.data;
|
|
||||||
// Ensure lists are arrays
|
|
||||||
this.form.softwareProjectProductInfoList = this.form.softwareProjectProductInfoList || [];
|
|
||||||
this.form.hardwareProjectProductInfoList = this.form.hardwareProjectProductInfoList || [];
|
|
||||||
this.form.maintenanceProjectProductInfoList = this.form.maintenanceProjectProductInfoList || [];
|
|
||||||
this.loading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
handleClose(done) {
|
|
||||||
this.visible = false;
|
|
||||||
if (done) done();
|
|
||||||
},
|
|
||||||
formatAmount(value) {
|
|
||||||
if (value === null || value === undefined) return '';
|
|
||||||
return Number(value).toLocaleString('en-US', {
|
|
||||||
minimumFractionDigits: 2,
|
|
||||||
maximumFractionDigits: 2
|
|
||||||
});
|
|
||||||
},
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
<style scoped>
|
|
||||||
.detail-container {
|
|
||||||
padding: 20px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue