小程序目录调整完成

This commit is contained in:
aixianling
2022-05-12 12:16:40 +08:00
parent 6ed5ef69ad
commit 5d0801ac21
96 changed files with 14 additions and 1268 deletions

View File

@@ -0,0 +1,320 @@
<template>
<div class="wrapper padding">
<!-- <u-tabs :list="tabs" height="124" font-size="40" bg-color="#4181FF" inactive-color="rgba(255,255,255,0.75)"
:bar-style="{backgroundColor:'#fff'}" :active-item-style="active"
:is-scroll="true" :current="index" @change="onChange"></u-tabs> -->
<div class="tabs">
<u-tabs
:list="tabs"
font-size="36"
bg-color="transparent"
:bold="false"
inactive-color="#ccddff"
:is-scroll="true"
:gutter="16"
active-color="#fff"
:current="index"
@change="onChange">
</u-tabs>
</div>
<header>
<span @click="show=true">{{ !typeName ? '全部类型' : typeName }}
<u-icon name="arrow-down" size="28" color="#333333" :custom-style="{marginLeft:'8px'}"></u-icon>
</span>
<div class="total">
<em>{{ total }}</em>个农产品
</div>
</header>
<div class="card-list" v-if="list.length">
<div class="card" v-for="(item,index) in list" :key="index" @click="toDetail(item)">
<div class="top">
<div class="title">{{ item.title }}
</div>
<div class="ag-content">{{ item.content }}
</div>
<div class="phone-wrap">
<img class="img" :class="[item.files.length ==1 ? 'single' : '']" v-for="(photo,idx) in item.files"
:key="idx" :src="photo.url" alt="" @click.stop="preview(item.files,idx)">
</div>
<div class="ag-info">
<div class="tag">{{ $dict.getLabel('agriculturalType', item.type) }}</div>
<div class="date">{{ item.createTime }}</div>
</div>
</div>
<div class="phone" @click.stop="phone(item.phone)">
<u-icon name="phone-fill" size="32" color="#4181FF"></u-icon>
<span>{{ item.phone }}</span>
</div>
</div>
</div>
<AiEmpty v-else/>
<div class="btn-wrapper">
<div class="btn" @click="suport" hover-class="text-hover">我要发布</div>
</div>
<u-select v-model="show" :list="$dict.getDict('agriculturalTypeSearch')" value-name="dictValue"
label-name="dictName" @confirm="confirm"></u-select>
</div>
</template>
<script>
export default {
name: "AppAgProducts",
appName: "晒农产品",
data() {
return {
index: 0,
show: false,
current: 1,
type: "",
typeName: "",
list: [],
total: 0,
}
},
onLoad() {
this.$dict.load("agriculturalTypeSearch");
},
computed: {
active() {
return {
fontSize: "22px",
color: "#FFFFFF",
};
},
tabs() {
return [{
name: '全部'
}, {
name: '我的发布'
}]
},
},
methods: {
preview(photos, index) {
this.$previewImage(photos, index, "url");
},
onChange(val) {
this.index = val;
this.current = 1;
if (!!this.index) {
this.getMine();
} else this.getAll();
},
phone(phoneNumber) {
uni.makePhoneCall({phoneNumber});
},
confirm(val) {
this.type = val[0].value;
this.typeName = val[0].label;
this.current = 1;
if (!!this.index) {
this.getMine();
} else this.getAll();
},
getAll() {
this.$instance.post("/app/appshowagriculturalproduce/list", null, {
params: {
type: this.type,
current: this.current,
}
}).then(res => {
if (res?.data) {
this.list = this.current > 1 ? [...this.list, ...res.data.records] : res.data.records;
this.total = res.data.total;
}
})
},
getMine() {
this.$instance.post("/app/appshowagriculturalproduce/listByWx", null, {
params: {
type: this.type,
current: this.current,
}
}).then(res => {
if (res?.data) {
this.list = this.current > 1 ? [...this.list, ...res.data.records] : res.data.records;
this.total = res.data.total;
}
})
},
toDetail({id}) {
uni.navigateTo({
url: "./agDetail?id=" + id + "&type=" + this.index
})
},
suport() {
uni.navigateTo({
url: "./agAdd"
})
}
},
onShow() {
this.current = 1;
if (!!this.index) {
this.getMine();
} else {
this.getAll();
}
},
onReachBottom() {
this.current++;
if (!!this.index) {
this.getMine();
} else {
this.getAll();
}
}
}
</script>
<style lang="scss" scoped>
.padding {
padding-top: 100px;
padding-bottom: 156px;
.tabs {
position: fixed;
top: 0;
left: 0;
z-index: 11;
width: 100%;
padding: 10px 0 10px 16px;
box-sizing: border-box;
background: #4181FF;
}
header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 48px 32px 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;
}
}
}
.card-list {
display: flex;
flex-direction: column;
box-sizing: border-box;
padding: 0 32px;
.card {
background: #FFFFFF;
box-shadow: 0px -1px 0px 0px #DDDDDD;
border-radius: 16px 16px 0px 0px;
margin-bottom: 24px;
.top {
box-sizing: border-box;
padding: 32px;
border-bottom: 1px solid #DDDDDD;
.title {
font-size: 36px;
font-weight: 600;
color: #333333;
line-height: 50px;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
overflow: hidden;
}
.ag-content {
font-size: 32px;
font-weight: 400;
color: #999999;
line-height: 44px;
margin-top: 8px;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
overflow: hidden;
}
.phone-wrap {
gap: 4px;
display: flex;
align-items: center;
flex-wrap: wrap;
margin-top: 24px;
.img {
width: 203px;
height: 204px;
}
.single {
width: 100%;
height: 350px;
}
}
.ag-info {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 24px;
.tag {
width: 88px;
height: 48px;
background: #EEEEEE;
border-radius: 24px;
font-size: 28px;
font-weight: 400;
color: #999999;
text-align: center;
line-height: 50px;
}
.date {
font-size: 28px;
font-weight: 400;
color: #999999;
}
}
}
.phone {
height: 104px;
box-sizing: border-box;
display: flex;
align-items: center;
box-sizing: border-box;
padding: 32px;
& > img {
width: 32px;
height: 33px;
}
& > span {
font-size: 28px;
font-weight: 400;
color: #4181FF;
margin-left: 12px;
}
}
}
}
}
</style>

View File

