diff --git a/package.json b/package.json
index d08a4c0..1b16c95 100644
--- a/package.json
+++ b/package.json
@@ -53,7 +53,9 @@
"@tarojs/runtime": "3.6.23",
"@tarojs/shared": "3.6.23",
"@tarojs/taro": "3.6.23",
+ "axios": "^1.6.8",
"clsx": "^2.1.0",
+ "qs": "^6.12.0",
"react": "^18.0.0",
"react-dom": "^18.0.0"
},
diff --git a/project.config.json b/project.config.json
index 3d09de5..8457eb6 100644
--- a/project.config.json
+++ b/project.config.json
@@ -14,7 +14,8 @@
"ignore": [],
"disablePlugins": [],
"outputPath": ""
- }
+ },
+ "packNpmRelationList": []
},
"compileType": "miniprogram",
"libVersion": "2.30.3",
diff --git a/src/app.config.ts b/src/app.config.ts
index 783aba6..6590522 100644
--- a/src/app.config.ts
+++ b/src/app.config.ts
@@ -2,6 +2,7 @@ export default defineAppConfig({
pages: [
// 首页y以及首页tab页内容
'pages/index/index', // 首页
+ 'pages/login/index', // 登录页
// 被其他页面引用的组件不要写在这里
// 'pages/iot/index', // 物联网
@@ -9,12 +10,14 @@ export default defineAppConfig({
// 'pages/equipment/index', // 巡检设备
// 跳转页面
+ 'pages/weatherStation/index', // 气象站
'pages/msgDetail/index', // 消息详情
],
window: {
backgroundTextStyle: 'light',
navigationBarBackgroundColor: '#0fc87c',
navigationBarTitleText: 'WeChat',
- navigationBarTextStyle: 'white'
+ navigationBarTextStyle: 'white',
+ navigationStyle: 'custom'
}
})
diff --git a/src/assets/images/bg.png b/src/assets/images/bg.png
new file mode 100644
index 0000000..f84a390
Binary files /dev/null and b/src/assets/images/bg.png differ
diff --git a/src/assets/images/icons/back.png b/src/assets/images/icons/back.png
new file mode 100644
index 0000000..d127668
Binary files /dev/null and b/src/assets/images/icons/back.png differ
diff --git a/src/assets/images/icons/data/icon1.png b/src/assets/images/icons/data/icon1.png
new file mode 100644
index 0000000..8c6eacb
Binary files /dev/null and b/src/assets/images/icons/data/icon1.png differ
diff --git a/src/assets/images/icons/data/icon2.png b/src/assets/images/icons/data/icon2.png
new file mode 100644
index 0000000..dfd3a9b
Binary files /dev/null and b/src/assets/images/icons/data/icon2.png differ
diff --git a/src/assets/images/icons/data/icon3.png b/src/assets/images/icons/data/icon3.png
new file mode 100644
index 0000000..a4a86f2
Binary files /dev/null and b/src/assets/images/icons/data/icon3.png differ
diff --git a/src/assets/images/icons/data/icon4.png b/src/assets/images/icons/data/icon4.png
new file mode 100644
index 0000000..85af9e2
Binary files /dev/null and b/src/assets/images/icons/data/icon4.png differ
diff --git a/src/assets/images/icons/data/icon5.png b/src/assets/images/icons/data/icon5.png
new file mode 100644
index 0000000..764d58d
Binary files /dev/null and b/src/assets/images/icons/data/icon5.png differ
diff --git a/src/assets/images/icons/data/icon6.png b/src/assets/images/icons/data/icon6.png
new file mode 100644
index 0000000..d90f79e
Binary files /dev/null and b/src/assets/images/icons/data/icon6.png differ
diff --git a/src/assets/images/icons/data/index.ts b/src/assets/images/icons/data/index.ts
new file mode 100644
index 0000000..50271c3
--- /dev/null
+++ b/src/assets/images/icons/data/index.ts
@@ -0,0 +1,6 @@
+export {default as icon1} from './icon1.png';
+export {default as icon2} from './icon2.png';
+export {default as icon3} from './icon3.png';
+export {default as icon4} from './icon4.png';
+export {default as icon5} from './icon5.png';
+export {default as icon6} from './icon6.png';
\ No newline at end of file
diff --git a/src/assets/images/icons/question-line.png b/src/assets/images/icons/question-line.png
new file mode 100644
index 0000000..d2d4956
Binary files /dev/null and b/src/assets/images/icons/question-line.png differ
diff --git a/src/assets/images/loginBg.png b/src/assets/images/loginBg.png
new file mode 100644
index 0000000..829ddd6
Binary files /dev/null and b/src/assets/images/loginBg.png differ
diff --git a/src/assets/images/tab/tab1.png b/src/assets/images/tab/tab1.png
index b7b003a..a0f2140 100644
Binary files a/src/assets/images/tab/tab1.png and b/src/assets/images/tab/tab1.png differ
diff --git a/src/assets/images/tab/tab1_selected.png b/src/assets/images/tab/tab1_selected.png
index 0152caf..6d04fb3 100644
Binary files a/src/assets/images/tab/tab1_selected.png and b/src/assets/images/tab/tab1_selected.png differ
diff --git a/src/assets/images/tab/tab2.png b/src/assets/images/tab/tab2.png
index 06f1ab8..76d194c 100644
Binary files a/src/assets/images/tab/tab2.png and b/src/assets/images/tab/tab2.png differ
diff --git a/src/assets/images/tab/tab3.png b/src/assets/images/tab/tab3.png
index 89f0e3f..052ee78 100644
Binary files a/src/assets/images/tab/tab3.png and b/src/assets/images/tab/tab3.png differ
diff --git a/src/assets/images/tab/tab3_selected.png b/src/assets/images/tab/tab3_selected.png
index 2911018..274a42c 100644
Binary files a/src/assets/images/tab/tab3_selected.png and b/src/assets/images/tab/tab3_selected.png differ
diff --git a/src/components/customized/navigation/index.tsx b/src/components/customized/navigation/index.tsx
new file mode 100644
index 0000000..69399fe
--- /dev/null
+++ b/src/components/customized/navigation/index.tsx
@@ -0,0 +1,20 @@
+import { Image, View } from "@tarojs/components"
+import Taro from "@tarojs/taro";
+import arrow from '../../../assets/images/icons/back.png'
+
+const HeaderNation = ({ title = '' }) => {
+ const showBack = Taro.getCurrentPages().length > 1
+ return (
+
+ {
+ Taro.navigateBack()
+ }}>
+ { showBack ? : null }
+
+ { title }
+
+
+ )
+}
+
+export default HeaderNation;
\ No newline at end of file
diff --git a/src/config/axios/errorCode.ts b/src/config/axios/errorCode.ts
new file mode 100644
index 0000000..94d719f
--- /dev/null
+++ b/src/config/axios/errorCode.ts
@@ -0,0 +1,6 @@
+export default {
+ '401': '认证失败,无法访问系统资源',
+ '403': '当前操作没有权限',
+ '404': '访问资源不存在',
+ default: '系统未知错误,请反馈给管理员'
+}
diff --git a/src/config/axios/index.ts b/src/config/axios/index.ts
new file mode 100644
index 0000000..e69de29
diff --git a/src/config/axios/service.ts b/src/config/axios/service.ts
new file mode 100644
index 0000000..50f3baf
--- /dev/null
+++ b/src/config/axios/service.ts
@@ -0,0 +1,109 @@
+import axios, { AxiosError, AxiosInstance, AxiosRequestHeaders, AxiosResponse, InternalAxiosRequestConfig } from "axios";
+import { axiosConfig } from "..";
+import Taro from "@tarojs/taro";
+import qs from 'qs'
+import errorCode from './errorCode'
+
+// 请求白名单,无须token的接口
+const whiteList: string[] = ['/login', '/refresh-token']
+
+// 是否正在刷新中
+let isRefreshToken = false
+// 请求队列
+let requestList: any[] = []
+
+// 创建实例
+const service: AxiosInstance = axios.create({
+ baseURL: axiosConfig.baseUrl,
+ timeout: axiosConfig.timeout,
+ withCredentials: axiosConfig.withCredentials
+});
+
+const getAccessToken = () => {
+ return Taro.getStorageSync('token')
+}
+
+// request拦截器
+service.interceptors.request.use((config: InternalAxiosRequestConfig) => {
+ // 是否需要设置 token
+ let isToken = (config!.headers || {}).isToken === false
+ whiteList.some((v) => {
+ if (config.url) {
+ config.url.indexOf(v) > -1
+ return (isToken = false)
+ }
+ })
+ if (getAccessToken() && !isToken) {
+ ; (config as any).headers.Authorization = 'Bearer ' + getAccessToken() // 让每个请求携带自定义token
+ }
+ const params = config.params || {}
+ const data = config.data || false
+
+ if (
+ config.method?.toUpperCase() === 'POST' &&
+ (config.headers as AxiosRequestHeaders)['Content-Type'] ===
+ 'application/x-www-form-urlencoded'
+ ) { config.data = qs.stringify(data) }
+
+ // get参数编码
+ if (config.method?.toUpperCase() === 'GET' && params) {
+ config.params = {}
+ const paramsStr = qs.stringify(params, { allowDots: true })
+ if (paramsStr) {
+ config.url = config.url + '?' + paramsStr
+ }
+ }
+
+ return config
+}, (error: AxiosError) => {
+ Promise.reject(error)
+})
+
+// response 拦截器
+service.interceptors.response.use(
+ async (response: AxiosResponse) => {
+ let { data } = response
+ const config = response.config
+ if (!data) { throw new Error() }
+
+ const code = data.code || 200 // 默认成功
+ // 获取错误信息
+ const msg = data.msg || errorCode[code] || errorCode['default']
+
+ if (code === 401) {
+ // 如果未认证,并且未进行刷新令牌,说明可能是访问令牌过期了
+ // isRefreshToken false 未开始刷新token 进入刷新token程序
+ if (!isRefreshToken) {
+ isRefreshToken = true
+ try {
+ // 使用默认的用户名密码进行登录操作
+ const token = 'request login'
+ Taro.setStorageSync('token', token)
+ config.headers!.Authorization = 'Bearer ' + getAccessToken()
+ requestList.forEach((cb: any) => { cb() })
+ requestList = []
+ return service(config)
+ } catch (e) {
+ // 刷新失败时 处理错误
+ requestList = [] // 清空队列
+ return Promise.reject()
+ } finally {
+ requestList = []
+ isRefreshToken = false
+ }
+ } else {
+ // 正在尝试刷新token,放入等待队列
+ return new Promise((resolve) => {
+ requestList.push(() => {
+ config.headers!.Authorization = 'Bearer ' + getAccessToken() // 让每个请求携带自定义token 请根据实际情况自行修改
+ resolve(service(config))
+ })
+ })
+ }
+ } else if (code === 500) {
+ return Promise.reject(new Error(msg))
+ } else {
+ return data
+ }
+ }
+)
\ No newline at end of file
diff --git a/src/config/index.ts b/src/config/index.ts
new file mode 100644
index 0000000..eaf7a0b
--- /dev/null
+++ b/src/config/index.ts
@@ -0,0 +1,5 @@
+export const axiosConfig = {
+ baseUrl: '',
+ timeout: 30000,
+ withCredentials: false // 禁用 Cookie 等信息
+}
\ No newline at end of file
diff --git a/src/pages/index/index.tsx b/src/pages/index/index.tsx
index b39edc5..3f38f32 100644
--- a/src/pages/index/index.tsx
+++ b/src/pages/index/index.tsx
@@ -2,6 +2,7 @@ import { Image, View } from "@tarojs/components";
import "./index.scss";
import { useState } from "react";
import Iot from "../iot";
+import basicBg from '../../assets/images/bg.png'
import MsgCenter from "../msgCenter";
import EquipMent from "../equipment";
import tab1Icon from '../../assets/images/tab/tab1.png'
@@ -12,10 +13,23 @@ import tab3Icon from '../../assets/images/tab/tab3.png'
import tab3Icon_selected from '../../assets/images/tab/tab3_selected.png'
import Taro from "@tarojs/taro";
+import HeaderNation from "../../components/customized/navigation";
const Index = () => {
const [curSelectedItem, setCurSelectedItem] = useState('iot')
Taro.setNavigationBarTitle({ title: '物联网' })
+
+ // 判断权限,没有权限进入登录页面
+ const handleAuth = () => {
+ const token = Taro.getStorageSync('token')
+ if (token) {
+ // Taro.redirectTo({ url: '/pages/login/index' })
+ } else {
+ Taro.redirectTo({ url: '/pages/login/index' })
+ }
+ }
+ handleAuth()
+
const bottomMenuList = [
{
id: 'iot',
@@ -41,7 +55,10 @@ const Index = () => {
]
return (
-
+
{
bottomMenuList.map(item => {
@@ -79,6 +96,15 @@ const Index = () => {
: null
}
+
);
};
diff --git a/src/pages/iot/index.tsx b/src/pages/iot/index.tsx
index ea1a7c6..b4e1c99 100644
--- a/src/pages/iot/index.tsx
+++ b/src/pages/iot/index.tsx
@@ -4,6 +4,7 @@ import onlineIcon from '../../assets/images/icons/online.png'
import offlineIcon from '../../assets/images/icons/offline.png'
import errorIcon from '../../assets/images/icons/error.png'
import img from '../../assets/images/img.png'
+import Taro from "@tarojs/taro"
const Iot = () => {
const [selectedMenuId, setSelectedMenuId] = useState('all')
@@ -40,24 +41,30 @@ const Iot = () => {
return (
-
+
{
topMenus.map(item => {
return (
setSelectedMenuId(item.id)}
>{ item.title }
)
})
}
-
+
{
dataList.map(item => {
return (
-
+ {
+ Taro.navigateTo({ url: '/pages/weatherStation/index?id=' + item.id })
+ }}
+ >
diff --git a/src/pages/login/index.config.ts b/src/pages/login/index.config.ts
new file mode 100644
index 0000000..38f5101
--- /dev/null
+++ b/src/pages/login/index.config.ts
@@ -0,0 +1,3 @@
+export default definePageConfig({
+ navigationBarTitleText: '登录'
+})
\ No newline at end of file
diff --git a/src/pages/login/index.tsx b/src/pages/login/index.tsx
new file mode 100644
index 0000000..3f5536d
--- /dev/null
+++ b/src/pages/login/index.tsx
@@ -0,0 +1,76 @@
+import { Button, Image, Input, Text, View } from "@tarojs/components"
+import loginBg from '../../assets/images/loginBg.png'
+import questionIcon from '../../assets/images/icons/question-line.png'
+import Taro from "@tarojs/taro"
+import { useState } from "react"
+
+const Login = () => {
+ const [username, setUserName] = useState('')
+ const [password, setPassWord] = useState('')
+ const handleLogin = () => {
+ if (!username || !password) return
+ Taro.setStorageSync('username', username)
+ Taro.setStorageSync('password', password)
+ // 请求完成后跳转
+ Taro.showLoading({ title: '加载中...'})
+ setTimeout(() => {
+ Taro.setStorageSync('token', 'testToken')
+ Taro.hideLoading()
+ Taro.redirectTo({ url: '/pages/index/index' })
+ }, 2000)
+ }
+
+ return (
+
+
+
+
+ 您好,
+
+
+ 欢迎登录
+
+
+
+ 用户名
+
+ setUserName((_username.target as any).value)}
+ >
+
+
+
+ 密码
+
+ setPassWord((_password.target as any).value)}
+ >
+
+
+
+
+
+ 忘记密码?
+
+
+
+
+
+
+
+
+ )
+}
+
+export default Login;
\ No newline at end of file
diff --git a/src/pages/weatherStation/index.config.ts b/src/pages/weatherStation/index.config.ts
new file mode 100644
index 0000000..e6b75f9
--- /dev/null
+++ b/src/pages/weatherStation/index.config.ts
@@ -0,0 +1,3 @@
+export default definePageConfig({
+ navigationBarTitleText: '气象站'
+})
\ No newline at end of file
diff --git a/src/pages/weatherStation/index.tsx b/src/pages/weatherStation/index.tsx
new file mode 100644
index 0000000..ef022b0
--- /dev/null
+++ b/src/pages/weatherStation/index.tsx
@@ -0,0 +1,142 @@
+import { Image, View } from "@tarojs/components"
+import Taro from "@tarojs/taro";
+import { useState } from "react";
+import img from '../../assets/images/img.png'
+import basicBg from '../../assets/images/bg.png'
+import HeaderNation from "../../components/customized/navigation";
+import { icon1, icon2, icon3, icon4 } from "../../assets/images/icons/data";
+
+const SubTitle = ({title = '', updateTime = ''}) => {
+ return (
+
+ { title }
+ { updateTime !== '' ? '数据更新于' + updateTime : '' }
+
+ )
+}
+
+const IconLabelValue = ({ value, unit, label, img }) => {
+ return (
+
+
+
+ { value }
+ { unit }
+
+ { label }
+
+
+
+
+
+ )
+}
+
+const GridContainer = ({ children }) => {
+ return (
+
+ { children }
+
+ )
+}
+
+const BasicStatus = (status = true) => {
+ return (
+ { status ? '在线' : '离线' }
+ )
+}
+
+const BasicInfoCard = ({ title, info, status, imgSrc }) => {
+ return (
+
+
+
+
+
+ { title }
+ { info }
+ { status ? BasicStatus() : '' }
+
+
+ )
+}
+
+const WeatherStation = () => {
+ const baseId = Taro.getCurrentInstance().router?.params.id || 0; // 基地id
+ const [curDeviceId, setCurDeviceId] = useState('1')
+ const deviceList = [
+ {
+ id: '1',
+ title: '设备1'
+ },
+ {
+ id: '2',
+ title: '设备2'
+ },
+ {
+ id: '3',
+ title: '设备3'
+ },
+ ]
+
+ const [data, setData] = useState([
+ { genre: 'Sports', sold: 275 },
+ { genre: 'Strategy', sold: 115 },
+ { genre: 'Action', sold: 120 },
+ { genre: 'Shooter', sold: 350 },
+ { genre: 'Other', sold: 150 },
+ ])
+
+ return (
+
+
+
+
+ {
+ deviceList.map(item => {
+ return (
+ setCurDeviceId(item.id)}
+ >{ item.title }
+ )
+ })
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export default WeatherStation;
\ No newline at end of file
diff --git a/tailwind.config.js b/tailwind.config.js
index e4b02b2..8c0ef2a 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -2,7 +2,10 @@
module.exports = {
content: ["./src/**/*.{html,js,ts,jsx,tsx}"],
theme: {
- extend: {}
+ extend: {},
+ textColor: {
+ 'primary': '#0fc87c'
+ }
},
plugins: [],
// v3 版本的 tailwindcss 有些不同