Commit b18bbe25 authored by 智勇's avatar 智勇

联调版本

parent 0d10c77e
# vue-admin-template
> 这是一个 极简的 vue admin 管理后台 它只包含了 Element UI & axios & iconfont & permission control & lint,这些搭建后台必要的东西。
[线上地址](http://panjiachen.github.io/vue-admin-template)
[国内访问](https://panjiachen.gitee.io/vue-admin-template)
## Extra
如果你想要根据用户角色来动态生成侧边栏和 router,你可以使用该分支[permission-control](https://github.com/PanJiaChen/vue-admin-template/tree/permission-control)
本项目基于`webpack4`开发,若还想使用`webpack3`开发,请使用该分支[webpack3](https://github.com/PanJiaChen/vue-admin-template/tree/webpack3)
如果你想使用基于 vue + typescript 的管理后台, 可以看看这个项目: [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template) (鸣谢: [@Armour](https://github.com/Armour))
## 相关项目
[vue-element-admin](https://github.com/PanJiaChen/vue-element-admin)
[electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin)
[vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template)
写了一个系列的教程配套文章,如何从零构建后一个完整的后台项目:
- [手摸手,带你用 vue 撸后台 系列一(基础篇)](https://juejin.im/post/59097cd7a22b9d0065fb61d2)
- [手摸手,带你用 vue 撸后台 系列二(登录权限篇)](https://juejin.im/post/591aa14f570c35006961acac)
- [手摸手,带你用 vue 撸后台 系列三 (实战篇)](https://juejin.im/post/593121aa0ce4630057f70d35)
- [手摸手,带你用 vue 撸后台 系列四(vueAdmin 一个极简的后台基础模板,专门针对本项目的文章,算作是一篇文档)](https://juejin.im/post/595b4d776fb9a06bbe7dba56)
- [手摸手,带你封装一个 vue component](https://segmentfault.com/a/1190000009090836)
## Build Setup
```bash
# Clone project
git clone https://github.com/PanJiaChen/vue-admin-template.git
# Install dependencies
npm install
# 建议不要用cnpm 安装有各种诡异的bug 可以通过如下操作解决npm速度慢的问题
npm install --registry=https://registry.npm.taobao.org
# Serve with hot reload at localhost:9528
npm run dev
# Build for production with minification
npm run build
# Build for production and view the bundle analyzer report
npm run build --report
```
## Demo
![demo](https://github.com/PanJiaChen/PanJiaChen.github.io/blob/master/images/demo.gif)
### Element-Ui 使用 cdn 教程
首先找到 `index.html` ([根目录下](https://github.com/PanJiaChen/vue-admin-template/blob/element-ui-cdn/index.html))
引入 Element 的 css 和 js ,并且引入 vue 。因为 Element-Ui 是依赖 vue 的,所以必须在它之前引入 vue 。
之后找到 [webpack.base.conf.js](https://github.com/PanJiaChen/vue-admin-template/blob/element-ui-cdn/build/webpack.base.conf.js) 加入 `externals` 让 webpack 不打包 vue 和 element
```
externals: {
vue: 'Vue',
'element-ui':'ELEMENT'
}
```
之后还有一个小细节是如果你用了全局对象方式引入 vue,就不需要 手动 `Vue.use(Vuex)` ,它会自动挂载,具体见 [issue](https://github.com/vuejs/vuex/issues/731)
最终你可以使用 `npm run build --report` 查看效果
如图:
![demo](https://panjiachen.github.io/images/element-cdn.png)
**[具体代码](https://github.com/PanJiaChen/vue-admin-template/commit/746aff560932704ae821f82f10b8b2a9681d5177)**
**[对应分支](https://github.com/PanJiaChen/vue-admin-template/tree/element-ui-cdn)**
## Browsers support
Modern browsers and Internet Explorer 10+.
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
| --------- | --------- | --------- | --------- |
| IE10, IE11, Edge| last 2 versions| last 2 versions| last 2 versions
## License
[MIT](https://github.com/PanJiaChen/vue-admin-template/blob/master/LICENSE) license.
Copyright (c) 2017-present PanJiaChen
......@@ -4,5 +4,6 @@ const prodEnv = require('./prod.env')
module.exports = {
NODE_ENV: '"development"',
BASE_API: '"http://yapi.quantgroups.com"',
BASE_API: '"http://boss-ka2.liangkebang.net"',
// BASE_API: '"http://yapi.quantgroups.com"',
}
......@@ -12,7 +12,7 @@ module.exports = {
proxyTable: {},
// Various Dev Server settings
host: 'localhost', // can be overwritten by process.env.HOST
host: '192.168.28.179', // can be overwritten by process.env.HOST
port: 9001, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
autoOpenBrowser: true,
errorOverlay: true,
......
'use strict'
module.exports = {
NODE_ENV: '"production"',
BASE_API: '"https://easy-mock.com/mock/5950a2419adc231f356a6636/vue-admin"',
BASE_API: '"http://boss-ka2.liangkebang.net"',
}
......@@ -17,7 +17,7 @@ Mock.XHR.prototype.send = function() {
// User
Mock.mock(/\/user\/login/, 'post', userAPI.login)
Mock.mock(/\/user\/info/, 'get', userAPI.getInfo)
// Mock.mock(/\/user\/info/, 'get', userAPI.getInfo)
Mock.mock(/\/user\/logout/, 'post', userAPI.logout)
// Table
......
{
"name": "vue-admin-template",
"name": "ka-op-ui",
"version": "3.9.0",
"license": "MIT",
"description": "A vue admin template with Element UI & axios & iconfont & permission control & lint",
"author": "Pan <panfree23@gmail.com>",
"description": "ka联调平台",
"author": "",
"scripts": {
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"start": "npm run dev",
......
......@@ -2,15 +2,18 @@ import request from '@/utils/request'
export function getChannels(data) {
return request({
url: '/mock/229/channel/info',
url: '/channel/info',
method: 'post',
data
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
params: data
})
}
export function saveChannel(data) {
return request({
url: '/mock/229/channel/cfg/info',
url: '/channel/cfg/info',
method: 'post',
data
})
......@@ -18,7 +21,7 @@ export function saveChannel(data) {
export function getChannelDetail(query) {
return request({
url: '/mock/229/channel/cfg/info',
url: '/channel/cfg/info',
method: 'get',
params: query
})
......
......@@ -2,8 +2,7 @@ import request from '@/utils/request'
export function login(username, password) {
return request({
url: '/mock/229/login',
// url: '/user/login',
url: '/login',
method: 'post',
data: {
username,
......@@ -14,8 +13,7 @@ export function login(username, password) {
export function getInfo(token) {
return request({
// url: '/user/info',
url: '/mock/229/user/detail/info',
url: '/user/detail/info',
method: 'get',
params: { token }
})
......@@ -23,7 +21,7 @@ export function getInfo(token) {
export function logout() {
return request({
url: '/mock/229/logout',
url: '/logout',
method: 'delete'
})
}
......@@ -2,7 +2,7 @@ import request from '@/utils/request'
export function getOrders(query) {
return request({
url: '/mock/229/order/Info',
url: '/order/list',
method: 'get',
params: query
})
......@@ -10,7 +10,7 @@ export function getOrders(query) {
export function approve(data) {
return request({
url: '/mock/229/order/approve',
url: '/order/approve',
method: 'post',
data
})
......@@ -18,8 +18,16 @@ export function approve(data) {
export function getOrderDetail(query) {
return request({
url: '/mock/229/order/status/info',
url: '/order/status/info',
method: 'get',
params: query
})
}
export function cancelLoan(data) {
return request({
url: '/order/cancel/loan',
method: 'post',
params: data
})
}
......@@ -2,24 +2,27 @@ import request from '@/utils/request'
export function clearInfo(data) {
return request({
url: '/mock/229/user/info/clean',
url: '/user/info/clean',
method: 'post',
data
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
params: data
})
}
export function closeOrder(data) {
return request({
url: '/mock/229/user/order/clean',
url: '/user/order/clean',
method: 'post',
data
params: data
})
}
export function forceCloseOrder(data) {
return request({
url: '/mock/229/order/settle',
url: '/order/settle',
method: 'post',
data
params: data
})
}
......@@ -23,7 +23,7 @@ import '@/permission' // permission control
* it will intercept your request, so you won't see the request in the network.
* If you remove `../mock` it will automatically request easy-mock data.
*/
import '../mock' // simulation data
// import '../mock' // simulation data
Vue.use(ElementUI, { locale })
......
......@@ -10,6 +10,24 @@ NProgress.configure({ showSpinner: false })// NProgress configuration
const whiteList = ['/login'] // 不重定向白名单
router.beforeEach((to, from, next) => {
NProgress.start()
// if (whiteList.indexOf(to.path) !== -1) {
// next()
// } else {
// if (store.getters.roles.length === 0) {
// store.dispatch('GetInfo').then(res => { // 拉取用户信息
// next()
// }).catch(() => {
// store.dispatch('FedLogOut').then(() => {
// // Message.error(err || 'Verification failed, please login again')
// next(`/login`) // 否则全部重定向到登录页
// // next({ path: '/' })
// })
// })
// } else {
// next()
// }
// }
if (getToken()) {
if (to.path === '/login') {
next({ path: '/' })
......
......@@ -16,9 +16,6 @@ const user = {
SET_NAME: (state, name) => {
state.name = name
},
SET_AVATAR: (state, avatar) => {
state.avatar = avatar
},
SET_ROLES: (state, roles) => {
state.roles = roles
}
......@@ -31,8 +28,8 @@ const user = {
return new Promise((resolve, reject) => {
login(username, userInfo.password).then(response => {
const data = response.data
setToken(data.token)
commit('SET_TOKEN', data.token)
setToken(data)
commit('SET_TOKEN', data)
resolve()
}).catch(error => {
reject(error)
......@@ -45,15 +42,13 @@ const user = {
return new Promise((resolve, reject) => {
getInfo(state.token).then(response => {
const data = response.data
// data.roles = data.roleInfo.role
data.roles = data.userInfo.userName.length > 10 ? ['admin'] : ['channel']
data.roles = data.rank.indexOf('ADMINISTRATOR') !== -1 ? ['admin'] : ['channel']
if (data.roles && data.roles.length > 0) { // 验证返回的roles是否是一个非空数组
commit('SET_ROLES', data.roles)
} else {
reject('getInfo: roles must be a non-null array !')
}
commit('SET_NAME', data.userInfo.userName)
commit('SET_AVATAR', data.avatar)
commit('SET_NAME', data.userInfo.userId)
resolve(response)
}).catch(error => {
reject(error)
......
import Cookies from 'js-cookie'
const TokenKey = 'ka_op_token'
const TokenKey = 'SESSION'
export function getToken() {
return Cookies.get(TokenKey)
......
......@@ -6,6 +6,7 @@ import { getToken } from '@/utils/auth'
// 创建axios实例
const service = axios.create({
baseURL: process.env.BASE_API, // api 的 base_url
withCredentials: true,
timeout: 1000 * 10 // 请求超时时间
})
......@@ -13,7 +14,7 @@ const service = axios.create({
service.interceptors.request.use(
config => {
if (store.getters.token) {
config.headers['X-Token'] = getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
config.headers['SESSION'] = getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
}
return config
},
......@@ -26,40 +27,40 @@ service.interceptors.request.use(
// response 拦截器
service.interceptors.response.use(
response => response.data,
// response => {
// /**
// * code为非20000是抛错 可结合自己业务进行修改
// */
// const res = response.data
// if (res.code !== 20000) {
// Message({
// message: res.message,
// type: 'error',
// duration: 5 * 1000
// })
// response => response.data,
response => {
/**
* code为非20000是抛错 可结合自己业务进行修改
*/
const res = response.data
if (res.code !== 200000) {
Message({
message: res.message,
type: 'error',
duration: 5 * 1000
})
// // 50008:非法的token; 50012:其他客户端登录了; 50014:Token 过期了;
// if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
// MessageBox.confirm(
// '你已被登出,可以取消继续留在该页面,或者重新登录',
// '确定登出',
// {
// confirmButtonText: '重新登录',
// cancelButtonText: '取消',
// type: 'warning'
// }
// ).then(() => {
// store.dispatch('FedLogOut').then(() => {
// location.reload() // 为了重新实例化vue-router对象 避免bug
// })
// })
// }
// return Promise.reject('error')
// } else {
// return response.data
// }
// },
// 50008:非法的token; 50012:其他客户端登录了; 500003:Token 过期了;
if (res.code === 501002 || res.code === 500003) {
MessageBox.confirm(
'你已被登出,可以取消继续留在该页面,或者重新登录',
'确定登出',
{
confirmButtonText: '重新登录',
cancelButtonText: '取消',
type: 'warning'
}
).then(() => {
store.dispatch('FedLogOut').then(() => {
location.reload() // 为了重新实例化vue-router对象 避免bug
})
})
}
return Promise.reject('error')
} else {
return response.data
}
},
error => {
console.log('err' + error) // for debug
Message({
......
......@@ -39,7 +39,7 @@
</el-table>
<pagination v-show="count>0" :total="count" :page.sync="page" :limit.sync="listQuery.pageSize" @pagination="getChannels" />
<el-card class="box-card" >
<el-card v-show="channel.addInfo.approveCallBackUrl" class="box-card">
<el-card v-permission="['admin']" v-show="channel.basicInfo.channelId" class="box-card" style="margin-bottom:20px;float:left;width:45%;margin-right:1%">
<div slot="header" >
......@@ -140,7 +140,7 @@ export default {
},
channels: [],
channel: { basicInfo: {}, addInfo: {}},
count: undefined,
count: 1,
page: 1,
roles: undefined
}
......@@ -157,18 +157,25 @@ export default {
}
}
this.listQuery.pageNumber = this.page - 1
// this.channels = []
// this.count = 1
getChannels(this.listQuery).then(res => {
this.channels = res.data.content
this.count = res.data.totalElements
if (this.channels.length > 0) {
this.$refs.myTable.setCurrentRow(this.channels[0])
if (res.data) {
this.channels = res.data.content
this.count = res.data.totalElements
if (this.channels.length > 0) {
this.$refs.myTable.setCurrentRow(this.channels[0])
}
}
})
},
handleCurrentChange(val) {
this.channel = { basicInfo: {}, addInfo: {}}
getChannelDetail({ channelId: val.channelId }).then(res => {
this.channel = res.data
if (res.data) {
this.channel = res.data
}
})
},
......@@ -187,6 +194,9 @@ export default {
// },
savevData() {
if (!this.roles.includes('admin')) {
this.channel.basicInfo = { channelId: this.channel.basicInfo.channelId }
}
saveChannel(this.channel).then(() => {
this.$notify({
title: '成功',
......@@ -194,7 +204,7 @@ export default {
type: 'success',
duration: 1000
})
this.getChannels()
this.handleCurrentChange(this.channel.basicInfo)
})
}
}
......
......@@ -28,42 +28,42 @@
Sign in
</el-button>
</el-form-item>
<div class="tips">
<!-- <div class="tips">
<span style="margin-right:20px;">username: admin</span>
<span> password: admin</span>
</div>
</div> -->
</el-form>
</div>
</template>
<script>
import { isvalidUsername } from '@/utils/validate'
// import { isvalidUsername } from '@/utils/validate'
export default {
name: 'Login',
data() {
const validateUsername = (rule, value, callback) => {
if (!isvalidUsername(value)) {
callback(new Error('请输入正确的用户名'))
} else {
callback()
}
}
const validatePass = (rule, value, callback) => {
if (value.length < 5) {
callback(new Error('密码不能小于5位'))
} else {
callback()
}
}
// const validateUsername = (rule, value, callback) => {
// if (!isvalidUsername(value)) {
// callback(new Error('请输入正确的用户名'))
// } else {
// callback()
// }
// }
// const validatePass = (rule, value, callback) => {
// if (value.length < 5) {
// callback(new Error('密码不能小于5位'))
// } else {
// callback()
// }
// }
return {
loginForm: {
username: 'admin',
password: 'admin'
username: 'admin01',
password: '123'
},
loginRules: {
username: [{ required: true, trigger: 'blur', validator: validateUsername }],
password: [{ required: true, trigger: 'blur', validator: validatePass }]
// username: [{ required: true, trigger: 'blur', validator: validateUsername }],
// password: [{ required: true, trigger: 'blur', validator: validatePass }]
},
loading: false,
pwdType: 'password',
......
......@@ -2,9 +2,10 @@
<div class="app-container">
<div class="filter-container" style="padding-bottom:20px">
<el-input v-model="listQuery.channelOrderNumber" placeholder="订单号" clearable style="width: 200px;" class="filter-item" @keyup.enter.native="getOrders"/>
<el-select v-model="listQuery.channelId" placeholder="渠道号" clearable style="width: 200px" class="filter-item" >
<el-input v-model="listQuery.channelId" placeholder="渠道号" clearable style="width: 200px;" class="filter-item" @keyup.enter.native="getOrders"/>
<!-- <el-select v-model="listQuery.channelId" placeholder="渠道号" clearable style="width: 200px" class="filter-item" >
<el-option v-for="item in channelOptions" :key="item.key" :label="item.display_name" :value="item.key"/>
</el-select>
</el-select> -->
<el-button class="filter-item" type="primary" icon="el-icon-search" @click="getOrders">查询</el-button>
</div>
......@@ -13,10 +14,11 @@
:data="orders"
border
max-height="300"
size="medium"
fit
highlight-current-row
style="margin-bottom:20px"
@current-change="handleCurrentChange">
>
<el-table-column label="ID" type="index" align="center" width="65"/>
......@@ -27,11 +29,12 @@
<el-table-column label="操作" align="center" >
<template slot-scope="scope">
<el-button v-for="item in scope.row.opt" :key="item.action" size="medium" @click="handleOption(scope.row,item)">{{ item.name }}</el-button>
<el-button v-for="item in scope.row.opt" :key="item.action" size="mini" @click="handleOption(scope.row,item)">{{ item.name }}</el-button>
</template>
</el-table-column>
</el-table>
<pagination v-show="count>0" :total="count" :page.sync="page" :limit.sync="listQuery.pageSize" @pagination="getOrders" />
<el-card class="box-card" >
<el-tabs v-model="activeName" type="card" @tab-click="handleClick">
......@@ -84,25 +87,43 @@
</div>
</el-dialog>
<el-dialog :visible.sync="dialogDeleteVisible" :data="order" title="Cancel">
<span >
确定要 {{ opt }} {{ order.channelId }} 吗?
</span>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogDeleteVisible = false">取消</el-button>
<el-button type="primary" @click="cancelLoan()">确定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { getOrders, getOrderDetail, approve } from '@/api/order'
import { getOrders, getOrderDetail, approve, cancelLoan } from '@/api/order'
import Pagination from '@/components/Pagination'
export default {
components: { Pagination },
filters: {
},
data() {
return {
activeName: 'first',
dialogTitle: '',
listQuery: {},
count: 1,
page: 1,
listQuery: {
pageNumber: 0,
pageSize: 10
},
dialogFormVisible: false,
dialogDeleteVisible: false,
opt: '',
orders: [],
order: {},
orderDetail: [],
channel: { basicInfo: {}, addInfo: {}},
approveData: {},
typeOptions: [
{ key: '0', display_name: '存管' },
......@@ -130,16 +151,17 @@ export default {
}
}
getOrders(this.listQuery).then(res => {
this.orders = res.data
this.orders = res.data.content
this.count = res.data.totalElements
if (this.orders.length > 0) {
this.$refs.myTable.setCurrentRow(this.orders[0])
}
// if (this.orders.length > 0) {
// this.$refs.myTable.setCurrentRow(this.orders[0])
// }
// for test
for (const o in this.orders) {
this.orders[o].opt = o % 2 === 0 ? [{ action: 'audit', name: '审核' }, { action: 'loan', name: '放款' }] : [{ action: 'audit', name: '审核' }]
}
// for (const o in this.orders) {
// this.orders[o].opt = o % 2 === 0 ? [{ action: 'audit', name: '审核' }, { action: 'loan', name: '放款' }] : [{ action: 'audit', name: '审核' }]
// }
})
},
......@@ -159,6 +181,21 @@ export default {
isPass: '0'
}
}
if (opt.action === 'cancel') {
this.opt = '贷前关单'
this.dialogDeleteVisible = true
}
},
cancelLoan() {
cancelLoan({ channelOrderNumber: this.order.channelOrderNumber }).then(() => {
this.$notify({
title: '关单完毕',
type: 'success',
duration: 1000
})
})
},
handleApprove(data) {
......
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