初始化

This commit is contained in:
aixianling
2021-12-14 18:36:19 +08:00
parent 9afa4101b6
commit a8dff862d2
327 changed files with 88702 additions and 0 deletions

View File

@@ -0,0 +1,285 @@
<template>
<ai-detail>
<template slot="title">
<ai-title :title="id ? '编辑项目' : '添加项目'" isShowBack isShowBottomBorder @onBackClick="cancel(false)">
</ai-title>
</template>
<template slot="content">
<el-form ref="form" :model="form" label-width="110px" label-position="right">
<ai-card title="基本信息">
<template #content>
<div class="ai-form">
<el-form-item label="名称" prop="name" :rules="[{ required: true, message: '请输入大屏项目名称', trigger: 'blur' }]">
<el-input size="small" :maxlength="30" placeholder="请输入大屏项目名称" v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="描述" style="width: 100%;" prop="description">
<el-input size="small" :maxlength="200" :rows="5" type="textarea" style="width: 100%;"
placeholder="请输入描述" v-model="form.description"></el-input>
</el-form-item>
<el-form-item label="是否开启" style="width: 100%;" prop="status">
<el-switch
v-model="form.status"
active-value="1"
inactive-value="0">
</el-switch>
</el-form-item>
</div>
</template>
</ai-card>
<ai-card title="大屏">
<template #right>
<el-button @click="add('')" type="primary">添加大屏</el-button>
<el-button @click="dialog=true" type="primary">定制大屏</el-button>
</template>
<template #content>
<ai-table
:tableData="tableData"
:col-configs="colConfigs"
:total="total"
style="margin-top: 6px;"
:border="true"
:isShowPagination="false"
@getList="() => {}">
<el-table-column slot="options" width="160px" fixed="right" label="操作" align="center">
<template slot-scope="{ row, column, $index }">
<div class="table-options">
<el-button type="text" @click="toEdit(row.id, row.isCustom, row)">编辑</el-button>
<el-button type="text" @click="toViewer(row.id)">预览</el-button>
<el-button type="text" @click="remove($index)">删除</el-button>
</div>
</template>
</el-table-column>
</ai-table>
</template>
</ai-card>
</el-form>
<Layout
v-if="isShowLayout"
:instance="instance"
:dict="dict"
:params="query"
@change="onChange"
:urlPrefix="urlPrefix"
@close="isShowLayout = false">
</Layout>
<ai-dv-wrapper :views="[{label: '返回'}]" @change="screenId = false" v-if="screenId" :title="form.name">
<AppGigscreenViewer :urlPrefix="urlPrefix" :instance="instance" :dict="dict" :id="screenId"></AppGigscreenViewer>
</ai-dv-wrapper>
<ai-dialog :visible.sync="dialog" title="定制大屏" @closed="custom={}" @onConfirm="handleCustomizedDV">
<el-form ref="CustomDVFrom" size="small" :model="custom" :rules="rules" label-width="80px">
<el-form-item label="大屏标题" prop="title">
<el-input v-model="custom.title" clearable placeholder="请填写"/>
</el-form-item>
<el-form-item label="选择大屏" prop="dv">
<ai-select v-model="custom.dv" :selectList="dict.getDict('customizedDVs')"/>
</el-form-item>
<el-form-item label="静态数据">
<el-input type="textarea" rows="5" v-model="custom.meta"/>
</el-form-item>
</el-form>
</ai-dialog>
</template>
<template #footer>
<el-button @click="cancel">取消</el-button>
<el-button type="primary" @click="confirm">提交</el-button>
</template>
</ai-detail>
</template>
<script>
import AppGigscreenViewer from '../../viewer/AppGigscreenViewer'
import Layout from './Layout.vue'
export default {
name: 'Add',
props: {
instance: Function,
dict: Object,
params: Object,
urlPrefix: String
},
components: {
Layout,
AppGigscreenViewer
},
data() {
return {
info: {},
department: [],
form: {
name: '',
relationLsIds: '',
relationLsNames: '',
status: '1',
description: ''
},
screenId: '',
query: {},
total: 0,
colConfigs: [
{prop: 'title', label: '标题'},
{prop: 'id', label: 'ID'}
],
tableData: [],
isShowLayout: false,
id: '',
dialog: false,
custom: {},
rules: {
dv: [{required: true, message: "请选择 定制大屏"}],
title: [{required: true, message: "请输入 大屏标题"}],
}
}
},
created() {
this.dict.load('customizedDVs')
if (this.params && this.params.id) {
this.id = this.params.id
this.getInfo(this.params.id)
}
},
methods: {
getInfo(id) {
this.instance.post(`${this.urlPrefix}/appdiylargescreen/queryLargeScreenProjectDetailById?id=${id}`).then(res => {
if (res.code === 0) {
this.form = {
...res.data
}
if (res.data.relationLsIds) {
this.tableData = res.data.lsList.map(v => {
let conf = JSON.parse(v.config || '') || {}
return {
id: v.id,
title: v.title,
dv: conf.custom || '',
meta: JSON.stringify(conf.meta),
isCustom: !!conf.custom
}
})
this.total = res.data.lsList.length
}
}
})
},
toViewer(id) {
this.screenId = id
},
getList() {
this.instance.post(`${this.urlPrefix}/appdiylargescreen/allLargeScreenByPage`, null, {
params: {
current: 1,
size: 1000
}
}).then(res => {
if (res.code == 0) {
this.tableData = res.data.records
this.total = res.data.total
}
})
},
onChange(e) {
const ids = this.tableData.map(v => v.id)
if (ids.indexOf(e.id) < 0) {
this.tableData.push({
title: e.title,
id: e.id
})
} else {
const index = this.tableData.findIndex(v => v.id === e.id)
this.$set(this.tableData[index], 'title', e.title)
}
},
add() {
this.query = {
id: '',
name: this.form.name
}
this.isShowLayout = true
},
toEdit(id, isCustom, form) {
if (!isCustom) {
this.query = {
id,
name: this.form.name
}
this.isShowLayout = true
} else {
this.dialog = true
this.custom = {
...form,
}
}
},
remove(index) {
this.tableData.splice(index, 1)
},
confirm() {
this.$refs.form.validate((valid) => {
if (valid) {
const ids = this.tableData.map(v => v.id).join(',')
const names = this.tableData.map(v => v.name).join(',')
this.instance.post(`${this.urlPrefix}/appdiylargescreen/addOrUpdateLargeScreenProject`, {
...this.form,
relationLsIds: ids,
relationLsNames: names
}).then(res => {
if (res.code == 0) {
this.$message.success('提交成功')
setTimeout(() => {
this.cancel(true)
}, 600)
}
})
}
})
},
cancel(isRefresh) {
this.$emit('change', {
type: 'list',
isRefresh: !!isRefresh
})
},
handleCustomizedDV() {
this.$refs.CustomDVFrom.validate(v => {
if (v) {
this.instance.post(`${this.urlPrefix}/appdiylargescreen/addOrUpdateLargeScreen`, {
config: JSON.stringify({
custom: this.custom.dv,
meta: JSON.parse(this.custom.meta?.replace(/\\n/g, '') || null)
}),
status: 1,
id: this.custom.id,
title: this.custom.title,
}).then(res => {
if (res?.code == 0 && res?.data) {
this.$message.success('保存成功')
this.onChange(res.data)
this.dialog = false
}
})
}
})
}
}
}
</script>
<style scoped lang="scss">
</style>

