wip: bookmark replace

This commit is contained in:
zzs 2025-03-03 14:11:52 +08:00
parent 3ce85b2874
commit 4c5c10124b
29 changed files with 589 additions and 32 deletions

View File

@ -84,6 +84,11 @@
<artifactId>spring-expression</artifactId>
<version>5.3.18</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,139 @@
package com.wmyun.farmwork.word.core;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.io.file.FileNameUtil;
import com.wmyun.farmwork.word.core.enums.BookmarkType;
import com.wmyun.farmwork.word.core.model.AbstractExData;
import com.wmyun.farmwork.word.core.model.BookmarkReplaceDataModel;
import com.wmyun.farmwork.word.core.model.ext.PictureExData;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBookmark;
import org.springframework.stereotype.Component;
import org.w3c.dom.Node;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @Description: TODO
* @Date: 2025/3/3 10:10
* @Created: by ZZSLL
*/
@Component
@Slf4j
public class BookmarkExec {
public final static String tmpDir = System.getProperty("java.io.tmpdir") + File.separator;
public static File replace(List<BookmarkReplaceDataModel> data, byte[] word, File file) {
Map<String, BookmarkReplaceDataModel> map = data.stream().collect(Collectors.toMap(BookmarkReplaceDataModel::getName, b -> b));
try (XWPFDocument doc = new XWPFDocument(IoUtil.toStream(word))) {
// 收集所有段落
// 1. 正文中的段落
List<XWPFParagraph> allParagraphs = new ArrayList<>(doc.getParagraphs());
// 2. 正文中表格内的段落
for (XWPFTable table : doc.getTables()) {
for (XWPFTableRow row : table.getRows()) {
for (XWPFTableCell cell : row.getTableCells()) {
allParagraphs.addAll(cell.getParagraphs());
}
}
}
// 3. 页眉中的段落及页眉内表格中的段落
for (XWPFHeader header : doc.getHeaderList()) {
allParagraphs.addAll(header.getParagraphs());
for (XWPFTable table : header.getTables()) {
for (XWPFTableRow row : table.getRows()) {
for (XWPFTableCell cell : row.getTableCells()) {
allParagraphs.addAll(cell.getParagraphs());
}
}
}
}
// 4. 页脚中的段落及页脚内表格中的段落
for (XWPFFooter footer : doc.getFooterList()) {
allParagraphs.addAll(footer.getParagraphs());
for (XWPFTable table : footer.getTables()) {
for (XWPFTableRow row : table.getRows()) {
for (XWPFTableCell cell : row.getTableCells()) {
allParagraphs.addAll(cell.getParagraphs());
}
}
}
}
for (XWPFParagraph paragraph : allParagraphs) {
List<CTBookmark> bookmarkStartList = paragraph.getCTP().getBookmarkStartList();
for (CTBookmark bookmark : bookmarkStartList) {
String name = bookmark.getName();
if (map.containsKey(name)) {
List<XWPFRun> runs = paragraph.getRuns();
XWPFRun run = null;
int idx = 0;
for (int i = 0; i < runs.size(); i++) {
Node previousSibling = runs.get(i).getCTR().getDomNode().getPreviousSibling();
if (previousSibling != null) {
String nodeName = previousSibling.getNodeName();
if ("w:bookmarkEnd".equals(nodeName)) {
Node bookmarkStartNode = previousSibling.getPreviousSibling();
if (bookmarkStartNode != null) {
Node nameAttribute = bookmarkStartNode.getAttributes().getNamedItem("w:name");
if (nameAttribute != null && name.equals(nameAttribute.getNodeValue())) {
idx = i - 1;
break;
}
}
}
}
}
if (idx >= 0 && idx < runs.size()) {
run = runs.get(idx);
} else {
run = paragraph.createRun();
}
BookmarkReplaceDataModel model = map.get(name);
BookmarkType type = model.getType();
if (BookmarkType.TEXT.equals(type)) {
run.setText(model.getValue());
}
if (BookmarkType.PICTURE.equals(type)) {
AbstractExData extData = model.getExtData();
if (extData instanceof PictureExData picture) {
try {
run.addPicture(new ByteArrayInputStream(picture.readAsByteArray()), XWPFDocument.PICTURE_TYPE_PNG, picture.getPictureName(), Units.toEMU(picture.getWidth()), Units.toEMU(picture.getHeight()));
} catch (InvalidFormatException e) {
log.error(e.getMessage(), e);
throw new RuntimeException(e);
}
}
}
}
}
}
File outFile = FileUtil.newFile(tmpDir + "gen/" + FileNameUtil.getName(file));
File parentDir = outFile.getParentFile();
if (!parentDir.exists()) {
parentDir.mkdirs();
}
try (FileOutputStream out = new FileOutputStream(outFile)) {
doc.write(out);
}
return outFile;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

View File

@ -0,0 +1,89 @@
package com.wmyun.farmwork.word.core;
import cn.hutool.core.io.IoUtil;
import com.wmyun.farmwork.word.core.model.BookmarkQueryDataModel;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.xmlbeans.impl.common.IOUtil;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBookmark;
import org.springframework.stereotype.Component;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* @Description: TODO
* @Date: 2025/3/3 9:47
* @Created: by ZZSLL
*/
@Component
public class BookmarkQuery {
/**
* 查询word文件中所有书签
*/
public static List<BookmarkQueryDataModel> queryAll(byte[] fileContent) {
InputStream in = new ByteArrayInputStream(fileContent);
Set<BookmarkQueryDataModel> results = new HashSet<>();
List<CTBookmark> bookmarks = new ArrayList<>();
try (XWPFDocument doc = new XWPFDocument(in)) {
for (XWPFParagraph paragraph : doc.getParagraphs()) {
bookmarks.addAll(paragraph.getCTP().getBookmarkStartList());
}
for (XWPFTable table : doc.getTables()) {
for (XWPFTableRow row : table.getRows()) {
for (XWPFTableCell cell : row.getTableCells()) {
for (XWPFParagraph para : cell.getParagraphs()) {
bookmarks.addAll(para.getCTP().getBookmarkStartList());
}
}
}
}
for (XWPFHeader header : doc.getHeaderList()) {
for (XWPFParagraph para : header.getParagraphs()) {
bookmarks.addAll(para.getCTP().getBookmarkStartList());
}
for (XWPFTable table : header.getTables()) {
for (XWPFTableRow row : table.getRows()) {
for (XWPFTableCell cell : row.getTableCells()) {
for (XWPFParagraph para : cell.getParagraphs()) {
bookmarks.addAll(para.getCTP().getBookmarkStartList());
}
}
}
}
}
for (XWPFFooter footer : doc.getFooterList()) {
for (XWPFParagraph para : footer.getParagraphs()) {
bookmarks.addAll(para.getCTP().getBookmarkStartList());
}
for (XWPFTable table : footer.getTables()) {
for (XWPFTableRow row : table.getRows()) {
for (XWPFTableCell cell : row.getTableCells()) {
for (XWPFParagraph para : cell.getParagraphs()) {
bookmarks.addAll(para.getCTP().getBookmarkStartList());
}
}
}
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
for (CTBookmark bookmark : bookmarks) {
String name = bookmark.getName();
results.add(new BookmarkQueryDataModel(name, null));
}
return new ArrayList<>(results);
}
}

View File

@ -0,0 +1,24 @@
package com.wmyun.farmwork.word.core.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @Classname BookmarkType
* @Description TODO
* @Date 2025/3/3 9:46
* @Created by violet
*/
@AllArgsConstructor
@Getter
public enum BookmarkType {
TEXT("TEXT"),
PICTURE("PICTURE");
private final String type;
}

View File

@ -0,0 +1,24 @@
package com.wmyun.farmwork.word.core.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @Classname ImageProvideType
* @Description TODO
* @Date 2025/3/3 10:59
* @Created by violet
*/
@AllArgsConstructor
@Getter
public enum PictureProvideDataType {
DOWNLOAD_URL("DOWNLOAD_URL"),
BASE64("BASE64"),
ABSOLUTE_PATH("ABSOLUTE_PATH");
private final String type;
}

View File

@ -0,0 +1,14 @@
package com.wmyun.farmwork.word.core.model;
import lombok.Data;
/**
* @Description: 扩展数据
* @Date: 2025/3/3 10:58
* @Created: by ZZSLL
*/
@Data
public class AbstractExData {
}

View File

@ -0,0 +1,22 @@
package com.wmyun.farmwork.word.core.model;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.wmyun.farmwork.word.core.enums.BookmarkType;
import lombok.AllArgsConstructor;
import lombok.Data;
/**
* @Description: 查询word文件中所有书签返回值数据结构
* @Date: 2025/3/3 9:44
* @Created: by ZZSLL
*/
@Data
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class BookmarkQueryDataModel {
private String name;
private BookmarkType type;
}

View File

@ -0,0 +1,26 @@
package com.wmyun.farmwork.word.core.model;
import com.wmyun.farmwork.word.core.enums.BookmarkType;
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.Map;
/**
* @Description: 书签替换数据类型
* @Date: 2025/3/3 10:04
* @Created: by ZZSLL
*/
@Data
@AllArgsConstructor
public class BookmarkReplaceDataModel {
private String name;
private BookmarkType type;
private String value;
private AbstractExData extData;
}

View File

@ -0,0 +1,46 @@
package com.wmyun.farmwork.word.core.model.ext;
import cn.hutool.core.io.FileUtil;
import cn.hutool.http.HttpUtil;
import com.wmyun.farmwork.word.core.enums.PictureProvideDataType;
import com.wmyun.farmwork.word.core.model.AbstractExData;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.SneakyThrows;
import java.net.URL;
import java.util.Base64;
/**
* @Description: 图片扩展数据
* @Date: 2025/3/3 10:58
* @Created: by ZZSLL
*/
@Data
@AllArgsConstructor
public class PictureExData extends AbstractExData {
private Integer width;
private Integer height;
private String pictureName;
private PictureProvideDataType dataType;
private String data;
@SneakyThrows
public byte[] readAsByteArray() {
if (PictureProvideDataType.BASE64.equals(dataType)) {
return Base64.getDecoder().decode(data);
}
if (PictureProvideDataType.DOWNLOAD_URL.equals(dataType)) {
return HttpUtil.downloadBytes(data);
}
if (PictureProvideDataType.ABSOLUTE_PATH.equals(dataType)) {
return FileUtil.readBytes(data);
}
return null;
}
}

View File

@ -0,0 +1,21 @@
package com.wmyun.farmwork.word.core.model.ext;
import com.wmyun.farmwork.word.core.model.AbstractExData;
import lombok.AllArgsConstructor;
import lombok.Data;
/**
* @Description: 文字扩展数据
* @Date: 2025/3/3 11:14
* @Created: by ZZSLL
*/
@Data
@AllArgsConstructor
public class TextExData extends AbstractExData {
private Boolean bold;
private Boolean italic;
}

View File

@ -1,8 +1,8 @@
package com.wmyun.farmwork.word.config;
package com.wmyun.farmwork.word.deprecated.config;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
import com.wmyun.farmwork.word.core.model.constant.TagType;
import com.wmyun.farmwork.word.deprecated.core.model.constant.TagType;
/**
* @Description: TODO
@ -10,6 +10,7 @@ import com.wmyun.farmwork.word.core.model.constant.TagType;
* @Created: by ZZSLL
*/
@Deprecated
public class DefaultConfig {
public static Configure def() {
return Configure.builder()

View File

@ -1,14 +1,13 @@
package com.wmyun.farmwork.word.core;
package com.wmyun.farmwork.word.deprecated.core;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.data.Pictures;
import com.deepoove.poi.data.Texts;
import com.deepoove.poi.data.style.Style;
import com.wmyun.farmwork.word.config.DefaultConfig;
import com.wmyun.farmwork.word.core.model.exec.TemplateExecDataModel;
import com.wmyun.farmwork.word.core.model.type.TypeImage;
import com.wmyun.farmwork.word.core.model.type.TypeText;
import com.wmyun.farmwork.word.deprecated.config.DefaultConfig;
import com.wmyun.farmwork.word.deprecated.core.model.exec.TemplateExecDataModel;
import com.wmyun.farmwork.word.deprecated.core.model.type.TypeImage;
import com.wmyun.farmwork.word.deprecated.core.model.type.TypeText;
import jakarta.validation.constraints.NotNull;
import org.springframework.stereotype.Component;
@ -16,7 +15,6 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
/**
@ -26,6 +24,7 @@ import java.util.Map;
*/
@Component
@Deprecated
public class TemplateReplaceExecutor {
public static String doReplace(@NotNull String absolutePath, TemplateExecDataModel data) {
return doReplace(absolutePath, data, DefaultConfig.def());

View File

@ -1,14 +1,14 @@
package com.wmyun.farmwork.word.core;
package com.wmyun.farmwork.word.deprecated.core;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.template.ElementTemplate;
import com.deepoove.poi.template.MetaTemplate;
import com.deepoove.poi.template.run.RunTemplate;
import com.wmyun.farmwork.word.config.DefaultConfig;
import com.wmyun.farmwork.word.core.model.constant.TagType;
import com.wmyun.farmwork.word.core.model.gen.TagsGenDataModel;
import com.wmyun.farmwork.word.core.utils.WPUtils;
import com.wmyun.farmwork.word.deprecated.config.DefaultConfig;
import com.wmyun.farmwork.word.deprecated.core.model.constant.TagType;
import com.wmyun.farmwork.word.deprecated.core.model.gen.TagsGenDataModel;
import com.wmyun.farmwork.word.deprecated.core.utils.WPUtils;
import jakarta.validation.constraints.NotNull;
import org.apache.poi.xwpf.usermodel.*;
@ -25,6 +25,7 @@ import java.util.regex.Pattern;
@Deprecated
public class TemplateTagsGenerate {
public static List<TagsGenDataModel> execAllTags(@NotNull String absolutePath) {

View File

@ -1,4 +1,4 @@
package com.wmyun.farmwork.word.core.model.constant;
package com.wmyun.farmwork.word.deprecated.core.model.constant;
import lombok.AllArgsConstructor;
import lombok.Getter;
@ -12,6 +12,7 @@ import lombok.Getter;
@Getter
@AllArgsConstructor
@Deprecated
public enum TagType {
TEXT("TEXT", ""),

View File

@ -1,7 +1,7 @@
package com.wmyun.farmwork.word.core.model.exec;
package com.wmyun.farmwork.word.deprecated.core.model.exec;
import com.wmyun.farmwork.word.core.model.type.TypeImage;
import com.wmyun.farmwork.word.core.model.type.TypeText;
import com.wmyun.farmwork.word.deprecated.core.model.type.TypeImage;
import com.wmyun.farmwork.word.deprecated.core.model.type.TypeText;
import lombok.*;
import java.util.List;
@ -15,6 +15,7 @@ import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Deprecated
public class TemplateExecDataModel {
private List<TypeText> text;

View File

@ -1,6 +1,6 @@
package com.wmyun.farmwork.word.core.model.gen;
package com.wmyun.farmwork.word.deprecated.core.model.gen;
import com.wmyun.farmwork.word.core.model.constant.TagType;
import com.wmyun.farmwork.word.deprecated.core.model.constant.TagType;
import lombok.*;
import java.util.List;
@ -14,6 +14,7 @@ import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Deprecated
public class TagsGenDataModel {
/**

View File

@ -1,4 +1,4 @@
package com.wmyun.farmwork.word.core.model.type;
package com.wmyun.farmwork.word.deprecated.core.model.type;
import lombok.AllArgsConstructor;
import lombok.Data;
@ -11,6 +11,7 @@ import lombok.Data;
@Data
@AllArgsConstructor
@Deprecated
public class TypeImage {
/**

View File

@ -1,4 +1,4 @@
package com.wmyun.farmwork.word.core.model.type;
package com.wmyun.farmwork.word.deprecated.core.model.type;
import lombok.AllArgsConstructor;
import lombok.Data;
@ -14,6 +14,7 @@ import java.util.Map;
@Data
@AllArgsConstructor
@Deprecated
public class TypeTable {
/**
* 标签名称

View File

@ -1,4 +1,4 @@
package com.wmyun.farmwork.word.core.model.type;
package com.wmyun.farmwork.word.deprecated.core.model.type;
import lombok.AllArgsConstructor;
import lombok.Data;
@ -11,6 +11,7 @@ import lombok.Data;
@Data
@AllArgsConstructor
@Deprecated
public class TypeText {
/**

View File

@ -1,4 +1,4 @@
package com.wmyun.farmwork.word.core.utils;
package com.wmyun.farmwork.word.deprecated.core.utils;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;

View File

@ -0,0 +1,126 @@
销售合同
Sales Contract
Договор купли-продажи
合同号Contract Договор No.
日期 Date Дата:
地点The place Место:
卖方The Seller Продавец:
Ensign Heavy Industries Co., Ltd.
Инсайн Хеви Индастриз Ко., Лтд
Add: No. 1567, Ensign Street, and Economic Development Zone,
Changle, Weifang, Shandong, China
Адрес: № 1567, Инcайн Стрит энд Экономик Девелопмент Зоун,
Чанле, Вейфань, Шаньдунь, Китай
Tel: +86-536-6295117 Fax: +86-536-6298797
Тел: +86 536 6296117, факс +86 536 6298797
Contact: Eda
Контактное лицо: Эда
Email: eda@ensignhi.com
Адрес эл.почты: eda@ensignhi.com
买方The Buyer Покупатель:
ТОО "Atameken-Energy"
Add/Адрес: КАЗАХСТАН, ТУРКЕСТАНСКАЯ обл, ТУРКЕСТАН г, ТУРКЕСТАН г, УЛИЦА А.ЮСУПОВ ул, дом 160
Contact / Контактное лицо: БОЛАТ НАГЫМЖАН
本合同由双方订立,根据本合同规定的条款,卖方同意出售,买方同意购买下列货物。
This contract is made by and between the Seller and Buyer, whereby the Seller agrees to sell and the Buyer agrees to buy the under mentioned commodity according to the terms and conditions stipulated below:
Настоящий договор заключен между Продавцом и Покупателем, согласно чему, Продавец продает, а Покупатель покупает нижеуказанный товар, в соответствии с условиями и сроками, определенными ниже:
商品名称及价格 Commodity, Quantity, Unit price and Total Value:
Товар, количество, цена за единицу, общая стоимость
Name, range, quantity, and price of Goods for every lot, as well as delivery period will be specified in
No.
п/п
PART NO.
Номер детали
PART NAME
Наименование детали
QTY
Кол-во
Unit Price
Цена за ед.
Total price
Цена итого
FCA Ensign factory in CNY{{&table}}
[index]
[m_code]
[m_name]
[m_qty]
[m_unit_price]
[m_amount]
TOTAL QUANTITY: {{total_qty}}
212Pcs
TOTAL AMOUNT: {{total_amount}}
CNY10000
SAY TOTAL:CHINESE YUAN TENTHOUSAND ONLY.
包装Packing Упаковка: 装于箱内Packed in boxes Упаковано в коробки
装运期Time of Shipment Время отгрузки: 2025年3月Before in March. 2025,
装运港Port of Loading Пункт отгрузки: 中国 英轩工厂 Port,ChinaФабрика ENSIGN, Китай
目的港Port of Destination Пункт назначения: 哈萨克斯坦,突厥斯坦 Turkestan Port, KazakhstanРусский Тур
付款方式Payment Условия оплаты:
Free given spare parts along with the purchasing machines.
Бесплатно предоставляем запасные части вместе с приобретаемой техникой.
合同有效期Expiry Date of the Contract Срок действия договора/срок возврата аванса:
2025年5月30日 May 30th, 2025
货物所有权转移Transfer of the goods ownership Передача товара в собственность:
买方付清全部货款后,货物所有权转移给买方;如果买方没有付清全部货款,卖方保留对货物的全部所有权。
The ownership of the goods shall be transferred to the buyer after the buyer pays back the total contract value. The seller retains the full ownership of the goods if the buyer doesn't pay back the total contract value.
Передача товара в собственность Покупателю произойдет после полной оплаты Покупателем стоимости договора. Право собственности на товар сохраняется за Продавцом в случае, если Покупатель не выплачивает полную стоимость договора.
9.不可抗力Force Majeure Форс-мажор:
卖方由于罢工、火灾、地震、暴动、爆炸、政府行为等不可抗力事故,未能在合同规定期限内装货或不能交货,则不承担责任,卖方应立即以传真通知买方,如果买方提出要求,卖方应以挂号函件向买方提供由中国国际贸易促进委员会或有关机构出具的证明,证明上述事由的存在。
The Seller shall not be held responsible if they, owing to force majeure cause, such as Act of God, strike, riot, civil commotion, breakdown of machinery, fire or any other causes beyond Seller's control, fail to make delivery within the time stipulated in the Contract or cannot deliver the goods. However in such cases, the Seller shall inform the Buyer immediately by fax and if it is requested by the Buyer, shall also deliver to the Buyer by registered letter, a certificate attesting the existence of such a cause issued by the China Council for the Promotion of International Trade or by a competent authority.
Продавец не несет ответственности за события, происходящие вследствие форс-мажора, если таковые происходят: стихийные бедствия, забастовки, мятежи, гражданские волнения, выход из строя оборудования, пожар или другие события, выходящие за рамки контроля Продавца, и приведшие к нарушению сроков поставок в периоды, оговоренные Договором, либо к невозможности поставки Товара. Однако, о всех таких случаях Продавец незамедлительно информирует Покупателя по факсу и, если это требуется Покупателю, официальным письмом, справкой, подтверждающей наступление таких событий, заверенной китайским консулом по международной торговле или другим компетентным органом.
10.异议和索赔Discrepancy and Claim Несоответствия и претензии:
1外观质量和数量等可目视检查的不符或缺失买方需在货物到达目的港后10个工作日内提报卖方产品潜在缺陷买方需在货物到港后30个工作日内凭卖方认可的权威机构出具的检测报告提报卖方未经卖方同意买方不得销售或使用该类产品。
(1) The visual survey of any discrepancy or deficiency such as apparent quality and quantity should be reported to the seller within 10 working days from the date of goods arrival at the destination port, while for the latent defects of goods, an Inspection Report issued by an approved authority institution by the Seller should be sent to the Seller within 30 working days from the date of goods arrival at the destination port. The defective goods which have not been approved by the Seller should not be sold or used.
(1) Выявленные при визуальном осмотре несоответствия и дефекты, как в качестве, так и в количестве, должны быть предоставлены в форме отчета Продавцу в течение 10 рабочих дней в даты поступления товара в пункт назначения, в то время отчет по скрытым дефектам товара, выданный уполномоченным государством учреждением, должен быть отправлен Продавцу по электронной почте в течение 30 дней с даты поступления товара в пункт назначения. Оборудование с дефектами не может быть продано или использовано без разрешения Продавца.
(2) 卖方向买方提供制造商提供的所有质保。装载机质保期为提单日起24个月经销商销售日起18个月装载机开始运行起2000个工作小时以先到者为准
(2)The Seller provides the Buyer all the warranties provided by the factory-manufacturer. Wheel loader warranty period is 24 months since date of B/L, 18 months since date of sale by the dealer, 2000 working hours since the loader starts to be operatedsubject to whichever comes first.
(2) Продавец обеспечивает Покупателю все гарантии, предоставленные заводом-производителем. Гарантийный период составляет 24 месяца с даты получения предоплаты, 18 месяцев с даты продажи дилером, 2000 мото/часов с момента запуска в работу, в зависимости от того, что наступает раньше.
11.仲裁Arbitration Арбитраж:
凡因执行本合同和有关本合同所发生的一切争执,双方应协商解决,如果协商不能解决,应提交位于北京的中国国际经济贸易仲裁委员会,根据其仲裁规则进行仲裁,仲裁裁决是终局的,对双方均有约束力,除非另有规定外,仲裁费用均由败诉方负担。本合同适用中国法律。
All disputes arising from the execution of, or in connection with this Contract, shall be settled through negotiation. In case no settlement can be reached through negotiation, the case shall then be submitted to the China International Economic and Trade Arbitration Commission, Beijing, for arbitration in accordance with the Commission's Rules of Procedure. The award rendered by the Commission shall be final and binding on bothparties. The fees for arbitration shall be borne by the losing party unless otherwise awarded. This contract issigned as to Chinese laws.
Все споры, возникающие при исполнении или в связи с настоящим Контрактом, должны решаться путемпереговоров. В случае невозможности урегулирования спора путем переговоров, дело передается вКитайскую международную экономическую и торговую арбитражную комиссию, Пекин, для арбитража всоответствии с Правилами процедуры Комиссии. Решение, вынесенное Комиссией, являетсяокончательным и обязательным для обеих сторон. Арбитражные сборы несет проигравшая сторона, если не принято иное решение. Настоящий договор подписан в соответствии с законодательством Китая.
12本合同采用中英俄文书写经双方签字后生效传真件或扫描副本有效,如若中英俄文有歧义,则以中文为准。双方对本合同所有内容有保密义务,不得以任何形式泄露给第三方。任何一方在未取得对方书面同意前,无权将本合同规定之权利义务转让给第三方。本合同所有附件属于合同的组成部分,与本合同具有同等法律效力。
This appendix is made in Chinese English and Russian becomes effective as soon as it is signed by both parties. Fax copies and scanned originals of the docs hold the same force. And if any dispute or miscellaneous on language here determinate that Chinese version is predominate authentic. Both parties shall be responsible to keep all the information under this contract confident and cannot reveal to any third party in any manner. Neither party is entitled to transfer its right and obligation under this Contract to a third party before obtaining a written consent from the other party. All appendixes to the Contract shall form an integral part of the Contract and have the same effectiveness as the contract。
Настоящее приложение составлено на китайском английском и русском языках и вступает в силу с момента его подписания обеими сторонами. Факсимильные копии и сканы оригиналов документов имеют такую же силу. И если возникнет спор или разногласие по поводу языка, здесь определяется, что китайская версия является преобладающей аутентичной. Обе стороны несут ответственность за сохранение всей информации по настоящему договору в тайне и не могут раскрывать ее третьим лицам каким-либо образом. Ни одна из сторон не имеет права передавать свои права и обязательства по настоящему Контракту третьей стороне до получения письменного согласия другой стороны. Все приложения к контракту являются его неотъемлемой частью и имеют такую же силу, как и контракт.
13、卖方银行信息 The Seller's Bank Information Банковские реквизиты
本合同项下款项必须付到以下银行账户:
Payments under this contract must be paid to the following bank account:
Платежи по настоящему договору производятся по следующим банковским реквизитам:
Beneficiary Получатель: ENSIGN HEAVY INDUSTRIES CO., LTD.
Address Адрес: No.1567, Ensign Street, Economic Development Zone, Changle, Weifang, Shandong, China.
Tel: +86-536-6298882 Fax:+86-536-6298797
Bank Name Наименование банка : CHINA ZHESHANG BANK Китайский Zhe Shang Bank
Bank Address Адрес банка: NO.288 Qingchun Road,Hangzhou City,Zhejiang Province,China
№ 288 Цинчунь, город Ханчжоу, провинция Чжэцзян, Китай
Swift Code: ZJCBCN2N
Account Number: 4580000010120100081585
以上任何银行信息的变更,以卖方传真通知为准。
Any changes of the above bank information shall be subject to the seller's fax notice only.
Все изменения банковских реквизитов допускаются только при условии направления Продавцом уведомления по факсу.
卖方 买方
The Seller The Buyer
Продавец: ________________ Покупатель : ______
供方盖章

View File

@ -0,0 +1,38 @@
package com.wmyun.module.infra.controller.admin.word;
import com.wmyun.farmwork.word.core.model.BookmarkQueryDataModel;
import com.wmyun.farmwork.word.core.model.BookmarkReplaceDataModel;
import com.wmyun.farmwork.word.deprecated.core.model.gen.TagsGenDataModel;
import com.wmyun.framework.common.pojo.CommonResult;
import com.wmyun.module.infra.service.file.WordBookmarkService;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Set;
/**
* @Description: TODO
* @Date: 2025/3/3 9:36
* @Created: by ZZSLL
*/
@Tag(name = "管理后台 - Word bookmark替换")
@RestController
@RequestMapping("/infra/word/bookmark")
public class WordBookmarkController {
@Autowired
private WordBookmarkService service;
@PostMapping("/file/{fileId}")
public CommonResult<Set<String>> requestAllBookmarks(@PathVariable("fileId") String fileId) {
return CommonResult.success(service.queryAllBookmarks(fileId));
}
@PostMapping("/file/{fileId}/generate")
public CommonResult<Object> doGenerate(@PathVariable("fileId") String fileId, @RequestBody List<BookmarkReplaceDataModel> data) {
return CommonResult.success(service.replaceBookmarkWithContent(fileId, data));
}
}

View File

@ -1,7 +1,7 @@
package com.wmyun.module.infra.controller.admin.word;
import com.wmyun.farmwork.word.core.model.exec.TemplateExecDataModel;
import com.wmyun.farmwork.word.core.model.gen.TagsGenDataModel;
import com.wmyun.farmwork.word.deprecated.core.model.exec.TemplateExecDataModel;
import com.wmyun.farmwork.word.deprecated.core.model.gen.TagsGenDataModel;
import com.wmyun.framework.common.pojo.CommonResult;
import com.wmyun.module.infra.service.file.WordTemplateTagService;
import io.swagger.v3.oas.annotations.tags.Tag;

View File

@ -31,6 +31,8 @@ public interface FileService {
*/
String createFile(String name, String path, byte[] content);
FileDO createFileDO(String name, String path, byte[] content);
/**
* 创建文件
*

View File

@ -69,6 +69,36 @@ public class FileServiceImpl implements FileService {
return url;
}
@Override
@SneakyThrows
public FileDO createFileDO(String name, String path, byte[] content) {
// 计算默认的 path
String type = FileTypeUtils.getMineType(content, name);
if (StrUtil.isEmpty(path)) {
path = FileUtils.generatePath(content, name);
}
// 如果 name 为空则使用 path 填充
if (StrUtil.isEmpty(name)) {
name = path;
}
// 上传到文件存储器
FileClient client = fileConfigService.getMasterFileClient();
Assert.notNull(client, "客户端(master) 不能为空");
String url = client.upload(content, path, type);
// 保存到数据库
FileDO file = new FileDO();
file.setConfigId(client.getId());
file.setName(name);
file.setPath(path);
file.setUrl(url);
file.setType(type);
file.setSize(content.length);
fileMapper.insert(file);
return file;
}
@Override
public Long createFile(FileCreateReqVO createReqVO) {
FileDO file = BeanUtils.toBean(createReqVO, FileDO.class);

View File

@ -0,0 +1,20 @@
package com.wmyun.module.infra.service.file;
import com.wmyun.farmwork.word.core.model.BookmarkReplaceDataModel;
import java.util.List;
import java.util.Set;
/**
* @Classname WordBookmarkService
* @Description TODO
* @Date 2025/3/3 9:38
* @Created by violet
*/
public interface WordBookmarkService {
Set<String> queryAllBookmarks(String fileId);
Long replaceBookmarkWithContent(String fileId, List<BookmarkReplaceDataModel> data);
}

View File

@ -0,0 +1,50 @@
package com.wmyun.module.infra.service.file;
import cn.hutool.core.io.FileUtil;
import com.wmyun.farmwork.word.core.BookmarkExec;
import com.wmyun.farmwork.word.core.BookmarkQuery;
import com.wmyun.farmwork.word.core.model.BookmarkQueryDataModel;
import com.wmyun.farmwork.word.core.model.BookmarkReplaceDataModel;
import com.wmyun.module.infra.dal.dataobject.file.FileDO;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.File;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* @Description: TODO
* @Date: 2025/3/3 9:38
* @Created: by ZZSLL
*/
@Service
public class WordBookmarkServiceImpl implements WordBookmarkService {
@Autowired
private FileService fileService;
@Autowired
private FilePreviewService previewService;
@SneakyThrows
@Override
public Set<String> queryAllBookmarks(String fileId) {
FileDO fileDO = previewService.queryFileInfoByFileId(fileId);
return BookmarkQuery.queryAll(fileService.getFileContent(fileDO.getConfigId(), fileDO.getPath())).stream().map(BookmarkQueryDataModel::getName).collect(Collectors.toSet());
}
@SneakyThrows
@Override
public Long replaceBookmarkWithContent(String fileId, List<BookmarkReplaceDataModel> data) {
FileDO fileDO = previewService.queryFileInfoByFileId(fileId);
byte[] content = fileService.getFileContent(fileDO.getConfigId(), fileDO.getPath());
File file = FileUtil.newFile(BookmarkExec.tmpDir + fileDO.getName());
FileUtil.writeBytes(content, file);
File outputFile = BookmarkExec.replace(data, content, file);
return fileService.createFileDO(outputFile.getName(), outputFile.getAbsolutePath(), FileUtil.readBytes(outputFile)).getId();
}
}

View File

@ -1,7 +1,7 @@
package com.wmyun.module.infra.service.file;
import com.wmyun.farmwork.word.core.model.exec.TemplateExecDataModel;
import com.wmyun.farmwork.word.core.model.gen.TagsGenDataModel;
import com.wmyun.farmwork.word.deprecated.core.model.exec.TemplateExecDataModel;
import com.wmyun.farmwork.word.deprecated.core.model.gen.TagsGenDataModel;
import java.util.List;

View File

@ -1,9 +1,9 @@
package com.wmyun.module.infra.service.file;
import com.wmyun.farmwork.word.core.TemplateReplaceExecutor;
import com.wmyun.farmwork.word.core.TemplateTagsGenerate;
import com.wmyun.farmwork.word.core.model.exec.TemplateExecDataModel;
import com.wmyun.farmwork.word.core.model.gen.TagsGenDataModel;
import com.wmyun.farmwork.word.deprecated.core.TemplateReplaceExecutor;
import com.wmyun.farmwork.word.deprecated.core.TemplateTagsGenerate;
import com.wmyun.farmwork.word.deprecated.core.model.exec.TemplateExecDataModel;
import com.wmyun.farmwork.word.deprecated.core.model.gen.TagsGenDataModel;
import com.wmyun.module.infra.dal.dataobject.file.FileDO;
import com.wmyun.module.infra.framework.file.core.client.FileClient;
import org.springframework.beans.factory.annotation.Autowired;