Commit be326b71 authored by wanli's avatar wanli

feat(frontend/src/views/User/Login.vue): 前端登录

parent 498128c0
''' '''
Author: your name Author: your name
Date: 2021-07-12 11:14:48 Date: 2021-07-12 11:14:48
LastEditTime: 2021-07-12 11:29:36 LastEditTime: 2021-07-15 17:43:48
LastEditors: Please set LastEditors LastEditors: Please set LastEditors
Description: In User Settings Edit Description: In User Settings Edit
FilePath: \evm-store\tools\build_out\controllers\appi.py FilePath: \evm-store\tools\build_out\controllers\appi.py
......
...@@ -147,7 +147,9 @@ class AppResource(object): ...@@ -147,7 +147,9 @@ class AppResource(object):
# 应用打包 # 应用打包
# 插入一条打包记录 # 插入一条打包记录
user = UserModel.query.filter(UserModel.id==params.get('user')).one_or_none() logger.info(jwt)
user = UserModel.query.filter(UserModel.uuid==jwt.get('uuid')).one_or_none()
if not user: if not user:
return False, ResponseCode.USER_NOT_EXISTS return False, ResponseCode.USER_NOT_EXISTS
......
...@@ -65,8 +65,8 @@ class PostAppSchema(ma.SQLAlchemySchema): ...@@ -65,8 +65,8 @@ class PostAppSchema(ma.SQLAlchemySchema):
app_icon = ma.auto_field() app_icon = ma.auto_field()
app_version = ma.auto_field() app_version = ma.auto_field()
category = ma.auto_field() category = ma.auto_field()
category_2th = ma.auto_field() category_2th = fields.String(required=False)
developer = ma.auto_field() developer = fields.String(required=False)
app_screen_size = ma.auto_field() app_screen_size = ma.auto_field()
app_arch = ma.auto_field() app_arch = ma.auto_field()
app_review = ma.auto_field() app_review = ma.auto_field()
......
'''
Author: your name
Date: 2021-07-15 03:22:19
LastEditTime: 2021-07-15 10:20:28
LastEditors: Please set LastEditors
Description: In User Settings Edit
FilePath: \evm-store\tools\build_out\views\__init__.py
'''
#!/usr/bin/env python
# -*- coding: utf_8 -*-
from flask import Blueprint
from flask_restful import Api
from . import area
from . import app
from . import package
from . import user
from . import login
from . import device
from . import annex
from . import file
from . import monitorWatch
from . import monitorSystem
from . import monitorLvgl
from . import monitorImage
from . import monitorEvm
api_v1 = Blueprint('api_v1', __name__)
api = Api(api_v1)
api.add_resource(area.AreaResource, '/area/<string:uuid>')
api.add_resource(area.AreaResourceList, '/area')
api.add_resource(app.AppResource, '/app/<string:uuid>')
api.add_resource(app.AppResourceList, '/app')
api.add_resource(package.PackageResource, '/package/<string:uuid>')
api.add_resource(package.PackageResourceList, '/package')
api.add_resource(user.UserResource, '/user/<string:uuid>')
api.add_resource(user.UserResourceList, '/user')
api.add_resource(login.LoginResource, '/login/<string:uuid>')
api.add_resource(login.LoginResourceList, '/login')
api.add_resource(device.DeviceResource, '/device/<string:uuid>')
api.add_resource(device.DeviceResourceList, '/device')
api.add_resource(annex.AnnexResource, '/annex/<string:uuid>')
api.add_resource(annex.AnnexResourceList, '/annex')
api.add_resource(file.FileInit, "/file-manager/initialize")
api.add_resource(file.FileContent, "/file-manager/content")
api.add_resource(file.FileDisk, "/file-manager/disk")
api.add_resource(file.FileTree, "/file-manager/tree")
api.add_resource(file.FileDownload, "/file-manager/download")
api.add_resource(file.FilePrview, "/file-manager/preview")
api.add_resource(monitorWatch.MonitorWatchResource, '/monitorWatch/<string:uuid>')
api.add_resource(monitorWatch.MonitorWatchResourceList, '/monitorWatch')
api.add_resource(monitorSystem.MonitorSystemResource, '/monitorSystem/<string:uuid>')
api.add_resource(monitorSystem.MonitorSystemResourceList, '/monitorSystem')
api.add_resource(monitorLvgl.MonitorLvglResource, '/monitorLvgl/<string:uuid>')
api.add_resource(monitorLvgl.MonitorLvglResourceList, '/monitorLvgl')
api.add_resource(monitorImage.MonitorImageResource, '/monitorImage/<string:uuid>')
api.add_resource(monitorImage.MonitorImageResourceList, '/monitorImage')
api.add_resource(monitorEvm.MonitorEvmResource, '/monitorEvm/<string:uuid>')
api.add_resource(monitorEvm.MonitorEvmResourceList, '/monitorEvm')
# -*- coding: utf-8 -*- '''
Author: your name
Date: 2021-07-15 03:22:19
LastEditTime: 2021-07-15 17:45:32
LastEditors: Please set LastEditors
Description: In User Settings Edit
FilePath: \evm-store\tools\build_out\views\__init__.py
'''
#!/usr/bin/env python
# -*- coding: utf_8 -*-
from flask import Blueprint from flask import Blueprint
from flask_restful import Api from flask_restful import Api
...@@ -9,6 +18,7 @@ from . import user ...@@ -9,6 +18,7 @@ from . import user
from . import login from . import login
from . import device from . import device
from . import annex from . import annex
from . import file
from . import monitorWatch from . import monitorWatch
from . import monitorSystem from . import monitorSystem
from . import monitorLvgl from . import monitorLvgl
...@@ -41,6 +51,13 @@ api.add_resource(device.DeviceResourceList, '/device') ...@@ -41,6 +51,13 @@ api.add_resource(device.DeviceResourceList, '/device')
api.add_resource(annex.AnnexResource, '/annex/<string:uuid>') api.add_resource(annex.AnnexResource, '/annex/<string:uuid>')
api.add_resource(annex.AnnexResourceList, '/annex') api.add_resource(annex.AnnexResourceList, '/annex')
api.add_resource(file.FileInit, "/file-manager/initialize")
api.add_resource(file.FileContent, "/file-manager/content")
api.add_resource(file.FileDisk, "/file-manager/disk")
api.add_resource(file.FileTree, "/file-manager/tree")
api.add_resource(file.FileDownload, "/file-manager/download")
api.add_resource(file.FilePrview, "/file-manager/preview")
api.add_resource(monitorWatch.MonitorWatchResource, '/monitorWatch/<string:uuid>') api.add_resource(monitorWatch.MonitorWatchResource, '/monitorWatch/<string:uuid>')
api.add_resource(monitorWatch.MonitorWatchResourceList, '/monitorWatch') api.add_resource(monitorWatch.MonitorWatchResourceList, '/monitorWatch')
......
import os
from datetime import datetime
from flask import current_app, jsonify, request from flask import current_app, jsonify, request
from flask_restful import Resource from flask_restful import Resource
from flask_restful.reqparse import RequestParser from flask_restful.reqparse import RequestParser
from flask_jwt_extended import ( jwt_required, get_jwt_identity ) from flask_jwt_extended import ( jwt_required, get_jwt_identity )
from werkzeug.utils import secure_filename
from application.config import config
from application.signal_manager import signalManager from application.signal_manager import signalManager
from models.app import postAppSchema, deleteAppSchema, getListAppSchema, getListAppsSchema, getAppSchema, putAppSchema from models.app import postAppSchema, deleteAppSchema, getListAppSchema, getListAppsSchema, getAppSchema, putAppSchema
from webcreator.log import logger from webcreator.log import logger
...@@ -37,13 +41,56 @@ class AppResourceList(Resource): ...@@ -37,13 +41,56 @@ class AppResourceList(Resource):
@jwt_required(locations=["headers"]) @jwt_required(locations=["headers"])
def post(self): def post(self):
try: try:
jwt = get_jwt_identity()
# 获取request.files参数
json_payload = request.json json_payload = request.json
data = postAppSchema.load(json_payload) params = postAppSchema.load(json_payload)
result, message = signalManager.actionPostApp.emit(data)
now_str = datetime.now().strftime("%Y%m%d%H%M%S")
# 获取相对路径
dirname = "{}-{}-{}-{}".format(params["app_name"], params["app_version"], params["category"], now_str)
relative_path = os.sep.join([config.EPK_DIR, dirname])
# 获取最终存储的绝对路径
upload_path = os.path.normpath(os.sep.join([config.UPLOAD_ROOT_DIR, relative_path]))
if not os.path.exists(upload_path):
os.makedirs(upload_path)
files = []
# 应用logo
logo = request.files.get("logo")
if logo:
filename = secure_filename(logo.filename)
file_path = os.sep.join([upload_path, filename])
file_path = os.path.normpath(file_path)
logo.save(file_path)
params.update({ "app_icon": file_path })
# 应用源文件
fileList = request.files.getlist('fileList')
if fileList:
upload_path = os.sep.join([upload_path, "src"])
if not os.path.exists(upload_path):
os.mkdir(upload_path)
for f in fileList:
filename = secure_filename(f.filename)
file_path = os.sep.join([upload_path, filename])
file_path = os.path.normpath(file_path)
f.save(file_path)
files.append(file_path)
# obj = dict()
# obj['filename'] = binfile.filename
# obj['content'] = binfile.stream.read()
params.update({ "fileList": files, "epk_path": upload_path })
result, message = signalManager.actionPostApp.emit(params, jwt)
if result: if result:
logger.warn(result) logger.warn(result)
return response_result(ResponseCode.HTTP_SUCCESS, data=result, msg=message) return response_result(ResponseCode.HTTP_SUCCESS, data=result, msg=message)
return response_result(ResponseCode.HTTP_NOT_FOUND) return response_result(message)
except Exception as e: except Exception as e:
current_app.logger.error(e) current_app.logger.error(e)
return response_result(ResponseCode.HTTP_SERVER_ERROR) return response_result(ResponseCode.HTTP_SERVER_ERROR)
...@@ -95,8 +142,8 @@ class AppResource(Resource): ...@@ -95,8 +142,8 @@ class AppResource(Resource):
def delete(self, uuid): def delete(self, uuid):
try: try:
json_payload = request.json json_payload = request.json
print("========>", uuid, json_payload) data = deleteAppSchema.load(json_payload)
# data = deleteAppSchema.load(json_payload) print("========>", uuid, data, json_payload)
result, message = signalManager.actionDeleteApp.emit(uuid) result, message = signalManager.actionDeleteApp.emit(uuid)
if result: if result:
return response_result(ResponseCode.HTTP_SUCCESS, data=result, msg=message) return response_result(ResponseCode.HTTP_SUCCESS, data=result, msg=message)
......
// set baseUrl // set baseUrl
MIX_LFM_BASE_URL=http://my-url.loc/file-manager/ BASE_URL=http://localhost:3000/
// if you don't want to use csrf-token - you can off it // if you don't want to use csrf-token - you can off it
MIX_LFM_CSRF_TOKEN=OFF CSRF_TOKEN=OFF
\ No newline at end of file \ No newline at end of file
...@@ -9465,6 +9465,11 @@ ...@@ -9465,6 +9465,11 @@
"integrity": "sha1-dIkR+wT0imDEdxs3XKxFqA3xHAM=", "integrity": "sha1-dIkR+wT0imDEdxs3XKxFqA3xHAM=",
"dev": true "dev": true
}, },
"js-cookie": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz",
"integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ=="
},
"js-message": { "js-message": {
"version": "1.0.5", "version": "1.0.5",
"resolved": "http://registry.npm.taobao.org/js-message/download/js-message-1.0.5.tgz", "resolved": "http://registry.npm.taobao.org/js-message/download/js-message-1.0.5.tgz",
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
"codemirror": "^5.59.2", "codemirror": "^5.59.2",
"core-js": "^3.9.0", "core-js": "^3.9.0",
"cropperjs": "^1.5.11", "cropperjs": "^1.5.11",
"js-cookie": "^2.2.1",
"npm-check-updates": "^11.7.1", "npm-check-updates": "^11.7.1",
"numeral": "^2.0.6", "numeral": "^2.0.6",
"plyr": "^3.6.4", "plyr": "^3.6.4",
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
</template> </template>
<script> <script>
import { LocaleProvider, ConfigProvider, Input } from "ant-design-vue"; import { LocaleProvider, ConfigProvider } from "ant-design-vue";
export default { export default {
components: { components: {
LocaleProvider, LocaleProvider,
......
/*
* @Author: your name
* @Date: 2021-07-15 09:33:39
* @LastEditTime: 2021-07-15 19:22:09
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: \evm-store\tools\frontend\src\api\openapi.js
*/
import request from '@/utils/request' import request from '@/utils/request'
export function users(params) { export function users(params) {
...@@ -7,3 +15,19 @@ export function users(params) { ...@@ -7,3 +15,19 @@ export function users(params) {
params params
}) })
} }
export function postLogin(params) {
return request({
url: '/api/v1/login',
method: 'post',
data: params
})
}
export function postApplication(params) {
return request({
url: "/api/v1/app",
method: "post",
data: params
})
}
\ No newline at end of file
/*
* @Author: your name
* @Date: 2021-07-15 09:33:39
* @LastEditTime: 2021-07-15 18:24:43
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: \evm-store\tools\frontend\src\defaultSettings.js
*/
export default { export default {
navTheme: 'dark', // theme for nav menu navTheme: 'dark', // theme for nav menu
primaryColor: '#1890FF', // primary color of ant design primaryColor: '#1890FF', // primary color of ant design
layout: 'sidemenu', // nav menu position: sidemenu or topmenu layout: 'sidemenu', // nav menu position: sidemenu or topmenu
contentWidth: 'Fluid', // layout of content: Fluid or Fixed, only works when layout is topmenu contentWidth: 'Fixed', // layout of content: Fluid or Fixed, only works when layout is topmenu
fixedHeader: false, // sticky header fixedHeader: true, // sticky header
autoHideHeader: false, // auto hide header autoHideHeader: true, // auto hide header
fixSiderbar: false, // sticky siderbar fixSiderbar: true, // sticky siderbar
leftMenuTitle: "EVM 应用商店", // 左侧边栏顶部名称 leftMenuTitle: "EVM 应用商店", // 左侧边栏顶部名称
leftMenuIcon: "", // 左侧边栏顶部Logo leftMenuIcon: "", // 左侧边栏顶部Logo
appSlogan: "EVM,致力于为互联网行业提供物联网解决方案", // 应用宣传文案 appSlogan: "EVM,致力于为互联网行业提供物联网解决方案", // 应用宣传文案
......
/*
* @Author: your name
* @Date: 2021-07-15 09:33:39
* @LastEditTime: 2021-07-15 20:32:40
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: \evm-store\tools\frontend\src\main.js
*/
import Vue from 'vue' import Vue from 'vue'
import App from './App' import App from './App'
import store from './store' import store from './store'
......
import Vue from 'vue' import Vue from "vue";
import Router from 'vue-router' import Router from "vue-router";
import store from '../store' import store from "../store";
import UserLayout from '@/layouts/UserLayout' import UserLayout from "@/layouts/UserLayout";
import BasicLayout from '@/layouts/BasicLayout' import BasicLayout from "@/layouts/BasicLayout";
import BlankLayout from '@/layouts/BlankLayout' import BlankLayout from "@/layouts/BlankLayout";
Vue.use(Router) Vue.use(Router);
const router = new Router({ const router = new Router({
routes: [ routes: [
// user // user
{ {
path: '/user', path: "/user",
component: UserLayout, component: UserLayout,
children: [ children: [
{ path: '/user', redirect: '/user/login' }, { path: "/user", redirect: "/user/login" },
{ path: '/user/login', component: () => import('@/views/User/Login') }, { path: "/user/login", component: () => import("@/views/User/Login") },
{ path: '/user/register', component: () => import('@/views/User/Register') }, {
path: "/user/register",
component: () => import("@/views/User/Register"),
},
], ],
}, },
// app // app
{ {
path: '/', path: "/",
component: BasicLayout, component: BasicLayout,
children: [ children: [
// dashboard // dashboard
{ path: '/', redirect: '/dashboard/analysis' }, { path: "/", redirect: "/dashboard/analysis" },
{ {
path: '/dashboard', path: "/dashboard",
name: 'dashboard', name: "dashboard",
component: BlankLayout, component: BlankLayout,
children: [ children: [
{ path: '/dashboard/analysis', name: 'analysis', component: () => import('@/views/Dashboard/Analysis') }, {
path: "/dashboard/analysis",
name: "analysis",
component: () => import("@/views/Dashboard/Analysis"),
},
// { path: '/dashboard/monitor', name: 'monitor', component: () => import('@/views/Dashboard/Analysis') }, // { path: '/dashboard/monitor', name: 'monitor', component: () => import('@/views/Dashboard/Analysis') },
{ path: '/dashboard/workplace', name: 'workplace', component: () => import('@/views/Dashboard/Workplace') }, {
] path: "/dashboard/workplace",
name: "workplace",
component: () => import("@/views/Dashboard/Workplace"),
},
],
}, },
{ {
path: '/form', path: "/form",
name: 'form', name: "form",
icon: 'form', icon: "form",
component: BlankLayout, component: BlankLayout,
children: [ children: [
{ path: '/form/basic-form', name: 'basicform', component: () => import('@/views/Dashboard/Analysis') },
{ {
path: '/form/step-form', path: "/form/basic-form",
name: 'stepform', name: "basicform",
component: () => import("@/views/Dashboard/Analysis"),
},
{
path: "/form/step-form",
name: "stepform",
component: BlankLayout, component: BlankLayout,
hideChildrenInMenu: true, hideChildrenInMenu: true,
children: [ children: [
{ {
path: '/form/step-form/info', path: "/form/step-form/info",
name: 'info', name: "info",
component: () => import('@/views/Dashboard/Analysis'), component: () => import("@/views/Dashboard/Analysis"),
}, },
] ],
}, },
{ path: '/form/advanced-form', name: 'advancedform', component: () => import('@/views/Dashboard/Analysis') }, {
] path: "/form/advanced-form",
name: "advancedform",
component: () => import("@/views/Dashboard/Analysis"),
},
],
}, },
{ {
path: '/list', path: "/list",
icon: 'table', icon: "table",
name: 'list', name: "list",
component: BlankLayout, component: BlankLayout,
children: [ children: [
{ {
path: '/list/search', path: "/list/search",
name: 'searchlist', name: "searchlist",
component: BlankLayout, component: BlankLayout,
children: [ children: [
{ {
path: '/list/search/articles', path: "/list/search/articles",
name: 'articles', name: "articles",
}, },
{ {
path: '/list/search/projects', path: "/list/search/projects",
name: 'projects', name: "projects",
}, },
{ {
path: '/list/search/applications', path: "/list/search/applications",
name: 'applications', name: "applications",
}, },
] ],
} },
] ],
}, },
{ {
path: '/profile', path: "/profile",
icon: 'profile', icon: "profile",
name: 'profile', name: "profile",
}, },
{ {
path: '/system', path: "/system",
name: 'system', name: "system",
component: BlankLayout, component: BlankLayout,
children: [ children: [
{ {
path: '/system/setting', path: "/system/setting",
name: 'setting', name: "setting",
component: BlankLayout, component: BlankLayout,
children: [ children: [
{ {
path: '/system/setting/menu', path: "/system/setting/menu",
name: 'menu', name: "menu",
component: () => import('@/views/System/Menu') component: () => import("@/views/System/Menu"),
}, },
{ {
path: '/system/setting/module', path: "/system/setting/module",
name: 'module', name: "module",
component: () => import('@/views/System/Role') component: () => import("@/views/System/Role"),
}, },
{ {
path: '/system/setting/config', path: "/system/setting/config",
name: 'config', name: "config",
component: () => import('@/views/System/Role') component: () => import("@/views/System/Role"),
}, },
{ {
path: '/system/setting/dict', path: "/system/setting/dict",
name: 'dict', name: "dict",
component: () => import('@/views/System/Role') component: () => import("@/views/System/Role"),
}, },
{ {
path: '/system/setting/area', path: "/system/setting/area",
name: 'area', name: "area",
component: () => import('@/views/System/Role') component: () => import("@/views/System/Role"),
}, },
{ {
path: '/system/setting/file-manager', path: "/system/setting/file-manager",
name: 'file-manager', name: "file-manager",
component: () => import('@/views/FileManager/FileManager') component: () => import("@/views/FileManager/FileManager"),
}, },
] ],
}, },
{ {
path: '/system/role', path: "/system/role",
name: 'role', name: "role",
component: () => import('@/views/System/Role') component: () => import("@/views/System/Role"),
}, },
{ {
path: '/system/admin', path: "/system/admin",
name: 'admin', name: "admin",
component: () => import('@/views/System/Role') component: () => import("@/views/System/Role"),
} },
] ],
}, },
] ],
}, },
{ {
path: '/application', path: "/application",
icon: 'table', icon: "table",
name: 'application', name: "application",
// redirect: '/application/index', // redirect: '/application/index',
component: BasicLayout, component: BasicLayout,
children: [ children: [
{ path: '/application', redirect: '/application/index' }, { path: "/application", redirect: "/application/index" },
{ path: '/application/index', component: () => import('@/views/Application/Index') }, {
{ path: '/application/manager', component: () => import('@/views/Application/Manager') }, path: "/application/index",
{ path: '/application/form', component: () => import('@/views/Application/Form') }, component: () => import("@/views/Application/Index"),
},
{
path: "/application/manager",
component: () => import("@/views/Application/Manager"),
},
{
path: "/application/form",
component: () => import("@/views/Application/Form"),
},
], ],
} },
] ],
}) });
router.afterEach(() => { router.afterEach(() => {
store.commit('global/UpdateBasicLayoutSpinning', false); store.commit('global/UpdateBasicLayoutSpinning', false);
}); });
export default router export default router;
/*
* @Author: your name
* @Date: 2021-07-15 09:33:39
* @LastEditTime: 2021-07-15 19:07:35
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: \evm-store\tools\frontend\src\store\index.js
*/
import Vue from 'vue' import Vue from 'vue'
import Vuex from 'vuex' import Vuex from 'vuex'
import fm from './file-manager' import fm from './file-manager'
import global from './modules/global' import global from './modules/global'
import globalNav from './modules/global-nav' import globalNav from './modules/global-nav'
import frontendLogin from './modules/frontend-login'
import frontendOpenapi from './modules/frontend-openapi' import frontendOpenapi from './modules/frontend-openapi'
Vue.use(Vuex) Vue.use(Vuex)
...@@ -14,7 +23,8 @@ export default new Vuex.Store({ ...@@ -14,7 +23,8 @@ export default new Vuex.Store({
frontend: { frontend: {
namespaced: true, namespaced: true,
modules: { modules: {
openapi: frontendOpenapi openapi: frontendOpenapi,
login: frontendLogin
} }
}, },
global: { global: {
......
// import Cookies from 'js-cookie' /*
import api from '~a/index' * @Author: your name
import { setStore, removeStore } from '~u/storage' * @Date: 2021-07-15 09:33:39
* @LastEditTime: 2021-07-15 21:14:30
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: \evm-store\tools\frontend\src\store\modules\frontend-login.js
*/
import Cookies from "js-cookie";
import api from "@/utils/request";
const TokenKey = "Authorization";
const state = { const state = {
mobile:'', mobile: "",
// checkMobile: { token: null,
// mobile: '', userinfo: {},
// data: '', // checkMobile: {
// }, // mobile: '',
} // data: '',
// },
};
const actions = { const actions = {
async ['logoutClean']({ commit, rootState: { route: { path } } }, config) { async ["logoutClean"](
const { data: { code, data } } = await api.post('/auth/clean', { ...config }) {
if (code === '0') { commit,
commit('removeAuthToken') rootState: {
} route: { path },
},
}, },
config
} ) {
const {
data: { code, data },
} = await api.post("/auth/clean", { ...config });
if (code === "0") {
commit("removeAuthToken");
}
},
setToken({ commit }, token) {
commit("setToken", token);
},
removeToken({ commit }) {
commit("removeToken");
resetRouter();
},
setUserInfo({ commit }, userinfo) {
commit("setUserInfo", userinfo);
},
removeUserInfo({ commit }, userinfo) {
commit("removeUserInfo", userinfo);
},
};
const mutations = { const mutations = {
["receiveAuthToken"](state, payload) {
['receiveAuthToken'](state, payload) { Cookies.set(TokenKey, payload.access_token, {
setStore('access_token', payload.access_token) expires: payload.expires_in / 86400,
setStore('expires_in', payload.expires_in) });
setStore('token_type', payload.token_type) },
// Cookies.set('token', payload.access_token, { expires: (payload.expires_in / 86400) }); ["removeAuthToken"](state) {
}, Cookies.remove(TokenKey);
['removeAuthToken'](state) { },
removeStore('access_token') ["receiveMobile"](state, payload) {
removeStore('expires_in') state.mobile = payload;
removeStore('token_type') },
// Cookies.remove('token') setToken: (state, token) => {
}, state.token = token;
['receiveMobile'](state, payload) { Cookies.set(TokenKey, token);
state.mobile = payload; },
}, removeToken: (state, token) => {
} state.token = null;
Cookies.remove(TokenKey, token);
},
setUserInfo: (state, name) => {
state.userinfo = name;
Cookies.set("userinfo", name);
},
removeUserInfo: (state, name) => {
state.userinfo = null;
Cookies.remove("userinfo", name);
},
};
const getters = { const getters = {
['getMobile'](state) { ["getMobile"](state) {
return state.mobile return state.mobile;
}, },
} ["getToken"](state) {
return state.token;
},
["getUserInfo"](state) {
return state.userinfo;
},
};
export default { export default {
namespaced: true, namespaced: true,
state, state,
actions, actions,
mutations, mutations,
getters getters,
} };
\ No newline at end of file
import { users } from '@/api/openapi' /*
* @Author: your name
* @Date: 2021-07-15 09:33:39
* @LastEditTime: 2021-07-15 18:36:43
* @LastEditors: your name
* @Description: In User Settings Edit
* @FilePath: \evm-store\tools\frontend\src\store\modules\frontend-openapi.js
*/
import { users } from "@/api/openapi";
const state = { const state = {
loading: false, loading: false,
users: { users: {
data: [], data: [],
pagination: { pagination: {
showSizeChanger: true, showSizeChanger: true,
} },
} },
} };
const actions = { const actions = {
['getUsers']({ commit, state }, config) { ["getUsers"]({ commit, state }, config) {
state.loading = true state.loading = true;
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
users(config).then(response => { users(config)
// console.log(response); .then((response) => {
commit('setUsers', { // console.log(response);
...response, commit("setUsers", {
config ...response,
}) config,
state.loading = false });
resolve() state.loading = false;
}).catch(error => { resolve();
state.loading = false
reject(error)
})
}) })
}, .catch((error) => {
} state.loading = false;
reject(error);
});
});
},
};
const mutations = { const mutations = {
["setUsers"](state, { results, config }) {
['setUsers'](state, { results, config }) { state.users = {
state.users = { data: results,
data: results, pagination: {
pagination: { total: 200,
total: 200, pageSize: config.results,
pageSize: config.results },
} };
} },
} };
}
const getters = { const getters = {
['getUsers'](state) { ["getUsers"](state) {
return state.users; return state.users;
}, },
['loading'](state) { ["loading"](state) {
return state.loading; return state.loading;
}, },
} };
export default { export default {
namespaced: true, namespaced: true,
state, state,
actions, actions,
mutations, mutations,
getters getters,
} };
\ No newline at end of file
import Cookies from "js-cookie";
const TokenKey = "Authorization";
export function getToken() {
return Cookies.get(TokenKey);
}
export function setToken(token) {
return Cookies.set(TokenKey, token);
}
export function removeToken() {
return Cookies.remove(TokenKey);
}
import axios from 'axios' /*
import { message, Modal } from "ant-design-vue"; * @Author: your name
import qs from 'qs'; * @Date: 2021-07-15 09:33:39
* @LastEditTime: 2021-07-15 21:15:15
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: \evm-store\tools\frontend\src\utils\request.js
*/
import axios from 'axios';
import store from "@/store";
import { message } from "ant-design-vue";
import { getToken } from "@/utils/auth";
// create an axios instance // create an axios instance
const service = axios.create({ const service = axios.create({
// baseURL: process.env.BASE_API, // api的base_url baseURL: process.env.BASE_URL, // api的base_url
timeout: 5000, // request timeout timeout: 15000, // request timeout
// responseType: "json", // responseType: "json",
// crossDomain: true, // crossDomain: true,
// xhrFields: { withCredentials: true }, // xhrFields: { withCredentials: true },
...@@ -18,20 +27,10 @@ const service = axios.create({ ...@@ -18,20 +27,10 @@ const service = axios.create({
// request interceptor // request interceptor
service.interceptors.request.use(config => { service.interceptors.request.use(config => {
// Do something before request is sent // Do something before request is sent
// if (getCookies(_CONST.TOKEN)) { if (store.state.frontend.login.token) {
// config.headers['Authorization'] = 'Bearer ' + getCookies(_CONST.TOKEN) // 让每个请求携带token-- ['Authorization']为自定义key 请根据实际情况自行修改 // 让每个请求携带token-- ['Authorization']为自定义key 请根据实际情况自行修改
// } config.headers['Authorization'] = 'Bearer ' + getToken()
// 在发送请求之前做某件事
if (
config.method === "post" ||
config.method === "put" ||
config.method === "delete"
) {
// 序列化
config.data = qs.stringify(config.data);
} }
// console.log('config', config);
return config return config
}, error => { }, error => {
// Do something with request error // Do something with request error
...@@ -56,13 +55,8 @@ service.interceptors.response.use( ...@@ -56,13 +55,8 @@ service.interceptors.response.use(
*/ */
// console.log('error', error) // console.log('error', error)
const res = error.response; const res = error.response;
// console.log(res);
if (res && res.data) { if (res && res.data) {
const { code, error, error_description } = res.data; const { code, msg } = res.data;
// console.info(code)
// console.info(error)
// console.info(error_description)
// 100401:非法的token; 100412:其他客户端登录了; 100413:Token 过期了; // 100401:非法的token; 100412:其他客户端登录了; 100413:Token 过期了;
if (code === 100401 || code === 100412 || code === 100413) { if (code === 100401 || code === 100412 || code === 100413) {
// MessageBox.confirm('操作失败,原因:' + error + ',可以取消继续留在该页面,或者重新登录', '操作提示', { // MessageBox.confirm('操作失败,原因:' + error + ',可以取消继续留在该页面,或者重新登录', '操作提示', {
...@@ -73,6 +67,7 @@ service.interceptors.response.use( ...@@ -73,6 +67,7 @@ service.interceptors.response.use(
// removeCookies(_CONST.TOKEN); // removeCookies(_CONST.TOKEN);
// location.reload();// 为了重新实例化vue-router对象 避免bug // location.reload();// 为了重新实例化vue-router对象 避免bug
// }) // })
message.error(msg, 3);
} else { } else {
let error; let error;
if (!error) { if (!error) {
......
...@@ -8,14 +8,14 @@ ...@@ -8,14 +8,14 @@
:wrapperCol="{ span: 10 }" :wrapperCol="{ span: 10 }"
:required="true" :required="true"
> >
<a-input placeholder="给应用起个名字" /> <a-input v-model="post.app_name" placeholder="给应用起个名字" />
</a-form-item> </a-form-item>
<a-form-item <a-form-item
label="打包算法" label="打包算法"
:labelCol="{ span: 7 }" :labelCol="{ span: 7 }"
:wrapperCol="{ span: 10 }" :wrapperCol="{ span: 10 }"
> >
<a-radio-group v-model="value" @change="onChange"> <a-radio-group v-model="post.algorithm" @change="onChange">
<a-radio-button value="zlib"> zlib </a-radio-button> <a-radio-button value="zlib"> zlib </a-radio-button>
<a-radio-button value="eheatshrink"> eheatshrink </a-radio-button> <a-radio-button value="eheatshrink"> eheatshrink </a-radio-button>
</a-radio-group> </a-radio-group>
...@@ -35,13 +35,14 @@ ...@@ -35,13 +35,14 @@
:required="true" :required="true"
> >
<a-select <a-select
mode="tags" v-model="post.category"
mode="default"
style="width: 100%" style="width: 100%"
placeholder="应用所属类别" placeholder="应用所属类别"
@change="handleChange" @change="handleChange"
> >
<a-select-option v-for="i in 25" :key="(i + 9).toString(36) + i"> <a-select-option v-for="item in categoryList" :key="(item.value + 9).toString(36) + item.value">
{{ (i + 9).toString(36) + i }} {{ item.label }}
</a-select-option> </a-select-option>
</a-select> </a-select>
</a-form-item> </a-form-item>
...@@ -56,8 +57,7 @@ ...@@ -56,8 +57,7 @@
list-type="picture-card" list-type="picture-card"
class="avatar-uploader" class="avatar-uploader"
:show-upload-list="false" :show-upload-list="false"
action="https://www.mocky.io/v2/5cc8019d300000980a055e76" :before-upload="beforeLogoUpload"
:before-upload="beforeUpload"
@change="handleChange" @change="handleChange"
> >
<img v-if="imageUrl" :src="imageUrl" alt="avatar" /> <img v-if="imageUrl" :src="imageUrl" alt="avatar" />
...@@ -73,7 +73,7 @@ ...@@ -73,7 +73,7 @@
:wrapperCol="{ span: 10 }" :wrapperCol="{ span: 10 }"
:required="true" :required="true"
> >
<a-select :default-value="sizeList[0].label" style="width: 120px"> <a-select :default-value="sizeList[0].label" v-model="post.app_screen_size" style="width: 120px">
<a-select-option v-for="item in sizeList" :key="(item.value + 9).toString(36) + item.value" :value="item.label"> <a-select-option v-for="item in sizeList" :key="(item.value + 9).toString(36) + item.value" :value="item.label">
{{ item.label }} {{ item.label }}
</a-select-option> </a-select-option>
...@@ -85,7 +85,7 @@ ...@@ -85,7 +85,7 @@
:wrapperCol="{ span: 10 }" :wrapperCol="{ span: 10 }"
:required="true" :required="true"
> >
<a-select :default-value="portList[0].label" style="width: 120px"> <a-select :default-value="portList[0].label" v-model="post.app_arch" style="width: 120px">
<a-select-option v-for="item in portList" :key="(item.value + 9).toString(36) + item.value" :value="item.label"> <a-select-option v-for="item in portList" :key="(item.value + 9).toString(36) + item.value" :value="item.label">
{{ item.label }} {{ item.label }}
</a-select-option> </a-select-option>
...@@ -96,7 +96,7 @@ ...@@ -96,7 +96,7 @@
:labelCol="{ span: 7 }" :labelCol="{ span: 7 }"
:wrapperCol="{ span: 10 }" :wrapperCol="{ span: 10 }"
> >
<a-textarea rows="4" placeholder="请输入应用介绍" /> <a-textarea v-model="post.remarks" rows="4" placeholder="请输入应用介绍" />
</a-form-item> </a-form-item>
<a-form-item <a-form-item
label="应用源文件" label="应用源文件"
...@@ -107,7 +107,7 @@ ...@@ -107,7 +107,7 @@
<a-upload-dragger <a-upload-dragger
name="file" name="file"
:multiple="true" :multiple="true"
action="https://www.mocky.io/v2/5cc8019d300000980a055e76" :before-upload="beforeUpload"
@change="handleSourceFileChange" @change="handleSourceFileChange"
> >
<p class="ant-upload-drag-icon"> <p class="ant-upload-drag-icon">
...@@ -125,7 +125,7 @@ ...@@ -125,7 +125,7 @@
style="margin-top: 24px" style="margin-top: 24px"
:wrapperCol="{ span: 10, offset: 7 }" :wrapperCol="{ span: 10, offset: 7 }"
> >
<a-button type="primary">提交</a-button> <a-button type="primary" @click="onSumbit">提交</a-button>
<a-button style="margin-left: 8px">保存</a-button> <a-button style="margin-left: 8px">保存</a-button>
</a-form-item> </a-form-item>
</a-form> </a-form>
...@@ -156,6 +156,9 @@ import { ...@@ -156,6 +156,9 @@ import {
} from "ant-design-vue"; } from "ant-design-vue";
import PageHeaderWrapper from "@/components/PageHeaderWrapper"; import PageHeaderWrapper from "@/components/PageHeaderWrapper";
import DescriptionItem from "@/components/DescriptionItem"; import DescriptionItem from "@/components/DescriptionItem";
import { postApplication } from "@/api/openapi";
export default { export default {
name: "BasicForm", name: "BasicForm",
data() { data() {
...@@ -163,10 +166,28 @@ export default { ...@@ -163,10 +166,28 @@ export default {
loading: false, loading: false,
imageUrl: "", imageUrl: "",
value: 1, value: 1,
title: "编辑", title: "添加",
post: { post: {
app_version: '', app_name: null,
app_icon: null,
app_version: null,
category: null,
app_screen_size: null,
app_arch: null,
remarks: null,
logo: null,
fileList: []
}, },
logo: null,
fileList: [],
categoryList: [
{ label: '影音视听', value: 1 },
{ label: '实用工具', value: 2 },
{ label: '图书阅读', value: 3 },
{ label: '学习教育', value: 4 },
{ label: '医疗健康', value: 5 },
{ label: '未定义', value: 6 }
],
sizeList: [ sizeList: [
{ label: '240 * 240', value: 1 }, { label: '240 * 240', value: 1 },
{ label: '390 * 390', value: 2 }, { label: '390 * 390', value: 2 },
...@@ -210,18 +231,42 @@ export default { ...@@ -210,18 +231,42 @@ export default {
ARangePicker: DatePicker.RangePicker, ARangePicker: DatePicker.RangePicker,
}, },
methods: { methods: {
handleUploadChange(info) { handleRemove(file) {
if (info.file.status === "uploading") { const index = this.fileList.indexOf(file);
this.loading = true; const newFileList = this.fileList.slice();
return; newFileList.splice(index, 1);
} this.fileList = newFileList;
if (info.file.status === "done") { },
// Get this url from response in real world. beforeLogoUpload(file) {
getBase64(info.file.originFileObj, (imageUrl) => { this.logo = file;
this.imageUrl = imageUrl;
this.loading = false; return false;
}); },
beforeUpload(file) {
this.fileList = [...this.fileList, file];
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isLt2M) {
this.$message.error("Image must smaller than 2MB!");
} }
return false;
},
handleUpload() {
this.uploading = true;
let formData = new FormData();
this.fileList.forEach(item => {
formData.append("fileList", item.file)
});
formData.append("logo", this.logo.file)
Object.keys(this.post).forEach(k => {
if (this.post[k] && typeof this.post[k] !== "object") {
formData.append(k, this.post[k])
}
});
this.postApplication(formData)
}, },
handleSourceFileChange(info) { handleSourceFileChange(info) {
const status = info.file.status; const status = info.file.status;
...@@ -234,24 +279,30 @@ export default { ...@@ -234,24 +279,30 @@ export default {
this.$message.error(`${info.file.name} file upload failed.`); this.$message.error(`${info.file.name} file upload failed.`);
} }
}, },
beforeUpload(file) {
const isJpgOrPng =
file.type === "image/jpeg" || file.type === "image/png";
if (!isJpgOrPng) {
this.$message.error("You can only upload JPG file!");
}
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isLt2M) {
this.$message.error("Image must smaller than 2MB!");
}
return isJpgOrPng && isLt2M;
},
onChange(e) { onChange(e) {
console.log(`checked = ${e.target.value}`); console.log(`checked = ${e.target.value}`);
}, },
handleChange(value) { handleChange(value) {
console.log(`selected ${value}`); console.log(`selected ${value}`);
}, },
postApplication(formData) {
postApplication(formData).then(res => {
console.log(res)
this.fileList = [];
this.logo = null;
this.post.fileList = [];
this.post.logo = null;
this.uploading = false;
this.$message.success('upload successfully.');
}).catch(err => {
console.log(err)
this.uploading = false;
this.$message.error('upload failed.');
})
},
onSumbit() {
this.handleUpload()
}
}, },
computed: { computed: {
desc() { desc() {
...@@ -259,7 +310,12 @@ export default { ...@@ -259,7 +310,12 @@ export default {
}, },
}, },
created() { created() {
console.log(this.$route.query); const { type } = this.$route.query
if (type && type == "update") {
this.title = "更新"
} else {
this.title = "添加"
}
}, },
}; };
</script> </script>
......
...@@ -179,7 +179,6 @@ import { ...@@ -179,7 +179,6 @@ import {
Field, Field,
yuan, yuan,
MiniProgress MiniProgress
// MiniBar, // MiniBar,
// MiniArea // MiniArea
} from "@/components/Charts"; } from "@/components/Charts";
......
<template> <template>
<div class="ai-login-main"> <div class="ai-login-main">
<div class="ai-login"> <div class="ai-login">
<a-form <a-form :form="form" @submit="handleSubmit">
@submit="handleSubmit"
>
<a-tabs <a-tabs
:animated="false" :animated="false"
:defaultActiveKey="activeKey" :defaultActiveKey="activeKey"
...@@ -17,7 +15,7 @@ ...@@ -17,7 +15,7 @@
{ rules: [{ required: true, message: '请输入用户名!' }] }, { rules: [{ required: true, message: '请输入用户名!' }] },
]" ]"
> >
<a-input placeholder="用户名" size="large"> <a-input v-model="post.account" placeholder="用户名" size="large">
<a-icon type="user" style="color: rgba(0, 0, 0, 0.25)" /> <a-icon type="user" style="color: rgba(0, 0, 0, 0.25)" />
</a-input> </a-input>
</a-form-item> </a-form-item>
...@@ -28,7 +26,12 @@ ...@@ -28,7 +26,12 @@
{ rules: [{ required: true, message: '请输入密码!' }] }, { rules: [{ required: true, message: '请输入密码!' }] },
]" ]"
> >
<a-input type="password" placeholder="密码" size="large"> <a-input
v-model="post.password"
type="password"
placeholder="密码"
size="large"
>
<a-icon type="lock" style="color: rgba(0, 0, 0, 0.25)" /> <a-icon type="lock" style="color: rgba(0, 0, 0, 0.25)" />
</a-input> </a-input>
</a-form-item> </a-form-item>
...@@ -91,6 +94,7 @@ ...@@ -91,6 +94,7 @@
class="submit" class="submit"
type="primary" type="primary"
htmlType="submit" htmlType="submit"
@click="doLogin"
> >
登录 登录
</a-button> </a-button>
...@@ -123,14 +127,21 @@ import { ...@@ -123,14 +127,21 @@ import {
} from "ant-design-vue"; } from "ant-design-vue";
import SendCaptchaButton from "@/components/SendCaptchaButton"; import SendCaptchaButton from "@/components/SendCaptchaButton";
// import { mapGetters } from "vuex"; // import { mapGetters } from "vuex";
import { postLogin } from "@/api/openapi";
export default { export default {
name: "ai-login", name: "ai-login",
data: () => ({ data: () => ({
activeKey: "2", activeKey: "1",
active: [], active: [],
submitting: false, submitting: false,
autoLogin: false, autoLogin: false,
start: false, start: false,
post: {
account: null,
password: null,
},
}), }),
components: { components: {
AForm: Form, AForm: Form,
...@@ -145,7 +156,22 @@ export default { ...@@ -145,7 +156,22 @@ export default {
ACol: Col, ACol: Col,
ASendCaptchaButton: SendCaptchaButton, ASendCaptchaButton: SendCaptchaButton,
}, },
beforeCreate() {
this.form = this.$form.createForm(this, {});
},
methods: { methods: {
doLogin() {
postLogin(this.post)
.then((res) => {
this.$store.commit("frontend/login/setToken", res.data.token);
this.$store.commit("frontend/login/setUserInfo", { uuid: res.data.uuid, name: res.data.name });
message.success(res.msg)
this.$router.push({ path: "/" });
})
.catch((err) => {
message.error(err.msg)
});
},
onSwithAutoLogin(e) { onSwithAutoLogin(e) {
this.autoLogin = e.target.checked; this.autoLogin = e.target.checked;
}, },
...@@ -159,18 +185,16 @@ export default { ...@@ -159,18 +185,16 @@ export default {
this.active.push("captcha"); this.active.push("captcha");
} }
}, },
handleSubmit(e) { handleSubmit() {
window.console.log(e);
this.form.validateFields( this.form.validateFields(
this.active, this.active,
{ {
force: true, force: true,
}, },
(err, values) => { (err, values) => {
window.console.log(values); window.console.log(err, values);
if (!err) { if (!err) {
// console.log("Received values of form: ", values); console.log("Received values of form: ", values);
this.$router.push({ path: "/" });
} }
} }
); );
......
/*
* @Author: your name
* @Date: 2021-07-15 09:33:39
* @LastEditTime: 2021-07-15 18:29:06
* @LastEditors: your name
* @Description: In User Settings Edit
* @FilePath: \evm-store\tools\frontend\vue.config.js
*/
"use strict"; "use strict";
// 基础配置文件 // 基础配置文件
const path = require("path"); const path = require("path");
...@@ -24,7 +32,7 @@ module.exports = { ...@@ -24,7 +32,7 @@ module.exports = {
// change xxx-api/login => mock/login // change xxx-api/login => mock/login
// detail: https://cli.vuejs.org/config/#devserver-proxy // detail: https://cli.vuejs.org/config/#devserver-proxy
"/api/v1": { "/api/v1": {
target: "http://127.0.0.1:5001/", target: "http://127.0.0.1:3000/",
changeOrigin: true, changeOrigin: true,
pathRewrite: {}, pathRewrite: {},
}, },
......
...@@ -6447,6 +6447,11 @@ js-base64@^2.1.8, js-base64@^2.1.9: ...@@ -6447,6 +6447,11 @@ js-base64@^2.1.8, js-base64@^2.1.9:
resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.6.4.tgz#f4e686c5de1ea1f867dbcad3d46d969428df98c4" resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.6.4.tgz#f4e686c5de1ea1f867dbcad3d46d969428df98c4"
integrity sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ== integrity sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==
js-cookie@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-2.2.1.tgz#69e106dc5d5806894562902aa5baec3744e9b2b8"
integrity sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==
js-levenshtein@^1.1.3: js-levenshtein@^1.1.3:
version "1.1.6" version "1.1.6"
resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d" resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d"
......
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