whx vor 1 Jahr
Ursprung
Commit
8f2ab53292

+ 146 - 0
virgo.wzfrontend/console/src/components/common/customData.vue

@@ -0,0 +1,146 @@
+<template>
+	<div class="custom-data">
+		<table border="1" cellspacing="0" cellpadding="0">
+			<tr class="th-title">
+				<th style="width: 200px;">属性代码</th>
+				<th style="width: 200px;">属性名称</th>
+				<th>属性值</th>
+			</tr>
+			<tr v-for="(item,index) in listData" :key="index">
+				<td>
+					<el-input v-model="item.key"></el-input>
+				</td>
+				<td>
+					<el-input v-model="item.keyName"></el-input>
+				</td>
+				<td>
+					<div class="td-input">
+						<el-input v-model="item.value"></el-input>
+						<div class="td-icon" @click="deleteRow(index)">
+							<i class="iconfont huifont-guanbi"></i>
+						</div>
+					</div>
+				</td>
+			</tr>
+			<tr>
+				<td colspan="3">
+					<div class="insert-icon color-primary" @click="insertRow()">
+						<i class="iconfont huifont-xinzeng"></i>
+						新增
+					</div>
+				</td>
+			</tr>
+		</table>
+	</div>
+</template>
+
+<script>
+	export default {
+		props: {
+			list: {
+				type: Array,
+				default: () => {
+					return []
+				}
+			},
+		},
+		data() {
+			return {
+				listData: []
+			}
+		},
+		created() {
+			this.listData = this.list;
+		},
+		methods: {
+			insertRow() {
+				this.listData.push({
+					key: '',
+					keyName: '',
+					value: ''
+				});
+			},
+			deleteRow(index) {
+				this.$confirm('确定要删除该项数据?', () => {
+					this.listData.splice(index, 1);
+				});
+			}
+		},
+		watch: {
+			list() {
+				this.listData = this.list;
+			}
+		},
+	}
+</script>
+
+<style lang="scss">
+	.custom-data {
+		table {
+			width: 100%;
+			border: 1px solid $--color-border;
+			border-collapse: collapse;
+			table-layout: fixed;
+		}
+
+		table th {
+			padding: 5px 0;
+			border: 1px solid $--color-border;
+			font-weight: 500;
+		}
+
+
+		table td {
+			border: 1px solid $--color-border;
+			padding: 6px 20px;
+		}
+
+		.insert-icon {
+			text-align: center;
+			cursor: pointer;
+			border-radius: 2px;
+			border: 1px dashed $--color-border;
+			line-height: 26px;
+			font-size: 13px;
+
+			.huifont-xinzeng {
+				font-size: 13px;
+			}
+		}
+
+		.td-input {
+			display: flex;
+			align-items: center;
+
+			.el-input {
+				flex: 1;
+				width: 0;
+				overflow: hidden;
+			}
+
+			.td-icon {
+				width: 20px;
+				height: 20px;
+				background: #171F2D;
+				border-radius: 10px;
+				border: 1px solid #8596B0;
+				opacity: 0.6;
+				text-align: center;
+				line-height: 16px;
+				margin-left: 12px;
+				color: #8596B0;
+				cursor: pointer;
+			}
+
+			.td-icon:hover {
+				color: $--color-red;
+				border-color: $--color-red;
+			}
+
+			.iconfont {
+				font-size: 10px;
+				margin-left: 1px;
+			}
+		}
+	}
+</style>

+ 30 - 61
virgo.wzfrontend/console/src/components/common/projectItem.vue

@@ -1,13 +1,13 @@
 <template>
-	<el-form :model="formBox" label-position="top">
-		<el-form-item label="单位工程">
+	<el-form :model="formBox" ref="formBox" label-position="top">
+		<el-form-item label="单位工程" prop="projectItemId" :rules="[{required: true, message: '请选择单位工程'}]">
 			<el-select v-model="formBox.projectItemId" placeholder="请选择单位工程" @change="changeProjectItem">
 				<el-option v-for="item in projectItemList" :key="item.id" :label="item.name" :value="item.id">
 				</el-option>
 			</el-select>
 		</el-form-item>
-		<el-form-item label="具体位置">
-			<el-select v-model="formBox.projectItemTargetId" placeholder="请选择具体位置" @change="changeRoom">
+		<el-form-item label="具体位置" prop="projectItemTargetId" :rules="[{required: true, message: '请选择具体位置'}]">
+			<el-select v-model="formBox.projectItemTargetId" placeholder="请选择具体位置">
 				<el-option v-for="item in projectItemTargetList" :key="item.id" :label="item.name" :value="item.id">
 				</el-option>
 			</el-select>
