xy 3 years ago
parent c720f088cf
commit 8239264290

@ -0,0 +1,17 @@
import request from '@/utils/request'
export function getList(params){
return request({
method:'get',
url:'/api/merchant/balance/get-list',
params
})
}
export function balance(params){
return request({
method:'get',
url:'/api/merchant/balance',
params
})
}

@ -0,0 +1,17 @@
import request from '@/utils/request'
export function getList(params){
return request({
method:'get',
url:'/api/merchant/order/get-list',
params
})
}
export function itemAction(params){
return request({
method:'get',
url:'/api/merchant/order/item-action',
params
})
}

@ -72,8 +72,7 @@ export default {
}
},
btnWidth: {
type: Number,
default: 190
type: Number
},
//

@ -1,108 +1,133 @@
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
/* Layout */
import Layout from '@/layout'
/**
* Note: sub-menu only appear when route children.length >= 1
* Detail see: https://panjiachen.github.io/vue-element-admin-site/guide/essentials/router-and-nav.html
*
* hidden: true if set true, item will not show in the sidebar(default is false)
* alwaysShow: true if set true, will always show the root menu
* if not set alwaysShow, when item has more than one children route,
* it will becomes nested mode, otherwise not show the root menu
* redirect: noRedirect if set noRedirect will no redirect in the breadcrumb
* name:'router-name' the name is used by <keep-alive> (must set!!!)
* meta : {
roles: ['admin','editor'] control the page roles (you can set multiple roles)
title: 'title' the name show in sidebar and breadcrumb (recommend set)
icon: 'svg-name'/'el-icon-x' the icon show in the sidebar
breadcrumb: false if set false, the item will hidden in breadcrumb(default is true)
activeMenu: '/example/list' if set path, the sidebar will highlight the path you set
}
*/
/**
* constantRoutes
* a base page that does not have permission requirements
* all roles can be accessed
*/
export const constantRoutes = [{
path: '/login',
component: () => import('@/views/login/index'),
hidden: true
},
{
path: '/404',
component: () => import('@/views/404'),
hidden: true
},
{
path: '/info',
component: Layout,
children: [{
path: 'password',
component: () => import('@/views/system/password'),
name: '密码修改',
meta: {
title: '密码修改'
}
}],
hidden: true
},
{
path: '/',
component: Layout,
redirect: '/dashboard',
children: [{
path: 'dashboard',
name: '系统首页',
component: () => import('@/views/dashboard/index'),
meta: {
title: '系统首页',
icon: 'dashboard'
}
}, ]
}
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
/* Layout */
import Layout from '@/layout'
/**
* Note: sub-menu only appear when route children.length >= 1
* Detail see: https://panjiachen.github.io/vue-element-admin-site/guide/essentials/router-and-nav.html
*
* hidden: true if set true, item will not show in the sidebar(default is false)
* alwaysShow: true if set true, will always show the root menu
* if not set alwaysShow, when item has more than one children route,
* it will becomes nested mode, otherwise not show the root menu
* redirect: noRedirect if set noRedirect will no redirect in the breadcrumb
* name:'router-name' the name is used by <keep-alive> (must set!!!)
* meta : {
roles: ['admin','editor'] control the page roles (you can set multiple roles)
title: 'title' the name show in sidebar and breadcrumb (recommend set)
icon: 'svg-name'/'el-icon-x' the icon show in the sidebar
breadcrumb: false if set false, the item will hidden in breadcrumb(default is true)
activeMenu: '/example/list' if set path, the sidebar will highlight the path you set
}
*/
/**
* constantRoutes
* a base page that does not have permission requirements
* all roles can be accessed
*/
export const constantRoutes = [{
path: '/login',
component: () => import('@/views/login/index'),
hidden: true
},
{
path: '/404',
component: () => import('@/views/404'),
hidden: true
},
{
path: '/info',
component: Layout,
children: [{
path: 'password',
component: () => import('@/views/system/password'),
name: '密码修改',
meta: {
title: '密码修改'
}
}],
hidden: true
},
{
path: '/dashboard',
component: Layout,
redirect: '/dashboard',
children: [{
path: '',
name: '系统首页',
component: () => import('@/views/dashboard/index'),
meta: {
title: '系统首页',
icon: 'dashboard'
}
}]
},
{
path: '/order',
component: Layout,
children: [{
path: '',
name: '订单管理',
component: () => import('@/views/order/index'),
meta: {
title: '订单管理',
icon: 'el-icon-s-order'
}
}]
},
{
path: '/finance',
component: Layout,
children: [{
path: '',
name: '财务中心',
component: () => import('@/views/finance/index'),
meta: {
title: '财务中心',
icon: 'el-icon-s-finance'
}
}]
}
]
/**
* asyncRoutes
* the routes that need to be dynamically loaded based on user roles
*/
export const asyncRoutes = [
// 404 page must be placed at the end !!!
{
path: '*',
redirect: '/404',
hidden: true
}
]
const createRouter = () => new Router({
// mode: 'history', // require service support
scrollBehavior: () => ({
y: 0
}),
routes: constantRoutes
})
const router = createRouter()
// Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
export function resetRouter() {
const newRouter = createRouter()
router.matcher = newRouter.matcher // reset router
}
/**
* asyncRoutes
* the routes that need to be dynamically loaded based on user roles
*/
export const asyncRoutes = [
// 404 page must be placed at the end !!!
{
path: '*',
redirect: '/404',
hidden: true
}
]
const createRouter = () => new Router({
// mode: 'history', // require service support
scrollBehavior: () => ({
y: 0
}),
routes: constantRoutes
})
const router = createRouter()
// Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
export function resetRouter() {
const newRouter = createRouter()
router.matcher = newRouter.matcher // reset router
}
export default router

@ -76,35 +76,35 @@ const componentHandler = (path) => {
}
return loadView(path)
}
/**
* 后台查询的菜单数据拼装成路由格式的数据
* @param routes
*/
export function generaMenu(routes, data) {
data.forEach(item => {
if (item.url === "/") {
routes.push({
path: '/',
component: Layout,
redirect: '/dashboard',
children: [{
path: 'dashboard',
name: '系统首页',
component: () => import('@/views/dashboard/index'),
meta: {
title: '系统首页',
icon: 'dashboard'
}
}]
})
} else if (item.url === "##") {
/**
* 后台查询的菜单数据拼装成路由格式的数据
* @param routes
*/
export function generaMenu(routes, data) {
data.forEach(item => {
if (item.url === "/") {
routes.push({
path: '/',
component: Layout,
redirect: '/dashboard',
children: [{
path: 'dashboard',
name: '系统首页',
component: () => import('@/views/dashboard/index'),
meta: {
title: '系统首页',
icon: 'dashboard'
}
}]
})
} else if (item.url === "##") {
routes.push({
path: item.path,
component: Layout,
children: [{
path: item.path,
name: item.name,
name: item.name,
component: item.url === '#' ? Layout : loadView(item.path),
meta: {
title: item.name,
@ -113,33 +113,33 @@ export function generaMenu(routes, data) {
icon: item.icon
}
}]
})
} else {
var path = item.url;
if (item.path != "null" && item.path != null && item.path != "") {
path = item.path
}
const menu = {
path: (path === '#' ? item.id + '_key' : path),
redirect: (item.children.length > 0 ? "noRedirect" : ""),
component: item.url === '#' ? Layout : loadView(item.url),
// hidden: true,
children: [],
name: 'menu_' + item.id,
meta: {
title: item.name,
id: item.id,
roles: ['admin'],
icon: item.icon
}
}
if (item.children) {
generaMenu(menu.children, item.children)
}
routes.push(menu)
}
})
})
} else {
var path = item.url;
if (item.path != "null" && item.path != null && item.path != "") {
path = item.path
}
const menu = {
path: (path === '#' ? item.id + '_key' : path),
redirect: (item.children.length > 0 ? "noRedirect" : ""),
component: item.url === '#' ? Layout : loadView(item.url),
// hidden: true,
children: [],
name: 'menu_' + item.id,
meta: {
title: item.name,
id: item.id,
roles: ['admin'],
icon: item.icon
}
}
if (item.children) {
generaMenu(menu.children, item.children)
}
routes.push(menu)
}
})
}
const mutations = {
@ -178,9 +178,9 @@ const actions = {
commit
}, roles) {
return new Promise(resolve => {
const loadMenuData = []
Object.assign(loadMenuData, asyncRoutes)
generaMenu(asyncRoutes, loadMenuData)
//const loadMenuData = []
//Object.assign(loadMenuData, asyncRoutes)
//generaMenu(asyncRoutes, loadMenuData)
let accessedRoutes
if (roles.includes('admin')) {
// alert(JSON.stringify(asyncRoutes))

@ -14,7 +14,7 @@ let loading ;
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
// withCredentials: true, // send cookies when cross-domain requests
timeout: 5000, // request timeout
timeout: 10000, // request timeout
isLoading:true
})

@ -1,365 +1,362 @@
<template>
<div>
<div class="statistics">
<div style="display: flex;justify-content: flex-end;margin-bottom: 10px;">
<el-date-picker v-model="dateMonth" value-format="yyyy-MM" type="month" @change="loadData" placeholder="选择月份">
</el-date-picker>
</div>
<panel-group :totaldata="list" />
</div>
<div class="chart">
<div style="display: flex;justify-content: flex-end;margin-bottom: 10px;">
<el-date-picker v-model="year" value-format="yyyy" type="year" @change="getCharData" placeholder="选择年份">
</el-date-picker>
</div>
<div>
<el-row :gutter="16">
<el-col :xs="12" :sm="12" :lg="8">
<div class="chart-wrapper">
<div class="chart-title">
<router-link to="/toolbox/exception">人员借阅统计</router-link>
</div>
<ybar-chart :chartData="lineUserData" />
</div>
</el-col>
<el-col :xs="12" :sm="12" :lg="8">
<div class="chart-wrapper">
<div class="chart-title">
<router-link to="/toolbox/exception">部门借阅统计</router-link>
</div>
<ybar-chart :chartData="lineDeptData" />
</div>
</el-col>
<el-col :xs="12" :sm="12" :lg="8">
<div class="chart-wrapper">
<div class="chart-title">
<router-link to="/toolbox/exception">书籍借阅统计</router-link>
</div>
<ybar-chart :chartData="lineBookData" />
</div>
</el-col>
</el-row>
</div>
</div>
<el-row :gutter="16" style="margin-top: 20px;">
<el-col :xs="12" :sm="12" :lg="8">
<div class="chart-wrapper">
<div class="chart-title">
<router-link to="/toolbox/exception">类目借阅统计</router-link>
</div>
<ybar-chart :chartData="lineTypeData" />
</div>
</el-col>
<el-col :xs="16" :sm="16" :lg="16">
<div class="chart-wrapper">
<div class="chart-title">
<router-link to="/toolbox/exception">月度借阅趋势</router-link>
</div>
<line-chart :chartData="lineArr" />
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import echarts from "echarts"
import PanelGroup from './components/PanelGroup'
import LineChart from './components/LineChart.vue'
import YbarChart from './components/YbarChart.vue'
import {
getChartsData,
getCounts
} from "../../api/dashboard.js"
export default {
components: {
PanelGroup,
LineChart,
YbarChart
},
data() {
return {
dateMonth: "",
year: "",
col: '',
line: '',
business_data: [],
collect_data: [],
list: {},
customerArr: [],
orderArr: [],
chartData: {},
lineTypeData: {
xArr: [],
yArr: []
},
lineUserData: {
xArr: [],
yArr: []
},
lineDeptData: {
xArr: [],
yArr: []
},
lineBookData: {
xArr: [],
yArr: []
},
lineArr: {
xArr: [],
legendArr: ["借阅次数"],
series: [{
name: '借阅次数',
type: 'line',
stack: 'Total',
data: []
}]
}
}
},
watch: {},
methods: {
async loadData() {
await getCounts({
date: this.dateMonth
}).then((res) => {
this.list = res;
}).catch(error => {
});
},
async getCharData() {
await getChartsData({
year: this.year
}).then((res) => {
var xArrMonth = [];
var yArrData = [];
for (var i = 1; i <= 12; i++) {
xArrMonth.push(i + "月");
let d = res.month.filter(function(item) {
return item.month == i;
})
if (d.length > 0)
yArrData.push(d[0].total);
else
yArrData.push(0);
}
this.lineArr.xArr = xArrMonth;
this.lineArr.series[0].data = yArrData;
let xTypeArr = [];
let yTypeArr = [];
for (var mod of res.type) {
xTypeArr.push(mod.total)
yTypeArr.push(mod.type.name)
}
this.lineTypeData = {
xArr: xTypeArr,
yArr: yTypeArr
}
xTypeArr = [];
yTypeArr = [];
for (var mod of res.person) {
xTypeArr.push(mod.total)
yTypeArr.push(mod.user?.name)
}
this.lineUserData = {
xArr: xTypeArr,
yArr: yTypeArr
}
xTypeArr = [];
yTypeArr = [];
for (var mod of res.book) {
xTypeArr.push(mod.total)
yTypeArr.push(mod.book?.name)
}
this.lineBookData = {
xArr: xTypeArr,
yArr: yTypeArr
}
xTypeArr = [];
yTypeArr = [];
for (var mod of res.department) {
xTypeArr.push(mod.total)
yTypeArr.push(mod.department?.name)
}
this.lineDeptData = {
xArr: xTypeArr,
yArr: yTypeArr
}
}).catch(error => {
})
}
},
created() {
this.dateMonth = this.$moment().format("YYYY-MM");
this.year = this.$moment().format("YYYY");
this.loadData();
this.getCharData();
},
mounted() {
window.onresize = () => {
this.col.resize()
this.line.resize()
}
},
destroyed() {
window.onresize = null
}
}
</script>
<style lang="scss" scoped>
.chart-wrapper {
background: #fff;
padding: 15px;
}
.statistics {
display: flex;
flex-direction: column;
margin-top: 20px;
&-title {
padding-left: 6px;
}
&-content {
text-align: center;
font-size: 13px;
&-top {
&__num {
font-weight: 600;
}
&__name {
font-size: 10px;
color: rgb(140, 140, 140);
}
}
&-bottom {
display: flex;
justify-content: space-between;
&-left {
&__num {
font-weight: 600;
}
&__name {
font-size: 10px;
color: rgb(140, 140, 140);
}
}
&-right {
&__num {
font-weight: 600;
}
&__name {
font-size: 10px;
color: rgb(140, 140, 140);
}
}
}
}
&>div {
flex: 1;
margin-right: 20px;
&:last-child {
margin-right: 0;
}
}
}
.chart {
display: flex;
margin-top: 20px;
flex-direction: column;
.chartBox {
display: flex;
.chartItem {
width: 49%;
.chartItemTitle {
font-size: 16px;
margin-bottom: 20px;
}
#col-chart {
background: #fff;
border-radius: 10px;
flex: 1;
margin-right: 20px;
padding: 20px;
box-sizing: border-box;
min-height: 400px;
width: 100%;
}
#line-chart {
background: #fff;
border-radius: 10px;
flex: 1;
padding: 20px;
box-sizing: border-box;
min-height: 400px;
}
}
}
}
<template>
<div>
<div class="statistics">
<div style="display: flex;justify-content: flex-end;margin-bottom: 10px;">
<el-date-picker v-model="dateMonth" value-format="yyyy-MM" type="month" @change="loadData" placeholder="选择月份">
</el-date-picker>
</div>
<!-- <panel-group :totaldata="list" />-->
</div>
<!-- <div class="chart">-->
<!-- <div style="display: flex;justify-content: flex-end;margin-bottom: 10px;">-->
<!-- <el-date-picker v-model="year" value-format="yyyy" type="year" @change="getCharData" placeholder="选择年份">-->
<!-- </el-date-picker>-->
<!-- </div>-->
<!-- <div>-->
<!-- <el-row :gutter="16">-->
<!-- <el-col :xs="12" :sm="12" :lg="8">-->
<!-- <div class="chart-wrapper">-->
<!-- <div class="chart-title">-->
<!-- <router-link to="/toolbox/exception">人员借阅统计</router-link>-->
<!-- </div>-->
<!-- <ybar-chart :chartData="lineUserData" />-->
<!-- </div>-->
<!-- </el-col>-->
<!-- <el-col :xs="12" :sm="12" :lg="8">-->
<!-- <div class="chart-wrapper">-->
<!-- <div class="chart-title">-->
<!-- <router-link to="/toolbox/exception">部门借阅统计</router-link>-->
<!-- </div>-->
<!-- <ybar-chart :chartData="lineDeptData" />-->
<!-- </div>-->
<!-- </el-col>-->
<!-- <el-col :xs="12" :sm="12" :lg="8">-->
<!-- <div class="chart-wrapper">-->
<!-- <div class="chart-title">-->
<!-- <router-link to="/toolbox/exception">书籍借阅统计</router-link>-->
<!-- </div>-->
<!-- <ybar-chart :chartData="lineBookData" />-->
<!-- </div>-->
<!-- </el-col>-->
<!-- </el-row>-->
<!-- </div>-->
<!-- </div>-->
<!-- <el-row :gutter="16" style="margin-top: 20px;">-->
<!-- <el-col :xs="12" :sm="12" :lg="8">-->
<!-- <div class="chart-wrapper">-->
<!-- <div class="chart-title">-->
<!-- <router-link to="/toolbox/exception">类目借阅统计</router-link>-->
<!-- </div>-->
<!-- <ybar-chart :chartData="lineTypeData" />-->
<!-- </div>-->
<!-- </el-col>-->
<!-- <el-col :xs="16" :sm="16" :lg="16">-->
<!-- <div class="chart-wrapper">-->
<!-- <div class="chart-title">-->
<!-- <router-link to="/toolbox/exception">月度借阅趋势</router-link>-->
<!-- </div>-->
<!-- <line-chart :chartData="lineArr" />-->
<!-- </div>-->
<!-- </el-col>-->
<!-- </el-row>-->
</div>
</template>
<script>
import echarts from "echarts"
import PanelGroup from './components/PanelGroup'
import LineChart from './components/LineChart.vue'
import YbarChart from './components/YbarChart.vue'
import {
getChartsData,
getCounts
} from "../../api/dashboard.js"
export default {
components: {
PanelGroup,
LineChart,
YbarChart
},
data() {
return {
dateMonth: "",
year: "",
col: '',
line: '',
business_data: [],
collect_data: [],
list: {},
customerArr: [],
orderArr: [],
chartData: {},
lineTypeData: {
xArr: [],
yArr: []
},
lineUserData: {
xArr: [],
yArr: []
},
lineDeptData: {
xArr: [],
yArr: []
},
lineBookData: {
xArr: [],
yArr: []
},
lineArr: {
xArr: [],
legendArr: ["借阅次数"],
series: [{
name: '借阅次数',
type: 'line',
stack: 'Total',
data: []
}]
}
}
},
watch: {},
methods: {
async loadData() {
await getCounts({
date: this.dateMonth
}).then((res) => {
this.list = res;
}).catch(error => {
});
},
async getCharData() {
await getChartsData({
year: this.year
}).then((res) => {
var xArrMonth = [];
var yArrData = [];
for (var i = 1; i <= 12; i++) {
xArrMonth.push(i + "月");
let d = res.month.filter(function(item) {
return item.month == i;
})
if (d.length > 0)
yArrData.push(d[0].total);
else
yArrData.push(0);
}
this.lineArr.xArr = xArrMonth;
this.lineArr.series[0].data = yArrData;
let xTypeArr = [];
let yTypeArr = [];
for (var mod of res.type) {
xTypeArr.push(mod.total)
yTypeArr.push(mod.type.name)
}
this.lineTypeData = {
xArr: xTypeArr,
yArr: yTypeArr
}
xTypeArr = [];
yTypeArr = [];
for (var mod of res.person) {
xTypeArr.push(mod.total)
yTypeArr.push(mod.user?.name)
}
this.lineUserData = {
xArr: xTypeArr,
yArr: yTypeArr
}
xTypeArr = [];
yTypeArr = [];
for (var mod of res.book) {
xTypeArr.push(mod.total)
yTypeArr.push(mod.book?.name)
}
this.lineBookData = {
xArr: xTypeArr,
yArr: yTypeArr
}
xTypeArr = [];
yTypeArr = [];
for (var mod of res.department) {
xTypeArr.push(mod.total)
yTypeArr.push(mod.department?.name)
}
this.lineDeptData = {
xArr: xTypeArr,
yArr: yTypeArr
}
}).catch(error => {
})
}
},
created() {
this.dateMonth = this.$moment().format("YYYY-MM");
this.year = this.$moment().format("YYYY");
//this.loadData();
//this.getCharData();
},
mounted() {
},
destroyed() {
//window.onresize = null
}
}
</script>
<style lang="scss" scoped>
.chart-wrapper {
background: #fff;
padding: 15px;
}
.statistics {
display: flex;
flex-direction: column;
margin-top: 20px;
&-title {
padding-left: 6px;
}
&-content {
text-align: center;
font-size: 13px;
&-top {
&__num {
font-weight: 600;
}
&__name {
font-size: 10px;
color: rgb(140, 140, 140);
}
}
&-bottom {
display: flex;
justify-content: space-between;
&-left {
&__num {
font-weight: 600;
}
&__name {
font-size: 10px;
color: rgb(140, 140, 140);
}
}
&-right {
&__num {
font-weight: 600;
}
&__name {
font-size: 10px;
color: rgb(140, 140, 140);
}
}
}
}
&>div {
flex: 1;
margin-right: 20px;
&:last-child {
margin-right: 0;
}
}
}
.chart {
display: flex;
margin-top: 20px;
flex-direction: column;
.chartBox {
display: flex;
.chartItem {
width: 49%;
.chartItemTitle {
font-size: 16px;
margin-bottom: 20px;
}
#col-chart {
background: #fff;
border-radius: 10px;
flex: 1;
margin-right: 20px;
padding: 20px;
box-sizing: border-box;
min-height: 400px;
width: 100%;
}
#line-chart {
background: #fff;
border-radius: 10px;
flex: 1;
padding: 20px;
box-sizing: border-box;
min-height: 400px;
}
}
}
}
</style>

