From 9c094a1fe3e1ae3dadef6433f8401818fe2b8304 Mon Sep 17 00:00:00 2001
From: lzhe <lzhe@example.com>
Date: 星期五, 21 六月 2024 10:53:43 +0800
Subject: [PATCH] 1

---
 src/views/console/workstation/index.vue |  529 +++++++++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 431 insertions(+), 98 deletions(-)

diff --git a/src/views/console/workstation/index.vue b/src/views/console/workstation/index.vue
index d113566..3d2d445 100644
--- a/src/views/console/workstation/index.vue
+++ b/src/views/console/workstation/index.vue
@@ -7,65 +7,236 @@
 						<el-aside width="200px" v-loading="showGrouploading">
 							<el-container>
 								<el-main class="nopadding">
-									<el-tree ref="group" class="menu" node-key="id" :data="group" :current-node-key="''"
-										:highlight-current="true" :expand-on-click-node="false"
-										:default-expanded-keys="[1]" :filter-node-method="groupFilterNode"
-										@node-click="groupClick"></el-tree>
+									<el-tree :expand-on-click-node="false" ref="group" class="menu" node-key="id"
+										:data="group" :current-node-key="treeCheckKey" :highlight-current="true"
+										:check-on-click-node="true" :default-expanded-keys="[1]"
+										:render-content="renderContent" @node-click="groupClick1"></el-tree>
 								</el-main>
 							</el-container>
 						</el-aside>
 						<el-container>
 							<el-header>
 								<div class="left-panel">
-									<el-button type="primary" icon="el-icon-plus"></el-button>
-									<el-button type="danger" plain icon="el-icon-delete"></el-button>
-									<el-button type="primary" plain>瀵煎叆</el-button>
-									<el-button type="primary" plain>鎵归噺鎿嶄綔</el-button>
+									<el-button @click="table_add" type="primary" icon="el-icon-plus"></el-button>
+									<el-button type="danger" plain icon="el-icon-delete" @click="batchDel"></el-button>
+									<!-- <el-button type="primary" plain>瀵煎叆</el-button>
+									<el-button type="primary" plain>鎵归噺鎿嶄綔</el-button> -->
 								</div>
 								<div class="right-panel">
 									<div class="right-panel-search">
-										<el-select v-model="value" placeholder="Select" style="width: 240px">
-											<el-option v-for="item in options" :key="item.value" :label="item.label"
+										<span>绫诲瀷</span>
+										<el-select v-model="type" style="width: 240px" clearable>
+											<el-option v-for="item in types" :key="item.value" :label="item.label"
 												:value="item.value" />
 										</el-select>
-										<el-select v-model="value" placeholder="Select" style="width: 240px">
-											<el-option v-for="item in options" :key="item.value" :label="item.label"
+										<span>鐘舵��</span>
+										<el-select v-model="statu" style="width: 240px" clearable>
+											<el-option v-for="item in status" :key="item.value" :label="item.label"
 												:value="item.value" />
 										</el-select>
-										<el-input style="width: 240px" placeholder="璇疯緭鍏ュ伐浣嶅悕绉�/缂栧彿" clearable></el-input>
-										<el-button type="primary" icon="el-icon-search"></el-button>
+										<el-input v-model="keyWord" style="width: 240px" placeholder="璇疯緭鍏ュ伐浣嶅悕绉�/缂栧彿"
+											clearable></el-input>
+										<el-button @click="search" type="primary" icon="el-icon-search"></el-button>
 									</div>
 								</div>
 							</el-header>
 							<el-main class="nopadding">
