This commit is contained in:
Mrx
2026-05-20 14:48:07 +08:00
parent 02a2bfd0a9
commit 19a11516ec
2 changed files with 1292 additions and 279 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -22,6 +22,14 @@ const loading = ref(false)
const result = ref<Record<string, any> | null>(null)
const error = ref('')
// 游戏相关状态
const gameOptions = ref<Array<{ label: string; value: string; isCorrect: boolean }>>([])
const selectedOption = ref<string | null>(null)
const answered = ref(false)
const answeredCorrect = ref(false)
const systemIdiom = ref('') // 系统给出的成语
const chainGameStep = ref(0) // 接龙游戏步骤0=初始1=用户输入
// 选择框相关状态
const popup = ref<any>(null)
const currentField = ref<any>(null)
@@ -32,6 +40,7 @@ onLoad((query) => {
const key = (query?.key as string) || ''
toolKey.value = key
tool.value = getToolboxItem(key)
console.log('工具配置:', tool.value)
if (!tool.value) {
error.value = '未找到该工具'
}
@@ -41,10 +50,24 @@ onLoad((query) => {
// 初始化表单默认值
if (tool.value.fields) {
tool.value.fields.forEach(field => {
// 设置默认值
if (field.default !== undefined && !form.value[field.key]) {
form.value[field.key] = field.default
}
// 对于 select 类型,即使没有值也设置默认值
if (field.type === 'select' && !form.value[field.key] && field.default !== undefined) {
form.value[field.key] = field.default
}
// 如果是日期字段且没有默认值,设置为今天
if (field.type === 'date' && !form.value[field.key]) {
const today = new Date()
const year = today.getFullYear()
const month = String(today.getMonth() + 1).padStart(2, '0')
const day = String(today.getDate()).padStart(2, '0')
form.value[field.key] = `${year}-${month}-${day}`
}
})
console.log('初始化后的表单:', JSON.stringify(form.value))
}
// 如果工具标记了自动查询或不需要输入参数,打开即查
@@ -73,6 +96,70 @@ function getSelectedLabel(field, value) {
return option ? option.label : null
}
// 判断字段是否可见
function isFieldVisible(field, formValue) {
if (!tool.value?.fieldVisibility || !field.key) {
return true
}
const visibilityFn = tool.value.fieldVisibility[field.key]
if (visibilityFn && typeof visibilityFn === 'function') {
return visibilityFn(formValue)
}
return true
}
// 获取动态placeholder
function getFieldPlaceholder(field) {
if (!tool.value?.fieldPlaceholder || !field.key) {
return field.placeholder || ''
}
const placeholderFn = tool.value.fieldPlaceholder[field.key]
if (placeholderFn && typeof placeholderFn === 'function') {
return placeholderFn(form.value)
}
return field.placeholder || ''
}
// 处理单选按钮切换
function handleRadioChange(fieldKey: string, value: any) {
form.value[fieldKey] = value
// 清空依赖该字段的其他字段值
if (tool.value?.fieldVisibility) {
Object.keys(tool.value.fieldVisibility).forEach(key => {
const visibilityFn = tool.value.fieldVisibility[key]
if (visibilityFn && !visibilityFn(form.value)) {
form.value[key] = ''
}
})
}
// 清空word字段的值
if (fieldKey === 'type') {
form.value['word'] = ''
}
}
// 获取显示值(支持 transform
function getDisplayValue(key: string, value: any) {
if (!tool.value?.resultLabels)
return value
const labelOrObj = tool.value.resultLabels[key]
if (typeof labelOrObj === 'object' && labelOrObj !== null && labelOrObj.transform) {
return labelOrObj.transform(value)
}
return value
}
// 处理输入框输入,自动截断
function handleInput(fieldKey: string, value: string) {
form.value[fieldKey] = value
// 如果有maxlength限制自动截断
const field = tool.value?.fields?.find(f => f.key === fieldKey)
if (field?.maxlength && value.length > field.maxlength) {
form.value[fieldKey] = value.substring(0, field.maxlength)
}
}
// 显示自定义选择器
function showPicker(field) {
currentField.value = field
@@ -106,9 +193,49 @@ async function handleQuery() {
return
error.value = ''
answered.value = false
// 成语接龙特殊处理
if (toolKey.value === 'chengyujielong') {
if (!form.value.word) {
error.value = '请输入成语'
return
}
loading.value = true
try {
const res = await postToolboxQuery(toolKey.value, {
word: form.value.word,
userid: '1212' // 固定用户ID
})
if (res.code === 200 && res.data?.result) {
result.value = res.data.result
answered.value = true // 标记已回答
// 如果接龙成功,保存系统返回的成语
if (res.data.result.word) {
systemIdiom.value = res.data.result.word
chainGameStep.value = 1
}
} else {
error.value = res.msg || '接龙失败'
}
} catch {
error.value = '网络错误,请稍后重试'
} finally {
loading.value = false
}
return
}
result.value = null
revealedKeys.value = new Set()
// 调试:打印表单值
console.log('提交的表单数据:', JSON.stringify(form.value))
console.log('验证结果:', tool.value.validate(form.value))
if (!tool.value.validate(form.value)) {
error.value = tool.value.validateMsg
return
@@ -119,6 +246,21 @@ async function handleQuery() {
const res = await postToolboxQuery(toolKey.value, form.value)
if (res.code === 200 && res.data?.result) {
result.value = res.data.result
// 如果是游戏类工具
if (tool.value?.isGame) {
// 成语填字和诗词填空:准备选项
if (toolKey.value === 'idiom-quiz' || toolKey.value === 'poem-fill') {
prepareGameOptions()
}
// 成语接龙:记录系统返回的成语
if (toolKey.value === 'chengyujielong') {
if (result.value?.word) {
systemIdiom.value = result.value.word
chainGameStep.value = 1
}
}
}
}
else {
error.value = res.msg || '查询失败'
@@ -187,6 +329,71 @@ const listLabelEntries = computed(() => {
return []
return Object.entries(tool.value.resultLabels)
})
// 游戏工具:准备选项(打乱顺序)
const prepareGameOptions = () => {
if (!result.value || !result.value.correct)
return
const correct = result.value.correct
const options = [
{ label: correct, value: correct, isCorrect: true },
{ label: result.value.wrong_a || '', value: result.value.wrong_a || '', isCorrect: false },
{ label: result.value.wrong_b || '', value: result.value.wrong_b || '', isCorrect: false },
{ label: result.value.wrong_c || '', value: result.value.wrong_c || '', isCorrect: false },
].filter(opt => opt.label) // 过滤空值
// 打乱顺序
for (let i = options.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1))
;[options[i], options[j]] = [options[j], options[i]]
}
gameOptions.value = options
selectedOption.value = null
answered.value = false
}
// 点击选项
function handleOptionClick(option: { label: string; value: string; isCorrect: boolean }) {
if (answered.value)
return
selectedOption.value = option.value
answered.value = true
answeredCorrect.value = option.isCorrect
// 如果答对了,显示完整答案和解释
if (option.isCorrect) {
revealedKeys.value.add('full')
revealedKeys.value.add('explan')
}
}
// 快速填入:将系统接龙的成语填入输入框
function handleQuickFill() {
if (result.value?.word) {
form.value.word = result.value.word
systemIdiom.value = result.value.word
// 清空之前的结果
result.value = null
answered.value = false
}
}
// 重新开始(再来一题)
function handleRestart() {
if (toolKey.value === 'chengyujielong') {
// 成语接龙:清空表单,重新开局
form.value.word = ''
systemIdiom.value = ''
chainGameStep.value = 0
answered.value = false
result.value = null
return
}
handleQuery()
}
</script>
<template>
@@ -201,6 +408,8 @@ const listLabelEntries = computed(() => {
<!-- 动态表单 -->
<view class="form-area">
<view v-for="field in tool.fields" :key="field.key" class="field">
<!-- 检查字段是否可见 -->
<template v-if="isFieldVisible(field, form)">
<text class="field-label">{{ field.label }}</text>
<!-- 按钮切换 (Radio) -->
@@ -210,7 +419,7 @@ const listLabelEntries = computed(() => {
:key="opt.value"
class="radio-item"
:class="{ active: (form[field.key] ?? field.default) === opt.value }"
@tap="form[field.key] = opt.value"
@tap="handleRadioChange(field.key, opt.value)"
>
{{ opt.label }}
</view>
@@ -252,7 +461,7 @@ const listLabelEntries = computed(() => {
:placeholder="field.placeholder"
:value="form[field.key] || ''"
placeholder-class="field-ph"
@input="(e: any) => (form[field.key] = e.detail.value)"
@input="(e: any) => handleInput(field.key, e.detail.value)"
/>
<!-- 普通输入框 -->
@@ -261,12 +470,15 @@ const listLabelEntries = computed(() => {
class="field-input"
:type="field.type"
:maxlength="field.maxlength"
:placeholder="field.placeholder"
:placeholder="getFieldPlaceholder(field)"
:value="form[field.key] || ''"
placeholder-class="field-ph"
confirm-type="done"
@input="(e: any) => (form[field.key] = e.detail.value)"
>
@input="(e: any) => handleInput(field.key, e.detail.value)"
@blur="(e: any) => (form[field.key] = e.detail.value)"
@confirm="(e: any) => (form[field.key] = e.detail.value)"
/>
</template>
</view>
</view>
@@ -284,10 +496,183 @@ const listLabelEntries = computed(() => {
<text class="msg-text">{{ error }}</text>
</view>
<!-- 游戏类工具特殊展示 -->
<view v-if="tool?.isGame && result" class="game-area">
<!-- 成语接龙特殊展示 -->
<template v-if="toolKey === 'chengyujielong'">
<!-- 用户输入的成语 -->
<view v-if="form.word" class="chain-user-input">
<text class="chain-user-label">你的成语</text>
<text class="chain-user-value">{{ form.word }}</text>
</view>
<!-- 系统接龙的结果 -->
<view v-if="result && result.word" class="chain-result">
<view class="chain-success">
<text class="chain-success-icon">🔗</text>
<view class="chain-success-content">
<text class="chain-idiom">{{ result.word }}</text>
<text v-if="result.pinyin" class="chain-pinyin">{{ result.pinyin }}</text>
<text v-if="result.jieshi" class="chain-explain">{{ result.jieshi }}</text>
</view>
</view>
<!-- 快速填入按钮 -->
<button class="chain-quick-btn" @tap="handleQuickFill">
📝 用这个继续接龙
</button>
</view>
<!-- 空状态提示 -->
<view v-if="!result" class="chain-empty">
<text class="chain-empty-text">输入成语后系统会自动接龙</text>
</view>
</template>
<!-- 填字游戏成语填字诗词填空 -->
<template v-else>
<!-- 难度标签 -->
<view v-if="result.diff" class="game-diff">
<text class="game-diff-text">{{ getDisplayValue('diff', result.diff) }}</text>
</view>
<!-- 题目 -->
<view class="game-question">
<text class="game-question-text">{{ result.question }}</text>
</view>
<!-- 选项按钮 -->
<view class="game-options">
<view
v-for="(option, index) in gameOptions"
:key="index"
class="game-option"
:class="{
'game-option-selected': selectedOption === option.value,
'game-option-correct': answered && option.isCorrect,
'game-option-wrong': answered && selectedOption === option.value && !option.isCorrect,
}"
@tap="handleOptionClick(option)"
>
<text class="game-option-text">{{ option.label }}</text>
</view>
</view>
<!-- 答案和解释 -->
<view v-if="answered" class="game-result">
<!-- 答对提示 -->
<view v-if="answeredCorrect" class="game-status game-status-correct">
<text class="game-status-text">🎉 回答正确</text>
</view>
<!-- 答错提示 -->
<view v-else class="game-status game-status-wrong">
<text class="game-status-text"> 回答错误</text>
</view>
<!-- 成语填字显示完整成语和解释 -->
<template v-if="toolKey === 'idiom-quiz'">
<view class="game-answer">
<text class="game-answer-label">完整成语</text>
<text class="game-answer-value">{{ result.full }}</text>
</view>
<view class="game-explan">
<text class="game-explan-label">成语解释</text>
<text class="game-explan-value">{{ result.explan }}</text>
</view>
</template>
<!-- 诗词填空显示完整诗句和详细信息 -->
<template v-else-if="toolKey === 'poem-fill'">
<view class="game-answer">
<text class="game-answer-label">完整诗句</text>
<text class="game-answer-value">{{ result.full }}</text>
</view>
<view class="game-poem-info">
<view v-if="result.title" class="game-poem-item">
<text class="game-poem-label">诗名</text>
<text class="game-poem-value">{{ result.title }}</text>
</view>
<view v-if="result.author" class="game-poem-item">
<text class="game-poem-label">作者</text>
<text class="game-poem-value">{{ result.author }}</text>
</view>
<view v-if="result.dynasty" class="game-poem-item">
<text class="game-poem-label">朝代</text>
<text class="game-poem-value">{{ result.dynasty }}</text>
</view>
<view v-if="result.category" class="game-poem-item">
<text class="game-poem-label">分类</text>
<text class="game-poem-value">{{ result.category }}</text>
</view>
</view>
<view v-if="result.note" class="game-explan">
<text class="game-explan-label">注释</text>
<text class="game-explan-value">{{ result.note }}</text>
</view>
</template>
</view>
</template>
<!-- 再来一题按钮 -->
<button class="game-restart-btn" @tap="handleRestart">
🔄 再来一题
</button>
</view>
<!-- 结果展示 - 普通键值对 -->
<view v-if="resultEntries.length > 0 && tool?.resultType !== 'list'" class="result-area">
<view v-if="resultEntries.length > 0 && tool?.resultType !== 'list' && !tool?.isGame" class="result-area">
<view class="result-title">查询结果</view>
<view class="result-list">
<!-- 字典类型特殊显示 -->
<view v-if="tool?.resultType === 'dict'" class="dict-result">
<!-- 汉字标题 -->
<view v-if="result.word" class="dict-word">
<text class="dict-word-text">{{ result.word }}</text>
</view>
<!-- 基础信息卡片 -->
<view v-if="result.py || result.pyyb || result.wubi || result.bihua || result.bushou" class="dict-basic-info">
<view v-if="result.py" class="dict-info-item">
<text class="dict-info-label">拼音</text>
<text class="dict-info-value">{{ result.py }}</text>
</view>
<view v-if="result.pyyb" class="dict-info-item">
<text class="dict-info-label">拼音音标</text>
<text class="dict-info-value">{{ result.pyyb }}</text>
</view>
<view v-if="result.wubi" class="dict-info-item">
<text class="dict-info-label">五笔</text>
<text class="dict-info-value">{{ result.wubi }}</text>
</view>
<view v-if="result.bihua" class="dict-info-item">
<text class="dict-info-label">笔画</text>
<text class="dict-info-value">{{ result.bihua }}</text>
</view>
<view v-if="result.bushou" class="dict-info-item">
<text class="dict-info-label">部首</text>
<text class="dict-info-value">{{ result.bushou }}</text>
</view>
<view v-if="result.bishun" class="dict-info-item">
<text class="dict-info-label">笔顺</text>
<text class="dict-info-value">{{ result.bishun }}</text>
</view>
</view>
<!-- 释义卡片 -->
<view v-if="result.content" class="dict-content">
<text class="dict-content-title">释义</text>
<text class="dict-content-text">{{ result.content }}</text>
</view>
<!-- 详细解释卡片 -->
<view v-if="result.explain" class="dict-explain">
<text class="dict-explain-title">详细解释</text>
<text class="dict-explain-text">{{ result.explain }}</text>
</view>
</view>
<!-- 普通列表显示 -->
<view v-else class="result-list">
<view
v-for="item in resultEntries"
:key="item.key"
@@ -308,6 +693,8 @@ const listLabelEntries = computed(() => {
<text class="result-hide-btn" @tap="toggleReveal(item.key)">收起</text>
</template>
</view>
<!-- 多行文本 -->
<text v-else-if="typeof item.value === 'string' && item.value.length > 50" class="result-value result-multiline">{{ item.value }}</text>
<!-- 普通字段 -->
<text v-else class="result-value">{{ item.value }}</text>
</view>
@@ -357,7 +744,22 @@ const listLabelEntries = computed(() => {
<text v-if="fIdx === 0" class="card-item-index">{{ idx + 1 }}</text>
<text v-else class="card-item-index-placeholder" />
<text class="card-item-field-label">{{ typeof fieldLabel === 'object' ? fieldLabel.label : fieldLabel }}</text>
<!-- 隐藏字段点击显示/隐藏 -->
<view v-if="typeof fieldLabel === 'object' && fieldLabel.hidden" class="card-item-reveal-wrap">
<view
v-if="!revealedKeys.has(`${idx}-${fieldKey}`)"
class="card-item-reveal-btn"
@tap="toggleReveal(`${idx}-${fieldKey}`)"
>
点击查看
</view>
<template v-else>
<text class="card-item-field-value">{{ item[fieldKey] }}</text>
<text class="card-item-hide-btn" @tap="toggleReveal(`${idx}-${fieldKey}`)">收起</text>
</template>
</view>
<!-- 普通字段 -->
<text v-else class="card-item-field-value">{{ item[fieldKey] }}</text>
</template>
</view>
</view>
@@ -521,6 +923,79 @@ const listLabelEntries = computed(() => {
color: #f53f3f;
}
/* 字典结果样式 */
.dict-result {
display: flex;
flex-direction: column;
gap: 24rpx;
}
.dict-word {
background: linear-gradient(135deg, #1768ff, #4e8cff);
padding: 32rpx;
border-radius: 20rpx;
text-align: center;
}
.dict-word-text {
font-size: 72rpx;
font-weight: 600;
color: #ffffff;
}
.dict-basic-info {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 16rpx;
padding: 0 8rpx;
}
.dict-info-item {
background: #f7f8fa;
padding: 20rpx;
border-radius: 16rpx;
display: flex;
flex-direction: column;
gap: 8rpx;
}
.dict-info-label {
font-size: 24rpx;
color: #86909c;
}
.dict-info-value {
font-size: 30rpx;
font-weight: 500;
color: #1d2129;
}
.dict-content,
.dict-explain {
background: #ffffff;
border: 1rpx solid #e5e6f0;
border-radius: 16rpx;
padding: 24rpx;
}
.dict-content-title,
.dict-explain-title {
font-size: 28rpx;
font-weight: 600;
color: #1d2129;
display: block;
margin-bottom: 16rpx;
}
.dict-content-text,
.dict-explain-text {
font-size: 26rpx;
color: #4e5969;
line-height: 1.8;
white-space: pre-wrap;
word-wrap: break-word;
}
.result-area {
margin-top: 8rpx;
padding-top: 24rpx;
@@ -560,6 +1035,12 @@ const listLabelEntries = computed(() => {
text-align: right;
}
.result-multiline {
text-align: left;
line-height: 1.8;
word-wrap: break-word;
}
.result-reveal-wrap {
flex: 1;
display: flex;
@@ -648,6 +1129,29 @@ const listLabelEntries = computed(() => {
font-weight: 500;
}
/* 列表卡片中的隐藏字段 */
.card-item-reveal-wrap {
flex: 1;
display: flex;
align-items: center;
gap: 12rpx;
}
.card-item-reveal-btn {
padding: 8rpx 24rpx;
font-size: 24rpx;
color: #ffffff;
background: linear-gradient(135deg, #1768ff, #4e8cff);
border-radius: 24rpx;
cursor: pointer;
}
.card-item-hide-btn {
font-size: 22rpx;
color: #86909c;
flex-shrink: 0;
}
/* 自定义选择器样式 */
.picker-container {
background-color: #fff;
@@ -688,4 +1192,285 @@ const listLabelEntries = computed(() => {
font-size: 28rpx;
color: #333;
}
/* 游戏区域样式 */
.game-area {
margin-top: 28rpx;
padding: 28rpx;
background: linear-gradient(145deg, #ffffff 0%, #f7f8ff 100%);
border-radius: 20rpx;
border: 2rpx solid #e5e6f0;
}
.game-diff {
margin-bottom: 16rpx;
}
.game-diff-text {
font-size: 22rpx;
color: #86909c;
background: #f7f8fa;
padding: 8rpx 20rpx;
border-radius: 20rpx;
}
.game-question {
text-align: center;
padding: 40rpx 20rpx;
margin-bottom: 32rpx;
}
.game-question-text {
font-size: 48rpx;
font-weight: 600;
color: #1d2129;
line-height: 1.6;
}
.game-options {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 16rpx;
margin-bottom: 32rpx;
}
.game-option {
height: 88rpx;
display: flex;
align-items: center;
justify-content: center;
background: #ffffff;
border: 2rpx solid #e5e6f0;
border-radius: 16rpx;
transition: all 0.2s;
}
.game-option:active {
transform: scale(0.98);
}
.game-option-selected {
border-color: #1768ff;
background: #e8f3ff;
}
.game-option-correct {
border-color: #00b42a;
background: #e8ffeb;
}
.game-option-wrong {
border-color: #f53f3f;
background: #ffe8e8;
}
.game-option-text {
font-size: 32rpx;
font-weight: 600;
color: #1d2129;
}
.game-result {
margin-bottom: 24rpx;
padding: 24rpx;
background: #f7f8fa;
border-radius: 16rpx;
}
.game-status {
text-align: center;
padding: 16rpx;
border-radius: 12rpx;
margin-bottom: 20rpx;
}
.game-status-correct {
background: #e8ffeb;
}
.game-status-wrong {
background: #ffe8e8;
}
.game-status-text {
font-size: 28rpx;
font-weight: 600;
}
.game-answer {
display: flex;
align-items: baseline;
margin-bottom: 16rpx;
}
.game-answer-label {
font-size: 24rpx;
color: #86909c;
}
.game-answer-value {
font-size: 32rpx;
font-weight: 600;
color: #1d2129;
margin-left: 8rpx;
}
.game-explan {
display: flex;
flex-direction: column;
gap: 8rpx;
}
.game-explan-label {
font-size: 24rpx;
color: #86909c;
font-weight: 600;
}
.game-explan-value {
font-size: 26rpx;
color: #4e5969;
line-height: 1.8;
}
/* 诗词信息样式 */
.game-poem-info {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 12rpx;
margin-bottom: 16rpx;
padding: 16rpx;
background: #ffffff;
border-radius: 12rpx;
}
.game-poem-item {
display: flex;
align-items: baseline;
gap: 8rpx;
}
.game-poem-label {
font-size: 22rpx;
color: #86909c;
}
.game-poem-value {
font-size: 24rpx;
font-weight: 500;
color: #1d2129;
}
.game-restart-btn {
width: 100%;
height: 88rpx;
line-height: 88rpx;
background: linear-gradient(135deg, #1768ff, #4e8cff);
color: #ffffff;
font-size: 28rpx;
font-weight: 500;
border-radius: 16rpx;
border: none;
margin-top: 16rpx;
}
.game-restart-btn[disabled] {
opacity: 0.6;
}
/* 成语接龙游戏样式 */
.chain-user-input {
display: flex;
align-items: center;
gap: 12rpx;
margin-bottom: 24rpx;
padding: 20rpx;
background: linear-gradient(135deg, #e8f3ff 0%, #ffffff 100%);
border-radius: 16rpx;
}
.chain-user-label {
font-size: 24rpx;
color: #86909c;
}
.chain-user-value {
font-size: 32rpx;
font-weight: 600;
color: #1768ff;
}
.chain-result {
margin-bottom: 24rpx;
}
.chain-success {
display: flex;
align-items: flex-start;
gap: 16rpx;
padding: 24rpx;
background: linear-gradient(145deg, #ffffff 0%, #f7f8ff 100%);
border: 2rpx solid #e8f3ff;
border-radius: 16rpx;
}
.chain-success-icon {
flex-shrink: 0;
width: 48rpx;
height: 48rpx;
line-height: 48rpx;
text-align: center;
background: linear-gradient(135deg, #00b42a, #36cfc9);
color: #ffffff;
font-size: 28rpx;
font-weight: 600;
border-radius: 50%;
}
.chain-success-content {
flex: 1;
display: flex;
flex-direction: column;
gap: 8rpx;
}
.chain-idiom {
font-size: 36rpx;
font-weight: 600;
color: #1d2129;
}
.chain-pinyin {
font-size: 22rpx;
color: #86909c;
}
.chain-explain {
font-size: 24rpx;
color: #4e5969;
line-height: 1.6;
}
.chain-quick-btn {
width: 100%;
height: 88rpx;
line-height: 88rpx;
background: linear-gradient(135deg, #1768ff, #4e8cff);
color: #ffffff;
font-size: 28rpx;
font-weight: 500;
border-radius: 16rpx;
border: none;
margin-top: 16rpx;
}
.chain-empty {
text-align: center;
padding: 40rpx 0;
color: #86909c;
}
.chain-empty-text {
font-size: 24rpx;
}
</style>