Files
RuoYi-Vue/ruoyi-ui/src/views/office/code/index.vue
王鹏 5e7bbe6c9d fixed
2026-03-31 20:33:20 +08:00

974 lines
38 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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="68px">
<el-form-item label="项目名称" prop="codeName">
<el-input
v-model="queryParams.codeName"
placeholder="请输入项目名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<!-- <el-form-item label="运行环境" prop="codeEnvironment">-->
<!-- <el-input-->
<!-- v-model="queryParams.codeEnvironment"-->
<!-- placeholder="请输入运行环境"-->
<!-- clearable-->
<!-- @keyup.enter.native="handleQuery"-->
<!-- />-->
<!-- </el-form-item>-->
<el-form-item label="项目技术" prop="codeTechnology">
<el-input
v-model="queryParams.codeTechnology"
placeholder="请输入项目技术"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="项目来源" prop="codeSource">
<el-select v-model="queryParams.codeSource" placeholder="请选择项目来源" clearable>
<el-option
v-for="dict in dict.type.code_source"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="付费方式" prop="paymentType">
<el-select v-model="queryParams.paymentType" placeholder="请选择付费方式" clearable>
<el-option
v-for="dict in dict.type.payment_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<!-- <el-form-item label="网盘地址" prop="diskLink">-->
<!-- <el-input-->
<!-- v-model="queryParams.diskLink"-->
<!-- placeholder="请输入网盘地址"-->
<!-- clearable-->
<!-- @keyup.enter.native="handleQuery"-->
<!-- />-->
<!-- </el-form-item>-->
<el-form-item label="是否发布" prop="publishFlag">
<el-select v-model="queryParams.publishFlag" placeholder="请选择是否发布" clearable>
<el-option
v-for="dict in dict.type.sys_yes_no"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</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:code: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:code: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:code:remove']"
>删除
</el-button>
</el-col>-->
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="el-icon-download"
size="mini"
@click="handleExport"
v-hasPermi="['office:code:export']"
>导出
</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="codeList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center"/>
<el-table-column label="项目名称" align="center" prop="codeName"/>
<!-- <el-table-column label="项目描述" align="center" prop="codeDesc" />-->
<el-table-column label="运行环境" align="center" prop="codeEnvironment"/>
<el-table-column label="项目技术" align="center" prop="codeTechnology"/>
<el-table-column label="项目来源" align="center" prop="codeSource">
<template slot-scope="scope">
<dict-tag :options="dict.type.code_source" :value="scope.row.codeSource"/>
</template>
</el-table-column>
<el-table-column label="付费方式" align="center" prop="paymentType">
<template slot-scope="scope">
<dict-tag :options="dict.type.payment_type" :value="scope.row.paymentType"/>
</template>
</el-table-column>
<!-- <el-table-column label="网盘地址" align="center" prop="diskLink" />-->
<el-table-column label="是否发布" align="center" prop="publishFlag">
<template slot-scope="scope">
<dict-tag :options="dict.type.sys_yes_no" :value="scope.row.publishFlag"/>
</template>
</el-table-column>
<!-- <el-table-column label="截图文件" align="center" prop="pictureFile" />-->
<!-- <el-table-column label="视频文件" align="center" prop="videoFile" />-->
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-document-copy"
@click="transToArticle(scope.row)"
v-hasPermi="['office:code:edit']"
>转文章
</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-document-copy"
@click="showCoverDialog(scope.row)"
v-hasPermi="['office:code:edit']"
>转文章(南音)
</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-view"
@click="handleDetail(scope.row)"
v-hasPermi="['office:code:query']"
>查看
</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleCopy(scope.row)"
v-hasPermi="['office:code:edit']"
>复制
</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
v-hasPermi="['office:code:edit']"
>修改
</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
:disabled="scope.row.publishFlag == 'Y'"
@click="handleDelete(scope.row)"
v-hasPermi="['office:code: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="800px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="项目名称" prop="codeName">
<el-input v-model="form.codeName" placeholder="请输入项目名称"/>
</el-form-item>
<el-form-item label="项目描述" prop="codeDesc">
<editor v-model="form.codeDesc" :min-height="192"/>
</el-form-item>
<el-form-item label="运行环境" prop="codeEnvironment">
<el-input v-model="form.codeEnvironment" placeholder="请输入运行环境"/>
</el-form-item>
<el-form-item label="项目技术" prop="codeTechnology">
<el-input v-model="form.codeTechnology" placeholder="请输入项目技术"/>
</el-form-item>
<el-form-item label="项目来源" prop="codeSource">
<el-select v-model="form.codeSource" placeholder="请选择项目来源">
<el-option
v-for="dict in dict.type.code_source"
:key="dict.value"
:label="dict.label"
:value="dict.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="付费方式" prop="paymentType">
<el-radio-group v-model="form.paymentType">
<el-radio
v-for="dict in dict.type.payment_type"
:key="dict.value"
:label="dict.value"
>{{dict.label}}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="网盘地址" prop="diskLink">
<el-input v-model="form.diskLink" placeholder="请输入网盘地址"/>
</el-form-item>
<el-form-item label="是否发布" prop="publishFlag">
<el-radio-group v-model="form.publishFlag">
<el-radio
v-for="dict in dict.type.sys_yes_no"
:key="dict.value"
:label="dict.value"
>{{dict.label}}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="截图文件" prop="pictureFile">
<file-upload v-model="form.pictureFile"/>
</el-form-item>
<el-form-item label="视频文件" prop="videoFile">
<file-upload v-model="form.videoFile"/>
</el-form-item>
</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>
<!-- 查看源码信息对话框 -->
<el-dialog :title="title" :visible.sync="openDetail" width="800px" append-to-body>
<el-descriptions class="margin-top" :title="form.codeName" :column="4" direction="vertical" border>
<!-- <el-descriptions-item label="项目名称">{{ form.codeName }}</el-descriptions-item>-->
<el-descriptions-item label="项目描述" :span="4">
<span v-html="form.codeDesc"/>
</el-descriptions-item>
<el-descriptions-item label="运行环境" :span="4">{{ form.codeEnvironment }}</el-descriptions-item>
<el-descriptions-item label="项目技术" :span="4">{{ form.codeTechnology }}</el-descriptions-item>
<!-- <el-descriptions-item label="项目来源">-->
<!-- <dict-tag :options="dict.type.code_source" :value="form.codeSource"/>-->
<!-- </el-descriptions-item>-->
<!-- <el-descriptions-item label="付费方式">-->
<!-- <dict-tag :options="dict.type.payment_type" :value="form.paymentType"/>-->
<!-- </el-descriptions-item>-->
<el-descriptions-item label="网盘地址" :span="2">{{ form.diskLink }}</el-descriptions-item>
<el-descriptions-item label="是否发布" :span="2">
<dict-tag :options="dict.type.sys_yes_no" :value="form.publishFlag"/>
</el-descriptions-item>
<el-descriptions-item label="截图文件" :span="4">
<el-link v-if="form.pictureFile" :href="`${baseUrl}${form.pictureFile}`" :underline="false" target="_blank">
<span class="el-icon-document"> 下载 </span>
</el-link>
</el-descriptions-item>
<el-descriptions-item label="视频文件" :span="4">
<el-link v-if="form.videoFile" :href="`${baseUrl}${form.videoFile}`" :underline="false" target="_blank">
<span class="el-icon-document"> 下载 </span>
</el-link>
</el-descriptions-item>
<el-descriptions-item label="截图展示" :span="4">
<el-image
style="width: 100px; height: 80px; padding: 3px;"
v-for="(item, index) in form.fileList"
:key="index"
:src="item.fileUrl"
:preview-src-list="previewList"
/>
</el-descriptions-item>
</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>
</div>
</el-dialog>
<!-- 封面预览对话框 -->
<el-dialog :title="'封面预览'" :visible.sync="coverDialogVisible" width="500px" append-to-body>
<div class="cover-preview" style="text-align: center;">
<img :src="coverImageUrl" style="max-width: 100%; height: auto;" v-if="coverImageUrl"/>
<div v-else>加载中...</div>
</div>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="handleDownload"> </el-button>
<el-button type="primary" @click="handleTransToArticle1"> </el-button>
<el-button @click="coverDialogVisible = false"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import {listCode, getCode, delCode, addCode, updateCode, transToArticle, transToArticle1} from "@/api/office/code";
import {html2Text} from "../../../utils";
import {getToken} from "@/utils/auth";
import request from '@/utils/request';
export default {
name: "Code",
dicts: ['payment_type', 'sys_yes_no', 'code_source'],
data() {
return {
baseUrl: process.env.VUE_APP_BASE_API,
// 遮罩层
loading: true,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 源码管理表格数据
codeList: [],
// 弹出层标题
title: "",
// 是否显示弹出层
open: false,
openDetail: false,
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
codeName: null,
codeDesc: null,
codeEnvironment: null,
codeTechnology: null,
codeSource: null,
paymentType: null,
diskLink: null,
publishFlag: null,
pictureFile: null,
videoFile: null
},
// 表单参数
form: {},
// 表单校验
rules: {},
// 封面对话框显示状态
coverDialogVisible: false,
// 封面图片URL
coverImageUrl: '',
previewBlob: null,
currentFileName: '',
currentRow: ''
};
},
created() {
this.getList();
},
computed: {
previewList() {
return this.form.fileList.map(i => {
return i.fileUrl
})
}
},
methods: {
/** 查询源码管理列表 */
getList() {
this.loading = true;
listCode(this.queryParams).then(response => {
this.codeList = response.rows;
this.total = response.total;
this.loading = false;
});
},
// 取消按钮
cancel() {
this.open = false;
this.openDetail = false;
this.reset();
},
// 表单重置
reset() {
this.form = {
codeId: null,
codeName: null,
codeDesc: null,
codeEnvironment: 'jdk1.8 + mysql5.7以上 + idea + vscode',
codeTechnology: 'springboot + vue2 + elementui + nodejs14',
codeSource: null,
paymentType: null,
diskLink: null,
publishFlag: null,
pictureFile: null,
videoFile: null
};
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;
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];
}
}
}
console.log('项目编号:', projectCode);
console.log('后端技术:', backendTech);
console.log('前端技术:', frontendTech);
console.log('项目名称:', projectName);
let content = '![](https://img.yidaima.cn/weicome.gif)\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' + '![](' + item.fileUrl + ')' + '\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 - 后端接口系统访问地址:'
+ '\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>';
navigator.clipboard.writeText(content).then(() => {
this.$message({
message: '复制成功',
type: 'success'
});
}).catch(err => {
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 = '![](https://img.yidaima.cn/weicome.gif)\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' + '![](' + item.fileUrl + ')' + '\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'
});
});
},
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 + 'Vue3JavaSpringBoot前后端分离可提供远程调试项目编号'+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' + '![](' + item.fileUrl + ')' + '\n\n';
}
} else {
content = content + '请前往微信小程序:南音源码库。查看项目详情!\n\n'
}
content = content + '#### 资源下载' + '\n' + '![](https://img.yidaima.cn/qrcode.jpg)' + '\n\n' + '请打开微信扫描上面小程序码,打开小程序搜索 "**项目编号**" 即可下载资源';
navigator.clipboard.writeText(content).then(() => {
this.$message({
message: '复制成功',
type: 'success'
});
}).catch(err => {
this.$message({
message: '复制失败: ' + err,
type: 'error'
});
});
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
// 多选框选中数据
handleSelectionChange(selection) {
this.ids = selection.map(item => item.codeId)
this.single = selection.length !== 1
this.multiple = !selection.length
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.open = true;
this.title = "添加源码信息";
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset();
const codeId = row.codeId || this.ids
getCode(codeId).then(response => {
this.form = response.data;
this.open = true;
this.title = "修改源码信息";
});
},
/** 复制按钮操作 */
handleCopy(row) {
this.reset();
const codeId = row.codeId || this.ids
getCode(codeId).then(response => {
this.form = response.data;
delete this.form.codeId
this.open = true;
this.title = "复制源码信息";
});
},
/** 明细按钮操作 */
handleDetail(row) {
this.reset();
const codeId = row.codeId || this.ids
getCode(codeId).then(response => {
this.form = response.data;
this.openDetail = true;
this.title = "查看源码信息";
});
},
transToArticle(row) {
transToArticle(row.codeId).then(response => {
console.log(response)
this.$modal.msgSuccess(response.msg);
});
},
showCoverDialog(row) {
this.currentRow = row
const id = row.codeId || this.ids
const baseUrl = process.env.VUE_APP_BASE_API
fetch(`${baseUrl}/office/project/cover/${id}`, {
method: 'GET',
headers: {
'Authorization': 'Bearer ' + getToken()
}
}).then(response => {
if (!response.ok) {
throw new Error('Network response was not ok')
}
return response.blob()
})
.then(blob => {
// 保存blob数据和文件名
this.previewBlob = blob
this.currentFileName = `${row.projectName || 'cover'}.png`
// 创建预览URL
this.coverImageUrl = window.URL.createObjectURL(blob)
// 显示预览对话框
this.coverDialogVisible = true
})
.catch(err => {
console.error('获取封面图片失败:', err)
this.$modal.msgError('获取封面图片失败')
})
},
// 处理下载操作
handleDownload() {
if (!this.previewBlob || !this.currentFileName) {
return
}
// 创建新的blob对象添加type属性
const newBlob = new Blob([this.previewBlob], { type: 'application/octet-stream' })
const url = window.URL.createObjectURL(newBlob)
const link = document.createElement('a')
link.style.display = 'none'
link.href = url
link.download = `${this.currentRow.codeName}.png`
document.body.appendChild(link)
link.click()
// 延迟移除,确保下载开始
setTimeout(() => {
document.body.removeChild(link)
window.URL.revokeObjectURL(url)
}, 100)
this.$modal.msgSuccess('封面图片已下载')
},
handleTransToArticle1() {
// 将 Blob 转换为 File 对象
const file = new File([this.previewBlob], this.currentFileName, { type: 'image/png' });
// 创建 FormData
const formData = new FormData();
formData.append('file', file);
// 上传到七牛云
request({
url: '/common/qiniuUpload',
method: 'post',
data: formData,
headers: {
'Content-Type': 'multipart/form-data'
}
}).then(response => {
if (response.code === 200) {
// 获取上传后的URL
const imageUrl = response.url;
// 调用转文章接口
transToArticle1(this.currentRow.codeId, imageUrl).then(response => {
this.$modal.msgSuccess(response.msg);
this.getList();
});
} else {
this.$modal.msgError('封面图片上传失败');
}
}).catch(error => {
console.error('转文章失败:', error);
this.$modal.msgError('转文章失败');
});
this.coverDialogVisible = false;
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
if (this.form.codeId != null) {
updateCode(this.form).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
});
} else {
addCode(this.form).then(response => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
});
}
}
});
},
/** 删除按钮操作 */
handleDelete(row) {
const codeIds = row.codeId || this.ids;
this.$modal.confirm('是否确认删除源码管理编号为"' + codeIds + '"的数据项?').then(function () {
return delCode(codeIds);
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {
});
},
/** 导出按钮操作 */
handleExport() {
this.download('office/code/export', {
...this.queryParams
}, `code_${new Date().getTime()}.xlsx`)
}
}
};
</script>