You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
462 lines
12 KiB
462 lines
12 KiB
<template>
|
|
<div ref="contractList" style="padding: 0 20px;">
|
|
<lx-header icon="md-apps" style="margin-bottom: 10px; border: 0px; margin-top: 15px" text="支付表格配置">
|
|
<div slot="content"></div>
|
|
<slot>
|
|
<!-- 搜索区域 -->
|
|
<div class="search-wrapper">
|
|
<div class="selects">
|
|
<div>
|
|
<span style="padding: 0 6px;word-break: keep-all;">表格名称</span>
|
|
<el-input v-model="searchForm.name" placeholder="请输入表格名称" style="width: 180px" />
|
|
</div>
|
|
|
|
<div>
|
|
<span style="padding: 0 6px;word-break: keep-all;">状态</span>
|
|
<el-select v-model="searchForm.status" placeholder="所有状态" style="width: 180px">
|
|
<el-option label="所有状态" value=""></el-option>
|
|
<el-option label="已启用" value="1"></el-option>
|
|
<el-option label="已禁用" value="0"></el-option>
|
|
</el-select>
|
|
</div>
|
|
|
|
<div>
|
|
<span style="padding: 0 6px;word-break: keep-all;">类型</span>
|
|
<el-select v-model="searchForm.type" placeholder="所有类型" style="width: 180px">
|
|
<el-option label="所有类型" value=""></el-option>
|
|
<el-option label="HTML" :value="1"></el-option>
|
|
<el-option label="DOCX" :value="2"></el-option>
|
|
</el-select>
|
|
</div>
|
|
|
|
<el-button style="margin-left: 10px" @click="resetSearch">重置</el-button>
|
|
<el-button style="margin-left: 10px" type="primary" @click="handleSearch">查询</el-button>
|
|
</div>
|
|
|
|
<!-- 新增按钮 -->
|
|
<div class="operation-wrapper">
|
|
<el-button type="primary" @click="handleCreate">新增</el-button>
|
|
</div>
|
|
</div>
|
|
</slot>
|
|
</lx-header>
|
|
|
|
|
|
<!-- 表格区域 -->
|
|
<div class="table-container">
|
|
<el-table :data="tableData" style="width: 100%">
|
|
<el-table-column prop="name" label="表格名称"></el-table-column>
|
|
<el-table-column prop="type" label="类型">
|
|
<template #default="scope">
|
|
{{ getTypeText(scope.row.type) }}
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column label="状态">
|
|
<template #default="scope">
|
|
<el-tag :type="getStatusType(scope.row.status)" effect="plain">
|
|
{{ getStatusText(scope.row.status) }}
|
|
</el-tag>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column prop="scenes" label="已使用场景"></el-table-column>
|
|
<el-table-column prop="created_at" label="创建时间"></el-table-column>
|
|
<el-table-column prop="updated_at" label="更新时间"></el-table-column>
|
|
<el-table-column label="操作" width="280">
|
|
<template #default="scope">
|
|
<div class="operation-buttons">
|
|
<el-button size="small" type="primary" plain @click="handleEdit(scope.row)">编辑</el-button>
|
|
<el-button size="small" type="info" plain @click="handlePreview(scope.row)">预览</el-button>
|
|
<el-button
|
|
size="small"
|
|
:type="scope.row.status === 0 ? 'success' : 'warning'"
|
|
plain
|
|
@click="handleStatusChange(scope.row)"
|
|
>
|
|
{{ scope.row.status === 0 ? '启用' : '禁用' }}
|
|
</el-button>
|
|
<el-button
|
|
size="small"
|
|
type="danger"
|
|
plain
|
|
@click="handleDelete(scope.row)"
|
|
>
|
|
删除
|
|
</el-button>
|
|
</div>
|
|
</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
|
|
<!-- 分页 -->
|
|
<div class="pagination-container">
|
|
<el-pagination
|
|
background
|
|
layout="prev, pager, next"
|
|
:total="total"
|
|
:current-page="currentPage"
|
|
@current-change="handlePageChange"
|
|
>
|
|
</el-pagination>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 添加预览模态框 -->
|
|
<el-dialog
|
|
title="模板预览"
|
|
:visible.sync="previewModalVisible"
|
|
width="80%"
|
|
:before-close="closePreviewModal"
|
|
top="5vh"
|
|
class="template-preview-dialog"
|
|
>
|
|
<div class="preview-header">
|
|
<h3>{{ currentTemplate.name }}</h3>
|
|
</div>
|
|
<div class="preview-container">
|
|
<!-- 预览HTML内容 -->
|
|
<div v-if="currentTemplate.type == 1 && currentTemplate.template"
|
|
class="html-preview"
|
|
v-html="formatHtmlForPreview(currentTemplate.template)"></div>
|
|
|
|
<!-- 预览DOCX内容 -->
|
|
<div v-else-if="currentTemplate.type == 2" class="docx-preview">
|
|
<el-empty description="DOCX预览功能正在开发中"></el-empty>
|
|
</div>
|
|
|
|
<!-- 无可预览内容 -->
|
|
<div v-else class="empty-preview">
|
|
<el-empty description="无预览内容"></el-empty>
|
|
</div>
|
|
</div>
|
|
</el-dialog>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { getContractFormList, deleteContractForm, saveContractForm } from '@/api/businessConfig/businessConfig'
|
|
|
|
export default {
|
|
name: 'PayFormConfig',
|
|
data() {
|
|
return {
|
|
searchForm: {
|
|
name: '',
|
|
status: '',
|
|
type: ''
|
|
},
|
|
tableData: [],
|
|
total: 0,
|
|
currentPage: 1,
|
|
pageSize: 10,
|
|
previewModalVisible: false,
|
|
currentTemplate: {}
|
|
}
|
|
},
|
|
created() {
|
|
this.fetchData()
|
|
},
|
|
methods: {
|
|
async fetchData() {
|
|
try {
|
|
const params = {
|
|
page: this.currentPage,
|
|
page_size: this.pageSize,
|
|
keyword: this.searchForm.name,
|
|
status: this.searchForm.status,
|
|
type: this.searchForm.type
|
|
}
|
|
const res = await getContractFormList(params)
|
|
if (res.errcode !== undefined) {
|
|
this.$message.error(res.errmsg || '获取数据失败')
|
|
return
|
|
}
|
|
this.tableData = res.data || []
|
|
this.total = res.total || 0
|
|
} catch (error) {
|
|
console.error('获取数据失败:', error)
|
|
this.$message.error('获取数据失败')
|
|
}
|
|
},
|
|
handleCreate() {
|
|
this.$router.push('/businessConfig/EditPayForm')
|
|
},
|
|
async handleSearch() {
|
|
this.currentPage = 1
|
|
await this.fetchData()
|
|
},
|
|
resetSearch() {
|
|
this.searchForm = {
|
|
name: '',
|
|
status: '',
|
|
type: ''
|
|
}
|
|
this.currentPage = 1
|
|
this.fetchData()
|
|
},
|
|
handleEdit(row) {
|
|
this.$router.push(`/businessConfig/EditPayForm?id=${row.id}`)
|
|
},
|
|
handlePreview(row) {
|
|
this.currentTemplate = {...row}
|
|
this.previewModalVisible = true
|
|
},
|
|
closePreviewModal() {
|
|
this.previewModalVisible = false
|
|
this.currentTemplate = {}
|
|
},
|
|
handleStatusChange(row) {
|
|
const status = row.status === 0 ? 1 : 0
|
|
const action = status === 1 ? '启用' : '禁用'
|
|
|
|
this.$confirm(`确定要${action}该表格吗?`, '提示', {
|
|
confirmButtonText: '确定',
|
|
cancelButtonText: '取消',
|
|
type: 'warning'
|
|
}).then(async () => {
|
|
try {
|
|
const params = {
|
|
id: row.id,
|
|
status: status,
|
|
// 保留其他必要字段
|
|
name: row.name,
|
|
type: row.type,
|
|
link_type: row.link_type
|
|
}
|
|
|
|
const res = await saveContractForm(params)
|
|
if (res.errcode !== undefined) {
|
|
this.$message.error(res.errmsg || `${action}失败`)
|
|
return
|
|
}
|
|
this.$message.success(`${action}成功`)
|
|
this.fetchData() // 重新加载数据
|
|
} catch (error) {
|
|
console.error(`${action}失败:`, error)
|
|
this.$message.error(`${action}失败`)
|
|
}
|
|
}).catch(() => {
|
|
this.$message.info('已取消操作')
|
|
})
|
|
},
|
|
async handlePageChange(page) {
|
|
this.currentPage = page
|
|
await this.fetchData()
|
|
},
|
|
getStatusType(status) {
|
|
const types = {
|
|
1: 'success', // 已启用
|
|
0: 'danger' // 已禁用
|
|
}
|
|
return types[status] || 'info'
|
|
},
|
|
getStatusText(status) {
|
|
const texts = {
|
|
1: '已启用',
|
|
0: '已禁用'
|
|
}
|
|
return texts[status] || '--'
|
|
},
|
|
getTypeText(type) {
|
|
const types = {
|
|
1: 'HTML',
|
|
2: 'DOCX'
|
|
}
|
|
return types[type] || type
|
|
},
|
|
formatDate(dateStr) {
|
|
if (!dateStr) return '--'
|
|
return dateStr
|
|
},
|
|
handleDelete(row) {
|
|
this.$confirm('确定要删除该表格吗?删除后不可恢复。', '提示', {
|
|
confirmButtonText: '确定',
|
|
cancelButtonText: '取消',
|
|
type: 'warning'
|
|
}).then(async () => {
|
|
try {
|
|
const res = await deleteContractForm(row.id)
|
|
if (res.errcode !== undefined) {
|
|
this.$message.error(res.errmsg || '删除失败')
|
|
return
|
|
}
|
|
this.$message.success('删除成功')
|
|
this.fetchData() // 重新加载数据
|
|
} catch (error) {
|
|
console.error('删除失败:', error)
|
|
this.$message.error('删除失败')
|
|
}
|
|
}).catch(() => {
|
|
this.$message.info('已取消删除')
|
|
})
|
|
},
|
|
// 格式化HTML用于预览
|
|
formatHtmlForPreview(html) {
|
|
if (!html) return ''
|
|
// 移除所有变量占位符
|
|
let processedHtml = html.replace(/\${[^}]+}/g, '')
|
|
// 将所有 display:none 样式改为 display:block
|
|
processedHtml = processedHtml.replace(/display:\s*none/g, 'display: block')
|
|
return processedHtml
|
|
},
|
|
// 获取DOCX文件的完整URL
|
|
getFullDocUrl(relativeUrl) {
|
|
// 当前网站的域名和协议
|
|
const baseUrl = window.location.origin
|
|
// 拼接完整的URL
|
|
return `${baseUrl}${relativeUrl}`
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.search-wrapper {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: flex-start;
|
|
margin-bottom: 16px;
|
|
margin-top: 16px;
|
|
}
|
|
|
|
.selects {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
align-items: center;
|
|
|
|
& > div {
|
|
margin-bottom: 6px;
|
|
display: flex;
|
|
align-items: center;
|
|
margin-right: 10px;
|
|
|
|
span {
|
|
white-space: nowrap;
|
|
color: #606266;
|
|
}
|
|
}
|
|
|
|
:deep(.el-input__inner) {
|
|
height: 32px;
|
|
line-height: 32px;
|
|
}
|
|
|
|
:deep(.el-button) {
|
|
height: 32px;
|
|
padding: 0 15px;
|
|
}
|
|
}
|
|
|
|
.operation-wrapper {
|
|
margin-left: 16px;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.table-container {
|
|
background-color: #fff;
|
|
padding: 20px;
|
|
border-radius: 5px;
|
|
box-shadow: 0 0 10px rgba(0,0,0,0.1);
|
|
}
|
|
|
|
.pagination-container {
|
|
margin-top: 20px;
|
|
display: flex;
|
|
justify-content: center;
|
|
}
|
|
|
|
.w-100 {
|
|
width: 100%;
|
|
}
|
|
|
|
:deep(.el-table) {
|
|
margin-top: 20px;
|
|
}
|
|
|
|
.operation-buttons {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 5px;
|
|
|
|
.el-button {
|
|
margin-left: 0 !important;
|
|
margin-right: 0;
|
|
}
|
|
}
|
|
|
|
.preview-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 20px;
|
|
padding-bottom: 15px;
|
|
border-bottom: 1px solid #ebeef5;
|
|
|
|
h3 {
|
|
margin: 0;
|
|
font-size: 18px;
|
|
color: #303133;
|
|
}
|
|
}
|
|
|
|
.preview-container {
|
|
background-color: #fff;
|
|
padding: 20px;
|
|
min-height: 500px;
|
|
max-height: 70vh;
|
|
overflow-y: auto;
|
|
border: 1px solid #ebeef5;
|
|
border-radius: 4px;
|
|
|
|
:deep(*) {
|
|
max-width: 100%;
|
|
}
|
|
}
|
|
|
|
.html-preview {
|
|
background-color: white;
|
|
padding: 15px;
|
|
border: 1px solid #dcdfe6;
|
|
border-radius: 4px;
|
|
min-height: 500px;
|
|
|
|
:deep(table) {
|
|
border-collapse: collapse;
|
|
width: 100%;
|
|
max-width: 100%;
|
|
}
|
|
|
|
:deep(td), :deep(th) {
|
|
border: 1px solid #000;
|
|
padding: 8px;
|
|
}
|
|
}
|
|
|
|
.docx-preview {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
height: 400px;
|
|
}
|
|
|
|
.empty-preview {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
height: 400px;
|
|
}
|
|
|
|
.template-preview-dialog {
|
|
:deep(.el-dialog__body) {
|
|
padding: 20px;
|
|
}
|
|
|
|
:deep(.el-dialog__header) {
|
|
padding: 15px 20px;
|
|
border-bottom: 1px solid #f0f0f0;
|
|
}
|
|
}
|
|
</style>
|
|
|
|
|
|
|