Browse Source

修改首页和新增发票管理页面

master
liaoxinyu 1 year ago
parent
commit
e157c5fc93
  1. 13
      src/api/home.js
  2. 37
      src/api/invoice.js
  3. 35
      src/components/charts/bar.vue
  4. 64
      src/components/charts/pie.vue
  5. 66
      src/view/customer/wxulist.vue
  6. 110
      src/view/invoice/headlist.vue
  7. 158
      src/view/invoice/reqlist.vue
  8. 118
      src/view/single-page/home/example.vue
  9. 141
      src/view/single-page/home/home.vue

13
src/api/home.js

@ -0,0 +1,13 @@
import axios from '@/libs/api.request'
/**
* 获取发票申请列表数据
* @returns {wx.RequestTask | never}
*/
export const getHome = (params) => {
return axios.request({
url: 'Index/statistics',
method: 'get',
params: params
})
}

37
src/api/invoice.js

@ -0,0 +1,37 @@
import axios from '@/libs/api.request'
/**
* 获取发票申请列表数据
* @returns {wx.RequestTask | never}
*/
export const getinvoiceList = (params) => {
return axios.request({
url: 'InvoiceIssuance/index',
method: 'get',
params: params
})
}
/**
* 获取发票项目选项
* @returns {wx.RequestTask | never}
*/
export const getIndexData = (params) => {
return axios.request({
url: 'InvoiceIssuance/getIndexData',
method: 'get',
params: params
})
}
/**
* 获取发票抬头数据
* @returns {wx.RequestTask | never}
*/
export const getInvoiceHead = (params) => {
return axios.request({
url: 'InvoiceHead/index',
method: 'get',
params: params
})
}

35
src/components/charts/bar.vue

@ -1,5 +1,5 @@
<template>
<div ref="dom" class="charts chart-bar"></div>
<div ref="dom" class="charts chart-bar"></div>
</template>
<script>
@ -19,13 +19,28 @@ export default {
dom: null
}
},
mounted () {
this.$nextTick(() => {
this.initChart()
on(window, 'resize', this.resize)
})
},
watch: {
value: {
deep: true,
handler () {
this.initChart() //
}
}
},
beforeDestroy () {
off(window, 'resize', this.resize)
},
methods: {
resize () {
this.dom.resize()
}
},
mounted () {
this.$nextTick(() => {
},
initChart () {
let xAxisData = Object.keys(this.value)
let seriesData = Object.values(this.value)
let option = {
@ -46,13 +61,11 @@ export default {
type: 'bar'
}]
}
this.dom = echarts.init(this.$refs.dom, 'tdTheme')
if (!this.dom) {
this.dom = echarts.init(this.$refs.dom, 'tdTheme')
}
this.dom.setOption(option)
on(window, 'resize', this.resize)
})
},
beforeDestroy () {
off(window, 'resize', this.resize)
}
}
}
</script>

64
src/components/charts/pie.vue

