Browse Source

活动页面

master
xuhuajiao 1 week ago
parent
commit
c79efd8c35
  1. 11
      src/api/digitalScreen/index.js
  2. 31
      src/api/weixin/index.js
  3. 37
      src/assets/styles/quillEditor.css
  4. 8
      src/utils/request.js
  5. 198
      src/views/weChatMiniProgram/activity.vue

11
src/api/digitalScreen/index.js

@ -147,6 +147,14 @@ export function FetchDeleteScreenPromotionVideo(parameter) {
})
}
export function FetchCancelResumeActivity(parameter) {
return request({
url: 'api/screenSetting/cancelResumeActivity',
method: 'post',
data: parameter
})
}
export default {
FetchInitScreenSetting,
FetchEditScreenSetting,
@ -164,5 +172,6 @@ export default {
FetchDeleteScreenWelcomePromotion,
FetchInitScreenPromotionVideo,
FetchEditScreenPromotionVideo,
FetchDeleteScreenPromotionVideo
FetchDeleteScreenPromotionVideo,
FetchCancelResumeActivity
}

31
src/api/weixin/index.js

@ -14,6 +14,35 @@ export function FetchReplyReaderMessage(parameter) {
})
}
// 新增 / 编辑活动
export function add(data) {
return request({
url: 'api/weixin/editActivity',
method: 'post',
data
})
}
export function edit(data) {
return request({
url: 'api/weixin/editActivity',
method: 'post',
data
})
}
// 取消活动/恢复活动
export function FetchCancelResumeActivity(data) {
return request({
url: 'api/weixin/cancelResumeActivity',
method: 'post',
data
})
}
export default {
FetchReplyReaderMessage
FetchReplyReaderMessage,
add,
edit,
FetchCancelResumeActivity
}

37
src/assets/styles/quillEditor.css

@ -203,3 +203,40 @@
.ql-size-30px {
font-size: 30px;
}
/* 表格列宽拖动相关样式 */
.quill-better-table-wrapper table {
table-layout: fixed !important;
width: 100% !important;
border-collapse: collapse;
}
.quill-better-table-wrapper table td,
.quill-better-table-wrapper table th {
border: 1px solid #ccc;
padding: 8px;
overflow: hidden;
white-space: nowrap;
}
.ql-align-center {
text-align: center;
img{
display: block;
width: 100%;
margin: 0 auto;
}
}
.ql-align-right {
text-align: right;
}
.ql-align-justify {
text-align: justify;
}
.ql-align-right {
text-align: right;
}

8
src/utils/request.js

