feat: 初始化魔兽世界金币价格查询小程序项目
添加基础项目结构,包括页面、组件和配置文件 实现金币价格展示和价格走势图功能 添加筛选功能支持按区服和阵营筛选
This commit is contained in:
+2
-1
@@ -19,7 +19,8 @@ dmypy.json
|
||||
.pyre/
|
||||
.pytype/
|
||||
*.so
|
||||
|
||||
node_modules/
|
||||
weixin/node_modules
|
||||
# Editor directories and files
|
||||
.vscode/
|
||||
.idea/
|
||||
|
||||
+27
@@ -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>
|
||||
+11
@@ -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
|
||||
Generated
+37369
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>
|
||||
Vendored
+11
@@ -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;
|
||||
}
|
||||
}
|
||||
Vendored
+4
@@ -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>
|
||||
Binary file not shown.
|
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;
|
||||
Reference in New Issue
Block a user