Commit 92f069b9865b24111435a8693bde658540d46330

Authored by xp.Huang
2 parents 62cf4308 f8e14e09

Merge branch 'perf/add-visual-board' into 'main_dev'

perf:首页添加看板展示

See merge request yunteng/thingskit-app!122
... ... @@ -20,6 +20,11 @@ const getConfigurationApi = (params = {}) => {
20 20 .get('/yt/configuration/center', params)
21 21 }
22 22
  23 +// 获取看板分页API
  24 +const getVisualBoardApi = (params) => {
  25 + return uni.$u.http.get('yt/data_board',params)
  26 +}
  27 +
23 28 //获取组织列表
24 29 const getMeOrgListApi = () => {
25 30 return uni.$u.http
... ... @@ -31,5 +36,6 @@ export default {
31 36 getCameraApi,
32 37 byCameraIdGetDetailApi,
33 38 getConfigurationApi,
34   - getMeOrgListApi
  39 + getMeOrgListApi,
  40 + getVisualBoardApi
35 41 }
... ...
... ... @@ -8,8 +8,8 @@ import {
8 8 * baseWebSocketUrl 服务端 websocket地址
9 9 * socketPrefix websocket前缀 ((https, wss),( http, ws))
10 10 */
11   -
12 11 const baseUrl = "http://222.180.200.114:48080/api";
  12 +const baseVisualUrl = "http://192.168.1.10:8083"
13 13 const baseDrawioUrl = "http://222.180.200.114:9527/thingskit-scada";
14 14 const baseWebSocketUrl = "222.180.200.114:48080";
15 15 const socketPrefix = "ws";
... ... @@ -42,6 +42,7 @@ systemInfo.platform = "plus";
42 42 const courtConfig = {
43 43 publicAppId: "", //公众号appId
44 44 baseUrl, //服务端地址
  45 + baseVisualUrl,//服务端看板地址
45 46 baseDrawioUrl, //服务端组态地址
46 47 baseWebSocketUrl, //服务端websocket地址
47 48 socketPrefix, //websocket前缀
... ...
... ... @@ -403,4 +403,4 @@
403 403 width: 663rpx !important;
404 404 }
405 405 }
406   -</style>
\ No newline at end of file
  406 +</style>
... ...
1 1 {
2 2 "name" : "ThingsKit",
3   - "appid" : "__UNI__AD0D64F",
  3 + "appid" : "__UNI__E8FFC75",
4 4 "description" : "thingskit",
5 5 "versionName" : "1.0.0",
6 6 "versionCode" : 100,
... ... @@ -105,7 +105,7 @@
105 105 },
106 106 "quickapp" : {},
107 107 "mp-weixin" : {
108   - "appid" : "wxd5d018355f38262b",
  108 + "appid" : "wx3a36e5189b607150",
109 109 "setting" : {
110 110 "urlCheck" : false,
111 111 "minified" : true,
... ...
... ... @@ -61,6 +61,18 @@
61 61 "style": {
62 62 "navigationBarTitleText": "组织筛选"
63 63 }
  64 + },
  65 + {
  66 + "path": "pages/index/components/visualBoard/index",
  67 + "style": {
  68 + "navigationBarTitleText": "查看看板"
  69 + }
  70 + },
  71 + {
  72 + "path": "pages/index/components/visualBoard/detail",
  73 + "style": {
  74 + "navigationBarTitleText": "看板详情"
  75 + }
64 76 }
65 77 ],
66 78 "subPackages": [{
... ... @@ -194,4 +206,4 @@
194 206 }
195 207 ]
196 208 }
197   -}
\ No newline at end of file
  209 +}
... ...
... ... @@ -59,4 +59,4 @@
59 59
60 60 <style lang="scss" scoped>
61 61 @import '../../static/configuration.scss';
62   -</style>
\ No newline at end of file
  62 +</style>
