发现DeepSeek网页端现在支持类似Claude 的Artifacts效果(HTML卡片工具)//附带提示词
今天本来要写Latex的,结果意外发现网页端现在能用行间公式 \[\]包裹得到HTML的渲染。
想到是不是可以让Deepseek 也输出类似 Anthropic 这种网页端小卡片工具的效果。
像这样:
Anthropic 的 Artifact

DeepSeek 效果

感觉这个特性挺好玩的,以后就可以靠这个让它生成点小工具。也不用复制到html文件里面再打开。
特性研究
但是Deepseek跟Antropic 的这个Artifacts还不一样。
Deepseek是借助Mathjax渲染机制把html格式渲染的,但是mathjax本身渲染机制不支持<script>标签注入。所以直接用Anthropic 的方法,肯定是不行的。

这里用了 oninput="" onclick="" 事件属性 注入JavaScript
其他的一些事件属性也可以,如下表。
| 实现方式 | 原理 | 优点 | 缺点 |
|---|---|---|---|
| 纯伪协议注入 | 每次点击链接时运行一段逻辑(如 javascript:...)。 | 极其简单,不需要修改网页源码,即点即用。 | 无法实现实时“倒计时”效果,只能点击瞬间触发,属于被动交互。 |
| 定时器注入 (setInterval) | 注入一段 JS 脚本,在页面 DOM 中创建一个浮动层或修改标题。 | 可以实现动态倒计时,实时显示北京时间或冷却进度,视觉效果拉满。 | 逻辑较复杂,涉及 DOM 操作及定时器的内存管理(需要手动清除)。 |
href 接 JavaScript 伪协议也可以。
示例
<a href="javascript:(function(){window.t=window.t||0;var n=Date.now();if(n-window.t>3000){window.t=n;console.log('注入成功!北京时间:'+new Date().toLocaleString());}else{console.warn('冷却中...');}void(0);})();">
点我 Log 时间
</a>
但是这里有一个细节。如果你里面要声明变量,声明的变量一定不要用 let ,不然反复点击注入要 触发标识符重复定义的 Syntax Error
即
Identifier 'example' has already been declared
ok,那我们现在都搞清楚了,来构建提示词。
也可以构建Skill,像这样,我感觉效果还不错。
提示词
<提示词隔离区 开始>
# 你的技能Skill
## 🛠️ Skill: HTML卡片工具生成器
**Skill 名称:** generate_html_card
**触发时机:** 当用户需要可视化工具/转换工具/交互卡片时使用
**Skill 细节:**
生成卡片工具时严格遵守以下规则:
【卡片输出规则】
1. 卡片必须以 \\[ 开头,以 \\] 结尾(反斜杠+方括号)
2. \\[ 和 \\] 之间只放HTML代码,禁止用```html包裹
3. 所有CSS样式内联写在 style="" 里,每个规则独立换行
4. JS逻辑写在 onclick/oninput/onchange 等事件属性里,禁止使用<script>标签
5. 事件属性内变量声明用 var 或直接赋值,禁止使用 let/const
6. 禁止使用 Canvas API 绘制复杂图形,优先用 CSS 实现视觉效果(渐变、阴影、动画等)
7. 如果功能复杂,优先思考能否用 CSS 动画 + 简单 JS 触发器实现,而非编写大量 JS 逻辑
8. 必须保证卡片能正常交互,不能因为规则限制而输出无法运行的代码。你一定可以做到。
【对话交流规则】
1. 输出卡片后,你可以正常用文字向我解释工具的功能、设计、用法
2. 卡片工具和对话交流是分开的,互不干扰
3. 不要因为输出卡片就变成只会输出代码的机器
【反例警告与正确示范】
❌ 绝对禁止的输出形式:
<div>...</div>
<script>...</script>
✅ 唯一正确的输出形式(复杂逻辑请严格套用此模板):
\[
<div id="app">
<!-- 界面元素 -->
<button onclick="window.appAction && window.appAction()">点击</button>
<!-- 隐藏初始化器:利用 onmouseover 一次性注入全部逻辑 -->
<div style="display:none;" onmouseover="
if (window._inited) return;
window._inited = true;
// 1. 定义数据
var data = [];
// 2. 定义工具函数挂载到 window
window.parseMenu = function(text) { ... };
window.saveData = function() { ... };
// 3. 定义交互入口
window.appAction = function() { ... };
// 4. 初始化执行
window.loadData();
"></div>
</div>
\]
请务必模仿上述结构:使用隐藏 div 的 onmouseover 作为初始化脚本块,使用 window 对象挂载跨函数变量。禁止使用 <script> 标签。
</提示词隔离区 结束>
封装后的效果:


啊哈哈哈。实现了。
就是目前这一版提示词它输出的还是会带有卡片背景。
如果想要Artifacts那样透明背景 轻量的工具,可以直接试试这个提示词。
注意要适配localstorage 的主题(light dark 或system)
进阶提示词
<提示词隔离区 开始>
# 你的技能Skill
## 🛠️ Skill: HTML卡片工具生成器
**Skill 名称:** generate_html_card
**触发时机:** 当用户需要可视化工具/计算器/交互卡片时使用
---
## 📖 环境原理说明
你输出的HTML卡片运行在特殊渲染容器中,这导致:
1. **<style> 会失效**:被当作文本丢弃 → CSS必须内联在 style="" 里
2. **<script> 会失效**:被当作文本丢弃 → JS必须写在 onclick/oninput 等事件属性里
3. **let/const 重复声明报错**:事件属性每次触发在同一全局作用域 → 用 var 或直接赋值
4. **异步API丢失上下文**:setTimeout/setInterval 回调在全局执行,访问不到闭包变量 → 只用同步交互
5. **状态靠DOM属性**:数据存在 data-* 属性里,通过 getAttribute/setAttribute 读写
6. **主题自适应**:检测 localStorage 中的 __appKit_@deepseek/chat_themePreference 判断亮暗模式
---
## ✅ 正确示例(请模仿此结构)
\[
<div id="card" style="
max-width: 360px;
margin: 2rem auto;
padding: 2rem 1.5rem;
background: transparent;
border-radius: 28px;
box-shadow: 0 20px 35px -8px rgba(0,0,0,0.15);
font-family: system-ui, 'Segoe UI', Roboto, sans-serif;
border: 1px solid rgba(128,128,128,0.2);
transition: all 0.2s;
">
<div style="
margin-bottom: 1.5rem;
font-weight: 650;
font-size: 1.5rem;
border-bottom: 2px solid rgba(128,128,128,0.2);
padding-bottom: 0.8rem;
" id="title">
🔢 奇偶判定
</div>
<div style="margin-bottom: 1.5rem;">
<label style="
display: block;
font-size: 0.8rem;
font-weight: 600;
margin-bottom: 6px;
text-transform: uppercase;
" id="label">输入整数</label>
<input type="number" id="numInput" placeholder="例如 42" value="" style="
width: 100%;
padding: 14px 16px;
font-size: 1.2rem;
border: 2px solid rgba(128,128,128,0.3);
border-radius: 18px;
background: transparent;
outline: none;
box-sizing: border-box;
" oninput="
var val = this.value.trim();
var resDiv = document.getElementById('resultDisplay');
var iconSpan = document.getElementById('resultIcon');
var textSpan = document.getElementById('resultText');
if (val === '') {
resDiv.style.background = 'rgba(128,128,128,0.1)';
iconSpan.innerHTML = '🔍';
textSpan.innerText = '等待输入';
return;
}
var num = Number(val);
if (isNaN(num) || !Number.isInteger(num)) {
resDiv.style.background = 'rgba(200,70,50,0.15)';
iconSpan.innerHTML = '⚠️';
textSpan.innerText = '需要整数';
return;
}
var isEven = num % 2 === 0;
resDiv.style.background = isEven ? 'rgba(40,160,80,0.15)' : 'rgba(220,120,40,0.15)';
iconSpan.innerHTML = isEven ? '⭕' : '🔘';
textSpan.innerText = isEven ? '偶数' : '奇数';
">
</div>
<div id="resultDisplay" style="
background: rgba(128,128,128,0.1);
border-radius: 20px;
padding: 1.2rem 1.5rem;
display: flex;
align-items: center;
gap: 16px;
transition: background 0.2s;
">
<span id="resultIcon" style="font-size: 2.5rem;">🔍</span>
<span id="resultText" style="font-size: 2rem; font-weight: 650;">等待输入</span>
</div>
<div style="
margin-top: 1.2rem;
font-size: 0.75rem;
text-align: right;
opacity: 0.6;
">
⚡ 实时判定
</div>
</div>
<!-- 主题自适应 + 初始化 -->
<div style="
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 9999;
" onmouseover="
if (window._themeInited) return;
window._themeInited = true;
var themeJson = localStorage.getItem('__appKit_@deepseek/chat_themePreference');
var isDark = false;
if (themeJson) {
try {
var themeData = JSON.parse(themeJson);
if (themeData.value === 'dark') isDark = true;
else if (themeData.value === 'system') isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
} catch(e) {}
}
var textColor = isDark ? '#f0f0f0' : '#1a1a1a';
var card = document.getElementById('card');
var title = document.getElementById('title');
var label = document.getElementById('label');
var input = document.getElementById('numInput');
var resultText = document.getElementById('resultText');
if (card) card.style.color = textColor;
if (title) title.style.color = textColor;
if (label) label.style.color = isDark ? '#b0b0b0' : '#5f5f73';
if (input) {
input.style.color = textColor;
input.style.borderColor = isDark ? 'rgba(255,255,255,0.2)' : 'rgba(0,0,0,0.2)';
}
if (resultText) resultText.style.color = textColor;
var self = document.getElementById('themeTrigger');
if (self) self.style.display = 'none';
" id="themeTrigger"></div>
\]
---
## 🛠️ 输出规则
1. 必须以 \\[ 开头,以 \\] 结尾
2. 中间只放HTML,禁止用```html包裹
3. CSS内联写在 style="" 里,每个规则独立换行
4. 背景用 transparent,文字颜色通过主题检测动态设置
5. JS写在 onclick/oninput 等事件属性里,禁止 <script>
6. 变量用 var 或直接赋值,禁止 let/const
7. 禁止 setTimeout/setInterval/requestAnimationFrame
8. 交互设计为同步模式:触发→计算→更新DOM→结束
---
## 💬 对话规则
输出卡片后,用文字解释功能、设计思路。卡片和对话互不干扰。
</提示词隔离区 结束>

效果相当好哇。



哈哈哈,感觉很有意思。相当于用 Deepseek 也拥有Claude Artifacts 的技能了。
如果喜欢的话,点个赞呀~
收录于知乎专栏「js逆向实例」· 查看知乎原文