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", "path": "pages/login",
"style": { "style": {
"navigationBarTitleText": "登录", "navigationBarTitleText": "登录",
"navigationStyle": "custom", "navigationStyle": "custom",
"disableScroll": true "disableScroll": true
} }
}, { },
{
"path": "pages/index", "path": "pages/index",
"style": { "style": {
"navigationBarTitleText": "首页", "navigationBarTitleText": "首页",
@ -68,204 +70,215 @@
"^u-(.*)": "@/uni_modules/uview-ui/components/u-$1/u-$1.vue" "^u-(.*)": "@/uni_modules/uview-ui/components/u-$1/u-$1.vue"
} }
}, },
"subPackages": [{ "subPackages": [
"root": "sub", {
"pages": [{ "root": "sub",
"path": "owner/edit", "pages": [
"style": { {
"navigationBarTitleText": "个人信息" "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"
} }
} },
}, {
{ "path": "owner/invite",
"path": "owner/policy-detail", "style": {
"style": { "navigationBarTitleText": "邀请企业"
"navigationBarTitleText": "政策法规",
"usingComponents": {},
"componentPlaceholder": {}
}
},
{
"path": "owner/jobInfo",
"style": {
"navigationBarTitleText": "工作汇报",
"usingComponents": {
"van-search": "/wxcomponents/vant/search/index"
},
"componentPlaceholder": {
"u-modal": "view"
} }
} },
}, {
{ "path": "owner/policy",
"path": "owner/job-detail", "style": {
"style": { "navigationBarTitleText": "政策法规",
"navigationBarTitleText": "工作汇报", "usingComponents": {
"usingComponents": {}, "van-search": "/wxcomponents/vant/search/index"
"componentPlaceholder": {} },
} "componentPlaceholder": {
}, "u-modal": "view"
}
{
"path": "enterprise/edit",
"style": {
"navigationBarTitleText": "企业填报"
}
}, {
"path": "common/waiting",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom"
}
}, {
"path": "enterprise/detail",
"style": {
"navigationBarTitleText": "档案详情",
"componentPlaceholder": {
"u-modal": "view"
} }
} },
}, { {
"path": "chat/index", "path": "owner/policy-detail",
"style": { "style": {
"navigationBarTitleText": "智慧生态" "navigationBarTitleText": "政策法规",
} "usingComponents": {},
}, { "componentPlaceholder": {}
"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/jobInfo",
"path": "task/record", "style": {
"style": { "navigationBarTitleText": "工作汇报",
"navigationBarTitleText": "记录详情 ", "usingComponents": {
"usingComponents": {}, "van-search": "/wxcomponents/vant/search/index"
"componentPlaceholder": {} },
} "componentPlaceholder": {
}, "u-modal": "view"
{ }
"path": "task/locate",
"style": {
"usingComponents": {
"van-action-sheet": "/wxcomponents/vant/action-sheet/index"
},
"componentPlaceholder": {
"u-modal": "view"
} }
} },
}, {
{ "path": "owner/job-detail",
"path": "task/enforce", "style": {
"style": { "navigationBarTitleText": "工作汇报",
"navigationBarTitleText": "结果反馈", "usingComponents": {},
"usingComponents": { "componentPlaceholder": {}
"van-action-sheet": "/wxcomponents/vant/action-sheet/index"
},
"componentPlaceholder": {
"u-modal": "view",
"uni-easyinput": "view"
} }
} },
}, {
{ "path": "enterprise/edit",
"path": "task/log", "style": {
"style": { "navigationBarTitleText": "企业填报"
"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": "common/waiting",
"path": "invite/addEnterprise", "style": {
"style": { "navigationBarTitleText": "",
"navigationBarTitleText": "新增企业", "navigationStyle": "custom"
"componentPlaceholder": {} }
} },
}, {
{ "path": "enterprise/detail",
"path": "invite/enterpriseIntroduce", "style": {
"style": { "navigationBarTitleText": "档案详情",
"navigationBarTitleText": "企业简介", "componentPlaceholder": {
"componentPlaceholder": { "u-modal": "view"
"uni-easyinput": "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": { "tabBar": {
"list": [{ "list": [
{
"pagePath": "pages/index" "pagePath": "pages/index"
}, },
{ {
@ -287,6 +300,5 @@
"navigationBarTitleText": "智慧生态", "navigationBarTitleText": "智慧生态",
"navigationBarBackgroundColor": "#FFF", "navigationBarBackgroundColor": "#FFF",
"backgroundColor": "#FFF" "backgroundColor": "#FFF"
} }
} }

68
static/scss/global.scss

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

819
sub/enterprise/detail.vue

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

299
sub/inspection/record.vue

@ -1,148 +1,167 @@
<template> <template>
<scroll-view scroll-y flex-enable class="view-container"> <scroll-view
<view class="box" v-for="log in list" :key="log.id"> scroll-y
<view class="wd-flex" style="gap: 10px; align-items: center"> flex-enable
<view class="view-container"
:style="{ >
color: $dict.echoDictOption( <view
dictMap.inspections_mark, class="box"
log.status v-for="log in list"
).remark :key="log.id"
}" >
> <view
{{ class="wd-flex"
$dict.echoDictOption(dictMap.inspections_mark, log.status) style="gap: 10px; align-items: center"
.label >
}} <view
</view> :style="{
<view class=""> color: $dict.echoDictOption(
{{ $util.formatDate(log.createTime, 'YYYY/M/D') }} dictMap.inspections_mark,
</view> log.status
</view> ).remark,
<scroll-view }"
scroll-x >
style="flex-flow: row nowrap; white-space: nowrap" {{
:enable-flex="true" $dict.echoDictOption(
> dictMap.inspections_mark,
<view log.status
v-for="people in log.userList" ).label
:key="people.userId" }}
style=" </view>
display: inline-flex; <view class="">
gap: 24rpx; {{ $util.formatDate(log.createTime, 'YYYY/M/D') }}
border: 1px solid #f9f9f9; </view>
border-radius: 16rpx; </view>
padding: 24rpx; <scroll-view
margin-right: 24rpx; scroll-x
" style="flex-flow: row nowrap; white-space: nowrap"
> :enable-flex="true"
<u-avatar >
:src="people.avtar" <view
size="80rpx" v-for="people in log.userList"
shape="circle" :key="people.userId"
></u-avatar> style="
<view class="wd-flex wd-flex-col" style="gap: 2px"> display: inline-flex;
<text>{{ people.realName }}</text> gap: 24rpx;
<text>{{ people.deptName }}</text> border: 1px solid #f9f9f9;
</view> border-radius: 16rpx;
</view> padding: 24rpx;
</scroll-view> margin-right: 24rpx;
<cs-text-more :value="log.feedBack"></cs-text-more> "
<view class="imageList"> >
<image <u-avatar
:src="photo.url" :src="people.avtar"
v-for="photo in log.fileList" size="80rpx"
:key="photo.id" shape="circle"
mode="aspectFill" ></u-avatar>
class="image" <view
@tap="previewImage(log.fileList)" class="wd-flex wd-flex-col"
></image> style="gap: 2px"
</view> >
</view> <text>{{ people.realName }}</text>
<cs-emty v-if="list.length == 0"></cs-emty> <text>{{ people.deptName }}</text>
</scroll-view> </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> </template>
<script> <script>
import { getDictBatchByType } from '@/api/system/dict.js' import { getDictBatchByType } from '@/api/system/dict.js'
import { getTaskLog } from '@/api/enterprise/index.js' import { getTaskLog } from '@/api/enterprise/index.js'
export default { export default {
data() { data() {
return { return {
queryParams: { queryParams: {
taskId: '' taskId: '',
}, },
list: [], list: [],
dictMap: {} dictMap: {},
} }
}, },
onLoad(res) { onLoad(res) {
uni.setNavigationBarTitle({ uni.setNavigationBarTitle({
title: res.taskName title: res.taskName,
}) })
this.queryParams.taskId = res.taskId this.queryParams.taskId = res.taskId
this.getDict() this.getDict()
this.getList() this.getList()
}, },
onReachBottom() { onReachBottom() {
this.loadMore() this.loadMore()
}, },
onPullDownRefresh() { onPullDownRefresh() {
this.reset() this.reset()
}, },
methods: { methods: {
/** /**
* 获取字典 * 获取字典
*/ */
async getDict() { async getDict() {
const dict = await getDictBatchByType({ const dict = await getDictBatchByType({
type: ['inspections_mark'].join(',') type: ['inspections_mark'].join(','),
}) })
this.dictMap = { this.dictMap = {
...dict.data ...dict.data,
} }
}, },
async getList() { async getList() {
uni.showToast({ uni.showToast({
title: '加载中', title: '加载中',
mask: true, mask: true,
icon: 'loading' icon: 'loading',
}) })
const res = await getTaskLog(this.queryParams.taskId) const res = await getTaskLog(
this.list = res.data this.queryParams.taskId
uni.hideToast() )
}, this.list = res.data
previewImage(url) { uni.hideToast()
this.$util.perviewImage(url.map(i => i.url)) },
} previewImage(url) {
} this.$util.perviewImage(url.map(i => i.url))
} },
},
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.view-container { .view-container {
padding: 24rpx; padding: 24rpx;
flex-direction: column; flex-direction: column;
gap: 24rpx; gap: 24rpx;
.box { .box {
border-radius: 24rpx; border-radius: 24rpx;
padding: 24rpx; padding: 24rpx;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 24rpx; gap: 24rpx;
background-color: #fff; background-color: #fff;
position: relative; position: relative;
margin-bottom: 24rpx; margin-bottom: 24rpx;
.imageList { .imageList {
display: flex; display: flex;
gap: 24rpx; flex-wrap: wrap;
.image { gap: 24rpx;
width: 192rpx; .image {
height: 192rpx; width: 192rpx;
border-radius: 16rpx; height: 192rpx;
flex-shrink: 0; border-radius: 16rpx;
} flex-shrink: 0;
} }
} }
} }
}
</style> </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> <template>
<view class="view"> <view class="view">
<view class="block"> <view class="block">
<view style=""> <view style="">
<text style="color: #f8285a; margin-right: 4px">*</text> <text style="color: #f8285a; margin-right: 4px"
资质名称 >*</text
</view> >
<view 资质名称
class="value" </view>
@tap="showPicker('enterprise_qua', 'qualificationName')" <view
> class="value"
<view class="input-textarea" v-if="prove.qualificationName"> @tap="
{{ showPicker('enterprise_qua', 'qualificationName')
$dict.echoDicValue( "
dictMap.enterprise_qua, >
prove.qualificationName <view
) class="input-textarea"
}} v-if="prove.qualificationName"
</view> >
<view class="input-textarea" style="color: #808080" v-else> {{
请选择资质名称 $dict.echoDicValue(
</view> dictMap.enterprise_qua,
<u-icon name="arrow-right"></u-icon> prove.qualificationName
</view> )
</view> }}
</view>
<view
class="input-textarea"
style="color: #808080"
v-else
>
请选择资质名称
</view>
<u-icon name="arrow-right"></u-icon>
</view>
</view>
<view class="block"> <view class="block">
<view style=""> <view style="">
<text style="color: #f8285a; margin-right: 4px">*</text> <text style="color: #f8285a; margin-right: 4px"
资质编号 >*</text
</view> >
<view class="value"> 资质编号
<input </view>
class="input-value" <view class="value">
type="text" <input
:adjust-position="true" class="input-value"
cursorSpacing="32" type="text"
placeholder-class="txt" :adjust-position="true"
placeholder="请输入资质编号" cursorSpacing="32"
v-model="prove.enterpriseAuth" placeholder-class="txt"
/> placeholder="请输入资质编号"
<u-icon name="arrow-right"></u-icon> v-model="prove.enterpriseAuth"
</view> />
</view> <u-icon name="arrow-right"></u-icon>
</view>
</view>
<!-- <view class="block"> <!-- <view class="block">
<view style=""> <view style="">
<text style="color: #f8285a; margin-right: 4px">*</text> <text style="color: #f8285a; margin-right: 4px">*</text>
办理时间 办理时间
@ -58,359 +71,412 @@
<u-icon name="arrow-right"></u-icon> <u-icon name="arrow-right"></u-icon>
</view> </view>
</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
<view style=""> class="block"
<text style="color: #f8285a; margin-right: 4px">*</text> v-if="!prove.isLong"
到期时间 >
</view> <view style="">
<view class="value" @tap="showCalendar('expiryDate')"> <text style="color: #f8285a; margin-right: 4px"
<view class="input-textarea" v-if="prove.expiryDate"> >*</text
{{ prove.expiryDate }} >
</view> 到期时间
<view class="input-textarea" style="color: #808080" v-else> </view>
请选择到期时间 <view
</view> class="value"
<u-icon name="arrow-right"></u-icon> @tap="showCalendar('expiryDate')"
</view> >
</view> <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="upload-wrapper">
<view <view
class="wd-flex" class="wd-flex"
style=" style="
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
width: 100%; width: 100%;
" "
> >
<view style=""> <view style="">
<text style="color: #f8285a; margin-right: 4px">*</text> <text style="color: #f8285a; margin-right: 4px"
资质照片 >*</text
</view> >
<view style="color: #808080">要求清晰有效</view> 资质照片
</view> </view>
<u-upload <view style="color: #808080">要求清晰有效</view>
:fileList="prove.photo" </view>
@afterRead="addPhoto" <u-upload
@delete="delPhoto" :fileList="prove.photo"
:maxCount="1" @afterRead="addPhoto"
width="101" @delete="delPhoto"
height="101" :maxCount="1"
></u-upload> width="101"
</view> height="101"
></u-upload>
</view>
<cs-bottom-wrapper> <cs-bottom-wrapper>
<view class="operation"> <view class="operation">
<button class="btn green" @tap="submit">保存</button> <button
</view> class="btn green"
</cs-bottom-wrapper> @tap="submit"
<u-picker >
:show="picker.show" 保存
:columns="picker.data" </button>
@cancel="closePicker" </view>
closeOnClickOverlay </cs-bottom-wrapper>
keyName="label" <u-picker
ref="uPicker" :show="picker.show"
@close="closePicker" :columns="picker.data"
@confirm="confirmPicker" @cancel="closePicker"
></u-picker> closeOnClickOverlay
<uni-calendar keyName="label"
ref="calendarRef" ref="uPicker"
:insert="false" @close="closePicker"
@confirm="confirmCalendar" @confirm="confirmPicker"
/> ></u-picker>
</view> <uni-calendar
ref="calendarRef"
:insert="false"
@confirm="confirmCalendar"
/>
</view>
</template> </template>
<script> <script>
import { uploadFile } from '@/api/system/file.js' import { uploadFile } from '@/api/system/file.js'
import { getDictBatchByType } from '@/api/system/dict.js' import { getDictBatchByType } from '@/api/system/dict.js'
import { updateProve, createProve } from '@/api/enterprise/prove.js' import {
export default { updateProve,
data() { createProve,
return { } from '@/api/enterprise/prove.js'
enterpriseId: '', export default {
prove: { data() {
id: '', return {
qualificationName: '', enterpriseId: '',
expiryDate: '', prove: {
enterpriseAuth: '', id: '',
photo: [] qualificationName: '',
}, expiryDate: '',
dictMap: {}, enterpriseAuth: '',
// photo: [],
picker: { isLong: false,
show: false, },
// dictMap: {},
key: null, //
data: [] picker: {
}, show: false,
// //
calendar: { key: null,
// data: [],
key: null },
} //
} calendar: {
}, //
onLoad(res) { key: null,
this.getDict() },
uni.setNavigationBarTitle({ }
title: res.prove ? '编辑资质' : '新增资质' },
}) onLoad(res) {
if (res.enterpriseId) { this.getDict()
this.enterpriseId = res.enterpriseId uni.setNavigationBarTitle({
} title: res.prove ? '编辑资质' : '新增资质',
if (res.prove) { })
this.prove = JSON.parse(res.prove) if (res.enterpriseId) {
} this.enterpriseId = res.enterpriseId
}, }
methods: { if (res.prove) {
/** this.prove = JSON.parse(res.prove)
* 获取字典 }
*/ },
async getDict() { methods: {
const dict = await getDictBatchByType({ /**
type: ['enterprise_qua'].join(',') * 获取字典
}) */
this.dictMap = { async getDict() {
...dict.data const dict = await getDictBatchByType({
} type: ['enterprise_qua'].join(','),
}, })
/** this.dictMap = {
* 选择图片并上传 ...dict.data,
* @param {Object} e }
*/ },
async addPhoto(e) { /**
uni.showLoading({ * 选择图片并上传
title: '正在上传...' * @param {Object} e
}) */
this.prove.photo.push({ async addPhoto(e) {
...e.file, uni.showLoading({
status: 'uploading', title: '正在上传...',
message: '上传中' })
}) this.prove.photo.push({
uploadFile({ name: `file`, filePath: e.file.url }).then(res => { ...e.file,
this.prove.photo = [] status: 'uploading',
this.prove.photo.push({ message: '上传中',
...res.data, })
status: 'success', uploadFile({
message: '' name: `file`,
}) filePath: e.file.url,
uni.hideLoading() }).then(res => {
}) this.prove.photo = []
}, this.prove.photo.push({
/** ...res.data,
* 删除图片 status: 'success',
* @param {Object} e message: '',
*/ })
delPhoto(e) { uni.hideLoading()
this.prove.photo = [] })
}, },
/** /**
* 选择器确认回调 * 删除图片
* @param {Object} e * @param {Object} e
*/ */
confirmPicker(e) { delPhoto(e) {
const { value } = e this.prove.photo = []
this.prove[this.picker.key] = value[0].value },
this.closePicker() /**
}, * 选择器确认回调
/** * @param {Object} e
* 关闭选择器 */
*/ confirmPicker(e) {
closePicker() { const { value } = e
this.picker = { this.prove[this.picker.key] = value[0].value
show: false, this.closePicker()
key: '', },
data: [] /**
} * 关闭选择器
}, */
showPicker(dict, key) { closePicker() {
this.picker.data.push(this.dictMap[dict]) this.picker = {
this.picker.key = key show: false,
this.picker.show = true key: '',
}, data: [],
/** }
* 显示日历 },
* @param {Object} key 表单中需要赋值的键 showPicker(dict, key) {
*/ this.picker.data.push(this.dictMap[dict])
showCalendar(key) { this.picker.key = key
this.$refs.calendarRef.open() this.picker.show = true
this.calendar = { },
key /**
} * 显示日历
}, * @param {Object} key 表单中需要赋值的键
/** */
* 日历选中之后的回调 showCalendar(key) {
* @param {Object} e this.$refs.calendarRef.open()
*/ this.calendar = {
confirmCalendar(e) { key,
this.prove[this.calendar.key] = e.fulldate }
this.closeCalendar() },
}, /**
/** * 日历选中之后的回调
* 关闭日历 * @param {Object} e
*/ */
closeCalendar() { confirmCalendar(e) {
this.calendar = { this.prove[this.calendar.key] = e.fulldate
key: null this.closeCalendar()
} },
}, /**
async submit() { * 关闭日历
const valide = await this.verifyForm() */
if (!valide) return closeCalendar() {
if (this.prove.id) { this.calendar = {
uni.showLoading({ key: null,
title: '更新中...' }
}) },
const data = { ...this.prove } async submit() {
data.files = this.prove.photo.map(p => p.id) const valide = await this.verifyForm()
data.expiryDate = new Date(this.prove.expiryDate).getTime() if (!valide) return
updateProve(data).then(res => { if (this.prove.id) {
uni.hideLoading() uni.showLoading({
uni.showToast({ title: '更新中...',
icon: 'none', })
title: '操作成功' const data = { ...this.prove }
}) data.files = this.prove.photo.map(p => p.id)
uni.$emit('prove', this.prove) data.expiryDate = new Date(
uni.navigateBack() this.prove.expiryDate
}) ).getTime()
} else if (this.enterpriseId) { updateProve(data).then(res => {
uni.showLoading({ uni.hideLoading()
title: '更新中...' uni.showToast({
}) icon: 'none',
const data = { ...this.prove } title: '操作成功',
data.files = this.prove.photo.map(p => p.id) })
data.expiryDate = new Date(this.prove.expiryDate).getTime() uni.$emit('prove', this.prove)
data.enterpriseId = this.enterpriseId uni.navigateBack()
createProve(data).then(res => { })
uni.hideLoading() } else if (this.enterpriseId) {
uni.showToast({ uni.showLoading({
icon: 'none', title: '更新中...',
title: '操作成功' })
}) const data = { ...this.prove }
uni.$emit('prove', this.prove) data.files = this.prove.photo.map(p => p.id)
uni.navigateBack() data.expiryDate = new Date(
}) this.prove.expiryDate
} else { ).getTime()
uni.$emit('prove', this.prove) data.enterpriseId = this.enterpriseId
uni.navigateBack() createProve(data).then(res => {
} uni.hideLoading()
}, uni.showToast({
async hanlderApi() { icon: 'none',
if (this.prove.id) { title: '操作成功',
} else { })
} uni.$emit('prove', this.prove)
}, uni.navigateBack()
async verifyForm() { })
const msgMap = { } else {
qualificationName: '请填写资质名称', uni.$emit('prove', this.prove)
expiryDate: '请选择到期日期', uni.navigateBack()
enterpriseAuth: '请填写资质编号', }
photo: '请上传资质照片' },
} async hanlderApi() {
const keys = Object.keys(this.prove).filter(i => { if (this.prove.id) {
if (!Object.hasOwn(msgMap, i)) { } else {
return false }
} },
if (i == 'expiryDate' && this.prove.qualificationName == 99) async verifyForm() {
return false const msgMap = {
if (!this.prove[i] && i) return i qualificationName: '请填写资质名称',
if (typeof this.prove[i] == 'object' && this.prove[i].length == 0) expiryDate: '请选择到期日期',
return i enterpriseAuth: '请填写资质编号',
}) photo: '请上传资质照片',
if (keys.length > 0) { }
const msg = keys const keys = Object.keys(this.prove).filter(i => {
.map(i => { if (!Object.hasOwn(msgMap, i)) {
return msgMap[i] return false
}) }
.join('\n') if (i == 'expiryDate' && this.prove.isLong)
uni.showToast({ return false
icon: 'none', if (!this.prove[i] && i) return i
title: msg if (
}) typeof this.prove[i] == 'object' &&
return false this.prove[i].length == 0
} )
return true 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> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.view { .view {
padding: 12px; padding: 12px;
display: flex; display: flex;
flex-flow: column nowrap; flex-flow: column nowrap;
gap: 12px; gap: 12px;
overflow: hidden; overflow: hidden;
overflow-y: scroll; overflow-y: scroll;
max-height: 100vh; max-height: 100vh;
padding-bottom: 12vh; padding-bottom: 12vh;
} }
.block { .block {
display: flex; display: flex;
flex-flow: row nowrap; flex-flow: row nowrap;
background-color: #fff; background-color: #fff;
padding: 12px; padding: 12px;
border-radius: 8px; border-radius: 8px;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
gap: 12px; gap: 12px;
.value { .value {
flex: 1; flex: 1;
display: flex; display: flex;
flex-flow: row nowrap; flex-flow: row nowrap;
justify-content: space-between; justify-content: space-between;
gap: 4px; gap: 4px;
.input-value { .input-value {
flex: 1; flex: 1;
text-align: right; text-align: right;
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis; text-overflow: ellipsis;
} }
.input-textarea { .input-textarea {
flex: 1; flex: 1;
display: -webkit-box; display: -webkit-box;
overflow: hidden; overflow: hidden;
text-align: right; text-align: right;
max-height: 3rem; max-height: 3rem;
line-height: 1rem; line-height: 1rem;
text-overflow: ellipsis; text-overflow: ellipsis;
-webkit-line-clamp: 3; -webkit-line-clamp: 3;
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
word-break: break-all; word-break: break-all;
} }
} }
} }
.upload-wrapper { .upload-wrapper {
display: flex; display: flex;
flex-flow: column nowrap; flex-flow: column nowrap;
background-color: #fff; background-color: #fff;
padding: 12px; padding: 12px;
border-radius: 8px; border-radius: 8px;
gap: 12px; gap: 12px;
} }
.operation { .operation {
padding: 12px; padding: 12px;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
gap: 12px; gap: 12px;
.btn { .btn {
flex: 1; flex: 1;
border-radius: 8px; border-radius: 8px;
display: flex; display: flex;
padding: 12px 0; padding: 12px 0;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
.green { .green {
background-color: $cs-color-main; background-color: $cs-color-main;
color: #fff; color: #fff;
} }
} }
</style> </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> <template>
<view class="view-container"> <view class="view-container">
<view class="box"> <view class="box">
<view <view
class="wd-flex" class="wd-flex"
style="justify-content: space-between; align-items: center" style="
> justify-content: space-between;
<view style="font-weight: bold"> align-items: center;
<text style="color: #f8285a; margin-right: 8rpx">*</text> "
处理意见 >
</view> <view style="font-weight: bold">
</view> <text style="color: #f8285a; margin-right: 8rpx"
<view style="color: #071437">{{ detail.feedBack }}</view> >*</text
<view >
class="wd-flex" 处理意见
style="justify-content: space-between; align-items: center" </view>
> </view>
<view style="font-weight: bold"> <view style="color: #071437">{{
<text style="color: #f8285a; margin-right: 8rpx">*</text> detail.feedBack
上传证明 }}</view>
</view> <view
</view> class="wd-flex"
<view style="
class="imageList" justify-content: space-between;
@tap="$util.perviewImage(detail.fileList.map(i => i.url))" align-items: center;
> "
<image >
:src="photo.url" <view style="font-weight: bold">
v-for="photo in detail.fileList" <text style="color: #f8285a; margin-right: 8rpx"
:key="photo.id" >*</text
mode="aspectFill" >
class="image" 上传证明
></image> </view>
</view> </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
<view class="box"
class="wd-flex" v-if="detail.status == 3"
style="justify-content: space-between; align-items: center" >
> <view
<view style="font-weight: bold"> class="wd-flex"
<text style="color: #f8285a; margin-right: 8rpx">*</text> style="
截止日期 justify-content: space-between;
</view> align-items: center;
<view class="wd-flex" style="gap: 8rpx; align-items: center"> "
<text style="color: #f8285a"> >
{{ $util.formatDate(detail.correctionTime, 'YYYY年M月D日') }} <view style="font-weight: bold">
</text> <text style="color: #f8285a; margin-right: 8rpx"
</view> >*</text
</view> >
</view> 截止日期
</view> </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> </template>
<script> <script>
import { getDictBatchByType } from '@/api/system/dict.js' import { getDictBatchByType } from '@/api/system/dict.js'
import { InspectionsApi } from '@/api/inspections/index.js' import { InspectionsApi } from '@/api/inspections/index.js'
export default { export default {
data() { data() {
return { detail: {}, dictMap: {} } return { detail: {}, dictMap: {} }
}, },
async onLoad(res) { async onLoad(res) {
this.detail.id = res.id this.detail.id = res.id
await this.getDict() await this.getDict()
}, },
onShow() { onShow() {
this.getDetail() this.getDetail()
}, },
methods: { methods: {
getDetail() { getDetail() {
InspectionsApi.feedBackDetail(this.detail.id).then(res => { InspectionsApi.feedBackDetail(this.detail.id).then(
this.detail = res.data res => {
}) this.detail = res.data
}, }
/** )
* 获取字典 },
*/ /**
async getDict() { * 获取字典
const dict = await getDictBatchByType({ */
type: ['inspections_mark'].join(',') async getDict() {
}) const dict = await getDictBatchByType({
this.dictMap = { type: ['inspections_mark'].join(','),
...dict.data })
} this.dictMap = {
} ...dict.data,
} }
} },
},
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.view-container { .view-container {
padding: 24rpx; padding: 24rpx;
display: flex; display: flex;
gap: 24rpx; gap: 24rpx;
flex-direction: column; flex-direction: column;
.box { .box {
padding: 24rpx; padding: 24rpx;
border-radius: 16rpx; border-radius: 16rpx;
background-color: #fff; background-color: #fff;
display: flex; display: flex;
flex-flow: column nowrap; flex-flow: column nowrap;
gap: 24rpx; gap: 24rpx;
.imageList { .imageList {
display: flex; display: flex;
gap: 24rpx; flex-wrap: wrap;
.image { gap: 24rpx;
width: 192rpx; .image {
height: 192rpx; width: 192rpx;
border-radius: 16rpx; height: 192rpx;
flex-shrink: 0; border-radius: 16rpx;
} flex-shrink: 0;
} }
} }
} }
}
</style> </style>

865
sub/task/record.vue

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

Loading…
Cancel
Save