... ...
  1 +<template>
  2 + <view>
  3 + <web-view :src="visualBoardUrl"></web-view>
  4 + </view>
  5 +
  6 +</template>
  7 +
  8 +<script>
  9 + import config from '../../../../config/baseUrl.js'
  10 + export default {
  11 + data(){
  12 + return {
  13 + visualBoardUrl:'',
  14 + }
  15 + },
  16 + async onLoad(e){
  17 + const url = await this.createShareUrl({id:e.id})
  18 + console.log(url,'url')
  19 + this.visualBoardUrl = url
  20 + },
  21 + methods:{
  22 + getUrl(id,userId){
  23 + return `/appPage/${id}/${userId}`
  24 + },
  25 +
  26 + async createShareUrl(record){
  27 + const userInfo = uni.getStorageSync('userInfo')
  28 + const { id } = record;
  29 + // http://192.168.10.131:8083
  30 + return `${config.baseVisualUrl}${this.getUrl(id,userInfo.userId)}`;
  31 + }
  32 + }
  33 + }
  34 +</script>
  35 +
  36 +<style>
  37 +</style>
... ...
  1 +import config from '../../../../config/baseUrl.js'
  2 +import {
  3 + atob,
  4 + btoa
  5 +} from './weapp.atob.js'
  6 +const getRandomString = () => Number(Math.random().toString().substring(2)).toString(36);
  7 +
  8 +export const ScadaModeEnum = {
  9 + PRIVATE_VIEW: 'PRIVATE_VIEW',
  10 + PUBLIC_VIEW: 'PUBLIC_VIEW',
  11 +}
  12 +
  13 +export const encode = (record) => {
  14 + let hash = JSON.stringify(record);
  15 + const mixinString = getRandomString()
  16 + .slice(0, 10)
  17 + .padEnd(10, getRandomString())
  18 + .split('')
  19 + .map((item) => (Math.random() > 0.5 ? item.toUpperCase() : item))
  20 + .join('');
  21 + hash = btoa(hash);
  22 + hash = hash.substring(0, 6) + mixinString + hash.substring(6);
  23 + hash = btoa(hash);
  24 + return hash;
  25 +};
  26 +
  27 +
  28 +export const createScadaPageLink = (
  29 + record,
  30 + mode = ScadaModeEnum.PRIVATE_VIEW,
  31 + open = false
  32 +) => {
  33 + const userInfo = uni.getStorageSync('userInfo')
  34 + const params = {
  35 + configurationId: record?.id,
  36 + organizationId: record?.organizationId,
  37 + mode: record?.viewType === ScadaModeEnum.PRIVATE_VIEW ? 'lightbox' : 'share',
  38 + platform: record?.platform,
  39 + userId: userInfo.userId
  40 + };
  41 +
  42 + if (record?.viewType === ScadaModeEnum.PUBLIC_VIEW) {
  43 + params.publicId = record.publicId;
  44 + }
  45 +
  46 + const hash = encode(params);
  47 +
  48 + const href = `${config.baseDrawioUrl}#${hash}`
  49 +
  50 + return href
  51 +};