-								<scTable ref="table" :apiObj="apiObj" @selection-change="selectionChange" stripe
-									remoteSort remoteFilter>
-									<el-table-column type="selection" width="50"></el-table-column>
-									<el-table-column label="宸ヤ綅缂栧彿" prop="id" width="120"
-										sortable='custom'></el-table-column>
-									<el-table-column label="宸ヤ綅鍚嶇О" prop="id" width="120"
-										sortable='custom'></el-table-column>
-									<el-table-column label="宸ヤ綅绫诲瀷" prop="id" width="120"
-										sortable='custom'></el-table-column>
-									<el-table-column label="宸ヤ綅鏃ュ巻" prop="id" width="120"
-										sortable='custom'></el-table-column>
-									<el-table-column label="鎿嶄綔" fixed="right" align="right" width="160">
-										<template #default="scope">
-											<el-button-group>
-												<el-button text type="primary" size="small"
-													@click="table_show(scope.row, scope.$index)">鏌ョ湅</el-button>
-												<el-button text type="primary" size="small"
-													@click="table_edit(scope.row, scope.$index)">缂栬緫</el-button>
-												<el-popconfirm title="纭畾鍒犻櫎鍚楋紵"
-													@confirm="table_del(scope.row, scope.$index)">
+								<div style="display: flex">
+									<scTable highlight-current-row @dataChange="dataChange" @row-click="rowClick"
+										ref="table" :params="params" :apiObj="apiObj"
+										@selection-change="selectionChange" stripe>
+										<el-table-column type="selection" width="50"></el-table-column>
+										<el-table-column label="宸ヤ綅缂栧彿" prop="code" width="120"></el-table-column>
+										<el-table-column label="宸ヤ綅鍚嶇О" prop="name" width="120"></el-table-column>
+										<el-table-column label="宸ヤ綅绫诲瀷" prop="type" width="120"></el-table-column>
+										<el-table-column label="宸ヤ綅鏃ュ巻" prop="calendarName" width="120"></el-table-column>
+										<el-table-column label="鎿嶄綔" fixed="right" align="right" width="160">
+											<template #default="scope">
+												<el-button-group>
+													<el-button text type="primary" size="small"
+														@click="table_edit(scope.row, scope.$index)">缂栬緫</el-button>
+													<el-popconfirm title="纭畾鍒犻櫎鍚楋紵"
+														@confirm="table_del(scope.row, scope.$index, '0')">
+														<template #reference>
+															<el-button text type="primary" size="small">鍒犻櫎</el-button>
+														</template>
+													</el-popconfirm>
+													<!-- <el-popconfirm title="纭畾鍋滅敤鍚楋紵"
+													@confirm="table_del(scope.row, scope.$index,'1')">
 													<template #reference>
-														<el-button text type="primary" size="small">鍒犻櫎</el-button>
+														<el-button text type="primary" size="small">鍋滅敤</el-button>
 													</template>
