Commit 249b839498114354466d683e1cb030b93997b896

Authored by xp.Huang
2 parents 2f6bd6e7 9f612429

Merge branch 'dev-ft' into 'main'

预览打包小程序完成

See merge request huang/thingskit-app!22
Showing 68 changed files with 1114 additions and 5794 deletions
... ... @@ -71,16 +71,11 @@
71 71 <view v-if="list.status !== 'CLEARED_ACK'" style="width: 500rpx;margin-left: 80rpx;margin-top: 44rpx;">
72 72 <u-button @click="handleSubmit" type="primary" shape="circle" text="处理"></u-button>
73 73 </view>
74   - <f-tabbar></f-tabbar>
75 74 </view>
76 75 </template>
77 76
78 77 <script>
79   -import fTabbar from '@/components/module/f-tabbar/f-tabbar';
80 78 export default {
81   - components: {
82   - fTabbar
83   - },
84 79 data() {
85 80 return {
86 81 formModel: {
... ...
alarmSubPage/alarmDetailPage/static/alarmDetail.scss renamed from pages/alarm/static/alarmDetail.scss
1 1 import store from '@/store';
2 2 import base from "@/config/baseUrl";
3   -import QQMapWX from '@/plugins/qqmap-wx-jssdk.js';
  3 +// import QQMapWX from '@/plugins/qqmap-wx-jssdk.js';
4 4 import {
5 5 getAppLatLon
6 6 } from '@/plugins/utils';
... ...
1 1 import base from "@/config/baseUrl";
2   -import store from '@/store';
3   -import {
4   - judgeLogin
5   -} from '@/config/login';
  2 +import store from "@/store";
  3 +import { judgeLogin } from "@/config/login";
6 4
7 5 // 初始化请求配置
8 6 uni.$u.http.setConfig((config) => {
9   - const token = store.state.userInfo.isToken || (uni.getStorageSync('userInfo').isToken || undefined)
10   - // #ifdef H5
11   - window.sessionStorage.getItem('userInfo').isToken;
12   - // #endif
13   - /* config 为默认全局配置*/
14   - config.baseURL = base.baseUrl; /* 根域名 */
15   - config.header = {
16   - 'Content-Type': 'application/json',
17   - 'Authorization': 'Bearer ' + token
18   - }
19   - config.custom = {
20   - load: true, //是否显示加载动画
21   - isFactory: true, //true:返回的数据成功只返回data false:返回response
22   - catch: true, //默认数据返回不成功进入catch返回
23   - auth: true, //token
24   - }
25   - return config
26   -})
  7 + const token =
  8 + store.state.userInfo.isToken ||
  9 + uni.getStorageSync("userInfo").isToken ||
  10 + undefined;
  11 + // #ifdef H5
  12 + window.sessionStorage.getItem("userInfo").isToken;
  13 + // #endif
  14 + /* config 为默认全局配置*/
  15 + config.baseURL = base.baseUrl; /* 根域名 */
  16 + config.header = {
  17 + "Content-Type": "application/json",
  18 + Authorization: "Bearer " + token,
  19 + };
  20 + config.custom = {
  21 + load: true, //是否显示加载动画
  22 + isFactory: true, //true:返回的数据成功只返回data false:返回response
  23 + catch: true, //默认数据返回不成功进入catch返回
  24 + auth: true, //token
  25 + };
  26 + return config;
  27 +});
27 28
28 29 // 请求拦截
29   -uni.$u.http.interceptors.request.use((config) => { // 可使用async await 做异步操作
30   - // 初始化请求拦截器时,会执行此方法,此时data为undefined,赋予默认{}
31   - config.data = config.data || {}
32   - // 根据custom参数中配置的是否需要token,添加对应的请求头
33   - if (config?.custom?.auth) {
34   - config.header.Authorization = 'Bearer ' + store.state.userInfo.isToken || (uni.getStorageSync(
35   - 'userInfo').isToken || undefined)
36   - }
37   - console.log("请求开始", config);
38   - if (config?.custom?.load) {
39   - //打开加载动画
40   - store.commit("setLoadingShow", true);
41   - }
  30 +uni.$u.http.interceptors.request.use(
  31 + (config) => {
  32 + // 可使用async await 做异步操作
  33 + // 初始化请求拦截器时,会执行此方法,此时data为undefined,赋予默认{}
  34 + config.data = config.data || {};
  35 + // 根据custom参数中配置的是否需要token,添加对应的请求头
  36 + if (config?.custom?.auth) {
  37 + config.header.Authorization =
  38 + "Bearer " + store.state.userInfo.isToken ||
  39 + uni.getStorageSync("userInfo").isToken ||
  40 + undefined;
  41 + }
  42 + console.log("请求开始", config);
  43 + if (config?.custom?.load) {
  44 + //打开加载动画
  45 + store.commit("setLoadingShow", true);
  46 + }
42 47
43   - return config
44   -}, config => { // 可使用async await 做异步操作
45   - return Promise.reject(config)
46   -})
  48 + return config;
  49 + },
  50 + (config) => {
  51 + // 可使用async await 做异步操作
  52 + return Promise.reject(config);
  53 + }
  54 +);
47 55
48 56 // 响应拦截
49   -uni.$u.http.interceptors.response.use((response) => {
50   - /* 对响应成功做点什么 可使用async await 做异步操作*/
51   - // 关闭加载动画
52   - store.commit("setLoadingShow", false);
53   - const data = response.data
54   - // 自定义参数
55   - const custom = response.config?.custom
56   - // code: 200、请求成功 其他,没有更多参数 401、被迫下线重新登录、
57   - if (response.statusCode == 200) {
58   - return Promise.resolve(data)
59   - // if (!custom.isFactory) {
60   - // return Promise.reject(response.data)
61   - // } else {
62   - // return data.data === undefined ? {} : Promise.reject(response.data)
63   - // }
64   - } else if (response.statusCode == 401) { //被迫下线重新登录
65   - // 清空登录信息
66   - store.commit("emptyUserInfo");
67   - // 20秒节流,弹窗登录
68   - uni.$u.throttle(judgeLogin(), 20000)
69   - return new Promise(() => {})
70   - } else {
71   - // 如果没有显式定义custom的toast参数为false的话,默认对报错进行toast弹出提示
72   - if (custom.toast !== false) {
73   - uni.$u.toast(data.message || data.msg)
74   - }
75   - // 如果需要catch返回,则进行reject
76   - if (custom?.catch) {
77   - return Promise.reject(data)
78   - } else {
79   - // 否则返回一个pending中的promise,请求不会进入catch中
80   - return new Promise(() => {})
81   - }
82   - }
83   -}, (response) => {
84   - // 关闭加载动画
85   - store.commit("setLoadingShow", false);
86   - // 对响应错误做点什么 (statusCode !== 200)
87   - let errorData = '请检查网络或服务器'
88   - let message = response.data?.message || response?.errMsg
89   - if (message == "request:fail url not in domain list") {
90   - errorData = '检查请求域名是否添加了域名白名单'
91   - } else if (message == 'request:fail timeout') {
92   - errorData = '请求超时:请检查网络'
93   - } else if (message == 'Token has expired') {
94   - errorData = 'Token失效,请重新登录'
95   - uni.reLaunch({
96   - url: '/pages/public/login'
97   - })
98   - store.commit('emptyUserInfo')
99   - } else if (message == 'Invalid username or password') {
100   - errorData = '用户名或者密码无效'
101   - uni.reLaunch({
102   - url: '/pages/public/login'
103   - })
104   - store.commit('emptyUserInfo')
105   - } else {
106   - errorData = message || '请检查网络或服务器'
107   - }
108   - uni.$u.toast(errorData)
109   - return Promise.reject(response)
110   -})
  57 +uni.$u.http.interceptors.response.use(
  58 + (response) => {
  59 + /* 对响应成功做点什么 可使用async await 做异步操作*/
  60 + // 关闭加载动画
  61 + store.commit("setLoadingShow", false);
  62 + const data = response.data;
  63 + // 自定义参数
  64 + const custom = response.config?.custom;
  65 + // code: 200、请求成功 其他,没有更多参数 401、被迫下线重新登录、
  66 + if (response.statusCode == 200) {
  67 + return Promise.resolve(data);
  68 + // if (!custom.isFactory) {
  69 + // return Promise.reject(response.data)
  70 + // } else {
  71 + // return data.data === undefined ? {} : Promise.reject(response.data)
  72 + // }
  73 + } else if (response.statusCode == 401) {
  74 + //被迫下线重新登录
  75 + // 清空登录信息
  76 + store.commit("emptyUserInfo");
  77 + // 20秒节流,弹窗登录
  78 + uni.$u.throttle(judgeLogin(), 20000);
  79 + return new Promise(() => {});
  80 + } else {
  81 + // 如果没有显式定义custom的toast参数为false的话,默认对报错进行toast弹出提示
  82 + if (custom.toast !== false) {
  83 + uni.$u.toast(data.message || data.msg);
  84 + }
  85 + // 如果需要catch返回,则进行reject
  86 + if (custom?.catch) {
  87 + return Promise.reject(data);
  88 + } else {
  89 + // 否则返回一个pending中的promise,请求不会进入catch中
  90 + return new Promise(() => {});
  91 + }
  92 + }
  93 + },
  94 + (response) => {
  95 + // 关闭加载动画
  96 + store.commit("setLoadingShow", false);
  97 + // 对响应错误做点什么 (statusCode !== 200)
  98 + let errorData = "请检查网络或服务器";
  99 + let message = response.data?.message || response?.errMsg;
  100 + if (message == "request:fail url not in domain list") {
  101 + errorData = "检查请求域名是否添加了域名白名单";
  102 + } else if (message == "request:fail timeout") {
  103 + errorData = "请求超时:请检查网络";
  104 + } else if (message == "Token has expired") {
  105 + errorData = "Token失效,请重新登录";
  106 + uni.reLaunch({
  107 + url: "/publicLoginSubPage/public/login",
  108 + });
  109 + store.commit("emptyUserInfo");
  110 + } else if (message == "Invalid username or password") {
  111 + errorData = "用户名或者密码无效";
  112 + uni.reLaunch({
  113 + url: "/publicLoginSubPage/public/login",
  114 + });
  115 + store.commit("emptyUserInfo");
  116 + } else {
  117 + errorData = message || "请检查网络或服务器";
  118 + }
  119 + uni.$u.toast(errorData);
  120 + return Promise.reject(response);
  121 + }
  122 +);
... ...
1   -<template>
2   - <view class="device-detail-page">
3   - <!-- 公共组件-每个页面必须引入 -->
4   - <public-module></public-module>
5   - <u-sticky bgColor="#fff"><u-tabs :list="list" :current="currentTab" @click="handleTabClick"></u-tabs></u-sticky>
6   - <view style="margin-top:30rpx;">
7   - <basicInfo v-if="currentTab == 0" :deviceDetail="deviceDetail" />
8   - <realTimeData v-if="currentTab === 1" />
9   - <historyData v-if="currentTab === 2" :keys="keys" />
10   - <alarmHistory v-if="currentTab === 3" />
11   - <commondRecord v-if="currentTab === 4" />
12   - </view>
13   - <f-tabbar></f-tabbar>
14   - </view>
15   -</template>
16   -
17   -<script>
18   -import fTabbar from '@/components/module/f-tabbar/f-tabbar';
19   -import basicInfo from './tabDetail/basicInfo.vue';
20   -import realTimeData from './tabDetail/realtimeData.vue';
21   -import alarmHistory from './tabDetail/alarmHistory.vue';
22   -import historyData from './tabDetail/historyData.vue';
23   -import commondRecord from './tabDetail/commondRecord.vue';
24   -import { getDeviceKeys } from './api/index.js';
25   -export default {
26   - components: {
27   - fTabbar,
28   - basicInfo,
29   - realTimeData,
30   - alarmHistory,
31   - historyData,
32   - commondRecord
33   - },
34   - data() {
35   - return {
36   - list: [{ name: '基础信息' }, { name: '实时数据' }, { name: '历史数据' }, { name: '告警记录' }, { name: '命令记录' }],
37   - currentTab: 0,
38   - id: '',
39   - deviceDetail: {},
40   - keys:[]
41   - };
42   - },
43   - async onLoad(options) {
44   - const { id, alarmStatus, lastOnlineTime, tbDeviceId } = options;
45   - const res = await uni.$u.http.get(`/yt/device/${id}`);
46   - this.deviceDetail = { ...res, alarmStatus, lastOnlineTime };
47   -
48   - // var socketTask = uni.connectSocket({
49   - // url: 'wss://dev.thingskit.com:8080/api/ws/plugins/telemetry?token=' + uni.getStorageSync('userInfo').isToken, //仅为示例,并非真实接口地址。
50   - // complete: ()=> {}
51   - // });
52   - // uni.onSocketOpen((header)=>{
53   - // console.log('连接成功',header)
54   - // })
55   - // // socketTask.onMessage(function(data) {
56   - // // console.log('收到消息了', data);
57   - // // });
58   - // socketTask.send({
59   - // data: JSON.stringify({
60   - // attrSubCmds: [],
61   - // tsSubCmds: [
62   - // {
63   - // entityType: 'DEVICE',
64   - // entityId: id,
65   - // scope: 'LATEST_TELEMETRY',
66   - // cmdId: 1
67   - // }
68   - // ],
69   - // historyCmds: [],
70   - // entityDataCmds: [],
71   - // entityDataUnsubscribeCmds: [],
72   - // alarmDataCmds: [],
73   - // alarmDataUnsubscribeCmds: [],
74   - // entityCountCmds: [],
75   - // entityCountUnsubscribeCmds: []
76   - // }),
77   - // success() {
78   - // console.log('发送成功了');
79   - // }
80   - // });
81   -
82   -
83   - const keys = await getDeviceKeys(tbDeviceId);
84   - // 隐藏原生的tabbar'
85   - this.keys = [keys]
86   - uni.hideTabBar();
87   - },
88   - methods: {
89   - handleTabClick({ index }) {
90   - this.currentTab = index;
91   - }
92   - }
93   -};
  1 +<template>
  2 + <view class="device-detail-page">
  3 + <!-- 公共组件-每个页面必须引入 -->
  4 + <public-module></public-module>
  5 + <u-sticky bgColor="#fff"><u-tabs :list="list" :current="currentTab" @click="handleTabClick"></u-tabs></u-sticky>
  6 + <view style="margin-top:30rpx;">
  7 + <basicInfo v-if="currentTab == 0" :deviceDetail="deviceDetail" />
  8 + <realTimeData v-if="currentTab === 1" />
  9 + <historyData v-if="currentTab === 2" :keys="keys" />
  10 + <alarmHistory v-if="currentTab === 3" />
  11 + <commondRecord v-if="currentTab === 4" />
  12 + </view>
  13 + <f-tabbar></f-tabbar>
  14 + </view>
  15 +</template>
  16 +
  17 +<script>
  18 +import fTabbar from '@/components/module/f-tabbar/f-tabbar';
  19 +import basicInfo from './tabDetail/basicInfo.vue';
  20 +import realTimeData from './tabDetail/realtimeData.vue';
  21 +import alarmHistory from './tabDetail/alarmHistory.vue';
  22 +import historyData from './tabDetail/historyData.vue';
  23 +import commondRecord from './tabDetail/commondRecord.vue';
  24 +import { getDeviceKeys } from '../../pages/device/api/index';
  25 +export default {
  26 + components: {
  27 + fTabbar,
  28 + basicInfo,
  29 + realTimeData,
  30 + alarmHistory,
  31 + historyData,
  32 + commondRecord
  33 + },
  34 + data() {
  35 + return {
  36 + list: [{ name: '基础信息' }, { name: '实时数据' }, { name: '历史数据' }, { name: '告警记录' }, { name: '命令记录' }],
  37 + currentTab: 0,
  38 + id: '',
  39 + deviceDetail: {},
  40 + keys:[]
  41 + };
  42 + },
  43 + async onLoad(options) {
  44 + const { id, alarmStatus, lastOnlineTime, tbDeviceId } = options;
  45 + const res = await uni.$u.http.get(`/yt/device/${id}`);
  46 + this.deviceDetail = { ...res, alarmStatus, lastOnlineTime };
  47 +
  48 + // var socketTask = uni.connectSocket({
  49 + // url: 'wss://dev.thingskit.com:8080/api/ws/plugins/telemetry?token=' + uni.getStorageSync('userInfo').isToken, //仅为示例,并非真实接口地址。
  50 + // complete: ()=> {}
  51 + // });
  52 + // uni.onSocketOpen((header)=>{
  53 + // console.log('连接成功',header)
  54 + // })
  55 + // // socketTask.onMessage(function(data) {
  56 + // // console.log('收到消息了', data);
  57 + // // });
  58 + // socketTask.send({
  59 + // data: JSON.stringify({
  60 + // attrSubCmds: [],
  61 + // tsSubCmds: [
  62 + // {
  63 + // entityType: 'DEVICE',
  64 + // entityId: id,
  65 + // scope: 'LATEST_TELEMETRY',
  66 + // cmdId: 1
  67 + // }
  68 + // ],
  69 + // historyCmds: [],
  70 + // entityDataCmds: [],
  71 + // entityDataUnsubscribeCmds: [],
  72 + // alarmDataCmds: [],
  73 + // alarmDataUnsubscribeCmds: [],
  74 + // entityCountCmds: [],
  75 + // entityCountUnsubscribeCmds: []
  76 + // }),
  77 + // success() {
  78 + // console.log('发送成功了');
  79 + // }
  80 + // });
  81 +
  82 +
  83 + const keys = await getDeviceKeys(tbDeviceId);
  84 + // 隐藏原生的tabbar'
  85 + this.keys = [keys]
  86 + uni.hideTabBar();
  87 + },
  88 + methods: {
  89 + handleTabClick({ index }) {
  90 + this.currentTab = index;
  91 + }
  92 + }
  93 +};
94 94 </script>
... ...
deviceSubPage/deviceDetailPage/tabDetail/alarmHistory.vue renamed from pages/device/tabDetail/alarmHistory.vue
1   -<template>
2   - <view class="alert-page">
3   - <!-- 公共组件-每个页面必须引入 -->
4   - <public-module></public-module>
5   - <view style="width: 192rpx;margin: 19rpx;"><u-button @click="openSearchDialog" shape="circle" type="info" icon="search" text="筛选"></u-button></view>
6   - <view class="device-list">
7   - <view @click="openDeviceDetail(item.id)" class="list-item" v-for="(item, index) in list" :key="index">
8   - <view class="u-flex item" style="justify-content: flex-start;flex-direction: column;align-items: center;">
9   - <view style="width: 400rpx;text-align: left;">
10   - <text style="color:#333;font-size: 15px;">{{ item.name1 }}</text>
11   - </view>
12   - <view style="width: 400rpx;text-align: left;">
13   - <text style="color:#666;font-size: 15px;">{{ item.name2 }}</text>
14   - </view>
15   - <view style="width: 400rpx;text-align: left;">
16   - <text style="color:#666;font-size: 15px;">{{ item.name3 }}</text>
17   - </view>
18   - <view style="width: 400rpx;text-align: left;">
19   - <text style="color:#999;font-size: 15px;">{{ item.time }}</text>
20   - </view>
21   - </view>
22   - <view class="item">
23   - <view class="u-flex" style="margin-top: -6rpx;">
24   - <image style="width: 30rpx;height: 30rpx;margin-top: 5rpx;margin-right: 5rpx;" :src="item.name4" mode=""></image>
25   - <view>
26   - <text style="color: #377DFF;font-size: 13px;margin-left: 5rpx;margin-top: 20rpx;">{{ item.name5 }}</text>
27   - </view>
28   - </view>
29   - </view>
30   - </view>
31   - </view>
32   - <view style="height: 30rpx;"></view>
33   - <!-- 告警筛选 -->
34   - <u-popup @close="close" closeable bgColor="transparent" :overlay="true" :show="show" mode="bottom">
35   - <view style="height: 1100rpx;background:#fff;border-radius: 20rpx;overflow-y: scroll;">
36   - <view style="text-align: center;position: relative;top: 68rpx;margin-top: -40rpx;"><text style="font-size: 16px;color: #333333;">筛选条件</text></view>
37   - <view style="margin-top: 97rpx;margin-left: 43rpx;">
38   - <view style="width: 750rpx;margin-left: 14rpx;"><text style="color: #333333;font-size: 14px;">告警状态</text></view>
39   - <view
40   - class="u-flex"
41   - style="margin-top: 15rpx;width:650rpx;height: 60rpx;
42   - flex-wrap: wrap;justify-content: space-between; align-content: space-between;"
43   - >
44   - <view
45   - v-for="(item, index) in alertStatus"
46   - :key="index"
47   - style="margin: 10rpx;line-height: 50rpx;text-align: center;
48   - width:180rpx;height: 60rpx;
49   - background-color:#F6F6F6;border-radius:32px"
50   - >
51   - <text style="color:#333333;font-size: 13px;">{{ item.name }}</text>
52   - </view>
53   - </view>
54   - </view>
55   - <view style="margin-top: 145rpx;margin-left: 43rpx;">
56   - <view style="width: 750rpx;margin-left: 14rpx;"><text style="color: #333333;font-size: 14px;">设备类型</text></view>
57   - <view
58   - class="u-flex"
59   - style="margin-top: 15rpx;width:650rpx;height: 60rpx;
60   - flex-wrap: wrap;justify-content: space-between; align-content: space-between;"
61   - >
62   - <view
63   - v-for="(item, index) in deviceType"
64   - :key="index"
65   - style="margin: 10rpx;line-height: 50rpx;text-align: center;
66   - width:180rpx;height: 60rpx;
67   - background-color:#F6F6F6;border-radius:32px"
68   - >
69   - <text style="color:#333;font-size: 13px;">{{ item.name }}</text>
70   - </view>
71   - </view>
72   - </view>
73   - <view style="margin-top: 136rpx;margin-left: 43rpx;">
74   - <view style="width: 750rpx;margin-left: 14rpx;"><text style="color: #333;font-size: 14px;">告警等级</text></view>
75   - <view
76   - class="u-flex"
77   - style="margin-top: 15rpx;width:650rpx;height: 60rpx;
78   - flex-wrap: wrap;justify-content: space-between; align-content: space-between;"
79   - >
80   - <view
81   - v-for="(item, index) in alertLevel"
82   - :key="index"
83   - style="margin: 10rpx;line-height: 50rpx;text-align: center;
84   - width:180rpx;height: 60rpx;
85   - background-color:#F6F6F6;border-radius:32px"
86   - >
87   - <text style="color:#333333;font-size: 13px;">{{ item.name }}</text>
88   - </view>
89   - </view>
90   - </view>
91   - <view style="margin-top: 136rpx;margin-left: 43rpx;">
92   - <view style="width: 750rpx;margin-left: 14rpx;"><text style="color: #333333;font-size: 14px;">选择时间</text></view>
93   - <view
94   - class="u-flex"
95   - style="margin-top: 15rpx;width:650rpx;height: 60rpx;
96   - flex-wrap: wrap;justify-content: space-between; align-content: space-between;"
97   - >
98   - <view
99   - v-for="(item, index) in timeArea"
100   - :key="index"
101   - style="margin: 10rpx;line-height: 50rpx;text-align: center;
102   - width:180rpx;height: 60rpx;
103   - background-color:#F6F6F6;border-radius:32px"
104   - >
105   - <text style="color:#333333;font-size: 13px;">{{ item.name }}</text>
106   - </view>
107   - </view>
108   - </view>
109   - <view style="margin-top: 136rpx;margin-left: 43rpx;">
110   - <view class="u-flex" style="margin-left: 10rpx;margin-top: 15rpx;width:750rpx;height: 60rpx;">
111   - <u--form labelPosition="left" :model="timeData" :rules="rules" ref="form1" style="padding-left: 26rpx;width: 617rpx!important;">
112   - <u-form-item
113   - style="font-size: 14px;"
114   - label="选择日期"
115   - prop="selectTime"
116   - labelWidth="80"
117   - borderBottom
118   - @click="
119   - showCalendar = true;
120   - hideKeyboard();
121   - "
122   - >
123   - <u--input v-model="timeData.selectTime" placeholder="请选择日期" border="none"></u--input>
124   - </u-form-item>
125   - </u--form>
126   - </view>
127   - </view>
128   - <view class="u-flex" style="margin-top: 128rpx;margin-left: 55rpx;">
129   - <view style="width: 300rpx"><u-button type="info" shape="circle" text="重置"></u-button></view>
130   - <view style="width: 300rpx;margin-left:46rpx ;"><u-button type="primary" shape="circle" text="确认"></u-button></view>
131   - </view>
132   - <view style="height: 30rpx;"></view>
133   - </view>
134   - </u-popup>
135   - <u-calendar
136   - :show="showCalendar"
137   - mode="range"
138   - @confirm="calendarConfirm"
139   - @close="calendarClose"
140   - startText="开始时间"
141   - endText="结束时间"
142   - confirmDisabledText="请选择日期"
143   - :formatter="formatter"
144   - ></u-calendar>
145   - <f-tabbar :isFillHeight="false"></f-tabbar>
146   - </view>
147   -</template>
148   -
149   -<script>
150   -import fTabbar from '@/components/module/f-tabbar/f-tabbar';
151   -export default {
152   - components: {
153   - fTabbar
154   - },
155   - data() {
156   - return {
157   - show: false,
158   - timeData: {
159   - selectTime: '',
160   - getTimeGap: ''
161   - },
162   - showCalendar: false,
163   - alertStatus: [
164   - {
165   - index: 1,
166   - name: '全部',
167   - bgColor: '#377DFF',
168   - textColor: '#377DFF'
169   - },
170   - {
171   - index: 2,
172   - name: '激活未确认',
173   - bgColor: '#F6F6F6',
174   - textColor: '#F6F6F6'
175   - },
176   - {
177   - index: 3,
178   - name: '激活已确认',
179   - bgColor: '#F6F6F6',
180   - textColor: '#F6F6F6'
181   - },
182   - {
183   - index: 4,
184   - name: '清除未确认',
185   - bgColor: '#F6F6F6',
186   - textColor: '#F6F6F6'
187   - },
188   - {
189   - index: 5,
190   - name: '清除已确认',
191   - bgColor: '#F6F6F6',
192   - textColor: '#F6F6F6'
193   - },
194   - {
195   - index: 6,
196   - name: '清除已确认',
197   - bgColor: '#F6F6F6',
198   - textColor: '#F6F6F6'
199   - }
200   - ],
201   - deviceType: [
202   - {
203   - index: 1,
204   - name: '全部',
205   - bgColor: '#377DFF',
206   - textColor: '#377DFF'
207   - },
208   - {
209   - index: 2,
210   - name: '网关设备',
211   - bgColor: '#F6F6F6',
212   - textColor: '#F6F6F6'
213   - },
214   - {
215   - index: 3,
216   - name: '网关子设备',
217   - bgColor: '#F6F6F6',
218   - textColor: '#F6F6F6'
219   - },
220   - {
221   - index: 4,
222   - name: '直连设备',
223   - bgColor: '#F6F6F6',
224   - textColor: '#F6F6F6'
225   - }
226   - ],
227   - alertLevel: [
228   - {
229   - index: 1,
230   - name: '全部',
231   - bgColor: '#377DFF',
232   - textColor: '#377DFF'
233   - },
234   - {
235   - index: 2,
236   - name: '危险',
237   - bgColor: '#F6F6F6',
238   - textColor: '#F6F6F6'
239   - },
240   - {
241   - index: 3,
242   - name: '重要',
243   - bgColor: '#F6F6F6',
244   - textColor: '#F6F6F6'
245   - },
246   - {
247   - index: 4,
248   - name: '次要',
249   - bgColor: '#F6F6F6',
250   - textColor: '#F6F6F6'
251   - },
252   - {
253   - index: 4,
254   - name: '警告',
255   - bgColor: '#F6F6F6',
256   - textColor: '#F6F6F6'
257   - },
258   - {
259   - index: 4,
260   - name: '不确定',
261   - bgColor: '#F6F6F6',
262   - textColor: '#F6F6F6'
263   - }
264   - ],
265   - timeArea: [
266   - {
267   - index: 1,
268   - name: '全部',
269   - value: '全部',
270   - bgColor: '#F6F6F6',
271   - textColor: '#F6F6F6'
272   - },
273   - {
274   - index: 2,
275   - name: '30分钟',
276   - value: '30',
277   - bgColor: '#F6F6F6',
278   - textColor: '#F6F6F6'
279   - },
280   - {
281   - index: 3,
282   - name: '1小时',
283   - value: '30',
284   - bgColor: '#F6F6F6',
285   - textColor: '#F6F6F6'
286   - },
287   - {
288   - index: 4,
289   - name: '2小时',
290   - value: '120',
291   - bgColor: '#F6F6F6',
292   - textColor: '#F6F6F6'
293   - },
294   - {
295   - index: 5,
296   - name: '近一天',
297   - value: '24',
298   - bgColor: '#F6F6F6',
299   - textColor: '#F6F6F6'
300   - },
301   - {
302   - index: 6,
303   - name: '',
304   - value: '',
305   - bgColor: '#F6F6F6',
306   - textColor: '#F6F6F6'
307   - }
308   - ],
309   - list: [
310   - {
311   - name1: '1号楼1楼三单元水表',
312   - name2: 'CO₂:65.32',
313   - name3: '告警状态:清除已确认',
314   - name4: '../../../static/danger.png',
315   - name5: '危险',
316   - time: '2022-04-01 02:12:23',
317   - id: 'xx1'
318   - },
319   - {
320   - name1: '2号楼1楼三单元水表',
321   - name2: 'PH:9.8',
322   - name3: '告警状态:激活未确认',
323   - name4: '../../../static/major.png',
324   - name5: '重要',
325   - time: '2022-04-01 02:12:23',
326   - id: 'xx2'
327   - },
328   - {
329   - name1: '3号楼1楼三单元水表',
330   - name2: 'NH3:600',
331   - name3: '告警状态:激活未确认',
332   - name4: '../../../static/secondary.png',
333   - name5: '次要',
334   - time: '2022-04-01 02:12:23',
335   - id: 'xx3'
336   - },
337   - {
338   - name1: '4号楼1楼三单元水表',
339   - name2: '水深:1.4',
340   - name3: '告警状态:激活未确认',
341   - name4: '../../../static/secondary.png',
342   - name5: '次要',
343   - time: '2022-04-01 02:12:23',
344   - id: 'xx4'
345   - },
346   - {
347   - name1: '5号楼1楼三单元水表',
348   - name2: 'COD:125',
349   - name3: '告警状态:激活未确认',
350   - name4: '../../../static/noshue.png',
351   - name5: '不确定',
352   - time: '2022-04-01 02:12:23',
353   - id: 'xx5'
354   - }
355   - ]
356   - };
357   - },
358   - onLoad(e) {
359   - // 隐藏原生的tabbar
360   - uni.hideTabBar();
361   - },
362   - methods: {
363   - open() {},
364   - close() {
365   - this.show = false;
366   - },
367   - openSearchDialog() {
368   - this.show = true;
369   - },
370   - hideKeyboard() {
371   - uni.hideKeyboard();
372   - },
373   - calendarConfirm(e) {
374   - this.showCalendar = false;
375   - this.timeData.selectTime = `${e[0]} / ${e[e.length - 1]}`;
376   - },
377   - calendarClose() {
378   - this.showCalendar = false;
379   - }
380   - }
381   -};
382   -</script>
383   -
384   -<style lang="scss" scoped>
385   -.alert-page {
386   - margin-top: -39rpx;
387   -}
388   -.device-list {
389   - display: flex;
390   - flex-direction: column;
391   - padding-left: 18rpx;
392   - margin-top: -18rpx;
393   - .list-item {
394   - width: 713rpx;
395   - height: 233rpx;
396   - background-color: #fff;
397   - margin-top: 24rpx;
398   - display: flex;
399   -
400   - border-radius: 10px;
401   - justify-content: space-between;
402   - .item {
403   - margin: 30rpx;
404   - }
405   - }
406   -}
  1 +<template>
  2 + <view class="alert-page">
  3 + <!-- 公共组件-每个页面必须引入 -->
  4 + <public-module></public-module>
  5 + <view style="width: 192rpx;margin: 19rpx;"><u-button @click="openSearchDialog" shape="circle" type="info" icon="search" text="筛选"></u-button></view>
  6 + <view class="device-list">
  7 + <view @click="openDeviceDetail(item.id)" class="list-item" v-for="(item, index) in list" :key="index">
  8 + <view class="u-flex item" style="justify-content: flex-start;flex-direction: column;align-items: center;">
  9 + <view style="width: 400rpx;text-align: left;">
  10 + <text style="color:#333;font-size: 15px;">{{ item.name1 }}</text>
  11 + </view>
  12 + <view style="width: 400rpx;text-align: left;">
  13 + <text style="color:#666;font-size: 15px;">{{ item.name2 }}</text>
  14 + </view>
  15 + <view style="width: 400rpx;text-align: left;">
  16 + <text style="color:#666;font-size: 15px;">{{ item.name3 }}</text>
  17 + </view>
  18 + <view style="width: 400rpx;text-align: left;">
  19 + <text style="color:#999;font-size: 15px;">{{ item.time }}</text>
  20 + </view>
  21 + </view>
  22 + <view class="item">
  23 + <view class="u-flex" style="margin-top: -6rpx;">
  24 + <image style="width: 30rpx;height: 30rpx;margin-top: 5rpx;margin-right: 5rpx;" :src="item.name4" mode=""></image>
  25 + <view>
  26 + <text style="color: #377DFF;font-size: 13px;margin-left: 5rpx;margin-top: 20rpx;">{{ item.name5 }}</text>
  27 + </view>
  28 + </view>
  29 + </view>
  30 + </view>
  31 + </view>
  32 + <view style="height: 30rpx;"></view>
  33 + <!-- 告警筛选 -->
  34 + <u-popup @close="close" closeable bgColor="transparent" :overlay="true" :show="show" mode="bottom">
  35 + <view style="height: 1100rpx;background:#fff;border-radius: 20rpx;overflow-y: scroll;">
  36 + <view style="text-align: center;position: relative;top: 68rpx;margin-top: -40rpx;"><text style="font-size: 16px;color: #333333;">筛选条件</text></view>
  37 + <view style="margin-top: 97rpx;margin-left: 43rpx;">
  38 + <view style="width: 750rpx;margin-left: 14rpx;"><text style="color: #333333;font-size: 14px;">告警状态</text></view>
  39 + <view
  40 + class="u-flex"
  41 + style="margin-top: 15rpx;width:650rpx;height: 60rpx;
  42 + flex-wrap: wrap;justify-content: space-between; align-content: space-between;"
  43 + >
  44 + <view
  45 + v-for="(item, index) in alertStatus"
  46 + :key="index"
  47 + style="margin: 10rpx;line-height: 50rpx;text-align: center;
  48 + width:180rpx;height: 60rpx;
  49 + background-color:#F6F6F6;border-radius:32px"
  50 + >
  51 + <text style="color:#333333;font-size: 13px;">{{ item.name }}</text>
  52 + </view>
  53 + </view>
  54 + </view>
  55 + <view style="margin-top: 145rpx;margin-left: 43rpx;">
  56 + <view style="width: 750rpx;margin-left: 14rpx;"><text style="color: #333333;font-size: 14px;">设备类型</text></view>
  57 + <view
  58 + class="u-flex"
  59 + style="margin-top: 15rpx;width:650rpx;height: 60rpx;
  60 + flex-wrap: wrap;justify-content: space-between; align-content: space-between;"
  61 + >
  62 + <view
  63 + v-for="(item, index) in deviceType"
  64 + :key="index"
  65 + style="margin: 10rpx;line-height: 50rpx;text-align: center;
  66 + width:180rpx;height: 60rpx;
  67 + background-color:#F6F6F6;border-radius:32px"
  68 + >
  69 + <text style="color:#333;font-size: 13px;">{{ item.name }}</text>
  70 + </view>
  71 + </view>
  72 + </view>
  73 + <view style="margin-top: 136rpx;margin-left: 43rpx;">
  74 + <view style="width: 750rpx;margin-left: 14rpx;"><text style="color: #333;font-size: 14px;">告警等级</text></view>
  75 + <view
  76 + class="u-flex"
  77 + style="margin-top: 15rpx;width:650rpx;height: 60rpx;
  78 + flex-wrap: wrap;justify-content: space-between; align-content: space-between;"
  79 + >
  80 + <view
  81 + v-for="(item, index) in alertLevel"
  82 + :key="index"
  83 + style="margin: 10rpx;line-height: 50rpx;text-align: center;
  84 + width:180rpx;height: 60rpx;
  85 + background-color:#F6F6F6;border-radius:32px"
  86 + >
  87 + <text style="color:#333333;font-size: 13px;">{{ item.name }}</text>
  88 + </view>
  89 + </view>
  90 + </view>
  91 + <view style="margin-top: 136rpx;margin-left: 43rpx;">
  92 + <view style="width: 750rpx;margin-left: 14rpx;"><text style="color: #333333;font-size: 14px;">选择时间</text></view>
  93 + <view
  94 + class="u-flex"
  95 + style="margin-top: 15rpx;width:650rpx;height: 60rpx;
  96 + flex-wrap: wrap;justify-content: space-between; align-content: space-between;"
  97 + >
  98 + <view
  99 + v-for="(item, index) in timeArea"
  100 + :key="index"
  101 + style="margin: 10rpx;line-height: 50rpx;text-align: center;
  102 + width:180rpx;height: 60rpx;
  103 + background-color:#F6F6F6;border-radius:32px"
  104 + >
  105 + <text style="color:#333333;font-size: 13px;">{{ item.name }}</text>
  106 + </view>
  107 + </view>
  108 + </view>
  109 + <view style="margin-top: 136rpx;margin-left: 43rpx;">
  110 + <view class="u-flex" style="margin-left: 10rpx;margin-top: 15rpx;width:750rpx;height: 60rpx;">
  111 + <u--form labelPosition="left" :model="timeData" :rules="rules" ref="form1" style="padding-left: 26rpx;width: 617rpx!important;">
  112 + <u-form-item
  113 + style="font-size: 14px;"
  114 + label="选择日期"
  115 + prop="selectTime"
  116 + labelWidth="80"
  117 + borderBottom
  118 + @click="
  119 + showCalendar = true;
  120 + hideKeyboard();
  121 + "
  122 + >
  123 + <u--input v-model="timeData.selectTime" placeholder="请选择日期" border="none"></u--input>
  124 + </u-form-item>
  125 + </u--form>
  126 + </view>
  127 + </view>
  128 + <view class="u-flex" style="margin-top: 128rpx;margin-left: 55rpx;">
  129 + <view style="width: 300rpx"><u-button type="info" shape="circle" text="重置"></u-button></view>
  130 + <view style="width: 300rpx;margin-left:46rpx ;"><u-button type="primary" shape="circle" text="确认"></u-button></view>
  131 + </view>
  132 + <view style="height: 30rpx;"></view>
  133 + </view>
  134 + </u-popup>
  135 + <u-calendar
  136 + :show="showCalendar"
  137 + mode="range"
  138 + @confirm="calendarConfirm"
  139 + @close="calendarClose"
  140 + startText="开始时间"
  141 + endText="结束时间"
  142 + confirmDisabledText="请选择日期"
  143 + :formatter="formatter"
  144 + ></u-calendar>
  145 + <f-tabbar :isFillHeight="false"></f-tabbar>
  146 + </view>
  147 +</template>
  148 +
  149 +<script>
  150 +import fTabbar from '@/components/module/f-tabbar/f-tabbar';
  151 +export default {
  152 + components: {
  153 + fTabbar
  154 + },
  155 + data() {
  156 + return {
  157 + show: false,
  158 + timeData: {
  159 + selectTime: '',
  160 + getTimeGap: ''
  161 + },
  162 + showCalendar: false,
  163 + alertStatus: [
  164 + {
  165 + index: 1,
  166 + name: '全部',
  167 + bgColor: '#377DFF',
  168 + textColor: '#377DFF'
  169 + },
  170 + {
  171 + index: 2,
  172 + name: '激活未确认',
  173 + bgColor: '#F6F6F6',
  174 + textColor: '#F6F6F6'
  175 + },
  176 + {
  177 + index: 3,
  178 + name: '激活已确认',
  179 + bgColor: '#F6F6F6',
  180 + textColor: '#F6F6F6'
  181 + },
  182 + {
  183 + index: 4,
  184 + name: '清除未确认',
  185 + bgColor: '#F6F6F6',
  186 + textColor: '#F6F6F6'
  187 + },
  188 + {
  189 + index: 5,
  190 + name: '清除已确认',
  191 + bgColor: '#F6F6F6',
  192 + textColor: '#F6F6F6'
  193 + },
  194 + {
  195 + index: 6,
  196 + name: '清除已确认',
  197 + bgColor: '#F6F6F6',
  198 + textColor: '#F6F6F6'
  199 + }
  200 + ],
  201 + deviceType: [
  202 + {
  203 + index: 1,
  204 + name: '全部',
  205 + bgColor: '#377DFF',
  206 + textColor: '#377DFF'
  207 + },
  208 + {
  209 + index: 2,
  210 + name: '网关设备',
  211 + bgColor: '#F6F6F6',
  212 + textColor: '#F6F6F6'
  213 + },
  214 + {
  215 + index: 3,
  216 + name: '网关子设备',
  217 + bgColor: '#F6F6F6',
  218 + textColor: '#F6F6F6'
  219 + },
  220 + {
  221 + index: 4,
  222 + name: '直连设备',
  223 + bgColor: '#F6F6F6',
  224 + textColor: '#F6F6F6'
  225 + }
  226 + ],
  227 + alertLevel: [
  228 + {
  229 + index: 1,
  230 + name: '全部',
  231 + bgColor: '#377DFF',
  232 + textColor: '#377DFF'
  233 + },
  234 + {
  235 + index: 2,
  236 + name: '危险',
  237 + bgColor: '#F6F6F6',
  238 + textColor: '#F6F6F6'
  239 + },
  240 + {
  241 + index: 3,
  242 + name: '重要',
  243 + bgColor: '#F6F6F6',
  244 + textColor: '#F6F6F6'
  245 + },
  246 + {
  247 + index: 4,
  248 + name: '次要',
  249 + bgColor: '#F6F6F6',
  250 + textColor: '#F6F6F6'
  251 + },
  252 + {
  253 + index: 4,
  254 + name: '警告',
  255 + bgColor: '#F6F6F6',
  256 + textColor: '#F6F6F6'
  257 + },
  258 + {
  259 + index: 4,
  260 + name: '不确定',
  261 + bgColor: '#F6F6F6',
  262 + textColor: '#F6F6F6'
  263 + }
  264 + ],
  265 + timeArea: [
  266 + {
  267 + index: 1,
  268 + name: '全部',
  269 + value: '全部',
  270 + bgColor: '#F6F6F6',
  271 + textColor: '#F6F6F6'
  272 + },
  273 + {
  274 + index: 2,
  275 + name: '30分钟',
  276 + value: '30',
  277 + bgColor: '#F6F6F6',
  278 + textColor: '#F6F6F6'
  279 + },
  280 + {
  281 + index: 3,
  282 + name: '1小时',
  283 + value: '30',
  284 + bgColor: '#F6F6F6',
  285 + textColor: '#F6F6F6'
  286 + },
  287 + {
  288 + index: 4,
  289 + name: '2小时',
  290 + value: '120',
  291 + bgColor: '#F6F6F6',
  292 + textColor: '#F6F6F6'
  293 + },
  294 + {
  295 + index: 5,
  296 + name: '近一天',
  297 + value: '24',
  298 + bgColor: '#F6F6F6',
  299 + textColor: '#F6F6F6'
  300 + },
  301 + {
  302 + index: 6,
  303 + name: '',
  304 + value: '',
  305 + bgColor: '#F6F6F6',
  306 + textColor: '#F6F6F6'
  307 + }
  308 + ],
  309 + list: [
  310 + {
  311 + name1: '1号楼1楼三单元水表',
  312 + name2: 'CO₂:65.32',
  313 + name3: '告警状态:清除已确认',
  314 + name4: '../../../static/danger.png',
  315 + name5: '危险',
  316 + time: '2022-04-01 02:12:23',
  317 + id: 'xx1'
  318 + },
  319 + {
  320 + name1: '2号楼1楼三单元水表',
  321 + name2: 'PH:9.8',
  322 + name3: '告警状态:激活未确认',
  323 + name4: '../../../static/major.png',
  324 + name5: '重要',
  325 + time: '2022-04-01 02:12:23',
  326 + id: 'xx2'
  327 + },
  328 + {
  329 + name1: '3号楼1楼三单元水表',
  330 + name2: 'NH3:600',
  331 + name3: '告警状态:激活未确认',
  332 + name4: '../../../static/secondary.png',
  333 + name5: '次要',
  334 + time: '2022-04-01 02:12:23',
  335 + id: 'xx3'
  336 + },
  337 + {
  338 + name1: '4号楼1楼三单元水表',
  339 + name2: '水深:1.4',
  340 + name3: '告警状态:激活未确认',
  341 + name4: '../../../static/secondary.png',
  342 + name5: '次要',
  343 + time: '2022-04-01 02:12:23',
  344 + id: 'xx4'
  345 + },
  346 + {
  347 + name1: '5号楼1楼三单元水表',
  348 + name2: 'COD:125',
  349 + name3: '告警状态:激活未确认',
  350 + name4: '../../../static/noshue.png',
  351 + name5: '不确定',
  352 + time: '2022-04-01 02:12:23',
  353 + id: 'xx5'
  354 + }
  355 + ]
  356 + };
  357 + },
  358 + onLoad(e) {
  359 + // 隐藏原生的tabbar
  360 + uni.hideTabBar();
  361 + },
  362 + methods: {
  363 + open() {},
  364 + close() {
  365 + this.show = false;
  366 + },
  367 + openSearchDialog() {
  368 + this.show = true;
  369 + },
  370 + hideKeyboard() {
  371 + uni.hideKeyboard();
  372 + },
  373 + calendarConfirm(e) {
  374 + this.showCalendar = false;
  375 + this.timeData.selectTime = `${e[0]} / ${e[e.length - 1]}`;
  376 + },
  377 + calendarClose() {
  378 + this.showCalendar = false;
  379 + }
  380 + }
  381 +};
  382 +</script>
  383 +
  384 +<style lang="scss" scoped>
  385 +.alert-page {
  386 + margin-top: -39rpx;
  387 +}
  388 +.device-list {
  389 + display: flex;
  390 + flex-direction: column;
  391 + padding-left: 18rpx;
  392 + margin-top: -18rpx;
  393 + .list-item {
  394 + width: 713rpx;
  395 + height: 233rpx;
  396 + background-color: #fff;
  397 + margin-top: 24rpx;
  398 + display: flex;
  399 +
  400 + border-radius: 10px;
  401 + justify-content: space-between;
  402 + .item {
  403 + margin: 30rpx;
  404 + }
  405 + }
  406 +}
407 407 </style>
... ...
deviceSubPage/deviceDetailPage/tabDetail/basicInfo.vue renamed from pages/device/tabDetail/basicInfo.vue
1   -<template>
2   - <view class="basic-page">
3   - <!-- 公共组件-每个页面必须引入 -->
4   - <public-module />
5   - <view class="u-flex" style="justify-content: space-between;height: 140rpx;background-color: #fff;border-radius: 18px;">
6   - <view class="u-flex">
7   - <view style="margin-left: 20rpx;">
8   - {{deviceDetail.name}}
9   - </view>
10   - <view style="margin-left: 20rpx; font-size: 14px;" :style="{color:deviceDetail.deviceState==='INACTIVE'?'#666':deviceDetail.deviceState==='ONLINE'?'#377DFF':'#DE4437'}">
11   - {{deviceDetail.deviceState==='INACTIVE'?'未激活':deviceDetail.deviceState==='ONLINE'?'在线':'离线'}}
12   - </view>
13   - </view>
14   - <view style="margin-right: 20rpx;">
15   - <u-button type="primary" shape="circle" size="mini" text="下发命令" @click="showModal"/>
16   - </view>
17   - </view>
18   - <view style="margin-top: 40rpx;height: 577rpx;background-color: #fff;border-radius: 20px;">
19   - <u-list>
20   - <u-list-item>
21   -
22   - <u-cell :title="deviceDetail.sn">
23   - <view slot="icon">设备编号</view>
24   - </u-cell>
25   - </u-list-item>
26   - <u-list-item>
27   - <u-cell :title="deviceType">
28   - <view slot="icon">设备类型</view>
29   - </u-cell>
30   - </u-list-item>
31   - <u-list-item>
32   - <u-cell :title="deviceDetail.organizationDTO.name">
33   - <view slot="icon">所属组织</view>
34   - </u-cell>
35   - </u-list-item>
36   - <u-list-item>
37   - <u-cell :title="formatLastOnlineTime">
38   - <view slot="icon">最后连接时间</view>
39   - </u-cell>
40   - </u-list-item>
41   - <u-list-item>
42   - <u-cell :title="alarmStatus">
43   - <view slot="icon">是否告警</view>
44   - </u-cell>
45   - </u-list-ite>
46   - <u-cell :title="deviceDetail.description">
47   - <view slot="icon">设备描述</view>
48   - </u-cell>
49   - </u-list-item>
50   - </u-list>
51   - </view>
52   - <!-- 下发指令 -->
53   - <u-modal :show="showModel" title="命令下发" closeOnClickOverlay showCancelButton @close="hiddenModal" @cancel="hiddenModal" @confirm="handleConfirm" >
54   - <u--textarea placeholder="请输入命令内容" v-model="formModel.intro" count />
55   - </u-modal>
56   - <f-tabbar />
57   - </view>
58   -</template>
59   -
60   -<script>
61   -import {formatToDate} from '@/plugins/utils.js';
62   -export default {
63   - props:{
64   - deviceDetail:{
65   - type:Object,
66   - default:()=>({}),
67   - }
68   - },
69   - data() {
70   - return {
71   - showModel: false,
72   - };
73   - },
74   - computed:{
75   - deviceType(){
76   - return this.deviceDetail.deviceType==='DIRECT_CONNECTION'?'直连设备':this.deviceDetail.deviceType==='GATEWAY'?'网关设备':this.deviceDetail.deviceType==='SENSOR'?'网关子设备':''
77   - },
78   - alarmStatus(){
79   - return this.deviceDetail.alarmStatus === '0'?'否':'是'
80   - },
81   - formatLastOnlineTime(){
82   - return formatToDate(Number(this.deviceDetail.lastOnlineTime),'YYYY-MM-DD HH:mm:ss')
83   - }
84   - },
85   - onLoad(e) {
86   - // 隐藏原生的tabbar
87   - uni.hideTabBar();
88   - },
89   - onMounted(){
90   - console.log(this.deviceDetail)
91   -
92   - },
93   - methods: {
94   - showModal() {
95   - this.showModel = true;
96   - },
97   - hiddenModal(){
98   - this.showModel = false;
99   - },
100   - handleConfirm(){
101   - console.log('确定')
102   - }
103   - }
104   -};
105   -</script>
  1 +<template>
  2 + <view class="basic-page">
  3 + <!-- 公共组件-每个页面必须引入 -->
  4 + <public-module />
  5 + <view class="u-flex" style="justify-content: space-between;height: 140rpx;background-color: #fff;border-radius: 18px;">
  6 + <view class="u-flex">
  7 + <view style="margin-left: 20rpx;">
  8 + {{deviceDetail.name}}
  9 + </view>
  10 + <view style="margin-left: 20rpx; font-size: 14px;" :style="{color:deviceDetail.deviceState==='INACTIVE'?'#666':deviceDetail.deviceState==='ONLINE'?'#377DFF':'#DE4437'}">
  11 + {{deviceDetail.deviceState==='INACTIVE'?'未激活':deviceDetail.deviceState==='ONLINE'?'在线':'离线'}}
  12 + </view>
  13 + </view>
  14 + <view style="margin-right: 20rpx;">
  15 + <u-button type="primary" shape="circle" size="mini" text="下发命令" @click="showModal"/>
  16 + </view>
  17 + </view>
  18 + <view style="margin-top: 40rpx;height: 577rpx;background-color: #fff;border-radius: 20px;">
  19 + <u-list>
  20 + <u-list-item>
  21 +
  22 + <u-cell :title="deviceDetail.sn">
  23 + <view slot="icon">设备编号</view>
  24 + </u-cell>
  25 + </u-list-item>
  26 + <u-list-item>
  27 + <u-cell :title="deviceType">
  28 + <view slot="icon">设备类型</view>
  29 + </u-cell>
  30 + </u-list-item>
  31 + <u-list-item>
  32 + <u-cell :title="deviceDetail.organizationDTO.name">
  33 + <view slot="icon">所属组织</view>
  34 + </u-cell>
  35 + </u-list-item>
  36 + <u-list-item>
  37 + <u-cell :title="formatLastOnlineTime">
  38 + <view slot="icon">最后连接时间</view>
  39 + </u-cell>
  40 + </u-list-item>
  41 + <u-list-item>
  42 + <u-cell :title="alarmStatus">
  43 + <view slot="icon">是否告警</view>
  44 + </u-cell>
  45 + </u-list-ite>
  46 + <u-cell :title="deviceDetail.description">
  47 + <view slot="icon">设备描述</view>
  48 + </u-cell>
  49 + </u-list-item>
  50 + </u-list>
  51 + </view>
  52 + <!-- 下发指令 -->
  53 + <u-modal :show="showModel" title="命令下发" closeOnClickOverlay showCancelButton @close="hiddenModal" @cancel="hiddenModal" @confirm="handleConfirm" >
  54 + <u--textarea placeholder="请输入命令内容" v-model="formModel.intro" count />
  55 + </u-modal>
  56 + <f-tabbar />
  57 + </view>
  58 +</template>
  59 +
  60 +<script>
  61 +import {formatToDate} from '@/plugins/utils.js';
  62 +export default {
  63 + props:{
  64 + deviceDetail:{
  65 + type:Object,
  66 + default:()=>({}),
  67 + }
  68 + },
  69 + data() {
  70 + return {
  71 + showModel: false,
  72 + };
  73 + },
  74 + computed:{
  75 + deviceType(){
  76 + return this.deviceDetail.deviceType==='DIRECT_CONNECTION'?'直连设备':this.deviceDetail.deviceType==='GATEWAY'?'网关设备':this.deviceDetail.deviceType==='SENSOR'?'网关子设备':''
  77 + },
  78 + alarmStatus(){
  79 + return this.deviceDetail.alarmStatus === '0'?'否':'是'
  80 + },
  81 + formatLastOnlineTime(){
  82 + return formatToDate(Number(this.deviceDetail.lastOnlineTime),'YYYY-MM-DD HH:mm:ss')
  83 + }
  84 + },
  85 + onLoad(e) {
  86 + // 隐藏原生的tabbar
  87 + uni.hideTabBar();
  88 + },
  89 + onMounted(){
  90 + console.log(this.deviceDetail)
  91 +
  92 + },
  93 + methods: {
  94 + showModal() {
  95 + this.showModel = true;
  96 + },
  97 + hiddenModal(){
  98 + this.showModel = false;
  99 + },
  100 + handleConfirm(){
  101 + console.log('确定')
  102 + }
  103 + }
  104 +};
  105 +</script>
... ...
deviceSubPage/deviceDetailPage/tabDetail/commondRecord.vue renamed from pages/device/tabDetail/commondRecord.vue
deviceSubPage/deviceDetailPage/tabDetail/historyData.vue renamed from pages/device/tabDetail/historyData.vue
1   -<template>
2   - <view class="historyData">
3   - <!-- 公共组件-每个页面必须引入 -->
4   - <public-module></public-module>
5   - <view class="historyData-top">
6   - <u-form :label-style="{ 'font-size': '0rpx' }">
7   - <u-form-item @click="openCalendar">
8   - <u-input v-model="timeData.selectTime" disabled disabledColor="#fff" placeholder="请选择日期" border="none">
9   - <template slot="prefix">
10   - <image class="icon" src="../../../static/can-der.png"></image>
11   - </template>
12   - </u-input>
13   - </u-form-item>
14   - <u-form-item @click="openTimeGap">
15   - <u-input v-model="timeData.getTimeGap" disabled disabledColor="#fff" placeholder="请选择时间区间" border="none">
16   - <template slot="prefix">
17   - <image class="icon" src="../../../static/time.png"></image>
18   - </template>
19   - </u-input>
20   - </u-form-item>
21   - <u-form-item @click="openType"><u-input shape="circle" v-model="timeData.getType" placeholder="请选择属性" disabled disabledColor="#377DFF0D" /></u-form-item>
22   - </u-form>
23   - <!-- <qiun-data-charts type="tarea" :chartData="chartData" canvas2d /> -->
24   - </view>
25   - <view class="historyData-bottom">
26   - <view class="table">
27   - <view class="tr bg-w">
28   - <view class="th">变量值</view>
29   - <view class="th">更新时间</view>
30   - </view>
31   - <view class="tr bg-g">
32   - <view class="td">10</view>
33   - <view class="td">2022-03-01 18:16:33</view>
34   - </view>
35   -
36   - </view>
37   - </view>
38   - <u-calendar
39   - :show="showCalendar"
40   - closeOnClickOverlay
41   - mode="range"
42   - startText="开始时间"
43   - endText="结束时间"
44   - confirmDisabledText="请选择日期"
45   - @confirm="calendarConfirm"
46   - @close="calendarClose"
47   - ></u-calendar>
48   - <u-picker :show="showTimeGap" :columns="columns" keyName="label" closeOnClickOverlay @confirm="confirmTimeGap" @cancel="cancelTimeGap" @close="cancelTimeGap"></u-picker>
49   - <u-picker :show="showSelectType" :columns="keys" closeOnClickOverlay @confirm="confirmTypeGap" @cancel="cancelTypeGap" @close="cancelTypeGap"></u-picker>
50   - <f-tabbar></f-tabbar>
51   - </view>
52   -</template>
53   -
54   -<script>
55   -import fTabbar from '@/components/module/f-tabbar/f-tabbar';
56   -import qiunDataCharts from '@/uni_modules/qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue';
57   -import { getDeviceKeys, getHistroyData } from '../api/index.js';
58   -export default {
59   - components: {
60   - fTabbar,
61   - qiunDataCharts
62   - },
63   - props:{
64   - keys:{
65   - type:Array,
66   - default:()=>[]
67   - }
68   - },
69   - data() {
70   - return {
71   - showCalendar: false,
72   - showTimeGap: false,
73   - showSelectType: false,
74   - columns: [
75   - [
76   - {
77   - label: '5分钟',
78   - value: 300
79   - },
80   - {
81   - label: '10分钟',
82   - value: 600
83   - },
84   - {
85   - label: '15分钟',
86   - value: 900
87   - },
88   - {
89   - label: '30分钟',
90   - value: 1800
91   - },
92   - {
93   - label: '1小时',
94   - value: 3600
95   - },
96   - {
97   - label: '2小时',
98   - value: 7200
99   - },
100   - {
101   - label: '6小时',
102   - value: 21600
103   - }
104   - ]
105   - ],
106   - timeData: {
107   - selectTime: '',
108   - getTimeGap: '',
109   - getType: ''
110   - }
111   - };
112   - },
113   - methods: {
114   - openCalendar() {
115   - this.showCalendar = true;
116   - },
117   - openTimeGap() {
118   - this.showTimeGap = true;
119   - },
120   - openType() {
121   - this.showSelectType = true;
122   - },
123   - calendarConfirm(date) {
124   - this.showCalendar = false;
125   - this.timeData.selectTime = `${date[0]} 至 ${date[1]}`;
126   - },
127   - calendarClose() {
128   - this.showCalendar = false;
129   - },
130   - confirmTimeGap(time) {
131   - this.showTimeGap = false;
132   - this.timeData.getTimeGap = time.value[0].label;
133   - },
134   -
135   - cancelTimeGap() {
136   - this.showTimeGap = false;
137   - },
138   - confirmTypeGap(time) {
139   - this.showSelectType = false;
140   - this.timeData.getType = time.value[0];
141   - },
142   - cancelTypeGap() {
143   - this.showSelectType = false;
144   - }
145   - }
146   -};
147   -</script>
148   -
149   -<style lang="scss" scoped>
150   -.historyData {
151   - margin: 30rpx;
152   - .historyData-top {
153   - padding: 30rpx;
154   - background-color: #fff;
155   - height: 870rpx;
156   - border-radius: 20rpx;
157   - .icon {
158   - width: 28rpx;
159   - height: 28rpx;
160   - margin-right: 15rpx;
161   - }
162   - }
163   - .historyData-bottom {
164   - margin-top: 30rpx;
165   - background-color: #fff;
166   - border-radius: 20rpx;
167   - .table {
168   - border: 0px solid darkgray;
169   - .tr {
170   - display: flex;
171   - width: 100%;
172   - justify-content: center;
173   - height: 3rem;
174   - align-items: center;
175   - .th {
176   - display: flex;
177   - justify-content: center;
178   - align-items: center;
179   - width: 50%;
180   - color: #333;
181   - font-weight: 500;
182   - }
183   - .td {
184   - color: #999;
185   - width: 50%;
186   - display: flex;
187   - justify-content: center;
188   - text-align: center;
189   - }
190   - }
191   - }
192   - }
193   -}
194   -.odd {
195   - background-color: #f9fcff;
196   -}
  1 +<template>
  2 + <view class="historyData">
  3 + <!-- 公共组件-每个页面必须引入 -->
  4 + <public-module></public-module>
  5 + <view class="historyData-top">
  6 + <u-form :label-style="{ 'font-size': '0rpx' }">
  7 + <u-form-item @click="openCalendar">
  8 + <u-input v-model="timeData.selectTime" disabled disabledColor="#fff" placeholder="请选择日期" border="none">
  9 + <template slot="prefix">
  10 + <image class="icon" src="../../../static/can-der.png"></image>
  11 + </template>
  12 + </u-input>
  13 + </u-form-item>
  14 + <u-form-item @click="openTimeGap">
  15 + <u-input v-model="timeData.getTimeGap" disabled disabledColor="#fff" placeholder="请选择时间区间" border="none">
  16 + <template slot="prefix">
  17 + <image class="icon" src="../../../static/time.png"></image>
  18 + </template>
  19 + </u-input>
  20 + </u-form-item>
  21 + <u-form-item @click="openType"><u-input shape="circle" v-model="timeData.getType" placeholder="请选择属性" disabled disabledColor="#377DFF0D" /></u-form-item>
  22 + </u-form>
  23 + <!-- <qiun-data-charts type="tarea" :chartData="chartData" canvas2d /> -->
  24 + </view>
  25 + <view class="historyData-bottom">
  26 + <view class="table">
  27 + <view class="tr bg-w">
  28 + <view class="th">变量值</view>
  29 + <view class="th">更新时间</view>
  30 + </view>
  31 + <view class="tr bg-g">
  32 + <view class="td">10</view>
  33 + <view class="td">2022-03-01 18:16:33</view>
  34 + </view>
  35 +
  36 + </view>
  37 + </view>
  38 + <u-calendar
  39 + :show="showCalendar"
  40 + closeOnClickOverlay
  41 + mode="range"
  42 + startText="开始时间"
  43 + endText="结束时间"
  44 + confirmDisabledText="请选择日期"
  45 + @confirm="calendarConfirm"
  46 + @close="calendarClose"
  47 + ></u-calendar>
  48 + <u-picker :show="showTimeGap" :columns="columns" keyName="label" closeOnClickOverlay @confirm="confirmTimeGap" @cancel="cancelTimeGap" @close="cancelTimeGap"></u-picker>
  49 + <u-picker :show="showSelectType" :columns="keys" closeOnClickOverlay @confirm="confirmTypeGap" @cancel="cancelTypeGap" @close="cancelTypeGap"></u-picker>
  50 + <f-tabbar></f-tabbar>
  51 + </view>
  52 +</template>
  53 +
  54 +<script>
  55 +import fTabbar from '@/components/module/f-tabbar/f-tabbar';
  56 +import qiunDataCharts from '@/uni_modules/qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue';
  57 +import { getDeviceKeys, getHistroyData } from '../../../pages/device/api/index';
  58 +export default {
  59 + components: {
  60 + fTabbar,
  61 + qiunDataCharts
  62 + },
  63 + props:{
  64 + keys:{
  65 + type:Array,
  66 + default:()=>[]
  67 + }
  68 + },
  69 + data() {
  70 + return {
  71 + showCalendar: false,
  72 + showTimeGap: false,
  73 + showSelectType: false,
  74 + columns: [
  75 + [
  76 + {
  77 + label: '5分钟',
  78 + value: 300
  79 + },
  80 + {
  81 + label: '10分钟',
  82 + value: 600
  83 + },
  84 + {
  85 + label: '15分钟',
  86 + value: 900
  87 + },
  88 + {
  89 + label: '30分钟',
  90 + value: 1800
  91 + },
  92 + {
  93 + label: '1小时',
  94 + value: 3600
  95 + },
  96 + {
  97 + label: '2小时',
  98 + value: 7200
  99 + },
  100 + {
  101 + label: '6小时',
  102 + value: 21600
  103 + }
  104 + ]
  105 + ],
  106 + timeData: {
  107 + selectTime: '',
  108 + getTimeGap: '',
  109 + getType: ''
  110 + }
  111 + };
  112 + },
  113 + methods: {
  114 + openCalendar() {
  115 + this.showCalendar = true;
  116 + },
  117 + openTimeGap() {
  118 + this.showTimeGap = true;
  119 + },
  120 + openType() {
  121 + this.showSelectType = true;
  122 + },
  123 + calendarConfirm(date) {
  124 + this.showCalendar = false;
  125 + this.timeData.selectTime = `${date[0]} 至 ${date[1]}`;
  126 + },
  127 + calendarClose() {
  128 + this.showCalendar = false;
  129 + },
  130 + confirmTimeGap(time) {
  131 + this.showTimeGap = false;
  132 + this.timeData.getTimeGap = time.value[0].label;
  133 + },
  134 +
  135 + cancelTimeGap() {
  136 + this.showTimeGap = false;
  137 + },
  138 + confirmTypeGap(time) {
  139 + this.showSelectType = false;
  140 + this.timeData.getType = time.value[0];
  141 + },
  142 + cancelTypeGap() {
  143 + this.showSelectType = false;
  144 + }
  145 + }
  146 +};
  147 +</script>
  148 +
  149 +<style lang="scss" scoped>
  150 +.historyData {
  151 + margin: 30rpx;
  152 + .historyData-top {
  153 + padding: 30rpx;
  154 + background-color: #fff;
  155 + height: 870rpx;
  156 + border-radius: 20rpx;
  157 + .icon {
  158 + width: 28rpx;
  159 + height: 28rpx;
  160 + margin-right: 15rpx;
  161 + }
  162 + }
  163 + .historyData-bottom {
  164 + margin-top: 30rpx;
  165 + background-color: #fff;
  166 + border-radius: 20rpx;
  167 + .table {
  168 + border: 0px solid darkgray;
  169 + .tr {
  170 + display: flex;
  171 + width: 100%;
  172 + justify-content: center;
  173 + height: 3rem;
  174 + align-items: center;
  175 + .th {
  176 + display: flex;
  177 + justify-content: center;
  178 + align-items: center;
  179 + width: 50%;
  180 + color: #333;
  181 + font-weight: 500;
  182 + }
  183 + .td {
  184 + color: #999;
  185 + width: 50%;
  186 + display: flex;
  187 + justify-content: center;
  188 + text-align: center;
  189 + }
  190 + }
  191 + }
  192 + }
  193 +}
  194 +.odd {
  195 + background-color: #f9fcff;
  196 +}
197 197 </style>
... ...
deviceSubPage/deviceDetailPage/tabDetail/realtimeData.vue renamed from pages/device/tabDetail/realtimeData.vue
feedBackSubPage/feedback/feedback.vue renamed from pages/feedback/feedback.vue
... ... @@ -26,21 +26,6 @@ Vue.use(f_show_modal)
26 26 import uView from '@/uni_modules/uview-ui'
27 27 Vue.use(uView)
28 28
29   -// #ifdef MP
30   -// 引入uView对小程序分享的mixin封装
31   -const mpShare = require('@/uni_modules/uview-ui/libs/mixin/mpShare.js')
32   -Vue.mixin(mpShare)
33   -// #endif
34   -
35   -// #ifdef H5
36   -//微信公众号(分享、扫码、获取位置等)
37   -import '@/plugins/jwxUtils.js';
38   -// #endif
39   -
40   -// 基于iconfont图标库组件
41   -// import fIcon from "@/components/module/f-icon/f-icon.vue";
42   -// Vue.component("f-icon", fIcon);
43   -
44 29 // 公共组件
45 30 import publicModule from "@/components/common/public-module.vue";
46 31 Vue.component("public-module", publicModule);
... ...
1 1 {
2   - "name": "yun-teng-app",
3   - "appid": "__UNI__C873643",
4   - "description": "云腾app、小程序",
5   - "versionName": "1.0.0",
6   - "versionCode": 100,
7   - "transformPx": false,
8   - "app-plus": {
9   - "usingComponents": true,
10   - "nvueStyleCompiler": "uni-app",
11   - "compilerVersion": 3,
12   - "splashscreen": {
13   - "alwaysShowBeforeRender": true,
14   - "waiting": true,
15   - "autoclose": true,
16   - "delay": 0
17   - },
18   - "modules": {},
19   - "distribute": {
20   - "android": {
21   - "permissions": [
22   - "<uses-feature android:name=\"android.hardware.camera\"/>",
23   - "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
24   - "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
25   - "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
26   - "<uses-permission android:name=\"android.permission.CAMERA\"/>",
27   - "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
28   - "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
29   - "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
30   - "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
31   - "<uses-permission android:name=\"android.permission.INSTALL_PACKAGES\"/>",
32   - "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
33   - "<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
34   - "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
35   - "<uses-permission android:name=\"android.permission.REQUEST_INSTALL_PACKAGES\"/>",
36   - "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
37   - "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
38   - "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
39   - ]
40   - },
41   - "ios": {},
42   - "sdkConfigs": {
43   - "ad": {},
44   - "geolocation": {
45   - "system": {
46   - "__platform__": ["ios", "android"]
47   - },
48   - "amap": {
49   - "__platform__": ["ios", "android"],
50   - "appkey_ios": "",
51   - "appkey_android": ""
52   - }
53   - },
54   - "maps": {}
55   - }
56   - }
57   - },
58   - "quickapp": {},
59   - "mp-weixin": {
60   - "appid": "wx0ad61d7bf6808e02",
61   - "setting": {
62   - "urlCheck": false,
63   - "minified": true,
64   - "es6": true
65   - },
66   - "usingComponents": true,
67   - "permission": {
68   - "scope.userLocation": {
69   - "desc": "你的位置信息将用于小程序位置接口的效果展示"
70   - }
71   - },
72   - "lazyCodeLoading": "requiredComponents"
73   - },
74   - "mp-alipay": {
75   - "usingComponents": true
76   - },
77   - "mp-baidu": {
78   - "usingComponents": true
79   - },
80   - "mp-toutiao": {
81   - "usingComponents": true
82   - },
83   - "uniStatistics": {
84   - "enable": false
85   - },
86   - "vueVersion": "2",
87   - "h5": {
88   - "sdkConfigs": {
89   - "maps": {}
90   - },
91   - "router": {
92   - "base": "minImage/h5/"
93   - }
94   - }
  2 + "name" : "yun-teng-app",
  3 + "appid" : "__UNI__C873643",
  4 + "description" : "thingskit小程序",
  5 + "versionName" : "1.0.0",
  6 + "versionCode" : 100,
  7 + "transformPx" : false,
  8 + "app-plus" : {
  9 + "usingComponents" : true,
  10 + "nvueStyleCompiler" : "uni-app",
  11 + "compilerVersion" : 3,
  12 + "splashscreen" : {
  13 + "alwaysShowBeforeRender" : true,
  14 + "waiting" : true,
  15 + "autoclose" : true,
  16 + "delay" : 0
  17 + },
  18 + "modules" : {},
  19 + "distribute" : {
  20 + "android" : {
  21 + "permissions" : [
  22 + "<uses-feature android:name=\"android.hardware.camera\"/>",
  23 + "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
  24 + "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
  25 + "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
  26 + "<uses-permission android:name=\"android.permission.CAMERA\"/>",
  27 + "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
  28 + "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
  29 + "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
  30 + "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
  31 + "<uses-permission android:name=\"android.permission.INSTALL_PACKAGES\"/>",
  32 + "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
  33 + "<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
  34 + "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
  35 + "<uses-permission android:name=\"android.permission.REQUEST_INSTALL_PACKAGES\"/>",
  36 + "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
  37 + "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
  38 + "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
  39 + ]
  40 + },
  41 + "ios" : {},
  42 + "sdkConfigs" : {
  43 + "ad" : {},
  44 + "geolocation" : {
  45 + "system" : {
  46 + "__platform__" : [ "ios", "android" ]
  47 + },
  48 + "amap" : {
  49 + "__platform__" : [ "ios", "android" ],
  50 + "appkey_ios" : "",
  51 + "appkey_android" : ""
  52 + }
  53 + },
  54 + "maps" : {}
  55 + }
  56 + }
  57 + },
  58 + "quickapp" : {},
  59 + "mp-weixin" : {
  60 + "appid" : "wxd5d018355f38262b",
  61 + "setting" : {
  62 + "urlCheck" : false,
  63 + "minified" : true,
  64 + "es6" : true,
  65 + "postcss" : true
  66 + },
  67 + "usingComponents" : true,
  68 + "permission" : {
  69 + "scope.userLocation" : {
  70 + "desc" : "你的位置信息将用于小程序位置接口的效果展示"
  71 + }
  72 + },
  73 + "lazyCodeLoading" : "requiredComponents",
  74 + //开启分包优化
  75 + "optimization" : {
  76 + "subPackages" : true
  77 + }
  78 + },
  79 + "mp-alipay" : {
  80 + "usingComponents" : true
  81 + },
  82 + "mp-baidu" : {
  83 + "usingComponents" : true
  84 + },
  85 + "mp-toutiao" : {
  86 + "usingComponents" : true
  87 + },
  88 + "uniStatistics" : {
  89 + "enable" : false
  90 + },
  91 + "vueVersion" : "2",
  92 + "h5" : {
  93 + "sdkConfigs" : {
  94 + "maps" : {}
  95 + },
  96 + "router" : {
  97 + "base" : "minImage/h5/"
  98 + }
  99 + }
95 100 }
... ...
... ... @@ -4,7 +4,8 @@
4 4 "description": "### 项目结构",
5 5 "main": "main.js",
6 6 "scripts": {
7   - "test": "echo \"Error: no test specified\" && exit 1"
  7 + "test": "echo \"Error: no test specified\" && exit 1",
  8 + "dev:mp-wenxin": "cross-env NODE_ENV=development UNI_PLATFORM=mp-weixin vue-cli-service uni-build --watch --minimize"
8 9 },
9 10 "repository": {
10 11 "type": "git",
... ...
... ... @@ -14,12 +14,12 @@
14 14 "navigationBarTitleText": "设备"
15 15 }
16 16 },
17   - {
18   - "path": "pages/device/deviceDetail",
19   - "style": {
20   - "navigationBarTitleText": "设备详情"
21   - }
22   - },
  17 + // {
  18 + // "path": "pages/device/deviceDetail",
  19 + // "style": {
  20 + // "navigationBarTitleText": "设备详情"
  21 + // }
  22 + // },
23 23 {
24 24 "path": "pages/device/org/org",
25 25 "style": {
... ... @@ -33,9 +33,9 @@
33 33 }
34 34 },
35 35 {
36   - "path": "pages/alarm/alarmDetail",
  36 + "path": "pages/alarm/org/org",
37 37 "style": {
38   - "navigationBarTitleText": "告警详情"
  38 + "navigationBarTitleText": "组织筛选"
39 39 }
40 40 },
41 41 {
... ... @@ -43,44 +43,8 @@
43 43 "style": {
44 44 "navigationBarTitleText": "个人中心"
45 45 }
46   - }, {
47   - "path": "pages/personal/code",
48   - "style": {
49   - "navigationBarTitleText": "验证码登录"
50   - }
51   -
52   - }, {
53   - "path": "pages/personal/findPassword",
54   - "style": {
55   - "navigationBarTitleText": "找回密码"
56   - }
57   -
58   - }, {
59   - "path": "pages/personal/set",
60   - "style": {
61   - "navigationBarTitleText": "个人资料"
62   - }
63   -
64   - }, {
65   - "path": "pages/systemNotify/systemNotify",
66   - "style": {
67   - "navigationBarTitleText": "通知列表"
68   - }
69 46 },
70 47 {
71   - "path": "pages/systemNotify/notifyDetail",
72   - "style": {
73   - "navigationBarTitleText": "通知详情"
74   - }
75   - }, {
76   - "path": "pages/feedback/feedback",
77   - "style": {
78   - "navigationBarTitleText": "意见反馈",
79   - "app-plus": {
80   - "scrollIndicator": "none"
81   - }
82   - }
83   - }, {
84 48 "path": "pages/index/camera/camera",
85 49 "style": {
86 50 "navigationBarTitleText": "查看摄像头"
... ... @@ -98,33 +62,86 @@
98 62 }
99 63
100 64 },
101   -
102 65 {
103 66 "path": "pages/index/configuration/configurationDetail",
104 67 "style": {
105 68 "navigationBarTitleText": "组态详情"
106 69 }
107   -
  70 + }
  71 + ],
  72 + "subPackages": [{
  73 + "root": "alarmSubPage",
  74 + "pages": [{
  75 + "path": "alarmDetailPage/alarmDetail",
  76 + "style": {
  77 + "navigationBarTitleText": "告警详情"
  78 + }
  79 + }]
108 80 },
109 81 {
110   - "path": "pages/alarm/org/org",
111   - "style": {
112   - "navigationBarTitleText": "组织筛选"
113   - }
114   -
  82 + "root": "deviceSubPage",
  83 + "pages": [{
  84 + "path": "deviceDetailPage/deviceDetail",
  85 + "style": {
  86 + "navigationBarTitleText": "设备详情"
  87 + }
  88 + }]
115 89 },
116 90 {
117   - "path": "pages/public/login",
118   - "style": {
119   - "navigationBarTitleText": "登录"
120   - }
121   -
  91 + "root": "sysNotifySubPage",
  92 + "pages": [{
  93 + "path": "sysNotifyPage/systemNotify",
  94 + "style": {
  95 + "navigationBarTitleText": "系统通知"
  96 + }
  97 + },
  98 + {
  99 + "path": "sysNotifyPage/notifyDetail",
  100 + "style": {
  101 + "navigationBarTitleText": "通知详情"
  102 + }
  103 + }
  104 + ]
  105 + },
  106 + {
  107 + "root": "feedBackSubPage",
  108 + "pages": [{
  109 + "path": "feedback/feedback",
  110 + "style": {
  111 + "navigationBarTitleText": "意见反馈"
  112 + }
  113 + }]
  114 + },
  115 + {
  116 + "root": "publicLoginSubPage",
  117 + "pages": [{
  118 + "path": "public/login",
  119 + "style": {
  120 + "navigationBarTitleText": "登录"
  121 + }
  122 + },
  123 + {
  124 + "path": "other/set",
  125 + "style": {
  126 + "navigationBarTitleText": "个人资料"
  127 + }
  128 + },
  129 + {
  130 + "path": "other/code",
  131 + "style": {
  132 + "navigationBarTitleText": "验证码登录"
  133 + }
  134 + },
  135 + {
  136 + "path": "other/findPassword",
  137 + "style": {
  138 + "navigationBarTitleText": "忘记密码"
  139 + }
  140 + }
  141 + ]
122 142 }
123 143 ],
124 144 "globalStyle": {
125   - "mp-alipay": {
126   - "allowsBounceVertical": "NO"
127   - },
128 145 "navigationBarTextStyle": "black",
129 146 "navigationBarTitleText": "云腾app",
130 147 "navigationBarBackgroundColor": "#FFFFFF",
... ...
... ... @@ -427,7 +427,8 @@ export default {
427 427 status: e.status
428 428 };
429 429 uni.navigateTo({
430   - url: './alarmDetail?data=' + JSON.stringify(obj)
  430 + url:'/alarmSubPage/alarmDetailPage/alarmDetail?data='+JSON.stringify(obj)
  431 + // url: '/' + JSON.stringify(obj)
431 432 });
432 433 }
433 434 }
... ...
... ... @@ -225,7 +225,7 @@ export default {
225 225 },
226 226 openDeviceDetail(id, alarmStatus, lastOnlineTime,tbDeviceId) {
227 227 uni.navigateTo({
228   - url: `deviceDetail?id=${id}&alarmStatus=${alarmStatus}&lastOnlineTime=${lastOnlineTime}&tbDeviceId=${tbDeviceId}`
  228 + url: `/deviceSubPage/deviceDetailPage/deviceDetail?id=${id}&alarmStatus=${alarmStatus}&lastOnlineTime=${lastOnlineTime}&tbDeviceId=${tbDeviceId}`
229 229 });
230 230 },
231 231 handleClickTag(currentIndex, list) {
... ... @@ -296,4 +296,4 @@ export default {
296 296 }
297 297 }
298 298 }
299   -</style>
  299 +</style>