@ -1,5 +1,5 @@
<template>
<div ref="dom" class="charts chart-pie"></div>
<div ref="dom" class="charts chart-pie"></div>
</template>
<script>
@ -19,14 +19,29 @@ export default {
dom: null
}
},
mounted () {
this.$nextTick(() => {
this.initChart()
on(window, 'resize', this.resize)
})
},
watch: {
value: {
deep: true,
handler () {
this.initChart() //
}
}
},
beforeDestroy () {
off(window, 'resize', this.resize)
},
methods: {
resize () {
this.dom.resize()
}
},
mounted () {
this.$nextTick(() => {
let legend = this.value.map(_ => _.name)
},
initChart () {
let legend = this.value.map(item => item.name)
let option = {
title: {
text: this.text,
@ -42,29 +57,26 @@ export default {
left: 'left',
data: legend
},
series: [
{
type: 'pie',
radius: '55%',
center: ['50%', '60%'],
data: this.value,
itemStyle: {
emphasis: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
series: [{
name: 'Access From',
type: 'pie',
radius: '55%',
center: ['50%', '60%'],
data: this.value,
itemStyle: {
emphasis: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
]
}]
}
this.dom = echarts.init(this.$refs.dom, 'tdTheme')
this.dom.setOption(option)
on(window, 'resize', this.resize)
})
},
beforeDestroy () {
off(window, 'resize', this.resize)
if (!this.dom) {
this.dom = echarts.init(this.$refs.dom, 'tdTheme')
}
this.dom.setOption(option) //
}
}
}
</script>

66
src/view/customer/wxulist.vue

@ -1,36 +1,35 @@
<template>
<div id="wxulist">
<div id="wxulist">
<!-- 查询条件 -->
<Row>
<Col span="24">
<Card class="margin-bottom-10">
<Form inline>
<FormItem class="margin-bottom-0">
<Input v-model="searchConf.phone" placeholder="输入手机号码查询"></Input>
</FormItem>
<FormItem class="margin-bottom-0">
<Button type="primary" @click="search">{{ $t('find_button') }}/{{ $t('refresh_button') }}</Button>
</FormItem>
</Form>
</Card>
</Col>
</Row>
<Row>
<Col span="24">
<Card class="margin-bottom-10">
<Form inline>
<FormItem class="margin-bottom-0">
<Input v-model="searchConf.phone" @on-enter="search" clearable placeholder="输入手机号码查询"></Input>
</FormItem>
<FormItem class="margin-bottom-0">
<Button type="primary" @click="search">{{ $t('find_button') }}/{{ $t('refresh_button') }}</Button>
</FormItem>
</Form>
</Card>
</Col>
</Row>
<Row>
<Col span="24">
<Card>
<!-- 用户列表 -->
<div>
<Table :loading="listLoading" :columns="columnsList" :data="tableData" stripe disabled-hover></Table>
</div>
<div class="margin-top-15" style="text-align: center">
<Page :total="tableShow.listCount" :current="tableShow.currentPage" :page-size="tableShow.pageSize" @on-change="changePage" @on-page-size-change="changeSize" show-elevator show-sizer show-total></Page>
</div>
</Card>
</Col>
</Row>
</div>
<Row>
<Col span="24">
<Card>
<!-- 用户列表 -->
<div>
<Table :loading="listLoading" :columns="columnsList" :data="tableData" stripe disabled-hover></Table>
</div>
<div class="margin-top-15" style="text-align: center">
<Page :total="tableShow.listCount" :current="tableShow.currentPage" :page-size="tableShow.pageSize" @on-change="changePage" @on-page-size-change="changeSize" show-elevator show-sizer show-total></Page>
</div>
</Card>
</Col>
</Row>
</div>
</template>
<style lang="less" scoped>
@ -221,9 +220,10 @@ export default {
getList({
page: vm.tableShow.currentPage,
size: vm.tableShow.pageSize,
type: vm.searchConf.type,
keywords: vm.searchConf.keywords,
status: vm.searchConf.status
key: vm.searchConf.phone
// type: vm.searchConf.type,
// keywords: vm.searchConf.keywords,
// status: vm.searchConf.status
}).then(response => {
vm.tableData = response.data.data.list
vm.tableShow.listCount = response.data.data.count

110
src/view/invoice/headlist.vue

@ -0,0 +1,110 @@
<template>
<div>
<Row>
<Col span="24">
<Card class="margin-bottom-10">
<Form inline>
<FormItem class="margin-bottom-0">
<Input v-model="pucode_id" @on-enter="search" clearable placeholder="输入用户编码查询"></Input>
</FormItem>
<FormItem class="margin-bottom-0">
<Button type="primary" @click="search">{{ $t('find_button') }}/{{ $t('refresh_button') }}</Button>
</FormItem>
</Form>
</Card>
</Col>
</Row>
<Row>
<Col span="24">
<Card>
<!-- 用户列表 -->
<div>
<Table :loading="listLoading" :columns="columnsList" :data="tableData" stripe disabled-hover></Table>
</div>
<div class="margin-top-15" style="text-align: center">
<Page :total="count" :current="page" :page-size="size" @on-change="changePage" @on-page-size-change="changeSize" show-elevator show-sizer show-total></Page>
</div>
</Card>
</Col>
</Row>
</div>
</template>
<script>
import { getInvoiceHead } from '@/api/invoice'
export default {
name: 'reqlist',
data () {
return {
size: 10,
page: 1,
count: 0,
tableData: [],
listLoading: false,
pucode_id: '',
columnsList: [
{ title: 'id', align: 'center', key: 'id', minWidth: 80 },
{ title: '用户编码', align: 'center', key: 'pucode', minWidth: 100 },
{
title: '微信用户头像',
align: 'center',
key: 'id',
minWidth: 100,
render: (h, params) => {
return h('img', {
attrs: {
src: params.row.headimgurl,
style: 'width:72px;height:72px;'
}
})
}
},
{ title: '微信用户名', align: 'center', key: 'wechat_user_name', minWidth: 100 },
{ title: '电话', align: 'center', key: 'telephone', minWidth: 100 },
{ title: '地址', align: 'center', key: 'address', minWidth: 100 },
{ title: '抬头类型', align: 'center', key: 'type', minWidth: 100 },
{ title: '抬头名称', align: 'center', key: 'title', minWidth: 100 },
{ title: '税号', align: 'center', key: 'tax_number', minWidth: 100 },
{ title: '开户行', align: 'center', key: 'bank_name', minWidth: 100 },
{ title: '银行账号', align: 'center', key: 'bank_account', minWidth: 100 },
{ title: '创建时间', align: 'center', key: 'create_time', minWidth: 80 }
]
}
},
created () {
this.InvoiceHead()
},
methods: {
InvoiceHead () {
let data = {
page: this.page,
size: this.size,
pucode: this.pucode_id
}
this.listLoading = true
getInvoiceHead(data).then(response => {
this.tableData = response.data.data.list
this.count = response.data.data.count
this.listLoading = false
})
},
search () {
this.page = 1
this.InvoiceHead()
},
//
changePage (page) {
this.page = page
this.InvoiceHead()
},
//
changeSize (size) {
this.size = size
this.InvoiceHead()
}
}
}
</script>
<style>
</style>

158
src/view/invoice/reqlist.vue

@ -0,0 +1,158 @@
<template>
<div>
<!-- 查询条件 -->
<Row>
<Col span="24">
<Card class="margin-bottom-10">
<Form inline>
<FormItem class="margin-bottom-0">
<Input v-model="phone" @on-clear="phone_clear" clearable placeholder="输入手机号码查询"></Input>
</FormItem>
<FormItem class="margin-bottom-0">
<Input v-model="pucode_id" @on-clear="pucode_clear" clearable placeholder="用户编号查询"></Input>
</FormItem>
<FormItem class="margin-bottom-0">
<Select v-model="merge_id" clearable style="width:200px" @on-clear="merge_clear" placeholder="请选择合并开票">
<Option v-for="item in cityList" :value="item.value" :key="item.value">{{ item.label }}</Option>
</Select>
</FormItem>
<FormItem class="margin-bottom-0">
<Select v-model="project_id" clearable style="width:200px" @on-clear="project_clear" placeholder="请选择开票项目">
<Option v-for="item in projectList" :value="item.value" :key="item.value">{{ item.text }}</Option>
</Select>
</FormItem>
<FormItem class="margin-bottom-0">
<Button type="primary" @click="search">{{ $t('find_button') }}/{{ $t('refresh_button') }}</Button>
</FormItem>
</Form>
</Card>
</Col>
</Row>
<Row>
<Col span="24">
<Card>
<!-- 用户列表 -->
<div>
<Table :loading="listLoading" :columns="columnsList" :data="tableData" stripe disabled-hover></Table>
</div>
<div class="margin-top-15" style="text-align: center">
<Page :total="listCount" :current="page" :page-size="size" @on-change="changePage" @on-page-size-change="changeSize" show-elevator show-sizer show-total></Page>
</div>
</Card>
</Col>
</Row>
</div>
</template>
<script>
import { getinvoiceList, getIndexData } from '@/api/invoice'
export default {
name: 'reqlist',
data () {
return {
size: 10,
page: 1,
listCount: 0,
tableData: [],
listLoading: false,
phone: '',
pucode_id: '',
project_id: '',
merge_id: '',
cityList: [{ value: '0', label: '不合并' }, { value: '1', label: '合并' }],
projectList: [],
columnsList: [
{ title: 'id', align: 'center', key: 'id', minWidth: 80 },
{ title: '用户编号', align: 'center', key: 'pucode', width: 130 },
{ title: '手机号码', align: 'center', key: 'mobile', width: 150 },
{ title: '邮箱号', align: 'center', key: 'email', width: 200 },
{ title: '抬头类型', align: 'center', key: 'head_type', width: 100 },
{ title: '抬头名称', align: 'center', key: 'head_title', width: 100 },
{ title: '开票项目', align: 'center', key: 'project_itle', width: 100 },
{ title: '合并开票', align: 'center', key: 'merge', minWidth: 100 },
{ title: '状态', align: 'center', key: 'status', width: 100 },
{ title: '开票金额', align: 'center', key: 'amount', width: 100 },
{ title: '创建时间', align: 'center', key: 'create_time', width: 110 },
{ title: '到期时间', align: 'center', key: 'expire_time', width: 100 },
{ title: '开票时间', align: 'center', key: 'issuance_time', width: 110 },
{ title: '作废时间', align: 'center', key: 'cancel_time', width: 110 }
]
}
},
created () {
this.getinvoiceList()
this.getIndexData()
},
mounted () {
window.addEventListener('keydown', this.handleKeyDown)
},
beforeDestroy () {
//
window.removeEventListener('keydown', this.handleKeyDown)
},
methods: {
handleKeyDown (event) {
if (event.key === 'Enter') {
//
this.search()
}
},
//
getinvoiceList () {
let data = {
page: this.page,
size: this.size,
pucode: this.pucode_id,
project_id: this.project_id ? +this.project_id : '',
mobile: this.phone ? +this.phone : '',
merge: this.merge_id ? +this.merge_id : ''
}
this.listLoading = true
getinvoiceList(data).then(response => {
this.tableData = response.data.data.list
this.listCount = response.data.data.count
this.listLoading = false
})
},
//
getIndexData () {
getIndexData().then(response => {
this.projectList = response.data.data
})
},
merge_clear () {
this.merge_id = ''
},
project_clear () {
this.project_id = ''
},
phone_clear () {
this.phone = ''
},
pucode_clear () {
this.pucode_id = ''
},
search () {
this.page = 1
this.getinvoiceList()
},
handleEnter (event) {
console.log(event)
},
//
changePage (page) {
this.page = page
this.getinvoiceList()
},
//
changeSize (size) {
this.size = size
this.getinvoiceList()
}
}
}
</script>
<style>
</style>

118
src/view/single-page/home/example.vue

@ -1,5 +1,5 @@
<template>
<div ref="dom"></div>
<div ref="dom"></div>
</template>
<script>
@ -12,76 +12,87 @@ export default {
dom: null
}
},
mounted () {
this.$nextTick(() => {
this.initChart()
on(window, 'resize', this.resize)
})
},
beforeDestroy () {
off(window, 'resize', this.resize)
},
methods: {
resize () {
this.dom.resize()
}
},
mounted () {
const option = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
label: {
backgroundColor: '#6a7985'
},
initChart () {
const option = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
label: {
backgroundColor: '#6a7985'
}
}
}
},
grid: {
top: '3%',
left: '1.2%',
right: '1%',
bottom: '3%',
containLabel: true
},
xAxis: [
{
},
grid: {
top: '3%',
left: '1.2%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: [{
type: 'category',
boundaryGap: false,
data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
}
],
yAxis: [
{
}],
yAxis: [{
type: 'value'
}
],
series: [
{
}],
series: [{
name: '运营商/网络服务',
type: 'line',
stack: '总量',
areaStyle: { normal: {
color: '#2d8cf0'
} },
areaStyle: {
normal: {
color: '#2d8cf0'
}
},
data: [120, 132, 101, 134, 90, 230, 210]
},
{
name: '银行/证券',
type: 'line',
stack: '总量',
areaStyle: { normal: {
color: '#10A6FF'
} },
areaStyle: {
normal: {
color: '#10A6FF'
}
},
data: [257, 358, 278, 234, 290, 330, 310]
},
{
name: '游戏/视频',
type: 'line',
stack: '总量',
areaStyle: { normal: {
color: '#0C17A6'
} },
areaStyle: {
normal: {
color: '#0C17A6'
}
},
data: [379, 268, 354, 269, 310, 478, 358]
},
{
name: '餐饮/外卖',
type: 'line',
stack: '总量',
areaStyle: { normal: {
color: '#4608A6'
} },
areaStyle: {
normal: {
color: '#4608A6'
}
},
data: [320, 332, 301, 334, 390, 330, 320]
},
{
@ -94,21 +105,20 @@ export default {
position: 'top'
}
},
areaStyle: { normal: {
color: '#398DBF'
} },
areaStyle: {
normal: {
color: '#398DBF'
}
},
data: [820, 645, 546, 745, 872, 624, 258]
}
]
}
this.$nextTick(() => {
this.dom = echarts.init(this.$refs.dom)
]
}
if (!this.dom) {
this.dom = echarts.init(this.$refs.dom)
}
this.dom.setOption(option)
on(window, 'resize', this.resize)
})
},
beforeDestroy () {
off(window, 'resize', this.resize)
}
}
}
</script>

