慧治理定制应用

This commit is contained in:
aixianling
2022-08-24 10:09:08 +08:00
parent 23302fc5c3
commit c917ac5acf
9 changed files with 1625 additions and 0 deletions

View File

@@ -65,6 +65,43 @@
</div>
</div>
</tempalte>
<div class="title-wrap" v-if="activityList.length">
<span class="title">居民活动</span>
<div class="right">
<span class="title-more" @click="$linkTo('/mods/AppVillageActivity/AppVillageActivity')">更多活动</span>
<u-icon name="arrow-right" size="28" color="#999999"></u-icon>
</div>
</div>
<scroll-view :scroll-x="true" style="width: 100%" class="scroll-wrap" v-if="activityList.length">
<div
class="scroll-card"
@click="$linkTo('/mods/AppVillageActivity/ActivityDetail?id=' + item.id)"
hover-class="text-hover"
v-for="(item, index) in activityList"
:key="index">
<image :src="item.url" mode="aspectFill"/>
<div class="text">
<span>{{ item.title }}</span>
</div>
</div>
<AiEmpty v-if="!activityList.length"></AiEmpty>
</scroll-view>
<div class="title-wrap">
<span class="title">乡村相册</span>
</div>
<div class="album-list">
<div
class="album"
v-for="(item, index) in albumList"
hover-class="text-hover"
:key="index"
@click="$linkTo('./AppPhotoAlbum?type=' + item.type + '&name=' + item.name + '&url=' + item.coverImg)">
<image :src="item.coverImg"/>
<div class="total">{{ item.total }}</div>
<div class="desc">{{ item.name }}</div>
</div>
<AiEmpty style="width: 100%" v-if="!albumList.length"></AiEmpty>
</div>
<AiLogin ref="login"/>
</div>
</template>
@@ -83,6 +120,8 @@ export default {
areaName: '',
areaId: '',
$areaId: '',
albumList: [],
activityList: [],
publicList: [],
moduleId: "",
isInit: false
@@ -96,8 +135,14 @@ export default {
this.autoLogin()
this.$nextTick(() => {
this.getAlbumList()
this.getActiveList()
this.getName()
})
uni.$on('update', () => {
this.getAlbumList()
})
},
computed: {
@@ -198,11 +243,45 @@ export default {
this.newsList = []
this.$nextTick(() => {
this.getActiveList()
this.getAlbumList()
this.getPublicList()
uni.setStorageSync('areaId', this.areaId)
uni.setStorageSync('areaName', this.areaName)
})
},
getAlbumList() {
this.$instance.post(`/app/appvillagepicturealbum/queryAlbumMenu?areaId=${this.areaId}`).then(res => {
if (res.code == 0) {
this.albumList = res.data.map(v => {
return {
...v,
coverImg: `${this.$cdn}/dvcp/album/album${v.type}.png`
}
})
}
})
},
getActiveList() {
this.$instance.post(`/app/appvillageactivityinfo/listUp`, null, {
params: {
current: 1,
size: 6,
areaId: this.areaId
}
}).then(res => {
if (res.code == 0) {
this.activityList = res.data.records.map(v => {
return {
...v,
url: v.url ? JSON.parse(v.url)[0].url : ''
}
})
}
})
}
},
onShareAppMessage() {
@@ -507,6 +586,67 @@ export default {
}
}
.album-list {
box-sizing: border-box;
padding: 0 32px 32px;
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 16px;
.album {
position: relative;
width: 218px;
height: 240px;
background: #FFFFFF;
box-shadow: 0 0 8px 0 rgba(0, 0, 0, 0.02);
border-radius: 16px;
overflow: hidden;
image {
position: absolute;
left: 0;
top: 0;
z-index: 1;
width: 100%;
height: 100%;
}
.total {
display: flex;
position: absolute;
align-items: center;
justify-content: center;
right: 8px;
top: 8px;
z-index: 2;
width: 74px;
height: 40px;
background: rgba(0, 0, 0, .6);
border-radius: 8px;
font-size: 22px;
font-weight: 400;
color: #FFFFFF;
}
.desc {
position: absolute;
bottom: 16px;
left: 0;
z-index: 2;
width: 100%;
height: 40px;
line-height: 40px;
padding: 0 12px;
font-size: 32px;
text-align: center;
color: #FFFFFF;
font-weight: 600;
box-sizing: border-box;
}
}
}
::v-deep .AiArea {
padding-top: 64px;
height: 88px;

View File

@@ -0,0 +1,385 @@
<template>
<div class="photo" v-if="pageShow">
<div class="header" :class="[isFixed ? 'header-active' : '']">
<div class="status-bar" :style="{height: statusBarHeight + 'px'}"></div>
<div class="nav-bar">
<image src="/static/img/left.png" @click="back"/>
<h2>邻里相册</h2>
</div>
</div>
<div class="back-wrapper" @click="back" v-show="!isFixed" :style="{marginTop : statusBarHeight + 'px'}">
<image src="/static/img/left.png"/>
</div>
<div class="photo-header">
<image :src="coverImg" mode="aspectFill"/>
<h2>{{ name }}</h2>
</div>
<div class="photo-info">
<div class="photo-info__item">
<h2>{{ info.total }}</h2>
<span>照片</span>
</div>
<div class="photo-info__item">
<h2>{{ info.thisMonth }}</h2>
<span>本月</span>
</div>
<div class="photo-info__item">
<h2>{{ info.lastMonth }}</h2>
<span>上月</span>
</div>
<div class="photo-info__item">
<h2>{{ info.thisYear }}</h2>
<span>今年</span>
</div>
</div>
<div class="photo-list">
<div class="photo-group" v-for="(group, index) in list" :key="index">
<h2>{{ group.name }}</h2>
<div class="photo-wrapper">
<div class="photo-item" v-for="(item, i) in group.list" :key="i">
<image :src="item.url" @click="preview(item.url)" mode="aspectFill"/>
<div class="photo-item__text">
<span>{{ item.createUserName }} 上传</span>
</div>
</div>
</div>
</div>
<AiEmpty v-if="!list.length" description="暂无照片"></AiEmpty>
</div>
<div class="btn-wrapper">
<div class="btn" @click="upload" hover-class="text-hover">上传图片</div>
</div>
<AiLogin ref="login"/>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
name: "AppPhotoAlbum",
appName: "邻里相册",
customNavigation: true,
data() {
return {
isFixed: false,
statusBarHeight: 20,
list: [],
type: '',
info: {},
name: '',
coverImg: '',
imgList: [],
hideStatus: false,
pageShow: false
}
},
computed: {
...mapState(['user', 'token'])
},
onLoad(query) {
this.type = query.type
this.name = query.name
this.coverImg = query.url
this.statusBarHeight = uni.getSystemInfoSync().statusBarHeight
this.$loading()
this.getList(query.type)
this.getTotalInfo(query.type)
},
onUnload() {
// uni.$off('update')
},
methods: {
back() {
uni.navigateBack({
delta: 1
})
},
preview(url) {
let imgs = []
this.list.forEach(item => {
imgs = [...imgs, ...item.list.map(v => v.url)]
})
uni.previewImage({
urls: imgs,
current: url
})
},
upload() {
if (!this.token) {
this.$refs.login.show()
return false
}
this.imgList = []
this.hideStatus = false
uni.chooseImage({
count: this.limit,
sizeType: ['compressed'],
sourceType: ['album', 'camera'],
success: (res) => {
if (res.tempFilePaths.length > 9) {
this.$toast(`图片不能超过9张`)
return false
}
this.$loading('上传中')
res.tempFilePaths.forEach((item, index) => {
if (index === res.tempFilePaths.length - 1) {
this.hideStatus = true
}
this.$nextTick(() => {
this.uploadFile(item, res.tempFilePaths.length)
})
})
},
})
},
uploadFile(img, total) {
uni.uploadFile({
url: this.$instance.config.baseURL + '/admin/file/add',
filePath: img,
name: 'file',
header: {
'Content-Type': 'multipart/form-data',
Authorization: uni.getStorageSync('token'),
},
success: (res) => {
const data = JSON.parse(res.data)
if (data.code === 0) {
this.imgList.push(data.data[0].split(';')[0])
} else {
this.$toast(data.msg)
}
},
complete: () => {
this.$nextTick(() => {
if (this.imgList.length === total && this.hideStatus) {
this.$instance.post(`/app/appvillagepicturealbum/addPictures`, {
areaName: uni.getStorageSync('areaName'),
areaId: uni.getStorageSync('areaId'),
type: this.type,
urlList: this.imgList
}).then(res => {
if (res.code == 0) {
this.getList(this.type)
this.getTotalInfo(this.type)
uni.$emit('update')
}
this.$hideLoading()
this.hideStatus = false
})
}
})
}
})
},
getTotalInfo(type) {
this.$instance.post(`/app/appvillagepicturealbum/statistic?areaId=${uni.getStorageSync('areaId')}&type=${type}`).then(res => {
if (res.code === 0) {
this.info = res.data
}
})
},
getList(type) {
this.$instance.post(`/app/appvillagepicturealbum/queryAlbum?areaId=${uni.getStorageSync('areaId')}&type=${type}`).then(res => {
if (res.code === 0) {
this.list = Object.keys(res.data).map(v => {
return {
name: v,
list: res.data[v]
}
})
this.$nextTick(() => {
this.pageShow = true
})
}
this.$hideLoading()
})
}
},
onPageScroll(params) {
this.isFixed = params.scrollTop > 60;
}
}
</script>
<style lang="scss" socped>
.photo {
width: 100vw;
overflow-x: hidden;
padding-bottom: 130px;
* {
box-sizing: border-box;
}
.back-wrapper {
position: fixed;
z-index: 11;
left: 20px;
top: 24px;
width: 40px;
height: 40px;
image {
width: 40px;
height: 40px;
}
}
.header {
position: fixed;
left: 0;
top: 0;
z-index: 0;
width: 100%;
opacity: 0;
transition: all 0.2s ease;
&.header-active {
z-index: 1111;
opacity: 1;
background: linear-gradient(180deg, #4670F5 0%, #4772F5 100%);
}
.nav-bar {
position: relative;
height: 88px;
line-height: 88px;
color: #fff;
font-size: 32px;
text-align: center;
image {
position: absolute;
top: 0;
left: 0;
z-index: 1;
width: 40px;
height: 40px;
padding: 24px 20px 0 20px;
box-sizing: content-box;
}
}
}
.photo-header {
position: relative;
height: 400px;
image {
width: 100%;
height: 400px;
filter: blur(2px);
}
h2 {
display: flex;
position: absolute;
align-items: center;
justify-content: center;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
color: #fff;
background: rgba(0, 0, 0, 0.1);
font-size: 56px;
}
}
.photo-info {
display: flex;
align-items: center;
height: 168px;
background: #FFFFFF;
box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.02);
& > div {
flex: 1;
text-align: center;
h2 {
margin-bottom: 10px;
font-weight: 600;
font-size: 38px;
color: #333333;
}
span {
color: #999999;
font-size: 26px;
}
}
}
.photo-list {
margin-top: 32px;
padding: 0 32px;
h2 {
margin-bottom: 32px;
color: #333333;
font-size: 38px;
}
.photo-wrapper {
display: flex;
flex-wrap: wrap;
.photo-item {
position: relative;
width: 328px;
height: 328px;
margin-right: 30px;
margin-bottom: 32px;
border-radius: 12px;
overflow: hidden;
&:nth-of-type(2n) {
margin-right: 0;
}
.photo-item__text {
position: absolute;
bottom: 0;
left: 0;
z-index: 1;
width: 100%;
height: 80px;
line-height: 80px;
padding: 0 16px;
color: #FFFFFF;
font-size: 26px;
background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.5) 100%);
}
image {
width: 328px;
height: 328px;
}
}
}
}
}
</style>