\ No newline at end of file
... ...
  1 +<template>
  2 + <view class="configuation-page">
  3 + <view class="configuation-header">
  4 + <view class="header-gap"></view>
  5 + <view class="search-top">
  6 + <view class="search-main">
  7 + <u--input @change="inputChanged" prefixIcon="search" placeholder="请输入看板名称" border="surround"
  8 + shape="circle"></u--input>
  9 + </view>
  10 + </view>
  11 + </view>
  12 + <view style="height:35rpx"></view>
  13 + <!-- 公共组件-每个页面必须引入 -->
  14 + <public-module></public-module>
  15 + <!-- 自带分页组件 -->
  16 + <mescroll-body ref="mescrollRef" :up="upOption" @init="mescrollInit" :down="downOption" @down="downCallback"
  17 + @up="upCallback">
  18 + <view class="configuation-container">
  19 + <view class="configuation-item">
  20 + <view @click="openConfigDetail(item)" v-for="(item, index) in list" :key="index" class="item">
  21 + <image class="image" :src="item.icon || defaultConfigImage"></image>
  22 + <text class="name">{{ item.name }}</text>
  23 + </view>
  24 + </view>
  25 + </view>
  26 + <mescroll-empty v-if="!list.length" />
  27 + </mescroll-body>
  28 + <!-- 自带分页组件 -->
  29 + <view style="height: 60rpx;"></view>
  30 + </view>
  31 +</template>
  32 +
  33 +<script>
  34 + import MescrollMixin from '@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js';
  35 + import api from '@/api/index.js'
  36 + import {
  37 + createScadaPageLink
  38 + } from './help';
  39 +
  40 + export default {
  41 + mixins: [MescrollMixin], // 使用mixin (在main.js注册全局组件)
  42 + data() {
  43 + return {
  44 + defaultConfigImage: '../../../../static/test.png',
  45 + page: {
  46 + num: 0,
  47 + size: 10
  48 + },
  49 + downOption: {
  50 + auto: true //是否在初始化后,自动执行downCallback; 默认true
  51 + },
  52 + upOption: {
  53 + auto: false // 不自动加载
  54 + },
  55 + list: []
  56 + };
  57 + },
  58 + onLoad() {
  59 + // 隐藏原生的tabbar
  60 + uni.hideTabBar();
  61 + uni.setStorageSync('getConfiguration', {
  62 + isConfiguration: false
  63 + });
  64 + },
  65 + onUnload() {
  66 + uni.setStorageSync('getConfiguration', {
  67 + isConfiguration: false
  68 + });
  69 + uni.removeStorageSync('getConfiguration');
  70 + },
  71 + methods: {
  72 + inputChanged(e) {
  73 + this.page.num = 1;
  74 + this.loadData(1, e);
  75 + },
  76 + openConfigDetail(e) {
  77 + console.log(e,'e')
  78 + uni.navigateTo({
  79 + url: 'detail?id=' + e.id
  80 + });
  81 + },
  82 + /*下拉刷新的回调 */
  83 + downCallback() {
  84 + //联网加载数据
  85 + this.page.num = 1;
  86 + this.loadData(1);
  87 + },
  88 + /*上拉加载的回调: 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 */
  89 + upCallback() {
  90 + //联网加载数据
  91 + this.page.num += 1;
  92 + this.loadData(this.page.num);
  93 + },
  94 + async loadData(pageNo, name) {
  95 + let httpData = {
  96 + page: pageNo,
  97 + pageSize: 10,
  98 + name,
  99 + platform: 'phone'
  100 + };
  101 + const res = await api.homeApi.getVisualBoardApi({
  102 + params: httpData,
  103 + custom: {
  104 + load: false
  105 + }
  106 + })
  107 + if (res) {
  108 + uni.stopPullDownRefresh();
  109 + this.mescroll.endByPage(res.items.length, res.total);
  110 + this.cameraTotal = res.total;
  111 + if (pageNo == 1) {
  112 + this.list = res.items;
  113 + } else {
  114 + this.list = this.list.concat(res.items);
  115 + }
  116 + }
  117 + }
  118 + }
  119 + };
  120 +</script>
  121 +
  122 +<style lang="scss" scoped>
  123 + @import '../../static/configuration.scss';
  124 +</style>
