Commit deff746d authored by niguangyjf's avatar niguangyjf

综合首页

parent 57cc89f1
FROM nginx:1.18
COPY nginx-conf/nginx.conf /etc/nginx/nginx.conf
COPY dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
\ No newline at end of file
variables:
#KUBECONFIG: /etc/deploy/config
#debug 模式开关
#CI_DEBUG_TRACE: "true"
# https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#use-docker-in-docker
#DOCKER_HOST: tcp://localhost:2375
DOCKER_DRIVER: overlay2
DOCKER_TLS_CERTDIR: '/certs'
##This folder is cached between builds
##http://docs.gitlab.com/ce/ci/yaml/README.html#cache
cache:
untracked: true
key: ${CI_COMMIT_REF_SLUG}
paths:
- ./node_modules
- ./dist
stages:
- build
- push
- deploy
## -- master -- ##
## -- test -- ###########################################################################################
build-node:test:
image: node:12.13.0
stage: build
variables:
API_ADDR: 'https://api.devops.thinker.vc'
before_script:
- npm config set registry=http://registry.npm.taobao.org
- npm config set puppeteer_download_host=https://storage.googleapis.com.cnpmjs.org
- yarn config set ignore-engines true
- export APP_ENV_OS=test
script:
- yarn
- yarn build
only:
- test
tags:
- node-build-mac
docker-push:test:
image: docker:20.10.16
# services:
# - docker:20.10.16-dind
stage: push
before_script:
- docker login -u ${docker_username} -p ${docker_password} registry.cn-shenzhen.aliyuncs.com
script:
- docker build -t registry.cn-shenzhen.aliyuncs.com/thinker-vc/thinker-cloud-admin-front:test-1.0.0 .
- docker push registry.cn-shenzhen.aliyuncs.com/thinker-vc/thinker-cloud-admin-front:test-1.0.0
after_script:
- docker rmi registry.cn-shenzhen.aliyuncs.com/thinker-vc/thinker-cloud-admin-front:test-1.0.0
tags:
- node-build-mac
only:
- test
docker-compose-down-and-up:test:
stage: deploy
tags:
- thinker-cloud-test
script:
- cat /etc/hosts
- echo ">>>>docker-compose down and up"
- cd /data/thinker-devops-cloud/frontend
- docker-compose pull admin-web
- docker-compose up -d admin-web
- docker system prune -f
- echo ">>>>done"
variables:
GIT_STRATEGY: clone
GIT_CHECKOUT: 'false'
cache: {}
only:
- test
## -- master -- #########################################################################################
build-node:master:
image: node:12.13.0
stage: build
variables:
API_ADDR: 'https://api.devops.thinkervc.com'
before_script:
- npm config set registry=http://registry.npm.taobao.org
- npm config set puppeteer_download_host=https://storage.googleapis.com.cnpmjs.org
- yarn config set ignore-engines true
- export APP_ENV_OS=production
script:
- yarn
- yarn run build
only:
- master
tags:
- node-build-mac
docker-push:master:
image: docker:20.10.16
stage: push
before_script:
- docker login -u ${docker_username} -p ${docker_password} registry.cn-shenzhen.aliyuncs.com
script:
- ls -al dist
- docker build -t registry.cn-shenzhen.aliyuncs.com/thinker-vc/thinker-cloud-admin-front:1.0.0 .
- docker push registry.cn-shenzhen.aliyuncs.com/thinker-vc/thinker-cloud-admin-front:1.0.0
after_script:
- docker rmi registry.cn-shenzhen.aliyuncs.com/thinker-vc/thinker-cloud-admin-front:1.0.0
- rm -rf dist/*
tags:
- node-build-mac
only:
- master
docker-compose-down-and-up:master:
stage: deploy
tags:
- thinker-cloud-app
script:
- cat /etc/hosts
- echo ">>>>docker-compose down and up"
- cd /data/thinker-devops-cloud/frontend
- docker-compose pull admin-web
- docker-compose up -d admin-web
- docker system prune -f
- echo ">>>>done"
variables:
GIT_STRATEGY: clone
GIT_CHECKOUT: 'false'
cache: {}
only:
- master
# nginx for frontend
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
gzip on;
server {
listen 80;
server_name localhost;
#charset koi8-r;
access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
location /nginx-health {
access_log off;
return 200 "healthy\n";
}
# error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
#include /etc/nginx/conf.d/*.conf;
}
......@@ -8,44 +8,52 @@ onLaunch(() => {
const Authorization = uni.getStorageSync('Authorization');
console.log(`33333333333333333`, Authorization)
if(Authorization) {
router.clear('/service/home')
uni.reLaunch({
url: 'pages/service/home/index'
})
console.log(`33333333333333344444333`, Authorization)
} else {
uni.reLaunch({
url: '/login'
})
url: 'pages/login/index'
});
}
})
onShow(() => {
const Authorization = uni.getStorageSync('Authorization');
if(Authorization) {
router.clear('/service/home')
} else {
uni.reLaunch({
url: '/login'
url: 'pages/service/home/index'
})
} else {
uni.reLaunch({
url: 'pages/login/index'
});
}
clog.info('App Show')
})
onHide(() => {
const Authorization = uni.getStorageSync('Authorization');
if(Authorization) {
router.clear('/service/home')
} else {
uni.reLaunch({
url: '/login'
url: 'pages/service/home/index'
})
} else {
uni.reLaunch({
url: 'pages/login/index'
});
}
clog.info('App Hide')
})
onLoad(() => {
const Authorization = uni.getStorageSync('Authorization');
if(Authorization) {
router.clear('/service/home')
} else {
uni.reLaunch({
url: '/login'
url: 'pages/service/home/index'
})
} else {
uni.reLaunch({
url: 'pages/login/index'
});
}
clog.info('App Load')
})
......
......@@ -46,7 +46,9 @@ const handleError = (response) => {
const errorText = response?.data?.message || codeMessage[response.statusCode];
const { statusCode } = response;
if (statusCode === 401) {
router.push('/login');
uni.reLaunch({
url: '/pages/login/index'
});
return false;
}
uni.showToast({
......@@ -77,7 +79,7 @@ http.setConfig((config) => {
http.interceptors.request.use((config) => {
/* 请求之前拦截器。可以使用async await 做异步操作 */
const token = getTokenStorage()
const token = getTokenStorage() || config.header.Authorization;
const inputToken = config.header.Authorization
config.header = {
...config.header,
......
{
"name" : "uniapp-vue3-ts-fast",
"appid" : "",
"name" : "cloud-weixin",
"appid" : "__UNI__425AA34",
"description" : "",
"versionName" : "1.0.0",
"versionCode" : "100",
......@@ -53,9 +53,14 @@
"appid" : "",
"setting" : {
"urlCheck" : false,
"minified" : true
"minified" : false
},
"usingComponents" : true
"usingComponents" : true,
"permission" : {
"scope.userLocation" : {
"desc" : "地图服务"
}
}
},
"mp-alipay" : {
"usingComponents" : true
......@@ -69,5 +74,28 @@
"uniStatistics" : {
"enable" : false
},
"vueVersion" : "3"
"vueVersion" : "3",
"h5" : {
"title" : "新科云",
"router" : {
"mode" : "hash",
"base" : "./"
},
"devServer" : {
"port" : 9080,
"https" : true
},
"optimization" : {
"treeShaking" : {
"enable" : true
}
},
"sdkConfigs" : {
"maps" : {
"qqmap" : {
"key" : "IE4BZ-6VUKU-7AFV4-2M4XL-4BW6J-4TFR7"
}
}
}
}
}
{
"easycom": {
"autoscan": true,
"custom": {
"^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue"
}
},
"pages": [{
"path": "pages/route/index"
}],
"globalStyle": {
"navigationStyle": "custom",
"navigationBarTextStyle": "black"
}
}
\ No newline at end of file
"easycom": {
"autoscan": true,
"custom": {
"^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue"
}
},
"pages": [{
"path": "pages/service/home/index"
},
{
"path": "pages/service/monitor/index"
},
{
"path": "pages/service/workplace/index"
},
{
"path": "pages/service/info/index"
},
{
"path": "pages/service/my/index"
},
{
"path": "pages/login/index"
}
],
"tabBar": {
"color": "#A0A0A0",
"selectedColor": "#007bff",
"borderStyle": "black",
"backgroundColor": "#ffffff",
"height": "60px",
"list": [{
"pagePath": "pages/service/home/index",
"iconPath": "/static/tabIcon/home.png",
"selectedIconPath": "/static/tabIcon/home_act.png",
"text": "首页"
},
{
"pagePath": "pages/service/monitor/index",
"iconPath": "/static/tabIcon/monitor.png",
"selectedIconPath": "/static/tabIcon/monitor_act.png",
"text": "监控"
},
{
"pagePath": "pages/service/workplace/index",
"iconPath": "/static/tabIcon/workplace.png",
"selectedIconPath": "/static/tabIcon/workplace_act.png",
"text": "工作台"
},
{
"pagePath": "pages/service/info/index",
"iconPath": "/static/tabIcon/info.png",
"selectedIconPath": "/static/tabIcon/info_act.png",
"text": "消息"
},
{
"pagePath": "pages/service/my/index",
"iconPath": "/static/tabIcon/my.png",
"selectedIconPath": "/static/tabIcon/my_act.png",
"text": "我的"
}
]
},
"globalStyle": {
"navigationStyle": "custom",
"navigationBarTextStyle": "black"
}
}
......@@ -16,7 +16,9 @@
import router from '@/router';
import ctimer from '@/utils/ctimer';
ctimer.add(() => {
router.clear('/login')
uni.reLaunch({
url: 'pages/login/index'
});
}, 1500)
</script>
......
......@@ -91,8 +91,11 @@
uni.showToast({
title: "登录成功!",
mask: true,
duration: 2500,
success: () => {
router.push('/service/home')
uni.switchTab({
url: '/pages/service/home/index'
})
}
})
}
......@@ -122,11 +125,13 @@
onBeforeMount(() => {
const Authorization = uni.getStorageSync('Authorization');
if(Authorization) {
router.clear('/service/home')
uni.redirectTo({
url: '/pages/service/home/index'
});
} else {
uni.reLaunch({
url: '/login'
})
url: '/pages/login/index'
});
}
})
</script>
......
......@@ -21,7 +21,7 @@
</div>
</div>
</div>
<global-bottom :show="router?.item?.item?.showTabs"></global-bottom>
<!-- <global-bottom :show="router?.item?.item?.showTabs"></global-bottom> -->
<log v-if="conf.debug" />
<mask v-if="conf.mask" />
<!-- <fps :show="conf.fps" /> -->
......@@ -113,7 +113,9 @@ onMounted(() => {
})
//第一个页面
router.clear('/login')
uni.reLaunch({
url: 'pages/login/index'
});
// router.clear('/load')
})
......
<template>
<cover-view>
<cover-view>11111111111</cover-view>
</cover-view>
</template>
<script setup lang="ts">
</script>
<style lang="scss" scoped>
// @import 'index.scss'
</style>
.home_com_content {
position: relative;
width: 100%;
height: 100%;
.location_btn {
background-color: #fff;
width: 30px;
height: 30px;
border-radius: 5px;
position: absolute;
bottom: 100px;
right: 16px;
.location_button {
width: 100%;
height: 100%;
background-image: url("/static/image/location.png");
background-size: 23px 23px;
background-position: center center;
background-repeat: no-repeat;
}
}
.com_search {
padding: 0 12px 0px;
padding: 16px 18px 0px;
width: 100%;
box-sizing: border-box;
margin-top: 12px;
position: relative;
.search_input {
flex: 1;
......@@ -20,6 +38,7 @@
border-radius: 3px;
}
.collection_content {
margin-bottom: 12px;
image {
width: 19px;
height: 19px;
......@@ -28,8 +47,7 @@
}
.com_project {
text-align: right;
position: absolute;
right: 12px;
right: 16px;
top: 42px;
image {
width: 19px;
......@@ -39,10 +57,13 @@
}
.device_card {
position: fixed;
bottom: 82px;
bottom: 16px;
/*#ifdef H5*/
bottom: 76px;
/*#endif*/
left: 0px;
width: 100%;
padding: 0px 12px;
padding: 0px 16px;
box-sizing: border-box;
.card_content_line {
height: 3px;
......@@ -67,12 +88,17 @@
color: #323232;
}
.title {
image {
width: 14px;
height: 14px;
margin-top: 5px;
.title_img {
width: 16px;
height: 16px;
::v-deep img {
width: 16px;
height: 16px;
}
}
.title_card {
margin-left: 5px;
margin-left: 4px;
}
}
}
......
<template>
<div class="home_com_content" :style="{width: '100%', height: 'calc(100% - 114px)'}">
<div class="home_com_content">
<!-- :latitude="latitude" :longitude="longitude" :markers="covers" -->
<!-- <map style="width: 100%; height: 100%;">
<cover-view style="width: 100%;">
<cover-view style="display: flex;justify-content: space-between;align-items: center;padding: 16px 16px 0px;width: 100%;">
<u--input class="search_input" customStyle="background-color: #fff; height: 16px;flex: 1" v-model="conf.searchValue" placeholder="请输入账号" clearable />
<div>
<img src="/static/image/collection.png" style="width: 19px;" />
</div>
<map style="width: 100%; height: 100%;" id="home-map" :latitude="conf.position.latitude"
:longitude="conf.position.longitude" :markers="conf.markers" @markertap="markerChange" @click="mapChange"
:customCallout="callout">
<cover-view class="location_btn">
<cover-view class="location_button" @click="locationAction"></cover-view>
</cover-view>
<cover-view class="com_search pos_aline_start">
<u-input class="search_input" customStyle="background-color: #fff; height: 16px;flex: 1"
v-model="conf.searchValue" placeholder="请输入搜索内容" clearable>
<template #prefix>
<u-icon name="scan" size="21" @click="scanAction" />
</template>
</u-input>
<cover-view class="pos_start_column">
<cover-view class="collection_content">
<u-badge :value="conf.collectValue" max="99" bgColor="#FFA200" :absolute="true"
:offset="[10, conf.collectValue > 9 ? 1 : 8]" />
<cover-image src="/static/image/collection.png" />
</cover-view>
<cover-view class="com_project">
<u-badge :value="conf.projectValue" max="99" bgColor="#0052D9" :absolute="true"
:offset="[50, conf.projectValue > 9 ? 1 : 8]" />
<cover-image src="/static/image/project_icon.png" />
</cover-view>
</cover-view>
</cover-view>
</map> -->
<div class="com_search pos_btw">
<u--input class="search_input" customStyle="background-color: #fff; height: 16px;flex: 1"
v-model="conf.searchValue" placeholder="请输入搜索内容" clearable prefixIcon="scan" />
<div class="collection_content">
<image src="/static/image/collection.png" />
</div>
<div class="com_project">
<image src="/static/image/project_icon.png" />
</div>
</div>
<u-row class="device_card" gutter="12" align="bottom">
<u-col span="4" v-for="item in conf.totalList" :data-id="item.id" @touchstart="touchstart" :key="item.id"
@touchend="touchend" @click="() => cardChange(item.id)">
<div>
<div class="card_content_line"
:style="{backgroundColor: conf.cardCurrent === item.id ? '#0052D9' : 'transparent'}" />
<div @click="() => totalChange(item.list[0].id)">
<div :class="`card_content_body ${conf.current === item.list[0].id ? 'active' : ''}`">
<div class="value">{{item.list[0].value}}</div>
<div class=".pos_start title">
<image
:src="`/static/image/${conf.show && `${item.list[0].icon?.split('_')?.[0] || ''}_all` || conf.current === item.list[0].id ? `${item.list[0].icon}-active` : item.list[0].icon}.png`" />
<div class="title_card">{{item.list[0].label}}</div>
<cover-view>
<u-row class="device_card" gutter="10" align="bottom">
<u-col span="4" v-for="item in conf.totalList" :data-id="item.id" @touchstart="touchstart"
:key="item.id" @touchend="touchend" @click="() => cardChange(item.id)">
<div>
<div class="card_content_line"
:style="{backgroundColor: conf.cardCurrent === item.id ? '#0052D9' : 'transparent'}" />
<div @click="() => totalChange(item.list[0].id)">
<div :class="`card_content_body ${conf.current === item.list[0].id ? 'active' : ''}`">
<div class="value">{{item.list[0].value}}</div>
<div class="pos_start title">
<cover-image class="title_img" v-if="conf.show"
:src="`/static/image/${conf.current === item.list[0].id ? `${item.list[0].icon?.split('_')?.[0] || ''}-active.png`: (conf.cardCurrent === item.id && `${item.list[0].icon?.split('_')?.[0] || ''}_all.png` || `${item.list[0].icon}.png`)}`" />
<cover-image class="title_img" v-else
:src="`/static/image/${conf.cardCurrent === item.id ? `${item.list[0].icon?.split('_')?.[0] || ''}-active.png` : `${item.list[0].icon}.png`}`" />
<div class="title_card">{{item.list[0].label}}</div>
</div>
</div>
</div>
</div>
</div>
<div v-for="(child, index) in item.list?.filter(ele => ele?.id !== item.list[0].id)" :key="item.id"
@click="() => totalChange(child.id)" v-if="conf.show && conf.cardCurrent === item?.id"
:style="{transition: '2s', height: conf.show && conf.cardCurrent === item?.id ? 'auto' : 0}">
<div :class="`card_content_body ${conf.current === child.id ? 'active' : ''}`">
<div class="value">{{child.value}}</div>
<div class=".pos_start title">
<image
:src="`/static/image/${conf.show && `${child.icon?.split('_')?.[0] || ''}_all` || conf.current === child.id ? `${child.icon}-active` : child.icon}.png`" />
<div class="title_card">{{child.label}}</div>
<div v-for="(child, index) in item.list?.filter(ele => ele?.id !== item.list[0].id)"
:key="item.id" @click="() => totalChange(child.id)"
v-if="conf.show && conf.cardCurrent === item?.id"
:style="{transition: '2s', height: conf.show && conf.cardCurrent === item?.id ? 'auto' : 0}">
<div :class="`card_content_body ${conf.current === child.id ? 'active' : ''}`">
<div class="value">{{child.value}}</div>
<div class="pos_start title">
<cover-image class="title_img"
:src="`/static/image/${conf.current === child.id ? `${child.icon?.split('_')?.[0]}-active` : child.icon}.png`" />
<div class="title_card">{{child.label}}</div>
</div>
</div>
</div>
</div>
</div>
</div>
</u-col>
</u-row>
</u-col>
</u-row>
</cover-view>
<cover-view slot="callout">
<block v-for="(item,index) in markers" :key="index">
<cover-view class="customCallout" :marker-id="item.id" style="padding: 10px;background-color: red;">
<cover-view class="content">
{{item.id}}
<cover-view class="equipment-status" :class="item.id ? 'red': ''">在线</cover-view>
</cover-view>
</cover-view>
</block>
</cover-view>
<!-- <device-info-modal v-if="conf.selectedId" /> -->
</map>
</div>
</template>
<script setup lang="ts">
import {
reactive,
watch,
computed,
getCurrentInstance
} from 'vue';
import {
debounce
} from '@/utils';
import DeviceInfoModal from './components/DeviceInfoModal.vue'
const internalInstance = getCurrentInstance();
const conf = reactive({
searchValue: '',
cardCurrent: 'gateway',
current: 'gateway_total',
show: false,
touchData: {},
codeUrl: '',
selectedId: '',
selectedShow: false,
position: {
latitude: 39.909, // 默认定在首都
longitude: 116.39742,
},
markers: [{
id: 1,
latitude: 39.909,
longitude: 116.39742,
iconPath: '/static/image/device_map_normal.png',
width: 26,
height: 30,
title: '天安门',
customCallout: {
anchorY: 0,
anchorX: 0,
display: "ALWAYS"
},
},
{
id: 2,
latitude: 39.90,
longitude: 116.39,
iconPath: '/static/image/gateway_map_normal.png',
width: 26,
height: 30,
title: '天2安门',
customCallout: {
anchorY: 0,
anchorX: 0,
display: "ALWAYS"
},
}
] as any[],
collectValue: 12, // 收藏数量
projectValue: 15, // 项目数量
controls: [{
//在地图上显示控件,控件不随着地图移动
id: 1, //控件id
iconPath: "/static/image/location.png", //显示的图标
clickable: true,
position: {
//控件在地图的位置
top: 390,
left: 330,
width: 23,
height: 23,
},
}, ],
totalList: [{
id: 'gateway',
list: [{
......@@ -147,9 +226,9 @@
},
{
label: '待处理',
id: 'alarm_nodeal',
id: 'alarm_undeal',
value: 23322,
icon: 'alarm_nodeal'
icon: 'alarm_undeal'
},
{
label: '已转工单',
......@@ -195,7 +274,63 @@
if (subX > -50) {
console.log('左滑')
}
console.log(e, `************`, conf.show)
console.log(e, `************`, conf)
}
// 定位
const locationAction = () => {
console.log(`)))))))))`)
uni.createMapContext("home-map", internalInstance).moveToLocation({
longitude: conf.position.longitude,
latitude: conf.position.latitude,
});
}
// 扫描
const scanFail = () => {
uni.showToast({
title: '扫描失败!',
icon: 'error'
})
}
const chooseImage = () => {
uni.scanCode({
success: (result) => {
if (result.result) {
}
console.log(result, `*********`);
},
fail: scanFail
})
}
const scanAction = () => {
/*#ifdef APP-PLUS*/
chooseImage()
console.log('APP端')
/*#endif*/
/*#ifdef H5*/
chooseImage()
console.log('H5端')
/*#endif*/
/*#ifdef MP*/
chooseImage()
console.log('微信小程序端')
/*#endif*/
}
// 地图点击事件
const mapChange = (e) => {
e?.preventDefault?.()
console.log(`点击了地图`, e)
conf.selectedId = '';
}
// 地图标记点点击
const markerChange = (e: any) => {
e?.preventDefault?.()
const {
markerId
} = e.detail;
conf.selectedId = markerId;
console.log(markerId, `^^^^&&&&&&`)
return false;
}
</script>
......
<template>
<div :style="{marginTop: `${store.system.statusBarHeight + 44}px`}">
<ul>
<li>{{conf.userInfo.name || ''}}</li>
<li>{{conf.userInfo.id || ''}}</li>
</ul>
00000000
</div>
</template>
<script setup lang="ts">
import store from '@/store';
import JSBridge from '@/utils/JSBridge'
import {
http
} from '@/api/service.js'
import {
reactive,
getCurrentInstance,
onMounted,
watch,
watchEffect
} from 'vue';
// 1、创建JSBridge对象
/*#ifdef H5*/
const jsBridge = new JSBridge();
/*#endif*/
const conf = reactive({
userInfo: 0,
searchValue: '',
tab: 0,
ele: '',
})
onMounted(() => {
const unsubscribe = jsBridge.subscribe('test', async (params) => {
console.info('web收到一条订阅消息:eventName=test, params=', params);
const data = await http.get('/account-service/user/myInfo', {
Authorization: `bearer ${params}`
})
if (data.data) {
const userInfo = data.data || {};
conf.userInfo = userInfo;
}
console.log(data.data || {})
});
})
</script>
<style scoped lang="scss">
</style>
......@@ -2,6 +2,7 @@
.title {
&-bar {
width: 100vw;
background-color: #fff;
}
&-box {
......@@ -42,4 +43,33 @@
height: 50rpx;
}
}
.tab_card {
height: 50px;
background-color: #fff;
// position: relative;
.more_tab_card {
// position: absolute;
// top: 0px;
// right: 0px;
padding: 12px;
background-color: #fff;
box-shadow: -5px 0px 3px #ececec;
image {
width: 21px;
height: 22px;
}
.u-tabs__wrapper__nav {
/* #ifdef MP-WEIXIN */
position: relative;
/* #endif */
}
}
}
.com_home {
height: calc(100% - 114px);
/* #ifdef H5 */
height: calc(100% - 94px);
/* #endif */
width: 100%;
}
}
\ No newline at end of file
......@@ -9,10 +9,42 @@
<div class="title-right"></div>
</div>
</div>
<u-sticky bgColor="#fff">
<u-tabs :current="conf.tab" lineColor="#0052D9" lineWidth="106" :list="conf.tabList" @change="tabChange" itemStyle="padding: 15px 23px;" />
</u-sticky>
<com-home v-if="conf.tab === 0" />
<div class="pos_start tab_card">
<u-tabs :current="conf.tab" lineColor="#0052D9" lineWidth="106" :list="conf.tabList" @change="tabChange"
itemStyle="padding: 15px 23px;" style="width: 100vw;" keyName="name">
<template #right>
<div class="more_tab_card" v-if="conf.tabList?.length > 5" @click="moreTabAction">
<image src="/static/image/more_tab.png" />
</div>
</template>
</u-tabs>
</div>
<!-- <div styleName="container">
<div styleName="add-button">
<Button
type="primary"
onClick={() => {
// 4、发布订阅消息:“test”。native端订阅test消息,请参考上面原生端代码
jsBridge.publisher('test', { data: '这是H5端发布消息' });
}}
>
发布消息
</Button>
</div>
<div styleName="delete-button">
<Button
type="primary"
onClick={async () => {
// 5、发送请求消息:“/test”,异步接收响应数据。native端注册响应消息,请参考上面原生端代码
const res = await jsBridge.request('/test', { data: '这是H5端请求消息' });
console.info('web收到一条响应消息:eventName=/test, res=', res.data);
}}
>
请求消息
</Button>
</div>
</div> -->
<com-home v-if="conf.tab === 0" class="com_home" />
</div>
</template>
......@@ -21,11 +53,13 @@
import store from '@/store';
import {
reactive,
getCurrentInstance
getCurrentInstance,
onMounted,
watch,
watchEffect
} from 'vue';
import ComHome from './ComHome/index.vue'
const internalInstance = getCurrentInstance();
const login = internalInstance.appContext.config.globalProperties.login;
const conf = reactive({
......@@ -42,6 +76,7 @@
},
searchValue: '',
tab: 0,
ele: '',
tabList: [{
name: '综合首页',
value: 1
......@@ -49,13 +84,38 @@
name: '能源管理',
value: 2
}, {
name: '智慧教室',
name: '智慧教2室',
value: 3
}, {
name: '智慧3教室',
value: 4
}, {
name: '智慧4教室',
value: 5
}, {
name: '智慧5教室',
value: 6
}]
})
router.item.item.title = store.user.proinfo.name
// router.item.item.title = store.user.proinfo.name;
watchEffect(() => {
if (conf.ele) {
const ele = document.querySelector('.u-tabs__wrapper__scroll-view');
ele?.setAttribute('scroll-left', 0)
console.log(`***222*****`, conf.ele)
}
}, [conf.ele])
onMounted(() => {
const ele = document?.querySelector('.u-tabs__wrapper__scroll-view');
const attr = ele?.getAttribute('scroll-left')
conf.ele = attr;
ele?.setAttribute('scroll-left', 0);
console.log(ele, `********`, attr);
})
const tabChange = (e) => {
conf.tab = e?.index
console.log(e, `###########`)
......@@ -70,6 +130,12 @@
console.log(`11111111111111111`, login)
conf.color = 'green'
}
// 更多
const moreTabAction = () => {
uni.navigateTo({
url: '/pages/service/home/project/index'
})
}
</script>
<style lang="scss" scoped>
......
<template>
<div>99999</div>
</template>
<script>
</script>
<style>
</style>
\ No newline at end of file
<template>
<div>99999</div>
</template>
<script>
</script>
<style>
</style>
\ No newline at end of file
<template>
<div>99999</div>
</template>
<script>
</script>
<style>
</style>
\ No newline at end of file
<template>
<div class="absolute fit column">
<uni-swiper-dot :info="conf.info" :current="conf.current" field="content" :mode="conf.mode"
:dots-styles="conf.dotsStyles" style="margin-bottom:10rpx;">
<swiper class="swiper-box" @change="change" autoplay circular style="height:400rpx">
<swiper-item>
<img class="fit" src="@/static/image/pro.png" />
</swiper-item>
<swiper-item>
<view class="fit flex flex-center">
B
</view>
</swiper-item>
<swiper-item>
<view class="fit flex flex-center">
C
</view>
</swiper-item>
</swiper>
</uni-swiper-dot>
<div class="col scroll-y">
<div class="row" style="gap:30rpx;padding: 30rpx;">
<div class="val-item column flex-center no-wrap" v-for="l in 5" :key="l">
<div class="val-item-text1">0.00</div>
<div class="val-item-text2">KW</div>
<div class="val-item-text3">运动距离</div>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import router from '@/router';
import store from '@/store';
import { reactive } from 'vue';
const conf = reactive({
info: [1, 1, 1],
current: 0,
mode: 'round',
dotsStyles: {
backgroundColor: 'rgba(66,66,66,0.1)',
border: '1px rgba(66,66,66,0) solid',
color: '#fff',
selectedBackgroundColor: 'rgba(66,66,66,0.4)',
selectedBorder: '1px rgba(66,66,66,0) solid'
}
})
router.item.item.title = store.user.proinfo.name + "-摸鱼"
const change = (e: any) => {
conf.current = e.detail.current;
}
</script>
<style lang="scss">
.val-item {
width: 210rpx;
height: 156rpx;
border-radius: 20rpx;
background: rgba(0, 0, 0, 0.03);
&-text1 {
font-size: 44rpx;
line-height: 44rpx;
color: #3EB958;
}
&-text2 {
font-size: 20rpx;
margin: 10rpx 0rpx 5rpx 0rpx;
color: rgba(66, 66, 66, 0.5);
}
&-text3 {
font-size: 22rpx;
color: rgba(66, 66, 66, 0.6);
}
}
</style>
<template>
<div>99999</div>
</template>
<script>
</script>
<style>
</style>
\ No newline at end of file
<template>
<div>111111111</div>
</template>
<script>
</script>
<style>
</style>
\ No newline at end of file
......@@ -3,11 +3,12 @@
<!-- <load v-else-if="show('/load')" /> -->
<login v-else-if="show('/login')" />
<prolist v-else-if="show('/prolist')" />
<shome v-else-if="show('/service/home')" />
<sp1 v-else-if="show('/service/p1')" />
<!-- <sp1 v-else-if="show('/service/p1')" /> -->
<sp2 v-else-if="show('/service/p2')" />
<sp3 v-else-if="show('/service/p3')" />
<project-list v-else-if="show('/home/project')" />
</template>
......@@ -17,9 +18,10 @@ import error from '@/pages/error/index.vue';
import login from '@/pages/login/index.vue';
import prolist from '@/pages/prolist/index.vue';
import shome from '@/pages/service/home/index.vue';
import sp1 from '@/pages/service/p1/index.vue';
// import sp1 from '@/pages/service/p1/index.vue';
import sp2 from '@/pages/service/p2/index.vue';
import sp3 from '@/pages/service/p3/index.vue';
import ProjectList from '@/pages/service/home/ProjectList/index.vue';
const props = defineProps({
pagePath: { default: '' }
......
......@@ -66,6 +66,21 @@ export const routerList = [
name: null as any
},
},
{
pagePath: "/home/project",
param: {
name: null as any
},
showTitle: true,
backShow: true,
titleBackFun: () => {
router.clear('/service/home')
},
titleStyles: {
background: '#ffffff',
color: '#0052D9'
},
},
{
pagePath: "/prolist",
showTitle: true,
......
@import 'light.scss';
@import 'dark.scss';
\ No newline at end of file
@import 'dark.scss';
page {
height: 100vh;
/*#ifdef H5*/
height: 91vh !important;
/*#endif*/
font-size: 14px;
}
\ No newline at end of file
......@@ -79,6 +79,7 @@ $uni-font-size-paragraph:30rpx;
page {
box-sizing: border-box;
font-size: 14px;
}
.primary-color {
color: var(--primary);
......
import { v1 as uuid } from 'uuid';
export type SubscribeCallback = (params?: any) => void;
const MESSAGE_TYPE_REQUEST = 'request';
const MESSAGE_TYPE_PUBLISHER = 'publisher';
const NATIVE_CHANNEL = 'nativeChannel'; // 原生通信通道名称
const JAVASCRIPT_CHANNEL = 'javascriptChannel'; // js通信通道名称
const REQUEST_TIME_OUT = 20000;
interface BridgeMessage {
id: string;
type: string;
eventName: string;
params: any;
}
export default class JSBridge {
private native: any = window[NATIVE_CHANNEL];
private subscribeCallbackMap = {};
private requestCallbackMap = {};
constructor() {
window[JAVASCRIPT_CHANNEL] = (jsonStr) => {
const message = JSON.parse(decodeURIComponent(atob(jsonStr))) as BridgeMessage;
const id = message.id;
const type = message.type;
const eventName = message.eventName;
const params = message.params;
if (type === MESSAGE_TYPE_REQUEST) {
this.requestCallbackMap[id] && this.requestCallbackMap[id](params);
} else if (type === MESSAGE_TYPE_PUBLISHER) {
const callbacks = this.subscribeCallbackMap[eventName];
if (callbacks) {
callbacks.forEach((callback) => callback(params));
}
}
};
}
// 请求响应
request = (eventName: string, params: any, timeout = REQUEST_TIME_OUT): Promise<any> => {
return new Promise((resolve: any) => {
const id: string = uuid();
let timer;
this.requestCallbackMap[id] = (params) => {
clearTimeout(timer);
delete this.requestCallbackMap[id];
resolve(params);
};
timer = setTimeout(() => {
// code == -1表示响应超时
this.requestCallbackMap[id] && this.requestCallbackMap[id](JSON.stringify({ code: -1, data: '访问超时' }));
}, timeout);
this.native &&
this.native.postMessage(JSON.stringify({ type: 'request', id: id, eventName: eventName, params: params }));
});
};
// 发布
publisher = (eventName: string, params: any): void => {
this.native && this.native.postMessage(JSON.stringify({ type: 'publisher', eventName: eventName, params: params }));
};
// 订阅
subscribe = (eventName: string, callback: SubscribeCallback): SubscribeCallback => {
if (!this.subscribeCallbackMap[eventName]) {
this.subscribeCallbackMap[eventName] = [];
}
this.subscribeCallbackMap[eventName].push(callback);
return () => this.unsubscribe(eventName, callback);
};
// 取消订阅
unsubscribe = (eventName: string, callback: SubscribeCallback): void => {
const callbacks = this.subscribeCallbackMap[eventName];
if (callbacks) {
callbacks.forEach((item, index) => {
if (item === callback) {
callbacks.splice(index, 1);
}
});
}
};
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment