Browse Source

远程验厂

devlop
mo-bai 4 years ago
parent
commit
7dbf5e0029
31 changed files with 2129 additions and 637 deletions
  1. 146
      apis/commonApi.js
  2. 40
      apis/deviceApi.js
  3. 85
      apis/factoryApi.js
  4. 36
      components/qn-easyinput/qn-easyinput.vue
  5. 229
      enums/index.js
  6. 4
      env/index.js
  7. 151
      pages.json
  8. 82
      pages/agreement/index.vue
  9. 246
      pages/apply-inspection/index.vue
  10. 223
      pages/certification/index.vue
  11. 187
      pages/device-info/index.vue
  12. 241
      pages/device-production-detail/index.vue
  13. 124
      pages/factory-inspection/Banner.vue
  14. 576
      pages/factory-inspection/index.vue
  15. 64
      pages/page-view/index.vue
  16. 134
      pages/production-info/index.vue
  17. BIN
      static/imgs/device-info/camera-bg.png
  18. BIN
      static/imgs/device-info/clock.png
  19. BIN
      static/imgs/device-info/close-icon.png
  20. BIN
      static/imgs/device-info/device-detail-bg.png
  21. BIN
      static/imgs/device-info/down-arrow-icon.png
  22. BIN
      static/imgs/device-info/factory-avatar.png
  23. BIN
      static/imgs/device-info/gear.png
  24. BIN
      static/imgs/device-info/logo.png
  25. BIN
      static/imgs/device-info/select-icon.png
  26. BIN
      static/imgs/device-info/selected-icon.png
  27. BIN
      static/imgs/factory/address-icon.png
  28. BIN
      static/imgs/factory/phone-blue-icon.png
  29. 158
      store/index.js
  30. 2
      utils/http/index.js
  31. 38
      utils/index.js

146
apis/commonApi.js

@ -88,148 +88,14 @@ export function getBaseInfo(data = {}, refresh = false) {
}
/**
* 获取当前账号的企业实名认证地址
* @param {object} data 参数 enterpriseId
* 手机登录获取验证码接口
* @param {object} data 获取验证码参数
* @returns 获取验证码结果
* swagger:http://api-ops-uec-test.qniao.cn/uec/swagger-ui/index.html?urls.primaryName=CustomerApi#/%E7%99%BB%E5%BD%95%E8%AE%A4%E8%AF%81/authorizeByCaptchaUsingPOST
*/
export function getVerifyUrl(data = {}) {
export const getAuthCaptcha = (data) => {
return http.post({
url: '/yyt-uec/get/fdd-enterprise-verify-url?enterpriseId=' + data.enterpriseId,
url: '/uec/get/auth-captcha',
data
})
}
/**
* 生成担保合同的签约地址同意纸盘商只需要签约一次即可
* @param {object} data 参数 mallSupplierId
*/
export function getGuaranteeContract(data = {}) {
return http.post({
url: '/yyt-uec/create/supplier/guarantee-contract?mallSupplierId=' + data.mallSupplierId,
data
})
}
/**
* 获取当前账号企业的飞算额度
* @param {object} data 参数 enterpriseId
*/
export function getFsCredit(data = {}) {
return http.get({
url: '/yyt-uec/credit/get/enterprise-feisuan-credit',
data
})
}
/**
* 获取当前账号企业的被担保的月结额度
* @param {object} data 参数 enterpriseId supplierId
*/
export function getMonthCredit(data = {}) {
return http.get({ url: '/yyt-uec/customer/get/supplier-credit', data })
}
/**
* 转换合同成图片
* @param {object} data 图片地址链接 fileUrl
*/
export function transformFileToImg(data) {
return http.get({
url: '/document/get/enterprise-documents/file-image-base64',
data: data
})
}
/**
* 获取飞算地址
*/
export function getFeisuanUrl(data = {}) {
return http.get({
url: '/yyt-uec/feisuan/feisuan-apply-url.json',
data: data
})
}
/**
* 营业执照OCR识别 photoUrl
*/
export function getLicenseOcr(data = {}) {
return http.post({
url: '/base-paper-trading/ocr/business-license',
data: data
})
}
/**
* 身份证正面OCR识别 image
*/
export function getFrontIdCardOcr(data = {}) {
return http.post({
url: '/base-paper-trading/ocr/id-card/face',
data: data
})
}
/**
* 身份证背面OCR识别 image
*/
export function getBackIdCardOcr(data = {}) {
return http.post({
url: '/base-paper-trading/ocr/id-card/back',
data: data
})
}
/**
* 纸盘商开通会员,创建订单
* @param {object} data
* @value {string} type
* @value {string} enterpriseId
*/
export function openVip(data = {}) {
return http.post({
url: `/yyt-uec/customer/apply/for/vip?type=${data.type}&enterpriseId=${data.enterpriseId}`,
data: data
})
}
/**
* 纸盘商开通会员,真实支付
* @param {object} data
* @value {string} tradeOrderId
* @value {string} channelId
* @param {string} userOpenId 用户openId
*/
export function openVipPay(data = {}) {
return http.post({
url: PAY_URL + `?userOpenId=${data.userOpenId}`,
data: data
})
}
/**
* 获取用户openId
* @param {object} data
* @value {string} authCode 授权码
* @value {string} authMethod 3WeChatServiceAccount
*/
export function getOpenId(data = {}) {
return http.post({
url: '/uec/get/user-openid/by-oauth2',
data: data
})
}
/**
* 绑定纸盘商销售id
* @param {object} data
* @value {string} customerEnterpriseId 客户企业id
* @value {string} customerId 客户id
* @value {string} sellerId 纸盘商销售id
* @value {string} sellerSupplierId 纸盘商id
*/
export function bindUser(data = {}) {
return http.post({
url: '/yyt-uec/seller/bound/customer',
data: data
})
}

40
apis/deviceApi.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
})
}