@ -0,0 +1,90 @@
<template>
<div>
<div >
<div ref="lxHeader">
<LxHeader icon="md-apps" text="财务管理" style="margin-bottom: 10px; border: 0px; margin-top: 15px">
<div slot="content"></div>
<slot>
<div style="display: flex;align-items: center;">
<template v-for="(val,key) in balance">
<el-card shadow="hover" style="margin-right: 10px">
<div style="display: flex;flex-direction: column;justify-content: center;">
<div style="font-weight: 600">
{{ balanceFormat(key) }}
</div>
<div style="text-align: center;">
{{ val }}
</div>
</div>
</el-card>
</template>
</div>
</slot>
</LxHeader>
</div>
</div>
<xy-table :table-item="table" :list="data">
<template v-slot:btns><div></div></template>
</xy-table>
</div>
</template>
<script>
import LxHeader from '@/components/LxHeader/index.vue'
import {getList,balance} from '@/api/finance'
export default {
components: {
LxHeader
},
data() {
return {
select:{
page:1,
rows:10,
},
balance:{},
data:[],
table:[
]
}
},
methods: {
async getBalance(){
let res = await balance()
console.log(res)
this.balance = res
},
async getList(){
let res = await getList(this.select)
console.log(res)
this.data = res.data
}
},
computed: {
balanceFormat(){
return function(key){
let map = new Map([
['balance','余额'],
['fees','充值'],
['recharges','退款'],
['refunds','佣金']
])
return map.get(key)
}
}
},
mounted() {
this.getList()
this.getBalance()
}
}
</script>
<style scoped lang="scss">
</style>

