Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
Expand Down Expand Up @@ -126,6 +128,74 @@ public static class NewTips implements Serializable {
@SerializedName("tips_content")
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.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -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());
}
}
}
Original file line number Diff line number Diff line change
@@ -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());
}
});
}
}