|
- <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 @click="informClick(block.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("learun/adms/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
- //微信推送跳转
- if (!!param.page) {
- //通知公告
- if (param.page == "notice") {
- this.NAV_TO("/pages/LR_OAModule/list");
- }
- //邮件
- if (param.page == "mail") {
- this.NAV_TO("/pages/EducationalAdministration/SYS_ReceiveMessage/list");
- }
- //OA待办
- if (param.page == "oa") {
- this.NAV_TO("/pages/nworkflow/myflow/list");
- }
- //公文下发
- if (param.page == "file") {
- this.NAV_TO("/pages/EducationalAdministration/Sys_ReceiveFile/list");
- }
- return;
- }
- },
-
- // 验证登录状态
- 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("learun/adms/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(
- "learun/adms/desktop/imgid" +
- (this.CONFIG("isDistributed") == true ? "?isDistributed=true" : "")
- ),
- this.HTTP_GET("learun/adms/function/list").then(
- (result) => result.data
- ),
- this.HTTP_GET("learun/adms/function/mylist"),
- this.HTTP_GET("learun/adms/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("learun/adms/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("learun/adms/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("learun/adms/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) {
- console.log(item);
- this.NAV_TO("/pages/home/notice", item, true);
- },
- informClick(titleName) {
- if (titleName == "通知公告") {
- this.NAV_TO("/pages/LR_OAModule/list", "", 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>
|