From 3e091224ab26252d8624b42b461ba773ee8bee0f Mon Sep 17 00:00:00 2001
From: gaoshp <291585735@qq.com>
Date: 星期日, 03 十一月 2024 19:16:31 +0800
Subject: [PATCH] update

---
 src/components/scFileSelect/index.vue |  577 +++++++++++++++++++++++++++++++++++++-------------------
 1 files changed, 379 insertions(+), 198 deletions(-)

diff --git a/src/components/scFileSelect/index.vue b/src/components/scFileSelect/index.vue
index 224baed..487040e 100644
--- a/src/components/scFileSelect/index.vue
+++ b/src/components/scFileSelect/index.vue
@@ -3,41 +3,47 @@
  * @version: 1.0
  * @Author: sakuya
  * @Date: 2021骞�10鏈�11鏃�16:01:40
- * @LastEditors:
- * @LastEditTime:
+ * @LastEditors: Sneed
+ * @LastEditTime: 2024-06-16 16:16:25
 -->
 
 <template>
 	<div class="sc-file-select">
 		<div class="sc-file-select__side" v-loading="menuLoading">
 			<div class="sc-file-select__side-menu">
-				<el-tree ref="group" class="menu" :data="menu" :node-key="treeProps.key" :props="treeProps" :current-node-key="menu.length>0?menu[0][treeProps.key]:''" highlight-current @node-click="groupClick">
+				<el-tree :expand-on-click-node="false" ref="group" class="menu" :data="menu" :node-key="treeProps.key"
+					:props="treeProps" :current-node-key="menu.length > 0 ? menu[0][treeProps.key] : ''" highlight-current
+					@node-click="groupClick">
 					<template #default="{ node }">
 						<span class="el-tree-node__label">
-							<el-icon class="icon"><el-icon-folder /></el-icon>{{node.label}}
+							<el-icon class="icon"><el-icon-folder /></el-icon>{{ node.label }}
 						</span>
 					</template>
 				</el-tree>
 			</div>
 			<div class="sc-file-select__side-msg" v-if="multiple">
-				宸查�夋嫨 <b>{{value.length}}</b> / <b>{{max}}</b> 椤�
+				宸查�夋嫨 <b>{{ value.length }}</b> / <b>{{ max }}</b> 椤�
 			</div>
 		</div>
 		<div class="sc-file-select__files" v-loading="listLoading">
 			<div class="sc-file-select__top">
 				<div class="upload" v-if="!hideUpload">
-					<el-upload class="sc-file-select__upload" action="" multiple :show-file-list="false" :accept="accept" :on-change="uploadChange" :before-upload="uploadBefore" :on-progress="uploadProcess" :on-success="uploadSuccess" :on-error="uploadError" :http-request="uploadRequest">
+					<el-upload class="sc-file-select__upload" action="" multiple :show-file-list="false"
+						:accept="accept" :on-change="uploadChange" :before-upload="uploadBefore"
+						:on-progress="uploadProcess" :on-success="uploadSuccess" :on-error="uploadError"
+						:http-request="uploadRequest">
 						<el-button type="primary" icon="el-icon-upload">鏈湴涓婁紶</el-button>
 					</el-upload>
-					<span class="tips"><el-icon><el-icon-warning /></el-icon>澶у皬涓嶈秴杩噞{maxSize}}MB</span>
+					<span class="tips"><el-icon><el-icon-warning /></el-icon>澶у皬涓嶈秴杩噞{ maxSize }}MB</span>
 				</div>
 				<div class="keyword">
-					<el-input v-model="keyword" prefix-icon="el-icon-search" placeholder="鏂囦欢鍚嶆悳绱�" clearable @keyup.enter="search" @clear="search"></el-input>
+					<el-input v-model="keyword" prefix-icon="el-icon-search" placeholder="鏂囦欢鍚嶆悳绱�" clearable
+						@keyup.enter="search" @clear="search"></el-input>
 				</div>
 			</div>
 			<div class="sc-file-select__list">
 				<el-scrollbar ref="scrollbar">
-					<el-empty v-if="fileList.length==0 && data.length==0" description="鏃犳暟鎹�" :image-size="80"></el-empty>
+					<el-empty v-if="fileList.length == 0 && data.length == 0" description="鏃犳暟鎹�" :image-size="80"></el-empty>
 					<div v-for="(file, index) in fileList" :key="index" class="sc-file-select__item">
 						<div class="sc-file-select__item__file">
 							<div class="sc-file-select__item__upload">
