Browse Source

执法记录

master
parent
commit
3b571e6482
  1. 75
      App.vue
  2. 28
      api/inspections/index.js
  3. 23
      api/login.js
  4. 11
      api/system/user.js
  5. 10
      api/task/index.js
  6. 33
      components/cs-bottom-wrapper/index.vue
  7. 8
      components/cs-dict-tag/index.vue
  8. 4
      config.js
  9. 2
      main.js
  10. 3
      manifest.json
  11. 15
      pages.json
  12. 46
      pages/enterprise.vue
  13. BIN
      static/images/emty.png
  14. BIN
      static/images/icon/refresh.png
  15. BIN
      static/images/locateImage.png
  16. BIN
      static/images/task/position.png
  17. 45
      static/js/echarts.min.js
  18. 1
      static/js/qqmap-wx-jssdk.min.js
  19. 12
      static/scss/global.scss
  20. 3
      store/getters.js
  21. 10
      store/modules/user.js
  22. 135
      sub/common/waiting.vue
  23. 66
      sub/enterprise/detail.vue
  24. 21
      sub/task/detail.vue
  25. 464
      sub/task/locate.vue
  26. 120
      sub/task/record.vue
  27. 21
      uni_modules/s-components/s-header/index.vue
  28. 3
      utils/constant.js
  29. 44
      utils/getCode.js
  30. 20
      utils/ruoyi.js
  31. 2
      utils/storage.js

75
App.vue

@ -1,7 +1,7 @@
<script>
import config from './config'
import store from '@/store'
import { getAccessToken,setOpenId,getOpenId } from '@/utils/auth'
import { getAccessToken, setOpenId, getOpenId } from '@/utils/auth'
export default {
data() {
@ -55,37 +55,35 @@ export default {
}
},
login() {
console.log('-------'+getOpenId())
if(getOpenId()){
const data = {
type: 34,
code: getOpenId(),
state: 'default',
userType: this.getUserType()
}
//
this.$store.dispatch('Login', data).then(() => {
this.loginSuccess()
})
}
else{
uni.login({
success: res => {
const data = {
type: 34,
code: res.code,
state: 'default',
userType: this.getUserType()
}
setOpenId(res.code);
//
this.$store.dispatch('Login', data).then(() => {
this.loginSuccess()
})
}
})
}
console.log('-------' + getOpenId())
if (getOpenId()) {
const data = {
type: 34,
code: getOpenId(),
state: 'default',
userType: this.getUserType()
}
//
this.$store.dispatch('Login', data).then(() => {
this.loginSuccess()
})
} else {
uni.login({
success: res => {
const data = {
type: 34,
code: res.code,
state: 'default',
userType: this.getUserType()
}
setOpenId(res.code)
//
this.$store.dispatch('Login', data).then(() => {
this.loginSuccess()
})
}
})
}
},
getUserType() {
//
@ -116,15 +114,14 @@ export default {
return
}
//
if (user.audit == 2) {
//
if (user.audit == null) {
//
uni.navigateTo({
url: '/sub/owner/edit'
})
return
}
//
uni.navigateTo({
url: '/sub/owner/edit'
})
}
}
}

28
api/inspections/index.js

@ -20,5 +20,33 @@ export const InspectionsApi = {
url: `/system/enterprise-inspections/appGet?id=${id}`,
method: 'GET',
})
},
/**
* 获取反馈结果
*/
getFeedBack: (id) => {
return request({
url: `/system/inspections-log/appList?inspectionsId=${id}`,
method: 'GET',
})
},
/**
* 签到列表
*/
getLocate: (id) => {
return request({
url: `/system/inspections-log/signInList?inspectionsId=${id}`,
method: 'GET',
})
},
/**
* 签到
*/
locate: (data) => {
return request({
url: `/system/inspections-log/signIn`,
method: "POST",
data
})
}
}

23
api/login.js

@ -7,8 +7,8 @@ export function login(data) {
headers: {
isToken: false
},
'method': 'POST',
'data': data
method: 'POST',
data
})
}
@ -16,7 +16,7 @@ export function login(data) {
export function getInfo() {
return request({
url: '/system/auth/get-permission-info',
'method': 'GET'
method: 'GET'
})
}
@ -24,7 +24,7 @@ export function getInfo() {
export function logout() {
return request({
url: '/system/auth/logout',
'method': 'POST'
method: 'POST'
})
}
@ -32,7 +32,18 @@ export function logout() {
export function qrLogin(data) {
return request({
url: '/system/auth/social-login-openid',
'method': 'POST',
'data': data
method: 'POST',
data
})
}
/**
* 获取小程序码
*/
export const getMiniCode = (data) => {
return request({
url: '/system/auth/web_code_login',
method: "POST",
data
})
}

11
api/system/user.js

@ -39,4 +39,15 @@ export function uploadAvatar(data) {
name: data.name,
filePath: data.filePath
})
}
/**
* 获取人员列表
* @param {Object} id
*/
export function getUserList(id) {
return request({
url: `/system/enterprise-inspections/changeSelectUser?deptId=${id}`,
method: 'GET'
})
}

10
api/task/index.js

@ -21,5 +21,15 @@ export const TaskApi = {
url: `/system/task-info/appGet?id=${id}`,
method: 'GET',
})
},
/**
* 转发
*/
replay: (data) => {
return request({
url: `/system/enterprise-inspections/passOn`,
method: 'POST',
data
})
}
}

