藏头诗应用是一个基于 Cordova 框架开发的移动应用,通过调用第三方 API 实现智能诗词生成功能。用户只需输入关键字,即可生成包含藏头、藏尾、藏中等不同形式的优美诗词。
https://v3.alapi.cn/api/ai/poem
image-20251121150718671
创建 poem.html 文件,包含:
使用 CSS3 实现:
创建 poem.js 文件,实现:
更新 Content Security Policy (CSP),允许:
<form id="poem-form">
<div class="form-group">
<label for="token" class="label-with-help">
<span>API Token *</span>
<button type="button" class="help-btn" onclick="openTokenModal()">获取 Token</button>
</label>
<div class="token-input-wrapper">
<input type="text" id="token" name="token" placeholder="请输入API Token" required>
</div>
</div>
<div class="form-group">
<label for="keyword">关键字 *</label>
<input type="text" id="keyword" name="keyword"
placeholder="请输入2-8个字的藏字内容,如:我喜欢你"
required maxlength="8" minlength="2">
</div>
<div class="form-row">
<div class="form-group">
<label for="num">诗句格式</label>
<select id="num" name="num">
<option value="5">五言诗</option>
<option value="7">七言诗</option>
</select>
</div>
<div class="form-group">
<label for="type">藏头位置</label>
<select id="type" name="type">
<option value="1">藏头</option>
<option value="2">藏尾</option>
<option value="3">藏中</option>
<option value="4">递增</option>
<option value="5">递减</option>
</select>
</div>
<div class="form-group">
<label for="rhyme">押韵类型</label>
<select id="rhyme" name="rhyme">
<option value="1">双句一压</option>
<option value="2">双句押韵</option>
<option value="3">一三四押</option>
</select>
</div>
</div>
<button type="submit" class="submit-btn" id="submit-btn">生成藏头诗</button>
</form>
<div class="modal-overlay" id="token-modal" onclick="closeTokenModal(event)">
<div class="modal-content" onclick="event.stopPropagation()">
<div class="modal-header">
<h2>获取 API Token</h2>
<button class="modal-close" onclick="closeTokenModal()">×</button>
</div>
<div class="modal-body">
<p style="margin-bottom: 15px; color: #666;">
请在下方页面注册并获取您的 API Token,然后将 Token 复制到输入框中。
</p>
<iframe src="https://www.alapi.cn/aff/nutpi" id="token-iframe"></iframe>
</div>
<div class="modal-footer">
<p style="margin: 0; color: #666;">
如果页面无法加载,请
<a href="https://www.alapi.cn/aff/nutpi" target="_blank">点击这里在新窗口打开</a>
</p>
</div>
</div>
</div>
.form-container {
background-color: #f8f9fa;
padding: 25px;
border-radius: 8px;
margin-bottom: 30px;
box-shadow: 02px8pxrgba(0,0,0,0.1);
}
.form-group {
margin-bottom: 20px;
}
.form-groupinput,
.form-groupselect {
width: 100%;
padding: 12px;
border: 1px solid #ddd;
border-radius: 6px;
font-size: 16px;
box-sizing: border-box;
transition: border-color 0.3s;
}
.form-groupinput:focus,
.form-groupselect:focus {
outline: none;
border-color: #3498db;
box-shadow: 0003pxrgba(52, 152, 219, 0.1);
}
.form-row {
display: flex;
gap: 15px;
}
@media (max-width:768px) {
.form-row {
flex-direction: column;
}
}
.modal-overlay {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
z-index: 1000;
justify-content: center;
align-items: center;
}
.modal-overlay.show {
display: flex;
}
.modal-content {
background-color: white;
border-radius: 8px;
width: 90%;
max-width: 600px;
max-height: 80vh;
overflow: hidden;
box-shadow: 04px20pxrgba(0, 0, 0, 0.3);
display: flex;
flex-direction: column;
}
// 表单提交处理
document.getElementById('poem-form').addEventListener('submit', function(e) {
e.preventDefault();
generatePoem();
});
function generatePoem() {
const form = document.getElementById('poem-form');
const submitBtn = document.getElementById('submit-btn');
const loading = document.getElementById('loading');
const errorMessage = document.getElementById('error-message');
const resultContainer = document.getElementById('result-container');
// 获取表单数据
const formData = {
token: document.getElementById('token').value.trim(),
keyword: document.getElementById('keyword').value.trim(),
num: document.getElementById('num').value,
type: document.getElementById('type').value,
rhyme: document.getElementById('rhyme').value
};
// 验证关键字长度
if (formData.keyword.length < 2 || formData.keyword.length > 8) {
showError('关键字长度必须在2-8个字之间');
return;
}
// 验证token
if (!formData.token) {
showError('请输入API Token');
return;
}
// 显示加载状态
submitBtn.disabled = true;
submitBtn.textContent = '生成中...';
loading.classList.add('show');
errorMessage.classList.remove('show');
resultContainer.classList.remove('show');
// 构建请求参数
const params = new URLSearchParams();
params.append('token', formData.token);
params.append('keyword', formData.keyword);
params.append('num', formData.num);
params.append('type', formData.type);
params.append('rhyme', formData.rhyme);
// 发送POST请求
fetch('https://v3.alapi.cn/api/ai/poem', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: params.toString()
})
.then(response => {
if (!response.ok) {
thrownewError('网络请求失败: ' + response.status);
}
return response.json();
})
.then(data => {
console.log('API响应:', data);
if (data.success && data.code === 200) {
displayPoem(data.data);
} else {
showError(data.message || '生成失败,请检查参数');
}
})
.catch(error => {
console.error('请求错误:', error);
showError('请求失败: ' + error.message + '。请检查网络连接或API Token是否正确');
})
.finally(() => {
// 恢复按钮状态
submitBtn.disabled = false;
submitBtn.textContent = '生成藏头诗';
loading.classList.remove('show');
});
}
function displayPoem(data) {
const resultContainer = document.getElementById('result-container');
const poemText = document.getElementById('poem-text');
const poemList = document.getElementById('poem-list');
// 显示诗词文本
if (data.poem) {
poemText.textContent = data.poem;
} else {
poemText.textContent = '未生成诗词内容';
}
// 显示诗词列表
poemList.innerHTML = '';
if (data.list && Array.isArray(data.list)) {
data.list.forEach((line, index) => {
const li = document.createElement('li');
li.textContent = `${index + 1}. ${line}`;
poemList.appendChild(li);
});
}
// 显示结果容器
resultContainer.classList.add('show');
// 滚动到结果区域
resultContainer.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
// 页面加载完成后的初始化
document.addEventListener('DOMContentLoaded', function() {
// 尝试从本地存储加载token
const savedToken = localStorage.getItem('poem_api_token');
if (savedToken) {
document.getElementById('token').value = savedToken;
}
// 保存token到本地存储
document.getElementById('token').addEventListener('blur', function() {
const token = this.value.trim();
if (token) {
localStorage.setItem('poem_api_token', token);
}
});
console.log('藏头诗页面加载完成');
});
// 打开 Token 获取弹窗
function openTokenModal() {
document.getElementById('token-modal').classList.add('show');
document.body.style.overflow = 'hidden'; // 禁止背景滚动
}
// 关闭 Token 获取弹窗
function closeTokenModal(event) {
if (event && event.target !== event.currentTarget) {
return; // 如果点击的是弹窗内容,不关闭
}
document.getElementById('token-modal').classList.remove('show');
document.body.style.overflow = ''; // 恢复背景滚动
}
// ESC 键关闭弹窗
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape') {
const modal = document.getElementById('token-modal');
if (modal.classList.contains('show')) {
closeTokenModal();
}
}
});
参数名 | 类型 | 必填 | 说明 | 示例 |
|---|---|---|---|---|
token | string | 是 | 接口调用 token,需要在 token 管理中创建 | qlVquQZPYSeaCi6u |
keyword | string | 是 | 藏字内容,2-8 个字 | 我喜欢你 |
num | string | 否 | 诗句格式,5 五言诗[默认]、7 七言诗 | 5 |
type | string | 否 | 藏头位置,1 藏头[默认]、2 藏尾、3 藏中、4 递增、5 递减 | 1 |
rhyme | string | 否 | 押韵类型,1 双句一压[默认]、2 双句押韵、3 一三四押 | 1 |
{
"request_id": "726522748246958080",
"success": true,
"message": "success",
"code": 200,
"data": {
"keyword": "天下第一",
"poem": "天香飘户月枝春,下感知己时横流。第一莫教渔父见,一归华表好增伤。",
"list": [
"天香飘户月枝春",
"下感知己时横流",
"第一莫教渔父见",
"一归华表好增伤"
]
},
"time": 1734176521,
"usage": 0
}
// 构建请求参数
const params = new URLSearchParams();
params.append('token', formData.token);
params.append('keyword', formData.keyword);
params.append('num', formData.num);
params.append('type', formData.type);
params.append('rhyme', formData.rhyme);
// 发送POST请求
fetch('https://v3.alapi.cn/api/ai/poem', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: params.toString()
})
.then(response => {
if (!response.ok) {
thrownewError('网络请求失败: ' + response.status);
}
return response.json();
})
.then(data => {
if (data.success && data.code === 200) {
displayPoem(data.data);
} else {
showError(data.message || '生成失败,请检查参数');
}
})
.catch(error => {
console.error('请求错误:', error);
showError('请求失败: ' + error.message + '。请检查网络连接或API Token是否正确');
});
// 验证关键字长度
if (formData.keyword.length < 2 || formData.keyword.length > 8) {
showError('关键字长度必须在2-8个字之间');
return;
}
// 验证token
if (!formData.token) {
showError('请输入API Token');
return;
}
<input type="text" id="keyword" name="keyword"
placeholder="请输入2-8个字的藏字内容,如:我喜欢你"
required maxlength="8" minlength="2">
// 显示加载状态
submitBtn.disabled = true;
submitBtn.textContent = '生成中...';
loading.classList.add('show');
// 恢复按钮状态
submitBtn.disabled = false;
submitBtn.textContent = '生成藏头诗';
loading.classList.remove('show');
.loading {
text-align: center;
padding: 20px;
color: #666;
display: none;
}
.loading.show {
display: block;
}
.loading::after {
content: '...';
animation: dots 1.5ssteps(4, end) infinite;
}
@keyframes dots {
0%, 20% { content: '.'; }
40% { content: '..'; }
60%, 100% { content: '...'; }
}
function showError(message) {
const errorMessage = document.getElementById('error-message');
errorMessage.textContent = message;
errorMessage.classList.add('show');
}
.error-message {
background-color: #fee;
color: #c00;
padding: 15px;
border-radius: 6px;
border-left: 4px solid #f00;
margin-top: 20px;
display: none;
}
.error-message.show {
display: block;
}
// 页面加载时恢复 Token
const savedToken = localStorage.getItem('poem_api_token');
if (savedToken) {
document.getElementById('token').value = savedToken;
}
// 输入框失去焦点时保存 Token
document.getElementById('token').addEventListener('blur', function() {
const token = this.value.trim();
if (token) {
localStorage.setItem('poem_api_token', token);
}
});
// 滚动到结果区域
resultContainer.scrollIntoView({ behavior: 'smooth', block: 'start' });
.poem-text {
font-size: 20px;
line-height: 2;
color: #2c3e50;
text-align: center;
font-family: 'KaiTi', '楷体', serif;
white-space: pre-line;
}
原因:浏览器的同源策略限制
解决方案:
fetch API(Cordova 环境支持跨域)<meta http-equiv="Content-Security-Policy"
content="default-src 'self' data: https://ssl.gstatic.com https://v3.alapi.cn https://www.alapi.cn 'unsafe-eval';
style-src 'self' 'unsafe-inline';
media-src *;
img-src 'self' data: content:;
script-src 'self' 'unsafe-inline' 'unsafe-eval';
connect-src 'self' https://v3.alapi.cn https://www.alapi.cn;
frame-src https://www.alapi.cn;">
原因:CSP 策略限制或网络问题
解决方案:
frame-src 指令到 CSP<div class="modal-footer">
<p style="margin: 0; color: #666;">
如果页面无法加载,请
<a href="https://www.alapi.cn/aff/nutpi" target="_blank">点击这里在新窗口打开</a>
</p>
</div>
原因:浏览器清除缓存或 localStorage 被清空
解决方案:
localStorage 持久化存储原因:网络延迟或 API 服务器响应慢
解决方案:
// 添加超时处理
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 10000); // 10秒超时
fetch('https://v3.alapi.cn/api/ai/poem', {
method: 'POST',
signal: controller.signal,
// ... 其他配置
})
.then(response => {
clearTimeout(timeoutId);
// ... 处理响应
})
.catch(error => {
if (error.name === 'AbortError') {
showError('请求超时,请检查网络连接后重试');
}
});
原因:响应式设计不完善
解决方案:
@media (max-width:768px) {
.form-row {
flex-direction: column;
}
.modal-content {
width: 95%;
max-height: 90vh;
}
.modal-bodyiframe {
height: 400px;
}
.token-input-wrapper {
flex-direction: column;
}
.help-btn {
margin-top: 8px;
width: 100%;
}
}
// 完善的错误处理链
fetch(url, options)
.then(response => {
if (!response.ok) {
thrownewError(`HTTP error! status: ${response.status}`);
}
return response.json();
})
.then(data => {
if (data.success) {
// 处理成功情况
} else {
thrownewError(data.message || '未知错误');
}
})
.catch(error => {
// 统一错误处理
console.error('Error:', error);
showError(error.message);
});
// 防抖处理(避免频繁请求)
let debounceTimer;
function generatePoemDebounced() {
clearTimeout(debounceTimer);
debounceTimer = setTimeout(() => {
generatePoem();
}, 300);
}
// 请求取消(避免重复请求)
let currentController = null;
function generatePoem() {
// 取消之前的请求
if (currentController) {
currentController.abort();
}
currentController = new AbortController();
fetch(url, {
signal: currentController.signal,
// ...
});
}
www/
├── poem.html # 藏头诗页面
├── js/
│ └── poem.js # 藏头诗功能脚本
├── index.html # 首页
├── about.html # 关于我们
└── css/
└── index.css # 样式文件
harmonyos/entry/src/main/resources/rawfile/www/
├── poem.html # 藏头诗页面(同步)
├── js/
│ └── poem.js # 藏头诗功能脚本(同步)
└── ...
# 添加浏览器平台(用于测试)
hcordova platform add browser
# 运行浏览器预览
hcordova run browser
# 构建 HarmonyOS 应用
hcordova build harmonyos
# 构建 Android 应用
hcordova build android
# 构建 iOS 应用(仅 macOS)
hcordova build ios
config.xml 中的 CSP 配置// 保存生成历史
function saveHistory(poemData) {
const history = JSON.parse(localStorage.getItem('poem_history') || '[]');
history.unshift({
keyword: poemData.keyword,
poem: poemData.poem,
timestamp: Date.now()
});
// 只保留最近 50 条
if (history.length > 50) {
history.pop();
}
localStorage.setItem('poem_history', JSON.stringify(history));
}
// 分享诗词
function sharePoem(poem) {
if (navigator.share) {
navigator.share({
title: '我生成的藏头诗',
text: poem
});
} else {
// 复制到剪贴板
navigator.clipboard.writeText(poem);
alert('诗词已复制到剪贴板');
}
}
// 收藏诗词
function favoritePoem(poemData) {
const favorites = JSON.parse(localStorage.getItem('poem_favorites') || '[]');
favorites.push(poemData);
localStorage.setItem('poem_favorites', JSON.stringify(favorites));
}
// 导出为图片
function exportAsImage(poem) {
// 使用 canvas 或第三方库生成图片
// 例如使用 html2canvas
}
本文详细介绍了如何在 Cordova 应用中实现藏头诗生成功能,包括:
通过本文的指导,您可以快速实现一个功能完整、用户体验良好的藏头诗应用。希望本文对您的开发工作有所帮助!
作者: 坚果派开发团队 最后更新: 2025 年 版本: 1.0
参考资源:
参考资料
[1]
alapi.cn: https://www.alapi.cn/aff/nutpi
[2]
AlAPI 官方文档: https://www.alapi.cn/aff/nutpi
[3]
Cordova 官方文档: https://cordova.apache.org/docs/en/latest/
[4]
MDN Web Docs - Fetch API: https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API