View File

@@ -0,0 +1,353 @@
<template>
<div class="page">
<div class="header-bg">
<div class="header-info">
<div class="wrap" @click="handleLogin()">
<div class="user-img-div">
<img :src="user.avatarUrl" alt="" class="user-img" v-if="user.id && user.avatarUrl"/>
<open-data type="userAvatarUrl" lang="zh_CN" class="user-img" v-else/>
</div>
<div class="user-info">
<div class="option">
<template v-if="!user.id">
<p>登录</p>
<p>点击进行登录</p>
</template>
<template v-else>
<p v-if="isApprove">{{ user.realName }}</p>
<p v-else>{{ user.nickName }}</p>
<p>{{ user.areaName || "" }}</p>
</template>
</div>
<p class="info" v-if="user.id" @click.stop="$linkTo('./userInfo')">个人信息</p>
</div>
</div>
</div>
</div>
<div class="approve">
<img class="icon" src="https://cdn.cunwuyun.cn/wxmp/mine/approve.png" alt="">
<div class="flex">
<span class="cert" v-if="isApprove" v-text="approveLabel" @click="$linkTo('/mods/AppAuth/AppAuth')"/>
<u-icon v-else name="arrow-right" color="#E7F2FF" size="28"
:label="approveLabel" label-color="#E7F2FF" label-pos="left" @click="approve"/>
</div>
</div>
<div class="list-wrap">
<div class="card" v-for="(group,index) in listGroup" :key="index">
<div class="item" v-for="(item) in group" hover-class="bg-hover" :key="item.label"
@click="linkTo(item.path, item.type)">
<div class="block">
<img class="icon" :src="item.icon" alt="">
</div>
<span class="desc" v-if="!item.share">{{ item.label }}</span>
<button open-type="share" v-else>
<span>{{ item.label }}</span>
</button>
</div>
</div>
</div>
<AiLogin ref="login" @success="getAuth()"/>
</div>
</template>
<script>
import {mapActions, mapState} from "vuex";
export default {
name: "AppMine",
appName: "我的",
customNavigation: true,
computed: {
...mapState(['user', 'token']),
isApprove() {
return this.user?.status == 2;
},
approveLabel() {
return this.user?.status == 2 ? "已认证" :
this.user?.status == 1 ? "审核中" :
this.user?.status == -1 ? "审核驳回" : "前往认证"
},
listGroup() {
return [
[
{
icon: "https://cdn.cunwuyun.cn/wxmp/mine/wodejiating.png",
label: "我的家庭",
path: "./myFamily",
type: 'idNumber'
},
{
icon: "https://cdn.cunwuyun.cn/wxmp/mine/wodejiaxiang.png",
label: "我的社区",
path: "./AppHometown",
type: 'token'
}
],
[
{
icon: "https://cdn.cunwuyun.cn/wxmp/mine/wodejifen.png",
label: "我的积分",
path: "/mods/AppCreditPoints/AppCreditPoints?type=detail",
type: 'idNumber'
},
{
icon: "https://cdn.cunwuyun.cn/wxmp/mine/chaoshidingdan.png",
label: "超市订单",
path: "/mods/AppOrderList/AppOrderList",
type: 'idNumber'
},
{
icon: "https://cdn.cunwuyun.cn/wxmp/mine/banshijindu.png",
label: "办事进度",
path: "/mods/AppProgress/AppProgress",
type: 'idNumber'
}
],
]
}
},
methods: {
...mapActions(['getUserInfo']),
approve() {
if (!this.token) {
this.$refs.login.show();
} else if (!this.isApprove) {
if (this.user.status == 0) {
this.$linkTo('/mods/AppAuth/AppAuth');
} else {
this.$linkTo('/mods/AppAuth/authSuccess')
}
}
},
linkTo(url, type) {
if (type) {
if (this.token) {
if (type == 'token') {
this.$linkTo(url)
}
if (type == 'idNumber') {
if (this.user.status == 0) {
if (!this.user.phone) {
this.$linkTo('/pages/phone/bingPhoneNumber?from=auth')
} else {
this.$linkTo('/mods/AppAuth/AppAuth')
}
} else {
this.$linkTo(url)
}
}
} else {
this.$refs.login.show()
}
} else {
this.$linkTo(url)
}
},
handleLogin() {
if (!this.token) {
this.$refs.login.show();
}
},
getAuth() {
this.$nextTick(() => {
this.token && this.getUserInfo()
})
}
},
onShow() {
this.getAuth();
},
onShareAppMessage() {
return {
title: '欢迎使用数字乡村治理服务一体化平台~',
path: `/pages/AppModules/AppModules`
}
},
}
</script>
<style scoped lang="scss">
@import "~dvcp-wui/common";
.page {
width: 100%;
min-height: 100%;
background-color: #F3F6F9;
position: relative;
.header-bg {
width: 100%;
height: 512px;
position: relative;
.header-info {
width: 100%;
height: 100%;
background: url("https://cdn.cunwuyun.cn/wxmp/sanjianxi/mineBg.png") no-repeat no-repeat;
background-size: 100% 100%;
box-sizing: border-box;
padding: 240px 0 0 48px;
.wrap {
width: 100%;
height: 96px;
display: flex;
align-items: center;
.user-img-div {
display: inline-block;
width: 96px;
height: 96px;
border-radius: 50%;
overflow: hidden;
border: 4px solid #FFFFFF;
flex-shrink: 0;
.user-img {
display: inline-block;
width: 96px;
height: 96px;
border-radius: 58px;
}
}
.user-info {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
margin-left: 26px;
box-sizing: border-box;
padding-right: 32px;
.option {
& > p:first-child {
font-size: 34px;
font-weight: 600;
color: #333333;
line-height: 54px;
}
& > p:last-child {
font-size: 26px;
font-weight: 400;
color: #7088A0;
line-height: 36px;
}
}
.info {
width: 136px;
height: 48px;
border-radius: 8px;
border: 2px solid #7088A0;
font-size: 26px;
font-weight: 400;
color: #7088A0;
display: flex;
align-items: center;
justify-content: center;
}
}
}
}
}
.approve {
position: absolute;
left: 50%;
top: 400px;
transform: translateX(-50%);
width: 686px;
height: 112px;
background: linear-gradient(90deg, #8FB4FF 0%, #4181FF 100%);
border-radius: 16px;
display: flex;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
padding: 0 20px;
.icon {
width: 296px;
height: 52px;
}
.cert {
font-family: PingFangSC-Regular, PingFang SC;
font-size: 28px;
color: #E7F2FF;
margin-right: 4px;
}
}
.list-wrap {
box-sizing: border-box;
padding: 32px;
.card {
width: 100%;
min-height: 100px;
border-radius: 16px;
background-color: #fff;
margin-bottom: 32px;
.item {
height: 100px;
display: flex;
align-items: center;
&:last-child {
.desc {
border-bottom: none !important;
}
}
.block {
width: 80px;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
.icon {
width: 44px;
height: 44px;
}
}
.desc, & > button {
height: 100%;
flex: 1;
font-size: 30px;
font-weight: 400;
color: #666666;
display: flex;
align-items: center;
border-bottom: 1px solid #EEEEEE;
& > span {
width: 100%;
height: 100%;
text-align: left;
display: flex;
align-items: center;
}
&::after {
border: none;
}
}
.no-border {
border-bottom: none;
}
}
&:first-of-type {
margin-bottom: 32px;
}
}
}
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 993 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1,180 @@
<template>
<div class="page">
<div class="credit-points">
<div class="bg-blue"></div>
<div class="header-content">
<div class="title">家庭地址</div>
<div class="address">
<img src="https://cdn.cunwuyun.cn/img/location-blue.svg" alt="">
<p>{{ info.resident.currentAreaName || '' }}{{ info.resident.currentAddress || '' }}</p>
</div>
</div>
<div class="list-content">
<div class="title">家庭成员</div>
<div class="item" v-for="(item, index) in info.family" :key="index">
<img src="https://cdn.cunwuyun.cn/dvcp/myFamily/1.png" alt="" class="banner-top" v-if="item.sex == 1">
<img src="https://cdn.cunwuyun.cn/dvcp/myFamily/2.png" alt="" class="banner-top" v-else>
<div class="user-img">
<img v-if="item.photo" :src="item.photo" alt=""/>
<img v-else src="https://cdn.cunwuyun.cn/dvcp/myFamily/tx.png" alt=""/>
</div>
<div class="user-info">
<p>{{ item.name }}</p>
<div v-if="item.householdName == 1" class="color-5AAD6A">户主</div>
<div v-else>{{ $dict.getLabel('householdRelation', item.householdRelation) }}</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
appName: "我的家庭",
computed: {
...mapState(['user', 'token'])
},
data() {
return {
info: {}
}
},
onLoad() {
this.$dict.load('householdRelation').then(() => {
this.$nextTick(() => {
this.getUser()
})
})
},
methods: {
getUser() {
this.$instance.post(`/app/appresident/detailForWx?id=${this.user.residentId}`).then(res => {
if (res.code === 0) {
this.info = res.data
}
})
}
}
}
</script>
<style scoped lang="scss">
@import "~dvcp-wui/common";
.page {
width: 100%;
background-color: #f3f6f9;
.credit-points {
.bg-blue {
width: 100%;
height: 112px;
background-color: #197DF0;
}
.header-content {
width: 690px;
background: #FFF;
border-radius: 16px;
margin: -80px 0 32px 30px;
padding: 0 30px 80px;
box-sizing: border-box;
box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.02);
.address {
font-size: 32px;
color: #666;
overflow: hidden;
img {
width: 34px;
height: 38px;
margin-right: 14px;
vertical-align: middle;
}
p {
line-height: 44px;
width: 580px;
word-break: break-all;
float: right;
}
}
}
.title {
font-size: 32px;
font-weight: 500;
color: #333;
line-height: 120px;
}
.list-content {
width: 690px;
background: #FFF;
border-radius: 16px;
padding: 0 30px 110px;
box-sizing: border-box;
margin-left: 30px;
box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.02);
.item {
width: 630px;
height: 192px;
background: #FFF;
box-shadow: 0 4px 10px 0 rgba(0, 0, 0, 0.08);
border-radius: 16px;
padding-left: 30px;
box-sizing: border-box;
margin-bottom: 32px;
overflow: hidden;
.banner-top {
width: 100%;
height: 72px;
}
.user-img {
width: 104px;
height: 104px;
margin: -16px 34px 0 0;
border-radius: 50%;
float: left;
img {
width: 100%;
height: 100%;
border-radius: 50%;
}
}
.user-info {
margin-top: -16px;
width: calc(100% - 138px);
float: right;
p {
font-size: 32px;
font-weight: 600;
color: #333;
line-height: 44px;
margin-bottom: 8px;
}
div {
font-size: 26px;
font-weight: 400;
color: #666;
line-height: 36px;
}
.color-5AAD6A {
color: #5AAD6A;
}
}
}
}
}
}
</style>