@@ -45,9 +51,10 @@
 							</div>
 							<el-image :src="file.tempImg" fit="contain"></el-image>
 						</div>
-						<p>{{file.name}}</p>
+						<p>{{ file.name }}</p>
 					</div>
-					<div v-for="item in data" :key="item[fileProps.key]" class="sc-file-select__item" :class="{active: value.includes(item[fileProps.url]) }" @click="select(item)">
+					<div v-for="item in data" :key="item[fileProps.key]" class="sc-file-select__item"
+						:class="{ active: value.includes(item[fileProps.url]) }" @click="select(item)">
 						<div class="sc-file-select__item__file">
 							<div class="sc-file-select__item__checkbox" v-if="multiple">
 								<el-icon><el-icon-check /></el-icon>
@@ -56,228 +63,402 @@
 								<el-icon><el-icon-check /></el-icon>
 							</div>
 							<div class="sc-file-select__item__box"></div>
-							<el-image v-if="_isImg(item[fileProps.url])" :src="item[fileProps.url]" fit="contain" lazy></el-image>
+							<el-image v-if="_isImg(item[fileProps.url])" :src="item[fileProps.url]" fit="contain"
+								lazy></el-image>
 							<div v-else class="item-file item-file-doc">
-								<i v-if="files[_getExt(item[fileProps.url])]" :class="files[_getExt(item[fileProps.url])].icon" :style="{color:files[_getExt(item[fileProps.url])].color}"></i>
+								<i v-if="files[_getExt(item[fileProps.url])]"
+									:class="files[_getExt(item[fileProps.url])].icon"
+									:style="{ color: files[_getExt(item[fileProps.url])].color }"></i>
 								<i v-else class="sc-icon-file-list-fill" style="color: #999;"></i>
 							</div>
 						</div>
-						<p :title="item[fileProps.fileName]">{{item[fileProps.fileName]}}</p>
+						<p :title="item[fileProps.fileName]">{{ item[fileProps.fileName] }}</p>
 					</div>
 				</el-scrollbar>
 			</div>
 			<div class="sc-file-select__pagination">
-				<el-pagination small background layout="prev, pager, next" :total="total" :page-size="pageSize" v-model:currentPage="currentPage" @current-change="reload"></el-pagination>
+				<el-pagination small background layout="prev, pager, next" :total="total" :page-size="pageSize"
+					v-model:currentPage="currentPage" @current-change="reload"></el-pagination>
 			</div>
 			<div class="sc-file-select__do">
 				<slot name="do"></slot>
-				<el-button type="primary" :disabled="value.length<=0" @click="submit">纭� 瀹�</el-button>
+				<el-button type="primary" :disabled="value.length <= 0" @click="submit">纭� 瀹�</el-button>
 			</div>
 		</div>
 	</div>
 </template>
 
 <script>
-	import config from "@/config/fileSelect"
+import config from "@/config/fileSelect"
 