@@ -0,0 +1,178 @@
<template>
<div class="wrapper">
<div class="card">
<div class="form">
<em>*</em>
<label>标题</label>
</div>
<u-input type="textarea" trim placeholder="请输入标题" maxlength="100"
placeholder-style="color: #999999;font-size: 15px;" v-model="form.title"/>
<div class="form" style="border-top: 1px solid #dddddd;">
<em>*</em>
<label>详细描述</label>
</div>
<u-input type="textarea" trim placeholder="请输入详细描述信息" maxlength="500"
placeholder-style="color: #999999;font-size: 15px;" v-model="form.content"/>
</div>
<div class="card">
<div class="form">
<em>*</em>
<label>农产品类型</label>
<AiSelect class="right" v-model="form.type" dict="agriculturalType"/>
</div>
</div>
<div class="card" style="padding-bottom: 20px;">
<div class="form">
<label>图片上传
<span>(最多9张)</span>
</label>
</div>
<AiUploader :limit="9" v-model="form.files"></AiUploader>
</div>
<div class="card">
<div class="form border">
<em>*</em>
<label>联系人</label>
<div class="right">
<u-input trim placeholder="请输入" input-align="right"
placeholder-style="color:#999;font-size: 17px;" v-model="form.contactPerson"></u-input>
</div>
</div>
<div class="form border">
<em>*</em>
<label>联系方式</label>
<div class="right">
<u-input trim placeholder="请输入" input-align="right"
placeholder-style="color:#999;font-size: 17px;" :maxlength="11" v-model="form.phone"></u-input>
</div>
</div>
<div class="form">
<em>*</em>
<label>地址</label>
<div class="right">
<u-input trim placeholder="请输入" input-align="right" style="flex: 1;margin-left: 16px;"
placeholder-style="color:#999;font-size: 17px;" v-model="form.address"></u-input>
</div>
</div>
</div>
<div class="btn-wrapper">
<div class="btn" @click="submit" hover-class="text-hover">提交</div>
</div>
</div>
</template>
<script>
export default {
name: "agAdd",
appName: "发布晒农产品",
data() {
return {
form: {
title: "",
content: "",
type: "",
typeName: "",
files: [],
contactPerson: "",
phone: "",
address: "",
},
flag: false
}
},
onLoad() {
this.$dict.load("agriculturalType");
},
methods: {
submit() {
if (!!!this.form.title) return this.$u.toast("请输入标题");
if (!!!this.form.content) return this.$u.toast("请输入详细描述");
if (!!!this.form.type) return this.$u.toast("请选择农产品类型");
if (!!!this.form.contactPerson) return this.$u.toast("请输入联系人")
if (!!!this.form.phone) return this.$u.toast("请输入联系方式");
if (!!!this.form.address) return this.$u.toast("请输入地址");
if (this.flag) return
this.flag = true
this.$loading()
this.$instance.post("/app/appshowagriculturalproduce/addOrUpdate", {
...this.form
}).then(res => {
this.$hideLoading()
this.flag = false
if (res.code == 0) {
this.$u.toast("提交成功");
setTimeout(_ => {
uni.navigateBack();
}, 500)
}
})
}
},
}
</script>
<style lang="scss" scoped>
.wrapper {
padding-bottom: 150px;
}
.card {
box-sizing: border-box;
padding-left: 32px;
background-color: #fff;
margin-bottom: 24px;
.form {
height: 112px;
background: #FFFFFF;
display: flex;
align-items: center;
& > em {
width: 16px;
height: 44px;
font-weight: 400;
color: #FF4466;
line-height: 54px;
font-style: normal;
margin-right: 8px;
}
& > label {
font-size: 32px;
font-weight: 500;
color: #666666;
& > span {
font-size: 28px;
font-weight: 400;
color: #999999;
}
}
.right {
flex: 1;
display: flex;
align-items: center;
flex-direction: row-reverse;
margin-right: 32px;
.value {
font-size: 34px;
font-weight: 600;
color: #333333;
}
}
}
.border {
border-bottom: 1px solid #DDDDDD;
}
}
</style>

View File

@@ -0,0 +1,201 @@
<template>
<div class="wrapper padding">
<div class="card">
<header>{{ detail.title }}</header>
<div class="date">{{ detail.createTime }}</div>
<div class="detail-content">{{ detail.content }}
</div>
<div class="photo-title">图片</div>
<div class="photo-wrap">
<img :src="item.url" alt=""
v-for="(item,index) in detail.files" :key="index" @click="preview(index)">
</div>
</div>
<div class="card">
<div class="item">
<div class="label">联系方式</div>
<div class="value" @click="phone">
<u-icon name="phone-fill" size="28" color="#4181FF" :custom-style="{marginRight:'6px'}"></u-icon>
{{ detail.phone }}
</div>
</div>
<div class="item">
<div class="label">地址</div>
<div class="address">{{ detail.address }}</div>
</div>
</div>
<div class="btn-wrapper" v-if="type==1">
<div class="btn" @click="unDo" hover-class="text-hover">撤销发布</div>
</div>
<!-- <div class="btn" @click="unDo" v-if="type==1">撤销发布</div> -->
</div>
</template>
<script>
export default {
name: "agDetail",
appName: "农产品详情",
data() {
return {
id: null,
type: null,
detail: {},
}
},
onLoad(opt) {
this.id = opt.id;
this.type = opt.type;
this.getDetail();
},
methods: {
preview(index) {
this.$previewImage(this.detail.files, index, "url");
},
phone() {
uni.makePhoneCall({
phoneNumber: this.detail.phone
})
},
unDo() {
uni.showModal({
title: "提示",
content: "是否确定要撤销?",
success: res => {
if (res.confirm) {
this.$instance.post("/app/appshowagriculturalproduce/delete", null, {
params: {ids: this.id}
}).then(ret => {
if (ret.code == 0) {
this.$u.toast("撤销成功");
setTimeout(_ => {
uni.navigateBack();
}, 500)
}
})
}
}
})
},
getDetail() {
this.$instance.post("/app/appshowagriculturalproduce/queryDetailById", null, {
params: {id: this.id}
}).then(res => {
if (res?.data) {
this.detail = res.data;
}
})
}
},
}
</script>
<style lang="scss" scoped>
.padding {
padding-bottom: 156px;
.card {
background-color: #FFFFFF;
margin-bottom: 24px;
box-sizing: border-box;
padding: 40px 32px;
header {
font-size: 48px;
font-weight: 600;
color: #333333;
line-height: 66px;
}
.date {
font-size: 30px;
font-weight: 400;
color: #999999;
margin-top: 16px;
}
.detail-content {
font-size: 36px;
font-weight: 400;
color: #333333;
line-height: 64px;
margin-top: 64px;
padding-bottom: 48px;
}
.photo-title {
height: 112px;
display: flex;
align-items: center;
font-size: 32px;
font-weight: 400;
color: #999999;
}
.photo-wrap {
display: flex;
align-items: center;
gap: 4px;
flex-wrap: wrap;
& > img {
width: 225px;
height: 225px;
}
}
.item {
display: flex;
justify-content: space-between;
margin-bottom: 32px;
&:last-child {
margin-bottom: 0;
}
.label {
font-size: 32px;
font-weight: 400;
color: #999999;
}
.value {
font-size: 32px;
font-weight: 400;
color: #4181FF;
}
.address {
width: 480px;
font-size: 32px;
font-weight: 400;
color: #333333;
line-height: 44px;
text-align: right;
}
}
}
.btn-wrapper {
height: 100px;
line-height: 100px;
}
.btn {
width: 686px;
height: 88px;
background: #FFFFFF;
border-radius: 16px;
border: 1px solid #FF4466;
display: flex;
align-items: center;
justify-content: center;
font-size: 34px;
font-weight: 600;
position: fixed;
left: 50%;
bottom: 32px;
transform: translateX(-50%);
color: #FF4466;
}
}
</style>

