Compare commits
4 Commits
copilot/fi
...
1d08953fce
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1d08953fce | ||
|
|
968a4a453f | ||
|
|
028074cf5b | ||
|
|
087c85c738 |
@@ -6,6 +6,8 @@ import lombok.experimental.Accessors;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -126,6 +128,74 @@ public class ContentValue implements Serializable {
|
|||||||
@SerializedName("tips_content")
|
@SerializedName("tips_content")
|
||||||
private List<TipsContent> tipsContent;
|
private List<TipsContent> tipsContent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a simple Tips control with mixed plain text and clickable links.
|
||||||
|
*
|
||||||
|
* @param lang the language code (e.g., "zh_CN")
|
||||||
|
* @param textAndLinks array of objects where strings become plain text and Link objects become clickable links
|
||||||
|
* @return NewTips instance with the specified content
|
||||||
|
*/
|
||||||
|
public static NewTips of(String lang, Object... textAndLinks) {
|
||||||
|
NewTips tips = new NewTips();
|
||||||
|
TipsContent content = new TipsContent();
|
||||||
|
TipsContent.Text text = new TipsContent.Text();
|
||||||
|
|
||||||
|
List<TipsContent.SubText> subTexts = new ArrayList<>();
|
||||||
|
|
||||||
|
for (Object item : textAndLinks) {
|
||||||
|
TipsContent.SubText subText = new TipsContent.SubText();
|
||||||
|
TipsContent.SubText.Content subContent = new TipsContent.SubText.Content();
|
||||||
|
|
||||||
|
if (item instanceof String) {
|
||||||
|
// Plain text
|
||||||
|
TipsContent.SubText.Content.PlainText plainText = new TipsContent.SubText.Content.PlainText();
|
||||||
|
plainText.setContent((String) item);
|
||||||
|
subContent.setPlainText(plainText);
|
||||||
|
subText.setType(1);
|
||||||
|
} else if (item instanceof TipsContent.SubText.Content.Link) {
|
||||||
|
// Link
|
||||||
|
subContent.setLink((TipsContent.SubText.Content.Link) item);
|
||||||
|
subText.setType(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
subText.setContent(subContent);
|
||||||
|
subTexts.add(subText);
|
||||||
|
}
|
||||||
|
|
||||||
|
text.setSubText(subTexts);
|
||||||
|
content.setText(text);
|
||||||
|
content.setLang(lang);
|
||||||
|
tips.setTipsContent(Arrays.asList(content));
|
||||||
|
|
||||||
|
return tips;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a simple Tips control with only plain text.
|
||||||
|
*
|
||||||
|
* @param lang the language code (e.g., "zh_CN")
|
||||||
|
* @param textContent the plain text content
|
||||||
|
* @return NewTips instance with plain text content
|
||||||
|
*/
|
||||||
|
public static NewTips ofText(String lang, String textContent) {
|
||||||
|
return of(lang, textContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a Tips control with a single clickable link.
|
||||||
|
*
|
||||||
|
* @param lang the language code (e.g., "zh_CN")
|
||||||
|
* @param linkTitle the display text for the link
|
||||||
|
* @param linkUrl the URL to link to
|
||||||
|
* @return NewTips instance with a single clickable link
|
||||||
|
*/
|
||||||
|
public static NewTips ofLink(String lang, String linkTitle, String linkUrl) {
|
||||||
|
TipsContent.SubText.Content.Link link = new TipsContent.SubText.Content.Link();
|
||||||
|
link.setTitle(linkTitle);
|
||||||
|
link.setUrl(linkUrl);
|
||||||
|
return of(lang, link);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type tips_content.
|
* The type tips_content.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -0,0 +1,124 @@
|
|||||||
|
package me.chanjar.weixin.cp.bean.oa.applydata;
|
||||||
|
|
||||||
|
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import static org.testng.Assert.*;
|
||||||
|
|
||||||
|
public class ContentValueTipsTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTipsWithLinksManualCreation() {
|
||||||
|
System.out.println("Testing ContentValue.NewTips structure with Link (manual creation):");
|
||||||
|
|
||||||
|
// Create a Tips structure with both plain text and link
|
||||||
|
ContentValue.NewTips tips = new ContentValue.NewTips();
|
||||||
|
ContentValue.NewTips.TipsContent tipsContent = new ContentValue.NewTips.TipsContent();
|
||||||
|
ContentValue.NewTips.TipsContent.Text text = new ContentValue.NewTips.TipsContent.Text();
|
||||||
|
|
||||||
|
// Create plain text subtext
|
||||||
|
ContentValue.NewTips.TipsContent.SubText plainSubText = new ContentValue.NewTips.TipsContent.SubText();
|
||||||
|
ContentValue.NewTips.TipsContent.SubText.Content plainContent = new ContentValue.NewTips.TipsContent.SubText.Content();
|
||||||
|
ContentValue.NewTips.TipsContent.SubText.Content.PlainText plainTextContent =
|
||||||
|
new ContentValue.NewTips.TipsContent.SubText.Content.PlainText();
|
||||||
|
plainTextContent.setContent("This is plain text. For more info, ");
|
||||||
|
plainContent.setPlainText(plainTextContent);
|
||||||
|
plainSubText.setType(1); // Type 1 for plain text
|
||||||
|
plainSubText.setContent(plainContent);
|
||||||
|
|
||||||
|
// Create link subtext
|
||||||
|
ContentValue.NewTips.TipsContent.SubText linkSubText = new ContentValue.NewTips.TipsContent.SubText();
|
||||||
|
ContentValue.NewTips.TipsContent.SubText.Content linkContent = new ContentValue.NewTips.TipsContent.SubText.Content();
|
||||||
|
ContentValue.NewTips.TipsContent.SubText.Content.Link link =
|
||||||
|
new ContentValue.NewTips.TipsContent.SubText.Content.Link();
|
||||||
|
link.setTitle("click here");
|
||||||
|
link.setUrl("https://work.weixin.qq.com");
|
||||||
|
linkContent.setLink(link);
|
||||||
|
linkSubText.setType(2); // Type 2 for link
|
||||||
|
linkSubText.setContent(linkContent);
|
||||||
|
|
||||||
|
text.setSubText(Arrays.asList(plainSubText, linkSubText));
|
||||||
|
tipsContent.setText(text);
|
||||||
|
tipsContent.setLang("zh_CN");
|
||||||
|
|
||||||
|
tips.setTipsContent(Arrays.asList(tipsContent));
|
||||||
|
|
||||||
|
// Convert to JSON
|
||||||
|
String json = WxCpGsonBuilder.create().toJson(tips);
|
||||||
|
System.out.println("Generated JSON:");
|
||||||
|
System.out.println(json);
|
||||||
|
|
||||||
|
// Try to parse it back
|
||||||
|
validateTipsStructure(tips, json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTipsWithConvenienceMethods() {
|
||||||
|
System.out.println("Testing ContentValue.NewTips with convenience methods:");
|
||||||
|
|
||||||
|
// Test 1: Simple plain text
|
||||||
|
ContentValue.NewTips textOnly = ContentValue.NewTips.ofText("zh_CN", "This is a simple text tip.");
|
||||||
|
String textJson = WxCpGsonBuilder.create().toJson(textOnly);
|
||||||
|
System.out.println("Text-only JSON: " + textJson);
|
||||||
|
validateTipsStructure(textOnly, textJson);
|
||||||
|
|
||||||
|
// Test 2: Single link
|
||||||
|
ContentValue.NewTips linkOnly = ContentValue.NewTips.ofLink("zh_CN", "Visit WeChat Work", "https://work.weixin.qq.com");
|
||||||
|
String linkJson = WxCpGsonBuilder.create().toJson(linkOnly);
|
||||||
|
System.out.println("Link-only JSON: " + linkJson);
|
||||||
|
validateTipsStructure(linkOnly, linkJson);
|
||||||
|
|
||||||
|
// Test 3: Mixed content using convenience method
|
||||||
|
ContentValue.NewTips.TipsContent.SubText.Content.Link link =
|
||||||
|
new ContentValue.NewTips.TipsContent.SubText.Content.Link();
|
||||||
|
link.setTitle("click here");
|
||||||
|
link.setUrl("https://work.weixin.qq.com");
|
||||||
|
|
||||||
|
ContentValue.NewTips mixed = ContentValue.NewTips.of("zh_CN",
|
||||||
|
"For more information, ", link, " or contact support.");
|
||||||
|
String mixedJson = WxCpGsonBuilder.create().toJson(mixed);
|
||||||
|
System.out.println("Mixed content JSON: " + mixedJson);
|
||||||
|
validateTipsStructure(mixed, mixedJson);
|
||||||
|
|
||||||
|
System.out.println("All convenience method tests passed!");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateTipsStructure(ContentValue.NewTips tips, String json) {
|
||||||
|
try {
|
||||||
|
ContentValue.NewTips parsedTips = WxCpGsonBuilder.create().fromJson(json, ContentValue.NewTips.class);
|
||||||
|
assertNotNull(parsedTips);
|
||||||
|
assertNotNull(parsedTips.getTipsContent());
|
||||||
|
assertFalse(parsedTips.getTipsContent().isEmpty());
|
||||||
|
|
||||||
|
ContentValue.NewTips.TipsContent.Text parsedText = parsedTips.getTipsContent().get(0).getText();
|
||||||
|
assertNotNull(parsedText);
|
||||||
|
assertNotNull(parsedText.getSubText());
|
||||||
|
assertTrue(parsedText.getSubText().size() > 0);
|
||||||
|
|
||||||
|
// Verify structure based on content
|
||||||
|
for (ContentValue.NewTips.TipsContent.SubText subText : parsedText.getSubText()) {
|
||||||
|
assertNotNull(subText.getType());
|
||||||
|
assertNotNull(subText.getContent());
|
||||||
|
|
||||||
|
if (subText.getType() == 1) {
|
||||||
|
// Plain text
|
||||||
|
assertNotNull(subText.getContent().getPlainText());
|
||||||
|
assertNotNull(subText.getContent().getPlainText().getContent());
|
||||||
|
} else if (subText.getType() == 2) {
|
||||||
|
// Link
|
||||||
|
assertNotNull(subText.getContent().getLink());
|
||||||
|
assertNotNull(subText.getContent().getLink().getTitle());
|
||||||
|
assertNotNull(subText.getContent().getLink().getUrl());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("✓ JSON parsing and validation successful");
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("✗ Error parsing: " + e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
fail("Failed to parse JSON: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
package me.chanjar.weixin.cp.bean.oa.applydata;
|
||||||
|
|
||||||
|
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Usage examples for ContentValue.NewTips with clickable link support.
|
||||||
|
*
|
||||||
|
* This example demonstrates how to create Tips controls that can render URLs as clickable links,
|
||||||
|
* addressing the issue where "Tips控件无法将url渲染为可点击的链接".
|
||||||
|
*
|
||||||
|
* @author WxJava Community
|
||||||
|
*/
|
||||||
|
public class TipsUsageExample {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
demonstrateBasicUsage();
|
||||||
|
demonstrateAdvancedUsage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basic usage examples for creating Tips with clickable links.
|
||||||
|
*/
|
||||||
|
public static void demonstrateBasicUsage() {
|
||||||
|
System.out.println("=== Basic Tips Usage Examples ===\n");
|
||||||
|
|
||||||
|
// Example 1: Simple plain text tip
|
||||||
|
ContentValue.NewTips textTip = ContentValue.NewTips.ofText("zh_CN",
|
||||||
|
"这是一个简单的文本提示。");
|
||||||
|
System.out.println("1. Plain text tip JSON:");
|
||||||
|
System.out.println(WxCpGsonBuilder.create().toJson(textTip));
|
||||||
|
System.out.println();
|
||||||
|
|
||||||
|
// Example 2: Simple clickable link tip
|
||||||
|
ContentValue.NewTips linkTip = ContentValue.NewTips.ofLink("zh_CN",
|
||||||
|
"访问企业微信官网", "https://work.weixin.qq.com");
|
||||||
|
System.out.println("2. Single link tip JSON:");
|
||||||
|
System.out.println(WxCpGsonBuilder.create().toJson(linkTip));
|
||||||
|
System.out.println();
|
||||||
|
|
||||||
|
// Example 3: Mixed content - text with clickable link
|
||||||
|
ContentValue.NewTips.TipsContent.SubText.Content.Link helpLink =
|
||||||
|
new ContentValue.NewTips.TipsContent.SubText.Content.Link();
|
||||||
|
helpLink.setTitle("点击查看详情");
|
||||||
|
helpLink.setUrl("https://work.weixin.qq.com/help");
|
||||||
|
|
||||||
|
ContentValue.NewTips mixedTip = ContentValue.NewTips.of("zh_CN",
|
||||||
|
"如需了解更多信息,请", helpLink, "。");
|
||||||
|
System.out.println("3. Mixed content tip JSON:");
|
||||||
|
System.out.println(WxCpGsonBuilder.create().toJson(mixedTip));
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Advanced usage examples showing complex Tips with multiple links and text.
|
||||||
|
*/
|
||||||
|
public static void demonstrateAdvancedUsage() {
|
||||||
|
System.out.println("=== Advanced Tips Usage Examples ===\n");
|
||||||
|
|
||||||
|
// Example 4: Complex tip with multiple links
|
||||||
|
ContentValue.NewTips.TipsContent.SubText.Content.Link docsLink =
|
||||||
|
new ContentValue.NewTips.TipsContent.SubText.Content.Link();
|
||||||
|
docsLink.setTitle("开发文档");
|
||||||
|
docsLink.setUrl("https://developer.work.weixin.qq.com");
|
||||||
|
|
||||||
|
ContentValue.NewTips.TipsContent.SubText.Content.Link supportLink =
|
||||||
|
new ContentValue.NewTips.TipsContent.SubText.Content.Link();
|
||||||
|
supportLink.setTitle("技术支持");
|
||||||
|
supportLink.setUrl("https://work.weixin.qq.com/contact");
|
||||||
|
|
||||||
|
ContentValue.NewTips complexTip = ContentValue.NewTips.of("zh_CN",
|
||||||
|
"审批流程说明:\n1. 提交申请后系统将自动处理\n2. 如有疑问请查看",
|
||||||
|
docsLink,
|
||||||
|
"或联系",
|
||||||
|
supportLink);
|
||||||
|
System.out.println("4. Complex tip with multiple links JSON:");
|
||||||
|
System.out.println(WxCpGsonBuilder.create().toJson(complexTip));
|
||||||
|
System.out.println();
|
||||||
|
|
||||||
|
// Demonstrate that the structure supports proper type differentiation
|
||||||
|
System.out.println("=== Type Verification ===");
|
||||||
|
ContentValue.NewTips parsed = WxCpGsonBuilder.create().fromJson(
|
||||||
|
WxCpGsonBuilder.create().toJson(complexTip), ContentValue.NewTips.class);
|
||||||
|
|
||||||
|
parsed.getTipsContent().get(0).getText().getSubText().forEach(subText -> {
|
||||||
|
if (subText.getType() == 1) {
|
||||||
|
System.out.println("Plain text: \"" + subText.getContent().getPlainText().getContent() + "\"");
|
||||||
|
} else if (subText.getType() == 2) {
|
||||||
|
System.out.println("Link: \"" + subText.getContent().getLink().getTitle() +
|
||||||
|
"\" -> " + subText.getContent().getLink().getUrl());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user