智慧教务系统
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

542 lines
13 KiB

<template>
<view class="container">
<view class="header">
<text class="title">字典获取优化演示</text>
<text class="subtitle">对比原方式和批量获取的性能差异</text>
</view>
<!-- 性能对比 -->
<view class="performance-section">
<view class="section-title">性能对比</view>
<!-- 原有方式 -->
<view class="test-item">
<view class="test-header">
<text class="test-name">原方式单个获取</text>
<button
class="test-btn old-style"
@click="testOldMethod"
:disabled="oldTesting">
{{ oldTesting ? '测试中...' : '开始测试' }}
</button>
</view>
<view class="test-result" v-if="oldResult">
<text class="result-text">耗时: {{ oldResult.time }}ms</text>
<text class="result-text">请求次数: {{ oldResult.requests }}次</text>
<text class="result-text">获取数据: {{ oldResult.count }}个字典</text>
</view>
</view>
<!-- 新方式 -->
<view class="test-item">
<view class="test-header">
<text class="test-name">新方式(批量获取)</text>
<button
class="test-btn new-style"
@click="testNewMethod"
:disabled="newTesting">
{{ newTesting ? '测试中...' : '开始测试' }}
</button>
</view>
<view class="test-result" v-if="newResult">
<text class="result-text">耗时: {{ newResult.time }}ms</text>
<text class="result-text">请求次数: {{ newResult.requests }}次</text>
<text class="result-text">获取数据: {{ newResult.count }}个字典</text>
<text class="improvement">
性能提升: {{ newResult.improvement }}
</text>
</view>
</view>
</view>
<!-- 缓存演示 -->
<view class="cache-section">
<view class="section-title">缓存机制演示</view>
<view class="cache-controls">
<button class="cache-btn" @click="testCache">测试缓存效果</button>
<button class="cache-btn clear" @click="clearCache">清除缓存</button>
</view>
<view class="cache-result" v-if="cacheResult">
<text class="cache-text">第一次获取: {{ cacheResult.firstTime }}ms</text>
<text class="cache-text">缓存获取: {{ cacheResult.cacheTime }}ms</text>
<text class="cache-text">性能提升: {{ cacheResult.improvement }}</text>
</view>
</view>
<!-- 字典数据展示 -->
<view class="data-section">
<view class="section-title">字典数据展示</view>
<view class="dict-tabs">
<view
class="tab-item"
:class="{ active: activeTab === key }"
v-for="(data, key) in dictData"
:key="key"
@click="activeTab = key">
{{ getDictDisplayName(key) }}
</view>
</view>
<scroll-view class="dict-content" scroll-y>
<view class="dict-items" v-if="dictData[activeTab]">
<view
class="dict-item"
v-for="(item, index) in dictData[activeTab]"
:key="index">
<text class="item-name">{{ item.name || item.text || '-' }}</text>
<text class="item-value">{{ item.value || '-' }}</text>
</view>
</view>
<view class="empty-state" v-else>
<text>暂无数据</text>
</view>
</scroll-view>
</view>
<!-- 使用说明 -->
<view class="usage-section">
<view class="section-title">使用说明</view>
<view class="usage-content">
<text class="usage-text">1. 使用 dictUtil.getBatchDict() 批量获取字典</text>
<text class="usage-text">2. 支持自动缓存30分钟有效期</text>
<text class="usage-text">3. 支持业务场景批量获取</text>
<text class="usage-text">4. 向后兼容原有 util.getDict() 方法</text>
</view>
</view>
</view>
</template>
<script>
import dictUtil from '@/common/dictUtil.js'
import util from '@/common/util.js'
export default {
data() {
return {
// 测试状态
oldTesting: false,
newTesting: false,
// 测试结果
oldResult: null,
newResult: null,
cacheResult: null,
// 字典数据
dictData: {},
activeTab: '',
// 测试用的字典keys
testKeys: [
'SourceChannel',
'source',
'customer_purchasing_power',
'preliminarycustomerintention',
'cognitive_concept',
'kh_status',
'decision_maker',
'distance'
]
}
},
onLoad() {
// 初始化时获取一次字典数据用于展示
this.loadInitialData()
},
methods: {
// 加载初始数据
async loadInitialData() {
try {
const data = await dictUtil.getBatchDict(this.testKeys)
this.dictData = data
this.activeTab = Object.keys(data)[0] || ''
} catch (error) {
console.error('加载初始数据失败:', error)
}
},
// 测试原有方式(单个获取)
async testOldMethod() {
this.oldTesting = true
this.oldResult = null
try {
const startTime = Date.now()
let successCount = 0
// 模拟原有的单个获取方式
for (const key of this.testKeys) {
try {
await this.getOldDict(key)
successCount++
} catch (error) {
console.warn(`获取字典 ${key} 失败:`, error)
}
}
const endTime = Date.now()
const totalTime = endTime - startTime
this.oldResult = {
time: totalTime,
requests: this.testKeys.length,
count: successCount
}
uni.showToast({
title: `原方式完成,耗时 ${totalTime}ms`,
icon: 'none'
})
} catch (error) {
console.error('测试原方式失败:', error)
uni.showToast({
title: '测试失败',
icon: 'none'
})
} finally {
this.oldTesting = false
}
},
// 测试新方式(批量获取)
async testNewMethod() {
this.newTesting = true
this.newResult = null
try {
const startTime = Date.now()
// 使用新的批量获取方式
const data = await dictUtil.getBatchDict(this.testKeys, false) // 不使用缓存进行公平测试
const endTime = Date.now()
const totalTime = endTime - startTime
const successCount = Object.keys(data).length
this.newResult = {
time: totalTime,
requests: 1, // 批量获取只需要1次请求
count: successCount
}
// 计算性能提升
if (this.oldResult) {
const improvement = Math.round(((this.oldResult.time - totalTime) / this.oldResult.time) * 100)
this.newResult.improvement = `${improvement}%`
}
// 更新展示数据
this.dictData = data
uni.showToast({
title: `新方式完成,耗时 ${totalTime}ms`,
icon: 'none'
})
} catch (error) {
console.error('测试新方式失败:', error)
uni.showToast({
title: '测试失败',
icon: 'none'
})
} finally {
this.newTesting = false
}
},
// 模拟原有的单个字典获取
async getOldDict(key) {
return new Promise((resolve, reject) => {
// 模拟单个接口请求的延迟
setTimeout(async () => {
try {
// 这里可以调用原有的获取方法,或者模拟
const result = await dictUtil.getDict(key, false)
resolve(result)
} catch (error) {
reject(error)
}
}, Math.random() * 200 + 100) // 模拟 100-300ms 的网络延迟
})
},
// 测试缓存效果
async testCache() {
try {
// 清除缓存确保公平测试
dictUtil.clearCache()
// 第一次获取(无缓存)
const startTime1 = Date.now()
await dictUtil.getBatchDict(this.testKeys.slice(0, 3), true)
const firstTime = Date.now() - startTime1
// 第二次获取(有缓存)
const startTime2 = Date.now()
await dictUtil.getBatchDict(this.testKeys.slice(0, 3), true)
const cacheTime = Date.now() - startTime2
const improvement = Math.round(((firstTime - cacheTime) / firstTime) * 100)
this.cacheResult = {
firstTime,
cacheTime,
improvement: `${improvement}%`
}
uni.showToast({
title: '缓存测试完成',
icon: 'success'
})
} catch (error) {
console.error('缓存测试失败:', error)
uni.showToast({
title: '缓存测试失败',
icon: 'none'
})
}
},
// 清除缓存
clearCache() {
dictUtil.clearCache()
this.cacheResult = null
uni.showToast({
title: '缓存已清除',
icon: 'success'
})
},
// 获取字典显示名称
getDictDisplayName(key) {
const nameMap = {
'SourceChannel': '来源渠道',
'source': '来源',
'customer_purchasing_power': '购买力',
'preliminarycustomerintention': '意向度',
'cognitive_concept': '认知理念',
'kh_status': '客户状态',
'decision_maker': '决策人',
'distance': '距离'
}
return nameMap[key] || key
}
}
}
</script>
<style lang="scss" scoped>
.container {
padding: 20rpx;
background: #f5f5f5;
min-height: 100vh;
}
.header {
background: #fff;
padding: 30rpx;
border-radius: 12rpx;
margin-bottom: 20rpx;
text-align: center;
.title {
font-size: 36rpx;
font-weight: 600;
color: #333;
display: block;
margin-bottom: 10rpx;
}
.subtitle {
font-size: 26rpx;
color: #666;
display: block;
}
}
.performance-section, .cache-section, .data-section, .usage-section {
background: #fff;
border-radius: 12rpx;
padding: 30rpx;
margin-bottom: 20rpx;
}
.section-title {
font-size: 32rpx;
font-weight: 600;
color: #333;
margin-bottom: 20rpx;
border-left: 4rpx solid #29d3b4;
padding-left: 16rpx;
}
.test-item {
margin-bottom: 30rpx;
padding: 20rpx;
background: #f8f9fa;
border-radius: 8rpx;
&:last-child {
margin-bottom: 0;
}
}
.test-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15rpx;
.test-name {
font-size: 28rpx;
font-weight: 500;
color: #333;
}
.test-btn {
padding: 12rpx 24rpx;
border-radius: 6rpx;
border: none;
font-size: 24rpx;
color: #fff;
&.old-style {
background: #ff6b6b;
}
&.new-style {
background: #29d3b4;
}
&:disabled {
opacity: 0.6;
}
}
}
.test-result {
display: flex;
flex-direction: column;
gap: 8rpx;
.result-text {
font-size: 24rpx;
color: #666;
}
.improvement {
font-size: 26rpx;
color: #29d3b4;
font-weight: 600;
}
}
.cache-controls {
display: flex;
gap: 20rpx;
margin-bottom: 20rpx;
.cache-btn {
flex: 1;
padding: 16rpx;
border-radius: 8rpx;
border: none;
font-size: 26rpx;
color: #fff;
background: #29d3b4;
&.clear {
background: #ff6b6b;
}
}
}
.cache-result {
display: flex;
flex-direction: column;
gap: 8rpx;
.cache-text {
font-size: 24rpx;
color: #666;
}
}
.dict-tabs {
display: flex;
flex-wrap: wrap;
gap: 10rpx;
margin-bottom: 20rpx;
.tab-item {
padding: 12rpx 20rpx;
background: #f0f0f0;
border-radius: 20rpx;
font-size: 24rpx;
color: #666;
&.active {
background: #29d3b4;
color: #fff;
}
}
}
.dict-content {
height: 400rpx;
border: 1rpx solid #eee;
border-radius: 8rpx;
}
.dict-items {
padding: 20rpx;
}
.dict-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16rpx 0;
border-bottom: 1rpx solid #f0f0f0;
&:last-child {
border-bottom: none;
}
.item-name {
font-size: 26rpx;
color: #333;
flex: 1;
}
.item-value {
font-size: 24rpx;
color: #666;
margin-left: 20rpx;
}
}
.empty-state {
padding: 60rpx;
text-align: center;
color: #999;
font-size: 26rpx;
}
.usage-content {
display: flex;
flex-direction: column;
gap: 12rpx;
.usage-text {
font-size: 26rpx;
color: #666;
line-height: 1.6;
}
}
</style>