Browse Source

[新增]消防力量采集基础功能完成

dev
邵佳豪 4 years ago
parent
commit
0dc8f985b6
  1. 75
      src/app/data-collection/fire-force/fire-force.component.html
  2. 227
      src/app/data-collection/fire-force/fire-force.component.scss
  3. 247
      src/app/data-collection/fire-force/fire-force.component.ts
  4. BIN
      src/assets/images/pdf.jpg
  5. BIN
      src/assets/images/txt.jpg
  6. BIN
      src/assets/images/vedio.jpg
  7. BIN
      src/assets/images/word.jpg

75
src/app/data-collection/fire-force/fire-force.component.html

@ -6,6 +6,7 @@
<mat-slide-toggle color="primary" (change)='slideChange($event)' checked labelPosition='before'>列表过滤</mat-slide-toggle>
</div>
<div>
<button (click)="reset()" style="width: 68px;margin-right: 12px;" mat-flat-button color="primary">重置</button>
<button (click)="addFireForce()" style="width: 68px;" mat-flat-button color="primary">新增</button>
</div>
</div>
@ -36,7 +37,7 @@
<span>消防队</span>
<span>完整度</span>
</div>
<div class="fireForceTree" id="fireForceTree">
<div class="fireForceTree" id="fireForceTree" *ngIf="isTreeView">
<mat-tree [dataSource]="dataSource" [treeControl]="treeControl" >
<mat-tree-node (click)="selectTreeNode(node)" [ngClass]="{'selectedTreeNode': node.id == selectedFireForceId}" *matTreeNodeDef="let node;" matTreeNodePadding matTreeNodePaddingIndent='10px'>
@ -44,7 +45,11 @@
<span class="nodename">{{node.name}}</span>
<div class="integrity">
<span class="integrityNum">
{{node.fireForceDetailInfo ? accMul(node.fireForceDetailInfo.integrityScore.toFixed(3),100,1) : 0}}%
</span>
<div class="integrityColorDiv" [style]="integrity(node.fireForceDetailInfo ? (node.fireForceDetailInfo.integrityScore.toFixed(2) * 100).toFixed(): 0)">
</div>
</div>
<div class="deletebtn" (click)="deleteFireForce(node,$event)"><mat-icon>highlight_off</mat-icon></div>
</mat-tree-node>
@ -60,11 +65,30 @@
</button>
<span class="nodename">{{node.name}}</span>
<div class="integrity">
<span class="integrityNum">
{{node.fireForceDetailInfo ? accMul(node.fireForceDetailInfo.integrityScore.toFixed(3),100,1) : 0}}%
</span>
<div class="integrityColorDiv" [style]="integrity(node.fireForceDetailInfo ? (node.fireForceDetailInfo.integrityScore.toFixed(2) * 100).toFixed(): 0)">
</div>
</div>
<div class="deletebtn" (click)="deleteFireForce(node,$event)"><mat-icon>highlight_off</mat-icon></div>
</mat-tree-node>
</mat-tree>
</mat-tree>
</div>
<div class="fireForceList" *ngIf="!isTreeView">
<ul>
<li [ngClass]="{'selectedLi': item.id == selectedFireForceId}" *ngFor="let item of allFireForceList;let key = index" (click)="selectTreeNode(item)">
<div class="name" [title]="item.name">{{item.name}}</div>
<div class="integrity">
<span class="integrityNum">
{{item.fireForceDetailInfo ? accMul(item.fireForceDetailInfo.integrityScore.toFixed(3),100,1) : 0}}%
</span>
<div class="integrityColorDiv" [style]="integrity(item.fireForceDetailInfo ? (item.fireForceDetailInfo.integrityScore.toFixed(2) * 100).toFixed(): 0)">
</div>
</div>
<div class="deletebtn" (click)="deleteFireForce(item,$event)"><mat-icon>highlight_off</mat-icon></div>
</li>
</ul>
</div>
</div>
</div>
@ -82,6 +106,10 @@
</div>
</div>
<div class="detailsbox" *ngIf="selectedFireForceLevel != null">
<div class="masklayer" *ngIf="isMasklayer">
<mat-spinner [diameter]='30'></mat-spinner>
<span>上传中...</span>
</div>
<div class="tabsbox">
<div class="tabs">
<div (click)="selectedTab(1)" [ngClass]="{'selectedBtn': tabIndex == 1}">
@ -95,10 +123,16 @@
</div>
</div>
<div class="btnbox">
<button class="uploadAttachment" *ngIf="tabIndex == 3" mat-flat-button color="primary">
<mat-icon>attach_file</mat-icon>
上传附件
</button>
<div class="uploadAttachment" *ngIf="tabIndex == 3">
<button mat-flat-button color="primary">
<mat-icon>attach_file</mat-icon>
上传附件
</button>
<a href="javascript:;" class="a-upload">
<input type="file" (change)='uploadAttachment($event)'>
</a>
</div>
<span class="save" (click)="save()"><mat-icon>save</mat-icon>保存</span>
<span class="submitAudit"><mat-icon>open_in_browser</mat-icon>提交审核</span>
</div>
@ -513,8 +547,31 @@
</div> -->
<!-- 相关资料 -->
<div class="contant" *ngIf="tabIndex == 3">
相关资料
<div class="fileDivBox" *ngFor="let item of AttachmentArr" >
<mat-icon class="deleteFile" (click)="deleteFile(item,$event)">highlight_off</mat-icon>
<div class="imgbox">
<img *ngIf="item.fileName.split('.')[item.fileName.split('.').length-1] == 'png'
|| item.fileName.split('.')[item.fileName.split('.').length-1] == 'jpg'"
class="thumbnailImg" src="/api/Objects/PlanPlatform/{{item.objectName}}" alt="">
<img *ngIf="item.fileName.split('.')[item.fileName.split('.').length-1] == 'docx'
|| item.fileName.split('.')[item.fileName.split('.').length-1] == 'doc'"
class="thumbnailImg" src="/assets/images/word.jpg" alt="">
<img *ngIf="item.fileName.split('.')[item.fileName.split('.').length-1] == 'pdf'"
class="thumbnailImg" src="/assets/images/pdf.jpg" alt="">
<img *ngIf="item.fileName.split('.')[item.fileName.split('.').length-1] == 'txt'"
class="thumbnailImg" src="/assets/images/txt.jpg" alt="">
<img *ngIf="item.fileName.split('.')[item.fileName.split('.').length-1] == 'mp4'"
class="thumbnailImg" src="/assets/images/vedio.jpg" alt="">
</div>
<span [title]="item.fileName">{{item.fileName}}</span>
<button (click)="clickFile(item)" class="btn btn1" mat-flat-button color="primary">查看</button>
<button class="btn btn2" mat-flat-button color="primary">下载</button>
</div>
</div>
</div>
</div>
</div>
<div id="viewerjs" style="display:none">
</div>

