31 changed files with 2129 additions and 637 deletions
Split View
Diff Options
-
146apis/commonApi.js
-
40apis/deviceApi.js
-
85apis/factoryApi.js
-
36components/qn-easyinput/qn-easyinput.vue
-
229enums/index.js
-
4env/index.js
-
151pages.json
-
82pages/agreement/index.vue
-
246pages/apply-inspection/index.vue
-
223pages/certification/index.vue
-
187pages/device-info/index.vue
-
241pages/device-production-detail/index.vue
-
124pages/factory-inspection/Banner.vue
-
576pages/factory-inspection/index.vue
-
64pages/page-view/index.vue
-
134pages/production-info/index.vue
-
BINstatic/imgs/device-info/camera-bg.png
-
BINstatic/imgs/device-info/clock.png
-
BINstatic/imgs/device-info/close-icon.png
-
BINstatic/imgs/device-info/device-detail-bg.png
-
BINstatic/imgs/device-info/down-arrow-icon.png
-
BINstatic/imgs/device-info/factory-avatar.png
-
BINstatic/imgs/device-info/gear.png
-
BINstatic/imgs/device-info/logo.png
-
BINstatic/imgs/device-info/select-icon.png
-
BINstatic/imgs/device-info/selected-icon.png
-
BINstatic/imgs/factory/address-icon.png
-
BINstatic/imgs/factory/phone-blue-icon.png
-
158store/index.js
-
2utils/http/index.js
-
38utils/index.js
@ -0,0 +1,40 @@ |
|||
import http from '@/utils/http/index.js' |
|||
|
|||
/** |
|||
* 校验分享id是否有密码 |
|||
* @param {object} data |
|||
* @value {string} id 分享id |
|||
*/ |
|||
export function checkShareId(data = {}) { |
|||
return http.get({ |
|||
url: `/base-paper-trading/get/mechanical-equipment-share/${data.id}`, |
|||
data: data |
|||
}) |
|||
} |
|||
|
|||
/** |
|||
* 校验分享id的密码 |
|||
* @param {object} data |
|||
* @value {string} id 分享id |
|||
* @value {string} password 分享密码 |
|||
*/ |
|||
export function checkSharePassword(data = {}) { |
|||
return http.post({ |
|||
url: `/base-paper-trading/check/mechanical-equipment-share/password`, |
|||
data: data |
|||
}) |
|||
} |
|||
|
|||
/** |
|||
* 获取设备详情 |
|||
* @param {object} data |
|||
* @value {string} id 分享id |
|||
* @value {string} startDate 开始时间 |
|||
* @value {string} endDate 结束时间 |
|||
*/ |
|||
export function getShareDeviceInfo(data = {}) { |
|||
return http.get({ |
|||
url: `/base-paper-trading/get/mechanical-equipment/detail/${data.id}`, |
|||
data: data |
|||
}) |
|||
} |
|||
@ -0,0 +1,85 @@ |
|||
import http from '@/utils/http/index.js' |
|||
|
|||
/** |
|||
* 查询工厂信息 |
|||
* |
|||
*/ |
|||
export function getFactoryInfo(data = {}) { |
|||
return http.get({ |
|||
url: `/yyt-uec/get/factory/information/${data.id}`, |
|||
data |
|||
}) |
|||
} |
|||
|
|||
/** |
|||
* 获取设备列表 |
|||
*/ |
|||
export function getEquipmentList(data = {}) { |
|||
return http.get({ |
|||
url: '/base-paper-trading/get/mechanical-equipment/extension-list', |
|||
data |
|||
}) |
|||
} |
|||
|
|||
/** |
|||
* 获取产品列表 |
|||
*/ |
|||
export function getProductionList(data = {}) { |
|||
return http.get({ |
|||
url: '/base-paper-trading/get/packagingProduct/list', |
|||
data |
|||
}) |
|||
} |
|||
/** |
|||
* 获取申请验厂详情 |
|||
*/ |
|||
export function getApplyInfo(data = {}) { |
|||
return http.get({ |
|||
url: `/base-paper-trading/get/factory-inspection/${data.id}`, |
|||
data |
|||
}) |
|||
} |
|||
|
|||
/** |
|||
* 获取设备信息 |
|||
*/ |
|||
export function getEquipmentInfo(data = {}) { |
|||
return http.get({ |
|||
url: `/base-paper-trading/get/mechanical-equipment/${data.id}`, |
|||
data |
|||
}) |
|||
} |
|||
|
|||
/** |
|||
* 获取产品详情 |
|||
* @param {object} data |
|||
* @property {string} id |
|||
*/ |
|||
export function getProductionInfo(data = {}) { |
|||
return http.get({ |
|||
url: `/base-paper-trading/get/packagingProduct/${data.id}`, |
|||
data |
|||
}) |
|||
} |
|||
|
|||
/** |
|||
* 用户申请验厂 |
|||
* @param {object} data |
|||
* @property {string} id |
|||
*/ |
|||
export function userApplying(data = {}) { |
|||
return http.post({ |
|||
url: `/base-paper-trading/apply/for-factory-inspection`, |
|||
data |
|||
}) |
|||
} |
|||
|
|||
/** |
|||
* 获取监控设备的token |
|||
*/ |
|||
export function getAccessToken(data = {}) { |
|||
return http.get({ |
|||
url: `/base-paper-trading/get/mechanical-equipment/monitor/token`, |
|||
data |
|||
}) |
|||
} |
|||
@ -1,8 +1,8 @@ |
|||
/** |
|||
* @description 唯一环境变量 |
|||
*/ |
|||
// const env = 'test'
|
|||
const env = 'test' |
|||
// const env = 'dev'
|
|||
const env = 'production' |
|||
// const env = 'production'
|
|||
|
|||
export default env |
|||
@ -0,0 +1,82 @@ |
|||
<template> |
|||
<view class="content"> |
|||
<uni-nav-bar left-icon="back" @clickLeft="back" statusBar fixed title="用户与隐私协议"></uni-nav-bar> |
|||
<view style="word-break: break-all; white-space: pre-wrap; padding: 20rpx 16rpx" v-html="content"></view> |
|||
</view> |
|||
</template> |
|||
<script> |
|||
const content = `软件许可使用协议 |
|||
发布时间:2020年 7 月 1 日 |
|||
|
|||
|
|||
|
|||
提示条款 |
|||
|
|||
本软件许可使用协议(以下称"本协议")由您与广州千鸟电商科技有限公司(以下称“我们”)于广东省广州市天河区共同签署。 |
|||
|
|||
|
|||
|
|||
在使用“印包客”软件(软件名称以实际展示为准,以下称许可软件)之前,请您认真阅读并同意《千鸟互联服务协议》以及《隐私权政策》,这是我们向您提供许可软件及许可软件相关服务的前提。我们特别在此提示您注意阅读免除或者限制责任的条款、法律适用和争议解决条款,相关条款将以粗体标识,您需要重点阅读。如您对协议有任何疑问,可向客服咨询。如果您完全同意并接受本协议,您可下载安装或开始使用许可软件。 |
|||
|
|||
|
|||
|
|||
本协议的内容包括协议正文及所有我们已经公布的适用于所有使用者的各类服务条款及规则(诸如《千鸟互联服务协议》、千鸟平台规则等),未来我们会继续丰富相关的服务条款与规则,并依法定程序公布生效。所有条款与规则为协议不可分割的组成部分,与协议具有同等法律效力。 |
|||
|
|||
|
|||
|
|||
一、 定义 |
|||
|
|||
1、 许可软件:是指由我们开发的,供您从下载平台下载,并仅限在相应系统手持移动终端中安装、使用的软件系统。 |
|||
|
|||
2、 千鸟互联服务:我们基于互联网,以包含千鸟互联网站、本软件等在内的各种形态(包括未来技术发展出现的新的服务形态)向您提供的各项服务。 |
|||
|
|||
|
|||
|
|||
二、许可范围 |
|||
|
|||
1、 由于软件适配平台及终端限制,您理解您仅可在许可软件列明的系统终端使用许可软件;您将许可软件安装在非对应系统的其他终端设备上的,可能会对您硬件或软件功能造成损害。 |
|||
|
|||
2、 许可软件仅限用于非商业目的,供您个人消费合理自用。未经许可,您不可为商业运营目的安装、使用、运行许可软件。 |
|||
|
|||
3、 为了改善用户体验、完善服务内容、保证许可软件与我们提供服务的商业诉求一致,我们会对许可软件及/或其相关服务、功能、界面进行更新、修改,包括开发新的功能、删除旧功能等。您可按照变更后许可软件的实际情况取得相应功能或服务的授权,并可适用本协议相关约定。 |
|||
|
|||
|
|||
|
|||
三、使用规范 |
|||
|
|||
1、 您应该规范使用许可软件,以下方式是违反使用规范的: |
|||
|
|||
|
|||
|
|||
(1) 从事危害网络信息安全、欺诈、盗用他人账户、资金等违法犯罪活动,发表、传送、传播、储存侵害我们及他人知识产权、商业秘密权,或其他违反国家法律法规政策、破坏公序良俗、损害公共利益的行为; |
|||
|
|||
(2) 擅自对许可软件及/或其组成部分进行出租、出借、再许可、复制、修改、链接、转载、汇编、发表、出版、建立镜像站点,或借助许可软件发展与之有关的衍生产品、作品、服务、插件、外挂、兼容、互联等; |
|||
|
|||
(3) 通过非由我们或我们关联公司开发、授权或认可的第三方兼容软件、系统登录或使用许可软件,或针对许可软件使用非我们及我们关联公司开发、授权或认证的插件和外挂; |
|||
|
|||
(4) 删除许可软件及其他副本上关于版权的信息、内容,或修改、删除或避开为保护知识产权而设置的任何技术措施; |
|||
|
|||
(5) 对许可软件或者许可软件运行过程中释放在终端中的任何数据及许可软件运行过程中终端与服务器端的交互数据进行获取、复制、修改或创作任何衍生作品,包括使用插件、外挂或非经授权的第三方工具/服务接入许可软件和相关系统等形式; |
|||
|
|||
(6) 通过修改或伪造许可软件运行中的指令、数据、数据包,增加、删减、变动许可软件的功能或运行效果,及/或将具有上述用途的软件通过信息网络向公众传播或者运营; |
|||
|
|||
(7) 其他以任何不合法的方式、不合法的目的或以任何与本协议约定不一致的方式使用许可软件。 |
|||
` |
|||
import { back } from '@/utils/hook.js' |
|||
export default { |
|||
data() { |
|||
return { |
|||
content: content |
|||
} |
|||
}, |
|||
methods: { |
|||
back |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
.content { |
|||
width: 750rpx; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,246 @@ |
|||
<template> |
|||
<view class="form"> |
|||
<uni-nav-bar left-icon="back" @clickLeft="back" statusBar fixed title="申请验厂"></uni-nav-bar> |
|||
<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="11" |
|||
v-model="form.mobile" |
|||
: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_1">*</text> |
|||
<text class="text_2">验证码</text> |
|||
<view> |
|||
<view v-show="timer > 0" class="timer_area"> |
|||
<text class="timer">{{ `(${timer}S后) ` }}</text> |
|||
<text class="timer_text">重新获取</text> |
|||
</view> |
|||
<text v-show="timer <= 0" class="code" @click="getCode">获取验证码</text> |
|||
</view> |
|||
</view> |
|||
<qn-easyinput |
|||
:maxlength="6" |
|||
v-model="form.captcha" |
|||
: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_1">*</text> |
|||
<text class="text_2">用户名</text> |
|||
</view> |
|||
<qn-easyinput |
|||
:maxlength="20" |
|||
v-model="form.userName" |
|||
: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_1">*</text> |
|||
<text class="text_2">企业名</text> |
|||
</view> |
|||
<qn-easyinput |
|||
:maxlength="20" |
|||
v-model="form.enterpriseName" |
|||
:inputBorder="false" |
|||
text="right" |
|||
placeholderStyle=" fontSize: 28rpx" |
|||
placeholder="请输入企业名" |
|||
></qn-easyinput> |
|||
</view> |
|||
<view class="divider"></view> |
|||
<qn-footer fixed> |
|||
<view class="flex-col items-center text-wrapper_1" @click="apply"> |
|||
<text>提交申请</text> |
|||
</view> |
|||
</qn-footer> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import { validateField } from '@/utils/index.js' |
|||
import { getAuthCaptcha } from '@/apis/commonApi.js' |
|||
import { userApplying } from '@/apis/factoryApi.js' |
|||
import { codePurpose, verificationType } from '@/enums/index.js' |
|||
import { back } from '@/utils/hook.js' |
|||
const validateFields = [ |
|||
{ |
|||
name: 'userName', |
|||
rules: [{ required: true, message: '请输入用户名' }] |
|||
}, |
|||
{ |
|||
name: 'mobile', |
|||
rules: [ |
|||
{ required: true, message: '请输入手机号' }, |
|||
{ type: 'phone', message: '请输入正确的手机号' } |
|||
] |
|||
}, |
|||
{ |
|||
name: 'captcha', |
|||
rules: [{ required: true, message: '请输入验证码' }] |
|||
}, |
|||
{ |
|||
name: 'enterpriseName', |
|||
rules: [{ required: true, message: '请输入企业名' }] |
|||
} |
|||
] |
|||
|
|||
export default { |
|||
data() { |
|||
return { |
|||
form: { |
|||
userName: '', |
|||
mobile: '', |
|||
enterpriseName: '', |
|||
captcha: '' |
|||
}, |
|||
factoryId: '', |
|||
timer: 0 |
|||
} |
|||
}, |
|||
methods: { |
|||
back, |
|||
// 申请验厂 |
|||
apply() { |
|||
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 |
|||
} |
|||
} |
|||
userApplying({ |
|||
...this.form |
|||
}).then((res) => { |
|||
if (res) { |
|||
uni.showModal({ |
|||
title: '申请已发出,请联系该企业管理员通过审核', |
|||
icon: 'success', |
|||
success: () => { |
|||
back() |
|||
} |
|||
}) |
|||
} |
|||
}) |
|||
}, |
|||
// 获取验证码 |
|||
getCode() { |
|||
let rules = [ |
|||
{ required: true, message: '请输入手机号' }, |
|||
{ type: 'phone', message: '请输入正确的手机号' } |
|||
] |
|||
const { isValid, msg } = validateField(this.form.mobile, rules) |
|||
if (!isValid) { |
|||
uni.showToast({ |
|||
title: msg, |
|||
icon: 'none' |
|||
}) |
|||
return |
|||
} |
|||
this.countdown() |
|||
getAuthCaptcha({ |
|||
purpose: codePurpose.CERTIFICATION, |
|||
verifiableAccount: this.form.mobile, |
|||
verifiableAccountType: verificationType.PHONE |
|||
}).then(() => { |
|||
uni.showToast({ |
|||
title: '验证码已发送', |
|||
icon: 'none' |
|||
}) |
|||
}) |
|||
}, |
|||
// 倒计时 |
|||
countdown() { |
|||
this.timer = 60 |
|||
let timer = setInterval(() => { |
|||
this.timer-- |
|||
if (this.timer <= 0) { |
|||
clearInterval(timer) |
|||
} |
|||
}, 1000) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
.form { |
|||
width: 750rpx; |
|||
background-color: #fff; |
|||
} |
|||
.text-wrapper_1 { |
|||
margin: 0 32rpx; |
|||
padding: 23rpx 0; |
|||
background-color: rgb(0, 122, 255); |
|||
border-radius: 10rpx; |
|||
color: rgb(255, 255, 255); |
|||
} |
|||
.timer_area { |
|||
width: auto; |
|||
flex: 0 0 auto; |
|||
margin-left: 16rpx; |
|||
.timer { |
|||
font-size: 28rpx; |
|||
color: #007aff; |
|||
} |
|||
.timer_text { |
|||
font-size: 28rpx; |
|||
color: #999999; |
|||
} |
|||
} |
|||
.code { |
|||
margin-left: 16rpx; |
|||
width: 160rpx; |
|||
font-size: 28rpx; |
|||
color: #007aff; |
|||
flex: 0 0 auto; |
|||
} |
|||
.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; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,223 @@ |
|||
<template> |
|||
<view class="content"> |
|||
<view class="flex-col group_4"> |
|||
<view class="flex-row group_5"> |
|||
<image src="/static/imgs/device-info/logo.png" class="image_4" /> |
|||
<text class="text_4">印包客</text> |
|||
</view> |
|||
<view class="flex-row group_6"> |
|||
<image src="/static/imgs/device-info/factory-avatar.png" class="image_5" /> |
|||
<view class="flex-col group_7"> |
|||
<text class="text_5">{{ userInfo.companyName || 'xxx' }} 的分享</text> |
|||
<text class="text_6">{{ userInfo.name || userInfo.mobile || 'xxx' }}</text> |
|||
</view> |
|||
</view> |
|||
<view class="flex-col section_1"> |
|||
<view class="flex-col items-center button"> |
|||
<qn-easyinput :inputBorder="false" v-model="password" placeholder="请输入访问密码" text="center"></qn-easyinput> |
|||
</view> |
|||
<view class="flex-col items-center button_1" @click="checkPassword"> |
|||
<text>立即访问</text> |
|||
</view> |
|||
<text class="text_9">{{ expireTip }}</text> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import { go2, back } from '@/utils/hook.js' |
|||
import { difTime } from '@/utils/index.js' |
|||
import { checkShareId, checkSharePassword } from '@/apis/deviceApi' |
|||
import { isEncrypt } from '@/enums/index.js' |
|||
export default { |
|||
data() { |
|||
return { |
|||
shareId: null, |
|||
mechanicalEquipmentId: null, |
|||
isValid: false, |
|||
expireTime: null, |
|||
password: '', |
|||
userInfo: { |
|||
name: '', |
|||
companyName: '', |
|||
mobile: '' |
|||
} |
|||
} |
|||
}, |
|||
methods: { |
|||
go2, |
|||
back |
|||
}, |
|||
onLoad(options) { |
|||
if (options.shareId) { |
|||
this.shareId = options.shareId |
|||
} else { |
|||
uni.showModal({ |
|||
title: '分享id不存在,请询问印包厂', |
|||
icon: 'error' |
|||
}) |
|||
} |
|||
}, |
|||
mounted() { |
|||
this.check() |
|||
}, |
|||
computed: { |
|||
expireTip() { |
|||
if (this.isValid) { |
|||
return `${this.expireTime.hours}小时${this.expireTime.minutes}分钟后过期` |
|||
} |
|||
return '该分享已到期,请重新联系印包厂' |
|||
} |
|||
}, |
|||
methods: { |
|||
check() { |
|||
if (this.shareId) { |
|||
checkShareId({ id: this.shareId }).then((res) => { |
|||
if (res && res.expireTime) { |
|||
this.userInfo.name = res.userName |
|||
this.userInfo.companyName = res.enterpriseName |
|||
this.userInfo.mobile = res.userMobile |
|||
this.mechanicalEquipmentId = res.mechanicalEquipmentId |
|||
// 先判断是否过期 |
|||
const { beyond, hours, minutes } = difTime(Date.now(), res.expireTime) |
|||
if (beyond) { |
|||
this.isValid = false |
|||
return |
|||
} else { |
|||
this.isValid = true |
|||
this.expireTime = { |
|||
hours, |
|||
minutes |
|||
} |
|||
} |
|||
if (res.encryptOrNot == isEncrypt.NO) { |
|||
this.jumpDevice() |
|||
} |
|||
} |
|||
}) |
|||
} |
|||
}, |
|||
jumpDevice() { |
|||
go2( |
|||
'device-production-detail', |
|||
{ |
|||
id: this.mechanicalEquipmentId |
|||
}, |
|||
true |
|||
) |
|||
}, |
|||
checkPassword() { |
|||
if (!this.isValid) { |
|||
uni.showToast({ |
|||
title: '该分享已到期,请重新联系印包厂', |
|||
icon: 'none' |
|||
}) |
|||
return |
|||
} |
|||
checkSharePassword({ |
|||
id: this.shareId, |
|||
password: this.password |
|||
}).then((res) => { |
|||
if (res) { |
|||
this.jumpDevice() |
|||
} else { |
|||
uni.showToast({ |
|||
title: '密码错误', |
|||
icon: 'error' |
|||
}) |
|||
} |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
.content { |
|||
width: 750rpx; |
|||
padding-top: 128rpx; |
|||
.group_4 { |
|||
padding-top: 32rpx; |
|||
flex: 1 1 auto; |
|||
overflow-y: auto; |
|||
.group_5 { |
|||
padding: 0 39rpx; |
|||
color: rgb(0, 0, 0); |
|||
font-size: 42rpx; |
|||
font-weight: 500; |
|||
line-height: 59rpx; |
|||
letter-spacing: 6rpx; |
|||
white-space: nowrap; |
|||
.image_4 { |
|||
width: 67rpx; |
|||
height: 81rpx; |
|||
} |
|||
.text_4 { |
|||
margin-left: 22rpx; |
|||
align-self: center; |
|||
} |
|||
} |
|||
.group_6 { |
|||
margin-top: 40rpx; |
|||
padding: 0 32rpx; |
|||
.image_5 { |
|||
width: 80rpx; |
|||
height: 80rpx; |
|||
} |
|||
.group_7 { |
|||
margin: 4rpx 0 4rpx 16rpx; |
|||
flex: 1 1 auto; |
|||
.text_5 { |
|||
color: rgb(51, 51, 51); |
|||
font-size: 30rpx; |
|||
font-weight: 500; |
|||
line-height: 42rpx; |
|||
white-space: nowrap; |
|||
} |
|||
.text_6 { |
|||
color: rgb(136, 136, 136); |
|||
font-size: 22rpx; |
|||
line-height: 30rpx; |
|||
white-space: nowrap; |
|||
} |
|||
} |
|||
} |
|||
.section_1 { |
|||
margin-top: 24rpx; |
|||
padding: 131rpx 80rpx 848rpx; |
|||
background-color: rgb(255, 255, 255); |
|||
border-radius: 32rpx 32rpx 0px 0px; |
|||
.button { |
|||
padding: 26rpx 0; |
|||
color: rgb(85, 85, 85); |
|||
font-size: 30rpx; |
|||
font-weight: 500; |
|||
line-height: 42rpx; |
|||
white-space: nowrap; |
|||
background-color: rgb(247, 248, 250); |
|||
border-radius: 47rpx; |
|||
} |
|||
.button_1 { |
|||
margin-top: 64rpx; |
|||
padding: 26rpx 0; |
|||
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: 47rpx; |
|||
} |
|||
.text_9 { |
|||
margin-top: 22rpx; |
|||
align-self: center; |
|||
color: rgb(136, 136, 136); |
|||
font-size: 22rpx; |
|||
line-height: 30rpx; |
|||
white-space: nowrap; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,187 @@ |
|||
<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> |
|||
<view class="apply-area" v-if="!applyAgree"> |
|||
<view class="flex-row section_4"> |
|||
<text class="text_14">申请通过后可查看设备实时生产信息</text> |
|||
<view class="flex-col items-center button" @click="go2('apply-inspection', { factoryId: factoryId })"> |
|||
<text>申请验厂</text> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import { go2, back } from '@/utils/hook.js' |
|||
import { getEquipmentInfo } from '@/apis/factoryApi.js' |
|||
export default { |
|||
data() { |
|||
return { |
|||
info: { imgItemList: [] }, |
|||
id: null, |
|||
swiperCurrent: 0 |
|||
} |
|||
}, |
|||
onLoad(options) { |
|||
if (options.id) { |
|||
this.id = options.id |
|||
} |
|||
}, |
|||
onShow() { |
|||
if (this.id) { |
|||
getEquipmentInfo({ id: this.id }).then((res) => { |
|||
if (res) { |
|||
this.info = res |
|||
} |
|||
}) |
|||
} |
|||
}, |
|||
computed: { |
|||
applyAgree() { |
|||
let expireTime = this.$store.state.shareExpireTime |
|||
if (expireTime) { |
|||
let now = new Date().getTime() |
|||
if (now < expireTime) { |
|||
return true |
|||
} |
|||
} |
|||
return false |
|||
} |
|||
}, |
|||
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 |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</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; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
.apply-area { |
|||
position: fixed; |
|||
bottom: 0; |
|||
left: 0; |
|||
right: 0; |
|||
.section_4 { |
|||
margin-top: -55rpx; |
|||
padding: 16rpx 28rpx 16rpx 32rpx; |
|||
background-color: rgb(255, 255, 255); |
|||
box-shadow: 0px 2rpx 4rpx 0px rgba(0, 0, 0, 0.1); |
|||
position: relative; |
|||
.text_14 { |
|||
align-self: center; |
|||
color: rgb(51, 51, 51); |
|||
font-size: 26rpx; |
|||
line-height: 37rpx; |
|||
white-space: nowrap; |
|||
} |
|||
.button { |
|||
margin-left: 14rpx; |
|||
padding: 23rpx 0; |
|||
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; |
|||
width: 260rpx; |
|||
height: 88rpx; |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,241 @@ |
|||
<template> |
|||
<view class="content"> |
|||
<uni-nav-bar left-icon="back" @clickLeft="back" statusBar fixed title="设备生产信息"></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"> |
|||
<text>{{ curDevice.name }}</text> |
|||
</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 | formatTime }}</text> |
|||
<text class="text_11">工作时长/h</text> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
<view class="flex-col section_5"> |
|||
<view class="flex-col items-center group_9"> |
|||
<view class="camera_bg"></view> |
|||
<image @click="showLive" src="/static/imgs/device-info/camera-bg.png" class="image_7" /> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import { go2, back } from '@/utils/hook.js' |
|||
import { getShareDeviceInfo } from '@/apis/deviceApi' |
|||
import { getAccessToken } from '@/apis/factoryApi' |
|||
import { round } from '@/utils/index.js' |
|||
import { YINGSHI_LIVE_URL } from '@/enums/index.js' |
|||
export default { |
|||
data() { |
|||
return { |
|||
id: null, |
|||
dateRange: null, |
|||
curDevice: {} |
|||
} |
|||
}, |
|||
onLoad(options) { |
|||
if (options.id) { |
|||
this.id = options.id |
|||
this.getDeviceInfo() |
|||
} |
|||
}, |
|||
methods: { |
|||
go2, |
|||
back, |
|||
getDeviceInfo() { |
|||
getShareDeviceInfo({ |
|||
id: this.id, |
|||
startDate: this.dateRange ? this.dateRange[0] : null, |
|||
endDate: this.dateRange ? this.dateRange[1] : null |
|||
}).then((res) => { |
|||
this.curDevice = res |
|||
}) |
|||
}, |
|||
dateRangeChange(value) { |
|||
if (value) { |
|||
this.dateRange = [...value] |
|||
} else { |
|||
this.dateRange = null |
|||
} |
|||
}, |
|||
showLive() { |
|||
if (this.curDevice) { |
|||
getAccessToken().then((res) => { |
|||
if (res) { |
|||
console.log('res', res) |
|||
this.curDevice.accessToken = res |
|||
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.getDeviceInfo() |
|||
} |
|||
}, |
|||
filters: { |
|||
formatDate(time) { |
|||
return time.replace(/-/g, '.') |
|||
}, |
|||
formatTime(time) { |
|||
if (time) { |
|||
return round(time, 2) |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</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/device-info/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; |
|||
} |
|||
.group_8 { |
|||
padding: 28rpx 0 40rpx; |
|||
.section_3 { |
|||
padding: 22rpx 22rpx 36rpx; |
|||
flex: 1 1 308rpx; |
|||
background-image: url('/static/imgs/device-info/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/device-info/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%); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,124 @@ |
|||
<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> |
|||
<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> |
|||
@ -0,0 +1,576 @@ |
|||
<template> |
|||
<view> |
|||
<view class="flex-col group"> |
|||
<!-- 只能使用v-if,fixed会影响observer --> |
|||
<view class="justify-between header" v-if="showTitle"> |
|||
<text class="text">{{ factoryInfo.name || '-' }}</text> |
|||
</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="showBusinessImg"> |
|||
<text>营业执照</text> |
|||
</view> |
|||
</view> |
|||
<view class="flex-col group_7"> |
|||
<view class="flex-row"> |
|||
<image src="/static/imgs/factory/phone-blue-icon.png" class="image_3" /> |
|||
<text class="text_3">{{ factoryInfo.contactName || '-' }} {{ factoryInfo.contactMobile }}</text> |
|||
</view> |
|||
<view class="flex-row group_9"> |
|||
<image src="/static/imgs/factory/address-icon.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="jumpDeviceInfo(item)"> |
|||
<image mode="aspectFit" @click.stop="preview(item)" :src="item.imgItemList[0].url" 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.machineDescribe }} |
|||
</text> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
<view v-if="curTab == 'production'"> |
|||
<view class="grid"> |
|||
<view class="flex-col grid-item" v-for="production in productionList" :key="production.id" @click="go2('production-info', { id: production.id })"> |
|||
<text>{{ production.name }}</text> |
|||
<image mode="aspectFit" :src="production.imgItemList[0].url" class="image_7" /> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
<view class="observer">{{ hasMore ? '加载中~' : '没有更多~' }}</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
<view class="apply-area" v-if="!applyAgree"> |
|||
<view class="flex-row section_4"> |
|||
<text class="text_14">申请通过后可查看设备实时生产信息</text> |
|||
<view class="flex-col items-center button" @click="go2('apply-inspection', { factoryId: shareId })"> |
|||
<text>申请验厂</text> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import Banner from './Banner.vue' |
|||
import { go2 } from '@/utils/hook.js' |
|||
import { getFactoryInfo, getProductionList, getEquipmentList, getApplyInfo } from '@/apis/factoryApi.js' |
|||
import { fileType, applyStatus } 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, |
|||
shareId: null |
|||
} |
|||
}, |
|||
watch: { |
|||
curTab(val) { |
|||
// 重置 |
|||
this.hasMore = false |
|||
this.pagination.pageNum = 1 |
|||
this.getList() |
|||
} |
|||
}, |
|||
onLoad(options) { |
|||
// 企业id |
|||
if (options.shareId) { |
|||
this.shareId = options.shareId |
|||
} |
|||
// 通过的申请id |
|||
if (options.applyId) { |
|||
getApplyInfo({ |
|||
id: options.applyId |
|||
}).then((res) => { |
|||
if (res) { |
|||
if (res.status == applyStatus.AGREE) { |
|||
res.expireTime = res.expireTime.replace(/-/g, '/') |
|||
let timeStamp = new Date(res.expireTime).getTime() |
|||
this.$store.commit('setShareExpireTime', timeStamp) |
|||
} |
|||
if (res.status == applyStatus.REJECT) { |
|||
uni.showToast({ |
|||
title: '您的申请已被拒绝', |
|||
icon: 'error' |
|||
}) |
|||
} |
|||
} |
|||
}) |
|||
} |
|||
}, |
|||
computed: { |
|||
applyAgree() { |
|||
let expireTime = this.$store.state.shareExpireTime |
|||
if (expireTime) { |
|||
let now = new Date().getTime() |
|||
if (now < expireTime) { |
|||
return true |
|||
} |
|||
} |
|||
return false |
|||
} |
|||
}, |
|||
onShow() { |
|||
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, |
|||
showBusinessImg() { |
|||
// 营业执照 |
|||
uni.previewImage({ |
|||
urls: [this.factoryInfo.businessLicenseImg], |
|||
current: 0 |
|||
}) |
|||
}, |
|||
getCompanyInfo() { |
|||
getFactoryInfo({ id: this.shareId }).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 |
|||
} |
|||
} |
|||
}) |
|||
} |
|||
}) |
|||
}, |
|||
selectTab(tab) { |
|||
this.pagination.pageNum = 1 |
|||
this.curTab = tab |
|||
}, |
|||
// 获取列表 |
|||
getList() { |
|||
if (this.curTab == 'device') { |
|||
getEquipmentList({ ...this.pagination, enterpriseId: this.shareId }).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 |
|||
} |
|||
}) |
|||
} |
|||
if (this.curTab == 'production') { |
|||
getProductionList({ ...this.pagination, enterpriseId: this.shareId }).then((res) => { |
|||
if (res) { |
|||
if (res.current <= 1) { |
|||
this.productionList = res.records |
|||
} else { |
|||
this.productionList = this.productionList.concat(res.records) |
|||
} |
|||
this.hasMore = this.productionList.length < res.total |
|||
} |
|||
}) |
|||
} |
|||
}, |
|||
preview(device) { |
|||
let urls = device.imgItemList.map((item) => { |
|||
return item.url |
|||
}) |
|||
uni.previewImage({ |
|||
current: 0, |
|||
urls |
|||
}) |
|||
}, |
|||
jumpDeviceInfo(item) { |
|||
if (this.applyAgree) { |
|||
if (!item.cloudBoxId) { |
|||
uni.showModal({ |
|||
title: '提示', |
|||
content: '该设备未绑定云盒,点击确定跳转到设备信息页', |
|||
success: (res) => { |
|||
if (res.confirm) { |
|||
this.go2('deviceInfo', { |
|||
id: item.id |
|||
}) |
|||
} |
|||
} |
|||
}) |
|||
} else { |
|||
go2('device-production-detail', { id: item.id, factoryId: this.shareId }) |
|||
} |
|||
} else { |
|||
go2('device-info', { id: item.id }) |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</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 { |
|||
background-color: rgb(0, 0, 0); |
|||
margin-right: 24rpx; |
|||
width: 638rpx; |
|||
height: 390rpx; |
|||
} |
|||
.group_13 { |
|||
margin-top: 20rpx; |
|||
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-top: 12rpx; |
|||
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; |
|||
} |
|||
} |
|||
} |
|||
.section_6 { |
|||
padding-top: 40rpx; |
|||
overflow: hidden; |
|||
border-radius: 40rpx 40rpx 0px 0px; |
|||
background-color: rgb(255, 255, 255); |
|||
height: 408rpx; |
|||
.text_13 { |
|||
align-self: center; |
|||
color: rgb(51, 51, 51); |
|||
font-size: 28rpx; |
|||
font-weight: 500; |
|||
line-height: 40rpx; |
|||
white-space: nowrap; |
|||
} |
|||
.group_20 { |
|||
margin-top: 40rpx; |
|||
.group_21 { |
|||
padding: 0 48rpx 32rpx; |
|||
color: rgb(51, 51, 51); |
|||
font-size: 24rpx; |
|||
line-height: 33rpx; |
|||
white-space: nowrap; |
|||
.group_23 { |
|||
width: 494rpx; |
|||
.image_15 { |
|||
width: 96rpx; |
|||
height: 96rpx; |
|||
} |
|||
.text_15 { |
|||
margin-left: 12rpx; |
|||
margin-top: 16rpx; |
|||
} |
|||
} |
|||
.image_14 { |
|||
border-radius: 50%; |
|||
width: 96rpx; |
|||
height: 96rpx; |
|||
} |
|||
.text_14 { |
|||
margin-top: 16rpx; |
|||
} |
|||
} |
|||
.section_7 { |
|||
background-color: rgb(247, 248, 250); |
|||
height: 16rpx; |
|||
} |
|||
.button { |
|||
padding: 26rpx 0; |
|||
color: rgb(51, 51, 51); |
|||
font-size: 32rpx; |
|||
line-height: 45rpx; |
|||
white-space: nowrap; |
|||
background-color: rgb(255, 255, 255); |
|||
} |
|||
} |
|||
} |
|||
.grid { |
|||
padding: 20rpx 32rpx 91rpx; |
|||
width: 750rpx; |
|||
color: rgb(31, 31, 31); |
|||
font-size: 28rpx; |
|||
font-weight: 500; |
|||
line-height: 40rpx; |
|||
white-space: nowrap; |
|||
display: grid; |
|||
grid-template-columns: repeat(2, 1fr); |
|||
grid-row-gap: 22rpx; |
|||
grid-column-gap: 16rpx; |
|||
.grid-item { |
|||
padding: 24rpx 20rpx 20rpx; |
|||
border-radius: 10rpx; |
|||
filter: drop-shadow(0px 5rpx 11rpx #00000014); |
|||
background-color: rgb(255, 255, 255); |
|||
background-position: 0px 0px; |
|||
background-size: 100% 100%; |
|||
background-repeat: no-repeat; |
|||
.image_7 { |
|||
margin-top: 20rpx; |
|||
width: 296rpx; |
|||
height: 296rpx; |
|||
} |
|||
} |
|||
} |
|||
.apply-area { |
|||
position: fixed; |
|||
bottom: 0; |
|||
left: 0; |
|||
right: 0; |
|||
.section_4 { |
|||
margin-top: -55rpx; |
|||
padding: 16rpx 28rpx 16rpx 32rpx; |
|||
background-color: rgb(255, 255, 255); |
|||
box-shadow: 0px 2rpx 4rpx 0px rgba(0, 0, 0, 0.1); |
|||
position: relative; |
|||
.text_14 { |
|||
align-self: center; |
|||
color: rgb(51, 51, 51); |
|||
font-size: 26rpx; |
|||
line-height: 37rpx; |
|||
white-space: nowrap; |
|||
} |
|||
.button { |
|||
margin-left: 14rpx; |
|||
padding: 23rpx 0; |
|||
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; |
|||
width: 260rpx; |
|||
height: 88rpx; |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,64 @@ |
|||
<template> |
|||
<view> |
|||
<web-view :src="url"></web-view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import { back } from '@/utils/hook.js' |
|||
import { makeSocket } from '@/utils/index.js' |
|||
export default { |
|||
data() { |
|||
return { |
|||
url: '', |
|||
socket: null |
|||
} |
|||
}, |
|||
onLoad(option) { |
|||
if (option) { |
|||
this.url = decodeURIComponent(option.url) |
|||
console.log(this.url, option) |
|||
} 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: { |
|||
getMessage(data) { |
|||
// 签约成功 |
|||
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> |
|||
@ -0,0 +1,134 @@ |
|||
<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.produceDescribe || '没有描述' }} |
|||
</text> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
import { go2, back } from '@/utils/hook.js' |
|||
import { getProductionInfo } from '@/apis/factoryApi.js' |
|||
export default { |
|||
data() { |
|||
return { |
|||
info: { imgItemList: [] }, |
|||
id: null, |
|||
swiperCurrent: 0 |
|||
} |
|||
}, |
|||
onLoad(options) { |
|||
if (options.id) { |
|||
this.id = options.id |
|||
} |
|||
}, |
|||
onShow() { |
|||
if (this.id) { |
|||
getProductionInfo({ 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 |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
</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; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
Write
Preview
Loading…
Cancel
Save