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:
@@ -0,0 +1,106 @@
|
||||
package com.ruoyi.office.controller;
|
||||
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.enums.BusinessType;
|
||||
import com.ruoyi.office.domain.TtCopyTemplate;
|
||||
import com.ruoyi.office.service.ITtCopyTemplateService;
|
||||
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||
import com.ruoyi.common.core.page.TableDataInfo;
|
||||
|
||||
/**
|
||||
* 文案模板Controller
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-04-10
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/office/copyTemplate")
|
||||
public class TtCopyTemplateController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private ITtCopyTemplateService ttCopyTemplateService;
|
||||
|
||||
/**
|
||||
* 查询文案模板列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('office:copyTemplate:list')")
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo list(TtCopyTemplate ttCopyTemplate) {
|
||||
startPage();
|
||||
List<TtCopyTemplate> list = ttCopyTemplateService.selectTtCopyTemplateList(ttCopyTemplate);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有启用的文案模板(供源码明细页动态按钮使用,无需分页权限)
|
||||
*/
|
||||
@GetMapping("/enabled")
|
||||
public AjaxResult listEnabled() {
|
||||
return success(ttCopyTemplateService.selectEnabledTemplates());
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出文案模板列表
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('office:copyTemplate:export')")
|
||||
@Log(title = "文案模板", businessType = BusinessType.EXPORT)
|
||||
@PostMapping("/export")
|
||||
public void export(HttpServletResponse response, TtCopyTemplate ttCopyTemplate) {
|
||||
List<TtCopyTemplate> list = ttCopyTemplateService.selectTtCopyTemplateList(ttCopyTemplate);
|
||||
ExcelUtil<TtCopyTemplate> util = new ExcelUtil<TtCopyTemplate>(TtCopyTemplate.class);
|
||||
util.exportExcel(response, list, "文案模板数据");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文案模板详细信息
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('office:copyTemplate:query')")
|
||||
@GetMapping(value = "/{templateId}")
|
||||
public AjaxResult getInfo(@PathVariable("templateId") Long templateId) {
|
||||
return success(ttCopyTemplateService.selectTtCopyTemplateByTemplateId(templateId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增文案模板
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('office:copyTemplate:add')")
|
||||
@Log(title = "文案模板", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody TtCopyTemplate ttCopyTemplate) {
|
||||
return toAjax(ttCopyTemplateService.insertTtCopyTemplate(ttCopyTemplate));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改文案模板
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('office:copyTemplate:edit')")
|
||||
@Log(title = "文案模板", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody TtCopyTemplate ttCopyTemplate) {
|
||||
return toAjax(ttCopyTemplateService.updateTtCopyTemplate(ttCopyTemplate));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除文案模板
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('office:copyTemplate:remove')")
|
||||
@Log(title = "文案模板", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{templateIds}")
|
||||
public AjaxResult remove(@PathVariable Long[] templateIds) {
|
||||
return toAjax(ttCopyTemplateService.deleteTtCopyTemplateByTemplateIds(templateIds));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package com.ruoyi.office.domain;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import com.ruoyi.common.annotation.Excel;
|
||||
import com.ruoyi.common.core.domain.BaseEntity;
|
||||
|
||||
/**
|
||||
* 文案模板对象 tt_copy_template
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-04-10
|
||||
*/
|
||||
public class TtCopyTemplate extends BaseEntity {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 模板ID */
|
||||
private Long templateId;
|
||||
|
||||
/** 按钮显示名称 */
|
||||
@Excel(name = "按钮名称")
|
||||
private String templateName;
|
||||
|
||||
/** 文案模板内容,支持 {变量} 占位符 */
|
||||
@Excel(name = "模板内容")
|
||||
private String templateBody;
|
||||
|
||||
/** 排序号 */
|
||||
@Excel(name = "排序")
|
||||
private Integer sortNum;
|
||||
|
||||
/** 状态(0正常 1停用) */
|
||||
@Excel(name = "状态")
|
||||
private String status;
|
||||
|
||||
public void setTemplateId(Long templateId) {
|
||||
this.templateId = templateId;
|
||||
}
|
||||
|
||||
public Long getTemplateId() {
|
||||
return templateId;
|
||||
}
|
||||
|
||||
public void setTemplateName(String templateName) {
|
||||
this.templateName = templateName;
|
||||
}
|
||||
|
||||
public String getTemplateName() {
|
||||
return templateName;
|
||||
}
|
||||
|
||||
public void setTemplateBody(String templateBody) {
|
||||
this.templateBody = templateBody;
|
||||
}
|
||||
|
||||
public String getTemplateBody() {
|
||||
return templateBody;
|
||||
}
|
||||
|
||||
public void setSortNum(Integer sortNum) {
|
||||
this.sortNum = sortNum;
|
||||
}
|
||||
|
||||
public Integer getSortNum() {
|
||||
return sortNum;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
|
||||
.append("templateId", getTemplateId())
|
||||
.append("templateName", getTemplateName())
|
||||
.append("templateBody", getTemplateBody())
|
||||
.append("sortNum", getSortNum())
|
||||
.append("status", getStatus())
|
||||
.append("createTime", getCreateTime())
|
||||
.append("updateTime", getUpdateTime())
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.ruoyi.office.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import com.ruoyi.office.domain.TtCopyTemplate;
|
||||
|
||||
/**
|
||||
* 文案模板Mapper接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-04-10
|
||||
*/
|
||||
public interface TtCopyTemplateMapper {
|
||||
|
||||
/**
|
||||
* 查询文案模板
|
||||
*/
|
||||
public TtCopyTemplate selectTtCopyTemplateByTemplateId(Long templateId);
|
||||
|
||||
/**
|
||||
* 查询文案模板列表
|
||||
*/
|
||||
public List<TtCopyTemplate> selectTtCopyTemplateList(TtCopyTemplate ttCopyTemplate);
|
||||
|
||||
/**
|
||||
* 查询所有启用的文案模板(按排序号升序)
|
||||
*/
|
||||
public List<TtCopyTemplate> selectEnabledTemplates();
|
||||
|
||||
/**
|
||||
* 新增文案模板
|
||||
*/
|
||||
public int insertTtCopyTemplate(TtCopyTemplate ttCopyTemplate);
|
||||
|
||||
/**
|
||||
* 修改文案模板
|
||||
*/
|
||||
public int updateTtCopyTemplate(TtCopyTemplate ttCopyTemplate);
|
||||
|
||||
/**
|
||||
* 批量删除文案模板
|
||||
*/
|
||||
public int deleteTtCopyTemplateByTemplateIds(Long[] templateIds);
|
||||
|
||||
/**
|
||||
* 删除文案模板信息
|
||||
*/
|
||||
public int deleteTtCopyTemplateByTemplateId(Long templateId);
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.ruoyi.office.service;
|
||||
|
||||
import java.util.List;
|
||||
import com.ruoyi.office.domain.TtCopyTemplate;
|
||||
|
||||
/**
|
||||
* 文案模板Service接口
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-04-10
|
||||
*/
|
||||
public interface ITtCopyTemplateService {
|
||||
|
||||
/**
|
||||
* 查询文案模板
|
||||
*/
|
||||
public TtCopyTemplate selectTtCopyTemplateByTemplateId(Long templateId);
|
||||
|
||||
/**
|
||||
* 查询文案模板列表(带分页、筛选)
|
||||
*/
|
||||
public List<TtCopyTemplate> selectTtCopyTemplateList(TtCopyTemplate ttCopyTemplate);
|
||||
|
||||
/**
|
||||
* 查询所有启用的文案模板(供源码明细页按钮使用)
|
||||
*/
|
||||
public List<TtCopyTemplate> selectEnabledTemplates();
|
||||
|
||||
/**
|
||||
* 新增文案模板
|
||||
*/
|
||||
public int insertTtCopyTemplate(TtCopyTemplate ttCopyTemplate);
|
||||
|
||||
/**
|
||||
* 修改文案模板
|
||||
*/
|
||||
public int updateTtCopyTemplate(TtCopyTemplate ttCopyTemplate);
|
||||
|
||||
/**
|
||||
* 批量删除文案模板
|
||||
*/
|
||||
public int deleteTtCopyTemplateByTemplateIds(Long[] templateIds);
|
||||
|
||||
/**
|
||||
* 删除文案模板信息
|
||||
*/
|
||||
public int deleteTtCopyTemplateByTemplateId(Long templateId);
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.ruoyi.office.service.impl;
|
||||
|
||||
import java.util.List;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.ruoyi.common.utils.DateUtils;
|
||||
import com.ruoyi.office.domain.TtCopyTemplate;
|
||||
import com.ruoyi.office.mapper.TtCopyTemplateMapper;
|
||||
import com.ruoyi.office.service.ITtCopyTemplateService;
|
||||
|
||||
/**
|
||||
* 文案模板Service业务层处理
|
||||
*
|
||||
* @author ruoyi
|
||||
* @date 2026-04-10
|
||||
*/
|
||||
@Service
|
||||
public class TtCopyTemplateServiceImpl implements ITtCopyTemplateService {
|
||||
|
||||
@Autowired
|
||||
private TtCopyTemplateMapper ttCopyTemplateMapper;
|
||||
|
||||
@Override
|
||||
public TtCopyTemplate selectTtCopyTemplateByTemplateId(Long templateId) {
|
||||
return ttCopyTemplateMapper.selectTtCopyTemplateByTemplateId(templateId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TtCopyTemplate> selectTtCopyTemplateList(TtCopyTemplate ttCopyTemplate) {
|
||||
return ttCopyTemplateMapper.selectTtCopyTemplateList(ttCopyTemplate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TtCopyTemplate> selectEnabledTemplates() {
|
||||
return ttCopyTemplateMapper.selectEnabledTemplates();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int insertTtCopyTemplate(TtCopyTemplate ttCopyTemplate) {
|
||||
ttCopyTemplate.setCreateTime(DateUtils.getNowDate());
|
||||
return ttCopyTemplateMapper.insertTtCopyTemplate(ttCopyTemplate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateTtCopyTemplate(TtCopyTemplate ttCopyTemplate) {
|
||||
ttCopyTemplate.setUpdateTime(DateUtils.getNowDate());
|
||||
return ttCopyTemplateMapper.updateTtCopyTemplate(ttCopyTemplate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteTtCopyTemplateByTemplateIds(Long[] templateIds) {
|
||||
return ttCopyTemplateMapper.deleteTtCopyTemplateByTemplateIds(templateIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteTtCopyTemplateByTemplateId(Long templateId) {
|
||||
return ttCopyTemplateMapper.deleteTtCopyTemplateByTemplateId(templateId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.ruoyi.office.mapper.TtCopyTemplateMapper">
|
||||
|
||||
<resultMap type="TtCopyTemplate" id="TtCopyTemplateResult">
|
||||
<result property="templateId" column="template_id" />
|
||||
<result property="templateName" column="template_name" />
|
||||
<result property="templateBody" column="template_body" />
|
||||
<result property="sortNum" column="sort_num" />
|
||||
<result property="status" column="status" />
|
||||
<result property="createTime" column="create_time" />
|
||||
<result property="updateTime" column="update_time" />
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectTtCopyTemplateVo">
|
||||
select template_id, template_name, template_body, sort_num, status, create_time, update_time
|
||||
from tt_copy_template
|
||||
</sql>
|
||||
|
||||
<select id="selectTtCopyTemplateList" parameterType="TtCopyTemplate" resultMap="TtCopyTemplateResult">
|
||||
<include refid="selectTtCopyTemplateVo"/>
|
||||
<where>
|
||||
<if test="templateName != null and templateName != ''"> and template_name like concat('%', #{templateName}, '%')</if>
|
||||
<if test="status != null and status != ''"> and status = #{status}</if>
|
||||
</where>
|
||||
order by sort_num asc, create_time asc
|
||||
</select>
|
||||
|
||||
<select id="selectEnabledTemplates" resultMap="TtCopyTemplateResult">
|
||||
<include refid="selectTtCopyTemplateVo"/>
|
||||
where status = '0'
|
||||
order by sort_num asc, create_time asc
|
||||
</select>
|
||||
|
||||
<select id="selectTtCopyTemplateByTemplateId" parameterType="Long" resultMap="TtCopyTemplateResult">
|
||||
<include refid="selectTtCopyTemplateVo"/>
|
||||
where template_id = #{templateId}
|
||||
</select>
|
||||
|
||||
<insert id="insertTtCopyTemplate" parameterType="TtCopyTemplate" useGeneratedKeys="true" keyProperty="templateId">
|
||||
insert into tt_copy_template
|
||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
<if test="templateName != null and templateName != ''">template_name,</if>
|
||||
<if test="templateBody != null">template_body,</if>
|
||||
<if test="sortNum != null">sort_num,</if>
|
||||
<if test="status != null and status != ''">status,</if>
|
||||
<if test="createTime != null">create_time,</if>
|
||||
<if test="updateTime != null">update_time,</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="templateName != null and templateName != ''">#{templateName},</if>
|
||||
<if test="templateBody != null">#{templateBody},</if>
|
||||
<if test="sortNum != null">#{sortNum},</if>
|
||||
<if test="status != null and status != ''">#{status},</if>
|
||||
<if test="createTime != null">#{createTime},</if>
|
||||
<if test="updateTime != null">#{updateTime},</if>
|
||||
</trim>
|
||||
</insert>
|
||||
|
||||
<update id="updateTtCopyTemplate" parameterType="TtCopyTemplate">
|
||||
update tt_copy_template
|
||||
<trim prefix="SET" suffixOverrides=",">
|
||||
<if test="templateName != null and templateName != ''">template_name = #{templateName},</if>
|
||||
<if test="templateBody != null">template_body = #{templateBody},</if>
|
||||
<if test="sortNum != null">sort_num = #{sortNum},</if>
|
||||
<if test="status != null and status != ''">status = #{status},</if>
|
||||
<if test="updateTime != null">update_time = #{updateTime},</if>
|
||||
</trim>
|
||||
where template_id = #{templateId}
|
||||
</update>
|
||||
|
||||
<delete id="deleteTtCopyTemplateByTemplateId" parameterType="Long">
|
||||
delete from tt_copy_template where template_id = #{templateId}
|
||||
</delete>
|
||||
|
||||
<delete id="deleteTtCopyTemplateByTemplateIds" parameterType="Long">
|
||||
delete from tt_copy_template where template_id in
|
||||
<foreach item="templateId" collection="array" open="(" separator="," close=")">
|
||||
#{templateId}
|
||||
</foreach>
|
||||
</delete>
|
||||
|
||||
</mapper>
|
||||
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(/【(.+?)】/);
|
||||
const codeMatch = codeName.match(/【(.+?)】/);
|
||||
if (codeMatch && codeMatch[1]) {
|
||||
projectCode = codeMatch[1];
|
||||
}
|
||||
|
||||
// 去掉编号部分,提取项目名称
|
||||
projectName = projectName.replace(/【.+?】/, '').trim();
|
||||
// 去掉编号部分,提取纯项目名称
|
||||
projectName = codeName.replace(/【.+?】/, '').trim();
|
||||
if (projectName.startsWith('基于')) {
|
||||
const nameMatch = projectName.match(/实现的(.+?)$/);
|
||||
if (nameMatch && nameMatch[1]) {
|
||||
projectName = nameMatch[1];
|
||||
}
|
||||
}
|
||||
|
||||
// 项目描述转纯文本
|
||||
let plainDesc = '';
|
||||
if (this.form.codeDesc) {
|
||||
let codeDesc = this.form.codeDesc.replace(/<\/p>/g, '</p>\n');
|
||||
plainDesc = html2Text(codeDesc.trimEnd());
|
||||
}
|
||||
|
||||
console.log('项目编号:', projectCode);
|
||||
console.log('后端技术:', backendTech);
|
||||
console.log('前端技术:', frontendTech);
|
||||
console.log('项目名称:', projectName);
|
||||
|
||||
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>
|
||||
258
sql/copy_template.sql
Normal file
258
sql/copy_template.sql
Normal file
@@ -0,0 +1,258 @@
|
||||
-- ----------------------------
|
||||
-- 文案模板表
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS tt_copy_template;
|
||||
CREATE TABLE tt_copy_template (
|
||||
template_id BIGINT NOT NULL AUTO_INCREMENT COMMENT '模板ID',
|
||||
template_name VARCHAR(100) NOT NULL COMMENT '按钮显示名称',
|
||||
template_body LONGTEXT NOT NULL COMMENT '文案模板内容,支持 {变量} 占位符',
|
||||
sort_num INT DEFAULT 0 COMMENT '排序号',
|
||||
status CHAR(1) DEFAULT '0' COMMENT '状态(0正常 1停用)',
|
||||
create_by VARCHAR(64) DEFAULT '' COMMENT '创建者',
|
||||
create_time DATETIME COMMENT '创建时间',
|
||||
update_by VARCHAR(64) DEFAULT '' COMMENT '更新者',
|
||||
update_time DATETIME COMMENT '更新时间',
|
||||
remark VARCHAR(500) DEFAULT NULL COMMENT '备注',
|
||||
PRIMARY KEY (template_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文案模板表';
|
||||
|
||||
-- ----------------------------
|
||||
-- 文案模板初始数据
|
||||
-- ----------------------------
|
||||
INSERT INTO tt_copy_template (template_name, template_body, sort_num, status, create_time, create_by) VALUES
|
||||
|
||||
('复制网站文案', '{codeName}
|
||||
|
||||
#### 项目描述
|
||||
{codeDesc}
|
||||
|
||||
#### 运行环境
|
||||
{codeEnvironment}
|
||||
|
||||
#### 项目技术
|
||||
{codeTechnology}
|
||||
|
||||
#### 项目截图
|
||||
{screenshots}
|
||||
|
||||
#### 资源下载
|
||||

|
||||
|
||||
请打开微信扫描上面小程序码,打开小程序搜索 "**{projectCode}**" 即可下载资源', 1, '0', NOW(), 'admin'),
|
||||
|
||||
('复制闲鱼文案', '{codeName}
|
||||
|
||||
### 项目描述
|
||||
{codeDesc}
|
||||
|
||||
### 运行环境
|
||||
{codeEnvironment}
|
||||
|
||||
### 项目技术
|
||||
{codeTechnology}
|
||||
|
||||
标价包含项目源码+数据库脚本+文档,没有调试解答,由于此商品的可复制性,发货后,不退不换,介意勿拍', 2, '0', NOW(), 'admin'),
|
||||
|
||||
('复制闲鱼文案1', '{projectName}|Vue3|Java|SpringBoot|前后端分离|可提供远程调试|项目编号:{projectCode}
|
||||
|
||||
重要‼️:项目源码+环境部署教程+软件安装破解教程+项目运行教程
|
||||
|
||||
技术
|
||||
①:架构: B/S、MVC
|
||||
②:系统环境:Windows/Mac
|
||||
③:开发环境:{codeEnvironment}
|
||||
④:技术栈:{codeTechnology}
|
||||
|
||||
功能
|
||||
{codeDesc}', 3, '0', NOW(), 'admin'),
|
||||
|
||||
('复制抖音、视频号、小红书文案', '{codeName}
|
||||
|
||||
### 项目描述
|
||||
{codeDesc}
|
||||
|
||||
### 运行环境
|
||||
{codeEnvironment}
|
||||
|
||||
### 项目技术
|
||||
{codeTechnology}
|
||||
|
||||
获取项目源码资源,\\/X小CX:南音源码库', 4, '0', NOW(), 'admin'),
|
||||
|
||||
('FeastCoding', '
|
||||
# 项目描述
|
||||
#### 视频演示
|
||||
{codeDesc}
|
||||
|
||||
# 技术选型
|
||||
* 开发工具:Idea + Vscode
|
||||
* 运行环境:JDK 1.8 + Maven + MySQL 5.7以上 + Node.js 14
|
||||
* 服务端技术:SpringBoot + Mybatis-Plus + Maven
|
||||
* 前端技术:Vue3 + Axios + Element-UI
|
||||
|
||||
# 系统截图
|
||||
{screenshots}
|
||||
|
||||
# 运行步骤
|
||||
### 准备环境
|
||||
安装JDK 1.8、Maven、Node.js 14 和 MySQL 5.7以上
|
||||
|
||||
### 创建数据库
|
||||
使用Navicat工具创建数据库并导入SQL脚本
|
||||
|
||||
### 配置后端
|
||||
修改`application.yml`中的数据库连接信息(用户名/密码/库名)
|
||||
|
||||
### 启动后端服务
|
||||
进入后端项目(`/server_code`) 执行:
|
||||
```
|
||||
mvn clean install
|
||||
mvn spring-boot:run
|
||||
```
|
||||
|
||||
### 前端依赖安装
|
||||
进入前端目录(`/manage_code`或者`/client_code`),执行安装命令:
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
### 启动前端服务
|
||||
执行启动命令:
|
||||
```
|
||||
npm run serve
|
||||
```
|
||||
|
||||
### 访问系统
|
||||
- 后端接口系统访问地址:
|
||||
`http://localhost:8080`
|
||||
- 后台系统前端访问地址:
|
||||
`http://localhost:8081`
|
||||
- 前台系统前端访问地址:
|
||||
`http://localhost:8082`
|
||||
|
||||
### 常见问题
|
||||
#### 端口冲突
|
||||
- 修改后端配置文件`application.yml`
|
||||
- 修改前端配置文件`vue.config.js`
|
||||
|
||||
#### 前端安装依赖失败
|
||||
- 删除node_modules、package-lock.json文件
|
||||
```
|
||||
rm -rf node_modules package-lock.json
|
||||
```
|
||||
- 清除缓存
|
||||
```
|
||||
npm cache clean --force
|
||||
```
|
||||
- 切换npm镜像源
|
||||
```
|
||||
npm config set registry https://registry.npmmirror.com
|
||||
```
|
||||
|
||||
# 推荐阅读
|
||||
- [基于Springboot + vue3实现的果树系统](https://mp.weixin.qq.com/s/F7mO-9ENdfKqa89InlPUlg)
|
||||
- [基于Springboot + vue3实现的个人健康管理系统](https://mp.weixin.qq.com/s/UUUh4S2KfOnRKnLKZLlS3Q)
|
||||
- [基于Springboot + vue3实现的旅游网站系统](https://mp.weixin.qq.com/s/EY6XVtJXyY5FThfn0PoOew)
|
||||
- [基于Springboot + vue3实现的房屋租售系统](https://mp.weixin.qq.com/s/tbDCa5504JwOt-ECt3t_Yg)
|
||||
|
||||
# 其他说明
|
||||
>* 1、本系统源码由**南音工作室**精心收集整理,并经过严格测试验证,确保运行稳定可靠。
|
||||
>* 2、**南音工作室**开始招募合伙人,有兴趣一起搞钱的小伙伴,可以在公众号后台回复关键词【**合伙人**】查看详细介绍。
|
||||
>* 3、如需获取详细运行教程,欢迎在公众号后台回复关键词【**运行教程**】,即可自助领取完整指导文档。
|
||||
>* 4、我们已为您整理上万套优质源码项目资源,回复【**源码搜索**】即可快速查找您需要的源码资源。
|
||||
>* 5、为了回馈粉丝,特意整理了海量福利资源免费分享,回复【**免费资源**】即可领取。
|
||||
>* 6、创作不易,如果觉得内容有帮助,别忘了**点赞/推荐/分享/收藏**支持我们,您的鼓励是我们持续更新的最大动力!
|
||||
|
||||
# 源码获取
|
||||
|
||||
<center>
|
||||
<img src="https://img.yidaima.cn/qrcode.jpg" style="width: 100px;">
|
||||
<br>
|
||||
<span>长按小程序码,打开小程序搜索 "<Strong style="color:var(--md-primary-color);">{projectCode}</Strong>" 即可获取资源</span>
|
||||
</center>', 5, '0', NOW(), 'admin'),
|
||||
|
||||
('南音', '
|
||||
### 项目描述
|
||||
##### 视频演示
|
||||
{codeDesc}
|
||||
|
||||
### 技术选型
|
||||
**开发工具**:Idea + Vscode
|
||||
**运行环境**:JDK 1.8 + Maven + MySQL 5.7以上 + Node.js 14
|
||||
**服务端技术**:SpringBoot + Mybatis-Plus + Maven
|
||||
**前端技术**:Vue3 + Axios + Element-UI
|
||||
|
||||
### 系统截图
|
||||
{screenshots}
|
||||
|
||||
### 运行步骤
|
||||
##### 准备环境
|
||||
安装JDK 1.8、Maven、Node.js 14 和 MySQL 5.7以上
|
||||
|
||||
##### 创建数据库
|
||||
使用Navicat工具创建数据库并导入SQL脚本
|
||||
|
||||
##### 配置后端
|
||||
修改`application.yml`中的数据库连接信息(用户名/密码/库名)
|
||||
|
||||
##### 启动后端服务
|
||||
进入后端项目(`/server_code`) 执行:
|
||||
```
|
||||
mvn clean install
|
||||
mvn spring-boot:run
|
||||
```
|
||||
|
||||
##### 前端依赖安装
|
||||
进入前端目录(`/manage_code`或者`/client_code`), 执行安装命令:
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
##### 启动前端服务
|
||||
执行启动命令:
|
||||
```
|
||||
npm run serve
|
||||
```
|
||||
|
||||
##### 访问系统
|
||||
- 后端接口系统访问地址:`http://localhost:8080`
|
||||
- 后台系统前端访问地址:`http://localhost:8081`
|
||||
- 前台系统前端访问地址:`http://localhost:8082`
|
||||
|
||||
##### 常见问题
|
||||
###### 端口冲突
|
||||
- 修改后端配置文件`application.yml`
|
||||
- 修改前端配置文件`vue.config.js`
|
||||
|
||||
###### 前端安装依赖失败
|
||||
- 删除node_modules、package-lock.json文件
|
||||
```
|
||||
rm -rf node_modules package-lock.json
|
||||
```
|
||||
- 清除缓存
|
||||
```
|
||||
npm cache clean --force
|
||||
```
|
||||
- 切换npm镜像源
|
||||
```
|
||||
npm config set registry https://registry.npmmirror.com
|
||||
```
|
||||
|
||||
### 推荐阅读
|
||||
- [基于Springboot + vue3实现的果树系统](https://mp.weixin.qq.com/s/F7mO-9ENdfKqa89InlPUlg)
|
||||
- [基于Springboot + vue3实现的个人健康管理系统](https://mp.weixin.qq.com/s/UUUh4S2KfOnRKnLKZLlS3Q)
|
||||
- [基于Springboot + vue3实现的旅游网站系统](https://mp.weixin.qq.com/s/EY6XVtJXyY5FThfn0PoOew)
|
||||
- [基于Springboot + vue3实现的房屋租售系统](https://mp.weixin.qq.com/s/tbDCa5504JwOt-ECt3t_Yg)
|
||||
|
||||
### 其他说明
|
||||
>1、本系统源码由**程序员南音**精心收集整理,并经过严格测试验证,确保运行稳定可靠。
|
||||
>2、创作不易,如果觉得内容有帮助,别忘了**点赞/推荐/分享/收藏**支持我们,您的鼓励是我们持续更新的最大动力!
|
||||
>3、温馨提示:系统可能存在少量待完善功能,欢迎有技术热情的小伙伴共同参与优化改进。
|
||||
|
||||
# 源码获取
|
||||
|
||||
<center>
|
||||
<img src="https://img.yidaima.cn/qrcode.jpg" style="width: 100px;">
|
||||
<br>
|
||||
<span>长按小程序码,打开小程序搜索 "<Strong style="color:var(--md-primary-color);">{projectCode}</Strong>" 即可获取资源</span>
|
||||
</center>', 6, '0', NOW(), 'admin');
|
||||
Reference in New Issue
Block a user