Files
RuoYi-Vue/ruoyi-ui/src/views/office/copyTemplate/index.vue
王鹏 6940541216 feat: 新增文案模板管理功能,源码明细页按钮支持动态配置
- 新增 tt_copy_template 表及 CRUD 后端接口
- 新增文案模板管理页面,支持 {变量} 占位符动态替换
- 源码明细页复制按钮由硬编码改为数据库驱动
- 支持占位符:codeName、projectCode、projectName、codeDesc、codeEnvironment、codeTechnology、diskLink、screenshots

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 19:20:32 +08:00

232 lines
8.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="80px">
<el-form-item label="按钮名称" prop="templateName">
<el-input
v-model="queryParams.templateName"
placeholder="请输入按钮名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable>
<el-option label="正常" value="0" />
<el-option label="停用" value="1" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['office:copyTemplate:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate" v-hasPermi="['office:copyTemplate:edit']">修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete" v-hasPermi="['office:copyTemplate:remove']">删除</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="templateList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="按钮名称" align="center" prop="templateName" width="160" />
<el-table-column label="排序" align="center" prop="sortNum" width="80" />
<el-table-column label="状态" align="center" prop="status" width="100">
<template slot-scope="scope">
<el-tag :type="scope.row.status === '0' ? 'success' : 'danger'">
{{ scope.row.status === '0' ? '正常' : '停用' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="模板内容(预览)" align="left" prop="templateBody" show-overflow-tooltip />
<el-table-column label="创建时间" align="center" prop="createTime" width="160" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="160">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['office:copyTemplate:edit']">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['office:copyTemplate:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
<!-- 新增或修改对话框 -->
<el-dialog :title="title" :visible.sync="open" width="900px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="90px">
<el-form-item label="按钮名称" prop="templateName">
<el-input v-model="form.templateName" placeholder="请输入按钮显示名称,例如:复制网站文案" />
</el-form-item>
<el-row>
<el-col :span="12">
<el-form-item label="排序" prop="sortNum">
<el-input-number v-model="form.sortNum" :min="0" :max="999" style="width:100%" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="状态" prop="status">
<el-radio-group v-model="form.status">
<el-radio label="0">正常</el-radio>
<el-radio label="1">停用</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="模板内容" prop="templateBody">
<el-input
v-model="form.templateBody"
type="textarea"
:rows="20"
placeholder="请输入文案模板内容,支持以下占位符:
{codeName} 项目名称(完整)
{projectCode} 项目编号(如 A075
{projectName} 纯项目名(去掉编号和基于...实现的前缀)
{codeDesc} 项目描述(纯文本)
{codeEnvironment} 运行环境
{codeTechnology} 项目技术
{diskLink} 网盘地址
{screenshots} 截图列表(自动生成 markdown 格式)"
/>
</el-form-item>
<el-alert type="info" :closable="false" style="margin-bottom:0">
<template slot="title">
<strong>支持的占位符</strong>
<code>{codeName}</code> 项目名称 &nbsp;
<code>{projectCode}</code> 项目编号 &nbsp;
<code>{projectName}</code> 纯项目名 &nbsp;
<code>{codeDesc}</code> 描述(纯文本) &nbsp;
<code>{codeEnvironment}</code> 运行环境 &nbsp;
<code>{codeTechnology}</code> 项目技术 &nbsp;
<code>{diskLink}</code> 网盘地址 &nbsp;
<code>{screenshots}</code> 截图列表
</template>
</el-alert>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { listCopyTemplate, getCopyTemplate, addCopyTemplate, updateCopyTemplate, delCopyTemplate } from "@/api/office/copyTemplate";
export default {
name: "CopyTemplate",
data() {
return {
loading: true,
ids: [],
single: true,
multiple: true,
showSearch: true,
total: 0,
templateList: [],
title: "",
open: false,
queryParams: {
pageNum: 1,
pageSize: 10,
templateName: null,
status: null
},
form: {},
rules: {
templateName: [{ required: true, message: "按钮名称不能为空", trigger: "blur" }],
templateBody: [{ required: true, message: "模板内容不能为空", trigger: "blur" }],
sortNum: [{ required: true, message: "排序不能为空", trigger: "blur" }]
}
};
},
created() {
this.getList();
},
methods: {
getList() {
this.loading = true;
listCopyTemplate(this.queryParams).then(response => {
this.templateList = response.rows;
this.total = response.total;
this.loading = false;
});
},
cancel() {
this.open = false;
this.reset();
},
reset() {
this.form = {
templateId: null,
templateName: null,
templateBody: null,
sortNum: 0,
status: "0"
};
this.resetForm("form");
},
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
handleSelectionChange(selection) {
this.ids = selection.map(item => item.templateId);
this.single = selection.length !== 1;
this.multiple = !selection.length;
},
handleAdd() {
this.reset();
this.open = true;
this.title = "新增文案模板";
},
handleUpdate(row) {
this.reset();
const templateId = row.templateId || this.ids;
getCopyTemplate(templateId).then(response => {
this.form = response.data;
this.open = true;
this.title = "修改文案模板";
});
},
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
if (this.form.templateId != null) {
updateCopyTemplate(this.form).then(() => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
});
} else {
addCopyTemplate(this.form).then(() => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
});
}
}
});
},
handleDelete(row) {
const templateIds = row.templateId || this.ids;
this.$modal.confirm('是否确认删除文案模板"' + (row.templateName || '') + '"').then(() => {
return delCopyTemplate(templateIds);
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
}
}
};
</script>