@@ -18,8 +18,6 @@
 <script>
 	import {
 		getProjectDetailById,
-		getProjectItemTargetList,
-		getRoomList
 	} from '@/httpApi/space'
 	export default {
 		props: ['form', 'room'],
@@ -28,93 +26,64 @@
 				formBox: {
 					projectItemId: '',
 					projectItemTargetId: '',
-					projectItemTargetRoomId: ''
 				},
 				projectItemList: [],
 				projectItemTargetList: [],
-				roomList: []
 			}
 		},
 		created() {
-			if (this.form.projectItemId) this.initData(this.form)
 			this.init();
 		},
 		methods: {
 			init() {
 				this.projectItemList = [];
 				this.projectItemTargetList = [];
-				getProjectDetailById(this.$store.getters.organization.id, this.$store.getters.project.id).then(res => {
+				getProjectDetailById(this.$store.getters.project.id).then(res => {
 					if (res.state) {
-						this.projectItemList = res.data.projectItemList
+						this.projectItemList = res.data.projectItemList;
+						if (this.form.projectItemId) this.initData()
 					}
 				})
 			},
 			changeProjectItem() {
 				this.formBox.projectItemTargetId = '';
-				this.projectItemTargetList = [];
-				this.formBox.projectItemTargetRoomId = '';
-				this.roomList = [];
-				getProjectItemTargetList(this.formBox.projectItemId).then(res => {
-					if (res.state) {
-						this.projectItemTargetList = res.data;
-					}
-				})
+				this.projectItemTargetList = this.projectItemList.filter(node => node.id === this.formBox.projectItemId)[0]
+					.projectItemTargetList;
 			},
-			changeRoom() {
-				if (this.room) return;
-				this.formBox.projectItemTargetRoomId = '';
-				this.roomList = [];
-				getRoomList(this.formBox.projectItemTargetId).then(res => {
-					if (res.state) {
-						this.roomList = res.data;
+			submit(callBack) {
+				this.$refs.formBox.validate((valid) => {
+					if (valid) {
+						callBack(this.formBox, true);
+					} else {
+						callBack(this.formBox, false);
+						return false;
 					}
-				})
+				});
 			},
 			returnItem() {
 				return {
 					projectItem: this.projectItemList.filter(node => node.id === this.formBox.projectItemId)[0] || {},
 					projectItemTarget: this.projectItemTargetList.filter(node => node.id === this.formBox
-						.projectItemTargetId)[0] || {},
-					projectItemTargetRoom: this.roomList.filter(node => node.id === this.formBox.projectItemTargetRoomId)[
-						0] || {}
+						.projectItemTargetId)[0] || {}
 				}
 			},
-			initData(val) {
-				if (val.projectItemId) {
-					this.formBox.projectItemId = val.projectItemId;
-					if (val.projectItemId) {
-						getProjectItemTargetList(this.formBox.projectItemId).then(res => {
-							if (res.state) {
-								this.formBox.projectItemTargetId = val.projectItemTargetId;
-								this.projectItemTargetList = res.data;
-								if (res.data.length === 0) this.formBox.projectItemTargetId = '';
-								if (val.projectItemTargetId) {
-									getRoomList(this.formBox.projectItemTargetId).then(res => {
-										if (res.state) {
-											this.formBox.projectItemTargetRoomId = val
-												.projectItemTargetRoomId;
-											this.roomList = res.data;
-											if (res.data.length === 0) this.formBox
-												.projectItemTargetRoomId = '';
-										}
-									})
-								}
-							}
-						})
-					}
-				}
+			initData() {
+				this.formBox.projectItemId = this.form.projectItemId;
+				this.formBox.projectItemTargetId = this.form.projectItemTargetId;
+				this.projectItemTargetList = this.projectItemList.filter(node => node.id === this.formBox.projectItemId)[0]
+					.projectItemTargetList;
 			}
 		},
 		watch: {
-			form(val) {
-				this.initData(val);
+			form() {
+				if (this.projectItemList.length > 0) {
+					this.initData();
+				} else {
+					this.init();
+				}
 			}
 		},
 	}
 </script>
 
-<style lang="scss">
-	.project-item-change {
-		width: 100%;
-	}
-</style>
+<style></style>

+ 206 - 201
virgo.wzfrontend/console/src/components/common/tag.vue

@@ -1,202 +1,207 @@
-<template>
-	<div class="tag">
-		<div :class="className(item)" v-for="item in list" :key="item.id" @click="selectTag(item)">
-			<span class="label">{{item.name}}</span>
-			<i class="iconfont huifont-bianji" v-if="type === 'insert'" @click.stop="updateTag(item)"></i>
-			<i class="iconfont huifont-guanbi" v-if="type === 'insert'" @click.stop="deleteTag(item)"></i>
-		</div>
-		<div class="target-item target-item-insert" v-if="type === 'insert'" @click="insertTag">
-			<i class="iconfont huifont-xinzeng"></i>
-			<span class="label">新增标签</span>
-		</div>
-	</div>
-</template>
-
-<script>
-	import {
-		getTagList,
-		insertTag,
-		updateTag,
-		deleteTag
-	} from '@/httpApi/space'
-	export default {
-		name: 'tag',
-		props: {
-			type: {
-				type: String,
-				default: ''
-			},
-			tagType: {
-				type: Number,
-				default: 1
-			},
-			tagActive: {
-				type: Array,
-				default: () => {
-					return []
-				}
-			}
-		},
-		data() {
-			return {
-				list: [],
-				tagList: [],
-				dataBox: []
-			}
-		},
-		created() {
-			this.init();
-		},
-		methods: {
-			init() {
-				getTagList(this.tagType).then(res => {
-					if (res.state) {
-						this.dataBox = res.data;
-						this.initTagList();
-					}
-				})
-			},
-			initTagList() {
-				this.tagList = this.dataBox.filter(node => this.tagActive.filter(item => item == node.id)
-					.length > 0);
-				if (this.type === 'insert') {
-					this.list = this.dataBox;
-				} else {
-					this.list = this.tagList;
-				}
-			},
-			insertTag() {
-				this.$prompt('请输入标签名称', '有极', {
-					confirmButtonText: '确 定',
-					cancelButtonClass: 'cancel',
-					confirmButtonClass: 'confirm',
-					cancelButtonText: '取 消',
-					inputPattern: /\S/,
-					inputErrorMessage: '请输入标签名称'
-				}).then(({
-					value
-				}) => {
-					insertTag({
-						type: this.tagType,
-						name: value
-					}).then(res => {
-						if (res.state) {
-							this.init();
-							this.$message.success('操作成功')
-						}
-					})
-				}).catch(() => {});
-			},
-			updateTag(item) {
-				this.$prompt('请输入标签名称', '有极', {
-					confirmButtonText: '确 定',
-					cancelButtonClass: 'cancel',
-					confirmButtonClass: 'confirm',
-					cancelButtonText: '取 消',
-					inputPattern: /\S/,
-					inputErrorMessage: '请输入标签名称',
-					inputValue: item.name
-				}).then(({
-					value
-				}) => {
-					updateTag({
-						type: this.tagType,
-						name: value,
-						id: item.id
-					}).then(res => {
-						if (res.state) {
-							this.init();
-							this.$message.success('操作成功')
-						}
-					})
-				}).catch(() => {});
-			},
-			selectTag(item) {
-				if (this.type === 'look') return;
-				if (this.tagList.filter(node => node.id === item.id).length > 0) {
-					let index = this.tagList.findIndex(node => node.id === item.id);
-					this.tagList.splice(index, 1);
-				} else {
-					this.tagList.push(item);
-				}
-			},
-			className(item) {
-				let str = this.tagList.filter(node => node.id === item.id).length > 0 ? 'target-item active' :
-					'target-item';
-				if (this.type === 'insert') str += ' add'
-				return str;
-			},
-			deleteTag(item) {
-				this.$confirm('确定要删除该标签?', () => {
-					deleteTag(item.id).then(res => {
-						if (res.state) {
-							this.init();
-							this.$message.success('操作成功');
-						}
-					})
-				});
-			},
-			tagIds() {
-				return this.tagList.sort((a, b) => a.id - b.id).map(node => node.id).join(',');
-			}
-		},
-		watch: {
-			tagActive() {
-				this.initTagList();
-			}
-		},
-	}
-</script>
-
-<style lang="scss">
-	.tag {
-		display: flex;
-		flex-wrap: wrap;
-
-		.target-item {
-			display: flex;
-			height: 32px;
-			align-items: center;
-			margin: 5px 0;
-			margin-right: 15px;
-			background: #46577a;
-			border-radius: 15px;
-			padding: 0 15px;
-
-			.iconfont {
-				margin-left: 10px;
-				font-size: 12px;
-			}
-
-			.huifont-bianji {
-				font-size: 18px;
-			}
-
-			&.active {
-				background: $--color-primary;
-				color: #fff;
-			}
-
-			&.add {
-				cursor: pointer;
-			}
-		}
-
-		.target-item-insert {
-			cursor: pointer;
-			background: transparent;
-			border: 1px solid #7383ad;
-			color: #7383ad;
-
-			.iconfont {
-				margin-left: 0;
-				margin-right: 10px;
-			}
-		}
-
-		.target-item-insert:hover {
-			border-color: $--color-primary;
-			color: $--color-primary;
-		}
-	}
+<template>
+	<div class="tag">
+		<div class="no-tips" v-if="list.length === 0 && type === 'look'">暂无标签</div>
+		<div :class="className(item)" v-for="item in list" :key="item.id" @click="selectTag(item)">
+			<span class="label">{{item.name}}</span>
+			<i class="iconfont huifont-bianji" v-if="type === 'insert'" @click.stop="updateTag(item)"></i>
+			<i class="iconfont huifont-guanbi" v-if="type === 'insert'" @click.stop="deleteTag(item)"></i>
+		</div>
+		<div class="target-item target-item-insert" v-if="type === 'insert'" @click="insertTag">
+			<i class="iconfont huifont-xinzeng"></i>
+			<span class="label">新增标签</span>
+		</div>
+	</div>
+</template>
+
+<script>
+	import {
+		getTagList,
+		insertTag,
+		updateTag,
+		deleteTag
+	} from '@/httpApi/space'
+	export default {
+		name: 'tag',
+		props: {
+			type: {
+				type: String,
+				default: ''
+			},
+			tagType: {
+				type: Number,
+				default: 1
+			},
+			tagActive: {
+				type: Array,
+				default: () => {
+					return []
+				}
+			}
+		},
+		data() {
+			return {
+				list: [],
+				tagList: [],
+				dataBox: []
+			}
+		},
+		created() {
+			this.init();
+		},
+		methods: {
+			init() {
+				getTagList(this.tagType).then(res => {
+					if (res.state) {
+						this.dataBox = res.data;
+						this.initTagList();
+					}
+				})
+			},
+			initTagList() {
+				this.tagList = this.dataBox.filter(node => this.tagActive.filter(item => item == node.id)
+					.length > 0);
+				if (this.type === 'insert') {
+					this.list = this.dataBox;
+				} else {
+					this.list = this.tagList;
+				}
+			},
+			insertTag() {
+				this.$prompt('请输入标签名称', '有极', {
+					confirmButtonText: '确 定',
+					cancelButtonClass: 'cancel',
+					confirmButtonClass: 'confirm',
+					cancelButtonText: '取 消',
+					inputPattern: /\S/,
+					inputErrorMessage: '请输入标签名称'
+				}).then(({
+					value
+				}) => {
+					insertTag({
+						type: this.tagType,
+						name: value
+					}).then(res => {
+						if (res.state) {
+							this.init();
+							this.$message.success('操作成功')
+						}
+					})
+				}).catch(() => {});
+			},
+			updateTag(item) {
+				this.$prompt('请输入标签名称', '有极', {
+					confirmButtonText: '确 定',
+					cancelButtonClass: 'cancel',
+					confirmButtonClass: 'confirm',
+					cancelButtonText: '取 消',
+					inputPattern: /\S/,
+					inputErrorMessage: '请输入标签名称',
+					inputValue: item.name
+				}).then(({
+					value
+				}) => {
+					updateTag({
+						type: this.tagType,
+						name: value,
+						id: item.id
+					}).then(res => {
+						if (res.state) {
+							this.init();
+							this.$message.success('操作成功')
+						}
+					})
+				}).catch(() => {});
+			},
+			selectTag(item) {
+				if (this.type === 'look') return;
+				if (this.tagList.filter(node => node.id === item.id).length > 0) {
+					let index = this.tagList.findIndex(node => node.id === item.id);
+					this.tagList.splice(index, 1);
+				} else {
+					this.tagList.push(item);
+				}
+			},
+			className(item) {
+				let str = this.tagList.filter(node => node.id === item.id).length > 0 ? 'target-item active' :
+					'target-item';
+				if (this.type === 'insert') str += ' add'
+				return str;
+			},
+			deleteTag(item) {
+				this.$confirm('确定要删除该标签?', () => {
+					deleteTag(item.id).then(res => {
+						if (res.state) {
+							this.init();
+							this.$message.success('操作成功');
+						}
+					})
+				});
+			},
+			tagIds() {
+				return this.tagList.sort((a, b) => a.id - b.id).map(node => node.id).join(',');
+			}
+		},
+		watch: {
+			tagActive() {
+				this.initTagList();
+			}
+		},
+	}
+</script>
+
+<style lang="scss">
+	.tag {
+		display: flex;
+		flex-wrap: wrap;
+
+		.target-item {
+			display: flex;
+			height: 28px;
+			align-items: center;
+			margin: 5px 0;
+			margin-right: 15px;
+			background: #46577a;
+			border-radius: 15px;
+			padding: 0 15px;
+
+			.label {
+				font-size: 12px;
+			}
+
+			.iconfont {
+				margin-left: 10px;
+				font-size: 12px;
+			}
+
+			.huifont-bianji {
+				font-size: 18px;
+			}
+
+			&.active {
+				background: $--color-primary;
+				color: #fff;
+			}
+
+			&.add {
+				cursor: pointer;
+			}
+		}
+
+		.target-item-insert {
+			cursor: pointer;
+			background: transparent;
+			border: 1px solid #7383ad;
+			color: #7383ad;
+
+			.iconfont {
+				margin-left: 0;
+				margin-right: 10px;
+			}
+		}
+
+		.target-item-insert:hover {
+			border-color: $--color-primary;
+			color: $--color-primary;
+		}
+	}
 </style>

+ 114 - 10
virgo.wzfrontend/console/src/components/common/upload.vue

@@ -4,7 +4,13 @@
 			<div class="no-tips" v-if="fileList.length === 0">暂无附件</div>
 			<div class="common-perview-image" v-else>
 				<div class="common-update-image-box" v-for="(item,index) in fileList" :key="item.id">
-					<el-image :src="item.url" :preview-src-list="[item.url]">
+					<div class="el-image video-image" v-if="item.type === 'mp4'">
+						<div class="video-icon">
+							<i class="el-icon-video-play" @click="openVideo(item)"></i>
+						</div>
+						<img :src="videoPreviewList[item.id]" class="el-image__inner">
+					</div>
+					<el-image :src="item.url" :preview-src-list="[item.url]" v-else>
 						<div slot="error" class="image-slot">
 							<el-tooltip class="item" effect="dark" :content="item.name" placement="bottom">
 								<div class="image-text">{{item.type.toUpperCase()}}</div>
@@ -16,7 +22,13 @@
 		</div>
 		<div class="common-update-image" v-else>
 			<div class="common-update-image-box" v-for="(item,index) in fileList" :key="item.id">
-				<el-image :src="item.url" :preview-src-list="[item.url]">
+				<div class="el-image video-image" v-if="item.type === 'mp4'">
+					<div class="video-icon">
+						<i class="el-icon-video-play" @click="openVideo(item)"></i>
+					</div>
+					<img :src="videoPreviewList[item.id]" class="el-image__inner">
+				</div>
+				<el-image :src="item.url" :preview-src-list="[item.url]" v-else>
 					<div slot="error" class="image-slot">
 						<el-tooltip class="item" effect="dark" :content="item.name" placement="bottom">
 							<div class="image-text">{{item.type.toUpperCase()}}</div>
@@ -28,14 +40,22 @@
 				</div>
 			</div>
 			<el-upload :action="action" :headers="headers" :show-file-list="false" name="uploadFile"
-				:before-upload="beforeUpload" :on-success="successFile" :on-error="errorFile"
-				v-if="fileList.length < maxLen">
+				:before-upload="beforeUpload" :on-success="successFile" :on-error="errorFile" :accept="accept"
+				v-if="fileList.length < maxLen" :on-progress="progress">
 				<div class="common-update-button">
 					<i class="iconfont huifont-xinzeng"></i>
 					<div class="common-update-button-label">{{text}}</div>
 				</div>
 			</el-upload>
 		</div>
+		<el-dialog :title="video.name" custom-class="monitor-dialog" :visible.sync="visible" width="900px"
+			height="500px" :append-to-body="true">
+			<div class="video-box">
+				<video v-if="visible" width="900" height="445" controls>
+					<source :src="video.url" type="video/mp4" />
+				</video>
+			</div>
+		</el-dialog>
 	</div>
 </template>
 
@@ -62,8 +82,12 @@
 			},
 			text: {
 				type: String,
-				default: '上传附件'
-			}
+				default: '上传图片'
+			},
+			accept: {
+				type: String,
+				default: '.png, .jpg, .jpeg'
+			},
 		},
 		data() {
 			return {
@@ -73,7 +97,10 @@
 				},
 				url: '',
 				srcList: [],
-				fileList: []
+				fileList: [],
+				videoPreviewList: {},
+				visible: false,
+				video: {}
 			};
 		},
 		created() {
@@ -89,6 +116,12 @@
 					return false;
 				}
 			},
