xy 2 years ago
parent f84ffdbf1a
commit 2dec808df0

@ -190,7 +190,7 @@ export default {
color: 'rgba(255,255,255,.8)',
fontSize: 12
},
data: newData.lease.map(item => item?.zulinkaishiqixian??'')
data: newData.lease?.map(item => item?.zulinkaishiqixian??'') || []
},
// Y
yAxis: {
@ -298,7 +298,7 @@ export default {
color: this.colorList.areaBtoG
}
},
data: newData.lease.map(i => i?.zulinmianji??0),
data: newData.lease?.map(i => i?.zulinmianji??0) || [],
lineSmooth: true,
markLine: {
silent: true,
@ -339,7 +339,7 @@ export default {
},
silent: true,
barWidth: '50%',
data: newData.lease.map(i => i?.zulinmianji??0),
data: newData.lease?.map(i => i?.zulinmianji??0) || [],
animation: false
}
]

@ -6,6 +6,7 @@ import permission from './modules/permission'
import settings from './modules/settings'
import user from './modules/user'
import form from './modules/form'
import bigdata from "./modules/bigdata"
Vue.use(Vuex)
@ -15,7 +16,8 @@ const store = new Vuex.Store({
permission,
settings,
user,
form
form,
bigdata
},
getters
})

@ -0,0 +1,142 @@
import { index } from "@/api/system/baseForm";
import * as $moment from "moment";
const state = {
assets: [[],[]],
leases: [],
adventLeases: [],
safety: [],
type: 1,
}
let config = {}
const mutations = {
SET_ASSETS: (state, assets) => {
state.assets = assets
},
SET_LEASES: (state, leases) => {
state.leases = leases
},
SET_ADVENT_LEASES: (state, adventLeases) => {
state.adventLeases = adventLeases
},
SET_TYPE: (state, type) => {
state.type = type
},
SET_SAFETY: (state, safety) => {
state.safety = safety
}
}
const actions = {
getAssets({ commit, state }) {
return new Promise((resolve, reject) => {
Promise.all([
index({
table_name: "houses",
page: 1,
page_size: 999
},false),
index({
table_name: "lands",
page: 1,
page_size: 999
})
]).then(res => {
const [houses,lands] = res;
commit("SET_ASSETS",[houses.data,lands.data])
resolve([houses.data,lands.data])
}).catch(err => {
reject(err)
})
})
},
getLeases({ commit, state }) {
return new Promise((resolve, reject) => {
index({
table_name: "leases",
page: 1,
page_size: 999,
filter: [
{
key: 'zulinjieshuqixian',
op: 'range',
value: `${$moment().format("YYYY-MM-DD")},2999-12-31`
},
{
key: 'zulinkaishiqixian',
op: 'range',
value: `${$moment(0).format("YYYY-MM-DD")},${$moment().format("YYYY-MM-DD")}`
}
]
}).then(res => {
commit("SET_LEASES", res.data)
resolve(res)
}).catch(err => {
reject(err)
})
})
},
async getAdventLeases({ commit, state }) {
if (!config.time || !config.unit) {
const res = await index({
table_name: 'warnings',
filter: [
{
key: 'flag',
op: 'eq',
value: 'contract'
}
]
},false)
config.time = Number(res.data[0]?.time);
config.unit = res.data[0]?.unit;
}
return new Promise((resolve, reject) => {
let preDate = $moment().add(config.time, config.unit).format("YYYY-MM-DD")
index({
table_name: "leases",
page: 1,
page_size: 999,
filter: [
{
key: 'zulinjieshuqixian',
op: 'range',
value: `${$moment().format("YYYY-MM-DD")},${preDate}`
},
{
key: 'zulinkaishiqixian',
op: 'range',
value: ``
}
]
}).then(res => {
commit("SET_ADVENT_LEASES", res.data)
resolve(res)
}).catch(err => {
reject(err)
})
})
},
getSafety({ commit, state }) {
return new Promise((resolve, reject) => {
index({
table_name: "asset_safety_inspections",
page: 1,
page_size: 999
}).then(res => {
commit("SET_SAFETY", res.data)
resolve(res)
}).catch(err => {
reject(err)
})
})
}
}
export default {
namespaced: true,
state,
mutations,
actions
}