141
src/view/single-page/home/home.vue

@ -1,43 +1,45 @@
<template>
<div>
<Row :gutter="20">
<i-col :xs="12" :md="8" :lg="4" v-for="(infor, i) in inforCardData" :key="`infor-${i}`" style="height: 120px;padding-bottom: 10px;">
<infor-card shadow :color="infor.color" :icon="infor.icon" :icon-size="36">
{{infor.count}}
<p>{{ infor.title }}</p>
</infor-card>
</i-col>
</Row>
<Row :gutter="20" class="margin-top-10">
<i-col :md="24" :lg="8" class="margin-bottom-20">
<Card shadow>
<chart-pie style="height: 300px;" :value="pieData" text="用户访问来源"></chart-pie>
</Card>
</i-col>
<i-col :md="24" :lg="16" class="margin-bottom-20">
<Card shadow>
<chart-bar style="height: 300px;" :value="barData" text="每周用户活跃量"/>
</Card>
</i-col>
</Row>
<Row>
<Card shadow>
<i-col :md="24" :lg="8" class="margin-bottom-20">
<example style="height: 310px;"/>
</i-col>
<!-- <Tabs :animated="false">
<TabPane label="标签一">标签一的内容</TabPane>
<TabPane label="标签二">标签二的内容</TabPane>
<TabPane label="标签三">标签三的内容</TabPane>
</Tabs> -->
</Card>
</Row>
</div>
<div>
<Row :gutter="20">
<i-col :xs="12" :md="8" :lg="4" v-for="(infor, i) in inforCardData" :key="`infor-${i}`"
style="height: 120px;padding-bottom: 10px;">
<infor-card shadow :color="infor.color" :icon="infor.icon" :icon-size="36">
{{infor.count}}
<p>{{ infor.title }}</p>
</infor-card>
</i-col>
</Row>
<Row :gutter="20" class="margin-top-10">
<i-col :md="24" :lg="8" class="margin-bottom-20">
<Card shadow>
<chart-pie style="height: 300px;" :value="pieData" text="用户访问来源"></chart-pie>
</Card>
</i-col>
<i-col :md="24" :lg="16" class="margin-bottom-20">
<Card shadow>
<chart-bar style="height: 300px;" :value="barData" text="每周用户活跃量" />
</Card>
</i-col>
</Row>
<Row :gutter="20">
<i-col :md="24" :lg="8" class="margin-bottom-20">
<Card shadow>
<example style="height: 310px;" />
<!-- <Tabs :animated="false">
<TabPane label="标签一">标签一的内容</TabPane>
<TabPane label="标签二">标签二的内容</TabPane>
<TabPane label="标签三">标签三的内容</TabPane>
</Tabs> -->
</Card>
</i-col>
</Row>
</div>
</template>
<script>
import InforCard from '_c/info-card'
import { ChartPie, ChartBar } from '_c/charts'
import { getHome } from '@/api/home'
import Example from './example.vue'
export default {
name: 'home',
@ -50,39 +52,54 @@ export default {
data () {
return {
inforCardData: [
{ title: '新增用户', icon: 'md-person-add', count: 803, color: '#2d8cf0' },
{ title: '累计点击', icon: 'md-locate', count: 232, color: '#19be6b' },
{ title: '新增问答', icon: 'md-help-circle', count: 142, color: '#ff9900' },
{ title: '分享统计', icon: 'md-share', count: 657, color: '#ed3f14' },
{ title: '新增互动', icon: 'md-chatbubbles', count: 12, color: '#E46CBB' },
{ title: '新增页面', icon: 'md-map', count: 14, color: '#9A66E4' }
// {title: '',icon: 'md-person-add',count: 803,color: '#2d8cf0'},
// {title: '',icon: 'md-locate',count: 232,color: '#19be6b'},
// {title: '',icon: 'md-help-circle',count: 142,color: '#ff9900'},
// {title: '',icon: 'md-share',count: 657,color: '#ed3f14'},
// {title: '',icon: 'md-chatbubbles',count: 12,color: '#E46CBB'},
// {title: '',icon: 'md-map',count: 14,color: '#9A66E4'}
],
pieData: [
{ value: 335, name: '直接访问' },
{ value: 310, name: '邮件营销' },
{ value: 234, name: '联盟广告' },
{ value: 135, name: '视频广告' },
{ value: 1548, name: '搜索引擎' }
],
barData: {
Mon: 13253,
Tue: 34235,
Wed: 26321,
Thu: 12340,
Fri: 24643,
Sat: 1322,
Sun: 1324
}
icons: ['ios-globe', 'md-person', 'md-help-circle', 'md-share', 'md-chatbubbles', 'md-map'],
colors: ['#2d8cf0', '#19be6b', '#ff9900', '#ed3f14', '#E46CBB', '#9A66E4'],
//
pieData: [],
//
barData: {}
}
},
mounted () {
//
created () {
this.init()
},
methods: {
init () {
getHome().then(response => {
const invoiceData = response.data.data.invoice_head_data
this.pieData = invoiceData.map(item => ({
name: item.type,
value: item.count
}))
// barData
this.barData = {}
invoiceData.forEach(item => {
// 使 type count
this.barData[item.type] = item.count
})
this.inforCardData = invoiceData.map((item, index) => ({
title: item.type,
count: item.count,
icon: this.icons[index % this.icons.length], //
color: this.colors[index % this.colors.length] //
}))
})
}
}
}
</script>
<style lang="less">
.count-style{
font-size: 50px;
}
<style lang="less" scoped>
.count-style {
font-size: 50px;
}
</style>

Loading…
Cancel
Save