View File

@@ -0,0 +1,224 @@
<template>
<div class="wrapper" :style="{ paddingTop: categorys.length ? '54px' : '10px' }" v-if="pageShow">
<div class="tabs">
<u-tabs
:list="categorys && categorys.map(e=>({name:e.categoryName}))"
font-size="36"
bg-color="transparent"
:bold="false"
inactive-color="#ccddff"
:is-scroll="true"
:gutter="16"
active-color="#fff"
:current="index"
@change="tabChange">
</u-tabs>
</div>
<div class="list-wrap" v-if="categoryList && categoryList.length">
<div class="list-card" hover-class="bg-hover" v-for="(category,index) in categoryList" :key="index"
@click="$linkTo('./contentDetail?id='+category.id)">
<div class="header">{{ category.title }}</div>
<div class="content-wrap" v-if="category.contentType==0 && category.files && category.files.length == 1">
<img class="img" :src="item.url" v-for="(item,index) in category.files" :key="index.id" alt="">
</div>
<div class="content-wrap" v-if="category.contentType==0 && category.files && category.files.length > 1">
<img class="min-img" :src="item.url" v-for="(item,index) in category.files && category.files.slice(0,3)"
:key="index.id" alt="">
</div>
<div class="content-wrap" v-if="category.contentType==1">
<img class="img" :src="category.pictureUrl" alt="">
<img class="play-icon" src="https://cdn.cunwuyun.cn/AppContent/play.png" alt="">
</div>
<div class="bottom">
<div class="left">
<div class="tag">{{ category.categoryName || names }}</div>
{{ category.createTime }}
</div>
<div class="right">
<em>{{ category.viewCount }}</em>
人看过
</div>
</div>
</div>
</div>
<AiEmpty v-else></AiEmpty>
</div>
</template>
<script>
import {mapState} from "vuex";
export default {
name: "AppContent",
appName: "内容管理",
data() {
return {
index: 0,
names: "",
categorys: [],
categoryList: [],
pageShow: false,
search: {}
}
},
onLoad(option) {
this.$loading()
this.names = option.names;
this.search.areaId = option.areaId || this.user.areaId || ""
this.getName();
if (option.names) {
uni.setNavigationBarTitle({
title: option.names
})
}
},
computed: {
...mapState(['user']),
active() {
return {
fontSize: "22px",
color: "#fff",
};
},
},
methods: {
getName() {
this.$instance.post("/app/appcontentmoduleinfo/listByName", null, {
params: {names: this.names}
}).then(res => {
if (res?.data) {
this.categorys = res.data?.[0]?.categoryList || [];
this.search.moduleId = res.data?.[0]?.id || "";
this.search.categoryId = res.data?.[0]?.categoryList?.[0]?.id || "";
this.getCategoryList();
} else {
this.$hideLoading()
}
})
},
tabChange(e) {
this.index = e
this.search.categoryId = this.categorys?.[e]?.id
this.getCategoryList();
},
getCategoryList() {
this.$instance.post("/app/appcontentinfo/list", null, {
params: {...this.search, size: 10}
}).then(res => {
if (res?.data) {
this.categoryList = this.current > 1 ? [...this.categoryList, ...res.data.records] : res.data.records;
}
this.pageShow = true
this.$hideLoading()
})
},
},
onReachBottom() {
this.current++;
this.getCategoryList();
}
}
</script>
<style lang="scss" scoped>
.wrapper {
padding-top: 100px;
.list-wrap {
box-sizing: border-box;
padding: 32px;
.list-card {
width: 100%;
min-height: 100px;
background: #FFFFFF;
box-shadow: 0 0 8px 0 rgba(0, 0, 0, 0.02);
border-radius: 16px;
box-sizing: border-box;
padding: 32px;
margin-bottom: 24px;
.header {
font-size: 36px;
font-weight: 600;
color: #333333;
line-height: 50px;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
.content-wrap {
display: flex;
gap: 4px;
flex-wrap: wrap;
margin-top: 24px;
position: relative;
.img {
width: 100%;
height: 350px;
}
.min-img {
width: 204px;
height: 204px;
}
.play-icon {
width: 80px;
height: 80px;
border-radius: 50%;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
}
.bottom {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 24px;
.left {
display: flex;
align-items: center;
font-size: 28px;
font-weight: 400;
color: #999999;
.tag {
width: 144px;
height: 48px;
background: #EEEEEE;
border-radius: 24px;
display: flex;
align-items: center;
justify-content: center;
font-size: 28px;
font-weight: 400;
color: #999999;
margin-right: 16px;
}
}
.right {
font-size: 28px;
font-weight: 400;
color: #999999;
display: flex;
align-items: center;
em {
font-style: normal;
color: #4181FF;
}
}
}
}
}
}
</style>

View File

@@ -0,0 +1,51 @@
<template>
<section class="contentDetail">
<AiDetail :detail="detail" :props="props"/>
</section>
</template>
<script>
export default {
name: "contentDetail",
appName:"内容详情",
data() {
return {
detail: {title: "内容详情"},
props: {
count: "viewCount"
},
id: "",
}
},
onLoad({id}) {
if (id) {
this.id = id;
this.getDetail(id);
}
},
methods: {
getDetail(id) {
this.$instance.post(`/app/appcontentinfo/queryDetailById`, null, {
params: {id}
}).then(res => {
if (res?.data) {
this.detail = res.data
}
})
},
},
onShareAppMessage() {
return {
title: this.detail.title,
path: '/mods/AppContent/contentDetail?id=' + this.id
};
}
}
</script>
<style lang="scss" scoped>
.contentDetail {
}
</style>

View File

@@ -0,0 +1,103 @@
<template>
<section class="contentManager">
<AiNewsList :list="list" :loadmore="loadmore" @select="showDetail">
<template #header>
<div class="search-wrap">
<div class="search">
<u-icon name="search" color="rgba(255,255,255,0.5)" size="40"></u-icon>
<input placeholder="请输入需要搜索的内容" class="desc" placeholder-style="color:rgba(255,255,255,0.5);"
confirm-type="search" @change="onChange"/>
</div>
</div>
</template>
</AiNewsList>
</section>
</template>
<script>
import {mapState} from "vuex";
export default {
name: "contentManager",
appName: "搜索结果",
computed: {
...mapState(['user']),
loadmore() {
return this.pages <= this.current ? 'loading ' : 'nomore'
}
},
data() {
return {
list: [],
current: 1,
pages: 0,
name: "",
}
},
onLoad(params) {
if (params.moduleId) {
this.moduleId = params.moduleId
this.getData(params.moduleId)
}
},
methods: {
onChange(val) {
this.current = 1;
this.getData(val.detail.value);
},
getData(title = "") {
let {current} = this
this.moduleId && this.$instance.post("/app/appcontentinfo/list", null, {
params: {moduleId: this.moduleId, current, size: 10, title}
}).then(res => {
if (res?.data) {
this.list = current > 1 ? [...this.list, ...res.data.records] : res.data.records
this.pages = res.data.pages
}
})
},
handleSelectArea(e) {
this.search.areaId = e.id
this.getData()
},
showDetail(row) {
uni.navigateTo({url: `./contentDetail?id=${row.id}`})
},
},
onReachBottom() {
this.current++;
this.getData()
},
}
</script>
<style lang="scss" scoped>
::v-deep .search-wrap {
width: 750px;
height: 112px;
box-sizing: border-box;
padding: 0 32px;
display: flex;
align-items: center;
justify-content: center;
background-color: #4181FF;
.search {
width: 100%;
height: 64px;
background: rgba(0, 0, 0, .2);
border-radius: 32px;
box-sizing: border-box;
padding: 0 32px;
display: flex;
align-items: center;
.desc {
flex: 1;
font-size: 28px;
color: #FFFFFF;
margin-left: 16px;
}
}
}
</style>

View File

@@ -0,0 +1,121 @@
<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: "AppHometown",
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;
}
.address {
font-size: 30px;
font-weight: 400;
color: #999999;
line-height: 42px;
margin-top: 16px;
}
.desc {
font-size: 36px;
font-weight: 400;
color: #333333;
line-height: 64px;
margin-top: 64px;
padding-bottom: 120px;
}
.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,352 @@
<template>
<div class="wrapper">
<div class="search-wrap">
<div class="left" @click="show=true">
<span>{{ search.typeName ? search.typeName : "全部" }}</span>
<u-icon name="arrow-down" color="#ffffff" size="20"></u-icon>
</div>
<div class="right">
<u-icon name="search" size="32" color="rgba(255,255,255,0.5)" :custom-style="{marginRight:'8px'}"></u-icon>
<input placeholder="请输入需要搜索的内容" style="flex: 1;color:#fff;" confirm-type="search"
placeholder-style="color:rgba(255,255,255,0.5)" v-model="search.title"
@confirm="current=1;getList()"></input>
</div>
</div>
<div class="job-list" v-if="list.length">
<header>
<span>招工就业列表</span>
<div class="right">
<em>{{ total }}</em>个职位
</div>
</header>
<div class="card" v-for="(item,index) in list" :key="index">
<template v-if="item.type == 1">
<div class="top" @click="toDetail(0,item)">
<div class="title">{{ item.title }}</div>
<div class="job-content">{{ item.remark || "" }}</div>
<div class="photo">
<img
:src="photo.url"
alt="" v-for="photo in item.files" :key="photo.id">
</div>
<div class="info">
<div class="tag">个人求职</div>
<div class="date">{{ item.createTime && item.createTime.slice(0, 16) }}</div>
</div>
</div>
<div class="bottom">
<span class="name">{{ item.linkName }}</span>
<div class="right" @click="phone(item)">
<u-icon name="phone-fill" size="36" color="#4181FF" :custom-style="{marginRight:'8px'}"></u-icon>
{{ item.linkPhone }}
</div>
</div>
</template>
<template v-if="item.type == 0">
<div class="top" @click="toDetail(1,item)">
<div class="post-info">
<div class="post">{{ item.title }}</div>
<div class="salary">{{ item.salary }}</div>
</div>
<div class="require">{{ item.remark || "" }}</div>
<div class="info">
<div class="tag" style="background-color:#1AAAFF">企业招工</div>
<div class="date">{{ item.createTime && item.createTime.slice(0, 16) }}</div>
</div>
</div>
<div class="bottom">
<div class="company">{{ item.companyName }}</div>
</div>
</template>
</div>
</div>
<AiEmpty v-else></AiEmpty>
<div class="btn-wrapper">
<div class="btn" @click="$linkTo('./pubJob')" hover-class="text-hover">我要找工作</div>
</div>
<u-select v-model="show" :list="selectList" @confirm="onConfirm"></u-select>
</div>
</template>
<script>
export default {
name: "AppJob",
appName: "招工就业",
data() {
return {
show: false,
current: 1,
list: [],
total: 0,
search: {
title: "",
type: "",
typeName: "",
}
}
},
computed: {
selectList() {
return [{
value: '',
label: '全部'
}, {
value: '0',
label: '企业招工'
},
{
value: '1',
label: '个人求职'
}];
}
},
methods: {
preview(index) {
this.$previewImage(this.list, index, "url");
},
phone({linkPhone: phoneNumber}) {
uni.makePhoneCall({phoneNumber});
},
onConfirm(val) {
this.search.typeName = val[0].label;
this.search.type = val[0].value;
this.current = 1;
this.getList();
},
getList() {
this.$instance.post("/app/appjob/list", null, {
params: {
...this.search,
current: this.current
}
}).then(res => {
if (res?.data) {
this.list = this.current > 1 ? [...this.list, ...res.data.records] : res.data.records;
this.total = res.data.total;
}
})
},
toDetail(val, {id}) {
uni.navigateTo({
url: !!val ? `./compJob?id=${id}` : `./persJob?id=${id}`
})
}
},
onShow() {
this.current = 1;
this.getList();
},
onReachBottom() {
this.current++;
this.getList();
}
}
</script>
<style lang="scss" scoped>
.wrapper {
padding-top: 124px;
}
.search-wrap {
position: fixed;
left: 0;
top: 0;
z-index: 11;
width: 100%;
height: 124px;
background: #4181FF;
box-sizing: border-box;
padding: 0 32px;
display: flex;
align-items: center;
box-sizing: border-box;
.left {
display: flex;
align-items: center;
& > span {
font-size: 40px;
font-weight: 500;
color: #FFFFFF;
margin-right: 16px;
}
}
.right {
flex: 1;
height: 64px;
background: rgba(0, 0, 0, .2);
border-radius: 32px;
margin-left: 32px;
box-sizing: border-box;
padding: 0 32px;
display: flex;
align-items: center;
}
}
.job-list {
box-sizing: border-box;
padding: 0 32px 156px;
& > header {
box-sizing: border-box;
padding: 48px 0 32px;
display: flex;
align-items: center;
justify-content: space-between;
& > span {
font-size: 38px;
font-weight: 600;
color: #333333;
}
.right {
font-size: 28px;
font-weight: 400;
color: #666666;
display: flex;
align-items: center;
& > em {
color: #4181FF;
}
}
}
.card {
background: #FFFFFF;
box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.02);
border-radius: 16px;
margin-bottom: 24px;
.top {
box-sizing: border-box;
padding: 32px;
border-bottom: 1px solid #DDDDDD;
.title {
font-size: 36px;
font-weight: 600;
color: #333333;
line-height: 50px;
margin-bottom: 24px;
}
.job-content {
font-size: 32px;
font-weight: 400;
color: #999999;
line-height: 44px;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
margin-bottom: 24px;
}
.photo {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 4px;
& > img {
width: 204px;
height: 204px;
}
}
.info {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 24px;
.tag {
width: 144px;
height: 48px;
background: #42D784;
border-radius: 24px;
font-size: 28px;
font-weight: 400;
color: #FFFFFF;
line-height: 50px;
text-align: center;
}
.date {
font-size: 28px;
font-weight: 400;
color: #999999;
}
}
.post-info {
display: flex;
align-items: center;
justify-content: space-between;
.post {
font-size: 36px;
font-weight: 600;
color: #333333;
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin-right: 16px;
}
.salary {
font-size: 36px;
font-weight: 600;
color: #FF3521;
}
}
.require {
font-size: 32px;
font-weight: 400;
color: #999999;
margin-top: 24px;
}
}
.bottom {
height: 104px;
display: flex;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
padding: 0 32px;
.name {
font-size: 28px;
font-weight: 400;
color: #333333;
}
.right {
display: flex;
align-items: center;
font-size: 28px;
font-weight: 400;
color: #4181FF;
}
.company {
font-size: 28px;
font-weight: 400;
color: #333333;
line-height: 40px;
}
}
}
}
</style>

