-
2.env.development
-
2.env.production
-
8README.md
-
2index.html
-
64main.js
-
9244package-lock.json
-
18package.json
-
BINpublic/app.png
-
BINpublic/home.png
-
BINpublic/left.png
-
BINpublic/refresh.png
-
BINpublic/right.png
-
29src/api/dataAPI.js
-
BINsrc/assets/img/smallTitle/BigLine.png
-
BINsrc/assets/img/smallTitle/title-jn-left.png
-
BINsrc/assets/img/smallTitle/title-jn-right.png
-
BINsrc/assets/img/smallTitle/右.png
-
BINsrc/assets/img/smallTitle/左.png
-
6src/main.js
-
97src/router/index.js
-
202src/store/fakeLink-dataList.js
-
129src/utils/request.js
-
3src/views/animation/anima.vue
-
3src/views/calendar/calendar.vue
-
16src/views/commponent/backBtn.vue
-
91src/views/fakeLink/component/smallTitle.vue
-
781src/views/fakeLink/dbqb/dbqb.vue
-
1238src/views/fakeLink/dbqb/echarts/EnergyKlineEcharts.vue
-
231src/views/fakeLink/homepage-two.vue
-
471src/views/fakeLink/homepage.vue
-
163src/views/fakeLink/login.vue
-
68src/views/homepage.vue
-
6src/views/homework/homework.vue
-
249src/views/hxl_DZP/dzp1.vue
-
79src/views/three3D/3D1.vue
@ -0,0 +1,64 @@ |
|||
// 引入Electron的核心模块
|
|||
const { app, BrowserWindow, Menu } = require("electron"); |
|||
|
|||
const path = require("path"); |
|||
|
|||
// 创建窗口的函数
|
|||
function createWindow() { |
|||
// 定义图标路径
|
|||
const iconPath = path.join(__dirname, "./public/app.png"); |
|||
|
|||
// 新建一个窗口(就像打开一个浏览器窗口)
|
|||
const mainWindow = new BrowserWindow({ |
|||
width: 800, // 窗口宽度
|
|||
height: 600, // 窗口高度
|
|||
icon: iconPath, |
|||
...(process.platform === "linux" ? { icon } : {}), |
|||
webPreferences: { |
|||
// 允许在Vue页面中使用Node.js的功能(可选,按需开启)
|
|||
nodeIntegration: true, |
|||
contextIsolation: false, |
|||
}, |
|||
}); |
|||
|
|||
// 告诉窗口要显示的内容:
|
|||
// 开发阶段,显示Vue3的本地服务地址(就是刚才npm run dev的地址)
|
|||
mainWindow.loadURL("http://localhost:5173"); |
|||
|
|||
// 创建一个简单的菜单(包含前进/后退按钮)
|
|||
// const menu = Menu.buildFromTemplate([
|
|||
// {
|
|||
// label: "", // 菜单名称
|
|||
// icon: path.join(__dirname, './public/left.png'), // 16x16
|
|||
// submenu: [
|
|||
// {
|
|||
// label: "后退", // 后退按钮
|
|||
// click: () => mainWindow.webContents.goBack(), // 调用后退API
|
|||
// },
|
|||
// {
|
|||
// label: "前进", // 前进按钮
|
|||
// click: () => mainWindow.webContents.goForward(), // 调用前进API
|
|||
// },
|
|||
// ],
|
|||
// },
|
|||
// ]);
|
|||
const menu = null; |
|||
Menu.setApplicationMenu(menu); // 把菜单应用到窗口
|
|||
// 打开开发者工具(类似浏览器的F12,方便调试,可选)
|
|||
// mainWindow.webContents.openDevTools()
|
|||
} |
|||
|
|||
// 当Electron准备好后,创建窗口
|
|||
app.whenReady().then(() => { |
|||
createWindow(); |
|||
|
|||
// 对于Mac系统的兼容(不用深究,照抄即可)
|
|||
app.on("activate", () => { |
|||
if (BrowserWindow.getAllWindows().length === 0) createWindow(); |
|||
}); |
|||
}); |
|||
|
|||
// 关闭所有窗口时退出应用(Windows和Linux的习惯)
|
|||
app.on("window-all-closed", () => { |
|||
if (process.platform !== "darwin") app.quit(); |
|||
}); |
9244
package-lock.json
File diff suppressed because it is too large
View File
@ -1,25 +1,37 @@ |
|||
{ |
|||
"name": "dzp", |
|||
"main": "main.js", |
|||
"private": true, |
|||
"version": "0.0.0", |
|||
"type": "module", |
|||
"author": "hxl", |
|||
"description": "学习项目", |
|||
"license": "ISC", |
|||
"scripts": { |
|||
"start": "electron .", |
|||
"dev": "vite --host", |
|||
"build": "vite build", |
|||
"preview": "vite preview" |
|||
"preview": "vite preview", |
|||
"electron:dev": "electron ." |
|||
}, |
|||
"dependencies": { |
|||
"@element-plus/icons-vue": "^2.3.1", |
|||
"@lucky-canvas/vue": "^0.1.11", |
|||
"@pinia-plugin-persistedstate/nuxt": "^1.2.1", |
|||
"axios": "^1.10.0", |
|||
"echarts": "^6.0.0", |
|||
"element-plus": "^2.9.8", |
|||
"lucky-canvas": "^1.7.27", |
|||
"moment": "^2.30.1", |
|||
"pinia": "^3.0.3", |
|||
"three": "^0.178.0", |
|||
"vue": "^3.5.13", |
|||
"vue-router": "^4.5.0" |
|||
}, |
|||
"devDependencies": { |
|||
"@vitejs/plugin-vue": "^5.2.1", |
|||
"electron": "^37.3.1", |
|||
"electron-builder": "^26.0.12", |
|||
"less": "^4.4.1", |
|||
"sass": "^1.92.1", |
|||
"vite": "^6.2.6" |
|||
} |
|||
} |
After Width: 412 | Height: 411 | Size: 90 KiB |
After Width: 200 | Height: 200 | Size: 4.6 KiB |
After Width: 200 | Height: 200 | Size: 2.2 KiB |
After Width: 200 | Height: 200 | Size: 7.3 KiB |
After Width: 200 | Height: 200 | Size: 2.3 KiB |
@ -0,0 +1,29 @@ |
|||
import request from "../utils/request"; |
|||
|
|||
const APIurl = import.meta.env.VITE_APP_API_BASE_URL; |
|||
|
|||
//数据接口
|
|||
export const dataListAPI = function (params) { |
|||
// URLSearchParams只接受全部字符串的数据
|
|||
// 将传入数据转化成字符串
|
|||
const StringParams = new URLSearchParams( |
|||
Object.entries(params).map(([key, value]) => [key, String(value)]) |
|||
); |
|||
return request({ |
|||
url: `${APIurl}/api/brain/data`, |
|||
method: "post", |
|||
data: StringParams, |
|||
headers: { |
|||
"Content-Type": "application/x-www-form-urlencoded", |
|||
}, |
|||
}); |
|||
}; |
|||
|
|||
// ai情绪大模型的接口
|
|||
export const aiEmotionAPI = function (params) { |
|||
return request({ |
|||
url: `${APIurl}/api/aiEmotion/client/getAiEmotionData`, |
|||
method: "post", |
|||
data: params, |
|||
}); |
|||
}; |
After Width: 640 | Height: 2 | Size: 342 B |
After Width: 52 | Height: 50 | Size: 545 B |
After Width: 52 | Height: 50 | Size: 562 B |
After Width: 80 | Height: 70 | Size: 4.5 KiB |
After Width: 80 | Height: 70 | Size: 4.4 KiB |
@ -1,39 +1,66 @@ |
|||
import { createRouter, createWebHistory } from 'vue-router' |
|||
import { createRouter, createWebHistory } from "vue-router"; |
|||
const routes = [ |
|||
{ |
|||
path: '/', |
|||
redirect: '/homepage' |
|||
}, |
|||
{ |
|||
path: '/homepage', |
|||
name: 'homepage', |
|||
component: () => import('../views/homepage.vue') |
|||
}, |
|||
{ |
|||
path: '/hxl_dzp1', |
|||
name: 'hxl_dzp1', |
|||
component: () => import('../views/hxl_DZP/dzp1.vue') |
|||
}, |
|||
{ |
|||
path: '/animation', |
|||
name: 'animation', |
|||
component: () => import('../views/animation/anima.vue') |
|||
}, |
|||
{ |
|||
path: '/homework', |
|||
name: 'homework', |
|||
component: () => import('../views/homework/homework.vue') |
|||
}, |
|||
{ |
|||
path: '/calendar', |
|||
name: 'calendar', |
|||
component: () => import('../views/calendar/calendar.vue') |
|||
} |
|||
] |
|||
{ |
|||
path: "/", |
|||
redirect: "/homepage", |
|||
}, |
|||
{ |
|||
path: "/homepage", |
|||
name: "homepage", |
|||
component: () => import("../views/homepage.vue"), |
|||
}, |
|||
{ |
|||
path: "/hxl_dzp1", |
|||
name: "hxl_dzp1", |
|||
component: () => import("../views/hxl_DZP/dzp1.vue"), |
|||
}, |
|||
{ |
|||
path: "/animation", |
|||
name: "animation", |
|||
component: () => import("../views/animation/anima.vue"), |
|||
}, |
|||
{ |
|||
path: "/homework", |
|||
name: "homework", |
|||
component: () => import("../views/homework/homework.vue"), |
|||
}, |
|||
{ |
|||
path: "/calendar", |
|||
name: "calendar", |
|||
component: () => import("../views/calendar/calendar.vue"), |
|||
}, |
|||
{ |
|||
path: "/3D1", |
|||
name: "3D1", |
|||
component: () => import("../views/three3D/3D1.vue"), |
|||
}, |
|||
{ |
|||
path: "/fakeLink", |
|||
name: "fakeLink", |
|||
component: () => import("../views/fakeLink/homepage.vue"), |
|||
}, |
|||
{ |
|||
path: "/fakeLinkLogin", |
|||
name: "fakeLinkLogin", |
|||
component: () => import("../views/fakeLink/login.vue"), |
|||
}, |
|||
{ |
|||
path: "/homepageTwo", |
|||
name: "homepageTwo", |
|||
component: () => import("../views/fakeLink/homepage-two.vue"), |
|||
children: [ |
|||
{ |
|||
path: "/dbqb", |
|||
name: "dbqb", |
|||
component: () => import("../views/fakeLink/dbqb/dbqb.vue"), |
|||
}, |
|||
], |
|||
}, |
|||
]; |
|||
// 创建路由实例
|
|||
const router = createRouter({ |
|||
history: createWebHistory(import.meta.env.VITE_PUBLIC_PATH), |
|||
routes |
|||
}) |
|||
history: createWebHistory(import.meta.env.VITE_PUBLIC_PATH), |
|||
routes, |
|||
}); |
|||
// 导出
|
|||
export default router |
|||
export default router; |
@ -0,0 +1,202 @@ |
|||
import { defineStore } from "pinia"; |
|||
import { ref } from "vue"; |
|||
import { ElMessageBox, ElMessage } from "element-plus"; |
|||
import { useRouter } from "vue-router"; |
|||
const router = useRouter(); |
|||
import { dataListAPI, aiEmotionAPI } from "../api/dataAPI"; |
|||
import { version } from "less"; |
|||
|
|||
export const fakeLinkDataListStore = defineStore( |
|||
"fakeLinkDataListStore", |
|||
() => { |
|||
const userInfo = ref({}); |
|||
|
|||
const getUserInfo = (username, password) => { |
|||
if (username == "hxl") { |
|||
userInfo.value.nickname = "NikooooHong"; |
|||
userInfo.value.img = |
|||
"https://d31zlh4on95l9h.cloudfront.net/images/9a431843b182c64a05fa3c8f6772b8a4.png"; |
|||
userInfo.value.token = "DairyQueen"; |
|||
|
|||
return 200; |
|||
} else { |
|||
return 400; |
|||
} |
|||
}; |
|||
|
|||
const getMarket = () => { |
|||
let market = ""; |
|||
const queryMarket = getQueryVariable("market"); |
|||
if (queryMarket) { |
|||
if ( |
|||
typeof queryMarket === "string" && |
|||
[ |
|||
"sg", |
|||
"my", |
|||
"in", |
|||
"hk", |
|||
"th", |
|||
"vi", |
|||
"usa", |
|||
"can", |
|||
"gb", |
|||
"cn", |
|||
].includes(queryMarket) |
|||
) { |
|||
return (market = queryMarket); |
|||
} else { |
|||
switch (queryMarket) { |
|||
case "SGX": |
|||
return (market = "sg"); |
|||
case "BMB": |
|||
return (market = "my"); |
|||
case "IDX": |
|||
return (market = "in"); |
|||
case "HKEX": |
|||
return (market = "hk"); |
|||
case "SET": |
|||
return (market = "th"); |
|||
case "HN": |
|||
return (market = "vi"); |
|||
case "HONSE": |
|||
return (market = "vi"); |
|||
case "AMERA": |
|||
return (market = "usa"); |
|||
case "NYSE": |
|||
return (market = "usa"); |
|||
case "NASDAQ": |
|||
return (market = "usa"); |
|||
case "DLD": |
|||
return (market = "can"); |
|||
case "DLDCY": |
|||
return (market = "can"); |
|||
case "GINDEX": |
|||
return (market = "gb"); |
|||
case "BZ": |
|||
return (market = "cn"); |
|||
case "SH": |
|||
return (market = "cn"); |
|||
case "SZ": |
|||
return (market = "cn"); |
|||
default: |
|||
return "无市场数据"; |
|||
} |
|||
} |
|||
} else { |
|||
return (market = ""); |
|||
} |
|||
}; |
|||
|
|||
const getQueryVariable = (variable) => { |
|||
const query = window.location.search.substring(1); |
|||
const vars = query.split("&"); |
|||
for (let i = 0; i < vars.length; i++) { |
|||
const pair = vars[i].split("="); |
|||
if (pair[0] === variable) { |
|||
return pair[1]; |
|||
} |
|||
} |
|||
return ""; |
|||
}; |
|||
|
|||
const dataList = ref({}); |
|||
const brainDataList = ref(null); |
|||
const swordDataList = ref(null); |
|||
const priceDataList = ref(null); |
|||
const timeDataList = ref(null); |
|||
const showALLData = ref(null); |
|||
const HomePage = ref(null); |
|||
const AIBull = ref(null); |
|||
const AIGoldBull = ref(null); |
|||
const AIRadar = ref(null); |
|||
const fetchChartData = async () => { |
|||
const getMarketString = localStorage.getItem("localMarket"); |
|||
const getCodeString = localStorage.getItem("localCode"); |
|||
try { |
|||
const res = await dataListAPI({ |
|||
token: |
|||
"8Csj5VVX1UbIb4C3oxrnbZi0+fEeMx8pywnIlrmTm45Cb/EllzWACLto9J9+fCFsfdgBOvKvyY94FvqlvM0", |
|||
market: getMarket() || getMarketString || "gb", |
|||
code: getQueryVariable("code") || getCodeString || "NDX", |
|||
language: "cn", |
|||
brainPrivilegeState: 1, |
|||
swordPrivilegeState: 1, |
|||
stockForecastPrivilegeState: 1, |
|||
spaceForecastPrivilegeState: 1, |
|||
aibullPrivilegeState: 1, |
|||
aigoldBullPrivilegeState: 1, |
|||
airadarPrivilegeState: 1, |
|||
marketList: ["usa", "sg", "my", "hk", "cn", "can", "vi", "th", "in"], |
|||
}); |
|||
// 将涨跌幅改为保留两位小数
|
|||
let zhangFu = res.data.HomePage.StockInformation.ZhangFu; |
|||
let head = zhangFu[0]; |
|||
let tail = zhangFu[zhangFu.length - 1]; |
|||
if (zhangFu && zhangFu.length > 2) { |
|||
zhangFu = zhangFu.slice(1, -1); // 去掉开头一位和结尾一位
|
|||
} |
|||
zhangFu = Number(zhangFu).toFixed(2); |
|||
zhangFu = head + zhangFu + tail; |
|||
res.data.HomePage.StockInformation.ZhangFu = zhangFu; |
|||
res.data.ShowAll.StockInformation.ZhangFu = zhangFu; |
|||
console.log("res", res); |
|||
brainDataList.value = res.data.Brain; |
|||
swordDataList.value = res.data.Sword; |
|||
priceDataList.value = res.data.StockForecast; |
|||
timeDataList.value = res.data.SpaceForecast; |
|||
showALLData.value = res.data.ShowAll; |
|||
HomePage.value = res.data.HomePage; |
|||
AIBull.value = res.data.AIBull; |
|||
AIGoldBull.value = res.data.AIGoldBull; |
|||
AIRadar.value = res.data.AIRadar; |
|||
dataList.value = res.data; // 返回获取到的数据
|
|||
} catch (error) { |
|||
console.error("获取图表数据出错:", error); |
|||
} |
|||
}; |
|||
|
|||
const AiEmotinData = ref({}); |
|||
// 调用aiEmotionAPI获取数据
|
|||
const getAiEmotinData = async () => { |
|||
const getMarketString = localStorage.getItem("localMarket"); |
|||
const getCodeString = localStorage.getItem("localCode"); |
|||
console.log(getMarketString, getCodeString); |
|||
try { |
|||
const res = await aiEmotionAPI({ |
|||
token: |
|||
"8Csj5VVX1UbIb4C3oxrnbZi0+fEeMx8pywnIlrmTm45Cb/EllzWACLto9J9+fCFsfdgBOvKvyY94FvqlvM0", |
|||
market: getMarketString || "gb", |
|||
code: getCodeString || "NDX", |
|||
language: "cn", |
|||
version: "1", |
|||
}); |
|||
|
|||
// 处理响应数据
|
|||
if (res.data) { |
|||
AiEmotinData.value = res.data; |
|||
} |
|||
} catch (error) { |
|||
console.error("获取图表数据出错:", error); |
|||
} finally { |
|||
console.log("数据获取过程结束"); |
|||
} |
|||
}; |
|||
|
|||
return { |
|||
userInfo, |
|||
getUserInfo, |
|||
dataList, |
|||
HomePage, |
|||
fetchChartData, |
|||
AiEmotinData, |
|||
getAiEmotinData, |
|||
}; |
|||
}, |
|||
{ |
|||
persist: { |
|||
key: "userInfo", |
|||
storage: sessionStorage, |
|||
paths: ["expireData"], |
|||
}, |
|||
} |
|||
); |
@ -0,0 +1,129 @@ |
|||
import axios from 'axios' |
|||
import { ElMessage } from 'element-plus' |
|||
|
|||
const ERROR_MESSAGES = { |
|||
badRequest: '请求错误(400)', |
|||
unauthorized: '未授权,请登录(401)', |
|||
forbidden: '拒绝访问(403)', |
|||
notFound: `请求地址出错: ${'[具体 URL 将在这里被替换]'}`, |
|||
methodNotAllowed: '请求方法未允许(405)', |
|||
requestTimeout: '请求超时(408)', |
|||
internalServerError: '服务器内部错误(500)', |
|||
notImplemented: '服务未实现(501)', |
|||
badGateway: '网络错误(502)', |
|||
serviceUnavailable: '服务不可用(503)', |
|||
gatewayTimeout: '网络超时(504)', |
|||
httpVersionNotSupported: 'HTTP 版本不受支持(505)', |
|||
defaultConnectionError: '连接错误: [原始错误消息]', |
|||
networkError: '网络异常,请检查后重试!', |
|||
serverFailure: '连接到服务器失败,请联系管理员' |
|||
} |
|||
|
|||
const service = axios.create({ |
|||
baseURL: '', // url = base url + request url+
|
|||
// timeout: 50000,
|
|||
withCredentials: false // send cookies when cross-domain requests
|
|||
// headers: {
|
|||
// // clear cors
|
|||
// 'Cache-Control': 'no-cache',
|
|||
// Pragma: 'no-cache'
|
|||
// }
|
|||
}) |
|||
|
|||
const setErrorMsg = (error) => { |
|||
if (error && error.response) { |
|||
switch (error.response.status) { |
|||
case 400: |
|||
error.message = ERROR_MESSAGES.badRequest |
|||
break |
|||
case 401: |
|||
error.message = ERROR_MESSAGES.unauthorized |
|||
break |
|||
case 403: |
|||
error.message = ERROR_MESSAGES.forbidden |
|||
break |
|||
case 404: |
|||
error.message = ERROR_MESSAGES.notFound.replace( |
|||
'[具体 URL 将在这里被替换]', |
|||
error.response.config.url |
|||
) |
|||
break |
|||
case 405: |
|||
error.message = ERROR_MESSAGES.methodNotAllowed |
|||
break |
|||
case 408: |
|||
error.message = ERROR_MESSAGES.requestTimeout |
|||
break |
|||
case 500: |
|||
error.message = ERROR_MESSAGES.internalServerError |
|||
break |
|||
case 501: |
|||
error.message = ERROR_MESSAGES.notImplemented |
|||
break |
|||
case 502: |
|||
error.message = ERROR_MESSAGES.badGateway |
|||
break |
|||
case 503: |
|||
error.message = ERROR_MESSAGES.serviceUnavailable |
|||
break |
|||
case 504: |
|||
error.message = ERROR_MESSAGES.gatewayTimeout |
|||
break |
|||
case 505: |
|||
error.message = ERROR_MESSAGES.httpVersionNotSupported |
|||
break |
|||
default: |
|||
error.message = ERROR_MESSAGES.defaultConnectionError.replace( |
|||
'[原始错误消息]', |
|||
error.message |
|||
) |
|||
} |
|||
} else { |
|||
if (error.message === 'Network Error') { |
|||
error.message = ERROR_MESSAGES.networkError |
|||
} else { |
|||
error.message = ERROR_MESSAGES.serverFailure |
|||
} |
|||
} |
|||
return error.message |
|||
} |
|||
|
|||
// Request interceptors
|
|||
service.interceptors.request.use( |
|||
(config) => { |
|||
// 在此处添加请求头等,如添加 token
|
|||
// if (store.state.token) {
|
|||
// config.headers['Authorization'] = `Bearer ${store.state.token}`
|
|||
// }
|
|||
return config |
|||
}, |
|||
(error) => { |
|||
return Promise.reject(error) |
|||
} |
|||
) |
|||
|
|||
// Response interceptors
|
|||
service.interceptors.response.use( |
|||
async (response) => { |
|||
// await new Promise(resovle => setTimeout(resovle, 3000));
|
|||
// if (response.config.loadingInstance) {
|
|||
// response.config.loadingInstance.close();
|
|||
// }
|
|||
const res = response.data |
|||
if (res.code !== 200) { |
|||
const errorMsg = res.msg || 'Unkonw error' |
|||
// ElMessage.error(errorMsg)
|
|||
// return Promise.reject(new Error(res.msg || 'Error'))
|
|||
return response.data |
|||
} else { |
|||
return response.data |
|||
} |
|||
}, |
|||
(error) => { |
|||
const errorMessage = setErrorMsg(error) |
|||
ElMessage.error(errorMessage) |
|||
return Promise.reject(error) |
|||
} |
|||
) |
|||
|
|||
export default service |
@ -0,0 +1,16 @@ |
|||
<template> |
|||
<div> |
|||
<el-button type="primary" @click="goBack">返回首页</el-button> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { useRouter } from "vue-router"; |
|||
const router = useRouter(); |
|||
const goBack = () => { |
|||
router.push("/homepage"); |
|||
}; |
|||
</script> |
|||
|
|||
<style scoped> |
|||
</style> |
@ -0,0 +1,91 @@ |
|||
<template> |
|||
<header class="title"> |
|||
<div class="title-text" :style="fontSize"> |
|||
<img |
|||
v-if="props.colorBgc" |
|||
:src="titleLeft" |
|||
alt="" |
|||
class="title-text-img" |
|||
/> |
|||
<div v-if="props.colorBgc">{{ props.titleKey }}</div> |
|||
<img |
|||
v-if="props.colorBgc" |
|||
:src="titleRight" |
|||
alt="" |
|||
class="title-text-img" |
|||
/> |
|||
<img v-if="!props.colorBgc" :src="left" alt="" class="title-text-img" /> |
|||
<div v-if="!props.colorBgc">{{ props.titleKey }}</div> |
|||
<img v-if="!props.colorBgc" :src="right" alt="" class="title-text-img" /> |
|||
</div> |
|||
<div class="title-line"> |
|||
<img :src="bigLine" class="title-line-img" /> |
|||
</div> |
|||
</header> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { defineProps, computed } from "vue"; |
|||
|
|||
import right from "../../../assets/img/smallTitle/右.png"; |
|||
import left from "../../../assets/img/smallTitle/左.png"; |
|||
import titleRight from "../../../assets/img/smallTitle/title-jn-right.png"; |
|||
import titleLeft from "../../../assets/img/smallTitle/title-jn-left.png"; |
|||
import bigLine from "../../../assets/img/smallTitle/BigLine.png"; |
|||
|
|||
// 定义 props 接收传入的标题 |
|||
const props = defineProps({ |
|||
titleKey: { |
|||
type: String, |
|||
required: true, |
|||
}, |
|||
colorBgc: { |
|||
type: String, |
|||
required: true, |
|||
}, |
|||
}); |
|||
// 定义 fontSize 的类型,并确保 computed 返回正确的类型 |
|||
const fontSize = computed(() => { |
|||
// 简体或者繁体 |
|||
if (window.innerWidth < 768) { |
|||
return { fontSize: "3.5vw" }; |
|||
} else { |
|||
return { fontSize: "1.5vw" }; |
|||
} |
|||
}); |
|||
</script> |
|||
|
|||
<style scoped lang="less"> |
|||
.title { |
|||
position: relative; |
|||
.title-text { |
|||
font-size: 3vw; |
|||
display: flex; |
|||
align-items: center; |
|||
flex-wrap: wrap; |
|||
justify-content: center; |
|||
color: white; |
|||
.title-text-img { |
|||
width: 10%; |
|||
} |
|||
} |
|||
.title-line { |
|||
text-align: center; |
|||
position: absolute; |
|||
bottom: -1vw; |
|||
left: 50%; /* 将左边距设置为 50% */ |
|||
transform: translateX(-50%); /* 使用 transform 来将元素水平居中 */ |
|||
width: 85%; |
|||
.title-line-img { |
|||
width: 100%; |
|||
height: auto; |
|||
} |
|||
} |
|||
} |
|||
@media (min-width: 768px) { |
|||
.title-text-img { |
|||
width: 6% !important; |
|||
} |
|||
} |
|||
</style> |
|||
|
@ -0,0 +1,781 @@ |
|||
<template> |
|||
<div class="energyconverter"> |
|||
<div> |
|||
<smallTitle titleKey="情绪能量转化器" /> |
|||
</div> |
|||
<!-- k线图部分 --> |
|||
<div class="pricePrediction"> |
|||
<section class="price-Prediction"> |
|||
<div class="CanvsbackgroundImg"> |
|||
<div class="trapezoid" ref="stockNameContainer"> |
|||
<el-scrollbar v-if="isTextOverflow" class="stock-scrollbar"> |
|||
<div class="stock-marquee" :data-text="StockInformation.Name"> |
|||
<span |
|||
class="stock-name stock-name1" |
|||
style="white-space: nowrap; cursor: pointer" |
|||
>{{ StockInformation.Name }} {{ StockInformation.Code }}</span |
|||
> |
|||
</div> |
|||
</el-scrollbar> |
|||
<span |
|||
v-else |
|||
class="stock-name stock-name1" |
|||
style="white-space: nowrap; cursor: pointer" |
|||
>{{ StockInformation.Name }} {{ StockInformation.Code }}</span |
|||
> |
|||
</div> |
|||
<!-- k线图部分图纸 --> |
|||
<EnergyKlineEcharts class="k"></EnergyKlineEcharts> |
|||
</div> |
|||
</section> |
|||
</div> |
|||
<div class="smtcTitle"> |
|||
<smallTitle titleKey="功能介绍" /> |
|||
</div> |
|||
<div class="emotionDecoder" style="color: white"> |
|||
<div class="functionIntroduce" :class="currentLang"> |
|||
<ol> |
|||
<li> |
|||
<span class="area1" style="color: #ff9f9f">情绪冰点区</span |
|||
><span class="area1text" |
|||
>:市场极度悲观绝望后的末端。恐慌弥漫,投资者信心崩溃,普遍绝望,对利好麻木,对利空极度敏感,“割肉”离场意愿强烈。</span |
|||
> |
|||
</li> |
|||
<li> |
|||
<span class="area2" style="color: #ffcb75">认知潜伏区</span |
|||
><span class="area2text" |
|||
>:聪明资金建仓期,此时股票会呈现抗跌性但缺乏上涨动力。市场情绪低迷、悲观、缺乏信心,负面解读占主导,潜在利好逻辑被忽视或质疑。</span |
|||
> |
|||
</li> |
|||
<li> |
|||
<span class="area3" style="color: #d7e95d">多空消化区</span |
|||
><span class="area3text" |
|||
>:市场从单边下跌转向震荡企稳,多空力量从失衡转向初步平衡。恐慌情绪缓解,但信心依然脆弱,多空分歧加大,观望气氛浓厚。对利好利空反应不一。</span |
|||
> |
|||
</li> |
|||
<li> |
|||
<span class="area4" style="color: #a0f56f">共识加速区</span |
|||
><span class="area4text" |
|||
>:市场或个股形成上涨共识,进入主升浪。乐观情绪快速升温并扩散,信心高涨,看多成为主流,投资者追涨意愿强烈,对利空选择性忽视或解读为利好。</span |
|||
> |
|||
</li> |
|||
<li> |
|||
<span class="area5" style="color: #87f3cd">情绪临界区</span |
|||
><span class="area5text" |
|||
>:市场情绪达到极度亢奋、非理性的顶峰,上涨动能接近衰竭的临界点。狂热、贪婪情绪主导,估值体系失效,风险意识被抛诸脑后。</span |
|||
> |
|||
</li> |
|||
<li> |
|||
<span class="area6" style="color: #51c3f9">杠杆失衡区</span |
|||
><span class="area6text" |
|||
>:市场系统脆弱性急剧上升,价格波动被显著放大。情绪高度敏感且脆弱,波动剧烈引发恐慌。参与者普遍焦虑,对下跌的耐受度极低。</span |
|||
> |
|||
</li> |
|||
<li> |
|||
<span class="area7" style="color: #d0a7ff">情绪熔断区</span |
|||
><span class="area7text" |
|||
>:市场在极端负面情绪和恐慌抛售下,触发交易机制熔断或出现类似熔断效应的流动性瞬间枯竭状态。极度恐慌、绝望、非理性,信心彻底崩溃。</span |
|||
> |
|||
</li> |
|||
</ol> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="smtcTitle"> |
|||
<smallTitle titleKey="功能亮点" /> |
|||
</div> |
|||
<div class="emotionDecoder" style="color: white"> |
|||
<div class="functionlight"> |
|||
<span |
|||
class="lighttitle" |
|||
:style="{ |
|||
color: '#f8e71c', |
|||
whiteSpace: isChineseLanguage ? 'nowrap' : 'normal', |
|||
}" |
|||
>实现“财富裂变”的“情绪炼金炉”!</span |
|||
> |
|||
<br /> |
|||
|
|||
<span class="content"> |
|||
股市中蕴藏着巨大的情绪能量,恐惧与贪婪的碰撞产生市场波动势能,股市本质是亿万股民的情绪熔炉。情绪能量转化器,首次运用行为金融物理模型,将多空情绪的对冲转化为可定向输出的交易动能,通过“情绪炼金炉”将这种交易动能划分为七种反应堆,让每一场情绪风暴都成为你财富裂变的催化剂! |
|||
</span> |
|||
<br /> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { computed, ref, onMounted, onUnmounted, watch } from "vue"; |
|||
import { ElMessage } from "element-plus"; |
|||
import EnergyKlineEcharts from "./echarts/EnergyKlineEcharts.vue"; |
|||
import { fakeLinkDataListStore } from "../../../store/fakeLink-dataList"; |
|||
const dataListStore = fakeLinkDataListStore(); |
|||
import smallTitle from "../component/smallTitle.vue"; |
|||
import { useRouter, useRoute } from "vue-router"; |
|||
const router = useRouter(); |
|||
const StockInformation = ref({}); |
|||
// 监听窗口大小变化 |
|||
onMounted(() => { |
|||
new Promise((data, emotionData) => { |
|||
dataListStore.fetchChartData(); |
|||
dataListStore.getAiEmotinData(); |
|||
}); |
|||
StockInformation.value = dataListStore.AiEmotinData.StockInformation; |
|||
}); |
|||
</script> |
|||
|
|||
<style scoped lang="less"> |
|||
.energyconverter { |
|||
border: 1px solid rgba(28, 99, 206, 0.8); |
|||
background-color: rgba(255, 255, 255, 0.1); |
|||
border-radius: 8px; |
|||
min-height: 100%; |
|||
// height: 100%; |
|||
width: 69%; |
|||
margin: 0vw auto; |
|||
margin-top: 20px; |
|||
} |
|||
/* 标题样式 */ |
|||
.title { |
|||
color: white; |
|||
text-align: center; |
|||
margin-top: 1vw; |
|||
margin-bottom: 2vw; |
|||
font-size: 2vw; |
|||
} |
|||
|
|||
/* 功能介绍样式 */ |
|||
.functionIntroduce { |
|||
width: 100%; |
|||
|
|||
font-size: 1.6vw; |
|||
|
|||
position: relative; |
|||
line-height: 1.8; |
|||
margin-bottom: 0.8rem; |
|||
|
|||
ol { |
|||
padding-left: 2.5rem; |
|||
margin: 0; |
|||
counter-reset: item; |
|||
|
|||
@media (max-width: 768px) { |
|||
padding-left: 1.5rem; |
|||
} |
|||
} |
|||
|
|||
li { |
|||
@media (min-width: 769px) and (max-width: 1024px) { |
|||
padding: 0.8rem 1rem; |
|||
font-size: 1.5rem !important; |
|||
} |
|||
@media (max-width: 768px) { |
|||
padding: 0.3rem 0.8rem; |
|||
} |
|||
} |
|||
|
|||
.area { |
|||
display: inline-block; |
|||
font-size: clamp(1.2rem, 3vw, 1.6rem); |
|||
font-weight: bold; |
|||
margin-right: 0.8rem; |
|||
position: relative; |
|||
z-index: 12; |
|||
letter-spacing: 0.5px; |
|||
|
|||
@media (min-width: 769px) and (max-width: 1024px) { |
|||
font-size: 6rem !important; |
|||
} |
|||
|
|||
@media (max-width: 768px) { |
|||
font-size: clamp(1rem, 3.5vw, 1.2rem); |
|||
display: block; |
|||
} |
|||
} |
|||
|
|||
.text { |
|||
font-size: clamp(1.1rem, 2.5vw, 1.3rem); |
|||
|
|||
color: rgba(255, 255, 255, 0.95); |
|||
position: relative; |
|||
z-index: 12; |
|||
letter-spacing: 0.5px; |
|||
|
|||
@media (min-width: 769px) and (max-width: 1024px) { |
|||
font-size: clamp(1.2rem, 2.8vw, 1.4rem); |
|||
line-height: 1.6; |
|||
} |
|||
|
|||
@media (max-width: 768px) { |
|||
font-size: clamp(0.9rem, 3vw, 1.1rem); |
|||
display: block; |
|||
line-height: 1.4; |
|||
} |
|||
} |
|||
|
|||
br { |
|||
margin-top: 0.8rem; |
|||
display: block; |
|||
content: ""; |
|||
} |
|||
|
|||
@media (min-width: 769px) and (max-width: 1024px) { |
|||
padding: 1.5rem 1.2rem; |
|||
} |
|||
} |
|||
|
|||
.functionlight { |
|||
width: 100%; |
|||
padding: 2rem; |
|||
position: relative; |
|||
|
|||
.lighttitle { |
|||
display: block; |
|||
font-size: clamp(1.4rem, 3vw, 1.8rem); |
|||
margin-top: -0.5rem; |
|||
line-height: 1.5; |
|||
letter-spacing: 0.8px; |
|||
text-align: center; |
|||
width: 100%; |
|||
font-weight: bold; |
|||
|
|||
@media (min-width: 769px) and (max-width: 1024px) { |
|||
font-size: clamp(1.5rem, 3.2vw, 1.9rem); |
|||
margin-bottom: 0.5rem; |
|||
letter-spacing: 0.6px; |
|||
} |
|||
@media (max-width: 768px) { |
|||
font-size: clamp(1rem, 3.5vw, 1.3rem); |
|||
margin-bottom: 0.8rem; |
|||
letter-spacing: 0.5px; |
|||
padding: 0rem !important; |
|||
word-break: break-word; |
|||
} |
|||
} |
|||
|
|||
.content { |
|||
display: block; |
|||
font-size: 1.6vw; |
|||
line-height: 1.8; |
|||
color: rgba(255, 255, 255, 0.95); |
|||
margin-bottom: 0.8rem; |
|||
text-indent: 2em; |
|||
@media (min-width: 769px) and (max-width: 1024px) { |
|||
font-size: clamp(1.2rem, 2.8vw, 1.4rem); |
|||
line-height: 1.5; |
|||
padding: 0.8rem 0.5rem; |
|||
text-align: justify; |
|||
} |
|||
|
|||
@media (max-width: 768px) { |
|||
font-size: 0.9rem; |
|||
padding: 0.3rem 0.5rem; |
|||
text-align: justify; |
|||
} |
|||
} |
|||
|
|||
br { |
|||
margin-top: 0.8rem; |
|||
display: block; |
|||
content: ""; |
|||
} |
|||
|
|||
/* 响应式调整 - 平板设备 */ |
|||
@media (min-width: 769px) and (max-width: 1024px) { |
|||
padding: 1.5rem 1.2rem; |
|||
} |
|||
|
|||
/* 响应式调整 - 手机设备 */ |
|||
@media (max-width: 768px) { |
|||
padding: 1.2rem 0.8rem; |
|||
} |
|||
} |
|||
|
|||
/* k线图部分 样式*/ |
|||
.pricePrediction { |
|||
color: white; |
|||
|
|||
.price-Prediction { |
|||
position: relative; |
|||
|
|||
/* 标题 */ |
|||
.trapezoid { |
|||
position: absolute; |
|||
top: 9%; |
|||
left: 7%; |
|||
color: #a7691c; |
|||
font-weight: bold; |
|||
font-size: 2vw; |
|||
z-index: 999; |
|||
} |
|||
|
|||
/* 滚动条样式 */ |
|||
.stock-scrollbar { |
|||
width: 70%; |
|||
height: auto; |
|||
} |
|||
|
|||
.stock-marquee { |
|||
display: inline-block; |
|||
white-space: nowrap; |
|||
animation: marquee 10s linear infinite; |
|||
position: relative; |
|||
} |
|||
|
|||
.stock-marquee::after { |
|||
content: " " attr(data-text); /* 使用全角空格让中间空出来 */ |
|||
position: absolute; |
|||
left: 100%; |
|||
white-space: nowrap; |
|||
color: #a7691c; |
|||
} |
|||
|
|||
@keyframes marquee { |
|||
0% { |
|||
transform: translateX(0%); |
|||
} |
|||
100% { |
|||
transform: translateX(-120%); |
|||
} |
|||
} |
|||
|
|||
.scrollbar-flex-content { |
|||
display: flex; |
|||
width: 130px; |
|||
} |
|||
|
|||
.stock-name { |
|||
/* margin-top: 5px; */ |
|||
/* display: flex; */ |
|||
width: 100%; |
|||
cursor: pointer; |
|||
white-space: nowrap; |
|||
text-align: center; |
|||
/* align-items: center; */ |
|||
/* justify-content: center; */ |
|||
} |
|||
|
|||
/* 背景 */ |
|||
.CanvsbackgroundImg { |
|||
background-image: url("https://d31zlh4on95l9h.cloudfront.net/images/892dc6e2755ecc9cf6fb41561c287acf.png"); |
|||
background-repeat: no-repeat; |
|||
background-size: 100% 100%; |
|||
height: 44vw; |
|||
max-width: 95%; // 添加这行,限制最大宽度 |
|||
padding: 20px 0px; // 减少左右内边距,从 10px 改为 5px |
|||
box-sizing: border-box; // 改为 border-box 以包含内边距 |
|||
position: relative; |
|||
margin: 3vw auto 5vw auto; // 添加 auto 实现水平居中 |
|||
// margin-left: 30px; // 删除固定左边距 |
|||
// margin-right: 30px; // 删除固定右边距 |
|||
} |
|||
} |
|||
} |
|||
|
|||
.smtcTitle { |
|||
margin-top: -1rem; |
|||
margin-bottom: 1rem; |
|||
position: relative; |
|||
z-index: 5; |
|||
|
|||
/* 响应式调整 */ |
|||
@media (max-width: 768px) { |
|||
margin-top: -0.5rem; |
|||
margin-bottom: 0.5rem; |
|||
} |
|||
} |
|||
|
|||
/* 情绪解码器解释样式 - 响应式优化 */ |
|||
.emotionDecoder { |
|||
/* 透明背景,方形边框样式 */ |
|||
background-image: url("https://d31zlh4on95l9h.cloudfront.net/images/03e7df3bde2e80f71718b25fee3d4b98.png"); |
|||
background-repeat: no-repeat; |
|||
background-size: 100% 100%; |
|||
height: auto; |
|||
position: relative; |
|||
display: flex; |
|||
padding: clamp(1.5rem, 3vw, 2.5rem); |
|||
/* 确保左右边距完全相等 */ |
|||
width: 92%; |
|||
max-width: 1200px; |
|||
margin: clamp(1.5rem, 4vw, 3rem) auto; |
|||
/* 使用 auto 确保左右边距相等 */ |
|||
letter-spacing: 0.5px; |
|||
// min-height: 220px; |
|||
justify-content: space-between; |
|||
align-items: center; |
|||
box-sizing: border-box; |
|||
overflow-x: hidden; |
|||
|
|||
/* 响应式调整 */ |
|||
@media (max-width: 768px) { |
|||
padding: clamp(1rem, 2vw, 1.5rem); |
|||
width: 95%; |
|||
min-height: 180px; |
|||
margin: clamp(1rem, 2vw, 1.5rem) auto; |
|||
} |
|||
|
|||
.box { |
|||
display: flex; |
|||
flex-direction: row; |
|||
width: 100%; |
|||
height: 100%; |
|||
gap: clamp(1.5rem, 3vw, 2.5rem); |
|||
position: relative; |
|||
z-index: 5; |
|||
|
|||
/* 响应式调整 */ |
|||
@media (max-width: 768px) { |
|||
flex-direction: column; |
|||
gap: clamp(1rem, 2vw, 1.5rem); |
|||
} |
|||
} |
|||
|
|||
// .message1, |
|||
// .message2 { |
|||
// color: white; |
|||
// padding: clamp(0.75rem, 1.5vw, 1.5rem); |
|||
// position: relative; |
|||
// flex: 1; |
|||
// border-radius: 4px; |
|||
// background: rgba(255, 255, 255, 0.05); |
|||
// backdrop-filter: blur(10px); |
|||
|
|||
// } |
|||
|
|||
.message1-en { |
|||
margin-left: 10px !important; |
|||
} |
|||
|
|||
.title1-en, |
|||
.title2-en { |
|||
font-size: clamp(0.875rem, 1.2vw, 1.125rem); |
|||
color: #f8e71c; |
|||
font-weight: 600; |
|||
margin-bottom: clamp(0.5rem, 1vw, 1rem); |
|||
letter-spacing: 0.3px; |
|||
} |
|||
|
|||
.message2-en { |
|||
color: white; |
|||
padding: clamp(0.75rem, 1.5vw, 1.5rem); |
|||
font-size: clamp(0.75rem, 1vw, 0.95rem); |
|||
line-height: 1.6; |
|||
} |
|||
|
|||
.cycle-stage-table { |
|||
margin-top: clamp(1rem, 2vw, 2rem); |
|||
width: 100%; |
|||
overflow-x: auto; |
|||
|
|||
table { |
|||
width: 100%; |
|||
border-collapse: collapse; |
|||
background: rgba(255, 255, 255, 0.05); |
|||
backdrop-filter: blur(10px); |
|||
border-radius: 8px; |
|||
overflow: hidden; |
|||
border: 1px solid rgba(74, 144, 226, 0.3); |
|||
|
|||
th, |
|||
td { |
|||
padding: clamp(0.75rem, 1.5vw, 1rem); |
|||
text-align: center; |
|||
border: 1px solid rgba(74, 144, 226, 0.2); |
|||
color: white; |
|||
font-size: clamp(0.8rem, 1vw, 1rem); |
|||
line-height: 1.4; |
|||
} |
|||
|
|||
th { |
|||
background: rgba(74, 144, 226, 0.3); |
|||
color: white; |
|||
font-weight: 600; |
|||
letter-spacing: 0.5px; |
|||
} |
|||
|
|||
tbody tr:nth-child(even) { |
|||
background: rgba(255, 255, 255, 0.02); |
|||
} |
|||
|
|||
tbody tr:hover { |
|||
background: rgba(74, 144, 226, 0.1); |
|||
transition: background 0.3s ease; |
|||
} |
|||
|
|||
td:first-child { |
|||
font-weight: 600; |
|||
color: white; |
|||
} |
|||
} |
|||
} |
|||
|
|||
/* 温度区间表格样式 */ |
|||
.temperature-table { |
|||
margin-top: clamp(1rem, 2vw, 2rem); |
|||
width: 100%; |
|||
overflow-x: auto; |
|||
|
|||
table { |
|||
width: 100%; |
|||
border-collapse: collapse; |
|||
background: rgba(255, 255, 255, 0.05); |
|||
backdrop-filter: blur(10px); |
|||
border-radius: 8px; |
|||
overflow: hidden; |
|||
border: 1px solid rgba(74, 144, 226, 0.3); |
|||
|
|||
th, |
|||
td { |
|||
padding: clamp(0.75rem, 1.5vw, 1rem); |
|||
text-align: center; |
|||
border: 1px solid rgba(74, 144, 226, 0.2); |
|||
color: white; |
|||
font-size: clamp(0.8rem, 1vw, 1rem); |
|||
line-height: 1.4; |
|||
} |
|||
|
|||
th { |
|||
background: rgba(74, 144, 226, 0.3); |
|||
color: white; |
|||
font-weight: 600; |
|||
letter-spacing: 0.5px; |
|||
} |
|||
|
|||
tbody tr:nth-child(even) { |
|||
background: rgba(255, 255, 255, 0.02); |
|||
} |
|||
|
|||
tbody tr:hover { |
|||
background: rgba(74, 144, 226, 0.1); |
|||
transition: background 0.3s ease; |
|||
} |
|||
|
|||
td:first-child { |
|||
font-weight: 600; |
|||
color: white; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
/* 在当前组件的style标签中添加以下代码 */ |
|||
:deep(.echarts-container) { |
|||
background-color: #ffffff !important; // 修改为你想要的背景颜色 |
|||
} |
|||
|
|||
/* pc端 */ |
|||
/* 媒体查询(与原页面保持一致) */ |
|||
@media (min-width: 768px) { |
|||
} |
|||
|
|||
@media (min-width: 768px) and (max-width: 1024px) { |
|||
} |
|||
|
|||
/* 大屏幕设备响应式 - message1和message2竖着排 */ |
|||
@media (min-width: 1025px) { |
|||
.emotionDecoder { |
|||
.box { |
|||
flex-direction: column; |
|||
gap: clamp(1rem, 2vw, 2rem); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/* 平板设备响应式 */ |
|||
@media (max-width: 1024px) { |
|||
.emotionDecoder { |
|||
// margin: clamp(0.75rem, 2vw, 1.5rem); |
|||
// padding: clamp(0.75rem, 1.5vw, 1.5rem); |
|||
|
|||
.box { |
|||
flex-direction: column; |
|||
gap: clamp(0.75rem, 1.5vw, 1.25rem); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/* 移动设备响应式 */ |
|||
@media (max-width: 768px) { |
|||
.functionIntroduce { |
|||
font-size: 0.9rem !important; |
|||
padding: 0 !important; |
|||
padding-left: 0rem !important; |
|||
|
|||
/* 非中文语言在移动设备上的上下边距 */ |
|||
&.en, |
|||
&.th, |
|||
&.kr { |
|||
padding-top: 2rem !important; |
|||
padding-bottom: 2rem !important; |
|||
|
|||
/* 确保英文版本与中文版本字体大小一致 */ |
|||
.area1, |
|||
.area2, |
|||
.area3, |
|||
.area4, |
|||
.area5, |
|||
.area6, |
|||
.area7 { |
|||
font-size: clamp(1rem, 3.5vw, 1.2rem) !important; |
|||
} |
|||
|
|||
.area1text, |
|||
.area2text, |
|||
.area3text, |
|||
.area4text, |
|||
.area5text, |
|||
.area6text, |
|||
.area7text { |
|||
font-size: clamp(0.9rem, 3vw, 1.1rem) !important; |
|||
} |
|||
} |
|||
} |
|||
.pricePrediction .price-Prediction { |
|||
margin-bottom: 2rem; |
|||
|
|||
.trapezoid { |
|||
font-size: 25px !important; |
|||
text-align: center; |
|||
top: 4.5%; |
|||
|
|||
.scrollbar-flex-content { |
|||
display: flex; |
|||
width: 260px; |
|||
} |
|||
} |
|||
|
|||
.CanvsbackgroundImg { |
|||
background-image: url(https://d31zlh4on95l9h.cloudfront.net/images/a3db9928e5e0b50e781ada5d4fa8dc43.png); |
|||
// padding: 40vw 5vw; |
|||
margin-top: 5vw !important; |
|||
background-size: 100% 100%; |
|||
width: 100%; |
|||
max-width: 95%; |
|||
height: 120vw; |
|||
} |
|||
} |
|||
|
|||
.emotionDecoder { |
|||
margin-bottom: 2rem; |
|||
|
|||
.box { |
|||
flex-direction: column; |
|||
gap: 1rem; |
|||
} |
|||
|
|||
.message1-en { |
|||
margin-left: 20px !important; |
|||
} |
|||
|
|||
.title1-en, |
|||
.title2-en { |
|||
font-size: 1rem; |
|||
margin-bottom: 0.5rem; |
|||
} |
|||
|
|||
.message2-en { |
|||
font-size: 0.875rem; |
|||
padding: 0.75rem; |
|||
margin: 0.5rem 0; |
|||
} |
|||
} |
|||
|
|||
.title { |
|||
font-size: 4vw !important; |
|||
} |
|||
|
|||
.title1 { |
|||
font-size: 2.8vw !important; |
|||
} |
|||
|
|||
.title1-en { |
|||
font-size: 2.8vw !important; /* 统一与中文版本相同的字体大小 */ |
|||
top: -20px !important; |
|||
} |
|||
|
|||
.message2 { |
|||
font-size: 3vw !important; |
|||
} |
|||
|
|||
.message2-en { |
|||
font-size: 3vw !important; |
|||
margin: 35px 0px 20px 0px !important; |
|||
} |
|||
|
|||
/* 获取报告图按钮样式 */ |
|||
// .getReport { |
|||
// height: 25vw; |
|||
// bottom: -5vw; |
|||
// } |
|||
|
|||
.title2 { |
|||
font-size: 2.8vw !important; |
|||
// margin-top: -4%; |
|||
} |
|||
|
|||
.title2-en { |
|||
font-size: 2.8vw !important; /* 统一与中文版本相同的字体大小 */ |
|||
// margin-top: -4%; |
|||
} |
|||
} |
|||
|
|||
/* 小屏幕设备响应式 */ |
|||
@media (max-width: 480px) { |
|||
.pricePrediction { |
|||
.price-Prediction { |
|||
.trapezoid { |
|||
font-size: 25px !important; |
|||
text-align: center; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.emotionDecoder { |
|||
.message1, |
|||
.message2 { |
|||
padding: 0.5rem; |
|||
} |
|||
|
|||
.message2-en { |
|||
font-size: 0.8rem; |
|||
} |
|||
|
|||
.cycle-stage-table { |
|||
margin: 0.5rem 0; |
|||
|
|||
table { |
|||
th, |
|||
td { |
|||
padding: 0.5rem 0.25rem; |
|||
font-size: 0.75rem; |
|||
line-height: 1.3; |
|||
} |
|||
|
|||
th { |
|||
font-size: 0.8rem; |
|||
} |
|||
} |
|||
} |
|||
|
|||
/* 移动端表格样式 */ |
|||
.temperature-table { |
|||
margin: 0.5rem 0; |
|||
|
|||
table { |
|||
th, |
|||
td { |
|||
padding: 0.5rem 0.25rem; |
|||
font-size: 0.75rem; |
|||
line-height: 1.3; |
|||
} |
|||
|
|||
th { |
|||
font-size: 0.8rem; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</style> |
1238
src/views/fakeLink/dbqb/echarts/EnergyKlineEcharts.vue
File diff suppressed because it is too large
View File
@ -0,0 +1,231 @@ |
|||
<template> |
|||
<div class="container"> |
|||
<div class="head"> |
|||
<div class="head1"> |
|||
<div class="head1Btn"> |
|||
<img class="headImg" src="../../../public/left.png" alt="" /> |
|||
</div> |
|||
<div class="head1Btn"> |
|||
<img class="headImg" src="../../../public/right.png" alt="" /> |
|||
</div> |
|||
<div class="head1Btn"> |
|||
<img class="headImg" src="../../../public/refresh.png" alt="" /> |
|||
</div> |
|||
<div class="head1Btn"> |
|||
<img class="headImg" src="../../../public/home.png" alt="" /> |
|||
</div> |
|||
</div> |
|||
<div class="head2"> |
|||
<div class="rightGroup"> |
|||
<div class="head2Btn">产品下载</div> |
|||
</div> |
|||
<div class="leftGroup"> |
|||
<div class="head2Btn">消息</div> |
|||
<div class="head2Btn">精网原创</div> |
|||
<div class="head2Btn" v-if="dataListStore.userInfo.token"> |
|||
<el-popover :width="150"> |
|||
<template #reference> |
|||
<div class="userInfo"> |
|||
<img :src="dataListStore.userInfo.img" alt="头像" /> |
|||
<span class="nickname">{{ |
|||
dataListStore.userInfo.nickname |
|||
}}</span> |
|||
</div> |
|||
</template> |
|||
<template #default> |
|||
<div class="userInfoBtn myAccount">我的账户</div> |
|||
<div class="userInfoBtn coupon">优惠券</div> |
|||
<div class="userInfoBtn myOrder">我的订单</div> |
|||
<div class="userInfoBtn" @click="logout">退出登录</div> |
|||
</template> |
|||
</el-popover> |
|||
</div> |
|||
<div class="head2Btn" v-else @click="login">登录</div> |
|||
<div class="head2Btn">多语言</div> |
|||
<div class="head2Btn">市场</div> |
|||
<div class="head2Btn">反馈帮助中心</div> |
|||
</div> |
|||
</div> |
|||
<div class="head3"> |
|||
<img |
|||
src="https://d31zlh4on95l9h.cloudfront.net/assets/heimaxunzhang/blueHomliyLink.png" |
|||
alt="logo" |
|||
class="logo" |
|||
@click="router.push('/fakeLink')" |
|||
/> |
|||
<div class="breadCrumb"> |
|||
<div @click="router.push('/fakeLink')" class="homePage">首页</div> |
|||
<span class="separator">/</span> |
|||
<div @click="router.push('/dbqb')" class="dbqb">夺宝奇兵</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="body"> |
|||
<div class="bodyContent"> |
|||
<router-view></router-view> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { ref, onMounted, nextTick } from "vue"; |
|||
import { fakeLinkDataListStore } from "../../store/fakeLink-dataList.js"; |
|||
const dataListStore = fakeLinkDataListStore(); |
|||
import { useRouter } from "vue-router"; |
|||
const router = useRouter(); |
|||
const login = () => { |
|||
router.push("/fakeLinkLogin"); |
|||
}; |
|||
|
|||
const logout = () => { |
|||
router.push("/fakeLinkLogin"); |
|||
}; |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.container { |
|||
width: 100%; |
|||
height: 100%; |
|||
overflow: hidden; |
|||
} |
|||
.head { |
|||
width: 100%; |
|||
position: fixed; |
|||
top: 0px; |
|||
} |
|||
|
|||
.head1 { |
|||
width: 100%; |
|||
height: 40px; |
|||
background-color: white; |
|||
display: flex; |
|||
align-items: center; |
|||
color: white; |
|||
} |
|||
|
|||
.head2 { |
|||
width: 100%; |
|||
height: 45px; |
|||
background-color: #222222; |
|||
display: flex; |
|||
align-items: center; |
|||
color: white; |
|||
} |
|||
|
|||
.head3 { |
|||
padding: 0 60px; |
|||
width: 100%; |
|||
height: 60px; |
|||
color: #808080; |
|||
display: flex; |
|||
align-items: center; |
|||
} |
|||
|
|||
.logo { |
|||
width: 142px; |
|||
height: 24px; |
|||
margin-right: 100px; |
|||
cursor: pointer; |
|||
} |
|||
|
|||
.breadCrumb { |
|||
display: flex; |
|||
} |
|||
|
|||
.homePage { |
|||
cursor: pointer; |
|||
} |
|||
|
|||
.separator { |
|||
margin: 0 5px; |
|||
} |
|||
|
|||
.dbqb { |
|||
cursor: pointer; |
|||
} |
|||
|
|||
.body { |
|||
padding: 145px 0 0 0; |
|||
box-sizing: border-box; |
|||
height: 100%; |
|||
overflow: hidden; |
|||
} |
|||
|
|||
.bodyContent { |
|||
background-image: url("https://d31zlh4on95l9h.cloudfront.net/images/fba08457e53a11186eee9dacab51e344.png"); |
|||
background-size: 100% 100%; |
|||
height: 100%; |
|||
overflow: auto; |
|||
} |
|||
|
|||
.headImg { |
|||
height: 30px; |
|||
width: 30px; |
|||
} |
|||
|
|||
.head1Btn { |
|||
height: 100%; |
|||
padding: 0 10px; |
|||
cursor: pointer; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
} |
|||
.head1Btn:hover { |
|||
background-color: #d3d3d3; |
|||
} |
|||
|
|||
.head2Btn { |
|||
height: 100%; |
|||
padding: 0 10px; |
|||
cursor: pointer; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
} |
|||
.head2Btn:hover { |
|||
background-color: #333333; |
|||
} |
|||
|
|||
.rightGroup { |
|||
height: 100%; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
} |
|||
|
|||
.leftGroup { |
|||
height: 100%; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
margin-left: auto; |
|||
} |
|||
|
|||
.userInfo { |
|||
display: flex; |
|||
justify-content: center; |
|||
} |
|||
|
|||
.nickname { |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
} |
|||
|
|||
.userInfoBtn { |
|||
color: #409eff; |
|||
font-size: 14px; |
|||
padding: 0 20px; |
|||
white-space: nowrap; |
|||
overflow: hidden; |
|||
height: 34px; |
|||
line-height: 34px; |
|||
box-sizing: border-box; |
|||
cursor: pointer; |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
} |
|||
</style> |
@ -0,0 +1,471 @@ |
|||
<template> |
|||
<div class="container"> |
|||
<div class="head"> |
|||
<div class="head1"> |
|||
<div class="head1Btn"> |
|||
<img class="headImg" src="../../../public/left.png" alt="" /> |
|||
</div> |
|||
<div class="head1Btn"> |
|||
<img class="headImg" src="../../../public/right.png" alt="" /> |
|||
</div> |
|||
<div class="head1Btn"> |
|||
<img class="headImg" src="../../../public/refresh.png" alt="" /> |
|||
</div> |
|||
<div class="head1Btn"> |
|||
<img class="headImg" src="../../../public/home.png" alt="" /> |
|||
</div> |
|||
</div> |
|||
<div class="head2"> |
|||
<div class="rightGroup"> |
|||
<div class="head2Btn">产品下载</div> |
|||
</div> |
|||
<div class="leftGroup"> |
|||
<div class="head2Btn">消息</div> |
|||
<div class="head2Btn">精网原创</div> |
|||
<div class="head2Btn" v-if="dataListStore.userInfo.token"> |
|||
<el-popover :width="150"> |
|||
<template #reference> |
|||
<div class="userInfo"> |
|||
<img :src="dataListStore.userInfo.img" alt="头像" /> |
|||
<span class="nickname">{{ |
|||
dataListStore.userInfo.nickname |
|||
}}</span> |
|||
</div> |
|||
</template> |
|||
<template #default> |
|||
<div class="userInfoBtn myAccount">我的账户</div> |
|||
<div class="userInfoBtn coupon">优惠券</div> |
|||
<div class="userInfoBtn myOrder">我的订单</div> |
|||
<div class="userInfoBtn" @click="logout">退出登录</div> |
|||
</template> |
|||
</el-popover> |
|||
</div> |
|||
<div class="head2Btn" v-else @click="login">登录</div> |
|||
<div class="head2Btn">多语言</div> |
|||
<div class="head2Btn">市场</div> |
|||
<div class="head2Btn">反馈帮助中心</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="body"> |
|||
<el-container> |
|||
<el-aside width="150px"> |
|||
<img |
|||
src="https://d31zlh4on95l9h.cloudfront.net/assets/homily-jingwangHw.png" |
|||
alt="logo" |
|||
class="logo" |
|||
/> |
|||
<div |
|||
v-for="item in leftList" |
|||
:key="item" |
|||
class="leftItem" |
|||
:class="{ leftItemActive: nowLeftItem == item }" |
|||
@click="clickLeftItem(item)" |
|||
> |
|||
{{ item }} |
|||
</div> |
|||
</el-aside> |
|||
<el-main class="bodyMain"> |
|||
<div class="oneLine"> |
|||
<el-carousel |
|||
height="150px" |
|||
direction="vertical" |
|||
:autoplay="true" |
|||
indicator-position="outside" |
|||
> |
|||
<el-carousel-item v-for="item in middleList" :key="item"> |
|||
<img :src="item.img" alt="" class="carouselImg" /> |
|||
</el-carousel-item> |
|||
</el-carousel> |
|||
</div> |
|||
<div class="twoLine"> |
|||
<div class="search"> |
|||
<input |
|||
type="text" |
|||
class="searchBox" |
|||
placeholder="请输入要搜索的内容" |
|||
/> |
|||
<div class="searchBtn">搜索</div> |
|||
</div> |
|||
<div class="dbqb"> |
|||
<div class="dbqbTitle">夺宝奇兵</div> |
|||
<img |
|||
class="dbqbUrl" |
|||
src="https://d31zlh4on95l9h.cloudfront.net/images/4abaf213-6ced-4605-aca7-d7ff97c4d311.gif" |
|||
alt="" |
|||
@click="toDbqb" |
|||
/> |
|||
</div> |
|||
</div> |
|||
</el-main> |
|||
</el-container> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { ref, onMounted, nextTick } from "vue"; |
|||
import { fakeLinkDataListStore } from "../../store/fakeLink-dataList.js"; |
|||
const dataListStore = fakeLinkDataListStore(); |
|||
import { useRouter } from "vue-router"; |
|||
const router = useRouter(); |
|||
const leftList = ref([ |
|||
"关注", |
|||
"推荐", |
|||
"频道", |
|||
"资讯", |
|||
"轻松一刻", |
|||
"公司达人动态", |
|||
"剧场", |
|||
"任务中心", |
|||
"静态专区", |
|||
"视频", |
|||
"心愿池", |
|||
"电子书", |
|||
"弘历软件", |
|||
"征文", |
|||
"Homily Chart", |
|||
"炒股心理", |
|||
"技术分析新得", |
|||
"更多", |
|||
]); |
|||
|
|||
const middleList = ref([ |
|||
{ |
|||
img: "https://d31zlh4on95l9h.cloudfront.net/images/5iujc501000dcoq046ryswk8p0qyj36t.jpg", |
|||
name: "今日直播", |
|||
}, |
|||
{ |
|||
img: "https://d31zlh4on95l9h.cloudfront.net/images/5iujc501000dco901dbcdjc7b04pl1k3.jpg", |
|||
name: "智见未来", |
|||
}, |
|||
{ |
|||
img: "https://d31zlh4on95l9h.cloudfront.net/images/5iujc501000dco7vaxmzf8e6v0o0yu14.jpg", |
|||
name: "课程安排", |
|||
}, |
|||
{ |
|||
img: "https://d31zlh4on95l9h.cloudfront.net/images/5iujc501000dcktw5n7cy7a17zrvf0cv.jpg", |
|||
name: "财神香港", |
|||
}, |
|||
{ |
|||
img: "https://d31zlh4on95l9h.cloudfront.net/images/5iujc501000dco8a40jtj9v6y0lba30k.png", |
|||
name: "情绪周期", |
|||
}, |
|||
{ |
|||
img: "https://d31zlh4on95l9h.cloudfront.net/images/5iujc501000dcncaw58dwlt5603ezwpz.jpg", |
|||
name: "MY线下", |
|||
}, |
|||
]); |
|||
|
|||
const login = () => { |
|||
router.push("/fakeLinkLogin"); |
|||
}; |
|||
|
|||
const logout = () => { |
|||
router.push("/fakeLinkLogin"); |
|||
}; |
|||
|
|||
const nowLeftItem = ref("推荐"); |
|||
const clickLeftItem = (item) => { |
|||
nowLeftItem.value = item; |
|||
console.log(item); |
|||
}; |
|||
|
|||
const carouselRef = ref(null); |
|||
|
|||
onMounted(async () => { |
|||
await nextTick(); |
|||
// 获取所有指示器按钮 |
|||
const indicators = document.querySelectorAll(".el-carousel__button"); |
|||
|
|||
// 为每个指示器添加对应的名称 |
|||
indicators.forEach((button, index) => { |
|||
console.log(button); |
|||
if (middleList.value[index]) { |
|||
// 或者直接设置文本内容 |
|||
button.textContent = middleList.value[index].name; |
|||
} |
|||
}); |
|||
}); |
|||
|
|||
const toDbqb = () => { |
|||
router.push("/dbqb"); |
|||
}; |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.container { |
|||
width: 100%; |
|||
height: 100%; |
|||
} |
|||
.head { |
|||
width: 100%; |
|||
position: fixed; |
|||
top: 0px; |
|||
} |
|||
|
|||
.head1 { |
|||
width: 100%; |
|||
height: 40px; |
|||
background-color: white; |
|||
display: flex; |
|||
align-items: center; |
|||
color: white; |
|||
} |
|||
|
|||
.head2 { |
|||
width: 100%; |
|||
height: 45px; |
|||
background-color: #222222; |
|||
display: flex; |
|||
align-items: center; |
|||
color: white; |
|||
} |
|||
|
|||
.body { |
|||
padding: 100px 380px 0 380px; |
|||
box-sizing: border-box; |
|||
} |
|||
|
|||
.headImg { |
|||
height: 30px; |
|||
width: 30px; |
|||
} |
|||
|
|||
.head1Btn { |
|||
height: 100%; |
|||
padding: 0 10px; |
|||
cursor: pointer; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
} |
|||
.head1Btn:hover { |
|||
background-color: #d3d3d3; |
|||
} |
|||
|
|||
.head2Btn { |
|||
height: 100%; |
|||
padding: 0 10px; |
|||
cursor: pointer; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
} |
|||
.head2Btn:hover { |
|||
background-color: #333333; |
|||
} |
|||
|
|||
.rightGroup { |
|||
height: 100%; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
} |
|||
|
|||
.leftGroup { |
|||
height: 100%; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
margin-left: auto; |
|||
} |
|||
|
|||
.userInfo { |
|||
display: flex; |
|||
justify-content: center; |
|||
} |
|||
|
|||
.nickname { |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
} |
|||
|
|||
.userInfoBtn { |
|||
color: #409eff; |
|||
font-size: 14px; |
|||
padding: 0 20px; |
|||
white-space: nowrap; |
|||
overflow: hidden; |
|||
height: 34px; |
|||
line-height: 34px; |
|||
box-sizing: border-box; |
|||
cursor: pointer; |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
} |
|||
/* .userInfoBtn:hover{ |
|||
|
|||
} */ |
|||
|
|||
.myAccount { |
|||
} |
|||
|
|||
.logo { |
|||
width: 80%; |
|||
/* height: 100%; */ |
|||
} |
|||
|
|||
.leftItem { |
|||
width: 80%; |
|||
height: 38px; |
|||
line-height: 38px; |
|||
border-radius: 4px; |
|||
font-size: 16px; |
|||
color: black; |
|||
cursor: pointer; |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
margin-bottom: 1.5px; |
|||
} |
|||
|
|||
.leftItem:hover { |
|||
background-color: rgb(69, 131, 254); |
|||
color: white; |
|||
} |
|||
|
|||
.leftItemActive { |
|||
background-color: rgb(69, 131, 254); |
|||
color: white; |
|||
} |
|||
|
|||
.bodyMain { |
|||
padding: 0; |
|||
display: flex; |
|||
} |
|||
|
|||
.oneLine { |
|||
/* border: 1px solid red; */ |
|||
width: 65%; |
|||
} |
|||
|
|||
.carouselImg { |
|||
width: 100%; |
|||
height: 300px; |
|||
} |
|||
|
|||
.twoLine { |
|||
/* border: 1px solid blue; */ |
|||
width: 35%; |
|||
} |
|||
|
|||
.search { |
|||
width: 100%; |
|||
height: 44px; |
|||
display: flex; |
|||
background-color: rgba(142, 142, 142, 0.05); |
|||
font-size: 16px; |
|||
} |
|||
|
|||
.searchBox { |
|||
background-color: rgba(245, 246, 247); |
|||
width: 78%; |
|||
padding: 10px; |
|||
border: 0.2px #76767618 solid; |
|||
font-size: 14px; |
|||
color: rgb(85, 85, 85) !important; |
|||
outline: none; |
|||
} |
|||
|
|||
.searchBox:hover { |
|||
border: 1px solid #409eff; |
|||
} |
|||
|
|||
.searchBox:focus { |
|||
border: 1px solid #409eff; /* 聚焦时的边框颜色 */ |
|||
} |
|||
|
|||
.searchBtn { |
|||
color: white; |
|||
background-color: rgb(32, 142, 218); |
|||
cursor: pointer; |
|||
margin-left: auto; |
|||
width: 22%; |
|||
height: 100%; |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
} |
|||
|
|||
.dbqb { |
|||
box-sizing: border-box; |
|||
width: 100%; |
|||
padding: 15px; |
|||
font-size: 14px; |
|||
margin-top: 15px; |
|||
border-radius: 4px; |
|||
background-color: rgba(142, 142, 142, 0.05); |
|||
} |
|||
|
|||
.dbqbTitle { |
|||
font-size: 18px; |
|||
color: rgb(34, 34, 34); |
|||
font-weight: bold; |
|||
margin-bottom: 30px; |
|||
} |
|||
|
|||
.dbqbUrl { |
|||
width: 100%; |
|||
} |
|||
</style> |
|||
|
|||
<style> |
|||
.el-carousel--vertical { |
|||
display: flex; |
|||
} |
|||
|
|||
.el-carousel__container { |
|||
width: 91%; |
|||
height: 300px !important; |
|||
} |
|||
|
|||
.el-carousel__indicators--outside { |
|||
background-color: black; |
|||
width: 9%; |
|||
display: flex; |
|||
flex-direction: column; |
|||
justify-content: center; |
|||
} |
|||
|
|||
.el-carousel__indicator--vertical { |
|||
height: 50px; |
|||
width: 100%; |
|||
box-sizing: border-box; |
|||
color: white; |
|||
cursor: pointer; |
|||
font-size: 14px; |
|||
padding: 5px 0; |
|||
transition: all 0.3s ease-out; |
|||
/* background-color: rgb(0, 0, 0) !important; */ |
|||
overflow: hidden; |
|||
} |
|||
|
|||
/* .el-carousel__indicator--vertical .el-carousel__button{ |
|||
|
|||
} */ |
|||
|
|||
.el-carousel__button { |
|||
margin: 0; |
|||
height: 100% !important; |
|||
width: 100% !important; |
|||
border-radius: 0 !important; |
|||
color: white; |
|||
outline: none; |
|||
} |
|||
|
|||
.el-carousel__indicators--outside button { |
|||
opacity: 1 !important; |
|||
background-color: transparent !important; |
|||
} |
|||
|
|||
.is-active { |
|||
background-color: #fa2c19; |
|||
} |
|||
|
|||
button { |
|||
outline: none; |
|||
} |
|||
</style> |
@ -0,0 +1,163 @@ |
|||
<template> |
|||
<div class="container"> |
|||
<div class="loginContainer"> |
|||
<img |
|||
class="backgroundImg" |
|||
src="https://d31zlh4on95l9h.cloudfront.net/assets/registerHw.png" |
|||
alt="" |
|||
/> |
|||
<div class="loginWindow"> |
|||
<input type="text" class="username" v-model="userInfo.username" /> |
|||
<input type="password" class="password" v-model="userInfo.password" /> |
|||
<div class="policy"> |
|||
<el-checkbox-group v-model="agree"> |
|||
<el-checkbox value="1" /> |
|||
</el-checkbox-group> |
|||
<span class="hasAgreed">我已阅读并同意</span> |
|||
<span class="privacy">隐私条款</span> |
|||
</div> |
|||
<div class="login" @click="login">登录</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { useRouter } from "vue-router"; |
|||
import { ref, watch } from "vue"; |
|||
import { ElMessageBox, ElMessage } from "element-plus"; |
|||
import { fakeLinkDataListStore } from "../../store/fakeLink-dataList"; |
|||
const fakeLinkDataStore = fakeLinkDataListStore(); |
|||
|
|||
const router = useRouter(); |
|||
const agree = ref([]); |
|||
const userInfo = ref({ |
|||
username: "", |
|||
password: "", |
|||
}); |
|||
|
|||
const login = () => { |
|||
if (!userInfo.value.username) { |
|||
ElMessage.error("请输入用户名"); |
|||
return; |
|||
} |
|||
if (!userInfo.value.password) { |
|||
ElMessage.error("请输入密码"); |
|||
return; |
|||
} |
|||
if (agree.value.length !== 1) { |
|||
ElMessage.error("请同意协议"); |
|||
return; |
|||
} |
|||
|
|||
const res = fakeLinkDataStore.getUserInfo( |
|||
userInfo.value.username, |
|||
userInfo.value.password |
|||
); |
|||
if (res == 200) { |
|||
ElMessage.success("登录成功"); |
|||
router.push("fakeLink"); |
|||
} else { |
|||
ElMessage.error("用户名或密码不正确"); |
|||
} |
|||
}; |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.container { |
|||
width: 100%; |
|||
height: 100%; |
|||
background-image: url("https://cdn.legu168.com/jtzy/Product/pcjingwang/images/login_bg_7584f6a.png"); |
|||
background-size: 100% 100%; |
|||
background-repeat: no-repeat; |
|||
/* padding-top: 100px; */ |
|||
} |
|||
|
|||
.loginContainer { |
|||
position: relative; |
|||
display: flex; |
|||
/* width: 100%; */ |
|||
/* height: 50%; */ |
|||
justify-content: center; |
|||
padding-top: 30px; |
|||
} |
|||
|
|||
.backgroundImg { |
|||
width: 630px; |
|||
height: auto; |
|||
position: absolute; |
|||
} |
|||
|
|||
.loginWindow { |
|||
margin-top: 230px; |
|||
background-color: rgba(255, 255, 255, 0.9); |
|||
padding: 28px 50px; |
|||
width: 400px; |
|||
box-sizing: border-box; |
|||
display: flex; |
|||
flex-direction: column; |
|||
z-index: 2; |
|||
} |
|||
|
|||
.username { |
|||
width: 300px; |
|||
height: 38px; |
|||
margin-bottom: 10px; |
|||
box-sizing: border-box; |
|||
font-size: 16px; |
|||
padding-left: 10px; |
|||
border: 1px solid rgb(221, 221, 221); |
|||
outline: none; |
|||
} |
|||
|
|||
.username:focus { |
|||
border: 1px solid #409eff; /* 聚焦时的边框颜色 */ |
|||
} |
|||
|
|||
.password { |
|||
width: 300px; |
|||
height: 38px; |
|||
margin-bottom: 10px; |
|||
box-sizing: border-box; |
|||
font-size: 16px; |
|||
padding-left: 10px; |
|||
border: 1px solid rgb(221, 221, 221); |
|||
outline: none; |
|||
} |
|||
|
|||
.password:focus { |
|||
border: 1px solid #409eff; /* 聚焦时的边框颜色 */ |
|||
} |
|||
|
|||
.policy { |
|||
display: flex; |
|||
align-items: center; |
|||
font-size: 14px; |
|||
} |
|||
|
|||
.hasAgreed { |
|||
margin-right: 5px; |
|||
} |
|||
|
|||
.privacy { |
|||
color: rgb(64, 101, 153); |
|||
cursor: pointer; |
|||
} |
|||
|
|||
.privacy:hover { |
|||
color: red; |
|||
} |
|||
|
|||
.login { |
|||
width: 100%; |
|||
height: 38px; |
|||
color: white; |
|||
background-color: rgb(248, 89, 89); |
|||
font-size: 18px; |
|||
margin: 20px 0px; |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
cursor: pointer; |
|||
} |
|||
</style> |
@ -1,46 +1,54 @@ |
|||
<template> |
|||
<h1 style="width:100%;text-align:center;margin:20px 0px 10px 0px">练习首页</h1> |
|||
<el-divider> |
|||
<el-icon><star-filled /></el-icon> |
|||
</el-divider> |
|||
<div class="btns"> |
|||
<div v-for="button in buttons" :key="button.text" :type="button.type" class="btn" @click="router.push(button.path)"> |
|||
{{ button.text }} |
|||
</div> |
|||
<h1 style="width: 100%; text-align: center; margin: 20px 0px 10px 0px"> |
|||
练习首页 |
|||
</h1> |
|||
<el-divider> |
|||
<el-icon><star-filled /></el-icon> |
|||
</el-divider> |
|||
<div class="btns"> |
|||
<div |
|||
v-for="button in buttons" |
|||
:key="button.text" |
|||
:type="button.type" |
|||
class="btn" |
|||
@click="router.push(button.path)" |
|||
> |
|||
{{ button.text }} |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { ref } from 'vue' |
|||
import { useRouter } from 'vue-router' |
|||
const router = useRouter() |
|||
import { ref } from "vue"; |
|||
import { useRouter } from "vue-router"; |
|||
const router = useRouter(); |
|||
|
|||
const buttons = [ |
|||
{ type: 'primary', text: '转盘',path:'/hxl_dzp1' }, |
|||
{ type: 'success', text: '动画',path:'/animation' }, |
|||
{ type: 'success', text: '作业',path:'/homework' }, |
|||
{ type: 'success', text: '日历',path:'/calendar' }, |
|||
] |
|||
|
|||
|
|||
{ type: "primary", text: "转盘", path: "/hxl_dzp1" }, |
|||
{ type: "success", text: "动画", path: "/animation" }, |
|||
{ type: "success", text: "作业", path: "/homework" }, |
|||
{ type: "success", text: "日历", path: "/calendar" }, |
|||
{ type: "success", text: "3D1", path: "/3D1" }, |
|||
{ type: "success", text: "HomilyLink", path: "/fakeLink" }, |
|||
]; |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.btns{ |
|||
width: 100%; |
|||
height: auto; |
|||
display: flex; |
|||
flex-direction: column; |
|||
gap: 20px; |
|||
.btns { |
|||
width: 100%; |
|||
height: auto; |
|||
display: flex; |
|||
flex-direction: column; |
|||
gap: 20px; |
|||
} |
|||
|
|||
.btn { |
|||
width: 100%; |
|||
height: auto; |
|||
font-size: 30px; |
|||
font-weight: bold; |
|||
text-align: center; |
|||
cursor: pointer; |
|||
width: 100%; |
|||
height: auto; |
|||
font-size: 30px; |
|||
font-weight: bold; |
|||
text-align: center; |
|||
cursor: pointer; |
|||
} |
|||
</style> |
|||
<style></style> |
@ -1,132 +1,183 @@ |
|||
<script setup> |
|||
import { ref, onMounted } from 'vue' |
|||
import { ref, onMounted } from "vue"; |
|||
import backBtn from "../commponent/backBtn.vue"; |
|||
|
|||
const showPopup = ref(false); |
|||
const popupMessage = ref(''); |
|||
const totalScore = ref(4000) // 初始分数 |
|||
const myLucky = ref() |
|||
const popupMessage = ref(""); |
|||
const totalScore = ref(4000); // 初始分数 |
|||
const myLucky = ref(); |
|||
// 新增状态 |
|||
const spinCount = ref(0) |
|||
const isSpinning = ref(false) |
|||
const spinCount = ref(0); |
|||
const isSpinning = ref(false); |
|||
// 新增变量记录基础分数 |
|||
//const baseScore = 4000 |
|||
const wheelConfig = ref({ |
|||
}) |
|||
const wheelConfig = ref({}); |
|||
const prizes = ref([ |
|||
{ fonts: [{ text: '-199', top: '10%', fontColor: '#FF2C29', fontSize: '40px' }], background: '#FAF9F0' }, //0 |
|||
{ fonts: [{ text: '-55', top: '10%', fontColor: '#FF2C29', fontSize: '40px' }], background: '#F5D7AD' }, //1 |
|||
{ fonts: [{ text: '+200', top: '10%', fontColor: '#FF2C29', fontSize: '40px' }], background: '#FAF9F0' }, //2 |
|||
{ fonts: [{ text: '-88', top: '10%', fontColor: '#FF2C29', fontSize: '40px' }], background: '#F5D7AD' }, //3 |
|||
{ fonts: [{ text: '-11', top: '10%', fontColor: '#FF2C29', fontSize: '40px' }], background: '#FAF9F0' }, //4 |
|||
{ fonts: [{ text: '-299', top: '10%', fontColor: '#FF2C29', fontSize: '40px' }], background: '#F5D7AD' }, //5 |
|||
{ fonts: [{ text: '+200', top: '10%', fontColor: '#FF2C29', fontSize: '40px' }], background: '#FAF9F0' }, //6 |
|||
{ fonts: [{ text: '-66', top: '10%', fontColor: '#FF2C29', fontSize: '40px' }], background: '#F5D7AD' }, //7 |
|||
]) |
|||
const blocks = ref([{ padding: '13px', background: ' #FF2A00' }]) |
|||
{ |
|||
fonts: [ |
|||
{ text: "-199", top: "10%", fontColor: "#FF2C29", fontSize: "40px" }, |
|||
], |
|||
background: "#FAF9F0", |
|||
}, //0 |
|||
{ |
|||
fonts: [ |
|||
{ text: "-55", top: "10%", fontColor: "#FF2C29", fontSize: "40px" }, |
|||
], |
|||
background: "#F5D7AD", |
|||
}, //1 |
|||
{ |
|||
fonts: [ |
|||
{ text: "+200", top: "10%", fontColor: "#FF2C29", fontSize: "40px" }, |
|||
], |
|||
background: "#FAF9F0", |
|||
}, //2 |
|||
{ |
|||
fonts: [ |
|||
{ text: "-88", top: "10%", fontColor: "#FF2C29", fontSize: "40px" }, |
|||
], |
|||
background: "#F5D7AD", |
|||
}, //3 |
|||
{ |
|||
fonts: [ |
|||
{ text: "-11", top: "10%", fontColor: "#FF2C29", fontSize: "40px" }, |
|||
], |
|||
background: "#FAF9F0", |
|||
}, //4 |
|||
{ |
|||
fonts: [ |
|||
{ text: "-299", top: "10%", fontColor: "#FF2C29", fontSize: "40px" }, |
|||
], |
|||
background: "#F5D7AD", |
|||
}, //5 |
|||
{ |
|||
fonts: [ |
|||
{ text: "+200", top: "10%", fontColor: "#FF2C29", fontSize: "40px" }, |
|||
], |
|||
background: "#FAF9F0", |
|||
}, //6 |
|||
{ |
|||
fonts: [ |
|||
{ text: "-66", top: "10%", fontColor: "#FF2C29", fontSize: "40px" }, |
|||
], |
|||
background: "#F5D7AD", |
|||
}, //7 |
|||
]); |
|||
const blocks = ref([{ padding: "13px", background: " #FF2A00" }]); |
|||
const buttons = ref([ |
|||
{ radius: '50%', background: '#617df2' }, |
|||
{ radius: '45%', background: '#afc8ff' }, |
|||
{ |
|||
radius: '40%', background: '#869cfa', pointer: true, |
|||
fonts: [{ text: '开始\n抽奖', top: '-20px' }] |
|||
}]) |
|||
{ radius: "50%", background: "#617df2" }, |
|||
{ radius: "45%", background: "#afc8ff" }, |
|||
{ |
|||
radius: "40%", |
|||
background: "#869cfa", |
|||
pointer: true, |
|||
fonts: [{ text: "开始\n抽奖", top: "-20px" }], |
|||
}, |
|||
]); |
|||
|
|||
//自定义数组 |
|||
const customOrder = ref([0, 4, 3, 1, 2, 4, 5, 7, 3, 4, 0]) |
|||
const customOrder = ref([0, 4, 3, 1, 2, 4, 5, 7, 3, 4, 0]); |
|||
let orderIndex = 0; |
|||
|
|||
function startCallback() { |
|||
// 检查转动条件和次数 |
|||
if (spinCount.value >= 11) { // 从0开始计数,11表示第12次 |
|||
alert('已达最大转动次数!') |
|||
return |
|||
} |
|||
|
|||
isSpinning.value = true |
|||
spinCount.value++ |
|||
// 重置为初始分数 |
|||
//totalScore.value = baseScore |
|||
// 调用抽奖组件的play方法开始游戏 |
|||
myLucky.value.play() |
|||
// 模拟调用接口异步抽奖 |
|||
setTimeout(() => { |
|||
// |
|||
console.log(orderIndex, 'orderIndex') |
|||
|
|||
const index = orderIndex |
|||
|
|||
console.log(customOrder.value[index], 'custome') |
|||
// 调用stop停止旋转并传递中奖索引 |
|||
myLucky.value.stop(customOrder.value[index]) |
|||
//更新指针(循环) |
|||
orderIndex = (index + 1) % customOrder.value.length; |
|||
}, 3000) |
|||
// 检查转动条件和次数 |
|||
if (spinCount.value >= 11) { |
|||
// 从0开始计数,11表示第12次 |
|||
alert("已达最大转动次数!"); |
|||
return; |
|||
} |
|||
|
|||
isSpinning.value = true; |
|||
spinCount.value++; |
|||
// 重置为初始分数 |
|||
//totalScore.value = baseScore |
|||
// 调用抽奖组件的play方法开始游戏 |
|||
myLucky.value.play(); |
|||
// 模拟调用接口异步抽奖 |
|||
setTimeout(() => { |
|||
// |
|||
console.log(orderIndex, "orderIndex"); |
|||
|
|||
const index = orderIndex; |
|||
|
|||
console.log(customOrder.value[index], "custome"); |
|||
// 调用stop停止旋转并传递中奖索引 |
|||
myLucky.value.stop(customOrder.value[index]); |
|||
//更新指针(循环) |
|||
orderIndex = (index + 1) % customOrder.value.length; |
|||
}, 3000); |
|||
} |
|||
const scoreAnimation = ref(false) |
|||
|
|||
const scoreAnimation = ref(false); |
|||
|
|||
// 抽奖结束end回调 |
|||
function endCallback(prize) { |
|||
const result = Number(prize.fonts[0].text) |
|||
console.log(prize.fonts[0].text) |
|||
// 更新总分 |
|||
setTimeout(() => { |
|||
totalScore.value = totalScore.value + result |
|||
}, 1000); |
|||
|
|||
// 触发动画 |
|||
animateScoreChange() |
|||
// 先清空文字 |
|||
popupMessage.value = ""; |
|||
showPopup.value = true; |
|||
// 设置弹窗内容 |
|||
setTimeout(() => { |
|||
popupMessage.value = `${result}金币`; |
|||
}, 1000); // <--- 正确的用法 |
|||
|
|||
showPopup.value = true; |
|||
// 3秒后隐藏弹窗 |
|||
setTimeout(() => { |
|||
showPopup.value = false; |
|||
}, 3000); |
|||
const result = Number(prize.fonts[0].text); |
|||
console.log(prize.fonts[0].text); |
|||
// 更新总分 |
|||
setTimeout(() => { |
|||
totalScore.value = totalScore.value + result; |
|||
}, 1000); |
|||
|
|||
// 触发动画 |
|||
animateScoreChange(); |
|||
// 先清空文字 |
|||
popupMessage.value = ""; |
|||
showPopup.value = true; |
|||
// 设置弹窗内容 |
|||
setTimeout(() => { |
|||
popupMessage.value = `${result}金币`; |
|||
}, 1000); // <--- 正确的用法 |
|||
|
|||
showPopup.value = true; |
|||
// 3秒后隐藏弹窗 |
|||
setTimeout(() => { |
|||
showPopup.value = false; |
|||
}, 3000); |
|||
} |
|||
// 添加分数变化动画方法 |
|||
const animateScoreChange = () => { |
|||
scoreAnimation.value = true |
|||
setTimeout(() => { |
|||
scoreAnimation.value = false |
|||
}, 3000) |
|||
} |
|||
scoreAnimation.value = true; |
|||
setTimeout(() => { |
|||
scoreAnimation.value = false; |
|||
}, 3000); |
|||
}; |
|||
|
|||
onMounted(() => { |
|||
console.log(import.meta.env.MODE, '1111') |
|||
console.log(process.env.NODE_ENV, '2222') |
|||
}) |
|||
console.log(import.meta.env.MODE, "1111"); |
|||
console.log(process.env.NODE_ENV, "2222"); |
|||
}); |
|||
</script> |
|||
|
|||
<template> |
|||
<div style="display:flex;height:100%;width:100%"> |
|||
<el-card class="manageCard"> |
|||
管理台 |
|||
</el-card> |
|||
<el-card class="wheelCard"> |
|||
<div class="luckyWheel"> |
|||
<LuckyWheel class="lucky" ref="myLucky" width="434px" height="434px" :default-config="wheelConfig" |
|||
:prizes="prizes" :blocks="blocks" :buttons="buttons" @start="startCallback" @end="endCallback" /> |
|||
|
|||
</div> |
|||
</el-card> |
|||
</div> |
|||
<backBtn></backBtn> |
|||
|
|||
<div style="display: flex; height: 100%; width: 100%"> |
|||
<el-card class="manageCard"> 管理台 </el-card> |
|||
<el-card class="wheelCard"> |
|||
<div class="luckyWheel"> |
|||
<LuckyWheel |
|||
class="lucky" |
|||
ref="myLucky" |
|||
width="434px" |
|||
height="434px" |
|||
:default-config="wheelConfig" |
|||
:prizes="prizes" |
|||
:blocks="blocks" |
|||
:buttons="buttons" |
|||
@start="startCallback" |
|||
@end="endCallback" |
|||
/> |
|||
</div> |
|||
</el-card> |
|||
</div> |
|||
</template> |
|||
|
|||
<style scoped> |
|||
.el-card { |
|||
margin: 20px; |
|||
margin: 20px; |
|||
} |
|||
|
|||
.manageCard{ |
|||
width: auto; |
|||
flex: 1; |
|||
.manageCard { |
|||
width: auto; |
|||
flex: 1; |
|||
} |
|||
|
|||
</style> |
@ -0,0 +1,79 @@ |
|||
<template> |
|||
<backBtn></backBtn> |
|||
|
|||
<div>3D1</div> |
|||
<div id="webgl" style="margin-top: 200px; margin-left: 100px"></div> |
|||
</template> |
|||
|
|||
<script setup> |
|||
// 引入three.js |
|||
import * as THREE from "three"; |
|||
// 引入轨道控制器扩展库OrbitControls.js |
|||
import { OrbitControls } from "three/addons/controls/OrbitControls.js"; |
|||
import backBtn from '../commponent/backBtn.vue' |
|||
import { ref, onMounted } from "vue"; |
|||
|
|||
onMounted(() => { |
|||
create3D1(); |
|||
}); |
|||
|
|||
const create3D1 = () => { |
|||
// 创建3D场景对象Scene |
|||
const scene = new THREE.Scene(); |
|||
|
|||
//创建一个长方体几何对象Geometry |
|||
const geometry = new THREE.BoxGeometry(100, 100, 100); |
|||
|
|||
//创建一个材质对象Material |
|||
const material = new THREE.MeshBasicMaterial({ |
|||
color: 0xff0000, //0xff0000设置材质颜色为红色 |
|||
}); |
|||
|
|||
// 两个参数分别为几何体geometry、材质material |
|||
const mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh |
|||
|
|||
//设置网格模型在三维空间中的位置坐标,默认是坐标原点 |
|||
mesh.position.set(0, 0, 0); |
|||
|
|||
const axesHelper = new THREE.AxesHelper(150); |
|||
scene.add(axesHelper); |
|||
scene.add(mesh); |
|||
|
|||
// 定义相机输出画布的尺寸(单位:像素px) |
|||
const width = 800; //宽度 |
|||
const height = 500; //高度 |
|||
// 实例化一个透视投影相机对象 |
|||
const camera = new THREE.PerspectiveCamera(30, width / height, 1, 3000); |
|||
|
|||
//相机在Three.js三维坐标系中的位置 |
|||
// 根据需要设置相机位置具体值 |
|||
camera.position.set(200, 200, 200); |
|||
camera.lookAt(mesh.position); //指向mesh对应的位置 |
|||
|
|||
// 创建渲染器对象 |
|||
const renderer = new THREE.WebGLRenderer(); |
|||
renderer.setSize(width, height); //设置three.js渲染区域的尺寸(像素px) |
|||
// renderer.render(scene, camera); //执行渲染操作 |
|||
document.getElementById("webgl").appendChild(renderer.domElement); |
|||
const clock = new THREE.Clock(); |
|||
// 渲染函数 |
|||
function render() { |
|||
const spt = clock.getDelta() * 1000; //毫秒 |
|||
// console.log("两帧渲染时间间隔(毫秒)", spt); |
|||
// console.log("帧率FPS", 1000 / spt); |
|||
renderer.render(scene, camera); //执行渲染操作 |
|||
mesh.rotateY(0.01); //每次绕y轴旋转0.01弧度 |
|||
requestAnimationFrame(render); //请求再次执行渲染函数render,渲染下一帧 |
|||
} |
|||
render(); |
|||
// 设置相机控件轨道控制器OrbitControls |
|||
const controls = new OrbitControls(camera, renderer.domElement); |
|||
// 如果OrbitControls改变了相机参数,重新调用渲染器渲染三维场景 |
|||
controls.addEventListener("change", function () { |
|||
renderer.render(scene, camera); //执行渲染操作 |
|||
}); //监听鼠标、键盘事件 |
|||
}; |
|||
</script> |
|||
|
|||
<style scoped> |
|||
</style> |