-												</el-popconfirm>
-											</el-button-group>
-										</template>
-									</el-table-column>
-								</scTable>
+												</el-popconfirm> -->
+												</el-button-group>
+											</template>
+										</el-table-column>
+									</scTable>
+									<div style="margin-left: 14px" v-if="Object.keys(previewData).length > 0">
+										<div class="header">
+											<p class="preview-title">宸ヤ綅淇℃伅</p>
+											<div class="preview-content">
+												<div class="img">
+													<img v-if="!previewData.avatar" :src="machinePng" alt="">
+													<scUpload v-else disabled v-model="previewData.avatar" title="宸ヤ綅鍥剧墖">
+													</scUpload>
+												</div>
+												<ul>
+													<li>宸ヤ綅缂栧彿 {{ previewData.code }}</li>
+													<li>宸ヤ綅缁� {{ previewData.groupName }}</li>
+													<li>宸ヤ綅鍚嶇О {{ previewData.name }}</li>
+													<li>宸ヤ綅绫诲瀷 {{ types.find(v => v.value == previewData.type)?.label }}
+													</li>
+													<li>宸ヤ綅鏃ュ巻 {{ previewData.calendarName }}</li>
+													<li>鐘舵�� {{ previewData.status ? '鍚敤' : '绂佺敤' }}</li>
+												</ul>
+											</div>
+											<el-tabs tab-position="top" class="custom-tabs" v-model="normal">
+												<el-tab-pane label="鏈哄櫒淇℃伅" name="1">
+													<el-container>
+														<el-header>鍩虹鏁版嵁</el-header>
+														<el-main>
+															<el-row>
+																<el-col :span="4">
+																	鏈哄櫒缂栧彿
+																</el-col>
+																<el-col :span="8">
+																	{{ basic.machineCode }}
+																</el-col>
+																<el-col :span="4">
+																	鏈哄櫒鍚嶇О
+																</el-col>
+																<el-col :span="8">
+																	{{ basic.machineName }}
+																</el-col>
+																<el-col :span="4">
+																	鏈哄櫒鍝佺墝
+																</el-col>
+																<el-col :span="8">
+																	{{ basic.machineBrand }}
+																</el-col>
+																<el-col :span="4">
+																	椹卞姩鍚嶇О
+																</el-col>
+																<el-col :span="8">
+																	{{ basic.typeName }}
+																</el-col>
+															</el-row>
+														</el-main>
+													</el-container>
+													<el-container>
+														<el-header>
+															<span>閲囬泦淇℃伅</span>
+															<el-button @click="editFlag = !editFlag"
+																style="margin-left: auto;" text type="primary"
+																size="small">閰嶇疆宸ヤ綅閲囬泦</el-button>
+															<el-button v-show="editFlag" @click="saveInfo" text
+																type="primary" size="small">淇濆瓨</el-button>
+															<el-button text type="primary"
+																size="small">淇敼DMP閰嶇疆</el-button>
+														</el-header>
+														<el-main>
+															<el-table :data="list" height="200px">
+																<el-table-column label="閲囬泦鍙橀噺鍚嶇О" prop="name"
+																	width="120" />
+																<el-table-column label="宸ヤ綅鍙橀噺鍚嶇О" prop="dataItem"
+																	width="120">
+																	<template #default="scope">
+																		<el-input :disabled="!editFlag"
+																			v-model="scope.row.dataItem"></el-input>
+																	</template>
+																</el-table-column>
+																<el-table-column label="鏁版嵁鏍囩" prop="description"
+																	width="150">
+																	<template #default="scope">
+																		<el-select :disabled="!editFlag"
+																			v-model="scope.row.description">
+																			<el-option
+																				v-for="item in workstation_param_type"
+																				:key="item.dictKey"
+																				:label="item.dictValue"
+																				:value="item.dictKey - 0" />
+																		</el-select>
+																		<!-- {{ dmp_data_type.find(v => v.dictKey == scope.row.wcsDataType)?.dictValue }} -->
+																	</template>
+																</el-table-column>
+																<el-table-column label="鏁版嵁绫诲埆" prop="wcsDataType"
+																	width="150">
+																	<template #default="scope">
+																		<el-select disabled
+																			v-model="scope.row.wcsDataType">
+																			<el-option v-for="item in dmp_data_type"
+																				:key="item.dictKey"
+																				:label="item.dictValue"
+																				:value="item.dictKey - 0" />
+																		</el-select>
+																		<!-- {{ dmp_data_type.find(v => v.dictKey == scope.row.wcsDataType)?.dictValue }} -->
+																	</template>
+																</el-table-column>
+																<el-table-column label="澶у睆" prop="bigScreen">
+																	<template #default="scope">
+																		<el-checkbox :disabled="!editFlag"
+																			v-model="scope.row.bigScreen" />
+																	</template>
+																</el-table-column>
+																<el-table-column label="瀹炴椂鏁版嵁" prop="realTimeData">
+																	<template #default="scope">
+																		<el-checkbox :disabled="!editFlag"
+																			v-model="scope.row.realTimeData" />
+																	</template>
+																</el-table-column>
+																<el-table-column label="杩囩▼鍙傛暟" prop="processParameter">
+																	<template #default="scope">
+																		<el-checkbox :disabled="!editFlag"
+																			v-model="scope.row.processParameter" />
+																	</template>
+																</el-table-column>
+															</el-table>
+														</el-main>
+													</el-container>
+												</el-tab-pane>
+												<el-tab-pane label="鎵╁睍淇℃伅" name="2">
+													<el-row>
+														<el-col :span="4">
+															宸ョ
+														</el-col>
+														<el-col :span="8">
+															{{ info.deviceType }}
+														</el-col>
+														<el-col :span="4">
+															鍔犲伐灞炴��
+														</el-col>
+														<el-col :span="8">
+															{{ info.properties }}
+														</el-col>
+														<el-col :span="4">
+															绋嬪簭浼犺緭鏂瑰紡
+														</el-col>
+														<el-col :span="8">
+															{{ info.transmissionMode }}
+														</el-col>
+														<el-col :span="4">
+															FTP鐩綍
+														</el-col>
+														<el-col :span="8">
+															{{ info.ftpCatalogue }}
+														</el-col>
+														<el-col :span="4">
+															宸ヤ綔鍙�
+														</el-col>
+														<el-col :span="8">
+															<ul class="workbench">
+																<li v-for="item in workbenchVOList" :key="item.sort">
+																	{{ `銆�${item.sort}銆慲 }}{{ item.name }}
+																</li>
+															</ul>
+														</el-col>
+													</el-row>
+												</el-tab-pane>
+											</el-tabs>
+										</div>
+									</div>
+								</div>
+
 							</el-main>
 						</el-container>
 					</el-container>
@@ -77,23 +248,17 @@
 							<el-container>
 								<el-main class="nopadding">
 									<el-tree ref="group" class="menu" node-key="id" :data="group"
-										:current-node-key="treeCheckKey" 
-										:highlight-current="true"
-										:expand-on-click-node="false" 
-										:check-on-click-node="true"
-										:default-expanded-keys="[1]"
-										:render-content="renderContent"
-										:filter-node-method="groupFilterNode"
+										:current-node-key="treeCheckKey" :highlight-current="true"
+										:expand-on-click-node="false" :check-on-click-node="true"
+										:default-expanded-keys="[1]" :render-content="renderContent"
 										@node-click="groupClick"></el-tree>
 								</el-main>
 							</el-container>
 						</el-aside>
 						<el-container>
 							<el-main class="" v-show="addGroupShow">
-								<el-form
-									v-show="treeCheckedNode.id == 1"
-									:model="form" :rules="rules" ref="dialogForm" label-width="200px"
-									label-position="left">
+								<el-form v-show="treeCheckedNode.id == 1" :model="form" :rules="rules" ref="dialogForm"
+									label-width="200px" label-position="left">
 									<el-form-item label="浜х嚎鏍囩" prop="groupTag">
 										<el-select v-model="form.groupTag" clearable placeholder="浜х嚎鏍囩"
 											style="width: 240px">
@@ -113,7 +278,8 @@
 											placeholder="澶囨敞"></el-input>
 									</el-form-item>
 								</el-form>
-								<el-form v-show="group_tag.map(item => item.dictKey).includes(treeCheckedNode.groupTag) || beltline_type.map(item => item.dictKey).includes(treeCheckedNode.groupTag) || treeCheckedNode.id == 101"
+								<el-form
+									v-show="group_tag.map(item => item.dictKey).includes(treeCheckedNode.groupTag) || beltline_type.map(item => item.dictKey).includes(treeCheckedNode.groupTag) || treeCheckedNode.id == 101"
 									:model="form" :rules="rules" ref="dialogForm" label-width="200px"
 									label-position="left">
 									<el-form-item label="宸ヤ綅缁勬爣绛�" prop="groupTag">
@@ -139,7 +305,8 @@
 							<el-header v-show="!addGroupShow">
 								<div class="left-panel">
 									<el-button @click="addChild" type="primary" plain>鏂板涓嬬骇</el-button>
-									<el-button @click="deleteWorkGroup" v-show="!['1', '101'].includes(treeCheckedNode.id)" type="danger"
+									<el-button @click="deleteWorkGroup"
+										v-show="!['1', '101'].includes(treeCheckedNode.id)" type="danger"
 										plain>鍒犻櫎</el-button>
 								</div>
 							</el-header>
@@ -205,20 +372,54 @@
 
 			</el-tabs>
 		</el-card>
+		<Dialog ref="dialog" @success="success" :option="{ types, status, group }"></Dialog>
 	</el-main>
 </template>
 
 <script>
 import pmsPng from '@/assets/pms.png'
+import Dialog from './Dialog.vue'
+import machinePng from '@/assets/machine.png'
 export default {
 	name: 'system',
+	components: {
+		Dialog
+	},
 	data() {
 		return {
+			machinePng,
 			showGrouploading: false,
 			options: [],
-			activeName: '2',
+			activeName: '1',
+			normal: '1',
 			group: [],
 			groupFilterText: '',
+			apiObj: '',
+			params: {},
+			keyWord: '',
+			type: '',
+			statu: 1,
+			types: [
+				{
+					label: '鏈哄櫒',
+					value: 0
+				},
+				{
+					label: '浜哄伐',
+					value: 1
+				},
+			],
+			status: [
+				{
+					label: '鍚敤',
+					value: 1
+				},
+				{
+					label: '鍋滅敤',
+					value: 0
+				}
+			],
+			previewData: {},
 			// --------
 			form: {
 				groupTag: '',
@@ -235,12 +436,45 @@
 			treeCheckKey: [],
 			beltline_type: [],
 			group_tag: [],
-			addGroupShow: false
+			dmp_data_type: [],
+			workstation_param_type: [],
+			addGroupShow: false,
+			selection: [],
+			list: [],
+			basic: {
+				machineCode: '-',
+				machineName: '-',
+				machineBrand: '-',
+				typeName: '-',
+			},
+			info: {
+				deviceType: '-',
+				properties: '-',
+				transmissionMode: '-',
+				ftpCatalogue: '-',
+			},
+			workbenchVOList: [],
+			editFlag: false
 		}
 	},
 	watch: {
-		activeName() {
-			this.queryList()
+		activeName: {
+			handler(val) {
+				this.queryList().then(() => {
+					if (val == 1) {
+						console.log('>>>>>>>>>>>>>>', this.treeCheckedNode)
+						this.apiObj = this.$API.workstation.getList
+						this.params = {
+							groupId: this.treeCheckedNode.id,
+							keyWord: '',
+							status: 1,
+							type: ''
+						}
+						this.groupClick1(this.treeCheckedNode)
+					}
+				})
+			},
+			immediate: true
 		},
 		treeCheckedNode: {
 			handler(val) {
@@ -257,16 +491,15 @@
 		this.queryList()
 	},
 	methods: {
-		renderContent (h, {node,data}) {
-			console.log(node,data)
+		renderContent(h, { data }) {
 			let img = data.groupTag == 'fms_beltline'
-			return h('span',{
+			return h('span', {
 
 			},
-			img ? h('img', {
-				src: pmsPng
-			}, '') : '',
-			data.name)
+				img ? h('img', {
+					src: pmsPng
+				}, '') : '',
+				data.name)
 		},
 		init() {
 			this.$API.system.dic.getDic.get({ code: 'beltline_type' }).then(res => {
@@ -275,12 +508,27 @@
 			this.$API.system.dic.getDic.get({ code: 'group_tag' }).then(res => {
 				this.group_tag = res.data
 			})
+			this.$API.system.dic.getDic.get({ code: 'dmp_data_type' }).then(res => {
+				this.dmp_data_type = res.data
+			})
+			this.$API.system.dic.getDic.get({ code: 'workstation_param_type' }).then(res => {
+				this.workstation_param_type = res.data
+			})
 
 		},
-		queryList(flag) {
+		success() {
+			this.search()
+		},
+		async queryList(flag) {
 			this.showGrouploading = true
-			this.$API.basicdata.getWorkstationGroup.get().then(res => {
+			this.treeCheckedNode = {}
+			this.treeCheckKey = ''
+			return this.$API.workstation.getWorkstationGroup.get().then(res => {
 				if (res.code == 200) {
+					let data = this.formatData(res.data)
+					this.group = data
+					this.showGrouploading = false
+					// this.$nextTick(() => {
 					if (!flag) {
 						let parent = res.data.filter(item => item.parentId == 0)[0]
 						this.treeCheckedNode = parent
@@ -290,10 +538,8 @@
 						this.treeCheckedNode = parent
 						this.treeCheckKey = parent.id
 					}
-					
-					let data = this.formatData(res.data)
-					this.group = data
-					this.showGrouploading = false
+					// })
+
 				}
 			})
 		},
@@ -319,8 +565,8 @@
 			return newData
 		},
 		async saveWorkstationGroup() {
-			const validate = await this.$refs.dialogForm.validate().catch(()=>{})
-			if(!validate){ return false }
+			const validate = await this.$refs.dialogForm.validate().catch(() => { })
+			if (!validate) { return false }
 			if (this.addGroupShow) {
 				let data = Object.assign({
 					code: "",
@@ -330,62 +576,149 @@
 					status: 1,
 					groupType: this.treeCheckedNode.groupType,
 					groupCategory: this.treeCheckedNode.groupCategory
-				},this.form)
-				return this.$API.basicdata.saveWorkstationGroup.post(data).then(res => {
+				}, this.form)
+				return this.$API.workstation.saveWorkstationGroup.post(data).then(res => {
 					console.log(res)
 					this.queryList(true)
 				})
 			}
-			let data = Object.assign({},this.treeCheckedNode,this.form)
-			this.$API.basicdata.saveWorkstationGroup.put(data).then(res => {
+			let data = Object.assign({}, this.treeCheckedNode, this.form)
+			this.$API.workstation.saveWorkstationGroup.put(data).then(res => {
 				console.log(res)
 				this.queryList(true)
 			})
 		},
-		deleteWorkGroup () {
-			this.$API.basicdata.deleteWorkGroup.delete({
+		deleteWorkGroup() {
+			this.$API.workstation.deleteWorkGroup.delete({
 				groupId: this.treeCheckedNode.id
 			}).then(() => {
 				this.queryList()
 			})
 		},
-		addChild () {
+		addChild() {
 			this.addGroupShow = true
 			this.$refs.dialogForm.resetFields()
 		},
-		groupFilterNode() {
-
-		},
 		groupClick(node) {
-			console.log(node)
 			this.treeCheckedNode = node
 		},
-		table_add() {
-			var newRow = {
-				key: "",
-				value: "",
-				title: "",
-				isSet: true
+		search() {
+			this.groupClick1(this.treeCheckedNode)
+		},
+		rowClick(data) {
+			this.previewData = data
+			console.log(data, '>>>>>>>>>>>')
+			if (!data.id) {
+				Object.keys(this.basic).forEach(key => {
+					this.basic[key] = '-'
+				})
+				Object.keys(this.info).forEach(key => {
+					this.info[key] = '-'
+				})
+				this.list = []
+				this.workbenchVOList = []
+				return
 			}
-			this.setting.push(newRow)
+			this.$HTTP.get(`/api/blade-cps/workstation/listDmpVariablesByWorkstationId?workstationId=${data.id}`).then(res => {
+				this.list = res?.data?.dmpVariablesVOList
+				Object.keys(this.basic).forEach(key => {
+					this.basic[key] = res?.data?.[key] || '-'
+				})
+			})
+			this.$HTTP.get(`/api/blade-cps/workstation-workbench/listWorkbench?workstationId=${data.id}`).then(res => {
+				Object.keys(this.info).forEach(key => {
+					this.info[key] = res?.data?.[key] || '-'
+				})
+				this.workbenchVOList = res?.data?.workstationList || []
+			})
+		},
+		groupClick1(data) {
+			console.log('-------', data)
+			var params = {
+				groupId: data.id,
+				keyWord: this.keyWord,
+				status: this.statu,
+				type: this.type,
+			}
+			this.$refs.table.reload(params)
+
+		},
+		dataChange(res, data) {
+
+			if (data.length > 0) {
+				console.log(data[0], '>>>>>>>>')
+				this.$refs.table.setCurrentRow(data[0])
+				this.previewData = data[0]
+				this.rowClick(data[0])
+			} else {
+				this.$refs.table.setCurrentRow()
+				this.previewData = {}
+				this.rowClick({})
+			}
+		},
+		table_add() {
+			this.$refs.dialog.open()
 		},
 		table_edit(row) {
-			if (row.isSet) {
-				row.isSet = false
-			} else {
-				row.isSet = true
-			}
+			this.$refs.dialog.open('edit', row)
 		},
-		table_del(row, index) {
-			this.setting.splice(index, 1)
+		table_del(row, index, type) {
+			this.$HTTP.delete(`/api/blade-cps/workstation?type=0&workstationIds=${row.id}`).then(res => {
+				this.search()
+			})
+		},
+		selectionChange(selection) {
+			this.selection = selection
+		},
+		batchDel() {
+			this.$HTTP.delete(`/api/blade-cps/workstation?type=0&workstationIds=${this.selection.map(item => item.id).join(',')}`).then(res => {
+				this.search()
+			})
+		},
+		saveInfo() {
+			this.$HTTP.post('/api/blade-cps/workstation-wcs/save', this.workbenchVOList).then(res => {
+				this.editFlag = false
+			})
 		},
 	}
 }
 </script>
 
-<style scoped>
+<style lang="scss" scoped>
 .show-info {
 	list-style: none;
 	font-size: 14px;
 }
+
+.preview-title {
+	padding: 12px;
+	margin-bottom: 14px;
+	font-size: 16px;
+}
+
+.preview-content {
+	font-size: 14px;
+	display: flex;
+	align-items: center;
+
+	.img {
+		width: 30%;
+	}
+
+	ul {
+		list-style: none;
+		display: flex;
+		flex-wrap: wrap;
+
+		li {
+			width: 50%;
+			flex: 1 0 auto;
+			margin-bottom: 10px;
+		}
+	}
+}
+
+.workbench {
+	list-style: none;
+}
 </style>

--
Gitblit v1.9.3