优化:模拟数据显示优化
This commit is contained in:
parent
748544c883
commit
9d92b4cbfe
7
.browserslistrc
Normal file
7
.browserslistrc
Normal file
@ -0,0 +1,7 @@
|
||||
# 兼容国产手机、微信内置浏览器、旧版 Android WebView
|
||||
>= 0.5%
|
||||
last 2 versions
|
||||
not dead
|
||||
Chrome >= 64
|
||||
Android >= 5
|
||||
iOS >= 11
|
||||
1
.env
1
.env
@ -4,6 +4,7 @@
|
||||
|
||||
# VITE_USE_MOCK_DATA=false # 全部关闭 mock
|
||||
# SSH 部署(npm run deploy),可选覆盖
|
||||
VITE_USE_MOCK_WALLET=false # 关闭钱包 mock
|
||||
# DEPLOY_HOST=38.246.250.238
|
||||
# DEPLOY_USER=root
|
||||
# DEPLOY_PATH=/opt/1panel/www/sites/pm.xtrader.vip/index
|
||||
|
||||
@ -8,10 +8,10 @@
|
||||
|
||||
## 核心能力
|
||||
|
||||
- **分类导航**:三层级分类选择(一级 Tab、二级图标、三级 Tab)
|
||||
- **分类导航**:三层级分类选择(一级 Tab、二级文字标签、三级 Tab)
|
||||
- **事件列表**:卡片式展示,支持下拉刷新、触底加载
|
||||
- **搜索**:可按关键词搜索事件
|
||||
- **分类筛选**:选中分类后,自动提取所有层级节点的 `tagIds` 进行事件筛选
|
||||
- **分类筛选**:选中分类后,自动提取所有层级节点的 `tagIds` 进行事件筛选;切换语言时重新请求分类接口并刷新列表
|
||||
- **Footer**:使用 `<Footer />` 组件,包含品牌、链接、语言选择、免责声明
|
||||
|
||||
## 数据流
|
||||
|
||||
72
package-lock.json
generated
72
package-lock.json
generated
@ -31,6 +31,7 @@
|
||||
"@vue/eslint-config-typescript": "^14.6.0",
|
||||
"@vue/test-utils": "^2.4.6",
|
||||
"@vue/tsconfig": "^0.8.1",
|
||||
"autoprefixer": "^10.4.27",
|
||||
"eslint": "^9.39.2",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-plugin-oxlint": "~1.42.0",
|
||||
@ -40,6 +41,7 @@
|
||||
"jsdom": "^27.4.0",
|
||||
"npm-run-all2": "^8.0.4",
|
||||
"oxlint": "~1.42.0",
|
||||
"postcss": "^8.5.8",
|
||||
"prettier": "3.8.1",
|
||||
"typescript": "~5.9.3",
|
||||
"vite": "^7.3.1",
|
||||
@ -3307,6 +3309,43 @@
|
||||
"url": "https://github.com/sponsors/sxzz"
|
||||
}
|
||||
},
|
||||
"node_modules/autoprefixer": {
|
||||
"version": "10.4.27",
|
||||
"resolved": "https://registry.npmmirror.com/autoprefixer/-/autoprefixer-10.4.27.tgz",
|
||||
"integrity": "sha512-NP9APE+tO+LuJGn7/9+cohklunJsXWiaWEfV3si4Gi/XHDwVNgkwr1J3RQYFIvPy76GmJ9/bW8vyoU1LcxwKHA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/postcss/"
|
||||
},
|
||||
{
|
||||
"type": "tidelift",
|
||||
"url": "https://tidelift.com/funding/github/npm/autoprefixer"
|
||||
},
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"browserslist": "^4.28.1",
|
||||
"caniuse-lite": "^1.0.30001774",
|
||||
"fraction.js": "^5.3.4",
|
||||
"picocolors": "^1.1.1",
|
||||
"postcss-value-parser": "^4.2.0"
|
||||
},
|
||||
"bin": {
|
||||
"autoprefixer": "bin/autoprefixer"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10 || ^12 || >=14"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"postcss": "^8.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/available-typed-arrays": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmmirror.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
|
||||
@ -3715,9 +3754,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001767",
|
||||
"resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001767.tgz",
|
||||
"integrity": "sha512-34+zUAMhSH+r+9eKmYG+k2Rpt8XttfE4yXAjoZvkAPs15xcYQhyBYdalJ65BzivAvGRMViEjy6oKr/S91loekQ==",
|
||||
"version": "1.0.30001780",
|
||||
"resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001780.tgz",
|
||||
"integrity": "sha512-llngX0E7nQci5BPJDqoZSbuZ5Bcs9F5db7EtgfwBerX9XGtkkiO4NwfDDIRzHTTwcYC8vC7bmeUEPGrKlR/TkQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@ -5042,6 +5081,20 @@
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/fraction.js": {
|
||||
"version": "5.3.4",
|
||||
"resolved": "https://registry.npmmirror.com/fraction.js/-/fraction.js-5.3.4.tgz",
|
||||
"integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/rawify"
|
||||
}
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.2.tgz",
|
||||
@ -6867,9 +6920,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/postcss": {
|
||||
"version": "8.5.6",
|
||||
"resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.6.tgz",
|
||||
"integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
|
||||
"version": "8.5.8",
|
||||
"resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.8.tgz",
|
||||
"integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
@ -6908,6 +6961,13 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/postcss-value-parser": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmmirror.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
|
||||
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/prelude-ls": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.2.1.tgz",
|
||||
|
||||
@ -41,6 +41,7 @@
|
||||
"@vue/eslint-config-typescript": "^14.6.0",
|
||||
"@vue/test-utils": "^2.4.6",
|
||||
"@vue/tsconfig": "^0.8.1",
|
||||
"autoprefixer": "^10.4.27",
|
||||
"eslint": "^9.39.2",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-plugin-oxlint": "~1.42.0",
|
||||
@ -50,6 +51,7 @@
|
||||
"jsdom": "^27.4.0",
|
||||
"npm-run-all2": "^8.0.4",
|
||||
"oxlint": "~1.42.0",
|
||||
"postcss": "^8.5.8",
|
||||
"prettier": "3.8.1",
|
||||
"typescript": "~5.9.3",
|
||||
"vite": "^7.3.1",
|
||||
|
||||
5
postcss.config.js
Normal file
5
postcss.config.js
Normal file
@ -0,0 +1,5 @@
|
||||
export default {
|
||||
plugins: {
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
||||
@ -39,8 +39,9 @@ export function toLwcData(points: [number, number][]): { time: UTCTimestamp; val
|
||||
for (const [t, v] of sorted) {
|
||||
const utcSec = t >= 1e12 ? t / 1000 : t
|
||||
const time = timeToLocal(utcSec)
|
||||
if (result.length > 0 && result[result.length - 1].time === time) {
|
||||
result[result.length - 1].value = v
|
||||
const last = result[result.length - 1]
|
||||
if (last && last.time === time) {
|
||||
last.value = v
|
||||
} else {
|
||||
result.push({ time, value: v })
|
||||
}
|
||||
|
||||
@ -116,13 +116,6 @@
|
||||
:class="{ 'home-category-icon-item--active': layerActiveValues[1] === item.id }"
|
||||
@click="onCategorySelect(1, item.id)"
|
||||
>
|
||||
<v-icon
|
||||
size="24"
|
||||
class="home-category-icon"
|
||||
:color="resolveCategoryIconColor(item) ?? 'grey'"
|
||||
>
|
||||
{{ item.icon || DEFAULT_CATEGORY_ICON }}
|
||||
</v-icon>
|
||||
<span class="home-category-icon-label">{{ item.label }}</span>
|
||||
</button>
|
||||
</div>
|
||||
@ -243,11 +236,9 @@ import {
|
||||
type EventCardItem,
|
||||
} from '../api/event'
|
||||
import {
|
||||
DEFAULT_CATEGORY_ICON,
|
||||
enrichWithIcons,
|
||||
getPmTagMain,
|
||||
MOCK_CATEGORY_TREE,
|
||||
resolveCategoryIconColor,
|
||||
type CategoryTreeNode,
|
||||
} from '../api/category'
|
||||
import { USE_MOCK_CATEGORY } from '../config/mock'
|
||||
@ -480,13 +471,49 @@ function onCardOpenTrade(
|
||||
const toastStore = useToastStore()
|
||||
const localeStore = useLocaleStore()
|
||||
|
||||
// 监听语言切换,语言变化时重新加载事件列表
|
||||
/** 加载分类树(接口或 mock),完成后初始化选中并触发事件列表加载 */
|
||||
async function loadCategory() {
|
||||
function loadEventListAfterCategoryReady() {
|
||||
const cached = getEventListCache()
|
||||
if (cached && cached.list.length > 0) {
|
||||
eventList.value = cached.list
|
||||
eventPage.value = cached.page
|
||||
eventTotal.value = cached.total
|
||||
eventPageSize.value = cached.pageSize
|
||||
} else {
|
||||
loadEvents(1, false)
|
||||
}
|
||||
}
|
||||
|
||||
if (USE_MOCK_CATEGORY) {
|
||||
categoryTree.value = enrichWithIcons(MOCK_CATEGORY_TREE)
|
||||
initCategorySelection()
|
||||
loadEventListAfterCategoryReady()
|
||||
} else {
|
||||
try {
|
||||
const res = await getPmTagMain()
|
||||
if (res.code === 0 || res.code === 200) {
|
||||
const data = res.data
|
||||
categoryTree.value =
|
||||
Array.isArray(data) && data.length > 0 ? data : enrichWithIcons(MOCK_CATEGORY_TREE)
|
||||
} else {
|
||||
categoryTree.value = enrichWithIcons(MOCK_CATEGORY_TREE)
|
||||
}
|
||||
} catch {
|
||||
categoryTree.value = enrichWithIcons(MOCK_CATEGORY_TREE)
|
||||
}
|
||||
initCategorySelection()
|
||||
loadEventListAfterCategoryReady()
|
||||
}
|
||||
}
|
||||
|
||||
// 监听语言切换,语言变化时重新请求分类并加载事件列表
|
||||
watch(
|
||||
() => localeStore.currentLocale,
|
||||
() => {
|
||||
clearEventListCache()
|
||||
eventPage.value = 1
|
||||
loadEvents(1, false, activeSearchKeyword.value)
|
||||
loadCategory()
|
||||
},
|
||||
)
|
||||
|
||||
@ -605,41 +632,7 @@ function checkScrollLoad() {
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
/** 分类树就绪后加载列表(确保 activeTagIds 已计算,与下拉刷新参数一致) */
|
||||
function loadEventListAfterCategoryReady() {
|
||||
const cached = getEventListCache()
|
||||
if (cached && cached.list.length > 0) {
|
||||
eventList.value = cached.list
|
||||
eventPage.value = cached.page
|
||||
eventTotal.value = cached.total
|
||||
eventPageSize.value = cached.pageSize
|
||||
} else {
|
||||
loadEvents(1, false)
|
||||
}
|
||||
}
|
||||
|
||||
if (USE_MOCK_CATEGORY) {
|
||||
categoryTree.value = enrichWithIcons(MOCK_CATEGORY_TREE)
|
||||
initCategorySelection()
|
||||
loadEventListAfterCategoryReady()
|
||||
} else {
|
||||
getPmTagMain()
|
||||
.then((res) => {
|
||||
if (res.code === 0 || res.code === 200) {
|
||||
const data = res.data
|
||||
categoryTree.value = Array.isArray(data) && data.length > 0 ? data : enrichWithIcons(MOCK_CATEGORY_TREE)
|
||||
} else {
|
||||
categoryTree.value = enrichWithIcons(MOCK_CATEGORY_TREE)
|
||||
}
|
||||
initCategorySelection()
|
||||
loadEventListAfterCategoryReady()
|
||||
})
|
||||
.catch(() => {
|
||||
categoryTree.value = enrichWithIcons(MOCK_CATEGORY_TREE)
|
||||
initCategorySelection()
|
||||
loadEventListAfterCategoryReady()
|
||||
})
|
||||
}
|
||||
loadCategory()
|
||||
nextTick(() => {
|
||||
const sentinel = sentinelRef.value
|
||||
if (sentinel) {
|
||||
@ -996,15 +989,15 @@ onActivated(() => {
|
||||
}
|
||||
|
||||
.home-category-layer--icon {
|
||||
padding: 12px 16px;
|
||||
padding: 6px 16px;
|
||||
}
|
||||
|
||||
.home-category-icon-row {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
gap: 8px;
|
||||
gap: 6px;
|
||||
overflow-x: auto;
|
||||
padding-bottom: 4px;
|
||||
padding-bottom: 2px;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
|
||||
@ -1015,13 +1008,12 @@ onActivated(() => {
|
||||
.home-category-icon-item {
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
min-width: 56px;
|
||||
padding: 8px 12px;
|
||||
justify-content: center;
|
||||
min-width: 44px;
|
||||
padding: 4px 10px;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
border-radius: 6px;
|
||||
background: transparent;
|
||||
color: #64748b;
|
||||
font-size: 12px;
|
||||
|
||||
@ -3,6 +3,16 @@ import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import { nodePolyfills } from 'vite-plugin-node-polyfills'
|
||||
|
||||
/** 移除 crossorigin 属性,避免部分手机浏览器加载资源异常 */
|
||||
function removeCrossorigin() {
|
||||
return {
|
||||
name: 'remove-crossorigin',
|
||||
transformIndexHtml(html: string) {
|
||||
return html.replace(/\s*crossorigin\s*/g, ' ')
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export default defineConfig({
|
||||
resolve: {
|
||||
alias: {
|
||||
@ -11,17 +21,19 @@ export default defineConfig({
|
||||
},
|
||||
plugins: [
|
||||
vue(),
|
||||
// 2. 将此插件添加到插件数组中
|
||||
nodePolyfills({
|
||||
// 为了彻底解决SIWE等库的问题,建议包含以下选项
|
||||
protocolImports: true,
|
||||
}),
|
||||
removeCrossorigin(),
|
||||
],
|
||||
// 3. 可选但推荐:显式定义 process.env 以避免其他潜在错误
|
||||
define: {
|
||||
'process.env': {},
|
||||
},
|
||||
build: {
|
||||
target: 'es2020',
|
||||
cssTarget: 'chrome64',
|
||||
},
|
||||
server: {
|
||||
host: true, // 监听 0.0.0.0,允许局域网内其他设备访问
|
||||
host: true,
|
||||
},
|
||||
})
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user