Browse Source

移动盘点

master
xuhuajiao 5 months ago
parent
commit
ecc07b9495
  1. 1
      .env.development
  2. 3
      .env.production
  3. 5
      package.json
  4. 3
      public/static/config.js
  5. 11
      src/api/stockTask/index.js
  6. 2
      src/assets/styles/sidebar.scss
  7. 3
      src/main.js
  8. 15
      src/utils/upload.js
  9. 9
      src/views/visualCheck/checkManage/checkLog/index.vue
  10. 6
      src/views/visualCheck/checkManage/dataScreening/girdList.vue
  11. 515
      src/views/visualCheck/checkManage/mobileCheck/index.vue
  12. 271
      src/views/visualCheck/checkManage/mobileCheck/module/corpper.vue
  13. 84
      src/views/visualCheck/checkManage/paramSetting/index.vue

1
.env.development

@ -3,6 +3,7 @@ ENV = 'development'
# 接口地址 # 接口地址
# 许镇-本地服地址 # 许镇-本地服地址
#VUE_APP_BASE_API = 'http://192.168.99.67:12010'
VUE_APP_BASE_API = 'http://192.168.99.86:12010' VUE_APP_BASE_API = 'http://192.168.99.86:12010'
#VUE_APP_BASE_API = 'http://27.19.205.234:17070' #VUE_APP_BASE_API = 'http://27.19.205.234:17070'

3
.env.production

@ -3,7 +3,8 @@ ENV = 'production'
# 如果使用 Nginx 代理后端接口,那么此处需要改为 '/',文件查看 Docker 部署篇,Nginx 配置 # 如果使用 Nginx 代理后端接口,那么此处需要改为 '/',文件查看 Docker 部署篇,Nginx 配置
# 接口地址,注意协议,如果你没有配置 ssl,需要将 https 改为 http # 接口地址,注意协议,如果你没有配置 ssl,需要将 https 改为 http
VUE_APP_BASE_API = 'http://192.168.3.220:12010'
#VUE_APP_BASE_API = 'http://192.168.3.220:12010'
VUE_APP_BASE_API = 'http://192.168.99.86:12010'
# 如果接口是 http 形式, wss 需要改为 ws # 如果接口是 http 形式, wss 需要改为 ws
#VUE_APP_WS_API = 'ws://27.16.212.58:11100' #VUE_APP_WS_API = 'ws://27.16.212.58:11100'
#VUE_APP_CAMERA_API = '192.168.99.107:3000' #VUE_APP_CAMERA_API = '192.168.99.107:3000'

5
package.json

@ -39,6 +39,7 @@
"codemirror": "^5.49.2", "codemirror": "^5.49.2",
"connect": "3.6.6", "connect": "3.6.6",
"core-js": "^3.6.5", "core-js": "^3.6.5",
"cropperjs": "^1.6.2",
"d3": "^4.12.0", "d3": "^4.12.0",
"dimple": "git+https://github.com/PMSI-AlignAlytics/dimple.git#2.3.0", "dimple": "git+https://github.com/PMSI-AlignAlytics/dimple.git#2.3.0",
"docx-preview": "^0.1.8", "docx-preview": "^0.1.8",
@ -85,7 +86,8 @@
"vue": "^2.6.14", "vue": "^2.6.14",
"vue-awesome-swiper": "^3.1.3", "vue-awesome-swiper": "^3.1.3",
"vue-count-to": "^1.0.13", "vue-count-to": "^1.0.13",
"vue-cropper": "0.4.9",
"vue-cropper": "^0.4.9",
"vue-cropperjs": "^5.0.0",
"vue-demi": "^0.14.7", "vue-demi": "^0.14.7",
"vue-echarts": "^5.0.0-beta.0", "vue-echarts": "^5.0.0-beta.0",
"vue-highlightjs": "^1.3.3", "vue-highlightjs": "^1.3.3",
@ -124,6 +126,7 @@
"eslint": "5.15.3", "eslint": "5.15.3",
"eslint-plugin-vue": "5.2.2", "eslint-plugin-vue": "5.2.2",
"generate-asset-webpack-plugin": "^0.3.0", "generate-asset-webpack-plugin": "^0.3.0",
"html-webpack-plugin": "^4.5.2",
"http-proxy-middleware": "^0.19.1", "http-proxy-middleware": "^0.19.1",
"husky": "1.3.1", "husky": "1.3.1",
"lint-staged": "8.1.5", "lint-staged": "8.1.5",

3
public/static/config.js