@ -5,7 +5,7 @@
<div class="contract">
<div class="contract__title">
<h3>办通知</h3>
<h3>办通知</h3>
<div class="more" @click="$router.push('/lease')">
@ -90,7 +90,7 @@
</div>
<div class="list">
<div class="list-item" v-for="item in assetSafetyInspections" @click="$refs['drawer'].setType(4),$refs['drawer'].setRow(item),$refs['drawer'].show()">
<div class="list-item" v-for="item in assetSafetyPlan" @click="$refs['drawer'].setType(4),$refs['drawer'].setRow(item),$refs['drawer'].show()">
<span>{{ item.zichanmingcheng }}</span>
<span>{{ $moment(new Date(item.riqi)).format('YYYY-MM-DD') }}</span>
</div>
@ -266,7 +266,7 @@
},
systems: [],
systemTotal: 0,
assetSafetyInspectionsSelect: {
assetSafetyPlanSelect: {
table_name: 'asset_safety_inspections',
page: 1,
page_size: 10,
@ -278,8 +278,8 @@
}
]
},
assetSafetyInspectionsTotal: 0,
assetSafetyInspections: [],
assetSafetyPlanTotal: 0,
assetSafetyPlan: [],
noticeSelect: {
table_name: 'notices',
page: 1,
@ -471,11 +471,11 @@
this.notices = res;
this.noticeTotal = res.length;
},
async getAssetSafetyInspections () {
this.assetSafetyInspectionsSelect.filter[0].value = `${this.$moment().format("YYYY-MM-DD")},${this.$moment().add(this.config.time, this.config.unit).format("YYYY-MM-DD")}`
const res = await index(this.assetSafetyInspectionsSelect,false);
this.assetSafetyInspections = res.data;
this.assetSafetyInspectionsTotal = res.total;
async getAssetSafetyPlan () {
this.assetSafetyPlanSelect.filter[0].value = `${this.$moment().format("YYYY-MM-DD")},${this.$moment().add(this.config.time, this.config.unit).format("YYYY-MM-DD")}`
const res = await index(this.assetSafetyPlanSelect,false);
this.assetSafetyPlan = res.data;
this.assetSafetyPlanTotal = res.total;
},
async getSystems () {
const res = await index(this.systemSelect,false);
@ -499,7 +499,7 @@
this.getSystems();
this.getConfig().then(_ => {
this.getLeases();
this.getAssetSafetyInspections();
this.getAssetSafetyPlan();
})
//this.loadData();
},

@ -1,6 +1,6 @@
<template>
<div class="btns">
<div class="item" v-for="item in items" :class="{ 'item-active': activeText === item.text }" @click="activeText = item.text">
<div class="item" v-for="item in items" :class="{ 'item-active': activeText === item.text }" @click="btnClick(item)">
<div class="item__icon">
<SvgIcon :icon-class="item.icon"></SvgIcon>
</div>
@ -31,13 +31,18 @@ export default {
return {
activeText: "资产总览",
items: [
{ text: "资产总览", icon: "house" },
{ text: "租赁数据", icon: "qiandai" },
{ text: "安全巡检", icon: "weixiu" }
{ text: "资产总览", icon: "house", type: 1 },
{ text: "租赁数据", icon: "qiandai", type: 2 },
{ text: "安全巡检", icon: "weixiu", type: 3 },
]
}
},
methods: {},
methods: {
btnClick (item) {
this.activeText = item.text
this.$store.commit("bigdata/SET_TYPE", item.type)
}
},
computed: {}
}
</script>