85
apis/factoryApi.js

@ -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
})
}

36
components/qn-easyinput/qn-easyinput.vue

@ -232,23 +232,12 @@ export default {
},
watch: {
value(newVal) {
if (this.errMsg) this.errMsg = ''
this.val = newVal
// fix by mehaotian is_reset uni-forms
if (this.form && this.formItem && !this.is_reset) {
this.is_reset = false
this.formItem.setValue(newVal)
}
this.resetValue(newVal)
},
modelValue(newVal) {
if (this.errMsg) this.errMsg = ''
this.val = newVal
if (this.form && this.formItem && !this.is_reset) {
this.is_reset = false
this.formItem.setValue(newVal)
}
this.resetValue(newVal)
},
focus(newVal) {
focus() {
this.$nextTick(() => {
this.focused = this.focus
})
@ -280,6 +269,17 @@ export default {
})
},
methods: {
/**
* 监听value modelValue 变化
*/
resetValue(newVal) {
if (this.errMsg) this.errMsg = ''
this.val = newVal
if (this.form && this.formItem && !this.is_reset) {
this.is_reset = false
this.formItem.setValue(newVal)
}
},
onClickIcon(type) {
this.$emit('iconClick', type)
},
@ -313,9 +313,7 @@ export default {
}
if (this.errMsg) this.errMsg = ''
this.val = value
// vue2
this.$emit('input', value)
//  vue3
this.$emit('update:modelValue', value)
},
@ -330,10 +328,7 @@ export default {
},
onClear() {
this.val = ''
// vue2
this.$emit('input', '')
// vue2
//  vue3
this.$emit('update:modelValue', '')
},
fieldClick() {
@ -381,7 +376,8 @@ $uni-border-1: #dcdfe6 !default;
width: 100%;
display: flex;
box-sizing: border-box;
min-height: 36px;
// min-height: 21px;
height: 100%;
/* #endif */
flex-direction: row;
align-items: center;

229
enums/index.js

@ -7,6 +7,13 @@ export const XAPPID = '503258978847966408'
export const PAY_URL = `https://api-client-psc${urlEnv}.qniao.cn/payment-settlement-center/pay-for-service-account`
// 当前支付页面地址
export const VIP_URL = `https://shopkeeper${urlEnv}.qniao.cn/#/pages/vip-center/index`
/**
* 萤石云直播地址
* @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&`
/**
* 账号类型
@ -28,32 +35,21 @@ export const encryptType = {
}
/**
* 验证码用途
* 是否加密 不加密0 加密1
*/
export const codePurpose = {
CERTIFICATION: 1,
RESET_LOGIN_PASSWORD: 2,
RESET_PHONE: 3,
BIND_BANK_CARD: 4,
RESET_CREDIT_PASSWORD: 5
export const isEncrypt = {
NO: 0,
YES: 1
}
/**
* 可验证账号类型
*/
export const verificationType = {
PHONE: 1,
EMAIL: 2
}
/**
* 法大大企业认证状态 1:未认证 2:认证中 3:已认证 4:认证失败
* 文件类型 图片1视频2
*/
export const fddEnterpriseStatus = {
UNCERTIFIED: 1,
CERTIFIED_ING: 2,
CERTIFIED_SUCCESS: 3,
CERTIFIED_FAIL: 4
export const fileType = {
IMG: 1,
VIDEO: 2
}
/**
* 上传地址
*/
@ -62,191 +58,28 @@ export const uploadUrl = {
file: `https://api-client-yyt${urlEnv}.qniao.cn/yyt-uec/file-uploading/upload/file`
}
/**
* 结算周期1月结30飞算1期2月结453月结60飞算2期4月结755月结90飞算3期
*/
export const settlementPeriodEnum = [
{
value: 1,
label: '月结30'
},
{
value: 2,
label: '月结45'
},
{
value: 3,
label: '月结60'
},
{
value: 4,
label: '月结75'
},
{
value: 5,
label: '月结90'
}
]
/**
* 结算周期112233
*/
export const fsSettlementPeriodEnum = [
{
value: 1,
label: '1期'
},
{
value: 2,
label: '2期'
},
{
value: 3,
label: '3期'
}
]
/**
* 飞算结算方式 1: 先息后本
*/
export const fsSettlementMethodEnum = [
{
value: 1,
label: '先息后本'
}
]
/**
* 飞算授信审核状态 0: 待客户申请 1: 审核中 2: 通过 3: 拒绝
* 申请状态 1:已提交 2:已同意 3:已拒绝
*/
export const fsAuditStatus = {
WAIT_APPLY: 0,
AUDITING: 1,
PASS: 2,
export const applyStatus = {
SUBMIT: 1,
AGREE: 2,
REJECT: 3
}
/**
* 客户订单状态 0: 全部 ; 30100: 待确认 ; 30204: 待供应商确认 ; 30101: 已下单 ; 30104: 已完成 ; 30105: 已取消
*/
export const orderStatusEnum = {
ALL: 0,
WAIT_CONFIRM: 30100,
WAIT_SUPPLIER_CONFIRM: 30204,
ORDERED: 30101,
FINISHED: 30104,
CANCELED: 30105
}
/**
* 客户订单状态 0: 全部 ; 30100: 待确认 ; 30204: 待供应商确认 ; 30101: 已下单 ; 30104: 已完成 ;
*/
export const orderStatusArray = [
{
value: orderStatusEnum.ALL,
label: '全部'
},
{
value: orderStatusEnum.WAIT_CONFIRM,
label: '待确认'
},
{
value: orderStatusEnum.WAIT_SUPPLIER_CONFIRM,
label: '待供应商确认'
},
{
value: orderStatusEnum.ORDERED,
label: '已下单'
},
{
value: orderStatusEnum.FINISHED,
label: '已完成'
},
{
value: orderStatusEnum.CANCELED,
label: '已取消'
}
]
export const orderStatusMap = {
[orderStatusEnum.ALL]: '全部',
[orderStatusEnum.WAIT_CONFIRM]: '待确认',
[orderStatusEnum.WAIT_SUPPLIER_CONFIRM]: '待供应商确认',
[orderStatusEnum.ORDERED]: '已下单',
[orderStatusEnum.FINISHED]: '已完成',
[orderStatusEnum.CANCELED]: '已取消'
}
/**
* 供应商订单状态 待客户确认订单/30202,待供应商确认订单/30205,待发货/30106,已发货/30107 已发货在H5客户端显示 待收货/30107 ,待客户借款/30207,支付中/30208,待客户支付/30214,付款失败/30211,已完成/30213,待客户还款/30217,已取消/30212,还款中/30216
*/
export const supplierOrderStatusEnum = {
WAIT_CLIENT_CONFIRM: 30202,
WAIT_SUPPLIER_CONFIRM: 30205,
WAIT_DELIVERY: 30106,
WAIT_RECEIVE: 30107,
WAIT_CLIENT_LOAN: 30207,
PAYING: 30208,
WAIT_CLIENT_PAY: 30214,
PAY_FAIL: 30211,
FINISHED: 30213,
WAIT_CLIENT_REPAY: 30217,
REPAYING: 30216,
CANCELED: 30212
}
/**
* 供应商订单状态 待客户确认订单/30202,待供应商确认订单/30205,待发货/30106,已发货/30107 已发货在H5客户端显示 待收货/30107 ,待客户借款/30207,支付中/30208,待客户支付/30214,付款失败/30211,已完成/30213,待客户还款/30217,已取消/30212,还款中/30216
*/
export const supplierOrderStatusMap = {
[supplierOrderStatusEnum.WAIT_CLIENT_CONFIRM]: '待客户确认',
[supplierOrderStatusEnum.WAIT_SUPPLIER_CONFIRM]: '待供应商确认',
[supplierOrderStatusEnum.WAIT_DELIVERY]: '待发货',
[supplierOrderStatusEnum.WAIT_RECEIVE]: '待收货',
[supplierOrderStatusEnum.WAIT_CLIENT_LOAN]: '待借款',
[supplierOrderStatusEnum.PAYING]: '支付中',
[supplierOrderStatusEnum.WAIT_CLIENT_PAY]: '待支付',
[supplierOrderStatusEnum.PAY_FAIL]: '付款失败',
[supplierOrderStatusEnum.FINISHED]: '已完成',
[supplierOrderStatusEnum.WAIT_CLIENT_REPAY]: '待还款',
[supplierOrderStatusEnum.REPAYING]: '还款中',
[supplierOrderStatusEnum.CANCELED]: '已取消'
}
/**
* 支付方式 1:微信支付 2:月结支付 4:飞算支付
*/
export const paymentMethodEnum = {
WECHAT_PAY: 1,
MONTHLY_PAY: 2,
FLY_PAY: 4
}
export const paymentMethodMap = {
[paymentMethodEnum.WECHAT_PAY]: '微信支付',
[paymentMethodEnum.MONTHLY_PAY]: '月结支付',
[paymentMethodEnum.FLY_PAY]: '飞算支付'
}
/**
* 订单是否开票 1:开票 0:不开票
* 默认开票
* 验证码用途
*/
export const invoiceStatusEnum = {
INVOICE: 1,
NO_INVOICE: 0
}
export const invoiceStatusMap = {
[invoiceStatusEnum.INVOICE]: '开票',
[invoiceStatusEnum.NO_INVOICE]: '不开票'
export const codePurpose = {
CERTIFICATION: 1,
RESET_LOGIN_PASSWORD: 2,
RESET_PHONE: 3,
BIND_BANK_CARD: 4,
RESET_CREDIT_PASSWORD: 5
}
/**
* 库存单位 1: 2:
* 可验证账号类型
*/
export const stockUnitEnum = {
SHEET: 1,
TON: 2
}
export const stockUnitMap = {
[stockUnitEnum.SHEET]: '张',
[stockUnitEnum.TON]: '吨'
export const verificationType = {
PHONE: 1,
EMAIL: 2
}

4
env/index.js

@ -1,8 +1,8 @@
/**
* @description 唯一环境变量
*/
// const env = 'test'
const env = 'test'
// const env = 'dev'
const env = 'production'
// const env = 'production'
export default env

151
pages.json

@ -1,35 +1,5 @@
{
"pages": [
{
"path": "pages/store/index",
"style": {
"navigationBarTitleText": "店铺首页",
"navigationStyle": "custom"
},
"h5": { "titleNView": false }
},
{
"path": "pages/cart/index",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "购物车"
}
},
{
"path": "pages/mine/index",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "个人中心"
}
},
{
"path": "pages/login/index",
"style": {
"navigationBarTitleText": "登录",
"navigationStyle": "custom",
"enablePullDownRefresh": false
}
},
{
"path": "pages/agreement/index",
"style": {
@ -46,123 +16,52 @@
}
},
{
"path": "pages/notification-page/index",
"path": "pages/device-info/index",
"style": {
"navigationBarTitleText": "统一第三方通知页面",
"enablePullDownRefresh": false
}
},
{
"path": "pages/enterprise-info/index",
"style": {
"navigationBarTitleText": "完善企业信息",
"navigationBarTitleText": "设备信息",
"enablePullDownRefresh": false,
"navigationStyle": "custom"
}
},
{
"path": "pages/enterprise-info-edit/index",
"path": "pages/device-production-detail/index",
"style": {
"navigationBarTitleText": "修改企业信息",
"navigationBarTitleText": "设备生产详情",
"enablePullDownRefresh": false,
"navigationStyle": "custom"
}
},
{
"path": "pages/address-manage/index",
"path": "pages/factory-inspection/index",
"style": {
"navigationBarTitleText": "收货地址",
"navigationBarTitleText": "远程验厂",
"enablePullDownRefresh": false,
"navigationStyle": "custom"
}
},
{
"path": "pages/error/index",
"path": "pages/production-info/index",
"style": {
"navigationBarTitleText": "页面不存在",
"navigationBarTitleText": "产品信息",
"enablePullDownRefresh": false,
"navigationStyle": "custom"
}
},
{
"path": "pages/order-list/index",
"path": "pages/apply-inspection/index",
"style": {
"navigationBarTitleText": "订单列表",
"navigationBarTitleText": "验厂申请",
"enablePullDownRefresh": false,
"navigationStyle": "custom"
}
},
{
"path": "pages/order-make/index",
"path": "pages/certification/index",
"style": {
"navigationBarTitleText": "创建订单",
"navigationBarTitleText": "信息验证",
"enablePullDownRefresh": false,
"navigationStyle": "custom"
}
},
{
"path": "pages/order-detail/index",
"style": {
"navigationBarTitleText": "订单详情",
"enablePullDownRefresh": false,
"navigationStyle": "custom"
}
},
{
"path": "pages/paper-details/index",
"style": {
"navigationBarTitleText": "纸品详情",
"navigationStyle": "custom",
"enablePullDownRefresh": false
}
},
{
"path": "pages/enquiry-list/index",
"style": {
"navigationBarTitleText": "询价列表",
"navigationStyle": "custom",
"enablePullDownRefresh": false
}
},
{
"path": "pages/for-comparison/index",
"style": {
"navigationBarTitleText": "实单询比价",
"navigationStyle": "custom",
"enablePullDownRefresh": false
}
},
{
"path": "pages/add-address-manage/index",
"style": {
"navigationBarTitleText": "新建收货地址",
"navigationStyle": "custom",
"enablePullDownRefresh": false
}
},
{
"path": "pages/account-management/index",
"style": {
"navigationBarTitleText": "账号管理",
"navigationStyle": "custom",
"enablePullDownRefresh": false
}
},
{
"path": "pages/add-account/index",
"style": {
"navigationBarTitleText": "新增企业账号",
"navigationStyle": "custom",
"enablePullDownRefresh": false
}
},
{
"path": "pages/vip-center/index",
"style": {
"navigationBarTitleText": "会员中心",
"navigationStyle": "custom",
"enablePullDownRefresh": false
}
}
],
"globalStyle": {
@ -171,32 +70,6 @@
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8"
},
"tabBar": {
"color": "#888",
"selectedColor": "#007AFF",
"borderStyle": "white",
"backgroundColor": "#f9f9f9",
"list": [
{
"pagePath": "pages/store/index",
"iconPath": "static/imgs/tabbar/store-gray.png",
"selectedIconPath": "static/imgs/tabbar/store-blue.png",
"text": "店铺首页"
},
{
"pagePath": "pages/cart/index",
"iconPath": "static/imgs/tabbar/cart-gray.png",
"selectedIconPath": "static/imgs/tabbar/cart-blue.png",
"text": "购物车"
},
{
"pagePath": "pages/mine/index",
"iconPath": "static/imgs/tabbar/mine-gray.png",
"selectedIconPath": "static/imgs/tabbar/mine-blue.png",
"text": "个人中心"
}
]
},
"condition": {
//
"current": 0, //(list )

82
pages/agreement/index.vue

@ -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>

246
pages/apply-inspection/index.vue

@ -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>

223
pages/certification/index.vue

@ -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>

187
pages/device-info/index.vue

@ -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>

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

@ -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>

124
pages/factory-inspection/Banner.vue

@ -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>

576
pages/factory-inspection/index.vue

@ -0,0 +1,576 @@
<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>
<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>

64
pages/page-view/index.vue

@ -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>

134
pages/production-info/index.vue

@ -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>

BIN
static/imgs/device-info/camera-bg.png

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

BIN
static/imgs/device-info/clock.png

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

BIN
static/imgs/device-info/close-icon.png

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

BIN
static/imgs/device-info/device-detail-bg.png

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

BIN
static/imgs/device-info/down-arrow-icon.png

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

BIN
static/imgs/device-info/factory-avatar.png

Before After
Width: 160  |  Height: 160  |  Size: 44 KiB

BIN
static/imgs/device-info/gear.png

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

BIN
static/imgs/device-info/logo.png

Before After
Width: 67  |  Height: 81  |  Size: 4.5 KiB

BIN
static/imgs/device-info/select-icon.png

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

BIN
static/imgs/device-info/selected-icon.png

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

BIN
static/imgs/factory/address-icon.png

Before After
Width: 27  |  Height: 30  |  Size: 1.2 KiB

BIN
static/imgs/factory/phone-blue-icon.png

Before After
Width: 28  |  Height: 28  |  Size: 1.1 KiB

158
store/index.js

@ -1,7 +1,6 @@
import Vue from 'vue'
import Vuex from 'vuex'
import { isObject, isArray } from '@/utils/is'
import { bindUser } from '@/apis/commonApi'
let qnToken = null,
/**
@ -11,43 +10,25 @@ let qnToken = null,
* @value mobile 手机号
*/
userInfo = null,
/**
* @value id 企业id
* @value name 企业名称
* @value fddEnterpriseStatus 法大大认证状态 1未认证2认证进行中3认证成功4认证失败
* @value isVip 是否是vip
* @value vipExpireTime vip过期时间
*/
companyInfo = null,
uecToken = null,
searchHistory = null,
/**
* @value supplierId 当前被分享的供应商id
* @value id 当前被分享的供应商账号id
*/
supplierId = null,
userId = null,
/**
* @value id 当前被分享的供应商账号id
* @value shareExpireTime 申请验厂通过的过期时间
*/
userId = null
const companyInfoParams = ['id', 'name', 'fddEnterpriseStatus', 'isVip', 'vipExpireTime']
shareExpireTime = 0
const userInfoParams = ['name', 'userId', 'mobile', 'avatar']
try {
uecToken = uni.getStorageSync('uecToken')
qnToken = uni.getStorageSync('qnToken')
supplierId = uni.getStorageSync('supplierId')
userId = uni.getStorageSync('userId')
shareExpireTime = uni.getStorageSync('shareExpireTime')
userInfo = uni.getStorageSync('userInfo')
searchHistory = uni.getStorageSync('searchHistory')
if (searchHistory) {
searchHistory = JSON.parse(searchHistory)
}
if (userInfo) {
userInfo = JSON.parse(userInfo)
}
companyInfo = uni.getStorageSync('companyInfo')
if (companyInfo) {
companyInfo = JSON.parse(companyInfo)
}
} catch (e) {
console.error('初始化错误:', e)
}
@ -57,15 +38,13 @@ const store = new Vuex.Store({
state: {
uecToken: uecToken || '',
qnToken: qnToken || '', // token
supplierId: supplierId || '', // 供应商id
userId: userId || '', // 供应商账号id
userInfo: userInfo || {}, // 用户信息
companyInfo: companyInfo || {}, // 印包厂信息
shareExpireTime: shareExpireTime || 0, // 申请验厂通过的过期时间
nextPage: {
name: '',
data: {}
},
searchHistory: searchHistory || [],
/**
* 监听cache的type即可,每次取值后都必须调用commit('resetCache')
*/
@ -166,66 +145,6 @@ const store = new Vuex.Store({
console.error('删除userInfo失败:', e)
}
},
setCompanyInfo(state, companyInfo) {
if (!isObject(companyInfo)) {
console.error('companyInfo必须是对象')
return
}
for (let companyInfoParam of companyInfoParams) {
if (companyInfo[companyInfoParam] === undefined) {
console.error(`companyInfo必须包含${companyInfoParam}`)
return
}
}
try {
uni.setStorageSync('companyInfo', JSON.stringify(companyInfo))
state.companyInfo = companyInfo
// 绑定供应商销售账号
if (state.userId && state.userInfo.userId) {
bindUser({
customerEnterpriseId: companyInfo.id,
sellerId: state.userId,
sellerSupplierId: state.supplierId,
customerId: state.userInfo.userId
})
}
} catch (e) {
console.error('设置companyInfo失败:', e)
}
},
/**
* 更改当前供应商信息
* @param {*} state 状态
* @param {arr} map 以key-value形式存储的数组
* @value key 需要更改的key
* @value value 更改后的值
*/
changeCompanyInfo(state, map) {
if (!isArray(map)) {
console.error('map必须是数组')
return
}
let companyInfo = state.companyInfo
map.forEach((item) => {
if (companyInfoParams.includes(item.key)) {
companyInfo[item.key] = item.value
}
})
try {
uni.setStorageSync('companyInfo', JSON.stringify(companyInfo))
state.companyInfo = companyInfo
} catch (e) {
console.error('更改companyInfo失败:', e)
}
},
removeCompanyInfo(state) {
try {
uni.removeStorageSync('companyInfo')
state.companyInfo = {}
} catch (e) {
console.error('删除companyInfo失败:', e)
}
},
setNextPage(state, nextPage) {
if (!isObject(nextPage)) {
console.error('nextPage必须是对象')
@ -238,42 +157,6 @@ const store = new Vuex.Store({
state.nextPage.name = ''
state.nextPage.data = {}
},
setSearchHistory(state, searchHistory) {
if (!isArray(searchHistory)) {
console.error('searchHistory必须是数组')
return
}
try {
uni.setStorageSync('searchHistory', JSON.stringify(searchHistory))
state.searchHistory = searchHistory
} catch (e) {
console.error('更改searchHistory失败:', e)
}
},
clearSearchHistory(state) {
try {
uni.removeStorageSync('searchHistory')
state.searchHistory = []
} catch (e) {
console.error('删除searchHistory失败:', e)
}
},
setSupplierId(state, id) {
try {
uni.setStorageSync('supplierId', id)
state.supplierId = id
} catch (e) {
console.error('更改supplierId失败:', e)
}
},
removeSupplierId(state) {
try {
uni.removeStorageSync('supplierId')
state.supplierId = ''
} catch (e) {
console.error('删除supplierId失败:', e)
}
},
setUserId(state, id) {
try {
uni.setStorageSync('userId', id)
@ -289,6 +172,22 @@ const store = new Vuex.Store({
} catch (e) {
console.error('删除userId失败:', e)
}
},
setShareExpireTime(state, timeStamp) {
try {
uni.setStorageSync('shareExpireTime', timeStamp)
state.shareExpireTime = timeStamp
} catch (e) {
console.error('更改shareExpireTime失败:', e)
}
},
removeShareExpireTime(state) {
try {
uni.removeStorageSync('shareExpireTime')
state.shareExpireTime = 0
} catch (e) {
console.error('删除shareExpireTime失败:', e)
}
}
},
actions: {
@ -296,19 +195,6 @@ const store = new Vuex.Store({
commit('removeUecToken')
commit('removeToken')
commit('removeUserInfo')
commit('removeCompanyInfo')
},
addSearchHistory({ commit, state }, searchHistory) {
let arr = [...state.searchHistory] // 单层数组直接解构
let index = arr.findIndex((item) => item === searchHistory)
if (index > -1) {
arr.splice(index, 1)
}
arr.unshift(searchHistory)
if (arr.length > 10) {
arr = arr.slice(0, 10)
}
commit('setSearchHistory', arr)
}
}
})

2
utils/http/index.js

@ -107,7 +107,7 @@ const resInterceptor = (response, options) => {
return res.data === null ? 1 : res.data
} else {
uni.showToast({
title: res.message,
title: res.message || res.msg,
icon: 'none'
})
return null

38
utils/index.js

@ -1,6 +1,6 @@
import env from '@/env/index.js'
import store from '@/store/index.js'
import { isDate, isString } from './is.js'
import { isDate, isString, isArray } from './is.js'
/**
* 日期格式化样例 yyyy-mm-dd hh:MM:ss
* @param date Date 需要转换的日期
@ -164,3 +164,39 @@ export const difTime = (time, target) => {
seconds
}
}
/**
* 根据规则校验字段
* @param {*} value 输入值
* @param {array} rules 规则集 {type,required,message}
* @value {boolean} required 是否必填
* @value {string} type 字段类型校验目前支持 phone
* @returns {object} {isValid,msg}
*/
export const validateField = (value, rules) => {
let isValid = true
let msg = ''
for (let rule of rules) {
if (rule.required) {
if (value === '' || value === undefined || value === null) {
isValid = false
msg = rule.message
break
}
if (isArray(value) && value.length === 0) {
isValid = false
msg = rule.message
break
}
}
if (rule.type === 'phone' && value !== '' && !/^1[3456789]\d{9}$/.test(value)) {
isValid = false
msg = rule.message
break
}
}
return {
isValid,
msg
}
}
Loading…
Cancel
Save