登陆根据token区分身份
This commit is contained in:
parent
d04483f899
commit
ee96a2b2f5
106
App.vue
106
App.vue
|
@ -2,7 +2,7 @@
|
||||||
// #ifdef APP-PLUS
|
// #ifdef APP-PLUS
|
||||||
import appUpdate from "@/components/appUpdate/appUpdate.js";
|
import appUpdate from "@/components/appUpdate/appUpdate.js";
|
||||||
// #endif
|
// #endif
|
||||||
|
import { jwtDecode } from "jwt-decode";
|
||||||
export default {
|
export default {
|
||||||
onLaunch: function () {
|
onLaunch: function () {
|
||||||
console.log("%c%s", "color:red", "onLaunch---");
|
console.log("%c%s", "color:red", "onLaunch---");
|
||||||
|
@ -76,37 +76,79 @@ export default {
|
||||||
// "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9zaWQiOiIwOGRkNzFiZC01N2MxLTQ1YmMtODBiYS0xMjkzYjU4MTViMmEiLCJ1bmlxdWVfbmFtZSI6IuS_nea0gSIsInJvbGUiOiJVc2VyIiwiaHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvd3MvMjAwNS8wNS9pZGVudGl0eS9jbGFpbXMvbW9iaWxlcGhvbmUiOiIxODE3NDAxMDU2MiIsImdyb3Vwc2lkIjoiNGIyZDk2NjItYTc2OC0wOGYyLWEwYzgtNzYyYjhjNzZkYTJhIiwibmJmIjoxNzQ0MjYzMTAyLCJleHAiOjE3NDQyNjY3MDIsImlhdCI6MTc0NDI2MzEwMn0.ZJTwC7rWCcywoM7ncysw-JRIiwXz4y_6hlmqctN-gMM"
|
// "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9zaWQiOiIwOGRkNzFiZC01N2MxLTQ1YmMtODBiYS0xMjkzYjU4MTViMmEiLCJ1bmlxdWVfbmFtZSI6IuS_nea0gSIsInJvbGUiOiJVc2VyIiwiaHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvd3MvMjAwNS8wNS9pZGVudGl0eS9jbGFpbXMvbW9iaWxlcGhvbmUiOiIxODE3NDAxMDU2MiIsImdyb3Vwc2lkIjoiNGIyZDk2NjItYTc2OC0wOGYyLWEwYzgtNzYyYjhjNzZkYTJhIiwibmJmIjoxNzQ0MjYzMTAyLCJleHAiOjE3NDQyNjY3MDIsImlhdCI6MTc0NDI2MzEwMn0.ZJTwC7rWCcywoM7ncysw-JRIiwXz4y_6hlmqctN-gMM"
|
||||||
let token = data.token;
|
let token = data.token;
|
||||||
uni.setStorageSync("token", "Bearer " + token);
|
uni.setStorageSync("token", "Bearer " + token);
|
||||||
const normalTabBar = [
|
console.log(jwtDecode(token), "解析的token信息");
|
||||||
{
|
let resData = jwtDecode(token);
|
||||||
pagePath: "/pages/index/planList",
|
this.$u.vuex("vuex_userData", resData);
|
||||||
iconPath: "/static/tab/planList.png",
|
// User | Admin
|
||||||
selectedIconPath: "/static/tab/planList-active.png",
|
let role = resData.role;
|
||||||
text: "计划",
|
console.log(role, "role----");
|
||||||
},
|
// return;
|
||||||
{
|
if (role === "User") {
|
||||||
pagePath: "/pages/index/index",
|
const normalTabBar = [
|
||||||
iconPath: "/static/tab/admin-home.png",
|
{
|
||||||
selectedIconPath: "/static/tab/admin-home-acitve.png",
|
pagePath: "/pages/index/planList",
|
||||||
text: "首页",
|
iconPath: "/static/tab/planList.png",
|
||||||
},
|
selectedIconPath: "/static/tab/planList-active.png",
|
||||||
{
|
text: "计划",
|
||||||
pagePath: "/pages/user/index",
|
},
|
||||||
iconPath: "/static/tab/admin-my.png",
|
{
|
||||||
selectedIconPath: "/static/tab/admin-my-active.png",
|
pagePath: "/pages/index/index",
|
||||||
text: "设置",
|
iconPath: "/static/tab/admin-home.png",
|
||||||
},
|
selectedIconPath: "/static/tab/admin-home-acitve.png",
|
||||||
];
|
text: "首页",
|
||||||
this.$u.vuex("vuex_tabbar", normalTabBar);
|
},
|
||||||
uni.switchTab({
|
{
|
||||||
url: "/pages/index/index",
|
pagePath: "/pages/user/index",
|
||||||
success() {
|
iconPath: "/static/tab/admin-my.png",
|
||||||
console.log("跳转成功");
|
selectedIconPath: "/static/tab/admin-my-active.png",
|
||||||
window.initFn = null; // 清除全局函数
|
text: "设置",
|
||||||
},
|
},
|
||||||
fail(err) {
|
];
|
||||||
console.error("跳转失败", err);
|
this.$u.vuex("vuex_tabbar", normalTabBar);
|
||||||
},
|
uni.switchTab({
|
||||||
});
|
url: "/pages/index/index",
|
||||||
|
success() {
|
||||||
|
console.log("跳转成功");
|
||||||
|
window.initFn = null; // 清除全局函数
|
||||||
|
},
|
||||||
|
fail(err) {
|
||||||
|
console.error("跳转失败", err);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (role === "Admin") {
|
||||||
|
const adminTabBar = [
|
||||||
|
{
|
||||||
|
pagePath: "/pages/adminHome/index",
|
||||||
|
iconPath: "/static/tab/admin-home.png",
|
||||||
|
selectedIconPath: "/static/tab/admin-home-acitve.png",
|
||||||
|
text: "首页",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pagePath: "/pages/adminNfc/index",
|
||||||
|
iconPath: "/static/tab/nfc.png",
|
||||||
|
selectedIconPath: "/static/tab/nfc-active.png",
|
||||||
|
text: "nfc写入",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pagePath: "/pages/adminMy/index",
|
||||||
|
iconPath: "/static/tab/admin-my.png",
|
||||||
|
selectedIconPath: "/static/tab/admin-my-active.png",
|
||||||
|
text: "我的",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
this.$u.vuex("vuex_tabbar", adminTabBar);
|
||||||
|
uni.switchTab({
|
||||||
|
url: "/pages/adminHome/index",
|
||||||
|
success() {
|
||||||
|
console.log("跳转成功");
|
||||||
|
window.initFn = null; // 清除全局函数
|
||||||
|
},
|
||||||
|
fail(err) {
|
||||||
|
console.error("跳转失败", err);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2015 Auth0, Inc. <support@auth0.com> (http://auth0.com)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
|
@ -0,0 +1,134 @@
|
||||||
|

|
||||||
|
|
||||||
|
**IMPORTANT:** This library doesn't validate the token, any well-formed JWT can be decoded. You should validate the token in your server-side logic by using something like [express-jwt](https://github.com/auth0/express-jwt), [koa-jwt](https://github.com/stiang/koa-jwt), [Microsoft.AspNetCore.Authentication.JwtBearer](https://www.nuget.org/packages/Microsoft.AspNetCore.Authentication.JwtBearer), etc.
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|
[](https://opensource.org/licenses/MIT)
|
||||||
|
[](https://circleci.com/gh/auth0/jwt-decode)
|
||||||
|
|
||||||
|
:books: [Documentation](#documentation) - :rocket: [Getting Started](#getting-started) - :speech_balloon: [Feedback](#feedback)
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
- [Docs site](https://www.auth0.com/docs) - explore our docs site and learn more about Auth0.
|
||||||
|
|
||||||
|
## Getting started
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
Install with NPM or Yarn.
|
||||||
|
|
||||||
|
Run `npm install jwt-decode` or `yarn add jwt-decode` to install the library.
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { jwtDecode } from "jwt-decode";
|
||||||
|
|
||||||
|
const token = "eyJ0eXAiO.../// jwt token";
|
||||||
|
const decoded = jwtDecode(token);
|
||||||
|
|
||||||
|
console.log(decoded);
|
||||||
|
|
||||||
|
/* prints:
|
||||||
|
* {
|
||||||
|
* foo: "bar",
|
||||||
|
* exp: 1393286893,
|
||||||
|
* iat: 1393268893
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
|
||||||
|
// decode header by passing in options (useful for when you need `kid` to verify a JWT):
|
||||||
|
const decodedHeader = jwtDecode(token, { header: true });
|
||||||
|
console.log(decodedHeader);
|
||||||
|
|
||||||
|
/* prints:
|
||||||
|
* {
|
||||||
|
* typ: "JWT",
|
||||||
|
* alg: "HS256"
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note:** A falsy or malformed token will throw an `InvalidTokenError` error; see below for more information on specific errors.
|
||||||
|
|
||||||
|
## Errors
|
||||||
|
|
||||||
|
This library works with valid JSON web tokens. The basic format of these token is
|
||||||
|
```
|
||||||
|
[part1].[part2].[part3]
|
||||||
|
```
|
||||||
|
All parts are supposed to be valid base64 (url) encoded json.
|
||||||
|
Depending on the `{ header: <option> }` option it will decode part 1 (only if header: true is specified) or part 2 (default)
|
||||||
|
|
||||||
|
Not adhering to the format will result in a `InvalidTokenError` with one of the following messages:
|
||||||
|
|
||||||
|
- `Invalid token specified: must be a string` => the token passed was not a string, this library only works on strings.
|
||||||
|
- `Invalid token specified: missing part #` => this probably means you are missing a dot (`.`) in the token
|
||||||
|
- `Invalid token specified: invalid base64 for part #` => the part could not be base64 decoded (the message should contain the error the base64 decoder gave)
|
||||||
|
- `Invalid token specified: invalid json for part #` => the part was correctly base64 decoded, however, the decoded value was not valid JSON (the message should contain the error the JSON parser gave)
|
||||||
|
|
||||||
|
#### Use with TypeScript
|
||||||
|
|
||||||
|
The return type of the `jwtDecode` function is determined by the `header` property of the object passed as the second argument. If omitted (or set to false), it'll use `JwtPayload`, when true it will use `JwtHeader`.
|
||||||
|
If needed, you can specify what the expected return type should be by passing a type argument to the `jwtDecode` function.
|
||||||
|
|
||||||
|
You can extend both `JwtHeader` and `JwtPayload` to include non-standard claims or properties.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { jwtDecode } from "jwt-decode";
|
||||||
|
|
||||||
|
const token = "eyJhsw5c";
|
||||||
|
const decoded = jwtDecode<JwtPayload>(token); // Returns with the JwtPayload type
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Use as a CommonJS package
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const { jwtDecode } = require('jwt-decode');
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Include with a script tag
|
||||||
|
|
||||||
|
Copy the file `jwt-decode.js` from the root of the `build/esm` folder to your project somewhere, then import `jwtDecode` from it inside a script tag that's marked with `type="module"`:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script type="module">
|
||||||
|
import { jwtDecode } from "/path/to/jwt-decode.js";
|
||||||
|
|
||||||
|
const token = "eyJhsw5c";
|
||||||
|
const decoded = jwtDecode(token);
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Feedback
|
||||||
|
|
||||||
|
### Contributing
|
||||||
|
|
||||||
|
We appreciate feedback and contribution to this repo! Before you get started, please see the following:
|
||||||
|
|
||||||
|
- [Auth0's general contribution guidelines](https://github.com/auth0/open-source-template/blob/master/GENERAL-CONTRIBUTING.md)
|
||||||
|
- [Auth0's code of conduct guidelines](https://github.com/auth0/open-source-template/blob/master/CODE-OF-CONDUCT.md)
|
||||||
|
|
||||||
|
### Raise an issue
|
||||||
|
|
||||||
|
To provide feedback or report a bug, please [raise an issue on our issue tracker](https://github.com/auth0/jwt-decode/issues).
|
||||||
|
|
||||||
|
### Vulnerability Reporting
|
||||||
|
|
||||||
|
Please do not report security vulnerabilities on the public GitHub issue tracker. The [Responsible Disclosure Program](https://auth0.com/responsible-disclosure-policy) details the procedure for disclosing security issues.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<picture>
|
||||||
|
<source media="(prefers-color-scheme: light)" srcset="https://cdn.auth0.com/website/sdks/logos/auth0_light_mode.png" width="150">
|
||||||
|
<source media="(prefers-color-scheme: dark)" srcset="https://cdn.auth0.com/website/sdks/logos/auth0_dark_mode.png" width="150">
|
||||||
|
<img alt="Auth0 Logo" src="https://cdn.auth0.com/website/sdks/logos/auth0_light_mode.png" width="150">
|
||||||
|
</picture>
|
||||||
|
</p>
|
||||||
|
<p align="center">Auth0 is an easy to implement, adaptable authentication and authorization platform. To learn more checkout <a href="https://auth0.com/why-auth0">Why Auth0?</a></p>
|
||||||
|
<p align="center">
|
||||||
|
This project is licensed under the MIT license. See the <a href="./LICENSE"> LICENSE</a> file for more info.</p>
|
|
@ -0,0 +1,23 @@
|
||||||
|
export interface JwtDecodeOptions {
|
||||||
|
header?: boolean;
|
||||||
|
}
|
||||||
|
export interface JwtHeader {
|
||||||
|
typ?: string;
|
||||||
|
alg?: string;
|
||||||
|
kid?: string;
|
||||||
|
}
|
||||||
|
export interface JwtPayload {
|
||||||
|
iss?: string;
|
||||||
|
sub?: string;
|
||||||
|
aud?: string[] | string;
|
||||||
|
exp?: number;
|
||||||
|
nbf?: number;
|
||||||
|
iat?: number;
|
||||||
|
jti?: string;
|
||||||
|
}
|
||||||
|
export declare class InvalidTokenError extends Error {
|
||||||
|
}
|
||||||
|
export declare function jwtDecode<T = JwtHeader>(token: string, options: JwtDecodeOptions & {
|
||||||
|
header: true;
|
||||||
|
}): T;
|
||||||
|
export declare function jwtDecode<T = JwtPayload>(token: string, options?: JwtDecodeOptions): T;
|
|
@ -0,0 +1,62 @@
|
||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.jwtDecode = exports.InvalidTokenError = void 0;
|
||||||
|
class InvalidTokenError extends Error {
|
||||||
|
}
|
||||||
|
exports.InvalidTokenError = InvalidTokenError;
|
||||||
|
InvalidTokenError.prototype.name = "InvalidTokenError";
|
||||||
|
function b64DecodeUnicode(str) {
|
||||||
|
return decodeURIComponent(atob(str).replace(/(.)/g, (m, p) => {
|
||||||
|
let code = p.charCodeAt(0).toString(16).toUpperCase();
|
||||||
|
if (code.length < 2) {
|
||||||
|
code = "0" + code;
|
||||||
|
}
|
||||||
|
return "%" + code;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
function base64UrlDecode(str) {
|
||||||
|
let output = str.replace(/-/g, "+").replace(/_/g, "/");
|
||||||
|
switch (output.length % 4) {
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
output += "==";
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
output += "=";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error("base64 string is not of the correct length");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return b64DecodeUnicode(output);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
return atob(output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function jwtDecode(token, options) {
|
||||||
|
if (typeof token !== "string") {
|
||||||
|
throw new InvalidTokenError("Invalid token specified: must be a string");
|
||||||
|
}
|
||||||
|
options || (options = {});
|
||||||
|
const pos = options.header === true ? 0 : 1;
|
||||||
|
const part = token.split(".")[pos];
|
||||||
|
if (typeof part !== "string") {
|
||||||
|
throw new InvalidTokenError(`Invalid token specified: missing part #${pos + 1}`);
|
||||||
|
}
|
||||||
|
let decoded;
|
||||||
|
try {
|
||||||
|
decoded = base64UrlDecode(part);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
throw new InvalidTokenError(`Invalid token specified: invalid base64 for part #${pos + 1} (${e.message})`);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return JSON.parse(decoded);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
throw new InvalidTokenError(`Invalid token specified: invalid json for part #${pos + 1} (${e.message})`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.jwtDecode = jwtDecode;
|
|
@ -0,0 +1 @@
|
||||||
|
{"type": "commonjs"}
|
|
@ -0,0 +1,23 @@
|
||||||
|
export interface JwtDecodeOptions {
|
||||||
|
header?: boolean;
|
||||||
|
}
|
||||||
|
export interface JwtHeader {
|
||||||
|
typ?: string;
|
||||||
|
alg?: string;
|
||||||
|
kid?: string;
|
||||||
|
}
|
||||||
|
export interface JwtPayload {
|
||||||
|
iss?: string;
|
||||||
|
sub?: string;
|
||||||
|
aud?: string[] | string;
|
||||||
|
exp?: number;
|
||||||
|
nbf?: number;
|
||||||
|
iat?: number;
|
||||||
|
jti?: string;
|
||||||
|
}
|
||||||
|
export declare class InvalidTokenError extends Error {
|
||||||
|
}
|
||||||
|
export declare function jwtDecode<T = JwtHeader>(token: string, options: JwtDecodeOptions & {
|
||||||
|
header: true;
|
||||||
|
}): T;
|
||||||
|
export declare function jwtDecode<T = JwtPayload>(token: string, options?: JwtDecodeOptions): T;
|
|
@ -0,0 +1,57 @@
|
||||||
|
export class InvalidTokenError extends Error {
|
||||||
|
}
|
||||||
|
InvalidTokenError.prototype.name = "InvalidTokenError";
|
||||||
|
function b64DecodeUnicode(str) {
|
||||||
|
return decodeURIComponent(atob(str).replace(/(.)/g, (m, p) => {
|
||||||
|
let code = p.charCodeAt(0).toString(16).toUpperCase();
|
||||||
|
if (code.length < 2) {
|
||||||
|
code = "0" + code;
|
||||||
|
}
|
||||||
|
return "%" + code;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
function base64UrlDecode(str) {
|
||||||
|
let output = str.replace(/-/g, "+").replace(/_/g, "/");
|
||||||
|
switch (output.length % 4) {
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
output += "==";
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
output += "=";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error("base64 string is not of the correct length");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return b64DecodeUnicode(output);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
return atob(output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export function jwtDecode(token, options) {
|
||||||
|
if (typeof token !== "string") {
|
||||||
|
throw new InvalidTokenError("Invalid token specified: must be a string");
|
||||||
|
}
|
||||||
|
options || (options = {});
|
||||||
|
const pos = options.header === true ? 0 : 1;
|
||||||
|
const part = token.split(".")[pos];
|
||||||
|
if (typeof part !== "string") {
|
||||||
|
throw new InvalidTokenError(`Invalid token specified: missing part #${pos + 1}`);
|
||||||
|
}
|
||||||
|
let decoded;
|
||||||
|
try {
|
||||||
|
decoded = base64UrlDecode(part);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
throw new InvalidTokenError(`Invalid token specified: invalid base64 for part #${pos + 1} (${e.message})`);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return JSON.parse(decoded);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
throw new InvalidTokenError(`Invalid token specified: invalid json for part #${pos + 1} (${e.message})`);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
{
|
||||||
|
"name": "jwt-decode",
|
||||||
|
"version": "4.0.0",
|
||||||
|
"description": "Decode JWT tokens, mostly useful for browser applications.",
|
||||||
|
"type": "module",
|
||||||
|
"main": "build/cjs/index.js",
|
||||||
|
"module": "build/esm/index.js",
|
||||||
|
"types": "build/cjs/index.d.ts",
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"import": {
|
||||||
|
"types": "./build/esm/index.d.ts",
|
||||||
|
"default": "./build/esm/index.js"
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"types": "./build/cjs/index.d.ts",
|
||||||
|
"default": "./build/cjs/index.js"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"jwt",
|
||||||
|
"browser"
|
||||||
|
],
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git://github.com/auth0/jwt-decode"
|
||||||
|
},
|
||||||
|
"url": "https://github.com/auth0/jwt-decode/issues",
|
||||||
|
"homepage": "https://github.com/auth0/jwt-decode#readme",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "concurrently --kill-others \"npm run build:watch\" \"npm run dev:server\"",
|
||||||
|
"dev:server": "browser-sync start --config bs-config.json",
|
||||||
|
"prebuild": "shx rm -rf ./build && shx mkdir -p ./build/cjs && shx echo '{\"type\": \"commonjs\"}'> build/cjs/package.json",
|
||||||
|
"build": "tsc -b ./tsconfig.cjs.json ./tsconfig.esm.json",
|
||||||
|
"build:watch": "npm run build -- --watch",
|
||||||
|
"lint": "eslint .",
|
||||||
|
"lint:package": "publint",
|
||||||
|
"test": "npm run test:node && npm run test:browser",
|
||||||
|
"test:node": "NODE_OPTIONS='--experimental-vm-modules --no-warnings' jest --coverage",
|
||||||
|
"test:browser": "NODE_OPTIONS='--experimental-vm-modules --no-warnings' jest --coverage --testEnvironment=jsdom",
|
||||||
|
"prepack": "npm run build",
|
||||||
|
"prepare": "husky install"
|
||||||
|
},
|
||||||
|
"author": "Jose F. Romaniello <jfromaniello@gmail.com>",
|
||||||
|
"contributors": [
|
||||||
|
"Sam Bellen <sam.bellen@auth0.com>"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "7.23.2",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^6.4.1",
|
||||||
|
"@typescript-eslint/parser": "^6.4.1",
|
||||||
|
"browser-sync": "^2.29.3",
|
||||||
|
"concurrently": "^8.2.0",
|
||||||
|
"eslint": "^8.48.0",
|
||||||
|
"eslint-config-prettier": "^9.0.0",
|
||||||
|
"eslint-import-resolver-typescript": "^3.6.0",
|
||||||
|
"eslint-plugin-import": "^2.28.1",
|
||||||
|
"eslint-plugin-prettier": "^5.0.0",
|
||||||
|
"husky": "^8.0.3",
|
||||||
|
"jest": "^29.7.0",
|
||||||
|
"jest-environment-jsdom": "^29.6.2",
|
||||||
|
"lint-staged": "^15.0.2",
|
||||||
|
"prettier": "^3.0.2",
|
||||||
|
"publint": "^0.2.2",
|
||||||
|
"shx": "^0.3.4",
|
||||||
|
"ts-jest": "^29.1.1",
|
||||||
|
"ts-node": "^10.9.1",
|
||||||
|
"typescript": "^5.1.6"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"build"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"lint-staged": {
|
||||||
|
"*.{js,ts}": "eslint --fix"
|
||||||
|
}
|
||||||
|
}
|
|
@ -53,6 +53,9 @@
|
||||||
></image>
|
></image>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
<view v-if="true" style="display: flex">
|
||||||
|
<u-button type="error" @click="testFn">调试录入卡片</u-button>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<u-tabbar :list="vuex_tabbar"></u-tabbar>
|
<u-tabbar :list="vuex_tabbar"></u-tabbar>
|
||||||
</view>
|
</view>
|
||||||
|
@ -70,7 +73,32 @@ export default {
|
||||||
uni.hideLoading(); // 关闭 Loading
|
uni.hideLoading(); // 关闭 Loading
|
||||||
},
|
},
|
||||||
onLoad() {},
|
onLoad() {},
|
||||||
methods: {},
|
methods: {
|
||||||
|
testFn() {
|
||||||
|
let u = navigator.userAgent;
|
||||||
|
let isAndroid = u.indexOf("Android") > -1 || u.indexOf("Adr") > -1; //android
|
||||||
|
// let isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios
|
||||||
|
try {
|
||||||
|
if (isAndroid && AndroidJs) {
|
||||||
|
console.log("%c%s", "color:red", "安卓--调用方法");
|
||||||
|
const reqRow = {
|
||||||
|
name: "input",
|
||||||
|
data: "",
|
||||||
|
};
|
||||||
|
AndroidJs.func(JSON.stringify(reqRow)); // 给安卓传参
|
||||||
|
} else {
|
||||||
|
console.log("%c%s", "color:red", "苹果--调用方法");
|
||||||
|
const reqRow = {
|
||||||
|
name: "back-iphone",
|
||||||
|
data: "",
|
||||||
|
};
|
||||||
|
window.webkit.messageHandlers.func.postMessage(JSON.stringify(reqRow)); // 给ios 传参
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e, "e-----判断安卓苹果类型出错");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
@ -118,8 +118,8 @@
|
||||||
{{ errorMsg }}
|
{{ errorMsg }}
|
||||||
</view>
|
</view>
|
||||||
<view class="btn-box">
|
<view class="btn-box">
|
||||||
<view class="btn-cancel" @click="errorShow = false">暂不</view>
|
<view class="btn-cancel" @click="errorShow = false">关闭</view>
|
||||||
<view class="btn-success" @click="errorShow = false">异常上报</view>
|
<!-- <view class="btn-success" @click="errorShow = false">异常上报</view> -->
|
||||||
<!-- <view class="btn-success" @click="exceptionReportFn">异常上报</view> -->
|
<!-- <view class="btn-success" @click="exceptionReportFn">异常上报</view> -->
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
@ -220,14 +220,15 @@ export default {
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return uni.showToast({ title: "未传入参数 initFn", icon: "none" });
|
return uni.showToast({ title: "未传入参数 initFn", icon: "none" });
|
||||||
}
|
}
|
||||||
// uni.showModal({
|
uni.showModal({
|
||||||
// title: "查看initFn",
|
title: "开发调试查看nimei",
|
||||||
// content: JSON.stringify(data) || "未传入参数 initFn",
|
content: JSON.stringify(data) || "未传入参数 initFn",
|
||||||
// showCancel: true,
|
showCancel: true,
|
||||||
// success: function (res) {},
|
success: function (res) {},
|
||||||
// });
|
});
|
||||||
let cardID = data.cardID;
|
let cardID = data.cardID;
|
||||||
let nimei = data.nimei;
|
// let nimei = data.nimei;
|
||||||
|
let nimei = data.uuid;
|
||||||
const req = {
|
const req = {
|
||||||
Nimei: nimei,
|
Nimei: nimei,
|
||||||
// Nimei:'"78F04BC3E9A6DE4782C11A2346F39C68'
|
// Nimei:'"78F04BC3E9A6DE4782C11A2346F39C68'
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<view class="content">
|
<view class="content">
|
||||||
<view v-if="true" style="display:flex">
|
<view v-if="false" style="display:flex">
|
||||||
<u-button type="error" @click="testFn">调试录入卡片</u-button>
|
<u-button type="error" @click="testFn">调试录入卡片</u-button>
|
||||||
<!-- <u-button type="error" @click="test1Fn">调试token过期</u-button> -->
|
|
||||||
</view>
|
</view>
|
||||||
<daySelect @dateChange="onDateChange" />
|
<daySelect @dateChange="onDateChange" />
|
||||||
<view v-if="isToday" class="task-info">
|
<view v-if="isToday" class="task-info">
|
||||||
|
@ -165,10 +164,6 @@ export default {
|
||||||
console.log(e, "e-----判断安卓苹果类型出错");
|
console.log(e, "e-----判断安卓苹果类型出错");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
test1Fn(){
|
|
||||||
uni.setStorageSync("token", "Bearer ");
|
|
||||||
this.getPlanByDate();
|
|
||||||
},
|
|
||||||
onDateChange({ date, isToday }) {
|
onDateChange({ date, isToday }) {
|
||||||
this.isToday = isToday;
|
this.isToday = isToday;
|
||||||
this.currentDate = date;
|
this.currentDate = date;
|
||||||
|
|
|
@ -1,36 +1,30 @@
|
||||||
<template>
|
<template>
|
||||||
<view class="content">
|
<view class="content">
|
||||||
<view
|
<view
|
||||||
style="
|
style="margin-top: 50rpx; display: flex; align-items: center; padding-right: 50rpx"
|
||||||
margin-top: 50rpx;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding-right: 50rpx;
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<view style="margin-right: 50rpx">账号</view>
|
<view style="margin-right: 50rpx">账号</view>
|
||||||
<u-input v-model="phone" border placeholder="账号"></u-input>
|
<u-input v-model="phone" border placeholder="账号"></u-input>
|
||||||
</view>
|
</view>
|
||||||
<view
|
<view
|
||||||
style="
|
style="margin-top: 50rpx; display: flex; align-items: center; padding-right: 50rpx"
|
||||||
margin-top: 50rpx;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding-right: 50rpx;
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<view style="margin-right: 50rpx">账号</view>
|
<view style="margin-right: 50rpx">账号</view>
|
||||||
<u-input v-model="pwd" border placeholder="密码"></u-input>
|
<u-input v-model="pwd" border placeholder="密码"></u-input>
|
||||||
</view>
|
</view>
|
||||||
<u-button type="primary" @click="loginFn" style="margin-top: 50rpx"
|
<u-button type="primary" @click="loginFn" style="margin-top: 50rpx">登陆</u-button>
|
||||||
>登陆</u-button
|
|
||||||
>
|
|
||||||
<u-button type="primary" @click="login1Fn" style="margin-top: 50rpx"
|
<u-button type="primary" @click="login1Fn" style="margin-top: 50rpx"
|
||||||
>登陆13800451500清洁工</u-button
|
>登陆13800451500清洁工</u-button
|
||||||
>
|
>
|
||||||
<u-button type="primary" @click="login2Fn" style="margin-top: 50rpx"
|
<u-button type="primary" @click="login2Fn" style="margin-top: 50rpx"
|
||||||
>登陆18174010562管理员</u-button
|
>登陆18174010562管理员</u-button
|
||||||
>
|
>
|
||||||
|
<u-button type="primary" @click="login4Fn" style="margin-top: 50rpx"
|
||||||
|
>登陆18174010562清洁工</u-button
|
||||||
|
>
|
||||||
|
<u-button type="primary" @click="login3Fn" style="margin-top: 50rpx"
|
||||||
|
>登陆18174010561</u-button
|
||||||
|
>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
|
@ -50,8 +44,8 @@ export default {
|
||||||
onLoad() {},
|
onLoad() {},
|
||||||
methods: {
|
methods: {
|
||||||
login1Fn() {
|
login1Fn() {
|
||||||
// this.phone = "13800451500";
|
this.phone = "13800451500";
|
||||||
this.phone = "18174010561";
|
// this.phone = "18174010561";
|
||||||
this.pwd = "123456";
|
this.pwd = "123456";
|
||||||
|
|
||||||
const normalTabBar = [
|
const normalTabBar = [
|
||||||
|
@ -104,6 +98,60 @@ export default {
|
||||||
this.$u.vuex("vuex_tabbar", adminTabBar);
|
this.$u.vuex("vuex_tabbar", adminTabBar);
|
||||||
this.loginFn("admin");
|
this.loginFn("admin");
|
||||||
},
|
},
|
||||||
|
login4Fn() {
|
||||||
|
this.phone = "18174010562";
|
||||||
|
this.pwd = "123456";
|
||||||
|
|
||||||
|
const normalTabBar = [
|
||||||
|
{
|
||||||
|
pagePath: "/pages/index/planList",
|
||||||
|
iconPath: "/static/tab/planList.png",
|
||||||
|
selectedIconPath: "/static/tab/planList-active.png",
|
||||||
|
text: "计划",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pagePath: "/pages/index/index",
|
||||||
|
iconPath: "/static/tab/admin-home.png",
|
||||||
|
selectedIconPath: "/static/tab/admin-home-acitve.png",
|
||||||
|
text: "首页",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pagePath: "/pages/user/index",
|
||||||
|
iconPath: "/static/tab/admin-my.png",
|
||||||
|
selectedIconPath: "/static/tab/admin-my-active.png",
|
||||||
|
text: "设置",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
this.$u.vuex("vuex_tabbar", normalTabBar);
|
||||||
|
this.loginFn("user");
|
||||||
|
},
|
||||||
|
login3Fn() {
|
||||||
|
this.phone = "18174010561";
|
||||||
|
this.pwd = "123456";
|
||||||
|
|
||||||
|
const normalTabBar = [
|
||||||
|
{
|
||||||
|
pagePath: "/pages/index/planList",
|
||||||
|
iconPath: "/static/tab/planList.png",
|
||||||
|
selectedIconPath: "/static/tab/planList-active.png",
|
||||||
|
text: "计划",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pagePath: "/pages/index/index",
|
||||||
|
iconPath: "/static/tab/admin-home.png",
|
||||||
|
selectedIconPath: "/static/tab/admin-home-acitve.png",
|
||||||
|
text: "首页",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pagePath: "/pages/user/index",
|
||||||
|
iconPath: "/static/tab/admin-my.png",
|
||||||
|
selectedIconPath: "/static/tab/admin-my-active.png",
|
||||||
|
text: "设置",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
this.$u.vuex("vuex_tabbar", normalTabBar);
|
||||||
|
this.loginFn("user");
|
||||||
|
},
|
||||||
async loginFn(type) {
|
async loginFn(type) {
|
||||||
let salt = bcrypt.genSaltSync(12);
|
let salt = bcrypt.genSaltSync(12);
|
||||||
let req = {
|
let req = {
|
||||||
|
|
|
@ -12,7 +12,7 @@ try {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 需要永久存储,且下次APP启动需要取出的,在state中的变量名
|
// 需要永久存储,且下次APP启动需要取出的,在state中的变量名
|
||||||
let saveStateKeys = ['vuex_user', 'vuex_token', 'vuex_tabbar'];
|
let saveStateKeys = ['vuex_user', 'vuex_token', 'vuex_tabbar', 'vuex_userData'];
|
||||||
|
|
||||||
// 保存变量到本地存储中
|
// 保存变量到本地存储中
|
||||||
const saveLifeData = function (key, value) {
|
const saveLifeData = function (key, value) {
|
||||||
|
@ -34,6 +34,8 @@ const store = new Vuex.Store({
|
||||||
// 加上vuex_前缀,是防止变量名冲突,也让人一目了然
|
// 加上vuex_前缀,是防止变量名冲突,也让人一目了然
|
||||||
vuex_user: lifeData.vuex_user ? lifeData.vuex_user : { name: '明月' },
|
vuex_user: lifeData.vuex_user ? lifeData.vuex_user : { name: '明月' },
|
||||||
vuex_token: lifeData.vuex_token ? lifeData.vuex_token : '',
|
vuex_token: lifeData.vuex_token ? lifeData.vuex_token : '',
|
||||||
|
// token解析的用户信息
|
||||||
|
vuex_userData: lifeData.userData ? lifeData.userData : {},
|
||||||
vuex_tabbar: lifeData.vuex_tabbar ? lifeData.vuex_tabbar : [
|
vuex_tabbar: lifeData.vuex_tabbar ? lifeData.vuex_tabbar : [
|
||||||
// {
|
// {
|
||||||
// "pagePath": "/pages/adminHome/index",
|
// "pagePath": "/pages/adminHome/index",
|
||||||
|
|
Loading…
Reference in New Issue