974 lines
38 KiB
Vue
974 lines
38 KiB
Vue
<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 = '\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 - 后端接口系统访问地址:'
|
||
+ '\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 = '\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'
|
||
});
|
||
});
|
||
},
|
||
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'
|
||
});
|
||
});
|
||
},
|
||
/** 搜索按钮操作 */
|
||
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>
|