... ...
  1 +var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
  2 +var b64re = /^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/;
  3 +export const btoa = function(string) {
  4 + string = String(string);
  5 + var bitmap, a, b, c, result = "",
  6 + i = 0,
  7 + rest = string.length % 3;
  8 + for (; i < string.length;) {
  9 + if ((a = string.charCodeAt(i++)) > 255 ||
  10 + (b = string.charCodeAt(i++)) > 255 ||
  11 + (c = string.charCodeAt(i++)) > 255)
  12 + throw new TypeError(
  13 + "Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range."
  14 + );
  15 + bitmap = (a << 16) | (b << 8) | c;
  16 + result += b64.charAt(bitmap >> 18 & 63) + b64.charAt(bitmap >> 12 & 63) +
  17 + b64.charAt(bitmap >> 6 & 63) + b64.charAt(bitmap & 63);
  18 + }
  19 + return rest ? result.slice(0, rest - 3) + "===".substring(rest) : result;
  20 +};
  21 +
  22 +export const atob = function(string) {
  23 + string = String(string).replace(/[\t\n\f\r ]+/g, "");
  24 + if (!b64re.test(string))
  25 + throw new TypeError(
  26 + "Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.");
  27 + string += "==".slice(2 - (string.length & 3));
  28 + var bitmap, result = "",
  29 + r1, r2, i = 0;
  30 + for (; i < string.length;) {
  31 + bitmap = b64.indexOf(string.charAt(i++)) << 18 | b64.indexOf(string.charAt(i++)) << 12 |
  32 + (r1 = b64.indexOf(string.charAt(i++))) << 6 | (r2 = b64.indexOf(string.charAt(i++)));
  33 + result += r1 === 64 ? String.fromCharCode(bitmap >> 16 & 255) :
  34 + r2 === 64 ? String.fromCharCode(bitmap >> 16 & 255, bitmap >> 8 & 255) :
  35 + String.fromCharCode(bitmap >> 16 & 255, bitmap >> 8 & 255, bitmap & 255);
  36 + }
  37 + return result;
  38 +};
  39 +
  40 +function b64DecodeUnicode(str) {
  41 + return decodeURIComponent(exports.weAtob(str).replace(/(.)/g, function(p) {
  42 + var code = p.charCodeAt(0).toString(16).toUpperCase();
  43 + if (code.length < 2) {
  44 + code = "0" + code;
  45 + }
  46 + return "%" + code;
  47 + }));
  48 +}
  49 +
  50 +function base64_url_decode(str) {
  51 + var output = str.replace(/-/g, "+").replace(/_/g, "/");
  52 + switch (output.length % 4) {
  53 + case 0:
  54 + break;
  55 + case 2:
  56 + output += "==";
  57 + break;
  58 + case 3:
  59 + output += "=";
  60 + break;
  61 + default:
  62 + throw "Illegal base64url string!";
  63 + }
  64 + try {
  65 + return b64DecodeUnicode(output);
  66 + } catch (err) {
  67 + return exports.weAtob(output);
  68 + }
  69 +}
  70 +
  71 +function weappJwtDecode(token, options) {
  72 + if (typeof token !== "string") {
  73 + throw ("Invalid token specified");
  74 + }
  75 + options = options || {};
  76 + var pos = options.header === true ? 0 : 1;
  77 + try {
  78 + return JSON.parse(base64_url_decode(token.split(".")[pos]));
  79 + } catch (e) {
  80 + throw ("Invalid token specified: " + e.message);
  81 + }
  82 +}
\ No newline at end of file
... ...
... ... @@ -8,6 +8,11 @@ const basicGridList = [{
8 8 icon: '/static/status.png',
9 9 text: '组态'
10 10 },
  11 + {
  12 + event: 'visualBoard',
  13 + icon: '/static/visual-board.png',
  14 + text: '看板'
  15 + },
11 16 ]
12 17
13 18 const basicStatistics = [{
... ... @@ -51,4 +56,4 @@ const basicStatistics = [{
51 56 export {
52 57 basicGridList,
53 58 basicStatistics
54   -}
\ No newline at end of file
  59 +}
... ...
... ... @@ -127,8 +127,13 @@
127 127 openConfiguration() {
128 128 useNavigateTo('components/configuration/configuration')
129 129 },
  130 + openVisualBoard() {
  131 + useNavigateTo('components/visualBoard/index')
  132 + },
130 133 handleEvent(event) {
131   - if (event === 'openCamera') this.openCamera()
  134 + if(event==='visualBoard') {
  135 + this.openVisualBoard()
  136 + }else if (event === 'openCamera') this.openCamera()
132 137 else {
133 138 this.openConfiguration()
134 139 }
... ... @@ -160,4 +165,4 @@
160 165
161 166 <style lang="scss" scoped>
162 167 @import './static/index.scss';
163   -</style>
\ No newline at end of file
  168 +</style>
... ...
... ... @@ -36,6 +36,7 @@
36 36 width: 100rpx;
37 37 height: 100rpx;
38 38 margin-top: 20rpx;
  39 + border-radius: 32rpx;
39 40 }
40 41 }
41 42 .center-text {
... ...