View File

@@ -0,0 +1,92 @@
<template>
<div class="swiper">
<el-carousel height="100%" indicator-position="none">
<el-carousel-item v-for="(item, index) in data" :key="index">
<img :src="item.img">
<div class="swiper-content" v-if="item.title">
<h2>{{ item.title }}</h2>
<p>{{ item.content }}</p>
</div>
</el-carousel-item>
</el-carousel>
</div>
</template>
<script>
export default {
name: 'AiSwiper',
props: {
data: {
type: Array,
default: () => []
},
width: {
type: String,
default: '100%'
},
heigth: {
type: String,
default: '100%'
}
},
data () {
return {
}
},
mounted () {
},
methods: {
}
}
</script>
<style lang="scss" scoped>
.swiper {
width: 100%;
height: 100%;
padding: 20px 0 0;
::v-deep .el-carousel {
height: 100%;
}
img {
width: 100%;
height: 100%;
}
.swiper-content {
position: absolute;
bottom: 0;
left: 0;
z-index: 1;
width: 100%;
padding: 10px;
text-align: center;
background: linear-gradient(180deg, rgba(0, 0, 0, 0.1) 0%, #000000 100%);
h2 {
margin-bottom: 4px;
color: #fff;
text-align: center;
font-size: 18px;
}
p {
line-height: 22px;
white-space: pre-line;
color: #B6DFFF;
font-size: 14px;
text-align: center;
}
}
}
</style>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,141 @@
<template>
<ai-list class="form-list" isTabs style="width: 100%">
<template slot="content">
<ai-search-bar>
<template #left>
<ai-select
v-model="search.status"
@change="search.current = 1, getList()"
placeholder="发布状态"
:selectList="dict.getDict('questionnaireStatus')">
</ai-select>
<el-button type="primary" @click="toEdit('')">添加大屏</el-button>
<el-button type="primary" @click="toAddData">数据源管理</el-button>
</template>
<template #right>
<el-input
v-model="search.title"
size="small"
placeholder="请输入模板名称或创建人"
clearable
@keyup.enter.native="search.current = 1, getList()"
@clear="search.current = 1, search.title = '', getList()"
suffix-icon="iconfont iconSearch">
</el-input>
</template>
</ai-search-bar>
<ai-table
:tableData="tableData"
:col-configs="colConfigs"
:total="total"
v-loading="loading"
style="margin-top: 6px;"
:current.sync="search.current"
:size.sync="search.size"
@getList="getList">
<el-table-column slot="options" width="120px" fixed="right" label="操作" align="center">
<template slot-scope="{ row }">
<div class="table-options">
<el-button type="text" @click="toEdit(row.id)">编辑</el-button>
</div>
</template>
</el-table-column>
</ai-table>
</template>
</ai-list>
</template>
<script>
export default {
name: 'FormList',
props: {
instance: Function,
dict: Object,
areaId: String,
urlPrefix: String
},
data () {
return {
search: {
current: 1,
status: '',
size: 10,
title: ''
},
colConfigs: [
{ prop: 'name', label: '模板名称' },
{ prop: 'createUserName', align: 'center', label: '创建人' },
{ prop: 'description', align: 'center', label: '描述' },
{ prop: 'status', align: 'center', label: '状态', formart: v => v === '1' ? '已开启' : '未开启' },
{ prop: 'createTime', align: 'center', label: '创建时间' }
],
tableData: [],
total: 0,
loading: false
}
},
created () {
this.dict.load('questionnaireStatus').then(() => {
this.getList()
})
},
mounted () {
this.loading = true
},
methods: {
getList () {
this.instance.post(`${this.urlPrefix}/appdiylargescreen/allLargeScreenProjectByPage`, null, {
params: {
...this.search
}
}).then(res => {
if (res.code == 0) {
this.tableData = res.data.records
this.total = res.data.total
this.loading = false
} else {
this.loading = false
}
}).catch(() => {
this.loading = false
})
},
toEdit (id) {
this.$emit('change', {
type: 'add',
params: {
id: id || ''
}
})
},
toAddData () {
this.$emit('change', {
type: 'SourceData'
})
},
onConfirm () {
this.$emit('change', {
type: 'add',
params: {
id: '',
templateType: 0,
type: this.currIndex
}
})
}
}
}
</script>
<style scoped lang="scss">
.form-list {
}
</style>

View File

@@ -0,0 +1,188 @@
<template>
<div class="render-element" style="width: 100%; height: 100%;">
<ai-dv-display v-if="data.type === 'display'" :title="data.title" :list="data[data.dataType]"></ai-dv-display>
<ai-dv-panel
style="height: 100%; width: 100%;"
v-if="data.type !== 'display'"
:title="data.title"
:border="data.border || ''">
<AiDvSummary v-if="data.type === 'summary'" :key="`summary${index}`" :type="data.display" :data="data[data.dataType]"/>
<AiSwiper v-else-if="data.type === 'swiper'" :heigth="'100%'" :data="data[data.dataType]"/>
<dv-scroll-board
v-if="data.type === 'table'"
:config="formatTable(data[data.dataType], data.isShowIndex, data.rowNum)"
:key="data.height"
:style="{height: data.height + 'px', width: '100%'}" />
<ai-echart
v-else-if="data.type === 'barChart1'"
style="height: 100%; width: 100%;"
:ref="'chart' + index"
:key="`chart${index}`"
:data="data[data.dataType]"
:ops="data.config"/>
<ai-echart
v-else-if="data.type === 'barChart2'"
style="height: 100%; width: 100%;"
:ref="'chart' + index"
:key="`chart${index}`"
:data="data[data.dataType]"
:ops="data.config"/>
<ai-echart
v-else-if="data.type === 'barChart3'"
style="height: 100%; width: 100%;"
:ref="'chart' + index"
:key="`chart${index}`"
:data="data[data.dataType]"
:ops="data.config"/>
<ai-echart
v-else-if="data.type === 'barChart5'"
style="height: 100%; width: 100%;"
:ref="'chart' + index"
:key="`chart${index}`"
:data="data[data.dataType]"
:ops="data.config"/>
<ai-echart
v-else-if="data.type === 'barChart7'"
style="height: 100%; width: 100%;"
:ref="'chart' + index"
:key="`chart${index}`"
:data="data[data.dataType]"
:ops="data.config"/>
<ai-echart
v-else-if="data.type === 'barChart8'"
style="height: 100%; width: 100%;"
:ref="'chart' + index"
:key="`chart${index}`"
:data="data[data.dataType]"
:ops="data.config"/>
<ai-echart
v-else-if="data.type === 'barChart9'"
style="height: 100%; width: 100%;"
:ref="'chart' + index"
:key="`chart${index}`"
:data="data[data.dataType]"
:ops="data.config"/>
<ai-echart
v-else-if="data.type === 'lineChart1'"
style="height: 100%; width: 100%;"
:ref="'chart' + index"
:key="`chart${index}`"
:data="data[data.dataType]"
:ops="lineChart1"/>
<ai-echart
v-else-if="data.type === 'lineChart2'"
style="height: 100%; width: 100%;"
:ref="'chart' + index"
:key="`chart${index}`"
:data="data[data.dataType]"
:ops="lineChart2"/>
<ai-echart
v-else-if="data.type === 'lineChart3'"
style="height: 100%; width: 100%;"
:ref="'chart' + index"
:key="`chart${index}`"
:data="data[data.dataType]"
:ops="data.config"/>
<ai-echart
v-else-if="data.type === 'lineChart4'"
style="height: 100%; width: 100%;"
:ref="'chart' + index"
:key="`chart${index}`"
:data="data[data.dataType]"
:ops="data.config"/>
<ai-echart
v-else-if="data.type === 'lineChart5'"
style="height: 100%; width: 100%;"
:ref="'chart' + index"
:key="`chart${index}`"
:data="data[data.dataType]"
:ops="lineChart5"/>
<ai-echart
v-else-if="data.type === 'pieChart'"
style="height: 100%; width: 100%;"
:ref="'chart' + index"
:key="`chart${index}`"
:data="data[data.dataType]"
:ops="pieChart"/>
<ai-map :markers="data[data.dataType]" v-else-if="data.type=='map'" :mask="data.mask === '1'" :areaId="data.areaId || user.info.areaId" map-style="amap://styles/e51987628aee5206d4c9ca8c6e98b4f7"/>
<ai-monitor :src="data.src" v-else-if="data.type === 'monitor'" :type="data.monitorType"></ai-monitor>
<video style="width: 100%; height: 100%; object-fit: fill;" loop :src="data.src" autoplay v-else-if="data.type === 'video'"></video>
</ai-dv-panel>
</div>
</template>
<script>
import { mapState } from 'vuex'
import AiSwiper from './AiSwiper.vue'
import pieChart from 'dvcp-dv-ui/components/AiEchart/template/pie/pieChart2'
import lineChart1 from 'dvcp-dv-ui/components/AiEchart/template/line/lineChart1'
import lineChart2 from 'dvcp-dv-ui/components/AiEchart/template/line/lineChart2'
import lineChart5 from 'dvcp-dv-ui/components/AiEchart/template/line/lineChart5'
export default {
name: 'RenderElement',
props: ['data', 'index'],
components: {
AiSwiper
},
data () {
return {
lineChart1,
lineChart2,
lineChart5,
pieChart
}
},
computed: {
...mapState(['user'])
},
methods: {
formatTable(data, isShowIndex, rowNum) {
if (!data.length) {
return {
header: [],
data: []
}
}
let rows = []
const header = data.map(v => {
return v[Object.keys(v)[0]]
})
Object.keys(data[0]).forEach((item, index) => {
if (index !== 0) {
rows.push(item)
}
})
return {
header: header,
data: rows.map(item => {
return data.map(v => {
return v[item]
})
}),
headerBGC: 'transparent',
evenRowBGC: 'transparent',
oddRowBGC: 'rgba(0, 133, 255, 0.2)',
headerHeight: 42,
rowNum: rowNum || 7,
index: isShowIndex === '1',
carousel: 'page',
indexHeader: '排名',
align: ['center', 'center', 'center', 'center', 'center']
}
},
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@@ -0,0 +1,430 @@
<template>
<ai-detail>
<template slot="title">
<ai-title title="数据源" isShowBack isShowBottomBorder @onBackClick="cancel(false)">
</ai-title>
</template>
<template slot="content">
<ai-card title="数据源列表">
<template #right>
<el-button type="primary" @click="isShow = true">添加数据源</el-button>
</template>
<template #content>
<ai-search-bar class="search-bar">
<template slot="right">
<el-input
v-model="search.name"
size="small"
@keyup.enter.native="search.current = 1, getList()"
placeholder="请输入名字"
clearable
@clear="search.current = 1, search.name = '', getList()"
suffix-icon="iconfont iconSearch">
</el-input>
</template>
</ai-search-bar>
<ai-table
:tableData="tableData"
:col-configs="colConfigs"
:total="total"
style="margin-top: 6px;"
:border="true"
:current.sync="search.current"
:size.sync="search.size"
@getList="getList">
<el-table-column slot="options" width="160px" fixed="right" label="操作" align="center">
<template slot-scope="{ row }">
<div class="table-options">
<el-button type="text" @click="toEdit(row)">编辑</el-button>
<el-button type="text" @click="remove(row.id)">删除</el-button>
</div>
</template>
</el-table-column>
</ai-table>
</template>
</ai-card>
<ai-dialog
:visible.sync="isShow"
width="820px"
title="数据源"
@close="onClose"
@onConfirm="onConfirm">
<el-form ref="form" :model="form" label-width="110px" label-position="right">
<div class="ai-form">
<el-form-item label="数据源描述" style="width: 100%;" prop="description" :rules="[{ required: true, message: '请输入数据源描述', trigger: 'blur' }]">
<el-input
size="small"
placeholder="请输入数据源描述"
v-model="form.description">
</el-input>
</el-form-item>
<el-form-item label="村微应用" style="width: 100%;" prop="appId" :rules="[{ required: true, message: '请选择村微应用', trigger: 'change' }]">
<el-select size="small" style="width: 100%;" v-model="form.appId" placeholder="请选择村微应用" @change="onAppChange">
<el-option
v-for="item in appList"
:key="item.id"
:label="item.appName"
:value="item.id">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="数据范围" style="width: 100%;" prop="dataRange" :rules="[{ required: true, message: '请选择数据范围', trigger: 'change' }]">
<el-radio-group v-model="form.dataRange">
<el-radio label="0">全部</el-radio>
<el-radio label="1">自定义条数</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="数据条数" style="width: 100%;" v-if="form.dataRange === '1'" prop="count" :rules="[{ required: true, message: '请输入数据条数', trigger: 'blur' }]">
<el-input
size="small"
placeholder="请输入数据条数"
v-model="form.count">
</el-input>
</el-form-item>
<el-form-item :label="'统计项' + index" style="width: 100%;" v-for="(item, index) in form.statisticsConfigs" :key="'statisticsConfigs' + index">
<div class="form-flex">
<div>
<el-select size="small" style="width: 160px;" v-model="item.fieldName" @change="e => onChooseField('statisticsConfigs', e, index)" placeholder="请选择" clearable>
<el-option
v-for="(item, index) in filedList"
:key="index"
:label="item.fieldCnName"
:value="item.fieldName">
</el-option>
</el-select>
<el-select size="small" style="margin: 0 10px; width: 160px;" v-model="item.calcType" placeholder="请选择" clearable>
<el-option
v-for="item in dict.getDict('diyLargeScreenDatasourceCalcType2')"
:key="item.id"
:label="item.dictName"
:value="item.dictValue">
</el-option>
</el-select>
<el-input size="small" style="width: 165px;" placeholder="请输入别名" v-model="item.alias"></el-input>
</div>
<el-button type="danger" v-if="index > 0" @click="removeConfig('statisticsConfigs', index)">删除</el-button>
</div>
</el-form-item>
<el-form-item style="width: 100%;">
<el-button type="primary" @click="add('statisticsConfigs')">添加统计项</el-button>
</el-form-item>
<el-form-item :label="'分组' + index" style="width: 100%;" v-for="(item, index) in form.groupConfigs" :key="'groupConfigs' + item.fieldName">
<div class="form-flex">
<div>
<el-select size="small" style="width: 160px;" v-model="item.fieldName" placeholder="请选择" clearable>
<el-option
v-for="item in filedList"
:key="item.id"
:label="item.fieldCnName"
:value="item.fieldName">
</el-option>
</el-select>
</div>
<el-button type="danger" @click="removeConfig('groupConfigs', index)">删除</el-button>
</div>
</el-form-item>
<el-form-item style="width: 100%;">
<el-button type="primary" @click="add('groupConfigs')">添加分组</el-button>
</el-form-item>
<el-form-item :label="'统计项' + index" style="width: 100%;" v-for="(item, index) in form.orderConfigs" :key="'orderConfigs' + item.fieldName">
<div class="form-flex">
<div>
<el-select size="small" style="width: 160px;" v-model="item.fieldName" placeholder="请选择" clearable>
<el-option
v-for="item in filedList"
:key="item.id"
:label="item.fieldCnName"
:value="item.fieldName">
</el-option>
</el-select>
<el-select size="small" style="width: 160px; margin-left: 10px;" v-model="item.orderType" placeholder="请选择" clearable>
<el-option
v-for="item in orderTypeDict"
:key="item.id"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</div>
<el-button type="danger" @click="removeConfig('orderConfigs', index)">删除</el-button>
</div>
</el-form-item>
<el-form-item style="width: 100%;">
<el-button type="primary" @click="add('orderConfigs')">添加排序</el-button>
</el-form-item>
</div>
</el-form>
</ai-dialog>
</template>
</ai-detail>
</template>
<script>
export default {
name: 'SourceData',
props: {
instance: Function,
dict: Object,
params: Object,
urlPrefix: String
},
data () {
return {
isShow: false,
search: {
current: 1,
size: 10,
name: ''
},
total: 0,
colConfigs: [
{ prop: 'appName', label: '应用名' },
{ prop: 'appTableName', label: '表名' },
{ prop: 'createUserName', label: '创建人' },
{ prop: 'description', label: '描述' },
{ prop: 'createTime', align: 'center', label: '创建时间' }
],
tableData: [],
filedList: [],
appList: [],
form: {
orderType: 'asc',
dataRange: '0',
appId: '',
description: '',
appName: '',
appTableName: '',
count: '100',
statisticsConfigs: [{
alias: '',
calcType: '',
dictCode: '',
fieldCnName: '',
fieldName: ''
}],
orderConfigs: [{
alias: '',
calcType: '',
dictCode: '',
fieldCnName: '',
fieldName: ''
}],
groupConfigs: [{
alias: '',
calcType: '',
dictCode: '',
fieldCnName: '',
fieldName: ''
}]
},
id: '',
orderTypeDict: [
{
value: 'asc',
label: '升序'
},
{
value: 'desc',
label: '降序'
}
]
}
},
created () {
this.dict.load(['diyLargeScreenDatasourceCalcType2']).then(() => {
this.getList()
this.getAppList()
})
},
methods: {
getInfo (id) {
this.instance.post(`${this.urlPrefix}/wxcp/wxuser/queryDetailById?id=${id}`).then(res => {
if (res.code === 0) {
this.form = {
...res.data
}
}
})
},
onChooseField (type, fieldName, index) {
const dictCode = this.filedList.filter(v => v.fieldName === fieldName)[0].dictCode
this.$set(this.form[type][index], 'dictCode', dictCode)
},
add (type) {
this.form[type].push({
alias: '',
calcType: '',
dictCode: '',
fieldCnName: '',
fieldName: ''
})
},
removeConfig (type, index) {
this.form[type].splice(index, 1)
},
toEdit (e) {
this.id = e.id
this.instance.post(`${this.urlPrefix}/appdiylargescreen/queryDatasourceDetailById?id=${e.id}`).then(res => {
if (res.code === 0) {
this.form = {
...res.data
}
this.form.dataRange = this.form.dataRange === '0' ? '0' : '1'
this.form.count = res.data.dataRange
this.filedList = this.appList.filter(v => v.id === res.data.appId)[0].fields.map(item => {
let value = []
res.data.configs.forEach(v => {
if (v.fieldName === item.fieldName) {
value.push(v.calcType)
}
})
return {
...item,
value
}
})
this.isShow = true
}
})
},
remove (id) {
this.$confirm('确定删除该数据?').then(() => {
this.instance.post(`${this.urlPrefix}/appquestionnairetemplate/delete?id=${id}`).then(res => {
if (res.code == 0) {
this.$message.success('删除成功!')
this.getList()
}
})
})
},
getList () {
this.instance.post(`${this.urlPrefix}/appdiylargescreen/allDatasourceByPage`, null, {
params: {
...this.search
}
}).then(res => {
if (res.code == 0) {
this.tableData = res.data.records
this.total = res.data.total
}
})
},
getAppList () {
this.instance.post(`${this.urlPrefix}/appdiylargescreen/allDatasourceApp`).then(res => {
if (res.code === 0) {
this.appList = res.data
}
})
},
onClose () {
this.id = ''
this.form.orderType = 'asc'
this.form.dataRange = 0
this.form.appId = ''
this.form.description = ''
this.form.appName = ''
this.form.appTableName = ''
this.form.count = 100
},
onAppChange (e) {
const value = this.appList.filter(v => v.id === e)[0]
this.form.appTableName = value.appTableName
this.form.appName = value.appName
this.form.statisticsConfigs = [{
alias: '',
calcType: '',
dictCode: '',
fieldCnName: '',
fieldName: ''
}]
this.form.orderConfigs = [{
alias: '',
calcType: '',
dictCode: '',
fieldCnName: '',
fieldName: ''
}]
this.form.groupConfigs = [{
alias: '',
calcType: '',
dictCode: '',
fieldCnName: '',
fieldName: ''
}]
this.filedList = value.fields.map(v => {
return {
...v,
value: ''
}
})
},
onConfirm () {
this.$refs.form.validate((valid) => {
if (valid) {
let configs = []
this.filedList.forEach(item => {
if (item.value.length) {
item.value.forEach(v => {
configs.push({
alias: item.fieldCnName,
calcType: v,
fieldCnName: item.fieldCnName,
fieldName: item.fieldName,
dictCode: item.dictCode,
orderType: this.orderType
})
})
}
})
this.instance.post(`${this.urlPrefix}/appdiylargescreen/addOrUpdateDatasource`, {
...this.form,
configs,
id: this.id ? this.id : '',
dataRange: this.form.dataRange === '0' ? 0 : this.form.count
}).then(res => {
if (res.code === 0) {
this.$message.success(this.id ? '编辑成功' : '添加成功')
this.search.current = 1
this.isShow = false
this.getList()
}
})
}
})
},
cancel (isRefresh) {
this.$emit('change', {
type: 'list',
isRefresh: !!isRefresh
})
}
}
}
</script>
<style scoped lang="scss">
.form-flex {
display: flex;
justify-content: space-between;
align-items: center;
}
</style>

View File

@@ -0,0 +1,455 @@
<template>
<div class="layout-config__group--wrapper">
<ai-dialog
append-to-body
:visible.sync="isShowEditor"
width="1000px"
class="layout-config__edit"
title="编辑器"
@onConfirm="onConfirm">
<div style="height: 500px;">
<vue-json-editor
v-model="json"
:show-btns="false"
mode="code"
lang="zh">
</vue-json-editor>
</div>
</ai-dialog>
<div class="layout-config__group" v-if="options.monitorType !== 'hik'">
<h2>基础设置</h2>
<div class="layout-config__item">
<label>数据类型</label>
<div class="layout-config__item--right">
<el-select size="mini" v-model="options.dataType" placeholder="请选择数据类型">
<el-option
v-for="item in dataTypes"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</div>
</div>
<div class="layout-config__code" v-if="options.dataType === 'staticData'">
<el-button @click="showEditor" class="layout-config__code--btn" title="编辑" type="text" icon="iconfont iconjdq_led_edit"></el-button>
<vue-json-editor
:value="options.staticData"
:show-btns="false"
mode="view"
lang="zh">
</vue-json-editor>
</div>
<template v-else-if="options.dataType === 'dynamicData'">
<div class="layout-config__item">
<label>数据源</label>
<div class="layout-config__item--right">
<el-select size="mini" v-model="options.sourceDataId" placeholder="请选择数据源" @change="onDataChange">
<el-option
v-for="item in sourceData"
:key="item.id"
:label="item.description"
:value="item.id">
</el-option>
</el-select>
</div>
</div>
</template>
<template v-else>
<div class="layout-config__item">
<label>接口地址</label>
<div class="layout-config__item--right">
<el-input size="mini" v-model="options.api" @blur="onApiChange"></el-input>
</div>
</div>
</template>
</div>
<div class="layout-config__group" v-if="options.monitorType === 'hik'">
<h2>基础设置</h2>
<div class="layout-config__item">
<label>视频ID</label>
<div class="layout-config__item--right">
<el-input size="mini" v-model="options.src"></el-input>
</div>
</div>
</div>
<div class="layout-config__group" v-if="options.dataType !== 'staticData' && options.type === 'monitor' && options.monitorType === 'cmcc'">
<h2>字段设置</h2>
<div class="layout-config__item">
<label>监控视频</label>
<div class="layout-config__item--right">
<el-select size="mini" v-model="options.moniterId" placeholder="请选择监控视频" @change="onMoniterId">
<el-option
v-for="(item, index) in monitorList"
:key="index"
:label="item.name"
:value="item.id">
</el-option>
</el-select>
</div>
</div>
</div>
<div class="layout-config__group" v-if="options.dataType !== 'staticData' && options.type !== 'monitor' && keys.length && options.type !== 'table'">
<h2>字段设置</h2>
<div class="layout-config__item">
<label>X轴设置</label>
<div class="layout-config__item--right">
<el-select size="mini" v-model="options.dataX" placeholder="请选择X轴" @change="onChooseChange">
<el-option
v-for="(item, index) in keys"
:key="index"
:label="item"
:value="item">
</el-option>
</el-select>
</div>
</div>
<div class="layout-config__item">
<label>Y轴设置</label>
<div class="layout-config__item--right">
<el-select size="mini" multiple :multiple-limit="options.type.indexOf('pie') > -1 ? 1 : 100" v-model="options.dataY" collapse-tags placeholder="请选择Y轴" @change="onChooseChange">
<el-option
v-for="(item, index) in keys"
:key="index"
:label="item"
:value="item">
</el-option>
</el-select>
</div>
</div>
</div>
</div>
</template>
<script>
import vueJsonEditor from 'vue-json-editor'
export default {
name: 'dataCofing',
props: {
options: Object,
instance: Function,
dict: Object,
params: Object,
urlPrefix: String
},
data () {
return {
dataTypes: [
{
value: 'staticData',
label: '静态数据'
},
{
value: 'dynamicData',
label: '动态数据'
},
{
value: 'apiData',
label: '接口'
}
],
isShowEditor: false,
json: {},
sourceDataId: '',
sourceData: [],
keys: [],
monitorList: [],
list: []
}
},
components: {
vueJsonEditor
},
mounted () {
this.getDataList()
if ((this.options.dataY && this.options.dataY.length && this.options.dataX) || this.options.type === 'monitor') {
const api = this.options.dataType === 'apiData' ? this.options.api : `${this.urlPrefix}/appdiylargescreen/statisticsByLsid?id=${this.options.sourceDataId}`
this.instance.post(api).then(res => {
if (res.code == 0) {
if (res.data.length && this.options.type !== 'monitor') {
this.list = res.data
this.keys = Object.keys(res.data[0])
this.$nextTick(() => {
this.onChooseChange()
})
} else if (this.options.type === 'monitor') {
this.monitorList = res.data
if (this.options.src) {
const obj = res.data.filter(v => this.options.title === v.name)
if (obj.length) {
this.options.src = obj[0].url
}
}
}
}
})
}
},
methods: {
showEditor () {
this.json = JSON.parse(JSON.stringify(this.options.staticData))
this.isShowEditor = true
},
onMoniterId (e) {
this.instance.post(`${this.urlPrefix}/appzyvideoequipment/getWebSdkUrl?deviceId=${e}`).then(res => {
if (res.code == 0) {
this.options.src = JSON.parse(res.data).url
}
})
},
getDataList () {
this.instance.post(`${this.urlPrefix}/appdiylargescreen/allDatasourceByPage`, null, {
params: {
current: 1,
size: 10000
}
}).then(res => {
if (res.code == 0) {
this.sourceData = res.data.records
}
})
},
onApiChange () {
this.options.dataX = ''
this.options.dataY = []
this.instance.post(this.options.api).then(res => {
if (res.code == 0) {
if (res.data.length) {
if (this.options.type === 'table') {
const keys = Object.keys(res.data[0])
const list = res.data
this.options.apiData = keys.map(v => {
let obj = {}
list.forEach((item, index) => {
obj[`v${index}`] = item[v]
})
return {
row: v,
...obj
}
})
} else if (this.options.type === 'summary') {
this.options.apiData = Object.keys(res.data[0]).map(item => {
return {
key: item,
value: res.data[0][item]
}
})
} else if (this.options.type === 'monitor') {
this.monitorList = res.data
} else {
this.list = res.data
this.keys = Object.keys(res.data[0])
}
}
}
})
},
onChooseChange () {
let arr = []
if (this.options.dataX && this.options.dataY.length) {
this.list.forEach(item => {
let obj = {}
this.options.dataY.forEach(v => {
obj[v] = item[v]
})
arr.push({
[this.options.dataX]: item[this.options.dataX],
...obj
})
})
this.options[this.options.dataType] = arr
}
},
onDataChange (e) {
this.options.dataX = ''
this.options.dataY = []
this.instance.post(`${this.urlPrefix}/appdiylargescreen/statisticsByLsid?id=${e}`).then(res => {
if (res.code == 0) {
if (res.data.length) {
if (this.options.type === 'table') {
const keys = Object.keys(res.data[0])
const list = res.data
this.options.dynamicData = keys.map(v => {
let obj = {}
list.forEach((item, index) => {
obj[`v${index}`] = item[v]
})
return {
row: v,
...obj
}
})
} else if (this.options.type === 'summary') {
this.options.dynamicData = Object.keys(res.data[0]).map(item => {
return {
key: item,
value: res.data[0][item]
}
})
} else {
this.list = res.data
this.keys = Object.keys(res.data[0])
}
}
}
})
},
onConfirm () {
this.$set(this.options, 'staticData', JSON.parse(JSON.stringify(this.json)))
this.isShowEditor = false
this.$emit('change')
}
}
}
</script>
<style lang="scss">
.el-dialog__body {
.jsoneditor-vue {
height: 480px;
.jsoneditor-poweredBy {
display: none;
}
}
}
.layout-config__group--wrapper {
.layout-config__code .jsoneditor-vue {
.jsoneditor-menu {
display: none;
}
.jsoneditor {
border: 1px solid #030411;
background: #0e1013;
}
.jsoneditor-field {
color: gray;
}
.jsoneditor-tree button:focus {
background-color: transparent;
outline: none;
}
}
.layout-config__group {
padding: 10px 10px 20px;
border-bottom: 1px solid #000000;
&:last-child {
border: none;
}
.layout-config__code {
position: relative;
padding-left: 10px;
.layout-config__code--btn {
position: absolute;
right: 0;
top: 0;
color: gray;
z-index: 1;
&:hover {
opacity: 0.8 ;
}
}
}
& > h2 {
margin-bottom: 20px;
color: #FFFFFF;
font-size: 15px;
font-weight: 700;
}
}
.layout-config__item {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 10px;
&:last-child {
margin-bottom: 0;
}
label {
flex-shrink: 0;
width: 60px;
color: #FFFFFF;
font-size: 12px;
text-align: right;
}
.layout-config__item--right {
display: flex;
align-items: center;
justify-content: flex-end;
width: 200px;
text-align: right;
}
.el-select .el-tag {
color: #fff;
background: transparent;
}
input {
background: #262C33;
font-size: 12px;
color: #fff;
border: 1px solid #030411;
}
.el-input__icon {
color: #fff;
}
.el-switch__label {
color: #fff;
}
.el-select {
width: 100%;
&:last-child {
margin-right: 0;
}
input {
background: #262C33;
font-size: 12px;
color: #fff;
border: 1px solid #030411;
}
.el-input__icon {
color: #fff;
}
}
}
}
</style>