+			progress(e) {
+				let percent = e.percent >= 100 ? 99 : parseInt(e.percent)
+				this.$loading({
+					percent: (percent + '%')
+				});
+			},
 			successFile(response, file, fileList) {
 				//上传成功
 				if (!response.data) return this.errorFile();
@@ -101,30 +134,100 @@
 					url: data.node.url,
 					type: typeList[typeList.length - 1]
 				});
+				this.$loading.close();
 			},
 			errorFile() {
 				//上传失败
 				this.$message.error('上传失败');
+				this.$loading.close();
 			},
 			removeFile(index) {
 				this.$confirm('确定要删除该文件?', () => {
 					this.fileList.splice(index, 1);
 				});
+			},
+			openVideo(item) {
+				this.video = item;
+				this.visible = true;
+			},
+			mp4Preview(item) {
+				const video = document.createElement('video') // 也可以自己创建video
+				video.src = item.url // url地址 url跟 视频流是一样的
+				video.crossOrigin = '*' // 解决跨域问题,也就是提示污染资源无法转换视频
+				video.currentTime = 1 // 第一帧
+
+				video.oncanplay = () => {
+					let canvas = document.createElement('canvas') // 获取 canvas 对象
+					const ctx = canvas.getContext('2d') // 绘制2d
+
+					canvas.width = video.clientWidth ? video.clientWidth : 320 // 获取视频宽度
+					canvas.height = video.clientHeight ? video.clientHeight : 320 //获取视频高度
+					// 利用canvas对象方法绘图
+					ctx.drawImage(video, 0, 0, canvas.width, canvas.height)
+					// 转换成base64形式
+					const videoFirstImgsrc = canvas.toDataURL('image/png') // 截取后的视频封面
+					this.videoPreviewList[item.id] = videoFirstImgsrc;
+					this.$forceUpdate();
+					video.remove()
+					canvas.remove();
+
+				}
 			}
 		},
 		watch: {
 			list(val) {
-				this.fileList = JSON.parse(JSON.stringify(val))
+				this.fileList = JSON.parse(JSON.stringify(val));
+			},
+			fileList() {
+				for (let i = 0; i < this.fileList.length; i++) {
+					if (this.fileList[i].type === 'mp4') {
+						this.mp4Preview(this.fileList[i])
+					}
+				}
 			}
 		},
 	}
 </script>
 
 <style lang="scss">
