Browse Source

推广

devlop
mo-bai 4 years ago
parent
commit
ac42a9af5a
32 changed files with 2816 additions and 78 deletions
  1. 38
      App.vue
  2. 81
      apis/deviceApi.js
  3. 11
      apis/factoryApi.js
  4. 2
      components/qn-easyinput/qn-easyinput.vue
  5. 104
      components/qn-select/qn-select.vue
  6. 38
      enums/index.js
  7. 31
      pages.json
  8. 92
      pages/complete-info/EnterpriseForm.vue
  9. 30
      pages/complete-info/index.vue
  10. 177
      pages/device-info/index.vue
  11. 409
      pages/device-operation/index.vue
  12. 471
      pages/device-production-detail/index.vue
  13. 70
      pages/digital-workshops/EmptyData.vue
  14. 712
      pages/digital-workshops/index.vue
  15. 77
      pages/page-view/index.vue
  16. 128
      pages/promotion/Banner.vue
  17. 407
      pages/promotion/index.vue
  18. BIN
      static/imgs/.DS_Store
  19. BIN
      static/imgs/digital-workshops/add-icon.png
  20. BIN
      static/imgs/digital-workshops/clock.png
  21. BIN
      static/imgs/digital-workshops/device-detail-bg.png
  22. BIN
      static/imgs/digital-workshops/down-arrow-icon.png
  23. BIN
      static/imgs/digital-workshops/gear.png
  24. BIN
      static/imgs/digital-workshops/no-camera.png
  25. BIN
      static/imgs/digital-workshops/toggle-icon.png
  26. BIN
      static/imgs/general/camera-bg.png
  27. BIN
      static/imgs/general/line-share-icon.png
  28. BIN
      static/imgs/general/select-icon.png
  29. BIN
      static/imgs/general/selected-icon.png
  30. BIN
      static/imgs/general/session-share-icon.png
  31. BIN
      static/imgs/promotion/video-close.png
  32. 16
      utils/hook.js

38
App.vue

@ -17,25 +17,25 @@ export default {
//#ifdef APP-PLUS //#ifdef APP-PLUS
checkUpdate().then((version) => { checkUpdate().then((version) => {
let curVersion = plus.runtime.version let curVersion = plus.runtime.version
if (version != curVersion) {
let client = uni.getSystemInfoSync().platform
if (client === 'ios') {
uni.showModal({
title: '更新提示',
content: '有新的版本更新,请前往App Store更新'
})
} else {
uni.showModal({
title: '更新提示',
content: '有新版本,请前往更新',
success: (res) => {
if (res.confirm) {
// plus.runtime.openURL(`https://www.pgyer.com/ST8i`)
}
}
})
}
}
// if (version != curVersion) {
// let client = uni.getSystemInfoSync().platform
// if (client === 'ios') {
// uni.showModal({
// title: '',
// content: 'App Store'
// })
// } else {
// uni.showModal({
// title: '',
// content: '',
// success: (res) => {
// if (res.confirm) {
// // plus.runtime.openURL(`https://www.pgyer.com/ST8i`)
// }
// </span><span class="err"> pan> }
// })
// }
// }
}) })
//#endif //#endif
}, },

81
apis/deviceApi.js

@ -0,0 +1,81 @@
import http from '../utils/http/index.js'
/**
* 获取设备类型
*/
export function getDeviceTypeList(data = {}) {
return http.get({
url: '/base-paper-trading/get/mechanical-equipment/type',
data
})
}
/**
* 获取生产工艺列表
*/
export function getTechnicsList(data = {}) {
return http.get({
url: '/base-paper-trading/get/technics/type',
data
})
}
/**
* 添加或修改设备
*/
export function changeDevice(data = {}) {
return http.post({
url: '/base-paper-trading/save/mechanical-equipment',
data
})
}
/**
* 获取设备列表
*/
export function getDeviceList(data = {}) {
return http.get({
url: '/base-paper-trading/get/mechanical-equipment/list',
data
})
}
/**
* 印包客监控台获取设备类型统计数据
*/
export function getEquipmentStatistics(data = {}) {
return http.get({
url: '/base-paper-trading/get/mechanical-equipment/type-statistics/list',
data
})
}
/**
* 设备生产详情分享
*/
export function makeDeviceShare(data = {}) {
return http.post({
url: '/base-paper-trading/create/mechanical-equipment/share',
data
})
}
/**
* 推广界面获取设备列表
*/
export function getEquipmentList(data = {}) {
return http.get({
url: '/base-paper-trading/get/mechanical-equipment/list',
data
})
}
/**
* 获取设备信息
*/
export function getEquipmentInfo(data = {}) {
return http.get({
url: `/base-paper-trading/get/mechanical-equipment/${data.id}`,
data
})
}

11
apis/factoryApi.js

@ -21,3 +21,14 @@ export function savePersonalInfo(data = {}) {
data data
}) })
} }
/**
* 查询工厂信息
*
*/
export function getFactoryInfo(data = {}) {
return http.get({
url: `/yyt-uec/get/factory/information/${data.id}`,
data
})
}

2
components/qn-easyinput/qn-easyinput.vue

@ -376,7 +376,7 @@ $uni-border-1: #dcdfe6 !default;
width: 100%; width: 100%;
display: flex; display: flex;
box-sizing: border-box; box-sizing: border-box;
// min-height: 36px;
min-height: 21px;
height: 100%; height: 100%;
/* #endif */ /* #endif */
flex-direction: row; flex-direction: row;

104
components/qn-select/qn-select.vue