View File

@@ -0,0 +1,151 @@
<template>
<div class="wrapper">
<div class="card">
<div class="post-info">
<div class="post-name">
<span>{{ detail.title }}</span>
<span>{{ detail.salary }}</span>
</div>
<p>{{ detail.education }} | {{ detail.gender }} | {{ detail.age }}</p>
</div>
<div class="form">
<div class="label">招聘企业</div>
<div class="value">{{ detail.companyName }}</div>
</div>
<div class="form">
<div class="label">招聘联系人</div>
<div class="value">{{ detail.linkName }}</div>
</div>
<div class="form">
<div class="label">联系方式</div>
<div class="value phone" @click="phone">
<u-icon name="phone-fill" color="#4181FF" size="32" :custom-stype="{marginRight:'8px'}"></u-icon>
{{ detail.linkPhone }}
</div>
</div>
<template v-if="detail.remark">
<header>岗位要求</header>
<div class="post-require">{{ detail.remark }}
</div>
</template>
</div>
</div>
</template>
<script>
export default {
name: "compJob",
appName: "企业招工详情",
data() {
return {
id: null,
detail: {},
}
},
onLoad({id}) {
this.id = id;
this.getDetail();
},
methods: {
phone() {
uni.makePhoneCall({phoneNumber: this.detail.linkPhone});
},
getDetail() {
this.$instance.post("/app/appjob/detail", null, {
params: {id: this.id}
}).then(res => {
if (res?.data) {
this.detail = res.data;
}
})
}
},
onShareAppMessage() {
return {
title: "企业招工",
path: "/mods/AppJob/compJob?id=" + this.id
}
}
}
</script>
<style lang="scss" scoped>
.card {
padding: 32px 0 32px 32px;
background-color: #ffffff;
.post-info {
padding-right: 32px;
.post-name {
display: flex;
justify-content: space-between;
line-height: 56px;
& > span:first-child {
font-size: 40px;
font-weight: 600;
color: #333333;
}
& > span:last-child {
font-size: 36px;
font-weight: 600;
color: #FF3521;
flex-shrink: 0;
}
}
& > p {
font-size: 32px;
font-weight: 400;
color: #999999;
margin: 16px 0 32px;
}
}
.form {
height: 112px;
background: #FFFFFF;
border-bottom: 1px solid #DDDDDD;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid #DDDDDD;
padding-right: 32px;
.label {
font-size: 32px;
font-weight: 400;
color: #999999;
}
.value {
font-size: 32px;
font-weight: 400;
color: #333333;
}
.phone {
font-size: 28px;
color: #4181FF;
}
}
header {
font-size: 38px;
font-weight: 600;
color: #333333;
padding: 32px 0;
}
.post-require {
font-size: 32px;
font-weight: 400;
color: #333333;
line-height: 56px;
padding-right: 20px;
}
}
</style>

