mirror of
https://gitee.com/beijing_hongye_huicheng/lilishop-ui.git
synced 2026-11-13 12:28:54 +08:00
feat(seller): 评价管理列表增强(回复状态/有无图片筛选、评价分级 Tab、会员头像列)及多页面样式优化(商品列表、部门管理、OSS 素材、运费模板、页头页脚等)
This commit is contained in:
@@ -1,81 +1,37 @@
|
||||
<template>
|
||||
<div class="search">
|
||||
<el-card>
|
||||
<el-row class="operation">
|
||||
<el-switch
|
||||
v-model="strict"
|
||||
active-text="级联"
|
||||
inactive-text="单选"
|
||||
style="margin-right: 5px"
|
||||
/>
|
||||
<el-button @click="addRoot">添加部门</el-button>
|
||||
<el-button type="primary" @click="add">添加子部门</el-button>
|
||||
<div class="operation">
|
||||
<el-button type="primary" @click="openAdd('0')">添加部门</el-button>
|
||||
<el-button @click="delAll">批量删除</el-button>
|
||||
<el-button @click="getParentList">刷新</el-button>
|
||||
</el-row>
|
||||
<el-row type="flex" justify="start">
|
||||
<el-col :md="8" :lg="8" :xl="6">
|
||||
<el-alert type="info" show-icon :closable="false">
|
||||
当前选择编辑:
|
||||
<span class="select-title">{{ editTitle }}</span>
|
||||
<a v-if="form.id" class="select-clear" @click="cancelSelect">取消选择</a>
|
||||
</el-alert>
|
||||
<div v-loading="loading" class="tree-bar" :style="{ maxHeight: maxHeight }">
|
||||
<el-tree
|
||||
ref="treeRef"
|
||||
:data="data"
|
||||
:props="treeProps"
|
||||
node-key="id"
|
||||
show-checkbox
|
||||
highlight-current
|
||||
default-expand-all
|
||||
:check-strictly="!strict"
|
||||
:current-node-key="currentNodeKey"
|
||||
@node-click="onNodeClick"
|
||||
@check="onCheckChange"
|
||||
/>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :md="15" :lg="13" :xl="9" style="margin-left: 10px">
|
||||
<el-form ref="formRef" :model="form" label-width="100px" :rules="formValidate">
|
||||
<el-form-item label="部门名称" prop="title">
|
||||
<el-input v-model="form.title" />
|
||||
</el-form-item>
|
||||
<el-form-item label="选择角色">
|
||||
<el-select
|
||||
v-model="selectedRole"
|
||||
multiple
|
||||
:loading="userLoading"
|
||||
placeholder="请选择角色"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in users"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="排序值" prop="sortOrder">
|
||||
<el-tooltip placement="right" content="值越小越靠前,支持小数">
|
||||
<el-input-number v-model="form.sortOrder" :max="1000" :min="0" />
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button
|
||||
type="primary"
|
||||
style="margin-right: 5px"
|
||||
:loading="submitLoading"
|
||||
@click="submitEdit"
|
||||
>
|
||||
修改并保存
|
||||
</el-button>
|
||||
<el-button @click="handleReset">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-button @click="getList">刷新</el-button>
|
||||
</div>
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="data"
|
||||
row-key="id"
|
||||
border
|
||||
default-expand-all
|
||||
@selection-change="onSelectionChange"
|
||||
>
|
||||
<el-table-column type="selection" width="50" align="center" />
|
||||
<el-table-column prop="title" label="部门名称" min-width="180" />
|
||||
<el-table-column label="上级部门" min-width="140">
|
||||
<template #default="{ row }">{{ parentTitle(row) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="sortOrder" label="排序值" width="90" align="center" />
|
||||
<el-table-column prop="createTime" label="创建时间" width="170" align="center" />
|
||||
<el-table-column prop="updateTime" label="修改时间" width="170" align="center" />
|
||||
<el-table-column label="操作" width="200" align="center" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<a class="link-text" @click="openAdd(row.id)">添加子级</a>
|
||||
<span class="op-split">|</span>
|
||||
<a class="link-text" @click="openEdit(row)">编辑</a>
|
||||
<span class="op-split">|</span>
|
||||
<a class="link-text" @click="delOne(row)">删除</a>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
<el-dialog
|
||||
@@ -83,30 +39,55 @@
|
||||
:title="modalTitle"
|
||||
width="500px"
|
||||
:close-on-click-modal="false"
|
||||
destroy-on-close
|
||||
>
|
||||
<el-form ref="formAddRef" :model="formAdd" label-width="85px" :rules="formValidate">
|
||||
<div v-if="showParent">
|
||||
<el-form-item label="上级部门:">{{ form.title }}</el-form-item>
|
||||
</div>
|
||||
<el-form ref="formRef" :model="form" label-width="85px" :rules="formValidate">
|
||||
<el-form-item label="上级部门">
|
||||
<el-tree-select
|
||||
v-model="form.parentId"
|
||||
:data="parentOptions"
|
||||
:props="{ label: 'title', children: 'children' }"
|
||||
node-key="id"
|
||||
check-strictly
|
||||
default-expand-all
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="部门名称" prop="title">
|
||||
<el-input v-model="formAdd.title" />
|
||||
<el-input v-model="form.title" placeholder="请输入部门名称" />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="modalType === 1" label="选择角色">
|
||||
<el-select
|
||||
v-model="selectedRole"
|
||||
multiple
|
||||
:loading="roleLoading"
|
||||
placeholder="请选择角色"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in roles"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="排序值" prop="sortOrder">
|
||||
<el-tooltip placement="right" content="值越小越靠前,支持小数">
|
||||
<el-input-number v-model="formAdd.sortOrder" :max="1000" :min="0" />
|
||||
<el-input-number v-model="form.sortOrder" :max="1000" :min="0" />
|
||||
</el-tooltip>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="cancelAdd">取消</el-button>
|
||||
<el-button type="primary" :loading="submitLoading" @click="submitAdd">提交</el-button>
|
||||
<el-button @click="modalVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="submitLoading" @click="handleSubmit">提交</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onMounted, ref } from "vue";
|
||||
import { computed, onMounted, ref } from "vue";
|
||||
import {
|
||||
initDepartment,
|
||||
addDepartment,
|
||||
@@ -120,36 +101,24 @@ import { Message, Modal } from "@/utils/message";
|
||||
|
||||
defineOptions({ name: "store-department-manage" });
|
||||
|
||||
const treeRef = ref(null);
|
||||
const formRef = ref(null);
|
||||
const formAddRef = ref(null);
|
||||
|
||||
const loading = ref(true);
|
||||
const maxHeight = ref("500px");
|
||||
const strict = ref(true);
|
||||
const userLoading = ref(false);
|
||||
const modalVisible = ref(false);
|
||||
const selectList = ref([]);
|
||||
const selectCount = ref(0);
|
||||
const showParent = ref(false);
|
||||
const modalType = ref(0); // 0 添加 1 编辑
|
||||
const modalTitle = ref("");
|
||||
const editTitle = ref("");
|
||||
const submitLoading = ref(false);
|
||||
const roleLoading = ref(false);
|
||||
const data = ref([]);
|
||||
const roles = ref([]);
|
||||
const selectedRole = ref([]);
|
||||
const currentNodeKey = ref(null);
|
||||
const treeProps = {
|
||||
label: "title",
|
||||
children: "children",
|
||||
isLeaf: "isLeaf",
|
||||
};
|
||||
const selectedRows = ref([]);
|
||||
const form = ref({
|
||||
id: "",
|
||||
parentId: "0",
|
||||
title: "",
|
||||
parentId: "",
|
||||
parentTitle: "",
|
||||
sortOrder: 0,
|
||||
status: 0,
|
||||
});
|
||||
const formAdd = ref({});
|
||||
const formValidate = {
|
||||
title: [{ required: true, message: "名称不能为空", trigger: "blur" }],
|
||||
sortOrder: [
|
||||
@@ -161,23 +130,57 @@ const formValidate = {
|
||||
},
|
||||
],
|
||||
};
|
||||
const submitLoading = ref(false);
|
||||
const data = ref([]);
|
||||
const users = ref([]);
|
||||
|
||||
function init() {
|
||||
getParentList();
|
||||
// id -> title 映射,用于展示上级部门名称
|
||||
const titleMap = computed(() => {
|
||||
const map = {};
|
||||
const walk = (list) => {
|
||||
list.forEach((item) => {
|
||||
map[item.id] = item.title;
|
||||
if (item.children?.length) walk(item.children);
|
||||
});
|
||||
};
|
||||
walk(data.value);
|
||||
return map;
|
||||
});
|
||||
|
||||
// 上级部门下拉树:根节点为“一级部门”;编辑时剔除自身及子级,防止循环挂级
|
||||
const parentOptions = computed(() => {
|
||||
const tree =
|
||||
modalType.value === 1 ? pruneTree(data.value, form.value.id) : data.value;
|
||||
return [{ id: "0", title: "一级部门", children: tree }];
|
||||
});
|
||||
|
||||
function pruneTree(list, excludeId) {
|
||||
return list
|
||||
.filter((item) => item.id !== excludeId)
|
||||
.map((item) => ({
|
||||
...item,
|
||||
children: item.children?.length
|
||||
? pruneTree(item.children, excludeId)
|
||||
: undefined,
|
||||
}));
|
||||
}
|
||||
function getParentList() {
|
||||
|
||||
function parentTitle(row) {
|
||||
if (row.parentId === "0" || row.parentId == null) return "-";
|
||||
return titleMap.value[row.parentId] || "-";
|
||||
}
|
||||
|
||||
function getList() {
|
||||
loading.value = true;
|
||||
initDepartment().then((res) => {
|
||||
loading.value = false;
|
||||
if (res.success) {
|
||||
const list = Array.isArray(res.result) ? res.result : [];
|
||||
data.value = bubbleSort(normalizeDepartmentTree(list));
|
||||
}
|
||||
});
|
||||
initDepartment()
|
||||
.then((res) => {
|
||||
if (res.success) {
|
||||
const list = Array.isArray(res.result) ? res.result : [];
|
||||
data.value = sortTree(normalizeDepartmentTree(list));
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
}
|
||||
|
||||
function normalizeDepartmentTree(list) {
|
||||
return list.map((item) => {
|
||||
const node = { ...item };
|
||||
@@ -189,90 +192,71 @@ function normalizeDepartmentTree(list) {
|
||||
return node;
|
||||
});
|
||||
}
|
||||
function onNodeClick(data) {
|
||||
if (!data) {
|
||||
cancelSelect();
|
||||
return;
|
||||
}
|
||||
const row = JSON.parse(JSON.stringify(data));
|
||||
for (const attr in row) {
|
||||
if (row[attr] == null) {
|
||||
row[attr] = "";
|
||||
}
|
||||
}
|
||||
editTitle.value = row.title;
|
||||
currentNodeKey.value = row.id;
|
||||
userLoading.value = true;
|
||||
|
||||
getUserByDepartmentId(row.id).then((res) => {
|
||||
const way = [];
|
||||
res.result &&
|
||||
res.result.forEach((item) => {
|
||||
way.push(item.roleId);
|
||||
});
|
||||
selectedRole.value = way;
|
||||
function sortTree(list) {
|
||||
list.sort((a, b) => (a.sortOrder ?? 0) - (b.sortOrder ?? 0));
|
||||
list.forEach((item) => {
|
||||
if (item.children?.length) sortTree(item.children);
|
||||
});
|
||||
return list;
|
||||
}
|
||||
|
||||
getRoleList({
|
||||
pageNumber: 1,
|
||||
pageSize: 10000,
|
||||
}).then((res) => {
|
||||
userLoading.value = false;
|
||||
if (res.success) {
|
||||
users.value = res.result.records;
|
||||
form.value = row;
|
||||
}
|
||||
});
|
||||
function onSelectionChange(rows) {
|
||||
selectedRows.value = rows;
|
||||
}
|
||||
function onCheckChange(_data, { checkedNodes }) {
|
||||
selectList.value = checkedNodes;
|
||||
selectCount.value = checkedNodes.length;
|
||||
|
||||
function openAdd(parentId) {
|
||||
modalType.value = 0;
|
||||
modalTitle.value = parentId === "0" ? "添加部门" : "添加子部门";
|
||||
form.value = { id: "", parentId, title: "", sortOrder: 0, status: 0 };
|
||||
modalVisible.value = true;
|
||||
}
|
||||
function bubbleSort(array) {
|
||||
if (!Array.isArray(array)) return [];
|
||||
const len = array.length;
|
||||
if (len < 2) return array;
|
||||
for (let i = 0; i < len; i++) {
|
||||
for (let j = 0; j < i; j++) {
|
||||
if (array[j].sortOrder > array[i].sortOrder) {
|
||||
const temp = array[j];
|
||||
array[j] = array[i];
|
||||
array[i] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
return array;
|
||||
}
|
||||
function cancelSelect() {
|
||||
treeRef.value?.setCurrentKey(null);
|
||||
currentNodeKey.value = null;
|
||||
formRef.value.resetFields();
|
||||
delete form.value.id;
|
||||
editTitle.value = "";
|
||||
|
||||
function openEdit(row) {
|
||||
modalType.value = 1;
|
||||
modalTitle.value = "编辑部门";
|
||||
form.value = {
|
||||
id: row.id,
|
||||
parentId: row.parentId ?? "0",
|
||||
title: row.title,
|
||||
sortOrder: row.sortOrder ?? 0,
|
||||
status: 0,
|
||||
};
|
||||
selectedRole.value = [];
|
||||
roleLoading.value = true;
|
||||
modalVisible.value = true;
|
||||
Promise.all([
|
||||
getUserByDepartmentId(row.id),
|
||||
getRoleList({ pageNumber: 1, pageSize: 10000 }),
|
||||
]).then(([bindRes, roleRes]) => {
|
||||
roleLoading.value = false;
|
||||
if (bindRes.result) {
|
||||
selectedRole.value = bindRes.result.map((item) => item.roleId);
|
||||
}
|
||||
if (roleRes.success) {
|
||||
roles.value = roleRes.result.records;
|
||||
}
|
||||
});
|
||||
}
|
||||
function cancelAdd() {
|
||||
modalVisible.value = false;
|
||||
}
|
||||
function handleReset() {
|
||||
formRef.value.resetFields();
|
||||
form.value.status = 0;
|
||||
}
|
||||
function submitEdit() {
|
||||
formRef.value.validate((valid) => {
|
||||
if (valid) {
|
||||
if (!form.value.id) {
|
||||
Message.warning("请先点击选择要修改的部门");
|
||||
return;
|
||||
}
|
||||
const roleWay = [];
|
||||
selectedRole.value.forEach((item) => {
|
||||
roleWay.push({
|
||||
departmentId: form.value.id,
|
||||
roleId: item,
|
||||
});
|
||||
});
|
||||
|
||||
function handleSubmit() {
|
||||
formRef.value.validate((valid) => {
|
||||
if (!valid) return;
|
||||
submitLoading.value = true;
|
||||
if (modalType.value === 0) {
|
||||
addDepartment(form.value).then((res) => {
|
||||
submitLoading.value = false;
|
||||
if (res.success) {
|
||||
Message.success("添加成功");
|
||||
modalVisible.value = false;
|
||||
getList();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
const roleWay = selectedRole.value.map((roleId) => ({
|
||||
departmentId: form.value.id,
|
||||
roleId,
|
||||
}));
|
||||
Promise.all([
|
||||
editDepartment(form.value.id, form.value),
|
||||
updateDepartmentRole(form.value.id, roleWay),
|
||||
@@ -280,76 +264,48 @@ function submitEdit() {
|
||||
submitLoading.value = false;
|
||||
if (res[0].success) {
|
||||
Message.success("编辑成功");
|
||||
init();
|
||||
modalVisible.value = false;
|
||||
getList();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
function submitAdd() {
|
||||
formAddRef.value.validate((valid) => {
|
||||
if (valid) {
|
||||
submitLoading.value = true;
|
||||
addDepartment(formAdd.value).then((res) => {
|
||||
submitLoading.value = false;
|
||||
|
||||
function delOne(row) {
|
||||
Modal.confirm({
|
||||
title: "确认删除",
|
||||
content: "删除该部门将同时删除其下级所有部门,确认删除?",
|
||||
loading: true,
|
||||
onOk: () => {
|
||||
deleteDepartment(row.id).then((res) => {
|
||||
Modal.remove();
|
||||
if (res.success) {
|
||||
Message.success("添加成功");
|
||||
init();
|
||||
modalVisible.value = false;
|
||||
Message.success("删除成功");
|
||||
getList();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
function add() {
|
||||
if (form.value.id == "" || form.value.id == null) {
|
||||
Message.warning("请先点击选择一个部门");
|
||||
return;
|
||||
}
|
||||
modalTitle.value = "添加子部门";
|
||||
showParent.value = true;
|
||||
formAdd.value = {
|
||||
parentId: form.value.id,
|
||||
sortOrder: 0,
|
||||
status: 0,
|
||||
};
|
||||
modalVisible.value = true;
|
||||
}
|
||||
function addRoot() {
|
||||
modalTitle.value = "添加一级部门";
|
||||
showParent.value = false;
|
||||
formAdd.value = {
|
||||
parentId: 0,
|
||||
sortOrder: 0,
|
||||
status: 0,
|
||||
};
|
||||
modalVisible.value = true;
|
||||
}
|
||||
|
||||
function delAll() {
|
||||
if (selectCount.value <= 0) {
|
||||
if (selectedRows.value.length === 0) {
|
||||
Message.warning("您还未勾选要删除的数据");
|
||||
return;
|
||||
}
|
||||
Modal.confirm({
|
||||
title: "确认删除",
|
||||
content:
|
||||
"您确认要删除所选的 " + selectCount.value + " 条数据及其下级所有数据?",
|
||||
content: `您确认要删除所选的 ${selectedRows.value.length} 条数据及其下级所有数据?`,
|
||||
loading: true,
|
||||
onOk: () => {
|
||||
let ids = "";
|
||||
selectList.value.forEach(function (e) {
|
||||
ids += e.id + ",";
|
||||
});
|
||||
ids = ids.substring(0, ids.length - 1);
|
||||
const ids = selectedRows.value.map((e) => e.id).join(",");
|
||||
deleteDepartment(ids).then((res) => {
|
||||
Modal.remove();
|
||||
if (res.success) {
|
||||
Message.success("删除成功");
|
||||
selectList.value = [];
|
||||
selectCount.value = 0;
|
||||
cancelSelect();
|
||||
init();
|
||||
selectedRows.value = [];
|
||||
getList();
|
||||
}
|
||||
});
|
||||
},
|
||||
@@ -357,12 +313,21 @@ function delAll() {
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
const height = document.documentElement.clientHeight;
|
||||
maxHeight.value = Number(height - 287) + "px";
|
||||
init();
|
||||
getList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "@/styles/tree-common.scss";
|
||||
.operation {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.link-text {
|
||||
color: #2d8cf0;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
}
|
||||
.op-split {
|
||||
margin: 0 8px;
|
||||
color: #dcdee2;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user