@ -1,14 +1,14 @@
<template> <template>
<view>
<view style="width: 100%; height: 100%">
<view class="select-mask" v-show="visible" @click="hideOption"></view> <view class="select-mask" v-show="visible" @click="hideOption"></view>
<view class="select-section" @click="showOption">
<text :class="text ? '' : 'placeholder'">{{ text || placeholder }}</text>
<view class="select-section" :style="contentStyle" @click="showOption">
<text class="text" :class="label ? '' : 'placeholder'" :style="label ? '' : placeholderStyle">{{ label || placeholder }}</text>
<view class="icon"></view> <view class="icon"></view>
<view class="options-area" v-show="visible"> <view class="options-area" v-show="visible">
<slot> <slot>
<view class="option" v-for="item in options" :key="item.value" @click.stop="handleSelect(item)"> <view class="option" v-for="item in options" :key="item.value" @click.stop="handleSelect(item)">
<text>{{ item.label }}</text> <text>{{ item.label }}</text>
<view v-if="value == item.value" class="icon"></view>
<view v-show="isSelected(item.value)" class="icon"></view>
</view> </view>
</slot> </slot>
</view> </view>
@ -26,35 +26,102 @@ export default {
type: String, type: String,
default: '请选择' default: '请选择'
}, },
/**
* 下拉框选项
* @param {Object} item
* @property {String} label - 选项名称
* @property {String} value - 选项值
*/
options: { options: {
type: Array, type: Array,
default: () => [] default: () => []
},
placeholderStyle: {
type: String,
default: ''
},
/**
* 指向select-section的样式
*/
contentStyle: {
type: String,
default: ''
},
/**
* 是否多选
*/
multiple: {
type: Boolean,
default: false
} }
}, },
data() { data() {
return { return {
visible: false, visible: false,
text: ''
label: ''
} }
}, },
methods: { methods: {
handleSelect(item) { handleSelect(item) {
this.text = item.label
this.$emit('input', item.value)
this.hideOption()
if (this.multiple) {
let value = []
if (!this.value) {
value = []
} else {
value = [...this.value]
}
const index = value.indexOf(item.value)
if (index > -1) {
value.splice(index, 1)
} else {
value.push(item.value)
}
this.$emit('input', value)
} else {
this.hideOption()
this.$emit('input', item.value)
}
}, },
showOption() { showOption() {
this.visible = true this.visible = true
}, },
hideOption() { hideOption() {
console.log('hideOption')
this.visible = false this.visible = false
},
isSelected(value) {
if (this.multiple) {
return this.value.indexOf(value) > -1
} else {
return this.value === value
}
},
/**
* 处理外层val或options改变的情况
*/
handleChange(val, options) {
if (this.multiple) {
let labelList = []
for (let value of val) {
const item = options.find((item) => item.value === value)
if (item) {
labelList.push(item.label)
} else {
labelList.push(' ')
}
}
this.label = labelList.join(' , ')
} else {
let target = options.find((o) => o.value === val)
this.label = target?.label || ''
}
} }
}, },
watch: { watch: {
value(val) { value(val) {
let target = this.options.find((o) => o.value === val)
this.text = target?.label || ''
this.handleChange(val, this.options)
},
options(val) {
this.handleChange(this.value, val)
} }
} }
} }
@ -64,10 +131,12 @@ export default {
.select-section { .select-section {
width: 100%; width: 100%;
height: 100%; height: 100%;
min-height: 64rpx;
// min-height: 64rpx;
position: relative; position: relative;
// fixed
transform: translateX(0); transform: translateX(0);
z-index: 300;
// z-index: 300;
z-index: 90;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
@ -78,11 +147,18 @@ export default {
padding: 12rpx 24rpx; padding: 12rpx 24rpx;
background-color: rgb(245, 245, 245); background-color: rgb(245, 245, 245);
border-radius: 8rpx; border-radius: 8rpx;
.text {
flex: 1 1 auto;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.icon { .icon {
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADgAAAAgCAYAAABHA7voAAACtklEQVRYhdXYOW8TQRgG4CcxBHIQTA5uCCDRICSoKChB3MefBYmjpYCCDjokEnIQEDRIiPsqPltJjGe8a++G8EpWJPvLeB7P7OzsDGEIZ3AK27GEx/js/8oUzmMWH/EU80M4i3MdxR9wB582s4cDZB+uiwFan7sNXMBIxwc7cRQv8aP27g2WWYHrNEBj2N/qdpq4IbBbNTOij91wMNLAtJi/3TKKQ2Ikf1bevcEyJXA7MjXPG3iD45nCMVsP2cQt+dm1iCcNcY3N45g0chwHBPJXdf3sK7sFbjRTs4yH+NVovfEdC5iTRk5gv3+LnBS48UzNMh5ozbbGug++CWRuJHdhrxjxzUZOCNxEpmYDjo1AiiEnxeo1j999drZsxnFb/MCptKflhnWiE0gx5G6x+m4GckyM3GSmpo37657dDUgxZLP1WlAfclTgmpmaJI40kEC+EreQ1I10j/hlF3r1tI/sxM3Wd6SSxZEHsjaSOeSUuDZe9WirTHYI3HSmZkUPHL2BFENOi4VgsUB7vTIicDOZmhWxWvbcJxcBUgw5I6bVUsE2u2VEbJxnMzWFcRQHsnZNHpNG7hWb9+US7bazHdfEo08qpXCUA8JXvReefa12V0q0uw1XxXYwldI4ygMphtzf+rtasA9XxIY+ldf6wLUb7ydFkAfFruJNj++/jCOZmte4r88H736BFEMeEhv5t10+G8YlcXKQykA4BgMSyEWckD4ZOIwveLfuvWFcFAtWKgPjGBzI2kjmkEfFAdZ7cYp3oVWfSiU4qgFSDDknjvNO42SmrcpwxK9ZZZpiFzLW5/9XiqO6EWzni7gmj0uPZCqrKsZRPZA1ZG66dmYV99RwBlsHkHLI2nDUB6QYspZpuT51Agnkku4b9Pbe8nudHagbSCBfiOfFMfFU8gyPbJ2D5P83fwA+SqvvLFrSmAAAAABJRU5ErkJggg==') background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADgAAAAgCAYAAABHA7voAAACtklEQVRYhdXYOW8TQRgG4CcxBHIQTA5uCCDRICSoKChB3MefBYmjpYCCDjokEnIQEDRIiPsqPltJjGe8a++G8EpWJPvLeB7P7OzsDGEIZ3AK27GEx/js/8oUzmMWH/EU80M4i3MdxR9wB582s4cDZB+uiwFan7sNXMBIxwc7cRQv8aP27g2WWYHrNEBj2N/qdpq4IbBbNTOij91wMNLAtJi/3TKKQ2Ikf1bevcEyJXA7MjXPG3iD45nCMVsP2cQt+dm1iCcNcY3N45g0chwHBPJXdf3sK7sFbjRTs4yH+NVovfEdC5iTRk5gv3+LnBS48UzNMh5ozbbGug++CWRuJHdhrxjxzUZOCNxEpmYDjo1AiiEnxeo1j999drZsxnFb/MCptKflhnWiE0gx5G6x+m4GckyM3GSmpo37657dDUgxZLP1WlAfclTgmpmaJI40kEC+EreQ1I10j/hlF3r1tI/sxM3Wd6SSxZEHsjaSOeSUuDZe9WirTHYI3HSmZkUPHL2BFENOi4VgsUB7vTIicDOZmhWxWvbcJxcBUgw5I6bVUsE2u2VEbJxnMzWFcRQHsnZNHpNG7hWb9+US7bazHdfEo08qpXCUA8JXvReefa12V0q0uw1XxXYwldI4ygMphtzf+rtasA9XxIY+ldf6wLUb7ydFkAfFruJNj++/jCOZmte4r88H736BFEMeEhv5t10+G8YlcXKQykA4BgMSyEWckD4ZOIwveLfuvWFcFAtWKgPjGBzI2kjmkEfFAdZ7cYp3oVWfSiU4qgFSDDknjvNO42SmrcpwxK9ZZZpiFzLW5/9XiqO6EWzni7gmj0uPZCqrKsZRPZA1ZG66dmYV99RwBlsHkHLI2nDUB6QYspZpuT51Agnkku4b9Pbe8nudHagbSCBfiOfFMfFU8gyPbJ2D5P83fwA+SqvvLFrSmAAAAABJRU5ErkJggg==')
no-repeat center center/cover; no-repeat center center/cover;
width: 28rpx; width: 28rpx;
height: 16rpx; height: 16rpx;
margin-left: 16rpx;
} }
} }
.select-mask { .select-mask {
@ -90,7 +166,7 @@ export default {
height: 100vh; height: 100vh;
background-color: transparent; background-color: transparent;
position: fixed; position: fixed;
z-index: 200;
z-index: 80;
top: 0; top: 0;
left: 0; left: 0;
right: 0; right: 0;

38
enums/index.js

@ -5,12 +5,19 @@ export const XAPPID = '503258978847966407'
export const H5_URL = `https://printpackage${urlEnv}.qniao.cn` export const H5_URL = `https://printpackage${urlEnv}.qniao.cn`
export const H5_URL_STORE = `${H5_URL}/#/pages/store/index?share=true&`
export const H5_URL_PAPER = `${H5_URL}/#/pages/paper-details/index?share=true&`
export const H5_URL_DEVICE = `${H5_URL}/#/pages/certification/index?`
// 统一支付接口 // 统一支付接口
export const PAY_URL = `https://api-client-psc${urlEnv}.qniao.cn/payment-settlement-center/pay` export const PAY_URL = `https://api-client-psc${urlEnv}.qniao.cn/payment-settlement-center/pay`
/**
* 萤石云直播地址
* @param {string} accessToken 访问令牌
* @param {string} deviceSerial 设备序列号
* @param {string} channelNo 通道号
*/
export const YINGSHI_LIVE_URL = `https://open.ys7.com/ezopen/h5/live?autoplay=1&audio=1&hd=1&`
/** /**
* 企业类型: 印刷包装厂 2 供应商 5 个人 8 * 企业类型: 印刷包装厂 2 供应商 5 个人 8
*/ */
@ -20,6 +27,13 @@ export const enterpriseType = {
PERSONAL: 8 PERSONAL: 8
} }
/**
* 设备状态: 空闲中 1 工作中 2
*/
export const deviceStatus = {
FREE: 1,
WORKING: 2
}
/** /**
* 账号类型 * 账号类型
*/ */
@ -64,8 +78,26 @@ export const fddEnterpriseStatus = {
export const uploadUrl = { export const uploadUrl = {
image: `https://api-client-yyt${urlEnv}.qniao.cn/yyt-uec/file-uploading/upload/image`, image: `https://api-client-yyt${urlEnv}.qniao.cn/yyt-uec/file-uploading/upload/image`,
file: `https://api-client-yyt${urlEnv}.qniao.cn/yyt-uec/file-uploading/upload/file`, file: `https://api-client-yyt${urlEnv}.qniao.cn/yyt-uec/file-uploading/upload/file`,
video: `https://api-client-yyt${urlEnv}.qniao.cn/yyt-uec/file-uploading/upload/file?type=mp4`
// video: `https://api-client-yyt${urlEnv}.qniao.cn/yyt-uec/file-uploading/upload/file?type=mp4`
video: `https://api-client-yyt${urlEnv}.qniao.cn/yyt-uec/file-uploading/upload/video/file?type=mp4`
} }
/**
* 文件类型 图片1视频2
*/
export const fileType = {
IMG: 1,
VIDEO: 2
}
/**
* 是否加密 不加密0 加密1
*/
export const isEncrypt = {
NO: 0,
YES: 1
}
/** /**
* 结算周期1月结30飞算1期2月结453月结60飞算2期4月结755月结90飞算3期 * 结算周期1月结30飞算1期2月结453月结60飞算2期4月结755月结90飞算3期
*/ */

31
pages.json

@ -19,6 +19,22 @@
"navigationStyle": "custom" "navigationStyle": "custom"
} }
}, },
{
"path": "pages/device-operation/index",
"style": {
"navigationBarTitleText": "设备操作",
"enablePullDownRefresh": false,
"navigationStyle": "custom"
}
},
{
"path": "pages/device-production-detail/index",
"style": {
"navigationBarTitleText": "生产详情",
"enablePullDownRefresh": false,
"navigationStyle": "custom"
}
},
{ {
"path": "pages/promotion/index", "path": "pages/promotion/index",
"style": { "style": {
@ -27,6 +43,14 @@
"navigationStyle": "custom" "navigationStyle": "custom"
} }
}, },
{
"path": "pages/device-info/index",
"style": {
"navigationBarTitleText": "设备信息",
"enablePullDownRefresh": false,
"navigationStyle": "custom"
}
},
{ {
"path": "pages/mall/index", "path": "pages/mall/index",
"style": { "style": {
@ -66,6 +90,13 @@
"enablePullDownRefresh": false, "enablePullDownRefresh": false,
"navigationStyle": "custom" "navigationStyle": "custom"
} }
},
{
"path": "pages/page-view/index",
"style": {
"navigationBarTitleText": "统一第三方页面",
"enablePullDownRefresh": false
}
} }
], ],
"globalStyle": { "globalStyle": {

92
pages/complete-info/EnterpriseForm.vue

@ -100,11 +100,11 @@
<view class="flex-row group_10"> <view class="flex-row group_10">
<text class="text_19">工厂视频(可选)</text> <text class="text_19">工厂视频(可选)</text>
</view> </view>
<view class="video-area" v-if="videoUrl">
<view class="video-area" v-if="video.fileUrl">
<image class="video__close-icon" @click="clearVideo" src="/static/imgs/general/close-icon.png"></image> <image class="video__close-icon" @click="clearVideo" src="/static/imgs/general/close-icon.png"></image>
<video :src="videoUrl" class="video"></video>
<video :src="video.fileUrl" class="video"></video>
</view> </view>
<view v-show="!videoUrl" class="flex-col items-center section_4" @click="selectVideo">
<view v-show="!video.fileUrl" class="flex-col items-center section_4" @click="selectVideo">
<image src="/static/imgs/general/camera-icon.png" class="image_6" /> <image src="/static/imgs/general/camera-icon.png" class="image_6" />
<text class="text_20">点击上传</text> <text class="text_20">点击上传</text>
</view> </view>
@ -130,6 +130,8 @@
import { getArea, getLicenseOcr } from '@/apis/commonApi.js' import { getArea, getLicenseOcr } from '@/apis/commonApi.js'
import { uploadImage, uploadVideo } from '@/utils/hook.js' import { uploadImage, uploadVideo } from '@/utils/hook.js'
import { validateField } from '@/utils/index.js' import { validateField } from '@/utils/index.js'
import { fileType } from '@/enums/index.js'
import { getFactoryInfo } from '@/apis/factoryApi.js'
const validateFields = [ const validateFields = [
{ {
@ -173,12 +175,12 @@ const validateFields = [
} }
] ]
const fileType = {
IMG: 1,
VIDEO: 2
}
export default { export default {
props: {
id: {
type: [Number, String]
}
},
data() { data() {
return { return {
form: { form: {
@ -201,7 +203,47 @@ export default {
}, },
items: [], items: [],
imgList: [], imgList: [],
videoUrl: null
video: {
fileUrl: null,
videoPicUrl: null
},
operation: 'add'
}
},
created() {
if (this.id) {
getFactoryInfo({ id: this.id }).then((res) => {
if (res) {
this.operation = 'edit'
for (let key in this.form) {
this.form[key] = res[key]
}
this.form.id = res.id
//
this.form.imgItemList = []
this.imgList = res.imgItemList.filter((item) => item.type == fileType.IMG).map((item) => item.fileUrl)
let video = res.imgItemList.find((item) => item.type == fileType.VIDEO)
if (video) {
this.video.fileUrl = video.fileUrl
this.video.videoPicUrl = video.videoPicUrl
}
}
})
}
},
mounted() {
getArea().then((res) => {
if (res) {
this.items = res
}
})
},
watch: {
imgList(val) {
this.form.imgItemList = val.map((url) => ({
fileUrl: url,
type: fileType.IMG
}))
} }
}, },
methods: { methods: {
@ -242,10 +284,11 @@ export default {
} }
} }
// imgItemList // imgItemList
if (this.videoUrl) {
if (this.video.fileUrl) {
this.form.imgItemList.push({ this.form.imgItemList.push({
type: fileType.VIDEO, type: fileType.VIDEO,
imgUrl: this.videoUrl
fileUrl: this.video.fileUrl,
videoPicUrl: this.video.videoPicUrl
}) })
} }
return this.form return this.form
@ -273,9 +316,10 @@ export default {
}, },
selectVideo() { selectVideo() {
uploadVideo() uploadVideo()
.then((url) => {
if (url) {
this.videoUrl = url
.then((video) => {
if (video) {
this.video.fileUrl = video.url
this.video.videoPicUrl = video.thumb
} }
}) })
.catch((e) => { .catch((e) => {
@ -286,7 +330,10 @@ export default {
}) })
}, },
clearVideo() { clearVideo() {
this.videoUrl = ''
this.video = {
fileUrl: null,
videoPicUrl: null
}
}, },
clearImage(index) { clearImage(index) {
this.imgList.splice(index, 1) this.imgList.splice(index, 1)
@ -307,21 +354,6 @@ export default {
current: url current: url
}) })
} }
},
mounted() {
getArea().then((res) => {
if (res) {
this.items = res
}
})
},
watch: {
imgList(val) {
this.form.imgItemList = val.map((url) => ({
imgUrl: url,
type: fileType.IMG
}))
}
} }
} }
</script> </script>