View File

@@ -0,0 +1,156 @@
<template>
<div class="padding">
<div class="card">
<div class="post-info">{{ detail.title }}
</div>
<div class="date">{{ detail.createTime }}</div>
<div class="form border">
<div class="label">求职联系人</div>
<div class="value">{{ detail.linkName }}</div>
</div>
<div class="form border">
<div class="label">联系方式</div>
<div class="value phone" @click="phone">
<u-icon name="phone-fill" color="#4181FF" size="32" :custom-stype="{marginRight:'8px'}"></u-icon>
{{ detail.linkPhone }}
</div>
</div>
<div class="form">
<div class="label">图片</div>
</div>
<div class="photo border">
<img :src="item.url" alt=""
v-for="(item,index) in detail.files" :key="index" @click="preview(index)">
</div>
<header>详细描述</header>
<div class="post-require">{{ detail.remark }}
</div>
</div>
</div>
</template>
<script>
export default {
name: "persJob",
appName:"个人求职详情",
data() {
return {
id: null,
detail: {},
}
},
onLoad({id}) {
this.id = id;
this.getDetail();
},
methods: {
preview(index) {
this.$previewImage(this.detail.files, index, "url");
},
phone() {
uni.makePhoneCall({phoneNumber: this.detail.linkPhone});
},
getDetail() {
this.$instance.post("/app/appjob/detail", null, {
params: {id: this.id}
}).then(res => {
if (res?.data) {
this.detail = res.data;
}
})
}
},
onShareAppMessage() {
return {
title: "个人求职",
path: "/mods/AppJob/persJob?id=" + this.id
}
}
}
</script>
<style lang="scss" scoped>
.padding {
min-height: 100%;
background-color: #ffffff;
.card {
padding: 32px 0 32px 32px;
background-color: #ffffff;
.post-info {
font-size: 40px;
font-weight: 600;
color: #333333;
line-height: 56px;
padding-right: 32px;
}
.date {
font-size: 32px;
font-weight: 400;
color: #999999;
margin: 16px 0 32px;
}
.form {
height: 112px;
background: #FFFFFF;
display: flex;
align-items: center;
justify-content: space-between;
padding-right: 32px;
.label {
font-size: 32px;
font-weight: 400;
color: #999999;
}
.value {
font-size: 32px;
font-weight: 400;
color: #333333;
}
.phone {
font-size: 28px;
color: #4181FF;
}
}
.border {
border-bottom: 1px solid #DDDDDD;
}
.photo {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 4px;
padding-bottom: 48px;
& > img {
width: 225px;
height: 225px;
}
}
header {
font-size: 38px;
font-weight: 600;
color: #333333;
padding: 32px 0;
}
.post-require {
font-size: 32px;
font-weight: 400;
color: #333333;
line-height: 56px;
padding-right: 20px;
}
}
}
</style>