@ -1,251 +1,243 @@
<template>
<div class="login-container">
<vue-particles color="#ffffff" :particleOpacity="0.7" :particlesNumber="80" shapeType="circle" :particleSize="4"
linesColor="#ffffff" :linesWidth="1" :lineLinked="true" :lineOpacity="0.4" :linesDistance="150" :moveSpeed="3"
:hoverEffect="true" hoverMode="grab" :clickEffect="true" clickMode="push"> </vue-particles>
<el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" auto-complete="on"
label-position="left">
<div class="title-container">
<h3 class="title">{{title}}</h3>
</div>
<el-form-item prop="username">
<span class="svg-container">
<svg-icon icon-class="user" />
</span>
<el-input ref="username" v-model="loginForm.username" placeholder="请输入登录名" name="username" type="text"
tabindex="1" auto-complete="on" />
</el-form-item>
<el-form-item prop="password">
<span class="svg-container">
<svg-icon icon-class="password" />
</span>
<el-input :key="passwordType" ref="password" v-model="loginForm.password" :type="passwordType"
placeholder="请输入密码" name="password" tabindex="2" auto-complete="on" @keyup.enter.native="handleLogin" />
<span class="show-pwd" @click="showPwd">
<svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" />
</span>
</el-form-item>
<el-button :loading="loading" type="primary" style="width:100%;margin-bottom:30px;"
@click.native.prevent="handleLogin">登录</el-button>
</el-form>
</div>
</template>
<script>
import {
validUsername
} from '@/utils/validate'
const defaultSettings = require('../../../src/settings.js')
export default {
name: 'Login',
data() {
const validateUsername = (rule, value, callback) => {
if (!validUsername(value)) {
callback(new Error('请正确输入登录名'))
} else {
callback()
}
}
const validatePassword = (rule, value, callback) => {
if (value.length < 6) {
callback(new Error('密码输入错误'))
} else {
callback()
}
}
return {
title: "",
loginForm: {
username: '',
password: ''
},
loginRules: {
username: [{
required: true,
trigger: 'blur',
validator: validateUsername
}],
password: [{
required: true,
trigger: 'blur',
validator: validatePassword
}]
},
loading: false,
passwordType: 'password',
redirect: undefined
}
},
watch: {
$route: {
handler: function(route) {
this.redirect = route.query && route.query.redirect
},
immediate: true
}
},
created() {
this.title = defaultSettings.title;
},
methods: {
showPwd() {
if (this.passwordType === 'password') {
this.passwordType = ''
} else {
this.passwordType = 'password'
}
this.$nextTick(() => {
this.$refs.password.focus()
})
<template>
<div class="login-container">
<vue-particles color="#ffffff" :particleOpacity="0.7" :particlesNumber="80" shapeType="circle" :particleSize="4"
linesColor="#ffffff" :linesWidth="1" :lineLinked="true" :lineOpacity="0.4" :linesDistance="150" :moveSpeed="3"
:hoverEffect="true" hoverMode="grab" :clickEffect="true" clickMode="push"> </vue-particles>
<el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" auto-complete="on"
label-position="left">
<div class="title-container">
<h3 class="title">{{title}}</h3>
</div>
<el-form-item prop="username">
<span class="svg-container">
<svg-icon icon-class="user" />
</span>
<el-input ref="username" v-model="loginForm.username" placeholder="请输入登录名" name="username" type="text"
tabindex="1" auto-complete="on" />
</el-form-item>
<el-form-item prop="password">
<span class="svg-container">
<svg-icon icon-class="password" />
</span>
<el-input :key="passwordType" ref="password" v-model="loginForm.password" :type="passwordType"
placeholder="请输入密码" name="password" tabindex="2" auto-complete="on" @keyup.enter.native="handleLogin" />
<span class="show-pwd" @click="showPwd">
<svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" />
</span>
</el-form-item>
<el-button :loading="loading" type="primary" style="width:100%;margin-bottom:30px;"
@click.native.prevent="handleLogin">登录</el-button>
</el-form>
</div>
</template>
<script>
import {
validUsername
} from '@/utils/validate'
const defaultSettings = require('../../../src/settings.js')
export default {
name: 'Login',
data() {
const validateUsername = (rule, value, callback) => {
if (!validUsername(value)) {
callback(new Error('请正确输入登录名'))
} else {
callback()
}
}
return {
title: "",
loginForm: {
username: '',
password: ''
},
loginRules: {
username: [{
required: true,
trigger: 'blur',
validator: validateUsername
}],
password: [{
required: true,
trigger: 'blur',
}]
},
loading: false,
passwordType: 'password',
redirect: undefined
}
},
watch: {
$route: {
handler: function(route) {
this.redirect = route.query && route.query.redirect
},
immediate: true
}
},
created() {
this.title = defaultSettings.title;
},
methods: {
showPwd() {
if (this.passwordType === 'password') {
this.passwordType = ''
} else {
this.passwordType = 'password'
}
this.$nextTick(() => {
this.$refs.password.focus()
})
},
//
handleLogin() {
this.$refs.loginForm.validate(valid => {
if (valid) {
this.loading = true
this.$store.dispatch('user/login', this.loginForm).then(() => {
this.$router.push({
path: this.redirect || '/'
})
this.loading = false
}).catch(() => {
this.loading = false
})
} else {
console.log('error submit!!')
return false
}
})
}
}
}
</script>
<style lang="scss">
#particles-js {
width: 100%;
height: 99%;
position: absolute;
}
/* 修复input 背景不协调 和光标变色 */
/* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */
$bg:#122583;
$light_gray:#122583;
$cursor: #122583;
@supports (-webkit-mask: none) and (not (cater-color: $cursor)) {
.login-container .el-input input {
color: $cursor;
}
}
/* reset element-ui css */
.login-container {
.el-input {
display: inline-block;
height: 47px;
width: 85%;
input {
background: transparent;
border: 0px;
-webkit-appearance: none;
border-radius: 0px;
padding: 12px 5px 12px 15px;
color: $light_gray;
height: 47px;
caret-color: $cursor;
&:-webkit-autofill {
//box-shadow: 0 0 0px 1000px $bg inset !important;
//-webkit-text-fill-color: $cursor !important;
}
}
}
.el-form-item {
border: 1px solid rgba(255, 255, 255, 0.1);
background: rgba(0, 0, 0, 0.1);
border-radius: 5px;
color: #454545;
}
}
</style>
<style lang="scss" scoped>
$bg:#122583;
$dark_gray:#122583;
$light_gray:#122583;
.login-container {
min-height: 100%;
width: 100%;
//background-color: $bg;
background: url("../../assets/bg.png") no-repeat;
overflow: hidden;
.login-form {
position: relative;
width: 520px;
max-width: 100%;
padding: 20px 35px 0;
margin: 160px auto;
overflow: hidden;
background-color: #fff;
}
.tips {
font-size: 14px;
color: #fff;
margin-bottom: 10px;
span {
&:first-of-type {
margin-right: 16px;
}
}
}
.svg-container {
padding: 6px 5px 6px 15px;
color: $dark_gray;
vertical-align: middle;
width: 30px;
display: inline-block;
}
.title-container {
position: relative;
.title {
font-size: 26px;
color: $light_gray;
margin: 0px auto 40px auto;
text-align: center;
font-weight: bold;
}
}
.show-pwd {
position: absolute;
right: 10px;
top: 7px;
font-size: 16px;
color: $dark_gray;
cursor: pointer;
user-select: none;
}
}
//
handleLogin() {
this.$refs.loginForm.validate(valid => {
if (valid) {
this.loading = true
this.$store.dispatch('user/login', this.loginForm).then(() => {
this.$router.push({
path: this.redirect || '/'
})
this.loading = false
}).catch(() => {
this.loading = false
})
} else {
console.log('error submit!!')
return false
}
})
}
}
}
</script>
<style lang="scss">
#particles-js {
width: 100%;
height: 99%;
position: absolute;
}
/* 修复input 背景不协调 和光标变色 */
/* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */
$bg:#122583;
$light_gray:#122583;
$cursor: #122583;
@supports (-webkit-mask: none) and (not (cater-color: $cursor)) {
.login-container .el-input input {
color: $cursor;
}
}
/* reset element-ui css */
.login-container {
.el-input {
display: inline-block;
height: 47px;
width: 85%;
input {
background: transparent;
border: 0px;
-webkit-appearance: none;
border-radius: 0px;
padding: 12px 5px 12px 15px;
color: $light_gray;
height: 47px;
caret-color: $cursor;
&:-webkit-autofill {
//box-shadow: 0 0 0px 1000px $bg inset !important;
//-webkit-text-fill-color: $cursor !important;
}
}
}
.el-form-item {
border: 1px solid rgba(255, 255, 255, 0.1);
background: rgba(0, 0, 0, 0.1);
border-radius: 5px;
color: #454545;
}
}
</style>
<style lang="scss" scoped>
$bg:#122583;
$dark_gray:#122583;
$light_gray:#122583;
.login-container {
min-height: 100%;
width: 100%;
//background-color: $bg;
background: url("../../assets/bg.png") no-repeat;
overflow: hidden;
.login-form {
position: relative;
width: 520px;
max-width: 100%;
padding: 20px 35px 0;
margin: 160px auto;
overflow: hidden;
background-color: #fff;
}
.tips {
font-size: 14px;
color: #fff;
margin-bottom: 10px;
span {
&:first-of-type {
margin-right: 16px;
}
}
}
.svg-container {
padding: 6px 5px 6px 15px;
color: $dark_gray;
vertical-align: middle;
width: 30px;
display: inline-block;
}
.title-container {
position: relative;
.title {
font-size: 26px;
color: $light_gray;
margin: 0px auto 40px auto;
text-align: center;
font-weight: bold;
}
}
.show-pwd {
position: absolute;
right: 10px;
top: 7px;
font-size: 16px;
color: $dark_gray;
cursor: pointer;
user-select: none;
}
}
</style>