30
pages/complete-info/index.vue

@ -4,7 +4,7 @@
<image src="/static/imgs/general/back-icon.png" class="image" @click="back" /> <image src="/static/imgs/general/back-icon.png" class="image" @click="back" />
<text>完善信息</text> <text>完善信息</text>
</view> </view>
<enterprise-form ref="enterpriseForm" v-if="role == 'enterprise'"></enterprise-form>
<enterprise-form ref="enterpriseForm" v-if="role == 'enterprise'" :id="factoryId"></enterprise-form>
<person-form ref="personForm" v-if="role == 'person'"></person-form> <person-form ref="personForm" v-if="role == 'person'"></person-form>
<qn-footer fixed> <qn-footer fixed>
<view class="flex-col items-center text-wrapper_1" @click="save"> <view class="flex-col items-center text-wrapper_1" @click="save">
@ -27,7 +27,13 @@ export default {
}, },
data() { data() {
return { return {
role: 'person'
/**
* @description 当前角色
* @value person | enterprise
*/
role: 'person',
companyId: null,
factoryId: null
} }
}, },
methods: { methods: {
@ -69,11 +75,18 @@ export default {
if (this.role == 'person') { if (this.role == 'person') {
this.validatePerson() this.validatePerson()
} }
},
getCompanyInfo() {
if (this.role == 'enterprise') {
this.factoryId = this.companyId
}
// if(this.role == 'person') {
// }
} }
}, },
computed: { computed: {
translateBg() { translateBg() {
console.log('role', this.role)
if (this.role == 'enterprise') { if (this.role == 'enterprise') {
return 'url(https://qncloud.oss-cn-shenzhen.aliyuncs.com/print-package-app/complete-factory.png)' return 'url(https://qncloud.oss-cn-shenzhen.aliyuncs.com/print-package-app/complete-factory.png)'
} }
@ -89,11 +102,20 @@ export default {
title: '角色未选择,即将跳转', title: '角色未选择,即将跳转',
icon: 'none' icon: 'none'
}) })
setTimeout(() => { setTimeout(() => {
go2('select-role', {}, true)
if (options.id) {
back()
} else {
go2('select-role', {}, true)
}
}, 1000) }, 1000)
} else { } else {
this.role = options.role this.role = options.role
if (options.id) {
this.companyId = options.id
this.getCompanyInfo()
}
} }
} }
} }

177
pages/device-info/index.vue

@ -0,0 +1,177 @@
<template>
<view class="content">
<uni-nav-bar left-icon="back" @clickLeft="back" statusBar fixed title="授信记录"></uni-nav-bar>
<view class="flex-col group_4">
<view class="flex-col group_5">
<view class="flex-col items-center group_6">
<swiper class="swiper" @change="changeSwiper">
<swiper-item v-for="(item, index) in info.imgItemList" :key="index">
<image mode="aspectFit" :src="item.url" class="image" @click="preview(item.url)" />
</swiper-item>
</swiper>
<view class="flex-col items-center text-wrapper">
<text>{{ swiperCurrent + 1 }}/{{ info.imgItemList.length }}</text>
</view>
</view>
<view class="flex-col section_1">
<text class="text_5">{{ info.name || '设备' }}</text>
<text class="text_6">
{{ info.machineDescribe || '没有描述' }}
</text>
</view>
</view>
<view class="flex-row section_2">
<view class="flex-col items-center text-wrapper_1" @click="deleteDevice">
<text>删除</text>
</view>
<view class="flex-col items-center text-wrapper_2" @click="go2('device-operation', { operation: 'edit', id: info.id })">
<text>编辑</text>
</view>
</view>
</view>
</view>
</template>
<script>
import { go2, back } from '@/utils/hook.js'
import { getEquipmentInfo } from '@/apis/deviceApi.js'
export default {
data() {
return {
info: { imgItemList: [] },
id: null,
swiperCurrent: 1
}
},
onLoad(options) {
if (options.id) {
this.id = options.id
}
},
created() {
if (this.id) {
getEquipmentInfo({ id: this.id }).then((res) => {
if (res) {
this.info = res
}
})
}
},
methods: {
go2,
back,
changeSwiper(e) {
this.swiperCurrent = e.detail.current
},
preview(url) {
let urls = info.imgItemList.map((img) => img.url)
uni.previewImage({
current: url,
urls: urls
})
},
//
deleteDevice() {}
}
}
</script>
<style lang="scss" scoped>
.content {
width: 750rpx;
.group_4 {
flex: 1 1 auto;
overflow-y: auto;
.group_5 {
.group_6 {
width: 750rpx;
height: 440rpx;
.swiper {
width: 100%;
height: 100%;
.image {
width: 100%;
height: 100%;
background-color: rgb(0, 0, 0);
}
}
color: rgb(255, 255, 255);
font-size: 28rpx;
line-height: 40rpx;
white-space: nowrap;
position: relative;
.text-wrapper {
background-color: rgba(0, 0, 0, 0.4);
border-radius: 20rpx;
width: 64rpx;
position: absolute;
right: 32rpx;
bottom: 60rpx;
}
}
.section_1 {
margin-top: -40rpx;
padding: 32rpx 30rpx 100rpx 32rpx;
background-image: linear-gradient(
180deg,
rgb(255, 255, 255) 0%,
rgb(255, 255, 255) 0%,
rgb(253, 253, 254) 30.62%,
rgba(247, 248, 250, 0) 100%,
rgba(247, 248, 250, 0) 100%
);
border-radius: 40rpx 40rpx 0px 0px;
position: relative;
.text_5 {
color: rgb(0, 0, 0);
font-size: 36rpx;
font-weight: 500;
line-height: 50rpx;
white-space: nowrap;
}
.text_6 {
margin-top: 20rpx;
color: rgb(51, 51, 51);
font-size: 26rpx;
line-height: 37rpx;
text-align: left;
}
}
}
.section_2 {
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding: 16rpx 28rpx;
background-color: rgb(255, 255, 255);
.text-wrapper_1 {
padding: 21rpx 0;
color: rgb(245, 34, 45);
font-size: 30rpx;
font-weight: 500;
line-height: 42rpx;
white-space: nowrap;
border-radius: 10rpx;
width: 270rpx;
height: 88rpx;
border: solid 2rpx rgb(245, 34, 45);
}
.text-wrapper_2 {
margin-left: 24rpx;
padding: 23rpx 0;
flex: 1 1 auto;
color: rgb(255, 255, 255);
font-size: 30rpx;
font-weight: 500;
line-height: 42rpx;
white-space: nowrap;
background-color: rgb(0, 122, 255);
border-radius: 10rpx;
height: 88rpx;
}
}
}
}
</style>

409
pages/device-operation/index.vue