View File

@@ -0,0 +1,158 @@
<template>
<div class="wrapper">
<div class="card">
<div class="form">
<em>*</em>
<label>标题</label>
</div>
<u-input type="textarea" trim placeholder="请输入标题" maxlength="100" v-model="form.title"
placeholder-style="color: #999999;font-size: 17px;font-weight:normal;"
:custom-style="{color:'#333',fontSize:'17px',paddingLeft:'12px'}"/>
<div class="form border-top">
<em>*</em>
<label>详细描述</label>
</div>
<u-input type="textarea" trim placeholder="请输入详细描述信息…" maxlength="500" v-model="form.remark"
placeholder-style="color: #999999;font-size: 17px;font-weight:normal;"
:custom-style="{color:'#333',fontSize:'17px',paddingLeft:'12px'}"/>
</div>
<div class="card" style="padding-bottom: 20px">
<div class="form">
<label>图片上传
<span>(最多9张)</span>
</label>
</div>
<AiUploader :limit="9" v-model="form.files"></AiUploader>
</div>
<div class="card">
<div class="form border">
<em>*</em>
<label>联系人</label>
<div class="right">
<u-input trim placeholder="请输入" input-align="right"
placeholder-style="color:#999;font-size: 17px;font-weight:normal;" v-model="form.linkName"
:custom-style="{fontWeight:600,color:'#333',fontSize:'17px'}"></u-input>
</div>
</div>
<div class="form">
<em>*</em>
<label>联系方式</label>
<div class="right">
<u-input trim placeholder="请输入" input-align="right"
placeholder-style="color:#999;font-size: 17px;font-weight:normal;" v-model="form.linkPhone"
:custom-style="{fontWeight:600,color:'#333',fontSize:'17px'}"></u-input>
</div>
</div>
</div>
<div class="btn-wrapper">
<div class="btn" @click="submit" hover-class="text-hover">提交</div>
</div>
</div>
</template>
<script>
export default {
name: "pubJob",
appName: "我要找工作",
data() {
return {
form: {
title: "",
remark: "",
files: [],
linkName: "",
linkPhone: "",
type: 1,
},
flag: false
}
},
methods: {
submit() {
if (!!!this.form.title) return this.$u.toast("请输入标题");
if (!!!this.form.remark) return this.$u.toast("请输入详细描述");
if (!!!this.form.linkName) return this.$u.toast("请输入联系人");
if (!!!this.form.linkPhone) return this.$u.toast("请输入联系方式");
if (this.flag) return
this.flag = true
this.$loading()
this.$instance.post("/app/appjob/addOrUpdate", {
...this.form
}).then(res => {
this.$hideLoading()
this.flag = false
if (res.code == 0) {
this.$u.toast("提交成功");
setTimeout(_ => {
uni.navigateBack();
}, 500)
}
})
}
},
}
</script>
<style lang="scss" scoped>
.wrapper {
padding-bottom: 150px;
}
.card {
box-sizing: border-box;
padding-left: 32px;
background-color: #fff;
margin-bottom: 24px;
.form {
height: 112px;
background: #FFFFFF;
display: flex;
align-items: center;
& > em {
width: 16px;
height: 44px;
font-weight: 400;
color: #FF4466;
line-height: 54px;
font-style: normal;
margin-right: 8px;
}
& > label {
font-size: 32px;
font-weight: 600;
color: #666666;
& > span {
font-size: 28px;
font-weight: 400;
color: #999999;
}
}
.right {
flex: 1;
display: flex;
align-items: center;
flex-direction: row-reverse;
margin-right: 32px;
.value {
font-size: 34px;
font-weight: 600;
color: #333333;
}
}
}
.border-top {
border-top: 1px solid #DDDDDD;
}
.border {
border-bottom: 1px solid #DDDDDD;
}
}
</style>

