feat: 新增文案模板管理功能,源码明细页按钮支持动态配置
- 新增 tt_copy_template 表及 CRUD 后端接口
- 新增文案模板管理页面,支持 {变量} 占位符动态替换
- 源码明细页复制按钮由硬编码改为数据库驱动
- 支持占位符:codeName、projectCode、projectName、codeDesc、codeEnvironment、codeTechnology、diskLink、screenshots
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
52
ruoyi-ui/src/api/office/copyTemplate.js
Normal file
52
ruoyi-ui/src/api/office/copyTemplate.js
Normal file
@@ -0,0 +1,52 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询文案模板列表
|
||||
export function listCopyTemplate(query) {
|
||||
return request({
|
||||
url: '/office/copyTemplate/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询所有启用的文案模板(源码明细页按钮用)
|
||||
export function listEnabledTemplates() {
|
||||
return request({
|
||||
url: '/office/copyTemplate/enabled',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 查询文案模板详细
|
||||
export function getCopyTemplate(templateId) {
|
||||
return request({
|
||||
url: '/office/copyTemplate/' + templateId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增文案模板
|
||||
export function addCopyTemplate(data) {
|
||||
return request({
|
||||
url: '/office/copyTemplate',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改文案模板
|
||||
export function updateCopyTemplate(data) {
|
||||
return request({
|
||||
url: '/office/copyTemplate',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除文案模板
|
||||
export function delCopyTemplate(templateId) {
|
||||
return request({
|
||||
url: '/office/copyTemplate/' + templateId,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
@@ -308,13 +308,13 @@
|
||||
</el-descriptions>
|
||||
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="copySiteTextToClipboard">复制网站文案</el-button>
|
||||
<el-button type="primary" @click="copyXianyuTextToClipboard">复制闲鱼文案</el-button>
|
||||
<el-button type="primary" @click="copyXianyuTextToClipboard1">复制闲鱼文案1</el-button>
|
||||
<el-button type="primary" @click="copyOtherTextToClipboard">复制抖音、视频号、小红书文案</el-button>
|
||||
<el-button type="primary" @click="copyTextToClipboard">FeastCoding</el-button>
|
||||
<el-button type="primary" @click="copyTextToClipboard1">南音</el-button>
|
||||
<el-button @click="cancel">返 回</el-button>
|
||||
<el-button
|
||||
v-for="tpl in copyTemplates"
|
||||
:key="tpl.templateId"
|
||||
type="primary"
|
||||
@click="copyByTemplate(tpl)"
|
||||
>{{ tpl.templateName }}</el-button>
|
||||
<el-button @click="cancelDetail">返 回</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
@@ -335,6 +335,7 @@
|
||||
|
||||
<script>
|
||||
import {listCode, getCode, delCode, addCode, updateCode, transToArticle, transToArticle1} from "@/api/office/code";
|
||||
import {listEnabledTemplates} from "@/api/office/copyTemplate";
|
||||
import {html2Text} from "../../../utils";
|
||||
import {getToken} from "@/utils/auth";
|
||||
import request from '@/utils/request';
|
||||
@@ -389,11 +390,14 @@
|
||||
coverImageUrl: '',
|
||||
previewBlob: null,
|
||||
currentFileName: '',
|
||||
currentRow: ''
|
||||
currentRow: '',
|
||||
// 文案模板列表(动态按钮)
|
||||
copyTemplates: []
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
this.loadCopyTemplates();
|
||||
},
|
||||
computed: {
|
||||
previewList() {
|
||||
@@ -435,359 +439,69 @@
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
copyTextToClipboard() {
|
||||
let codeDesc = this.form.codeDesc.replace(/<\/p>/g, '</p>\n\n');
|
||||
// 先转换为纯文本
|
||||
let plainText = html2Text(codeDesc.trimEnd());
|
||||
// 处理纯文本中包含"角色"关键词的行添加####前缀
|
||||
plainText = plainText.replace(/^(.*)个角色(.*)$/gm, '#### $&');
|
||||
plainText = plainText.replace(/^(.*)角色:(.*)$/gm, '#### $&');
|
||||
|
||||
// 提取项目名称(去掉编号部分)
|
||||
let projectName = this.form.codeName;
|
||||
copyByTemplate(tpl) {
|
||||
// 从数据库模板中提取并替换占位符
|
||||
let codeName = this.form.codeName || '';
|
||||
let projectCode = '';
|
||||
let backendTech = '';
|
||||
let frontendTech = '';
|
||||
let projectName = codeName;
|
||||
|
||||
if (projectName) {
|
||||
// 提取项目编号 【A075】
|
||||
const codeMatch = projectName.match(/【(.+?)】/);
|
||||
if (codeMatch && codeMatch[1]) {
|
||||
projectCode = codeMatch[1];
|
||||
}
|
||||
|
||||
// 去掉编号部分,提取项目名称
|
||||
projectName = projectName.replace(/【.+?】/, '').trim();
|
||||
if (projectName.startsWith('基于')) {
|
||||
const nameMatch = projectName.match(/实现的(.+?)$/);
|
||||
if (nameMatch && nameMatch[1]) {
|
||||
projectName = nameMatch[1];
|
||||
}
|
||||
// 提取项目编号 【A075】
|
||||
const codeMatch = codeName.match(/【(.+?)】/);
|
||||
if (codeMatch && codeMatch[1]) {
|
||||
projectCode = codeMatch[1];
|
||||
}
|
||||
// 去掉编号部分,提取纯项目名称
|
||||
projectName = codeName.replace(/【.+?】/, '').trim();
|
||||
if (projectName.startsWith('基于')) {
|
||||
const nameMatch = projectName.match(/实现的(.+?)$/);
|
||||
if (nameMatch && nameMatch[1]) {
|
||||
projectName = nameMatch[1];
|
||||
}
|
||||
}
|
||||
|
||||
console.log('项目编号:', projectCode);
|
||||
console.log('后端技术:', backendTech);
|
||||
console.log('前端技术:', frontendTech);
|
||||
console.log('项目名称:', projectName);
|
||||
// 项目描述转纯文本
|
||||
let plainDesc = '';
|
||||
if (this.form.codeDesc) {
|
||||
let codeDesc = this.form.codeDesc.replace(/<\/p>/g, '</p>\n');
|
||||
plainDesc = html2Text(codeDesc.trimEnd());
|
||||
}
|
||||
|
||||
let content = '\n# 项目描述\n#### 视频演示\n' + plainText
|
||||
+ '\n\n# 技术选型'
|
||||
+ '\n* 开发工具:Idea + Vscode'
|
||||
+ '\n* 运行环境:JDK 1.8 + Maven + MySQL 5.7以上 + Node.js 14'
|
||||
+ '\n* 服务端技术:SpringBoot + Mybatis-Plus + Maven'
|
||||
+ '\n* 前端技术:Vue3 + Axios + Element-UI'
|
||||
+ '\n\n# 系统截图\n';
|
||||
|
||||
let index = 0
|
||||
if(this.form.fileList && this.form.fileList.length > 0){
|
||||
// 生成截图列表
|
||||
let screenshots = '';
|
||||
let index = 0;
|
||||
if (this.form.fileList && this.form.fileList.length > 0) {
|
||||
for (let item of this.form.fileList) {
|
||||
content = content + ++index + '.' + item.fileName
|
||||
+ '\n' + '' + '\n\n';
|
||||
screenshots = screenshots + ++index + '.' + item.fileName + '\n\n\n';
|
||||
}
|
||||
} else {
|
||||
content = content + '请前往微信小程序:南音源码库。查看项目详情!\n\n'
|
||||
screenshots = '请前往微信小程序:南音源码库。查看项目详情!\n\n';
|
||||
}
|
||||
|
||||
content = content + '# 运行步骤'
|
||||
+ '\n### 准备环境'
|
||||
+ '\n 安装JDK 1.8、Maven、Node.js 14 和 MySQL 5.7以上'
|
||||
+ '\n\n### 创建数据库'
|
||||
+ '\n 使用Navicat工具创建数据库并导入SQL脚本'
|
||||
+ '\n\n### 配置后端'
|
||||
+ '\n 修改`application.yml`中的数据库连接信息(用户名/密码/库名)'
|
||||
+ '\n\n### 启动后端服务'
|
||||
+ '\n 进入后端项目(`/server_code`) 执行:'
|
||||
+ '\n ```'
|
||||
+ '\n mvn clean install'
|
||||
+ '\n mvn spring-boot:run'
|
||||
+ '\n ```'
|
||||
+ '\n\n### 前端依赖安装'
|
||||
+ '\n 进入前端目录(`/manage_code`或者`/client_code`),执行安装命令:'
|
||||
+ '\n ```'
|
||||
+ '\n npm install'
|
||||
+ '\n ```'
|
||||
+ '\n '
|
||||
+ '\n### 启动前端服务'
|
||||
+ '\n 执行启动命令:'
|
||||
+ '\n ```'
|
||||
+ '\n npm run serve '
|
||||
+ '\n ```'
|
||||
+ '\n\n### 访问系统'
|
||||
+ '\n - 后端接口系统访问地址:'
|
||||
+ '\n `http://localhost:8080`'
|
||||
+ '\n - 后台系统前端访问地址:'
|
||||
+ '\n `http://localhost:8081`'
|
||||
+ '\n - 前台系统前端访问地址:'
|
||||
+ '\n `http://localhost:8082`'
|
||||
+ '\n\n### 常见问题'
|
||||
+ '\n#### 端口冲突'
|
||||
+ '\n - 修改后端配置文件`application.yml`'
|
||||
+ '\n - 修改前端配置文件`vue.config.js` '
|
||||
+ '\n\n#### 前端安装依赖失败'
|
||||
+ '\n - 删除node_modules、package-lock.json文件'
|
||||
+ '\n ```'
|
||||
+ '\n rm -rf node_modules package-lock.json'
|
||||
+ '\n ```'
|
||||
+ '\n - 清除缓存'
|
||||
+ '\n ```'
|
||||
+ '\n npm cache clean --force'
|
||||
+ '\n ```'
|
||||
+ '\n - 切换npm镜像源'
|
||||
+ '\n ```'
|
||||
+ '\n npm config set registry https://registry.npmmirror.com'
|
||||
+ '\n ```'
|
||||
+ '\n\n# 推荐阅读'
|
||||
+ '\n- [基于Springboot + vue3实现的果树系统](https://mp.weixin.qq.com/s/F7mO-9ENdfKqa89InlPUlg)'
|
||||
+ '\n- [基于Springboot + vue3实现的个人健康管理系统](https://mp.weixin.qq.com/s/UUUh4S2KfOnRKnLKZLlS3Q)'
|
||||
+ '\n- [基于Springboot + vue3实现的旅游网站系统](https://mp.weixin.qq.com/s/EY6XVtJXyY5FThfn0PoOew)'
|
||||
+ '\n- [基于Springboot + vue3实现的房屋租售系统](https://mp.weixin.qq.com/s/tbDCa5504JwOt-ECt3t_Yg)'
|
||||
+ '\n\n# 其他说明'
|
||||
+ '\n>* 1、本系统源码由**南音工作室**精心收集整理,并经过严格测试验证,确保运行稳定可靠。'
|
||||
+ '\n>* 2、**南音工作室**开始招募合伙人,有兴趣一起搞钱的小伙伴,可以在公众号后台回复关键词【**合伙人**】查看详细介绍。'
|
||||
+ '\n>* 3、如需获取详细运行教程,欢迎在公众号后台回复关键词【**运行教程**】,即可自助领取完整指导文档。'
|
||||
+ '\n>* 4、我们已为您整理上万套优质源码项目资源,回复【**源码搜索**】即可快速查找您需要的源码资源。'
|
||||
+ '\n>* 5、为了回馈粉丝,特意整理了海量福利资源免费分享,回复【**免费资源**】即可领取。'
|
||||
+ '\n>* 6、创作不易,如果觉得内容有帮助,别忘了**点赞/推荐/分享/收藏**支持我们,您的鼓励是我们持续更新的最大动力!'
|
||||
+ '\n\n# 源码获取'
|
||||
+ '\n\n<center>'
|
||||
+ '\n <img src="https://img.yidaima.cn/qrcode.jpg" style="width: 100px;">'
|
||||
+ '\n <br>'
|
||||
+ '\n <span>长按小程序码,打开小程序搜索 "<Strong style="color:var(--md-primary-color);">' + projectCode + '</Strong>" 即可获取资源</span>'
|
||||
+ '\n</center>';
|
||||
// 替换模板中的占位符
|
||||
let content = tpl.templateBody || '';
|
||||
content = content.replace(/{codeName}/g, codeName);
|
||||
content = content.replace(/{projectCode}/g, projectCode);
|
||||
content = content.replace(/{projectName}/g, projectName);
|
||||
content = content.replace(/{codeDesc}/g, plainDesc);
|
||||
content = content.replace(/{codeEnvironment}/g, this.form.codeEnvironment || '');
|
||||
content = content.replace(/{codeTechnology}/g, this.form.codeTechnology || '');
|
||||
content = content.replace(/{diskLink}/g, this.form.diskLink || '');
|
||||
content = content.replace(/{screenshots}/g, screenshots);
|
||||
|
||||
navigator.clipboard.writeText(content).then(() => {
|
||||
this.$message({
|
||||
message: '复制成功',
|
||||
type: 'success'
|
||||
});
|
||||
this.$message({ message: '复制成功', type: 'success' });
|
||||
}).catch(err => {
|
||||
this.$message({
|
||||
message: '复制失败: ' + err,
|
||||
type: 'error'
|
||||
});
|
||||
this.$message({ message: '复制失败: ' + err, type: 'error' });
|
||||
});
|
||||
},
|
||||
copyTextToClipboard1() {
|
||||
let codeDesc = this.form.codeDesc.replace(/<\/p>/g, '</p>\n\n');
|
||||
// 先转换为纯文本
|
||||
let plainText = html2Text(codeDesc.trimEnd());
|
||||
|
||||
// 提取项目名称(去掉编号部分)
|
||||
let projectCode = 'A081'; // 默认编号
|
||||
if (this.form.codeName) {
|
||||
const match = this.form.codeName.match(/【(.+?)】/);
|
||||
if (match && match[1]) {
|
||||
projectCode = match[1];
|
||||
}
|
||||
}
|
||||
|
||||
let content = '\n### 项目描述\n##### 视频演示\n' + plainText
|
||||
+ '\n\n### 技术选型'
|
||||
+ '\n**开发工具**:Idea + Vscode'
|
||||
+ '\n**运行环境**:JDK 1.8 + Maven + MySQL 5.7以上 + Node.js 14'
|
||||
+ '\n**服务端技术**:SpringBoot + Mybatis-Plus + Maven'
|
||||
+ '\n**前端技术**:Vue3 + Axios + Element-UI'
|
||||
+ '\n\n### 系统截图\n';
|
||||
|
||||
let index = 0
|
||||
if(this.form.fileList && this.form.fileList.length > 0){
|
||||
for (let item of this.form.fileList) {
|
||||
content = content + ++index + '.' + item.fileName
|
||||
+ '\n' + '' + '\n\n';
|
||||
}
|
||||
} else {
|
||||
content = content + '请前往微信小程序:南音源码库。查看项目详情!\n\n'
|
||||
}
|
||||
|
||||
content = content + '### 运行步骤'
|
||||
+ '\n##### 准备环境'
|
||||
+ '\n 安装JDK 1.8、Maven、Node.js 14 和 MySQL 5.7以上'
|
||||
+ '\n\n##### 创建数据库'
|
||||
+ '\n 使用Navicat工具创建数据库并导入SQL脚本'
|
||||
+ '\n\n##### 配置后端'
|
||||
+ '\n 修改`application.yml`中的数据库连接信息(用户名/密码/库名)'
|
||||
+ '\n\n##### 启动后端服务'
|
||||
+ '\n 进入后端项目(`/server_code`) 执行:'
|
||||
+ '\n ```'
|
||||
+ '\n mvn clean install'
|
||||
+ '\n mvn spring-boot:run'
|
||||
+ '\n ```'
|
||||
+ '\n\n##### 前端依赖安装'
|
||||
+ '\n 进入前端目录(`/manage_code`或者`/client_code`), 执行安装命令:'
|
||||
+ '\n ```'
|
||||
+ '\n npm install'
|
||||
+ '\n ```'
|
||||
+ '\n '
|
||||
+ '\n##### 启动前端服务'
|
||||
+ '\n 执行启动命令:'
|
||||
+ '\n ```'
|
||||
+ '\n npm run serve '
|
||||
+ '\n ```'
|
||||
+ '\n\n##### 访问系统'
|
||||
+ '\n - 后端接口系统访问地址:`http://localhost:8080`'
|
||||
+ '\n - 后台系统前端访问地址:`http://localhost:8081`'
|
||||
+ '\n - 前台系统前端访问地址:`http://localhost:8082`'
|
||||
+ '\n\n##### 常见问题'
|
||||
+ '\n###### 端口冲突'
|
||||
+ '\n - 修改后端配置文件`application.yml`'
|
||||
+ '\n - 修改前端配置文件`vue.config.js` '
|
||||
+ '\n\n###### 前端安装依赖失败'
|
||||
+ '\n - 删除node_modules、package-lock.json文件'
|
||||
+ '\n ```'
|
||||
+ '\n rm -rf node_modules package-lock.json'
|
||||
+ '\n ```'
|
||||
+ '\n - 清除缓存'
|
||||
+ '\n ```'
|
||||
+ '\n npm cache clean --force'
|
||||
+ '\n ```'
|
||||
+ '\n - 切换npm镜像源'
|
||||
+ '\n ```'
|
||||
+ '\n npm config set registry https://registry.npmmirror.com'
|
||||
+ '\n ```'
|
||||
+ '\n\n### 推荐阅读'
|
||||
+ '\n- [基于Springboot + vue3实现的果树系统](https://mp.weixin.qq.com/s/F7mO-9ENdfKqa89InlPUlg)'
|
||||
+ '\n- [基于Springboot + vue3实现的个人健康管理系统](https://mp.weixin.qq.com/s/UUUh4S2KfOnRKnLKZLlS3Q)'
|
||||
+ '\n- [基于Springboot + vue3实现的旅游网站系统](https://mp.weixin.qq.com/s/EY6XVtJXyY5FThfn0PoOew)'
|
||||
+ '\n- [基于Springboot + vue3实现的房屋租售系统](https://mp.weixin.qq.com/s/tbDCa5504JwOt-ECt3t_Yg)'
|
||||
+ '\n\n### 其他说明'
|
||||
+ '\n>1、本系统源码由**程序员南音**精心收集整理,并经过严格测试验证,确保运行稳定可靠。'
|
||||
+ '\n>2、创作不易,如果觉得内容有帮助,别忘了**点赞/推荐/分享/收藏**支持我们,您的鼓励是我们持续更新的最大动力!'
|
||||
+ '\n>3、温馨提示:系统可能存在少量待完善功能,欢迎有技术热情的小伙伴共同参与优化改进。'
|
||||
+ '\n\n# 源码获取'
|
||||
+ '\n\n<center>'
|
||||
+ '\n <img src="https://img.yidaima.cn/qrcode.jpg" style="width: 100px;">'
|
||||
+ '\n <br>'
|
||||
+ '\n <span>长按小程序码,打开小程序搜索 "<Strong style="color:var(--md-primary-color);">' + projectCode + '</Strong>" 即可获取资源</span>'
|
||||
+ '\n</center>';
|
||||
|
||||
navigator.clipboard.writeText(content).then(() => {
|
||||
this.$message({
|
||||
message: '复制成功',
|
||||
type: 'success'
|
||||
});
|
||||
}).catch(err => {
|
||||
this.$message({
|
||||
message: '复制失败: ' + err,
|
||||
type: 'error'
|
||||
});
|
||||
loadCopyTemplates() {
|
||||
listEnabledTemplates().then(response => {
|
||||
this.copyTemplates = response.data || [];
|
||||
});
|
||||
},
|
||||
copyXianyuTextToClipboard() {
|
||||
let codeDesc = this.form.codeDesc.replace(/<\/p>/g, '</p>\n');
|
||||
let content = this.form.codeName + '\n\n' + '### 项目描述' + '\n' + html2Text(codeDesc.trimEnd())
|
||||
+ '\n\n' + '### 运行环境' + '\n' + this.form.codeEnvironment
|
||||
+ '\n\n' + '### 项目技术' + '\n' + this.form.codeTechnology
|
||||
+ '\n\n标价包含项目源码+数据库脚本+文档,没有调试解答,由于此商品的可复制性,发货后,不退不换,介意勿拍';
|
||||
navigator.clipboard.writeText(content).then(() => {
|
||||
this.$message({
|
||||
message: '复制成功',
|
||||
type: 'success'
|
||||
});
|
||||
}).catch(err => {
|
||||
this.$message({
|
||||
message: '复制失败: ' + err,
|
||||
type: 'error'
|
||||
});
|
||||
});
|
||||
},
|
||||
copyXianyuTextToClipboard1() {
|
||||
let codeDesc = this.form.codeDesc.replace(/<\/p>/g, '</p>\n');
|
||||
|
||||
// 提取纯文本描述作为功能部分
|
||||
let functionDesc = html2Text(codeDesc.trimEnd());
|
||||
|
||||
// 分离项目编号、后端技术和前端技术
|
||||
let projectName = this.form.codeName;
|
||||
let projectCode = '';
|
||||
let backendTech = '';
|
||||
let frontendTech = '';
|
||||
|
||||
if (projectName) {
|
||||
// 提取项目编号 【A075】
|
||||
const codeMatch = projectName.match(/【(.+?)】/);
|
||||
if (codeMatch && codeMatch[1]) {
|
||||
projectCode = codeMatch[1];
|
||||
}
|
||||
|
||||
// 去掉编号部分,提取项目名称
|
||||
projectName = projectName.replace(/【.+?】/, '').trim();
|
||||
if (projectName.startsWith('基于')) {
|
||||
const nameMatch = projectName.match(/实现的(.+?)$/);
|
||||
if (nameMatch && nameMatch[1]) {
|
||||
projectName = nameMatch[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let content = projectName + '|Vue3|Java|SpringBoot|前后端分离|可提供远程调试|项目编号:'+projectCode
|
||||
+ '\n\n重要‼️:项目源码+环境部署教程+软件安装破解教程+项目运行教程'
|
||||
+ '\n\n技术'
|
||||
+ '\n①:架构: B/S、MVC'
|
||||
+ '\n②:系统环境:Windows/Mac'
|
||||
+ '\n③:开发环境:' + this.form.codeEnvironment
|
||||
+ '\n④:技术栈:' + this.form.codeTechnology
|
||||
+ '\n\n功能'
|
||||
+ '\n' + functionDesc;
|
||||
|
||||
navigator.clipboard.writeText(content).then(() => {
|
||||
this.$message({
|
||||
message: '复制成功',
|
||||
type: 'success'
|
||||
});
|
||||
}).catch(err => {
|
||||
this.$message({
|
||||
message: '复制失败: ' + err,
|
||||
type: 'error'
|
||||
});
|
||||
});
|
||||
},
|
||||
copyOtherTextToClipboard() {
|
||||
let codeDesc = this.form.codeDesc.replace(/<\/p>/g, '</p>\n');
|
||||
let content = this.form.codeName + '\n\n' + '### 项目描述' + '\n' + html2Text(codeDesc.trimEnd())
|
||||
+ '\n\n' + '### 运行环境' + '\n' + this.form.codeEnvironment
|
||||
+ '\n\n' + '### 项目技术' + '\n' + this.form.codeTechnology
|
||||
+ '\n\n获取项目源码资源,\\/X小CX:南音源码库';
|
||||
navigator.clipboard.writeText(content).then(() => {
|
||||
this.$message({
|
||||
message: '复制成功',
|
||||
type: 'success'
|
||||
});
|
||||
}).catch(err => {
|
||||
this.$message({
|
||||
message: '复制失败: ' + err,
|
||||
type: 'error'
|
||||
});
|
||||
});
|
||||
},
|
||||
copySiteTextToClipboard() {
|
||||
let codeDesc = this.form.codeDesc.replace(/<\/p>/g, '</p>\n\n');
|
||||
let content = this.form.codeName + '\n\n' + '#### 项目描述' + '\n' + html2Text(codeDesc.trimEnd())
|
||||
+ '\n\n' + '#### 运行环境' + '\n' + this.form.codeEnvironment
|
||||
+ '\n\n' + '#### 项目技术' + '\n' + this.form.codeTechnology
|
||||
+ '\n\n' + '#### 项目截图' + '\n';
|
||||
let index = 0
|
||||
if(this.form.fileList.length > 0){
|
||||
for (let item of this.form.fileList) {
|
||||
content = content + ++index + '.' + item.fileName
|
||||
+ '\n' + '' + '\n\n';
|
||||
}
|
||||
} else {
|
||||
content = content + '请前往微信小程序:南音源码库。查看项目详情!\n\n'
|
||||
}
|
||||
|
||||
content = content + '#### 资源下载' + '\n' + '' + '\n\n' + '请打开微信扫描上面小程序码,打开小程序搜索 "**项目编号**" 即可下载资源';
|
||||
navigator.clipboard.writeText(content).then(() => {
|
||||
this.$message({
|
||||
message: '复制成功',
|
||||
type: 'success'
|
||||
});
|
||||
}).catch(err => {
|
||||
this.$message({
|
||||
message: '复制失败: ' + err,
|
||||
type: 'error'
|
||||
});
|
||||
});
|
||||
cancelDetail() {
|
||||
this.openDetail = false;
|
||||
this.reset();
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
|
||||
232
ruoyi-ui/src/views/office/copyTemplate/index.vue
Normal file
232
ruoyi-ui/src/views/office/copyTemplate/index.vue
Normal file
@@ -0,0 +1,232 @@
|
||||
<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> 项目名称
|
||||
<code>{projectCode}</code> 项目编号
|
||||
<code>{projectName}</code> 纯项目名
|
||||
<code>{codeDesc}</code> 描述(纯文本)
|
||||
<code>{codeEnvironment}</code> 运行环境
|
||||
<code>{codeTechnology}</code> 项目技术
|
||||
<code>{diskLink}</code> 网盘地址
|
||||
<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>
|
||||
Reference in New Issue
Block a user