@ -52,7 +52,13 @@ service.interceptors.response.use(
} else if (response.data instanceof Blob) {
return response.data
} else if (response.data) {
return response.data
if (errorMsg) {
Message.error({
message: errorMsg,
duration: 5000
})
}
return Promise.reject(response.data)
} else {
Message.error({
message: errorMsg,

198
src/views/weChatMiniProgram/activity.vue

@ -50,22 +50,22 @@
/>
</el-form-item>
</el-row>
<el-form-item class="activity-number" label="活动人数" prop="numberLimit">
<el-form-item class="activity-number" label="活动人数" prop="activityPeople">
<el-radio-group v-model="form.numberLimit" v-removeAriaHidden @change="handleNumberLimitChange">
<el-radio :label="1">不限制</el-radio>
<el-radio :label="2">限制</el-radio>
</el-radio-group>
<el-input v-if="form.numberLimit === 2" v-model="form.number" type="number" placeholder="请输入" @blur="validateNumber" />
<el-input v-if="form.numberLimit === 2" v-model.number="form.activityPeople" type="number" placeholder="请输入" min="1" @blur="validateNumber" />
</el-form-item>
<el-row>
<el-form-item label="活动地点" prop="address">
<el-input v-model="form.address" placeholder="请输入" style="width: 500px;" />
<el-form-item label="活动地点" prop="activityLocation">
<el-input v-model="form.activityLocation" placeholder="请输入" style="width: 500px;" />
</el-form-item>
</el-row>
<el-row>
<el-form-item label="活动封面" prop="imgPath">
<el-form-item label="活动封面" prop="coverImage">
<div class="activity-upload">
<img v-if="form.imgPath" :src="`${baseApi}/api/fileRelevant/getImg?imgType=2&imgId=${form.imgPath}`" class="upload-preview">
<img v-if="form.coverImage" :src="`${baseApi}/api/fileRelevant/getImg?imgType=2&imgId=${form.coverImage}`" class="upload-preview">
<div v-else class="upload-preview-placeholder">
<img :src="require('@/assets/images/system/default-img.jpg')" class="placeholder-img">
</div>
@ -127,6 +127,7 @@
<el-button type="primary" @click="confirmCancel">确认</el-button>
</div>
</el-dialog>
<ActivityDetail :visible.sync="detailVisible" :activity.sync="detailActivity" />
<!--表格渲染-->
<div class="container-wrap">
<span class="right-top-line" />
@ -139,24 +140,25 @@
:data="crud.data"
@selection-change="crud.selectionChangeHandler"
@row-click="clickRowHandler"
@row-dblclick="dblclickRowHandler"
>
<el-table-column type="selection" align="center" width="55" />
<el-table-column prop="icon" label="封面" align="center">
<el-table-column prop="coverImage" label="封面" align="center">
<template slot-scope="scope">
<img
style="height:80px;display:block;margin:0 auto;"
:src="scope.row.imgPath ? `${baseApi}/api/fileRelevant/getImg?imgType=2&imgId=${scope.row.imgPath}` : require('@/assets/images/system/default-img.jpg')"
:src="scope.row.coverImage ? `${baseApi}/api/fileRelevant/getImg?imgType=2&imgId=${scope.row.coverImage}` : require('@/assets/images/system/default-img.jpg')"
alt="封面"
>
</template>
</el-table-column>
<!-- width="260" :show-overflow-tooltip="true" -->
<el-table-column label="标题" prop="title" />
<el-table-column prop="title" label="活动名称" />
<el-table-column prop="startTime" label="开始时间" />
<el-table-column prop="endTime" label="结束时间" />
<el-table-column prop="number" label="活动人数">
<el-table-column prop="activityPeople" label="活动人数">
<template slot-scope="scope">
{{ scope.row.number || '不限制' }}
{{ scope.row.activityPeople || '不限制' }}
</template>
</el-table-column>
<el-table-column prop="gridName" label="实约人数">
@ -166,39 +168,36 @@
</el-table-column>
<el-table-column prop="status" label="状态" width="100" align="center">
<template slot-scope="scope">
<!-- <span :class="getStatusClass(scope.row.status)">{{ getStatusText(scope.row.status) }}</span> -->
<!-- 未开始 -->
<span v-if="scope.row.status === 0" class="row-state row-physical state-active">{{ getStatusText(scope.row.status) }}</span>
<!-- 进行中 -->
<span v-if="scope.row.status === 1" class="row-state row-binding state-active">{{ getStatusText(scope.row.status) }}</span>
<!-- 已结束 -->
<span v-if="scope.row.status === 2" class="row-state">{{ getStatusText(scope.row.status) }}</span>
<!-- 手动取消 -->
<span v-if="scope.row.status === 3" class="row-state row-lending state-active">{{ getStatusText(scope.row.status) }}</span>
<span :class="getStatusClass(scope.row.status)">{{ scope.row.status }}</span>
</template>
</el-table-column>
<el-table-column label="操作" width="100" align="center">
<el-table-column label="操作" width="160" align="center">
<template slot-scope="scope">
<!-- <el-button
type="text"
icon="el-icon-edit"
@click="handleEdit(scope.row)"
>编辑</el-button> -->
<el-button
v-if="scope.row.status === 0 || scope.row.status === 1"
style="padding: 7px !important;"
v-if="scope.row.status === '未开始' || scope.row.status === '进行中'"
type="text"
icon="el-icon-circle-close"
@click="showCancelDialog(scope.row)"
>取消</el-button>
<el-button
v-else-if="scope.row.status === 3 && canRestore(scope.row)"
style="padding: 7px !important;"
type="success"
v-else-if="scope.row.status === '已取消' && canRestore(scope.row)"
type="text"
icon="el-icon-refresh"
@click="restoreActivity(scope.row)"
>恢复</el-button>
</template>
</el-table-column>
<el-table-column prop="create_time" label="创建日期" width="160">
<!-- <el-table-column prop="create_time" label="创建日期" width="160">
<template slot-scope="scope">
<div>{{ scope.row.create_time | parseTime }}</div>
</template>
</el-table-column>
</el-table-column> -->
</el-table>
<!--分页组件-->
<pagination v-if="crud.data.length!==0" />
@ -207,7 +206,7 @@
</template>
<script>
import crudWeChat from '@/api/digitalScreen/index'
import crudWeChat from '@/api/weixin/index'
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
import CRUD, { presenter, header, form, crud } from '@crud/crud'
import crudOperation from '@crud/CRUD.operation'
@ -215,13 +214,14 @@ import pagination from '@crud/Pagination'
import { mapGetters } from 'vuex'
import QuillEditor from '@/components/quillEditor/index.vue'
import { getToken } from '@/utils/auth'
import ActivityDetail from './module/activityDetail.vue'
const defaultForm = { id: null, title: null, startTime: null, endTime: null, number: null, numberLimit: 1, address: null, imgPath: null }
const defaultForm = { id: null, title: null, startTime: null, endTime: null, activityPeople: null, numberLimit: 1, activityLocation: null, coverImage: null }
export default {
name: 'Activity',
components: { crudOperation, pagination, QuillEditor },
components: { crudOperation, pagination, QuillEditor, ActivityDetail },
cruds() {
return CRUD({ title: '活动', url: 'api/screenSetting/initScreenBookRecommend2', crudMethod: { ...crudWeChat },
return CRUD({ title: '活动', url: 'api/weixin/initActivityInfo', crudMethod: { ...crudWeChat },
optShow: {
add: true,
edit: true,
@ -245,6 +245,8 @@ export default {
reason: '',
row: null
},
detailVisible: false,
detailActivity: {},
rules: {
title: [
{ required: true, message: '请输入活动标题', trigger: 'blur' }
@ -267,11 +269,11 @@ export default {
trigger: 'change'
}
],
numberLimit: [
activityPeople: [
{
validator: (rule, value, callback) => {
if (value === 2 && (!this.form.number || this.form.number.toString().trim() === '')) {
callback(new Error('请输入活动人数'))
if (this.form.numberLimit === 2 && (!value || value < 1)) {
callback(new Error('限制人数最少为1'))
} else {
callback()
}
@ -279,10 +281,10 @@ export default {
trigger: ['blur', 'change']
}
],
address: [
activityLocation: [
{ required: true, message: '请输入活动地点', trigger: 'blur' }
],
imgPath: [
coverImage: [
{ required: true, message: '请上传活动封面', trigger: 'change' }
]
},
@ -315,55 +317,6 @@ export default {
methods: {
[CRUD.HOOK.beforeRefresh]() {
this.crud.params.libcode = this.user.fonds.fondsNo
const mockData = [
{
id: 1,
imgPath: null,
title: '读书分享会',
startTime: '2026-01-15 14:00',
endTime: '2026-01-15 16:00',
number: null,
gridName: 45,
status: 1,
create_time: '2026-01-10 10:00:00'
},
{
id: 2,
imgPath: null,
title: '新书发布会',
startTime: '2026-01-20 10:00',
endTime: '2026-01-20 12:00',
number: 100,
gridName: 88,
status: 0,
create_time: '2026-01-12 14:30:00'
},
{
id: 3,
imgPath: null,
title: '作家见面会',
startTime: '2026-01-05 10:00',
endTime: '2026-01-05 12:00',
number: 80,
gridName: 75,
status: 2,
create_time: '2026-01-01 09:00:00'
},
{
id: 4,
imgPath: null,
title: '亲子阅读活动',
startTime: '2026-07-16 14:00',
endTime: '2026-07-30 16:00',
number: 60,
gridName: 30,
status: 3,
create_time: '2026-01-14 11:00:00'
}
]
this.crud.data = mockData
this.crud.loading = false
return false
},
//
[CRUD.HOOK.afterToCU](crud, form) {
@ -373,29 +326,34 @@ export default {
},
//
[CRUD.HOOK.beforeToEdit](crud, form) {
console.log('crud', crud.form)
form.numberLimit = form.number === null ? 1 : 2
form.numberLimit = form.activityPeople === 0 ? 1 : 2
this.editorContent = form.activityContent
},
//
[CRUD.HOOK.afterValidateCU](crud) {
console.log(crud.form)
if (!this.editorContent.trim()) {
this.$message({ message: '请输入活动内容', type: 'error', offset: 8 })
return false
}
crud.form.activityContent = this.editorContent
if (crud.form.numberLimit === 1) {
crud.form.number = null
crud.form.activityPeople = 0
}
delete crud.form.numberLimit
return false
console.log('crud.form', crud.form)
return true
},
validateNumber() {
this.$refs.form.validateField('numberLimit')
this.$refs.form.validateField('activityPeople')
},
handleNumberLimitChange(val) {
if (val === 1) {
this.$refs.form.clearValidate('numberLimit')
this.$refs.form.clearValidate('activityPeople')
}
},
handleImgUploadSuccess(res) {
if (res.code === 200) {
this.form.imgPath = res.data
this.form.coverImage = res.data
this.$message({ message: '上传成功', type: 'success', offset: 8 })
} else {
this.$message({ message: res.message || '上传失败', type: 'error', offset: 8 })
@ -427,12 +385,12 @@ export default {
},
getStatusClass(status) {
const classMap = {
0: 'status-pending',
1: 'status-active',
2: 'status-ended',
3: 'status-canceled'
'未开始': 'row-state row-physical state-active',
'进行中': 'row-state row-binding state-active',
'已结束': 'row-state',
'已取消': 'row-state row-lending state-active'
}
return classMap[status] || 'status-default'
return classMap[status] || ''
},
canRestore(row) {
const now = new Date().getTime()
@ -442,10 +400,20 @@ export default {
return (now < startTime) || (now >= startTime && now <= endTime && endTime - now >= threeDays)
},
restoreActivity(row) {
const now = new Date().getTime()
const startTime = new Date(row.startTime).getTime()
row.status = now < startTime ? 0 : 1
this.$message({ message: '活动已恢复', type: 'success', offset: 8 })
this.$confirm('确定要恢复该活动吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(async() => {
const res = await crudWeChat.FetchCancelResumeActivity({ id: row.id })
console.log('restoreActivity', res)
if (res.code !== 500) {
this.$message({ message: res, type: 'success', offset: 8 })
this.crud.refresh()
} else {
this.$message({ message: res.message || '操作失败', type: 'error', offset: 8 })
}
}).catch(() => {})
},
showCancelDialog(row) {
this.cancelForm.title = row.title
@ -454,16 +422,17 @@ export default {
this.cancelDialogVisible = true
},
confirmCancel() {
// if (!this.cancelForm.reason.trim()) {
// this.$message({ message: '', type: 'error', offset: 8 })
// return
// }
//
this.$refs.cancelForm.validate((valid) => {
this.$refs.cancelForm.validate(async(valid) => {
if (valid) {
this.cancelForm.row.status = 3
const res = await crudWeChat.FetchCancelResumeActivity({ id: this.cancelForm.row.id })
console.log('res', res)
if (res.code !== 500) {
this.$message({ message: res, type: 'success', offset: 8 })
this.crud.refresh()
} else {
this.$message({ message: res.message || '操作失败', type: 'error', offset: 8 })
}
this.cancelDialogVisible = false
this.$message({ message: '活动已取消', type: 'success', offset: 8 })
} else {
console.log('校验失败')
}
@ -495,6 +464,13 @@ export default {
clickRowHandler(row) {
this.$refs.table.clearSelection()
this.$refs.table.toggleRowSelection(row)
},
handleEdit(row) {
this.crud.toEdit(row)
},
dblclickRowHandler(row) {
this.detailActivity = row
this.detailVisible = true
}
}
}

Loading…
Cancel
Save