33
components/cs-bottom-wrapper/index.vue

@ -0,0 +1,33 @@
<template>
<view class="view">
<slot></slot>
<view class="safe" v-if="isFit"></view>
</view>
</template>
<script>
export default {
name: 'cs-bottom-wrapper',
data() {
return {}
},
computed: {
isFit() {
return uni.getStorageSync('SYSTEM').includes('iOS')
}
}
}
</script>
<style lang="scss" scoped>
.view {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
background-color: #fff;
.safe {
height: 25px;
}
}
</style>

8
components/cs-dict-tag/index.vue

@ -1,5 +1,7 @@
<template>
<view :class="[getClass, 'dict-tag']">{{ current.label }}</view>
<view :class="[getClass, 'dict-tag']" v-if="current.label">
{{ current.label }}
</view>
</template>
<script>
@ -51,7 +53,9 @@ export default {
mounted() {},
methods: {
getDickObj() {
this.current = this.$props.dict.find(i => i.value == this.$props.value)
this.current = this.$props.dict.find(
i => i.value == this.$props.value
)
}
}
}

4
config.js

@ -1,7 +1,7 @@
// 应用全局配置
module.exports = {
// baseUrl: 'http://api-dashboard.yudao.iocoder.cn',
baseUrl: 'http://localhost:48080',
// baseUrl: 'https://hb.jzce.com',
baseUrl: 'http://188.188.3.232:48080',
baseApi: '/admin-api',
// 应用信息
appInfo: {

2
main.js

@ -5,7 +5,6 @@ import plugins from './plugins' // plugins
import './permission' // permission
import * as dict from '@/utils/dict.js'
import * as util from '@/utils/ruoyi.js'
// 引入uView
import uView from '@/uni_modules/uview-ui'
// import mpShare from '@/uni_modules/uview-ui/libs/mixin/mpShare.js'
@ -15,6 +14,7 @@ Vue.use(plugins).use(uView)
let mpShare = require('@/uni_modules/uview-ui/libs/mixin/mpShare.js');
Vue.mixin(mpShare)
Vue.config.productionTip = false
// 挂载vuex

3
manifest.json

@ -60,7 +60,8 @@
"scope.userLocation": {
"desc": "获取企业位置"
}
}
},
"requiredPrivateInfos": ["getLocation", "chooseLocation"]
},
"vueVersion": "2",
"h5": {

15
pages.json

@ -110,15 +110,18 @@
"path": "task/record",
"style": {
"navigationBarTitleText": "记录详情",
"onReachBottonDistance": 50,
"enablePullDownRefresh": true,
"usingComponents": {},
"componentPlaceholder": {}
}
},
{
"path": "task/locate",
"style": {
"usingComponents": {
"van-dropdown-menu": "/wxcomponents/vant/dropdown-menu/index",
"van-dropdown-item": "/wxcomponents/vant/dropdown-item/index"
"van-action-sheet": "/wxcomponents/vant/action-sheet/index"
},
"componentPlaceholder": {
"u-modal": "view",
"u-sticky": "view"
"u-modal": "view"
}
}
}

46
pages/enterprise.vue