... ...
... ... @@ -102,7 +102,7 @@ export default {
102 102 uni.$u.http.get('/yt/video', { params: httpData, custom: { load: false } }).then(res => {
103 103 if (res) {
104 104 console.log('Video', res);
105   - // this.list = res.items;
  105 + this.list = res.items;
106 106 }
107 107 });
108 108 },
... ...
... ... @@ -7,7 +7,7 @@
7 7 <!-- 登录 -->
8 8 <view class="u-flex u-p-l-30 u-p-r-20 u-p-t-75 u-p-b-30">
9 9 <block v-if="userInfo.isToken">
10   - <view @click="openPersonalInfo" class="u-m-r-20"><image class="avatar" mode="aspectFill" :src="userInfo.avatar || '../../static/default-avatar.png'"></image></view>
  10 + <view @click="openPersonalInfo" class="u-m-r-20"><image class="avatar" mode="aspectFill" :src="userInfo.avatar"></image></view>
11 11 <view @click="openPersonalInfo" class="u-flex-1">
12 12 <view class="nickName u-flex">
13 13 <view class="name u-m-r-10" v-if="userInfo.realName">
... ... @@ -34,7 +34,7 @@
34 34 <!-- 登录 -->
35 35 <view class="u-flex u-p-l-30 u-p-r-20 u-p-t-75 u-p-b-30">
36 36 <block v-if="userInfo.isToken">
37   - <view @click="openPersonalInfo" class="u-m-r-20"><image class="avatar" mode="aspectFill" :src="userInfo.avatar||'../../static/default-avatar.png'"></image></view>
  37 + <view @click="openPersonalInfo" class="u-m-r-20"><image class="avatar" mode="aspectFill" :src="userInfo.avatar"></image></view>