View File

@@ -0,0 +1,123 @@
<template>
<div class="page">
<template v-if="detail">
<header>{{ detail.areaName }}</header>
<div class="address">{{ detail.address }}</div>
<div class="desc">
<u-parse :html="detail.content"></u-parse>
</div>
</template>
<AiEmpty v-else description="暂无社区简介"/>
<div class="btn" @click="cancel" v-if="user.homeArea">
<div>解除入驻</div>
</div>
</div>
</template>
<script>
import {mapState} from "vuex";
export default {
name: "myHometown",
appName: "我的社区",
data() {
return {
detail: null,
}
},
onLoad() {
this.getDetail();
},
computed: {
...mapState(["user"])
},
methods: {
getDetail() {
if (!this.user.homeArea) return
this.$instance.post("/app/appcountrysidetourism/queryDetailByAreaIdForWX", null, {
params: {areaId: this.user.homeArea}
}).then(res => {
if (res?.data) {
this.detail = res.data;
}
})
},
cancel() {
this.$instance.post("/app/appwechatuser/unbindHome", {id: this.user.id}).then(res => {
if (res.code == 0) {
this.$u.toast('解除入驻成功')
setTimeout(() => {
uni.navigateBack()
}, 600)
}
})
}
},
}
</script>
<style lang="scss" scoped>
.page {
background-color: #fff;
box-sizing: border-box;
padding: 32px 0;
position: relative;
width: 100vw;
overflow-x: hidden;
min-height: 100vh;
header {
font-size: 48px;
font-weight: 600;
color: #333333;
line-height: 66px;
padding-left: 32px;
}
.address {
font-size: 30px;
font-weight: 400;
color: #999999;
line-height: 42px;
margin-top: 16px;
padding-left: 32px;
}
.desc {
font-size: 36px;
font-weight: 400;
color: #333333;
line-height: 64px;
margin-top: 64px;
padding: 32px 0 120px 32px;
}
.btn {
width: 100%;
background-color: #fff;
position: fixed;
left: 50%;
bottom: 0;
padding-bottom: 16px;
z-index: 999;
transform: translateX(-50%);
div {
width: 686px;
height: 88px;
background: #FFFFFF;
border-radius: 16px;
border: 1px solid #FF4466;
font-size: 34px;
font-weight: 600;
color: #FF4466;
display: flex;
align-items: center;
justify-content: center;
margin-left: 32px;
}
}
}
</style>

