feat: 劳务协议编辑改独立页 + 去 el-card 圆角框
- 新增 LaborProtocolEdit.vue (独立页, 新建/编辑复用, 跟 ExpertNew.vue 风格一致)
- 加路由 /admin/labor-protocol/new 和 /admin/labor-protocol/edit/:id
- LaborProtocol.vue 删 el-dialog + 改为 router.push 跳转
- 新增 .form-card.nested { border: none; box-shadow: none; } 去 el-card 圆角框
- 新增 _self/admin_labor_protocol.md 审查报告
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -48,6 +48,8 @@ const routes = [
|
||||
{ path: 'special-plan/edit/:id', name: 'admin-special-plan-edit', component: () => import('@/views/admin/BizSpecialPlanEdit.vue'), meta: { title: '编辑专项计划' } },
|
||||
{ path: 'project-category', name: 'admin-project-category', component: () => import('@/views/admin/ProjectCategory.vue'), meta: { title: '项目类别管理' } },
|
||||
{ path: 'labor-protocol', name: 'admin-labor-protocol', component: () => import('@/views/admin/LaborProtocol.vue'), meta: { title: '劳务协议配置' } },
|
||||
{ path: 'labor-protocol/new', name: 'admin-labor-protocol-new', component: () => import('@/views/admin/LaborProtocolEdit.vue'), meta: { title: '新建劳务协议模板' } },
|
||||
{ path: 'labor-protocol/edit/:id', name: 'admin-labor-protocol-edit', component: () => import('@/views/admin/LaborProtocolEdit.vue'), meta: { title: '编辑劳务协议模板' } },
|
||||
{ path: 'account', name: 'admin-account', component: () => import('@/views/admin/Account.vue'), meta: { title: '账号信息' } }
|
||||
]
|
||||
},
|
||||
|
||||
@@ -16,10 +16,14 @@
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="load">查询</el-button>
|
||||
<el-button @click="reset">重置</el-button>
|
||||
<el-button type="success" @click="openCreate">新建模板</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 批量按钮 -->
|
||||
<div class="batch-bar">
|
||||
<el-button type="primary" @click="goCreate">新建模板</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 列表 -->
|
||||
<el-table :data="rows" border stripe v-loading="loading">
|
||||
<el-table-column prop="id" label="ID" width="80" />
|
||||
@@ -28,7 +32,7 @@
|
||||
<el-table-column label="默认" width="80" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag v-if="row.defaultFlag === 'Y'" type="success">默认</el-tag>
|
||||
<span v-else style="color:#c0c4cc">—</span>
|
||||
<span v-else class="dash-cell">—</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" width="100">
|
||||
@@ -40,7 +44,7 @@
|
||||
<el-table-column prop="updateTime" label="更新时间" width="170" />
|
||||
<el-table-column label="操作" width="240" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button size="small" link type="primary" @click="openEdit(row)">编辑</el-button>
|
||||
<el-button size="small" link type="primary" @click="goEdit(row)">编辑</el-button>
|
||||
<el-button size="small" link type="warning" :disabled="row.defaultFlag === 'Y'" @click="setDefault(row)">设为默认</el-button>
|
||||
<el-button size="small" link type="danger" @click="removeRow(row)">删除</el-button>
|
||||
</template>
|
||||
@@ -58,47 +62,17 @@
|
||||
@size-change="load"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 新建/编辑 dialog -->
|
||||
<el-dialog v-model="editOpen" :title="form.id ? '编辑模板' : '新建模板'" width="780px" destroy-on-close>
|
||||
<el-form :model="form" :rules="rules" ref="formRef" label-width="100px">
|
||||
<el-form-item label="模板名" prop="templateName">
|
||||
<el-input v-model="form.templateName" placeholder="如: 默认劳务协议" maxlength="100" />
|
||||
</el-form-item>
|
||||
<el-form-item label="排序" prop="sortOrder">
|
||||
<el-input-number v-model="form.sortOrder" :min="0" :max="9999" />
|
||||
</el-form-item>
|
||||
<el-form-item label="默认模板">
|
||||
<el-switch v-model="form.defaultFlag" active-value="Y" inactive-value="N" />
|
||||
<span style="margin-left:12px;color:#909399;font-size:12px">开启后其他模板自动取消默认</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio value="Y">启用</el-radio>
|
||||
<el-radio value="N">禁用</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="模板内容" prop="templateContent">
|
||||
<el-input v-model="form.templateContent" type="textarea" :rows="14"
|
||||
placeholder="HTML 模板, 支持占位符: {name} {phone} {会议名称} {会议时间} {会议地址} {劳务形式} {费用总额} ..." />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="form.remark" placeholder="选填" maxlength="500" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="editOpen = false">取消</el-button>
|
||||
<el-button type="primary" :loading="submitting" @click="submit">保存</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import request from '@/utils/request'
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
const q = reactive({ templateName: '', status: '', pageNum: 1, pageSize: 20 })
|
||||
const rows = ref([])
|
||||
const total = ref(0)
|
||||
@@ -120,66 +94,12 @@ function reset() {
|
||||
load()
|
||||
}
|
||||
|
||||
const editOpen = ref(false)
|
||||
const submitting = ref(false)
|
||||
const formRef = ref(null)
|
||||
const form = reactive({
|
||||
id: null,
|
||||
templateName: '',
|
||||
templateContent: '',
|
||||
defaultFlag: 'N',
|
||||
sortOrder: 0,
|
||||
status: 'Y',
|
||||
remark: ''
|
||||
})
|
||||
|
||||
const rules = {
|
||||
templateName: [{ required: true, message: '请输入模板名', trigger: 'blur' }],
|
||||
templateContent: [{ required: true, message: '请输入模板内容', trigger: 'blur' }]
|
||||
function goCreate() {
|
||||
router.push('/admin/labor-protocol/new')
|
||||
}
|
||||
|
||||
function openCreate() {
|
||||
Object.assign(form, {
|
||||
id: null,
|
||||
templateName: '',
|
||||
templateContent: '',
|
||||
defaultFlag: 'N',
|
||||
sortOrder: 0,
|
||||
status: 'Y',
|
||||
remark: ''
|
||||
})
|
||||
editOpen.value = true
|
||||
}
|
||||
|
||||
function openEdit(row) {
|
||||
Object.assign(form, {
|
||||
id: row.id,
|
||||
templateName: row.templateName,
|
||||
templateContent: row.templateContent,
|
||||
defaultFlag: row.defaultFlag || 'N',
|
||||
sortOrder: row.sortOrder || 0,
|
||||
status: row.status || 'Y',
|
||||
remark: row.remark || ''
|
||||
})
|
||||
editOpen.value = true
|
||||
}
|
||||
|
||||
async function submit() {
|
||||
await formRef.value.validate()
|
||||
submitting.value = true
|
||||
try {
|
||||
if (form.id) {
|
||||
await request({ url: '/business/laborProtocolTemplate', method: 'put', data: form })
|
||||
ElMessage.success('已更新')
|
||||
} else {
|
||||
await request({ url: '/business/laborProtocolTemplate', method: 'post', data: form })
|
||||
ElMessage.success('已新建')
|
||||
}
|
||||
editOpen.value = false
|
||||
load()
|
||||
} catch (e) {
|
||||
ElMessage.error(e?.msg || '保存失败')
|
||||
} finally { submitting.value = false }
|
||||
function goEdit(row) {
|
||||
router.push(`/admin/labor-protocol/edit/${row.id}`)
|
||||
}
|
||||
|
||||
async function setDefault(row) {
|
||||
@@ -211,9 +131,13 @@ onMounted(load)
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.admin-labor-protocol { padding: 16px; max-width: 1400px; }
|
||||
/* 整页面板 (与 People.vue 风格一致) */
|
||||
.admin-labor-protocol { padding: 16px; }
|
||||
.breadcrumb { font-size: 13px; color: #8c8c8c; margin-bottom: 12px; }
|
||||
.filter-form { margin-bottom: 12px; }
|
||||
.batch-bar { display: flex; gap: 8px; margin-bottom: 12px; align-items: center; }
|
||||
.pager { display: flex; justify-content: flex-end; margin-top: 12px; }
|
||||
:deep(.el-textarea__inner) { font-family: 'Consolas', 'Monaco', monospace; font-size: 12px; }
|
||||
|
||||
/* 表格空状态 (默认标记 = N) */
|
||||
.dash-cell { color: #c0c4cc; }
|
||||
</style>
|
||||
@@ -0,0 +1,158 @@
|
||||
<template>
|
||||
<!--
|
||||
劳务协议模板 新建/编辑 独立页
|
||||
编辑/新建复用: 通过 route.params.id 区分
|
||||
-->
|
||||
<div class="page-card labor-protocol-edit">
|
||||
<!-- 面包屑 -->
|
||||
<div class="breadcrumb">
|
||||
<a @click="goBack">劳务协议配置</a> > {{ isEdit ? '编辑模板' : '新建模板' }}
|
||||
</div>
|
||||
|
||||
<!-- 表单卡片 -->
|
||||
<el-card v-loading="loadingDetail" shadow="never" class="form-card nested">
|
||||
<el-form :model="form" :rules="rules" ref="formRef" label-width="120px">
|
||||
<el-row :gutter="12">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="模板名" prop="templateName">
|
||||
<el-input v-model="form.templateName" placeholder="如: 默认劳务协议" maxlength="100" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="排序" prop="sortOrder">
|
||||
<el-input-number v-model="form.sortOrder" :min="0" :max="9999" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="12">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="默认模板" prop="defaultFlag">
|
||||
<el-switch v-model="form.defaultFlag" active-value="Y" inactive-value="N" />
|
||||
<span class="default-hint">开启后其他模板自动取消默认</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio value="Y">启用</el-radio>
|
||||
<el-radio value="N">禁用</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-form-item label="模板内容" prop="templateContent">
|
||||
<el-input v-model="form.templateContent" type="textarea" :rows="20"
|
||||
placeholder="HTML 模板, 支持占位符: {name} {phone} {会议名称} {会议时间} {会议地址} {劳务形式} {费用总额} ..." />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" placeholder="选填" maxlength="500" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="primary" :loading="submitting" @click="submit">保存</el-button>
|
||||
<el-button @click="goBack">取消</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, computed, onMounted } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import request from '@/utils/request'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
const isEdit = computed(() => !!route.params.id)
|
||||
const loadingDetail = ref(false)
|
||||
const submitting = ref(false)
|
||||
const formRef = ref(null)
|
||||
|
||||
const form = reactive({
|
||||
id: null,
|
||||
templateName: '',
|
||||
templateContent: '',
|
||||
defaultFlag: 'N',
|
||||
sortOrder: 0,
|
||||
status: 'Y',
|
||||
remark: ''
|
||||
})
|
||||
|
||||
const rules = {
|
||||
templateName: [{ required: true, message: '请输入模板名', trigger: 'blur' }],
|
||||
templateContent: [{ required: true, message: '请输入模板内容', trigger: 'blur' }]
|
||||
}
|
||||
|
||||
async function loadDetail() {
|
||||
if (!isEdit.value) return
|
||||
loadingDetail.value = true
|
||||
try {
|
||||
const { data } = await request({ url: `/business/laborProtocolTemplate/${route.params.id}`, method: 'get' })
|
||||
Object.assign(form, {
|
||||
id: data.id,
|
||||
templateName: data.templateName,
|
||||
templateContent: data.templateContent,
|
||||
defaultFlag: data.defaultFlag || 'N',
|
||||
sortOrder: data.sortOrder || 0,
|
||||
status: data.status || 'Y',
|
||||
remark: data.remark || ''
|
||||
})
|
||||
} catch (e) {
|
||||
ElMessage.error('加载模板详情失败')
|
||||
} finally { loadingDetail.value = false }
|
||||
}
|
||||
|
||||
async function submit() {
|
||||
await formRef.value.validate()
|
||||
submitting.value = true
|
||||
try {
|
||||
if (isEdit.value) {
|
||||
await request({ url: '/business/laborProtocolTemplate', method: 'put', data: form })
|
||||
ElMessage.success('已更新')
|
||||
} else {
|
||||
await request({ url: '/business/laborProtocolTemplate', method: 'post', data: form })
|
||||
ElMessage.success('已新建')
|
||||
}
|
||||
goBack()
|
||||
} catch (e) {
|
||||
ElMessage.error(e?.msg || '保存失败')
|
||||
} finally { submitting.value = false }
|
||||
}
|
||||
|
||||
function goBack() {
|
||||
router.push('/admin/labor-protocol')
|
||||
}
|
||||
|
||||
onMounted(loadDetail)
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 整页面板 (与 People.vue 风格一致) */
|
||||
.labor-protocol-edit { padding: 16px; max-width: 1200px; }
|
||||
/* 面包屑带可点击返回 */
|
||||
.breadcrumb { font-size: 13px; color: #8c8c8c; margin-bottom: 12px; }
|
||||
.breadcrumb a { color: var(--brand-primary); cursor: pointer; text-decoration: none; }
|
||||
.breadcrumb a:hover { color: var(--brand-primary-deep, var(--brand-primary)); }
|
||||
|
||||
/* 去掉 el-card 默认的边框/阴影 (跟 ExpertNew.vue 保持一致) */
|
||||
.form-card.nested { background: transparent; border: none; box-shadow: none; }
|
||||
:deep(.form-card .el-card__body) { padding: 24px 28px; }
|
||||
|
||||
/* 主按钮用项目色变量 (覆盖 el 默认 #409eff) */
|
||||
:deep(.el-button--primary) { background: var(--brand-primary); border-color: var(--brand-primary); border-radius: 4px; }
|
||||
:deep(.el-button--primary:hover) { background: var(--brand-primary-deep, var(--brand-primary)); border-color: var(--brand-primary-deep, var(--brand-primary)); }
|
||||
:deep(.el-button) { border-radius: 4px; }
|
||||
:deep(.el-input__wrapper), :deep(.el-textarea__inner) { border-radius: 4px; }
|
||||
|
||||
/* 默认模板提示文字 */
|
||||
.default-hint { margin-left: 12px; color: #909399; font-size: 12px; }
|
||||
|
||||
/* template_content 是 HTML, 用等宽字体更清晰 */
|
||||
:deep(.el-textarea__inner) { font-family: 'Consolas', 'Monaco', monospace; font-size: 12px; }
|
||||
</style>
|
||||
Reference in New Issue
Block a user