@ -62,15 +62,27 @@
class="wd-flex wd-items-center enterprise"
@click="goDetail(enterprise.id)"
>
<u-avatar :src="enterprise.files[0].url" shape="square" size="64"></u-avatar>
<u-avatar
:src="enterprise.files[0].url"
shape="square"
size="64"
></u-avatar>
<view class="wd-flex wd-flex-col" style="gap: 4px">
<text class="wd-font-800 wd-text-15">{{ enterprise.enterprisesName }}</text>
<text class="wd-font-800 wd-text-15">
{{ enterprise.enterprisesName }}
</text>
<view class="wd-flex wd-pb-8px">
<u-icon name="map" size="14" color="#17C653"></u-icon>
<text class="address wd-text-12" style="margin-left: 4px">{{ enterprise.address }}</text>
<text class="address wd-text-12" style="margin-left: 4px">
{{ enterprise.address }}
</text>
</view>
<view class="tagList">
<view class="tag" v-for="(tag, index) in enterprise.tagList" :key="index">
<view
class="tag"
v-for="(tag, index) in enterprise.tagList"
:key="index"
>
{{ tag }}
</view>
</view>
@ -78,9 +90,14 @@
<view
class="audit"
v-if="enterprise.audit != 2"
:style="{ color: enterprise.audit == 1 ? '#F6B100' : '#ea000c', backgroundColor: '#FFF8DD' }"
:style="{
color: enterprise.audit == 1 ? '#F6B100' : '#ea000c',
backgroundColor: '#FFF8DD'
}"
>
{{ $dict.echoDicValue(dictMap.user_audit_type, enterprise.audit) }}
{{
$dict.echoDicValue(dictMap.user_audit_type, enterprise.audit)
}}
</view>
</view>
<u-loadmore :status="load" marginTop="12" marginBottom="12" />
@ -91,7 +108,11 @@
<script>
import { getEnterPriseList } from '@/api/enterprise/index.js'
import { getDictBatchByType, getDeptTree, getTagData } from '@/api/system/dict.js'
import {
getDictBatchByType,
getDeptTree,
getTagData
} from '@/api/system/dict.js'
export default {
data() {
return {
@ -155,7 +176,9 @@ export default {
},
async getDict() {
const tags = await getTagData(['qy', ' hy', 'st', 'wr'].join(','))
const dict = await getDictBatchByType({ type: ['user_audit_type'].join(',') })
const dict = await getDictBatchByType({
type: ['user_audit_type'].join(',')
})
let tagMap = {}
tags.data.forEach(t => {
tagMap[t.tagCode] = t.children
@ -193,7 +216,12 @@ export default {
this.queryParams.pageNo = 1
this.load = 'loadmore'
this.list = []
this.queryParams.tagList = [this.queryParams.qy, this.queryParams.hy, this.queryParams.st, this.queryParams.wr]
this.queryParams.tagList = [
this.queryParams.qy,
this.queryParams.hy,
this.queryParams.st,
this.queryParams.wr
]
.filter(i => i != '')
.join()
this.getList()

BIN
static/images/emty.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

BIN
static/images/icon/refresh.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 955 B

BIN
static/images/locateImage.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

BIN
static/images/task/position.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

45
static/js/echarts.min.js vendored

File diff suppressed because one or more lines are too long

1
static/js/qqmap-wx-jssdk.min.js vendored

File diff suppressed because one or more lines are too long

12
static/scss/global.scss

@ -1,3 +1,15 @@
page {
background-color: #f9f9f9;
position: relative;
}
button {
padding-left: 0;
padding-right: 0;
font-size: 16px;
line-height: inherit;
&::after {
content: '';
display: none;
}
}

3
store/getters.js

@ -5,6 +5,7 @@ const getters = {
roles: state => state.user.roles,
permissions: state => state.user.permissions,
userId: state => state.user.id,
phone: state => state.user.phone
phone: state => state.user.phone,
deptId: state => state.user.deptId
}
export default getters

10
store/modules/user.js

@ -20,6 +20,7 @@ const user = {
avatar: storage.get(constant.avatar),
phone: storage.get(constant.phone),
roles: storage.get(constant.roles),
deptId: storage.get(constant.deptId),
permissions: storage.get(constant.permissions)
},
mutations: {
@ -43,6 +44,10 @@ const user = {
state.roles = roles
storage.set(constant.roles, roles)
},
SET_DEPTID: (state, deptId) => {
state.deptId = deptId
storage.set(constant.deptId, deptId)
},
SET_PERMISSIONS: (state, permissions) => {
state.permissions = permissions
storage.set(constant.permissions, permissions)
@ -76,8 +81,8 @@ const user = {
getInfo().then(res => {
const user = res.data.user
if (res.data.roles && res.data.roles.length > 0) {
commit('SET_ROLES', res.roles)
commit('SET_PERMISSIONS', res.permissions)
commit('SET_ROLES', res.data.roles)
commit('SET_PERMISSIONS', res.data.permissions)
} else {
commit('SET_ROLES', ['ROLE_DEFAULT'])
}
@ -85,6 +90,7 @@ const user = {
commit('SET_AVATAR', user.avatar)
commit('SET_NAME', user.name)
commit('SET_PHONE', user.mobile)
commit('SET_DEPTID', user.deptId)
resolve(res)
}).catch(error => {
reject(error)

135
sub/common/waiting.vue

@ -1,46 +1,103 @@
<template>
<view class="wd-flex wd-flex-col wd-flex-center" style="height: 100%; gap: 10px">
<icon type="waiting" size="40" />
<button @tap="btnLogin">允许登陆</button>
</view>
<view class="waiting">
<u--image
src="/static/favicon.png"
width="144px"
height="144px"
mode="aspectFit"
:fade="true"
duration="200"
></u--image>
<button
class="login"
@click="login"
:loading="loading"
loadingText="授权中..."
v-if="!isLogin"
>
授权登录
</button>
<text v-else class="title">登录成功</text>
</view>
</template>
<script>
import {
getAccessToken,getOpenId
} from '@/utils/auth'
import {qrLogin}from '@/api/login'
import { getAccessToken, getOpenId } from '@/utils/auth'
import { qrLogin } from '@/api/login'
export default {
data() {
return {
scene:""
}
},
onShow(res) {
console.log(res)
},
methods: {
btnLogin() {
const openid = getOpenId()
console.log('登陆信息发送', this.scene)
console.log('opeid', openid)
qrLogin({
code:this.scene,
openid:getAccessToken()
})
}
},
onLoad(query) {
// scene 使 decodeURIComponent scene
this.scene = decodeURIComponent(query.scene)
}
}
export default {
data() {
return {
scene: '',
loading: false,
isLogin: false
}
},
methods: {
login() {
if (!this.scene) {
uni
.showModal({
content: '链接失效,请重新扫码',
showCancel: false
})
.then(() => {
uni.exitMiniProgram({
success: res => {
console.log(res)
}
})
})
} else {
this.loading = true
qrLogin({
code: this.scene,
openid: getAccessToken()
}).then(res => {
this.loading = false
this.isLogin = true
uni.exitMiniProgram()
})
}
}
},
onLoad(query) {
// scene 使 decodeURIComponent scene
this.scene = decodeURIComponent(query.scene)
}
}
</script>
<style lang="scss"></style>
<style lang="scss" scoped>
.waiting {
height: 100vh;
display: flex;
flex-flow: column nowrap;
justify-content: center;
align-items: center;
background: #17c653;
gap: 40px;
.login {
display: flex;
padding: var(--Number-12px, 12px) var(--Number-40px, 40px);
justify-content: center;
align-items: center;
border-radius: var(--Number-120px, 120px);
background: var(--LightMode-Light-Light, #fff);
box-shadow: 0px 3px 4px 0px rgba(0, 0, 0, 0.03);
color: var(--LightMode-Success-Success, #17c653);
font-family: 'PingFang SC';
font-size: 16px;
font-style: normal;
font-weight: 500;
line-height: normal;
}
.title {
font-family: 'PingFang SC';
font-size: 16px;
font-style: normal;
font-weight: 500;
line-height: normal;
}
}
</style>

66
sub/enterprise/detail.vue

@ -1,7 +1,11 @@
<template>
<cs-page isCustom>
<template #header>
<view class="wd-flex wd-flex-row wd-flex-center" style="position: relative" @click="goBack">
<view
class="wd-flex wd-flex-row wd-flex-center"
style="position: relative"
@click="goBack"
>
<view class="icon-box">
<u-icon name="arrow-left" size="12"></u-icon>
</view>
@ -11,32 +15,62 @@
<view class="detail-container">
<view class="box detail">
<view>
<text class="wd-font-800 wd-text-16" style="margin-bottom: 4px">{{ detail.enterprisesName }}</text>
<view class="address">
<u-icon name="map" size="14" color="#17C653"></u-icon>
<text class="wd-font-800 wd-text-16" style="margin-bottom: 4px">
{{ detail.enterprisesName }}
</text>
</view>
<view class="address">
<u-icon name="map" size="14" color="#17C653"></u-icon>
<text style="text-decoration: underline">
{{ detail.address }}
</view>
</text>
</view>
<view class="wd-flex" style="align-items: center">
<text class="address" style="margin-right: 8px">环保负责人</text>
<text style="margin-right: 16px">{{ detail.enterprisesName }}</text>
<text style="margin-right: 16px">
{{ detail.enterprisesName }}
</text>
<text class="address" style="margin-right: 8px">联系方式</text>
<text style="text-decoration: underline">{{ detail.environmentalContactPhone }}</text>
<text style="text-decoration: underline">
{{ detail.environmentalContactPhone }}
</text>
</view>
<view class="images-box">
<image v-for="(src, index) in detail.files" :key="index" :src="src.url" mode="widthFix" class="image"></image>
<image
v-for="(src, index) in detail.files"
:key="index"
:src="src.url"
mode="widthFix"
class="image"
></image>
</view>
<text class="address">{{ detail.introduction }}</text>
</view>
<view class="box wd-text-12" v-for="prove in detail.qualificationList" :key="prove.id">
<view
class="box wd-text-12"
v-for="prove in detail.qualificationList"
:key="prove.id"
>
<view class="wd-flex" style="gap: 8px">
<image src="@/static/images/enterprise/zz.png" style="width: 90px; height: 70px" mode="widthFix"></image>
<view style="flex: 1; justify-content: space-between" class="wd-flex wd-flex-col">
<image
src="@/static/images/enterprise/zz.png"
style="width: 90px; height: 70px"
mode="widthFix"
></image>
<view
style="flex: 1; justify-content: space-between"
class="wd-flex wd-flex-col"
>
<view class="wd-flex" style="gap: 8px; align-items: center">
<text class="label">资质名称</text>
<view>
{{ $dict.echoDicValue(dictMap.enterprise_qua, prove.qualificationName.toString()) }}
{{
$dict.echoDicValue(
dictMap.enterprise_qua,
prove.qualificationName.toString()
)
}}
</view>
</view>
<view class="wd-flex" style="gap: 8px; align-items: center">
@ -91,7 +125,9 @@ export default {
* 获取字典
*/
async getDict() {
const dict = await getDictBatchByType({ type: ['enterprises_type', 'enterprise_qua'].join(',') })
const dict = await getDictBatchByType({
type: ['enterprises_type', 'enterprise_qua'].join(',')
})
this.dictMap = {
...dict.data
}
@ -122,7 +158,7 @@ export default {
.detail {
display: flex;
flex-flow: column nowrap;
gap: 16px;
gap: 12px;
.address {
display: flex;
flex-flow: row nowrap;
@ -136,6 +172,8 @@ export default {
flex-flow: row nowrap;
gap: 12px;
.image {
width: 96px;
height: 96px;
border-radius: $cs-border-radius;
}
}

21
sub/task/detail.vue

@ -95,6 +95,16 @@
}
"
/>
<van-dropdown-item
v-if=""
:value="queryParams.dept"
:options="userList"
@change="
v => {
querySelect(v, 'dept')
}
"
/>
<van-dropdown-item
:value="queryParams.Inspections_status"
:options="getDropdownOption('Inspections_status')"
@ -205,6 +215,7 @@
import { getDeptTree, getDictBatchByType } from '@/api/system/dict.js'
import { TaskApi } from '@/api/task/index.js'
import { InspectionsApi } from '@/api/inspections/index.js'
import { getUserList } from '@/api/system/user.js'
export default {
data() {
return {
@ -235,7 +246,8 @@ export default {
load: 'loadmore',
model: {
show: false
}
},
userList: []
}
},
onLoad(res) {
@ -320,7 +332,10 @@ export default {
this.detail = res.data
this.getList()
},
async getUser(deptId) {
const res = await getUserList(deptId)
console.log(res)
},
async getList() {
uni.showToast({
title: '加载中',
@ -599,4 +614,4 @@ export default {
margin: 12px 0;
border-radius: 0px;
}
</style>
</style>

464
sub/task/locate.vue

@ -0,0 +1,464 @@
<template>
<view class="view-container">
<view class="box">
<view class="header">
<view class="wd-font-800">执法签到</view>
<view class="refresh" @tap="refresh">
<image
src="/static/images/icon/refresh.png"
mode="aspectFit"
style="width: 16px; height: 16px"
></image>
刷新
</view>
</view>
<view class="row codeview">
<image :src="miniCode" mode="aspectFill" class="code"></image>
<view class="info">
<view class="">
<view class="wd-font-800">执法协同人员请</view>
<view class="wd-font-800">扫描二维码签到</view>
<view class="wd-font-800 wd-mt-8" style="color: #f8285a">
(要求2人以上)
</view>
</view>
<view
class="wd-font-800"
style="color: #17c653; text-decoration: underline"
@tap="showTip = true"
>
无法正常签到
</view>
</view>
</view>
<view class="row" v-if="list.length == 0">
<view class="emty">
<image
class="image"
src="/static/images/emty.png"
mode="aspectFill"
></image>
<text class="wd-text-14" style="color: #99a1b7">
暂无处理结果
</text>
</view>
</view>
<view class="locate-record row" v-for="item in list" :key="item.id">
<view class="info">
<u-avatar
:src="item.avtar"
size="40px"
shape="circle"
></u-avatar>
<view>
<view style="margin-bottom: 4px">
<text style="font-weight: 800">{{ item.realName }}</text>
<text style="font-size: 13px; color: #4b5675">
{{ item.deptName }}
</text>
</view>
<view style="font-size: 13px; color: #4b5675">
{{ $util.formatDate(item.time, 'YYYY年M月D日 hh:mm') }}
</view>
</view>
</view>
<view class="wd-flex wd-flex-center" style="gap: 4px">
<u-icon
name="checkmark-circle-fill"
size="16"
color="#17C653"
></u-icon>
<text class="wd-text-13">已签到</text>
</view>
</view>
</view>
<cs-bottom-wrapper v-if="showBtn">
<view class="operation">
<button
class="btn green"
v-if="distance < radius"
@tap="locate"
:loading="loading"
>
确认签到
</button>
<view class="btn grey" v-else>不在签到范围</view>
</view>
</cs-bottom-wrapper>
<u-modal
:show="showTip"
width="295px"
closeOnClickOverlay
@close="showTip = false"
>
<view class="tip">
<view class="header">
<view>如无法签到 请确认以下</view>
<view>功能是否正常启用?</view>
</view>
<view class="info">
<view class="msg">
<u-icon name="wifi" color="#17C653" size="20"></u-icon>
开启手机设置GPS定位功能
</view>
<view class="msg">
<u-icon name="wifi" color="#17C653" size="20"></u-icon>
开启手机授权微信定位功能
</view>
<view class="msg">
<u-icon name="wifi" color="#17C653" size="20"></u-icon>
开启右上角小程序定位功能
</view>
</view>
</view>
<template #confirmButton>
<view class="wd-flex wd-flex-center">
<view class="confirm-btn" @tap="showTip = false">确认</view>
</view>
</template>
</u-modal>
<van-action-sheet :show="showModel">
<view class="model-view">
<image
class="image"
src="/static/images/task/position.png"
mode="aspectFill"
></image>
<view class="open-setting" @tap="openSetting()">开启定位</view>
</view>
</van-action-sheet>
</view>
</template>
<script>
import TencentMap from '@/static/js/qqmap-wx-jssdk.min.js'
import { getMiniCode } from '@/utils/getCode.js'
import { InspectionsApi } from '@/api/inspections/index.js'
import { getEnterPrise } from '@/api/enterprise/index.js'
export default {
data() {
return {
showModel: false,
inspectionsId: '',
miniCode: '',
enterpriseGps: '',
location: {},
distance: '',
radius: 1000000, //
showTip: false,
list: [],
loading: false,
share: {
title: '',
path: '',
imageUrl: ''
}
}
},
computed: {
showBtn() {
return (
this.list.findIndex(i => i.userId == this.$store.getters.userId) <
-1
)
}
},
onLoad(res) {
if (res.scene) {
const data = decodeURIComponent(res.scene)
const obj = {}
data.split('&').forEach(i => {
const arr = i.split('=')
obj[arr[0]] = arr[1]
})
this.inspectionsId = obj.inspectionsId
this.enterpriseId = obj.enterpriseId
} else {
this.inspectionsId = res.inspectionsId
this.enterpriseId = res.enterpriseId
}
this.share = {
title: '',
path: `/sub/task/locate?inspectionsId=${this.inspectionsId}&enterpriseId=${this.enterpriseId}`,
imageUrl: require('@/static/images/locateImage.png')
}
this.init()
},
onReady() {
this.useAuth()
},
onShareAppMessage() {
return this.share
},
onShareTimeline() {
return this.share
},
methods: {
async init() {
const miniCode = await getMiniCode({
scene: `inspectionsId=${this.inspectionsId}&enterpriseId=${this.enterpriseId}`,
page: 'sub/task/locate',
check_path: false,
env_version: 'develop',
is_hyaline: true
})
const enterprise = await getEnterPrise(this.enterpriseId)
this.enterprisesName = enterprise.data.enterprisesName
this.enterpriseGps = enterprise.data.gpsLocation
uni.setNavigationBarTitle({
title: this.enterprisesName
})
this.share.title = `执法签到-${this.enterprisesName}`
this.getLocateList()
this.miniCode = miniCode
},
async getLocateList() {
const res = await InspectionsApi.getLocate(this.inspectionsId)
//
const isLead = res.data.findIndex(i => {
i.userId == this.$store.getters.userId && i.isInspect
})
console.log(isLead)
this.list = res.data
},
useAuth() {
const that = this
uni.getSetting({
success: res => {
//
res.authSetting['scope.userLocation']
? _getLocation()
: _getAuth()
}
})
/**
* 打开微信设置
*/
function _getAuth() {
uni.authorize({
scope: 'scope.userLocation',
success: res => {
_getLocation()
},
fail: () => {
that.showModel = true
}
})
}
function _getLocation() {
uni.getLocation({
type: 'gcj02',
success: res => {
that.location = {
latitude: res.latitude,
longitude: res.longitude
}
that.getDistance()
},
fail: err => {
that.showTip = true
uni.showToast({
icon: 'none',
title: '获取定位失败'
})
}
})
}
},
openSetting() {
const that = this
uni.openSetting({
success: res => {
that.showModel = false
that.useAuth()
}
})
},
getDistance() {
const that = this
const map = new TencentMap({
key: 'PQ5BZ-GZ5C7-RTMXB-HSAPB-3TOAV-5CBLZ'
})
map.calculateDistance({
mode: 'straight',
form: this.location,
to: this.enterpriseGps,
success: res => {
that.distance = res.result.elements[0].distance
}
})
},
refresh() {
this.getDistance()
this.getLocateList()
},
async locate() {
this.loading = true
const res = await InspectionsApi.locate({
inspectionsId: this.inspectionsId
})
this.loading = false
uni.showToast({
icon: 'none',
title: res.data
})
this.refresh()
}
}
}
</script>
<style lang="scss" scoped>
.view-container {
height: 100vh;
padding: 12px;
.box {
background-color: #fff;
border-radius: $cs-border-radius;
padding: 16px;
display: flex;
flex-flow: column nowrap;
gap: 12px;
}
.header {
display: flex;
align-items: center;
justify-content: space-between;
.refresh {
display: flex;
align-items: center;
gap: 4px;
color: $cs-color-main;
font-weight: bold;
}
}
.row {
border-radius: var(--Number-8px, 8px);
border: 1px solid var(--LightMode-Grey-Grey-100, #f9f9f9);
background: var(--LightMode-Light-Light, #fff);
padding: 16px;
}
.codeview {
display: flex;
justify-content: space-between;
.code {
width: 320rpx;
height: 320rpx;
}
.info {
display: flex;
flex-direction: column;
justify-content: space-between;
gap: 80rpx;
}
}
}
.locate-record {
display: flex;
justify-content: space-between;
.info {
display: flex;
justify-content: space-between;
align-items: center;
gap: 12px;
}
}
.emty {
display: flex;
flex-direction: column;
align-items: center;
gap: 12px;
padding: 24px 12px;
border-radius: 8px;
.image {
width: 64px;
height: 64px;
}
}
.operation {
padding: 12px;
display: flex;
align-items: center;
justify-content: center;
gap: 12px;
.btn {
flex: 1;
border-radius: 8px;
display: flex;
padding: 12px 0;
align-items: center;
justify-content: center;
}
.green {
background-color: $cs-color-main;
color: #fff;
}
.grey {
background: #f1f1f4;
color: #99a1b7;
}
}
.model-view {
height: 700rpx;
display: flex;
flex-direction: column;
align-items: center;
gap: 24px;
.image {
width: 470rpx;
height: 420rpx;
}
.open-setting {
padding: var(--Number-12px, 12px) var(--Number-48px, 48px);
gap: 10px;
border-radius: var(--Number-120px, 120px);
background: var(--LightMode-Success-Success, #17c653);
color: #fff;
font-size: 16px;
font-weight: 500;
/* Widget Shadow */
box-shadow: 0px 3px 4px 0px rgba(0, 0, 0, 0.03);
}
}
.confirm-btn {
background-color: $cs-color-main;
padding: 12px 40px;
color: #fff;
font-size: 16px;
font-weight: 600;
border-radius: 120px;
}
.tip {
display: flex;
flex-flow: column nowrap;
gap: 24px;
.header {
display: flex;
flex-flow: column nowrap;
justify-content: center;
align-items: center;
color: #17c653;
font-style: italic;
font-weight: bold;
}
.info {
display: flex;
flex-flow: column nowrap;
justify-content: center;
align-items: center;
color: #071437;
gap: 16px;
.msg {
display: flex;
justify-content: center;
align-items: center;
gap: 4px;
}
}
}
</style>

120
sub/task/record.vue

@ -19,12 +19,12 @@
>
<view class="wd-flex" style="align-items: center; gap: 4px">
<u-icon name="calendar" color="#17C653" />
<text class="wd-text-13 wd-ml-4px">
<text class="wd-text-13 wd-ml-4px wd-font-800">
{{
`${$util.formatDate(
detail.startDate,
'YYYY/M/D'
)}~${$util.formatDate(detail.endDate, 'YYYY/M/D')}`
)} ${$util.formatDate(detail.endDate, 'YYYY/M/D')}`
}}
</text>
</view>
@ -73,7 +73,10 @@
<text class="wd-font-800 wd-text-15">
{{ detail.enterprise.enterprisesName }}
</text>
<view class="wd-flex wd-pb-8px">
<view
class="wd-flex wd-pb-8px"
@tap.native.stop="viewPosition(detail.enterprise)"
>
<u-icon name="map" size="14" color="#17C653"></u-icon>
<text class="address wd-text-12" style="margin-left: 4px">
{{ detail.enterprise.address }}
@ -97,6 +100,24 @@
></cs-dict-tag>
</view>
</view>
<view class="box record">
<view class="wd-text-14 wd-font-800 wd-pb-12">结果反馈</view>
<view class="emty">
<image
class="image"
src="/static/images/emty.png"
mode="aspectFill"
></image>
<text class="wd-text-14" style="color: #99a1b7">暂无处理结果</text>
</view>
</view>
<cs-bottom-wrapper>
<view class="operation">
<view class="btn" @tap="locate">执法签到</view>
</view>
</cs-bottom-wrapper>
</view>
</template>
@ -104,6 +125,7 @@
import { getDeptTree, getDictBatchByType } from '@/api/system/dict.js'
import { TaskApi } from '@/api/task/index.js'
import { getEnterPrise } from '@/api/enterprise/index.js'
import { InspectionsApi } from '../../api/inspections'
export default {
data() {
return {
@ -117,15 +139,11 @@ export default {
isShowAllText: false,
//
queryParams: {
dept: '',
Inspections_status: '',
pageSize: 8,
pageNo: 1,
taskId: '',
recordId: ''
recordId: '',
enterpriseId: ''
},
list: [],
load: 'loadmore'
list: []
}
},
onLoad(res) {
@ -141,7 +159,7 @@ export default {
*/
async getDict() {
const dict = await getDictBatchByType({
type: ['task_state', 'Inspections_status'].join(',')
type: ['Inspections_status'].join(',')
})
const dept = await getDeptTree()
this.dictMap = {
@ -156,31 +174,30 @@ export default {
...res.data,
enterprise: enterprise.data
}
uni.getLocation({
success: res => {
console.log(res)
}
const feedBack = await InspectionsApi.getFeedBack(
this.queryParams.recordId
)
this.list = feedBack.data.list
},
goEnterprise(enterprise) {
uni.navigateTo({
url: `/sub/enterprise/detail?id=${enterprise.id}`
})
// this.getList()
},
async getList() {
uni.showToast({
title: '加载中',
mask: true,
icon: 'loading'
viewPosition(enterprise) {
const position = enterprise.gpsLocation
.split(',')
.map(i => Number(i))
this.$util.viewPosition({
lat: position[0],
lng: position[1],
name: enterprise.address
})
this.load = 'loading'
// const { data } = await InspectionsApi.getList(this.queryParams)
this.list.push(...data.list)
this.load = 'loadmore'
if (this.list.length == data.total) {
this.load = 'nomore'
}
uni.hideToast()
},
goEnterprise(enterprise) {
locate() {
uni.navigateTo({
url: `/sub/enterprise/detail?id=${enterprise.id}`
url: `/sub/task/locate?inspectionsId=${this.queryParams.recordId}&enterpriseId=${this.queryParams.enterpriseId}`
})
}
}
@ -189,7 +206,12 @@ export default {
<style lang="scss" scoped>
.view-container {
height: 100vh;
padding: 12px;
display: flex;
flex-flow: column nowrap;
gap: 12px;
position: relative;
.box {
background-color: #fff;
border-radius: $cs-border-radius;
@ -232,6 +254,7 @@ export default {
font-size: 12px;
.address {
color: $uni-text-color-grey;
text-decoration: underline;
}
&:active {
background-color: $cs-color-touch;
@ -271,5 +294,40 @@ export default {
transform-origin: 50% 50%;
}
}
.record {
.emty {
display: flex;
flex-direction: column;
align-items: center;
gap: 12px;
border-radius: var(--Number-8px, 8px);
border: 1px solid var(--LightMode-Grey-Grey-100, #f9f9f9);
padding: 24px 12px;
border-radius: 8px;
.image {
width: 64px;
height: 64px;
}
}
}
.operation {
padding: 12px;
display: flex;
align-items: center;
justify-content: center;
gap: 12px;
.btn {
flex: 1;
border-radius: 8px;
display: flex;
padding: 12px 0;
align-items: center;
justify-content: center;
background-color: $cs-color-main;
color: #fff;
}
}
}
</style>

21
uni_modules/s-components/s-header/index.vue

@ -6,12 +6,25 @@
</view>
<view v-else>
<view class="operation" v-if="isTab">
<view class="wd-flex wd-items-center" style="gap: 10px">
<u--image src="/static/favicon.png" width="24px" height="24px" mode="aspectFit"></u--image>
<view
class="wd-flex wd-items-center"
style="gap: 10px; padding: 4px 12px"
>
<u--image
src="/static/favicon.png"
width="24px"
height="24px"
mode="aspectFit"
></u--image>
<text class="title">{{ title }}</text>
</view>
</view>
<view class="operation wd-flex wd-flex-row wd-items-center" style="gap: 10px" v-else @tap="goback">
<view
class="operation wd-flex wd-flex-row wd-items-center"
style="gap: 10px; padding: 4px 12px"
v-else
@tap="goback"
>
<view class="icon-box">
<u-icon name="arrow-left" size="12"></u-icon>
</view>
@ -54,7 +67,7 @@ export default {
height: 6vh;
}
.operation {
padding: 10px;
padding: 12px 4px;
.title {
color: #000;
font-size: 16px;

3
utils/constant.js

@ -4,7 +4,8 @@ const constant = {
roles: 'vuex_roles',
permissions: 'vuex_permissions',
userId: 'vuex_userId',
phone: 'vuex_phone'
phone: 'vuex_phone',
deptId: 'vuex_deptId'
}
export default constant

44
utils/getCode.js

@ -0,0 +1,44 @@
let AccessToken
function getAccessToken() {
return new Promise((resolve, reject) => {
uni.request({
url: 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wx6d80755768234f3b&secret=c8180f2ab1b8454d403c7aa336782e21',
method: "GET",
success(res) {
resolve(res.data.access_token)
},
fail(err) {
console.error(err)
resolve(false)
}
})
})
}
function getCode(data, token) {
return new Promise((resolve) => {
uni.request({
url: `https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=${token}`,
method: "POST",
responseType: "arraybuffer",
data: JSON.stringify(data),
success(res) {
resolve(res)
},
fail(err) {
console.error(err)
resolve(false)
}
})
})
}
export async function getMiniCode(data) {
const token = await getAccessToken()
const code = await getCode(data, token)
const arrayBuffer = new Uint8Array(code.data)
const base64 = wx.arrayBufferToBase64(arrayBuffer)
return `data:image/jpeg;base64,${base64}`
}

20
utils/ruoyi.js

@ -70,4 +70,24 @@ export function formatDate(date, format = 'YYYY-MM-DD HH:mm:ss') {
format = 'YYYY-MM-DD HH:mm:ss';
}
return dayjs(date).format(format);
}
/**
* 查看位置
* @param {number} lat 经度
* @param {number} lng 纬度
* @param {string} name 地址名称
*/
export function viewPosition({
lat,
lng,
name = ''
}) {
uni.openLocation({
latitude: lat,
longitude: lng,
address: lat,
lng,
name
})
}

2
utils/storage.js

@ -5,7 +5,7 @@ let storageKey = 'storage_data'
// 存储节点变量名
let storageNodeKeys = [constant.avatar, constant.roles, constant.permissions, constant.userId, constant
.name, constant.phone
.name, constant.phone, constant.deptId
]
// 存储的数据

Loading…
Cancel
Save