View File

@@ -0,0 +1,222 @@
<template>
<div class="page">
<div class="info-list">
<div class="item-content mar-b8">
<div class="item solid">
<p class="mar-t22">头像</p>
<button class="user-img-div" open-type="chooseAvatar" @chooseavatar="handleWeixinSync">
<img :src="user.avatarUrl" class="user-img">
</button>
</div>
<div class="item">
<p>用户昵称</p>
<div v-if="!editNickName" @click="editNickName=true">
<p class="name" v-text="nickName"/>
</div>
<input v-else type="nickname" class="editNickName" v-model="nickName" @blur="handleWeixinSync">
</div>
</div>
<div class="item-content mar-b8">
<div class="item">
<p>手机号</p>
<div>{{ user.phone || '' }}</div>
</div>
</div>
<div class="item-content" @click="onLogout">
<div class="item">
<p class="login-out">退出登录</p>
</div>
</div>
</div>
</div>
</template>
<script>
import {mapActions, mapState} from 'vuex'
export default {
name: "userInfo",
appName: "个人中心",
computed: {
...mapState(['user', 'token']),
nickName: {
set(v) {
},
get() {
const {nickName} = this.user
return nickName
}
}
},
onLoad() {
this.getUserInfo()
},
data() {
return {
editNickName: false
}
},
methods: {
...mapActions(['getUserInfo', 'autoLogin']),
upLoad(img) {
return new Promise((resolve, reject) => {
uni.uploadFile({
url: `${this.$instance.baseURL}/admin/file/add`,
filePath: img,
name: 'file',
header: {
'Content-Type': 'multipart/form-data',
Authorization: uni.getStorageSync('token')
},
success: uploadFileRes => {
resolve(uploadFileRes)
},
fail: err => {
reject(err)
}
})
})
},
onLogout() {
uni.showModal({
title: '提示',
content: "是否要退出登录",
success: res => {
if (res.confirm) {
this.$store.commit('logout')
this.$toast('退出成功');
setTimeout(() => {
uni.switchTab({
url: '/pages/AppMine/AppMine'
})
}, 500)
}
}
})
},
handleWeixinSync({detail}) {
const {value: nickName, avatarUrl} = detail
this.autoLogin({nickName, avatarUrl})
}
}
}
</script>
<style scoped lang="scss">
@import "~dvcp-wui/common";
.page {
width: 100%;
background-color: #F5F5F5;
.info-list {
margin: 0 0 16px 0;
.item-content {
padding: 0 32px;
background-color: #fff;
}
.item {
padding: 36px 0;
line-height: 40px;
width: 100%;
box-sizing: content-box;
display: flex;
justify-content: space-between;
p {
color: #333;
font-weight: 400;
}
div {
color: #666;
font-size: 28px;
}
.user-img-div {
width: 104px;
height: 104px;
border-radius: 50%;
overflow: hidden;
}
.user-img {
width: 104px;
height: 104px;
vertical-align: middle;
border-radius: 50%;
}
.right-icon {
width: 40px;
height: 40px;
vertical-align: middle;
}
.mar-t22 {
margin-top: 44px;
}
}
.login-out {
width: 100%;
font-size: 30px;
text-align: center;
}
}
.self-knowledge-show {
position: fixed;
left: 0;
top: 0;
z-index: 100;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.3);
}
.toast-bg {
position: fixed;
z-index: 101;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.toast {
background-color: #fff;
width: 686px;
height: 316px;
font-size: 36px;
}
.toast-msg {
text-align: center;
line-height: 50px;
color: #333;
font-weight: 500;
padding: 84px 0 80px 0;
}
.toast-btn {
display: inline-block;
width: 120px;
text-align: center;
line-height: 50px;
}
.cancel {
margin-left: 394px;
margin-right: 40px;
}
.confirm {
color: #197DF0;
}
.editNickName {
text-align: right;
font-size: 28px;
}
}
</style>