@ -0,0 +1,116 @@
<template>
<div>
<div >
<div ref="lxHeader">
<LxHeader icon="md-apps" text="订单管理" style="margin-bottom: 10px; border: 0px; margin-top: 15px">
<div slot="content"></div>
<slot>
<div style="display: flex;align-items: center;">
<div style="margin-right: 10px;">是否包含历史记录</div>
<el-switch v-model="select.show_history" :active-value="1" :inactive-value="0"></el-switch>
<Button type="primary" @click="getList" style="margin-left: 10px">查询</Button>
</div>
</slot>
</LxHeader>
</div>
</div>
<xy-table :table-item="table" :list="data">
<template v-slot:btns><div></div></template>
</xy-table>
</div>
</template>
<script>
import LxHeader from '@/components/LxHeader/index.vue'
import {getList} from '@/api/order'
export default {
components: {
LxHeader
},
data() {
return {
select:{
page:1,
rows:10,
show_history:0
},
data:[],
table:[
{
label:'客户姓名',
sortable:false,
prop:'member_name',
width:160
},
{
label:'客户电话',
sortable:false,
prop:'member_phone',
width: 200
},
{
label:'预产期',
sortable:false,
prop:'member_due_date',
width: 180
},
{
label:'产品类型',
sortable:false,
prop:'product_type.name',
width: 180
},
{
label:'状态',
sortable:false,
prop:'state_name',
width:120
},
{
label:'操作',
sortable:false,
align:'left',
customFn:row => {
let map = new Map([
['follow_by_merchant','el-icon-s-comment'],
['accept_by_merchant','el-icon-s-promotion'],
['return_by_merchant','el-icon-refresh-left'],
['confirm_by_merchant','el-icon-check'],
['mark_cancel_by_merchant','el-icon-circle-close'],
['finish_by_merchant','el-icon-edit-outline']
])
let btns = []
if(typeof row?.merchant_actions == 'object'){
for(let key in row.merchant_actions){
btns.push(
<el-button size="mini" type="primary" icon={map.get(key)} plain>{row.merchant_actions[key]}</el-button>
)
}
}
return btns
}
}
]
}
},
methods: {
async getList(){
let res = await getList(this.select)
console.log(res)
this.data = res.data
}
},
computed: {},
mounted() {
this.getList()
}
}
</script>
<style scoped lang="scss">
</style>
Loading…
Cancel
Save