<template>
	<view id="home" class="page">
		<!-- 顶部搜索栏 -->
		<view class="header text-white">
			<!-- #ifndef H5 -->
			<l-icon @click="scanClick" type="scan" color="white" class="header-left text-xxl margin-left-sm" />
			<!-- #endif -->
			<view @click="moreClick(1)" class="search header-mid margin-lr-sm">
				<l-icon type="search" color="white" class="margin-lr-sm" />
				搜索更多应用
			</view>
			<l-icon @click="msgClick" type="mail" color="white" class="header-right text-xxl margin-right-sm" />
		</view>

		<!-- 轮播图片 -->
		<swiper v-if="imgCount > 0" style="height:120px;">
			<swiper-item v-for="(item, index) of imgData" :key="index" style="height:120px;">
				<image :src="item" mode="aspectFill" style="height:100%; width:100%;"></image>
			</swiper-item>
		</swiper>

		<!-- 功能宫格列表 -->
		<view class="col-4 function-list cu-list grid no-border">
			<view v-for="(item, index) in funcListDisplay" @click="funcListClick(item)" :key="index" class="cu-item text-center flex flex-wrap justify-center align-center">
				<view class="app-item align-center flex flex-wrap justify-center align-center">
					<l-icon :type="item.icon" color="white" class="text-sl" />
				</view>
				<text>{{ item.F_Name }}</text>
			</view>
		</view>
		<view class="text-center bg-white margin-bottom">
			<text @click="moreClick(0)" class="function-more-btn margin-tb-sm text-gray">更多应用</text>
		</view>

		<!-- 统计数据宫格 -->
		<l-title>统计数据</l-title>
		<view class="count-list cu-list grid col-3 margin-bottom">
			<view v-for="(item, index) in countData" :key="index" class="cu-item text-center">
				<text class="margin-bottom-xs">{{ item.title || '(未命名)' }}</text>
				<text class="count-item-value">{{ item.value || '-' }}</text>
			</view>
		</view>

		<!-- 通知列表区块 -->
		<view v-for="(block, blockIndex) of noticeData" :key="blockIndex" class="margin-bottom">
			<!-- <view class="margin-top"></view> -->
			<l-title>{{ block.title }}</l-title>
			<l-list>
				<l-list-item v-for="(item, i) of block.content" @click="noticeClick(item)" :key="i" arrow>
					{{ item.f_title || '(无标题)' }}
					<l-tag slot="action" line="gray">{{ postDateTime(item.f_time) }}</l-tag>
				</l-list-item>
			</l-list>
		</view>

		<!-- 图表区块 -->
		<view v-for="(item) of chartData" :key="item.id" class="margin-bottom">
			<l-title>{{ item.title }}</l-title>
			<view :style="{ width: cWidth + 'px', height: cHeight + 'px' }" class="chart-list">
				<!--#ifndef MP-ALIPAY -->
				<canvas v-if="item.type === 1" @tap="chartTap(item, $event)" @touchstart="touchStart(item.id, $event)" @touchmove="touchMove(item.id, $event)"
				 @touchend="touchEnd(item.id, $event)" :style="{ width: cWidth + 'px', height: cHeight + 'px' }" :canvas-id="item.id"
				 :id="item.id" class="charts"></canvas>
				<canvas v-else @tap="chartTap(item, $event)" :style="{ width: cWidth + 'px', height: cHeight + 'px' }" :canvas-id="item.id"
				 :id="item.id" class="charts"></canvas>
				<!--#endif -->

				<!-- 阿里小程序，需要以2倍尺寸显示，然后缩放为50% -->
				<!--#ifdef MP-ALIPAY -->
				<canvas v-if="item.type === 1" @tap="chartTap(item, $event)" @touchstart="touchStart(item.id, $event)" @touchmove="touchMove(item.id, $event)"
				 @touchend="touchEnd(item.id, $event)" :style="{
            width: cWidth * pixelRatio + 'px',
            height: cHeight * pixelRatio + 'px',
            transform: 'scale(' + 1 / pixelRatio + ')',
            marginLeft: (-cWidth * (pixelRatio - 1)) / 2 + 'px',
            marginTop: (-cHeight * (pixelRatio - 1)) / 2 + 'px'
          }"
				 :canvas-id="item.id" :id="item.id" class="charts"></canvas>
				<canvas v-else @tap="chartTap(item, $event)" :style="{
            width: cWidth * pixelRatio + 'px',
            height: cHeight * pixelRatio + 'px',
            transform: 'scale(' + 1 / pixelRatio + ')',
            marginLeft: (-cWidth * (pixelRatio - 1)) / 2 + 'px',
            marginTop: (-cHeight * (pixelRatio - 1)) / 2 + 'px'
          }"
				 :canvas-id="item.id" :id="item.id" class="charts"></canvas>
				<!--#endif -->
			</view>
		</view>
	</view>