@ -10,8 +10,10 @@
<div class="body d-flex">
<btns></btns>
<div class="left d-flex flex-column">
<dv-border-box-12>
<MapComponent></MapComponent>
<dv-border-box-12 style="padding: 14px;">
<MapComponent v-show="$store.state.bigdata.type === 1"></MapComponent>
<Map1Component v-show="$store.state.bigdata.type === 2 || $store.state.bigdata.type === 3"></Map1Component>
</dv-border-box-12>
<leftBottom class="mt-2"></leftBottom>
</div>
@ -29,6 +31,7 @@
<script>
import drawMixin from "@/mixin/drawMixin";
import MapComponent from "./map.vue";
import Map1Component from "./map1.vue";
import HeaderComponent from "./header.vue";
import right1 from "./right1.vue";
import right2 from "./right2.vue";
@ -36,9 +39,11 @@ import right3 from "./right3.vue";
import btns from "./btns.vue";
import leftBottom from "./leftBottom.vue"
import { index } from '@/api/system/baseForm';
import { mapActions } from "vuex"
export default {
components: {
MapComponent,
Map1Component,
HeaderComponent,
right1,
right2,
@ -47,12 +52,6 @@ export default {
leftBottom
},
mixins: [drawMixin],
provide() {
return {
assets: () => this.assetsData,
leases: () => this.leases,
}
},
data() {
return {
loading: true,
@ -61,53 +60,25 @@ export default {
}
},
methods: {
async getLeases () {
const res = await index({
table_name: "leases",
page: 1,
page_size: 999,
filter: [
{
key: 'zulinjieshuqixian',
op: 'range',
value: `${this.$moment().format("YYYY-MM-DD")},2999-12-31`
},
{
key: 'zulinkaishiqixian',
op: 'range',
value: `${this.$moment(0).format("YYYY-MM-DD")},${this.$moment().format("YYYY-MM-DD")}`
}
]
})
this.leases = res.data
},
async getData () {
await Promise.all([
index({
table_name: "houses",
page: 1,
page_size: 999
},false),
index({
table_name: "lands",
page: 1,
page_size: 999
})
]).then(res => {
const [houses,lands] = res;
this.assetsData = [houses.data,lands.data];
})
},
...mapActions("bigdata",{
getLeases: "getLeases",
getAssets: "getAssets",
getAdventLeases: "getAdventLeases",
getSafety: "getSafety",
})
},
computed: {
},
computed: {},
mounted() {
setTimeout(() => {
this.loading = false;
},500)
},
created() {
this.getData();
this.getAssets()
this.getLeases()
this.getAdventLeases()
this.getSafety()
}
}
</script>
@ -137,6 +108,7 @@ export default {
padding-left: 13%;
.left {
flex-basis: 74%;
}
.right {
flex: 1;

@ -37,7 +37,6 @@ export default {
components: {
SvgIcon
},
inject: ["assets"],
data() {
return {
items: [
@ -70,7 +69,7 @@ export default {
total () {
return function(tag) {
let total = 0;
const [houses,lands] = this.assets()
const [houses,lands] = this.$store.state.bigdata.assets
switch (tag) {
case "total":
total += houses.reduce((a,b) => a + parseFloat(b.dengjimianji ?? 0),0)

@ -10,7 +10,6 @@ import "echarts-gl";
import WUXI from "@/assets/wuxi.json";
import tooltip from "./tooltip.vue"
export default {
inject: ["assets"],
data() {
return {
areas: new Map([
@ -165,7 +164,7 @@ export default {
},
labelData () {
let a = this.assets()
let a = this.$store.state.bigdata.assets
const [houses,lands] = a
let temp = Array.from(this.areas,(item,index) => ({
tag: item[0],
@ -207,6 +206,5 @@ export default {
#map {
width: 100%;
height: 100%;
padding: 20px;
}
</style>

@ -0,0 +1,169 @@
<template>
<div id="map1">
</div>
</template>
<script>
export default {
data() {
return {
markerList: [],
cluster: ""
}
},
computed: {
leases () {
return this.$store.state.bigdata.leases;
}
},
methods: {
pickRow({ row }) {
//this.isShowInfoWindow = true;
//this.openData = row;
let location = row.land_id_lands_id_relation ? row.land_id_lands_id_relation.zichanweizhi : row.house_id_houses_id_relation.zichanweizhi;
if (location) {
let lat, lng;
[lng, lat] = location.split(",");
this.map.panTo([lng, lat]);
this.map.setZoom(30);
// this.infoWindow.open(this.map, [lng, lat]);
} else {
this.map.panTo(this.center);
//this.infoWindow.open(this.map, this.center);
}
},
init(adcode = ["320200"]) {
this.map = new AMap.Map("map1", {
pitch: 50,
viewMode: "3D",
center: [120.283692, 31.614211],
rotation: -12, //
zoom: 20,
mapStyle: "amap://styles/blue"
});
this.map.on('click',e => {
console.log(e)
})
},
setMapMarker() {
this.map.remove(this.markerList);
this.markerList = [];
this.leases.forEach((item) => {
let location = item.land_id_lands_id_relation ? item.land_id_lands_id_relation.zichanweizhi : item.house_id_houses_id_relation.zichanweizhi;
if (location) {
let lat, lng;
[lng, lat] = location.split(",");
let marker = new AMap.Marker({
icon: "//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png",
position: [Number(lng), Number(lat)],
offset: new AMap.Pixel(-13, -30),
});
let markerContent = document.createElement("div");
markerContent.setAttribute("class", "map-marker");
markerContent.onclick = () => {
this.pickRow({ row: item });
};
let markerImg = document.createElement("img");
markerImg.src = "//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png";
let markerSpan = document.createElement("span");
markerSpan.setAttribute("class", "map-marker__text");
markerSpan.innerText =
item.dikuaimingcheng?.length > 4
? item.dikuaimingcheng.slice(0, 2) +
".." +
item.dikuaimingcheng.slice(item.dikuaimingcheng.length - 2)
: item.dikuaimingcheng;
markerContent.appendChild(markerImg);
markerContent.appendChild(markerSpan);
marker.setContent(markerContent);
this.markerList.push(marker);
}
});
this.map.add(this.markerList);
this.addCluster();
},
addCluster() {
if (this.cluster) {
this.cluster.setMap(null);
}
this.cluster = new AMap.MarkerClusterer(this.map, this.markerList, {
gridSize: 50, //
//renderClusterMarker: this.renderClusterMarker, //
//renderMarker: this.renderMarker, //
});
},
renderMarker(context) {
let content =
'<div style="background-color: hsla(180, 100%, 50%, 0.3); height: 18px; width: 18px; border: 1px solid hsl(180, 100%, 40%); border-radius: 12px; box-shadow: hsl(180, 100%, 50%) 0px 0px 3px;"></div>';
let offset = new AMap.Pixel(-9, -9);
context.marker.setContent(content);
context.marker.setOffset(offset);
},
renderClusterMarker(context) {
let factor = Math.pow(context.count / this.list.length, 1 / 18);
let div = document.createElement("div");
let Hue = 180 - factor * 180;
let bgColor = "hsla(" + Hue + ",100%,40%,0.7)";
let fontColor = "hsla(" + Hue + ",100%,90%,1)";
let borderColor = "hsla(" + Hue + ",100%,40%,1)";
let shadowColor = "hsla(" + Hue + ",100%,90%,1)";
div.style.backgroundColor = bgColor;
let size = Math.round(
30 + Math.pow(context.count / this.list.length, 1 / 5) * 20
);
div.style.width = div.style.height = size + "px";
div.style.border = "solid 1px " + borderColor;
div.style.borderRadius = size / 2 + "px";
div.style.boxShadow = "0 0 5px " + shadowColor;
div.innerHTML = context.count;
div.style.lineHeight = size + "px";
div.style.color = fontColor;
div.style.fontSize = "14px";
div.style.textAlign = "center";
context.marker.setOffset(new AMap.Pixel(-size / 2, -size / 2));
context.marker.setContent(div);
},
},
watch: {
leases () {
if (this.map) {
this.$nextTick(() => {
this.setMapMarker();
})
}
}
},
mounted() {
this.$nextTick(() => {
this.init()
})
}
}
</script>
<style scoped lang="scss">
#map1 {
width: 100%;
height: 100%;
padding: 20px;
}
</style>
<style lang="scss">
.map-marker {
display: flex;
flex-direction: column;
align-items: center;
&__text {
background: #fff;
zoom: 0.75;
padding: 2px 6px;
border-radius: 4px;
white-space: nowrap;
filter: drop-shadow(2px 2px 5px #00000055);
}
}
</style>

@ -5,7 +5,7 @@
<span>
<SvgIcon icon-class="tudi" class="text-icon"></SvgIcon>
</span>
<span class="fs-xl text">土地资产</span>
<span class="fs-xl text">{{ type === 1 ? '土地资产' : '合约中' }}</span>
</div>
<dv-scroll-ranking-board class="dv-scr-rank-board mt-1" :config="ranking" />
@ -19,26 +19,44 @@ export default {
components: {
SvgIcon
},
inject: ["assets"],
data() {
return {
}
},
methods: {},
computed: {
type () {
return this.$store.state.bigdata.type
},
ranking () {
if (this.assets()[1]) {
return {
data: this.assets()[1].map(item => ({
name: item.name.length > 16 ? (item.name.slice(0, 14) + '...') : item.name,
value: item.dengjimianji ?? 0
})),
carousel: 'single',
unit: '平方',
waitTime: 4000,
rowNum: 3
if (this.type === 1) {
if (this.$store.state.bigdata.assets[1]) {
return {
data: this.$store.state.bigdata.assets[1].map(item => ({
name: item.name.length > 16 ? (item.name.slice(0, 14) + '...') : item.name,
value: item.dengjimianji ?? 0
})),
carousel: 'single',
unit: '平方',
waitTime: 4000,
rowNum: 3
}
}
} else if (this.type === 2) {
if (this.$store.state.bigdata.leases) {
return {
data: this.$store.state.bigdata.leases.map(item => ({
name: item.dikuaimingcheng.length > 16 ? (item.dikuaimingcheng.slice(0, 14) + '...') : item.dikuaimingcheng,
value: item.zulinmianji ?? 0
})),
carousel: 'single',
unit: '平方',
waitTime: 4000,
rowNum: 3
}
}
}
}
}
}

@ -5,7 +5,7 @@
<span>
<SvgIcon icon-class="fangwu" class="text-icon"></SvgIcon>
</span>
<span class="fs-xl text">房屋资产</span>
<span class="fs-xl text">{{ type === 1 ? '房屋资产' : '临期' }}</span>
</div>
<dv-scroll-ranking-board class="dv-scr-rank-board mt-1" :config="ranking"/>
@ -20,23 +20,40 @@ export default {
components: {
SvgIcon
},
inject: ["assets"],
data() {
return {}
},
methods: {},
computed: {
type () {
return this.$store.state.bigdata.type
},
ranking() {
if (this.assets()[0]) {
return {
data: this.assets()[0].map(item => ({
name: item.name.length > 16 ? (item.name.slice(0, 14) + '...') : item.name,
value: item.dengjimianji ?? 0
})),
carousel: 'single',
unit: '平方',
waitTime: 4000,
rowNum: 3
if (this.type === 1) {
if (this.$store.state.bigdata.assets[0]) {
return {
data: this.$store.state.bigdata.assets[0].map(item => ({
name: item.name.length > 16 ? (item.name.slice(0, 14) + '...') : item.name,
value: item.dengjimianji ?? 0
})),
carousel: 'single',
unit: '平方',
waitTime: 4000,
rowNum: 3
}
}
} else if (this.type === 2) {
if (this.$store.state.bigdata.adventLeases) {
return {
data: this.$store.state.bigdata.adventLeases.map(item => ({
name: item.dikuaimingcheng.length > 16 ? (item.dikuaimingcheng.slice(0, 14) + '...') : item.dikuaimingcheng,
value: item.zulinmianji ?? 0
})),
carousel: 'single',
unit: '平方',
waitTime: 4000,
rowNum: 3
}
}
}
}

@ -25,7 +25,6 @@
import SvgIcon from "@/components/SvgIcon"
import Chart from "@/components/Charts"
export default {
inject: ["assets","leases"],
components: {
SvgIcon,
Chart
@ -63,7 +62,6 @@ export default {
assets = this.assetsList.filter(i => !!(i.jiaotong || i.jiaoyu || i.shangquan || i.shushidu))
myAsset = assets[Math.floor(Math.random() * assets.length)];
}
console.log(myAsset)
// if (this.leaseList instanceof Array) {
// console.log(this.leaseList)
// myLease = this.leaseList[Math.floor(Math.random() * this.leaseList.length)];
@ -72,7 +70,6 @@ export default {
//
this.cdata.asset = myAsset??{};
this.cdata.lease = myAsset ? myAsset["id_leases_land_id_relation"] : [];
console.log(this.cdata.lease)
this.cdata.radarData = myAsset ? [myAsset.jiaotong, myAsset.jiaoyu, myAsset.shangquan, myAsset.shushidu] : [];
this.cdata.radarDataAvg = assets ?
[
@ -86,10 +83,10 @@ export default {
},
computed: {
assetsList () {
return this.assets()[1]
return this.$store.state.bigdata.assets[1]
},
leaseList () {
return this.leases()
return this.$store.state.bigdata.leases
}
}
};

@ -1,6 +1,6 @@
<template>
<div>
<Table class="table" :data="info" :columns="columns"></Table>
<Table class="table" :data="showInfo" :columns="columns"></Table>
</div>
</template>
@ -11,6 +11,8 @@ export default {
},
data() {
return {
index: 0,
timer: null,
columns: [
{
key: "name",
@ -24,7 +26,27 @@ export default {
}
},
methods: {},
computed: {}
computed: {
showInfo () {
return this.info?.slice(this.index, this.index + 8) || [];
}
},
watch: {
info (newData) {
this.$nextTick(() => {
clearInterval(this.timer)
if (this.info?.length > 8) {
this.timer = setInterval(() => {
this.index = (++this.index) % (this.info?.length || 0);
},3000)
}
})
}
},
beforeDestroy () {
clearInterval(this.timer)
console.log('des')
}
}
</script>
@ -32,5 +54,9 @@ export default {
.table {
width: 320px;
height: auto;
max-height: 400px;
overflow-y: hidden;
}
::v-deep .ivu-table {}
</style>

@ -0,0 +1,256 @@
<script>
import { save, show, index, destroy } from "@/api/system/baseForm";
import { CreateDialog } from "@/utils/createDialog"
import { deepCopy } from "@/utils";
import { resolveFormInfo } from '@/utils/createTable'
export default {
props: {
tableName: String,
},
render(h) {
let dialog = new CreateDialog(this,[
{
key: 'niandu',
label: '年度',
render: h('el-date-picker', {
props: {
value: this.form['niandu'],
type: "year",
valueFormat: "yyyy"
},
style: {
width: '100%'
},
on: {
['input']:e => {
this.form['niandu'] = e
this.$set(this,'form',Object.assign({},this.form))
}
}
})
},
{
key: 'yuedu',
label: '月度',
render: h('el-date-picker', {
props: {
value: this.form['yuedu'],
type: "month",
valueFormat: "yyyy-MM"
},
style: {
width: '100%'
},
on: {
['input']:e => {
this.form['yuedu'] = e
console.log(this.form)
this.$set(this,'form',Object.assign({},this.form))
}
}
})
}
],{
width: "650px"
})
return dialog.render()
},
data() {
return {
columns: 1,
row: {},
formInfo: [],
id: "",
type: "add",
dialogVisible: false,
form: {},
originalForm: {},
rules: {},
file: {},
};
},
methods: {
setRow (row) {
this.row = row
},
init() {
for (let key in this.form) {
if (this.form[key] instanceof Array) {
this.form[key] = [];
} else {
this.form[key] = "";
}
}
this.$refs["elForm"].clearValidate();
},
show() {
this.dialogVisible = true;
},
hidden() {
this.dialogVisible = false;
},
setType(type = "add") {
let types = ["add", "editor", "show"];
if (types.includes(type)) {
this.type = type;
} else {
console.warn("Unknown type: " + type);
}
},
setId(id) {
if (typeof id == "number") {
this.id = id;
} else {
console.error("error typeof id: " + typeof id);
}
},
async getDetail() {
const res = await show({ id: this.id, table_name: this.tableName });
this.$integrateData(this.form, res);
this.formInfo.forEach((i) => {
if (i && (i.edit_input === "file" || i.edit_input === "files")) {
res[i._relations.link_with_name]
? (this.file[i.field] =
res[i._relations.link_with_name] instanceof Array
? res[i._relations.link_with_name].map((i) => {
return {
name: i?.name,
url: i?.url,
response: i,
};
})
: [
{
name: res[i._relations.link_with_name]?.name,
url: res[i._relations.link_with_name]?.url,
response: res[i._relations.link_with_name],
},
])
: (this.file[i.field] = []);
}
this.form = Object.assign({}, this.form);
this.originalForm = deepCopy(res);
});
},
submit() {
if (this.type === "add") {
if (this.form.hasOwnProperty("id")) {
delete this.form.id;
}
}
if (this.type === "editor") {
Object.defineProperty(this.form, "id", {
value: this.id,
enumerable: true,
configurable: true,
writable: true,
});
}
save(Object.assign(this.form, { table_name: this.tableName })).then(res => {
this.$Message.success({
content: `${this.type === "add" ? "新增" : "编辑"}成功`,
});
this.$emit("refresh");
this.hidden();
})
},
},
computed: {
title () {
if (this.type === 'add') return '新增'
if (this.type === 'editor') return '编辑'
if (this.type === 'show') return '查看'
}
},
watch: {
formInfo: {
handler: function (newVal) {
this.form = {};
this.rules = {};
this.file = {};
newVal.forEach((i) => {
if (i.field) {
this.form[i.field] = "";
if (
i.validation instanceof Array &&
i.validation.length > 0 &&
!!i.validation.find((i) => i === "required")
) {
this.rules[i.field] = [
{ required: true, message: `请填写${i.name}` },
];
}
if (i.edit_input === "files") {
this.form[i.field] = [];
}
if (i.edit_input === "files" || i.edit_input === "file") {
this.file[i.field] = [];
}
if (i.edit_input === "checkbox") {
this.form[i.field] = [];
}
if (i._relations) {
this.form[i._relations?.link_with_name] = [];
}
}
});
this.columns = newVal.length > 11 ? '2' : '1'
},
//immediate: true,
},
dialogVisible(val) {
if (val) {
document.documentElement.style.setProperty(
"--column-num",
this.columns
);
if (this.type === "editor" || this.type === "show") {
this.$nextTick(() => this.getDetail());
}
} else {
this.id = "";
this.type = "";
this.init();
this.$refs["elForm"].clearValidate();
delete this.form.id;
for (let key in this.file) {
this.file[key] = [];
}
}
},
},
created() {
resolveFormInfo(29).then(res => this.formInfo = res)
}
};
</script>
<style>
:root {
--column-num: 2;
}
</style>
<style scoped lang="scss">
.uploaded-a {
color: red;
text-decoration: none;
transition: all 0.2s;
}
.uploaded-a:hover {
color: red;
text-decoration: underline;
}
.form-body {
display: grid;
grid-gap: 10px;
grid-template-columns: repeat(var(--column-num), 1fr);
}
</style>

@ -0,0 +1,665 @@
<template>
<div>
<!-- 查询配置 -->
<div>
<div ref="lxHeader">
<LxHeader
:icon="$route.meta.icon"
:text="$route.meta.title"
style="margin-bottom: 10px; border: 0px; margin-top: 15px"
>
<div slot="content"></div>
<slot>
<header-content :auths="auths_auth_mixin">
<template #search>
<div style="display: flex">
<Select
v-model="select.filter[0].key"
style="width: 100px"
placeholder="搜索条目"
>
<Option
v-for="item in form"
:key="item.id"
:value="item.field"
>{{ item.name }}</Option
>
</Select>
<Select
v-model="select.filter[0].op"
style="width: 100px; margin-left: 10px"
placeholder="搜索条件"
>
<Option
v-for="item in op"
:key="item.value"
:value="item.value"
>{{ item.label }}</Option
>
</Select>
<template
v-if="
select.filter[0].op !== 'range' &&
!columnArrTest(select.filter[0].key)
"
>
<Input
v-model="select.filter[0].value"
style="width: 150px; margin-left: 10px"
placeholder="请填写关键词"
/>
</template>
<template
v-else-if="
select.filter[0].op !== 'range' &&
columnArrTest(select.filter[0].key)
"
>
<Select
v-model="select.filter[0].value"
style="width: 150px; margin-left: 10px"
placeholder="请选择关键词"
>
<Option
v-for="item in getColumnParams(select.filter[0].key)"
:key="item.id"
:value="getColumnField(select.filter[0].key)._relations ? item[getColumnField(select.filter[0].key)._relations.foreign_key] : item.value"
>{{
item.key || item.value || item.name || item.no || item.mingcheng || item.id
}}</Option
>
</Select>
</template>
<template v-else>
<Input
:value="select.filter[0].value.split(',')[0]"
style="width: 150px; margin-left: 10px"
placeholder="范围开始关键词"
@input="(e) => inputStartHandler(e, select.filter[0])"
/>
<span
style="
margin-left: 10px;
display: flex;
align-items: center;
"
></span
>
<Input
:value="select.filter[0].value.split(',')[1]"
style="width: 150px; margin-left: 10px"
placeholder="范围结束关键词"
@input="(e) => inputEndHandler(e, select.filter[0])"
/>
</template>
<Button
style="margin-left: 10px"
type="primary"
@click="$refs['xyTable'].getTableData(true)"
>查询</Button
>
<xy-selectors
style="margin-left: 10px"
@reset="reset"
@search="$refs['xyTable'].getTableData(true)"
>
<template>
<div class="select">
<div
class="select__item"
v-for="(item, index) in select.filter"
:key="`${item.value}-${index}`"
>
<p>条件{{ index + 1 }}</p>
<Select
v-model="item.key"
style="width: 100px"
placeholder="搜索条目"
>
<Option
v-for="item in form"
:key="item.id"
:value="item.field"
>{{ item.name }}</Option
>
</Select>
<Select
v-model="item.op"
style="width: 100px; margin-left: 10px"
placeholder="搜索条件"
>
<Option
v-for="item in op"
:key="item.value"
:value="item.value"
>{{ item.label }}</Option
>
</Select>
<template
v-if="
item.op !== 'range' && !columnArrTest(item.key)
"
>
<Input
v-model="item.value"
style="width: 150px; margin-left: 10px"
placeholder="请填写关键词"
/>
</template>
<template
v-else-if="
item.op !== 'range' && columnArrTest(item.key)
"
>
<Select
v-model="item.value"
style="width: 150px; margin-left: 10px"
placeholder="请选择关键词"
>
<Option
v-for="item in getColumnParams(item.key)"
:key="item.id"
:value="getColumnField(item.key)._relations ? item[getColumnField(item.key)._relations.foreign_key] : item.value"
>{{
item.key || item.value || item.name || item.no || item.mingcheng || item.id
}}</Option
>
</Select>
</template>
<template v-else>
<Input
:value="item.value.split(',')[0]"
style="width: 150px; margin-left: 10px"
placeholder="范围开始关键词"
@input="(e) => inputStartHandler(e, item)"
/>
<span style="margin-left: 10px"></span>
<Input
:value="item.value.split(',')[1]"
style="width: 150px; margin-left: 10px"
placeholder="范围结束关键词"
@input="(e) => inputEndHandler(e, item)"
/>
</template>
<el-button
v-if="index !== 0"
size="small"
type="danger"
icon="el-icon-delete"
circle
style="margin-left: 10px"
@click="select.filter.splice(index, 1)"
></el-button>
</div>
</div>
<div class="add-btn">
<el-button
size="small"
type="primary"
icon="el-icon-plus"
circle
@click="
select.filter.push({ key: '', op: '', value: '' })
"
></el-button>
<span>新增一条</span>
</div>
</template>
</xy-selectors>
</div>
</template>
<template #create>
<Button
type="primary"
@click="
$refs['dialog'].setType('add'), $refs['dialog'].show()
"
>新增</Button
>
</template>
<template #import>
<Button type="primary" @click="$refs['imports'].show()"
>导入</Button
>
</template>
<template #export>
<Button
type="primary"
@click="exportExcel(new Date().getTime().toString())"
>导出</Button
>
</template>
</header-content>
</slot>
</LxHeader>
</div>
</div>
<xy-table
:btn-width="300"
:auths="auths_auth_mixin"
:delay-req="true"
:destroy-action="destroy"
ref="xyTable"
:border="true"
:action="index"
:req-opt="select"
:destroy-req-opt="select"
:table-item="table"
@editor="
(row) => {
$refs['dialog'].setId(row.id);
$refs['dialog'].setType('editor');
$refs['dialog'].show();
}
"
@loaded="adjustAlignment"
>
</xy-table>
<add ref="dialog" :table-name="customForm.tableName" @refresh="$refs['xyTable'].getTableData()"></add>
<drawer
:table-name="customForm.tableName"
:form-info="form"
ref="drawer"
></drawer>
<imports
:table-name="customForm.tableName"
:form-info="form"
ref="imports"
@refresh="$refs['xyTable'].getTableData()"
></imports>
</div>
</template>
<script>
import { index as fieldIndex } from "@/api/system/customFormField";
import { authMixin } from "@/mixin/authMixin";
import { index, destroy } from "@/api/system/baseForm";
import { op } from "@/const/op";
import { download } from "@/utils/downloadRequest";
import { getparameter } from "@/api/system/dictionary";
import { show } from "@/api/system/customForm";
import * as XLSX from "xlsx";
import { saveAs } from "file-saver";
import { listdept } from "@/api/system/department"
import LxHeader from "@/components/LxHeader/index.vue";
import headerContent from "@/components/LxHeader/XyContent.vue";
import drawer from "@/views/component/drawer.vue";
import imports from "@/views/component/imports.vue";
import add from "./component/addSafetyPlan.vue"
export default {
name: 'tableList',
components: {
LxHeader,
headerContent,
drawer,
imports,
add
},
mixins: [authMixin],
provide: {
formStore: () => this.form,
},
data() {
return {
firstAdjustTable: true,
op,
select: {
table_name: "",
filter: [
{
key: "",
op: "",
value: "",
},
],
},
form: [],
table: [],
customForm: {
customFormId: "",
tableName: "",
},
};
},
methods: {
index,
destroy,
download,
reset() {
this.select.filter.splice(1);
this.select.filter[0] = {
key: "",
op: "",
value: "",
};
},
async exportExcel(sheetName) {
const res = await index(
Object.assign(this.select, { page: 1, page_size: 9999 })
);
if (res.data) {
let headers = this.form.map((i) => {
return {
key: i.field,
title: i.name,
};
});
const data = res.data.map((row) =>
headers.map((header) => row[header.key])
);
data.unshift(headers.map((header) => header.title));
const wb = XLSX.utils.book_new();
const ws = XLSX.utils.aoa_to_sheet(data);
XLSX.utils.book_append_sheet(wb, ws, sheetName);
const wbout = XLSX.write(wb, {
bookType: "xlsx",
bookSST: true,
type: "array",
});
saveAs(
new Blob([wbout], { type: "application/octet-stream" }),
`${sheetName}.xlsx`
);
}
},
//target
inputStartHandler(e, target) {
let temp = target?.value.split(",")[1];
target.value = `${e},${temp ? temp : ""}`;
},
inputEndHandler(e, target) {
let temp = target?.value.split(",")[0];
target.value = `${temp ? temp : ""},${e}`;
},
async getFormDetail() {
if (this.$route.meta.params?.custom_form) {
let decode = decodeURIComponent(this.$route.meta.params?.custom_form);
try {
let custom_form = JSON.parse(decode);
this.customForm.customFormId = custom_form.custom_form_id;
this.customForm.tableName = custom_form.table_name;
this.select.table_name = custom_form.table_name;
} catch (err) {
console.warn(err);
}
}
const res = await show({ id: this.customForm.customFormId }, false);
//
//
let baseTable = new Map([
['departments', async () => {
const res = await listdept()
return res
}],
['admins',[]]
])
let { fields, relation } = res;
let fieldRes = fields.sort((a,b) => a.sort - b.sort)
if (
!fields ||
!relation ||
!fields instanceof Array ||
!relation instanceof Array
) {
throw new Error("fields或relation格式错误");
}
console.log(fieldRes)
fieldRes?.forEach((i, index) => {
i._relations = relation.find(
(j) => j.link_table_name.split("_")[1] === i.field
) || relation.find(
(j) => j.local_key === i.field
);
if (i.select_item && typeof i.select_item === "object") {
let keys = Object.keys(i.select_item);
if (keys.length > 0) {
i._params = keys.map((key) => {
return {
key,
value: /^\d*$/.test(i.select_item[key])
? Number(i.select_item[key])
: i.select_item[key],
};
});
}
}
if (i.edit_input === 'file' || i.edit_input === 'files') {
return
}
if (i._relations) {
if (baseTable.get(i._relations.link_table_name)) {
baseTable
.get(i._relations.link_table_name)()
.then((res) => {
i._params = res.data;
});
} else {
i._params = i._relations.parameter_id
? getparameter({ id: i._relations.parameter_id }, false).then(
(res) => {
i._params = res.detail;
}
)
: this.index({
table_name: i._relations.link_table_name,
page: 1,
page_size: 9999,
}).then((res) => {
i._params = res.data;
});
}
}
});
this.form = fieldRes || [];
this.form
?.filter((i) => i.list_show)
.forEach((i) => {
let linkOb = {};
if (i.edit_input === "richtext") {
linkOb.customFn = (row) => {
return (
<div
style={{ "max-height": "55px","overflow": "scroll" }}
domPropsInnerHTML={row[i.field]}
></div>
);
};
}
if (
i.select_item &&
typeof i.select_item === "object" &&
!(i.select_item instanceof Array)
) {
let keys = Object.keys(i.select_item);
linkOb.customFn = (row) => {
let paramMap = new Map();
keys.forEach((key) => {
paramMap.set(i.select_item[key], key);
});
return <span>{ paramMap.get(row[i.field]) ? paramMap.get(row[i.field].toString()) : row[i.field] }</span>;
};
}
if (i._relations) {
let { link_relation, foreign_key, link_with_name } = i._relations;
if (link_relation === "newHasOne" || link_relation === "hasOne") {
linkOb.customFn = (row) => {
if (i.edit_input === "file") {
return (
<a
download={row[link_with_name]?.original_name}
href={row[link_with_name]?.url}
>
{row[link_with_name]?.original_name}
</a>
);
} else {
return (
<span>
{row[link_with_name]?.name ||
row[link_with_name]?.no ||
row[link_with_name]?.value}
</span>
);
}
};
}
if (link_relation === "hasMany" || link_relation === "newHasMany") {
linkOb.customFn = (row) => {
if (i.edit_input === "files") {
return (
<div style="display: flex;flex-direction: column;">
{row[link_with_name]?.map((o) => (
<a>
{ o?.original_name || o?.name }
</a>
))}
</div>
)
} else {
return (
<div>
{row[link_with_name]?.map((o) => (
<p>
{o?.name ||
o?.no ||
o?.value ||
o?.biaoti ||
o?.mingcheng}
</p>
))}
</div>
);
}
};
}
}
//let alignLeft = ['dikuaimingcheng','chengjiandanwei','jianshedanwei','wuyedanwei']
this.table.push(
Object.assign(
{
prop: i.field,
label: i.name,
width: i.width,
align: 'center',
fixed: i.is_fixed,
},
linkOb
)
);
});
this.table.unshift({
type: "index",
width: 60,
label: "序号",
});
},
adjustAlignment () {
if (this.firstAdjustTable) {
const data = this.$refs['xyTable'].getListData();
if (data.length === 0) return;
this.form.filter(i => i.list_show).forEach((i) => {
let lengthTemp;
let temp = 0;
while (!lengthTemp || temp < data.length) {
lengthTemp = data[temp][i.field]?.length??0;
temp++;
}
for (let j = 0;j < data.length;j++) {
if (/^-?\d+\.\d+/.test(data[j][i.field])) {
this.table.find(a => a.prop === i.field).align = 'right';
return
}
if (Math.abs(lengthTemp - (data[j][i.field]?.length)??0) > 4) {
this.table.find(a => a.prop === i.field).align = 'left';
return
}
}
})
this.$nextTick(() => {
this.$refs['xyTable'].doLayout();
this.firstAdjustTable = false;
})
}
}
},
computed: {
columnArrTest() {
return function (field) {
return this.form.find((i) => i.field === field)
? this.form.find((i) => i.field === field).search_input === "checkbox" || this.form.find((i) => i.field === field).search_input === "radio"
: false;
};
},
getColumnField() {
return function (field) {
return this.form.find((i) => i.field === field)
? this.form.find((i) => i.field === field)
: {};
};
},
getColumnParams() {
return function (field) {
return this.form.find((i) => i.field === field)
? this.form.find((i) => i.field === field)._params
: [];
};
}
},
created() {
this.getFormDetail();
},
};
</script>
<style scoped lang="scss">
.select {
&__item {
& > p {
display: inline-block;
width: 80px;
text-align: center;
}
& + div {
margin-top: 6px;
}
}
}
.add-btn {
display: flex;
justify-content: center;
align-items: center;
margin-top: 10px;
& > span {
padding: 0 10px;
}
}
a {
color: red;
text-decoration: none;
transition: all 0.2s;
}
a:hover {
color: red;
text-decoration: underline;
}
</style>
Loading…
Cancel
Save