227
src/app/data-collection/fire-force/fire-force.component.scss

@ -91,8 +91,20 @@
.integrity{
width: 100px;
height: 16px;
background-color: green;
position: relative;
background-color: #F2F4F6;
.integrityNum{
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
color: black;
font-size: 13px;
cursor: default;
}
.integrityColorDiv{
height: 100%;
}
}
.mat-tree-node{
cursor: pointer;
@ -119,6 +131,71 @@
}
}
}
.fireForceList{
flex: 1;
overflow-y: auto;
li{
cursor: pointer;
width: 100%;
height: 36px;
line-height: 36px;
display: flex;
align-items: center;
font-size: 14px;
div{
float: left;
box-sizing: border-box;
}
.name{
text-align: left;
width: 60%;
padding-left: 22px;
white-space:nowrap;
overflow:hidden;
text-overflow:ellipsis;
}
.integrity{
height: 58%;
width: 32%;
position: relative;
background-color: #F2F4F6;
.integrityNum{
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
color: black;
font-size: 13px;
cursor: default;
}
.integrityColorDiv{
height: 100%;
}
}
.deletebtn{
flex: 1;
text-align: center;
mat-icon{
width: 20px;
height: 20px;
cursor: pointer;
font-size: 20px;
vertical-align: text-top;
color: rgba(49, 46, 46, 0.144);
}
mat-icon:hover{
color: #000;
}
}
}
li:hover{
background-color: #b3d3ee;
}
.selectedLi{
background-color: #b3d3ee;
}
}
.paginator{
height: 56px;
width: 100%;
@ -193,9 +270,12 @@
.detailsbox{
width: 100%;
height:500px;
position: relative;
.tabsbox{
width: 100%;
height: 40px;
overflow: hidden;
overflow-x: auto;
line-height: 40px;
display: flex;
justify-content: space-between;
@ -217,7 +297,45 @@
}
}
.btnbox{
display: flex;
align-items: center;
.uploadAttachment{
display: inline-block;
margin-right: 20px;
width: 120px;
text-align: center;
height: 28px;
line-height: 28px;
position: relative;
button{
width: 100%;
height: 28px;
line-height: 28px;
mat-icon{
transform: rotate(25deg);
font-size: 20px;
width: 20px;
height: 20px;
}
}
.a-upload{
display: inline-block;
position: absolute;
left: 0;
top: 0;
display: inline-block;
width: 100%;
height: 100%;
opacity: 0;
input{
width: 100%;
height: 100%;
cursor: pointer;
}
}
}
span{
display: inline-block;
cursor: pointer;
color: #2196F3;
mat-icon{
@ -233,22 +351,7 @@
.submitAudit{
margin: 0 30px;
}
.uploadAttachment{
margin-right: 20px;
width: 120px;
text-align: center;
height: 28px;
line-height: 28px;
mat-icon{
transform: rotate(25deg);
font-size: 20px;
width: 20px;
height: 20px;
}
mat-icon{
padding: 0 8px;
}
}
}
}
.contant{
@ -306,6 +409,94 @@
.smallwidth{
width: 30%;
}
// 相关资料
.fileDivBox{
position: relative;
float: left;
border: 1px solid #EBEBEB;
width: 160px;
height: 162px;
box-sizing: border-box;
padding: 16px 16px 0;
display: flex;
flex-direction: column;
margin: 12px;
align-items: center;
cursor: pointer;
.imgbox{
width: 134px;
height: 110px;
display: flex;
justify-content: center;
align-items: center;
.thumbnailImg{
width: 134px;
height: 110px;
}
}
span{
width: 100%;
text-align: center;
margin-top: 5px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
color: gray;
}
.deleteFile{
position: absolute;
right: 0;
top: 0;
width: 18px;
height: 18px;
font-size: 18px;
display: none;
}
.btn{
position: absolute;
height: 30px;
line-height: 30px;
font-size: 14px;
display: none;
}
.btn1{
top: 35px;
}
.btn2{
top: 75px;
}
}
.fileDivBox:hover{
border: 1px solid #000;
.deleteFile{
display: block;
}
.deleteFile:hover{
color: red;
}
.btn{
display: block;
}
}
}
.masklayer{
position: absolute;
left: 0;
top: 0;
z-index: 2000;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.2);
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
span{
font-size: 14px;
margin-top: 5px;
}
}
}
}

