整合前端
This commit is contained in:
518
ruoyi-ui/src/views/site/article/index.vue
Normal file
518
ruoyi-ui/src/views/site/article/index.vue
Normal file
@@ -0,0 +1,518 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="100px">
|
||||
<el-form-item label="所属文章分类" prop="categoryId">
|
||||
<el-select v-model="queryParams.categoryId" placeholder="请选择分类" clearable>
|
||||
<el-option v-for="item in categoryOptions" :key="item.categoryId" :label="item.categoryName"
|
||||
:value="item.categoryId" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="语言编码" prop="langCode">
|
||||
<LanguageSelect v-model="queryParams.langCode" placeholder="请选择语种" />
|
||||
</el-form-item>
|
||||
<el-form-item label="文章标题" prop="title">
|
||||
<el-input v-model="queryParams.title" placeholder="请输入文章标题" clearable @keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="发布状态" prop="isPublished">
|
||||
<el-select v-model="queryParams.isPublished" placeholder="请选择发布状态" clearable>
|
||||
<el-option label="已发布" value="1" />
|
||||
<el-option label="未发布" value="0" />
|
||||
</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">新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single"
|
||||
@click="handleUpdate">修改</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple"
|
||||
@click="handleDelete">删除</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport">导出</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="articleList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="所属文章分类" align="center" min-width="120">
|
||||
<template slot-scope="scope">
|
||||
{{ getCategoryName(scope.row.categoryId) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="语言" align="center" width="100">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="scope.row.langCode === 'zh-CN' ? 'primary' : 'success'" size="small">{{ scope.row.langCode
|
||||
}}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="封面" align="center" width="80">
|
||||
<template slot-scope="scope">
|
||||
<image-preview :src="scope.row.cover" fit="contain" width="60" height="40" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="文章标题" prop="title" align="center" min-width="200" show-overflow-tooltip />
|
||||
<el-table-column label="摘要" prop="summary" align="center" min-width="150" show-overflow-tooltip />
|
||||
<el-table-column label="发布状态" align="center" width="100">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="scope.row.isPublished === '1' ? 'success' : 'info'" size="small">
|
||||
{{ scope.row.isPublished === '1' ? '已发布' : '未发布' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="发布时间" align="center" width="180">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ parseTime(scope.row.publishedTime, '{y}-{m}-{d}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="关联文章" align="center" width="120">
|
||||
<template slot-scope="scope">
|
||||
<el-button v-if="scope.row.relatedArticleId" type="text" size="mini" @click="handleViewRelated(scope.row)">
|
||||
查看关联
|
||||
</el-button>
|
||||
<span v-else>无</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<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-edit" @click="handleUpdate(scope.row)">修改</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)">删除</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-view" @click="handlePreview(scope.row)">预览</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-link" @click="handleCopyLink(scope.row)">复制链接</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="100px" size="small">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="所属文章分类" prop="categoryId" required>
|
||||
<el-select v-model="form.categoryId" placeholder="请选择分类" clearable>
|
||||
<el-option v-for="item in categoryOptions" :key="item.categoryId" :label="item.categoryName"
|
||||
:value="item.categoryId" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="语言编码" prop="langCode" required>
|
||||
<LanguageSelect v-model="form.langCode" placeholder="请选择语种" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="文章标题" prop="title" required>
|
||||
<el-input v-model="form.title" placeholder="请输入文章标题" maxlength="200" show-word-limit />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="关联文章ID" prop="relatedArticleId">
|
||||
<el-input v-model="form.relatedArticleId" placeholder="请输入关联文章ID(同一篇文章的其他语言版本)" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="封面地址" prop="cover">
|
||||
<el-input v-model="form.cover" placeholder="请输入封面地址" />
|
||||
</el-form-item>
|
||||
<el-form-item label="摘要" prop="summary">
|
||||
<el-input v-model="form.summary" type="textarea" placeholder="请输入摘要" :rows="3" maxlength="500"
|
||||
show-word-limit />
|
||||
</el-form-item>
|
||||
<el-form-item label="文章内容" prop="content" required>
|
||||
<editor v-model="form.content" :min-height="300" />
|
||||
</el-form-item>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="发布状态" prop="isPublished">
|
||||
<el-select v-model="form.isPublished" placeholder="请选择发布状态" clearable>
|
||||
<el-option label="已发布" value="1" />
|
||||
<el-option label="未发布" value="0" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="发布时间" prop="publishedTime">
|
||||
<el-date-picker clearable v-model="form.publishedTime" type="datetime" value-format="yyyy-MM-dd HH:mm:ss"
|
||||
placeholder="请选择发布时间" style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="SEO 友好链接" prop="slug">
|
||||
<el-input v-model="form.slug" placeholder="请输入SEO 友好链接" />
|
||||
</el-form-item>
|
||||
<el-form-item label="排序" prop="sortOrder">
|
||||
<el-input-number v-model="form.sortOrder" :min="0" :max="9999" placeholder="请输入排序" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" type="textarea" placeholder="请输入备注" :rows="2" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 文章预览对话框 -->
|
||||
<el-dialog title="文章预览" :visible.sync="previewDialog" width="80%" top="5vh">
|
||||
<div class="preview-container">
|
||||
<h3 class="preview-title">{{ previewTitle }}</h3>
|
||||
<div class="preview-meta">
|
||||
<span class="meta-item">{{ parseTime(previewPublishedTime, '{y}-{m}-{d} {h}:{i}') }}</span>
|
||||
<span class="meta-item">{{ previewLangCode }}</span>
|
||||
</div>
|
||||
<div v-html="previewContent" class="preview-content"></div>
|
||||
</div>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="previewDialog = false">关闭</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { addArticle, delArticle, getArticle, listArticle, updateArticle } from "@/api/site/article";
|
||||
import { listArticleCategory } from "@/api/site/articleCategory";
|
||||
import LanguageSelect from '@/components/LanguageSelect.vue';
|
||||
|
||||
export default {
|
||||
name: "Article",
|
||||
components: {
|
||||
LanguageSelect
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
// 按钮loading
|
||||
buttonLoading: false,
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 选中数组
|
||||
ids: [],
|
||||
// 非单个禁用
|
||||
single: true,
|
||||
// 非多个禁用
|
||||
multiple: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 文章表格数据
|
||||
articleList: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
categoryId: undefined,
|
||||
langCode: undefined,
|
||||
title: undefined,
|
||||
isPublished: undefined
|
||||
},
|
||||
// 表单参数
|
||||
form: {
|
||||
articleId: undefined,
|
||||
categoryId: undefined,
|
||||
langCode: undefined,
|
||||
slug: undefined,
|
||||
title: undefined,
|
||||
summary: undefined,
|
||||
content: undefined,
|
||||
isPublished: "0",
|
||||
publishedTime: new Date().toISOString().slice(0, 19).replace('T', ' '),
|
||||
sortOrder: 0,
|
||||
delFlag: undefined,
|
||||
remark: undefined,
|
||||
createTime: undefined,
|
||||
createBy: undefined,
|
||||
updateTime: undefined,
|
||||
updateBy: undefined,
|
||||
cover: undefined,
|
||||
relatedArticleId: undefined
|
||||
},
|
||||
// 表单校验
|
||||
rules: {
|
||||
categoryId: [
|
||||
{ required: true, message: '请选择所属文章分类', trigger: 'change' }
|
||||
],
|
||||
langCode: [
|
||||
{ required: true, message: '请选择语言编码', trigger: 'change' }
|
||||
],
|
||||
title: [
|
||||
{ required: true, message: '请输入文章标题', trigger: 'blur' },
|
||||
{ min: 1, max: 200, message: '标题长度不能超过200个字符', trigger: 'blur' }
|
||||
],
|
||||
content: [
|
||||
{ required: true, message: '请输入文章内容', trigger: 'blur' }
|
||||
]
|
||||
},
|
||||
categoryOptions: [],
|
||||
previewDialog: false,
|
||||
previewContent: "",
|
||||
previewTitle: "",
|
||||
previewPublishedTime: "",
|
||||
previewLangCode: ""
|
||||
};
|
||||
},
|
||||
created () {
|
||||
this.getList();
|
||||
this.getCategoryOptions();
|
||||
},
|
||||
methods: {
|
||||
getCategoryOptions () {
|
||||
listArticleCategory({}).then(res => {
|
||||
this.categoryOptions = res.rows || [];
|
||||
});
|
||||
},
|
||||
getCategoryName (id) {
|
||||
const item = this.categoryOptions.find(opt => opt.categoryId === id);
|
||||
return item ? item.categoryName : id;
|
||||
},
|
||||
handlePreview (row) {
|
||||
if (row.content) {
|
||||
this.previewTitle = row.title;
|
||||
this.previewContent = row.content;
|
||||
this.previewPublishedTime = row.publishedTime;
|
||||
this.previewLangCode = row.langCode;
|
||||
this.previewDialog = true;
|
||||
} else {
|
||||
getArticle(row.articleId).then(res => {
|
||||
this.previewTitle = res.data.title;
|
||||
this.previewContent = res.data.content;
|
||||
this.previewPublishedTime = res.data.publishedTime;
|
||||
this.previewLangCode = res.data.langCode;
|
||||
this.previewDialog = true;
|
||||
});
|
||||
}
|
||||
},
|
||||
handleViewRelated (row) {
|
||||
if (row.relatedArticleId) {
|
||||
this.loading = true;
|
||||
getArticle(row.relatedArticleId).then(res => {
|
||||
this.loading = false;
|
||||
this.previewTitle = res.data.title;
|
||||
this.previewContent = res.data.content;
|
||||
this.previewPublishedTime = res.data.publishedTime;
|
||||
this.previewLangCode = res.data.langCode;
|
||||
this.previewDialog = true;
|
||||
}).catch(() => {
|
||||
this.loading = false;
|
||||
this.$message.error('获取关联文章失败');
|
||||
});
|
||||
}
|
||||
},
|
||||
/** 查询文章列表 */
|
||||
getList () {
|
||||
this.loading = true;
|
||||
listArticle(this.queryParams).then(response => {
|
||||
this.articleList = response.rows;
|
||||
this.total = response.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
// 取消按钮
|
||||
cancel () {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
// 表单重置
|
||||
reset () {
|
||||
this.form = {
|
||||
articleId: undefined,
|
||||
categoryId: undefined,
|
||||
langCode: undefined,
|
||||
slug: undefined,
|
||||
title: undefined,
|
||||
summary: undefined,
|
||||
content: undefined,
|
||||
isPublished: "0",
|
||||
publishedTime: new Date().toISOString().slice(0, 19).replace('T', ' '),
|
||||
sortOrder: 0,
|
||||
delFlag: undefined,
|
||||
remark: undefined,
|
||||
createTime: undefined,
|
||||
createBy: undefined,
|
||||
updateTime: undefined,
|
||||
updateBy: undefined,
|
||||
cover: undefined,
|
||||
relatedArticleId: undefined
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery () {
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery () {
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
// 多选框选中数据
|
||||
handleSelectionChange (selection) {
|
||||
this.ids = selection.map(item => item.articleId)
|
||||
this.single = selection.length !== 1
|
||||
this.multiple = !selection.length
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd () {
|
||||
this.reset();
|
||||
this.open = true;
|
||||
this.title = "添加文章";
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate (row) {
|
||||
this.loading = true;
|
||||
this.reset();
|
||||
const articleId = row.articleId || this.ids
|
||||
getArticle(articleId).then(response => {
|
||||
this.loading = false;
|
||||
this.form = response.data;
|
||||
this.open = true;
|
||||
this.title = "修改文章";
|
||||
}).catch(() => {
|
||||
this.loading = false;
|
||||
this.$message.error('获取文章详情失败');
|
||||
});
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm () {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (valid) {
|
||||
this.buttonLoading = true;
|
||||
const articleData = {
|
||||
...this.form
|
||||
};
|
||||
// 处理slug自动生成
|
||||
if (!articleData.slug && articleData.title) {
|
||||
articleData.slug = articleData.title.toLowerCase().replace(/[^\w\s-]/g, '').replace(/\s+/g, '-').substring(0, 100);
|
||||
}
|
||||
|
||||
const requestMethod = articleData.articleId ? updateArticle : addArticle;
|
||||
requestMethod(articleData).then(response => {
|
||||
this.$modal.msgSuccess(articleData.articleId ? "修改成功" : "新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}).catch(() => {
|
||||
this.$modal.msgError(articleData.articleId ? "修改失败" : "新增失败");
|
||||
}).finally(() => {
|
||||
this.buttonLoading = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete (row) {
|
||||
const articleIds = row.articleId || this.ids;
|
||||
this.$modal.confirm('是否确认删除选中的文章数据?', '警告', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.loading = true;
|
||||
return delArticle(articleIds);
|
||||
}).then(() => {
|
||||
this.loading = false;
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
this.ids = [];
|
||||
this.single = true;
|
||||
this.multiple = true;
|
||||
}).catch(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport () {
|
||||
this.download('site/article/export', {
|
||||
...this.queryParams
|
||||
}, `article_${new Date().getTime()}.xlsx`)
|
||||
},
|
||||
handleCopyLink (row) {
|
||||
const url = `/${row.categoryId}/${row.articleId}`;
|
||||
if (navigator && navigator.clipboard && navigator.clipboard.writeText) {
|
||||
navigator.clipboard.writeText(url).then(() => {
|
||||
this.$message.success('复制成功');
|
||||
}, () => {
|
||||
this.$message.error('复制失败,请手动复制');
|
||||
});
|
||||
} else {
|
||||
// 兼容性处理
|
||||
const input = document.createElement('input');
|
||||
input.value = url;
|
||||
document.body.appendChild(input);
|
||||
input.select();
|
||||
try {
|
||||
document.execCommand('copy');
|
||||
this.$message.success('复制成功');
|
||||
} catch (e) {
|
||||
this.$message.error('复制失败,请手动复制');
|
||||
}
|
||||
document.body.removeChild(input);
|
||||
}
|
||||
},
|
||||
/** 快速添加关联文章 */
|
||||
quickAddRelatedArticle () {
|
||||
if (this.form.articleId) {
|
||||
this.reset();
|
||||
this.form.relatedArticleId = this.form.articleId;
|
||||
this.open = true;
|
||||
this.title = "添加关联文章(其他语言版本)";
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.preview-container {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.preview-title {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.preview-meta {
|
||||
text-align: center;
|
||||
color: #909399;
|
||||
margin-bottom: 30px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.meta-item {
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
.preview-content {
|
||||
line-height: 1.8;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.preview-content img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
margin: 10px 0;
|
||||
}
|
||||
</style>
|
||||
257
ruoyi-ui/src/views/site/articleCategory/index.vue
Normal file
257
ruoyi-ui/src/views/site/articleCategory/index.vue
Normal file
@@ -0,0 +1,257 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="100px">
|
||||
<el-form-item label="分类名称" prop="categoryName">
|
||||
<el-input v-model="queryParams.categoryName" placeholder="请输入分类名称" clearable
|
||||
@keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="分类描述" prop="description">
|
||||
<el-input v-model="queryParams.description" placeholder="请输入分类描述" clearable @keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="排序" prop="sortOrder">
|
||||
<el-input v-model="queryParams.sortOrder" placeholder="请输入排序" clearable @keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="是否启用" prop="isEnabled">
|
||||
<el-input v-model="queryParams.isEnabled" placeholder="请输入是否启用" clearable @keyup.enter.native="handleQuery" />
|
||||
</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">新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single"
|
||||
@click="handleUpdate">修改</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple"
|
||||
@click="handleDelete">删除</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport">导出</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="articleCategoryList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<!-- <el-table-column label="文章分类主键" align="center" prop="categoryId" v-if="true"/> -->
|
||||
<!-- <el-table-column label="上级分类ID" align="center" prop="parentId" /> -->
|
||||
<!-- <el-table-column label="语言编码" align="center" prop="langCode" /> -->
|
||||
<el-table-column label="分类名称" align="center" prop="categoryName" />
|
||||
<el-table-column label="分类描述" align="center" prop="description" />
|
||||
<el-table-column label="排序" align="center" prop="sortOrder" />
|
||||
<el-table-column label="是否启用" align="center" prop="isEnabled" />
|
||||
<el-table-column label="备注" align="center" prop="remark" />
|
||||
<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-edit" @click="handleUpdate(scope.row)">修改</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)">删除</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="500px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
|
||||
<el-form-item label="分类名称" prop="categoryName">
|
||||
<el-input v-model="form.categoryName" type="text" placeholder="请输入内容" />
|
||||
</el-form-item>
|
||||
<el-form-item label="分类描述" prop="description">
|
||||
<el-input v-model="form.description" type="textarea" placeholder="请输入内容" />
|
||||
</el-form-item>
|
||||
<el-form-item label="排序" prop="sortOrder">
|
||||
<el-input v-model="form.sortOrder" placeholder="请输入排序" />
|
||||
</el-form-item>
|
||||
<el-form-item label="是否启用" prop="isEnabled">
|
||||
<el-input v-model="form.isEnabled" placeholder="请输入是否启用" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { addArticleCategory, delArticleCategory, getArticleCategory, listArticleCategory, updateArticleCategory } from "@/api/site/articleCategory";
|
||||
import LanguageSelect from '@/components/LanguageSelect.vue';
|
||||
|
||||
export default {
|
||||
name: "ArticleCategory",
|
||||
components: {
|
||||
LanguageSelect
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
// 按钮loading
|
||||
buttonLoading: false,
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 选中数组
|
||||
ids: [],
|
||||
// 非单个禁用
|
||||
single: true,
|
||||
// 非多个禁用
|
||||
multiple: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 文章分类表格数据
|
||||
articleCategoryList: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
parentId: undefined,
|
||||
langCode: undefined,
|
||||
categoryName: undefined,
|
||||
description: undefined,
|
||||
sortOrder: undefined,
|
||||
isEnabled: undefined,
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 表单校验
|
||||
rules: {
|
||||
}
|
||||
};
|
||||
},
|
||||
created () {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询文章分类列表 */
|
||||
getList () {
|
||||
this.loading = true;
|
||||
listArticleCategory(this.queryParams).then(response => {
|
||||
this.articleCategoryList = response.rows;
|
||||
this.total = response.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
// 取消按钮
|
||||
cancel () {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
// 表单重置
|
||||
reset () {
|
||||
this.form = {
|
||||
categoryId: undefined,
|
||||
parentId: undefined,
|
||||
langCode: undefined,
|
||||
categoryName: undefined,
|
||||
description: undefined,
|
||||
sortOrder: undefined,
|
||||
isEnabled: undefined,
|
||||
delFlag: undefined,
|
||||
remark: undefined,
|
||||
createTime: undefined,
|
||||
createBy: undefined,
|
||||
updateTime: undefined,
|
||||
updateBy: undefined
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery () {
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery () {
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
// 多选框选中数据
|
||||
handleSelectionChange (selection) {
|
||||
this.ids = selection.map(item => item.categoryId)
|
||||
this.single = selection.length !== 1
|
||||
this.multiple = !selection.length
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd () {
|
||||
this.reset();
|
||||
this.open = true;
|
||||
this.title = "添加文章分类";
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate (row) {
|
||||
this.loading = true;
|
||||
this.reset();
|
||||
const categoryId = row.categoryId || this.ids
|
||||
getArticleCategory(categoryId).then(response => {
|
||||
this.loading = false;
|
||||
this.form = response.data;
|
||||
this.open = true;
|
||||
this.title = "修改文章分类";
|
||||
});
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm () {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (valid) {
|
||||
this.buttonLoading = true;
|
||||
if (this.form.categoryId != null) {
|
||||
updateArticleCategory(this.form).then(response => {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}).finally(() => {
|
||||
this.buttonLoading = false;
|
||||
});
|
||||
} else {
|
||||
addArticleCategory(this.form).then(response => {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}).finally(() => {
|
||||
this.buttonLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete (row) {
|
||||
const categoryIds = row.categoryId || this.ids;
|
||||
this.$modal.confirm('是否确认删除文章分类编号为"' + categoryIds + '"的数据项?').then(() => {
|
||||
this.loading = true;
|
||||
return delArticleCategory(categoryIds);
|
||||
}).then(() => {
|
||||
this.loading = false;
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => {
|
||||
}).finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport () {
|
||||
this.download('export/articleCategory/export', {
|
||||
...this.queryParams
|
||||
}, `articleCategory_${new Date().getTime()}.xlsx`)
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
356
ruoyi-ui/src/views/site/carousel/index.vue
Normal file
356
ruoyi-ui/src/views/site/carousel/index.vue
Normal file
@@ -0,0 +1,356 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="100px">
|
||||
<el-form-item label="语言编码" prop="langCode">
|
||||
<LanguageSelect v-model="queryParams.langCode" placeholder="请选择语种" />
|
||||
</el-form-item>
|
||||
<el-form-item label="轮播标题" prop="title">
|
||||
<el-input
|
||||
v-model="queryParams.title"
|
||||
placeholder="请输入轮播标题"
|
||||
clearable
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="轮播说明" prop="caption">
|
||||
<el-input
|
||||
v-model="queryParams.caption"
|
||||
placeholder="请输入轮播说明"
|
||||
clearable
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="图片链接" prop="imageUrl">
|
||||
<el-input
|
||||
v-model="queryParams.imageUrl"
|
||||
placeholder="请输入图片链接"
|
||||
clearable
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="点击跳转 URL" prop="linkUrl">
|
||||
<el-input
|
||||
v-model="queryParams.linkUrl"
|
||||
placeholder="请输入点击跳转 URL"
|
||||
clearable
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="排序" prop="sortOrder">
|
||||
<el-input
|
||||
v-model="queryParams.sortOrder"
|
||||
placeholder="请输入排序"
|
||||
clearable
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否启用" prop="isEnabled">
|
||||
<el-input
|
||||
v-model="queryParams.isEnabled"
|
||||
placeholder="请输入是否启用"
|
||||
clearable
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</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"
|
||||
>新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="success"
|
||||
plain
|
||||
icon="el-icon-edit"
|
||||
size="mini"
|
||||
:disabled="single"
|
||||
@click="handleUpdate"
|
||||
>修改</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
icon="el-icon-delete"
|
||||
size="mini"
|
||||
:disabled="multiple"
|
||||
@click="handleDelete"
|
||||
>删除</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="warning"
|
||||
plain
|
||||
icon="el-icon-download"
|
||||
size="mini"
|
||||
@click="handleExport"
|
||||
>导出</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="carouselList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<!-- <el-table-column label="轮播图主键" align="center" prop="carouselId" v-if="true"/> -->
|
||||
<el-table-column label="语言编码" align="center" prop="langCode" />
|
||||
<el-table-column label="轮播标题" align="center" prop="title" />
|
||||
<el-table-column label="轮播说明" align="center" prop="caption" />
|
||||
<el-table-column label="图片链接" align="center" prop="imageUrl">
|
||||
<template slot-scope="scope">
|
||||
<el-image
|
||||
v-if="scope.row.imageUrl"
|
||||
:src="scope.row.imageUrl"
|
||||
:preview-src-list="[scope.row.imageUrl]"
|
||||
style="max-width: 100px; max-height: 60px;"
|
||||
fit="contain"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="点击跳转 URL" align="center" prop="linkUrl" />
|
||||
<el-table-column label="排序" align="center" prop="sortOrder" />
|
||||
<el-table-column label="是否启用" align="center" prop="isEnabled" />
|
||||
<el-table-column label="备注" align="center" prop="remark" />
|
||||
<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-edit"
|
||||
@click="handleUpdate(scope.row)"
|
||||
>修改</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-delete"
|
||||
@click="handleDelete(scope.row)"
|
||||
>删除</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="500px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
|
||||
<el-form-item label="语言编码" prop="langCode">
|
||||
<LanguageSelect v-model="form.langCode" placeholder="请选择语种" />
|
||||
</el-form-item>
|
||||
<el-form-item label="轮播标题" prop="title">
|
||||
<el-input v-model="form.title" placeholder="请输入轮播标题" />
|
||||
</el-form-item>
|
||||
<el-form-item label="轮播说明" prop="caption">
|
||||
<el-input v-model="form.caption" type="textarea" placeholder="请输入内容" />
|
||||
</el-form-item>
|
||||
<el-form-item label="图片链接" prop="imageUrl">
|
||||
<el-input v-model="form.imageUrl" type="textarea" placeholder="请输入内容" />
|
||||
</el-form-item>
|
||||
<el-form-item label="点击跳转 URL" prop="linkUrl">
|
||||
<el-input v-model="form.linkUrl" type="textarea" placeholder="请输入内容" />
|
||||
</el-form-item>
|
||||
<el-form-item label="排序" prop="sortOrder">
|
||||
<el-input v-model="form.sortOrder" placeholder="请输入排序" />
|
||||
</el-form-item>
|
||||
<el-form-item label="是否启用" prop="isEnabled">
|
||||
<el-input v-model="form.isEnabled" placeholder="请输入是否启用" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { addCarousel, delCarousel, getCarousel, listCarousel, updateCarousel } from "@/api/site/carousel";
|
||||
import LanguageSelect from '@/components/LanguageSelect.vue';
|
||||
|
||||
export default {
|
||||
name: "Carousel",
|
||||
components: {
|
||||
LanguageSelect
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 按钮loading
|
||||
buttonLoading: false,
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 选中数组
|
||||
ids: [],
|
||||
// 非单个禁用
|
||||
single: true,
|
||||
// 非多个禁用
|
||||
multiple: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 轮播图表格数据
|
||||
carouselList: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
langCode: undefined,
|
||||
title: undefined,
|
||||
caption: undefined,
|
||||
imageUrl: undefined,
|
||||
linkUrl: undefined,
|
||||
sortOrder: undefined,
|
||||
isEnabled: undefined,
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 表单校验
|
||||
rules: {
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询轮播图列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
listCarousel(this.queryParams).then(response => {
|
||||
this.carouselList = response.rows;
|
||||
this.total = response.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
// 取消按钮
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
// 表单重置
|
||||
reset() {
|
||||
this.form = {
|
||||
carouselId: undefined,
|
||||
langCode: undefined,
|
||||
title: undefined,
|
||||
caption: undefined,
|
||||
imageUrl: undefined,
|
||||
linkUrl: undefined,
|
||||
sortOrder: undefined,
|
||||
isEnabled: undefined,
|
||||
delFlag: undefined,
|
||||
remark: undefined,
|
||||
createTime: undefined,
|
||||
createBy: undefined,
|
||||
updateTime: undefined,
|
||||
updateBy: undefined
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
// 多选框选中数据
|
||||
handleSelectionChange(selection) {
|
||||
this.ids = selection.map(item => item.carouselId)
|
||||
this.single = selection.length!==1
|
||||
this.multiple = !selection.length
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset();
|
||||
this.open = true;
|
||||
this.title = "添加轮播图";
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.loading = true;
|
||||
this.reset();
|
||||
const carouselId = row.carouselId || this.ids
|
||||
getCarousel(carouselId).then(response => {
|
||||
this.loading = false;
|
||||
this.form = response.data;
|
||||
this.open = true;
|
||||
this.title = "修改轮播图";
|
||||
});
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (valid) {
|
||||
this.buttonLoading = true;
|
||||
if (this.form.carouselId != null) {
|
||||
updateCarousel(this.form).then(response => {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}).finally(() => {
|
||||
this.buttonLoading = false;
|
||||
});
|
||||
} else {
|
||||
addCarousel(this.form).then(response => {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}).finally(() => {
|
||||
this.buttonLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const carouselIds = row.carouselId || this.ids;
|
||||
this.$modal.confirm('是否确认删除轮播图编号为"' + carouselIds + '"的数据项?').then(() => {
|
||||
this.loading = true;
|
||||
return delCarousel(carouselIds);
|
||||
}).then(() => {
|
||||
this.loading = false;
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => {
|
||||
}).finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
this.download('export/carousel/export', {
|
||||
...this.queryParams
|
||||
}, `carousel_${new Date().getTime()}.xlsx`)
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
281
ruoyi-ui/src/views/site/category/index.vue
Normal file
281
ruoyi-ui/src/views/site/category/index.vue
Normal file
@@ -0,0 +1,281 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="100px">
|
||||
<el-form-item label="语言编码" prop="langCode">
|
||||
<LanguageSelect v-model="queryParams.langCode" placeholder="请选择语种" />
|
||||
</el-form-item>
|
||||
<el-form-item label="分类名称" prop="categoryName">
|
||||
<el-input v-model="queryParams.categoryName" placeholder="请输入分类名称" clearable
|
||||
@keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="分类描述" prop="description">
|
||||
<el-input v-model="queryParams.description" placeholder="请输入分类描述" clearable @keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="排序" prop="sortOrder">
|
||||
<el-input v-model="queryParams.sortOrder" placeholder="请输入排序" clearable @keyup.enter.native="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="是否启用" prop="isEnabled">
|
||||
<el-input v-model="queryParams.isEnabled" placeholder="请输入是否启用" clearable @keyup.enter.native="handleQuery" />
|
||||
</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="['export:category:add']">新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="info" plain icon="el-icon-sort" size="mini" @click="toggleExpandAll">展开/折叠</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table v-if="refreshTable" v-loading="loading" :data="categoryList" row-key="categoryId"
|
||||
:default-expand-all="isExpandAll" :tree-props="{ children: 'children', hasChildren: 'hasChildren' }">
|
||||
<el-table-column label="id" prop="categoryId" />
|
||||
<!-- <el-table-column label="分类类型:0=模块分类,1=展示品分类" align="center" prop="type" /> -->
|
||||
<!-- <el-table-column label="语言编码" align="center" prop="langCode" /> -->
|
||||
<el-table-column label="分类名称" align="center" prop="categoryName" />
|
||||
<el-table-column label="分类描述" align="center" prop="description" />
|
||||
<el-table-column label="排序" align="center" prop="sortOrder" />
|
||||
<el-table-column label="是否启用" align="center" prop="isEnabled" />
|
||||
<el-table-column label="备注" align="center" prop="remark" />
|
||||
<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-edit" @click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['export:category:edit']">修改</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-plus" @click="handleAdd(scope.row)"
|
||||
v-hasPermi="['export:category:add']">新增</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
|
||||
v-hasPermi="['export:category:remove']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 添加或修改分类对话框 -->
|
||||
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
|
||||
<el-form-item label="父分类ID" prop="parentId">
|
||||
<treeselect v-model="form.parentId" :options="categoryOptions" :normalizer="normalizer"
|
||||
placeholder="请选择父分类ID" />
|
||||
</el-form-item>
|
||||
<el-form-item label="分类名称" prop="categoryName">
|
||||
<el-input v-model="form.categoryName" placeholder="请输入分类名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="分类描述" prop="description">
|
||||
<el-input v-model="form.description" type="textarea" placeholder="请输入内容" />
|
||||
</el-form-item>
|
||||
<el-form-item label="排序" prop="sortOrder">
|
||||
<el-input v-model="form.sortOrder" placeholder="请输入排序" />
|
||||
</el-form-item>
|
||||
<el-form-item label="是否启用" prop="isEnabled">
|
||||
<el-input v-model="form.isEnabled" placeholder="请输入是否启用" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { addCategory, delCategory, getCategory, listCategory, updateCategory } from "@/api/site/category";
|
||||
import LanguageSelect from '@/components/LanguageSelect.vue';
|
||||
import Treeselect from "@riophae/vue-treeselect";
|
||||
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
|
||||
|
||||
export default {
|
||||
name: "Category",
|
||||
components: {
|
||||
Treeselect,
|
||||
LanguageSelect
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
// 按钮loading
|
||||
buttonLoading: false,
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 分类表格数据
|
||||
categoryList: [],
|
||||
// 分类树选项
|
||||
categoryOptions: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 是否展开,默认全部展开
|
||||
isExpandAll: true,
|
||||
// 重新渲染表格状态
|
||||
refreshTable: true,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
parentId: undefined,
|
||||
type: undefined,
|
||||
langCode: undefined,
|
||||
categoryName: undefined,
|
||||
description: undefined,
|
||||
sortOrder: undefined,
|
||||
isEnabled: undefined,
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 表单校验
|
||||
rules: {
|
||||
}
|
||||
};
|
||||
},
|
||||
created () {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询分类列表 */
|
||||
getList () {
|
||||
this.loading = true;
|
||||
listCategory(this.queryParams).then(response => {
|
||||
this.categoryList = this.handleTree(response.data, "categoryId", "parentId");
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 转换分类数据结构 */
|
||||
normalizer (node) {
|
||||
if (node.children && !node.children.length) {
|
||||
delete node.children;
|
||||
}
|
||||
return {
|
||||
id: node.categoryId,
|
||||
label: node.description,
|
||||
children: node.children
|
||||
};
|
||||
},
|
||||
/** 查询分类下拉树结构 */
|
||||
getTreeselect () {
|
||||
listCategory().then(response => {
|
||||
this.categoryOptions = [];
|
||||
const data = { categoryId: 0, categoryName: '顶级节点', description: '顶级节点', children: [] };
|
||||
data.children = this.handleTree(response.data, "categoryId", "parentId");
|
||||
this.categoryOptions.push(data);
|
||||
});
|
||||
},
|
||||
// 取消按钮
|
||||
cancel () {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
// 表单重置
|
||||
reset () {
|
||||
this.form = {
|
||||
categoryId: null,
|
||||
parentId: null,
|
||||
type: null,
|
||||
langCode: null,
|
||||
categoryName: null,
|
||||
description: null,
|
||||
sortOrder: null,
|
||||
isEnabled: null,
|
||||
delFlag: null,
|
||||
remark: null,
|
||||
createTime: null,
|
||||
createBy: null,
|
||||
updateTime: null,
|
||||
updateBy: null
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery () {
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery () {
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd (row) {
|
||||
this.reset();
|
||||
this.getTreeselect();
|
||||
if (row != null && row.categoryId) {
|
||||
this.form.parentId = row.categoryId;
|
||||
} else {
|
||||
this.form.parentId = 0;
|
||||
}
|
||||
this.open = true;
|
||||
this.title = "添加分类";
|
||||
},
|
||||
/** 展开/折叠操作 */
|
||||
toggleExpandAll () {
|
||||
this.refreshTable = false;
|
||||
this.isExpandAll = !this.isExpandAll;
|
||||
this.$nextTick(() => {
|
||||
this.refreshTable = true;
|
||||
});
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate (row) {
|
||||
this.loading = true;
|
||||
this.reset();
|
||||
this.getTreeselect();
|
||||
if (row != null) {
|
||||
this.form.parentId = row.categoryId;
|
||||
}
|
||||
getCategory(row.categoryId).then(response => {
|
||||
this.loading = false;
|
||||
this.form = response.data;
|
||||
this.open = true;
|
||||
this.title = "修改分类";
|
||||
});
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm () {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (valid) {
|
||||
this.buttonLoading = true;
|
||||
if (this.form.categoryId != null) {
|
||||
updateCategory(this.form).then(response => {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}).finally(() => {
|
||||
this.buttonLoading = false;
|
||||
});
|
||||
} else {
|
||||
addCategory(this.form).then(response => {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}).finally(() => {
|
||||
this.buttonLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete (row) {
|
||||
this.$modal.confirm('是否确认删除分类编号为"' + row.categoryId + '"的数据项?').then(() => {
|
||||
this.loading = true;
|
||||
return delCategory(row.categoryId);
|
||||
}).then(() => {
|
||||
this.loading = false;
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => {
|
||||
}).finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
360
ruoyi-ui/src/views/site/contact/index.vue
Normal file
360
ruoyi-ui/src/views/site/contact/index.vue
Normal file
@@ -0,0 +1,360 @@
|
||||
<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="langCode">
|
||||
<LanguageSelect v-model="queryParams.langCode" placeholder="请选择语种" />
|
||||
</el-form-item>
|
||||
<el-form-item label="联系电话" prop="phone">
|
||||
<el-input
|
||||
v-model="queryParams.phone"
|
||||
placeholder="请输入联系电话"
|
||||
clearable
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="联系邮箱" prop="email">
|
||||
<el-input
|
||||
v-model="queryParams.email"
|
||||
placeholder="请输入联系邮箱"
|
||||
clearable
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="传真" prop="fax">
|
||||
<el-input
|
||||
v-model="queryParams.fax"
|
||||
placeholder="请输入传真"
|
||||
clearable
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="联系地址" prop="address">
|
||||
<el-input
|
||||
v-model="queryParams.address"
|
||||
placeholder="请输入联系地址"
|
||||
clearable
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="二维码链接" prop="qrCode">
|
||||
<el-input
|
||||
v-model="queryParams.qrCode"
|
||||
placeholder="请输入二维码链接"
|
||||
clearable
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="额外说明" prop="description">
|
||||
<el-input
|
||||
v-model="queryParams.description"
|
||||
placeholder="请输入额外说明"
|
||||
clearable
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="排序" prop="sortOrder">
|
||||
<el-input
|
||||
v-model="queryParams.sortOrder"
|
||||
placeholder="请输入排序"
|
||||
clearable
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</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"
|
||||
>新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="success"
|
||||
plain
|
||||
icon="el-icon-edit"
|
||||
size="mini"
|
||||
:disabled="single"
|
||||
@click="handleUpdate"
|
||||
>修改</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
icon="el-icon-delete"
|
||||
size="mini"
|
||||
:disabled="multiple"
|
||||
@click="handleDelete"
|
||||
>删除</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="warning"
|
||||
plain
|
||||
icon="el-icon-download"
|
||||
size="mini"
|
||||
@click="handleExport"
|
||||
>导出</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="contactList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<!-- <el-table-column label="联系方式主键" align="center" prop="contactId" v-if="true"/> -->
|
||||
<el-table-column label="语言编码" align="center" prop="langCode" />
|
||||
<el-table-column label="联系电话" align="center" prop="phone" />
|
||||
<el-table-column label="联系邮箱" align="center" prop="email" />
|
||||
<el-table-column label="传真" align="center" prop="fax" />
|
||||
<el-table-column label="联系地址" align="center" prop="address" />
|
||||
<el-table-column label="二维码链接" align="center" prop="qrCode" />
|
||||
<el-table-column label="额外说明" align="center" prop="description" />
|
||||
<el-table-column label="排序" align="center" prop="sortOrder" />
|
||||
<el-table-column label="备注" align="center" prop="remark" />
|
||||
<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-edit"
|
||||
@click="handleUpdate(scope.row)"
|
||||
>修改</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-delete"
|
||||
@click="handleDelete(scope.row)"
|
||||
>删除</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="500px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
|
||||
<el-form-item label="语言编码" prop="langCode">
|
||||
<LanguageSelect v-model="form.langCode" placeholder="请选择语种" />
|
||||
</el-form-item>
|
||||
<el-form-item label="联系电话" prop="phone">
|
||||
<el-input v-model="form.phone" placeholder="请输入联系电话" />
|
||||
</el-form-item>
|
||||
<el-form-item label="联系邮箱" prop="email">
|
||||
<el-input v-model="form.email" placeholder="请输入联系邮箱" />
|
||||
</el-form-item>
|
||||
<el-form-item label="传真" prop="fax">
|
||||
<el-input v-model="form.fax" placeholder="请输入传真" />
|
||||
</el-form-item>
|
||||
<el-form-item label="联系地址" prop="address">
|
||||
<el-input v-model="form.address" type="textarea" placeholder="请输入内容" />
|
||||
</el-form-item>
|
||||
<el-form-item label="二维码链接" prop="qrCode">
|
||||
<el-input v-model="form.qrCode" type="textarea" placeholder="请输入内容" />
|
||||
</el-form-item>
|
||||
<el-form-item label="额外说明" prop="description">
|
||||
<el-input v-model="form.description" type="textarea" placeholder="请输入内容" />
|
||||
</el-form-item>
|
||||
<el-form-item label="排序" prop="sortOrder">
|
||||
<el-input v-model="form.sortOrder" placeholder="请输入排序" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { addContact, delContact, getContact, listContact, updateContact } from "@/api/site/contact";
|
||||
import LanguageSelect from '@/components/LanguageSelect.vue';
|
||||
|
||||
export default {
|
||||
name: "Contact",
|
||||
components: {
|
||||
LanguageSelect
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 按钮loading
|
||||
buttonLoading: false,
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 选中数组
|
||||
ids: [],
|
||||
// 非单个禁用
|
||||
single: true,
|
||||
// 非多个禁用
|
||||
multiple: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 联系方式表格数据
|
||||
contactList: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
langCode: undefined,
|
||||
phone: undefined,
|
||||
email: undefined,
|
||||
fax: undefined,
|
||||
address: undefined,
|
||||
qrCode: undefined,
|
||||
description: undefined,
|
||||
sortOrder: undefined,
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 表单校验
|
||||
rules: {
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询联系方式列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
listContact(this.queryParams).then(response => {
|
||||
this.contactList = response.rows;
|
||||
this.total = response.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
// 取消按钮
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
// 表单重置
|
||||
reset() {
|
||||
this.form = {
|
||||
contactId: undefined,
|
||||
langCode: undefined,
|
||||
phone: undefined,
|
||||
email: undefined,
|
||||
fax: undefined,
|
||||
address: undefined,
|
||||
qrCode: undefined,
|
||||
description: undefined,
|
||||
sortOrder: undefined,
|
||||
delFlag: undefined,
|
||||
remark: undefined,
|
||||
createTime: undefined,
|
||||
createBy: undefined,
|
||||
updateTime: undefined,
|
||||
updateBy: undefined
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
// 多选框选中数据
|
||||
handleSelectionChange(selection) {
|
||||
this.ids = selection.map(item => item.contactId)
|
||||
this.single = selection.length!==1
|
||||
this.multiple = !selection.length
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset();
|
||||
this.open = true;
|
||||
this.title = "添加联系方式";
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.loading = true;
|
||||
this.reset();
|
||||
const contactId = row.contactId || this.ids
|
||||
getContact(contactId).then(response => {
|
||||
this.loading = false;
|
||||
this.form = response.data;
|
||||
this.open = true;
|
||||
this.title = "修改联系方式";
|
||||
});
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (valid) {
|
||||
this.buttonLoading = true;
|
||||
if (this.form.contactId != null) {
|
||||
updateContact(this.form).then(response => {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}).finally(() => {
|
||||
this.buttonLoading = false;
|
||||
});
|
||||
} else {
|
||||
addContact(this.form).then(response => {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}).finally(() => {
|
||||
this.buttonLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const contactIds = row.contactId || this.ids;
|
||||
this.$modal.confirm('是否确认删除联系方式编号为"' + contactIds + '"的数据项?').then(() => {
|
||||
this.loading = true;
|
||||
return delContact(contactIds);
|
||||
}).then(() => {
|
||||
this.loading = false;
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => {
|
||||
}).finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
this.download('export/contact/export', {
|
||||
...this.queryParams
|
||||
}, `contact_${new Date().getTime()}.xlsx`)
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
724
ruoyi-ui/src/views/site/item/index.vue
Normal file
724
ruoyi-ui/src/views/site/item/index.vue
Normal file
@@ -0,0 +1,724 @@
|
||||
<template>
|
||||
<div class="app-container" style="display: flex;">
|
||||
<!-- 左侧分类树 -->
|
||||
<div style="width: 260px; margin-right: 20px;">
|
||||
<el-tree :data="categoryOptions" node-key="categoryId" :props="treeProps" @node-click="handleCategoryClick"
|
||||
default-expand-all highlight-current />
|
||||
</div>
|
||||
<!-- 右侧内容 -->
|
||||
<div style="flex: 1;">
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="100px">
|
||||
<el-form-item label="语言编码" prop="langCode">
|
||||
<LanguageSelect v-model="queryParams.langCode" placeholder="请选择语种" />
|
||||
</el-form-item>
|
||||
<el-form-item label="多语言键" prop="itemName">
|
||||
<el-input v-model="queryParams.itemName" placeholder="请输入多语言键" clearable @keyup.enter.native="handleQuery" />
|
||||
</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">新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single"
|
||||
@click="handleUpdate">修改</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple"
|
||||
@click="handleDelete">删除</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport">导出</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<ItemGroupTable v-loading="loading" :itemList="itemList" @update="handleUpdate" @delete="handleDelete" />
|
||||
|
||||
<!-- 新增展示品对话框(独立) -->
|
||||
<el-dialog title="添加展示品" :visible.sync="addOpen" width="800px" append-to-body>
|
||||
<el-form ref="addFormRef" :model="addForm" :rules="addRules" label-width="100px">
|
||||
<!-- 新增公共字段 -->
|
||||
<el-row>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="分类" prop="categoryId">
|
||||
<treeselect v-model="addForm.categoryId" :options="categoryOptions" :normalizer="normalizer"
|
||||
placeholder="请选择分类" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="多语言键" prop="itemName">
|
||||
<el-input v-model="addForm.itemName" placeholder="请输入多语言键" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="简述" prop="description">
|
||||
<el-input v-model="addForm.description" type="textarea" placeholder="请输入内容" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 新增:语言多选 + 动态正文 -->
|
||||
<el-form-item label="选择语言" prop="selectedLangs">
|
||||
<el-select v-model="addForm.selectedLangs" multiple placeholder="请选择需要添加的语言" style="width: 100%;"
|
||||
@change="handleAddLangChange" :loading="langLoading">
|
||||
<el-option v-for="lang in languageList" :key="lang.langCode"
|
||||
:label="`${lang.languageName} (${lang.langCode})`" :value="lang.langCode"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 动态正文输入框(修复 prop 路径) -->
|
||||
<div v-if="addForm.selectedLangs && addForm.selectedLangs.length > 0" class="lang-content-group">
|
||||
<el-form-item v-for="(langCode, index) in addForm.selectedLangs" :key="langCode"
|
||||
:label="`${getLangName(langCode)}正文`" :prop="`addLangContents.${index}.content`" :rules="[
|
||||
{ required: true, message: `请输入${getLangName(langCode)}正文`, trigger: 'blur' }
|
||||
]">
|
||||
<el-input type="textarea" v-model="addForm.addLangContents[index].content"
|
||||
:placeholder="`请输入${getLangName(langCode)}正文内容`" :min-height="120" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="addForm.remark" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button :loading="addLoading" type="primary" @click="submitAdd">确 定</el-button>
|
||||
<el-button @click="cancelAdd">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 修改展示品对话框(独立) -->
|
||||
<el-dialog title="修改展示品" :visible.sync="editOpen" width="800px" append-to-body>
|
||||
<el-form ref="editFormRef" :model="editForm" :rules="editRules" label-width="100px">
|
||||
<!-- 修改公共字段 -->
|
||||
<el-row>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="分类" prop="categoryId">
|
||||
<treeselect v-model="editForm.categoryId" :options="categoryOptions" :normalizer="normalizer"
|
||||
placeholder="请选择分类" disabled />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="多语言键" prop="itemName">
|
||||
<el-input v-model="editForm.itemName" placeholder="请输入多语言键" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="语言编码" prop="langCode">
|
||||
<el-select v-model="editForm.langCode" placeholder="请选择语言">
|
||||
<el-option v-for="lang in languageList" :key="lang.langCode"
|
||||
:label="`${lang.languageName} (${lang.langCode})`" :value="lang.langCode"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-form-item label="简述" prop="description">
|
||||
<el-input v-model="editForm.description" type="textarea" placeholder="请输入内容" />
|
||||
</el-form-item>
|
||||
|
||||
<!-- 修改:正文编辑区域(增加普通文本/JSON切换) -->
|
||||
<el-form-item label="正文" prop="content">
|
||||
<!-- 切换按钮 -->
|
||||
<el-button type="text" :class="{ 'text-primary': !editForm.isJsonMode }" @click="toggleEditMode(false)">
|
||||
<i class="el-icon-font" style="margin-right: 4px;"></i>普通文本
|
||||
</el-button>
|
||||
<el-button type="text" :class="{ 'text-primary': editForm.isJsonMode }" @click="toggleEditMode(true)">
|
||||
<i class="el-icon-code" style="margin-right: 4px;"></i>JSON格式
|
||||
</el-button>
|
||||
<!-- JSON模式提示 -->
|
||||
<el-tooltip v-if="editForm.isJsonMode" content="支持JSON格式化和语法校验" placement="right">
|
||||
<i class="el-icon-info" style="color: #409EFF; margin-left: 8px; cursor: pointer;"></i>
|
||||
</el-tooltip>
|
||||
|
||||
<!-- 根据模式显示不同编辑器 -->
|
||||
<div v-if="editForm.isJsonMode">
|
||||
<json-editor v-model="editForm.jsonContent" :height="200"
|
||||
:editor-options="{ mode: 'code', indentation: 2 }" @error="handleJsonError" />
|
||||
</div>
|
||||
<div v-else>
|
||||
<el-input type="textarea" v-model="editForm.textContent" placeholder="请输入正文内容" :min-height="200"
|
||||
resize="vertical" />
|
||||
</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="editForm.remark" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button :loading="editLoading" type="primary" @click="submitEdit">确 定</el-button>
|
||||
<el-button @click="cancelEdit">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listCategory } from "@/api/site/category";
|
||||
import { addItem, delItem, getItem, listItem, updateItem } from "@/api/site/item";
|
||||
import { listLanguage } from '@/api/site/language';
|
||||
import JsonEditor from '@/components/JSONEditor/index.vue';
|
||||
import LanguageSelect from '@/components/LanguageSelect.vue';
|
||||
import Treeselect from "@riophae/vue-treeselect";
|
||||
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
|
||||
import ItemGroupTable from "../panels/ItemGroupTable/index.vue";
|
||||
import ItemTable from "../panels/ItemTable/index.vue";
|
||||
|
||||
export default {
|
||||
name: "Item",
|
||||
components: {
|
||||
Treeselect,
|
||||
LanguageSelect,
|
||||
ItemGroupTable,
|
||||
ItemTable,
|
||||
JsonEditor,
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 选中数组
|
||||
ids: [],
|
||||
// 分类树选项
|
||||
categoryOptions: [],
|
||||
// 分类ID到描述的映射
|
||||
categoryMap: {},
|
||||
// 非单个禁用(修改按钮)
|
||||
single: true,
|
||||
// 非多个禁用(删除按钮)
|
||||
multiple: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 展示品表格数据
|
||||
itemList: [],
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 999,
|
||||
categoryId: undefined,
|
||||
langCode: undefined,
|
||||
itemName: undefined,
|
||||
description: undefined,
|
||||
content: undefined,
|
||||
accessory: undefined,
|
||||
linkUrl: undefined,
|
||||
itemType: undefined,
|
||||
sortOrder: undefined,
|
||||
isEnabled: undefined,
|
||||
},
|
||||
// 当前选中的分类ID
|
||||
currentCategoryId: null,
|
||||
// el-tree 配置
|
||||
treeProps: {
|
||||
label: 'description',
|
||||
children: 'children'
|
||||
},
|
||||
// 语言列表(从API获取)
|
||||
languageList: [],
|
||||
// 语言加载状态
|
||||
langLoading: false,
|
||||
|
||||
// ---------------------- 新增表单相关(独立)----------------------
|
||||
addOpen: false, // 新增弹窗显示状态
|
||||
addLoading: false, // 新增按钮loading
|
||||
// 新增表单数据(关键修改:addLangContents 移到 addForm 内部)
|
||||
addForm: {
|
||||
categoryId: undefined,
|
||||
selectedLangs: [], // 新增:多选语言编码
|
||||
addLangContents: [], // 动态正文内容(移到 form 内部)
|
||||
itemName: undefined,
|
||||
description: undefined,
|
||||
linkUrl: undefined,
|
||||
sortOrder: undefined,
|
||||
remark: undefined,
|
||||
isEnabled: 1, // 默认启用
|
||||
},
|
||||
// 新增:附件输入框内容(多行字符串)
|
||||
addAccessoryInput: '',
|
||||
// 新增表单校验规则(prop 路径对应 addForm.addLangContents)
|
||||
addRules: {
|
||||
categoryId: [{ required: true, message: '请选择分类', trigger: 'change' }],
|
||||
itemName: [{ required: true, message: '请输入多语言键', trigger: 'blur' }],
|
||||
selectedLangs: [{ required: true, message: '请至少选择一种语言', trigger: 'change' }],
|
||||
sortOrder: [{ required: true, message: '请输入排序', trigger: 'blur', type: 'number' }],
|
||||
// 动态正文的校验规则已在 el-form-item 上内联定义(因为是动态的)
|
||||
},
|
||||
|
||||
// ---------------------- 修改表单相关(独立)----------------------
|
||||
editOpen: false, // 修改弹窗显示状态
|
||||
editLoading: false, // 修改按钮loading
|
||||
// 修改表单数据(新增编辑模式相关字段)
|
||||
editForm: {
|
||||
itemId: undefined,
|
||||
categoryId: undefined,
|
||||
langCode: undefined,
|
||||
itemName: undefined,
|
||||
description: undefined,
|
||||
content: undefined, // 最终提交的正文内容(字符串)
|
||||
textContent: '', // 普通文本模式的内容
|
||||
jsonContent: {}, // JSON模式的内容(对象)
|
||||
isJsonMode: false, // 编辑模式:false=普通文本,true=JSON
|
||||
accessory: undefined,
|
||||
linkUrl: undefined,
|
||||
sortOrder: undefined,
|
||||
remark: undefined,
|
||||
isEnabled: 1,
|
||||
},
|
||||
// 修改:附件输入框内容(多行字符串)
|
||||
editAccessoryInput: '',
|
||||
// 修改表单校验规则(调整content的校验逻辑)
|
||||
editRules: {
|
||||
description: [{ required: true, message: '请输入简述', trigger: 'blur' }],
|
||||
content: [
|
||||
{ required: true, message: '请输入正文', trigger: 'blur' },
|
||||
// JSON模式时额外校验格式
|
||||
{
|
||||
validator: (rule, value, callback) => {
|
||||
if (this.editForm.isJsonMode && value) {
|
||||
try {
|
||||
JSON.parse(value);
|
||||
callback();
|
||||
} catch (e) {
|
||||
callback(new Error('JSON格式错误,请检查语法'));
|
||||
}
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
},
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
sortOrder: [{ required: true, message: '请输入排序', trigger: 'blur', type: 'number' }],
|
||||
}
|
||||
};
|
||||
},
|
||||
created () {
|
||||
this.getList();
|
||||
this.getTreeselect();
|
||||
this.fetchLanguageList(); // 初始化获取语言列表
|
||||
|
||||
// 监听编辑模式变化,同步content值
|
||||
this.$watch(
|
||||
() => this.editForm.isJsonMode,
|
||||
(newVal, oldVal) => {
|
||||
if (newVal !== oldVal) {
|
||||
this.syncEditContent();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// 监听textContent变化,同步到content(普通文本模式)
|
||||
this.$watch(
|
||||
() => this.editForm.textContent,
|
||||
(val) => {
|
||||
if (!this.editForm.isJsonMode) {
|
||||
this.editForm.content = val;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// 监听jsonContent变化,同步到content(JSON模式)
|
||||
this.$watch(
|
||||
() => this.editForm.jsonContent,
|
||||
(val) => {
|
||||
if (this.editForm.isJsonMode && val) {
|
||||
try {
|
||||
this.editForm.content = JSON.stringify(val, null, 2);
|
||||
} catch (e) {
|
||||
this.editForm.content = '';
|
||||
}
|
||||
}
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
},
|
||||
methods: {
|
||||
/** 查询展示品列表 */
|
||||
getList () {
|
||||
this.loading = true;
|
||||
listItem(this.queryParams).then(response => {
|
||||
this.itemList = response.rows;
|
||||
this.total = response.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
|
||||
/** 判断是否为JSON字符串 */
|
||||
isJson (str) {
|
||||
try {
|
||||
JSON.parse(str);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
/** 查询分类下拉树结构 */
|
||||
getTreeselect () {
|
||||
listCategory().then(response => {
|
||||
this.categoryOptions = [];
|
||||
const data = { categoryId: 0, categoryName: '顶级节点', description: '顶级节点', children: [] };
|
||||
data.children = this.handleTree(response.data, "categoryId", "parentId");
|
||||
this.categoryOptions.push(data);
|
||||
// 构建categoryMap
|
||||
this.categoryMap = {};
|
||||
function buildMap (list) {
|
||||
list.forEach(item => {
|
||||
if (item.categoryId !== undefined) {
|
||||
let desc = item.description || item.categoryName || String(item.categoryId);
|
||||
if (item.categoryId !== 0) {
|
||||
this.categoryMap[item.categoryId] = desc;
|
||||
}
|
||||
}
|
||||
if (item.children && item.children.length) buildMap.call(this, item.children);
|
||||
});
|
||||
}
|
||||
buildMap.call(this, this.categoryOptions);
|
||||
});
|
||||
},
|
||||
|
||||
/** 从API获取语言列表 */
|
||||
fetchLanguageList () {
|
||||
this.langLoading = true;
|
||||
listLanguage({ pageSize: 1000 }).then(res => {
|
||||
this.languageList = res.rows || [];
|
||||
this.langLoading = false;
|
||||
}).catch(() => {
|
||||
this.langLoading = false;
|
||||
this.$modal.msgError('获取语言列表失败');
|
||||
});
|
||||
},
|
||||
|
||||
/** 转换分类数据结构 */
|
||||
normalizer (node) {
|
||||
if (node.children && !node.children.length) {
|
||||
delete node.children;
|
||||
}
|
||||
return {
|
||||
id: node.categoryId,
|
||||
label: node.description,
|
||||
children: node.children
|
||||
};
|
||||
},
|
||||
|
||||
// 分类树点击事件
|
||||
handleCategoryClick (node) {
|
||||
this.currentCategoryId = node.categoryId;
|
||||
this.queryParams.categoryId = node.categoryId;
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery () {
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
|
||||
/** 重置按钮操作 */
|
||||
resetQuery () {
|
||||
this.$refs.queryForm.resetFields();
|
||||
if (this.currentCategoryId) {
|
||||
this.queryParams.categoryId = this.currentCategoryId;
|
||||
} else {
|
||||
this.queryParams.categoryId = undefined;
|
||||
}
|
||||
this.handleQuery();
|
||||
},
|
||||
|
||||
// 表格多选框选中事件
|
||||
handleSelectionChange (selection) {
|
||||
this.ids = selection.map(item => item.itemId);
|
||||
this.single = selection.length !== 1; // 选中1条时启用修改按钮
|
||||
this.multiple = !selection.length; // 至少选中1条时启用删除按钮
|
||||
},
|
||||
|
||||
// ---------------------- 新增表单操作(独立)----------------------
|
||||
/** 新增按钮操作 */
|
||||
handleAdd () {
|
||||
this.resetAddForm(); // 重置新增表单
|
||||
// 自动带入当前选中的分类
|
||||
if (this.currentCategoryId) {
|
||||
this.addForm.categoryId = this.currentCategoryId;
|
||||
}
|
||||
this.addOpen = true;
|
||||
},
|
||||
|
||||
/** 重置新增表单 */
|
||||
resetAddForm () {
|
||||
this.addForm = {
|
||||
categoryId: this.currentCategoryId || undefined,
|
||||
selectedLangs: [],
|
||||
addLangContents: [], // 重置动态正文数组
|
||||
itemName: undefined,
|
||||
description: undefined,
|
||||
linkUrl: undefined,
|
||||
sortOrder: undefined,
|
||||
remark: undefined,
|
||||
isEnabled: 1,
|
||||
};
|
||||
this.addAccessoryInput = '';
|
||||
if (this.$refs.addFormRef) {
|
||||
this.$refs.addFormRef.resetFields();
|
||||
}
|
||||
},
|
||||
|
||||
/** 取消新增 */
|
||||
cancelAdd () {
|
||||
this.addOpen = false;
|
||||
this.resetAddForm();
|
||||
},
|
||||
|
||||
/** 新增:语言选择变化时,同步动态正文数组(修改为操作 addForm.addLangContents) */
|
||||
handleAddLangChange (selectedLangs) {
|
||||
this.addForm.addLangContents = selectedLangs.map(langCode => {
|
||||
// 保留已输入的正文内容
|
||||
const existing = this.addForm.addLangContents.find(item => item.langCode === langCode);
|
||||
return existing || { langCode, content: '' };
|
||||
});
|
||||
},
|
||||
|
||||
/** 提交新增表单(批量新增多语言) */
|
||||
submitAdd () {
|
||||
// 处理附件:多行转逗号分隔
|
||||
const accessory = this.addAccessoryInput
|
||||
.split('\n')
|
||||
.map(s => s.trim())
|
||||
.filter(s => s)
|
||||
.join(',');
|
||||
|
||||
this.$refs.addFormRef.validate(valid => {
|
||||
if (valid) {
|
||||
this.addLoading = true;
|
||||
// 构建每个语言的新增请求参数(从 addForm.addLangContents 取值)
|
||||
const requestList = this.addForm.selectedLangs.map((langCode, index) => ({
|
||||
categoryId: this.addForm.categoryId,
|
||||
langCode,
|
||||
itemName: this.addForm.itemName,
|
||||
description: this.addForm.description,
|
||||
content: this.addForm.addLangContents[index].content, // 修复取值路径
|
||||
accessory,
|
||||
linkUrl: this.addForm.linkUrl,
|
||||
sortOrder: this.addForm.sortOrder,
|
||||
isEnabled: this.addForm.isEnabled,
|
||||
remark: this.addForm.remark,
|
||||
}));
|
||||
|
||||
// 并发提交所有语言的新增请求
|
||||
Promise.all(requestList.map(params => addItem(params)))
|
||||
.then(() => {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.addOpen = false;
|
||||
this.getList();
|
||||
})
|
||||
.catch(error => {
|
||||
this.$modal.msgError(error.message || "新增失败");
|
||||
})
|
||||
.finally(() => {
|
||||
this.addLoading = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// ---------------------- 修改表单操作(独立)----------------------
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate (row) {
|
||||
const itemId = row && row.itemId ? row.itemId : this.ids[0]; // 优先取行数据,其次取选中的第一条
|
||||
this.loading = true;
|
||||
getItem(itemId).then(response => {
|
||||
this.loading = false;
|
||||
const data = { ...response.data };
|
||||
|
||||
// 初始化编辑模式和内容
|
||||
const isJson = this.isJson(data.content || '');
|
||||
this.editForm = {
|
||||
...data,
|
||||
isJsonMode: isJson,
|
||||
textContent: isJson ? JSON.stringify(data.content, null, 2) : data.content || '',
|
||||
jsonContent: isJson ? JSON.parse(data.content) : {},
|
||||
};
|
||||
|
||||
// 附件回显:逗号分隔转多行
|
||||
this.editAccessoryInput = this.editForm.accessory
|
||||
? this.editForm.accessory.split(',').join('\n')
|
||||
: '';
|
||||
|
||||
this.editOpen = true;
|
||||
});
|
||||
},
|
||||
|
||||
/** 切换编辑模式(普通文本/JSON) */
|
||||
toggleEditMode (isJsonMode) {
|
||||
this.editForm.isJsonMode = isJsonMode;
|
||||
},
|
||||
|
||||
/** 同步编辑内容(模式切换时调用) */
|
||||
syncEditContent () {
|
||||
if (this.editForm.isJsonMode) {
|
||||
// 普通文本 → JSON:尝试解析为JSON对象
|
||||
try {
|
||||
this.editForm.jsonContent = this.editForm.content
|
||||
? JSON.parse(this.editForm.content)
|
||||
: {};
|
||||
} catch (e) {
|
||||
// this.editForm.jsonContent = {};
|
||||
this.$modal.msgWarning('当前文本无法解析为JSON');
|
||||
}
|
||||
} else {
|
||||
// JSON → 普通文本:转为格式化的JSON字符串
|
||||
this.editForm.textContent = this.editForm.jsonContent
|
||||
? JSON.stringify(this.editForm.jsonContent, null, 2)
|
||||
: '';
|
||||
}
|
||||
},
|
||||
|
||||
/** JSON编辑错误处理 */
|
||||
handleJsonError (error) {
|
||||
this.$modal.msgError(`JSON编辑错误:${error.message}`);
|
||||
},
|
||||
|
||||
/** 重置修改表单 */
|
||||
resetEditForm () {
|
||||
this.editForm = {
|
||||
itemId: undefined,
|
||||
categoryId: undefined,
|
||||
langCode: undefined,
|
||||
itemName: undefined,
|
||||
description: undefined,
|
||||
content: undefined,
|
||||
textContent: '',
|
||||
jsonContent: {},
|
||||
isJsonMode: false,
|
||||
accessory: undefined,
|
||||
linkUrl: undefined,
|
||||
sortOrder: undefined,
|
||||
remark: undefined,
|
||||
isEnabled: 1,
|
||||
};
|
||||
this.editAccessoryInput = '';
|
||||
if (this.$refs.editFormRef) {
|
||||
this.$refs.editFormRef.resetFields();
|
||||
}
|
||||
},
|
||||
|
||||
/** 取消修改 */
|
||||
cancelEdit () {
|
||||
this.editOpen = false;
|
||||
this.resetEditForm();
|
||||
},
|
||||
|
||||
/** 提交修改表单(单语言修改) */
|
||||
submitEdit () {
|
||||
// 处理附件:多行转逗号分隔
|
||||
const accessory = this.editAccessoryInput
|
||||
.split('\n')
|
||||
.map(s => s.trim())
|
||||
.filter(s => s)
|
||||
.join(',');
|
||||
|
||||
this.$refs.editFormRef.validate(valid => {
|
||||
if (valid) {
|
||||
this.editLoading = true;
|
||||
// 构建修改请求参数(确保content是字符串格式)
|
||||
const editParams = {
|
||||
...this.editForm,
|
||||
accessory, // 更新处理后的附件
|
||||
content: this.editForm.content || '', // 确保提交字符串
|
||||
};
|
||||
|
||||
updateItem(editParams)
|
||||
.then(() => {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.editOpen = false;
|
||||
this.getList();
|
||||
})
|
||||
.catch(error => {
|
||||
this.$modal.msgError(error.message || "修改失败");
|
||||
})
|
||||
.finally(() => {
|
||||
this.editLoading = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// ---------------------- 公共操作 ----------------------
|
||||
/** 删除按钮操作 */
|
||||
handleDelete (row) {
|
||||
const itemIds = row && row.itemId ? row.itemId : this.ids;
|
||||
this.$modal.confirm(`是否确认删除展示品编号为"${itemIds}"的数据项?`).then(() => {
|
||||
this.loading = true;
|
||||
return delItem(itemIds);
|
||||
}).then(() => {
|
||||
this.loading = false;
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => {
|
||||
}).finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
|
||||
/** 导出按钮操作 */
|
||||
handleExport () {
|
||||
this.download('export/item/export', {
|
||||
...this.queryParams
|
||||
}, `item_${new Date().getTime()}.xlsx`);
|
||||
},
|
||||
|
||||
/** 根据语言编码获取语言名称 */
|
||||
getLangName (langCode) {
|
||||
const lang = this.languageList.find(item => item.langCode === langCode);
|
||||
return lang ? lang.languageName : langCode;
|
||||
},
|
||||
|
||||
/** 树形数据处理 */
|
||||
handleTree (data, id, parentId) {
|
||||
const result = [];
|
||||
const map = {};
|
||||
data.forEach(item => {
|
||||
map[item[id]] = item;
|
||||
});
|
||||
data.forEach(item => {
|
||||
const parent = map[item[parentId]];
|
||||
if (parent) {
|
||||
(parent.children || (parent.children = [])).push(item);
|
||||
} else {
|
||||
result.push(item);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.lang-content-group {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.lang-content-group .el-form-item {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
/* 切换按钮样式优化 */
|
||||
.mb4 {
|
||||
margin-bottom: 4px !important;
|
||||
}
|
||||
|
||||
.text-primary {
|
||||
color: #409eff !important;
|
||||
font-weight: 500;
|
||||
}
|
||||
</style>
|
||||
305
ruoyi-ui/src/views/site/language/index.vue
Normal file
305
ruoyi-ui/src/views/site/language/index.vue
Normal file
@@ -0,0 +1,305 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="100px">
|
||||
<el-form-item label="语言编码" prop="langCode">
|
||||
<el-input
|
||||
v-model="queryParams.langCode"
|
||||
placeholder="请输入语言编码"
|
||||
clearable
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="语言名称" prop="languageName">
|
||||
<el-input
|
||||
v-model="queryParams.languageName"
|
||||
placeholder="请输入语言名称"
|
||||
clearable
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="是否默认语言" prop="isDefault">
|
||||
<el-input
|
||||
v-model="queryParams.isDefault"
|
||||
placeholder="请输入是否默认语言"
|
||||
clearable
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="排序" prop="sortOrder">
|
||||
<el-input
|
||||
v-model="queryParams.sortOrder"
|
||||
placeholder="请输入排序"
|
||||
clearable
|
||||
@keyup.enter.native="handleQuery"
|
||||
/>
|
||||
</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"
|
||||
>新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="success"
|
||||
plain
|
||||
icon="el-icon-edit"
|
||||
size="mini"
|
||||
:disabled="single"
|
||||
@click="handleUpdate"
|
||||
>修改</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
icon="el-icon-delete"
|
||||
size="mini"
|
||||
:disabled="multiple"
|
||||
@click="handleDelete"
|
||||
>删除</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="warning"
|
||||
plain
|
||||
icon="el-icon-download"
|
||||
size="mini"
|
||||
@click="handleExport"
|
||||
>导出</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table v-loading="loading" :data="languageList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<!-- <el-table-column label="语言主键" align="center" prop="languageId" v-if="true"/> -->
|
||||
<el-table-column label="语言编码" align="center" prop="langCode" />
|
||||
<el-table-column label="语言名称" align="center" prop="languageName" />
|
||||
<!-- <el-table-column label="是否默认语言" align="center" prop="isDefault" /> -->
|
||||
<el-table-column label="排序" align="center" prop="sortOrder" />
|
||||
<el-table-column label="备注" align="center" prop="remark" />
|
||||
<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-edit"
|
||||
@click="handleUpdate(scope.row)"
|
||||
>修改</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
type="text"
|
||||
icon="el-icon-delete"
|
||||
@click="handleDelete(scope.row)"
|
||||
>删除</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="500px" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
|
||||
<el-form-item label="语言编码" prop="langCode">
|
||||
<el-input v-model="form.langCode" placeholder="请输入语言编码" />
|
||||
</el-form-item>
|
||||
<el-form-item label="语言名称" prop="languageName">
|
||||
<el-input v-model="form.languageName" placeholder="请输入语言名称" />
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="是否默认语言" prop="isDefault">
|
||||
<el-input v-model="form.isDefault" placeholder="请输入是否默认语言" />
|
||||
</el-form-item> -->
|
||||
<el-form-item label="排序" prop="sortOrder">
|
||||
<el-input v-model="form.sortOrder" placeholder="请输入排序" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button :loading="buttonLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { addLanguage, delLanguage, getLanguage, listLanguage, updateLanguage } from "@/api/site/language";
|
||||
|
||||
export default {
|
||||
name: "Language",
|
||||
data() {
|
||||
return {
|
||||
// 按钮loading
|
||||
buttonLoading: false,
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 选中数组
|
||||
ids: [],
|
||||
// 非单个禁用
|
||||
single: true,
|
||||
// 非多个禁用
|
||||
multiple: true,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
total: 0,
|
||||
// 语言管理表格数据
|
||||
languageList: [],
|
||||
// 弹出层标题
|
||||
title: "",
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
langCode: undefined,
|
||||
languageName: undefined,
|
||||
isDefault: undefined,
|
||||
sortOrder: undefined,
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
// 表单校验
|
||||
rules: {
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询语言管理列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
listLanguage(this.queryParams).then(response => {
|
||||
this.languageList = response.rows;
|
||||
this.total = response.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
// 取消按钮
|
||||
cancel() {
|
||||
this.open = false;
|
||||
this.reset();
|
||||
},
|
||||
// 表单重置
|
||||
reset() {
|
||||
this.form = {
|
||||
languageId: undefined,
|
||||
langCode: undefined,
|
||||
languageName: undefined,
|
||||
isDefault: undefined,
|
||||
sortOrder: undefined,
|
||||
delFlag: undefined,
|
||||
remark: undefined,
|
||||
createTime: undefined,
|
||||
createBy: undefined,
|
||||
updateTime: undefined,
|
||||
updateBy: undefined
|
||||
};
|
||||
this.resetForm("form");
|
||||
},
|
||||
/** 搜索按钮操作 */
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
/** 重置按钮操作 */
|
||||
resetQuery() {
|
||||
this.resetForm("queryForm");
|
||||
this.handleQuery();
|
||||
},
|
||||
// 多选框选中数据
|
||||
handleSelectionChange(selection) {
|
||||
this.ids = selection.map(item => item.languageId)
|
||||
this.single = selection.length !== 1
|
||||
this.multiple = !selection.length
|
||||
},
|
||||
/** 新增按钮操作 */
|
||||
handleAdd() {
|
||||
this.reset();
|
||||
this.open = true;
|
||||
this.title = "添加语言管理";
|
||||
},
|
||||
/** 修改按钮操作 */
|
||||
handleUpdate(row) {
|
||||
this.loading = true;
|
||||
this.reset();
|
||||
const languageId = row.languageId || this.ids
|
||||
getLanguage(languageId).then(response => {
|
||||
this.loading = false;
|
||||
this.form = response.data;
|
||||
this.open = true;
|
||||
this.title = "修改语言管理";
|
||||
});
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitForm() {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (valid) {
|
||||
this.buttonLoading = true;
|
||||
if (this.form.languageId != null) {
|
||||
updateLanguage(this.form).then(response => {
|
||||
this.$modal.msgSuccess("修改成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}).finally(() => {
|
||||
this.buttonLoading = false;
|
||||
});
|
||||
} else {
|
||||
addLanguage(this.form).then(response => {
|
||||
this.$modal.msgSuccess("新增成功");
|
||||
this.open = false;
|
||||
this.getList();
|
||||
}).finally(() => {
|
||||
this.buttonLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
/** 删除按钮操作 */
|
||||
handleDelete(row) {
|
||||
const languageIds = row.languageId || this.ids;
|
||||
this.$modal.confirm('是否确认删除语言管理编号为"' + languageIds + '"的数据项?').then(() => {
|
||||
this.loading = true;
|
||||
return delLanguage(languageIds);
|
||||
}).then(() => {
|
||||
this.loading = false;
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => {
|
||||
}).finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
this.download('export/language/export', {
|
||||
...this.queryParams
|
||||
}, `language_${new Date().getTime()}.xlsx`)
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
94
ruoyi-ui/src/views/site/panels/ItemGroupTable/index.vue
Normal file
94
ruoyi-ui/src/views/site/panels/ItemGroupTable/index.vue
Normal file
@@ -0,0 +1,94 @@
|
||||
<template>
|
||||
<el-table :data="groupedItems" height="500px" row-key="itemName" :expand-row-keys="defaultExpandedRows">
|
||||
<!-- 展开行内容 -->
|
||||
<el-table-column type="expand">
|
||||
<template slot-scope="scope">
|
||||
<el-table :data="scope.row.languages" border size="mini" style="width: 100%; margin-top: 10px;">
|
||||
<el-table-column label="语言编码" align="center" prop="langCode" width="120" />
|
||||
<el-table-column label="正文" align="center" prop="content" show-overflow-tooltip />
|
||||
<el-table-column label="是否启用" align="center" prop="isEnabled" width="100" />
|
||||
<el-table-column label="操作" align="center" width="140">
|
||||
<template slot-scope="langScope">
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(langScope.row)">修改</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete"
|
||||
@click="handleDelete(langScope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- <el-table-column type="selection" width="55" align="center" /> -->
|
||||
<el-table-column label="多语言键" align="center" prop="itemName" />
|
||||
<el-table-column label="描述" align="center" prop="description" />
|
||||
<el-table-column label="排序" align="center" prop="sortOrder" width="80" />
|
||||
<el-table-column label="备注" align="center" prop="remark" />
|
||||
<el-table-column label="语言数量" align="center" width="100">
|
||||
<template slot-scope="scope">{{ scope.row.languages.length }}</template>
|
||||
</el-table-column>
|
||||
<!-- <el-table-column label="操作" align="center" width="160">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-plus" @click="handleAddLanguage(scope.row)">添加语言</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleEditMain(scope.row)">编辑主信息</el-button>
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
</el-table>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "GroupedItemTable",
|
||||
props: {
|
||||
itemList: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
// 可设置默认展开的行
|
||||
defaultExpanded: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
// 按多语言键分组数据
|
||||
groupedItems () {
|
||||
const groups = {};
|
||||
|
||||
// 遍历原始数据进行分组
|
||||
this.itemList.forEach(item => {
|
||||
if (!groups[item.itemName]) {
|
||||
// 初始化分组,提取共同属性
|
||||
groups[item.itemName] = {
|
||||
itemName: item.itemName,
|
||||
description: item.description,
|
||||
sortOrder: item.sortOrder,
|
||||
remark: item.remark,
|
||||
languages: []
|
||||
};
|
||||
}
|
||||
|
||||
// 将当前语言项添加到对应分组
|
||||
groups[item.itemName].languages.push({
|
||||
...item
|
||||
});
|
||||
});
|
||||
|
||||
return Object.values(groups);
|
||||
},
|
||||
// 默认展开的行
|
||||
defaultExpandedRows () {
|
||||
return this.defaultExpanded;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 修改语言项
|
||||
handleUpdate (row) {
|
||||
this.$emit("update", row);
|
||||
},
|
||||
// 删除语言项
|
||||
handleDelete (row) {
|
||||
this.$emit("delete", row);
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
60
ruoyi-ui/src/views/site/panels/ItemTable/index.vue
Normal file
60
ruoyi-ui/src/views/site/panels/ItemTable/index.vue
Normal file
@@ -0,0 +1,60 @@
|
||||
<template>
|
||||
<el-table :data="itemList" height="500px">
|
||||
<!-- <el-table-column type="selection" width="55" align="center" /> -->
|
||||
<!-- <el-table-column label="所属分类" align="center" prop="categoryId" :formatter="categoryDescFormatter" /> -->
|
||||
<el-table-column label="语言编码" align="center" prop="langCode" />
|
||||
<el-table-column label="多语言键" align="center" prop="itemName" />
|
||||
<el-table-column label="描述" align="center" prop="description" />
|
||||
<el-table-column label="正文" align="center" prop="content" show-overflow-tooltip />
|
||||
<!-- <el-table-column label="外链 URL" align="center" prop="linkUrl" /> -->
|
||||
<!-- <el-table-column label="附件" align="center" prop="accessory"> -->
|
||||
<!-- <template slot-scope="scope">
|
||||
<div v-if="scope.row.accessory">
|
||||
<div v-for="(url, idx) in $options.methods.parseAccessory(scope.row.accessory)" :key="idx"
|
||||
style="display:inline-block;margin-right:12px;vertical-align:middle;">
|
||||
<template v-if="$options.methods.isImage(url)">
|
||||
<i class="el-icon-picture-outline" style="color:#409EFF;margin-right:4px;vertical-align:middle;"></i>
|
||||
<el-image :src="url" :preview-src-list="[url]"
|
||||
style="width:40px;height:40px;object-fit:cover;vertical-align:middle;border-radius:4px;border:1px solid #eee;"
|
||||
fit="cover" />
|
||||
</template>
|
||||
<template v-else>
|
||||
<i class="el-icon-link" style="color:#409EFF;margin-right:4px;vertical-align:middle;"></i>
|
||||
<a :href="url" target="_blank"
|
||||
style="color:#409EFF;text-decoration:underline;vertical-align:middle;">附件{{ idx + 1 }}</a>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
<el-table-column label="排序" align="center" prop="sortOrder" />
|
||||
<el-table-column label="是否启用" align="center" prop="isEnabled" />
|
||||
<el-table-column label="备注" align="center" prop="remark" />
|
||||
<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-edit" @click="handleUpdate(scope.row)">修改</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "ItemTable",
|
||||
props: {
|
||||
itemList: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
handleUpdate (row) {
|
||||
this.$emit("update", row);
|
||||
},
|
||||
handleDelete (row) {
|
||||
this.$emit("delete", row);
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user