View File

@@ -0,0 +1,110 @@
<template>
<div class="padding" v-if="pageShow">
<header>{{ detail.title }}</header>
<div class="info">
<span>{{ detail.publishUnitName }} {{ detail.createTime && detail.createTime.slice(0, 16) }}</span>
<div class="right">
<em>{{ detail.views }}</em>人看过
</div>
</div>
<div class="notice-content">
<u-parse :html="detail.content"/>
</div>
<div class="photo">
<img :src="item.url" alt="" v-for="(item,index) in images" :key="index" @click="preview(index)">
</div>
</div>
</template>
<script>
export default {
name: "AppNotice",
appName:"通知公告",
data() {
return {
id: null,
pageShow: false,
detail: {},
images: [],
}
},
onLoad({id}) {
this.$loading()
this.id = id;
this.getDetail();
},
methods: {
preview(index) {
this.$previewImage(this.images, index, 'path');
},
getDetail() {
this.$instance.post("/app/appmininotice/queryDetailById", null, {
params: {id: this.id}
}).then(res => {
if (res?.data) {
this.detail = res.data;
this.images = JSON.parse(res.data.images || '[]');
this.$nextTick(() => {
this.pageShow = true
})
}
this.$hideLoading()
})
}
},
}
</script>
<style lang="scss" scoped>
.padding {
min-height: 100%;
box-sizing: border-box;
padding: 40px 32px;
background-color: #fff;
header {
font-size: 48px;
font-weight: 600;
color: #333333;
line-height: 66px;
}
.info {
display: flex;
justify-content: space-between;
font-size: 30px;
font-weight: 400;
color: #999999;
padding: 16px 0 64px;
.right {
display: flex;
flex-shrink: 0;
margin-left: 16px;
& > em {
font-style: normal;
color: #4181FF;
}
}
}
.notice-content {
font-size: 28px;
// color: #333;
// line-height: 64px;
}
.photo {
display: flex;
flex-direction: column;
& > img {
width: 100%;
margin-top: 32px;
}
}
}
</style>

View File

@@ -0,0 +1,217 @@
<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 || require('../../../static/img/police.png')"
@click="preview(index)"
alt="">
<div class="right">
<span class="user-name">{{ item.name }}</span>
<span class="state">驻村辅警</span>
<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
}
},
onLoad() {
this.$loading()
this.areaId = this.$areaId
this.areaName = this.$areaName
this.$nextTick(() => {
this.getList()
})
},
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>

View File

@@ -0,0 +1,240 @@
<template>
<div class="news">
<div class="header">
<div class="header-search">
<u-icon name="search" class="icon-search" size="40" color="rgba(255,255,255,0.5)"></u-icon>
<input placeholder="请输入标题" v-model="title" @confirm="onConfirm" confirm-type="search"
placeholder-style="color:rgba(255,255,255,0.5);">
</div>
</div>
<div class="topic-list">
<div class="topic-item" v-for="(item, index) in list" :key="index" hover-class="bg-hover"
@click="$linkTo(`./detail?id=${item.id}`)">
<div class="topic-item__left">
<h2>{{ item.title }}</h2>
<p>{{ item.publishTime }}</p>
</div>
<image :src="item.thumbUrl" mode="aspectFill"/>
</div>
</div>
<div class="loading">
<u-loadmore :status="loadingStatus"/>
</div>
</div>
</template>
<script>
export default {
name:"AppTopic",
appName:"热点话题",
data() {
return {
title: '',
isLoading: false,
list: [],
isShowEmpty: false,
isMore: false,
current: 0,
areaId: '',
loadingStatus: 'loadmore'
}
},
onLoad() {
this.areaId = uni.getStorageSync('areaId')
this.getList(uni.getStorageSync('areaId'))
},
methods: {
onConfirm() {
this.loadingStatus = 'loadmore'
this.current = 0
this.$loading()
this.$nextTick(() => {
this.getList(this.areaId)
})
},
getList(areaId) {
if (this.loadingStatus === 'loading' || this.loadingStatus === 'nomore') return
this.loadingStatus = 'loading'
this.$instance.post(`/app/apphotsubject/listForWx?current=${this.current + 1}&size=10&status=1&title=${this.title}`, null, {
withoutToken: 1
}).then(res => {
if (res.code === 0) {
if (this.current === 0) {
this.list = []
}
const data = res.data.records
this.list.push(...data)
this.current = this.current + 1
this.loadingStatus = 'loadmore'
if (!res.data.records.length || res.data.records.length < 10) {
this.loadingStatus = 'nomore'
}
} else {
this.loadingStatus = 'loadmore'
}
}).catch(() => {
this.loadingStatus = 'loadmore'
})
},
toDetail(id) {
this.$linkTo(`./newsDetail?id=${id}&areaId=${this.areaId}`)
}
},
onReachBottom() {
this.getList(this.areaId)
}
}
</script>
<style lang="scss" scoped>
.news {
min-height: 100vh;
background: #F3F6F9;
padding-bottom: 40px;
}
.loading {
margin-top: 40px;
}
.topic-item {
display: flex;
width: 686px;
height: 208px;
margin: 32px auto 0;
padding: 32px;
background: #FFFFFF;
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.02);
border-radius: 8px;
overflow: hidden;
.topic-item__left {
flex: 1;
margin-right: 32px h2 {
height: 88px;
line-height: 44px;
margin-bottom: 16px;
color: #333333;
font-size: 32px;
text-align: justify;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
p {
color: #999999;
font-size: 28px;
}
}
image {
flex-shrink: 1;
width: 192px;
height: 144px;
}
}
div {
box-sizing: border-box;
}
.noMore {
line-height: 90px;
text-align: center;
color: #999;
font-size: 26px;
}
.topic-list {
padding-top: 112px;
}
.header {
position: fixed;
top: 0;
left: 0;
z-index: 11;
width: 100%;
height: 112px;
padding: 20px 0 0 0;
background: #4181FF;
.header-search {
display: flex;
align-items: center;
width: 690px;
height: 60px;
margin: 0 auto8px;
padding: 032px;
background: rgba(0, 0, 0, .2);
border-radius: 30px;
.icon-search {
flex-shrink: 1;
width: 32px;
height: 32px;
margin-right: 16px;
}
input {
flex: 1;
height: 100%;
font-size: 28px;
color: #fff;
}
}
.header-tab {
display: flex;
justify-content: center;
height: 80px;
padding-top: 16px;
background: #2D80FB;
span {
margin-right: 50px;
padding-bottom: 24px;
font-size: 28px;
color: #fff;
border-bottom: 4px solid transparent;
&:last-child {
margin-right: 0;
}
&.active {
color: #fff;
border-bottom: 4px solid #fff;
}
}
}
}
.no-more {
margin-top: 20px;
text-align: center;
color: #999;
image {
width: 400px;
height: 240px;
}
p {
text-align: center;
color: #999;
font-size: 28px;
}
}
</style>

