Commit cfee98d1 by 蒋秀川

'jxc'

0 parents
Showing 737 changed files with 4476 additions and 0 deletions
node_modules
.DS_Store
dist
dist-ssr
*.local
\ No newline at end of file \ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,viewport-fit=cover,initial-scale=1.0,maximum-scale=1.0, user-scalable=no">
<title>视频巡店</title>
</head>
<body>
<div id="app" class="fullPage"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
{
"name": "vite",
"version": "0.0.0",
"scripts": {
"dev": "vite",
"build": "vite build"
},
"dependencies": {
"@vitejs/plugin-vue-jsx": "^1.3.9",
"axios": "^0.26.1",
"blueimp-md5": "^2.16.0",
"echarts": "^5.3.2",
"ezuikit-js": "^0.5.3",
"postcss-px-to-viewport": "^1.1.1",
"rollup-plugin-copy": "^3.4.0",
"url-param-parser": "^0.0.2",
"vant": "^3.0.0",
"vconsole": "^3.14.6",
"vue": "^3.0.6",
"weixin-js-sdk": "^1.6.0"
},
"devDependencies": {
"@vitejs/plugin-vue": "^1.2.2",
"@vue/compiler-sfc": "^3.0.11",
"less": "^4.1.1",
"vite": "^2.2.4",
"vite-plugin-style-import": "^0.10.0"
}
}
No preview for this file type
This diff could not be displayed because it is too large.
No preview for this file type
This diff could not be displayed because it is too large.
No preview for this file type
<template>
<div class="fullPage touchmove">
<livePlayer :params="paramObj"></livePlayer>
<div class="tour-btns" v-if="paramObj.type=='titem'">
<van-button @click="navBackTour" type="primary">返回上一页</van-button>
<van-button @click="pictureBtn" type="primary">确认并截图</van-button>
</div>
<div class="tour-btns" v-else-if="paramObj.type=='view'">
<van-button block @click="navBack" type="primary">查看其他监控点</van-button>
</div>
<div class="tour-btns" v-else>
<van-button @click="navBack" type="primary">查看其他监控点</van-button>
<van-button @click="pictureBtn" type="primary">开始巡检</van-button>
</div>
</div>
</template>
<script setup>
import { reactive, ref, onMounted, getCurrentInstance } from 'vue';
import { Toast } from 'vant';
import livePlayer from '@/components/livePlayer.vue';
//import vconsole from 'vconsole';
if (process.env.NODE_ENV !== 'production') {
//new vconsole();
}
/*获取 Url 参数 S*/
import parse from 'url-param-parser';
const paramObj = parse(window.location.href).search || {}
/********************************/
document.title = decodeURIComponent(paramObj.name);
localStorage.setItem('atoken', paramObj.atoken);
localStorage.setItem('lang', 'zh_CN');
/*获取 Url 参数 E*/
import tourApi from '@/api';
//var data = reactive(v);
const navBack = () => {
wx.miniProgram.redirectTo({
url: `/pages/tour/gate/index?type=${paramObj.type}`
});
};
const navBackTour = ()=>{
wx.miniProgram.navigateBack();
}
const pictureBtn = () => {
Toast.loading({
duration: 0,
message: '视频截图中···',
forbidClick: true,
});
tourApi.getCapture({id:paramObj.channelid}).then(res=>{
if(res.status!=200){
return Toast.fail(res.data.msg);
}
let picUrl = res.data.data;
Toast.clear();
if(paramObj.type!='titem'){
wx.miniProgram.redirectTo({
url: `/pages/tour/index/index?action=capture&picUrl=${picUrl}&id=${paramObj.id}&channelid=${paramObj.channelid}&mallId=${paramObj.mallId}&title=${paramObj.name}`
});
}else{
/***********巡店详情截图****************/
wx.miniProgram.navigateTo({
url: `/pages/tour/titem/index?action=capture&picUrl=${picUrl}&id=${paramObj.tid}`
});
}
})
};
onMounted(() => {
})
</script>
<style scoped lang="less">
.tour-btns{
display: flex;
justify-content: space-between;
padding:20px 2vw 0;
:deep(.van-button){
margin-bottom: 20px;
width:47vw;
&.van-button--block{
width:100%;
}
}
}
</style>
\ No newline at end of file \ No newline at end of file
import axios from 'axios'
import md5 from 'blueimp-md5'
import { param2 } from '@/utils'
import { Toast } from 'vant';
//const baseURL = 'https://store.keliuyun.com/report';
//const baseURL = 'https://mall.keliuyun.com';
const baseURL = 'http://192.168.1.106:81';
const Axios = axios.create({
baseURL: baseURL, // 因为我本地做了反向代理
timeout: 0,
// responseType: "json",
// changeOrigin: true,//允许跨域
withCredentials: true, // 是否允许带cookie这些
headers: {
"Content-Type": "application/json;charset=UTF-8"
// 'Content-Type': 'application/x-www-form-urlencoded'
}
})
let store = {
source: {
token: null,
cancel: null
}
}
// 请求拦截器
Axios.interceptors.request.use(
config => {
const suffix = '4c413628731691abc99eb2fca5f69aab'
const { method, params, data, url } = config
let language = localStorage.getItem('lang'),
aToken = localStorage.getItem('atoken');
if (language) {
let languageObj = {
'mall_CN': 'zh-CN,zh;q=0.9',
'zh_CN': 'zh-CN,zh;q=0.9',
'en_US': 'en-US,en;q=0.5',
'zh_TW': 'zh-TW,zh;q=0.3',
// 'zh_ar': 'zh-AR,zh;q=0.9'
}
languageObj[language] && (config.headers['Accept-Language'] = languageObj[language]);
}
aToken && (config.headers.Authorization = aToken);
config.cancelToken = store.source.token
const signalStr = method.toUpperCase() +
(params ? param2(params) : '') +
(data ? JSON.stringify(data) : '') +
suffix + (config.headers.Authorization ? config.headers.Authorization : '');
const hashSignature = md5(signalStr)
config.headers['signature'] = hashSignature
return config;
}, error => {
console.error(error);
return Promise.reject(error.data.msg)
}
)
Axios.interceptors.response.use(
res => {
if (res.data && !res.data.success) {
if (res.data.ecode && res.data.ecode != 200) {
Toast.fail(res.data.enote)
console.error(res.data.enote)
return ;
} else {
// 非标准返回体
if (res.status == 200) {
return res;
}
}
if (res.data.code == 500) {
console.error(res.data.msg)
}
return Promise.reject(res.data.msg);
} else if (!res.data && res.status == 200) {
return res;
} else if (res.data.success && res.config.method != 'get') {
//
}
return res;
}
)
export default function(method, url, data = null, config = null, bodyDelete) {
method = method.toLowerCase()
if (method == 'post') {
return Axios.post(url, data, config)
} else if (method == 'get') {
let defaultParam = {
_t: Date.parse(new Date()) / 1000
}
return Axios.get(url, { params: {...defaultParam, ...data }, config })
} else if (bodyDelete) {
return Axios.delete(url, { data: data }, config)
} else if (method == 'delete') {
return Axios.delete(url, { params: data }, config)
} else if (method == 'put') {
return Axios.put(url, data, config)
} else {
console.error('unknown method' + method)
return false
}
}
\ No newline at end of file \ No newline at end of file
import req from '@/api/http.js'
const tourApi = {
getLiveAddress(params,config) {
return req('get', `/patrol/patrolDeviceChannel/getLiveAddress/${params.id}`, params, config)
},
getLiveInfo(params,config){
return req('get', `/patrol/patrolDeviceChannel/getLiveInfo/${params.id}`, params, config)
},
// 截图
getCapture(params,config) {
return req('get', `/patrol/patrolDeviceChannel/capture/${params.id}`, params, config)
},
}
export default tourApi;
\ No newline at end of file \ No newline at end of file
<template>
<div class="videoWrap">
<div v-show="platform==1" class="video-box">
<canvas class="box" id="canvasVideo"></canvas>
</div>
<div v-show="platform==2" class="video-box">
<div class="box" id="my-video"></div>
</div>
<!-- <div class="tour-btns" v-else>
<van-button block @click="navBack" type="primary">查看其他监控点</van-button>
</div> -->
</div>
</template>
<script>
import { defineComponent,reactive,toRefs} from 'vue'
import { Toast} from 'vant';
import EZUIKit from 'ezuikit-js'
import SLPlayer from '@/static/js/slplayer'
import tourApi from '@/api';
export default defineComponent({
props: {
params: Object
},
data() {
return {
palyUrl: '',
player: '',
playerIndex: 0,
playerEz: '',
}
},
methods: {
createPlayer(row) {
this.playerIndex++;
let that = this;
that.Module = {
/* ************************************ */
// 定义视频画布
canvas: document.getElementById("canvasVideo"),
/* ************************************ */
// 设置相应的事件回调
onStart: function() {
console.log("onStart...")
},
onEnd: function() {
console.log("onEnd...")
},
onError: function(code, err) {
alert('error: ', code, err)
console.log('error: ', code, err);
},
onVideoStart: function() {
console.log('onVideoStart。。。');
},
// 录像回放中返回时间刻度
onPlayTime: function(ts) {
if (ts == 0) return;
var date = new Date(ts * 1000); //如果date为10位不需要乘1000
var Y = date.getFullYear() + '-';
var M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-';
var D = (date.getDate() < 10 ? '0' + (date.getDate()) : date.getDate()) + ' ';
var h = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ':';
var m = (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()) + ':';
var s = (date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds());
var timestamp = Y + M + D + h + m + s;
}
}
SLPlayer(that.Module).then(function(obj) {
that.loading = false
that.player = obj;
setTimeout(() => {
that.player.start(row);
Toast.clear();
}, 1000)
});
},
playerVideo(data) {
this.palyUrl = data.liveAddress;
let atoken = data.accessToken;
// 拾联视频
if (this.platform == 1) {
// 清除萤石云视频
if (this.playerEz) {
let canvasVideo = document.getElementById('my-video')
canvasVideo.innerHTML = ''
}
if (this.playerIndex > 0) {
// 暂停上次播放并重新开始新的视频
this.player.stop();
setTimeout(() => {
this.player.start(this.palyUrl);
Toast.clear();
}, 100)
} else {
this.createPlayer(this.palyUrl);
}
} else {
// 萤石云视频
// 清除拾联视频
if (this.player) {
this.player.stop();
}
if (this.playerEz) {
let canvasVideo = document.getElementById('my-video')
canvasVideo.innerHTML = ''
}
// 开始萤石云视频
this.playerEz = new EZUIKit.EZUIKitPlayer({
id: "my-video", // 视频容器ID
accessToken: atoken,
url: this.palyUrl,
template: 'mobileLive', //simple - 极简版;standard-标准版;security - 安防版(预览回放);voice-语音版;
autoplay: true,
//footer: ['hd', 'fullScreen'],
width: window.innerWidth,
height:window.innerWidth*1080/1920,
});
Toast.clear();
}
},
loadTourVideo() {
Toast.loading({
duration:0,
message: '加载中···',
forbidClick: true,
});
let {channelid,platform} = this.params;
tourApi.getLiveAddress({ id: channelid, protocol:platform == 2 ? 1 : 2, quality: 1 }).then(res => {
var data = res.data;
if (data.code != 200) {
Toast.fail({
message: data.msg,
onClose() {
wx.miniProgram.navigateBack()
}
});
} else {
this.playerVideo(data.data);
}
})
}
},
created() {
this.loadTourVideo();
},
destroyed(){
},
setup(props, context) {
const params = reactive(props.params);
return {
...toRefs(params)
}
}
})
</script>
<style scoped lang="less">
.videoWrap {
position: relative;
width: 100%;
.video-box {
position: relative;
.box {
position: relative;
width: 100%;
min-height: 420px;
background: #000;
}
}
:deep(.head-message),:deep(.live-ptz-title){
display: none!important;
}
:deep(.mobile-ez-ptz-container){
padding-top:20px;
}
/*,/deep/.mobile-ez-ptz-container{
display: none!important;
}*/
}
</style>
\ No newline at end of file \ No newline at end of file
import { createApp } from 'vue';
import wx from 'weixin-js-sdk';
window.wx = wx;
import App from './App.vue';
import Vant from 'vant';
import '@s/css/index.css';
import 'vant/lib/index.css';
const app = createApp(App);
app.use(Vant);
app.mount('#app')
@charset "utf-8";
/*=====================================
reset
=====================================*/
html,
body,
h1,
h2,
h3,
h4,
h5,
h6,
table,
thead,
tfoot,
tbody,
form,
fieldset,
legend,
div,
p,
span,
dl,
dt,
dd,
ul,
ol,
li,
blockquote,
pre,
q,
cite,
code,
input,
select,
textarea{margin:0;padding:0;/* font-family:"fang"; */}
h1,
h2,
h3,
h4,
h5,
h6,
strong,
em,
cite,
address,
sup,
sub,
th{font-weight:normal;font-style:normal;vertical-align:auto;font-size:1em;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-tap-highlight-color:transparent;}
i{font-style:normal;}
/* @font-face{
font-family: fang;
src: url('http://h5.wufae.com/Chevrolet/upload/static/css/fang.ttf') format('truetype');
} */
*{/* font-family:"fang"; */box-sizing:border-box;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-tap-highlight-color:transparent;}
input,
textarea,
input:focus,
select:focus,
textarea:focus{/* font-family:"fang"; */border-width:0px;border-color:transparent;-webkit-tap-highlight-color:transparent;outline:transparent;}
ul,
ol{list-style-type:none;}
a:link,
a:visited{text-decoration:none;outline:0 none;}
a:hover,
a:active{text-decoration:underline;outline:0 none;}
fieldset,
a img{border:none;}
img{vertical-align:top;display:block;}
input,
textarea,
button{font-size:100%;}
button{cursor:pointer;}
textarea{resize:none;overflow:auto;}
table{border-collapse:collapse;border-spacing:0;}
select optgroup{font-style:normal;}
legend{display:none;}
input[type="radio"],
input[type="checkbox"],
textarea{vertical-align:middle;}
input,
select{background:transparent;border:0;outline:none;}
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button{-webkit-appearance:none!important;margin:0;}
.iswin input[type="radio"],
.iswin input[type="checkbox"],
.iswin textarea{vertical-align:-3px;}
input[type="radio"],
input[type="checkbox"]{margin-right:3px;}
input[type="text"],
input[type="password"],
textarea{border:none;}
input[type="text"]:focus,
input[type="password"]:focus,
a,
img{tap-highlight-color:rgba(0,0,0,0);focus-ring-color:rgba(0,0,0,0);-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-focus-ring-color:rgba(0,0,0,0);-moz-tap-highlight-color:rgba(0,0,0,0);-moz-focus-ring-color:rgba(0,0,0,0);}
.application{position:absolute;left:0;top:0;bottom:0;right:0;}
/*=====================================
ȫ?? =====================================*/
html{height:100%;overflow:hidden;}
body{transition:opacity 0.25s;position:relative;margin:0 auto;width:100%;height:100%;}
body.succ{opacity:1;}
.root_gap{position:relative; /* width:96%; */margin:0 30px;}
.clearfix{zoom:1;}
.clearfix:after{content:"";display:block;height:0;font-size:0;clear:both;overflow:hidden;visibility:hidden;}
.fullPage{position:absolute;left:0;top:0;width: 100%;height: 100%;background-color: #f3f9ff;}
.touchmove{overflow:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch;overflow-scrolling:touch;}
\ No newline at end of file \ No newline at end of file
This diff could not be displayed because it is too large.
No preview for this file type
This diff could not be displayed because it is too large.
No preview for this file type
/**
* @param {array} actual
* @returns {array}
*/
export function cleanArray(actual) {
const newArray = []
for (let i = 0; i < actual.length; i++) {
if (actual[i]) {
newArray.push(actual[i])
}
}
return newArray
}
/**
* @param {object} json
* @returns {string}
*/
export function param2(json) {
if (!json) return ''
return cleanArray(
Object.keys(json).map(key => {
if (json[key] === undefined ||
json[key] === null
) return ''
return encodeURIComponent(key) + '=' + json[key]
})
).join('&')
}
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import pxtovw from 'postcss-px-to-viewport'
import styleImport, { VantResolve } from 'vite-plugin-style-import';
const loder_pxtovw=pxtovw({
unitToConvert: "px", // 需要转换的单位,默认为"px"
viewportWidth: 750, // 设计稿的视口宽度
unitPrecision: 2, // 单位转换后保留的精度
propList: ["*"], // 能转化为vw的属性列表
viewportUnit: "vw", // 希望使用的视口单位
fontViewportUnit: "vw", // 字体使用的视口单位
selectorBlackList: ['ignore'], // 需要忽略的CSS选择器
exclude:[/node_module/],
})
import path from 'path';
import copy from 'rollup-plugin-copy'
export default defineConfig({
base:'./',
publicDir:'public',
plugins: [
vue(),
vueJsx(),
styleImport({
libs: [
{
libraryName: "vant",
esModule: true,
resolveStyle: (name) => `vant/es/${name}/style`,
},
],
}),
],
css: {
postcss:{
plugins: [loder_pxtovw]
}
},
resolve:{
alias:{
"@": path.resolve(__dirname, "./src"),
"@s": path.resolve(__dirname, "./src/static")
}
},
build:{
assetsDir:'static',
// rollupOptions:{
// plugins:[copy({
// targets: [
// { src: 'public/*', dest: 'dist/pp' }
// ]
// })]
// }
}
})
This diff is collapsed. Click to expand it.
/*
* Eslint config file
* Documentation: https://eslint.org/docs/user-guide/configuring/
* Install the Eslint extension before using this feature.
*/
module.exports = {
env: {
es6: true,
browser: true,
node: true,
},
ecmaFeatures: {
modules: true,
},
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
},
globals: {
wx: true,
App: true,
Page: true,
getCurrentPages: true,
getApp: true,
Component: true,
requirePlugin: true,
requireMiniProgram: true,
},
// extends: 'eslint:recommended',
rules: {},
}
# Windows
[Dd]esktop.ini
Thumbs.db
$RECYCLE.BIN/
# macOS
.DS_Store
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
# Node.js
node_modules/
let http = require('../utils/request');
module.exports = {
// 获取报表id
getReportCharts: (data) => {
const params = {
"report": data.report
}
if (wx.getStorageSync('deploymentType') === 'private') {
return http.post(data.url, {
url: wx.getStorageSync('baseUrl') + data.url,
param: JSON.stringify(params),
method: 'GET'
}, data.header)
} else {
return http.get(data.url, params, data.header)
}
},
// 获取首页报表
getIndexInfo: (url, data, header) => {
if (wx.getStorageSync('deploymentType') === 'private') {
return http.post(url, {
url: wx.getStorageSync('baseUrl') + url,
param: JSON.stringify(data),
method: 'GET'
}, header)
} else {
return http.get(url, data, header)
}
},
}
\ No newline at end of file \ No newline at end of file
let http = require('../utils/request');
module.exports = {
// 登陆接口
login: (data) => {
const params = {
"loginName": data.name,
"password": data.password
}
if (wx.getStorageSync('deploymentType') !== 'private') {
return http.post(data.url, params)
} else {
return http.get(data.url,
{
url: wx.getStorageSync('baseUrl') + data.url,
param: JSON.stringify(params),
method: 'POST'
},
// {
// 'Authorization': 'no'
// }
)
}
},
getApps: (data) => {
if (wx.getStorageSync('deploymentType') === 'private') {
return http.post(data.url, {
url: wx.getStorageSync('baseUrl') + data.url,
param: null,
method: 'GET'
}, data.header)
} else {
return http.get(data.url, null, data.header)
}
},
getMenus: (data) => {
if (wx.getStorageSync('deploymentType') === 'private') {
return http.post(data.url, {
url: wx.getStorageSync('baseUrl') + data.url,
param: null,
method: 'GET'
}, data.header)
} else {
return http.get(data.url, null, data.header)
}
},
getAccounts: (data) => {
if (wx.getStorageSync('deploymentType') === 'private') {
return http.post(data.url, {
url: wx.getStorageSync('baseUrl') + data.url,
param: null,
method: 'GET'
}, data.header)
} else {
return http.get(data.url, null, data.header)
}
},
getMalls: (data) => {
const params = {
"accountId": data.accountId,
"status": 1
}
if (wx.getStorageSync('deploymentType') === 'private') {
return http.post(data.url, {
url: wx.getStorageSync('baseUrl') + data.url,
param: JSON.stringify(params),
method: 'GET'
}, data.header)
} else {
return http.get(data.url, params, data.header)
}
},
}
\ No newline at end of file \ No newline at end of file
let http = require('../utils/request');
import _ from 'underscore';
module.exports = {
/**
* 获取自定义列表
*/
getCharts(params) {
let url = '/report/reportChart/getCharts';
let atoken = wx.getStorageSync('atoken');
if (wx.getStorageSync('deploymentType') === 'private') {
return http.post(url, {
url: wx.getStorageSync('baseUrl') + url,
param: JSON.stringify(params),
method: 'GET'
}, {
'Authorization':atoken
})
} else {
return http.get(url, params);
}
},
/**
* 顶部卡片区域
*/
headReport(params, config) {
let url = `/report/new/report/${params.dateType}/${params.orgType}/head`;
let atoken = wx.getStorageSync('atoken');
if (wx.getStorageSync('deploymentType') === 'private') {
return http.post(url, {
url: wx.getStorageSync('baseUrl') + url,
param: JSON.stringify(params),
method: 'GET'
}, {
'Authorization':atoken
})
} else {
return http.get(url, params);
}
},
/**
* 图表内容区域
*/
bodyReport(params, config) {
let url = `/report/new/report/${params.dateType}/${params.orgType}/body`;
let atoken = wx.getStorageSync('atoken');
params = _.pick(params, val => {
return String(val) != 'undefined' && String(val).length > 0;
})
if (wx.getStorageSync('deploymentType') === 'private') {
return http.post(url, {
url: wx.getStorageSync('baseUrl') + url,
param: JSON.stringify(params),
method: 'GET'
}, {
'Authorization':atoken
})
} else {
return http.get(url, params);
}
}
}
\ No newline at end of file \ No newline at end of file
let http = require('../utils/request');
import _ from 'underscore';
module.exports = {
handle(params,config){
return http.post(`/patrol/patrolRecord/handle`, params,config);
},
tourUserList(params){
return http.get(`/patrol/s-user/mall/${params.mallId}`, params);
},
uploadFile(params){
return http.post(`/report/file`, params);
},
/**
* 用户列表
*/
userList(params) {
return http.get('/report/users', params);
},
/**
* 用户所属的商场
*/
userMall(params) {
return http.get('/report/userMalls', params);
},
//巡店记录
getPatrolRecordList(params) {
return http.get('/patrol/patrolRecord/list', params);
},
getPatrolSopTypeTree(params) {
return http.get('/patrol/patrolSopType/tree', params);
},
// 查看巡店详情
getPatrolRecordDetail(params,config) {
return http.get(`/patrol/patrolRecord/${params.id}`, params);
},
//提交巡店记录
confirmPatrolRecord(params,config) {
return http.post(`/patrol/patrolRecord`, params,config);
},
/**
* 获取监控点列表
*/
getPatrolGateList(params) {
return http.get('/patrol/patrolGate/list', params);
},
getPatrolGate(params) {
return http.get(`/patrol/patrolGate/${params.id}`, params)
},
getLiveAddress(params) {
return http.get(`/patrol/patrolDeviceChannel/getLiveAddress/${params.id}`, params);
},
// 截图
getCapture(params) {
return http.get(`/patrol/patrolDeviceChannel/capture/${params.id}`, params);
},
getBase64(params){
return http.get(`/patrol/file`, params)
},
// 获取监控点关联sop
getPatrolGateSopProjectList(params) {
return http.get(`/patrol/patrolGateSopProject/list`, params);
},
}
\ No newline at end of file \ No newline at end of file
// app.js
require('./extends/page-extend')
import {ajaxUrl,picUrl} from './config.js';
App({
onLaunch() {
const updateManager = wx.getUpdateManager()
updateManager.onCheckForUpdate(function (res) {
// 请求完新版本信息的回调
console.log(res.hasUpdate)
})
updateManager.onUpdateReady(function () {
wx.showModal({
title: '更新提示',
content: '新版本已经准备好,是否重启应用?',
success(res) {
if (res.confirm) {
// 新的版本已经下载好,调用 applyUpdate 应用新版本并重启
updateManager.applyUpdate()
}
}
})
})
updateManager.onUpdateFailed(function () {
// 新版本下载失败
})
let menuButtonObject = wx.getMenuButtonBoundingClientRect();
wx.getSystemInfo({
success: res => {
let statusBarHeight = res.statusBarHeight,
navTop = menuButtonObject.top,//胶囊按钮与顶部的距离
navHeight = statusBarHeight + menuButtonObject.height + (menuButtonObject.top - statusBarHeight)*2;//导航高度
this.globalData.navHeight = navHeight;
this.globalData.navTop = navTop;
this.globalData.windowHeight = res.windowHeight;
this.globalData.windowWidth = res.windowWidth;
},
fail(err) {
console.log(err);
}
})
// 展示本地存储能力
const logs = wx.getStorageSync('logs') || []
logs.unshift(Date.now())
wx.setStorageSync('logs', logs)
// 登录
wx.login({
success: res => {
// 发送 res.code 到后台换取 openId, sessionKey, unionId
}
})
// 获取用户信息
wx.getSetting({
success: res => {
if (res.authSetting['scope.userInfo']) {
// 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
wx.getUserInfo({
success: res => {
// 可以将 res 发送给后台解码出 unionId
this.globalData.userInfo = res.userInfo
// 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
// 所以此处加入 callback 以防止这种情况
if (this.userInfoReadyCallback) {
this.userInfoReadyCallback(res)
}
}
})
}
}
})
},
globalData: {
mallList:[],
picUrl:picUrl,
ajaxUrl:ajaxUrl,
userInfo: null,
pageType: 'mall',
deploymentType: 'private',
url: '',
openTest:false
}
})
/*
,{
"root": "pages/tour",
"name": "tour",
"pages":[
"list/index",
"titem/index",
"webview/index",
"video/index"
]
}
*/
\ No newline at end of file \ No newline at end of file
{
"pages": [
"pages/tour/titem/index",
"pages/home/index",
"pages/tour/list/index",
"pages/tour/gate/index",
"pages/tour/webview/index",
"pages/tour/index/index",
"pages/login/index",
"pages/index/index",
"pages/me/index",
"pages/tour/point/index"
],
"subPackages": [
{
"root": "pages/zong",
"name": "zong",
"pages": [
"basic/index",
"condition/index",
"contrast/index",
"entry-rate/index",
"holiday-comparison/index",
"ranking/index",
"selectFollr/index",
"selectGate/index",
"selectMall/index",
"selectZone/index",
"sequential/index",
"timeTravel/index"
]
}
],
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "Weixin",
"navigationBarTextStyle": "black",
"navigationStyle": "custom"
},
"tabBar": {
"color": "#8181A5",
"selectedColor": "#0069FF",
"borderStyle": "black",
"backgroundColor": "#ffffff",
"list": [
{
"pagePath": "pages/index/index",
"iconPath": "images/home.png",
"selectedIconPath": "images/home-b.png",
"text": "首页"
},
{
"pagePath": "pages/home/index",
"iconPath": "images/cong.png",
"selectedIconPath": "images/cong-b.png",
"text": "工作台"
},
{
"pagePath": "pages/me/index",
"iconPath": "images/me.png",
"selectedIconPath": "images/me-b.png",
"text": "我的"
}
]
},
"useExtendedLib": {
"weui": true
},
"usingComponents": {
"navbar2": "/components/navbar2/index",
"malllist": "/components/mallList/index",
"van-icon": "@vant/weapp/icon/index",
"arrow": "/components/arrow/index",
"van-tab": "@vant/weapp/tab/index",
"van-tabs": "@vant/weapp/tabs/index",
"van-row": "@vant/weapp/row/index",
"van-col": "@vant/weapp/col/index",
"van-cell": "@vant/weapp/cell/index",
"van-collapse": "@vant/weapp/collapse/index",
"van-collapse-item": "@vant/weapp/collapse-item/index",
"van-empty": "@vant/weapp/empty/index",
"van-button": "@vant/weapp/button/index",
"van-divider": "@vant/weapp/divider/index"
},
"lazyCodeLoading": "requiredComponents",
"sitemapLocation": "sitemap.json"
}
\ No newline at end of file \ No newline at end of file
/**app.wxss**/
view {
box-sizing: border-box;
}
page{background-color: #efeff4;}
.root_gap {
padding-left: 20rpx;
padding-right: 20rpx;
}
.ellipsis{overflow: hidden;text-overflow: ellipsis;white-space: nowrap;}
.container {
/* height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
padding: 200rpx 0;
box-sizing: border-box; */
width: 100%;
/* position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0; */
display: flex;
flex-direction: column;
align-items: center;
/* justify-content: space-between; */
box-sizing: border-box;
background-color: #F5F5FA;
padding-bottom: 0rpx;
}
.acea-row {
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
}
.row-around {
justify-content: space-around;
}
.acea-column {
flex-direction: column;
}
.row-start {
justify-content: flex-start
}
.echart-item {
width: 710rpx;
border-radius: 14rpx;
background-color: #fff;
box-shadow: 0px 4rpx 8rpx 0px rgba(118, 118, 118, 0.24);
box-sizing: border-box;
padding: 24rpx 0;
margin: 30rpx auto 0;
}
.echart-item .echart-item-title {
font-size: 30rpx;
font-weight: 600;
color: rgba(0, 0, 0, 0.85);
line-height: 40rpx;
display: flex;
padding-left: 20rpx;
justify-content: space-between;
}
.echart-item .echart-item-content {
width: 100%;
height: calc(100% - 19px);
}
.echart-item .actions{
display: flex;
font-size: 26rpx;
color: #8C8C8C;
}
.echart-item .actions .active{
color:#2f6cee
}
.echart-item .actions .split{
padding:0 6rpx;
}
ec-canvas {
width: 100%;
height: 100%;
}
.tablist{
--tabs-bottom-bar-color:#1267E0;
--tab-active-text-color:#1267E0;
--font-weight-bold:600;
--tab-font-size:26rpx;
--tabs-line-height:60rpx;
}
.bgimg{
position: absolute;
left:0;
top:0;
width: 100%;
height: 100%;
z-index: 0;
}
.navtitle{display:flex;position: relative;width: 100%;color:#fff;text-align: left;padding-left: 20rpx;font-weight: normal;font-size: 35rpx;align-items: center;}
page-container{
position: absolute;
z-index: 20;
}
/*********************************/
.tcol{
border-right: 1px solid rgba(0,0,0,0.1);
font-size: 14px;
text-align: center;
}
.tcol.none{
border-right: none;
}
.tcol.yes{
color:#07c160
}
.tcol.no{
color:#ee0a24
}
.tcol.none{
color:#1989fa
}
// components/arrow/index.js
Component({
styleIsolation: 'apply-shared',
/**
* 组件的属性列表
*/
properties: {
size:{
type:String,
value:'10rpx'
},
direction:{
type:String,
value:''
},
customClass:{
type:String,
value:''
},
},
/**
* 组件的初始数据
*/
data: {
},
/**
* 组件的方法列表
*/
methods: {
}
})
{
"component": true,
"usingComponents": {}
}
\ No newline at end of file \ No newline at end of file
<view class="arrow {{direction}} {{customClass}}">
<view class="triangle u" style="border-width:{{size}}"></view>
<view class="triangle d" style="border-width:{{size}}"></view>
</view>
\ No newline at end of file \ No newline at end of file
/* components/arrow/index.wxss */
.triangle{
width: 0;
height: 0;
border: 10rpx solid transparent;
}
.triangle.u{
border-bottom-color: #ccc;
margin-bottom: 5rpx;
}
.triangle.d{
border-top-color: #ccc;
}
.arrow{
display: inline-block;
vertical-align: middle;
padding:0 4rpx;
}
.arrow.up .triangle.u{
border-bottom-color: #000;
}
.arrow.down .triangle.d{
border-top-color: #000;
}
\ No newline at end of file \ No newline at end of file
// components/ceshi/index.js
const App = getApp();
Component({
/**
* 组件的属性列表
*/
properties: {
},
/**
* 组件的初始数据
*/
data: {
windowWidth: App.globalData.windowWidth,
mode: 'date',
dateItems: [
{
value: 'date',
label: '日'
},
{
value: 'week',
label: '周'
},
{
value: 'month',
label: '月'
},
{
value: 'year',
label: '年'
},
],
pickerArray: [], //日期控件数据list
pickerIndex: [], //日期控件选择的index
mode: 'date',
dateString: '',
pickerIndex1: []
},
lifetimes: {
attached() {
// 在组件实例进入页面节点树时执行
},
detached() {
// 在组件实例被从页面节点树移除时执行
},
ready() {
this.getPickerArray()
}
},
/**
* 组件的方法列表
*/
methods: {
//补零
formatNumber(n) {
n = n.toString()
return n[1] ? n : '0' + n
},
//日期时间格式化
formateDateTime(arr) {
let mode = this.data.mode
let unit = ['第一周', '第二周', '第三周', '第四周', '第五周']
let weekReturn = ''
if (mode === 'week') {
weekReturn = arr[0] + '-' + arr[1] + '-' + unit[arr[2] - 1]
}
switch (mode) {
case 'date':
return arr.map(this.formatNumber).join('-')
break;
case 'week':
return weekReturn
break;
case 'month':
return arr.map(this.formatNumber).join('-')
break;
case 'year':
return arr.map(this.formatNumber).join('-')
break;
}
},
/**
*
* 获取本月天数
* @param {number} year
* @param {number} month
* @param {number} [day=0] 0为本月0最后一天的
* @returns number 1-31
*/
_getNumOfDays(year, month, day = 0) {
return new Date(year, month, day).getDate();
},
/**
* 根据年月 获取 输入月份有几周
* @param {*} mode
*/
_getNewWeeks(year, month) {
let d = new Date()
d.setFullYear(year, month, 0)
let monthDays = d.getDate(); // 该月天数
let weeks = 0; // 该月周数
// 计算第一周
d.setFullYear(year, month - 1, 1) // 该月第一天
let w1 = d.getDay() // 获取星期几(0 - 6)该月第一天 星期几
// 按照星期一到星期天的形式计算
if (w1 === 0) {
// 如果这个月的一号是这周的最后一天
weeks = 1
monthDays = monthDays - 1
} else {
// 如果这个月的一号不是这周的最后一天
weeks = 1
monthDays = monthDays - (7 - w1 + 1)
}
// 计算最后一周天数
d.setFullYear(year, month, 0)
let newmonthDays = d.getDate()
d.setFullYear(year, month - 1, newmonthDays) // 该月最后一天
let w2 = d.getDay() // 获取星期几(0 ~ 6) 该月第一天 星期几
if (w2 === 0) {
monthDays = monthDays - 7
} else {
monthDays = monthDays - w2
}
weeks = weeks + 1 // 再加最后一周
weeks = weeks + (monthDays / 7) // 加上剩余的周数
return weeks
},
// 获取当前第几周
_getWeek(dt) {
let d1 = new Date(dt);
let d2 = new Date(dt);
d2.setMonth(0);
d2.setDate(1);
let rq = d1 - d2;
let days = Math.ceil(rq / (24 * 60 * 60 * 1000));
let num = Math.ceil(days / 7);
return num + 1;
},
//获取pickerArray
getPickerArray(mode = this.data.mode) {
let date = new Date();
let pickerArray = []
//年
let year = [];
for (let i = date.getFullYear() - 5; i <= date.getFullYear() + 5; i++) {
year.push({
id: i,
name: i + '年'
});
}
let currentYear = date.getFullYear();
let yearIndex = year.findIndex(item => item.id == currentYear);
pickerArray.push({
picker: 'year',
value: year,
pickerIndex: yearIndex
})
//月
let month = [];
for (let i = 1; i <= 12; i++) {
month.push({
id: i,
name: i + '月'
});
}
pickerArray.push({
picker: 'month',
value: month,
pickerIndex: date.getMonth(),
})
// 周
let week = [];
let unit = ['第一周', '第二周', '第三周', '第四周', '第五周']
let weekNum = this._getNewWeeks(date.getFullYear(), date.getMonth() + 1);
for (let i = 1; i <= weekNum; i++) {
week.push({
id: i,
name: unit[i - 1]
})
}
pickerArray.push({
picker: 'week',
value: week,
pickerIndex: this._getWeek(date.getFullYear() + "-" + date.getMonth() + 1 + "-" + date.getDate()) - 1
})
//日
let dayNum = this._getNumOfDays(date.getFullYear(), date.getMonth() + 1);
let day = [];
for (let i = 1; i <= dayNum; i++) {
day.push({
id: i,
name: i + '日'
});
}
pickerArray.push({
picker: 'day',
value: day,
pickerIndex: date.getDate() - 1,
})
let pickerIndex = []
//过滤不同mode的pickerArray keys
let formatPickerArray = () => {
switch (mode) {
case 'date':
return ['year', 'month', 'day']
break;
case 'week':
return ['year', 'month', 'week']
break;
case 'month':
return ['year', 'month']
break;
case 'year':
return ['year']
break;
}
}
//过滤不同mode的pickerArray values
let pickerValues = formatPickerArray(mode)
let formatPickers = []
//获取pickers选项和默认选择下标
pickerArray.map(item => {
if (pickerValues.indexOf(item.picker) >= 0) {
pickerIndex.push(item.pickerIndex)
formatPickers.push(item.value)
}
})
this.setData({
pickerArray: formatPickers,
pickerIndex,
})
//通过下标获取对应时间
let currentDate = this.getPickerValue(pickerIndex)
this.setData({
dateString: currentDate
})
},
getPickerValue(pickerIndex) {
let date = this.data.pickerArray.map((item, index) =>
this.data.pickerArray[index][pickerIndex[index]].id
)
let dateString = this.formateDateTime(date)
return dateString
},
pickerChange: function (e) {
let currentDate = this.getPickerValue(e.detail.value)
this.setData({
dateString: currentDate
})
let detail = {
value: currentDate
}
},
// 切换年、月时周和日变化
pickerYearOrMonthChangeWeekOrDay(year, value) {
if (this.data.mode === 'week') {
let week = [];
let unit = ['第一周', '第二周', '第三周', '第四周', '第五周']
let weekNum = this._getNewWeeks(year, value.value + 1);
for (let i = 1; i <= weekNum; i++) {
week.push({
id: i,
name: unit[i - 1]
})
}
this.data.pickerArray[2] = week
} else {
let days = this._getNumOfDays(year, value.value + 1)
let day = [];
for (let i = 1; i <= days; i++) {
day.push({
id: i,
name: i + '日'
});
}
this.data.pickerArray[2] = day
}
this.setData({
pickerArray: this.data.pickerArray
})
},
bindChange: async function(e) {
const val = e.detail.value
this.setData({ pickerIndex1: val })
let { pickerIndex, pickerArray, mode } = this.data;
let year = pickerArray[0][pickerIndex[0]].id
if (pickerIndex[0] !== val[0]) { // 切换年
year = pickerArray[0][val[0]].id;
if (mode === 'week' || mode === 'date') {
this.setData({ pickerIndex: [val[0], 0, 0] })
this.pickerYearOrMonthChangeWeekOrDay(year, { value: 0 })
} else if (mode === 'month') {
this.setData({ pickerIndex: [val[0], 0] })
} else {
this.setData({ pickerIndex: [val[0]] })
}
}
if (pickerIndex[0] === val[0] && pickerIndex[1] !== val[1]) { // 切换月
if (mode === 'week' || mode === 'date') {
this.pickerYearOrMonthChangeWeekOrDay(year, { value: val[1] })
}
}
},
changeItem: function(e) {
this.setData({ mode: e.target.dataset.unit })
},
}
})
{
"component": true,
"usingComponents": {}
}
\ No newline at end of file \ No newline at end of file
<view class="picker-timer" style="width: {{windowWidth}}px">
<view class="selected-date">
<view class="left commonText">取消</view>
<view class="changeDate">
<view
class="changeDateItem"
wx:key="index"
wx:for-item="actionItem"
wx:for-index="index"
wx:for="{{dateItems}}"
data-unit="{{actionItem.value}}"
style="margin-left: {{index === 0 ? 0 : '24rpx'}};background-color: {{actionItem.value === mode ? 'rgba(255, 255, 255, .9)' : 'rgba(255, 255, 255, 0)'}};color:{{actionItem.value === mode ? '#0069FF' : 'rgba(255, 255, 255, .5)'}}"
bindtap="changeItem"
>
{{ actionItem.label }}
</view>
</view>
<view class="right commonText">完成</view>
</view>
<view class="date-picker">
<picker-view
indicator-style="height: 50px;"
style="width: 100%; height: 300px;"
value="{{pickerIndex}}"
bindchange="bindChange"
bindpickend="bindpickend"
>
<picker-view-column
data-item="{{itemIndex}}"
wx:key="itemIndex"
wx:for-item="actionItem"
wx:for-index="itemIndex"
wx:for="{{pickerArray}}"
>
<view
wx:for="{{actionItem}}"
wx:key="{{itemIndex}}"
wx:for-item="aItem"
style="line-height: 50px; text-align: center;">
{{aItem.name}}
</view>
</picker-view-column>
</picker-view>
</view>
</view>
\ No newline at end of file \ No newline at end of file
.picker-timer {
height: 460rpx;
position: fixed;
left: 0;
bottom: 0;
}
.selected-date {
width: 100%;
height: 80rpx;
background-color: #0069FF;
display: flex;
align-items: center;
justify-content: center;
position: relative;
}
.selected-date .commonText {
font-size: 26rpx;
color: #fff;
line-height: 32rpx;
}
.selected-date .left {
position: absolute;
left: 32rpx;
top: 24rpx;
}
.selected-date .right {
position: absolute;
right: 32rpx;
top: 24rpx;
}
.changeDate {
width: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.date-picker {
height: 380rpx;
width: 100%;
background-color: #fff;
}
.changeDateItem {
width: 80rpx;
height: 40rpx;
border-radius: 18rpx;
font-size: 22rpx;
display: flex;
align-items: center;
justify-content: center;
}
\ No newline at end of file \ No newline at end of file
Component({
/**
* 组件的属性列表
*/
properties: {
imgUrls: Array,
},
/**
* 组件的初始数据
*/
data: {
currentIndex: 0
},
/**
* 组件的方法列表
*/
methods: {
swiperChange(e) {
this.setData({
currentIndex: e.detail.current
});
}
}
});
\ No newline at end of file \ No newline at end of file
{
"component": true,
"usingComponents": {}
}
\ No newline at end of file \ No newline at end of file
<swiper indicator-dots="false"
autoplay="{{false}}"
interval="5000"
indicator-dots="{{false}}"
indicator-color='#8a8a8a'
indicator-active-color='#333'
circular="true"
class="swiper-block"
bindchange="swiperChange"
previous-margin="100rpx"
next-margin="100rpx"
current="{{0}}">
<block wx:for="{{imgUrls}}" wx:index="{{index}}" wx:key="{{index}}">
<swiper-item class="swiper-item ">
<image mode="aspectFill" src="{{item}}" class="slide-image {{currentIndex == index ? 'active' : 'common'}}" />
</swiper-item>
</block>
</swiper>
\ No newline at end of file \ No newline at end of file
page{
background-color: #fff;
}
.swiper-block {
background: #fff;
height: 200rpx;
width: 100%;
}
.swiper-item{
display: flex;
flex-direction: column;
justify-content: start;
align-items: flex-start;
overflow: unset;
width: 550rpx;
height: 450rpx;
padding-top: 70rpx;
padding-bottom: 20rpx;
box-sizing: border-box;
}
.slide-image{
height: 300rpx;
width: 450rpx;
border-radius: 10rpx;
margin: 0rpx 50rpx ;
z-index: 1;
box-shadow: 10rpx 5px 40rpx rgba(0, 0, 0,0.5);
}
.active{
transform: scale(1.3);
transition: all .5s ease-in 0s;
z-index: 20;
opacity: 1;
}
.common{
transform: scale(1);
transition: all .5s ease-in 0s;
z-index: 0;
opacity: 0.4;
}
.dots-box{
display: flex;
justify-content: center;
align-items: center;
}
.dots{
width: 30rpx;
height: 6rpx;
margin: 0 4rpx;
background-color: #aaa;
margin-top: -80rpx;
}
.bg-333{
background-color: #333;
}
\ No newline at end of file \ No newline at end of file
// components/echart/basic/index.js
import * as echarts from '../../../ec-canvas/echarts';
import _ from 'underscore';
const chartInstance = {};
Component({
/**
* 组件的属性列表
*/
properties: {
height:{
type:String,
value:'375rpx'
},
chartId:{
type:String,
value:'chart_'+Math.random().toString(16).substr(2,5)
},
chartData:{
type:Object,
value:{},
observer(newVal){
this.setOption(newVal);
}
},
},
lifetimes:{
attached: function() {
this.initEchart();
}
},
/**
* 组件的初始数据
*/
data: {
ecData:{
lazyLoad: true
}
},
/**
* 组件的方法列表
*/
methods: {
initEchart(){
let that = this;
this.selectComponent('#'+this.data.chartId).init((canvas, width, height, dpr) => {
chartInstance[this.data.chartId] = echarts.init(canvas, null, {
width: width,
height: height,
devicePixelRatio: dpr
});
//this.setOption();
// 注意这里一定要返回chart实例,否则会影响时间处理等
return chartInstance[this.data.chartId];
})
},
setOption:function(option = this.data.chartData){
if(chartInstance[this.data.chartId]&&option){
chartInstance[this.data.chartId].clear();
chartInstance[this.data.chartId].setOption(option);
}
}
}
})
{
"component": true,
"usingComponents": {
"ec-canvas": "/ec-canvas/ec-canvas"
}
}
\ No newline at end of file \ No newline at end of file
<!--components/echart/basic/index.wxml-->
<view style="height:{{height}}">
<ec-canvas id="{{chartId}}" canvas-id="{{chartId}}_canvas" ec="{{ ecData }}"></ec-canvas>
</view>
/* components/echart/basic/index.wxss */
\ No newline at end of file \ No newline at end of file
import {
optionFormatter
} from "./dealChart";
module.exports = Behavior({
methods: {
getInstance(){
return this.selectComponent('#basicChart');
},
setEmpty(){
this.initChartData({
otherConf: {}
});
},
/**
* 处理图表参数
* 说明 preChartData:预处理后端的基础数据
* dealChartData:处理成echart直接生成图表的数据
* */
initChartData(cdata) {
let chartData = JSON.parse(JSON.stringify(cdata));
const option = chartData.noProcess ? this.checkOption(chartData) : optionFormatter(chartData);
if (!option) return;
if (option.isEmpty) {
option.xAxis = {
show: false
};
option.yAxis = {
show: false
};
option.grid = {
top: 20,
right: 20,
bottom: 20,
left: 20
};
this.setData({
chartData: option
})
return;
}
option.tooltip = {
show: true,
trigger: 'axis',
padding:[5,15],
position: function(pos, params, dom, rect, size){
let obj={};
if (pos[0] + size.contentSize[0] > size.viewSize[0]){
obj['right'] = size.viewSize[0] - pos[0]
} else {
obj['left'] = pos[0]
}
if(pos[1] + size.contentSize[1] > size.viewSize[1]){
obj['bottom'] = size.viewSize[1] - pos[1]
}else{
obj['top'] = pos[1]
}
return obj;
}
};
this.setData({
chartData: this.dealChartData(option)
})
},
/**
* 自定义处理图表参数
* */
checkOption(chartData) {
if (chartData.series && (chartData.series.length == 0 || (chartData.series[0].data && chartData.series[0].data.length == 0))) {
let nodatatext = '暂无数据';
return {
isEmpty: true,
graphic: [
/*{
type:'image',
left: 'center',
bottom: '51%',
style: {
image: '/static/img/no_data.png',
width: 60,
height: 60,
}
},*/
{
type: 'text',
left: 'center',
top: '52%',
z: 100,
style: {
fill: '#444',
text: nodatatext,
font: '16px "Microsoft YaHei"'
}
}
]
};
}
return chartData;
},
/**
* 获取自定义颜色
* */
getSeriesColor(length) {
return ['#4a90ff', '#55d9a9', '#f7cf98', '#ff9fc2', '#91e7f8', '#fd7041', '#597ef4', '#f8f02d', '#fa2d2e', '#b05cdd', '#ff877e', '#939893'].slice(0,length);
},
}
});
\ No newline at end of file \ No newline at end of file
const legend = {
type: 'scroll',
orient: "horizontal",
x: "center",
itemWidth: 12,
itemHeight: 12,
selected: {},
data: []
}
const xAxis = {
type: 'category',
axisTick: {
show: false
},
axisLabel: {
align: "right",
rotate: 0, // x轴label旋转角度
margin: 5,
color: "rgba(0, 0, 0, 0.45)",
fontFamily: 'GenShinGothic-Monospace-Regular',
fontSize: 11,
lineHeight: 12,
showMinLabel: false,
textStyle: {
color: '#888'
}
},
axisLine: {
show: false,
width: 1,
lineStyle: {
color: '#888'
}
},
axisTick: {
show: false
},
data: []
}
const yAxis = {
type: 'value',
nameTextStyle: {
color: '#444',
fontSize: 10
},
axisTick: {
show: false
},
axisLabel: {
color: "rgba(0, 0, 0, 0.45)",
fontSize: 10,
lineHeight: 11,
margin: 5,
textStyle: {
color: '#888'
}
},
axisLine: {
show: false,
lineStyle: {
color: '#888'
}
},
splitLine: {
show: true,
lineStyle: {
color: '#f5f5f5'
}
}
}
/**
* 格式化 echarts 结构
* @param {object} data
* @return {object}
*/
export function optionFormatter(data) {
let nodatatext = '暂无数据';
let option = {},
emptyOption = {
isEmpty: true,
graphic: [/*{
type:'image',
left: 'center',
bottom: '51%',
style: {
image: '/images/no_data.png',
width: 60,
height: 60,
}
},*/{
type: 'text',
left: 'center',
top: '48%',
z: 100,
style: {
fill: '#444',
text: nodatatext,
font: '13px "Microsoft YaHei"'
}
}],
otherConf: data ? Object.assign({}, data.otherConf || {}) : {}
}
if (!data || !Object.keys(data).length) {
return emptyOption
} else if (!data.series) {
return emptyOption
} else if (!data.series.length) {
return emptyOption
}else if(data.series[0].data&&data.series[0].data.length==0){
return emptyOption
}
option = {
animation: true,
tooltip: {
show: true,
trigger: 'axis',
backgroundColor: '#fff',
textStyle: {
color: '#333'
},
extraCssText: 'box-shadow: 0px 0px 10px -4px rgba(3, 3, 3, .4)'
},
legend: legend,
grid: {},
xAxis: xAxis,
yAxis: data.yaxis || yAxis,
series: []
}
if (typeof(data.title) === 'string') {
option.title = {
text: data.title,
show: false,
textStyle: {
color: '#444',
fontSize: 18,
fontWeight: 'normal',
},
left: 24,
top: 16
}
}
option.color = data.color
// 处理series
// 如果不清除, 页面中有多个同类型报表将叠加
option.legend.data = []
option.xAxis.data = []
data.series.forEach((item, index) => {
if (data.notSale) {
// if(index === 1 && item.name === '销售额') {
// item.yAxisIndex = 1
// }
index === 0 && option.legend.data.push(item.name)
} else {
if (item.name) {
option.legend.data.push({ name: item.name })
}
}
})
if (data.xaxis) {
option.xAxis.data = data.xaxis.data
}
option.series = data.series
// 整合特殊情况配置
/**
* isYear: 是否年报表
* hasYaxisName: 是否显示 y 轴名称
* seriesText: 单位
* isIndependent: 是否单独的排行榜
* selectedLen: legend 选中长度
* hideDataZoom: 是否隐藏缩放轴
* chartKey: 特殊报表处理字段
* grid: 网格配置
* kpiType: 指标值
* normalXAxisLabel: 是否正常显示 x 轴 label
* yAxisName: y 轴名称(计量单位)
* _color: option color
* ...
*/
option.otherConf = Object.assign({}, data.otherConf)
return JSON.parse(JSON.stringify(option))
}
\ No newline at end of file \ No newline at end of file
// components/echart/trend/index.js
const behavior = require('../behavior.js');
import _ from 'underscore';
Component({
/**
* 组件的属性列表
*/
properties: {
chartId:String,
cdata: {
type: Object,
value: {},
observer(newVal) {
this.setChartData(newVal)
}
},
height: {
type: String
},
},
behaviors: [behavior],
/**
* 组件的初始数据
*/
data: {
chartId: 'trend',
avgVal:'',
chartData: {}
},
/**
* 组件的方法列表
*/
methods: {
setChartData(data) {
if(_.isEmpty(data)||!data.series||data.series.length==0){
return this.setEmpty();
}
try {
let avgVal = _.findWhere(data.series, {
name: 'avg'
}).data[0];
data.series = _.filter(data.series, item => item.name != 'avg');
if (avgVal || avgVal == 0) {
avgVal = typeof avgVal == 'string' ? avgVal.replaceAll(/\d+/g, '$&') : `${countVal}个`;
this.setData({
avgVal:parseFloat(avgVal)
})
}
let floorData = JSON.parse(JSON.stringify({
...data,
yaxis: data.xaxis
}));
let maxNum;
if (floorData.series[0].data.length) {
maxNum = (_.max(floorData.series[0].data))*1.25;
let barWidth= '50%';
floorData.series[0].barWidth = barWidth;
floorData.series[1] = {
name: 'background',
type: 'bar',
barWidth:barWidth,
label: {
show: true
},
itemStyle: {
normal: {
barBorderRadius: 0,
color: '#f3f3f4'
}
},
barGap: '-100%',
z: 0,
data: new Array(floorData.series[0].data.length).fill(maxNum)
};
} else {
floorData.series = [];
}
let chartData = Object.assign({}, floorData, {
otherConf: {
_color: ['#5597F7'],
reverseAxis: true,
labelPosition: 'right',
grid: {
top: 40,
right: maxNum>500?0:-25,
bottom: 0,
left: 0
},
showCount: false,
usePercent: true
}
});
this.initChartData(chartData)
} catch (err) {
this.setEmpty()
}
},
dealChartData(optionFormat) {
// 特殊配置项
let {
grid,
_color,
hasYaxisName,
yAxisLineHide,
legendBottom,
seriesText,
yAxisName,
tooltipTitle,
labelShow = false,
labelPosition = '',
hideLoading = false,
reverseAxis = false,
showBackground = false,
usePercent = false,
showCount = true,
rotateVal = 0
} = optionFormat.otherConf;
let currentClickIndex = null
optionFormat.legend.bottom = legendBottom || 0;
optionFormat.legend.itemGap = 65;
optionFormat.legend.show = false;
optionFormat.color = _color; //this.getRandomColors(optionFormat.series.length);
optionFormat.hideLoading = hideLoading;
optionFormat.grid = grid || {
top: 40,
right: hasYaxisName ? 40 : 20,
bottom: 20,
left: 40
};
optionFormat.tooltip.trigger = "axis";
optionFormat.tooltip.axisPointer = {
type: "line",
lineStyle: {
color: "#444"
}
};
optionFormat.tooltip.show = false;
let yAxis = {
type: reverseAxis ? "category" : "value",
// nameRotate: 1,
splitLine: {
lineStyle: {
color: "#f5f5f5"
}
},
axisLine: {
show: !yAxisLineHide,
lineStyle: {
color: "#888"
}
},
axisTick: {
show: false
},
axisLabel: {
fontSize: 12,
fontFamily: this.fontFamily,
color: "#666"
}
};
optionFormat.xAxis.type = reverseAxis ? 'value' : 'category';
optionFormat.xAxis.axisLabel.interval = 0;
optionFormat.xAxis.axisLabel.rotate = rotateVal;
if (hasYaxisName) {
yAxis.name = yAxisName[0];
let yAxis2 = Object.assign({}, yAxis, {
name: yAxisName[1],
position: 'right'
})
optionFormat.yAxis = [yAxis, yAxis2];
} else {
//optionFormat.yAxis = yAxis;
}
if (reverseAxis) {
optionFormat.grid.left = 80;
//optionFormat.tooltip.show = false;
optionFormat.tooltip.axisPointer.type = 'none';
optionFormat.tooltip.axisPointer.show = false;
optionFormat.xAxis.show = false;
optionFormat.yAxis.axisLine = {
show: false
}
optionFormat.yAxis.axisTick = {
show: false
}
} else {
optionFormat.yAxis = yAxis;
}
let totalNum = 0;
optionFormat.series.forEach((item, index) => {
if (usePercent && item.name != "background") {
item.data.forEach(dataItem => {
totalNum += (dataItem instanceof Object ? dataItem.value : dataItem);
});
}
if (reverseAxis) {
item.showBackground = showBackground;
item.label = {
show: index > 0 ? false : true,
fontSize: 12,
//fontWeight:'bold',
position: labelPosition || 'insideRight',
}
} else if (labelShow) {
item.label = {
show: true,
fontSize: 12,
color: '#000',
position: 'top'
}
}
item.label.formatter = function (params) {
if (usePercent) {
let ratio = (params.value / totalNum * 100).toFixed(2) + '%';
if (!showCount) return ratio;
return ratio + (reverseAxis ? '/' : '\n') + params.value + '人次';
}
return params.value + '人次';
}
if (item.type === "line") {
if (hasYaxisName) item.yAxisIndex = 0;
item.symbolSize = 6;
} else if (item.type === "bar") {
if (hasYaxisName) item.yAxisIndex = 1;
}
});
let option = Object.assign({}, optionFormat);
return option;
}
}
})
\ No newline at end of file \ No newline at end of file
{
"component": true,
"usingComponents": {
"basic":"../basic/index"
}
}
\ No newline at end of file \ No newline at end of file
<!--components/echart/trend/index.wxml-->
<view class="cwrap">
<view class="stay" wx:if="{{avgVal}}">人均停留时长<text>{{avgVal}}</text>分</view>
<basic chartId="{{chartId}}" chartData="{{chartData}}" height="{{height}}"></basic>
</view>
/* components/echart/trend/index.wxss */
.cwrap{position: relative;}
.stay{position: absolute;top:20rpx;left:20rpx;font-size: 26rpx;color:#333}
.stay text{color:#5597F7;font-weight: 600;font-size:28rpx;margin:0 5rpx;}
\ No newline at end of file \ No newline at end of file
// components/echart/chart-line/index.js
import * as echarts from '../../../ec-canvas/echarts';
const App = getApp();
let Chart = [];
const optionConfig = {
jtss: {
color: ["#3BB7FF", "#FFC62E", "#CCCCCC"],
legend: {
data: []
}
}
}
function initJtssChart(canvas, width, height, dpr) {
let chart1 = echarts.init(canvas, null, {
width: width,
height: height,
devicePixelRatio: dpr
});
canvas.setChart(chart1);
const option = {
color: optionConfig.jtss.color,
legend: {
data: [
{
name: '当日',
icon: 'line'
},
{
name: '昨日',
icon: 'line'
},
{
name: '上周',
icon: 'line'
}
],
top: 0,
right: 0,
z: 100,
itemHeight: 2,
itemWidth: 10,
textStyle: {
fontSize: 11,
fontWeight: 400,
color: "#8C8C8C"
},
},
grid: {
right: 10,
left: 10,
top: 30,
borderColor: "transparent",
bottom: 0,
containLabel: true,
},
tooltip: {
show: true,
trigger: 'axis'
},
xAxis: {
type: 'category',
boundaryGap: false,
data: ["10:00", "11:00", "12:00", "13:00", "14:00", "16:00", "17:00", "18:00", "19:00"],
axisLine: {
width: 1,
lineStyle: {
color: "#EEEEEE",
}
},
axisTick: {
show: false,
},
axisLabel: {
align: "right",
rotate: 0, // x轴label旋转角度
margin: 10,
color: "rgba(0, 0, 0, 0.45)",
fontFamily: 'GenShinGothic-Monospace-Regular',
fontSize: 11,
lineHeight: 12
},
},
yAxis: {
type: 'value',
splitLine: {
show: false
},
axisTick: {
show: false,
},
axisLine: {
show: false,
},
axisLabel: {
color: "rgba(0, 0, 0, 0.45)",
fontSize: 11,
lineHeight: 11,
margin: 10
},
},
series: [
{
name: '当日',
type: 'line',
smooth: true,
data: [18, 36, 65, 30, 78, 40, 33, 30, 78]
},
{
name: '昨日',
type: 'line',
smooth: true,
data: [12, 50, 51, 35, 70, 30, 20, 35, 70]
},
{
name: '上周',
type: 'line',
smooth: true,
data: [12, 5, 1, 3, 7, 3, 2, 3, 70]
}
]
};
chart1.setOption(option);
return chart1;
}
Component({
options: {
addGlobalClass: true,
},
/**
* 组件的属性列表
*/
properties: {
echartInfo: Object,
keyArr: Object,
reportType: String
},
/**
* 组件的初始数据
*/
data: {
ranks: [
{
title: '小米延庆区环球新意授权体验店',
value: 6292,
}
],
isShoweyes: true,
turnoverEc: {
lazyLoad: true
},
echartsData: {}
},
lifetimes: {
attached() {
this.echartsComponnet1 = this.selectComponent('#jtsskl-dom-line');
},
detached() {
// 在组件实例被从页面节点树移除时执行
},
ready() {
Chart = []; // 重置图表存储容器,不然会报错
this.getData(); // 获取数据
}
},
/**
* 组件的方法列表
*/
methods: {
getData() {
const { reportType } = this.data
getIndexInfo(`/report/report/${reportType}/account/body`, data).then(res => {
let body = res.data
})
// const { data, keyArr, reportType } = this.data
// console.log(this.data)
// this.setData({
// echartsData: data
// }, () => {
for (let i = 1; i < 2; i++) {
if (!Chart[i]) {
this.initEcharts(i); // 初始化图表
} else {
this.setOption(i); // 更新数据
}
}
// })
},
// 初始化图表
initEcharts: function(i) {
this['echartsComponnet' + i].init((canvas, width, height, dpr) => {
Chart[i - 1] = echarts.init(canvas, null, {
width: width,
height: height,
devicePixelRatio: dpr
});
this.setOption(i);
// 注意这里一定要返回chart实例,否则会影响时间处理等
return Chart[i - 1]
})
},
setOption: function(i) {
Chart[i - 1].clear(); // 清除
Chart[i - 1].setOption(this['getOption' + i]()); //获取新数据
},
getOption1() {
let { echartsData } = this.data
console.log(echartsData)
return {
color: optionConfig.jtss.color,
legend: {
data: [
{
name: '当日',
icon: 'line'
},
{
name: '昨日',
icon: 'line'
},
{
name: '上周',
icon: 'line'
}
],
top: 0,
right: 0,
z: 100,
itemHeight: 2,
itemWidth: 10,
textStyle: {
fontSize: 11,
fontWeight: 400,
color: "#8C8C8C"
},
},
grid: {
right: 10,
left: 10,
top: 30,
borderColor: "transparent",
bottom: 0,
containLabel: true,
},
tooltip: {
show: true,
trigger: 'axis'
},
xAxis: {
type: 'category',
boundaryGap: false,
data: ["10:00", "11:00", "12:00", "13:00", "14:00", "16:00", "17:00", "18:00", "19:00"],
axisLine: {
width: 1,
lineStyle: {
color: "#EEEEEE",
}
},
axisTick: {
show: false,
},
axisLabel: {
align: "right",
rotate: 0, // x轴label旋转角度
margin: 10,
color: "rgba(0, 0, 0, 0.45)",
fontFamily: 'GenShinGothic-Monospace-Regular',
fontSize: 11,
lineHeight: 12
},
},
yAxis: {
type: 'value',
splitLine: {
show: false
},
axisTick: {
show: false,
},
axisLine: {
show: false,
},
axisLabel: {
color: "rgba(0, 0, 0, 0.45)",
fontSize: 11,
lineHeight: 11,
margin: 10
},
},
series: [
{
name: '当日',
type: 'line',
smooth: true,
data: [18, 36, 65, 30, 78, 40, 33, 30, 78]
},
{
name: '昨日',
type: 'line',
smooth: true,
data: [12, 50, 51, 35, 70, 30, 20, 35, 70]
},
{
name: '上周',
type: 'line',
smooth: true,
data: [12, 5, 1, 3, 7, 3, 2, 3, 70]
}
]
}
}
// initJtljChart: function(canvas, width, height, dpr) {
// const chart = echarts.init(canvas, null, {
// width: width,
// height: height,
// devicePixelRatio: dpr // new
// });
// canvas.setChart(chart);
// const option = {
// color: ["#3BB7FF", "#FFC62E", "#CCCCCC"],
// legend: {
// data: [
// {
// name: '当日',
// icon: 'line'
// },
// {
// name: '昨日',
// icon: 'line'
// },
// {
// name: '上周',
// icon: 'line'
// }
// ],
// top: 0,
// right: 0,
// z: 100,
// itemHeight: 2,
// itemWidth: 10,
// textStyle: {
// fontSize: 11,
// fontWeight: 400,
// color: "#8C8C8C"
// },
// },
// grid: {
// right: 10,
// left: 10,
// top: 30,
// borderColor: "transparent",
// bottom: 0,
// containLabel: true,
// },
// tooltip: {
// show: true,
// trigger: 'axis'
// },
// xAxis: {
// type: 'category',
// boundaryGap: false,
// data: ["10:00", "11:00", "12:00", "13:00", "14:00", "16:00", "17:00", "18:00", "19:00"],
// axisLine: {
// width: 1,
// lineStyle: {
// color: "#EEEEEE",
// }
// },
// axisTick: {
// show: false,
// },
// axisLabel: {
// align: "right",
// rotate: 0, // x轴label旋转角度
// margin: 10,
// color: "rgba(0, 0, 0, 0.45)",
// fontFamily: 'GenShinGothic-Monospace-Regular',
// fontSize: 11,
// lineHeight: 12
// },
// },
// yAxis: {
// type: 'value',
// splitLine: {
// show: false
// },
// axisTick: {
// show: false,
// },
// axisLine: {
// show: false,
// },
// axisLabel: {
// color: "rgba(0, 0, 0, 0.45)",
// fontSize: 11,
// lineHeight: 11,
// margin: 10
// },
// },
// series: [
// {
// name: '当日',
// type: 'line',
// smooth: true,
// data: [18, 36, 65, 30, 78, 40, 33, 30, 78]
// },
// {
// name: '昨日',
// type: 'line',
// smooth: true,
// data: [12, 50, 51, 35, 70, 30, 20, 35, 70]
// },
// {
// name: '上周',
// type: 'line',
// smooth: true,
// data: [12, 5, 1, 3, 7, 3, 2, 3, 70]
// }
// ]
// };
// chart.setOption(option);
// return chart;
// },
},
})
{
"component": true,
"usingComponents": {
"ec-canvas": "../../../ec-canvas/ec-canvas"
}
}
\ No newline at end of file \ No newline at end of file
<!--components/echart/chart-line/index.wxml-->
<view class="echart-content">
<view class="echart-item">
<view class="echart-item-title">集团实时客流</view>
<view class="echart-item-content" hidden="{{!isShoweyes}}">
<ec-canvas id="jtsskl-dom-line" canvas-id="jtsskl-line" ec="{{ turnoverEc }}"></ec-canvas>
</view>
</view>
<view class="echart-item">
<view class="echart-item-title">集团累计客流</view>
<view class="echart-item-content">
<ec-canvas id="jtljkl-dom-line" canvas-id="jtljkl-line" ec="{{ ec1 }}"></ec-canvas>
</view>
</view>
<view class="echart-item" style="max-height: 453px">
<view class="echart-item-title">全国门店排名</view>
<view class="echart-item-content">
</view>
</view>
</view>
.echart-content {
width: 100%;
height: 100%;
}
.echart-item {
width: 100%;
border-radius: 7px;
background-color: #fff;
box-shadow: 0px 2px 4px 0px rgba(118, 118, 118, 0.24);
box-sizing: border-box;
padding: 12px;
height: 219px;
margin-bottom: 15px;
}
.echart-item .echart-item-title {
font-size: 14px;
font-family: MicrosoftYaHeiUI;
color: #000000;
line-height: 19px;
}
.echart-item .echart-item-content {
width: 100%;
height: calc(100% - 19px);
}
ec-canvas {
width: 100%;
height: 100%;
}
\ No newline at end of file \ No newline at end of file
// components/echart/ranking/index.js
import _ from 'underscore';
const customBehavior = require('../../../extends/custom.behavior.js');
Component({
behaviors:[customBehavior],
/**
* 组件的属性列表
*/
properties: {
customClass:String,
cdata: {
type: Object,
value: {},
observer(newVal) {
if(newVal&&!_.isEmpty(newVal))this.setChartData(newVal)
}
}
},
/**
* 组件的初始数据
*/
data: {
chartData: [],
tabKey:'',
postfix:''
},
/**
* 组件的方法列表
*/
methods: {
getTime(seconds){
if(isNaN(seconds))return seconds;
return parseInt(seconds/3600)+'时'+parseInt(seconds%3600/60)+'分'+(seconds%60)+'秒';
},
setChartData(tabData) {
let tabKey = tabData.key;
let chartData = this.buildTableContent(tabData);
let maxVal = Math.max(..._.without(_.pluck(chartData,tabKey),'--'));
chartData = _.map(chartData,item=>{
let kVal = item[tabKey]!='--'?item[tabKey]:0;
item.percentage = parseInt(kVal*100/maxVal);
if(tabKey.includes('_time')){
item[tabKey] = isNaN(item[tabKey])?'--':parseInt(item[tabKey]/60)+'分';
}
return item;
})
let postfix = '';
if(tabKey.includes('_rate')){
postfix = '%';
}
// if(tabKey.includes('_time')){
// postfix = '分';
// }
this.setData({
chartData,
postfix,
tabKey
})
},
}
})
\ No newline at end of file \ No newline at end of file
{
"component": true,
"usingComponents": {
"van-progress": "@vant/weapp/progress/index"
}
}
\ No newline at end of file \ No newline at end of file
<!--components/echart/ranking/index.wxml-->
<view class="lwraper {{customClass}}">
<view class="list">
<view class="item" wx:for="{{chartData}}" wx:key="index">
<view class="info">
<view class="name ~ellipsis">
<text class="idx color">{{item.defaultOrg0}}</text>
{{item.defaultOrg1}}
</view>
<view class="num color">
{{item[tabKey]}}{{postfix}}
</view>
</view>
<view class="progress">
<view class="bar">
<van-progress show-pivot="{{false}}" color="{{(index==0?'#FA6400':index==1?'#F7B500':index==2?'#44D7B6':'#1972F5')}}"percentage="{{item.percentage}}" stroke-width="4" />
</view>
</view>
</view>
</view>
</view>
\ No newline at end of file \ No newline at end of file
/* components/echart/ranking/index.wxss */
.lwraper{
padding:0rpx 20rpx 20rpx;
}
.list{
position: relative;
padding-top:20rpx ;
}
.list .item{
position: relative;
padding:10rpx 0;
border-bottom: 1rpx solid #fafafa;
}
.list .item .info{
display: flex;
justify-content: space-between;
}
.list .item .name{
color:#6d6d6d;
font-size: 28rpx;
}
.list .item .name .idx{
font-weight: 600;
margin-right: 5rpx;
}
.list .item:nth-child(1) .color{
color:#FA6400
}
.list .item:nth-child(2) .color{
color:#F7B500
}
.list .item:nth-child(3) .color{
color:#44D7B6
}
.no_rank .list .item .name .idx{
color:#6d6d6d!important;
}
.list .item .progress{
padding:10rpx 0rpx;
display: flex;
align-items: center;
}
.list .item .progress .bar{
width: 100%;
position: relative;
}
.list .item .num{
color:#636161;
width:100rpx;
text-align: right;
font-size: 30rpx;
font-weight: 600;
}
// components/echart/trend/index.js
const behavior = require('../behavior.js');
import _ from 'underscore';
Component({
/**
* 组件的属性列表
*/
properties: {
chartId:String,
cdata: {
type: Object,
value: {},
observer(newVal) {
this.initChartData(newVal)
}
},
height: {
type: String
}
},
behaviors: [behavior],
/**
* 组件的初始数据
*/
data: {
chartData: {}
},
/**
* 组件的方法列表
*/
methods: {
dealChartData(optionFormat) {
let {
normalXAxisLabel,
grid,
hasBoundaryGap = false,
_color,
isYear,
perUnit = '人次',
doubleYaxis = false,
showLineArea = true,
periodTime,
nextTimeNum,
legendShow,
legendBottom,
seriesText,
oriData,
calcPercent
} = optionFormat.otherConf;
optionFormat.legend.show = legendShow || false;
let _colors = _color || this.getSeriesColor(optionFormat.series.length);
let areaColor = _colors.map(item => {
return {
type: "linear",
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0,
color: item // 0% 处的颜色
},
{
offset: 1,
color: "#fff" // 100% 处的颜色
}
]
};
});
let _grid = {
top: 20,
right: 0,
bottom: 20,
left: 32
};
// 覆盖格式化后的`option`数据 按需修改
let coverTemp = {
color: _colors, // ["#87D14B", "#3BB8FF", "#FFC62E", "#FF9631", "#7460EE"]
grid: grid || _grid
};
if (doubleYaxis) {
optionFormat.yAxis.name = this.$t('format.perTime');
optionFormat.yAxis = [JSON.parse(JSON.stringify(optionFormat.yAxis)), JSON.parse(JSON.stringify(optionFormat.yAxis))]
optionFormat.yAxis[1].name = '增长率%';
optionFormat.yAxis[1].nameLocation = 'end';
} else /* if(optionFormat.series.length==1)*/ {
//optionFormat.yAxis.name = perUnit;
optionFormat.yAxis.nameLocation = 'end';
}
if (!showLineArea) {
optionFormat.yAxis.axisLine.show = false;
}
optionFormat.series = _.filter(optionFormat.series,item=>{
return item.name!='天气'&&item.name!='温度'
})
optionFormat.series.forEach((item, index) => {
if (item.type === "bar") {
if (item.data.length < 20) item.barWidth = 50;
} else {
if (showLineArea) {
item.showSymbol = true;
item.symbolSize = 4;
item.areaStyle = {
normal: {
color: areaColor[index]
}
};
} else {
item.showSymbol = true;
item.symbol = 'circle';
item.symbolSize = 6;
}
if (doubleYaxis) {
item.yAxisIndex = 1;
item.areaStyle.normal.opacity = 0;
}
item.smooth = true;
}
});
optionFormat.xAxis.boundaryGap = hasBoundaryGap;
//optionFormat.xAxis.axisLabel.interval = optionFormat.series[0].length>30?'auto':0;
optionFormat.legend.bottom = legendBottom || 0;
let option = Object.assign({}, optionFormat, coverTemp);
return option;
}
}
})
\ No newline at end of file \ No newline at end of file
{
"component": true,
"usingComponents": {
"basic":"../basic/index"
}
}
\ No newline at end of file \ No newline at end of file
<!--components/echart/trend/index.wxml-->
<basic chartId="{{chartId}}" chartData="{{chartData}}" height="{{height}}"></basic>
/* components/echart/trend/index.wxss */
\ No newline at end of file \ No newline at end of file
// components/zone-picker/index.js
Component({
/**
* 组件的属性列表
*/
properties: {
icon: Boolean
},
/**
* 组件的初始数据
*/
data: {
pickerIndex: 0,
pickerArray: []
},
lifetimes: {
attached() {
// 在组件实例进入页面节点树时执行
},
detached() {
// 在组件实例被从页面节点树移除时执行
},
ready() {
const accountList = wx.getStorageSync('accountList');
if (accountList) {
const aclist = JSON.parse(accountList)
aclist.unshift({ id: null, name: '全部' })
this.setData({ pickerArray: aclist })
}
}
},
/**
* 组件的方法列表
*/
methods: {
// 确认
pickerChange: function (e) {
const { pickerArray } = this.data
this.triggerEvent('onZonePickerCallback', pickerArray[e.detail.value])
},
pickerColumnChange: function (e) {
},
pickerCancel: function (e) {
}
}
})
{
"component": true,
"usingComponents": {}
}
\ No newline at end of file \ No newline at end of file
<view>
<picker
mode="selector"
bindchange="pickerChange"
bindcolumnchange="pickerColumnChange"
bindcancel="pickerCancel"
value="{{pickerIndex}}"
range="{{pickerArray}}"
range-key="{{'name'}}"
>
<view>
<image wx:if="{{icon}}" src="../../images/arrow-r.png" mode="aspecFill"
style="width: 36rpx; height: 36rpx;margin-top: 12rpx"></image>
<image wx:if="{{!icon}}" src="../../images/home/md.png" mode="aspecFill" class="md" />
</view>
</picker>
</view>
\ No newline at end of file \ No newline at end of file
.md {
width: 34rpx;
height: 30rpx;
margin-right: 26rpx;
}
\ No newline at end of file \ No newline at end of file
import {
getMalls,
} from "../../api/login";
import {
getPatrolGateList
} from "../../api/tour.js";
import _ from 'underscore';
Component({
/**
* 组件的属性列表
*/
properties: {
},
/**
* 组件的初始数据
*/
data: {
mallList: [],
activeMall: [],
gateId:'',
navHeight: getApp().globalData.navHeight
},
ready() {
this.getMalls()
},
/**
* 组件的方法列表
*/
methods: {
onChange(evt){
this.setData({
activeMall:evt.detail
},()=>{
this.loadGates(evt.detail[evt.detail.length-1]);
})
},
loadGates(mallId){
getPatrolGateList({mallId}).then(res=>{
let mallObj = _.findWhere(this.data.mallList,{id:mallId});
if(!res.data||!res.data.list){
mallObj.empty = true;
//this.triggerEvent('gateChange',{});
}else{
mallObj.gates = res.data.list;
let gateObj = res.data.list[0];
//this.triggerEvent('gateChange',{id:gateObj.id,name:gateObj.name,mallId:gateObj.mallId});
}
this.setData({
mallList:this.data.mallList
},()=>{
})
})
},
backBtn() {
this.triggerEvent('back');
},
// 获取门店列表
getMalls: function () {
const {
accountId,
atoken
} = this.data
getMalls({
url: '/report/malls',
accountId: wx.getStorageSync('accountId')
}).then((malls) => {
const data = malls.data;
this.setData({
mallList: data
},()=>{
let mallId = wx.getStorageSync('mallId');
if(!mallId){
mallId = data[0].id;
wx.setStorageSync('mallId', mallId);
}
this.onChange({detail:[mallId]});
});
})
},
selectGate(evt){
let {id,name,mallId} = evt.currentTarget.dataset;
this.setData({
gateId:id
},()=>{
this.triggerEvent('gateChange',{id,name,mallId});
})
}
}
});
\ No newline at end of file \ No newline at end of file
{
"component": true,
"usingComponents": {
}
}
\ No newline at end of file \ No newline at end of file
<view class="malllist" style="padding-top: {{navHeight}}px;">
<navbar2>
<view class="navtit">
<van-icon bindtap="backBtn" name="arrow-left" custom-class="back"/>
选择监控点
<view></view>
</view>
</navbar2>
<scroll-view scroll-y class="list">
<van-collapse value="{{ activeMall }}" bind:change="onChange">
<van-collapse-item custom-class="item" content-class="gcont" wx:for="{{mallList}}" wx:key="index" title="{{item.name}}" name="{{item.id}}" is-link="{{true}}">
<view style="text-align: center;" wx:if="{{item.empty}}">暂无监控点</view>
<van-cell data-id="{{item.id}}" data-name="{{item.name}}" data-mallId="{{item.mallId}}" bindtap="selectGate" wx:for="{{item.gates}}" wx:key="index" title="{{item.name}}">
<van-icon name="success" wx:if="{{gateId==item.id}}" color="#1267E0" size="20"/>
</van-cell>
</van-collapse-item>
</van-collapse>
</scroll-view>
</view>
\ No newline at end of file \ No newline at end of file
.malllist{
position: absolute;
top:0;
left:0;
width: 100%;
height: 100%;
}
.list{
position: relative;
width: 100%;
height: 100%;
background-color: #f3f9ff;
}
.navtit{background:#fff;position: relative;padding-left: 20rpx;padding-right: 20rpx;display: flex;justify-content: space-between;}
.list .item{--cell-background-color: #efeff4;border-bottom: 1px solid rgba(0,0,0,0.1);}
.list .gcont{--cell-background-color: #fff;--cell-horizontal-padding:20px;}
\ No newline at end of file \ No newline at end of file
import {
getMalls,
} from "../../api/login";
Component({
/**
* 组件的属性列表
*/
properties: {
all:{
type:Boolean,
value:false
}
},
/**
* 组件的初始数据
*/
data: {
mallList: [],
navHeight: getApp().globalData.navHeight
},
ready() {
this.getMalls()
},
/**
* 组件的方法列表
*/
methods: {
backBtn() {
this.triggerEvent('back');
},
// 获取门店列表
getMalls: function () {
const {
accountId,
atoken
} = this.data
getMalls({
url: '/report/malls',
accountId: wx.getStorageSync('accountId')
}).then((malls) => {
const data = malls.data;
if(this.data.all){
data.unshift({
id:0,
name:'全部门店'
})
}
this.setData({
mallList: data
});
if (data.length == 1) {
this.triggerEvent('mallLoad', data);
wx.setStorageSync('isMall', true);
} else {
this.triggerEvent('mallLoad', data);
wx.setStorageSync('isMall', false);
data.unshift({
id: null,
name: '全部'
})
}
})
},
selectZone(evt){
let {id,name} = evt.currentTarget.dataset;
this.triggerEvent('mallChange',{id,name});
}
}
})
\ No newline at end of file \ No newline at end of file
{
"component": true,
"usingComponents": {
"navbar2": "/components/navbar2/index",
"van-cell": "@vant/weapp/cell/index"
}
}
\ No newline at end of file \ No newline at end of file
<view class="malllist" style="padding-top: {{navHeight}}px;">
<navbar2>
<view class="navtit">
<van-icon bindtap="backBtn" name="arrow-left" custom-class="back"/>
选择门店
<view></view>
</view>
</navbar2>
<scroll-view scroll-y class="list">
<van-cell data-id="{{item.id}}" data-name="{{item.name}}" bindtap="selectZone" custom-class="item" wx:for="{{mallList}}" wx:key="index" title="{{item.name}}" is-link />
</scroll-view>
</view>
\ No newline at end of file \ No newline at end of file
.malllist{
position: absolute;
top:0;
left:0;
width: 100%;
height: 100%;
}
.list{
position: relative;
width: 100%;
height: 100%;
background-color: #f3f9ff;
}
.list .item{
margin: 20rpx 0;
--cell-font-size:32rpx;
}
.navtit{background:#fff;position: relative;padding-left: 20rpx;padding-right: 20rpx;display: flex;justify-content: space-between;}
\ No newline at end of file \ No newline at end of file
// components/modal/index.js
Component({
/**
* 组件的属性列表
*/
properties: {
},
/**
* 组件的初始数据
*/
data: {
deploymentType: '',
baseUrl: '',
items: [
{
value: 'store',
label: '智慧零售'
}
]
},
lifetimes: {
attached: function() {
const { items } = this.data
const wechat = wx.getStorageSync('wechat')
if (!wechat) {
items.push(
{
value: 'private',
label: '私有平台'
}
)
}
this.setData({
deploymentType: wx.getStorageSync('deploymentType'),
baseUrl: wx.getStorageSync('baseUrl'),
items
})
}
},
/**
* 组件的方法列表
*/
methods: {
changeType: function(e) {
const { item } = e.currentTarget.dataset;
this.setData({ deploymentType: item.value })
this.triggerEvent('changeType', item.value)
},
changeBaseUrl: function(value, cursor, keyCode) {
this.setData({
baseUrl: value.detail.value
})
wx.setStorage({
data: value.detail.value,
key: 'baseUrl'
})
},
hideModal: function() {
this.triggerEvent('hideModal')
}
}
})
{
"component": true,
"usingComponents": {}
}
\ No newline at end of file \ No newline at end of file
<view class="modal">
<view class="modal-content">
<view class="radio-type" wx:key="index" wx:for-item="actionItem" wx:for-index="index" wx:for="{{items}}" style="background-color: {{ deploymentType === actionItem.value ? '#3BB7FF' : '#fff' }}" bindtap="changeType" data-item="{{ actionItem }}">
<view class="yuan" style="border: {{ deploymentType === actionItem.value ? '2rpx solid #fff' : '2rpx solid #3BB7FF' }}">
<view class="yuan-n"></view>
</view>
<view style="color: {{ deploymentType === actionItem.value ? '#fff' : '#3BB7FF' }}">{{ actionItem.label }}</view>
</view>
<input wx:if="{{ deploymentType === 'private' }}" placeholder="输入私有部署地址" class="modal-input" value="{{ baseUrl }}" bindinput="changeBaseUrl" placeholder-style="color: rgba(0, 0, 0, 0.25)" />
<view class="modal-button">
<button class="modal-submit" disabled="{{ (deploymentType === 'private' && baseUrl === '') || deploymentType === '' }}" bindtap="hideModal">确认</button>
</view>
</view>
</view>
\ No newline at end of file \ No newline at end of file
.modal {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.4);
z-index: 999;
display: flex;
align-items: center;
justify-content: center;
}
.modal .modal-content {
width: calc(100% - 84rpx);
height: 640rpx;
background-color: #fff;
border-radius: 24rpx;
box-sizing: border-box;
padding: 66rpx 60rpx 40rpx 60rpx;
position: relative;
}
.modal .modal-content .radio-type {
width: 100%;
height: 72rpx;
border-radius: 36rpx;
border: 2rpx solid #3BB7FF;
margin-bottom: 60rpx;
display: flex;
align-items: center;
box-sizing: border-box;
position: relative;
justify-content: center;
font-size: 32rpx;
}
.modal .modal-content .radio-type .yuan {
width: 32rpx;
height: 32rpx;
border-radius: 32rpx;
display: flex;
align-items: center;
justify-content: center;
position: absolute;
left: 26rpx;
top: 16rpx;
}
.modal .modal-content .radio-type .yuan .yuan-n {
width: 16rpx;
height: 16rpx;
border-radius: 16rpx;
background-color: #fff;
}
.modal-input {
width: 100%;
height: 64rpx;
border-radius: 4rpx;
border: 2rpx solid #F0F0F3;
margin-top: 40rpx;
box-sizing: border-box;
padding: 10rpx 24rpx;
font-size: 28rpx;
}
.modal-button {
width: 100%;
height: 80rpx;
box-sizing: border-box;
padding: 0rpx 30rpx;
position: absolute;
left: 0rpx;
bottom: 40rpx;
}
.modal-button .modal-submit {
width: 100%;
height: 100%;
background: linear-gradient(121deg, #30D2FF 0%, #0069FF 100%);
box-shadow: 0rpx 6rpx 10rpx 0rpx #468FFF;
border-radius: 80rpx;
font-size: 32rpx;
color: #fff;
}
\ No newline at end of file \ No newline at end of file
const App = getApp();
Component({
options: {
addGlobalClass: true,
},
/**
* 组件的属性列表
*/
properties: {
pageName:String,
bgColor: String,
navbarColor: String,
nav: String,
backIcon: String
},
/**
* 组件的初始数据
*/
data: {
isBlack:false
},
lifetimes: {
attached: function () {
this.setData({
navH: App.globalData.navHeight,
windowWidth: App.globalData.windowWidth,
navTop: App.globalData.navTop,
isBlack:this.data.navbarColor.includes('fff')?true:false
})
}
},
/**
* 组件的方法列表
*/
methods: {
//回退
navBack: function () {
wx.navigateBack({
delta: 1
})
},
//回主页
toIndex: function () {
wx.navigateTo({
url: '/pages/admin/home/index/index'
})
},
goback: function() {
this.triggerEvent('onGoBack')
},
}
})
\ No newline at end of file \ No newline at end of file
{
"component": true,
"usingComponents": {
}
}
\ No newline at end of file \ No newline at end of file
<view
class="navbar custom-class"
style='height:{{navH}}px;background-color:{{bgColor}};width:{{windowWidth}}px'
>
<view wx:if="{{ nav === 'home' }}" class='navbar-home-title' style='top:{{navTop}}px;width:{{windowWidth/2}}px'>
{{pageName}}
</view>
<view wx:if="{{ nav === 'back' }}" class="back" style='top:{{navTop}}px;' bindtap="goback">
<image src="../../images/arrow{{isBlack?1:''}}.png"></image>
<view class='navbar-home-title1 ~max-width' style='color:{{navbarColor}}'>
{{pageName}}
</view>
</view>
<view wx:if="{{ !nav }}" class='navbar-title' style='top:{{navTop}}px;color:{{navbarColor}}'>
{{pageName}}
</view>
</view>
\ No newline at end of file \ No newline at end of file
.navbar {
width: 100%;
overflow: hidden;
position: fixed;
top: 0;
left: 0;
z-index: 10;
flex-shrink: 0;
}
.navbar-home-title {
font-size: 40rpx;
color: #fff;
position: absolute;
left: 46rpx;
z-index: 10;
overflow: hidden;
}
.navbar-home-title1 {
font-size: 40rpx;
color: #fff;
margin-left: 20rpx;
}
.navbar-title {
width: 100%;
box-sizing: border-box;
padding-left: 80px;
padding-right: 90px;
height: 32px;
line-height: 32px;
text-align: center;
position: absolute;
left: 0;
z-index: 10;
color: #333;
font-size: 20px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.navbar-title1 {
height: 32px;
line-height: 32px;
text-align: center;
position: absolute;
left: 0;
z-index: 10;
color: #333;
font-size: 20px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.home-icon {
display: flex;
margin-top: 16rpx;
}
.navbar-action-wrap {
display: -webkit-flex;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
-webkit-align-items: center;
align-items: center;
position: absolute;
right: 190rpx;
z-index: 11;
line-height: 1;
}
.navbar-action_item {
padding: 3px 0;
color: #333;
}
.navbar-action-group .navbar-action_item {
border-right: 1px solid #f0f0f0;
padding: 3px 14px;
}
.navbar-action-group .last {
border-right: none;
}
.home-left-icon {
display: flex;
margin-top: 7px;
}
.home-left-icon .item {
font-size: 12px;
margin-right: 10px;
}
.back {
position: absolute;
left: 35rpx;
z-index: 999;
display: flex;
align-items: center;
}
.back image {
width: 36rpx;
height: 36rpx;
}
\ No newline at end of file \ No newline at end of file
const App = getApp();
Component({
options: {
addGlobalClass: true,
//multipleSlots: true
},
/**
* 组件的属性列表
*/
properties: {
pageName:String,
bgColor: String,
navbarColor: String,
nav: String,
backIcon: String
},
/**
* 组件的初始数据
*/
data: {
isBlack:false
},
lifetimes: {
attached: function () {
this.setData({
navH: App.globalData.navHeight,
windowWidth: App.globalData.windowWidth,
navTop: App.globalData.navTop,
isBlack:this.data.navbarColor.includes('fff')?true:false
})
}
},
/**
* 组件的方法列表
*/
methods: {
//回退
navBack: function () {
wx.navigateBack({
delta: 1
})
},
//回主页
toIndex: function () {
wx.navigateTo({
url: '/pages/admin/home/index/index'
})
},
goback: function() {
this.triggerEvent('onGoBack')
},
}
})
\ No newline at end of file \ No newline at end of file
{
"component": true,
"usingComponents": {
}
}
\ No newline at end of file \ No newline at end of file
<view class="navbar" style='color:{{navbarColor}};height:{{navH}}px;background-color:{{bgColor}};width:{{windowWidth}}px'>
<view class="nav-content" style='top:{{navTop}}px;'>
<slot></slot>
</view>
</view>
\ No newline at end of file \ No newline at end of file
.navbar{
width: 100%;
overflow: hidden;
position: fixed;
top: 0;
left: 0;
z-index: 10;
flex-shrink: 0;
}
.navbar .nav-content{
width: 100%;
box-sizing: border-box;
height: 32px;
line-height: 32px;
text-align: center;
position: absolute;
left: 0;
z-index: 10;
color: #333;
font-size: 20px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
\ No newline at end of file \ No newline at end of file
{
"component": true,
"usingComponents": {}
}
\ No newline at end of file \ No newline at end of file
<view>
<picker
disabled="{{disabled}}"
mode="multiSelector"
bindchange="pickerChange"
bindcolumnchange="pickerColumnChange"
bindcancel="pickerCancel"
value="{{pickerIndex}}"
range="{{pickerArray}}"
range-key="{{'name'}}"
>
<view class="tview">
{{dateStr}}
<image wx:if="{{icon}}" class="arrow" src="../../images/arrow-r.png" mode="aspecFill"
style=""></image>
<image wx:if="{{!icon}}" src="../../images/home/date.png" mode="aspecFill" class="date" />
</view>
</picker>
</view>
\ No newline at end of file \ No newline at end of file
.input_base {
border: 2rpx solid #ccc;
padding-left: 10rpx;
margin-right: 50rpx;
}
.input_h30 {
height: 30px;
line-height: 30px;
}
.col-1 {
-webkit-box-flex: 1;
box-flex: 1;
}
.date {
width: 34rpx;
height: 32rpx;
margin-right: 20rpx;
}
.arrow{
width: 36rpx; height: 36rpx;margin-top: 12rpx
}
.tview{font-size: 36rpx;}
\ No newline at end of file \ No newline at end of file
// components/zone-picker/index.js
import {
getMalls,
} from "../../api/login";
Component({
/**
* 组件的属性列表
*/
properties: {
icon: Boolean,
hidden:Boolean
},
/**
* 组件的初始数据
*/
data: {
pickerIndex: 0,
pickerArray: [],
accountId: '',
atoken: ''
},
lifetimes: {
attached() {
// 在组件实例进入页面节点树时执行
},
detached() {
// 在组件实例被从页面节点树移除时执行
},
ready() {
const accountId = wx.getStorageSync('accountId');
const atoken = wx.getStorageSync('atoken');
this.setData({ accountId, atoken }, () => {
this.getMalls()
})
}
},
/**
* 组件的方法列表
*/
methods: {
// 确认
pickerChange: function (e) {
const { pickerArray } = this.data
this.triggerEvent('onZonePickerCallback', pickerArray[e.detail.value])
},
// 获取门店列表
getMalls: function() {
const { accountId, atoken } = this.data
getMalls({
url: '/report/malls',
accountId: accountId,
header: { 'Authorization': atoken }
}).then((malls) => {
const data = malls.data;
if(data.length==1){
this.triggerEvent('mallLoad',data);
}else{
this.triggerEvent('mallLoad',data);
data.unshift({ id: null, name: '全部' })
}
this.setData({ pickerArray: data })
})
},
pickerColumnChange: function (e) {
},
pickerCancel: function (e) {
}
}
})
{
"component": true,
"usingComponents": {}
}
\ No newline at end of file \ No newline at end of file
<view hidden="{{hidden}}">
<picker
mode="selector"
bindchange="pickerChange"
bindcolumnchange="pickerColumnChange"
bindcancel="pickerCancel"
value="{{pickerIndex}}"
range="{{pickerArray}}"
range-key="{{'name'}}"
>
<view>
<image wx:if="{{icon}}" src="../../images/arrow-r.png" mode="aspecFill"
style="width: 36rpx; height: 36rpx;margin-top: 12rpx"></image>
<image wx:if="{{!icon}}" src="../../images/home/md.png" mode="aspecFill" class="md" />
</view>
</picker>
</view>
\ No newline at end of file \ No newline at end of file
.md {
width: 34rpx;
height: 30rpx;
margin-right: 26rpx;
}
\ No newline at end of file \ No newline at end of file
module.exports = {
//ajaxUrl:'https://mall.keliuyun.com',
ajaxUrl:'http://192.168.1.106:81',
//ajaxUrl:'https://applet.keliuyun.com:17072',
picUrl:'https://store.keliuyun.com/images/applet'
}
\ No newline at end of file \ No newline at end of file
module.exports = {
"title": "集团近期趋势",
"series": [{
"name": "Passenger flow",
"data": [
1748,
1715,
2563,
2305,
1848,
1783,
1454
],
"type": "line"
}],
"xaxis": {
"data": [
"02-24(Thu)",
"02-25(Fri)",
"02-26(Sat)",
"02-27(Sun)",
"02-28(Mon)",
"03-01(Tue)",
"03-02(Wed)"
]
}
}
\ No newline at end of file \ No newline at end of file
import WxCanvas from './wx-canvas';
import * as echarts from './echarts';
let ctx;
function compareVersion(v1, v2) {
v1 = v1.split('.')
v2 = v2.split('.')
const len = Math.max(v1.length, v2.length)
while (v1.length < len) {
v1.push('0')
}
while (v2.length < len) {
v2.push('0')
}
for (let i = 0; i < len; i++) {
const num1 = parseInt(v1[i])
const num2 = parseInt(v2[i])
if (num1 > num2) {
return 1
} else if (num1 < num2) {
return -1
}
}
return 0
}
Component({
properties: {
canvasId: {
type: String,
value: 'ec-canvas'
},
ec: {
type: Object
},
forceUseOldCanvas: {
type: Boolean,
value: false
}
},
data: {
isUseNewCanvas: false
},
ready: function () {
// Disable prograssive because drawImage doesn't support DOM as parameter
// See https://developers.weixin.qq.com/miniprogram/dev/api/canvas/CanvasContext.drawImage.html
echarts.registerPreprocessor(option => {
if (option && option.series) {
if (option.series.length > 0) {
option.series.forEach(series => {
series.progressive = 0;
});
}
else if (typeof option.series === 'object') {
option.series.progressive = 0;
}
}
});
if (!this.data.ec) {
console.warn('组件需绑定 ec 变量,例:<ec-canvas id="mychart-dom-bar" '
+ 'canvas-id="mychart-bar" ec="{{ ec }}"></ec-canvas>');
return;
}
if (!this.data.ec.lazyLoad) {
this.init();
}
},
methods: {
init: function (callback) {
const version = wx.getSystemInfoSync().SDKVersion
const canUseNewCanvas = compareVersion(version, '2.9.0') >= 0;
const forceUseOldCanvas = this.data.forceUseOldCanvas;
const isUseNewCanvas = canUseNewCanvas && !forceUseOldCanvas;
this.setData({ isUseNewCanvas });
if (forceUseOldCanvas && canUseNewCanvas) {
console.warn('开发者强制使用旧canvas,建议关闭');
}
if (isUseNewCanvas) {
// console.log('微信基础库版本大于2.9.0,开始使用<canvas type="2d"/>');
// 2.9.0 可以使用 <canvas type="2d"></canvas>
this.initByNewWay(callback);
} else {
const isValid = compareVersion(version, '1.9.91') >= 0
if (!isValid) {
console.error('微信基础库版本过低,需大于等于 1.9.91。'
+ '参见:https://github.com/ecomfe/echarts-for-weixin'
+ '#%E5%BE%AE%E4%BF%A1%E7%89%88%E6%9C%AC%E8%A6%81%E6%B1%82');
return;
} else {
console.warn('建议将微信基础库调整大于等于2.9.0版本。升级后绘图将有更好性能');
this.initByOldWay(callback);
}
}
},
initByOldWay(callback) {
// 1.9.91 <= version < 2.9.0:原来的方式初始化
ctx = wx.createCanvasContext(this.data.canvasId, this);
const canvas = new WxCanvas(ctx, this.data.canvasId, false);
echarts.setCanvasCreator(() => {
return canvas;
});
// const canvasDpr = wx.getSystemInfoSync().pixelRatio // 微信旧的canvas不能传入dpr
const canvasDpr = 1
var query = wx.createSelectorQuery().in(this);
query.select('.ec-canvas').boundingClientRect(res => {
if (typeof callback === 'function') {
this.chart = callback(canvas, res.width, res.height, canvasDpr);
}
else if (this.data.ec && typeof this.data.ec.onInit === 'function') {
this.chart = this.data.ec.onInit(canvas, res.width, res.height, canvasDpr);
}
else {
this.triggerEvent('init', {
canvas: canvas,
width: res.width,
height: res.height,
canvasDpr: canvasDpr // 增加了dpr,可方便外面echarts.init
});
}
}).exec();
},
initByNewWay(callback) {
// version >= 2.9.0:使用新的方式初始化
const query = wx.createSelectorQuery().in(this)
query
.select('.ec-canvas')
.fields({ node: true, size: true })
.exec(res => {
const canvasNode = res[0].node
this.canvasNode = canvasNode
const canvasDpr = wx.getSystemInfoSync().pixelRatio
const canvasWidth = res[0].width
const canvasHeight = res[0].height
const ctx = canvasNode.getContext('2d')
const canvas = new WxCanvas(ctx, this.data.canvasId, true, canvasNode)
echarts.setCanvasCreator(() => {
return canvas
})
if (typeof callback === 'function') {
this.chart = callback(canvas, canvasWidth, canvasHeight, canvasDpr)
} else if (this.data.ec && typeof this.data.ec.onInit === 'function') {
this.chart = this.data.ec.onInit(canvas, canvasWidth, canvasHeight, canvasDpr)
} else {
this.triggerEvent('init', {
canvas: canvas,
width: canvasWidth,
height: canvasHeight,
dpr: canvasDpr
})
}
})
},
canvasToTempFilePath(opt) {
if (this.data.isUseNewCanvas) {
// 新版
const query = wx.createSelectorQuery().in(this)
query
.select('.ec-canvas')
.fields({ node: true, size: true })
.exec(res => {
const canvasNode = res[0].node
opt.canvas = canvasNode
wx.canvasToTempFilePath(opt)
})
} else {
// 旧的
if (!opt.canvasId) {
opt.canvasId = this.data.canvasId;
}
ctx.draw(true, () => {
wx.canvasToTempFilePath(opt, this);
});
}
},
touchStart(e) {
if (this.chart && e.touches.length > 0) {
var touch = e.touches[0];
var handler = this.chart.getZr().handler;
handler.dispatch('mousedown', {
zrX: touch.x,
zrY: touch.y
});
handler.dispatch('mousemove', {
zrX: touch.x,
zrY: touch.y
});
handler.processGesture(wrapTouch(e), 'start');
}
},
touchMove(e) {
if (this.chart && e.touches.length > 0) {
var touch = e.touches[0];
var handler = this.chart.getZr().handler;
handler.dispatch('mousemove', {
zrX: touch.x,
zrY: touch.y
});
handler.processGesture(wrapTouch(e), 'change');
}
},
touchEnd(e) {
if (this.chart) {
const touch = e.changedTouches ? e.changedTouches[0] : {};
var handler = this.chart.getZr().handler;
handler.dispatch('mouseup', {
zrX: touch.x,
zrY: touch.y
});
handler.dispatch('click', {
zrX: touch.x,
zrY: touch.y
});
handler.processGesture(wrapTouch(e), 'end');
}
}
}
});
function wrapTouch(event) {
for (let i = 0; i < event.touches.length; ++i) {
const touch = event.touches[i];
touch.offsetX = touch.x;
touch.offsetY = touch.y;
}
return event;
}
{
"component": true,
"usingComponents": {}
}
\ No newline at end of file \ No newline at end of file
This diff could not be displayed because it is too large.
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!