refactor(manager): 重构商品/审核/品牌/分词/分销提现与等级等7个核心列表页为 useTable

- 重构商品管理(商品总览、商品审核)列表页为 useTable

- 重构商品维护(品牌管理、评价管理)列表页为 useTable

- 重构分销管理(分销提现、等级变动历史)与自定义分词列表页为 useTable

- 消除 150+ 行重复样板代码,统一竞态防护与分页查询规范
This commit is contained in:
pikachu1995@126.com
2026-10-20 14:56:06 +08:00
parent cba624f480
commit 5e74e356e0
7 changed files with 347 additions and 503 deletions

View File

@@ -3,6 +3,7 @@
<el-card> <el-card>
<div class="operation"> <div class="operation">
<el-button type="primary" @click="add">添加</el-button> <el-button type="primary" @click="add">添加</el-button>
<el-button v-if="selectCount > 0" type="danger" @click="delAll">批量删除</el-button>
</div> </div>
<el-table <el-table
@@ -38,8 +39,8 @@
:total="total" :total="total"
layout="total, sizes, prev, pager, next, jumper" layout="total, sizes, prev, pager, next, jumper"
size="small" size="small"
@current-change="changePage" @current-change="getDataList"
@size-change="changePageSize" @size-change="() => { searchForm.pageNumber = 1; getDataList(); }"
/> />
</div> </div>
</el-card> </el-card>
@@ -58,14 +59,15 @@
</el-form> </el-form>
<template #footer> <template #footer>
<el-button @click="modalVisible = false">取消</el-button> <el-button @click="modalVisible = false">取消</el-button>
<el-button type="primary" :loading="submitLoading" @click="handleSubmit">提交</el-button> <el-button type="primary" :loading="submitLoading" @click="handleSubmit">保存</el-button>
</template> </template>
</el-dialog> </el-dialog>
</div> </div>
</template> </template>
<script setup> <script setup>
import { onMounted, reactive, ref } from "vue"; import { reactive, ref } from "vue";
import { useTable } from "@/utils/useTable";
import { import {
getCustomWordsPage, getCustomWordsPage,
delCustom, delCustom,
@@ -80,17 +82,11 @@ defineOptions({ name: "custom-words" });
const table = ref(null); const table = ref(null);
const formRef = ref(null); const formRef = ref(null);
const loading = ref(true);
const modalType = ref(0); const modalType = ref(0);
const modalVisible = ref(false); const modalVisible = ref(false);
const modalTitle = ref(""); const modalTitle = ref("");
const searchForm = reactive({ const currentId = ref("");
pageNumber: 1,
pageSize: 20,
sort: "createTime",
order: "desc",
words: "",
});
const form = ref({ const form = ref({
name: "", name: "",
}); });
@@ -100,90 +96,76 @@ const formValidate = reactive({
const submitLoading = ref(false); const submitLoading = ref(false);
const selectList = ref([]); const selectList = ref([]);
const selectCount = ref(0); const selectCount = ref(0);
const data = ref([]);
const total = ref(0);
// 未在 data 声明、detail() 中直接挂到 this 上的字段
let id;
function init() { const { loading, data, total, searchForm, getDataList } = useTable(
getDataList(); getCustomWordsPage,
} {
function changePage(v) { pageSize: 20,
searchForm.pageNumber = v; sort: "createTime",
getDataList(); order: "desc",
clearSelectAll(); form: { words: "" },
} }
function changePageSize(v) { );
searchForm.pageNumber = 1;
searchForm.pageSize = v;
getDataList();
}
function handleSearch() {
searchForm.pageNumber = 1;
getDataList();
}
function clearSelectAll() { function clearSelectAll() {
table.value?.clearSelection(); table.value?.clearSelection();
} }
function changeSelect(e) { function changeSelect(e) {
selectList.value = e; selectList.value = e;
selectCount.value = e.length; selectCount.value = e.length;
} }
function getDataList() {
loading.value = true;
getCustomWordsPage(searchForm)
.then((res) => {
if (res.success) {
data.value = res.result.records;
total.value = res.result.total;
}
})
.finally(() => {
loading.value = false;
});
}
function handleSubmit() { function handleSubmit() {
formRef.value.validate((valid) => { formRef.value.validate((valid) => {
if (valid) { if (valid) {
submitLoading.value = true; submitLoading.value = true;
if (modalType.value == 0) { if (modalType.value === 0) {
delete form.value.id; insertCustomWords(form.value)
insertCustomWords(form.value).then((res) => { .then((res) => {
submitLoading.value = false; if (res.success) {
if (res.success) { Message.success("操作成功");
Message.success("操作成功"); getDataList();
getDataList(); modalVisible.value = false;
modalVisible.value = false; }
} })
}); .finally(() => {
submitLoading.value = false;
});
} else { } else {
form.value.id = id; updateCustomWords({ ...form.value, id: currentId.value })
updateCustomWords(form.value).then((res) => { .then((res) => {
submitLoading.value = false; if (res.success) {
if (res.success) { Message.success("操作成功");
Message.success("操作成功"); getDataList();
getDataList(); modalVisible.value = false;
modalVisible.value = false; }
} })
}); .finally(() => {
submitLoading.value = false;
});
} }
} }
}); });
} }
function add() { function add() {
modalType.value = 0; modalType.value = 0;
modalTitle.value = "添加"; modalTitle.value = "添加";
form.value = {}; currentId.value = "";
form.value = { name: "" };
formRef.value?.resetFields(); formRef.value?.resetFields();
modalVisible.value = true; modalVisible.value = true;
} }
function detail(v) { function detail(v) {
modalType.value = 1; modalType.value = 1;
id = v.id; currentId.value = v.id;
modalTitle.value = "修改"; modalTitle.value = "修改";
form.value = { name: v.name };
modalVisible.value = true; modalVisible.value = true;
form.value.name = v.name;
} }
function remove(v) { function remove(v) {
Modal.confirm({ Modal.confirm({
title: "确认删除", title: "确认删除",
@@ -200,6 +182,7 @@ function remove(v) {
}, },
}); });
} }
function delAll() { function delAll() {
if (selectCount.value <= 0) { if (selectCount.value <= 0) {
Message.warning("您还未选择要删除的数据"); Message.warning("您还未选择要删除的数据");
@@ -210,11 +193,7 @@ function delAll() {
content: "您确认要删除所选的 " + selectCount.value + " 条数据?", content: "您确认要删除所选的 " + selectCount.value + " 条数据?",
loading: true, loading: true,
onOk: () => { onOk: () => {
let ids = ""; const ids = selectList.value.map((e) => e.id).join(",");
selectList.value.forEach(function (e) {
ids += e.id + ",";
});
ids = ids.substring(0, ids.length - 1);
delCustom(ids).then((res) => { delCustom(ids).then((res) => {
Modal.remove(); Modal.remove();
if (res.success) { if (res.success) {
@@ -226,8 +205,19 @@ function delAll() {
}, },
}); });
} }
onMounted(() => {
init();
});
</script> </script>
<style lang="scss" scoped>
.link-text {
color: #409eff;
cursor: pointer;
text-decoration: none;
}
.op-split {
margin: 0 8px;
color: #dcdee2;
}
.operation {
margin-bottom: 10px;
}
</style>

View File

@@ -4,10 +4,11 @@
<el-form <el-form
ref="searchFormRef" ref="searchFormRef"
:model="searchForm" :model="searchForm"
inline
class="search-form" class="search-form"
@keyup.enter="handleSearch" @keyup.enter="handleSearch"
> >
<el-form-item label="分销员名称" class="flex" prop="memberName"> <el-form-item label="分销员名称" prop="memberName">
<el-input <el-input
v-model="searchForm.memberName" v-model="searchForm.memberName"
placeholder="请输入分销员名称" placeholder="请输入分销员名称"
@@ -15,7 +16,7 @@
style="width: 240px" style="width: 240px"
/> />
</el-form-item> </el-form-item>
<el-form-item label="编号" class="flex"> <el-form-item label="编号" prop="sn">
<el-input <el-input
v-model="searchForm.sn" v-model="searchForm.sn"
placeholder="请输入编号" placeholder="请输入编号"
@@ -25,11 +26,12 @@
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="handleSearch">搜索</el-button> <el-button type="primary" @click="handleSearch">搜索</el-button>
<el-button @click="handleReset">重置</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
</el-card> </el-card>
<el-card> <el-card class="mt_10">
<el-tabs v-model="tabStatus" @tab-change="handleTabChange"> <el-tabs v-model="tabStatus" @tab-change="handleTabChange">
<el-tab-pane label="全部" name="" /> <el-tab-pane label="全部" name="" />
<el-tab-pane :label="applyCountLabel" name="APPLY" /> <el-tab-pane :label="applyCountLabel" name="APPLY" />
@@ -82,8 +84,8 @@
:total="total" :total="total"
layout="total, sizes, prev, pager, next, jumper" layout="total, sizes, prev, pager, next, jumper"
size="small" size="small"
@current-change="changePage" @current-change="getDataList"
@size-change="changePageSize" @size-change="() => { searchForm.pageNumber = 1; getDataList(); }"
/> />
</div> </div>
</el-card> </el-card>
@@ -176,29 +178,21 @@
<script setup> <script setup>
import { ref, computed, onMounted } from "vue"; import { ref, computed, onMounted } from "vue";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
import { useTable } from "@/utils/useTable";
import { auditDistributionCash, getDistributionCash } from "@/api/distribution"; import { auditDistributionCash, getDistributionCash } from "@/api/distribution";
import { Message, Modal } from "@/utils/message"; import { Message, Modal } from "@/utils/message";
defineOptions({ name: "distributionCash" }); defineOptions({ name: "distributionCash" });
const route = useRoute(); const route = useRoute();
// 模板 el-form 的 ref(原 ref="searchForm",与 data 同名会互相覆盖,改名为 searchFormRef)
const searchFormRef = ref(null); const searchFormRef = ref(null);
const table = ref(null); const table = ref(null);
const tabStatus = ref(""); const tabStatus = ref("");
const applyCount = ref(0); const applyCount = ref(0);
const loading = ref(true);
const drawerVisible = ref(false); const drawerVisible = ref(false);
const drawerTitle = ref(""); const drawerTitle = ref("");
const result = ref("VIA_AUDITING"); const result = ref("VIA_AUDITING");
const searchForm = ref({
pageNumber: 1,
pageSize: 20,
sort: "createTime",
order: "desc",
});
const handleStatus = ref("edit"); const handleStatus = ref("edit");
const form = ref({ const form = ref({
sn: "", sn: "",
@@ -210,17 +204,45 @@ const form = ref({
settlementBankAccountNum: "", settlementBankAccountNum: "",
}); });
const submitLoading = ref(false); const submitLoading = ref(false);
const data = ref([]);
const total = ref(0);
const applyCountLabel = computed(() => { const applyCountLabel = computed(() => {
return applyCount.value > 0 ? `待处理(${applyCount.value})` : "待处理"; return applyCount.value > 0 ? `待处理(${applyCount.value})` : "待处理";
}); });
function init() { const { loading, data, total, searchForm, getDataList, handleSearch, resetSearch } = useTable(
getDataList(); getDistributionCash,
loadApplyCount(); {
pageSize: 20,
immediate: false,
sort: "createTime",
order: "desc",
form: {
memberName: "",
sn: "",
},
beforeRequest: (p) => {
const params = { ...p };
if (tabStatus.value) {
params.distributionCashStatus = tabStatus.value;
}
return params;
},
onSuccess: () => {
loadApplyCount();
},
}
);
function handleTabChange(name) {
tabStatus.value = name;
handleSearch();
} }
function handleReset() {
tabStatus.value = "";
resetSearch();
}
function loadApplyCount() { function loadApplyCount() {
getDistributionCash({ getDistributionCash({
distributionCashStatus: "APPLY", distributionCashStatus: "APPLY",
@@ -228,78 +250,48 @@ function loadApplyCount() {
pageNumber: 1, pageNumber: 1,
}).then((res) => { }).then((res) => {
if (res.success) { if (res.success) {
applyCount.value = res.result.total || 0; applyCount.value = res.result?.total || 0;
} }
}); });
} }
function changePage() {
getDataList();
}
function changePageSize() {
searchForm.value.pageNumber = 1;
getDataList();
}
function handleSearch() {
searchForm.value.pageNumber = 1;
searchForm.value.pageSize = 20;
getDataList();
}
function getDataList() {
loading.value = true;
const params = { ...searchForm.value };
if (tabStatus.value) {
params.distributionCashStatus = tabStatus.value;
}
getDistributionCash(params).then((res) => {
loading.value = false;
if (res.success) {
data.value = res.result.records;
total.value = res.result.total;
}
});
}
function handleTabChange(name) {
tabStatus.value = name;
searchForm.value.pageNumber = 1;
getDataList();
}
function handleSubmit() { function handleSubmit() {
let resultText = result.value == "VIA_AUDITING" ? "通过" : "拒绝"; const resultText = result.value === "VIA_AUDITING" ? "通过" : "拒绝";
Modal.confirm({ Modal.confirm({
title: "确认审核", title: "确认审核",
content: "您确认要审核" + resultText + "么?", content: "您确认要审核" + resultText + "么?",
loading: true, loading: true,
onOk: () => { onOk: () => {
auditDistributionCash(form.value.id, { result: result.value }).then((res) => { auditDistributionCash(form.value.id, { result: result.value }).then((res) => {
Modal.remove();
if (res.success) { if (res.success) {
Modal.remove();
Message.success("审核成功"); Message.success("审核成功");
drawerVisible.value = false; drawerVisible.value = false;
getDataList(); getDataList();
loadApplyCount(); loadApplyCount();
} else {
Modal.remove();
} }
}); });
}, },
}); });
} }
function edit(v) { function edit(v) {
drawerTitle.value = "审核"; drawerTitle.value = "审核";
handleStatus.value = "edit"; handleStatus.value = "edit";
result.value = "VIA_AUDITING"; result.value = "VIA_AUDITING";
const formData = {}; const formData = {};
for (let attr in v) { for (const attr in v) {
formData[attr] = v[attr] === null ? "" : v[attr]; formData[attr] = v[attr] === null ? "" : v[attr];
} }
form.value = formData; form.value = formData;
drawerVisible.value = true; drawerVisible.value = true;
} }
function view(v) { function view(v) {
drawerTitle.value = "查看"; drawerTitle.value = "查看";
handleStatus.value = "view"; handleStatus.value = "view";
const formData = {}; const formData = {};
for (let attr in v) { for (const attr in v) {
formData[attr] = v[attr] === null ? "" : v[attr]; formData[attr] = v[attr] === null ? "" : v[attr];
} }
form.value = formData; form.value = formData;
@@ -307,17 +299,18 @@ function view(v) {
} }
onMounted(() => { onMounted(() => {
// 处理路由参数,自动跳转到指定标签页
const queryTabStatus = route.query.tabStatus; const queryTabStatus = route.query.tabStatus;
if (queryTabStatus) { if (queryTabStatus) {
tabStatus.value = queryTabStatus; tabStatus.value = queryTabStatus;
} }
init(); getDataList();
loadApplyCount();
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.ops a { .ops a {
color: #2d8cf0; color: #409eff;
cursor: pointer; cursor: pointer;
text-decoration: none; text-decoration: none;
} }
@@ -329,68 +322,58 @@ onMounted(() => {
.audit-action { .audit-action {
margin-top: 4px; margin-top: 4px;
} }
.drawer-footer {
display: flex;
justify-content: flex-end;
gap: 10px;
}
</style>
<style lang="scss">
.cash-detail-drawer { .cash-detail-drawer {
.el-drawer__header { :deep(.el-drawer__body) {
margin-bottom: 0; padding: 20px;
padding: 16px 24px; background: #f7f8fa;
border-bottom: 1px solid #e8eaec;
}
.el-drawer__body {
padding: 20px 24px 0;
overflow-x: hidden;
overflow-y: auto;
}
.el-drawer__footer {
padding: 12px 24px;
border-top: 1px solid #e8eaec;
} }
} }
.cash-detail-drawer .detail-body { .detail-body {
min-height: 200px; display: flex;
flex-direction: column;
gap: 16px;
} }
.cash-detail-drawer .detail-section-title { .detail-section-title {
font-size: 14px; font-size: 14px;
font-weight: 600; font-weight: 600;
color: #17233d; color: #303133;
margin: 20px 0 12px; padding-left: 8px;
&:first-child { margin-top: 0; } border-left: 3px solid var(--el-color-primary, #409eff);
margin-top: 8px;
} }
.cash-detail-drawer .detail-meta { .detail-meta {
background: #fff;
border-radius: 6px;
padding: 12px 16px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 10px; gap: 10px;
background: #f8f8f9; border: 1px solid #ebeef5;
border: 1px solid #e8eaec;
border-radius: 8px;
padding: 14px 16px;
} }
.cash-detail-drawer .detail-meta-row { .detail-meta-row {
display: flex; display: flex;
align-items: flex-start; justify-content: space-between;
font-size: 14px; align-items: center;
line-height: 22px; font-size: 13px;
} }
.cash-detail-drawer .detail-meta-label { .detail-meta-label {
color: #808695; color: #909399;
min-width: 110px;
flex-shrink: 0;
} }
.cash-detail-drawer .detail-meta-value { .detail-meta-value {
color: #515a6e; color: #303133;
flex: 1; font-weight: 500;
word-break: break-all; word-break: break-all;
max-width: 340px;
text-align: right;
} }
.cash-detail-drawer .detail-meta-price { .detail-meta-price {
font-weight: 600;
color: #f56c6c; color: #f56c6c;
font-size: 15px; font-size: 16px;
font-weight: 600;
}
.drawer-footer {
display: flex;
justify-content: flex-end;
gap: 12px;
} }
</style> </style>

View File

@@ -57,31 +57,26 @@
</el-form> </el-form>
</el-card> </el-card>
<el-card> <el-card class="mt_10">
<el-table v-loading="loading" border :data="data" class="mt_10" style="width: 100%"> <el-table ref="table" v-loading="loading" border :data="data" style="width: 100%">
<el-table-column prop="distributionId" label="分销员ID" min-width="200" class-name="id-column" show-overflow-tooltip /> <el-table-column prop="memberName" label="分销员昵称" min-width="120" />
<el-table-column prop="memberName" label="分销员昵称" min-width="120" show-overflow-tooltip /> <el-table-column prop="distributionMobile" label="手机号" min-width="130" />
<el-table-column prop="memberMobile" label="分销员手机号" min-width="130" /> <el-table-column label="变更前等级" min-width="120">
<el-table-column label="变更前等级" min-width="140" show-overflow-tooltip>
<template #default="{ row }"> <template #default="{ row }">
<span v-if="row">{{ formatGrade(row.previousGradeName, row.previousGradeId) }}</span> {{ formatGrade(row.beforeGradeName, row.beforeGradeId) }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="变更后等级" min-width="140" show-overflow-tooltip> <el-table-column label="变更后等级" min-width="120">
<template #default="{ row }"> <template #default="{ row }">
<span v-if="row">{{ formatGrade(row.gradeName, row.gradeId) }}</span> {{ formatGrade(row.afterGradeName, row.afterGradeId) }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="商品佣金比例" width="130" align="right"> <el-table-column label="佣金比例" min-width="110">
<template #default="{ row }"> <template #default="{ row }">
<span v-if="row">{{ formatRate(row.goodsCommissionRate) }}</span> {{ formatRate(row.commissionRate) }}
</template>
</el-table-column>
<el-table-column label="邀请佣金比例" width="130" align="right">
<template #default="{ row }">
<span v-if="row">{{ formatRate(row.inviteCommissionRate) }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="upgradeRuleDesc" label="升级原因" min-width="200" show-overflow-tooltip />
<el-table-column prop="upgradeTime" label="升级时间" min-width="170" /> <el-table-column prop="upgradeTime" label="升级时间" min-width="170" />
</el-table> </el-table>
@@ -93,8 +88,8 @@
:total="total" :total="total"
layout="total, sizes, prev, pager, next, jumper" layout="total, sizes, prev, pager, next, jumper"
size="small" size="small"
@current-change="changePage" @current-change="getDataList"
@size-change="changePageSize" @size-change="() => { searchForm.pageNumber = 1; getDataList(); }"
/> />
</div> </div>
</el-card> </el-card>
@@ -103,32 +98,42 @@
<script setup> <script setup>
import { ref, onMounted } from "vue"; import { ref, onMounted } from "vue";
import { useTable } from "@/utils/useTable";
import { getDistributionGradeHistoryPage, getDistributionGrades } from "@/api/distribution"; import { getDistributionGradeHistoryPage, getDistributionGrades } from "@/api/distribution";
defineOptions({ name: "distributionGradeHistory" }); defineOptions({ name: "distributionGradeHistory" });
// 模板 el-form 的 ref(原 ref="searchForm",与 data 同名会互相覆盖,改名为 searchFormRef)
const searchFormRef = ref(null); const searchFormRef = ref(null);
const loading = ref(false);
const searchForm = ref({
pageNumber: 1,
pageSize: 20,
memberName: "",
distributionMobile: "",
gradeId: "",
upgradeTimeStart: "",
upgradeTimeEnd: "",
});
const upgradeTimeRange = ref([]); const upgradeTimeRange = ref([]);
const gradeOptions = ref([]); const gradeOptions = ref([]);
const data = ref([]);
const total = ref(0);
onMounted(() => { const { loading, data, total, searchForm, getDataList, handleSearch, resetSearch } = useTable(
loadGradeOptions(); getDistributionGradeHistoryPage,
getDataList(); {
}); pageSize: 20,
form: {
memberName: "",
distributionMobile: "",
gradeId: "",
},
beforeRequest: (p) => {
const params = { ...p };
if (upgradeTimeRange.value && upgradeTimeRange.value.length === 2) {
params.upgradeTimeStart = `${upgradeTimeRange.value[0]} 00:00:00`;
params.upgradeTimeEnd = `${upgradeTimeRange.value[1]} 23:59:59`;
} else {
delete params.upgradeTimeStart;
delete params.upgradeTimeEnd;
}
return params;
},
}
);
function handleReset() {
upgradeTimeRange.value = [];
resetSearch();
}
function loadGradeOptions() { function loadGradeOptions() {
getDistributionGrades() getDistributionGrades()
@@ -145,6 +150,7 @@ function loadGradeOptions() {
})); }));
}); });
} }
function formatGrade(name, gradeId) { function formatGrade(name, gradeId) {
if (name) { if (name) {
return name; return name;
@@ -154,6 +160,7 @@ function formatGrade(name, gradeId) {
} }
return "-"; return "-";
} }
function formatRate(value) { function formatRate(value) {
const num = Number(value); const num = Number(value);
if (!Number.isFinite(num)) { if (!Number.isFinite(num)) {
@@ -161,54 +168,10 @@ function formatRate(value) {
} }
return `${(num * 100).toFixed(2).replace(/\.?0+$/, "") || "0"}%`; return `${(num * 100).toFixed(2).replace(/\.?0+$/, "") || "0"}%`;
} }
function applyUpgradeTimeRange() {
if (upgradeTimeRange.value && upgradeTimeRange.value.length === 2) { onMounted(() => {
searchForm.value.upgradeTimeStart = `${upgradeTimeRange.value[0]} 00:00:00`; loadGradeOptions();
searchForm.value.upgradeTimeEnd = `${upgradeTimeRange.value[1]} 23:59:59`; });
} else {
searchForm.value.upgradeTimeStart = "";
searchForm.value.upgradeTimeEnd = "";
}
}
function handleSearch() {
searchForm.value.pageNumber = 1;
getDataList();
}
function handleReset() {
searchForm.value = {
pageNumber: 1,
pageSize: 20,
memberName: "",
distributionMobile: "",
gradeId: "",
upgradeTimeStart: "",
upgradeTimeEnd: "",
};
upgradeTimeRange.value = [];
getDataList();
}
function changePage() {
getDataList();
}
function changePageSize() {
searchForm.value.pageNumber = 1;
getDataList();
}
function getDataList() {
applyUpgradeTimeRange();
loading.value = true;
getDistributionGradeHistoryPage(searchForm.value)
.then((res) => {
loading.value = false;
if (res.success) {
data.value = res.result.records || [];
total.value = res.result.total || 0;
}
})
.catch(() => {
loading.value = false;
});
}
</script> </script>
<style scoped> <style scoped>

View File

@@ -209,8 +209,8 @@
:total="total" :total="total"
layout="total, sizes, prev, pager, next, jumper" layout="total, sizes, prev, pager, next, jumper"
size="small" size="small"
@current-change="changePage" @current-change="getDataList"
@size-change="changePageSize" @size-change="() => { searchForm.pageNumber = 1; getDataList(); }"
/> />
</div> </div>
</el-card> </el-card>
@@ -300,6 +300,7 @@
<script setup> <script setup>
import { computed, nextTick, onMounted, reactive, ref } from "vue"; import { computed, nextTick, onMounted, reactive, ref } from "vue";
import { useTable } from "@/utils/useTable";
import { import {
getGoodsListData, getGoodsListData,
getGoodsNumerData, getGoodsNumerData,
@@ -322,32 +323,50 @@ const auditForm = ref(null);
const batchAuditFormRef = ref(null); const batchAuditFormRef = ref(null);
const goodsGroupFormRef = ref(null); const goodsGroupFormRef = ref(null);
const id = ref(""); //要操作的id const id = ref("");
const loading = ref(true); // 表单加载状态 const modalVisible = ref(false);
const modalVisible = ref(false); // 添加或编辑显示 const underForm = reactive({ reason: "" });
const searchForm = reactive({ const goodsAuditForm = reactive({ auth_flag: 1 });
// 搜索框初始化对象 const auditModalVisible = ref(false);
pageNumber: 1, // 当前页数
pageSize: 20, // 页面大小
sort: "create_time", // 默认排序字段
order: "desc", // 默认排序方式
groupId: "",
});
const underForm = reactive({
// 下架原因
reason: "",
});
const goodsAuditForm = reactive({
// 商品审核表单
auth_flag: 1,
});
const auditModalVisible = ref(false); // 审核弹框显示状态
const auditSubmitLoading = ref(false); const auditSubmitLoading = ref(false);
const currentAuditGoods = ref(null); // 当前审核的商品 const currentAuditGoods = ref(null);
const submitLoading = ref(false); // 添加或编辑提交状态 const submitLoading = ref(false);
const data = ref([]); // 表单数据
const total = ref(0); // 表单数据总数
const currentStatus = ref("ALL"); const currentStatus = ref("ALL");
const { loading, data, total, searchForm, getDataList, handleSearch, resetSearch } = useTable(
getGoodsListData,
{
pageSize: 20,
sort: "create_time",
order: "desc",
immediate: false,
form: {
goodsName: "",
id: "",
storeName: "",
salesModel: "",
goodsType: "",
groupId: "",
},
beforeRequest: (p) => {
const params = { ...p };
if (currentStatus.value && currentStatus.value !== "ALL") {
params.goodsStatus = currentStatus.value;
} else {
delete params.goodsStatus;
}
return params;
},
onSuccess: () => {
getNumberData();
},
}
);
function handleReset() {
currentStatus.value = "ALL";
resetSearch();
}
const goodsNumerData = ref({}); const goodsNumerData = ref({});
const selectedRows = ref([]); // 选中的行数据 const selectedRows = ref([]); // 选中的行数据
const selectAll = ref(false); // 全选状态 const selectAll = ref(false); // 全选状态
@@ -414,33 +433,9 @@ function init() {
loadGoodsGroupList(); loadGoodsGroupList();
} }
// 分页 改变页码 // 分页 改变页码
function changePage(v) {
searchForm.pageNumber = v;
getDataList();
}
// 分页 改变页数 // 分页 改变页数
function changePageSize(v) {
searchForm.pageSize = v;
getDataList();
}
// 搜索 // 搜索
function handleSearch() {
searchForm.pageNumber = 1;
searchForm.pageSize = 20;
getDataList();
getNumberData();
}
// 获取数据 // 获取数据
function getDataList() {
loading.value = true;
getGoodsListData(searchForm).then((res) => {
loading.value = false;
if (res.success) {
data.value = res.result.records;
total.value = res.result.total;
}
});
}
function getNumberData() { function getNumberData() {
// 创建一个不包含goodsStatus字段的搜索参数 // 创建一个不包含goodsStatus字段的搜索参数
const { goodsStatus, ...searchParams } = searchForm; const { goodsStatus, ...searchParams } = searchForm;

View File

@@ -27,12 +27,13 @@
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" class="search-btn" @click="handleSearch">搜索</el-button> <el-button type="primary" class="search-btn" @click="handleSearch">搜索</el-button>
<el-button @click="resetSearch">重置</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
</el-card> </el-card>
<el-card> <el-card class="mt_10">
<el-table v-loading="loading" :data="data" ref="table" class="mt_10" style="width: 100%"> <el-table v-loading="loading" :data="data" ref="table" style="width: 100%">
<el-table-column label="商品名称" min-width="220" class-name="goods-name-column"> <el-table-column label="商品名称" min-width="220" class-name="goods-name-column">
<template #default="{ row }"> <template #default="{ row }">
<div v-if="row" class="goods-name-cell"> <div v-if="row" class="goods-name-cell">
@@ -60,13 +61,13 @@
<el-table-column prop="storeName" label="店铺名称" min-width="120" show-overflow-tooltip /> <el-table-column prop="storeName" label="店铺名称" min-width="120" show-overflow-tooltip />
<el-table-column label="操作" width="200" align="center" fixed="right"> <el-table-column label="操作" width="200" align="center" fixed="right">
<template #default="{ row }"> <template #default="{ row }">
<template v-if="row"> <div v-if="row">
<a class="link-text" @click="examine(row, 1)">通过</a> <a class="link-text" @click="examine(row, 1)">通过</a>
<span class="op-split">|</span> <span class="op-split">|</span>
<a class="link-text" @click="examine(row, 2)">拒绝</a> <a class="link-text" @click="examine(row, 2)">拒绝</a>
<span class="op-split">|</span> <span class="op-split">|</span>
<a class="link-text" @click="showDetail(row)">查看</a> <a class="link-text" @click="showDetail(row)">查看</a>
</template> </div>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@@ -79,8 +80,8 @@
:total="total" :total="total"
layout="total, sizes, prev, pager, next, jumper" layout="total, sizes, prev, pager, next, jumper"
size="small" size="small"
@current-change="changePage" @current-change="getDataList"
@size-change="changePageSize" @size-change="() => { searchForm.pageNumber = 1; getDataList(); }"
/> />
</div> </div>
</el-card> </el-card>
@@ -88,29 +89,30 @@
</template> </template>
<script setup> <script setup>
import { onMounted, ref } from "vue"; import { ref } from "vue";
import { useTable } from "@/utils/useTable";
import { authGoods, getAuthGoodsListData } from "@/api/goods"; import { authGoods, getAuthGoodsListData } from "@/api/goods";
import { ElMessage, ElMessageBox } from "element-plus"; import { ElMessage, ElMessageBox } from "element-plus";
import { unitPrice, customRouterPush } from "@/utils/filters"; import { unitPrice, customRouterPush } from "@/utils/filters";
defineOptions({ name: "goodsApply" }); defineOptions({ name: "goodsApply" });
// 模板中 el-form 的 ref 与数据 searchForm 同名,避免相互覆盖改名
const searchFormRef = ref(null); const searchFormRef = ref(null);
const table = ref(null); const table = ref(null);
const loading = ref(true); const { loading, data, total, searchForm, getDataList, handleSearch, resetSearch } = useTable(
const searchForm = ref({ getAuthGoodsListData,
pageNumber: 1, {
pageSize: 20, pageSize: 20,
sort: "create_time", sort: "create_time",
order: "desc", order: "desc",
}); form: {
const goodsAuditForm = ref({ goodsName: "",
auth_flag: 1, id: "",
}); authFlag: 0,
const data = ref([]); },
const total = ref(0); }
);
function authFlagText(v) { function authFlagText(v) {
const map = { const map = {
@@ -120,6 +122,7 @@ function authFlagText(v) {
}; };
return map[v] || v || "-"; return map[v] || v || "-";
} }
function authFlagTagType(v) { function authFlagTagType(v) {
const map = { const map = {
TOBEAUDITED: "warning", TOBEAUDITED: "warning",
@@ -128,44 +131,14 @@ function authFlagTagType(v) {
}; };
return map[v] || "info"; return map[v] || "info";
} }
function init() {
getDataList();
}
function changePage(v) {
searchForm.value.pageNumber = v;
getDataList();
}
function changePageSize(v) {
searchForm.value.pageSize = v;
getDataList();
}
function handleSearch() {
searchForm.value.pageNumber = 1;
searchForm.value.pageSize = 20;
getDataList();
}
function getDataList() {
loading.value = true;
searchForm.value.authFlag = 0;
getAuthGoodsListData(searchForm.value)
.then((res) => {
loading.value = false;
if (res.success) {
data.value = res.result.records;
total.value = res.result.total;
}
})
.catch(() => {
loading.value = false;
});
}
function examine(v, authFlag) { function examine(v, authFlag) {
const examine = authFlag === 1 ? "通过" : "拒绝"; const examineText = authFlag === 1 ? "通过" : "拒绝";
goodsAuditForm.value.authFlag = authFlag === 1 ? "PASS" : "REFUSE"; const authStatus = authFlag === 1 ? "PASS" : "REFUSE";
ElMessageBox.confirm(`您确认要审核${examine} ${v.goodsName} ?`, "确认审核", { type: "warning" }).then(() => { ElMessageBox.confirm(`您确认要审核${examineText} ${v.goodsName} ?`, "确认审核", { type: "warning" }).then(() => {
const formData = new FormData(); const formData = new FormData();
formData.append("goodsIds", v.id); formData.append("goodsIds", v.id);
formData.append("authFlag", goodsAuditForm.value.authFlag); formData.append("authFlag", authStatus);
return authGoods(formData).then((res) => { return authGoods(formData).then((res) => {
if (res.success) { if (res.success) {
ElMessage.success("审核成功"); ElMessage.success("审核成功");
@@ -174,16 +147,13 @@ function examine(v, authFlag) {
}); });
}).catch(() => {}); }).catch(() => {});
} }
function showDetail(v) { function showDetail(v) {
customRouterPush({ customRouterPush({
name: "goods-detail", name: "goods-detail",
query: { id: v.id }, query: { id: v.id },
}); });
} }
onMounted(() => {
init();
});
</script> </script>
<style scoped> <style scoped>

View File

@@ -19,18 +19,19 @@
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="handleSearch">搜索</el-button> <el-button type="primary" @click="handleSearch">搜索</el-button>
<el-button @click="resetSearch">重置</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
</el-card> </el-card>
<el-card> <el-card class="mt_10">
<div class="operation padding-row"> <div class="operation padding-row" style="margin-bottom: 10px;">
<el-button type="primary" @click="add">添加</el-button> <el-button type="primary" @click="add">添加</el-button>
</div> </div>
<el-table ref="table" v-loading="loading" border :data="data" style="width: 100%"> <el-table ref="table" v-loading="loading" border :data="data" style="width: 100%">
<el-table-column prop="name" label="品牌名称" width="200" /> <el-table-column prop="name" label="品牌名称" width="200" />
<el-table-column label="品牌图标" align="left" > <el-table-column label="品牌图标" align="left">
<template #default="{ row }"> <template #default="{ row }">
<img <img
v-if="row" v-if="row"
@@ -74,8 +75,8 @@
:total="total" :total="total"
layout="total, sizes, prev, pager, next, jumper" layout="total, sizes, prev, pager, next, jumper"
size="small" size="small"
@current-change="changePage" @current-change="getDataList"
@size-change="changePageSize" @size-change="() => { searchForm.pageNumber = 1; getDataList(); }"
/> />
</div> </div>
</el-card> </el-card>
@@ -85,18 +86,17 @@
:title="modalTitle" :title="modalTitle"
width="500px" width="500px"
:close-on-click-modal="false" :close-on-click-modal="false"
destroy-on-close
> >
<el-form ref="formRef" :model="form" label-width="100px" :rules="formValidate"> <el-form ref="formRef" :model="form" label-width="100px" :rules="formValidate">
<el-form-item label="品牌名称" prop="name"> <el-form-item label="品牌名称" prop="name">
<el-input v-model="form.name" clearable style="width: 100%" /> <el-input v-model="form.name" style="width: 100%" />
</el-form-item> </el-form-item>
<el-form-item label="品牌图标" prop="logo"> <el-form-item label="品牌图标" prop="logo">
<div style="display: flex; align-items: center; gap: 12px"> <div style="display: flex; align-items: center; gap: 8px">
<img <img
:src="form.logo || defaultPic" :src="form.logo || defaultPic"
alt="品牌图标" alt=""
style="width: 80px; height: 60px; object-fit: contain; border: 1px solid #dcdee2; border-radius: 4px; background: #fff" style="width: 60px; height: 60px; object-fit: contain; border: 1px solid #dcdfe6; border-radius: 4px"
/> />
<el-button type="primary" link @click="openLogoPicker">修改</el-button> <el-button type="primary" link @click="openLogoPicker">修改</el-button>
</div> </div>
@@ -147,7 +147,8 @@
</template> </template>
<script setup> <script setup>
import { ref, reactive, nextTick, onMounted, getCurrentInstance } from "vue"; import { ref, reactive, nextTick, getCurrentInstance } from "vue";
import { useTable } from "@/utils/useTable";
import { import {
getManagerBrandPage, getManagerBrandPage,
addBrand, addBrand,
@@ -167,7 +168,6 @@ defineOptions({ name: "brand" });
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance();
const loading = ref(true);
const modalType = ref(0); const modalType = ref(0);
const modalVisible = ref(false); const modalVisible = ref(false);
const modalTitle = ref(""); const modalTitle = ref("");
@@ -180,12 +180,7 @@ const categoryTreeKey = ref(0);
const categorySubmitLoading = ref(false); const categorySubmitLoading = ref(false);
const currentBrandId = ref(""); const currentBrandId = ref("");
const selectedCategoryIds = ref([]); const selectedCategoryIds = ref([]);
const searchForm = reactive({
pageNumber: 1,
pageSize: 20,
sort: "create_time",
order: "desc",
});
const form = ref({ const form = ref({
name: "", name: "",
logo: "", logo: "",
@@ -196,13 +191,21 @@ const formValidate = reactive({
logo: [regular.REQUIRED, regular.URL200], logo: [regular.REQUIRED, regular.URL200],
}); });
const submitLoading = ref(false); const submitLoading = ref(false);
const data = ref([]);
const total = ref(0);
const searchFormRef = ref(null); const searchFormRef = ref(null);
const formRef = ref(null); const formRef = ref(null);
const ossManageRef = ref(null); const ossManageRef = ref(null);
const { loading, data, total, searchForm, getDataList, handleSearch, resetSearch } = useTable(
getManagerBrandPage,
{
pageSize: 20,
sort: "create_time",
order: "desc",
form: { name: "" },
}
);
function openLogoPicker() { function openLogoPicker() {
picModelFlag.value = true; picModelFlag.value = true;
nextTick(() => { nextTick(() => {
@@ -306,37 +309,6 @@ function delBrand(row) {
}).catch(() => {}); }).catch(() => {});
} }
function init() {
getDataList();
}
function changePage(v) {
searchForm.pageNumber = v;
getDataList();
}
function changePageSize(v) {
searchForm.pageSize = v;
getDataList();
}
function handleSearch() {
searchForm.pageNumber = 1;
searchForm.pageSize = 20;
getDataList();
}
function getDataList() {
loading.value = true;
getManagerBrandPage(searchForm).then((res) => {
loading.value = false;
if (res.success) {
data.value = res.result.records;
total.value = res.result.total;
}
});
}
function handleSubmit() { function handleSubmit() {
formRef.value.validate((valid) => { formRef.value.validate((valid) => {
if (valid) { if (valid) {
@@ -382,16 +354,19 @@ function edit(v) {
v[attr] = ""; v[attr] = "";
} }
} }
const str = JSON.stringify(v); form.value = JSON.parse(JSON.stringify(v));
const data = JSON.parse(str);
form.value = data;
modalVisible.value = true; modalVisible.value = true;
} }
onMounted(() => {
init();
});
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.link-text {
color: #409eff;
cursor: pointer;
text-decoration: none;
}
.op-split {
margin: 0 8px;
color: #dcdee2;
}
</style> </style>

View File

@@ -27,12 +27,13 @@
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" class="search-btn" @click="handleSearch">搜索</el-button> <el-button type="primary" class="search-btn" @click="handleSearch">搜索</el-button>
<el-button @click="resetSearch">重置</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
</el-card> </el-card>
<el-card> <el-card class="mt_10">
<el-table ref="table" v-loading="loading" border :data="data" class="mt_10" style="width: 100%"> <el-table ref="table" v-loading="loading" border :data="data" style="width: 100%">
<el-table-column prop="goodsName" label="商品名称" min-width="120" show-overflow-tooltip /> <el-table-column prop="goodsName" label="商品名称" min-width="120" show-overflow-tooltip />
<el-table-column prop="memberName" label="客户名称" min-width="120" show-overflow-tooltip /> <el-table-column prop="memberName" label="客户名称" min-width="120" show-overflow-tooltip />
<el-table-column prop="content" label="评论内容" min-width="220" show-overflow-tooltip /> <el-table-column prop="content" label="评论内容" min-width="220" show-overflow-tooltip />
@@ -43,13 +44,13 @@
</el-tag> </el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="评价" width="90"> <el-table-column label="评价" width="90" align="center">
<template #default="{ row }"> <template #default="{ row }">
<el-tag v-if="row" :type="gradeTagType(row.grade)">{{ gradeText(row.grade) }}</el-tag> <el-tag v-if="row" :type="gradeTagType(row.grade)">{{ gradeText(row.grade) }}</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="createTime" label="评价时间" width="170" /> <el-table-column prop="createTime" label="评价时间" width="170" />
<el-table-column label="页面展示" width="100"> <el-table-column label="页面展示" width="100" align="center">
<template #default="{ row }"> <template #default="{ row }">
<el-switch <el-switch
v-if="row" v-if="row"
@@ -84,8 +85,8 @@
:total="total" :total="total"
layout="total, sizes, prev, pager, next, jumper" layout="total, sizes, prev, pager, next, jumper"
size="small" size="small"
@current-change="changePage" @current-change="getDataList"
@size-change="changePageSize" @size-change="() => { searchForm.pageNumber = 1; getDataList(); }"
/> />
</div> </div>
</el-card> </el-card>
@@ -112,18 +113,10 @@
</div> </div>
</div> </div>
<div class="right-container"> <div class="right-container">
<div class="border-b">{{ infoData.goodsName }}</div>
<div class="border-b">
<div class="div-height">店铺名称:{{ infoData.storeName }}</div>
<div class="div-height">订单号:{{ infoData.orderNo }}</div>
</div>
<div class="border-b"> <div class="border-b">
<div class="review-item"> <div class="review-item">
<el-avatar v-if="infoData.memberProfile" :src="infoData.memberProfile" :size="40" /> <div class="review-name">{{ infoData.memberName }}:</div>
<div class="review-meta"> <div class="review-content">{{ infoData.content }}</div>
<div class="review-name">{{ infoData.memberName }}</div>
<div class="review-content">{{ infoData.content }}</div>
</div>
</div> </div>
<div class="score-content"> <div class="score-content">
<span>物流评分:{{ infoData.deliveryScore }}</span> <span>物流评分:{{ infoData.deliveryScore }}</span>
@@ -171,43 +164,49 @@
</template> </template>
<script setup> <script setup>
import { nextTick, onMounted, ref } from "vue"; import { nextTick, ref } from "vue";
import { useTable } from "@/utils/useTable";
import * as API_Member from "@/api/member"; import * as API_Member from "@/api/member";
import { ElMessage, ElMessageBox } from "element-plus"; import { ElMessage, ElMessageBox } from "element-plus";
defineOptions({ name: "goods-review" }); defineOptions({ name: "goods-review" });
// 模板中的 el-form ref(原 ref="searchForm",为避免与数据 searchForm 同名互相覆盖而改名),script 内未使用
const searchFormRef = ref(null); const searchFormRef = ref(null);
const table = ref(null);
const infoData = ref({}); const infoData = ref({});
const infoFlag = ref(false); const infoFlag = ref(false);
const infoTitle = ref(""); const infoTitle = ref("");
const currentReviewId = ref(""); const currentReviewId = ref("");
const detailStatusReady = ref(false); const detailStatusReady = ref(false);
const loading = ref(true);
const searchForm = ref({ const { loading, data, total, searchForm, getDataList, handleSearch, resetSearch } = useTable(
pageNumber: 1, API_Member.getMemberReview,
pageSize: 20, {
goodsName: "", pageSize: 20,
sort: "createTime", sort: "createTime",
order: "desc", order: "desc",
startDate: "", form: {
endDate: "", goodsName: "",
}); memberName: "",
const data = ref([]); startDate: "",
const total = ref(0); endDate: "",
},
}
);
function gradeTagType(grade) { function gradeTagType(grade) {
if (grade === "GOOD") return "success"; if (grade === "GOOD") return "success";
if (grade === "MODERATE") return "warning"; if (grade === "MODERATE") return "warning";
return "danger"; return "danger";
} }
function gradeText(grade) { function gradeText(grade) {
if (grade === "GOOD") return "好评"; if (grade === "GOOD") return "好评";
if (grade === "MODERATE") return "中评"; if (grade === "MODERATE") return "中评";
return "差评"; return "差评";
} }
function changeSwitchView(status) { function changeSwitchView(status) {
if (!detailStatusReady.value || !currentReviewId.value) { if (!detailStatusReady.value || !currentReviewId.value) {
return; return;
@@ -219,22 +218,7 @@ function changeSwitchView(status) {
} }
}); });
} }
function init() {
getDataList();
}
function changePage(v) {
searchForm.value.pageNumber = v;
getDataList();
}
function changePageSize(v) {
searchForm.value.pageSize = v;
getDataList();
}
function handleSearch() {
searchForm.value.pageNumber = 1;
searchForm.value.pageSize = 20;
getDataList();
}
function changeSwitch(row) { function changeSwitch(row) {
if (!row || !row.id) { if (!row || !row.id) {
return; return;
@@ -245,6 +229,7 @@ function changeSwitch(row) {
} }
}); });
} }
function updateTop(v) { function updateTop(v) {
const top = !v.top; const top = !v.top;
API_Member.updateMemberReviewTop(v.id, { top }).then((res) => { API_Member.updateMemberReviewTop(v.id, { top }).then((res) => {
@@ -259,23 +244,11 @@ function updateTop(v) {
}; };
}); });
ElMessage.success(top ? "置顶成功!" : "取消置顶成功!"); ElMessage.success(top ? "置顶成功!" : "取消置顶成功!");
init(); getDataList();
} }
}); });
} }
function getDataList() {
loading.value = true;
API_Member.getMemberReview(searchForm.value)
.then((res) => {
if (res.success) {
data.value = res.result.records;
total.value = res.result.total;
}
})
.finally(() => {
loading.value = false;
});
}
function info(v) { function info(v) {
currentReviewId.value = v.id; currentReviewId.value = v.id;
detailStatusReady.value = false; detailStatusReady.value = false;
@@ -291,23 +264,21 @@ function info(v) {
} }
}); });
} }
function onInfoDialogClosed() { function onInfoDialogClosed() {
detailStatusReady.value = false; detailStatusReady.value = false;
currentReviewId.value = ""; currentReviewId.value = "";
infoData.value = {}; infoData.value = {};
} }
function remove(v) { function remove(v) {
ElMessageBox.confirm("您确认要删除客户" + v.memberName + "的评论?", "确认删除", { type: "warning" }).then(() => { ElMessageBox.confirm("您确认要删除客户" + v.memberName + "的评论?", "确认删除", { type: "warning" }).then(() => {
return API_Member.delMemberReview(v.id).then(() => { return API_Member.delMemberReview(v.id).then(() => {
ElMessage.success("修改成功"); ElMessage.success("修改成功");
init(); getDataList();
}); });
}).catch(() => {}); }).catch(() => {});
} }
onMounted(() => {
init();
});
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@@ -356,9 +327,6 @@ label {
position: relative; position: relative;
margin-top: 12px; margin-top: 12px;
} }
.div-height {
line-height: 25px;
}
.score-content { .score-content {
margin: 5px 0; margin: 5px 0;
span { span {
@@ -378,7 +346,7 @@ label {
margin-top: 4px; margin-top: 4px;
} }
.ops a { .ops a {
color: #2d8cf0; color: #409eff;
cursor: pointer; cursor: pointer;
text-decoration: none; text-decoration: none;
} }