@ -0,0 +1,409 @@
<template>
<view class="content">
<uni-nav-bar left-icon="back" @clickLeft="back" statusBar fixed :title="operation == 'add' ? '新增设备' : '编辑设备'"></uni-nav-bar>
<view class="form">
<view class="flex-col group_9">
<view class="flex-row group_10">
<text class="text_18">*</text>
<text class="text_19">设备图片</text>
<text class="tip">(图片单张大小不超过2M数量最多5张)</text>
</view>
<view class="flex-row">
<view v-for="(item, index) in form.imgItemList" :key="item.url" class="image-area">
<image class="image__close-icon" @click="clearImage(index)" src="/static/imgs/general/close-icon.png"></image>
<image :src="item.url" class="upload_image" @click="preview(item.url)"></image>
</view>
<view v-show="form.imgItemList.length < 5" class="flex-col items-center section_4" @click="selectImg">
<image src="/static/imgs/general/camera-icon.png" class="image_6" />
<text class="text_20">点击上传</text>
</view>
</view>
</view>
<view class="divider"></view>
<view class="justify-between group">
<view class="flex-row">
<text class="text_1">*</text>
<text class="text_2">设备名称</text>
</view>
<qn-easyinput
:maxlength="20"
v-model="form.name"
:inputBorder="false"
text="right"
placeholderStyle="fontSize: 28rpx"
placeholder="请输入设备名称"
></qn-easyinput>
</view>
<view class="divider"></view>
<view class="justify-between group">
<view class="flex-row">
<text class="text_2">设备类型</text>
</view>
<view style="width: 400rpx; z-index: 2">
<qn-select
:placeholderStyle="placeholderStyle"
contentStyle="background: none; padding: 0;text-align: right;"
:options="deviceTypeList"
v-model="form.type"
placeholder="请选择设备类型"
></qn-select>
</view>
</view>
<view class="divider"></view>
<view class="justify-between group">
<view class="flex-row">
<text class="text_2">生产工艺</text>
</view>
<view style="width: 400rpx; z-index: 1">
<qn-select
:placeholderStyle="placeholderStyle"
contentStyle="background: none; padding: 0;text-align: right;"
:options="technicsTypeList"
v-model="form.technicsTypeList"
placeholder="请选择设备支持的生产类型"
multiple
></qn-select>
</view>
</view>
<view class="divider"></view>
<view class="group">
<view class="flex-row">
<text class="text_1">*</text>
<text class="text_2">设备描述</text>
</view>
<qn-easyinput
:maxlength="200"
v-model="form.machineDescribe"
type="textarea"
placeholderStyle="fontSize: 28rpx "
placeholder="请输入设备介绍"
style="background-color: rgb(247, 248, 250); margin-top: 16rpx"
></qn-easyinput>
</view>
<view class="divider"></view>
<view class="justify-between group">
<view class="flex-row">
<text class="text_2">摄像头ID</text>
</view>
<qn-easyinput
:maxlength="20"
v-model="form.cameraId"
:inputBorder="false"
text="right"
placeholderStyle=" fontSize: 28rpx"
placeholder="请输入摄像头ID"
></qn-easyinput>
</view>
<view class="divider"></view>
<view class="justify-between group">
<view class="flex-row">
<text class="text_2">摄像头渠道号</text>
</view>
<qn-easyinput
:maxlength="20"
v-model="form.channelNum"
:inputBorder="false"
text="right"
type="number"
placeholderStyle=" fontSize: 28rpx"
placeholder="请输入摄像头渠道号"
></qn-easyinput>
</view>
<view class="divider"></view>
<view class="justify-between group">
<view class="flex-row">
<text class="text_2">云盒ID</text>
</view>
<qn-easyinput
:maxlength="20"
v-model="form.cloudBoxId"
:inputBorder="false"
text="right"
placeholderStyle=" fontSize: 28rpx"
placeholder="请输入云盒ID"
></qn-easyinput>
</view>
</view>
<qn-footer fixed>
<view class="flex-col items-center text-wrapper_1" @click="save">
<text>保存</text>
</view>
</qn-footer>
</view>
</template>
<script>
import { go2, back, uploadImage } from '@/utils/hook.js'
import { validateField } from '@/utils/index.js'
import { fileType } from '@/enums/index.js'
import { getDeviceTypeList, getTechnicsList, changeDevice, getEquipmentInfo } from '@/apis/deviceApi.js'
const validateFields = [
{
name: 'imgItemList',
rules: [{ required: true, message: '请上传设备图片' }]
},
{
name: 'name',
rules: [{ required: true, message: '请输入设备名称' }]
},
{
name: 'machineDescribe',
rules: [{ required: true, message: '请输入设备描述' }]
}
]
export default {
data() {
return {
operation: 'add', // add:, edit:
deviceId: null,
form: {
id: null,
imgItemList: [],
machineDescribe: '',
cameraId: '',
channelNum: '',
cloudBoxId: '',
name: '',
type: '',
technicsTypeList: []
},
deviceTypeList: [],
technicsTypeList: [],
placeholderStyle: 'font-size: 28rpx;font-weight:400;'
}
},
watch: {
'form.type'(val) {
console.log('val:', val)
}
},
onLoad(options) {
if (options.operation) {
this.operation = options.operation
if (options.operation == 'edit') {
this.init(options.id)
}
} else {
uni.showToast({
title: '参数错误,即将返回',
icon: 'error',
duration: 2000,
mask: true,
success: () => {
setTimeout(() => {
back()
}, 2000)
}
})
}
},
created() {
getDeviceTypeList().then((res) => {
if (res) {
this.deviceTypeList = res.map((item) => ({ label: item.name, value: item.id }))
}
})
getTechnicsList().then((res) => {
if (res) {
this.technicsTypeList = res.map((item) => ({ label: item.name, value: item.id }))
}
})
},
methods: {
go2,
back,
clearImage(index) {
this.form.imgItemList.splice(index, 1)
},
//
init(id) {
getEquipmentInfo({ id }).then((res) => {
if (res) {
Object.keys(this.form).forEach((key) => {
this.form[key] = res[key]
})
this.form.technicsTypeList = res.technicsTypeList.map((item) => item.id + '')
}
})
},
preview(url) {
uni.previewImage({
urls: [url],
current: url
})
},
selectImg() {
uploadImage()
.then((urls) => {
if (urls) {
this.form.imgItemList.push({
url: urls[0],
type: fileType.IMG
})
}
})
.catch((e) => {
uni.showToast({
title: '上传失败:' + (e.message || e),
icon: 'fail',
duration: 1500
})
})
},
save() {
for (let field of validateFields) {
const { name, rules } = field
const value = this.form[name]
const { isValid, msg } = validateField(value, rules)
if (!isValid) {
uni.showToast({
title: msg,
icon: 'none'
})
return false
}
}
if (this.form.cameraId) {
if (!this.form.channelNum) {
uni.showToast({
title: '请输入摄像头渠道号',
icon: 'none'
})
return false
}
}
let list = this.technicsTypeList.filter((item) => this.form.technicsTypeList.includes(item.value))
let technicsTypeList = list.map((item) => ({ id: item.value, name: item.label }))
changeDevice({ ...this.form, technicsTypeList }).then((res) => {
if (res) {
uni.showToast({
title: '保存成功',
icon: 'success',
duration: 1500
})
setTimeout(() => {
back()
}, 1500)
}
})
}
}
}
</script>
<style lang="scss" scoped>
.form {
width: 750rpx;
background-color: #fff;
}
.group {
padding: 24rpx 28rpx 24rpx 32rpx;
font-size: 28rpx;
line-height: 40rpx;
white-space: nowrap;
.text_3 {
color: rgb(0, 122, 255);
}
.text_1 {
color: rgb(245, 34, 45);
}
.text_2 {
margin-left: 4rpx;
color: rgb(0, 0, 0);
}
}
.divider {
margin: 0 28rpx;
background-color: rgb(216, 216, 216);
height: 2rpx;
}
.group_9 {
padding: 22rpx 32rpx 32rpx;
.group_10 {
padding-bottom: 16rpx;
.text_18 {
color: rgb(245, 34, 45);
font-size: 28rpx;
line-height: 40rpx;
white-space: nowrap;
}
.text_19 {
margin-left: 4rpx;
color: rgb(0, 0, 0);
font-size: 28rpx;
line-height: 40rpx;
white-space: nowrap;
}
.tip {
margin-left: 16rpx;
font-size: 24rpx;
line-height: 40rpx;
color: #858585;
}
}
.section_4 {
margin-left: 19rpx;
padding: 23rpx 0 13rpx;
color: rgb(76, 74, 88);
font-size: 26rpx;
line-height: 37rpx;
white-space: nowrap;
background-color: rgba(220, 222, 224, 0.5);
border-radius: 10rpx;
width: 120rpx;
.image_6 {
width: 42rpx;
height: 36rpx;
}
.text_20 {
margin-top: 12rpx;
}
}
}
.upload_image {
width: 120rpx;
height: 120rpx;
border-radius: 10rpx;
}
.video-area {
position: relative;
width: 686rpx;
.video__close-icon {
position: absolute;
top: 0;
right: 0;
width: 32rpx;
height: 32rpx;
z-index: 100;
}
.video {
width: 686rpx;
height: 450rpx;
}
}
.image-area {
position: relative;
margin-left: 19rpx;
width: 120rpx;
height: 120rpx;
border-radius: 10rpx;
.image__close-icon {
position: absolute;
top: 0;
right: 0;
width: 32rpx;
height: 32rpx;
z-index: 1;
}
}
.text-wrapper_1 {
margin: 0 32rpx;
padding: 23rpx 0;
background-color: rgb(0, 122, 255);
border-radius: 10rpx;
color: rgb(255, 255, 255);
}
</style>

471
pages/device-production-detail/index.vue

