提交 50c5e543 authored 作者: 王鹏飞's avatar 王鹏飞

校友圈2.0

上级 fc09a94c
......@@ -22,10 +22,10 @@
"vue-router": "^3.1.6"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.3.1",
"@vue/cli-plugin-eslint": "~4.3.1",
"@vue/cli-plugin-router": "~4.3.1",
"@vue/cli-service": "~4.3.1",
"@vue/cli-plugin-babel": "~4.4.1",
"@vue/cli-plugin-eslint": "~4.4.1",
"@vue/cli-plugin-router": "~4.4.1",
"@vue/cli-service": "~4.4.1",
"@vue/eslint-config-prettier": "^6.0.0",
"babel-eslint": "^10.0.3",
"babel-plugin-import": "^1.13.0",
......
......@@ -8,7 +8,7 @@
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover"
/>
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
<title>紫荆校友</title>
<title>紫荆校友</title>
<script>
;(function(win, doc) {
function resizeRoot() {
......
......@@ -152,3 +152,100 @@ export function getComment(id, params) {
params
})
}
// 获取活动列表
export function getActivityList(params) {
return httpRequest.get('/api/alumni/v1/activities2/list', { params })
}
// 获取活动详情
export function getActivityDetail(id) {
return httpRequest.get(`/api/alumni/v1/activities/${id}`)
}
// 创建活动
export function addActivity(data) {
return httpRequest.post('/api/alumni/v1/activities2/add', data)
}
// 更新活动
export function updateActivity2(id, data) {
return httpRequest.post(`/api/alumni/v1/activities2/edit/${id}`, data)
}
// 获取组织列表
export function getGroupList(params) {
return httpRequest.get('/api/alumni/v1/organization/list', { params })
}
// 获取组织详情
export function getGroup(id) {
return httpRequest.get(`/api/alumni/v1/organization/detail/${id}`)
}
// 创建组织
export function addGroup(data) {
return httpRequest.post('/api/alumni/v1/organization/add', data)
}
// 更新组织
export function updateGroup(id, data) {
return httpRequest.post(`/api/alumni/v1/organization/edit/${id}`, data)
}
// 加入组织
export function joinGroup(id) {
return httpRequest.post(`/api/alumni/v1/organization/join/${id}`)
}
// 退出组织
export function leaveGroup(id) {
return httpRequest.post(`/api/alumni/v1/organization/cancel/${id}`)
}
// 获取组织内的活动
export function getActivitesByGroup(groupId, params) {
return httpRequest.get(`/api/alumni/v1/activities2/inorg/${groupId}`, {
params
})
}
// 获取成员列表
export function getMemberList(params) {
return httpRequest.get('/api/alumni/v1/student/list', { params })
}
// 获取我的信息
export function getMy() {
return httpRequest.get('/api/alumni/v1/student/total')
}
// 获取我参与的组织
export function getJoinedGroupes() {
return httpRequest.get('/api/alumni/v1/organization/joined')
}
// 获取我创建的组织
export function getMyGroupes() {
return httpRequest.get('/api/alumni/v1/organization/my')
}
// 获取我参与的活动
export function getJoinedActivities() {
return httpRequest.get('/api/alumni/v1/activities2/joined')
}
// 获取我的审批
export function getMyApproves() {
return httpRequest.get('/api/alumni/v1/activities2/check/list')
}
// 审核活动
export function updateActivityStatus(id, data) {
return httpRequest.post(`/api/alumni/v1/activities2/check/${id}`, data)
}
// 获取消息列表
export function getMessageList(params) {
return httpRequest.get('/api/alumni/v1/student/messages', { params })
}
......@@ -121,19 +121,34 @@ body {
color: #fff;
background: linear-gradient(
180deg,
rgba(255, 155, 150, 1) 0%,
rgba(206, 62, 58, 1) 100%
rgba(255, 201, 44, 1) 0%,
rgba(255, 116, 42, 1) 100%
);
border-radius: 5px;
border-radius: 20px;
cursor: pointer;
}
.submit-button {
display: block;
width: 100%;
height: 40px;
line-height: 40px;
text-align: center;
color: #fff;
background: linear-gradient(
180deg,
rgba(255, 201, 44, 1) 0%,
rgba(255, 116, 42, 1) 100%
);
border-radius: 20px;
cursor: pointer;
}
.empty {
margin-top: 45px;
padding-top: 130px;
font-size: 15px;
color: #333;
background: url('~@/assets/img/icon_warning.png') no-repeat center top;
background-size: 93px 93px;
margin-top: 50px;
padding-top: 170px;
font-size: 14px;
color: #999;
background: url('~@/assets/img/icon_empty.png') no-repeat center top;
background-size: 180px auto;
text-align: center;
}
.form-tips {
......@@ -142,16 +157,21 @@ body {
color: #999;
}
.form {
padding: 0 14px 30px;
padding: 0 0 40px;
}
.form .submit-button {
margin-top: 20px;
}
.form .van-cell {
flex-direction: column;
padding: 10px 0;
}
.form input.van-field__control,
.form textarea.van-field__control {
height: 40px;
padding: 0 20px;
border: 1px solid #999;
padding: 0 10px;
border: 1px solid #ccc;
border-radius: 6px;
}
.form .van-field__label {
margin-bottom: 10px;
......@@ -169,14 +189,22 @@ body {
overflow: hidden;
}
#app {
padding-bottom: env(safe-area-inset-bottom);
[class*='van-hairline']::after {
border-color: #f1f1f1;
}
.van-tabs__line {
background-color: #ff6767;
}
.van-popup--bottom {
padding-bottom: env(safe-area-inset-bottom);
}
body:before {
#app {
padding-bottom: env(safe-area-inset-bottom);
}
/* body:before {
width: 100%;
height: 100%;
content: ' ';
......@@ -185,4 +213,34 @@ body:before {
top: 0;
left: 0;
background: #fff;
} */
.main {
margin: 0 20px;
}
.main::after {
content: '';
height: 0;
line-height: 0;
display: block;
visibility: hidden;
clear: both;
}
.list {
overflow: hidden;
}
.red {
color: #f00;
}
.status-default {
color: #ffad3e !important;
}
.status-warning {
color: #b41010 !important;
}
.status-success {
color: #67c23a !important;
}
<template>
<div class="activity-item" @click="onClick">
<div class="activity-item-index" :class="topClass" v-if="showIndex">
<template v-if="!topClass">
{{ currentIndex }}
</template>
</div>
<div class="activity-item-pic" v-if="data.activity_image">
<img :src="data.activity_image" />
</div>
<div class="activity-item-main">
<div class="activity-item-title line-clamp">{{ data.activity_name }}</div>
<div class="activity-item-content">
<p class="activity-item-content__city">{{ data.activity_city }}</p>
<p class="activity-item-content__ft">
<span>{{ data.activity_time }}</span>
<span>{{ data.stu_nums }}人报名</span>
</p>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'ActivityItem',
props: {
data: Object,
index: Number,
showIndex: { type: Boolean, default: false }
},
computed: {
currentIndex() {
return this.index + 1
},
topClass() {
return this.currentIndex <= 3 ? `top${this.currentIndex}` : ''
}
},
methods: {
onClick() {
this.$router.push({ name: 'activityItem', params: { id: this.data.id } })
}
}
}
</script>
<style lang="scss" scoped>
.activity-item {
display: flex;
padding-bottom: 10px;
margin-bottom: 10px;
border-bottom: 1px solid #f5f5f5;
}
.activity-item-pic {
width: 120px;
height: 62px;
margin-right: 10px;
overflow: hidden;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.activity-item-main {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
overflow: hidden;
}
.activity-item-title {
font-size: 14px;
color: #222;
}
.activity-item-content {
p {
color: #999;
margin-top: 5px;
}
}
p.activity-item-content__city {
margin-top: 12px;
}
.activity-item-content__ft {
display: flex;
justify-content: space-between;
}
.activity-item-index {
width: 25px;
margin-right: 10px;
font-size: 14px;
color: #999;
line-height: 62px;
text-align: center;
}
.top1 {
background: url('~@/assets/img/top_01.png') no-repeat center;
background-size: contain;
}
.top2 {
background: url('~@/assets/img/top_02.png') no-repeat center;
background-size: contain;
}
.top3 {
background: url('~@/assets/img/top_03.png') no-repeat center;
background-size: contain;
}
</style>
<template>
<div class="activity-item" @click="onClick">
<div class="activity-item-main">
<div class="activity-item-title line-clamp">{{ data.activity_name }}</div>
<p class="activity-item-views">{{ data.views }}次浏览</p>
</div>
<div class="activity-item-pic" v-if="data.activity_image">
<img :src="data.activity_image" />
</div>
</div>
</template>
<script>
export default {
name: 'ActivityItem',
props: { data: Object },
methods: {
onClick() {
this.$router.push({ name: 'activityItem', params: { id: this.data.id } })
}
}
}
</script>
<style lang="scss" scoped>
.activity-item {
display: flex;
padding-bottom: 10px;
margin-bottom: 10px;
border-bottom: 1px solid #f1f1f1;
}
.activity-item-main {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
overflow: hidden;
}
.activity-item-title {
font-size: 14px;
color: #222;
}
.activity-item-views {
margin-top: 14px;
font-size: 12px;
color: #999;
}
.activity-item-pic {
width: 120px;
height: 78px;
margin-left: 10px;
overflow: hidden;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
</style>
<template>
<div class="list">
<van-list
v-model="loading"
:finished="finished"
@load="onLoad"
v-if="list.length"
>
<activity-item
v-for="(item, index) in list"
:data="item"
:index="index"
:show-index="showIndex"
:key="item.id"
></activity-item>
</van-list>
<div class="empty" v-else>暂时没有内容哦,去别处看看吧~</div>
</div>
</template>
<script>
import * as api from '@/api/index'
import ActivityItem from '@/components/ActivityItem'
export default {
components: { ActivityItem },
props: {
params: {
type: Object,
default() {
return {}
}
},
showIndex: { type: Boolean, default: false }
},
data() {
return {
list: [],
loading: false,
finished: false,
requestParams: { offset: 0, limit: 20 }
}
},
watch: {
params: {
immediate: true,
handler(value) {
this.requestParams = Object.assign({}, this.requestParams, value)
}
}
},
methods: {
getList() {
this.loading = true
api
.getActivityList(this.requestParams)
.then(response => {
if (response.length) {
this.list = this.list.concat(response)
}
this.loading = false
this.finished = response.length < this.requestParams.limit
})
.catch(() => {
this.loading = false
this.finished = true
})
},
onLoad() {
this.requestParams.offset =
this.requestParams.offset + this.requestParams.limit
this.getList()
},
// 刷新
refresh() {
this.requestParams.offset = 0
this.list = []
this.getList()
}
},
beforeMount() {
this.getList()
}
}
</script>
<template>
<div class="card">
<div class="card-hd">
<h3 class="card-hd__title">{{ title }}</h3>
<div class="card-hd__aside"><slot name="aside"></slot></div>
</div>
<div class="card-bd">
<slot></slot>
</div>
</div>
</template>
<script>
export default {
name: 'Card',
props: {
title: String
}
}
</script>
<style lang="scss">
.card {
}
.card-hd {
display: flex;
justify-content: space-between;
padding: 10px 0 20px;
}
.card-hd__title {
padding-bottom: 5px;
font-size: 16px;
font-weight: 600;
color: #333;
border-bottom: 3px solid #ff6767;
}
.card-bd {
}
</style>
......@@ -15,10 +15,16 @@
readonly
clickable
:border="false"
:required="false"
v-bind="item"
v-model="ruleForm[item.name]"
@click="showPicker(item)"
/>
>
<template #label>
{{ item.label }}
<span class="red" v-if="item.required">*</span>
</template>
</van-field>
</template>
<!-- 选择 -->
<template v-else-if="item.fieldType === 'select'">
......@@ -26,29 +32,45 @@
readonly
clickable
:border="false"
:value="getPickerValue(item.name, ruleForm[item.name])"
:required="false"
:value="ruleForm[item.name] | pickerValueText(item)"
v-bind="item"
@click="showPicker(item)"
/>
>
<template #label>
{{ item.label }}
<span class="red" v-if="item.required">*</span>
</template>
</van-field>
</template>
<!-- 上传图片 -->
<van-field
:border="false"
:required="false"
v-bind="item"
v-model="ruleForm[item.name]"
v-else-if="item.fieldType === 'uploader'"
>
<template #label>
{{ item.label }}
<span class="red" v-if="item.required">*</span>
</template>
<template #input>
<upload v-model="ruleForm[item.name]" :max-count="1" />
</template>
</van-field>
<!-- 上传图片 -->
<!-- 单选 -->
<van-field
:border="false"
:required="false"
v-bind="item"
v-model="ruleForm[item.name]"
v-else-if="item.fieldType === 'radio'"
>
<template #label>
{{ item.label }}
<span class="red" v-if="item.required">*</span>
</template>
<template #input>
<van-radio-group
v-model="ruleForm[item.name]"
......@@ -58,19 +80,25 @@
:name="item.name"
v-for="item in item.values"
:key="item.name"
>{{ item.text }}</van-radio
>
{{ item.text }}
</van-radio>
</van-radio-group>
</template>
</van-field>
<!-- 文本框 -->
<van-field
:border="false"
:required="false"
v-bind="item"
v-model="ruleForm[item.name]"
v-else
/>
>
<template #label>
{{ item.label }}
<span class="red" v-if="item.required">*</span>
</template>
</van-field>
<van-popup v-model="picker.visible" position="bottom">
<van-datetime-picker
type="datetime"
......@@ -78,18 +106,20 @@
:min-date="minDate"
@confirm="onTimePickerConfirm"
@cancel="picker.visible = false"
v-if="picker.type === 'datetime'"
v-if="picker.fieldType === 'datetime'"
/>
<van-picker
show-toolbar
:value-key="picker.labelKey"
:columns="picker.values"
@confirm="onPickerConfirm"
@cancel="picker.visible = false"
v-if="picker.type === 'select'"
v-if="picker.fieldType === 'select'"
/>
</van-popup>
</div>
</template>
<slot></slot>
</van-form>
</template>
......@@ -129,10 +159,11 @@ export default {
ruleForm: this.model,
picker: {
visible: false,
type: '',
fieldType: '',
name: '',
value: '',
valueKey: 'name',
valueKey: 'value',
labelKey: 'text',
values: [],
remote: null
},
......@@ -140,33 +171,42 @@ export default {
pickerActive: {}
}
},
filters: {
pickerValueText(value, field) {
if (!value || !field.values) {
return ''
}
const valueKey = field.valueKey || 'value'
const labelKey = field.labelKey || 'text'
const found = field.values.find(item => item[valueKey] === value)
return found ? found[labelKey] : ''
}
},
methods: {
getPickerValue(name, value) {
const field = this.fields.find(item => item.name === name)
const found = field.values.find(item => item[field.valueKey] === value)
return found ? found.text : ''
},
showPicker({ fieldType, name, remote, values = [], valueKey = 'name' }) {
this.picker.visible = true
this.picker.name = name
this.picker.type = fieldType
showPicker(field) {
this.picker = Object.assign(
{
visible: true,
fieldType: '',
name: '',
value: '',
valueKey: 'value',
labelKey: 'text',
values: [],
remote: null
},
field
)
this.picker.value = this.ruleForm[name]
if (fieldType === 'select') {
this.picker.valueKey = valueKey
this.picker.values = values
if (remote) {
this.picker.remote = remote
this.getSelectList(remote)
}
if (field.fieldType === 'select' && field.remote && !field.values) {
this.getPickerOptions(field)
}
},
onPickerConfirm(data) {
this.ruleForm[this.picker.name] = data[this.picker.valueKey]
this.picker.visible = false
if (this.picker.remote && this.picker.remote.change) {
this.pickerActive = this.pickerList.find(
item => item[this.picker.remote.valueKey] === data
)
this.pickerActive = data
}
},
onTimePickerConfirm(time) {
......@@ -178,14 +218,17 @@ export default {
submit() {
return this.$refs.form.submit()
},
getSelectList(remote) {
getPickerOptions(field) {
const remote = field.remote
if (!remote) {
return
}
remote.request(this.pickerActive).then(response => {
const data = response.data
this.pickerList = data
this.pickerColumns = data.map(item => item[remote.valueKey])
remote.method(this.pickerActive).then(response => {
if (remote.callback) {
response = remote.callback(response)
}
field.values = response
this.$set(this.picker, 'values', response)
})
}
}
......
<template>
<div class="group-item" @click="onClick">
<div class="group-item-index" :class="topClass" v-if="showIndex">
<template v-if="!topClass">
{{ currentIndex }}
</template>
</div>
<div class="group-item-pic" v-if="data.logo">
<img :src="data.logo" />
</div>
<div class="group-item-main">
<div class="group-item-title line-clamp">{{ data.org_name }}</div>
<div class="group-item-content">
<p class="group-item-content__num">
<template v-if="data.num">{{ data.num }}</template>
</p>
<p class="group-item-content__city">{{ data.org_city }}</p>
<p class="group-item-content__hot">{{ data.hot }}</p>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'GroupItem',
props: {
data: Object,
index: Number,
showIndex: { type: Boolean, default: false }
},
computed: {
currentIndex() {
return this.index + 1
},
topClass() {
return this.currentIndex <= 3 ? `top${this.currentIndex}` : ''
}
},
methods: {
onClick() {
this.$router.push({ name: 'groupItem', params: { id: this.data.id } })
}
}
}
</script>
<style lang="scss" scoped>
.group-item {
display: flex;
padding-bottom: 20px;
margin-bottom: 20px;
border-bottom: 1px solid #f5f5f5;
}
.group-item-pic {
width: 120px;
height: 62px;
margin-right: 10px;
overflow: hidden;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.group-item-main {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
overflow: hidden;
}
.group-item-title {
font-size: 14px;
color: #222;
}
.group-item-content {
display: flex;
color: #999;
}
.group-item-content__num {
flex: 1;
}
.group-item-content__city {
margin: 0 10px;
max-width: 60px;
overflow: hidden;
white-space: nowrap;
}
.group-item-index {
width: 25px;
margin-right: 10px;
font-size: 14px;
color: #999;
line-height: 62px;
text-align: center;
}
.top1 {
background: url('~@/assets/img/top_01.png') no-repeat center;
background-size: contain;
}
.top2 {
background: url('~@/assets/img/top_02.png') no-repeat center;
background-size: contain;
}
.top3 {
background: url('~@/assets/img/top_03.png') no-repeat center;
background-size: contain;
}
</style>
<template>
<div class="list">
<van-list
v-model="loading"
:finished="finished"
@load="onLoad"
v-if="list.length"
>
<group-item
v-for="(item, index) in list"
:data="item"
:index="index"
:show-index="showIndex"
:key="item.id"
></group-item>
</van-list>
<div class="empty" v-else>暂时没有内容哦,去别处看看吧~</div>
</div>
</template>
<script>
import * as api from '@/api/index'
import GroupItem from '@/components/GroupItem'
export default {
components: { GroupItem },
props: {
params: {
type: Object,
default() {
return {}
}
},
showIndex: { type: Boolean, default: false }
},
data() {
return {
list: [],
loading: false,
finished: false,
requestParams: { offset: 0, limit: 20 }
}
},
watch: {
params: {
immediate: true,
handler(value) {
this.requestParams = Object.assign({}, this.requestParams, value)
}
}
},
methods: {
getList() {
this.loading = true
api
.getGroupList(this.requestParams)
.then(response => {
if (response.length) {
this.list = this.list.concat(response)
}
this.loading = false
this.finished = response.length < this.requestParams.limit
})
.catch(() => {
this.loading = false
this.finished = true
})
},
onLoad() {
this.requestParams.offset =
this.requestParams.offset + this.requestParams.limit
this.getList()
},
// 刷新
refresh() {
this.requestParams.offset = 0
this.list = []
this.getList()
}
},
beforeMount() {
this.getList()
}
}
</script>
<template>
<div class="member-item">
<div class="member-item-pic">
<img :src="data.avatar" v-if="data.avatar" />
</div>
<slot name="member-before"></slot>
<div class="member-item-content">
<h4>{{ data.personal_name }}</h4>
<p>{{ data.class_name }}</p>
</div>
<slot name="member-after"></slot>
</div>
</template>
<script>
export default {
name: 'MemberItem',
props: { data: Object }
}
</script>
<style lang="scss" scoped>
.member-item {
display: flex;
margin-bottom: 20px;
}
.member-item-pic {
width: 40px;
height: 40px;
border-radius: 50%;
background-color: #ccc;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.member-item-content {
margin-left: 10px;
h4 {
font-size: 14px;
font-weight: 400;
color: #222;
}
p {
font-size: 14px;
color: #999;
}
}
</style>
<template>
<div class="list">
<van-list
v-model="loading"
:finished="finished"
@load="onLoad"
v-if="list.length"
>
<member-item
v-for="item in list"
:data="item"
:key="item.id"
></member-item>
</van-list>
<div class="empty" v-else>暂时没有内容哦,去别处看看吧~</div>
</div>
</template>
<script>
import * as api from '@/api/index'
import MemberItem from '@/components/MemberItem'
export default {
components: { MemberItem },
props: {
params: {
type: Object,
default() {
return {}
}
},
requestCallback: Function
},
data() {
return {
list: [],
loading: false,
finished: false,
requestParams: { offset: 0, limit: 20 }
}
},
watch: {
params: {
immediate: true,
handler(value) {
this.requestParams = Object.assign({}, this.requestParams, value)
}
}
},
methods: {
getList() {
this.loading = true
api
.getMemberList(this.requestParams)
.then(response => {
if (response.length) {
this.$emit('request-success', this.list.concat(response))
if (this.requestCallback) {
response = this.requestCallback(response)
}
this.list = this.list.concat(response)
}
this.loading = false
this.finished = response.length < this.requestParams.limit
})
.catch(() => {
this.loading = false
this.finished = true
})
},
onLoad() {
this.requestParams.offset =
this.requestParams.offset + this.requestParams.limit
this.getList()
},
// 刷新
refresh() {
this.requestParams.offset = 0
this.list = []
this.getList()
}
},
beforeMount() {
this.getList()
}
}
</script>
<template>
<div class="message-item">
<div class="message-item-pic" :class="`message-item-pic-${type}`"></div>
<div class="message-item-content">
<div class="message-item-content-hd">
<div class="message-item-content__title">{{ data.title }}</div>
<div class="message-item-content__time">{{ data.time }}</div>
</div>
<div class="message-item-content-bd">
<p>紫荆官方发布了一条新消息,点击查看</p>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'MessageItem',
props: { type: String, data: Object }
}
</script>
<style lang="scss" scoped>
.message-item {
display: flex;
padding-bottom: 20px;
margin-bottom: 20px;
border-bottom: 1px solid #f1f1f1;
}
.message-item-pic {
width: 40px;
height: 40px;
}
.message-item-pic-1 {
background-image: url('~@/assets/img/message_group_icon.png');
}
.message-item-pic-2 {
background-image: url('~@/assets/img/message_activity_icon.png');
}
.message-item-pic-3 {
background-image: url('~@/assets/img/message_settings_icon.png');
}
.meesage-item-content {
flex: 1;
margin-left: 10px;
}
</style>
<template>
<div class="my-activity-item" @click="onClick">
<div class="my-activity-item-bd">
<div class="my-activity-item-main">
<div class="my-activity-item-title">
{{ data.activity_demand_type_str }}
</div>
<div class="my-activity-item-content">
<p>
<b>地点:</b><span>{{ data.activity_city }}</span>
</p>
<p>
<b>时间:</b><span>{{ data.activity_time }}</span>
</p>
<p>
<b>主题:</b><span>{{ data.activity_name }}</span>
</p>
<p>
<b>审核状态:</b
><span :class="statusClass">{{ data.approve_status_str }}</span>
</p>
</div>
</div>
<div class="my-activity-item-pic" v-if="data.activity_image">
<img :src="data.activity_image" />
</div>
</div>
<div class="my-activity-item-ft">
<ul>
<!-- 审核的活动 -->
<template v-if="isCheck">
<li v-if="data.approve_status === '-1'">
<div
class="button default-button"
@click.stop="$emit('check', data)"
>
审核
</div>
</li>
<li v-else>
<div class="button default-button" @click.stop="onClick">详情</div>
</li>
</template>
<!-- 正常的活动 -->
<template v-else>
<li v-if="data.is_mine">
<div class="button default-button" @click.stop="onClick">管理</div>
</li>
<li v-else>
<div class="button default-button" @click.stop="onClick">详情</div>
</li>
</template>
<li>
<div
class="button default-button"
@click.stop="
$router.push({ name: 'activityMember', params: { id: data.id } })
"
>
成员列表
</div>
</li>
</ul>
</div>
</div>
</template>
<script>
export default {
name: 'MyActivityItem',
props: { data: Object, isCheck: Boolean },
computed: {
statusClass() {
const status = this.data.approve_status
return {
'status-default': status === '-1',
'status-success': status === '1' || status === '2',
'status-warning': status === '0'
}
}
},
methods: {
onClick() {
this.$router.push({ name: 'activityItem', params: { id: this.data.id } })
}
}
}
</script>
<style lang="scss" scoped>
.my-activity-item {
margin-bottom: 10px;
padding: 20px;
box-shadow: 0px 2px 8px 0px rgba(0, 0, 0, 0.05);
border-radius: 6px;
}
.my-activity-item-bd {
display: flex;
overflow: hidden;
}
.my-activity-item-main {
flex: 1;
}
.my-activity-item-title {
font-size: 15px;
color: #222;
}
.my-activity-item-content {
color: #999;
p {
margin-top: 10px;
display: flex;
b {
color: #999;
white-space: nowrap;
}
span {
margin-left: 5px;
flex: 1;
color: #222;
overflow: 1;
}
}
}
.my-activity-item-pic {
width: 100px;
height: 100px;
margin-left: 10px;
border-radius: 6px;
overflow: hidden;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.my-activity-item-ft {
margin-top: 20px;
ul {
display: flex;
justify-content: space-between;
}
.button {
width: 64px;
height: 30px;
text-align: center;
border-radius: 5px;
}
.default-button {
font-size: 12px;
color: #999;
line-height: 30px;
border: 1px solid #999;
}
.primary-button {
font-size: 12px;
color: #fff;
line-height: 30px;
background: linear-gradient(
180deg,
rgba(255, 201, 44, 1) 0%,
rgba(255, 116, 42, 1) 100%
);
}
}
</style>
<template>
<div class="list">
<van-list
v-model="loading"
:finished="finished"
@load="onLoad"
v-if="list.length"
>
<my-activity-item
v-for="item in list"
:data="item"
:key="item.id"
></my-activity-item>
</van-list>
<div class="empty" v-else>暂时没有内容哦,去别处看看吧~</div>
</div>
</template>
<script>
import * as api from '@/api/index'
import MyActivityItem from '@/components/MyActivityItem'
export default {
components: { MyActivityItem },
data() {
return {
list: [],
loading: false,
finished: false,
page: { offset: 0, limit: 10 }
}
},
methods: {
getList() {
this.loading = true
api
.getJoinedActivities(this.page)
.then(response => {
if (response.length) {
this.list = this.list.concat(response)
}
this.loading = false
this.finished = response.length < this.page.limit
})
.catch(() => {
this.loading = false
this.finished = true
})
},
onLoad() {
this.page.offset = this.page.offset + this.page.limit
this.getList()
}
},
beforeMount() {
this.getList()
}
}
</script>
<template>
<div class="list">
<van-list
v-model="loading"
:finished="finished"
@load="onLoad"
v-if="list.length"
>
<my-activity-item
v-for="item in list"
:data="item"
:isCheck="true"
:key="item.id"
@check="onCheck"
></my-activity-item>
</van-list>
<div class="empty" v-else>暂时没有内容哦,去别处看看吧~</div>
<!-- 审核 -->
<van-action-sheet
v-model="check.show"
cancel-text="取消"
:actions="check.actions"
@select="onSelect"
/>
</div>
</template>
<script>
import * as api from '@/api/index'
import MyActivityItem from '@/components/MyActivityItem'
export default {
components: { MyActivityItem },
props: {
params: {
type: Object,
default() {
return {}
}
}
},
data() {
return {
list: [],
loading: false,
finished: false,
requestParams: { offset: 0, limit: 20 },
// 审核
check: {
show: false,
data: null,
actions: [
{ name: '通过', value: '1' },
{ name: '拒绝', value: '0' }
]
}
}
},
watch: {
params: {
immediate: true,
handler(value) {
this.requestParams = Object.assign({}, this.requestParams, value)
}
}
},
methods: {
getList() {
this.loading = true
api
.getMyApproves(this.requestParams)
.then(response => {
if (response.length) {
this.list = this.list.concat(response)
}
this.loading = false
this.finished = response.length < this.requestParams.limit
})
.catch(() => {
this.loading = false
this.finished = true
})
},
onLoad() {
this.requestParams.offset =
this.requestParams.offset + this.requestParams.limit
this.getList()
},
// 刷新
refresh() {
this.requestParams.offset = 0
this.list = []
this.getList()
},
// 显示审核
onCheck(data) {
this.check.show = true
this.check.data = data
},
// 审核
onSelect(data) {
const activityId = this.check.data.id
api
.updateActivityStatus(activityId, { status: data.value })
.then(response => {
this.$dialog
.alert({
confirmButtonText: '确定',
message: response.message
})
.then(() => {
// 刷新列表
this.refresh()
})
})
.finally(() => {
this.check.show = false
})
}
},
beforeMount() {
this.getList()
}
}
</script>
<template>
<div class="my-group-item" @click="onClick">
<div class="my-group-item-bd">
<div class="my-group-item-main">
<div class="my-group-item-title line-clamp">{{ data.org_name }}</div>
<div class="my-group-item-content">
<p>
<b>地点:</b><span>{{ data.org_city }}</span>
</p>
<p>
<b>类型:</b><span>{{ data.org_type_str }}</span>
</p>
<p>
<b>宗旨:</b><span>{{ data.org_name }}</span>
</p>
<p>
<b>审核状态:</b
><span :class="statusClass">{{ data.approve_status_str }}</span>
</p>
</div>
</div>
<div class="my-group-item-pic" v-if="data.logo">
<img :src="data.logo" />
</div>
</div>
<div class="my-group-item-ft">
<ul>
<li><div class="button default-button">详情</div></li>
<li>
<div
class="button default-button"
@click.stop="
$router.push({ name: 'groupMember', params: { id: data.id } })
"
>
成员列表
</div>
</li>
<li>
<div
class="button primary-button"
@click.stop="
$router.push({ name: 'groupActivity', params: { id: data.id } })
"
>
活动
</div>
</li>
</ul>
</div>
</div>
</template>
<script>
export default {
name: 'Card',
props: {
data: Object,
index: Number,
showIndex: { type: Boolean, default: false }
},
computed: {
currentIndex() {
return this.index + 1
},
topClass() {
return this.currentIndex <= 3 ? `top${this.currentIndex}` : ''
},
statusClass() {
const status = this.data.approve_status
return {
'status-default': status === '-1',
'status-success': status === '1',
'status-warning': status === '0'
}
}
},
methods: {
onClick() {
this.$router.push({ name: 'groupItem', params: { id: this.data.id } })
}
}
}
</script>
<style lang="scss" scoped>
.my-group-item {
margin-bottom: 10px;
padding: 20px;
box-shadow: 0px 2px 8px 0px rgba(0, 0, 0, 0.05);
border-radius: 6px;
}
.my-group-item-bd {
display: flex;
// align-items: flex-start;
overflow: hidden;
}
.my-group-item-main {
flex: 1;
}
.my-group-item-title {
font-size: 15px;
color: #222;
}
.my-group-item-content {
color: #999;
p {
margin-top: 10px;
display: flex;
b {
color: #999;
white-space: nowrap;
}
span {
margin-left: 5px;
flex: 1;
color: #222;
overflow: 1;
}
}
}
.my-group-item-pic {
width: 100px;
height: 100px;
margin-left: 10px;
border-radius: 6px;
overflow: hidden;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.my-group-item-ft {
margin-top: 20px;
ul {
display: flex;
justify-content: space-between;
}
.button {
width: 64px;
height: 30px;
text-align: center;
border-radius: 5px;
}
.default-button {
font-size: 12px;
color: #999;
line-height: 30px;
border: 1px solid #999;
}
.primary-button {
font-size: 12px;
color: #fff;
line-height: 30px;
background: linear-gradient(
180deg,
rgba(255, 201, 44, 1) 0%,
rgba(255, 116, 42, 1) 100%
);
}
}
</style>
<template>
<div class="list">
<van-list
v-model="loading"
:finished="finished"
@load="onLoad"
v-if="list.length"
>
<my-group-item
v-for="item in list"
:data="item"
:key="item.id"
></my-group-item>
</van-list>
<div class="empty" v-else>暂时没有内容哦,去别处看看吧~</div>
</div>
</template>
<script>
import * as api from '@/api/index'
import MyGroupItem from '@/components/MyGroupItem'
export default {
components: { MyGroupItem },
data() {
return {
list: [],
loading: false,
finished: false,
page: { offset: 0, limit: 10 }
}
},
methods: {
getList() {
this.loading = true
api
.getJoinedGroupes(this.page)
.then(response => {
if (response.length) {
this.list = this.list.concat(response)
}
this.loading = false
this.finished = response.length < this.page.limit
})
.catch(() => {
this.loading = false
this.finished = true
})
},
onLoad() {
this.page.offset = this.page.offset + this.page.limit
this.getList()
}
},
beforeMount() {
this.getList()
}
}
</script>
<template>
<div class="search-bar">
<form @submit.prevent="onSearch">
<input
type="search"
class="search-input"
:placeholder="placeholder"
v-model="currentValue"
v-bind="$attrs"
@input="onChange"
ref="formInput"
/>
</form>
</div>
</template>
<script>
export default {
props: {
value: String,
focus: { type: Boolean, default: false },
placeholder: { type: String, default: '输入组织或校友姓名搜索' }
},
data() {
return {
currentValue: this.value,
debounced: null
}
},
watch: {
value(value) {
this.currentValue = value
}
},
computed: {
formInput() {
return this.$refs.formInput
}
},
methods: {
bindFocus() {
this.formInput.focus()
},
onChange() {
this.$emit('input', this.currentValue)
this.$emit('change', this.currentValue)
},
onSearch() {
this.$emit('search', this.currentValue)
}
},
mounted() {
this.bindFocus()
}
}
</script>
<style lang="scss">
.search-bar {
padding: 10px 0;
}
.search-input {
display: block;
width: 100%;
height: 32px;
line-height: 32px;
background: url('~@/assets/img/icon_search.png') no-repeat 22px center;
background-size: 16px;
padding-left: 50px;
border: 1px solid #f1f1f1;
border-radius: 16px;
}
</style>
<template>
<div class="tab-bar">
<div class="tab-bar-inner">
<ul class="tab-bar-list">
<li
class="tab-bar-item tab-bar-item__home"
:class="{ 'is-active': isActive('home') }"
@click="$router.push('home')"
>
首页
</li>
<li class="tab-bar-item" @click="$router.push('create')">
<div class="tab-bar-item-create">
<div class="tab-bar-item-create__icon"></div>
<div class="tab-bar-item-create__title">创建</div>
</div>
</li>
<li
class="tab-bar-item tab-bar-item__my"
:class="{ 'is-active': isActive('my') }"
@click="$router.push('my')"
>
我的
</li>
</ul>
</div>
</div>
</template>
<script>
export default {
data() {
return {}
},
methods: {
isActive(path) {
return this.$route.name === path
}
}
}
</script>
<style lang="scss">
.tab-bar {
height: 80px;
}
.tab-bar-inner {
position: fixed;
left: 0;
right: 0;
bottom: 0;
height: 50px;
background-color: #fff;
max-width: 750px;
margin: 0 auto;
box-shadow: 0px -8px 16px 0px rgba(0, 0, 0, 0.05);
}
.tab-bar-list {
display: flex;
}
.tab-bar-item {
flex: 1;
font-size: 12px;
color: #999;
text-align: center;
}
.tab-bar-item.is-active {
color: #ff6767;
}
.tab-bar-item-create {
margin: -20px auto 0;
}
.tab-bar-item-create__icon {
width: 60px;
height: 60px;
margin: 0 auto;
background: #fff url('~@/assets/img/tab_create.png') no-repeat center center;
background-size: 100%;
border-radius: 50%;
}
.tab-bar-item-create__title {
margin-top: -10px;
}
.tab-bar-item__home {
padding-top: 30px;
background: url('~@/assets/img/tab_home.png') no-repeat center 2px;
background-size: 27px auto;
}
.tab-bar-item__home.is-active {
background-image: url('~@/assets/img/tab_home_hover.png');
}
.tab-bar-item__my {
padding-top: 30px;
background: url('~@/assets/img/tab_my.png') no-repeat center 2px;
background-size: 23px auto;
}
.tab-bar-item__my.is-active {
background-image: url('~@/assets/img/tab_my_hover.png');
}
</style>
......@@ -64,9 +64,9 @@ export default {
<style lang="scss" scoped>
::v-deep .van-uploader__upload,
::v-deep .van-uploader__preview-image {
width: 150px;
height: 80px;
background-color: #e0e0e0;
width: 100px;
height: 100px;
background-color: #eee;
border-radius: 0;
}
::v-deep .van-uploader__upload-icon {
......
......@@ -53,6 +53,16 @@ Vue.use(Uploader)
import { List } from 'vant'
Vue.use(List)
import { IndexBar, IndexAnchor } from 'vant'
Vue.use(IndexBar)
Vue.use(IndexAnchor)
import { Area } from 'vant'
Vue.use(Area)
import { ActionSheet } from 'vant'
Vue.use(ActionSheet)
// 公共css
import '@/assets/css/base.css'
......
......@@ -12,26 +12,26 @@ const routes = [
component: () => import('@/views/Login.vue')
},
// 首页
{
name: 'index',
path: '/',
component: () => import('@/views/Index.vue')
},
// {
// name: 'index',
// path: '/',
// component: () => import('@/views/Index.vue')
// },
// 创建
{
path: '/create',
component: Layout,
children: [
{
name: 'create',
path: '',
component: () => import('@/views/Create.vue')
}
]
},
// {
// path: '/create',
// component: Layout,
// children: [
// {
// name: 'create',
// path: '',
// component: () => import('@/views/Create.vue')
// }
// ]
// },
// 详情
{
path: '/item/:id',
path: '/activity/item/:id',
component: Layout,
children: [
{
......@@ -64,6 +64,126 @@ const routes = [
component: () => import('@/views/Comment.vue')
}
]
},
// 首页
{
path: '/',
name: 'home',
component: () => import('@/views/home/Index.vue')
},
// 搜索
{
path: '/search',
name: 'search',
component: () => import('@/views/search/Index.vue')
},
// 创建
{
path: '/create',
name: 'create',
component: () => import('@/views/create/Index.vue')
},
// 创建组织
{
path: '/create/group',
name: 'createGroup',
component: () => import('@/views/create/Group.vue')
},
// 创建活动
{
path: '/create/activity',
name: 'createActivity',
component: () => import('@/views/create/Activity.vue')
},
// 我的
{
path: '/my',
name: 'my',
component: () => import('@/views/my/Index.vue')
},
// 我的消息
{
path: '/message',
name: 'message',
component: () => import('@/views/message/Index.vue')
},
// 消息列表
{
path: '/message/:type',
name: 'messageList',
component: () => import('@/views/message/List.vue')
},
// 消息详情
{
path: '/message/:type/:id',
name: 'messageItem',
component: () => import('@/views/message/Item.vue')
},
// 设置
{
path: '/settings',
name: 'settings',
component: () => import('@/views/settings/Index.vue')
},
// 我的组织
{
path: '/my/group',
name: 'myGroup',
component: () => import('@/views/my/MyGroup.vue')
},
// 我的活动
{
path: '/my/activity',
name: 'myActivity',
component: () => import('@/views/my/MyActivity.vue')
},
// 我的审批
{
path: '/my/approve',
name: 'myApprove',
component: () => import('@/views/my/MyApprove.vue')
},
// 活动列表
{
path: '/activity',
name: 'activity',
component: () => import('@/views/activity/Index.vue')
},
// 活动个详情
{
path: '/activity/:id',
name: 'activityItem',
component: () => import('@/views/activity/Item.vue')
},
// 活动成员列表
{
path: '/activity/:id/member',
name: 'activityMember',
component: () => import('@/views/activity/Member.vue')
},
// 组织列表
{
path: '/group',
name: 'group',
component: () => import('@/views/group/Index.vue')
},
// 组织详情
{
path: '/group/:id',
name: 'groupItem',
component: () => import('@/views/group/Item.vue')
},
// 组织成员列表
{
path: '/group/:id/member',
name: 'groupMember',
component: () => import('@/views/group/Member.vue')
},
// 组织活动列表
{
path: '/group/:id/activity',
name: 'groupActivity',
component: () => import('@/views/group/Activity.vue')
}
]
......
......@@ -56,8 +56,8 @@ export default {
const UA = navigator.userAgent.toLowerCase()
return {
ruleForm: {
account: '13811534871',
password: '123456',
account: '',
password: '',
RememberMe: false
},
passwordVisible: false,
......@@ -148,10 +148,9 @@ export default {
}
},
created() {
this.onSubmit()
// if (this.isWechat && !this.checkWechatLogin()) {
// this.wechatLogin()
// }
if (this.isWechat && !this.checkWechatLogin()) {
this.wechatLogin()
}
}
}
</script>
......
<template>
<div class="main">
<!-- 搜索 -->
<search-bar readonly @click.native="onSearch"></search-bar>
<card :title="title">
<activity-list :show-index="!type" :params="{ type }"></activity-list>
</card>
</div>
</template>
<script>
// components
import SearchBar from '@/components/SearchBar'
import Card from '@/components/Card'
import ActivityList from '@/components/ActivityList'
export default {
name: 'ActivityIndex',
components: { SearchBar, Card, ActivityList },
data() {
return {}
},
computed: {
type() {
return this.$route.query.type
},
title() {
const typeMap = {
1: '公益行',
2: '去游学',
3: '直播课',
4: '找工作',
5: '运动家'
}
return typeMap[this.type] || '活动热度榜'
}
},
methods: {
onSearch() {
this.$router.push({ name: 'search', query: { tab: '2' } })
}
}
}
</script>
<style lang="scss"></style>
<template>
<div class="detail">
<!-- 标题 -->
<div class="detail-title">
<h1>{{ detail.activity_name }}</h1>
</div>
<!-- 作者 -->
<div class="detail-user" v-if="detail.initiator">
<div class="detail-user__pic">
<img :src="detail.initiator.avatar | avatar" />
</div>
<div class="detail-user__content">
<p>{{ detail.initiator.nickname }}</p>
<p>{{ datetimeText }}</p>
</div>
<div class="detail-user__tool" v-if="canJoin">
<span class="join-button" v-if="detail.has_joined">已报名</span>
<span
class="join-button"
@click="$router.push({ name: 'join', params: { id: pid } })"
v-else
>报名</span
>
</div>
</div>
<!-- 封面 -->
<div class="detail-pic" v-if="detail.activity_image">
<img :src="detail.activity_image" />
</div>
<!-- 内容 -->
<div class="detail-content" v-html="contentHtml"></div>
<div class="detail-form" v-if="detail.activity_type === '10'">
<div class="detail-form__item" v-if="detail.activity_time">
<div class="detail-form__label">
<span class="detail-form-icon detail-form-icon__clock"></span>
时间:
</div>
<div class="detail-form__content">{{ detail.activity_time }}</div>
</div>
<div class="detail-form__item" v-if="detail.activity_address">
<div class="detail-form__label">
<span class="detail-form-icon detail-form-icon__address"></span>
地点:
</div>
<div class="detail-form__content">{{ detail.activity_address }}</div>
</div>
<!-- <div class="detail-form__item" v-if="detail.participator_limit">
<div class="detail-form__label">
<span class="detail-form-icon detail-form-icon__peoples"></span>
希望人数:
</div>
<div class="detail-form__content">
{{ detail.participator_limit }}
</div>
</div> -->
</div>
<!-- 评论 -->
<div class="detail-comments" v-if="hasComment">
<comment-list
relatedType="1"
:activityId="pid"
:data="commentList"
@update="getCommentList"
></comment-list>
</div>
</div>
</template>
<script>
import CommentList from '@/components/CommentList'
import * as api from '@/api/index'
import { format } from 'timeago.js'
export default {
components: { CommentList },
metaInfo: {
title: '紫荆校友圈'
},
data() {
return {
detail: {
activity_contents: ''
},
commentList: []
}
},
computed: {
pid() {
return this.$route.params.id
},
datetimeText() {
return format(this.detail.created_time, 'zh_CN')
},
isPass() {
return this.detail.approve_status === '1'
},
isMyPublished() {
return !!this.detail.my_published
},
hasComment() {
return this.detail.comment_switch === '1'
},
contentHtml() {
const content = this.detail.activity_contents || ''
return content.replace(/\r\n|\n/gi, '<br />')
},
canJoin() {
return (
this.isPass && !this.isMyPublished && this.detail.activity_type === '10'
)
}
},
methods: {
// 详情
getDetail() {
const toast = this.$toast.loading({
message: '加载中...',
forbidClick: true,
duration: 0
})
api
.getActivity(this.pid)
.then(response => {
this.detail = response
toast.clear()
})
.catch(toast.clear)
},
// 热门评论
getCommentList() {
api.getCommentList(this.pid).then(response => {
this.commentList = response
})
}
},
beforeMount() {
this.getDetail()
this.getCommentList()
}
}
</script>
<style lang="scss" scoped>
.detail {
padding: 10px 20px;
}
.detail-pic {
margin-left: -20px;
margin-right: -20px;
margin-top: 20px;
img {
width: 100%;
}
}
.detail-user {
display: flex;
align-items: center;
margin-top: 10px;
}
.detail-user__pic {
width: 40px;
height: 40px;
background-color: #ccc;
border-radius: 50%;
overflow: hidden;
img {
width: 100%;
height: 100%;
}
}
.detail-user__content {
flex: 1;
padding-left: 20px;
p {
font-size: 13px;
color: #999;
}
}
.join-button {
display: inline-block;
height: 30px;
padding: 0 20px;
line-height: 30px;
color: #fff;
background: linear-gradient(
180deg,
rgba(255, 201, 44, 1) 0%,
rgba(255, 116, 42, 1) 100%
);
box-shadow: 0px 5px 20px 0px rgba(253, 3, 20, 0.3);
border-radius: 20px;
cursor: pointer;
}
.detail-title {
h1 {
font-size: 18px;
color: #333;
line-height: 26px;
}
}
.detail-content {
margin-top: 10px;
font-size: 15px;
color: #222;
line-height: 30px;
p {
font-size: 14px;
color: #222;
line-height: 30px;
text-indent: 2em;
}
}
.detail-form__item {
display: flex;
align-items: flex-start;
margin-top: 20px;
line-height: 20px;
}
.detail-form__label {
display: flex;
}
.detail-form__content {
flex: 1;
overflow: hidden;
}
.detail-form-icon {
display: inline-block;
width: 20px;
height: 20px;
margin-right: 10px;
}
.detail-form-icon__clock {
background: url('~@/assets/img/icon_clock.png') no-repeat center;
background-size: contain;
}
.detail-form-icon__address {
background: url('~@/assets/img/icon_address.png') no-repeat center;
background-size: contain;
}
.detail-form-icon__peoples {
background: url('~@/assets/img/icon_peoples.png') no-repeat center;
background-size: contain;
}
</style>
<template>
<div class="main">
<card title="成员列表"> </card>
</div>
</template>
<script>
import Card from '@/components/Card'
import * as api from '@/api'
export default {
name: 'ActivityMember',
components: { Card },
data() {
return {
detail: null
}
},
computed: {
pid() {
return this.$route.params.id
}
},
methods: {
getDetail() {
api.getMemberList({ offset: 0, limit: 100 }).then(response => {
this.detail = response
})
}
},
beforeMount() {
this.getDetail()
}
}
</script>
<style lang="scss" scoped>
.info-item {
margin-bottom: 20px;
display: flex;
}
.info-item__label {
width: 70px;
color: #999;
text-align: center;
}
.info-item__content {
flex: 1;
color: #222;
overflow: hidden;
margin-left: 20px;
}
.button {
width: 128px;
height: 30px;
margin: 0 auto;
line-height: 30px;
color: #fff;
text-align: center;
background: linear-gradient(
180deg,
rgba(2, 236, 228, 1) 0%,
rgba(18, 186, 244, 1) 100%
);
border-radius: 20px;
}
::v-deep .group-avatar {
width: 100px;
height: 100px;
border-radius: 6px;
object-fit: cover;
}
</style>
<template>
<div class="main">
<card title="创建活动">
<v-form ref="form" :fields="fields" @submit="onSubmit">
<input
type="button"
value="确认创建,提交审核"
class="submit-button"
@click="handleSubmit"
/>
</v-form>
</card>
</div>
</template>
<script>
import Card from '@/components/Card'
import VForm from '@/components/Form'
import * as api from '@/api'
export default {
name: 'CreateActivity',
components: { Card, VForm },
data() {
return {
fields: [
{
name: 'activity_name',
label: '主题',
required: true,
placeholder: '请输入活动主题',
rules: [{ required: true, message: '请输入活动主题' }]
},
{
fieldType: 'uploader',
name: 'activity_image',
label: '封面',
required: true,
placeholder: '请上传活动封面'
},
{
type: 'textarea',
name: 'activity_contents',
label: '描述',
required: true,
placeholder: '请简单描述一下该活动',
autosize: { maxHeight: 120, minHeight: 120 },
rules: [{ required: true, message: '请简单描述一下该活动' }]
},
{
fieldType: 'datetime',
name: 'activity_time',
label: '时间',
required: true,
placeholder: '请选择活动时间',
rules: [{ required: true, message: '请选择活动时间' }]
},
{
name: 'activity_city',
label: '城市',
required: true,
placeholder: '请输入活动城市',
rules: [{ required: true, message: '请输入活动城市' }]
},
{
name: 'activity_address',
label: '具体地址',
required: true,
placeholder: '请输入活动具体地址',
rules: [{ required: true, message: '请输入活动具体地址' }]
},
{
fieldType: 'select',
name: 'org_id',
label: '审核渠道',
required: true,
placeholder: '请选择审核本活动的上级组织',
rules: [{ required: true, message: '请选择审核本活动的上级组织' }],
labelKey: 'org_name',
valueKey: 'id',
remote: { method: api.getJoinedGroupes }
},
{
fieldType: 'select',
name: 'visibility',
label: '活动可见性',
required: true,
placeholder: '请选择本活动对哪些用户组可见',
rules: [{ required: true, message: '请选择本活动对哪些用户组可见' }],
values: [
{ text: '所有人可见', value: '1' },
{ text: '所在组织可见', value: '2' },
{ text: '审核组织可见', value: '3' }
]
}
],
groups: []
}
},
methods: {
handleSubmit() {
this.$refs.form.submit()
},
onSubmit(data) {
const ruleForm = this.$refs.form.ruleForm
if (data.activity_image) {
const [first = { url: '' }] = data.activity_image
data.activity_image = first.url
}
data.org_id = ruleForm.org_id
data.visibility = ruleForm.visibility
api.addActivity(data).then(response => {
if (response.success) {
this.$dialog
.alert({
confirmButtonText: '确定',
message: '活动创建成功,已提交审核'
})
.then(() => {
this.$router.replace({ name: 'my', query: { tab: '1' } })
})
} else {
this.$toast(response.message)
}
})
}
}
}
</script>
<style lang="scss"></style>
<template>
<card title="创建新组织" style="margin:0 20px;">
<v-form ref="form" :fields="fields" @submit="onSubmit">
<input
type="button"
value="确认创建,提交审核"
class="submit-button"
@click="handleSubmit"
/>
</v-form>
</card>
</template>
<script>
import Card from '@/components/Card'
import VForm from '@/components/Form'
import * as api from '@/api'
export default {
name: 'CreateGroup',
components: { Card, VForm },
data() {
return {
fields: [
{
fieldType: 'select',
name: 'org_type',
label: '类型',
required: true,
placeholder: '请选择您要创建的组织类型',
rules: [{ required: true, message: '请选择您要创建的组织类型' }],
values: [
{ name: '1', text: '地方校友会' },
{ name: '2', text: '行业研究会' },
{ name: '3', text: '俱乐部' }
],
valueKey: 'name'
},
{
name: 'org_name',
label: '名称',
required: true,
placeholder: '请输入组织名称',
rules: [{ required: true, message: '请输入组织名称' }]
},
{
name: 'purpose',
label: '宗旨',
required: true,
placeholder: '请简述您的创建组织的宗旨',
rules: [{ required: true, message: '请简述您的创建组织的宗旨' }]
},
{
type: 'textarea',
name: 'goal',
label: '目的',
required: true,
placeholder: '请输入组织目的',
autosize: { maxHeight: 160, minHeight: 120 },
rules: [{ required: true, message: '请输入组织目的' }]
},
{
name: 'initiator',
label: '发起人',
required: true,
placeholder: '请输入组织发起人',
rules: [{ required: true, message: '请输入组织发起人' }]
},
{
name: 'org_city',
label: '城市',
required: true,
placeholder: '请输入组织所在城市',
rules: [{ required: true, message: '请输入组织所在城市' }]
},
{
type: 'textarea',
name: 'rules',
label: '组织章程',
required: true,
placeholder: '请输入组织章程',
autosize: { maxHeight: 160, minHeight: 120 },
rules: [{ required: true, message: '请输入组织章程' }]
},
{
type: 'textarea',
name: 'plan',
label: '活动计划',
required: true,
placeholder: '请简述您所创建组织的活动计划',
autosize: { maxHeight: 160, minHeight: 120 },
rules: [{ required: true, message: '请简述您所创建组织的活动计划' }]
},
{
fieldType: 'uploader',
name: 'logo',
label: '头像',
required: true,
placeholder: '请上传组织头像'
}
]
}
},
methods: {
handleSubmit() {
this.$refs.form.submit()
},
onSubmit(data) {
const ruleForm = this.$refs.form.ruleForm
if (data.logo) {
const [first = { url: '' }] = data.logo
data.logo = first.url
}
data.org_type = ruleForm.org_type || 1
api.addGroup(data).then(response => {
if (response.success) {
this.$dialog
.alert({
confirmButtonText: '确定',
message: '组织创建成功,已提交审核'
})
.then(() => {
this.$router.replace({ name: 'my' })
})
} else {
this.$toast(response.message)
}
})
}
}
}
</script>
<style lang="scss"></style>
<template>
<div class="create">
<div class="create-hd">
<h1 class="create-hd__title">请选择您想进行的操作</h1>
<p class="create-hd__tip">我们将为您展现下一步指引</p>
</div>
<div class="create-bd">
<div class="create-item">
<div
class="create-item-box create-item__group"
:class="{ 'is-disabled': groupDisabled }"
@click="onCreateGroup"
>
<div class="pic"></div>
<div class="title">创建新组织</div>
</div>
<p class="create-item__tip" v-if="groupCount === 0">
您还未加入组织,请先加入/创建一个组织吧~<router-link
:to="{ name: 'group' }"
>去逛逛</router-link
>
</p>
<p class="create-item__tip" v-else-if="groupCount < 6">
您已加入{{ groupCount }}个组织,可直接发布活动或<router-link
:to="{ name: 'group' }"
>看看其他组织</router-link
>
</p>
<p class="create-item__tip" v-if="groupCount >= 6">
您已加入满{{ groupCount }}个组织咯,请直接创建活动或者管理<router-link
:to="{ name: 'my' }"
>我的组织~</router-link
>
</p>
</div>
<div class="create-item">
<div
class="create-item-box create-item__activity"
:class="{ 'is-disabled': activityDisabled }"
@click="onCreateActivity"
>
<div class="pic"></div>
<div class="title">创建活动</div>
</div>
<p class="create-item__tip" v-if="groupCount === 0">
您还未加入组织,请先加入/创建一个组织吧~<router-link
:to="{ name: 'group' }"
>去逛逛</router-link
>
</p>
</div>
</div>
</div>
</template>
<script>
import * as api from '@/api'
export default {
name: 'CreateIndex',
data() {
return {
groupList: [],
maxGroup: 6
}
},
computed: {
groupCount() {
return this.groupList.length || 0
},
groupDisabled() {
return this.groupCount >= 6
},
activityDisabled() {
return !this.groupCount
}
},
methods: {
// 创建组织
onCreateGroup() {
!this.groupDisabled && this.$router.replace({ name: 'createGroup' })
},
// 创建活动
onCreateActivity() {
!this.activityDisabled && this.$router.replace({ name: 'createActivity' })
},
// 获取我加入的组织
getJoinedGroupes() {
api.getJoinedGroupes().then(response => {
this.groupList = Array.isArray(response) ? response : []
})
}
},
beforeMount() {
this.getJoinedGroupes()
}
}
</script>
<style lang="scss">
.create {
padding: 40px;
}
.create-hd__title {
font-size: 18px;
color: #222;
}
.create-hd__tip {
margin-top: 10px;
font-size: 12px;
color: #999;
}
.create-item {
margin-top: 20px;
}
.create-item__tip {
margin-top: 10px;
font-size: 12px;
text-align: center;
color: #999;
a {
color: #1989fa;
white-space: nowrap;
}
}
.create-item-box {
display: flex;
align-items: center;
height: 130px;
font-size: 20px;
color: #fff;
border-radius: 6px;
cursor: pointer;
&.is-disabled {
background: #eee;
cursor: not-allowed;
}
.pic {
width: 90px;
height: 90px;
margin: 0 35px 0 30px;
}
}
.create-item__group {
background: linear-gradient(
180deg,
rgba(255, 201, 44, 1) 0%,
rgba(255, 116, 42, 1) 100%
);
.pic {
background: url('~@/assets/img/create_group.png') no-repeat;
background-size: contain;
}
&.is-disabled {
.pic {
background: url('~@/assets/img/create_group_disabled.png') no-repeat;
background-size: contain;
}
}
}
.create-item__activity {
background: linear-gradient(
180deg,
rgba(2, 236, 228, 1) 0%,
rgba(18, 186, 244, 1) 100%
);
.pic {
background: url('~@/assets/img/create_activity.png') no-repeat;
background-size: contain;
}
&.is-disabled {
.pic {
background: url('~@/assets/img/create_activity_disabled.png') no-repeat;
background-size: contain;
}
}
}
</style>
<template>
<div class="main">
<card title="活动列表">
<van-list
v-model="loading"
:finished="finished"
@load="onLoad"
v-if="list.length"
>
<activity-item
v-for="item in list"
:data="item"
:key="item.id"
></activity-item>
</van-list>
<div class="empty" v-else>暂时没有内容哦,去别处看看吧~</div>
</card>
</div>
</template>
<script>
import Card from '@/components/Card'
import ActivityItem from '@/components/ActivityItem'
import * as api from '@/api'
export default {
name: 'GroupActivity',
components: { Card, ActivityItem },
data() {
return {
list: [],
loading: false,
finished: false,
requestParams: { offset: 0, limit: 20 }
}
},
computed: {
pid() {
return this.$route.params.id
}
},
methods: {
getList() {
this.loading = true
api
.getActivitesByGroup(this.pid, this.requestParams)
.then(response => {
if (response.length) {
this.list = this.list.concat(response)
}
this.loading = false
this.finished = response.length < this.requestParams.limit
})
.catch(() => {
this.loading = false
this.finished = true
})
},
onLoad() {
this.requestParams.offset =
this.requestParams.offset + this.requestParams.limit
this.getList()
},
// 刷新
refresh() {
this.requestParams.offset = 0
this.list = []
this.getList()
}
},
beforeMount() {
this.getList()
}
}
</script>
<style lang="scss" scoped></style>
<template>
<div class="main">
<!-- 搜索 -->
<search-bar
readonly
placeholder="输入职位或公司名称"
@click.native="$router.push({ name: 'search' })"
></search-bar>
<card title="组织排行榜">
<group-list :show-index="true"></group-list>
</card>
</div>
</template>
<script>
// components
import SearchBar from '@/components/SearchBar'
import Card from '@/components/Card'
import GroupList from '@/components/GroupList'
export default {
name: 'GroupIndex',
components: { SearchBar, Card, GroupList },
data() {
return {
typeMap: {
1: '公益行',
2: '去游学',
3: '直播课',
4: '找工作',
5: '运动家'
}
}
},
computed: {
title() {
const { type = 1 } = this.$route.query
return this.typeMap[type]
}
},
methods: {
onSearch() {
this.$router.push({ name: 'search' })
}
}
}
</script>
<style lang="scss"></style>
<template>
<div class="main">
<card title="组织详情" v-if="detail">
<!-- <template #aside>
<h6 class="leave-group" v-if="detail.button_show === 3">退出组织</h6>
</template> -->
<div class="info">
<div class="info-item" v-for="item in fields" :key="item.name">
<div class="info-item__label">{{ item.label }}</div>
<div class="info-item__content">
<template v-if="item.computed">
<div v-html="item.computed(detail[item.name], detail)"></div>
</template>
<template v-else>
{{ detail[item.name] }}
</template>
</div>
</div>
</div>
<div class="buttons">
<input
type="button"
class="button button-primary"
value="申请加入"
@click="joinGroup"
v-if="detail.button_show === 1"
/>
<input
type="button"
class="button button-default"
value="已申请,等待审核"
v-if="detail.button_show === 2"
@click="onLeave"
/>
</div>
</card>
</div>
</template>
<script>
import Card from '@/components/Card'
import * as api from '@/api'
export default {
name: 'Group',
components: { Card },
data() {
return {
detail: null,
fields: [
{ name: 'org_name', label: '名称' },
{ name: 'org_type_str', label: '类型' },
{ name: 'org_city', label: '城市' },
{ name: 'purpose', label: '宗旨' },
{ name: 'goal', label: '目的' },
{ name: 'initiator', label: '主要发起人' },
{ name: 'rules', label: '组织章程' },
{ name: 'plan', label: '活动计划' },
{
name: 'logo',
label: '头像',
computed(value) {
return `<img src="${value}" class="group-avatar">`
}
}
]
}
},
computed: {
pid() {
return this.$route.params.id
}
},
methods: {
// 组织详情
getDetail() {
api.getGroup(this.pid).then(response => {
this.detail = response
})
},
// 加入组织
joinGroup() {
api.joinGroup(this.pid).then(() => {
this.getDetail()
})
},
// 离开组织
leaveGroup() {
api.leaveGroup(this.pid).then(() => {
this.getDetail()
})
},
onLeave() {
this.$dialog
.confirm({
title: '提示',
message: '你已申请加入该组织,是否取消申请?'
})
.then(() => {
this.leaveGroup()
})
.catch(() => {})
}
},
beforeMount() {
this.getDetail()
}
}
</script>
<style lang="scss" scoped>
.info-item {
margin-bottom: 20px;
display: flex;
}
.info-item__label {
width: 70px;
color: #999;
text-align: center;
}
.info-item__content {
flex: 1;
color: #222;
overflow: hidden;
margin-left: 20px;
}
.buttons {
margin: 20px 0;
text-align: center;
}
.button {
display: inline-block;
min-width: 128px;
height: 30px;
padding: 0 16px;
line-height: 30px;
color: #fff;
text-align: center;
border-radius: 20px;
}
.button-default {
background: #ccc;
}
.button-primary {
background: linear-gradient(
180deg,
rgba(2, 236, 228, 1) 0%,
rgba(18, 186, 244, 1) 100%
);
}
::v-deep .group-avatar {
width: 100px;
height: 100px;
border-radius: 6px;
object-fit: cover;
}
.leave-group {
font-size: 12px;
font-weight: 400;
line-height: 30px;
color: #ccc;
}
</style>
<template>
<div class="main">
<card title="成员列表">
<div class="member-card" v-if="memberApplicationList.length">
<div class="member-card-hd">新成员申请</div>
<div class="member-card-bd">
<member-item
v-for="item in memberApplicationList"
:data="item"
:key="item.id"
></member-item>
</div>
</div>
<div class="member-card" v-if="memberManagementList.length">
<div class="member-card-hd">组织创建者、管理员</div>
<div class="member-card-bd">
<member-item
v-for="item in memberManagementList"
:data="item"
:key="item.id"
></member-item>
</div>
</div>
<div class="member-card">
<div class="member-card-hd">成员</div>
<div class="member-card-bd">
<member-list
:params="{ org_id: pid }"
:request-callback="requestCallback"
@request-success="requestSuccess"
></member-list>
</div>
</div>
</card>
</div>
</template>
<script>
import Card from '@/components/Card'
import MemberList from '@/components/MemberList'
import MemberItem from '@/components/MemberItem'
export default {
name: 'GroupMember',
components: { Card, MemberList, MemberItem },
data() {
return {
detail: null,
list: []
}
},
computed: {
pid() {
return this.$route.params.id
},
// 申请列表
memberApplicationList() {
// role: -1待审核、0拒绝、1通过
return this.list.filter(item => item.status === '-1')
},
// 管理员列表
memberManagementList() {
// role: 1参与者、 2发起人
return this.list.filter(item => item.role === '2')
}
},
methods: {
// 请求数据处理
requestCallback(data) {
// role: 1参与者、 2发起人
return data.filter(item => item.role === '1')
},
// 请求成功
requestSuccess(list) {
this.list = list
}
},
beforeMount() {}
}
</script>
<style lang="scss" scoped>
.member-card {
margin-left: -20px;
margin-right: -20px;
}
.member-card-hd {
height: 36px;
padding: 0 20px;
font-size: 14px;
line-height: 36px;
color: #999;
background-color: #f1f1f1;
}
.member-card-bd {
margin: 0 20px;
}
::v-deep .member-item {
margin: 20px 0;
}
</style>
<template>
<div class="main">
<!-- 搜索 -->
<search-bar
readonly
placeholder="输入组织或校友姓名搜索"
@click.native="$router.push({ name: 'search' })"
></search-bar>
<!-- banner -->
<div class="banner"><img src="img/home_banner.png" /></div>
<!-- 导航 -->
<div class="nav">
<ul class="nav-list">
<li
class="nav-item"
v-for="(item, index) in navList"
:key="index"
@click="handleNavClick(item)"
>
<div class="pic"><img :src="item.url" /></div>
<div class="title">{{ item.title }}</div>
</li>
</ul>
</div>
<!-- 排行榜 -->
<div class="top-bar">
<ul class="top-bar-list">
<li
class="top-bar-item top-bar-item__group"
@click="$router.push({ name: 'group' })"
>
组织排行榜
</li>
<li
class="top-bar-item top-bar-item__activity"
@click="$router.push({ name: 'activity' })"
>
活动热度榜
</li>
</ul>
</div>
<card title="最新活动">
<activity-list :params="{ newest: 0 }"></activity-list>
</card>
<tab-bar></tab-bar>
</div>
</template>
<script>
// components
import SearchBar from '@/components/SearchBar'
import TabBar from '@/components/TabBar'
import Card from '@/components/Card'
import ActivityList from '@/components/ActivityList'
export default {
name: 'HomeIndex',
components: { SearchBar, TabBar, Card, ActivityList },
data() {
return {
navList: [
{ url: 'img/home_nav_01.png', title: '公益行', type: 1 },
{ url: 'img/home_nav_02.png', title: '去游学', type: 2 },
{ url: 'img/home_nav_03.png', title: '直播课', type: 3 },
{ url: 'img/home_nav_04.png', title: '找工作', type: 4 },
{ url: 'img/home_nav_05.png', title: '运动家', type: 5 }
]
}
},
methods: {
handleNavClick({ type }) {
this.$router.push({ name: 'activity', query: { type } })
}
}
}
</script>
<style lang="scss">
.banner {
margin: 10px 0;
img {
width: 100%;
}
}
.nav {
padding: 10px 0;
}
.nav-list {
display: flex;
justify-content: space-between;
}
.nav-item {
display: flex;
flex-direction: column;
align-items: center;
.pic {
width: 40px;
height: 40px;
img {
width: 100%;
}
}
.title {
margin-top: 4px;
color: #666;
}
}
.top-bar {
padding: 20px 0;
}
.top-bar-list {
display: flex;
justify-content: space-between;
}
.top-bar-item {
width: 42%;
height: 40px;
font-size: 14px;
font-weight: 600;
line-height: 40px;
color: #fff;
text-align: center;
border-radius: 40px;
cursor: pointer;
}
.top-bar-item__group {
background: linear-gradient(
180deg,
rgba(255, 201, 44, 1) 0%,
rgba(255, 116, 42, 1) 100%
);
box-shadow: 0px 5px 20px 0px rgba(253, 3, 20, 0.3);
}
.top-bar-item__activity {
background: linear-gradient(
180deg,
rgba(2, 236, 228, 1) 0%,
rgba(18, 186, 244, 1) 100%
);
box-shadow: 0px 5px 20px 0px rgba(17, 187, 243, 0.3);
}
</style>
<template>
<div class="main">
<card title="我的消息">
<div class="message-card" @click="onClick(3)">
<div class="message-card-pic">
<img src="~@/assets/img/message_settings_icon.png" />
</div>
<div class="message-card-content">
<h4>系统消息</h4>
<p>紫荆官方发布了一条新消息,点击查看</p>
</div>
</div>
<div class="message-card" @click="onClick(1)">
<div class="message-card-pic">
<img src="~@/assets/img/message_group_icon.png" />
</div>
<div class="message-card-content">
<h4>组织消息</h4>
<p>您创建的组织有新的人员加入请求</p>
</div>
</div>
<div class="message-card" @click="onClick(2)">
<div class="message-card-pic">
<img src="~@/assets/img/message_activity_icon.png" />
</div>
<div class="message-card-content">
<h4>活动消息</h4>
<p>您创建的活动有新的人员加入请求</p>
</div>
</div>
</card>
</div>
</template>
<script>
import Card from '@/components/Card'
export default {
name: 'MessageIndex',
components: { Card },
data() {
return {}
},
methods: {
onClick(type) {
this.$router.push({ name: 'messageList', params: { type } })
}
}
}
</script>
<style lang="scss" scoped>
.message-card {
display: flex;
padding-bottom: 20px;
margin-bottom: 20px;
border-bottom: 1px solid #f1f1f1;
}
.message-card-pic {
width: 40px;
height: 40px;
img {
width: 100%;
height: 100%;
object-fit: contain;
}
}
.message-card-content {
margin-left: 10px;
h4 {
font-size: 14px;
color: #333;
}
p {
margin-top: 6px;
font-size: 12px;
color: #999;
}
}
</style>
<template>
<div class="main">
<card :title="title"></card>
</div>
</template>
<script>
import Card from '@/components/Card'
export default {
name: 'Message',
components: { Card },
data() {
return {}
},
computed: {
type() {
return this.$route.params.type
},
title() {
const typeMap = { 1: '组织消息', 2: '活动消息', 3: '系统消息' }
return typeMap[this.type]
}
}
}
</script>
<template>
<div class="main">
<card :title="title">
<van-list
v-model="loading"
:finished="finished"
@load="onLoad"
v-if="list.length"
>
<message-item
v-for="item in list"
:data="item"
:type="type"
:key="item.id"
></message-item>
</van-list>
<div class="empty" v-else>暂时没有内容哦,去别处看看吧~</div>
</card>
</div>
</template>
<script>
import Card from '@/components/Card'
import MessageItem from '@/components/MessageItem'
import * as api from '@/api'
export default {
name: 'MessageList',
components: { Card, MessageItem },
data() {
return {
list: [],
loading: false,
finished: false,
requestParams: { offset: 0, limit: 20, type: '' }
}
},
computed: {
type() {
return this.$route.params.type
},
title() {
const typeMap = { 1: '组织消息', 2: '活动消息', 3: '系统消息' }
return typeMap[this.type]
}
},
methods: {
getList() {
this.loading = true
this.requestParams.type = this.type
api
.getMessageList(this.requestParams)
.then(response => {
if (response.length) {
this.list = this.list.concat(response)
}
this.loading = false
this.finished = response.length < this.requestParams.limit
})
.catch(() => {
this.loading = false
this.finished = true
})
},
onLoad() {
this.requestParams.offset =
this.requestParams.offset + this.requestParams.limit
this.getList()
},
// 刷新
refresh() {
this.requestParams.offset = 0
this.list = []
this.getList()
}
},
beforeMount() {
this.getList()
}
}
</script>
<template>
<div class="main my">
<div class="tools">
<ul class="tools-list">
<li class="tools-item" @click="$router.push({ name: 'settings' })">
<img src="~@/assets/img/my_settings.png" width="20" />
</li>
<li class="tools-item" @click="$router.push({ name: 'message' })">
<img src="~@/assets/img/my_message.png" width="13" />
</li>
</ul>
</div>
<div class="user">
<div class="user-avatar"><img :src="user.avatar" /></div>
<div class="user-content">
<div class="user-content__name">{{ user.nickname }}</div>
<div class="user-content__info">{{ user.mobile }}</div>
</div>
<div class="user-aside">
<dl @click="$router.push({ name: 'myGroup' })">
<dt>{{ detail.org_stu_total }}</dt>
<dd>组织</dd>
</dl>
<dl @click="$router.push({ name: 'myActivity' })">
<dt>{{ detail.act_stu_total }}</dt>
<dd>活动</dd>
</dl>
<dl @click="$router.push({ name: 'myApprove' })">
<dt>{{ detail.act_check_total }}</dt>
<dd>审批</dd>
</dl>
</div>
</div>
<van-tabs v-model="tabActive" :line-height="2">
<van-tab title="我的组织" name="0">
<my-group-list></my-group-list>
</van-tab>
<van-tab title="我的活动" name="1">
<my-activity-list></my-activity-list>
</van-tab>
<van-tab title="我的审批" name="2">
<my-approve-list></my-approve-list>
</van-tab>
</van-tabs>
<tab-bar></tab-bar>
</div>
</template>
<script>
// components
import TabBar from '@/components/TabBar'
import MyGroupList from '@/components/MyGroupList'
import MyActivityList from '@/components/MyActivityList'
import MyApproveList from '@/components/MyApproveList'
import * as api from '@/api'
export default {
name: 'MyIndex',
components: { TabBar, MyGroupList, MyActivityList, MyApproveList },
data() {
return {
tabActive: '0',
detail: {}
}
},
watch: {
$route: {
immediate: true,
depp: true,
handler(route) {
this.tabActive = route.query.tab || '0'
}
}
},
computed: {
user() {
return this.detail.user || {}
}
},
methods: {
onTabClick(name) {
this.$router.push({ query: { tab: name } })
},
// 获取我的详情
getDetail() {
api.getMy().then(response => {
this.detail = response
})
}
},
beforeMount() {
this.getDetail()
}
}
</script>
<style lang="scss">
.tools-list {
display: flex;
justify-content: flex-end;
align-items: center;
padding: 10px 0 20px;
}
.tools-item {
margin-left: 30px;
}
.user {
display: flex;
align-items: center;
margin-bottom: 30px;
}
.user-avatar {
width: 60px;
height: 60px;
background-color: #ccc;
border-radius: 50%;
overflow: hidden;
}
.user-content {
display: flex;
height: 60px;
flex: 1;
flex-direction: column;
justify-content: space-between;
margin-left: 10px;
}
.user-content__name {
font-size: 17px;
color: #222;
}
.user-content__info {
color: #999;
}
.user-aside {
display: flex;
dl {
text-align: center;
margin-left: 10px;
}
dt {
font-size: 17px;
color: #222;
}
dd {
color: #999;
}
}
.my .list {
margin-top: 20px;
}
</style>
<template>
<div class="main">
<card title="我的活动">
<my-activity-list></my-activity-list>
</card>
</div>
</template>
<script>
import Card from '@/components/Card'
import MyActivityList from '@/components/MyActivityList'
export default {
components: { Card, MyActivityList },
data() {
return {}
}
}
</script>
<template>
<div class="main">
<card title="我的审批">
<my-approve-list></my-approve-list>
</card>
</div>
</template>
<script>
import Card from '@/components/Card'
import MyApproveList from '@/components/MyApproveList'
export default {
components: { Card, MyApproveList },
data() {
return {}
}
}
</script>
<template>
<div class="main">
<card title="我的组织">
<my-group-list></my-group-list>
</card>
</div>
</template>
<script>
import Card from '@/components/Card'
import MyGroupList from '@/components/MyGroupList'
export default {
components: { Card, MyGroupList },
data() {
return {}
}
}
</script>
<template>
<div class="main search">
<search-bar
placeholder=""
:focus="true"
v-model="searchValue"
@search="onSearch"
ref="searchBar"
></search-bar>
<van-tabs v-model="tabActive" :line-height="2" @click="onTabClick">
<van-tab title="组织" name="0">
<group-list
:params="{ keywords: searchValue }"
ref="list"
v-if="tabActive === '0'"
></group-list>
</van-tab>
<van-tab title="个人" name="1">
<member-list
:params="{ keywords: searchValue }"
ref="list"
v-if="tabActive === '1'"
></member-list>
</van-tab>
<van-tab title="活动" name="2">
<activity-list
:params="{ keywords: searchValue }"
ref="list"
v-if="tabActive === '2'"
></activity-list>
</van-tab>
</van-tabs>
</div>
</template>
<script>
// components
import SearchBar from '@/components/SearchBar'
import GroupList from '@/components/GroupList'
import MemberList from '@/components/MemberList'
import ActivityList from '@/components/ActivityList'
export default {
name: 'Search',
components: { SearchBar, GroupList, MemberList, ActivityList },
data() {
return {
tabActive: '0',
searchValue: ''
}
},
watch: {
$route: {
immediate: true,
depp: true,
handler(route) {
this.tabActive = route.query.tab || '0'
this.searchValue = route.query.keywords
}
}
},
methods: {
onTabClick(name) {
this.$router.replace({ query: { tab: name, keywords: this.searchValue } })
},
onSearch() {
this.$router.replace({
query: { tab: this.tabActive, keywords: this.searchValue }
})
}
}
}
</script>
<style lang="scss">
.search {
.list {
margin-top: 20px;
}
}
</style>
<template>
<div class="main">
<card title="设置">
<input
type="button"
class="submit-button"
value="退出登录"
style="margin-top:calc(100vh - 120px);"
@click="logout"
/>
</card>
</div>
</template>
<script>
import Card from '@/components/Card'
export default {
name: 'Settings',
components: { Card },
data() {
return {}
},
methods: {
// 退出登录
logout() {
this.$router.push({ name: 'login' })
}
}
}
</script>
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论