Browse Source

优化页面结构和样式,调整各个组件的布局和样式,提升用户体验

master
parent
commit
31f74b1c06
  1. 394
      pages.json
  2. 68
      static/scss/global.scss
  3. 819
      sub/enterprise/detail.vue
  4. 299
      sub/inspection/record.vue
  5. 1501
      sub/invite/addEnterprise.vue
  6. 840
      sub/invite/prove.vue
  7. 1723
      sub/task/detail.vue
  8. 249
      sub/task/log.vue
  9. 865
      sub/task/record.vue

394
pages.json

@ -1,12 +1,14 @@
{
"pages": [{
"pages": [
{
"path": "pages/login",
"style": {
"navigationBarTitleText": "登录",
"navigationStyle": "custom",
"disableScroll": true
}
}, {
},
{
"path": "pages/index",
"style": {
"navigationBarTitleText": "首页",
@ -68,204 +70,215 @@
"^u-(.*)": "@/uni_modules/uview-ui/components/u-$1/u-$1.vue"
}
},
"subPackages": [{
"root": "sub",
"pages": [{
"path": "owner/edit",
"style": {
"navigationBarTitleText": "个人信息"
}
}, {
"path": "owner/invite",
"style": {
"navigationBarTitleText": "邀请企业"
}
},
{
"path": "owner/policy",
"style": {
"navigationBarTitleText": "政策法规",
"usingComponents": {
"van-search": "/wxcomponents/vant/search/index"
},
"componentPlaceholder": {
"u-modal": "view"
"subPackages": [
{
"root": "sub",
"pages": [
{
"path": "owner/edit",
"style": {
"navigationBarTitleText": "个人信息"
}
}
},
{
"path": "owner/policy-detail",
"style": {
"navigationBarTitleText": "政策法规",
"usingComponents": {},
"componentPlaceholder": {}
}
},
{
"path": "owner/jobInfo",
"style": {
"navigationBarTitleText": "工作汇报",
"usingComponents": {
"van-search": "/wxcomponents/vant/search/index"
},
"componentPlaceholder": {
"u-modal": "view"
},
{
"path": "owner/invite",
"style": {
"navigationBarTitleText": "邀请企业"
}
}
},
{
"path": "owner/job-detail",
"style": {
"navigationBarTitleText": "工作汇报",
"usingComponents": {},
"componentPlaceholder": {}
}
},
{
"path": "enterprise/edit",
"style": {
"navigationBarTitleText": "企业填报"
}
}, {
"path": "common/waiting",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
}, {
"path": "enterprise/detail",
"style": {
"navigationBarTitleText": "档案详情",
"componentPlaceholder": {
"u-modal": "view"
},
{
"path": "owner/policy",
"style": {
"navigationBarTitleText": "政策法规",
"usingComponents": {
"van-search": "/wxcomponents/vant/search/index"
},
"componentPlaceholder": {
"u-modal": "view"
}
}
}
}, {
"path": "chat/index",
"style": {
"navigationBarTitleText": "智慧生态"
}
}, {
"path": "task/detail",
"style": {
"navigationBarTitleText": "执法记录",
"onReachBottonDistance": 50,
"enablePullDownRefresh": true,
"usingComponents": {
"van-dropdown-menu": "/wxcomponents/vant/dropdown-menu/index",
"van-dropdown-item": "/wxcomponents/vant/dropdown-item/index"
},
"componentPlaceholder": {
"u-modal": "view",
"u-sticky": "view"
},
{
"path": "owner/policy-detail",
"style": {
"navigationBarTitleText": "政策法规",
"usingComponents": {},
"componentPlaceholder": {}
}
}
},
{
"path": "task/record",
"style": {
"navigationBarTitleText": "记录详情 ",
"usingComponents": {},
"componentPlaceholder": {}
}
},
{
"path": "task/locate",
"style": {
"usingComponents": {
"van-action-sheet": "/wxcomponents/vant/action-sheet/index"
},
"componentPlaceholder": {
"u-modal": "view"
},
{
"path": "owner/jobInfo",
"style": {
"navigationBarTitleText": "工作汇报",
"usingComponents": {
"van-search": "/wxcomponents/vant/search/index"
},
"componentPlaceholder": {
"u-modal": "view"
}
}
}
},
{
"path": "task/enforce",
"style": {
"navigationBarTitleText": "结果反馈",
"usingComponents": {
"van-action-sheet": "/wxcomponents/vant/action-sheet/index"
},
"componentPlaceholder": {
"u-modal": "view",
"uni-easyinput": "view"
},
{
"path": "owner/job-detail",
"style": {
"navigationBarTitleText": "工作汇报",
"usingComponents": {},
"componentPlaceholder": {}
}
}
},
{
"path": "task/log",
"style": {
"navigationBarTitleText": "结果反馈"
}
},
{
"path": "inspection/detail",
"style": {
"navigationBarTitleText": "",
"onReachBottonDistance": 50,
"enablePullDownRefresh": true
}
},
{
"path": "inspection/record",
"style": {
"navigationBarTitleText": "",
"onReachBottonDistance": 50,
"enablePullDownRefresh": true
}
},
{
"path": "invite/index",
"style": {
"navigationBarTitleText": "我的企业",
"enablePullDownRefresh": true,
"componentPlaceholder": {
"u-modal": "view",
"uni-easyinput": "view"
},
{
"path": "enterprise/edit",
"style": {
"navigationBarTitleText": "企业填报"
}
}
},
{
"path": "invite/addEnterprise",
"style": {
"navigationBarTitleText": "新增企业",
"componentPlaceholder": {}
}
},
{
"path": "invite/enterpriseIntroduce",
"style": {
"navigationBarTitleText": "企业简介",
"componentPlaceholder": {
"uni-easyinput": "view"
},
{
"path": "common/waiting",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
},
{
"path": "enterprise/detail",
"style": {
"navigationBarTitleText": "档案详情",
"componentPlaceholder": {
"u-modal": "view"
}
}
},
{
"path": "chat/index",
"style": {
"navigationBarTitleText": "智慧生态"
}
},
{
"path": "task/detail",
"style": {
"navigationBarTitleText": "执法记录",
"onReachBottonDistance": 50,
"enablePullDownRefresh": true,
"usingComponents": {
"van-dropdown-menu": "/wxcomponents/vant/dropdown-menu/index",
"van-dropdown-item": "/wxcomponents/vant/dropdown-item/index"
},
"componentPlaceholder": {
"u-modal": "view",
"u-sticky": "view"
}
}
},
{
"path": "task/record",
"style": {
"navigationBarTitleText": "记录详情 ",
"usingComponents": {},
"componentPlaceholder": {}
}
},
{
"path": "task/locate",
"style": {
"usingComponents": {
"van-action-sheet": "/wxcomponents/vant/action-sheet/index"
},
"componentPlaceholder": {
"u-modal": "view"
}
}
},
{
"path": "task/enforce",
"style": {
"navigationBarTitleText": "结果反馈",
"usingComponents": {
"van-action-sheet": "/wxcomponents/vant/action-sheet/index"
},
"componentPlaceholder": {
"u-modal": "view",
"uni-easyinput": "view"
}
}
},
{
"path": "task/log",
"style": {
"navigationBarTitleText": "结果反馈"
}
},
{
"path": "inspection/detail",
"style": {
"navigationBarTitleText": "",
"onReachBottonDistance": 50,
"enablePullDownRefresh": true
}
},
{
"path": "inspection/record",
"style": {
"navigationBarTitleText": "",
"onReachBottonDistance": 50,
"enablePullDownRefresh": true
}
},
{
"path": "invite/index",
"style": {
"navigationBarTitleText": "我的企业",
"enablePullDownRefresh": true,
"componentPlaceholder": {
"u-modal": "view",
"uni-easyinput": "view"
}
}
},
{
"path": "invite/addEnterprise",
"style": {
"navigationBarTitleText": "新增企业",
"componentPlaceholder": {}
}
},
{
"path": "invite/enterpriseIntroduce",
"style": {
"navigationBarTitleText": "企业简介",
"componentPlaceholder": {
"uni-easyinput": "view"
}
}
},
{
"path": "invite/enterpriseTags",
"style": {
"navigationBarTitleText": "行业类别(可多选)"
}
},
{
"path": "invite/prove",
"style": {
"navigationBarTitleText": "",
"componentPlaceholder": {
"u-switch": "view"
}
}
},
{
"path": "owner/notic",
"style": {
"navigationBarTitleText": "消息通知",
"disableScroll": true
}
}
},
{
"path": "invite/enterpriseTags",
"style": {
"navigationBarTitleText": "行业类别(可多选)"
}
},
{
"path": "invite/prove",
"style": {
"navigationBarTitleText": ""
}
},
{
"path": "owner/notic",
"style": {
"navigationBarTitleText": "消息通知",
"disableScroll": true
}
}
]
}],
]
}
],
"tabBar": {
"list": [{
"list": [
{
"pagePath": "pages/index"
},
{
@ -287,6 +300,5 @@
"navigationBarTitleText": "智慧生态",
"navigationBarBackgroundColor": "#FFF",
"backgroundColor": "#FFF"
}
}

68
static/scss/global.scss

@ -1,50 +1,52 @@
@font-face {
font-family: 'Tahoma';
src: url('https://hb.jzce.com/Tahoma.ttf') format('truetype');
font-family: 'Tahoma';
src: url('https://hb.jzce.com/Tahoma.ttf')
format('truetype');
}
page {
background-color: #f9f9f9;
position: relative;
color: #071437;
background-color: #f9f9f9;
position: relative;
color: #071437;
}
view {
box-sizing: border-box;
box-sizing: border-box;
}
button {
padding-left: 0;
padding-right: 0;
font-size: 16px;
line-height: inherit;
&::after {
content: '';
display: none;
}
padding-left: 0;
padding-right: 0;
font-size: 16px;
line-height: inherit;
&::after {
content: '';
display: none;
}
}
::v-deep .uni-calendar__box {
padding-bottom: 32px;
padding-bottom: 32px;
}
.tagList {
display: flex;
flex-flow: row nowrap;
align-items: center;
gap: 16rpx;
.tag {
display: flex;
padding: 4rpx 12rpx;
justify-content: center;
align-items: center;
border-radius: 4rpx;
background: var(--LightMode-Grey-Grey-100, #f9f9f9);
color: var(--LightMode-Grey-Grey-600, #78829d);
text-align: center;
font-size: 24rpx;
font-style: normal;
font-weight: 400;
line-height: normal;
}
display: flex;
flex-flow: row nowrap;
align-items: center;
gap: 16rpx;
.tag {
display: flex;
padding: 4rpx 12rpx;
justify-content: center;
align-items: center;
border-radius: 4rpx;
background: var(--LightMode-Grey-Grey-100, #f9f9f9);
color: var(--LightMode-Grey-Grey-600, #78829d);
text-align: center;
font-size: 24rpx;
font-style: normal;
font-weight: 400;
line-height: normal;
white-space: nowrap;
}
}

819
sub/enterprise/detail.vue

@ -1,394 +1,461 @@
<template>
<scroll-view class="detail-container" scroll-y>
<view class="box detail">
<view>
<text class="wd-font-800 wd-text-16" style="margin-bottom: 8rpx">
{{ detail.enterprisesName }}
</text>
</view>
<view class="address" @click="goView(detail)">
<u-icon name="map" size="28rpx" color="#17C653"></u-icon>
<text
style="
text-decoration: underline;
color: #071437;
font-size: 26rpx;
padding-right: 3rem;
white-space: nowrap;
text-overflow: ellipsis;
width: 528rpx;
overflow: hidden;
"
>
{{
`${$dict.echoDicValue(
dictMap.enterprises_area,
detail.region
)} | ${detail.address}`
}}
</text>
</view>
<view class="tagList">
<view
class="tag"
v-for="(tag, index) in detail.tagList"
:key="index"
>
{{ tag }}
</view>
</view>
<view class="wd-flex" style="align-items: center">
<text class="address" style="margin-right: 24rpx">环保负责人</text>
<text style="margin-right: 24rpx; color: #071437">
{{ detail.contactName }}
</text>
<text class="address" style="margin-right: 24rpx">联系方式</text>
<text
style="text-decoration: underline; color: #071437"
@click="callPhone(detail.environmentalContactPhone)"
>
{{ detail.environmentalContactPhone }}
</text>
</view>
<view
class="images-box"
@click="$util.perviewImage(detail.files.map(i => i.url))"
>
<image
v-for="(src, index) in detail.files"
:key="index"
:src="src.url"
mode="aspectFill"
class="image"
></image>
</view>
<cs-text-more :value="detail.introduction"></cs-text-more>
<!-- <view class="status">
<scroll-view
class="detail-container"
scroll-y
>
<view class="box detail">
<view>
<text
class="wd-font-800 wd-text-16"
style="margin-bottom: 8rpx"
>
{{ detail.enterprisesName }}
</text>
</view>
<view
class="address"
@click="goView(detail)"
>
<u-icon
name="map"
size="28rpx"
color="#17C653"
></u-icon>
<text
style="
text-decoration: underline;
color: #071437;
font-size: 26rpx;
padding-right: 3rem;
white-space: nowrap;
text-overflow: ellipsis;
width: 528rpx;
overflow: hidden;
"
>
{{
`${$dict.echoDicValue(
dictMap.enterprises_area,
detail.region
)} | ${detail.address}`
}}
</text>
</view>
<view class="tagList">
<view
class="tag"
v-for="(tag, index) in detail.tagList"
:key="index"
>
{{ tag }}
</view>
</view>
<view
class="wd-flex"
style="align-items: center"
>
<text
class="address"
style="margin-right: 24rpx"
>环保负责人</text
>
<text style="margin-right: 24rpx; color: #071437">
{{ detail.contactName }}
</text>
<text
class="address"
style="margin-right: 24rpx"
>联系方式</text
>
<text
style="text-decoration: underline; color: #071437"
@click="
callPhone(detail.environmentalContactPhone)
"
>
{{ detail.environmentalContactPhone }}
</text>
</view>
<view
class="images-box"
@click="
$util.perviewImage(detail.files.map(i => i.url))
"
>
<image
v-for="(src, index) in detail.files"
:key="index"
:src="src.url"
mode="aspectFill"
class="image"
></image>
</view>
<cs-text-more
:value="detail.introduction"
></cs-text-more>
<!-- <view class="status">
<cs-dict-tag
:dict="dictMap.enterprises_status"
:value="detail.enterprisesStatus"
></cs-dict-tag>
</view> -->
</view>
</view>
<view
class="box wd-text-12 prove"
v-for="prove in detail.qualificationList"
:key="prove.id"
>
<view class="wd-flex" style="gap: 18rpx; position: relative">
<image
:src="prove.files[0].url"
style="width: 180rpx; height: 140rpx"
mode="aspectFill"
@click="$util.perviewImage([prove.files[0].url])"
></image>
<view
style="flex: 1; justify-content: space-between"
class="wd-flex wd-flex-col"
>
<view class="wd-flex" style="gap: 18rpx; align-items: center">
<text class="label" style="color: #78829d">资质名称</text>
<view style="color: #071437">
{{
$dict.echoDicValue(
dictMap.enterprise_qua,
prove.qualificationName.toString()
)
}}
</view>
</view>
<view class="wd-flex" style="gap: 18rpx; align-items: center">
<text class="label">资质编号</text>
<view style="color: #071437">
{{ prove.enterpriseAuth }}
</view>
</view>
<view class="wd-flex" style="gap: 18rpx; align-items: center">
<text class="label">资质时限</text>
<view style="color: #071437">
{{
prove.qualificationName == 99
? '永久'
: $util.formatDate(prove.expiryDate, 'YYYY/M/D')
}}
</view>
</view>
</view>
</view>
<view class="status" v-if="prove.status != 1">
<cs-dict-tag
:dict="dictMap.enterprise_qualification_status"
:value="prove.status"
></cs-dict-tag>
</view>
</view>
<view
class="box wd-text-12 prove"
v-for="prove in detail.qualificationList"
:key="prove.id"
>
<view
class="wd-flex"
style="gap: 18rpx; position: relative"
>
<image
:src="prove.files[0].url"
style="width: 180rpx; height: 140rpx"
mode="aspectFill"
@click="$util.perviewImage([prove.files[0].url])"
></image>
<view
style="flex: 1; justify-content: space-between"
class="wd-flex wd-flex-col"
>
<view
class="wd-flex"
style="gap: 18rpx; align-items: center"
>
<text
class="label"
style="color: #78829d"
>资质名称</text
>
<view style="color: #071437">
{{
$dict.echoDicValue(
dictMap.enterprise_qua,
prove.qualificationName.toString()
)
}}
</view>
</view>
<view
class="wd-flex"
style="gap: 18rpx; align-items: center"
>
<text class="label">资质编号</text>
<view style="color: #071437">
{{ prove.enterpriseAuth }}
</view>
</view>
<view
class="wd-flex"
style="gap: 18rpx; align-items: center"
>
<text class="label">资质时限</text>
<view style="color: #071437">
{{
!prove.expiryDate
? '长期有效'
: $util.formatDate(
prove.expiryDate,
'YYYY/M/D'
)
}}
</view>
</view>
</view>
</view>
<view
class="status"
v-if="prove.status != 1"
>
<cs-dict-tag
:dict="dictMap.enterprise_qualification_status"
:value="prove.status"
></cs-dict-tag>
</view>
</view>
<cs-bottom-wrapper v-if="isView">
<view class="operation">
<view
class="btn green"
@tap="showModel = true"
v-if="!detail.isAudit"
>
确认审核
</view>
<view
:class="['btn', total > 0 ? 'green' : 'grey']"
@tap="goInspections"
v-else
>
执法记录
<text v-if="total > 0">({{ total }})</text>
</view>
</view>
</cs-bottom-wrapper>
<cs-bottom-wrapper v-if="isView">
<view class="operation">
<view
class="btn green"
@tap="showModel = true"
v-if="!detail.isAudit"
>
确认审核
</view>
<view
:class="['btn', total > 0 ? 'green' : 'grey']"
@tap="goInspections"
v-else
>
执法记录
<text v-if="total > 0">({{ total }})</text>
</view>
</view>
</cs-bottom-wrapper>
<cs-bottom-wrapper v-if="isChange">
<view class="operation">
<view class="btn green">认领该企业</view>
</view>
</cs-bottom-wrapper>
<cs-bottom-wrapper v-if="isChange">
<view class="operation">
<view class="btn green">认领该企业</view>
</view>
</cs-bottom-wrapper>
<u-modal
:show="showModel"
confirmText="返回"
showCancelButton
cancel-text="确认"
cancel-color="#17C653"
confirm-color="#071437"
@confirm="showModel = false"
@cancel="postApi"
>
<view class="wd-flex wd-flex-col wd-flex-center" style="gap: 10px">
<view style="font-size: 32rpx; color: #071437; font-weight: 800">
是否审核?
</view>
<view class="">请确保企业信息真实性</view>
</view>
</u-modal>
</scroll-view>
<u-modal
:show="showModel"
confirmText="返回"
showCancelButton
cancel-text="确认"
cancel-color="#17C653"
confirm-color="#071437"
@confirm="showModel = false"
@cancel="postApi"
>
<view
class="wd-flex wd-flex-col wd-flex-center"
style="gap: 10px"
>
<view
style="
font-size: 32rpx;
color: #071437;
font-weight: 800;
"
>
是否审核?
</view>
<view class="">请确保企业信息真实性</view>
</view>
</u-modal>
</scroll-view>
</template>
<script>
import {
getEnterPrise,
checkEnterprise,
getTaskList
} from '@/api/enterprise/index.js'
import { getDictBatchByType } from '@/api/system/dict.js'
export default {
data() {
return {
detail: {
id: '',
type: '',
region: ''
},
showModel: false,
dictMap: {},
total: 0,
isView: true,
isChange: false
}
},
onLoad(res) {
if (res.id) {
this.detail.id = res.id
}
if (res.view) {
this.isView = false
}
if (res.change) {
this.isView = false
this.isChange = true
}
this.getDict()
this.init()
},
methods: {
/**
* 获取字典
*/
async getDict() {
const dict = await getDictBatchByType({
type: [
'enterprises_type',
'enterprises_area',
'enterprises_status',
'enterprise_qualification_status',
'enterprise_qua'
].join(',')
})
this.dictMap = {
...dict.data
}
},
callPhone(number) {
uni.makePhoneCall({
phoneNumber: number
})
},
async init() {
const res = await getEnterPrise(this.detail.id)
this.detail = res.data
this.getTaskLength()
},
goBack() {
uni.switchTab({
url: '/pages/enterprise'
})
},
goView(enterprise) {
if (!enterprise.gpsLocation) {
uni.showToast({
icon: 'none',
title: '暂无gps信息'
})
return
}
const position = enterprise.gpsLocation.split(',')
this.$util.viewPosition({
lat: position[0],
lng: position[1],
name: enterprise.enterprisesName,
address: enterprise.address
})
},
postApi() {
checkEnterprise(this.detail.id).then(() => {
uni.showToast({
icon: 'none',
title: '操作成功'
})
this.showModel = false
this.init()
})
},
getTaskLength() {
const data = {
enterpriseId: this.detail.id,
pageNo: 1,
pageSize: 10
}
getTaskList(data).then(res => {
this.total = res.data.total
})
},
goInspections() {
if (this.total > 0) {
uni.navigateTo({
url: `/sub/inspection/detail?enterprisesId=${this.detail.id}&enterprisesName=${this.detail.enterprisesName}`
})
}
}
}
}
import {
getEnterPrise,
checkEnterprise,
getTaskList,
} from '@/api/enterprise/index.js'
import { getDictBatchByType } from '@/api/system/dict.js'
export default {
data() {
return {
detail: {
id: '',
type: '',
region: '',
},
showModel: false,
dictMap: {},
total: 0,
isView: true,
isChange: false,
}
},
onLoad(res) {
if (res.id) {
this.detail.id = res.id
}
if (res.view) {
this.isView = false
}
if (res.change) {
this.isView = false
this.isChange = true
}
this.getDict()
this.init()
},
methods: {
/**
* 获取字典
*/
async getDict() {
const dict = await getDictBatchByType({
type: [
'enterprises_type',
'enterprises_area',
'enterprises_status',
'enterprise_qualification_status',
'enterprise_qua',
].join(','),
})
this.dictMap = {
...dict.data,
}
},
callPhone(number) {
uni.makePhoneCall({
phoneNumber: number,
})
},
async init() {
const res = await getEnterPrise(this.detail.id)
this.detail = res.data
this.getTaskLength()
},
goBack() {
uni.switchTab({
url: '/pages/enterprise',
})
},
goView(enterprise) {
if (!enterprise.gpsLocation) {
uni.showToast({
icon: 'none',
title: '暂无gps信息',
})
return
}
const position = enterprise.gpsLocation.split(',')
this.$util.viewPosition({
lat: position[0],
lng: position[1],
name: enterprise.enterprisesName,
address: enterprise.address,
})
},
postApi() {
checkEnterprise(this.detail.id).then(() => {
uni.showToast({
icon: 'none',
title: '操作成功',
})
this.showModel = false
this.init()
})
},
getTaskLength() {
const data = {
enterpriseId: this.detail.id,
pageNo: 1,
pageSize: 10,
}
getTaskList(data).then(res => {
this.total = res.data.total
})
},
goInspections() {
if (this.total > 0) {
uni.navigateTo({
url: `/sub/inspection/detail?enterprisesId=${this.detail.id}&enterprisesName=${this.detail.enterprisesName}`,
})
}
},
},
}
</script>
<style lang="scss" scoped>
.detail-container {
padding: 24rpx;
position: relative;
.box {
margin-bottom: 24rpx;
background-color: #fff;
border-radius: $cs-border-radius;
padding: 24rpx;
}
.detail {
display: flex;
flex-flow: column nowrap;
gap: 24rpx;
.address {
display: flex;
flex-flow: row nowrap;
gap: 10rpx;
color: $uni-text-color-grey;
}
.tagList {
display: flex;
gap: 8rpx;
flex-flow: row wrap;
color: $uni-text-color-grey;
.tag {
font-size: 24rpx;
display: flex;
padding: 4rpx 12rpx;
justify-content: center;
align-items: center;
border-radius: 4rpx;
background: #f9f9f9;
}
}
.status {
position: absolute;
right: -38rpx;
top: 12rpx;
transform: rotateZ(45deg) translateX(40rpx) translateY(-40rpx);
transform-origin: 50% 50%;
padding: 8rpx 40rpx;
font-size: 24rpx;
text-align: center;
}
}
.prove {
position: relative;
overflow: hidden;
.status {
position: absolute;
right: 0;
top: 0;
transform: rotateZ(45deg) translateX(60rpx) translateY(-41rpx);
transform-origin: 50% 50%;
}
}
.images-box {
display: flex;
flex-flow: row nowrap;
gap: 24rpx;
.image {
width: 196rpx;
height: 196rpx;
border-radius: $cs-border-radius;
flex-shrink: 0;
}
}
}
.detail-container {
padding: 24rpx;
position: relative;
padding-bottom: 200rpx;
.box {
margin-bottom: 24rpx;
background-color: #fff;
border-radius: $cs-border-radius;
padding: 24rpx;
}
.detail {
display: flex;
flex-flow: column nowrap;
gap: 24rpx;
.address {
display: flex;
flex-flow: row nowrap;
gap: 10rpx;
color: $uni-text-color-grey;
}
.tagList {
display: flex;
gap: 8rpx;
flex-flow: row wrap;
color: $uni-text-color-grey;
.tag {
font-size: 24rpx;
display: flex;
padding: 4rpx 12rpx;
justify-content: center;
align-items: center;
border-radius: 4rpx;
background: #f9f9f9;
}
}
.status {
position: absolute;
right: -38rpx;
top: 12rpx;
transform: rotateZ(45deg) translateX(40rpx)
translateY(-40rpx);
transform-origin: 50% 50%;
padding: 8rpx 40rpx;
font-size: 24rpx;
text-align: center;
}
}
.prove {
position: relative;
overflow: hidden;
.status {
position: absolute;
right: 0;
top: 0;
transform: rotateZ(45deg) translateX(60rpx)
translateY(-41rpx);
transform-origin: 50% 50%;
}
}
.images-box {
display: flex;
flex-flow: row nowrap;
gap: 24rpx;
.image {
width: 196rpx;
height: 196rpx;
border-radius: $cs-border-radius;
flex-shrink: 0;
}
}
}
.label {
color: $uni-text-color-grey;
}
.icon-box {
position: absolute;
left: 0;
}
.operation {
padding: 24rpx;
display: flex;
align-items: center;
justify-content: center;
gap: 24rpx;
.red {
background: var(--LightMode-Danger-Danger-Light, #ffeef3);
color: var(--LightMode-Danger-Danger, #f8285a);
}
.btn {
flex: 1;
border-radius: 18rpx;
display: flex;
padding: 24rpx 0;
align-items: center;
font-weight: bold;
justify-content: center;
}
.green {
background-color: $cs-color-main;
color: #fff;
}
.grey {
background: #f1f1f4;
color: #99a1b7;
}
}
.label {
color: $uni-text-color-grey;
}
.icon-box {
position: absolute;
left: 0;
}
.operation {
padding: 24rpx;
display: flex;
align-items: center;
justify-content: center;
gap: 24rpx;
.red {
background: var(
--LightMode-Danger-Danger-Light,
#ffeef3
);
color: var(--LightMode-Danger-Danger, #f8285a);
}
.btn {
flex: 1;
border-radius: 18rpx;
display: flex;
padding: 24rpx 0;
align-items: center;
font-weight: bold;
justify-content: center;
}
.green {
background-color: $cs-color-main;
color: #fff;
}
.grey {
background: #f1f1f4;
color: #99a1b7;
}
}
</style>

299
sub/inspection/record.vue

@ -1,148 +1,167 @@
<template>
<scroll-view scroll-y flex-enable class="view-container">
<view class="box" v-for="log in list" :key="log.id">
<view class="wd-flex" style="gap: 10px; align-items: center">
<view
:style="{
color: $dict.echoDictOption(
dictMap.inspections_mark,
log.status
).remark
}"
>
{{
$dict.echoDictOption(dictMap.inspections_mark, log.status)
.label
}}
</view>
<view class="">
{{ $util.formatDate(log.createTime, 'YYYY/M/D') }}
</view>
</view>
<scroll-view
scroll-x
style="flex-flow: row nowrap; white-space: nowrap"
:enable-flex="true"
>
<view
v-for="people in log.userList"
:key="people.userId"
style="
display: inline-flex;
gap: 24rpx;
border: 1px solid #f9f9f9;
border-radius: 16rpx;
padding: 24rpx;
margin-right: 24rpx;
"
>
<u-avatar
:src="people.avtar"
size="80rpx"
shape="circle"
></u-avatar>
<view class="wd-flex wd-flex-col" style="gap: 2px">
<text>{{ people.realName }}</text>
<text>{{ people.deptName }}</text>
</view>
</view>
</scroll-view>
<cs-text-more :value="log.feedBack"></cs-text-more>
<view class="imageList">
<image
:src="photo.url"
v-for="photo in log.fileList"
:key="photo.id"
mode="aspectFill"
class="image"
@tap="previewImage(log.fileList)"
></image>
</view>
</view>
<cs-emty v-if="list.length == 0"></cs-emty>
</scroll-view>
<scroll-view
scroll-y
flex-enable
class="view-container"
>
<view
class="box"
v-for="log in list"
:key="log.id"
>
<view
class="wd-flex"
style="gap: 10px; align-items: center"
>
<view
:style="{
color: $dict.echoDictOption(
dictMap.inspections_mark,
log.status
).remark,
}"
>
{{
$dict.echoDictOption(
dictMap.inspections_mark,
log.status
).label
}}
</view>
<view class="">
{{ $util.formatDate(log.createTime, 'YYYY/M/D') }}
</view>
</view>
<scroll-view
scroll-x
style="flex-flow: row nowrap; white-space: nowrap"
:enable-flex="true"
>
<view
v-for="people in log.userList"
:key="people.userId"
style="
display: inline-flex;
gap: 24rpx;
border: 1px solid #f9f9f9;
border-radius: 16rpx;
padding: 24rpx;
margin-right: 24rpx;
"
>
<u-avatar
:src="people.avtar"
size="80rpx"
shape="circle"
></u-avatar>
<view
class="wd-flex wd-flex-col"
style="gap: 2px"
>
<text>{{ people.realName }}</text>
<text>{{ people.deptName }}</text>
</view>
</view>
</scroll-view>
<cs-text-more :value="log.feedBack"></cs-text-more>
<view class="imageList">
<image
:src="photo.url"
v-for="photo in log.fileList"
:key="photo.id"
mode="aspectFill"
class="image"
@tap="previewImage(log.fileList)"
></image>
</view>
</view>
<cs-emty v-if="list.length == 0"></cs-emty>
</scroll-view>
</template>
<script>
import { getDictBatchByType } from '@/api/system/dict.js'
import { getTaskLog } from '@/api/enterprise/index.js'
export default {
data() {
return {
queryParams: {
taskId: ''
},
list: [],
dictMap: {}
}
},
onLoad(res) {
uni.setNavigationBarTitle({
title: res.taskName
})
this.queryParams.taskId = res.taskId
this.getDict()
this.getList()
},
onReachBottom() {
this.loadMore()
},
onPullDownRefresh() {
this.reset()
},
methods: {
/**
* 获取字典
*/
async getDict() {
const dict = await getDictBatchByType({
type: ['inspections_mark'].join(',')
})
this.dictMap = {
...dict.data
}
},
async getList() {
uni.showToast({
title: '加载中',
mask: true,
icon: 'loading'
})
const res = await getTaskLog(this.queryParams.taskId)
this.list = res.data
uni.hideToast()
},
previewImage(url) {
this.$util.perviewImage(url.map(i => i.url))
}
}
}
import { getDictBatchByType } from '@/api/system/dict.js'
import { getTaskLog } from '@/api/enterprise/index.js'
export default {
data() {
return {
queryParams: {
taskId: '',
},
list: [],
dictMap: {},
}
},
onLoad(res) {
uni.setNavigationBarTitle({
title: res.taskName,
})
this.queryParams.taskId = res.taskId
this.getDict()
this.getList()
},
onReachBottom() {
this.loadMore()
},
onPullDownRefresh() {
this.reset()
},
methods: {
/**
* 获取字典
*/
async getDict() {
const dict = await getDictBatchByType({
type: ['inspections_mark'].join(','),
})
this.dictMap = {
...dict.data,
}
},
async getList() {
uni.showToast({
title: '加载中',
mask: true,
icon: 'loading',
})
const res = await getTaskLog(
this.queryParams.taskId
)
this.list = res.data
uni.hideToast()
},
previewImage(url) {
this.$util.perviewImage(url.map(i => i.url))
},
},
}
</script>
<style lang="scss" scoped>
.view-container {
padding: 24rpx;
flex-direction: column;
gap: 24rpx;
.box {
border-radius: 24rpx;
padding: 24rpx;
display: flex;
flex-direction: column;
gap: 24rpx;
background-color: #fff;
position: relative;
margin-bottom: 24rpx;
.imageList {
display: flex;
gap: 24rpx;
.image {
width: 192rpx;
height: 192rpx;
border-radius: 16rpx;
flex-shrink: 0;
}
}
}
}
.view-container {
padding: 24rpx;
flex-direction: column;
gap: 24rpx;
.box {
border-radius: 24rpx;
padding: 24rpx;
display: flex;
flex-direction: column;
gap: 24rpx;
background-color: #fff;
position: relative;
margin-bottom: 24rpx;
.imageList {
display: flex;
flex-wrap: wrap;
gap: 24rpx;
.image {
width: 192rpx;
height: 192rpx;
border-radius: 16rpx;
flex-shrink: 0;
}
}
}
}
</style>

1501
sub/invite/addEnterprise.vue

File diff suppressed because it is too large Load Diff

840
sub/invite/prove.vue

@ -1,49 +1,62 @@
<template>
<view class="view">
<view class="block">
<view style="">
<text style="color: #f8285a; margin-right: 4px">*</text>
资质名称
</view>
<view
class="value"
@tap="showPicker('enterprise_qua', 'qualificationName')"
>
<view class="input-textarea" v-if="prove.qualificationName">
{{
$dict.echoDicValue(
dictMap.enterprise_qua,
prove.qualificationName
)
}}
</view>
<view class="input-textarea" style="color: #808080" v-else>
请选择资质名称
</view>
<u-icon name="arrow-right"></u-icon>
</view>
</view>
<view class="view">
<view class="block">
<view style="">
<text style="color: #f8285a; margin-right: 4px"
>*</text
>
资质名称
</view>
<view
class="value"
@tap="
showPicker('enterprise_qua', 'qualificationName')
"
>
<view
class="input-textarea"
v-if="prove.qualificationName"
>
{{
$dict.echoDicValue(
dictMap.enterprise_qua,
prove.qualificationName
)
}}
</view>
<view
class="input-textarea"
style="color: #808080"
v-else
>
请选择资质名称
</view>
<u-icon name="arrow-right"></u-icon>
</view>
</view>
<view class="block">
<view style="">
<text style="color: #f8285a; margin-right: 4px">*</text>
资质编号
</view>
<view class="value">
<input
class="input-value"
type="text"
:adjust-position="true"
cursorSpacing="32"
placeholder-class="txt"
placeholder="请输入资质编号"
v-model="prove.enterpriseAuth"
/>
<u-icon name="arrow-right"></u-icon>
</view>
</view>
<view class="block">
<view style="">
<text style="color: #f8285a; margin-right: 4px"
>*</text
>
资质编号
</view>
<view class="value">
<input
class="input-value"
type="text"
:adjust-position="true"
cursorSpacing="32"
placeholder-class="txt"
placeholder="请输入资质编号"
v-model="prove.enterpriseAuth"
/>
<u-icon name="arrow-right"></u-icon>
</view>
</view>
<!-- <view class="block">
<!-- <view class="block">
<view style="">
<text style="color: #f8285a; margin-right: 4px">*</text>
办理时间
@ -58,359 +71,412 @@
<u-icon name="arrow-right"></u-icon>
</view>
</view> -->
<view class="block">
<view style="">
<text style="color: #f8285a; margin-right: 4px"
>*</text
>
长期有效
</view>
<view
class="value"
style="flex-direction: row-reverse"
>
<u-switch v-model="prove.isLong"></u-switch>
</view>
</view>
<view class="block" v-if="prove.qualificationName != 99">
<view style="">
<text style="color: #f8285a; margin-right: 4px">*</text>
到期时间
</view>
<view class="value" @tap="showCalendar('expiryDate')">
<view class="input-textarea" v-if="prove.expiryDate">
{{ prove.expiryDate }}
</view>
<view class="input-textarea" style="color: #808080" v-else>
请选择到期时间
</view>
<u-icon name="arrow-right"></u-icon>
</view>
</view>
<view
class="block"
v-if="!prove.isLong"
>
<view style="">
<text style="color: #f8285a; margin-right: 4px"
>*</text
>
到期时间
</view>
<view
class="value"
@tap="showCalendar('expiryDate')"
>
<view
class="input-textarea"
v-if="prove.expiryDate"
>
{{ prove.expiryDate }}
</view>
<view
class="input-textarea"
style="color: #808080"
v-else
>
请选择到期时间
</view>
<u-icon name="arrow-right"></u-icon>
</view>
</view>
<view class="upload-wrapper">
<view
class="wd-flex"
style="
justify-content: space-between;
align-items: center;
width: 100%;
"
>
<view style="">
<text style="color: #f8285a; margin-right: 4px">*</text>
资质照片
</view>
<view style="color: #808080">要求清晰有效</view>
</view>
<u-upload
:fileList="prove.photo"
@afterRead="addPhoto"
@delete="delPhoto"
:maxCount="1"
width="101"
height="101"
></u-upload>
</view>
<view class="upload-wrapper">
<view
class="wd-flex"
style="
justify-content: space-between;
align-items: center;
width: 100%;
"
>
<view style="">
<text style="color: #f8285a; margin-right: 4px"
>*</text
>
资质照片
</view>
<view style="color: #808080">要求清晰有效</view>
</view>
<u-upload
:fileList="prove.photo"
@afterRead="addPhoto"
@delete="delPhoto"
:maxCount="1"
width="101"
height="101"
></u-upload>
</view>
<cs-bottom-wrapper>
<view class="operation">
<button class="btn green" @tap="submit">保存</button>
</view>
</cs-bottom-wrapper>
<u-picker
:show="picker.show"
:columns="picker.data"
@cancel="closePicker"
closeOnClickOverlay
keyName="label"
ref="uPicker"
@close="closePicker"
@confirm="confirmPicker"
></u-picker>
<uni-calendar
ref="calendarRef"
:insert="false"
@confirm="confirmCalendar"
/>
</view>
<cs-bottom-wrapper>
<view class="operation">
<button
class="btn green"
@tap="submit"
>
保存
</button>
</view>
</cs-bottom-wrapper>
<u-picker
:show="picker.show"
:columns="picker.data"
@cancel="closePicker"
closeOnClickOverlay
keyName="label"
ref="uPicker"
@close="closePicker"
@confirm="confirmPicker"
></u-picker>
<uni-calendar
ref="calendarRef"
:insert="false"
@confirm="confirmCalendar"
/>
</view>
</template>
<script>
import { uploadFile } from '@/api/system/file.js'
import { getDictBatchByType } from '@/api/system/dict.js'
import { updateProve, createProve } from '@/api/enterprise/prove.js'
export default {
data() {
return {
enterpriseId: '',
prove: {
id: '',
qualificationName: '',
expiryDate: '',
enterpriseAuth: '',
photo: []
},
dictMap: {},
//
picker: {
show: false,
//
key: null,
data: []
},
//
calendar: {
//
key: null
}
}
},
onLoad(res) {
this.getDict()
uni.setNavigationBarTitle({
title: res.prove ? '编辑资质' : '新增资质'
})
if (res.enterpriseId) {
this.enterpriseId = res.enterpriseId
}
if (res.prove) {
this.prove = JSON.parse(res.prove)
}
},
methods: {
/**
* 获取字典
*/
async getDict() {
const dict = await getDictBatchByType({
type: ['enterprise_qua'].join(',')
})
this.dictMap = {
...dict.data
}
},
/**
* 选择图片并上传
* @param {Object} e
*/
async addPhoto(e) {
uni.showLoading({
title: '正在上传...'
})
this.prove.photo.push({
...e.file,
status: 'uploading',
message: '上传中'
})
uploadFile({ name: `file`, filePath: e.file.url }).then(res => {
this.prove.photo = []
this.prove.photo.push({
...res.data,
status: 'success',
message: ''
})
uni.hideLoading()
})
},
/**
* 删除图片
* @param {Object} e
*/
delPhoto(e) {
this.prove.photo = []
},
/**
* 选择器确认回调
* @param {Object} e
*/
confirmPicker(e) {
const { value } = e
this.prove[this.picker.key] = value[0].value
this.closePicker()
},
/**
* 关闭选择器
*/
closePicker() {
this.picker = {
show: false,
key: '',
data: []
}
},
showPicker(dict, key) {
this.picker.data.push(this.dictMap[dict])
this.picker.key = key
this.picker.show = true
},
/**
* 显示日历
* @param {Object} key 表单中需要赋值的键
*/
showCalendar(key) {
this.$refs.calendarRef.open()
this.calendar = {
key
}
},
/**
* 日历选中之后的回调
* @param {Object} e
*/
confirmCalendar(e) {
this.prove[this.calendar.key] = e.fulldate
this.closeCalendar()
},
/**
* 关闭日历
*/
closeCalendar() {
this.calendar = {
key: null
}
},
async submit() {
const valide = await this.verifyForm()
if (!valide) return
if (this.prove.id) {
uni.showLoading({
title: '更新中...'
})
const data = { ...this.prove }
data.files = this.prove.photo.map(p => p.id)
data.expiryDate = new Date(this.prove.expiryDate).getTime()
updateProve(data).then(res => {
uni.hideLoading()
uni.showToast({
icon: 'none',
title: '操作成功'
})
uni.$emit('prove', this.prove)
uni.navigateBack()
})
} else if (this.enterpriseId) {
uni.showLoading({
title: '更新中...'
})
const data = { ...this.prove }
data.files = this.prove.photo.map(p => p.id)
data.expiryDate = new Date(this.prove.expiryDate).getTime()
data.enterpriseId = this.enterpriseId
createProve(data).then(res => {
uni.hideLoading()
uni.showToast({
icon: 'none',
title: '操作成功'
})
uni.$emit('prove', this.prove)
uni.navigateBack()
})
} else {
uni.$emit('prove', this.prove)
uni.navigateBack()
}
},
async hanlderApi() {
if (this.prove.id) {
} else {
}
},
async verifyForm() {
const msgMap = {
qualificationName: '请填写资质名称',
expiryDate: '请选择到期日期',
enterpriseAuth: '请填写资质编号',
photo: '请上传资质照片'
}
const keys = Object.keys(this.prove).filter(i => {
if (!Object.hasOwn(msgMap, i)) {
return false
}
if (i == 'expiryDate' && this.prove.qualificationName == 99)
return false
if (!this.prove[i] && i) return i
if (typeof this.prove[i] == 'object' && this.prove[i].length == 0)
return i
})
if (keys.length > 0) {
const msg = keys
.map(i => {
return msgMap[i]
})
.join('\n')
uni.showToast({
icon: 'none',
title: msg
})
return false
}
return true
}
}
}
import { uploadFile } from '@/api/system/file.js'
import { getDictBatchByType } from '@/api/system/dict.js'
import {
updateProve,
createProve,
} from '@/api/enterprise/prove.js'
export default {
data() {
return {
enterpriseId: '',
prove: {
id: '',
qualificationName: '',
expiryDate: '',
enterpriseAuth: '',
photo: [],
isLong: false,
},
dictMap: {},
//
picker: {
show: false,
//
key: null,
data: [],
},
//
calendar: {
//
key: null,
},
}
},
onLoad(res) {
this.getDict()
uni.setNavigationBarTitle({
title: res.prove ? '编辑资质' : '新增资质',
})
if (res.enterpriseId) {
this.enterpriseId = res.enterpriseId
}
if (res.prove) {
this.prove = JSON.parse(res.prove)
}
},
methods: {
/**
* 获取字典
*/
async getDict() {
const dict = await getDictBatchByType({
type: ['enterprise_qua'].join(','),
})
this.dictMap = {
...dict.data,
}
},
/**
* 选择图片并上传
* @param {Object} e
*/
async addPhoto(e) {
uni.showLoading({
title: '正在上传...',
})
this.prove.photo.push({
...e.file,
status: 'uploading',
message: '上传中',
})
uploadFile({
name: `file`,
filePath: e.file.url,
}).then(res => {
this.prove.photo = []
this.prove.photo.push({
...res.data,
status: 'success',
message: '',
})
uni.hideLoading()
})
},
/**
* 删除图片
* @param {Object} e
*/
delPhoto(e) {
this.prove.photo = []
},
/**
* 选择器确认回调
* @param {Object} e
*/
confirmPicker(e) {
const { value } = e
this.prove[this.picker.key] = value[0].value
this.closePicker()
},
/**
* 关闭选择器
*/
closePicker() {
this.picker = {
show: false,
key: '',
data: [],
}
},
showPicker(dict, key) {
this.picker.data.push(this.dictMap[dict])
this.picker.key = key
this.picker.show = true
},
/**
* 显示日历
* @param {Object} key 表单中需要赋值的键
*/
showCalendar(key) {
this.$refs.calendarRef.open()
this.calendar = {
key,
}
},
/**
* 日历选中之后的回调
* @param {Object} e
*/
confirmCalendar(e) {
this.prove[this.calendar.key] = e.fulldate
this.closeCalendar()
},
/**
* 关闭日历
*/
closeCalendar() {
this.calendar = {
key: null,
}
},
async submit() {
const valide = await this.verifyForm()
if (!valide) return
if (this.prove.id) {
uni.showLoading({
title: '更新中...',
})
const data = { ...this.prove }
data.files = this.prove.photo.map(p => p.id)
data.expiryDate = new Date(
this.prove.expiryDate
).getTime()
updateProve(data).then(res => {
uni.hideLoading()
uni.showToast({
icon: 'none',
title: '操作成功',
})
uni.$emit('prove', this.prove)
uni.navigateBack()
})
} else if (this.enterpriseId) {
uni.showLoading({
title: '更新中...',
})
const data = { ...this.prove }
data.files = this.prove.photo.map(p => p.id)
data.expiryDate = new Date(
this.prove.expiryDate
).getTime()
data.enterpriseId = this.enterpriseId
createProve(data).then(res => {
uni.hideLoading()
uni.showToast({
icon: 'none',
title: '操作成功',
})
uni.$emit('prove', this.prove)
uni.navigateBack()
})
} else {
uni.$emit('prove', this.prove)
uni.navigateBack()
}
},
async hanlderApi() {
if (this.prove.id) {
} else {
}
},
async verifyForm() {
const msgMap = {
qualificationName: '请填写资质名称',
expiryDate: '请选择到期日期',
enterpriseAuth: '请填写资质编号',
photo: '请上传资质照片',
}
const keys = Object.keys(this.prove).filter(i => {
if (!Object.hasOwn(msgMap, i)) {
return false
}
if (i == 'expiryDate' && this.prove.isLong)
return false
if (!this.prove[i] && i) return i
if (
typeof this.prove[i] == 'object' &&
this.prove[i].length == 0
)
return i
})
if (keys.length > 0) {
const msg = keys
.map(i => {
return msgMap[i]
})
.join('\n')
uni.showToast({
icon: 'none',
title: msg,
})
return false
}
return true
},
async changeIsLong(e) {
this.prove.isLong = !this.prove.isLong
},
},
}
</script>
<style lang="scss" scoped>
.view {
padding: 12px;
display: flex;
flex-flow: column nowrap;
gap: 12px;
overflow: hidden;
overflow-y: scroll;
max-height: 100vh;
padding-bottom: 12vh;
}
.block {
display: flex;
flex-flow: row nowrap;
background-color: #fff;
padding: 12px;
border-radius: 8px;
justify-content: space-between;
align-items: center;
gap: 12px;
.value {
flex: 1;
display: flex;
flex-flow: row nowrap;
justify-content: space-between;
gap: 4px;
.input-value {
flex: 1;
text-align: right;
white-space: nowrap;
text-overflow: ellipsis;
}
.input-textarea {
flex: 1;
display: -webkit-box;
overflow: hidden;
text-align: right;
max-height: 3rem;
line-height: 1rem;
text-overflow: ellipsis;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
word-break: break-all;
}
}
}
.view {
padding: 12px;
display: flex;
flex-flow: column nowrap;
gap: 12px;
overflow: hidden;
overflow-y: scroll;
max-height: 100vh;
padding-bottom: 12vh;
}
.block {
display: flex;
flex-flow: row nowrap;
background-color: #fff;
padding: 12px;
border-radius: 8px;
justify-content: space-between;
align-items: center;
gap: 12px;
.value {
flex: 1;
display: flex;
flex-flow: row nowrap;
justify-content: space-between;
gap: 4px;
.input-value {
flex: 1;
text-align: right;
white-space: nowrap;
text-overflow: ellipsis;
}
.input-textarea {
flex: 1;
display: -webkit-box;
overflow: hidden;
text-align: right;
max-height: 3rem;
line-height: 1rem;
text-overflow: ellipsis;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
word-break: break-all;
}
}
}
.upload-wrapper {
display: flex;
flex-flow: column nowrap;
background-color: #fff;
padding: 12px;
border-radius: 8px;
gap: 12px;
}
.upload-wrapper {
display: flex;
flex-flow: column nowrap;
background-color: #fff;
padding: 12px;
border-radius: 8px;
gap: 12px;
}
.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;
}
}
.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;
}
}
</style>

1723
sub/task/detail.vue

File diff suppressed because it is too large Load Diff

249
sub/task/log.vue

@ -1,117 +1,152 @@
<template>
<view class="view-container">
<view class="box">
<view
class="wd-flex"
style="justify-content: space-between; align-items: center"
>
<view style="font-weight: bold">
<text style="color: #f8285a; margin-right: 8rpx">*</text>
处理意见
</view>
</view>
<view style="color: #071437">{{ detail.feedBack }}</view>
<view
class="wd-flex"
style="justify-content: space-between; align-items: center"
>
<view style="font-weight: bold">
<text style="color: #f8285a; margin-right: 8rpx">*</text>
上传证明
</view>
</view>
<view
class="imageList"
@tap="$util.perviewImage(detail.fileList.map(i => i.url))"
>
<image
:src="photo.url"
v-for="photo in detail.fileList"
:key="photo.id"
mode="aspectFill"
class="image"
></image>
</view>
</view>
<view class="view-container">
<view class="box">
<view
class="wd-flex"
style="
justify-content: space-between;
align-items: center;
"
>
<view style="font-weight: bold">
<text style="color: #f8285a; margin-right: 8rpx"
>*</text
>
处理意见
</view>
</view>
<view style="color: #071437">{{
detail.feedBack
}}</view>
<view
class="wd-flex"
style="
justify-content: space-between;
align-items: center;
"
>
<view style="font-weight: bold">
<text style="color: #f8285a; margin-right: 8rpx"
>*</text
>
上传证明
</view>
</view>
<view
class="imageList"
@tap="
$util.perviewImage(
detail.fileList.map(i => i.url)
)
"
>
<image
:src="photo.url"
v-for="photo in detail.fileList"
:key="photo.id"
mode="aspectFill"
class="image"
></image>
</view>
</view>
<view class="box" v-if="detail.status == 3">
<view
class="wd-flex"
style="justify-content: space-between; align-items: center"
>
<view style="font-weight: bold">
<text style="color: #f8285a; margin-right: 8rpx">*</text>
截止日期
</view>
<view class="wd-flex" style="gap: 8rpx; align-items: center">
<text style="color: #f8285a">
{{ $util.formatDate(detail.correctionTime, 'YYYY年M月D日') }}
</text>
</view>
</view>
</view>
</view>
<view
class="box"
v-if="detail.status == 3"
>
<view
class="wd-flex"
style="
justify-content: space-between;
align-items: center;
"
>
<view style="font-weight: bold">
<text style="color: #f8285a; margin-right: 8rpx"
>*</text
>
截止日期
</view>
<view
class="wd-flex"
style="gap: 8rpx; align-items: center"
>
<text style="color: #f8285a">
{{
$util.formatDate(
detail.correctionTime,
'YYYY年M月D日'
)
}}
</text>
</view>
</view>
</view>
</view>
</template>
<script>
import { getDictBatchByType } from '@/api/system/dict.js'
import { InspectionsApi } from '@/api/inspections/index.js'
export default {
data() {
return { detail: {}, dictMap: {} }
},
async onLoad(res) {
this.detail.id = res.id
await this.getDict()
},
onShow() {
this.getDetail()
},
methods: {
getDetail() {
InspectionsApi.feedBackDetail(this.detail.id).then(res => {
this.detail = res.data
})
},
/**
* 获取字典
*/
async getDict() {
const dict = await getDictBatchByType({
type: ['inspections_mark'].join(',')
})
this.dictMap = {
...dict.data
}
}
}
}
import { getDictBatchByType } from '@/api/system/dict.js'
import { InspectionsApi } from '@/api/inspections/index.js'
export default {
data() {
return { detail: {}, dictMap: {} }
},
async onLoad(res) {
this.detail.id = res.id
await this.getDict()
},
onShow() {
this.getDetail()
},
methods: {
getDetail() {
InspectionsApi.feedBackDetail(this.detail.id).then(
res => {
this.detail = res.data
}
)
},
/**
* 获取字典
*/
async getDict() {
const dict = await getDictBatchByType({
type: ['inspections_mark'].join(','),
})
this.dictMap = {
...dict.data,
}
},
},
}
</script>
<style lang="scss" scoped>
.view-container {
padding: 24rpx;
display: flex;
gap: 24rpx;
flex-direction: column;
.box {
padding: 24rpx;
border-radius: 16rpx;
background-color: #fff;
display: flex;
flex-flow: column nowrap;
gap: 24rpx;
.view-container {
padding: 24rpx;
display: flex;
gap: 24rpx;
flex-direction: column;
.box {
padding: 24rpx;
border-radius: 16rpx;
background-color: #fff;
display: flex;
flex-flow: column nowrap;
gap: 24rpx;
.imageList {
display: flex;
gap: 24rpx;
.image {
width: 192rpx;
height: 192rpx;
border-radius: 16rpx;
flex-shrink: 0;
}
}
}
}
.imageList {
display: flex;
flex-wrap: wrap;
gap: 24rpx;
.image {
width: 192rpx;
height: 192rpx;
border-radius: 16rpx;
flex-shrink: 0;
}
}
}
}
</style>

865
sub/task/record.vue

@ -1,397 +1,492 @@
<template>
<scroll-view class="view-container" scroll-y>
<view class="box detail" style="margin-bottom: 12px">
<text class="wd-font-800 wd-text-16">
{{ detail.title }}
</text>
<view class="tagList">
<view class="tag" v-if="detail.priority">
{{ $dict.echoDicValue(dictMap.task_priority, detail.priority) }}
</view>
<view
v-for="(tag, index) in detail.tagList"
:key="index"
class="tag"
>
{{ tag }}
</view>
</view>
<view
class="wd-flex wd-text-13"
style="justify-content: space-between"
>
<view class="wd-flex" style="align-items: center; gap: 8rpx">
<u-icon name="calendar" color="#17C653" />
<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日')}`
}}
</text>
</view>
</view>
<cs-text-more :value="detail.description"></cs-text-more>
<view
class="wd-flex wd-items-center enterprise"
@tap="goEnterprise(detail.enterprise)"
>
<u-avatar
:src="detail.enterprise.files[0].url"
shape="square"
size="64"
></u-avatar>
<view class="wd-flex wd-flex-col" style="overflow: hidden">
<text class="wd-font-800 wd-text-15">
{{ detail.enterprise.enterprisesName }}
</text>
<view class="wd-flex" style="margin-top: 4rpx">
<u-icon name="map" size="28rpx" color="#17C653"></u-icon>
<text class="address wd-text-12" style="margin-left: 8rpx">
{{
`${$dict.echoDicValue(
dictMap.enterprises_area,
detail.enterprise.region
)} | ${detail.enterprise.address}`
}}
</text>
</view>
<view class="tagList" style="margin-top: 16rpx">
<view
class="tag"
v-for="(tag, index) in detail.enterprise.tagList"
:key="index"
>
{{ tag }}
</view>
</view>
</view>
</view>
<view class="audit">
<cs-dict-tag
:dict="dictMap.task_state"
:value="detail.status"
></cs-dict-tag>
</view>
</view>
<scroll-view
class="view-container"
scroll-y
>
<view
class="box detail"
style="margin-bottom: 12px"
>
<text
class="wd-font-800 wd-text-16"
style="padding-right: 100rpx"
>
{{ detail.title }}
</text>
<view class="tagList">
<view
class="tag"
v-if="detail.priority"
>
{{
$dict.echoDicValue(
dictMap.task_priority,
detail.priority
)
}}
</view>
<view
v-for="(tag, index) in detail.tagList"
:key="index"
class="tag"
>
{{ tag }}
</view>
</view>
<view
class="wd-flex wd-text-13"
style="justify-content: space-between"
>
<view
class="wd-flex"
style="align-items: center; gap: 8rpx"
>
<u-icon
name="calendar"
color="#17C653"
/>
<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日'
)}`
}}
</text>
</view>
</view>
<cs-text-more
:value="detail.description"
></cs-text-more>
<view
class="wd-flex wd-items-center enterprise"
@tap="goEnterprise(detail.enterprise)"
>
<u-avatar
:src="detail.enterprise.files[0].url"
shape="square"
size="64"
></u-avatar>
<view
class="wd-flex wd-flex-col"
style="overflow: hidden"
>
<text class="wd-font-800 wd-text-15">
{{ detail.enterprise.enterprisesName }}
</text>
<view
class="wd-flex"
style="margin-top: 4rpx"
>
<u-icon
name="map"
size="28rpx"
color="#17C653"
></u-icon>
<text
class="address wd-text-12"
style="margin-left: 8rpx"
>
{{
`${$dict.echoDicValue(
dictMap.enterprises_area,
detail.enterprise.region
)} | ${detail.enterprise.address}`
}}
</text>
</view>
<view
class="tagList"
style="margin-top: 16rpx"
>
<view
class="tag"
v-for="(tag, index) in detail.enterprise
.tagList"
:key="index"
>
{{ tag }}
</view>
</view>
</view>
</view>
<view class="audit">
<cs-dict-tag
:dict="dictMap.task_state"
:value="detail.status"
></cs-dict-tag>
</view>
</view>
<view class="box record">
<view class="wd-text-14 wd-font-800">结果反馈</view>
<view
class="row log"
v-for="item in list"
:key="item.id"
@tap="goLog(item)"
>
<view style="margin-bottom: 24rpx">
<text
:style="{
marginRight: '20rpx',
fontWeight: 'bold',
color: $dict.echoDictOption(
dictMap.Inspections_status,
item.status
).remark
}"
>
{{
$dict.echoDicValue(dictMap.Inspections_status, item.status)
}}
</text>
<text>
{{ $util.formatDate(item.createTime, 'YYYY/M/D h:m') }}
</text>
</view>
<scroll-view
scroll-x="true"
style="flex-flow: row nowrap; white-space: nowrap"
>
<view
class="row"
v-for="people in item.userList"
:key="people.userId"
style="display: inline-flex; gap: 24rpx; margin-right: 24rpx"
>
<u-avatar
:src="people.avtar"
size="80rpx"
shape="circle"
></u-avatar>
<view class="wd-flex wd-flex-col" style="gap: 4rpx">
<text>{{ people.realName }}</text>
<text>{{ people.deptName }}</text>
</view>
</view>
</scroll-view>
</view>
<view class="emty" v-if="list.length == 0">
<image
class="image"
src="/static/images/emty.png"
mode="aspectFill"
></image>
<text class="wd-text-14" style="color: #99a1b7">暂无处理结果</text>
</view>
<view class="audit">
<cs-dict-tag
:dict="dictMap.inspections_mark"
:value="inspectionsState"
color="#fff"
:bgColor="setColor(inspectionsState)"
></cs-dict-tag>
</view>
</view>
<view class="box record">
<view class="wd-text-14 wd-font-800">结果反馈</view>
<view
class="row log"
v-for="item in list"
:key="item.id"
@tap="goLog(item)"
>
<view style="margin-bottom: 24rpx">
<text
:style="{
marginRight: '20rpx',
fontWeight: 'bold',
color: $dict.echoDictOption(
dictMap.Inspections_status,
item.status
).remark,
}"
>
{{
$dict.echoDicValue(
dictMap.Inspections_status,
item.status
)
}}
</text>
<text>
{{
$util.formatDate(
item.createTime,
'YYYY/M/D h:m'
)
}}
</text>
</view>
<scroll-view
scroll-x="true"
style="flex-flow: row nowrap; white-space: nowrap"
>
<view
class="row"
v-for="people in item.userList"
:key="people.userId"
style="
display: inline-flex;
gap: 24rpx;
margin-right: 24rpx;
"
>
<u-avatar
:src="people.avtar"
size="80rpx"
shape="circle"
></u-avatar>
<view
class="wd-flex wd-flex-col"
style="gap: 4rpx"
>
<text>{{ people.realName }}</text>
<text>{{ people.deptName }}</text>
</view>
</view>
</scroll-view>
</view>
<view
class="emty"
v-if="list.length == 0"
>
<image
class="image"
src="/static/images/emty.png"
mode="aspectFill"
></image>
<text
class="wd-text-14"
style="color: #99a1b7"
>暂无处理结果</text
>
</view>
<view class="audit">
<cs-dict-tag
:dict="dictMap.inspections_mark"
:value="inspectionsState"
color="#fff"
:bgColor="setColor(inspectionsState)"
></cs-dict-tag>
</view>
</view>
<cs-bottom-wrapper>
<view
class="operation"
v-if="[null, 0, 3].includes(inspectionsState)"
>
<view class="btn green" @tap="locate">执法签到</view>
</view>
<view class="operation" v-else-if="inspectionsState == 1">
<view class="btn red" @tap="tackle(3)">整改处理</view>
<view class="btn green" @tap="tackle(2)">审批通过</view>
</view>
<view class="operation" v-else>
<view class="btn grey">任务完成</view>
</view>
</cs-bottom-wrapper>
</scroll-view>
<cs-bottom-wrapper>
<view
class="operation"
v-if="[null, 0, 3].includes(inspectionsState)"
>
<view
class="btn green"
@tap="locate"
>执法签到</view
>
</view>
<view
class="operation"
v-else-if="inspectionsState == 1"
>
<view
class="btn red"
@tap="tackle(3)"
>整改处理</view
>
<view
class="btn green"
@tap="tackle(2)"
>审批通过</view
>
</view>
<view
class="operation"
v-else
>
<view class="btn grey">任务完成</view>
</view>
</cs-bottom-wrapper>
</scroll-view>
</template>
<script>
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 {
dictMap: {},
//
detail: {
id: '',
description: '',
priority: '',
enterprise: {
region: '',
type: ''
}
},
//
isShowAllText: false,
//
queryParams: {
taskId: '',
recordId: '',
enterpriseId: ''
},
list: [],
inspectionsState: null
}
},
onLoad(res) {
this.queryParams.taskId = res.taskId
this.queryParams.recordId = res.recordId
this.queryParams.enterpriseId = res.enterpriseId
this.getDict()
this.init()
},
onShow() {
this.init()
},
methods: {
/**
* 获取字典
*/
async getDict() {
const dict = await getDictBatchByType({
type: [
'Inspections_status',
'task_state',
'inspections_mark',
'enterprises_type',
'enterprises_area',
'task_priority'
].join(',')
})
const dept = await getDeptTree()
this.dictMap = {
...dict.data,
dept: dept.data
}
},
async init() {
const res = await TaskApi.getDetail(this.queryParams.taskId)
const enterprise = await getEnterPrise(this.queryParams.enterpriseId)
this.detail = {
...res.data,
enterprise: enterprise.data
}
const feedBack = await InspectionsApi.getFeedBack(
this.queryParams.recordId
)
this.list = feedBack.data
this.inspectionsState =
this.list[this.list.length - 1]?.status || null
},
goEnterprise(enterprise) {
uni.navigateTo({
url: `/sub/enterprise/detail?id=${enterprise.id}`
})
},
viewPosition(enterprise) {
const position = enterprise.gpsLocation
.split(',')
.map(i => Number(i))
this.$util.viewPosition({
lat: position[0],
lng: position[1],
name: enterprise.enterprisesName,
address: enterprise.address
})
},
locate() {
uni.navigateTo({
url: `/sub/task/locate?inspectionsId=${this.queryParams.recordId}&enterpriseId=${this.queryParams.enterpriseId}`
})
},
setColor(status) {
const colorMap = {
1: '#F6B100',
2: '#17C653',
3: '#F8285A'
}
return colorMap[status]
},
tackle(state) {
uni.navigateTo({
url: `/sub/task/enforce?state=${state}&inspectionsId=${this.queryParams.recordId}`
})
},
goLog(record) {
if ([2, 3].includes(record.status)) {
uni.navigateTo({
url: `/sub/task/log?id=${record.id}`
})
}
}
}
}
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 {
dictMap: {},
//
detail: {
id: '',
description: '',
priority: '',
enterprise: {
region: '',
type: '',
},
},
//
isShowAllText: false,
//
queryParams: {
taskId: '',
recordId: '',
enterpriseId: '',
},
list: [],
inspectionsState: null,
}
},
onLoad(res) {
this.queryParams.taskId = res.taskId
this.queryParams.recordId = res.recordId
this.queryParams.enterpriseId = res.enterpriseId
this.getDict()
this.init()
},
onShow() {
this.init()
},
methods: {
/**
* 获取字典
*/
async getDict() {
const dict = await getDictBatchByType({
type: [
'Inspections_status',
'task_state',
'inspections_mark',
'enterprises_type',
'enterprises_area',
'task_priority',
].join(','),
})
const dept = await getDeptTree()
this.dictMap = {
...dict.data,
dept: dept.data,
}
},
async init() {
const res = await TaskApi.getDetail(
this.queryParams.taskId
)
const enterprise = await getEnterPrise(
this.queryParams.enterpriseId
)
this.detail = {
...res.data,
enterprise: enterprise.data,
}
const feedBack = await InspectionsApi.getFeedBack(
this.queryParams.recordId
)
this.list = feedBack.data
this.inspectionsState =
this.list[this.list.length - 1]?.status || null
},
goEnterprise(enterprise) {
uni.navigateTo({
url: `/sub/enterprise/detail?id=${enterprise.id}`,
})
},
viewPosition(enterprise) {
const position = enterprise.gpsLocation
.split(',')
.map(i => Number(i))
this.$util.viewPosition({
lat: position[0],
lng: position[1],
name: enterprise.enterprisesName,
address: enterprise.address,
})
},
locate() {
uni.navigateTo({
url: `/sub/task/locate?inspectionsId=${this.queryParams.recordId}&enterpriseId=${this.queryParams.enterpriseId}`,
})
},
setColor(status) {
const colorMap = {
1: '#F6B100',
2: '#17C653',
3: '#F8285A',
}
return colorMap[status]
},
tackle(state) {
uni.navigateTo({
url: `/sub/task/enforce?state=${state}&inspectionsId=${this.queryParams.recordId}`,
})
},
goLog(record) {
if ([2, 3].includes(record.status)) {
uni.navigateTo({
url: `/sub/task/log?id=${record.id}`,
})
}
},
},
}
</script>
<style lang="scss" scoped>
.view-container {
padding: 0 24rpx;
position: relative;
padding-bottom: 200rpx;
.box {
background-color: #fff;
border-radius: $cs-border-radius;
padding: 32rpx;
margin-top: 24rpx;
}
.row {
border-radius: $cs-border-radius;
padding: 24rpx;
border: 2rpx solid #f9f9f9;
}
.detail {
display: flex;
flex-flow: column nowrap;
gap: 24rpx;
position: relative;
overflow: hidden;
.view-container {
padding: 0 24rpx;
position: relative;
padding-bottom: 200rpx;
.box {
background-color: #fff;
border-radius: $cs-border-radius;
padding: 32rpx;
margin-top: 24rpx;
}
.row {
border-radius: $cs-border-radius;
padding: 24rpx;
border: 2rpx solid #f9f9f9;
}
.detail {
display: flex;
flex-flow: column nowrap;
gap: 24rpx;
position: relative;
overflow: hidden;
.enterprise {
border: 2rpx solid #f9f9f9;
padding: 24rpx;
border-radius: $cs-border-radius;
gap: 24rpx;
position: relative;
overflow: hidden;
font-size: 24rpx;
.address {
color: $uni-text-color-grey;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
&:active {
background-color: $cs-color-touch;
}
}
.audit {
position: absolute;
right: 0;
top: 0;
transform: translateX(36rpx) translateY(32rpx) rotateZ(45deg);
transform-origin: 50% 50%;
}
}
.enterprise {
border: 2rpx solid #f9f9f9;
padding: 24rpx;
border-radius: $cs-border-radius;
gap: 24rpx;
position: relative;
overflow: hidden;
font-size: 24rpx;
.address {
color: $uni-text-color-grey;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
&:active {
background-color: $cs-color-touch;
}
}
.audit {
position: absolute;
right: 0;
top: 0;
transform: translateX(36rpx) translateY(32rpx)
rotateZ(45deg);
transform-origin: 50% 50%;
}
}
.record {
position: relative;
overflow: hidden;
display: flex;
flex-flow: column nowrap;
gap: 24rpx;
.emty {
display: flex;
flex-direction: column;
align-items: center;
gap: 24rpx;
border-radius: 16rpx;
border: 2rpx solid var(--LightMode-Grey-Grey-100, #f9f9f9);
padding: 48rpx 24rpx;
border-radius: 16rpx;
.image {
width: 128rpx;
height: 128rpx;
}
}
.audit {
position: absolute;
right: 0;
top: 0;
transform: translateX(68rpx) translateY(19rpx) rotateZ(45deg);
transform-origin: 50% 50%;
}
}
.log {
&:active {
background-color: $cs-color-touch;
}
}
.operation {
padding: 24rpx;
display: flex;
align-items: center;
justify-content: center;
gap: 24rpx;
.btn {
flex: 1;
border-radius: 16rpx;
display: flex;
padding: 24rpx 0;
align-items: center;
justify-content: center;
font-weight: bold;
}
.green {
background-color: $cs-color-main;
color: #fff;
}
.red {
background-color: #f8285a;
color: #fff;
}
.grey {
background-color: #f1f1f4;
color: #99a1b7;
}
}
}
.record {
position: relative;
overflow: hidden;
display: flex;
flex-flow: column nowrap;
gap: 24rpx;
.emty {
display: flex;
flex-direction: column;
align-items: center;
gap: 24rpx;
border-radius: 16rpx;
border: 2rpx solid
var(--LightMode-Grey-Grey-100, #f9f9f9);
padding: 48rpx 24rpx;
border-radius: 16rpx;
.image {
width: 128rpx;
height: 128rpx;
}
}
.audit {
position: absolute;
right: 0;
top: 0;
transform: translateX(68rpx) translateY(19rpx)
rotateZ(45deg);
transform-origin: 50% 50%;
}
}
.log {
&:active {
background-color: $cs-color-touch;
}
}
.operation {
padding: 24rpx;
display: flex;
align-items: center;
justify-content: center;
gap: 24rpx;
.btn {
flex: 1;
border-radius: 16rpx;
display: flex;
padding: 24rpx 0;
align-items: center;
justify-content: center;
font-weight: bold;
}
.green {
background-color: $cs-color-main;
color: #fff;
}
.red {
background-color: #f8285a;
color: #fff;
}
.grey {
background-color: #f1f1f4;
color: #99a1b7;
}
}
}
</style>

Loading…
Cancel
Save