+	.el-dialog.monitor-dialog {
+		height: 500px;
+		margin-top: 20vh !important;
+	}
+
 	.common-update {
 		display: flex;
 		flex-wrap: wrap;
 
+		.video-image {
+			cursor: pointer;
+			position: relative;
+
+			&:hover {
+				.video-icon {
+					opacity: 1;
+				}
+			}
+
+			.video-icon {
+				position: absolute;
+				top: 0;
+				left: 0;
+				right: 0;
+				bottom: 0;
+				display: flex;
+				align-items: center;
+				justify-content: center;
+				background: rgba(0, 0, 0, 0.6);
+				opacity: 0;
+				transition: opacity 200ms;
+
+				i {
+					font-size: 24px;
+				}
+			}
+		}
+
 		.common-update-button {
 			width: 100px;
 			height: 100px;
@@ -162,7 +265,8 @@
 		.image-slot {
 			width: 100%;
 			height: 100%;
-			border: 1px solid $--input-border;
+			border-radius: 4px;
+			background: #9a9a9a;
 
 			.image-text {
 				font-size: 20px;
@@ -171,7 +275,7 @@
 				display: flex;
 				align-items: center;
 				justify-content: center;
-				color: $--color-common;
+				color: #fff;
 				font-weight: bold;
 			}
 		}

+ 122 - 79
virgo.wzfrontend/console/src/components/work/space/house/detail.vue

@@ -1,80 +1,123 @@
-<template>
-	<div class="hui-detail">
-		<div class="hui-detail-title">基础信息</div>
-		<div class="hui-detail-content">
-			<div class="hui-detail-item">
-				<div class="hui-detail-label">项目名称</div>
-				<div class="hui-detail-value">{{detail.name}}</div>
-			</div>
-			<div class="hui-detail-item">
-				<div class="hui-detail-label">项目区域</div>
-				<div class="hui-detail-value">{{detail.address.join('-')}}</div>
-			</div>
-			<div class="hui-detail-item">
-				<div class="hui-detail-label">具体地点</div>
-				<div class="hui-detail-value">{{detail.specific}}</div>
-			</div>
-			<div class="hui-detail-item">
-				<div class="hui-detail-label">项目描述</div>
-				<div class="hui-detail-value">{{detail.comment}}</div>
-			</div>
-		</div>
-		<div class="hui-detail-title">项目标签</div>
-		<div class="hui-detail-content hui-detail-image">
-			<tag ref="tag" type="look" :tagType="1" :tagActive="detail.tagIds ? detail.tagIds.split(',') : []">
-			</tag>
-		</div>
-		<div class="hui-detail-title">项目图片</div>
-		<div class="hui-detail-content hui-detail-image">
-			<upload ref="upload" :list="detail.picture ? JSON.parse(detail.picture) : []" type="preview">
-			</upload>
-		</div>
-	</div>
-</template>
-
-<script>
-	import {
-		getProjectDetailById
-	} from '@/httpApi/space'
-	import upload from '@/components/common/upload'
-	import tag from '@/components/common/tag'
-	export default {
-		props: ['detailId'],
-		data() {
-			return {
-				detail: {
-					name: '', //项目名称
-					address: [],
-					comment: '',
-					data: '',
-					organizationId: '',
-					picture: '',
-					tagIds: ''
-				}
-			}
-		},
-		created() {
-			if (this.detailId) this.init();
-		},
-		components: {
-			upload,
-			tag
-		},
-		methods: {
-			init() {
-				getProjectDetailById(this.detailId).then(res => {
-					if (res.state) {
-						let obj = res.data;
-						let data = {};
-						if (obj.data) data = JSON.parse(obj.data);
-						obj.address = JSON.parse(obj.address);
-						this.detail = Object.assign(obj, data);
-					}
-				})
-			}
-		},
-	}
-</script>
-<style lang="scss">
-
+<template>
+	<div class="hui-detail">
+		<div class="hui-detail-title">基础信息</div>
+		<div class="hui-detail-content">
+			<div class="hui-detail-item">
+				<div class="hui-detail-label">项目名称</div>
+				<div class="hui-detail-value">{{detail.name}}</div>
+			</div>
+			<div class="hui-detail-item">
+				<div class="hui-detail-label">房间号</div>
+				<div class="hui-detail-value">{{detail.roomNumber}}</div>
+			</div>
+			<div class="hui-detail-item">
+				<div class="hui-detail-label">房源类型</div>
+				<div class="hui-detail-value">{{$field.findHouseTypeName(detail.roomTypeId)}}</div>
+			</div>
+			<div class="hui-detail-item">
+				<div class="hui-detail-label">房源面积</div>
+				<div class="hui-detail-value">{{detail.area}}</div>
+			</div>
+			<div class="hui-detail-item">
+				<div class="hui-detail-label">产权证书</div>
+				<div class="hui-detail-value">{{detail.propertyCertificateNumber}}</div>
+			</div>
+			<div class="hui-detail-item">
+				<div class="hui-detail-label">启用日期</div>
+				<div class="hui-detail-value">{{detail.invocationDate}}</div>
+			</div>
+			<div class="hui-detail-item">
+				<div class="hui-detail-label">是否装修</div>
+				<div class="hui-detail-value">{{detail.decoration === 1 ? '已装修':'未装修'}}</div>
+			</div>
+			<div class="hui-detail-item">
+				<div class="hui-detail-label">公开房源</div>
+				<div class="hui-detail-value">{{detail.openState === 1 ? '公开':'不公开'}}</div>
+			</div>
+			<div class="hui-detail-item">
+				<div class="hui-detail-label">招商状态</div>
+				<div class="hui-detail-value">{{detail.investmentState === 1 ? '已招商':'未招商'}}</div>
+			</div>
+		</div>
+		<div v-if="detail.data && detail.data != '[]'">
+			<div class="hui-detail-title">自定义信息</div>
+			<div class="hui-detail-content">
+				<div class="hui-detail-item" v-for="(item,index) in JSON.parse(detail.data)">
+					<div class="hui-detail-label">{{item.keyName}}</div>
+					<div class="hui-detail-value">{{item.value}}</div>
+				</div>
+			</div>
+		</div>
+		<div class="hui-detail-title">房源标签</div>
+		<div class="hui-detail-content hui-detail-image">
+			<tag ref="tag" type="look" :tagType="3" :tagActive="detail.tagIds ? detail.tagIds.split(',') : []">
+			</tag>
+		</div>
+		<div class="hui-detail-title">房源图片</div>
+		<div class="hui-detail-content hui-detail-image">
+			<upload :list="detail.picture ? JSON.parse(detail.picture) : []" type="preview">
+			</upload>
+		</div>
+		<div class="hui-detail-title">房源视频</div>
+		<div class="hui-detail-content hui-detail-image">
+			<upload :list="detail.video ? JSON.parse(detail.video) : []" type="preview">
+			</upload>
+		</div>
+	</div>
+</template>
+
+<script>
+	import {
+		getHouseDetailById
+	} from '@/httpApi/space'
+	import upload from '@/components/common/upload'
+	import tag from '@/components/common/tag'
+	export default {
+		props: ['detailId'],
+		data() {
+			return {
+				detail: {
+					name: '', //房源名称
+					roomNumber: '',
+					roomState: '', //房源状态
+					roomType: '', //房源类型
+					area: '',
+					decoration: 0,
+					investmentState: 0,
+					invocationDate: '',
+					openState: 0,
+					propertyCertificateNumber: '',
+					picture: '',
+					tagIds: '',
+					data: '',
+					projectId: '',
+					projectItemId: '',
+					projectItemTargetId: ''
+				},
+				customData: []
+			}
+		},
+		created() {
+			if (this.detailId) this.init();
+		},
+		components: {
+			upload,
+			tag
+		},
+		methods: {
+			init() {
+				getHouseDetailById(this.detailId).then(res => {
+					if (res.state) {
+						this.detail = res.data;
+						if (this.detail.data) {
+							this.customData = JSON.parse(this.detail.data);
+						}
+					}
+				})
+			}
+		},
+	}
+</script>
+<style lang="scss">
+
 </style>

+ 50 - 33
virgo.wzfrontend/console/src/components/work/space/house/edit.vue

@@ -1,7 +1,7 @@
 <template>
 	<div class="hui-flex hui-dialog">
-		<div class="hui-flex-box hui-dialog-content">
-			<project-item ref="projectItem"></project-item>
+		<div class="hui-flex-box hui-dialog-content">
+			<project-item ref="projectItem" :form="houseForm"></project-item>
 			<el-form ref="houseForm" label-position="top" :model="houseForm">
 				<el-form-item label="房源名称" prop="name" :rules="[{required: true, message: '请输入房源名称'}]">
 					<el-input type="text" v-model="houseForm.name" placeholder="请输入房源名称"></el-input>
@@ -9,37 +9,51 @@
 				<el-form-item label="房间号" prop="roomNumber" :rules="[{required: true, message: '请输入房间号'}]">
 					<el-input type="text" v-model="houseForm.roomNumber" placeholder="请输入房间号"></el-input>
 				</el-form-item>
-				<el-form-item label="房源面积(m²)" prop="area" :rules="[{required: true, message: '请输入房源面积(m²)'}]">
-					<el-input type="number" v-model="houseForm.area" placeholder="请输入房源面积(m²)"></el-input>
+				<el-form-item label="房源类型" prop="roomTypeId" :rules="[{required: true, message: '请选择房源类型'}]">
+					<el-select v-model="houseForm.roomTypeId" placeholder="请选择房源类型">
+						<el-option :label="item.name" :value="item.id" v-for="(item,index) in $field.field.houseType"
+							:key="item.id">
+						</el-option>
+					</el-select>
 				</el-form-item>
 				<el-form-item label="是否装修">
 					<el-radio v-model="houseForm.decoration" :label="0">未装修</el-radio>
 					<el-radio v-model="houseForm.decoration" :label="1">已装修</el-radio>
 				</el-form-item>
-				<el-form-item label="启用日期">
-					<el-date-picker v-model="houseForm.invocationDate" type="date" placeholder="其选择启用日期">
-					</el-date-picker>
+				<el-form-item label="房源面积(m²)" prop="area" :rules="[{required: true, message: '请输入房源面积(m²)'}]">
+					<el-input type="number" v-model="houseForm.area" placeholder="请输入房源面积(m²)"></el-input>
 				</el-form-item>
 				<el-form-item label="是否公开房源">
 					<el-radio v-model="houseForm.openState" :label="0">不公开</el-radio>
 					<el-radio v-model="houseForm.openState" :label="1">公开</el-radio>
 				</el-form-item>
-				<el-form-item label="产权证书/不动产权证号">
-					<el-input type="text" v-model="houseForm.propertyCertificateNumber" placeholder="请输入产权证书/不动产权证号">
-					</el-input>
+				<el-form-item label="启用日期">
+					<el-date-picker v-model="houseForm.invocationDate" value-format="yyyy-MM-dd" type="date"
+						placeholder="其选择启用日期">
+					</el-date-picker>
 				</el-form-item>
 				<el-form-item label="招商状态">
 					<el-radio v-model="houseForm.investmentState" :label="0">未招商</el-radio>
 					<el-radio v-model="houseForm.investmentState" :label="1">已招商</el-radio>
 				</el-form-item>
+				<el-form-item label="产权证书/不动产权证号">
+					<el-input type="text" v-model="houseForm.propertyCertificateNumber" placeholder="请输入产权证书/不动产权证号">
+					</el-input>
+				</el-form-item>
 				<el-form-item label="房源配图" class="hui-textarea">
-					<upload ref="upload" :list="responsibility" type="insert"></upload>
+					<upload ref="image" :list="responsibility" type="insert"></upload>
+				</el-form-item>
+				<el-form-item label="房源视频" class="hui-textarea">
+					<upload ref="video" :list="videoList" type="insert" text="上传视频" accept=".mp4"></upload>
 				</el-form-item>
 				<el-form-item label="房源标签" class="hui-textarea">
 					<tag ref="tag" type="insert" :tagType="3"
 						:tagActive="houseForm.tagIds ? houseForm.tagIds.split(',') : []">
 					</tag>
 				</el-form-item>
+				<el-form-item label="房源视频" class="hui-textarea">
+					<custom-data ref="customData" :list="customList"></custom-data>
+				</el-form-item>
 			</el-form>
 		</div>
 		<div class="hui-dialog-submit">
@@ -59,6 +73,7 @@
 	import city from '@/components/common/city'
 	import tag from '@/components/common/tag'
 	import projectItem from '@/components/common/projectItem'
+	import customData from '@/components/common/customData'
 	export default {
 		props: ['isUpdate', 'detailId'],
 		data() {
@@ -67,7 +82,7 @@
 					name: '', //房源名称
 					roomNumber: '',
 					roomState: '', //房源状态
-					roomType: '', //房源类型
+					roomTypeId: '', //房源类型
 					area: '',
 					decoration: 0,
 					investmentState: 0,
@@ -81,8 +96,9 @@
 					projectItemId: '',
 					projectItemTargetId: ''
 				},
-				specific: '',
-				responsibility: []
+				responsibility: [],
+				videoList: [],
+				customList: []
 			}
 		},
 		created() {
@@ -92,32 +108,32 @@
 					if (res.state) {
 						this.houseForm = res.data;
 						if (this.houseForm.picture) this.responsibility = JSON.parse(this.houseForm.picture);
-						if (this.houseForm.data) {
-							let data = JSON.parse(this.houseForm.data);
-							this.specific = data.specific;
-						}
+						if (this.houseForm.video) this.videoList = JSON.parse(this.houseForm.video);
+						if (this.houseForm.data) this.customList = JSON.parse(this.houseForm.data);
 					}
 				})
 			}
 		},
 		methods: {
 			submit() {
-				this.$refs.houseForm.validate((valid) => {
-					if (valid) {
-						let postData = JSON.parse(JSON.stringify(this.houseForm));
-						postData.data = JSON.stringify({
-							specific: this.specific
-						});
-						postData['picture'] = JSON.stringify(this.$refs.upload.fileList);
-						postData['tagIds'] = this.$refs.tag.tagIds();
-						if (this.isUpdate) {
-							updateHouse(postData).then(this.successFunc);
+				this.$refs.projectItem.submit((projectData, valids) => {
+					this.$refs.houseForm.validate((valid) => {
+						if (valid && valids) {
+							let postData = JSON.parse(JSON.stringify(this.houseForm));
+							postData['picture'] = JSON.stringify(this.$refs.image.fileList);
+							postData['video'] = JSON.stringify(this.$refs.video.fileList);
+							postData['data'] = JSON.stringify(this.$refs.customData.listData);
+							postData['tagIds'] = this.$refs.tag.tagIds();
+							postData = Object.assign(postData, projectData);
+							if (this.isUpdate) {
+								updateHouse(postData).then(this.successFunc);
+							} else {
+								insertHouse(postData).then(this.successFunc);
+							}
 						} else {
-							insertHouse(postData).then(this.successFunc);
+							return false;
 						}
-					} else {
-						return false;
-					}
+					});
 				});
 			},
 			successFunc(res) {
@@ -131,7 +147,8 @@
 			city,
 			upload,
 			tag,
-			projectItem
+			projectItem,
+			customData
 		},
 	}
 </script>

+ 31 - 0
virgo.wzfrontend/console/src/config/field.js

@@ -0,0 +1,31 @@
+const houseType = [{
+	id: 1,
+	name: '纯写字楼'
+}, {
+	id: 2,
+	name: '商住两用'
+}, {
+	id: 3,
+	name: '商业裙楼'
+}, {
+	id: 4,
+	name: '厂房改造'
+}]
+
+const findItem = (type, id) => {
+	if (type === 'houseType') {
+		return houseType.find(node => node.id === id) || {
+			id: 0,
+			name: '-'
+		};
+	}
+}
+
+export default {
+	field: {
+		houseType
+	},
+	findHouseTypeName(id) {
+		return findItem('houseType', id).name;
+	}
+}

+ 8 - 4
virgo.wzfrontend/console/src/main.js

@@ -12,11 +12,15 @@ import loading from './loading/loading';
 Vue.use(loading);
 
 import empty from './components/common/empty'
-Vue.component('empty', empty)
-
+Vue.component('empty', empty)
+
 import avatar from './components/common/avatar'
 Vue.component('avatar', avatar)
 
+import field from './config/field.js'
+console.log(field);
+Vue.prototype.$field = field;
+
 Vue.prototype.$confirm = (title, callback) => {
 	return ElementUI.MessageBox.confirm(title, '有极提示', {
 		confirmButtonText: '确 定',
@@ -25,8 +29,8 @@ Vue.prototype.$confirm = (title, callback) => {
 		cancelButtonText: '取 消',
 		type: 'warning'
 	}).then(callback).catch(() => {});
-};
-//router拦截器
+};
+//router拦截器
 import './uitls/permission'
 new Vue({
 	router,

+ 17 - 3
virgo.wzfrontend/console/src/views/work/space/housing.vue

@@ -14,7 +14,21 @@
 							<div style="text-align: center;">{{scope.$index + 1}}</div>
 						</template>
 					</el-table-column>
-					<el-table-column label="项目名称" prop="name">
+					<el-table-column label="房间号" prop="roomNumber"></el-table-column>
+					<el-table-column label="楼宇" prop="projectItemName"></el-table-column>
+					<el-table-column label="楼层" prop="projectItemTargetName"></el-table-column>
+					<el-table-column label="房源面积(m²)" prop="area"></el-table-column>
+					<el-table-column label="招商状态">
+						<template slot-scope="scope">
+							<div v-if="scope.row.investmentState === 0" class="hui-state">
+								<span class="hui-state-bage hui-state-info"></span>
+								<span class="hui-state-label">待招商</span>
+							</div>
+							<div v-else class="hui-state">
+								<span class="hui-state-bage hui-state-primary"></span>
+								<span class="hui-state-label">已招商</span>
+							</div>
+						</template>
 					</el-table-column>
 					<el-table-column label="操作" width="150">
 						<template slot-scope="scope">
@@ -48,7 +62,7 @@
 <script>
 	import {
 		getHouseListByPage,
-		deleteProjectById
+		deleteHouseById
 	} from '@/httpApi/space'
 	import edit from '@/components/work/space/house/edit'
 	import detail from '@/components/work/space/house/detail'
@@ -100,7 +114,7 @@
 			},
 			deleteHouse(val) {
 				this.$confirm('确定要删除该房源?', () => {
-					deleteProjectById(val.id).then(res => {
+					deleteHouseById(val.id).then(res => {
 						if (res.state) {
 							this.init();
 							this.$message.success('操作成功');