@ -1,6 +1,7 @@
window.g = { window.g = {
AXIOS_TIMEOUT: 10000, AXIOS_TIMEOUT: 10000,
ApiUrl: 'http://192.168.3.220:12010', // 配置服务器地址,
// ApiUrl: 'http://192.168.3.220:12010', // 配置服务器地址,
ApiUrl: 'http://192.168.99.86:12010', // 配置服务器地址,
// ParentPage: { // 后续看需求配置 // ParentPage: { // 后续看需求配置
// CrossDomainProxyUrl: '/Home/CrossDomainProxy', // CrossDomainProxyUrl: '/Home/CrossDomainProxy',
// BtnsApi: '/api/services/app/Authorization/GetBtns', // BtnsApi: '/api/services/app/Authorization/GetBtns',

11
src/api/stockTask/index.js

@ -147,4 +147,13 @@ export function FetchStartStopBookAIService(params) {
}) })
} }
export default { add, edit, del, FetchUpdateStockTaskStatus, FetchInitSuggestTilting, FetchInitSetting, FetchEditSetting, FetchInitHomeInfo, FetchInitStockInfo, FetchInitHotBookList, FetchInitHotShelfList, FetchInitBookDetailsByGrids, FetchAITerminalStatusQuery, FetchBillByShelfIdAndGridShelf, FetchIsGoodcutByBillNoAndGridId, FetchInitErrorProbaDesc, FetchShowByBillIdAndShelfIdAndGridShelf, FetchStartStopBookAIService }
// 移动盘点
export function FetchMoveBills(data) {
return request({
url: 'api/stocktask-task/moveBill',
method: 'post',
data
})
}
export default { add, edit, del, FetchUpdateStockTaskStatus, FetchInitSuggestTilting, FetchInitSetting, FetchEditSetting, FetchInitHomeInfo, FetchInitStockInfo, FetchInitHotBookList, FetchInitHotShelfList, FetchInitBookDetailsByGrids, FetchAITerminalStatusQuery, FetchBillByShelfIdAndGridShelf, FetchIsGoodcutByBillNoAndGridId, FetchInitErrorProbaDesc, FetchShowByBillIdAndShelfIdAndGridShelf, FetchStartStopBookAIService, FetchMoveBills }

2
src/assets/styles/sidebar.scss

@ -18,7 +18,7 @@
top: $headerHeight; top: $headerHeight;
bottom: 0; bottom: 0;
left: 0; left: 0;
z-index: 99;
z-index: 99999;
@include bg_color; @include bg_color;
@include siderBar-set; @include siderBar-set;
padding-bottom: 50px; padding-bottom: 50px;

3
src/main.js

@ -67,6 +67,9 @@ Vue.directive('removeAriaHidden', {
} }
}) })
import VueCropper from 'vue-cropper'
Vue.use(VueCropper)
Vue.use(uploader) Vue.use(uploader)
Vue.use(checkPer) Vue.use(checkPer)
Vue.use(VueHighlightJS) Vue.use(VueHighlightJS)

15
src/utils/upload.js

@ -120,3 +120,18 @@ export function onlineUpload(api, file, params) {
} }
return axios.post(api, data, config) return axios.post(api, data, config)
} }
// 移动盘点
export function mobileUpload(api, file, params) {
var data = new FormData()
for (const item in file) {
data.append('files', file[item])
}
// data.append('files', file)
data.append('gridId', params.gridId)
data.append('stockRegion', params.stockRegion)
const config = {
headers: { 'Authorization': getToken() }
}
return axios.post(api, data, config)
}

9
src/views/visualCheck/checkManage/checkLog/index.vue

