add:新增知识库功能
This commit is contained in:
38
base-fast/Word模板标签文本.txt
Normal file
38
base-fast/Word模板标签文本.txt
Normal file
@@ -0,0 +1,38 @@
|
||||
# Word模板标签文本(直接复制使用)
|
||||
|
||||
## 循环开始标签
|
||||
{{#rows}}
|
||||
|
||||
## 循环结束标签
|
||||
{{/rows}}
|
||||
|
||||
## 数据字段标签
|
||||
{{seq}}
|
||||
{{materialName}}
|
||||
{{materialSpec}}
|
||||
{{qty}}
|
||||
{{unitName}}
|
||||
{{salePrice}}
|
||||
{{amount}}
|
||||
{{remark}}
|
||||
|
||||
## 其他字段标签
|
||||
{{totalPrice}}
|
||||
{{clientName}}
|
||||
{{contractCode}}
|
||||
{{effectiveDate}}
|
||||
|
||||
---
|
||||
|
||||
## 使用说明
|
||||
|
||||
1. 从本文件复制标签文本
|
||||
2. 粘贴到Word模板的对应位置
|
||||
3. 确保使用"无格式文本"粘贴
|
||||
|
||||
## 注意事项
|
||||
|
||||
- 标签必须完全匹配,包括大小写
|
||||
- 不要有多余的空格
|
||||
- 使用英文字符,不要用中文字符
|
||||
- {{#rows}} 中的 # 是英文井号
|
||||
243
base-fast/Word模板配置说明.md
Normal file
243
base-fast/Word模板配置说明.md
Normal file
@@ -0,0 +1,243 @@
|
||||
# Word合同模板配置说明
|
||||
|
||||
## 📋 问题原因
|
||||
|
||||
Word模板中的动态列表数据渲染失败,主要原因是:
|
||||
1. 没有配置 `LoopRowTableRenderPolicy` 循环行渲染策略
|
||||
2. 数据格式不匹配(直接传JSONArray而不是List<Map>)
|
||||
3. 模板语法使用不正确
|
||||
|
||||
## ✅ 解决方案
|
||||
|
||||
### 1. Word模板正确语法
|
||||
|
||||
在Word模板的表格中,需要使用以下格式:
|
||||
|
||||
```
|
||||
┌─────────┬──────────┬──────────┬──────┬──────┬──────────┬──────────┬──────┐
|
||||
│ 序号 │ 产品名称 │ 型号 │ 数量 │ 单位 │ 单价(元) │ 总价(元) │ 备注 │
|
||||
├─────────┼──────────┼──────────┼──────┼──────┼──────────┼──────────┼──────┤
|
||||
│{{#rows}}│ │ │ │ │ │ │ │
|
||||
├─────────┼──────────┼──────────┼──────┼──────┼──────────┼──────────┼──────┤
|
||||
│{{seq}} │{{materialName}}│{{materialSpec}}│{{qty}}│{{unitName}}│{{salePrice}}│{{amount}}│{{remark}}│
|
||||
├─────────┼──────────┼──────────┼──────┼──────┼──────────┼──────────┼──────┤
|
||||
│{{/rows}}│ │ │ │ │ │ │ │
|
||||
└─────────┴──────────┴──────────┴──────┴──────┴──────────┴──────────┴──────┘
|
||||
```
|
||||
|
||||
**重要说明**:
|
||||
- `{{#rows}}` 必须单独占一行(表格的一行)
|
||||
- 数据行包含所有字段:`{{seq}}`, `{{materialName}}` 等
|
||||
- `{{/rows}}` 必须单独占一行(表格的一行)
|
||||
- 这三行构成一个完整的循环结构
|
||||
|
||||
### 2. 模板文件位置
|
||||
|
||||
将模板文件放在以下位置之一:
|
||||
|
||||
**方式1:放在resources目录(推荐)**
|
||||
```
|
||||
src/main/resources/templates/contract_template.docx
|
||||
```
|
||||
|
||||
**方式2:使用绝对路径**
|
||||
```java
|
||||
/Users/mima0000/Desktop/合同.docx
|
||||
```
|
||||
|
||||
### 3. 后端代码关键点
|
||||
|
||||
#### 3.1 配置循环行策略
|
||||
```java
|
||||
LoopRowTableRenderPolicy policy = new LoopRowTableRenderPolicy();
|
||||
Configure config = Configure.builder()
|
||||
.bind("rows", policy) // 绑定rows标签
|
||||
.build();
|
||||
```
|
||||
|
||||
#### 3.2 数据格式转换
|
||||
```java
|
||||
// 错误方式 ❌
|
||||
dataMap.put("rows", JSONArray.parseArray(materialJson));
|
||||
|
||||
// 正确方式 ✅
|
||||
List<Map<String, Object>> rowsList = new ArrayList<>();
|
||||
for (int i = 0; i < materialArray.size(); i++) {
|
||||
JSONObject item = materialArray.getJSONObject(i);
|
||||
Map<String, Object> rowData = new HashMap<>();
|
||||
rowData.put("seq", i + 1);
|
||||
rowData.put("materialName", item.getString("materialName"));
|
||||
// ... 其他字段
|
||||
rowsList.add(rowData);
|
||||
}
|
||||
dataMap.put("rows", rowsList);
|
||||
```
|
||||
|
||||
#### 3.3 使用配置渲染
|
||||
```java
|
||||
XWPFTemplate template = XWPFTemplate.compile(templateStream, config)
|
||||
.render(dataMap);
|
||||
```
|
||||
|
||||
## 🎯 完整的Word模板示例
|
||||
|
||||
### 模板结构
|
||||
|
||||
```
|
||||
服务合同
|
||||
|
||||
需方:{{clientName}} 合同编号:{{contractCode}}
|
||||
供方:上海诺力智能科技有限公司 签订时间:{{effectiveDate}}
|
||||
|
||||
一、产品明细单
|
||||
|
||||
┌─────────┬──────────┬──────────┬──────┬──────┬──────────┬──────────┬──────┐
|
||||
│ 序号 │ 产品名称 │ 型号 │ 数量 │ 单位 │ 单价(元) │ 总价(元) │ 备注 │
|
||||
├─────────┼──────────┼──────────┼──────┼──────┼──────────┼──────────┼──────┤
|
||||
│{{#rows}}│ │ │ │ │ │ │ │
|
||||
├─────────┼──────────┼──────────┼──────┼──────┼──────────┼──────────┼──────┤
|
||||
│{{seq}} │{{materialName}}│{{materialSpec}}│{{qty}}│{{unitName}}│{{salePrice}}│{{amount}}│{{remark}}│
|
||||
├─────────┼──────────┼──────────┼──────┼──────┼──────────┼──────────┼──────┤
|
||||
│{{/rows}}│ │ │ │ │ │ │ │
|
||||
├─────────┴──────────┴──────────┴──────┴──────┴──────────┼──────────┼──────┤
|
||||
│ 共计: │{{totalPrice}}│ │
|
||||
└──────────────────────────────────────────────┴──────────┴──────┘
|
||||
|
||||
二、质量要求:{{qc}}
|
||||
三、交货时间、地点:货期:{{delivery}},交货地:{{place}}
|
||||
四、运输方式:{{transport}}
|
||||
五、包装标准:{{packaging}}
|
||||
六、结算方式:{{pay}},付款方式:{{payment}}
|
||||
七、违约责任:{{breach}}
|
||||
八、解决合同纠纷的方式:{{solve_dispute}}
|
||||
九、其它约定事项:{{supplement}}
|
||||
|
||||
┌──────────────────────────────┬──────────────────────────────┐
|
||||
│ 需方: │ 供方: │
|
||||
├──────────────────────────────┼──────────────────────────────┤
|
||||
│单位名称:{{clientName}} │单位名称:上海诺力智能科技有限公司│
|
||||
│地址:{{clientAdd}} │地址:上海青浦区徐泾镇... │
|
||||
│委托代理人:{{juridicalPerson}}│委托代理人: │
|
||||
│电话:{{clientTel}} │电话: │
|
||||
│传真:{{clientFax}} │传真: │
|
||||
│开户银行:{{clientBank}} │开户银行:招商银行虹桥支行 │
|
||||
│帐号:{{clientCard}} │帐号:12191702501091 │
|
||||
└──────────────────────────────┴──────────────────────────────┘
|
||||
```
|
||||
|
||||
## 📝 字段说明
|
||||
|
||||
### 基本信息字段
|
||||
| 字段名 | 说明 | 示例 |
|
||||
|--------|------|------|
|
||||
| clientName | 客户名称 | XX公司 |
|
||||
| contractCode | 合同编号 | HT20250101 |
|
||||
| effectiveDate | 生效日期 | 2025年01月01日 |
|
||||
| totalPrice | 总价 | 100000.00 |
|
||||
|
||||
### 列表字段(rows)
|
||||
| 字段名 | 说明 | 示例 |
|
||||
|--------|------|------|
|
||||
| seq | 序号 | 1, 2, 3... |
|
||||
| materialName | 产品名称 | 叉车 |
|
||||
| materialSpec | 型号 | CPD15 |
|
||||
| qty | 数量 | 10 |
|
||||
| unitName | 单位 | 台 |
|
||||
| salePrice | 单价 | 50000.00 |
|
||||
| amount | 总价 | 500000.00 |
|
||||
| remark | 备注 | 含税 |
|
||||
|
||||
### 合同条款字段
|
||||
| 字段名 | 说明 |
|
||||
|--------|------|
|
||||
| qc | 质量要求 |
|
||||
| delivery | 交货时间 |
|
||||
| place | 交货地点 |
|
||||
| transport | 运输方式 |
|
||||
| packaging | 包装标准 |
|
||||
| pay | 结算方式 |
|
||||
| payment | 付款方式 |
|
||||
| breach | 违约责任 |
|
||||
| solve_dispute | 解决纠纷方式 |
|
||||
| supplement | 其它约定 |
|
||||
|
||||
### 客户信息字段
|
||||
| 字段名 | 说明 |
|
||||
|--------|------|
|
||||
| clientAdd | 客户地址 |
|
||||
| juridicalPerson | 法人代表 |
|
||||
| clientTel | 客户电话 |
|
||||
| clientFax | 客户传真 |
|
||||
| clientBank | 客户开户行 |
|
||||
| clientCard | 客户账号 |
|
||||
|
||||
## 🔧 常见问题
|
||||
|
||||
### 1. 列表数据不显示
|
||||
**原因**:没有配置 `LoopRowTableRenderPolicy`
|
||||
**解决**:在代码中添加配置
|
||||
```java
|
||||
Configure config = Configure.builder()
|
||||
.bind("rows", policy)
|
||||
.build();
|
||||
```
|
||||
|
||||
### 2. 列表只显示一行
|
||||
**原因**:模板中 `{{#rows}}` 和 `{{/rows}}` 没有单独占一行
|
||||
**解决**:确保循环标签单独占表格的一行
|
||||
|
||||
### 3. 数据格式错误
|
||||
**原因**:直接传JSONArray而不是List<Map>
|
||||
**解决**:转换为List<Map<String, Object>>格式
|
||||
|
||||
### 4. 中文乱码
|
||||
**原因**:文件名编码问题
|
||||
**解决**:使用URLEncoder编码文件名
|
||||
```java
|
||||
String fileName = java.net.URLEncoder.encode("合同.docx", "UTF-8");
|
||||
```
|
||||
|
||||
## 🎉 测试步骤
|
||||
|
||||
1. **准备模板文件**
|
||||
- 按照上述格式创建Word模板
|
||||
- 保存为 `contract_template.docx`
|
||||
- 放到 `src/main/resources/templates/` 目录
|
||||
|
||||
2. **测试导出**
|
||||
- 访问:`GET /flow/contract/export?contractId=1`
|
||||
- 检查下载的Word文档
|
||||
- 验证列表数据是否正确显示
|
||||
|
||||
3. **验证数据**
|
||||
- 打开导出的Word文档
|
||||
- 检查产品明细表是否有多行数据
|
||||
- 检查所有字段是否正确填充
|
||||
|
||||
## 💡 最佳实践
|
||||
|
||||
1. **模板管理**
|
||||
- 将模板文件放在resources目录
|
||||
- 使用版本控制管理模板
|
||||
- 为不同类型合同创建不同模板
|
||||
|
||||
2. **错误处理**
|
||||
- 添加try-catch捕获异常
|
||||
- 记录详细的错误日志
|
||||
- 返回友好的错误提示
|
||||
|
||||
3. **性能优化**
|
||||
- 缓存模板对象
|
||||
- 使用流式处理大文件
|
||||
- 异步处理导出任务
|
||||
|
||||
## 📚 参考资料
|
||||
|
||||
- poi-tl官方文档:http://deepoove.com/poi-tl/
|
||||
- 循环行表格:http://deepoove.com/poi-tl/#_loop-row-table
|
||||
- GitHub示例:https://github.com/Sayi/poi-tl
|
||||
|
||||
---
|
||||
|
||||
**更新时间**: 2026-01-30
|
||||
**版本**: v1.0
|
||||
@@ -71,6 +71,42 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-aop</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>easyexcel</artifactId>
|
||||
<version>2.2.6</version>
|
||||
</dependency>
|
||||
<!--Excel-->
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi</artifactId>
|
||||
<version>4.1.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.deepoove</groupId>
|
||||
<artifactId>poi-tl</artifactId>
|
||||
<version>1.10.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi-ooxml</artifactId>
|
||||
<version>4.1.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi-ooxml-schemas</artifactId>
|
||||
<version>4.1.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-compress</artifactId>
|
||||
<version>1.21</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.11.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
|
||||
|
||||
@@ -67,6 +67,8 @@ public class ShiroConfig {
|
||||
filterMap.put("/js/**", "anon");
|
||||
filterMap.put("/img/**", "anon");
|
||||
filterMap.put("/fonts/**", "anon");
|
||||
filterMap.put("/fonts/**", "anon");
|
||||
filterMap.put("/flow/contract/export", "anon");
|
||||
|
||||
filterMap.put("/**", "oauth2");
|
||||
shiroFilter.setFilterChainDefinitionMap(filterMap);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.boge.modules.contract.controller;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
@@ -10,26 +12,31 @@ import com.boge.common.utils.CodeUtil;
|
||||
import com.boge.common.utils.PageUtils;
|
||||
import com.boge.common.utils.R;
|
||||
import com.boge.common.utils.ShiroUtils;
|
||||
import com.boge.modules.client.entity.ClientQuery;
|
||||
import com.boge.modules.contract.dao.ContractDao;
|
||||
import com.boge.modules.client.entity.ClientEntity;
|
||||
import com.boge.modules.client.service.ClientService;
|
||||
import com.boge.modules.contract.entity.ContractEntity;
|
||||
import com.boge.modules.contract.entity.ContractQuery;
|
||||
import com.boge.modules.contract.service.ContractService;
|
||||
import com.boge.modules.orderRecord.record.RecordEvent;
|
||||
import com.boge.modules.price.entity.PriceEntity;
|
||||
import com.boge.modules.price.enums.PriceApprovalEnum;
|
||||
import com.boge.modules.tickets.entity.LocalStorage;
|
||||
import com.boge.modules.tickets.service.LocalStorageService;
|
||||
import lombok.val;
|
||||
import com.boge.modules.sys.localStorage.service.entity.LocalStorage;
|
||||
import com.boge.modules.sys.localStorage.service.LocalStorageService;
|
||||
import com.deepoove.poi.XWPFTemplate;
|
||||
import com.deepoove.poi.data.RowRenderData;
|
||||
import com.deepoove.poi.data.Rows;
|
||||
import com.deepoove.poi.data.TableRenderData;
|
||||
import com.deepoove.poi.data.Tables;
|
||||
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
@@ -46,6 +53,8 @@ public class ContractController {
|
||||
@Autowired
|
||||
private ContractService contractService;
|
||||
@Autowired
|
||||
private ClientService clientService;
|
||||
@Autowired
|
||||
private LocalStorageService localStorageService;
|
||||
@Autowired
|
||||
private EventPublisher eventPublisher;
|
||||
@@ -132,4 +141,77 @@ public class ContractController {
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出合同
|
||||
*/
|
||||
@RequestMapping("/export")
|
||||
//@RequiresPermissions("flow:contract:delete")
|
||||
public void export(Integer contractId, HttpServletResponse response){
|
||||
try {
|
||||
// 1. 查询合同数据
|
||||
ContractEntity contract = contractService.selectDtlById(contractId);
|
||||
String materialJson = contract.getMaterialJson();
|
||||
ClientEntity clientEntity = clientService.getById(contract.getClientId());
|
||||
|
||||
// 2. 构建数据Map
|
||||
Map<String, Object> dataMap = new HashMap<>();
|
||||
dataMap.put("clientName", clientEntity.getClientName());
|
||||
dataMap.put("contractCode", contract.getContractCode());
|
||||
dataMap.put("effectiveDate", new SimpleDateFormat("yyyy年MM月dd日").format(contract.getEffectiveTime()));
|
||||
dataMap.put("clientAdd", clientEntity.getAddress());
|
||||
dataMap.put("juridicalPerson", clientEntity.getJuridicalPerson());
|
||||
dataMap.put("clientTel", clientEntity.getTel());
|
||||
dataMap.put("clientFax", clientEntity.getFax());
|
||||
dataMap.put("clientBank", clientEntity.getBank());
|
||||
dataMap.put("clientCard", clientEntity.getCard());
|
||||
dataMap.put("totalPrice", contract.getTotalPrice());
|
||||
dataMap.put("qc", contract.getQc());
|
||||
dataMap.put("delivery", contract.getDelivery());
|
||||
dataMap.put("place", contract.getPlace());
|
||||
dataMap.put("transport", contract.getTransport());
|
||||
dataMap.put("packaging", contract.getPackaging());
|
||||
dataMap.put("pay", contract.getPay());
|
||||
dataMap.put("payment", contract.getPayment());
|
||||
dataMap.put("breach", contract.getBreach());
|
||||
dataMap.put("solve_dispute", contract.getSolveDispute());
|
||||
dataMap.put("supplement", contract.getSupplement());
|
||||
|
||||
// 3. 处理产品明细列表数据
|
||||
JSONArray materialArray = JSONArray.parseArray(materialJson);
|
||||
List<Map<String, Object>> rowsList = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < materialArray.size(); i++) {
|
||||
JSONObject item = materialArray.getJSONObject(i);
|
||||
Map<String, Object> rowData = new HashMap<>();
|
||||
rowData.put("seq", i + 1); // 序号
|
||||
rowData.put("materialName", item.getString("materialName"));
|
||||
rowData.put("materialSpec", item.getString("materialSpec"));
|
||||
rowData.put("qty", item.getString("qty"));
|
||||
rowData.put("unitName", item.getString("unitName"));
|
||||
rowData.put("salePrice", item.getString("salePrice"));
|
||||
rowData.put("amount", item.getString("amount"));
|
||||
rowData.put("remark", item.getString("remark"));
|
||||
rowsList.add(rowData);
|
||||
}
|
||||
dataMap.put("goods", rowsList);
|
||||
// 4. 配置循环行渲染策略
|
||||
com.deepoove.poi.config.Configure config = com.deepoove.poi.config.Configure.builder()
|
||||
.bind("goods", new LoopRowTableRenderPolicy()) // 绑定rows标签使用循环行策略
|
||||
.build();
|
||||
InputStream templateStream = new java.io.FileInputStream("/Users/mima0000/Desktop/合同.docx");
|
||||
XWPFTemplate template = XWPFTemplate.compile(templateStream, config).render(dataMap);
|
||||
// 6. 设置响应头
|
||||
String fileName = "合同_" + contract.getContractCode() + ".docx";
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
|
||||
response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" +
|
||||
java.net.URLEncoder.encode(fileName, "UTF-8"));
|
||||
// 7. 输出到响应流
|
||||
template.write(response.getOutputStream());
|
||||
template.close();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
throw new RuntimeException("导出合同失败: " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,8 +13,8 @@ import com.boge.modules.flow.entity.FlwHiTaskEntity;
|
||||
import com.boge.modules.flow.service.ActHiProcessinfoService;
|
||||
import com.boge.modules.flow.service.FlwInstanceService;
|
||||
import com.boge.modules.sys.entity.SysUserEntity;
|
||||
import com.boge.modules.tickets.entity.LocalStorage;
|
||||
import com.boge.modules.tickets.service.LocalStorageService;
|
||||
import com.boge.modules.sys.localStorage.service.entity.LocalStorage;
|
||||
import com.boge.modules.sys.localStorage.service.LocalStorageService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package com.boge.modules.price.controller;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.boge.common.publisher.EventPublisher;
|
||||
import com.boge.common.publisher.EventType;
|
||||
@@ -11,18 +11,18 @@ import com.boge.common.utils.PageUtils;
|
||||
import com.boge.common.utils.R;
|
||||
import com.boge.common.utils.ShiroUtils;
|
||||
import com.boge.modules.orderRecord.record.RecordEvent;
|
||||
import com.boge.modules.orderRecord.record.service.PmOrderRecordService;
|
||||
import com.boge.modules.price.entity.PriceDto;
|
||||
import com.boge.modules.price.entity.PriceEntity;
|
||||
import com.boge.modules.price.enums.PriceApprovalEnum;
|
||||
import com.boge.modules.price.service.PriceService;
|
||||
import com.boge.modules.tickets.entity.LocalStorage;
|
||||
import com.boge.modules.tickets.service.LocalStorageService;
|
||||
import com.boge.modules.sys.localStorage.service.entity.LocalStorage;
|
||||
import com.boge.modules.sys.localStorage.service.LocalStorageService;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
@@ -128,4 +128,16 @@ public class PriceController {
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 审核
|
||||
*/
|
||||
@RequestMapping("/export")
|
||||
//@RequiresPermissions("flow:contract:delete")
|
||||
public R export(Integer priceId, HttpServletResponse response){
|
||||
PriceEntity contract = priceService.getById(priceId);
|
||||
ClassPathResource pathResource = new ClassPathResource("static/model/报价单样式.xls");// 根目录
|
||||
String materialJson = contract.getMaterialJson();
|
||||
localStorageService.downloadExcelModel(pathResource.getPath(),response,(JSONObject)JSON.toJSON(contract),JSONArray.parseArray(materialJson));
|
||||
return R.ok();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
// Source code recreated from a .class file by IntelliJ IDEA
|
||||
// (powered by FernFlower decompiler)
|
||||
//
|
||||
package com.boge.modules.sys;
|
||||
package com.boge.modules.sys.localStorage.controller;
|
||||
|
||||
import com.boge.common.exception.RRException;
|
||||
import com.boge.common.utils.FileUtil;
|
||||
import com.boge.modules.tickets.entity.LocalStorage;
|
||||
import com.boge.modules.tickets.service.LocalStorageService;
|
||||
import com.boge.modules.sys.localStorage.service.LocalStorageService;
|
||||
import com.boge.modules.sys.localStorage.service.entity.LocalStorage;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@@ -1,14 +1,14 @@
|
||||
package com.boge.modules.tickets.service;
|
||||
package com.boge.modules.sys.localStorage.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.boge.modules.tickets.entity.LocalStorage;
|
||||
import com.boge.modules.tickets.entity.TicketsEntity;
|
||||
import com.boge.modules.sys.localStorage.service.entity.LocalStorage;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface LocalStorageService extends IService<LocalStorage> {
|
||||
|
||||
@@ -21,4 +21,14 @@ public interface LocalStorageService extends IService<LocalStorage> {
|
||||
|
||||
void download(List<LocalStorage> localStorageDtos, HttpServletResponse response) throws IOException;
|
||||
void downloadFile(LocalStorage localStorage, HttpServletRequest request, HttpServletResponse response) throws IOException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param fileUrl
|
||||
* @param response
|
||||
* @param mapParam:模版中json的数据{xxx}
|
||||
* @param listParam:模版中列表的数据{date.xxx}
|
||||
*/
|
||||
void downloadExcelModel(String fileUrl, HttpServletResponse response, Map mapParam, List listParam);
|
||||
void downloadWordModel(String fileUrl, HttpServletResponse response, Map mapParam);
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
package com.boge.modules.tickets.dao;
|
||||
package com.boge.modules.sys.localStorage.service.dao;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.boge.modules.tickets.entity.LocalStorage;
|
||||
import com.boge.modules.tickets.entity.TicketsEntity;
|
||||
import com.boge.modules.sys.localStorage.service.entity.LocalStorage;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.boge.modules.sys.localStorage.service.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
@Data
|
||||
public class LocalStorageDto implements Serializable {
|
||||
private Long id;
|
||||
private String realName;
|
||||
private String name;
|
||||
private String suffix;
|
||||
private String type;
|
||||
private String size;
|
||||
|
||||
}
|
||||
@@ -1,19 +1,11 @@
|
||||
package com.boge.modules.tickets.entity;
|
||||
package com.boge.modules.sys.localStorage.service.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import org.hibernate.annotations.CreationTimestamp;
|
||||
import org.hibernate.annotations.UpdateTimestamp;
|
||||
import org.springframework.data.annotation.CreatedBy;
|
||||
import org.springframework.data.annotation.LastModifiedBy;
|
||||
import org.springframework.data.elasticsearch.annotations.Document;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.io.Serializable;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.boge.modules.tickets.entity;
|
||||
package com.boge.modules.sys.localStorage.service.entity;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.List;
|
||||
@@ -1,29 +1,41 @@
|
||||
package com.boge.modules.tickets.service.impl;
|
||||
package com.boge.modules.sys.localStorage.service.impl;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.alibaba.excel.EasyExcel;
|
||||
import com.alibaba.excel.ExcelWriter;
|
||||
import com.alibaba.excel.write.metadata.WriteSheet;
|
||||
import com.alibaba.excel.write.metadata.fill.FillWrapper;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.boge.common.exception.RRException;
|
||||
import com.boge.common.query.MapOf;
|
||||
import com.boge.common.utils.FileProperties;
|
||||
import com.boge.common.utils.FileUtil;
|
||||
import com.boge.modules.contract.entity.ContractEntity;
|
||||
import com.boge.modules.contract.service.ContractService;
|
||||
import com.boge.modules.tickets.dao.LocalStorageMapper;
|
||||
import com.boge.modules.tickets.entity.LocalStorage;
|
||||
|
||||
import com.boge.modules.tickets.service.LocalStorageService;
|
||||
|
||||
import com.boge.modules.sys.localStorage.service.LocalStorageService;
|
||||
import com.boge.modules.sys.localStorage.service.dao.LocalStorageMapper;
|
||||
import com.boge.modules.sys.localStorage.service.entity.LocalStorage;
|
||||
import com.deepoove.poi.XWPFTemplate;
|
||||
import org.apache.poi.xwpf.usermodel.XWPFDocument;
|
||||
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
|
||||
import org.apache.poi.xwpf.usermodel.XWPFRun;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.validation.BindException;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.*;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.*;
|
||||
@Service
|
||||
public class LocalStorageServiceImpl extends ServiceImpl<LocalStorageMapper, LocalStorage> implements LocalStorageService {
|
||||
|
||||
@@ -101,4 +113,56 @@ public class LocalStorageServiceImpl extends ServiceImpl<LocalStorageMapper, Lo
|
||||
FileUtil.downloadFile(request, response,file,false);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void downloadExcelModel(String fileUrl, HttpServletResponse response, Map mapParam, List listParam){
|
||||
ExcelWriter writer;
|
||||
InputStream templateInputStream = null;
|
||||
try {
|
||||
ClassPathResource classPathResource = new ClassPathResource(fileUrl);
|
||||
if (!classPathResource.exists()){
|
||||
throw new RRException("文件不存在"+fileUrl);
|
||||
}
|
||||
templateInputStream = classPathResource.getInputStream();
|
||||
// templateInputStream = new FileInputStream("/Users/mima0000/Desktop/报价单.xlsx");
|
||||
response.setHeader("Content-Disposition", "attachment; filename*=UTf-8''"+"12321"+".xlsx");
|
||||
ServletOutputStream outputStream = response.getOutputStream();
|
||||
writer = EasyExcel.write(outputStream).withTemplate(templateInputStream).build();
|
||||
WriteSheet sheet = EasyExcel.writerSheet().build();
|
||||
writer.fill(mapParam, sheet);
|
||||
if (!CollectionUtils.isEmpty(listParam)){
|
||||
writer.fill(new FillWrapper("data", listParam), sheet);
|
||||
}
|
||||
writer.finish();
|
||||
outputStream.close();
|
||||
}catch (Exception ex){
|
||||
ex.printStackTrace();
|
||||
throw new RRException(ex.getMessage());
|
||||
}finally {
|
||||
// ExcelWriter writer;
|
||||
// InputStream templateInputStream;
|
||||
try{
|
||||
if (templateInputStream!=null) templateInputStream.close();
|
||||
}catch (Exception ex){}
|
||||
}
|
||||
|
||||
}
|
||||
public void downloadWordModel(String fileUrl, HttpServletResponse response, Map mapParam){
|
||||
// 2. 加载模板并填充(类似 EasyExcel)
|
||||
ClassPathResource classPathResource = new ClassPathResource(fileUrl);
|
||||
|
||||
// if (!classPathResource.exists()){
|
||||
// throw new RRException("文件不存在"+fileUrl);
|
||||
// }
|
||||
InputStream inputStream = null;
|
||||
XWPFTemplate template = null;
|
||||
try {
|
||||
// 3. 输出到文件
|
||||
template = XWPFTemplate.compile("/Users/mima0000/Desktop/合同.docx").render(mapParam);
|
||||
template.writeAndClose(new FileOutputStream("/Users/mima0000/Desktop/"+new Random().nextInt(1000)+"23.docx"));
|
||||
}catch (Exception ex){
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
//
|
||||
// Source code recreated from a .class file by IntelliJ IDEA
|
||||
// (powered by FernFlower decompiler)
|
||||
//
|
||||
package com.boge.modules.tickets.controller;
|
||||
import com.boge.common.exception.RRException;
|
||||
import com.boge.common.utils.FileUtil;
|
||||
import com.boge.modules.tickets.entity.LocalStorage;
|
||||
import com.boge.modules.tickets.service.LocalStorageService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
@RestController
|
||||
@Api(
|
||||
tags = {"工具:本地存储管理"}
|
||||
)
|
||||
@RequestMapping({"/api/localStorage"})
|
||||
public class LocalStorageController {
|
||||
private final LocalStorageService localStorageService;
|
||||
|
||||
@ApiOperation("查询文件")
|
||||
@GetMapping
|
||||
public ResponseEntity<Object> query(@RequestParam String annex) {
|
||||
List<LocalStorage> list = new ArrayList<>();
|
||||
if (StringUtils.isNotEmpty(annex)){
|
||||
String[] split = annex.split(",");
|
||||
list = localStorageService.listByIds(Arrays.asList(split));
|
||||
}
|
||||
return new ResponseEntity(list, HttpStatus.OK);
|
||||
}
|
||||
|
||||
@ApiOperation("导出数据")
|
||||
@GetMapping({"/download"})
|
||||
public void download(@RequestParam Long storageId , HttpServletResponse response, HttpServletRequest request) throws IOException {
|
||||
this.localStorageService.downloadFile(this.localStorageService.getById(storageId),request, response);
|
||||
}
|
||||
|
||||
@ApiOperation("上传文件")
|
||||
@PostMapping
|
||||
public ResponseEntity<Object> create(@RequestParam String name, @RequestParam("file") MultipartFile file) {
|
||||
LocalStorage localStorage = this.localStorageService.create(name, file);
|
||||
return new ResponseEntity(localStorage, HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
@PostMapping({"/pictures"})
|
||||
@ApiOperation("上传图片")
|
||||
public ResponseEntity<Object> upload(@RequestParam MultipartFile file) {
|
||||
String suffix = FileUtil.getExtensionName(file.getOriginalFilename());
|
||||
if (!"图片".equals(FileUtil.getFileType(suffix))) {
|
||||
throw new RRException("只能上传图片");
|
||||
} else {
|
||||
LocalStorage localStorage = this.localStorageService.create((String)null, file);
|
||||
return new ResponseEntity(localStorage, HttpStatus.OK);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@DeleteMapping
|
||||
@ApiOperation("多选删除")
|
||||
public ResponseEntity<Object> delete(@RequestBody Long[] ids) {
|
||||
localStorageService.removeByIds(Arrays.asList(ids));
|
||||
return new ResponseEntity(HttpStatus.OK);
|
||||
}
|
||||
|
||||
public LocalStorageController(final LocalStorageService localStorageService) {
|
||||
this.localStorageService = localStorageService;
|
||||
}
|
||||
}
|
||||
@@ -8,11 +8,7 @@ import com.boge.common.utils.ShiroUtils;
|
||||
import com.boge.modules.sys.entity.SysUserEntity;
|
||||
import com.boge.modules.tickets.dto.TicketsDTO;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import com.boge.modules.tickets.entity.TicketsEntity;
|
||||
import com.boge.modules.tickets.service.TicketsService;
|
||||
@@ -78,6 +74,16 @@ public class TicketsController {
|
||||
ticketsService.saveTicket(tickets);
|
||||
return R.ok();
|
||||
}
|
||||
/**
|
||||
* 发起
|
||||
*/
|
||||
@GetMapping("/initiate")
|
||||
//@RequiresPermissions("tickets:tickets:save")
|
||||
public R initiate( String ticketsId){
|
||||
ticketsService.initiate(ticketsId);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 修改
|
||||
|
||||
@@ -10,7 +10,8 @@ import lombok.Getter;
|
||||
UNCHECK(0, "未开始"),
|
||||
CHECKED(1, "已指派"),
|
||||
REJECT(2, "处理中"),
|
||||
FINISH(3, "已完成");
|
||||
FINISH(3, "已完成"),
|
||||
REFUSE(4, "拒绝");
|
||||
|
||||
private Integer code;
|
||||
private String msg;
|
||||
|
||||
@@ -23,5 +23,7 @@ public interface TicketsService extends IService<TicketsEntity> {
|
||||
PageUtils queryPageByType(Map<String, Object> params);
|
||||
|
||||
void saveTicket(TicketsEntity tickets);
|
||||
|
||||
void initiate(String ticketsId);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@ package com.boge.modules.tickets.service.impl;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.boge.common.exception.RRException;
|
||||
import com.boge.common.utils.ShiroUtils;
|
||||
import com.boge.modules.car.entity.CarEntity;
|
||||
import com.boge.modules.car.service.CarService;
|
||||
@@ -13,6 +15,7 @@ import com.boge.modules.sys.service.SysUserRoleService;
|
||||
import com.boge.modules.sys.service.impl.SysUserServiceImpl;
|
||||
import com.boge.modules.tickets.dto.TicketsDTO;
|
||||
import com.boge.modules.tickets.enums.TicketUserEnums;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.flowable.common.engine.api.FlowableException;
|
||||
import org.flowable.engine.IdentityService;
|
||||
import org.flowable.engine.RuntimeService;
|
||||
@@ -115,22 +118,27 @@ public class TicketsServiceImpl extends ServiceImpl<TicketsDao, TicketsEntity> i
|
||||
|
||||
@Override
|
||||
public void saveTicket(TicketsEntity tickets) {
|
||||
// 启动流程
|
||||
try {
|
||||
// 记录流程的发起人
|
||||
identityService.setAuthenticatedUserId(ShiroUtils.getUserId().toString());
|
||||
Map<String, Object> startVars = new HashMap<>();
|
||||
ProcessInstance processInstance = runtimeService.startProcessInstanceById(defId, startVars);
|
||||
SysUserEntity loginUser = ShiroUtils.getUserEntity();
|
||||
tickets.setCreateTime(new Date());
|
||||
tickets.setCreateUser(loginUser.getNickname());
|
||||
tickets.setStatus(TicketsStatusEnums.REJECT.getCode());
|
||||
tickets.setAssignUserId(TicketUserEnums.SPECIALIST.getCode());
|
||||
tickets.setProcessInstance(processInstance.getProcessInstanceId());
|
||||
ticketsDao.insert(tickets);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
SysUserEntity loginUser = ShiroUtils.getUserEntity();
|
||||
tickets.setCreateTime(new Date());
|
||||
tickets.setCreateUser(loginUser.getNickname());
|
||||
tickets.setStatus(TicketsStatusEnums.UNCHECK.getCode());
|
||||
ticketsDao.insert(tickets);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initiate(String ticketsId) {
|
||||
if (StringUtils.isEmpty(ticketsId)){
|
||||
throw new RRException("工单ID不能为空");
|
||||
}
|
||||
// 记录流程的发起人
|
||||
identityService.setAuthenticatedUserId(ShiroUtils.getUserId().toString());
|
||||
Map<String, Object> startVars = new HashMap<>();
|
||||
ProcessInstance processInstance = runtimeService.startProcessInstanceById(defId, startVars);
|
||||
this.update(new LambdaUpdateWrapper<TicketsEntity>()
|
||||
.set(TicketsEntity::getProcessInstance,processInstance.getProcessInstanceId())
|
||||
.set(TicketsEntity::getStatus,TicketsStatusEnums.REJECT.getCode())
|
||||
.set(TicketsEntity::getAssignUserId,ShiroUtils.getUserId())
|
||||
.eq(TicketsEntity::getTicketsId,ticketsId));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
BIN
base-fast/src/main/resources/templates/合同.docx
Normal file
BIN
base-fast/src/main/resources/templates/合同.docx
Normal file
Binary file not shown.
BIN
base-fast/src/main/resources/templates/报价单.xlsx
Normal file
BIN
base-fast/src/main/resources/templates/报价单.xlsx
Normal file
Binary file not shown.
@@ -52,19 +52,14 @@
|
||||
</span>
|
||||
</div>
|
||||
<div class="clause-item">
|
||||
<strong>三、 售后服务:</strong>
|
||||
<span v-text="dataForm.after_sales" @input="this.dataForm.after_sales = $event.target.innerText" class="editable-clause" contenteditable="true" style="text-decoration: underline;">
|
||||
</span>
|
||||
</div>
|
||||
<div class="clause-item">
|
||||
<strong>四、 交货时间、地点:</strong>
|
||||
<strong>三、 服务时间、地点:</strong>
|
||||
货期:
|
||||
<span v-text="dataForm.delivery" @input="this.dataForm.delivery = $event.target.innerText" class="editable-clause" contenteditable="true" style="text-decoration: underline;"/>
|
||||
。交货地:
|
||||
<span v-text="dataForm.place" @input="this.dataForm.place = $event.target.innerText" class="editable-clause" contenteditable="true" style="text-decoration: underline;"/>
|
||||
</div>
|
||||
<div class="clause-item">
|
||||
<strong>五、 运输方式及到达站和费用负担:</strong>
|
||||
<strong>四、 运输方式及到达站和费用负担:</strong>
|
||||
<span v-text="dataForm.transport" @input="this.dataForm.transport = $event.target.innerText" class="editable-clause" contenteditable="true" style="text-decoration: underline;"/>
|
||||
</div>
|
||||
<div class="clause-item">
|
||||
@@ -285,193 +280,33 @@ export default {
|
||||
return result
|
||||
},
|
||||
exportToExcel () {
|
||||
// 获取客户名称
|
||||
let clientName = ''
|
||||
if (this.dictData && this.dictData[1]) {
|
||||
const client = this.dictData[1].find(item => item.value === this.dataForm.clientId)
|
||||
clientName = client ? client.label : ''
|
||||
// 检查contractId是否存在
|
||||
if (!this.dataForm.contractId) {
|
||||
this.$message.error('合同ID不存在,无法导出')
|
||||
return
|
||||
}
|
||||
|
||||
// 构建Excel HTML内容
|
||||
let excelHtml = `
|
||||
<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">
|
||||
<!--[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: 100%;
|
||||
}
|
||||
th, td {
|
||||
border: 1px solid #000;
|
||||
padding: 8px;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
}
|
||||
th {
|
||||
background-color: #f5f5f5;
|
||||
font-weight: bold;
|
||||
}
|
||||
.text-left {
|
||||
text-align: left;
|
||||
}
|
||||
.title-row {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
padding: 10px 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<table>
|
||||
<tr>
|
||||
<td colspan="8" style="font-size: 18px; font-weight: bold; text-align: center; padding: 15px;">产品购销合同</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="4" class="text-left">需方:${clientName}</td>
|
||||
<td colspan="4" class="text-left">合同编号:${this.dataForm.contractCode || ''}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="4" class="text-left">供方:上海诺力智能科技有限公司</td>
|
||||
<td colspan="4" class="text-left">生效日期:${this.dataForm.effectiveTime || ''}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="8" class="text-left title-row">一、产品明细单</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>序号</th>
|
||||
<th>产品名称</th>
|
||||
<th>订货代码</th>
|
||||
<th>型号</th>
|
||||
<th>数量</th>
|
||||
<th>单位</th>
|
||||
<th>单价(元)</th>
|
||||
<th>总价(元)</th>
|
||||
</tr>
|
||||
`
|
||||
|
||||
// 添加产品明细
|
||||
this.materData.forEach((item, index) => {
|
||||
excelHtml += `
|
||||
<tr>
|
||||
<td>${index + 1}</td>
|
||||
<td>${item.materialName || ''}</td>
|
||||
<td>${item.materialCode || ''}</td>
|
||||
<td>${item.materialSpec || ''}</td>
|
||||
<td>${item.qty || ''}</td>
|
||||
<td>${item.unitName || ''}</td>
|
||||
<td>${item.salePrice || ''}</td>
|
||||
<td>${item.amount || ''}</td>
|
||||
</tr>
|
||||
`
|
||||
// 调用后端接口导出Excel
|
||||
const url = this.$http.adornUrl('/flow/contract/export')
|
||||
const params = this.$http.adornParams({
|
||||
contractId: this.dataForm.contractId
|
||||
})
|
||||
|
||||
// 添加合计行
|
||||
excelHtml += `
|
||||
<tr>
|
||||
<td colspan="7" class="text-left">共计:</td>
|
||||
<td>${this.dataForm.totalPrice || ''}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="6" class="text-left">共计人民币金额:(大写)${this.toChineseCurrency(this.dataForm.totalPrice)}</td>
|
||||
<td colspan="2">含13%增值税</td>
|
||||
</tr>
|
||||
`
|
||||
// 构建完整的URL
|
||||
const fullUrl = `${url}?${new URLSearchParams(params).toString()}`
|
||||
|
||||
// 添加合同条款
|
||||
excelHtml += `
|
||||
<tr>
|
||||
<td colspan="8" class="text-left">二、质量要求、技术标准、供方对质量负责的条件和期限:${this.dataForm.qc || ''}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="8" class="text-left">三、售后服务:${this.dataForm.afterSales || ''}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="8" class="text-left">四、交货时间、地点:货期:${this.dataForm.delivery || ''},交货地:${this.dataForm.place || ''}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="8" class="text-left">五、运输方式及到达站和费用负担:${this.dataForm.transport || ''}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="8" class="text-left">六、包装标准:${this.dataForm.packaging || ''}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="8" class="text-left">七、结算方式:${this.dataForm.pay || ''},付款方式:${this.dataForm.payment || ''}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="8" class="text-left">八、违约责任:${this.dataForm.breach || ''}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="8" class="text-left">九、解决合同纠纷的方式:${this.dataForm.solveDispute || ''}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="8" class="text-left">十、其它约定事项:${this.dataForm.supplement || ''}</td>
|
||||
</tr>
|
||||
`
|
||||
// 创建隐藏的iframe来下载文件
|
||||
const iframe = document.createElement('iframe')
|
||||
iframe.style.display = 'none'
|
||||
iframe.src = fullUrl
|
||||
document.body.appendChild(iframe)
|
||||
|
||||
// 添加双方信息
|
||||
excelHtml += `
|
||||
<tr>
|
||||
<td colspan="4" class="text-left" style="vertical-align: top;">
|
||||
<div><strong>需方:</strong></div>
|
||||
<div>单位名称:${this.client.clientName || ''}</div>
|
||||
<div>地址:${this.client.address || ''}</div>
|
||||
<div>委托代理电话:${this.client.tel || ''}</div>
|
||||
<div>传真:${this.client.fax || ''}</div>
|
||||
<div>开户银行:${this.client.bank || ''}</div>
|
||||
<div>帐号:${this.client.card || ''}</div>
|
||||
</td>
|
||||
<td colspan="4" class="text-left" style="vertical-align: top;">
|
||||
<div><strong>供方:</strong></div>
|
||||
<div>单位名称:上海诺力智能科技有限公司(盖章)</div>
|
||||
<div>地址:上海青浦区徐泾镇高光路215弄99号4号楼302室</div>
|
||||
<div>委托代理电话:</div>
|
||||
<div>传真:</div>
|
||||
<div>开户银行:招商银行虹桥支行</div>
|
||||
<div>帐号:12191702501091</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
// 延迟移除iframe
|
||||
setTimeout(() => {
|
||||
document.body.removeChild(iframe)
|
||||
}, 3000)
|
||||
|
||||
// 创建Blob对象
|
||||
const blob = new Blob(['\ufeff', excelHtml], {
|
||||
type: 'application/vnd.ms-excel;charset=utf-8'
|
||||
})
|
||||
|
||||
// 生成文件名
|
||||
const fileName = `产品购销合同_${this.dataForm.contractCode || new Date().getTime()}.xls`
|
||||
|
||||
// 创建下载链接
|
||||
const link = document.createElement('a')
|
||||
link.href = URL.createObjectURL(blob)
|
||||
link.download = fileName
|
||||
|
||||
// 触发下载
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
|
||||
// 清理
|
||||
document.body.removeChild(link)
|
||||
URL.revokeObjectURL(link.href)
|
||||
|
||||
this.$message.success('Excel文件导出成功')
|
||||
this.$message.success('正在导出Excel文件,请稍候...')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,12 +151,26 @@
|
||||
fixed="right"
|
||||
header-align="center"
|
||||
align="center"
|
||||
width="170"
|
||||
width="220"
|
||||
label="操作">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="small" @click="addOrUpdateHandle(scope.row.ticketsId)">修改</el-button>
|
||||
<el-button type="text" size="small" @click="deleteHandle(scope.row.ticketsId)">删除</el-button>
|
||||
<el-button type="text" size="small" @click="startFlowHandle(scope.row.processInstance)">流程进度</el-button>
|
||||
<el-button
|
||||
v-if="scope.row.status === 0"
|
||||
type="text" size="small" @click="addOrUpdateHandle(scope.row.ticketsId)">修改</el-button>
|
||||
<el-button
|
||||
v-if="scope.row.status === 0"
|
||||
type="text" size="small" @click="deleteHandle(scope.row.ticketsId)">删除</el-button>
|
||||
<!-- 只有未开始状态才显示发起流程按钮 -->
|
||||
<el-button
|
||||
v-if="scope.row.status === 0"
|
||||
type="text"
|
||||
size="small"
|
||||
@click="initiateFlowHandle(scope.row.ticketsId)">
|
||||
发起流程
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="scope.row.status !== 0"
|
||||
type="text" size="small" @click="startFlowHandle(scope.row.processInstance)">流程进度</el-button>
|
||||
<el-button type="text" size="small" @click="$router.push(`/tickets-detail?id=${scope.row.ticketsId}`)">详情</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -389,6 +403,37 @@
|
||||
this.$message.error(data.msg)
|
||||
}
|
||||
})
|
||||
},
|
||||
// 发起流程
|
||||
initiateFlowHandle(ticketsId) {
|
||||
this.$confirm('确定要发起流程吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.$http({
|
||||
url: this.$http.adornUrl('/tickets/tickets/initiate'),
|
||||
method: 'get',
|
||||
params: this.$http.adornParams({
|
||||
ticketsId: ticketsId
|
||||
})
|
||||
}).then(({data}) => {
|
||||
if (data && data.code === 200) {
|
||||
this.$message({
|
||||
message: '流程发起成功',
|
||||
type: 'success',
|
||||
duration: 1500,
|
||||
onClose: () => {
|
||||
this.getDataList()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.$message.error(data.msg || '流程发起失败')
|
||||
}
|
||||
}).catch(() => {
|
||||
this.$message.error('流程发起失败,请稍后重试')
|
||||
})
|
||||
}).catch(() => {})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user