@ -0,0 +1,471 @@
<template>
<view class="content">
<uni-nav-bar left-icon="back" @clickLeft="back" statusBar fixed title="生产详情">
<view slot="right"><text class="text_4" @click="popupShow">分享</text></view>
</uni-nav-bar>
<view class="flex-col group_5">
<view class="flex-col section_1">
<view class="justify-between group_6">
<text class="text_5">生产数据</text>
<view class="flex-row group_7">
<qn-datetime-picker :border="false" type="daterange" @change="dateRangeChange">
<text>{{ (dateRange ? `${dateRange[0]}${dateRange[1]}` : '全部') | formatDate }}</text>
</qn-datetime-picker>
<image v-show="!dateRange" src="/static/imgs/digital-workshops/down-arrow-icon.png" class="image-icon" />
<image v-show="dateRange" @click="dateRangeChange(null)" src="/static/imgs/general/close-icon.png" class="image-icon" />
</view>
</view>
<view class="justify-between section_2">
<qn-select
contentStyle="background: none; padding: 14rpx 22rpx;text-align: left;"
:options="deviceList"
v-model="id"
placeholder="请选择设备"
></qn-select>
</view>
<view class="flex-row group_8">
<view class="flex-col section_3">
<text class="text_8">{{ curDevice.produceTotalNum }}</text>
<text class="text_9">产能/</text>
</view>
<view class="flex-col section_4">
<text class="text_10">{{ curDevice.totalWorkHour | formatNumber }}</text>
<text class="text_11">工作时长/h</text>
</view>
</view>
</view>
<view class="flex-col section_5">
<view class="flex-col items-center group_9" v-if="curDevice.cameraId">
<view class="camera_bg"></view>
<image @click="palyVideo()" src="/static/imgs/general/camera-bg.png" class="image_7" />
</view>
<view v-else>
<view class="flex-col items-center group_9">
<image mode="aspectFit" src="/static/imgs/digital-workshops/no-camera.png" />
</view>
</view>
</view>
</view>
<uni-popup ref="popup" type="bottom">
<view class="flex-col group_10">
<view class="flex-col section_7">
<view class="flex-col section_8">
<text class="text_12">立即分享给好友</text>
<view class="flex-col group_11">
<view class="top-group flex-row">
<image src="/static/imgs/general/session-share-icon.png" class="image_8" @click="share('WXSceneSession')" />
<image src="/static/imgs/general/line-share-icon.png" class="image_9" @click="share('WXSceneTimeline')" />
</view>
<view class="top-group flex-row view_1">
<text>微信好友</text>
<text class="text_14">朋友圈</text>
</view>
<view class="divider"></view>
<view class="flex-col section_9">
<view class="justify-between group_12">
<view class="flex-row group_13" @click="selectMethod(true)">
<image :src="hasPassword ? '/static/imgs/general/selected-icon.png' : '/static/imgs/general/select-icon.png'" class="image_10" />
<text class="text_15">密码分享</text>
</view>
<view class="flex-row group_14" v-show="hasPassword">
<qn-easyinput
:maxlength="20"
v-model="password"
:inputBorder="false"
text="right"
placeholderStyle=" fontSize: 28rpx"
placeholder="请设置访问密码"
></qn-easyinput>
</view>
</view>
<text class="text_17" v-show="hasPassword">请提前告知用户访问密码以便及时查看信息</text>
<view class="flex-row group_15" @click="selectMethod(false)">
<image :src="hasPassword ? '/static/imgs/general/select-icon.png' : '/static/imgs/general/selected-icon.png'" class="image_10" />
<text class="text_18">公开访问</text>
</view>
</view>
</view>
</view>
</view>
<view class="flex-col items-center button" @click="popupHide">
<text>取消</text>
</view>
</view>
</uni-popup>
</view>
</template>
<script>
import { go2, back } from '@/utils/hook.js'
import { round } from '@/utils/index.js'
import { getDeviceList, makeDeviceShare } from '@/apis/deviceApi.js'
import { H5_URL_DEVICE, isEncrypt, YINGSHI_LIVE_URL } from '@/enums/index.js'
export default {
data() {
return {
id: null,
dateRange: null,
deviceList: [],
password: '',
hasPassword: true
}
},
onLoad(options) {
if (options.id) {
this.id = options.id
this.getList()
}
},
methods: {
go2,
back,
popupShow() {
this.$refs.popup.open('bottom')
},
popupHide() {
this.$refs.popup.close()
},
getDeviceInfo() {},
dateRangeChange(value) {
if (value) {
this.dateRange = [...value]
} else {
this.dateRange = null
}
},
getList() {
getDeviceList({
startTime: this.dateRange ? this.dateRange[0] : null,
endTime: this.dateRange ? this.dateRange[1] : null,
pageNum: 1,
pageSize: 1000
}).then((res) => {
if (res) {
this.deviceList = res.records.map((item) => ({ ...item, label: item.name, value: item.id }))
}
})
},
selectMethod(isPassword) {
this.hasPassword = isPassword
},
share(scene) {
//
if (this.hasPassword && !this.password) {
uni.showToast({
title: '请输入访问密码',
icon: 'none'
})
return
}
makeDeviceShare({
encryptOrNot: this.hasPassword ? isEncrypt.YES : isEncrypt.NO,
mechanicalEquipmentId: this.id,
password: this.password
}).then((res) => {
if (res) {
uni.share({
provider: 'weixin',
type: 0,
title: '设备展示',
summary: '机器进度实时查看',
scene: scene, // WXSceneTimeline,WXSceneSession
imageUrl: 'https://qncloud.oss-cn-shenzhen.aliyuncs.com/paper_shopkeeper/wx-share-store.png',
href: H5_URL_DEVICE + `shareId=${res}`,
success: () => {
console.log('分享成功')
},
fail: (err) => {
console.log('err', err)
}
})
}
})
},
palyVideo() {
if (this.curDevice) {
this.curDevice.accessToken = 'at.1bi93a6k73ochhe60yo0tl3h15b4atv1-8kz22w16z4-1vni1th-smig38b8n'
let url = YINGSHI_LIVE_URL + `accessToken=${this.curDevice.accessToken}&deviceSerial=${this.curDevice.cameraId}&channelNo=${this.curDevice.channelNum}`
go2('page-view', { url: encodeURIComponent(url) })
}
}
},
watch: {
dateRange() {
this.getList()
}
},
computed: {
curDevice() {
return this.deviceList.find((item) => item.id === this.id) || {}
}
},
filters: {
formatDate(time) {
return time.replace(/-/g, '.')
},
formatNumber(number) {
if (number) {
return round(number, 2)
}
return ''
}
}
}
</script>
<style lang="scss" scoped>
.content {
width: 750rpx;
.text_4 {
color: rgb(0, 122, 255);
font-size: 28rpx;
}
}
.group_5 {
padding: 20rpx 32rpx;
.section_1 {
padding: 0 28rpx;
background-image: url('/static/imgs/digital-workshops/device-detail-bg.png');
background-position: 0px 0px;
background-size: 686rpx 380rpx;
background-repeat: no-repeat;
.group_6 {
padding: 32rpx 0 18rpx;
.text_5 {
color: transparent;
font-size: 34rpx;
font-weight: 500;
line-height: 48rpx;
white-space: nowrap;
background-image: linear-gradient(180deg, rgb(15, 90, 212) 0%, rgb(15, 90, 212) 0%, rgb(135, 226, 241) 155.46%, rgb(135, 226, 241) 100%);
-webkit-background-clip: text;
}
.group_7 {
margin: 6rpx 0;
color: rgb(133, 133, 133);
font-size: 26rpx;
line-height: 37rpx;
white-space: nowrap;
.image-icon {
margin: 0 0 5rpx 16rpx;
width: 28rpx;
height: 28rpx;
}
}
}
.section_2 {
color: rgb(51, 51, 51);
font-size: 32rpx;
line-height: 45rpx;
white-space: nowrap;
border-radius: 10rpx;
border: solid 2rpx rgb(224, 224, 224);
.image_5 {
margin: 6rpx 0;
}
}
.group_8 {
padding: 28rpx 0 40rpx;
.section_3 {
padding: 22rpx 22rpx 36rpx;
flex: 1 1 308rpx;
background-image: url('/static/imgs/digital-workshops/gear.png');
background-position: 0px 0px;
background-size: 308rpx 136rpx;
background-repeat: no-repeat;
height: 136rpx;
.text_8 {
color: rgb(68, 113, 189);
font-size: 30rpx;
font-weight: 500;
line-height: 42rpx;
white-space: nowrap;
}
.text_9 {
margin-top: 6rpx;
color: rgb(68, 113, 189);
font-size: 22rpx;
line-height: 30rpx;
white-space: nowrap;
}
}
.section_4 {
margin-left: 14rpx;
padding: 22rpx 22rpx 36rpx;
flex: 1 1 308rpx;
background-image: url('/static/imgs/digital-workshops/clock.png');
background-position: 0px 0px;
background-size: 308rpx 136rpx;
background-repeat: no-repeat;
height: 136rpx;
.text_10 {
color: rgb(83, 146, 106);
font-size: 30rpx;
font-weight: 500;
line-height: 42rpx;
white-space: nowrap;
}
.text_11 {
margin-top: 6rpx;
color: rgb(83, 146, 106);
font-size: 22rpx;
line-height: 30rpx;
white-space: nowrap;
}
}
}
.image_4 {
margin-left: 17rpx;
align-self: center;
width: 20rpx;
height: 13rpx;
}
}
.section_5 {
margin-top: 20rpx;
padding: 28rpx 0;
background-color: rgb(255, 255, 255);
box-shadow: 0px 5rpx 22rpx 0px rgba(0, 0, 0, 0.04);
border-radius: 14rpx;
.group_9 {
margin: 0 28rpx;
border-radius: 6rpx;
position: relative;
.camera_bg {
border-radius: 6rpx;
width: 630rpx;
height: 340rpx;
background-color: rgb(51, 51, 51);
}
.image_7 {
width: 96rpx;
height: 96rpx;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
}
}
}
.group_10 {
height: 637rpx;
.section_7 {
padding-bottom: 96rpx;
background-color: rgb(247, 248, 250);
border-radius: 40rpx 40rpx 0px 0px;
.section_8 {
padding-top: 40rpx;
overflow: hidden;
border-radius: 40rpx 40rpx 0px 0px;
background-color: rgb(255, 255, 255);
height: 520rpx;
.text_12 {
align-self: center;
color: rgb(51, 51, 51);
font-size: 28rpx;
font-weight: 500;
line-height: 40rpx;
white-space: nowrap;
}
.group_11 {
margin-top: 40rpx;
.top-group {
padding: 0 48rpx;
.image_8 {
border-radius: 50%;
width: 96rpx;
height: 96rpx;
}
.image_9 {
margin-left: 64rpx;
width: 96rpx;
height: 96rpx;
}
.text_14 {
margin-left: 76rpx;
}
}
.view_1 {
margin-top: 16rpx;
color: rgb(51, 51, 51);
font-size: 24rpx;
line-height: 33rpx;
white-space: nowrap;
}
.divider {
margin: 32rpx 32rpx 0;
background-color: rgb(235, 237, 240);
height: 1rpx;
}
.section_9 {
padding: 24rpx 32rpx 0;
background-color: rgb(255, 255, 255);
.image_10 {
margin: 4rpx 0;
width: 32rpx;
height: 32rpx;
}
.group_12 {
padding-left: 2rpx;
.group_13 {
color: rgb(51, 51, 51);
font-size: 28rpx;
line-height: 40rpx;
white-space: nowrap;
.text_15 {
margin-left: 18rpx;
}
}
.group_14 {
color: rgb(136, 136, 136);
font-size: 28rpx;
line-height: 40rpx;
white-space: nowrap;
}
}
.text_17 {
margin-top: 16rpx;
align-self: center;
color: rgb(136, 136, 136);
font-size: 24rpx;
line-height: 33rpx;
white-space: nowrap;
}
.group_15 {
margin-top: 22rpx;
padding: 26rpx 2rpx 20rpx;
color: rgb(51, 51, 51);
font-size: 28rpx;
line-height: 40rpx;
white-space: nowrap;
border-top: solid 2rpx rgb(235, 237, 240);
.image_12 {
margin: 4rpx 0;
}
.text_18 {
margin-left: 18rpx;
}
}
.image_4 {
margin-left: 17rpx;
align-self: center;
width: 20rpx;
height: 20rpx;
}
}
}
}
}
.button {
margin-top: -75rpx;
padding: 26rpx 0;
color: rgb(51, 51, 51);
font-size: 32rpx;
line-height: 45rpx;
white-space: nowrap;
background-color: rgb(255, 255, 255);
position: relative;
}
}
</style>

70
pages/digital-workshops/EmptyData.vue

@ -0,0 +1,70 @@
<template>
<view class="flex-col section_1">
<view class="flex-row-center-center page__title">监控台</view>
<view class="flex-col group_5">
<view class="flex-col group_6">
<text class="text_3">添加设备</text>
<text class="text_4">开始构架你的数字车间</text>
</view>
<view class="flex-col items-center text-wrapper" @click="go2('device-operation', { operation: 'add' })">
<text>添加设备</text>
</view>
</view>
</view>
</template>
<script>
import { go2 } from '@/utils/hook.js'
export default {
methods: {
go2
}
}
</script>
<style lang="scss" scoped>
.section_1 {
padding: 4rpx 0 302rpx;
background-image: url('https://qncloud.oss-cn-shenzhen.aliyuncs.com/print-package-app/digital-workshop-bg.png');
background-position: 0px 0px;
background-size: 100% 100%;
background-repeat: no-repeat;
.page__title {
font-size: 34rpx;
color: rgb(255, 255, 255);
margin-top: 56rpx;
}
.group_5 {
margin-top: 42rpx;
padding: 0 32rpx;
.group_6 {
padding-bottom: 34rpx;
.text_3 {
color: rgb(255, 255, 255);
font-size: 38rpx;
font-weight: 500;
line-height: 53rpx;
white-space: nowrap;
}
.text_4 {
margin-top: 5rpx;
color: rgb(255, 255, 255);
font-size: 34rpx;
line-height: 48rpx;
white-space: nowrap;
}
}
.text-wrapper {
padding: 18rpx 0;
color: rgb(0, 122, 255);
font-size: 32rpx;
font-weight: 500;
line-height: 45rpx;
white-space: nowrap;
background-color: rgb(255, 255, 255);
border-radius: 40rpx;
width: 200rpx;
}
}
}
</style>

712
pages/digital-workshops/index.vue

@ -1,9 +1,715 @@
<template> <template>
<view>digital</view>
<view class="page">
<!-- 非工厂展示 -->
<view v-show="!isFactory">空白页</view>
<!-- 工厂企业展示 -->
<view v-show="isFactory">
<view class="flex-col group" v-if="deviceList.length > 0">
<view class="flex-col section_1">
<view class="flex-row-center-center page__title">监控台</view>
<view class="flex-col group_5">
<view class="flex-col group_6">
<text class="text_3">{{ companyName }}</text>
<text class="text_4">{{ userName }}</text>
</view>
<view class="flex-col section_2">
<view class="justify-between">
<view class="flex-row">
<text class="text_5">设备数据</text>
<view class="flex-row" @click="go2('device-operation', { operation: 'add' })">
<text class="text_6">添加</text>
<image src="/static/imgs/digital-workshops/add-icon.png" class="image_3" />
</view>
</view>
<view class="flex-row group_9">
<qn-datetime-picker :border="false" type="daterange" @change="dateRangeChange">
<text>{{ dateRange ? `${dateRange[0]}${dateRange[1]}` : '全部' }}</text>
</qn-datetime-picker>
<image v-show="!dateRange" src="/static/imgs/digital-workshops/down-arrow-icon.png" class="image_4" />
<image v-show="dateRange" @click="dateRangeChange(null)" src="/static/imgs/general/close-icon.png" class="image_4" />
</view>
</view>
<view class="justify-between group_10">
<text>设备类型</text>
<view class="flex-row group_11">
<text>设备数量()</text>
<text class="text_10">设备产量()</text>
</view>
</view>
<view class="flex-row group_18" v-for="(item, index) in deviceTypeList" :key="index">
<view class="flex-row group_19">
<view class="section_6" :style="{ backgroundColor: colorList[index] }"></view>
<text class="text_20">{{ item.name }}</text>
</view>
<text class="text-wrapper_6">{{ item.equipmentNum }}</text>
<text class="text-wrapper_7">{{ item.produceTotalNum }}</text>
</view>
</view>
</view>
</view>
<view class="flex-col group_20">
<view class="flex-row group_21">
<text>设备列表({{ deviceNum }})</text>
<image @click="toggle" src="/static/imgs/digital-workshops/toggle-icon.png" class="image_5" />
</view>
<view class="flex-col section_7" v-show="curTab == 1">
<view class="flex-row section_8">
<text>设备名称</text>
<text class="text_25">状态</text>
<text class="text_26">产量/</text>
<text class="text_27">工作时长/h</text>
</view>
</view>
<scroll-list ref="list" :option="option" @load="upCallback" @refresh="downCallback">
<view class="flex-col section_9" v-if="curTab == 1">
<view class="device-group flex-row" v-for="device in deviceList" :key="device.id" @click="go2('device-production-detail', { id: device.id })">
<text class="text_28">{{ device.name }}</text>
<view
class="flex-col items-center view_1"
:class="{ 'text-wrapper_8': device.workingStatus == deviceStatus.WORKING, 'text-wrapper_9': device.workingStatus == deviceStatus.FREE }"
>
<text>{{ device.workingStatus == deviceStatus.WORKING ? '工作中' : '空闲中' }}</text>
</view>
<text class="text_30 text_31">{{ device.produceTotalNum }}</text>
<text class="text_32">{{ device.totalWorkHour | formatNumber }}</text>
</view>
</view>
<view class="grid" v-if="curTab == 0">
<view class="grid-item flex-col" v-for="device in deviceList" :key="device.id" @click="go2('device-production-detail', { id: device.id })">
<view class="flex-row">
<text class="text_24">{{ device.name }}</text>
<view class="column flex-col items-center" :class="`right-text-wrapper${device.workingStatus == deviceStatus.WORKING ? '__active' : ''}`">
<text>{{ device.workingStatus == deviceStatus.WORKING ? '工作中' : '空闲中' }}</text>
</view>
</view>
<image :src="device.cameraId ? '' : '/static/imgs/digital-workshops/no-camera.png'" class="image_6" />
<view class="bottom-group justify-between">
<text>产量</text>
<text>{{ device.produceTotalNum || 0 }}</text>
</view>
<view class="bottom-group justify-between">
<text>时长</text>
<text>{{ device.totalWorkHour | formatNumber }}h</text>
</view>
</view>
</view>
</scroll-list>
</view>
</view>
<view v-else>
<empty-data></empty-data>
</view>
</view>
</view>
</template> </template>
<script> <script>
export default {}
import { enterpriseType, deviceStatus } from '@/enums/index.js'
import { go2 } from '@/utils/hook.js'
import { round } from '@/utils/index.js'
import EmptyData from './EmptyData.vue'
import { getDeviceList, getEquipmentStatistics } from '@/apis/deviceApi.js'
const colorList = ['#FA541C', '#EB2F96', '#13C2C2', '#9254DE', '#1890FF', '#4E6EFE', '#FAA90E', '#FF3333', '#64B327']
export default {
components: {
EmptyData
},
data() {
return {
dateRange: null,
deviceTypeList: [],
deviceList: [],
deviceNum: 0,
colorList: Object.freeze(colorList),
pagination: {
pageNum: 0,
pageSize: 10
},
option: {
size: 10,
auto: true,
emptyText: '暂无设备~',
background: '#F7F8FA',
fontSize: '40rpx'
},
deviceStatus: Object.freeze(deviceStatus),
curTab: 0
}
},
computed: {
isFactory() {
return this.$store.state.companyInfo.enterpriseType == enterpriseType.PRINT_PACKAGE_FACTORY
},
userName() {
return this.$store.state.userInfo.name || this.$store.state.userInfo.mobile
},
companyName() {
return this.$store.state.companyInfo.name
}
},
onShow() {
if (this.isFactory) {
this.getDeviceList()
this.getDeviceStatistics()
}
},
methods: {
go2,
round,
//
getDeviceStatistics() {
getEquipmentStatistics({
pageNum: 1,
pageSize: 100,
startDate: this.dateRange ? this.dateRange[0] : null,
endDate: this.dateRange ? this.dateRange[1] : null
}).then((res) => {
if (res) {
this.deviceTypeList = res.records
}
})
},
selectDateRange() {},
dateRangeChange(value) {
if (value) {
this.dateRange = [...value]
} else {
this.dateRange = null
}
},
//
getDeviceList() {
return new Promise((resolve, reject) => {
let condition = {
...this.pagination,
startDate: this.dateRange ? this.dateRange[0] : '',
endDate: this.dateRange ? this.dateRange[1] : ''
}
getDeviceList(condition)
.then((res) => {
if (res) {
if (res.current <= 1) {
this.deviceList = res.records
} else {
this.deviceList = this.list.concat(res.records)
}
this.deviceNum = res.total
resolve({ list: this.deviceList, total: res.total })
} else {
reject()
}
})
.catch((err) => {
reject(err)
})
})
},
downCallback() {
this.pagination.pageNum = 1
this.getDeviceList()
.then(({ list, total }) => {
this.$refs.list.refreshSuccess({ list, total })
})
.catch(() => {
this.$refs.list.refreshFail()
})
},
upCallback() {
this.pagination.pageNum++
this.getDeviceList()
.then(({ list, total }) => {
this.$refs.list.loadSuccess({ list, total })
})
.catch(() => {
this.$refs.list.loadFail()
})
},
toggle() {
this.curTab = (this.curTab + 1) % 2
}
},
watch: {
dateRange() {
this.getDeviceList()
this.getDeviceStatistics()
}
},
filters: {
formatNumber(number) {
if (number) {
return round(number, 2)
}
return ''
}
}
}
</script> </script>
<style></style>
<style lang="scss" scoped>
.page {
height: 100vh;
width: 750rpx;
background-color: #f7f8fa;
.page__title {
font-size: 34rpx;
color: rgb(255, 255, 255);
margin-top: 56rpx;
}
}
.group {
flex: 1 1 auto;
overflow-y: auto;
.section_1 {
padding-top: 4rpx;
background: url('https://qncloud.oss-cn-shenzhen.aliyuncs.com/print-package-app/digital-workshop-bg.png') no-repeat top/cover;
.group_5 {
margin-top: 70rpx;
.group_6 {
padding: 0 32rpx;
.text_3 {
color: rgb(255, 255, 255);
font-size: 38rpx;
font-weight: 500;
line-height: 53rpx;
white-space: nowrap;
}
.text_4 {
margin-top: 5rpx;
color: rgb(255, 255, 255);
font-size: 34rpx;
line-height: 48rpx;
white-space: nowrap;
}
}
.section_2 {
margin-top: 43rpx;
padding: 30rpx 32rpx 32rpx;
background-color: rgb(255, 255, 255);
border-radius: 20rpx;
.group_10 {
margin-top: 16rpx;
color: rgb(133, 133, 133);
font-size: 24rpx;
line-height: 33rpx;
white-space: nowrap;
.group_11 {
margin-right: 64rpx;
.text_10 {
margin-left: 72rpx;
}
}
}
.group_18 {
margin-top: 20rpx;
.group_19 {
width: 260rpx;
color: rgb(31, 31, 31);
font-size: 28rpx;
line-height: 40rpx;
.section_6 {
align-self: center;
background-color: rgb(100, 179, 39);
border-radius: 2rpx;
width: 16rpx;
height: 16rpx;
}
.text_20 {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
margin-left: 10rpx;
width: 240rpx;
}
}
.text-wrapper_6 {
margin-left: 20rpx;
width: 190rpx;
color: rgb(51, 51, 51);
font-size: 28rpx;
font-weight: 500;
line-height: 40rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.text-wrapper_7 {
margin-left: 20rpx;
width: 200rpx;
color: rgb(51, 51, 51);
font-size: 28rpx;
font-weight: 500;
line-height: 40rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
.group_9 {
margin: 8rpx 0;
color: rgb(133, 133, 133);
font-size: 24rpx;
line-height: 33rpx;
white-space: nowrap;
.image_4 {
margin: 0 0 5rpx 16rpx;
width: 28rpx;
height: 28rpx;
}
}
.text_5 {
color: rgb(31, 31, 31);
font-size: 34rpx;
font-weight: 500;
line-height: 48rpx;
white-space: nowrap;
}
.text_6 {
margin: 4rpx 0 4rpx 24rpx;
color: rgb(0, 122, 255);
font-size: 28rpx;
line-height: 40rpx;
white-space: nowrap;
}
.image_3 {
margin: 8rpx 0 8rpx 14rpx;
width: 32rpx;
height: 32rpx;
}
}
}
.group_2 {
padding: 0 5rpx;
position: relative;
.image-wrapper {
position: absolute;
left: 5rpx;
top: 50%;
transform: translateY(-50%);
width: 107rpx;
.image {
width: 92rpx;
height: 16rpx;
}
}
.group_3 {
line-height: 26rpx;
white-space: nowrap;
.text {
color: rgb(255, 255, 255);
font-size: 20rpx;
line-height: 26rpx;
}
.text_1 {
color: rgb(255, 255, 255);
font-size: 20rpx;
line-height: 26rpx;
}
}
.group_4 {
color: rgb(255, 255, 255);
font-size: 22rpx;
line-height: 26rpx;
white-space: nowrap;
position: absolute;
right: 13rpx;
top: 50%;
transform: translateY(-50%);
.image_1 {
margin: 4rpx 0 3rpx 10rpx;
width: 43rpx;
height: 19rpx;
}
}
}
.image_2 {
margin-top: 25rpx;
width: 100vw;
height: 8vw;
}
}
.group_20 {
padding: 34rpx 0 30rpx;
.group_21 {
padding: 0 32rpx;
color: rgb(31, 31, 31);
font-size: 34rpx;
font-weight: 500;
line-height: 48rpx;
white-space: nowrap;
.image_5 {
margin-left: 16rpx;
align-self: center;
width: 28rpx;
height: 28rpx;
}
}
.grid {
padding: 0 32rpx;
margin-top: 20rpx;
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-row-gap: 22rpx;
grid-column-gap: 16rpx;
.grid-item {
padding: 24rpx 20rpx 20rpx;
border-radius: 22rpx;
box-shadow: 0 0 8rpx rgba(0, 0, 0, 0.1);
background-color: rgb(255, 255, 255);
// background-image: url('https://codefun-proj-user-res-1256085488.cos.ap-guangzhou.myqcloud.com/611dd17441a9be0011f45822/620ccb0962a7d90011fe5c8f/16479425621806615216.png');
// background-position: 0px 0px;
// background-size: 100% 100%;
// background-repeat: no-repeat;
.image_6 {
margin-top: 20rpx;
width: 296rpx;
height: 182rpx;
}
.bottom-group {
margin-top: 20rpx;
color: rgb(31, 31, 31);
font-size: 22rpx;
line-height: 30rpx;
white-space: nowrap;
}
.text_24 {
color: rgb(31, 31, 31);
font-size: 28rpx;
font-weight: 500;
line-height: 40rpx;
white-space: nowrap;
}
.column {
margin-left: 14rpx;
margin-right: 20rpx;
}
}
}
.right-text-wrapper__active {
color: rgb(12, 187, 107);
font-size: 24rpx;
line-height: 33rpx;
white-space: nowrap;
padding: 2rpx 0;
background-color: rgba(223, 255, 226, 0.6);
border-radius: 4rpx;
width: 92rpx;
height: 40rpx;
border: solid 2rpx rgba(12, 187, 107, 0.6);
}
.right-text-wrapper {
padding: 2rpx 0;
color: rgb(197, 49, 37);
font-size: 24rpx;
line-height: 33rpx;
white-space: nowrap;
background-color: rgba(255, 225, 223, 0.6);
border-radius: 4rpx;
width: 92rpx;
height: 40rpx;
border: solid 2rpx rgba(197, 49, 37, 0.6);
}
}
}
.section_7 {
background-color: rgb(255, 255, 255);
border-radius: 20rpx 20rpx 0 0;
.section_8 {
padding: 24rpx 32rpx 22rpx;
color: rgb(133, 133, 133);
font-size: 24rpx;
line-height: 33rpx;
white-space: nowrap;
background-color: rgb(255, 255, 255);
border-radius: 20rpx 20rpx 0px 0px;
border-bottom: solid 2rpx rgba(151, 151, 151, 0.4);
.text_25 {
margin-left: 145rpx;
}
.text_26 {
margin-left: 95rpx;
}
.text_27 {
margin-left: 90rpx;
}
}
}
.section_9 {
padding: 0 32rpx;
background-color: rgb(255, 255, 255);
.device-group {
padding: 23rpx 0;
border-bottom: solid 2rpx rgba(151, 151, 151, 0.4);
.text_28 {
width: 220rpx;
color: rgb(31, 31, 31);
font-size: 28rpx;
line-height: 40rpx;
white-space: nowrap;
}
.view_1 {
margin-left: 20rpx;
}
.text_30 {
width: 150rpx;
color: rgb(31, 31, 31);
font-size: 28rpx;
line-height: 40rpx;
white-space: nowrap;
}
.text_31 {
margin-left: 50rpx;
}
.text_32 {
margin-left: 20rpx;
color: rgb(31, 31, 31);
font-size: 28rpx;
line-height: 40rpx;
white-space: nowrap;
}
.text_34 {
color: rgb(31, 31, 31);
font-size: 28rpx;
line-height: 40rpx;
white-space: nowrap;
}
.view_3 {
margin-left: 71rpx;
}
.text_36 {
margin-left: 50rpx;
}
.text_41 {
margin-right: 85rpx;
color: rgb(31, 31, 31);
font-size: 28rpx;
line-height: 40rpx;
white-space: nowrap;
}
.text_42 {
color: rgb(31, 31, 31);
font-size: 28rpx;
line-height: 40rpx;
white-space: nowrap;
}
.group_23 {
margin-left: 73rpx;
}
.text_46 {
margin-left: 131rpx;
}
.text_47 {
color: rgb(31, 31, 31);
font-size: 28rpx;
line-height: 40rpx;
white-space: nowrap;
}
.group_24 {
margin-left: 101rpx;
}
.text_50 {
margin-left: 131rpx;
}
.text_51 {
color: rgb(31, 31, 31);
font-size: 28rpx;
line-height: 40rpx;
white-space: nowrap;
}
.group_25 {
margin-left: 101rpx;
}
.text_54 {
margin-left: 131rpx;
}
.text_38 {
color: rgb(31, 31, 31);
font-size: 28rpx;
line-height: 40rpx;
white-space: nowrap;
}
.view_5 {
margin-left: 15rpx;
}
.text_40 {
margin-left: 50rpx;
color: rgb(31, 31, 31);
font-size: 28rpx;
line-height: 40rpx;
white-space: nowrap;
}
.text-wrapper_8 {
color: rgb(12, 187, 107);
font-size: 24rpx;
line-height: 33rpx;
white-space: nowrap;
padding: 2rpx 0;
background-color: rgba(223, 255, 226, 0.6);
border-radius: 4rpx;
width: 92rpx;
height: 40rpx;
border: solid 2rpx rgba(12, 187, 107, 0.6);
}
.text_44 {
margin-left: 50rpx;
color: rgb(31, 31, 31);
font-size: 28rpx;
line-height: 40rpx;
white-space: nowrap;
}
}
.group_26 {
padding: 19rpx 0;
border-bottom: solid 2rpx rgba(151, 151, 151, 0.4);
.group_27 {
width: 434rpx;
.group_28 {
text-align: left;
width: 228rpx;
height: 80rpx;
.text_55 {
color: rgb(31, 31, 31);
font-size: 28rpx;
line-height: 40rpx;
}
.text_56 {
color: rgb(0, 122, 255);
font-size: 28rpx;
line-height: 40rpx;
}
}
.view_12 {
margin-left: 11rpx;
align-self: center;
}
.text_58 {
margin-left: 50rpx;
align-self: center;
color: rgb(31, 31, 31);
font-size: 28rpx;
line-height: 40rpx;
white-space: nowrap;
}
}
.text_59 {
margin-right: 85rpx;
align-self: center;
color: rgb(31, 31, 31);
font-size: 28rpx;
line-height: 40rpx;
white-space: nowrap;
}
}
.text-wrapper_9 {
color: rgb(197, 49, 37);
font-size: 24rpx;
line-height: 33rpx;
white-space: nowrap;
padding: 2rpx 0;
background-color: rgba(255, 225, 223, 0.6);
border-radius: 4rpx;
width: 92rpx;
height: 40rpx;
border: solid 2rpx rgba(197, 49, 37, 0.6);
}
}
</style>

77
pages/page-view/index.vue

@ -0,0 +1,77 @@
<template>
<view>
<web-view :src="url"></web-view>
</view>
</template>
<script>
import { go2, back } from '@/utils/hook.js'
import { makeSocket } from '@/utils/index.js'
export default {
data() {
return {
url: '',
socket: null,
params: null
}
},
onLoad(option) {
if (option) {
this.url = decodeURIComponent(option.url)
this.params = JSON.parse(option.params)
console.log('params', option.params)
} else {
uni.showToast({
title: '参数错误',
icon: 'none',
complete: () => {
setTimeout(() => {
back()
}, 1000)
}
})
}
},
created() {
makeSocket({ pageInfo: 'page-view', retry: true }).then((res) => {
this.socket = res
this.socket.onMessage(this.getMessage)
})
},
methods: {
/**
* @param {Object} data {data:{},type:''}
*/
getMessage(data) {
//
if (data.type === 'guaranteeSuccess') {
go2('fs-credit', { ...this.params }, true)
}
//
if (data.type == 'zzgSupplierTCSignSuccess') {
go2('order-detail', { orderId: data.data.orderId }, true)
}
//
if (data.type == 'signSuccess') {
// go2('paper-mall-order-detail', { id: data.orderId }, true)
}
//
if (data.type == 'certificatedSuccess') {
back()
}
},
destroySocket() {
if (this.socket) {
this.socket.close()
this.socket = null
}
}
},
destroyed() {
this.destroySocket()
},
onHide() {
this.destroySocket()
}
}
</script>

128
pages/promotion/Banner.vue

@ -0,0 +1,128 @@
<template>
<view class="group_1">
<swiper :current="swiperCurrent" @change="changeSwiper" class="swiper">
<swiper-item v-for="(item, index) in list" :key="index">
<image mode="aspectFit" v-if="item.type == 'image'" :src="item.url" class="image" @click="preview(item.url)" />
<view v-if="item.type == 'video'" class="video-area">
<image mode="aspectFit" @click="playVideo(index)" v-show="showIndex != index" :src="item.imageUrl" class="image" />
<view>
<video v-if="showIndex == index" autoplay :src="item.url" class="video"></video>
</view>
</view>
</swiper-item>
</swiper>
<image
src="https://project-user-resource-1256085488.cos.ap-guangzhou.myqcloud.com/611dd17441a9be0011f45822/620ccb0962a7d90011fe5c8f/16484397546890459564.png"
class="image_1"
/>
<view class="flex-col items-center text-wrapper">
<text>{{ swiperCurrent + 1 }}/{{ list.length }}</text>
</view>
<image v-if="showClose" @click="closeVideo()" class="video-close" src="/static/imgs/promotion/video-close.png"></image>
</view>
</template>
<script>
export default {
props: {
/**
* @property {Array<Object>} list - banner列表
* @property {String} list.type - banner类型image:图片video:视频
* @property {String} list.url - banner图片地址
* @property {String} list.imageUrl - banner视频封面地址
*/
list: {
type: Array,
default: () => []
}
},
data() {
return {
swiperCurrent: 0,
showIndex: null,
showClose: false
}
},
methods: {
changeSwiper(e) {
this.swiperCurrent = e.detail.current
},
playVideo(index) {
this.showClose = true
this.showIndex = index
},
closeVideo() {
this.showIndex = null
this.showClose = false
},
preview(url) {
let urls = []
for (let item of this.list) {
if (item.type == 'image') {
urls.push(item.url)
}
}
uni.previewImage({
current: url,
urls: urls
})
}
}
}
</script>
<style lang="scss" scoped>
.image_1 {
position: absolute;
top: 78rpx;
right: 20rpx;
border-radius: 50%;
width: 66rpx;
height: 66rpx;
}
.group_1 {
color: rgb(255, 255, 255);
font-size: 28rpx;
line-height: 40rpx;
white-space: nowrap;
position: relative;
height: 440rpx;
width: 750rpx;
.swiper {
height: 440rpx;
width: 750rpx;
}
.image {
width: 750rpx;
height: 440rpx;
background-color: rgb(0, 0, 0);
}
.video-area {
width: 100%;
height: 100%;
position: relative;
.video {
width: 750rpx;
height: 440rpx;
}
}
.text-wrapper {
position: absolute;
right: 20rpx;
bottom: 62rpx;
background-color: rgba(0, 0, 0, 0.4);
border-radius: 20rpx;
width: 64rpx;
}
}
/** 定制关闭 */
.video-close {
position: fixed;
bottom: 260rpx;
right: 32rpx;
width: 66rpx;
height: 66rpx;
z-index: 9999;
}
</style>

407
pages/promotion/index.vue

@ -0,0 +1,407 @@
<template>
<view>
<view class="flex-col group">
<!-- 只能使用v-iffixed会影响observer -->
<view class="justify-between header" v-if="showTitle">
<text class="text">{{ factoryInfo.name || '-' }}</text>
<view class="flex-row group_1">
<text class="text_1">分享</text>
<image
src="https://codefun-proj-user-res-1256085488.cos.ap-guangzhou.myqcloud.com/611dd17441a9be0011f45822/620ccb0962a7d90011fe5c8f/16486138596948699331.png"
class="image"
/>
</view>
</view>
<Banner :list="swiperList"></Banner>
<view class="flex-col group_3">
<view class="flex-col section_1">
<view class="flex-col">
<view class="justify-between">
<text class="text_1">{{ factoryInfo.name || '-' }}</text>
<view class="flex-row group_6" @click="editFactory">
<text>修改</text>
<image
src="https://codefun-proj-user-res-1256085488.cos.ap-guangzhou.myqcloud.com/611dd17441a9be0011f45822/620ccb0962a7d90011fe5c8f/16484397523702242367.png"
class="image_2"
/>
</view>
</view>
<view class="flex-col group_7">
<view class="flex-row">
<image
src="https://project-user-resource-1256085488.cos.ap-guangzhou.myqcloud.com/611dd17441a9be0011f45822/620ccb0962a7d90011fe5c8f/16484397546883580497.png"
class="image_3"
/>
<text class="text_3">{{ factoryInfo.contactName || '-' }} {{ factoryInfo.contactMobile }}</text>
</view>
<view class="flex-row group_9">
<image
src="https://project-user-resource-1256085488.cos.ap-guangzhou.myqcloud.com/611dd17441a9be0011f45822/620ccb0962a7d90011fe5c8f/16484397546889037530.png"
class="image_4"
/>
<text class="text_4">{{ factoryInfo.locProvinceName + factoryInfo.locCityName + factoryInfo.locDistrictName + factoryInfo.locDetail }}</text>
</view>
</view>
</view>
<text class="text_5">
{{ factoryInfo.factoryIntroduce || '-' }}
</text>
</view>
<view class="flex-col line-tabs">
<view class="flex-row group_10">
<view class="flex-col items-center text_7" :style="{ color: curTab == 'device' ? 'rgb(0, 122, 255)' : '' }">
<text @click="selectTab('device')">工厂设备</text>
<view v-show="curTab == 'device'" class="section_2"></view>
</view>
<view class="flex-col items-center text_7" :style="{ color: curTab == 'production' ? 'rgb(0, 122, 255)' : '' }">
<text @click="selectTab('production')">产品展示</text>
<view v-show="curTab == 'production'" class="section_2"></view>
</view>
</view>
<view v-if="curTab == 'device'">
<view class="flex-col section_3" v-for="(item, index) in deviceList" :key="index" @click="go2('device-info', { id: item.id })">
<image
src="https://codefun-proj-user-res-1256085488.cos.ap-guangzhou.myqcloud.com/611dd17441a9be0011f45822/620ccb0962a7d90011fe5c8f/16484397512933663615.png"
class="image_5"
/>
<view class="flex-col">
<view class="justify-between group_13">
<text class="text_8">{{ item.name }}</text>
</view>
<text class="text_9">
{{ item.cameraId }}
</text>
</view>
</view>
</view>
<view class="observer">{{ hasMore ? '加载中~' : '没有更多~' }}</view>
</view>
<image
src="https://project-user-resource-1256085488.cos.ap-guangzhou.myqcloud.com/611dd17441a9be0011f45822/620ccb0962a7d90011fe5c8f/16484397546886233508.png"
class="image_6"
/>
</view>
</view>
</view>
</template>
<script>
import Banner from './Banner.vue'
import { go2 } from '@/utils/hook.js'
import { getFactoryInfo } from '@/apis/factoryApi.js'
import { getEquipmentList } from '@/apis/deviceApi.js'
import { fileType } from '@/enums/index.js'
export default {
components: {
Banner
},
data() {
return {
factoryInfo: {},
swiperList: [],
swiperCurrent: 0,
curTab: 'device',
pagination: {
pageNum: 1,
pageSize: 10
},
deviceList: [],
productionList: [],
observer: null,
hasMore: false,
showTitle: false
}
},
computed: {
hasFactory() {
return this.$store.state.companyInfo.id || 0
}
},
watch: {
hasFactory(val) {
if (val) {
this.getCompanyInfo()
}
},
curTab(val) {
//
this.hasMore = false
this.pagination.pageNum = 1
this.getList()
}
},
created() {
this.getCompanyInfo()
this.getList()
},
mounted() {
this.observer = uni.createIntersectionObserver(this)
//
this.observer
.relativeToViewport({
bottom: 50
})
.observe('.observer', (res) => {
if (res.intersectionRatio > 0 && this.hasMore) {
this.pagination.pageNum++
this.getList()
}
})
let observerTitle = uni.createIntersectionObserver(this)
observerTitle
.relativeToViewport({
bottom: 50
})
.observe('.text_1', (res) => {
if (res.intersectionRatio > 0) {
this.showTitle = false
}
if (res.intersectionRatio == 0) {
this.showTitle = !this.showTitle
}
})
},
methods: {
go2,
editFactory() {
go2('complete-info', { id: this.$store.state.companyInfo.id, role: 'enterprise' })
},
getCompanyInfo() {
getFactoryInfo({ id: this.$store.state.companyInfo.id }).then((res) => {
if (res) {
this.factoryInfo = res
this.swiperList = res.imgItemList.map((item) => {
if (item.type == fileType.IMG) {
return {
type: 'image',
url: item.fileUrl
}
}
if (item.type == fileType.VIDEO) {
return {
type: 'video',
url: item.fileUrl,
imageUrl: item.videoPicUrl
}
}
return {}
})
}
})
},
selectTab(tab) {
this.pagination.pageNum = 1
this.curTab = tab
},
//
getList() {
if (this.curTab == 'device') {
getEquipmentList({ ...this.pagination }).then((res) => {
if (res) {
if (res.current <= 1) {
this.deviceList = res.records
for (let i = 0; i < 3; i++) {
this.deviceList = [...this.deviceList, ...this.deviceList]
}
} else {
this.deviceList = this.deviceList.concat(res.records)
}
this.hasMore = this.deviceList.length < res.total
}
})
}
if (this.curTab == 'production') {
getEquipmentList({ ...this.pagination }).then((res) => {
if (res) {
if (res.current <= 1) {
this.deviceList = res.records
} else {
this.deviceList = this.deviceList.concat(res.records)
}
this.hasMore = this.deviceList.length < res.total
}
})
}
}
}
}
</script>
<style lang="scss" scoped>
.group {
padding-bottom: 68rpx;
flex: 1 1 auto;
overflow-y: auto;
height: 100vh; //
.group_3 {
margin-top: -40rpx;
position: relative;
.section_1 {
padding: 32rpx 32rpx 20rpx;
background-color: #fff;
border-radius: 40rpx 40rpx 0px 0px;
.text_5 {
margin-right: 7rpx;
margin-top: 48rpx;
color: rgb(51, 51, 51);
font-size: 26rpx;
line-height: 37rpx;
text-align: left;
}
.group_7 {
margin-top: 18rpx;
color: rgb(51, 51, 51);
font-size: 26rpx;
line-height: 37rpx;
white-space: nowrap;
.group_9 {
margin-top: 12rpx;
padding: 0 3rpx;
.image_4 {
margin: 3rpx 0 3rpx;
width: 27rpx;
height: 30rpx;
}
.text_4 {
margin-left: 12rpx;
width: 650rpx;
white-space: break-spaces;
}
}
.image_3 {
margin: 4rpx 0 4rpx;
width: 28rpx;
height: 28rpx;
}
.text_3 {
margin-left: 12rpx;
}
}
.text_1 {
color: rgb(0, 0, 0);
font-size: 36rpx;
font-weight: 500;
line-height: 50rpx;
white-space: nowrap;
}
.group_6 {
margin: 7rpx 7rpx 7rpx 0;
color: rgb(0, 122, 255);
font-size: 26rpx;
line-height: 37rpx;
white-space: nowrap;
.image_2 {
margin: 9rpx 0 9rpx 15rpx;
width: 10rpx;
height: 18rpx;
}
}
}
.line-tabs {
width: 750rpx;
padding-bottom: 20rpx;
.group_10 {
position: sticky;
top: 128rpx;
z-index: 10;
padding: 20rpx 38rpx;
background-color: rgb(255, 255, 255);
.section_2 {
margin-top: 18rpx;
background-color: rgb(0, 122, 255);
border-radius: 3rpx;
width: 80rpx;
height: 6rpx;
}
.text_7 {
margin-right: 32rpx;
color: rgb(51, 51, 51);
font-size: 28rpx;
line-height: 40rpx;
white-space: nowrap;
}
}
.section_3 {
margin: 20rpx 32rpx 0rpx;
padding: 26rpx 0 25rpx 24rpx;
filter: drop-shadow(0px 11rpx 23.5rpx #00000014);
background-color: rgb(255, 255, 255);
border-radius: 10rpx;
.image_5 {
margin-right: 24rpx;
width: 638rpx;
height: 390rpx;
}
.group_13 {
color: rgb(0, 0, 0);
font-size: 32rpx;
font-weight: 600;
line-height: 45rpx;
white-space: nowrap;
.text_8 {
align-self: center;
}
}
.text_9 {
margin-right: 40rpx;
color: rgb(51, 51, 51);
font-size: 26rpx;
line-height: 32rpx;
text-align: left;
}
}
}
}
.image_6 {
position: fixed;
bottom: 160rpx;
right: 32rpx;
box-shadow: 0px 2rpx 4rpx 0px rgba(0, 0, 0, 0.12);
border-radius: 50%;
width: 82rpx;
height: 82rpx;
}
}
.observer {
width: 100%;
display: flex;
align-self: center;
justify-content: center;
padding: 20rpx 32rpx 20rpx;
color: rgb(130, 132, 138);
font-size: 32rpx;
}
.header {
padding: 59rpx 35rpx 21rpx 38rpx;
background-color: rgb(255, 255, 255);
border-bottom: solid 1rpx rgb(221, 221, 221);
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 100;
height: 128rpx;
.text {
color: rgb(0, 0, 0);
font-size: 36rpx;
font-weight: 500;
line-height: 50rpx;
white-space: nowrap;
}
.group_1 {
margin: 7rpx 0 6rpx;
color: rgb(51, 51, 51);
font-size: 24rpx;
line-height: 33rpx;
white-space: nowrap;
.text_1 {
margin-bottom: 3rpx;
}
.image {
margin-left: 14rpx;
width: 37rpx;
height: 37rpx;
}
}
}
</style>

BIN
static/imgs/.DS_Store

BIN
static/imgs/digital-workshops/add-icon.png

Before After
Width: 64  |  Height: 64  |  Size: 2.1 KiB

BIN
static/imgs/digital-workshops/clock.png

Before After
Width: 154  |  Height: 68  |  Size: 9.8 KiB

BIN
static/imgs/digital-workshops/device-detail-bg.png

Before After
Width: 343  |  Height: 190  |  Size: 5.0 KiB

BIN
static/imgs/digital-workshops/down-arrow-icon.png

Before After
Width: 40  |  Height: 40  |  Size: 575 B

BIN
static/imgs/digital-workshops/gear.png

Before After
Width: 154  |  Height: 68  |  Size: 9.3 KiB

BIN
static/imgs/digital-workshops/no-camera.png

Before After
Width: 296  |  Height: 182  |  Size: 11 KiB

BIN
static/imgs/digital-workshops/toggle-icon.png

Before After
Width: 56  |  Height: 56  |  Size: 1.2 KiB

BIN
static/imgs/general/camera-bg.png

Before After
Width: 192  |  Height: 192  |  Size: 6.5 KiB

BIN
static/imgs/general/line-share-icon.png

Before After
Width: 96  |  Height: 96  |  Size: 4.2 KiB

BIN
static/imgs/general/select-icon.png

Before After
Width: 64  |  Height: 64  |  Size: 2.1 KiB

BIN
static/imgs/general/selected-icon.png

Before After
Width: 64  |  Height: 64  |  Size: 1.9 KiB

BIN
static/imgs/general/session-share-icon.png

Before After
Width: 192  |  Height: 192  |  Size: 9.1 KiB

BIN
static/imgs/promotion/video-close.png

Before After
Width: 66  |  Height: 66  |  Size: 1.9 KiB

16
utils/hook.js

@ -25,7 +25,7 @@ export function back() {
delta: 1 delta: 1
}) })
} else { } else {
go2('client')
go2('digital-workshops')
} }
} }
@ -134,7 +134,9 @@ export function uploadImage(sourceType = ['album', 'camera'], count = 1) {
* 视频文件上传 * 视频文件上传
* @param {array} sourceType 上传的方式 album:相册 camera:相机 * @param {array} sourceType 上传的方式 album:相册 camera:相机
* @param {boolean} compressed 是否压缩 * @param {boolean} compressed 是否压缩
* @return {Promise<string>} 返回对应的文件地址
* @return {Promise<object>} 返回对应的文件地址
* @value {string} url 视频地址
* @value {string} thumb 视频缩略图地址
*/ */
export function uploadVideo(sourceType = ['album', 'camera'], compressed = true) { export function uploadVideo(sourceType = ['album', 'camera'], compressed = true) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -184,8 +186,14 @@ export function uploadFile(path, type = 'image') {
success: (res) => { success: (res) => {
let result = JSON.parse(res.data) let result = JSON.parse(res.data)
if (result.data) { if (result.data) {
resolve(result.data)
return result.data
if (type == 'video') {
resolve({
url: result.data.videoFileUrl,
thumb: result.data.videoImgUrl
})
} else {
resolve(result.data)
}
} else { } else {
reject(result.message) reject(result.message)
} }

Loading…
Cancel
Save