38 38 <view @click="openPersonalInfo" class="u-flex-1">
39 39 <view class="nickName u-flex">
40 40 <view class="name u-m-r-10" v-if="userInfo.realName">
... ... @@ -60,12 +60,12 @@
60 60 </view>
61 61 <view class="u-flex my-nav">
62 62 <view class="nav-main">
63   - <view @click="onTokenJump('../systemNotify/systemNotify')" class="u-flex nav-link">
  63 + <view @click="onTokenJump('/sysNotifySubPage/sysNotifyPage/systemNotify')" class="u-flex nav-link">
64 64 <view class="nav-image"><image class="image" src="../../static/sys-not.png"></image></view>
65 65 <view class="nav-center"><text class="text">系统通知</text></view>
66 66 <view class="nav-right"><image class="image" src="../../static/arrow-right.png"></image></view>
67 67 </view>
68   - <view @click="onTokenJump('../feedback/feedback')" class="u-flex nav-link">
  68 + <view @click="onTokenJump('/feedBackSubPage/feedback/feedback')" class="u-flex nav-link">
69 69 <view class="nav-image"><image class="image" src="../../static/find-sugg.png"></image></view>
70 70 <view class="nav-center"><text class="text">意见反馈</text></view>
71 71 <view class="nav-right"><image class="image" src="../../static/arrow-right.png"></image></view>
... ... @@ -173,18 +173,6 @@ export default {
173 173 title: '绑定账号',
174 174 systemInfo: base.systemInfo,
175 175 PrimaryButtonColor: '#0079fe', //主题色
176   - list: [
177   - {
178   - title: '系统通知',
179   - url: '../systemNotify/systemNotify',
180   - icon: 'setting-fill'
181   - },
182   - {
183   - title: '意见反馈',
184   - url: '../feedback/feedback',
185   - icon: 'more-circle-fill'
186   - }
187   - ]
188 176 };
189 177 },
190 178 onLoad() {
... ... @@ -204,16 +192,6 @@ export default {
204 192 });
205 193 });
206 194 },
207   - // openSysNotify() {
208   - // uni.navigateTo({
209   - // url: '../systemNotify/systemNotify'
210   - // });
211   - // },
212   - // openFeedBack() {
213   - // uni.navigateTo({
214   - // url: '../feedback/feedback'
215   - // });
216   - // },
217 195 onJump(url) {
218 196 uni.navigateTo({
219 197 url: url
... ... @@ -221,7 +199,7 @@ export default {
221 199 },
222 200 openLoginFunc() {
223 201 uni.navigateTo({
224   - url: '../public/login'
  202 + url: '/publicLoginSubPage/public/login'
225 203 });
226 204 },
227 205 openPersonalInfo() {
... ... @@ -229,7 +207,7 @@ export default {
229 207 data: this.userInfo
230 208 };
231 209 uni.navigateTo({
232   - url: './set?data=' + JSON.stringify(obj)
  210 + url: '/publicLoginSubPage/other/set?data=' + JSON.stringify(obj)
233 211 });
234 212 },
235 213 clickAccountFunc() {
... ... @@ -306,7 +284,7 @@ export default {
306 284 that.showLogout = false;
307 285 setTimeout(() => {
308 286 uni.navigateTo({
309   - url: '../public/login'
  287 + url: '/publicLoginSubPage/public/login'
310 288 });
311 289 }, 500);
312 290 } else if (res.cancel) {
... ...
1   -!function(e,n){"function"==typeof define&&(define.amd||define.cmd)?define(function(){return n(e)}):n(e,!0)}(this,function(e,n){function i(n,i,t){e.WeixinJSBridge?WeixinJSBridge.invoke(n,o(i),function(e){c(n,e,t)}):u(n,t)}function t(n,i,t){e.WeixinJSBridge?WeixinJSBridge.on(n,function(e){t&&t.trigger&&t.trigger(e),c(n,e,i)}):t?u(n,t):u(n,i)}function o(e){return e=e||{},e.appId=C.appId,e.verifyAppId=C.appId,e.verifySignType="sha1",e.verifyTimestamp=C.timestamp+"",e.verifyNonceStr=C.nonceStr,e.verifySignature=C.signature,e}function r(e){return{timeStamp:e.timestamp+"",nonceStr:e.nonceStr,package:e.package,paySign:e.paySign,signType:e.signType||"SHA1"}}function a(e){return e.postalCode=e.addressPostalCode,delete e.addressPostalCode,e.provinceName=e.proviceFirstStageName,delete e.proviceFirstStageName,e.cityName=e.addressCitySecondStageName,delete e.addressCitySecondStageName,e.countryName=e.addressCountiesThirdStageName,delete e.addressCountiesThirdStageName,e.detailInfo=e.addressDetailInfo,delete e.addressDetailInfo,e}function c(e,n,i){"openEnterpriseChat"==e&&(n.errCode=n.err_code),delete n.err_code,delete n.err_desc,delete n.err_detail;var t=n.errMsg;t||(t=n.err_msg,delete n.err_msg,t=s(e,t),n.errMsg=t),(i=i||{})._complete&&(i._complete(n),delete i._complete),t=n.errMsg||"",C.debug&&!i.isInnerInvoke&&alert(JSON.stringify(n));var o=t.indexOf(":");switch(t.substring(o+1)){case"ok":i.success&&i.success(n);break;case"cancel":i.cancel&&i.cancel(n);break;default:i.fail&&i.fail(n)}i.complete&&i.complete(n)}function s(e,n){var i=e,t=v[i];t&&(i=t);var o="ok";if(n){var r=n.indexOf(":");"confirm"==(o=n.substring(r+1))&&(o="ok"),"failed"==o&&(o="fail"),-1!=o.indexOf("failed_")&&(o=o.substring(7)),-1!=o.indexOf("fail_")&&(o=o.substring(5)),"access denied"!=(o=(o=o.replace(/_/g," ")).toLowerCase())&&"no permission to execute"!=o||(o="permission denied"),"config"==i&&"function not exist"==o&&(o="ok"),""==o&&(o="fail")}return n=i+":"+o}function d(e){if(e){for(var n=0,i=e.length;n<i;++n){var t=e[n],o=h[t];o&&(e[n]=o)}return e}}function u(e,n){if(!(!C.debug||n&&n.isInnerInvoke)){var i=v[e];i&&(e=i),n&&n._complete&&delete n._complete,console.log('"'+e+'",',n||"")}}function l(e){if(!(k||w||C.debug||x<"6.0.2"||V.systemType<0)){var n=new Image;V.appId=C.appId,V.initTime=A.initEndTime-A.initStartTime,V.preVerifyTime=A.preVerifyEndTime-A.preVerifyStartTime,N.getNetworkType({isInnerInvoke:!0,success:function(e){V.networkType=e.networkType;var i="https://open.weixin.qq.com/sdk/report?v="+V.version+"&o="+V.isPreVerifyOk+"&s="+V.systemType+"&c="+V.clientVersion+"&a="+V.appId+"&n="+V.networkType+"&i="+V.initTime+"&p="+V.preVerifyTime+"&u="+V.url;n.src=i}})}}function p(){return(new Date).getTime()}function f(n){T&&(e.WeixinJSBridge?n():S.addEventListener&&S.addEventListener("WeixinJSBridgeReady",n,!1))}function m(){N.invoke||(N.invoke=function(n,i,t){e.WeixinJSBridge&&WeixinJSBridge.invoke(n,o(i),t)},N.on=function(n,i){e.WeixinJSBridge&&WeixinJSBridge.on(n,i)})}function g(e){if("string"==typeof e&&e.length>0){var n=e.split("?")[0],i=e.split("?")[1];return n+=".html",void 0!==i?n+"?"+i:n}}if(!e.jWeixin){var h={config:"preVerifyJSAPI",onMenuShareTimeline:"menu:share:timeline",onMenuShareAppMessage:"menu:share:appmessage",onMenuShareQQ:"menu:share:qq",onMenuShareWeibo:"menu:share:weiboApp",onMenuShareQZone:"menu:share:QZone",previewImage:"imagePreview",getLocation:"geoLocation",openProductSpecificView:"openProductViewWithPid",addCard:"batchAddCard",openCard:"batchViewCard",chooseWXPay:"getBrandWCPayRequest",openEnterpriseRedPacket:"getRecevieBizHongBaoRequest",startSearchBeacons:"startMonitoringBeacons",stopSearchBeacons:"stopMonitoringBeacons",onSearchBeacons:"onBeaconsInRange",consumeAndShareCard:"consumedShareCard",openAddress:"editAddress"},v=function(){var e={};for(var n in h)e[h[n]]=n;return e}(),S=e.document,I=S.title,y=navigator.userAgent.toLowerCase(),_=navigator.platform.toLowerCase(),k=!(!_.match("mac")&&!_.match("win")),w=-1!=y.indexOf("wxdebugger"),T=-1!=y.indexOf("micromessenger"),M=-1!=y.indexOf("android"),P=-1!=y.indexOf("iphone")||-1!=y.indexOf("ipad"),x=function(){var e=y.match(/micromessenger\/(\d+\.\d+\.\d+)/)||y.match(/micromessenger\/(\d+\.\d+)/);return e?e[1]:""}(),A={initStartTime:p(),initEndTime:0,preVerifyStartTime:0,preVerifyEndTime:0},V={version:1,appId:"",initTime:0,preVerifyTime:0,networkType:"",isPreVerifyOk:1,systemType:P?1:M?2:-1,clientVersion:x,url:encodeURIComponent(location.href)},C={},L={_completes:[]},B={state:0,data:{}};f(function(){A.initEndTime=p()});var O=!1,E=[],N={config:function(e){C=e,u("config",e);var n=!1!==C.check;f(function(){if(n)i(h.config,{verifyJsApiList:d(C.jsApiList)},function(){L._complete=function(e){A.preVerifyEndTime=p(),B.state=1,B.data=e},L.success=function(e){V.isPreVerifyOk=0},L.fail=function(e){L._fail?L._fail(e):B.state=-1};var e=L._completes;return e.push(function(){l()}),L.complete=function(n){for(var i=0,t=e.length;i<t;++i)e[i]();L._completes=[]},L}()),A.preVerifyStartTime=p();else{B.state=1;for(var e=L._completes,t=0,o=e.length;t<o;++t)e[t]();L._completes=[]}}),m()},ready:function(e){0!=B.state?e():(L._completes.push(e),!T&&C.debug&&e())},error:function(e){x<"6.0.2"||(-1==B.state?e(B.data):L._fail=e)},checkJsApi:function(e){var n=function(e){var n=e.checkResult;for(var i in n){var t=v[i];t&&(n[t]=n[i],delete n[i])}return e};i("checkJsApi",{jsApiList:d(e.jsApiList)},(e._complete=function(e){if(M){var i=e.checkResult;i&&(e.checkResult=JSON.parse(i))}e=n(e)},e))},onMenuShareTimeline:function(e){t(h.onMenuShareTimeline,{complete:function(){i("shareTimeline",{title:e.title||I,desc:e.title||I,img_url:e.imgUrl||"",link:e.link||location.href,type:e.type||"link",data_url:e.dataUrl||""},e)}},e)},onMenuShareAppMessage:function(e){t(h.onMenuShareAppMessage,{complete:function(n){"favorite"===n.scene?i("sendAppMessage",{title:e.title||I,desc:e.desc||"",link:e.link||location.href,img_url:e.imgUrl||"",type:e.type||"link",data_url:e.dataUrl||""}):i("sendAppMessage",{title:e.title||I,desc:e.desc||"",link:e.link||location.href,img_url:e.imgUrl||"",type:e.type||"link",data_url:e.dataUrl||""},e)}},e)},onMenuShareQQ:function(e){t(h.onMenuShareQQ,{complete:function(){i("shareQQ",{title:e.title||I,desc:e.desc||"",img_url:e.imgUrl||"",link:e.link||location.href},e)}},e)},onMenuShareWeibo:function(e){t(h.onMenuShareWeibo,{complete:function(){i("shareWeiboApp",{title:e.title||I,desc:e.desc||"",img_url:e.imgUrl||"",link:e.link||location.href},e)}},e)},onMenuShareQZone:function(e){t(h.onMenuShareQZone,{complete:function(){i("shareQZone",{title:e.title||I,desc:e.desc||"",img_url:e.imgUrl||"",link:e.link||location.href},e)}},e)},updateTimelineShareData:function(e){i("updateTimelineShareData",{title:e.title,link:e.link,imgUrl:e.imgUrl},e)},updateAppMessageShareData:function(e){i("updateAppMessageShareData",{title:e.title,desc:e.desc,link:e.link,imgUrl:e.imgUrl},e)},startRecord:function(e){i("startRecord",{},e)},stopRecord:function(e){i("stopRecord",{},e)},onVoiceRecordEnd:function(e){t("onVoiceRecordEnd",e)},playVoice:function(e){i("playVoice",{localId:e.localId},e)},pauseVoice:function(e){i("pauseVoice",{localId:e.localId},e)},stopVoice:function(e){i("stopVoice",{localId:e.localId},e)},onVoicePlayEnd:function(e){t("onVoicePlayEnd",e)},uploadVoice:function(e){i("uploadVoice",{localId:e.localId,isShowProgressTips:0==e.isShowProgressTips?0:1},e)},downloadVoice:function(e){i("downloadVoice",{serverId:e.serverId,isShowProgressTips:0==e.isShowProgressTips?0:1},e)},translateVoice:function(e){i("translateVoice",{localId:e.localId,isShowProgressTips:0==e.isShowProgressTips?0:1},e)},chooseImage:function(e){i("chooseImage",{scene:"1|2",count:e.count||9,sizeType:e.sizeType||["original","compressed"],sourceType:e.sourceType||["album","camera"]},(e._complete=function(e){if(M){var n=e.localIds;try{n&&(e.localIds=JSON.parse(n))}catch(e){}}},e))},getLocation:function(e){},previewImage:function(e){i(h.previewImage,{current:e.current,urls:e.urls},e)},uploadImage:function(e){i("uploadImage",{localId:e.localId,isShowProgressTips:0==e.isShowProgressTips?0:1},e)},downloadImage:function(e){i("downloadImage",{serverId:e.serverId,isShowProgressTips:0==e.isShowProgressTips?0:1},e)},getLocalImgData:function(e){!1===O?(O=!0,i("getLocalImgData",{localId:e.localId},(e._complete=function(e){if(O=!1,E.length>0){var n=E.shift();wx.getLocalImgData(n)}},e))):E.push(e)},getNetworkType:function(e){var n=function(e){var n=e.errMsg;e.errMsg="getNetworkType:ok";var i=e.subtype;if(delete e.subtype,i)e.networkType=i;else{var t=n.indexOf(":"),o=n.substring(t+1);switch(o){case"wifi":case"edge":case"wwan":e.networkType=o;break;default:e.errMsg="getNetworkType:fail"}}return e};i("getNetworkType",{},(e._complete=function(e){e=n(e)},e))},openLocation:function(e){i("openLocation",{latitude:e.latitude,longitude:e.longitude,name:e.name||"",address:e.address||"",scale:e.scale||28,infoUrl:e.infoUrl||""},e)},getLocation:function(e){e=e||{},i(h.getLocation,{type:e.type||"wgs84"},(e._complete=function(e){delete e.type},e))},hideOptionMenu:function(e){i("hideOptionMenu",{},e)},showOptionMenu:function(e){i("showOptionMenu",{},e)},closeWindow:function(e){i("closeWindow",{},e=e||{})},hideMenuItems:function(e){i("hideMenuItems",{menuList:e.menuList},e)},showMenuItems:function(e){i("showMenuItems",{menuList:e.menuList},e)},hideAllNonBaseMenuItem:function(e){i("hideAllNonBaseMenuItem",{},e)},showAllNonBaseMenuItem:function(e){i("showAllNonBaseMenuItem",{},e)},scanQRCode:function(e){i("scanQRCode",{needResult:(e=e||{}).needResult||0,scanType:e.scanType||["qrCode","barCode"]},(e._complete=function(e){if(P){var n=e.resultStr;if(n){var i=JSON.parse(n);e.resultStr=i&&i.scan_code&&i.scan_code.scan_result}}},e))},openAddress:function(e){i(h.openAddress,{},(e._complete=function(e){e=a(e)},e))},openProductSpecificView:function(e){i(h.openProductSpecificView,{pid:e.productId,view_type:e.viewType||0,ext_info:e.extInfo},e)},addCard:function(e){for(var n=e.cardList,t=[],o=0,r=n.length;o<r;++o){var a=n[o],c={card_id:a.cardId,card_ext:a.cardExt};t.push(c)}i(h.addCard,{card_list:t},(e._complete=function(e){var n=e.card_list;if(n){for(var i=0,t=(n=JSON.parse(n)).length;i<t;++i){var o=n[i];o.cardId=o.card_id,o.cardExt=o.card_ext,o.isSuccess=!!o.is_succ,delete o.card_id,delete o.card_ext,delete o.is_succ}e.cardList=n,delete e.card_list}},e))},chooseCard:function(e){i("chooseCard",{app_id:C.appId,location_id:e.shopId||"",sign_type:e.signType||"SHA1",card_id:e.cardId||"",card_type:e.cardType||"",card_sign:e.cardSign,time_stamp:e.timestamp+"",nonce_str:e.nonceStr},(e._complete=function(e){e.cardList=e.choose_card_info,delete e.choose_card_info},e))},openCard:function(e){for(var n=e.cardList,t=[],o=0,r=n.length;o<r;++o){var a=n[o],c={card_id:a.cardId,code:a.code};t.push(c)}i(h.openCard,{card_list:t},e)},consumeAndShareCard:function(e){i(h.consumeAndShareCard,{consumedCardId:e.cardId,consumedCode:e.code},e)},chooseWXPay:function(e){i(h.chooseWXPay,r(e),e)},openEnterpriseRedPacket:function(e){i(h.openEnterpriseRedPacket,r(e),e)},startSearchBeacons:function(e){i(h.startSearchBeacons,{ticket:e.ticket},e)},stopSearchBeacons:function(e){i(h.stopSearchBeacons,{},e)},onSearchBeacons:function(e){t(h.onSearchBeacons,e)},openEnterpriseChat:function(e){i("openEnterpriseChat",{useridlist:e.userIds,chatname:e.groupName},e)},launchMiniProgram:function(e){i("launchMiniProgram",{targetAppId:e.targetAppId,path:g(e.path),envVersion:e.envVersion},e)},miniProgram:{navigateBack:function(e){e=e||{},f(function(){i("invokeMiniProgramAPI",{name:"navigateBack",arg:{delta:e.delta||1}},e)})},navigateTo:function(e){f(function(){i("invokeMiniProgramAPI",{name:"navigateTo",arg:{url:e.url}},e)})},redirectTo:function(e){f(function(){i("invokeMiniProgramAPI",{name:"redirectTo",arg:{url:e.url}},e)})},switchTab:function(e){f(function(){i("invokeMiniProgramAPI",{name:"switchTab",arg:{url:e.url}},e)})},reLaunch:function(e){f(function(){i("invokeMiniProgramAPI",{name:"reLaunch",arg:{url:e.url}},e)})},postMessage:function(e){f(function(){i("invokeMiniProgramAPI",{name:"postMessage",arg:e.data||{}},e)})},getEnv:function(n){f(function(){n({miniprogram:"miniprogram"===e.__wxjs_environment})})}}},b=1,R={};return S.addEventListener("error",function(e){if(!M){var n=e.target,i=n.tagName,t=n.src;if(("IMG"==i||"VIDEO"==i||"AUDIO"==i||"SOURCE"==i)&&-1!=t.indexOf("wxlocalresource://")){e.preventDefault(),e.stopPropagation();var o=n["wx-id"];if(o||(o=b++,n["wx-id"]=o),R[o])return;R[o]=!0,wx.ready(function(){wx.getLocalImgData({localId:t,success:function(e){n.src=e.localData}})})}}},!0),S.addEventListener("load",function(e){if(!M){var n=e.target,i=n.tagName;n.src;if("IMG"==i||"VIDEO"==i||"AUDIO"==i||"SOURCE"==i){var t=n["wx-id"];t&&(R[t]=!1)}}},!0),n&&(e.wx=e.jWeixin=N),N}});
\ No newline at end of file
1   -// 获取微信公众号SDK权限
2   -import base from '@/config/baseUrl';
3   -import { isWechat } from '@/config/h5Utils';
4   -
5   -//获取地理位置
6   -export const getLocation = () => {
7   - return new Promise((resolve, reject) => {
8   - jWeixin.ready(function () {
9   - jWeixin.getLocation({
10   - type: 'gcj02',
11   - success: function (res) {
12   - resolve(res);
13   - },
14   - fail: (err) => {
15   - reject(err);
16   - }
17   - });
18   - });
19   - });
20   -}
21   -export const shareData = (info) => {
22   - let item = {
23   - title: info.title || base.share.title, // 分享标题
24   - desc: info.desc || base.share.desc, // 分享描述
25   - imgUrl: info.imgUrl || base.share.imgUrl, // 分享链接
26   - link: info.link || base.share.link, // 分享图标
27   - }
28   - return item
29   -}
30   -//设置分享信息
31   -export const setShare = (data, callback) => {
32   - //配置校验成功后执行
33   - jWeixin.ready(function () {
34   - if (!data.link) {
35   - let url = window.location.href;
36   - let index = url.indexOf("?");
37   - if (index != -1) {
38   - if (url.indexOf("#") != -1 && url.indexOf("#") > index) {
39   - url = url.substring(0, index) + url.substring(url.indexOf("#"));
40   - } else {
41   - url = url.substr(0, index);
42   - }
43   - }
44   - data.link = url;
45   - }
46   - jWeixin.updateAppMessageShareData(shareData(data));
47   - jWeixin.updateTimelineShareData(shareData(data));
48   - });
49   -}
50   -//微信扫一扫
51   -export const scanQRCode = ( callback,needResult = 0) => {
52   - //配置校验成功后执行
53   - jWeixin.ready(function () {
54   - jWeixin.scanQRCode({
55   - needResult: needResult, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
56   - scanType: ["qrCode","barCode"], // 可以指定扫二维码还是一维码,默认二者都有
57   - success: function (res) {
58   - callback && callback(res);
59   - }
60   - });
61   - });
62   -}
63   -//获取微信JSSDK授权
64   -window.onload = function () {
65   - // 需配置公众号appId
66   - if (!(base.publicAppId && isWechat())) {
67   - return;
68   - }
69   - //获取当前页面地址
70   - let url = window.location.href;
71   - url = url.substring(0, url.indexOf("#"));
72   - //获取微信公众号SDK权限的签名、随机数、时间戳
73   - uni.$u.http.post("api/jWeixinConfig", {
74   - url: url
75   - }).then(res => {
76   - // 微信SDK配置
77   - jWeixin.config({
78   - debug: false,
79   - appId: base.publicAppId, // 必填,公众号的唯一标识
80   - timestamp: res.timestamp, // 必填,生成签名的时间戳
81   - nonceStr: res.noncestr, // 必填,生成签名的随机串
82   - signature: res.signature,// 必填,签名
83   - jsApiList: [
84   - 'scanQRCode',
85   - "getLocation",
86   - "updateAppMessageShareData",
87   - "updateTimelineShareData",
88   - 'onMenuShareAppMessage', //旧的接口,即将废弃
89   - 'onMenuShareTimeline' //旧的接口,即将废弃
90   - ]
91   - });
92   - //设置分享内容
93   - setShare();
94   - });
95   - //配置校验失败后执行
96   - jWeixin.error(function (res) {
97   - // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
98   - console.log(res);
99   - });
100   -};
\ No newline at end of file
1   -/*
2   - * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
3   - * Digest Algorithm, as defined in RFC 1321.
4   - * Version 1.1 Copyright (C) Paul Johnston 1999 - 2002.
5   - * Code also contributed by Greg Holt
6   - * See http://pajhome.org.uk/site/legal.html for details.
7   - */
8   -
9   -/*
10   - * Add integers, wrapping at 2^32. This uses 16-bit operations internally
11   - * to work around bugs in some JS interpreters.
12   - */
13   -function safe_add(x, y) {
14   - var lsw = (x & 0xFFFF) + (y & 0xFFFF)
15   - var msw = (x >> 16) + (y >> 16) + (lsw >> 16)
16   - return (msw << 16) | (lsw & 0xFFFF)
17   -}
18   -
19   -/*
20   - * Bitwise rotate a 32-bit number to the left.
21   - */
22   -function rol(num, cnt) {
23   - return (num << cnt) | (num >>> (32 - cnt))
24   -}
25   -
26   -/*
27   - * These functions implement the four basic operations the algorithm uses.
28   - */
29   -function cmn(q, a, b, x, s, t) {
30   - return safe_add(rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b)
31   -}
32   -function ff(a, b, c, d, x, s, t) {
33   - return cmn((b & c) | ((~b) & d), a, b, x, s, t)
34   -}
35   -function gg(a, b, c, d, x, s, t) {
36   - return cmn((b & d) | (c & (~d)), a, b, x, s, t)
37   -}
38   -function hh(a, b, c, d, x, s, t) {
39   - return cmn(b ^ c ^ d, a, b, x, s, t)
40   -}
41   -function ii(a, b, c, d, x, s, t) {
42   - return cmn(c ^ (b | (~d)), a, b, x, s, t)
43   -}
44   -
45   -/*
46   - * Calculate the MD5 of an array of little-endian words, producing an array
47   - * of little-endian words.
48   - */
49   -function coreMD5(x) {
50   - var a = 1732584193
51   - var b = -271733879
52   - var c = -1732584194
53   - var d = 271733878
54   -
55   - for (var i = 0; i < x.length; i += 16) {
56   - var olda = a
57   - var oldb = b
58   - var oldc = c
59   - var oldd = d
60   -
61   - a = ff(a, b, c, d, x[i + 0], 7, -680876936)
62   - d = ff(d, a, b, c, x[i + 1], 12, -389564586)
63   - c = ff(c, d, a, b, x[i + 2], 17, 606105819)
64   - b = ff(b, c, d, a, x[i + 3], 22, -1044525330)
65   - a = ff(a, b, c, d, x[i + 4], 7, -176418897)
66   - d = ff(d, a, b, c, x[i + 5], 12, 1200080426)
67   - c = ff(c, d, a, b, x[i + 6], 17, -1473231341)
68   - b = ff(b, c, d, a, x[i + 7], 22, -45705983)
69   - a = ff(a, b, c, d, x[i + 8], 7, 1770035416)
70   - d = ff(d, a, b, c, x[i + 9], 12, -1958414417)
71   - c = ff(c, d, a, b, x[i + 10], 17, -42063)
72   - b = ff(b, c, d, a, x[i + 11], 22, -1990404162)
73   - a = ff(a, b, c, d, x[i + 12], 7, 1804603682)
74   - d = ff(d, a, b, c, x[i + 13], 12, -40341101)
75   - c = ff(c, d, a, b, x[i + 14], 17, -1502002290)
76   - b = ff(b, c, d, a, x[i + 15], 22, 1236535329)
77   -
78   - a = gg(a, b, c, d, x[i + 1], 5, -165796510)
79   - d = gg(d, a, b, c, x[i + 6], 9, -1069501632)
80   - c = gg(c, d, a, b, x[i + 11], 14, 643717713)
81   - b = gg(b, c, d, a, x[i + 0], 20, -373897302)
82   - a = gg(a, b, c, d, x[i + 5], 5, -701558691)
83   - d = gg(d, a, b, c, x[i + 10], 9, 38016083)
84   - c = gg(c, d, a, b, x[i + 15], 14, -660478335)
85   - b = gg(b, c, d, a, x[i + 4], 20, -405537848)
86   - a = gg(a, b, c, d, x[i + 9], 5, 568446438)
87   - d = gg(d, a, b, c, x[i + 14], 9, -1019803690)
88   - c = gg(c, d, a, b, x[i + 3], 14, -187363961)
89   - b = gg(b, c, d, a, x[i + 8], 20, 1163531501)
90   - a = gg(a, b, c, d, x[i + 13], 5, -1444681467)
91   - d = gg(d, a, b, c, x[i + 2], 9, -51403784)
92   - c = gg(c, d, a, b, x[i + 7], 14, 1735328473)
93   - b = gg(b, c, d, a, x[i + 12], 20, -1926607734)
94   -
95   - a = hh(a, b, c, d, x[i + 5], 4, -378558)
96   - d = hh(d, a, b, c, x[i + 8], 11, -2022574463)
97   - c = hh(c, d, a, b, x[i + 11], 16, 1839030562)
98   - b = hh(b, c, d, a, x[i + 14], 23, -35309556)
99   - a = hh(a, b, c, d, x[i + 1], 4, -1530992060)
100   - d = hh(d, a, b, c, x[i + 4], 11, 1272893353)
101   - c = hh(c, d, a, b, x[i + 7], 16, -155497632)
102   - b = hh(b, c, d, a, x[i + 10], 23, -1094730640)
103   - a = hh(a, b, c, d, x[i + 13], 4, 681279174)
104   - d = hh(d, a, b, c, x[i + 0], 11, -358537222)
105   - c = hh(c, d, a, b, x[i + 3], 16, -722521979)
106   - b = hh(b, c, d, a, x[i + 6], 23, 76029189)
107   - a = hh(a, b, c, d, x[i + 9], 4, -640364487)
108   - d = hh(d, a, b, c, x[i + 12], 11, -421815835)
109   - c = hh(c, d, a, b, x[i + 15], 16, 530742520)
110   - b = hh(b, c, d, a, x[i + 2], 23, -995338651)
111   -
112   - a = ii(a, b, c, d, x[i + 0], 6, -198630844)
113   - d = ii(d, a, b, c, x[i + 7], 10, 1126891415)
114   - c = ii(c, d, a, b, x[i + 14], 15, -1416354905)
115   - b = ii(b, c, d, a, x[i + 5], 21, -57434055)
116   - a = ii(a, b, c, d, x[i + 12], 6, 1700485571)
117   - d = ii(d, a, b, c, x[i + 3], 10, -1894986606)
118   - c = ii(c, d, a, b, x[i + 10], 15, -1051523)
119   - b = ii(b, c, d, a, x[i + 1], 21, -2054922799)
120   - a = ii(a, b, c, d, x[i + 8], 6, 1873313359)
121   - d = ii(d, a, b, c, x[i + 15], 10, -30611744)
122   - c = ii(c, d, a, b, x[i + 6], 15, -1560198380)
123   - b = ii(b, c, d, a, x[i + 13], 21, 1309151649)
124   - a = ii(a, b, c, d, x[i + 4], 6, -145523070)
125   - d = ii(d, a, b, c, x[i + 11], 10, -1120210379)
126   - c = ii(c, d, a, b, x[i + 2], 15, 718787259)
127   - b = ii(b, c, d, a, x[i + 9], 21, -343485551)
128   -
129   - a = safe_add(a, olda)
130   - b = safe_add(b, oldb)
131   - c = safe_add(c, oldc)
132   - d = safe_add(d, oldd)
133   - }
134   - return [a, b, c, d]
135   -}
136   -
137   -/*
138   - * Convert an array of little-endian words to a hex string.
139   - */
140   -function binl2hex(binarray) {
141   - var hex_tab = "0123456789abcdef"
142   - var str = ""
143   - for (var i = 0; i < binarray.length * 4; i++) {
144   - str += hex_tab.charAt((binarray[i >> 2] >> ((i % 4) * 8 + 4)) & 0xF) +
145   - hex_tab.charAt((binarray[i >> 2] >> ((i % 4) * 8)) & 0xF)
146   - }
147   - return str
148   -}
149   -
150   -/*
151   - * Convert an array of little-endian words to a base64 encoded string.
152   - */
153   -function binl2b64(binarray) {
154   - var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
155   - var str = ""
156   - for (var i = 0; i < binarray.length * 32; i += 6) {
157   - str += tab.charAt(((binarray[i >> 5] << (i % 32)) & 0x3F) |
158   - ((binarray[i >> 5 + 1] >> (32 - i % 32)) & 0x3F))
159   - }
160   - return str
161   -}
162   -
163   -/*
164   - * Convert an 8-bit character string to a sequence of 16-word blocks, stored
165   - * as an array, and append appropriate padding for MD4/5 calculation.
166   - * If any of the characters are >255, the high byte is silently ignored.
167   - */
168   -function str2binl(str) {
169   - var nblk = ((str.length + 8) >> 6) + 1 // number of 16-word blocks
170   - var blks = new Array(nblk * 16)
171   - for (var i = 0; i < nblk * 16; i++) blks[i] = 0
172   - for (var i = 0; i < str.length; i++)
173   - blks[i >> 2] |= (str.charCodeAt(i) & 0xFF) << ((i % 4) * 8)
174   - blks[i >> 2] |= 0x80 << ((i % 4) * 8)
175   - blks[nblk * 16 - 2] = str.length * 8
176   - return blks
177   -}
178   -
179   -/*
180   - * Convert a wide-character string to a sequence of 16-word blocks, stored as
181   - * an array, and append appropriate padding for MD4/5 calculation.
182   - */
183   -function strw2binl(str) {
184   - var nblk = ((str.length + 4) >> 5) + 1 // number of 16-word blocks
185   - var blks = new Array(nblk * 16)
186   - for (var i = 0; i < nblk * 16; i++) blks[i] = 0
187   - for (var i = 0; i < str.length; i++)
188   - blks[i >> 1] |= str.charCodeAt(i) << ((i % 2) * 16)
189   - blks[i >> 1] |= 0x80 << ((i % 2) * 16)
190   - blks[nblk * 16 - 2] = str.length * 16
191   - return blks
192   -}
193   -
194   -/*
195   - * External interface
196   - */
197   -function md5(str) { return binl2hex(coreMD5(str2binl(str))) }
198   -function hexMD5w(str) { return binl2hex(coreMD5(strw2binl(str))) }
199   -function b64MD5(str) { return binl2b64(coreMD5(str2binl(str))) }
200   -function b64MD5w(str) { return binl2b64(coreMD5(strw2binl(str))) }
201   -/* Backward compatibility */
202   -function calcMD5(str) { return binl2hex(coreMD5(str2binl(str))) }
203   -module.exports = md5
\ No newline at end of file
1   -var ERROR_CONF={KEY_ERR:311,KEY_ERR_MSG:'key格式错误',PARAM_ERR:310,PARAM_ERR_MSG:'请求参数信息有误',SYSTEM_ERR:600,SYSTEM_ERR_MSG:'系统错误',WX_ERR_CODE:1000,WX_OK_CODE:200};var BASE_URL='https://apis.map.qq.com/ws/';var URL_SEARCH=BASE_URL+'place/v1/search';var URL_SUGGESTION=BASE_URL+'place/v1/suggestion';var URL_GET_GEOCODER=BASE_URL+'geocoder/v1/';var URL_CITY_LIST=BASE_URL+'district/v1/list';var URL_AREA_LIST=BASE_URL+'district/v1/getchildren';var URL_DISTANCE=BASE_URL+'distance/v1/';var URL_DIRECTION=BASE_URL+'direction/v1/';var MODE={driving:'driving',transit:'transit'};var EARTH_RADIUS=6378136.49;var Utils={safeAdd(x,y){var lsw=(x&0xffff)+(y&0xffff);var msw=(x>>16)+(y>>16)+(lsw>>16);return(msw<<16)|(lsw&0xffff)},bitRotateLeft(num,cnt){return(num<<cnt)|(num>>>(32-cnt))},md5cmn(q,a,b,x,s,t){return this.safeAdd(this.bitRotateLeft(this.safeAdd(this.safeAdd(a,q),this.safeAdd(x,t)),s),b)},md5ff(a,b,c,d,x,s,t){return this.md5cmn((b&c)|(~b&d),a,b,x,s,t)},md5gg(a,b,c,d,x,s,t){return this.md5cmn((b&d)|(c&~d),a,b,x,s,t)},md5hh(a,b,c,d,x,s,t){return this.md5cmn(b^c^d,a,b,x,s,t)},md5ii(a,b,c,d,x,s,t){return this.md5cmn(c^(b|~d),a,b,x,s,t)},binlMD5(x,len){x[len>>5]|=0x80<<(len%32);x[((len+64)>>>9<<4)+14]=len;var i;var olda;var oldb;var oldc;var oldd;var a=1732584193;var b=-271733879;var c=-1732584194;var d=271733878;for(i=0;i<x.length;i+=16){olda=a;oldb=b;oldc=c;oldd=d;a=this.md5ff(a,b,c,d,x[i],7,-680876936);d=this.md5ff(d,a,b,c,x[i+1],12,-389564586);c=this.md5ff(c,d,a,b,x[i+2],17,606105819);b=this.md5ff(b,c,d,a,x[i+3],22,-1044525330);a=this.md5ff(a,b,c,d,x[i+4],7,-176418897);d=this.md5ff(d,a,b,c,x[i+5],12,1200080426);c=this.md5ff(c,d,a,b,x[i+6],17,-1473231341);b=this.md5ff(b,c,d,a,x[i+7],22,-45705983);a=this.md5ff(a,b,c,d,x[i+8],7,1770035416);d=this.md5ff(d,a,b,c,x[i+9],12,-1958414417);c=this.md5ff(c,d,a,b,x[i+10],17,-42063);b=this.md5ff(b,c,d,a,x[i+11],22,-1990404162);a=this.md5ff(a,b,c,d,x[i+12],7,1804603682);d=this.md5ff(d,a,b,c,x[i+13],12,-40341101);c=this.md5ff(c,d,a,b,x[i+14],17,-1502002290);b=this.md5ff(b,c,d,a,x[i+15],22,1236535329);a=this.md5gg(a,b,c,d,x[i+1],5,-165796510);d=this.md5gg(d,a,b,c,x[i+6],9,-1069501632);c=this.md5gg(c,d,a,b,x[i+11],14,643717713);b=this.md5gg(b,c,d,a,x[i],20,-373897302);a=this.md5gg(a,b,c,d,x[i+5],5,-701558691);d=this.md5gg(d,a,b,c,x[i+10],9,38016083);c=this.md5gg(c,d,a,b,x[i+15],14,-660478335);b=this.md5gg(b,c,d,a,x[i+4],20,-405537848);a=this.md5gg(a,b,c,d,x[i+9],5,568446438);d=this.md5gg(d,a,b,c,x[i+14],9,-1019803690);c=this.md5gg(c,d,a,b,x[i+3],14,-187363961);b=this.md5gg(b,c,d,a,x[i+8],20,1163531501);a=this.md5gg(a,b,c,d,x[i+13],5,-1444681467);d=this.md5gg(d,a,b,c,x[i+2],9,-51403784);c=this.md5gg(c,d,a,b,x[i+7],14,1735328473);b=this.md5gg(b,c,d,a,x[i+12],20,-1926607734);a=this.md5hh(a,b,c,d,x[i+5],4,-378558);d=this.md5hh(d,a,b,c,x[i+8],11,-2022574463);c=this.md5hh(c,d,a,b,x[i+11],16,1839030562);b=this.md5hh(b,c,d,a,x[i+14],23,-35309556);a=this.md5hh(a,b,c,d,x[i+1],4,-1530992060);d=this.md5hh(d,a,b,c,x[i+4],11,1272893353);c=this.md5hh(c,d,a,b,x[i+7],16,-155497632);b=this.md5hh(b,c,d,a,x[i+10],23,-1094730640);a=this.md5hh(a,b,c,d,x[i+13],4,681279174);d=this.md5hh(d,a,b,c,x[i],11,-358537222);c=this.md5hh(c,d,a,b,x[i+3],16,-722521979);b=this.md5hh(b,c,d,a,x[i+6],23,76029189);a=this.md5hh(a,b,c,d,x[i+9],4,-640364487);d=this.md5hh(d,a,b,c,x[i+12],11,-421815835);c=this.md5hh(c,d,a,b,x[i+15],16,530742520);b=this.md5hh(b,c,d,a,x[i+2],23,-995338651);a=this.md5ii(a,b,c,d,x[i],6,-198630844);d=this.md5ii(d,a,b,c,x[i+7],10,1126891415);c=this.md5ii(c,d,a,b,x[i+14],15,-1416354905);b=this.md5ii(b,c,d,a,x[i+5],21,-57434055);a=this.md5ii(a,b,c,d,x[i+12],6,1700485571);d=this.md5ii(d,a,b,c,x[i+3],10,-1894986606);c=this.md5ii(c,d,a,b,x[i+10],15,-1051523);b=this.md5ii(b,c,d,a,x[i+1],21,-2054922799);a=this.md5ii(a,b,c,d,x[i+8],6,1873313359);d=this.md5ii(d,a,b,c,x[i+15],10,-30611744);c=this.md5ii(c,d,a,b,x[i+6],15,-1560198380);b=this.md5ii(b,c,d,a,x[i+13],21,1309151649);a=this.md5ii(a,b,c,d,x[i+4],6,-145523070);d=this.md5ii(d,a,b,c,x[i+11],10,-1120210379);c=this.md5ii(c,d,a,b,x[i+2],15,718787259);b=this.md5ii(b,c,d,a,x[i+9],21,-343485551);a=this.safeAdd(a,olda);b=this.safeAdd(b,oldb);c=this.safeAdd(c,oldc);d=this.safeAdd(d,oldd)}return[a,b,c,d]},binl2rstr(input){var i;var output='';var length32=input.length*32;for(i=0;i<length32;i+=8){output+=String.fromCharCode((input[i>>5]>>>(i%32))&0xff)}return output},rstr2binl(input){var i;var output=[];output[(input.length>>2)-1]=undefined;for(i=0;i<output.length;i+=1){output[i]=0}var length8=input.length*8;for(i=0;i<length8;i+=8){output[i>>5]|=(input.charCodeAt(i/8)&0xff)<<(i%32)}return output},rstrMD5(s){return this.binl2rstr(this.binlMD5(this.rstr2binl(s),s.length*8))},rstrHMACMD5(key,data){var i;var bkey=this.rstr2binl(key);var ipad=[];var opad=[];var hash;ipad[15]=opad[15]=undefined;if(bkey.length>16){bkey=this.binlMD5(bkey,key.length*8)}for(i=0;i<16;i+=1){ipad[i]=bkey[i]^0x36363636;opad[i]=bkey[i]^0x5c5c5c5c}hash=this.binlMD5(ipad.concat(this.rstr2binl(data)),512+data.length*8);return this.binl2rstr(this.binlMD5(opad.concat(hash),512+128))},rstr2hex(input){var hexTab='0123456789abcdef';var output='';var x;var i;for(i=0;i<input.length;i+=1){x=input.charCodeAt(i);output+=hexTab.charAt((x>>>4)&0x0f)+hexTab.charAt(x&0x0f)}return output},str2rstrUTF8(input){return unescape(encodeURIComponent(input))},rawMD5(s){return this.rstrMD5(this.str2rstrUTF8(s))},hexMD5(s){return this.rstr2hex(this.rawMD5(s))},rawHMACMD5(k,d){return this.rstrHMACMD5(this.str2rstrUTF8(k),str2rstrUTF8(d))},hexHMACMD5(k,d){return this.rstr2hex(this.rawHMACMD5(k,d))},md5(string,key,raw){if(!key){if(!raw){return this.hexMD5(string)}return this.rawMD5(string)}if(!raw){return this.hexHMACMD5(key,string)}return this.rawHMACMD5(key,string)},getSig(requestParam,sk,feature,mode){var sig=null;var requestArr=[];Object.keys(requestParam).sort().forEach(function(key){requestArr.push(key+'='+requestParam[key])});if(feature=='search'){sig='/ws/place/v1/search?'+requestArr.join('&')+sk}if(feature=='suggest'){sig='/ws/place/v1/suggestion?'+requestArr.join('&')+sk}if(feature=='reverseGeocoder'){sig='/ws/geocoder/v1/?'+requestArr.join('&')+sk}if(feature=='geocoder'){sig='/ws/geocoder/v1/?'+requestArr.join('&')+sk}if(feature=='getCityList'){sig='/ws/district/v1/list?'+requestArr.join('&')+sk}if(feature=='getDistrictByCityId'){sig='/ws/district/v1/getchildren?'+requestArr.join('&')+sk}if(feature=='calculateDistance'){sig='/ws/distance/v1/?'+requestArr.join('&')+sk}if(feature=='direction'){sig='/ws/direction/v1/'+mode+'?'+requestArr.join('&')+sk}sig=this.md5(sig);return sig},location2query(data){if(typeof data=='string'){return data}var query='';for(var i=0;i<data.length;i++){var d=data[i];if(!!query){query+=';'}if(d.location){query=query+d.location.lat+','+d.location.lng}if(d.latitude&&d.longitude){query=query+d.latitude+','+d.longitude}}return query},rad(d){return d*Math.PI/180.0},getEndLocation(location){var to=location.split(';');var endLocation=[];for(var i=0;i<to.length;i++){endLocation.push({lat:parseFloat(to[i].split(',')[0]),lng:parseFloat(to[i].split(',')[1])})}return endLocation},getDistance(latFrom,lngFrom,latTo,lngTo){var radLatFrom=this.rad(latFrom);var radLatTo=this.rad(latTo);var a=radLatFrom-radLatTo;var b=this.rad(lngFrom)-this.rad(lngTo);var distance=2*Math.asin(Math.sqrt(Math.pow(Math.sin(a/2),2)+Math.cos(radLatFrom)*Math.cos(radLatTo)*Math.pow(Math.sin(b/2),2)));distance=distance*EARTH_RADIUS;distance=Math.round(distance*10000)/10000;return parseFloat(distance.toFixed(0))},getWXLocation(success,fail,complete){wx.getLocation({type:'gcj02',success:success,fail:fail,complete:complete})},getLocationParam(location){if(typeof location=='string'){var locationArr=location.split(',');if(locationArr.length===2){location={latitude:location.split(',')[0],longitude:location.split(',')[1]}}else{location={}}}return location},polyfillParam(param){param.success=param.success||function(){};param.fail=param.fail||function(){};param.complete=param.complete||function(){}},checkParamKeyEmpty(param,key){if(!param[key]){var errconf=this.buildErrorConfig(ERROR_CONF.PARAM_ERR,ERROR_CONF.PARAM_ERR_MSG+key+'参数格式有误');param.fail(errconf);param.complete(errconf);return true}return false},checkKeyword(param){return!this.checkParamKeyEmpty(param,'keyword')},checkLocation(param){var location=this.getLocationParam(param.location);if(!location||!location.latitude||!location.longitude){var errconf=this.buildErrorConfig(ERROR_CONF.PARAM_ERR,ERROR_CONF.PARAM_ERR_MSG+' location参数格式有误');param.fail(errconf);param.complete(errconf);return false}return true},buildErrorConfig(errCode,errMsg){return{status:errCode,message:errMsg}},handleData(param,data,feature){if(feature=='search'){var searchResult=data.data;var searchSimplify=[];for(var i=0;i<searchResult.length;i++){searchSimplify.push({id:searchResult[i].id||null,title:searchResult[i].title||null,latitude:searchResult[i].location&&searchResult[i].location.lat||null,longitude:searchResult[i].location&&searchResult[i].location.lng||null,address:searchResult[i].address||null,category:searchResult[i].category||null,tel:searchResult[i].tel||null,adcode:searchResult[i].ad_info&&searchResult[i].ad_info.adcode||null,city:searchResult[i].ad_info&&searchResult[i].ad_info.city||null,district:searchResult[i].ad_info&&searchResult[i].ad_info.district||null,province:searchResult[i].ad_info&&searchResult[i].ad_info.province||null})}param.success(data,{searchResult:searchResult,searchSimplify:searchSimplify})}else if(feature=='suggest'){var suggestResult=data.data;var suggestSimplify=[];for(var i=0;i<suggestResult.length;i++){suggestSimplify.push({adcode:suggestResult[i].adcode||null,address:suggestResult[i].address||null,category:suggestResult[i].category||null,city:suggestResult[i].city||null,district:suggestResult[i].district||null,id:suggestResult[i].id||null,latitude:suggestResult[i].location&&suggestResult[i].location.lat||null,longitude:suggestResult[i].location&&suggestResult[i].location.lng||null,province:suggestResult[i].province||null,title:suggestResult[i].title||null,type:suggestResult[i].type||null})}param.success(data,{suggestResult:suggestResult,suggestSimplify:suggestSimplify})}else if(feature=='reverseGeocoder'){var reverseGeocoderResult=data.result;var reverseGeocoderSimplify={address:reverseGeocoderResult.address||null,latitude:reverseGeocoderResult.location&&reverseGeocoderResult.location.lat||null,longitude:reverseGeocoderResult.location&&reverseGeocoderResult.location.lng||null,adcode:reverseGeocoderResult.ad_info&&reverseGeocoderResult.ad_info.adcode||null,city:reverseGeocoderResult.address_component&&reverseGeocoderResult.address_component.city||null,district:reverseGeocoderResult.address_component&&reverseGeocoderResult.address_component.district||null,nation:reverseGeocoderResult.address_component&&reverseGeocoderResult.address_component.nation||null,province:reverseGeocoderResult.address_component&&reverseGeocoderResult.address_component.province||null,street:reverseGeocoderResult.address_component&&reverseGeocoderResult.address_component.street||null,street_number:reverseGeocoderResult.address_component&&reverseGeocoderResult.address_component.street_number||null,recommend:reverseGeocoderResult.formatted_addresses&&reverseGeocoderResult.formatted_addresses.recommend||null,rough:reverseGeocoderResult.formatted_addresses&&reverseGeocoderResult.formatted_addresses.rough||null};if(reverseGeocoderResult.pois){var pois=reverseGeocoderResult.pois;var poisSimplify=[];for(var i=0;i<pois.length;i++){poisSimplify.push({id:pois[i].id||null,title:pois[i].title||null,latitude:pois[i].location&&pois[i].location.lat||null,longitude:pois[i].location&&pois[i].location.lng||null,address:pois[i].address||null,category:pois[i].category||null,adcode:pois[i].ad_info&&pois[i].ad_info.adcode||null,city:pois[i].ad_info&&pois[i].ad_info.city||null,district:pois[i].ad_info&&pois[i].ad_info.district||null,province:pois[i].ad_info&&pois[i].ad_info.province||null})}param.success(data,{reverseGeocoderResult:reverseGeocoderResult,reverseGeocoderSimplify:reverseGeocoderSimplify,pois:pois,poisSimplify:poisSimplify})}else{param.success(data,{reverseGeocoderResult:reverseGeocoderResult,reverseGeocoderSimplify:reverseGeocoderSimplify})}}else if(feature=='geocoder'){var geocoderResult=data.result;var geocoderSimplify={title:geocoderResult.title||null,latitude:geocoderResult.location&&geocoderResult.location.lat||null,longitude:geocoderResult.location&&geocoderResult.location.lng||null,adcode:geocoderResult.ad_info&&geocoderResult.ad_info.adcode||null,province:geocoderResult.address_components&&geocoderResult.address_components.province||null,city:geocoderResult.address_components&&geocoderResult.address_components.city||null,district:geocoderResult.address_components&&geocoderResult.address_components.district||null,street:geocoderResult.address_components&&geocoderResult.address_components.street||null,street_number:geocoderResult.address_components&&geocoderResult.address_components.street_number||null,level:geocoderResult.level||null};param.success(data,{geocoderResult:geocoderResult,geocoderSimplify:geocoderSimplify})}else if(feature=='getCityList'){var provinceResult=data.result[0];var cityResult=data.result[1];var districtResult=data.result[2];param.success(data,{provinceResult:provinceResult,cityResult:cityResult,districtResult:districtResult})}else if(feature=='getDistrictByCityId'){var districtByCity=data.result[0];param.success(data,districtByCity)}else if(feature=='calculateDistance'){var calculateDistanceResult=data.result.elements;var distance=[];for(var i=0;i<calculateDistanceResult.length;i++){distance.push(calculateDistanceResult[i].distance)}param.success(data,{calculateDistanceResult:calculateDistanceResult,distance:distance})}else if(feature=='direction'){var direction=data.result.routes;param.success(data,direction)}else{param.success(data)}},buildWxRequestConfig(param,options,feature){var that=this;options.header={"content-type":"application/json"};options.method='GET';options.success=function(res){var data=res.data;if(data.status===0){that.handleData(param,data,feature)}else{param.fail(data)}};options.fail=function(res){res.statusCode=ERROR_CONF.WX_ERR_CODE;param.fail(that.buildErrorConfig(ERROR_CONF.WX_ERR_CODE,res.errMsg))};options.complete=function(res){var statusCode=+res.statusCode;switch(statusCode){case ERROR_CONF.WX_ERR_CODE:{param.complete(that.buildErrorConfig(ERROR_CONF.WX_ERR_CODE,res.errMsg));break}case ERROR_CONF.WX_OK_CODE:{var data=res.data;if(data.status===0){param.complete(data)}else{param.complete(that.buildErrorConfig(data.status,data.message))}break}default:{param.complete(that.buildErrorConfig(ERROR_CONF.SYSTEM_ERR,ERROR_CONF.SYSTEM_ERR_MSG))}}};return options},locationProcess(param,locationsuccess,locationfail,locationcomplete){var that=this;locationfail=locationfail||function(res){res.statusCode=ERROR_CONF.WX_ERR_CODE;param.fail(that.buildErrorConfig(ERROR_CONF.WX_ERR_CODE,res.errMsg))};locationcomplete=locationcomplete||function(res){if(res.statusCode==ERROR_CONF.WX_ERR_CODE){param.complete(that.buildErrorConfig(ERROR_CONF.WX_ERR_CODE,res.errMsg))}};if(!param.location){that.getWXLocation(locationsuccess,locationfail,locationcomplete)}else if(that.checkLocation(param)){var location=Utils.getLocationParam(param.location);locationsuccess(location)}}};class QQMapWX{constructor(options){if(!options.key){throw Error('key值不能为空')}this.key=options.key};search(options){var that=this;options=options||{};Utils.polyfillParam(options);if(!Utils.checkKeyword(options)){return}var requestParam={keyword:options.keyword,orderby:options.orderby||'_distance',page_size:options.page_size||10,page_index:options.page_index||1,output:'json',key:that.key};if(options.address_format){requestParam.address_format=options.address_format}if(options.filter){requestParam.filter=options.filter}var distance=options.distance||"1000";var auto_extend=options.auto_extend||1;var region=null;var rectangle=null;if(options.region){region=options.region}if(options.rectangle){rectangle=options.rectangle}var locationsuccess=function(result){if(region&&!rectangle){requestParam.boundary="region("+region+","+auto_extend+","+result.latitude+","+result.longitude+")";if(options.sig){requestParam.sig=Utils.getSig(requestParam,options.sig,'search')}}else if(rectangle&&!region){requestParam.boundary="rectangle("+rectangle+")";if(options.sig){requestParam.sig=Utils.getSig(requestParam,options.sig,'search')}}else{requestParam.boundary="nearby("+result.latitude+","+result.longitude+","+distance+","+auto_extend+")";if(options.sig){requestParam.sig=Utils.getSig(requestParam,options.sig,'search')}}wx.request(Utils.buildWxRequestConfig(options,{url:URL_SEARCH,data:requestParam},'search'))};Utils.locationProcess(options,locationsuccess)};getSuggestion(options){var that=this;options=options||{};Utils.polyfillParam(options);if(!Utils.checkKeyword(options)){return}var requestParam={keyword:options.keyword,region:options.region||'全国',region_fix:options.region_fix||0,policy:options.policy||0,page_size:options.page_size||10,page_index:options.page_index||1,get_subpois:options.get_subpois||0,output:'json',key:that.key};if(options.address_format){requestParam.address_format=options.address_format}if(options.filter){requestParam.filter=options.filter}if(options.location){var locationsuccess=function(result){requestParam.location=result.latitude+','+result.longitude;if(options.sig){requestParam.sig=Utils.getSig(requestParam,options.sig,'suggest')}wx.request(Utils.buildWxRequestConfig(options,{url:URL_SUGGESTION,data:requestParam},"suggest"))};Utils.locationProcess(options,locationsuccess)}else{if(options.sig){requestParam.sig=Utils.getSig(requestParam,options.sig,'suggest')}wx.request(Utils.buildWxRequestConfig(options,{url:URL_SUGGESTION,data:requestParam},"suggest"))}};reverseGeocoder(options){var that=this;options=options||{};Utils.polyfillParam(options);var requestParam={coord_type:options.coord_type||5,get_poi:options.get_poi||0,output:'json',key:that.key};if(options.poi_options){requestParam.poi_options=options.poi_options}var locationsuccess=function(result){requestParam.location=result.latitude+','+result.longitude;if(options.sig){requestParam.sig=Utils.getSig(requestParam,options.sig,'reverseGeocoder')}wx.request(Utils.buildWxRequestConfig(options,{url:URL_GET_GEOCODER,data:requestParam},'reverseGeocoder'))};Utils.locationProcess(options,locationsuccess)};geocoder(options){var that=this;options=options||{};Utils.polyfillParam(options);if(Utils.checkParamKeyEmpty(options,'address')){return}var requestParam={address:options.address,output:'json',key:that.key};if(options.region){requestParam.region=options.region}if(options.sig){requestParam.sig=Utils.getSig(requestParam,options.sig,'geocoder')}wx.request(Utils.buildWxRequestConfig(options,{url:URL_GET_GEOCODER,data:requestParam},'geocoder'))};getCityList(options){var that=this;options=options||{};Utils.polyfillParam(options);var requestParam={output:'json',key:that.key};if(options.sig){requestParam.sig=Utils.getSig(requestParam,options.sig,'getCityList')}wx.request(Utils.buildWxRequestConfig(options,{url:URL_CITY_LIST,data:requestParam},'getCityList'))};getDistrictByCityId(options){var that=this;options=options||{};Utils.polyfillParam(options);if(Utils.checkParamKeyEmpty(options,'id')){return}var requestParam={id:options.id||'',output:'json',key:that.key};if(options.sig){requestParam.sig=Utils.getSig(requestParam,options.sig,'getDistrictByCityId')}wx.request(Utils.buildWxRequestConfig(options,{url:URL_AREA_LIST,data:requestParam},'getDistrictByCityId'))};calculateDistance(options){var that=this;options=options||{};Utils.polyfillParam(options);if(Utils.checkParamKeyEmpty(options,'to')){return}var requestParam={mode:options.mode||'walking',to:Utils.location2query(options.to),output:'json',key:that.key};if(options.from){options.location=options.from}if(requestParam.mode=='straight'){var locationsuccess=function(result){var locationTo=Utils.getEndLocation(requestParam.to);var data={message:"query ok",result:{elements:[]},status:0};for(var i=0;i<locationTo.length;i++){data.result.elements.push({distance:Utils.getDistance(result.latitude,result.longitude,locationTo[i].lat,locationTo[i].lng),duration:0,from:{lat:result.latitude,lng:result.longitude},to:{lat:locationTo[i].lat,lng:locationTo[i].lng}})}var calculateResult=data.result.elements;var distanceResult=[];for(var i=0;i<calculateResult.length;i++){distanceResult.push(calculateResult[i].distance)}return options.success(data,{calculateResult:calculateResult,distanceResult:distanceResult})};Utils.locationProcess(options,locationsuccess)}else{var locationsuccess=function(result){requestParam.from=result.latitude+','+result.longitude;if(options.sig){requestParam.sig=Utils.getSig(requestParam,options.sig,'calculateDistance')}wx.request(Utils.buildWxRequestConfig(options,{url:URL_DISTANCE,data:requestParam},'calculateDistance'))};Utils.locationProcess(options,locationsuccess)}};direction(options){var that=this;options=options||{};Utils.polyfillParam(options);if(Utils.checkParamKeyEmpty(options,'to')){return}var requestParam={output:'json',key:that.key};if(typeof options.to=='string'){requestParam.to=options.to}else{requestParam.to=options.to.latitude+','+options.to.longitude}var SET_URL_DIRECTION=null;options.mode=options.mode||MODE.driving;SET_URL_DIRECTION=URL_DIRECTION+options.mode;if(options.from){options.location=options.from}if(options.mode==MODE.driving){if(options.from_poi){requestParam.from_poi=options.from_poi}if(options.heading){requestParam.heading=options.heading}if(options.speed){requestParam.speed=options.speed}if(options.accuracy){requestParam.accuracy=options.accuracy}if(options.road_type){requestParam.road_type=options.road_type}if(options.to_poi){requestParam.to_poi=options.to_poi}if(options.from_track){requestParam.from_track=options.from_track}if(options.waypoints){requestParam.waypoints=options.waypoints}if(options.policy){requestParam.policy=options.policy}if(options.plate_number){requestParam.plate_number=options.plate_number}}if(options.mode==MODE.transit){if(options.departure_time){requestParam.departure_time=options.departure_time}if(options.policy){requestParam.policy=options.policy}}var locationsuccess=function(result){requestParam.from=result.latitude+','+result.longitude;if(options.sig){requestParam.sig=Utils.getSig(requestParam,options.sig,'direction',options.mode)}wx.request(Utils.buildWxRequestConfig(options,{url:SET_URL_DIRECTION,data:requestParam},'direction'))};Utils.locationProcess(options,locationsuccess)}};module.exports=QQMapWX;
\ No newline at end of file
publicLoginSubPage/other/code.vue renamed from pages/personal/code.vue
publicLoginSubPage/other/findPassword.vue renamed from pages/personal/findPassword.vue
publicLoginSubPage/other/set.vue renamed from pages/personal/set.vue
publicLoginSubPage/other/static/code.scss renamed from pages/personal/static/code.scss
publicLoginSubPage/other/static/findPassword.scss renamed from pages/personal/static/findPassword.scss
publicLoginSubPage/other/static/set.scss renamed from pages/personal/static/set.scss
... ... @@ -122,22 +122,12 @@ export default {
122 122 uni.showToast({
123 123 title: '登录成功~',
124 124 icon: 'none'
  125 + }).then(res => {
  126 + uni.reLaunch({
  127 + url: '/pages/personal/personal'
125 128 });
126   - this.saveUserInfo();
127   - // #ifndef MP
128   - // setTimeout(() => {
129   - // uni.navigateBack();
130   - // }, 500);
131   - uni.switchTab({
132   - url: '../personal/personal'
133   - });
134   - // #endif
135   - // #ifdef MP
136   - // uni.navigateBack();
137   - uni.switchTab({
138   - url: '../personal/personal'
139 129 });
140   - // #endif
  130 + this.saveUserInfo();
141 131 }
142 132 })
143 133 .catch(e => {
... ... @@ -154,12 +144,12 @@ export default {
154 144 },
155 145 openCodeFunc() {
156 146 uni.navigateTo({
157   - url: '../personal/code'
  147 + url: '../other/code'
158 148 });
159 149 },
160 150 findPassrordFunc() {
161 151 uni.navigateTo({
162   - url: '../personal/findPassword'
  152 + url: '../other/findPassword'
163 153 });
164 154 },
165 155 showPasswordMode() {
... ...
publicLoginSubPage/public/static/login.scss renamed from pages/public/static/login.scss
sysNotifySubPage/sysNotifyPage/notifyDetail.vue renamed from pages/systemNotify/notifyDetail.vue
sysNotifySubPage/sysNotifyPage/static/notifyDetail.scss renamed from pages/systemNotify/static/notifyDetail.scss
sysNotifySubPage/sysNotifyPage/static/systemNotify.scss renamed from pages/systemNotify/static/systemNotify.scss
sysNotifySubPage/sysNotifyPage/systemNotify.vue renamed from pages/systemNotify/systemNotify.vue
... ... @@ -7,14 +7,13 @@
7 7 <u-form-item
8 8 label="类型"
9 9 prop="userInfo.sex"
10   - borderBottom
11 10 @click="
12 11 showType = true;
13 12 hideKeyboard();
14 13 "
15 14 ref="item1"
16 15 >
17   - <u--input v-model="model1.userInfo.type" placeholder="请选择类型" border="none"></u--input>
  16 + <u--input v-model="model1.userInfo.type" placeholder="请选择类型" border="surround"></u--input>
18 17 <u-icon slot="right" name="arrow-right"></u-icon>
19 18 </u-form-item>
20 19 </u--form>
... ... @@ -38,19 +37,15 @@
38 37 </view>
39 38 </mescroll-body>
40 39 </view>
41   - <f-tabbar></f-tabbar>
42 40 </view>
43 41 </template>
44 42
45 43 <script>
46   -import fTabbar from '@/components/module/f-tabbar/f-tabbar';
47 44 import MescrollMixin from '@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js';
48 45
49 46 export default {
50 47 mixins: [MescrollMixin], // 使用mixin (在main.js注册全局组件)
51   - components: {
52   - fTabbar
53   - },
  48 +
54 49 data() {
55 50 return {
56 51 model1: {
... ... @@ -61,6 +56,10 @@ export default {
61 56 showType: false,
62 57 actions: [
63 58 {
  59 + name: '全部',
  60 + value: ''
  61 + },
  62 + {
64 63 name: '会议',
65 64 value: 'MEETING'
66 65 },
... ...
1   -export default {
2   - props: {
3   - // 显示文字
4   - title: {
5   - type: String,
6   - default: uni.$u.props.alert.title
7   - },
8   - // 主题,success/warning/info/error
9   - type: {
10   - type: String,
11   - default: uni.$u.props.alert.type
12   - },
13   - // 辅助性文字
14   - description: {
15   - type: String,
16   - default: uni.$u.props.alert.description
17   - },
18   - // 是否可关闭
19   - closable: {
20   - type: Boolean,
21   - default: uni.$u.props.alert.closable
22   - },
23   - // 是否显示图标
24   - showIcon: {
25   - type: Boolean,
26   - default: uni.$u.props.alert.showIcon
27   - },
28   - // 浅或深色调,light-浅色,dark-深色
29   - effect: {
30   - type: String,
31   - default: uni.$u.props.alert.effect
32   - },
33   - // 文字是否居中
34   - center: {
35   - type: Boolean,
36   - default: uni.$u.props.alert.center
37   - },
38   - // 字体大小
39   - fontSize: {
40   - type: [String, Number],
41   - default: uni.$u.props.alert.fontSize
42   - }
43   - }
44   -}
1   -<template>
2   - <u-transition
3   - mode="fade"
4   - :show="show"
5   - >
6   - <view
7   - class="u-alert"
8   - :class="[`u-alert--${type}--${effect}`]"
9   - @tap.stop="clickHandler"
10   - :style="[$u.addStyle(customStyle)]"
11   - >
12   - <view
13   - class="u-alert__icon"
14   - v-if="showIcon"
15   - >
16   - <u-icon
17   - :name="iconName"
18   - size="18"
19   - :color="iconColor"
20   - ></u-icon>
21   - </view>
22   - <view
23   - class="u-alert__content"
24   - :style="[{
25   - paddingRight: closable ? '20px' : 0
26   - }]"
27   - >
28   - <text
29   - class="u-alert__content__title"
30   - v-if="title"
31   - :style="[{
32   - fontSize: $u.addUnit(fontSize),
33   - textAlign: center ? 'center' : 'left'
34   - }]"
35   - :class="[effect === 'dark' ? 'u-alert__text--dark' : `u-alert__text--${type}--light`]"
36   - >{{ title }}</text>
37   - <text
38   - class="u-alert__content__desc"
39   - v-if="description"
40   - :style="[{
41   - fontSize: $u.addUnit(fontSize),
42   - textAlign: center ? 'center' : 'left'
43   - }]"
44   - :class="[effect === 'dark' ? 'u-alert__text--dark' : `u-alert__text--${type}--light`]"
45   - >{{ description }}</text>
46   - </view>
47   - <view
48   - class="u-alert__close"
49   - v-if="closable"
50   - @tap.stop="closeHandler"
51   - >
52   - <u-icon
53   - name="close"
54   - :color="iconColor"
55   - size="15"
56   - ></u-icon>
57   - </view>
58   - </view>
59   - </u-transition>
60   -</template>
61   -
62   -<script>
63   - import props from './props.js';
64   - /**
65   - * Alert 警告提示
66   - * @description 警告提示,展现需要关注的信息。
67   - * @tutorial https://www.uviewui.com/components/alertTips.html
68   - *
69   - * @property {String} title 显示的文字
70   - * @property {String} type 使用预设的颜色 (默认 'warning' )
71   - * @property {String} description 辅助性文字,颜色比title浅一点,字号也小一点,可选
72   - * @property {Boolean} closable 关闭按钮(默认为叉号icon图标) (默认 false )
73   - * @property {Boolean} showIcon 是否显示左边的辅助图标 ( 默认 false )
74   - * @property {String} effect 多图时,图片缩放裁剪的模式 (默认 'light' )
75   - * @property {Boolean} center 文字是否居中 (默认 false )
76   - * @property {String | Number} fontSize 字体大小 (默认 14 )
77   - * @property {Object} customStyle 定义需要用到的外部样式
78   - * @event {Function} click 点击组件时触发
79   - * @example <u-alert :title="title" type = "warning" :closable="closable" :description = "description"></u-alert>
80   - */
81   - export default {
82   - name: 'u-alert',
83   - mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
84   - data() {
85   - return {
86   - show: true
87   - }
88   - },
89   - computed: {
90   - iconColor() {
91   - return this.effect === 'light' ? this.type : '#fff'
92   - },
93   - // 不同主题对应不同的图标
94   - iconName() {
95   - switch (this.type) {
96   - case 'success':
97   - return 'checkmark-circle-fill';
98   - break;
99   - case 'error':
100   - return 'close-circle-fill';
101   - break;
102   - case 'warning':
103   - return 'error-circle-fill';
104   - break;
105   - case 'info':
106   - return 'info-circle-fill';
107   - break;
108   - case 'primary':
109   - return 'more-circle-fill';
110   - break;
111   - default:
112   - return 'error-circle-fill';
113   - }
114   - }
115   - },
116   - methods: {
117   - // 点击内容
118   - clickHandler() {
119   - this.$emit('click')
120   - },
121   - // 点击关闭按钮
122   - closeHandler() {
123   - this.show = false
124   - }
125   - }
126   - }
127   -</script>
128   -
129   -<style lang="scss" scoped>
130   - @import "../../libs/css/components.scss";
131   -
132   - .u-alert {
133   - position: relative;
134   - background-color: $u-primary;
135   - padding: 8px 10px;
136   - @include flex(row);
137   - align-items: center;
138   - border-top-left-radius: 4px;
139   - border-top-right-radius: 4px;
140   - border-bottom-left-radius: 4px;
141   - border-bottom-right-radius: 4px;
142   -
143   - &--primary--dark {
144   - background-color: $u-primary;
145   - }
146   -
147   - &--primary--light {
148   - background-color: #ecf5ff;
149   - }
150   -
151   - &--error--dark {
152   - background-color: $u-error;
153   - }
154   -
155   - &--error--light {
156   - background-color: #FEF0F0;
157   - }
158   -
159   - &--success--dark {
160   - background-color: $u-success;
161   - }
162   -
163   - &--success--light {
164   - background-color: #f5fff0;
165   - }
166   -
167   - &--warning--dark {
168   - background-color: $u-warning;
169   - }
170   -
171   - &--warning--light {
172   - background-color: #FDF6EC;
173   - }
174   -
175   - &--info--dark {
176   - background-color: $u-info;
177   - }
178   -
179   - &--info--light {
180   - background-color: #f4f4f5;
181   - }
182   -
183   - &__icon {
184   - margin-right: 5px;
185   - }
186   -
187   - &__content {
188   - @include flex(column);
189   - flex: 1;
190   -
191   - &__title {
192   - color: $u-main-color;
193   - font-size: 14px;
194   - font-weight: bold;
195   - color: #fff;
196   - margin-bottom: 2px;
197   - }
198   -
199   - &__desc {
200   - color: $u-main-color;
201   - font-size: 14px;
202   - flex-wrap: wrap;
203   - color: #fff;
204   - }
205   - }
206   -
207   - &__title--dark,
208   - &__desc--dark {
209   - color: #FFFFFF;
210   - }
211   -
212   - &__text--primary--light,
213   - &__text--primary--light {
214   - color: $u-primary;
215   - }
216   -
217   - &__text--success--light,
218   - &__text--success--light {
219   - color: $u-success;
220   - }
221   -
222   - &__text--warning--light,
223   - &__text--warning--light {
224   - color: $u-warning;
225   - }
226   -
227   - &__text--error--light,
228   - &__text--error--light {
229   - color: $u-error;
230   - }
231   -
232   - &__text--info--light,
233   - &__text--info--light {
234   - color: $u-info;
235   - }
236   -
237   - &__close {
238   - position: absolute;
239   - top: 11px;
240   - right: 10px;
241   - }
242   - }
243   -</style>
1   -export default {
2   - props: {
3   - // 最大输入长度
4   - maxlength: {
5   - type: [String, Number],
6   - default: uni.$u.props.codeInput.maxlength
7   - },
8   - // 是否用圆点填充
9   - dot: {
10   - type: Boolean,
11   - default: uni.$u.props.codeInput.dot
12   - },
13   - // 显示模式,box-盒子模式,line-底部横线模式
14   - mode: {
15   - type: String,
16   - default: uni.$u.props.codeInput.mode
17   - },
18   - // 是否细边框
19   - hairline: {
20   - type: Boolean,
21   - default: uni.$u.props.codeInput.hairline
22   - },
23   - // 字符间的距离
24   - space: {
25   - type: [String, Number],
26   - default: uni.$u.props.codeInput.space
27   - },
28   - // 预置值
29   - value: {
30   - type: [String, Number],
31   - default: uni.$u.props.codeInput.value
32   - },
33   - // 是否自动获取焦点
34   - focus: {
35   - type: Boolean,
36   - default: uni.$u.props.codeInput.focus
37   - },
38   - // 字体是否加粗
39   - bold: {
40   - type: Boolean,
41   - default: uni.$u.props.codeInput.bold
42   - },
43   - // 字体颜色
44   - color: {
45   - type: String,
46   - default: uni.$u.props.codeInput.color
47   - },
48   - // 字体大小
49   - fontSize: {
50   - type: [String, Number],
51   - default: uni.$u.props.codeInput.fontSize
52   - },
53   - // 输入框的大小,宽等于高
54   - size: {
55   - type: [String, Number],
56   - default: uni.$u.props.codeInput.size
57   - },
58   - // 是否隐藏原生键盘,如果想用自定义键盘的话,需设置此参数为true
59   - disabledKeyboard: {
60   - type: Boolean,
61   - default: uni.$u.props.codeInput.disabledKeyboard
62   - },
63   - // 边框和线条颜色
64   - borderColor: {
65   - type: String,
66   - default: uni.$u.props.codeInput.borderColor
67   - },
68   - // 是否禁止输入"."符号
69   - disabledDot: {
70   - type: Boolean,
71   - default: uni.$u.props.codeInput.disabledDot
72   - }
73   - }
74   -}
1   -<template>
2   - <view class="u-code-input">
3   - <view
4   - class="u-code-input__item"
5   - :style="[itemStyle(index)]"
6   - v-for="(item, index) in codeLength"
7   - :key="index"
8   - >
9   - <view
10   - class="u-code-input__item__dot"
11   - v-if="dot && codeArray.length > index"
12   - ></view>
13   - <text
14   - v-else
15   - :style="{
16   - fontSize: $u.addUnit(fontSize),
17   - fontWeight: bold ? 'bold' : 'normal',
18   - color: color
19   - }"
20   - >{{codeArray[index]}}</text>
21   - <view
22   - class="u-code-input__item__line"
23   - v-if="mode === 'line'"
24   - :style="[lineStyle]"
25   - ></view>
26   - </view>
27   - <input
28   - :disabled="disabledKeyboard"
29   - type="number"
30   - :focus="focus"
31   - :value="inputValue"
32   - :maxlength="maxlength"
33   - class="u-code-input__input"
34   - @input="inputHandler"
35   - :style="{
36   - height: $u.addUnit(size)
37   - }"
38   - />
39   - </view>
40   -</template>
41   -
42   -<script>
43   - import props from './props.js';
44   - /**
45   - * CodeInput 验证码输入
46   - * @description 该组件一般用于验证用户短信验证码的场景,也可以结合uView的键盘组件使用
47   - * @tutorial https://www.uviewui.com/components/codeInput.html
48   - * @property {String | Number} maxlength 最大输入长度 (默认 6 )
49   - * @property {Boolean} dot 是否用圆点填充 (默认 false )
50   - * @property {String} mode 显示模式,box-盒子模式,line-底部横线模式 (默认 'box' )
51   - * @property {Boolean} hairline 是否细边框 (默认 false )
52   - * @property {String | Number} space 字符间的距离 (默认 10 )
53   - * @property {String | Number} value 预置值
54   - * @property {Boolean} focus 是否自动获取焦点 (默认 false )
55   - * @property {Boolean} bold 字体和输入横线是否加粗 (默认 false )
56   - * @property {String} color 字体颜色 (默认 '#606266' )
57   - * @property {String | Number} fontSize 字体大小,单位px (默认 18 )
58   - * @property {String | Number} size 输入框的大小,宽等于高 (默认 35 )
59   - * @property {Boolean} disabledKeyboard 是否隐藏原生键盘,如果想用自定义键盘的话,需设置此参数为true (默认 false )
60   - * @property {String} borderColor 边框和线条颜色 (默认 '#c9cacc' )
61   - * @property {Boolean} disabledDot 是否禁止输入"."符号 (默认 true )
62   - *
63   - * @event {Function} change 输入内容发生改变时触发,具体见上方说明 value:当前输入的值
64   - * @event {Function} finish 输入字符个数达maxlength值时触发,见上方说明 value:当前输入的值
65   - * @example <u-code-input v-model="value4" :focus="true"></u-code-input>
66   - */
67   - export default {
68   - name: 'u-code-input',
69   - mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
70   - data() {
71   - return {
72   - inputValue: ''
73   - }
74   - },
75   - watch: {
76   - value: {
77   - immediate: true,
78   - handler(val) {
79   - // 转为字符串,超出部分截掉
80   - this.inputValue = String(val).substring(0, this.maxlength)
81   - }
82   - },
83   - },
84   - computed: {
85   - // 根据长度,循环输入框的个数,因为头条小程序数值不能用于v-for
86   - codeLength() {
87   - return new Array(Number(this.maxlength))
88   - },
89   - // 循环item的样式
90   - itemStyle() {
91   - return index => {
92   - const addUnit = uni.$u.addUnit
93   - const style = {
94   - width: addUnit(this.size),
95   - height: addUnit(this.size)
96   - }
97   - // 盒子模式下,需要额外进行处理
98   - if (this.mode === 'box') {
99   - // 设置盒子的边框,如果是细边框,则设置为0.5px宽度
100   - style.border = `${this.hairline ? 0.5 : 1}px solid ${this.borderColor}`
101   - // 如果盒子间距为0的话
102   - if (uni.$u.getPx(this.space) === 0) {
103   - // 给第一和最后一个盒子设置圆角
104   - if (index === 0) {
105   - style.borderTopLeftRadius = '3px'
106   - style.borderBottomLeftRadius = '3px'
107   - }
108   - if (index === this.codeLength.length - 1) {
109   - style.borderTopRightRadius = '3px'
110   - style.borderBottomRightRadius = '3px'
111   - }
112   - // 最后一个盒子的右边框需要保留
113   - if (index !== this.codeLength.length - 1) {
114   - style.borderRight = 'none'
115   - }
116   - }
117   - }
118   - if (index !== this.codeLength.length - 1) {
119   - // 设置验证码字符之间的距离,通过margin-right设置,最后一个字符,无需右边框
120   - style.marginRight = addUnit(this.space)
121   - } else {
122   - // 最后一个盒子的有边框需要保留
123   - style.marginRight = 0
124   - }
125   -
126   - return style
127   - }
128   - },
129   - // 将输入的值,转为数组,给item历遍时,根据当前的索引显示数组的元素
130   - codeArray() {
131   - return String(this.inputValue).split('')
132   - },
133   - // 下划线模式下,横线的样式
134   - lineStyle() {
135   - const style = {}
136   - style.height = this.hairline ? '2px' : '4px'
137   - style.width = uni.$u.addUnit(this.size)
138   - // 线条模式下,背景色即为边框颜色
139   - style.backgroundColor = this.borderColor
140   - return style
141   - }
142   - },
143   - methods: {
144   - // 监听输入框的值发生变化
145   - inputHandler(e) {
146   - const value = e.detail.value
147   - this.inputValue = value
148   - // 是否允许输入“.”符号
149   - if(this.disabledDot) {
150   - this.$nextTick(() => {
151   - this.inputValue = value.replace('.', '')
152   - })
153   - }
154   - // 未达到maxlength之前,发送change事件,达到后发送finish事件
155   - this.$emit('change', value)
156   - // 修改通过v-model双向绑定的值
157   - this.$emit('input', value)
158   - // 达到用户指定输入长度时,发出完成事件
159   - if (String(value).length >= Number(this.maxlength)) {
160   - this.$emit('finish', value)
161   - }
162   - }
163   - }
164   - }
165   -</script>
166   -
167   -<style lang="scss" scoped>
168   - @import "../../libs/css/components.scss";
169   -
170   - .u-code-input {
171   - @include flex;
172   - position: relative;
173   - overflow: hidden;
174   -
175   - &__item {
176   - @include flex;
177   - justify-content: center;
178   - align-items: center;
179   -
180   - &__text {
181   - font-size: 15px;
182   - color: $u-content-color;
183   - }
184   -
185   - &__dot {
186   - width: 7px;
187   - height: 7px;
188   - border-radius: 100px;
189   - background-color: $u-content-color;
190   - }
191   -
192   - &__line {
193   - position: absolute;
194   - bottom: 0;
195   - height: 4px;
196   - border-radius: 100px;
197   - width: 40px;
198   - background-color: $u-content-color;
199   - }
200   - }
201   -
202   - &__input {
203   - // 之所以需要input输入框,是因为有它才能唤起键盘
204   - // 这里将它设置为两倍的屏幕宽度,再将左边的一半移出屏幕,为了不让用户看到输入的内容
205   - position: absolute;
206   - left: -750rpx;
207   - width: 1500rpx;
208   - top: 0;
209   - background-color: transparent;
210   - text-align: left;
211   - }
212   - }
213   -</style>
1   -export default {
2   - props: {
3   - // 倒计时总秒数
4   - seconds: {
5   - type: [String, Number],
6   - default: uni.$u.props.code.seconds
7   - },
8   - // 尚未开始时提示
9   - startText: {
10   - type: String,
11   - default: uni.$u.props.code.startText
12   - },
13   - // 正在倒计时中的提示
14   - changeText: {
15   - type: String,
16   - default: uni.$u.props.code.changeText
17   - },
18   - // 倒计时结束时的提示
19   - endText: {
20   - type: String,
21   - default: uni.$u.props.code.endText
22   - },
23   - // 是否在H5刷新或各端返回再进入时继续倒计时
24   - keepRunning: {
25   - type: Boolean,
26   - default: uni.$u.props.code.keepRunning
27   - },
28   - // 为了区分多个页面,或者一个页面多个倒计时组件本地存储的继续倒计时变了
29   - uniqueKey: {
30   - type: String,
31   - default: uni.$u.props.code.uniqueKey
32   - }
33   - }
34   -}
1   -<template>
2   - <view class="u-code">
3   - <!-- 此组件功能由js完成,无需写html逻辑 -->
4   - </view>
5   -</template>
6   -
7   -<script>
8   - import props from './props.js';
9   - /**
10   - * Code 验证码输入框
11   - * @description 考虑到用户实际发送验证码的场景,可能是一个按钮,也可能是一段文字,提示语各有不同,所以本组件 不提供界面显示,只提供提示语,由用户将提示语嵌入到具体的场景
12   - * @tutorial https://www.uviewui.com/components/code.html
13   - * @property {String | Number} seconds 倒计时所需的秒数(默认 60 )
14   - * @property {String} startText 开始前的提示语,见官网说明(默认 '获取验证码' )
15   - * @property {String} changeText 倒计时期间的提示语,必须带有字母"x",见官网说明(默认 'X秒重新获取' )
16   - * @property {String} endText 倒计结束的提示语,见官网说明(默认 '重新获取' )
17   - * @property {Boolean} keepRunning 是否在H5刷新或各端返回再进入时继续倒计时( 默认false )
18   - * @property {String} uniqueKey 为了区分多个页面,或者一个页面多个倒计时组件本地存储的继续倒计时变了
19   - *
20   - * @event {Function} change 倒计时期间,每秒触发一次
21   - * @event {Function} start 开始倒计时触发
22   - * @event {Function} end 结束倒计时触发
23   - * @example <u-code ref="uCode" @change="codeChange" seconds="20"></u-code>
24   - */
25   - export default {
26   - name: "u-code",
27   - mixins: [uni.$u.mpMixin, uni.$u.mixin,props],
28   - data() {
29   - return {
30   - secNum: this.seconds,
31   - timer: null,
32   - canGetCode: true, // 是否可以执行验证码操作
33   - }
34   - },
35   - mounted() {
36   - this.checkKeepRunning()
37   - },
38   - watch: {
39   - seconds: {
40   - immediate: true,
41   - handler(n) {
42   - this.secNum = n
43   - }
44   - }
45   - },
46   - methods: {
47   - checkKeepRunning() {
48   - // 获取上一次退出页面(H5还包括刷新)时的时间戳,如果没有上次的保存,此值可能为空
49   - let lastTimestamp = Number(uni.getStorageSync(this.uniqueKey + '_$uCountDownTimestamp'))
50   - if(!lastTimestamp) return this.changeEvent(this.startText)
51   - // 当前秒的时间戳
52   - let nowTimestamp = Math.floor((+ new Date()) / 1000)
53   - // 判断当前的时间戳,是否小于上一次的本该按设定结束,却提前结束的时间戳
54   - if(this.keepRunning && lastTimestamp && lastTimestamp > nowTimestamp) {
55   - // 剩余尚未执行完的倒计秒数
56   - this.secNum = lastTimestamp - nowTimestamp
57   - // 清除本地保存的变量
58   - uni.removeStorageSync(this.uniqueKey + '_$uCountDownTimestamp')
59   - // 开始倒计时
60   - this.start()
61   - } else {
62   - // 如果不存在需要继续上一次的倒计时,执行正常的逻辑
63   - this.changeEvent(this.startText)
64   - }
65   - },
66   - // 开始倒计时
67   - start() {
68   - // 防止快速点击获取验证码的按钮而导致内部产生多个定时器导致混乱
69   - if(this.timer) {
70   - clearInterval(this.timer)
71   - this.timer = null
72   - }
73   - this.$emit('start')
74   - this.canGetCode = false
75   - // 这里放这句,是为了一开始时就提示,否则要等setInterval的1秒后才会有提示
76   - this.changeEvent(this.changeText.replace(/x|X/, this.secNum))
77   - this.setTimeToStorage()
78   - this.timer = setInterval(() => {
79   - if (--this.secNum) {
80   - // 用当前倒计时的秒数替换提示字符串中的"x"字母
81   - this.changeEvent(this.changeText.replace(/x|X/, this.secNum))
82   - } else {
83   - clearInterval(this.timer)
84   - this.timer = null
85   - this.changeEvent(this.endText)
86   - this.secNum = this.seconds
87   - this.$emit('end')
88   - this.canGetCode = true
89   - }
90   - }, 1000)
91   - },
92   - // 重置,可以让用户再次获取验证码
93   - reset() {
94   - this.canGetCode = true
95   - clearInterval(this.timer)
96   - this.secNum = this.seconds
97   - this.changeEvent(this.endText)
98   - },
99   - changeEvent(text) {
100   - this.$emit('change', text)
101   - },
102   - // 保存时间戳,为了防止倒计时尚未结束,H5刷新或者各端的右上角返回上一页再进来
103   - setTimeToStorage() {
104   - if(!this.keepRunning || !this.timer) return
105   - // 记录当前的时间戳,为了下次进入页面,如果还在倒计时内的话,继续倒计时
106   - // 倒计时尚未结束,结果大于0;倒计时已经开始,就会小于初始值,如果等于初始值,说明没有开始倒计时,无需处理
107   - if(this.secNum > 0 && this.secNum <= this.seconds) {
108   - // 获取当前时间戳(+ new Date()为特殊写法),除以1000变成秒,再去除小数部分
109   - let nowTimestamp = Math.floor((+ new Date()) / 1000)
110   - // 将本该结束时候的时间戳保存起来 => 当前时间戳 + 剩余的秒数
111   - uni.setStorage({
112   - key: this.uniqueKey + '_$uCountDownTimestamp',
113   - data: nowTimestamp + Number(this.secNum)
114   - })
115   - }
116   - }
117   - },
118   - // 组件销毁的时候,清除定时器,否则定时器会继续存在,系统不会自动清除
119   - beforeDestroy() {
120   - this.setTimeToStorage()
121   - clearTimeout(this.timer)
122   - this.timer = null
123   - }
124   - }
125   -</script>
126   -
127   -<style lang="scss" scoped>
128   - @import "../../libs/css/components.scss";
129   -</style>
1   -export default {
2   - props: {
3   - // 宫格的name
4   - name: {
5   - type: [String, Number, null],
6   - default: uni.$u.props.gridItem.name
7   - },
8   - // 背景颜色
9   - bgColor: {
10   - type: String,
11   - default: uni.$u.props.gridItem.bgColor
12   - }
13   - }
14   -}
1   -<template>
2   - <!-- #ifndef APP-NVUE -->
3   - <view
4   - class="u-grid-item"
5   - hover-class="u-grid-item--hover-class"
6   - :hover-stay-time="200"
7   - @tap="clickHandler"
8   - :class="classes"
9   - :style="[itemStyle]"
10   - >
11   - <slot />
12   - </view>
13   - <!-- #endif -->
14   - <!-- #ifdef APP-NVUE -->
15   - <view
16   - class="u-grid-item"
17   - :hover-stay-time="200"
18   - @tap="clickHandler"
19   - :class="classes"
20   - :style="[itemStyle]"
21   - >
22   - <slot />
23   - </view>
24   - <!-- #endif -->
25   -</template>
26   -
27   -<script>
28   - import props from './props.js';
29   - /**
30   - * gridItem 提示
31   - * @description 宫格组件一般用于同时展示多个同类项目的场景,可以给宫格的项目设置徽标组件(badge),或者图标等,也可以扩展为左右滑动的轮播形式。搭配u-grid使用
32   - * @tutorial https://www.uviewui.com/components/grid.html
33   - * @property {String | Number} name 宫格的name ( 默认 null )
34   - * @property {String} bgColor 宫格的背景颜色 (默认 'transparent' )
35   - * @property {Object} customStyle 自定义样式,对象形式
36   - * @event {Function} click 点击宫格触发
37   - * @example <u-grid-item></u-grid-item>
38   - */
39   - export default {
40   - name: "u-grid-item",
41   - mixins: [uni.$u.mpMixin, uni.$u.mixin,props],
42   - data() {
43   - return {
44   - parentData: {
45   - col: 3, // 父组件划分的宫格数
46   - border: true, // 是否显示边框,根据父组件决定
47   - },
48   - // #ifdef APP-NVUE
49   - width: 0, // nvue下才这么计算,vue下放到computed中,否则会因为延时造成闪烁
50   - // #endif
51   - classes: [], // 类名集合,用于判断是否显示右边和下边框
52   - };
53   - },
54   - mounted() {
55   - this.init()
56   - },
57   - computed: {
58   - // #ifndef APP-NVUE
59   - // vue下放到computed中,否则会因为延时造成闪烁
60   - width() {
61   - return 100 / Number(this.parentData.col) + '%'
62   - },
63   - // #endif
64   - itemStyle() {
65   - const style = {
66   - background: this.bgColor,
67   - width: this.width
68   - }
69   - return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle))
70   - }
71   - },
72   - methods: {
73   - init() {
74   - // 用于在父组件u-grid的children中被添加入子组件时,
75   - // 重新计算item的边框
76   - uni.$on('$uGridItem', () => {
77   - this.gridItemClasses()
78   - })
79   - // 父组件的实例
80   - this.updateParentData()
81   - // #ifdef APP-NVUE
82   - // 获取元素该有的长度,nvue下要延时才准确
83   - this.$nextTick(function(){
84   - this.getItemWidth()
85   - })
86   - // #endif
87   - // 发出事件,通知所有的grid-item都重新计算自己的边框
88   - uni.$emit('$uGridItem')
89   - this.gridItemClasses()
90   - },
91   - // 获取父组件的参数
92   - updateParentData() {
93   - // 此方法写在mixin中
94   - this.getParentData('u-grid');
95   - },
96   - clickHandler() {
97   - let name = this.name
98   - // 如果没有设置name属性,历遍父组件的children数组,判断当前的元素是否和本实例this相等,找出当前组件的索引
99   - const children = this.parent?.children
100   - if(children && this.name === null) {
101   - name = children.findIndex(child => child === this)
102   - }
103   - // 调用父组件方法,发出事件
104   - this.parent && this.parent.childClick(name)
105   - this.$emit('click', name)
106   - },
107   - async getItemWidth() {
108   - // 如果是nvue,不能使用百分比,只能使用固定宽度
109   - let width = 0
110   - if(this.parent) {
111   - // 获取父组件宽度后,除以栅格数,得出每个item的宽度
112   - const parentWidth = await this.getParentWidth()
113   - width = parentWidth / Number(this.parentData.col) + 'px'
114   - }
115   - this.width = width
116   - },
117   - // 获取父元素的尺寸
118   - getParentWidth() {
119   - // #ifdef APP-NVUE
120   - // 返回一个promise,让调用者可以用await同步获取
121   - const dom = uni.requireNativePlugin('dom')
122   - return new Promise(resolve => {
123   - // 调用父组件的ref
124   - dom.getComponentRect(this.parent.$refs['u-grid'], res => {
125   - resolve(res.size.width)
126   - })
127   - })
128   - // #endif
129   - },
130   - gridItemClasses() {
131   - if(this.parentData.border) {
132   - const classes = []
133   - this.parent.children.map((child, index) =>{
134   - if(this === child) {
135   - const len = this.parent.children.length
136   - // 贴近右边屏幕边沿的child,并且最后一个(比如只有横向2个的时候),无需右边框
137   - if((index + 1) % this.parentData.col !== 0 && index + 1 !== len) {
138   - classes.push('u-border-right')
139   - }
140   - // 总的宫格数量对列数取余的值
141   - // 如果取余后,值为0,则意味着要将最后一排的宫格,都不需要下边框
142   - const lessNum = len % this.parentData.col === 0 ? this.parentData.col : len % this.parentData.col
143   - // 最下面的一排child,无需下边框
144   - if(index < len - lessNum) {
145   - classes.push('u-border-bottom')
146   - }
147   - }
148   - })
149   - // 支付宝,头条小程序无法动态绑定一个数组类名,否则解析出来的结果会带有",",而导致失效
150   - // #ifdef MP-ALIPAY || MP-TOUTIAO
151   - classes = classes.join(' ')
152   - // #endif
153   - this.classes = classes
154   - }
155   - }
156   - },
157   - beforeDestroy() {
158   - // 移除事件监听,释放性能
159   - uni.$off('$uGridItem')
160   - }
161   - };
162   -</script>
163   -
164   -<style lang="scss" scoped>
165   - @import "../../libs/css/components.scss";
166   - $u-grid-item-hover-class-opcatiy:.5 !default;
167   - $u-grid-item-margin-top:1rpx !default;
168   - $u-grid-item-border-right-width:0.5px !default;
169   - $u-grid-item-border-bottom-width:0.5px !default;
170   - $u-grid-item-border-right-color:$u-border-color !default;
171   - $u-grid-item-border-bottom-color:$u-border-color !default;
172   - .u-grid-item {
173   - align-items: center;
174   - justify-content: center;
175   - position: relative;
176   - flex-direction: column;
177   - /* #ifndef APP-NVUE */
178   - box-sizing: border-box;
179   - display: flex;
180   - /* #endif */
181   -
182   - /* #ifdef MP */
183   - position: relative;
184   - float: left;
185   - /* #endif */
186   -
187   - /* #ifdef MP-WEIXIN */
188   - margin-top:$u-grid-item-margin-top;
189   - /* #endif */
190   -
191   - &--hover-class {
192   - opacity:$u-grid-item-hover-class-opcatiy;
193   - }
194   - }
195   -
196   - /* #ifdef APP-NVUE */
197   - // 由于nvue不支持组件内引入app.vue中再引入的样式,所以需要写在这里
198   - .u-border-right {
199   - border-right-width:$u-grid-item-border-right-width;
200   - border-color: $u-grid-item-border-right-color;
201   - }
202   -
203   - .u-border-bottom {
204   - border-bottom-width:$u-grid-item-border-bottom-width;
205   - border-color:$u-grid-item-border-bottom-color;
206   - }
207   -
208   - /* #endif */
209   -</style>
1   -export default {
2   - props: {
3   - // 分成几列
4   - col: {
5   - type: [String, Number],
6   - default: uni.$u.props.grid.col
7   - },
8   - // 是否显示边框
9   - border: {
10   - type: Boolean,
11   - default: uni.$u.props.grid.border
12   - },
13   - // 宫格对齐方式,表现为数量少的时候,靠左,居中,还是靠右
14   - align: {
15   - type: String,
16   - default: uni.$u.props.grid.align
17   - }
18   - }
19   -}
1   -<template>
2   - <view
3   - class="u-grid"
4   - ref='u-grid'
5   - :style="[gridStyle]"
6   - >
7   - <slot />
8   - </view>
9   -</template>
10   -
11   -<script>
12   - import props from './props.js';
13   - /**
14   - * grid 宫格布局
15   - * @description 宫格组件一般用于同时展示多个同类项目的场景,可以给宫格的项目设置徽标组件(badge),或者图标等,也可以扩展为左右滑动的轮播形式。
16   - * @tutorial https://www.uviewui.com/components/grid.html
17   - * @property {String | Number} col 宫格的列数(默认 3 )
18   - * @property {Boolean} border 是否显示宫格的边框(默认 false )
19   - * @property {String} align 宫格对齐方式,表现为数量少的时候,靠左,居中,还是靠右 (默认 'left' )
20   - * @property {Object} customStyle 定义需要用到的外部样式
21   - * @event {Function} click 点击宫格触发
22   - * @example <u-grid :col="3" @click="click"></u-grid>
23   - */
24   - export default {
25   - name: 'u-grid',
26   - mixins: [uni.$u.mpMixin, uni.$u.mixin,props],
27   - data() {
28   - return {
29   - index: 0,
30   - width: 0
31   - }
32   - },
33   - watch: {
34   - // 当父组件需要子组件需要共享的参数发生了变化,手动通知子组件
35   - parentData() {
36   - if (this.children.length) {
37   - this.children.map(child => {
38   - // 判断子组件(u-radio)如果有updateParentData方法的话,就就执行(执行的结果是子组件重新从父组件拉取了最新的值)
39   - typeof(child.updateParentData) == 'function' && child.updateParentData();
40   - })
41   - }
42   - },
43   - },
44   - created() {
45   - // 如果将children定义在data中,在微信小程序会造成循环引用而报错
46   - this.children = []
47   - },
48   - computed: {
49   - // 计算父组件的值是否发生变化
50   - parentData() {
51   - return [this.hoverClass, this.col, this.size, this.border];
52   - },
53   - // 宫格对齐方式
54   - gridStyle() {
55   - let style = {};
56   - switch (this.align) {
57   - case 'left':
58   - style.justifyContent = 'flex-start';
59   - break;
60   - case 'center':
61   - style.justifyContent = 'center';
62   - break;
63   - case 'right':
64   - style.justifyContent = 'flex-end';
65   - break;
66   - default:
67   - style.justifyContent = 'flex-start';
68   - };
69   - return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle));
70   - }
71   - },
72   - methods: {
73   - // 此方法由u-grid-item触发,用于在u-grid发出事件
74   - childClick(name) {
75   - this.$emit('click', name)
76   - }
77   - }
78   - };
79   -</script>
80   -
81   -<style lang="scss" scoped>
82   - @import "../../libs/css/components.scss";
83   - $u-grid-width:100% !default;
84   - .u-grid {
85   - /* #ifdef MP */
86   - width: $u-grid-width;
87   - position: relative;
88   - box-sizing: border-box;
89   - overflow: hidden;
90   - display: block;
91   - /* #endif */
92   - justify-content: center;
93   - @include flex;
94   - flex-wrap: wrap;
95   - align-items: center;
96   - }
97   -</style>
1   -export default {
2   - props: {
3   - // 标题
4   - title: {
5   - type: [String, Number],
6   - default: uni.$u.props.stepsItem.title
7   - },
8   - // 描述文本
9   - desc: {
10   - type: [String, Number],
11   - default: uni.$u.props.stepsItem.desc
12   - },
13   - // 图标大小
14   - iconSize: {
15   - type: [String, Number],
16   - default: uni.$u.props.stepsItem.iconSize
17   - },
18   - // 当前步骤是否处于失败状态
19   - error: {
20   - type: Boolean,
21   - default: uni.$u.props.stepsItem.error
22   - }
23   - }
24   -}
1   -<template>
2   - <view class="u-steps-item" ref="u-steps-item" :class="[`u-steps-item--${parentData.direction}`]">
3   - <view class="u-steps-item__line" v-if="index + 1 < childLength"
4   - :class="[`u-steps-item__line--${parentData.direction}`]" :style="[lineStyle]"></view>
5   - <view class="u-steps-item__wrapper"
6   - :class="[`u-steps-item__wrapper--${parentData.direction}`, parentData.dot && `u-steps-item__wrapper--${parentData.direction}--dot`]">
7   - <slot name="icon">
8   - <view class="u-steps-item__wrapper__dot" v-if="parentData.dot" :style="{
9   - backgroundColor: statusColor
10   - }">
11   -
12   - </view>
13   - <view class="u-steps-item__wrapper__icon" v-else-if="parentData.activeIcon || parentData.inactiveIcon">
14   - <u-icon :name="index <= parentData.current ? parentData.activeIcon : parentData.inactiveIcon"
15   - :size="iconSize"
16   - :color="index <= parentData.current ? parentData.activeColor : parentData.inactiveColor">
17   - </u-icon>
18   - </view>
19   - <view v-else :style="{
20   - backgroundColor: statusClass === 'process' ? parentData.activeColor : 'transparent',
21   - borderColor: statusColor
22   - }" class="u-steps-item__wrapper__circle">
23   - <text v-if="statusClass === 'process' || statusClass === 'wait'"
24   - class="u-steps-item__wrapper__circle__text" :style="{
25   - color: index == parentData.current ? '#ffffff' : parentData.inactiveColor
26   - }">{{ index + 1}}</text>
27   - <u-icon v-else :color="statusClass === 'error' ? 'error' : parentData.activeColor" size="12"
28   - :name="statusClass === 'error' ? 'close' : 'checkmark'"></u-icon>
29   - </view>
30   - </slot>
31   - </view>
32   - <view class="u-steps-item__content" :class="[`u-steps-item__content--${parentData.direction}`]"
33   - :style="[contentStyle]">
34   - <u--text :text="title" :type="parentData.current == index ? 'main' : 'content'" lineHeight="20px"
35   - :size="parentData.current == index ? 14 : 13"></u--text>
36   - <slot name="desc">
37   - <u--text :text="desc" type="tips" size="12"></u--text>
38   - </slot>
39   - </view>
40   - <!-- <view
41   - class="u-steps-item__line"
42   - v-if="showLine && parentData.direction === 'column'"
43   - :class="[`u-steps-item__line--${parentData.direction}`]"
44   - :style="[lineStyle]"
45   - ></view> -->
46   - </view>
47   -</template>
48   -
49   -<script>
50   - import props from './props.js';
51   - // #ifdef APP-NVUE
52   - const dom = uni.requireNativePlugin('dom')
53   - // #endif
54   - /**
55   - * StepsItem 步骤条的子组件
56   - * @description 本组件需要和u-steps配合使用
57   - * @tutorial https://uviewui.com/components/steps.html
58   - * @property {String} title 标题文字
59   - * @property {String} current 描述文本
60   - * @property {String | Number} iconSize 图标大小 (默认 17 )
61   - * @property {Boolean} error 当前步骤是否处于失败状态 (默认 false )
62   - * @example <u-steps current="0"><u-steps-item title="已出库" desc="10:35" ></u-steps-item></u-steps>
63   - */
64   - export default {
65   - name: 'u-steps-item',
66   - mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
67   - data() {
68   - return {
69   - index: 0,
70   - childLength: 0,
71   - showLine: false,
72   - size: {
73   - height: 0,
74   - width: 0
75   - },
76   - parentData: {
77   - direction: 'row',
78   - current: 0,
79   - activeColor: '',
80   - inactiveColor: '',
81   - activeIcon: '',
82   - inactiveIcon: '',
83   - dot: false
84   - }
85   - }
86   - },
87   - watch: {
88   - 'parentData'(newValue, oldValue) {
89   - }
90   - },
91   - created() {
92   - this.init()
93   - },
94   - computed: {
95   - lineStyle() {
96   - const style = {}
97   - if (this.parentData.direction === 'row') {
98   - style.width = this.size.width + 'px'
99   - style.left = this.size.width / 2 + 'px'
100   - } else {
101   - style.height = this.size.height + 'px'
102   - // style.top = this.size.height / 2 + 'px'
103   - }
104   - style.backgroundColor = this.parent.children?.[this.index + 1]?.error ? uni.$u.color.error : this.index <
105   - this
106   - .parentData
107   - .current ? this.parentData.activeColor : this.parentData.inactiveColor
108   - return style
109   - },
110   - statusClass() {
111   - const {
112   - index,
113   - error
114   - } = this
115   - const {
116   - current
117   - } = this.parentData
118   - if (current == index) {
119   - return error === true ? 'error' : 'process'
120   - } else if (error) {
121   - return 'error'
122   - } else if (current > index) {
123   - return 'finish'
124   - } else {
125   - return 'wait'
126   - }
127   - },
128   - statusColor() {
129   - let color = ''
130   - switch (this.statusClass) {
131   - case 'finish':
132   - color = this.parentData.activeColor
133   - break
134   - case 'error':
135   - color = uni.$u.color.error
136   - break
137   - case 'process':
138   - color = this.parentData.dot ? this.parentData.activeColor : 'transparent'
139   - break
140   - default:
141   - color = this.parentData.inactiveColor
142   - break
143   - }
144   - return color
145   - },
146   - contentStyle() {
147   - const style = {}
148   - if (this.parentData.direction === 'column') {
149   - style.marginLeft = this.parentData.dot ? '2px' : '6px'
150   - style.marginTop = this.parentData.dot ? '0px' : '6px'
151   - } else {
152   - style.marginTop = this.parentData.dot ? '2px' : '6px'
153   - style.marginLeft = this.parentData.dot ? '2px' : '6px'
154   - }
155   -
156   - return style
157   - }
158   - },
159   - mounted() {
160   - this.parent && this.parent.updateFromChild()
161   - uni.$u.sleep().then(() => {
162   - this.getStepsItemRect()
163   - })
164   - },
165   - methods: {
166   - init() {
167   - // 初始化数据
168   - this.updateParentData()
169   - if (!this.parent) {
170   - return uni.$u.error('u-steps-item必须要搭配u-steps组件使用')
171   - }
172   - this.index = this.parent.children.indexOf(this)
173   - this.childLength = this.parent.children.length
174   - },
175   - updateParentData() {
176   - // 此方法在mixin中
177   - this.getParentData('u-steps')
178   - },
179   - // 父组件数据发生变化
180   - updateFromParent() {
181   - this.init()
182   - },
183   - // 获取组件的尺寸,用于设置横线的位置
184   - getStepsItemRect() {
185   - // #ifndef APP-NVUE
186   - this.$uGetRect('.u-steps-item').then(size => {
187   - this.size = size
188   - })
189   - // #endif
190   -
191   - // #ifdef APP-NVUE
192   - dom.getComponentRect(this.$refs['u-steps-item'], res => {
193   - const {
194   - size
195   - } = res
196   - this.size = size
197   - })
198   - // #endif
199   - }
200   - }
201   - }
202   -</script>
203   -
204   -<style lang="scss" scoped>
205   - @import "../../libs/css/components.scss";
206   -
207   - .u-steps-item {
208   - flex: 1;
209   - @include flex;
210   -
211   - &--row {
212   - flex-direction: column;
213   - align-items: center;
214   - position: relative;
215   - }
216   -
217   - &--column {
218   - position: relative;
219   - flex-direction: row;
220   - justify-content: flex-start;
221   - padding-bottom: 5px;
222   - }
223   -
224   - &__wrapper {
225   - @include flex;
226   - justify-content: center;
227   - align-items: center;
228   - position: relative;
229   - background-color: #fff;
230   -
231   - &--column {
232   - width: 20px;
233   - height: 32px;
234   -
235   - &--dot {
236   - height: 20px;
237   - width: 20px;
238   - }
239   - }
240   -
241   - &--row {
242   - width: 32px;
243   - height: 20px;
244   -
245   - &--dot {
246   - width: 20px;
247   - height: 20px;
248   - }
249   - }
250   -
251   - &__circle {
252   - width: 20px;
253   - height: 20px;
254   - /* #ifndef APP-NVUE */
255   - box-sizing: border-box;
256   - flex-shrink: 0;
257   - /* #endif */
258   - border-radius: 100px;
259   - border-width: 1px;
260   - border-color: $u-tips-color;
261   - border-style: solid;
262   - @include flex(row);
263   - align-items: center;
264   - justify-content: center;
265   - transition: background-color 0.3s;
266   -
267   - &__text {
268   - color: $u-tips-color;
269   - font-size: 11px;
270   - @include flex(row);
271   - align-items: center;
272   - justify-content: center;
273   - text-align: center;
274   - line-height: 11px;
275   - }
276   - }
277   -
278   - &__dot {
279   - width: 10px;
280   - height: 10px;
281   - border-radius: 100px;
282   - background-color: $u-content-color;
283   - }
284   - }
285   -
286   - &__content {
287   - @include flex;
288   - flex: 1;
289   -
290   - &--row {
291   - flex-direction: column;
292   - align-items: center;
293   - }
294   -
295   - &--column {
296   - flex-direction: column;
297   - margin-left: 6px;
298   - }
299   - }
300   -
301   - &__line {
302   - position: absolute;
303   - background: $u-tips-color;
304   -
305   - &--row {
306   - top: 10px;
307   - height: 1px;
308   - }
309   -
310   - &--column {
311   - width: 1px;
312   - left: 10px;
313   - }
314   - }
315   - }
316   -</style>
1   -export default {
2   - props: {
3   - // 排列方向
4   - direction: {
5   - type: String,
6   - default: uni.$u.props.steps.direction
7   - },
8   - // 设置第几个步骤
9   - current: {
10   - type: [String, Number],
11   - default: uni.$u.props.steps.current
12   - },
13   - // 激活状态颜色
14   - activeColor: {
15   - type: String,
16   - default: uni.$u.props.steps.activeColor
17   - },
18   - // 未激活状态颜色
19   - inactiveColor: {
20   - type: String,
21   - default: uni.$u.props.steps.inactiveColor
22   - },
23   - // 激活状态的图标
24   - activeIcon: {
25   - type: String,
26   - default: uni.$u.props.steps.activeIcon
27   - },
28   - // 未激活状态图标
29   - inactiveIcon: {
30   - type: String,
31   - default: uni.$u.props.steps.inactiveIcon
32   - },
33   - // 是否显示点类型
34   - dot: {
35   - type: Boolean,
36   - default: uni.$u.props.steps.dot
37   - }
38   - }
39   -}
1   -<template>
2   - <view
3   - class="u-steps"
4   - :class="[`u-steps--${direction}`]"
5   - >
6   - <slot></slot>
7   - </view>
8   -</template>
9   -
10   -<script>
11   - import props from './props.js';
12   - /**
13   - * Steps 步骤条
14   - * @description 该组件一般用于完成一个任务要分几个步骤,标识目前处于第几步的场景。
15   - * @tutorial https://uviewui.com/components/steps.html
16   - * @property {String} direction row-横向,column-竖向 (默认 'row' )
17   - * @property {String | Number} current 设置当前处于第几步 (默认 0 )
18   - * @property {String} activeColor 激活状态颜色 (默认 '#3c9cff' )
19   - * @property {String} inactiveColor 未激活状态颜色 (默认 '#969799' )
20   - * @property {String} activeIcon 激活状态的图标
21   - * @property {String} inactiveIcon 未激活状态图标
22   - * @property {Boolean} dot 是否显示点类型 (默认 false )
23   - * @example <u-steps current="0"><u-steps-item title="已出库" desc="10:35" ></u-steps-item></u-steps>
24   - */
25   - export default {
26   - name: 'u-steps',
27   - mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
28   - data() {
29   - return {
30   - }
31   - },
32   - watch: {
33   - children() {
34   - this.updateChildData()
35   - },
36   - parentData() {
37   - this.updateChildData()
38   - }
39   - },
40   - computed: {
41   - // 监听参数的变化,通过watch中,手动去更新子组件的数据,否则子组件不会自动变化
42   - parentData() {
43   - return [this.current, this.direction, this.activeColor, this.inactiveColor, this.activeIcon, this.inactiveIcon, this.dot]
44   - }
45   - },
46   - methods: {
47   - // 更新子组件的数据
48   - updateChildData() {
49   - this.children.map(child => {
50   - // 先判断子组件是否存在对应的方法
51   - uni.$u.test.func((child || {}).updateFromParent()) && child.updateFromParent()
52   - })
53   - },
54   - // 接受子组件的通知,去修改其他子组件的数据
55   - updateFromChild() {
56   - this.updateChildData()
57   - }
58   - },
59   - created() {
60   - this.children = []
61   - }
62   - }
63   -</script>
64   -
65   -<style lang="scss" scoped>
66   - @import "../../libs/css/components.scss";
67   -
68   - .u-steps {
69   - @include flex;
70   -
71   - &--column {
72   - flex-direction: column
73   - }
74   -
75   - &--row {
76   - flex-direction: row;
77   - flex: 1;
78   - }
79   - }
80   -</style>
1   -/**
2   - * 此为wxs模块,只支持APP-VUE,微信和QQ小程序以及H5平台
3   - * wxs内部不支持es6语法,变量只能使用var定义,无法使用解构,箭头函数等特性
4   - */
5   -
6   -// 开始触摸
7   -function touchstart(event, ownerInstance) {
8   - // 触发事件的组件的ComponentDescriptor实例
9   - var instance = event.instance
10   - // wxs内的局部变量快照,此快照是属于整个组件的,在touchstart和touchmove事件中都能获取到相同的结果
11   - var state = instance.getState()
12   - if (state.disable) return
13   - var touches = event.touches
14   - // 如果进行的是多指触控,不允许进行操作
15   - if (touches && touches.length > 1) return
16   - // 标识当前为滑动中状态
17   - state.moving = true
18   - // 记录触摸开始点的坐标值
19   - state.startX = touches[0].pageX
20   - state.startY = touches[0].pageY
21   -}
22   -
23   -// 触摸滑动
24   -function touchmove(event, ownerInstance) {
25   - // 触发事件的组件的ComponentDescriptor实例
26   - var instance = event.instance
27   - // wxs内的局部变量快照
28   - var state = instance.getState()
29   - if (state.disabled || !state.moving) return
30   -
31   - var touches = event.touches
32   - var pageX = touches[0].pageX
33   - var pageY = touches[0].pageY
34   - var moveX = pageX - state.startX
35   - var moveY = pageY - state.startY
36   - var buttonsWidth = state.buttonsWidth
37   -
38   - // 移动的X轴距离大于Y轴距离,也即终点与起点位置连线,与X轴夹角小于45度时,禁止页面滚动
39   - if (Math.abs(moveX) > Math.abs(moveY) || Math.abs(moveX) > state.threshold) {
40   - event.preventDefault()
41   - event.stopPropagation()
42   - }
43   - // 如果移动的X轴距离小于Y轴距离,也即终点位置与起点位置连线,与Y轴夹角小于45度时,认为是页面上下滑动,而不是左右滑动单元格
44   - if (Math.abs(moveX) < Math.abs(moveY)) return
45   -
46   - // 限制右滑的距离,不允许内容部分往右偏移,右滑会导致X轴偏移值大于0,以此做判断
47   - // 此处不能直接return,因为滑动过程中会缺失某些关键点坐标,会导致错乱,最好的办法就是
48   - // 在超出后,设置为0
49   - if (state.status === 'open') {
50   - // 在开启状态下,向左滑动,需忽略
51   - if (moveX < 0) moveX = 0
52   - // 想要收起菜单,最大能移动的距离为按钮的总宽度
53   - if (moveX > buttonsWidth) moveX = buttonsWidth
54   - // 如果是已经打开了的状态,向左滑动时,移动收起菜单
55   - moveSwipeAction(-buttonsWidth + moveX, instance, ownerInstance)
56   - } else {
57   - // 关闭状态下,右滑动需忽略
58   - if (moveX > 0) moveX = 0
59   - // 滑动的距离不允许超过所有按钮的总宽度,此时只能是左滑,最终设置按钮的总宽度,同时为负数
60   - if (Math.abs(moveX) > buttonsWidth) moveX = -buttonsWidth
61   - // 只要是在滑过程中,就不断移动菜单的内容部分,从而使隐藏的菜单显示出来
62   - moveSwipeAction(moveX, instance, ownerInstance)
63   - }
64   -}
65   -
66   -// 触摸结束
67   -function touchend(event, ownerInstance) {
68   - // 触发事件的组件的ComponentDescriptor实例
69   - var instance = event.instance
70   - // wxs内的局部变量快照
71   - var state = instance.getState()
72   - if (!state.moving || state.disabled) return
73   - var touches = event.changedTouches ? event.changedTouches[0] : {}
74   - var pageX = touches.pageX
75   - var pageY = touches.pageY
76   - var moveX = pageX - state.startX
77   - if (state.status === 'open') {
78   - // 在展开的状态下,继续左滑,无需操作
79   - if (moveX < 0) return
80   - // 在开启状态下,点击一下内容区域,moveX为0,也即没有进行移动,这时执行收起菜单逻辑
81   - if (moveX === 0) {
82   - return closeSwipeAction(instance, ownerInstance)
83   - }
84   - // 在开启状态下,滑动距离小于阈值,则默认为不关闭,同时恢复原来的打开状态
85   - if (Math.abs(moveX) < state.threshold) {
86   - openSwipeAction(instance, ownerInstance)
87   - } else {
88   - // 如果滑动距离大于阈值,则执行收起逻辑
89   - closeSwipeAction(instance, ownerInstance)
90   - }
91   - } else {
92   - // 在关闭的状态下,右滑,无需操作
93   - if (moveX > 0) return
94   - // 理由同上
95   - if (Math.abs(moveX) < state.threshold) {
96   - closeSwipeAction(instance, ownerInstance)
97   - } else {
98   - openSwipeAction(instance, ownerInstance)
99   - }
100   - }
101   -}
102   -
103   -// 获取过渡时间
104   -function getDuration(value) {
105   - if (value.toString().indexOf('s') >= 0) return value
106   - return value > 30 ? value + 'ms' : value + 's'
107   -}
108   -
109   -// 滑动结束时判断滑动的方向
110   -function getMoveDirection(instance, ownerInstance) {
111   - var state = instance.getState()
112   -}
113   -
114   -// 移动滑动选择器内容区域,同时显示出其隐藏的菜单
115   -function moveSwipeAction(moveX, instance, ownerInstance) {
116   - var state = instance.getState()
117   - // 获取所有按钮的实例,需要通过它去设置按钮的位移
118   - var buttons = ownerInstance.selectAllComponents('.u-swipe-action-item__right__button')
119   - var len = buttons.length
120   - var previewButtonsMoveX = 0
121   -
122   - // 设置菜单内容部分的偏移
123   - instance.requestAnimationFrame(function() {
124   - instance.setStyle({
125   - // 设置translateX的值
126   - 'transition': 'none',
127   - transform: 'translateX(' + moveX + 'px)',
128   - '-webkit-transform': 'translateX(' + moveX + 'px)'
129   - })
130   - // 折叠按钮动画
131   - for (var i = len - 1; i >= 0; i--) {
132   - // 通过比例,得出元素自身该移动的距离
133   - var translateX = state.buttons[i].width / state.buttonsWidth * moveX
134   - // 最终移动的距离,是通过自身比例算出的距离,再加上在它之前所有按钮移动的距离之和
135   - var realTranslateX = translateX + previewButtonsMoveX
136   - buttons[i].setStyle({
137   - // 在移动期间,不能使用过渡效果,否则会造成卡顿,本质原因是每次移动一点,就要花一定时间去过渡这个过程
138   - 'transition': 'none',
139   - 'transform': 'translateX(' + realTranslateX + 'px)',
140   - '-webkit-transform': 'translateX(' + realTranslateX + 'px)'
141   - })
142   - // 记录本按钮之前的所有按钮的移动距离之和
143   - previewButtonsMoveX += translateX
144   - }
145   - })
146   -}
147   -
148   -// 一次性展开滑动菜单
149   -function openSwipeAction(instance, ownerInstance) {
150   - var state = instance.getState()
151   - // 获取所有按钮的实例,需要通过它去设置按钮的位移
152   - var buttons = ownerInstance.selectAllComponents('.u-swipe-action-item__right__button')
153   - var len = buttons.length
154   - // 处理duration单位问题
155   - const duration = getDuration(state.duration)
156   - // 展开过程中,是向左移动,所以X的偏移应该为负值
157   - var buttonsWidth = -state.buttonsWidth
158   - var previewButtonsMoveX = 0
159   - instance.requestAnimationFrame(function() {
160   - // 设置菜单主体内容
161   - instance.setStyle({
162   - 'transition': 'transform ' + duration,
163   - 'transform': 'translateX(' + buttonsWidth + 'px)',
164   - '-webkit-transform': 'translateX(' + buttonsWidth + 'px)',
165   - })
166   - // 设置各个隐藏的按钮为展开的状态
167   - for (var i = len - 1; i >= 0; i--) {
168   - // 通过比例,得出元素自身该移动的距离
169   - var translateX = state.buttons[i].width / state.buttonsWidth * buttonsWidth
170   - // 最终移动的距离,是通过自身比例算出的距离,再加上在它之前所有按钮移动的距离之和
171   - var realTranslateX = translateX + previewButtonsMoveX
172   - buttons[i].setStyle({
173   - // 在移动期间,需要加上动画效果
174   - 'transition': 'transform ' + duration,
175   - 'transform': 'translateX(' + realTranslateX + 'px)',
176   - '-webkit-transform': 'translateX(' + realTranslateX + 'px)'
177   - })
178   - // 记录本按钮之前的所有按钮的移动距离之和
179   - previewButtonsMoveX += translateX
180   - }
181   - })
182   - setStatus('open', instance)
183   -}
184   -
185   -// 标记菜单的当前状态,open-已经打开,close-已经关闭
186   -function setStatus(status, instance) {
187   - var state = instance.getState()
188   - state.status = status
189   -}
190   -
191   -// 一次性收起滑动菜单
192   -function closeSwipeAction(instance, ownerInstance) {
193   - var state = instance.getState()
194   - // 获取所有按钮的实例,需要通过它去设置按钮的位移
195   - var buttons = ownerInstance.selectAllComponents('.u-swipe-action-item__right__button')
196   - var len = buttons.length
197   - // 处理duration单位问题
198   - const duration = getDuration(state.duration)
199   - instance.requestAnimationFrame(function() {
200   - // 设置菜单主体内容
201   - instance.setStyle({
202   - 'transition': 'transform ' + duration,
203   - 'transform': 'translateX(0px)',
204   - '-webkit-transform': 'translateX(0px)'
205   - })
206   - // 设置各个隐藏的按钮为收起的状态
207   - for (var i = len - 1; i >= 0; i--) {
208   - buttons[i].setStyle({
209   - 'transition': 'transform ' + duration,
210   - 'transform': 'translateX(0px)',
211   - '-webkit-transform': 'translateX(0px)'
212   - })
213   - }
214   - })
215   - setStatus('close', instance)
216   -}
217   -
218   -// show的状态发生变化
219   -function showChange(newValue, oldValue, ownerInstance, instance) {
220   - var state = instance.getState()
221   - if (state.disabled) return
222   - // 打开或关闭单元格
223   - if (newValue) {
224   - openSwipeAction(instance, ownerInstance)
225   - } else {
226   - closeSwipeAction(instance, ownerInstance)
227   - }
228   -}
229   -
230   -// 菜单尺寸发生变化
231   -function sizeChange(newValue, oldValue, ownerInstance, instance) {
232   - // wxs内的局部变量快照
233   - var state = instance.getState()
234   - state.disabled = newValue.disabled
235   - state.duration = newValue.duration
236   - state.show = newValue.show
237   - state.threshold = newValue.threshold
238   - state.buttons = newValue.buttons
239   -
240   - var len = state.buttons.length
241   - if (len) {
242   - var buttonsWidth = 0
243   - var buttons = newValue.buttons
244   - for (var i = 0; i < len; i++) {
245   - buttonsWidth += buttons[i].width
246   - }
247   - }
248   - state.buttonsWidth = buttonsWidth
249   -}
250   -
251   -module.exports = {
252   - touchstart: touchstart,
253   - touchmove: touchmove,
254   - touchend: touchend,
255   - sizeChange: sizeChange
256   -}
1   -/**
2   - * 此为wxs模块,只支持APP-VUE,微信和QQ小程序以及H5平台
3   - * wxs内部不支持es6语法,变量只能使用var定义,无法使用解构,箭头函数等特性
4   - */
5   -
6   -// 开始触摸
7   -function touchstart(event, ownerInstance) {
8   - // 触发事件的组件的ComponentDescriptor实例
9   - var instance = event.instance
10   - // wxs内的局部变量快照,此快照是属于整个组件的,在touchstart和touchmove事件中都能获取到相同的结果
11   - var state = instance.getState()
12   - if (state.disabled) return
13   - var touches = event.touches
14   - // 如果进行的是多指触控,不允许进行操作
15   - if (touches && touches.length > 1) return
16   - // 标识当前为滑动中状态
17   - state.moving = true
18   - // 记录触摸开始点的坐标值
19   - state.startX = touches[0].pageX
20   - state.startY = touches[0].pageY
21   -
22   - ownerInstance.callMethod('closeOther')
23   -}
24   -
25   -// 触摸滑动
26   -function touchmove(event, ownerInstance) {
27   - // 触发事件的组件的ComponentDescriptor实例
28   - var instance = event.instance
29   - // wxs内的局部变量快照
30   - var state = instance.getState()
31   - if (state.disabled || !state.moving) return
32   - var touches = event.touches
33   - var pageX = touches[0].pageX
34   - var pageY = touches[0].pageY
35   - var moveX = pageX - state.startX
36   - var moveY = pageY - state.startY
37   - var buttonsWidth = state.buttonsWidth
38   -
39   - // 移动的X轴距离大于Y轴距离,也即终点与起点位置连线,与X轴夹角小于45度时,禁止页面滚动
40   - if (Math.abs(moveX) > Math.abs(moveY) || Math.abs(moveX) > state.threshold) {
41   - event.preventDefault && event.preventDefault()
42   - event.stopPropagation && event.stopPropagation()
43   - }
44   - // 如果移动的X轴距离小于Y轴距离,也即终点位置与起点位置连线,与Y轴夹角小于45度时,认为是页面上下滑动,而不是左右滑动单元格
45   - if (Math.abs(moveX) < Math.abs(moveY)) return
46   -
47   - // 限制右滑的距离,不允许内容部分往右偏移,右滑会导致X轴偏移值大于0,以此做判断
48   - // 此处不能直接return,因为滑动过程中会缺失某些关键点坐标,会导致错乱,最好的办法就是
49   - // 在超出后,设置为0
50   - if (state.status === 'open') {
51   - // 在开启状态下,向左滑动,需忽略
52   - if (moveX < 0) moveX = 0
53   - // 想要收起菜单,最大能移动的距离为按钮的总宽度
54   - if (moveX > buttonsWidth) moveX = buttonsWidth
55   - // 如果是已经打开了的状态,向左滑动时,移动收起菜单
56   - moveSwipeAction(-buttonsWidth + moveX, instance, ownerInstance)
57   - } else {
58   - // 关闭状态下,右滑动需忽略
59   - if (moveX > 0) moveX = 0
60   - // 滑动的距离不允许超过所有按钮的总宽度,此时只能是左滑,最终设置按钮的总宽度,同时为负数
61   - if (Math.abs(moveX) > buttonsWidth) moveX = -buttonsWidth
62   - // 只要是在滑过程中,就不断移动单元格内容部分,从而使隐藏的菜单显示出来
63   - moveSwipeAction(moveX, instance, ownerInstance)
64   - }
65   -}
66   -
67   -// 触摸结束
68   -function touchend(event, ownerInstance) {
69   - // 触发事件的组件的ComponentDescriptor实例
70   - var instance = event.instance
71   - // wxs内的局部变量快照
72   - var state = instance.getState()
73   - if (!state.moving || state.disabled) return
74   - var touches = event.changedTouches ? event.changedTouches[0] : {}
75   - var pageX = touches.pageX
76   - var pageY = touches.pageY
77   - var moveX = pageX - state.startX
78   - if (state.status === 'open') {
79   - // 在展开的状态下,继续左滑,无需操作
80   - if (moveX < 0) return
81   - // 在开启状态下,点击一下内容区域,moveX为0,也即没有进行移动,这时执行收起菜单逻辑
82   - if (moveX === 0) {
83   - return closeSwipeAction(instance, ownerInstance)
84   - }
85   - // 在开启状态下,滑动距离小于阈值,则默认为不关闭,同时恢复原来的打开状态
86   - if (Math.abs(moveX) < state.threshold) {
87   - openSwipeAction(instance, ownerInstance)
88   - } else {
89   - // 如果滑动距离大于阈值,则执行收起逻辑
90   - closeSwipeAction(instance, ownerInstance)
91   - }
92   - } else {
93   - // 在关闭的状态下,右滑,无需操作
94   - if (moveX > 0) return
95   - // 理由同上
96   - if (Math.abs(moveX) < state.threshold) {
97   - closeSwipeAction(instance, ownerInstance)
98   - } else {
99   - openSwipeAction(instance, ownerInstance)
100   - }
101   - }
102   -}
103   -
104   -// 获取过渡时间
105   -function getDuration(value) {
106   - if (value.toString().indexOf('s') >= 0) return value
107   - return value > 30 ? value + 'ms' : value + 's'
108   -}
109   -
110   -// 滑动结束时判断滑动的方向
111   -function getMoveDirection(instance, ownerInstance) {
112   - var state = instance.getState()
113   -}
114   -
115   -// 移动滑动选择器内容区域,同时显示出其隐藏的菜单
116   -function moveSwipeAction(moveX, instance, ownerInstance) {
117   - var state = instance.getState()
118   - // 获取所有按钮的实例,需要通过它去设置按钮的位移
119   - var buttons = ownerInstance.selectAllComponents('.u-swipe-action-item__right__button')
120   -
121   - // 设置菜单内容部分的偏移
122   - instance.requestAnimationFrame(function() {
123   - instance.setStyle({
124   - // 设置translateX的值
125   - 'transition': 'none',
126   - transform: 'translateX(' + moveX + 'px)',
127   - '-webkit-transform': 'translateX(' + moveX + 'px)'
128   - })
129   - })
130   -}
131   -
132   -// 一次性展开滑动菜单
133   -function openSwipeAction(instance, ownerInstance) {
134   - var state = instance.getState()
135   - // 获取所有按钮的实例,需要通过它去设置按钮的位移
136   - var buttons = ownerInstance.selectAllComponents('.u-swipe-action-item__right__button')
137   - // 处理duration单位问题
138   - var duration = getDuration(state.duration)
139   - // 展开过程中,是向左移动,所以X的偏移应该为负值
140   - var buttonsWidth = -state.buttonsWidth
141   - instance.requestAnimationFrame(function() {
142   - // 设置菜单主体内容
143   - instance.setStyle({
144   - 'transition': 'transform ' + duration,
145   - 'transform': 'translateX(' + buttonsWidth + 'px)',
146   - '-webkit-transform': 'translateX(' + buttonsWidth + 'px)',
147   - })
148   - })
149   - setStatus('open', instance, ownerInstance)
150   -}
151   -
152   -// 标记菜单的当前状态,open-已经打开,close-已经关闭
153   -function setStatus(status, instance, ownerInstance) {
154   - var state = instance.getState()
155   - state.status = status
156   - ownerInstance.callMethod('setState', status)
157   -}
158   -
159   -// 一次性收起滑动菜单
160   -function closeSwipeAction(instance, ownerInstance) {
161   - var state = instance.getState()
162   - // 获取所有按钮的实例,需要通过它去设置按钮的位移
163   - var buttons = ownerInstance.selectAllComponents('.u-swipe-action-item__right__button')
164   - var len = buttons.length
165   - // 处理duration单位问题
166   - var duration = getDuration(state.duration)
167   - instance.requestAnimationFrame(function() {
168   - // 设置菜单主体内容
169   - instance.setStyle({
170   - 'transition': 'transform ' + duration,
171   - 'transform': 'translateX(0px)',
172   - '-webkit-transform': 'translateX(0px)'
173   - })
174   - // 设置各个隐藏的按钮为收起的状态
175   - for (var i = len - 1; i >= 0; i--) {
176   - buttons[i].setStyle({
177   - 'transition': 'transform ' + duration,
178   - 'transform': 'translateX(0px)',
179   - '-webkit-transform': 'translateX(0px)'
180   - })
181   - }
182   - })
183   - setStatus('close', instance, ownerInstance)
184   -}
185   -
186   -// status的状态发生变化
187   -function statusChange(newValue, oldValue, ownerInstance, instance) {
188   - var state = instance.getState()
189   - if (state.disabled) return
190   - // 打开或关闭单元格
191   - if (newValue === 'close' && state.status === 'open') {
192   - closeSwipeAction(instance, ownerInstance)
193   - } else if(newValue === 'open' && state.status === 'close') {
194   - openSwipeAction(instance, ownerInstance)
195   - }
196   -}
197   -
198   -// 菜单尺寸发生变化
199   -function sizeChange(newValue, oldValue, ownerInstance, instance) {
200   - // wxs内的局部变量快照
201   - var state = instance.getState()
202   - state.disabled = newValue.disabled
203   - state.duration = newValue.duration
204   - state.show = newValue.show
205   - state.threshold = newValue.threshold
206   - state.buttons = newValue.buttons
207   -
208   - if (state.buttons) {
209   - var len = state.buttons.length
210   - var buttonsWidth = 0
211   - var buttons = newValue.buttons
212   - for (var i = 0; i < len; i++) {
213   - buttonsWidth += buttons[i].width
214   - }
215   - }
216   - state.buttonsWidth = buttonsWidth
217   -}
218   -
219   -module.exports = {
220   - touchstart: touchstart,
221   - touchmove: touchmove,
222   - touchend: touchend,
223   - sizeChange: sizeChange,
224   - statusChange: statusChange
225   -}
1   -// nvue操作dom的库,用于获取dom的尺寸信息
2   -const dom = uni.requireNativePlugin('dom')
3   -// nvue中用于操作元素动画的库,类似于uni.animation,只不过uni.animation不能用于nvue
4   -const animation = uni.requireNativePlugin('animation')
5   -
6   -export default {
7   - data() {
8   - return {
9   - // 是否滑动中
10   - moving: false,
11   - // 状态,open-打开状态,close-关闭状态
12   - status: 'close',
13   - // 开始触摸点的X和Y轴坐标
14   - startX: 0,
15   - startY: 0,
16   - // 所有隐藏按钮的尺寸信息数组
17   - buttons: [],
18   - // 所有按钮的总宽度
19   - buttonsWidth: 0,
20   - // 记录上一次移动的位置值
21   - moveX: 0,
22   - // 记录上一次滑动的位置,用于前后两次做对比,如果移动的距离小于某一阈值,则认为前后之间没有移动,为了解决可能存在的通信阻塞问题
23   - lastX: 0
24   - }
25   - },
26   - computed: {
27   - // 获取过渡时间
28   - getDuratin() {
29   - let duration = String(this.duration)
30   - // 如果ms为单位,返回ms的数值部分
31   - if (duration.indexOf('ms') >= 0) return parseInt(duration)
32   - // 如果s为单位,为了得到ms的数值,需要乘以1000
33   - if (duration.indexOf('s') >= 0) return parseInt(duration) * 1000
34   - // 如果值传了数值,且小于30,认为是s单位
35   - duration = Number(duration)
36   - return duration < 30 ? duration * 1000 : duration
37   - }
38   - },
39   - watch: {
40   - show: {
41   - immediate: true,
42   - handler(n) {
43   - // if(n === true) {
44   - // uni.$u.sleep(50).then(() => {
45   - // this.openSwipeAction()
46   - // })
47   - // } else {
48   - // this.closeSwipeAction()
49   - // }
50   - }
51   - }
52   - },
53   - mounted() {
54   - uni.$u.sleep(20).then(() => {
55   - this.queryRect()
56   - })
57   - },
58   - methods: {
59   - close() {
60   - this.closeSwipeAction()
61   - },
62   - // 触摸单元格
63   - touchstart(event) {
64   - if (this.disabled) return
65   - this.closeOther()
66   - const { touches } = event
67   - // 记录触摸开始点的坐标值
68   - this.startX = touches[0].pageX
69   - this.startY = touches[0].pageY
70   - },
71   - // // 触摸滑动
72   - touchmove(event) {
73   - if (this.disabled) return
74   - const { touches } = event
75   - const { pageX } = touches[0]
76   - const { pageY } = touches[0]
77   - let moveX = pageX - this.startX
78   - const moveY = pageY - this.startY
79   - const { buttonsWidth } = this
80   - const len = this.buttons.length
81   -
82   - // 判断前后两次的移动距离,如果小于一定值,则不进行移动处理
83   - if (Math.abs(pageX - this.lastX) < 0.3) return
84   - this.lastX = pageX
85   -
86   - // 移动的X轴距离大于Y轴距离,也即终点与起点位置连线,与X轴夹角小于45度时,禁止页面滚动
87   - if (Math.abs(moveX) > Math.abs(moveY) || Math.abs(moveX) > this.threshold) {
88   - event.stopPropagation()
89   - }
90   - // 如果移动的X轴距离小于Y轴距离,也即终点位置与起点位置连线,与Y轴夹角小于45度时,认为是页面上下滑动,而不是左右滑动单元格
91   - if (Math.abs(moveX) < Math.abs(moveY)) return
92   -
93   - // 限制右滑的距离,不允许内容部分往右偏移,右滑会导致X轴偏移值大于0,以此做判断
94   - // 此处不能直接return,因为滑动过程中会缺失某些关键点坐标,会导致错乱,最好的办法就是
95   - // 在超出后,设置为0
96   - if (this.status === 'open') {
97   - // 在开启状态下,向左滑动,需忽略
98   - if (moveX < 0) moveX = 0
99   - // 想要收起菜单,最大能移动的距离为按钮的总宽度
100   - if (moveX > buttonsWidth) moveX = buttonsWidth
101   - // 如果是已经打开了的状态,向左滑动时,移动收起菜单
102   - this.moveSwipeAction(-buttonsWidth + moveX)
103   - } else {
104   - // 关闭状态下,右滑动需忽略
105   - if (moveX > 0) moveX = 0
106   - // 滑动的距离不允许超过所有按钮的总宽度,此时只能是左滑,最终设置按钮的总宽度,同时为负数
107   - if (Math.abs(moveX) > buttonsWidth) moveX = -buttonsWidth
108   - // 只要是在滑过程中,就不断移动菜单的内容部分,从而使隐藏的菜单显示出来
109   - this.moveSwipeAction(moveX)
110   - }
111   - },
112   - // 单元格结束触摸
113   - touchend(event) {
114   - if (this.disabled) return
115   - const touches = event.changedTouches ? event.changedTouches[0] : {}
116   - const { pageX } = touches
117   - const { pageY } = touches
118   - const { buttonsWidth } = this
119   - this.moveX = pageX - this.startX
120   - if (this.status === 'open') {
121   - // 在展开的状态下,继续左滑,无需操作
122   - if (this.moveX < 0) this.moveX = 0
123   - if (this.moveX > buttonsWidth) this.moveX = buttonsWidth
124   - // 在开启状态下,点击一下内容区域,moveX为0,也即没有进行移动,这时执行收起菜单逻辑
125   - if (this.moveX === 0) {
126   - return this.closeSwipeAction()
127   - }
128   - // 在开启状态下,滑动距离小于阈值,则默认为不关闭,同时恢复原来的打开状态
129   - if (Math.abs(this.moveX) < this.threshold) {
130   - this.openSwipeAction()
131   - } else {
132   - // 如果滑动距离大于阈值,则执行收起逻辑
133   - this.closeSwipeAction()
134   - }
135   - } else {
136   - // 在关闭的状态下,右滑,无需操作
137   - if (this.moveX >= 0) this.moveX = 0
138   - if (this.moveX <= -buttonsWidth) this.moveX = -buttonsWidth
139   - // 理由同上
140   - if (Math.abs(this.moveX) < this.threshold) {
141   - this.closeSwipeAction()
142   - } else {
143   - this.openSwipeAction()
144   - }
145   - }
146   - },
147   - // 移动滑动选择器内容区域,同时显示出其隐藏的菜单
148   - moveSwipeAction(moveX) {
149   - if (this.moving) return
150   - this.moving = true
151   -
152   - let previewButtonsMoveX = 0
153   - const len = this.buttons.length
154   - animation.transition(this.$refs['u-swipe-action-item__content'].ref, {
155   - styles: {
156   - transform: `translateX(${moveX}px)`
157   - },
158   - timingFunction: 'linear'
159   - }, () => {
160   - this.moving = false
161   - })
162   - // 按钮的组的长度
163   - for (let i = len - 1; i >= 0; i--) {
164   - const buttonRef = this.$refs[`u-swipe-action-item__right__button-${i}`][0].ref
165   - // 通过比例,得出元素自身该移动的距离
166   - const translateX = this.buttons[i].width / this.buttonsWidth * moveX
167   - // 最终移动的距离,是通过自身比例算出的距离,再加上在它之前所有按钮移动的距离之和
168   - const realTranslateX = translateX + previewButtonsMoveX
169   - animation.transition(buttonRef, {
170   - styles: {
171   - transform: `translateX(${realTranslateX}px)`
172   - },
173   - duration: 0,
174   - delay: 0,
175   - timingFunction: 'linear'
176   - }, () => {})
177   - // 记录本按钮之前的所有按钮的移动距离之和
178   - previewButtonsMoveX += translateX
179   - }
180   - },
181   - // 关闭菜单
182   - closeSwipeAction() {
183   - if (this.status === 'close') return
184   - this.moving = true
185   - const { buttonsWidth } = this
186   - animation.transition(this.$refs['u-swipe-action-item__content'].ref, {
187   - styles: {
188   - transform: 'translateX(0px)'
189   - },
190   - duration: this.getDuratin,
191   - timingFunction: 'ease-in-out'
192   - }, () => {
193   - this.status = 'close'
194   - this.moving = false
195   - this.closeHandler()
196   - })
197   - // 按钮的组的长度
198   - const len = this.buttons.length
199   - for (let i = len - 1; i >= 0; i--) {
200   - const buttonRef = this.$refs[`u-swipe-action-item__right__button-${i}`][0].ref
201   - // 如果不满足边界条件,返回
202   - if (this.buttons.length === 0 || !this.buttons[i] || !this.buttons[i].width) return
203   -
204   - animation.transition(buttonRef, {
205   - styles: {
206   - transform: 'translateX(0px)'
207   - },
208   - duration: this.getDuratin,
209   - timingFunction: 'ease-in-out'
210   - }, () => {})
211   - }
212   - },
213   - // 打开菜单
214   - openSwipeAction() {
215   - if (this.status === 'open') return
216   - this.moving = true
217   - const buttonsWidth = -this.buttonsWidth
218   - let previewButtonsMoveX = 0
219   - animation.transition(this.$refs['u-swipe-action-item__content'].ref, {
220   - styles: {
221   - transform: `translateX(${buttonsWidth}px)`
222   - },
223   - duration: this.getDuratin,
224   - timingFunction: 'ease-in-out'
225   - }, () => {
226   - this.status = 'open'
227   - this.moving = false
228   - this.openHandler()
229   - })
230   - // 按钮的组的长度
231   - const len = this.buttons.length
232   - for (let i = len - 1; i >= 0; i--) {
233   - const buttonRef = this.$refs[`u-swipe-action-item__right__button-${i}`][0].ref
234   - // 如果不满足边界条件,返回
235   - if (this.buttons.length === 0 || !this.buttons[i] || !this.buttons[i].width) return
236   - // 通过比例,得出元素自身该移动的距离
237   - const translateX = this.buttons[i].width / this.buttonsWidth * buttonsWidth
238   - // 最终移动的距离,是通过自身比例算出的距离,再加上在它之前所有按钮移动的距离之和
239   - const realTranslateX = translateX + previewButtonsMoveX
240   - animation.transition(buttonRef, {
241   - styles: {
242   - transform: `translateX(${realTranslateX}px)`
243   - },
244   - duration: this.getDuratin,
245   - timingFunction: 'ease-in-out'
246   - }, () => {})
247   - previewButtonsMoveX += translateX
248   - }
249   - },
250   - // 查询按钮节点信息
251   - queryRect() {
252   - // 历遍所有按钮数组,通过getRectByDom返回一个promise
253   - const promiseAll = this.rightOptions.map((item, index) => this.getRectByDom(this.$refs[`u-swipe-action-item__right__button-${index}`][0]))
254   - // 通过promise.all方法,让所有按钮的查询结果返回一个数组的形式
255   - Promise.all(promiseAll).then((sizes) => {
256   - this.buttons = sizes
257   - // 计算所有按钮总宽度
258   - this.buttonsWidth = sizes.reduce((sum, cur) => sum + cur.width, 0)
259   - })
260   - },
261   - // 通过nvue的dom模块,查询节点信息
262   - getRectByDom(ref) {
263   - return new Promise((resolve) => {
264   - dom.getComponentRect(ref, (res) => {
265   - resolve(res.size)
266   - })
267   - })
268   - }
269   - }
270   -}
1   -// nvue操作dom的库,用于获取dom的尺寸信息
2   -const dom = uni.requireNativePlugin('dom');
3   -const bindingX = uni.requireNativePlugin('bindingx');
4   -const animation = uni.requireNativePlugin('animation');
5   -
6   -export default {
7   - data() {
8   - return {
9   - // 所有按钮的总宽度
10   - buttonsWidth: 0,
11   - // 是否正在移动中
12   - moving: false
13   - }
14   - },
15   - computed: {
16   - // 获取过渡时间
17   - getDuratin() {
18   - let duration = String(this.duration)
19   - // 如果ms为单位,返回ms的数值部分
20   - if (duration.indexOf('ms') >= 0) return parseInt(duration)
21   - // 如果s为单位,为了得到ms的数值,需要乘以1000
22   - if (duration.indexOf('s') >= 0) return parseInt(duration) * 1000
23   - // 如果值传了数值,且小于30,认为是s单位
24   - duration = Number(duration)
25   - return duration < 30 ? duration * 1000 : duration
26   - }
27   - },
28   - watch: {
29   - show(n) {
30   - if(n) {
31   - this.moveCellByAnimation('open')
32   - } else {
33   - this.moveCellByAnimation('close')
34   - }
35   - }
36   - },
37   - mounted() {
38   - this.initialize()
39   - },
40   - methods: {
41   - initialize() {
42   - this.queryRect()
43   - },
44   - // 关闭单元格,用于打开一个,自动关闭其他单元格的场景
45   - closeHandler() {
46   - if(this.status === 'open') {
47   - // 如果在打开状态下,进行点击的话,直接关闭单元格
48   - return this.moveCellByAnimation('close') && this.unbindBindingX()
49   - }
50   - },
51   - // 点击单元格
52   - clickHandler() {
53   - // 如果在移动中被点击,进行忽略
54   - if(this.moving) return
55   - // 尝试关闭其他打开的单元格
56   - this.parent && this.parent.closeOther(this)
57   - if(this.status === 'open') {
58   - // 如果在打开状态下,进行点击的话,直接关闭单元格
59   - return this.moveCellByAnimation('close') && this.unbindBindingX()
60   - }
61   - },
62   - // 滑动单元格
63   - onTouchstart(e) {
64   - // 如果当前正在移动中,或者disabled状态,则返回
65   - if(this.moving || this.disabled) {
66   - return this.unbindBindingX()
67   - }
68   - if(this.status === 'open') {
69   - // 如果在打开状态下,进行点击的话,直接关闭单元格
70   - return this.moveCellByAnimation('close') && this.unbindBindingX()
71   - }
72   - // 特殊情况下,e可能不为一个对象
73   - e?.stopPropagation && e.stopPropagation()
74   - e?.preventDefault && e.preventDefault()
75   - this.moving = true
76   - // 获取元素ref
77   - const content = this.getContentRef()
78   - let expression = `min(max(${-this.buttonsWidth}, x), 0)`
79   - // 尝试关闭其他打开的单元格
80   - this.parent && this.parent.closeOther(this)
81   -
82   - // 阿里为了KPI而开源的BindingX
83   - this.panEvent = bindingX.bind({
84   - anchor: content,
85   - eventType: 'pan',
86   - props: [{
87   - element: content,
88   - // 绑定width属性,设置其宽度值
89   - property: 'transform.translateX',
90   - expression
91   - }]
92   - }, (res) => {
93   - this.moving = false
94   - if (res.state === 'end' || res.state === 'exit') {
95   - const deltaX = res.deltaX
96   - if(deltaX <= -this.buttonsWidth || deltaX >= 0) {
97   - // 如果触摸滑动的过程中,大于单元格的总宽度,或者大于0,意味着已经动过滑动达到了打开或者关闭的状态
98   - // 这里直接进行状态的标记
99   - this.$nextTick(() => {
100   - this.status = deltaX <= -this.buttonsWidth ? 'open' : 'close'
101   - })
102   - } else if(Math.abs(deltaX) > uni.$u.getPx(this.threshold)) {
103   - // 在移动大于阈值、并且小于总按钮宽度时,进行自动打开或者关闭
104   - // 移动距离大于0时,意味着需要关闭状态
105   - if(Math.abs(deltaX) < this.buttonsWidth) {
106   - this.moveCellByAnimation(deltaX > 0 ? 'close' : 'open')
107   - }
108   - } else {
109   - // 在小于阈值时,进行关闭操作(如果在打开状态下,将不会执行bindingX)
110   - this.moveCellByAnimation('close')
111   - }
112   - }
113   - })
114   - },
115   - // 释放bindingX
116   - unbindBindingX() {
117   - // 释放上一次的资源
118   - if (this?.panEvent?.token != 0) {
119   - bindingX.unbind({
120   - token: this.panEvent?.token,
121   - // pan为手势事件
122   - eventType: 'pan'
123   - })
124   - }
125   - },
126   - // 查询按钮节点信息
127   - queryRect() {
128   - // 历遍所有按钮数组,通过getRectByDom返回一个promise
129   - const promiseAll = this.options.map((item, index) => {
130   - return this.getRectByDom(this.$refs[`u-swipe-action-item__right__button-${index}`][0])
131   - })
132   - // 通过promise.all方法,让所有按钮的查询结果返回一个数组的形式
133   - Promise.all(promiseAll).then(sizes => {
134   - this.buttons = sizes
135   - // 计算所有按钮总宽度
136   - this.buttonsWidth = sizes.reduce((sum, cur) => sum + cur.width, 0)
137   - })
138   - },
139   - // 通过nvue的dom模块,查询节点信息
140   - getRectByDom(ref) {
141   - return new Promise(resolve => {
142   - dom.getComponentRect(ref, res => {
143   - resolve(res.size)
144   - })
145   - })
146   - },
147   - // 移动单元格到左边或者右边尽头
148   - moveCellByAnimation(status = 'open') {
149   - if(this.moving) return
150   - // 标识当前状态
151   - this.moveing = true
152   - const content = this.getContentRef()
153   - const x = status === 'open' ? -this.buttonsWidth : 0
154   - animation.transition(content, {
155   - styles: {
156   - transform: `translateX(${x}px)`,
157   - },
158   - duration: uni.$u.getDuration(this.duration, false),
159   - timingFunction: 'ease-in-out'
160   - }, () => {
161   - this.moving = false
162   - this.status = status
163   - this.unbindBindingX()
164   - })
165   - },
166   - // 获取元素ref
167   - getContentRef() {
168   - return this.$refs['u-swipe-action-item__content'].ref
169   - },
170   - beforeDestroy() {
171   - this.unbindBindingX()
172   - }
173   - }
174   -}
1   -export default {
2   - props: {
3   - // 控制打开或者关闭
4   - show: {
5   - type: Boolean,
6   - default: uni.$u.props.swipeActionItem.show
7   - },
8   - // 标识符,如果是v-for,可用index索引值
9   - name: {
10   - type: [String, Number],
11   - default: uni.$u.props.swipeActionItem.name
12   - },
13   - // 是否禁用
14   - disabled: {
15   - type: Boolean,
16   - default: uni.$u.props.swipeActionItem.disabled
17   - },
18   - // 是否自动关闭其他swipe按钮组
19   - autoClose: {
20   - type: Boolean,
21   - default: uni.$u.props.swipeActionItem.autoClose
22   - },
23   - // 滑动距离阈值,只有大于此值,才被认为是要打开菜单
24   - threshold: {
25   - type: Number,
26   - default: uni.$u.props.swipeActionItem.threshold
27   - },
28   - // 右侧按钮内容
29   - options: {
30   - type: Array,
31   - default() {
32   - return uni.$u.props.swipeActionItem.rightOptions
33   - }
34   - },
35   - // 动画过渡时间,单位ms
36   - duration: {
37   - type: [String, Number],
38   - default: uni.$u.props.swipeActionItem.duration
39   - }
40   - }
41   -}
1   -<template>
2   - <view class="u-swipe-action-item" ref="u-swipe-action-item">
3   - <view class="u-swipe-action-item__right">
4   - <slot name="button">
5   - <view v-for="(item,index) in options" :key="index" class="u-swipe-action-item__right__button"
6   - :ref="`u-swipe-action-item__right__button-${index}`" :style="[{
7   - alignItems: item.style && item.style.borderRadius ? 'center' : 'stretch'
8   - }]" @tap="buttonClickHandler(item, index)">
9   - <view class="u-swipe-action-item__right__button__wrapper" :style="[{
10   - backgroundColor: item.style && item.style.backgroundColor ? item.style.backgroundColor : '#C7C6CD',
11   - borderRadius: item.style && item.style.borderRadius ? item.style.borderRadius : '0',
12   - padding: item.style && item.style.borderRadius ? '0' : '0 15px',
13   - }, item.style]">
14   - <u-icon v-if="item.icon" :name="item.icon"
15   - :color="item.style && item.style.color ? item.style.color : '#ffffff'"
16   - :size="item.iconSize ? $u.addUnit(item.iconSize) : item.style && item.style.fontSize ? $u.getPx(item.style.fontSize) * 1.2 : 17"
17   - :customStyle="{
18   - marginRight: item.text ? '2px' : 0
19   - }"></u-icon>
20   - <text v-if="item.text" class="u-swipe-action-item__right__button__wrapper__text u-line-1"
21   - :style="[{
22   - color: item.style && item.style.color ? item.style.color : '#ffffff',
23   - fontSize: item.style && item.style.fontSize ? item.style.fontSize : '16px',
24   - lineHeight: item.style && item.style.fontSize ? item.style.fontSize : '16px',
25   - }]">{{ item.text }}</text>
26   - </view>
27   - </view>
28   - </slot>
29   - </view>
30   - <!-- #ifdef APP-VUE || MP-WEIXIN || H5 || MP-QQ -->
31   - <view class="u-swipe-action-item__content" @touchstart="wxs.touchstart" @touchmove="wxs.touchmove"
32   - @touchend="wxs.touchend" :status="status" :change:status="wxs.statusChange" :size="size"
33   - :change:size="wxs.sizeChange">
34   - <!-- #endif -->
35   - <!-- #ifdef APP-NVUE -->
36   - <view class="u-swipe-action-item__content" ref="u-swipe-action-item__content" @panstart="onTouchstart"
37   - @tap="clickHandler">
38   - <!-- #endif -->
39   - <slot />
40   - </view>
41   - </view>
42   -</template>
43   -<!-- #ifdef APP-VUE || MP-WEIXIN || H5 || MP-QQ -->
44   -<script src="./index.wxs" module="wxs" lang="wxs"></script>
45   -<!-- #endif -->
46   -<script>
47   - import touch from '../../libs/mixin/touch.js'
48   - import props from './props.js';
49   - // #ifdef APP-NVUE
50   - import nvue from './nvue.js';
51   - // #endif
52   - // #ifdef APP-VUE || MP-WEIXIN || H5 || MP-QQ
53   - import wxs from './wxs.js';
54   - // #endif
55   - /**
56   - * SwipeActionItem 滑动单元格子组件
57   - * @description 该组件一般用于左滑唤出操作菜单的场景,用的最多的是左滑删除操作
58   - * @tutorial https://www.uviewui.com/components/swipeAction.html
59   - * @property {Boolean} show 控制打开或者关闭(默认 false )
60   - * @property {String | Number} index 标识符,如果是v-for,可用index索引
61   - * @property {Boolean} disabled 是否禁用(默认 false )
62   - * @property {Boolean} autoClose 是否自动关闭其他swipe按钮组(默认 true )
63   - * @property {Number} threshold 滑动距离阈值,只有大于此值,才被认为是要打开菜单(默认 30 )
64   - * @property {Array} options 右侧按钮内容
65   - * @property {String | Number} duration 动画过渡时间,单位ms(默认 350 )
66   - * @event {Function(index)} open 组件打开时触发
67   - * @event {Function(index)} close 组件关闭时触发
68   - * @example <u-swipe-action><u-swipe-action-item :options="options1" ></u-swipe-action-item></u-swipe-action>
69   - */
70   - export default {
71   - name: 'u-swipe-action-item',
72   - mixins: [uni.$u.mpMixin, uni.$u.mixin, props, touch],
73   - // #ifdef APP-NVUE
74   - mixins: [uni.$u.mpMixin, uni.$u.mixin, props, nvue, touch],
75   - // #endif
76   - // #ifdef APP-VUE || MP-WEIXIN || H5 || MP-QQ
77   - mixins: [uni.$u.mpMixin, uni.$u.mixin, props, touch, wxs],
78   - // #endif
79   - data() {
80   - return {
81   - // 按钮的尺寸信息
82   - size: {},
83   - // 父组件u-swipe-action的参数
84   - parentData: {
85   - autoClose: true,
86   - },
87   - // 当前状态,open-打开,close-关闭
88   - status: 'close',
89   - }
90   - },
91   - watch: {
92   - // 由于wxs无法直接读取外部的值,需要在外部值变化时,重新执行赋值逻辑
93   - wxsInit(newValue, oldValue) {
94   - this.queryRect()
95   - }
96   - },
97   - computed: {
98   - wxsInit() {
99   - return [this.disabled, this.autoClose, this.threshold, this.options, this.duration]
100   - }
101   - },
102   - mounted() {
103   - this.init()
104   - },
105   - methods: {
106   - init() {
107   - // 初始化父组件数据
108   - this.updateParentData()
109   - // #ifndef APP-NVUE
110   - uni.$u.sleep().then(() => {
111   - this.queryRect()
112   - })
113   - // #endif
114   - },
115   - updateParentData() {
116   - // 此方法在mixin中
117   - this.getParentData('u-swipe-action')
118   - },
119   - // #ifndef APP-NVUE
120   - // 查询节点
121   - queryRect() {
122   - this.$uGetRect('.u-swipe-action-item__right__button', true).then(buttons => {
123   - this.size = {
124   - buttons,
125   - show: this.show,
126   - disabled: this.disabled,
127   - threshold: this.threshold,
128   - duration: this.duration
129   - }
130   - })
131   - },
132   - // #endif
133   - // 按钮被点击
134   - buttonClickHandler(item, index) {
135   - this.$emit('click', {
136   - index,
137   - name: this.name
138   - })
139   - }
140   - },
141   - }
142   -</script>
143   -
144   -<style lang="scss" scoped>
145   - @import "../../libs/css/components.scss";
146   -
147   - .u-swipe-action-item {
148   - position: relative;
149   - overflow: hidden;
150   - /* #ifndef APP-NVUE || MP-WEIXIN */
151   - touch-action: none;
152   - /* #endif */
153   -
154   - &__content {
155   - background-color: #FFFFFF;
156   - z-index: 10;
157   - }
158   -
159   - &__right {
160   - position: absolute;
161   - top: 0;
162   - bottom: 0;
163   - right: 0;
164   - @include flex;
165   -
166   - &__button {
167   - @include flex;
168   - justify-content: center;
169   - overflow: hidden;
170   - align-items: center;
171   -
172   - &__wrapper {
173   - @include flex;
174   - align-items: center;
175   - justify-content: center;
176   - padding: 0 15px;
177   -
178   - &__text {
179   - @include flex;
180   - align-items: center;
181   - color: #FFFFFF;
182   - font-size: 15px;
183   - text-align: center;
184   - justify-content: center;
185   - }
186   - }
187   - }
188   - }
189   - }
190   -</style>
1   -export default {
2   - methods: {
3   - // 关闭时执行
4   - closeHandler() {
5   - this.status = 'close'
6   - },
7   - setState(status) {
8   - this.status = status
9   - },
10   - closeOther() {
11   - // 尝试关闭其他打开的单元格
12   - this.parent && this.parent.closeOther(this)
13   - }
14   - }
15   -}
1   -export default {
2   - props: {
3   - // 是否自动关闭其他swipe按钮组
4   - autoClose: {
5   - type: Boolean,
6   - default: uni.$u.props.swipeAction.autoClose
7   - }
8   - }
9   -}
1   -<template>
2   - <view class="u-swipe-action">
3   - <slot></slot>
4   - </view>
5   -</template>
6   -
7   -<script>
8   - import props from './props.js';
9   - /**
10   - * SwipeAction 滑动单元格
11   - * @description 该组件一般用于左滑唤出操作菜单的场景,用的最多的是左滑删除操作
12   - * @tutorial https://www.uviewui.com/components/swipeAction.html
13   - * @property {Boolean} autoClose 是否自动关闭其他swipe按钮组
14   - * @event {Function(index)} click 点击组件时触发
15   - * @example <u-swipe-action><u-swipe-action-item :rightOptions="options1" ></u-swipe-action-item></u-swipe-action>
16   - */
17   - export default {
18   - name: 'u-swipe-action',
19   - mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
20   - data() {
21   - return {}
22   - },
23   - provide() {
24   - return {
25   - swipeAction: this
26   - }
27   - },
28   - computed: {
29   - // 这里computed的变量,都是子组件u-swipe-action-item需要用到的,由于头条小程序的兼容性差异,子组件无法实时监听父组件参数的变化
30   - // 所以需要手动通知子组件,这里返回一个parentData变量,供watch监听,在其中去通知每一个子组件重新从父组件(u-swipe-action-item)
31   - // 拉取父组件新的变化后的参数
32   - parentData() {
33   - return [this.autoClose]
34   - }
35   - },
36   - watch: {
37   - // 当父组件需要子组件需要共享的参数发生了变化,手动通知子组件
38   - parentData() {
39   - if (this.children.length) {
40   - this.children.map(child => {
41   - // 判断子组件(u-swipe-action-item)如果有updateParentData方法的话,就就执行(执行的结果是子组件重新从父组件拉取了最新的值)
42   - typeof(child.updateParentData) === 'function' && child.updateParentData()
43   - })
44   - }
45   - },
46   - },
47   - created() {
48   - this.children = []
49   - },
50   - methods: {
51   - closeOther(child) {
52   - if (this.autoClose) {
53   - // 历遍所有的单元格,找出非当前操作中的单元格,进行关闭
54   - this.children.map((item, index) => {
55   - if (child !== item) {
56   - item.closeHandler()
57   - }
58   - })
59   - }
60   - }
61   - }
62   - }
63   -</script>
64   -
65   -<style lang="scss" scoped>
66   -
67   -</style>
1   -export default {
2   - props: {
3   - // 轮播的长度
4   - length: {
5   - type: [String, Number],
6   - default: uni.$u.props.swiperIndicator.length
7   - },
8   - // 当前处于活动状态的轮播的索引
9   - current: {
10   - type: [String, Number],
11   - default: uni.$u.props.swiperIndicator.current
12   - },
13   - // 指示器非激活颜色
14   - indicatorActiveColor: {
15   - type: String,
16   - default: uni.$u.props.swiperIndicator.indicatorActiveColor
17   - },
18   - // 指示器的激活颜色
19   - indicatorInactiveColor: {
20   - type: String,
21   - default: uni.$u.props.swiperIndicator.indicatorInactiveColor
22   - },
23   - // 指示器模式,line-线型,dot-点型
24   - indicatorMode: {
25   - type: String,
26   - default: uni.$u.props.swiperIndicator.indicatorMode
27   - }
28   - }
29   -}
1   -<template>
2   - <view class="u-swiper-indicator">
3   - <view
4   - class="u-swiper-indicator__wrapper"
5   - v-if="indicatorMode === 'line'"
6   - :class="[`u-swiper-indicator__wrapper--${indicatorMode}`]"
7   - :style="{
8   - width: $u.addUnit(lineWidth * length),
9   - backgroundColor: indicatorInactiveColor
10   - }"
11   - >
12   - <view
13   - class="u-swiper-indicator__wrapper--line__bar"
14   - :style="[lineStyle]"
15   - ></view>
16   - </view>
17   - <view
18   - class="u-swiper-indicator__wrapper"
19   - v-if="indicatorMode === 'dot'"
20   - >
21   - <view
22   - class="u-swiper-indicator__wrapper__dot"
23   - v-for="(item, index) in length"
24   - :key="index"
25   - :class="[index === current && 'u-swiper-indicator__wrapper__dot--active']"
26   - :style="[dotStyle(index)]"
27   - >
28   -
29   - </view>
30   - </view>
31   - </view>
32   -</template>
33   -
34   -<script>
35   - import props from './props.js';
36   - /**
37   - * SwiperIndicator 轮播图指示器
38   - * @description 该组件一般用于导航轮播,广告展示等场景,可开箱即用,
39   - * @tutorial https://www.uviewui.com/components/swiper.html
40   - * @property {String | Number} length 轮播的长度(默认 0 )
41   - * @property {String | Number} current 当前处于活动状态的轮播的索引(默认 0 )
42   - * @property {String} indicatorActiveColor 指示器非激活颜色
43   - * @property {String} indicatorInactiveColor 指示器的激活颜色
44   - * @property {String} indicatorMode 指示器模式(默认 'line' )
45   - * @example <u-swiper :list="list4" indicator keyName="url" :autoplay="false"></u-swiper>
46   - */
47   - export default {
48   - name: 'u-swiper-indicator',
49   - mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
50   - data() {
51   - return {
52   - lineWidth: 22
53   - }
54   - },
55   - computed: {
56   - // 指示器为线型的样式
57   - lineStyle() {
58   - let style = {}
59   - style.width = uni.$u.addUnit(this.lineWidth)
60   - style.transform = `translateX(${ uni.$u.addUnit(this.current * this.lineWidth) })`
61   - style.backgroundColor = this.indicatorActiveColor
62   - return style
63   - },
64   - // 指示器为点型的样式
65   - dotStyle() {
66   - return index => {
67   - let style = {}
68   - style.backgroundColor = index === this.current ? this.indicatorActiveColor : this.indicatorInactiveColor
69   - return style
70   - }
71   - }
72   - },
73   - }
74   -</script>
75   -
76   -<style lang="scss" scoped>
77   - @import "../../libs/css/components.scss";
78   -
79   - .u-swiper-indicator {
80   -
81   - &__wrapper {
82   - @include flex;
83   -
84   - &--line {
85   - border-radius: 100px;
86   - height: 4px;
87   -
88   - &__bar {
89   - width: 22px;
90   - height: 4px;
91   - border-radius: 100px;
92   - background-color: #FFFFFF;
93   - transition: transform 0.3s;
94   - }
95   - }
96   -
97   - &__dot {
98   - width: 5px;
99   - height: 5px;
100   - border-radius: 100px;
101   - margin: 0 4px;
102   -
103   - &--active {
104   - width: 12px;
105   - }
106   - }
107   -
108   - }
109   - }
110   -</style>
1   -export default {
2   - props: {
3   - // 列表数组,元素可为字符串,如为对象可通过keyName指定目标属性名
4   - list: {
5   - type: Array,
6   - default: uni.$u.props.swiper.list
7   - },
8   - // 是否显示面板指示器
9   - indicator: {
10   - type: Boolean,
11   - default: uni.$u.props.swiper.indicator
12   - },
13   - // 指示器非激活颜色
14   - indicatorActiveColor: {
15   - type: String,
16   - default: uni.$u.props.swiper.indicatorActiveColor
17   - },
18   - // 指示器的激活颜色
19   - indicatorInactiveColor: {
20   - type: String,
21   - default: uni.$u.props.swiper.indicatorInactiveColor
22   - },
23   - // 指示器样式,可通过bottom,left,right进行定位
24   - indicatorStyle: {
25   - type: [String, Object],
26   - default: uni.$u.props.swiper.indicatorStyle
27   - },
28   - // 指示器模式,line-线型,dot-点型
29   - indicatorMode: {
30   - type: String,
31   - default: uni.$u.props.swiper.indicatorMode
32   - },
33   - // 是否自动切换
34   - autoplay: {
35   - type: Boolean,
36   - default: uni.$u.props.swiper.autoplay
37   - },
38   - // 当前所在滑块的 index
39   - current: {
40   - type: [String, Number],
41   - default: uni.$u.props.swiper.current
42   - },
43   - // 当前所在滑块的 item-id ,不能与 current 被同时指定
44   - currentItemId: {
45   - type: String,
46   - default: uni.$u.props.swiper.currentItemId
47   - },
48   - // 滑块自动切换时间间隔
49   - interval: {
50   - type: [String, Number],
51   - default: uni.$u.props.swiper.interval
52   - },
53   - // 滑块切换过程所需时间
54   - duration: {
55   - type: [String, Number],
56   - default: uni.$u.props.swiper.duration
57   - },
58   - // 播放到末尾后是否重新回到开头
59   - circular: {
60   - type: Boolean,
61   - default: uni.$u.props.swiper.circular
62   - },
63   - // 前边距,可用于露出前一项的一小部分,nvue和支付宝不支持
64   - previousMargin: {
65   - type: [String, Number],
66   - default: uni.$u.props.swiper.previousMargin
67   - },
68   - // 后边距,可用于露出后一项的一小部分,nvue和支付宝不支持
69   - nextMargin: {
70   - type: [String, Number],
71   - default: uni.$u.props.swiper.nextMargin
72   - },
73   - // 当开启时,会根据滑动速度,连续滑动多屏,支付宝不支持
74   - acceleration: {
75   - type: Boolean,
76   - default: uni.$u.props.swiper.acceleration
77   - },
78   - // 同时显示的滑块数量,nvue、支付宝小程序不支持
79   - displayMultipleItems: {
80   - type: Number,
81   - default: uni.$u.props.swiper.displayMultipleItems
82   - },
83   - // 指定swiper切换缓动动画类型,有效值:default、linear、easeInCubic、easeOutCubic、easeInOutCubic
84   - // 只对微信小程序有效
85   - easingFunction: {
86   - type: String,
87   - default: uni.$u.props.swiper.easingFunction
88   - },
89   - // list数组中指定对象的目标属性名
90   - keyName: {
91   - type: String,
92   - default: uni.$u.props.swiper.keyName
93   - },
94   - // 图片的裁剪模式
95   - imgMode: {
96   - type: String,
97   - default: uni.$u.props.swiper.imgMode
98   - },
99   - // 组件高度
100   - height: {
101   - type: [String, Number],
102   - default: uni.$u.props.swiper.height
103   - },
104   - // 背景颜色
105   - bgColor: {
106   - type: String,
107   - default: uni.$u.props.swiper.bgColor
108   - },
109   - // 组件圆角,数值或带单位的字符串
110   - radius: {
111   - type: [String, Number],
112   - default: uni.$u.props.swiper.radius
113   - },
114   - // 是否加载中
115   - loading: {
116   - type: Boolean,
117   - default: uni.$u.props.swiper.loading
118   - },
119   - // 是否显示标题,要求数组对象中有title属性
120   - showTitle: {
121   - type: Boolean,
122   - default: uni.$u.props.swiper.showTitle
123   - }
124   - }
125   -}
1   -<template>
2   - <view
3   - class="u-swiper"
4   - :style="{
5   - backgroundColor: bgColor,
6   - height: $u.addUnit(height),
7   - borderRadius: $u.addUnit(radius)
8   - }"
9   - >
10   - <view
11   - class="u-swiper__loading"
12   - v-if="loading"
13   - >
14   - <u-loading-icon mode="circle"></u-loading-icon>
15   - </view>
16   - <swiper
17   - v-else
18   - class="u-swiper__wrapper"
19   - :style="{
20   - height: $u.addUnit(height),
21   - }"
22   - @change="change"
23   - :circular="circular"
24   - :interval="interval"
25   - :duration="duration"
26   - :autoplay="autoplay"
27   - :current="current"
28   - :currentItemId="currentItemId"
29   - :previousMargin="$u.addUnit(previousMargin)"
30   - :nextMargin="$u.addUnit(nextMargin)"
31   - :acceleration="acceleration"
32   - :displayMultipleItems="displayMultipleItems"
33   - :easingFunction="easingFunction"
34   - >
35   - <swiper-item
36   - class="u-swiper__wrapper__item"
37   - v-for="(item, index) in list"
38   - :key="index"
39   - >
40   - <view
41   - class="u-swiper__wrapper__item__wrapper"
42   - :style="[itemStyle(index)]"
43   - >
44   - <!-- nvue中,image图片的宽度默认为屏幕宽度,需要通过flex:1撑开,另外必须设置高度才能显示图片 -->
45   - <image
46   - class="u-swiper__wrapper__item__wrapper__image"
47   - v-if="$u.test.image(getSource(item))"
48   - :src="getSource(item)"
49   - :mode="imgMode"
50   - @tap="clickHandler(index)"
51   - :style="{
52   - height: $u.addUnit(height),
53   - borderRadius: $u.addUnit(radius)
54   - }"
55   - ></image>
56   - <video
57   - class="u-swiper__wrapper__item__wrapper__video"
58   - v-if="$u.test.video(getSource(item))"
59   - :id="`video-${index}`"
60   - :enable-progress-gesture="false"
61   - :src="getSource(item)"
62   - :poster="getPoster(item)"
63   - :title="showTitle && $u.test.object(item) && item.title ? item.title : ''"
64   - :style="{
65   - height: $u.addUnit(height)
66   - }"
67   - controls
68   - @tap="clickHandler(index)"
69   - ></video>
70   - <text
71   - v-if="showTitle && $u.test.object(item) && item.title && $u.test.image(getSource(item))"
72   - class="u-swiper__wrapper__item__wrapper__title u-line-1"
73   - >{{ item.title }}</text>
74   - </view>
75   - </swiper-item>
76   - </swiper>
77   - <view class="u-swiper__indicator" :style="[$u.addStyle(indicatorStyle)]">
78   - <slot name="indicator">
79   - <u-swiper-indicator
80   - v-if="!loading && indicator && !showTitle"
81   - :indicatorActiveColor="indicatorActiveColor"
82   - :indicatorInactiveColor="indicatorInactiveColor"
83   - :length="list.length"
84   - :current="currentIndex"
85   - :indicatorMode="indicatorMode"
86   - ></u-swiper-indicator>
87   - </slot>
88   - </view>
89   - </view>
90   -</template>
91   -
92   -<script>
93   - import props from './props.js';
94   - /**
95   - * Swiper 轮播图
96   - * @description 该组件一般用于导航轮播,广告展示等场景,可开箱即用,
97   - * @tutorial https://www.uviewui.com/components/swiper.html
98   - * @property {Array} list 轮播图数据
99   - * @property {Boolean} indicator 是否显示面板指示器(默认 false )
100   - * @property {String} indicatorActiveColor 指示器非激活颜色(默认 '#FFFFFF' )
101   - * @property {String} indicatorInactiveColor 指示器的激活颜色(默认 'rgba(255, 255, 255, 0.35)' )
102   - * @property {String | Object} indicatorStyle 指示器样式,可通过bottom,left,right进行定位
103   - * @property {String} indicatorMode 指示器模式(默认 'line' )
104   - * @property {Boolean} autoplay 是否自动切换(默认 true )
105   - * @property {String | Number} current 当前所在滑块的 index(默认 0 )
106   - * @property {String} currentItemId 当前所在滑块的 item-id ,不能与 current 被同时指定
107   - * @property {String | Number} interval 滑块自动切换时间间隔(ms)(默认 3000 )
108   - * @property {String | Number} duration 滑块切换过程所需时间(ms)(默认 300 )
109   - * @property {Boolean} circular 播放到末尾后是否重新回到开头(默认 false )
110   - * @property {String | Number} previousMargin 前边距,可用于露出前一项的一小部分,nvue和支付宝不支持(默认 0 )
111   - * @property {String | Number} nextMargin 后边距,可用于露出后一项的一小部分,nvue和支付宝不支持(默认 0 )
112   - * @property {Boolean} acceleration 当开启时,会根据滑动速度,连续滑动多屏,支付宝不支持(默认 false )
113   - * @property {Number} displayMultipleItems 同时显示的滑块数量,nvue、支付宝小程序不支持(默认 1 )
114   - * @property {String} easingFunction 指定swiper切换缓动动画类型, 只对微信小程序有效(默认 'default' )
115   - * @property {String} keyName list数组中指定对象的目标属性名(默认 'url' )
116   - * @property {String} imgMode 图片的裁剪模式(默认 'aspectFill' )
117   - * @property {String | Number} height 组件高度(默认 130 )
118   - * @property {String} bgColor 背景颜色(默认 '#f3f4f6' )
119   - * @property {String | Number} radius 组件圆角,数值或带单位的字符串(默认 4 )
120   - * @property {Boolean} loading 是否加载中(默认 false )
121   - * @property {Boolean} showTitle 是否显示标题,要求数组对象中有title属性(默认 false )
122   - * @event {Function(index)} click 点击轮播图时触发 index:点击了第几张图片,从0开始
123   - * @event {Function(index)} change 轮播图切换时触发(自动或者手动切换) index:切换到了第几张图片,从0开始
124   - * @example <u-swiper :list="list4" keyName="url" :autoplay="false"></u-swiper>
125   - */
126   - export default {
127   - name: 'u-swiper',
128   - mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
129   - data() {
130   - return {
131   - currentIndex: 0
132   - }
133   - },
134   - watch: {
135   - current(val, preVal) {
136   - if(val === preVal) return;
137   - this.currentIndex = val; // 和上游数据关联上
138   - }
139   - },
140   - computed: {
141   - itemStyle() {
142   - return index => {
143   - const style = {}
144   - // #ifndef APP-NVUE || MP-TOUTIAO
145   - // 左右流出空间的写法不支持nvue和头条
146   - // 只有配置了此二值,才加上对应的圆角,以及缩放
147   - if (this.nextMargin && this.previousMargin) {
148   - style.borderRadius = uni.$u.addUnit(this.radius)
149   - if (index !== this.currentIndex) style.transform = 'scale(0.92)'
150   - }
151   - // #endif
152   - return style
153   - }
154   - }
155   - },
156   - methods: {
157   - // 获取目标路径,可能数组中为字符串,对象的形式,额外可指定对象的目标属性名keyName
158   - getSource(item) {
159   - if (typeof item === 'string') return item
160   - if (typeof item === 'object' && this.keyName) return item[this.keyName]
161   - else uni.$u.error('请按格式传递列表参数')
162   - return ''
163   - },
164   - // 轮播切换事件
165   - change(e) {
166   - // 当前的激活索引
167   - const {
168   - current
169   - } = e.detail
170   - this.pauseVideo(this.currentIndex)
171   - this.currentIndex = current
172   - this.$emit('change', e.detail)
173   - },
174   - // 切换轮播时,暂停视频播放
175   - pauseVideo(index) {
176   - const lastItem = this.getSource(this.list[index])
177   - if (uni.$u.test.video(lastItem)) {
178   - // 当视频隐藏时,暂停播放
179   - const video = uni.createVideoContext(`video-${index}`, this)
180   - video.pause()
181   - }
182   - },
183   - // 当一个轮播item为视频时,获取它的视频海报
184   - getPoster(item) {
185   - return typeof item === 'object' && item.poster ? item.poster : ''
186   - },
187   - // 点击某个item
188   - clickHandler(index) {
189   - this.$emit('click', index)
190   - }
191   - },
192   - }
193   -</script>
194   -
195   -<style lang="scss" scoped>
196   - @import "../../libs/css/components.scss";
197   -
198   - .u-swiper {
199   - @include flex;
200   - justify-content: center;
201   - align-items: center;
202   - position: relative;
203   - overflow: hidden;
204   -
205   - &__wrapper {
206   - flex: 1;
207   -
208   - &__item {
209   - flex: 1;
210   -
211   - &__wrapper {
212   - @include flex;
213   - position: relative;
214   - overflow: hidden;
215   - transition: transform 0.3s;
216   - flex: 1;
217   -
218   - &__image {
219   - flex: 1;
220   - }
221   -
222   - &__video {
223   - flex: 1;
224   - }
225   -
226   - &__title {
227   - position: absolute;
228   - background-color: rgba(0, 0, 0, 0.3);
229   - bottom: 0;
230   - left: 0;
231   - right: 0;
232   - font-size: 28rpx;
233   - padding: 12rpx 24rpx;
234   - color: #FFFFFF;
235   - flex: 1;
236   - }
237   - }
238   - }
239   - }
240   -
241   - &__indicator {
242   - position: absolute;
243   - bottom: 10px;
244   - }
245   - }
246   -</style>
1   -## 3.0.1(2021-05-13)
2   -1. 跳转颜色和图标配置
3   -2. 新增静默更新
4   -## 3.0.0(2021-05-12)
5   -1. 支持uni_modules
1   -// #ifdef APP-PLUS
2   -import componentConfig from "@/config/componentConfig"
3   -const platform = uni.getSystemInfoSync().platform;
4   -// 主颜色
5   -const $mainColor = componentConfig.appUpdateColor ? componentConfig.appUpdateColor : "FF5B78";
6   -// 弹窗图标url
7   -const $iconUrl = componentConfig.appUpdateIcon ? componentConfig.appUpdateIcon : "/uni_modules/zhouWei-APPUpdate/static/ic_ar.png";
8   -
9   -// 获取当前应用的版本号
10   -export const getCurrentNo = function(callback) {
11   - // 获取本地应用资源版本号
12   - plus.runtime.getProperty(plus.runtime.appid, function(inf) {
13   - callback && callback({
14   - versionCode: inf.versionCode,
15   - versionName: inf.version
16   - });
17   - });
18   -}
19   -// 从服务器下载应用资源包(wgt文件)
20   -const getDownload = function(data) {
21   - let dtask;
22   - if(data.updateType == 'forcibly' || data.updateType == 'solicit'){
23   - let popupData = {
24   - progress: true,
25   - buttonNum: 2
26   - };
27   - if(data.updateType == 'forcibly'){
28   - popupData.buttonNum = 0;
29   - }
30   - let lastProgressValue = 0;
31   - let popupObj = downloadPopup(popupData);
32   - dtask = plus.downloader.createDownload(data.downloadUrl, {
33   - filename: "_doc/update/"
34   - }, function(download, status) {
35   - if (status == 200) {
36   - popupObj.change({
37   - progressValue: 100,
38   - progressTip:"正在安装文件...",
39   - progress: true,
40   - buttonNum: 0
41   - });
42   - plus.runtime.install(download.filename, {}, function() {
43   - popupObj.change({
44   - contentText: "应用资源更新完成!",
45   - buttonNum: 1,
46   - progress: false
47   - });
48   - }, function(e) {
49   - popupObj.cancel();
50   - plus.nativeUI.alert("安装文件失败[" + e.code + "]:" + e.message);
51   - });
52   - } else {
53   - popupObj.change({
54   - contentText: "文件下载失败...",
55   - buttonNum: 1,
56   - progress: false
57   - });
58   - }
59   - });
60   - dtask.start();
61   - dtask.addEventListener("statechanged", function(task, status) {
62   - switch (task.state) {
63   - case 1: // 开始
64   - popupObj.change({
65   - progressValue:0,
66   - progressTip:"准备下载...",
67   - progress: true
68   - });
69   - break;
70   - case 2: // 已连接到服务器
71   - popupObj.change({
72   - progressValue:0,
73   - progressTip:"开始下载...",
74   - progress: true
75   - });
76   - break;
77   - case 3:
78   - const progress = parseInt(task.downloadedSize / task.totalSize * 100);
79   - if(progress - lastProgressValue >= 2){
80   - lastProgressValue = progress;
81   - popupObj.change({
82   - progressValue:progress,
83   - progressTip: "已下载" + progress + "%",
84   - progress: true
85   - });
86   - }
87   - break;
88   - }
89   - });
90   - // 取消下载
91   - popupObj.cancelDownload = function(){
92   - dtask && dtask.abort();
93   - uni.showToast({
94   - title: "已取消下载",
95   - icon:"none"
96   - });
97   - }
98   - // 重启APP
99   - popupObj.reboot = function(){
100   - plus.runtime.restart();
101   - }
102   - } else if(data.updateType == "silent"){
103   - dtask = plus.downloader.createDownload(data.downloadUrl, {
104   - filename: "_doc/update/"
105   - }, function(download, status) {
106   - if (status == 200) {
107   - plus.runtime.install(download.filename, {}, function() {
108   - console.log("应用资源更新完成");
109   - }, function(e) {
110   - plus.nativeUI.alert("安装文件失败[" + e.code + "]:" + e.message);
111   - });
112   - } else {
113   - plus.nativeUI.alert("文件下载失败...");
114   - }
115   - });
116   - dtask.start();
117   - }
118   -}
119   -// 文字换行
120   -function drawtext(text, maxWidth) {
121   - let textArr = text.split("");
122   - let len = textArr.length;
123   - // 上个节点
124   - let previousNode = 0;
125   - // 记录节点宽度
126   - let nodeWidth = 0;
127   - // 文本换行数组
128   - let rowText = [];
129   - // 如果是字母,侧保存长度
130   - let letterWidth = 0;
131   - // 汉字宽度
132   - let chineseWidth = 14;
133   - // otherFont宽度
134   - let otherWidth = 7;
135   - for (let i = 0; i < len; i++) {
136   - if (/[\u4e00-\u9fa5]|[\uFE30-\uFFA0]/g.test(textArr[i])) {
137   - if(letterWidth > 0){
138   - if(nodeWidth + chineseWidth + letterWidth * otherWidth > maxWidth){
139   - rowText.push({
140   - type: "text",
141   - content: text.substring(previousNode, i)
142   - });
143   - previousNode = i;
144   - nodeWidth = chineseWidth;
145   - letterWidth = 0;
146   - } else {
147   - nodeWidth += chineseWidth + letterWidth * otherWidth;
148   - letterWidth = 0;
149   - }
150   - } else {
151   - if(nodeWidth + chineseWidth > maxWidth){
152   - rowText.push({
153   - type: "text",
154   - content: text.substring(previousNode, i)
155   - });
156   - previousNode = i;
157   - nodeWidth = chineseWidth;
158   - }else{
159   - nodeWidth += chineseWidth;
160   - }
161   - }
162   - } else {
163   - if(/\n/g.test(textArr[i])){
164   - rowText.push({
165   - type: "break",
166   - content: text.substring(previousNode, i)
167   - });
168   - previousNode = i + 1;
169   - nodeWidth = 0;
170   - letterWidth = 0;
171   - }else if(textArr[i] == "\\" && textArr[i + 1] == "n"){
172   - rowText.push({
173   - type: "break",
174   - content: text.substring(previousNode, i)
175   - });
176   - previousNode = i + 2;
177   - nodeWidth = 0;
178   - letterWidth = 0;
179   - }else if(/[a-zA-Z0-9]/g.test(textArr[i])){
180   - letterWidth += 1;
181   - if(nodeWidth + letterWidth * otherWidth > maxWidth){
182   - rowText.push({
183   - type: "text",
184   - content: text.substring(previousNode, i + 1 - letterWidth)
185   - });
186   - previousNode = i + 1 - letterWidth;
187   - nodeWidth = letterWidth * otherWidth;
188   - letterWidth = 0;
189   - }
190   - } else{
191   - if(nodeWidth + otherWidth > maxWidth){
192   - rowText.push({
193   - type: "text",
194   - content: text.substring(previousNode, i)
195   - });
196   - previousNode = i;
197   - nodeWidth = otherWidth;
198   - }else{
199   - nodeWidth += otherWidth;
200   - }
201   - }
202   - }
203   - }
204   - if (previousNode < len) {
205   - rowText.push({
206   - type: "text",
207   - content: text.substring(previousNode, len)
208   - });
209   - }
210   - return rowText;
211   -}
212   -// 是否更新弹窗
213   -function updatePopup(data, callback) {
214   - // 弹窗遮罩层
215   - let maskLayer = new plus.nativeObj.View("maskLayer", { //先创建遮罩层
216   - top: '0px',
217   - left: '0px',
218   - height: '100%',
219   - width: '100%',
220   - backgroundColor: 'rgba(0,0,0,0.5)'
221   - });
222   -
223   - // 以下为计算菜单的nview绘制布局,为固定算法,使用者无关关心
224   - const screenWidth = plus.screen.resolutionWidth;
225   - const screenHeight = plus.screen.resolutionHeight;
226   - //弹窗容器宽度
227   - const popupViewWidth = screenWidth * 0.7;
228   - // 弹窗容器的Padding
229   - const viewContentPadding = 20;
230   - // 弹窗容器的宽度
231   - const viewContentWidth = parseInt(popupViewWidth - (viewContentPadding * 2));
232   - // 描述的列表
233   - const descriptionList = drawtext(data.versionInfo, viewContentWidth);
234   - // 弹窗容器高度
235   - let popupViewHeight = 80 + 20 + 20 + 90 + 10;
236   -
237   - let popupViewContentList = [{
238   - src: $iconUrl,
239   - id: "logo",
240   - tag: "img",
241   - position: {
242   - top: "0px",
243   - left: (popupViewWidth - 124) / 2 + "px",
244   - width: "124px",
245   - height: "80px",
246   - }
247   - },
248   - {
249   - tag: 'font',
250   - id: 'title',
251   - text: "发现新版本" + data.versionName,
252   - textStyles: {
253   - size: '18px',
254   - color: "#333",
255   - weight: "bold",
256   - whiteSpace: "normal"
257   - },
258   - position: {
259   - top: '90px',
260   - left: viewContentPadding + "px",
261   - width: viewContentWidth + "px",
262   - height: "30px",
263   - }
264   - }];
265   - const textHeight = 18;
266   - let contentTop = 130;
267   - descriptionList.forEach((item,index) => {
268   - if(index > 0){
269   - popupViewHeight += textHeight;
270   - contentTop += textHeight;
271   - }
272   - popupViewContentList.push({
273   - tag: 'font',
274   - id: 'content' + index + 1,
275   - text: item.content,
276   - textStyles: {
277   - size: '14px',
278   - color: "#666",
279   - lineSpacing: "50%",
280   - align: "left"
281   - },
282   - position: {
283   - top: contentTop + "px",
284   - left: viewContentPadding + "px",
285   - width: viewContentWidth + "px",
286   - height: textHeight + "px",
287   - }
288   - });
289   - if(item.type == "break"){
290   - contentTop += 10;
291   - popupViewHeight += 10;
292   - }
293   - });
294   -
295   - if(data.updateType == "forcibly"){
296   - popupViewContentList.push({
297   - tag: 'rect', //绘制底边按钮
298   - rectStyles:{
299   - radius: "6px",
300   - color: $mainColor
301   - },
302   - position:{
303   - bottom: viewContentPadding + 'px',
304   - left: viewContentPadding + "px",
305   - width: viewContentWidth + "px",
306   - height: "30px"
307   - }
308   - });
309   - popupViewContentList.push({
310   - tag: 'font',
311   - id: 'confirmText',
312   - text: "立即升级",
313   - textStyles: {
314   - size: '14px',
315   - color: "#FFF",
316   - lineSpacing: "0%",
317   - },
318   - position: {
319   - bottom: viewContentPadding + 'px',
320   - left: viewContentPadding + "px",
321   - width: viewContentWidth + "px",
322   - height: "30px"
323   - }
324   - });
325   - } else {
326   - // 绘制底边按钮
327   - popupViewContentList.push({
328   - tag: 'rect',
329   - id: 'cancelBox',
330   - rectStyles: {
331   - radius: "3px",
332   - borderColor: "#f1f1f1",
333   - borderWidth: "1px",
334   - },
335   - position: {
336   - bottom: viewContentPadding + 'px',
337   - left: viewContentPadding + "px",
338   - width: (viewContentWidth - viewContentPadding) / 2 + "px",
339   - height: "30px",
340   - }
341   - });
342   - popupViewContentList.push({
343   - tag: 'rect',
344   - id: 'confirmBox',
345   - rectStyles: {
346   - radius: "3px",
347   - color: $mainColor,
348   - },
349   - position: {
350   - bottom: viewContentPadding + 'px',
351   - left: ((viewContentWidth - viewContentPadding) / 2 + viewContentPadding * 2) + "px",
352   - width: (viewContentWidth - viewContentPadding) / 2 + "px",
353   - height: "30px",
354   - }
355   - });
356   - popupViewContentList.push({
357   - tag: 'font',
358   - id: 'cancelText',
359   - text: "暂不升级",
360   - textStyles: {
361   - size: '14px',
362   - color: "#666",
363   - lineSpacing: "0%",
364   - whiteSpace: "normal"
365   - },
366   - position: {
367   - bottom: viewContentPadding + 'px',
368   - left: viewContentPadding + "px",
369   - width: (viewContentWidth - viewContentPadding) / 2 + "px",
370   - height: "30px",
371   - }
372   - });
373   - popupViewContentList.push({
374   - tag: 'font',
375   - id: 'confirmText',
376   - text: "立即升级",
377   - textStyles: {
378   - size: '14px',
379   - color: "#FFF",
380   - lineSpacing: "0%",
381   - whiteSpace: "normal"
382   - },
383   - position: {
384   - bottom: viewContentPadding + 'px',
385   - left: ((viewContentWidth - viewContentPadding) / 2 + viewContentPadding * 2) + "px",
386   - width: (viewContentWidth - viewContentPadding) / 2 + "px",
387   - height: "30px",
388   - }
389   - });
390   - }
391   - // 弹窗内容
392   - let popupView = new plus.nativeObj.View("popupView", { //创建底部图标菜单
393   - tag: "rect",
394   - top: (screenHeight - popupViewHeight) / 2 + "px",
395   - left: '15%',
396   - height: popupViewHeight + "px",
397   - width: "70%"
398   - });
399   - // 绘制白色背景
400   - popupView.drawRect({
401   - color: "#FFFFFF",
402   - radius: "8px"
403   - }, {
404   - top: "40px",
405   - height: popupViewHeight - 40 + "px",
406   - });
407   -
408   - popupView.draw(popupViewContentList);
409   - popupView.addEventListener("click", function(e) {
410   - let maxTop = popupViewHeight - viewContentPadding;
411   - let maxLeft = popupViewWidth - viewContentPadding;
412   - let buttonWidth = (viewContentWidth - viewContentPadding) / 2;
413   - if (e.clientY > maxTop - 30 && e.clientY < maxTop) {
414   - if(data.updateType == "forcibly"){
415   - if(e.clientX > viewContentPadding && e.clientX < maxLeft){
416   - // 立即升级
417   - maskLayer.hide();
418   - popupView.hide();
419   - callback && callback();
420   - }
421   - } else {
422   - // 暂不升级
423   - if (e.clientX > viewContentPadding && e.clientX < maxLeft - buttonWidth - viewContentPadding) {
424   - maskLayer.hide();
425   - popupView.hide();
426   - } else if (e.clientX > maxLeft - buttonWidth && e.clientX < maxLeft) {
427   - // 立即升级
428   - maskLayer.hide();
429   - popupView.hide();
430   - callback && callback();
431   - }
432   - }
433   -
434   - }
435   - });
436   - if(data.updateType == "solicit"){
437   - // 点击遮罩层
438   - maskLayer.addEventListener("click", function() { //处理遮罩层点击
439   - maskLayer.hide();
440   - popupView.hide();
441   - });
442   - }
443   - // 显示弹窗
444   - maskLayer.show();
445   - popupView.show();
446   -}
447   -// 文件下载的弹窗绘图
448   -function downloadPopupDrawing(data){
449   - // 以下为计算菜单的nview绘制布局,为固定算法,使用者无关关心
450   - const screenWidth = plus.screen.resolutionWidth;
451   - const screenHeight = plus.screen.resolutionHeight;
452   - //弹窗容器宽度
453   - const popupViewWidth = screenWidth * 0.7;
454   - // 弹窗容器的Padding
455   - const viewContentPadding = 20;
456   - // 弹窗容器的宽度
457   - const viewContentWidth = popupViewWidth - (viewContentPadding * 2);
458   - // 弹窗容器高度
459   - let popupViewHeight = viewContentPadding * 3 + 60;
460   - let progressTip = data.progressTip || "准备下载...";
461   - let contentText = data.contentText || "正在为您更新,请耐心等待";
462   - let elementList = [
463   - {
464   - tag: 'rect', //背景色
465   - color: '#FFFFFF',
466   - rectStyles:{
467   - radius: "8px"
468   - }
469   - },
470   - {
471   - tag: 'font',
472   - id: 'title',
473   - text: "升级APP",
474   - textStyles: {
475   - size: '16px',
476   - color: "#333",
477   - weight: "bold",
478   - verticalAlign: "middle",
479   - whiteSpace: "normal"
480   - },
481   - position: {
482   - top: viewContentPadding + 'px',
483   - height: "30px",
484   - }
485   - },
486   - {
487   - tag: 'font',
488   - id: 'content',
489   - text: contentText,
490   - textStyles: {
491   - size: '14px',
492   - color: "#333",
493   - verticalAlign: "middle",
494   - whiteSpace: "normal"
495   - },
496   - position: {
497   - top: viewContentPadding * 2 + 30 + 'px',
498   - height: "20px",
499   - }
500   - }
501   - ];
502   - // 是否有进度条
503   - if(data.progress){
504   - popupViewHeight += viewContentPadding + 40;
505   - elementList = elementList.concat([
506   - {
507   - tag: 'font',
508   - id: 'progressValue',
509   - text: progressTip,
510   - textStyles: {
511   - size: '14px',
512   - color: $mainColor,
513   - whiteSpace: "normal"
514   - },
515   - position: {
516   - top: viewContentPadding * 4 + 20 + 'px',
517   - height: "30px"
518   - }
519   - },
520   - {
521   - tag: 'rect', //绘制进度条背景
522   - id: 'progressBg',
523   - rectStyles:{
524   - radius: "4px",
525   - borderColor: "#f1f1f1",
526   - borderWidth: "1px",
527   - },
528   - position:{
529   - top: viewContentPadding * 4 + 60 + 'px',
530   - left: viewContentPadding + "px",
531   - width: viewContentWidth + "px",
532   - height: "8px"
533   - }
534   - },
535   - ]);
536   - }
537   - if (data.buttonNum == 2) {
538   - popupViewHeight += viewContentPadding + 30;
539   - elementList = elementList.concat([
540   - {
541   - tag: 'rect', //绘制底边按钮
542   - rectStyles:{
543   - radius: "3px",
544   - borderColor: "#f1f1f1",
545   - borderWidth: "1px",
546   - },
547   - position:{
548   - bottom: viewContentPadding + 'px',
549   - left: viewContentPadding + "px",
550   - width: (viewContentWidth - viewContentPadding) / 2 + "px",
551   - height: "30px"
552   - }
553   - },
554   - {
555   - tag: 'rect', //绘制底边按钮
556   - rectStyles:{
557   - radius: "3px",
558   - color: $mainColor
559   - },
560   - position:{
561   - bottom: viewContentPadding + 'px',
562   - left: ((viewContentWidth - viewContentPadding) / 2 + viewContentPadding * 2) + "px",
563   - width: (viewContentWidth - viewContentPadding) / 2 + "px",
564   - height: "30px"
565   - }
566   - },
567   - {
568   - tag: 'font',
569   - id: 'cancelText',
570   - text: "取消下载",
571   - textStyles: {
572   - size: '14px',
573   - color: "#666",
574   - lineSpacing: "0%",
575   - whiteSpace: "normal"
576   - },
577   - position: {
578   - bottom: viewContentPadding + 'px',
579   - left: viewContentPadding + "px",
580   - width: (viewContentWidth - viewContentPadding) / 2 + "px",
581   - height: "30px",
582   - }
583   - },
584   - {
585   - tag: 'font',
586   - id: 'confirmText',
587   - text: "后台下载",
588   - textStyles: {
589   - size: '14px',
590   - color: "#FFF",
591   - lineSpacing: "0%",
592   - whiteSpace: "normal"
593   - },
594   - position: {
595   - bottom: viewContentPadding + 'px',
596   - left: ((viewContentWidth - viewContentPadding) / 2 + viewContentPadding * 2) + "px",
597   - width: (viewContentWidth - viewContentPadding) / 2 + "px",
598   - height: "30px",
599   - }
600   - }
601   - ]);
602   - }
603   - if (data.buttonNum == 1) {
604   - popupViewHeight += viewContentPadding + 40;
605   - elementList = elementList.concat([
606   - {
607   - tag: 'rect', //绘制底边按钮
608   - rectStyles:{
609   - radius: "6px",
610   - color: $mainColor
611   - },
612   - position:{
613   - bottom: viewContentPadding + 'px',
614   - left: viewContentPadding + "px",
615   - width: viewContentWidth + "px",
616   - height: "40px"
617   - }
618   - },
619   - {
620   - tag: 'font',
621   - id: 'confirmText',
622   - text: "关闭",
623   - textStyles: {
624   - size: '14px',
625   - color: "#FFF",
626   - lineSpacing: "0%",
627   - },
628   - position: {
629   - bottom: viewContentPadding + 'px',
630   - left: viewContentPadding + "px",
631   - width: viewContentWidth + "px",
632   - height: "40px"
633   - }
634   - }
635   - ]);
636   - }
637   - return {
638   - popupViewHeight:popupViewHeight,
639   - popupViewWidth:popupViewWidth,
640   - screenHeight:screenHeight,
641   - viewContentWidth:viewContentWidth,
642   - viewContentPadding:viewContentPadding,
643   - elementList: elementList
644   - };
645   -}
646   -// 文件下载的弹窗
647   -function downloadPopup(data) {
648   - // 弹窗遮罩层
649   - let maskLayer = new plus.nativeObj.View("maskLayer", { //先创建遮罩层
650   - top: '0px',
651   - left: '0px',
652   - height: '100%',
653   - width: '100%',
654   - backgroundColor: 'rgba(0,0,0,0.5)'
655   - });
656   - let popupViewData = downloadPopupDrawing(data);
657   - // 弹窗内容
658   - let popupView = new plus.nativeObj.View("popupView", { //创建底部图标菜单
659   - tag: "rect",
660   - top: (popupViewData.screenHeight - popupViewData.popupViewHeight) / 2 + "px",
661   - left: '15%',
662   - height: popupViewData.popupViewHeight + "px",
663   - width: "70%",
664   - });
665   - let progressValue = 0;
666   - let progressTip = 0;
667   - let contentText = 0;
668   - let buttonNum = 2;
669   - if(data.buttonNum >= 0){
670   - buttonNum = data.buttonNum;
671   - }
672   - popupView.draw(popupViewData.elementList);
673   - let callbackData = {
674   - change: function(res) {
675   - let progressElement = [];
676   - if(res.progressValue){
677   - progressValue = res.progressValue;
678   - // 绘制进度条
679   - progressElement.push({
680   - tag: 'rect', //绘制进度条背景
681   - id: 'progressValueBg',
682   - rectStyles:{
683   - radius: "4px",
684   - color: $mainColor
685   - },
686   - position:{
687   - top: popupViewData.viewContentPadding * 4 + 60 + 'px',
688   - left: popupViewData.viewContentPadding + "px",
689   - width: popupViewData.viewContentWidth * (res.progressValue / 100) + "px",
690   - height: "8px"
691   - }
692   - });
693   - }
694   - if(res.progressTip){
695   - progressTip = res.progressTip;
696   - progressElement.push({
697   - tag: 'font',
698   - id: 'progressValue',
699   - text: res.progressTip,
700   - textStyles: {
701   - size: '14px',
702   - color: $mainColor,
703   - whiteSpace: "normal"
704   - },
705   - position: {
706   - top: popupViewData.viewContentPadding * 4 + 20 + 'px',
707   - height: "30px"
708   - }
709   - });
710   - }
711   - if(res.contentText){
712   - contentText = res.contentText;
713   - progressElement.push({
714   - tag: 'font',
715   - id: 'content',
716   - text: res.contentText,
717   - textStyles: {
718   - size: '16px',
719   - color: "#333",
720   - whiteSpace: "normal"
721   - },
722   - position: {
723   - top: popupViewData.viewContentPadding * 2 + 30 + 'px',
724   - height: "30px",
725   - }
726   - });
727   - }
728   - if(res.buttonNum >= 0 && buttonNum != res.buttonNum){
729   - buttonNum = res.buttonNum;
730   - popupView.reset();
731   - popupViewData = downloadPopupDrawing(Object.assign({
732   - progressValue:progressValue,
733   - progressTip:progressTip,
734   - contentText:contentText,
735   - },res));
736   - let newElement = [];
737   - popupViewData.elementList.map((item,index) => {
738   - let have = false;
739   - progressElement.forEach((childItem,childIndex) => {
740   - if(item.id == childItem.id){
741   - have = true;
742   - }
743   - });
744   - if(!have){
745   - newElement.push(item);
746   - }
747   - });
748   - progressElement = newElement.concat(progressElement);
749   - popupView.setStyle({
750   - tag: "rect",
751   - top: (popupViewData.screenHeight - popupViewData.popupViewHeight) / 2 + "px",
752   - left: '15%',
753   - height: popupViewData.popupViewHeight + "px",
754   - width: "70%",
755   - });
756   - popupView.draw(progressElement);
757   - }else{
758   - popupView.draw(progressElement);
759   - }
760   - },
761   - cancel: function() {
762   - maskLayer.hide();
763   - popupView.hide();
764   - }
765   - }
766   - popupView.addEventListener("click", function(e) {
767   - let maxTop = popupViewData.popupViewHeight - popupViewData.viewContentPadding;
768   - let maxLeft = popupViewData.popupViewWidth - popupViewData.viewContentPadding;
769   - if (e.clientY > maxTop - 40 && e.clientY < maxTop) {
770   - if(buttonNum == 1){
771   - // 单按钮
772   - if (e.clientX > popupViewData.viewContentPadding && e.clientX < maxLeft) {
773   - maskLayer.hide();
774   - popupView.hide();
775   - callbackData.reboot();
776   - }
777   - }else if(buttonNum == 2){
778   - // 双按钮
779   - let buttonWidth = (popupViewData.viewContentWidth - popupViewData.viewContentPadding) / 2;
780   - if (e.clientX > popupViewData.viewContentPadding && e.clientX < maxLeft - buttonWidth - popupViewData.viewContentPadding) {
781   - maskLayer.hide();
782   - popupView.hide();
783   - callbackData.cancelDownload();
784   - } else if (e.clientX > maxLeft - buttonWidth && e.clientX < maxLeft) {
785   - maskLayer.hide();
786   - popupView.hide();
787   - }
788   - }
789   - }
790   - });
791   - // 显示弹窗
792   - maskLayer.show();
793   - popupView.show();
794   - // 改变进度条
795   - return callbackData;
796   -}
797   -export default function(isPrompt = false) {
798   - getCurrentNo(versionInfo => {
799   - componentConfig.getServerNo(versionInfo, isPrompt, res => {
800   - if (res.updateType == "forcibly" || res.updateType == "silent") {
801   - if (/\.wgt$/i.test(res.downloadUrl)) {
802   - getDownload(res);
803   - } else if(/\.html$/i.test(res.downloadUrl)){
804   - plus.runtime.openURL(res.downloadUrl);
805   - } else {
806   - if (platform == "android") {
807   - getDownload(res);
808   - } else {
809   - plus.runtime.openURL(res.downloadUrl);
810   - }
811   - }
812   - } else if(res.updateType == "solicit"){
813   - updatePopup(res, function() {
814   - if (/\.wgt$/i.test(res.downloadUrl)) {
815   - getDownload(res);
816   - } else if(/\.html$/i.test(res.downloadUrl)){
817   - plus.runtime.openURL(res.downloadUrl);
818   - } else {
819   - if (platform == "android") {
820   - getDownload(res);
821   - } else {
822   - plus.runtime.openURL(res.downloadUrl);
823   - }
824   - }
825   - });
826   - }
827   - });
828   - });
829   -}
830   -// #endif
\ No newline at end of file
1   -{
2   - "id": "zhouWei-APPUpdate",
3   - "displayName": "APP版本更新、强制更新、静默更新、下载进度(wgt更新)",
4   - "version": "3.0.1",
5   - "description": "APP版本更新、强制更新、静默更新、漂亮弹窗、下载进度(wgt更新)",
6   - "keywords": [
7   - "APP版本更新",
8   - "强制更新",
9   - "版本更新",
10   - "静默更新"
11   -],
12   - "repository": "https://github.com/zhouwei1994/uni-app-demo",
13   - "engines": {
14   - "HBuilderX": "^3.1.0"
15   - },
16   - "dcloudext": {
17   - "category": [
18   - "JS SDK",
19   - "通用 SDK"
20   - ],
21   - "sale": {
22   - "regular": {
23   - "price": "0.00"
24   - },
25   - "sourcecode": {
26   - "price": "0.00"
27   - }
28   - },
29   - "contact": {
30   - "qq": "465081029"
31   - },
32   - "declaration": {
33   - "ads": "无",
34   - "data": "无",
35   - "permissions": "<uses-permission android:name=\\\"android.permission.INSTALL_PACKAGES\\\"/> \n<uses-permission android:name=\\\"android.permission.REQUEST_INSTALL_PACKAGES\\\"/>"
36   - },
37   - "npmurl": ""
38   - },
39   - "uni_modules": {
40   - "dependencies": [],
41   - "encrypt": [],
42   - "platforms": {
43   - "cloud": {
44   - "tcb": "y",
45   - "aliyun": "y"
46   - },
47   - "client": {
48   - "App": {
49   - "app-vue": "y",
50   - "app-nvue": "y"
51   - },
52   - "H5-mobile": {
53   - "Safari": "n",
54   - "Android Browser": "n",
55   - "微信浏览器(Android)": "n",
56   - "QQ浏览器(Android)": "n"
57   - },
58   - "H5-pc": {
59   - "Chrome": "n",
60   - "IE": "n",
61   - "Edge": "n",
62   - "Firefox": "n",
63   - "Safari": "n"
64   - },
65   - "小程序": {
66   - "微信": "n",
67   - "阿里": "n",
68   - "百度": "n",
69   - "字节跳动": "n",
70   - "QQ": "n"
71   - },
72   - "快应用": {
73   - "华为": "n",
74   - "联盟": "n"
75   - }
76   - }
77   - }
78   - }
79   -}
\ No newline at end of file
1   -### 常见问题
2   -1.安卓apk下载完成后没有更新APP?
3   -
4   -答:问题是因为没有添加APP安装应用的权限,解决方法在`manifest.json`文件里面`APP模块权限配置`的`Android打包权限配置`勾选以下权限
5   -```
6   -<uses-permission android:name=\"android.permission.INSTALL_PACKAGES\"/>
7   -<uses-permission android:name=\"android.permission.REQUEST_INSTALL_PACKAGES\"/>
8   -```
9   -若还有问题请看[安装apk无法执行的解决方案](https://ask.dcloud.net.cn/article/35703 "安装apk无法执行的解决方案")
10   -
11   -2.APP更新后版本号没变,还是之前的版本号?
12   -
13   -答:可能是更新的安装包没有升级版本号,`manifest.json`文件里面基本设置`应用版本号`和`应用版本名称`需要升高(保持一直减少问题)
14   -
15   -3.APP更新后没有覆盖之前的APP?
16   -
17   -答:可能是更新的安装包`包名`和APP的`包名`不一样
18   -
19   -4.弹窗的图标不显示?
20   -
21   -答:检查图片是不是放项目资源文件`static`,然后重新运行项目
22   -
23   -5.版本号是在前端对比还是在后端接口对比?
24   -
25   -答:当前案例是本地的版本号通过接口传递给后台,是后台对比的,若需要前端对比,请在接口返回数据的地方修改,不更新就不要调用`callback`方法
26   -
27   -6.本地的版本号比接口的版本号高还弹窗升级窗口?
28   -
29   -答:当前案例是本地的版本号通过接口传递给后台,后台对比是否需要升级,不需要升级就不要返回数据(特别是需要wgt更新的,建议这种方式)
30   -
31   -### 第一步`关键`配置APP更新接口(可以参考上面的示例)
32   -在项目目录下`config/componentConfig.js`里面如下配置
33   -```
34   -// 此方法是接口请求方法
35   -import $http from '@/config/requestConfig'
36   -export default {
37   - // 发起ajax请求获取服务端版本号
38   - getServerNo: (version, isPrompt = false, callback) => {
39   - let httpData = {
40   - version: version.versionCode,
41   - // 版本名称
42   - versionName: version.versionName,
43   - // setupPage参数说明(判断用户是不是从设置页面点击的更新,如果是设置页面点击的更新,有不要用静默更新了,不然用户点击没反应很奇怪的)
44   - setupPage: isPrompt
45   - };
46   - if (platform == "android") {
47   - httpData.type = 1101;
48   - } else {
49   - httpData.type = 1102;
50   - }
51   - /* 接口入参说明
52   - * version: 应用当前版本号(已自动获取)
53   - * versionName: 应用当前版本名称(已自动获取)
54   - * type:平台(1101是安卓,1102是IOS)
55   - */
56   - /****************以下是示例*******************/
57   - // 可以用自己项目的请求方法(接口自己找后台要,插件不提供)
58   - $http.get("api/common/v1/app_version", httpData,{
59   - isPrompt: isPrompt
60   - }).then(res => {
61   - /* res的数据说明
62   - * | 参数名称 | 一定返回 | 类型 | 描述
63   - * | -------------|--------- | --------- | ------------- |
64   - * | versionCode | y | int | 版本号 |
65   - * | versionName | y | String | 版本名称 |
66   - * | versionInfo | y | String | 版本信息 |
67   - * | updateType | y | String | forcibly = 强制更新, solicit = 弹窗确认更新, silent = 静默更新 |
68   - * | downloadUrl | y | String | 版本下载链接(IOS安装包更新请放跳转store应用商店链接,安卓apk和wgt文件放文件下载链接) |
69   - */
70   - if (res && res.downloadUrl) {
71   - // 兼容之前的版本(updateType是新版才有的参数)
72   - if(res.updateType){
73   - callback && callback(res);
74   - } else {
75   - if(res.forceUpdate){
76   - res.updateType = "forcibly";
77   - } else {
78   - res.updateType = "solicit";
79   - }
80   - callback && callback(res);
81   - }
82   - } else if (isPrompt) {
83   - uni.showToast({
84   - title: "暂无新版本",
85   - icon: "none"
86   - });
87   - }
88   - });
89   - /****************以上是示例*******************/
90   - },
91   - // 弹窗主颜色(不填默认粉色)
92   - appUpdateColor: "f00",
93   - // 弹窗图标(不填显示默认图标,链接配置示例如: '/static/demo/ic_attention.png')
94   - appUpdateIcon: ''
95   -}
96   -```
97   -
98   -### 第二步 使用方法
99   -```
100   -// App.vue页面
101   -
102   -// #ifdef APP-PLUS
103   -import APPUpdate from '@/uni_modules/zhouWei-APPUpdate/js_sdk/appUpdate';
104   -// #endif
105   -
106   -onLaunch: function(e) {
107   - // #ifdef APP-PLUS
108   - APPUpdate();
109   - // #endif
110   -}
111   -```
112   -
113   -### 第三步 添加APP安装应用的权限
114   -`manifest.json`文件里面`APP模块权限配置`的`Android打包权限配置`勾选以下权限
115   -```
116   -<uses-permission android:name=\"android.permission.INSTALL_PACKAGES\"/>
117   -<uses-permission android:name=\"android.permission.REQUEST_INSTALL_PACKAGES\"/>
118   -```
119   -
120   -### 修改弹窗的主题色或弹窗图标
121   -`APPUpdate/index.js`里面上面`$mainColor`常量中定义主题颜色,`$iconUrl`常量中定义图标地址
122   -
123   -### 检查APP是否有新版本(一般在设置页面使用)
124   -```
125   -// #ifdef APP-PLUS
126   -import APPUpdate, { getCurrentNo } from '@/uni_modules/zhouWei-APPUpdate/js_sdk/appUpdate';
127   -// #endif
128   -export default {
129   - data() {
130   - return {
131   - version: "" // 版本号
132   - };
133   - },
134   - //第一次加载
135   - onLoad(e) {
136   - // #ifdef APP-PLUS
137   - getCurrentNo(res => {
138   - // 进页面获取当前APP版本号(用于页面显示)
139   - this.version = res.version;
140   - });
141   - // #endif
142   - },
143   - //方法
144   - methods: {
145   - // 检查APP是否有新版本
146   - onAPPUpdate() {
147   - // true 没有新版本的时候有提示,默认:false
148   - APPUpdate(true);
149   - }
150   - }
151   -}
152   -```
\ No newline at end of file