mirror of
https://gitee.com/beijing_hongye_huicheng/lilishop-ui.git
synced 2026-11-09 02:18:55 +08:00
refactor: 四端完成 Options API → script setup + vuex → pinia 迁移
- buyer(95) / seller(169) / im(53) / manager(280) 共 597 个组件全部从 Options API 转换为 <script setup> - 四端 vuex 全部移除,状态管理统一迁移至 pinia 4(stores/ 目录) - util.js 等基础设施去除 vm 首参依赖;全局属性($Message/$filters 等)在 script 内改为具名导入 - 被外部 ref 访问的公共组件均已补齐 defineExpose(清单见各端 MIGRATION-VUE3.md) - 各端 eslint 启用 vue/component-api-style 防止新代码回退 Options API - 四端 yarn build 全部通过;迁移约定与注意事项已更新至各端 MIGRATION-VUE3.md
This commit is contained in:
@@ -39,7 +39,7 @@
|
||||
:close-on-click-modal="false"
|
||||
destroy-on-close
|
||||
>
|
||||
<el-form ref="form" :model="formAdd" label-width="100px" :rules="formValidate">
|
||||
<el-form ref="formRef" :model="formAdd" label-width="100px" :rules="formValidate">
|
||||
<el-form-item v-if="showParent" label="上级分类" prop="parentId">
|
||||
{{ parentTitle }}
|
||||
<el-input v-model="formAdd.parentId" style="display: none" />
|
||||
@@ -59,137 +59,137 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import { ref, onMounted } from "vue";
|
||||
import { saveArticleCategory, getArticleCategory, delArticleCategory, updateArticleCategory } from "@/api/pages";
|
||||
import { regular } from "@/utils";
|
||||
import { Message, Modal } from "@/utils/message";
|
||||
|
||||
export default {
|
||||
name: "lili-components",
|
||||
data() {
|
||||
return {
|
||||
submitLoading: false,
|
||||
loading: false,
|
||||
expandLevel: 1,
|
||||
modalType: 0,
|
||||
modalVisible: false,
|
||||
modalTitle: "",
|
||||
showParent: false,
|
||||
parentTitle: "",
|
||||
formAdd: {
|
||||
parentId: "",
|
||||
sort: 1,
|
||||
level: 0,
|
||||
articleCategoryName: "",
|
||||
},
|
||||
formValidate: {
|
||||
articleCategoryName: [regular.REQUIRED],
|
||||
sort: [regular.REQUIRED, regular.INTEGER],
|
||||
},
|
||||
tableData: [],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.getAllList();
|
||||
},
|
||||
addChildren(v) {
|
||||
this.modalType = 0;
|
||||
this.modalTitle = "添加子分类";
|
||||
this.formAdd.articleCategoryName = "";
|
||||
this.parentTitle = v.articleCategoryName;
|
||||
this.formAdd.level = Number(v.level) + 1;
|
||||
this.showParent = true;
|
||||
delete this.formAdd.id;
|
||||
this.formAdd.parentId = v.id;
|
||||
this.modalVisible = true;
|
||||
},
|
||||
edit(v) {
|
||||
this.modalType = 1;
|
||||
this.modalTitle = "编辑";
|
||||
this.formAdd.id = v.id;
|
||||
this.formAdd.articleCategoryName = v.articleCategoryName;
|
||||
this.formAdd.level = v.level;
|
||||
this.formAdd.parentId = v.parentId;
|
||||
this.formAdd.sort = v.sort;
|
||||
this.showParent = false;
|
||||
this.modalVisible = true;
|
||||
},
|
||||
addParent() {
|
||||
this.modalType = 0;
|
||||
this.modalTitle = "添加一级分类";
|
||||
this.parentTitle = "顶级分类";
|
||||
this.showParent = true;
|
||||
this.$refs.form?.resetFields();
|
||||
delete this.formAdd.id;
|
||||
this.formAdd.parentId = 0;
|
||||
this.modalVisible = true;
|
||||
},
|
||||
Submit() {
|
||||
this.$refs.form.validate((valid) => {
|
||||
if (!valid) return;
|
||||
this.submitLoading = true;
|
||||
if (this.modalType === 0) {
|
||||
delete this.formAdd.id;
|
||||
saveArticleCategory(this.formAdd).then((res) => {
|
||||
this.submitLoading = false;
|
||||
if (res.success) {
|
||||
this.$Message.success("添加成功");
|
||||
this.formAdd = {
|
||||
parentId: "",
|
||||
sort: 1,
|
||||
level: 0,
|
||||
articleCategoryName: "",
|
||||
};
|
||||
}
|
||||
this.getAllList();
|
||||
this.modalVisible = false;
|
||||
});
|
||||
} else {
|
||||
updateArticleCategory(this.formAdd, this.formAdd.id).then((res) => {
|
||||
this.submitLoading = false;
|
||||
if (res.success) {
|
||||
this.$Message.success("修改成功");
|
||||
}
|
||||
this.getAllList();
|
||||
this.modalVisible = false;
|
||||
this.$refs.form.resetFields();
|
||||
});
|
||||
defineOptions({ name: "lili-components" });
|
||||
|
||||
const submitLoading = ref(false);
|
||||
const loading = ref(false);
|
||||
const expandLevel = ref(1);
|
||||
const modalType = ref(0);
|
||||
const modalVisible = ref(false);
|
||||
const modalTitle = ref("");
|
||||
const showParent = ref(false);
|
||||
const parentTitle = ref("");
|
||||
const formAdd = ref({
|
||||
parentId: "",
|
||||
sort: 1,
|
||||
level: 0,
|
||||
articleCategoryName: "",
|
||||
});
|
||||
const formValidate = ref({
|
||||
articleCategoryName: [regular.REQUIRED],
|
||||
sort: [regular.REQUIRED, regular.INTEGER],
|
||||
});
|
||||
const tableData = ref([]);
|
||||
|
||||
// 模板 el-form 的 ref(原 ref="form",避免与顶层变量重名,改名为 formRef)
|
||||
const formRef = ref(null);
|
||||
|
||||
function init() {
|
||||
getAllList();
|
||||
}
|
||||
function addChildren(v) {
|
||||
modalType.value = 0;
|
||||
modalTitle.value = "添加子分类";
|
||||
formAdd.value.articleCategoryName = "";
|
||||
parentTitle.value = v.articleCategoryName;
|
||||
formAdd.value.level = Number(v.level) + 1;
|
||||
showParent.value = true;
|
||||
delete formAdd.value.id;
|
||||
formAdd.value.parentId = v.id;
|
||||
modalVisible.value = true;
|
||||
}
|
||||
function edit(v) {
|
||||
modalType.value = 1;
|
||||
modalTitle.value = "编辑";
|
||||
formAdd.value.id = v.id;
|
||||
formAdd.value.articleCategoryName = v.articleCategoryName;
|
||||
formAdd.value.level = v.level;
|
||||
formAdd.value.parentId = v.parentId;
|
||||
formAdd.value.sort = v.sort;
|
||||
showParent.value = false;
|
||||
modalVisible.value = true;
|
||||
}
|
||||
function addParent() {
|
||||
modalType.value = 0;
|
||||
modalTitle.value = "添加一级分类";
|
||||
parentTitle.value = "顶级分类";
|
||||
showParent.value = true;
|
||||
formRef.value?.resetFields();
|
||||
delete formAdd.value.id;
|
||||
formAdd.value.parentId = 0;
|
||||
modalVisible.value = true;
|
||||
}
|
||||
function Submit() {
|
||||
formRef.value.validate((valid) => {
|
||||
if (!valid) return;
|
||||
submitLoading.value = true;
|
||||
if (modalType.value === 0) {
|
||||
delete formAdd.value.id;
|
||||
saveArticleCategory(formAdd.value).then((res) => {
|
||||
submitLoading.value = false;
|
||||
if (res.success) {
|
||||
Message.success("添加成功");
|
||||
formAdd.value = {
|
||||
parentId: "",
|
||||
sort: 1,
|
||||
level: 0,
|
||||
articleCategoryName: "",
|
||||
};
|
||||
}
|
||||
getAllList();
|
||||
modalVisible.value = false;
|
||||
});
|
||||
} else {
|
||||
updateArticleCategory(formAdd.value, formAdd.value.id).then((res) => {
|
||||
submitLoading.value = false;
|
||||
if (res.success) {
|
||||
Message.success("修改成功");
|
||||
}
|
||||
getAllList();
|
||||
modalVisible.value = false;
|
||||
formRef.value.resetFields();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
function remove(v) {
|
||||
Modal.confirm({
|
||||
title: "确认删除",
|
||||
content: "您确认要删除 " + v.articleCategoryName + " ?",
|
||||
loading: true,
|
||||
onOk: () => {
|
||||
delArticleCategory(v.id).then((res) => {
|
||||
Modal.remove();
|
||||
if (res.success) {
|
||||
Message.success("操作成功");
|
||||
getAllList();
|
||||
}
|
||||
});
|
||||
},
|
||||
remove(v) {
|
||||
this.$Modal.confirm({
|
||||
title: "确认删除",
|
||||
content: "您确认要删除 " + v.articleCategoryName + " ?",
|
||||
loading: true,
|
||||
onOk: () => {
|
||||
delArticleCategory(v.id).then((res) => {
|
||||
this.$Modal.remove();
|
||||
if (res.success) {
|
||||
this.$Message.success("操作成功");
|
||||
this.getAllList();
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
getAllList() {
|
||||
this.loading = true;
|
||||
getArticleCategory()
|
||||
.then((res) => {
|
||||
if (res.success) {
|
||||
this.tableData = res.result || [];
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
function getAllList() {
|
||||
loading.value = true;
|
||||
getArticleCategory()
|
||||
.then((res) => {
|
||||
if (res.success) {
|
||||
tableData.value = res.result || [];
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
init();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -22,84 +22,81 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import { ref, onMounted } from "vue";
|
||||
import { Chart } from "@antv/g2";
|
||||
import { getHotWordsHistory } from "@/api/index";
|
||||
import { Message } from "@/utils/message";
|
||||
import { unixToDate } from "@/utils/filters";
|
||||
|
||||
export default {
|
||||
name: "HOTWORDS_HISTORY",
|
||||
data() {
|
||||
return {
|
||||
params: {
|
||||
date: "",
|
||||
},
|
||||
hotWordsChart: null,
|
||||
hotWordsData: [],
|
||||
endMonth: null,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
const yesterday = new Date(Date.now() - 24 * 60 * 60 * 1000);
|
||||
this.params.date = this.$filters.unixToDate(Math.floor(yesterday.getTime() / 1000), "yyyy-MM-dd");
|
||||
},
|
||||
methods: {
|
||||
disabledDate(date) {
|
||||
if (this.endMonth) {
|
||||
const endDate = this.getDate(this.endMonth);
|
||||
return (date && date > endDate) || date > new Date();
|
||||
}
|
||||
return date && date > new Date();
|
||||
defineOptions({ name: "HOTWORDS_HISTORY" });
|
||||
|
||||
const params = ref({
|
||||
date: "",
|
||||
});
|
||||
const hotWordsChart = ref(null);
|
||||
const hotWordsData = ref([]);
|
||||
const endMonth = ref(null);
|
||||
|
||||
// 原 created
|
||||
const yesterday = new Date(Date.now() - 24 * 60 * 60 * 1000);
|
||||
params.value.date = unixToDate(Math.floor(yesterday.getTime() / 1000), "yyyy-MM-dd");
|
||||
|
||||
function disabledDate(date) {
|
||||
if (endMonth.value) {
|
||||
const endDate = getDate(endMonth.value);
|
||||
return (date && date > endDate) || date > new Date();
|
||||
}
|
||||
return date && date > new Date();
|
||||
}
|
||||
function getDate(monthStr) {
|
||||
const [year, month] = monthStr.split("-");
|
||||
return new Date(year, month, 0);
|
||||
}
|
||||
async function search(val) {
|
||||
if (val) {
|
||||
params.value.date = val;
|
||||
}
|
||||
const res = await getHotWordsHistory(params.value);
|
||||
if (res.success) {
|
||||
hotWordsData.value = res.result || [];
|
||||
if (hotWordsChart.value) {
|
||||
hotWordsChart.value.changeData(hotWordsData.value);
|
||||
hotWordsChart.value.render();
|
||||
}
|
||||
if (!hotWordsData.value.length) {
|
||||
Message.error("暂无数据");
|
||||
}
|
||||
}
|
||||
}
|
||||
function init() {
|
||||
const chart = new Chart({
|
||||
container: "container",
|
||||
autoFit: true,
|
||||
height: 500,
|
||||
padding: [50, 20, 50, 20],
|
||||
});
|
||||
chart.scale("score", {
|
||||
alias: "搜索次数",
|
||||
});
|
||||
chart.axis("keywords", {
|
||||
tickLine: {
|
||||
alignTick: false,
|
||||
},
|
||||
getDate(monthStr) {
|
||||
const [year, month] = monthStr.split("-");
|
||||
return new Date(year, month, 0);
|
||||
},
|
||||
async search(val) {
|
||||
if (val) {
|
||||
this.params.date = val;
|
||||
}
|
||||
const res = await getHotWordsHistory(this.params);
|
||||
if (res.success) {
|
||||
this.hotWordsData = res.result || [];
|
||||
if (this.hotWordsChart) {
|
||||
this.hotWordsChart.changeData(this.hotWordsData);
|
||||
this.hotWordsChart.render();
|
||||
}
|
||||
if (!this.hotWordsData.length) {
|
||||
Message.error("暂无数据");
|
||||
}
|
||||
}
|
||||
},
|
||||
init() {
|
||||
const chart = new Chart({
|
||||
container: "container",
|
||||
autoFit: true,
|
||||
height: 500,
|
||||
padding: [50, 20, 50, 20],
|
||||
});
|
||||
chart.scale("score", {
|
||||
alias: "搜索次数",
|
||||
});
|
||||
chart.axis("keywords", {
|
||||
tickLine: {
|
||||
alignTick: false,
|
||||
},
|
||||
});
|
||||
chart.axis("score", false);
|
||||
chart.tooltip({
|
||||
showMarkers: false,
|
||||
});
|
||||
chart.interval().position("keywords*score").color("#f59b99");
|
||||
chart.interaction("element-active");
|
||||
this.hotWordsChart = chart;
|
||||
this.search();
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
};
|
||||
});
|
||||
chart.axis("score", false);
|
||||
chart.tooltip({
|
||||
showMarkers: false,
|
||||
});
|
||||
chart.interval().position("keywords*score").color("#f59b99");
|
||||
chart.interaction("element-active");
|
||||
hotWordsChart.value = chart;
|
||||
search();
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
init();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
>
|
||||
<el-form ref="form" :model="form" label-width="100px" :rules="formValidate">
|
||||
<el-form ref="formRef" :model="form" label-width="100px" :rules="formValidate">
|
||||
<el-form-item label="热词" prop="keywords">
|
||||
<el-input v-model="form.keywords" clearable style="width: 100%" />
|
||||
</el-form-item>
|
||||
@@ -45,86 +45,84 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import { onMounted, reactive, ref } from "vue";
|
||||
import { Close } from "@element-plus/icons-vue";
|
||||
import { getHotWords, setHotWords, deleteHotWords } from "@/api/index";
|
||||
import { regular } from "@/utils";
|
||||
import { Message, Modal } from "@/utils/message";
|
||||
|
||||
export default {
|
||||
name: "HOTWORDS_TODAY",
|
||||
components: { Close },
|
||||
data() {
|
||||
return {
|
||||
submitLoading: false,
|
||||
modalTitle: "",
|
||||
loading: true,
|
||||
modalVisible: false,
|
||||
form: {
|
||||
keywords: "",
|
||||
point: 0,
|
||||
},
|
||||
data: [],
|
||||
formValidate: {
|
||||
keywords: [regular.REQUIRED, regular.VARCHAR20],
|
||||
point: [regular.REQUIRED, regular.NUMBER],
|
||||
},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.getDataList();
|
||||
},
|
||||
getDataList() {
|
||||
this.loading = true;
|
||||
getHotWords().then((res) => {
|
||||
this.loading = false;
|
||||
defineOptions({ name: "HOTWORDS_TODAY" });
|
||||
|
||||
const formRef = ref(null);
|
||||
|
||||
const submitLoading = ref(false);
|
||||
const modalTitle = ref("");
|
||||
const loading = ref(true);
|
||||
const modalVisible = ref(false);
|
||||
const form = ref({
|
||||
keywords: "",
|
||||
point: 0,
|
||||
});
|
||||
const data = ref([]);
|
||||
const formValidate = reactive({
|
||||
keywords: [regular.REQUIRED, regular.VARCHAR20],
|
||||
point: [regular.REQUIRED, regular.NUMBER],
|
||||
});
|
||||
|
||||
function init() {
|
||||
getDataList();
|
||||
}
|
||||
function getDataList() {
|
||||
loading.value = true;
|
||||
getHotWords().then((res) => {
|
||||
loading.value = false;
|
||||
if (res.success) {
|
||||
data.value = res.result;
|
||||
}
|
||||
});
|
||||
}
|
||||
function handleSubmit() {
|
||||
formRef.value.validate((valid) => {
|
||||
if (valid) {
|
||||
submitLoading.value = true;
|
||||
setHotWords(form.value).then((res) => {
|
||||
submitLoading.value = false;
|
||||
if (res.success) {
|
||||
this.data = res.result;
|
||||
Message.success("操作成功");
|
||||
getDataList();
|
||||
modalVisible.value = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
function add(words) {
|
||||
modalTitle.value = "设置热词";
|
||||
form.value.keywords = words || "";
|
||||
form.value.point = 1;
|
||||
modalVisible.value = true;
|
||||
}
|
||||
function deleteWords(words) {
|
||||
Modal.confirm({
|
||||
title: "是否确定删除热词",
|
||||
content: "您确定要删除此热词吗?",
|
||||
okText: "确定",
|
||||
cancelText: "取消",
|
||||
onOk: () => {
|
||||
deleteHotWords({ words }).then((res) => {
|
||||
if (res.success) {
|
||||
Message.success("删除成功");
|
||||
getDataList();
|
||||
}
|
||||
});
|
||||
},
|
||||
handleSubmit() {
|
||||
this.$refs.form.validate((valid) => {
|
||||
if (valid) {
|
||||
this.submitLoading = true;
|
||||
setHotWords(this.form).then((res) => {
|
||||
this.submitLoading = false;
|
||||
if (res.success) {
|
||||
this.$Message.success("操作成功");
|
||||
this.getDataList();
|
||||
this.modalVisible = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
add(words) {
|
||||
this.modalTitle = "设置热词";
|
||||
this.form.keywords = words || "";
|
||||
this.form.point = 1;
|
||||
this.modalVisible = true;
|
||||
},
|
||||
deleteWords(words) {
|
||||
this.$Modal.confirm({
|
||||
title: "是否确定删除热词",
|
||||
content: "您确定要删除此热词吗?",
|
||||
okText: "确定",
|
||||
cancelText: "取消",
|
||||
onOk: () => {
|
||||
deleteHotWords({ words }).then((res) => {
|
||||
if (res.success) {
|
||||
this.$Message.success("删除成功");
|
||||
this.getDataList();
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
init();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="layout">
|
||||
<el-form
|
||||
ref="formValidate"
|
||||
ref="formValidateRef"
|
||||
label-width="150px"
|
||||
label-position="right"
|
||||
:model="formValidate"
|
||||
@@ -42,68 +42,67 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import { setSetting } from "@/api/index";
|
||||
import { Message } from "@/utils/message";
|
||||
|
||||
export default {
|
||||
props: ["res", "type"],
|
||||
data() {
|
||||
return {
|
||||
ruleValidate: {},
|
||||
formValidate: {
|
||||
saveNum: 1,
|
||||
hotWordsSettingItems: [
|
||||
{
|
||||
keywords: "",
|
||||
score: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.init();
|
||||
},
|
||||
methods: {
|
||||
addSetItem() {
|
||||
if (this.formValidate.hotWordsSettingItems.length >= 5) {
|
||||
this.$Message.error("最多5个热词项");
|
||||
} else {
|
||||
this.formValidate.hotWordsSettingItems.push({
|
||||
keywords: "",
|
||||
score: 1,
|
||||
});
|
||||
}
|
||||
const props = defineProps(["res", "type"]);
|
||||
|
||||
const formValidateRef = ref(null);
|
||||
// 动态 $refs[name] 查找的映射表
|
||||
const formRefs = { formValidate: formValidateRef };
|
||||
|
||||
const ruleValidate = ref({});
|
||||
const formValidate = ref({
|
||||
saveNum: 1,
|
||||
hotWordsSettingItems: [
|
||||
{
|
||||
keywords: "",
|
||||
score: 1,
|
||||
},
|
||||
submit(name) {
|
||||
this.$refs[name].validate((valid) => {
|
||||
if (valid) {
|
||||
this.setupSetting();
|
||||
} else {
|
||||
this.$Message.error("请正确填写内容!");
|
||||
}
|
||||
});
|
||||
},
|
||||
setupSetting() {
|
||||
setSetting(this.type || "HOT_WORDS", this.formValidate).then((res) => {
|
||||
if (res.success) {
|
||||
this.$Message.success("保存成功!");
|
||||
} else {
|
||||
this.$Message.error("保存失败!");
|
||||
}
|
||||
});
|
||||
},
|
||||
init() {
|
||||
if (!this.res) {
|
||||
return;
|
||||
}
|
||||
const parsed = typeof this.res === "string" ? JSON.parse(this.res) : this.res;
|
||||
if (parsed.hotWordsSettingItems) {
|
||||
this.formValidate = { ...parsed };
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
],
|
||||
});
|
||||
|
||||
init();
|
||||
|
||||
function addSetItem() {
|
||||
if (formValidate.value.hotWordsSettingItems.length >= 5) {
|
||||
Message.error("最多5个热词项");
|
||||
} else {
|
||||
formValidate.value.hotWordsSettingItems.push({
|
||||
keywords: "",
|
||||
score: 1,
|
||||
});
|
||||
}
|
||||
}
|
||||
function submit(name) {
|
||||
formRefs[name].value.validate((valid) => {
|
||||
if (valid) {
|
||||
setupSetting();
|
||||
} else {
|
||||
Message.error("请正确填写内容!");
|
||||
}
|
||||
});
|
||||
}
|
||||
function setupSetting() {
|
||||
setSetting(props.type || "HOT_WORDS", formValidate.value).then((res) => {
|
||||
if (res.success) {
|
||||
Message.success("保存成功!");
|
||||
} else {
|
||||
Message.error("保存失败!");
|
||||
}
|
||||
});
|
||||
}
|
||||
function init() {
|
||||
if (!props.res) {
|
||||
return;
|
||||
}
|
||||
const parsed = typeof props.res === "string" ? JSON.parse(props.res) : props.res;
|
||||
if (parsed.hotWordsSettingItems) {
|
||||
formValidate.value = { ...parsed };
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<div class="article-page__main">
|
||||
<el-card class="article-detail">
|
||||
<el-form
|
||||
ref="searchForm"
|
||||
ref="searchFormRef"
|
||||
:model="searchForm"
|
||||
inline
|
||||
label-width="70px"
|
||||
@@ -100,7 +100,7 @@
|
||||
:close-on-click-modal="false"
|
||||
destroy-on-close
|
||||
>
|
||||
<el-form ref="form" :model="form" label-width="100px" :rules="formValidate">
|
||||
<el-form ref="formRef" :model="form" label-width="100px" :rules="formValidate">
|
||||
<el-form-item label="文章标题" prop="title">
|
||||
<el-input v-model="form.title" clearable style="width: 40%" />
|
||||
</el-form-item>
|
||||
@@ -144,7 +144,8 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import { ref, watch, nextTick, onMounted } from "vue";
|
||||
import {
|
||||
getArticleCategory,
|
||||
saveArticle,
|
||||
@@ -156,6 +157,7 @@ import {
|
||||
} from "@/api/pages";
|
||||
import tinymec from "@/components/editor/index.vue";
|
||||
import { regular } from "@/utils";
|
||||
import { Message, Modal } from "@/utils/message";
|
||||
|
||||
const validateArticleContent = (rule, value, callback) => {
|
||||
const html = String(value || "").trim();
|
||||
@@ -175,280 +177,281 @@ const validateArticleContent = (rule, value, callback) => {
|
||||
callback();
|
||||
};
|
||||
|
||||
export default {
|
||||
components: {
|
||||
tinymec,
|
||||
defineProps({
|
||||
selected: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
props: {
|
||||
selected: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
const emit = defineEmits(["callbacked"]);
|
||||
|
||||
// 模板 el-form 的 ref(原 ref="searchForm",与 data 同名会互相覆盖,改名为 searchFormRef)
|
||||
const searchFormRef = ref(null);
|
||||
const table = ref(null);
|
||||
// 模板 el-form 的 ref(原 ref="form",与 data 同名会互相覆盖,改名为 formRef)
|
||||
const formRef = ref(null);
|
||||
const editor = ref(null);
|
||||
|
||||
const selectedIndex = ref(99999);
|
||||
const loading = ref(true);
|
||||
const modalType = ref(0);
|
||||
const modalVisible = ref(false);
|
||||
const modalTitle = ref("");
|
||||
const treeDataDefault = ref([]);
|
||||
const searchForm = ref({
|
||||
pageNumber: 1,
|
||||
pageSize: 20,
|
||||
sort: "createTime",
|
||||
order: "desc",
|
||||
categoryId: "",
|
||||
});
|
||||
const searchTreeValue = ref("");
|
||||
const form = ref({
|
||||
openStatus: false,
|
||||
title: "",
|
||||
categoryId: "",
|
||||
sort: 1,
|
||||
content: "",
|
||||
id: "",
|
||||
});
|
||||
const formValidate = ref({
|
||||
title: [{ required: true, message: "请输入文章标题", trigger: "blur" }],
|
||||
categoryId: [{ required: true, message: "请选择文章分类", trigger: "change" }],
|
||||
sort: [regular.REQUIRED, regular.INTEGER],
|
||||
content: [{ required: true, validator: validateArticleContent, trigger: "change" }],
|
||||
});
|
||||
const list = ref([]);
|
||||
const treeValue = ref("");
|
||||
const treeData = ref([]);
|
||||
const submitLoading = ref(false);
|
||||
const data = ref([]);
|
||||
const total = ref(0);
|
||||
|
||||
watch(
|
||||
() => searchForm.value.categoryId,
|
||||
() => {
|
||||
handleSearch();
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedIndex: 99999,
|
||||
loading: true,
|
||||
modalType: 0,
|
||||
modalVisible: false,
|
||||
modalTitle: "",
|
||||
treeDataDefault: [],
|
||||
searchForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 20,
|
||||
sort: "createTime",
|
||||
order: "desc",
|
||||
categoryId: "",
|
||||
},
|
||||
searchTreeValue: "",
|
||||
form: {
|
||||
openStatus: false,
|
||||
title: "",
|
||||
categoryId: "",
|
||||
sort: 1,
|
||||
content: "",
|
||||
id: "",
|
||||
},
|
||||
formValidate: {
|
||||
title: [{ required: true, message: "请输入文章标题", trigger: "blur" }],
|
||||
categoryId: [{ required: true, message: "请选择文章分类", trigger: "change" }],
|
||||
sort: [regular.REQUIRED, regular.INTEGER],
|
||||
content: [{ required: true, validator: validateArticleContent, trigger: "change" }],
|
||||
},
|
||||
list: [],
|
||||
treeValue: "",
|
||||
treeData: [],
|
||||
submitLoading: false,
|
||||
data: [],
|
||||
total: 0,
|
||||
};
|
||||
{ deep: true }
|
||||
);
|
||||
watch(
|
||||
() => searchForm.value.title,
|
||||
() => {
|
||||
handleSearch();
|
||||
},
|
||||
watch: {
|
||||
"searchForm.categoryId": {
|
||||
handler() {
|
||||
this.handleSearch();
|
||||
},
|
||||
deep: true,
|
||||
},
|
||||
"searchForm.title": {
|
||||
handler() {
|
||||
this.handleSearch();
|
||||
},
|
||||
deep: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getDefaultForm() {
|
||||
return {
|
||||
openStatus: false,
|
||||
title: "",
|
||||
categoryId: "",
|
||||
sort: 1,
|
||||
content: "",
|
||||
};
|
||||
},
|
||||
init() {
|
||||
this.getDataList();
|
||||
this.getAllList(0);
|
||||
},
|
||||
selectRow(row, index) {
|
||||
this.selectedIndex = index;
|
||||
this.$emit("callbacked", row);
|
||||
},
|
||||
handleCateChange(data) {
|
||||
if (!data) return;
|
||||
const { value, title } = data;
|
||||
this.searchForm.categoryId =
|
||||
value === "0" || value === 0 ? "" : value;
|
||||
this.searchTreeValue = title;
|
||||
},
|
||||
changeSwitch(v) {
|
||||
const params = { status: v.openStatus };
|
||||
updateArticleStatus(v.id, params).then((res) => {
|
||||
this.submitLoading = false;
|
||||
if (res.success) {
|
||||
}
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
function getDefaultForm() {
|
||||
return {
|
||||
openStatus: false,
|
||||
title: "",
|
||||
categoryId: "",
|
||||
sort: 1,
|
||||
content: "",
|
||||
};
|
||||
}
|
||||
function init() {
|
||||
getDataList();
|
||||
getAllList(0);
|
||||
}
|
||||
function selectRow(row, index) {
|
||||
selectedIndex.value = index;
|
||||
emit("callbacked", row);
|
||||
}
|
||||
function handleCateChange(data) {
|
||||
if (!data) return;
|
||||
const { value, title } = data;
|
||||
searchForm.value.categoryId =
|
||||
value === "0" || value === 0 ? "" : value;
|
||||
searchTreeValue.value = title;
|
||||
}
|
||||
function changeSwitch(v) {
|
||||
const params = { status: v.openStatus };
|
||||
updateArticleStatus(v.id, params).then((res) => {
|
||||
submitLoading.value = false;
|
||||
if (res.success) {
|
||||
}
|
||||
});
|
||||
}
|
||||
function handleCategoryChange(value) {
|
||||
form.value.categoryId = value;
|
||||
const findTitle = (nodes, id) => {
|
||||
for (const node of nodes || []) {
|
||||
if (node.value === id) return node.title;
|
||||
const childTitle = findTitle(node.children, id);
|
||||
if (childTitle) return childTitle;
|
||||
}
|
||||
return "";
|
||||
};
|
||||
treeValue.value = findTitle(treeDataDefault.value, value);
|
||||
}
|
||||
function handleCheckChange(data) {
|
||||
let value = "";
|
||||
let title = "";
|
||||
list.value = [];
|
||||
data.forEach((item) => {
|
||||
value += `${item.value},`;
|
||||
title += `${item.title},`;
|
||||
});
|
||||
value = value.substring(0, value.length - 1);
|
||||
title = title.substring(0, title.length - 1);
|
||||
list.value.push({ value, title });
|
||||
form.value.categoryId = value;
|
||||
treeValue.value = title;
|
||||
}
|
||||
function changePage(v) {
|
||||
searchForm.value.pageNumber = v;
|
||||
getDataList();
|
||||
}
|
||||
function changePageSize(v) {
|
||||
searchForm.value.pageNumber = 1;
|
||||
searchForm.value.pageSize = v;
|
||||
getDataList();
|
||||
}
|
||||
function handleSearch() {
|
||||
searchForm.value.pageNumber = 1;
|
||||
searchForm.value.pageSize = 20;
|
||||
getDataList();
|
||||
}
|
||||
function getAllList(parent_id) {
|
||||
loading.value = true;
|
||||
getArticleCategory(parent_id).then((res) => {
|
||||
loading.value = false;
|
||||
if (res.success) {
|
||||
treeData.value = getTree(res.result);
|
||||
treeDataDefault.value = getTree(res.result);
|
||||
treeData.value.unshift({
|
||||
title: "全部",
|
||||
level: 0,
|
||||
children: [],
|
||||
id: "0",
|
||||
categoryId: 0,
|
||||
value: "0",
|
||||
});
|
||||
},
|
||||
handleCategoryChange(value) {
|
||||
this.form.categoryId = value;
|
||||
const findTitle = (nodes, id) => {
|
||||
for (const node of nodes || []) {
|
||||
if (node.value === id) return node.title;
|
||||
const childTitle = findTitle(node.children, id);
|
||||
if (childTitle) return childTitle;
|
||||
}
|
||||
return "";
|
||||
};
|
||||
this.treeValue = findTitle(this.treeDataDefault, value);
|
||||
},
|
||||
handleCheckChange(data) {
|
||||
let value = "";
|
||||
let title = "";
|
||||
this.list = [];
|
||||
data.forEach((item) => {
|
||||
value += `${item.value},`;
|
||||
title += `${item.title},`;
|
||||
});
|
||||
value = value.substring(0, value.length - 1);
|
||||
title = title.substring(0, title.length - 1);
|
||||
this.list.push({ value, title });
|
||||
this.form.categoryId = value;
|
||||
this.treeValue = title;
|
||||
},
|
||||
changePage(v) {
|
||||
this.searchForm.pageNumber = v;
|
||||
this.getDataList();
|
||||
},
|
||||
changePageSize(v) {
|
||||
this.searchForm.pageNumber = 1;
|
||||
this.searchForm.pageSize = v;
|
||||
this.getDataList();
|
||||
},
|
||||
handleSearch() {
|
||||
this.searchForm.pageNumber = 1;
|
||||
this.searchForm.pageSize = 20;
|
||||
this.getDataList();
|
||||
},
|
||||
getAllList(parent_id) {
|
||||
this.loading = true;
|
||||
getArticleCategory(parent_id).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.treeData = this.getTree(res.result);
|
||||
this.treeDataDefault = this.getTree(res.result);
|
||||
this.treeData.unshift({
|
||||
title: "全部",
|
||||
level: 0,
|
||||
children: [],
|
||||
id: "0",
|
||||
categoryId: 0,
|
||||
value: "0",
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
getTree(tree = []) {
|
||||
const arr = [];
|
||||
if (!!tree && tree.length !== 0) {
|
||||
tree.forEach((item) => {
|
||||
const obj = {};
|
||||
obj.title = item.articleCategoryName;
|
||||
obj.value = item.id;
|
||||
obj.attr = item.articleCategoryName;
|
||||
obj.children = this.getTree(item.children);
|
||||
arr.push(obj);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
function getTree(tree = []) {
|
||||
const arr = [];
|
||||
if (!!tree && tree.length !== 0) {
|
||||
tree.forEach((item) => {
|
||||
const obj = {};
|
||||
obj.title = item.articleCategoryName;
|
||||
obj.value = item.id;
|
||||
obj.attr = item.articleCategoryName;
|
||||
obj.children = getTree(item.children);
|
||||
arr.push(obj);
|
||||
});
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
function buildArticleSearchParams() {
|
||||
const params = { ...searchForm.value };
|
||||
const categoryId = params.categoryId;
|
||||
if (
|
||||
categoryId === "" ||
|
||||
categoryId === null ||
|
||||
categoryId === undefined ||
|
||||
categoryId === 0 ||
|
||||
categoryId === "0"
|
||||
) {
|
||||
delete params.categoryId;
|
||||
}
|
||||
return params;
|
||||
}
|
||||
function getDataList(val) {
|
||||
if (val) form.value = {};
|
||||
loading.value = true;
|
||||
getArticle(buildArticleSearchParams())
|
||||
.then((res) => {
|
||||
if (res.success) {
|
||||
total.value = res.result.total;
|
||||
data.value = res.result.records?.length ? res.result.records : [];
|
||||
}
|
||||
return arr;
|
||||
},
|
||||
buildArticleSearchParams() {
|
||||
const params = { ...this.searchForm };
|
||||
const categoryId = params.categoryId;
|
||||
if (
|
||||
categoryId === "" ||
|
||||
categoryId === null ||
|
||||
categoryId === undefined ||
|
||||
categoryId === 0 ||
|
||||
categoryId === "0"
|
||||
) {
|
||||
delete params.categoryId;
|
||||
}
|
||||
return params;
|
||||
},
|
||||
getDataList(val) {
|
||||
if (val) this.form = {};
|
||||
this.loading = true;
|
||||
getArticle(this.buildArticleSearchParams())
|
||||
.then((res) => {
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
}
|
||||
function handleSubmit() {
|
||||
if (editor.value?.getContent) {
|
||||
form.value.content = editor.value.getContent();
|
||||
}
|
||||
formRef.value.validate((valid) => {
|
||||
if (valid) {
|
||||
submitLoading.value = true;
|
||||
if (modalType.value === 0) {
|
||||
delete form.value.id;
|
||||
saveArticle(form.value).then((res) => {
|
||||
submitLoading.value = false;
|
||||
if (res.success) {
|
||||
this.total = res.result.total;
|
||||
this.data = res.result.records?.length ? res.result.records : [];
|
||||
Message.success("操作成功");
|
||||
getDataList();
|
||||
modalVisible.value = false;
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
handleSubmit() {
|
||||
if (this.$refs.editor?.getContent) {
|
||||
this.form.content = this.$refs.editor.getContent();
|
||||
}
|
||||
this.$refs.form.validate((valid) => {
|
||||
if (valid) {
|
||||
this.submitLoading = true;
|
||||
if (this.modalType === 0) {
|
||||
delete this.form.id;
|
||||
saveArticle(this.form).then((res) => {
|
||||
this.submitLoading = false;
|
||||
if (res.success) {
|
||||
this.$Message.success("操作成功");
|
||||
this.getDataList();
|
||||
this.modalVisible = false;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
updateArticle(this.form).then((res) => {
|
||||
this.submitLoading = false;
|
||||
if (res.success) {
|
||||
this.$Message.success("操作成功");
|
||||
this.getDataList();
|
||||
this.modalVisible = false;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
updateArticle(form.value).then((res) => {
|
||||
submitLoading.value = false;
|
||||
if (res.success) {
|
||||
Message.success("操作成功");
|
||||
getDataList();
|
||||
modalVisible.value = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
function add() {
|
||||
modalType.value = 0;
|
||||
modalTitle.value = "添加文章";
|
||||
treeValue.value = "";
|
||||
form.value = getDefaultForm();
|
||||
modalVisible.value = true;
|
||||
nextTick(() => {
|
||||
formRef.value?.clearValidate?.();
|
||||
});
|
||||
}
|
||||
function edit(data) {
|
||||
modalType.value = 1;
|
||||
modalTitle.value = "编辑文章";
|
||||
treeValue.value = "";
|
||||
form.value = getDefaultForm();
|
||||
seeArticle(data.id).then((res) => {
|
||||
if (res.result) {
|
||||
modalVisible.value = true;
|
||||
form.value.categoryId = res.result.categoryId;
|
||||
treeValue.value = data.articleCategoryName;
|
||||
form.value.id = data.id;
|
||||
form.value.content = res.result.content;
|
||||
form.value.title = res.result.title;
|
||||
form.value.sort = res.result.sort;
|
||||
form.value.openStatus = res.result.openStatus;
|
||||
}
|
||||
});
|
||||
}
|
||||
function remove(v) {
|
||||
Modal.confirm({
|
||||
title: "确认删除",
|
||||
content: "您确认要删除么?",
|
||||
loading: true,
|
||||
onOk: () => {
|
||||
delArticle(v.id).then((res) => {
|
||||
Modal.remove();
|
||||
if (res.success) {
|
||||
Message.success("操作成功");
|
||||
getDataList();
|
||||
}
|
||||
});
|
||||
},
|
||||
add() {
|
||||
this.modalType = 0;
|
||||
this.modalTitle = "添加文章";
|
||||
this.treeValue = "";
|
||||
this.form = this.getDefaultForm();
|
||||
this.modalVisible = true;
|
||||
this.$nextTick(() => {
|
||||
this.$refs.form?.clearValidate?.();
|
||||
});
|
||||
},
|
||||
edit(data) {
|
||||
this.modalType = 1;
|
||||
this.modalTitle = "编辑文章";
|
||||
this.treeValue = "";
|
||||
this.form = this.getDefaultForm();
|
||||
seeArticle(data.id).then((res) => {
|
||||
if (res.result) {
|
||||
this.modalVisible = true;
|
||||
this.form.categoryId = res.result.categoryId;
|
||||
this.treeValue = data.articleCategoryName;
|
||||
this.form.id = data.id;
|
||||
this.form.content = res.result.content;
|
||||
this.form.title = res.result.title;
|
||||
this.form.sort = res.result.sort;
|
||||
this.form.openStatus = res.result.openStatus;
|
||||
}
|
||||
});
|
||||
},
|
||||
remove(v) {
|
||||
this.$Modal.confirm({
|
||||
title: "确认删除",
|
||||
content: "您确认要删除么?",
|
||||
loading: true,
|
||||
onOk: () => {
|
||||
delArticle(v.id).then((res) => {
|
||||
this.$Modal.remove();
|
||||
if (res.success) {
|
||||
this.$Message.success("操作成功");
|
||||
this.getDataList();
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
init();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -20,32 +20,22 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import todayHotWords from "./template/todayHotWords";
|
||||
import historyHotWords from "./template/historyHotWords";
|
||||
import setupHotWords from "./template/setupHotWords";
|
||||
import statisticsHotWords from "./template/statisticsHotWords";
|
||||
|
||||
export default {
|
||||
name: "hotWords",
|
||||
components: {
|
||||
todayHotWords,
|
||||
historyHotWords,
|
||||
setupHotWords,
|
||||
statisticsHotWords,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
templatesWay: [
|
||||
{ template: "todayHotWords", label: "今日热词" },
|
||||
{ template: "historyHotWords", label: "历史热词" },
|
||||
{ template: "statisticsHotWords", label: "热词统计" },
|
||||
{ template: "setupHotWords", label: "设置热词" },
|
||||
],
|
||||
currentTemplate: "todayHotWords",
|
||||
};
|
||||
},
|
||||
};
|
||||
defineOptions({ name: "hotWords" });
|
||||
|
||||
const templatesWay = ref([
|
||||
{ template: "todayHotWords", label: "今日热词" },
|
||||
{ template: "historyHotWords", label: "历史热词" },
|
||||
{ template: "statisticsHotWords", label: "热词统计" },
|
||||
{ template: "setupHotWords", label: "设置热词" },
|
||||
]);
|
||||
const currentTemplate = ref("todayHotWords");
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
@@ -22,81 +22,76 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import { onMounted, reactive, ref } from "vue";
|
||||
import { Chart } from "@antv/g2";
|
||||
import { getHotWordsHistory } from "@/api/index";
|
||||
import { unixToDate } from "@/utils/filters";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
params: {
|
||||
date: "",
|
||||
},
|
||||
hotWordsChart: null,
|
||||
hotWordsData: [],
|
||||
hasData: true,
|
||||
endMonth: null,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
const yesterday = new Date(Date.now() - 24 * 60 * 60 * 1000);
|
||||
this.params.date = this.$filters.unixToDate(Math.floor(yesterday.getTime() / 1000), "yyyy-MM-dd");
|
||||
},
|
||||
methods: {
|
||||
disabledDate(date) {
|
||||
if (this.endMonth) {
|
||||
const endDate = this.getDate(this.endMonth);
|
||||
return (date && date > endDate) || date > new Date();
|
||||
}
|
||||
return date && date > new Date();
|
||||
const params = reactive({
|
||||
date: "",
|
||||
});
|
||||
const hotWordsChart = ref(null);
|
||||
const hotWordsData = ref([]);
|
||||
const hasData = ref(true);
|
||||
const endMonth = ref(null);
|
||||
|
||||
const yesterday = new Date(Date.now() - 24 * 60 * 60 * 1000);
|
||||
params.date = unixToDate(Math.floor(yesterday.getTime() / 1000), "yyyy-MM-dd");
|
||||
|
||||
function disabledDate(date) {
|
||||
if (endMonth.value) {
|
||||
const endDate = getDate(endMonth.value);
|
||||
return (date && date > endDate) || date > new Date();
|
||||
}
|
||||
return date && date > new Date();
|
||||
}
|
||||
function getDate(monthStr) {
|
||||
const [year, month] = monthStr.split("-");
|
||||
return new Date(year, month, 0);
|
||||
}
|
||||
async function search(val) {
|
||||
if (val) {
|
||||
params.date = val;
|
||||
}
|
||||
const res = await getHotWordsHistory(params);
|
||||
if (res.success) {
|
||||
hotWordsData.value = res.result || [];
|
||||
hasData.value = hotWordsData.value.length > 0;
|
||||
if (hasData.value && hotWordsChart.value) {
|
||||
hotWordsChart.value.changeData(hotWordsData.value);
|
||||
hotWordsChart.value.render();
|
||||
}
|
||||
}
|
||||
}
|
||||
function init() {
|
||||
const chart = new Chart({
|
||||
container: "container",
|
||||
autoFit: true,
|
||||
height: 500,
|
||||
padding: [50, 20, 50, 20],
|
||||
});
|
||||
chart.scale("score", {
|
||||
alias: "搜索次数",
|
||||
});
|
||||
chart.axis("keywords", {
|
||||
tickLine: {
|
||||
alignTick: false,
|
||||
},
|
||||
getDate(monthStr) {
|
||||
const [year, month] = monthStr.split("-");
|
||||
return new Date(year, month, 0);
|
||||
},
|
||||
async search(val) {
|
||||
if (val) {
|
||||
this.params.date = val;
|
||||
}
|
||||
const res = await getHotWordsHistory(this.params);
|
||||
if (res.success) {
|
||||
this.hotWordsData = res.result || [];
|
||||
this.hasData = this.hotWordsData.length > 0;
|
||||
if (this.hasData && this.hotWordsChart) {
|
||||
this.hotWordsChart.changeData(this.hotWordsData);
|
||||
this.hotWordsChart.render();
|
||||
}
|
||||
}
|
||||
},
|
||||
init() {
|
||||
const chart = new Chart({
|
||||
container: "container",
|
||||
autoFit: true,
|
||||
height: 500,
|
||||
padding: [50, 20, 50, 20],
|
||||
});
|
||||
chart.scale("score", {
|
||||
alias: "搜索次数",
|
||||
});
|
||||
chart.axis("keywords", {
|
||||
tickLine: {
|
||||
alignTick: false,
|
||||
},
|
||||
});
|
||||
chart.axis("score", false);
|
||||
chart.tooltip({
|
||||
showMarkers: false,
|
||||
});
|
||||
chart.interval().position("keywords*score").color("#f59b99");
|
||||
chart.interaction("element-active");
|
||||
this.hotWordsChart = chart;
|
||||
this.search();
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
};
|
||||
});
|
||||
chart.axis("score", false);
|
||||
chart.tooltip({
|
||||
showMarkers: false,
|
||||
});
|
||||
chart.interval().position("keywords*score").color("#f59b99");
|
||||
chart.interaction("element-active");
|
||||
hotWordsChart.value = chart;
|
||||
search();
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
init();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="layout">
|
||||
<el-form
|
||||
ref="formValidate"
|
||||
ref="formRef"
|
||||
label-width="150px"
|
||||
label-position="right"
|
||||
:model="formValidate"
|
||||
@@ -49,65 +49,60 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import { setSetting, getSetting } from "@/api/index";
|
||||
import { Message } from "@/utils/message";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
ruleValidate: {},
|
||||
formValidate: {
|
||||
saveNum: 1,
|
||||
hotWordsSettingItems: [
|
||||
{
|
||||
keywords: "",
|
||||
score: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.init();
|
||||
},
|
||||
methods: {
|
||||
addSetItem() {
|
||||
if (this.formValidate.hotWordsSettingItems.length >= 5) {
|
||||
this.$Message.error("最多5个热词项");
|
||||
} else {
|
||||
this.formValidate.hotWordsSettingItems.push({
|
||||
keywords: "",
|
||||
score: 1,
|
||||
});
|
||||
}
|
||||
const formRef = ref(null);
|
||||
const ruleValidate = ref({});
|
||||
const formValidate = ref({
|
||||
saveNum: 1,
|
||||
hotWordsSettingItems: [
|
||||
{
|
||||
keywords: "",
|
||||
score: 1,
|
||||
},
|
||||
submit(name) {
|
||||
this.$refs[name].validate((valid) => {
|
||||
if (valid) {
|
||||
this.setupSetting();
|
||||
} else {
|
||||
this.$Message.error("请正确填写内容!");
|
||||
}
|
||||
});
|
||||
},
|
||||
setupSetting() {
|
||||
setSetting("HOT_WORDS", this.formValidate).then((res) => {
|
||||
if (res.success) {
|
||||
this.$Message.success("保存成功!");
|
||||
} else {
|
||||
this.$Message.error("保存失败!");
|
||||
}
|
||||
this.init();
|
||||
});
|
||||
},
|
||||
async init() {
|
||||
const res = await getSetting("HOT_WORDS");
|
||||
if (res.success && res.result) {
|
||||
this.formValidate = res.result;
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
],
|
||||
});
|
||||
|
||||
init();
|
||||
|
||||
function addSetItem() {
|
||||
if (formValidate.value.hotWordsSettingItems.length >= 5) {
|
||||
Message.error("最多5个热词项");
|
||||
} else {
|
||||
formValidate.value.hotWordsSettingItems.push({
|
||||
keywords: "",
|
||||
score: 1,
|
||||
});
|
||||
}
|
||||
}
|
||||
function submit(name) {
|
||||
formRef.value.validate((valid) => {
|
||||
if (valid) {
|
||||
setupSetting();
|
||||
} else {
|
||||
Message.error("请正确填写内容!");
|
||||
}
|
||||
});
|
||||
}
|
||||
function setupSetting() {
|
||||
setSetting("HOT_WORDS", formValidate.value).then((res) => {
|
||||
if (res.success) {
|
||||
Message.success("保存成功!");
|
||||
} else {
|
||||
Message.error("保存失败!");
|
||||
}
|
||||
init();
|
||||
});
|
||||
}
|
||||
async function init() {
|
||||
const res = await getSetting("HOT_WORDS");
|
||||
if (res.success && res.result) {
|
||||
formValidate.value = res.result;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -22,91 +22,88 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import { ref, shallowRef, watch, onMounted } from "vue";
|
||||
import { Chart } from "@antv/g2";
|
||||
import { getHotWordsStatistics } from "@/api/index";
|
||||
import affixTime from "@/components/affix-time";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
affixTime,
|
||||
const params = ref({
|
||||
searchType: "LAST_SEVEN",
|
||||
year: "",
|
||||
month: "",
|
||||
top: 50,
|
||||
});
|
||||
// G2 Chart 实例不做深度响应式(避免 Proxy 包装破坏图表内部状态)
|
||||
const hotWordsChart = shallowRef("");
|
||||
const hotWordsData = ref([]);
|
||||
const hasData = ref(true);
|
||||
|
||||
// 历史遗留:原 watch 监听的 year 从未在 data 中声明,此处补齐声明以保留监听行为
|
||||
const year = ref("");
|
||||
|
||||
watch(
|
||||
params,
|
||||
() => {
|
||||
search();
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
params: {
|
||||
searchType: "LAST_SEVEN",
|
||||
year: "",
|
||||
month: "",
|
||||
top: 50,
|
||||
{ deep: true, immediate: true }
|
||||
);
|
||||
watch(year, (val) => {
|
||||
params.value.year = new Date(val).getFullYear();
|
||||
});
|
||||
|
||||
function clickBreadcrumb(val) {
|
||||
params.value = { ...params.value, ...val };
|
||||
}
|
||||
|
||||
async function search() {
|
||||
const res = await getHotWordsStatistics(params.value);
|
||||
if (res.success) {
|
||||
hotWordsData.value = res.result || [];
|
||||
hasData.value = hotWordsData.value.length > 0;
|
||||
if (!hasData.value) {
|
||||
return;
|
||||
}
|
||||
if (!hotWordsChart.value) {
|
||||
hotWordsChart.value = new Chart({
|
||||
container: "container",
|
||||
autoFit: true,
|
||||
height: 500,
|
||||
padding: [50, 20, 50, 20],
|
||||
});
|
||||
}
|
||||
init();
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
if (hotWordsChart.value) {
|
||||
hotWordsChart.value.data(hotWordsData.value);
|
||||
hotWordsChart.value.scale("score", {
|
||||
alias: "搜索次数",
|
||||
});
|
||||
|
||||
hotWordsChart.value.axis("keywords", {
|
||||
tickLine: {
|
||||
alignTick: false,
|
||||
},
|
||||
hotWordsChart: "",
|
||||
hotWordsData: [],
|
||||
hasData: true,
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
params: {
|
||||
handler() {
|
||||
this.search();
|
||||
},
|
||||
deep: true,
|
||||
immediate: true,
|
||||
},
|
||||
year(val) {
|
||||
this.params.year = new Date(val).getFullYear();
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
clickBreadcrumb(val) {
|
||||
this.params = { ...this.params, ...val };
|
||||
},
|
||||
async search() {
|
||||
const res = await getHotWordsStatistics(this.params);
|
||||
if (res.success) {
|
||||
this.hotWordsData = res.result || [];
|
||||
this.hasData = this.hotWordsData.length > 0;
|
||||
if (!this.hasData) {
|
||||
return;
|
||||
}
|
||||
if (!this.hotWordsChart) {
|
||||
this.hotWordsChart = new Chart({
|
||||
container: "container",
|
||||
autoFit: true,
|
||||
height: 500,
|
||||
padding: [50, 20, 50, 20],
|
||||
});
|
||||
}
|
||||
this.init();
|
||||
}
|
||||
},
|
||||
init() {
|
||||
if (this.hotWordsChart) {
|
||||
this.hotWordsChart.data(this.hotWordsData);
|
||||
this.hotWordsChart.scale("score", {
|
||||
alias: "搜索次数",
|
||||
});
|
||||
});
|
||||
hotWordsChart.value.axis("score", false);
|
||||
|
||||
this.hotWordsChart.axis("keywords", {
|
||||
tickLine: {
|
||||
alignTick: false,
|
||||
},
|
||||
});
|
||||
this.hotWordsChart.axis("score", false);
|
||||
hotWordsChart.value.tooltip({
|
||||
showMarkers: false,
|
||||
});
|
||||
hotWordsChart.value.interval().position("keywords*score").color("#409EFF");
|
||||
hotWordsChart.value.interaction("element-active");
|
||||
|
||||
this.hotWordsChart.tooltip({
|
||||
showMarkers: false,
|
||||
});
|
||||
this.hotWordsChart.interval().position("keywords*score").color("#409EFF");
|
||||
this.hotWordsChart.interaction("element-active");
|
||||
hotWordsChart.value.render();
|
||||
}
|
||||
}
|
||||
|
||||
this.hotWordsChart.render();
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
};
|
||||
onMounted(() => {
|
||||
init();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
>
|
||||
<el-form ref="form" :model="form" label-width="100px" :rules="formValidate">
|
||||
<el-form ref="formRef" :model="form" label-width="100px" :rules="formValidate">
|
||||
<el-form-item label="热词" prop="keywords">
|
||||
<el-input v-model="form.keywords" clearable style="width: 100%" />
|
||||
</el-form-item>
|
||||
@@ -49,85 +49,91 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import { onMounted, reactive, ref } from "vue";
|
||||
import { getHotWords, setHotWords, deleteHotWords } from "@/api/index";
|
||||
import { regular } from "@/utils";
|
||||
import { Message, Modal } from "@/utils/message";
|
||||
import { useAppStore } from "@/stores/app";
|
||||
|
||||
export default {
|
||||
name: "todayHotWords",
|
||||
data() {
|
||||
return {
|
||||
submitLoading: false,
|
||||
modalTitle: "",
|
||||
loading: true,
|
||||
modalVisible: false,
|
||||
form: {
|
||||
keywords: "",
|
||||
point: 0,
|
||||
},
|
||||
data: [],
|
||||
formValidate: {
|
||||
keywords: [regular.REQUIRED, regular.VARCHAR20],
|
||||
point: [regular.REQUIRED, regular.NUMBER],
|
||||
},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.getDataList();
|
||||
},
|
||||
getDataList() {
|
||||
this.loading = true;
|
||||
getHotWords().then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.data = res.result;
|
||||
this.$store.state.app.hotWords = this.data;
|
||||
}
|
||||
});
|
||||
},
|
||||
handleSubmit() {
|
||||
this.$refs.form.validate((valid) => {
|
||||
if (valid) {
|
||||
this.submitLoading = true;
|
||||
setHotWords(this.form).then((res) => {
|
||||
this.submitLoading = false;
|
||||
if (res.success) {
|
||||
this.$Message.success("操作成功");
|
||||
this.getDataList();
|
||||
this.modalVisible = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
add(words) {
|
||||
this.modalTitle = "设置热词";
|
||||
this.form.keywords = words || "";
|
||||
this.form.point = 1;
|
||||
this.modalVisible = true;
|
||||
},
|
||||
deleteWords(words) {
|
||||
this.$Modal.confirm({
|
||||
title: "是否确定删除热词",
|
||||
content: "您确定要删除此热词吗?",
|
||||
okText: "确定",
|
||||
cancelText: "取消",
|
||||
onOk: () => {
|
||||
deleteHotWords({ words }).then((res) => {
|
||||
if (res.success) {
|
||||
this.$Message.success("删除成功");
|
||||
this.getDataList();
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
defineOptions({ name: "todayHotWords" });
|
||||
|
||||
const appStore = useAppStore();
|
||||
|
||||
const submitLoading = ref(false);
|
||||
const modalTitle = ref("");
|
||||
const loading = ref(true);
|
||||
const modalVisible = ref(false);
|
||||
const form = reactive({
|
||||
keywords: "",
|
||||
point: 0,
|
||||
});
|
||||
const data = ref([]);
|
||||
const formValidate = {
|
||||
keywords: [regular.REQUIRED, regular.VARCHAR20],
|
||||
point: [regular.REQUIRED, regular.NUMBER],
|
||||
};
|
||||
|
||||
const formRef = ref(null);
|
||||
|
||||
function init() {
|
||||
getDataList();
|
||||
}
|
||||
|
||||
function getDataList() {
|
||||
loading.value = true;
|
||||
getHotWords().then((res) => {
|
||||
loading.value = false;
|
||||
if (res.success) {
|
||||
data.value = res.result;
|
||||
appStore.hotWords = data.value;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function handleSubmit() {
|
||||
formRef.value.validate((valid) => {
|
||||
if (valid) {
|
||||
submitLoading.value = true;
|
||||
setHotWords(form).then((res) => {
|
||||
submitLoading.value = false;
|
||||
if (res.success) {
|
||||
Message.success("操作成功");
|
||||
getDataList();
|
||||
modalVisible.value = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function add(words) {
|
||||
modalTitle.value = "设置热词";
|
||||
form.keywords = words || "";
|
||||
form.point = 1;
|
||||
modalVisible.value = true;
|
||||
}
|
||||
|
||||
function deleteWords(words) {
|
||||
Modal.confirm({
|
||||
title: "是否确定删除热词",
|
||||
content: "您确定要删除此热词吗?",
|
||||
okText: "确定",
|
||||
cancelText: "取消",
|
||||
onOk: () => {
|
||||
deleteHotWords({ words }).then((res) => {
|
||||
if (res.success) {
|
||||
Message.success("删除成功");
|
||||
getDataList();
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
init();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -88,61 +88,61 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted } from "vue";
|
||||
import { getMemberFeedback, getMemberFeedbackDetail } from "@/api/other";
|
||||
|
||||
export default {
|
||||
name: "feedback",
|
||||
data() {
|
||||
return {
|
||||
loading: true,
|
||||
form: {},
|
||||
searchForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 20,
|
||||
sort: "createTime",
|
||||
order: "desc",
|
||||
},
|
||||
detailVisible: false,
|
||||
data: [],
|
||||
total: 0,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.getFeedback();
|
||||
},
|
||||
changePage() {
|
||||
this.getFeedback();
|
||||
},
|
||||
changePageSize() {
|
||||
this.searchForm.pageNumber = 1;
|
||||
this.getFeedback();
|
||||
},
|
||||
getFeedback() {
|
||||
this.loading = true;
|
||||
getMemberFeedback(this.searchForm).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.data = res.result.records;
|
||||
this.total = res.result.total;
|
||||
}
|
||||
});
|
||||
},
|
||||
detail(v) {
|
||||
getMemberFeedbackDetail(v.id).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.form = res.result;
|
||||
this.detailVisible = true;
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
};
|
||||
defineOptions({ name: "feedback" });
|
||||
|
||||
// 模板 el-table / el-form 的模板 ref(对应原 $refs.table / $refs.formValidate)
|
||||
const table = ref(null);
|
||||
const formValidate = ref(null);
|
||||
|
||||
const loading = ref(true);
|
||||
const form = ref({});
|
||||
const searchForm = reactive({
|
||||
pageNumber: 1,
|
||||
pageSize: 20,
|
||||
sort: "createTime",
|
||||
order: "desc",
|
||||
});
|
||||
const detailVisible = ref(false);
|
||||
const data = ref([]);
|
||||
const total = ref(0);
|
||||
|
||||
function init() {
|
||||
getFeedback();
|
||||
}
|
||||
function changePage() {
|
||||
getFeedback();
|
||||
}
|
||||
function changePageSize() {
|
||||
searchForm.pageNumber = 1;
|
||||
getFeedback();
|
||||
}
|
||||
function getFeedback() {
|
||||
loading.value = true;
|
||||
getMemberFeedback(searchForm).then((res) => {
|
||||
loading.value = false;
|
||||
if (res.success) {
|
||||
data.value = res.result.records;
|
||||
total.value = res.result.total;
|
||||
}
|
||||
});
|
||||
}
|
||||
function detail(v) {
|
||||
getMemberFeedbackDetail(v.id).then((res) => {
|
||||
loading.value = false;
|
||||
if (res.success) {
|
||||
form.value = res.result;
|
||||
detailVisible.value = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
init();
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.ops a {
|
||||
|
||||
Reference in New Issue
Block a user