-	export default {
-		props: {
-			modelValue: null,
-			hideUpload: { type: Boolean, default: false },
-			multiple: { type: Boolean, default: false },
-			max: {type: Number, default: config.max},
-			onlyImage: { type: Boolean, default: false },
-			maxSize: {type: Number, default: config.maxSize},
+export default {
+	props: {
+		modelValue: null,
+		hideUpload: { type: Boolean, default: false },
+		multiple: { type: Boolean, default: false },
+		max: { type: Number, default: config.max },
+		onlyImage: { type: Boolean, default: false },
+		maxSize: { type: Number, default: config.maxSize },
+	},
+	data() {
+		return {
+			keyword: null,
+			pageSize: 20,
+			total: 0,
+			currentPage: 1,
+			data: [],
+			menu: [],
+			menuId: '',
+			value: this.multiple ? [] : '',
+			fileList: [],
+			accept: this.onlyImage ? "image/gif, image/jpeg, image/png" : "",
+			listLoading: false,
+			menuLoading: false,
+			treeProps: config.menuProps,
+			fileProps: config.fileProps,
+			files: config.files
+		}
+	},
+	watch: {
+		multiple() {
+			this.value = this.multiple ? [] : ''
+			this.$emit('update:modelValue', JSON.parse(JSON.stringify(this.value)));
+		}
+	},
+	mounted() {
+		this.getMenu()
+		this.getData()
+	},
+	methods: {
+		//鑾峰彇鍒嗙被鏁版嵁
+		async getMenu() {
+			this.menuLoading = true
+			var res = await config.menuApiObj.get()
+			this.menu = res.data
+			this.menuLoading = false
 		},
-		data() {
-			return {
-				keyword: null,
-				pageSize: 20,
-				total: 0,
-				currentPage: 1,
-				data: [],
-				menu: [],
-				menuId: '',
-				value: this.multiple ? [] : '',
-				fileList: [],
-				accept: this.onlyImage ? "image/gif, image/jpeg, image/png" : "",
-				listLoading: false,
-				menuLoading: false,
-				treeProps: config.menuProps,
-				fileProps: config.fileProps,
-				files: config.files
+		//鑾峰彇鍒楄〃鏁版嵁
+		async getData() {
+			this.listLoading = true
+			var reqData = {
+				[config.request.menuKey]: this.menuId,
+				[config.request.page]: this.currentPage,
+				[config.request.pageSize]: this.pageSize,
+				[config.request.keyword]: this.keyword
 			}
-		},
-		watch: {
-			multiple(){
-				this.value = this.multiple ? [] : ''
-				this.$emit('update:modelValue', JSON.parse(JSON.stringify(this.value)));
+			if (this.onlyImage) {
+				reqData.type = 'image'
 			}
+			var res = await config.listApiObj.get(reqData)
+			var parseData = config.listParseData(res)
+			this.data = parseData.rows
+			this.total = parseData.total
+			this.listLoading = false
+			this.$refs.scrollbar.setScrollTop(0)
 		},
-		mounted() {
-			this.getMenu()
+		//鏍戠偣鍑讳簨浠�
+		groupClick(data) {
+			this.menuId = data.id
+			this.currentPage = 1
+			this.keyword = null
 			this.getData()
 		},
-		methods: {
-			//鑾峰彇鍒嗙被鏁版嵁
-			async getMenu(){
-				this.menuLoading = true
-				var res = await config.menuApiObj.get()
-				this.menu = res.data
-				this.menuLoading = false
-			},
-			//鑾峰彇鍒楄〃鏁版嵁
-			async getData(){
-				this.listLoading = true
-				var reqData = {
-					[config.request.menuKey]: this.menuId,
-					[config.request.page]: this.currentPage,
-					[config.request.pageSize]: this.pageSize,
-					[config.request.keyword]: this.keyword
+		//鍒嗛〉鍒锋柊琛ㄦ牸
+		reload() {
+			this.getData()
+		},
+		search() {
+			this.currentPage = 1
+			this.getData()
+		},
+		select(item) {
+			const itemUrl = item[this.fileProps.url]
+			if (this.multiple) {
+				if (this.value.includes(itemUrl)) {
+					this.value.splice(this.value.findIndex(f => f == itemUrl), 1)
+				} else {
+					this.value.push(itemUrl)
 				}
-				if(this.onlyImage){
-					reqData.type = 'image'
+			} else {
+				if (this.value.includes(itemUrl)) {
+					this.value = ''
+				} else {
+					this.value = itemUrl
 				}
-				var res = await config.listApiObj.get(reqData)
-				var parseData = config.listParseData(res)
-				this.data = parseData.rows
-				this.total = parseData.total
-				this.listLoading = false
-				this.$refs.scrollbar.setScrollTop(0)
-			},
-			//鏍戠偣鍑讳簨浠�
-			groupClick(data){
-				this.menuId = data.id
-				this.currentPage = 1
-				this.keyword = null
-				this.getData()
-			},
-			//鍒嗛〉鍒锋柊琛ㄦ牸
-			reload(){
-				this.getData()
-			},
-			search(){
-				this.currentPage = 1
-				this.getData()
-			},
-			select(item){
-				const itemUrl = item[this.fileProps.url]
-				if(this.multiple){
-					if(this.value.includes(itemUrl)){
-						this.value.splice(this.value.findIndex(f => f == itemUrl), 1)
-					}else{
-						this.value.push(itemUrl)
-					}
-				}else{
-					if(this.value.includes(itemUrl)){
-						this.value = ''
-					}else{
-						this.value = itemUrl
-					}
-				}
-			},
-			submit(){
-				const value = JSON.parse(JSON.stringify(this.value))
-				this.$emit('update:modelValue', value);
-				this.$emit('submit', value);
-			},
-			//涓婁紶澶勭悊
-			uploadChange(file, fileList){
-				file.tempImg = URL.createObjectURL(file.raw);
-				this.fileList = fileList
-			},
-			uploadBefore(file){
-				const maxSize = file.size / 1024 / 1024 < this.maxSize;
-				if (!maxSize) {
-					this.$message.warning(`涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃 ${this.maxSize}MB!`);
-					return false;
-				}
-			},
-			uploadRequest(param){
-				var apiObj = config.apiObj;
-				const data = new FormData();
-				data.append("file", param.file);
-				data.append([config.request.menuKey], this.menuId);
-				apiObj.post(data, {
-					onUploadProgress: e => {
-						param.onProgress(e)
-					}
-				}).then(res => {
-					param.onSuccess(res)
-				}).catch(err => {
-					param.onError(err)
-				})
-			},
-			uploadProcess(event, file){
-				file.progress = Number((event.loaded / event.total * 100).toFixed(2))
-			},
-			uploadSuccess(res, file){
-				this.fileList.splice(this.fileList.findIndex(f => f.uid == file.uid), 1)
-				var response = config.uploadParseData(res);
-				this.data.unshift({
-					[this.fileProps.key]: response.id,
-					[this.fileProps.fileName]: response.fileName,
-					[this.fileProps.url]: response.url
-				})
-				if(!this.multiple){
-					this.value = response.url
-				}
-			},
-			uploadError(err){
-				this.$notify.error({
-					title: '涓婁紶鏂囦欢閿欒',
-					message: err
-				})
-			},
-			//鍐呯疆鍑芥暟
-			_isImg(fileUrl){
-				const imgExt = ['.jpg', '.jpeg', '.png', '.gif', '.bmp']
-				const fileExt = fileUrl.substring(fileUrl.lastIndexOf("."))
-				return imgExt.indexOf(fileExt) != -1
-			},
-			_getExt(fileUrl){
-				return fileUrl.substring(fileUrl.lastIndexOf(".") + 1)
 			}
+		},
+		submit() {
+			const value = JSON.parse(JSON.stringify(this.value))
+			this.$emit('update:modelValue', value);
+			this.$emit('submit', value);
+		},
+		//涓婁紶澶勭悊
+		uploadChange(file, fileList) {
+			file.tempImg = URL.createObjectURL(file.raw);
+			this.fileList = fileList
+		},
+		uploadBefore(file) {
+			const maxSize = file.size / 1024 / 1024 < this.maxSize;
+			if (!maxSize) {
+				this.$message.warning(`涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃 ${this.maxSize}MB!`);
+				return false;
+			}
+		},
+		uploadRequest(param) {
+			var apiObj = config.apiObj;
+			const data = new FormData();
+			data.append("file", param.file);
+			data.append([config.request.menuKey], this.menuId);
+			apiObj.post(data, {
+				onUploadProgress: e => {
+					param.onProgress(e)
+				}
+			}).then(res => {
+				param.onSuccess(res)
+			}).catch(err => {
+				param.onError(err)
+			})
+		},
+		uploadProcess(event, file) {
+			file.progress = Number((event.loaded / event.total * 100).toFixed(2))
+		},
+		uploadSuccess(res, file) {
+			this.fileList.splice(this.fileList.findIndex(f => f.uid == file.uid), 1)
+			var response = config.uploadParseData(res);
+			this.data.unshift({
+				[this.fileProps.key]: response.id,
+				[this.fileProps.fileName]: response.fileName,
+				[this.fileProps.url]: response.url
+			})
+			if (!this.multiple) {
+				this.value = response.url
+			}
+		},
+		uploadError(err) {
+			this.$notify.error({
+				title: '涓婁紶鏂囦欢閿欒',
+				message: err
+			})
+		},
+		//鍐呯疆鍑芥暟
+		_isImg(fileUrl) {
+			const imgExt = ['.jpg', '.jpeg', '.png', '.gif', '.bmp']
+			const fileExt = fileUrl.substring(fileUrl.lastIndexOf("."))
+			return imgExt.indexOf(fileExt) != -1
+		},
+		_getExt(fileUrl) {
+			return fileUrl.substring(fileUrl.lastIndexOf(".") + 1)
 		}
 	}
+}
 </script>
 
 <style scoped>
-	.sc-file-select {display: flex;}
-	.sc-file-select__files {flex: 1;}
+.sc-file-select {
+	display: flex;
+}
 
-	.sc-file-select__list {height:400px;}
-	.sc-file-select__item {display: inline-block;float: left;margin:0 15px 25px 0;width:110px;cursor: pointer;}
-	.sc-file-select__item__file {width:110px;height:110px;position: relative;}
-	.sc-file-select__item__file .el-image {width:110px;height:110px;}
-	.sc-file-select__item__box {position: absolute;top:0;right:0;bottom:0;left:0;border: 2px solid var(--el-color-success);z-index: 1;display: none;}
-	.sc-file-select__item__box::before {content: '';position: absolute;top:0;right:0;bottom:0;left:0;background: var(--el-color-success);opacity: 0.2;display: none;}
-	.sc-file-select__item:hover .sc-file-select__item__box {display: block;}
-	.sc-file-select__item.active .sc-file-select__item__box {display: block;}
-	.sc-file-select__item.active .sc-file-select__item__box::before {display: block;}
-	.sc-file-select__item p {margin-top: 10px;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;-webkit-text-overflow:ellipsis;text-align: center;}
-	.sc-file-select__item__checkbox {position: absolute;width: 20px;height: 20px;top:7px;right:7px;z-index: 2;background: rgba(0,0,0,0.2);border: 1px solid #fff;display: flex;flex-direction: column;align-items: center;justify-content: center;}
-	.sc-file-select__item__checkbox i {font-size: 14px;color: #fff;font-weight: bold;display: none;}
-	.sc-file-select__item__select {position: absolute;width: 20px;height: 20px;top:0px;right:0px;z-index: 2;background: var(--el-color-success);display: none;flex-direction: column;align-items: center;justify-content: center;}
-	.sc-file-select__item__select i {font-size: 14px;color: #fff;font-weight: bold;}
-	.sc-file-select__item.active .sc-file-select__item__checkbox {background: var(--el-color-success);}
-	.sc-file-select__item.active .sc-file-select__item__checkbox i {display: block;}
-	.sc-file-select__item.active .sc-file-select__item__select {display: flex;}
-	.sc-file-select__item__file .item-file {width:110px;height:110px;display: flex;flex-direction: column;align-items: center;justify-content: center;}
-	.sc-file-select__item__file .item-file i {font-size: 40px;}
-	.sc-file-select__item__file .item-file.item-file-doc {color: #409eff;}
+.sc-file-select__files {
+	flex: 1;
+}
 
-	.sc-file-select__item__upload {position: absolute;top:0;right:0;bottom:0;left:0;z-index: 1;background: rgba(255,255,255,0.7);display: flex;flex-direction: column;align-items: center;justify-content: center;}
+.sc-file-select__list {
+	height: 400px;
+}
 
-	.sc-file-select__side {width: 200px;margin-right: 15px;border-right: 1px solid rgba(128,128,128,0.2);display: flex;flex-flow: column;}
-	.sc-file-select__side-menu {flex: 1;}
-	.sc-file-select__side-msg {height:32px;line-height: 32px;}
+.sc-file-select__item {
+	display: inline-block;
+	float: left;
+	margin: 0 15px 25px 0;
+	width: 110px;
+	cursor: pointer;
+}
 
-	.sc-file-select__top {margin-bottom: 15px;display: flex;justify-content: space-between;}
-	.sc-file-select__upload {display: inline-block;}
-	.sc-file-select__top .tips {font-size: 12px;margin-left: 10px;color: #999;}
-	.sc-file-select__top .tips i {font-size: 14px;margin-right: 5px;position: relative;bottom: -0.125em;}
-	.sc-file-select__pagination {margin:15px 0;}
+.sc-file-select__item__file {
+	width: 110px;
+	height: 110px;
+	position: relative;
+}
 
-	.sc-file-select__do {text-align: right;}
+.sc-file-select__item__file .el-image {
+	width: 110px;
+	height: 110px;
+}
+
+.sc-file-select__item__box {
+	position: absolute;
+	top: 0;
+	right: 0;
+	bottom: 0;
+	left: 0;
+	border: 2px solid var(--el-color-success);
+	z-index: 1;
+	display: none;
+}
+
+.sc-file-select__item__box::before {
+	content: '';
+	position: absolute;
+	top: 0;
+	right: 0;
+	bottom: 0;
+	left: 0;
+	background: var(--el-color-success);
+	opacity: 0.2;
+	display: none;
+}
+
+.sc-file-select__item:hover .sc-file-select__item__box {
+	display: block;
+}
+
+.sc-file-select__item.active .sc-file-select__item__box {
+	display: block;
+}
+
+.sc-file-select__item.active .sc-file-select__item__box::before {
+	display: block;
+}
+
+.sc-file-select__item p {
+	margin-top: 10px;
+	white-space: nowrap;
+	text-overflow: ellipsis;
+	overflow: hidden;
+	-webkit-text-overflow: ellipsis;
+	text-align: center;
+}
+
+.sc-file-select__item__checkbox {
+	position: absolute;
+	width: 20px;
+	height: 20px;
+	top: 7px;
+	right: 7px;
+	z-index: 2;
+	background: rgba(0, 0, 0, 0.2);
+	border: 1px solid #fff;
+	display: flex;
+	flex-direction: column;
+	align-items: center;
+	justify-content: center;
+}
+
+.sc-file-select__item__checkbox i {
+	font-size: 14px;
+	color: #fff;
+	font-weight: bold;
+	display: none;
+}
+
+.sc-file-select__item__select {
+	position: absolute;
+	width: 20px;
+	height: 20px;
+	top: 0px;
+	right: 0px;
+	z-index: 2;
+	background: var(--el-color-success);
+	display: none;
+	flex-direction: column;
+	align-items: center;
+	justify-content: center;
+}
+
+.sc-file-select__item__select i {
+	font-size: 14px;
+	color: #fff;
+	font-weight: bold;
+}
+
+.sc-file-select__item.active .sc-file-select__item__checkbox {
+	background: var(--el-color-success);
+}
+
+.sc-file-select__item.active .sc-file-select__item__checkbox i {
+	display: block;
+}
+
+.sc-file-select__item.active .sc-file-select__item__select {
+	display: flex;
+}
+
+.sc-file-select__item__file .item-file {
+	width: 110px;
+	height: 110px;
+	display: flex;
+	flex-direction: column;
+	align-items: center;
+	justify-content: center;
+}
+
+.sc-file-select__item__file .item-file i {
+	font-size: 40px;
+}
+
+.sc-file-select__item__file .item-file.item-file-doc {
+	color: #409eff;
+}
+
+.sc-file-select__item__upload {
+	position: absolute;
+	top: 0;
+	right: 0;
+	bottom: 0;
+	left: 0;
+	z-index: 1;
+	background: rgba(255, 255, 255, 0.7);
+	display: flex;
+	flex-direction: column;
+	align-items: center;
+	justify-content: center;
+}
+
+.sc-file-select__side {
+	width: 200px;
+	margin-right: 15px;
+	border-right: 1px solid rgba(128, 128, 128, 0.2);
+	display: flex;
+	flex-flow: column;
+}
+
+.sc-file-select__side-menu {
+	flex: 1;
+}
+
+.sc-file-select__side-msg {
+	height: 32px;
+	line-height: 32px;
+}
+
+.sc-file-select__top {
+	margin-bottom: 15px;
+	display: flex;
+	justify-content: space-between;
+}
+
+.sc-file-select__upload {
+	display: inline-block;
+}
+
+.sc-file-select__top .tips {
+	font-size: 12px;
+	margin-left: 10px;
+	color: #999;
+}
+
+.sc-file-select__top .tips i {
+	font-size: 14px;
+	margin-right: 5px;
+	position: relative;
+	bottom: -0.125em;
+}
+
+.sc-file-select__pagination {
+	margin: 15px 0;
+}
+
+.sc-file-select__do {
+	text-align: right;
+}
 </style>

--
Gitblit v1.9.3