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
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>
|