123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782 |
- <template>
- <div :class="$style.title">
- <a-form-model layout="inline">
- <a-form-model-item label="年份:">
- <div style="width: 240px">
- <audit-year-time v-model="year" :single="false" @change="yearChange" />
- </div>
- </a-form-model-item>
- <a-form-model-item>
- <a-form-model-item label="组织机构:">
- <div style="width: 240px">
- <a-select
- v-model="mdgOrgCode"
- show-search
- placeholder="请先选择"
- :disabled="year.length === 0 || !isJt"
- :filter-option="filterOption"
- allow-clear
- >
- <a-select-option v-for="(item, i) in unitList" :key="i" :value="item.code">{{
- item.name
- }}</a-select-option>
- </a-select>
- </div>
- </a-form-model-item>
- <a-button type="primary" @click="searchData">查询</a-button>
- </a-form-model-item>
- </a-form-model>
- <a-divider></a-divider>
- <div :class="$style.contentView">
- <div :class="$style.viewBody">
- <div :class="$style.contentTitle">指标汇总</div>
- <a-form-model layout="inline" :class="$style.searchform">
- <a-form-model-item label="年份:">
- <div style="width: 200px">
- <a-select v-model="onYear">
- <a-select-option v-for="(item, i) in year" :key="i" :value="item">{{
- item
- }}</a-select-option>
- </a-select>
- </div>
- </a-form-model-item>
- <!-- 查询搜索 -->
- <a-form-model-item>
- <a-button type="primary" @click="searchBar">搜索</a-button>
- <a-button @click="resetBar">重置</a-button>
- </a-form-model-item>
- </a-form-model>
- <a-spin :spinning="isshowLoading1">
- <div id="echartsbar" :class="$style.bar"></div>
- <!-- 上网采购金额 -->
- <div :class="$style.purchaseData">上网采购金额:{{ purchase }}(万元)</div>
- </a-spin>
- </div>
- <div :class="$style.viewBody">
- <div :class="$style.contentTitle">趋势分析</div>
- <a-form-model layout="inline" :class="$style.searchform">
- <a-form-model-item label="指标选择:">
- <div style="width: 200px">
- <a-select v-model="targetKeys" placeholder="请选择指标" @change="selectZbChange">
- <a-select-option v-for="(item, i) in thirdClassifyData" :key="i" :value="item">
- {{ item }}
- </a-select-option>
- </a-select>
- </div>
- </a-form-model-item>
- <!-- 查询搜索 -->
- <a-form-model-item>
- <a-button type="primary" @click="searchLine">搜索</a-button>
- <a-button @click="resetLine">重置</a-button>
- </a-form-model-item>
- </a-form-model>
- <a-spin :spinning="isshowLoading2">
- <div id="echartsline" :class="$style.line"></div>
- </a-spin>
- </div>
- </div>
- </div>
- </template>
- <script>
- import components from '../riskLibrary/_import-components/audit-view-board-import'
- import auditPortraitService from './audit-portrait-service'
- import { message } from 'ant-design-vue'
- import auditYearTime from './audit-year-time.vue'
- import echarts from 'echarts'
- import { getUserInfo } from '@/common/store-mixin'
- import auditMaintainService from '../dataUphold/data-config'
- export default {
- name: 'AuditViewBoard',
- metaInfo: {
- title: '采购管理',
- },
- components: {
- ...components,
- auditYearTime,
- },
- data() {
- return {
- // 年份
- year: [],
- // 公司选择
- mdgOrgCode: '',
- // 单位列表
- unitList: [],
- // 饼图年份
- onYear: '',
- // 采购金额
- echartsBar: null,
- echartsLine: null,
- purchase: 0,
- purchaseData: [],
- isshowLoading1: false,
- isshowLoading2: false,
- // 趋势分析
- trendData: [],
- // 指标选择
- targetKeys: '',
- // 指标选择数据
- mockData: [],
- // 三级
- thirdClassifyData: [],
- // 表格数据
- tableData: [],
- // 表格列
- columns: [],
- // 搜索数据
- searchForm: {
- year: [],
- orgId: '',
- orgName: '',
- },
- orgList: [],
- isJt: false,
- userData: {},
- }
- },
- created() {
- // 默认年份 ,默认当前年份 及前两年
- // this.year = [2022]
- this.year = [
- new Date().getFullYear() - 3,
- new Date().getFullYear() - 2,
- new Date().getFullYear() - 1,
- ]
- this.yearChange('init')
- },
- mounted() {
- // 监听窗口变化
- // 初始化组织机构
- },
- // 页面销毁时取消监听
- beforeDestroy() {
- window.removeEventListener('resize', () => {
- this.echartsBar.resize()
- this.echartsLine.resize()
- })
- },
- methods: {
- // 初始化公司列表
- yearChange(type) {
- // 清空所选的组织机构
- this.mdgOrgCode = ''
- // 年份变化, 默认为第一年
- this.onYear = this.year[0] || ''
- // 查询所有有值公司
- const yearData = { year: this.year }
- this.searchForm.year = this.year
- auditPortraitService.getOrgList(yearData).then((res) => {
- // 过滤等于null的数据
- this.unitList = res.data.data.map((item) => {
- return {
- code: item.org_code,
- name: item.org_name,
- }
- })
- // 集团公司
- if (type === 'init') {
- const userInfo = getUserInfo()
- const grop = ['100001', '100000']
- // 查询当前公司列表下是否有本公司数据,如果有则本公司 为默认值,如果没有则不选中
- auditMaintainService.getCompany(userInfo.account).then((res) => {
- // 是否是集团员工
- this.userData = res.data
- if (grop.includes(res.data.code)) this.isJt = true
- const isOrg = this.unitList.find((item) => item.code === res.data.code)
- // 如果有匹配的值则为默认值
- if (isOrg && !this.isJt) {
- this.mdgOrgCode = res.data.code
- }
- // 如果不是集团 并且没有匹配值
- if (!this.isJt && !isOrg) {
- // 向unitList插入
- this.unitList.unshift({
- code: res.data.code,
- name: res.data.name,
- })
- }
- // 是集团
- if (this.isJt) {
- this.mdgOrgCode = '100000'
- }
- // 如果值不为空
- if (this.mdgOrgCode) {
- this.searchForm.orgId = this.mdgOrgCode
- this.searchForm.orgName = this.unitList.find(
- (item) => item.code === this.mdgOrgCode
- ).name
- }
- // 如果没有值则停止查询
- this.initUserUnit('init')
- })
- } else {
- const isOrg = this.unitList.find((item) => item.code === this.userData.code)
- // 如果有匹配的值则为默认值
- if (isOrg && !this.isJt) {
- this.mdgOrgCode = this.userData.code
- }
- // 如果不是集团 并且没有匹配值
- if (!this.isJt && !isOrg) {
- // 向unitList插入
- this.unitList.unshift({
- code: this.userData.code,
- name: this.userData.name,
- })
- }
- // 是集团
- if (this.isJt) {
- this.mdgOrgCode = '100000'
- }
- // 如果值不为空
- if (this.mdgOrgCode) {
- this.searchForm.orgId = this.mdgOrgCode
- this.searchForm.orgName = this.unitList.find(
- (item) => item.code === this.mdgOrgCode
- ).name
- }
- }
- })
- },
- // 公司查询
- filterOption(input, option) {
- return option.componentOptions.children[0].text.indexOf(input) >= 0
- },
- // 搜索
- searchData() {
- // 长度必须大于0
- if (this.year.length === 0) {
- message.error('请选择年份')
- return
- }
- if (!this.mdgOrgCode) {
- // message.error('该年份没有采购指标数据')
- message.error('请选择组织机构')
- return
- }
- this.searchBar()
- this.searchLine()
- // 查询指标
- },
- // 指标汇总
- searchBar() {
- if (!this.onYear) {
- message.error('请选择年份')
- return
- }
- // 组织机构
- if (!this.mdgOrgCode) {
- message.error('请选择组织机构')
- return
- }
- this.isshowLoading1 = true
- // 饼图数据
- const params = {
- mdg_orgCode: this.mdgOrgCode,
- year: [this.onYear],
- metricNameCn: this.mockData.map((item) => item.value),
- }
- auditPortraitService
- .getPurchaseData(params)
- .then((res) => {
- this.purchaseData = res.data.data[0].data || []
- // 过滤带率的数据
- this.purchaseData = this.purchaseData.filter(
- (item) => item.metric_name_cn.indexOf('率') === -1
- )
- // 如果有值则转成数字 保留两位小数,
- this.purchaseData = this.purchaseData.map((item) => {
- item.index_value = item.index_value ? (item.index_value * 1).toFixed(2) : 0
- return item
- })
- this.purchase =
- this.purchaseData.filter((item) => item.metric_name === 'swcgjewy')[0].index_value || 0
- this.initBar()
- })
- .finally(() => {
- // 如果两秒后还没有加载完毕则关闭
- setTimeout(() => {
- this.isshowLoading1 = false
- }, 2000)
- })
- },
- // 重置指标汇总
- resetBar() {
- // 重置年份
- this.onYear = this.year[0] || ''
- // 重新查询
- this.searchBar()
- },
- // 趋势分析
- searchLine() {
- if (this.targetKeys === '') {
- message.error('请选择指标')
- return
- }
- // 组织机构
- if (!this.mdgOrgCode) {
- message.error('请选择组织机构')
- return
- }
- this.isshowLoading2 = true
- // 根据指标获取值
- const cnData = this.mockData.filter((item) => item.thirdClassify === this.targetKeys)
- const params = {
- mdg_orgCode: this.mdgOrgCode,
- year: this.year,
- metricNameCn: cnData.map((item) => item.value),
- }
- auditPortraitService
- .getPurchaseData(params)
- .then((res) => {
- this.trendData = res.data.data || []
- // 整理成name 折线
- // 调用echarts
- this.initLine()
- })
- .finally(() => {
- // 如果两秒后还没有加载完毕则关闭
- setTimeout(() => {
- this.isshowLoading2 = false
- }, 2000)
- })
- },
- // 重置趋势分析
- resetLine() {
- // 重置指标 默认第一个指标
- this.targetKeys = this.mockData.find(
- (item) => item.thirdClassify === '上网采购'
- ).thirdClassify
- // 重新查询
- this.searchLine()
- },
- // 初始化指标
- initUserUnit(type) {
- const params = {
- columns:
- 'sortNumber,firstClassify,secondClassify,indexName,indexNameEn,indexMeasure,price,systemSource,remark,thirdClassify',
- maxResults: 1000,
- startPosition: 0,
- expressions: [
- {
- dataType: 'str',
- name: 'firstClassify',
- op: 'eq',
- stringValue: '采购管理',
- },
- ],
- buttonExpressions: [],
- formId: 'iamFinancialIndex',
- }
- auditPortraitService.getBusinessList(params).then((res) => {
- const data = res.data.data
- // 所有二级分类
- this.thirdClassifyData = Array.from(new Set(data.map((item) => item.thirdClassify)))
- // 获取所有指标
- this.mockData = data.map((item) => ({
- value: item.indexNameEn,
- label: item.indexName,
- // 三级名称
- thirdClassify: item.thirdClassify,
- }))
- // 默认选中网上
- this.targetKeys = this.mockData.find(
- (item) => item.thirdClassify === '上网采购'
- ).thirdClassify
- if (type === 'init') {
- if (!this.mdgOrgCode) {
- message.error('该年份没有采购指标数据')
- return
- }
- this.searchLine()
- this.searchBar()
- }
- })
- },
- // 选择指标
- selectZbChange(value) {
- //
- },
- // 初始化饼图
- initBar() {
- const bar = document.getElementById('echartsbar')
- this.echartsBar = echarts.init(bar)
- this.echartsBar.clear()
- const color = ['#fac858', '#ee6666', '#73c0de', '#3ba272', '#fc8452', '#9a60b4']
- // 招标部分,公开采购 + 邀请招标采购
- // 非招部分=竞争性谈判采购+单一来源采购+询价采购+其他采购
- const zb = [
- {
- name: '公开招标',
- nameEn: 'gkzb_sjhtje',
- },
- ]
- const fzb = [
- {
- name: '邀请招标',
- nameEn: 'yqzbjewy',
- },
- {
- name: '竞争性谈判',
- nameEn: 'jzxtpjewy',
- },
- {
- name: '单一来源采购',
- nameEn: 'dylyjewy',
- },
- {
- name: '询价采购',
- nameEn: 'xjjewy',
- },
- {
- name: '其他采购',
- nameEn: 'qtcgjewy',
- },
- ]
- const allZb = [...zb, ...fzb]
- // 按照allZb的顺序排序
- // 整理成 value name
- const outer = []
- allZb.map((item) => {
- this.purchaseData.map((data) => {
- if (data.metric_name === item.nameEn) {
- outer.push({
- value: data.index_value,
- name: item.name,
- })
- }
- })
- })
- const inside = [
- {
- value: outer[0].value,
- name: '招标',
- },
- {
- // 除第一个外的所有值相加
- value: outer.slice(1).reduce((prev, cur) => {
- return prev + cur.value
- }, 0),
- name: '非招',
- },
- ]
- const option = {
- tooltip: {
- trigger: 'item',
- formatter: '{a} <br/>{b}: {c} ({d}%)',
- },
- legend: {
- data: ['非招', '招标', ...zb.map((val) => val.name), ...fzb.map((val) => val.name)],
- },
- series: [
- {
- name: '指标名称(万元)',
- type: 'pie',
- selectedMode: 'single',
- radius: [0, '25%'],
- label: {
- position: 'inner',
- fontSize: 14,
- },
- labelLine: {
- show: false,
- },
- // 饼图中心
- data: inside,
- itemStyle: {
- color: function(colos) {
- return colos.dataIndex === 1 ? '#91cc75' : '#5470c6'
- },
- },
- },
- {
- name: '指标名称(万元)',
- type: 'pie',
- radius: ['35%', '45%'],
- labelLine: {
- length: 30,
- },
- label: {
- formatter: '{a|{a}}{abg|}\n{hr|}\n {b|{b}:}{c} {per|{d}%} ',
- backgroundColor: '#F6F8FC',
- borderColor: '#8C8D8E',
- borderWidth: 1,
- borderRadius: 4,
- rich: {
- a: {
- color: '#6E7079',
- lineHeight: 22,
- align: 'center',
- },
- hr: {
- borderColor: '#8C8D8E',
- width: '100%',
- borderWidth: 1,
- height: 0,
- },
- b: {
- color: '#4C5058',
- fontSize: 14,
- fontWeight: 'bold',
- lineHeight: 33,
- },
- per: {
- color: '#fff',
- backgroundColor: '#4C5058',
- padding: [3, 4],
- borderRadius: 4,
- },
- },
- },
- data: outer,
- itemStyle: {
- color: function(colos) {
- return color[colos.dataIndex]
- },
- },
- },
- ],
- }
- this.echartsBar.setOption(option)
- this.isshowLoading1 = false
- // 添加尺寸变化监听
- window.addEventListener('resize', () => {
- this.echartsBar.resize()
- })
- },
- // 初始化折线图
- initLine() {
- const line = document.getElementById('echartsline')
- this.echartsLine = echarts.init(line)
- this.echartsLine.clear()
- // 如果data为空则不渲染
- let data = []
- if (this.trendData.length !== 0) {
- data = this.trendData[0].data.map((val) => {
- return {
- name: val.metric_name_cn,
- data: [],
- }
- })
- this.trendData.map((item) => {
- item.data.map((val, i) => {
- data[i].data.push((val.index_value * 1).toFixed(2) || 0)
- })
- })
- }
- // 排序
- // name不含率的靠前
- data.sort((a, b) => {
- return a.name.indexOf('率') - b.name.indexOf('率')
- })
- // {
- // name: data[0].name,
- // type: 'bar',
- // data: data[0].data,
- // barWidth: 30,
- // itemStyle: {
- // color: '#02a7f0',
- // },
- // },
- // {
- // name: data[1].name,
- // type: 'line',
- // yAxisIndex: 1,
- // data: data[1].data,
- // itemStyle: {
- // color: '#89bf80',
- // },
- // },
- const series = data.map((item, i) => {
- const setData = i === 0 ? item.data : item.data.map((val) => val * 100)
- return {
- name: item.name,
- type: i === 0 ? 'bar' : 'line',
- data: setData,
- yAxisIndex: i === 0 ? 0 : 1,
- barWidth: 30,
- itemStyle: {
- color: i === 0 ? '#02a7f0' : '#89bf80',
- },
- }
- })
- const year = this.trendData.map((item) => item.year)
- const option = {
- tooltip: {
- trigger: 'axis',
- axisPointer: {
- type: 'cross',
- crossStyle: {
- color: '#999',
- },
- },
- formatter: function(params) {
- let res = params[0].name
- res += '<br/>' + params[0].seriesName + ' : ' + params[0].value + '(万元)'
- if (params[1]) {
- res += '<br/>' + params[1].seriesName + ' : ' + params[1].value + '%'
- }
- return res
- },
- },
- legend: {
- data: data.map((item) => item.name),
- },
- grid: {
- left: '8%',
- containLabel: true,
- },
- dataZoom: {
- // 横向滚动,最多十年
- type: 'slider',
- show: true,
- },
- xAxis: [
- {
- type: 'category',
- data: year,
- axisPointer: {
- type: 'shadow',
- },
- },
- ],
- // {
- // type: 'value',
- // name: data[0].name,
- // interval: 100,
- // axisLabel: {
- // formatter: '{value} (万元)',
- // },
- // },
- // {
- // type: 'value',
- // name: data[1].name,
- // min: 0,
- // max: 100,
- // interval: 10,
- // axisLabel: {
- // formatter: '{value} %',
- // },
- // },
- yAxis: data.map((item, i) => {
- const obj = {
- type: 'value',
- name: item.name,
- // 单位
- axisLabel: {
- formatter: i === 0 ? '{value} (万元)' : '{value} %',
- },
- }
- // if (i === 1) {
- // obj.interval = 10
- // }
- return obj
- }),
- series: series,
- }
- this.echartsLine.setOption(option)
- this.isshowLoading2 = false
- // 添加尺寸变化监听
- window.addEventListener('resize', () => {
- this.echartsLine.resize()
- })
- },
- },
- }
- </script>
- <style module lang="scss">
- @use '@/common/design' as *;
- .bar {
- width: 100%;
- height: 550px;
- }
- .line {
- width: 100%;
- height: 600px;
- }
- .title {
- padding: 20px;
- background: #fff;
- }
- ::v-deep .ant-card-body {
- height: 100%;
- }
- .purchase-data {
- width: 80%;
- height: 40px;
- margin: 10px auto;
- font-size: 18px;
- line-height: 40px;
- color: #fff;
- text-align: center;
- background: #02a7f0;
- border-radius: 10px;
- }
- .content-view {
- display: flex;
- justify-content: space-between;
- .view-body {
- position: relative;
- flex: 1;
- width: 48%;
- height: 800px;
- border: 1px solid #0086d6;
- border-radius: 10px;
- &:last-child {
- margin-left: 20px;
- }
- // title居中浮动
- .content-title {
- position: absolute;
- top: -20px;
- left: calc(50% - 75px);
- width: 150px;
- height: 40px;
- font-size: 18px;
- font-weight: 600;
- line-height: 40px;
- color: #fff;
- text-align: center;
- background: #02a7f0;
- border-radius: 5px;
- }
- &:last-child .content-title {
- background-color: #00bfbf;
- }
- .searchform {
- padding: 25px 0 10px 15px;
- }
- }
- }
- .spicclasswrapper {
- height: 100%;
- ::v-deep .ant-spin-container {
- height: 100%;
- }
- }
- .spicclass {
- height: 100%;
- }
- </style>
|