web端产品库 vite版本

This commit is contained in:
aixianling
2022-04-27 18:18:57 +08:00
parent ee93320cad
commit 4f0178c627
172 changed files with 4520 additions and 16858 deletions

View File

@@ -7,63 +7,67 @@
<template #content>
<ai-search-bar>
<template slot="left">
<el-button type="primary" icon="iconfont iconAdd" @click="handleAdd"
>添加</el-button
>
<el-button type="primary" icon="iconfont iconAdd" @click="handleAdd">添加</el-button>
</template>
<template slot="right">
<el-input
v-model="search.title"
class="search-input"
size="small"
placeholder="请输入课程主题"
clearable
v-throttle="
v-model="search.title"
class="search-input"
size="small"
placeholder="请输入课程主题"
clearable
v-throttle="
() => {
(search.current = 1), getList();
}
"
@clear="(search.current = 1), (search.title = ''), getList()"
suffix-icon="iconfont iconSearch"
@clear="(search.current = 1), (search.title = ''), getList()"
suffix-icon="iconfont iconSearch"
>
</el-input>
</template>
</ai-search-bar>
<ai-table
:tableData="tableData"
:col-configs="colConfigs"
stripe
:total="total"
:current.sync="page.current"
:size.sync="page.size"
style="margin-top: 10px"
@getList="getList"
:tableData="tableData"
:col-configs="colConfigs"
stripe
:total="total"
:current.sync="page.current"
:size.sync="page.size"
style="margin-top: 10px"
@getList="getList"
:dict="dict"
>
<el-table-column
slot="options"
label="操作"
align="center"
width="230px"
fixed="right"
slot="options"
label="操作"
align="center"
width="230px"
fixed="right"
>
<div slot-scope="{ row }" class="table-options">
<el-button
type="text"
:title="row.status == 0 ? '发布' : '取消发布'"
@click="handleChange(row)"
>{{ row.status == 0 ? "发布" : "取消发布" }}</el-button
type="text"
:title="row.status == 0 ? '发布' : '取消发布'"
@click="handleChange(row)"
>{{ row.status == 0 ? "发布" : "取消发布" }}
</el-button
>
<el-button type="text" title="添加" @click="handleAddSeries(row)"
>添加剧集</el-button
>添加剧集
</el-button
>
<el-button type="text" title="详情" @click="handleDetail(row)"
>详情</el-button
>详情
</el-button
>
<el-button type="text" title="编辑" @click="handleEdit(row)"
>编辑</el-button
>编辑
</el-button
>
<el-button type="text" title="删除" @click="handleDelete(row)"
>删除</el-button
>删除
</el-button
>
</div>
</el-table-column>
@@ -71,14 +75,14 @@
</template>
</ai-list>
<component
:is="comp"
v-else
:row="row"
:instance="instance"
:dict="dict"
:permissions="permissions"
@back="back"
:isEdit="isEdit"
:is="comp"
v-else
:row="row"
:instance="instance"
:dict="dict"
:permissions="permissions"
@back="back"
:isEdit="isEdit"
></component>
</section>
</template>
@@ -86,12 +90,12 @@
<script>
import partyClassAdd from "./components/partyClassAdd";
import seriesManage from "./components/seriesManage";
import { mapState } from "vuex";
import {mapState} from "vuex";
export default {
name: "AppPartyHistoryClass",
label: "党员学习",
components: { partyClassAdd, seriesManage },
components: {partyClassAdd, seriesManage},
props: {
instance: Function,
dict: Object,
@@ -121,37 +125,21 @@ export default {
...mapState(["user"]),
colConfigs() {
return [
{ label: "课程主题", prop: "title" },
{
label: "更新状态",
render: (h, { row }) => [
<span>
{" "}
{this.dict.getLabel(
"classroomUpdateStatus",
row.updateStatus
)}{" "}
</span>,
],
},
{ label: "更新时间", prop: "updateDate" },
{ label: "发布时间", prop: "createDate" },
{
label: "发布状态",
render: (h, { row }) => [
<span> {this.dict.getLabel("newsCenterStatus", row.status)} </span>,
],
},
{ label: "发布组织", prop: "organizationName" },
{ slot: "options" },
{label: "课程主题", prop: "title"},
{label: "更新状态", dict: "classroomUpdateStatus", prop: "updateStatus"},
{label: "更新时间", prop: "updateDate"},
{label: "发布时间", prop: "createDate"},
{label: "发布状态", prop: "status", dict: "newsCenterStatus"},
{label: "发布组织", prop: "organizationName"},
{slot: "options"},
];
},
},
methods: {
handleChange(row) {
this.$confirm(`是否确定要${row.status == 0 ? "发布" : "取消发布"}?`).then(
(_) => {
this.instance
(_) => {
this.instance
.post("/app/apppartyclassroom/addOrUpdate", {
id: row.id,
status: row.status == 0 ? 1 : 0,
@@ -159,12 +147,12 @@ export default {
.then((res) => {
if (res.code == 0) {
this.$message.success(
`${row.status == 0 ? "发布成功" : "取消发布成功"}`
`${row.status == 0 ? "发布成功" : "取消发布成功"}`
);
this.getList();
}
});
}
}
);
},
handleAddSeries(row) {
@@ -172,20 +160,20 @@ export default {
this.comp = "seriesManage";
this.row = row;
},
handleDelete({ id }) {
handleDelete({id}) {
this.$confirm("确定要删除吗?").then((_) => {
this.instance
.post("/app/apppartyclassroom/delete", null, {
params: {
ids: id,
},
})
.then((res) => {
if (res.code == 0) {
this.$message.success("删除成功");
this.getList();
}
});
.post("/app/apppartyclassroom/delete", null, {
params: {
ids: id,
},
})
.then((res) => {
if (res.code == 0) {
this.$message.success("删除成功");
this.getList();
}
});
});
},
handleEdit(row) {
@@ -228,18 +216,18 @@ export default {
},
getList() {
this.instance
.post("/app/apppartyclassroom/list", null, {
params: {
...this.page,
...this.search,
},
})
.then((res) => {
if (res?.data) {
this.tableData = res.data.records;
this.total = res.data.total;
}
});
.post("/app/apppartyclassroom/list", null, {
params: {
...this.page,
...this.search,
},
})
.then((res) => {
if (res?.data) {
this.tableData = res.data.records;
this.total = res.data.total;
}
});
},
},
created() {

View File

@@ -70,7 +70,7 @@ export default {
...mapState(["user"]),
colConfigs() {
return [
{label: "类型", render: (h, {row}) => [< span> {row.type == 1 ? '单选题' : '多选题'} < /span>]},
{label: "类型", render: (h, {row}) =>h('p',row.type == 1 ? '单选题' : '多选题')},
{label: "题目", prop: "title"},
{label: "创建时间", prop: "createDate"},
{slot: "options"}

View File

@@ -60,7 +60,7 @@
</section>
</template>
<script>
<script lang="jsx">
import {mapState} from 'vuex'
import DeviceSlider from "../components/deviceSlider"
import LocateDialog from "../components/locateDialog"
@@ -227,7 +227,7 @@
if (node.isLeaf) {
return (
<div class="flexRow">
{index > 0 ?
{index > 0 ?
<span>{ index }</span>
: ''
}

View File

@@ -1,99 +0,0 @@
<template>
<ai-list v-if="!isShowDetail">
<template slot="title">
<ai-title title="大屏列表" :isShowBottomBorder="false" :instance="instance"></ai-title>
</template>
<template slot="tabs">
<el-tabs v-model="currIndex">
<el-tab-pane v-for="(tab,i) in tabs" :key="i" :label="tab.label">
<component :urlPrefix="urlPrefix" :areaId="areaId" :ref="tab.name" v-if="currIndex == i" :is="tab.comp"
@change="onChange" lazy
:instance="instance" :dict="dict" :permissions="permissions"/>
</el-tab-pane>
</el-tabs>
</template>
</ai-list>
<Add v-else-if="componentName === 'Add'" :urlPrefix="urlPrefix" :areaId="areaId" :params="params" :instance="instance"
:dict="dict"
:permissions="permissions" @change="onChange"></Add>
<SourceData v-else-if="componentName === 'SourceData'" :urlPrefix="urlPrefix" :params="params" :instance="instance"
:dict="dict"
:permissions="permissions" @change="onChange"></SourceData>
</template>
<script>
import List from './components/List.vue'
import Add from './components/Add'
import SourceData from './components/SourceData'
import dvui from '../../../project/dvui/entries'
import Vue from "vue";
Vue.use(dvui)
export default {
name: 'AppDesigner',
label: '大屏设计',
components: {
List,
Add,
SourceData
},
props: {
instance: Function,
dict: Object,
permissions: Function,
urlPrefix: {
type: String,
default: '/app'
}
},
computed: {
tabs() {
return [
{label: '大屏列表', name: 'FormList', comp: List, permission: ''}
].filter(() => {
return true
})
}
},
data() {
return {
currIndex: '0',
componentName: '',
params: {},
areaId: '',
isShowDetail: false
}
},
methods: {
onChange(data) {
if (data.type === 'list') {
this.componentName = 'List'
this.isShowDetail = false
this.params = data.params
}
if (data.type === 'add') {
this.componentName = 'Add'
this.isShowDetail = true
this.params = data.params
}
if (data.type === 'SourceData') {
this.componentName = 'SourceData'
this.isShowDetail = true
this.params = data.params
}
}
},
created() {
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@@ -1,297 +0,0 @@
<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"
row-key="id"
: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'
import Sortable from 'sortablejs'
export default {
name: 'Add',
props: {
instance: Function,
dict: Object,
params: Object,
urlPrefix: String
},
inject: {
home:{default: ''}
},
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)
}
},
mounted () {
},
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
this.$nextTick(() => {
this.rowDrop()
})
}
}
})
},
rowDrop() {
const tbody = document.querySelector('.el-table__body-wrapper tbody')
const _this = this
Sortable.create(tbody, {
onEnd({ newIndex, oldIndex }) {
const currRow = _this.tableData.splice(oldIndex, 1)[0]
_this.tableData.splice(newIndex, 0, currRow)
}
})
},
toViewer(id) {
this.screenId = id
},
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('提交成功')
this.home && this.home.refreshDvOptions && this.home.refreshDvOptions()
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

@@ -1,92 +0,0 @@
<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

@@ -1,178 +0,0 @@
<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('cwpStatus')">
</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.name"
size="small"
placeholder="请输入模板名称或创建人"
clearable
v-throttle="() => {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="160px" fixed="right" label="操作" align="center">
<template slot-scope="{ row }">
<div class="table-options">
<el-button type="text" @click="toEdit(row.id)">编辑</el-button>
<el-button type="text" @click="copy(row.id)">复制</el-button>
</div>
</template>
</el-table-column>
</ai-table>
<ai-dialog
:visible.sync="isShowAdd"
width="780px"
title="复制大屏"
@close="onClose"
@onConfirm="onConfirm">
<el-form ref="form" :model="form" label-width="110px" label-position="right">
<div class="ai-form" :model="form" label-width="110px" label-position="right">
<el-form-item label="名称" prop="name" style="width: 100%;" :rules="[{ required: true, message: '请输入名称', trigger: 'blur' }]">
<el-input size="small" placeholder="请输入名称" v-model="form.name"></el-input>
</el-form-item>
</div>
</el-form>
</ai-dialog>
</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,
name: ''
},
form: {
name: ''
},
id: '',
isShowAdd: false,
colConfigs: [
{ prop: 'name', label: '模板名称' },
{ prop: 'createUserName', align: 'center', label: '创建人' },
{ prop: 'description', align: 'center', label: '描述' },
{ prop: 'status', align: 'center', label: '状态', formart: v => this.dict.getLabel('cwpStatus', v) },
{ prop: 'createTime', align: 'center', label: '创建时间' }
],
tableData: [],
total: 0,
loading: false
}
},
created () {
this.dict.load('cwpStatus').then(() => {
this.getList()
})
},
mounted () {
this.loading = true
},
methods: {
copy (id) {
this.id = id
this.isShowAdd = true
},
onClose () {
this.id = ''
this.form.name = ''
},
onConfirm () {
this.$refs.form.validate((valid) => {
if (valid) {
this.instance.post(`${this.urlPrefix}/appdiylargescreen/copyLargeScreenProject`, null, {
params: {
...this.form,
id: this.id
}
}).then(res => {
if (res.code === 0) {
this.$message.success('复制成功')
this.isShowAdd = false
this.getList()
}
})
}
})
},
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'
})
}
}
}
</script>
<style scoped lang="scss">
</style>

View File

@@ -1,188 +0,0 @@
<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'" :summaryTitle="data.summaryTitle" :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

@@ -1,456 +0,0 @@
<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"
v-throttle="() => {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="920px"
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="dataRange" :rules="[{ required: true, message: '请选择数据范围', trigger: 'change' }]">
<el-radio-group v-model="form.type">
<el-radio label="0">村微应用</el-radio>
<el-radio label="1">SQL</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item v-if="form.type === '1'" label="sql语句" style="width: 100%;" prop="description" :rules="[{ required: true, message: '请输入sql语句', trigger: 'blur' }]">
<el-input
size="small"
type="textarea"
placeholder="请输入数据源描述"
v-model="form.sqlContent">
</el-input>
</el-form-item>
<el-form-item v-if="form.type === '0'" 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 v-if="form.type === '0'" 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' && form.type === '0'" prop="count" :rules="[{ required: true, message: '请输入数据条数', trigger: 'blur' }]">
<el-input
size="small"
placeholder="请输入数据条数"
v-model="form.count">
</el-input>
</el-form-item>
<div v-if="form.type === '0'">
<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>
</div>
<el-form-item style="width: 100%;" v-if="form.type === '0'">
<el-button type="primary" @click="add('statisticsConfigs')">添加统计项</el-button>
</el-form-item>
<div v-if="form.type === '0'">
<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>
</div>
<el-form-item style="width: 100%;" v-if="form.type === '0'">
<el-button type="primary" @click="add('groupConfigs')">添加分组</el-button>
</el-form-item>
<div v-if="form.type === '0'">
<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>
</div>
<el-form-item style="width: 100%;" v-if="form.type === '0'">
<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', align: 'center', label: '表名' },
{ prop: 'description', align: 'center', label: '描述' },
{ prop: 'type', align: 'center', label: '类型', formart: v => v === '0' ? '村微应用' : 'sql语句' },
{ prop: 'createUserName', align: 'center', label: '创建人' },
{ prop: 'createTime', align: 'center', label: '创建时间' }
],
tableData: [],
filedList: [],
appList: [],
form: {
orderType: 'asc',
dataRange: '0',
type: '0',
sqlContent: '',
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).length && 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 = []
if (this.filedList.length) {
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

@@ -1,459 +0,0 @@
<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>
<code-editor v-model="json" :lint="true" auto-format height="440px"></code-editor>
</div>
</ai-dialog>
<div class="layout-config__group" v-if="options.monitorType !== 'hik' && options.monitorType !== 'dahua'">
<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' || options.monitorType === 'dahua'">
<h2>基础设置</h2>
<div class="layout-config__item">
<label>视频地址</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' || options.monitorType === 'slw')">
<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'
import { CodeEditor } from 'bin-code-editor'
import 'bin-code-editor/lib/styles/index.css'
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: [],
jsonData: `{"title":"测试json数据","children":[{"name":"子项名称", "desc":"子项说明" },{"name":"子项名称1", "desc":"子项说明1" }]}`
}
},
components: {
vueJsonEditor,
CodeEditor
},
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.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') {
if (this.options.display === 'summary9') {
this.options.apiData = res.data
} else {
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(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>

View File

@@ -1,638 +0,0 @@
import lineChart1 from 'dvcp-dv-ui/components/AiEchart/template/line/lineChart1'
import lineChart2 from 'dvcp-dv-ui/components/AiEchart/template/line/lineChart2'
import lineChart3 from 'dvcp-dv-ui/components/AiEchart/template/line/lineChart3'
import lineChart4 from 'dvcp-dv-ui/components/AiEchart/template/line/lineChart4'
import lineChart5 from 'dvcp-dv-ui/components/AiEchart/template/line/lineChart5'
import barChart1 from 'dvcp-dv-ui/components/AiEchart/template/bar/barChart1'
import barChart2 from 'dvcp-dv-ui/components/AiEchart/template/bar/barChart2'
import barChart3 from 'dvcp-dv-ui/components/AiEchart/template/bar/barChart3'
import barChart8 from 'dvcp-dv-ui/components/AiEchart/template/bar/barChart8'
import barChart5 from 'dvcp-dv-ui/components/AiEchart/template/bar/barChart5'
import barChart7 from 'dvcp-dv-ui/components/AiEchart/template/bar/barChart7'
import barChart9 from 'dvcp-dv-ui/components/AiEchart/template/bar/barChart9'
import pieChart from 'dvcp-dv-ui/components/AiEchart/template/pie/pieChart2'
const components = [
{
type: 'chart',
label: '图表',
list: [
{
label: '柱状图',
type: 'bar',
list: [
{
code: 'widget-linechart',
type: 'barChart1',
label: '柱状图1',
title: '柱状图',
border: 'border1',
icon: 'icontext_box',
value: '',
thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/bar1.png',
width: 500,
sourceDataId: '',
height: 300,
dataX: '',
zIndex: 1,
dataY: [],
top: 0,
left: 0,
api: '',
apiData: [],
dataType: 'staticData',
staticData: [
{ name: '阿斯达', v1: 23 },
{ name: '水电费', v1: 12 },
{ name: '凡哥', v1: 67 },
{ name: '党费', v1: 98 }
],
config: barChart1,
dynamicData: []
},
{
code: 'widget-linechart',
type: 'barChart1',
label: '柱状图2',
icon: 'icontext_box',
value: '',
title: '柱状图2',
width: 500,
border: 'border1',
sourceDataId: '',
height: 300,
thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/bar2.png',
dataX: '',
dataY: [],
top: 0,
zIndex: 1,
left: 0,
dataType: 'staticData',
api: '',
apiData: [],
staticData: [
{ name: '阿斯达', v1: 23 },
{ name: '水电费', v1: 12 },
{ name: '凡哥', v1: 67 },
{ name: '党费', v1: 98 }
],
config: barChart2,
dynamicData: []
},
{
code: 'widget-linechart',
type: 'barChart3',
label: '柱状图3',
title: '柱状图3',
icon: 'icontext_box',
value: '',
width: 500,
sourceDataId: '',
height: 300,
thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/bar3.png',
dataX: '',
dataY: [],
border: 'border1',
top: 0,
left: 0,
zIndex: 1,
dataType: 'staticData',
api: '',
apiData: [],
staticData: [
{ name: '阿斯达', v1: 23 },
{ name: '水电费', v1: 12 },
{ name: '凡哥', v1: 67 },
{ name: '党费', v1: 98 }
],
config: barChart3,
dynamicData: []
},
{
code: 'widget-linechart',
type: 'barChart5',
label: '柱状图4',
title: '柱状图4',
icon: 'icontext_box',
value: '',
width: 500,
sourceDataId: '',
height: 300,
dataX: '',
dataY: [],
zIndex: 1,
thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/bar5.png',
top: 0,
left: 0,
border: 'border1',
api: '',
apiData: [],
dataType: 'staticData',
staticData: [
{ name: '阿斯达', v1: 23 },
{ name: '水电费', v1: 12 },
{ name: '凡哥', v1: 67 },
{ name: '党费', v1: 98 }
],
config: barChart5,
dynamicData: []
},
{
code: 'widget-linechart',
type: 'barChart7',
label: '柱状图5',
title: '柱状图5',
icon: 'icontext_box',
value: '',
width: 500,
sourceDataId: '',
height: 300,
thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/bar7.png',
dataX: '',
zIndex: 1,
dataY: [],
top: 0,
left: 0,
api: '',
apiData: [],
dataType: 'staticData',
staticData: [
{ name: '阿斯达', v1: 23 },
{ name: '水电费', v1: 12 },
{ name: '凡哥', v1: 67 },
{ name: '党费', v1: 98 }
],
config: barChart7,
dynamicData: []
},
{
code: 'widget-linechart',
type: 'barChart8',
label: '柱状图6',
title: '柱状图6',
icon: 'icontext_box',
value: '',
width: 500,
sourceDataId: '',
border: 'border1',
height: 300,
thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/bar8.png',
dataX: '',
dataY: [],
zIndex: 1,
top: 0,
left: 0,
api: '',
apiData: [],
dataType: 'staticData',
staticData: [
{ name: '阿斯达', v1: 23 },
{ name: '水电费', v1: 12 },
{ name: '凡哥', v1: 67 },
{ name: '党费', v1: 98 }
],
config: barChart8,
dynamicData: []
},
{
code: 'widget-linechart',
type: 'barChart9',
label: '柱状图7',
title: '柱状图7',
border: 'border1',
icon: 'icontext_box',
value: '',
width: 500,
thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/bar9.png',
sourceDataId: '',
height: 300,
dataX: '',
dataY: [],
zIndex: 1,
top: 0,
left: 0,
api: '',
apiData: [],
dataType: 'staticData',
staticData: [
{ name: '阿斯达', v1: 23 },
{ name: '水电费', v1: 12 },
{ name: '凡哥', v1: 67 },
{ name: '党费', v1: 98 }
],
config: barChart9,
dynamicData: []
}
]
},
{
label: '折线图',
type: 'line',
list: [
{
code: 'widget-linechart',
type: 'lineChart1',
label: '折线图1',
title: '折线图1',
border: 'border1',
icon: 'icontext_box',
value: '',
width: 500,
height: 300,
top: 0,
left: 0,
zIndex: 1,
api: '',
apiData: [],
thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/line1.png',
dataX: '',
dataY: [],
dataType: 'staticData',
staticData: [
{ name: '阿斯达', v1: 23, v2: 33 },
{ name: '水电费', v1: 12, v2: 34 },
{ name: '凡哥', v1: 67, v2: 25 },
{ name: '党费', v1: 98, v2: 85 }
],
config: lineChart1,
sourceDataId: '',
dynamicData: []
},
{
code: 'widget-linechart',
type: 'lineChart2',
label: '折线图2',
title: '折线图2',
border: 'border1',
icon: 'icontext_box',
value: '',
width: 500,
thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/line2.png',
height: 300,
top: 0,
left: 0,
dataX: '',
dataY: [],
zIndex: 1,
api: '',
apiData: [],
dataType: 'staticData',
staticData: [
{ name: '阿斯达', v1: 23, v2: 33 },
{ name: '水电费', v1: 12, v2: 34 },
{ name: '凡哥', v1: 67, v2: 25 },
{ name: '党费', v1: 98, v2: 85 }
],
config: lineChart2,
sourceDataId: '',
dynamicData: []
},
{
code: 'widget-linechart',
type: 'lineChart3',
label: '折线图3',
title: '折线图3',
icon: 'icontext_box',
border: 'border1',
value: '',
width: 500,
height: 300,
zIndex: 1,
thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/line3.png',
top: 0,
left: 0,
dataX: '',
dataY: [],
api: '',
apiData: [],
dataType: 'staticData',
staticData: [
{ name: '阿斯达', v1: 23, v2: 33 },
{ name: '水电费', v1: 12, v2: 34 },
{ name: '凡哥', v1: 67, v2: 25 },
{ name: '党费', v1: 98, v2: 85 }
],
config: lineChart3,
sourceDataId: '',
dynamicData: []
},
{
code: 'widget-linechart',
type: 'lineChart4',
label: '折线图4',
title: '折线图4',
icon: 'icontext_box',
value: '',
border: 'border1',
width: 500,
height: 300,
zIndex: 1,
thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/line4.png',
top: 0,
left: 0,
dataX: '',
dataY: [],
api: '',
apiData: [],
dataType: 'staticData',
staticData: [
{ name: '阿斯达', v1: 23, v2: 33 },
{ name: '水电费', v1: 12, v2: 34 },
{ name: '凡哥', v1: 67, v2: 25 },
{ name: '党费', v1: 98, v2: 85 }
],
config: lineChart4,
sourceDataId: '',
dynamicData: []
},
{
code: 'widget-linechart',
type: 'lineChart5',
label: '折线图5',
title: '折线图5',
icon: 'icontext_box',
value: '',
border: 'border1',
width: 500,
height: 300,
zIndex: 1,
top: 0,
left: 0,
dataX: '',
thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/line5.png',
dataY: [],
api: '',
apiData: [],
dataType: 'staticData',
staticData: [
{ name: '阿斯达', v1: 23, v2: 33 },
{ name: '水电费', v1: 12, v2: 34 },
{ name: '凡哥', v1: 67, v2: 25 },
{ name: '党费', v1: 98, v2: 85 }
],
config: lineChart5,
sourceDataId: '',
dynamicData: []
}
]
},
{
label: '饼图',
type: 'pie',
list: [
{
code: 'widget-linechart',
type: 'pieChart',
label: '饼图',
title: '饼图',
icon: 'icontext_box',
value: '',
border: 'border1',
width: 500,
height: 300,
zIndex: 1,
top: 0,
left: 0,
thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/pie.png',
dataX: '',
dataY: [],
api: '',
apiData: [],
dataType: 'staticData',
staticData: [
{ name: '阿斯达', v1: 23, v2: 33 },
{ name: '水电费', v1: 12, v2: 34 },
{ name: '凡哥', v1: 67, v2: 25 },
{ name: '党费', v1: 98, v2: 85 }
],
config: pieChart,
sourceDataId: '',
dynamicData: []
}
]
}
]
},
{
type: 'table',
label: '表格',
list: [
{
label: '表格',
type: 'table',
list: [
{
type: 'table',
label: '表格',
title: '表格',
border: 'border1',
width: 650,
height: 400,
zIndex: 1,
thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/table.png',
dataX: '',
dataY: [],
rowNum: 7,
isShowIndex: '1',
sourceDataId: '',
api: '',
apiData: [],
dataType: 'staticData',
dynamicData: [],
staticData: [
{ name: '列1', v: 23, v2: 3 },
{ name: '列2', v: 12, v2: 4 },
{ name: '列2', v: 12, v2: 4 }
]
}
]
}
]
},
{
type: 'other',
label: '其他',
list: [
{
label: '地图',
type: 'map',
list: [
{
type: 'map',
label: '地图',
display: 'map',
width: 840,
height: 534,
left: 0,
top: 0,
mask: '2',
areaId: '',
zIndex: 1,
apiData: [],
dataType: 'staticData',
dynamicData: [],
staticData: [
{
content: '中卫慧通',
lng: 117.1339399,
lat: 36.7190487
}
],
api: '',
thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/map.png'
}
]
},
{
label: '边框',
type: 'panel',
list: [
{
type: 'panel',
label: '边框',
title: '边框',
border: 'border0',
width: 400,
height: 400,
isZoom: false,
zIndex: 1,
thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/border.png'
}
]
},
{
label: '装饰',
type: 'display',
list: [
{
type: 'display',
label: '装饰',
display: 'display0',
width: 840,
height: 540,
isZoom: false,
zIndex: 1,
title: '标题',
thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/display.png',
sourceDataId: '',
dataType: 'staticData',
staticData: [
{
key: '个人服务办理',
value: 247
},
{
key: '同比上月',
value: 247
}
]
}
]
},
{
label: '轮播图',
type: 'swiper',
list: [
{
type: 'swiper',
label: '轮播图',
width: 400,
height: 300,
zIndex: 1,
border: 'border2',
dataType: 'staticData',
staticData: [
{
img: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/pie.png',
title: '湖羊',
content: `歙县众城湖羊养殖专业合作社
徐晓红 - 18273645627
歙县郑村镇唐跃村碉墅`
}
],
thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/swiper.png'
}
]
},
{
label: '视频播放器',
type: 'video',
list: [
{
type: 'video',
label: '视频播放器',
width: 400,
height: 300,
zIndex: 1,
src: '',
border: 'border2',
thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/swiper.png'
}
]
},
{
label: '数据统计',
type: 'summary',
list: [
{
type: 'summary',
label: '数据统计',
display: 'summary0',
width: 480,
height: 240,
zIndex: 1,
top: 0,
left: 0,
dataX: '',
dataY: [],
summaryTitle: '',
border: 'border3',
sourceDataId: '',
title: '数据统计',
dataType: 'staticData',
staticData: [
{
key: '个人服务办理',
value: 247
},
{
key: '同比上月',
value: 247
}
],
dynamicData: [],
thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/total.png'
}
]
},
{
label: '视频监控',
type: 'monitor',
list: [
{
type: 'monitor',
label: '视频监控',
src: '',
width: 480,
height: 240,
zIndex: 1,
top: 0,
left: 0,
title: '',
moniterId: '',
monitorType: 'cmcc',
api: '/app/appzyvideoequipment/list2',
border: 'border2',
sourceDataId: '',
dataType: 'staticData',
staticData: '',
dynamicData: '',
thumb: 'https://cdn.cunwuyun.cn/dvcp/dv/tpl/video.png'
}
]
}
]
}
]
export { components }

View File

@@ -1,88 +0,0 @@
<template>
<section class="AiDataPanel">
<b class="item-title" v-text="label"/>
<div class="num-bg">
<span ref="num" class="num" v-text="num"/>
</div>
</section>
</template>
<script>
import {gsap} from 'gsap'
export default {
name: "AiDataPanel",
props: {
label: {default: "标题"},
value: {default: 0}
},
data() {
return {
num: 0
}
},
methods: {
animation() {
let demo = {num: Math.max(this.value - 30, 0)}
gsap.to(demo, 1, {
num: this.value, onUpdate: () => {
this.num = demo.num?.toFixed(0)
}
})
}
},
mounted() {
this.animation()
}
}
</script>
<style lang="scss" scoped>
.AiDataPanel {
flex: 1;
width: 172px;
height: 160px;
display: flex;
flex-direction: column;
align-items: center;
background: #000;
& + .AiDataPanel {
margin-left: 16px;
}
.item-title {
font-size: 24px;
line-height: 32px;
background-image: -webkit-linear-gradient(bottom, #35BEFF, #EBF9FF, #FFFFFF);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
margin-top: 30px;
}
.num-bg {
width: 100%;
height: 160px;
background-image: url(https://cdn.cunwuyun.cn/dvcp/dv/dianjiang/number-bg.png);
background-size: 100% 100%;
position: relative;
margin-top: -76px;
.num {
position: absolute;
left: 0;
bottom: 30px;
width: 100%;
text-align: center;
height: 50px;
font-size: 40px;
font-family: D-DIN-Bold, D-DIN;
font-weight: bold;
line-height: 54px;
background-image: -webkit-linear-gradient(bottom, #35BEFF, #EBF9FF, #FFFFFF);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
}
}
</style>

View File

@@ -1,30 +0,0 @@
<template>
<section class="AiStaData">
<ai-data-panel v-for="op in data" :key="op[key]"
:label="op[label]" :value="op[key]"/>
</section>
</template>
<script>
import AiDataPanel from "./AiDataPanel";
export default {
name: "AiStaData",
components: {AiDataPanel},
props: {
data: {default: () => []},
key: {default: "id"},
label: {default: "label"},
}
}
</script>
<style lang="scss" scoped>
.AiStaData {
width: 100%;
display: flex;
align-items: center;
flex-wrap: wrap;
justify-content: center;
}
</style>

View File

@@ -1,223 +0,0 @@
<template>
<div class="AppGigscreenViewer">
<div v-if="!component">
<div
class="component-item"
:style="{
width: item.width + 'px',
height: item.height + 'px',
left: item.left * scale + 'px',
top: item.top * scale + 'px',
position: 'absolute',
zIndex: item.zIndex,
transform: `scale(${scale})`
}"
v-for="(item, index) in componentList"
:key="index">
<RenderElement :data="item" :index="index"></RenderElement>
</div>
</div>
<components v-else :is="component" :dict="dict" :instance="instance" :nav="meta"/>
</div>
</template>
<script>
import RenderElement from '../designer/components/RenderElement'
export default {
name: 'AppGigscreenViewer',
label: '大屏预览',
props: {
instance: Function,
dict: Object,
id: String,
urlPrefix: {
type: String,
default: '/app'
}
},
watch: {
id(v) {
this.getInfo(v)
}
},
components: {
RenderElement
},
data() {
return {
component: '',
dashboard: {
title: '大屏',
width: 1920,
height: 1080,
backgroundColor: '',
backgroundImage: []
},
componentList: [],
scale: 1,
meta: {}
}
},
created() {
this.getInfo(this.id)
// this.scale = document.body.clientWidth / 1920
},
mounted() {
this.$nextTick(() => {
let content = document.querySelector('#dv-full-screen-container')
if (content) {
const transform = content.style.transform
const scale = transform.replace('scale', '').replace('(', '').replace(')', '')
if (scale == 1) {
this.scale = document.body.clientWidth / 1920
}
}
})
},
methods: {
getInfo(id) {
this.component = null
this.instance.post(`${this.urlPrefix}/appdiylargescreen/queryLargeScreenDetailById?id=${id}`).then(res => {
if (res?.data) {
const config = JSON.parse(res.data.config)
if (config.custom) {
this.component = config.custom
this.meta = config?.meta || {}
} else {
this.componentList = JSON.parse(res.data.config).config
this.dashboard = JSON.parse(res.data.config).dashboard
this.componentList.forEach((item, index) => {
if (item.dataType !== 'staticData' && ((item.type.indexOf('Chart') > -1) || item.type === 'display' || item.type === 'table' || item.type === 'summary')) {
this.getSourceData(item, index)
}
if (item.type === 'monitor' && item.monitorType === 'cmcc') {
this.instance.post(`${this.urlPrefix}/appzyvideoequipment/getWebSdkUrl?deviceId=${item.moniterId}`).then(res => {
if (res.code == 0) {
this.$set(this.componentList[index], 'src', JSON.parse(res.data).url)
}
})
}
if (item.type === 'monitor' && item.monitorType === 'slw') {
this.instance.post(`${this.urlPrefix}/appzyvideoequipment/getWebSdkUrl?deviceId=${item.moniterId}`).then(res => {
if (res.code == 0) {
this.$set(this.componentList[index], 'src', res.data)
}
})
}
})
}
}
})
},
getSourceData(item, index) {
const api = item.dataType === 'apiData' ? item.api : `${this.urlPrefix}/appdiylargescreen/statisticsByLsid?id=${item.sourceDataId}`
this.instance.post(api).then(res => {
if (res.code == 0) {
if (res.data.length) {
const keys = Object.keys(res.data[0])
const list = res.data
let dynamicData = []
if (item.type === 'table') {
dynamicData = keys.map(v => {
let obj = {}
list.forEach((item, index) => {
obj[`v${index}`] = item[v]
})
return {
row: v,
...obj
}
})
} else if (item.type === 'summary') {
if (item.display === 'summary9') {
dynamicData = res.data
} else {
dynamicData = Object.keys(res.data[0]).map(item => {
return {
key: item,
value: res.data[0][item]
}
})
}
} else if (item.dataType === 'dynamicData' && !item.dataX && !item.dataY.length) {
dynamicData = Object.keys(res.data[0]).map(item => {
return {
label: item,
value: res.data[0][item]
}
})
} else {
if (item.dataX && item.dataY.length) {
list.forEach(i => {
let obj = {}
item.dataY.forEach(v => {
obj[v] = i[v]
})
dynamicData.push({
[item.dataX]: i[item.dataX],
...obj
})
})
}
}
this.$set(this.componentList[index], item.dataType, dynamicData)
}
}
})
},
close() {
this.$emit('close')
}
}
}
</script>
<style lang="scss">
.AppGigscreenViewer {
position: relative;
height: 100%;
background: transparent !important;
.component-item {
transform-origin: 0 0;
}
.dv-scroll-board {
height: calc(100%) !important;
.header-item {
color: #7e8697;
font-size: 16px;
}
.index {
display: inline-block;
width: 26px;
height: 26px;
line-height: 26px;
font-size: 16px;
background-color: #4F57FF !important;
}
}
.vdr {
border: none;
}
}
</style>

View File

@@ -104,17 +104,12 @@ export default {
return [
{prop: "residentName", label: "姓名"},
{prop: "description", label: "调整说明"},
{
prop: "changeIntegral", label: "类型", align: "center",
render: (h, {row}) => [< span> {+row.changeIntegral > 0 ? "加分" : '减分'
} < /span>]
},
{prop: "changeIntegral", label: "类型", align: "center", render: (h, {row}) => h('p', +row.changeIntegral > 0 ? "加分" : '减分')},
{
prop: "changeIntegral",
label: "积分",
align: "center",
render: (h, {row}) => [
<span>{row.changeIntegral > 0 ? `+${row.changeIntegral}` : `${row.changeIntegral}`}</span>]
render: (h, {row}) =>h('p',row.changeIntegral > 0 ? `+${row.changeIntegral}` : `${row.changeIntegral}`)
},
{prop: "doTime", label: "操作时间"},
{prop: "declareObjName", label: "操作人", align: "center"},

View File

@@ -26,168 +26,169 @@
</el-form>
</ai-dialog>
<locate-dialog v-model="locate" :ins="instance" :latlng="latlng" @confirm="v=>handleLocate(selected,v)"/>
<ai-area custom-clicker :input-clicker="false" v-model="selected.areaId" :hideLevel="disabledLevel" :instance="instance" ref="BindArea"
<ai-area custom-clicker :input-clicker="false" v-model="selected.areaId" :hideLevel="disabledLevel"
:instance="instance" ref="BindArea"
@change="handleSubmit(selected)"/>
</section>
</template>
<script>
import { mapState } from 'vuex'
import DeviceSlider from "../components/deviceSlider";
import LocateDialog from "../components/locateDialog";
<script lang="jsx">
import {mapState} from 'vuex'
import DeviceSlider from "../components/deviceSlider";
import LocateDialog from "../components/locateDialog";
export default {
name: "AppMonitorManage",
components: {LocateDialog, DeviceSlider},
label: "监控实况",
props: {
instance: Function,
dict: Object,
permissions: Function
export default {
name: "AppMonitorManage",
components: {LocateDialog, DeviceSlider},
label: "监控实况",
props: {
instance: Function,
dict: Object,
permissions: Function
},
computed: {
splitOps() {
return [
{label: "单分屏", value: 1, per: "100%"},
{label: "四分屏", value: 4, per: "49%"},
{label: "九分屏", value: 9, per: "32%"}
]
},
computed: {
splitOps() {
return [
{label: "单分屏", value: 1, per: "100%"},
{label: "四分屏", value: 4, per: "49%"},
{label: "九分屏", value: 9, per: "32%"}
]
},
currentSplitStyle() {
let per = this.splitOps.find(e => e.value == this.splitScreen)?.per || "100%"
return {width: per, height: per}
},
...mapState(['user'])
currentSplitStyle() {
let per = this.splitOps.find(e => e.value == this.splitScreen)?.per || "100%"
return {width: per, height: per}
},
...mapState(['user'])
},
data() {
return {
slider: true,
fullscreen: false,
splitScreen: 1,
monitors: [],
dialog: false,
locate: false,
selected: {
areaId: ''
},
latlng: null,
disabledLevel: 0,
rules: {
name: [{required: true, message: "请填写 设备名称"}]
}
data() {
return {
slider: true,
fullscreen: false,
splitScreen: 1,
monitors: [],
dialog: false,
locate: false,
selected: {
areaId: ''
},
latlng: null,
disabledLevel: 0,
rules: {
name: [{required: true, message: "请填写 设备名称"}]
}
},
}
},
created () {
this.selected.areaId = this.user.info.areaId
this.disabledLevel = this.user.info.areaList.length
},
created() {
this.selected.areaId = this.user.info.areaId
this.disabledLevel = this.user.info.areaList.length
},
methods: {
handleFullscreen() {
this.fullscreen = !this.fullscreen
this.$fullscreen(this.fullscreen)
},
handleSelectMonitor(monitor) {
let {id} = monitor,
index = this.monitors.findIndex(e => e.id == id)
if (index > -1) {
this.monitors.splice(index, 1)
this.monitors.map((e, i) => {
if (i > index) {
this.showMonitor(e, true)
}
})
} else if (this.monitors.length >= this.splitScreen && this.splitScreen > 1) {
this.$message.warning("可分屏监控已满,请先取消其他的监控")
} else {
this.showMonitor(monitor)
}
},
showMonitor(monitor, refresh = false) {
let {id: deviceId} = monitor
deviceId && this.instance.post("/app/appzyvideoequipment/getWebSdkUrl", null, {
params: {deviceId}
}).then(res => {
if (res?.data) {
let data = JSON.parse(res.data)
if (refresh) {
monitor.url = data.url
} else if (this.splitScreen == 1) {
this.monitors = [{...monitor, ...data}]
} else {
this.monitors.push({...monitor, ...data})
}
methods: {
handleFullscreen() {
this.fullscreen = !this.fullscreen
this.$fullscreen(this.fullscreen)
},
handleSelectMonitor(monitor) {
let {id} = monitor,
index = this.monitors.findIndex(e => e.id == id)
if (index > -1) {
this.monitors.splice(index, 1)
this.monitors.map((e, i) => {
if (i > index) {
this.showMonitor(e, true)
}
})
},
renderTreeItem: function (h, {node, data}) {
let show = data.deviceStatus==1 ? 'show' : ''
if (node.isLeaf) {
return (
<div class="flexRow">
<i class={['iconfont', 'iconshipinjiankong', show]}/>
<div>{node.label}</div>
<el-dropdown class="menuBtn" onCommand={e => this.handleSliderOption(e, data)}>
<i class="iconfont iconMore"/>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="edit">修改名称</el-dropdown-item>
<el-dropdown-item command="area">行政地区</el-dropdown-item>
<el-dropdown-item command="locate">地图标绘</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
)
} else return (
} else if (this.monitors.length >= this.splitScreen && this.splitScreen > 1) {
this.$message.warning("可分屏监控已满,请先取消其他的监控")
} else {
this.showMonitor(monitor)
}
},
showMonitor(monitor, refresh = false) {
let {id: deviceId} = monitor
deviceId && this.instance.post("/app/appzyvideoequipment/getWebSdkUrl", null, {
params: {deviceId}
}).then(res => {
if (res?.data) {
let data = JSON.parse(res.data)
if (refresh) {
monitor.url = data.url
} else if (this.splitScreen == 1) {
this.monitors = [{...monitor, ...data}]
} else {
this.monitors.push({...monitor, ...data})
}
}
})
},
renderTreeItem: function (h, {node, data}) {
let show = data.deviceStatus == 1 ? 'show' : ''
if (node.isLeaf) {
return (
<div class="flexRow">
<i class={['iconfont', 'iconshipinjiankong', show]}/>
<div>{node.label}</div>
{data.id != 'no_area' ? <div class="sta">
<p>{data.online || 0}</p>/{data.sum || 0}
</div>
: <div/>}
<el-dropdown class="menuBtn" onCommand={e => this.handleSliderOption(e, data)}>
<i class="iconfont iconMore"/>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="edit">修改名称</el-dropdown-item>
<el-dropdown-item command="area">行政地区</el-dropdown-item>
<el-dropdown-item command="locate">地图标绘</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
)
},
handleSliderOption(command, data) {
this.selected = JSON.parse(JSON.stringify({...data, command}))
if (command == "edit") {//修改名称
this.dialog = true
} else if (command == "area") {//绑定areaId
this.$refs.BindArea?.chooseArea()
} else if (command == "locate") {//地图标绘
this.latlng = data.lat && data.lng ? {
lat: data.lat,
lng: data.lng
} : ''
this.locate = true
}
},
handleSubmit(row) {
delete row.createTime
return this.instance.post("/app/appzyvideoequipment/addOrUpdate", {
...row
}).then(res => {
if (res?.code == 0) {
this.$message.success("提交成功!")
this.dialog = false
this.$refs.DeviceSlider?.getDevices()
}
})
},
handleLocate(row, locate) {
if (locate) {
let {lat, lng} = locate.location
this.handleSubmit({...row, lat, lng}).then(() => {
this.locate = false
})
}
} else return (
<div class="flexRow">
<div>{node.label}</div>
{data.id != 'no_area' ? <div class="sta">
<p>{data.online || 0}</p>/{data.sum || 0}
</div>
: <div/>}
</div>
)
},
handleSliderOption(command, data) {
this.selected = JSON.parse(JSON.stringify({...data, command}))
if (command == "edit") {//修改名称
this.dialog = true
} else if (command == "area") {//绑定areaId
this.$refs.BindArea?.chooseArea()
} else if (command == "locate") {//地图标绘
this.latlng = data.lat && data.lng ? {
lat: data.lat,
lng: data.lng
} : ''
this.locate = true
}
},
beforeDestroy() {
this.monitors = []
handleSubmit(row) {
delete row.createTime
return this.instance.post("/app/appzyvideoequipment/addOrUpdate", {
...row
}).then(res => {
if (res?.code == 0) {
this.$message.success("提交成功!")
this.dialog = false
this.$refs.DeviceSlider?.getDevices()
}
})
},
handleLocate(row, locate) {
if (locate) {
let {lat, lng} = locate.location
this.handleSubmit({...row, lat, lng}).then(() => {
this.locate = false
})
}
}
},
beforeDestroy() {
this.monitors = []
}
}
</script>
<style lang="scss" scoped>

View File

@@ -15,13 +15,14 @@
</el-button>
</template>
</ai-search-bar>
<ai-table :tableData="tableData"
:col-configs="colConfigs"
:total="total"
ref="aitableex"
:current.sync="search.current"
:size.sync="search.size"
@getList="getAppLeaveMessage">
<ai-table :tableData="tableData"
:col-configs="colConfigs"
:total="total"
ref="aitableex"
:current.sync="search.current"
:size.sync="search.size"
:dict="dict"
@getList="getAppLeaveMessage">
<el-table-column label="是否公示" slot="isPublic" align="center" width="150">
<template v-slot="{row}">
<el-switch v-model="row.isPublic" @change="onChange(row)" active-value="0" inactive-value="1"
@@ -31,7 +32,9 @@
<el-table-column label="操作" slot="options" align="center" width="150">
<template v-slot="{row}">
<el-button type="text" title="详情" @click="toDetail(row.id)" v-if="$permissions('app_appleavemessagereply_detail')">详情</el-button>
<el-button type="text" title="详情" @click="toDetail(row.id)"
v-if="$permissions('app_appleavemessagereply_detail')">详情
</el-button>
</template>
</el-table-column>
</ai-table>
@@ -123,7 +126,6 @@ export default {
onChange({id, isPublic}) {
this.instance.post(`/app/appleavemessage/public?id=${id}`).then(res => {
if (res.code == 0) {
console.log(isPublic)
this.$message.success(isPublic == 1 ? "已公示" : "不公示")
this.getAppLeaveMessage()
}
@@ -213,15 +215,14 @@ export default {
...mapState(['user']),
colConfigs() {
return [
{ prop: 'msgCode', label: '编号', align: 'center' },
{ prop: 'title', label: '标题', align: 'center' },
{ prop: 'type', label: '类型', align: 'center',
render:(h,{row})=>[<span>{this.dict.getLabel('leaveMessageType', row.type)}</span>] },
{ prop: 'leaveName', label: '留言', align: 'center' },
{ prop: 'createTime', label: '留言提交时间', align: 'center' },
{ prop: 'lastReplyTime', label: '最后回复时间', align: 'center' },
{ slot: 'isPublic'},
{ slot: 'options'},
{prop: 'msgCode', label: '编号', align: 'center'},
{prop: 'title', label: '标题', align: 'center'},
{prop: 'type', label: '类型', align: 'center', dict: "leaveMessageType"},
{prop: 'leaveName', label: '留言人', align: 'center'},
{prop: 'createTime', label: '留言提交时间', align: 'center'},
{prop: 'lastReplyTime', label: '最后回复时间', align: 'center'},
{slot: 'isPublic'},
{slot: 'options'},
]
}
}

View File

@@ -7,58 +7,62 @@
<el-select v-model="search.department" placeholder="请选择所属部门" @change="page.current=1,getList()"
size="small" clearable>
<el-option
v-for="(item,i) in dict.getDict('hbDepartment')" :key="i"
:label="item.dictName"
:value="item.dictValue">
v-for="(item,i) in dict.getDict('hbDepartment')" :key="i"
:label="item.dictName"
:value="item.dictValue">
</el-option>
</el-select>
<el-select v-model="search.classificationId" placeholder="请选择所属分类" @change="page.current=1,getList()"
size="small" clearable>
<el-option
v-for="(item,i) in classList" :key="i"
:label="item.name"
:value="item.id">
v-for="(item,i) in classList" :key="i"
:label="item.name"
:value="item.id">
</el-option>
</el-select>
</template>
<template #right>
<el-input
v-model="search.processName"
size="small"
placeholder="事项名称/创建人"
@clear="search={},page.current=1,getList()"
v-throttle="() => {page.current = 1, getList()}"
clearable
suffix-icon="iconfont iconSearch"/>
v-model="search.processName"
size="small"
placeholder="事项名称/创建人"
@clear="search={},page.current=1,getList()"
v-throttle="() => {page.current = 1, getList()}"
clearable
suffix-icon="iconfont iconSearch"/>
</template>
</ai-search-bar>
<ai-search-bar>
<template #left>
<el-button type="primary" icon="iconfont iconAdd" @click="goPage(tab.value==0 ? 'addConfig':'guidance')">添加{{tab.value==0?'事项':'办事指南'}}</el-button>
<el-button type="primary" icon="iconfont iconAdd" @click="goPage(tab.value==0 ? 'addConfig':'guidance')">
添加{{ tab.value == 0 ? '事项' : '办事指南' }}
</el-button>
</template>
</ai-search-bar>
<ai-table
:tableData="tableData"
:col-configs="colConfigs"
:header-cell-style="{fontWeight:'bold',color:'#333'}"
:total="page.total"
:current.sync="page.current"
:size.sync="page.size"
@getList="getList">
:tableData="tableData"
:col-configs="colConfigs"
:header-cell-style="{fontWeight:'bold',color:'#333'}"
:total="page.total"
:current.sync="page.current"
:size.sync="page.size"
:dict="dict"
@getList="getList">
<el-table-column label="是否启用" slot="processDefStatus" align="center" width="150">
<template v-slot="{row}">
<el-switch
v-model="row.processDefStatus"
@change="onChange(row)" active-value="1" inactive-value="0"
active-color="#5088FF"
inactive-color="#D0D4DC">
v-model="row.processDefStatus"
@change="onChange(row)" active-value="1" inactive-value="0"
active-color="#5088FF"
inactive-color="#D0D4DC">
</el-switch>
</template>
</el-table-column>
<el-table-column label="操作" slot="options" align="center" width="150">
<template v-slot="{row}">
<div class="table-options">
<el-button type="text" title="编辑" @click="goPage(tab.value==0 ? 'addConfig':'guidance',row)">编辑</el-button>
<el-button type="text" title="编辑" @click="goPage(tab.value==0 ? 'addConfig':'guidance',row)">编辑
</el-button>
<el-button type="text" title="删除" @click="delInfo(row)">删除</el-button>
</div>
</template>
@@ -70,145 +74,141 @@
</template>
<script>
import day from 'dayjs'
import day from 'dayjs'
export default {
name: "configList",
props: {
instance: Function,
dict: Object,
permissions: Function,
tab: Object,
},
data() {
return {
search: {
department: "",
classificationId: "",
processName: "",
export default {
name: "configList",
props: {
instance: Function,
dict: Object,
permissions: Function,
tab: Object,
},
data() {
return {
search: {
department: "",
classificationId: "",
processName: "",
},
page: {current: 1, size: 10},
total: 0,
row: {},
tableData: [],
classList: [],
}
},
computed: {
colConfigs() {
return [
{
prop: 'processName',
align: 'left',
label: '事项名称',
},
page: {current: 1, size: 10},
total: 0,
row: {},
tableData: [],
classList: [],
}
{
prop: 'department',
align: 'left',
label: '所属部门',
dict: "hbDepartment"
},
{
prop: 'classificationName',
align: 'center',
label: '所属分类',
},
{
prop: 'timeLimit',
align: 'center',
label: '办结时限(日)',
},
{
prop: 'createUserName',
align: 'center',
label: '创建人',
},
{
prop: 'createTime',
align: 'center',
label: '最后修改时间',
render: (h, {row}) => h('p', day(row.createTime).format("YYYY-MM-DD HH:mm"))
},
{slot: 'processDefStatus', align: 'center', label: '是否启用',},
{slot: 'options', align: 'center', label: '操作',},
].filter(e => this.tab.value == 0 ? true : (e.prop != "timeLimit"))
},
computed: {
colConfigs() {
return [
{
prop: 'processName',
align: 'left',
label: '事项名称',
},
{
prop: 'department',
align: 'left',
label: '所属部门',
render: (h, {row}) => [ < span > {this.dict.getLabel('hbDepartment', row.department)} < /span>]
},
{
prop: 'classificationName',
align: 'center',
label: '所属分类',
},
{
prop: 'timeLimit',
align: 'center',
label: '办结时限(日)',
},
{
prop: 'createUserName',
align: 'center',
label: '创建人',
},
{
prop: 'createTime',
align: 'center',
label: '最后修改时间',
render: (h, {row}) => [ < span > {day(row.createTime
).
format("YYYY-MM-DD HH:mm")
}<
/span>]
},
{slot: 'processDefStatus', align:'center', label:'是否启用',},
{ slot: 'options',align:'center',label:'操作',},
].filter(e=>this.tab.value==0 ? true : (e.prop!="timeLimit"))
},
},
methods: {
goPage(comp, row = {}) {
this.$emit("goPage", {comp, row})
},
methods: {
goPage(comp, row = {}) {
this.$emit("goPage", {comp, row})
},
/**
* 获取分类
*/
getClassification() {
this.instance.post(`/app/zwspapprovalclassification/list`, null, {
params:{
current: 1,
status: 1,
size: 9999
}
}).then(res => {
if (res && res.data) {
this.classList = res.data.records
}
})
},
/**
* 删除
* */
delInfo({id}) {
this.$confirm("是否删除").then(() => {
this.instance.post(`/app/approval-process-def/delete?id=${id}`).then(res => {
if (res.code == 0) {
this.$message.success("删除成功")
this.getList()
}
})
})
},
/**
* 启用,停用
*/
onChange({id, processDefStatus}) {
this.instance.post(`/app/approval-process-def/enable-disable`, null, {
params: {id}
}).then(res => {
/**
* 获取分类
*/
getClassification() {
this.instance.post(`/app/zwspapprovalclassification/list`, null, {
params: {
current: 1,
status: 1,
size: 9999
}
}).then(res => {
if (res && res.data) {
this.classList = res.data.records
}
})
},
/**
* 删除
* */
delInfo({id}) {
this.$confirm("是否删除").then(() => {
this.instance.post(`/app/approval-process-def/delete?id=${id}`).then(res => {
if (res.code == 0) {
this.$message.success(processDefStatus == 0 ? "不启用" : "已启用")
this.$message.success("删除成功")
this.getList()
}
})
},
})
},
/**
* 启用,停用
*/
onChange({id, processDefStatus}) {
this.instance.post(`/app/approval-process-def/enable-disable`, null, {
params: {id}
}).then(res => {
if (res.code == 0) {
this.$message.success(processDefStatus == 0 ? "不启用" : "已启用")
this.getList()
}
})
},
getList() {
this.instance.post(`/app/approval-process-def/list`, null, {
params: {
...this.page,
...this.search,
processType: this.tab.value
},
}).then(res => {
if (res?.data) {
this.tableData = res.data.records
this.page.total = res.data.total;
}
})
},
getList() {
this.instance.post(`/app/approval-process-def/list`, null, {
params: {
...this.page,
...this.search,
processType: this.tab.value
},
}).then(res => {
if (res?.data) {
this.tableData = res.data.records
this.page.total = res.data.total;
}
})
},
mounted() {
this.getList()
this.getClassification()
},
}
},
mounted() {
this.getList()
this.getClassification()
},
}
</script>
<style lang="scss" scoped>
.config-list {
height: 100%;
}
.config-list {
height: 100%;
}
</style>

View File

@@ -26,6 +26,7 @@
:total="total"
:current.sync="page.current"
:size.sync="page.size"
:dict="dict"
@getList="getList">
<el-table-column slot="option" label="操作" fixed="right" width="300" align="center">
<template slot-scope="{ row }">
@@ -80,7 +81,7 @@
{prop: 'viewTotal', label: '浏览数', align: 'center'},
{prop: 'publishUserName', label: '发布人'},
{prop: 'publishTime', label: '发布时间'},
{prop: 'status', label: '发布状态', align: 'center',render:(h,{row})=>[<span>{this.$dict.getLabel('newsCenterStatus',row.status)}</span>]},
{prop: 'status', label: '发布状态', align: 'center',dict:"newsCenterStatus"},
{slot: 'option'},
]
}

View File

@@ -53,6 +53,7 @@
:total="total"
:current.sync="search.current"
:size.sync="search.size"
:dict="dict"
@getList="getList">
<el-table-column slot="readUserName" label="姓名" align="center">
<template slot-scope="{ row }">
@@ -103,9 +104,8 @@ export default {
{slot: "unitName"},
{
prop: "readStatus", label: "查阅状态", align: "center",
render: (h, {row}) => [<span
style={{color: this.dict.getColor("announcementReadStatus", row.readStatus)}}>{this.dict.getLabel("announcementReadStatus", row.readStatus)}</span>]
},
render: (h, {row}) => h('p', {color: this.dict.getColor("announcementReadStatus", row.readStatus)}, this.dict.getLabel("announcementReadStatus", row.readStatus))
}
];
}
},

View File

@@ -40,6 +40,7 @@
:total="total"
:current.sync="search.current"
:size.sync="search.size"
:dict="dict"
@getList="getList">
<el-table-column slot="releaseUserName" label="发布人" align="center">
<template slot-scope="{ row }">
@@ -123,17 +124,20 @@ export default {
{prop: 'title', label: '标题'},
{
prop: 'readNum', label: '查询状态', align: 'center',
render: (h, {row}) => [<span class='status'
onClick={this.showDialog.bind(this, row)}>{row.readNum}人已读</span>,
<span class='status' onClick={this.showDialog.bind(this, row)}>{row.unReadNum}人未读</span>]
render: (h, {row}) => h('p', {
class: 'status', on: {
click() {
this.showDialog(row)
}
}
}, `${row.readNum || 0}人已读,${row.unReadNum}人未读`)
},
{slot: 'releaseUserName'},
{slot: 'unitName'},
{prop: 'releaseTime', label: '发布时间', align: 'center'},
{
prop: 'status', label: '发布状态', align: 'center',
render: (h, {row}) => [<span
style={{color: this.dict.getColor("announcementStatus", row.status)}}>{this.dict.getLabel("announcementStatus", row.status)}</span>]
render: (h, {row}) => h('p', {color: this.dict.getColor("announcementStatus", row.status)}, this.dict.getLabel("announcementStatus", row.status))
},
{slot: 'options'},
];

View File

@@ -3,56 +3,59 @@
<template slot="content">
<ai-search-bar>
<template slot="left">
<el-button :disabled="!permissions('app_appactivity_edit')" icon="iconfont iconAdd" type="primary" size="small" @click="add">添加</el-button>
<el-button :disabled="!permissions('app_appactivity_edit')" icon="iconfont iconAdd" type="primary"
size="small" @click="add">添加
</el-button>
</template>
<template slot="right">
<el-input
placeholder="请输入标题"
size="small"
clearable
v-model="search.title"
v-throttle="() => {search.current = 1, getList()}"
@clear="search.current = 1, search.title = '', getList()"
suffix-icon="iconfont iconSearch" />
placeholder="请输入标题"
size="small"
clearable
v-model="search.title"
v-throttle="() => {search.current = 1, getList()}"
@clear="search.current = 1, search.title = '', getList()"
suffix-icon="iconfont iconSearch"/>
</template>
</ai-search-bar>
<div class="ai-table">
<ai-table
:tableData="tableData"
:col-configs="colConfigs"
:total="total"
:current.sync="search.current"
:size.sync="search.size"
@getList="getList">
:tableData="tableData"
:col-configs="colConfigs"
:total="total"
:current.sync="search.current"
:size.sync="search.size"
:dict="dict"
@getList="getList">
<el-table-column slot="options" label="操作" align="center" width="250" fixed="right">
<template slot-scope="{ row }">
<div class="table-options">
<el-button
type="text"
@click="publish(row)"
:title="row.status === '1' ? '取消发布' : '发布'"
:disabled="!permissions('app_appvillageinfo_edit')">
type="text"
@click="publish(row)"
:title="row.status === '1' ? '取消发布' : '发布'"
:disabled="!permissions('app_appvillageinfo_edit')">
{{ row.status === '1' ? '取消发布' : '发布' }}
</el-button>
<el-button
type="text"
title="详情"
@click="toDetail(row.id)"
:disabled="!permissions('app_appactivity_detail')">
type="text"
title="详情"
@click="toDetail(row.id)"
:disabled="!permissions('app_appactivity_detail')">
详情
</el-button>
<el-button
type="text"
title="编辑"
@click="toAdd(row.id)"
:disabled="!permissions('app_appactivity_edit')">
type="text"
title="编辑"
@click="toAdd(row.id)"
:disabled="!permissions('app_appactivity_edit')">
编辑
</el-button>
<el-button
@click="remove(row.id)"
type="text"
title="删除"
:disabled="!permissions('app_appactivity_del')">
@click="remove(row.id)"
type="text"
title="删除"
:disabled="!permissions('app_appactivity_del')">
删除
</el-button>
</div>
@@ -65,133 +68,133 @@
</template>
<script>
import { mapState } from 'vuex'
import {mapState} from 'vuex'
export default {
name: 'ReportEvent',
props: {
instance: Function,
dict: Object,
areaId: String,
permissions: Function
export default {
name: 'ReportEvent',
props: {
instance: Function,
dict: Object,
areaId: String,
permissions: Function
},
computed: {
...mapState(['user']),
colConfigs() {
return [
{prop: 'title', label: '标题'},
{prop: 'type', label: '活动名称', dict: "activityAirticleType"},
{prop: 'readCount', label: '浏览数', align: 'center'},
{prop: 'commentCount', label: '评论数', align: 'center'},
{prop: 'createDate', label: '创建时间'},
{prop: 'status', label: '发布状态', dict: "villInfoStatus"},
{slot: 'options', label: '操作'}
]
}
},
data() {
return {
search: {
current: 1,
size: 10,
title: ''
},
total: 0,
ids: [],
tableData: [],
}
},
created() {
this.dict.load("activityAirticleType", 'villInfoStatus').then(() => this.getList())
},
methods: {
getList() {
this.instance.post(`/app/appactivity/list`, null, {
params: {
...this.search,
areaId: this.areaId
}
}).then(res => {
if (res.data) {
this.tableData = res.data.records
this.total = res.data.total
}
})
},
computed: {
...mapState(['user']),
colConfigs() {
return [
{ prop: 'title', label: '标题'},
{ prop: 'type', label: '活动名称',render:(h,{row})=>[<span>{this.dict.getLabel('activityAirticleType', row.type)}</span>]},
{ prop: 'readCount', label: '浏览数', align: 'center' },
{ prop: 'commentCount', label: '评论数', align: 'center' },
{ prop: 'createDate', label: '创建时间'},
{ prop: 'status', label: '发布状态',render:(h,{row})=>[<span>{this.dict.getLabel('villInfoStatus', row.status)}</span>]},
{ slot: 'options', label: '操作' }
]
}
},
data () {
return {
search: {
current: 1,
size: 10,
title: ''
},
total: 0,
ids: [],
tableData: [],
}
},
created () {
this.dict.load("activityAirticleType",'villInfoStatus').then(() => this.getList())
},
methods: {
getList () {
this.instance.post(`/app/appactivity/list`, null, {
params: {
...this.search,
areaId: this.areaId
}
publish(params) {
this.$confirm(`是否${params.status === '1' ? '取消发布' : '发布'}该条数据?`).then(() => {
this.instance.post(`/app/appactivity/updateCountYardstatus`, {
id: params.id,
status: params.status === '1' ? 0 : 1
}).then(res => {
if (res.data) {
this.tableData = res.data.records
this.total = res.data.total
if (res.code == 0) {
this.$message.success(`${params.status === '1' ? '取消发布' : '发布'}成功!`)
this.getList()
}
})
},
})
},
publish (params) {
this.$confirm(`是否${params.status === '1' ? '取消发布' : '发布'}该条数据?`).then(() => {
this.instance.post(`/app/appactivity/updateCountYardstatus`, {
id: params.id,
status: params.status === '1' ? 0 : 1
}).then(res => {
if (res.code == 0) {
this.$message.success(`${params.status === '1' ? '取消发布' : '发布'}成功!`)
this.getList()
}
})
})
},
toAdd(id) {
this.$emit('change', {
type: 'add',
params: {
id
}
})
},
toAdd (id) {
this.$emit('change', {
type: 'add',
params: {
id
add() {
this.$emit('change', {
type: 'add',
params: {
id: ''
}
})
},
toEdit(id) {
this.$emit('change', {
type: 'add',
params: {
type: 'ReportAdd',
id
}
})
},
toDetail(id) {
this.$emit('change', {
type: 'detail',
params: {
type: 'eventDetail',
id
}
})
},
remove(id) {
this.$confirm('确定删除该数据?').then(() => {
this.instance.post(`/app/appactivity/delete?ids=${id}`).then(res => {
if (res.code == 0) {
this.$message.success('删除成功!')
this.getList()
}
})
},
add () {
this.$emit('change', {
type: 'add',
params: {
id: ''
}
})
},
toEdit (id) {
this.$emit('change', {
type: 'add',
params: {
type: 'ReportAdd',
id
}
})
},
toDetail (id) {
this.$emit('change', {
type: 'detail',
params: {
type: 'eventDetail',
id
}
})
},
remove (id) {
this.$confirm('确定删除该数据?').then(() => {
this.instance.post(`/app/appactivity/delete?ids=${id}`).then(res => {
if (res.code == 0) {
this.$message.success('删除成功!')
this.getList()
}
})
})
}
})
}
}
}
</script>
<style lang="scss" scoped>
.join-event {
height: 100%;
}
.join-event {
height: 100%;
}
</style>

View File

@@ -13,13 +13,13 @@
</div>
</div>
<div class="header-right">
<!-- <div class="header-right__item">-->
<!-- <span>成员总数</span>-->
<!-- <h3>{{ chartData.groupSum}}</h3>-->
<!-- </div>-->
<!-- <div class="header-right__item">-->
<!-- <span>成员总数</span>-->
<!-- <h3>{{ chartData.groupSum}}</h3>-->
<!-- </div>-->
<div class="header-right__item">
<span>成员总数</span>
<h3>{{chartData.today && chartData.today.total }}</h3>
<h3>{{ chartData.today && chartData.today.total }}</h3>
</div>
<div class="header-right__item">
<span>今日新增</span>
@@ -27,13 +27,13 @@
</div>
<div class="header-right__item">
<span>今日流失</span>
<h3>{{chartData.today && chartData.today.decrease}}</h3>
<h3>{{ chartData.today && chartData.today.decrease }}</h3>
</div>
</div>
</div>
<div class="detail-top__content">
<ai-wrapper
label-width="80px">
label-width="80px">
<ai-info-item label="群主" :value="info.ownerName"></ai-info-item>
<ai-info-item label="群公告" :value="info.notice" isLine></ai-info-item>
<ai-info-item label="群聊标签" isLine>
@@ -53,14 +53,25 @@
<ai-card title="成员列表">
<template slot="content">
<ai-table
:tableData="tableData"
:col-configs="colConfigs"
:total="total"
border
ref="aitableex"
@getList="getDynamicInfo"
:current.sync="search.current"
:size.sync="search.size">
:tableData="tableData"
:col-configs="colConfigs"
:total="total"
border
ref="aitableex"
@getList="getDynamicInfo"
:current.sync="search.current"
:size.sync="search.size"
:dict="dict">
<el-table-column slot="member" label="成员">
<template slot-scope="{row}">
<el-row type="flex" align="middle">
<img class="avatar" :src='row.avatar || "https://cdn.cunwuyun.cn/dvcp/h5/defaultAvatar.png"'/>
<div v-text="row.memberName"/>
<span :style="{color: row.customerType == 1 ? '#2EA222' : '#3C7FC8', marginLeft: '8px'}"
v-text="(row.customerType == 1 ? '@微信' : '@' + row.corpName)|| ''"/>
</el-row>
</template>
</el-table-column>
<el-table-column slot="options" label="操作" width="100" align="center">
<template slot-scope="{ row }">
<el-button type="text" v-if="row.type==2 && row.avatar" @click="toDetail(row)">居民详情</el-button>
@@ -74,304 +85,300 @@
</template>
<script>
import * as echarts from 'echarts'
import * as echarts from 'echarts'
export default {
name: 'Detail',
export default {
name: 'Detail',
props: {
instance: Function,
dict: Object,
params: Object
},
props: {
instance: Function,
dict: Object,
params: Object
},
computed: {
colConfigs() {
return [
{
prop: 'memberName', label: '成员',render:(h,{row})=>[<img class="avatar" src={row.avatar || "https://cdn.cunwuyun.cn/dvcp/h5/defaultAvatar.png"} />,
<span>{row.memberName}</span>,
<span style={{color:row.customerType==1 ? '#2EA222' : '#3C7FC8',marginLeft:'8px'}}>{ row.customerType?(row.customerType==1 ? '@微信' : '@' + row.corpName):'' }</span>],
computed: {
colConfigs() {
return [
{slot: "member"},
{prop: 'type', label: '类型', dict: "wxGroupMemberType"},
{prop: 'joinTime', label: '入群时间'},
{prop: 'joinScene', label: '入群方式', dict: "wxGroupMemberJoinScene"},
{slot: "options"},
]
}
},
data() {
return {
isShow: false,
info: {},
search: {
current: 1,
size: 10
},
{prop: 'type', label: '类型',render:(h,{row})=>[<span>{this.dict.getLabel("wxGroupMemberType",row.type)}</span>]},
{prop: 'joinTime', label: '入群时间'},
{prop: 'joinScene', label: '入群方式',render:(h,{row})=>[<span>{this.dict.getLabel("wxGroupMemberJoinScene",row.joinScene)}</span>]},
{slot: "options"},
]
}
},
total: 0,
tableData: [],
chart: null,
chartData: {},
}
},
data() {
return {
isShow: false,
info: {},
search: {
current: 1,
size: 10
created() {
this.dict.load("wxGroupMemberJoinScene", "wxGroupMemberType")
},
mounted() {
if (this.params && this.params.id) {
this.getInfo()
this.getDynamicInfo()
this.getChart()
}
},
methods: {
getChart() {
this.instance.post(`/app/wxcp/wxgroup/groupStatistic`, null, {
params: {
id: this.params.id
}
}).then(res => {
if (res && res.data) {
this.chartData = res.data
this.initChart()
}
})
},
initChart() {
this.chart = echarts.init(document.getElementById('lineChart'))
this.setOptions()
},
setOptions() {
const x = Object.keys(this.chartData.list)
const y = Object.values(this.chartData.list)
this.chart.setOption({
tooltip: {
trigger: 'axis'
},
total: 0,
tableData: [],
chart: null,
chartData: {},
}
},
created() {
this.dict.load("wxGroupMemberJoinScene", "wxGroupMemberType")
},
mounted() {
if (this.params && this.params.id) {
this.getInfo()
this.getDynamicInfo()
this.getChart()
}
},
methods: {
getChart() {
this.instance.post(`/app/wxcp/wxgroup/groupStatistic`, null, {
params: {
id: this.params.id
}
}).then(res => {
if (res && res.data) {
this.chartData = res.data
this.initChart()
}
})
},
initChart() {
this.chart = echarts.init(document.getElementById('lineChart'))
this.setOptions()
},
setOptions() {
const x = Object.keys(this.chartData.list)
const y = Object.values(this.chartData.list)
this.chart.setOption({
tooltip: {
trigger: 'axis'
legend: {
type: "plain"
},
grid: {
left: '20px',
right: '38px',
bottom: '14px',
top: '30px',
containLabel: true
},
color: ['#2266FF', '#22AA99', '#F8B425'],
xAxis: {
type: 'category',
axisLabel: {
align: 'center',
padding: [2, 0, 0, 0],
interval: 0,
fontSize: 14,
color: '#666666'
},
legend: {
type: "plain"
},
grid: {
left: '20px',
right: '38px',
bottom: '14px',
top: '30px',
containLabel: true
},
color: ['#2266FF', '#22AA99', '#F8B425'],
xAxis: {
type: 'category',
axisLabel: {
align: 'center',
padding: [2, 0, 0, 0],
interval: 0,
fontSize: 14,
color: '#666666'
},
boundaryGap: false,
axisLine: {
lineStyle: {
color: '#E1E5EF'
}
},
data: x
},
yAxis: {
axisTick: {
length: 0,
show: false
},
splitLine: {
show: true,
lineStyle: {
color: ['#E1E5EF'],
width: 1,
type: 'solid'
}
},
nameTextStyle: {
color: '#666666',
align: 'left'
},
axisLine: {
show: false
},
axisLabel: {
color: '#666666'
},
type: 'value'
},
series: [
{
name: '成员总数',
type: 'line',
data: y.map(v => v.total)
},
{
name: '新增成员数',
type: 'line',
data: y.map(v => v.increase)
},
{
name: '流失成员数',
type: 'line',
data: y.map(v => v.decrease)
boundaryGap: false,
axisLine: {
lineStyle: {
color: '#E1E5EF'
}
]
})
},
getInfo() {
this.instance.post(`/app/wxcp/wxgroup/getDetail?id=${this.params.id}`).then(res => {
if (res && res.data) {
this.info = res.data
},
data: x
},
yAxis: {
axisTick: {
length: 0,
show: false
},
splitLine: {
show: true,
lineStyle: {
color: ['#E1E5EF'],
width: 1,
type: 'solid'
}
},
nameTextStyle: {
color: '#666666',
align: 'left'
},
axisLine: {
show: false
},
axisLabel: {
color: '#666666'
},
type: 'value'
},
series: [
{
name: '成员总数',
type: 'line',
data: y.map(v => v.total)
},
{
name: '新增成员数',
type: 'line',
data: y.map(v => v.increase)
},
{
name: '流失成员数',
type: 'line',
data: y.map(v => v.decrease)
}
})
},
]
})
},
getDynamicInfo() {
this.instance.post(`/app/wxcp/wxgroup/listMember?groupId=${this.params.id}`, null, {
params: {
...this.search
}
}).then(res => {
if (res.code === 0) {
this.tableData = res.data.records
this.total = res.data.total
}
})
},
getInfo() {
this.instance.post(`/app/wxcp/wxgroup/getDetail?id=${this.params.id}`).then(res => {
if (res && res.data) {
this.info = res.data
}
})
},
toDetail(row) {
this.$router.push({
name: '68',
query: {
id: row.userId,
type: 'Detail'
}
})
},
getDynamicInfo() {
this.instance.post(`/app/wxcp/wxgroup/listMember?groupId=${this.params.id}`, null, {
params: {
...this.search
}
}).then(res => {
if (res.code === 0) {
this.tableData = res.data.records
this.total = res.data.total
}
})
},
cancel(isRefresh) {
this.$emit('change', {
type: 'list',
isRefresh: isRefresh ? true : false
})
}
toDetail(row) {
this.$router.push({
name: '68',
query: {
id: row.userId,
type: 'Detail'
}
})
},
cancel(isRefresh) {
this.$emit('change', {
type: 'list',
isRefresh: isRefresh ? true : false
})
}
}
}
</script>
<style scoped lang="scss">
.AppResidentManage {
::v-deep .ai-detail__content--wrapper {
max-width: 100% !important;
padding: 20px;
.AppResidentManage {
::v-deep .ai-detail__content--wrapper {
max-width: 100% !important;
padding: 20px;
}
h2, h3 {
margin: 0;
}
.detail-top {
padding: 30px 40px;
background: #FFFFFF;
box-shadow: 0px 4px 6px -2px rgba(15, 15, 21, 0.15);
border-radius: 2px;
margin-bottom: 20px;
.detail-top__content {
padding-top: 32px;
}
h2, h3 {
margin: 0;
}
.detail-top__header {
display: flex;
justify-content: space-between;
align-items: center;
padding-bottom: 32px;
border-bottom: 1px solid #EEEEEE;
.detail-top {
padding: 30px 40px;
background: #FFFFFF;
box-shadow: 0px 4px 6px -2px rgba(15, 15, 21, 0.15);
border-radius: 2px;
margin-bottom: 20px;
.header-right {
.header-right__item {
width: 120px;
margin-right: 8px;
text-align: center;
}
.detail-top__content {
padding-top: 32px;
div {
text-align: center;
&:last-child {
margin-right: 0;
}
span {
display: block;
margin-bottom: 10px;
color: #888888;
}
}
.el-button {
height: 28px;
margin-left: 8px;
border-radius: 14px;
font-size: 12px;
padding: 7px 15px;
}
}
.detail-top__header {
.header-left, .header-right {
display: flex;
justify-content: space-between;
align-items: center;
padding-bottom: 32px;
border-bottom: 1px solid #EEEEEE;
}
.header-right {
.header-right__item {
width: 120px;
margin-right: 8px;
text-align: center;
}
div {
text-align: center;
&:last-child {
margin-right: 0;
}
span {
display: block;
margin-bottom: 10px;
color: #888888;
}
}
.el-button {
height: 28px;
margin-left: 8px;
border-radius: 14px;
font-size: 12px;
padding: 7px 15px;
}
.header-left {
img {
width: 64px;
height: 64px;
margin-right: 16px;
}
.header-left, .header-right {
display: flex;
align-items: center;
h2 {
margin-bottom: 6px;
color: #222222;
font-size: 16px;
}
.header-left {
img {
width: 64px;
height: 64px;
margin-right: 16px;
}
h2 {
margin-bottom: 6px;
color: #222222;
font-size: 16px;
}
p {
color: #2EA222;
font-size: 14px;
}
p {
color: #2EA222;
font-size: 14px;
}
}
}
#lineChart {
width: 100%;
height: 336px;
}
.table-tags {
.el-tag {
margin-right: 8px;
&:last-child {
margin-right: 0;
}
}
}
::v-deep .avatar {
width: 40px;
height: 40px;
vertical-align: middle;
margin-right: 8px;
object-fit: fill;
}
}
#lineChart {
width: 100%;
height: 336px;
}
.table-tags {
.el-tag {
margin-right: 8px;
&:last-child {
margin-right: 0;
}
}
}
::v-deep .avatar {
width: 40px;
height: 40px;
vertical-align: middle;
margin-right: 8px;
object-fit: fill;
}
}
</style>