</template>

<script>
	import moment from 'moment'
	import mapValues from 'lodash/mapValues'
	import uCharts from '@/common/u-charts.js'

	// 用于保存图表操作对象
	let chartsObject = {}
	let chartsConfig = {}

	export default {
		data() {
			return {
				imgData: [],
				listData: [],
				myList: [],

				countData: [],
				noticeData: [],
				chartData: [],

				pixelRatio: 1,
				cWidth: '',
				cHeight: '',
				chartsFontSize: 10
			}
		},

		async onLoad(param) {
			await this.init(param)
		},

		// 本页面开启下拉刷新，用于刷新首页数据
		onPullDownRefresh() {
			this.refresh().then(() => {
				this.TOAST('已更新首页数据')
				uni.stopPullDownRefresh()
			})
		},

		methods: {
			// 页面初始化
			async init(param) {
				this.HIDE_LOADING()

				// 有参数表示可能是打开分享消息；将数据存入全局变量以备后续跳转
				if (param && param.learun && param.pagePath) {
					this.SET_GLOBAL('jumpParam', param)
				}

				// 登录状态无效，则跳转到登录页
				const stateValid = await this.checkLoginState()
				if (!stateValid) {
					this.RELAUNCH_TO('/pages/login')
					return
				}

				// 图表相关参数初始化
				this.initCharts()

				// 加载页面数据和全局数据
				await this.FETCH_CLIENTDATA()
				await this.refresh()

				// 监听「我的应用」列表修改
				this.ON('home-list-change', () => {
					this.HTTP_GET('/function/mylist').then(newList => {
						this.myList = newList
					})
				})

				this.SET_STORAGE('nextTime', null)

				// 处理小程序分享消息跳转
				// #ifdef MP
				const jumpParam = this.GET_GLOBAL('jumpParam')
				if (jumpParam) {
					this.SET_GLOBAL('jumpParam', null)
					this.MP_SHARE_DECODE(jumpParam)
				}
				// #endif
			},

			// 验证登录状态
			async checkLoginState() {
				const token = this.GET_GLOBAL('token') || uni.getStorageSync('token')
				if (!token || token === 'null' || token === 'undefined') {
					this.RELAUNCH_TO('/pages/login')
					this.HIDE_LOADING()

					return false
				}
				this.SET_GLOBAL('token', token)

				// 判断是否有 loginUser 对象
				if (this.GET_GLOBAL('loginUser')) {
					return true
				}

				// 拉取用户信息验证登录态；如果失败则跳转至登录页
				const userInfo = await this.HTTP_GET('/user/info')
				if (!userInfo) {
					this.SET_GLOBAL('token', null)
					this.SET_STORAGE('token', null)
					return false
				}

				// 有登录态，则设置用户信息和全局数据
				const {
					baseinfo,
					mpinfo,
					post,
					role
				} = userInfo
				const user = { ...baseinfo,
					post,
					role
				}
				if (mpinfo && Array.isArray(mpinfo) && mpinfo.includes(this.PLATFORM)) {
					user.miniProgram = true
				}
				this.SET_GLOBAL('loginUser', user)

				return true
			},

			// 刷新首页数据
			async refresh() {
				// 清空页面数据
				chartsObject = {}

				this.imgData = []
				this.listData = []
				this.myList = []

				this.countData = []
				this.noticeData = []
				this.chartData = []

				// 同时发出请求，获取轮播图、所有功能列表、我的功能列表、商机通知提醒图表数据
				// 商机、通知提醒图表数据，获取的是数据ID，所以还需要进一步请求
				const [imgData, listData, myList, settingData] = await Promise.all([
					this.HTTP_GET('/desktop/imgid' + (this.CONFIG('isDistributed')==true ? '?isDistributed=true' : '')),
					this.HTTP_GET('/function/list').then(result => result.data),
					this.HTTP_GET('/function/mylist'),
					this.HTTP_GET('/desktop/setting').then(result => result.data)
				])
				this.imgData=imgData;
				if (!this.CONFIG('isDistributed'))
					// 轮播图需要加上 url 前缀
					this.imgData = imgData.map(t => this.API + `/desktop/img?data=${t}`)

				// 功能区按钮需要处理 icon
				this.listData = listData.map(item => {
					const icon = item.F_Icon ? item.F_Icon.replace(`iconfont icon-`, ``) : ''
					const existsIcon = this.getUiIcons().some(t => t === icon)

					return {
						...item,
						icon: existsIcon ? icon : 'roundright'
					}
				})

				// 我的应用列表需要过滤掉不存在的按钮
				this.myList = myList.filter(t => listData.find(item => item.F_Id === t))

				// 发出请求，获取商机信息、消息通知信息、图表信息；三类数据全部同时请求
				await Promise.all([
					...settingData.target.map(item =>
						this.HTTP_GET('/desktop/data', {
							type: 'Target',
							id: item.F_Id
						}).then(data => {
							if (data && data.value) {
								const {
									value
								} = data
								this.countData.push({
									title: item.F_Name,
									value
								})
							}
						})
					),

					...settingData.list.map(item =>
						this.HTTP_GET('/desktop/data', {
							type: 'list',
							id: item.F_Id
						}).then(data => {
							if (data && data.value) {
								const {
									value
								} = data
								this.noticeData.push({
									title: item.F_Name,
									content: value
								})
							}
						})
					),

					...settingData.chart.map(item =>
						this.HTTP_GET('/desktop/data', {
							type: 'chart',
							id: item.F_Id
						}).then(data => {
							if (data && data.value) {
								const {
									value
								} = data
								this.chartData.push({
									title: item.F_Name,
									value,
									id: item.F_Id,
									type: item.F_Type
								})
							}
						})
					)
				])

				// 渲染图表
				this.chartData.forEach(item => {
					// 根据 item.type 的值选用对应的图表初始化配置项
					// 0=环形图；1=折线图；2=柱状图
					const charts = new uCharts(
						[{
								...chartsConfig,
								canvasId: item.id,
								type: 'ring',
								series: item.value.map(t => ({
									name: t.name,
									data: t.value
								})),
								extra: {
									pie: {
										offsetAngle: -45,
										ringWidth: 20,
										labelWidth: 15
									}
								},
								legend: {
									lineHeight: 20
								}
							},
							{
								...chartsConfig,
								canvasId: item.id,
								type: 'line',
								series: [{
									name: item.title,
									data: item.value.map(t => t.value)
								}],
								categories: item.value.map(t => t.name),
								extra: {
									line: {
										type: 'straight'
									}
								},
								xAxis: {
									rotateLabel: true,
									fontSize: this.chartsFontSize,
									itemCount: 8
								},
								enableScroll: true
							},
							{
								...chartsConfig,
								canvasId: item.id,
								type: 'column',
								series: [{
									name: item.title,
									data: item.value.map(t => t.value)
								}],
								categories: item.value.map(t => t.name),
								xAxis: {
									rotateLabel: true,
									fontSize: this.chartsFontSize
								}
							}
						][item.type]
					)

					chartsObject[item.id] = charts
				})
			},

			// 初始化图表
			initCharts() {
				// （阿里小程序）设置图表尺寸为2倍
				// #ifdef MP-ALIPAY
				const pixelRatio = uni.getSystemInfoSync().pixelRatio
				if (pixelRatio > 1) {
					this.pixelRatio = 2
					this.chartsFontSize = 15
				}
				// #endif

				this.cWidth = uni.upx2px(750)
				this.cHeight = uni.upx2px(500)
				chartsConfig = {
					$this: this,
					pixelRatio: this.pixelRatio,
					width: this.cWidth * this.pixelRatio,
					height: this.cHeight * this.pixelRatio,
					background: '#FFFFFF',
					dataLabel: true,
					padding: [20, 15, 5, 15]
				}
			},

			// 图表点击事件
			chartTap(chartItem, e) {
				const format = ({
					name,
					data
				}, category) => `${category || ''} ${name}: ${data}`

				// #ifdef MP-DINGTALK
				const detail = e.detail
				const item = detail
				e.mp.changedTouches = [item]
				// #endif

				chartsObject[chartItem.id].showToolTip(e, {
					format
				})
			},

			// 图表拖动事件（开始）
			touchStart(chartId, e) {
				chartsObject[chartId].scrollStart(e)
			},

			// 图表拖动事件（拖动）
			touchMove(chartId, e) {
				chartsObject[chartId].scroll(e)
			},

			// 图表拖动事件（结束）
			touchEnd(chartId, e) {
				chartsObject[chartId].scrollEnd(e)
			},

			// 格式化日期的显示（新闻列表、通知公告等）
			postDateTime(timeStr) {
				return moment(timeStr).fromNow()
			},

			// 点击功能按钮
			funcListClick(item) {
				if (item.F_IsSystem === 2) {
					this.NAV_TO(`/pages/customapp/list?formId=${item.F_FormId}`, item, true)
					return
				}

				this.NAV_TO(`/pages/${item.F_Url}/list`)
			},

			// 点击通知公告的标题
			noticeClick(item) {
				this.NAV_TO('/pages/home/notice', item, true)
			},

			// #ifndef H5
			// 点击左上角扫码图标，H5 无此功能
			scanClick() {
				uni.scanCode({
					scanType: ['qrCode', 'barCode'],
					success: ({
						result,
						charSet
					}) => {
						// 您可以在这里自行定制扫码后的功能
					}
				})
			},
			// #endif

			// 点击更多功能按钮
			moreClick(openSearch) {
				this.NAV_TO(`/pages/home/more${openSearch ? '?search=1' : ''}`)
			},

			// 点击右上角的消息按钮
			msgClick() {
				this.TAB_TO('/pages/msg')
			}
		},

		computed: {
			// 「我的功能」区域按钮列表
			funcListDisplay() {
				const {
					myList,
					listData
				} = this
				const myFuncList = myList.reduce((list, id) => {
					if (listData.find(t => t.F_Id === id)) {
						return [...list, listData.find(t => t.F_Id === id)]
					}
					return list
				}, [])

				return myFuncList
			},

			// imgData 数组的长度
			imgCount() {
				return this.imgData.length
			}
		}
	}