View File

@@ -0,0 +1,222 @@
<template>
<div class="wrapper" v-if="pageShow">
<div class="area">
<AiAreaPicker v-model="areaId" :name.sync="areaName" :areaId="$areaId" @input="handleSelect">
<div class="ai-area__wrapper">
<span class="label" v-if="areaName">{{ areaName }}</span>
<span v-else>请选择</span>
<image src="/static/img/area-bottom.png"/>
</div>
</AiAreaPicker>
</div>
<tempate v-if="list.length">
<header>
<span>辅警列表</span>
<div class="total">
<em>{{ list.length }}</em>名辅警
</div>
</header>
<div class="list-wrap">
<div class="card" v-for="(item,index) in list" :key="index">
<img
:src="item.picture || `https://cdn.cunwuyun.cn/AppPolice/police.png`"
@click="preview(index)"
alt="">
<div class="right">
<span class="user-name">{{ item.name }}</span>
<span class="state" v-text="appName"/>
<span class="phone" @click="call(item)">{{ item.phone }}</span>
<span>{{ item.areaName }}</span>
</div>
</div>
</div>
</tempate>
<AiEmpty v-else></AiEmpty>
</div>
</template>
<script>
export default {
name: 'AppPolice',
appName: "社区辅警",
data() {
return {
current: 1,
areaId: "",
list: [],
areaName: '',
$areaId: '',
pageShow: false
}
},
computed: {
appName: v => v.$route.query?.appName || v.$options.appName
},
onLoad() {
this.$loading()
this.areaId = this.$areaId
this.areaName = this.$areaName
this.$nextTick(() => {
this.getList()
})
},
onShow() {
const {appName: title} = this
uni.setNavigationBarTitle({title})
},
methods: {
call({phone: phoneNumber}) {
uni.makePhoneCall({phoneNumber})
},
preview(index) {
if (this.list[index]["picture"]?.startsWith("http")) {
uni.previewImage({
current: this.list[index]["picture"],
urls: [this.list[index]["picture"]]
})
}
},
handleSelect() {
this.$loading()
this.current = 1
this.$nextTick(() => {
this.getList()
})
},
getList() {
this.$instance.post(`/app/appvillageauxiliarypolice/list`, null, {
params: {
isPublic: 1,
areaId: this.areaId,
current: this.current
}
}).then(res => {
if (res?.data) {
this.list = this.current > 1 ? [...this.list, ...res.data.records] : res.data.records;
}
this.pageShow = true
this.$hideLoading()
})
}
},
onReachBottom() {
this.current++;
this.getList();
}
}
</script>
<style lang="scss" scoped>
.wrapper {
padding-top: 124px;
padding-bottom: 20px;
}
.area {
display: flex;
align-items: center;
position: fixed;
left: 0;
top: 0;
z-index: 1;
height: 124px;
width: 100%;
box-sizing: border-box;
background: #4181FF;
padding-left: 32px;
.ai-area__wrapper {
display: flex;
align-items: center;
span {
margin-right: 16px;
color: #FFFFFF;
font-size: 44px;
}
image {
width: 16px;
height: 8px;
}
}
}
header {
display: flex;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
padding: 32px;
& > span {
font-size: 38px;
font-weight: 600;
color: #333333;
}
.total {
margin-left: auto;
font-size: 28px;
font-weight: 400;
color: #666666;
display: flex;
align-items: center;
& > em {
color: #4181FF;
}
}
}
.list-wrap {
box-sizing: border-box;
padding: 0 32px;
.card {
box-sizing: border-box;
padding: 32px;
background: #FFFFFF;
box-shadow: 0 0 8px 0 rgba(0, 0, 0, 0.02);
border-radius: 16px;
display: flex;
align-items: center;
margin-bottom: 24px;
& > img {
width: 200px;
height: 200px;
border-radius: 8px;
margin-right: 32px;
flex-shrink: 0;
}
.right {
height: 200px;
flex: 1;
display: flex;
flex-direction: column;
font-size: 26px;
font-weight: 400;
color: #666666;
.user-name {
font-size: 32px;
font-weight: 600;
color: #333333;
margin-bottom: 16px;
}
.state {
color: #666666;
}
.phone {
color: #4181FF;
margin: 8px 0;
}
}
}
}
</style>