13 changed files with 1112 additions and 42 deletions
@ -0,0 +1 @@ |
|||||
|
CREATE INDEX idx_qymc_tyshxydm ON sszt_jbxx110497_new(QYMC, TYSHXYDM); |
||||
@ -0,0 +1,4 @@ |
|||||
|
package com.zdxt.enforcementcode.controller; |
||||
|
|
||||
|
public class BureauUnitController { |
||||
|
} |
||||
@ -0,0 +1,22 @@ |
|||||
|
import { _get, _post, _put, _delete } from "../../http/index"; |
||||
|
|
||||
|
// region 计划管理接口
|
||||
|
|
||||
|
const planBaseUrl = "/app-enf/cpPlan"; |
||||
|
|
||||
|
// 计划列表(分页)
|
||||
|
export const getPlanList = (params, success, error) => _get(planBaseUrl + "/list", params, success, error); |
||||
|
|
||||
|
// 计划详情
|
||||
|
export const getPlanDetail = (id, success, error) => _get(planBaseUrl + "/" + id, {}, success, error); |
||||
|
|
||||
|
// 新增计划
|
||||
|
export const addPlan = (params, success, error) => _post(planBaseUrl, params, success, error); |
||||
|
|
||||
|
// 编辑计划
|
||||
|
export const editPlan = (params, success, error) => _put(planBaseUrl, params, success, error); |
||||
|
|
||||
|
// 删除计划
|
||||
|
export const deletePlan = (ids, success, error) => _delete(planBaseUrl + "/" + ids, {}, success, error); |
||||
|
|
||||
|
// endregion
|
||||
@ -0,0 +1,437 @@ |
|||||
|
<template> |
||||
|
<div class="plan-edit-page app_content"> |
||||
|
<!-- 顶部导航 --> |
||||
|
<van-nav-bar |
||||
|
:title="isEdit ? '编辑计划' : '新增计划'" |
||||
|
left-arrow |
||||
|
@click-left="onBack" |
||||
|
/> |
||||
|
|
||||
|
<div class="content"> |
||||
|
<!-- 提示条 --> |
||||
|
<van-notice-bar |
||||
|
v-if="showNotice" |
||||
|
left-icon="info-o" |
||||
|
text="请各执法单位,于本月25日前提交次月的计划" |
||||
|
:scrollable="false" |
||||
|
background="#fff9dc" |
||||
|
color="#7d661c" |
||||
|
class="notice-bar" |
||||
|
closeable |
||||
|
@close="showNotice = false" |
||||
|
/> |
||||
|
|
||||
|
<!-- 表单 --> |
||||
|
<div class="form-card"> |
||||
|
<!-- 计划类别 --> |
||||
|
<van-field name="planType" label="计划类别" required> |
||||
|
<template #input> |
||||
|
<van-radio-group v-model="form.planType" direction="horizontal"> |
||||
|
<van-radio :name="1">日常计划</van-radio> |
||||
|
<van-radio :name="2">专项计划</van-radio> |
||||
|
</van-radio-group> |
||||
|
</template> |
||||
|
</van-field> |
||||
|
|
||||
|
<!-- 计划时间 --> |
||||
|
<van-field |
||||
|
v-model="planDateDisplay" |
||||
|
label="计划时间" |
||||
|
placeholder="请选择时间" |
||||
|
required |
||||
|
readonly |
||||
|
is-link |
||||
|
@click="showDatePicker = true" |
||||
|
/> |
||||
|
|
||||
|
<!-- 执行时段 --> |
||||
|
<van-field name="planTime" label="执行时段" required> |
||||
|
<template #input> |
||||
|
<van-radio-group v-model="form.planTime" direction="horizontal"> |
||||
|
<van-radio :name="1">上午</van-radio> |
||||
|
<van-radio :name="2">下午</van-radio> |
||||
|
<van-radio :name="3">其他</van-radio> |
||||
|
</van-radio-group> |
||||
|
</template> |
||||
|
</van-field> |
||||
|
|
||||
|
<!-- 执法事项 --> |
||||
|
<van-field |
||||
|
v-model="form.enforceContent" |
||||
|
label="执法事项" |
||||
|
type="textarea" |
||||
|
placeholder="请输入执法事项" |
||||
|
required |
||||
|
:maxlength="1000" |
||||
|
show-word-limit |
||||
|
rows="3" |
||||
|
autosize |
||||
|
/> |
||||
|
|
||||
|
<!-- 执法单位 --> |
||||
|
<van-field |
||||
|
v-model="form.bureauDeptName" |
||||
|
label="执法单位" |
||||
|
required |
||||
|
readonly |
||||
|
/> |
||||
|
|
||||
|
<!-- 企业名称 --> |
||||
|
<van-field |
||||
|
v-model="form.enterpriseName" |
||||
|
label="企业名称" |
||||
|
placeholder="请输入执法企业" |
||||
|
required |
||||
|
/> |
||||
|
|
||||
|
<!-- 执法人员 --> |
||||
|
<van-field label="执法人员" required> |
||||
|
<template #input> |
||||
|
<div class="person-box"> |
||||
|
<div |
||||
|
v-for="(person, index) in personList" |
||||
|
:key="index" |
||||
|
class="person-line" |
||||
|
> |
||||
|
<span class="person-name">{{ person.name }}</span> |
||||
|
<span class="person-phone">{{ person.phone }}</span> |
||||
|
<van-icon |
||||
|
v-if="personList.length > 1" |
||||
|
name="close" |
||||
|
class="person-remove" |
||||
|
@click="removePerson(index)" |
||||
|
/> |
||||
|
</div> |
||||
|
<div class="add-person-line" @click="onAddPerson"> |
||||
|
<span class="placeholder-text">请输入</span> |
||||
|
<van-icon name="add-o" color="#2382cf" size="20" /> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
</van-field> |
||||
|
|
||||
|
<!-- 是否公开 --> |
||||
|
<van-field name="isPublic" label="是否公开" required> |
||||
|
<template #input> |
||||
|
<van-radio-group v-model="form.isPublic" direction="horizontal"> |
||||
|
<van-radio :name="1">是</van-radio> |
||||
|
<van-radio :name="0">否</van-radio> |
||||
|
</van-radio-group> |
||||
|
</template> |
||||
|
</van-field> |
||||
|
|
||||
|
<!-- 参与联合 --> |
||||
|
<van-field name="isUnion" label="参与联合" required> |
||||
|
<template #input> |
||||
|
<van-radio-group v-model="form.isUnion" direction="horizontal"> |
||||
|
<van-radio :name="1">是</van-radio> |
||||
|
<van-radio :name="0">否</van-radio> |
||||
|
</van-radio-group> |
||||
|
</template> |
||||
|
</van-field> |
||||
|
</div> |
||||
|
|
||||
|
<!-- 提交按钮 --> |
||||
|
<div class="submit-wrap"> |
||||
|
<van-button |
||||
|
type="primary" |
||||
|
block |
||||
|
round |
||||
|
:loading="submitting" |
||||
|
loading-text="提交中..." |
||||
|
@click="onSubmit" |
||||
|
> |
||||
|
提交 |
||||
|
</van-button> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<!-- 日期选择器 --> |
||||
|
<van-popup v-model:show="showDatePicker" position="bottom" round> |
||||
|
<van-date-picker |
||||
|
v-model="datePickerValue" |
||||
|
title="选择计划时间" |
||||
|
:min-date="minDate" |
||||
|
@confirm="onDateConfirm" |
||||
|
@cancel="showDatePicker = false" |
||||
|
/> |
||||
|
</van-popup> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script setup name="cpPlanEdit"> |
||||
|
import { useRouter, useRoute } from 'vue-router'; |
||||
|
import { showToast } from 'vant'; |
||||
|
import { addPlan, editPlan, getPlanDetail } from '@/api/enforcement/plan'; |
||||
|
|
||||
|
const router = useRouter(); |
||||
|
const route = useRoute(); |
||||
|
|
||||
|
const isEdit = computed(() => !!route.query.id); |
||||
|
const showNotice = ref(true); |
||||
|
const submitting = ref(false); |
||||
|
const showDatePicker = ref(false); |
||||
|
const minDate = new Date(); |
||||
|
|
||||
|
// 表单数据 |
||||
|
const form = ref({ |
||||
|
planType: 1, |
||||
|
planDate: '', |
||||
|
planTime: 1, |
||||
|
planActualDate: '', |
||||
|
planActualTime: 1, |
||||
|
enforceContent: '', |
||||
|
bureauDeptId: '', |
||||
|
bureauDeptName: '', |
||||
|
enterpriseName: '', |
||||
|
enterpriseNumber: '', |
||||
|
enterpriseId: '', |
||||
|
enforceUserNames: '', |
||||
|
enforceUserIds: '', |
||||
|
enforceUserCodes: '', |
||||
|
isPublic: 1, |
||||
|
isUnion: 0, |
||||
|
reserveStatus: 0, |
||||
|
systemReserved: 0, |
||||
|
manualReserved: 0, |
||||
|
editEnable: 1, |
||||
|
organId: '', |
||||
|
organName: '', |
||||
|
deptId: '', |
||||
|
deptName: '', |
||||
|
isDelete: 0, |
||||
|
}); |
||||
|
|
||||
|
// 人员列表 |
||||
|
const personList = ref([]); |
||||
|
|
||||
|
// 日期选择值 |
||||
|
const datePickerValue = ref([ |
||||
|
String(new Date().getFullYear()), |
||||
|
String(new Date().getMonth() + 1).padStart(2, '0'), |
||||
|
String(new Date().getDate()).padStart(2, '0'), |
||||
|
]); |
||||
|
|
||||
|
// 日期显示文本 |
||||
|
const planDateDisplay = computed(() => { |
||||
|
if (!form.value.planDate) return ''; |
||||
|
const timeText = { 1: '上午', 2: '下午', 3: '其他' }; |
||||
|
return form.value.planDate + ' ' + (timeText[form.value.planTime] || ''); |
||||
|
}); |
||||
|
|
||||
|
// 如果是编辑模式,加载详情 |
||||
|
onMounted(() => { |
||||
|
if (isEdit.value) { |
||||
|
loadDetail(route.query.id); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
const loadDetail = (id) => { |
||||
|
getPlanDetail(id, (res) => { |
||||
|
if (res.code === 200 && res.data) { |
||||
|
const data = res.data; |
||||
|
Object.keys(form.value).forEach(key => { |
||||
|
if (data[key] !== undefined && data[key] !== null) { |
||||
|
form.value[key] = data[key]; |
||||
|
} |
||||
|
}); |
||||
|
// 解析人员 |
||||
|
if (data.enforceUserNames) { |
||||
|
const names = data.enforceUserNames.split(','); |
||||
|
personList.value = names.map(name => ({ name, phone: '' })); |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
// 日期确认 |
||||
|
const onDateConfirm = ({ selectedValues }) => { |
||||
|
form.value.planDate = selectedValues.join('-'); |
||||
|
form.value.planActualDate = form.value.planDate; |
||||
|
showDatePicker.value = false; |
||||
|
}; |
||||
|
|
||||
|
// 添加人员(暂时简单实现) |
||||
|
const onAddPerson = () => { |
||||
|
// TODO: 后续对接人员选择器 |
||||
|
showToast('人员选择功能开发中'); |
||||
|
}; |
||||
|
|
||||
|
// 移除人员 |
||||
|
const removePerson = (index) => { |
||||
|
personList.value.splice(index, 1); |
||||
|
syncPersonData(); |
||||
|
}; |
||||
|
|
||||
|
// 同步人员数据到表单 |
||||
|
const syncPersonData = () => { |
||||
|
form.value.enforceUserNames = personList.value.map(p => p.name).join(','); |
||||
|
form.value.enforceUserIds = personList.value.map(p => p.id || '').join(','); |
||||
|
form.value.enforceUserCodes = personList.value.map(p => p.code || '').join(','); |
||||
|
}; |
||||
|
|
||||
|
// 返回 |
||||
|
const onBack = () => { |
||||
|
router.back(); |
||||
|
}; |
||||
|
|
||||
|
// 表单校验 |
||||
|
const validate = () => { |
||||
|
if (!form.value.planDate) { |
||||
|
showToast('请选择计划时间'); |
||||
|
return false; |
||||
|
} |
||||
|
if (!form.value.enforceContent) { |
||||
|
showToast('请输入执法事项'); |
||||
|
return false; |
||||
|
} |
||||
|
if (!form.value.enterpriseName) { |
||||
|
showToast('请输入企业名称'); |
||||
|
return false; |
||||
|
} |
||||
|
return true; |
||||
|
}; |
||||
|
|
||||
|
// 提交 |
||||
|
const onSubmit = () => { |
||||
|
if (!validate()) return; |
||||
|
|
||||
|
submitting.value = true; |
||||
|
form.value.planActualTime = form.value.planTime; |
||||
|
|
||||
|
const api = isEdit.value ? editPlan : addPlan; |
||||
|
api( |
||||
|
form.value, |
||||
|
(res) => { |
||||
|
submitting.value = false; |
||||
|
if (res.code === 200) { |
||||
|
showToast(isEdit.value ? '修改成功' : '新增成功'); |
||||
|
router.back(); |
||||
|
} else { |
||||
|
showToast(res.msg || '操作失败'); |
||||
|
} |
||||
|
}, |
||||
|
() => { |
||||
|
submitting.value = false; |
||||
|
showToast('网络错误,请重试'); |
||||
|
} |
||||
|
); |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style lang="less" scoped> |
||||
|
.plan-edit-page { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
height: 100%; |
||||
|
background: #eaf4ff; |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
:deep(.van-nav-bar) { |
||||
|
background: #347bc3; |
||||
|
flex-shrink: 0; |
||||
|
|
||||
|
.van-nav-bar__title { |
||||
|
color: #fff; |
||||
|
font-size: 18px; |
||||
|
font-weight: 600; |
||||
|
} |
||||
|
|
||||
|
.van-icon { |
||||
|
color: #fff; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.content { |
||||
|
flex: 1; |
||||
|
overflow-y: auto; |
||||
|
padding: 12px; |
||||
|
} |
||||
|
|
||||
|
.notice-bar { |
||||
|
border-radius: 8px; |
||||
|
margin-bottom: 12px; |
||||
|
border: 1px solid #f3dfa5; |
||||
|
} |
||||
|
|
||||
|
.form-card { |
||||
|
background: #fff; |
||||
|
border-radius: 14px; |
||||
|
overflow: hidden; |
||||
|
box-shadow: 0 4px 14px rgba(44, 116, 190, 0.08); |
||||
|
|
||||
|
:deep(.van-field) { |
||||
|
padding: 14px; |
||||
|
} |
||||
|
|
||||
|
:deep(.van-field__label) { |
||||
|
width: 80px; |
||||
|
font-size: 15px; |
||||
|
color: #333; |
||||
|
} |
||||
|
|
||||
|
:deep(.van-radio-group--horizontal) { |
||||
|
gap: 24px; |
||||
|
} |
||||
|
|
||||
|
:deep(.van-radio__label) { |
||||
|
font-size: 15px; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.person-box { |
||||
|
flex: 1; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
gap: 8px; |
||||
|
} |
||||
|
|
||||
|
.person-line { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
font-size: 15px; |
||||
|
color: #666; |
||||
|
gap: 8px; |
||||
|
|
||||
|
.person-name { |
||||
|
margin-right: 4px; |
||||
|
} |
||||
|
|
||||
|
.person-phone { |
||||
|
color: #999; |
||||
|
} |
||||
|
|
||||
|
.person-remove { |
||||
|
margin-left: auto; |
||||
|
color: #999; |
||||
|
font-size: 16px; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.add-person-line { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: space-between; |
||||
|
color: #c4c9cf; |
||||
|
font-size: 15px; |
||||
|
cursor: pointer; |
||||
|
|
||||
|
.placeholder-text { |
||||
|
color: #c4c9cf; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.submit-wrap { |
||||
|
padding: 22px 0 0; |
||||
|
|
||||
|
:deep(.van-button) { |
||||
|
height: 50px; |
||||
|
font-size: 17px; |
||||
|
font-weight: 500; |
||||
|
background: linear-gradient(135deg, #1890ff, #0b63d1); |
||||
|
border: none; |
||||
|
box-shadow: 0 8px 20px rgba(24, 144, 255, 0.28); |
||||
|
} |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,134 @@ |
|||||
|
<template> |
||||
|
<div class="plan-page app_content"> |
||||
|
<!-- 顶部导航 --> |
||||
|
<van-nav-bar |
||||
|
title="计划" |
||||
|
left-arrow |
||||
|
@click-left="onBack" |
||||
|
/> |
||||
|
|
||||
|
<!-- Tab 切换 --> |
||||
|
<van-tabs |
||||
|
v-model:active="activeTab" |
||||
|
title-active-color="#111" |
||||
|
title-inactive-color="#666" |
||||
|
color="#2f8bd3" |
||||
|
line-width="36px" |
||||
|
line-height="2px" |
||||
|
:border="false" |
||||
|
> |
||||
|
<van-tab title="我的计划" name="mine"> |
||||
|
<cp-plan-mine @edit="onEdit" /> |
||||
|
</van-tab> |
||||
|
<van-tab title="其他计划" name="other"> |
||||
|
<cp-plan-other /> |
||||
|
</van-tab> |
||||
|
</van-tabs> |
||||
|
|
||||
|
<!-- 悬浮新增按钮 --> |
||||
|
<div class="add-btn" @click="onAdd"> |
||||
|
<van-icon name="plus" size="22" color="#fff" /> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script setup name="cpPlanList"> |
||||
|
import { useRouter } from 'vue-router'; |
||||
|
import CpPlanMine from './cp_plan_mine.vue'; |
||||
|
import CpPlanOther from './cp_plan_other.vue'; |
||||
|
|
||||
|
const router = useRouter(); |
||||
|
const activeTab = ref('mine'); |
||||
|
|
||||
|
const onBack = () => { |
||||
|
router.back(); |
||||
|
}; |
||||
|
|
||||
|
const onAdd = () => { |
||||
|
router.push({ path: '/enforcement/plan/edit' }); |
||||
|
}; |
||||
|
|
||||
|
const onEdit = (item) => { |
||||
|
router.push({ path: '/enforcement/plan/edit', query: { id: item.id } }); |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style lang="less" scoped> |
||||
|
.plan-page { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
height: 100%; |
||||
|
background: #eaf4ff; |
||||
|
position: relative; |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
:deep(.van-nav-bar) { |
||||
|
background: #347bc3; |
||||
|
flex-shrink: 0; |
||||
|
|
||||
|
.van-nav-bar__title { |
||||
|
color: #fff; |
||||
|
font-size: 18px; |
||||
|
font-weight: 600; |
||||
|
} |
||||
|
|
||||
|
.van-icon { |
||||
|
color: #fff; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
:deep(.van-tabs) { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
flex: 1; |
||||
|
min-height: 0; |
||||
|
} |
||||
|
|
||||
|
:deep(.van-tabs__wrap) { |
||||
|
height: 54px; |
||||
|
background: #fff; |
||||
|
border-bottom: 1px solid #e4edf7; |
||||
|
flex-shrink: 0; |
||||
|
} |
||||
|
|
||||
|
:deep(.van-tab) { |
||||
|
font-size: 16px; |
||||
|
} |
||||
|
|
||||
|
:deep(.van-tab--active) { |
||||
|
font-weight: 600; |
||||
|
} |
||||
|
|
||||
|
:deep(.van-tabs__content), |
||||
|
:deep(.van-tabs__track), |
||||
|
:deep(.van-tab__panel-wrapper), |
||||
|
:deep(.van-tab__pane) { |
||||
|
flex: 1; |
||||
|
min-height: 0; |
||||
|
height: 100%; |
||||
|
} |
||||
|
|
||||
|
:deep(.van-tabs__content) { |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
.add-btn { |
||||
|
position: fixed; |
||||
|
right: 22px; |
||||
|
bottom: 28px; |
||||
|
width: 56px; |
||||
|
height: 56px; |
||||
|
border-radius: 50%; |
||||
|
background: linear-gradient(135deg, #1890ff, #0b63d1); |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
box-shadow: 0 8px 20px rgba(24, 144, 255, 0.38); |
||||
|
z-index: 100; |
||||
|
|
||||
|
&:active { |
||||
|
transform: scale(0.96); |
||||
|
} |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,320 @@ |
|||||
|
<template> |
||||
|
<div class="plan-mine"> |
||||
|
<van-pull-refresh v-model="refreshing" @refresh="onRefresh"> |
||||
|
<van-list |
||||
|
v-model:loading="loading" |
||||
|
:finished="finished" |
||||
|
finished-text="没有更多了" |
||||
|
@load="onLoad" |
||||
|
> |
||||
|
<div class="plan-list"> |
||||
|
<!-- 第一条高亮卡片 --> |
||||
|
<section |
||||
|
v-for="(item, index) in planList" |
||||
|
:key="item.id" |
||||
|
class="plan-card" |
||||
|
:class="index === 0 ? 'primary-card' : 'normal-card'" |
||||
|
> |
||||
|
<div class="card-header"> |
||||
|
<div class="card-type">{{ item.isUnion === 1 ? '联合执法' : '普通执法' }}</div> |
||||
|
<div class="status" :class="index === 0 ? '' : 'blue'"> |
||||
|
{{ getStatusText(item.reserveStatus) }} |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="plan-title">{{ item.enforceContent }}</div> |
||||
|
|
||||
|
<div class="info-row"> |
||||
|
<div class="label" :class="index !== 0 ? 'dark' : ''">执法单位:</div> |
||||
|
<div class="value" :class="index !== 0 ? 'gray' : ''">{{ item.bureauDeptName }}</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="info-row"> |
||||
|
<div class="label" :class="index !== 0 ? 'dark' : ''">执法人员:</div> |
||||
|
<div class="value" :class="[index !== 0 ? 'gray' : '', 'multi']"> |
||||
|
<span v-for="(name, i) in getPersonList(item)" :key="i">{{ name }}</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="info-row"> |
||||
|
<div class="label" :class="index !== 0 ? 'dark' : ''">计划时间:</div> |
||||
|
<div class="value" :class="index !== 0 ? 'gray' : ''"> |
||||
|
{{ item.planDate }} {{ getPlanTimeText(item.planTime) }} |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="info-row"> |
||||
|
<div class="label" :class="index !== 0 ? 'dark' : ''">企业名称:</div> |
||||
|
<div class="value" :class="index !== 0 ? 'gray' : ''">{{ item.enterpriseName }}</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="card-actions" :class="index === 0 ? 'primary-actions' : ''"> |
||||
|
<div |
||||
|
class="action-item" |
||||
|
:class="index !== 0 ? 'blue-action' : ''" |
||||
|
@click="onEditPlan(item)" |
||||
|
> |
||||
|
<van-icon name="edit" /> |
||||
|
<span>编辑</span> |
||||
|
</div> |
||||
|
<div |
||||
|
class="action-item" |
||||
|
:class="index !== 0 ? 'blue-action' : ''" |
||||
|
@click="onDeletePlan(item)" |
||||
|
> |
||||
|
<van-icon name="delete-o" /> |
||||
|
<span>删除</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
</section> |
||||
|
</div> |
||||
|
|
||||
|
<!-- 空状态 --> |
||||
|
<van-empty v-if="!loading && planList.length === 0" description="暂无计划" /> |
||||
|
</van-list> |
||||
|
</van-pull-refresh> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script setup name="cpPlanMine"> |
||||
|
import { showConfirmDialog, showToast } from 'vant'; |
||||
|
import { getPlanList, deletePlan } from '@/api/enforcement/plan'; |
||||
|
|
||||
|
const emit = defineEmits(['edit']); |
||||
|
|
||||
|
const planList = ref([]); |
||||
|
const loading = ref(false); |
||||
|
const finished = ref(false); |
||||
|
const refreshing = ref(false); |
||||
|
const pageNum = ref(1); |
||||
|
const pageSize = 10; |
||||
|
|
||||
|
// 状态文本映射 |
||||
|
const getStatusText = (status) => { |
||||
|
const map = { 0: '草稿', 1: '待预约', 2: '预约中', 3: '预约完成' }; |
||||
|
return map[status] || '待确认'; |
||||
|
}; |
||||
|
|
||||
|
// 时段文本 |
||||
|
const getPlanTimeText = (time) => { |
||||
|
const map = { 1: '上午', 2: '下午', 3: '其他' }; |
||||
|
return map[time] || ''; |
||||
|
}; |
||||
|
|
||||
|
// 获取人员列表 |
||||
|
const getPersonList = (item) => { |
||||
|
if (!item.enforceUserNames) return []; |
||||
|
return item.enforceUserNames.split(','); |
||||
|
}; |
||||
|
|
||||
|
// 加载数据 |
||||
|
const onLoad = () => { |
||||
|
fetchList(); |
||||
|
}; |
||||
|
|
||||
|
// 下拉刷新 |
||||
|
const onRefresh = () => { |
||||
|
pageNum.value = 1; |
||||
|
finished.value = false; |
||||
|
planList.value = []; |
||||
|
fetchList(); |
||||
|
}; |
||||
|
|
||||
|
// 请求列表 |
||||
|
const fetchList = () => { |
||||
|
loading.value = true; |
||||
|
getPlanList( |
||||
|
{ pageNum: pageNum.value, pageSize }, |
||||
|
(res) => { |
||||
|
refreshing.value = false; |
||||
|
loading.value = false; |
||||
|
if (res.code === 200) { |
||||
|
const rows = res.rows || []; |
||||
|
if (pageNum.value === 1) { |
||||
|
planList.value = rows; |
||||
|
} else { |
||||
|
planList.value.push(...rows); |
||||
|
} |
||||
|
if (rows.length < pageSize) { |
||||
|
finished.value = true; |
||||
|
} else { |
||||
|
pageNum.value++; |
||||
|
} |
||||
|
} else { |
||||
|
finished.value = true; |
||||
|
} |
||||
|
}, |
||||
|
() => { |
||||
|
refreshing.value = false; |
||||
|
loading.value = false; |
||||
|
finished.value = true; |
||||
|
} |
||||
|
); |
||||
|
}; |
||||
|
|
||||
|
// 编辑 |
||||
|
const onEditPlan = (item) => { |
||||
|
emit('edit', item); |
||||
|
}; |
||||
|
|
||||
|
// 删除 |
||||
|
const onDeletePlan = (item) => { |
||||
|
showConfirmDialog({ |
||||
|
title: '提示', |
||||
|
message: '确定要删除该计划吗?', |
||||
|
}).then(() => { |
||||
|
deletePlan(item.id, (res) => { |
||||
|
if (res.code === 200) { |
||||
|
showToast('删除成功'); |
||||
|
onRefresh(); |
||||
|
} else { |
||||
|
showToast(res.msg || '删除失败'); |
||||
|
} |
||||
|
}); |
||||
|
}).catch(() => {}); |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style lang="less" scoped> |
||||
|
.plan-mine { |
||||
|
height: 100%; |
||||
|
overflow-y: auto; |
||||
|
padding: 12px; |
||||
|
box-sizing: border-box; |
||||
|
} |
||||
|
|
||||
|
.plan-list { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
gap: 14px; |
||||
|
} |
||||
|
|
||||
|
/* 卡片通用 */ |
||||
|
.plan-card { |
||||
|
border-radius: 14px; |
||||
|
padding: 16px; |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
.card-header { |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
align-items: center; |
||||
|
margin-bottom: 14px; |
||||
|
} |
||||
|
|
||||
|
.card-type { |
||||
|
font-size: 17px; |
||||
|
font-weight: 500; |
||||
|
} |
||||
|
|
||||
|
.status { |
||||
|
font-size: 14px; |
||||
|
color: #f5c189; |
||||
|
|
||||
|
&.blue { |
||||
|
color: #1f75c9; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.plan-title { |
||||
|
display: block; |
||||
|
font-size: 17px; |
||||
|
font-weight: 700; |
||||
|
line-height: 1.5; |
||||
|
margin-bottom: 14px; |
||||
|
white-space: nowrap; |
||||
|
overflow: hidden; |
||||
|
text-overflow: ellipsis; |
||||
|
} |
||||
|
|
||||
|
.info-row { |
||||
|
display: flex; |
||||
|
align-items: flex-start; |
||||
|
margin-bottom: 8px; |
||||
|
font-size: 14px; |
||||
|
line-height: 1.5; |
||||
|
} |
||||
|
|
||||
|
.label { |
||||
|
width: 72px; |
||||
|
flex-shrink: 0; |
||||
|
color: rgba(255, 255, 255, 0.95); |
||||
|
font-weight: 500; |
||||
|
|
||||
|
&.dark { |
||||
|
color: #333; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.value { |
||||
|
flex: 1; |
||||
|
color: rgba(255, 255, 255, 0.72); |
||||
|
|
||||
|
&.gray { |
||||
|
color: #8a8a8a; |
||||
|
} |
||||
|
|
||||
|
&.multi { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
gap: 4px; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* 蓝色高亮卡片 */ |
||||
|
.primary-card { |
||||
|
background: linear-gradient(135deg, #0d56c8 0%, #278fe0 100%); |
||||
|
color: #fff; |
||||
|
box-shadow: 0 6px 16px rgba(28, 108, 202, 0.25); |
||||
|
|
||||
|
.card-type { |
||||
|
color: rgba(255, 255, 255, 0.82); |
||||
|
} |
||||
|
|
||||
|
.plan-title { |
||||
|
color: #fff; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* 普通卡片 */ |
||||
|
.normal-card { |
||||
|
background: #fff; |
||||
|
box-shadow: 0 4px 14px rgba(44, 116, 190, 0.08); |
||||
|
|
||||
|
.card-type { |
||||
|
color: #333; |
||||
|
} |
||||
|
|
||||
|
.plan-title { |
||||
|
color: #111; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* 操作区域 */ |
||||
|
.card-actions { |
||||
|
margin-top: 14px; |
||||
|
padding-top: 12px; |
||||
|
border-top: 1px solid rgba(0, 0, 0, 0.06); |
||||
|
display: flex; |
||||
|
justify-content: flex-end; |
||||
|
gap: 24px; |
||||
|
|
||||
|
&.primary-actions { |
||||
|
border-top-color: rgba(255, 255, 255, 0.18); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.action-item { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
gap: 4px; |
||||
|
font-size: 14px; |
||||
|
color: rgba(255, 255, 255, 0.88); |
||||
|
cursor: pointer; |
||||
|
|
||||
|
&.blue-action { |
||||
|
color: #2382cf; |
||||
|
} |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,21 @@ |
|||||
|
<template> |
||||
|
<div class="plan-other"> |
||||
|
<van-empty |
||||
|
image="search" |
||||
|
description="其他计划功能开发中" |
||||
|
/> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script setup name="cpPlanOther"> |
||||
|
</script> |
||||
|
|
||||
|
<style lang="less" scoped> |
||||
|
.plan-other { |
||||
|
height: 100%; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
padding: 60px 0; |
||||
|
} |
||||
|
</style> |
||||
Loading…
Reference in new issue