居民管理迁移

This commit is contained in:
liuye
2022-02-07 09:54:39 +08:00
parent 7518fd15f4
commit 7b4d887bcf
11 changed files with 658 additions and 1904 deletions

View File

@@ -0,0 +1,230 @@
<template>
<div class="AppResidentDocument">
<div class="areatop">
<!-- <div>区域选择</div>
<AiAreaPicker v-model="areaId" :areaId="user.areaId" @select="seachObj"></AiAreaPicker>
<u-icon name="photo"></u-icon> -->
<!-- @select="areaSelect" -->
<u-form label-width="auto">
<u-form-item label="区域选择" right-icon="arrow-right" class="areaIds">
<AiAreaPicker v-model="areaId" :areaId="user.areaId" @select="seachObj" :name.sync="areaName"></AiAreaPicker>
</u-form-item>
</u-form>
</div>
<div class="line"></div>
<u-tabs :list="tabList" :is-scroll="false" :current="currentTabs" height="96" @change="change"></u-tabs>
<div class="seachObjs">
<u-search v-model="keyword" :clearabled="true" placeholder="姓名/联系方式/身份证后6位" :show-action="false" bg-color="#F5F5F5" search-icon-color="#E2E8F1" color="#666" height="58" @search="handerSearch" @clear="handerClear"></u-search>
</div>
<div class="dataes" v-if="datas.length > 0">
<div class="datass" v-for="(item, iindex) in datas" :key="iindex" @click="toDetailCard(item)">
<div class="left">
<img :src="item.photo" alt="" v-if="item.photo" />
<img src="./components/img/4.png" alt="" v-else />
</div>
<div class="right">
<div class="rightTop">{{ item.name }}</div>
<div class="rightBottom">
<span>{{ item.idNumber.replace(/^(\w{6})\w{8}(.*)$/, '$1********$2') }}</span>
<span>{{ item.phone }}</span>
</div>
</div>
</div>
</div>
<AiEmpty class="emptyWrap" v-else></AiEmpty>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
name: 'AppResidentDocument',
appName: '居民管理',
components: {},
props: {},
data() {
return {
keyword: '',
datas: [],
current: 1,
size: 10,
tabList: [
{
name: '本地居民',
},
{
name: '流动人员',
},
],
currentTabs: 0,
areaId: '',
areaName: '',
}
},
computed: {
...mapState(['user']),
},
watch: {},
onLoad() {
this.areaId = this.user.areaId
this.areaName = this.user.areaName
this.getList()
},
onShow() {
document.title = '居民管理'
},
methods: {
getList() {
this.$http
.post('/app/appresident/list', null, {
params: {
size: this.size,
current: this.current,
con: this.keyword,
areaId: this.areaId,
residentType: this.currentTabs == 0 ? '0' : '1',
},
})
.then((res) => {
if (res.code == 0) {
this.datas = this.current > 1 ? [...this.datas, ...res.data.records] : res.data.records
this.pages = res.data.pages
}
})
},
change(index) {
this.currentTabs = index
this.current = 1
this.datas = []
this.getList()
},
toDetailCard(item) {
uni.navigateTo({ url: `./DetailCard?id=${item.id}` })
},
seachObj(e) {
this.areaId = e
this.current = 1
this.getList()
},
handerSearch(e) {
this.keyword = e
this.current = 1
this.getList()
},
handerClear() {
this.keyword = ''
this.current = 1
this.getList()
},
},
onReachBottom() {
this.current = this.current + 1
this.getList()
},
}
</script>
<style scoped lang="scss">
uni-page-body {
height: 100%;
}
.AppResidentDocument {
height: 100%;
.areatop {
display: flex;
justify-content: space-between;
align-items: center;
}
.line {
height: 16px;
background: #f5f5f5;
}
.seachObjs {
border-bottom: 2px solid #f5f5f5;
border-top: 2px solid #f5f5f5;
padding: 20px 32px;
background: #fff;
}
::v-deep .u-form {
width: 100%;
.areaIds {
.u-form-item__body {
.u-form-item--right {
.u-form-item--right__content {
display: flex;
align-items: center;
.u-form-item--right__content__slot {
.AiAreaPicker {
width: 100%;
display: flex;
justify-content: flex-end;
.areaSelector {
.location {
opacity: 0;
}
}
}
}
.u-form-item--right__content__icon {
margin-bottom: 8px;
}
}
}
}
}
}
.dataes {
background: #fff;
.datass {
display: flex;
padding: 24px 32px;
.left {
img {
width: 80px;
height: 80px;
border-radius: 50%;
}
}
.right {
display: flex;
flex-direction: column;
margin-left: 32px;
width: 100%;
.rightTop {
font-size: 32px;
font-weight: 500;
color: #333333;
}
.rightBottom {
display: flex;
justify-content: space-between;
margin-top: 8px;
}
}
}
}
.emptyWrap {
background: #f5f5f5;
margin: 0;
}
}
</style>

View File

