Files
aggregate_translate_website/userinfo.html
2025-07-18 18:08:30 +08:00

1182 lines
39 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<meta name="baidu-site-verification" content="codeva-bhaFvYlfgd" />
<meta
name="keywords"
content="deepl、deepl翻译、百度翻译、谷歌翻译、腾讯翻译君"
/>
<meta
name="description"
content="聚合翻译提供即时免费的中文、英语、日语、韩语、法语、德语、俄语、西班牙语、葡萄牙语、越南语、印尼语、意大利语、荷兰语、泰语全文翻译等服务。"
/>
<meta name="baidu-site-verification" content="codeva-mXz3BqI9VN" />
<link rel="stylesheet" href="static/css/public.css" />
<!-- <link rel="stylesheet" href="static/translate/css/public.css?v=4"> -->
<link rel="stylesheet" href="static/css/layui.css" />
<!-- <link rel="stylesheet" href="static/js/css/buefy.min.css"> -->
<script src="static/js/jquery-1.11.0.min.js"></script>
<script src="static/js/axios.min.js"></script>
<script src="static/translate/js/echarts.min.js"></script>
<script src="static/js/countUp.min.js"></script>
<script src="static/js/vue.js"></script>
<script src="static/js/lodash.min.js"></script>
<script src="static/js/layui.all.js"></script>
<script src="static/js/common.js"></script>
<script src="https://cdn.jsdelivr.net/npm/qrcode@1.4.4/build/qrcode.min.js"></script>
<script src="static/js/countdown.js"></script>
<!-- <script src="static/js/buefy.min.js"></script> -->
<title>聚合翻译</title>
<script>
var _hmt = _hmt || [];
(function () {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?c4e0dd6add63dd71fa52870120ca22cf";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script>
</head>
<body>
<div id="main" class="public-header normal">
<div class="container clearfix">
<div class="left">
<img
src="https://codeai.oss-cn-hangzhou.aliyuncs.com/img/logo.png"
alt=""
class="logo default"
/><img
src="https://codeai.oss-cn-hangzhou.aliyuncs.com/img/logo1.png"
alt=""
class="logo1 default"
/><img
src="https://codeai.oss-cn-hangzhou.aliyuncs.com/img/logow.png"
alt=""
class="logo light"
/><img
src="https://codeai.oss-cn-hangzhou.aliyuncs.com/img/logo1w.png"
alt=""
class="logo1 light"
/>
<div class="nav">
<a class="" href="index.html"><span>首页</span></a
><a class="" href="onlineTranslation.html"><span>文本翻译</span></a
><a class="" href="voice.html"><span>语音翻译</span></a
><a class="" href="api.html"><span>API文档</span></a
><a class="" href="commonProblems.html"><span>常见问题</span></a>
</div>
</div>
<div v-if="userInfo!=undefined&&userInfo.userId>0" class="right">
<a href="userinfo.html" class="console">控制台</a>
<div class="user-info">
<div class="phone">{{userInfo.name}}</div>
<i></i>
<div class="log-out" @click="logOut">退出</div>
</div>
</div>
<div v-else class="right">
<a class="unlogin" href="login.html">登录</a>
</div>
</div>
<div class="bg"></div>
</div>
<script type="text/javascript">
var vm = new Vue({
el: "#main",
data() {
return {
userInfo: {},
token: "",
};
},
created() {},
mounted() {
let token = localStorage.getItem("token");
if (token) {
this.token = token;
this.getUserInfo(token);
} else {
location.href = "login.html";
}
},
methods: {
logOut() {
axios
.post("/logout", {
headers: {
Authorization: `Bearer ${this.token}`,
},
})
.then((response) => {
localStorage.removeItem("token");
location.reload();
});
},
getUserInfo(token) {
let that = this;
axios
.get("/getinfo", {
headers: {
Authorization: `Bearer ${this.token}`,
},
})
.then((response) => {
if (response.data.code === 200) {
this.userInfo = response.data.data;
console.log("userinfo", this.userInfo);
} else {
localStorage.removeItem("token");
location.href = "login.html";
}
});
},
},
});
</script>
<style>
.page-console {
height: auto !important;
padding-bottom: 16px;
}
.range-picker {
display: flex;
align-items: center;
justify-content: flex-end;
margin: 40px auto 0;
}
.range-picker .col {
margin-right: 16px;
font-size: 16px;
color: #333;
cursor: pointer;
}
.range-picker .col.on {
color: #2578ff;
}
</style>
<div id="app" class="page-console" style="padding-top: 90px">
<div class="id-container">
<div class="user-id-container">
<img
src="https://codeai.oss-cn-hangzhou.aliyuncs.com/img/pay.png"
class="user-id-icon"
/><span class="user-id-text">用户ID : {{userInfo.userId}}</span>
</div>
</div>
<div class="tab-container">
<!-- <div class="tabs">
<div class="tab on">文本翻译</div>
<div class="tab">语音翻译</div>
</div> -->
<div id="text-translation" class="w1200 transUserinfo">
<h5>使用情况</h5>
<div class="line"></div>
<div class="table-row">
<div class="col">
<div class="cell"><span>翻译引擎</span></div>
<div class="cell"><span>已使用字符数</span></div>
<div class="cell"><span>剩余字符数</span></div>
<div class="cell"><span>价格U/百万字符)</span></div>
<div class="cell"><span>操作</span></div>
</div>
<div
class="col"
v-for="(item,index) in translateInfos"
:key="'platform_'+index"
>
<div class="cell"><span>{{item.name}}</span></div>
<div class="cell"><span>{{item.useChars}}</span></div>
<div class="cell">
<span>{{item.remainChars}}</span>
<img v-if="item.remainChars>0" class="btn-clock" @click="showRecord(item.platformId,index)" src="static/image/clock.png"/>
</div>
<div class="cell"><span>{{item.price}}</span></div>
<div class="cell">
<div class="act">
<span class="recharge" @click="show(item)">充值</span
><span class="view" @click="look(item.apiKey,index)"
>查看API密钥</span
>
</div>
</div>
</div>
</div>
<div class="warn">备注:技术问题,请联系客服。</div>
<div class="clearfix" style="height: 361px">
<!-- <div class="range-picker">
<div class="col on">近7天</div>
<div class="col">近15天</div>
<div class="col">近30天</div>
</div> -->
<div class="chart-container-wrapper">
<!-- ECharts 图表将渲染到这个 div 中 -->
<div id="mainEchart" class="echarts-chart-direct"></div>
</div>
</div>
</div>
<div
id="voice-translation"
class="w1200 transUserinfo"
style="display: none"
>
<div class="header-container">
<div class="title-section">
<h5>使用情况</h5>
<div class="api-key">
<span>密钥:</span
><button class="copy-btn" style="display: none">复制</button>
</div>
</div>
<div class="balance-section">
<div class="balance">剩余金额0元</div>
<button class="recharge-btn">充值</button>
</div>
</div>
<div class="line"></div>
<div class="table-container table-row">
<div class="grid-header col">
<div class="cell" style="width: 180px">翻译引擎</div>
<div class="cell">服务类型</div>
<div class="cell">已消耗时常/用量</div>
<div class="cell">已消费金额(元)</div>
<div class="cell">价格(元/小时)</div>
</div>
<div class="grid-body">
<div class="vendor-cell" style="grid-row: span 3">
<span>微软</span>
</div>
</div>
</div>
<div class="warn">备注:技术问题,请联系客服。</div>
<div class="clearfix" style="height: 361px">
<div class="range-picker">
<div class="col on">近7天</div>
<div class="col">近15天</div>
<div class="col">近30天</div>
</div>
<!-- <div
id="chartDoms"
style="width: 1200px; height: 300px; margin: 30px auto"
></div> -->
</div>
</div>
</div>
<div class="public-customer">
<div class="ctr">
<div class="item">
<img
src="https://codeai.oss-cn-hangzhou.aliyuncs.com/img/p25.png"
alt=""
/>
<div>电报咨询</div>
<div class="detail wechat">
<h5>电报咨询</h5>
<img
src="/static/picture/p23.jpg"
alt=""
/>
<p>手机扫码加我电报</p>
</div>
</div>
<div class="line"></div>
<div class="item">
<img
src="https://codeai.oss-cn-hangzhou.aliyuncs.com/img/p26.png"
alt=""
/>
<div>电话咨询</div>
<div class="detail">
<h5>电话咨询</h5>
<div class="phone">+18435173355</div>
</div>
</div>
</div>
</div>
<div class="modal-overlay" style="display: none">
<div class="modal">
<button class="close-btn" @click="close">&times;</button>
<div
class="modal-content"
:style="loadingQr ? 'opacity: 0.4; pointer-events: none;' : ''"
>
<h3 v-if="rechargeData.step === 1">Step 1: 输入购买数量</h3>
<h3 v-else>Step 2: 支付信息</h3>
<!-- Step 1 -->
<div v-if="rechargeData.step === 1" class="step">
<label>购买数量:</label>
<input type="number" v-model.number="rechargeData.count" min="1" />
</div>
<!-- Step 2 -->
<div v-else class="step">
<div class="qr-code">
<div id="qrcode"></div>
<!-- <div v-if="loadingQr" class="loading-spinner"></div> -->
<!-- <img v-else-if="qrCodeUrl" :src="qrCodeUrl" alt="二维码"
@load="onQrLoadSuccess" @error="onQrLoadError"
style="width: 100%; height: 100%; border-radius: 8px;" />
<span v-else style="font-size: 12px; color: #999;">加载失败</span> -->
</div>
<div class="wallet-info">
<p>主链:<strong>{{ rechargeData.blockChain }}</strong></p>
<p>钱包地址: <strong>{{ rechargeData.receiveAddress }}</strong></p>
<p>支付金额: <strong>{{ rechargeData.amount }} USDT</strong></p>
<p>
<countdown :time="(rechargeData.expireUnix * 1000) - Date.now()"
v-if="rechargeData.expireUnix && (rechargeData.expireUnix * 1000) > Date.now()" >
<template slot-scope="props">
倒计时:
<span v-if="props.minutes>0||props.hours>0||props.days>0">{{ props.minutes }} 分</span>
<span v-if="props.seconds>0||props.minutes>0||props.hours>0||props.days>0">{{ props.seconds }} 秒</span>
<span style="color: red;" v-if="props.days==0&&props.hours==0&&props.minutes==0&&props.seconds==0">订单已过期,请勿支付!</span>
</template>
</countdown>
</p>
</div>
</div>
<div class="btn-group">
<!-- <button class="btn btn-secondary" @click="close">关闭</button> -->
<button class="btn btn-secondary" v-if="rechargeData.step === 2" @click="prevStep">上一步</button>
<button class="btn btn-primary" v-if="rechargeData.step === 1" :disabled="!rechargeData.count" @click="nextStep">下一步</button>
</div>
</div>
</div>
<!-- loading 遮罩层 -->
<div class="modal-loading-overlay" v-if="loadingQr">
<div class="spinner"></div>
</div>
</div>
<div class="modal-overlay-record" style="display: none">
<div class="service-modal">
<div class="content-normal">
<div class="close" @click="closeRecord"></div>
<div v-for="(item,index) in rechargeList" :key="'record'+index" class="content-item">
<div>订单号:{{item.orderNo}}</div>
<div>金额:{{item.amount}}</div>
<div>总字符数:{{item.totalCharater}}</div>
<div>可用字符数:{{item.remainCharater}}</div>
<!-- <div>倒计时:{{item.expireUnix}}</div> -->
<countdown :time="(item.expireUnix * 1000) - Date.now()"
v-if="item.expireUnix && (item.expireUnix * 1000) > Date.now()" >
<template slot-scope="props">
倒计时:<span v-if="props.days > 0">{{ props.days }} 天</span>
<span v-if="props.hours>0||props.days>0">{{ props.hours }} 时</span>
<span v-if="props.minutes>0||props.hours>0||props.days>0">{{ props.minutes }} 分</span>
<span v-if="props.seconds>0||props.minutes>0||props.hours>0||props.days>0">{{ props.seconds }} 秒</span>
</template>
</countdown>
</div>
</div>
</div>
</div>
</div>
<style>
.modal-overlay {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.4);
display: flex;
justify-content: center;
align-items: center;
z-index: 999;
}
.modal {
background: #ffffff;
border-radius: 12px;
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.1);
padding: 24px 28px;
width: 400px;
max-width: 90%;
animation: fadeIn 0.3s ease;
position:relative;
}
.modal-content {
transition: opacity 0.2s;
}
.modal-loading-overlay {
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
background-color: rgba(255, 255, 255, 0.6);
display: flex;
justify-content: center;
align-items: center;
z-index: 10;
border-radius: 12px;
}
.spinner {
border: 4px solid #f3f3f3;
border-top: 4px solid #409eff;
border-radius: 50%;
width: 32px;
height: 32px;
animation: spin 0.8s linear infinite;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(-20px); }
to { opacity: 1; transform: translateY(0); }
}
.modal h3 {
margin-top: 0;
font-size: 20px;
color: #333;
}
input[type="number"] {
width: 100%;
padding: 10px 12px;
font-size: 16px;
margin-top: 8px;
border: 1px solid #ccc;
border-radius: 6px;
transition: border-color 0.2s;
}
input[type="number"]:focus {
border-color: #409eff;
outline: none;
}
button{
cursor: pointer;
}
.step {
padding-top: 16px;
margin-bottom: 16px;
}
.qr-code {
width: 150px;
height: 150px;
background: #f8f8f8;
border: 1px dashed #ccc;
display: flex;
align-items: center;
justify-content: center;
margin: 0 auto;
border-radius: 8px;
}
.loading-spinner {
border: 3px solid #f3f3f3;
border-top: 3px solid #409eff;
border-radius: 50%;
width: 28px;
height: 28px;
animation: spin 0.8s linear infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
.btn-group {
display: flex;
justify-content: flex-end;
gap: 8px;
margin-top: 16px;
}
.btn {
padding: 8px 16px;
border: none;
border-radius: 6px;
font-size: 14px;
transition: background-color 0.2s ease;
}
.btn-primary {
background-color: #409eff;
color: #fff;
}
.btn-primary:disabled {
background-color: #a0cfff;
cursor: not-allowed;
}
.btn-secondary {
background-color: #e0e0e0;
color: #333;
}
.wallet-info {
font-size: 14px;
color: #555;
text-align: center;
margin-top: 12px;
}
.close-btn {
position: absolute;
top: 12px;
right: 12px;
background: transparent;
border: none;
font-size: 20px;
color: #999;
cursor: pointer;
transition: color 0.2s ease;
}
.close-btn:hover {
color: #333;
}
</style>
<script type="text/javascript">
// 工具函数:将十六进制颜色转换为 RGBA 格式
function hexToRgba(hex, alpha) {
const r = parseInt(hex.slice(1, 3), 16);
const g = parseInt(hex.slice(3, 5), 16);
const b = parseInt(hex.slice(5, 7), 16);
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
}
var vm = new Vue({
el: "#app",
components:{
countdown: window.VueCountdown,
},
data() {
return {
translateInfo: [],
translateInfos: [],
isShow: false,
dateType: 0,
pageChart: null,
tabShow: "text",
token: "",
userMoney: 0,
userInfo: {},
activeStep:"2",
showRecharge:false,
loadingQr:false,
rechargeData:{
platformId:null,
name:null,
count:1,
amount:null,
receiveAddress:null,
step:1,
expireUnix:undefined
},
// ECharts 图表数据
myChart: null, // 用于存储 ECharts 实例
xAxisData: [],
seriesData: [],
receiveAddress: "",
rechargeList:[]
};
},
created() {
},
mounted() {
console.log(this.$refs.myCountdown)
let token = localStorage.getItem("token");
if (token) {
this.token = token;
this.getUserInfo(token);
} else {
location.href = "login.html";
}
// === 直接在主 Vue 实例的 mounted 钩子中初始化 ECharts ===
// 确保在 DOM 更新周期之后再初始化 ECharts
this.$nextTick(() => {
setTimeout(() => {
this.initECharts();
}, 100); // 增加一个短暂的延迟
});
// 监听窗口大小变化,使图表自适应
window.addEventListener("resize", this.resizeECharts);
this.getUserPlatforms();
this.getStatistics();
// this.getReceiveAddress();
},
beforeDestroy() {
// 销毁 ECharts 实例并移除事件监听器
if (this.myChart) {
this.myChart.dispose();
}
window.removeEventListener("resize", this.resizeECharts);
},
watch: {
dateType() {
if (this.tabShow == "voice") {
this.getVoicestatistics();
} else {
this.getStatistics();
}
},
// 监听数据变化,重新渲染图表
seriesData: {
deep: true,
handler() {
this.updateECharts();
},
},
xAxisData: {
deep: true,
handler() {
this.updateECharts();
},
},
},
methods: {
getUserPlatforms() {
axios
.get("/tm-member/platforms", {
headers: { Authorization: `Bearer ${this.token}` },
})
.then((res) => {
if (res.data.code == 200) {
let result = res.data.data;
this.translateInfos = result;
} else {
layer.msg(response.data.msg);
}
});
},
// getReceiveAddress() {
// axios
// .get("/configKey/trx_receive_address", {
// headers: { Authorization: `Bearer ${this.token}` },
// })
// .then((res) => {
// if (res.data.code == 200) {
// this.receiveAddress = res.data.data.configValue;
// this.generateQRCode();
// } else {
// layer.msg(response.data.msg);
// }
// });
// },
getMemberAdvent(platformId){
axios
.get("/tm-member/member-advent", {
headers: { Authorization: `Bearer ${this.token}` },
params:{platformId}
})
.then((res) => {
if (res.data.code == 200) {
let result = res.data.data;
this.rechargeList = result;
} else {
layer.msg(response.data.msg);
}
});
},
getUserInfo(token) {
console.log("token", token);
let that = this;
axios
.get("/getinfo", {
headers: {
Authorization: `Bearer ${token}`,
},
})
.then((response) => {
console.log(response.data);
console.log("code", response.data.code);
if (response.data.code === 200) {
that.userInfo = response.data.data;
console.log("userinfo", that.userInfo);
} else {
localStorage.removeItem("token");
location.href = "login.html";
}
});
},
getStatistics() {
const that = this;
axios
.get("/tm-member-platform/statistics", {
headers: { Authorization: `Bearer ${this.token}` },
})
.then((response) => {
if (response.data.code == 200) {
this.xAxisData = response.data.data.xAxis;
this.seriesData = response.data.data.data || [];
} else {
layer.msg(response.data.msg);
}
});
},
look(apiKey, index) {
var layer = layui.layer;
// layer.open({
// content: token,
// // shade: 0.8
// shade: ["0.4"]
// // shade: false
// })
layer.open({
type: 1,
title: "API密钥",
closeBtn: 1,
shadeClose: true,
skin: "11",
content:
'<div class="secret-key"><div class="secret"><span>' +
apiKey +
'</span><i class="copy" data="' +
apiKey +
'" >复制</i></div></div>',
});
},
show(item) {
$(".modal-overlay").fadeIn();
this.rechargeData.platformId=item.platformId;
this.rechargeData.name=item.name;
},
close() {
$(".modal-overlay").fadeOut();
this.rechargeData={
platformId:null,
name:null,
count:1,
amount:null,
receiveAddress:null,
step:1,
expireUnix:undefined
};
console.log(this.rechargeData);
},
prevStep(){
this.rechargeData.step=1;
},
nextStep(){
if(this.rechargeData.count<=0){
layer.msg("数量不能小于0");
return;
}
this.loadingQr=true;
axios.post("/tm-member/recharge",this.rechargeData,{headers: { Authorization: `Bearer ${this.token}` }})
.then(res => {
console.log("sss",res);
if(res.data.code===200){
this.rechargeData.step=2;
this.rechargeData.amount=res.data.data.amount;
this.rechargeData.receiveAddress=res.data.data.receiveAddress;
this.rechargeData.blockChain=res.data.data.blockChain;
this.rechargeData.expireUnix=res.data.data.expireUnix;
let _that=this;
this.$nextTick(() => {
_that.generateQRCode(_that.rechargeData.receiveAddress);
})
}else{
layer.msg(res.data.msg);
}
}).finally(() => {
this.loadingQr=false;
});
},
showRecord(platformId){
$(".modal-overlay-record").fadeIn();
this.getMemberAdvent(platformId);
},
closeRecord(){
$(".modal-overlay-record").fadeOut();
},
tabClick(val) {
this.tabShow = val;
this.pageChart = null;
if (val == "voice") {
this.getVoicestatistics();
this.getuserinfo();
this.getUsersDuration();
}
},
copy() {
const apiKey = this.token;
navigator.clipboard.writeText(apiKey).then(() => {
console.log("已复制");
layer.msg("复制成功");
});
},
getUserInfo(token) {
let that = this;
axios
.get("/getinfo", {
headers: {
Authorization: `Bearer ${this.token}`,
},
})
.then((response) => {
if (response.data.code === 200) {
this.userInfo = response.data.data;
console.log("userinfo", this.userInfo);
} else {
location.href = "login.html";
}
});
},
// 模拟更新图表数据的方法
updateRandomChartData() {
// 直接调用 fetchChartData 来模拟数据更新
this.fetchChartData();
layer.msg("图表数据已更新!");
},
// === ECharts 初始化和更新方法 ===
initECharts() {
// 在这里添加一个检查,确保 echarts 对象是存在的
if (typeof echarts === "undefined") {
console.error("ECharts 库未加载!");
return;
}
const chartDom = document.getElementById("mainEchart");
if (!chartDom) {
console.error("ECharts 图表容器 DOM 元素 #mainEchart 未找到!");
return;
}
// 初始化 ECharts 实例
this.myChart = echarts.init(chartDom);
this.updateECharts(); // 首次加载数据
},
updateECharts() {
if (!this.myChart) {
console.error("ECharts 实例未创建!无法更新图表。");
return;
}
// 动态生成 series 配置
const series = this.seriesData.map((item, index) => {
// 使用 this.seriesData
const colors = [
"#3c8dbc",
"#00a65a",
"#f39c12",
"#724a9c",
"#e74c3c",
"#1abc9c",
];
const color = colors[index % colors.length];
return {
name: item.platformName, // 使用 platformName
type: "line",
// stack: '总量', // 如果不需要堆叠,请注释或移除此行
smooth: true,
lineStyle: {
width: 3,
},
itemStyle: {
borderColor: color,
borderWidth: 2,
},
emphasis: {
focus: "series",
},
data: item.data, // 使用 item.data
areaStyle: {
opacity: 0.8,
// 确保 echarts.graphic 存在
color:
typeof echarts !== "undefined" && echarts.graphic
? new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: hexToRgba(color, 0.3),
},
{
offset: 1,
color: hexToRgba(color, 0),
},
])
: color, // Fallback to solid color if graphic is not available
},
};
});
// 动态生成 legend data
const legendData = (this.seriesData || []).map(
(item) => item.platformName
); // 使用 platformName
const option = {
title: {
text: "字符消耗统计", // 标题可以直接在主实例中定义
left: "center",
textStyle: {
color: "#333",
fontSize: 18,
fontWeight: "bold",
},
},
tooltip: {
trigger: "axis",
axisPointer: {
type: "cross",
label: {
backgroundColor: "#6a7985",
},
},
formatter: function (params) {
var result = params[0].name + "<br/>";
params.forEach(function (item) {
if (
item.data !== null &&
item.seriesName &&
item.value !== undefined
) {
result +=
'<span style="display:inline-block;margin-right:4px;border-radius:10px;width:10px;height:10px;background-color:' +
item.color +
';"></span>' +
item.seriesName +
": " +
item.value +
"<br/>";
}
});
return result;
},
},
legend: {
data: legendData,
top: "bottom",
textStyle: {
color: "#666",
},
padding: [10, 0, 0, 0],
},
grid: {
left: "3%",
right: "4%",
bottom: "10%",
containLabel: true,
},
xAxis: {
type: "category",
boundaryGap: false,
data: this.xAxisData, // 直接使用 xAxisData
axisLabel: {
color: "#555",
},
axisLine: {
lineStyle: {
color: "#ccc",
},
},
},
yAxis: {
type: "value",
name: "字符数", // Y轴名称可以直接在主实例中定义
nameTextStyle: {
color: "#555",
padding: [0, 0, 10, 0],
},
axisLabel: {
formatter: "{value} ",
color: "#555",
},
axisLine: {
lineStyle: {
color: "#ccc",
},
},
splitLine: {
lineStyle: {
type: "dashed",
color: "#e0e0e0",
},
},
},
series: series,
};
this.myChart.setOption(option);
// 确保在设置选项后也调整图表大小
setTimeout(() => {
if (this.myChart) {
this.myChart.resize();
}
}, 50); // 增加一个短暂的延迟
},
resizeECharts() {
// 更改方法名以与组件内的 resizeChart 区分
if (this.myChart) {
const chartDom = document.getElementById("mainEchart");
if (chartDom) {
}
this.myChart.resize();
}
},
generateQRCode(qrString) {
const text = qrString.trim(); // 获取输入框内容并去除首尾空格
const qrcodeContainer = document.getElementById('qrcode');
if (text) {
console.log('container',qrcodeContainer)
// 1. 清空容器内的所有内容,包括旧的二维码或提示信息
qrcodeContainer.innerHTML = '';
this.showPlaceholder = false;
this.qrError = null;
// 2. 创建一个新的 canvas 元素
const canvasElement = document.createElement('canvas');
// 可以给 canvas 设置一个 ID 或者类名,如果需要后续引用或样式控制
// canvasElement.id = 'qrCanvas';
qrcodeContainer.appendChild(canvasElement); // 将 canvas 添加到容器中
// 3. 使用 QRCode.toCanvas 在新创建的 canvas 上生成二维码
QRCode.toCanvas(canvasElement, text, { // 将 canvasElement 传递给 toCanvas
width: 150, // 设置二维码宽度
color: {
dark: '#000000', // 二维码颜色
light:'#ffffff' // 背景颜色
}
}, (error) => {
if (error) {
qrcodeContainer.innerHTML = `<p class="text-red-500">获取地址失败请刷新</p>`; // 重新显示错误信息
} else {
console.log('二维码生成成功!');
}
});
} else {
// 如果输入为空,给出提示
qrcodeContainer.innerHTML = ''; // 清空可能存在的旧二维码
}
}
}
});
function copy(val) {
var layer = layui.layer;
const jsonStr = JSON.stringify(val);
// 模拟 输入框
var cInput = document.createElement("input");
cInput.value = jsonStr;
document.body.appendChild(cInput);
cInput.select(); // 选取文本框内容
// 执行浏览器复制命令
// 复制命令会将当前选中的内容复制到剪切板中这里就是创建的input标签
// Input要在正常的编辑状态下原生复制方法才会生效
document.execCommand("copy");
layer.msg("复制成功");
// 复制成功后再将构造的标签 移除
document.body.removeChild(cInput);
}
$("body").on("click", ".copy", function () {
console.log($(this).attr("data"));
copy($(this).attr("data"));
});
// $('body .copy').click(function() {
// console.log($(this).attr('data'))
// copy($(this).attr('data'))
// })
</script>
<div class="public-footer">
<div class="w1200">
<div class="left">
<img
src="https://codeai.oss-cn-hangzhou.aliyuncs.com/img/logo.png"
alt=""
/>
</div>
<div
style="
flex-direction: column;
line-height: 23px;
padding-left: 100px;
color: #fff;
font-size: 12px;
"
>
<p style="color: #fff; font-size: 12px"><span>官方频道:@apiapl_news</span></p>
<p style="color: #fff; font-size: 12px"><span>咨询客服:@apiapl</span></p>
<span></span>
</p>
</div>
<div class="right" style="white-space: nowrap">
<p></p>
<p><span>技术服务:@apiapl_sdk</span></p>
<p><span>联系邮箱info@apiapl.com</span></p>
<p class=""><span>联系电话:+18435173355 </span></p>
<p></p>
</div>
</div>
<div class="copyright">
<a href="https://beian.miit.gov.cn/" target="blank"></a>
</div>
</div>
<div class="layui-layer-move" style="cursor: move; display: none"></div>
<style>
.btn-clock{
width: 15px;
cursor: pointer;
}
.chart-container-wrapper {
width: 100%;
max-width: 900px; /* 最大宽度 */
background-color: #ffffff;
border-radius: 12px; /* 圆角 */
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); /* 阴影 */
padding: 20px;
box-sizing: border-box;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
margin: 20px auto; /* 居中显示 */
}
.echarts-chart-direct {
/* 更改类名以区分这里是直接渲染的div */
width: 100%;
height: 300px; /* === 移除此行,高度由内联样式直接控制 === */
/* === 调试用样式:添加边框和背景色 === */
/* ==================================== */
}
/* 响应式调整图表高度 */
@media (max-width: 768px) {
.chart-container-wrapper {
height: 350px !important; /* 响应式也添加 !important */
padding: 15px;
}
}
@media (max-width: 480px) {
.chart-container-wrapper {
height: 300px !important; /* 响应式也添加 !important */
padding: 10px;
}
}
</style>
</body>
</html>