View File

@@ -0,0 +1,205 @@
<template>
<div class="topic-detail" v-if="pageShow">
<div class="topic-header">
<h2>{{ info.title }}</h2>
<p>{{ info.publishTime }}</p>
<div class="topic-tags">
<span v-for="(item, index) in info.keyWords" :key="index">{{ item }}</span>
</div>
</div>
<div class="topic-list">
<div class="topic-item" v-for="(item, index) in info.contents" :key="index">
<div class="topic-item__top">
<image src="/static/img/rmht.png"/>
<div class="topic-item__top--right">
<h2>{{ item.question }}</h2>
<p>{{ item.questionSource }}</p>
</div>
</div>
<div class="topic-item__bottom">
<h2 v-if="item.answerSource">
<span style="color:#000;"> {{ item.answerSource }} </span>
回复
</h2>
<h2 v-else>话题回复</h2>
<p>{{ item.answer }}</p>
<div class="topic-item__img">
<image v-for="(img, i) in item.files" :key="i" :src="img.url" mode="aspectFill" hover-class="text-hover"
@click="preview(img.url, item.files)"/>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
appName: "话题详情",
data() {
return {
info: {},
id: '',
pageShow: false
}
},
onLoad(query) {
this.$loading()
this.id = query.id
this.getInfo()
},
methods: {
getInfo() {
this.$instance.post(`/app/apphotsubject/detailForWx?id=${this.id}`).then(res => {
if (res.code === 0) {
this.info = res.data
if (res.data.keyWords) {
this.info.keyWords = res.data.keyWords.split(',')
}
this.$nextTick(() => {
this.pageShow = true
})
this.$hideLoading()
}
})
},
preview(img, imgs) {
uni.previewImage({
current: img,
urls: imgs.map(v => v.url)
})
}
},
onShareAppMessage() {
return {
title: this.info.title,
path: `/mods/AppTopic/detail?id=${this.id}`
}
}
}
</script>
<style lang="scss" scoped>
.topic-detail {
* {
box-sizing: border-box;
}
.topic-list {
margin-top: 16px;
}
.topic-item__bottom {
margin-top: 22px;
padding: 24px 24px;
background: #FFFFFF;
border-radius: 16px;
border: 1px solid #D8DDE6;
.topic-item__img {
margin-top: 16px;
font-size: 0;
image {
width: 206px;
height: 206px;
margin: 0 10px 10px 0;
border-radius: 8px;
&:nth-of-type(3n) {
margin-right: 0;
}
}
}
p {
color: #333333;
font-size: 32px;
text-align: justify;
}
h2 {
margin-bottom: 16px;
color: #1365DD;
font-size: 26px;
}
}
.topic-item {
margin-bottom: 16px;
padding: 32px;
background: #fff;
.topic-item__top--right {
flex: 1;
h2 {
line-height: 1.3;
margin-bottom: 16px;
font-size: 32px;
color: #333;
text-align: justify;
white-space: pre-line;
}
p {
color: #343D65;
font-size: 28px;
}
}
.topic-item__top {
display: flex;
image {
position: relative;
top: 6px;
width: 32px;
height: 32px;
margin-right: 16px;
}
}
}
.topic-header {
padding: 32px 32px 16px;
background: #FFFFFF;
border-bottom: 1px solid #D8DDE6;
.topic-tags {
font-size: 0;
span {
display: inline-block;
height: 48px;
line-height: 48px;
margin: 0 16px 16px 0;
padding: 016px;
color: #6179A7;
font-size: 28px;
background: #F4F5FA;
border-radius: 24px;
}
}
h2 {
line-height: 1.3;
margin-bottom: 16px;
font-size: 40px;
color: #333333;
text-align: justify;
}
p {
margin-bottom: 16px;
color: #999999;
font-size: 28px;
}
}
}
</style>

View File

@@ -0,0 +1,98 @@
<template>
<div class="info" v-if="pageShow">
<h2>{{ info.title }}</h2>
<div class="info-info">
<span>{{ info.areaName }}</span>
<span>{{ info.createDate }}</span>
</div>
<image class="banner" @click="preview(banner)" v-if="banner" mode="widthFix" :src="banner"/>
<div class="rich-content">
<u-parse :html="info.content"></u-parse>
</div>
<AiEmpty v-if="!info.title"></AiEmpty>
</div>
</template>
<script>
export default {
name: "AppVillagerInfo",
appName: "本村简介",
data() {
return {
pageShow: false,
info: {},
banner: ''
}
},
onLoad(query) {
if (query.type !== '0') {
uni.setNavigationBarTitle({
title: '村规民约'
})
}
this.$loading()
this.getInfo(query.type)
},
methods: {
getInfo(type) {
this.$instance.post(`/app/appcountrysidetourism/queryDetailByAreaIdForWX?areaId=${uni.getStorageSync('areaId')}&type=${type}`).then(res => {
if (res.code === 0 && res.data) {
this.info = res.data
this.banner = res.data.thumbUrl ? JSON.parse(res.data.thumbUrl)[0].url : ''
}
this.$nextTick(() => {
this.pageShow = true
})
})
},
preview(url) {
uni.previewImage({
urls: [url],
current: url
})
}
}
}
</script>
<style lang="scss" scoped>
.info {
min-height: 100vh;
padding: 0 32px 40px;
box-sizing: border-box;
background-color: #fff;
.banner {
width: 100%;
margin-bottom: 20px;
}
h2 {
line-height: 1.3;
padding: 32px 0 16px;
font-size: 48px;
font-weight: 600;
color: #333;
}
.info-info {
display: flex;
align-items: center;
margin-bottom: 30px;
span {
color: #999999;
font-size: 30px;
&:last-child {
margin-left: 32px;
}
}
}
}
</style>