</script>

<style lang="less" scoped>
	.page {
		background-color: #f3f3f3;

		.header {
			height: 100rpx;
			background-color: #0c86d8;
			display: flex;
			align-items: center;

			.header-left {
				flex-grow: 0;
			}

			.header-mid {
				flex-grow: 1;
				background-color: #3d9ee0;
				line-height: 60rpx;
				height: 60rpx;
				font-size: 24rpx;
				color: #fff;
				border-radius: 6rpx;
			}

			.header-right {
				flex-grow: 0;
			}
		}

		.content {
			background-color: #fff;
		}

		.function-list {
			padding-bottom: 0;

			.cu-item {
				.app-item {
					border-radius: 50%;
					height: 45px;
					width: 45px;
				}

				&:nth-child(7n + 1)>.app-item {
					background-color: #62bbff;
				}

				&:nth-child(7n + 2)>.app-item {
					background-color: #7bd2ff;
				}

				&:nth-child(7n + 3)>.app-item {
					background-color: #ffd761;
				}

				&:nth-child(7n + 4)>.app-item {
					background-color: #fe955c;
				}

				&:nth-child(7n + 5)>.app-item {
					background-color: #ff6283;
				}

				&:nth-child(7n + 6)>.app-item {
					background-color: #60e3f3;
				}

				&:nth-child(7n)>.app-item {
					background-color: #acc8fe;
				}
			}
		}

		.function-more-btn {
			display: inline-block;
			border: currentColor 1px solid;
			border-radius: 2px;
			padding: 10rpx 50rpx;
		}

		.count-list {
			&:after {
				content: '';
				clear: both;
				display: table;
			}

			.count-item-value {
				color: #0188d2;
				font-size: 24px;
			}
		}

		.chart-list {
			background-color: #fff;
			overflow: hidden;
		}
	}
</style>

<style lang="less">
	#home {
		width: 750rpx;
		overflow-x: hidden;

		.function-list .cu-item text[class*='cuIcon'] {
			margin-top: 0 !important;
		}
	}
</style>