@ -47,6 +47,7 @@
<span v-if="scope.row.stockType===4">书架盘点</span> <span v-if="scope.row.stockType===4">书架盘点</span>
<span v-if="scope.row.stockType===5">架位盘点</span> <span v-if="scope.row.stockType===5">架位盘点</span>
<span v-if="scope.row.stockType===6">层位盘点</span> <span v-if="scope.row.stockType===6">层位盘点</span>
<span v-if="scope.row.stockType===7">移动盘点</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="stockRegion" label="目标位置" min-width="180" /> <el-table-column prop="stockRegion" label="目标位置" min-width="180" />
@ -140,6 +141,7 @@
<li v-if="detailInfo.stockType===4"><span>盘点类型</span>书架盘点</li> <li v-if="detailInfo.stockType===4"><span>盘点类型</span>书架盘点</li>
<li v-if="detailInfo.stockType===5"><span>盘点类型</span>架位盘点</li> <li v-if="detailInfo.stockType===5"><span>盘点类型</span>架位盘点</li>
<li v-if="detailInfo.stockType===6"><span>盘点类型</span>层位盘点</li> <li v-if="detailInfo.stockType===6"><span>盘点类型</span>层位盘点</li>
<li v-if="detailInfo.stockType===7"><span>盘点类型</span>移动盘点</li>
<li><span>目标位置</span>{{ detailInfo.stockRegion }}</li> <li><span>目标位置</span>{{ detailInfo.stockRegion }}</li>
<li><span>目标数量</span>{{ detailInfo.stockGridNum }} / {{ detailInfo.totalGridNum }} 层位</li> <li><span>目标数量</span>{{ detailInfo.stockGridNum }} / {{ detailInfo.totalGridNum }} 层位</li>
@ -277,7 +279,8 @@ export default {
{ key: 3, display_name: '计划盘点' }, { key: 3, display_name: '计划盘点' },
{ key: 4, display_name: '书架盘点' }, { key: 4, display_name: '书架盘点' },
{ key: 5, display_name: '架位盘点' }, { key: 5, display_name: '架位盘点' },
{ key: 6, display_name: '层位盘点' }
{ key: 6, display_name: '层位盘点' },
{ key: 7, display_name: '移动盘点' }
], ],
blurryTime: null, blurryTime: null,
tabIndex: 0, tabIndex: 0,
@ -368,8 +371,8 @@ export default {
return true return true
}, },
clickRowHandler(row) { clickRowHandler(row) {
this.$refs.table.clearSelection()
this.$refs.table.toggleRowSelection(row)
// this.$refs.table.clearSelection()
// this.$refs.table.toggleRowSelection(row)
}, },
doExport(data) { doExport(data) {
this.$confirm('此操作将导出所选数据' + '<span>你是否还要继续?</span>', '提示', { this.$confirm('此操作将导出所选数据' + '<span>你是否还要继续?</span>', '提示', {

6
src/views/visualCheck/checkManage/dataScreening/girdList.vue

@ -418,6 +418,8 @@ export default {
return '架位盘点' return '架位盘点'
case 6: case 6:
return '层位盘点' return '层位盘点'
case 7:
return '移动盘点'
default: default:
return '现在' return '现在'
} }
@ -503,6 +505,7 @@ export default {
color: '#0bbd87' color: '#0bbd87'
}) })
this.billNoImg = this.checkDateLine[this.timeIndex].stockType === 0 ? this.checkDateLine[1].stockBill : this.checkDateLine[this.timeIndex].stockBill this.billNoImg = this.checkDateLine[this.timeIndex].stockType === 0 ? this.checkDateLine[1].stockBill : this.checkDateLine[this.timeIndex].stockBill
console.log('this.checkDateLine', this.checkDateLine)
} else { } else {
this.checkDateLine = [] this.checkDateLine = []
} }
@ -777,8 +780,7 @@ export default {
handleHistory(item, index) { handleHistory(item, index) {
this.shelfAllGridDataLoading = true this.shelfAllGridDataLoading = true
this.timeIndex = index this.timeIndex = index
this.billNoImg = this.checkDateLine[this.timeIndex].stockType === 0 ? this.checkDateLine[1].stockBill : this.checkDateLine[this.timeIndex].stockBill
this.billNoImg = item.stockType === 0 ? this.checkDateLine[1].stockBill : item.stockBill
if (item.stockType === 0) { if (item.stockType === 0) {
this.initData() this.initData()
setTimeout(() => { setTimeout(() => {

515
src/views/visualCheck/checkManage/mobileCheck/index.vue

@ -0,0 +1,515 @@
<template>
<div class="app-container row-container">
<!-- style="height: calc(100vh - 200px);" -->
<!-- style="height: calc(100vh);" -->
<div class="container-wrap" :style="{ height: !isMobile ? 'calc(100vh - 200px)' : '' }">
<span class="right-top-line" />
<span class="left-bottom-line" />
<div class="camera-container">
<div :class="!isMobile ? 'mobile-step' : 'mobile-step isMobile-step'">
<!-- <span>选择目标位置</span> -->
<el-divider content-position="left"><img src="@/assets/images/collect/one.png"><span>选择目标位置</span></el-divider>
<div class="step-style">
<el-form ref="form" :inline="true" :model="form" :rules="rules" size="small" label-width="90px">
<el-form-item class="collection-tree-select" label="所在架位" prop="actualShelfId">
<treeselect
v-model="form.actualShelfId"
:options="regionTreeData"
flat
:multiple="false"
placeholder="选择架"
:normalizer="normalizer"
:default-expand-level="levelNumber"
style="width: 282px;"
:disabled="!stepOne"
:searchable="false"
@select="node=>treeSelectInput(node)"
>
<div slot="value-label" slot-scope="{ node }">{{ getAutoNameUnknown(node.label) }}</div>
</treeselect>
</el-form-item>
<el-form-item class="collection-tree-select" label="所在层位" prop="gridId">
<treeselect
v-model="form.gridId"
:options="girdData"
placeholder="选择层位"
:normalizer="normalizerGird"
:default-expand-level="levelNumber"
:disabled="!stepOne"
style="width: 282px; "
:searchable="false"
@select="node=>gridSelectInput(node)"
>
<div slot="value-label" slot-scope="{ node }">{{ getAutoNameUnknown(node.label) }}</div>
</treeselect>
</el-form-item>
</el-form>
<el-button v-if="stepOne" class="check-btn" style="margin-bottom: 18px" :loading="submitLoading" type="primary" @click="submitStepOne">下一步</el-button>
</div>
</div>
<div :class="!isMobile ? 'mobile-step' : 'mobile-step isMobile-step'">
<!-- <span>拍照上传</span> -->
<el-divider content-position="left"><img src="@/assets/images/collect/two2.png"><span>拍照上传</span></el-divider>
<!-- style="margin: 20px 0;" -->
<div v-if="!stepOne" class="step-style">
<div class="mobile-check-upload">
<div class="upload-input">
<input
ref="imgFile"
accept="image/*"
capture="camera"
type="file"
multiple
:disabled="stepOne"
@change="previewFiles"
>
<div class="upload-zip"><i class="iconfont icon-shangchuan2" />{{ isMobile ? '拍照上传':'上传文件' }}</div>
</div>
<div style="margin-left: 40px;">
<div v-for="(imgSrc, index) in imageSources" :key="index" style="display: inline-block; margin: 10px;">
<img
:src="imgSrc"
style="display: inline-block; max-width: 100px; max-height: 100px;"
@click="showCoverPreview(imgSrc)"
>
<i class="iconfont icon-shanchu1" @click="deleteImage(index)" />
</div>
</div>
<!-- 裁切上传 -->
<!-- <el-form ref="formValidate" :model="formValidate" :rules="ruleCropper" label-width="100px" class="mobile-stepForm">
<el-form-item label="照片上传" prop="mainImage">
<div v-if="formValidate.mainImage !== ''" class="list-img-box">
<img :src="formValidate.mainImage" style="max-width:300px; max-height:150px" alt="图书" @click="showCoverPreview(formValidate.mainImage)">
</div>
<div class="upload-zip" @click="uploadPicture('flagImg')"><i class="iconfont icon-shangchuan2" />{{ isMobile ? '拍照上传':'上传文件' }}</div>
<input v-model="formValidate.mainImage" type="hidden" placeholder="请添加照片">
</el-form-item>
</el-form> -->
</div>
<div>
<el-button type="primary" @click="returnStepOne">上一步</el-button>
<el-button class="check-btn" :loading="submitLoading" type="primary" @click="saveData">下一步</el-button>
</div>
</div>
</div>
<div :class="!isMobile ? 'mobile-step' : 'mobile-step isMobile-step'">
<!-- <span>开始盘点</span> -->
<el-divider content-position="left"><img src="@/assets/images/collect/three2.png"><span>开始盘点</span></el-divider>
<div v-if="stepThree" class="step-style step-three-text">
<p v-if="mobileResult">
移动盘点已创建成功单号{{ mobileResult.stockBill }}查看详情请转到
<router-link :to="{ path: '/check/check/checkLog'}">
盘点日志
</router-link>
</p>
<p v-else>
移动盘点创建失败
</p>
</div>
</div>
</div>
</div>
<!-- 点击缩略图看大图 -->
<el-dialog v-if="!isMobile" class="preview-dialog" :append-to-body="true" :close-on-click-modal="false" :before-close="handleClose" :visible="showCoverVisible" title="查看大图">
<span class="dialog-right-top" />
<span class="dialog-left-bottom" />
<div class="setting-dialog" style="max-height:calc(100vh - 230px); overflow:auto;">
<img style="max-width:100%; object-fit: contain;" :src="previewSrc">
</div>
</el-dialog>
<el-dialog v-else class="mobile-dialog" :append-to-body="true" :close-on-click-modal="false" :before-close="handleClose" :visible="showCoverVisible" title="查看大图">
<span class="dialog-right-top" />
<span class="dialog-left-bottom" />
<div class="setting-dialog">
<img style="max-width:100%; max-height: 100%; object-fit: contain;" :src="previewSrc">
</div>
</el-dialog>
<!-- 剪裁组件弹窗 -->
<el-dialog
title="裁切照片"
:close-on-click-modal="false"
:modal-append-to-body="false"
append-to-body
:visible.sync="cropperModel"
width="950px"
center
>
<cropper-image
ref="child"
@uploadImgSuccess="handleUploadSuccess"
/>
</el-dialog>
<!--查看大图-->
<el-dialog
:close-on-click-modal="false"
:modal-append-to-body="false"
append-to-body
title="查看大图"
:visible.sync="imgVisible"
center
>
<img v-if="imgVisible" :src="imgName" style="width: 100%" alt="查看">
</el-dialog>
</div>
</template>
<script>
import { FetchRegionTree } from '@/api/deviceVI/index'
import { FetchShelfGridAllByShelfId } from '@/api/shelf/index'
import { mapGetters } from 'vuex'
import { removeQUPrefix } from '@/utils/index'
import { mobileUpload } from '@/utils/upload'
import Treeselect from '@riophae/vue-treeselect'
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
import CropperImage from './module/corpper.vue'
export default {
name: 'MobileCheck',
components: { Treeselect, CropperImage },
data() {
return {
form: { actualShelfId: null, gridId: null },
levelNumber: 4,
regionTreeData: [],
selectShelfVal: null,
selectGridVal: null,
girdData: [],
permission: {
add: ['admin', 'paramSetting:add'],
edit: ['admin', 'paramSetting:edit'],
del: ['admin', 'paramSetting:del']
},
showCoverVisible: false, // dialog
previewSrc: '', // src
imageSources: [], // URL
selectedFiles: [], // File
isMobile: false,
submitLoading: false,
rules: {
gridId: [
{ required: true, message: '请选择层位', trigger: 'change' }
],
actualShelfId: [
{ required: true, message: '请选择书架', trigger: 'change' }
]
},
stepOne: true,
stepTwo: false,
stepThree: false,
//
formValidate: {
mainImage: ''
},
ruleCropper: {
mainImage: [
{ required: true, message: '请上传照片', trigger: 'blur' }
]
},
cropperModel: false,
imgName: '',
imgVisible: false
}
},
computed: {
...mapGetters([
'baseApi'
])
},
created() {
FetchRegionTree().then(res => {
this.regionTreeData = [this.transformData(res)]
}).catch(() => {
})
this.checkDevice()
},
beforeDestroy() {
},
mounted() {
},
methods: {
// vue-treeSelectunknown
getAutoNameUnknown(name) {
if (name.lastIndexOf('unknown') > -1) {
return name.split('(')[0]
} else {
return name
}
},
normalizer(node) {
if (node.children && !node.children.length) {
delete node.children
}
return {
id: node.id,
label: node.label,
children: node.children,
isDisabled: !node.shelfId
}
},
normalizerGird(node) {
return {
id: node.id,
label: removeQUPrefix(node.gridName)
}
},
transformData(data) {
return {
id: data.fondsId,
fondsId: data.fondsId,
label: data.fondsName,
children: data.floors.map(floor => ({
id: floor.id,
floorId: floor.id,
label: floor.floorName,
children: floor.regions.map(region => ({
id: region.id,
regionId: region.id,
label: region.regionName,
parentFloorId: floor.id,
children: region.bookShelf.map(shelfItem => ({
id: shelfItem.shelfId,
shelfId: shelfItem.shelfId,
label: shelfItem.shelfName,
regionName: floor.floorName + '-' + region.regionName,
parentRegionId: region.id
}))
}))
}))
}
},
treeSelectInput(value) {
console.log(value)
// '3F--001A'
this.selectShelfVal = value
this.form.gridId = null
this.getShelfGridAllByShelfId()
},
getShelfGridAllByShelfId() {
const params = {
'shelfId': this.selectShelfVal.id
}
FetchShelfGridAllByShelfId(params).then(res => {
this.girdData = res
}).catch(() => {
})
},
gridSelectInput(value) {
console.log(value)
this.selectGridVal = value
},
checkDevice() {
const userAgent = navigator.userAgent.toLowerCase()
const mobileKeywords = ['android', 'iphone', 'ipad', 'ipod']
this.isMobile = mobileKeywords.some(keyword => userAgent.includes(keyword))
},
previewFiles() {
const files = this.$refs.imgFile.files
const maxImages = 3
const remainingSlots = maxImages - this.imageSources.length
if (remainingSlots === 0) {
this.$message({ message: '已有 3 张图片,不能再上传', type: 'error', offset: 8 })
}
const validFiles = []
for (let i = 0; i < files.length; i++) {
const file = files[i]
if (file.type === 'image/jpeg') {
validFiles.push(file)
} else {
this.$message({ message: `文件 ${file.name} 不是 JPG 格式,将忽略该文件`, type: 'error', offset: 8 })
}
}
if (validFiles.length > remainingSlots) {
this.$message({ message: `最多只能再上传 ${remainingSlots} 张图片,将只处理部分选择的图片`, type: 'error', offset: 8 })
}
const numFilesToProcess = Math.min(validFiles.length, remainingSlots)
for (let i = 0; i < numFilesToProcess; i++) {
const file = validFiles[i]
const reader = new FileReader()
reader.onload = (e) => {
this.imageSources.push(e.target.result)
}
reader.readAsDataURL(file)
this.selectedFiles.push(file)
}
},
submitStepOne() {
this.$refs.form.validate((valid) => {
if (valid) {
this.stepOne = false
} else {
console.log('error submit!!')
return false
}
})
},
returnStepOne() {
this.stepOne = true
this.stepTwo = false
this.imageSources = []
this.selectedFiles = []
},
saveData() {
// this.formValidate.mainImage === ''
if (this.selectedFiles.length === 0) {
this.$message({ message: '请上传照片', type: 'error', offset: 8 })
} else {
this.submitLoading = true
const params = {
'gridId': this.form.gridId,
'stockRegion': this.selectShelfVal.regionName + '-' + removeQUPrefix(this.selectGridVal.gridName)
}
mobileUpload(this.baseApi + '/api/stocktask-task/moveBill', this.selectedFiles, params).then(res => {
console.log(res)
if (res.data.code === 200) {
this.mobileResult = res.data.data
this.stepOne = false
this.stepTwo = true
} else {
this.$message({ message: res.data.message, type: 'error', offset: 8 })
this.mobileResult = null
}
this.submitLoading = false
})
}
},
deleteImage(index) {
this.imageSources.splice(index, 1)
this.selectedFiles.splice(index, 1)
},
handleClose(done) {
this.showCoverVisible = false
done()
},
//
showCoverPreview(imgSrc) {
this.showCoverVisible = true
this.previewSrc = imgSrc
},
// -----
uploadPicture() {
this.cropperModel = true
},
//
handleUploadSuccess(data) {
console.log(data)
this.formValidate.mainImage = data.url
this.selectedFiles = data.file
// switch (data.name) {
// case 'flagImg':
// this.formValidate.mainImage = 'http://ydfblog.cn/dfs/' + data.url
// console.log('' + data.name)
// break
// }
this.cropperModel = false
}
}
}
</script>
<style lang="scss" scoped>
.camera-container{
height: 100%;
}
.mobile-step{
position: relative;
height: calc(100% / 3);
::v-deep .el-divider--horizontal{
margin: 0 !important;
.el-divider__text{
display: flex;
justify-content: flex-start;
align-items: center;
img{
display: block;
margin-top: -10px;
}
span{
font-size: 16px;
margin-left: 10px;
font-weight: bold;
color: #0c0e1e;
}
}
}
// padding-left: 20px;
// &::before{
// content: '';
// position: absolute;
// top: 0;
// left: 0;
// width: 10px;
// height: 10px;
// border-radius: 50%;
// background-color: #0c0e1e;
// }
// &::after{
// content: '';
// position: absolute;
// top: 8px;
// left: 4px;
// width: 2px;
// height: calc(100% - 20px);
// background-color: #0c0e1e;
// }
}
.isMobile-step{
height: 200px;
}
.mobile-check-upload{
display: flex;
justify-content: flex-start;
align-items: center;
.upload-input{
margin-top: 0 !important;
}
}
// .bg-button{
// color: #fff;
// background: #1f55eb;
// }
.mobile-dialog{
::v-deep .el-dialog{
width: 100%;
}
}
.upload-input input{
width: 105px;
}
.step-style{
display: flex; justify-content: space-between; align-items: center; height: calc(100%); padding: 0 16px;
}
.step-three-text {
justify-content: flex-start;
a{
font-weight: bold;
color: #1f55eb;
}
}
.vue-treeselect__search {
display: none;
}
.mobile-stepForm{
::v-deep .el-form-item__content{
display: flex;
justify-content: flex-start;
align-items: end;
.upload-zip{
margin-left: 40px;
}
}
}
</style>

271
src/views/visualCheck/checkManage/mobileCheck/module/corpper.vue

@ -0,0 +1,271 @@
<template>
<div class="cropper-content">
<div class="cropper-box">
<div class="cropper">
<vue-cropper
ref="cropper"
:img="option.img"
:output-size="option.outputSize"
:output-type="option.outputType"
:info="option.info"
:can-scale="option.canScale"
:auto-crop="option.autoCrop"
:auto-crop-width="option.autoCropWidth"
:auto-crop-height="option.autoCropHeight"
:fixed="option.fixed"
:fixed-number="option.fixedNumber"
:full="option.full"
:fixed-box="option.fixedBox"
:can-move="option.canMove"
:can-move-box="option.canMoveBox"
:original="option.original"
:center-box="option.centerBox"
:height="option.height"
:info-true="option.infoTrue"
:max-img-size="option.maxImgSize"
:enlarge="option.enlarge"
:mode="option.mode"
@realTime="realTime"
@imgLoad="imgLoad"
/>
</div>
<!--底部操作工具按钮-->
<div class="footer-btn">
<div class="scope-btn">
<label class="btn" for="uploads">上传照片</label>
<input id="uploads" type="file" style="position:absolute; clip:rect(0 0 0 0);" accept="image/png, image/jpeg, image/gif, image/jpg" capture="camera" @change="selectImg($event)">
<el-button size="mini" type="danger" icon="el-icon-zoom-in" @click="changeScale(1)">放大</el-button>
<el-button size="mini" type="danger" icon="el-icon-zoom-out" @click="changeScale(-1)">缩小</el-button>
<!-- <el-button size="mini" type="danger" @click="rotateLeft"> 左旋转</el-button>
<el-button size="mini" type="danger" @click="rotateRight"> 右旋转</el-button> -->
</div>
<div class="upload-cropper-btn">
<el-button size="mini" type="success" @click="uploadImg('blob')">确认裁切 <i class="el-icon-upload" /></el-button>
</div>
</div>
</div>
<!--预览效果图-->
<div class="show-preview">
<div :style="previews.div" class="preview">
<img :src="previews.url" :style="previews.img">
</div>
</div>
</div>
</template>
<script>
import { VueCropper } from 'vue-cropper'
export default {
name: 'CropperImage',
components: {
VueCropper
},
data() {
return {
previews: {},
option: {
img: '', //
outputSize: 1, // (0.1 - 1)
outputType: 'jpeg', // jpeg || png || webp
fixedNumber: [1.53, 1], //
infoTrue: false, // truefalse
maxImgSize: 10 * 1024 * 1024, // 10MB
enlarge: 1, //
full: false, // propsfull
canMove: true, //
original: false, //
height: true, // dpr
canMoveBox: true, //
autoCrop: true, //
autoCropWidth: 200, //
autoCropHeight: 200, //
fixedBox: false, //
mode: 'cover', //
info: true, //
canScale: true, //
fixed: false, //
centerBox: false //
},
imageUrl: ''
}
},
beforeDestroy() {
if (this.imageUrl) {
URL.revokeObjectURL(this.imageUrl)
}
},
methods: {
//
imgLoad(msg) {
console.log('工具初始化函数=====' + msg)
},
//
changeScale(num) {
num = num || 1
this.$refs.cropper.changeScale(num)
},
//
rotateLeft() {
this.$refs.cropper.rotateLeft()
},
//
rotateRight() {
this.$refs.cropper.rotateRight()
},
//
realTime(data) {
this.previews = data
},
//
selectImg(e) {
const file = e.target.files[0]
if (!/\.(jpg|jpeg|JPG)$/.test(e.target.value)) {
this.$message({
message: '图片类型要求:jpeg、jpg',
type: 'error'
})
return false
}
// blob
const reader = new FileReader()
reader.onload = (e) => {
let data
if (typeof e.target.result === 'object') {
data = window.URL.createObjectURL(new Blob([e.target.result]))
} else {
data = e.target.result
}
this.option.img = data
}
// base64
reader.readAsDataURL(file)
this.selectedFiles = file
},
//
uploadImg(type) {
const _this = this
if (type === 'blob') {
// blob
this.$refs.cropper.getCropBlob(async(data) => {
console.log('data', data)
// Blob File
const file = new File([data], 'DX.jpg', { type: data.type })
// File URL
this.imageUrl = URL.createObjectURL(file)
// const formData = new FormData()
// formData.append('file', file, 'DX.jpg')
console.log('file', file)
const imgInfo = {
url: this.imageUrl,
file: file
}
console.log('imgInfo', imgInfo)
_this.$emit('uploadImgSuccess', imgInfo)
// axios
// const { data: res } = await _this.$http.post('/api/file/imgUpload', formData)
// if (res.code === 200) {
// _this.$message({
// message: res.msg,
// type: 'success'
// })
// const data = res.data.replace('[', '').replace(']', '').split(',')
// const imgInfo = {
// name: _this.cropperName,
// url: data[0]
// }
// console.log('imgInfo', imgInfo)
// _this.$emit('uploadImgSuccess', imgInfo)
// } else {
// _this.$message({
// message: '',
// type: 'error'
// })
// }
})
}
},
// base64file
convertBase64UrlToBlob(urlData) {
const bytes = window.atob(urlData.split(',')[1])// urlbyte
// ,ascii00
const ab = new ArrayBuffer(bytes.length)
const ia = new Uint8Array(ab)
for (var i = 0; i < bytes.length; i++) {
ia[i] = bytes.charCodeAt(i)
}
return new Blob([ab], { type: 'image/jpeg' })
}
}
}
</script>
<style scoped lang="scss">
.cropper-content{
display: flex;
display: -webkit-flex;
justify-content: flex-end;
.cropper-box{
flex: 1;
width: 100%;
.cropper{
width: auto;
height: 300px;
}
}
.show-preview{
flex: 1;
-webkit-flex: 1;
display: flex;
display: -webkit-flex;
justify-content: center;
.preview{
overflow: hidden;
border:1px solid #67c23a;
background: #cccccc;
}
}
}
.footer-btn{
margin-top: 30px;
display: flex;
display: -webkit-flex;
justify-content: space-between;
.scope-btn{
display: flex;
display: -webkit-flex;
justify-content: space-between;
padding-right: 10px;
}
.upload-cropper-btn{
flex: 1;
-webkit-flex: 1;
display: flex;
display: -webkit-flex;
justify-content: flex-end;
}
.btn {
outline: none;
display: inline-block;
line-height: 1;
white-space: nowrap;
cursor: pointer;
-webkit-appearance: none;
text-align: center;
-webkit-box-sizing: border-box;
box-sizing: border-box;
outline: 0;
-webkit-transition: .1s;
transition: .1s;
font-weight: 500;
padding: 8px 15px;
font-size: 12px;
border-radius: 3px;
color: #fff;
background-color: #409EFF;
border-color: #409EFF;
margin-right: 10px;
}
}
</style>

84
src/views/visualCheck/checkManage/paramSetting/index.vue

@ -104,6 +104,51 @@
<div v-else-if="servicesDisplayed && !isAllServicesRunning" class="service-bottom-text" :class="{ 'fade-in': servicesDisplayed &&!isAllServicesRunning }" style="color: #ED4A41;">请尽快联系系统维护人员进行恢复</div> <div v-else-if="servicesDisplayed && !isAllServicesRunning" class="service-bottom-text" :class="{ 'fade-in': servicesDisplayed &&!isAllServicesRunning }" style="color: #ED4A41;">请尽快联系系统维护人员进行恢复</div>
</div> </div>
</el-dialog> </el-dialog>
<div class="cropper-app">
<el-form ref="formValidate" :model="formValidate" :rules="ruleValidate" label-width="100px" class="demo-ruleForm">
<el-form-item label="照片上传" prop="mainImage">
<div class="list-img-box">
<div v-if="formValidate.mainImage !== ''">
<img :src="formValidate.mainImage" style="width:300px;height:150px" alt="图书" @click="showCoverPreview(formValidate.mainImage)">
</div>
<!-- <div class="upload-btn" style="height: 120px;" @click="uploadPicture('flagImg')">
<i class="el-icon-plus" style="font-size: 30px;" />
<span>照片上传</span>
</div> -->
<div class="upload-zip" @click="uploadPicture('flagImg')"><i class="iconfont icon-shangchuan2" />{{ isMobile ? '拍照上传':'上传文件' }}</div>
</div>
<input v-model="formValidate.mainImage" type="hidden" placeholder="请添加照片">
</el-form-item>
</el-form>
<!-- 剪裁组件弹窗 -->
<el-dialog
title="裁切照片"
:close-on-click-modal="false"
:modal-append-to-body="false"
append-to-body
:visible.sync="cropperModel"
width="950px"
center
>
<cropper-image
ref="child"
@uploadImgSuccess="handleUploadSuccess"
/>
</el-dialog>
<!--查看大图-->
<el-dialog
:close-on-click-modal="false"
:modal-append-to-body="false"
append-to-body
title="查看大图"
:visible.sync="imgVisible"
center
>
<img v-if="imgVisible" :src="imgName" style="width: 100%" alt="查看">
</el-dialog>
</div>
</div> </div>
</template> </template>
@ -113,12 +158,13 @@ import { encrypt } from '@/utils/rsaEncrypt'
import { verifyMaintenance } from '@/api/system/param' import { verifyMaintenance } from '@/api/system/param'
import CRUD, { presenter, header, form, crud } from '@crud/crud' import CRUD, { presenter, header, form, crud } from '@crud/crud'
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
import CropperImage from '../mobileCheck/module/corpper.vue'
const defaultForm = { ip: '', maxNum: null } const defaultForm = { ip: '', maxNum: null }
export default { export default {
name: 'ParamSetting', name: 'ParamSetting',
components: { },
components: { CropperImage },
cruds() { cruds() {
return CRUD({ return CRUD({
title: '参数设置', title: '参数设置',
@ -175,7 +221,20 @@ export default {
serviceItems: [], serviceItems: [],
currentIndex: -1, currentIndex: -1,
timer: null, timer: null,
servicesDisplayed: false
servicesDisplayed: false,
formValidate: {
mainImage: ''
},
ruleValidate: {
mainImage: [
{ required: true, message: '请上传照片', trigger: 'blur' }
]
},
//
cropperModel: false,
imgName: '',
imgVisible: false
} }
}, },
computed: { computed: {
@ -195,6 +254,27 @@ export default {
} }
}, },
methods: { methods: {
//
uploadPicture() {
this.cropperModel = true
},
//
handleUploadSuccess(data) {
console.log(data)
this.formValidate.mainImage = data.url
// switch (data.name) {
// case 'flagImg':
// this.formValidate.mainImage = 'http://ydfblog.cn/dfs/' + data.url
// console.log('' + data.name)
// break
// }
this.cropperModel = false
},
//
showCoverPreview(imgSrc) {
this.imgVisible = true
this.imgName = imgSrc
},
initData() { initData() {
crudStockTask.FetchInitSetting().then(res => { crudStockTask.FetchInitSetting().then(res => {
this.crud.form.ip = res.ip this.crud.form.ip = res.ip

Loading…
Cancel
Save