mirror of
https://gitee.com/beijing_hongye_huicheng/lilishop-ui.git
synced 2026-08-07 03:15:01 +08:00
refactor: 重构组件逻辑与样式优化
- 在 App.vue 中重构站点信息的获取与应用逻辑,提升代码可读性与维护性。 - 更新 Search.vue 组件,优化搜索框的样式与结构,增强用户体验。 - 在 element.scss 中注释掉不再使用的样式,并新增确认收货按钮的样式。 - 改进多个页面的布局与样式,确保响应式设计的一致性与美观性。 - 更新订单相关组件的按钮样式,提升视觉一致性与可用性。
This commit is contained in:
@@ -24,12 +24,11 @@
|
||||
<el-tree
|
||||
ref="treeRef"
|
||||
:data="data"
|
||||
lazy
|
||||
:load="loadNode"
|
||||
:props="treeProps"
|
||||
node-key="id"
|
||||
show-checkbox
|
||||
highlight-current
|
||||
default-expand-all
|
||||
:check-strictly="!strict"
|
||||
:current-node-key="currentNodeKey"
|
||||
@node-click="onNodeClick"
|
||||
@@ -109,7 +108,6 @@
|
||||
<script>
|
||||
import {
|
||||
initDepartment,
|
||||
loadDepartment,
|
||||
addDepartment,
|
||||
editDepartment,
|
||||
deleteDepartment,
|
||||
@@ -176,23 +174,20 @@ export default {
|
||||
initDepartment().then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
this.data = this.bubbleSort(res.result);
|
||||
const list = Array.isArray(res.result) ? res.result : [];
|
||||
this.data = this.bubbleSort(this.normalizeDepartmentTree(list));
|
||||
}
|
||||
});
|
||||
},
|
||||
loadNode(node, resolve) {
|
||||
const id = node.data?.id;
|
||||
if (id === undefined || id === null) {
|
||||
resolve([]);
|
||||
return;
|
||||
}
|
||||
loadDepartment(id).then((res) => {
|
||||
this.loadingEdit = false;
|
||||
if (res.success) {
|
||||
resolve(res.result || []);
|
||||
normalizeDepartmentTree(list) {
|
||||
return list.map((item) => {
|
||||
const node = { ...item };
|
||||
if (Array.isArray(node.children) && node.children.length > 0) {
|
||||
node.children = this.normalizeDepartmentTree(node.children);
|
||||
} else {
|
||||
resolve([]);
|
||||
delete node.children;
|
||||
}
|
||||
return node;
|
||||
});
|
||||
},
|
||||
onNodeClick(data) {
|
||||
@@ -235,6 +230,7 @@ export default {
|
||||
this.selectCount = checkedNodes.length;
|
||||
},
|
||||
bubbleSort(array) {
|
||||
if (!Array.isArray(array)) return [];
|
||||
const len = array.length;
|
||||
if (len < 2) return array;
|
||||
for (let i = 0; i < len; i++) {
|
||||
|
||||
@@ -77,7 +77,7 @@ export default {
|
||||
selectDate: null,
|
||||
searchForm: {
|
||||
type: 1,
|
||||
key: "",
|
||||
searchKey: "",
|
||||
operatorName: "",
|
||||
pageNumber: 1,
|
||||
pageSize: 20,
|
||||
@@ -114,15 +114,23 @@ export default {
|
||||
},
|
||||
handleSearch() {
|
||||
this.searchForm.pageNumber = 1;
|
||||
if (this.selectDate && this.selectDate.length === 2) {
|
||||
this.searchForm.startDate = this.selectDate[0];
|
||||
this.searchForm.endDate = this.selectDate[1];
|
||||
}
|
||||
this.getLogList();
|
||||
},
|
||||
getLogList() {
|
||||
this.loading = true;
|
||||
getLogListData(this.searchForm).then((res) => {
|
||||
this.loading = false;
|
||||
if (res.success) {
|
||||
if (res && res.success) {
|
||||
this.data = res.result.records;
|
||||
this.total = res.result.total;
|
||||
} else {
|
||||
this.data = [];
|
||||
this.total = 0;
|
||||
this.$Message.error((res && res.message) || "日志查询失败");
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
@@ -135,8 +135,10 @@
|
||||
v-model="menuModalVisible"
|
||||
:title="modalTitle"
|
||||
width="500px"
|
||||
align-center
|
||||
append-to-body
|
||||
:close-on-click-modal="false"
|
||||
top="30px"
|
||||
class="menu-manage-dialog"
|
||||
>
|
||||
<el-form ref="formAdd" :model="formAdd" label-width="100px" :rules="formValidate">
|
||||
<div v-if="showParent">
|
||||
@@ -557,3 +559,10 @@ export default {
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
.menu-manage-dialog .el-dialog__body {
|
||||
max-height: calc(100vh - 220px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -135,8 +135,10 @@
|
||||
v-model="menuModalVisible"
|
||||
:title="modalTitle"
|
||||
width="500px"
|
||||
align-center
|
||||
append-to-body
|
||||
:close-on-click-modal="false"
|
||||
top="30px"
|
||||
class="menu-manage-dialog"
|
||||
>
|
||||
<el-form ref="formAdd" :model="formAdd" label-width="100px" :rules="formValidate">
|
||||
<div v-if="showParent">
|
||||
@@ -557,3 +559,10 @@ export default {
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
.menu-manage-dialog .el-dialog__body {
|
||||
max-height: calc(100vh - 220px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
</style>
|
||||
|
||||
484
manager/src/views/sys/message/messageTemplate.vue
Normal file
484
manager/src/views/sys/message/messageTemplate.vue
Normal file
@@ -0,0 +1,484 @@
|
||||
<template>
|
||||
<div class="search">
|
||||
<el-card>
|
||||
<div class="toolbar">
|
||||
<div class="toolbar-title">消息模板管理</div>
|
||||
<div>
|
||||
<el-button size="small" style="margin-right: 8px" @click="reloadCurrent">刷新</el-button>
|
||||
<el-button size="small" style="margin-right: 8px" :loading="syncOaLoading" @click="syncOaTemplates">
|
||||
同步服务号模板
|
||||
</el-button>
|
||||
<el-button size="small" :loading="syncMpLoading" @click="syncMpTemplates">同步小程序模板</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-tabs v-model="activeTab">
|
||||
<el-tab-pane label="会员消息模板" name="member">
|
||||
<el-alert
|
||||
type="info"
|
||||
show-icon
|
||||
:closable="false"
|
||||
style="margin-bottom: 10px"
|
||||
title="支持维护站内信、微信服务号消息、微信小程序订阅消息开关。未匹配模板的渠道会显示禁用。"
|
||||
/>
|
||||
<el-table v-loading="loading" border :data="memberRows" style="width: 100%">
|
||||
<el-table-column prop="index" label="序号" width="80" align="center" />
|
||||
<el-table-column prop="noticeNode" label="模板应用场景" min-width="180" show-overflow-tooltip />
|
||||
<el-table-column label="站内信" width="110" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-switch
|
||||
:model-value="isOpen(row.noticeStatus)"
|
||||
@change="(v) => toggleNoticeChannel(v, row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="微信服务号消息" width="140" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-switch
|
||||
:model-value="isOpen(row.oaStatus)"
|
||||
:disabled="!row.oaId"
|
||||
@change="(v) => toggleOaChannel(v, row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="微信小程序订阅消息" width="160" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-switch
|
||||
:model-value="isOpen(row.mpStatus)"
|
||||
:disabled="!row.mpId"
|
||||
@change="(v) => toggleMpChannel(v, row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="邮箱" width="120" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-switch
|
||||
:model-value="isOpen(row.emailStatus)"
|
||||
:disabled="!row.emailContent"
|
||||
@change="(v) => toggleEmailChannel(v, row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="400" align="center" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<div class="ops">
|
||||
<a class="link-text" @click="openNoticeModal(row)">站内信</a>
|
||||
<span class="op-split">|</span>
|
||||
<a
|
||||
:class="row.oaId ? 'link-text' : 'link-disabled'"
|
||||
@click="row.oaId && openOaModal(row)"
|
||||
>
|
||||
微信服务号消息
|
||||
</a>
|
||||
<span class="op-split">|</span>
|
||||
<a
|
||||
:class="row.mpId ? 'link-text' : 'link-disabled'"
|
||||
@click="row.mpId && openMpModal(row)"
|
||||
>
|
||||
微信小程序订阅消息
|
||||
</a>
|
||||
<span class="op-split">|</span>
|
||||
<a class="link-text" @click="openEmailModal(row)">邮箱</a>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="mt_10" style="display: flex; justify-content: flex-end">
|
||||
<el-pagination
|
||||
v-model:current-page="searchForm.pageNumber"
|
||||
v-model:page-size="searchForm.pageSize"
|
||||
:total="total"
|
||||
:page-sizes="[20, 50, 100]"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
size="small"
|
||||
@current-change="loadMemberPage"
|
||||
@size-change="changePageSize"
|
||||
/>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="商户消息模板" name="store">
|
||||
<el-alert type="info" :closable="false" title="商户消息模板待扩展,后续可复用会员模板能力。" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="平台消息模板" name="platform">
|
||||
<el-alert type="info" :closable="false" title="平台消息模板待扩展,后续可复用会员模板能力。" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="邮箱消息模板" name="email">
|
||||
<el-alert type="info" :closable="false" title="邮箱消息模板待扩展,后续可按场景映射邮箱模板。" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-card>
|
||||
|
||||
<el-dialog v-model="noticeModalVisible" title="站内信模板" width="700px">
|
||||
<el-form label-width="120px">
|
||||
<el-form-item label="模板应用场景">
|
||||
<el-input :model-value="currentRow.noticeNode || '-'" readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="启用">
|
||||
<el-switch
|
||||
:model-value="isOpen(currentRow.noticeStatus)"
|
||||
@change="(v) => toggleNoticeChannel(v, currentRow)"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="模板内容">
|
||||
<el-input :model-value="noticeDetailText" type="textarea" :autosize="{ minRows: 4, maxRows: 8 }" readonly />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="noticeModalVisible = false">关闭</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog v-model="oaModalVisible" title="微信服务号消息模板" width="700px">
|
||||
<el-form label-width="140px">
|
||||
<el-form-item label="模板应用场景">
|
||||
<el-input :model-value="currentRow.noticeNode || '-'" readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="启用">
|
||||
<el-switch
|
||||
:model-value="isOpen(currentRow.oaStatus)"
|
||||
:disabled="!currentRow.oaId"
|
||||
@change="(v) => toggleOaChannel(v, currentRow)"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="模板名称">
|
||||
<el-input :model-value="currentRow.oaName || '-'" readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="微信模板ID">
|
||||
<el-input :model-value="currentRow.oaCode || '-'" readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="模板内容">
|
||||
<el-input
|
||||
:model-value="currentRow.oaContent || '-'"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 4, maxRows: 8 }"
|
||||
readonly
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-alert v-if="!currentRow.oaId" type="warning" :closable="false" title="当前场景未匹配到微信服务号模板。" />
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="oaModalVisible = false">关闭</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog v-model="emailModalVisible" title="邮箱消息模板" width="700px">
|
||||
<el-form label-width="120px">
|
||||
<el-form-item label="模板应用场景">
|
||||
<el-input :model-value="currentRow.noticeNode || '-'" readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="启用">
|
||||
<el-switch
|
||||
:model-value="isOpen(currentRow.emailStatus)"
|
||||
@change="(v) => toggleEmailChannel(v, currentRow)"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="模板内容">
|
||||
<el-input :model-value="emailDetailText" type="textarea" :autosize="{ minRows: 4, maxRows: 8 }" readonly />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="emailModalVisible = false">关闭</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog v-model="mpModalVisible" title="微信小程序订阅消息模板" width="700px">
|
||||
<el-form label-width="150px">
|
||||
<el-form-item label="模板应用场景">
|
||||
<el-input :model-value="currentRow.noticeNode || '-'" readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="启用">
|
||||
<el-switch
|
||||
:model-value="isOpen(currentRow.mpStatus)"
|
||||
:disabled="!currentRow.mpId"
|
||||
@change="(v) => toggleMpChannel(v, currentRow)"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="模板名称">
|
||||
<el-input :model-value="currentRow.mpName || '-'" readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="公共模板库ID">
|
||||
<el-input :model-value="currentRow.mpTemplateId || '-'" readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="订阅消息模板ID">
|
||||
<el-input :model-value="currentRow.mpCode || '-'" readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="模板内容">
|
||||
<el-input
|
||||
:model-value="currentRow.mpContent || '-'"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 4, maxRows: 8 }"
|
||||
readonly
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-alert v-if="!currentRow.mpId" type="warning" :closable="false" title="当前场景未匹配到微信小程序模板。" />
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="mpModalVisible = false">关闭</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as API_Setting from "@/api/setting.js";
|
||||
|
||||
export default {
|
||||
name: "messageTemplate",
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
activeTab: "member",
|
||||
syncOaLoading: false,
|
||||
syncMpLoading: false,
|
||||
total: 0,
|
||||
searchForm: {
|
||||
pageNumber: 1,
|
||||
pageSize: 20,
|
||||
},
|
||||
memberRows: [],
|
||||
currentRow: {},
|
||||
noticeDetailText: "",
|
||||
noticeModalVisible: false,
|
||||
oaModalVisible: false,
|
||||
mpModalVisible: false,
|
||||
emailModalVisible: false,
|
||||
emailDetailText: "",
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
isOpen(status) {
|
||||
return String(status || "").toUpperCase() === "OPEN";
|
||||
},
|
||||
wechatEnableToOpenClose(enable) {
|
||||
if (enable === true || enable === "true" || enable === 1) return "OPEN";
|
||||
return "CLOSE";
|
||||
},
|
||||
toOpenClose(flag) {
|
||||
return flag ? "OPEN" : "CLOSE";
|
||||
},
|
||||
safeText(v) {
|
||||
return v === undefined || v === null ? "" : String(v);
|
||||
},
|
||||
pickByKeys(obj, keys) {
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
const val = obj ? obj[keys[i]] : "";
|
||||
if (val !== undefined && val !== null && val !== "") return val;
|
||||
}
|
||||
return "";
|
||||
},
|
||||
formatOaContent(item) {
|
||||
if (!item) return "";
|
||||
const first = this.pickByKeys(item, ["first", "title", "name"]);
|
||||
const remark = this.pickByKeys(item, ["remark", "content"]);
|
||||
const keywords = Array.isArray(item.keywords)
|
||||
? item.keywords.map((k) => this.pickByKeys(k, ["name", "value", "label"])).filter(Boolean).join(" / ")
|
||||
: this.safeText(item.keywordsText || "");
|
||||
return [first, keywords, remark].filter(Boolean).join("\n");
|
||||
},
|
||||
formatMpContent(item) {
|
||||
if (!item) return "";
|
||||
const keywordsText = this.safeText(item.keywordsText);
|
||||
if (keywordsText) return keywordsText;
|
||||
if (Array.isArray(item.keywords)) {
|
||||
return item.keywords.map((k) => this.pickByKeys(k, ["name", "value", "label"])).filter(Boolean).join(" / ");
|
||||
}
|
||||
return this.safeText(item.content);
|
||||
},
|
||||
async loadMemberPage() {
|
||||
this.loading = true;
|
||||
try {
|
||||
const res = await API_Setting.getMessageTemplateAggregatePage(this.searchForm);
|
||||
if (!(res && res.success && res.result)) {
|
||||
this.memberRows = [];
|
||||
this.total = 0;
|
||||
this.$Message.error((res && res.message) || "加载消息模板失败");
|
||||
return;
|
||||
}
|
||||
const records = res.result.records || [];
|
||||
this.total = res.result.total || 0;
|
||||
this.memberRows = records.map((agg, idx) => {
|
||||
const item = { ...(agg.notice || {}) };
|
||||
const oa = agg.wechatOa;
|
||||
const mp = agg.wechatMp;
|
||||
return {
|
||||
...item,
|
||||
emailStatus: item.emailStatus || "CLOSE",
|
||||
emailContent: item.emailContent || "",
|
||||
index: (this.searchForm.pageNumber - 1) * this.searchForm.pageSize + idx + 1,
|
||||
oaId: oa ? oa.id : "",
|
||||
oaName: oa ? this.pickByKeys(oa, ["name", "templateName", "title"]) : "",
|
||||
oaCode: oa ? this.pickByKeys(oa, ["code", "templateId"]) : "",
|
||||
oaStatus: oa ? this.wechatEnableToOpenClose(oa.enable) : "",
|
||||
oaRaw: oa || null,
|
||||
oaContent: this.formatOaContent(oa),
|
||||
mpId: mp ? mp.id : "",
|
||||
mpName: mp ? this.pickByKeys(mp, ["name", "templateName", "title"]) : "",
|
||||
mpTemplateId: mp ? this.pickByKeys(mp, ["templateId"]) : "",
|
||||
mpCode: mp ? this.pickByKeys(mp, ["code"]) : "",
|
||||
mpStatus: mp ? this.wechatEnableToOpenClose(mp.enable) : "",
|
||||
mpRaw: mp || null,
|
||||
mpContent: this.formatMpContent(mp),
|
||||
};
|
||||
});
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
reloadCurrent() {
|
||||
if (this.activeTab === "member") this.loadMemberPage();
|
||||
},
|
||||
async syncOaTemplates() {
|
||||
this.syncOaLoading = true;
|
||||
try {
|
||||
const res = await API_Setting.wechatMessageSync();
|
||||
if (res && res.success) {
|
||||
await this.loadMemberPage();
|
||||
this.$Message.success("服务号模板同步成功");
|
||||
} else {
|
||||
this.$Message.error((res && res.message) || "服务号模板同步失败");
|
||||
}
|
||||
} finally {
|
||||
this.syncOaLoading = false;
|
||||
}
|
||||
},
|
||||
async syncMpTemplates() {
|
||||
this.syncMpLoading = true;
|
||||
try {
|
||||
const res = await API_Setting.wechatMPMessageSync();
|
||||
if (res && res.success) {
|
||||
await this.loadMemberPage();
|
||||
this.$Message.success("小程序模板同步成功");
|
||||
} else {
|
||||
this.$Message.error((res && res.message) || "小程序模板同步失败");
|
||||
}
|
||||
} finally {
|
||||
this.syncMpLoading = false;
|
||||
}
|
||||
},
|
||||
changePageSize() {
|
||||
this.searchForm.pageNumber = 1;
|
||||
this.loadMemberPage();
|
||||
},
|
||||
async openNoticeModal(row) {
|
||||
this.currentRow = { ...row };
|
||||
this.noticeDetailText = row.noticeContent || "";
|
||||
this.noticeModalVisible = true;
|
||||
const res = await API_Setting.getNoticeMessageDetail(row.id);
|
||||
if (res && res.success && res.result) {
|
||||
const d = res.result;
|
||||
this.noticeDetailText = [d.noticeTitle, d.noticeContent].filter(Boolean).join("\n");
|
||||
}
|
||||
},
|
||||
openOaModal(row) {
|
||||
this.currentRow = { ...row };
|
||||
this.oaModalVisible = true;
|
||||
},
|
||||
openMpModal(row) {
|
||||
this.currentRow = { ...row };
|
||||
this.mpModalVisible = true;
|
||||
},
|
||||
async openEmailModal(row) {
|
||||
this.currentRow = { ...row };
|
||||
const fallback = row.emailContent || row.noticeContent || "";
|
||||
this.emailDetailText = row.noticeTitle ? [row.noticeTitle, fallback].filter(Boolean).join("\n") : fallback;
|
||||
this.emailModalVisible = true;
|
||||
const res = await API_Setting.getNoticeMessageDetail(row.id);
|
||||
if (res && res.success && res.result) {
|
||||
const d = res.result;
|
||||
if (d.emailContent) {
|
||||
this.emailDetailText = d.emailContent;
|
||||
} else {
|
||||
this.emailDetailText = [d.noticeTitle, d.noticeContent].filter(Boolean).join("\n");
|
||||
}
|
||||
}
|
||||
},
|
||||
updateRowStatus(row, key, val) {
|
||||
const idx = this.memberRows.findIndex((x) => x.id === row.id);
|
||||
if (idx >= 0) this.memberRows[idx][key] = val;
|
||||
if (this.currentRow && this.currentRow.id === row.id) this.currentRow[key] = val;
|
||||
},
|
||||
async toggleNoticeChannel(v, row) {
|
||||
const old = row.noticeStatus;
|
||||
this.updateRowStatus(row, "noticeStatus", this.toOpenClose(v));
|
||||
const res = await API_Setting.updateMessageStatus(row.id, this.toOpenClose(v));
|
||||
if (!(res && res.success)) {
|
||||
this.updateRowStatus(row, "noticeStatus", old);
|
||||
this.$Message.error((res && res.message) || "站内信开关更新失败");
|
||||
} else {
|
||||
this.$Message.success("站内信开关更新成功");
|
||||
}
|
||||
},
|
||||
async toggleOaChannel(v, row) {
|
||||
if (!row.oaId) return;
|
||||
const old = row.oaStatus;
|
||||
this.updateRowStatus(row, "oaStatus", this.toOpenClose(v));
|
||||
const params = { id: row.oaId, enable: v };
|
||||
try {
|
||||
const res = await API_Setting.editWechatMessageTemplate(row.oaId, params);
|
||||
if (!(res && res.success)) {
|
||||
this.updateRowStatus(row, "oaStatus", old);
|
||||
this.$Message.error((res && res.message) || "服务号开关更新失败");
|
||||
} else {
|
||||
this.$Message.success("服务号开关更新成功");
|
||||
}
|
||||
} catch (e) {
|
||||
this.updateRowStatus(row, "oaStatus", old);
|
||||
this.$Message.error((e && e.message) || "服务号开关更新失败");
|
||||
}
|
||||
},
|
||||
async toggleMpChannel(v, row) {
|
||||
if (!row.mpId) return;
|
||||
const old = row.mpStatus;
|
||||
this.updateRowStatus(row, "mpStatus", this.toOpenClose(v));
|
||||
const params = { id: row.mpId, enable: v };
|
||||
const res = await API_Setting.editWechatMPMessageTemplate(row.mpId, params);
|
||||
if (!(res && res.success)) {
|
||||
this.updateRowStatus(row, "mpStatus", old);
|
||||
this.$Message.error((res && res.message) || "小程序开关更新失败");
|
||||
} else {
|
||||
this.$Message.success("小程序开关更新成功");
|
||||
}
|
||||
},
|
||||
async toggleEmailChannel(v, row) {
|
||||
const old = row.emailStatus || "CLOSE";
|
||||
this.updateRowStatus(row, "emailStatus", this.toOpenClose(v));
|
||||
const res = await API_Setting.updateNoticeMessageEmailStatus(row.id, this.toOpenClose(v));
|
||||
if (!(res && res.success)) {
|
||||
this.updateRowStatus(row, "emailStatus", old);
|
||||
this.$Message.error((res && res.message) || "邮箱开关更新失败");
|
||||
} else {
|
||||
this.$Message.success("邮箱开关更新成功");
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.loadMemberPage();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.toolbar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.toolbar-title {
|
||||
font-weight: 600;
|
||||
}
|
||||
.ops a {
|
||||
color: #409eff;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
}
|
||||
.link-disabled {
|
||||
color: #c0c4cc;
|
||||
cursor: not-allowed;
|
||||
text-decoration: none;
|
||||
}
|
||||
.op-split {
|
||||
display: inline-block;
|
||||
margin: 0 8px;
|
||||
color: #dcdfe6;
|
||||
}
|
||||
</style>
|
||||
@@ -57,7 +57,7 @@
|
||||
<div v-if="row" class="ops">
|
||||
<a class="link-text" @click="detail(row)">详细</a>
|
||||
<span class="op-split">|</span>
|
||||
<a class="link-text" @click="delete(row.id)">删除</a>
|
||||
<a class="link-text" @click="removeMessage(row.id)">删除</a>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -207,16 +207,21 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="memberShow" label="选择会员" prop="scopeType">
|
||||
<el-button type="primary" plain @click="addVip">选择会员</el-button>
|
||||
<div v-if="messageSendForm.messageClient == 'member'" style="margin-top: 24px">
|
||||
<el-table border :data="selectedMember" style="width: 100%">
|
||||
<el-table-column prop="nickName" label="用户名称" min-width="120" />
|
||||
<el-table-column label="手机号" min-width="120">
|
||||
<div class="member-select-wrap">
|
||||
<el-button type="primary" plain @click="addVip">选择会员</el-button>
|
||||
<el-table
|
||||
v-if="messageSendForm.messageClient == 'member'"
|
||||
border
|
||||
:data="selectedMember"
|
||||
class="member-select-table"
|
||||
>
|
||||
<el-table-column prop="nickName" label="用户名称" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column label="手机号" min-width="140">
|
||||
<template #default="{ row }">
|
||||
<span v-if="row">{{ row.mobile || "暂未填写" }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" min-width="50" align="center">
|
||||
<el-table-column label="操作" width="80" align="center">
|
||||
<template #default="{ row, $index }">
|
||||
<a v-if="row" class="link-text" @click="delUser($index)">删除</a>
|
||||
</template>
|
||||
@@ -235,9 +240,14 @@
|
||||
<userList
|
||||
v-if="checkUserList"
|
||||
ref="memberLayout"
|
||||
:selectedMember="true"
|
||||
:selectedList="selectedMember"
|
||||
@callback="callbackSelectUser"
|
||||
/>
|
||||
<template #footer>
|
||||
<el-button @click="cancelMemberSelect">取消</el-button>
|
||||
<el-button type="primary" @click="confirmMemberSelect">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog
|
||||
@@ -359,6 +369,7 @@ export default {
|
||||
return {
|
||||
activeTab: "MESSAGE",
|
||||
checkUserList: false,
|
||||
memberSelectSnapshot: [],
|
||||
selectedMember: [],
|
||||
loading: true,
|
||||
modalVisible: false,
|
||||
@@ -455,10 +466,17 @@ export default {
|
||||
this.loading = false;
|
||||
},
|
||||
addVip() {
|
||||
this.memberSelectSnapshot = JSON.parse(JSON.stringify(this.selectedMember));
|
||||
this.checkUserList = true;
|
||||
this.$nextTick(() => {
|
||||
this.$refs.memberLayout.selectedMember = true;
|
||||
});
|
||||
},
|
||||
cancelMemberSelect() {
|
||||
this.selectedMember = JSON.parse(JSON.stringify(this.memberSelectSnapshot));
|
||||
this.reSelectMember();
|
||||
this.checkUserList = false;
|
||||
},
|
||||
confirmMemberSelect() {
|
||||
this.reSelectMember();
|
||||
this.checkUserList = false;
|
||||
},
|
||||
paneChange(v) {
|
||||
if (v == "SETTING") {
|
||||
@@ -526,7 +544,7 @@ export default {
|
||||
return shop ? shop.storeName : "";
|
||||
});
|
||||
},
|
||||
delete(id) {
|
||||
removeMessage(id) {
|
||||
this.$Modal.confirm({
|
||||
title: "确认删除",
|
||||
content: "您确认删除此站内信 ?",
|
||||
@@ -545,6 +563,7 @@ export default {
|
||||
this.messageModalTitle = "发送站内信";
|
||||
this.shopShow = false;
|
||||
this.memberShow = false;
|
||||
this.selectedMember = [];
|
||||
this.messageSendForm = {
|
||||
messageRange: "ALL",
|
||||
messageClient: "member",
|
||||
@@ -719,4 +738,11 @@ export default {
|
||||
margin: 0 8px;
|
||||
color: #dcdfe6;
|
||||
}
|
||||
.member-select-wrap {
|
||||
width: 100%;
|
||||
}
|
||||
.member-select-table {
|
||||
width: 100%;
|
||||
margin-top: 12px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -83,15 +83,27 @@ methodItem h4 {
|
||||
border-radius: 6px;
|
||||
}
|
||||
}
|
||||
.choose-member-item {
|
||||
width: 100%;
|
||||
|
||||
.el-form-item__content {
|
||||
margin-left: 0 !important;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.choose-member {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
min-width: 580px;
|
||||
height: 400px;
|
||||
border: 1px solid #eee;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.source-member {
|
||||
width: 50%;
|
||||
flex: 3;
|
||||
min-width: 0;
|
||||
border-right: 1px solid #eee;
|
||||
padding: 10px;
|
||||
}
|
||||
@@ -116,7 +128,8 @@ methodItem h4 {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.traget-member {
|
||||
width: 50%;
|
||||
flex: 2;
|
||||
min-width: 0;
|
||||
padding: 10px;
|
||||
}
|
||||
.scroll-card {
|
||||
|
||||
@@ -184,7 +184,7 @@
|
||||
<el-dialog
|
||||
v-model="sendSmsModal"
|
||||
:title="sendSmsModalTitle"
|
||||
width="900px"
|
||||
width="1100px"
|
||||
:close-on-click-modal="false"
|
||||
destroy-on-close
|
||||
>
|
||||
@@ -234,7 +234,7 @@
|
||||
<el-radio value="2">自定义选择</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="customSms">
|
||||
<el-form-item v-if="customSms" label-width="0" class="choose-member-item">
|
||||
<div class="choose-member">
|
||||
<div class="source-member">
|
||||
<el-input
|
||||
|
||||
@@ -161,6 +161,9 @@
|
||||
box-sizing: border-box;
|
||||
margin: 0 13px 8px;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
.card {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
@@ -172,12 +175,19 @@
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
.checkbox {
|
||||
.card-checkbox {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
z-index: 1000;
|
||||
height: auto;
|
||||
margin: 0;
|
||||
|
||||
:deep(.el-checkbox__label) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.preview {
|
||||
width: 100%;
|
||||
@@ -226,35 +236,6 @@
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
/* Checkbox默认的样式 */
|
||||
.check-box {
|
||||
.ivu-checkbox {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 10px;
|
||||
z-index: 100;
|
||||
}
|
||||
}
|
||||
/* 覆盖iView默认的Checkbox样式 */
|
||||
.ivu-checkbox-wrapper {
|
||||
/*font-size: 16px; !* 修改字体大小 *!*/
|
||||
/*color: #495060; !* 修改文本颜色 *!*/
|
||||
/* 添加其他需要的样式 */
|
||||
}
|
||||
.ivu-checkbox-inner {
|
||||
/*width: 20px; !* 修改选框大小 *!*/
|
||||
/*height: 20px;*/
|
||||
/*border-color: #dcdee2; !* 修改边框颜色 *!*/
|
||||
/* 添加其他需要的样式 */
|
||||
}
|
||||
/* 当Checkbox被选中时的样式 */
|
||||
.ivu-checkbox-checked .ivu-checkbox-inner {
|
||||
/*background-color: #2db7f5; !* 修改选中时的背景颜色 *!*/
|
||||
}
|
||||
/* 当Checkbox不可用时的样式 */
|
||||
.ivu-checkbox-disabled .ivu-checkbox-inner {
|
||||
/*background-color: #e9e9e9; !* 修改禁用状态下的背景颜色 *!*/
|
||||
}
|
||||
|
||||
.demo-tree-render .ivu-tree-title{
|
||||
width: 94%;
|
||||
|
||||
@@ -35,6 +35,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
.oss-select-footer {
|
||||
margin-top: 16px;
|
||||
padding-top: 12px;
|
||||
border-top: 1px solid #ededed;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.tab-empty {
|
||||
padding: 48px 0;
|
||||
color: #999;
|
||||
@@ -59,6 +68,10 @@
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
.oss-manage-date-popper {
|
||||
z-index: 4000 !important;
|
||||
}
|
||||
|
||||
</style>
|
||||
<template>
|
||||
<div class="search">
|
||||
@@ -86,6 +99,8 @@
|
||||
<el-date-picker
|
||||
v-model="selectDate"
|
||||
clearable
|
||||
teleported
|
||||
popper-class="oss-manage-date-popper"
|
||||
value-format="YYYY-MM-DD"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
@@ -165,37 +180,39 @@
|
||||
<el-checkbox-group v-model="selectedOss" @change="selectOssChange">
|
||||
<div class="img-box">
|
||||
<div v-for="(item, index) in data" :key="index" class="img-item">
|
||||
<el-checkbox :value="item.id + ',' + item.url" class="check-box">
|
||||
<div
|
||||
class="card"
|
||||
@mouseenter="onMouseOver(item, index)"
|
||||
@mouseleave="onMouseOut(item, index)"
|
||||
>
|
||||
<img :src="item.url" alt="" />
|
||||
<div v-if="item.isShowPreview" class="preview">
|
||||
<div @click.prevent="download(item)">
|
||||
<el-tooltip content="下载" placement="top">
|
||||
<el-icon :size="18"><Download /></el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<div @click.prevent="remove(item)">
|
||||
<el-tooltip content="删除" placement="top">
|
||||
<el-icon :size="18"><Delete /></el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<div @click.prevent="showPic(item)">
|
||||
<el-tooltip content="预览" placement="top">
|
||||
<el-icon :size="22"><View /></el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<div
|
||||
class="card"
|
||||
:class="{ 'custom-checkbox-card-checked': selectedOss.includes(item.id + ',' + item.url) }"
|
||||
@mouseenter="onMouseOver(item, index)"
|
||||
@mouseleave="onMouseOut(item, index)"
|
||||
>
|
||||
<el-checkbox
|
||||
:value="item.id + ',' + item.url"
|
||||
class="card-checkbox"
|
||||
@click.stop
|
||||
/>
|
||||
<img :src="item.url" alt="" />
|
||||
<div v-if="item.isShowPreview" class="preview">
|
||||
<div @click.prevent="download(item)">
|
||||
<el-tooltip content="下载" placement="top">
|
||||
<el-icon :size="18"><Download /></el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<div @click.prevent="remove(item)">
|
||||
<el-tooltip content="删除" placement="top">
|
||||
<el-icon :size="18"><Delete /></el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<div @click.prevent="showPic(item)">
|
||||
<el-tooltip content="预览" placement="top">
|
||||
<el-icon :size="22"><View /></el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</el-checkbox>
|
||||
<div>
|
||||
<el-tooltip :content="item.name" placement="bottom">
|
||||
<div class="text">{{ item.name }}</div>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<el-tooltip :content="item.name" placement="bottom">
|
||||
<div class="text">{{ item.name }}</div>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</el-checkbox-group>
|
||||
@@ -210,6 +227,10 @@
|
||||
@current-change="pageChange"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="isComponent && selectImage" class="oss-select-footer">
|
||||
<el-button @click="handleSelectCancel">取消</el-button>
|
||||
<el-button type="primary" @click="handleSelectConfirm">确定</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@@ -488,6 +509,10 @@ export default {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
maxSelect: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -954,8 +979,8 @@ export default {
|
||||
if (val) this.selectImage = val
|
||||
},
|
||||
selectedOss(val) {
|
||||
if (val && val.length) {
|
||||
this.$emit("callback", {url: val[val.length - 1].split(',')[1]});
|
||||
if (val && val.length && !(this.isComponent && this.selectImage)) {
|
||||
this.$emit("callback", { url: val[val.length - 1].split(",")[1] });
|
||||
}
|
||||
},
|
||||
// 初始化监听 是否清空所选图片
|
||||
@@ -1062,6 +1087,11 @@ export default {
|
||||
},
|
||||
// 复选框值改变时触发
|
||||
selectOssChange(e) {
|
||||
if (this.maxSelect === 1 && e.length > 1) {
|
||||
const last = e[e.length - 1];
|
||||
this.selectedOss = [last];
|
||||
e = [last];
|
||||
}
|
||||
if (e) {
|
||||
this.selectList = e.map(item => {
|
||||
return {id: item.split(',')[0]}
|
||||
@@ -1291,6 +1321,18 @@ export default {
|
||||
selectedParams(val) {
|
||||
this.$emit("callback", val);
|
||||
},
|
||||
handleSelectConfirm() {
|
||||
if (!this.selectedOss.length) {
|
||||
this.$Message.warning("请选择图片");
|
||||
return;
|
||||
}
|
||||
const last = this.selectedOss[this.selectedOss.length - 1];
|
||||
this.$emit("callback", { url: last.split(",")[1] });
|
||||
},
|
||||
handleSelectCancel() {
|
||||
this.selectedOss = [];
|
||||
this.$emit("callback", { url: "" });
|
||||
},
|
||||
// 初始化数据
|
||||
init() {
|
||||
this.accessToken = {
|
||||
|
||||
@@ -74,9 +74,10 @@
|
||||
v-model="permModalVisible"
|
||||
:title="modalTitle"
|
||||
width="500px"
|
||||
align-center
|
||||
append-to-body
|
||||
:close-on-click-modal="false"
|
||||
class="permModal"
|
||||
top="30px"
|
||||
class="permModal role-perm-dialog"
|
||||
>
|
||||
<div v-loading="treeLoading" style="position: relative; max-height: 560px; overflow: auto">
|
||||
<el-tree
|
||||
@@ -115,7 +116,14 @@
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog v-model="selectIsSuperModel" title="选择菜单权限" width="800px">
|
||||
<el-dialog
|
||||
v-model="selectIsSuperModel"
|
||||
title="选择菜单权限"
|
||||
width="800px"
|
||||
align-center
|
||||
append-to-body
|
||||
class="role-perm-dialog"
|
||||
>
|
||||
<div class="btns">
|
||||
<el-button type="primary" class="btn-item" @click="setRole()">一键选中·数据权限</el-button>
|
||||
<el-button class="btn-item" @click="setRole('onlyView')">一键选中·查看权限</el-button>
|
||||
@@ -295,23 +303,30 @@ export default {
|
||||
addRole() {
|
||||
this.modalType = 0;
|
||||
this.modalTitle = "添加角色";
|
||||
this.$refs.roleForm?.resetFields();
|
||||
delete this.roleForm.id;
|
||||
this.roleForm = {
|
||||
name: "",
|
||||
description: "",
|
||||
};
|
||||
this.roleModalVisible = true;
|
||||
this.$nextTick(() => {
|
||||
this.$refs.roleForm?.resetFields();
|
||||
this.$refs.roleForm?.clearValidate();
|
||||
});
|
||||
},
|
||||
edit(v) {
|
||||
this.modalType = 1;
|
||||
this.modalTitle = "编辑角色";
|
||||
this.$refs.roleForm?.resetFields();
|
||||
for (let attr in v) {
|
||||
if (v[attr] == null) {
|
||||
v[attr] = "";
|
||||
}
|
||||
}
|
||||
let str = JSON.stringify(v);
|
||||
let roleInfo = JSON.parse(str);
|
||||
const roleInfo = JSON.parse(JSON.stringify(v));
|
||||
this.roleForm = roleInfo;
|
||||
this.roleModalVisible = true;
|
||||
this.$nextTick(() => {
|
||||
this.$refs.roleForm?.clearValidate();
|
||||
});
|
||||
},
|
||||
remove(v) {
|
||||
this.$Modal.confirm({
|
||||
@@ -553,3 +568,10 @@ export default {
|
||||
margin-right: 20px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
.role-perm-dialog .el-dialog__body {
|
||||
max-height: calc(100vh - 220px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -7,19 +7,19 @@
|
||||
<div class="form-list">
|
||||
<el-form
|
||||
ref="formValidate"
|
||||
label-width="120px"
|
||||
label-width="140px"
|
||||
label-position="right"
|
||||
:model="formValidate"
|
||||
:rules="ruleValidate"
|
||||
>
|
||||
<el-form-item label="买家PC端域名" prop="pc">
|
||||
<el-input v-model="formValidate.pc" class="w200" />
|
||||
<el-input v-model="formValidate.pc" />
|
||||
</el-form-item>
|
||||
<el-form-item label="买家WAP端域名" prop="wap">
|
||||
<el-input v-model="formValidate.wap" class="w200" />
|
||||
<el-input v-model="formValidate.wap" />
|
||||
</el-form-item>
|
||||
<el-form-item label="登录回调域名" prop="callbackUrl">
|
||||
<el-input maxlength="300" v-model="formValidate.callbackUrl" class="w200" />
|
||||
<el-input maxlength="300" v-model="formValidate.callbackUrl" />
|
||||
</el-form-item>
|
||||
<el-form-item label="操作">
|
||||
<el-button @click="setupSetting">保存设置</el-button>
|
||||
@@ -52,10 +52,11 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
submit(name) {
|
||||
const that = this;
|
||||
if (handleSubmit(that, name)) {
|
||||
this.setupSetting();
|
||||
}
|
||||
handleSubmit(this, name)
|
||||
.then(() => {
|
||||
this.setupSetting();
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
setupSetting() {
|
||||
setSetting(this.type, this.formValidate).then((res) => {
|
||||
@@ -67,8 +68,8 @@ export default {
|
||||
});
|
||||
},
|
||||
init() {
|
||||
this.res = JSON.parse(this.res);
|
||||
this.formValidate = { ...this.res };
|
||||
const setting = JSON.parse(this.res || "{}");
|
||||
this.formValidate = { ...setting };
|
||||
Object.keys(this.formValidate).forEach((item) => {
|
||||
if (item.indexOf("pId") < 0) {
|
||||
this.ruleValidate[item] = [
|
||||
@@ -112,12 +113,21 @@ export default {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
.row {
|
||||
width: 600px;
|
||||
width: 100%;
|
||||
max-width: 720px;
|
||||
margin-right: 10px;
|
||||
display: flex;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
:deep(.el-input) {
|
||||
width: 480px !important;
|
||||
}
|
||||
|
||||
.el-input {
|
||||
width: 480px;
|
||||
}
|
||||
|
||||
.label-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -135,4 +145,8 @@ export default {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
:deep(.el-form-item__label) {
|
||||
white-space: nowrap;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -44,6 +44,12 @@
|
||||
<script>
|
||||
import { setSetting } from "@/api/index";
|
||||
import { handleSubmit } from "../setting/validate";
|
||||
|
||||
const DEFAULT_QQ_CONNECT_ITEMS = [
|
||||
{ clientType: "PC", appId: "", appKey: "" },
|
||||
{ clientType: "H5", appId: "", appKey: "" },
|
||||
];
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
@@ -63,10 +69,11 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
submit(name) {
|
||||
const that = this;
|
||||
if (handleSubmit(that, name)) {
|
||||
this.setupSetting();
|
||||
}
|
||||
handleSubmit(this, name)
|
||||
.then(() => {
|
||||
this.setupSetting();
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
setupSetting() {
|
||||
setSetting(this.type, {
|
||||
@@ -81,17 +88,15 @@ export default {
|
||||
}
|
||||
});
|
||||
},
|
||||
async init() {
|
||||
this.formValidate = JSON.parse(this.res).qqConnectSettingItemList;
|
||||
Object.keys(this.formValidate).forEach((item) => {
|
||||
this.ruleValidate[item] = [
|
||||
{
|
||||
required: true,
|
||||
message: "请填写必填项",
|
||||
trigger: "blur",
|
||||
},
|
||||
];
|
||||
});
|
||||
init() {
|
||||
const setting = JSON.parse(this.res || "{}");
|
||||
const items = setting.qqConnectSettingItemList;
|
||||
this.formValidate =
|
||||
Array.isArray(items) && items.length ? items : DEFAULT_QQ_CONNECT_ITEMS;
|
||||
this.ruleValidate = {
|
||||
appId: [{ required: true, message: "请填写必填项", trigger: "blur" }],
|
||||
appKey: [{ required: true, message: "请填写必填项", trigger: "blur" }],
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -45,6 +45,13 @@
|
||||
import { setSetting } from "@/api/index";
|
||||
import { handleSubmit } from "../setting/validate";
|
||||
|
||||
const DEFAULT_WECHAT_CONNECT_ITEMS = [
|
||||
{ clientType: "PC", appId: "", appSecret: "" },
|
||||
{ clientType: "H5", appId: "", appSecret: "" },
|
||||
{ clientType: "APP", appId: "", appSecret: "" },
|
||||
{ clientType: "WECHAT_MP", appId: "", appSecret: "" },
|
||||
];
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
@@ -64,10 +71,11 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
submit(name) {
|
||||
const that = this;
|
||||
if (handleSubmit(that, name)) {
|
||||
this.setupSetting();
|
||||
}
|
||||
handleSubmit(this, name)
|
||||
.then(() => {
|
||||
this.setupSetting();
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
setupSetting() {
|
||||
setSetting(this.type, {
|
||||
@@ -82,17 +90,15 @@ export default {
|
||||
}
|
||||
});
|
||||
},
|
||||
async init() {
|
||||
this.formValidate = JSON.parse(this.res).wechatConnectSettingItems;
|
||||
Object.keys(this.formValidate).forEach((item) => {
|
||||
this.ruleValidate[item] = [
|
||||
{
|
||||
required: true,
|
||||
message: "请填写必填项",
|
||||
trigger: "blur",
|
||||
},
|
||||
];
|
||||
});
|
||||
init() {
|
||||
const setting = JSON.parse(this.res || "{}");
|
||||
const items = setting.wechatConnectSettingItems;
|
||||
this.formValidate =
|
||||
Array.isArray(items) && items.length ? items : DEFAULT_WECHAT_CONNECT_ITEMS;
|
||||
this.ruleValidate = {
|
||||
appId: [{ required: true, message: "请填写必填项", trigger: "blur" }],
|
||||
appSecret: [{ required: true, message: "请填写必填项", trigger: "blur" }],
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -49,10 +49,11 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
submit(name) {
|
||||
let that = this;
|
||||
if (handleSubmit(that, name)) {
|
||||
this.setupSetting();
|
||||
}
|
||||
handleSubmit(this, name)
|
||||
.then(() => {
|
||||
this.setupSetting();
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
// 保存设置
|
||||
setupSetting() {
|
||||
@@ -66,9 +67,8 @@ export default {
|
||||
},
|
||||
// 实例化数据
|
||||
init() {
|
||||
this.res = JSON.parse(this.res);
|
||||
|
||||
this.formValidate = { ...this.res };
|
||||
const setting = JSON.parse(this.res || "{}");
|
||||
this.formValidate = { ...setting };
|
||||
Object.keys(this.formValidate).forEach((item) => {
|
||||
this.ruleValidate[item] = [
|
||||
{
|
||||
|
||||
@@ -41,6 +41,14 @@
|
||||
import { setSetting } from "@/api/index";
|
||||
import { handleSubmit } from "../setting/validate";
|
||||
import { getPaymentSupportForm } from "@/api/setting";
|
||||
|
||||
const DEFAULT_PAYMENT_SUPPORT_ITEMS = [
|
||||
{ client: "PC", supports: [] },
|
||||
{ client: "H5", supports: [] },
|
||||
{ client: "APP", supports: [] },
|
||||
{ client: "WECHAT_MP", supports: [] },
|
||||
];
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
@@ -51,7 +59,7 @@ export default {
|
||||
WECHAT_MP: "小程序端",
|
||||
PC: "PC端",
|
||||
},
|
||||
formValidate: {},
|
||||
formValidate: [],
|
||||
payWay: {
|
||||
ALIPAY: "支付宝支付",
|
||||
WECHAT: "微信支付",
|
||||
@@ -67,10 +75,11 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
submit(name) {
|
||||
const that = this;
|
||||
if (handleSubmit(that, name)) {
|
||||
this.setupSetting();
|
||||
}
|
||||
handleSubmit(this, name)
|
||||
.then(() => {
|
||||
this.setupSetting();
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
handleChangePayType(val) {
|
||||
this.$Modal.confirm({
|
||||
@@ -97,13 +106,17 @@ export default {
|
||||
}
|
||||
});
|
||||
},
|
||||
async init() {
|
||||
this.formValidate = JSON.parse(this.res).paymentSupportItems;
|
||||
init() {
|
||||
const setting = JSON.parse(this.res || "{}");
|
||||
const items = setting.paymentSupportItems;
|
||||
this.formValidate =
|
||||
Array.isArray(items) && items.length ? items : DEFAULT_PAYMENT_SUPPORT_ITEMS;
|
||||
this.checkSupport = JSON.parse(JSON.stringify(this.formValidate));
|
||||
console.log(this.formValidate);
|
||||
|
||||
await getPaymentSupportForm().then((res) => {
|
||||
this.supportForm = res.result;
|
||||
getPaymentSupportForm().then((res) => {
|
||||
if (res.success && res.result) {
|
||||
this.supportForm = res.result;
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
@@ -74,10 +74,11 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
submit(name) {
|
||||
let that = this;
|
||||
if (handleSubmit(that, name)) {
|
||||
this.setupSetting();
|
||||
}
|
||||
handleSubmit(this, name)
|
||||
.then(() => {
|
||||
this.setupSetting();
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
// 保存设置
|
||||
setupSetting() {
|
||||
@@ -91,9 +92,8 @@ export default {
|
||||
},
|
||||
// 实例化数据
|
||||
init() {
|
||||
this.res = JSON.parse(this.res);
|
||||
|
||||
this.formValidate = { ...this.res };
|
||||
const setting = JSON.parse(this.res || "{}");
|
||||
this.formValidate = { ...setting };
|
||||
Object.keys(this.formValidate).forEach((item) => {
|
||||
if (item.indexOf("pId") < 0) {
|
||||
this.ruleValidate[item] = [
|
||||
|
||||
@@ -96,7 +96,6 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
handleSubmit,
|
||||
picModelFlag: false,
|
||||
formValidate: {
|
||||
buyerSideLogo: "",
|
||||
@@ -126,10 +125,11 @@ export default {
|
||||
});
|
||||
},
|
||||
submit(name) {
|
||||
const that = this;
|
||||
if (handleSubmit(that, name)) {
|
||||
this.setupSetting();
|
||||
}
|
||||
handleSubmit(this, name)
|
||||
.then(() => {
|
||||
this.setupSetting();
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
callbackSelected(val) {
|
||||
this.picModelFlag = false;
|
||||
|
||||
@@ -50,16 +50,18 @@
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="label-btns">
|
||||
<el-button type="primary" @click="submit('formValidate')">保存</el-button>
|
||||
<div class="es-buttons">
|
||||
<div class="label-btns goods-setting-btns">
|
||||
<div class="goods-setting-action-row">
|
||||
<el-button type="success" @click="createIndex()">重新生成所有商品索引</el-button>
|
||||
<el-button type="info" @click="deleteDownGoods()">删除ES中下架的商品</el-button>
|
||||
<el-button type="warning" @click="generateCache()">生成所有商品的缓存</el-button>
|
||||
<el-button type="danger" @click="deleteNotExistIndex()">删除不存在的索引</el-button>
|
||||
<div class="progress-item" v-if="showProgress">
|
||||
<el-progress :percentage="progressVal" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-item" v-if="showProgress">
|
||||
<el-progress :percentage="progressVal" />
|
||||
<div class="goods-setting-save-row">
|
||||
<el-button type="primary" @click="submit('formValidate')">保存</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-form>
|
||||
@@ -207,7 +209,27 @@ export default {
|
||||
.label-item {
|
||||
display: flex;
|
||||
}
|
||||
.goods-setting-btns {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 10px;
|
||||
margin-left: 150px;
|
||||
}
|
||||
.goods-setting-action-row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
.goods-setting-action-row .progress-item {
|
||||
flex: 0 0 240px;
|
||||
min-width: 200px;
|
||||
}
|
||||
.goods-setting-action-row .progress-item :deep(.el-progress) {
|
||||
width: 100%;
|
||||
}
|
||||
:deep(.el-input){
|
||||
width: 100px !important;
|
||||
width: 180px !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -33,10 +33,11 @@ export default {
|
||||
methods: {
|
||||
// 保存
|
||||
submit(name) {
|
||||
let that = this;
|
||||
if (handleSubmit(that, name)) {
|
||||
this.setupSetting()
|
||||
}
|
||||
handleSubmit(this, name)
|
||||
.then(() => {
|
||||
this.setupSetting();
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
// 保存设置
|
||||
setupSetting() {
|
||||
|
||||
@@ -71,10 +71,11 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
submit(name) {
|
||||
const that = this;
|
||||
if (handleSubmit(that, name)) {
|
||||
this.setupSetting();
|
||||
}
|
||||
handleSubmit(this, name)
|
||||
.then(() => {
|
||||
this.setupSetting();
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
setupSetting() {
|
||||
setSetting(this.type, this.formValidate).then((res) => {
|
||||
|
||||
@@ -63,10 +63,11 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
submit(name) {
|
||||
const that = this;
|
||||
if (handleSubmit(that, name)) {
|
||||
this.setupSetting();
|
||||
}
|
||||
handleSubmit(this, name)
|
||||
.then(() => {
|
||||
this.setupSetting();
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
setupSetting() {
|
||||
setSetting(this.type, this.formValidate).then((res) => {
|
||||
@@ -115,12 +116,12 @@ export default {
|
||||
}
|
||||
|
||||
.el-input {
|
||||
width: 100px;
|
||||
width: 180px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
:deep(.el-input){
|
||||
width: 100px !important;
|
||||
width: 180px !important;
|
||||
}
|
||||
|
||||
.desc {
|
||||
|
||||
@@ -120,10 +120,11 @@ export default {
|
||||
methods: {
|
||||
// 保存
|
||||
submit(name) {
|
||||
let that = this;
|
||||
if (handleSubmit(that, name)) {
|
||||
this.setupSetting()
|
||||
}
|
||||
handleSubmit(this, name)
|
||||
.then(() => {
|
||||
this.setupSetting();
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
// 保存设置
|
||||
setupSetting() {
|
||||
|
||||
@@ -69,10 +69,11 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
submit(name) {
|
||||
const that = this;
|
||||
if (handleSubmit(that, name)) {
|
||||
this.setupSetting();
|
||||
}
|
||||
handleSubmit(this, name)
|
||||
.then(() => {
|
||||
this.setupSetting();
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
setupSetting() {
|
||||
setSetting(this.type, this.formValidate).then((res) => {
|
||||
@@ -140,27 +141,27 @@ export default {
|
||||
display: flex;
|
||||
|
||||
> .el-input-number {
|
||||
width: 100px;
|
||||
width: 120px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
> .el-input-number:nth-last-of-type(1) {
|
||||
width: 150px;
|
||||
width: 180px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
> .el-input {
|
||||
width: 100px;
|
||||
width: 180px;
|
||||
margin: 0 10px;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-input){
|
||||
width: 70px !important;
|
||||
width: 180px !important;
|
||||
}
|
||||
|
||||
.el-input {
|
||||
width: 70px;
|
||||
width: 180px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
|
||||
@@ -115,10 +115,11 @@ export default {
|
||||
methods: {
|
||||
// 保存
|
||||
submit(name) {
|
||||
let that = this;
|
||||
if (handleSubmit(that, name)) {
|
||||
this.setupSetting()
|
||||
}
|
||||
handleSubmit(this, name)
|
||||
.then(() => {
|
||||
this.setupSetting();
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
// 保存设置
|
||||
setupSetting() {
|
||||
|
||||
@@ -44,10 +44,11 @@ export default {
|
||||
props: ["res", "type"],
|
||||
methods: {
|
||||
submit(name) {
|
||||
const that = this;
|
||||
if (handleSubmit(that, name)) {
|
||||
this.setupSetting();
|
||||
}
|
||||
handleSubmit(this, name)
|
||||
.then(() => {
|
||||
this.setupSetting();
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
setupSetting() {
|
||||
setSetting(this.type, this.formValidate).then((res) => {
|
||||
|
||||
@@ -1,23 +1,28 @@
|
||||
//表单中必填
|
||||
export function validateRequired(rule, value, callback) {
|
||||
if (value != void 0 || value != null) {
|
||||
if (value !== undefined && value !== null && value !== "") {
|
||||
callback();
|
||||
} else {
|
||||
return callback(new Error("必填项不能为空"));
|
||||
callback(new Error("必填项不能为空"));
|
||||
}
|
||||
}
|
||||
|
||||
// 验证必填项
|
||||
// 验证必填项(Element Plus 表单校验为异步,返回 Promise)
|
||||
export function handleSubmit(that, name) {
|
||||
let flag = false;
|
||||
that.$refs[name].validate(valid => {
|
||||
if (valid) {
|
||||
flag = true;
|
||||
return flag;
|
||||
} else {
|
||||
that.$Message.error("请正确填写内容!");
|
||||
return flag;
|
||||
return new Promise((resolve, reject) => {
|
||||
const form = that.$refs[name];
|
||||
if (!form) {
|
||||
that.$Message.error("表单未就绪,请稍后重试");
|
||||
reject(new Error("form ref missing"));
|
||||
return;
|
||||
}
|
||||
form.validate((valid) => {
|
||||
if (valid) {
|
||||
resolve(true);
|
||||
} else {
|
||||
that.$Message.error("请正确填写内容!");
|
||||
reject(new Error("validation failed"));
|
||||
}
|
||||
});
|
||||
});
|
||||
return flag
|
||||
}
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
:name="tabItem.type"
|
||||
>
|
||||
<component
|
||||
v-if="settingData"
|
||||
v-if="settingData && selected === tabItem.type"
|
||||
:is="templateSetting[tabItem.type]"
|
||||
:res="settingData"
|
||||
:type="selected"
|
||||
:type="tabItem.type"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
@@ -130,6 +130,8 @@ export default {
|
||||
getSetting(name).then((res) => {
|
||||
if (res.result) {
|
||||
this.settingData = JSON.stringify(res.result);
|
||||
} else {
|
||||
this.settingData = "{}";
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
@@ -94,9 +94,11 @@
|
||||
v-model="userModalVisible"
|
||||
:title="modalTitle"
|
||||
width="500px"
|
||||
align-center
|
||||
append-to-body
|
||||
:close-on-click-modal="false"
|
||||
top="30px"
|
||||
destroy-on-close
|
||||
class="user-manage-dialog"
|
||||
>
|
||||
<el-form ref="form" :model="form" label-width="70px" :rules="formValidate">
|
||||
<el-form-item label="用户名" prop="username">
|
||||
@@ -106,7 +108,7 @@
|
||||
<el-input v-model="form.nickName" autocomplete="off" />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="modalType == 0" label="密码" prop="password" :error="errorPass">
|
||||
<el-input v-model="form.password" type="password" show-password autocomplete="off" />
|
||||
<el-input v-model="form.password" type="password" show-password autocomplete="new-password" />
|
||||
</el-form-item>
|
||||
<el-form-item label="邮箱" prop="email">
|
||||
<el-input v-model="form.email" />
|
||||
@@ -326,7 +328,6 @@ export default {
|
||||
add() {
|
||||
this.modalType = 0;
|
||||
this.modalTitle = "添加用户";
|
||||
this.$refs.form?.resetFields();
|
||||
this.form = {
|
||||
username: "",
|
||||
mobile: "",
|
||||
@@ -336,20 +337,23 @@ export default {
|
||||
departmentId: 0,
|
||||
departmentTitle: "",
|
||||
};
|
||||
this.$refs.depTree.setData("", "");
|
||||
this.userModalVisible = true;
|
||||
this.$nextTick(() => {
|
||||
this.$refs.form?.resetFields();
|
||||
this.$refs.depTree?.setData("", "");
|
||||
});
|
||||
},
|
||||
edit(v) {
|
||||
this.form = JSON.parse(JSON.stringify(v));
|
||||
this.modalType = 1;
|
||||
this.modalTitle = "编辑用户";
|
||||
this.$refs.form?.resetFields();
|
||||
for (let attr in this.form) {
|
||||
if (this.form[attr] == null) {
|
||||
this.form[attr] = "";
|
||||
}
|
||||
}
|
||||
this.$refs.depTree.setData(this.form.departmentId, this.form.departmentTitle);
|
||||
const departmentId = this.form.departmentId;
|
||||
const departmentTitle = this.form.departmentTitle;
|
||||
let selectRolesId = [];
|
||||
if (this.form.roles) {
|
||||
this.form.roles.forEach(function (e) {
|
||||
@@ -358,6 +362,10 @@ export default {
|
||||
}
|
||||
this.form.roles = selectRolesId;
|
||||
this.userModalVisible = true;
|
||||
this.$nextTick(() => {
|
||||
this.$refs.form?.resetFields();
|
||||
this.$refs.depTree?.setData(departmentId, departmentTitle);
|
||||
});
|
||||
},
|
||||
enable(v) {
|
||||
let params = { status: true };
|
||||
@@ -462,3 +470,36 @@ export default {
|
||||
color: #dcdee2;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
.user-manage-dialog {
|
||||
.el-dialog__body {
|
||||
max-height: calc(100vh - 220px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.el-input__wrapper {
|
||||
background-color: #fff !important;
|
||||
box-shadow: 0 0 0 1px var(--el-border-color) inset !important;
|
||||
|
||||
&.is-focus {
|
||||
box-shadow: 0 0 0 1px var(--el-border-color) inset !important;
|
||||
}
|
||||
}
|
||||
|
||||
.el-input__inner {
|
||||
background-color: transparent !important;
|
||||
|
||||
&:-webkit-autofill,
|
||||
&:-webkit-autofill:hover,
|
||||
&:-webkit-autofill:focus,
|
||||
&:-webkit-autofill:active {
|
||||
-webkit-box-shadow: 0 0 0 1000px #fff inset !important;
|
||||
box-shadow: 0 0 0 1000px #fff inset !important;
|
||||
-webkit-text-fill-color: #606266 !important;
|
||||
caret-color: #606266;
|
||||
transition: background-color 99999s ease-out;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user