247
src/app/data-collection/fire-force/fire-force.component.ts

@ -8,6 +8,7 @@ import { MatSnackBar, MatSnackBarConfig } from '@angular/material/snack-bar';
import { MatTreeFlatDataSource, MatTreeFlattener } from '@angular/material/tree';
import { NzTreeNode } from 'ng-zorro-antd/tree';
import { TreeService } from 'src/app/http-interceptors/tree.service';
import Viewer from 'viewerjs'
declare var AMap: any;
@Component({
@ -18,7 +19,7 @@ declare var AMap: any;
export class FireForceComponent implements OnInit {
constructor(private tree: TreeService,public snackBar: MatSnackBar,private http:HttpClient,private elementRef: ElementRef,public renderer2: Renderer2,public dialog: MatDialog) { }
isMasklayer:boolean = false//遮罩层是否打开
isCheckedOfSearchDiv:boolean = true//列表过滤滑块
slideChange(e){
this.isCheckedOfSearchDiv = e.checked
@ -51,9 +52,42 @@ export class FireForceComponent implements OnInit {
}
//获得所有消防力量
newdata:any
allFireForceList:any= []
getAllFireForce(){
this.http.get('/api/CustomFireForce').subscribe((data:any) => {
   this.dataSource.data = this.tree.toTree(data)
let MinIntegrity = 0
let MaxIntegrity = 1.1
if(this.searchForm.integrityNum == '0'){
MinIntegrity = 0
MaxIntegrity = 0.5
}else if(this.searchForm.integrityNum == '1'){
MinIntegrity = 0.5
MaxIntegrity = 0.6
}else if(this.searchForm.integrityNum == '2'){
MinIntegrity = 0.6
MaxIntegrity = 0.7
}else if(this.searchForm.integrityNum == '3'){
MinIntegrity = 0.7
MaxIntegrity = 0.8
}else if(this.searchForm.integrityNum == '4'){
MinIntegrity = 0.8
MaxIntegrity = 0.9
}else if(this.searchForm.integrityNum == '5'){
MinIntegrity = 0.9
MaxIntegrity = 1.1
}else if(this.searchForm.integrityNum == '-1'){
MinIntegrity = 0
MaxIntegrity = 1.1
}
let params:any = {
Keyword : this.searchForm.name ? this.searchForm.name : '',
MinIntegrity : MinIntegrity,
MaxIntegrity : MaxIntegrity
}
this.http.get('/api/CustomFireForce',{params:params}).subscribe((data:any) => {
console.log('所有消防力量列表',data)
this.allFireForceList = data
   this.dataSource.data = this.tree.toTree(data)
this.treeControl.expand(this.treeControl.dataNodes[0]);
})
}
upDateAllFireForce = ():void=>{
@ -91,7 +125,8 @@ export class FireForceComponent implements OnInit {
code:node.code,
division:node.division,
fireForceDetailId:node.fireForceDetailId,
forceType:node.forceType
forceType:node.forceType,
fireForceDetailInfo:node.fireForceDetailInfo
};
}
treeControl = new FlatTreeControl<any>(node => node.level, node => node.expandable);
@ -111,7 +146,7 @@ export class FireForceComponent implements OnInit {
this.isGisTopBox = false
if(this.selectedFireForceId != node.id){
this.clearData()
this.selectedFireForce = node
this.selectedFireForceId = node.id
if(node.forceType != 0){//如果是其他消防力量
@ -147,6 +182,10 @@ export class FireForceComponent implements OnInit {
}else{
this.map.setCity('上海市');
}
//相关资料
console.log('详情',data)
data.relevantInfomationData ? this.AttachmentArr = JSON.parse(data.relevantInfomationData) : null
if(node.forceType == 0 && node.level == 0){
this.ZongpersonCountData = JSON.parse(data.personCountData)
this.ZongcontactData = JSON.parse(data.contactData)
@ -162,20 +201,36 @@ export class FireForceComponent implements OnInit {
if(node.forceType != 0){
this.otherpersonCountData = JSON.parse(data.personCountData)
this.othercontactData = JSON.parse(data.contactData)
}
})
}else{
this.map.setCity('上海市');
}
}
}
//搜索
isTreeView:boolean = true//决定显示树还是列表
searchList(){
console.log(this.searchForm)
if(!this.searchForm.name && !this.searchForm.integrityNum){
this.isTreeView = true
}else{
this.isTreeView = false
}
this.getAllFireForce()
}
//重置搜索
reset(){
this.isTreeView = true
this.selectedFireForceLevel = null
this.searchForm = {
name:'',
integrityNum:''
}
this.getAllFireForce()
}
//js乘法
accMul(arg1,arg2,fix) {
if(!parseInt(fix)==fix)
@ -248,7 +303,8 @@ export class FireForceComponent implements OnInit {
},
personCountData:[],//人员数量自定义
contactData:[],//联系方式自定义
dutyForceData:[]//执勤力量自定义
dutyForceData:[],//执勤力量自定义
RelevantInfomationData:[]//相关资料
}
//总队支队人员数量
ZongpersonCountData:any=[
@ -305,6 +361,8 @@ export class FireForceComponent implements OnInit {
]
//清空表单数据
clearData(){
this.deletedFile = []//清空相关资料已删除缓存
this.AttachmentArr = []//清空相关资料
this.superior = {
name:'',
code:''
@ -325,7 +383,8 @@ export class FireForceComponent implements OnInit {
},
personCountData:[],//人员数量自定义
contactData:[],//联系方式自定义
dutyForceData:[]//执勤力量自定义
dutyForceData:[],//执勤力量自定义
RelevantInfomationData:[]//相关资料
}
this.ZongpersonCountData = [
{PropertyName :'现役官兵人数',PropertyValue:''},
@ -412,10 +471,21 @@ export class FireForceComponent implements OnInit {
alert('名称必填')
return
}
console.log(777,this.atLastPositionLngLat)
//删除一下数据库的文件
if(this.deletedFile.length != 0){
this.deletedFile.forEach(item => {
// this.http.delete(`/api/Objects/PlanPlatform/${item.objectName}?x-oss-process=image/resize,m_fixed,h_100,w_100`).subscribe(data=>{
// console.log('删除缩略图成功')
// })
this.http.delete(`/api/Objects/PlanPlatform/${item.objectName}`).subscribe(data=>{
console.log('删除原文件成功')
})
});
}
this.FireForceDetailInfo.jurisdictionArea = Number(this.FireForceDetailInfo.jurisdictionArea)
this.FireForceDetailInfo.RelevantInfomationData = JSON.stringify(this.AttachmentArr)
//如果是总支大中
// console.log(8888, this.FireForceDetailInfo)
this.FireForceDetailInfo.location = {x:'',y:''}
if(this.atLastPositionLngLat.x){
this.FireForceDetailInfo.location.x = this.atLastPositionLngLat.x
@ -447,7 +517,6 @@ export class FireForceComponent implements OnInit {
config.duration = 3000
this.snackBar.open('保存成功','确定',config);
this.upDateAllFireForce()
console.log(123,data)
})
}
//如果是其他消防力量
@ -468,6 +537,7 @@ export class FireForceComponent implements OnInit {
config.verticalPosition = 'top';
config.duration = 3000
this.snackBar.open('保存成功','确定',config);
this.upDateAllFireForce()
// console.log(123,data)
})
}else{
@ -564,18 +634,18 @@ export class FireForceComponent implements OnInit {
isGisTopBox:boolean = false //
searchTitle:any = ''//
positionLngLat:any = {}//临时坐标点
atLastPositionLngLat:any = {x:null,y:null}//最终坐标点
positionLngLat:any = {x:'',y:''}//临时坐标点
atLastPositionLngLat:any = {x:'',y:''}//最终坐标点
setPosition(){
if(!this.isGisTopBox){
this.isGisTopBox = true
this.newPositionMarker ? this.map.remove(this.newPositionMarker) : null
let center
console.log()
console.log(789,this.atLastPositionLngLat)
if(this.newPositionMarker && this.atLastPositionLngLat.x){//如果已经标注单位坐标
console.log(1)
center = [this.atLastPositionLngLat.x, this.atLastPositionLngLat.y]
}else if(this.newPositionMarker && !this.atLastPositionLngLat.x && this.FireForceDetailInfo.location.x){
}else if(this.newPositionMarker && !this.atLastPositionLngLat.x && this.FireForceDetailInfo.location && this.FireForceDetailInfo.location.x){
console.log(2)
center = [this.FireForceDetailInfo.location.x, this.FireForceDetailInfo.location.y]
}else{
@ -628,6 +698,151 @@ export class FireForceComponent implements OnInit {
}
}
//上传附件
file:any; //上传的文件
AttachmentArr:any = []//上传附件地址集合
uploadId:any//分块上传id
objectName:any
uploadAttachment(e){
console.log('选择的文件',e)
this.file = e.target.files[0] || null //上传的文件
let file = e.target.files[0] || null //获取上传的文件
let fileSize = file.size || null //上传文件的总大小
let shardSize = 5 * 1024 * 1024 //5MB一个分片
this.isMasklayer = true
if (file && fileSize<=shardSize) { //上传文件<=5MB时
console.log('file',this.file)
let formData = new FormData()
formData.append("file",file)
//this.selectedFireForce.id 选择的组织机构的id
this.http.post(`/api/Objects/PlanPlatform/FireForce/${this.selectedFireForce.id}`,formData).subscribe((data:any)=>{
// this.objectName = data.objectName
let obj = {
objectName:data.objectName,
fileName:data.fileName,
fileLength:data.fileLength
}
this.AttachmentArr.push(obj)
this.isMasklayer = false
console.log('上传成功',data)
})
} else if (file && fileSize>shardSize) { //上传文件>5MB时,分块上传
let data = {filename: file.name}
this.http.post(`/api/NewMultipartUpload/PlanPlatform/FireForce/${this.selectedFireForce.id}`,{},{params:data}).subscribe((data:any)=>{ //初始化分段上传
console.log('初始化分块上传成功',data)
this.objectName = data.objectName
this.uploadId = data.uploadId
this.subsectionUploading()
})
}
}
PartNumberETag:any=[]; //每次返回需要保存的信息
//开始分段上传
async subsectionUploading () {
let file = this.file || null //获取上传的文件
let fileSize = file.size || null //上传文件的总大小
let shardSize = 5 * 1024 * 1024 //5MB一个分片
let allSlice = Math.ceil(fileSize / shardSize) //总文件/5MB===共分多少段
for (let i = 0;i < allSlice;i++) { //循环分段上传
let start = i * shardSize //切割文件开始位置
let end = Math.min(fileSize, start + shardSize); //切割文件结束位置
let formData = new FormData()
formData.append("file",file.slice(start, end))
//同步写法实现异步调用
let result = await new Promise((resolve, reject) => {
// await 需要后面返回一个 promise 对象
this.http.post(`/api/MultipartUpload/PlanPlatform/${this.objectName}?uploadId=${this.uploadId}&partNumber=${i+1}`,formData).subscribe((data:any)=>{
let msg = {
"partNumber":data.partNumber || null,
"eTag": data.eTag || null}
resolve(msg) // 调用 promise 内置方法处理成功
})
});
this.PartNumberETag.push(result)
// this.uploadProgress = Number((i/allSlice).toFixed(2))*100
if (this.PartNumberETag.length === allSlice) {
// this.uploadProgress = 100
this.endUploading()}
}//for循环
}
//完成分块上传
endUploading () {
let data = this.PartNumberETag
let paramsData = {uploadId:this.uploadId}
this.http.post(`/api/CompleteMultipartUpload/PlanPlatform/${this.objectName}`,data,{params:paramsData}).subscribe(data=>{
this.PartNumberETag =[] //清空保存返回的信息
let obj = {
objectName:this.objectName,
fileName:this.file.name,
fileLength:this.file.size
}
this.AttachmentArr.push(obj)
console.log('完成分块上传',data)
this.isMasklayer = false
})
}
//删除图片
deletedFile:any = []
deleteFile(item,e){
console.log(this.AttachmentArr)
e.stopPropagation()
let isTrue = window.confirm('确定要删除该文件吗?')
if(isTrue){
let index
this.AttachmentArr.forEach((element,key) => {
if(element.objectName == item.objectName){
index = key
}
});
this.AttachmentArr.splice(index,1)
this.deletedFile.push(item)
let config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.snackBar.open('删除成功','确定',config);
}
}
//点击文件
clickFile(item){
console.log(item)
let suffix = item.fileName.split('.')[item.fileName.split('.').length-1]
if(suffix == 'png' || suffix == 'jpg'){
console.log('这是图片')
let dom = document.getElementById(`viewerjs`)
let pObjs = dom.childNodes;
let node = document.createElement("img")
node.style.display = "none";
node.src = "/api/Objects/PlanPlatform/" + item.objectName;
node.id = 'img'
dom.appendChild(node)
setTimeout(() => {
let viewer = new Viewer(document.getElementById(`viewerjs`), {
hidden:()=>{
dom.removeChild(pObjs[0]);
viewer.destroy();
}
});
node.click();
}, 0);
}
if(suffix == 'docx' || suffix == 'doc' || suffix == 'pdf'){
let config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.snackBar.open('暂不支持查看','确定',config);
}
}
}

BIN
src/assets/images/pdf.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

BIN
src/assets/images/txt.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
src/assets/images/vedio.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

BIN
src/assets/images/word.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Loading…
Cancel
Save