@@ -0,0 +1,209 @@
<template>
<div class="DetailCard">
<div class="top"></div>
<div class="middle">
<div class="hint">家庭地址</div>
<div class="areaHint">
<u-icon name="map-fill" color="#73ABFF"></u-icon>
<span>{{ resident.currentAreaName }}</span>
<span v-if="resident.currentAddress">{{ resident.currentAddress }}</span>
</div>
</div>
<div class="bottom">
<div class="hints">家庭成员 {{ data.family && data.family.length }}</div>
<div v-if="data.family && data.family.length > 0">
<div class="card" v-for="(item, i) in data.family" :key="i" @click="toDetailPeople(item)">
<div class="photos">
<img :src="item.photo" alt="" v-if="item.photo" />
<img src="./components/img/44.png" alt="" v-else />
</div>
<div class="right">
<div class="rightTop">
<div class="rightTop-lefts">
<span class="names">{{ item.name }}</span>
<span class="fileStatuss" v-if="item.fileStatus == 1"> {{ $dict.getLabel('fileStatus', item.fileStatus) }}</span>
<span class="householdNames" v-if="item.householdName == 1">户主</span>
<span class="householdNames" v-else>
{{ $dict.getLabel('householdRelation', item.householdRelation) }}
</span>
</div>
<div class="rightTop-rights">
<u-section :show-line="false" sub-title="详情"></u-section>
</div>
</div>
<div class="rightBottom">
<span>身份证号</span>
<span>{{ item.idNumber.replace(/^(\w{6})\w{8}(.*)$/, '$1******$2') }}</span>
</div>
</div>
</div>
</div>
<AiEmpty v-else></AiEmpty>
</div>
</div>
</template>
<script>
export default {
name: 'DetailCard',
components: {},
props: {},
data() {
return {
id: '',
data: [],
resident: {},
}
},
computed: {},
watch: {},
onLoad(o) {
document.title = '居民信息'
this.id = o.id
this.$dict.load('householdRelation', 'fileStatus').then(() => {
this.getDetail()
})
},
onShow() {},
methods: {
getDetail() {
this.$http.post(`/app/appresident/detail?id=${this.id}`).then((res) => {
if (res.code == 0) {
this.data = res.data
this.$forceUpdate()
this.$nextTick(() => {
this.resident = res.data.resident
this.$forceUpdate()
})
}
})
},
toDetailPeople(item) {
uni.navigateTo({ url: `./DetailPeople?id=${item.id}` })
},
},
}
</script>
<style scoped lang="scss">
.DetailCard {
height: 100%;
.top {
height: 112px;
background: #3975c6;
}
.middle {
margin: -80px 32px 0 32px;
padding: 38px 30px 78px 28px;
background: #ffffff;
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.02);
border-radius: 16px;
z-index: 999;
.hint {
font-size: 32px;
font-weight: 500;
color: #333333;
}
.areaHint {
margin-top: 38px;
span {
margin-left: 14px;
}
}
}
.bottom {
margin: 32px 30px 48px 30px;
background: #fff;
padding: 38px 30px 30px 30px;
.hints {
margin-bottom: 38px;
}
.card {
display: flex;
box-shadow: 0px 4px 10px 0px rgba(0, 0, 0, 0.08);
border-radius: 16px;
padding: 48px 32px;
margin-bottom: 32px;
.photos {
img {
width: 96px;
height: 96px;
border-radius: 50%;
}
}
.right {
display: flex;
flex-direction: column;
margin-left: 40px;
width: 100%;
.rightTop {
display: flex;
justify-content: space-between;
.rightTop-lefts {
.names {
font-size: 32px;
font-weight: 600;
}
.householdNames {
margin-left: 30px;
font-size: 26px;
font-weight: 500;
color: #5aad6a;
}
.fileStatuss {
display: inline-block;
margin-left: 30px;
color: #ff4466;
background: #ffecef;
border-radius: 8px;
width: 88px;
height: 40px;
line-height: 40px;
text-align: center;
}
}
.rightTop-rights {
::v-deep .u-section {
.u-section__right-info {
color: #3975c6 !important;
.u-section__right-info__icon-arrow {
.u-icon {
.u-icon__icon {
color: #3975c6 !important;
}
}
}
}
}
}
}
.rightBottom {
margin-top: 20px;
}
}
}
.card:nth-child(2n-1) {
// background: royalblue;
background: url(http://respub.sinoecare.net/20211222/装饰-20211222162743.png) no-repeat;
background-size: 100% 100%;
}
.card:nth-child(2n) {
// background: pink;
background: url(http://respub.sinoecare.net/20211222/装饰2-20211222162934.png) no-repeat;
background-size: 100% 100%;
}
}
}
</style>

View File

@@ -0,0 +1,219 @@
<template>
<div class="DetailPeople">
<div class="top">
<div class="photos">
<img :src="data.resident.photo" alt="" v-if="data.resident && data.resident.photo" />
<img src="./components/img/44.png" alt="" v-else />
</div>
<div class="right">
<div class="rightTop">
<span class="names">{{ data.resident && data.resident.name }}</span>
<span class="householdNames" v-if="data.resident && data.resident.householdName == 1">户主</span>
<span class="householdNames" v-else>
{{ $dict.getLabel('householdRelation', data.resident && data.resident.householdRelation) }}
</span>
</div>
<div class="rightBottom" v-if="data.resident && data.resident.phone">{{ data.resident.phone }}</div>
</div>
</div>
<div class="line"></div>
<div class="middle">
<div class="hint">个人基本信息</div>
<div class="contents">
<div class="item">
<span>籍贯</span>
<span>{{ data.resident && data.resident.birthplaceAreaName }}</span>
</div>
<div class="item">
<span>身份证号</span>
<span>{{ data.resident && data.resident.idNumber.replace(/^(\w{6})\w{8}(.*)$/, '$1****$2') }}</span>
</div>
<div class="item">
<span>民族</span>
<span v-if="data.resident && data.resident.nation"> {{ $dict.getLabel('nation', data.resident.nation) }}</span>
</div>
<div class="item">
<span>文化程度</span>
<span v-if="data.resident && data.resident.education">{{ $dict.getLabel('education', data.resident.education) }}</span>
</div>
<div class="item">
<span>婚姻状况</span>
<span v-if="data.resident && data.resident.maritalStatus">{{ $dict.getLabel('maritalStatus', data.resident.maritalStatus) }}</span>
</div>
<div class="item">
<span>政治面貌</span>
<span v-if="data.resident && data.resident.politicsStatus">{{ $dict.getLabel('politicsStatus', data.resident.politicsStatus) }}</span>
</div>
<div class="item">
<span>兵役状况</span>
<span v-if="data.resident && data.resident.militaryStatus">{{ $dict.getLabel('militaryStatus', data.resident.militaryStatus) }}</span>
</div>
<div class="item">
<span>宗教信仰</span>
<span v-if="data.resident && data.resident.faithType">{{ $dict.getLabel('faithType', data.resident.faithType) }}</span>
</div>
<div class="item">
<span>职业</span>
<span v-if="data.resident && data.resident.job">{{ $dict.getLabel('job', data.resident.job) }}</span>
</div>
</div>
</div>
<div class="lines"></div>
<div class="bottom">
<div class="hint">联络信息</div>
<div class="contents">
<div class="item">
<span>联系方式</span>
<span class="phones" v-if="data.resident && data.resident.phone" @click="callPhone(data.resident.phone)">{{ data.resident.phone }}</span>
</div>
<div class="item">
<span>现住址</span>
<span v-if="data.resident && data.resident.currentAreaName">{{ data.resident.currentAreaName }}</span>
</div>
<div class="item">
<span>现住详细地址</span>
<span v-if="data.resident && data.resident.currentAddress">{{ data.resident.currentAddress }}</span>
</div>
<div class="item">
<span>户籍地址</span>
<span v-if="data.resident && data.resident.householdAreaName">{{ data.resident.householdAreaName }}</span>
</div>
<div class="item">
<span>户籍详细地址</span>
<span v-if="data.resident && data.resident.householdAddress">{{ data.resident.householdAddress }}</span>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'DetailPeople',
components: {},
props: {},
data() {
return {
id: '',
data: [],
}
},
computed: {},
watch: {},
onLoad(o) {
this.id = o.id
this.$dict.load('householdRelation', 'nation', 'education', 'maritalStatus', 'politicsStatus', 'militaryStatus', 'faithType', 'job').then(() => {
this.getDetail()
})
},
onShow() {
document.title = '家庭成员信息'
},
methods: {
getDetail() {
this.$http.post(`/app/appresident/detail?id=${this.id}`).then((res) => {
if (res.code == 0) {
this.data = res.data
// this.$nextTick(() => {
// this.currentAreaName = res.data.resident.currentAreaName
// })
}
})
},
callPhone(phone) {
uni.makePhoneCall({ phoneNumber: phone })
},
},
}
</script>
<style scoped lang="scss">
.DetailPeople {
height: 100%;
background: #fff;
.top {
display: flex;
padding: 48px 32px 32px 32px;
.photos {
img {
width: 112px;
height: 112px;
border-radius: 50%;
}
}
.right {
display: flex;
flex-direction: column;
width: 100%;
margin-left: 24px;
.rightTop {
display: flex;
justify-content: space-between;
.names {
font-size: 32px;
font-weight: 600;
}
.householdNames {
margin-left: 30px;
font-size: 26px;
font-weight: 500;
color: #5aad6a;
}
}
.rightBottom {
margin-top: 16px;
}
}
}
.line {
height: 8px;
background: #f5f5f5;
}
.middle,
.bottom {
padding: 0 32px;
.hint {
padding: 32px 0;
}
.contents {
.item {
display: flex;
justify-content: space-between;
padding: 14px 0;
.phones {
color: #3d94fb;
}
}
}
}
.lines {
height: 4px;
background: #f5f5f5;
}
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -1,825 +0,0 @@
<template>
<div class="AppResidentFile">
<div class="currentTabBar0" v-if="currentTabBar == 0">
<u-tabs :list="tabList" :is-scroll="false" :current="currentTabs" height="96" bg-color="#3975C6" inactive-color="#fff" active-color="#fff" @change="change"></u-tabs>
<div class="peopleGroup" v-if="currentTabs == 0">
<div class="topcard">
<div class="cards">
<div class="items">
<span class="items1">{{ groupSum }}</span>
<span>群聊总数</span>
</div>
<div class="items">
<span class="items2">{{ todayList1.total }}</span>
<span>群成员总数</span>
</div>
<div class="items">
<span class="items3">{{ todayList1.increase }}</span>
<span>今日入群</span>
</div>
<div class="items">
<span class="items4">{{ todayList1.decrease }}</span>
<span>今日退群</span>
</div>
</div>
</div>
<div class="echartes" id="echarts1">
<div class="echartss"></div>
</div>
</div>
<div class="people" v-if="currentTabs == 1">
<div class="topcard">
<div class="cards">
<div class="items">
<span class="items1">{{ todayList2.total }}</span>
<span>居民总数</span>
</div>
<div class="items">
<span class="items3">{{ todayList2.increase }}</span>
<span>今日新增</span>
</div>
<div class="items">
<span class="items4">{{ todayList2.decrease }}</span>
<span>今日流失</span>
</div>
</div>
</div>
<div class="echartes" id="echarts2">
<div class="echartss"></div>
</div>
</div>
</div>
<div class="currentTabBar1" v-if="currentTabBar == 1">
<AiTopFixed>
<u-search placeholder="请输入昵称、姓名" :show-action="false" search-icon-color="#ccc" v-model="search.name" @search=";(page1.current = 1), getList()" />
<AiCell>
<b slot="label" class="title"><i v-html="page1.total || 0" />个居民</b>
</AiCell>
</AiTopFixed>
<div class="mainPane">
<AiCell v-for="item in data" :key="item.id" @click.native="showResident(item)">
<template #label>
<AiImage :src="item.avatar" preview />
</template>
<div class="card wrap start" flex>
<b>{{ item.name }}</b>
<div flex class="tag" v-for="(tag, j) in item.tags" :key="j">{{ tag.tagName }}</div>
<div class="realName" shrink v-html="`真实姓名:${item.realName || '-'}`" />
</div>
</AiCell>
</div>
</div>
<div class="currentTabBar2" v-if="currentTabBar == 2">
<AiTopFixed>
<u-search placeholder="请输入群名、群主名" :show-action="false" search-icon-color="#ccc" v-model="search.name" @search=";(page2.current = 1), getList()" />
<AiCell>
<b slot="label" class="title"><i v-html="page2.total || 0" />个居民群</b>
</AiCell>
</AiTopFixed>
<div class="mainPane">
<AiCell v-for="(item, i) in list" :key="i" @click.native="toGroupList(item)">
<template #label>
<AiImage :src="item.avatar" preview />
</template>
<div class="card column start" flex>
<div flex class="groupName">
<b>{{ item.name || '群聊' }}</b>
<div class="personCount" v-if="item.personCount">({{ item.personCount }})</div>
</div>
<div class="owner" v-html="`群主:${item.ownerName}`" />
<div flex class="trends">
<div flex v-html="`今日入群:<em>${item.increase || 0}</em>`" />
<div flex v-html="`今日退群:<p>${item.decrease || 0}</p>`" />
</div>
</div>
</AiCell>
</div>
</div>
<!-- <u-tabbar v-model="currentTabBar" :list="lists" @change="changeTab" active-color="#3267F0" inactive-color="#C4CAD4" class="u-tabbar"></u-tabbar> -->
<div class="tabs">
<div class="item" @click="changeTab(index)" v-for="(item, index) in lists" :key="index">
<img :src="currentTabBar == index ? item.selectedIconPath : item.iconPath" alt="" />
<p :class="currentTabBar == index ? 'color-3267F0' : ''">{{ item.text }}</p>
</div>
</div>
</div>
</template>
<script>
import echarts from 'echarts'
import { mapState } from 'vuex'
export default {
name: 'AppResidentFile',
appName: '居民信息管理',
components: {},
props: {},
data() {
return {
lists: [
{
iconPath: 'http://respub.sinoecare.net/20211227/1n-20211227162529.png',
selectedIconPath: 'http://respub.sinoecare.net/20211227/1h-20211227164832.png',
text: '统计分析',
customIcon: false,
},
{
iconPath: 'http://respub.sinoecare.net/20211227/2n-20211227164853.png',
selectedIconPath: 'http://respub.sinoecare.net/20211227/2h-20211227164906.png',
text: '居民列表',
customIcon: false,
},
{
iconPath: 'http://respub.sinoecare.net/20211227/3n-20211227164927.png',
selectedIconPath: 'http://respub.sinoecare.net/20211227/3h-20211227165003.png',
text: '居民群列表',
customIcon: false,
},
],
currentTabBar: 0,
currentTabs: 0,
tabList: [
{
name: '居民群统计',
},
{
name: '居民统计',
},
],
Echarts1: null,
Echarts2: null,
areaId: '',
current: 1,
keyword: '',
data: [],
search: { name: '' },
list: [],
weekList: [],
groupSum: '',
todayList1: [],
todayList2: [],
counts1: '',
counts2: '',
page2: { current: 1, size: 10, total: 0 },
search2: { name: '' },
page1: { current: 1, size: 10, total: 0 },
search1: { name: '' },
}
},
computed: {
...mapState(['user', 'global']),
},
watch: {},
onLoad() {
document.title = '居民信息管理'
this.getEchart1()
this.areaId = this.user.areaId
},
mounted() {
this.Echarts1 = echarts.init(document.getElementById('echarts1'))
},
methods: {
// 居民列表
getList() {
this.$http
.post('/app/wxcp/wxcustomer/list', null, {
params: { ...this.page1, ...this.search, type: 1 },
})
.then((res) => {
if (res?.data) {
if (this.page1.current > 1) {
this.data = [...this.data, ...res.data.records]
} else this.data = res.data.records
this.page1.total = res.data.total
}
})
},
// reachBottom() {
// if (this.page1.total > this.list.length) {
// this.page1.current++
// this.getList()
// }
// },
showResident({ id }) {
id &&
uni.navigateTo({
url: './resident?id=' + id,
})
},
// 居民群列表
getList2() {
this.$http
.post('/app/wxcp/wxgroup/list', null, {
params: { ...this.page2, ...this.search },
})
.then((res) => {
if (res?.data) {
let meta = res.data.records?.map((e) => ({
...e,
avatar: e?.avatar || this.$cdn + 'groupAvatar.png',
}))
if (this.page2.current > 1) {
this.list = [...this.list, ...meta]
} else this.list = meta
this.page2.total = res.data.total
}
})
},
// reachBottom() {
// if (this.page2.total > this.list.length) {
// this.page2.current = this.page2.current + 1
// this.getList2()
// }
// },
toGroupList(item) {
uni.navigateTo({
url: `./GroupList?id=${item.id}`,
})
},
// 居民群统计
getEchart1() {
this.$http.post(`/app/wxcp/wxgroup/groupStatistic`).then((res) => {
if (res.code === 0) {
this.weekList = res.data.list
this.initEcharts1(this.weekList)
this.groupSum = res.data.groupSum
this.todayList1 = res.data.today
}
})
},
// 居民统计
getEchart2() {
this.$http.post(`/app/wxcp/wxcustomerlog/customerStatistic?areaId=${this.user.areaId}`).then((res) => {
if (res.code === 0) {
this.initEcharts2(res.data.list)
this.todayList2 = res.data.today
}
})
},
initEcharts1(data) {
var option = {
legend: {
data: ['群成员总数', '入群人数', '退群人数'],
y: 'bottom',
},
color: ['#4A86FD', '#32C5FF', '#FFAA44'],
tooltip: {
trigger: 'axis',
},
grid: {
top: '9%',
left: '6%',
right: '8%',
bottom: '9%',
containLabel: true,
},
xAxis: {
type: 'category',
data: Object.keys(data).map((e) => e.substring(e.length - 5, e.length)),
axisLine: {
show: true,
lineStyle: { color: '#666' },
},
axisLabel: {
show: true,
interval: 0,
},
axisTick: {
show: false,
},
},
yAxis: {
type: 'value',
axisLine: {
show: false,
},
splitLine: {
show: true,
lineStyle: {
color: '#D8DDE6',
},
},
axisLabel: {
show: true,
interval: 0,
},
axisTick: {
show: false,
},
},
series: [
{
lineStyle: {
normal: {
lineStyle: {
color: '#4A86FD',
},
},
},
color: '#4A86FD',
name: '群成员总数',
type: 'line',
stack: 'Total',
data: Object.values(data).map((e) => e.total),
},
{
lineStyle: {
normal: {
lineStyle: {
color: '#32C5FF',
},
},
},
color: '#32C5FF',
name: '入群人数',
type: 'line',
stack: 'Total',
data: Object.values(data).map((e) => e.increase),
},
{
lineStyle: {
normal: {
lineStyle: {
color: '#FFAA44',
},
},
},
color: '#FFAA44',
name: '退群人数',
type: 'line',
stack: 'Total',
data: Object.values(data).map((e) => e.decrease),
},
],
}
option && this.Echarts1.setOption(option)
},
initEcharts2(data) {
var options = {
legend: {
data: ['居民总数', '新增居民数', '流失居民数'],
y: 'bottom',
},
color: ['#4A86FD', '#32C5FF', '#FFAA44'],
tooltip: {
trigger: 'axis',
},
grid: {
top: '9%',
left: '6%',
right: '8%',
bottom: '9%',
containLabel: true,
},
xAxis: {
type: 'category',
data: Object.keys(data).map((e) => e.substring(e.length - 5, e.length)),
axisLine: {
show: true,
lineStyle: { color: '#666' },
},
axisLabel: {
show: true,
interval: 0,
},
axisTick: {
show: false,
},
},
yAxis: {
type: 'value',
axisLine: {
show: false,
},
splitLine: {
show: true,
lineStyle: {
color: '#D8DDE6',
},
},
axisLabel: {
show: true,
interval: 0,
},
axisTick: {
show: false,
},
},
series: [
{
lineStyle: {
normal: {
lineStyle: {
color: '#4A86FD',
},
},
},
color: '#4A86FD',
name: '居民总数',
type: 'line',
stack: 'Total',
data: Object.values(data).map((e) => e.total),
},
{
lineStyle: {
normal: {
lineStyle: {
color: '#32C5FF',
},
},
},
color: '#32C5FF',
name: '新增居民数',
type: 'line',
stack: 'Total',
data: Object.values(data).map((e) => e.increase),
},
{
lineStyle: {
normal: {
lineStyle: {
color: '#FFAA44',
},
},
},
color: '#FFAA44',
name: '流失居民数',
type: 'line',
stack: 'Total',
data: Object.values(data).map((e) => e.decrease),
},
],
}
if (this.Echarts2) {
options && this.Echarts2.setOption(options)
}
},
changeTab(e) {
this.currentTabBar = e
if (this.currentTabBar == 0) {
this.getList()
this.$nextTick(() => {
if (this.currentTabs == 0) {
this.Echarts1 = echarts.init(document.getElementById('echarts1'))
this.getEchart1()
}
if (this.currentTabs == 1) {
this.Echarts2 = echarts.init(document.getElementById('echarts2'))
this.getEchart2()
}
})
}
if (this.currentTabBar == 1) {
this.page1.current == 1
this.getList()
}
if (this.currentTabBar == 2) {
this.page2.current == 1
this.getList2()
}
},
change(index) {
this.currentTabs = index
this.$nextTick(() => {
if (index == 0) {
this.Echarts1 = echarts.init(document.getElementById('echarts1'))
this.getEchart1()
} else {
this.Echarts2 = echarts.init(document.getElementById('echarts2'))
this.getEchart2()
}
})
},
},
onReachBottom() {
if (this.currentTabBar == 1) {
this.page1.current++
this.getList()
}
if (this.currentTabBar == 2) {
this.page2.current++
this.getList2()
}
},
}
</script>
<style scoped lang="scss">
uni-page-body {
height: 100%;
}
.AppResidentFile {
height: 100%;
.currentTabBar0 {
padding-bottom: 98px;
.peopleGroup,
.people {
.topcard {
position: relative;
background: url(http://respub.sinoecare.net/20211221/4-20211221095551.png) no-repeat;
background-size: 100% 100%;
height: 320px;
.cards {
box-sizing: border-box;
position: absolute;
bottom: -35px;
width: 92%;
box-sizing: border-box;
margin: 0 32px;
height: 232px;
background: #ffffff;
border-radius: 8px;
z-index: 999;
display: flex;
justify-content: space-around;
align-items: center;
.items {
display: flex;
flex-direction: column;
align-items: center;
span {
font-size: 30px;
font-weight: 500;
color: #999999;
}
.items1 {
font-size: 40px;
font-weight: bold;
color: #354fc7;
}
.items2 {
font-size: 40px;
font-weight: bold;
color: #868686;
}
.items3 {
font-size: 40px;
font-weight: bold;
color: #5fba95;
}
.items4 {
font-size: 40px;
font-weight: bold;
color: #f09535;
}
}
}
}
.echartes {
margin-top: 64px;
padding-bottom: 20px;
height: 616px;
background: #fff;
box-sizing: border-box;
.echartss {
margin: 0 32px;
height: 100%;
padding-top: 16px;
box-sizing: border-box;
}
}
}
}
.currentTabBar1 {
height: 100%;
padding-bottom: 98px;
background: #fff;
::v-deep .AiTopFixed {
b.title {
color: #333;
font-size: 32px;
& > i {
color: #267fce;
font-style: normal;
margin: 0 4px;
}
}
}
::v-deep .mainPane {
background: #fff;
padding: 0 32px 88px;
.AiCell {
flex-shrink: 0;
justify-content: flex-start;
.content {
flex: 1;
min-width: 0;
max-width: unset;
border-bottom: 1px solid rgba(221, 221, 221, 1);
min-height: 160px;
}
}
.card {
text-align: left;
b {
max-width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-size: 36px;
}
.tag {
justify-content: center;
background: #f3f4f7;
border-radius: 4px;
padding: 0 16px;
font-size: 28px;
font-weight: 400;
color: #333;
margin-left: 16px;
margin-bottom: 16px;
height: 56px;
}
.realName {
width: 100%;
margin-top: 8px;
font-size: 28px;
font-weight: 400;
color: #999;
}
}
.AiImage {
margin-right: 24px;
image {
width: 112px;
height: 112px;
}
}
}
}
.currentTabBar2 {
padding-bottom: 98px;
::v-deep .AiTopFixed {
b.title {
color: #333;
font-size: 32px;
& > i {
color: #267fce;
font-style: normal;
margin: 0 4px;
}
}
}
::v-deep .mainPane {
background: #fff;
padding: 0 32px;
.AiCell {
align-items: center;
height: 230px;
justify-content: flex-start;
.content {
flex: 1;
min-width: 0;
height: 100%;
max-width: unset;
border-bottom: 1px solid rgba(221, 221, 221, 1);
}
}
.card {
height: 100%;
justify-content: center;
b {
font-size: 36px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.tag {
justify-content: center;
background: #f3f4f7;
border-radius: 4px;
padding: 0 16px;
font-size: 28px;
font-weight: 400;
color: #333;
margin-left: 16px;
height: 56px;
}
.groupName {
width: 100%;
text-align: left;
}
.owner,
.trends {
margin-top: 8px;
font-size: 28px;
font-weight: 400;
color: #999;
}
.personCount {
flex-shrink: 0;
font-size: 30px;
font-weight: 400;
color: #666;
}
.trends {
* + * {
margin-left: 24px;
}
em {
font-style: normal;
color: #5fba95;
}
p {
color: #f09535;
}
}
}
.AiImage {
margin-right: 24px;
image {
width: 112px;
height: 112px;
}
}
}
}
.tabs {
width: 100%;
height: 98px;
background: #fff;
border-top: 1px solid #ddd;
position: fixed;
bottom: 0;
left: 0;
display: flex;
.item {
flex: 1;
text-align: center;
img {
width: 56px;
height: 56px;
margin-top: 8px;
}
p {
font-size: 22px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #c4cad4;
line-height: 8px;
}
.color-3267F0 {
color: #3267f0;
}
}
}
}
</style>

View File

@@ -1,325 +0,0 @@
<template>
<div class="group-resident">
<template v-if="!showTagManage">
<AiTopFixed>
<div class="card">
<header>
<u-avatar mode="square" :src="$cdn + 'groupAvatar.png'" :size="112"></u-avatar>
{{ detail.name }}
</header>
<u-grid :col="2" :border="false">
<u-grid-item>
<label>建群日期</label>
<label v-if="detail.createTime">{{ detail.createTime.split(' ')[0] }}</label>
</u-grid-item>
<u-grid-item>
<label>成员总数</label>
<label v-if="isToday">{{ detail.statistic.today.total }}</label>
</u-grid-item>
<u-grid-item>
<label>今日入群</label>
<label v-if="isToday">{{ detail.statistic.today.increase }}</label>
</u-grid-item>
<u-grid-item>
<label>今日退群</label>
<label v-if="isToday">{{ detail.statistic.today.decrease }}</label>
</u-grid-item>
<!-- <u-grid-item>-->
<!-- <label>今日活跃人数</label>-->
<!-- <label>{{item.value}}</label>-->
<!-- </u-grid-item>-->
</u-grid>
<p class="statistics">
<span>成员性别</span>
<label>男性</label>
<b>{{ detail.man }}</b>
<label>女性</label>
<b>{{ detail.woman }}</b>
<label>未知</label>
<b>{{ detail.unknown }}</b>
</p>
</div>
</AiTopFixed>
<div class="card">
<AiCell title label="群标签">
<u-icon label="添加" size="38" name="iconAdd" custom-prefix="iconfont" color="#1365DD" label-color="#1365DD" @tap="showTagManage = true" />
</AiCell>
<AiCell top-label v-for="(op, name) in tagsList" :label="name" :key="name">
<u-row>
<div class="tag" v-for="(tag, j) in op" :key="j">{{ tag }}</div>
</u-row>
</AiCell>
</div>
<div class="card">
<AiCell title label="群成员"></AiCell>
<div class="wrap">
<div class="item" v-for="(item, index) in detail.groupUserList" :key="index" @click="handleWechat(item)">
<u-avatar mode="square" :src="item.avatar"></u-avatar>
<div class="info">
<div class="left">
<p>
{{ item.memberName }}
<b v-if="item.customerType == 2" style="color: #3c7fc8">@{{ item.corpName }}</b>
<b v-if="item.customerType == 1" style="color: #2ea222">@微信</b>
</p>
<p>真实姓名{{ item.realName }}</p>
</div>
<span v-if="item.userId == detail.owner">群主</span>
</div>
</div>
</div>
</div>
</template>
<TagManage v-if="showTagManage" />
</div>
</template>
<script>
import { mapActions } from 'vuex'
import TagManage from './tagManage'
export default {
name: 'GroupList',
components: {
TagManage,
},
props: {},
provide() {
return {
top: this,
}
},
data() {
return {
id: '',
detail: {},
groupId: null,
showTagManage: false,
}
},
onShow() {
document.title = '添加标签'
},
computed: {
tagsList() {
let obj = {}
this.detail?.tagList?.map((e) => {
if (e?.groupName) {
if (obj?.[e.groupName]) {
obj[e.groupName].push(e.tagName)
} else {
obj[e.groupName] = [e.tagName]
}
}
})
return obj
},
isToday() {
return !!this.detail?.statistic?.today
},
isNormal() {
return !!this.id
},
},
watch: {},
onLoad(o) {
this.id = o.id
this.getContact()
},
onShow() {},
methods: {
...mapActions(['injectJWeixin', 'wxInvoke']),
getContact() {
if (this.isNormal) {
this.groupId = this.id
this.getGroup(this.id)
} else
this.injectJWeixin('getCurExternalChat').then(() => {
this.wxInvoke([
'getCurExternalChat',
{},
(res) => {
if (res?.err_msg == 'getCurExternalChat:ok') {
this.groupId = res.chatId
this.getGroup(res.chatId)
}
},
])
})
},
getGroup(id) {
this.$http
.post('/app/wxcp/wxgroup/getDetail', null, {
params: { id },
})
.then((res) => {
if (res?.data) {
this.detail = res.data
}
})
},
handleWechat({ userId, type }) {
this.injectJWeixin('openUserProfile').then(() => {
this.wxInvoke([
'openUserProfile',
{
type,
userid: userId,
},
() => 0,
])
})
},
},
}
</script>
<style scoped lang="scss">
.group-resident {
width: 100%;
min-height: 100%;
background-color: #f5f5f5;
display: flex;
flex-direction: column;
::v-deep .AiTopFixed {
& > .card {
margin-top: 0;
}
}
::v-deep .card {
background-color: #ffffff;
padding: 16px 32px;
box-sizing: border-box;
margin-top: 16px;
header {
height: 192px;
display: flex;
align-items: center;
font-size: 36px;
font-weight: 600;
color: #333333;
.u-avatar {
margin-right: 24px;
}
}
::v-deep .u-grid-item-box {
box-sizing: border-box;
padding: 16px !important;
.uni-label-pointer {
width: 100%;
line-height: 40px;
color: #999999;
}
uni-label:last-child {
margin-top: 16px;
font-weight: 600;
color: #333333;
}
}
.statistics {
height: 96px;
display: flex;
align-items: center;
border-top: 1px solid #eee;
margin-top: 16px;
span {
font-size: 28px;
color: #999999;
}
label + b {
font-size: 28px;
color: #333333;
}
b {
color: #1365dd !important;
margin: 0 32px 0 16px;
}
}
& > section:first-child {
height: 90px !important;
display: flex;
align-items: center;
}
.wrap {
margin-bottom: 20px;
.item {
height: 176px;
display: flex;
align-items: center;
.info {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: space-between;
margin-left: 24px;
border-bottom: 1px solid #eee;
.left {
font-size: 36px;
font-weight: 600;
color: #333333;
b {
font-size: 28px;
font-weight: 400;
color: #3c7fc8;
margin-left: 16px;
}
p:last-child {
font-size: 28px;
font-weight: 400;
color: #999999;
margin-top: 8px;
}
}
span {
width: 88px;
height: 56px;
text-align: center;
background: rgba(19, 101, 221, 0.1);
box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.02);
border-radius: 4px;
font-size: 28px;
font-weight: 400;
color: #1365dd;
line-height: 56px;
}
}
}
}
}
::v-deep .tag {
height: 56px;
line-height: 56px;
background: #f3f4f7;
border-radius: 6px;
padding: 8px 16px;
margin-right: 16px;
margin-bottom: 16px;
overflow: hidden;
cursor: default;
}
}
</style>

View File

@@ -1,138 +0,0 @@
<template>
<section class="document" v-if="isShow">
<div class="card">
<div class="info">
<u-image border-radius="4" :src="top.detail.avatar" width="118" height="118" />
<div class="fill">
<b>{{ top.detail.realName || top.detail.name }}</b>
<u-row>
<span class="idNumber" v-html="IDObj.id" />
<a @tap="showID = !showID">{{ IDObj.btn }}</a>
</u-row>
</div>
</div>
<AiCell label="性别">{{ $dict.getLabel('sex', resident.sex) || '-' }}</AiCell>
<AiCell label="出生日期">{{ resident.birthDate }}</AiCell>
<AiCell label="年龄">{{ resident.age }}</AiCell>
<AiCell label="籍贯">{{ resident.birthplaceAreaName }}</AiCell>
<AiCell label="民族">{{ $dict.getLabel('nation', resident.nation) || '-' }}</AiCell>
<AiCell label="文化程度">{{ $dict.getLabel('education', resident.education) || '-' }}</AiCell>
<AiCell label="兵役状况">{{ $dict.getLabel('militaryStatus', resident.militaryStatus) || '-' }}</AiCell>
<AiCell label="政治面貌">{{ $dict.getLabel('politicsStatus', resident.politicsStatus) || '-' }}</AiCell>
<AiCell label="职业">{{ $dict.getLabel('job', resident.job) || '-' }}</AiCell>
<AiCell label="宗教信仰">{{ $dict.getLabel('faithType', resident.faithType) || '-' }}</AiCell>
</div>
<div class="card">
<AiCell title label="联络信息" />
<AiCell label="联系方式">{{ resident.phone }}</AiCell>
<AiCell label="现住址">{{ resident.currentAreaName + resident.currentAddress }}</AiCell>
</div>
<div class="card">
<AiCell title label="家庭信息" />
<AiCell label="是否户主">{{ $dict.getLabel('householdName', resident.householdName) || '-' }}</AiCell>
<AiCell label="与户主关系">{{ $dict.getLabel('householdRelation', resident.householdRelation) || '-' }}</AiCell>
<AiCell label="现住址">{{ resident.householdAreaName + resident.householdAddress }}</AiCell>
</div>
<div class="card">
<AiCell title label="家庭成员" />
<AiTable :data="family" :colConfigs="colConfigs" />
</div>
</section>
</template>
<script>
export default {
name: 'document',
inject: ['top'],
computed: {
IDObj() {
return this.showID
? {
id: this.resident?.idNumber,
btn: '隐藏',
}
: {
id: this.resident?.idNumber?.replace(/(\d{10}).+/g, '$1******'),
btn: '显示',
}
},
colConfigs() {
return [
{ label: '与户主关系', prop: 'householdRelation', width: '160rpx', dict: 'householdRelation' },
{ label: '姓名', prop: 'name', width: '120rpx' },
{ label: '性别', prop: 'sex', dict: 'sex' },
{ label: '年龄', prop: 'age' },
{ label: '身份证号', prop: 'idNumber', width: '320rpx' },
]
},
resident() {
let obj = {}
Object.keys(this.top.detail?.residentInfo?.resident || {}).map((e) => {
obj[e] = this.top.detail?.residentInfo?.resident[e] || ''
})
return obj
},
family() {
return this.top.detail?.residentInfo?.family?.map((e) => ({ ...e, householdRelation: e.householdRelation || '户主' }))
},
},
data() {
return {
showID: false,
isShow: false,
familyList: [],
}
},
created() {
this.$dict.load('sex', 'nation', 'education', 'job', 'faithType', 'politicsStatus', 'militaryStatus', 'householdRelation', 'householdName').then(() => {
this.isShow = true
})
// console.log('居民档案性别(无字典)', this.resident.sex)
// console.log('居民档案性别(有字典)', this.$dict.getLabel('sex', this.resident.sex))
// console.log('居民档案字典值', this.$dict.getDict('sex'))
},
onShow() {
// this.$dict.load('sex', 'nation', 'education', 'job', 'faithType', 'politicsStatus', 'militaryStatus', 'householdRelation', 'householdName')
document.title = '居民详情'
},
}
</script>
<style lang="scss" scoped>
.document {
overflow-y: auto;
background: #f5f5f5;
.info {
height: 186px;
width: 100%;
display: flex;
align-items: center;
.fill {
color: #3c7fc8;
margin-left: 24px;
font-size: 28px;
line-height: 40px;
display: flex;
flex-direction: column;
b {
font-size: 36px;
color: #333;
margin-bottom: 8px;
line-height: 50px;
}
a {
cursor: pointer;
}
.idNumber {
margin-right: 16px;
color: #999;
}
}
}
}
</style>

View File

@@ -1,369 +0,0 @@
<template>
<section class="info">
<div class="card">
<div class="baseInfo">
<u-image border-radius="4" :src="top.detail.avatar" width="118" height="118" />
<div class="fill">
<b>{{ top.detail.name }}</b>
<div v-if="top.detail.type == 1" class="wx">@微信</div>
<div v-if="top.detail.type == 2">@企业微信</div>
</div>
<div class="certBtn" @tap="handleCert">{{ !isCert ? '实名认证' : '解绑' }}</div>
</div>
<u-row>
<AiCell class="half" top-label label="来源">{{ $dict.getLabel('wxCustomerAddWay', top.detail.addWay) }}</AiCell>
<AiCell class="half" top-label label="添加时间">{{ top.detail.createTime }}</AiCell>
<AiCell class="half" top-label label="真实姓名">{{ top.detail.realName }}</AiCell>
<AiCell class="half" top-label label="手机号码">{{ resident.phone || '-' }}</AiCell>
<AiCell class="half" top-label label="家庭积分">{{ resident.familyIntegral }}</AiCell>
<AiCell class="half" top-label label="个人积分">{{ resident.personalIntegral }}</AiCell>
</u-row>
</div>
<div class="card">
<AiCell title label="公共标签">
<u-icon label="添加" size="38" name="iconAdd" custom-prefix="iconfont" color="#1365DD" label-color="#1365DD" @tap="top.showTagManage = true" />
</AiCell>
<AiCell top-label v-for="(op, name) in tagsList" :label="name" :key="name">
<u-row>
<div class="tag" v-for="(tag, j) in op" :key="j">{{ tag }}</div>
</u-row>
</AiCell>
</div>
<div class="card">
<AiCell title label="动态" />
<AiCell top-label>
<div class="logItem" v-for="item in customLogs" :key="item.id">
<div flex class="column" shrink>
<div class="dot" />
<div class="line fill" />
</div>
<div flex class="start column">
<b>{{ $dict.getLabel('wxCustomerLogType', item.type) }}</b>
<span>{{ item.createTime }}</span>
<div v-html="item.content" />
</div>
</div>
</AiCell>
</div>
<u-mask :show="dialog" @tap="dialog = false">
<div class="bindCert" @tap.stop>
<b class="title">实名认证</b>
<u-input class="searchInput" v-model="search" clearable placeholder="请输入姓名或身份证号" @input="handleSearch" />
<div class="residents">
<div flex class="spb" v-for="(op, i) in result" :key="i" @tap="bindCert(op.id)">
<div v-html="op.name" />
<div v-html="op.idNumber" />
</div>
</div>
</div>
</u-mask>
<div bottom>
<u-button type="primary" @tap="handleWechat">微信联系</u-button>
<u-button v-if="isMobile" :disabled="!resident.phone" @tap="handleTel">电话联系</u-button>
</div>
</section>
</template>
<script>
import { mapActions } from 'vuex'
export default {
name: 'info',
inject: ['top'],
computed: {
resident() {
return this.top.detail?.residentInfo?.resident || {}
},
tagsList() {
let obj = {}
this.top.detail?.tags?.map((e) => {
if (e.type == 1 && e?.groupName) {
if (obj?.[e.groupName]) {
obj[e.groupName].push(e.tagName)
} else {
obj[e.groupName] = [e.tagName]
}
}
})
return obj
},
isCert() {
return !!this.top?.detail?.residentInfo
},
isMobile() {
return ['Android', 'iPhone', 'SymbianOS', 'Windows Phone', 'iPad', 'iPod'].some((e) => navigator.userAgent.indexOf(e) > -1)
},
},
data() {
return {
dialog: false,
search: '',
result: [],
customLogs: [],
}
},
methods: {
...mapActions(['injectJWeixin', 'wxInvoke']),
searchResident() {
this.$http
.post('/app/appresident/check-name', null, {
params: { name: this.search },
})
.then((res) => {
if (res?.data) {
let reg = new RegExp(this.search, 'g')
this.result = res.data?.map((e) => ({
...e,
name: e.name.replace(reg, `<b>${this.search}</b>`),
idNumber: e.idNumber.replace(reg, `<b>${this.search}</b>`),
}))
}
})
},
handleSearch() {
if (this.search?.length >= 2) {
this.searchResident()
} else {
this.result = []
}
},
handleCert() {
if (this.isCert) {
this.$confirm('是否要解绑当前实名认证?').then(() => {
this.$http
.post('/app/wxcp/wxcustomer/unBindCustomer2Resident', null, {
params: { residentId: this.resident.id, customerId: this.top.custom },
})
.then((res) => {
if (res?.code == 0) {
this.$u.toast('解除绑定成功!')
this.top.getContact()
}
})
})
} else this.dialog = true
},
bindCert(residentId) {
this.dialog = false
this.$confirm('是否要绑定该居民?')
.then(() => {
this.$http
.post('/app/wxcp/wxcustomer/bindCustomer2Resident', null, {
params: { residentId, customerId: this.top.custom },
})
.then((res) => {
if (res?.code == 0) {
this.$u.toast('绑定成功!')
this.top.getContact()
}
})
.catch((err) => {
this.$u.toast(err)
setTimeout(() => (this.dialog = true), 1000)
})
})
.catch(() => (this.dialog = true))
},
getCustomLog(customerId) {
customerId &&
this.$http
.post('/app/wxcp/wxcustomerlog/listAll', null, {
params: { customerId },
})
.then((res) => {
if (res?.data) {
this.customLogs = res.data
}
})
},
handleTel() {
location.href = 'tel:' + this.resident.phone
},
handleWechat() {
this.wxInvoke([
'openUserProfile',
{
type: 2,
userid: this.top.custom,
},
() => 0,
])
},
},
created() {
this.$dict.load('wxCustomerAddWay', 'wxCustomerLogType')
this.getCustomLog(this.top.custom)
this.injectJWeixin('openUserProfile')
},
onShow() {
document.title = '居民详情'
}
}
</script>
<style lang="scss" scoped>
.info {
padding-bottom: 130px;
.certBtn {
cursor: pointer;
background: $uni-color-primary;
color: #fff;
padding: 8px 16px;
border-radius: 4px;
}
.baseInfo {
height: 186px;
width: 100%;
display: flex;
align-items: center;
.fill {
color: #3c7fc8;
margin-left: 24px;
font-size: 28px;
line-height: 40px;
b {
font-size: 36px;
color: #333;
margin-bottom: 8px;
line-height: 50px;
}
.wx {
color: #2ea222;
}
}
}
::v-deep .AiCell {
&.half {
width: 50%;
}
}
::v-deep .u-form-item {
width: 50%;
min-height: 124px;
.u-form-item--left {
color: #999;
min-height: 40px;
}
.u-form-item--right {
min-height: 0;
margin-top: 16px;
}
}
::v-deep .u-mask {
display: flex;
align-items: center;
justify-content: center;
.bindCert {
width: 600px;
padding: 32px;
min-height: 400px;
background-color: #fff;
display: flex;
flex-direction: column;
color: #333;
}
.residents {
max-height: 780px;
overflow-y: auto;
}
.title {
text-align: center;
font-size: 36px;
}
.searchInput {
margin: 16px 0;
border: 1px solid #d0d4dc;
border-radius: 8px;
padding: 0 16px !important;
flex: 0;
}
.spb {
height: 60px;
cursor: pointer;
padding: 0 16px;
b {
font-size: 32px;
}
&:nth-of-type(2n) {
background: #eee;
}
}
}
::v-deep .logItem {
display: flex;
min-height: 220px;
&:last-of-type {
.line {
display: none;
}
}
& > .column + .column {
margin-left: 16px;
}
.dot {
flex-shrink: 0;
width: 16px;
height: 16px;
background: $uni-color-primary;
border: 8px solid #ffffff;
border-radius: 50%;
margin: 8px 0;
}
.line {
width: 4px;
background: #eee;
}
.start {
font-size: 26px;
font-weight: 400;
color: #666;
b {
color: #333;
}
i {
color: $uni-color-primary;
font-style: normal;
}
& > b {
font-size: 32px;
font-weight: bold;
margin-bottom: 8px;
}
& > span {
color: #999;
}
& > div {
margin-top: 16px;
}
}
}
}
</style>

View File

@@ -1,155 +0,0 @@
<template>
<section class="resident">
<AiLoading v-if="!custom && !error" tips="获取居民信息中..." />
<AiResult v-else-if="error" status="error" :tips="error" />
<template v-else>
<tag-manage v-if="showTagManage" />
<template v-else>
<AiTopFixed>
<u-tabs :list="tabs" :is-scroll="false" :current="currentType" font-size="32" bar-width="192" height="96" @change="handleTabClick" />
</AiTopFixed>
<component :is="currentTab.comp" />
</template>
</template>
</section>
</template>
<script>
import { mapActions } from 'vuex'
import Info from './components/info'
import Document from './components/document'
import TagManage from './tagManage.vue'
export default {
name: 'resident',
components: { TagManage, Document, Info },
provide() {
return {
top: this,
id: '',
}
},
onShow() {
document.title = '居民详情'
},
computed: {
tabs() {
return [
{ name: '居民信息', value: 0, comp: Info },
{ name: '居民档案', value: 1, comp: Document, hide: !this.detail.residentInfo },
].filter((e) => !e.hide)
},
currentTab() {
return this.tabs.find((e) => e.value == this.currentType)
},
isNormal() {
return !!this.id
},
},
data() {
return {
currentType: 0,
detail: {},
showTagManage: false,
custom: '',
error: '',
}
},
methods: {
...mapActions(['injectJWeixin', 'wxInvoke']),
handleTabClick(i) {
this.currentType = i
},
getContact() {
if (this.isNormal) {
this.getCustom(this.id)
} else {
this.injectJWeixin('getCurExternalContact')
.then(() => {
this.wxInvoke([
'getCurExternalContact',
{},
(res) => {
if (res?.err_msg == 'getCurExternalContact:ok') {
this.getCustom(res.userId)
}
},
])
})
.catch(({ errMsg }) => {
this.error = errMsg
})
}
},
getCustom(id) {
this.$http
.post('/app/wxcp/wxcustomer/queryCustomerById', null, {
params: { id },
})
.then((ret) => {
if (ret?.data) {
this.custom = id
this.detail = ret.data
if (this.detail.type == 2) {
this.error = '只能查看个人微信绑定的居民信息'
}
}
})
},
},
onLoad(o) {
this.id = o.id
this.getContact()
},
}
</script>
<style lang="scss" scoped>
.resident {
display: flex;
flex-direction: column;
height: 100%;
background: #f5f5f5;
.error {
font-size: 32px;
color: #666;
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
::v-deep .u-scroll-box {
border-bottom: 1px solid #d4d4d4;
.u-tab-bar {
position: absolute;
bottom: -6px;
}
}
::v-deep .card {
background: #fff;
margin-bottom: 16px;
padding: 16px 32px;
}
.half {
width: 50%;
}
::v-deep .tag {
height: 56px;
line-height: 56px;
background: #f3f4f7;
border-radius: 6px;
padding: 8px 16px;
margin-right: 16px;
margin-bottom: 16px;
overflow: hidden;
cursor: default;
}
}
</style>

View File

@@ -1,92 +0,0 @@
<template>
<section class="tagManage">
<div class="card" v-for="(group, i) in tags" :key="i">
<AiCell title :label="group.name" />
<u-row>
<div class="tag" v-for="(op, j) in group.tagList" :key="j" :class="{ selected: selected.includes(op.id) }" @tap="$u.debounce(handleToggle(op.id))">
{{ op.name }}
</div>
</u-row>
</div>
</section>
</template>
<script>
export default {
name: 'tagManage',
inject: ['top'],
data() {
return {
tags: [],
}
},
computed: {
selected() {
return this.top.groupId ? this.top.detail?.tagList.map((e) => e.tagId) : this.top.detail?.tags.map((e) => e.tagId)
},
},
methods: {
getTags() {
this.$http
.post(this.top.groupId ? '/app/wxcp/wxgroupchattag/listAll' : '/app/wxcp/wxcorptag/listAll', null, {
params: { size: 9999 },
})
.then((res) => {
if (res?.data) {
this.tags = res.data.records
}
})
},
handleToggle(tagId) {
uni.showLoading({
title: '提交中',
})
this.$http
.post(this.top.groupId ? '/app/wxcp/wxgroupchattag/markTagForCP' : '/app/wxcp/wxcorptag/markTagForCP', null, {
params: this.top.groupId ? { tagId, groupId: this.top.groupId } : { tagId, customerId: this.top.custom },
})
.then((res) => {
uni.hideLoading()
if (res?.code == 0) {
this.$u.toast('操作成功!')
this.getTags()
this.top.getContact()
}
})
.catch((err) => {
uni.hideLoading()
this.$u.toast(err)
})
},
},
created() {
this.getTags()
},
}
</script>
<style lang="scss" scoped>
.tagManage {
padding-top: 16px;
.tag {
cursor: pointer !important;
&.selected {
background-color: $uni-color-primary !important;
color: #fff;
}
&.disabled {
color: #999;
cursor: not-allowed;
}
& + .tag {
margin-left: 16px;
}
}
}
</style>