24 changed files with 39459 additions and 1 deletions
@ -0,0 +1,27 @@
|
||||
<template> |
||||
<div> |
||||
<router-view /> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
onLaunch: function() { |
||||
console.log('App Launch') |
||||
}, |
||||
onShow: function() { |
||||
console.log('App Show') |
||||
}, |
||||
onHide: function() { |
||||
console.log('App Hide') |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style> |
||||
/* 全局样式 */ |
||||
page { |
||||
background-color: #f5f5f5; |
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; |
||||
} |
||||
</style> |
||||
@ -0,0 +1,11 @@
|
||||
import Vue from 'vue' |
||||
import App from './App' |
||||
|
||||
Vue.config.productionTip = false |
||||
|
||||
App.mpType = 'app' |
||||
|
||||
const app = new Vue({ |
||||
...App |
||||
}) |
||||
app.$mount() |
||||
@ -0,0 +1,63 @@
|
||||
{ |
||||
"name": "魔兽世界金币价格查询", |
||||
"appid": "", |
||||
"description": "魔兽世界各区金币价格查询小程序", |
||||
"versionName": "1.0.0", |
||||
"versionCode": 1, |
||||
"transformPx": true, |
||||
"mp-weixin": { |
||||
"appid": "", |
||||
"setting": { |
||||
"urlCheck": false, |
||||
"es6": true, |
||||
"enhance": true, |
||||
"postcss": true, |
||||
"preloadBackgroundData": false, |
||||
"minified": true, |
||||
"newFeature": false, |
||||
"coverView": true, |
||||
"nodeModules": false, |
||||
"autoAudits": false, |
||||
"showShadowRootInWxmlPanel": true, |
||||
"scopeDataCheck": false, |
||||
"uglifyFileName": true, |
||||
"checkInvalidKey": true, |
||||
"checkSiteMap": true, |
||||
"uploadWithSourceMap": true, |
||||
"compileHotReLoad": false, |
||||
"lazyloadPlaceholderEnable": false, |
||||
"useMultiFrameRuntime": true, |
||||
"useApiHook": true, |
||||
"useApiHostProcess": true, |
||||
"babelSetting": { |
||||
"ignore": [], |
||||
"disablePlugins": [], |
||||
"outputPath": "" |
||||
}, |
||||
"enableEngineNative": false, |
||||
"packNpmManually": false, |
||||
"packNpmRelationList": [], |
||||
"minifyWXSS": true, |
||||
"minifyWXML": true, |
||||
"showES6CompileOption": false, |
||||
"useIsolateContext": true, |
||||
"useCompilerV2": true, |
||||
"userConfirmedUseCompilerV2": true |
||||
}, |
||||
"usingComponents": true, |
||||
"permission": { |
||||
"scope.userLocation": { |
||||
"desc": "你的位置信息将用于获取附近的金币价格" |
||||
} |
||||
} |
||||
}, |
||||
"quickapp": {}, |
||||
"h5": { |
||||
"devServer": { |
||||
"port": 8080, |
||||
"disableHostCheck": true |
||||
}, |
||||
"title": "魔兽世界金币价格查询", |
||||
"domain": "" |
||||
} |
||||
} |
||||
@ -0,0 +1,34 @@
|
||||
{ |
||||
"pages": [ |
||||
{ |
||||
"path": "pages/gold-price/index", |
||||
"style": { |
||||
"navigationBarTitleText": "魔兽世界金币价格查询", |
||||
"navigationBarBackgroundColor": "#1989fa", |
||||
"navigationBarTextStyle": "white", |
||||
"enablePullDownRefresh": true |
||||
} |
||||
} |
||||
], |
||||
"globalStyle": { |
||||
"navigationBarBackgroundColor": "#1989fa", |
||||
"navigationBarTextStyle": "white", |
||||
"navigationBarTitleText": "魔兽世界金币价格查询", |
||||
"backgroundColor": "#F8F8F8" |
||||
}, |
||||
"uniIdRouter": {}, |
||||
"tabBar": { |
||||
"color": "#7A7E83", |
||||
"selectedColor": "#3cc51f", |
||||
"borderStyle": "black", |
||||
"backgroundColor": "#ffffff", |
||||
"list": [ |
||||
{ |
||||
"pagePath": "pages/gold-price/index", |
||||
"iconPath": "static/icon_home.png", |
||||
"selectedIconPath": "static/icon_home_selected.png", |
||||
"text": "金币价格" |
||||
} |
||||
] |
||||
} |
||||
} |
||||
@ -0,0 +1,215 @@
|
||||
<template> |
||||
<view class="container"> |
||||
<view class="header"> |
||||
<text class="title">魔兽世界金币价格查询</text> |
||||
</view> |
||||
|
||||
<view class="content"> |
||||
<!-- 铁血1区 --> |
||||
<view class="server-section"> |
||||
<view class="server-title"> |
||||
<text>铁血1区</text> |
||||
</view> |
||||
|
||||
<view class="faction-section"> |
||||
<view class="faction-title"> |
||||
<text>联盟</text> |
||||
</view> |
||||
<view class="price-table"> |
||||
<view class="table-header"> |
||||
<view class="table-cell">排名</view> |
||||
<view class="table-cell">价格</view> |
||||
<view class="table-cell">数量</view> |
||||
</view> |
||||
<view class="table-row" v-for="(price, index) in alliancePrices1" :key="index"> |
||||
<view class="table-cell">{{ index + 1 }}</view> |
||||
<view class="table-cell">{{ price.price }}</view> |
||||
<view class="table-cell">{{ price.amount }}</view> |
||||
</view> |
||||
</view> |
||||
</view> |
||||
|
||||
<view class="faction-section"> |
||||
<view class="faction-title"> |
||||
<text>部落</text> |
||||
</view> |
||||
<view class="price-table"> |
||||
<view class="table-header"> |
||||
<view class="table-cell">排名</view> |
||||
<view class="table-cell">价格</view> |
||||
<view class="table-cell">数量</view> |
||||
</view> |
||||
<view class="table-row" v-for="(price, index) in hordePrices1" :key="index"> |
||||
<view class="table-cell">{{ index + 1 }}</view> |
||||
<view class="table-cell">{{ price.price }}</view> |
||||
<view class="table-cell">{{ price.amount }}</view> |
||||
</view> |
||||
</view> |
||||
</view> |
||||
</view> |
||||
|
||||
<!-- 铁血2区 --> |
||||
<view class="server-section"> |
||||
<view class="server-title"> |
||||
<text>铁血2区</text> |
||||
</view> |
||||
|
||||
<view class="faction-section"> |
||||
<view class="faction-title"> |
||||
<text>联盟</text> |
||||
</view> |
||||
<view class="price-table"> |
||||
<view class="table-header"> |
||||
<view class="table-cell">排名</view> |
||||
<view class="table-cell">价格</view> |
||||
<view class="table-cell">数量</view> |
||||
</view> |
||||
<view class="table-row" v-for="(price, index) in alliancePrices2" :key="index"> |
||||
<view class="table-cell">{{ index + 1 }}</view> |
||||
<view class="table-cell">{{ price.price }}</view> |
||||
<view class="table-cell">{{ price.amount }}</view> |
||||
</view> |
||||
</view> |
||||
</view> |
||||
|
||||
<view class="faction-section"> |
||||
<view class="faction-title"> |
||||
<text>部落</text> |
||||
</view> |
||||
<view class="price-table"> |
||||
<view class="table-header"> |
||||
<view class="table-cell">排名</view> |
||||
<view class="table-cell">价格</view> |
||||
<view class="table-cell">数量</view> |
||||
</view> |
||||
<view class="table-row" v-for="(price, index) in hordePrices2" :key="index"> |
||||
<view class="table-cell">{{ index + 1 }}</view> |
||||
<view class="table-cell">{{ price.price }}</view> |
||||
<view class="table-cell">{{ price.amount }}</view> |
||||
</view> |
||||
</view> |
||||
</view> |
||||
</view> |
||||
</view> |
||||
</view> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
data() { |
||||
return { |
||||
// 模拟数据,后期从后端获取 |
||||
alliancePrices1: [ |
||||
{ price: '0.012元/金', amount: '100,000' }, |
||||
{ price: '0.013元/金', amount: '50,000' }, |
||||
{ price: '0.014元/金', amount: '20,000' } |
||||
], |
||||
hordePrices1: [ |
||||
{ price: '0.011元/金', amount: '150,000' }, |
||||
{ price: '0.012元/金', amount: '80,000' }, |
||||
{ price: '0.013元/金', amount: '30,000' } |
||||
], |
||||
alliancePrices2: [ |
||||
{ price: '0.015元/金', amount: '70,000' }, |
||||
{ price: '0.016元/金', amount: '40,000' }, |
||||
{ price: '0.017元/金', amount: '15,000' } |
||||
], |
||||
hordePrices2: [ |
||||
{ price: '0.014元/金', amount: '90,000' }, |
||||
{ price: '0.015元/金', amount: '50,000' }, |
||||
{ price: '0.016元/金', amount: '25,000' } |
||||
] |
||||
} |
||||
}, |
||||
onLoad() { |
||||
// 页面加载时从后端获取数据 |
||||
this.loadPriceData() |
||||
}, |
||||
methods: { |
||||
loadPriceData() { |
||||
// 后期从后端获取数据的方法 |
||||
console.log('加载价格数据...') |
||||
// 这里可以添加axios请求或者uni.request请求 |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped> |
||||
.container { |
||||
min-height: 100vh; |
||||
background-color: #f5f5f5; |
||||
} |
||||
|
||||
.header { |
||||
background-color: #1989fa; |
||||
color: white; |
||||
padding: 20rpx; |
||||
text-align: center; |
||||
} |
||||
|
||||
.title { |
||||
font-size: 36rpx; |
||||
font-weight: bold; |
||||
} |
||||
|
||||
.content { |
||||
padding: 20rpx; |
||||
} |
||||
|
||||
.server-section { |
||||
background-color: white; |
||||
border-radius: 10rpx; |
||||
padding: 20rpx; |
||||
margin-bottom: 20rpx; |
||||
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1); |
||||
} |
||||
|
||||
.server-title { |
||||
font-size: 32rpx; |
||||
font-weight: bold; |
||||
margin-bottom: 20rpx; |
||||
color: #333; |
||||
border-bottom: 2rpx solid #eee; |
||||
padding-bottom: 10rpx; |
||||
} |
||||
|
||||
.faction-section { |
||||
margin-bottom: 20rpx; |
||||
} |
||||
|
||||
.faction-title { |
||||
font-size: 28rpx; |
||||
font-weight: bold; |
||||
margin-bottom: 10rpx; |
||||
color: #666; |
||||
} |
||||
|
||||
.price-table { |
||||
border-radius: 5rpx; |
||||
overflow: hidden; |
||||
} |
||||
|
||||
.table-header { |
||||
display: flex; |
||||
background-color: #f0f0f0; |
||||
font-weight: bold; |
||||
border-bottom: 2rpx solid #eee; |
||||
} |
||||
|
||||
.table-row { |
||||
display: flex; |
||||
border-bottom: 1rpx solid #f0f0f0; |
||||
} |
||||
|
||||
.table-cell { |
||||
flex: 1; |
||||
padding: 15rpx; |
||||
text-align: center; |
||||
font-size: 24rpx; |
||||
} |
||||
|
||||
.table-row:last-child { |
||||
border-bottom: none; |
||||
} |
||||
</style> |
||||
@ -0,0 +1,23 @@
|
||||
.DS_Store |
||||
node_modules/ |
||||
unpackage/ |
||||
dist/ |
||||
|
||||
# local env files |
||||
.env.local |
||||
.env.*.local |
||||
|
||||
# Log files |
||||
npm-debug.log* |
||||
yarn-debug.log* |
||||
yarn-error.log* |
||||
|
||||
# Editor directories and files |
||||
.project |
||||
.idea |
||||
.vscode |
||||
*.suo |
||||
*.ntvs* |
||||
*.njsproj |
||||
*.sln |
||||
*.sw* |
||||
@ -0,0 +1,19 @@
|
||||
# weixin |
||||
|
||||
## Project setup |
||||
``` |
||||
npm install |
||||
``` |
||||
|
||||
### Compiles and hot-reloads for development |
||||
``` |
||||
npm run serve |
||||
``` |
||||
|
||||
### Compiles and minifies for production |
||||
``` |
||||
npm run build |
||||
``` |
||||
|
||||
### Customize configuration |
||||
See [Configuration Reference](https://cli.vuejs.org/config/). |
||||
@ -0,0 +1,81 @@
|
||||
const webpack = require('webpack') |
||||
const plugins = [] |
||||
|
||||
if (process.env.UNI_OPT_TREESHAKINGNG) { |
||||
plugins.push(require('@dcloudio/vue-cli-plugin-uni-optimize/packages/babel-plugin-uni-api/index.js')) |
||||
} |
||||
|
||||
if ( |
||||
( |
||||
process.env.UNI_PLATFORM === 'app-plus' && |
||||
process.env.UNI_USING_V8 |
||||
) || |
||||
( |
||||
process.env.UNI_PLATFORM === 'h5' && |
||||
process.env.UNI_H5_BROWSER === 'builtin' |
||||
) |
||||
) { |
||||
const path = require('path') |
||||
|
||||
const isWin = /^win/.test(process.platform) |
||||
|
||||
const normalizePath = path => (isWin ? path.replace(/\\/g, '/') : path) |
||||
|
||||
const input = normalizePath(process.env.UNI_INPUT_DIR) |
||||
try { |
||||
plugins.push([ |
||||
require('@dcloudio/vue-cli-plugin-hbuilderx/packages/babel-plugin-console'), |
||||
{ |
||||
file (file) { |
||||
file = normalizePath(file) |
||||
if (file.indexOf(input) === 0) { |
||||
return path.relative(input, file) |
||||
} |
||||
return false |
||||
} |
||||
} |
||||
]) |
||||
} catch (e) { } |
||||
} |
||||
|
||||
process.UNI_LIBRARIES = process.UNI_LIBRARIES || ['@dcloudio/uni-ui'] |
||||
process.UNI_LIBRARIES.forEach(libraryName => { |
||||
plugins.push([ |
||||
'import', |
||||
{ |
||||
'libraryName': libraryName, |
||||
'customName': (name) => { |
||||
return `${libraryName}/lib/${name}/${name}` |
||||
} |
||||
} |
||||
]) |
||||
}) |
||||
|
||||
if (process.env.UNI_PLATFORM !== 'h5') { |
||||
plugins.push('@babel/plugin-transform-runtime') |
||||
} |
||||
|
||||
const config = { |
||||
presets: [ |
||||
[ |
||||
'@vue/app', |
||||
{ |
||||
modules: webpack.version[0] > 4 ? 'auto' : 'commonjs', |
||||
useBuiltIns: process.env.UNI_PLATFORM === 'h5' ? 'usage' : 'entry' |
||||
} |
||||
] |
||||
], |
||||
plugins |
||||
} |
||||
|
||||
const UNI_H5_TEST = '**/@dcloudio/uni-h5/dist/index.umd.min.js' |
||||
if (process.env.NODE_ENV === 'production') { |
||||
config.overrides = [{ |
||||
test: UNI_H5_TEST, |
||||
compact: true, |
||||
}] |
||||
} else { |
||||
config.ignore = [UNI_H5_TEST] |
||||
} |
||||
|
||||
module.exports = config |
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,107 @@
|
||||
{ |
||||
"name": "weixin", |
||||
"version": "0.1.0", |
||||
"private": true, |
||||
"scripts": { |
||||
"serve": "npm run dev:h5", |
||||
"build": "npm run build:h5", |
||||
"build:app-plus": "cross-env NODE_ENV=production UNI_PLATFORM=app-plus vue-cli-service uni-build", |
||||
"build:custom": "cross-env NODE_ENV=production uniapp-cli custom", |
||||
"build:h5": "cross-env NODE_ENV=production UNI_PLATFORM=h5 vue-cli-service uni-build", |
||||
"build:mp-360": "cross-env NODE_ENV=production UNI_PLATFORM=mp-360 vue-cli-service uni-build", |
||||
"build:mp-alipay": "cross-env NODE_ENV=production UNI_PLATFORM=mp-alipay vue-cli-service uni-build", |
||||
"build:mp-baidu": "cross-env NODE_ENV=production UNI_PLATFORM=mp-baidu vue-cli-service uni-build", |
||||
"build:mp-harmony": "cross-env NODE_ENV=production UNI_PLATFORM=mp-harmony vue-cli-service uni-build", |
||||
"build:mp-jd": "cross-env NODE_ENV=production UNI_PLATFORM=mp-jd vue-cli-service uni-build", |
||||
"build:mp-kuaishou": "cross-env NODE_ENV=production UNI_PLATFORM=mp-kuaishou vue-cli-service uni-build", |
||||
"build:mp-lark": "cross-env NODE_ENV=production UNI_PLATFORM=mp-lark vue-cli-service uni-build", |
||||
"build:mp-qq": "cross-env NODE_ENV=production UNI_PLATFORM=mp-qq vue-cli-service uni-build", |
||||
"build:mp-toutiao": "cross-env NODE_ENV=production UNI_PLATFORM=mp-toutiao vue-cli-service uni-build", |
||||
"build:mp-weixin": "cross-env NODE_ENV=production UNI_PLATFORM=mp-weixin vue-cli-service uni-build", |
||||
"build:mp-xhs": "cross-env NODE_ENV=production UNI_PLATFORM=mp-xhs vue-cli-service uni-build", |
||||
"build:quickapp-native": "cross-env NODE_ENV=production UNI_PLATFORM=quickapp-native vue-cli-service uni-build", |
||||
"build:quickapp-webview": "cross-env NODE_ENV=production UNI_PLATFORM=quickapp-webview vue-cli-service uni-build", |
||||
"build:quickapp-webview-huawei": "cross-env NODE_ENV=production UNI_PLATFORM=quickapp-webview-huawei vue-cli-service uni-build", |
||||
"build:quickapp-webview-union": "cross-env NODE_ENV=production UNI_PLATFORM=quickapp-webview-union vue-cli-service uni-build", |
||||
"dev:app-plus": "cross-env NODE_ENV=development UNI_PLATFORM=app-plus vue-cli-service uni-build --watch", |
||||
"dev:custom": "cross-env NODE_ENV=development uniapp-cli custom", |
||||
"dev:h5": "cross-env NODE_ENV=development UNI_PLATFORM=h5 vue-cli-service uni-serve", |
||||
"dev:mp-360": "cross-env NODE_ENV=development UNI_PLATFORM=mp-360 vue-cli-service uni-build --watch", |
||||
"dev:mp-alipay": "cross-env NODE_ENV=development UNI_PLATFORM=mp-alipay vue-cli-service uni-build --watch", |
||||
"dev:mp-baidu": "cross-env NODE_ENV=development UNI_PLATFORM=mp-baidu vue-cli-service uni-build --watch", |
||||
"dev:mp-harmony": "cross-env NODE_ENV=development UNI_PLATFORM=mp-harmony vue-cli-service uni-build --watch", |
||||
"dev:mp-jd": "cross-env NODE_ENV=development UNI_PLATFORM=mp-jd vue-cli-service uni-build --watch", |
||||
"dev:mp-kuaishou": "cross-env NODE_ENV=development UNI_PLATFORM=mp-kuaishou vue-cli-service uni-build --watch", |
||||
"dev:mp-lark": "cross-env NODE_ENV=development UNI_PLATFORM=mp-lark vue-cli-service uni-build --watch", |
||||
"dev:mp-qq": "cross-env NODE_ENV=development UNI_PLATFORM=mp-qq vue-cli-service uni-build --watch", |
||||
"dev:mp-toutiao": "cross-env NODE_ENV=development UNI_PLATFORM=mp-toutiao vue-cli-service uni-build --watch", |
||||
"dev:mp-weixin": "cross-env NODE_ENV=development UNI_PLATFORM=mp-weixin vue-cli-service uni-build --watch", |
||||
"dev:mp-xhs": "cross-env NODE_ENV=development UNI_PLATFORM=mp-xhs vue-cli-service uni-build --watch", |
||||
"dev:quickapp-native": "cross-env NODE_ENV=development UNI_PLATFORM=quickapp-native vue-cli-service uni-build --watch", |
||||
"dev:quickapp-webview": "cross-env NODE_ENV=development UNI_PLATFORM=quickapp-webview vue-cli-service uni-build --watch", |
||||
"dev:quickapp-webview-huawei": "cross-env NODE_ENV=development UNI_PLATFORM=quickapp-webview-huawei vue-cli-service uni-build --watch", |
||||
"dev:quickapp-webview-union": "cross-env NODE_ENV=development UNI_PLATFORM=quickapp-webview-union vue-cli-service uni-build --watch", |
||||
"info": "node node_modules/@dcloudio/vue-cli-plugin-uni/commands/info.js", |
||||
"serve:quickapp-native": "node node_modules/@dcloudio/uni-quickapp-native/bin/serve.js", |
||||
"test:android": "cross-env UNI_PLATFORM=app-plus UNI_OS_NAME=android jest -i", |
||||
"test:h5": "cross-env UNI_PLATFORM=h5 jest -i", |
||||
"test:ios": "cross-env UNI_PLATFORM=app-plus UNI_OS_NAME=ios jest -i", |
||||
"test:mp-baidu": "cross-env UNI_PLATFORM=mp-baidu jest -i", |
||||
"test:mp-weixin": "cross-env UNI_PLATFORM=mp-weixin jest -i" |
||||
}, |
||||
"dependencies": { |
||||
"@dcloudio/uni-app": "^2.0.2-4080720251210002", |
||||
"@dcloudio/uni-app-plus": "^2.0.2-4080720251210002", |
||||
"@dcloudio/uni-h5": "^2.0.2-4080720251210002", |
||||
"@dcloudio/uni-i18n": "^2.0.2-4080720251210002", |
||||
"@dcloudio/uni-mp-360": "^2.0.2-4080720251210002", |
||||
"@dcloudio/uni-mp-alipay": "^2.0.2-4080720251210002", |
||||
"@dcloudio/uni-mp-baidu": "^2.0.2-4080720251210002", |
||||
"@dcloudio/uni-mp-harmony": "^2.0.2-4080720251210002", |
||||
"@dcloudio/uni-mp-jd": "^2.0.2-4080720251210002", |
||||
"@dcloudio/uni-mp-kuaishou": "^2.0.2-4080720251210002", |
||||
"@dcloudio/uni-mp-lark": "^2.0.2-4080720251210002", |
||||
"@dcloudio/uni-mp-qq": "^2.0.2-4080720251210002", |
||||
"@dcloudio/uni-mp-toutiao": "^2.0.2-4080720251210002", |
||||
"@dcloudio/uni-mp-vue": "^2.0.2-4080720251210002", |
||||
"@dcloudio/uni-mp-weixin": "^2.0.2-4080720251210002", |
||||
"@dcloudio/uni-mp-xhs": "^2.0.2-4080720251210002", |
||||
"@dcloudio/uni-quickapp-native": "^2.0.2-4080720251210002", |
||||
"@dcloudio/uni-quickapp-webview": "^2.0.2-4080720251210002", |
||||
"@dcloudio/uni-stacktracey": "^2.0.2-4080720251210002", |
||||
"@dcloudio/uni-stat": "^2.0.2-4080720251210002", |
||||
"@vue/shared": "^3.0.0", |
||||
"core-js": "^3.8.3", |
||||
"flyio": "^0.6.2", |
||||
"vue": ">= 2.6.14 < 2.7", |
||||
"vuex": "^3.2.0" |
||||
}, |
||||
"devDependencies": { |
||||
"@dcloudio/types": "^3.3.2", |
||||
"@dcloudio/uni-automator": "^2.0.2-4080720251210002", |
||||
"@dcloudio/uni-cli-i18n": "^2.0.2-4080720251210002", |
||||
"@dcloudio/uni-cli-shared": "^2.0.2-4080720251210002", |
||||
"@dcloudio/uni-helper-json": "*", |
||||
"@dcloudio/uni-migration": "^2.0.2-4080720251210002", |
||||
"@dcloudio/uni-template-compiler": "^2.0.2-4080720251210002", |
||||
"@dcloudio/vue-cli-plugin-hbuilderx": "^2.0.2-4080720251210002", |
||||
"@dcloudio/vue-cli-plugin-uni": "^2.0.2-4080720251210002", |
||||
"@dcloudio/vue-cli-plugin-uni-optimize": "^2.0.2-4080720251210002", |
||||
"@dcloudio/webpack-uni-mp-loader": "^2.0.2-4080720251210002", |
||||
"@dcloudio/webpack-uni-pages-loader": "^2.0.2-4080720251210002", |
||||
"@vue/cli-plugin-babel": "~5.0.0", |
||||
"@vue/cli-service": "~5.0.0", |
||||
"babel-plugin-import": "^1.11.0", |
||||
"cross-env": "^7.0.2", |
||||
"jest": "^25.4.0", |
||||
"postcss-comment": "^2.0.0", |
||||
"vue-template-compiler": ">= 2.6.14 < 2.7" |
||||
}, |
||||
"browserslist": [ |
||||
"Android >= 4.4", |
||||
"ios >= 9" |
||||
], |
||||
"uni-app": { |
||||
"scripts": {} |
||||
} |
||||
} |
||||
@ -0,0 +1,27 @@
|
||||
const path = require('path') |
||||
const webpack = require('webpack') |
||||
const config = { |
||||
parser: require('postcss-comment'), |
||||
plugins: [ |
||||
require('postcss-import')({ |
||||
resolve (id, basedir, importOptions) { |
||||
if (id.startsWith('~@/')) { |
||||
return path.resolve(process.env.UNI_INPUT_DIR, id.substr(3)) |
||||
} else if (id.startsWith('@/')) { |
||||
return path.resolve(process.env.UNI_INPUT_DIR, id.substr(2)) |
||||
} else if (id.startsWith('/') && !id.startsWith('//')) { |
||||
return path.resolve(process.env.UNI_INPUT_DIR, id.substr(1)) |
||||
} |
||||
return id |
||||
} |
||||
}), |
||||
require('autoprefixer')({ |
||||
remove: process.env.UNI_PLATFORM !== 'h5' |
||||
}), |
||||
require('@dcloudio/vue-cli-plugin-uni/packages/postcss') |
||||
] |
||||
} |
||||
if (webpack.version[0] > 4) { |
||||
delete config.parser |
||||
} |
||||
module.exports = config |
||||
@ -0,0 +1,25 @@
|
||||
<!DOCTYPE html> |
||||
<html lang="zh-CN"> |
||||
|
||||
<head> |
||||
<meta charset="utf-8"> |
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge"> |
||||
<title> |
||||
<%= htmlWebpackPlugin.options.title %> |
||||
</title> |
||||
<script> |
||||
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') || CSS.supports('top: constant(a)')) |
||||
document.write('<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' + (coverSupport ? ', viewport-fit=cover' : '') + '" />') |
||||
</script> |
||||
<link rel="stylesheet" href="<%= BASE_URL %>static/index.<%= VUE_APP_INDEX_CSS_HASH %>.css" /> |
||||
</head> |
||||
|
||||
<body> |
||||
<noscript> |
||||
<strong>Please enable JavaScript to continue.</strong> |
||||
</noscript> |
||||
<div id="app"></div> |
||||
<!-- built files will be auto injected --> |
||||
</body> |
||||
|
||||
</html> |
||||
@ -0,0 +1,11 @@
|
||||
/// <reference types='@dcloudio/types' />
|
||||
import Vue from 'vue' |
||||
declare module "vue/types/options" { |
||||
type Hooks = App.AppInstance & Page.PageInstance; |
||||
interface ComponentOptions<V extends Vue> extends Hooks { |
||||
/** |
||||
* 组件类型 |
||||
*/ |
||||
mpType?: string; |
||||
} |
||||
} |
||||
@ -0,0 +1,4 @@
|
||||
declare module "*.vue" { |
||||
import Vue from 'vue' |
||||
export default Vue |
||||
} |
||||
@ -0,0 +1,17 @@
|
||||
<script> |
||||
export default { |
||||
onLaunch: function() { |
||||
console.log('App Launch') |
||||
}, |
||||
onShow: function() { |
||||
console.log('App Show') |
||||
}, |
||||
onHide: function() { |
||||
console.log('App Hide') |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style> |
||||
/*每个页面公共css */ |
||||
</style> |
||||
@ -0,0 +1,12 @@
|
||||
import Vue from 'vue' |
||||
import App from './App' |
||||
import './uni.promisify.adaptor' |
||||
|
||||
Vue.config.productionTip = false |
||||
|
||||
App.mpType = 'app' |
||||
|
||||
const app = new Vue({ |
||||
...App |
||||
}) |
||||
app.$mount() |
||||
@ -0,0 +1,75 @@
|
||||
{ |
||||
"name": "魔兽世界金币价格查询", |
||||
"appid": "", |
||||
"description": "魔兽世界金币价格查询小程序", |
||||
"versionName": "1.0.0", |
||||
"versionCode": "100", |
||||
"transformPx": false, |
||||
"app-plus": { /* 5+App特有相关 */ |
||||
"usingComponents": true, |
||||
"splashscreen": { |
||||
"alwaysShowBeforeRender": true, |
||||
"waiting": true, |
||||
"autoclose": true, |
||||
"delay": 0 |
||||
}, |
||||
"modules": { /* 模块配置 */ |
||||
|
||||
}, |
||||
"distribute": { /* 应用发布信息 */ |
||||
"android": { /* android打包配置 */ |
||||
"permissions": ["<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>", |
||||
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>", |
||||
"<uses-permission android:name=\"android.permission.READ_CONTACTS\"/>", |
||||
"<uses-permission android:name=\"android.permission.VIBRATE\"/>", |
||||
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>", |
||||
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>", |
||||
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>", |
||||
"<uses-permission android:name=\"android.permission.WRITE_CONTACTS\"/>", |
||||
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>", |
||||
"<uses-permission android:name=\"android.permission.CAMERA\"/>", |
||||
"<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>", |
||||
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>", |
||||
"<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>", |
||||
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>", |
||||
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>", |
||||
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>", |
||||
"<uses-permission android:name=\"android.permission.CALL_PHONE\"/>", |
||||
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>", |
||||
"<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>", |
||||
"<uses-feature android:name=\"android.hardware.camera\"/>", |
||||
"<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>", |
||||
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>" |
||||
] |
||||
}, |
||||
"ios": { /* ios打包配置 */ |
||||
|
||||
}, |
||||
"sdkConfigs": { /* SDK配置 */ |
||||
|
||||
} |
||||
} |
||||
}, |
||||
"quickapp": { /* 快应用特有相关 */ |
||||
|
||||
}, |
||||
"mp-weixin": { /* 微信小程序特有相关 */ |
||||
"appid": "", |
||||
"setting": { |
||||
"urlCheck": false |
||||
}, |
||||
"usingComponents": true |
||||
}, |
||||
"mp-alipay" : { |
||||
"usingComponents" : true |
||||
}, |
||||
"mp-baidu" : { |
||||
"usingComponents" : true |
||||
}, |
||||
"mp-toutiao" : { |
||||
"usingComponents" : true |
||||
}, |
||||
"mp-qq" : { |
||||
"usingComponents" : true |
||||
} |
||||
} |
||||
@ -0,0 +1,38 @@
|
||||
{ |
||||
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages |
||||
{ |
||||
"path": "pages/index/index", |
||||
"style": { |
||||
"navigationBarTitleText": "当前金价" |
||||
} |
||||
}, |
||||
{ |
||||
"path": "pages/chart/chart", |
||||
"style": { |
||||
"navigationBarTitleText": "价格走势图" |
||||
} |
||||
} |
||||
], |
||||
"globalStyle": { |
||||
"navigationBarTextStyle": "black", |
||||
"navigationBarTitleText": "魔兽世界金币价格查询", |
||||
"navigationBarBackgroundColor": "#F8F8F8", |
||||
"backgroundColor": "#F8F8F8" |
||||
}, |
||||
"tabBar": { |
||||
"color": "#666666", |
||||
"selectedColor": "#1989fa", |
||||
"backgroundColor": "#ffffff", |
||||
"borderStyle": "black", |
||||
"list": [ |
||||
{ |
||||
"pagePath": "pages/index/index", |
||||
"text": "当前金价" |
||||
}, |
||||
{ |
||||
"pagePath": "pages/chart/chart", |
||||
"text": "价格走势图" |
||||
} |
||||
] |
||||
} |
||||
} |
||||
@ -0,0 +1,623 @@
|
||||
<template> |
||||
<view class="chart-container"> |
||||
<text class="title">价格走势图</text> |
||||
<!-- 悬浮筛选按钮 --> |
||||
<view class="floating-filter-btn" @click="showFilter = true"> |
||||
<text>筛选</text> |
||||
</view> |
||||
|
||||
<!-- 筛选面板 --> |
||||
<view class="filter-panel" v-if="showFilter"> |
||||
<view class="filter-header"> |
||||
<text class="filter-title">选择关注的区服和阵营</text> |
||||
<view class="close-btn" @click="showFilter = false">关闭</view> |
||||
</view> |
||||
<view class="filter-content"> |
||||
<checkbox-group @change="handleCheckboxChange"> |
||||
<view class="server-group" v-for="server in allServers" :key="server.id"> |
||||
<view class="server-title">{{ server.name }}</view> |
||||
<view class="faction-items"> |
||||
<view class="filter-item" v-for="faction in server.factions" :key="faction.id"> |
||||
<checkbox :value="faction.id" :checked="selectedFactions.includes(faction.id)"> |
||||
{{ faction.name }} |
||||
</checkbox> |
||||
</view> |
||||
</view> |
||||
</view> |
||||
</checkbox-group> |
||||
</view> |
||||
<view class="filter-footer"> |
||||
<view class="cancel-btn" @click="showFilter = false">取消</view> |
||||
<view class="save-btn" @click="saveFilter">保存</view> |
||||
</view> |
||||
</view> |
||||
|
||||
<view class="chart-header"> |
||||
<!-- 时间筛选 --> |
||||
<view class="time-filter"> |
||||
<view class="filter-item" :class="{ active: timeFilter === 'day' }" @click="timeFilter = 'day'"> |
||||
<text>天</text> |
||||
</view> |
||||
<view class="filter-item" :class="{ active: timeFilter === 'hour' }" @click="timeFilter = 'hour'"> |
||||
<text>时</text> |
||||
</view> |
||||
<view class="filter-item" :class="{ active: timeFilter === 'week' }" @click="timeFilter = 'week'"> |
||||
<text>周</text> |
||||
</view> |
||||
</view> |
||||
</view> |
||||
<view class="chart-content"> |
||||
<!-- 价格走势图区域 --> |
||||
<!-- 铁血1区 --> |
||||
<view v-if="isServerSelected('tx1')"> |
||||
<view class="chart-item" v-if="isFactionSelected('tx1-alliance')"> |
||||
<text class="chart-title">铁血1区 - 联盟</text> |
||||
<canvas canvas-id="tx1AllianceChart" class="chart-canvas"></canvas> |
||||
</view> |
||||
|
||||
<view class="chart-item" v-if="isFactionSelected('tx1-horde')"> |
||||
<text class="chart-title">铁血1区 - 部落</text> |
||||
<canvas canvas-id="tx1HordeChart" class="chart-canvas"></canvas> |
||||
</view> |
||||
</view> |
||||
|
||||
<!-- 铁血2区 --> |
||||
<view v-if="isServerSelected('tx2')"> |
||||
<view class="chart-item" v-if="isFactionSelected('tx2-alliance')"> |
||||
<text class="chart-title">铁血2区 - 联盟</text> |
||||
<canvas canvas-id="tx2AllianceChart" class="chart-canvas"></canvas> |
||||
</view> |
||||
|
||||
<view class="chart-item" v-if="isFactionSelected('tx2-horde')"> |
||||
<text class="chart-title">铁血2区 - 部落</text> |
||||
<canvas canvas-id="tx2HordeChart" class="chart-canvas"></canvas> |
||||
</view> |
||||
</view> |
||||
|
||||
<!-- 时光1区 --> |
||||
<view v-if="isServerSelected('sg1')"> |
||||
<view class="chart-item" v-if="isFactionSelected('sg1-alliance')"> |
||||
<text class="chart-title">时光1区 - 联盟</text> |
||||
<canvas canvas-id="sg1AllianceChart" class="chart-canvas"></canvas> |
||||
</view> |
||||
|
||||
<view class="chart-item" v-if="isFactionSelected('sg1-horde')"> |
||||
<text class="chart-title">时光1区 - 部落</text> |
||||
<canvas canvas-id="sg1HordeChart" class="chart-canvas"></canvas> |
||||
</view> |
||||
</view> |
||||
</view> |
||||
</view> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
data() { |
||||
return { |
||||
timeFilter: 'day', // day, hour, week |
||||
showFilter: false, |
||||
// 修改数据结构,支持服务器和阵营的两级筛选 |
||||
allServers: [ |
||||
{ |
||||
id: 'tx1', |
||||
name: '铁血1区', |
||||
factions: [ |
||||
{ id: 'tx1-alliance', name: '联盟', serverId: 'tx1' }, |
||||
{ id: 'tx1-horde', name: '部落', serverId: 'tx1' } |
||||
] |
||||
}, |
||||
{ |
||||
id: 'tx2', |
||||
name: '铁血2区', |
||||
factions: [ |
||||
{ id: 'tx2-alliance', name: '联盟', serverId: 'tx2' }, |
||||
{ id: 'tx2-horde', name: '部落', serverId: 'tx2' } |
||||
] |
||||
}, |
||||
{ |
||||
id: 'sg1', |
||||
name: '时光1区', |
||||
factions: [ |
||||
{ id: 'sg1-alliance', name: '联盟', serverId: 'sg1' }, |
||||
{ id: 'sg1-horde', name: '部落', serverId: 'sg1' } |
||||
] |
||||
} |
||||
], |
||||
selectedFactions: [], |
||||
// 模拟价格历史数据(元/1000金) |
||||
chartData: { |
||||
tx1Alliance: [], |
||||
tx1Horde: [], |
||||
tx2Alliance: [], |
||||
tx2Horde: [], |
||||
sg1Alliance: [], |
||||
sg1Horde: [] |
||||
} |
||||
}; |
||||
}, |
||||
onLoad() { |
||||
// 页面加载时从缓存中读取用户选择的阵营 |
||||
this.loadSelectedFactions(); |
||||
// 加载走势图数据 |
||||
this.generateMockData(); |
||||
// 初始绘制图表 |
||||
// 注意:需要等待DOM渲染完成后才能获取canvas尺寸 |
||||
}, |
||||
onReady() { |
||||
// 确保DOM渲染完成后绘制图表 |
||||
this.$nextTick(() => { |
||||
this.drawCharts(); |
||||
}); |
||||
}, |
||||
watch: { |
||||
// 监听时间筛选变化,重新绘制图表 |
||||
timeFilter: function() { |
||||
this.generateMockData(); |
||||
this.$nextTick(() => { |
||||
this.drawCharts(); |
||||
}); |
||||
} |
||||
}, |
||||
methods: { |
||||
// 加载用户选择的阵营 |
||||
loadSelectedFactions() { |
||||
const selected = uni.getStorageSync('selectedFactions'); |
||||
if (selected && selected.length > 0) { |
||||
this.selectedFactions = selected; |
||||
} else { |
||||
// 默认全部选中 |
||||
this.selectedFactions = []; |
||||
this.allServers.forEach(server => { |
||||
server.factions.forEach(faction => { |
||||
this.selectedFactions.push(faction.id); |
||||
}); |
||||
}); |
||||
// 保存到缓存 |
||||
uni.setStorageSync('selectedFactions', this.selectedFactions); |
||||
} |
||||
}, |
||||
|
||||
// 处理checkbox变化 |
||||
handleCheckboxChange(e) { |
||||
this.selectedFactions = e.detail.value; |
||||
}, |
||||
|
||||
// 保存筛选结果 |
||||
saveFilter() { |
||||
// 确保至少选择一个阵营 |
||||
if (this.selectedFactions.length === 0) { |
||||
uni.showToast({ |
||||
title: '请至少选择一个阵营', |
||||
icon: 'none' |
||||
}); |
||||
return; |
||||
} |
||||
|
||||
// 保存到缓存 |
||||
uni.setStorageSync('selectedFactions', this.selectedFactions); |
||||
|
||||
uni.showToast({ |
||||
title: '保存成功', |
||||
icon: 'success' |
||||
}); |
||||
this.showFilter = false; |
||||
// 重新绘制图表 |
||||
this.drawCharts(); |
||||
}, |
||||
|
||||
// 检查阵营是否被选中 |
||||
isFactionSelected(factionId) { |
||||
return this.selectedFactions.includes(factionId); |
||||
}, |
||||
|
||||
// 检查服务器是否有任何阵营被选中 |
||||
isServerSelected(serverId) { |
||||
return this.allServers.some(server => |
||||
server.id === serverId && |
||||
server.factions.some(faction => |
||||
this.selectedFactions.includes(faction.id) |
||||
) |
||||
); |
||||
}, |
||||
|
||||
// 生成模拟数据 |
||||
generateMockData() { |
||||
const basePrice = 10; |
||||
const fluctuation = 2; |
||||
let dataCount = 24; // 默认按小时 |
||||
let timeStep = 1; // 默认按小时 |
||||
|
||||
if (this.timeFilter === 'day') { |
||||
dataCount = 30; // 30天 |
||||
timeStep = 24; // 按天 |
||||
} else if (this.timeFilter === 'hour') { |
||||
dataCount = 24; // 24小时 |
||||
timeStep = 1; // 按小时 |
||||
} else if (this.timeFilter === 'week') { |
||||
dataCount = 12; // 12周 |
||||
timeStep = 168; // 按周 |
||||
} |
||||
|
||||
// 生成所有区服的模拟数据 |
||||
this.chartData = { |
||||
tx1Alliance: this.generatePriceData(basePrice + 1, fluctuation, dataCount, timeStep), |
||||
tx1Horde: this.generatePriceData(basePrice + 0.5, fluctuation, dataCount, timeStep), |
||||
tx2Alliance: this.generatePriceData(basePrice + 2, fluctuation, dataCount, timeStep), |
||||
tx2Horde: this.generatePriceData(basePrice + 1.5, fluctuation, dataCount, timeStep), |
||||
sg1Alliance: this.generatePriceData(basePrice + 3, fluctuation, dataCount, timeStep), |
||||
sg1Horde: this.generatePriceData(basePrice + 2.5, fluctuation, dataCount, timeStep) |
||||
}; |
||||
|
||||
console.log('Generated mock data:', this.chartData); |
||||
}, |
||||
|
||||
// 生成单个区服的价格数据 |
||||
generatePriceData(base, fluctuation, count, timeStep) { |
||||
const data = []; |
||||
const now = new Date(); |
||||
|
||||
for (let i = count - 1; i >= 0; i--) { |
||||
const time = new Date(now.getTime() - i * timeStep * 60 * 60 * 1000); |
||||
// 生成有波动的价格 |
||||
const price = base + (Math.random() - 0.5) * fluctuation; |
||||
data.push({ |
||||
time: time, |
||||
price: parseFloat(price.toFixed(2)) |
||||
}); |
||||
} |
||||
|
||||
return data; |
||||
}, |
||||
|
||||
// 绘制所有图表 |
||||
drawCharts() { |
||||
// 只绘制用户选择的阵营的图表 |
||||
if (this.isFactionSelected('tx1-alliance')) { |
||||
this.drawChart('tx1AllianceChart', this.chartData.tx1Alliance); |
||||
} |
||||
if (this.isFactionSelected('tx1-horde')) { |
||||
this.drawChart('tx1HordeChart', this.chartData.tx1Horde); |
||||
} |
||||
if (this.isFactionSelected('tx2-alliance')) { |
||||
this.drawChart('tx2AllianceChart', this.chartData.tx2Alliance); |
||||
} |
||||
if (this.isFactionSelected('tx2-horde')) { |
||||
this.drawChart('tx2HordeChart', this.chartData.tx2Horde); |
||||
} |
||||
if (this.isFactionSelected('sg1-alliance')) { |
||||
this.drawChart('sg1AllianceChart', this.chartData.sg1Alliance); |
||||
} |
||||
if (this.isFactionSelected('sg1-horde')) { |
||||
this.drawChart('sg1HordeChart', this.chartData.sg1Horde); |
||||
} |
||||
}, |
||||
|
||||
// 绘制单个图表 |
||||
drawChart(canvasId, data) { |
||||
if (!data || data.length === 0) return; |
||||
|
||||
const ctx = uni.createCanvasContext(canvasId, this); |
||||
|
||||
// 使用像素单位而不是rpx |
||||
const canvasWidth = 350; // 画布宽度(像素) |
||||
const canvasHeight = 150; // 画布高度(像素) |
||||
const padding = 25; // 边距(像素) |
||||
|
||||
// 计算图表区域 |
||||
const chartWidth = canvasWidth - 2 * padding; |
||||
const chartHeight = canvasHeight - 2 * padding; |
||||
|
||||
// 计算价格范围 |
||||
const prices = data.map(item => item.price); |
||||
const minPrice = Math.min(...prices) - 0.5; |
||||
const maxPrice = Math.max(...prices) + 0.5; |
||||
const priceRange = maxPrice - minPrice; |
||||
|
||||
// 计算时间范围 |
||||
const times = data.map(item => item.time); |
||||
const minTime = times[0]; |
||||
const maxTime = times[times.length - 1]; |
||||
const timeRange = maxTime - minTime; |
||||
|
||||
// 绘制坐标轴 |
||||
this.drawAxes(ctx, padding, chartWidth, chartHeight, minPrice, maxPrice, data); |
||||
|
||||
// 绘制价格曲线 |
||||
this.drawPriceLine(ctx, padding, chartWidth, chartHeight, data, minPrice, maxPrice, minTime, maxTime); |
||||
|
||||
// 绘制价格点 |
||||
this.drawPricePoints(ctx, padding, chartWidth, chartHeight, data, minPrice, maxPrice, minTime, maxTime); |
||||
|
||||
// 绘制完成 |
||||
ctx.draw(); |
||||
}, |
||||
|
||||
// 绘制坐标轴 |
||||
drawAxes(ctx, padding, chartWidth, chartHeight, minPrice, maxPrice, data) { |
||||
ctx.setStrokeStyle('#ccc'); |
||||
ctx.setLineWidth(1); |
||||
|
||||
// X轴 |
||||
ctx.beginPath(); |
||||
ctx.moveTo(padding, padding + chartHeight); |
||||
ctx.lineTo(padding + chartWidth, padding + chartHeight); |
||||
ctx.stroke(); |
||||
|
||||
// Y轴 |
||||
ctx.beginPath(); |
||||
ctx.moveTo(padding, padding); |
||||
ctx.lineTo(padding, padding + chartHeight); |
||||
ctx.stroke(); |
||||
|
||||
// 绘制Y轴刻度和标签 |
||||
const yTicks = 5; |
||||
for (let i = 0; i <= yTicks; i++) { |
||||
const y = padding + (chartHeight / yTicks) * i; |
||||
const price = maxPrice - (maxPrice - minPrice) * (i / yTicks); |
||||
|
||||
// 绘制刻度线 |
||||
ctx.beginPath(); |
||||
ctx.moveTo(padding - 3, y); |
||||
ctx.lineTo(padding, y); |
||||
ctx.stroke(); |
||||
|
||||
// 绘制价格标签 |
||||
ctx.setFontSize(10); |
||||
ctx.setFillStyle('#666'); |
||||
ctx.setTextAlign('right'); |
||||
ctx.fillText(price.toFixed(1), padding - 5, y + 3); |
||||
} |
||||
|
||||
// 绘制X轴刻度和标签 |
||||
const xTicks = this.timeFilter === 'day' ? 6 : 5; |
||||
for (let i = 0; i <= xTicks; i++) { |
||||
const x = padding + (chartWidth / xTicks) * i; |
||||
const index = Math.round((data.length - 1) * (i / xTicks)); |
||||
const time = data[index].time; |
||||
|
||||
// 绘制刻度线 |
||||
ctx.beginPath(); |
||||
ctx.moveTo(x, padding + chartHeight); |
||||
ctx.lineTo(x, padding + chartHeight + 3); |
||||
ctx.stroke(); |
||||
|
||||
// 格式化时间标签 |
||||
let timeLabel = ''; |
||||
if (this.timeFilter === 'day') { |
||||
timeLabel = time.getDate() + '日'; |
||||
} else if (this.timeFilter === 'hour') { |
||||
timeLabel = time.getHours() + '时'; |
||||
} else if (this.timeFilter === 'week') { |
||||
timeLabel = '第' + Math.ceil((time.getDate() + time.getDay()) / 7) + '周'; |
||||
} |
||||
|
||||
// 绘制时间标签 |
||||
ctx.setFontSize(10); |
||||
ctx.setFillStyle('#666'); |
||||
ctx.setTextAlign('center'); |
||||
ctx.fillText(timeLabel, x, padding + chartHeight + 15); |
||||
} |
||||
|
||||
// 绘制单位标签 |
||||
ctx.setFontSize(12); |
||||
ctx.setFillStyle('#333'); |
||||
ctx.setTextAlign('center'); |
||||
ctx.fillText('时间', padding + chartWidth / 2, padding + chartHeight + 30); |
||||
ctx.setTextAlign('right'); |
||||
ctx.fillText('价格 (元/1000金)', padding - 20, padding + chartHeight / 2); |
||||
}, |
||||
|
||||
// 绘制价格曲线 |
||||
drawPriceLine(ctx, padding, chartWidth, chartHeight, data, minPrice, maxPrice, minTime, maxTime) { |
||||
ctx.setStrokeStyle('#1989fa'); |
||||
ctx.setLineWidth(2); |
||||
|
||||
ctx.beginPath(); |
||||
data.forEach((item, index) => { |
||||
// 计算坐标 |
||||
const x = padding + (chartWidth * (item.time - minTime)) / (maxTime - minTime); |
||||
const y = padding + chartHeight - (chartHeight * (item.price - minPrice)) / (maxPrice - minPrice); |
||||
|
||||
if (index === 0) { |
||||
ctx.moveTo(x, y); |
||||
} else { |
||||
ctx.lineTo(x, y); |
||||
} |
||||
}); |
||||
ctx.stroke(); |
||||
}, |
||||
|
||||
// 绘制价格点 |
||||
drawPricePoints(ctx, padding, chartWidth, chartHeight, data, minPrice, maxPrice, minTime, maxTime) { |
||||
ctx.setFillStyle('#1989fa'); |
||||
|
||||
data.forEach(item => { |
||||
// 计算坐标 |
||||
const x = padding + (chartWidth * (item.time - minTime)) / (maxTime - minTime); |
||||
const y = padding + chartHeight - (chartHeight * (item.price - minPrice)) / (maxPrice - minPrice); |
||||
|
||||
// 绘制圆点 |
||||
ctx.beginPath(); |
||||
ctx.arc(x, y, 3, 0, 2 * Math.PI); |
||||
ctx.fill(); |
||||
}); |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style scoped> |
||||
.chart-container { |
||||
min-height: 100vh; |
||||
background-color: #f5f5f5; |
||||
padding: 20rpx; |
||||
} |
||||
|
||||
.chart-header { |
||||
text-align: center; |
||||
padding: 20rpx 0; |
||||
} |
||||
|
||||
.title { |
||||
font-size: 36rpx; |
||||
font-weight: bold; |
||||
color: #333; |
||||
text-align: center; |
||||
margin-bottom: 20rpx; |
||||
display: block; |
||||
} |
||||
|
||||
/* 悬浮筛选按钮样式 */ |
||||
.floating-filter-btn { |
||||
position: fixed; |
||||
right: 30rpx; |
||||
top: 30rpx; |
||||
width: 80rpx; |
||||
height: 80rpx; |
||||
background-color: #1989fa; |
||||
color: #fff; |
||||
border-radius: 50%; |
||||
display: flex; |
||||
justify-content: center; |
||||
align-items: center; |
||||
font-size: 24rpx; |
||||
box-shadow: 0 4rpx 10rpx rgba(25, 137, 250, 0.3); |
||||
z-index: 998; |
||||
} |
||||
|
||||
/* 筛选面板样式 */ |
||||
.filter-panel { |
||||
position: fixed; |
||||
top: 0; |
||||
left: 0; |
||||
width: 100%; |
||||
height: 100%; |
||||
background-color: rgba(0, 0, 0, 0.5); |
||||
z-index: 999; |
||||
display: flex; |
||||
flex-direction: column; |
||||
} |
||||
|
||||
.filter-header { |
||||
background-color: #fff; |
||||
padding: 20rpx; |
||||
display: flex; |
||||
justify-content: space-between; |
||||
align-items: center; |
||||
border-bottom: 1rpx solid #eee; |
||||
} |
||||
|
||||
.filter-title { |
||||
font-size: 32rpx; |
||||
font-weight: bold; |
||||
} |
||||
|
||||
.close-btn { |
||||
background-color: #f0f0f0; |
||||
color: #333; |
||||
font-size: 24rpx; |
||||
padding: 10rpx 20rpx; |
||||
border-radius: 20rpx; |
||||
} |
||||
|
||||
.filter-content { |
||||
background-color: #fff; |
||||
flex: 1; |
||||
padding: 20rpx; |
||||
overflow-y: auto; |
||||
} |
||||
|
||||
.server-group { |
||||
margin-bottom: 30rpx; |
||||
} |
||||
|
||||
.server-title { |
||||
font-weight: bold; |
||||
font-size: 30rpx; |
||||
margin-bottom: 15rpx; |
||||
padding-left: 20rpx; |
||||
} |
||||
|
||||
.faction-items { |
||||
padding-left: 40rpx; |
||||
} |
||||
|
||||
.filter-item { |
||||
margin-bottom: 15rpx; |
||||
font-size: 28rpx; |
||||
} |
||||
|
||||
.filter-footer { |
||||
background-color: #fff; |
||||
padding: 20rpx; |
||||
display: flex; |
||||
justify-content: space-around; |
||||
border-top: 1rpx solid #eee; |
||||
} |
||||
|
||||
.cancel-btn { |
||||
background-color: #f0f0f0; |
||||
color: #333; |
||||
font-size: 24rpx; |
||||
padding: 10rpx 40rpx; |
||||
border-radius: 20rpx; |
||||
} |
||||
|
||||
.save-btn { |
||||
background-color: #1989fa; |
||||
color: #fff; |
||||
font-size: 24rpx; |
||||
padding: 10rpx 40rpx; |
||||
border-radius: 20rpx; |
||||
} |
||||
|
||||
/* 时间筛选样式 */ |
||||
.time-filter { |
||||
display: flex; |
||||
justify-content: center; |
||||
margin: 20rpx 0; |
||||
gap: 20rpx; |
||||
} |
||||
|
||||
.filter-item { |
||||
padding: 10rpx 30rpx; |
||||
border-radius: 20rpx; |
||||
background-color: #f5f5f5; |
||||
font-size: 28rpx; |
||||
color: #666; |
||||
} |
||||
|
||||
.filter-item.active { |
||||
background-color: #1989fa; |
||||
color: #fff; |
||||
} |
||||
|
||||
.chart-content { |
||||
display: flex; |
||||
flex-direction: column; |
||||
gap: 30rpx; |
||||
} |
||||
|
||||
.chart-item { |
||||
background-color: #fff; |
||||
border-radius: 10rpx; |
||||
padding: 20rpx; |
||||
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1); |
||||
} |
||||
|
||||
.chart-title { |
||||
font-size: 32rpx; |
||||
font-weight: bold; |
||||
color: #333; |
||||
margin-bottom: 20rpx; |
||||
display: block; |
||||
} |
||||
|
||||
/* 图表画布样式 */ |
||||
.chart-canvas { |
||||
width: 700rpx; |
||||
height: 300rpx; |
||||
background-color: #fafafa; |
||||
border-radius: 8rpx; |
||||
} |
||||
</style> |
||||
@ -0,0 +1,587 @@
|
||||
<template> |
||||
<view class="container"> |
||||
<text class="title">魔兽世界金币价格查询</text> |
||||
<!-- 悬浮筛选按钮 --> |
||||
<view class="floating-filter-btn" @click="showFilter = true"> |
||||
<text>筛选</text> |
||||
</view> |
||||
|
||||
<!-- 筛选面板 --> |
||||
<view class="filter-panel" v-if="showFilter"> |
||||
<view class="filter-header"> |
||||
<text class="filter-title">选择关注的区服和阵营</text> |
||||
<button class="close-btn" @click="showFilter = false">关闭</button> |
||||
</view> |
||||
<view class="filter-content"> |
||||
<checkbox-group @change="handleCheckboxChange"> |
||||
<view class="server-group" v-for="server in allServers" :key="server.id"> |
||||
<view class="server-title">{{ server.name }}</view> |
||||
<view class="faction-items"> |
||||
<view class="filter-item" v-for="faction in server.factions" :key="faction.id"> |
||||
<checkbox :value="faction.id" :checked="selectedFactions.includes(faction.id)"> |
||||
{{ faction.name }} |
||||
</checkbox> |
||||
</view> |
||||
</view> |
||||
</view> |
||||
</checkbox-group> |
||||
</view> |
||||
<view class="filter-footer"> |
||||
<button class="cancel-btn" @click="showFilter = false">取消</button> |
||||
<button class="save-btn" @click="saveFilter">保存</button> |
||||
</view> |
||||
</view> |
||||
|
||||
<view class="content"> |
||||
<!-- 铁血1区 --> |
||||
<view class="server-section" v-if="isServerSelected('tx1')"> |
||||
<view class="server-title"> |
||||
<text>铁血1区</text> |
||||
</view> |
||||
|
||||
<view class="faction-section" v-if="isFactionSelected('tx1-alliance')"> |
||||
<view class="faction-title"> |
||||
<text>联盟</text> |
||||
</view> |
||||
<view class="price-table"> |
||||
<view class="table-header"> |
||||
<view class="table-cell">排名</view> |
||||
<view class="table-cell">价格</view> |
||||
<view class="table-cell">数量</view> |
||||
</view> |
||||
<view class="table-row" v-for="(price, index) in getDisplayPrices(alliancePrices1, 'tx1')" :key="index"> |
||||
<view class="table-cell">{{ index + 1 }}</view> |
||||
<view class="table-cell">{{ price.price }}</view> |
||||
<view class="table-cell">{{ price.amount }}</view> |
||||
</view> |
||||
</view> |
||||
<view class="expand-btn" v-if="alliancePrices1.length > 3" @click="toggleExpand('tx1')"> |
||||
{{ expandedServers['tx1'] ? '收起' : '展开更多' }} |
||||
</view> |
||||
</view> |
||||
|
||||
<view class="faction-section" v-if="isFactionSelected('tx1-horde')"> |
||||
<view class="faction-title"> |
||||
<text>部落</text> |
||||
</view> |
||||
<view class="price-table"> |
||||
<view class="table-header"> |
||||
<view class="table-cell">排名</view> |
||||
<view class="table-cell">价格</view> |
||||
<view class="table-cell">数量</view> |
||||
</view> |
||||
<view class="table-row" v-for="(price, index) in getDisplayPrices(hordePrices1, 'tx1')" :key="index"> |
||||
<view class="table-cell">{{ index + 1 }}</view> |
||||
<view class="table-cell">{{ price.price }}</view> |
||||
<view class="table-cell">{{ price.amount }}</view> |
||||
</view> |
||||
</view> |
||||
<view class="expand-btn" v-if="hordePrices1.length > 3" @click="toggleExpand('tx1')"> |
||||
{{ expandedServers['tx1'] ? '收起' : '展开更多' }} |
||||
</view> |
||||
</view> |
||||
</view> |
||||
|
||||
<!-- 铁血2区 --> |
||||
<view class="server-section" v-if="isServerSelected('tx2')"> |
||||
<view class="server-title"> |
||||
<text>铁血2区</text> |
||||
</view> |
||||
|
||||
<view class="faction-section" v-if="isFactionSelected('tx2-alliance')"> |
||||
<view class="faction-title"> |
||||
<text>联盟</text> |
||||
</view> |
||||
<view class="price-table"> |
||||
<view class="table-header"> |
||||
<view class="table-cell">排名</view> |
||||
<view class="table-cell">价格</view> |
||||
<view class="table-cell">数量</view> |
||||
</view> |
||||
<view class="table-row" v-for="(price, index) in getDisplayPrices(alliancePrices2, 'tx2')" :key="index"> |
||||
<view class="table-cell">{{ index + 1 }}</view> |
||||
<view class="table-cell">{{ price.price }}</view> |
||||
<view class="table-cell">{{ price.amount }}</view> |
||||
</view> |
||||
</view> |
||||
<view class="expand-btn" v-if="alliancePrices2.length > 3" @click="toggleExpand('tx2')"> |
||||
{{ expandedServers['tx2'] ? '收起' : '展开更多' }} |
||||
</view> |
||||
</view> |
||||
|
||||
<view class="faction-section" v-if="isFactionSelected('tx2-horde')"> |
||||
<view class="faction-title"> |
||||
<text>部落</text> |
||||
</view> |
||||
<view class="price-table"> |
||||
<view class="table-header"> |
||||
<view class="table-cell">排名</view> |
||||
<view class="table-cell">价格</view> |
||||
<view class="table-cell">数量</view> |
||||
</view> |
||||
<view class="table-row" v-for="(price, index) in getDisplayPrices(hordePrices2, 'tx2')" :key="index"> |
||||
<view class="table-cell">{{ index + 1 }}</view> |
||||
<view class="table-cell">{{ price.price }}</view> |
||||
<view class="table-cell">{{ price.amount }}</view> |
||||
</view> |
||||
</view> |
||||
<view class="expand-btn" v-if="hordePrices2.length > 3" @click="toggleExpand('tx2')"> |
||||
{{ expandedServers['tx2'] ? '收起' : '展开更多' }} |
||||
</view> |
||||
</view> |
||||
</view> |
||||
|
||||
|
||||
<!-- 时光1区 --> |
||||
<view class="server-section" v-if="isServerSelected('sg1')"> |
||||
<view class="server-title"> |
||||
<text>时光1区</text> |
||||
</view> |
||||
|
||||
<view class="faction-section" v-if="isFactionSelected('sg1-alliance')"> |
||||
<view class="faction-title"> |
||||
<text>联盟</text> |
||||
</view> |
||||
<view class="price-table"> |
||||
<view class="table-header"> |
||||
<view class="table-cell">排名</view> |
||||
<view class="table-cell">价格</view> |
||||
<view class="table-cell">数量</view> |
||||
</view> |
||||
<view class="table-row" v-for="(price, index) in getDisplayPrices(alliancePricesSg, 'sg1')" :key="index"> |
||||
<view class="table-cell">{{ index + 1 }}</view> |
||||
<view class="table-cell">{{ price.price }}</view> |
||||
<view class="table-cell">{{ price.amount }}</view> |
||||
</view> |
||||
</view> |
||||
<view class="expand-btn" v-if="alliancePricesSg.length > 3" @click="toggleExpand('sg1')"> |
||||
{{ expandedServers['sg1'] ? '收起' : '展开更多' }} |
||||
</view> |
||||
</view> |
||||
|
||||
<view class="faction-section" v-if="isFactionSelected('sg1-horde')"> |
||||
<view class="faction-title"> |
||||
<text>部落</text> |
||||
</view> |
||||
<view class="price-table"> |
||||
<view class="table-header"> |
||||
<view class="table-cell">排名</view> |
||||
<view class="table-cell">价格</view> |
||||
<view class="table-cell">数量</view> |
||||
</view> |
||||
<view class="table-row" v-for="(price, index) in getDisplayPrices(hordePricesSg, 'sg1')" :key="index"> |
||||
<view class="table-cell">{{ index + 1 }}</view> |
||||
<view class="table-cell">{{ price.price }}</view> |
||||
<view class="table-cell">{{ price.amount }}</view> |
||||
</view> |
||||
</view> |
||||
<view class="expand-btn" v-if="hordePricesSg.length > 3" @click="toggleExpand('sg1')"> |
||||
{{ expandedServers['sg1'] ? '收起' : '展开更多' }} |
||||
</view> |
||||
</view> |
||||
</view> |
||||
|
||||
</view> |
||||
</view> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
data() { |
||||
return { |
||||
showFilter: false, |
||||
// 修改数据结构,支持服务器和阵营的两级筛选 |
||||
allServers: [ |
||||
{ |
||||
id: 'tx1', |
||||
name: '铁血1区', |
||||
factions: [ |
||||
{ id: 'tx1-alliance', name: '联盟', serverId: 'tx1' }, |
||||
{ id: 'tx1-horde', name: '部落', serverId: 'tx1' } |
||||
] |
||||
}, |
||||
{ |
||||
id: 'tx2', |
||||
name: '铁血2区', |
||||
factions: [ |
||||
{ id: 'tx2-alliance', name: '联盟', serverId: 'tx2' }, |
||||
{ id: 'tx2-horde', name: '部落', serverId: 'tx2' } |
||||
] |
||||
}, |
||||
{ |
||||
id: 'sg1', |
||||
name: '时光1区', |
||||
factions: [ |
||||
{ id: 'sg1-alliance', name: '联盟', serverId: 'sg1' }, |
||||
{ id: 'sg1-horde', name: '部落', serverId: 'sg1' } |
||||
] |
||||
} |
||||
], |
||||
selectedFactions: [], |
||||
expandedServers: {}, // 记录每个服务器的展开状态 |
||||
// 模拟数据,后期从后端获取 |
||||
alliancePrices1: [ |
||||
{ price: '0.022', amount: '1000000' }, |
||||
{ price: '0.022', amount: '500000' }, |
||||
{ price: '0.023', amount: '300000' }, |
||||
{ price: '0.023', amount: '200000' }, |
||||
{ price: '0.023', amount: '100000' }, |
||||
{ price: '0.024', amount: '50000' }, |
||||
{ price: '0.024', amount: '50000' }, |
||||
{ price: '0.025', amount: '20000' }, |
||||
{ price: '0.025', amount: '20000' }, |
||||
{ price: '0.025', amount: '20000' } |
||||
], |
||||
hordePrices1: [ |
||||
{ price: '0.021', amount: '2000000' }, |
||||
{ price: '0.021', amount: '1000000' }, |
||||
{ price: '0.021', amount: '500000' }, |
||||
{ price: '0.022', amount: '300000' }, |
||||
{ price: '0.022', amount: '200000' }, |
||||
{ price: '0.022', amount: '100000' }, |
||||
{ price: '0.023', amount: '50000' }, |
||||
{ price: '0.023', amount: '50000' }, |
||||
{ price: '0.023', amount: '50000' }, |
||||
{ price: '0.024', amount: '20000' } |
||||
], |
||||
alliancePrices2: [ |
||||
{ price: '0.020', amount: '1500000' }, |
||||
{ price: '0.020', amount: '800000' }, |
||||
{ price: '0.021', amount: '500000' }, |
||||
{ price: '0.021', amount: '300000' }, |
||||
{ price: '0.021', amount: '200000' }, |
||||
{ price: '0.022', amount: '100000' }, |
||||
{ price: '0.022', amount: '100000' }, |
||||
{ price: '0.023', amount: '50000' }, |
||||
{ price: '0.023', amount: '50000' }, |
||||
{ price: '0.023', amount: '30000' } |
||||
], |
||||
hordePrices2: [ |
||||
{ price: '0.019', amount: '2000000' }, |
||||
{ price: '0.019', amount: '1000000' }, |
||||
{ price: '0.020', amount: '500000' }, |
||||
{ price: '0.020', amount: '300000' }, |
||||
{ price: '0.020', amount: '200000' }, |
||||
{ price: '0.021', amount: '100000' }, |
||||
{ price: '0.021', amount: '80000' }, |
||||
{ price: '0.021', amount: '50000' }, |
||||
{ price: '0.022', amount: '50000' }, |
||||
{ price: '0.022', amount: '30000' } |
||||
], |
||||
// 时光1区数据 |
||||
alliancePricesSg: [ |
||||
{ price: '0.025', amount: '1200000' }, |
||||
{ price: '0.025', amount: '600000' }, |
||||
{ price: '0.026', amount: '400000' }, |
||||
{ price: '0.026', amount: '300000' }, |
||||
{ price: '0.026', amount: '200000' }, |
||||
{ price: '0.027', amount: '150000' }, |
||||
{ price: '0.027', amount: '100000' }, |
||||
{ price: '0.027', amount: '80000' }, |
||||
{ price: '0.028', amount: '50000' }, |
||||
{ price: '0.028', amount: '50000' } |
||||
], |
||||
hordePricesSg: [ |
||||
{ price: '0.023', amount: '1500000' }, |
||||
{ price: '0.023', amount: '800000' }, |
||||
{ price: '0.024', amount: '500000' }, |
||||
{ price: '0.024', amount: '400000' }, |
||||
{ price: '0.024', amount: '300000' }, |
||||
{ price: '0.025', amount: '200000' }, |
||||
{ price: '0.025', amount: '150000' }, |
||||
{ price: '0.025', amount: '100000' }, |
||||
{ price: '0.026', amount: '80000' }, |
||||
{ price: '0.026', amount: '50000' } |
||||
] |
||||
} |
||||
}, |
||||
onLoad() { |
||||
// 页面加载时从缓存中读取用户选择的阵营 |
||||
this.loadSelectedFactions() |
||||
// 页面加载时从后端获取数据 |
||||
this.loadPriceData() |
||||
}, |
||||
methods: { |
||||
loadPriceData() { |
||||
// 后期从后端获取数据的方法 |
||||
console.log('加载价格数据...') |
||||
// 这里可以添加axios请求或者uni.request请求 |
||||
}, |
||||
|
||||
// 加载用户选择的阵营 |
||||
loadSelectedFactions() { |
||||
const selected = uni.getStorageSync('selectedFactions') |
||||
if (selected && selected.length > 0) { |
||||
this.selectedFactions = selected |
||||
} else { |
||||
// 默认全部选中 |
||||
this.selectedFactions = [] |
||||
this.allServers.forEach(server => { |
||||
server.factions.forEach(faction => { |
||||
this.selectedFactions.push(faction.id) |
||||
}) |
||||
}) |
||||
// 保存到缓存 |
||||
uni.setStorageSync('selectedFactions', this.selectedFactions) |
||||
} |
||||
}, |
||||
|
||||
// 处理checkbox变化 |
||||
handleCheckboxChange(e) { |
||||
this.selectedFactions = e.detail.value |
||||
}, |
||||
|
||||
// 保存筛选结果 |
||||
saveFilter() { |
||||
// 确保至少选择一个阵营 |
||||
if (this.selectedFactions.length === 0) { |
||||
uni.showToast({ |
||||
title: '请至少选择一个阵营', |
||||
icon: 'none' |
||||
}) |
||||
return |
||||
} |
||||
|
||||
// 保存到缓存 |
||||
uni.setStorageSync('selectedFactions', this.selectedFactions) |
||||
|
||||
// 筛选后自动展开所有服务器到5行 |
||||
this.selectedFactions.forEach(factionId => { |
||||
// 提取服务器ID |
||||
const serverId = factionId.split('-')[0] |
||||
// 使用$set确保Vue能检测到对象属性的变化 |
||||
this.$set(this.expandedServers, serverId, true) |
||||
}) |
||||
|
||||
uni.showToast({ |
||||
title: '保存成功', |
||||
icon: 'success' |
||||
}) |
||||
this.showFilter = false |
||||
}, |
||||
|
||||
// 切换服务器展开状态 |
||||
toggleExpand(serverId) { |
||||
// 使用$set确保Vue能检测到对象属性的变化 |
||||
this.$set(this.expandedServers, serverId, !this.expandedServers[serverId]) |
||||
}, |
||||
|
||||
// 获取要显示的价格行数 |
||||
getDisplayPrices(prices, serverId) { |
||||
const isExpanded = this.expandedServers[serverId] || false |
||||
return isExpanded ? prices.slice(0, 5) : prices.slice(0, 3) |
||||
}, |
||||
|
||||
// 检查阵营是否被选中 |
||||
isFactionSelected(factionId) { |
||||
return this.selectedFactions.includes(factionId) |
||||
}, |
||||
|
||||
// 检查服务器是否有任何阵营被选中 |
||||
isServerSelected(serverId) { |
||||
return this.allServers.some(server => |
||||
server.id === serverId && |
||||
server.factions.some(faction => |
||||
this.selectedFactions.includes(faction.id) |
||||
) |
||||
) |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style scoped> |
||||
.container { |
||||
min-height: 100vh; |
||||
background-color: #f5f5f5; |
||||
padding: 20rpx; |
||||
} |
||||
|
||||
.title { |
||||
font-size: 36rpx; |
||||
font-weight: bold; |
||||
color: #333; |
||||
text-align: center; |
||||
margin-bottom: 20rpx; |
||||
display: block; |
||||
} |
||||
|
||||
/* 悬浮筛选按钮样式 */ |
||||
.floating-filter-btn { |
||||
position: fixed; |
||||
right: 30rpx; |
||||
top: 30rpx; |
||||
width: 80rpx; |
||||
height: 80rpx; |
||||
background-color: #1989fa; |
||||
color: #fff; |
||||
border-radius: 50%; |
||||
display: flex; |
||||
justify-content: center; |
||||
align-items: center; |
||||
font-size: 24rpx; |
||||
box-shadow: 0 4rpx 10rpx rgba(25, 137, 250, 0.3); |
||||
z-index: 998; |
||||
} |
||||
|
||||
/* 筛选面板样式 */ |
||||
.filter-panel { |
||||
position: fixed; |
||||
top: 0; |
||||
left: 0; |
||||
width: 100%; |
||||
height: 100%; |
||||
background-color: rgba(0, 0, 0, 0.5); |
||||
z-index: 999; |
||||
display: flex; |
||||
flex-direction: column; |
||||
} |
||||
|
||||
.filter-header { |
||||
background-color: #fff; |
||||
padding: 20rpx; |
||||
display: flex; |
||||
justify-content: space-between; |
||||
align-items: center; |
||||
border-bottom: 1rpx solid #eee; |
||||
} |
||||
|
||||
.filter-title { |
||||
font-size: 32rpx; |
||||
font-weight: bold; |
||||
} |
||||
|
||||
.close-btn { |
||||
background-color: #f0f0f0; |
||||
color: #333; |
||||
font-size: 24rpx; |
||||
padding: 10rpx 20rpx; |
||||
border-radius: 20rpx; |
||||
} |
||||
|
||||
.filter-content { |
||||
background-color: #fff; |
||||
flex: 1; |
||||
padding: 20rpx; |
||||
overflow-y: auto; |
||||
} |
||||
|
||||
.server-group { |
||||
margin-bottom: 30rpx; |
||||
} |
||||
|
||||
.server-title { |
||||
font-weight: bold; |
||||
font-size: 30rpx; |
||||
margin-bottom: 15rpx; |
||||
padding-left: 20rpx; |
||||
} |
||||
|
||||
.faction-items { |
||||
padding-left: 40rpx; |
||||
} |
||||
|
||||
.filter-item { |
||||
margin-bottom: 15rpx; |
||||
font-size: 28rpx; |
||||
} |
||||
|
||||
.filter-footer { |
||||
background-color: #fff; |
||||
padding: 20rpx; |
||||
display: flex; |
||||
justify-content: space-around; |
||||
border-top: 1rpx solid #eee; |
||||
} |
||||
|
||||
.cancel-btn { |
||||
background-color: #f0f0f0; |
||||
color: #333; |
||||
font-size: 24rpx; |
||||
padding: 10rpx 40rpx; |
||||
border-radius: 20rpx; |
||||
} |
||||
|
||||
.save-btn { |
||||
background-color: #1989fa; |
||||
color: #fff; |
||||
font-size: 24rpx; |
||||
padding: 10rpx 40rpx; |
||||
border-radius: 20rpx; |
||||
} |
||||
|
||||
.title { |
||||
font-size: 36rpx; |
||||
font-weight: bold; |
||||
} |
||||
|
||||
.content { |
||||
padding: 20rpx; |
||||
} |
||||
|
||||
.server-section { |
||||
background-color: white; |
||||
border-radius: 10rpx; |
||||
padding: 20rpx; |
||||
margin-bottom: 20rpx; |
||||
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1); |
||||
} |
||||
|
||||
.server-title { |
||||
font-size: 32rpx; |
||||
font-weight: bold; |
||||
margin-bottom: 20rpx; |
||||
color: #333; |
||||
border-bottom: 2rpx solid #eee; |
||||
padding-bottom: 10rpx; |
||||
} |
||||
|
||||
.faction-section { |
||||
margin-bottom: 20rpx; |
||||
} |
||||
|
||||
.faction-title { |
||||
font-size: 28rpx; |
||||
font-weight: bold; |
||||
margin-bottom: 10rpx; |
||||
color: #666; |
||||
} |
||||
|
||||
.price-table { |
||||
border-radius: 5rpx; |
||||
overflow: hidden; |
||||
} |
||||
|
||||
.table-header { |
||||
display: flex; |
||||
background-color: #f0f0f0; |
||||
font-weight: bold; |
||||
border-bottom: 2rpx solid #eee; |
||||
} |
||||
|
||||
.table-row { |
||||
display: flex; |
||||
border-bottom: 1rpx solid #f0f0f0; |
||||
} |
||||
|
||||
.table-cell { |
||||
flex: 1; |
||||
padding: 15rpx; |
||||
text-align: center; |
||||
font-size: 24rpx; |
||||
} |
||||
|
||||
.table-row:last-child { |
||||
border-bottom: none; |
||||
} |
||||
|
||||
/* 展开按钮样式 */ |
||||
.expand-btn { |
||||
text-align: center; |
||||
color: #1989fa; |
||||
font-size: 24rpx; |
||||
padding: 10rpx; |
||||
margin-top: 10rpx; |
||||
cursor: pointer; |
||||
} |
||||
</style> |
||||
|
After Width: | Height: | Size: 3.9 KiB |
@ -0,0 +1,13 @@
|
||||
uni.addInterceptor({ |
||||
returnValue (res) { |
||||
if (!(!!res && (typeof res === "object" || typeof res === "function") && typeof res.then === "function")) { |
||||
return res; |
||||
} |
||||
return new Promise((resolve, reject) => { |
||||
if (!res) { |
||||
return resolve(res)
|
||||
} |
||||
res.then((res) => res[0] ? reject(res[0]) : resolve(res[1])); |
||||
}); |
||||
}, |
||||
}); |
||||
@ -0,0 +1,76 @@
|
||||
/** |
||||
* 这里是uni-app内置的常用样式变量 |
||||
* |
||||
* uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量 |
||||
* 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App |
||||
* |
||||
*/ |
||||
|
||||
/** |
||||
* 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能 |
||||
* |
||||
* 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件 |
||||
*/ |
||||
|
||||
/* 颜色变量 */ |
||||
|
||||
/* 行为相关颜色 */ |
||||
$uni-color-primary: #007aff; |
||||
$uni-color-success: #4cd964; |
||||
$uni-color-warning: #f0ad4e; |
||||
$uni-color-error: #dd524d; |
||||
|
||||
/* 文字基本颜色 */ |
||||
$uni-text-color: #333; // 基本色 |
||||
$uni-text-color-inverse: #fff; // 反色 |
||||
$uni-text-color-grey: #999; // 辅助灰色,如加载更多的提示信息 |
||||
$uni-text-color-placeholder: #808080; |
||||
$uni-text-color-disable: #c0c0c0; |
||||
|
||||
/* 背景颜色 */ |
||||
$uni-bg-color: #fff; |
||||
$uni-bg-color-grey: #f8f8f8; |
||||
$uni-bg-color-hover: #f1f1f1; // 点击状态颜色 |
||||
$uni-bg-color-mask: rgba(0, 0, 0, 0.4); // 遮罩颜色 |
||||
|
||||
/* 边框颜色 */ |
||||
$uni-border-color: #c8c7cc; |
||||
|
||||
/* 尺寸变量 */ |
||||
|
||||
/* 文字尺寸 */ |
||||
$uni-font-size-sm: 12px; |
||||
$uni-font-size-base: 14px; |
||||
$uni-font-size-lg: 16px; |
||||
|
||||
/* 图片尺寸 */ |
||||
$uni-img-size-sm: 20px; |
||||
$uni-img-size-base: 26px; |
||||
$uni-img-size-lg: 40px; |
||||
|
||||
/* Border Radius */ |
||||
$uni-border-radius-sm: 2px; |
||||
$uni-border-radius-base: 3px; |
||||
$uni-border-radius-lg: 6px; |
||||
$uni-border-radius-circle: 50%; |
||||
|
||||
/* 水平间距 */ |
||||
$uni-spacing-row-sm: 5px; |
||||
$uni-spacing-row-base: 10px; |
||||
$uni-spacing-row-lg: 15px; |
||||
|
||||
/* 垂直间距 */ |
||||
$uni-spacing-col-sm: 4px; |
||||
$uni-spacing-col-base: 8px; |
||||
$uni-spacing-col-lg: 12px; |
||||
|
||||
/* 透明度 */ |
||||
$uni-opacity-disabled: 0.3; // 组件禁用态的透明度 |
||||
|
||||
/* 文章场景相关 */ |
||||
$uni-color-title: #2c405a; // 文章标题颜色 |
||||
$uni-font-size-title: 20px; |
||||
$uni-color-subtitle: #555; // 二级标题颜色 |
||||
$uni-font-size-subtitle: 18px; |
||||
$uni-color-paragraph: #3f536e; // 文章段落颜色 |
||||
$uni-font-size-paragraph: 15px; |
||||
Loading…
Reference in new issue